From 2e5ef4fb5a5559ca4f19c28782db2662cdccaf3f Mon Sep 17 00:00:00 2001 From: andri lim Date: Fri, 13 Dec 2024 13:21:20 +0700 Subject: [PATCH] Wire ForkedChainRef properly to TxPool (#2933) --- .../nodocker/engine/engine_env.nim | 7 +- .../nodocker/graphql/graphql_sim.nim | 9 +-- hive_integration/nodocker/pyspec/test_env.nim | 2 +- hive_integration/nodocker/rpc/test_env.nim | 9 +-- nimbus/beacon/beacon_engine.nim | 2 +- nimbus/core/tx_pool.nim | 21 ++---- nimbus/core/tx_pool/tx_desc.nim | 9 ++- nimbus/nimbus_execution_client.nim | 8 +- tests/test_engine_api.nim | 5 +- tests/test_graphql.nim | 73 ++++++++----------- tests/test_ledger.nim | 7 +- tests/test_rpc.nim | 4 +- tests/test_txpool2.nim | 10 +-- 13 files changed, 73 insertions(+), 93 deletions(-) diff --git a/hive_integration/nodocker/engine/engine_env.nim b/hive_integration/nodocker/engine/engine_env.nim index 00fc71b47..2bb1c9519 100644 --- a/hive_integration/nodocker/engine/engine_env.nim +++ b/hive_integration/nodocker/engine/engine_env.nim @@ -83,10 +83,9 @@ proc newEngineEnv*(conf: var NimbusConf, chainFile: string, enableAuth: bool): E let node = setupEthNode(conf, ctx) com = makeCom(conf) - head = com.db.getCanonicalHead().expect("canonical head exists") - chain = newForkedChain(com, head) + chain = ForkedChainRef.init(com) - let txPool = TxPoolRef.new(com) + let txPool = TxPoolRef.new(chain) node.addEthHandlerCapability( node.peerPool, @@ -95,7 +94,7 @@ proc newEngineEnv*(conf: var NimbusConf, chainFile: string, enableAuth: bool): E # txPool must be informed of active head # so it can know the latest account state - doAssert txPool.smartHead(head, chain) + doAssert txPool.smartHead(chain.latestHeader) var key: JwtSharedKey key.fromHex(jwtSecret).isOkOr: diff --git a/hive_integration/nodocker/graphql/graphql_sim.nim b/hive_integration/nodocker/graphql/graphql_sim.nim index d0f3f0b87..317883721 100644 --- a/hive_integration/nodocker/graphql/graphql_sim.nim +++ b/hive_integration/nodocker/graphql/graphql_sim.nim @@ -83,8 +83,9 @@ proc main() = conf.networkId, conf.networkParams ) - - let txPool = TxPoolRef.new(com) + chain = ForkedChainRef.init(com) + txPool = TxPoolRef.new(chain) + discard importRlpBlock(blocksFile, com) let ctx = setupGraphqlContext(com, ethNode, txPool) @@ -94,9 +95,7 @@ proc main() = # txPool must be informed of active head # so it can know the latest account state # e.g. "sendRawTransaction Nonce too low" case - let head = com.db.getCanonicalHead() - let chainRef = newForkedChain(com, head) - doAssert txPool.smartHead(head, chainRef) + doAssert txPool.smartHead(chain.latestHeader) for fileName in walkDirRec( caseFolder, yieldFilter = {pcFile,pcLinkToFile}): diff --git a/hive_integration/nodocker/pyspec/test_env.nim b/hive_integration/nodocker/pyspec/test_env.nim index 7d61c42b5..0aecd511b 100644 --- a/hive_integration/nodocker/pyspec/test_env.nim +++ b/hive_integration/nodocker/pyspec/test_env.nim @@ -52,7 +52,7 @@ proc setupELClient*(conf: ChainConfig, node: JsonNode): TestEnv = doAssert(head.blockHash == genesisHeader.blockHash) let - txPool = TxPoolRef.new(com) + txPool = TxPoolRef.new(chain) beaconEngine = BeaconEngineRef.new(txPool, chain) serverApi = newServerAPI(chain, txPool) rpcServer = newRpcHttpServer(["127.0.0.1:0"]) diff --git a/hive_integration/nodocker/rpc/test_env.nim b/hive_integration/nodocker/rpc/test_env.nim index c8cab0468..b03162ab6 100644 --- a/hive_integration/nodocker/rpc/test_env.nim +++ b/hive_integration/nodocker/rpc/test_env.nim @@ -87,15 +87,14 @@ proc setupEnv*(): TestEnv = manageAccounts(ethCtx, conf) - let head = com.db.getCanonicalHead().expect("canonical head exists") - let chainRef = newForkedChain(com, head) - let txPool = TxPoolRef.new(com) + let chain = ForkedChainRef.init(com) + let txPool = TxPoolRef.new(chain) # txPool must be informed of active head # so it can know the latest account state - doAssert txPool.smartHead(head, chainRef) + doAssert txPool.smartHead(chain.latestHeader) - let rpcServer = setupRpcServer(ethCtx, com, ethNode, txPool, conf, chainRef) + let rpcServer = setupRpcServer(ethCtx, com, ethNode, txPool, conf, chain) let rpcClient = newRpcHttpClient() waitFor rpcClient.connect("127.0.0.1", Port(8545), false) let stopServer = stopRpcHttpServer diff --git a/nimbus/beacon/beacon_engine.nim b/nimbus/beacon/beacon_engine.nim index a26128149..919e35fb2 100644 --- a/nimbus/beacon/beacon_engine.nim +++ b/nimbus/beacon/beacon_engine.nim @@ -160,7 +160,7 @@ proc generateExecutionBundle*(ben: BeaconEngineRef, if headBlock.blockHash != xp.head.blockHash: # reorg - discard xp.smartHead(headBlock, ben.chain) + discard xp.smartHead(headBlock) if pos.timestamp <= headBlock.timestamp: return err "timestamp must be strictly later than parent" diff --git a/nimbus/core/tx_pool.nim b/nimbus/core/tx_pool.nim index ad87958bb..abd264ff5 100644 --- a/nimbus/core/tx_pool.nim +++ b/nimbus/core/tx_pool.nim @@ -226,14 +226,11 @@ ## A piece of code using this pool architecture could look like as follows: ## :: ## # see also unit test examples, e.g. "Block packer tests" -## var db: CoreDbRef # to be initialised +## var chain: ForkedChainRef # to be initialised ## var txs: seq[Transaction] # to be initialised ## -## proc mineThatBlock(blk: EthBlock) # external function ## -## .. -## -## var xq = TxPoolRef.new(db) # initialise tx-pool +## var xq = TxPoolRef.new(chain) # initialise tx-pool ## .. ## ## xq.add(txs) # add transactions .. @@ -241,10 +238,6 @@ ## ## let newBlock = xq.assembleBlock # fetch current mining block ## -## .. -## mineThatBlock(newBlock) ... # external mining & signing process -## .. -## ## xp.smartHead(newBlock.header) # update pool, new insertion point ## ## @@ -252,7 +245,7 @@ ## --------------------- ## In the example, transactions are processed into buckets via `add()`. ## -## The `ethBlock()` directive assembles and retrieves a new block for mining +## The `assembleBlock()` directive assembles and retrieves a new block for mining ## derived from the current pool state. It invokes the block packer which ## accumulates txs from the `pending` buscket into the `packed` bucket which ## then go into the block. @@ -389,11 +382,11 @@ proc setHead(xp: TxPoolRef; val: Header) # Public constructor/destructor # ------------------------------------------------------------------------------ -proc new*(T: type TxPoolRef; com: CommonRef): T +proc new*(T: type TxPoolRef; chain: ForkedChainRef): T {.gcsafe,raises: [].} = ## Constructor, returns a new tx-pool descriptor. new result - result.init(com) + result.init(chain) # ------------------------------------------------------------------------------ # Public functions, task manager, pool actions serialiser @@ -422,7 +415,7 @@ proc add*(xp: TxPoolRef; tx: PooledTransaction; info = "") ## Variant of `add()` for a single transaction. xp.add(@[tx], info) -proc smartHead*(xp: TxPoolRef; pos: Header, chain: ForkedChainRef): bool +proc smartHead*(xp: TxPoolRef; pos: Header): bool {.gcsafe,raises: [CatchableError].} = ## This function moves the internal head cache (i.e. tx insertion point, ## vmState) and ponts it to a now block on the chain. @@ -434,7 +427,7 @@ proc smartHead*(xp: TxPoolRef; pos: Header, chain: ForkedChainRef): bool ## the internal head cache, the previously calculated actions will be ## applied. ## - let rcDiff = xp.headDiff(pos, chain) + let rcDiff = xp.headDiff(pos, xp.chain) if rcDiff.isOk: let changes = rcDiff.value diff --git a/nimbus/core/tx_pool/tx_desc.nim b/nimbus/core/tx_pool/tx_desc.nim index 1a9e4bfdc..e7af74315 100644 --- a/nimbus/core/tx_pool/tx_desc.nim +++ b/nimbus/core/tx_pool/tx_desc.nim @@ -20,6 +20,7 @@ import ../../evm/types, ../../db/ledger, ../../constants, + ../../core/chain/forked_chain, ../pow/header, ../eip4844, ../casper, @@ -56,6 +57,7 @@ type lifeTime*: times.Duration ## Maximum life time of a tx in the system priceBump*: uint ## Min precentage price when superseding + chain*: ForkedChainRef const txItemLifeTime = ##\ @@ -137,12 +139,12 @@ proc update(xp: TxPoolRef; parent: Header) = # Public functions, constructor # ------------------------------------------------------------------------------ -proc init*(xp: TxPoolRef; com: CommonRef) = +proc init*(xp: TxPoolRef; chain: ForkedChainRef) = ## Constructor, returns new tx-pool descriptor. xp.startDate = getTime().utc.toTime - let head = com.db.getCanonicalHead.expect("Canonicalhead exists") - xp.vmState = setupVMState(com, head) + let head = chain.latestHeader + xp.vmState = setupVMState(chain.com, head) xp.txDB = TxTabsRef.new xp.lifeTime = txItemLifeTime @@ -150,6 +152,7 @@ proc init*(xp: TxPoolRef; com: CommonRef) = xp.param.reset xp.param.flags = txPoolFlags + xp.chain = chain # ------------------------------------------------------------------------------ # Public functions diff --git a/nimbus/nimbus_execution_client.nim b/nimbus/nimbus_execution_client.nim index 8544106d2..478f69633 100644 --- a/nimbus/nimbus_execution_client.nim +++ b/nimbus/nimbus_execution_client.nim @@ -43,13 +43,13 @@ when defined(evmc_enabled): proc basicServices(nimbus: NimbusNode, conf: NimbusConf, com: CommonRef) = - nimbus.txPool = TxPoolRef.new(com) - + nimbus.chainRef = ForkedChainRef.init(com) + # txPool must be informed of active head # so it can know the latest account state # e.g. sender nonce, etc - nimbus.chainRef = ForkedChainRef.init(com) - doAssert nimbus.txPool.smartHead(nimbus.chainRef.latestHeader,nimbus.chainRef) + nimbus.txPool = TxPoolRef.new(nimbus.chainRef) + doAssert nimbus.txPool.smartHead(nimbus.chainRef.latestHeader) nimbus.beaconEngine = BeaconEngineRef.new(nimbus.txPool, nimbus.chainRef) diff --git a/tests/test_engine_api.nim b/tests/test_engine_api.nim index 371527977..e36924a17 100644 --- a/tests/test_engine_api.nim +++ b/tests/test_engine_api.nim @@ -89,13 +89,12 @@ proc setupEnv(envFork: HardFork = MergeFork, let com = setupCom(conf) - head = com.db.getCanonicalHead().expect("canonical head exists") chain = ForkedChainRef.init(com) - txPool = TxPoolRef.new(com) + txPool = TxPoolRef.new(chain) # txPool must be informed of active head # so it can know the latest account state - doAssert txPool.smartHead(head, chain) + doAssert txPool.smartHead(chain.latestHeader) let server = newRpcHttpServerWithParams("127.0.0.1:0").valueOr: diff --git a/tests/test_graphql.nim b/tests/test_graphql.nim index acf03c27d..fa69e8708 100644 --- a/tests/test_graphql.nim +++ b/tests/test_graphql.nim @@ -18,29 +18,23 @@ import ../nimbus/common/[common, context], ./test_helpers -type - EthBlock = object - header: BlockHeader - transactions: seq[Transaction] - uncles: seq[BlockHeader] - const caseFolder = "tests/graphql" dataFolder = "tests/fixtures/eth_tests/BlockchainTests/ValidBlocks/bcUncleTest" -proc toBlock(n: JsonNode, key: string): EthBlock = +proc toBlock(n: JsonNode, key: string): Block = let rlpBlob = hexToSeqByte(n[key].str) - rlp.decode(rlpBlob, EthBlock) + rlp.decode(rlpBlob, Block) -proc setupChain(): CommonRef = +proc setupChain(): ForkedChainRef = let config = ChainConfig( chainId : MainNet.ChainId, - byzantiumBlock : some(0.BlockNumber), - constantinopleBlock : some(0.BlockNumber), - petersburgBlock : some(0.BlockNumber), - istanbulBlock : some(0.BlockNumber), - muirGlacierBlock : some(0.BlockNumber), - berlinBlock : some(10.BlockNumber) + byzantiumBlock : Opt.some(0.BlockNumber), + constantinopleBlock : Opt.some(0.BlockNumber), + petersburgBlock : Opt.some(0.BlockNumber), + istanbulBlock : Opt.some(0.BlockNumber), + muirGlacierBlock : Opt.some(0.BlockNumber), + berlinBlock : Opt.some(10.BlockNumber) ) var jn = json.parseFile(dataFolder & "/oneUncle.json") @@ -58,48 +52,41 @@ proc setupChain(): CommonRef = mixHash : gen.header.mixHash, coinBase : gen.header.coinbase, timestamp : gen.header.timestamp, - baseFeePerGas: gen.header.fee + baseFeePerGas: gen.header.baseFeePerGas ) if not parseGenesisAlloc($(jn["pre"]), genesis.alloc): quit(QuitFailure) - let customNetwork = NetworkParams( - config: config, - genesis: genesis - ) - - let com = CommonRef.new( - newCoreDbRef DefaultDbMemory, nil, - CustomNet, - customNetwork - ) - - let blocks = jn["blocks"] - var headers: seq[BlockHeader] - var bodies: seq[BlockBody] - for n in blocks: - let ethBlock = n.toBlock("rlp") - headers.add ethBlock.header - bodies.add BlockBody( - transactions: ethBlock.transactions, - uncles: ethBlock.uncles + let + customNetwork = NetworkParams( + config: config, + genesis: genesis ) + com = CommonRef.new( + newCoreDbRef DefaultDbMemory, + taskpool = nil, + CustomNet, + customNetwork + ) + chain = ForkedChainRef.init(com) + blocks = jn["blocks"] - let chain = newChain(com) - let res = chain.persistBlocks(headers, bodies) - assert res.isOk(), res.error() + for n in blocks: + let blk = n.toBlock("rlp") + chain.importBlock(blk).isOkOr: + doAssert(false, error) - com + chain proc graphqlMain*() = let conf = makeTestConfig() ethCtx = newEthContext() ethNode = setupEthNode(conf, ethCtx, eth) - com = setupChain() - txPool = TxPoolRef.new(com) + chain = setupChain() + txPool = TxPoolRef.new(chain) - let ctx = setupGraphqlContext(com, ethNode, txPool) + let ctx = setupGraphqlContext(chain.com, ethNode, txPool) when isMainModule: ctx.main(caseFolder, purgeSchema = false) else: diff --git a/tests/test_ledger.nim b/tests/test_ledger.nim index 1901162e4..6ca9e7c09 100644 --- a/tests/test_ledger.nim +++ b/tests/test_ledger.nim @@ -101,6 +101,7 @@ proc initEnv(): TestEnv = conf.networkId, conf.networkParams ) + chain = newForkedChain(com, com.genesisHeader) TestEnv( com : com, @@ -108,8 +109,8 @@ proc initEnv(): TestEnv = vaultKey: privKey(hexPrivKey), nonce : 0'u64, chainId : conf.networkParams.config.chainId, - xp : TxPoolRef.new(com), - chain : newForkedChain(com, com.genesisHeader), + xp : TxPoolRef.new(chain), + chain : chain, ) func makeTx( @@ -334,7 +335,7 @@ proc runLedgerTransactionTests(noisy = true) = ) env.importBlock(Block.init(blk.header, body)) - check env.xp.smartHead(blk.header, env.chain) + check env.xp.smartHead(blk.header) for tx in body.transactions: env.txs.add tx diff --git a/tests/test_rpc.nim b/tests/test_rpc.nim index b1e592171..a3c91cfcb 100644 --- a/tests/test_rpc.nim +++ b/tests/test_rpc.nim @@ -245,11 +245,11 @@ proc rpcMain*() = let env = setupEnv(signer, ks2, ctx, com) chain = ForkedChainRef.init(com) - txPool = TxPoolRef.new(com) + txPool = TxPoolRef.new(chain) # txPool must be informed of active head # so it can know the latest account state - doAssert txPool.smartHead(chain.latestHeader, chain) + doAssert txPool.smartHead(chain.latestHeader) let server = newRpcHttpServerWithParams("127.0.0.1:0").valueOr: diff --git a/tests/test_txpool2.nim b/tests/test_txpool2.nim index 3db5be1a1..2907f2446 100644 --- a/tests/test_txpool2.nim +++ b/tests/test_txpool2.nim @@ -131,7 +131,7 @@ proc initEnv(envFork: HardFork): TestEnv = conf: conf, com: com, chain: chain, - xp: TxPoolRef.new(com), + xp: TxPoolRef.new(chain), vaultKey: privKey(vaultKeyHex), chainId: conf.networkParams.config.chainId, nonce: 0'u64, @@ -262,7 +262,7 @@ proc runTxPoolBlobhashTest() = tx4 = env.signTxWithNonce(tx3, AccountNonce(env.nonce - 2)) xp = env.xp - check xp.smartHead(blk.header, chain) + check xp.smartHead(blk.header) xp.add(PooledTransaction(tx: tx4)) check inPoolAndOk(xp, rlpHash(tx4)) == false @@ -318,7 +318,7 @@ proc runTxHeadDelta(noisy = true) = # Synchronise TxPool against new chain head, register txs differences. # In this particular case, these differences will simply flush the # packer bucket. - check xp.smartHead(blk.header, chain) + check xp.smartHead(blk.header) # Move TxPool chain head to new chain head and apply delta jobs check xp.nItems.staged == 0 @@ -362,7 +362,7 @@ proc runGetBlockBodyTest() = let blk = r.get.blk check env.chain.importBlock(blk).isOk parentHeader = blk.header - check env.xp.smartHead(parentHeader, env.chain) + check env.xp.smartHead(parentHeader) check blk.transactions.len == 2 test "TxPool create second block": @@ -387,7 +387,7 @@ proc runGetBlockBodyTest() = let blk = r.get.blk check env.chain.importBlock(blk).isOk currentHeader = blk.header - check env.xp.smartHead(currentHeader, env.chain) + check env.xp.smartHead(currentHeader) check blk.transactions.len == 3 let currHash = currentHeader.blockHash check env.chain.forkChoice(currHash, currHash).isOk