Skip to content

Commit

Permalink
eth_estimateGas: support historical blocks (#13635)
Browse files Browse the repository at this point in the history
seems we already support - but 1 check used "latest state reader"
  • Loading branch information
AskAlexSharov authored Jan 31, 2025
1 parent 1728ef1 commit 76904e7
Show file tree
Hide file tree
Showing 2 changed files with 51 additions and 46 deletions.
35 changes: 22 additions & 13 deletions ChangeLog.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,37 +6,46 @@ ChangeLog
### Breaking changes
- Reverts Optimize gas by default in eth_createAccessList #8337

### Improvements:

## v3.0.0-beta1

### Breaking changes

- Bor chains: enable our internal Consensus Layer by default (name: Astrid)
- The process should auto upgrade - in which case you may find that it starts creating new snapshots for checkpoints and milestones.
- This may however fail, as there are a number of potential edge cases. If this happens the process will likely stop with a failure message.
- In this situation you will need to do a clean sync, in which case the complete snapshot set will be downloaded and astrid will sync.
- If you want to prevent this and retain the old behaviour start erigon with --polygon.sync=false
- `eth_estimateGas`: StateOverrides and HistoricalBlocks support

### TODO

- milestone: https://github.com/erigontech/erigon/milestone/5
- milestone: https://github.com/erigontech/erigon/milestone/28
- Known problem:
- external CL support
- `erigon_getLatestLogs` not implemented

### Acknowledgements:

## v3.0.0-beta1

### Breaking changes

- Bor chains: enable our internal Consensus Layer by default (name: Astrid)
- The process should auto upgrade - in which case you may find that it starts creating new snapshots for checkpoints
and milestones.
- This may however fail, as there are a number of potential edge cases. If this happens the process will likely stop
with a failure message.
- In this situation you will need to do a clean sync, in which case the complete snapshot set will be downloaded and
astrid will sync.
- If you want to prevent this and retain the old behaviour start erigon with --polygon.sync=false

### Acknowledgements:

## v3.0.0-alpha7

### Improvements:

- Faster eth_getTransactionReceipt with "txn-granularity cache" in https://github.com/erigontech/erigon/pull/13134 and "executing only 1 txn" https://github.com/erigontech/erigon/pull/12424
- Faster eth_getTransactionReceipt with "txn-granularity cache" in https://github.com/erigontech/erigon/pull/13134 and "
executing only 1 txn" https://github.com/erigontech/erigon/pull/12424
- Return PrunedError when trying to read unavailable historical data in https://github.com/erigontech/erigon/pull/13014

### Fixes:

- Fix trace_block returning "insufficient funds" (Issues #12525 and similar) with standalone rpcdaemon in https://github.com/erigontech/erigon/pull/13129

- Fix trace_block returning "insufficient funds" (Issues #12525 and similar) with standalone rpcdaemon
in https://github.com/erigontech/erigon/pull/13129

### Acknowledgements:

Expand Down
62 changes: 29 additions & 33 deletions turbo/jsonrpc/eth_call.go
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,35 @@ func (api *APIImpl) EstimateGas(ctx context.Context, argsOrNil *ethapi2.CallArgs
}
defer dbtx.Rollback()

chainConfig, err := api.chainConfig(ctx, dbtx)
if err != nil {
return 0, err
}
engine := api.engine()

latestCanBlockNumber, latestCanHash, isLatest, err := rpchelper.GetCanonicalBlockNumber(ctx, latestNumOrHash, dbtx, api._blockReader, api.filters) // DoCall cannot be executed on non-canonical blocks
if err != nil {
return 0, err
}

// try and get the block from the lru cache first then try DB before failing
block := api.tryBlockFromLru(latestCanHash)
if block == nil {
block, err = api.blockWithSenders(ctx, dbtx, latestCanHash, latestCanBlockNumber)
if err != nil {
return 0, err
}
}
if block == nil {
return 0, errors.New("could not find latest block in cache or db")
}

txNumsReader := rawdbv3.TxNums.WithCustomReadTxNumFunc(freezeblocks.ReadTxNumFuncFromBlockReader(ctx, api._blockReader))
stateReader, err := rpchelper.CreateStateReaderFromBlockNumber(ctx, dbtx, txNumsReader, latestCanBlockNumber, isLatest, 0, api.stateCache, chainConfig.ChainName)
if err != nil {
return 0, err
}

// Binary search the gas requirement, as it may be higher than the amount used
var (
lo = params.TxGas - 1
Expand Down Expand Up @@ -206,11 +235,6 @@ func (api *APIImpl) EstimateGas(ctx context.Context, argsOrNil *ethapi2.CallArgs
}
// Recap the highest gas limit with account's available balance.
if feeCap.Sign() != 0 {
cacheView, err := api.stateCache.View(ctx, dbtx)
if err != nil {
return 0, err
}
stateReader := rpchelper.CreateLatestCachedStateReader(cacheView, dbtx)
state := state.New(stateReader)
if state == nil {
return 0, errors.New("can't get the current state")
Expand Down Expand Up @@ -248,34 +272,6 @@ func (api *APIImpl) EstimateGas(ctx context.Context, argsOrNil *ethapi2.CallArgs
}
gasCap = hi

chainConfig, err := api.chainConfig(ctx, dbtx)
if err != nil {
return 0, err
}
engine := api.engine()

latestCanBlockNumber, latestCanHash, isLatest, err := rpchelper.GetCanonicalBlockNumber(ctx, latestNumOrHash, dbtx, api._blockReader, api.filters) // DoCall cannot be executed on non-canonical blocks
if err != nil {
return 0, err
}

// try and get the block from the lru cache first then try DB before failing
block := api.tryBlockFromLru(latestCanHash)
if block == nil {
block, err = api.blockWithSenders(ctx, dbtx, latestCanHash, latestCanBlockNumber)
if err != nil {
return 0, err
}
}
if block == nil {
return 0, errors.New("could not find latest block in cache or db")
}

txNumsReader := rawdbv3.TxNums.WithCustomReadTxNumFunc(freezeblocks.ReadTxNumFuncFromBlockReader(ctx, api._blockReader))
stateReader, err := rpchelper.CreateStateReaderFromBlockNumber(ctx, dbtx, txNumsReader, latestCanBlockNumber, isLatest, 0, api.stateCache, chainConfig.ChainName)
if err != nil {
return 0, err
}
header := block.HeaderNoCopy()

caller, err := transactions.NewReusableCaller(engine, stateReader, overrides, header, args, api.GasCap, latestNumOrHash, dbtx, api._blockReader, chainConfig, api.evmCallTimeout)
Expand Down

0 comments on commit 76904e7

Please sign in to comment.