From 76904e76d833e2e901e0030ddabb6a887fa281be Mon Sep 17 00:00:00 2001 From: Alex Sharov Date: Fri, 31 Jan 2025 23:16:18 +0700 Subject: [PATCH] `eth_estimateGas`: support historical blocks (#13635) seems we already support - but 1 check used "latest state reader" --- ChangeLog.md | 35 ++++++++++++++-------- turbo/jsonrpc/eth_call.go | 62 ++++++++++++++++++--------------------- 2 files changed, 51 insertions(+), 46 deletions(-) diff --git a/ChangeLog.md b/ChangeLog.md index 1d6ec2adff6..2d04c776c06 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -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: diff --git a/turbo/jsonrpc/eth_call.go b/turbo/jsonrpc/eth_call.go index 2167899b705..6796af3ac24 100644 --- a/turbo/jsonrpc/eth_call.go +++ b/turbo/jsonrpc/eth_call.go @@ -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 @@ -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") @@ -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)