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