mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-19 10:22:23 +00:00
move timestamp sanitization
This commit is contained in:
parent
5f0fafd8e6
commit
73ff7e51f6
3 changed files with 86 additions and 46 deletions
|
|
@ -1095,7 +1095,7 @@ func (o *BlockOverrides) Apply(blockCtx *vm.BlockContext) {
|
|||
|
||||
// MakeHeader returns a new header object with the overridden
|
||||
// fields.
|
||||
// Note: MakeHeader ignores blobGasPrice if set. That's because
|
||||
// Note: MakeHeader ignores BlobBaseFee if set. That's because
|
||||
// header has no such field.
|
||||
func (o *BlockOverrides) MakeHeader(header *types.Header) *types.Header {
|
||||
if o == nil {
|
||||
|
|
|
|||
|
|
@ -42,6 +42,9 @@ const (
|
|||
// maxSimulateBlocks is the maximum number of blocks that can be simulated
|
||||
// in a single request.
|
||||
maxSimulateBlocks = 256
|
||||
|
||||
// timestampIncrement is the default increment between block timestamps.
|
||||
timestampIncrement = 1
|
||||
)
|
||||
|
||||
// simBlock is a batch of calls to be simulated sequentially.
|
||||
|
|
@ -106,7 +109,7 @@ func (sim *simulator) execute(ctx context.Context, blocks []simBlock) ([]map[str
|
|||
defer cancel()
|
||||
|
||||
var err error
|
||||
blocks, err = sim.sanitizeBlockOrder(blocks)
|
||||
blocks, err = sim.sanitizeChain(blocks)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
@ -287,14 +290,16 @@ func (sim *simulator) activePrecompiles(ctx context.Context, base *types.Header)
|
|||
return vm.ActivePrecompiledContracts(rules).Copy()
|
||||
}
|
||||
|
||||
// sanitizeBlockOrder iterates the blocks checking that block numbers
|
||||
// are strictly increasing. When necessary it will generate empty blocks.
|
||||
// It modifies the block's override object.
|
||||
func (sim *simulator) sanitizeBlockOrder(blocks []simBlock) ([]simBlock, error) {
|
||||
// sanitizeChain checks the chain integrity. Specifically it checks that
|
||||
// block numbers and timestamp are strictly increasing, setting default values
|
||||
// when necessary. Gaps in block numbers are filled with empty blocks.
|
||||
// Note: It modifies the block's override object.
|
||||
func (sim *simulator) sanitizeChain(blocks []simBlock) ([]simBlock, error) {
|
||||
var (
|
||||
res = make([]simBlock, 0, len(blocks))
|
||||
base = sim.base
|
||||
prevNumber = base.Number
|
||||
res = make([]simBlock, 0, len(blocks))
|
||||
base = sim.base
|
||||
prevNumber = base.Number
|
||||
prevTimestamp = base.Time
|
||||
)
|
||||
for _, block := range blocks {
|
||||
if block.BlockOverrides == nil {
|
||||
|
|
@ -317,12 +322,25 @@ func (sim *simulator) sanitizeBlockOrder(blocks []simBlock) ([]simBlock, error)
|
|||
// Assign block number to the empty blocks.
|
||||
for i := uint64(0); i < gap.Uint64(); i++ {
|
||||
n := new(big.Int).Add(prevNumber, big.NewInt(int64(i+1)))
|
||||
b := simBlock{BlockOverrides: &BlockOverrides{Number: (*hexutil.Big)(n)}}
|
||||
t := prevTimestamp + timestampIncrement
|
||||
b := simBlock{BlockOverrides: &BlockOverrides{Number: (*hexutil.Big)(n), Time: (*hexutil.Uint64)(&t)}}
|
||||
prevTimestamp = t
|
||||
res = append(res, b)
|
||||
}
|
||||
}
|
||||
// Only append block after filling a potential gap.
|
||||
prevNumber = block.BlockOverrides.Number.ToInt()
|
||||
var t uint64
|
||||
if block.BlockOverrides.Time == nil {
|
||||
t = prevTimestamp + timestampIncrement
|
||||
block.BlockOverrides.Time = (*hexutil.Uint64)(&t)
|
||||
} else {
|
||||
t = uint64(*block.BlockOverrides.Time)
|
||||
if t <= prevTimestamp {
|
||||
return nil, &invalidBlockTimestampError{fmt.Sprintf("block timestamps must be in order: %d <= %d", t, prevTimestamp)}
|
||||
}
|
||||
}
|
||||
prevTimestamp = t
|
||||
res = append(res, block)
|
||||
}
|
||||
return res, nil
|
||||
|
|
@ -333,23 +351,15 @@ func (sim *simulator) sanitizeBlockOrder(blocks []simBlock) ([]simBlock, error)
|
|||
// It assumes blocks are in order and numbers have been validated.
|
||||
func (sim *simulator) makeHeaders(blocks []simBlock) ([]*types.Header, error) {
|
||||
var (
|
||||
res = make([]*types.Header, len(blocks))
|
||||
base = sim.base
|
||||
prevTimestamp = base.Time
|
||||
header = base
|
||||
res = make([]*types.Header, len(blocks))
|
||||
base = sim.base
|
||||
header = base
|
||||
)
|
||||
for bi, block := range blocks {
|
||||
if block.BlockOverrides == nil || block.BlockOverrides.Number == nil {
|
||||
return nil, errors.New("empty block number")
|
||||
}
|
||||
overrides := block.BlockOverrides
|
||||
if overrides.Time == nil {
|
||||
t := prevTimestamp + 1
|
||||
overrides.Time = (*hexutil.Uint64)(&t)
|
||||
} else if time := (*uint64)(overrides.Time); *time <= prevTimestamp {
|
||||
return nil, &invalidBlockTimestampError{fmt.Sprintf("block timestamps must be in order: %d <= %d", *time, prevTimestamp)}
|
||||
}
|
||||
prevTimestamp = uint64(*overrides.Time)
|
||||
|
||||
var withdrawalsHash *common.Hash
|
||||
if sim.chainConfig.IsShanghai(overrides.Number.ToInt(), (uint64)(*overrides.Time)) {
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
package ethapi
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math/big"
|
||||
"testing"
|
||||
|
||||
|
|
@ -10,35 +9,62 @@ import (
|
|||
)
|
||||
|
||||
func TestSimulateSanitizeBlockOrder(t *testing.T) {
|
||||
type result struct {
|
||||
number uint64
|
||||
timestamp uint64
|
||||
}
|
||||
for i, tc := range []struct {
|
||||
baseNumber int
|
||||
blocks []simBlock
|
||||
expectedLen int
|
||||
err string
|
||||
baseNumber int
|
||||
baseTimestamp uint64
|
||||
blocks []simBlock
|
||||
expected []result
|
||||
err string
|
||||
}{
|
||||
{
|
||||
baseNumber: 10,
|
||||
blocks: []simBlock{{}, {}, {}},
|
||||
expectedLen: 3,
|
||||
baseNumber: 10,
|
||||
baseTimestamp: 50,
|
||||
blocks: []simBlock{{}, {}, {}},
|
||||
expected: []result{{number: 11, timestamp: 51}, {number: 12, timestamp: 52}, {number: 13, timestamp: 53}},
|
||||
},
|
||||
{
|
||||
baseNumber: 10,
|
||||
blocks: []simBlock{{BlockOverrides: &BlockOverrides{Number: newInt(13)}}, {}},
|
||||
expectedLen: 4,
|
||||
baseNumber: 10,
|
||||
baseTimestamp: 50,
|
||||
blocks: []simBlock{{BlockOverrides: &BlockOverrides{Number: newInt(13), Time: newUint64(70)}}, {}},
|
||||
expected: []result{{number: 11, timestamp: 51}, {number: 12, timestamp: 52}, {number: 13, timestamp: 70}, {number: 14, timestamp: 71}},
|
||||
},
|
||||
{
|
||||
baseNumber: 10,
|
||||
blocks: []simBlock{{BlockOverrides: &BlockOverrides{Number: newInt(11)}}, {BlockOverrides: &BlockOverrides{Number: newInt(14)}}, {}},
|
||||
expectedLen: 5,
|
||||
baseNumber: 10,
|
||||
baseTimestamp: 50,
|
||||
blocks: []simBlock{{BlockOverrides: &BlockOverrides{Number: newInt(11)}}, {BlockOverrides: &BlockOverrides{Number: newInt(14)}}, {}},
|
||||
expected: []result{{number: 11, timestamp: 51}, {number: 12, timestamp: 52}, {number: 13, timestamp: 53}, {number: 14, timestamp: 54}, {number: 15, timestamp: 55}},
|
||||
},
|
||||
{
|
||||
baseNumber: 10,
|
||||
blocks: []simBlock{{BlockOverrides: &BlockOverrides{Number: newInt(13)}}, {BlockOverrides: &BlockOverrides{Number: newInt(12)}}},
|
||||
err: "block numbers must be in order: 12 <= 13",
|
||||
baseNumber: 10,
|
||||
baseTimestamp: 50,
|
||||
blocks: []simBlock{{BlockOverrides: &BlockOverrides{Number: newInt(13)}}, {BlockOverrides: &BlockOverrides{Number: newInt(12)}}},
|
||||
err: "block numbers must be in order: 12 <= 13",
|
||||
},
|
||||
{
|
||||
baseNumber: 10,
|
||||
baseTimestamp: 50,
|
||||
blocks: []simBlock{{BlockOverrides: &BlockOverrides{Number: newInt(13), Time: newUint64(52)}}},
|
||||
err: "block timestamps must be in order: 52 <= 52",
|
||||
},
|
||||
{
|
||||
baseNumber: 10,
|
||||
baseTimestamp: 50,
|
||||
blocks: []simBlock{{BlockOverrides: &BlockOverrides{Number: newInt(11), Time: newUint64(60)}}, {BlockOverrides: &BlockOverrides{Number: newInt(12), Time: newUint64(55)}}},
|
||||
err: "block timestamps must be in order: 55 <= 60",
|
||||
},
|
||||
{
|
||||
baseNumber: 10,
|
||||
baseTimestamp: 50,
|
||||
blocks: []simBlock{{BlockOverrides: &BlockOverrides{Number: newInt(11), Time: newUint64(60)}}, {BlockOverrides: &BlockOverrides{Number: newInt(13), Time: newUint64(61)}}},
|
||||
err: "block timestamps must be in order: 61 <= 61",
|
||||
},
|
||||
} {
|
||||
sim := &simulator{base: &types.Header{Number: big.NewInt(int64(tc.baseNumber))}}
|
||||
res, err := sim.sanitizeBlockOrder(tc.blocks)
|
||||
sim := &simulator{base: &types.Header{Number: big.NewInt(int64(tc.baseNumber)), Time: tc.baseTimestamp}}
|
||||
res, err := sim.sanitizeChain(tc.blocks)
|
||||
if err != nil {
|
||||
if err.Error() == tc.err {
|
||||
continue
|
||||
|
|
@ -49,9 +75,8 @@ func TestSimulateSanitizeBlockOrder(t *testing.T) {
|
|||
if err == nil && tc.err != "" {
|
||||
t.Fatalf("testcase %d: expected err", i)
|
||||
}
|
||||
if len(res) != tc.expectedLen {
|
||||
fmt.Printf("res: %v\n", res)
|
||||
t.Errorf("testcase %d: mismatch number of blocks. Want %d, have %d", i, tc.expectedLen, len(res))
|
||||
if len(res) != len(tc.expected) {
|
||||
t.Errorf("testcase %d: mismatch number of blocks. Want %d, have %d", i, len(tc.expected), len(res))
|
||||
}
|
||||
for bi, b := range res {
|
||||
if b.BlockOverrides == nil {
|
||||
|
|
@ -60,10 +85,15 @@ func TestSimulateSanitizeBlockOrder(t *testing.T) {
|
|||
if b.BlockOverrides.Number == nil {
|
||||
t.Fatalf("testcase %d: block number not set", i)
|
||||
}
|
||||
want := tc.baseNumber + bi + 1
|
||||
if b.BlockOverrides.Time == nil {
|
||||
t.Fatalf("testcase %d: block time not set", i)
|
||||
}
|
||||
if (uint64)(*b.BlockOverrides.Time) != tc.expected[bi].timestamp {
|
||||
t.Errorf("testcase %d: block timestamp mismatch. Want %d, have %d", i, tc.expected[bi].timestamp, (uint64)(*b.BlockOverrides.Time))
|
||||
}
|
||||
have := b.BlockOverrides.Number.ToInt().Uint64()
|
||||
if uint64(want) != have {
|
||||
t.Errorf("testcase %d: block number mismatch. Want %d, have %d", i, want, have)
|
||||
if have != tc.expected[bi].number {
|
||||
t.Errorf("testcase %d: block number mismatch. Want %d, have %d", i, tc.expected[bi].number, have)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue