github.com/amazechain/amc@v0.1.3/internal/api/api_backend.go (about) 1 // Copyright 2023 The AmazeChain Authors 2 // This file is part of the AmazeChain library. 3 // 4 // The AmazeChain library is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU Lesser General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // The AmazeChain library is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU Lesser General Public License for more details. 13 // 14 // You should have received a copy of the GNU Lesser General Public License 15 // along with the AmazeChain library. If not, see <http://www.gnu.org/licenses/>. 16 17 package api 18 19 import ( 20 "context" 21 "errors" 22 "fmt" 23 "github.com/amazechain/amc/accounts" 24 common2 "github.com/amazechain/amc/common" 25 types "github.com/amazechain/amc/common/block" 26 "github.com/amazechain/amc/common/transaction" 27 common "github.com/amazechain/amc/common/types" 28 "github.com/amazechain/amc/internal" 29 "github.com/amazechain/amc/internal/vm" 30 "github.com/amazechain/amc/internal/vm/evmtypes" 31 "github.com/amazechain/amc/modules/rawdb" 32 rpc "github.com/amazechain/amc/modules/rpc/jsonrpc" 33 "github.com/amazechain/amc/modules/state" 34 "github.com/amazechain/amc/params" 35 "github.com/holiman/uint256" 36 "github.com/ledgerwatch/erigon-lib/kv" 37 ) 38 39 // API implements ethapi.Backend for full nodes 40 //type API struct { 41 // extRPCEnabled bool 42 // allowUnprotectedTxs bool 43 // eth *node.Node 44 // //gpo *gasprice.Oracle 45 //} 46 47 // ChainConfig returns the active chain configuration. 48 func (b *API) ChainConfig() *params.ChainConfig { 49 return b.chainConfig 50 } 51 52 func (b *API) CurrentBlock() *types.Header { 53 return b.bc.CurrentBlock().Header().(*types.Header) 54 } 55 56 //func (b *API) SetHead(number uint64) { 57 // b.eth.handler.downloader.Cancel() 58 // b.bc.SetHead(number) 59 //} 60 61 func (b *API) HeaderByNumber(ctx context.Context, number rpc.BlockNumber) (*types.Header, error) { 62 // Pending block is only known by the miner 63 //if number == rpc.PendingBlockNumber { 64 // block := b.eth.Miner().PendingBlock() 65 // return block.Header(), nil 66 //} 67 // Otherwise resolve and return the block 68 if number == rpc.LatestBlockNumber { 69 return b.bc.CurrentBlock().Header().(*types.Header), nil 70 } 71 //if number == rpc.FinalizedBlockNumber { 72 // if !b.eth.Merger().TDDReached() { 73 // return nil, errors.New("'finalized' tag not supported on pre-merge network") 74 // } 75 // block := b.eth.blockchain.CurrentFinalBlock() 76 // if block != nil { 77 // return block, nil 78 // } 79 // return nil, errors.New("finalized block not found") 80 //} 81 //if number == rpc.SafeBlockNumber { 82 // if !b.eth.Merger().TDDReached() { 83 // return nil, errors.New("'safe' tag not supported on pre-merge network") 84 // } 85 // block := b.eth.blockchain.CurrentSafeBlock() 86 // if block != nil { 87 // return block, nil 88 // } 89 // return nil, errors.New("safe block not found") 90 //} 91 return b.bc.GetHeaderByNumber(uint256.NewInt(uint64(number.Int64()))).(*types.Header), nil 92 } 93 94 func (b *API) HeaderByNumberOrHash(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) (*types.Header, error) { 95 if blockNr, ok := blockNrOrHash.Number(); ok { 96 return b.HeaderByNumber(ctx, blockNr) 97 } 98 if hash, ok := blockNrOrHash.Hash(); ok { 99 header, _ := b.bc.GetHeaderByHash(hash) 100 if header == nil { 101 return nil, errors.New("header for hash not found") 102 } 103 if blockNrOrHash.RequireCanonical && b.bc.(*internal.BlockChain).GetCanonicalHash(header.Number64()) != hash { 104 return nil, errors.New("hash is not currently canonical") 105 } 106 return header.(*types.Header), nil 107 } 108 return nil, errors.New("invalid arguments; neither block nor hash specified") 109 } 110 111 func (b *API) HeaderByHash(ctx context.Context, hash common.Hash) (*types.Header, error) { 112 iHeader, _ := b.bc.GetHeaderByHash(hash) 113 return iHeader.(*types.Header), nil 114 } 115 116 func (b *API) BlockByNumber(ctx context.Context, number rpc.BlockNumber) (*types.Block, error) { 117 // Pending block is only known by the miner 118 //if number == rpc.PendingBlockNumber { 119 // block := b.minPendingBlock() 120 // return block, nil 121 //} 122 // Otherwise resolve and return the block 123 if number == rpc.LatestBlockNumber { 124 header := b.bc.CurrentBlock() 125 return b.bc.GetBlock(header.Hash(), header.Number64().Uint64()).(*types.Block), nil 126 } 127 //if number == rpc.FinalizedBlockNumber { 128 // if !b.eth.Merger().TDDReached() { 129 // return nil, errors.New("'finalized' tag not supported on pre-merge network") 130 // } 131 // header := b.eth.blockchain.CurrentFinalBlock() 132 // return b.eth.blockchain.GetBlock(header.Hash(), header.Number.Uint64()), nil 133 //} 134 //if number == rpc.SafeBlockNumber { 135 // //if !b.eth.Merger().TDDReached() { 136 // // return nil, errors.New("'safe' tag not supported on pre-merge network") 137 // //} 138 // header := b.BlockChain().CurrentBlock() 139 // return b.eth.blockchain.GetBlock(header.Hash(), header.Number.Uint64()), nil 140 //} 141 iBlock, err := b.bc.GetBlockByNumber(uint256.NewInt(uint64(number))) 142 if nil != err { 143 return nil, err 144 } 145 return iBlock.(*types.Block), nil 146 } 147 148 func (b *API) BlockByHash(ctx context.Context, hash common.Hash) (*types.Block, error) { 149 iBlock, _ := b.bc.GetBlockByHash(hash) 150 return iBlock.(*types.Block), nil 151 } 152 153 // GetBody returns body of a block. It does not resolve special block numbers. 154 //func (b *API) GetBody(ctx context.Context, hash common.Hash, number rpc.BlockNumber) (*types.Body, error) { 155 // if number < 0 || hash == (common.Hash{}) { 156 // return nil, errors.New("invalid arguments; expect hash and no special block numbers") 157 // } 158 // if body := b.bc.GetBody(hash); body != nil { 159 // return body, nil 160 // } 161 // return nil, errors.New("block body not found") 162 //} 163 164 func (b *API) BlockByNumberOrHash(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) (*types.Block, error) { 165 if blockNr, ok := blockNrOrHash.Number(); ok { 166 return b.BlockByNumber(ctx, blockNr) 167 } 168 if hash, ok := blockNrOrHash.Hash(); ok { 169 header, _ := b.bc.GetHeaderByHash(hash) 170 if header == nil { 171 return nil, errors.New("header for hash not found") 172 } 173 if blockNrOrHash.RequireCanonical && b.bc.(*internal.BlockChain).GetCanonicalHash(header.Number64()) != hash { 174 return nil, errors.New("hash is not currently canonical") 175 } 176 block := b.bc.GetBlock(hash, header.Number64().Uint64()) 177 if block == nil { 178 return nil, errors.New("header found, but block body is missing") 179 } 180 return block.(*types.Block), nil 181 } 182 return nil, errors.New("invalid arguments; neither block nor hash specified") 183 } 184 185 //func (b *API) PendingBlockAndReceipts() (*types.Block, types.Receipts) { 186 // return b.eth.miner.PendingBlockAndReceipts() 187 //} 188 189 //func (b *API) StateAndHeaderByNumber(ctx context.Context, number rpc.BlockNumber) (*state.StateDB, *types.Header, error) { 190 // // Pending state is only known by the miner 191 // if number == rpc.PendingBlockNumber { 192 // block, state := b.eth.miner.Pending() 193 // return state, block.Header(), nil 194 // } 195 // // Otherwise resolve the block number and return its state 196 // header, err := b.HeaderByNumber(ctx, number) 197 // if err != nil { 198 // return nil, nil, err 199 // } 200 // if header == nil { 201 // return nil, nil, errors.New("header not found") 202 // } 203 // stateDb, err := b.bc.StateAt(header.Root) 204 // return stateDb, header, err 205 //} 206 207 //func (b *API) StateAndHeaderByNumberOrHash(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) (*state.StateDB, *types.Header, error) { 208 // if blockNr, ok := blockNrOrHash.Number(); ok { 209 // return b.StateAndHeaderByNumber(ctx, blockNr) 210 // } 211 // if hash, ok := blockNrOrHash.Hash(); ok { 212 // header, err := b.HeaderByHash(ctx, hash) 213 // if err != nil { 214 // return nil, nil, err 215 // } 216 // if header == nil { 217 // return nil, nil, errors.New("header for hash not found") 218 // } 219 // if blockNrOrHash.RequireCanonical && b.eth.blockchain.GetCanonicalHash(header.Number.Uint64()) != hash { 220 // return nil, nil, errors.New("hash is not currently canonical") 221 // } 222 // stateDb, err := b.bc.StateAt(header.Root) 223 // return stateDb, header, err 224 // } 225 // return nil, nil, errors.New("invalid arguments; neither block nor hash specified") 226 //} 227 228 func (b *API) GetReceipts(ctx context.Context, hash common.Hash) (types.Receipts, error) { 229 return b.bc.GetReceipts(hash) 230 231 } 232 233 //func (b *API) GetLogs(ctx context.Context, hash common.Hash, number uint64) ([][]*types.Log, error) { 234 // return rawdb.ReadLogs(b.eth.chainDb, hash, number, b.ChainConfig()), nil 235 //} 236 237 func (b *API) GetTd(ctx context.Context, hash common.Hash) *uint256.Int { 238 if header, _ := b.bc.GetHeaderByHash(hash); header != nil { 239 return b.bc.GetTd(hash, header.Number64()) 240 } 241 return nil 242 } 243 244 func (b *API) GetEVM(ctx context.Context, msg *transaction.Message, state *state.IntraBlockState, header *types.Header, vmConfig *vm.Config) (*vm.EVM, func() error, error) { 245 if vmConfig == nil { 246 //vmConfig = b.bc.GetVMConfig() 247 vmConfig = &vm.Config{} 248 } 249 txContext := internal.NewEVMTxContext(msg) 250 getHeader := func(hash common.Hash, n uint64) *types.Header { 251 h := b.bc.GetHeader(hash, uint256.NewInt(n)) 252 return h.(*types.Header) 253 } 254 context := internal.NewEVMBlockContext(header, internal.GetHashFn(header, getHeader), b.bc.Engine(), nil) 255 return vm.NewEVM(context, txContext, state, b.bc.Config(), *vmConfig), state.Error, nil 256 } 257 258 //func (b *API) SubscribeRemovedLogsEvent(ch chan<- core.RemovedLogsEvent) event.Subscription { 259 // return b.bc.SubscribeRemovedLogsEvent(ch) 260 //} 261 262 //func (b *API) SubscribePendingLogsEvent(ch chan<- []*types.Log) event.Subscription { 263 // return b.eth.miner.SubscribePendingLogs(ch) 264 //} 265 // 266 //func (b *API) SubscribeChainEvent(ch chan<- core.ChainEvent) event.Subscription { 267 // return b.bc.SubscribeChainEvent(ch) 268 //} 269 // 270 //func (b *API) SubscribeChainHeadEvent(ch chan<- core.ChainHeadEvent) event.Subscription { 271 // return b.bc.SubscribeChainHeadEvent(ch) 272 //} 273 // 274 //func (b *API) SubscribeChainSideEvent(ch chan<- core.ChainSideEvent) event.Subscription { 275 // return b.bc.SubscribeChainSideEvent(ch) 276 //} 277 278 //func (b *API) SubscribeLogsEvent(ch chan<- []*types.Log) event.Subscription { 279 // return b.bc.SubscribeLogsEvent(ch) 280 //} 281 282 //func (b *API) SendTx(ctx context.Context, signedTx *types.Transaction) error { 283 // return b.eth.txPool.AddLocal(signedTx) 284 //} 285 // 286 //func (b *API) GetPoolTransactions() (types.Transactions, error) { 287 // pending := b.eth.txPool.Pending(false) 288 // var txs types.Transactions 289 // for _, batch := range pending { 290 // txs = append(txs, batch...) 291 // } 292 // return txs, nil 293 //} 294 // 295 //func (b *API) GetPoolTransaction(hash common.Hash) *types.Transaction { 296 // return b.eth.txPool.Get(hash) 297 //} 298 299 func (b *API) GetTransaction(ctx context.Context, txHash common.Hash) (*transaction.Transaction, common.Hash, uint64, uint64, error) { 300 var t *transaction.Transaction 301 var blockHash common.Hash 302 var index uint64 303 var err error 304 var blockNumber uint64 305 b.db.View(ctx, func(tx kv.Tx) error { 306 t, blockHash, blockNumber, index, err = rawdb.ReadTransactionByHash(tx, txHash) 307 return err 308 }) 309 return t, blockHash, blockNumber, index, nil 310 } 311 312 //func (b *API) GetPoolNonce(ctx context.Context, addr common.Address) (uint64, error) { 313 // return b.eth.txPool.Nonce(addr), nil 314 //} 315 // 316 //func (b *API) Stats() (pending int, queued int) { 317 // return b.eth.txPool.Stats() 318 //} 319 // 320 //func (b *API) TxPoolContent() (map[common.Address]types.Transactions, map[common.Address]types.Transactions) { 321 // return b.eth.TxPool().Content() 322 //} 323 // 324 //func (b *API) TxPoolContentFrom(addr common.Address) (types.Transactions, types.Transactions) { 325 // return b.eth.TxPool().ContentFrom(addr) 326 //} 327 // 328 //func (b *API) TxPool() *txpool.TxPool { 329 // return b.eth.TxPool() 330 //} 331 332 //func (b *API) SubscribeNewTxsEvent(ch chan<- core.NewTxsEvent) event.Subscription { 333 // return b.eth.TxPool().SubscribeNewTxsEvent(ch) 334 //} 335 // 336 //func (b *API) SyncProgress() ethereum.SyncProgress { 337 // return b.eth.Downloader().Progress() 338 //} 339 // 340 //func (b *API) SuggestGasTipCap(ctx context.Context) (*big.Int, error) { 341 // return b.gpo.SuggestTipCap(ctx) 342 //} 343 // 344 //func (b *API) FeeHistory(ctx context.Context, blockCount uint64, lastBlock rpc.BlockNumber, rewardPercentiles []float64) (firstBlock *big.Int, reward [][]*big.Int, baseFee []*big.Int, gasUsedRatio []float64, err error) { 345 // return b.gpo.FeeHistory(ctx, blockCount, lastBlock, rewardPercentiles) 346 //} 347 348 func (b *API) ChainDb() kv.RwDB { 349 return b.db 350 } 351 352 //func (b *API) EventMux() *event.TypeMux { 353 // return b.eth.EventMux() 354 //} 355 356 func (b *API) AccountManager() *accounts.Manager { 357 return b.accountManager 358 } 359 360 //func (b *API) ExtRPCEnabled() bool { 361 // return b.extRPCEnabled 362 //} 363 364 //func (b *API) UnprotectedAllowed() bool { 365 // return b.allowUnprotectedTxs 366 //} 367 368 //func (b *API) RPCGasCap() uint64 { 369 // return b.eth.config.RPCGasCap 370 //} 371 // 372 //func (b *API) RPCEVMTimeout() time.Duration { 373 // return b.eth.config.RPCEVMTimeout 374 //} 375 // 376 //func (b *API) RPCTxFeeCap() float64 { 377 // return b.eth.config.RPCTxFeeCap 378 //} 379 380 //func (b *API) BloomStatus() (uint64, uint64) { 381 // sections, _, _ := b.eth.bloomIndexer.Sections() 382 // return params.BloomBitsBlocks, sections 383 //} 384 // 385 //func (b *API) ServiceFilter(ctx context.Context, session *bloombits.MatcherSession) { 386 // for i := 0; i < bloomFilterThreads; i++ { 387 // go session.Multiplex(bloomRetrievalBatch, bloomRetrievalWait, b.eth.bloomRequests) 388 // } 389 //} 390 391 func (b *API) CurrentHeader() *types.Header { 392 return b.bc.CurrentBlock().Header().(*types.Header) 393 } 394 395 //func (b *API) Miner() *miner.Miner { 396 // return b..Miner().(*miner.Miner) 397 //} 398 399 //func (b *API) StateAtBlock(ctx context.Context, tx kv.Tx, block *types.Block /*reexec uint64, base *state.IntraBlockState, readOnly bool, preferDisk bool*/) (*state.IntraBlockState, tracers.StateReleaseFunc, error) { 400 // return b.bc.StateAt(tx, block.Number64().Uint64()), nil, nil 401 //} 402 // 403 //func (b *API) StateAtTransaction(ctx context.Context, tx kv.Tx, block *types.Block, txIndex int /*, reexec uint64*/) (*transaction.Message, evmtypes.BlockContext, *state.IntraBlockState, tracers.StateReleaseFunc, error) { 404 // return .StateAtTransaction(ctx, tx, block, txIndex /*, reexec*/) 405 //} 406 407 // stateAtTransaction returns the execution environment of a certain transaction. 408 func (eth *API) StateAtTransaction(ctx context.Context, dbTx kv.Tx, blk *types.Block, txIndex int) (*transaction.Message, evmtypes.BlockContext, *state.IntraBlockState, error) { 409 // Short circuit if it's genesis block. 410 if blk.Number64().Uint64() == 0 { 411 return nil, evmtypes.BlockContext{}, nil, errors.New("no transaction in genesis") 412 } 413 // Create the parent state database 414 parent := eth.BlockChain().GetBlock(blk.ParentHash(), blk.Number64().Uint64()-1).(*types.Block) 415 if parent == nil { 416 return nil, evmtypes.BlockContext{}, nil, fmt.Errorf("parent %#x not found", blk.ParentHash()) 417 } 418 // Lookup the statedb of parent block from the live database, 419 // otherwise regenerate it on the flight. 420 421 statedb, err := eth.StateAtBlock(ctx, dbTx, parent) 422 if err != nil { 423 return nil, evmtypes.BlockContext{}, nil, err 424 } 425 if txIndex == 0 && len(blk.Transactions()) == 0 { 426 return nil, evmtypes.BlockContext{}, statedb, nil 427 } 428 // Recompute transactions up to the target index. 429 signer := transaction.MakeSigner(eth.BlockChain().Config(), blk.Number64().ToBig()) 430 getHeader := func(hash common.Hash, number uint64) *types.Header { 431 return rawdb.ReadHeader(dbTx, hash, number) 432 } 433 blockContext := internal.NewEVMBlockContext(blk.Header().(*types.Header), internal.GetHashFn(blk.Header().(*types.Header), getHeader), eth.Engine(), nil) 434 vmenv := vm.NewEVM(blockContext, evmtypes.TxContext{}, statedb, eth.BlockChain().Config(), vm.Config{}) 435 rules := vmenv.ChainRules() 436 437 for idx, tx := range blk.Transactions() { 438 //// Assemble the transaction call message and return if the requested offset 439 //msg, _ := tx.AsMessage(signer, blk.BaseFee64()) 440 //txContext := internal.NewEVMTxContext(msg) 441 // 442 //if idx == txIndex { 443 // return msg, blockContext, statedb, release, nil 444 //} 445 //vmenv.Reset() 446 //// Not yet the searched for transaction, execute on top of the current state 447 //statedb.Prepare(tx.Hash(), blk.Hash(), idx) 448 //if _, err := internal.ApplyMessage(vmenv, msg, new(common.GasPool).AddGas(tx.Gas()), true, false); err != nil { 449 // return nil, evmtypes.BlockContext{}, nil, nil, fmt.Errorf("transaction %#x failed: %v", tx.Hash(), err) 450 //} 451 //// Ensure any modifications are committed to the state 452 //// Only delete empty objects if EIP158/161 (a.k.a Spurious Dragon) is in effect 453 //statedb.FinalizeTx(rules, ) 454 statedb.Prepare(tx.Hash(), blk.Hash(), idx) 455 456 // Assemble the transaction call message and return if the requested offset 457 msg, _ := tx.AsMessage(signer, blk.BaseFee64()) 458 if msg.FeeCap().IsZero() && eth.Engine() != nil { 459 syscall := func(contract common.Address, data []byte) ([]byte, error) { 460 return internal.SysCallContract(contract, data, *eth.BlockChain().Config(), statedb, blk.Header().(*types.Header), eth.Engine() /* constCall */) 461 } 462 msg.SetIsFree(eth.Engine().IsServiceTransaction(msg.From(), syscall)) 463 } 464 465 TxContext := internal.NewEVMTxContext(msg) 466 if idx == txIndex { 467 return &msg, blockContext, statedb, nil 468 } 469 vmenv.Reset(TxContext, statedb) 470 // Not yet the searched for transaction, execute on top of the current state 471 if _, err := internal.ApplyMessage(vmenv, msg, new(common2.GasPool).AddGas(tx.Gas()), true /* refunds */, false /* gasBailout */); err != nil { 472 return nil, evmtypes.BlockContext{}, nil, fmt.Errorf("transaction %x failed: %w", tx.Hash(), err) 473 } 474 // Ensure any modifications are committed to the state 475 // Only delete empty objects if EIP161 (part of Spurious Dragon) is in effect 476 _ = statedb.FinalizeTx(rules, statedb.GetStateReader().(*state.PlainState)) 477 478 if idx+1 == len(blk.Transactions()) { 479 // Return the state from evaluating all txs in the block, note no msg or TxContext in this case 480 return nil, blockContext, statedb, nil 481 } 482 } 483 return nil, evmtypes.BlockContext{}, nil, fmt.Errorf("transaction index %d out of range for block %#x", txIndex, blk.Hash()) 484 } 485 486 // StateAtBlock retrieves the state database associated with a certain block. 487 // If no state is locally available for the given block, a number of blocks 488 // are attempted to be reexecuted to generate the desired state. The optional 489 // base layer statedb can be provided which is regarded as the statedb of the 490 // parent block. 491 // 492 // An additional release function will be returned if the requested state is 493 // available. Release is expected to be invoked when the returned state is no longer needed. 494 // Its purpose is to prevent resource leaking. Though it can be noop in some cases. 495 // 496 // Parameters: 497 // - block: The block for which we want the state(state = block.Root) 498 // - reexec: The maximum number of blocks to reprocess trying to obtain the desired state 499 // - base: If the caller is tracing multiple blocks, the caller can provide the parent 500 // state continuously from the callsite. 501 // - readOnly: If true, then the live 'blockchain' state database is used. No mutation should 502 // be made from caller, e.g. perform Commit or other 'save-to-disk' changes. 503 // Otherwise, the trash generated by caller may be persisted permanently. 504 // - preferDisk: this arg can be used by the caller to signal that even though the 'base' is 505 // provided, it would be preferable to start from a fresh state, if we have it 506 // on disk. 507 func (eth *API) StateAtBlock(ctx context.Context, tx kv.Tx, blk *types.Block) (statedb *state.IntraBlockState, err error) { 508 var ( 509 //current *block.Block 510 //// database state.Database 511 //report = true 512 origin = blk.Number64().Uint64() 513 ) 514 // The state is only for reading purposes, check the state presence in 515 // live database. 516 //if readOnly { 517 // The state is available in live database, create a reference 518 // on top to prevent garbage collection and return a release 519 // function to deref it. 520 statedb = eth.BlockChain().StateAt(tx, origin) 521 //statedb.Database().TrieDB().Reference(block.Root(), common.Hash{}) 522 return statedb, nil 523 //} 524 //} 525 // The state is both for reading and writing, or it's unavailable in disk, 526 // try to construct/recover the state over an ephemeral trie.Database for 527 // isolating the live one. 528 //if base != nil { 529 // if preferDisk { 530 // // Create an ephemeral trie.Database for isolating the live one. Otherwise 531 // // the internal junks created by tracing will be persisted into the disk. 532 // database = state.NewDatabaseWithConfig(eth.chainDb, &trie.Config{Cache: 16}) 533 // if statedb, err = state.New(block.Root(), database, nil); err == nil { 534 // log.Info("Found disk backend for state trie", "root", block.Root(), "number", block.Number()) 535 // return statedb, noopReleaser, nil 536 // } 537 // } 538 // // The optional base statedb is given, mark the start point as parent block 539 // statedb, database, report = base, base.Database(), false 540 // current = eth.blockchain.GetBlock(block.ParentHash(), block.NumberU64()-1) 541 //} else { 542 // Otherwise, try to reexec blocks until we find a state or reach our limit 543 //current = block 544 545 // Create an ephemeral trie.Database for isolating the live one. Otherwise 546 // the internal junks created by tracing will be persisted into the disk. 547 // database = state.NewDatabaseWithConfig(eth.chainDb, &trie.Config{Cache: 16}) 548 549 // If we didn't check the live database, do check state over ephemeral database, 550 // otherwise we would rewind past a persisted block (specific corner case is 551 // chain tracing from the genesis). 552 //if !readOnly { 553 // statedb, err = state.New(current.Root(), database, nil) 554 // if err == nil { 555 // return statedb, noopReleaser, nil 556 // } 557 //} 558 //// Database does not have the state for the given block, try to regenerate 559 //for i := uint64(0); i < reexec; i++ { 560 // if err := ctx.Err(); err != nil { 561 // return nil, nil, err 562 // } 563 // if current.NumberU64() == 0 { 564 // return nil, nil, errors.New("genesis state is missing") 565 // } 566 // parent := eth.blockchain.GetBlock(current.ParentHash(), current.NumberU64()-1) 567 // if parent == nil { 568 // return nil, nil, fmt.Errorf("missing block %v %d", current.ParentHash(), current.NumberU64()-1) 569 // } 570 // current = parent 571 // 572 // statedb, err = state.New(current.Root(), database, nil) 573 // if err == nil { 574 // break 575 // } 576 //} 577 //if err != nil { 578 // switch err.(type) { 579 // case *trie.MissingNodeError: 580 // return nil, nil, fmt.Errorf("required historical state unavailable (reexec=%d)", reexec) 581 // default: 582 // return nil, nil, err 583 // } 584 //} 585 //} 586 // State is available at historical point, re-execute the blocks on top for 587 // the desired state. 588 //var ( 589 // start = time.Now() 590 // logged time.Time 591 // parent common.Hash 592 //) 593 //for current.NumberU64() < origin { 594 // if err := ctx.Err(); err != nil { 595 // return nil, nil, err 596 // } 597 // // Print progress logs if long enough time elapsed 598 // if time.Since(logged) > 8*time.Second && report { 599 // log.Info("Regenerating historical state", "block", current.NumberU64()+1, "target", origin, "remaining", origin-current.NumberU64()-1, "elapsed", time.Since(start)) 600 // logged = time.Now() 601 // } 602 // // Retrieve the next block to regenerate and process it 603 // next := current.NumberU64() + 1 604 // if current = eth.blockchain.GetBlockByNumber(next); current == nil { 605 // return nil, nil, fmt.Errorf("block #%d not found", next) 606 // } 607 // _, _, _, err := eth.blockchain.Processor().Process(current, statedb, vm.Config{}) 608 // if err != nil { 609 // return nil, nil, fmt.Errorf("processing block %d failed: %v", current.NumberU64(), err) 610 // } 611 // // Finalize the state so any modifications are written to the trie 612 // root, err := statedb.Commit(eth.blockchain.Config().IsEIP158(current.Number())) 613 // if err != nil { 614 // return nil, nil, fmt.Errorf("stateAtBlock commit failed, number %d root %v: %w", 615 // current.NumberU64(), current.Root().Hex(), err) 616 // } 617 // statedb, err = state.New(root, database, nil) 618 // if err != nil { 619 // return nil, nil, fmt.Errorf("state reset after block %d failed: %v", current.NumberU64(), err) 620 // } 621 // // Hold the state reference and also drop the parent state 622 // // to prevent accumulating too many nodes in memory. 623 // database.TrieDB().Reference(root, common.Hash{}) 624 // if parent != (common.Hash{}) { 625 // database.TrieDB().Dereference(parent) 626 // } 627 // parent = root 628 //} 629 //if report { 630 // nodes, imgs := database.TrieDB().Size() 631 // log.Info("Historical state regenerated", "block", current.NumberU64(), "elapsed", time.Since(start), "nodes", nodes, "preimages", imgs) 632 //} 633 //return statedb, func() { database.TrieDB().Dereference(block.Root()) }, nil 634 }