From 7e59eddb70ecca82bb19c44fa5cbe511026c34d9 Mon Sep 17 00:00:00 2001 From: ak88 Date: Mon, 8 Jan 2024 01:44:41 +0100 Subject: [PATCH] Squashed commit of the following: MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 4460f7a72d4fd0302b37a1037f29e05390ebae7d Author: Ben Adams Date: Sun Jan 7 10:28:24 2024 +0000 Pass `readonly struct` `BlockExecutionContext` via `in` (#6469) commit 74743cd14d0413d0d0265b6c1d301e194776e3e7 Author: Marek Moraczyński Date: Sat Jan 6 12:59:02 2024 +0100 Changed post-merge condition in MultiSyncModeSelector (#6433) commit 9b5a3f2988036b616730e07a7c59afe278cbfa24 Author: Klaudia Jazgar <67744705+kjazgar@users.noreply.github.com> Date: Fri Jan 5 20:14:37 2024 +0100 Feature/debug get bad blocks (#3838) Co-authored-by: lukasz.rozmej Co-authored-by: Marc commit 7d2958fab0992e764dc1ee9b9b1d4c49a2e1f6a6 Author: Marek Moraczyński Date: Fri Jan 5 14:43:35 2024 +0100 Handling exceptions during signatures recovery (#6461) commit 4550bfcfa9ea571b584a7cabfee3c61de581904b Author: Ben Adams Date: Fri Jan 5 13:10:47 2024 +0000 Write out IByteBuffer before it is released (#6459) commit 6c9309c50a8eace6557295fcacd05f213a43349f Author: Ruben Buniatyan Date: Thu Jan 4 23:14:46 2024 +0100 Fix solution builds and add debug build configuration (#6456) commit 4cb9a947d891a15f15423cd42c02135915f0cddb Author: Kamil Chodoła <43241881+kamilchodola@users.noreply.github.com> Date: Thu Jan 4 20:54:08 2024 +0100 Bump version to 1.26.0-unstable (#6443) * Bump version to 1.25.0 * Change already to 1.26.0 --------- Co-authored-by: Kamil Chodoła commit 61245df9eb30451b0396b564998161efd9733882 Author: Ben Adams Date: Thu Jan 4 14:43:09 2024 +0000 Use the empty account cache as cache (#6452) * Use the empty account cache as cache * Rename commit a7cbe276778d730f25cec8bf7a4f9f17c3f95236 Author: Marcin Sobczak <77129288+marcindsobczak@users.noreply.github.com> Date: Thu Jan 4 10:32:12 2024 +0100 Fix `BlobGasUsed` and `ExcessBlobGas` in Cancun genesis (#6446) * try hotfix * try with default 0 * another approach * try * requested simplification commit ab3711c26965ff8881e3af9e5a3b38baf4d2e1cb Author: Ahmad Bitar <33181301+smartprogrammer93@users.noreply.github.com> Date: Thu Jan 4 11:28:31 2024 +0300 fix debug build (#6447) commit 95d966ce8ae673baadeac0ab121a688317c47a59 Author: Kamil Chodoła <43241881+kamilchodola@users.noreply.github.com> Date: Wed Jan 3 17:46:02 2024 +0100 Fix checkout paths (#6451) Co-authored-by: Kamil Chodoła commit 805f942e85c2b33fa99c54c9ce0fa50e4421bd65 Author: Kamil Chodoła <43241881+kamilchodola@users.noreply.github.com> Date: Wed Jan 3 17:10:18 2024 +0100 Fix permission on build files (#6450) Co-authored-by: Kamil Chodoła commit 299d3c64b804c0cedb854776bc1272d8241325bf Author: Kamil Chodoła <43241881+kamilchodola@users.noreply.github.com> Date: Wed Jan 3 16:34:52 2024 +0100 Fix Release Action (#6449) commit 0e6ffe7e66bbdc38212dd9666fc274366390fbb9 Author: Ben Adams Date: Wed Jan 3 08:02:40 2024 +0000 Return to NoGCRegion now runtime bug is fixed (#6381) * Return to NoGCRegion now runtime bug is fixed * Remove other comment commit 292acdd821ba21d3a8ec6f46bbc70c86a4f9300e Author: Ben Adams Date: Wed Jan 3 07:01:54 2024 +0000 Speed up trie node traversal (#6436) commit d3c0443da526f4aa25360ff1935271308fc1929b Author: Ben Adams Date: Wed Jan 3 06:59:20 2024 +0000 Gas price estimation as float (#6445) commit cbc3e67b7db3d425b3d8eb8c9a447040487ac0df Author: Amirul Ashraf Date: Tue Jan 2 22:16:21 2024 +0800 Fix/flush on snap finish (#6444) * Flush on snap finish * Added test commit a3caae8918e56bbe4b0a2d25d1b9d3da525051e3 Author: Ruben Buniatyan Date: Tue Jan 2 12:25:31 2024 +0100 Update packages (#6437) * Update packages * Update packages * Update line endings commit 7bb1a4dfa819456887699051cdd3816b925ca63e Author: Ruben Buniatyan Date: Tue Jan 2 01:06:10 2024 +0100 Update file header (#6442) commit 6f2698c124d1d8e8cc24024f9f61ee001e12b790 Author: Nikita Mescheryakov Date: Mon Jan 1 21:13:10 2024 +0300 Optimism canyon (#6374) * Receipts * Create2Deployer * Fix null value * Refactor 1559 * Canyon eip 1559 * Refactor * MarkAsFailed * Revert TxProcessor * Fix tests * Fix tests * decoder * Fix configs * base-goerli regolith timestamp * Fix elasticity multiplier * Check tx type commit 344c56831902fc3869bb0b242893439064906257 Author: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon Jan 1 11:00:30 2024 +0100 Updating Fast Sync config files (#6441) Co-authored-by: LukaszRozmej commit 087b06ac3592494b1f8f8180f30a6aba7df0886f Author: Ben Adams Date: Fri Dec 29 23:49:48 2023 +0000 Remove db throttling (#6438) commit c4767a44ca6dae1d81d7ea5e0e0241593a450c55 Author: Ahmad Bitar <33181301+smartprogrammer93@users.noreply.github.com> Date: Fri Dec 29 19:18:11 2023 +0300 [Fix] Potential fix to missing tx index sometimes (related to reorgs) (#6422) * fixes * update unit tests to reflect reorg --------- Co-authored-by: Ahmad Mazen Radwan Bitar commit 6a9c76d25cc649df15906570bc9396148bb6d6b6 Author: Marek Moraczyński Date: Fri Dec 29 16:44:14 2023 +0100 Fixed FinalTotalDifficulty based on genesis (#6435) * Fixed FinalTotalDifficulty based on genesis * Fix whitespace * Fix test setup commit f601ede7c71c1ff503d2c741c023a724d5ed69b9 Author: Ben Adams Date: Fri Dec 29 05:11:17 2023 +0000 Make CappedArray readonly (#6434) commit 075365ab7563db9ec2c104c7b568407d0f0ad152 Author: Ben Adams Date: Thu Dec 28 23:08:43 2023 +0000 Reduce lock contention (#6417) * Reduce TxPool lock contention * Reduce lock contention with added spice * Use McsLock for LruCache * Whitespace * Calculate hashes in parallel * Name clash with extension and invalid round trip check * Add tests * Fix * Use monitor signalling to wake up sleeping threads * Additional comments * throttle db read/writes * Less contention on the priority lock * Whitespace * Boost forkchoice commit d8debc6fb93d9dc4c3745bda8afb44e266ab1ff3 Author: Lautaro Emanuel <31224949+emlautarom1@users.noreply.github.com> Date: Thu Dec 28 16:37:17 2023 -0300 Fix node restart on `gnosis-cancun` (#6423) * first draft * add more things * fix metric * fix * add tests * add serializers and tests * simplification * adjust network and rpc tests * post-merge fixes * enable eth68 * adjust tests * fix * Use blob gas instead of count * Shuffle 4844 constants, add GetMaxBlobsPerBlock * Replace `Keccak` with `Hash256` * fix PeerInfoExtensions * fix StateSyncDownloader * fix GetNodeDataTrieNodeRecovery * improve switching capabilities * `WasProcessed = true` for Genesis `BlockInfo` * Add tests --------- Co-authored-by: Marcin Sobczak Co-authored-by: Ruben Buniatyan Co-authored-by: Alexey Osipov commit 2a66d4189fa791c5261f519bf7f59bfa5579f6f6 Author: Amirul Ashraf Date: Thu Dec 28 22:22:28 2023 +0800 Fix metric not working (#6432) commit c81d577cadd8b3407e4a00c84e4401c33329209c Author: Marek Moraczyński Date: Thu Dec 28 14:49:34 2023 +0100 Fix TotalDifficulty for post-merge networks in genesis (#6407) * Fix TotalDifficulty for post-merge devnets * Fix whitespaces * test fixes commit dd613afea546ffc24d28742e641b1d5ad52a00f9 Author: Marcin Sobczak <77129288+marcindsobczak@users.noreply.github.com> Date: Thu Dec 28 14:46:09 2023 +0100 Update configs tests, add FastSyncCatchUpHeightDelta for holesky (#6431) * adjust config tests * add high FastSyncCatchUpHeightDelta for holesky * fix one more test commit fe807bbb65a72f0ff23bcf2afc4eaaff954295be Author: Marcin Sobczak <77129288+marcindsobczak@users.noreply.github.com> Date: Thu Dec 28 11:54:35 2023 +0100 Enable blob txs support in goerli configs (#6430) * enable blob support for goerli * add config test commit 2402d5a911072f76f6554b420057bba94d6dcad9 Author: Lukasz Rozmej Date: Thu Dec 28 11:40:47 2023 +0100 fix memory guard and slice (#6396) * fix memory guard and slice * Trim or pad variable length bytes (as Geth does) * fix ArgumentException * whitespace commit ada8cc91af3266f3ee562848c250616cb3ee1a81 Author: Amirul Ashraf Date: Thu Dec 28 17:39:11 2023 +0800 Reimplement KestrelMetricServer (#6429) commit be008123ceddc2acf3fff5ead410a4504cb376c6 Author: Amirul Ashraf Date: Thu Dec 28 17:13:06 2023 +0800 Feature/exit on blocknumber (#6428) * Exit on block number * Some minor log commit 2ad33ccaf1a47824fa1d413f193c7338e8a4011a Author: Ahmad Bitar <33181301+smartprogrammer93@users.noreply.github.com> Date: Thu Dec 28 11:45:40 2023 +0300 [Cancun]{Spec} Goerli config and fix for `ChainSpecBasedSpecProvider` (#6409) * init * format * format * Empty-Commit * make tests granular * Remove timestamp consecutive block transition. Keep first timestamp transition past block. * change approach to test fix * fixes * fix future fork info * Fully separate block forks from timtestamp ones (#6419) --------- Co-authored-by: lukasz.rozmej Co-authored-by: MarekM25 Co-authored-by: Alexey commit 0ad72e9fc89937d8ce7cc4a318e4fd1136c03d1e Author: Ben Adams Date: Wed Dec 27 16:39:14 2023 +0000 Don't use exceptions for flow control during sync (#6425) * Don't use exceptions for flow control during sync * Fix header caching * Fix time reporting * Better progress time commit 7e6c34064f19f54d23f9e2f71886320845aee013 Author: Ben Adams Date: Wed Dec 27 09:39:01 2023 +0000 Update Chain size test (#6426) commit 8fa3263c51233e0e4da2256d6498c9dd9955c0f8 Author: Marcin Sobczak <77129288+marcindsobczak@users.noreply.github.com> Date: Wed Dec 27 10:26:37 2023 +0100 Blob txs reorgs (#6254) * add column for processed txs * add feature of returning keys only * adjust BlobTxStorage * cosmetics * add logic for storing processed blob txs and removing finalized * rename * fix * add tests * cosmetics * add sender recovery for reorganized blob txs * requested change * one more place * postmerge fix * fix saving of processed blob txs * optimize saving processed txs * readd blob support config * fix whitespace * fix test * fix tests parallelism? * add more logs * fix blob txs metric * refactor BlobTxStorage * optimize collecting blob txs from processed block * Create IBlobTxStorage and separate blob specific methods from ITxStorage * use batch when cleaning processed txs db * fix * fix file encoding * fix init when blob support or reorgs disabled * fix signing test txs * add regression test * fix tests * one more regression test * post-merge fix * add test for readding reorganized blob txs * improve test * one more check in test * Remove unnecessary list Sleep -> Task in test * cosmetic * compress 3 bool flags to 1 enum * fix file encoding * fix whitespaces --------- Co-authored-by: lukasz.rozmej commit f3ed968e3428aedc84d617b53287e7036487b002 Author: Lautaro Emanuel <31224949+emlautarom1@users.noreply.github.com> Date: Tue Dec 26 11:09:44 2023 -0300 Upgrade Kute (#6366) * Introduce filter limits - Filters can include optional limits * Report progress at the start - Fixes progress not updating * Initial response validator - Verifies that the response does not contain an 'error' field * Include more examples of filters and limits * Perform validation outside time measurement * Add 'TracerValidator' - Responses can be stored into a new file * Document 'TracerValidator' - Disabled by default - Response tracing is ignored in dry mode * Make config help text more consistent * Capitalize * Change name of tracing to verbose * Update README.md * Use `-r|--responses` to store responses * Invert condition - Append if file exists - Create one if not * Make 'IJsonRpcValidator' take also request into consideration * Validate 'NewPayload' responses using custom strategy - 'TracerValidator' is no longer a decorator * Separate 'ResponseTracer' from Validator - Tracer should be independent - Add File and Null tracers - Simplify services setup * Validate and trace batch responses * Add TickSucceeded * Add temp sampleSize * Tick succeeded on batches too * Use 'CompleteReservoir' for sampling - Removes need for hack/magic numbers * Remove whitespace * Remove `IAuth` from `NullJsonRpcSubmitter` --------- Co-authored-by: Kamil Chodoła <43241881+kamilchodola@users.noreply.github.com> Co-authored-by: Kamil Chodoła commit 1df2cf4d140641e67c700d417fef152ea3e5ece9 Author: Ben Adams Date: Tue Dec 26 12:01:45 2023 +0000 Remove duplicate calls to FindHeader in eth_getLogs (#6421) * Remove duplicate calls to FindHeader in eth_getLogs * Check cancellation token * Fix tests due to params change commit 3fa5ba5d2bbe7f2ec6894207455409dfe1ad8df0 Author: Ben Adams Date: Tue Dec 26 08:50:53 2023 +0000 Remove Duplicate call to TryGetPendingTransaction in RPC (#6420) commit 02221a9096530d45ab2d7b74c21bb768574ff8cc Author: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon Dec 25 12:58:27 2023 +0100 Updating Fast Sync config files (#6416) Co-authored-by: LukaszRozmej commit 716a79159b3e934eec228ef42563365f260de140 Author: Amirul Ashraf Date: Mon Dec 25 07:40:00 2023 +0800 Fix double write during full pruning (#6415) * Fix double write during full pruning * Missed a null condition commit 1c0ce55086aa170ac98d22eea594be87864f4a52 Author: Ben Adams Date: Sun Dec 24 15:26:38 2023 +0000 RateLimiter: Remove unneeded async statemachine (#6418) * RateLimiter: Remove unneeded async statemachine * Fix test commit 3bd89b3656d06393c330512adcf1aa5511df7c66 Author: Ruben Buniatyan Date: Sat Dec 23 01:37:38 2023 +0100 Fix POSDAO tests workflow (#6414) commit aa6800ca414eab5966fa9b8e2df9c610ef5206bd Author: Ben Adams Date: Fri Dec 22 10:53:34 2023 +0000 Fix unbounded memory growth in DoubleArrayConverter (#6412) * Fix unbounded memory growth in DoubleArrayConverter * Whitespace commit bb1840fa6bf129b77ff89f08e4e45d7fa1ab455b Author: Ben Adams Date: Fri Dec 22 02:58:40 2023 +0000 Throw less expensive exceptions from Evm (#6406) * Reduce Evm eceptions * Less exceptions * Less exceptions * Whitespace * Remove signed benchmark * Moar commit b86383f1768f9b2ef9059f547a4880cc704498c1 Author: Ben Adams Date: Fri Dec 22 00:20:27 2023 +0000 Increase regex cache size (#6408) commit 90416e528c5aaebc5bdb454a209799c7265b1a65 Author: Ruben Buniatyan Date: Thu Dec 21 23:57:12 2023 +0100 Remove Nethermind launcher build (#6404) commit 536e2f78de881104ed2bf0d404d2ecc9d8772d5b Author: Ruben Buniatyan Date: Thu Dec 21 21:08:48 2023 +0100 Revise and improve diagnostics Dockerfile (#6398) commit 76c73a13f852a43937c1d589bb83bb22e778319b Author: Ayman Bouchareb Date: Thu Dec 21 14:09:54 2023 +0100 Add new RPC methods debug_getRawBlock, debug_getRawReceipts, debug_getRawHeader, debug_getRawTransaction (#6368) * Fix peer header when no peers to show (#4411) * Fix peer header when no peers to show * Only order once * Better fix maybe * Applying lukasz suggestion * Revise product version (#4322) * Replace submodules with packages (#4374) * Add optional argument Address in parity_pendingTransactions (#4413) * Add enough projects to build benchmark runner (#4431) * Fix peer header when no peers to show (#4411) * Fix peer header when no peers to show * Only order once * Better fix maybe * Applying lukasz suggestion * Revise product version (#4322) * Replace submodules with packages (#4374) * Add optional argument Address in parity_pendingTransactions (#4413) * Add enough projects to build benchmark runner (#4431) * Fix develop branch * Exit early on error (#4220) Exit early on error in steps except for step with "mustInitialize" set to false. * Fix peer header when no peers to show (#4411) * Fix peer header when no peers to show * Only order once * Better fix maybe * Applying lukasz suggestion * Revise product version (#4322) * Replace submodules with packages (#4374) * Add optional argument Address in parity_pendingTransactions (#4413) * Add enough projects to build benchmark runner (#4431) * Fix develop branch * Exit early on error (#4220) Exit early on error in steps except for step with "mustInitialize" set to false. * Changes to BlockForRPC class : Ignored Author field in JsonDeserialization * Changes to TransactionForRPC class : Ignored 'data' field in JsonDeserialization if null or empty, and Assigned ChainId from Signature.ChainId if tx.ChainId is null * Changes to [DebugBridge, IDebugBridge] files : Added utility functions to get Transactions and Receipts per block * Changes to [DebugRpcModule, IDebugRpcModule] files : Added missing debug Functions [getRawBlock, getRawBlockHeader, getRawReceipts, getRawTransaction] * Changes to TransactionForRPC class : Ignored 'data' field in JsonDeserialization if null or empty, and Assigned ChainId from Signature.ChainId if tx.ChainId is null * Changes to ProofConverter class : stripped leading zeros from value field, and stripped leading zeros while keeping lenght even in key * Changes to [DebugRpcModule, IDebugRpcModule] files : new Debug functions only accept Keccak inputs * Changes to [DebugRpcModule, IDebugRpcModule] files : fix getRawReceipts * Changes to [Rlp, ReceiptStorageDecoder] files : added parameterless constructor to RSD, and added a selector method to decorder in RLP * Changes to [ReceiptMessageDecoder] files : added IRlpObjectDecoder interface to RMD * Changes to [Rlp] files : changed Decoder selection strategy to depend on custom attribute * Changes to [DebugRpcModule] files : added custom RlpBehaviour to Rlp.Encode in debug_getRawReceipts * Changes to [EthRpcModule.cs] files : deactivated optimization for eth_createaAccessList * fix merge issues * fix failing tests * fixed ws removed added file * fix merge issue * revert script changes * remove non related changes from PR --------- Co-authored-by: smartprogrammer93 <33181301+smartprogrammer93@users.noreply.github.com> Co-authored-by: Ruben Buniatyan Co-authored-by: Alexey Co-authored-by: DCeleda Co-authored-by: Amirul Ashraf commit 5ac809f33587500b1b78e8a58eefe2e06c7277e7 Author: Kamil Chodoła <43241881+kamilchodola@users.noreply.github.com> Date: Wed Dec 20 12:26:20 2023 +0100 Add extra docker compose pull to ensure latest image (#6400) * Add extra docker compose pull to ensure latest image * Revert back to sedge run command commit 0415bcf397a8e14fc396096f295b41d230a34d94 Author: Marcin Sobczak <77129288+marcindsobczak@users.noreply.github.com> Date: Wed Dec 20 09:45:11 2023 +0100 Fix signing transactions in tests (#6397) * fix signing test txs * add regression test * fix tests * one more regression test commit 7f62918c54ff4fcd0b8048851908c36377581c64 Author: Marek Moraczyński Date: Tue Dec 19 22:55:37 2023 +0100 Add PivotUpdator tests (#6399) * Add PivotUpdater tests, cosmetic rename * whitespaces * revert class name change commit 7ef0b6b60d91ef8b126427f92ca043e1662fe1bc Author: Ruben Buniatyan Date: Tue Dec 19 17:22:02 2023 +0100 Revise and update workflows (#6388) commit f15eedc6a7dae2dba2c4409e03ed837b39c400af Author: Lukasz Rozmej Date: Tue Dec 19 13:59:30 2023 +0100 make ParityTraceActionFromReplayJsonConverter recursive (#6394) * make ParityTraceActionFromReplayJsonConverter recursive * Add test commit 13b85a3f5e364c7f7341a5e6f6a93ed44ff40f77 Author: Amirul Ashraf Date: Tue Dec 19 12:09:20 2023 +0800 Refactor/minor worldstate cleanup (#6385) * Remove address by storage * Make it clear what it it used for serving by hash * Fix test * TrieNodeRlpStore commit 482bc435d4f879a4f0fe9c3faa426608ed9841b8 Author: Ruben Buniatyan Date: Mon Dec 18 22:45:08 2023 +0100 Fix package path (#6389) commit 18e37da87a174c7473c09a550f3d71f7bd693d9b Author: Alexey Date: Tue Dec 19 00:31:18 2023 +0300 Properly activate timestamp fork (#6386) * Activate timestamp fork even if block matches block only fork * Remove duplication commit 97fb56c08ab3ed93fdcf65b18e1a7e60a9ff1d0c Author: ak88 Date: Mon Dec 18 17:03:01 2023 +0100 holesky networkId -> name (#6370) commit 5d5dda6ee3d8db40dec1ae5168cb4e70bcbbf070 Author: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Date: Sun Dec 17 22:41:51 2023 +0100 Updating Fast Sync config files (#6383) Co-authored-by: LukaszRozmej commit 355e3fe91b04e878f409abdce2fedd287b6b31a4 Author: Ben Adams Date: Fri Dec 15 12:00:32 2023 +0000 Use leaveOpen: false on StreamPipeReaderOptions (#6379) commit b8b0a8e7a89cfb008161e781a06954b04a02b0b2 Author: Ben Adams Date: Fri Dec 15 11:39:26 2023 +0000 Make methods static and/or readonly (and others) (#6376) * Make methods static and/or readonly * Hashtable Contains+Add -> Add * Hashtable Contains+Remove -> Remove * Span Fill(0) -> Clear() * Fix Ethereum tests * Whitespace * Fix * Fix benchmarks * Remove unneeded methods commit 9bed546f39c57f69f0495c77dd4b9d4966c8b86a Author: Ben Adams Date: Fri Dec 15 11:38:59 2023 +0000 Use RecyclableMemoryStream for MemoryStreams (#6371) * Use RecyclableMemoryStream for MemoryStreams * Use regular MemoryStream for recorder * leaveOpen: true * Use for recorder also commit bce32446bb9e06bc2d5d91e007e05c33a8f19670 Author: Ben Adams Date: Thu Dec 14 20:12:27 2023 +0000 Apply max responseBodySize correctly (#6372) * Apply max responseBodySize correctly * Fix log commit 36c117113f7ae8306f75dce2103199f3860188ce Author: Ben Adams Date: Thu Dec 14 15:02:18 2023 +0000 Reduce ResettableDictionary lookups (#6373) commit f62468e336ffb81dafbcdcde9cc7ba028941a9dc Author: Ben Adams Date: Thu Dec 14 12:23:12 2023 +0000 Use TryGetValue to halve Dictionary lookups (#6352) * Use TryGetValue to halve Dictionary lookups * fixes * Use CollectionsMarshal.GetValueRefOrAddDefault when appropriate * Re add comment * Missed one * Fix weird check commit 2749c160e47289e2c3ae4e15306fe90a74db21a1 Author: Jorge Mederos <46798594+jmederosalvarado@users.noreply.github.com> Date: Thu Dec 14 12:58:33 2023 +0100 Fix / Add OP configs (#6364) * Fix DisableGCOnNewPayload for op-goerli * Add archive configs for all op chains * Sepolia & goerli-config * Add rest * Change BaseDBPath and LogFileName for archive config * Add base-sepolia --------- Co-authored-by: Nikita Mescheryakov commit 82afd0fe078c8e085aef13ecc0eb71eeacfa22f9 Author: Marcin Sobczak <77129288+marcindsobczak@users.noreply.github.com> Date: Thu Dec 14 09:21:10 2023 +0100 Broadcast local txs only if MaxFeePerGas is equal at least 70% of current base fee (#6350) * limit initial broadcast * add BaseFeeThreshold to ChainHeadInfoProvider * simplify broadcaster * add simple test * make BaseFeeThreshold configurable in TxPoolConfig * remove from ChainHeadInfoProvider * more tests * cosmetic * cosmetic * fix posdao tests * Update src/Nethermind/Nethermind.TxPool/ITxPoolConfig.cs Co-authored-by: Ruben Buniatyan --------- Co-authored-by: Ruben Buniatyan commit 1bbd8b29baaebec78fff1446ed64d302747dc7f4 Author: Ben Adams Date: Thu Dec 14 01:56:46 2023 +0000 NewPayloadV3 required fields json deserialization (#6362) * Hive fixes * invalid params * Wrong place * Only return for engine_newPayloadV3 * Make ExecutionPayloadV3.BlobGasUsed and ExcessBlobGas required * small cleanup * overload instead of override * Revert "overload instead of override" This reverts commit 27c36863e82cd75b6c327da2d101e730f69724cd. * Revert "Revert "overload instead of override"" This reverts commit ab921f950d1c62de245a43522b9065aa411cebd4. * Revert "Revert "Revert "overload instead of override""" This reverts commit 782200e45de662d5eb33748c29f3e6206f59fc94. --------- Co-authored-by: lukasz.rozmej commit 33528df760fcc7369058470d50f545b2839b5bc5 Author: Ruben Buniatyan Date: Wed Dec 13 21:23:17 2023 +0100 Revise docs generation (#6361) commit dd88db60d764ee2bd27b5b134b6f8f7bfe59cde1 Author: Ben Adams Date: Wed Dec 13 18:08:46 2023 +0000 Serialize Json direct to Http PipeWriter (#6369) * Serialize Json direct to Http PipeWriter * Whitespace commit 7a768f7f6e85c6e09e8a732486c297f33a98781c Author: Pioua <136521243+dzizazda@users.noreply.github.com> Date: Wed Dec 13 14:42:33 2023 +0100 chore(src/Nethermind): typo fix (#6363) * typo fix * typo fix * typo fix * typo fix commit af048996208289bffb19a0b633aab8ab5879a1f0 Author: yanziseeker <153156292+AdventureSeeker987@users.noreply.github.com> Date: Wed Dec 13 21:42:19 2023 +0800 fix: typos (#6360) commit 0a3a694fe88ef4240516d615d3dbbb908de8ca33 Author: Lukasz Rozmej Date: Tue Dec 12 15:05:53 2023 +0100 Skip signature only for TxType.DepositTx (#6349) Co-authored-by: Nikita Mescheryakov commit 7cc83582c80eb5d275a1ead782ca130ce0f162b9 Author: Ben Adams Date: Tue Dec 12 11:06:00 2023 +0000 Make fields readonly (#6356) commit 2af3d8f6ac59539ef2f17d7354c580c3151cf6f2 Author: Ben Adams Date: Tue Dec 12 11:05:53 2023 +0000 Use length checks rather than .Any() (#6357) commit 9df511b27545f833b141ea2ee5153209fcb36305 Author: Ben Adams Date: Tue Dec 12 11:05:37 2023 +0000 Simplify null checks (#6355) commit 6744d21a6cda51b0d1829739b6cddbe72e125d39 Author: Ben Adams Date: Tue Dec 12 03:04:55 2023 +0000 Use runtime throw helpers (#6348) commit 1040052d4d33e9e53523a2ae0ab4b8059d3e7620 Author: Ben Adams Date: Mon Dec 11 21:31:32 2023 +0000 Fix excessive timer allocation in rate limiter (#6354) * Fix excessive timer allocation in rate limiter * Looser match * Rename to currentNextSlot commit 600b7b67825aca66c803b746f1ab72e1e1d2d4f5 Author: Ben Adams Date: Mon Dec 11 21:08:11 2023 +0000 Fix KeyExists leak (#6353) commit c284fa1ee3da9aa06a529bd81ee9a825ebdefd57 Author: Lukasz Rozmej Date: Mon Dec 11 16:55:56 2023 +0100 Fix json rpc missing parameter check (#6351) * Fix json rpc missing parameter check * Add more check when enumerating * Modify tests to serialize null on net_version commit 1242ecd79a72bf0ff42928c0cd46a5322cf71765 Author: Kamil Chodoła <43241881+kamilchodola@users.noreply.github.com> Date: Mon Dec 11 12:40:12 2023 +0100 Kch/rlp refactor (#6343) * RLP refactor/cleanup (#6243) Co-authored-by: Kamil Chodoła * Remove allowLeadingZeros * Fix Keccak -> Hash256 * fix for optimism --------- Co-authored-by: Kamil Chodoła Co-authored-by: Marcin Sobczak commit 7c61e14657beadf8a54ec2ac1268974385b9a3ae Author: Jorge Mederos <46798594+jmederosalvarado@users.noreply.github.com> Date: Mon Dec 11 09:51:34 2023 +0100 Disable networking on OpStack configs (#6334) * Disable networking on OpStack configs * Disable networking config for OP Stack testnets commit 82b816a5bc334793b13deb4833e413a01791b642 Author: Ben Adams Date: Mon Dec 11 07:59:43 2023 +0000 Improved Json Serialization (#6152) * System.Text.Json.Serialization * System.Text.Deserialization * Fixes * lint * Fixes * Fix * Fixes * Fixes * Lint * Fix invalid Json * u8 * Fixes * Fixes * Fix * Don't go via exception for short reverts * Fix * Fix * Multi-doc batch * Lint * Merge conflict * Fixes * Lint * Fix tests * Fix test * Tidy up * Turn of sync IO * Async * Don't double Advance * Async wrapper stream use * Fix build break * Merge issues * Compile issues * File scoped namespaces * Formatting * Merge fixes * Test Merge fixes * lang ver * Purge Newtonsoft * Fix evm tests * Fix parentBeaconBlockRootString serialization * Change type for serialization * Ignore syncing * Capitalised bools are invalid json * Capitalised bools are invalid json * Fix merge conflict * Fix data serialization * Fix trace entry * Merge conflicts * Formatting * Missed merge * whitespace * Fix EthereumTests Json * Ethereum tests * Fix hex prefix * Fix difficultly test * Add serializer options * Fix abi tests * Merge conflict * Feedback * revert to previous * Remove Netwonsoft * cosmetics * Pipeline Json responses * Merge fixes * Whitespace * fix test * Send multiple messages * Optional stream closing * Case insensitive * Update Nethermind.Serialization.Json.csproj * Whitespace * Update JavaScriptObjectConverter.cs * Feedback * Undo AI * Put orders back * Feedback * Whitespace * Use static constructor * Remove irrelevant test parameter * Add BigIntegerConverterTests back * Use FrozenDictionary * Deserialize collection to ArrayPoolList using GetArrayLength for initial capacity. Dispose it later. Move WhiteSpace to utf8 * simplify * Throw more explicit exception * name cleanup * Merge conflicts * Merge conflict * Add comments * more comments * Consolidate Disposable * Use FrozenDictionary for RpcLookup * Case sensitive * Be consistent on parsing type * Use correct type in test * Optimizations * Optimizations * Optimize * Optimize * Vectorize FromUtf8 hex * Optimization * Optimize * Parallel deserialize * Revert "Parallel deserialize" This reverts commit 94b08e3a69d9d6129440c30cb1e850d5345b9c0b. * Use using * Fix check * Parallel deserialize * Increase parallelThreshold * Use correct length * Cache Reflection Parameters * Fix tracing output * Match geth output * Turn AllowSynchronousIO back on * Revert object type arrays --------- Co-authored-by: lukasz.rozmej commit 3f2f149249b4dfa25a3e56c82fc48622b13a0d54 Author: Lukasz Rozmej Date: Mon Dec 11 08:58:09 2023 +0100 Unify js types, use typed arrays everywhere + long for slice parameters (#6319) commit 874cd73f0efbff23cdce9163f7294765f815752d Author: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Date: Sun Dec 10 13:01:29 2023 +0100 Updating Fast Sync config files (#6347) Co-authored-by: LukaszRozmej commit baff6319547a2a384cd439e65e8381246ca8bd36 Author: ak88 Date: Fri Dec 8 19:37:16 2023 +0100 Fix/check withdrawal bodiessyncfeed (#6345) * Also check withdrawals before insertion * refactor * refactor * unit tests * unnecessary using commit 0e0e35e4692dfc0852c7bf11d448a8ea9d7a8a0b Author: Amirul Ashraf Date: Fri Dec 8 20:41:55 2023 +0800 Refactor/state cleanup (#6260) * Separate statedb initialization from blockchain initialization * Minor cleanup * World state factory * Don't take db provider or trie store * Use state reader instead of trie store for full state finder * Unify and use property * Boundary watcher * Dont need this anymore * Minor comment * Reducing change * Missed a setter * Some tests * Fix build * Fix build * Addressing comment * Minor comment adjustment * Fix startup block tree fixer missed --- .editorconfig | 26 +- .github/workflows/build-solutions.yml | 32 +-- .github/workflows/release.yml | 6 +- CONTRIBUTING.md | 2 +- src/Nethermind/Chains/base-goerli.json | 15 +- src/Nethermind/Chains/base-sepolia.json | 13 +- src/Nethermind/Chains/op-goerli.json | 11 +- src/Nethermind/Chains/op-sepolia.json | 15 +- src/Nethermind/Directory.Build.props | 2 +- src/Nethermind/Directory.Packages.props | 30 +-- .../UserOperationSubscribeTests.cs | 2 +- .../AABlockProducerTransactionsExecutor.cs | 8 +- .../Nethermind.Api/IApiWithStores.cs | 2 + src/Nethermind/Nethermind.Api/IInitConfig.cs | 6 +- src/Nethermind/Nethermind.Api/InitConfig.cs | 1 + .../Nethermind.Api/NethermindApi.cs | 2 + .../BlockProducerBaseTests.BaseFee.cs | 12 +- .../Receipts/PersistentReceiptStorageTests.cs | 49 +++- .../Nethermind.Blockchain/BlockTree.cs | 4 + .../Blocks/BlockStore.cs | 28 +- .../Blocks/IBlockStore.cs | 2 + .../ReceiptCanonicalityMonitor.cs | 10 +- .../Receipts/IReceiptStorage.cs | 6 + .../Receipts/InMemoryReceiptStorage.cs | 16 +- .../Receipts/NullReceiptStorage.cs | 4 + .../Receipts/PersistentReceiptStorage.cs | 4 + .../TargetAdjustedGasLimitCalculatorTests.cs | 2 +- .../Eip1559GasLimitAdjuster.cs | 2 +- ...sor.BlockProductionTransactionsExecutor.cs | 6 +- ...sor.BlockValidationTransactionsExecutor.cs | 6 +- .../Processing/BlockProcessor.cs | 14 +- .../Processing/ProcessingStats.cs | 2 +- .../Processing/RecoverSignature.cs | 10 +- .../TransactionProcessorAdapterExtensions.cs | 4 +- .../Nethermind.Core.Test/BlockHeaderTests.cs | 10 +- .../Blockchain/TestBlockchain.cs | 4 +- .../Builders/BlockTreeBuilder.cs | 27 ++ .../Nethermind.Core/BaseFeeCalculator.cs | 8 +- .../Nethermind.Core/Caching/LruCache.cs | 13 + .../Nethermind.Core/Eip1559Constants.cs | 5 - .../Nethermind.Core/Specs/IEip1559Spec.cs | 3 + .../Nethermind.Core/TransactionReceipt.cs | 3 + .../Nethermind.Db.Rocks/DbOnTheRocks.cs | 32 +-- src/Nethermind/Nethermind.Db/DbNames.cs | 1 + src/Nethermind/Nethermind.Db/IDbProvider.cs | 1 + src/Nethermind/Nethermind.Db/Metrics.cs | 8 + .../Nethermind.Db/StandardDbInitializer.cs | 1 + .../Nethermind.Evm/ExecutionEnvironment.cs | 2 +- src/Nethermind/Nethermind.Evm/Metrics.cs | 24 +- .../Tracing/BlockReceiptsTracer.cs | 30 ++- .../Nethermind.Evm/Tracing/GasEstimator.cs | 2 +- .../BuildUpTransactionProcessorAdapter.cs | 4 +- ...llAndRestoreTransactionProcessorAdapter.cs | 4 +- .../ChangeableTransactionProcessorAdapter.cs | 4 +- .../ExecuteTransactionProcessorAdapter.cs | 4 +- .../ITransactionProcessor.cs | 8 +- .../ITransactionProcessorAdapter.cs | 2 +- .../ReadOnlyTransactionProcessor.cs | 16 +- .../TraceTransactionProcessorAdapter.cs | 4 +- .../TransactionProcessor.cs | 32 +-- .../Nethermind.Evm/TxExecutionContext.cs | 2 +- .../Nethermind.Evm/VirtualMachine.cs | 4 +- .../Steps/InitializeBlockTree.cs | 2 + .../Steps/InitializeBlockchain.cs | 2 +- .../Steps/RegisterRpcModules.cs | 17 +- .../EthModuleBenchmarks.cs | 1 + .../Modules/DebugModuleTests.cs | 47 +++- .../Modules/SubscribeModuleTests.cs | 7 +- .../Modules/DebugModule/DebugBridge.cs | 82 ++---- .../Modules/DebugModule/DebugModuleFactory.cs | 7 +- .../Modules/DebugModule/DebugRpcModule.cs | 6 + .../Modules/DebugModule/IDebugBridge.cs | 1 + .../Modules/DebugModule/IDebugRpcModule.cs | 4 + .../BlockTreeTests.cs | 7 +- .../EngineModuleTests.Setup.cs | 6 +- .../MergeRewardCalculatorTests.cs | 3 +- .../PoSSwitcherTests.cs | 12 +- .../Synchronization/BeaconHeadersSyncTests.cs | 5 +- .../Nethermind.Merge.Plugin/GC/GCKeeper.cs | 34 +-- .../Handlers/BlockCacheService.cs | 2 +- .../Handlers/IBlockCacheService.cs | 2 +- .../MergeGossipPolicy.cs | 3 +- .../Nethermind.Merge.Plugin/MergePlugin.cs | 3 +- .../Nethermind.Merge.Plugin/PoSSwitcher.cs | 8 +- .../Synchronization/BeaconSync.cs | 8 +- .../MevBlockProductionTransactionsExecutor.cs | 18 +- .../MinGasPriceTests.cs | 13 + .../Create2DeployerContractRewriter.cs | 34 +++ .../Nethermind.Optimism/IOPConfigHelper.cs | 3 + .../InitializeBlockchainOptimism.cs | 33 ++- .../Nethermind.Optimism/OPConfigHelper.cs | 21 +- .../OptimismBlockProcessor.cs | 47 ++++ .../OptimismBlockProducerEnvFactory.cs | 27 +- .../OptimismBlockReceiptTracer.cs | 50 ++++ .../Nethermind.Optimism/OptimismPlugin.cs | 2 +- .../OptimismTransactionProcessor.cs | 7 +- .../Ethereum/ContextWithMocks.cs | 4 +- .../Steps/Migrations/ReceiptMigrationTests.cs | 4 +- .../Nethermind.Runner/configs/base-goerli.cfg | 3 - .../Nethermind.Runner/configs/chiado.cfg | 4 +- .../Nethermind.Runner/configs/energyweb.cfg | 6 +- .../Nethermind.Runner/configs/exosama.cfg | 6 +- .../Nethermind.Runner/configs/gnosis.cfg | 4 +- .../Nethermind.Runner/configs/joc-mainnet.cfg | 6 +- .../Nethermind.Runner/configs/joc-testnet.cfg | 6 +- .../Nethermind.Runner/configs/mainnet.cfg | 4 +- .../Nethermind.Runner/configs/sepolia.cfg | 4 +- .../Nethermind.Runner/configs/volta.cfg | 6 +- .../ReceiptMessageDecoder.cs | 20 +- .../OverridableReleaseSpec.cs | 3 + .../ChainSpecStyle/ChainParameters.cs | 6 +- .../ChainSpecBasedSpecProvider.cs | 11 + .../ChainSpecStyle/ChainSpecLoader.cs | 16 +- .../Json/ChainSpecGenesisJson.cs | 4 +- .../ChainSpecStyle/Json/ChainSpecJson.cs | 9 + .../ChainSpecStyle/OptimismParameters.cs | 9 +- .../Nethermind.Specs/ReleaseSpec.cs | 3 + .../SystemTransactionReleaseSpec.cs | 3 + .../Nethermind.State/StateProvider.cs | 15 +- .../BlockDownloaderTests.Merge.cs | 2 + .../MultiSyncModeSelectorTests.Scenario.cs | 2 +- .../SnapSync/ProgressTrackerTests.cs | 21 ++ .../SyncServerTests.cs | 3 + .../SynchronizerTests.cs | 2 +- .../IBeaconSyncStrategy.cs | 3 + .../ParallelSync/MultiSyncModeSelector.cs | 2 +- .../SnapSync/ProgressTracker.cs | 5 +- .../Nethermind.Trie/PatriciaTree.cs | 249 ++++++++++++------ .../Nethermind.Trie/TrieNode.Decoder.cs | 29 +- src/Nethermind/Nethermind.Trie/TrieNode.cs | 141 ++++++++-- .../Nethermind.TxPool/BlobTxStorage.cs | 12 +- 131 files changed, 1226 insertions(+), 537 deletions(-) create mode 100644 src/Nethermind/Nethermind.Optimism/Create2DeployerContractRewriter.cs create mode 100644 src/Nethermind/Nethermind.Optimism/OptimismBlockProcessor.cs create mode 100644 src/Nethermind/Nethermind.Optimism/OptimismBlockReceiptTracer.cs diff --git a/.editorconfig b/.editorconfig index 472016080b2..b8d038cba7f 100644 --- a/.editorconfig +++ b/.editorconfig @@ -9,7 +9,7 @@ indent_style = space insert_final_newline = true trim_trailing_whitespace = true -file_header_template = SPDX-FileCopyrightText: 2023 Demerzel Solutions Limited\nSPDX-License-Identifier: LGPL-3.0-only +file_header_template = SPDX-FileCopyrightText: 2024 Demerzel Solutions Limited\nSPDX-License-Identifier: LGPL-3.0-only [*.cs] indent_size = 4 @@ -34,31 +34,31 @@ dotnet_naming_rule.non_field_members_should_be_pascal_case.style = pascal_case dotnet_naming_symbols.interface.applicable_kinds = interface dotnet_naming_symbols.interface.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected -dotnet_naming_symbols.interface.required_modifiers = +dotnet_naming_symbols.interface.required_modifiers = dotnet_naming_symbols.types.applicable_kinds = class, struct, interface, enum dotnet_naming_symbols.types.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected -dotnet_naming_symbols.types.required_modifiers = +dotnet_naming_symbols.types.required_modifiers = dotnet_naming_symbols.non_field_members.applicable_kinds = property, event, method dotnet_naming_symbols.non_field_members.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected -dotnet_naming_symbols.non_field_members.required_modifiers = +dotnet_naming_symbols.non_field_members.required_modifiers = # Naming styles dotnet_naming_style.begins_with_i.required_prefix = I -dotnet_naming_style.begins_with_i.required_suffix = -dotnet_naming_style.begins_with_i.word_separator = +dotnet_naming_style.begins_with_i.required_suffix = +dotnet_naming_style.begins_with_i.word_separator = dotnet_naming_style.begins_with_i.capitalization = pascal_case -dotnet_naming_style.pascal_case.required_prefix = -dotnet_naming_style.pascal_case.required_suffix = -dotnet_naming_style.pascal_case.word_separator = +dotnet_naming_style.pascal_case.required_prefix = +dotnet_naming_style.pascal_case.required_suffix = +dotnet_naming_style.pascal_case.word_separator = dotnet_naming_style.pascal_case.capitalization = pascal_case -dotnet_naming_style.pascal_case.required_prefix = -dotnet_naming_style.pascal_case.required_suffix = -dotnet_naming_style.pascal_case.word_separator = +dotnet_naming_style.pascal_case.required_prefix = +dotnet_naming_style.pascal_case.required_suffix = +dotnet_naming_style.pascal_case.word_separator = dotnet_naming_style.pascal_case.capitalization = pascal_case dotnet_style_operator_placement_when_wrapping = beginning_of_line dotnet_style_coalesce_expression = true:suggestion @@ -88,4 +88,4 @@ csharp_style_expression_bodied_lambdas = true:silent csharp_style_expression_bodied_local_functions = false:silent csharp_style_var_for_built_in_types = true:silent csharp_style_var_when_type_is_apparent = true:suggestion -csharp_style_var_elsewhere = false:suggestion \ No newline at end of file +csharp_style_var_elsewhere = false:suggestion diff --git a/.github/workflows/build-solutions.yml b/.github/workflows/build-solutions.yml index 930bf01e379..f339c0f2920 100644 --- a/.github/workflows/build-solutions.yml +++ b/.github/workflows/build-solutions.yml @@ -6,38 +6,20 @@ on: push: branches: [master] -defaults: - run: - working-directory: src/Nethermind - -env: - BUILD_CONFIG: release - DOTNET_SYSTEM_CONSOLE_ALLOW_ANSI_COLOR_REDIRECTION: 1 - TERM: xterm - jobs: build: name: Build runs-on: ubuntu-latest - permissions: - contents: read + strategy: + matrix: + config: [release, debug] + solution: [Nethermind, EthereumTests, Benchmarks] steps: - name: Check out repository uses: actions/checkout@v4 with: - submodules: true - - name: Install Linux packages - run: sudo apt-get update && sudo apt-get install libsnappy-dev + submodules: ${{ matrix.solution == 'EthereumTests' }} - name: Set up .NET uses: actions/setup-dotnet@v4 - - name: Install dependencies - run: | - dotnet restore Nethermind.sln - dotnet restore EthereumTests.sln - dotnet restore Benchmarks.sln - - name: Build Nethermind.sln - run: dotnet build Nethermind.sln -c ${{ env.BUILD_CONFIG }} --no-restore - - name: Build EthereumTests.sln - run: dotnet build EthereumTests.sln -c ${{ env.BUILD_CONFIG }} --no-restore - - name: Build Benchmarks.sln - run: dotnet build Benchmarks.sln -c ${{ env.BUILD_CONFIG }} --no-restore + - name: Build ${{ matrix.solution }}.sln + run: dotnet build src/Nethermind/${{ matrix.solution }}.sln -c ${{ matrix.config }} diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 78f12ea5e0a..b344bb08321 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -16,7 +16,7 @@ env: PACKAGE_DIR: pkg PACKAGE_RETENTION: 7 PUB_DIR: pub - SCRIPTS_PATH: ${{ github.workspace }}/nethermind/scripts/deployment + SCRIPTS_PATH: ${{ github.workspace }}/scripts/deployment jobs: build: @@ -116,8 +116,6 @@ jobs: steps: - name: Check out Nethermind repository uses: actions/checkout@v4 - with: - path: nethermind - name: Download artifacts uses: actions/download-artifact@v4 with: @@ -141,8 +139,6 @@ jobs: steps: - name: Check out Nethermind repository uses: actions/checkout@v4 - with: - path: nethermind - name: Download artifacts uses: actions/download-artifact@v4 with: diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 026af98679f..26ef4fd581a 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -56,7 +56,7 @@ Branch names must follow `snake_case` pattern. Follow the pattern `Demerzel Solutions Limited Nethermind $(Commit.Substring(0, 8)) - 1.24.0 + 1.26.0 unstable diff --git a/src/Nethermind/Directory.Packages.props b/src/Nethermind/Directory.Packages.props index 2dc7856a8d6..01c8186332e 100644 --- a/src/Nethermind/Directory.Packages.props +++ b/src/Nethermind/Directory.Packages.props @@ -4,12 +4,12 @@ - - - - - - + + + + + + @@ -24,7 +24,7 @@ - + @@ -49,14 +49,14 @@ - + - + @@ -65,15 +65,15 @@ - - + + - + @@ -88,9 +88,9 @@ - - + + - \ No newline at end of file + diff --git a/src/Nethermind/Nethermind.AccountAbstraction.Test/UserOperationSubscribeTests.cs b/src/Nethermind/Nethermind.AccountAbstraction.Test/UserOperationSubscribeTests.cs index 409ed0d0beb..799ee6444db 100644 --- a/src/Nethermind/Nethermind.AccountAbstraction.Test/UserOperationSubscribeTests.cs +++ b/src/Nethermind/Nethermind.AccountAbstraction.Test/UserOperationSubscribeTests.cs @@ -62,7 +62,7 @@ public void Setup() _blockTree = Substitute.For(); _txPool = Substitute.For(); _receiptStorage = Substitute.For(); - _receiptCanonicalityMonitor = new ReceiptCanonicalityMonitor(_blockTree, _receiptStorage, _logManager); + _receiptCanonicalityMonitor = new ReceiptCanonicalityMonitor(_receiptStorage, _logManager); _specProvider = Substitute.For(); _userOperationPools[_testPoolAddress] = Substitute.For(); _filterStore = new FilterStore(); diff --git a/src/Nethermind/Nethermind.AccountAbstraction/Executor/AABlockProducerTransactionsExecutor.cs b/src/Nethermind/Nethermind.AccountAbstraction/Executor/AABlockProducerTransactionsExecutor.cs index e3791db4b03..2066e0b9ac3 100644 --- a/src/Nethermind/Nethermind.AccountAbstraction/Executor/AABlockProducerTransactionsExecutor.cs +++ b/src/Nethermind/Nethermind.AccountAbstraction/Executor/AABlockProducerTransactionsExecutor.cs @@ -56,12 +56,12 @@ public override TxReceipt[] ProcessTransactions( { if (IsAccountAbstractionTransaction(transaction)) { - BlockProcessor.TxAction action = ProcessAccountAbstractionTransaction(block, blkCtx, transaction, i++, receiptsTracer, processingOptions, transactionsInBlock); + BlockProcessor.TxAction action = ProcessAccountAbstractionTransaction(block, in blkCtx, transaction, i++, receiptsTracer, processingOptions, transactionsInBlock); if (action == BlockProcessor.TxAction.Stop) break; } else { - BlockProcessor.TxAction action = ProcessTransaction(block, blkCtx, transaction, i++, receiptsTracer, processingOptions, transactionsInBlock); + BlockProcessor.TxAction action = ProcessTransaction(block, in blkCtx, transaction, i++, receiptsTracer, processingOptions, transactionsInBlock); if (action == BlockProcessor.TxAction.Stop) break; } } @@ -81,7 +81,7 @@ private bool IsAccountAbstractionTransaction(Transaction transaction) private BlockProcessor.TxAction ProcessAccountAbstractionTransaction( Block block, - BlockExecutionContext blkCtx, + in BlockExecutionContext blkCtx, Transaction currentTx, int index, BlockReceiptsTracer receiptsTracer, @@ -90,7 +90,7 @@ private BlockProcessor.TxAction ProcessAccountAbstractionTransaction( { int snapshot = receiptsTracer.TakeSnapshot(); - BlockProcessor.TxAction action = ProcessTransaction(block, blkCtx, currentTx, index, receiptsTracer, processingOptions, transactionsInBlock, false); + BlockProcessor.TxAction action = ProcessTransaction(block, in blkCtx, currentTx, index, receiptsTracer, processingOptions, transactionsInBlock, false); if (action != BlockProcessor.TxAction.Add) { return action; diff --git a/src/Nethermind/Nethermind.Api/IApiWithStores.cs b/src/Nethermind/Nethermind.Api/IApiWithStores.cs index 8a5bfa981d5..f6e02313adc 100644 --- a/src/Nethermind/Nethermind.Api/IApiWithStores.cs +++ b/src/Nethermind/Nethermind.Api/IApiWithStores.cs @@ -2,6 +2,7 @@ // SPDX-License-Identifier: LGPL-3.0-only using Nethermind.Blockchain; +using Nethermind.Blockchain.Blocks; using Nethermind.Blockchain.Find; using Nethermind.Blockchain.Receipts; using Nethermind.Consensus; @@ -27,5 +28,6 @@ public interface IApiWithStores : IBasicApi IReceiptFinder? ReceiptFinder { get; set; } IReceiptMonitor? ReceiptMonitor { get; set; } IWallet? Wallet { get; set; } + IBlockStore? BadBlocksStore { get; set; } } } diff --git a/src/Nethermind/Nethermind.Api/IInitConfig.cs b/src/Nethermind/Nethermind.Api/IInitConfig.cs index fa2600c4d5d..c72d7477666 100644 --- a/src/Nethermind/Nethermind.Api/IInitConfig.cs +++ b/src/Nethermind/Nethermind.Api/IInitConfig.cs @@ -74,15 +74,15 @@ public interface IInitConfig : IConfig [ConfigItem(Description = "The hint on the max memory limit, in bytes, to configure the database and networking memory allocations.", DefaultValue = "null")] long? MemoryHint { get; set; } + [ConfigItem(Description = "The maximum number of bad blocks observed on the network that will be stored to disk.", DefaultValue = "100")] + long? BadBlocksStored { get; set; } + [ConfigItem(Description = "[TECHNICAL] Disable garbage collector on newPayload", DefaultValue = "true", HiddenFromDocs = true)] bool DisableGcOnNewPayload { get; set; } [ConfigItem(Description = "[TECHNICAL] Disable setting malloc options. Set to true if using different memory allocator or manually setting malloc opts.", DefaultValue = "false", HiddenFromDocs = true)] bool DisableMallocOpts { get; set; } - [ConfigItem(Description = "Directory with era1 archives from which ancient blocks will be served.", DefaultValue = "", HiddenFromDocs = false)] - string AncientDataDirectory { get; set; } - [ConfigItem(Description = "[TECHNICAL] Exit when block number is reached. Useful for scripting and testing.", DefaultValue = "null", HiddenFromDocs = true)] long? ExitOnBlockNumber { get; set; } } diff --git a/src/Nethermind/Nethermind.Api/InitConfig.cs b/src/Nethermind/Nethermind.Api/InitConfig.cs index 0f34360044c..f594913ae3e 100644 --- a/src/Nethermind/Nethermind.Api/InitConfig.cs +++ b/src/Nethermind/Nethermind.Api/InitConfig.cs @@ -31,6 +31,7 @@ public class InitConfig : IInitConfig public string RpcDbUrl { get; set; } = String.Empty; public long? MemoryHint { get; set; } + public long? BadBlocksStored { get; set; } = 100; public bool DisableGcOnNewPayload { get; set; } = true; public bool DisableMallocOpts { get; set; } = false; public long? ExitOnBlockNumber { get; set; } = null; diff --git a/src/Nethermind/Nethermind.Api/NethermindApi.cs b/src/Nethermind/Nethermind.Api/NethermindApi.cs index 0454db9cd53..37c2bbbd517 100644 --- a/src/Nethermind/Nethermind.Api/NethermindApi.cs +++ b/src/Nethermind/Nethermind.Api/NethermindApi.cs @@ -7,6 +7,7 @@ using Nethermind.Abi; using Nethermind.Api.Extensions; using Nethermind.Blockchain; +using Nethermind.Blockchain.Blocks; using Nethermind.Blockchain.Filters; using Nethermind.Blockchain.Find; using Nethermind.Blockchain.FullPruning; @@ -210,6 +211,7 @@ public ISealEngine SealEngine public IEthSyncingInfo? EthSyncingInfo { get; set; } public IBlockProductionPolicy? BlockProductionPolicy { get; set; } public IWallet? Wallet { get; set; } + public IBlockStore? BadBlocksStore { get; set; } public ITransactionComparerProvider? TransactionComparerProvider { get; set; } public IWebSocketsManager WebSocketsManager { get; set; } = new WebSocketsManager(); diff --git a/src/Nethermind/Nethermind.Blockchain.Test/Producers/BlockProducerBaseTests.BaseFee.cs b/src/Nethermind/Nethermind.Blockchain.Test/Producers/BlockProducerBaseTests.BaseFee.cs index 4e66e5bd708..988136b6896 100644 --- a/src/Nethermind/Nethermind.Blockchain.Test/Producers/BlockProducerBaseTests.BaseFee.cs +++ b/src/Nethermind/Nethermind.Blockchain.Test/Producers/BlockProducerBaseTests.BaseFee.cs @@ -255,7 +255,7 @@ public async Task BlockProducer_returns_correct_fork_base_fee() .WithEip1559TransitionBlock(7) .CreateTestBlockchain() .BlocksBeforeTransitionShouldHaveZeroBaseFee() - .AssertNewBlock(Eip1559Constants.ForkBaseFee); + .AssertNewBlock(Eip1559Constants.DefaultForkBaseFee); await scenario.Finish(); } @@ -266,7 +266,7 @@ public async Task BlockProducer_returns_correctly_decreases_base_fee_on_empty_bl .WithEip1559TransitionBlock(6) .CreateTestBlockchain() .BlocksBeforeTransitionShouldHaveZeroBaseFee() - .AssertNewBlock(Eip1559Constants.ForkBaseFee) + .AssertNewBlock(Eip1559Constants.DefaultForkBaseFee) .AssertNewBlock(875000000) .AssertNewBlock(765625000) .AssertNewBlock(669921875) @@ -283,7 +283,7 @@ public async Task BaseFee_should_decrease_when_we_send_transactions_below_gas_ta .CreateTestBlockchain(gasLimit) .DeployContract() .BlocksBeforeTransitionShouldHaveZeroBaseFee() - .AssertNewBlock(Eip1559Constants.ForkBaseFee) + .AssertNewBlock(Eip1559Constants.DefaultForkBaseFee) .SendLegacyTransaction(gasLimit / 3, 20.GWei()) .SendEip1559Transaction(gasLimit / 3, 1.GWei(), 20.GWei()) .AssertNewBlock(875000000) @@ -301,7 +301,7 @@ public async Task BaseFee_should_not_change_when_we_send_transactions_equal_gas_ .CreateTestBlockchain(gasTarget) .DeployContract() .BlocksBeforeTransitionShouldHaveZeroBaseFee() - .AssertNewBlock(Eip1559Constants.ForkBaseFee) + .AssertNewBlock(Eip1559Constants.DefaultForkBaseFee) .SendLegacyTransaction(gasTarget / 2, 20.GWei()) .SendEip1559Transaction(gasTarget / 2, 1.GWei(), 20.GWei()) .AssertNewBlock(875000000) @@ -319,7 +319,7 @@ public async Task BaseFee_should_increase_when_we_send_transactions_above_gas_ta .CreateTestBlockchain(gasTarget) .DeployContract() .BlocksBeforeTransitionShouldHaveZeroBaseFee() - .AssertNewBlock(Eip1559Constants.ForkBaseFee) + .AssertNewBlock(Eip1559Constants.DefaultForkBaseFee) .SendLegacyTransaction(gasTarget / 2, 20.GWei()) .SendEip1559Transaction(gasTarget / 2, 1.GWei(), 20.GWei()) .SendLegacyTransaction(gasTarget / 2, 20.GWei()) @@ -337,7 +337,7 @@ public async Task When_base_fee_decreases_previously_fee_too_low_transaction_is_ .WithEip1559TransitionBlock(6) .CreateTestBlockchain(gasTarget) .BlocksBeforeTransitionShouldHaveZeroBaseFee() - .AssertNewBlock(Eip1559Constants.ForkBaseFee) + .AssertNewBlock(Eip1559Constants.DefaultForkBaseFee) .SendLegacyTransaction(gasTarget / 2, 7.GWei() / 10, nonce: UInt256.Zero) .AssertNewBlock(875000000) .AssertNewBlock(765625000) diff --git a/src/Nethermind/Nethermind.Blockchain.Test/Receipts/PersistentReceiptStorageTests.cs b/src/Nethermind/Nethermind.Blockchain.Test/Receipts/PersistentReceiptStorageTests.cs index aa0c2f505e0..6269c21cbb7 100644 --- a/src/Nethermind/Nethermind.Blockchain.Test/Receipts/PersistentReceiptStorageTests.cs +++ b/src/Nethermind/Nethermind.Blockchain.Test/Receipts/PersistentReceiptStorageTests.cs @@ -290,17 +290,22 @@ public void When_TxLookupLimitIs_NegativeOne_DoNotIndexTxHash() _receiptsDb.GetColumnDb(ReceiptsColumns.Transactions)[receipts[0].TxHash!.Bytes].Should().BeNull(); } - [Test] - public void Should_not_index_tx_hash_if_blockNumber_is_negative() + [TestCase(1L, false)] + [TestCase(10L, false)] + [TestCase(11L, true)] + public void Should_only_prune_index_tx_hashes_if_blockNumber_is_bigger_than_lookupLimit(long blockNumber, bool WillPruneOldIndicies) { _receiptConfig.TxLookupLimit = 10; CreateStorage(); _blockTree.BlockAddedToMain += - Raise.EventWith(new BlockReplacementEventArgs(Build.A.Block.WithNumber(1).TestObject)); + Raise.EventWith(new BlockReplacementEventArgs(Build.A.Block.WithNumber(blockNumber).TestObject)); Thread.Sleep(100); IEnumerable calls = _blockTree.ReceivedCalls() - .Where(call => !call.GetMethodInfo().Name.EndsWith(nameof(_blockTree.BlockAddedToMain))); - calls.Should().BeEmpty(); + .Where(call => call.GetMethodInfo().Name.EndsWith(nameof(_blockTree.FindBlock))); + if (WillPruneOldIndicies) + calls.Should().NotBeEmpty(); + else + calls.Should().BeEmpty(); } [Test] @@ -342,27 +347,49 @@ public void When_NewHeadBlock_Remove_TxIndex_OfRemovedBlock() [Test] public async Task When_NewHeadBlock_Remove_TxIndex_OfRemovedBlock_Unless_ItsAlsoInNewBlock() { + _receiptConfig.CompactTxIndex = _useCompactReceipts; CreateStorage(); (Block block, TxReceipt[] receipts) = InsertBlock(); + Block block2 = Build.A.Block + .WithParent(block) + .WithNumber(2) + .WithTransactions(Build.A.Transaction.SignedAndResolved(TestItem.PrivateKeyC).TestObject) + .TestObject; + _blockTree.FindBestSuggestedHeader().Returns(block2.Header); + _blockTree.BlockAddedToMain += Raise.EventWith(new BlockReplacementEventArgs(block2)); if (_receiptConfig.CompactTxIndex) { - _receiptsDb.GetColumnDb(ReceiptsColumns.Transactions)[receipts[0].TxHash!.Bytes].Should().BeEquivalentTo(Rlp.Encode(block.Number).Bytes); + _receiptsDb.GetColumnDb(ReceiptsColumns.Transactions)[block.Transactions[0].Hash!.Bytes].Should().BeEquivalentTo(Rlp.Encode(block.Number).Bytes); } else { - _receiptsDb.GetColumnDb(ReceiptsColumns.Transactions)[receipts[0].TxHash!.Bytes].Should().NotBeNull(); + _receiptsDb.GetColumnDb(ReceiptsColumns.Transactions)[block.Transactions[0].Hash!.Bytes].Should().BeEquivalentTo(block.Hash!.Bytes.ToArray()); } - Block newHead = Build.A.Block + Block block3 = Build.A.Block .WithNumber(1) + .WithTransactions(block2.Transactions) + .WithExtraData(new byte[1]) + .TestObject; + Block block4 = Build.A.Block + .WithNumber(2) .WithTransactions(block.Transactions) + .WithExtraData(new byte[1]) .TestObject; - _blockTree.FindBestSuggestedHeader().Returns(newHead.Header); - _blockTree.BlockAddedToMain += Raise.EventWith(new BlockReplacementEventArgs(newHead, block)); + _blockTree.FindBestSuggestedHeader().Returns(block4.Header); + _blockTree.BlockAddedToMain += Raise.EventWith(new BlockReplacementEventArgs(block3, block)); + _blockTree.BlockAddedToMain += Raise.EventWith(new BlockReplacementEventArgs(block4, block2)); await Task.Delay(100); - _receiptsDb.GetColumnDb(ReceiptsColumns.Transactions)[receipts[0].TxHash!.Bytes].Should().NotBeNull(); + if (_receiptConfig.CompactTxIndex) + { + _receiptsDb.GetColumnDb(ReceiptsColumns.Transactions)[block4.Transactions[0].Hash!.Bytes].Should().BeEquivalentTo(Rlp.Encode(block4.Number).Bytes); + } + else + { + _receiptsDb.GetColumnDb(ReceiptsColumns.Transactions)[block4.Transactions[0].Hash!.Bytes].Should().BeEquivalentTo(block4.Hash!.Bytes.ToArray()); + } } [Test] diff --git a/src/Nethermind/Nethermind.Blockchain/BlockTree.cs b/src/Nethermind/Nethermind.Blockchain/BlockTree.cs index 4a7eefa42fb..368f6201ea8 100644 --- a/src/Nethermind/Nethermind.Blockchain/BlockTree.cs +++ b/src/Nethermind/Nethermind.Blockchain/BlockTree.cs @@ -43,6 +43,7 @@ public partial class BlockTree : IBlockTree private readonly IHeaderStore _headerStore; private readonly IDb _blockInfoDb; private readonly IDb _metadataDb; + private readonly IBlockStore _badBlockStore; private readonly LruCache _invalidBlocks = new(128, 128, "invalid blocks"); @@ -110,6 +111,7 @@ public BlockTree( IHeaderStore? headerDb, IDb? blockInfoDb, IDb? metadataDb, + IBlockStore? badBlockStore, IChainLevelInfoRepository? chainLevelInfoRepository, ISpecProvider? specProvider, IBloomStorage? bloomStorage, @@ -121,6 +123,7 @@ public BlockTree( _headerStore = headerDb ?? throw new ArgumentNullException(nameof(headerDb)); _blockInfoDb = blockInfoDb ?? throw new ArgumentNullException(nameof(blockInfoDb)); _metadataDb = metadataDb ?? throw new ArgumentNullException(nameof(metadataDb)); + _badBlockStore = badBlockStore ?? throw new ArgumentNullException(nameof(badBlockStore)); _specProvider = specProvider ?? throw new ArgumentNullException(nameof(specProvider)); _bloomStorage = bloomStorage ?? throw new ArgumentNullException(nameof(bloomStorage)); _syncConfig = syncConfig ?? throw new ArgumentNullException(nameof(syncConfig)); @@ -710,6 +713,7 @@ public void DeleteInvalidBlock(Block invalidBlock) if (_logger.IsDebug) _logger.Debug($"Deleting invalid block {invalidBlock.ToString(Block.Format.FullHashAndNumber)}"); _invalidBlocks.Set(invalidBlock.Hash, invalidBlock); + _badBlockStore.Insert(invalidBlock); BestSuggestedHeader = Head?.Header; BestSuggestedBody = Head; diff --git a/src/Nethermind/Nethermind.Blockchain/Blocks/BlockStore.cs b/src/Nethermind/Nethermind.Blockchain/Blocks/BlockStore.cs index 830223ec0ab..67bf3d902b1 100644 --- a/src/Nethermind/Nethermind.Blockchain/Blocks/BlockStore.cs +++ b/src/Nethermind/Nethermind.Blockchain/Blocks/BlockStore.cs @@ -3,6 +3,8 @@ using System; using System.Buffers; +using System.Collections.Generic; +using System.Linq; using Nethermind.Core; using Nethermind.Core.Caching; using Nethermind.Core.Crypto; @@ -20,10 +22,12 @@ public class BlockStore : IBlockStore private readonly LruCache _blockCache = new(CacheSize, CacheSize, "blocks"); + private long? _maxSize; - public BlockStore(IDb blockDb) + public BlockStore(IDb blockDb, long? maxSize = null) { _blockDb = blockDb; + _maxSize = maxSize; } public void SetMetadata(byte[] key, byte[] value) @@ -36,6 +40,18 @@ public void SetMetadata(byte[] key, byte[] value) return _blockDb.Get(key); } + private void TruncateToMaxSize() + { + int toDelete = (int)(_blockDb.GetSize() - _maxSize!); + if (toDelete > 0) + { + foreach (var blockToDelete in GetAll().Take(toDelete)) + { + Delete(blockToDelete.Number, blockToDelete.Hash); + } + } + } + public void Insert(Block block, WriteFlags writeFlags = WriteFlags.None) { if (block.Hash is null) @@ -48,6 +64,11 @@ public void Insert(Block block, WriteFlags writeFlags = WriteFlags.None) using NettyRlpStream newRlp = _blockDecoder.EncodeToNewNettyStream(block); _blockDb.Set(block.Number, block.Hash, newRlp.AsSpan(), writeFlags); + + if (_maxSize is not null) + { + TruncateToMaxSize(); + } } private static void GetBlockNumPrefixedKey(long blockNumber, Hash256 blockHash, Span output) @@ -88,4 +109,9 @@ public void Cache(Block block) { _blockCache.Set(block.Hash, block); } + + public IEnumerable GetAll() + { + return _blockDb.GetAllValues(true).Select(bytes => _blockDecoder.Decode(bytes.AsRlpStream())); + } } diff --git a/src/Nethermind/Nethermind.Blockchain/Blocks/IBlockStore.cs b/src/Nethermind/Nethermind.Blockchain/Blocks/IBlockStore.cs index a84f2c5fe4a..6621182c949 100644 --- a/src/Nethermind/Nethermind.Blockchain/Blocks/IBlockStore.cs +++ b/src/Nethermind/Nethermind.Blockchain/Blocks/IBlockStore.cs @@ -1,6 +1,7 @@ // SPDX-FileCopyrightText: 2023 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using System.Collections.Generic; using Nethermind.Core; using Nethermind.Core.Crypto; using Nethermind.Serialization.Rlp; @@ -16,6 +17,7 @@ public interface IBlockStore void Insert(Block block, WriteFlags writeFlags = WriteFlags.None); void Delete(long blockNumber, Hash256 blockHash); Block? Get(long blockNumber, Hash256 blockHash, bool shouldCache = true); + IEnumerable GetAll(); ReceiptRecoveryBlock? GetReceiptRecoveryBlock(long blockNumber, Hash256 blockHash); void Cache(Block block); diff --git a/src/Nethermind/Nethermind.Blockchain/ReceiptCanonicalityMonitor.cs b/src/Nethermind/Nethermind.Blockchain/ReceiptCanonicalityMonitor.cs index d6d35d8b0ef..4d6b55283d9 100644 --- a/src/Nethermind/Nethermind.Blockchain/ReceiptCanonicalityMonitor.cs +++ b/src/Nethermind/Nethermind.Blockchain/ReceiptCanonicalityMonitor.cs @@ -16,24 +16,20 @@ public interface IReceiptMonitor : IDisposable public class ReceiptCanonicalityMonitor : IReceiptMonitor { - private readonly IBlockTree _blockTree; private readonly IReceiptStorage _receiptStorage; private readonly ILogger _logger; public event EventHandler? ReceiptsInserted; - public ReceiptCanonicalityMonitor(IBlockTree? blockTree, IReceiptStorage? receiptStorage, ILogManager? logManager) + public ReceiptCanonicalityMonitor(IReceiptStorage? receiptStorage, ILogManager? logManager) { - _blockTree = blockTree ?? throw new ArgumentNullException(nameof(blockTree)); _receiptStorage = receiptStorage ?? throw new ArgumentNullException(nameof(receiptStorage)); _logger = logManager?.GetClassLogger() ?? throw new ArgumentNullException(nameof(logManager)); - _blockTree.BlockAddedToMain += OnBlockAddedToMain; + _receiptStorage.ReceiptsInserted += OnBlockAddedToMain; } private void OnBlockAddedToMain(object sender, BlockReplacementEventArgs e) { - _receiptStorage.EnsureCanonical(e.Block); - // we don't want this to be on main processing thread Task.Run(() => TriggerReceiptInsertedEvent(e.Block, e.PreviousBlock)); } @@ -59,7 +55,7 @@ private void TriggerReceiptInsertedEvent(Block newBlock, Block? previousBlock) public void Dispose() { - _blockTree.BlockAddedToMain -= OnBlockAddedToMain; + _receiptStorage.ReceiptsInserted -= OnBlockAddedToMain; } } } diff --git a/src/Nethermind/Nethermind.Blockchain/Receipts/IReceiptStorage.cs b/src/Nethermind/Nethermind.Blockchain/Receipts/IReceiptStorage.cs index f1abcef89c9..236540cbe48 100644 --- a/src/Nethermind/Nethermind.Blockchain/Receipts/IReceiptStorage.cs +++ b/src/Nethermind/Nethermind.Blockchain/Receipts/IReceiptStorage.cs @@ -3,6 +3,7 @@ using Nethermind.Core; using Nethermind.Core.Crypto; +using System; namespace Nethermind.Blockchain.Receipts { @@ -14,5 +15,10 @@ public interface IReceiptStorage : IReceiptFinder long MigratedBlockNumber { get; set; } bool HasBlock(long blockNumber, Hash256 hash); void EnsureCanonical(Block block); + + /// + /// Receipts for a block are inserted + /// + event EventHandler ReceiptsInserted; } } diff --git a/src/Nethermind/Nethermind.Blockchain/Receipts/InMemoryReceiptStorage.cs b/src/Nethermind/Nethermind.Blockchain/Receipts/InMemoryReceiptStorage.cs index a118a0aec87..4b78996a0ac 100644 --- a/src/Nethermind/Nethermind.Blockchain/Receipts/InMemoryReceiptStorage.cs +++ b/src/Nethermind/Nethermind.Blockchain/Receipts/InMemoryReceiptStorage.cs @@ -11,13 +11,27 @@ namespace Nethermind.Blockchain.Receipts public class InMemoryReceiptStorage : IReceiptStorage { private readonly bool _allowReceiptIterator; + private readonly IBlockTree? _blockTree; private readonly ConcurrentDictionary _receipts = new(); private readonly ConcurrentDictionary _transactions = new(); - public InMemoryReceiptStorage(bool allowReceiptIterator = true) +#pragma warning disable CS0067 + public event EventHandler ReceiptsInserted; +#pragma warning restore CS0067 + + public InMemoryReceiptStorage(bool allowReceiptIterator = true, IBlockTree? blockTree = null) { _allowReceiptIterator = allowReceiptIterator; + _blockTree = blockTree; + if (_blockTree is not null) + _blockTree.BlockAddedToMain += BlockTree_BlockAddedToMain; + } + + private void BlockTree_BlockAddedToMain(object? sender, BlockReplacementEventArgs e) + { + EnsureCanonical(e.Block); + ReceiptsInserted?.Invoke(this, e); } public Hash256 FindBlockHash(Hash256 txHash) diff --git a/src/Nethermind/Nethermind.Blockchain/Receipts/NullReceiptStorage.cs b/src/Nethermind/Nethermind.Blockchain/Receipts/NullReceiptStorage.cs index 22f6b7fdc21..802c8d858e5 100644 --- a/src/Nethermind/Nethermind.Blockchain/Receipts/NullReceiptStorage.cs +++ b/src/Nethermind/Nethermind.Blockchain/Receipts/NullReceiptStorage.cs @@ -11,6 +11,10 @@ public class NullReceiptStorage : IReceiptStorage { public static NullReceiptStorage Instance { get; } = new(); +#pragma warning disable CS0067 + public event EventHandler ReceiptsInserted; +#pragma warning restore CS0067 + public Hash256? FindBlockHash(Hash256 hash) => null; private NullReceiptStorage() diff --git a/src/Nethermind/Nethermind.Blockchain/Receipts/PersistentReceiptStorage.cs b/src/Nethermind/Nethermind.Blockchain/Receipts/PersistentReceiptStorage.cs index ca972f1aa9a..a186d13d1d2 100644 --- a/src/Nethermind/Nethermind.Blockchain/Receipts/PersistentReceiptStorage.cs +++ b/src/Nethermind/Nethermind.Blockchain/Receipts/PersistentReceiptStorage.cs @@ -39,6 +39,8 @@ public class PersistentReceiptStorage : IReceiptStorage private const int CacheSize = 64; private readonly LruCache _receiptsCache = new(CacheSize, CacheSize, "receipts"); + public event EventHandler ReceiptsInserted; + public PersistentReceiptStorage( IColumnsDb receiptsDb, ISpecProvider specProvider, @@ -78,6 +80,8 @@ private void BlockTreeOnBlockAddedToMain(object? sender, BlockReplacementEventAr { RemoveBlockTx(e.PreviousBlock, e.Block); } + EnsureCanonical(e.Block); + ReceiptsInserted?.Invoke(this, e); // Dont block main loop Task.Run(() => diff --git a/src/Nethermind/Nethermind.Consensus.Test/TargetAdjustedGasLimitCalculatorTests.cs b/src/Nethermind/Nethermind.Consensus.Test/TargetAdjustedGasLimitCalculatorTests.cs index d3006e499c7..2f96501987d 100644 --- a/src/Nethermind/Nethermind.Consensus.Test/TargetAdjustedGasLimitCalculatorTests.cs +++ b/src/Nethermind/Nethermind.Consensus.Test/TargetAdjustedGasLimitCalculatorTests.cs @@ -27,7 +27,7 @@ public void Is_bump_on_1559_eip_block() TargetAdjustedGasLimitCalculator targetedAdjustedGasLimitCalculator = new(specProvider, new BlocksConfig()); BlockHeader header = Build.A.BlockHeader.WithNumber(londonBlock - 1).WithGasLimit(gasLimit).TestObject; long actualValue = targetedAdjustedGasLimitCalculator.GetGasLimit(header); - Assert.That(actualValue, Is.EqualTo(gasLimit * Eip1559Constants.ElasticityMultiplier)); + Assert.That(actualValue, Is.EqualTo(gasLimit * Eip1559Constants.DefaultElasticityMultiplier)); } } } diff --git a/src/Nethermind/Nethermind.Consensus/Eip1559GasLimitAdjuster.cs b/src/Nethermind/Nethermind.Consensus/Eip1559GasLimitAdjuster.cs index 3c1ecb4138f..98e15179438 100644 --- a/src/Nethermind/Nethermind.Consensus/Eip1559GasLimitAdjuster.cs +++ b/src/Nethermind/Nethermind.Consensus/Eip1559GasLimitAdjuster.cs @@ -14,7 +14,7 @@ public static long AdjustGasLimit(IReleaseSpec releaseSpec, long gasLimit, long long adjustedGasLimit = gasLimit; if (releaseSpec.Eip1559TransitionBlock == blockNumber) { - adjustedGasLimit *= Eip1559Constants.ElasticityMultiplier; + adjustedGasLimit *= releaseSpec.ElasticityMultiplier; } return adjustedGasLimit; diff --git a/src/Nethermind/Nethermind.Consensus/Processing/BlockProcessor.BlockProductionTransactionsExecutor.cs b/src/Nethermind/Nethermind.Consensus/Processing/BlockProcessor.BlockProductionTransactionsExecutor.cs index f794d3b64b6..fdaab77ccdb 100644 --- a/src/Nethermind/Nethermind.Consensus/Processing/BlockProcessor.BlockProductionTransactionsExecutor.cs +++ b/src/Nethermind/Nethermind.Consensus/Processing/BlockProcessor.BlockProductionTransactionsExecutor.cs @@ -79,7 +79,7 @@ public virtual TxReceipt[] ProcessTransactions(Block block, ProcessingOptions pr BlockExecutionContext blkCtx = new(block.Header); foreach (Transaction currentTx in transactions) { - TxAction action = ProcessTransaction(block, blkCtx, currentTx, i++, receiptsTracer, processingOptions, transactionsInBlock); + TxAction action = ProcessTransaction(block, in blkCtx, currentTx, i++, receiptsTracer, processingOptions, transactionsInBlock); if (action == TxAction.Stop) break; } @@ -91,7 +91,7 @@ public virtual TxReceipt[] ProcessTransactions(Block block, ProcessingOptions pr protected TxAction ProcessTransaction( Block block, - BlockExecutionContext blkCtx, + in BlockExecutionContext blkCtx, Transaction currentTx, int index, BlockReceiptsTracer receiptsTracer, @@ -109,7 +109,7 @@ protected TxAction ProcessTransaction( } else { - _transactionProcessor.ProcessTransaction(blkCtx, currentTx, receiptsTracer, processingOptions, _stateProvider); + _transactionProcessor.ProcessTransaction(in blkCtx, currentTx, receiptsTracer, processingOptions, _stateProvider); if (addToBlock) { diff --git a/src/Nethermind/Nethermind.Consensus/Processing/BlockProcessor.BlockValidationTransactionsExecutor.cs b/src/Nethermind/Nethermind.Consensus/Processing/BlockProcessor.BlockValidationTransactionsExecutor.cs index 116ba87a90c..e520562d4e2 100644 --- a/src/Nethermind/Nethermind.Consensus/Processing/BlockProcessor.BlockValidationTransactionsExecutor.cs +++ b/src/Nethermind/Nethermind.Consensus/Processing/BlockProcessor.BlockValidationTransactionsExecutor.cs @@ -39,14 +39,14 @@ public TxReceipt[] ProcessTransactions(Block block, ProcessingOptions processing for (int i = 0; i < block.Transactions.Length; i++) { Transaction currentTx = block.Transactions[i]; - ProcessTransaction(blkCtx, currentTx, i, receiptsTracer, processingOptions); + ProcessTransaction(in blkCtx, currentTx, i, receiptsTracer, processingOptions); } return receiptsTracer.TxReceipts.ToArray(); } - private void ProcessTransaction(BlockExecutionContext blkCtx, Transaction currentTx, int index, BlockReceiptsTracer receiptsTracer, ProcessingOptions processingOptions) + private void ProcessTransaction(in BlockExecutionContext blkCtx, Transaction currentTx, int index, BlockReceiptsTracer receiptsTracer, ProcessingOptions processingOptions) { - _transactionProcessor.ProcessTransaction(blkCtx, currentTx, receiptsTracer, processingOptions, _stateProvider); + _transactionProcessor.ProcessTransaction(in blkCtx, currentTx, receiptsTracer, processingOptions, _stateProvider); TransactionProcessed?.Invoke(this, new TxProcessedEventArgs(index, currentTx, receiptsTracer.TxReceipts[index])); } } diff --git a/src/Nethermind/Nethermind.Consensus/Processing/BlockProcessor.cs b/src/Nethermind/Nethermind.Consensus/Processing/BlockProcessor.cs index 232c125c38b..f7f5bd8c803 100644 --- a/src/Nethermind/Nethermind.Consensus/Processing/BlockProcessor.cs +++ b/src/Nethermind/Nethermind.Consensus/Processing/BlockProcessor.cs @@ -43,7 +43,7 @@ public partial class BlockProcessor : IBlockProcessor /// We use a single receipt tracer for all blocks. Internally receipt tracer forwards most of the calls /// to any block-specific tracers. /// - private readonly BlockReceiptsTracer _receiptsTracer; + protected BlockReceiptsTracer ReceiptsTracer { get; set; } public BlockProcessor( ISpecProvider? specProvider, @@ -67,7 +67,7 @@ public BlockProcessor( _blockTransactionsExecutor = blockTransactionsExecutor ?? throw new ArgumentNullException(nameof(blockTransactionsExecutor)); _beaconBlockRootHandler = new BeaconBlockRootHandler(); - _receiptsTracer = new BlockReceiptsTracer(); + ReceiptsTracer = new BlockReceiptsTracer(); } public event EventHandler BlockProcessed; @@ -226,13 +226,13 @@ protected virtual TxReceipt[] ProcessBlock( { IReleaseSpec spec = _specProvider.GetSpec(block.Header); - _receiptsTracer.SetOtherTracer(blockTracer); - _receiptsTracer.StartNewBlockTrace(block); + ReceiptsTracer.SetOtherTracer(blockTracer); + ReceiptsTracer.StartNewBlockTrace(block); _beaconBlockRootHandler.ApplyContractStateChanges(block, spec, _stateProvider); _stateProvider.Commit(spec); - TxReceipt[] receipts = _blockTransactionsExecutor.ProcessTransactions(block, options, _receiptsTracer, spec); + TxReceipt[] receipts = _blockTransactionsExecutor.ProcessTransactions(block, options, ReceiptsTracer, spec); if (spec.IsEip4844Enabled) { @@ -242,7 +242,7 @@ protected virtual TxReceipt[] ProcessBlock( block.Header.ReceiptsRoot = receipts.GetReceiptsRoot(spec, block.ReceiptsRoot); ApplyMinerRewards(block, blockTracer, spec); _withdrawalProcessor.ProcessWithdrawals(block, spec); - _receiptsTracer.EndBlockTrace(); + ReceiptsTracer.EndBlockTrace(); _stateProvider.Commit(spec); @@ -260,7 +260,7 @@ protected virtual TxReceipt[] ProcessBlock( // TODO: block processor pipeline private void StoreTxReceipts(Block block, TxReceipt[] txReceipts) { - // Setting canonical is done by ReceiptCanonicalityMonitor on block move to main + // Setting canonical is done when the BlockAddedToMain event is firec _receiptStorage.Insert(block, txReceipts, false); } diff --git a/src/Nethermind/Nethermind.Consensus/Processing/ProcessingStats.cs b/src/Nethermind/Nethermind.Consensus/Processing/ProcessingStats.cs index 5f29f9af04e..ed6d13e5520 100644 --- a/src/Nethermind/Nethermind.Consensus/Processing/ProcessingStats.cs +++ b/src/Nethermind/Nethermind.Consensus/Processing/ProcessingStats.cs @@ -124,7 +124,7 @@ public void UpdateStats(Block? block, IBlockTree blockTreeCtx, int recoveryQueue decimal bps = chunkMicroseconds == 0 ? -1 : chunkBlocks / chunkMicroseconds * 1000 * 1000; decimal chunkMs = (chunkMicroseconds == 0 ? -1 : chunkMicroseconds / 1000); decimal runMs = (runMicroseconds == 0 ? -1 : runMicroseconds / 1000); - string blockGas = Evm.Metrics.BlockMinGasPrice != decimal.MaxValue ? $" Gas gwei: {Evm.Metrics.BlockMinGasPrice:N2} .. {whiteText}{Math.Max(Evm.Metrics.BlockMinGasPrice, Evm.Metrics.BlockEstMedianGasPrice):N2}{resetColor} ({Evm.Metrics.BlockAveGasPrice:N2}) .. {Evm.Metrics.BlockMaxGasPrice:N2}" : ""; + string blockGas = Evm.Metrics.BlockMinGasPrice != float.MaxValue ? $" Gas gwei: {Evm.Metrics.BlockMinGasPrice:N2} .. {whiteText}{Math.Max(Evm.Metrics.BlockMinGasPrice, Evm.Metrics.BlockEstMedianGasPrice):N2}{resetColor} ({Evm.Metrics.BlockAveGasPrice:N2}) .. {Evm.Metrics.BlockMaxGasPrice:N2}" : ""; if (chunkBlocks > 1) { _logger.Info($"Processed {block.Number - chunkBlocks + 1,9}...{block.Number,9} | {chunkMs,9:N2} ms | slot {runMs,7:N0} ms |{blockGas}"); diff --git a/src/Nethermind/Nethermind.Consensus/Processing/RecoverSignature.cs b/src/Nethermind/Nethermind.Consensus/Processing/RecoverSignature.cs index c9e6d56dcb6..b39602df51b 100644 --- a/src/Nethermind/Nethermind.Consensus/Processing/RecoverSignature.cs +++ b/src/Nethermind/Nethermind.Consensus/Processing/RecoverSignature.cs @@ -58,7 +58,15 @@ public void RecoverData(Block block) // Don't access txPool in Parallel loop as increases contention foreach (Transaction blockTransaction in block.Transactions.Where(tx => tx.IsSigned && tx.SenderAddress is null)) { - _txPool.TryGetPendingTransaction(blockTransaction.Hash, out Transaction? transaction); + Transaction? transaction = null; + try + { + _txPool.TryGetPendingTransaction(blockTransaction.Hash, out transaction); + } + catch (Exception e) + { + if (_logger.IsError) _logger.Error($"An error occured while getting pending a transaction from TxPool, Transaction: {blockTransaction}", e); + } Address sender = transaction?.SenderAddress; if (sender != null) diff --git a/src/Nethermind/Nethermind.Consensus/Processing/TransactionProcessorAdapterExtensions.cs b/src/Nethermind/Nethermind.Consensus/Processing/TransactionProcessorAdapterExtensions.cs index 7e92e41dd13..9b57646922a 100644 --- a/src/Nethermind/Nethermind.Consensus/Processing/TransactionProcessorAdapterExtensions.cs +++ b/src/Nethermind/Nethermind.Consensus/Processing/TransactionProcessorAdapterExtensions.cs @@ -12,7 +12,7 @@ namespace Nethermind.Consensus.Processing; internal static class TransactionProcessorAdapterExtensions { public static void ProcessTransaction(this ITransactionProcessorAdapter transactionProcessor, - BlockExecutionContext blkCtx, + in BlockExecutionContext blkCtx, Transaction currentTx, BlockReceiptsTracer receiptsTracer, ProcessingOptions processingOptions, @@ -24,7 +24,7 @@ public static void ProcessTransaction(this ITransactionProcessorAdapter transact } using ITxTracer tracer = receiptsTracer.StartNewTxTrace(currentTx); - transactionProcessor.Execute(currentTx, blkCtx, receiptsTracer); + transactionProcessor.Execute(currentTx, in blkCtx, receiptsTracer); receiptsTracer.EndTxTrace(); } } diff --git a/src/Nethermind/Nethermind.Core.Test/BlockHeaderTests.cs b/src/Nethermind/Nethermind.Core.Test/BlockHeaderTests.cs index b2c59314889..849c25d3364 100644 --- a/src/Nethermind/Nethermind.Core.Test/BlockHeaderTests.cs +++ b/src/Nethermind/Nethermind.Core.Test/BlockHeaderTests.cs @@ -114,10 +114,13 @@ public void Eip_1559_CalculateBaseFee(long gasTarget, long baseFee, long expecte IReleaseSpec releaseSpec = Substitute.For(); releaseSpec.IsEip1559Enabled.Returns(true); releaseSpec.Eip1559BaseFeeMinValue.Returns((UInt256?)minimalBaseFee); + releaseSpec.ForkBaseFee.Returns(Eip1559Constants.DefaultForkBaseFee); + releaseSpec.BaseFeeMaxChangeDenominator.Returns(Eip1559Constants.DefaultBaseFeeMaxChangeDenominator); + releaseSpec.ElasticityMultiplier.Returns(Eip1559Constants.DefaultElasticityMultiplier); BlockHeader blockHeader = Build.A.BlockHeader.TestObject; blockHeader.Number = 2001; - blockHeader.GasLimit = gasTarget * Eip1559Constants.ElasticityMultiplier; + blockHeader.GasLimit = gasTarget * Eip1559Constants.DefaultElasticityMultiplier; blockHeader.BaseFeePerGas = (UInt256)baseFee; blockHeader.GasUsed = gasUsed; UInt256 actualBaseFee = BaseFeeCalculator.Calculate(blockHeader, releaseSpec); @@ -141,10 +144,13 @@ public void Eip_1559_CalculateBaseFee_shared_test_cases((BaseFeeTestCases Info, { IReleaseSpec releaseSpec = Substitute.For(); releaseSpec.IsEip1559Enabled.Returns(true); + releaseSpec.ForkBaseFee.Returns(Eip1559Constants.DefaultForkBaseFee); + releaseSpec.BaseFeeMaxChangeDenominator.Returns(Eip1559Constants.DefaultBaseFeeMaxChangeDenominator); + releaseSpec.ElasticityMultiplier.Returns(Eip1559Constants.DefaultElasticityMultiplier); BlockHeader blockHeader = Build.A.BlockHeader.TestObject; blockHeader.Number = 2001; - blockHeader.GasLimit = testCase.Info.ParentTargetGasUsed * Eip1559Constants.ElasticityMultiplier; + blockHeader.GasLimit = testCase.Info.ParentTargetGasUsed * Eip1559Constants.DefaultElasticityMultiplier; blockHeader.BaseFeePerGas = (UInt256)testCase.Info.ParentBaseFee; blockHeader.GasUsed = testCase.Info.ParentGasUsed; UInt256 actualBaseFee = BaseFeeCalculator.Calculate(blockHeader, releaseSpec); diff --git a/src/Nethermind/Nethermind.Core.Test/Blockchain/TestBlockchain.cs b/src/Nethermind/Nethermind.Core.Test/Blockchain/TestBlockchain.cs index 4c83df1211f..4215fda3fa3 100644 --- a/src/Nethermind/Nethermind.Core.Test/Blockchain/TestBlockchain.cs +++ b/src/Nethermind/Nethermind.Core.Test/Blockchain/TestBlockchain.cs @@ -160,13 +160,13 @@ protected virtual async Task Build(ISpecProvider? specProvider = _trieStoreWatcher = new TrieStoreBoundaryWatcher(WorldStateManager, BlockTree, LogManager); - ReceiptStorage = new InMemoryReceiptStorage(); + ReceiptStorage = new InMemoryReceiptStorage(blockTree: BlockTree); VirtualMachine virtualMachine = new(new BlockhashProvider(BlockTree, LogManager), SpecProvider, LogManager); TxProcessor = new TransactionProcessor(SpecProvider, State, virtualMachine, LogManager); BlockPreprocessorStep = new RecoverSignatures(EthereumEcdsa, TxPool, SpecProvider, LogManager); HeaderValidator = new HeaderValidator(BlockTree, Always.Valid, SpecProvider, LogManager); - new ReceiptCanonicalityMonitor(BlockTree, ReceiptStorage, LogManager); + new ReceiptCanonicalityMonitor(ReceiptStorage, LogManager); BlockValidator = new BlockValidator( new TxValidator(SpecProvider.ChainId), diff --git a/src/Nethermind/Nethermind.Core.Test/Builders/BlockTreeBuilder.cs b/src/Nethermind/Nethermind.Core.Test/Builders/BlockTreeBuilder.cs index 56433437a71..b61e4b993f7 100644 --- a/src/Nethermind/Nethermind.Core.Test/Builders/BlockTreeBuilder.cs +++ b/src/Nethermind/Nethermind.Core.Test/Builders/BlockTreeBuilder.cs @@ -47,6 +47,7 @@ public BlockTreeBuilder(Block genesisBlock, ISpecProvider specProvider) BlockNumbersDb = new TestMemDb(); BlockInfoDb = new TestMemDb(); MetadataDb = new TestMemDb(); + BadBlocksDb = new TestMemDb(); _genesisBlock = genesisBlock; _specProvider = specProvider; @@ -79,6 +80,7 @@ public BlockTree BlockTree HeaderStore, BlockInfoDb, MetadataDb, + BadBlockStore, ChainLevelInfoRepository, _specProvider, BloomStorage, @@ -105,6 +107,7 @@ protected override void BeforeReturn() public ISyncConfig SyncConfig { get; set; } = new SyncConfig(); public IDb BlocksDb { get; set; } + public IDb BadBlocksDb { get; set; } private IBlockStore? _blockStore; public IBlockStore BlockStore @@ -139,6 +142,18 @@ public IHeaderStore HeaderStore public IDb MetadataDb { get; set; } + private IBlockStore? _badBlockStore; + public IBlockStore BadBlockStore + { + get + { + return _badBlockStore ??= new BlockStore(BadBlocksDb, 100); + } + set + { + _badBlockStore = value; + } + } private IChainLevelInfoRepository? _chainLevelInfoRepository; public IChainLevelInfoRepository ChainLevelInfoRepository @@ -384,6 +399,18 @@ public BlockTreeBuilder WithBlockStore(IBlockStore blockStore) return this; } + public BlockTreeBuilder WithBadBlockStore(IBlockStore blockStore) + { + BadBlockStore = blockStore; + return this; + } + + public BlockTreeBuilder WithHeaderStore(IHeaderStore headerStore) + { + HeaderStore = headerStore; + return this; + } + public BlockTreeBuilder WithBlocksDb(IDb blocksDb) { BlocksDb = blocksDb; diff --git a/src/Nethermind/Nethermind.Core/BaseFeeCalculator.cs b/src/Nethermind/Nethermind.Core/BaseFeeCalculator.cs index 70b72473a73..268997f6df9 100644 --- a/src/Nethermind/Nethermind.Core/BaseFeeCalculator.cs +++ b/src/Nethermind/Nethermind.Core/BaseFeeCalculator.cs @@ -18,7 +18,7 @@ public static UInt256 Calculate(BlockHeader parent, IEip1559Spec specFor1559) long gasDelta; UInt256 feeDelta; bool isForkBlockNumber = specFor1559.Eip1559TransitionBlock == parent.Number + 1; - long parentGasTarget = parent.GasLimit / Eip1559Constants.ElasticityMultiplier; + long parentGasTarget = parent.GasLimit / specFor1559.ElasticityMultiplier; if (isForkBlockNumber) parentGasTarget = parent.GasLimit; @@ -30,20 +30,20 @@ public static UInt256 Calculate(BlockHeader parent, IEip1559Spec specFor1559) { gasDelta = parent.GasUsed - parentGasTarget; feeDelta = UInt256.Max( - parentBaseFee * (UInt256)gasDelta / (UInt256)parentGasTarget / Eip1559Constants.BaseFeeMaxChangeDenominator, + parentBaseFee * (UInt256)gasDelta / (UInt256)parentGasTarget / specFor1559.BaseFeeMaxChangeDenominator, UInt256.One); expectedBaseFee = parentBaseFee + feeDelta; } else { gasDelta = parentGasTarget - parent.GasUsed; - feeDelta = parentBaseFee * (UInt256)gasDelta / (UInt256)parentGasTarget / Eip1559Constants.BaseFeeMaxChangeDenominator; + feeDelta = parentBaseFee * (UInt256)gasDelta / (UInt256)parentGasTarget / specFor1559.BaseFeeMaxChangeDenominator; expectedBaseFee = UInt256.Max(parentBaseFee - feeDelta, 0); } if (isForkBlockNumber) { - expectedBaseFee = Eip1559Constants.ForkBaseFee; + expectedBaseFee = specFor1559.ForkBaseFee; } if (specFor1559.Eip1559BaseFeeMinValue.HasValue) diff --git a/src/Nethermind/Nethermind.Core/Caching/LruCache.cs b/src/Nethermind/Nethermind.Core/Caching/LruCache.cs index d96a4bc8d4b..e202c3cb5a4 100644 --- a/src/Nethermind/Nethermind.Core/Caching/LruCache.cs +++ b/src/Nethermind/Nethermind.Core/Caching/LruCache.cs @@ -146,6 +146,19 @@ public KeyValuePair[] ToArray() return array; } + [MethodImpl(MethodImplOptions.Synchronized)] + public TValue[] GetValues() + { + int i = 0; + TValue[] array = new TValue[_cacheMap.Count]; + foreach (KeyValuePair> kvp in _cacheMap) + { + array[i++] = kvp.Value.Value.Value; + } + + return array; + } + private void Replace(TKey key, TValue value) { LinkedListNode? node = _leastRecentlyUsed; diff --git a/src/Nethermind/Nethermind.Core/Eip1559Constants.cs b/src/Nethermind/Nethermind.Core/Eip1559Constants.cs index c2895bed910..cab44982cae 100644 --- a/src/Nethermind/Nethermind.Core/Eip1559Constants.cs +++ b/src/Nethermind/Nethermind.Core/Eip1559Constants.cs @@ -14,10 +14,5 @@ public class Eip1559Constants public static readonly UInt256 DefaultBaseFeeMaxChangeDenominator = 8; public static readonly int DefaultElasticityMultiplier = 2; - - // The above values are the default ones. However, we're allowing to override it from genesis - public static UInt256 ForkBaseFee { get; set; } = DefaultForkBaseFee; - public static UInt256 BaseFeeMaxChangeDenominator { get; set; } = DefaultBaseFeeMaxChangeDenominator; - public static long ElasticityMultiplier { get; set; } = DefaultElasticityMultiplier; } } diff --git a/src/Nethermind/Nethermind.Core/Specs/IEip1559Spec.cs b/src/Nethermind/Nethermind.Core/Specs/IEip1559Spec.cs index 33e5723eed3..0d343448551 100644 --- a/src/Nethermind/Nethermind.Core/Specs/IEip1559Spec.cs +++ b/src/Nethermind/Nethermind.Core/Specs/IEip1559Spec.cs @@ -17,5 +17,8 @@ public interface IEip1559Spec public long Eip1559TransitionBlock { get; } public Address? Eip1559FeeCollector => null; public UInt256? Eip1559BaseFeeMinValue => null; + public UInt256 ForkBaseFee { get; } + public UInt256 BaseFeeMaxChangeDenominator { get; } + public long ElasticityMultiplier { get; } } } diff --git a/src/Nethermind/Nethermind.Core/TransactionReceipt.cs b/src/Nethermind/Nethermind.Core/TransactionReceipt.cs index ea5f9c57531..5de0b0d85f3 100644 --- a/src/Nethermind/Nethermind.Core/TransactionReceipt.cs +++ b/src/Nethermind/Nethermind.Core/TransactionReceipt.cs @@ -39,6 +39,9 @@ public class TxReceipt public LogEntry[]? Logs { get; set; } public string? Error { get; set; } + public ulong? DepositNonce { get; set; } + public ulong? DepositReceiptVersion { get; set; } + /// /// Ignores receipt output on RLP serialization. /// Output is either StateRoot or StatusCode depending on eip configuration. diff --git a/src/Nethermind/Nethermind.Db.Rocks/DbOnTheRocks.cs b/src/Nethermind/Nethermind.Db.Rocks/DbOnTheRocks.cs index 2351d3c3367..99f4b222dcb 100644 --- a/src/Nethermind/Nethermind.Db.Rocks/DbOnTheRocks.cs +++ b/src/Nethermind/Nethermind.Db.Rocks/DbOnTheRocks.cs @@ -6,7 +6,6 @@ using System.Collections.Generic; using System.IO; using System.IO.Abstractions; -using System.Net.Sockets; using System.Reflection; using System.Threading; using ConcurrentCollections; @@ -15,7 +14,6 @@ using Nethermind.Core.Crypto; using Nethermind.Core.Exceptions; using Nethermind.Core.Extensions; -using Nethermind.Core.Threading; using Nethermind.Db.Rocks.Config; using Nethermind.Db.Rocks.Statistics; using Nethermind.Logging; @@ -26,9 +24,6 @@ namespace Nethermind.Db.Rocks; public class DbOnTheRocks : IDb, ITunableDb { - private McsPriorityLock _readThrottle = new(); - private McsPriorityLock _writeThrottle = new(); - private ILogger _logger; private string? _fullPath; @@ -505,7 +500,6 @@ public byte[]? this[ReadOnlySpan key] } } - using var handle = _readThrottle.Acquire(); return _db.Get(key, cf); } catch (RocksDbSharpException e) @@ -528,7 +522,6 @@ internal void SetWithColumnFamily(ReadOnlySpan key, ColumnFamilyHandle? cf try { - using var handle = _writeThrottle.Acquire(); if (value.IsNull()) { _db.Remove(key, cf, WriteFlagsToWriteOptions(flags)); @@ -572,7 +565,6 @@ internal void SetWithColumnFamily(ReadOnlySpan key, ColumnFamilyHandle? cf { try { - using var handle = _readThrottle.Acquire(); return _db.MultiGet(keys); } catch (RocksDbSharpException e) @@ -596,11 +588,8 @@ internal Span GetSpanWithColumnFamily(ReadOnlySpan key, ColumnFamily try { - Span span; - using (var handle = _readThrottle.Acquire()) - { - span = _db.GetSpan(key, cf); - } + Span span = _db.GetSpan(key, cf); + if (!span.IsNullOrEmpty()) { Interlocked.Increment(ref _allocatedSpan); @@ -636,7 +625,6 @@ public void Remove(ReadOnlySpan key) try { - using var handle = _writeThrottle.Acquire(); _db.Remove(key, null, WriteOptions); } catch (RocksDbSharpException e) @@ -672,7 +660,10 @@ protected internal Iterator CreateIterator(bool ordered = false, ColumnFamilyHan public IEnumerable GetAllKeys(bool ordered = false) { - ObjectDisposedException.ThrowIf(_isDisposing, this); + if (_isDisposing) + { + throw new ObjectDisposedException($"Attempted to read form a disposed database {Name}"); + } Iterator iterator = CreateIterator(ordered); return GetAllKeysCore(iterator); @@ -821,7 +812,6 @@ public bool KeyExists(ReadOnlySpan key) try { - using var handle = _readThrottle.Acquire(); // seems it has no performance impact return _db.Get(key) is not null; // return _db.Get(key, 32, _keyExistsBuffer, 0, 0, null, null) != -1; @@ -900,10 +890,7 @@ public void Dispose() try { - using (var handle = _dbOnTheRocks._writeThrottle.Acquire()) - { - _dbOnTheRocks._db.Write(_rocksBatch, _dbOnTheRocks.WriteFlagsToWriteOptions(_writeFlags)); - } + _dbOnTheRocks._db.Write(_rocksBatch, _dbOnTheRocks.WriteFlagsToWriteOptions(_writeFlags)); _dbOnTheRocks._currentBatches.TryRemove(this); ReturnWriteBatch(_rocksBatch); @@ -957,10 +944,7 @@ private void FlushOnTooManyWrites() try { - using (var handle = _dbOnTheRocks._writeThrottle.Acquire()) - { - _dbOnTheRocks._db.Write(currentBatch, _dbOnTheRocks.WriteFlagsToWriteOptions(_writeFlags)); - } + _dbOnTheRocks._db.Write(currentBatch, _dbOnTheRocks.WriteFlagsToWriteOptions(_writeFlags)); ReturnWriteBatch(currentBatch); } catch (RocksDbSharpException e) diff --git a/src/Nethermind/Nethermind.Db/DbNames.cs b/src/Nethermind/Nethermind.Db/DbNames.cs index 4d9f0c21350..c6004120c0b 100644 --- a/src/Nethermind/Nethermind.Db/DbNames.cs +++ b/src/Nethermind/Nethermind.Db/DbNames.cs @@ -13,6 +13,7 @@ public static class DbNames public const string BlockNumbers = "blockNumbers"; public const string Receipts = "receipts"; public const string BlockInfos = "blockInfos"; + public const string BadBlocks = "badBlocks"; public const string Bloom = "bloom"; public const string Witness = "witness"; public const string CHT = "canonicalHashTrie"; diff --git a/src/Nethermind/Nethermind.Db/IDbProvider.cs b/src/Nethermind/Nethermind.Db/IDbProvider.cs index dce39fe558a..7c4b764ff11 100644 --- a/src/Nethermind/Nethermind.Db/IDbProvider.cs +++ b/src/Nethermind/Nethermind.Db/IDbProvider.cs @@ -22,6 +22,7 @@ public interface IDbProvider : IDisposable public IDb HeadersDb => GetDb(DbNames.Headers); public IDb BlockNumbersDb => GetDb(DbNames.BlockNumbers); public IDb BlockInfosDb => GetDb(DbNames.BlockInfos); + public IDb BadBlocksDb => GetDb(DbNames.BadBlocks); // BloomDB progress / config (does not contain blooms - they are kept in bloom storage) public IDb BloomDb => GetDb(DbNames.Bloom); diff --git a/src/Nethermind/Nethermind.Db/Metrics.cs b/src/Nethermind/Nethermind.Db/Metrics.cs index 349b7eb430e..114a5227bd1 100644 --- a/src/Nethermind/Nethermind.Db/Metrics.cs +++ b/src/Nethermind/Nethermind.Db/Metrics.cs @@ -126,6 +126,14 @@ public static class Metrics [Description("Number of Metadata DB writes.")] public static long MetadataDbWrites { get; set; } + [CounterMetric] + [Description("Number of BadBlocks DB writes.")] + public static long BadBlocksDbWrites { get; set; } + + [CounterMetric] + [Description("Number of BadBlocks DB reads.")] + public static long BadBlocksDbReads { get; set; } + [CounterMetric] [Description("Number of BlobTransactions DB reads.")] public static long BlobTransactionsDbReads { get; set; } diff --git a/src/Nethermind/Nethermind.Db/StandardDbInitializer.cs b/src/Nethermind/Nethermind.Db/StandardDbInitializer.cs index 543f9adf8ea..d3832216b0d 100644 --- a/src/Nethermind/Nethermind.Db/StandardDbInitializer.cs +++ b/src/Nethermind/Nethermind.Db/StandardDbInitializer.cs @@ -41,6 +41,7 @@ private void RegisterAll(bool useReceiptsDb, bool useBlobsDb) RegisterDb(BuildRocksDbSettings(DbNames.Headers, () => Metrics.HeaderDbReads++, () => Metrics.HeaderDbWrites++)); RegisterDb(BuildRocksDbSettings(DbNames.BlockNumbers, () => Metrics.BlockNumberDbReads++, () => Metrics.BlockNumberDbWrites++)); RegisterDb(BuildRocksDbSettings(DbNames.BlockInfos, () => Metrics.BlockInfosDbReads++, () => Metrics.BlockInfosDbWrites++)); + RegisterDb(BuildRocksDbSettings(DbNames.BadBlocks, () => Metrics.BadBlocksDbReads++, () => Metrics.BadBlocksDbWrites++)); RocksDbSettings stateDbSettings = BuildRocksDbSettings(DbNames.State, () => Metrics.StateDbReads++, () => Metrics.StateDbWrites++); RegisterCustomDb(DbNames.State, () => new FullPruningDb( diff --git a/src/Nethermind/Nethermind.Evm/ExecutionEnvironment.cs b/src/Nethermind/Nethermind.Evm/ExecutionEnvironment.cs index afd332d5a39..ec6600fef8e 100644 --- a/src/Nethermind/Nethermind.Evm/ExecutionEnvironment.cs +++ b/src/Nethermind/Nethermind.Evm/ExecutionEnvironment.cs @@ -17,7 +17,7 @@ public ExecutionEnvironment Address caller, Address? codeSource, ReadOnlyMemory inputData, - TxExecutionContext txExecutionContext, + in TxExecutionContext txExecutionContext, UInt256 transferValue, UInt256 value, int callDepth = 0) diff --git a/src/Nethermind/Nethermind.Evm/Metrics.cs b/src/Nethermind/Nethermind.Evm/Metrics.cs index b904d0cd249..f9d16abd6c3 100644 --- a/src/Nethermind/Nethermind.Evm/Metrics.cs +++ b/src/Nethermind/Nethermind.Evm/Metrics.cs @@ -90,23 +90,23 @@ public class Metrics [Description("Number of contract create calls.")] public static long Creates { get; set; } internal static long Transactions { get; set; } - internal static decimal AveGasPrice { get; set; } - internal static decimal MinGasPrice { get; set; } = decimal.MaxValue; - internal static decimal MaxGasPrice { get; set; } - internal static decimal EstMedianGasPrice { get; set; } + internal static float AveGasPrice { get; set; } + internal static float MinGasPrice { get; set; } = float.MaxValue; + internal static float MaxGasPrice { get; set; } + internal static float EstMedianGasPrice { get; set; } internal static long BlockTransactions { get; set; } - internal static decimal BlockAveGasPrice { get; set; } - internal static decimal BlockMinGasPrice { get; set; } = decimal.MaxValue; - internal static decimal BlockMaxGasPrice { get; set; } - internal static decimal BlockEstMedianGasPrice { get; set; } + internal static float BlockAveGasPrice { get; set; } + internal static float BlockMinGasPrice { get; set; } = float.MaxValue; + internal static float BlockMaxGasPrice { get; set; } + internal static float BlockEstMedianGasPrice { get; set; } public static void ResetBlockStats() { BlockTransactions = 0; - BlockAveGasPrice = 0m; - BlockMaxGasPrice = 0m; - BlockEstMedianGasPrice = 0m; - BlockMinGasPrice = decimal.MaxValue; + BlockAveGasPrice = 0.0f; + BlockMaxGasPrice = 0.0f; + BlockEstMedianGasPrice = 0.0f; + BlockMinGasPrice = float.MaxValue; } } diff --git a/src/Nethermind/Nethermind.Evm/Tracing/BlockReceiptsTracer.cs b/src/Nethermind/Nethermind.Evm/Tracing/BlockReceiptsTracer.cs index 5c456e673b8..c43469bd91c 100644 --- a/src/Nethermind/Nethermind.Evm/Tracing/BlockReceiptsTracer.cs +++ b/src/Nethermind/Nethermind.Evm/Tracing/BlockReceiptsTracer.cs @@ -12,7 +12,7 @@ namespace Nethermind.Evm.Tracing; public class BlockReceiptsTracer : IBlockTracer, ITxTracer, IJournal, ITxTracerWrapper { - private Block _block = null!; + protected Block Block = null!; public bool IsTracingReceipt => true; public bool IsTracingActions => _currentTxTracer.IsTracingActions; public bool IsTracingOpLevelStorage => _currentTxTracer.IsTracingOpLevelStorage; @@ -42,7 +42,8 @@ public void MarkAsSuccess(Address recipient, long gasSpent, byte[] output, LogEn if (_currentTxTracer.IsTracingReceipt) { - _currentTxTracer.MarkAsSuccess(recipient, gasSpent, output, logs); + // TODO: is no stateRoot a bug? + _currentTxTracer.MarkAsSuccess(recipient, gasSpent, output, logs, null); } } @@ -58,30 +59,31 @@ public void MarkAsFailed(Address recipient, long gasSpent, byte[] output, string if (_currentTxTracer.IsTracingReceipt) { - _currentTxTracer.MarkAsFailed(recipient, gasSpent, output, error); + // TODO: is no stateRoot a bug? + _currentTxTracer.MarkAsFailed(recipient, gasSpent, output, error, null); } } - private TxReceipt BuildFailedReceipt(Address recipient, long gasSpent, string error, Hash256? stateRoot = null) + protected TxReceipt BuildFailedReceipt(Address recipient, long gasSpent, string error, Hash256? stateRoot) { TxReceipt receipt = BuildReceipt(recipient, gasSpent, StatusCode.Failure, Array.Empty(), stateRoot); receipt.Error = error; return receipt; } - private TxReceipt BuildReceipt(Address recipient, long spentGas, byte statusCode, LogEntry[] logEntries, Hash256? stateRoot = null) + protected virtual TxReceipt BuildReceipt(Address recipient, long spentGas, byte statusCode, LogEntry[] logEntries, Hash256? stateRoot) { - Transaction transaction = _currentTx!; + Transaction transaction = CurrentTx!; TxReceipt txReceipt = new() { Logs = logEntries, TxType = transaction.Type, Bloom = logEntries.Length == 0 ? Bloom.Empty : new Bloom(logEntries), - GasUsedTotal = _block.GasUsed, + GasUsedTotal = Block.GasUsed, StatusCode = statusCode, Recipient = transaction.IsContractCreation ? null : recipient, - BlockHash = _block.Hash, - BlockNumber = _block.Number, + BlockHash = Block.Hash, + BlockNumber = Block.Number, Index = _currentIndex, GasUsed = spentGas, Sender = transaction.SenderAddress, @@ -193,7 +195,7 @@ public void ReportFees(UInt256 fees, UInt256 burntFees) private ITxTracer _currentTxTracer = NullTxTracer.Instance; private int _currentIndex; private readonly List _txReceipts = new(); - private Transaction? _currentTx; + protected Transaction? CurrentTx; public IReadOnlyList TxReceipts => _txReceipts; public TxReceipt LastReceipt => _txReceipts[^1]; public bool IsTracingRewards => _otherTracer.IsTracingRewards; @@ -211,7 +213,7 @@ public void Restore(int snapshot) _txReceipts.RemoveAt(_txReceipts.Count - 1); } - _block.Header.GasUsed = _txReceipts.Count > 0 ? _txReceipts.Last().GasUsedTotal : 0; + Block.Header.GasUsed = _txReceipts.Count > 0 ? _txReceipts.Last().GasUsedTotal : 0; } public void ReportReward(Address author, string rewardType, UInt256 rewardValue) => @@ -224,7 +226,7 @@ public void StartNewBlockTrace(Block block) throw new InvalidOperationException("other tracer not set in receipts tracer"); } - _block = block; + Block = block; _currentIndex = 0; _txReceipts.Clear(); @@ -233,7 +235,7 @@ public void StartNewBlockTrace(Block block) public ITxTracer StartNewTxTrace(Transaction? tx) { - _currentTx = tx; + CurrentTx = tx; _currentTxTracer = _otherTracer.StartNewTxTrace(tx); return _currentTxTracer; } @@ -250,7 +252,7 @@ public void EndBlockTrace() if (_txReceipts.Count > 0) { Bloom blockBloom = new(); - _block.Header.Bloom = blockBloom; + Block.Header.Bloom = blockBloom; for (int index = 0; index < _txReceipts.Count; index++) { TxReceipt? receipt = _txReceipts[index]; diff --git a/src/Nethermind/Nethermind.Evm/Tracing/GasEstimator.cs b/src/Nethermind/Nethermind.Evm/Tracing/GasEstimator.cs index 7ae1c6c64a3..a2ddc2c0397 100644 --- a/src/Nethermind/Nethermind.Evm/Tracing/GasEstimator.cs +++ b/src/Nethermind/Nethermind.Evm/Tracing/GasEstimator.cs @@ -89,7 +89,7 @@ private bool TryExecutableTransaction(Transaction transaction, BlockHeader block transaction.GasLimit = gasLimit; BlockExecutionContext blCtx = new(block); - _transactionProcessor.CallAndRestore(transaction, blCtx, tracer.WithCancellation(token)); + _transactionProcessor.CallAndRestore(transaction, in blCtx, tracer.WithCancellation(token)); transaction.GasLimit = originalGasLimit; diff --git a/src/Nethermind/Nethermind.Evm/TransactionProcessing/BuildUpTransactionProcessorAdapter.cs b/src/Nethermind/Nethermind.Evm/TransactionProcessing/BuildUpTransactionProcessorAdapter.cs index 3583b6480b9..acfb1c7d295 100644 --- a/src/Nethermind/Nethermind.Evm/TransactionProcessing/BuildUpTransactionProcessorAdapter.cs +++ b/src/Nethermind/Nethermind.Evm/TransactionProcessing/BuildUpTransactionProcessorAdapter.cs @@ -15,7 +15,7 @@ public BuildUpTransactionProcessorAdapter(ITransactionProcessor transactionProce _transactionProcessor = transactionProcessor; } - public void Execute(Transaction transaction, BlockExecutionContext blkCtx, ITxTracer txTracer) => - _transactionProcessor.BuildUp(transaction, blkCtx, txTracer); + public void Execute(Transaction transaction, in BlockExecutionContext blkCtx, ITxTracer txTracer) => + _transactionProcessor.BuildUp(transaction, in blkCtx, txTracer); } } diff --git a/src/Nethermind/Nethermind.Evm/TransactionProcessing/CallAndRestoreTransactionProcessorAdapter.cs b/src/Nethermind/Nethermind.Evm/TransactionProcessing/CallAndRestoreTransactionProcessorAdapter.cs index 7042c9337a1..d518b5ee279 100644 --- a/src/Nethermind/Nethermind.Evm/TransactionProcessing/CallAndRestoreTransactionProcessorAdapter.cs +++ b/src/Nethermind/Nethermind.Evm/TransactionProcessing/CallAndRestoreTransactionProcessorAdapter.cs @@ -15,7 +15,7 @@ public CallAndRestoreTransactionProcessorAdapter(ITransactionProcessor transacti _transactionProcessor = transactionProcessor; } - public void Execute(Transaction transaction, BlockExecutionContext blkCtx, ITxTracer txTracer) => - _transactionProcessor.CallAndRestore(transaction, blkCtx, txTracer); + public void Execute(Transaction transaction, in BlockExecutionContext blkCtx, ITxTracer txTracer) => + _transactionProcessor.CallAndRestore(transaction, in blkCtx, txTracer); } } diff --git a/src/Nethermind/Nethermind.Evm/TransactionProcessing/ChangeableTransactionProcessorAdapter.cs b/src/Nethermind/Nethermind.Evm/TransactionProcessing/ChangeableTransactionProcessorAdapter.cs index 231950c656c..661a6698820 100644 --- a/src/Nethermind/Nethermind.Evm/TransactionProcessing/ChangeableTransactionProcessorAdapter.cs +++ b/src/Nethermind/Nethermind.Evm/TransactionProcessing/ChangeableTransactionProcessorAdapter.cs @@ -22,9 +22,9 @@ public ChangeableTransactionProcessorAdapter(ITransactionProcessor transactionPr TransactionProcessor = transactionProcessor; } - public void Execute(Transaction transaction, BlockExecutionContext blkCtx, ITxTracer txTracer) + public void Execute(Transaction transaction, in BlockExecutionContext blkCtx, ITxTracer txTracer) { - CurrentAdapter.Execute(transaction, blkCtx, txTracer); + CurrentAdapter.Execute(transaction, in blkCtx, txTracer); } } } diff --git a/src/Nethermind/Nethermind.Evm/TransactionProcessing/ExecuteTransactionProcessorAdapter.cs b/src/Nethermind/Nethermind.Evm/TransactionProcessing/ExecuteTransactionProcessorAdapter.cs index 2b4967dd3cd..b0f51de953e 100644 --- a/src/Nethermind/Nethermind.Evm/TransactionProcessing/ExecuteTransactionProcessorAdapter.cs +++ b/src/Nethermind/Nethermind.Evm/TransactionProcessing/ExecuteTransactionProcessorAdapter.cs @@ -15,7 +15,7 @@ public ExecuteTransactionProcessorAdapter(ITransactionProcessor transactionProce _transactionProcessor = transactionProcessor; } - public void Execute(Transaction transaction, BlockExecutionContext blkCtx, ITxTracer txTracer) => - _transactionProcessor.Execute(transaction, blkCtx, txTracer); + public void Execute(Transaction transaction, in BlockExecutionContext blkCtx, ITxTracer txTracer) => + _transactionProcessor.Execute(transaction, in blkCtx, txTracer); } } diff --git a/src/Nethermind/Nethermind.Evm/TransactionProcessing/ITransactionProcessor.cs b/src/Nethermind/Nethermind.Evm/TransactionProcessing/ITransactionProcessor.cs index 972ac5be1d8..21973ee817a 100644 --- a/src/Nethermind/Nethermind.Evm/TransactionProcessing/ITransactionProcessor.cs +++ b/src/Nethermind/Nethermind.Evm/TransactionProcessing/ITransactionProcessor.cs @@ -11,21 +11,21 @@ public interface ITransactionProcessor /// /// Execute transaction, commit state /// - void Execute(Transaction transaction, BlockExecutionContext blCtx, ITxTracer txTracer); + void Execute(Transaction transaction, in BlockExecutionContext blCtx, ITxTracer txTracer); /// /// Call transaction, rollback state /// - void CallAndRestore(Transaction transaction, BlockExecutionContext blCtx, ITxTracer txTracer); + void CallAndRestore(Transaction transaction, in BlockExecutionContext blCtx, ITxTracer txTracer); /// /// Execute transaction, keep the state uncommitted /// - void BuildUp(Transaction transaction, BlockExecutionContext blCtx, ITxTracer txTracer); + void BuildUp(Transaction transaction, in BlockExecutionContext blCtx, ITxTracer txTracer); /// /// Call transaction, no validations, commit state /// Will NOT charge gas from sender account, so stateDiff will miss gas fee /// - void Trace(Transaction transaction, BlockExecutionContext blCtx, ITxTracer txTracer); + void Trace(Transaction transaction, in BlockExecutionContext blCtx, ITxTracer txTracer); } diff --git a/src/Nethermind/Nethermind.Evm/TransactionProcessing/ITransactionProcessorAdapter.cs b/src/Nethermind/Nethermind.Evm/TransactionProcessing/ITransactionProcessorAdapter.cs index 06ab48f127e..4f09f301792 100644 --- a/src/Nethermind/Nethermind.Evm/TransactionProcessing/ITransactionProcessorAdapter.cs +++ b/src/Nethermind/Nethermind.Evm/TransactionProcessing/ITransactionProcessorAdapter.cs @@ -8,6 +8,6 @@ namespace Nethermind.Evm.TransactionProcessing { public interface ITransactionProcessorAdapter { - void Execute(Transaction transaction, BlockExecutionContext blkCtx, ITxTracer txTracer); + void Execute(Transaction transaction, in BlockExecutionContext blkCtx, ITxTracer txTracer); } } diff --git a/src/Nethermind/Nethermind.Evm/TransactionProcessing/ReadOnlyTransactionProcessor.cs b/src/Nethermind/Nethermind.Evm/TransactionProcessing/ReadOnlyTransactionProcessor.cs index 97c68f0aec2..f6999143fd9 100644 --- a/src/Nethermind/Nethermind.Evm/TransactionProcessing/ReadOnlyTransactionProcessor.cs +++ b/src/Nethermind/Nethermind.Evm/TransactionProcessing/ReadOnlyTransactionProcessor.cs @@ -23,17 +23,17 @@ public ReadOnlyTransactionProcessor(ITransactionProcessor transactionProcessor, _stateProvider.StateRoot = startState ?? throw new ArgumentNullException(nameof(startState)); } - public void Execute(Transaction transaction, BlockExecutionContext blCtx, ITxTracer txTracer) => - _transactionProcessor.Execute(transaction, blCtx, txTracer); + public void Execute(Transaction transaction, in BlockExecutionContext blCtx, ITxTracer txTracer) => + _transactionProcessor.Execute(transaction, in blCtx, txTracer); - public void CallAndRestore(Transaction transaction, BlockExecutionContext blCtx, ITxTracer txTracer) => - _transactionProcessor.CallAndRestore(transaction, blCtx, txTracer); + public void CallAndRestore(Transaction transaction, in BlockExecutionContext blCtx, ITxTracer txTracer) => + _transactionProcessor.CallAndRestore(transaction, in blCtx, txTracer); - public void BuildUp(Transaction transaction, BlockExecutionContext blCtx, ITxTracer txTracer) => - _transactionProcessor.BuildUp(transaction, blCtx, txTracer); + public void BuildUp(Transaction transaction, in BlockExecutionContext blCtx, ITxTracer txTracer) => + _transactionProcessor.BuildUp(transaction, in blCtx, txTracer); - public void Trace(Transaction transaction, BlockExecutionContext blCtx, ITxTracer txTracer) => - _transactionProcessor.Trace(transaction, blCtx, txTracer); + public void Trace(Transaction transaction, in BlockExecutionContext blCtx, ITxTracer txTracer) => + _transactionProcessor.Trace(transaction, in blCtx, txTracer); public bool IsContractDeployed(Address address) => _stateProvider.IsContract(address); diff --git a/src/Nethermind/Nethermind.Evm/TransactionProcessing/TraceTransactionProcessorAdapter.cs b/src/Nethermind/Nethermind.Evm/TransactionProcessing/TraceTransactionProcessorAdapter.cs index 3b51b89ccee..6c75c5b5e19 100644 --- a/src/Nethermind/Nethermind.Evm/TransactionProcessing/TraceTransactionProcessorAdapter.cs +++ b/src/Nethermind/Nethermind.Evm/TransactionProcessing/TraceTransactionProcessorAdapter.cs @@ -15,7 +15,7 @@ public TraceTransactionProcessorAdapter(ITransactionProcessor transactionProcess _transactionProcessor = transactionProcessor; } - public void Execute(Transaction transaction, BlockExecutionContext blkCtx, ITxTracer txTracer) => - _transactionProcessor.Trace(transaction, blkCtx, txTracer); + public void Execute(Transaction transaction, in BlockExecutionContext blkCtx, ITxTracer txTracer) => + _transactionProcessor.Trace(transaction, in blkCtx, txTracer); } } diff --git a/src/Nethermind/Nethermind.Evm/TransactionProcessing/TransactionProcessor.cs b/src/Nethermind/Nethermind.Evm/TransactionProcessing/TransactionProcessor.cs index 8eb05afb4be..e5f954c2aab 100644 --- a/src/Nethermind/Nethermind.Evm/TransactionProcessing/TransactionProcessor.cs +++ b/src/Nethermind/Nethermind.Evm/TransactionProcessing/TransactionProcessor.cs @@ -72,30 +72,30 @@ public TransactionProcessor( Ecdsa = new EthereumEcdsa(specProvider.ChainId, logManager); } - public void CallAndRestore(Transaction transaction, BlockExecutionContext blCtx, ITxTracer txTracer) + public void CallAndRestore(Transaction transaction, in BlockExecutionContext blCtx, ITxTracer txTracer) { - Execute(transaction, blCtx, txTracer, ExecutionOptions.CommitAndRestore); + Execute(transaction, in blCtx, txTracer, ExecutionOptions.CommitAndRestore); } - public void BuildUp(Transaction transaction, BlockExecutionContext blCtx, ITxTracer txTracer) + public void BuildUp(Transaction transaction, in BlockExecutionContext blCtx, ITxTracer txTracer) { // we need to treat the result of previous transaction as the original value of next transaction // when we do not commit WorldState.TakeSnapshot(true); - Execute(transaction, blCtx, txTracer, ExecutionOptions.None); + Execute(transaction, in blCtx, txTracer, ExecutionOptions.None); } - public void Execute(Transaction transaction, BlockExecutionContext blCtx, ITxTracer txTracer) + public void Execute(Transaction transaction, in BlockExecutionContext blCtx, ITxTracer txTracer) { - Execute(transaction, blCtx, txTracer, ExecutionOptions.Commit); + Execute(transaction, in blCtx, txTracer, ExecutionOptions.Commit); } - public void Trace(Transaction transaction, BlockExecutionContext blCtx, ITxTracer txTracer) + public void Trace(Transaction transaction, in BlockExecutionContext blCtx, ITxTracer txTracer) { - Execute(transaction, blCtx, txTracer, ExecutionOptions.NoValidation); + Execute(transaction, in blCtx, txTracer, ExecutionOptions.NoValidation); } - protected virtual void Execute(Transaction tx, BlockExecutionContext blCtx, ITxTracer tracer, ExecutionOptions opts) + protected virtual void Execute(Transaction tx, in BlockExecutionContext blCtx, ITxTracer tracer, ExecutionOptions opts) { BlockHeader header = blCtx.Header; IReleaseSpec spec = SpecProvider.GetSpec(header); @@ -117,7 +117,7 @@ protected virtual void Execute(Transaction tx, BlockExecutionContext blCtx, ITxT if (opts == ExecutionOptions.Commit || opts == ExecutionOptions.None) { - decimal gasPrice = (decimal)effectiveGasPrice / 1_000_000_000m; + float gasPrice = (float)((double)effectiveGasPrice / 1_000_000_000.0); Metrics.MinGasPrice = Math.Min(gasPrice, Metrics.MinGasPrice); Metrics.MaxGasPrice = Math.Max(gasPrice, Metrics.MaxGasPrice); @@ -125,11 +125,11 @@ protected virtual void Execute(Transaction tx, BlockExecutionContext blCtx, ITxT Metrics.BlockMaxGasPrice = Math.Max(gasPrice, Metrics.BlockMaxGasPrice); Metrics.AveGasPrice = (Metrics.AveGasPrice * Metrics.Transactions + gasPrice) / (Metrics.Transactions + 1); - Metrics.EstMedianGasPrice += Metrics.AveGasPrice * 0.01m * decimal.Sign(gasPrice - Metrics.EstMedianGasPrice); + Metrics.EstMedianGasPrice += Metrics.AveGasPrice * 0.01f * float.Sign(gasPrice - Metrics.EstMedianGasPrice); Metrics.Transactions++; Metrics.BlockAveGasPrice = (Metrics.BlockAveGasPrice * Metrics.BlockTransactions + gasPrice) / (Metrics.BlockTransactions + 1); - Metrics.BlockEstMedianGasPrice += Metrics.BlockAveGasPrice * 0.01m * decimal.Sign(gasPrice - Metrics.BlockEstMedianGasPrice); + Metrics.BlockEstMedianGasPrice += Metrics.BlockAveGasPrice * 0.01f * float.Sign(gasPrice - Metrics.BlockEstMedianGasPrice); Metrics.BlockTransactions++; } @@ -147,7 +147,7 @@ protected virtual void Execute(Transaction tx, BlockExecutionContext blCtx, ITxT if (commit) WorldState.Commit(spec, tracer.IsTracingState ? tracer : NullTxTracer.Instance); - ExecutionEnvironment env = BuildExecutionEnvironmnet(tx, blCtx, spec, tracer, opts, effectiveGasPrice); + ExecutionEnvironment env = BuildExecutionEnvironmnet(tx, in blCtx, spec, tracer, opts, effectiveGasPrice); long gasAvailable = tx.GasLimit - intrinsicGas; if (!ExecuteEVMCall(tx, header, spec, tracer, opts, gasAvailable, env, out TransactionSubstate? substate, out long spentGas, out byte statusCode)) @@ -433,7 +433,7 @@ protected virtual bool IncrementNonce(Transaction tx, BlockHeader header, IRelea } protected virtual ExecutionEnvironment BuildExecutionEnvironmnet( - Transaction tx, BlockExecutionContext blCtx, IReleaseSpec spec, ITxTracer tracer, ExecutionOptions opts, + Transaction tx, in BlockExecutionContext blCtx, IReleaseSpec spec, ITxTracer tracer, ExecutionOptions opts, in UInt256 effectiveGasPrice) { Address recipient = tx.GetRecipient(tx.IsContractCreation ? WorldState.GetNonce(tx.SenderAddress) : 0) ?? @@ -441,7 +441,7 @@ protected virtual ExecutionEnvironment BuildExecutionEnvironmnet( throw new InvalidDataException("Recipient has not been resolved properly before tx execution"); TxExecutionContext executionContext = - new(blCtx, tx.SenderAddress, effectiveGasPrice, tx.BlobVersionedHashes); + new(in blCtx, tx.SenderAddress, effectiveGasPrice, tx.BlobVersionedHashes); CodeInfo codeInfo = tx.IsContractCreation ? new(tx.Data.AsArray()) : VirtualMachine.GetCachedCodeInfo(WorldState, recipient, spec); @@ -450,7 +450,7 @@ protected virtual ExecutionEnvironment BuildExecutionEnvironmnet( return new ExecutionEnvironment ( - txExecutionContext: executionContext, + txExecutionContext: in executionContext, value: tx.Value, transferValue: tx.Value, caller: tx.SenderAddress, diff --git a/src/Nethermind/Nethermind.Evm/TxExecutionContext.cs b/src/Nethermind/Nethermind.Evm/TxExecutionContext.cs index 2e00bddb906..637c6fc0258 100644 --- a/src/Nethermind/Nethermind.Evm/TxExecutionContext.cs +++ b/src/Nethermind/Nethermind.Evm/TxExecutionContext.cs @@ -13,7 +13,7 @@ public readonly struct TxExecutionContext public UInt256 GasPrice { get; } public byte[][]? BlobVersionedHashes { get; } - public TxExecutionContext(BlockExecutionContext blockExecutionContext, Address origin, in UInt256 gasPrice, byte[][] blobVersionedHashes) + public TxExecutionContext(in BlockExecutionContext blockExecutionContext, Address origin, in UInt256 gasPrice, byte[][] blobVersionedHashes) { BlockExecutionContext = blockExecutionContext; Origin = origin; diff --git a/src/Nethermind/Nethermind.Evm/VirtualMachine.cs b/src/Nethermind/Nethermind.Evm/VirtualMachine.cs index 3ddd12fbc2d..d388f58a775 100644 --- a/src/Nethermind/Nethermind.Evm/VirtualMachine.cs +++ b/src/Nethermind/Nethermind.Evm/VirtualMachine.cs @@ -2297,7 +2297,7 @@ private EvmExceptionType InstructionCall( ExecutionEnvironment callEnv = new ( - txExecutionContext: env.TxExecutionContext, + txExecutionContext: in env.TxExecutionContext, callDepth: env.CallDepth + 1, caller: caller, codeSource: codeSource, @@ -2535,7 +2535,7 @@ private EvmExceptionType InstructionSelfDestruct(EvmState vmState, ref ExecutionEnvironment callEnv = new ( - txExecutionContext: env.TxExecutionContext, + txExecutionContext: in env.TxExecutionContext, callDepth: env.CallDepth + 1, caller: env.ExecutingAccount, executingAccount: contractAddress, diff --git a/src/Nethermind/Nethermind.Init/Steps/InitializeBlockTree.cs b/src/Nethermind/Nethermind.Init/Steps/InitializeBlockTree.cs index bd4036393c9..404a6c997a9 100644 --- a/src/Nethermind/Nethermind.Init/Steps/InitializeBlockTree.cs +++ b/src/Nethermind/Nethermind.Init/Steps/InitializeBlockTree.cs @@ -52,12 +52,14 @@ public Task Execute(CancellationToken cancellationToken) IBlockStore blockStore = new BlockStore(_get.DbProvider.BlocksDb); IHeaderStore headerStore = new HeaderStore(_get.DbProvider.HeadersDb, _get.DbProvider.BlockNumbersDb); + IBlockStore badBlockStore = _set.BadBlocksStore = new BlockStore(_get.DbProvider.BadBlocksDb, initConfig.BadBlocksStored); IBlockTree blockTree = _set.BlockTree = new BlockTree( blockStore, headerStore, _get.DbProvider.BlockInfosDb, _get.DbProvider.MetadataDb, + badBlockStore, chainLevelInfoRepository, _get.SpecProvider, bloomStorage, diff --git a/src/Nethermind/Nethermind.Init/Steps/InitializeBlockchain.cs b/src/Nethermind/Nethermind.Init/Steps/InitializeBlockchain.cs index 798b19e6b91..f87e07b38f7 100644 --- a/src/Nethermind/Nethermind.Init/Steps/InitializeBlockchain.cs +++ b/src/Nethermind/Nethermind.Init/Steps/InitializeBlockchain.cs @@ -73,7 +73,7 @@ protected virtual Task InitBlockchain() IStateReader stateReader = setApi.StateReader!; ITxPool txPool = _api.TxPool = CreateTxPool(); - ReceiptCanonicalityMonitor receiptCanonicalityMonitor = new(getApi.BlockTree, getApi.ReceiptStorage, _api.LogManager); + ReceiptCanonicalityMonitor receiptCanonicalityMonitor = new(getApi.ReceiptStorage, _api.LogManager); getApi.DisposeStack.Push(receiptCanonicalityMonitor); _api.ReceiptMonitor = receiptCanonicalityMonitor; diff --git a/src/Nethermind/Nethermind.Init/Steps/RegisterRpcModules.cs b/src/Nethermind/Nethermind.Init/Steps/RegisterRpcModules.cs index 9d318bcb3dd..298c969c97c 100644 --- a/src/Nethermind/Nethermind.Init/Steps/RegisterRpcModules.cs +++ b/src/Nethermind/Nethermind.Init/Steps/RegisterRpcModules.cs @@ -29,7 +29,6 @@ using Nethermind.Network.Config; using Nethermind.JsonRpc.Modules.Rpc; using Nethermind.Serialization.Json; -using Nethermind.Blockchain; namespace Nethermind.Init.Steps; @@ -117,6 +116,7 @@ public virtual async Task Execute(CancellationToken cancellationToken) if (_api.KeyStore is null) throw new StepDependencyException(nameof(_api.KeyStore)); if (_api.PeerPool is null) throw new StepDependencyException(nameof(_api.PeerPool)); if (_api.WitnessRepository is null) throw new StepDependencyException(nameof(_api.WitnessRepository)); + if (_api.BadBlocksStore is null) throw new StepDependencyException(nameof(_api.BadBlocksStore)); ProofModuleFactory proofModuleFactory = new(_api.WorldStateManager, _api.BlockTree, _api.BlockPreprocessor, _api.ReceiptFinder, _api.SpecProvider, _api.LogManager); rpcModuleProvider.RegisterBounded(proofModuleFactory, 2, rpcConfig.Timeout); @@ -134,6 +134,7 @@ public virtual async Task Execute(CancellationToken cancellationToken) _api.ConfigProvider, _api.SpecProvider, _api.SyncModeSelector, + _api.BadBlocksStore, _api.FileSystem, _api.LogManager); rpcModuleProvider.RegisterBoundedByCpuCount(debugModuleFactory, rpcConfig.Timeout); @@ -166,31 +167,21 @@ public virtual async Task Execute(CancellationToken cancellationToken) ManualPruningTrigger pruningTrigger = new(); _api.PruningTrigger.Add(pruningTrigger); - - IEraExporter eraService = new EraExporter( - _api.FileSystem, - _api.BlockTree, - _api.ReceiptStorage, - _api.SpecProvider, - BlockchainIds.GetBlockchainName(_api.SpecProvider.NetworkId), - _api.LogManager); AdminRpcModule adminRpcModule = new( _api.BlockTree, networkConfig, _api.PeerPool, _api.StaticNodesManager, _api.Enode, - eraService, initConfig.BaseDbPath, - pruningTrigger, - _api.ProcessExitToken!); + pruningTrigger); rpcModuleProvider.RegisterSingle(adminRpcModule); if (_api.TxPoolInfoProvider is null) throw new StepDependencyException(nameof(_api.TxPoolInfoProvider)); TxPoolRpcModule txPoolRpcModule = new(_api.TxPoolInfoProvider, _api.LogManager); rpcModuleProvider.RegisterSingle(txPoolRpcModule); - + if (_api.SyncServer is null) throw new StepDependencyException(nameof(_api.SyncServer)); if (_api.EngineSignerStore is null) throw new StepDependencyException(nameof(_api.EngineSignerStore)); diff --git a/src/Nethermind/Nethermind.JsonRpc.Benchmark/EthModuleBenchmarks.cs b/src/Nethermind/Nethermind.JsonRpc.Benchmark/EthModuleBenchmarks.cs index c846f9c8169..a0fc56d439d 100644 --- a/src/Nethermind/Nethermind.JsonRpc.Benchmark/EthModuleBenchmarks.cs +++ b/src/Nethermind/Nethermind.JsonRpc.Benchmark/EthModuleBenchmarks.cs @@ -73,6 +73,7 @@ public void GlobalSetup() new HeaderStore(dbProvider.HeadersDb, dbProvider.BlockNumbersDb), dbProvider.BlockInfosDb, dbProvider.MetadataDb, + new BlockStore(dbProvider.BadBlocksDb), chainLevelInfoRepository, specProvider, NullBloomStorage.Instance, diff --git a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/DebugModuleTests.cs b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/DebugModuleTests.cs index ed059c86e65..8b1a48dd697 100644 --- a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/DebugModuleTests.cs +++ b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/DebugModuleTests.cs @@ -4,17 +4,20 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Runtime.CompilerServices; using System.Threading; using System.Threading.Tasks; using FluentAssertions; +using Nethermind.Blockchain; +using Nethermind.Blockchain.Blocks; using Nethermind.Blockchain.Find; using Nethermind.Config; using Nethermind.Core; using Nethermind.Core.Crypto; using Nethermind.Core.Extensions; using Nethermind.Core.Test.Builders; +using Nethermind.Db; using Nethermind.Evm.Tracing.GethStyle; +using Nethermind.Int256; using Nethermind.JsonRpc.Data; using Nethermind.JsonRpc.Modules.DebugModule; using Nethermind.Logging; @@ -31,6 +34,7 @@ public class DebugModuleTests { private readonly IJsonRpcConfig jsonRpcConfig = new JsonRpcConfig(); private readonly IDebugBridge debugBridge = Substitute.For(); + private MemDb _blocksDb = new(); [Test] public async Task Get_from_db() @@ -39,6 +43,7 @@ public async Task Get_from_db() byte[] value = new byte[] { 4, 5, 6 }; debugBridge.GetDbValue(Arg.Any(), Arg.Any()).Returns(value); + IConfigProvider configProvider = Substitute.For(); DebugRpcModule rpcModule = new(LimboLogs.Instance, debugBridge, jsonRpcConfig); JsonRpcSuccessResponse? response = @@ -221,6 +226,46 @@ public async Task Get_trace_with_options() Assert.That(response, Is.EqualTo("{\"jsonrpc\":\"2.0\",\"result\":{\"gas\":\"0x0\",\"failed\":false,\"returnValue\":\"0xa2\",\"structLogs\":[{\"pc\":0,\"op\":\"STOP\",\"gas\":22000,\"gasCost\":1,\"depth\":1,\"error\":null,\"stack\":[],\"memory\":[\"0000000000000000000000000000000000000000000000000000000000000005\",\"0000000000000000000000000000000000000000000000000000000000000006\"],\"storage\":{\"0000000000000000000000000000000000000000000000000000000000000001\":\"0000000000000000000000000000000000000000000000000000000000000002\",\"0000000000000000000000000000000000000000000000000000000000000003\":\"0000000000000000000000000000000000000000000000000000000000000004\"}}]},\"id\":67}")); } + private BlockTree BuildBlockTree(Func? builderOptions = null) + { + BlockTreeBuilder builder = Build.A.BlockTree().WithBlocksDb(_blocksDb).WithBlockStore(new BlockStore(_blocksDb)); + builder = builderOptions?.Invoke(builder) ?? builder; + return builder.TestObject; + } + + [Test] + public void Debug_getBadBlocks_test() + { + IBlockStore badBlocksStore = null!; + BlockTree blockTree = BuildBlockTree(b => b.WithBadBlockStore(badBlocksStore = new BlockStore(b.BadBlocksDb))); + + Block block0 = Build.A.Block.WithNumber(0).WithDifficulty(1).TestObject; + Block block1 = Build.A.Block.WithNumber(1).WithDifficulty(2).WithParent(block0).TestObject; + Block block2 = Build.A.Block.WithNumber(2).WithDifficulty(3).WithParent(block1).TestObject; + Block block3 = Build.A.Block.WithNumber(2).WithDifficulty(4).WithParent(block2).TestObject; + + blockTree.SuggestBlock(block0); + blockTree.SuggestBlock(block1); + blockTree.SuggestBlock(block2); + blockTree.SuggestBlock(block3); + + blockTree.DeleteInvalidBlock(block1); + + BlockDecoder decoder = new(); + _blocksDb.Set(block1.Hash ?? new Hash256("0x0"), decoder.Encode(block1).Bytes); + + debugBridge.GetBadBlocks().Returns(badBlocksStore.GetAll()); + + AddBlockResult result = blockTree.SuggestBlock(block1); + Assert.That(result, Is.EqualTo(AddBlockResult.InvalidBlock)); + + DebugRpcModule rpcModule = new(LimboLogs.Instance, debugBridge, jsonRpcConfig); + ResultWrapper> blocks = rpcModule.debug_getBadBlocks(); + Assert.That(blocks.Data.Count, Is.EqualTo(1)); + Assert.That(blocks.Data.ElementAt(0).Hash, Is.EqualTo(block1.Hash)); + Assert.That(blocks.Data.ElementAt(0).Difficulty, Is.EqualTo(new UInt256(2))); + } + [Test] public async Task Get_trace_with_javascript_setup() { diff --git a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/SubscribeModuleTests.cs b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/SubscribeModuleTests.cs index 123497a5aa1..e2c033e4925 100644 --- a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/SubscribeModuleTests.cs +++ b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/SubscribeModuleTests.cs @@ -64,7 +64,7 @@ public void Setup() _filterStore = new FilterStore(); _jsonRpcDuplexClient = Substitute.For(); _jsonSerializer = new EthereumJsonSerializer(); - _receiptCanonicalityMonitor = new ReceiptCanonicalityMonitor(_blockTree, _receiptStorage, _logManager); + _receiptCanonicalityMonitor = new ReceiptCanonicalityMonitor(_receiptStorage, _logManager); _syncConfig = new SyncConfig(); IJsonSerializer jsonSerializer = new EthereumJsonSerializer(); @@ -114,6 +114,7 @@ private JsonRpcResult GetBlockAddedToMainResult(BlockReplacementEventArgs blockR })); _blockTree.BlockAddedToMain += Raise.EventWith(new object(), blockReplacementEventArgs); + _receiptStorage.ReceiptsInserted += Raise.EventWith(new object(), blockReplacementEventArgs); manualResetEvent.WaitOne(TimeSpan.FromMilliseconds(1000)).Should().Be(shouldReceiveResult); subscriptionId = newHeadSubscription.Id; @@ -133,6 +134,7 @@ private List GetLogsSubscriptionResult(Filter filter, BlockReplac })); _blockTree.BlockAddedToMain += Raise.EventWith(new object(), blockEventArgs); + _receiptStorage.ReceiptsInserted += Raise.EventWith(new object(), blockEventArgs); semaphoreSlim.Wait(TimeSpan.FromMilliseconds(100)); subscriptionId = logsSubscription.Id; @@ -713,6 +715,7 @@ public void LogsSubscription_should_not_send_logs_of_new_txs_on_ReceiptsInserted BlockReplacementEventArgs blockEventArgs = new(block); _blockTree.BlockAddedToMain += Raise.EventWith(new object(), blockEventArgs); + _receiptStorage.ReceiptsInserted += Raise.EventWith(new object(), blockEventArgs); manualResetEvent.WaitOne(TimeSpan.FromMilliseconds(200)); jsonRpcResults.Count.Should().Be(1); @@ -892,6 +895,7 @@ public async Task MultipleSubscriptions_concurrent_fast_messages(int messages) { BlockReplacementEventArgs eventArgs = new(Build.A.Block.TestObject); blockTree.BlockAddedToMain += Raise.EventWith(eventArgs); + _receiptStorage.ReceiptsInserted += Raise.EventWith(new object(), eventArgs); } }); @@ -1148,6 +1152,7 @@ public void LogsSubscription_can_send_logs_with_removed_txs_when_inserted() })); _blockTree.BlockAddedToMain += Raise.EventWith(new object(), blockEventArgs); + _receiptStorage.ReceiptsInserted += Raise.EventWith(new object(), blockEventArgs); manualResetEvent.WaitOne(TimeSpan.FromMilliseconds(2000)); jsonRpcResults.Count.Should().Be(1); diff --git a/src/Nethermind/Nethermind.JsonRpc/Modules/DebugModule/DebugBridge.cs b/src/Nethermind/Nethermind.JsonRpc/Modules/DebugModule/DebugBridge.cs index c55f8e32c61..c32e3b1f7cd 100644 --- a/src/Nethermind/Nethermind.JsonRpc/Modules/DebugModule/DebugBridge.cs +++ b/src/Nethermind/Nethermind.JsonRpc/Modules/DebugModule/DebugBridge.cs @@ -7,6 +7,7 @@ using System.Threading; using System.Threading.Tasks; using Nethermind.Blockchain; +using Nethermind.Blockchain.Blocks; using Nethermind.Blockchain.Find; using Nethermind.Blockchain.Receipts; using Nethermind.Config; @@ -32,6 +33,7 @@ public class DebugBridge : IDebugBridge private readonly IReceiptsMigration _receiptsMigration; private readonly ISpecProvider _specProvider; private readonly ISyncModeSelector _syncModeSelector; + private readonly IBlockStore _badBlockStore; private readonly Dictionary _dbMappings; public DebugBridge( @@ -42,7 +44,8 @@ public DebugBridge( IReceiptStorage receiptStorage, IReceiptsMigration receiptsMigration, ISpecProvider specProvider, - ISyncModeSelector syncModeSelector) + ISyncModeSelector syncModeSelector, + IBlockStore badBlockStore) { _configProvider = configProvider ?? throw new ArgumentNullException(nameof(configProvider)); _tracer = tracer ?? throw new ArgumentNullException(nameof(tracer)); @@ -51,6 +54,7 @@ public DebugBridge( _receiptsMigration = receiptsMigration ?? throw new ArgumentNullException(nameof(receiptsMigration)); _specProvider = specProvider ?? throw new ArgumentNullException(nameof(specProvider)); _syncModeSelector = syncModeSelector ?? throw new ArgumentNullException(nameof(syncModeSelector)); + _badBlockStore = badBlockStore; dbProvider = dbProvider ?? throw new ArgumentNullException(nameof(dbProvider)); IDb blockInfosDb = dbProvider.BlockInfosDb ?? throw new ArgumentNullException(nameof(dbProvider.BlockInfosDb)); IDb blocksDb = dbProvider.BlocksDb ?? throw new ArgumentNullException(nameof(dbProvider.BlocksDb)); @@ -76,25 +80,15 @@ public DebugBridge( } } - public byte[] GetDbValue(string dbName, byte[] key) - { - return _dbMappings[dbName][key]; - } + public IEnumerable GetBadBlocks() => _badBlockStore.GetAll(); - public ChainLevelInfo GetLevelInfo(long number) - { - return _blockTree.FindLevel(number); - } + public byte[] GetDbValue(string dbName, byte[] key) => _dbMappings[dbName][key]; - public int DeleteChainSlice(long startNumber, bool force = false) - { - return _blockTree.DeleteChainSlice(startNumber, force: force); - } + public ChainLevelInfo GetLevelInfo(long number) => _blockTree.FindLevel(number); - public void UpdateHeadBlock(Hash256 blockHash) - { - _blockTree.UpdateHeadBlock(blockHash); - } + public int DeleteChainSlice(long startNumber, bool force = false) => _blockTree.DeleteChainSlice(startNumber, force: force); + + public void UpdateHeadBlock(Hash256 blockHash) => _blockTree.UpdateHeadBlock(blockHash); public Task MigrateReceipts(long blockNumber) => _receiptsMigration.Run(blockNumber + 1); // add 1 to make go from inclusive (better for API) to exclusive (better for internal) @@ -118,6 +112,8 @@ public void InsertReceipts(BlockParameter blockParameter, TxReceipt[] txReceipts _receiptStorage.Insert(block, txReceipts); } + public GethLikeTxTrace GetTransactionTrace(Hash256 transactionHash, CancellationToken cancellationToken, GethTraceOptions? gethTraceOptions = null) => + _tracer.Trace(transactionHash, gethTraceOptions ?? GethTraceOptions.Default, cancellationToken); public TxReceipt[]? GetReceiptsForBlock(BlockParameter blockParam) { SearchResult searchResult = _blockTree.SearchForBlock(blockParam); @@ -143,41 +139,25 @@ public void InsertReceipts(BlockParameter blockParameter, TxReceipt[] txReceipts return block?.Transactions[txReceipt.Index]; } - public GethLikeTxTrace GetTransactionTrace(Hash256 transactionHash, CancellationToken cancellationToken, GethTraceOptions gethTraceOptions = null) - { - return _tracer.Trace(transactionHash, gethTraceOptions ?? GethTraceOptions.Default, cancellationToken); - } + public GethLikeTxTrace GetTransactionTrace(long blockNumber, int index, CancellationToken cancellationToken, GethTraceOptions? gethTraceOptions = null) => + _tracer.Trace(blockNumber, index, gethTraceOptions ?? GethTraceOptions.Default, cancellationToken); - public GethLikeTxTrace GetTransactionTrace(long blockNumber, int index, CancellationToken cancellationToken, GethTraceOptions gethTraceOptions = null) - { - return _tracer.Trace(blockNumber, index, gethTraceOptions ?? GethTraceOptions.Default, cancellationToken); - } + public GethLikeTxTrace GetTransactionTrace(Hash256 blockHash, int index, CancellationToken cancellationToken, GethTraceOptions? gethTraceOptions = null) => + _tracer.Trace(blockHash, index, gethTraceOptions ?? GethTraceOptions.Default, cancellationToken); - public GethLikeTxTrace GetTransactionTrace(Hash256 blockHash, int index, CancellationToken cancellationToken, GethTraceOptions gethTraceOptions = null) - { - return _tracer.Trace(blockHash, index, gethTraceOptions ?? GethTraceOptions.Default, cancellationToken); - } + public GethLikeTxTrace GetTransactionTrace(Rlp blockRlp, Hash256 transactionHash, CancellationToken cancellationToken, GethTraceOptions? gethTraceOptions = null) => + _tracer.Trace(blockRlp, transactionHash, gethTraceOptions ?? GethTraceOptions.Default, cancellationToken); - public GethLikeTxTrace GetTransactionTrace(Rlp blockRlp, Hash256 transactionHash, CancellationToken cancellationToken, GethTraceOptions gethTraceOptions = null) - { - return _tracer.Trace(blockRlp, transactionHash, gethTraceOptions ?? GethTraceOptions.Default, cancellationToken); - } + public GethLikeTxTrace? GetTransactionTrace(Transaction transaction, BlockParameter blockParameter, CancellationToken cancellationToken, GethTraceOptions? gethTraceOptions = null) => + _tracer.Trace(blockParameter, transaction, gethTraceOptions ?? GethTraceOptions.Default, cancellationToken); - public GethLikeTxTrace? GetTransactionTrace(Transaction transaction, BlockParameter blockParameter, CancellationToken cancellationToken, GethTraceOptions? gethTraceOptions = null) - { - return _tracer.Trace(blockParameter, transaction, gethTraceOptions ?? GethTraceOptions.Default, cancellationToken); - } - - public IReadOnlyCollection GetBlockTrace(BlockParameter blockParameter, CancellationToken cancellationToken, GethTraceOptions gethTraceOptions = null) - { - return _tracer.TraceBlock(blockParameter, gethTraceOptions ?? GethTraceOptions.Default, cancellationToken); - } + public IReadOnlyCollection GetBlockTrace(BlockParameter blockParameter, CancellationToken cancellationToken, GethTraceOptions? gethTraceOptions = null) => + _tracer.TraceBlock(blockParameter, gethTraceOptions ?? GethTraceOptions.Default, cancellationToken); - public IReadOnlyCollection GetBlockTrace(Rlp blockRlp, CancellationToken cancellationToken, GethTraceOptions? gethTraceOptions = null) - { - return _tracer.TraceBlock(blockRlp, gethTraceOptions ?? GethTraceOptions.Default, cancellationToken); - } + public IReadOnlyCollection GetBlockTrace(Rlp blockRlp, CancellationToken cancellationToken, GethTraceOptions? gethTraceOptions = null) => + _tracer.TraceBlock(blockRlp, gethTraceOptions ?? GethTraceOptions.Default, cancellationToken); + public byte[] GetBlockRlp(Hash256 blockHash) => _dbMappings[DbNames.Blocks].Get(blockHash); public byte[]? GetBlockRlp(BlockParameter parameter) { @@ -193,11 +173,6 @@ public IReadOnlyCollection GetBlockTrace(Rlp blockRlp, Cancella return null; } - public byte[] GetBlockRlp(Hash256 blockHash) - { - return _dbMappings[DbNames.Blocks].Get(blockHash); - } - public Block? GetBlock(BlockParameter param) => _blockTree.FindBlock(param); public byte[] GetBlockRlp(long number) @@ -206,10 +181,7 @@ public byte[] GetBlockRlp(long number) return hash is null ? null : _dbMappings[DbNames.Blocks].Get(hash); } - public object GetConfigValue(string category, string name) - { - return _configProvider.GetRawValue(category, name); - } + public object GetConfigValue(string category, string name) => _configProvider.GetRawValue(category, name); public SyncReportSymmary GetCurrentSyncStage() { diff --git a/src/Nethermind/Nethermind.JsonRpc/Modules/DebugModule/DebugModuleFactory.cs b/src/Nethermind/Nethermind.JsonRpc/Modules/DebugModule/DebugModuleFactory.cs index e9664e06f0d..948f48a22ce 100644 --- a/src/Nethermind/Nethermind.JsonRpc/Modules/DebugModule/DebugModuleFactory.cs +++ b/src/Nethermind/Nethermind.JsonRpc/Modules/DebugModule/DebugModuleFactory.cs @@ -5,6 +5,7 @@ using System.Collections.Generic; using System.IO.Abstractions; using Nethermind.Blockchain; +using Nethermind.Blockchain.Blocks; using Nethermind.Blockchain.Receipts; using Nethermind.Config; using Nethermind.Consensus.Processing; @@ -39,6 +40,7 @@ public class DebugModuleFactory : ModuleFactoryBase private readonly IReadOnlyDbProvider _dbProvider; private readonly IReadOnlyBlockTree _blockTree; private readonly ISyncModeSelector _syncModeSelector; + private readonly IBlockStore _badBlockStore; private readonly IFileSystem _fileSystem; private readonly ILogger _logger; @@ -55,6 +57,7 @@ public DebugModuleFactory( IConfigProvider configProvider, ISpecProvider specProvider, ISyncModeSelector syncModeSelector, + IBlockStore badBlockStore, IFileSystem fileSystem, ILogManager logManager) { @@ -71,6 +74,7 @@ public DebugModuleFactory( _specProvider = specProvider ?? throw new ArgumentNullException(nameof(specProvider)); _logManager = logManager ?? throw new ArgumentNullException(nameof(logManager)); _syncModeSelector = syncModeSelector ?? throw new ArgumentNullException(nameof(syncModeSelector)); + _badBlockStore = badBlockStore; _fileSystem = fileSystem ?? throw new ArgumentNullException(nameof(fileSystem)); _logger = logManager.GetClassLogger(); } @@ -112,7 +116,8 @@ public override IDebugRpcModule Create() _receiptStorage, _receiptsMigration, _specProvider, - _syncModeSelector); + _syncModeSelector, + _badBlockStore); return new DebugRpcModule(_logManager, debugBridge, _jsonRpcConfig); } diff --git a/src/Nethermind/Nethermind.JsonRpc/Modules/DebugModule/DebugRpcModule.cs b/src/Nethermind/Nethermind.JsonRpc/Modules/DebugModule/DebugRpcModule.cs index d24f73cb7fc..2816c277070 100644 --- a/src/Nethermind/Nethermind.JsonRpc/Modules/DebugModule/DebugRpcModule.cs +++ b/src/Nethermind/Nethermind.JsonRpc/Modules/DebugModule/DebugRpcModule.cs @@ -321,4 +321,10 @@ public ResultWrapper> debug_standardTraceBlockToFile(Hash256 return ResultWrapper>.Success(files); } + + public ResultWrapper> debug_getBadBlocks() + { + IEnumerable badBlocks = _debugBridge.GetBadBlocks(); + return ResultWrapper>.Success(badBlocks); + } } diff --git a/src/Nethermind/Nethermind.JsonRpc/Modules/DebugModule/IDebugBridge.cs b/src/Nethermind/Nethermind.JsonRpc/Modules/DebugModule/IDebugBridge.cs index 732dcdff7f7..73cc66f74b0 100644 --- a/src/Nethermind/Nethermind.JsonRpc/Modules/DebugModule/IDebugBridge.cs +++ b/src/Nethermind/Nethermind.JsonRpc/Modules/DebugModule/IDebugBridge.cs @@ -35,6 +35,7 @@ public interface IDebugBridge void InsertReceipts(BlockParameter blockParameter, TxReceipt[] receipts); SyncReportSymmary GetCurrentSyncStage(); IEnumerable TraceBlockToFile(Hash256 blockHash, CancellationToken cancellationToken, GethTraceOptions? gethTraceOptions = null); + public IEnumerable GetBadBlocks(); TxReceipt[]? GetReceiptsForBlock(BlockParameter param); Transaction? GetTransactionFromHash(Hash256 hash); } diff --git a/src/Nethermind/Nethermind.JsonRpc/Modules/DebugModule/IDebugRpcModule.cs b/src/Nethermind/Nethermind.JsonRpc/Modules/DebugModule/IDebugRpcModule.cs index 932a1d300da..e17f692779e 100644 --- a/src/Nethermind/Nethermind.JsonRpc/Modules/DebugModule/IDebugRpcModule.cs +++ b/src/Nethermind/Nethermind.JsonRpc/Modules/DebugModule/IDebugRpcModule.cs @@ -4,6 +4,7 @@ using System.Collections.Generic; using System.Threading.Tasks; using Nethermind.Blockchain.Find; +using Nethermind.Core; using Nethermind.Core.Crypto; using Nethermind.Evm.Tracing.GethStyle; using Nethermind.JsonRpc.Data; @@ -106,4 +107,7 @@ public interface IDebugRpcModule : IRpcModule [JsonRpcMethod(Description = "Writes to a file the full stack trace of all invoked opcodes of the transaction specified (or all transactions if not specified) that was included in the block specified. The parent of the block must be present or it will fail.", IsImplemented = true, IsSharable = false)] ResultWrapper> debug_standardTraceBlockToFile(Hash256 blockHash, GethTraceOptions options = null); + + [JsonRpcMethod(Description = "Return list of invalid blocks.")] + ResultWrapper> debug_getBadBlocks(); } diff --git a/src/Nethermind/Nethermind.Merge.Plugin.Test/BlockTreeTests.cs b/src/Nethermind/Nethermind.Merge.Plugin.Test/BlockTreeTests.cs index de7f0a7f2ec..f0729dff70a 100644 --- a/src/Nethermind/Nethermind.Merge.Plugin.Test/BlockTreeTests.cs +++ b/src/Nethermind/Nethermind.Merge.Plugin.Test/BlockTreeTests.cs @@ -20,6 +20,7 @@ using Nethermind.Merge.Plugin.Synchronization; using Nethermind.Serialization.Rlp; using Nethermind.Specs; +using Nethermind.Specs.ChainSpecStyle; using Nethermind.Specs.Forks; using Nethermind.Synchronization.Blocks; using Nethermind.Synchronization.Peers; @@ -76,7 +77,7 @@ public void Can_suggest_terminal_block_correctly() .WithSpecProvider(specProvider) .OfChainLength(10) .TestObject; - PoSSwitcher poSSwitcher = new(new MergeConfig(), new SyncConfig(), new MemDb(), tree, specProvider, LimboLogs.Instance); + PoSSwitcher poSSwitcher = new(new MergeConfig(), new SyncConfig(), new MemDb(), tree, specProvider, new ChainSpec(), LimboLogs.Instance); Block? block8 = tree.FindBlock(8, BlockTreeLookupOptions.None); Assert.False(block8!.IsTerminalBlock(specProvider)); @@ -95,7 +96,7 @@ public void Suggest_terminal_block_with_lower_number_and_lower_total_difficulty( .WithSpecProvider(specProvider) .OfChainLength(10) .TestObject; - PoSSwitcher poSSwitcher = new(new MergeConfig(), new SyncConfig(), new MemDb(), tree, specProvider, LimboLogs.Instance); + PoSSwitcher poSSwitcher = new(new MergeConfig(), new SyncConfig(), new MemDb(), tree, specProvider, new ChainSpec(), LimboLogs.Instance); Block? block7 = tree.FindBlock(7, BlockTreeLookupOptions.None); Block newTerminalBlock = Build.A.Block @@ -124,7 +125,7 @@ public void Cannot_change_best_suggested_to_terminal_block_after_merge_block() .OfChainLength(10) .TestObject; - PoSSwitcher poSSwitcher = new(new MergeConfig(), new SyncConfig(), new MemDb(), tree, specProvider, LimboLogs.Instance); + PoSSwitcher poSSwitcher = new(new MergeConfig(), new SyncConfig(), new MemDb(), tree, specProvider, new ChainSpec(), LimboLogs.Instance); Block? block8 = tree.FindBlock(8, BlockTreeLookupOptions.None); Assert.False(block8!.Header.IsTerminalBlock(specProvider)); diff --git a/src/Nethermind/Nethermind.Merge.Plugin.Test/EngineModuleTests.Setup.cs b/src/Nethermind/Nethermind.Merge.Plugin.Test/EngineModuleTests.Setup.cs index 982c5a1741b..8ada5ce1885 100644 --- a/src/Nethermind/Nethermind.Merge.Plugin.Test/EngineModuleTests.Setup.cs +++ b/src/Nethermind/Nethermind.Merge.Plugin.Test/EngineModuleTests.Setup.cs @@ -20,6 +20,7 @@ using Nethermind.Core.Crypto; using Nethermind.Core.Specs; using Nethermind.Core.Test.Blockchain; +using Nethermind.Core.Test.Builders; using Nethermind.Core.Timers; using Nethermind.Crypto; using Nethermind.Db; @@ -33,6 +34,7 @@ using Nethermind.Merge.Plugin.Handlers; using Nethermind.Merge.Plugin.Synchronization; using Nethermind.Specs; +using Nethermind.Specs.ChainSpecStyle; using Nethermind.Specs.Forks; using Nethermind.State; using Nethermind.Synchronization.ParallelSync; @@ -76,7 +78,7 @@ private IEngineRpcModule CreateEngineModule(MergeTestBlockchain chain, ISyncConf blockCacheService, chain.LogManager); invalidChainTracker.SetupBlockchainProcessorInterceptor(chain.BlockchainProcessor); - chain.BeaconSync = new BeaconSync(chain.BeaconPivot, chain.BlockTree, synchronizationConfig, blockCacheService, chain.LogManager); + chain.BeaconSync = new BeaconSync(chain.BeaconPivot, chain.BlockTree, synchronizationConfig, blockCacheService, chain.PoSSwitcher, chain.LogManager); EngineRpcCapabilitiesProvider capabilitiesProvider = new(chain.SpecProvider); return new EngineRpcModule( new GetPayloadV1Handler( @@ -236,7 +238,7 @@ protected override IBlockProcessor CreateBlockProcessor() protected IBlockValidator CreateBlockValidator() { IBlockCacheService blockCacheService = new BlockCacheService(); - PoSSwitcher = new PoSSwitcher(MergeConfig, SyncConfig.Default, new MemDb(), BlockTree, SpecProvider, LogManager); + PoSSwitcher = new PoSSwitcher(MergeConfig, SyncConfig.Default, new MemDb(), BlockTree, SpecProvider, new ChainSpec() { Genesis = Core.Test.Builders.Build.A.Block.WithDifficulty(0).TestObject }, LogManager); SealValidator = new MergeSealValidator(PoSSwitcher, Always.Valid); HeaderValidator preMergeHeaderValidator = new HeaderValidator(BlockTree, SealValidator, SpecProvider, LogManager); HeaderValidator = new MergeHeaderValidator(PoSSwitcher, preMergeHeaderValidator, BlockTree, SpecProvider, SealValidator, LogManager); diff --git a/src/Nethermind/Nethermind.Merge.Plugin.Test/MergeRewardCalculatorTests.cs b/src/Nethermind/Nethermind.Merge.Plugin.Test/MergeRewardCalculatorTests.cs index 8175a677e5f..3c49333bdaa 100644 --- a/src/Nethermind/Nethermind.Merge.Plugin.Test/MergeRewardCalculatorTests.cs +++ b/src/Nethermind/Nethermind.Merge.Plugin.Test/MergeRewardCalculatorTests.cs @@ -10,6 +10,7 @@ using Nethermind.Logging; using Nethermind.Merge.Plugin.Handlers; using Nethermind.Specs; +using Nethermind.Specs.ChainSpecStyle; using Nethermind.Specs.Forks; using NSubstitute; using NUnit.Framework; @@ -156,7 +157,7 @@ private static PoSSwitcher CreatePosSwitcher() specProvider.TerminalTotalDifficulty = 2; MergeConfig? mergeConfig = new() { }; IBlockCacheService blockCacheService = new BlockCacheService(); - return new PoSSwitcher(mergeConfig, new SyncConfig(), db, blockTree, specProvider, LimboLogs.Instance); + return new PoSSwitcher(mergeConfig, new SyncConfig(), db, blockTree, specProvider, new ChainSpec(), LimboLogs.Instance); } } diff --git a/src/Nethermind/Nethermind.Merge.Plugin.Test/PoSSwitcherTests.cs b/src/Nethermind/Nethermind.Merge.Plugin.Test/PoSSwitcherTests.cs index 9f2992c46ed..1c1b5838b21 100644 --- a/src/Nethermind/Nethermind.Merge.Plugin.Test/PoSSwitcherTests.cs +++ b/src/Nethermind/Nethermind.Merge.Plugin.Test/PoSSwitcherTests.cs @@ -30,7 +30,7 @@ public void Initial_TTD_should_be_null() { UInt256? expectedTtd = null; IBlockTree blockTree = Substitute.For(); - PoSSwitcher poSSwitcher = new(new MergeConfig(), new SyncConfig(), new MemDb(), blockTree, TestSpecProvider.Instance, LimboLogs.Instance); + PoSSwitcher poSSwitcher = new(new MergeConfig(), new SyncConfig(), new MemDb(), blockTree, TestSpecProvider.Instance, new ChainSpec(), LimboLogs.Instance); Assert.That(poSSwitcher.TerminalTotalDifficulty, Is.EqualTo(expectedTtd)); } @@ -45,7 +45,7 @@ public void Read_TTD_from_chainspec_if_not_specified_in_merge_config() ChainSpec chainSpec = loader.Load(File.ReadAllText(path)); ChainSpecBasedSpecProvider specProvider = new(chainSpec); - PoSSwitcher poSSwitcher = new(new MergeConfig(), new SyncConfig(), new MemDb(), blockTree, specProvider, LimboLogs.Instance); + PoSSwitcher poSSwitcher = new(new MergeConfig(), new SyncConfig(), new MemDb(), blockTree, specProvider, new ChainSpec(), LimboLogs.Instance); Assert.That(poSSwitcher.TerminalTotalDifficulty, Is.EqualTo(expectedTtd)); Assert.That(specProvider.MergeBlockNumber?.BlockNumber, Is.EqualTo(101)); @@ -93,7 +93,7 @@ public void Override_TTD_and_number_from_merge_config() IBlockTree blockTree = Substitute.For(); TestSpecProvider specProvider = new(London.Instance); specProvider.UpdateMergeTransitionInfo(100, 20); - PoSSwitcher poSSwitcher = new(new MergeConfig() { TerminalTotalDifficulty = "340", TerminalBlockNumber = 2000 }, new SyncConfig(), new MemDb(), blockTree, specProvider, LimboLogs.Instance); + PoSSwitcher poSSwitcher = new(new MergeConfig() { TerminalTotalDifficulty = "340", TerminalBlockNumber = 2000 }, new SyncConfig(), new MemDb(), blockTree, specProvider, new ChainSpec(), LimboLogs.Instance); Assert.That(poSSwitcher.TerminalTotalDifficulty, Is.EqualTo(expectedTtd)); Assert.That(specProvider.MergeBlockNumber?.BlockNumber, Is.EqualTo(2001)); @@ -106,7 +106,7 @@ public void Can_update_merge_transition_info() IBlockTree blockTree = Substitute.For(); TestSpecProvider specProvider = new(London.Instance); specProvider.UpdateMergeTransitionInfo(2001, expectedTtd); - PoSSwitcher poSSwitcher = new(new MergeConfig() { }, new SyncConfig(), new MemDb(), blockTree, specProvider, LimboLogs.Instance); + PoSSwitcher poSSwitcher = new(new MergeConfig() { }, new SyncConfig(), new MemDb(), blockTree, specProvider, new ChainSpec(), LimboLogs.Instance); Assert.That(poSSwitcher.TerminalTotalDifficulty, Is.EqualTo(expectedTtd)); Assert.That(specProvider.MergeBlockNumber?.BlockNumber, Is.EqualTo(2001)); @@ -254,7 +254,7 @@ private void AssertFinalTotalDifficulty(long ttd, long genesisDifficulty, long? SyncConfig syncConfig = new(); if (pivotTotalDifficulty != null) syncConfig = new SyncConfig() { PivotTotalDifficulty = $"{(UInt256)pivotTotalDifficulty}" }; - PoSSwitcher poSSwitcher = new PoSSwitcher(new MergeConfig(), syncConfig, new MemDb(), blockTree, specProvider, LimboLogs.Instance); + PoSSwitcher poSSwitcher = new PoSSwitcher(new MergeConfig(), syncConfig, new MemDb(), blockTree, specProvider, new ChainSpec() { Genesis = genesisBlock }, LimboLogs.Instance); if (expectedFinalTotalDifficulty != null) poSSwitcher.FinalTotalDifficulty.Should().Be((UInt256)expectedFinalTotalDifficulty); else @@ -266,7 +266,7 @@ private static PoSSwitcher CreatePosSwitcher(IBlockTree blockTree, IDb? db = nul { db ??= new MemDb(); MergeConfig? mergeConfig = new() { }; - return new PoSSwitcher(mergeConfig, new SyncConfig(), db, blockTree, specProvider ?? MainnetSpecProvider.Instance, LimboLogs.Instance); + return new PoSSwitcher(mergeConfig, new SyncConfig(), db, blockTree, specProvider ?? MainnetSpecProvider.Instance, new ChainSpec(), LimboLogs.Instance); } } } diff --git a/src/Nethermind/Nethermind.Merge.Plugin.Test/Synchronization/BeaconHeadersSyncTests.cs b/src/Nethermind/Nethermind.Merge.Plugin.Test/Synchronization/BeaconHeadersSyncTests.cs index 8006941d498..3e7d4dadbee 100644 --- a/src/Nethermind/Nethermind.Merge.Plugin.Test/Synchronization/BeaconHeadersSyncTests.cs +++ b/src/Nethermind/Nethermind.Merge.Plugin.Test/Synchronization/BeaconHeadersSyncTests.cs @@ -18,6 +18,7 @@ using Nethermind.Merge.Plugin.InvalidChainTracker; using Nethermind.Merge.Plugin.Synchronization; using Nethermind.Specs; +using Nethermind.Specs.ChainSpecStyle; using Nethermind.State.Repositories; using Nethermind.Synchronization; using Nethermind.Synchronization.FastBlocks; @@ -64,14 +65,14 @@ public IBeaconPivot BeaconPivot } private BeaconSync? _beaconSync; - public BeaconSync BeaconSync => _beaconSync ??= new(BeaconPivot, BlockTree, SyncConfig, BlockCacheService, LimboLogs.Instance); + public BeaconSync BeaconSync => _beaconSync ??= new(BeaconPivot, BlockTree, SyncConfig, BlockCacheService, PoSSwitcher, LimboLogs.Instance); private IDb? _metadataDb; public IDb MetadataDb => _metadataDb ??= new MemDb(); private PoSSwitcher? _poSSwitcher; public PoSSwitcher PoSSwitcher => _poSSwitcher ??= new(MergeConfig, SyncConfig, MetadataDb, BlockTree, - MainnetSpecProvider.Instance, LimboLogs.Instance); + MainnetSpecProvider.Instance, new ChainSpec(), LimboLogs.Instance); private IInvalidChainTracker? _invalidChainTracker; diff --git a/src/Nethermind/Nethermind.Merge.Plugin/GC/GCKeeper.cs b/src/Nethermind/Nethermind.Merge.Plugin/GC/GCKeeper.cs index 17d736dd280..5e22b0d1fe7 100644 --- a/src/Nethermind/Nethermind.Merge.Plugin/GC/GCKeeper.cs +++ b/src/Nethermind/Nethermind.Merge.Plugin/GC/GCKeeper.cs @@ -28,22 +28,16 @@ public GCKeeper(IGCStrategy gcStrategy, ILogManager logManager) public IDisposable TryStartNoGCRegion(long? size = null) { - // SustainedLowLatency is used rather than NoGCRegion - // due to runtime bug https://github.com/dotnet/runtime/issues/84096 - // The code is left in as comments so it can be reverted when the bug is fixed size ??= _defaultSize; - var priorLatencyMode = System.Runtime.GCSettings.LatencyMode; - //if (_gcStrategy.CanStartNoGCRegion()) - if (priorLatencyMode != GCLatencyMode.SustainedLowLatency) + if (_gcStrategy.CanStartNoGCRegion()) { FailCause failCause = FailCause.None; try { - GCSettings.LatencyMode = GCLatencyMode.SustainedLowLatency; - //if (!System.GC.TryStartNoGCRegion(size.Value, true)) - //{ - // failCause = FailCause.GCFailedToStartNoGCRegion; - //} + if (!System.GC.TryStartNoGCRegion(size.Value, true)) + { + failCause = FailCause.GCFailedToStartNoGCRegion; + } } catch (ArgumentOutOfRangeException) { @@ -60,10 +54,10 @@ public IDisposable TryStartNoGCRegion(long? size = null) if (_logger.IsError) _logger.Error($"{nameof(System.GC.TryStartNoGCRegion)} failed with exception.", e); } - return new NoGCRegion(this, priorLatencyMode, failCause, size, _logger); + return new NoGCRegion(this, failCause, size, _logger); } - return new NoGCRegion(this, priorLatencyMode, FailCause.StrategyDisallowed, size, _logger); + return new NoGCRegion(this, FailCause.StrategyDisallowed, size, _logger); } private enum FailCause @@ -79,15 +73,13 @@ private enum FailCause private class NoGCRegion : IDisposable { private readonly GCKeeper _gcKeeper; - private readonly GCLatencyMode _priorMode; private readonly FailCause _failCause; private readonly long? _size; private readonly ILogger _logger; - internal NoGCRegion(GCKeeper gcKeeper, GCLatencyMode priorMode, FailCause failCause, long? size, ILogger logger) + internal NoGCRegion(GCKeeper gcKeeper, FailCause failCause, long? size, ILogger logger) { _gcKeeper = gcKeeper; - _priorMode = priorMode; _failCause = failCause; _size = size; _logger = logger; @@ -95,19 +87,13 @@ internal NoGCRegion(GCKeeper gcKeeper, GCLatencyMode priorMode, FailCause failCa public void Dispose() { - // SustainedLowLatency is used rather than NoGCRegion - // due to runtime bug https://github.com/dotnet/runtime/issues/84096 - // The code is left in as comments so it can be reverted when the bug is fixed if (_failCause == FailCause.None) { - //if (GCSettings.LatencyMode == GCLatencyMode.NoGCRegion) - if (GCSettings.LatencyMode == GCLatencyMode.SustainedLowLatency && - _priorMode != GCLatencyMode.SustainedLowLatency) + if (GCSettings.LatencyMode == GCLatencyMode.NoGCRegion) { try { - GCSettings.LatencyMode = _priorMode; - //System.GC.EndNoGCRegion(); + System.GC.EndNoGCRegion(); _gcKeeper.ScheduleGC(); } catch (InvalidOperationException) diff --git a/src/Nethermind/Nethermind.Merge.Plugin/Handlers/BlockCacheService.cs b/src/Nethermind/Nethermind.Merge.Plugin/Handlers/BlockCacheService.cs index e411bcc211f..ad5bfdda95b 100644 --- a/src/Nethermind/Nethermind.Merge.Plugin/Handlers/BlockCacheService.cs +++ b/src/Nethermind/Nethermind.Merge.Plugin/Handlers/BlockCacheService.cs @@ -10,5 +10,5 @@ namespace Nethermind.Merge.Plugin.Handlers; public class BlockCacheService : IBlockCacheService { public ConcurrentDictionary BlockCache { get; } = new(); - public Hash256 FinalizedHash { get; set; } = Keccak.Zero; + public Hash256? FinalizedHash { get; set; } } diff --git a/src/Nethermind/Nethermind.Merge.Plugin/Handlers/IBlockCacheService.cs b/src/Nethermind/Nethermind.Merge.Plugin/Handlers/IBlockCacheService.cs index 77b5979cec5..191318bb5d7 100644 --- a/src/Nethermind/Nethermind.Merge.Plugin/Handlers/IBlockCacheService.cs +++ b/src/Nethermind/Nethermind.Merge.Plugin/Handlers/IBlockCacheService.cs @@ -10,5 +10,5 @@ namespace Nethermind.Merge.Plugin.Handlers; public interface IBlockCacheService { public ConcurrentDictionary BlockCache { get; } - Hash256 FinalizedHash { get; set; } + Hash256? FinalizedHash { get; set; } } diff --git a/src/Nethermind/Nethermind.Merge.Plugin/MergeGossipPolicy.cs b/src/Nethermind/Nethermind.Merge.Plugin/MergeGossipPolicy.cs index a3983e90070..28db239cf26 100644 --- a/src/Nethermind/Nethermind.Merge.Plugin/MergeGossipPolicy.cs +++ b/src/Nethermind/Nethermind.Merge.Plugin/MergeGossipPolicy.cs @@ -36,7 +36,8 @@ public MergeGossipPolicy( // According to spec (https://github.com/ethereum/EIPs/blob/d896145678bd65d3eafd8749690c1b5228875c39/EIPS/eip-3675.md#network) // We MUST discard NewBlock/NewBlockHash messages after receiving FIRST_FINALIZED_BLOCK. public bool ShouldDiscardBlocks => _poSSwitcher.TransitionFinished || - _blockCacheService.FinalizedHash != Keccak.Zero; /* _blockCacheService.FinalizedHash != Keccak.Zero - this condition was added for edge case situation. + (_blockCacheService.FinalizedHash != null && _blockCacheService.FinalizedHash != Keccak.Zero); /* _blockCacheService.FinalizedHash != null && _blockCacheService.FinalizedHash != Keccak.Zero + This condition was added for edge case situation. We started beacon sync, and we hadn't reached transition yet. If CL sent us non zero finalization hash, it would mean that network reached transition. However, in edge case situation (verified by merge hive tests), our node needs to be reorged to PoW again, so we can't add this condition _blockCacheService.FinalizedHash != Keccak.Zero to PoSSwitcher.TransitionFinished. On the other hand, we don't want to receive any blocks from the network, so we want to discard blocks. */ diff --git a/src/Nethermind/Nethermind.Merge.Plugin/MergePlugin.cs b/src/Nethermind/Nethermind.Merge.Plugin/MergePlugin.cs index 2213acad4e9..e1ac8dd4c12 100644 --- a/src/Nethermind/Nethermind.Merge.Plugin/MergePlugin.cs +++ b/src/Nethermind/Nethermind.Merge.Plugin/MergePlugin.cs @@ -92,6 +92,7 @@ public virtual Task Init(INethermindApi nethermindApi) _api.DbProvider.GetDb(DbNames.Metadata), _api.BlockTree, _api.SpecProvider, + _api.ChainSpec, _api.LogManager); _invalidChainTracker = new InvalidChainTracker.InvalidChainTracker( _poSSwitcher, @@ -406,7 +407,7 @@ public Task InitSynchronization() _api.LogManager), _invalidChainTracker, _api.LogManager); - _beaconSync = new BeaconSync(_beaconPivot, _api.BlockTree, _syncConfig, _blockCacheService, _api.LogManager); + _beaconSync = new BeaconSync(_beaconPivot, _api.BlockTree, _syncConfig, _blockCacheService, _poSSwitcher, _api.LogManager); _api.BetterPeerStrategy = new MergeBetterPeerStrategy(_api.BetterPeerStrategy, _poSSwitcher, _beaconPivot, _api.LogManager); diff --git a/src/Nethermind/Nethermind.Merge.Plugin/PoSSwitcher.cs b/src/Nethermind/Nethermind.Merge.Plugin/PoSSwitcher.cs index fe860873b6c..632d4716a8f 100644 --- a/src/Nethermind/Nethermind.Merge.Plugin/PoSSwitcher.cs +++ b/src/Nethermind/Nethermind.Merge.Plugin/PoSSwitcher.cs @@ -12,6 +12,7 @@ using Nethermind.Db; using Nethermind.Logging; using Nethermind.Serialization.Rlp; +using Nethermind.Specs.ChainSpecStyle; namespace Nethermind.Merge.Plugin { @@ -39,6 +40,7 @@ public class PoSSwitcher : IPoSSwitcher private readonly IDb _metadataDb; private readonly IBlockTree _blockTree; private readonly ISpecProvider _specProvider; + private readonly ChainSpec _chainSpec; private readonly ILogger _logger; private Hash256? _terminalBlockHash; @@ -55,6 +57,7 @@ public PoSSwitcher( IDb metadataDb, IBlockTree blockTree, ISpecProvider specProvider, + ChainSpec chainSpec, ILogManager logManager) { _mergeConfig = mergeConfig; @@ -62,6 +65,7 @@ public PoSSwitcher( _metadataDb = metadataDb; _blockTree = blockTree; _specProvider = specProvider; + _chainSpec = chainSpec; _logger = logManager.GetClassLogger(); Initialize(); @@ -98,7 +102,9 @@ private void LoadFinalTotalDifficulty() } else { - UInt256 genesisDifficulty = _blockTree.Genesis?.Difficulty ?? 0; + if (_chainSpec?.Genesis == null) return; + + UInt256 genesisDifficulty = _chainSpec.Genesis.Difficulty; if (genesisDifficulty >= TerminalTotalDifficulty) // networks with the merge in genesis { _finalTotalDifficulty = genesisDifficulty; diff --git a/src/Nethermind/Nethermind.Merge.Plugin/Synchronization/BeaconSync.cs b/src/Nethermind/Nethermind.Merge.Plugin/Synchronization/BeaconSync.cs index 1591dbc18af..368c5d11516 100644 --- a/src/Nethermind/Nethermind.Merge.Plugin/Synchronization/BeaconSync.cs +++ b/src/Nethermind/Nethermind.Merge.Plugin/Synchronization/BeaconSync.cs @@ -3,6 +3,7 @@ using Nethermind.Blockchain; using Nethermind.Blockchain.Synchronization; +using Nethermind.Consensus; using Nethermind.Core; using Nethermind.Core.Crypto; using Nethermind.Crypto; @@ -18,6 +19,7 @@ public class BeaconSync : IMergeSyncController, IBeaconSyncStrategy private readonly IBlockTree _blockTree; private readonly ISyncConfig _syncConfig; private readonly IBlockCacheService _blockCacheService; + private readonly IPoSSwitcher _poSSwitcher; private bool _isInBeaconModeControl = false; private readonly ILogger _logger; @@ -26,12 +28,14 @@ public BeaconSync( IBlockTree blockTree, ISyncConfig syncConfig, IBlockCacheService blockCacheService, + IPoSSwitcher poSSwitcher, ILogManager logManager) { _beaconPivot = beaconPivot; _blockTree = blockTree; _syncConfig = syncConfig; _blockCacheService = blockCacheService; + _poSSwitcher = poSSwitcher; _logger = logManager.GetClassLogger(); } @@ -105,6 +109,8 @@ lowestInsertedBeaconHeader is not null && /// public bool IsBeaconSyncFinished(BlockHeader? blockHeader) => !_beaconPivot.BeaconPivotExists() || (blockHeader is not null && _blockTree.WasProcessed(blockHeader.Number, blockHeader.GetOrCalculateHash())); + public bool MergeTransitionFinished => _poSSwitcher.TransitionFinished; + public long? GetTargetBlockHeight() { if (_beaconPivot.BeaconPivotExists()) @@ -114,7 +120,7 @@ lowestInsertedBeaconHeader is not null && return null; } - public Hash256 GetFinalizedHash() + public Hash256? GetFinalizedHash() { return _blockCacheService.FinalizedHash; } diff --git a/src/Nethermind/Nethermind.Mev/MevBlockProductionTransactionsExecutor.cs b/src/Nethermind/Nethermind.Mev/MevBlockProductionTransactionsExecutor.cs index add5367424e..a12e997e876 100644 --- a/src/Nethermind/Nethermind.Mev/MevBlockProductionTransactionsExecutor.cs +++ b/src/Nethermind/Nethermind.Mev/MevBlockProductionTransactionsExecutor.cs @@ -70,7 +70,7 @@ public override TxReceipt[] ProcessTransactions(Block block, ProcessingOptions p else { // otherwise process transaction as usual - TxAction action = ProcessTransaction(block, blkCtx, currentTx, transactionsInBlock.Count, receiptsTracer, processingOptions, transactionsInBlock); + TxAction action = ProcessTransaction(block, in blkCtx, currentTx, transactionsInBlock.Count, receiptsTracer, processingOptions, transactionsInBlock); if (action == TxAction.Stop) break; } } @@ -90,7 +90,7 @@ public override TxReceipt[] ProcessTransactions(Block block, ProcessingOptions p else { // process accumulated bundle - TxAction action = ProcessBundle(block, blkCtx, bundleTransactions, transactionsInBlock, receiptsTracer, processingOptions); + TxAction action = ProcessBundle(block, in blkCtx, bundleTransactions, transactionsInBlock, receiptsTracer, processingOptions); if (action == TxAction.Stop) break; // start accumulating new bundle @@ -103,11 +103,11 @@ public override TxReceipt[] ProcessTransactions(Block block, ProcessingOptions p { // process the bundle and stop accumulating it bundleHash = null; - TxAction action = ProcessBundle(block, blkCtx, bundleTransactions, transactionsInBlock, receiptsTracer, processingOptions); + TxAction action = ProcessBundle(block, in blkCtx, bundleTransactions, transactionsInBlock, receiptsTracer, processingOptions); if (action == TxAction.Stop) break; // process normal transaction - action = ProcessTransaction(block, blkCtx, currentTx, transactionsInBlock.Count, receiptsTracer, processingOptions, transactionsInBlock); + action = ProcessTransaction(block, in blkCtx, currentTx, transactionsInBlock.Count, receiptsTracer, processingOptions, transactionsInBlock); if (action == TxAction.Stop) break; } } @@ -115,7 +115,7 @@ public override TxReceipt[] ProcessTransactions(Block block, ProcessingOptions p // if we ended with accumulated bundle, lets process it if (bundleTransactions.Count > 0) { - ProcessBundle(block, blkCtx, bundleTransactions, transactionsInBlock, receiptsTracer, processingOptions); + ProcessBundle(block, in blkCtx, bundleTransactions, transactionsInBlock, receiptsTracer, processingOptions); } _stateProvider.Commit(spec, receiptsTracer); @@ -125,7 +125,7 @@ public override TxReceipt[] ProcessTransactions(Block block, ProcessingOptions p } private TxAction ProcessBundle(Block block, - BlockExecutionContext blkCtx, + in BlockExecutionContext blkCtx, List bundleTransactions, LinkedHashSet transactionsInBlock, BlockReceiptsTracer receiptsTracer, @@ -149,7 +149,7 @@ bool CheckFeeNotManipulated() TxAction txAction = TxAction.Skip; for (int index = 0; index < bundleTransactions.Count && bundleSucceeded; index++) { - txAction = ProcessBundleTransaction(block, blkCtx, bundleTransactions[index], index, receiptsTracer, processingOptions, transactionsInBlock); + txAction = ProcessBundleTransaction(block, in blkCtx, bundleTransactions[index], index, receiptsTracer, processingOptions, transactionsInBlock); bundleSucceeded &= txAction == TxAction.Add; // if we need to stop on not first tx in the bundle, we actually want to skip the bundle @@ -188,14 +188,14 @@ bool CheckFeeNotManipulated() private TxAction ProcessBundleTransaction( Block block, - BlockExecutionContext blkCtx, + in BlockExecutionContext blkCtx, BundleTransaction currentTx, int index, BlockReceiptsTracer receiptsTracer, ProcessingOptions processingOptions, LinkedHashSet transactionsInBlock) { - TxAction action = ProcessTransaction(block, blkCtx, currentTx, index, receiptsTracer, processingOptions, transactionsInBlock, false); + TxAction action = ProcessTransaction(block, in blkCtx, currentTx, index, receiptsTracer, processingOptions, transactionsInBlock, false); if (action == TxAction.Add) { string? error = receiptsTracer.LastReceipt.Error; diff --git a/src/Nethermind/Nethermind.Mining.Test/MinGasPriceTests.cs b/src/Nethermind/Nethermind.Mining.Test/MinGasPriceTests.cs index 2e613d8c8e9..bd1e9e4db65 100644 --- a/src/Nethermind/Nethermind.Mining.Test/MinGasPriceTests.cs +++ b/src/Nethermind/Nethermind.Mining.Test/MinGasPriceTests.cs @@ -54,6 +54,19 @@ public void Test1559(long minimum, long maxFeePerGas, long maxPriorityFeePerGas, specProvider.GetSpec(Arg.Any(), Arg.Any()).IsEip1559Enabled.Returns(true); specProvider.GetSpec(Arg.Any()).IsEip1559Enabled.Returns(true); specProvider.GetSpec(Arg.Any()).IsEip1559Enabled.Returns(true); + + specProvider.GetSpec(Arg.Any()).ForkBaseFee.Returns(Eip1559Constants.DefaultForkBaseFee); + specProvider.GetSpec(Arg.Any()).BaseFeeMaxChangeDenominator.Returns(Eip1559Constants.DefaultBaseFeeMaxChangeDenominator); + specProvider.GetSpec(Arg.Any()).ElasticityMultiplier.Returns(Eip1559Constants.DefaultElasticityMultiplier); + + specProvider.GetSpec(Arg.Any(), Arg.Any()).ForkBaseFee.Returns(Eip1559Constants.DefaultForkBaseFee); + specProvider.GetSpec(Arg.Any(), Arg.Any()).BaseFeeMaxChangeDenominator.Returns(Eip1559Constants.DefaultBaseFeeMaxChangeDenominator); + specProvider.GetSpec(Arg.Any(), Arg.Any()).ElasticityMultiplier.Returns(Eip1559Constants.DefaultElasticityMultiplier); + + specProvider.GetSpec(Arg.Any()).ForkBaseFee.Returns(Eip1559Constants.DefaultForkBaseFee); + specProvider.GetSpec(Arg.Any()).BaseFeeMaxChangeDenominator.Returns(Eip1559Constants.DefaultBaseFeeMaxChangeDenominator); + specProvider.GetSpec(Arg.Any()).ElasticityMultiplier.Returns(Eip1559Constants.DefaultElasticityMultiplier); + BlocksConfig blocksConfig = new() { MinGasPrice = (UInt256)minimum diff --git a/src/Nethermind/Nethermind.Optimism/Create2DeployerContractRewriter.cs b/src/Nethermind/Nethermind.Optimism/Create2DeployerContractRewriter.cs new file mode 100644 index 00000000000..5485998ec55 --- /dev/null +++ b/src/Nethermind/Nethermind.Optimism/Create2DeployerContractRewriter.cs @@ -0,0 +1,34 @@ +// SPDX-FileCopyrightText: 2023 Demerzel Solutions Limited +// SPDX-License-Identifier: LGPL-3.0-only + +using Nethermind.Blockchain; +using Nethermind.Blockchain.Find; +using Nethermind.Core; +using Nethermind.Core.Specs; +using Nethermind.State; + +namespace Nethermind.Optimism; + +public class Create2DeployerContractRewriter +{ + private IOPConfigHelper _opConfigHelper; + private ISpecProvider _specProvider; + private IBlockTree _blockTree; + + public Create2DeployerContractRewriter(IOPConfigHelper opConfigHelper, ISpecProvider specProvider, IBlockTree blockTree) + { + _opConfigHelper = opConfigHelper; + _specProvider = specProvider; + _blockTree = blockTree; + } + + public void RewriteContract(BlockHeader header, IWorldState worldState) + { + IReleaseSpec spec = _specProvider.GetSpec(header); + BlockHeader? parent = _blockTree.FindParent(header, BlockTreeLookupOptions.None)?.Header; + if ((parent is null || !_opConfigHelper.IsCanyon(parent)) && _opConfigHelper.IsCanyon(header)) + { + worldState.InsertCode(_opConfigHelper.Create2DeployerAddress!, _opConfigHelper.Create2DeployerCode, spec); + } + } +} diff --git a/src/Nethermind/Nethermind.Optimism/IOPConfigHelper.cs b/src/Nethermind/Nethermind.Optimism/IOPConfigHelper.cs index 2875a2b7e9a..e59e591d4b4 100644 --- a/src/Nethermind/Nethermind.Optimism/IOPConfigHelper.cs +++ b/src/Nethermind/Nethermind.Optimism/IOPConfigHelper.cs @@ -11,4 +11,7 @@ public interface IOPConfigHelper bool IsBedrock(BlockHeader header); bool IsRegolith(BlockHeader header); + bool IsCanyon(BlockHeader header); + Address? Create2DeployerAddress { get; } + byte[]? Create2DeployerCode { get; } } diff --git a/src/Nethermind/Nethermind.Optimism/InitializeBlockchainOptimism.cs b/src/Nethermind/Nethermind.Optimism/InitializeBlockchainOptimism.cs index 6920765a0dc..fb7b53726ff 100644 --- a/src/Nethermind/Nethermind.Optimism/InitializeBlockchainOptimism.cs +++ b/src/Nethermind/Nethermind.Optimism/InitializeBlockchainOptimism.cs @@ -5,6 +5,7 @@ using Nethermind.Api; using Nethermind.Blockchain.Services; using Nethermind.Config; +using Nethermind.Consensus.Processing; using Nethermind.Consensus.Producers; using Nethermind.Consensus.Validators; using Nethermind.Evm; @@ -27,11 +28,7 @@ public InitializeBlockchainOptimism(OptimismNethermindApi api) : base(api) protected override Task InitBlockchain() { - _api.SpecHelper = new( - _api.ChainSpec.Optimism.RegolithTimestamp, - _api.ChainSpec.Optimism.BedrockBlockNumber, - _api.ChainSpec.Optimism.L1FeeRecipient - ); + _api.SpecHelper = new(_api.ChainSpec.Optimism); _api.L1CostHelper = new(_api.SpecHelper, _api.ChainSpec.Optimism.L1BlockAddress); return base.InitBlockchain(); @@ -84,6 +81,32 @@ protected override IBlockValidator CreateBlockValidator() return new InvalidBlockInterceptor(blockValidator, _api.InvalidChainTracker, _api.LogManager); } + protected override BlockProcessor CreateBlockProcessor() + { + if (_api.DbProvider is null) throw new StepDependencyException(nameof(_api.DbProvider)); + if (_api.RewardCalculatorSource is null) throw new StepDependencyException(nameof(_api.RewardCalculatorSource)); + if (_api.TransactionProcessor is null) throw new StepDependencyException(nameof(_api.TransactionProcessor)); + if (_api.SpecHelper is null) throw new StepDependencyException(nameof(_api.SpecHelper)); + if (_api.SpecProvider is null) throw new StepDependencyException(nameof(_api.SpecProvider)); + if (_api.BlockTree is null) throw new StepDependencyException(nameof(_api.BlockTree)); + if (_api.WorldState is null) throw new StepDependencyException(nameof(_api.WorldState)); + + Create2DeployerContractRewriter contractRewriter = + new(_api.SpecHelper, _api.SpecProvider, _api.BlockTree); + + return new OptimismBlockProcessor( + _api.SpecProvider, + _api.BlockValidator, + _api.RewardCalculatorSource.Get(_api.TransactionProcessor!), + new BlockProcessor.BlockValidationTransactionsExecutor(_api.TransactionProcessor, _api.WorldState), + _api.WorldState, + _api.ReceiptStorage, + _api.WitnessCollector, + _api.LogManager, + _api.SpecHelper, + contractRewriter); + } + protected override IUnclesValidator CreateUnclesValidator() => Always.Valid; protected override IHealthHintService CreateHealthHintService() => diff --git a/src/Nethermind/Nethermind.Optimism/OPConfigHelper.cs b/src/Nethermind/Nethermind.Optimism/OPConfigHelper.cs index d9c56cf389c..3902d88b024 100644 --- a/src/Nethermind/Nethermind.Optimism/OPConfigHelper.cs +++ b/src/Nethermind/Nethermind.Optimism/OPConfigHelper.cs @@ -2,6 +2,7 @@ // SPDX-License-Identifier: LGPL-3.0-only using Nethermind.Core; +using Nethermind.Specs.ChainSpecStyle; namespace Nethermind.Optimism; @@ -9,14 +10,18 @@ public class OPSpecHelper : IOPConfigHelper { private readonly ulong _regolithTimestamp; private readonly long _bedrockBlockNumber; + private readonly ulong? _canyonTimestamp; public Address L1FeeReceiver { get; init; } - public OPSpecHelper(ulong regolithTimestamp, long bedrockBlockNumber, Address l1FeeReceiver) + public OPSpecHelper(OptimismParameters parameters) { - _regolithTimestamp = regolithTimestamp; - _bedrockBlockNumber = bedrockBlockNumber; - L1FeeReceiver = l1FeeReceiver; + _regolithTimestamp = parameters.RegolithTimestamp; + _bedrockBlockNumber = parameters.BedrockBlockNumber; + _canyonTimestamp = parameters.CanyonTimestamp; + L1FeeReceiver = parameters.L1FeeRecipient; + Create2DeployerCode = parameters.Create2DeployerCode; + Create2DeployerAddress = parameters.Create2DeployerAddress; } public bool IsRegolith(BlockHeader header) @@ -28,4 +33,12 @@ public bool IsBedrock(BlockHeader header) { return header.Number >= _bedrockBlockNumber; } + + public bool IsCanyon(BlockHeader header) + { + return header.Timestamp >= (_canyonTimestamp ?? long.MaxValue); + } + + public Address? Create2DeployerAddress { get; } + public byte[]? Create2DeployerCode { get; } } diff --git a/src/Nethermind/Nethermind.Optimism/OptimismBlockProcessor.cs b/src/Nethermind/Nethermind.Optimism/OptimismBlockProcessor.cs new file mode 100644 index 00000000000..50389d91351 --- /dev/null +++ b/src/Nethermind/Nethermind.Optimism/OptimismBlockProcessor.cs @@ -0,0 +1,47 @@ +// SPDX-FileCopyrightText: 2023 Demerzel Solutions Limited +// SPDX-License-Identifier: LGPL-3.0-only + +using System; +using Nethermind.Blockchain.Receipts; +using Nethermind.Consensus.Processing; +using Nethermind.Consensus.Rewards; +using Nethermind.Consensus.Validators; +using Nethermind.Consensus.Withdrawals; +using Nethermind.Core; +using Nethermind.Core.Specs; +using Nethermind.Evm.Tracing; +using Nethermind.Logging; +using Nethermind.State; + +namespace Nethermind.Optimism; + +public class OptimismBlockProcessor : BlockProcessor +{ + private Create2DeployerContractRewriter? _contractRewriter; + + public OptimismBlockProcessor( + ISpecProvider? specProvider, + IBlockValidator? blockValidator, + IRewardCalculator? rewardCalculator, + IBlockProcessor.IBlockTransactionsExecutor? blockTransactionsExecutor, + IWorldState? stateProvider, + IReceiptStorage? receiptStorage, + IWitnessCollector? witnessCollector, + ILogManager? logManager, + IOPConfigHelper opConfigHelper, + Create2DeployerContractRewriter contractRewriter, + IWithdrawalProcessor? withdrawalProcessor = null) + : base(specProvider, blockValidator, rewardCalculator, blockTransactionsExecutor, + stateProvider, receiptStorage, witnessCollector, logManager, withdrawalProcessor) + { + ArgumentNullException.ThrowIfNull(stateProvider); + _contractRewriter = contractRewriter; + ReceiptsTracer = new OptimismBlockReceiptTracer(opConfigHelper, stateProvider); + } + + protected override TxReceipt[] ProcessBlock(Block block, IBlockTracer blockTracer, ProcessingOptions options) + { + _contractRewriter?.RewriteContract(block.Header, _stateProvider); + return base.ProcessBlock(block, blockTracer, options); + } +} diff --git a/src/Nethermind/Nethermind.Optimism/OptimismBlockProducerEnvFactory.cs b/src/Nethermind/Nethermind.Optimism/OptimismBlockProducerEnvFactory.cs index 7393e7fdfa8..42df6a18aa3 100644 --- a/src/Nethermind/Nethermind.Optimism/OptimismBlockProducerEnvFactory.cs +++ b/src/Nethermind/Nethermind.Optimism/OptimismBlockProducerEnvFactory.cs @@ -10,14 +10,11 @@ using Nethermind.Consensus.Rewards; using Nethermind.Consensus.Transactions; using Nethermind.Consensus.Validators; -using Nethermind.Core; +using Nethermind.Consensus.Withdrawals; using Nethermind.Core.Specs; -using Nethermind.Db; -using Nethermind.Evm.TransactionProcessing; using Nethermind.Logging; using Nethermind.Specs.ChainSpecStyle; using Nethermind.State; -using Nethermind.Trie.Pruning; using Nethermind.TxPool; namespace Nethermind.Optimism; @@ -74,4 +71,26 @@ protected override ITxSource CreateTxSourceForProducer(ITxSource? additionalTxSo return new OptimismTxPoolTxSource(baseTxSource); } + + protected override BlockProcessor CreateBlockProcessor( + ReadOnlyTxProcessingEnv readOnlyTxProcessingEnv, + ISpecProvider specProvider, + IBlockValidator blockValidator, + IRewardCalculatorSource rewardCalculatorSource, + IReceiptStorage receiptStorage, + ILogManager logManager, + IBlocksConfig blocksConfig) + { + return new OptimismBlockProcessor(specProvider, + blockValidator, + rewardCalculatorSource.Get(readOnlyTxProcessingEnv.TransactionProcessor), + TransactionsExecutorFactory.Create(readOnlyTxProcessingEnv), + readOnlyTxProcessingEnv.StateProvider, + receiptStorage, + NullWitnessCollector.Instance, + logManager, + _specHelper, + new Create2DeployerContractRewriter(_specHelper, _specProvider, _blockTree), + new BlockProductionWithdrawalProcessor(new WithdrawalProcessor(readOnlyTxProcessingEnv.StateProvider, logManager))); + } } diff --git a/src/Nethermind/Nethermind.Optimism/OptimismBlockReceiptTracer.cs b/src/Nethermind/Nethermind.Optimism/OptimismBlockReceiptTracer.cs new file mode 100644 index 00000000000..95048f27080 --- /dev/null +++ b/src/Nethermind/Nethermind.Optimism/OptimismBlockReceiptTracer.cs @@ -0,0 +1,50 @@ +// SPDX-FileCopyrightText: 2023 Demerzel Solutions Limited +// SPDX-License-Identifier: LGPL-3.0-only + +using System; +using Nethermind.Core; +using Nethermind.Core.Crypto; +using Nethermind.Evm.Tracing; +using Nethermind.State; + +namespace Nethermind.Optimism; + +public class OptimismBlockReceiptTracer : BlockReceiptsTracer +{ + private IOPConfigHelper _opConfigHelper; + private IWorldState _worldState; + + public OptimismBlockReceiptTracer(IOPConfigHelper opConfigHelper, IWorldState worldState) + { + _opConfigHelper = opConfigHelper; + _worldState = worldState; + } + + private (ulong?, ulong?) GetDepositReceiptData(BlockHeader header) + { + ArgumentNullException.ThrowIfNull(CurrentTx); + + ulong? depositNonce = null; + ulong? version = null; + + if (CurrentTx.IsDeposit()) + { + depositNonce = _worldState.GetNonce(CurrentTx.SenderAddress!).ToUInt64(null); + if (_opConfigHelper.IsCanyon(header)) + { + version = 1; + } + } + + return (depositNonce == 0 ? 0 : depositNonce - 1, version); + } + + protected override TxReceipt BuildReceipt(Address recipient, long spentGas, byte statusCode, LogEntry[] logEntries, Hash256? stateRoot) + { + (ulong? depositNonce, ulong? version) = GetDepositReceiptData(Block.Header); + TxReceipt receipt = base.BuildReceipt(recipient, spentGas, statusCode, logEntries, stateRoot); + receipt.DepositNonce = depositNonce; + receipt.DepositReceiptVersion = version; + return receipt; + } +} diff --git a/src/Nethermind/Nethermind.Optimism/OptimismPlugin.cs b/src/Nethermind/Nethermind.Optimism/OptimismPlugin.cs index d95345a7fbb..c1897641cc1 100644 --- a/src/Nethermind/Nethermind.Optimism/OptimismPlugin.cs +++ b/src/Nethermind/Nethermind.Optimism/OptimismPlugin.cs @@ -136,7 +136,7 @@ public Task InitSynchronization() _api.DisposeStack.Push((PeerRefresher)_peerRefresher); _beaconPivot = new BeaconPivot(_syncConfig, _api.DbProvider.MetadataDb, _api.BlockTree, _api.LogManager); - _beaconSync = new BeaconSync(_beaconPivot, _api.BlockTree, _syncConfig, _blockCacheService, _api.LogManager); + _beaconSync = new BeaconSync(_beaconPivot, _api.BlockTree, _syncConfig, _blockCacheService, _api.PoSSwitcher, _api.LogManager); _api.BetterPeerStrategy = new MergeBetterPeerStrategy(null!, _api.PoSSwitcher, _beaconPivot, _api.LogManager); _api.Pivot = _beaconPivot; diff --git a/src/Nethermind/Nethermind.Optimism/OptimismTransactionProcessor.cs b/src/Nethermind/Nethermind.Optimism/OptimismTransactionProcessor.cs index b58391a4317..1af53687a9e 100644 --- a/src/Nethermind/Nethermind.Optimism/OptimismTransactionProcessor.cs +++ b/src/Nethermind/Nethermind.Optimism/OptimismTransactionProcessor.cs @@ -31,20 +31,19 @@ public OptimismTransactionProcessor( private UInt256? _currentTxL1Cost; - protected override void Execute(Transaction tx, BlockExecutionContext blCtx, ITxTracer tracer, ExecutionOptions opts) + protected override void Execute(Transaction tx, in BlockExecutionContext blCtx, ITxTracer tracer, ExecutionOptions opts) { + IReleaseSpec spec = SpecProvider.GetSpec(blCtx.Header); _currentTxL1Cost = null; if (tx.IsDeposit()) { - IReleaseSpec spec = SpecProvider.GetSpec(blCtx.Header); - WorldState.AddToBalanceAndCreateIfNotExists(tx.SenderAddress!, tx.Mint, spec); if (opts.HasFlag(ExecutionOptions.Commit) || !spec.IsEip658Enabled) WorldState.Commit(spec); } - base.Execute(tx, blCtx, tracer, opts); + base.Execute(tx, in blCtx, tracer, opts); } protected override bool ValidateStatic(Transaction tx, BlockHeader header, IReleaseSpec spec, ITxTracer tracer, ExecutionOptions opts, diff --git a/src/Nethermind/Nethermind.Runner.Test/Ethereum/ContextWithMocks.cs b/src/Nethermind/Nethermind.Runner.Test/Ethereum/ContextWithMocks.cs index 0550a49d49f..6d8f3484754 100644 --- a/src/Nethermind/Nethermind.Runner.Test/Ethereum/ContextWithMocks.cs +++ b/src/Nethermind/Nethermind.Runner.Test/Ethereum/ContextWithMocks.cs @@ -44,6 +44,7 @@ using Nethermind.Specs; using Nethermind.Synchronization.SnapSync; using NSubstitute; +using Nethermind.Blockchain.Blocks; namespace Nethermind.Runner.Test.Ethereum { @@ -117,7 +118,8 @@ public static NethermindApi ContextWithMocks() SyncProgressResolver = Substitute.For(), BetterPeerStrategy = Substitute.For(), ReceiptMonitor = Substitute.For(), - WitnessRepository = Substitute.For() + WitnessRepository = Substitute.For(), + BadBlocksStore = Substitute.For() }; api.WorldStateManager = new ReadOnlyWorldStateManager(api.DbProvider, Substitute.For(), LimboLogs.Instance); diff --git a/src/Nethermind/Nethermind.Runner.Test/Ethereum/Steps/Migrations/ReceiptMigrationTests.cs b/src/Nethermind/Nethermind.Runner.Test/Ethereum/Steps/Migrations/ReceiptMigrationTests.cs index 8762884e529..fe452fb0691 100644 --- a/src/Nethermind/Nethermind.Runner.Test/Ethereum/Steps/Migrations/ReceiptMigrationTests.cs +++ b/src/Nethermind/Nethermind.Runner.Test/Ethereum/Steps/Migrations/ReceiptMigrationTests.cs @@ -161,7 +161,9 @@ public void EnsureCanonical(Block block) { } - public event EventHandler ReceiptsInserted { add { } remove { } } +#pragma warning disable CS0067 + public event EventHandler ReceiptsInserted; +#pragma warning restore CS0067 } } } diff --git a/src/Nethermind/Nethermind.Runner/configs/base-goerli.cfg b/src/Nethermind/Nethermind.Runner/configs/base-goerli.cfg index 938b91d8dab..641271bc3ac 100644 --- a/src/Nethermind/Nethermind.Runner/configs/base-goerli.cfg +++ b/src/Nethermind/Nethermind.Runner/configs/base-goerli.cfg @@ -9,9 +9,6 @@ "Sync": { "NetworkingEnabled": false }, - "Sync": { - "NetworkingEnabled": false - }, "JsonRpc" : { "Enabled" : true, "Port" : 8545, diff --git a/src/Nethermind/Nethermind.Runner/configs/chiado.cfg b/src/Nethermind/Nethermind.Runner/configs/chiado.cfg index 9f17bd7fb82..bf562a4a091 100644 --- a/src/Nethermind/Nethermind.Runner/configs/chiado.cfg +++ b/src/Nethermind/Nethermind.Runner/configs/chiado.cfg @@ -13,8 +13,8 @@ "Sync": { "FastSync": true, "FastBlocks": true, - "PivotNumber": 7480000, - "PivotHash": "0x5f05365bfc54de3c1410c33354f4a6ec3f3d99d88992760a7a0b5bfedecc1439", + "PivotNumber": 7580000, + "PivotHash": "0xf23063619522a038100cb2fc66e7947294e6dd6da0422ff769f2833729f7d6fb", "PivotTotalDifficulty": "231708131825107706987652208063906496124457284", "FastSyncCatchUpHeightDelta": "10000000000", "UseGethLimitsInFastBlocks": false diff --git a/src/Nethermind/Nethermind.Runner/configs/energyweb.cfg b/src/Nethermind/Nethermind.Runner/configs/energyweb.cfg index 94bf9cf92ab..4d49d044dbb 100644 --- a/src/Nethermind/Nethermind.Runner/configs/energyweb.cfg +++ b/src/Nethermind/Nethermind.Runner/configs/energyweb.cfg @@ -8,9 +8,9 @@ }, "Sync": { "FastSync": true, - "PivotNumber": 27600000, - "PivotHash": "0x823ba12746ec06d8b717ebb17506083786b2d09ed94ef6a123808178e4e65b29", - "PivotTotalDifficulty": "9391793327017901591589139165116802635817474057", + "PivotNumber": 27710000, + "PivotHash": "0xf5f417b63a2a43ba7fcc610017f23380db4969600a8f7f2672ad774713247cd2", + "PivotTotalDifficulty": "9429224387379204822570110371934297139077403490", "FastBlocks": true, "UseGethLimitsInFastBlocks": false, "FastSyncCatchUpHeightDelta": 10000000000 diff --git a/src/Nethermind/Nethermind.Runner/configs/exosama.cfg b/src/Nethermind/Nethermind.Runner/configs/exosama.cfg index 36f8d2e062d..81c11ed694a 100644 --- a/src/Nethermind/Nethermind.Runner/configs/exosama.cfg +++ b/src/Nethermind/Nethermind.Runner/configs/exosama.cfg @@ -8,9 +8,9 @@ }, "Sync": { "FastSync": true, - "PivotNumber": 7380000, - "PivotHash": "0x713965cd5f7dfcf3222f01363f9e47424ae80e730aa7a4c0b93c282b8001d21c", - "PivotTotalDifficulty": "2511283867876525860359704602846449400197373288", + "PivotNumber": 7510000, + "PivotHash": "0x77046fb443f3c3f0d3a168a35800fb1fe577100b41965f579b658e9c70e6a0a1", + "PivotTotalDifficulty": "2555520575576247860609943301812579267686393288", "FastBlocks": true, "UseGethLimitsInFastBlocks": false, "FastSyncCatchUpHeightDelta": 10000000000 diff --git a/src/Nethermind/Nethermind.Runner/configs/gnosis.cfg b/src/Nethermind/Nethermind.Runner/configs/gnosis.cfg index 37b3677f820..6ded43f6d74 100644 --- a/src/Nethermind/Nethermind.Runner/configs/gnosis.cfg +++ b/src/Nethermind/Nethermind.Runner/configs/gnosis.cfg @@ -12,8 +12,8 @@ }, "Sync": { "FastSync": true, - "PivotNumber": 31580000, - "PivotHash": "0xa9d5fe3742935569f98e381cfbb8f479fdb4d4367a3b4c71eca31313326d67bd", + "PivotNumber": 31690000, + "PivotHash": "0xb1c5f676cb85d4794c0ee949bc44adbee925da08d982136c2813c4e5f4b56768", "PivotTotalDifficulty": "8626000110427538733349499292577475819600160930", "FastBlocks": true, "UseGethLimitsInFastBlocks": false, diff --git a/src/Nethermind/Nethermind.Runner/configs/joc-mainnet.cfg b/src/Nethermind/Nethermind.Runner/configs/joc-mainnet.cfg index b641647308e..5a2153deff0 100644 --- a/src/Nethermind/Nethermind.Runner/configs/joc-mainnet.cfg +++ b/src/Nethermind/Nethermind.Runner/configs/joc-mainnet.cfg @@ -9,9 +9,9 @@ "FastSync": true, "SnapSync": true, "FastBlocks": true, - "PivotNumber": 8750000, - "PivotHash": "0x0ca157493b30e4911bfd6f5531f3ff9f5950731bfb0a4a562a65a70e0866b9cf", - "PivotTotalDifficulty": "17499036" + "PivotNumber": 8870000, + "PivotHash": "0x3d8c071530dd409324d5b74916f94f1553afb850051ae6143dd9bdbd4ad2b866", + "PivotTotalDifficulty": "17734268" }, "Metrics": { "NodeName": "JOC-Mainnet" diff --git a/src/Nethermind/Nethermind.Runner/configs/joc-testnet.cfg b/src/Nethermind/Nethermind.Runner/configs/joc-testnet.cfg index ef9b162b106..b78abb7f41b 100644 --- a/src/Nethermind/Nethermind.Runner/configs/joc-testnet.cfg +++ b/src/Nethermind/Nethermind.Runner/configs/joc-testnet.cfg @@ -9,9 +9,9 @@ "FastSync": true, "SnapSync": true, "FastBlocks": true, - "PivotNumber": 2350000, - "PivotHash": "0xbade98eea2f7239e920c1ac8d37a4cf76eaa1e33f62dfbab1a968d4585ce0ca6", - "PivotTotalDifficulty": "4699812" + "PivotNumber": 2470000, + "PivotHash": "0x457e4a8f96f002fd503c380c8b45b077a9280b3f00b6198cf80cd69f22c67b59", + "PivotTotalDifficulty": "4939802" }, "Metrics": { "NodeName": "JOC-Testnet" diff --git a/src/Nethermind/Nethermind.Runner/configs/mainnet.cfg b/src/Nethermind/Nethermind.Runner/configs/mainnet.cfg index 66832e806bf..1c5a8cca358 100644 --- a/src/Nethermind/Nethermind.Runner/configs/mainnet.cfg +++ b/src/Nethermind/Nethermind.Runner/configs/mainnet.cfg @@ -12,8 +12,8 @@ "Sync": { "FastSync": true, "SnapSync": true, - "PivotNumber": 18850000, - "PivotHash": "0x60968426404bd84733406475bb2c2bc9a550cc02ec8565f71d246d5c69a83bd9", + "PivotNumber": 18900000, + "PivotHash": "0x84bd4976f299d9343a18a1088f1cec0dbcac72b6d51a6fc9b901921a55449fc6", "PivotTotalDifficulty": "58750003716598352816469", "FastBlocks": true, "FastSyncCatchUpHeightDelta": "10000000000" diff --git a/src/Nethermind/Nethermind.Runner/configs/sepolia.cfg b/src/Nethermind/Nethermind.Runner/configs/sepolia.cfg index 475b632fe37..c0aff1477e2 100644 --- a/src/Nethermind/Nethermind.Runner/configs/sepolia.cfg +++ b/src/Nethermind/Nethermind.Runner/configs/sepolia.cfg @@ -18,8 +18,8 @@ "FastBlocks": true, "SnapSync": true, "UseGethLimitsInFastBlocks": true, - "PivotNumber": 4944000, - "PivotHash": "0xb470476a2c4c811cb136d6e88e3c3b2fc9463bdeb3e8187228b6d8d4d37f8280", + "PivotNumber": 4988000, + "PivotHash": "0xfa0e1cff9cf2ad67171d4c4b2e19b09f411f79756fd99d861744607dd88e9131", "PivotTotalDifficulty": "17000018015853232", "FastSyncCatchUpHeightDelta": "10000000000" }, diff --git a/src/Nethermind/Nethermind.Runner/configs/volta.cfg b/src/Nethermind/Nethermind.Runner/configs/volta.cfg index ce6195d8911..f6685fcce6b 100644 --- a/src/Nethermind/Nethermind.Runner/configs/volta.cfg +++ b/src/Nethermind/Nethermind.Runner/configs/volta.cfg @@ -12,9 +12,9 @@ }, "Sync": { "FastSync": true, - "PivotNumber": 26010000, - "PivotHash": "0xf4866dd804892fab476209a7780101c66f8d77585475f46e1145d19dc66545f8", - "PivotTotalDifficulty": "8850744363613609434682373539300291179604019546", + "PivotNumber": 26100000, + "PivotHash": "0xbd8ddbf4f3677a4e959f961478f56a971816f275b443a51387ba68e623cc4aec", + "PivotTotalDifficulty": "8881369776636493896394077253969150318634850916", "FastBlocks": true, "UseGethLimitsInFastBlocks": false, "FastSyncCatchUpHeightDelta": 10000000000 diff --git a/src/Nethermind/Nethermind.Serialization.Rlp/ReceiptMessageDecoder.cs b/src/Nethermind/Nethermind.Serialization.Rlp/ReceiptMessageDecoder.cs index 052a6e766b1..ce58b0c0c95 100644 --- a/src/Nethermind/Nethermind.Serialization.Rlp/ReceiptMessageDecoder.cs +++ b/src/Nethermind/Nethermind.Serialization.Rlp/ReceiptMessageDecoder.cs @@ -57,8 +57,14 @@ public TxReceipt Decode(RlpStream rlpStream, RlpBehaviors rlpBehaviors = RlpBeha { entries[i] = Rlp.Decode(rlpStream, RlpBehaviors.AllowExtraBytes); } - txReceipt.Logs = entries; + + if (txReceipt.TxType == TxType.DepositTx && rlpStream.Position != lastCheck) + { + txReceipt.DepositNonce = rlpStream.DecodeUlong(); + txReceipt.DepositReceiptVersion = rlpStream.DecodeUlong(); + } + return txReceipt; } @@ -85,6 +91,12 @@ private static (int Total, int Logs) GetContentLength(TxReceipt item, RlpBehavio : Rlp.LengthOf(item.PostTransactionState); } + if (item.TxType == TxType.DepositTx && item.DepositReceiptVersion is not null) + { + contentLength += Rlp.LengthOf(item.DepositNonce ?? 0); + contentLength += Rlp.LengthOf(item.DepositReceiptVersion.Value); + } + return (contentLength, logsLength); } @@ -173,6 +185,12 @@ public void Encode(RlpStream rlpStream, TxReceipt item, RlpBehaviors rlpBehavior { rlpStream.Encode(item.Logs[i]); } + + if (item.TxType == TxType.DepositTx && item.DepositReceiptVersion is not null) + { + rlpStream.Encode(item.DepositNonce!.Value); + rlpStream.Encode(item.DepositReceiptVersion.Value); + } } } } diff --git a/src/Nethermind/Nethermind.Specs.Test/OverridableReleaseSpec.cs b/src/Nethermind/Nethermind.Specs.Test/OverridableReleaseSpec.cs index 225168c5b1d..b36a57071d0 100644 --- a/src/Nethermind/Nethermind.Specs.Test/OverridableReleaseSpec.cs +++ b/src/Nethermind/Nethermind.Specs.Test/OverridableReleaseSpec.cs @@ -157,5 +157,8 @@ public ulong Eip4844TransitionTimestamp public bool IsEip6780Enabled => _spec.IsEip6780Enabled; public bool IsEip4788Enabled => _spec.IsEip4788Enabled; public Address Eip4788ContractAddress => _spec.Eip4788ContractAddress; + public UInt256 ForkBaseFee => _spec.ForkBaseFee; + public UInt256 BaseFeeMaxChangeDenominator => _spec.BaseFeeMaxChangeDenominator; + public long ElasticityMultiplier => _spec.ElasticityMultiplier; } } diff --git a/src/Nethermind/Nethermind.Specs/ChainSpecStyle/ChainParameters.cs b/src/Nethermind/Nethermind.Specs/ChainSpecStyle/ChainParameters.cs index 2b5f645602b..817250bc01e 100644 --- a/src/Nethermind/Nethermind.Specs/ChainSpecStyle/ChainParameters.cs +++ b/src/Nethermind/Nethermind.Specs/ChainSpecStyle/ChainParameters.cs @@ -54,11 +54,11 @@ public class ChainParameters public long? Eip3541Transition { get; set; } public long? Eip3607Transition { get; set; } - public UInt256 Eip1559BaseFeeInitialValue { get; set; } + public UInt256? Eip1559BaseFeeInitialValue { get; set; } - public UInt256 Eip1559BaseFeeMaxChangeDenominator { get; set; } + public UInt256? Eip1559BaseFeeMaxChangeDenominator { get; set; } - public long Eip1559ElasticityMultiplier { get; set; } + public long? Eip1559ElasticityMultiplier { get; set; } /// /// Transaction permission managing contract address. diff --git a/src/Nethermind/Nethermind.Specs/ChainSpecStyle/ChainSpecBasedSpecProvider.cs b/src/Nethermind/Nethermind.Specs/ChainSpecStyle/ChainSpecBasedSpecProvider.cs index 4e94afb5f12..7aad4bac04f 100644 --- a/src/Nethermind/Nethermind.Specs/ChainSpecStyle/ChainSpecBasedSpecProvider.cs +++ b/src/Nethermind/Nethermind.Specs/ChainSpecStyle/ChainSpecBasedSpecProvider.cs @@ -6,6 +6,7 @@ using System.Linq; using System.Numerics; using System.Reflection; +using Nethermind.Core; using Nethermind.Core.Specs; using Nethermind.Int256; using Nethermind.Logging; @@ -205,8 +206,18 @@ private static ReleaseSpec CreateReleaseSpec(ChainSpec chainSpec, long releaseSt releaseSpec.IsEip3607Enabled = (chainSpec.Parameters.Eip3607Transition ?? long.MaxValue) <= releaseStartBlock; releaseSpec.ValidateChainId = (chainSpec.Parameters.ValidateChainIdTransition ?? 0) <= releaseStartBlock; releaseSpec.ValidateReceipts = ((chainSpec.Parameters.ValidateReceiptsTransition > 0) ? Math.Max(chainSpec.Parameters.ValidateReceiptsTransition ?? 0, chainSpec.Parameters.Eip658Transition ?? 0) : 0) <= releaseStartBlock; + releaseSpec.Eip1559FeeCollector = releaseSpec.IsEip1559Enabled && (chainSpec.Parameters.Eip1559FeeCollectorTransition ?? long.MaxValue) <= releaseStartBlock ? chainSpec.Parameters.Eip1559FeeCollector : null; releaseSpec.Eip1559BaseFeeMinValue = releaseSpec.IsEip1559Enabled && (chainSpec.Parameters.Eip1559BaseFeeMinValueTransition ?? long.MaxValue) <= releaseStartBlock ? chainSpec.Parameters.Eip1559BaseFeeMinValue : null; + releaseSpec.ElasticityMultiplier = chainSpec.Parameters.Eip1559ElasticityMultiplier ?? Eip1559Constants.DefaultElasticityMultiplier; + releaseSpec.ForkBaseFee = chainSpec.Parameters.Eip1559BaseFeeInitialValue ?? Eip1559Constants.DefaultForkBaseFee; + releaseSpec.BaseFeeMaxChangeDenominator = chainSpec.Parameters.Eip1559BaseFeeMaxChangeDenominator ?? Eip1559Constants.DefaultBaseFeeMaxChangeDenominator; + + if (chainSpec.Optimism?.CanyonTimestamp <= releaseStartTimestamp) + { + releaseSpec.BaseFeeMaxChangeDenominator = chainSpec.Optimism.CanyonBaseFeeChangeDenominator; + } + if (chainSpec.Ethash is not null) { diff --git a/src/Nethermind/Nethermind.Specs/ChainSpecStyle/ChainSpecLoader.cs b/src/Nethermind/Nethermind.Specs/ChainSpecStyle/ChainSpecLoader.cs index 163834c1a40..ec649bbda53 100644 --- a/src/Nethermind/Nethermind.Specs/ChainSpecStyle/ChainSpecLoader.cs +++ b/src/Nethermind/Nethermind.Specs/ChainSpecStyle/ChainSpecLoader.cs @@ -157,10 +157,10 @@ bool GetForInnerPathExistence(KeyValuePair o) TransactionPermissionContractTransition = chainSpecJson.Params.TransactionPermissionContractTransition, ValidateChainIdTransition = chainSpecJson.Params.ValidateChainIdTransition, ValidateReceiptsTransition = chainSpecJson.Params.ValidateReceiptsTransition, - Eip1559ElasticityMultiplier = chainSpecJson.Params.Eip1559ElasticityMultiplier ?? Eip1559Constants.ElasticityMultiplier, - Eip1559BaseFeeInitialValue = chainSpecJson.Params.Eip1559BaseFeeInitialValue ?? Eip1559Constants.ForkBaseFee, + Eip1559ElasticityMultiplier = chainSpecJson.Params.Eip1559ElasticityMultiplier ?? Eip1559Constants.DefaultElasticityMultiplier, + Eip1559BaseFeeInitialValue = chainSpecJson.Params.Eip1559BaseFeeInitialValue ?? Eip1559Constants.DefaultForkBaseFee, Eip1559BaseFeeMaxChangeDenominator = chainSpecJson.Params.Eip1559BaseFeeMaxChangeDenominator ?? - Eip1559Constants.BaseFeeMaxChangeDenominator, + Eip1559Constants.DefaultBaseFeeMaxChangeDenominator, Eip1559FeeCollector = chainSpecJson.Params.Eip1559FeeCollector, Eip1559FeeCollectorTransition = chainSpecJson.Params.Eip1559FeeCollectorTransition, Eip1559BaseFeeMinValueTransition = chainSpecJson.Params.Eip1559BaseFeeMinValueTransition, @@ -180,10 +180,6 @@ bool GetForInnerPathExistence(KeyValuePair o) ?? GetTransitionForExpectedPricing("alt_bn128_pairing", "price.alt_bn128_pairing.base", 45000); chainSpec.Parameters.Eip2565Transition ??= GetTransitionIfInnerPathExists("modexp", "price.modexp2565"); - Eip1559Constants.ElasticityMultiplier = chainSpec.Parameters.Eip1559ElasticityMultiplier; - Eip1559Constants.ForkBaseFee = chainSpec.Parameters.Eip1559BaseFeeInitialValue; - Eip1559Constants.BaseFeeMaxChangeDenominator = chainSpec.Parameters.Eip1559BaseFeeMaxChangeDenominator; - Eip4844Constants.OverrideIfAny( chainSpec.Parameters.Eip4844BlobGasPriceUpdateFraction, chainSpec.Parameters.Eip4844MaxBlobGasPerBlock, @@ -347,8 +343,12 @@ static AuRaParameters.Validator LoadValidator(ChainSpecJson.AuRaValidatorJson va { RegolithTimestamp = chainSpecJson.Engine.Optimism.RegolithTimestamp, BedrockBlockNumber = chainSpecJson.Engine.Optimism.BedrockBlockNumber, + CanyonTimestamp = chainSpecJson.Engine.Optimism.CanyonTimestamp, L1FeeRecipient = chainSpecJson.Engine.Optimism.L1FeeRecipient, - L1BlockAddress = chainSpecJson.Engine.Optimism.L1BlockAddress + L1BlockAddress = chainSpecJson.Engine.Optimism.L1BlockAddress, + CanyonBaseFeeChangeDenominator = chainSpecJson.Engine.Optimism.CanyonBaseFeeChangeDenominator, + Create2DeployerAddress = chainSpecJson.Engine.Optimism.Create2DeployerAddress, + Create2DeployerCode = chainSpecJson.Engine.Optimism.Create2DeployerCode }; } else if (chainSpecJson.Engine?.NethDev is not null) diff --git a/src/Nethermind/Nethermind.Specs/ChainSpecStyle/Json/ChainSpecGenesisJson.cs b/src/Nethermind/Nethermind.Specs/ChainSpecStyle/Json/ChainSpecGenesisJson.cs index c04038cafe0..a72fb549b86 100644 --- a/src/Nethermind/Nethermind.Specs/ChainSpecStyle/Json/ChainSpecGenesisJson.cs +++ b/src/Nethermind/Nethermind.Specs/ChainSpecStyle/Json/ChainSpecGenesisJson.cs @@ -24,8 +24,8 @@ internal class ChainSpecGenesisJson public bool StateUnavailable { get; set; } = false; public Hash256 StateRoot { get; set; } - public ulong? BlobGasUsed { get; set; } - public ulong? ExcessBlobGas { get; set; } + public ulong BlobGasUsed { get; set; } + public ulong ExcessBlobGas { get; set; } public Hash256 ParentBeaconBlockRoot { get; set; } } } diff --git a/src/Nethermind/Nethermind.Specs/ChainSpecStyle/Json/ChainSpecJson.cs b/src/Nethermind/Nethermind.Specs/ChainSpecStyle/Json/ChainSpecJson.cs index 4bf9b38fe2f..d819732c34f 100644 --- a/src/Nethermind/Nethermind.Specs/ChainSpecStyle/Json/ChainSpecJson.cs +++ b/src/Nethermind/Nethermind.Specs/ChainSpecStyle/Json/ChainSpecJson.cs @@ -7,6 +7,7 @@ using System.Text.Json; using System.Text.Json.Serialization; using Nethermind.Core; +using Nethermind.Core.Crypto; using Nethermind.Int256; namespace Nethermind.Specs.ChainSpecStyle.Json @@ -171,8 +172,12 @@ internal class OptimismEngineJson { public ulong RegolithTimestamp => Params.RegolithTimestamp; public long BedrockBlockNumber => Params.BedrockBlockNumber; + public ulong? CanyonTimestamp => Params.CanyonTimestamp; public Address L1FeeRecipient => Params.L1FeeRecipient; public Address L1BlockAddress => Params.L1BlockAddress; + public UInt256 CanyonBaseFeeChangeDenominator => Params.CanyonBaseFeeChangeDenominator; + public Address Create2DeployerAddress => Params.Create2DeployerAddress; + public byte[] Create2DeployerCode => Params.Create2DeployerCode; public OptimismEngineParamsJson Params { get; set; } } @@ -180,8 +185,12 @@ internal class OptimismEngineParamsJson { public ulong RegolithTimestamp { get; set; } public long BedrockBlockNumber { get; set; } + public ulong? CanyonTimestamp { get; set; } public Address L1FeeRecipient { get; set; } public Address L1BlockAddress { get; set; } + public UInt256 CanyonBaseFeeChangeDenominator { get; set; } + public Address Create2DeployerAddress { get; set; } + public byte[] Create2DeployerCode { get; set; } } internal class NethDevJson diff --git a/src/Nethermind/Nethermind.Specs/ChainSpecStyle/OptimismParameters.cs b/src/Nethermind/Nethermind.Specs/ChainSpecStyle/OptimismParameters.cs index 586481dbc96..b2439224257 100644 --- a/src/Nethermind/Nethermind.Specs/ChainSpecStyle/OptimismParameters.cs +++ b/src/Nethermind/Nethermind.Specs/ChainSpecStyle/OptimismParameters.cs @@ -1,7 +1,6 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only -using System.Collections.Generic; using Nethermind.Core; using Nethermind.Int256; @@ -13,8 +12,16 @@ public class OptimismParameters public long BedrockBlockNumber { get; set; } + public ulong? CanyonTimestamp { get; set; } + public Address L1FeeRecipient { get; set; } public Address L1BlockAddress { get; set; } + + public UInt256 CanyonBaseFeeChangeDenominator { get; set; } + + public Address Create2DeployerAddress { get; set; } + + public byte[] Create2DeployerCode { get; set; } } } diff --git a/src/Nethermind/Nethermind.Specs/ReleaseSpec.cs b/src/Nethermind/Nethermind.Specs/ReleaseSpec.cs index fa886f82fa6..5de83c8356b 100644 --- a/src/Nethermind/Nethermind.Specs/ReleaseSpec.cs +++ b/src/Nethermind/Nethermind.Specs/ReleaseSpec.cs @@ -72,6 +72,9 @@ public ReleaseSpec Clone() public ulong Eip4844TransitionTimestamp { get; set; } public Address Eip1559FeeCollector { get; set; } public UInt256? Eip1559BaseFeeMinValue { get; set; } + public UInt256 ForkBaseFee { get; set; } = Eip1559Constants.DefaultForkBaseFee; + public UInt256 BaseFeeMaxChangeDenominator { get; set; } = Eip1559Constants.DefaultBaseFeeMaxChangeDenominator; + public long ElasticityMultiplier { get; set; } = Eip1559Constants.DefaultElasticityMultiplier; public bool IsEip1153Enabled { get; set; } public bool IsEip3651Enabled { get; set; } public bool IsEip3855Enabled { get; set; } diff --git a/src/Nethermind/Nethermind.Specs/SystemTransactionReleaseSpec.cs b/src/Nethermind/Nethermind.Specs/SystemTransactionReleaseSpec.cs index b4c0c4d29e8..8774d7a03ae 100644 --- a/src/Nethermind/Nethermind.Specs/SystemTransactionReleaseSpec.cs +++ b/src/Nethermind/Nethermind.Specs/SystemTransactionReleaseSpec.cs @@ -130,5 +130,8 @@ public bool IsEip158IgnoredAccount(Address address) public bool IsEip6780Enabled => _spec.IsEip6780Enabled; public bool IsEip4788Enabled => _spec.IsEip4788Enabled; public Address Eip4788ContractAddress => _spec.Eip4788ContractAddress; + public UInt256 ForkBaseFee => _spec.ForkBaseFee; + public UInt256 BaseFeeMaxChangeDenominator => _spec.BaseFeeMaxChangeDenominator; + public long ElasticityMultiplier => _spec.ElasticityMultiplier; } } diff --git a/src/Nethermind/Nethermind.State/StateProvider.cs b/src/Nethermind/Nethermind.State/StateProvider.cs index 1d0cfa2ac28..4ecaff55d2a 100644 --- a/src/Nethermind/Nethermind.State/StateProvider.cs +++ b/src/Nethermind/Nethermind.State/StateProvider.cs @@ -26,6 +26,7 @@ internal class StateProvider private const int StartCapacity = Resettable.StartCapacity; private readonly ResettableDictionary> _intraBlockCache = new(); private readonly ResettableHashSet
_committedThisRound = new(); + private readonly HashSet
_nullAccountReads = new(); // Only guarding against hot duplicates so filter doesn't need to be too big // Note: // False negatives are fine as they will just result in a overwrite set @@ -508,7 +509,7 @@ public void Commit(IReleaseSpec releaseSpec, IWorldStateTracer stateTracer, bool // because it was not committed yet it means that the just cache is the only state (so it was read only) if (isTracing && change.ChangeType == ChangeType.JustCache) { - _readsForTracing.Add(change.Address); + _nullAccountReads.Add(change.Address); continue; } @@ -597,7 +598,7 @@ public void Commit(IReleaseSpec releaseSpec, IWorldStateTracer stateTracer, bool if (isTracing) { - foreach (Address nullRead in _readsForTracing) + foreach (Address nullRead in _nullAccountReads) { // // this may be enough, let us write tests stateTracer.ReportAccountRead(nullRead); @@ -606,7 +607,7 @@ public void Commit(IReleaseSpec releaseSpec, IWorldStateTracer stateTracer, bool Resettable.Reset(ref _changes, ref _capacity, ref _currentPosition, StartCapacity); _committedThisRound.Reset(); - _readsForTracing.Clear(); + _nullAccountReads.Clear(); _intraBlockCache.Reset(); if (isTracing) @@ -687,10 +688,10 @@ private void SetState(Address address, Account? account) _tree.Set(address, account); } - private readonly HashSet
_readsForTracing = new(); - private Account? GetAndAddToCache(Address address) { + if (_nullAccountReads.Contains(address)) return null; + Account? account = GetState(address); if (account is not null) { @@ -699,7 +700,7 @@ private void SetState(Address address, Account? account) else { // just for tracing - potential perf hit, maybe a better solution? - _readsForTracing.Add(address); + _nullAccountReads.Add(address); } return account; @@ -803,7 +804,7 @@ public void Reset() if (_logger.IsTrace) _logger.Trace("Clearing state provider caches"); _intraBlockCache.Reset(); _committedThisRound.Reset(); - _readsForTracing.Clear(); + _nullAccountReads.Clear(); _currentPosition = Resettable.EmptyPosition; Array.Clear(_changes, 0, _changes.Length); _needsStateRootUpdate = false; diff --git a/src/Nethermind/Nethermind.Synchronization.Test/BlockDownloaderTests.Merge.cs b/src/Nethermind/Nethermind.Synchronization.Test/BlockDownloaderTests.Merge.cs index 2800d2910bd..10ae29c0c92 100644 --- a/src/Nethermind/Nethermind.Synchronization.Test/BlockDownloaderTests.Merge.cs +++ b/src/Nethermind/Nethermind.Synchronization.Test/BlockDownloaderTests.Merge.cs @@ -20,6 +20,7 @@ using Nethermind.Merge.Plugin.Synchronization; using Nethermind.Merge.Plugin.Test; using Nethermind.Specs; +using Nethermind.Specs.ChainSpecStyle; using Nethermind.Stats; using Nethermind.Stats.Model; using Nethermind.Synchronization.Blocks; @@ -456,6 +457,7 @@ public MergeConfig MergeConfig MetadataDb, BlockTree, SpecProvider, + new ChainSpec(), LimboLogs.Instance); protected override IBetterPeerStrategy BetterPeerStrategy => _betterPeerStrategy ??= diff --git a/src/Nethermind/Nethermind.Synchronization.Test/ParallelSync/MultiSyncModeSelectorTests.Scenario.cs b/src/Nethermind/Nethermind.Synchronization.Test/ParallelSync/MultiSyncModeSelectorTests.Scenario.cs index b7cc95c5442..6e4e327bbe6 100644 --- a/src/Nethermind/Nethermind.Synchronization.Test/ParallelSync/MultiSyncModeSelectorTests.Scenario.cs +++ b/src/Nethermind/Nethermind.Synchronization.Test/ParallelSync/MultiSyncModeSelectorTests.Scenario.cs @@ -884,7 +884,7 @@ public ScenarioBuilder WhenMergeSyncPivotNotResolvedYet() { SyncConfig.MaxAttemptsToUpdatePivot = 3; BeaconSyncStrategy = Substitute.For(); - BeaconSyncStrategy.GetFinalizedHash().Returns(TestItem.KeccakA); + BeaconSyncStrategy.MergeTransitionFinished.Returns(true); return "merge sync pivot not resolved yet"; } ); diff --git a/src/Nethermind/Nethermind.Synchronization.Test/SnapSync/ProgressTrackerTests.cs b/src/Nethermind/Nethermind.Synchronization.Test/SnapSync/ProgressTrackerTests.cs index f702e409258..921b5baa7df 100644 --- a/src/Nethermind/Nethermind.Synchronization.Test/SnapSync/ProgressTrackerTests.cs +++ b/src/Nethermind/Nethermind.Synchronization.Test/SnapSync/ProgressTrackerTests.cs @@ -6,6 +6,7 @@ using FluentAssertions; using Nethermind.Blockchain; using Nethermind.Core.Crypto; +using Nethermind.Core.Test; using Nethermind.Core.Test.Builders; using Nethermind.Db; using Nethermind.Logging; @@ -135,4 +136,24 @@ public void Will_deque_storage_request_if_high() request.CodesRequest.Should().BeNull(); request.StorageRangeRequest.Should().NotBeNull(); } + + [Test] + public void Will_mark_progress_and_flush_when_finished() + { + BlockTree blockTree = Build.A.BlockTree().WithBlocks(Build.A.Block + .WithStateRoot(Keccak.EmptyTreeHash) + .TestObject).TestObject; + TestMemDb memDb = new TestMemDb(); + ProgressTracker progressTracker = new ProgressTracker(blockTree, memDb, LimboLogs.Instance, 1); + + (SnapSyncBatch request, bool finished) = progressTracker.GetNextRequest(); + request.AccountRangeRequest.Should().NotBeNull(); + progressTracker.UpdateAccountRangePartitionProgress(request.AccountRangeRequest!.LimitHash!.Value, Keccak.MaxValue, false); + progressTracker.ReportAccountRangePartitionFinished(request.AccountRangeRequest!.LimitHash!.Value); + (_, finished) = progressTracker.GetNextRequest(); + finished.Should().BeTrue(); + + memDb.WasFlushed.Should().BeTrue(); + memDb[ProgressTracker.ACC_PROGRESS_KEY].Should().BeEquivalentTo(Keccak.MaxValue.BytesToArray()); + } } diff --git a/src/Nethermind/Nethermind.Synchronization.Test/SyncServerTests.cs b/src/Nethermind/Nethermind.Synchronization.Test/SyncServerTests.cs index 5394cd8e754..8ecab27bc76 100644 --- a/src/Nethermind/Nethermind.Synchronization.Test/SyncServerTests.cs +++ b/src/Nethermind/Nethermind.Synchronization.Test/SyncServerTests.cs @@ -22,6 +22,7 @@ using Nethermind.Merge.Plugin.Handlers; using Nethermind.Merge.Plugin.InvalidChainTracker; using Nethermind.Specs; +using Nethermind.Specs.ChainSpecStyle; using Nethermind.Specs.Forks; using Nethermind.State; using Nethermind.Stats.Model; @@ -180,6 +181,7 @@ public void Terminal_block_with_lower_td_should_not_change_best_suggested_but_sh new MemDb(), localBlockTree, testSpecProvider, + new ChainSpec(), LimboLogs.Instance); HeaderValidator headerValidator = new( localBlockTree, @@ -389,6 +391,7 @@ private Context CreateMergeContext(int blockTreeChainLength, UInt256 ttd) new MemDb(), localBlockTree, testSpecProvider, + new ChainSpec(), LimboLogs.Instance); MergeSealEngine sealEngine = new( new SealEngine(new NethDevSealEngine(), Always.Valid), diff --git a/src/Nethermind/Nethermind.Synchronization.Test/SynchronizerTests.cs b/src/Nethermind/Nethermind.Synchronization.Test/SynchronizerTests.cs index a1ed58c7617..3d2cfd28eef 100644 --- a/src/Nethermind/Nethermind.Synchronization.Test/SynchronizerTests.cs +++ b/src/Nethermind/Nethermind.Synchronization.Test/SynchronizerTests.cs @@ -324,7 +324,7 @@ ISyncConfig GetSyncConfig() => { mergeConfig.TerminalTotalDifficulty = UInt256.MaxValue.ToString(CultureInfo.InvariantCulture); } - PoSSwitcher poSSwitcher = new(mergeConfig, syncConfig, dbProvider.MetadataDb, BlockTree, new TestSingleReleaseSpecProvider(Constantinople.Instance), _logManager); + PoSSwitcher poSSwitcher = new(mergeConfig, syncConfig, dbProvider.MetadataDb, BlockTree, new TestSingleReleaseSpecProvider(Constantinople.Instance), new ChainSpec(), _logManager); IBeaconPivot beaconPivot = new BeaconPivot(syncConfig, dbProvider.MetadataDb, BlockTree, _logManager); TrieStore trieStore = new(stateDb, LimboLogs.Instance); diff --git a/src/Nethermind/Nethermind.Synchronization/IBeaconSyncStrategy.cs b/src/Nethermind/Nethermind.Synchronization/IBeaconSyncStrategy.cs index 264369d4ac7..9043437fe28 100644 --- a/src/Nethermind/Nethermind.Synchronization/IBeaconSyncStrategy.cs +++ b/src/Nethermind/Nethermind.Synchronization/IBeaconSyncStrategy.cs @@ -17,6 +17,7 @@ private No() { } public bool ShouldBeInBeaconModeControl() => false; public bool IsBeaconSyncFinished(BlockHeader? blockHeader) => true; + public bool MergeTransitionFinished => false; public long? GetTargetBlockHeight() => null; public Hash256? GetFinalizedHash() => null; } @@ -27,6 +28,8 @@ public interface IBeaconSyncStrategy bool ShouldBeInBeaconModeControl(); bool IsBeaconSyncFinished(BlockHeader? blockHeader); + public bool MergeTransitionFinished { get; } + public long? GetTargetBlockHeight(); public Hash256? GetFinalizedHash(); } diff --git a/src/Nethermind/Nethermind.Synchronization/ParallelSync/MultiSyncModeSelector.cs b/src/Nethermind/Nethermind.Synchronization/ParallelSync/MultiSyncModeSelector.cs index f7f7c40fcd0..8dc3378cbde 100644 --- a/src/Nethermind/Nethermind.Synchronization/ParallelSync/MultiSyncModeSelector.cs +++ b/src/Nethermind/Nethermind.Synchronization/ParallelSync/MultiSyncModeSelector.cs @@ -356,7 +356,7 @@ private bool ShouldBeInBeaconHeaders(bool shouldBeInUpdatingPivot) private bool ShouldBeInUpdatingPivot() { bool updateRequestedAndNotFinished = _syncConfig.MaxAttemptsToUpdatePivot > 0; - bool isPostMerge = _beaconSyncStrategy.GetFinalizedHash() != null; + bool isPostMerge = _beaconSyncStrategy.MergeTransitionFinished; bool stateSyncNotFinished = _syncProgressResolver.FindBestFullState() == 0; bool result = updateRequestedAndNotFinished && diff --git a/src/Nethermind/Nethermind.Synchronization/SnapSync/ProgressTracker.cs b/src/Nethermind/Nethermind.Synchronization/SnapSync/ProgressTracker.cs index 15b99c6c7f8..f73edf4c79c 100644 --- a/src/Nethermind/Nethermind.Synchronization/SnapSync/ProgressTracker.cs +++ b/src/Nethermind/Nethermind.Synchronization/SnapSync/ProgressTracker.cs @@ -24,7 +24,7 @@ public class ProgressTracker public const int HIGH_STORAGE_QUEUE_SIZE = STORAGE_BATCH_SIZE * 100; private const int CODES_BATCH_SIZE = 1_000; public const int HIGH_CODES_QUEUE_SIZE = CODES_BATCH_SIZE * 5; - private readonly byte[] ACC_PROGRESS_KEY = Encoding.ASCII.GetBytes("AccountProgressKey"); + internal static readonly byte[] ACC_PROGRESS_KEY = Encoding.ASCII.GetBytes("AccountProgressKey"); // This does not need to be a lot as it spawn other requests. In fact 8 is probably too much. It is severely // bottlenecked by _syncCommit lock in SnapProviderHelper, which in turns is limited by the IO. @@ -416,7 +416,8 @@ private void GetSyncProgress() private void FinishRangePhase() { - _db.PutSpan(ACC_PROGRESS_KEY, ValueKeccak.MaxValue.Bytes); + _db.PutSpan(ACC_PROGRESS_KEY, ValueKeccak.MaxValue.Bytes, WriteFlags.DisableWAL); + _db.Flush(); } private void LogRequest(string reqType) diff --git a/src/Nethermind/Nethermind.Trie/PatriciaTree.cs b/src/Nethermind/Nethermind.Trie/PatriciaTree.cs index a66779f4a97..1cedadc144e 100644 --- a/src/Nethermind/Nethermind.Trie/PatriciaTree.cs +++ b/src/Nethermind/Nethermind.Trie/PatriciaTree.cs @@ -53,6 +53,9 @@ public class PatriciaTree private readonly bool _allowCommits; + private readonly bool _isTrace; + private readonly bool _isDebug; + private Hash256 _rootHash = Keccak.EmptyTreeHash; public TrieNode? RootRef { get; set; } @@ -116,6 +119,8 @@ public PatriciaTree( ICappedArrayPool? bufferPool = null) { _logger = logManager?.GetClassLogger() ?? throw new ArgumentNullException(nameof(logManager)); + _isTrace = _logger.IsTrace; + _isDebug = _logger.IsDebug; TrieStore = trieStore ?? throw new ArgumentNullException(nameof(trieStore)); _parallelBranches = parallelBranches; _allowCommits = allowCommits; @@ -137,13 +142,12 @@ public void Commit(long blockNumber, bool skipRoot = false, WriteFlags writeFlag { if (_currentCommit is null) { - throw new InvalidAsynchronousStateException( - $"{nameof(_currentCommit)} is NULL when calling {nameof(Commit)}"); + ThrowInvalidAsynchronousStateException(); } if (!_allowCommits) { - throw new TrieException("Commits are not allowed on this trie."); + ThrowTrieException(); } if (RootRef is not null && RootRef.IsDirty) @@ -151,7 +155,7 @@ public void Commit(long blockNumber, bool skipRoot = false, WriteFlags writeFlag Commit(new NodeCommitInfo(RootRef), skipSelf: skipRoot); while (_currentCommit.TryDequeue(out NodeCommitInfo node)) { - if (_logger.IsTrace) _logger.Trace($"Committing {node} in {blockNumber}"); + if (_isTrace) Trace(blockNumber, node); TrieStore.CommitNode(blockNumber, node, writeFlags: writeFlags); } @@ -161,21 +165,46 @@ public void Commit(long blockNumber, bool skipRoot = false, WriteFlags writeFlag } TrieStore.FinishBlockCommit(TrieType, blockNumber, RootRef, writeFlags); - if (_logger.IsDebug) _logger.Debug($"Finished committing block {blockNumber}"); + + if (_isDebug) Debug(blockNumber); + + [MethodImpl(MethodImplOptions.NoInlining)] + void Trace(long blockNumber, in NodeCommitInfo node) + { + _logger.Trace($"Committing {node} in {blockNumber}"); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + void Debug(long blockNumber) + { + _logger.Debug($"Finished committing block {blockNumber}"); + } + + [DoesNotReturn] + [StackTraceHidden] + static void ThrowInvalidAsynchronousStateException() + { + throw new InvalidAsynchronousStateException($"{nameof(_currentCommit)} is NULL when calling {nameof(Commit)}"); + } + + [DoesNotReturn] + [StackTraceHidden] + static void ThrowTrieException() + { + throw new TrieException("Commits are not allowed on this trie."); + } } private void Commit(NodeCommitInfo nodeCommitInfo, bool skipSelf = false) { if (_currentCommit is null) { - throw new InvalidAsynchronousStateException( - $"{nameof(_currentCommit)} is NULL when calling {nameof(Commit)}"); + ThrowInvalidAsynchronousStateException(nameof(_currentCommit)); } if (_commitExceptions is null) { - throw new InvalidAsynchronousStateException( - $"{nameof(_commitExceptions)} is NULL when calling {nameof(Commit)}"); + ThrowInvalidAsynchronousStateException(nameof(_commitExceptions)); } TrieNode node = nodeCommitInfo.Node; @@ -192,20 +221,16 @@ private void Commit(NodeCommitInfo nodeCommitInfo, bool skipSelf = false) } else { - if (_logger.IsTrace) + if (_isTrace) { - TrieNode child = node.GetChild(TrieStore, i); - if (child is not null) - { - _logger.Trace($"Skipping commit of {child}"); - } + Trace(node, i); } } } } else { - List nodesToCommit = new(); + List nodesToCommit = new(16); for (int i = 0; i < 16; i++) { if (node.IsChildDirty(i)) @@ -214,13 +239,9 @@ private void Commit(NodeCommitInfo nodeCommitInfo, bool skipSelf = false) } else { - if (_logger.IsTrace) + if (_isTrace) { - TrieNode child = node.GetChild(TrieStore, i); - if (child is not null) - { - _logger.Trace($"Skipping commit of {child}"); - } + Trace(node, i); } } } @@ -242,7 +263,7 @@ private void Commit(NodeCommitInfo nodeCommitInfo, bool skipSelf = false) if (!_commitExceptions.IsEmpty) { - throw new AggregateException(_commitExceptions); + ThrowAggregateExceptions(); } } else @@ -259,7 +280,7 @@ private void Commit(NodeCommitInfo nodeCommitInfo, bool skipSelf = false) TrieNode extensionChild = node.GetChild(TrieStore, 0); if (extensionChild is null) { - throw new InvalidOperationException("An attempt to store an extension without a child."); + ThrowInvalidExtension(); } if (extensionChild.IsDirty) @@ -268,7 +289,7 @@ private void Commit(NodeCommitInfo nodeCommitInfo, bool skipSelf = false) } else { - if (_logger.IsTrace) _logger.Trace($"Skipping commit of {extensionChild}"); + if (_isTrace) TraceExtensionSkip(extensionChild); } } @@ -284,7 +305,50 @@ private void Commit(NodeCommitInfo nodeCommitInfo, bool skipSelf = false) } else { - if (_logger.IsTrace) _logger.Trace($"Skipping commit of an inlined {node}"); + if (_isTrace) TraceSkipInlineNode(node); + } + + [DoesNotReturn] + [StackTraceHidden] + void ThrowAggregateExceptions() + { + throw new AggregateException(_commitExceptions); + } + + [DoesNotReturn] + [StackTraceHidden] + static void ThrowInvalidExtension() + { + throw new InvalidOperationException("An attempt to store an extension without a child."); + } + + [DoesNotReturn] + [StackTraceHidden] + static void ThrowInvalidAsynchronousStateException(string param) + { + throw new InvalidAsynchronousStateException($"{param} is NULL when calling {nameof(Commit)}"); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + void Trace(TrieNode node, int i) + { + TrieNode child = node.GetChild(TrieStore, i); + if (child is not null) + { + _logger.Trace($"Skipping commit of {child}"); + } + } + + [MethodImpl(MethodImplOptions.NoInlining)] + void TraceExtensionSkip(TrieNode extensionChild) + { + _logger.Trace($"Skipping commit of {extensionChild}"); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + void TraceSkipInlineNode(TrieNode node) + { + _logger.Trace($"Skipping commit of an inlined {node}"); } } @@ -320,15 +384,11 @@ private void SetRootHash(Hash256? value, bool resetObjects) : array = ArrayPool.Shared.Rent(nibblesCount)) [..nibblesCount]; // Slice to exact size; - try - { - Nibbles.BytesToNibbleBytes(rawKey, nibbles); - return Run(nibbles, nibblesCount, new CappedArray(Array.Empty()), false, startRootHash: rootHash).ToArray(); - } - finally - { - if (array is not null) ArrayPool.Shared.Return(array); - } + Nibbles.BytesToNibbleBytes(rawKey, nibbles); + var result = Run(nibbles, nibblesCount, new CappedArray(Array.Empty()), false, startRootHash: rootHash).ToArray(); + if (array is not null) ArrayPool.Shared.Return(array); + + return result; } catch (TrieException e) { @@ -337,6 +397,7 @@ private void SetRootHash(Hash256? value, bool resetObjects) } } + [MethodImpl(MethodImplOptions.NoInlining)] private static void EnhanceException(ReadOnlySpan rawKey, ValueHash256 rootHash, TrieException baseException) { static TrieNodeException? GetTrieNodeException(TrieException? exception) => @@ -367,8 +428,7 @@ public virtual void Set(ReadOnlySpan rawKey, byte[] value) [DebuggerStepThrough] public virtual void Set(ReadOnlySpan rawKey, CappedArray value) { - if (_logger.IsTrace) - _logger.Trace($"{(value.Length == 0 ? $"Deleting {rawKey.ToHexString()}" : $"Setting {rawKey.ToHexString()} = {value.AsSpan().ToHexString()}")}"); + if (_isTrace) Trace(in rawKey, in value); int nibblesCount = 2 * rawKey.Length; byte[] array = null; @@ -377,14 +437,14 @@ public virtual void Set(ReadOnlySpan rawKey, CappedArray value) : array = ArrayPool.Shared.Rent(nibblesCount)) [..nibblesCount]; // Slice to exact size - try - { - Nibbles.BytesToNibbleBytes(rawKey, nibbles); - Run(nibbles, nibblesCount, value, true); - } - finally + Nibbles.BytesToNibbleBytes(rawKey, nibbles); + Run(nibbles, nibblesCount, value, true); + + if (array is not null) ArrayPool.Shared.Return(array); + + void Trace(in ReadOnlySpan rawKey, in CappedArray value) { - if (array is not null) ArrayPool.Shared.Return(array); + _logger.Trace($"{(value.Length == 0 ? $"Deleting {rawKey.ToHexString()}" : $"Setting {rawKey.ToHexString()} = {value.AsSpan().ToHexString()}")}"); } } @@ -404,7 +464,7 @@ private CappedArray Run( { if (isUpdate && startRootHash is not null) { - throw new InvalidOperationException("Only reads can be done in parallel on the Patricia tree"); + ThrowNonConcurrentWrites(); } #if DEBUG @@ -426,7 +486,7 @@ private CappedArray Run( CappedArray result; if (startRootHash is not null) { - if (_logger.IsTrace) _logger.Trace($"Starting from {startRootHash} - {traverseContext.ToString()}"); + if (_isTrace) TraceStart(startRootHash, in traverseContext); TrieNode startNode = TrieStore.FindCachedOrUnknown(startRootHash); ResolveNode(startNode, in traverseContext); result = TraverseNode(startNode, in traverseContext); @@ -438,23 +498,50 @@ private CappedArray Run( { if (traverseContext.UpdateValue.IsNotNull) { - if (_logger.IsTrace) _logger.Trace($"Setting new leaf node with value {traverseContext.UpdateValue}"); + if (_isTrace) TraceNewLeaf(in traverseContext); byte[] key = updatePath[..nibblesCount].ToArray(); RootRef = TrieNodeFactory.CreateLeaf(key, traverseContext.UpdateValue); } - if (_logger.IsTrace) _logger.Trace($"Keeping the root as null in {traverseContext.ToString()}"); + if (_isTrace) TraceNull(in traverseContext); result = traverseContext.UpdateValue; } else { ResolveNode(RootRef, in traverseContext); - if (_logger.IsTrace) _logger.Trace($"{traverseContext.ToString()}"); + if (_isTrace) TraceNode(in traverseContext); result = TraverseNode(RootRef, in traverseContext); } } return result; + + [DoesNotReturn] + [StackTraceHidden] + static void ThrowNonConcurrentWrites() + { + throw new InvalidOperationException("Only reads can be done in parallel on the Patricia tree"); + } + + void TraceStart(Hash256 startRootHash, in TraverseContext traverseContext) + { + _logger.Trace($"Starting from {startRootHash} - {traverseContext.ToString()}"); + } + + void TraceNewLeaf(in TraverseContext traverseContext) + { + _logger.Trace($"Setting new leaf node with value {traverseContext.UpdateValue}"); + } + + void TraceNull(in TraverseContext traverseContext) + { + _logger.Trace($"Keeping the root as null in {traverseContext.ToString()}"); + } + + void TraceNode(in TraverseContext traverseContext) + { + _logger.Trace($"{traverseContext.ToString()}"); + } } private void ResolveNode(TrieNode node, in TraverseContext traverseContext) @@ -471,20 +558,36 @@ private void ResolveNode(TrieNode node, in TraverseContext traverseContext) private CappedArray TraverseNode(TrieNode node, in TraverseContext traverseContext) { - if (_logger.IsTrace) - _logger.Trace( - $"Traversing {node} to {(traverseContext.IsRead ? "READ" : traverseContext.IsDelete ? "DELETE" : "UPDATE")}"); + if (_isTrace) Trace(node, traverseContext); return node.NodeType switch { NodeType.Branch => TraverseBranch(node, in traverseContext), NodeType.Extension => TraverseExtension(node, in traverseContext), NodeType.Leaf => TraverseLeaf(node, in traverseContext), - NodeType.Unknown => throw new InvalidOperationException( - $"Cannot traverse unresolved node {node.Keccak}"), - _ => throw new NotSupportedException( - $"Unknown node type {node.NodeType}") + NodeType.Unknown => TraverseUnknown(node), + _ => ThrowNotSupported(node) }; + + [MethodImpl(MethodImplOptions.NoInlining)] + void Trace(TrieNode node, in TraverseContext traverseContext) + { + _logger.Trace($"Traversing {node} to {(traverseContext.IsRead ? "READ" : traverseContext.IsDelete ? "DELETE" : "UPDATE")}"); + } + + [DoesNotReturn] + [StackTraceHidden] + static CappedArray TraverseUnknown(TrieNode node) + { + throw new InvalidOperationException($"Cannot traverse unresolved node {node.Keccak}"); + } + + [DoesNotReturn] + [StackTraceHidden] + static CappedArray ThrowNotSupported(TrieNode node) + { + throw new NotSupportedException($"Unknown node type {node.NodeType}"); + } } private void ConnectNodes(TrieNode? node, in TraverseContext traverseContext) @@ -525,7 +628,7 @@ private void ConnectNodes(TrieNode? node, in TraverseContext traverseContext) // which is not possible in the Ethereum protocol where keys are of equal lengths // (it is possible in the more general trie definition) TrieNode leafFromBranch = TrieNodeFactory.CreateLeaf(Array.Empty(), node.Value); - if (_logger.IsTrace) _logger.Trace($"Converting {node} into {leafFromBranch}"); + if (_isTrace) _logger.Trace($"Converting {node} into {leafFromBranch}"); nextNode = leafFromBranch; } else @@ -567,7 +670,7 @@ L X - - - - - - - - - - - - - - */ { TrieNode extensionFromBranch = TrieNodeFactory.CreateExtension(new[] { (byte)childNodeIndex }, childNode); - if (_logger.IsTrace) + if (_isTrace) _logger.Trace( $"Extending child {childNodeIndex} {childNode} of {node} into {extensionFromBranch}"); @@ -603,7 +706,7 @@ L L - - - - - - - - - - - - - - */ byte[] newKey = Bytes.Concat((byte)childNodeIndex, childNode.Key); TrieNode extendedExtension = childNode.CloneWithChangedKey(newKey); - if (_logger.IsTrace) + if (_isTrace) _logger.Trace( $"Extending child {childNodeIndex} {childNode} of {node} into {extendedExtension}"); nextNode = extendedExtension; @@ -613,14 +716,14 @@ L L - - - - - - - - - - - - - - */ byte[] newKey = Bytes.Concat((byte)childNodeIndex, childNode.Key); TrieNode extendedLeaf = childNode.CloneWithChangedKey(newKey); - if (_logger.IsTrace) + if (_isTrace) _logger.Trace( $"Extending branch child {childNodeIndex} {childNode} into {extendedLeaf}"); - if (_logger.IsTrace) _logger.Trace($"Decrementing ref on a leaf extended up to eat a branch {childNode}"); + if (_isTrace) _logger.Trace($"Decrementing ref on a leaf extended up to eat a branch {childNode}"); if (node.IsSealed) { - if (_logger.IsTrace) _logger.Trace($"Decrementing ref on a branch replaced by a leaf {node}"); + if (_isTrace) _logger.Trace($"Decrementing ref on a branch replaced by a leaf {node}"); } nextNode = extendedLeaf; @@ -644,7 +747,7 @@ L L - - - - - - - - - - - - - - */ { byte[] newKey = Bytes.Concat(node.Key, nextNode.Key); TrieNode extendedLeaf = nextNode.CloneWithChangedKey(newKey); - if (_logger.IsTrace) + if (_isTrace) _logger.Trace($"Combining {node} and {nextNode} into {extendedLeaf}"); nextNode = extendedLeaf; @@ -678,7 +781,7 @@ L L - - - - - - - - - - - - - - */ byte[] newKey = Bytes.Concat(node.Key, nextNode.Key); TrieNode extendedExtension = nextNode.CloneWithChangedKey(newKey); - if (_logger.IsTrace) + if (_isTrace) _logger.Trace($"Combining {node} and {nextNode} into {extendedExtension}"); nextNode = extendedExtension; @@ -690,7 +793,7 @@ L L - - - - - - - - - - - - - - */ node = node.Clone(); } - if (_logger.IsTrace) _logger.Trace($"Connecting {node} with {nextNode}"); + if (_isTrace) _logger.Trace($"Connecting {node} with {nextNode}"); node.SetChild(0, nextNode); nextNode = node; } @@ -815,7 +918,7 @@ private CappedArray TraverseLeaf(TrieNode node, in TraverseContext travers longerPathValue = node.Value; } - int extensionLength = FindCommonPrefixLength(shorterPath, longerPath); + int extensionLength = shorterPath.CommonPrefixLength(longerPath); if (extensionLength == shorterPath.Length && extensionLength == longerPath.Length) { if (traverseContext.IsRead) @@ -893,7 +996,7 @@ private CappedArray TraverseExtension(TrieNode node, in TraverseContext tr TrieNode originalNode = node; ReadOnlySpan remaining = traverseContext.GetRemainingUpdatePath(); - int extensionLength = FindCommonPrefixLength(remaining, node.Key); + int extensionLength = remaining.CommonPrefixLength(node.Key); if (extensionLength == node.Key.Length) { if (traverseContext.IsUpdate) @@ -978,18 +1081,6 @@ private CappedArray TraverseNext(in TraverseContext traverseContext, int e return TraverseNode(next, in newContext); } - private static int FindCommonPrefixLength(ReadOnlySpan shorterPath, ReadOnlySpan longerPath) - { - int commonPrefixLength = 0; - int maxLength = Math.Min(shorterPath.Length, longerPath.Length); - for (int i = 0; i < maxLength && shorterPath[i] == longerPath[i]; i++, commonPrefixLength++) - { - // just finding the common part of the path - } - - return commonPrefixLength; - } - private readonly ref struct TraverseContext { public CappedArray UpdateValue { get; } diff --git a/src/Nethermind/Nethermind.Trie/TrieNode.Decoder.cs b/src/Nethermind/Nethermind.Trie/TrieNode.Decoder.cs index a8bf54f78ba..5a87b3c1e1c 100644 --- a/src/Nethermind/Nethermind.Trie/TrieNode.Decoder.cs +++ b/src/Nethermind/Nethermind.Trie/TrieNode.Decoder.cs @@ -4,7 +4,7 @@ using System; using System.Buffers; using System.Diagnostics; -using System.Linq; +using System.Diagnostics.CodeAnalysis; using System.Runtime.CompilerServices; using Nethermind.Core.Buffers; using Nethermind.Core.Crypto; @@ -29,7 +29,7 @@ public static CappedArray Encode(ITrieNodeResolver tree, TrieNode? item, I if (item is null) { - throw new TrieException("An attempt was made to RLP encode a null node."); + ThrowNullNode(); } return item.NodeType switch @@ -37,8 +37,22 @@ public static CappedArray Encode(ITrieNodeResolver tree, TrieNode? item, I NodeType.Branch => RlpEncodeBranch(tree, item, bufferPool), NodeType.Extension => EncodeExtension(tree, item, bufferPool), NodeType.Leaf => EncodeLeaf(item, bufferPool), - _ => throw new TrieException($"An attempt was made to encode a trie node of type {item.NodeType}") + _ => ThrowUnhandledNodeType(item) }; + + [DoesNotReturn] + [StackTraceHidden] + static void ThrowNullNode() + { + throw new TrieException("An attempt was made to RLP encode a null node."); + } + + [DoesNotReturn] + [StackTraceHidden] + static CappedArray ThrowUnhandledNodeType(TrieNode item) + { + throw new TrieException($"An attempt was made to encode a trie node of type {item.NodeType}"); + } } [SkipLocalsInit] @@ -101,7 +115,7 @@ private static CappedArray EncodeLeaf(TrieNode node, ICappedArrayPool? poo { if (node.Key is null) { - throw new TrieException($"Hex prefix of a leaf node is null at node {node.Keccak}"); + ThrowNullKey(node); } byte[] hexPrefix = node.Key; @@ -130,6 +144,13 @@ private static CappedArray EncodeLeaf(TrieNode node, ICappedArrayPool? poo return data; } + [DoesNotReturn] + [StackTraceHidden] + private static void ThrowNullKey(TrieNode node) + { + throw new TrieException($"Hex prefix of a leaf node is null at node {node.Keccak}"); + } + private static CappedArray RlpEncodeBranch(ITrieNodeResolver tree, TrieNode item, ICappedArrayPool? pool) { int valueRlpLength = AllowBranchValues ? Rlp.LengthOf(item.Value.AsSpan()) : 1; diff --git a/src/Nethermind/Nethermind.Trie/TrieNode.cs b/src/Nethermind/Nethermind.Trie/TrieNode.cs index bb229a48678..281c326fca1 100644 --- a/src/Nethermind/Nethermind.Trie/TrieNode.cs +++ b/src/Nethermind/Nethermind.Trie/TrieNode.cs @@ -3,6 +3,8 @@ using System; using System.ComponentModel; +using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; using System.Runtime.CompilerServices; using System.Threading; using Nethermind.Core; @@ -73,13 +75,19 @@ internal set { if (IsSealed) { - throw new InvalidOperationException( - $"{nameof(TrieNode)} {this} is already sealed when setting {nameof(Key)}."); + ThrowAlreadySealed(); } InitData(); _data![0] = value; Keccak = null; + + [DoesNotReturn] + [StackTraceHidden] + void ThrowAlreadySealed() + { + throw new InvalidOperationException($"{nameof(TrieNode)} {this} is already sealed when setting {nameof(Key)}."); + } } } @@ -144,8 +152,7 @@ public CappedArray Value { if (IsSealed) { - throw new InvalidOperationException( - $"{nameof(TrieNode)} {this} is already sealed when setting {nameof(Value)}."); + ThrowAlreadySealed(); } InitData(); @@ -170,6 +177,13 @@ public CappedArray Value } _data![IsLeaf ? 1 : BranchesCount] = value; + + [DoesNotReturn] + [StackTraceHidden] + void ThrowAlreadySealed() + { + throw new InvalidOperationException($"{nameof(TrieNode)} {this} is already sealed when setting {nameof(Value)}."); + } } } @@ -262,10 +276,17 @@ public void Seal() { if (IsSealed) { - throw new InvalidOperationException($"{nameof(TrieNode)} {this} is already sealed."); + ThrowAlreadySealed(); } IsDirty = false; + + [DoesNotReturn] + [StackTraceHidden] + void ThrowAlreadySealed() + { + throw new InvalidOperationException($"{nameof(TrieNode)} {this} is already sealed."); + } } /// @@ -281,7 +302,7 @@ public void ResolveNode(ITrieNodeResolver tree, ReadFlags readFlags = ReadFlags. { if (Keccak is null) { - throw new TrieException("Unable to resolve node without Keccak"); + ThrowMissingKeccak(); } FullRlp = tree.LoadRlp(Keccak, readFlags); @@ -289,7 +310,7 @@ public void ResolveNode(ITrieNodeResolver tree, ReadFlags readFlags = ReadFlags. if (FullRlp.IsNull) { - throw new TrieException($"Trie returned a NULL RLP for node {Keccak}"); + ThrowNullRlp(); } } } @@ -301,15 +322,51 @@ public void ResolveNode(ITrieNodeResolver tree, ReadFlags readFlags = ReadFlags. _rlpStream = FullRlp.AsRlpStream(); if (_rlpStream is null) { - throw new InvalidAsynchronousStateException($"{nameof(_rlpStream)} is null when {nameof(NodeType)} is {NodeType}"); + ThrowInvalidStateException(); + return; } if (!DecodeRlp(bufferPool, out int numberOfItems)) { - throw new TrieNodeException($"Unexpected number of items = {numberOfItems} when decoding a node from RLP ({FullRlp.AsSpan().ToHexString()})", Keccak ?? Nethermind.Core.Crypto.Keccak.Zero); + ThrowUnexpectedNumberOfItems(numberOfItems); } } catch (RlpException rlpException) + { + ThrowDecodingError(rlpException); + } + + [DoesNotReturn] + [StackTraceHidden] + static void ThrowMissingKeccak() + { + throw new TrieException("Unable to resolve node without Keccak"); + } + + [DoesNotReturn] + [StackTraceHidden] + void ThrowNullRlp() + { + throw new TrieException($"Trie returned a NULL RLP for node {Keccak}"); + } + + [DoesNotReturn] + [StackTraceHidden] + void ThrowInvalidStateException() + { + throw new InvalidAsynchronousStateException($"{nameof(_rlpStream)} is null when {nameof(NodeType)} is {NodeType}"); + } + + [DoesNotReturn] + [StackTraceHidden] + void ThrowUnexpectedNumberOfItems(int numberOfItems) + { + throw new TrieNodeException($"Unexpected number of items = {numberOfItems} when decoding a node from RLP ({FullRlp.AsSpan().ToHexString()})", Keccak ?? Nethermind.Core.Crypto.Keccak.Zero); + } + + [DoesNotReturn] + [StackTraceHidden] + void ThrowDecodingError(RlpException rlpException) { throw new TrieNodeException($"Error when decoding node {Keccak}", Keccak ?? Nethermind.Core.Crypto.Keccak.Zero, rlpException); } @@ -348,7 +405,7 @@ public bool TryResolveNode(ITrieNodeResolver tree, ReadFlags readFlags = ReadFla _rlpStream = FullRlp.AsRlpStream(); if (_rlpStream is null) { - throw new InvalidAsynchronousStateException($"{nameof(_rlpStream)} is null when {nameof(NodeType)} is {NodeType}"); + ThrowInvalidStateException(); } return DecodeRlp(bufferPool, out _); @@ -357,6 +414,13 @@ public bool TryResolveNode(ITrieNodeResolver tree, ReadFlags readFlags = ReadFla { return false; } + + [DoesNotReturn] + [StackTraceHidden] + void ThrowInvalidStateException() + { + throw new InvalidAsynchronousStateException($"{nameof(_rlpStream)} is null when {nameof(NodeType)} is {NodeType}"); + } } private bool DecodeRlp(ICappedArrayPool bufferPool, out int itemsCount) @@ -529,8 +593,7 @@ public bool IsChildNull(int i) { if (!IsBranch) { - throw new TrieException( - "An attempt was made to ask about whether a child is null on a non-branch node."); + ThrowNotABranch(); } if (_rlpStream is not null && _data?[i] is null) @@ -540,6 +603,13 @@ public bool IsChildNull(int i) } return _data?[i] is null || ReferenceEquals(_data[i], _nullNode); + + [DoesNotReturn] + [StackTraceHidden] + static void ThrowNotABranch() + { + throw new TrieException("An attempt was made to ask about whether a child is null on a non-branch node."); + } } public bool IsChildDirty(int i) @@ -598,9 +668,7 @@ public TrieNode? this[int i] { // we expect this to happen as a Trie traversal error (please see the stack trace above) // we need to investigate this case when it happens again - bool isKeccakCalculated = Keccak is not null && FullRlp.IsNotNull; - bool isKeccakCorrect = isKeccakCalculated && Keccak == Nethermind.Core.Crypto.Keccak.Compute(FullRlp.AsSpan()); - throw new TrieException($"Unexpected type found at position {childIndex} of {this} with {nameof(_data)} of length {_data?.Length}. Expected a {nameof(TrieNode)} or {nameof(Keccak)} but found {childOrRef?.GetType()} with a value of {childOrRef}. Keccak calculated? : {isKeccakCalculated}; Keccak correct? : {isKeccakCorrect}"); + ThrowUnexpectedTypeException(childIndex, childOrRef); } // pruning trick so we never store long persisted paths @@ -610,6 +678,15 @@ public TrieNode? this[int i] } return child; + + [DoesNotReturn] + [StackTraceHidden] + void ThrowUnexpectedTypeException(int childIndex, object childOrRef) + { + bool isKeccakCalculated = Keccak is not null && FullRlp.IsNotNull; + bool isKeccakCorrect = isKeccakCalculated && Keccak == Nethermind.Core.Crypto.Keccak.Compute(FullRlp.AsSpan()); + throw new TrieException($"Unexpected type found at position {childIndex} of {this} with {nameof(_data)} of length {_data?.Length}. Expected a {nameof(TrieNode)} or {nameof(Keccak)} but found {childOrRef?.GetType()} with a value of {childOrRef}. Keccak calculated? : {isKeccakCalculated}; Keccak correct? : {isKeccakCorrect}"); + } } public void ReplaceChildRef(int i, TrieNode child) @@ -628,14 +705,20 @@ public void SetChild(int i, TrieNode? node) { if (IsSealed) { - throw new InvalidOperationException( - $"{nameof(TrieNode)} {this} is already sealed when setting a child."); + ThrowAlreadySealed(); } InitData(); int index = IsExtension ? i + 1 : i; _data![index] = node ?? _nullNode; Keccak = null; + + [DoesNotReturn] + [StackTraceHidden] + void ThrowAlreadySealed() + { + throw new InvalidOperationException($"{nameof(TrieNode)} {this} is already sealed when setting a child."); + } } public long GetMemorySize(bool recursive) @@ -857,8 +940,6 @@ public void PrunePersistedRecursively(int maxLevelsDeep) // } } - #region private - private bool TryResolveStorageRoot(ITrieNodeResolver resolver, out TrieNode? storageRoot) { bool hasStorage = false; @@ -891,8 +972,8 @@ private void InitData() switch (NodeType) { case NodeType.Unknown: - throw new InvalidOperationException( - $"Cannot resolve children of an {nameof(NodeType.Unknown)} node"); + ThrowCannotResolveException(); + return; case NodeType.Branch: _data = new object[AllowBranchValues ? BranchesCount + 1 : BranchesCount]; break; @@ -901,6 +982,13 @@ private void InitData() break; } } + + [DoesNotReturn] + [StackTraceHidden] + static void ThrowCannotResolveException() + { + throw new InvalidOperationException($"Cannot resolve children of an {nameof(NodeType.Unknown)} node"); + } } private void SeekChild(int itemToSetOn) @@ -999,7 +1087,7 @@ private void UnresolveChild(int i) { if (!childNode.IsPersisted) { - throw new InvalidOperationException("Cannot unresolve a child that is not persisted yet."); + ThrowNotPersisted(); } else if (childNode.Keccak is not null) // if not by value node { @@ -1007,8 +1095,13 @@ private void UnresolveChild(int i) } } } - } - #endregion + [DoesNotReturn] + [StackTraceHidden] + static void ThrowNotPersisted() + { + throw new InvalidOperationException("Cannot unresolve a child that is not persisted yet."); + } + } } } diff --git a/src/Nethermind/Nethermind.TxPool/BlobTxStorage.cs b/src/Nethermind/Nethermind.TxPool/BlobTxStorage.cs index 4ba704d7c54..e05f726d6e1 100644 --- a/src/Nethermind/Nethermind.TxPool/BlobTxStorage.cs +++ b/src/Nethermind/Nethermind.TxPool/BlobTxStorage.cs @@ -65,7 +65,7 @@ public void Add(Transaction transaction) Span txHashPrefixed = stackalloc byte[64]; GetHashPrefixedByTimestamp(transaction.Timestamp, transaction.Hash, txHashPrefixed); - _fullBlobTxsDb.PutSpan(txHashPrefixed, EncodeTx(transaction)); + EncodeAndSaveTx(transaction, _fullBlobTxsDb, txHashPrefixed); _lightBlobTxsDb.Set(transaction.Hash, LightTxDecoder.Encode(transaction)); } @@ -85,7 +85,7 @@ public void AddBlobTransactionsFromBlock(long blockNumber, IList bl return; } - _processedBlobTxsDb.Set(blockNumber, EncodeTxs(blockBlobTransactions)); + EncodeAndSaveTxs(blockBlobTransactions, _processedBlobTxsDb, blockNumber); } public bool TryGetBlobTransactionsFromBlock(long blockNumber, out Transaction[]? blockBlobTransactions) @@ -138,17 +138,17 @@ private static void GetHashPrefixedByTimestamp(UInt256 timestamp, ValueHash256 h hash.Bytes.CopyTo(txHashPrefixed[32..]); } - private Span EncodeTx(Transaction transaction) + private void EncodeAndSaveTx(Transaction transaction, IDb db, Span txHashPrefixed) { int length = _txDecoder.GetLength(transaction, RlpBehaviors.InMempoolForm); IByteBuffer byteBuffer = PooledByteBufferAllocator.Default.Buffer(length); using NettyRlpStream rlpStream = new(byteBuffer); rlpStream.Encode(transaction, RlpBehaviors.InMempoolForm); - return byteBuffer.AsSpan(); + db.PutSpan(txHashPrefixed, byteBuffer.AsSpan()); } - private byte[] EncodeTxs(IList blockBlobTransactions) + private void EncodeAndSaveTxs(IList blockBlobTransactions, IDb db, long blockNumber) { int contentLength = GetLength(blockBlobTransactions); @@ -160,7 +160,7 @@ private byte[] EncodeTxs(IList blockBlobTransactions) _txDecoder.Encode(rlpStream, transaction, RlpBehaviors.InMempoolForm); } - return byteBuffer.Array; + db.Set(blockNumber, byteBuffer.Array); } private int GetLength(IList blockBlobTransactions)