Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[API] Interleaved state override to EstimateGas #86

Merged
merged 2 commits into from
Sep 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 7 additions & 4 deletions api/api_ethereum.go
Original file line number Diff line number Diff line change
Expand Up @@ -693,7 +693,7 @@ func (api *EthereumAPI) Call(ctx context.Context, args EthTransactionArgs, block

// EstimateGas returns an estimate of the amount of gas needed to execute the
// given transaction against the current pending block.
func (api *EthereumAPI) EstimateGas(ctx context.Context, args EthTransactionArgs, blockNrOrHash *rpc.BlockNumberOrHash) (hexutil.Uint64, error) {
func (api *EthereumAPI) EstimateGas(ctx context.Context, args EthTransactionArgs, blockNrOrHash *rpc.BlockNumberOrHash, overrides *EthStateOverride) (hexutil.Uint64, error) {
bcAPI := api.publicBlockChainAPI.b
bNrOrHash := rpc.NewBlockNumberOrHashWithNumber(rpc.LatestBlockNumber)
if blockNrOrHash != nil {
Expand All @@ -703,7 +703,7 @@ func (api *EthereumAPI) EstimateGas(ctx context.Context, args EthTransactionArgs
if rpcGasCap := bcAPI.RPCGasCap(); rpcGasCap != nil {
gasCap = rpcGasCap.Uint64()
}
return EthDoEstimateGas(ctx, bcAPI, args, bNrOrHash, gasCap)
return EthDoEstimateGas(ctx, bcAPI, args, bNrOrHash, overrides, gasCap)
}

// GetBlockTransactionCountByNumber returns the number of transactions in the block with the given block number.
Expand Down Expand Up @@ -1434,7 +1434,7 @@ func EthDoCall(ctx context.Context, b Backend, args EthTransactionArgs, blockNrO
return result, nil
}

func EthDoEstimateGas(ctx context.Context, b Backend, args EthTransactionArgs, blockNrOrHash rpc.BlockNumberOrHash, gasCap uint64) (hexutil.Uint64, error) {
func EthDoEstimateGas(ctx context.Context, b Backend, args EthTransactionArgs, blockNrOrHash rpc.BlockNumberOrHash, overrides *EthStateOverride, gasCap uint64) (hexutil.Uint64, error) {
// Use zero address if sender unspecified.
if args.From == nil {
args.From = new(common.Address)
Expand All @@ -1459,11 +1459,14 @@ func EthDoEstimateGas(ctx context.Context, b Backend, args EthTransactionArgs, b
if err != nil {
return 0, err
}
if err := overrides.Apply(state); err != nil {
return 0, err
}
balance := state.GetBalance(*args.From) // from can't be nil

executable := func(gas uint64) (bool, *blockchain.ExecutionResult, error) {
args.Gas = (*hexutil.Uint64)(&gas)
result, err := EthDoCall(ctx, b, args, rpc.NewBlockNumberOrHashWithNumber(rpc.LatestBlockNumber), nil, b.RPCEVMTimeout(), gasCap)
result, err := EthDoCall(ctx, b, args, blockNrOrHash, overrides, b.RPCEVMTimeout(), gasCap)
if err != nil {
if errors.Is(err, blockchain.ErrIntrinsicGas) {
return true, nil, nil // Special case, raise gas limit
Expand Down
2 changes: 1 addition & 1 deletion api/api_ethereum_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2600,6 +2600,6 @@ func TestEthereumAPI_EstimateGas(t *testing.T) {
defer mockCtrl.Finish()

testEstimateGas(t, mockBackend, func(args EthTransactionArgs) (hexutil.Uint64, error) {
return api.EstimateGas(context.Background(), args, nil)
return api.EstimateGas(context.Background(), args, nil, nil)
})
}
17 changes: 12 additions & 5 deletions api/api_public_blockchain.go
Original file line number Diff line number Diff line change
Expand Up @@ -400,32 +400,39 @@ func (s *PublicBlockChainAPI) EstimateComputationCost(ctx context.Context, args
}

// EstimateGas returns an estimate of the amount of gas needed to execute the given transaction against the latest block.
func (s *PublicBlockChainAPI) EstimateGas(ctx context.Context, args CallArgs) (hexutil.Uint64, error) {
func (s *PublicBlockChainAPI) EstimateGas(ctx context.Context, args CallArgs, blockNrOrHash *rpc.BlockNumberOrHash, overrides *EthStateOverride) (hexutil.Uint64, error) {
gasCap := uint64(0)
if rpcGasCap := s.b.RPCGasCap(); rpcGasCap != nil {
gasCap = rpcGasCap.Uint64()
}
return DoEstimateGas(ctx, s.b, args, s.b.RPCEVMTimeout(), new(big.Int).SetUint64(gasCap))
bNrOrHash := rpc.NewBlockNumberOrHashWithNumber(rpc.LatestBlockNumber)
if blockNrOrHash != nil {
bNrOrHash = *blockNrOrHash
}
return DoEstimateGas(ctx, s.b, args, bNrOrHash, overrides, s.b.RPCEVMTimeout(), new(big.Int).SetUint64(gasCap))
}

func DoEstimateGas(ctx context.Context, b Backend, args CallArgs, timeout time.Duration, gasCap *big.Int) (hexutil.Uint64, error) {
func DoEstimateGas(ctx context.Context, b Backend, args CallArgs, blockNrOrHash rpc.BlockNumberOrHash, overrides *EthStateOverride, timeout time.Duration, gasCap *big.Int) (hexutil.Uint64, error) {
var feeCap *big.Int
if args.GasPrice != nil {
feeCap = args.GasPrice.ToInt()
} else {
feeCap = common.Big0
}

state, _, err := b.StateAndHeaderByNumber(ctx, rpc.LatestBlockNumber)
state, _, err := b.StateAndHeaderByNumberOrHash(ctx, blockNrOrHash)
if err != nil {
return 0, err
}
if err := overrides.Apply(state); err != nil {
return 0, err
}
balance := state.GetBalance(args.From) // from can't be nil

// Create a helper to check if a gas allowance results in an executable transaction
executable := func(gas uint64) (bool, *blockchain.ExecutionResult, error) {
args.Gas = hexutil.Uint64(gas)
result, _, err := DoCall(ctx, b, args, rpc.NewBlockNumberOrHashWithNumber(rpc.LatestBlockNumber), vm.Config{ComputationCostLimit: params.OpcodeComputationCostLimitInfinite}, timeout, gasCap)
result, _, err := DoCall(ctx, b, args, blockNrOrHash, vm.Config{ComputationCostLimit: params.OpcodeComputationCostLimitInfinite}, timeout, gasCap)
if err != nil {
if errors.Is(err, blockchain.ErrIntrinsicGas) {
return true, nil, nil // Special case, raise gas limit
Expand Down
2 changes: 1 addition & 1 deletion api/api_public_blockchain_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,6 @@ func TestKaiaAPI_EstimateGas(t *testing.T) {
if ethArgs.Value != nil {
args.Value = *ethArgs.Value
}
return api.EstimateGas(context.Background(), args)
return api.EstimateGas(context.Background(), args, nil, nil)
})
}
2 changes: 1 addition & 1 deletion api/tx_args.go
Original file line number Diff line number Diff line change
Expand Up @@ -702,7 +702,7 @@ func (args *EthTransactionArgs) setDefaults(ctx context.Context, b Backend) erro
if rpcGasCap := b.RPCGasCap(); rpcGasCap != nil {
gasCap = rpcGasCap.Uint64()
}
estimated, err := EthDoEstimateGas(ctx, b, callArgs, pendingBlockNr, gasCap)
estimated, err := EthDoEstimateGas(ctx, b, callArgs, pendingBlockNr, nil, gasCap)
if err != nil {
return err
}
Expand Down
4 changes: 2 additions & 2 deletions console/web3ext/web3ext.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,8 +71,8 @@ web3._extend({
new web3._extend.Method({
name: 'estimateGas',
call: 'eth_estimateGas',
params: 2,
inputFormatter: [web3._extend.formatters.inputCallFormatter, web3._extend.formatters.inputBlockNumberFormatter],
params: 3,
inputFormatter: [web3._extend.formatters.inputCallFormatter, web3._extend.formatters.inputBlockNumberFormatter, null],
outputFormatter: web3._extend.utils.toDecimal
}),
new web3._extend.Method({
Expand Down
Loading