mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-19 18:32:23 +00:00
add optional validation of txes
This commit is contained in:
parent
fd786c081f
commit
6845b5eff6
4 changed files with 51 additions and 8 deletions
|
|
@ -908,7 +908,7 @@ func (api *API) TraceCall(ctx context.Context, args ethapi.TransactionArgs, bloc
|
||||||
config.BlockOverrides.Apply(&vmctx)
|
config.BlockOverrides.Apply(&vmctx)
|
||||||
}
|
}
|
||||||
// Execute the trace
|
// Execute the trace
|
||||||
msg, err := args.ToMessage(api.backend.RPCGasCap(), block.BaseFee())
|
msg, err := args.ToMessage(api.backend.RPCGasCap(), block.BaseFee(), true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1093,12 +1093,12 @@ 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, &vm.Config{NoBaseFee: true}, nil)
|
return doCall(ctx, b, args, state, header, timeout, new(core.GasPool).AddGas(globalGasCap), &blockCtx, &vm.Config{NoBaseFee: true}, nil, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
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, precompiles vm.PrecompiledContracts) (*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, precompiles vm.PrecompiledContracts, validate bool) (*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, !validate)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
@ -1217,6 +1217,7 @@ func (r *callResult) MarshalJSON() ([]byte, error) {
|
||||||
type multicallOpts struct {
|
type multicallOpts struct {
|
||||||
BlockStateCalls []CallBatch
|
BlockStateCalls []CallBatch
|
||||||
TraceTransfers bool
|
TraceTransfers bool
|
||||||
|
Validation bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// MulticallV1 executes series of transactions on top of a base state.
|
// MulticallV1 executes series of transactions on top of a base state.
|
||||||
|
|
@ -1289,7 +1290,7 @@ func (s *BlockChainAPI) MulticallV1(ctx context.Context, opts multicallOpts, blo
|
||||||
if opts.TraceTransfers {
|
if opts.TraceTransfers {
|
||||||
vmConfig.Tracer = newTracer()
|
vmConfig.Tracer = newTracer()
|
||||||
}
|
}
|
||||||
result, err := doCall(ctx, s.b, call, state, header, timeout, gp, &blockContext, vmConfig, precompiles)
|
result, err := doCall(ctx, s.b, call, state, header, timeout, gp, &blockContext, vmConfig, precompiles, opts.Validation)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
results[bi].Calls[i] = callResult{Error: err.Error(), Status: hexutil.Uint64(types.ReceiptStatusFailed)}
|
results[bi].Calls[i] = callResult{Error: err.Error(), Status: hexutil.Uint64(types.ReceiptStatusFailed)}
|
||||||
continue
|
continue
|
||||||
|
|
@ -1722,7 +1723,7 @@ func AccessList(ctx context.Context, b Backend, blockNrOrHash rpc.BlockNumberOrH
|
||||||
statedb := db.Copy()
|
statedb := db.Copy()
|
||||||
// Set the accesslist to the last al
|
// Set the accesslist to the last al
|
||||||
args.AccessList = &accessList
|
args.AccessList = &accessList
|
||||||
msg, err := args.ToMessage(b.RPCGasCap(), header.BaseFee)
|
msg, err := args.ToMessage(b.RPCGasCap(), header.BaseFee, true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, 0, nil, err
|
return nil, 0, nil, err
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -677,6 +677,7 @@ func TestMulticallV1(t *testing.T) {
|
||||||
randomAccounts = newAccounts(4)
|
randomAccounts = newAccounts(4)
|
||||||
latest = rpc.BlockNumberOrHashWithNumber(rpc.LatestBlockNumber)
|
latest = rpc.BlockNumberOrHashWithNumber(rpc.LatestBlockNumber)
|
||||||
includeTransfers = true
|
includeTransfers = true
|
||||||
|
validation = true
|
||||||
)
|
)
|
||||||
type callRes struct {
|
type callRes struct {
|
||||||
ReturnValue string `json:"return"`
|
ReturnValue string `json:"return"`
|
||||||
|
|
@ -701,6 +702,7 @@ func TestMulticallV1(t *testing.T) {
|
||||||
blocks []CallBatch
|
blocks []CallBatch
|
||||||
tag rpc.BlockNumberOrHash
|
tag rpc.BlockNumberOrHash
|
||||||
includeTransfers *bool
|
includeTransfers *bool
|
||||||
|
validation *bool
|
||||||
expectErr error
|
expectErr error
|
||||||
want []blockRes
|
want []blockRes
|
||||||
}{
|
}{
|
||||||
|
|
@ -1210,6 +1212,33 @@ func TestMulticallV1(t *testing.T) {
|
||||||
}},
|
}},
|
||||||
}},
|
}},
|
||||||
},
|
},
|
||||||
|
// Enable validation checks.
|
||||||
|
{
|
||||||
|
name: "validation-checks",
|
||||||
|
tag: latest,
|
||||||
|
blocks: []CallBatch{{
|
||||||
|
Calls: []TransactionArgs{{
|
||||||
|
From: &accounts[2].addr,
|
||||||
|
To: &cac,
|
||||||
|
Nonce: newUint64(2),
|
||||||
|
}},
|
||||||
|
}},
|
||||||
|
validation: &validation,
|
||||||
|
want: []blockRes{{
|
||||||
|
Number: "0xa",
|
||||||
|
Hash: n10hash,
|
||||||
|
GasLimit: "0x47e7c4",
|
||||||
|
GasUsed: "0x0",
|
||||||
|
FeeRecipient: "0x0000000000000000000000000000000000000000",
|
||||||
|
Calls: []callRes{{
|
||||||
|
ReturnValue: "0x",
|
||||||
|
GasUsed: "0x0",
|
||||||
|
Logs: []types.Log{},
|
||||||
|
Status: "0x0",
|
||||||
|
Error: fmt.Sprintf("err: nonce too high: address %s, tx: 2 state: 0 (supplied gas 10000000)", accounts[2].addr),
|
||||||
|
}},
|
||||||
|
}},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for i, tc := range testSuite {
|
for i, tc := range testSuite {
|
||||||
|
|
@ -1218,6 +1247,9 @@ func TestMulticallV1(t *testing.T) {
|
||||||
if tc.includeTransfers != nil && *tc.includeTransfers {
|
if tc.includeTransfers != nil && *tc.includeTransfers {
|
||||||
opts.TraceTransfers = true
|
opts.TraceTransfers = true
|
||||||
}
|
}
|
||||||
|
if tc.validation != nil && *tc.validation {
|
||||||
|
opts.Validation = true
|
||||||
|
}
|
||||||
result, err := api.MulticallV1(context.Background(), opts, tc.tag)
|
result, err := api.MulticallV1(context.Background(), opts, tc.tag)
|
||||||
if tc.expectErr != nil {
|
if tc.expectErr != nil {
|
||||||
if err == nil {
|
if err == nil {
|
||||||
|
|
@ -1278,6 +1310,11 @@ func hex2Bytes(str string) *hexutil.Bytes {
|
||||||
return &rpcBytes
|
return &rpcBytes
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func newUint64(v uint64) *hexutil.Uint64 {
|
||||||
|
rpcUint64 := hexutil.Uint64(v)
|
||||||
|
return &rpcUint64
|
||||||
|
}
|
||||||
|
|
||||||
// testHasher is the helper tool for transaction/receipt list hashing.
|
// testHasher is the helper tool for transaction/receipt list hashing.
|
||||||
// The original hasher is trie, in order to get rid of import cycle,
|
// The original hasher is trie, in order to get rid of import cycle,
|
||||||
// use the testing hasher instead.
|
// use the testing hasher instead.
|
||||||
|
|
|
||||||
|
|
@ -200,7 +200,7 @@ func (args *TransactionArgs) setLondonFeeDefaults(ctx context.Context, head *typ
|
||||||
// ToMessage converts the transaction arguments to the Message type used by the
|
// ToMessage converts the transaction arguments to the Message type used by the
|
||||||
// core evm. This method is used in calls and traces that do not require a real
|
// core evm. This method is used in calls and traces that do not require a real
|
||||||
// live transaction.
|
// live transaction.
|
||||||
func (args *TransactionArgs) ToMessage(globalGasCap uint64, baseFee *big.Int) (*core.Message, error) {
|
func (args *TransactionArgs) ToMessage(globalGasCap uint64, baseFee *big.Int, skipChecks bool) (*core.Message, error) {
|
||||||
// Reject invalid combinations of pre- and post-1559 fee styles
|
// Reject invalid combinations of pre- and post-1559 fee styles
|
||||||
if args.GasPrice != nil && (args.MaxFeePerGas != nil || args.MaxPriorityFeePerGas != nil) {
|
if args.GasPrice != nil && (args.MaxFeePerGas != nil || args.MaxPriorityFeePerGas != nil) {
|
||||||
return nil, errors.New("both gasPrice and (maxFeePerGas or maxPriorityFeePerGas) specified")
|
return nil, errors.New("both gasPrice and (maxFeePerGas or maxPriorityFeePerGas) specified")
|
||||||
|
|
@ -259,6 +259,10 @@ func (args *TransactionArgs) ToMessage(globalGasCap uint64, baseFee *big.Int) (*
|
||||||
if args.Value != nil {
|
if args.Value != nil {
|
||||||
value = args.Value.ToInt()
|
value = args.Value.ToInt()
|
||||||
}
|
}
|
||||||
|
var nonce uint64
|
||||||
|
if args.Nonce != nil {
|
||||||
|
nonce = uint64(*args.Nonce)
|
||||||
|
}
|
||||||
data := args.data()
|
data := args.data()
|
||||||
var accessList types.AccessList
|
var accessList types.AccessList
|
||||||
if args.AccessList != nil {
|
if args.AccessList != nil {
|
||||||
|
|
@ -268,13 +272,14 @@ func (args *TransactionArgs) ToMessage(globalGasCap uint64, baseFee *big.Int) (*
|
||||||
From: addr,
|
From: addr,
|
||||||
To: args.To,
|
To: args.To,
|
||||||
Value: value,
|
Value: value,
|
||||||
|
Nonce: nonce,
|
||||||
GasLimit: gas,
|
GasLimit: gas,
|
||||||
GasPrice: gasPrice,
|
GasPrice: gasPrice,
|
||||||
GasFeeCap: gasFeeCap,
|
GasFeeCap: gasFeeCap,
|
||||||
GasTipCap: gasTipCap,
|
GasTipCap: gasTipCap,
|
||||||
Data: data,
|
Data: data,
|
||||||
AccessList: accessList,
|
AccessList: accessList,
|
||||||
SkipAccountChecks: true,
|
SkipAccountChecks: skipChecks,
|
||||||
}
|
}
|
||||||
return msg, nil
|
return msg, nil
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue