mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-20 10:52:25 +00:00
add BlockOverrides to EstimateGas
This commit is contained in:
parent
8976a0c97a
commit
15fb389ec7
4 changed files with 36 additions and 16 deletions
|
|
@ -1212,7 +1212,7 @@ func (b *Block) Call(ctx context.Context, args struct {
|
|||
func (b *Block) EstimateGas(ctx context.Context, args struct {
|
||||
Data ethapi.TransactionArgs
|
||||
}) (hexutil.Uint64, error) {
|
||||
return ethapi.DoEstimateGas(ctx, b.r.backend, args.Data, *b.numberOrHash, nil, b.r.backend.RPCGasCap())
|
||||
return ethapi.DoEstimateGas(ctx, b.r.backend, args.Data, *b.numberOrHash, nil, nil, b.r.backend.RPCGasCap())
|
||||
}
|
||||
|
||||
type Pending struct {
|
||||
|
|
@ -1276,7 +1276,7 @@ func (p *Pending) EstimateGas(ctx context.Context, args struct {
|
|||
Data ethapi.TransactionArgs
|
||||
}) (hexutil.Uint64, error) {
|
||||
latestBlockNr := rpc.BlockNumberOrHashWithNumber(rpc.LatestBlockNumber)
|
||||
return ethapi.DoEstimateGas(ctx, p.r.backend, args.Data, latestBlockNr, nil, p.r.backend.RPCGasCap())
|
||||
return ethapi.DoEstimateGas(ctx, p.r.backend, args.Data, latestBlockNr, nil, nil, p.r.backend.RPCGasCap())
|
||||
}
|
||||
|
||||
// Resolver is the top-level object in the GraphQL hierarchy.
|
||||
|
|
|
|||
|
|
@ -1181,9 +1181,9 @@ func (s *BlockChainAPI) Call(ctx context.Context, args TransactionArgs, blockNrO
|
|||
// executeEstimate is a helper that executes the transaction under a given gas limit and returns
|
||||
// true if the transaction fails for a reason that might be related to not enough gas. A non-nil
|
||||
// error means execution failed due to reasons unrelated to the gas limit.
|
||||
func executeEstimate(ctx context.Context, b Backend, args TransactionArgs, state *state.StateDB, header *types.Header, gasCap uint64, gasLimit uint64) (bool, *core.ExecutionResult, error) {
|
||||
func executeEstimate(ctx context.Context, b Backend, args TransactionArgs, state *state.StateDB, header *types.Header, gasCap uint64, gasLimit uint64, blockOverrides *BlockOverrides) (bool, *core.ExecutionResult, error) {
|
||||
args.Gas = (*hexutil.Uint64)(&gasLimit)
|
||||
result, err := doCall(ctx, b, args, state, header, nil, nil, 0, gasCap)
|
||||
result, err := doCall(ctx, b, args, state, header, nil, blockOverrides, 0, gasCap)
|
||||
if err != nil {
|
||||
if errors.Is(err, core.ErrIntrinsicGas) {
|
||||
return true, nil, nil // Special case, raise gas limit
|
||||
|
|
@ -1197,7 +1197,7 @@ func executeEstimate(ctx context.Context, b Backend, args TransactionArgs, state
|
|||
// successfully at block `blockNrOrHash`. It returns error if the transaction would revert, or if
|
||||
// there are unexpected failures. The gas limit is capped by both `args.Gas` (if non-nil &
|
||||
// non-zero) and `gasCap` (if non-zero).
|
||||
func DoEstimateGas(ctx context.Context, b Backend, args TransactionArgs, blockNrOrHash rpc.BlockNumberOrHash, overrides *StateOverride, gasCap uint64) (hexutil.Uint64, error) {
|
||||
func DoEstimateGas(ctx context.Context, b Backend, args TransactionArgs, blockNrOrHash rpc.BlockNumberOrHash, overrides *StateOverride, blockOverrides *BlockOverrides, gasCap uint64) (hexutil.Uint64, error) {
|
||||
// Binary search the gas limit, as it may need to be higher than the amount used
|
||||
var (
|
||||
lo uint64 // lowest-known gas limit where tx execution fails
|
||||
|
|
@ -1272,7 +1272,7 @@ func DoEstimateGas(ctx context.Context, b Backend, args TransactionArgs, blockNr
|
|||
|
||||
// We first execute the transaction at the highest allowable gas limit, since if this fails we
|
||||
// can return error immediately.
|
||||
failed, result, err := executeEstimate(ctx, b, args, state.Copy(), header, gasCap, hi)
|
||||
failed, result, err := executeEstimate(ctx, b, args, state.Copy(), header, gasCap, hi, blockOverrides)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
|
@ -1300,7 +1300,7 @@ func DoEstimateGas(ctx context.Context, b Backend, args TransactionArgs, blockNr
|
|||
// range here is skewed to favor the low side.
|
||||
mid = lo * 2
|
||||
}
|
||||
failed, _, err = executeEstimate(ctx, b, args, state.Copy(), header, gasCap, mid)
|
||||
failed, _, err = executeEstimate(ctx, b, args, state.Copy(), header, gasCap, mid, blockOverrides)
|
||||
if err != nil {
|
||||
// This should not happen under normal conditions since if we make it this far the
|
||||
// transaction had run without error at least once before.
|
||||
|
|
@ -1321,12 +1321,12 @@ func DoEstimateGas(ctx context.Context, b Backend, args TransactionArgs, blockNr
|
|||
// returns error if the transaction would revert or if there are unexpected failures. The returned
|
||||
// value is capped by both `args.Gas` (if non-nil & non-zero) and the backend's RPCGasCap
|
||||
// configuration (if non-zero).
|
||||
func (s *BlockChainAPI) EstimateGas(ctx context.Context, args TransactionArgs, blockNrOrHash *rpc.BlockNumberOrHash, overrides *StateOverride) (hexutil.Uint64, error) {
|
||||
func (s *BlockChainAPI) EstimateGas(ctx context.Context, args TransactionArgs, blockNrOrHash *rpc.BlockNumberOrHash, overrides *StateOverride, blockOverrides *BlockOverrides) (hexutil.Uint64, error) {
|
||||
bNrOrHash := rpc.BlockNumberOrHashWithNumber(rpc.LatestBlockNumber)
|
||||
if blockNrOrHash != nil {
|
||||
bNrOrHash = *blockNrOrHash
|
||||
}
|
||||
return DoEstimateGas(ctx, s.b, args, bNrOrHash, overrides, s.b.RPCGasCap())
|
||||
return DoEstimateGas(ctx, s.b, args, bNrOrHash, overrides, blockOverrides, s.b.RPCGasCap())
|
||||
}
|
||||
|
||||
// RPCMarshalHeader converts the given header to the RPC output .
|
||||
|
|
|
|||
|
|
@ -621,10 +621,18 @@ func TestEstimateGas(t *testing.T) {
|
|||
tx, _ := types.SignTx(types.NewTx(&types.LegacyTx{Nonce: uint64(i), To: &accounts[1].addr, Value: big.NewInt(1000), Gas: params.TxGas, GasPrice: b.BaseFee(), Data: nil}), signer, accounts[0].key)
|
||||
b.AddTx(tx)
|
||||
}))
|
||||
|
||||
blockNumber := api.BlockNumber()
|
||||
nextBlockNumber := (*hexutil.Big)(big.NewInt(int64(blockNumber + 1)))
|
||||
block, _ := api.GetBlockByNumber(context.Background(), rpc.BlockNumber(blockNumber), true)
|
||||
ts := block["timestamp"].(hexutil.Uint64)
|
||||
timestamp := ts + 10
|
||||
|
||||
var testSuite = []struct {
|
||||
blockNumber rpc.BlockNumber
|
||||
call TransactionArgs
|
||||
overrides StateOverride
|
||||
blockOverrides BlockOverrides
|
||||
expectErr error
|
||||
want uint64
|
||||
}{
|
||||
|
|
@ -678,9 +686,21 @@ func TestEstimateGas(t *testing.T) {
|
|||
},
|
||||
expectErr: core.ErrInsufficientFunds,
|
||||
},
|
||||
// with BlockOverrides
|
||||
{
|
||||
blockNumber: rpc.LatestBlockNumber,
|
||||
call: TransactionArgs{
|
||||
From: &accounts[0].addr,
|
||||
To: &accounts[1].addr,
|
||||
Value: (*hexutil.Big)(big.NewInt(1000)),
|
||||
},
|
||||
blockOverrides: BlockOverrides{Time: ×tamp, Number: nextBlockNumber},
|
||||
expectErr: nil,
|
||||
want: 21000,
|
||||
},
|
||||
}
|
||||
for i, tc := range testSuite {
|
||||
result, err := api.EstimateGas(context.Background(), tc.call, &rpc.BlockNumberOrHash{BlockNumber: &tc.blockNumber}, &tc.overrides)
|
||||
result, err := api.EstimateGas(context.Background(), tc.call, &rpc.BlockNumberOrHash{BlockNumber: &tc.blockNumber}, &tc.overrides, &tc.blockOverrides)
|
||||
if tc.expectErr != nil {
|
||||
if err == nil {
|
||||
t.Errorf("test %d: want error %v, have nothing", i, tc.expectErr)
|
||||
|
|
|
|||
|
|
@ -111,7 +111,7 @@ func (args *TransactionArgs) setDefaults(ctx context.Context, b Backend) error {
|
|||
AccessList: args.AccessList,
|
||||
}
|
||||
pendingBlockNr := rpc.BlockNumberOrHashWithNumber(rpc.PendingBlockNumber)
|
||||
estimated, err := DoEstimateGas(ctx, b, callArgs, pendingBlockNr, nil, b.RPCGasCap())
|
||||
estimated, err := DoEstimateGas(ctx, b, callArgs, pendingBlockNr, nil, nil, b.RPCGasCap())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue