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 {
|
func (b *Block) EstimateGas(ctx context.Context, args struct {
|
||||||
Data ethapi.TransactionArgs
|
Data ethapi.TransactionArgs
|
||||||
}) (hexutil.Uint64, error) {
|
}) (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 {
|
type Pending struct {
|
||||||
|
|
@ -1276,7 +1276,7 @@ func (p *Pending) EstimateGas(ctx context.Context, args struct {
|
||||||
Data ethapi.TransactionArgs
|
Data ethapi.TransactionArgs
|
||||||
}) (hexutil.Uint64, error) {
|
}) (hexutil.Uint64, error) {
|
||||||
latestBlockNr := rpc.BlockNumberOrHashWithNumber(rpc.LatestBlockNumber)
|
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.
|
// 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
|
// 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
|
// 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.
|
// 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)
|
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 err != nil {
|
||||||
if errors.Is(err, core.ErrIntrinsicGas) {
|
if errors.Is(err, core.ErrIntrinsicGas) {
|
||||||
return true, nil, nil // Special case, raise gas limit
|
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
|
// 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 &
|
// there are unexpected failures. The gas limit is capped by both `args.Gas` (if non-nil &
|
||||||
// non-zero) and `gasCap` (if non-zero).
|
// 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
|
// Binary search the gas limit, as it may need to be higher than the amount used
|
||||||
var (
|
var (
|
||||||
lo uint64 // lowest-known gas limit where tx execution fails
|
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
|
// We first execute the transaction at the highest allowable gas limit, since if this fails we
|
||||||
// can return error immediately.
|
// 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 {
|
if err != nil {
|
||||||
return 0, err
|
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.
|
// range here is skewed to favor the low side.
|
||||||
mid = lo * 2
|
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 {
|
if err != nil {
|
||||||
// This should not happen under normal conditions since if we make it this far the
|
// This should not happen under normal conditions since if we make it this far the
|
||||||
// transaction had run without error at least once before.
|
// 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
|
// 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
|
// value is capped by both `args.Gas` (if non-nil & non-zero) and the backend's RPCGasCap
|
||||||
// configuration (if non-zero).
|
// 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)
|
bNrOrHash := rpc.BlockNumberOrHashWithNumber(rpc.LatestBlockNumber)
|
||||||
if blockNrOrHash != nil {
|
if blockNrOrHash != nil {
|
||||||
bNrOrHash = *blockNrOrHash
|
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 .
|
// 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)
|
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)
|
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 {
|
var testSuite = []struct {
|
||||||
blockNumber rpc.BlockNumber
|
blockNumber rpc.BlockNumber
|
||||||
call TransactionArgs
|
call TransactionArgs
|
||||||
overrides StateOverride
|
overrides StateOverride
|
||||||
|
blockOverrides BlockOverrides
|
||||||
expectErr error
|
expectErr error
|
||||||
want uint64
|
want uint64
|
||||||
}{
|
}{
|
||||||
|
|
@ -678,9 +686,21 @@ func TestEstimateGas(t *testing.T) {
|
||||||
},
|
},
|
||||||
expectErr: core.ErrInsufficientFunds,
|
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 {
|
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 tc.expectErr != nil {
|
||||||
if err == nil {
|
if err == nil {
|
||||||
t.Errorf("test %d: want error %v, have nothing", i, tc.expectErr)
|
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,
|
AccessList: args.AccessList,
|
||||||
}
|
}
|
||||||
pendingBlockNr := rpc.BlockNumberOrHashWithNumber(rpc.PendingBlockNumber)
|
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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue