mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-19 18:32:23 +00:00
add ecrecover override
This commit is contained in:
parent
80df50db7e
commit
c3f149425a
2 changed files with 67 additions and 7 deletions
|
|
@ -1012,16 +1012,16 @@ func DoCall(ctx context.Context, b Backend, args TransactionArgs, blockNrOrHash
|
|||
// Make sure the context is cancelled when the call has completed
|
||||
// this makes sure resources are cleaned up.
|
||||
defer cancel()
|
||||
return doCall(ctx, b, args, state, header, timeout, new(core.GasPool).AddGas(globalGasCap), &blockCtx)
|
||||
return doCall(ctx, b, args, state, header, timeout, new(core.GasPool).AddGas(globalGasCap), &blockCtx, &vm.Config{NoBaseFee: true})
|
||||
}
|
||||
|
||||
func doCall(ctx context.Context, b Backend, args TransactionArgs, state *state.StateDB, header *types.Header, timeout time.Duration, gp *core.GasPool, blockContext *vm.BlockContext) (*core.ExecutionResult, error) {
|
||||
func doCall(ctx context.Context, b Backend, args TransactionArgs, state *state.StateDB, header *types.Header, timeout time.Duration, gp *core.GasPool, blockContext *vm.BlockContext, vmConfig *vm.Config) (*core.ExecutionResult, error) {
|
||||
// Get a new instance of the EVM.
|
||||
msg, err := args.ToMessage(gp.Gas(), header.BaseFee)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
evm, vmError := b.GetEVM(ctx, msg, state, header, &vm.Config{NoBaseFee: true}, blockContext)
|
||||
evm, vmError := b.GetEVM(ctx, msg, state, header, vmConfig, blockContext)
|
||||
|
||||
// Wait for the context to be done and cancel the evm. Even if the
|
||||
// EVM has finished, cancelling may be done (repeatedly)
|
||||
|
|
@ -1096,9 +1096,10 @@ func (s *BlockChainAPI) Call(ctx context.Context, args TransactionArgs, blockNrO
|
|||
|
||||
// CallBatch is a batch of calls to be simulated sequentially.
|
||||
type CallBatch struct {
|
||||
BlockOverrides *BlockOverrides
|
||||
StateOverrides *StateOverride
|
||||
Calls []TransactionArgs
|
||||
BlockOverrides *BlockOverrides
|
||||
StateOverrides *StateOverride
|
||||
ECRecoverOverride *hexutil.Bytes // Override bytecode for ecrecover precompile.
|
||||
Calls []TransactionArgs
|
||||
}
|
||||
|
||||
type callResult struct {
|
||||
|
|
@ -1146,6 +1147,10 @@ func (s *BlockChainAPI) Multicall(ctx context.Context, blocks []CallBatch, block
|
|||
if err := block.StateOverrides.Apply(state); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// ECRecover replacement code will be fetched from statedb and executed as a normal EVM bytecode.
|
||||
if block.ECRecoverOverride != nil {
|
||||
state.SetCode(common.BytesToAddress([]byte{1}), *block.ECRecoverOverride)
|
||||
}
|
||||
blockContext := core.NewEVMBlockContext(header, NewChainContext(ctx, s.b), nil)
|
||||
if block.BlockOverrides != nil {
|
||||
block.BlockOverrides.Apply(&blockContext)
|
||||
|
|
@ -1155,7 +1160,7 @@ func (s *BlockChainAPI) Multicall(ctx context.Context, blocks []CallBatch, block
|
|||
// Hack to get logs from statedb which stores logs by txhash.
|
||||
txhash := common.BigToHash(big.NewInt(int64(i)))
|
||||
state.SetTxContext(txhash, i)
|
||||
result, err := doCall(ctx, s.b, call, state, header, timeout, gp, &blockContext)
|
||||
result, err := doCall(ctx, s.b, call, state, header, timeout, gp, &blockContext, &vm.Config{NoBaseFee: true, DisableECRecover: true})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ import (
|
|||
"math/big"
|
||||
"reflect"
|
||||
"sort"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
|
|
@ -776,6 +777,60 @@ func TestMulticall(t *testing.T) {
|
|||
GasUsed: "0x5508",
|
||||
}}},
|
||||
},
|
||||
// Test ecrecover override
|
||||
{
|
||||
tag: latest,
|
||||
blocks: []CallBatch{{
|
||||
StateOverrides: &StateOverride{
|
||||
randomAccounts[2].addr: OverrideAccount{
|
||||
// Yul code that returns ecrecover(0, 0, 0, 0).
|
||||
// object "Test" {
|
||||
// code {
|
||||
// // Free memory pointer
|
||||
// let free_ptr := mload(0x40)
|
||||
//
|
||||
// // Initialize inputs with zeros
|
||||
// mstore(free_ptr, 0) // Hash
|
||||
// mstore(add(free_ptr, 0x20), 0) // v
|
||||
// mstore(add(free_ptr, 0x40), 0) // r
|
||||
// mstore(add(free_ptr, 0x60), 0) // s
|
||||
//
|
||||
// // Call ecrecover precompile (at address 1) with all 0 inputs
|
||||
// let success := staticcall(gas(), 1, free_ptr, 0x80, free_ptr, 0x20)
|
||||
//
|
||||
// // Check if the call was successful
|
||||
// if eq(success, 0) {
|
||||
// revert(0, 0)
|
||||
// }
|
||||
//
|
||||
// // Return the recovered address
|
||||
// return(free_ptr, 0x14)
|
||||
// }
|
||||
// }
|
||||
Code: hex2Bytes("6040516000815260006020820152600060408201526000606082015260208160808360015afa60008103603157600080fd5b601482f3"),
|
||||
},
|
||||
},
|
||||
BlockOverrides: &BlockOverrides{},
|
||||
// Yul code that returns the address of the caller.
|
||||
// object "Test" {
|
||||
// code {
|
||||
// let c := caller()
|
||||
// mstore(0, c)
|
||||
// return(0xc, 0x14)
|
||||
// }
|
||||
// }
|
||||
ECRecoverOverride: hex2Bytes("33806000526014600cf3"),
|
||||
Calls: []TransactionArgs{{
|
||||
From: &randomAccounts[0].addr,
|
||||
To: &randomAccounts[2].addr,
|
||||
}},
|
||||
}},
|
||||
want: [][]res{{{
|
||||
// Caller is in this case the contract that invokes ecrecover.
|
||||
ReturnValue: strings.ToLower(randomAccounts[2].addr.String()),
|
||||
GasUsed: "0x52f6",
|
||||
}}},
|
||||
},
|
||||
}
|
||||
|
||||
for i, tc := range testSuite {
|
||||
|
|
|
|||
Loading…
Reference in a new issue