mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-20 02:42:27 +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
|
// 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()
|
||||||
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.
|
// Get a new instance of the EVM.
|
||||||
msg, err := args.ToMessage(gp.Gas(), header.BaseFee)
|
msg, err := args.ToMessage(gp.Gas(), header.BaseFee)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
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
|
// Wait for the context to be done and cancel the evm. Even if the
|
||||||
// EVM has finished, cancelling may be done (repeatedly)
|
// 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.
|
// CallBatch is a batch of calls to be simulated sequentially.
|
||||||
type CallBatch struct {
|
type CallBatch struct {
|
||||||
BlockOverrides *BlockOverrides
|
BlockOverrides *BlockOverrides
|
||||||
StateOverrides *StateOverride
|
StateOverrides *StateOverride
|
||||||
Calls []TransactionArgs
|
ECRecoverOverride *hexutil.Bytes // Override bytecode for ecrecover precompile.
|
||||||
|
Calls []TransactionArgs
|
||||||
}
|
}
|
||||||
|
|
||||||
type callResult struct {
|
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 {
|
if err := block.StateOverrides.Apply(state); err != nil {
|
||||||
return nil, err
|
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)
|
blockContext := core.NewEVMBlockContext(header, NewChainContext(ctx, s.b), nil)
|
||||||
if block.BlockOverrides != nil {
|
if block.BlockOverrides != nil {
|
||||||
block.BlockOverrides.Apply(&blockContext)
|
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.
|
// Hack to get logs from statedb which stores logs by txhash.
|
||||||
txhash := common.BigToHash(big.NewInt(int64(i)))
|
txhash := common.BigToHash(big.NewInt(int64(i)))
|
||||||
state.SetTxContext(txhash, 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 {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,7 @@ import (
|
||||||
"math/big"
|
"math/big"
|
||||||
"reflect"
|
"reflect"
|
||||||
"sort"
|
"sort"
|
||||||
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
|
@ -776,6 +777,60 @@ func TestMulticall(t *testing.T) {
|
||||||
GasUsed: "0x5508",
|
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 {
|
for i, tc := range testSuite {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue