auto-set and validate block number and timestamp

This commit is contained in:
Sina Mahmoodi 2023-09-04 15:00:05 +02:00
parent b0e78695f5
commit 56b4402f0c
2 changed files with 68 additions and 41 deletions

View file

@ -1247,31 +1247,26 @@ func (s *BlockChainAPI) MulticallV1(ctx context.Context, opts multicallOpts, blo
// Make sure the context is cancelled when the call has completed // Make sure the context is cancelled when the call has completed
// this makes sure resources are cleaned up. // this makes sure resources are cleaned up.
defer cancel() defer cancel()
blockContexts, err := makeBlockContexts(ctx, s.b, blocks, header)
if err != nil {
return nil, err
}
var ( var (
results = make([]blockResult, len(blocks)) results = make([]blockResult, len(blocks))
// Each tx and all the series of txes shouldn't consume more gas than cap // Each tx and all the series of txes shouldn't consume more gas than cap
globalGasCap = s.b.RPCGasCap() globalGasCap = s.b.RPCGasCap()
gp = new(core.GasPool).AddGas(globalGasCap) gp = new(core.GasPool).AddGas(globalGasCap)
prevNumber = header.Number.Uint64()
blockContext = core.NewEVMBlockContext(header, NewChainContext(ctx, s.b), nil) blockContext = core.NewEVMBlockContext(header, NewChainContext(ctx, s.b), nil)
rules = s.b.ChainConfig().Rules(blockContext.BlockNumber, blockContext.Random != nil, blockContext.Time) rules = s.b.ChainConfig().Rules(blockContext.BlockNumber, blockContext.Random != nil, blockContext.Time)
precompiles = vm.ActivePrecompiledContracts(rules).Copy() precompiles = vm.ActivePrecompiledContracts(rules).Copy()
) )
for bi, block := range blocks { for bi, block := range blocks {
blockContext = core.NewEVMBlockContext(header, NewChainContext(ctx, s.b), nil) blockContext = blockContexts[bi]
if block.BlockOverrides != nil { hash := crypto.Keccak256Hash(blockContext.BlockNumber.Bytes())
block.BlockOverrides.Apply(&blockContext)
}
// TODO: Consider hoisting this check up
if blockContext.BlockNumber.Uint64() < prevNumber {
return nil, fmt.Errorf("block numbers must be in order")
}
prevNumber = blockContext.BlockNumber.Uint64()
// State overrides are applied prior to execution of a block // State overrides are applied prior to execution of a block
if err := block.StateOverrides.ApplyMulticall(state, precompiles); err != nil { if err := block.StateOverrides.ApplyMulticall(state, precompiles); err != nil {
return nil, err return nil, err
} }
hash := crypto.Keccak256Hash(blockContext.BlockNumber.Bytes())
results[bi] = blockResult{ results[bi] = blockResult{
Number: hexutil.Uint64(blockContext.BlockNumber.Uint64()), Number: hexutil.Uint64(blockContext.BlockNumber.Uint64()),
Hash: hash, Hash: hash,
@ -1324,6 +1319,39 @@ func (s *BlockChainAPI) MulticallV1(ctx context.Context, opts multicallOpts, blo
return results, nil return results, nil
} }
func makeBlockContexts(ctx context.Context, b Backend, blocks []CallBatch, header *types.Header) ([]vm.BlockContext, error) {
res := make([]vm.BlockContext, len(blocks))
var (
prevNumber = header.Number.Uint64()
prevTimestamp = header.Time
)
for bi, block := range blocks {
blockContext := core.NewEVMBlockContext(header, NewChainContext(ctx, b), nil)
if block.BlockOverrides == nil {
block.BlockOverrides = new(BlockOverrides)
}
if block.BlockOverrides.Number == nil {
n := new(big.Int).Add(big.NewInt(int64(prevNumber)), big.NewInt(1))
block.BlockOverrides.Number = (*hexutil.Big)(n)
}
if block.BlockOverrides.Time == nil {
t := prevTimestamp + 1
block.BlockOverrides.Time = (*hexutil.Uint64)(&t)
}
block.BlockOverrides.Apply(&blockContext)
if blockContext.BlockNumber.Uint64() <= prevNumber {
return nil, fmt.Errorf("block numbers must be in order")
}
prevNumber = blockContext.BlockNumber.Uint64()
if blockContext.Time <= prevTimestamp {
return nil, fmt.Errorf("timestamps must be in order")
}
prevTimestamp = blockContext.Time
res[bi] = blockContext
}
return res, nil
}
func DoEstimateGas(ctx context.Context, b Backend, args TransactionArgs, blockNrOrHash rpc.BlockNumberOrHash, gasCap uint64) (hexutil.Uint64, error) { func DoEstimateGas(ctx context.Context, b Backend, args TransactionArgs, blockNrOrHash rpc.BlockNumberOrHash, gasCap uint64) (hexutil.Uint64, error) {
// Binary search the gas requirement, as it may be higher than the amount used // Binary search the gas requirement, as it may be higher than the amount used
var ( var (

View file

@ -682,7 +682,7 @@ func TestMulticallV1(t *testing.T) {
}, },
}, },
} }
n10hash = crypto.Keccak256Hash([]byte{0xa}).Hex() n11hash = crypto.Keccak256Hash([]byte{0xb}).Hex()
sha256Address = common.BytesToAddress([]byte{0x02}) sha256Address = common.BytesToAddress([]byte{0x02})
) )
api := NewBlockChainAPI(newTestBackend(t, genBlocks, genesis, func(i int, b *core.BlockGen) { api := NewBlockChainAPI(newTestBackend(t, genBlocks, genesis, func(i int, b *core.BlockGen) {
@ -754,8 +754,8 @@ func TestMulticallV1(t *testing.T) {
}}, }},
}}, }},
want: []blockRes{{ want: []blockRes{{
Number: "0xa", Number: "0xb",
Hash: n10hash, Hash: n11hash,
GasLimit: "0x47e7c4", GasLimit: "0x47e7c4",
GasUsed: "0xa410", GasUsed: "0xa410",
FeeRecipient: coinbase, FeeRecipient: coinbase,
@ -807,8 +807,8 @@ func TestMulticallV1(t *testing.T) {
}, },
}}, }},
want: []blockRes{{ want: []blockRes{{
Number: "0xa", Number: "0xb",
Hash: n10hash, Hash: n11hash,
GasLimit: "0x47e7c4", GasLimit: "0x47e7c4",
GasUsed: "0xa410", GasUsed: "0xa410",
FeeRecipient: coinbase, FeeRecipient: coinbase,
@ -824,8 +824,8 @@ func TestMulticallV1(t *testing.T) {
Status: "0x1", Status: "0x1",
}}, }},
}, { }, {
Number: "0xa", Number: "0xc",
Hash: n10hash, Hash: crypto.Keccak256Hash([]byte{0xc}).Hex(),
GasLimit: "0x47e7c4", GasLimit: "0x47e7c4",
GasUsed: "0x5208", GasUsed: "0x5208",
FeeRecipient: coinbase, FeeRecipient: coinbase,
@ -876,7 +876,7 @@ func TestMulticallV1(t *testing.T) {
}}, }},
want: []blockRes{{ want: []blockRes{{
Number: "0xb", Number: "0xb",
Hash: crypto.Keccak256Hash([]byte{0xb}).Hex(), Hash: n11hash,
GasLimit: "0x47e7c4", GasLimit: "0x47e7c4",
GasUsed: "0xe891", GasUsed: "0xe891",
FeeRecipient: strings.ToLower(cac.String()), FeeRecipient: strings.ToLower(cac.String()),
@ -956,8 +956,8 @@ func TestMulticallV1(t *testing.T) {
}, },
}}, }},
want: []blockRes{{ want: []blockRes{{
Number: "0xa", Number: "0xb",
Hash: n10hash, Hash: n11hash,
GasLimit: "0x47e7c4", GasLimit: "0x47e7c4",
GasUsed: "0x10683", GasUsed: "0x10683",
FeeRecipient: coinbase, FeeRecipient: coinbase,
@ -998,8 +998,8 @@ func TestMulticallV1(t *testing.T) {
}}, }},
}}, }},
want: []blockRes{{ want: []blockRes{{
Number: "0xa", Number: "0xb",
Hash: n10hash, Hash: n11hash,
GasLimit: "0x47e7c4", GasLimit: "0x47e7c4",
GasUsed: "0x5508", GasUsed: "0x5508",
FeeRecipient: coinbase, FeeRecipient: coinbase,
@ -1008,7 +1008,7 @@ func TestMulticallV1(t *testing.T) {
Logs: []types.Log{{ Logs: []types.Log{{
Address: randomAccounts[2].addr, Address: randomAccounts[2].addr,
Topics: []common.Hash{common.HexToHash("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")}, Topics: []common.Hash{common.HexToHash("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")},
BlockNumber: 10, BlockNumber: 11,
Data: []byte{}, Data: []byte{},
}}, }},
GasUsed: "0x5508", GasUsed: "0x5508",
@ -1061,15 +1061,14 @@ func TestMulticallV1(t *testing.T) {
Code: hex2Bytes("33806000526014600cf3"), Code: hex2Bytes("33806000526014600cf3"),
}, },
}, },
BlockOverrides: &BlockOverrides{},
Calls: []TransactionArgs{{ Calls: []TransactionArgs{{
From: &randomAccounts[0].addr, From: &randomAccounts[0].addr,
To: &randomAccounts[2].addr, To: &randomAccounts[2].addr,
}}, }},
}}, }},
want: []blockRes{{ want: []blockRes{{
Number: "0xa", Number: "0xb",
Hash: n10hash, Hash: n11hash,
GasLimit: "0x47e7c4", GasLimit: "0x47e7c4",
GasUsed: "0x52f6", GasUsed: "0x52f6",
FeeRecipient: coinbase, FeeRecipient: coinbase,
@ -1119,8 +1118,8 @@ func TestMulticallV1(t *testing.T) {
}}, }},
}}, }},
want: []blockRes{{ want: []blockRes{{
Number: "0xa", Number: "0xb",
Hash: n10hash, Hash: n11hash,
GasLimit: "0x47e7c4", GasLimit: "0x47e7c4",
GasUsed: "0xa58c", GasUsed: "0xa58c",
FeeRecipient: coinbase, FeeRecipient: coinbase,
@ -1168,8 +1167,8 @@ func TestMulticallV1(t *testing.T) {
}}, }},
includeTransfers: &includeTransfers, includeTransfers: &includeTransfers,
want: []blockRes{{ want: []blockRes{{
Number: "0xa", Number: "0xb",
Hash: n10hash, Hash: n11hash,
GasLimit: "0x47e7c4", GasLimit: "0x47e7c4",
GasUsed: "0xd984", GasUsed: "0xd984",
FeeRecipient: coinbase, FeeRecipient: coinbase,
@ -1227,8 +1226,8 @@ func TestMulticallV1(t *testing.T) {
}}, }},
}}, }},
want: []blockRes{{ want: []blockRes{{
Number: "0xa", Number: "0xb",
Hash: n10hash, Hash: n11hash,
GasLimit: "0x47e7c4", GasLimit: "0x47e7c4",
GasUsed: "0x1b83f", GasUsed: "0x1b83f",
FeeRecipient: coinbase, FeeRecipient: coinbase,
@ -1244,8 +1243,8 @@ func TestMulticallV1(t *testing.T) {
Status: "0x1", Status: "0x1",
}}, }},
}, { }, {
Number: "0xa", Number: "0xc",
Hash: n10hash, Hash: crypto.Keccak256Hash([]byte{0xc}).Hex(),
GasLimit: "0x47e7c4", GasLimit: "0x47e7c4",
GasUsed: "0xe6d9", GasUsed: "0xe6d9",
FeeRecipient: coinbase, FeeRecipient: coinbase,
@ -1270,8 +1269,8 @@ func TestMulticallV1(t *testing.T) {
}}, }},
validation: &validation, validation: &validation,
want: []blockRes{{ want: []blockRes{{
Number: "0xa", Number: "0xb",
Hash: n10hash, Hash: n11hash,
GasLimit: "0x47e7c4", GasLimit: "0x47e7c4",
GasUsed: "0x0", GasUsed: "0x0",
FeeRecipient: coinbase, FeeRecipient: coinbase,
@ -1324,8 +1323,8 @@ func TestMulticallV1(t *testing.T) {
}}, }},
}}, }},
want: []blockRes{{ want: []blockRes{{
Number: "0xa", Number: "0xb",
Hash: n10hash, Hash: n11hash,
GasLimit: "0x47e7c4", GasLimit: "0x47e7c4",
GasUsed: "0xc542", GasUsed: "0xc542",
FeeRecipient: coinbase, FeeRecipient: coinbase,
@ -1341,8 +1340,8 @@ func TestMulticallV1(t *testing.T) {
Status: "0x1", Status: "0x1",
}}, }},
}, { }, {
Number: "0xa", Number: "0xc",
Hash: n10hash, Hash: crypto.Keccak256Hash([]byte{0xc}).Hex(),
GasLimit: "0x47e7c4", GasLimit: "0x47e7c4",
GasUsed: "0x62a1", GasUsed: "0x62a1",
FeeRecipient: coinbase, FeeRecipient: coinbase,