Skip to content

Commit

Permalink
Update blockContext's time field for pending blocks to match current …
Browse files Browse the repository at this point in the history
…time. Enable eth_estimateGas and eth_call rpcs to utilize this
  • Loading branch information
ganeshvanahalli committed Jan 31, 2024
1 parent f04bb30 commit db458a3
Showing 1 changed file with 17 additions and 9 deletions.
26 changes: 17 additions & 9 deletions internal/ethapi/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -1075,7 +1075,7 @@ func (context *ChainContext) GetHeader(hash common.Hash, number uint64) *types.H
return header
}

func doCall(ctx context.Context, b Backend, args TransactionArgs, state *state.StateDB, header *types.Header, overrides *StateOverride, blockOverrides *BlockOverrides, timeout time.Duration, globalGasCap uint64, runMode core.MessageRunMode) (*core.ExecutionResult, error) {
func doCall(ctx context.Context, b Backend, args TransactionArgs, state *state.StateDB, header *types.Header, overrides *StateOverride, blockOverrides *BlockOverrides, timeout time.Duration, globalGasCap uint64, runMode core.MessageRunMode, blockNrOrHash *rpc.BlockNumberOrHash) (*core.ExecutionResult, error) {
if err := overrides.Apply(state); err != nil {
return nil, err
}
Expand All @@ -1098,6 +1098,14 @@ func doCall(ctx context.Context, b Backend, args TransactionArgs, state *state.S
}

blockCtx := core.NewEVMBlockContext(header, NewChainContext(ctx, b), nil)
if blockNrOrHash != nil &&
blockNrOrHash.BlockNumber != nil &&
*blockNrOrHash.BlockNumber == rpc.PendingBlockNumber {
blkTime := uint64(time.Now().Unix())
if blkTime > blockCtx.Time {
blockCtx.Time = blkTime
}
}
if blockOverrides != nil {
blockOverrides.Apply(&blockCtx)
}
Expand Down Expand Up @@ -1173,7 +1181,7 @@ func DoCall(ctx context.Context, b Backend, args TransactionArgs, blockNrOrHash
return nil, err
}

return doCall(ctx, b, args, state, header, overrides, blockOverrides, timeout, globalGasCap, runMode)
return doCall(ctx, b, args, state, header, overrides, blockOverrides, timeout, globalGasCap, runMode, &blockNrOrHash)
}

func newRevertError(result *core.ExecutionResult) *revertError {
Expand Down Expand Up @@ -1222,8 +1230,8 @@ func (e *revertError) ErrorData() interface{} {
// useful to execute and retrieve values.
func (s *BlockChainAPI) Call(ctx context.Context, args TransactionArgs, blockNrOrHash *rpc.BlockNumberOrHash, overrides *StateOverride, blockOverrides *BlockOverrides) (hexutil.Bytes, error) {
if blockNrOrHash == nil {
latest := rpc.BlockNumberOrHashWithNumber(rpc.LatestBlockNumber)
blockNrOrHash = &latest
pending := rpc.BlockNumberOrHashWithNumber(rpc.PendingBlockNumber)
blockNrOrHash = &pending
}
result, err := DoCall(ctx, s.b, args, *blockNrOrHash, overrides, blockOverrides, s.b.RPCEVMTimeout(), s.b.RPCGasCap(), core.MessageEthcallMode)
if err != nil {
Expand All @@ -1244,9 +1252,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, blockNrOrHash *rpc.BlockNumberOrHash) (bool, *core.ExecutionResult, error) {
args.Gas = (*hexutil.Uint64)(&gasLimit)
result, err := doCall(ctx, b, args, state, header, nil, nil, 0, gasCap, core.MessageGasEstimationMode)
result, err := doCall(ctx, b, args, state, header, nil, nil, 0, gasCap, core.MessageGasEstimationMode, blockNrOrHash)
if err != nil {
if errors.Is(err, core.ErrIntrinsicGas) {
return true, nil, nil // Special case, raise gas limit
Expand Down Expand Up @@ -1349,7 +1357,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, vanillaGasCap, hi)
failed, result, err := executeEstimate(ctx, b, args, state.Copy(), header, vanillaGasCap, hi, &blockNrOrHash)
if err != nil {
return 0, err
}
Expand Down Expand Up @@ -1377,7 +1385,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, &blockNrOrHash)
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.
Expand All @@ -1399,7 +1407,7 @@ func DoEstimateGas(ctx context.Context, b Backend, args TransactionArgs, blockNr
// 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) {
bNrOrHash := rpc.BlockNumberOrHashWithNumber(rpc.LatestBlockNumber)
bNrOrHash := rpc.BlockNumberOrHashWithNumber(rpc.PendingBlockNumber)
if blockNrOrHash != nil {
bNrOrHash = *blockNrOrHash
}
Expand Down

0 comments on commit db458a3

Please sign in to comment.