Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

consensus/bor: eliminate contract calls for current span #1444

Closed
wants to merge 9 commits into from
58 changes: 34 additions & 24 deletions consensus/bor/bor.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,11 @@ const (
inmemorySignatures = 4096 // Number of recent block signatures to keep in memory
)

const (
spanLength = 6400 // Number of blocks in a span
zerothSpanEnd = 255 // End block of 0th span
)

// Bor protocol constants.
var (
defaultSprintLength = map[string]uint64{
Expand Down Expand Up @@ -1094,39 +1099,44 @@ func (c *Bor) Close() error {
return nil
}

func (c *Bor) checkAndCommitSpan(
state *state.StateDB,
header *types.Header,
chain core.ChainContext,
) error {
var ctx = context.Background()
headerNumber := header.Number.Uint64()
// SpanIdAt returns the corresponding span id for the given block number.
func SpanIdAt(blockNum uint64) uint64 {
if blockNum > zerothSpanEnd {
return 1 + (blockNum-zerothSpanEnd-1)/spanLength
}
return 0
}

span, err := c.spanner.GetCurrentSpan(ctx, header.ParentHash)
if err != nil {
return err
// SpanEndBlockNum returns the number of the last block in the given span.
func SpanEndBlockNum(spanId uint64) uint64 {
if spanId > 0 {
return spanId*spanLength + zerothSpanEnd
}
return zerothSpanEnd
}

func (c *Bor) checkAndCommitSpan(state *state.StateDB, header *types.Header, chain core.ChainContext) error {
// Find the current span at parent block
headerNumber := header.Number.Uint64()
spanId := SpanIdAt(headerNumber)
sprintLength := c.config.CalculateSprint(headerNumber)

if c.needToCommitSpan(span, headerNumber) {
return c.FetchAndCommitSpan(ctx, span.ID+1, state, header, chain)
// Fetch the next span if required
if needToCommitSpan(spanId, headerNumber, sprintLength) {
return c.FetchAndCommitSpan(context.Background(), spanId+1, state, header, chain)
}

return nil
}

func (c *Bor) needToCommitSpan(currentSpan *span.Span, headerNumber uint64) bool {
// if span is nil
if currentSpan == nil {
return false
}

// check span is not set initially
if currentSpan.EndBlock == 0 {
func needToCommitSpan(spanId, headerNumber, sprintLength uint64) bool {
// Find the end block of the given span
spanEndBlock := SpanEndBlockNum(spanId)
if spanId == 0 && headerNumber == sprintLength {
// when in span 0 we fetch the next span (span 1) at the beginning of sprint 2 (block 16)
return true
}

// if current block is first block of last sprint in current span
if currentSpan.EndBlock > c.config.CalculateSprint(headerNumber) && currentSpan.EndBlock-c.config.CalculateSprint(headerNumber)+1 == headerNumber {
} else if spanEndBlock-sprintLength+1 == headerNumber {
// for subsequent spans, we always fetch the next span at the beginning of the last sprint of current span
return true
}

Expand Down
34 changes: 34 additions & 0 deletions consensus/bor/bor_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package bor

import (
"math/big"
"strconv"
"testing"

"github.com/holiman/uint256"
Expand Down Expand Up @@ -162,3 +163,36 @@ func TestEncodeSigHeaderJaipur(t *testing.T) {
hash = SealHash(h, &params.BorConfig{JaipurBlock: big.NewInt(10)})
require.Equal(t, hash, hashWithoutBaseFee)
}

func TestNeedToCommitSpan(t *testing.T) {
type test struct {
spanId uint64
headerNumber uint64
want bool
}

tests := []test{
{spanId: 0, headerNumber: 1, want: false},
{spanId: 0, headerNumber: 15, want: false},
{spanId: 0, headerNumber: 16, want: true}, // Second sprint start
{spanId: 0, headerNumber: 17, want: false},
{spanId: 1, headerNumber: 256, want: false},
{spanId: 1, headerNumber: 6639, want: false},
{spanId: 1, headerNumber: 6640, want: true}, // First block of last sprint of span 1
{spanId: 1, headerNumber: 6641, want: false},
{spanId: 1, headerNumber: 6655, want: false},
{spanId: 100, headerNumber: 633856, want: false},
{spanId: 100, headerNumber: 640239, want: false},
{spanId: 100, headerNumber: 640240, want: true}, // First block of last sprint of span 100
{spanId: 100, headerNumber: 640241, want: false},
}

for _, test := range tests {
test := test
name := "id=" + strconv.FormatUint(test.spanId, 10) + ",number=" + strconv.FormatUint(test.headerNumber, 10)
t.Run(name, func(t *testing.T) {
t.Parallel()
require.Equal(t, test.want, needToCommitSpan(test.spanId, test.headerNumber, 16))
})
}
}
3 changes: 3 additions & 0 deletions consensus/bor/snapshot.go
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,9 @@ func (s *Snapshot) apply(headers []*types.Header, c *Bor) (*Snapshot, error) {
// add recents
snap.Recents[number] = signer

// TODO
// Can't we do this step for the last header only?

// change validator set and change proposer
if number > 0 && (number+1)%s.chainConfig.Bor.CalculateSprint(number) == 0 {
if err := validateHeaderExtraField(header.Extra); err != nil {
Expand Down
Loading