From 8cfbd67cb28ef22cc593c01c813c18ff9836adf3 Mon Sep 17 00:00:00 2001 From: Amirul Ashraf Date: Mon, 11 Sep 2023 12:39:16 +0800 Subject: [PATCH 01/50] Fix read write metric snot updated (#6063) * Fix read write metric snot updated * Fix test --- src/Nethermind/Nethermind.Db.Rocks/ColumnDb.cs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/Nethermind/Nethermind.Db.Rocks/ColumnDb.cs b/src/Nethermind/Nethermind.Db.Rocks/ColumnDb.cs index 008991b728a..dceb3599a21 100644 --- a/src/Nethermind/Nethermind.Db.Rocks/ColumnDb.cs +++ b/src/Nethermind/Nethermind.Db.Rocks/ColumnDb.cs @@ -125,10 +125,15 @@ public void Compact() public long GetIndexSize() => _mainDb.GetIndexSize(); public long GetMemtableSize() => _mainDb.GetMemtableSize(); - public Span GetSpan(ReadOnlySpan key) => _rocksDb.GetSpan(key, _columnFamily); + public Span GetSpan(ReadOnlySpan key) + { + _mainDb.UpdateReadMetrics(); + return _rocksDb.GetSpan(key, _columnFamily); + } public void PutSpan(ReadOnlySpan key, ReadOnlySpan value) { + _mainDb.UpdateWriteMetrics(); _rocksDb.Put(key, value, _columnFamily, _mainDb.WriteOptions); } From 75499850d4b4087c967b767f9ab8d75de6407209 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 11 Sep 2023 15:15:34 +0200 Subject: [PATCH 02/50] Updating Fast Sync config files (#6086) Co-authored-by: LukaszRozmej --- src/Nethermind/Nethermind.Runner/configs/chiado.cfg | 4 ++-- src/Nethermind/Nethermind.Runner/configs/energyweb.cfg | 6 +++--- src/Nethermind/Nethermind.Runner/configs/exosama.cfg | 6 +++--- src/Nethermind/Nethermind.Runner/configs/gnosis.cfg | 4 ++-- src/Nethermind/Nethermind.Runner/configs/goerli.cfg | 4 ++-- src/Nethermind/Nethermind.Runner/configs/mainnet.cfg | 4 ++-- src/Nethermind/Nethermind.Runner/configs/sepolia.cfg | 4 ++-- src/Nethermind/Nethermind.Runner/configs/volta.cfg | 6 +++--- 8 files changed, 19 insertions(+), 19 deletions(-) diff --git a/src/Nethermind/Nethermind.Runner/configs/chiado.cfg b/src/Nethermind/Nethermind.Runner/configs/chiado.cfg index 3f78a0fa318..0b9e24df756 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": 5820000, - "PivotHash": "0x7c94917c84a22fec1f4b18c0ab1b084604bd68ee586fb81d304db4740dad0260", + "PivotNumber": 5950000, + "PivotHash": "0xa1f714043f233352e96c9ce7352f38251fb59f1294206f9a2f1937179ffb3cf1", "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 b04456caae0..61131c20f37 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": 25820000, - "PivotHash": "0xa40862e9c8af59c352a44194416e058097d5bedcbc01122a4126c2a6f980aec6", - "PivotTotalDifficulty": "8786090713898631126624332363888255219429504589", + "PivotNumber": 25930000, + "PivotHash": "0x59f0e0f2bda0ad332648ee42328f5e62a82a01c4f6b99007d5d4d148601d3f43", + "PivotTotalDifficulty": "8823521774259934357605303570705749722689434693", "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 4dd9c9ea0f1..f59f98bc1b1 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": 5450000, - "PivotHash": "0xf9cf872cc01a07f1ff3efcc773749bb8ad3246609ee9c705877fcf634dfeb811", - "PivotTotalDifficulty": "1854538899719114625875391610503136752091153290", + "PivotNumber": 5570000, + "PivotHash": "0x848a9f0145cf43a78dd02e8f73a8b6a918d3e29cb8dd1092fccf445db46c215f", + "PivotTotalDifficulty": "1895372783749627241490996563394948937465633290", "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 25de50f39de..b4b7cce9560 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": 29770000, - "PivotHash": "0x0eba5a6b744dba6fb351c52a2da5541ba8dddd76d6adec96e55c5220442d8a8a", + "PivotNumber": 29880000, + "PivotHash": "0xba2df29e0259704daada7c599558e2135d41b5b6138bac4341f75505f6605050", "PivotTotalDifficulty": "8626000110427538733349499292577475819600160930", "FastBlocks": true, "UseGethLimitsInFastBlocks": false, diff --git a/src/Nethermind/Nethermind.Runner/configs/goerli.cfg b/src/Nethermind/Nethermind.Runner/configs/goerli.cfg index 8033e614db0..c133ef507ad 100644 --- a/src/Nethermind/Nethermind.Runner/configs/goerli.cfg +++ b/src/Nethermind/Nethermind.Runner/configs/goerli.cfg @@ -15,8 +15,8 @@ "Sync": { "FastSync": true, "SnapSync": true, - "PivotNumber": 9600000, - "PivotHash": "0xa6589109b23fa6d489aa9e332d9f4a2d6722bde772a2d70fcf7e05675d4f7073", + "PivotNumber": 9630000, + "PivotHash": "0xfc325661d6b05868c03781d65df95fb63846f8b99707ebd907614008624ffdb0", "PivotTotalDifficulty": "10790000", "FastBlocks": true, "UseGethLimitsInFastBlocks": true, diff --git a/src/Nethermind/Nethermind.Runner/configs/mainnet.cfg b/src/Nethermind/Nethermind.Runner/configs/mainnet.cfg index 699875f3fc9..4238c93d7fa 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": 18051000, - "PivotHash": "0xd097e3121fc9d912b0f5820e0b7554772fc2c42c18f9cd646a406f2a54d8e228", + "PivotNumber": 18101000, + "PivotHash": "0x8c873e8c8bddd8202ea368e00339f1e8dd31c11b48fce562af79911d15496c2b", "PivotTotalDifficulty": "58750003716598352816469", "FastBlocks": true, "AncientBodiesBarrier": 11052984, diff --git a/src/Nethermind/Nethermind.Runner/configs/sepolia.cfg b/src/Nethermind/Nethermind.Runner/configs/sepolia.cfg index 4e7510adaee..ef45d5da42f 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": 4212000, - "PivotHash": "0x4fb6c9db0c3ccfa43a9818f620e093a26b7ba35fc765b02ca1537cd4c745e6d0", + "PivotNumber": 4256000, + "PivotHash": "0xbcd98e48fc103281613092e4f438443c57d83e48659ce6c49c463c38e3c0b95b", "PivotTotalDifficulty": "17000018015853232", "FastSyncCatchUpHeightDelta": "10000000000" }, diff --git a/src/Nethermind/Nethermind.Runner/configs/volta.cfg b/src/Nethermind/Nethermind.Runner/configs/volta.cfg index 5623831792b..2462c7397d8 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": 24530000, - "PivotHash": "0xe31db2f7a7c9b3d1771514bad0dfd97561045aff2dd6264ec5b26c70888cf2cd", - "PivotTotalDifficulty": "8347126460570620508756579120301274226652563516", + "PivotNumber": 24630000, + "PivotHash": "0x6656a988ec331a0140c2347e71d6f17ecad3ee804de6fa9f9ec36ec6432af7eb", + "PivotTotalDifficulty": "8381154697262714355102916581044451047797938883", "FastBlocks": true, "UseGethLimitsInFastBlocks": false, "FastSyncCatchUpHeightDelta": 10000000000 From 5a2f2ff5919a757a0aac96b73a69cb8316083ad1 Mon Sep 17 00:00:00 2001 From: Lautaro Emanuel <31224949+emlautarom1@users.noreply.github.com> Date: Mon, 11 Sep 2023 10:37:07 -0300 Subject: [PATCH 03/50] Remove `Data` field from serialized Transactions (#6079) * Remove 'Data' when serializing - Support during deserialization for compatibility * Fix test 'NewPendingTransactionsSubscription_on_NewPending_with_includeTransactions_param' * Fix test 'Eth_get_block_by_hash_with_tx' * Fix test 'Eth_get_block_by_number' * Fix test 'Eth_get_block_by_number_with_recovering_sender_from_receipts' * Fix test 'Eth_get_transaction_by_block_hash_and_index' * Fix test 'Eth_get_transaction_by_block_number_and_index' * Fix test 'Eth_get_transaction_by_hash' * Fix test 'Eth_pending_transactions' * Fix test 'Eth_pending_transactions_1559_tx' * Fix test 'Eth_pending_transactions_2930_tx' --- .../Modules/Eth/EthRpcModuleTests.EthCall.cs | 2 +- .../Modules/Eth/EthRpcModuleTests.cs | 20 +++++++++---------- .../Modules/SubscribeModuleTests.cs | 2 +- .../Data/TransactionForRpc.cs | 11 +++++++--- 4 files changed, 20 insertions(+), 15 deletions(-) diff --git a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/EthRpcModuleTests.EthCall.cs b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/EthRpcModuleTests.EthCall.cs index 97e2ab7fad1..30aba351ebd 100644 --- a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/EthRpcModuleTests.EthCall.cs +++ b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/EthRpcModuleTests.EthCall.cs @@ -88,7 +88,7 @@ public async Task Eth_call_no_recipient_should_work_as_init() using Context ctx = await Context.Create(); TransactionForRpc transaction = new(Keccak.Zero, 1L, 1, new Transaction()); transaction.From = TestItem.AddressA; - transaction.Data = new byte[] { 1, 2, 3 }; + transaction.Input = new byte[] { 1, 2, 3 }; string serialized = await ctx.Test.TestEthRpc("eth_call", ctx.Test.JsonSerializer.Serialize(transaction), "latest"); diff --git a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/EthRpcModuleTests.cs b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/EthRpcModuleTests.cs index 8e0f69905ce..1d1957356b5 100644 --- a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/EthRpcModuleTests.cs +++ b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/EthRpcModuleTests.cs @@ -74,7 +74,7 @@ public async Task Eth_get_transaction_by_block_hash_and_index() { using Context ctx = await Context.Create(); string serialized = await ctx.Test.TestEthRpc("eth_getTransactionByBlockHashAndIndex", ctx.Test.BlockTree.FindHeadBlock()!.Hash!.ToString(), "1"); - Assert.That(serialized, Is.EqualTo("{\"jsonrpc\":\"2.0\",\"result\":{\"hash\":\"0x7126cf20a0ad8bd51634837d9049615c34c1bff5e1a54e5663f7e23109bff48b\",\"nonce\":\"0x2\",\"blockHash\":\"0x29f141925d2d8e357ae5b6040c97aa12d7ac6dfcbe2b20e7b616d8907ac8e1f3\",\"blockNumber\":\"0x3\",\"transactionIndex\":\"0x1\",\"from\":\"0xb7705ae4c6f81b66cdb323c65f4e8133690fc099\",\"to\":\"0x942921b14f1b1c385cd7e0cc2ef7abe5598c8358\",\"value\":\"0x1\",\"gasPrice\":\"0x1\",\"gas\":\"0x5208\",\"data\":\"0x\",\"input\":\"0x\",\"type\":\"0x0\",\"v\":\"0x25\",\"s\":\"0x575361bb330bf38b9a89dd8279d42a20d34edeaeede9739a7c2bdcbe3242d7bb\",\"r\":\"0xe7c5ff3cba254c4fe8f9f12c3f202150bb9a0aebeee349ff2f4acb23585f56bd\"},\"id\":67}"), serialized.Replace("\"", "\\\"")); + Assert.That(serialized, Is.EqualTo("{\"jsonrpc\":\"2.0\",\"result\":{\"hash\":\"0x7126cf20a0ad8bd51634837d9049615c34c1bff5e1a54e5663f7e23109bff48b\",\"nonce\":\"0x2\",\"blockHash\":\"0x29f141925d2d8e357ae5b6040c97aa12d7ac6dfcbe2b20e7b616d8907ac8e1f3\",\"blockNumber\":\"0x3\",\"transactionIndex\":\"0x1\",\"from\":\"0xb7705ae4c6f81b66cdb323c65f4e8133690fc099\",\"to\":\"0x942921b14f1b1c385cd7e0cc2ef7abe5598c8358\",\"value\":\"0x1\",\"gasPrice\":\"0x1\",\"gas\":\"0x5208\",\"input\":\"0x\",\"type\":\"0x0\",\"v\":\"0x25\",\"s\":\"0x575361bb330bf38b9a89dd8279d42a20d34edeaeede9739a7c2bdcbe3242d7bb\",\"r\":\"0xe7c5ff3cba254c4fe8f9f12c3f202150bb9a0aebeee349ff2f4acb23585f56bd\"},\"id\":67}"), serialized.Replace("\"", "\\\"")); } [Test] @@ -82,7 +82,7 @@ public async Task Eth_get_transaction_by_hash() { using Context ctx = await Context.Create(); string serialized = await ctx.Test.TestEthRpc("eth_getTransactionByHash", ctx.Test.BlockTree.FindHeadBlock()!.Transactions.Last().Hash!.ToString()); - Assert.That(serialized, Is.EqualTo("{\"jsonrpc\":\"2.0\",\"result\":{\"hash\":\"0x7126cf20a0ad8bd51634837d9049615c34c1bff5e1a54e5663f7e23109bff48b\",\"nonce\":\"0x2\",\"blockHash\":\"0x29f141925d2d8e357ae5b6040c97aa12d7ac6dfcbe2b20e7b616d8907ac8e1f3\",\"blockNumber\":\"0x3\",\"transactionIndex\":\"0x1\",\"from\":\"0xb7705ae4c6f81b66cdb323c65f4e8133690fc099\",\"to\":\"0x942921b14f1b1c385cd7e0cc2ef7abe5598c8358\",\"value\":\"0x1\",\"gasPrice\":\"0x1\",\"gas\":\"0x5208\",\"data\":\"0x\",\"input\":\"0x\",\"type\":\"0x0\",\"v\":\"0x25\",\"s\":\"0x575361bb330bf38b9a89dd8279d42a20d34edeaeede9739a7c2bdcbe3242d7bb\",\"r\":\"0xe7c5ff3cba254c4fe8f9f12c3f202150bb9a0aebeee349ff2f4acb23585f56bd\"},\"id\":67}"), serialized.Replace("\"", "\\\"")); + Assert.That(serialized, Is.EqualTo("{\"jsonrpc\":\"2.0\",\"result\":{\"hash\":\"0x7126cf20a0ad8bd51634837d9049615c34c1bff5e1a54e5663f7e23109bff48b\",\"nonce\":\"0x2\",\"blockHash\":\"0x29f141925d2d8e357ae5b6040c97aa12d7ac6dfcbe2b20e7b616d8907ac8e1f3\",\"blockNumber\":\"0x3\",\"transactionIndex\":\"0x1\",\"from\":\"0xb7705ae4c6f81b66cdb323c65f4e8133690fc099\",\"to\":\"0x942921b14f1b1c385cd7e0cc2ef7abe5598c8358\",\"value\":\"0x1\",\"gasPrice\":\"0x1\",\"gas\":\"0x5208\",\"input\":\"0x\",\"type\":\"0x0\",\"v\":\"0x25\",\"s\":\"0x575361bb330bf38b9a89dd8279d42a20d34edeaeede9739a7c2bdcbe3242d7bb\",\"r\":\"0xe7c5ff3cba254c4fe8f9f12c3f202150bb9a0aebeee349ff2f4acb23585f56bd\"},\"id\":67}"), serialized.Replace("\"", "\\\"")); } [Test] @@ -99,7 +99,7 @@ public async Task Eth_pending_transactions() using Context ctx = await Context.Create(); ctx.Test.AddTransactions(Build.A.Transaction.SignedAndResolved(TestItem.PrivateKeyD).TestObject); string serialized = await ctx.Test.TestEthRpc("eth_pendingTransactions"); - Assert.That(serialized, Is.EqualTo("{\"jsonrpc\":\"2.0\",\"result\":[{\"hash\":\"0x190d9a78dbc61b1856162ab909976a1b28ba4a41ee041341576ea69686cd3b29\",\"nonce\":\"0x0\",\"blockHash\":\"0x0000000000000000000000000000000000000000000000000000000000000000\",\"blockNumber\":null,\"transactionIndex\":null,\"from\":\"0x475674cb523a0a2736b7f7534390288fce16982c\",\"to\":\"0x0000000000000000000000000000000000000000\",\"value\":\"0x1\",\"gasPrice\":\"0x1\",\"gas\":\"0x5208\",\"data\":\"0x\",\"input\":\"0x\",\"type\":\"0x0\",\"v\":\"0x26\",\"s\":\"0x2d04e55699fa32e6b65a22189f7571f5030d636d7d44a8b53fe016a2c3ecde24\",\"r\":\"0xda3978c3a1430bd902cf5bbca73c5a1eca019b3f003c95ee16657fd0bb89534c\"}],\"id\":67}"), serialized.Replace("\"", "\\\"")); + Assert.That(serialized, Is.EqualTo("{\"jsonrpc\":\"2.0\",\"result\":[{\"hash\":\"0x190d9a78dbc61b1856162ab909976a1b28ba4a41ee041341576ea69686cd3b29\",\"nonce\":\"0x0\",\"blockHash\":\"0x0000000000000000000000000000000000000000000000000000000000000000\",\"blockNumber\":null,\"transactionIndex\":null,\"from\":\"0x475674cb523a0a2736b7f7534390288fce16982c\",\"to\":\"0x0000000000000000000000000000000000000000\",\"value\":\"0x1\",\"gasPrice\":\"0x1\",\"gas\":\"0x5208\",\"input\":\"0x\",\"type\":\"0x0\",\"v\":\"0x26\",\"s\":\"0x2d04e55699fa32e6b65a22189f7571f5030d636d7d44a8b53fe016a2c3ecde24\",\"r\":\"0xda3978c3a1430bd902cf5bbca73c5a1eca019b3f003c95ee16657fd0bb89534c\"}],\"id\":67}"), serialized.Replace("\"", "\\\"")); } [Test] @@ -107,7 +107,7 @@ public async Task Eth_pending_transactions_1559_tx() { using Context ctx = await Context.CreateWithLondonEnabled(); ctx.Test.AddTransactions(Build.A.Transaction.WithMaxPriorityFeePerGas(6.GWei()).WithMaxFeePerGas(11.GWei()).WithType(TxType.EIP1559).SignedAndResolved(TestItem.PrivateKeyC).TestObject); - const string addedTx = "\"hash\":\"0xc668c8940b7416fe06db0dac853210d6d64fb2e9528c439c135a53106517fca6\",\"nonce\":\"0x0\",\"blockHash\":\"0x0000000000000000000000000000000000000000000000000000000000000000\",\"blockNumber\":null,\"transactionIndex\":null,\"from\":\"0x76e68a8696537e4141926f3e528733af9e237d69\",\"to\":\"0x0000000000000000000000000000000000000000\",\"value\":\"0x1\",\"gasPrice\":\"0x28fa6ae00\",\"maxPriorityFeePerGas\":\"0x165a0bc00\",\"maxFeePerGas\":\"0x28fa6ae00\",\"gas\":\"0x5208\",\"data\":\"0x\",\"input\":\"0x\",\"chainId\":\"0x1\",\"type\":\"0x2\",\"accessList\":[],\"v\":\"0x1\",\"s\":\"0x24e1404423c47d5c5fd9e0b6205811eaa3052f9acdb91a9c08821c2b7a0db1a4\",\"r\":\"0x408e34747109a32b924c61acb879d628505dbd0dcab15a3b1e3a4cfd589b65d2\",\"yParity\":\"0x1\""; + const string addedTx = "\"hash\":\"0xc668c8940b7416fe06db0dac853210d6d64fb2e9528c439c135a53106517fca6\",\"nonce\":\"0x0\",\"blockHash\":\"0x0000000000000000000000000000000000000000000000000000000000000000\",\"blockNumber\":null,\"transactionIndex\":null,\"from\":\"0x76e68a8696537e4141926f3e528733af9e237d69\",\"to\":\"0x0000000000000000000000000000000000000000\",\"value\":\"0x1\",\"gasPrice\":\"0x28fa6ae00\",\"maxPriorityFeePerGas\":\"0x165a0bc00\",\"maxFeePerGas\":\"0x28fa6ae00\",\"gas\":\"0x5208\",\"input\":\"0x\",\"chainId\":\"0x1\",\"type\":\"0x2\",\"accessList\":[],\"v\":\"0x1\",\"s\":\"0x24e1404423c47d5c5fd9e0b6205811eaa3052f9acdb91a9c08821c2b7a0db1a4\",\"r\":\"0x408e34747109a32b924c61acb879d628505dbd0dcab15a3b1e3a4cfd589b65d2\",\"yParity\":\"0x1\""; string serialized = await ctx.Test.TestEthRpc("eth_pendingTransactions"); serialized.Contains(addedTx).Should().BeTrue(); } @@ -117,7 +117,7 @@ public async Task Eth_pending_transactions_2930_tx() { using Context ctx = await Context.CreateWithLondonEnabled(); ctx.Test.AddTransactions(Build.A.Transaction.WithMaxPriorityFeePerGas(6.GWei()).WithMaxFeePerGas(11.GWei()).WithType(TxType.AccessList).SignedAndResolved(TestItem.PrivateKeyC).TestObject); - const string addedTx = "\"hash\":\"0xa296c4cf8ece2d7788e4a71125133dfd8025fc35cc5ffa3e283bc62b027cf512\",\"nonce\":\"0x0\",\"blockHash\":\"0x0000000000000000000000000000000000000000000000000000000000000000\",\"blockNumber\":null,\"transactionIndex\":null,\"from\":\"0x76e68a8696537e4141926f3e528733af9e237d69\",\"to\":\"0x0000000000000000000000000000000000000000\",\"value\":\"0x1\",\"gasPrice\":\"0x165a0bc00\",\"gas\":\"0x5208\",\"data\":\"0x\",\"input\":\"0x\",\"chainId\":\"0x1\",\"type\":\"0x1\",\"accessList\":[],\"v\":\"0x0\",\"s\":\"0x2b4cbea82cc417cdf510fb5fb0613a2881f2b8a76cd6cce6a5f77872f5124b44\",\"r\":\"0x925ede2e48031b060e6c4a0c7184eb58e37a19b41a3ba15a2d9767c0c41f6d76\",\"yParity\":\"0x0\""; + const string addedTx = "\"hash\":\"0xa296c4cf8ece2d7788e4a71125133dfd8025fc35cc5ffa3e283bc62b027cf512\",\"nonce\":\"0x0\",\"blockHash\":\"0x0000000000000000000000000000000000000000000000000000000000000000\",\"blockNumber\":null,\"transactionIndex\":null,\"from\":\"0x76e68a8696537e4141926f3e528733af9e237d69\",\"to\":\"0x0000000000000000000000000000000000000000\",\"value\":\"0x1\",\"gasPrice\":\"0x165a0bc00\",\"gas\":\"0x5208\",\"input\":\"0x\",\"chainId\":\"0x1\",\"type\":\"0x1\",\"accessList\":[],\"v\":\"0x0\",\"s\":\"0x2b4cbea82cc417cdf510fb5fb0613a2881f2b8a76cd6cce6a5f77872f5124b44\",\"r\":\"0x925ede2e48031b060e6c4a0c7184eb58e37a19b41a3ba15a2d9767c0c41f6d76\",\"yParity\":\"0x0\""; string serialized = await ctx.Test.TestEthRpc("eth_pendingTransactions"); serialized.Contains(addedTx).Should().BeTrue(); } @@ -127,7 +127,7 @@ public async Task Eth_get_transaction_by_block_number_and_index() { using Context ctx = await Context.Create(); string serialized = await ctx.Test.TestEthRpc("eth_getTransactionByBlockNumberAndIndex", ctx.Test.BlockTree.FindHeadBlock()!.Number.ToString(), "1"); - Assert.That(serialized, Is.EqualTo("{\"jsonrpc\":\"2.0\",\"result\":{\"hash\":\"0x7126cf20a0ad8bd51634837d9049615c34c1bff5e1a54e5663f7e23109bff48b\",\"nonce\":\"0x2\",\"blockHash\":\"0x29f141925d2d8e357ae5b6040c97aa12d7ac6dfcbe2b20e7b616d8907ac8e1f3\",\"blockNumber\":\"0x3\",\"transactionIndex\":\"0x1\",\"from\":\"0xb7705ae4c6f81b66cdb323c65f4e8133690fc099\",\"to\":\"0x942921b14f1b1c385cd7e0cc2ef7abe5598c8358\",\"value\":\"0x1\",\"gasPrice\":\"0x1\",\"gas\":\"0x5208\",\"data\":\"0x\",\"input\":\"0x\",\"type\":\"0x0\",\"v\":\"0x25\",\"s\":\"0x575361bb330bf38b9a89dd8279d42a20d34edeaeede9739a7c2bdcbe3242d7bb\",\"r\":\"0xe7c5ff3cba254c4fe8f9f12c3f202150bb9a0aebeee349ff2f4acb23585f56bd\"},\"id\":67}"), serialized.Replace("\"", "\\\"")); + Assert.That(serialized, Is.EqualTo("{\"jsonrpc\":\"2.0\",\"result\":{\"hash\":\"0x7126cf20a0ad8bd51634837d9049615c34c1bff5e1a54e5663f7e23109bff48b\",\"nonce\":\"0x2\",\"blockHash\":\"0x29f141925d2d8e357ae5b6040c97aa12d7ac6dfcbe2b20e7b616d8907ac8e1f3\",\"blockNumber\":\"0x3\",\"transactionIndex\":\"0x1\",\"from\":\"0xb7705ae4c6f81b66cdb323c65f4e8133690fc099\",\"to\":\"0x942921b14f1b1c385cd7e0cc2ef7abe5598c8358\",\"value\":\"0x1\",\"gasPrice\":\"0x1\",\"gas\":\"0x5208\",\"input\":\"0x\",\"type\":\"0x0\",\"v\":\"0x25\",\"s\":\"0x575361bb330bf38b9a89dd8279d42a20d34edeaeede9739a7c2bdcbe3242d7bb\",\"r\":\"0xe7c5ff3cba254c4fe8f9f12c3f202150bb9a0aebeee349ff2f4acb23585f56bd\"},\"id\":67}"), serialized.Replace("\"", "\\\"")); } [TestCase(false, "{\"jsonrpc\":\"2.0\",\"result\":{\"author\":\"0x0000000000000000000000000000000000000000\",\"difficulty\":\"0xf4240\",\"extraData\":\"0x010203\",\"gasLimit\":\"0x3d0900\",\"gasUsed\":\"0x0\",\"hash\":\"0xa2a9f03b9493046696099d27b2612b99497aa1f392ec966716ab393c715a5bb6\",\"logsBloom\":\"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\",\"miner\":\"0x0000000000000000000000000000000000000000\",\"mixHash\":\"0x2ba5557a4c62a513c7e56d1bf13373e0da6bec016755483e91589fe1c6d212e2\",\"nonce\":\"0x00000000000003e8\",\"number\":\"0x0\",\"parentHash\":\"0xff483e972a04a9a62bb4b7d04ae403c615604e4090521ecc5bb7af67f71be09c\",\"receiptsRoot\":\"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421\",\"sha3Uncles\":\"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347\",\"size\":\"0x201\",\"stateRoot\":\"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421\",\"totalDifficulty\":\"0x0\",\"timestamp\":\"0xf4240\",\"transactions\":[],\"transactionsRoot\":\"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421\",\"uncles\":[]},\"id\":67}")] @@ -624,7 +624,7 @@ public async Task Eth_get_block_by_hash_null() } [TestCase("0x71eac5e72c3b64431c246173352a8c625c8434d944eb5f3f58204fec3ec36b54", false, "{\"jsonrpc\":\"2.0\",\"result\":{\"author\":\"0x475674cb523a0a2736b7f7534390288fce16982c\",\"difficulty\":\"0x1\",\"extraData\":\"0x4e65746865726d696e64\",\"gasLimit\":\"0x3d0900\",\"gasUsed\":\"0xa410\",\"hash\":\"0x29f141925d2d8e357ae5b6040c97aa12d7ac6dfcbe2b20e7b616d8907ac8e1f3\",\"logsBloom\":\"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\",\"miner\":\"0x475674cb523a0a2736b7f7534390288fce16982c\",\"mixHash\":\"0x0000000000000000000000000000000000000000000000000000000000000000\",\"nonce\":\"0x0000000000000000\",\"number\":\"0x3\",\"parentHash\":\"0x49e7d7466be0927347ff2f654c014a768b5a5fcd8c483635210466dd0d6d204c\",\"receiptsRoot\":\"0xd95b673818fa493deec414e01e610d97ee287c9421c8eff4102b1647c1a184e4\",\"sha3Uncles\":\"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347\",\"size\":\"0x2cb\",\"stateRoot\":\"0x4e786afc8bed76b7299973ca70022b367cbb94c14ec30e9e7273b31b6b968de9\",\"totalDifficulty\":\"0xf4243\",\"timestamp\":\"0x5e47e919\",\"transactions\":[\"0x681c2b6f99e37fd6fe6046db8b51ec3460d699cacd6a376143fd5842ac50621f\",\"0x7126cf20a0ad8bd51634837d9049615c34c1bff5e1a54e5663f7e23109bff48b\"],\"transactionsRoot\":\"0x2e6e6deb19d24bd48eda6071ab38b1bae64c15ef1998c96f0d153711d3a3efc7\",\"uncles\":[]},\"id\":67}")] - [TestCase("0x71eac5e72c3b64431c246173352a8c625c8434d944eb5f3f58204fec3ec36b54", true, "{\"jsonrpc\":\"2.0\",\"result\":{\"author\":\"0x475674cb523a0a2736b7f7534390288fce16982c\",\"difficulty\":\"0x1\",\"extraData\":\"0x4e65746865726d696e64\",\"gasLimit\":\"0x3d0900\",\"gasUsed\":\"0xa410\",\"hash\":\"0x29f141925d2d8e357ae5b6040c97aa12d7ac6dfcbe2b20e7b616d8907ac8e1f3\",\"logsBloom\":\"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\",\"miner\":\"0x475674cb523a0a2736b7f7534390288fce16982c\",\"mixHash\":\"0x0000000000000000000000000000000000000000000000000000000000000000\",\"nonce\":\"0x0000000000000000\",\"number\":\"0x3\",\"parentHash\":\"0x49e7d7466be0927347ff2f654c014a768b5a5fcd8c483635210466dd0d6d204c\",\"receiptsRoot\":\"0xd95b673818fa493deec414e01e610d97ee287c9421c8eff4102b1647c1a184e4\",\"sha3Uncles\":\"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347\",\"size\":\"0x2cb\",\"stateRoot\":\"0x4e786afc8bed76b7299973ca70022b367cbb94c14ec30e9e7273b31b6b968de9\",\"totalDifficulty\":\"0xf4243\",\"timestamp\":\"0x5e47e919\",\"transactions\":[{\"hash\":\"0x681c2b6f99e37fd6fe6046db8b51ec3460d699cacd6a376143fd5842ac50621f\",\"nonce\":\"0x1\",\"blockHash\":\"0x29f141925d2d8e357ae5b6040c97aa12d7ac6dfcbe2b20e7b616d8907ac8e1f3\",\"blockNumber\":\"0x3\",\"transactionIndex\":\"0x0\",\"from\":\"0xb7705ae4c6f81b66cdb323c65f4e8133690fc099\",\"to\":\"0x942921b14f1b1c385cd7e0cc2ef7abe5598c8358\",\"value\":\"0x1\",\"gasPrice\":\"0x1\",\"gas\":\"0x5208\",\"data\":\"0x\",\"input\":\"0x\",\"type\":\"0x0\",\"v\":\"0x25\",\"s\":\"0x575361bb330bf38b9a89dd8279d42a20d34edeaeede9739a7c2bdcbe3242d7bb\",\"r\":\"0xe7c5ff3cba254c4fe8f9f12c3f202150bb9a0aebeee349ff2f4acb23585f56bd\"},{\"hash\":\"0x7126cf20a0ad8bd51634837d9049615c34c1bff5e1a54e5663f7e23109bff48b\",\"nonce\":\"0x2\",\"blockHash\":\"0x29f141925d2d8e357ae5b6040c97aa12d7ac6dfcbe2b20e7b616d8907ac8e1f3\",\"blockNumber\":\"0x3\",\"transactionIndex\":\"0x1\",\"from\":\"0xb7705ae4c6f81b66cdb323c65f4e8133690fc099\",\"to\":\"0x942921b14f1b1c385cd7e0cc2ef7abe5598c8358\",\"value\":\"0x1\",\"gasPrice\":\"0x1\",\"gas\":\"0x5208\",\"data\":\"0x\",\"input\":\"0x\",\"type\":\"0x0\",\"v\":\"0x25\",\"s\":\"0x575361bb330bf38b9a89dd8279d42a20d34edeaeede9739a7c2bdcbe3242d7bb\",\"r\":\"0xe7c5ff3cba254c4fe8f9f12c3f202150bb9a0aebeee349ff2f4acb23585f56bd\"}],\"transactionsRoot\":\"0x2e6e6deb19d24bd48eda6071ab38b1bae64c15ef1998c96f0d153711d3a3efc7\",\"uncles\":[]},\"id\":67}")] + [TestCase("0x71eac5e72c3b64431c246173352a8c625c8434d944eb5f3f58204fec3ec36b54", true, "{\"jsonrpc\":\"2.0\",\"result\":{\"author\":\"0x475674cb523a0a2736b7f7534390288fce16982c\",\"difficulty\":\"0x1\",\"extraData\":\"0x4e65746865726d696e64\",\"gasLimit\":\"0x3d0900\",\"gasUsed\":\"0xa410\",\"hash\":\"0x29f141925d2d8e357ae5b6040c97aa12d7ac6dfcbe2b20e7b616d8907ac8e1f3\",\"logsBloom\":\"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\",\"miner\":\"0x475674cb523a0a2736b7f7534390288fce16982c\",\"mixHash\":\"0x0000000000000000000000000000000000000000000000000000000000000000\",\"nonce\":\"0x0000000000000000\",\"number\":\"0x3\",\"parentHash\":\"0x49e7d7466be0927347ff2f654c014a768b5a5fcd8c483635210466dd0d6d204c\",\"receiptsRoot\":\"0xd95b673818fa493deec414e01e610d97ee287c9421c8eff4102b1647c1a184e4\",\"sha3Uncles\":\"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347\",\"size\":\"0x2cb\",\"stateRoot\":\"0x4e786afc8bed76b7299973ca70022b367cbb94c14ec30e9e7273b31b6b968de9\",\"totalDifficulty\":\"0xf4243\",\"timestamp\":\"0x5e47e919\",\"transactions\":[{\"hash\":\"0x681c2b6f99e37fd6fe6046db8b51ec3460d699cacd6a376143fd5842ac50621f\",\"nonce\":\"0x1\",\"blockHash\":\"0x29f141925d2d8e357ae5b6040c97aa12d7ac6dfcbe2b20e7b616d8907ac8e1f3\",\"blockNumber\":\"0x3\",\"transactionIndex\":\"0x0\",\"from\":\"0xb7705ae4c6f81b66cdb323c65f4e8133690fc099\",\"to\":\"0x942921b14f1b1c385cd7e0cc2ef7abe5598c8358\",\"value\":\"0x1\",\"gasPrice\":\"0x1\",\"gas\":\"0x5208\",\"input\":\"0x\",\"type\":\"0x0\",\"v\":\"0x25\",\"s\":\"0x575361bb330bf38b9a89dd8279d42a20d34edeaeede9739a7c2bdcbe3242d7bb\",\"r\":\"0xe7c5ff3cba254c4fe8f9f12c3f202150bb9a0aebeee349ff2f4acb23585f56bd\"},{\"hash\":\"0x7126cf20a0ad8bd51634837d9049615c34c1bff5e1a54e5663f7e23109bff48b\",\"nonce\":\"0x2\",\"blockHash\":\"0x29f141925d2d8e357ae5b6040c97aa12d7ac6dfcbe2b20e7b616d8907ac8e1f3\",\"blockNumber\":\"0x3\",\"transactionIndex\":\"0x1\",\"from\":\"0xb7705ae4c6f81b66cdb323c65f4e8133690fc099\",\"to\":\"0x942921b14f1b1c385cd7e0cc2ef7abe5598c8358\",\"value\":\"0x1\",\"gasPrice\":\"0x1\",\"gas\":\"0x5208\",\"input\":\"0x\",\"type\":\"0x0\",\"v\":\"0x25\",\"s\":\"0x575361bb330bf38b9a89dd8279d42a20d34edeaeede9739a7c2bdcbe3242d7bb\",\"r\":\"0xe7c5ff3cba254c4fe8f9f12c3f202150bb9a0aebeee349ff2f4acb23585f56bd\"}],\"transactionsRoot\":\"0x2e6e6deb19d24bd48eda6071ab38b1bae64c15ef1998c96f0d153711d3a3efc7\",\"uncles\":[]},\"id\":67}")] public async Task Eth_get_block_by_hash_with_tx(string blockParameter, bool withTxData, string expectedResult) { using Context ctx = await Context.Create(); @@ -633,8 +633,8 @@ public async Task Eth_get_block_by_hash_with_tx(string blockParameter, bool with } [TestCase(false, "earliest", "{\"jsonrpc\":\"2.0\",\"result\":{\"author\":\"0x0000000000000000000000000000000000000000\",\"difficulty\":\"0xf4240\",\"extraData\":\"0x010203\",\"gasLimit\":\"0x3d0900\",\"gasUsed\":\"0x0\",\"hash\":\"0x2167088a0f0de66028d2b728235af6d467108c1750c3e11a8f6e6cd60fddb0e4\",\"logsBloom\":\"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\",\"miner\":\"0x0000000000000000000000000000000000000000\",\"mixHash\":\"0x0000000000000000000000000000000000000000000000000000000000000000\",\"nonce\":\"0x00000000000003e8\",\"number\":\"0x0\",\"parentHash\":\"0x0000000000000000000000000000000000000000000000000000000000000000\",\"receiptsRoot\":\"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421\",\"sha3Uncles\":\"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347\",\"size\":\"0x201\",\"stateRoot\":\"0x1ef7300d8961797263939a3d29bbba4ccf1702fabf02d8ad7a20b454edb6fd2f\",\"totalDifficulty\":\"0xf4240\",\"timestamp\":\"0xf4240\",\"transactions\":[],\"transactionsRoot\":\"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421\",\"uncles\":[]},\"id\":67}")] - [TestCase(false, "latest", "{\"jsonrpc\":\"2.0\",\"result\":{\"author\":\"0x475674cb523a0a2736b7f7534390288fce16982c\",\"difficulty\":\"0x1\",\"extraData\":\"0x4e65746865726d696e64\",\"gasLimit\":\"0x3d0900\",\"gasUsed\":\"0xa410\",\"hash\":\"0x29f141925d2d8e357ae5b6040c97aa12d7ac6dfcbe2b20e7b616d8907ac8e1f3\",\"logsBloom\":\"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\",\"miner\":\"0x475674cb523a0a2736b7f7534390288fce16982c\",\"mixHash\":\"0x0000000000000000000000000000000000000000000000000000000000000000\",\"nonce\":\"0x0000000000000000\",\"number\":\"0x3\",\"parentHash\":\"0x49e7d7466be0927347ff2f654c014a768b5a5fcd8c483635210466dd0d6d204c\",\"receiptsRoot\":\"0xd95b673818fa493deec414e01e610d97ee287c9421c8eff4102b1647c1a184e4\",\"sha3Uncles\":\"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347\",\"size\":\"0x2cb\",\"stateRoot\":\"0x4e786afc8bed76b7299973ca70022b367cbb94c14ec30e9e7273b31b6b968de9\",\"totalDifficulty\":\"0xf4243\",\"timestamp\":\"0x5e47e919\",\"transactions\":[{\"hash\":\"0x681c2b6f99e37fd6fe6046db8b51ec3460d699cacd6a376143fd5842ac50621f\",\"nonce\":\"0x1\",\"blockHash\":\"0x29f141925d2d8e357ae5b6040c97aa12d7ac6dfcbe2b20e7b616d8907ac8e1f3\",\"blockNumber\":\"0x3\",\"transactionIndex\":\"0x0\",\"from\":\"0xb7705ae4c6f81b66cdb323c65f4e8133690fc099\",\"to\":\"0x942921b14f1b1c385cd7e0cc2ef7abe5598c8358\",\"value\":\"0x1\",\"gasPrice\":\"0x1\",\"gas\":\"0x5208\",\"data\":\"0x\",\"input\":\"0x\",\"type\":\"0x0\",\"v\":\"0x25\",\"s\":\"0x575361bb330bf38b9a89dd8279d42a20d34edeaeede9739a7c2bdcbe3242d7bb\",\"r\":\"0xe7c5ff3cba254c4fe8f9f12c3f202150bb9a0aebeee349ff2f4acb23585f56bd\"},{\"hash\":\"0x7126cf20a0ad8bd51634837d9049615c34c1bff5e1a54e5663f7e23109bff48b\",\"nonce\":\"0x2\",\"blockHash\":\"0x29f141925d2d8e357ae5b6040c97aa12d7ac6dfcbe2b20e7b616d8907ac8e1f3\",\"blockNumber\":\"0x3\",\"transactionIndex\":\"0x1\",\"from\":\"0xb7705ae4c6f81b66cdb323c65f4e8133690fc099\",\"to\":\"0x942921b14f1b1c385cd7e0cc2ef7abe5598c8358\",\"value\":\"0x1\",\"gasPrice\":\"0x1\",\"gas\":\"0x5208\",\"data\":\"0x\",\"input\":\"0x\",\"type\":\"0x0\",\"v\":\"0x25\",\"s\":\"0x575361bb330bf38b9a89dd8279d42a20d34edeaeede9739a7c2bdcbe3242d7bb\",\"r\":\"0xe7c5ff3cba254c4fe8f9f12c3f202150bb9a0aebeee349ff2f4acb23585f56bd\"}],\"transactionsRoot\":\"0x2e6e6deb19d24bd48eda6071ab38b1bae64c15ef1998c96f0d153711d3a3efc7\",\"uncles\":[]},\"id\":67}")] - [TestCase(false, "pending", "{\"jsonrpc\":\"2.0\",\"result\":{\"author\":\"0x475674cb523a0a2736b7f7534390288fce16982c\",\"difficulty\":\"0x1\",\"extraData\":\"0x4e65746865726d696e64\",\"gasLimit\":\"0x3d0900\",\"gasUsed\":\"0xa410\",\"hash\":\"0x29f141925d2d8e357ae5b6040c97aa12d7ac6dfcbe2b20e7b616d8907ac8e1f3\",\"logsBloom\":\"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\",\"miner\":\"0x475674cb523a0a2736b7f7534390288fce16982c\",\"mixHash\":\"0x0000000000000000000000000000000000000000000000000000000000000000\",\"nonce\":\"0x0000000000000000\",\"number\":\"0x3\",\"parentHash\":\"0x49e7d7466be0927347ff2f654c014a768b5a5fcd8c483635210466dd0d6d204c\",\"receiptsRoot\":\"0xd95b673818fa493deec414e01e610d97ee287c9421c8eff4102b1647c1a184e4\",\"sha3Uncles\":\"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347\",\"size\":\"0x2cb\",\"stateRoot\":\"0x4e786afc8bed76b7299973ca70022b367cbb94c14ec30e9e7273b31b6b968de9\",\"totalDifficulty\":\"0xf4243\",\"timestamp\":\"0x5e47e919\",\"transactions\":[{\"hash\":\"0x681c2b6f99e37fd6fe6046db8b51ec3460d699cacd6a376143fd5842ac50621f\",\"nonce\":\"0x1\",\"blockHash\":\"0x29f141925d2d8e357ae5b6040c97aa12d7ac6dfcbe2b20e7b616d8907ac8e1f3\",\"blockNumber\":\"0x3\",\"transactionIndex\":\"0x0\",\"from\":\"0xb7705ae4c6f81b66cdb323c65f4e8133690fc099\",\"to\":\"0x942921b14f1b1c385cd7e0cc2ef7abe5598c8358\",\"value\":\"0x1\",\"gasPrice\":\"0x1\",\"gas\":\"0x5208\",\"data\":\"0x\",\"input\":\"0x\",\"type\":\"0x0\",\"v\":\"0x25\",\"s\":\"0x575361bb330bf38b9a89dd8279d42a20d34edeaeede9739a7c2bdcbe3242d7bb\",\"r\":\"0xe7c5ff3cba254c4fe8f9f12c3f202150bb9a0aebeee349ff2f4acb23585f56bd\"},{\"hash\":\"0x7126cf20a0ad8bd51634837d9049615c34c1bff5e1a54e5663f7e23109bff48b\",\"nonce\":\"0x2\",\"blockHash\":\"0x29f141925d2d8e357ae5b6040c97aa12d7ac6dfcbe2b20e7b616d8907ac8e1f3\",\"blockNumber\":\"0x3\",\"transactionIndex\":\"0x1\",\"from\":\"0xb7705ae4c6f81b66cdb323c65f4e8133690fc099\",\"to\":\"0x942921b14f1b1c385cd7e0cc2ef7abe5598c8358\",\"value\":\"0x1\",\"gasPrice\":\"0x1\",\"gas\":\"0x5208\",\"data\":\"0x\",\"input\":\"0x\",\"type\":\"0x0\",\"v\":\"0x25\",\"s\":\"0x575361bb330bf38b9a89dd8279d42a20d34edeaeede9739a7c2bdcbe3242d7bb\",\"r\":\"0xe7c5ff3cba254c4fe8f9f12c3f202150bb9a0aebeee349ff2f4acb23585f56bd\"}],\"transactionsRoot\":\"0x2e6e6deb19d24bd48eda6071ab38b1bae64c15ef1998c96f0d153711d3a3efc7\",\"uncles\":[]},\"id\":67}")] + [TestCase(false, "latest", "{\"jsonrpc\":\"2.0\",\"result\":{\"author\":\"0x475674cb523a0a2736b7f7534390288fce16982c\",\"difficulty\":\"0x1\",\"extraData\":\"0x4e65746865726d696e64\",\"gasLimit\":\"0x3d0900\",\"gasUsed\":\"0xa410\",\"hash\":\"0x29f141925d2d8e357ae5b6040c97aa12d7ac6dfcbe2b20e7b616d8907ac8e1f3\",\"logsBloom\":\"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\",\"miner\":\"0x475674cb523a0a2736b7f7534390288fce16982c\",\"mixHash\":\"0x0000000000000000000000000000000000000000000000000000000000000000\",\"nonce\":\"0x0000000000000000\",\"number\":\"0x3\",\"parentHash\":\"0x49e7d7466be0927347ff2f654c014a768b5a5fcd8c483635210466dd0d6d204c\",\"receiptsRoot\":\"0xd95b673818fa493deec414e01e610d97ee287c9421c8eff4102b1647c1a184e4\",\"sha3Uncles\":\"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347\",\"size\":\"0x2cb\",\"stateRoot\":\"0x4e786afc8bed76b7299973ca70022b367cbb94c14ec30e9e7273b31b6b968de9\",\"totalDifficulty\":\"0xf4243\",\"timestamp\":\"0x5e47e919\",\"transactions\":[{\"hash\":\"0x681c2b6f99e37fd6fe6046db8b51ec3460d699cacd6a376143fd5842ac50621f\",\"nonce\":\"0x1\",\"blockHash\":\"0x29f141925d2d8e357ae5b6040c97aa12d7ac6dfcbe2b20e7b616d8907ac8e1f3\",\"blockNumber\":\"0x3\",\"transactionIndex\":\"0x0\",\"from\":\"0xb7705ae4c6f81b66cdb323c65f4e8133690fc099\",\"to\":\"0x942921b14f1b1c385cd7e0cc2ef7abe5598c8358\",\"value\":\"0x1\",\"gasPrice\":\"0x1\",\"gas\":\"0x5208\",\"input\":\"0x\",\"type\":\"0x0\",\"v\":\"0x25\",\"s\":\"0x575361bb330bf38b9a89dd8279d42a20d34edeaeede9739a7c2bdcbe3242d7bb\",\"r\":\"0xe7c5ff3cba254c4fe8f9f12c3f202150bb9a0aebeee349ff2f4acb23585f56bd\"},{\"hash\":\"0x7126cf20a0ad8bd51634837d9049615c34c1bff5e1a54e5663f7e23109bff48b\",\"nonce\":\"0x2\",\"blockHash\":\"0x29f141925d2d8e357ae5b6040c97aa12d7ac6dfcbe2b20e7b616d8907ac8e1f3\",\"blockNumber\":\"0x3\",\"transactionIndex\":\"0x1\",\"from\":\"0xb7705ae4c6f81b66cdb323c65f4e8133690fc099\",\"to\":\"0x942921b14f1b1c385cd7e0cc2ef7abe5598c8358\",\"value\":\"0x1\",\"gasPrice\":\"0x1\",\"gas\":\"0x5208\",\"input\":\"0x\",\"type\":\"0x0\",\"v\":\"0x25\",\"s\":\"0x575361bb330bf38b9a89dd8279d42a20d34edeaeede9739a7c2bdcbe3242d7bb\",\"r\":\"0xe7c5ff3cba254c4fe8f9f12c3f202150bb9a0aebeee349ff2f4acb23585f56bd\"}],\"transactionsRoot\":\"0x2e6e6deb19d24bd48eda6071ab38b1bae64c15ef1998c96f0d153711d3a3efc7\",\"uncles\":[]},\"id\":67}")] + [TestCase(false, "pending", "{\"jsonrpc\":\"2.0\",\"result\":{\"author\":\"0x475674cb523a0a2736b7f7534390288fce16982c\",\"difficulty\":\"0x1\",\"extraData\":\"0x4e65746865726d696e64\",\"gasLimit\":\"0x3d0900\",\"gasUsed\":\"0xa410\",\"hash\":\"0x29f141925d2d8e357ae5b6040c97aa12d7ac6dfcbe2b20e7b616d8907ac8e1f3\",\"logsBloom\":\"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\",\"miner\":\"0x475674cb523a0a2736b7f7534390288fce16982c\",\"mixHash\":\"0x0000000000000000000000000000000000000000000000000000000000000000\",\"nonce\":\"0x0000000000000000\",\"number\":\"0x3\",\"parentHash\":\"0x49e7d7466be0927347ff2f654c014a768b5a5fcd8c483635210466dd0d6d204c\",\"receiptsRoot\":\"0xd95b673818fa493deec414e01e610d97ee287c9421c8eff4102b1647c1a184e4\",\"sha3Uncles\":\"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347\",\"size\":\"0x2cb\",\"stateRoot\":\"0x4e786afc8bed76b7299973ca70022b367cbb94c14ec30e9e7273b31b6b968de9\",\"totalDifficulty\":\"0xf4243\",\"timestamp\":\"0x5e47e919\",\"transactions\":[{\"hash\":\"0x681c2b6f99e37fd6fe6046db8b51ec3460d699cacd6a376143fd5842ac50621f\",\"nonce\":\"0x1\",\"blockHash\":\"0x29f141925d2d8e357ae5b6040c97aa12d7ac6dfcbe2b20e7b616d8907ac8e1f3\",\"blockNumber\":\"0x3\",\"transactionIndex\":\"0x0\",\"from\":\"0xb7705ae4c6f81b66cdb323c65f4e8133690fc099\",\"to\":\"0x942921b14f1b1c385cd7e0cc2ef7abe5598c8358\",\"value\":\"0x1\",\"gasPrice\":\"0x1\",\"gas\":\"0x5208\",\"input\":\"0x\",\"type\":\"0x0\",\"v\":\"0x25\",\"s\":\"0x575361bb330bf38b9a89dd8279d42a20d34edeaeede9739a7c2bdcbe3242d7bb\",\"r\":\"0xe7c5ff3cba254c4fe8f9f12c3f202150bb9a0aebeee349ff2f4acb23585f56bd\"},{\"hash\":\"0x7126cf20a0ad8bd51634837d9049615c34c1bff5e1a54e5663f7e23109bff48b\",\"nonce\":\"0x2\",\"blockHash\":\"0x29f141925d2d8e357ae5b6040c97aa12d7ac6dfcbe2b20e7b616d8907ac8e1f3\",\"blockNumber\":\"0x3\",\"transactionIndex\":\"0x1\",\"from\":\"0xb7705ae4c6f81b66cdb323c65f4e8133690fc099\",\"to\":\"0x942921b14f1b1c385cd7e0cc2ef7abe5598c8358\",\"value\":\"0x1\",\"gasPrice\":\"0x1\",\"gas\":\"0x5208\",\"input\":\"0x\",\"type\":\"0x0\",\"v\":\"0x25\",\"s\":\"0x575361bb330bf38b9a89dd8279d42a20d34edeaeede9739a7c2bdcbe3242d7bb\",\"r\":\"0xe7c5ff3cba254c4fe8f9f12c3f202150bb9a0aebeee349ff2f4acb23585f56bd\"}],\"transactionsRoot\":\"0x2e6e6deb19d24bd48eda6071ab38b1bae64c15ef1998c96f0d153711d3a3efc7\",\"uncles\":[]},\"id\":67}")] [TestCase(false, "0x0", "{\"jsonrpc\":\"2.0\",\"result\":{\"author\":\"0x0000000000000000000000000000000000000000\",\"difficulty\":\"0xf4240\",\"extraData\":\"0x010203\",\"gasLimit\":\"0x3d0900\",\"gasUsed\":\"0x0\",\"hash\":\"0x2167088a0f0de66028d2b728235af6d467108c1750c3e11a8f6e6cd60fddb0e4\",\"logsBloom\":\"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\",\"miner\":\"0x0000000000000000000000000000000000000000\",\"mixHash\":\"0x0000000000000000000000000000000000000000000000000000000000000000\",\"nonce\":\"0x00000000000003e8\",\"number\":\"0x0\",\"parentHash\":\"0x0000000000000000000000000000000000000000000000000000000000000000\",\"receiptsRoot\":\"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421\",\"sha3Uncles\":\"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347\",\"size\":\"0x201\",\"stateRoot\":\"0x1ef7300d8961797263939a3d29bbba4ccf1702fabf02d8ad7a20b454edb6fd2f\",\"totalDifficulty\":\"0xf4240\",\"timestamp\":\"0xf4240\",\"transactions\":[],\"transactionsRoot\":\"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421\",\"uncles\":[]},\"id\":67}")] [TestCase(true, "earliest", "{\"jsonrpc\":\"2.0\",\"result\":{\"author\":\"0x0000000000000000000000000000000000000000\",\"difficulty\":\"0xf4240\",\"extraData\":\"0x010203\",\"gasLimit\":\"0x3d0900\",\"gasUsed\":\"0x0\",\"hash\":\"0x2167088a0f0de66028d2b728235af6d467108c1750c3e11a8f6e6cd60fddb0e4\",\"logsBloom\":\"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\",\"miner\":\"0x0000000000000000000000000000000000000000\",\"mixHash\":\"0x0000000000000000000000000000000000000000000000000000000000000000\",\"nonce\":\"0x00000000000003e8\",\"number\":\"0x0\",\"parentHash\":\"0x0000000000000000000000000000000000000000000000000000000000000000\",\"receiptsRoot\":\"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421\",\"sha3Uncles\":\"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347\",\"size\":\"0x201\",\"stateRoot\":\"0x1ef7300d8961797263939a3d29bbba4ccf1702fabf02d8ad7a20b454edb6fd2f\",\"totalDifficulty\":\"0xf4240\",\"timestamp\":\"0xf4240\",\"baseFeePerGas\":\"0x0\",\"transactions\":[],\"transactionsRoot\":\"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421\",\"uncles\":[]},\"id\":67}")] [TestCase(true, "latest", "{\"jsonrpc\":\"2.0\",\"result\":{\"author\":\"0x475674cb523a0a2736b7f7534390288fce16982c\",\"difficulty\":\"0x1\",\"extraData\":\"0x4e65746865726d696e64\",\"gasLimit\":\"0x7a1200\",\"gasUsed\":\"0x0\",\"hash\":\"0x16b111d85efa64c1c8e27f1e59c8ccd6bb6643b1999628ac37294c31158e2245\",\"logsBloom\":\"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\",\"miner\":\"0x475674cb523a0a2736b7f7534390288fce16982c\",\"mixHash\":\"0x0000000000000000000000000000000000000000000000000000000000000000\",\"nonce\":\"0x0000000000000000\",\"number\":\"0x3\",\"parentHash\":\"0x761cfe357802c8a2a68e37ad8325607920e72ce19b5b0d3e1ba01840f7e905ec\",\"receiptsRoot\":\"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421\",\"sha3Uncles\":\"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347\",\"size\":\"0x20b\",\"stateRoot\":\"0x1ef7300d8961797263939a3d29bbba4ccf1702fabf02d8ad7a20b454edb6fd2f\",\"totalDifficulty\":\"0xf4243\",\"timestamp\":\"0x5e47e919\",\"baseFeePerGas\":\"0x2da282a8\",\"transactions\":[],\"transactionsRoot\":\"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421\",\"uncles\":[]},\"id\":67}")] @@ -842,7 +842,7 @@ public async Task Eth_get_block_by_number_with_recovering_sender_from_receipts() ctx.Test = await TestRpcBlockchain.ForTest(SealEngineType.NethDev).WithBlockFinder(blockFinder).WithReceiptFinder(receiptFinder).Build(); string serialized = await ctx.Test.TestEthRpc("eth_getBlockByNumber", TestItem.KeccakA.ToString(), "true"); - Assert.That(serialized, Is.EqualTo("{\"jsonrpc\":\"2.0\",\"result\":{\"author\":\"0x0000000000000000000000000000000000000000\",\"difficulty\":\"0xf4240\",\"extraData\":\"0x010203\",\"gasLimit\":\"0x3d0900\",\"gasUsed\":\"0x0\",\"hash\":\"0xe3026a6708b90d5cb25557ac38ddc3f5ef550af10f31e1cf771524da8553fa1c\",\"logsBloom\":\"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\",\"miner\":\"0x0000000000000000000000000000000000000000\",\"mixHash\":\"0x2ba5557a4c62a513c7e56d1bf13373e0da6bec016755483e91589fe1c6d212e2\",\"nonce\":\"0x00000000000003e8\",\"number\":\"0x1\",\"parentHash\":\"0xff483e972a04a9a62bb4b7d04ae403c615604e4090521ecc5bb7af67f71be09c\",\"receiptsRoot\":\"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421\",\"sha3Uncles\":\"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347\",\"size\":\"0x221\",\"stateRoot\":\"0x1ef7300d8961797263939a3d29bbba4ccf1702fabf02d8ad7a20b454edb6fd2f\",\"totalDifficulty\":\"0x0\",\"timestamp\":\"0xf4240\",\"transactions\":[{\"nonce\":\"0x0\",\"blockHash\":\"0xe3026a6708b90d5cb25557ac38ddc3f5ef550af10f31e1cf771524da8553fa1c\",\"blockNumber\":\"0x1\",\"transactionIndex\":\"0x0\",\"from\":\"0x2d36e6c27c34ea22620e7b7c45de774599406cf3\",\"to\":\"0x0000000000000000000000000000000000000000\",\"value\":\"0x1\",\"gasPrice\":\"0x1\",\"gas\":\"0x5208\",\"data\":\"0x\",\"input\":\"0x\",\"type\":\"0x0\"}],\"transactionsRoot\":\"0x29cc403075ed3d1d6af940d577125cc378ee5a26f7746cbaf87f1cf4a38258b5\",\"uncles\":[]},\"id\":67}")); + Assert.That(serialized, Is.EqualTo("{\"jsonrpc\":\"2.0\",\"result\":{\"author\":\"0x0000000000000000000000000000000000000000\",\"difficulty\":\"0xf4240\",\"extraData\":\"0x010203\",\"gasLimit\":\"0x3d0900\",\"gasUsed\":\"0x0\",\"hash\":\"0xe3026a6708b90d5cb25557ac38ddc3f5ef550af10f31e1cf771524da8553fa1c\",\"logsBloom\":\"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\",\"miner\":\"0x0000000000000000000000000000000000000000\",\"mixHash\":\"0x2ba5557a4c62a513c7e56d1bf13373e0da6bec016755483e91589fe1c6d212e2\",\"nonce\":\"0x00000000000003e8\",\"number\":\"0x1\",\"parentHash\":\"0xff483e972a04a9a62bb4b7d04ae403c615604e4090521ecc5bb7af67f71be09c\",\"receiptsRoot\":\"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421\",\"sha3Uncles\":\"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347\",\"size\":\"0x221\",\"stateRoot\":\"0x1ef7300d8961797263939a3d29bbba4ccf1702fabf02d8ad7a20b454edb6fd2f\",\"totalDifficulty\":\"0x0\",\"timestamp\":\"0xf4240\",\"transactions\":[{\"nonce\":\"0x0\",\"blockHash\":\"0xe3026a6708b90d5cb25557ac38ddc3f5ef550af10f31e1cf771524da8553fa1c\",\"blockNumber\":\"0x1\",\"transactionIndex\":\"0x0\",\"from\":\"0x2d36e6c27c34ea22620e7b7c45de774599406cf3\",\"to\":\"0x0000000000000000000000000000000000000000\",\"value\":\"0x1\",\"gasPrice\":\"0x1\",\"gas\":\"0x5208\",\"input\":\"0x\",\"type\":\"0x0\"}],\"transactionsRoot\":\"0x29cc403075ed3d1d6af940d577125cc378ee5a26f7746cbaf87f1cf4a38258b5\",\"uncles\":[]},\"id\":67}")); } [TestCase(false)] diff --git a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/SubscribeModuleTests.cs b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/SubscribeModuleTests.cs index 18037ed4cad..2e75ca387cf 100644 --- a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/SubscribeModuleTests.cs +++ b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/SubscribeModuleTests.cs @@ -815,7 +815,7 @@ public void NewPendingTransactionsSubscription_on_NewPending_with_includeTransac jsonRpcResult.Response.Should().NotBeNull(); string serialized = _jsonSerializer.Serialize(jsonRpcResult.Response); - var expectedResult = string.Concat("{\"jsonrpc\":\"2.0\",\"method\":\"eth_subscription\",\"params\":{\"subscription\":\"", subscriptionId, "\",\"result\":{\"nonce\":\"0x0\",\"blockHash\":null,\"blockNumber\":null,\"transactionIndex\":null,\"to\":\"0x0000000000000000000000000000000000000000\",\"value\":\"0x1\",\"gasPrice\":\"0x1\",\"gas\":\"0x5208\",\"data\":\"0x\",\"input\":\"0x\",\"type\":\"0x0\"}}}"); + var expectedResult = string.Concat("{\"jsonrpc\":\"2.0\",\"method\":\"eth_subscription\",\"params\":{\"subscription\":\"", subscriptionId, "\",\"result\":{\"nonce\":\"0x0\",\"blockHash\":null,\"blockNumber\":null,\"transactionIndex\":null,\"to\":\"0x0000000000000000000000000000000000000000\",\"value\":\"0x1\",\"gasPrice\":\"0x1\",\"gas\":\"0x5208\",\"input\":\"0x\",\"type\":\"0x0\"}}}"); expectedResult.Should().Be(serialized); } diff --git a/src/Nethermind/Nethermind.JsonRpc/Data/TransactionForRpc.cs b/src/Nethermind/Nethermind.JsonRpc/Data/TransactionForRpc.cs index 2eefc2a73a8..4b4eabe1f18 100644 --- a/src/Nethermind/Nethermind.JsonRpc/Data/TransactionForRpc.cs +++ b/src/Nethermind/Nethermind.JsonRpc/Data/TransactionForRpc.cs @@ -91,7 +91,12 @@ public TransactionForRpc() public UInt256? MaxFeePerGas { get; set; } public long? Gas { get; set; } - public byte[]? Data { get; set; } + + // Required for compatibility with some CLs like Prysm + // Accept during deserialization, ignore during serialization + // See: https://github.com/NethermindEth/nethermind/pull/6067 + [JsonProperty(nameof(Data))] + private byte[]? Data { set { Input = value; } } [JsonProperty(NullValueHandling = NullValueHandling.Include)] public byte[]? Input { get; set; } @@ -130,7 +135,7 @@ public TransactionForRpc() To = To, SenderAddress = From, Value = Value ?? 0, - Data = Data ?? Input, + Data = Input, Type = Type, AccessList = TryGetAccessList(), ChainId = chainId, @@ -156,7 +161,7 @@ public TransactionForRpc() public T ToTransaction(ulong? chainId = null) where T : Transaction, new() { - byte[]? data = Data ?? Input; + byte[]? data = Input; T tx = new() { From 608f6cf74e5c7363f411a1f6bdb180c7912ec831 Mon Sep 17 00:00:00 2001 From: Yaroslav Kukharuk Date: Mon, 11 Sep 2023 19:22:29 +0200 Subject: [PATCH 04/50] Tests: Bump pruning size value for unit test (#6087) * Bump mainnet pruning size for a test * change bumped value to 5% increase --- .../Nethermind.Blockchain.Test/KnownChainSizesTests.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Nethermind/Nethermind.Blockchain.Test/KnownChainSizesTests.cs b/src/Nethermind/Nethermind.Blockchain.Test/KnownChainSizesTests.cs index 2bc50a847d1..415245bf21d 100644 --- a/src/Nethermind/Nethermind.Blockchain.Test/KnownChainSizesTests.cs +++ b/src/Nethermind/Nethermind.Blockchain.Test/KnownChainSizesTests.cs @@ -14,7 +14,7 @@ public class KnownChainSizesTests public void Update_known_chain_sizes() { // Pruning size have to be updated frequently - ChainSizes.CreateChainSizeInfo(BlockchainIds.Mainnet).PruningSize.Should().BeLessThan(200.GB()); + ChainSizes.CreateChainSizeInfo(BlockchainIds.Mainnet).PruningSize.Should().BeLessThan(210.GB()); ChainSizes.CreateChainSizeInfo(BlockchainIds.Goerli).PruningSize.Should().BeLessThan(70.GB()); ChainSizes.CreateChainSizeInfo(BlockchainIds.Sepolia).PruningSize.Should().BeLessThan(11.GB()); From 8571d761529887873a07a8e79a3e0697efb81b55 Mon Sep 17 00:00:00 2001 From: Lautaro Emanuel <31224949+emlautarom1@users.noreply.github.com> Date: Mon, 11 Sep 2023 16:19:21 -0300 Subject: [PATCH 05/50] Rerun logging setup on NLog config change (#6051) * Rerun setup on NLog configuration changed * Extract default logs folder into constant * Dispose event handler --- .../Nethermind.Logging.NLog/NLogManager.cs | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/src/Nethermind/Nethermind.Logging.NLog/NLogManager.cs b/src/Nethermind/Nethermind.Logging.NLog/NLogManager.cs index 2bb68e293aa..20ad3867675 100644 --- a/src/Nethermind/Nethermind.Logging.NLog/NLogManager.cs +++ b/src/Nethermind/Nethermind.Logging.NLog/NLogManager.cs @@ -14,11 +14,20 @@ namespace Nethermind.Logging.NLog { - public class NLogManager : ILogManager + public class NLogManager : ILogManager, IDisposable { private const string DefaultFileTargetName = "file-async_wrapped"; + private const string DefaultFolder = "logs"; public NLogManager(string logFileName, string logDirectory = null, string logRules = null) + { + Setup(logFileName, logDirectory, logRules); + // Required since 'NLog.config' could change during runtime, we need to re-apply the configuration + _logManagerOnConfigurationChanged = (sender, args) => Setup(logFileName, logDirectory, logRules); + LogManager.ConfigurationChanged += _logManagerOnConfigurationChanged; + } + + private void Setup(string logFileName, string logDirectory = null, string logRules = null) { logDirectory = SetupLogDirectory(logDirectory); SetupLogFile(logFileName, logDirectory); @@ -39,7 +48,7 @@ private static void SetupLogFile(string logFileName, string logDirectory) private static string SetupLogDirectory(string logDirectory) { - logDirectory = (string.IsNullOrEmpty(logDirectory) ? "logs" : logDirectory).GetApplicationResourcePath(); + logDirectory = (string.IsNullOrEmpty(logDirectory) ? DefaultFolder : logDirectory).GetApplicationResourcePath(); if (!Directory.Exists(logDirectory)) { Directory.CreateDirectory(logDirectory); @@ -49,6 +58,7 @@ private static string SetupLogDirectory(string logDirectory) } private ConcurrentDictionary _loggers = new(); + private EventHandler _logManagerOnConfigurationChanged; private NLogLogger BuildLogger(Type type) => new(type); @@ -147,5 +157,10 @@ public static void Shutdown() { LogManager.Shutdown(); } + + public void Dispose() + { + LogManager.ConfigurationChanged -= _logManagerOnConfigurationChanged; + } } } From fad045520ebd6a8fed9b2d793ce30dd1e99b8d4c Mon Sep 17 00:00:00 2001 From: Lautaro Emanuel <31224949+emlautarom1@users.noreply.github.com> Date: Mon, 11 Sep 2023 16:21:36 -0300 Subject: [PATCH 06/50] Fix JSON-RPC response streaming (#6078) * Add `WebSocketStream` - Wrap a `WebSocket` supporting `Stream` operations * Add single test * Include possible fix notes * Introduce 'CounterStream' - Decorator that counts the bytes written * Do not take ownership of the underlying WebSocket - Do not dispose `_socket` - When disposing, just send an "end of message" * Add 'SendUsingStream' to 'ISocketHandler' - Instead of using 'SendRawAsync' operate on the socket using a 'Stream' * Add more tests - Restructure tests (IPC, WebSockets) * Remove unused safe null operators * Replace implementation with 'Stream's * Use Test annotations * Test 'WebSockets' impl * Add 'NullJsonRpcLocalStats' - Do nothing on 'ReportCall' - Return default value on 'GetMethodStats' - Useful during testing * Initial WebSockets collection tests * Refactor message counting for WebSockets * Refactor IPC tests * Test sending collections through IPC * Increase test case count * Use 'NullJsonRpcLocalStats' when required * Send collections using streams * Invert if branches * Add tests for 'maxBatchResponseBodySize' option * Reorder fields, rename server * Fix random object usages * Throw 'InvalidOperationException' when socket is null --- .../JsonRpcSocketsClientTests.cs | 443 ++++++++++++++++++ .../NullJsonRpcLocalStats.cs | 19 + .../WebSockets/JsonRpcSocketsClient.cs | 72 ++- .../Nethermind.Sockets/CounterStream.cs | 64 +++ .../Nethermind.Sockets/ISocketHandler.cs | 2 + .../Nethermind.Sockets/IpcSocketsHandler.cs | 8 +- .../Nethermind.Sockets/WebSocketHandler.cs | 10 +- .../Nethermind.Sockets/WebSocketStream.cs | 108 +++++ 8 files changed, 680 insertions(+), 46 deletions(-) create mode 100644 src/Nethermind/Nethermind.JsonRpc.Test/JsonRpcSocketsClientTests.cs create mode 100644 src/Nethermind/Nethermind.JsonRpc/NullJsonRpcLocalStats.cs create mode 100644 src/Nethermind/Nethermind.Sockets/CounterStream.cs create mode 100644 src/Nethermind/Nethermind.Sockets/WebSocketStream.cs diff --git a/src/Nethermind/Nethermind.JsonRpc.Test/JsonRpcSocketsClientTests.cs b/src/Nethermind/Nethermind.JsonRpc.Test/JsonRpcSocketsClientTests.cs new file mode 100644 index 00000000000..993d86f8ccc --- /dev/null +++ b/src/Nethermind/Nethermind.JsonRpc.Test/JsonRpcSocketsClientTests.cs @@ -0,0 +1,443 @@ +// SPDX-FileCopyrightText: 2023 Demerzel Solutions Limited +// SPDX-License-Identifier: LGPL-3.0-only + +using System; +using System.Collections.Generic; +using System.Net; +using System.Net.Sockets; +using System.Net.WebSockets; +using System.Threading; +using System.Threading.Tasks; +using Nethermind.Evm.Tracing.GethStyle; +using Nethermind.JsonRpc.Modules; +using Nethermind.JsonRpc.Modules.DebugModule; +using Nethermind.JsonRpc.WebSockets; +using Nethermind.Logging; +using Nethermind.Serialization.Json; +using Nethermind.Sockets; +using NUnit.Framework; + +namespace Nethermind.JsonRpc.Test; + +[TestFixture] +public class JsonRpcSocketsClientTests +{ + public class UsingIpc + { + [Test] + [Explicit("Takes too long to run")] + public async Task Can_handle_very_large_objects() + { + IPEndPoint ipEndPoint = IPEndPoint.Parse("127.0.0.1:1337"); + + Task receiveBytes = OneShotServer( + ipEndPoint, + async socket => await CountNumberOfBytes(socket) + ); + + JsonRpcSuccessResponse bigObject = RandomSuccessResponse(200_000); + Task sendJsonRpcResult = Task.Run(async () => + { + using Socket socket = new Socket(ipEndPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp); + await socket.ConnectAsync(ipEndPoint); + + ISocketHandler handler = new IpcSocketsHandler(socket); + JsonRpcSocketsClient client = new JsonRpcSocketsClient( + clientName: "TestClient", + handler: handler, + endpointType: RpcEndpoint.IPC, + jsonRpcProcessor: null!, + jsonRpcService: null!, + jsonRpcLocalStats: new NullJsonRpcLocalStats(), + jsonSerializer: new EthereumJsonSerializer(converters: new GethLikeTxTraceConverter()) + ); + JsonRpcResult result = JsonRpcResult.Single(bigObject, default); + + return await client.SendJsonRpcResult(result); + }); + + await Task.WhenAll(sendJsonRpcResult, receiveBytes); + int sent = sendJsonRpcResult.Result; + int received = receiveBytes.Result; + Assert.That(sent, Is.EqualTo(received)); + } + + [Test] + [TestCase(2)] + [TestCase(10)] + [TestCase(50)] + public async Task Can_send_multiple_messages(int messageCount) + { + IPEndPoint ipEndPoint = IPEndPoint.Parse("127.0.0.1:1337"); + + Task receiveBytes = OneShotServer( + ipEndPoint, + async socket => await CountNumberOfBytes(socket) + ); + + Task sendJsonRpcResult = Task.Run(async () => + { + using Socket socket = new Socket(ipEndPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp); + await socket.ConnectAsync(ipEndPoint); + + ISocketHandler handler = new IpcSocketsHandler(socket); + JsonRpcSocketsClient client = new JsonRpcSocketsClient( + clientName: "TestClient", + handler: handler, + endpointType: RpcEndpoint.IPC, + jsonRpcProcessor: null!, + jsonRpcService: null!, + jsonRpcLocalStats: new NullJsonRpcLocalStats(), + jsonSerializer: new EthereumJsonSerializer(converters: new GethLikeTxTraceConverter()) + ); + JsonRpcResult result = JsonRpcResult.Single(RandomSuccessResponse(1_000), default); + + int totalBytesSent = 0; + for (int i = 0; i < messageCount; i++) + { + totalBytesSent += await client.SendJsonRpcResult(result); + } + + return totalBytesSent; + }); + + await Task.WhenAll(sendJsonRpcResult, receiveBytes); + int sent = sendJsonRpcResult.Result; + int received = receiveBytes.Result; + Assert.That(sent, Is.EqualTo(received)); + } + + [TestCase(2)] + [TestCase(10)] + [TestCase(50)] + public async Task Can_send_collections(int elements) + { + IPEndPoint ipEndPoint = IPEndPoint.Parse("127.0.0.1:1337"); + + Task receiveBytes = OneShotServer( + ipEndPoint, + async socket => await CountNumberOfBytes(socket) + ); + + Task sendCollection = Task.Run(async () => + { + using Socket socket = new Socket(ipEndPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp); + await socket.ConnectAsync(ipEndPoint); + + ISocketHandler handler = new IpcSocketsHandler(socket); + JsonRpcSocketsClient client = new JsonRpcSocketsClient( + clientName: "TestClient", + handler: handler, + endpointType: RpcEndpoint.IPC, + jsonRpcProcessor: null!, + jsonRpcService: null!, + jsonRpcLocalStats: new NullJsonRpcLocalStats(), + jsonSerializer: new EthereumJsonSerializer(converters: new GethLikeTxTraceConverter()) + ); + JsonRpcResult result = JsonRpcResult.Collection(RandomBatchResult(10, 100)); + + return await client.SendJsonRpcResult(result); + }); + + await Task.WhenAll(sendCollection, receiveBytes); + int sent = sendCollection.Result; + int received = receiveBytes.Result; + Assert.That(sent, Is.EqualTo(received)); + } + + private static async Task OneShotServer(IPEndPoint ipEndPoint, Func> func) + { + using Socket socket = new Socket(ipEndPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp); + socket.Bind(ipEndPoint); + socket.Listen(); + + Socket handler = await socket.AcceptAsync(); + + return await func(handler); + } + + private static async Task CountNumberOfBytes(Socket socket) + { + byte[] buffer = new byte[1024]; + int totalRead = 0; + + int read; + while ((read = await socket.ReceiveAsync(buffer)) != 0) + { + totalRead += read; + } + return totalRead; + } + } + + public class UsingWebSockets + { + [Test] + [TestCase(2)] + [TestCase(10)] + [TestCase(50)] + public async Task Can_send_multiple_messages(int messageCount) + { + CancellationTokenSource cts = new(); + + Task receiveMessages = OneShotServer( + "http://localhost:1337/", + async webSocket => await CountNumberOfMessages(webSocket, cts.Token) + ); + + Task sendMessages = Task.Run(async () => + { + using ClientWebSocket socket = new ClientWebSocket(); + await socket.ConnectAsync(new Uri("ws://localhost:1337/"), CancellationToken.None); + + using ISocketHandler handler = new WebSocketHandler(socket, NullLogManager.Instance); + using JsonRpcSocketsClient client = new JsonRpcSocketsClient( + clientName: "TestClient", + handler: handler, + endpointType: RpcEndpoint.Ws, + jsonRpcProcessor: null!, + jsonRpcService: null!, + jsonRpcLocalStats: new NullJsonRpcLocalStats(), + jsonSerializer: new EthereumJsonSerializer() + ); + JsonRpcResult result = JsonRpcResult.Single(RandomSuccessResponse(1_000), default); + + for (int i = 0; i < messageCount; i++) + { + await client.SendJsonRpcResult(result); + await Task.Delay(100); + } + cts.Cancel(); + + return messageCount; + }); + + await Task.WhenAll(sendMessages, receiveMessages); + int sent = sendMessages.Result; + int received = receiveMessages.Result; + Assert.That(sent, Is.EqualTo(received)); + } + + [TestCase(2)] + [TestCase(10)] + [TestCase(50)] + public async Task Can_send_collections(int elements) + { + CancellationTokenSource cts = new(); + + Task server = OneShotServer( + "http://localhost:1337/", + async webSocket => await CountNumberOfMessages(webSocket, cts.Token) + ); + + Task sendCollection = Task.Run(async () => + { + using ClientWebSocket socket = new ClientWebSocket(); + await socket.ConnectAsync(new Uri("ws://localhost:1337/"), CancellationToken.None); + + using ISocketHandler handler = new WebSocketHandler(socket, NullLogManager.Instance); + using JsonRpcSocketsClient client = new JsonRpcSocketsClient( + clientName: "TestClient", + handler: handler, + endpointType: RpcEndpoint.Ws, + jsonRpcProcessor: null!, + jsonRpcService: null!, + jsonRpcLocalStats: new NullJsonRpcLocalStats(), + jsonSerializer: new EthereumJsonSerializer() + ); + JsonRpcResult result = JsonRpcResult.Collection(RandomBatchResult(10, 100)); + + await client.SendJsonRpcResult(result); + + await Task.Delay(100); + cts.Cancel(); + }); + + await Task.WhenAll(sendCollection, server); + Assert.That(server.Result, Is.EqualTo(1)); + } + + [TestCase(1_000)] + [TestCase(5_000)] + [TestCase(10_000)] + [Ignore("Feature does not work correctly")] + public async Task Stops_on_limited_body_size(int maxByteCount) + { + CancellationTokenSource cts = new(); + + Task receiveBytes = OneShotServer( + "http://localhost:1337/", + async webSocket => await CountNumberOfBytes(webSocket, cts.Token) + ); + + Task sendCollection = Task.Run(async () => + { + using ClientWebSocket socket = new ClientWebSocket(); + await socket.ConnectAsync(new Uri("ws://localhost:1337/"), CancellationToken.None); + + using ISocketHandler handler = new WebSocketHandler(socket, NullLogManager.Instance); + using JsonRpcSocketsClient client = new JsonRpcSocketsClient( + clientName: "TestClient", + handler: handler, + endpointType: RpcEndpoint.Ws, + jsonRpcProcessor: null!, + jsonRpcService: null!, + jsonRpcLocalStats: new NullJsonRpcLocalStats(), + jsonSerializer: new EthereumJsonSerializer(), + maxBatchResponseBodySize: maxByteCount + ); + JsonRpcResult result = JsonRpcResult.Collection(RandomBatchResult(10, 100)); + + int sent = await client.SendJsonRpcResult(result); + + await Task.Delay(100); + cts.Cancel(); + + return sent; + }); + + await Task.WhenAll(sendCollection, receiveBytes); + int sent = sendCollection.Result; + long received = receiveBytes.Result; + Assert.That(received, Is.LessThanOrEqualTo(Math.Min(sent, maxByteCount))); + } + + private static async Task OneShotServer(string uri, Func> func) + { + using HttpListener httpListener = new(); + httpListener.Prefixes.Add(uri); + httpListener.Start(); + + HttpListenerContext context = await httpListener.GetContextAsync(); + HttpListenerWebSocketContext webSocketContext = await context.AcceptWebSocketAsync(null); + return await func(webSocketContext.WebSocket); + } + + private static async Task CountNumberOfMessages(WebSocket webSocket, CancellationToken token) + { + int messages = 0; + try + { + byte[] buffer = new byte[1024]; + + while (webSocket.State == WebSocketState.Open) + { + WebSocketReceiveResult result = await webSocket.ReceiveAsync(new ArraySegment(buffer), token); + if (result.EndOfMessage) + { + messages++; + } + } + } + catch (OperationCanceledException) { } + finally + { + if (webSocket.State == WebSocketState.Open) + { + await webSocket.CloseAsync(WebSocketCloseStatus.NormalClosure, string.Empty, token); + } + webSocket.Dispose(); + } + + return messages; + } + + private static async Task CountNumberOfBytes(WebSocket webSocket, CancellationToken token) + { + long bytes = 0; + try + { + byte[] buffer = new byte[1024]; + + while (webSocket.State == WebSocketState.Open) + { + WebSocketReceiveResult result = await webSocket.ReceiveAsync(new ArraySegment(buffer), token); + bytes += result.Count; + } + } + catch (OperationCanceledException) { } + finally + { + if (webSocket.State == WebSocketState.Open) + { + await webSocket.CloseAsync(WebSocketCloseStatus.NormalClosure, string.Empty, token); + } + webSocket.Dispose(); + } + + return bytes; + } + } + + private static JsonRpcBatchResult RandomBatchResult(int items, int size) + { + return new JsonRpcBatchResult((_, token) => + RandomAsyncEnumerable( + items, + () => Task.FromResult(new JsonRpcResult.Entry(RandomSuccessResponse(size), default)) + ).GetAsyncEnumerator(token) + ); + } + + private static JsonRpcSuccessResponse RandomSuccessResponse(int size) + { + return new JsonRpcSuccessResponse + { + MethodName = "mock", + Id = "42", + Result = RandomObject(size) + }; + } + + private static async IAsyncEnumerable RandomAsyncEnumerable(int items, Func> factory) + { + for (int i = 0; i < items; i++) + { + T value = await factory(); + yield return value; + } + } + + private static object RandomObject(int size) + { + string[] strings = RandomStringArray(size / 2); + object obj = new GethLikeTxTrace() + { + Entries = + { + new GethTxTraceEntry + { + Stack = strings, Memory = strings, + } + } + }; + return obj; + } + + private static string[] RandomStringArray(int length, bool runGc = true) + { + string[] array = new string[length]; + for (int i = 0; i < length; i++) + { + array[i] = RandomString(length); + if (runGc && i % 100 == 0) + { + GC.Collect(); + } + } + return array; + } + + private static string RandomString(int length) + { + const string chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; + char[] stringChars = new char[length]; + Random random = new(); + + for (int i = 0; i < stringChars.Length; i++) + { + stringChars[i] = chars[random.Next(chars.Length)]; + } + return new string(stringChars); + } +} diff --git a/src/Nethermind/Nethermind.JsonRpc/NullJsonRpcLocalStats.cs b/src/Nethermind/Nethermind.JsonRpc/NullJsonRpcLocalStats.cs new file mode 100644 index 00000000000..20a298e9e54 --- /dev/null +++ b/src/Nethermind/Nethermind.JsonRpc/NullJsonRpcLocalStats.cs @@ -0,0 +1,19 @@ +// SPDX-FileCopyrightText: 2023 Demerzel Solutions Limited +// SPDX-License-Identifier: LGPL-3.0-only + +using System.Threading.Tasks; + +namespace Nethermind.JsonRpc; + +public class NullJsonRpcLocalStats : IJsonRpcLocalStats +{ + + public Task ReportCall(RpcReport report, long elapsedMicroseconds = 0, long? size = null) + { + return Task.CompletedTask; + } + public MethodStats GetMethodStats(string methodName) + { + return new MethodStats(); + } +} diff --git a/src/Nethermind/Nethermind.JsonRpc/WebSockets/JsonRpcSocketsClient.cs b/src/Nethermind/Nethermind.JsonRpc/WebSockets/JsonRpcSocketsClient.cs index f332c5b18bd..d6451445bfd 100644 --- a/src/Nethermind/Nethermind.JsonRpc/WebSockets/JsonRpcSocketsClient.cs +++ b/src/Nethermind/Nethermind.JsonRpc/WebSockets/JsonRpcSocketsClient.cs @@ -111,11 +111,14 @@ private void IncrementBytesSentMetric(int size) public virtual async Task SendJsonRpcResult(JsonRpcResult result) { + await using Stream stream = _handler.SendUsingStream(); + await using Stream buffered = new BufferedStream(stream); + await using CounterStream resultData = new CounterStream(buffered); + if (result.IsCollection) { - int singleResponseSize = 1; bool isFirst = true; - await _handler.SendRawAsync(_jsonOpeningBracket, false); + await resultData.WriteAsync(_jsonOpeningBracket); JsonRpcBatchResultAsyncEnumerator enumerator = result.BatchedResponses!.GetAsyncEnumerator(CancellationToken.None); try { @@ -126,16 +129,14 @@ public virtual async Task SendJsonRpcResult(JsonRpcResult result) { if (!isFirst) { - await _handler.SendRawAsync(_jsonComma, false); - singleResponseSize += 1; + await resultData.WriteAsync(_jsonComma); } - isFirst = false; - singleResponseSize += await SendJsonRpcResultEntry(entry, false); + SendJsonRpcResultEntry(resultData, entry); _ = _jsonRpcLocalStats.ReportCall(entry.Report); // We reached the limit and don't want to responded to more request in the batch - if (!_jsonRpcContext.IsAuthenticated && singleResponseSize > _maxBatchResponseBodySize) + if (!_jsonRpcContext.IsAuthenticated && resultData.WrittenBytes > _maxBatchResponseBodySize) { enumerator.IsStopped = true; } @@ -147,52 +148,37 @@ public virtual async Task SendJsonRpcResult(JsonRpcResult result) await enumerator.DisposeAsync(); } - await _handler.SendRawAsync(_jsonClosingBracket, true); - singleResponseSize += 1; - - return singleResponseSize; + await resultData.WriteAsync(_jsonClosingBracket); } else { - return await SendJsonRpcResultEntry(result.SingleResponse!.Value); + SendJsonRpcResultEntry(resultData, result.SingleResponse!.Value); } + + // ? What if we write more than int.MaxValue. + // Result could be negative + return (int)resultData.WrittenBytes; } - private async Task SendJsonRpcResultEntry(JsonRpcResult.Entry result, bool endOfMessage = true) + private void SendJsonRpcResultEntry(Stream dest, JsonRpcResult.Entry result) { - void SerializeTimeoutException(MemoryStream stream, JsonRpcResult.Entry result) + using JsonRpcResult.Entry entry = result; + + try { - _jsonSerializer.Serialize(stream, _jsonRpcService.GetErrorResponse( - ErrorCodes.Timeout, - "Request was canceled due to enabled timeout.", - result.Response.Id, - result.Response.MethodName)); + _jsonSerializer.SerializeWaitForEnumeration(dest, result.Response); } - - using (result) + catch (Exception e) when (e is OperationCanceledException || e.InnerException is OperationCanceledException) { - await using MemoryStream resultData = new(); - - try - { - _jsonSerializer.SerializeWaitForEnumeration(resultData, result.Response); - } - catch (Exception e) when (e.InnerException is OperationCanceledException) - { - SerializeTimeoutException(resultData, result); - } - catch (OperationCanceledException) - { - SerializeTimeoutException(resultData, result); - } - - if (resultData.TryGetBuffer(out ArraySegment data)) - { - await _handler.SendRawAsync(data, endOfMessage); - return data.Count; - } - - return (int)resultData.Length; + _jsonSerializer.Serialize( + dest, + _jsonRpcService.GetErrorResponse( + ErrorCodes.Timeout, + "Request was canceled due to enabled timeout.", + result.Response.Id, + result.Response.MethodName + ) + ); } } } diff --git a/src/Nethermind/Nethermind.Sockets/CounterStream.cs b/src/Nethermind/Nethermind.Sockets/CounterStream.cs new file mode 100644 index 00000000000..c8fc360bb13 --- /dev/null +++ b/src/Nethermind/Nethermind.Sockets/CounterStream.cs @@ -0,0 +1,64 @@ +// SPDX-FileCopyrightText: 2023 Demerzel Solutions Limited +// SPDX-License-Identifier: LGPL-3.0-only + +using System; +using System.IO; + +namespace Nethermind.Sockets; + +public class CounterStream : Stream +{ + private readonly Stream _stream; + + public CounterStream(Stream stream) + { + _stream = stream ?? throw new ArgumentNullException(nameof(stream)); + } + + public long WrittenBytes { get; private set; } + + public override void Flush() => _stream.Flush(); + + public override int Read(byte[] buffer, int offset, int count) => _stream.Read(buffer, offset, count); + + public override long Seek(long offset, SeekOrigin origin) => _stream.Seek(offset, origin); + + public override void SetLength(long value) => _stream.SetLength(value); + + public override void Write(byte[] buffer, int offset, int count) + { + _stream.Write(buffer, offset, count); + WrittenBytes += count; + } + + public override bool CanRead + { + get => _stream.CanRead; + } + + public override bool CanSeek + { + get => _stream.CanSeek; + } + + public override bool CanWrite + { + get => _stream.CanWrite; + } + + public override long Length + { + get => _stream.Length; + } + + public override bool CanTimeout + { + get => _stream.CanTimeout; + } + + public override long Position + { + get => _stream.Position; + set => _stream.Position = value; + } +} diff --git a/src/Nethermind/Nethermind.Sockets/ISocketHandler.cs b/src/Nethermind/Nethermind.Sockets/ISocketHandler.cs index e2f73fee77e..65bd867128a 100644 --- a/src/Nethermind/Nethermind.Sockets/ISocketHandler.cs +++ b/src/Nethermind/Nethermind.Sockets/ISocketHandler.cs @@ -2,6 +2,7 @@ // SPDX-License-Identifier: LGPL-3.0-only using System; +using System.IO; using System.Threading.Tasks; namespace Nethermind.Sockets @@ -15,5 +16,6 @@ public interface ISocketHandler : IDisposable Task SendRawAsync(ArraySegment data, bool endMessage = true); Task GetReceiveResult(ArraySegment buffer); Task CloseAsync(ReceiveResult? result); + Stream SendUsingStream(); } } diff --git a/src/Nethermind/Nethermind.Sockets/IpcSocketsHandler.cs b/src/Nethermind/Nethermind.Sockets/IpcSocketsHandler.cs index 09ab7758e2a..1bfe41c6bde 100644 --- a/src/Nethermind/Nethermind.Sockets/IpcSocketsHandler.cs +++ b/src/Nethermind/Nethermind.Sockets/IpcSocketsHandler.cs @@ -2,6 +2,7 @@ // SPDX-License-Identifier: LGPL-3.0-only using System; +using System.IO; using System.Net.Sockets; using System.Threading.Tasks; @@ -44,9 +45,14 @@ public Task CloseAsync(ReceiveResult? result) return Task.Factory.StartNew(_socket.Close); } + public Stream SendUsingStream() + { + return new NetworkStream(_socket, FileAccess.Write, ownsSocket: false); + } + public void Dispose() { - _socket?.Dispose(); + _socket.Dispose(); } } } diff --git a/src/Nethermind/Nethermind.Sockets/WebSocketHandler.cs b/src/Nethermind/Nethermind.Sockets/WebSocketHandler.cs index 1ca93c0744a..fd07cdc2c93 100644 --- a/src/Nethermind/Nethermind.Sockets/WebSocketHandler.cs +++ b/src/Nethermind/Nethermind.Sockets/WebSocketHandler.cs @@ -2,6 +2,7 @@ // SPDX-License-Identifier: LGPL-3.0-only using System; +using System.IO; using System.Net.Sockets; using System.Net.WebSockets; using System.Threading; @@ -18,7 +19,7 @@ public class WebSocketHandler : ISocketHandler public WebSocketHandler(WebSocket webSocket, ILogManager logManager) { _webSocket = webSocket; - _logger = logManager?.GetClassLogger() ?? throw new ArgumentNullException(nameof(logManager)); + _logger = logManager.GetClassLogger() ?? throw new ArgumentNullException(nameof(logManager)); } public Task SendRawAsync(ArraySegment data, bool endOfMessage = true) => @@ -108,9 +109,14 @@ public Task CloseAsync(ReceiveResult? result) return Task.CompletedTask; } + public Stream SendUsingStream() + { + return new WebSocketStream(_webSocket, WebSocketMessageType.Text); + } + public void Dispose() { - _webSocket?.Dispose(); + _webSocket.Dispose(); } } } diff --git a/src/Nethermind/Nethermind.Sockets/WebSocketStream.cs b/src/Nethermind/Nethermind.Sockets/WebSocketStream.cs new file mode 100644 index 00000000000..c2d36755256 --- /dev/null +++ b/src/Nethermind/Nethermind.Sockets/WebSocketStream.cs @@ -0,0 +1,108 @@ +// SPDX-FileCopyrightText: 2023 Demerzel Solutions Limited +// SPDX-License-Identifier: LGPL-3.0-only + +using System; +using System.IO; +using System.Net.WebSockets; +using System.Threading; +using System.Threading.Tasks; + +namespace Nethermind.Sockets; + +public class WebSocketStream : Stream +{ + private WebSocket? _socket; + private readonly WebSocketMessageType _messageType; + + public WebSocketStream(WebSocket socket, WebSocketMessageType messageType) + { + _socket = socket; + _messageType = messageType; + } + + public override bool CanRead => true; + public override bool CanSeek => false; + public override bool CanWrite => true; + public override long Length => throw new NotSupportedException(); + + public override long Position + { + get => throw new NotSupportedException(); + set => throw new NotSupportedException(); + } + + public override async Task ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken) + { + ThrowIfDisposed(); + _ = _socket ?? throw new InvalidOperationException($"The underlying {nameof(WebSocket)} is null"); + + if (_socket.State is WebSocketState.Closed or WebSocketState.CloseReceived or WebSocketState.CloseSent) + { + return 0; + } + + ArraySegment segment = new(buffer, offset, count); + WebSocketReceiveResult result = await _socket.ReceiveAsync(segment, cancellationToken); + + if (result.MessageType == WebSocketMessageType.Close) + { + await _socket.CloseAsync(WebSocketCloseStatus.NormalClosure, "Remote close", cancellationToken); + return 0; + } + + return result.Count; + } + + public override async Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken) + { + ThrowIfDisposed(); + _ = _socket ?? throw new ArgumentNullException(nameof(_socket)); + if (_socket.State != WebSocketState.Open) { throw new IOException($"WebSocket not open ({_socket.State})"); } + + ArraySegment segment = new(buffer, offset, count); + await _socket.SendAsync(segment, _messageType, false, cancellationToken); + } + + public override void Flush() { } + + public override int Read(byte[] buffer, int offset, int count) + { + return ReadAsync(buffer, offset, count).GetAwaiter().GetResult(); + } + + public override long Seek(long offset, SeekOrigin origin) + { + throw new NotSupportedException(); + } + + public override void SetLength(long value) + { + throw new NotSupportedException(); + } + + public override void Write(byte[] buffer, int offset, int count) + { + WriteAsync(buffer, offset, count).GetAwaiter().GetResult(); + } + + protected override void Dispose(bool disposing) + { + try + { + if (disposing) + { + _socket?.SendAsync(ReadOnlyMemory.Empty, WebSocketMessageType.Text, true, CancellationToken.None); + } + } + finally + { + _socket = null; + base.Dispose(disposing); + } + } + + private void ThrowIfDisposed() + { + if (_socket == null) throw new ObjectDisposedException(nameof(_socket)); + } +} From fd660553075d83a7a4b80adbae03dbfb0c0f91a2 Mon Sep 17 00:00:00 2001 From: Yaroslav Kukharuk Date: Mon, 11 Sep 2023 22:38:06 +0200 Subject: [PATCH 07/50] CI: Switch Fix chiado test failures and switch action to matrix setup (#6083) * Disable chiaro wait step and output the logs * allow triggers for all branches * fetch logs from within sedge directory * switch CL to lodestar * invalid CL client? * try teku CL * change cl url flag * switch back to lodestar * revert back to the lighthouse CL and add sepolia back * add logging back * try default lighthouse CL * switch to matrix * Revert debugging changes * Set YAML indentation * Apply correct indentation --------- Co-authored-by: Ruben Buniatyan --- .editorconfig | 4 + .github/workflows/sync-testnets.yml | 144 ++++++---------------------- 2 files changed, 32 insertions(+), 116 deletions(-) diff --git a/.editorconfig b/.editorconfig index 75c4b4d016c..4ddeb73842d 100644 --- a/.editorconfig +++ b/.editorconfig @@ -46,6 +46,10 @@ indent_size = 2 [*.sh] indent_size = 2 +# YAML files +[*.{yml,yaml}] +indent_size = 2 + ############################### # Override Visual Studio # ############################### diff --git a/.github/workflows/sync-testnets.yml b/.github/workflows/sync-testnets.yml index 1bfec466576..f4d1d12dfd6 100644 --- a/.github/workflows/sync-testnets.yml +++ b/.github/workflows/sync-testnets.yml @@ -2,7 +2,7 @@ name: Sync Testnets on: push: - branches: ["master"] + branches: [master] workflow_dispatch: env: @@ -10,19 +10,30 @@ env: TERM: xterm jobs: - chiado: - name: "Run sync of chiado testnet" + testnet-sync: + strategy: + matrix: + include: + - network: "chiado" + checkpoint-sync-url: "http://139.144.26.89:4000/" + cl-client: "lighthouse" + el-client: "nethermind:current_branch_image" + - network: "sepolia" + checkpoint-sync-url: "https://beaconstate-sepolia.chainsafe.io" + cl-client: "lighthouse" + el-client: "nethermind:current_branch_image" + name: "Run sync of ${{ matrix.network }} testnet" runs-on: ubuntu-latest steps: - name: Checkout repository uses: actions/checkout@v3 - + - name: Configure settings id: settings run: | echo "BUILD_TIMESTAMP=$(date '+%s')" >> $GITHUB_OUTPUT echo "COMMIT_HASH=$(git describe --always --exclude=* --abbrev=40)" >> $GITHUB_OUTPUT - + - name: Set up Docker Buildx uses: docker/setup-buildx-action@v2 @@ -47,150 +58,51 @@ jobs: echo 'Generating sedge docker...' ./build/sedge deps install ./build/sedge generate --logging none -p $GITHUB_WORKSPACE/sedge \ - full-node --map-all --no-mev-boost --no-validator --network chiado \ - -c lighthouse:sigp/lighthouse:latest -e nethermind:current_branch_image \ + full-node --map-all --no-mev-boost --no-validator --network ${{ matrix.network }} \ + -c ${{ matrix.cl-client }} -e ${{ matrix.el-client }} \ --el-extra-flag Sync.NonValidatorNode=true --el-extra-flag Sync.DownloadBodiesInFastSync=false \ --el-extra-flag Sync.DownloadReceiptsInFastSync=false \ --el-extra-flag JsonRpc.EnabledModules=[Eth,Subscribe,Trace,TxPool,Web3,Personal,Proof,Net,Parity,Health,Rpc,Debug] \ - --cl-extra-flag checkpoint-sync-url=http://139.144.26.89:4000/ + --checkpoint-sync-url=${{ matrix.checkpoint-sync-url }} echo 'Running sedge...' docker compose up -d - - name: Wait for Chiado to sync + - name: Wait for ${{ matrix.network }} to sync id: wait timeout-minutes: 90 run: | set +e - - declare -A bad_logs - bad_logs["Invalid"]=1 - bad_logs["Exception"]=1 - bad_logs["Corrupted"]=1 - - declare -A good_logs - good_logs["Synced chain Head"]=0 - good_logs["Processed"]=0 - - declare -A required_count - required_count["Synced chain Head"]=20 - required_count["Processed"]=20 - - echo "Starting Docker logs monitoring..." - docker logs -f sedge-execution-client | while read -r line; do - echo "$line" - - for bad_log in "${!bad_logs[@]}"; do - if [[ "$line" == *"$bad_log"* ]]; then - echo "Error: $bad_log found in Docker logs." - exit 1 - fi - done - - for good_log in "${!good_logs[@]}"; do - if [[ "$line" == *"$good_log"* ]]; then - ((good_logs["$good_log"]++)) - fi - done - - # Check if all good logs have reached the required count - all_reached_required_count=true - for good_log in "${!good_logs[@]}"; do - if [[ ${good_logs[$good_log]} -lt ${required_count[$good_log]} ]]; then - all_reached_required_count=false - break - fi - done - - if $all_reached_required_count; then - echo "All required logs found." - break - fi - done - - echo "Node is synced." - - sepolia: - name: "Run sync of sepolia testnet" - runs-on: ubuntu-latest - steps: - - name: Checkout repository - uses: actions/checkout@v3 - - - name: Configure settings - id: settings - run: | - echo "BUILD_TIMESTAMP=$(date '+%s')" >> $GITHUB_OUTPUT - echo "COMMIT_HASH=$(git describe --always --exclude=* --abbrev=40)" >> $GITHUB_OUTPUT - - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v2 - - - name: Build docker image - run: docker buildx build --platform=linux/amd64 -t current_branch_image -f Dockerfile --build-arg COMMIT_HASH=${{ steps.settings.outputs.COMMIT_HASH }} --build-arg BUILD_TIMESTAMP=${{ steps.settings.outputs.BUILD_TIMESTAMP}} --load . - - - name: Setup Go environment - uses: actions/setup-go@v4.0.0 - - name: Install Sedge environment - run: | - echo "Downloading sedge sources..." - git clone https://github.com/NethermindEth/sedge.git sedge --branch main --single-branch - echo "Sources downloaded." - cd sedge - echo "Building sedge..." - make compile - - - name: Run Sedge - working-directory: sedge - run: | - echo 'Generating sedge docker...' - ./build/sedge deps install - ./build/sedge generate --logging none -p $GITHUB_WORKSPACE/sedge \ - full-node --map-all --no-mev-boost --no-validator --network sepolia \ - -c lighthouse:sigp/lighthouse:latest -e nethermind:current_branch_image \ - --el-extra-flag Sync.NonValidatorNode=true --el-extra-flag Sync.DownloadBodiesInFastSync=false \ - --el-extra-flag Sync.DownloadReceiptsInFastSync=false \ - --el-extra-flag JsonRpc.EnabledModules=[Eth,Subscribe,Trace,TxPool,Web3,Personal,Proof,Net,Parity,Health,Rpc,Debug] \ - --cl-extra-flag checkpoint-sync-url=https://beaconstate-sepolia.chainsafe.io - echo 'Running sedge...' - docker compose up -d - - - name: Wait for Sepolia to sync - id: wait - timeout-minutes: 90 - run: | - set +e - declare -A bad_logs bad_logs["Invalid"]=1 bad_logs["Exception"]=1 bad_logs["Corrupted"]=1 - + declare -A good_logs good_logs["Synced chain Head"]=0 good_logs["Processed"]=0 - + declare -A required_count required_count["Synced chain Head"]=20 required_count["Processed"]=20 - + echo "Starting Docker logs monitoring..." docker logs -f sedge-execution-client | while read -r line; do echo "$line" - + for bad_log in "${!bad_logs[@]}"; do if [[ "$line" == *"$bad_log"* ]]; then echo "Error: $bad_log found in Docker logs." exit 1 fi done - + for good_log in "${!good_logs[@]}"; do if [[ "$line" == *"$good_log"* ]]; then ((good_logs["$good_log"]++)) fi done - + # Check if all good logs have reached the required count all_reached_required_count=true for good_log in "${!good_logs[@]}"; do @@ -199,11 +111,11 @@ jobs: break fi done - + if $all_reached_required_count; then echo "All required logs found." break fi done - + echo "Node is synced." From 92f9b7765f54b752ed09ee8156b27acdc683b261 Mon Sep 17 00:00:00 2001 From: Ruben Buniatyan Date: Wed, 13 Sep 2023 16:11:41 +0200 Subject: [PATCH 08/50] Publish draft releases as the latest (#6058) --- scripts/deployment/publish-github.sh | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/scripts/deployment/publish-github.sh b/scripts/deployment/publish-github.sh index cc97dedddd4..2c6eb72fa00 100755 --- a/scripts/deployment/publish-github.sh +++ b/scripts/deployment/publish-github.sh @@ -5,7 +5,6 @@ set -e echo "Publishing packages to GitHub" -echo "Drafting release $GIT_TAG" release_id=$(curl https://api.github.com/repos/$GITHUB_REPOSITORY/releases \ -X GET \ @@ -14,6 +13,8 @@ release_id=$(curl https://api.github.com/repos/$GITHUB_REPOSITORY/releases \ if [ "$release_id" == "" ] then + echo "Drafting release $GIT_TAG" + body=$(printf \ '{"tag_name": "%s", "target_commitish": "%s", "name": "v%s", "body": "## Release notes\\n\\n", "draft": true, "prerelease": %s}' \ $GIT_TAG $GITHUB_SHA $GIT_TAG $PRERELEASE) @@ -25,9 +26,13 @@ then -H "Authorization: Bearer $GITHUB_TOKEN" \ -d "$body" | jq -r '.id') else + echo "Publishing release $GIT_TAG" + + make_latest=$([ $PRERELEASE = 'true' ] && echo "false" || echo "true") + body=$(printf \ - '{"target_commitish": "%s", "name": "v%s", "draft": false, "prerelease": %s}' \ - $GITHUB_SHA $GIT_TAG $PRERELEASE) + '{"target_commitish": "%s", "name": "v%s", "draft": false, "make_latest": "%s", "prerelease": %s}' \ + $GITHUB_SHA $GIT_TAG $make_latest $PRERELEASE) curl https://api.github.com/repos/$GITHUB_REPOSITORY/releases/$release_id \ -X PATCH \ From 433c0b2531db19a83a8c6ab88f2ee08614425392 Mon Sep 17 00:00:00 2001 From: Ayman Bouchareb Date: Wed, 13 Sep 2023 08:50:14 -0700 Subject: [PATCH 09/50] Activate Eip5656 hive tests (#5941) * decomment hive tests * remove comment * - update tests submodule commit reference * fix test inclusion * fix loading tests * switch tests from old commit to branch head * match path name to folder name * update tests name * add Eip1153 tests placeholder * file file * add place holder for missing tests * move tests submodule to HEAD --- .../Ethereum.Blockchain.Test/Eip1153Tests.cs | 27 +++++++++++++++++++ .../Ethereum.Blockchain.Test/Eip4844Tests.cs | 27 +++++++++++++++++++ .../Ethereum.Blockchain.Test/Eip5656Tests.cs | 14 +++++----- .../Ethereum.Blockchain.Test/EofTests.cs | 27 +++++++++++++++++++ .../Ethereum.Blockchain.Test.csproj | 2 +- .../Ethereum.Test.Base/JsonToEthereumTest.cs | 2 ++ .../LoadEipTestsStrategy.cs | 2 +- src/tests | 2 +- 8 files changed, 92 insertions(+), 11 deletions(-) create mode 100644 src/Nethermind/Ethereum.Blockchain.Test/Eip1153Tests.cs create mode 100644 src/Nethermind/Ethereum.Blockchain.Test/Eip4844Tests.cs create mode 100644 src/Nethermind/Ethereum.Blockchain.Test/EofTests.cs diff --git a/src/Nethermind/Ethereum.Blockchain.Test/Eip1153Tests.cs b/src/Nethermind/Ethereum.Blockchain.Test/Eip1153Tests.cs new file mode 100644 index 00000000000..924848f3ac2 --- /dev/null +++ b/src/Nethermind/Ethereum.Blockchain.Test/Eip1153Tests.cs @@ -0,0 +1,27 @@ +// SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited +// SPDX-License-Identifier: LGPL-3.0-only + +using System.Collections.Generic; +using Ethereum.Test.Base; +using NUnit.Framework; + +namespace Ethereum.Blockchain.Test; + +[TestFixture] +[Parallelizable(ParallelScope.All)] +public class EIP1153transientStorageTests : GeneralStateTestBase +{ + // Uncomment when Eip1153 tests are merged + + // [TestCaseSource(nameof(LoadTests))] + // public void Test(GeneralStateTest test) + // { + // Assert.True(RunTest(test).Pass); + // } + + public static IEnumerable LoadTests() + { + var loader = new TestsSourceLoader(new LoadEipTestsStrategy(), "stEIP1153-transientStorage"); + return (IEnumerable)loader.LoadTests(); + } +} diff --git a/src/Nethermind/Ethereum.Blockchain.Test/Eip4844Tests.cs b/src/Nethermind/Ethereum.Blockchain.Test/Eip4844Tests.cs new file mode 100644 index 00000000000..89cbdba8b61 --- /dev/null +++ b/src/Nethermind/Ethereum.Blockchain.Test/Eip4844Tests.cs @@ -0,0 +1,27 @@ +// SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited +// SPDX-License-Identifier: LGPL-3.0-only + +using System.Collections.Generic; +using Ethereum.Test.Base; +using NUnit.Framework; + +namespace Ethereum.Blockchain.Test; + +[TestFixture] +[Parallelizable(ParallelScope.All)] +public class EIP4844blobtransactionsTests : GeneralStateTestBase +{ + // Uncomment when stEIP4844 tests are merged + + // [TestCaseSource(nameof(LoadTests))] + // public void Test(GeneralStateTest test) + // { + // Assert.True(RunTest(test).Pass); + // } + + public static IEnumerable LoadTests() + { + var loader = new TestsSourceLoader(new LoadEipTestsStrategy(), "stEIP4844-blobtransactions"); + return (IEnumerable)loader.LoadTests(); + } +} diff --git a/src/Nethermind/Ethereum.Blockchain.Test/Eip5656Tests.cs b/src/Nethermind/Ethereum.Blockchain.Test/Eip5656Tests.cs index a2ae5e738b9..1a48e321290 100644 --- a/src/Nethermind/Ethereum.Blockchain.Test/Eip5656Tests.cs +++ b/src/Nethermind/Ethereum.Blockchain.Test/Eip5656Tests.cs @@ -9,15 +9,13 @@ namespace Ethereum.Blockchain.Test; [TestFixture] [Parallelizable(ParallelScope.All)] -public class Eip5656Tests : GeneralStateTestBase +public class EIP5656MCOPYTests : GeneralStateTestBase { - // wait untill Eip5656 tests are merged to de-comment this - - // [TestCaseSource(nameof(LoadTests))] - // public void Test(GeneralStateTest test) - // { - // Assert.True(RunTest(test).Pass); - // } + [TestCaseSource(nameof(LoadTests))] + public void Test(GeneralStateTest test) + { + Assert.True(RunTest(test).Pass); + } public static IEnumerable LoadTests() { diff --git a/src/Nethermind/Ethereum.Blockchain.Test/EofTests.cs b/src/Nethermind/Ethereum.Blockchain.Test/EofTests.cs new file mode 100644 index 00000000000..f4fad766299 --- /dev/null +++ b/src/Nethermind/Ethereum.Blockchain.Test/EofTests.cs @@ -0,0 +1,27 @@ +// SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited +// SPDX-License-Identifier: LGPL-3.0-only + +using System.Collections.Generic; +using Ethereum.Test.Base; +using NUnit.Framework; + +namespace Ethereum.Blockchain.Test; + +[TestFixture] +[Parallelizable(ParallelScope.All)] +public class EOFTests : GeneralStateTestBase +{ + // Uncomment when EOF tests are merged + + // [TestCaseSource(nameof(LoadTests))] + // public void Test(GeneralStateTest test) + // { + // Assert.True(RunTest(test).Pass); + // } + + public static IEnumerable LoadTests() + { + var loader = new TestsSourceLoader(new LoadEipTestsStrategy(), "stEOF"); + return (IEnumerable)loader.LoadTests(); + } +} diff --git a/src/Nethermind/Ethereum.Blockchain.Test/Ethereum.Blockchain.Test.csproj b/src/Nethermind/Ethereum.Blockchain.Test/Ethereum.Blockchain.Test.csproj index 75390641e9e..6b3b7fdfc72 100644 --- a/src/Nethermind/Ethereum.Blockchain.Test/Ethereum.Blockchain.Test.csproj +++ b/src/Nethermind/Ethereum.Blockchain.Test/Ethereum.Blockchain.Test.csproj @@ -39,7 +39,7 @@ %(RecursiveDir)%(FileName)%(Extension) PreserveNewest - + %(RecursiveDir)%(FileName)%(Extension) PreserveNewest diff --git a/src/Nethermind/Ethereum.Test.Base/JsonToEthereumTest.cs b/src/Nethermind/Ethereum.Test.Base/JsonToEthereumTest.cs index b57baed7639..7795e25e3ff 100644 --- a/src/Nethermind/Ethereum.Test.Base/JsonToEthereumTest.cs +++ b/src/Nethermind/Ethereum.Test.Base/JsonToEthereumTest.cs @@ -36,6 +36,8 @@ private static IReleaseSpec ParseSpec(string network) network = network.Replace("Shanghai+3855", "Shanghai"); network = network.Replace("Shanghai+3860", "Shanghai"); network = network.Replace("Shanghai+6780", "Cancun"); + network = network.Replace("GrayGlacier+1153", "Cancun"); + network = network.Replace("Merge+1153", "Cancun"); return network switch { "Frontier" => Frontier.Instance, diff --git a/src/Nethermind/Ethereum.Test.Base/LoadEipTestsStrategy.cs b/src/Nethermind/Ethereum.Test.Base/LoadEipTestsStrategy.cs index 4953110d2d7..82b5f344d2c 100644 --- a/src/Nethermind/Ethereum.Test.Base/LoadEipTestsStrategy.cs +++ b/src/Nethermind/Ethereum.Test.Base/LoadEipTestsStrategy.cs @@ -39,7 +39,7 @@ private string GetGeneralStateTestsDirectory() char pathSeparator = Path.AltDirectorySeparatorChar; string currentDirectory = AppDomain.CurrentDomain.BaseDirectory; - return currentDirectory.Remove(currentDirectory.LastIndexOf("src")) + $"src{pathSeparator}tests{pathSeparator}EipTests{pathSeparator}StateTests"; + return currentDirectory.Remove(currentDirectory.LastIndexOf("src")) + $"src{pathSeparator}tests{pathSeparator}EIPTests{pathSeparator}StateTests"; } private IEnumerable LoadTestsFromDirectory(string testDir, string wildcard) diff --git a/src/tests b/src/tests index 9b00b68593f..ccb8a77534b 160000 --- a/src/tests +++ b/src/tests @@ -1 +1 @@ -Subproject commit 9b00b68593f5869eb51a6659e1cc983e875e616b +Subproject commit ccb8a77534be6dd43d7dc42d928b84516ff47e5f From 42ced705473c6536eff6b35c20b069fe8dee8954 Mon Sep 17 00:00:00 2001 From: Ayman Bouchareb Date: Wed, 13 Sep 2023 09:03:33 -0700 Subject: [PATCH 10/50] - update contract address (#6088) --- .../BeaconBlockRoot/BeaconBlockRootHandler.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Nethermind/Nethermind.Blockchain/BeaconBlockRoot/BeaconBlockRootHandler.cs b/src/Nethermind/Nethermind.Blockchain/BeaconBlockRoot/BeaconBlockRootHandler.cs index ec90a12f136..fdfd5024038 100644 --- a/src/Nethermind/Nethermind.Blockchain/BeaconBlockRoot/BeaconBlockRootHandler.cs +++ b/src/Nethermind/Nethermind.Blockchain/BeaconBlockRoot/BeaconBlockRootHandler.cs @@ -12,7 +12,7 @@ namespace Nethermind.Consensus.BeaconBlockRoot; public class BeaconBlockRootHandler : IBeaconBlockRootHandler { public static UInt256 HISTORICAL_ROOTS_LENGTH = 98304; - private static readonly Address DefaultPbbrContractAddress = Address.FromNumber(0x0b); + private static readonly Address DefaultPbbrContractAddress = new Address("0xbEac00dDB15f3B6d645C48263dC93862413A222D"); public void ApplyContractStateChanges(Block block, IReleaseSpec spec, IWorldState stateProvider) { From 249dbcfc44d28c9ca4f466c3f052b058bc22c807 Mon Sep 17 00:00:00 2001 From: Ayman Bouchareb Date: Wed, 13 Sep 2023 11:09:19 -0700 Subject: [PATCH 11/50] Activate Eip1153 updated hive tests (#5942) * decomment ethereum tests suite * remove comment * update tests submodule reference commit * fix tests inclusion * fix tests not loading * set tests submodule ref to HEAD * match path name to folder name * fix tests fixture name * added placeholders for upcoming tests * move tests submodule to HEAD * ws fix --- .../Ethereum.Blockchain.Test/Eip1153Tests.cs | 12 +++++------- .../Ethereum.Test.Base/JsonToEthereumTest.cs | 2 ++ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/Nethermind/Ethereum.Blockchain.Test/Eip1153Tests.cs b/src/Nethermind/Ethereum.Blockchain.Test/Eip1153Tests.cs index 924848f3ac2..056d80d94f0 100644 --- a/src/Nethermind/Ethereum.Blockchain.Test/Eip1153Tests.cs +++ b/src/Nethermind/Ethereum.Blockchain.Test/Eip1153Tests.cs @@ -11,13 +11,11 @@ namespace Ethereum.Blockchain.Test; [Parallelizable(ParallelScope.All)] public class EIP1153transientStorageTests : GeneralStateTestBase { - // Uncomment when Eip1153 tests are merged - - // [TestCaseSource(nameof(LoadTests))] - // public void Test(GeneralStateTest test) - // { - // Assert.True(RunTest(test).Pass); - // } + [TestCaseSource(nameof(LoadTests))] + public void Test(GeneralStateTest test) + { + Assert.True(RunTest(test).Pass); + } public static IEnumerable LoadTests() { diff --git a/src/Nethermind/Ethereum.Test.Base/JsonToEthereumTest.cs b/src/Nethermind/Ethereum.Test.Base/JsonToEthereumTest.cs index 7795e25e3ff..0d35a806141 100644 --- a/src/Nethermind/Ethereum.Test.Base/JsonToEthereumTest.cs +++ b/src/Nethermind/Ethereum.Test.Base/JsonToEthereumTest.cs @@ -35,6 +35,8 @@ private static IReleaseSpec ParseSpec(string network) network = network.Replace("Merge+3540+3670", "Shanghai"); network = network.Replace("Shanghai+3855", "Shanghai"); network = network.Replace("Shanghai+3860", "Shanghai"); + network = network.Replace("GrayGlacier+1153", "Cancun"); + network = network.Replace("Merge+1153", "Cancun"); network = network.Replace("Shanghai+6780", "Cancun"); network = network.Replace("GrayGlacier+1153", "Cancun"); network = network.Replace("Merge+1153", "Cancun"); From a1b701f427ab9d20026fa6cf5a228777ff894284 Mon Sep 17 00:00:00 2001 From: Ahmad Bitar <33181301+smartprogrammer93@users.noreply.github.com> Date: Fri, 15 Sep 2023 15:03:52 +0300 Subject: [PATCH 12/50] eip-7516: BLOBBASEFEE opcode added (#6096) --- .../UserOperationTracerTests.cs | 2 +- .../AABlockProducerTransactionsExecutor.cs | 9 +- .../Executor/UserOperationSimulator.cs | 5 +- .../Contract/ValidatorContractTests.cs | 3 +- .../Reward/AuRaRewardCalculatorTests.cs | 3 +- .../Validators/ContractBasedValidatorTests.cs | 9 +- .../TransactionsExecutorTests.cs | 3 +- .../Contracts/CallableContract.cs | 2 +- .../Contracts/Contract.cs | 4 +- .../Nethermind.Blockchain/GenesisLoader.cs | 2 +- ...sor.BlockProductionTransactionsExecutor.cs | 7 +- ...sor.BlockValidationTransactionsExecutor.cs | 8 +- .../TransactionProcessorAdapterExtensions.cs | 32 +++--- .../Nethermind.Core/Specs/IReleaseSpec.cs | 1 + .../BytecodeBuilderExtensionsTests.cs | 6 +- .../Nethermind.Evm.Test/CoinbaseTests.cs | 5 +- .../Nethermind.Evm.Test/Eip1153Tests.cs | 6 +- .../Eip3198BaseFeeTests.cs | 2 +- .../Nethermind.Evm.Test/Eip3588Tests.cs | 2 +- .../Nethermind.Evm.Test/Eip3651Tests.cs | 2 +- .../Nethermind.Evm.Test/Eip3860Tests.cs | 4 +- .../Nethermind.Evm.Test/Eip4844Tests.cs | 2 +- .../Eip7516BlobBaseFeeTests.cs | 55 +++++++++++ .../Nethermind.Evm.Test/InvalidOpcodeTests.cs | 3 +- .../Nethermind.Evm.Test/Keccak256Tests.cs | 7 +- .../Tracing/ParityLikeTxTracerTests.cs | 2 +- .../VirtualMachineTests.cs | 4 +- .../VirtualMachineTestsBase.cs | 97 ++++++++++++++----- .../Nethermind.Evm/BlockExecutionContext.cs | 33 +++++++ src/Nethermind/Nethermind.Evm/Instruction.cs | 1 + .../Nethermind.Evm/Tracing/GasEstimator.cs | 4 +- .../BuildUpTransactionProcessorAdapter.cs | 4 +- ...llAndRestoreTransactionProcessorAdapter.cs | 4 +- .../ChangeableTransactionProcessorAdapter.cs | 4 +- .../ExecuteTransactionProcessorAdapter.cs | 4 +- .../ITransactionProcessor.cs | 41 ++++---- .../ITransactionProcessorAdapter.cs | 2 +- .../ReadOnlyTransactionProcessor.cs | 16 +-- .../TraceTransactionProcessorAdapter.cs | 4 +- .../TransactionProcessor.cs | 25 ++--- .../Nethermind.Evm/TxExecutionContext.cs | 6 +- .../Nethermind.Evm/VirtualMachine.cs | 35 ++++--- .../BlockchainBridgeTests.cs | 13 +-- .../Nethermind.Facade/BlockchainBridge.cs | 2 +- .../JsonRpcSocketsClientTests.cs | 36 ++++--- .../Modules/BoundedModulePoolTests.cs | 8 +- .../MevBlockProductionTransactionsExecutor.cs | 19 ++-- 47 files changed, 359 insertions(+), 189 deletions(-) create mode 100644 src/Nethermind/Nethermind.Evm.Test/Eip7516BlobBaseFeeTests.cs create mode 100644 src/Nethermind/Nethermind.Evm/BlockExecutionContext.cs diff --git a/src/Nethermind/Nethermind.AccountAbstraction.Test/UserOperationTracerTests.cs b/src/Nethermind/Nethermind.AccountAbstraction.Test/UserOperationTracerTests.cs index dd376d2a128..595d76753fd 100644 --- a/src/Nethermind/Nethermind.AccountAbstraction.Test/UserOperationTracerTests.cs +++ b/src/Nethermind/Nethermind.AccountAbstraction.Test/UserOperationTracerTests.cs @@ -236,7 +236,7 @@ public void Should_allow_gas_only_if_followed_by_call(Instruction instruction, b { (Block block, Transaction transaction) = PrepareTx(BlockNumber, 100000, code, addresses, 0); UserOperationTxTracer tracer = new(paymasterWhitelisted, firstSimulation, TestItem.AddressA, TestItem.AddressB, TestItem.AddressD, NullLogger.Instance); - _processor.Execute(transaction, block.Header, tracer); + _processor.Execute(transaction, new BlockExecutionContext(block.Header), tracer); return (tracer, block, transaction); } diff --git a/src/Nethermind/Nethermind.AccountAbstraction/Executor/AABlockProducerTransactionsExecutor.cs b/src/Nethermind/Nethermind.AccountAbstraction/Executor/AABlockProducerTransactionsExecutor.cs index a9bdcb0f1c0..e3791db4b03 100644 --- a/src/Nethermind/Nethermind.AccountAbstraction/Executor/AABlockProducerTransactionsExecutor.cs +++ b/src/Nethermind/Nethermind.AccountAbstraction/Executor/AABlockProducerTransactionsExecutor.cs @@ -8,6 +8,7 @@ using Nethermind.Core; using Nethermind.Core.Collections; using Nethermind.Core.Specs; +using Nethermind.Evm; using Nethermind.Evm.Tracing; using Nethermind.Evm.TransactionProcessing; using Nethermind.Logging; @@ -50,16 +51,17 @@ public override TxReceipt[] ProcessTransactions( int i = 0; LinkedHashSet transactionsInBlock = new(ByHashTxComparer.Instance); + BlockExecutionContext blkCtx = new(block.Header); foreach (Transaction transaction in transactions) { if (IsAccountAbstractionTransaction(transaction)) { - BlockProcessor.TxAction action = ProcessAccountAbstractionTransaction(block, transaction, i++, receiptsTracer, processingOptions, transactionsInBlock); + BlockProcessor.TxAction action = ProcessAccountAbstractionTransaction(block, blkCtx, transaction, i++, receiptsTracer, processingOptions, transactionsInBlock); if (action == BlockProcessor.TxAction.Stop) break; } else { - BlockProcessor.TxAction action = ProcessTransaction(block, transaction, i++, receiptsTracer, processingOptions, transactionsInBlock); + BlockProcessor.TxAction action = ProcessTransaction(block, blkCtx, transaction, i++, receiptsTracer, processingOptions, transactionsInBlock); if (action == BlockProcessor.TxAction.Stop) break; } } @@ -79,6 +81,7 @@ private bool IsAccountAbstractionTransaction(Transaction transaction) private BlockProcessor.TxAction ProcessAccountAbstractionTransaction( Block block, + BlockExecutionContext blkCtx, Transaction currentTx, int index, BlockReceiptsTracer receiptsTracer, @@ -87,7 +90,7 @@ private BlockProcessor.TxAction ProcessAccountAbstractionTransaction( { int snapshot = receiptsTracer.TakeSnapshot(); - BlockProcessor.TxAction action = ProcessTransaction(block, currentTx, index, receiptsTracer, processingOptions, transactionsInBlock, false); + BlockProcessor.TxAction action = ProcessTransaction(block, blkCtx, currentTx, index, receiptsTracer, processingOptions, transactionsInBlock, false); if (action != BlockProcessor.TxAction.Add) { return action; diff --git a/src/Nethermind/Nethermind.AccountAbstraction/Executor/UserOperationSimulator.cs b/src/Nethermind/Nethermind.AccountAbstraction/Executor/UserOperationSimulator.cs index 37ed9593d29..a0e47c6b01b 100644 --- a/src/Nethermind/Nethermind.AccountAbstraction/Executor/UserOperationSimulator.cs +++ b/src/Nethermind/Nethermind.AccountAbstraction/Executor/UserOperationSimulator.cs @@ -15,6 +15,7 @@ using Nethermind.Core.Extensions; using Nethermind.Core.Specs; using Nethermind.Crypto; +using Nethermind.Evm; using Nethermind.Evm.Tracing; using Nethermind.Evm.TransactionProcessing; using Nethermind.Facade; @@ -127,7 +128,7 @@ private UserOperationSimulationResult SimulateValidation( _logger ); - transactionProcessor.Trace(transaction, parent, txTracer); + transactionProcessor.Trace(transaction, new BlockExecutionContext(parent), txTracer); FailedOp? failedOp = _userOperationTxBuilder.DecodeEntryPointOutputError(txTracer.Output); @@ -258,7 +259,7 @@ private void CallAndRestore( : blockHeader.BaseFeePerGas; transaction.Hash = transaction.CalculateHash(); - transactionProcessor.CallAndRestore(transaction, callHeader, tracer); + transactionProcessor.CallAndRestore(transaction, new BlockExecutionContext(callHeader), tracer); } } } diff --git a/src/Nethermind/Nethermind.AuRa.Test/Contract/ValidatorContractTests.cs b/src/Nethermind/Nethermind.AuRa.Test/Contract/ValidatorContractTests.cs index 49922c49b97..acf6647aecb 100644 --- a/src/Nethermind/Nethermind.AuRa.Test/Contract/ValidatorContractTests.cs +++ b/src/Nethermind/Nethermind.AuRa.Test/Contract/ValidatorContractTests.cs @@ -11,6 +11,7 @@ using Nethermind.Core.Test; using Nethermind.Core.Test.Builders; using Nethermind.Crypto; +using Nethermind.Evm; using Nethermind.Evm.Tracing; using Nethermind.Evm.TransactionProcessing; using Nethermind.Logging; @@ -81,7 +82,7 @@ public void finalize_change_should_call_correct_transaction() contract.FinalizeChange(_block.Header); _transactionProcessor.Received().Execute( - Arg.Is(t => IsEquivalentTo(expectation, t)), _block.Header, Arg.Any()); + Arg.Is(t => IsEquivalentTo(expectation, t)), Arg.Is(blkCtx => blkCtx.Header.Equals(_block.Header)), Arg.Any()); } private static bool IsEquivalentTo(Transaction expected, Transaction item) diff --git a/src/Nethermind/Nethermind.AuRa.Test/Reward/AuRaRewardCalculatorTests.cs b/src/Nethermind/Nethermind.AuRa.Test/Reward/AuRaRewardCalculatorTests.cs index bdad150cea4..417955c1ffe 100644 --- a/src/Nethermind/Nethermind.AuRa.Test/Reward/AuRaRewardCalculatorTests.cs +++ b/src/Nethermind/Nethermind.AuRa.Test/Reward/AuRaRewardCalculatorTests.cs @@ -19,6 +19,7 @@ using Nethermind.Int256; using NSubstitute; using NUnit.Framework; +using Nethermind.Evm; namespace Nethermind.AuRa.Test.Reward { @@ -197,7 +198,7 @@ private void SetupBlockRewards(IDictionary rewards) { _transactionProcessor.When(x => x.Execute( Arg.Is(t => CheckTransaction(t, rewards.Keys, _rewardData)), - _block.Header, + Arg.Is(blkCtx => blkCtx.Header.Equals(_block.Header)), Arg.Is(t => t is CallOutputTracer))) .Do(args => { diff --git a/src/Nethermind/Nethermind.AuRa.Test/Validators/ContractBasedValidatorTests.cs b/src/Nethermind/Nethermind.AuRa.Test/Validators/ContractBasedValidatorTests.cs index fc0b09911a4..4fdef5729d7 100644 --- a/src/Nethermind/Nethermind.AuRa.Test/Validators/ContractBasedValidatorTests.cs +++ b/src/Nethermind/Nethermind.AuRa.Test/Validators/ContractBasedValidatorTests.cs @@ -29,6 +29,7 @@ using NSubstitute; using NUnit.Framework; using BlockTree = Nethermind.Blockchain.BlockTree; +using Nethermind.Evm; namespace Nethermind.AuRa.Test.Validators { @@ -175,13 +176,13 @@ public void loads_initial_validators_from_contract(long blockNumber) _transactionProcessor.Received() .CallAndRestore( Arg.Is(t => CheckTransaction(t, _getValidatorsData)), - _parentHeader, + Arg.Is(blkCtx => blkCtx.Header.Equals(_parentHeader)), Arg.Is(t => t is CallOutputTracer)); // finalizeChange should be called _transactionProcessor.Received(finalizeChangeCalled ? 1 : 0) .Execute(Arg.Is(t => CheckTransaction(t, _finalizeChangeData)), - block.Header, + Arg.Is(blkCtx => blkCtx.Header.Equals(block.Header)), Arg.Is(t => t is CallOutputTracer)); // initial validator should be true @@ -594,7 +595,7 @@ private void ValidateFinalizationForChain(ConsecutiveInitiateChangeTestParameter // finalizeChange should be called or not based on test spec _transactionProcessor.Received(chain.ExpectedFinalizationCount) .Execute(Arg.Is(t => CheckTransaction(t, _finalizeChangeData)), - _block.Header, + Arg.Is(blkCtx => blkCtx.Header.Equals(_block.Header)), Arg.Is(t => t is CallOutputTracer)); _transactionProcessor.ClearReceivedCalls(); @@ -625,7 +626,7 @@ private void SetupInitialValidators(BlockHeader header, BlockHeader parentHeader _transactionProcessor.When(x => x.CallAndRestore( Arg.Is(t => CheckTransaction(t, _getValidatorsData)), - Arg.Any(), + Arg.Any(), Arg.Is(t => t is CallOutputTracer))) .Do(args => args.Arg().MarkAsSuccess( diff --git a/src/Nethermind/Nethermind.Blockchain.Test/TransactionsExecutorTests.cs b/src/Nethermind/Nethermind.Blockchain.Test/TransactionsExecutorTests.cs index 257c8eecf2b..f43d92ead95 100644 --- a/src/Nethermind/Nethermind.Blockchain.Test/TransactionsExecutorTests.cs +++ b/src/Nethermind/Nethermind.Blockchain.Test/TransactionsExecutorTests.cs @@ -14,6 +14,7 @@ using Nethermind.Core.Specs; using Nethermind.Core.Test.Builders; using Nethermind.Db; +using Nethermind.Evm; using Nethermind.Evm.Tracing; using Nethermind.Evm.TransactionProcessing; using Nethermind.Int256; @@ -270,7 +271,7 @@ public void Proper_transactions_selected(TransactionSelectorTests.ProperTransact specProvider.GetSpec(Arg.Any()).Returns(spec); ITransactionProcessor transactionProcessor = Substitute.For(); - transactionProcessor.When(t => t.BuildUp(Arg.Any(), Arg.Any(), Arg.Any())) + transactionProcessor.When(t => t.BuildUp(Arg.Any(), Arg.Any(), Arg.Any())) .Do(info => { Transaction tx = info.Arg(); diff --git a/src/Nethermind/Nethermind.Blockchain/Contracts/CallableContract.cs b/src/Nethermind/Nethermind.Blockchain/Contracts/CallableContract.cs index 41dff35a7c9..5d3964f7204 100644 --- a/src/Nethermind/Nethermind.Blockchain/Contracts/CallableContract.cs +++ b/src/Nethermind/Nethermind.Blockchain/Contracts/CallableContract.cs @@ -66,7 +66,7 @@ private bool TryCall(BlockHeader header, Transaction transaction, out byte[] res try { - _transactionProcessor.Execute(transaction, header, tracer); + _transactionProcessor.Execute(transaction, new BlockExecutionContext(header), tracer); result = tracer.ReturnValue; return tracer.StatusCode == StatusCode.Success; } diff --git a/src/Nethermind/Nethermind.Blockchain/Contracts/Contract.cs b/src/Nethermind/Nethermind.Blockchain/Contracts/Contract.cs index dfa733b619e..efb89e16a7f 100644 --- a/src/Nethermind/Nethermind.Blockchain/Contracts/Contract.cs +++ b/src/Nethermind/Nethermind.Blockchain/Contracts/Contract.cs @@ -178,11 +178,11 @@ protected byte[] CallCore(ITransactionProcessor transactionProcessor, BlockHeade { if (callAndRestore) { - transactionProcessor.CallAndRestore(transaction, header, tracer); + transactionProcessor.CallAndRestore(transaction, new BlockExecutionContext(header), tracer); } else { - transactionProcessor.Execute(transaction, header, tracer); + transactionProcessor.Execute(transaction, new BlockExecutionContext(header), tracer); } failure = tracer.StatusCode != StatusCode.Success; diff --git a/src/Nethermind/Nethermind.Blockchain/GenesisLoader.cs b/src/Nethermind/Nethermind.Blockchain/GenesisLoader.cs index 992376c0378..b135a4a04ae 100644 --- a/src/Nethermind/Nethermind.Blockchain/GenesisLoader.cs +++ b/src/Nethermind/Nethermind.Blockchain/GenesisLoader.cs @@ -87,7 +87,7 @@ private void Preallocate(Block genesis) }; CallOutputTracer outputTracer = new(); - _transactionProcessor.Execute(constructorTransaction, genesis.Header, outputTracer); + _transactionProcessor.Execute(constructorTransaction, new BlockExecutionContext(genesis.Header), outputTracer); if (outputTracer.StatusCode != StatusCode.Success) { diff --git a/src/Nethermind/Nethermind.Consensus/Processing/BlockProcessor.BlockProductionTransactionsExecutor.cs b/src/Nethermind/Nethermind.Consensus/Processing/BlockProcessor.BlockProductionTransactionsExecutor.cs index 05b11f9d7b7..44c6cdc58f0 100644 --- a/src/Nethermind/Nethermind.Consensus/Processing/BlockProcessor.BlockProductionTransactionsExecutor.cs +++ b/src/Nethermind/Nethermind.Consensus/Processing/BlockProcessor.BlockProductionTransactionsExecutor.cs @@ -7,6 +7,7 @@ using Nethermind.Core; using Nethermind.Core.Collections; using Nethermind.Core.Specs; +using Nethermind.Evm; using Nethermind.Evm.Tracing; using Nethermind.Evm.TransactionProcessing; using Nethermind.Logging; @@ -67,9 +68,10 @@ public virtual TxReceipt[] ProcessTransactions(Block block, ProcessingOptions pr int i = 0; LinkedHashSet transactionsInBlock = new(ByHashTxComparer.Instance); + BlockExecutionContext blkCtx = new(block.Header); foreach (Transaction currentTx in transactions) { - TxAction action = ProcessTransaction(block, currentTx, i++, receiptsTracer, processingOptions, transactionsInBlock); + TxAction action = ProcessTransaction(block, blkCtx, currentTx, i++, receiptsTracer, processingOptions, transactionsInBlock); if (action == TxAction.Stop) break; } @@ -81,6 +83,7 @@ public virtual TxReceipt[] ProcessTransactions(Block block, ProcessingOptions pr protected TxAction ProcessTransaction( Block block, + BlockExecutionContext blkCtx, Transaction currentTx, int index, BlockReceiptsTracer receiptsTracer, @@ -96,7 +99,7 @@ protected TxAction ProcessTransaction( } else { - _transactionProcessor.ProcessTransaction(block, currentTx, receiptsTracer, processingOptions, _stateProvider); + _transactionProcessor.ProcessTransaction(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 958043cadc9..116ba87a90c 100644 --- a/src/Nethermind/Nethermind.Consensus/Processing/BlockProcessor.BlockValidationTransactionsExecutor.cs +++ b/src/Nethermind/Nethermind.Consensus/Processing/BlockProcessor.BlockValidationTransactionsExecutor.cs @@ -5,6 +5,7 @@ using System.Linq; using Nethermind.Core; using Nethermind.Core.Specs; +using Nethermind.Evm; using Nethermind.Evm.Tracing; using Nethermind.Evm.TransactionProcessing; using Nethermind.State; @@ -34,17 +35,18 @@ public BlockValidationTransactionsExecutor(ITransactionProcessorAdapter transact public TxReceipt[] ProcessTransactions(Block block, ProcessingOptions processingOptions, BlockReceiptsTracer receiptsTracer, IReleaseSpec spec) { Evm.Metrics.ResetBlockStats(); + BlockExecutionContext blkCtx = new(block.Header); for (int i = 0; i < block.Transactions.Length; i++) { Transaction currentTx = block.Transactions[i]; - ProcessTransaction(block, currentTx, i, receiptsTracer, processingOptions); + ProcessTransaction(blkCtx, currentTx, i, receiptsTracer, processingOptions); } return receiptsTracer.TxReceipts.ToArray(); } - private void ProcessTransaction(Block block, Transaction currentTx, int index, BlockReceiptsTracer receiptsTracer, ProcessingOptions processingOptions) + private void ProcessTransaction(BlockExecutionContext blkCtx, Transaction currentTx, int index, BlockReceiptsTracer receiptsTracer, ProcessingOptions processingOptions) { - _transactionProcessor.ProcessTransaction(block, currentTx, receiptsTracer, processingOptions, _stateProvider); + _transactionProcessor.ProcessTransaction(blkCtx, currentTx, receiptsTracer, processingOptions, _stateProvider); TransactionProcessed?.Invoke(this, new TxProcessedEventArgs(index, currentTx, receiptsTracer.TxReceipts[index])); } } diff --git a/src/Nethermind/Nethermind.Consensus/Processing/TransactionProcessorAdapterExtensions.cs b/src/Nethermind/Nethermind.Consensus/Processing/TransactionProcessorAdapterExtensions.cs index d00b2b4fdf2..b8f6ae446f4 100644 --- a/src/Nethermind/Nethermind.Consensus/Processing/TransactionProcessorAdapterExtensions.cs +++ b/src/Nethermind/Nethermind.Consensus/Processing/TransactionProcessorAdapterExtensions.cs @@ -2,29 +2,29 @@ // SPDX-License-Identifier: LGPL-3.0-only using Nethermind.Core; +using Nethermind.Evm; using Nethermind.Evm.Tracing; using Nethermind.Evm.TransactionProcessing; using Nethermind.State; -namespace Nethermind.Consensus.Processing +namespace Nethermind.Consensus.Processing; + +internal static class TransactionProcessorAdapterExtensions { - internal static class TransactionProcessorAdapterExtensions + public static void ProcessTransaction(this ITransactionProcessorAdapter transactionProcessor, + BlockExecutionContext blkCtx, + Transaction currentTx, + BlockReceiptsTracer receiptsTracer, + ProcessingOptions processingOptions, + IWorldState stateProvider) { - public static void ProcessTransaction(this ITransactionProcessorAdapter transactionProcessor, - Block block, - Transaction currentTx, - BlockReceiptsTracer receiptsTracer, - ProcessingOptions processingOptions, - IWorldState stateProvider) + if (processingOptions.ContainsFlag(ProcessingOptions.DoNotVerifyNonce)) { - if (processingOptions.ContainsFlag(ProcessingOptions.DoNotVerifyNonce)) - { - currentTx.Nonce = stateProvider.GetNonce(currentTx.SenderAddress); - } - - receiptsTracer.StartNewTxTrace(currentTx); - transactionProcessor.Execute(currentTx, block.Header, receiptsTracer); - receiptsTracer.EndTxTrace(); + currentTx.Nonce = stateProvider.GetNonce(currentTx.SenderAddress); } + + receiptsTracer.StartNewTxTrace(currentTx); + transactionProcessor.Execute(currentTx, blkCtx, receiptsTracer); + receiptsTracer.EndTxTrace(); } } diff --git a/src/Nethermind/Nethermind.Core/Specs/IReleaseSpec.cs b/src/Nethermind/Nethermind.Core/Specs/IReleaseSpec.cs index 6a170b29b07..f7e8519de72 100644 --- a/src/Nethermind/Nethermind.Core/Specs/IReleaseSpec.cs +++ b/src/Nethermind/Nethermind.Core/Specs/IReleaseSpec.cs @@ -360,5 +360,6 @@ public interface IReleaseSpec : IEip1559Spec, IReceiptSpec public bool IsBeaconBlockRootAvailable => IsEip4788Enabled; public bool MCopyIncluded => IsEip5656Enabled; + public bool BlobBaseFeeEnabled => IsEip4844Enabled; } } diff --git a/src/Nethermind/Nethermind.Evm.Test/BytecodeBuilderExtensionsTests.cs b/src/Nethermind/Nethermind.Evm.Test/BytecodeBuilderExtensionsTests.cs index decba85b0b5..7c6ffef480b 100644 --- a/src/Nethermind/Nethermind.Evm.Test/BytecodeBuilderExtensionsTests.cs +++ b/src/Nethermind/Nethermind.Evm.Test/BytecodeBuilderExtensionsTests.cs @@ -99,8 +99,6 @@ public static IEnumerable opcodes_with_0_arg() Instruction.PC, Instruction.JUMPDEST, Instruction.MSIZE, - Instruction.BEGINSUB, - Instruction.RETURNSUB, Instruction.INVALID, Instruction.SWAP1, Instruction.SWAP5, Instruction.SWAP9 , Instruction.SWAP13, @@ -159,8 +157,7 @@ public static IEnumerable opcodes_with_1_arg() Instruction.JUMP, Instruction.SLOAD, Instruction.TLOAD, - Instruction.MLOAD, - Instruction.JUMPSUB, + Instruction.MLOAD }; foreach (Instruction opcode in address_opcodes) @@ -213,7 +210,6 @@ public static IEnumerable opcodes_with_2_arg() Instruction.MSTORE, Instruction.BYTE, Instruction.MSTORE8, - Instruction.TSTORE, Instruction.SSTORE, Instruction.JUMPI }; diff --git a/src/Nethermind/Nethermind.Evm.Test/CoinbaseTests.cs b/src/Nethermind/Nethermind.Evm.Test/CoinbaseTests.cs index fbead389dd6..1bfe7c2aee7 100644 --- a/src/Nethermind/Nethermind.Evm.Test/CoinbaseTests.cs +++ b/src/Nethermind/Nethermind.Evm.Test/CoinbaseTests.cs @@ -5,6 +5,7 @@ using Nethermind.Specs; using Nethermind.Core.Test.Builders; using NUnit.Framework; +using Nethermind.Core.Specs; namespace Nethermind.Evm.Test { @@ -15,10 +16,10 @@ public class CoinbaseTests : VirtualMachineTestsBase private bool _setAuthor; - protected override Block BuildBlock(long blockNumber, SenderRecipientAndMiner senderRecipientAndMiner, Transaction transaction, long blockGasLimit = DefaultBlockGasLimit, ulong timestamp = 0) + protected override Block BuildBlock(ForkActivation activation, SenderRecipientAndMiner senderRecipientAndMiner, Transaction transaction, long blockGasLimit = DefaultBlockGasLimit, ulong exessBlobGas = 0) { senderRecipientAndMiner ??= new SenderRecipientAndMiner(); - Block block = base.BuildBlock(blockNumber, senderRecipientAndMiner, transaction, blockGasLimit, timestamp); + Block block = base.BuildBlock(activation, senderRecipientAndMiner, transaction, blockGasLimit); if (_setAuthor) block.Header.Author = TestItem.AddressC; block.Header.Beneficiary = senderRecipientAndMiner.Recipient; return block; diff --git a/src/Nethermind/Nethermind.Evm.Test/Eip1153Tests.cs b/src/Nethermind/Nethermind.Evm.Test/Eip1153Tests.cs index c18d1799ff0..f908d1638a2 100644 --- a/src/Nethermind/Nethermind.Evm.Test/Eip1153Tests.cs +++ b/src/Nethermind/Nethermind.Evm.Test/Eip1153Tests.cs @@ -42,14 +42,14 @@ public void before_activation_can_not_call_tstore_tload() .StoreDataInTransientStorage(1, 8) .Done; - TestAllTracerWithOutput result = Execute(MainnetSpecProvider.GrayGlacierBlockNumber, 100000, code, timestamp: MainnetSpecProvider.CancunBlockTimestamp - 1); + TestAllTracerWithOutput result = Execute((MainnetSpecProvider.GrayGlacierBlockNumber, MainnetSpecProvider.CancunBlockTimestamp - 1), 100000, code); Assert.That(result.StatusCode, Is.EqualTo(StatusCode.Failure)); code = Prepare.EvmCode .LoadDataFromTransientStorage(1) .Done; - result = Execute(MainnetSpecProvider.GrayGlacierBlockNumber, 100000, code, timestamp: MainnetSpecProvider.CancunBlockTimestamp - 1); + result = Execute((MainnetSpecProvider.GrayGlacierBlockNumber, MainnetSpecProvider.CancunBlockTimestamp - 1), 100000, code); Assert.That(result.StatusCode, Is.EqualTo(StatusCode.Failure)); } @@ -93,7 +93,7 @@ public void transient_storage_performance_test() byte[] code = prepare.Done; stopwatch.Start(); - TestAllTracerWithOutput result = Execute(MainnetSpecProvider.GrayGlacierBlockNumber, blockGasLimit, code, blockGasLimit, Timestamp); + TestAllTracerWithOutput result = Execute((MainnetSpecProvider.GrayGlacierBlockNumber, Timestamp), blockGasLimit, code, blockGasLimit); Assert.That(result.StatusCode, Is.EqualTo(StatusCode.Success)); stopwatch.Stop(); Assert.IsTrue(stopwatch.ElapsedMilliseconds < 5000); diff --git a/src/Nethermind/Nethermind.Evm.Test/Eip3198BaseFeeTests.cs b/src/Nethermind/Nethermind.Evm.Test/Eip3198BaseFeeTests.cs index 0f3455410ce..6b20654a11f 100644 --- a/src/Nethermind/Nethermind.Evm.Test/Eip3198BaseFeeTests.cs +++ b/src/Nethermind/Nethermind.Evm.Test/Eip3198BaseFeeTests.cs @@ -34,7 +34,7 @@ public void Base_fee_opcode_should_return_expected_results(bool eip3198Enabled, .Done; long blockNumber = eip3198Enabled ? MainnetSpecProvider.LondonBlockNumber : MainnetSpecProvider.LondonBlockNumber - 1; - (Block block, Transaction transaction) = PrepareTx(blockNumber, 100000, code); + (Block block, Transaction transaction) = PrepareTx((blockNumber, 0), 100000, code); block.Header.BaseFeePerGas = (UInt256)baseFee; if (send1559Tx) { diff --git a/src/Nethermind/Nethermind.Evm.Test/Eip3588Tests.cs b/src/Nethermind/Nethermind.Evm.Test/Eip3588Tests.cs index 5d074c64769..8dc5e60f093 100644 --- a/src/Nethermind/Nethermind.Evm.Test/Eip3588Tests.cs +++ b/src/Nethermind/Nethermind.Evm.Test/Eip3588Tests.cs @@ -23,7 +23,7 @@ private TestAllTracerWithOutput testBase(int repeat, bool isShanghai) } byte[] code = codeInitializer.Done; - TestAllTracerWithOutput receipt = Execute(BlockNumber, 1_000_000, code, timestamp: timestampParam); + TestAllTracerWithOutput receipt = Execute((BlockNumber, timestampParam), 1_000_000, code); return receipt; } diff --git a/src/Nethermind/Nethermind.Evm.Test/Eip3651Tests.cs b/src/Nethermind/Nethermind.Evm.Test/Eip3651Tests.cs index f81a2b17532..6d9fe4c1248 100644 --- a/src/Nethermind/Nethermind.Evm.Test/Eip3651Tests.cs +++ b/src/Nethermind/Nethermind.Evm.Test/Eip3651Tests.cs @@ -39,7 +39,7 @@ public void Access_beneficiary_address_before_eip_3651() .Op(Instruction.BALANCE) .Op(Instruction.POP) .Done; - TestAllTracerWithOutput result = Execute(BlockNumber, 100000, code, timestamp: Timestamp - 1); + TestAllTracerWithOutput result = Execute((BlockNumber, Timestamp - 1), 100000, code); result.StatusCode.Should().Be(1); AssertGas(result, GasCostOf.Transaction + 2605); } diff --git a/src/Nethermind/Nethermind.Evm.Test/Eip3860Tests.cs b/src/Nethermind/Nethermind.Evm.Test/Eip3860Tests.cs index b6b98209c7b..377a40460f1 100644 --- a/src/Nethermind/Nethermind.Evm.Test/Eip3860Tests.cs +++ b/src/Nethermind/Nethermind.Evm.Test/Eip3860Tests.cs @@ -37,7 +37,7 @@ public void Test_EIP_3860_GasCost_Create(string createCode, bool eip3860Enabled, byte[] callCode = Prepare.EvmCode.Call(TestItem.AddressC, 100000).Done; - var tracer = Execute(BlockNumber, eip3860Enabled ? Timestamp : Timestamp - 1, callCode); + var tracer = Execute((BlockNumber, eip3860Enabled ? Timestamp : Timestamp - 1), callCode); Assert.That(tracer.StatusCode, Is.EqualTo(StatusCode.Success)); Assert.That(tracer.GasSpent - _transactionCallCost, Is.EqualTo(expectedGasUsage)); } @@ -102,7 +102,7 @@ protected TestAllTracerWithOutput PrepExecuteCreateTransaction(ulong timestamp, TestState.CreateAccount(TestItem.AddressC, 1.Ether()); - (Block block, Transaction transaction) = PrepareTx(BlockNumber, 500000, createCode, timestamp: timestamp); + (Block block, Transaction transaction) = PrepareTx((BlockNumber, timestamp), 500000, createCode); transaction.GasPrice = 2.GWei(); transaction.To = null; diff --git a/src/Nethermind/Nethermind.Evm.Test/Eip4844Tests.cs b/src/Nethermind/Nethermind.Evm.Test/Eip4844Tests.cs index 250a891c35f..3f9cdffdfe3 100644 --- a/src/Nethermind/Nethermind.Evm.Test/Eip4844Tests.cs +++ b/src/Nethermind/Nethermind.Evm.Test/Eip4844Tests.cs @@ -43,7 +43,7 @@ public void Test_blobhash_index_in_range(int index, int blobhashesCount) .Return(32, 0) .Done; - TestAllTracerWithOutput result = Execute(BlockNumber, 50000, code, blobVersionedHashes: hashes, timestamp: Timestamp); + TestAllTracerWithOutput result = Execute(Activation, 50000, code, blobVersionedHashes: hashes); result.StatusCode.Should().Be(StatusCode.Success); result.ReturnValue.SequenceEqual(expectedOutput); diff --git a/src/Nethermind/Nethermind.Evm.Test/Eip7516BlobBaseFeeTests.cs b/src/Nethermind/Nethermind.Evm.Test/Eip7516BlobBaseFeeTests.cs new file mode 100644 index 00000000000..1a1036de336 --- /dev/null +++ b/src/Nethermind/Nethermind.Evm.Test/Eip7516BlobBaseFeeTests.cs @@ -0,0 +1,55 @@ +// SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited +// SPDX-License-Identifier: LGPL-3.0-only + +using FluentAssertions; +using Nethermind.Core; +using Nethermind.Core.Specs; +using Nethermind.Evm.TransactionProcessing; +using Nethermind.Int256; +using Nethermind.Logging; +using Nethermind.Specs; +using NUnit.Framework; + +namespace Nethermind.Evm.Test; + +public class Eip7516BlobBaseFeeTests : VirtualMachineTestsBase +{ + + [TestCase(true, 0ul)] + [TestCase(true, 100ul)] + [TestCase(true, 20ul)] + [TestCase(false, 20ul)] + [TestCase(false, 0ul)] + [TestCase(true, 0ul)] + [TestCase(true, 100ul)] + [TestCase(true, 20ul)] + [TestCase(false, 20ul)] + [TestCase(false, 0ul)] + public void Blob_Base_fee_opcode_should_return_expected_results(bool eip7516Enabled, ulong excessBlobGas) + { + _processor = new TransactionProcessor(SpecProvider, TestState, Machine, LimboLogs.Instance); + byte[] code = Prepare.EvmCode + .Op(Instruction.BLOBBASEFEE) + .PushData(0) + .Op(Instruction.SSTORE) + .Done; + + ForkActivation activation = eip7516Enabled ? MainnetSpecProvider.CancunActivation : MainnetSpecProvider.ShanghaiActivation; + (Block block, Transaction transaction) = PrepareTx(activation, 100000, code); + block.Header.ExcessBlobGas = excessBlobGas; + + TestAllTracerWithOutput tracer = CreateTracer(); + _processor.Execute(transaction, block.Header, tracer); + + _ = BlobGasCalculator.TryCalculateBlobGasPricePerUnit(excessBlobGas, out UInt256 expectedGasPrice); + if (eip7516Enabled) + { + AssertStorage((UInt256)0, expectedGasPrice); + } + else + { + tracer.Error.Should().Be(EvmExceptionType.BadInstruction.ToString()); + AssertStorage((UInt256)0, (UInt256)0); + } + } +} diff --git a/src/Nethermind/Nethermind.Evm.Test/InvalidOpcodeTests.cs b/src/Nethermind/Nethermind.Evm.Test/InvalidOpcodeTests.cs index 61b0e750c86..395a5c7fe8a 100644 --- a/src/Nethermind/Nethermind.Evm.Test/InvalidOpcodeTests.cs +++ b/src/Nethermind/Nethermind.Evm.Test/InvalidOpcodeTests.cs @@ -108,6 +108,7 @@ public class InvalidOpcodeTests : VirtualMachineTestsBase Instruction.TLOAD, Instruction.MCOPY, Instruction.BLOBHASH, + Instruction.BLOBBASEFEE } ).ToArray(); @@ -164,7 +165,7 @@ public void Test(long blockNumber, ulong? timestamp = null) .Done; bool isValidOpcode = ((Instruction)i != Instruction.INVALID) && validOpcodes.Contains((Instruction)i); - TestAllTracerWithOutput result = Execute(blockNumber, 1_000_000, code, timestamp: timestamp ?? 0); + TestAllTracerWithOutput result = Execute((blockNumber, timestamp ?? 0), 1_000_000, code); if (isValidOpcode) { diff --git a/src/Nethermind/Nethermind.Evm.Test/Keccak256Tests.cs b/src/Nethermind/Nethermind.Evm.Test/Keccak256Tests.cs index abfa2d0b7dc..282671a9a86 100644 --- a/src/Nethermind/Nethermind.Evm.Test/Keccak256Tests.cs +++ b/src/Nethermind/Nethermind.Evm.Test/Keccak256Tests.cs @@ -5,6 +5,7 @@ using Nethermind.Specs; using Nethermind.Core.Test.Builders; using NUnit.Framework; +using Nethermind.Core.Specs; namespace Nethermind.Evm.Test { @@ -16,9 +17,9 @@ public class Keccak256Tests : VirtualMachineTestsBase private bool _setAuthor; - protected override Block BuildBlock(long blockNumber, SenderRecipientAndMiner senderRecipientAndMiner, Transaction transaction, long blockGasLimit = DefaultBlockGasLimit, ulong timestamp = 0) + protected override Block BuildBlock(ForkActivation activation, SenderRecipientAndMiner senderRecipientAndMiner, Transaction transaction, long blockGasLimit = DefaultBlockGasLimit, ulong excessBlobGas = 0) { - Block block = base.BuildBlock(blockNumber, senderRecipientAndMiner, transaction, blockGasLimit, timestamp); + Block block = base.BuildBlock(activation, senderRecipientAndMiner, transaction, blockGasLimit, excessBlobGas); if (_setAuthor) block.Header.Author = TestItem.AddressC; block.Header.Beneficiary = TestItem.AddressB; return block; @@ -39,7 +40,7 @@ public void Spin_sha3() .Op(Instruction.JUMP) .Done; - TestAllTracerWithOutput receipt = Execute(8000000, 8000000, code); + TestAllTracerWithOutput receipt = Execute((8000000, 0), 8000000, code); AssertGas(receipt, 8000000); } diff --git a/src/Nethermind/Nethermind.Evm.Test/Tracing/ParityLikeTxTracerTests.cs b/src/Nethermind/Nethermind.Evm.Test/Tracing/ParityLikeTxTracerTests.cs index 68c2bf6d0b6..a49df9e8e1f 100644 --- a/src/Nethermind/Nethermind.Evm.Test/Tracing/ParityLikeTxTracerTests.cs +++ b/src/Nethermind/Nethermind.Evm.Test/Tracing/ParityLikeTxTracerTests.cs @@ -814,7 +814,7 @@ public void Is_tracing_rewards_only_when_rewards_trace_type_selected() private (ParityLikeTxTrace trace, Block block, Transaction tx) ExecuteInitAndTraceParityCall(params byte[] code) { - (Block block, Transaction transaction) = PrepareInitTx(BlockNumber, 100000, code); + (Block block, Transaction transaction) = PrepareInitTx((BlockNumber, Timestamp), 100000, code); ParityLikeTxTracer tracer = new(block, transaction, ParityTraceTypes.Trace | ParityTraceTypes.StateDiff); _processor.Execute(transaction, block.Header, tracer); return (tracer.BuildResult(), block, transaction); diff --git a/src/Nethermind/Nethermind.Evm.Test/VirtualMachineTests.cs b/src/Nethermind/Nethermind.Evm.Test/VirtualMachineTests.cs index 4bb0efb5aca..baa5d866b0a 100644 --- a/src/Nethermind/Nethermind.Evm.Test/VirtualMachineTests.cs +++ b/src/Nethermind/Nethermind.Evm.Test/VirtualMachineTests.cs @@ -423,7 +423,7 @@ public void Tload() .Op(Instruction.TLOAD) .Done; - TestAllTracerWithOutput receipt = Execute(MainnetSpecProvider.GrayGlacierBlockNumber, 100000, code, timestamp: MainnetSpecProvider.CancunBlockTimestamp); + TestAllTracerWithOutput receipt = Execute((MainnetSpecProvider.GrayGlacierBlockNumber, MainnetSpecProvider.CancunBlockTimestamp), 100000, code); Assert.That(receipt.GasSpent, Is.EqualTo(GasCostOf.Transaction + GasCostOf.VeryLow * 1 + GasCostOf.TLoad), "gas"); } @@ -542,7 +542,7 @@ public void Tstore() .Op(Instruction.TSTORE) .Done; - TestAllTracerWithOutput receipt = Execute(MainnetSpecProvider.GrayGlacierBlockNumber, 100000, code, timestamp: MainnetSpecProvider.CancunBlockTimestamp); + TestAllTracerWithOutput receipt = Execute((MainnetSpecProvider.GrayGlacierBlockNumber, MainnetSpecProvider.CancunBlockTimestamp), 100000, code); Assert.That(receipt.GasSpent, Is.EqualTo(GasCostOf.Transaction + GasCostOf.VeryLow * 2 + GasCostOf.TStore), "gas"); } diff --git a/src/Nethermind/Nethermind.Evm.Test/VirtualMachineTestsBase.cs b/src/Nethermind/Nethermind.Evm.Test/VirtualMachineTestsBase.cs index b21efa0478f..0a902722594 100644 --- a/src/Nethermind/Nethermind.Evm.Test/VirtualMachineTestsBase.cs +++ b/src/Nethermind/Nethermind.Evm.Test/VirtualMachineTestsBase.cs @@ -44,10 +44,11 @@ public class VirtualMachineTestsBase protected static PrivateKey RecipientKey { get; } = TestItem.PrivateKeyB; protected static PrivateKey MinerKey { get; } = TestItem.PrivateKeyD; + protected virtual ForkActivation Activation => (BlockNumber, Timestamp); protected virtual long BlockNumber { get; } = MainnetSpecProvider.ByzantiumBlockNumber; protected virtual ulong Timestamp => 0UL; protected virtual ISpecProvider SpecProvider => MainnetSpecProvider.Instance; - protected IReleaseSpec Spec => SpecProvider.GetSpec(BlockNumber, Timestamp); + protected IReleaseSpec Spec => SpecProvider.GetSpec(Activation); protected virtual ILogManager GetLogManager() { @@ -72,7 +73,7 @@ public virtual void Setup() protected GethLikeTxTrace ExecuteAndTrace(params byte[] code) { GethLikeTxMemoryTracer tracer = new(GethTraceOptions.Default with { EnableMemory = true }); - (Block block, Transaction transaction) = PrepareTx(BlockNumber, 100000, code); + (Block block, Transaction transaction) = PrepareTx(Activation, 100000, code); _processor.Execute(transaction, block.Header, tracer); return tracer.BuildResult(); } @@ -80,7 +81,7 @@ protected GethLikeTxTrace ExecuteAndTrace(params byte[] code) protected GethLikeTxTrace ExecuteAndTrace(long blockNumber, long gasLimit, params byte[] code) { GethLikeTxMemoryTracer tracer = new(GethTraceOptions.Default); - (Block block, Transaction transaction) = PrepareTx(blockNumber, gasLimit, code); + (Block block, Transaction transaction) = PrepareTx((blockNumber, Timestamp), gasLimit, code); _processor.Execute(transaction, block.Header, tracer); return tracer.BuildResult(); } @@ -88,14 +89,22 @@ protected GethLikeTxTrace ExecuteAndTrace(long blockNumber, long gasLimit, param protected GethLikeTxTrace ExecuteAndTraceToFile(Action dumpCallback, byte[] code, GethTraceOptions options) { GethLikeTxFileTracer tracer = new(dumpCallback, options); - (Block block, Transaction transaction) = PrepareTx(BlockNumber, 100000, code); + (Block block, Transaction transaction) = PrepareTx(Activation, 100000, code); _processor.Execute(transaction, block.Header, tracer); return tracer.BuildResult(); } - protected TestAllTracerWithOutput Execute(long blockNumber, ulong timestamp, params byte[] code) + /// + /// deprecated. Please use activation instead of blockNumber. + /// + protected TestAllTracerWithOutput Execute(long blockNumber, params byte[] code) { - (Block block, Transaction transaction) = PrepareTx(blockNumber, 100000, code, timestamp: timestamp); + return Execute((blockNumber, Timestamp), code); + } + + protected TestAllTracerWithOutput Execute(ForkActivation activation, params byte[] code) + { + (Block block, Transaction transaction) = PrepareTx(activation, 100000, code); TestAllTracerWithOutput tracer = CreateTracer(); _processor.Execute(transaction, block.Header, tracer); return tracer; @@ -103,28 +112,44 @@ protected TestAllTracerWithOutput Execute(long blockNumber, ulong timestamp, par protected TestAllTracerWithOutput Execute(params byte[] code) { - return Execute(BlockNumber, Timestamp, code); + return Execute(Activation, code); } protected virtual TestAllTracerWithOutput CreateTracer() => new(); protected T Execute(T tracer, byte[] code, ForkActivation? forkActivation = null) where T : ITxTracer { - (Block block, Transaction transaction) = PrepareTx(forkActivation?.BlockNumber ?? BlockNumber, 100000, code, timestamp: forkActivation?.Timestamp ?? Timestamp); + (Block block, Transaction transaction) = PrepareTx(forkActivation ?? Activation, 100000, code); _processor.Execute(transaction, block.Header, tracer); return tracer; } + /// + /// deprecated. Please use activation instead of blockNumber. + /// protected TestAllTracerWithOutput Execute(long blockNumber, long gasLimit, byte[] code, - long blockGasLimit = DefaultBlockGasLimit, ulong timestamp = 0, byte[][] blobVersionedHashes = null) + long blockGasLimit = DefaultBlockGasLimit, byte[][] blobVersionedHashes = null) { - (Block block, Transaction transaction) = PrepareTx(blockNumber, gasLimit, code, - blockGasLimit: blockGasLimit, timestamp: timestamp, blobVersionedHashes: blobVersionedHashes); + (Block block, Transaction transaction) = PrepareTx((blockNumber, Timestamp), gasLimit, code, + blockGasLimit: blockGasLimit, blobVersionedHashes: blobVersionedHashes); TestAllTracerWithOutput tracer = CreateTracer(); _processor.Execute(transaction, block.Header, tracer); return tracer; } + protected TestAllTracerWithOutput Execute(ForkActivation activation, long gasLimit, byte[] code, + long blockGasLimit = DefaultBlockGasLimit, byte[][] blobVersionedHashes = null) + { + (Block block, Transaction transaction) = PrepareTx(activation, gasLimit, code, + blockGasLimit: blockGasLimit, blobVersionedHashes: blobVersionedHashes); + TestAllTracerWithOutput tracer = CreateTracer(); + _processor.Execute(transaction, block.Header, tracer); + return tracer; + } + + /// + /// deprecated. Please use activation instead of blockNumber. + /// protected (Block block, Transaction transaction) PrepareTx( long blockNumber, long gasLimit, @@ -132,8 +157,21 @@ protected TestAllTracerWithOutput Execute(long blockNumber, long gasLimit, byte[ SenderRecipientAndMiner? senderRecipientAndMiner = null, int value = 1, long blockGasLimit = DefaultBlockGasLimit, - ulong timestamp = 0, - byte[][]? blobVersionedHashes = null) + byte[][]? blobVersionedHashes = null, + ulong excessBlobGas = 0) + { + return PrepareTx((blockNumber, Timestamp), gasLimit, code, senderRecipientAndMiner, value, blockGasLimit, blobVersionedHashes, excessBlobGas); + } + + protected (Block block, Transaction transaction) PrepareTx( + ForkActivation activation, + long gasLimit, + byte[]? code = null, + SenderRecipientAndMiner? senderRecipientAndMiner = null, + int value = 1, + long blockGasLimit = DefaultBlockGasLimit, + byte[][]? blobVersionedHashes = null, + ulong excessBlobGas = 0) { senderRecipientAndMiner ??= SenderRecipientAndMiner.Default; @@ -173,12 +211,21 @@ protected TestAllTracerWithOutput Execute(long blockNumber, long gasLimit, byte[ .SignedAndResolved(_ethereumEcdsa, senderRecipientAndMiner.SenderKey) .TestObject; - Block block = BuildBlock(blockNumber, senderRecipientAndMiner, transaction, blockGasLimit, timestamp); + Block block = BuildBlock(activation, senderRecipientAndMiner, transaction, blockGasLimit, excessBlobGas); return (block, transaction); } + /// + /// deprecated. Please use activation instead of blockNumber. + /// protected (Block block, Transaction transaction) PrepareTx(long blockNumber, long gasLimit, byte[] code, byte[] input, UInt256 value, SenderRecipientAndMiner senderRecipientAndMiner = null) + { + return PrepareTx((blockNumber, Timestamp), gasLimit, code, input, value, senderRecipientAndMiner); + } + + protected (Block block, Transaction transaction) PrepareTx(ForkActivation activation, long gasLimit, byte[] code, + byte[] input, UInt256 value, SenderRecipientAndMiner senderRecipientAndMiner = null) { senderRecipientAndMiner ??= SenderRecipientAndMiner.Default; @@ -209,11 +256,11 @@ protected TestAllTracerWithOutput Execute(long blockNumber, long gasLimit, byte[ .SignedAndResolved(_ethereumEcdsa, senderRecipientAndMiner.SenderKey) .TestObject; - Block block = BuildBlock(blockNumber, senderRecipientAndMiner); + Block block = BuildBlock(activation, senderRecipientAndMiner); return (block, transaction); } - protected (Block block, Transaction transaction) PrepareInitTx(long blockNumber, long gasLimit, byte[] code, + protected (Block block, Transaction transaction) PrepareInitTx(ForkActivation activation, long gasLimit, byte[] code, SenderRecipientAndMiner senderRecipientAndMiner = null) { senderRecipientAndMiner ??= SenderRecipientAndMiner.Default; @@ -228,28 +275,28 @@ protected TestAllTracerWithOutput Execute(long blockNumber, long gasLimit, byte[ .SignedAndResolved(_ethereumEcdsa, senderRecipientAndMiner.SenderKey) .TestObject; - Block block = BuildBlock(blockNumber, senderRecipientAndMiner); + Block block = BuildBlock(activation, senderRecipientAndMiner); return (block, transaction); } - protected Block BuildBlock(long blockNumber, SenderRecipientAndMiner senderRecipientAndMiner) + protected Block BuildBlock(ForkActivation activation, SenderRecipientAndMiner senderRecipientAndMiner) { - return BuildBlock(blockNumber, senderRecipientAndMiner, null); + return BuildBlock(activation, senderRecipientAndMiner, null); } - protected virtual Block BuildBlock(long blockNumber, SenderRecipientAndMiner senderRecipientAndMiner, - Transaction tx, long blockGasLimit = DefaultBlockGasLimit, - ulong timestamp = 0) + protected virtual Block BuildBlock(ForkActivation activation, SenderRecipientAndMiner senderRecipientAndMiner, + Transaction tx, long blockGasLimit = DefaultBlockGasLimit, ulong excessBlobGas = 0) { senderRecipientAndMiner ??= SenderRecipientAndMiner.Default; - return Build.A.Block.WithNumber(blockNumber) - .WithTransactions(tx is null ? new Transaction[0] : new[] { tx }) + return Build.A.Block.WithNumber(activation.BlockNumber) + .WithTimestamp(activation.Timestamp ?? 0) + .WithTransactions(tx is null ? Array.Empty() : new[] { tx }) .WithGasLimit(blockGasLimit) .WithBeneficiary(senderRecipientAndMiner.Miner) .WithBlobGasUsed(0) .WithExcessBlobGas(0) - .WithTimestamp(timestamp) .WithParentBeaconBlockRoot(TestItem.KeccakG) + .WithExcessBlobGas(excessBlobGas) .TestObject; } diff --git a/src/Nethermind/Nethermind.Evm/BlockExecutionContext.cs b/src/Nethermind/Nethermind.Evm/BlockExecutionContext.cs new file mode 100644 index 00000000000..759dc5ee04f --- /dev/null +++ b/src/Nethermind/Nethermind.Evm/BlockExecutionContext.cs @@ -0,0 +1,33 @@ +// SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited +// SPDX-License-Identifier: LGPL-3.0-only + +using System; +using Nethermind.Core; +using Nethermind.Int256; + +namespace Nethermind.Evm; + +public readonly struct BlockExecutionContext +{ + public BlockHeader Header { get; } + public UInt256? BlobBaseFee { get; } + + public BlockExecutionContext(BlockHeader blockHeader) + { + Header = blockHeader; + if (blockHeader?.ExcessBlobGas is not null) + { + if (!BlobGasCalculator.TryCalculateBlobGasPricePerUnit(blockHeader.ExcessBlobGas.Value, out UInt256 blobBaseFeeResult)) + { + throw new OverflowException("Blob gas price calculation led to overflow."); + } + BlobBaseFee = blobBaseFeeResult; + } + } + + public static implicit operator BlockExecutionContext(BlockHeader header) + { + return new BlockExecutionContext(header); + } + +} diff --git a/src/Nethermind/Nethermind.Evm/Instruction.cs b/src/Nethermind/Nethermind.Evm/Instruction.cs index 23fca24f163..1b82f66113e 100644 --- a/src/Nethermind/Nethermind.Evm/Instruction.cs +++ b/src/Nethermind/Nethermind.Evm/Instruction.cs @@ -67,6 +67,7 @@ public enum Instruction : byte SELFBALANCE = 0x47, BASEFEE = 0x48, BLOBHASH = 0x49, + BLOBBASEFEE = 0x4a, POP = 0x50, MLOAD = 0x51, diff --git a/src/Nethermind/Nethermind.Evm/Tracing/GasEstimator.cs b/src/Nethermind/Nethermind.Evm/Tracing/GasEstimator.cs index 2015aaf4834..f9e24d2c1d7 100644 --- a/src/Nethermind/Nethermind.Evm/Tracing/GasEstimator.cs +++ b/src/Nethermind/Nethermind.Evm/Tracing/GasEstimator.cs @@ -87,7 +87,9 @@ private bool TryExecutableTransaction(Transaction transaction, BlockHeader block long originalGasLimit = transaction.GasLimit; transaction.GasLimit = gasLimit; - _transactionProcessor.CallAndRestore(transaction, block, tracer.WithCancellation(token)); + + BlockExecutionContext blCtx = new(block); + _transactionProcessor.CallAndRestore(transaction, 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 6c66de2e7ba..3583b6480b9 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, BlockHeader block, ITxTracer txTracer) => - _transactionProcessor.BuildUp(transaction, block, txTracer); + public void Execute(Transaction transaction, BlockExecutionContext blkCtx, ITxTracer txTracer) => + _transactionProcessor.BuildUp(transaction, blkCtx, txTracer); } } diff --git a/src/Nethermind/Nethermind.Evm/TransactionProcessing/CallAndRestoreTransactionProcessorAdapter.cs b/src/Nethermind/Nethermind.Evm/TransactionProcessing/CallAndRestoreTransactionProcessorAdapter.cs index 8ede3451467..7042c9337a1 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, BlockHeader block, ITxTracer txTracer) => - _transactionProcessor.CallAndRestore(transaction, block, txTracer); + public void Execute(Transaction transaction, BlockExecutionContext blkCtx, ITxTracer txTracer) => + _transactionProcessor.CallAndRestore(transaction, blkCtx, txTracer); } } diff --git a/src/Nethermind/Nethermind.Evm/TransactionProcessing/ChangeableTransactionProcessorAdapter.cs b/src/Nethermind/Nethermind.Evm/TransactionProcessing/ChangeableTransactionProcessorAdapter.cs index bc8948b8bba..231950c656c 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, BlockHeader block, ITxTracer txTracer) + public void Execute(Transaction transaction, BlockExecutionContext blkCtx, ITxTracer txTracer) { - CurrentAdapter.Execute(transaction, block, txTracer); + CurrentAdapter.Execute(transaction, blkCtx, txTracer); } } } diff --git a/src/Nethermind/Nethermind.Evm/TransactionProcessing/ExecuteTransactionProcessorAdapter.cs b/src/Nethermind/Nethermind.Evm/TransactionProcessing/ExecuteTransactionProcessorAdapter.cs index c9f144a7b3f..2b4967dd3cd 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, BlockHeader block, ITxTracer txTracer) => - _transactionProcessor.Execute(transaction, block, txTracer); + public void Execute(Transaction transaction, BlockExecutionContext blkCtx, ITxTracer txTracer) => + _transactionProcessor.Execute(transaction, blkCtx, txTracer); } } diff --git a/src/Nethermind/Nethermind.Evm/TransactionProcessing/ITransactionProcessor.cs b/src/Nethermind/Nethermind.Evm/TransactionProcessing/ITransactionProcessor.cs index 7d8ec18031a..972ac5be1d8 100644 --- a/src/Nethermind/Nethermind.Evm/TransactionProcessing/ITransactionProcessor.cs +++ b/src/Nethermind/Nethermind.Evm/TransactionProcessing/ITransactionProcessor.cs @@ -4,29 +4,28 @@ using Nethermind.Core; using Nethermind.Evm.Tracing; -namespace Nethermind.Evm.TransactionProcessing +namespace Nethermind.Evm.TransactionProcessing; + +public interface ITransactionProcessor { - public interface ITransactionProcessor - { - /// - /// Execute transaction, commit state - /// - void Execute(Transaction transaction, BlockHeader block, ITxTracer txTracer); + /// + /// Execute transaction, commit state + /// + void Execute(Transaction transaction, BlockExecutionContext blCtx, ITxTracer txTracer); - /// - /// Call transaction, rollback state - /// - void CallAndRestore(Transaction transaction, BlockHeader block, ITxTracer txTracer); + /// + /// Call transaction, rollback state + /// + void CallAndRestore(Transaction transaction, BlockExecutionContext blCtx, ITxTracer txTracer); - /// - /// Execute transaction, keep the state uncommitted - /// - void BuildUp(Transaction transaction, BlockHeader block, ITxTracer txTracer); + /// + /// Execute transaction, keep the state uncommitted + /// + void BuildUp(Transaction transaction, 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, BlockHeader block, 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); } diff --git a/src/Nethermind/Nethermind.Evm/TransactionProcessing/ITransactionProcessorAdapter.cs b/src/Nethermind/Nethermind.Evm/TransactionProcessing/ITransactionProcessorAdapter.cs index a502c273267..06ab48f127e 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, BlockHeader block, ITxTracer txTracer); + void Execute(Transaction transaction, BlockExecutionContext blkCtx, ITxTracer txTracer); } } diff --git a/src/Nethermind/Nethermind.Evm/TransactionProcessing/ReadOnlyTransactionProcessor.cs b/src/Nethermind/Nethermind.Evm/TransactionProcessing/ReadOnlyTransactionProcessor.cs index a61ff37e813..55b484af884 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, BlockHeader block, ITxTracer txTracer) => - _transactionProcessor.Execute(transaction, block, txTracer); + public void Execute(Transaction transaction, BlockExecutionContext blCtx, ITxTracer txTracer) => + _transactionProcessor.Execute(transaction, blCtx, txTracer); - public void CallAndRestore(Transaction transaction, BlockHeader block, ITxTracer txTracer) => - _transactionProcessor.CallAndRestore(transaction, block, txTracer); + public void CallAndRestore(Transaction transaction, BlockExecutionContext blCtx, ITxTracer txTracer) => + _transactionProcessor.CallAndRestore(transaction, blCtx, txTracer); - public void BuildUp(Transaction transaction, BlockHeader block, ITxTracer txTracer) => - _transactionProcessor.BuildUp(transaction, block, txTracer); + public void BuildUp(Transaction transaction, BlockExecutionContext blCtx, ITxTracer txTracer) => + _transactionProcessor.BuildUp(transaction, blCtx, txTracer); - public void Trace(Transaction transaction, BlockHeader block, ITxTracer txTracer) => - _transactionProcessor.Trace(transaction, block, txTracer); + public void Trace(Transaction transaction, BlockExecutionContext blCtx, ITxTracer txTracer) => + _transactionProcessor.Trace(transaction, 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 7ae895330fa..3b51b89ccee 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, BlockHeader block, ITxTracer txTracer) => - _transactionProcessor.Trace(transaction, block, txTracer); + public void Execute(Transaction transaction, BlockExecutionContext blkCtx, ITxTracer txTracer) => + _transactionProcessor.Trace(transaction, blkCtx, txTracer); } } diff --git a/src/Nethermind/Nethermind.Evm/TransactionProcessing/TransactionProcessor.cs b/src/Nethermind/Nethermind.Evm/TransactionProcessing/TransactionProcessor.cs index da259dd9a1a..5ee2d4f5181 100644 --- a/src/Nethermind/Nethermind.Evm/TransactionProcessing/TransactionProcessor.cs +++ b/src/Nethermind/Nethermind.Evm/TransactionProcessing/TransactionProcessor.cs @@ -72,31 +72,32 @@ public TransactionProcessor( _ecdsa = new EthereumEcdsa(specProvider.ChainId, logManager); } - public void CallAndRestore(Transaction transaction, BlockHeader block, ITxTracer txTracer) + public void CallAndRestore(Transaction transaction, BlockExecutionContext blCtx, ITxTracer txTracer) { - Execute(transaction, block, txTracer, ExecutionOptions.CommitAndRestore); + Execute(transaction, blCtx, txTracer, ExecutionOptions.CommitAndRestore); } - public void BuildUp(Transaction transaction, BlockHeader block, ITxTracer txTracer) + public void BuildUp(Transaction transaction, 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, block, txTracer, ExecutionOptions.None); + Execute(transaction, blCtx, txTracer, ExecutionOptions.None); } - public void Execute(Transaction transaction, BlockHeader block, ITxTracer txTracer) + public void Execute(Transaction transaction, BlockExecutionContext blCtx, ITxTracer txTracer) { - Execute(transaction, block, txTracer, ExecutionOptions.Commit); + Execute(transaction, blCtx, txTracer, ExecutionOptions.Commit); } - public void Trace(Transaction transaction, BlockHeader block, ITxTracer txTracer) + public void Trace(Transaction transaction, BlockExecutionContext blCtx, ITxTracer txTracer) { - Execute(transaction, block, txTracer, ExecutionOptions.NoValidation); + Execute(transaction, blCtx, txTracer, ExecutionOptions.NoValidation); } - protected virtual void Execute(Transaction tx, BlockHeader header, ITxTracer tracer, ExecutionOptions opts) + protected virtual void Execute(Transaction tx, BlockExecutionContext blCtx, ITxTracer tracer, ExecutionOptions opts) { + BlockHeader header = blCtx.Header; IReleaseSpec spec = _specProvider.GetSpec(header); if (tx.IsSystem()) spec = new SystemTransactionReleaseSpec(spec); @@ -146,7 +147,7 @@ protected virtual void Execute(Transaction tx, BlockHeader header, ITxTracer tra if (commit) _worldState.Commit(spec, tracer.IsTracingState ? tracer : NullTxTracer.Instance); - ExecutionEnvironment env = BuildExecutionEnvironmnet(tx, header, spec, tracer, opts, effectiveGasPrice); + ExecutionEnvironment env = BuildExecutionEnvironmnet(tx, 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)) @@ -432,7 +433,7 @@ protected virtual bool IncrementNonce(Transaction tx, BlockHeader header, IRelea } protected virtual ExecutionEnvironment BuildExecutionEnvironmnet( - Transaction tx, BlockHeader header, IReleaseSpec spec, ITxTracer tracer, ExecutionOptions opts, + Transaction tx, BlockExecutionContext blCtx, IReleaseSpec spec, ITxTracer tracer, ExecutionOptions opts, in UInt256 effectiveGasPrice) { Address recipient = tx.GetRecipient(tx.IsContractCreation ? _worldState.GetNonce(tx.SenderAddress) : 0) ?? @@ -440,7 +441,7 @@ protected virtual ExecutionEnvironment BuildExecutionEnvironmnet( throw new InvalidDataException("Recipient has not been resolved properly before tx execution"); TxExecutionContext executionContext = - new(header, tx.SenderAddress, effectiveGasPrice, tx.BlobVersionedHashes); + new(blCtx, tx.SenderAddress, effectiveGasPrice, tx.BlobVersionedHashes); CodeInfo codeInfo = tx.IsContractCreation ? new(tx.Data.AsArray()) : _virtualMachine.GetCachedCodeInfo(_worldState, recipient, spec); diff --git a/src/Nethermind/Nethermind.Evm/TxExecutionContext.cs b/src/Nethermind/Nethermind.Evm/TxExecutionContext.cs index 427655f536b..2e00bddb906 100644 --- a/src/Nethermind/Nethermind.Evm/TxExecutionContext.cs +++ b/src/Nethermind/Nethermind.Evm/TxExecutionContext.cs @@ -8,14 +8,14 @@ namespace Nethermind.Evm { public readonly struct TxExecutionContext { - public BlockHeader Header { get; } + public readonly BlockExecutionContext BlockExecutionContext; public Address Origin { get; } public UInt256 GasPrice { get; } public byte[][]? BlobVersionedHashes { get; } - public TxExecutionContext(BlockHeader blockHeader, Address origin, in UInt256 gasPrice, byte[][] blobVersionedHashes) + public TxExecutionContext(BlockExecutionContext blockExecutionContext, Address origin, in UInt256 gasPrice, byte[][] blobVersionedHashes) { - Header = blockHeader; + BlockExecutionContext = blockExecutionContext; Origin = origin; GasPrice = gasPrice; BlobVersionedHashes = blobVersionedHashes; diff --git a/src/Nethermind/Nethermind.Evm/VirtualMachine.cs b/src/Nethermind/Nethermind.Evm/VirtualMachine.cs index b0236578ddc..7b22ee795b4 100644 --- a/src/Nethermind/Nethermind.Evm/VirtualMachine.cs +++ b/src/Nethermind/Nethermind.Evm/VirtualMachine.cs @@ -185,7 +185,7 @@ public TransactionSubstate Run(EvmState state, IWorldState worl _state = worldState; _worldState = worldState; - IReleaseSpec spec = _specProvider.GetSpec(state.Env.TxExecutionContext.Header.Number, state.Env.TxExecutionContext.Header.Timestamp); + IReleaseSpec spec = _specProvider.GetSpec(state.Env.TxExecutionContext.BlockExecutionContext.Header.Number, state.Env.TxExecutionContext.BlockExecutionContext.Header.Timestamp); EvmState currentState = state; byte[] previousCallResult = null; ZeroPaddedSpan previousCallOutput = ZeroPaddedSpan.Empty; @@ -777,6 +777,7 @@ private CallResult ExecuteCode code = env.CodeInfo.MachineCode.AsSpan(); EvmExceptionType exceptionType = EvmExceptionType.None; bool isRevert = false; @@ -1437,7 +1438,7 @@ private CallResult ExecuteCode long.MaxValue ? long.MaxValue : (long)a; - Keccak blockHash = _blockhashProvider.GetBlockhash(txCtx.Header, number); + Keccak blockHash = _blockhashProvider.GetBlockhash(blkCtx.Header, number); stack.PushBytes(blockHash != null ? blockHash.Bytes : BytesZero32); if (typeof(TLogger) == typeof(IsTracing)) @@ -1454,20 +1455,20 @@ private CallResult ExecuteCode( outputOffset = 0; } - ExecutionType executionType = GetCallExecutionType(instruction, env.TxExecutionContext.Header.IsPostMerge); + ExecutionType executionType = GetCallExecutionType(instruction, env.TxExecutionContext.BlockExecutionContext.Header.IsPostMerge); returnData = new EvmState( gasLimitUl, callEnv, @@ -2771,7 +2782,7 @@ private static bool Jump(in UInt256 jumpDest, ref int programCounter, in Executi private void StartInstructionTrace(Instruction instruction, EvmState vmState, long gasAvailable, int programCounter, in EvmStack stackValue) where TIsTracing : struct, IIsTracing { - _txTracer.StartOperation(vmState.Env.CallDepth + 1, gasAvailable, instruction, programCounter, vmState.Env.TxExecutionContext.Header.IsPostMerge); + _txTracer.StartOperation(vmState.Env.CallDepth + 1, gasAvailable, instruction, programCounter, vmState.Env.TxExecutionContext.BlockExecutionContext.Header.IsPostMerge); if (_txTracer.IsTracingMemory) { _txTracer.SetOperationMemory(vmState.Memory?.GetTrace() ?? Enumerable.Empty()); diff --git a/src/Nethermind/Nethermind.Facade.Test/BlockchainBridgeTests.cs b/src/Nethermind/Nethermind.Facade.Test/BlockchainBridgeTests.cs index c4920012481..c25373a8f74 100644 --- a/src/Nethermind/Nethermind.Facade.Test/BlockchainBridgeTests.cs +++ b/src/Nethermind/Nethermind.Facade.Test/BlockchainBridgeTests.cs @@ -132,8 +132,8 @@ public void Estimate_gas_returns_the_estimate_from_the_tracer() _transactionProcessor.Received().CallAndRestore( tx, - Arg.Is(bh => - bh.Number == 11 && bh.Timestamp == ((ITimestamper)_timestamper).UnixTime.Seconds), + Arg.Is(blkCtx => + blkCtx.Header.Number == 11 && blkCtx.Header.Timestamp == ((ITimestamper)_timestamper).UnixTime.Seconds), Arg.Is(t => t.InnerTracer is EstimateGasTracer)); } @@ -150,7 +150,8 @@ public void Call_uses_valid_post_merge_and_random_value() _blockchainBridge.Call(header, tx, CancellationToken.None); _transactionProcessor.Received().CallAndRestore( tx, - Arg.Is(header => header.IsPostMerge && header.Random == TestItem.KeccakA), + Arg.Is(blkCtx => + blkCtx.Header.IsPostMerge && blkCtx.Header.Random == TestItem.KeccakA), Arg.Any()); } @@ -165,7 +166,7 @@ public void Call_uses_valid_block_number() _blockchainBridge.Call(header, tx, CancellationToken.None); _transactionProcessor.Received().CallAndRestore( tx, - Arg.Is(bh => bh.Number == 10), + Arg.Is(blkCtx => blkCtx.Header.Number == 10), Arg.Any()); } @@ -180,7 +181,7 @@ public void Call_uses_valid_mix_hash() _blockchainBridge.Call(header, tx, CancellationToken.None); _transactionProcessor.Received().CallAndRestore( tx, - Arg.Is(bh => bh.MixHash == TestItem.KeccakA), + Arg.Is(blkCtx => blkCtx.Header.MixHash == TestItem.KeccakA), Arg.Any()); } @@ -195,7 +196,7 @@ public void Call_uses_valid_beneficiary() _blockchainBridge.Call(header, tx, CancellationToken.None); _transactionProcessor.Received().CallAndRestore( tx, - Arg.Is(bh => bh.Beneficiary == TestItem.AddressB), + Arg.Is(blkCtx => blkCtx.Header.Beneficiary == TestItem.AddressB), Arg.Any()); } diff --git a/src/Nethermind/Nethermind.Facade/BlockchainBridge.cs b/src/Nethermind/Nethermind.Facade/BlockchainBridge.cs index 5b8495bde0d..810376364c1 100644 --- a/src/Nethermind/Nethermind.Facade/BlockchainBridge.cs +++ b/src/Nethermind/Nethermind.Facade/BlockchainBridge.cs @@ -278,7 +278,7 @@ private void CallAndRestore( callHeader.MixHash = blockHeader.MixHash; callHeader.IsPostMerge = blockHeader.Difficulty == 0; transaction.Hash = transaction.CalculateHash(); - transactionProcessor.CallAndRestore(transaction, callHeader, tracer); + transactionProcessor.CallAndRestore(transaction, new(callHeader), tracer); } public ulong GetChainId() diff --git a/src/Nethermind/Nethermind.JsonRpc.Test/JsonRpcSocketsClientTests.cs b/src/Nethermind/Nethermind.JsonRpc.Test/JsonRpcSocketsClientTests.cs index 993d86f8ccc..247bdc64d29 100644 --- a/src/Nethermind/Nethermind.JsonRpc.Test/JsonRpcSocketsClientTests.cs +++ b/src/Nethermind/Nethermind.JsonRpc.Test/JsonRpcSocketsClientTests.cs @@ -32,17 +32,17 @@ public async Task Can_handle_very_large_objects() Task receiveBytes = OneShotServer( ipEndPoint, - async socket => await CountNumberOfBytes(socket) + CountNumberOfBytes ); JsonRpcSuccessResponse bigObject = RandomSuccessResponse(200_000); Task sendJsonRpcResult = Task.Run(async () => { - using Socket socket = new Socket(ipEndPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp); + using Socket socket = new(ipEndPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp); await socket.ConnectAsync(ipEndPoint); ISocketHandler handler = new IpcSocketsHandler(socket); - JsonRpcSocketsClient client = new JsonRpcSocketsClient( + JsonRpcSocketsClient client = new( clientName: "TestClient", handler: handler, endpointType: RpcEndpoint.IPC, @@ -63,6 +63,7 @@ public async Task Can_handle_very_large_objects() } [Test] + [Retry(5)] [TestCase(2)] [TestCase(10)] [TestCase(50)] @@ -72,16 +73,16 @@ public async Task Can_send_multiple_messages(int messageCount) Task receiveBytes = OneShotServer( ipEndPoint, - async socket => await CountNumberOfBytes(socket) + CountNumberOfBytes ); Task sendJsonRpcResult = Task.Run(async () => { - using Socket socket = new Socket(ipEndPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp); + using Socket socket = new(ipEndPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp); await socket.ConnectAsync(ipEndPoint); ISocketHandler handler = new IpcSocketsHandler(socket); - JsonRpcSocketsClient client = new JsonRpcSocketsClient( + JsonRpcSocketsClient client = new( clientName: "TestClient", handler: handler, endpointType: RpcEndpoint.IPC, @@ -107,6 +108,7 @@ public async Task Can_send_multiple_messages(int messageCount) Assert.That(sent, Is.EqualTo(received)); } + [Retry(5)] [TestCase(2)] [TestCase(10)] [TestCase(50)] @@ -116,16 +118,16 @@ public async Task Can_send_collections(int elements) Task receiveBytes = OneShotServer( ipEndPoint, - async socket => await CountNumberOfBytes(socket) + CountNumberOfBytes ); Task sendCollection = Task.Run(async () => { - using Socket socket = new Socket(ipEndPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp); + using Socket socket = new(ipEndPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp); await socket.ConnectAsync(ipEndPoint); ISocketHandler handler = new IpcSocketsHandler(socket); - JsonRpcSocketsClient client = new JsonRpcSocketsClient( + JsonRpcSocketsClient client = new( clientName: "TestClient", handler: handler, endpointType: RpcEndpoint.IPC, @@ -147,7 +149,7 @@ public async Task Can_send_collections(int elements) private static async Task OneShotServer(IPEndPoint ipEndPoint, Func> func) { - using Socket socket = new Socket(ipEndPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp); + using Socket socket = new(ipEndPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp); socket.Bind(ipEndPoint); socket.Listen(); @@ -173,6 +175,7 @@ private static async Task CountNumberOfBytes(Socket socket) public class UsingWebSockets { [Test] + [Retry(5)] [TestCase(2)] [TestCase(10)] [TestCase(50)] @@ -187,11 +190,11 @@ public async Task Can_send_multiple_messages(int messageCount) Task sendMessages = Task.Run(async () => { - using ClientWebSocket socket = new ClientWebSocket(); + using ClientWebSocket socket = new(); await socket.ConnectAsync(new Uri("ws://localhost:1337/"), CancellationToken.None); using ISocketHandler handler = new WebSocketHandler(socket, NullLogManager.Instance); - using JsonRpcSocketsClient client = new JsonRpcSocketsClient( + using JsonRpcSocketsClient client = new( clientName: "TestClient", handler: handler, endpointType: RpcEndpoint.Ws, @@ -218,6 +221,7 @@ public async Task Can_send_multiple_messages(int messageCount) Assert.That(sent, Is.EqualTo(received)); } + [Retry(5)] [TestCase(2)] [TestCase(10)] [TestCase(50)] @@ -232,11 +236,11 @@ public async Task Can_send_collections(int elements) Task sendCollection = Task.Run(async () => { - using ClientWebSocket socket = new ClientWebSocket(); + using ClientWebSocket socket = new(); await socket.ConnectAsync(new Uri("ws://localhost:1337/"), CancellationToken.None); using ISocketHandler handler = new WebSocketHandler(socket, NullLogManager.Instance); - using JsonRpcSocketsClient client = new JsonRpcSocketsClient( + using JsonRpcSocketsClient client = new( clientName: "TestClient", handler: handler, endpointType: RpcEndpoint.Ws, @@ -272,11 +276,11 @@ public async Task Stops_on_limited_body_size(int maxByteCount) Task sendCollection = Task.Run(async () => { - using ClientWebSocket socket = new ClientWebSocket(); + using ClientWebSocket socket = new(); await socket.ConnectAsync(new Uri("ws://localhost:1337/"), CancellationToken.None); using ISocketHandler handler = new WebSocketHandler(socket, NullLogManager.Instance); - using JsonRpcSocketsClient client = new JsonRpcSocketsClient( + using JsonRpcSocketsClient client = new( clientName: "TestClient", handler: handler, endpointType: RpcEndpoint.Ws, diff --git a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/BoundedModulePoolTests.cs b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/BoundedModulePoolTests.cs index 03f68c05199..4cb4e61e2f6 100644 --- a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/BoundedModulePoolTests.cs +++ b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/BoundedModulePoolTests.cs @@ -104,11 +104,11 @@ async Task rentReturnShared() { for (int i = 0; i < iterations; i++) { - TestContext.Out.WriteLine($"Rent shared {i}"); + // TestContext.Out.WriteLine($"Rent shared {i}"); IEthRpcModule ethRpcModule = await _modulePool.GetModule(true); Assert.That(ethRpcModule, Is.SameAs(sharedRpcModule)); _modulePool.ReturnModule(ethRpcModule); - TestContext.Out.WriteLine($"Return shared {i}"); + // TestContext.Out.WriteLine($"Return shared {i}"); } } @@ -116,11 +116,11 @@ async Task rentReturnExclusive() { for (int i = 0; i < iterations; i++) { - TestContext.Out.WriteLine($"Rent exclusive {i}"); + // TestContext.Out.WriteLine($"Rent exclusive {i}"); IEthRpcModule ethRpcModule = await _modulePool.GetModule(false); Assert.That(ethRpcModule, Is.Not.SameAs(sharedRpcModule)); _modulePool.ReturnModule(ethRpcModule); - TestContext.Out.WriteLine($"Return exclusive {i}"); + // TestContext.Out.WriteLine($"Return exclusive {i}"); } } diff --git a/src/Nethermind/Nethermind.Mev/MevBlockProductionTransactionsExecutor.cs b/src/Nethermind/Nethermind.Mev/MevBlockProductionTransactionsExecutor.cs index f0582000f77..d0bb75b435e 100644 --- a/src/Nethermind/Nethermind.Mev/MevBlockProductionTransactionsExecutor.cs +++ b/src/Nethermind/Nethermind.Mev/MevBlockProductionTransactionsExecutor.cs @@ -8,6 +8,7 @@ using Nethermind.Core.Collections; using Nethermind.Core.Crypto; using Nethermind.Core.Specs; +using Nethermind.Evm; using Nethermind.Evm.Tracing; using Nethermind.Evm.TransactionProcessing; using Nethermind.Int256; @@ -53,7 +54,7 @@ public override TxReceipt[] ProcessTransactions(Block block, ProcessingOptions p LinkedHashSet transactionsInBlock = new(ByHashTxComparer.Instance); List bundleTransactions = new(); Keccak? bundleHash = null; - + BlockExecutionContext blkCtx = new(block.Header); foreach (Transaction currentTx in transactions) { // if we don't accumulate bundle yet @@ -69,7 +70,7 @@ public override TxReceipt[] ProcessTransactions(Block block, ProcessingOptions p else { // otherwise process transaction as usual - TxAction action = ProcessTransaction(block, currentTx, transactionsInBlock.Count, receiptsTracer, processingOptions, transactionsInBlock); + TxAction action = ProcessTransaction(block, blkCtx, currentTx, transactionsInBlock.Count, receiptsTracer, processingOptions, transactionsInBlock); if (action == TxAction.Stop) break; } } @@ -89,7 +90,7 @@ public override TxReceipt[] ProcessTransactions(Block block, ProcessingOptions p else { // process accumulated bundle - TxAction action = ProcessBundle(block, bundleTransactions, transactionsInBlock, receiptsTracer, processingOptions); + TxAction action = ProcessBundle(block, blkCtx, bundleTransactions, transactionsInBlock, receiptsTracer, processingOptions); if (action == TxAction.Stop) break; // start accumulating new bundle @@ -102,11 +103,11 @@ public override TxReceipt[] ProcessTransactions(Block block, ProcessingOptions p { // process the bundle and stop accumulating it bundleHash = null; - TxAction action = ProcessBundle(block, bundleTransactions, transactionsInBlock, receiptsTracer, processingOptions); + TxAction action = ProcessBundle(block, blkCtx, bundleTransactions, transactionsInBlock, receiptsTracer, processingOptions); if (action == TxAction.Stop) break; // process normal transaction - action = ProcessTransaction(block, currentTx, transactionsInBlock.Count, receiptsTracer, processingOptions, transactionsInBlock); + action = ProcessTransaction(block, blkCtx, currentTx, transactionsInBlock.Count, receiptsTracer, processingOptions, transactionsInBlock); if (action == TxAction.Stop) break; } } @@ -114,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, bundleTransactions, transactionsInBlock, receiptsTracer, processingOptions); + ProcessBundle(block, blkCtx, bundleTransactions, transactionsInBlock, receiptsTracer, processingOptions); } _stateProvider.Commit(spec, receiptsTracer); @@ -124,6 +125,7 @@ public override TxReceipt[] ProcessTransactions(Block block, ProcessingOptions p } private TxAction ProcessBundle(Block block, + BlockExecutionContext blkCtx, List bundleTransactions, LinkedHashSet transactionsInBlock, BlockReceiptsTracer receiptsTracer, @@ -147,7 +149,7 @@ bool CheckFeeNotManipulated() TxAction txAction = TxAction.Skip; for (int index = 0; index < bundleTransactions.Count && bundleSucceeded; index++) { - txAction = ProcessBundleTransaction(block, bundleTransactions[index], index, receiptsTracer, processingOptions, transactionsInBlock); + txAction = ProcessBundleTransaction(block, 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 @@ -186,13 +188,14 @@ bool CheckFeeNotManipulated() private TxAction ProcessBundleTransaction( Block block, + BlockExecutionContext blkCtx, BundleTransaction currentTx, int index, BlockReceiptsTracer receiptsTracer, ProcessingOptions processingOptions, LinkedHashSet transactionsInBlock) { - TxAction action = ProcessTransaction(block, currentTx, index, receiptsTracer, processingOptions, transactionsInBlock, false); + TxAction action = ProcessTransaction(block, blkCtx, currentTx, index, receiptsTracer, processingOptions, transactionsInBlock, false); if (action == TxAction.Add) { string? error = receiptsTracer.LastReceipt.Error; From 62c784719915d424626fa60bba3ec663073bccfe Mon Sep 17 00:00:00 2001 From: Lautaro Emanuel <31224949+emlautarom1@users.noreply.github.com> Date: Fri, 15 Sep 2023 11:30:23 -0300 Subject: [PATCH 13/50] Fix `eth_getLogs` filtering for empty addresses list (#6094) * Initial 'AddressFilter' tests * Add 'by_ref' tests * Test 'AddressFilter.AnyAddress' * Accept any when addresses set is empty * Remove redundant qualifiers * Do not use null for 'AnyAddress' * Annotate field as nullable * Simplify conditionals * Use 'TestItem' data * Initial 'Matches' tests - Include 'ref' tests * Add no matching tests * Test 'AnyAddress.Matches' * Add extra 'Matches' tests * Add tests for forced null - Gets 100% coverage * Formatting --- .../Filters/AddressFilterTests.cs | 274 ++++++++++++++++++ .../Filters/AddressFilter.cs | 36 +-- 2 files changed, 289 insertions(+), 21 deletions(-) create mode 100644 src/Nethermind/Nethermind.Blockchain.Test/Filters/AddressFilterTests.cs diff --git a/src/Nethermind/Nethermind.Blockchain.Test/Filters/AddressFilterTests.cs b/src/Nethermind/Nethermind.Blockchain.Test/Filters/AddressFilterTests.cs new file mode 100644 index 00000000000..b65612e7320 --- /dev/null +++ b/src/Nethermind/Nethermind.Blockchain.Test/Filters/AddressFilterTests.cs @@ -0,0 +1,274 @@ +// SPDX-FileCopyrightText: 2023 Demerzel Solutions Limited +// SPDX-License-Identifier: LGPL-3.0-only + +using System.Collections.Generic; +using FluentAssertions; +using Nethermind.Blockchain.Filters; +using Nethermind.Core; +using Nethermind.Core.Crypto; +using Nethermind.Core.Test.Builders; +using NUnit.Framework; + +namespace Nethermind.Blockchain.Test.Filters; + +[TestFixture] +public class AddressFilterTests +{ + [Test] + public void Accepts_a_specific_address() + { + AddressFilter filter = new AddressFilter(TestItem.AddressA); + + filter.Accepts(TestItem.AddressA).Should().BeTrue(); + } + + [Test] + public void Accepts_a_specific_address_by_ref() + { + AddressFilter filter = new AddressFilter(TestItem.AddressA); + + AddressStructRef @ref = TestItem.AddressA.ToStructRef(); + filter.Accepts(ref @ref).Should().BeTrue(); + } + + [Test] + public void Rejects_different_address() + { + AddressFilter filter = new AddressFilter(TestItem.AddressA); + + filter.Accepts(TestItem.AddressB).Should().BeFalse(); + } + + [Test] + public void Rejects_different_address_by_ref() + { + AddressFilter filter = new AddressFilter(TestItem.AddressA); + + AddressStructRef addressBRef = TestItem.AddressB.ToStructRef(); + filter.Accepts(ref addressBRef).Should().BeFalse(); + } + + [Test] + public void Accepts_any_address() + { + AddressFilter filter = AddressFilter.AnyAddress; + + filter.Accepts(TestItem.AddressA).Should().BeTrue(); + filter.Accepts(TestItem.AddressB).Should().BeTrue(); + filter.Accepts(TestItem.AddressC).Should().BeTrue(); + } + + [Test] + public void Accepts_any_address_by_ref() + { + AddressFilter filter = AddressFilter.AnyAddress; + + AddressStructRef addressARef = TestItem.AddressA.ToStructRef(); + AddressStructRef addressBRef = TestItem.AddressB.ToStructRef(); + AddressStructRef addressCRef = TestItem.AddressC.ToStructRef(); + filter.Accepts(ref addressARef).Should().BeTrue(); + filter.Accepts(ref addressBRef).Should().BeTrue(); + filter.Accepts(ref addressCRef).Should().BeTrue(); + } + + [Test] + public void Accepts_any_address_when_set_is_empty() + { + HashSet
addresses = new(); + AddressFilter filter = new AddressFilter(addresses); + + filter.Accepts(TestItem.AddressA).Should().BeTrue(); + filter.Accepts(TestItem.AddressB).Should().BeTrue(); + filter.Accepts(TestItem.AddressC).Should().BeTrue(); + } + + [Test] + public void Accepts_any_address_when_set_is_empty_by_ref() + { + HashSet
addresses = new(); + AddressFilter filter = new AddressFilter(addresses); + + AddressStructRef addressARef = TestItem.AddressA.ToStructRef(); + AddressStructRef addressBRef = TestItem.AddressB.ToStructRef(); + AddressStructRef addressCRef = TestItem.AddressC.ToStructRef(); + filter.Accepts(ref addressARef).Should().BeTrue(); + filter.Accepts(ref addressBRef).Should().BeTrue(); + filter.Accepts(ref addressCRef).Should().BeTrue(); + } + + [Test] + public void Accepts_only_addresses_in_a_set() + { + HashSet
addresses = new() + { + TestItem.AddressA, TestItem.AddressC + }; + AddressFilter filter = new AddressFilter(addresses); + + filter.Accepts(TestItem.AddressA).Should().BeTrue(); + filter.Accepts(TestItem.AddressB).Should().BeFalse(); + filter.Accepts(TestItem.AddressC).Should().BeTrue(); + } + + [Test] + public void Accepts_only_addresses_in_a_set_by_ref() + { + HashSet
addresses = new() + { + TestItem.AddressA, TestItem.AddressC + }; + AddressFilter filter = new AddressFilter(addresses); + + AddressStructRef addressARef = TestItem.AddressA.ToStructRef(); + AddressStructRef addressBRef = TestItem.AddressB.ToStructRef(); + AddressStructRef addressCRef = TestItem.AddressC.ToStructRef(); + filter.Accepts(ref addressARef).Should().BeTrue(); + filter.Accepts(ref addressBRef).Should().BeFalse(); + filter.Accepts(ref addressCRef).Should().BeTrue(); + } + + [Test] + public void Matches_bloom_using_specific_address() + { + AddressFilter filter = new AddressFilter(TestItem.AddressA); + Core.Bloom bloom = BloomFromAddress(TestItem.AddressA); + + filter.Matches(bloom).Should().BeTrue(); + } + + [Test] + public void Matches_bloom_using_specific_address_by_ref() + { + AddressFilter filter = new AddressFilter(TestItem.AddressA); + BloomStructRef bloomRef = BloomFromAddress(TestItem.AddressA).ToStructRef(); + + filter.Matches(ref bloomRef).Should().BeTrue(); + } + + [Test] + public void Does_not_match_bloom_using_different_address() + { + AddressFilter filter = new AddressFilter(TestItem.AddressA); + + filter.Matches(BloomFromAddress(TestItem.AddressB)).Should().BeFalse(); + } + + [Test] + public void Does_not_match_bloom_using_different_address_by_ref() + { + AddressFilter filter = new AddressFilter(TestItem.AddressA); + BloomStructRef bloomRef = BloomFromAddress(TestItem.AddressB).ToStructRef(); + + filter.Matches(ref bloomRef).Should().BeFalse(); + } + + [Test] + public void Matches_bloom_using_any_address() + { + AddressFilter filter = AddressFilter.AnyAddress; + + filter.Matches(BloomFromAddress(TestItem.AddressA)).Should().BeTrue(); + filter.Matches(BloomFromAddress(TestItem.AddressB)).Should().BeTrue(); + filter.Matches(BloomFromAddress(TestItem.AddressC)).Should().BeTrue(); + } + + [Test] + public void Matches_bloom_using_any_address_by_ref() + { + AddressFilter filter = AddressFilter.AnyAddress; + + BloomStructRef bloomARef = BloomFromAddress(TestItem.AddressA).ToStructRef(); + BloomStructRef bloomBRef = BloomFromAddress(TestItem.AddressB).ToStructRef(); + BloomStructRef bloomCRef = BloomFromAddress(TestItem.AddressC).ToStructRef(); + filter.Matches(ref bloomARef).Should().BeTrue(); + filter.Matches(ref bloomBRef).Should().BeTrue(); + filter.Matches(ref bloomCRef).Should().BeTrue(); + } + + [Test] + public void Matches_any_bloom_when_set_is_empty() + { + HashSet
addresses = new(); + AddressFilter filter = new AddressFilter(addresses); + + filter.Matches(BloomFromAddress(TestItem.AddressA)).Should().BeTrue(); + filter.Matches(BloomFromAddress(TestItem.AddressB)).Should().BeTrue(); + filter.Matches(BloomFromAddress(TestItem.AddressC)).Should().BeTrue(); + } + + [Test] + public void Matches_any_bloom_when_set_is_empty_by_ref() + { + HashSet
addresses = new(); + AddressFilter filter = new AddressFilter(addresses); + + BloomStructRef bloomARef = BloomFromAddress(TestItem.AddressA).ToStructRef(); + BloomStructRef bloomBRef = BloomFromAddress(TestItem.AddressB).ToStructRef(); + BloomStructRef bloomCRef = BloomFromAddress(TestItem.AddressC).ToStructRef(); + filter.Matches(ref bloomARef).Should().BeTrue(); + filter.Matches(ref bloomBRef).Should().BeTrue(); + filter.Matches(ref bloomCRef).Should().BeTrue(); + } + + [Test] + public void Matches_any_bloom_when_set_is_forced_null() + { + AddressFilter filter = new AddressFilter(addresses: null!); + + filter.Matches(BloomFromAddress(TestItem.AddressA)).Should().BeTrue(); + filter.Matches(BloomFromAddress(TestItem.AddressB)).Should().BeTrue(); + filter.Matches(BloomFromAddress(TestItem.AddressC)).Should().BeTrue(); + } + + [Test] + public void Matches_any_bloom_when_set_is_forced_null_by_ref() + { + AddressFilter filter = new AddressFilter(addresses: null!); + + BloomStructRef bloomARef = BloomFromAddress(TestItem.AddressA).ToStructRef(); + BloomStructRef bloomBRef = BloomFromAddress(TestItem.AddressB).ToStructRef(); + BloomStructRef bloomCRef = BloomFromAddress(TestItem.AddressC).ToStructRef(); + filter.Matches(ref bloomARef).Should().BeTrue(); + filter.Matches(ref bloomBRef).Should().BeTrue(); + filter.Matches(ref bloomCRef).Should().BeTrue(); + } + + [Test] + public void Matches_any_bloom_using_addresses_set() + { + HashSet
addresses = new() + { + TestItem.AddressA, TestItem.AddressC + }; + AddressFilter filter = new AddressFilter(addresses); + + filter.Matches(BloomFromAddress(TestItem.AddressA)).Should().BeTrue(); + filter.Matches(BloomFromAddress(TestItem.AddressB)).Should().BeFalse(); + filter.Matches(BloomFromAddress(TestItem.AddressC)).Should().BeTrue(); + } + + [Test] + public void Matches_any_bloom_using_addresses_set_by_ref() + { + HashSet
addresses = new() + { + TestItem.AddressA, TestItem.AddressC + }; + AddressFilter filter = new AddressFilter(addresses); + + BloomStructRef bloomARef = BloomFromAddress(TestItem.AddressA).ToStructRef(); + BloomStructRef bloomBRef = BloomFromAddress(TestItem.AddressB).ToStructRef(); + BloomStructRef bloomCRef = BloomFromAddress(TestItem.AddressC).ToStructRef(); + filter.Matches(ref bloomARef).Should().BeTrue(); + filter.Matches(ref bloomBRef).Should().BeFalse(); + filter.Matches(ref bloomCRef).Should().BeTrue(); + } + + private static Core.Bloom BloomFromAddress(Address address) + { + LogEntry entry = new LogEntry(address, new byte[] { }, new Keccak[] { }); + Core.Bloom bloom = new Core.Bloom(new[] { entry }); + + return bloom; + } +} diff --git a/src/Nethermind/Nethermind.Facade/Filters/AddressFilter.cs b/src/Nethermind/Nethermind.Facade/Filters/AddressFilter.cs index f3722216202..84a0dbb7072 100644 --- a/src/Nethermind/Nethermind.Facade/Filters/AddressFilter.cs +++ b/src/Nethermind/Nethermind.Facade/Filters/AddressFilter.cs @@ -9,10 +9,10 @@ namespace Nethermind.Blockchain.Filters { public class AddressFilter { - public static AddressFilter AnyAddress = new((Address)null); + public static readonly AddressFilter AnyAddress = new(addresses: new HashSet
()); - private Core.Bloom.BloomExtract[] _addressesBloomIndexes; - private Core.Bloom.BloomExtract? _addressBloomExtract; + private Bloom.BloomExtract[]? _addressesBloomIndexes; + private Bloom.BloomExtract? _addressBloomExtract; public AddressFilter(Address address) { @@ -24,14 +24,14 @@ public AddressFilter(HashSet
addresses) Addresses = addresses; } - public Address? Address { get; set; } - public HashSet
? Addresses { get; set; } - private Core.Bloom.BloomExtract[] AddressesBloomExtracts => _addressesBloomIndexes ??= CalculateBloomExtracts(); - private Core.Bloom.BloomExtract AddressBloomExtract => _addressBloomExtract ??= Core.Bloom.GetExtract(Address); + public Address? Address { get; } + public HashSet
? Addresses { get; } + private Bloom.BloomExtract[] AddressesBloomExtracts => _addressesBloomIndexes ??= CalculateBloomExtracts(); + private Bloom.BloomExtract AddressBloomExtract => _addressBloomExtract ??= Bloom.GetExtract(Address); public bool Accepts(Address address) { - if (Addresses is not null) + if (Addresses?.Count > 0) { return Addresses.Contains(address); } @@ -41,7 +41,7 @@ public bool Accepts(Address address) public bool Accepts(ref AddressStructRef address) { - if (Addresses is not null) + if (Addresses?.Count > 0) { foreach (var a in Addresses) { @@ -54,7 +54,7 @@ public bool Accepts(ref AddressStructRef address) return Address is null || Address == address; } - public bool Matches(Core.Bloom bloom) + public bool Matches(Bloom bloom) { if (Addresses is not null) { @@ -71,14 +71,11 @@ public bool Matches(Core.Bloom bloom) return result; } - else if (Address is null) + if (Address is null) { return true; } - else - { - return bloom.Matches(AddressBloomExtract); - } + return bloom.Matches(AddressBloomExtract); } public bool Matches(ref BloomStructRef bloom) @@ -98,16 +95,13 @@ public bool Matches(ref BloomStructRef bloom) return result; } - else if (Address is null) + if (Address is null) { return true; } - else - { - return bloom.Matches(AddressBloomExtract); - } + return bloom.Matches(AddressBloomExtract); } - private Core.Bloom.BloomExtract[] CalculateBloomExtracts() => Addresses.Select(Core.Bloom.GetExtract).ToArray(); + private Bloom.BloomExtract[] CalculateBloomExtracts() => Addresses.Select(Bloom.GetExtract).ToArray(); } } From ec0e4a85d5e6ed1bf90087795fa2e875f340172d Mon Sep 17 00:00:00 2001 From: Ayman Bouchareb Date: Fri, 15 Sep 2023 07:49:50 -0700 Subject: [PATCH 14/50] -Update address and buffer size (#6098) --- .../BeaconBlockRoot/BeaconBlockRootHandler.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Nethermind/Nethermind.Blockchain/BeaconBlockRoot/BeaconBlockRootHandler.cs b/src/Nethermind/Nethermind.Blockchain/BeaconBlockRoot/BeaconBlockRootHandler.cs index fdfd5024038..f5fe8c2de97 100644 --- a/src/Nethermind/Nethermind.Blockchain/BeaconBlockRoot/BeaconBlockRootHandler.cs +++ b/src/Nethermind/Nethermind.Blockchain/BeaconBlockRoot/BeaconBlockRootHandler.cs @@ -11,8 +11,8 @@ namespace Nethermind.Consensus.BeaconBlockRoot; public class BeaconBlockRootHandler : IBeaconBlockRootHandler { - public static UInt256 HISTORICAL_ROOTS_LENGTH = 98304; - private static readonly Address DefaultPbbrContractAddress = new Address("0xbEac00dDB15f3B6d645C48263dC93862413A222D"); + public static UInt256 HISTORICAL_ROOTS_LENGTH = 8191; + private static readonly Address DefaultPbbrContractAddress = new Address("0xbEaC02001Aedb23b4088c853e4C05c57491c8bCA"); public void ApplyContractStateChanges(Block block, IReleaseSpec spec, IWorldState stateProvider) { From ba633427b9f29ac298d07d5f1fa8478e86c1c606 Mon Sep 17 00:00:00 2001 From: Lautaro Emanuel <31224949+emlautarom1@users.noreply.github.com> Date: Mon, 18 Sep 2023 12:48:28 -0300 Subject: [PATCH 15/50] Ensure `ChainId` is always set in 2930 and 1559 txs (#6061) * Ensure 'ChainId' is always set in 2930 and 1559 txs - Only Legacy transactions can ignore 'ChainId' - When ignored, default to 'Mainnet' (0x01) * Update tests - Ensure that 0x1 and 0x2 Txs have a 'chainId' field * Fix JSON comparison - Was defaulting to the dreaded 'Object.Equals' default implementation * Use 'FluentAssertions.Json' - Simplifies JSON comparison - Removes boilerplate * Default to last loaded chainspec if possible * Load default 'ChainId' for Transactions on 'ApiBuilder' --- .../Data/Eip2930Tests.cs | 31 ++++++++++--------- .../Data/TransactionForRpc.cs | 15 ++++++++- .../Ethereum/Api/ApiBuilder.cs | 5 ++- 3 files changed, 34 insertions(+), 17 deletions(-) diff --git a/src/Nethermind/Nethermind.JsonRpc.Test/Data/Eip2930Tests.cs b/src/Nethermind/Nethermind.JsonRpc.Test/Data/Eip2930Tests.cs index c85b5285a1c..9dc0342c55a 100644 --- a/src/Nethermind/Nethermind.JsonRpc.Test/Data/Eip2930Tests.cs +++ b/src/Nethermind/Nethermind.JsonRpc.Test/Data/Eip2930Tests.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using FluentAssertions; +using FluentAssertions.Json; using Nethermind.Core; using Nethermind.Core.Eip2930; using Nethermind.Core.Extensions; @@ -35,8 +36,8 @@ private AccessList GetTestAccessList() return accessListBuilder.ToAccessList(); } - [TestCase(TxType.AccessList, """{"nonce":"0x0","blockHash":null,"blockNumber":null,"transactionIndex":null,"to":null,"value":"0x0","gasPrice":"0x0","gas":"0x0","input":null,"type":"0x1","accessList":[{"address":"0xb7705ae4c6f81b66cdb323c65f4e8133690fc099","storageKeys":["0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000003","0x0000000000000000000000000000000000000000000000000000000000000005","0x0000000000000000000000000000000000000000000000000000000000000008"]},{"address":"0x942921b14f1b1c385cd7e0cc2ef7abe5598c8358","storageKeys":["0x000000000000000000000000000000000000000000000000000000000000002a"]}]}""")] - [TestCase(TxType.EIP1559, """{"nonce":"0x0","blockHash":null,"blockNumber":null,"transactionIndex":null,"to":null,"value":"0x0","gasPrice":"0x0","maxPriorityFeePerGas":"0x0","maxFeePerGas":"0x0","gas":"0x0","input":null,"type":"0x2","accessList":[{"address":"0xb7705ae4c6f81b66cdb323c65f4e8133690fc099","storageKeys":["0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000003","0x0000000000000000000000000000000000000000000000000000000000000005","0x0000000000000000000000000000000000000000000000000000000000000008"]},{"address":"0x942921b14f1b1c385cd7e0cc2ef7abe5598c8358","storageKeys":["0x000000000000000000000000000000000000000000000000000000000000002a"]}]}""")] + [TestCase(TxType.AccessList, """{"nonce":"0x0","blockHash":null,"blockNumber":null,"transactionIndex":null,"to":null,"value":"0x0","gasPrice":"0x0","gas":"0x0","input":null,"type":"0x1","chainId":"0x1","accessList":[{"address":"0xb7705ae4c6f81b66cdb323c65f4e8133690fc099","storageKeys":["0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000003","0x0000000000000000000000000000000000000000000000000000000000000005","0x0000000000000000000000000000000000000000000000000000000000000008"]},{"address":"0x942921b14f1b1c385cd7e0cc2ef7abe5598c8358","storageKeys":["0x000000000000000000000000000000000000000000000000000000000000002a"]}]}""")] + [TestCase(TxType.EIP1559, """{"nonce":"0x0","blockHash":null,"blockNumber":null,"transactionIndex":null,"to":null,"value":"0x0","gasPrice":"0x0","maxPriorityFeePerGas":"0x0","maxFeePerGas":"0x0","gas":"0x0","input":null,"type":"0x2","chainId":"0x1","accessList":[{"address":"0xb7705ae4c6f81b66cdb323c65f4e8133690fc099","storageKeys":["0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000003","0x0000000000000000000000000000000000000000000000000000000000000005","0x0000000000000000000000000000000000000000000000000000000000000008"]},{"address":"0x942921b14f1b1c385cd7e0cc2ef7abe5598c8358","storageKeys":["0x000000000000000000000000000000000000000000000000000000000000002a"]}]}""")] public void can_serialize_valid_accessList(TxType txType, string txJson) { Transaction transaction = new() @@ -48,11 +49,11 @@ public void can_serialize_valid_accessList(TxType txType, string txJson) string serialized = _serializer.Serialize(transactionForRpc); - JObject.Parse(serialized).Should().BeEquivalentTo(JObject.Parse(txJson)); + JToken.Parse(serialized).Should().BeEquivalentTo(JToken.Parse(txJson)); } - [TestCase(TxType.AccessList, """{"nonce":"0x0","blockHash":null,"blockNumber":null,"transactionIndex":null,"to":null,"value":"0x0","gasPrice":"0x0","gas":"0x0","input":null,"type":"0x01","accessList":[{"address":"0xb7705ae4c6f81b66cdb323c65f4e8133690fc099","storageKeys":["0x1","0x2","0x3","0x5","0x8"]},{"address":"0x942921b14f1b1c385cd7e0cc2ef7abe5598c8358","storageKeys":["0x2a"]}]}""")] - [TestCase(TxType.EIP1559, """{"nonce":"0x0","blockHash":null,"blockNumber":null,"transactionIndex":null,"to":null,"value":"0x0","gasPrice":"0x0","maxFeePerGas":"0x0","maxPriorityFeePerGas":"0x0","gas":"0x0","input":null,"type":"0x02","accessList":[{"address":"0xb7705ae4c6f81b66cdb323c65f4e8133690fc099","storageKeys":["0x1","0x2","0x3","0x5","0x8"]},{"address":"0x942921b14f1b1c385cd7e0cc2ef7abe5598c8358","storageKeys":["0x2a"]}]}""")] + [TestCase(TxType.AccessList, """{"nonce":"0x0","blockHash":null,"blockNumber":null,"transactionIndex":null,"to":null,"value":"0x0","gasPrice":"0x0","gas":"0x0","input":null,"type":"0x01","chainId":"0x01","accessList":[{"address":"0xb7705ae4c6f81b66cdb323c65f4e8133690fc099","storageKeys":["0x1","0x2","0x3","0x5","0x8"]},{"address":"0x942921b14f1b1c385cd7e0cc2ef7abe5598c8358","storageKeys":["0x2a"]}]}""")] + [TestCase(TxType.EIP1559, """{"nonce":"0x0","blockHash":null,"blockNumber":null,"transactionIndex":null,"to":null,"value":"0x0","gasPrice":"0x0","maxFeePerGas":"0x0","maxPriorityFeePerGas":"0x0","gas":"0x0","input":null,"type":"0x02","chainId":"0x01","accessList":[{"address":"0xb7705ae4c6f81b66cdb323c65f4e8133690fc099","storageKeys":["0x1","0x2","0x3","0x5","0x8"]},{"address":"0x942921b14f1b1c385cd7e0cc2ef7abe5598c8358","storageKeys":["0x2a"]}]}""")] public void can_deserialize_valid_accessList(TxType txType, string txJson) { Transaction transaction = new() @@ -78,7 +79,7 @@ public void can_serialize_null_accessList_to_nothing(TxType txType) string serialized = _serializer.Serialize(rpc); - JObject.Parse(serialized).GetValue("accessList").Should().BeNull(); + JObject.Parse(serialized).Should().NotHaveElement("accessList"); } [TestCase(TxType.AccessList)] @@ -118,8 +119,8 @@ public void can_deserialize_no_accessList() transactionForRpc.AccessList.Should().BeNull(); } - [TestCase(TxType.AccessList, """{"nonce":"0x0","blockHash":null,"blockNumber":null,"transactionIndex":null,"to":null,"value":"0x0","gasPrice":"0x0","gas":"0x0","input":null,"type":"0x1","accessList":[]}""")] - [TestCase(TxType.EIP1559, """{"nonce":"0x0","blockHash":null,"blockNumber":null,"transactionIndex":null,"to":null,"value":"0x0","gasPrice":"0x0","maxPriorityFeePerGas":"0x0","maxFeePerGas":"0x0","gas":"0x0","input":null,"type":"0x2","accessList":[]}""")] + [TestCase(TxType.AccessList, """{"nonce":"0x0","blockHash":null,"blockNumber":null,"transactionIndex":null,"to":null,"value":"0x0","gasPrice":"0x0","gas":"0x0","input":null,"type":"0x1","chainId":"0x1","accessList":[]}""")] + [TestCase(TxType.EIP1559, """{"nonce":"0x0","blockHash":null,"blockNumber":null,"transactionIndex":null,"to":null,"value":"0x0","gasPrice":"0x0","maxPriorityFeePerGas":"0x0","maxFeePerGas":"0x0","gas":"0x0","input":null,"type":"0x2","chainId":"0x1","accessList":[]}""")] public void can_serialize_empty_accessList(TxType txType, string txJson) { Dictionary> data = new(); @@ -132,7 +133,7 @@ public void can_serialize_empty_accessList(TxType txType, string txJson) string serialized = _serializer.Serialize(transactionForRpc); - JObject.Parse(serialized).Should().BeEquivalentTo(JObject.Parse(txJson)); + JToken.Parse(serialized).Should().BeEquivalentTo(JToken.Parse(txJson)); } [Test] @@ -146,8 +147,8 @@ public void can_deserialize_empty_accessList() transactionForRpc.AccessList!.Length.Should().Be(0); } - [TestCase(TxType.AccessList, """{"nonce":"0x0","blockHash":null,"blockNumber":null,"transactionIndex":null,"to":null,"value":"0x0","gasPrice":"0x0","gas":"0x0","input":null,"type":"0x1","accessList":[{"address":"0xb7705ae4c6f81b66cdb323c65f4e8133690fc099","storageKeys":[]}]}""")] - [TestCase(TxType.EIP1559, """{"nonce":"0x0","blockHash":null,"blockNumber":null,"transactionIndex":null,"to":null,"value":"0x0","gasPrice":"0x0","maxPriorityFeePerGas":"0x0","maxFeePerGas":"0x0","gas":"0x0","input":null,"type":"0x2","accessList":[{"address":"0xb7705ae4c6f81b66cdb323c65f4e8133690fc099","storageKeys":[]}]}""")] + [TestCase(TxType.AccessList, """{"nonce":"0x0","blockHash":null,"blockNumber":null,"transactionIndex":null,"to":null,"value":"0x0","gasPrice":"0x0","gas":"0x0","input":null,"type":"0x1","chainId":"0x1","accessList":[{"address":"0xb7705ae4c6f81b66cdb323c65f4e8133690fc099","storageKeys":[]}]}""")] + [TestCase(TxType.EIP1559, """{"nonce":"0x0","blockHash":null,"blockNumber":null,"transactionIndex":null,"to":null,"value":"0x0","gasPrice":"0x0","maxPriorityFeePerGas":"0x0","maxFeePerGas":"0x0","gas":"0x0","input":null,"type":"0x2","chainId":"0x1","accessList":[{"address":"0xb7705ae4c6f81b66cdb323c65f4e8133690fc099","storageKeys":[]}]}""")] public void can_serialize_accessList_with_empty_storageKeys(TxType txType, string txJson) { Dictionary> data = new() @@ -165,7 +166,7 @@ public void can_serialize_accessList_with_empty_storageKeys(TxType txType, strin string serialized = _serializer.Serialize(transactionForRpc); - JObject.Parse(serialized).Should().BeEquivalentTo(JObject.Parse(txJson)); + JToken.Parse(serialized).Should().BeEquivalentTo(JToken.Parse(txJson)); } [Test] @@ -180,8 +181,8 @@ public void can_deserialize_accessList_with_empty_storageKeys() transactionForRpc.AccessList.Should().BeEquivalentTo(accessList); } - [TestCase(TxType.AccessList, """{"nonce":"0x0","blockHash":null,"blockNumber":null,"transactionIndex":null,"to":null,"value":"0x0","gasPrice":"0x0","gas":"0x0","input":null,"type":"0x1","accessList":[{"address":"0xb7705ae4c6f81b66cdb323c65f4e8133690fc099","storageKeys":[]}]}""")] - [TestCase(TxType.EIP1559, """{"nonce":"0x0","blockHash":null,"blockNumber":null,"transactionIndex":null,"to":null,"value":"0x0","gasPrice":"0x0","maxPriorityFeePerGas":"0x0","maxFeePerGas":"0x0","gas":"0x0","input":null,"type":"0x2","accessList":[{"address":"0xb7705ae4c6f81b66cdb323c65f4e8133690fc099","storageKeys":[]}]}""")] + [TestCase(TxType.AccessList, """{"nonce":"0x0","blockHash":null,"blockNumber":null,"transactionIndex":null,"to":null,"value":"0x0","gasPrice":"0x0","gas":"0x0","input":null,"type":"0x1","chainId":"0x1","accessList":[{"address":"0xb7705ae4c6f81b66cdb323c65f4e8133690fc099","storageKeys":[]}]}""")] + [TestCase(TxType.EIP1559, """{"nonce":"0x0","blockHash":null,"blockNumber":null,"transactionIndex":null,"to":null,"value":"0x0","gasPrice":"0x0","maxPriorityFeePerGas":"0x0","maxFeePerGas":"0x0","gas":"0x0","input":null,"type":"0x2","chainId":"0x1","accessList":[{"address":"0xb7705ae4c6f81b66cdb323c65f4e8133690fc099","storageKeys":[]}]}""")] public void can_serialize_accessList_with_null_storageKeys(TxType txType, string txJson) { Dictionary> data = new() @@ -200,7 +201,7 @@ public void can_serialize_accessList_with_null_storageKeys(TxType txType, string string serialized = _serializer.Serialize(transactionForRpc); - JObject.Parse(serialized).Should().BeEquivalentTo(JObject.Parse(txJson)); + JToken.Parse(serialized).Should().BeEquivalentTo(JToken.Parse(txJson)); } [Test] diff --git a/src/Nethermind/Nethermind.JsonRpc/Data/TransactionForRpc.cs b/src/Nethermind/Nethermind.JsonRpc/Data/TransactionForRpc.cs index 4b4eabe1f18..ca340403e22 100644 --- a/src/Nethermind/Nethermind.JsonRpc/Data/TransactionForRpc.cs +++ b/src/Nethermind/Nethermind.JsonRpc/Data/TransactionForRpc.cs @@ -13,6 +13,10 @@ namespace Nethermind.JsonRpc.Data; public class TransactionForRpc { + // HACK: To ensure that serialized Txs always have a `ChainId` we keep the last loaded `ChainSpec`. + // See: https://github.com/NethermindEth/nethermind/pull/6061#discussion_r1321634914 + public static UInt256? DefaultChainId { get; set; } + public TransactionForRpc(Transaction transaction) : this(null, null, null, transaction) { } public TransactionForRpc(Keccak? blockHash, long? blockNumber, int? txIndex, Transaction transaction, UInt256? baseFee = null) @@ -36,7 +40,16 @@ public TransactionForRpc(Keccak? blockHash, long? blockNumber, int? txIndex, Tra MaxFeePerGas = transaction.MaxFeePerGas; MaxPriorityFeePerGas = transaction.MaxPriorityFeePerGas; } - ChainId = transaction.ChainId; + if (transaction.Type > TxType.Legacy) + { + ChainId = transaction.ChainId + ?? DefaultChainId + ?? BlockchainIds.Mainnet; + } + else + { + ChainId = transaction.ChainId; + } Type = transaction.Type; if (transaction.SupportsAccessList) { diff --git a/src/Nethermind/Nethermind.Runner/Ethereum/Api/ApiBuilder.cs b/src/Nethermind/Nethermind.Runner/Ethereum/Api/ApiBuilder.cs index e81b7dc8983..5b4859c293e 100644 --- a/src/Nethermind/Nethermind.Runner/Ethereum/Api/ApiBuilder.cs +++ b/src/Nethermind/Nethermind.Runner/Ethereum/Api/ApiBuilder.cs @@ -11,6 +11,7 @@ using Nethermind.Config; using Nethermind.Consensus; using Nethermind.Core; +using Nethermind.JsonRpc.Data; using Nethermind.Logging; using Nethermind.Serialization.Json; using Nethermind.Specs.ChainSpecStyle; @@ -80,7 +81,9 @@ private ChainSpec LoadChainSpec(IJsonSerializer ethereumJsonSerializer) ThisNodeInfo.AddInfo("Chainspec :", $"{chainSpecFile}"); IChainSpecLoader loader = new ChainSpecLoader(ethereumJsonSerializer); - return loader.LoadEmbeddedOrFromFile(chainSpecFile, _logger); + ChainSpec chainSpec = loader.LoadEmbeddedOrFromFile(chainSpecFile, _logger); + TransactionForRpc.DefaultChainId = chainSpec.ChainId; + return chainSpec; } private void SetLoggerVariables(ChainSpec chainSpec) From f373ffbc24346429707d13291501b72da8fc0386 Mon Sep 17 00:00:00 2001 From: Lautaro Emanuel <31224949+emlautarom1@users.noreply.github.com> Date: Mon, 18 Sep 2023 13:18:31 -0300 Subject: [PATCH 16/50] Remove HTTP log spam on default settings (#6097) * Do not change log levels for 'JsonWebAPI*' rules * Add comment to workaround --- src/Nethermind/Nethermind.Runner/Logging/NLogConfigurator.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/Nethermind/Nethermind.Runner/Logging/NLogConfigurator.cs b/src/Nethermind/Nethermind.Runner/Logging/NLogConfigurator.cs index 4c82688d5f6..570c7db86a9 100644 --- a/src/Nethermind/Nethermind.Runner/Logging/NLogConfigurator.cs +++ b/src/Nethermind/Nethermind.Runner/Logging/NLogConfigurator.cs @@ -71,6 +71,9 @@ public static void ConfigureLogLevels(CommandOption logLevelOverride) foreach (LoggingRule rule in LogManager.Configuration.LoggingRules) { + // WORKAROUND: Skip modifying 'JsonWebAPI*' rules since we want to preserve the original config on the 'NLog.config' file + if (rule.LoggerNamePattern == "JsonWebAPI*") { continue; } + foreach (var ruleTarget in rule.Targets) { if (ruleTarget.Name != "seq") From f16c9445d95cc2e27064ce91b6aaf1614500b8a7 Mon Sep 17 00:00:00 2001 From: Lautaro Emanuel <31224949+emlautarom1@users.noreply.github.com> Date: Mon, 18 Sep 2023 14:46:26 -0300 Subject: [PATCH 17/50] Mark flaky tests as explicit (#6102) - Remove retries --- .../Nethermind.JsonRpc.Test/JsonRpcSocketsClientTests.cs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/Nethermind/Nethermind.JsonRpc.Test/JsonRpcSocketsClientTests.cs b/src/Nethermind/Nethermind.JsonRpc.Test/JsonRpcSocketsClientTests.cs index 247bdc64d29..8fe59998d75 100644 --- a/src/Nethermind/Nethermind.JsonRpc.Test/JsonRpcSocketsClientTests.cs +++ b/src/Nethermind/Nethermind.JsonRpc.Test/JsonRpcSocketsClientTests.cs @@ -63,7 +63,6 @@ public async Task Can_handle_very_large_objects() } [Test] - [Retry(5)] [TestCase(2)] [TestCase(10)] [TestCase(50)] @@ -108,7 +107,6 @@ public async Task Can_send_multiple_messages(int messageCount) Assert.That(sent, Is.EqualTo(received)); } - [Retry(5)] [TestCase(2)] [TestCase(10)] [TestCase(50)] @@ -172,10 +170,10 @@ private static async Task CountNumberOfBytes(Socket socket) } } + [Explicit] public class UsingWebSockets { [Test] - [Retry(5)] [TestCase(2)] [TestCase(10)] [TestCase(50)] @@ -221,7 +219,6 @@ public async Task Can_send_multiple_messages(int messageCount) Assert.That(sent, Is.EqualTo(received)); } - [Retry(5)] [TestCase(2)] [TestCase(10)] [TestCase(50)] From 54d8149a70b86de120cdfda63905d0b0a6d906b1 Mon Sep 17 00:00:00 2001 From: Lukasz Rozmej Date: Mon, 18 Sep 2023 22:39:48 +0200 Subject: [PATCH 18/50] Add TrieHealing config (#6004) Co-authored-by: MarekM25 --- .../Synchronization/ISyncConfig.cs | 3 ++ .../Synchronization/SyncConfig.cs | 2 ++ .../Steps/InitializeBlockchain.cs | 29 +++++++++++++------ 3 files changed, 25 insertions(+), 9 deletions(-) diff --git a/src/Nethermind/Nethermind.Blockchain/Synchronization/ISyncConfig.cs b/src/Nethermind/Nethermind.Blockchain/Synchronization/ISyncConfig.cs index 5ec311eb5cc..e71408b912b 100644 --- a/src/Nethermind/Nethermind.Blockchain/Synchronization/ISyncConfig.cs +++ b/src/Nethermind/Nethermind.Blockchain/Synchronization/ISyncConfig.cs @@ -113,6 +113,9 @@ public interface ISyncConfig : IConfig [ConfigItem(Description = "[TECHNICAL] Specify max num of thread used for processing. Default is same as logical core count.", DefaultValue = "0")] public int MaxProcessingThreads { get; set; } + [ConfigItem(Description = "Enables healing trie from network when state is corrupted.", DefaultValue = "true", HiddenFromDocs = true)] + public bool TrieHealing { get; set; } + [ConfigItem(Description = "Exit Nethermind once sync is finished", DefaultValue = "false")] public bool ExitOnSynced { get; set; } diff --git a/src/Nethermind/Nethermind.Blockchain/Synchronization/SyncConfig.cs b/src/Nethermind/Nethermind.Blockchain/Synchronization/SyncConfig.cs index 2a6b154502e..c584ca0397d 100644 --- a/src/Nethermind/Nethermind.Blockchain/Synchronization/SyncConfig.cs +++ b/src/Nethermind/Nethermind.Blockchain/Synchronization/SyncConfig.cs @@ -66,6 +66,8 @@ public string? PivotHash public bool ExitOnSynced { get; set; } = false; public int ExitOnSyncedWaitTimeSec { get; set; } = 60; + public bool TrieHealing { get; set; } = true; + public override string ToString() { return diff --git a/src/Nethermind/Nethermind.Init/Steps/InitializeBlockchain.cs b/src/Nethermind/Nethermind.Init/Steps/InitializeBlockchain.cs index 9639c0af8b4..952bdaa678a 100644 --- a/src/Nethermind/Nethermind.Init/Steps/InitializeBlockchain.cs +++ b/src/Nethermind/Nethermind.Init/Steps/InitializeBlockchain.cs @@ -126,17 +126,28 @@ private Task InitBlockchain() persistenceStrategy = Persist.EveryBlock; } - TrieStore trieStore = new HealingTrieStore( - stateWitnessedBy, - pruningStrategy, - persistenceStrategy, - getApi.LogManager); + TrieStore trieStore = syncConfig.TrieHealing + ? new HealingTrieStore( + stateWitnessedBy, + pruningStrategy, + persistenceStrategy, + getApi.LogManager) + : new TrieStore( + stateWitnessedBy, + pruningStrategy, + persistenceStrategy, + getApi.LogManager); setApi.TrieStore = trieStore; - IWorldState worldState = setApi.WorldState = new HealingWorldState( - trieStore, - codeDb, - getApi.LogManager); + IWorldState worldState = setApi.WorldState = syncConfig.TrieHealing + ? new HealingWorldState( + trieStore, + codeDb, + getApi.LogManager) + : new WorldState( + trieStore, + codeDb, + getApi.LogManager); if (pruningConfig.Mode.IsFull()) { From 8ce10d324c05a44dc1fb9e07e6b8618350addac9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Moraczy=C5=84ski?= Date: Mon, 18 Sep 2023 22:51:21 +0200 Subject: [PATCH 19/50] Remove warnings from Merge.Plugin.Tests.csproj (#6103) * Remove warnings from Merge.Plugin tests * TreatWarningsAsErrors * Fix whitespace --- .../BlockTreeTests.cs | 85 ++++++++++--------- .../EngineModuleTests.V2.cs | 7 +- .../InvalidBlockInterceptorTest.cs | 27 +++--- .../InvalidChainTrackerTest.cs | 13 +-- .../InvalidHeaderInterceptorTest.cs | 17 ++-- .../MergeHeaderValidatorTests.cs | 13 +-- .../MergePluginTests.cs | 14 +-- .../Nethermind.Merge.Plugin.Test.csproj | 1 + .../Synchronization/BeaconHeadersSyncTests.cs | 37 ++++---- .../Synchronization/BeaconPivotTests.cs | 7 +- src/tests | 2 +- 11 files changed, 112 insertions(+), 111 deletions(-) diff --git a/src/Nethermind/Nethermind.Merge.Plugin.Test/BlockTreeTests.cs b/src/Nethermind/Nethermind.Merge.Plugin.Test/BlockTreeTests.cs index d38e7ae15fd..8d4f289ed71 100644 --- a/src/Nethermind/Nethermind.Merge.Plugin.Test/BlockTreeTests.cs +++ b/src/Nethermind/Nethermind.Merge.Plugin.Test/BlockTreeTests.cs @@ -11,6 +11,7 @@ using Nethermind.Core.Crypto; using Nethermind.Core.Specs; using Nethermind.Core.Test.Builders; +using Nethermind.Crypto; using Nethermind.Db; using Nethermind.Db.Blooms; using Nethermind.Int256; @@ -198,7 +199,7 @@ public void Can_start_insert_pivot_block_with_correct_pointers() (BlockTree notSyncedTree, BlockTree syncedTree) = BuildBlockTrees(10, 20); Block? beaconBlock = syncedTree.FindBlock(14, BlockTreeLookupOptions.None); BlockTreeInsertHeaderOptions insertHeaderOption = BlockTreeInsertHeaderOptions.BeaconBlockInsert; - AddBlockResult insertResult = notSyncedTree.Insert(beaconBlock, BlockTreeInsertBlockOptions.SaveHeader, insertHeaderOption); + AddBlockResult insertResult = notSyncedTree.Insert(beaconBlock!, BlockTreeInsertBlockOptions.SaveHeader, insertHeaderOption); Assert.That(insertResult, Is.EqualTo(AddBlockResult.Added)); Assert.That(notSyncedTree.BestKnownNumber, Is.EqualTo(9)); @@ -217,7 +218,7 @@ public void Can_insert_beacon_headers() Block? beaconBlock = syncedTree.FindBlock(14, BlockTreeLookupOptions.None); BlockTreeInsertHeaderOptions headerOptions = BlockTreeInsertHeaderOptions.BeaconBlockInsert; - AddBlockResult insertResult = notSyncedTree.Insert(beaconBlock, BlockTreeInsertBlockOptions.SaveHeader, headerOptions); + AddBlockResult insertResult = notSyncedTree.Insert(beaconBlock!, BlockTreeInsertBlockOptions.SaveHeader, headerOptions); for (int i = 13; i > 9; --i) { BlockHeader? beaconHeader = syncedTree.FindHeader(i, BlockTreeLookupOptions.None); @@ -231,7 +232,7 @@ public void Can_fill_beacon_headers_gap() { (BlockTree notSyncedTree, BlockTree syncedTree) = BuildBlockTrees(10, 20); - Block? beaconBlock = syncedTree.FindBlock(14, BlockTreeLookupOptions.None); + Block? beaconBlock = syncedTree.FindBlock(14, BlockTreeLookupOptions.None)!; BlockTreeInsertHeaderOptions headerOptions = BlockTreeInsertHeaderOptions.BeaconBlockInsert; AddBlockResult insertResult = notSyncedTree.Insert(beaconBlock, BlockTreeInsertBlockOptions.SaveHeader, headerOptions); @@ -257,16 +258,16 @@ public void FindHeader_will_not_change_total_difficulty_when_it_is_zero() { (BlockTree notSyncedTree, BlockTree syncedTree) = BuildBlockTrees(10, 20); - Block? beaconBlock = syncedTree.FindBlock(14, BlockTreeLookupOptions.None); + Block? beaconBlock = syncedTree.FindBlock(14, BlockTreeLookupOptions.None)!; BlockTreeInsertHeaderOptions headerOptions = BlockTreeInsertHeaderOptions.BeaconBlockInsert; AddBlockResult insertResult = notSyncedTree.Insert(beaconBlock, BlockTreeInsertBlockOptions.SaveHeader, headerOptions); BlockHeader? beaconHeader = syncedTree.FindHeader(13, BlockTreeLookupOptions.None); - beaconHeader.TotalDifficulty = null; + beaconHeader!.TotalDifficulty = null; AddBlockResult insertOutcome = notSyncedTree.Insert(beaconHeader!, headerOptions); Assert.That(insertResult, Is.EqualTo(insertOutcome)); BlockHeader? headerToCheck = notSyncedTree.FindHeader(beaconHeader.Hash, BlockTreeLookupOptions.None); - Assert.IsNull(headerToCheck.TotalDifficulty); + Assert.IsNull(headerToCheck!.TotalDifficulty); } [Test] @@ -274,16 +275,16 @@ public void FindBlock_will_not_change_total_difficulty_when_it_is_zero() { (BlockTree notSyncedTree, BlockTree syncedTree) = BuildBlockTrees(10, 20); - Block? beaconBlock = syncedTree.FindBlock(14, BlockTreeLookupOptions.None); + Block? beaconBlock = syncedTree.FindBlock(14, BlockTreeLookupOptions.None)!; BlockTreeInsertHeaderOptions headerOptions = BlockTreeInsertHeaderOptions.BeaconBlockInsert; AddBlockResult insertResult = notSyncedTree.Insert(beaconBlock, BlockTreeInsertBlockOptions.SaveHeader, headerOptions); Block? beaconBlock2 = syncedTree.FindBlock(13, BlockTreeLookupOptions.None); - beaconBlock2.Header.TotalDifficulty = null; + beaconBlock2!.Header.TotalDifficulty = null; AddBlockResult insertOutcome = notSyncedTree.Insert(beaconBlock2, BlockTreeInsertBlockOptions.None); Assert.That(insertResult, Is.EqualTo(insertOutcome)); Block? blockToCheck = notSyncedTree.FindBlock(beaconBlock2.Hash, BlockTreeLookupOptions.None); - Assert.IsNull(blockToCheck.TotalDifficulty); + Assert.IsNull(blockToCheck!.TotalDifficulty); } @@ -293,7 +294,7 @@ public class ScenarioBuilder { private BlockTreeBuilder? _syncedTreeBuilder; private IChainLevelHelper? _chainLevelHelper; - private IBeaconPivot _beaconPivot; + private IBeaconPivot? _beaconPivot; public ScenarioBuilder WithBlockTrees( int notSyncedTreeSize, @@ -361,7 +362,7 @@ public ScenarioBuilder InsertBeaconPivot(long num) public ScenarioBuilder SetProcessDestination(long num) { - _beaconPivot.ProcessDestination = SyncedTree.FindHeader(num, BlockTreeLookupOptions.None); + _beaconPivot!.ProcessDestination = SyncedTree.FindHeader(num, BlockTreeLookupOptions.None); return this; } @@ -386,7 +387,7 @@ public ScenarioBuilder SuggestBlocks(long low, long high) public ScenarioBuilder SuggestBlocksUsingChainLevels(int maxCount = 2, long maxHeaderNumber = long.MaxValue) { - BlockHeader[] headers = _chainLevelHelper!.GetNextHeaders(maxCount, maxHeaderNumber, 0); + BlockHeader[] headers = _chainLevelHelper!.GetNextHeaders(maxCount, maxHeaderNumber, 0)!; while (headers is not null && headers.Length > 1) { BlockDownloadContext blockDownloadContext = new( @@ -410,14 +411,14 @@ public ScenarioBuilder SuggestBlocksUsingChainLevels(int maxCount = 2, long maxH { beaconBlock = SyncedTree.FindBlock(headers[i].Hash!, BlockTreeLookupOptions.None); - beaconBlock.Header.TotalDifficulty = null; + beaconBlock!.Header.TotalDifficulty = null; } AddBlockResult insertResult = NotSyncedTree.SuggestBlock(beaconBlock, BlockTreeSuggestOptions.ShouldProcess | BlockTreeSuggestOptions.FillBeaconBlock | BlockTreeSuggestOptions.ForceSetAsMain); Assert.True(AddBlockResult.Added == insertResult, $"BeaconBlock {beaconBlock!.ToString(Block.Format.FullHashAndNumber)} result {insertResult}"); } - headers = _chainLevelHelper!.GetNextHeaders(maxCount, maxHeaderNumber, 0); + headers = _chainLevelHelper!.GetNextHeaders(maxCount, maxHeaderNumber, 0)!; } return this; @@ -437,10 +438,10 @@ public ScenarioBuilder InsertBeaconHeaders(long low, long high, TotalDifficultyM headerOptions |= BlockTreeInsertHeaderOptions.TotalDifficultyNotNeeded; for (long i = high; i >= low; --i) { - BlockHeader? beaconHeader = SyncedTree!.FindHeader(i, BlockTreeLookupOptions.None); + BlockHeader? beaconHeader = SyncedTree!.FindHeader(i, BlockTreeLookupOptions.None)!; if (tdMode == TotalDifficultyMode.Null) - beaconHeader!.TotalDifficulty = null; + beaconHeader.TotalDifficulty = null; else if (tdMode == TotalDifficultyMode.Zero) beaconHeader.TotalDifficulty = 0; AddBlockResult insertResult = NotSyncedTree!.Insert(beaconHeader!, headerOptions); @@ -481,7 +482,7 @@ public ScenarioBuilder InsertFork(long low, long high, bool moveToBeaconMainChai NotSyncedTree.Insert(blockToInsert, BlockTreeInsertBlockOptions.SaveHeader, BlockTreeInsertHeaderOptions.BeaconBlockInsert); SyncedTree.Insert(blockToInsert, BlockTreeInsertBlockOptions.SaveHeader, BlockTreeInsertHeaderOptions.NotOnMainChain); - BlockInfo newBlockInfo = new(blockToInsert.Hash, UInt256.Zero, BlockMetadata.BeaconBody | BlockMetadata.BeaconHeader); + BlockInfo newBlockInfo = new(blockToInsert.GetOrCalculateHash(), UInt256.Zero, BlockMetadata.BeaconBody | BlockMetadata.BeaconHeader); newBlockInfo.BlockNumber = blockToInsert.Number; blockInfos.Add(newBlockInfo); blocks.Add(blockToInsert); @@ -510,7 +511,7 @@ public ScenarioBuilder InsertOtherChainToMain(BlockTree blockTree, long low, lon blockTree.Insert(blockToInsert, BlockTreeInsertBlockOptions.SaveHeader, BlockTreeInsertHeaderOptions.BeaconBlockInsert); newBlocks.Add(blockToInsert); - BlockInfo newBlockInfo = new(blockToInsert.Hash, UInt256.Zero, BlockMetadata.BeaconBody | BlockMetadata.BeaconHeader); + BlockInfo newBlockInfo = new(blockToInsert.GetOrCalculateHash(), UInt256.Zero, BlockMetadata.BeaconBody | BlockMetadata.BeaconHeader); newBlockInfo.BlockNumber = blockToInsert.Number; parent = blockToInsert; } @@ -532,7 +533,7 @@ public ScenarioBuilder Restart() NullBloomStorage.Instance, new SyncConfig(), LimboLogs.Instance); - _chainLevelHelper = new ChainLevelHelper(NotSyncedTree, _beaconPivot, new SyncConfig(), LimboLogs.Instance); + _chainLevelHelper = new ChainLevelHelper(NotSyncedTree, _beaconPivot!, new SyncConfig(), LimboLogs.Instance); return this; } @@ -588,7 +589,7 @@ public ScenarioBuilder InsertToBlockDb(Block block) { BlockDecoder blockDecoder = new(); Rlp newRlp = blockDecoder.Encode(block); - NotSyncedTreeBuilder.BlocksDb.Set(block.Hash, newRlp.Bytes); + NotSyncedTreeBuilder.BlocksDb.Set(block.GetOrCalculateHash(), newRlp.Bytes); return this; } @@ -613,13 +614,13 @@ public ScenarioBuilder AssertChainLevel(int startNumber, int finalNumber) { for (int i = startNumber; i < finalNumber; ++i) { - ChainLevelInfo? level = NotSyncedTree.FindLevel(i); + ChainLevelInfo? level = NotSyncedTree.FindLevel(i)!; BlockInfo? blockInfo = level.MainChainBlock; blockInfo.Should().NotBe(null, $"Current block number: {i}"); - blockInfo.TotalDifficulty.Should().NotBe(0, $"Current block number: {i}"); + blockInfo!.TotalDifficulty.Should().NotBe(0, $"Current block number: {i}"); ChainLevelInfo? syncedLevel = SyncedTree.FindLevel(i); - blockInfo.BlockHash.Should().Be(syncedLevel?.MainChainBlock.BlockHash, $"Current block number: {i}"); + blockInfo.BlockHash.Should().Be(syncedLevel?.MainChainBlock!.BlockHash!, $"Current block number: {i}"); } return this; @@ -627,14 +628,14 @@ public ScenarioBuilder AssertChainLevel(int startNumber, int finalNumber) public ScenarioBuilder AssertForceNewBeaconSync() { - _beaconPivot.ShouldForceStartNewSync.Should().BeTrue(); + _beaconPivot!.ShouldForceStartNewSync.Should().BeTrue(); return this; } public ScenarioBuilder AssertNotForceNewBeaconSync() { - _beaconPivot.ShouldForceStartNewSync.Should().BeFalse(); + _beaconPivot!.ShouldForceStartNewSync.Should().BeFalse(); return this; } @@ -643,19 +644,19 @@ public ScenarioBuilder print() { // Console.WriteLine("LowestInsertedBeaconHeader:"+_notSyncedTree!.LowestInsertedBeaconHeader.Number); Console.WriteLine("Head:" + NotSyncedTree!.Head!.Number); - Console.WriteLine("BestSuggestedHeader:" + NotSyncedTree!.BestSuggestedHeader.Number); - Console.WriteLine("BestSuggestedBody:" + NotSyncedTree!.BestSuggestedBody.Number); + Console.WriteLine("BestSuggestedHeader:" + NotSyncedTree!.BestSuggestedHeader!.Number); + Console.WriteLine("BestSuggestedBody:" + NotSyncedTree!.BestSuggestedBody!.Number); // Console.WriteLine("LowestInsertedHeader:"+_notSyncedTree!.LowestInsertedHeader.Number); Console.WriteLine("BestKnownNumber:" + NotSyncedTree!.BestKnownNumber); Console.WriteLine("BestKnownBeaconNumber:" + NotSyncedTree!.BestKnownBeaconNumber); return this; } - public BlockTree SyncedTree { get; private set; } + public BlockTree SyncedTree { get; private set; } = null!; - public BlockTree NotSyncedTree { get; private set; } + public BlockTree NotSyncedTree { get; private set; } = null!; - public BlockTreeBuilder NotSyncedTreeBuilder { get; private set; } + public BlockTreeBuilder NotSyncedTreeBuilder { get; private set; } = null!; } public static ScenarioBuilder GoesLikeThis() @@ -671,7 +672,7 @@ public void FindHeader_should_throw_exception_when_trying_to_find_dangling_block .WithBlockTrees(10, 20); Block? beaconBlock = scenario.SyncedTree.FindBlock(14, BlockTreeLookupOptions.None); - scenario.InsertToHeaderDb(beaconBlock.Header); + scenario.InsertToHeaderDb(beaconBlock!.Header); Assert.Throws(() => scenario.NotSyncedTree.FindHeader(beaconBlock.Header.Hash, BlockTreeLookupOptions.None)); } @@ -681,7 +682,7 @@ public void FindBlock_should_throw_exception_when_trying_to_find_dangling_block( BlockTreeTestScenario.ScenarioBuilder scenario = BlockTreeTestScenario.GoesLikeThis() .WithBlockTrees(10, 20); - Block? beaconBlock = scenario.SyncedTree.FindBlock(14, BlockTreeLookupOptions.None); + Block? beaconBlock = scenario.SyncedTree.FindBlock(14, BlockTreeLookupOptions.None)!; scenario.InsertToBlockDb(beaconBlock); Assert.Throws(() => scenario.NotSyncedTree.FindBlock(beaconBlock.Header.Hash, BlockTreeLookupOptions.None)); } @@ -694,7 +695,7 @@ public void FindHeader_should_not_throw_exception_when_finding_blocks_with_known .InsertBeaconBlocks(18, 19); Block? beaconBlock = scenario.SyncedTree.FindBlock(14, BlockTreeLookupOptions.None); - scenario.InsertToHeaderDb(beaconBlock.Header); + scenario.InsertToHeaderDb(beaconBlock!.Header); Assert.DoesNotThrow(() => scenario.NotSyncedTree.FindHeader(beaconBlock.Header.Hash, BlockTreeLookupOptions.None)); } @@ -705,7 +706,7 @@ public void FindBlock_should_not_throw_exception_when_finding_blocks_with_known_ .WithBlockTrees(10, 20) .InsertBeaconBlocks(18, 19); - Block? beaconBlock = scenario.SyncedTree.FindBlock(14, BlockTreeLookupOptions.None); + Block? beaconBlock = scenario.SyncedTree.FindBlock(14, BlockTreeLookupOptions.None)!; scenario.InsertToBlockDb(beaconBlock); Assert.DoesNotThrow(() => scenario.NotSyncedTree.FindBlock(beaconBlock.Header.Hash, BlockTreeLookupOptions.None)); } @@ -716,7 +717,7 @@ public void FindHeader_should_not_throw_exception_when_create_level_is_missing() BlockTreeTestScenario.ScenarioBuilder scenario = BlockTreeTestScenario.GoesLikeThis() .WithBlockTrees(10, 20); - Block? beaconBlock = scenario.SyncedTree.FindBlock(14, BlockTreeLookupOptions.None); + Block? beaconBlock = scenario.SyncedTree.FindBlock(14, BlockTreeLookupOptions.None)!; scenario.InsertToHeaderDb(beaconBlock.Header); Assert.DoesNotThrow(() => scenario.NotSyncedTree.FindHeader(beaconBlock.Header.Hash, BlockTreeLookupOptions.DoNotCreateLevelIfMissing)); } @@ -727,7 +728,7 @@ public void FindBlock_should_not_throw_exception_when_create_level_is_missing() BlockTreeTestScenario.ScenarioBuilder scenario = BlockTreeTestScenario.GoesLikeThis() .WithBlockTrees(10, 20); - Block? beaconBlock = scenario.SyncedTree.FindBlock(14, BlockTreeLookupOptions.None); + Block? beaconBlock = scenario.SyncedTree.FindBlock(14, BlockTreeLookupOptions.None)!; scenario.InsertToBlockDb(beaconBlock!); Assert.DoesNotThrow(() => scenario.NotSyncedTree.FindBlock(beaconBlock.Header.Hash, BlockTreeLookupOptions.DoNotCreateLevelIfMissing)); } @@ -871,13 +872,13 @@ public void Fork_do_not_change_beacon_main_chain_block() .WithBlockTrees(4, 10) .InsertBeaconBlocks(5, 9); - ChainLevelInfo? level6 = scenario.NotSyncedTree.FindLevel(6); - Keccak previousBlockHash = level6.BeaconMainChainBlock.BlockHash; + ChainLevelInfo? level6 = scenario.NotSyncedTree.FindLevel(6)!; + Keccak previousBlockHash = level6.BeaconMainChainBlock!.BlockHash; scenario.InsertFork(6, 8); level6 = scenario.NotSyncedTree.FindLevel(6); - level6.BlockInfos.Length.Should().Be(2); - level6.BeaconMainChainBlock.BlockHash.Should().Be(previousBlockHash); + level6!.BlockInfos.Length.Should().Be(2); + level6.BeaconMainChainBlock!.BlockHash.Should().Be(previousBlockHash); } [Test] @@ -899,9 +900,9 @@ public void Can_set_total_difficulty_when_suggested_with_0() .InsertBeaconPivot(7) .InsertBeaconBlocks(8, 9, BlockTreeTestScenario.ScenarioBuilder.TotalDifficultyMode.Zero); - Block? block = scenario.NotSyncedTree.FindBlock(8, BlockTreeLookupOptions.None); + Block block = scenario.NotSyncedTree.FindBlock(8, BlockTreeLookupOptions.None)!; AddBlockResult result = scenario.NotSyncedTree.SuggestBlock(block); result.Should().Be(AddBlockResult.Added); - scenario.NotSyncedTree.FindBlock(8, BlockTreeLookupOptions.None).TotalDifficulty.Should().NotBe((UInt256)0); + scenario.NotSyncedTree.FindBlock(8, BlockTreeLookupOptions.None)!.TotalDifficulty.Should().NotBe((UInt256)0); } } diff --git a/src/Nethermind/Nethermind.Merge.Plugin.Test/EngineModuleTests.V2.cs b/src/Nethermind/Nethermind.Merge.Plugin.Test/EngineModuleTests.V2.cs index 73804c4690b..faf7149f163 100644 --- a/src/Nethermind/Nethermind.Merge.Plugin.Test/EngineModuleTests.V2.cs +++ b/src/Nethermind/Nethermind.Merge.Plugin.Test/EngineModuleTests.V2.cs @@ -340,8 +340,7 @@ public virtual async Task }; IEnumerable payloadBodies = rpc.engine_getPayloadBodiesByHashV1(blockHashes).Result.Data; - ExecutionPayloadBodyV1Result[] expected = new ExecutionPayloadBodyV1Result?[] - { + ExecutionPayloadBodyV1Result?[] expected = { new(Array.Empty(), withdrawals), null, new(txs, withdrawals) }; @@ -369,7 +368,7 @@ await rpc.engine_forkchoiceUpdatedV2(new ForkchoiceStateV1(executionPayload2.Blo IEnumerable payloadBodies = rpc.engine_getPayloadBodiesByRangeV1(1, 3).Result.Data; - ExecutionPayloadBodyV1Result[] expected = new ExecutionPayloadBodyV1Result?[] { new(txs, withdrawals) }; + ExecutionPayloadBodyV1Result?[] expected = { new(txs, withdrawals) }; payloadBodies.Should().BeEquivalentTo(expected, o => o.WithStrictOrdering()); } @@ -381,7 +380,7 @@ public async Task getPayloadBodiesByRangeV1_empty_response() IEngineRpcModule rpc = CreateEngineModule(chain); IEnumerable payloadBodies = rpc.engine_getPayloadBodiesByRangeV1(1, 1).Result.Data; - ExecutionPayloadBodyV1Result[] expected = Array.Empty(); + ExecutionPayloadBodyV1Result?[] expected = Array.Empty(); payloadBodies.Should().BeEquivalentTo(expected); } diff --git a/src/Nethermind/Nethermind.Merge.Plugin.Test/InvalidChainTracker/InvalidBlockInterceptorTest.cs b/src/Nethermind/Nethermind.Merge.Plugin.Test/InvalidChainTracker/InvalidBlockInterceptorTest.cs index 044eef33269..c1dce709da9 100644 --- a/src/Nethermind/Nethermind.Merge.Plugin.Test/InvalidChainTracker/InvalidBlockInterceptorTest.cs +++ b/src/Nethermind/Nethermind.Merge.Plugin.Test/InvalidChainTracker/InvalidBlockInterceptorTest.cs @@ -6,6 +6,7 @@ using Nethermind.Core; using Nethermind.Core.Crypto; using Nethermind.Core.Test.Builders; +using Nethermind.Crypto; using Nethermind.Logging; using Nethermind.Merge.Plugin.InvalidChainTracker; using Nethermind.Specs; @@ -39,14 +40,14 @@ public void TestValidateSuggestedBlock(bool baseReturnValue, bool isInvalidBlock _baseValidator.ValidateSuggestedBlock(block).Returns(baseReturnValue); _invalidBlockInterceptor.ValidateSuggestedBlock(block); - _tracker.Received().SetChildParent(block.Hash, block.ParentHash); + _tracker.Received().SetChildParent(block.GetOrCalculateHash(), block.ParentHash!); if (isInvalidBlockReported) { - _tracker.Received().OnInvalidBlock(block.Hash, block.ParentHash); + _tracker.Received().OnInvalidBlock(block.GetOrCalculateHash(), block.ParentHash); } else { - _tracker.DidNotReceive().OnInvalidBlock(block.Hash, block.ParentHash); + _tracker.DidNotReceive().OnInvalidBlock(block.GetOrCalculateHash(), block.ParentHash); } } @@ -60,14 +61,14 @@ public void TestValidateProcessedBlock(bool baseReturnValue, bool isInvalidBlock _baseValidator.ValidateProcessedBlock(block, txs, suggestedBlock).Returns(baseReturnValue); _invalidBlockInterceptor.ValidateProcessedBlock(block, txs, suggestedBlock); - _tracker.Received().SetChildParent(suggestedBlock.Hash, suggestedBlock.ParentHash); + _tracker.Received().SetChildParent(suggestedBlock.GetOrCalculateHash(), suggestedBlock.ParentHash!); if (isInvalidBlockReported) { - _tracker.Received().OnInvalidBlock(suggestedBlock.Hash, suggestedBlock.ParentHash); + _tracker.Received().OnInvalidBlock(suggestedBlock.GetOrCalculateHash(), suggestedBlock.ParentHash); } else { - _tracker.DidNotReceive().OnInvalidBlock(suggestedBlock.Hash, suggestedBlock.ParentHash); + _tracker.DidNotReceive().OnInvalidBlock(suggestedBlock.GetOrCalculateHash(), suggestedBlock.ParentHash); } } @@ -80,8 +81,8 @@ public void TestInvalidBlockhashShouldNotGetTracked() _baseValidator.ValidateSuggestedBlock(block).Returns(false); _invalidBlockInterceptor.ValidateSuggestedBlock(block); - _tracker.DidNotReceive().SetChildParent(block.Hash, block.ParentHash); - _tracker.DidNotReceive().OnInvalidBlock(block.Hash, block.ParentHash); + _tracker.DidNotReceive().SetChildParent(block.GetOrCalculateHash(), block.ParentHash!); + _tracker.DidNotReceive().OnInvalidBlock(block.GetOrCalculateHash(), block.ParentHash); } [Test] @@ -98,8 +99,8 @@ public void TestBlockWithNotMatchingTxShouldNotGetTracked() _baseValidator.ValidateSuggestedBlock(block).Returns(false); _invalidBlockInterceptor.ValidateSuggestedBlock(block); - _tracker.DidNotReceive().SetChildParent(block.Hash, block.ParentHash); - _tracker.DidNotReceive().OnInvalidBlock(block.Hash, block.ParentHash); + _tracker.DidNotReceive().SetChildParent(block.GetOrCalculateHash(), block.ParentHash!); + _tracker.DidNotReceive().OnInvalidBlock(block.GetOrCalculateHash(), block.ParentHash); } [Test] @@ -110,14 +111,14 @@ public void TestBlockWithIncorrectWithdrawalsShouldNotGetTracked() .TestObject; block = new Block(block.Header, block.Body.WithChangedWithdrawals( - block.Withdrawals.Take(8).ToArray() + block.Withdrawals!.Take(8).ToArray() )); _baseValidator.ValidateSuggestedBlock(block).Returns(false); _invalidBlockInterceptor.ValidateSuggestedBlock(block); - _tracker.DidNotReceive().SetChildParent(block.Hash, block.ParentHash); - _tracker.DidNotReceive().OnInvalidBlock(block.Hash, block.ParentHash); + _tracker.DidNotReceive().SetChildParent(block.GetOrCalculateHash(), block.ParentHash!); + _tracker.DidNotReceive().OnInvalidBlock(block.GetOrCalculateHash(), block.ParentHash); } } diff --git a/src/Nethermind/Nethermind.Merge.Plugin.Test/InvalidChainTracker/InvalidChainTrackerTest.cs b/src/Nethermind/Nethermind.Merge.Plugin.Test/InvalidChainTracker/InvalidChainTrackerTest.cs index 2893f170e96..0faafd424ac 100644 --- a/src/Nethermind/Nethermind.Merge.Plugin.Test/InvalidChainTracker/InvalidChainTrackerTest.cs +++ b/src/Nethermind/Nethermind.Merge.Plugin.Test/InvalidChainTracker/InvalidChainTrackerTest.cs @@ -9,6 +9,7 @@ using Nethermind.Core; using Nethermind.Core.Crypto; using Nethermind.Core.Test.Builders; +using Nethermind.Crypto; using Nethermind.Logging; using Nethermind.Merge.Plugin.Handlers; using NSubstitute; @@ -180,7 +181,7 @@ public void givenAnInvalidBlock_ifParentIsNotPostMerge_thenLastValidHashShouldBe Keccak invalidBlock = Keccak.Compute("A"); BlockHeader parentBlockHeader = new BlockHeaderBuilder().TestObject; - blockCacheService.BlockCache[parentBlockHeader.Hash] = new Block(parentBlockHeader); + blockCacheService.BlockCache[parentBlockHeader.GetOrCalculateHash()] = new Block(parentBlockHeader); IPoSSwitcher poSSwitcher = Substitute.For(); poSSwitcher.IsPostMerge(parentBlockHeader).Returns(false); @@ -200,18 +201,18 @@ public void givenAnInvalidBlock_WithUnknownParent_thenGetParentFromCache() BlockHeader parentBlockHeader = new BlockHeaderBuilder() .TestObject; BlockHeader blockHeader = new BlockHeaderBuilder() - .WithParentHash(parentBlockHeader.Hash).TestObject; + .WithParentHash(parentBlockHeader.GetOrCalculateHash()).TestObject; - blockCacheService.BlockCache[blockHeader.Hash] = new Block(blockHeader); - blockCacheService.BlockCache[parentBlockHeader.Hash] = new Block(parentBlockHeader); + blockCacheService.BlockCache[blockHeader.GetOrCalculateHash()] = new Block(blockHeader); + blockCacheService.BlockCache[parentBlockHeader.GetOrCalculateHash()] = new Block(parentBlockHeader); IPoSSwitcher alwaysPos = Substitute.For(); alwaysPos.IsPostMerge(Arg.Any()).Returns(true); _tracker = new(alwaysPos, blockFinder, blockCacheService, new TestLogManager()); // Small max section size, to make sure things propagate correctly - _tracker.OnInvalidBlock(blockHeader.Hash, null); + _tracker.OnInvalidBlock(blockHeader.GetOrCalculateHash(), null); - AssertInvalid(blockHeader.Hash, parentBlockHeader.Hash); + AssertInvalid(blockHeader.GetOrCalculateHash(), parentBlockHeader.Hash); } private void AssertValid(Keccak hash) diff --git a/src/Nethermind/Nethermind.Merge.Plugin.Test/InvalidChainTracker/InvalidHeaderInterceptorTest.cs b/src/Nethermind/Nethermind.Merge.Plugin.Test/InvalidChainTracker/InvalidHeaderInterceptorTest.cs index 76da84f0e28..1a082adb524 100644 --- a/src/Nethermind/Nethermind.Merge.Plugin.Test/InvalidChainTracker/InvalidHeaderInterceptorTest.cs +++ b/src/Nethermind/Nethermind.Merge.Plugin.Test/InvalidChainTracker/InvalidHeaderInterceptorTest.cs @@ -5,6 +5,7 @@ using Nethermind.Core; using Nethermind.Core.Crypto; using Nethermind.Core.Test.Builders; +using Nethermind.Crypto; using Nethermind.Logging; using Nethermind.Merge.Plugin.InvalidChainTracker; using NSubstitute; @@ -37,14 +38,14 @@ public void TestValidateHeader(bool baseReturnValue, bool isInvalidBlockReported _baseValidator.Validate(header, false).Returns(baseReturnValue); _invalidHeaderInterceptor.Validate(header, false); - _tracker.Received().SetChildParent(header.Hash, header.ParentHash); + _tracker.Received().SetChildParent(header.GetOrCalculateHash(), header.ParentHash!); if (isInvalidBlockReported) { - _tracker.Received().OnInvalidBlock(header.Hash, header.ParentHash); + _tracker.Received().OnInvalidBlock(header.GetOrCalculateHash(), header.ParentHash); } else { - _tracker.DidNotReceive().OnInvalidBlock(header.Hash, header.ParentHash); + _tracker.DidNotReceive().OnInvalidBlock(header.GetOrCalculateHash(), header.ParentHash); } } @@ -60,14 +61,14 @@ public void TestValidateHeaderWithParent(bool baseReturnValue, bool isInvalidBlo _baseValidator.Validate(header, parent, false).Returns(baseReturnValue); _invalidHeaderInterceptor.Validate(header, parent, false); - _tracker.Received().SetChildParent(header.Hash, header.ParentHash); + _tracker.Received().SetChildParent(header.GetOrCalculateHash(), header.ParentHash!); if (isInvalidBlockReported) { - _tracker.Received().OnInvalidBlock(header.Hash, header.ParentHash); + _tracker.Received().OnInvalidBlock(header.GetOrCalculateHash(), header.ParentHash); } else { - _tracker.DidNotReceive().OnInvalidBlock(header.Hash, header.ParentHash); + _tracker.DidNotReceive().OnInvalidBlock(header.GetOrCalculateHash(), header.ParentHash); } } @@ -84,7 +85,7 @@ public void TestInvalidBlockhashShouldNotGetTracked() _baseValidator.Validate(header, parent, false).Returns(false); _invalidHeaderInterceptor.Validate(header, parent, false); - _tracker.DidNotReceive().SetChildParent(header.Hash, header.ParentHash); - _tracker.DidNotReceive().OnInvalidBlock(header.Hash, header.ParentHash); + _tracker.DidNotReceive().SetChildParent(header.GetOrCalculateHash(), header.ParentHash!); + _tracker.DidNotReceive().OnInvalidBlock(header.GetOrCalculateHash(), header.ParentHash); } } diff --git a/src/Nethermind/Nethermind.Merge.Plugin.Test/MergeHeaderValidatorTests.cs b/src/Nethermind/Nethermind.Merge.Plugin.Test/MergeHeaderValidatorTests.cs index 3effb093527..8f181c1679e 100644 --- a/src/Nethermind/Nethermind.Merge.Plugin.Test/MergeHeaderValidatorTests.cs +++ b/src/Nethermind/Nethermind.Merge.Plugin.Test/MergeHeaderValidatorTests.cs @@ -19,18 +19,13 @@ public class MergeHeaderValidatorTests private class Context { public IPoSSwitcher PoSSwitcher => Substitute.For(); + public IHeaderValidator PreMergeHeaderValidator => Substitute.For(); - private IHeaderValidator? _preMergeHeaderValidator; - public IHeaderValidator PreMergeHeaderValidator => _preMergeHeaderValidator ?? Substitute.For(); + public IBlockTree BlockTree => Substitute.For(); - private IBlockTree? _blockTree; - public IBlockTree BlockTree => _blockTree ?? Substitute.For(); + public ISealValidator SealValidator => Substitute.For(); - private ISealValidator? _sealValidator; - public ISealValidator SealValidator => _sealValidator ?? Substitute.For(); - - private MergeHeaderValidator? _mergeHeaderValidator = null; - public MergeHeaderValidator MergeHeaderValidator => _mergeHeaderValidator ?? new MergeHeaderValidator( + public MergeHeaderValidator MergeHeaderValidator => new( PoSSwitcher, PreMergeHeaderValidator, BlockTree, diff --git a/src/Nethermind/Nethermind.Merge.Plugin.Test/MergePluginTests.cs b/src/Nethermind/Nethermind.Merge.Plugin.Test/MergePluginTests.cs index fb28b94df50..2460ac097f4 100644 --- a/src/Nethermind/Nethermind.Merge.Plugin.Test/MergePluginTests.cs +++ b/src/Nethermind/Nethermind.Merge.Plugin.Test/MergePluginTests.cs @@ -27,7 +27,7 @@ public class MergePluginTests private MergeConfig _mergeConfig = null!; private NethermindApi _context = null!; private MergePlugin _plugin = null!; - private CliquePlugin _consensusPlugin = null; + private CliquePlugin? _consensusPlugin = null; [SetUp] public void Setup() @@ -54,7 +54,7 @@ public void Setup() _context.ReceiptStorage!, _context.BlockPreprocessor!, _context.TxPool!, - _context.TransactionComparerProvider, + _context.TransactionComparerProvider!, miningConfig, _context.LogManager!); _context.ProcessExit = Substitute.For(); @@ -89,11 +89,11 @@ public void SlotPerSeconds_has_different_value_in_mergeConfig_and_blocksConfig() public void Init_merge_plugin_does_not_throw_exception(bool enabled) { _mergeConfig.TerminalTotalDifficulty = enabled ? "0" : null; - Assert.DoesNotThrowAsync(async () => await _consensusPlugin.Init(_context)); + Assert.DoesNotThrowAsync(async () => await _consensusPlugin!.Init(_context)); Assert.DoesNotThrowAsync(async () => await _plugin.Init(_context)); Assert.DoesNotThrowAsync(async () => await _plugin.InitNetworkProtocol()); Assert.DoesNotThrowAsync(async () => await _plugin.InitSynchronization()); - Assert.DoesNotThrowAsync(async () => await _plugin.InitBlockProducer(_consensusPlugin)); + Assert.DoesNotThrowAsync(async () => await _plugin.InitBlockProducer(_consensusPlugin!)); Assert.DoesNotThrowAsync(async () => await _plugin.InitRpcModules()); Assert.DoesNotThrowAsync(async () => await _plugin.DisposeAsync()); } @@ -101,17 +101,17 @@ public void Init_merge_plugin_does_not_throw_exception(bool enabled) [Test] public async Task Initializes_correctly() { - Assert.DoesNotThrowAsync(async () => await _consensusPlugin.Init(_context)); + Assert.DoesNotThrowAsync(async () => await _consensusPlugin!.Init(_context)); await _plugin.Init(_context); await _plugin.InitSynchronization(); await _plugin.InitNetworkProtocol(); ISyncConfig syncConfig = _context.Config(); Assert.IsTrue(syncConfig.NetworkingEnabled); Assert.IsTrue(_context.GossipPolicy.CanGossipBlocks); - await _plugin.InitBlockProducer(_consensusPlugin); + await _plugin.InitBlockProducer(_consensusPlugin!); Assert.IsInstanceOf(_context.BlockProducer); await _plugin.InitRpcModules(); - _context.RpcModuleProvider.Received().Register(Arg.Is>(m => m is SingletonModulePool)); + _context.RpcModuleProvider!.Received().Register(Arg.Is>(m => m is SingletonModulePool)); await _plugin.DisposeAsync(); } diff --git a/src/Nethermind/Nethermind.Merge.Plugin.Test/Nethermind.Merge.Plugin.Test.csproj b/src/Nethermind/Nethermind.Merge.Plugin.Test/Nethermind.Merge.Plugin.Test.csproj index 0b9de6e87ac..28c97e3f106 100644 --- a/src/Nethermind/Nethermind.Merge.Plugin.Test/Nethermind.Merge.Plugin.Test.csproj +++ b/src/Nethermind/Nethermind.Merge.Plugin.Test/Nethermind.Merge.Plugin.Test.csproj @@ -3,6 +3,7 @@ net7.0 enable + true diff --git a/src/Nethermind/Nethermind.Merge.Plugin.Test/Synchronization/BeaconHeadersSyncTests.cs b/src/Nethermind/Nethermind.Merge.Plugin.Test/Synchronization/BeaconHeadersSyncTests.cs index 764f7403721..bc78258de4a 100644 --- a/src/Nethermind/Nethermind.Merge.Plugin.Test/Synchronization/BeaconHeadersSyncTests.cs +++ b/src/Nethermind/Nethermind.Merge.Plugin.Test/Synchronization/BeaconHeadersSyncTests.cs @@ -10,6 +10,7 @@ using Nethermind.Core; using Nethermind.Core.Crypto; using Nethermind.Core.Test.Builders; +using Nethermind.Crypto; using Nethermind.Db; using Nethermind.Db.Blooms; using Nethermind.Logging; @@ -35,7 +36,7 @@ public class BeaconHeadersSyncTests { private class Context { - private IBlockTree _blockTree; + private IBlockTree? _blockTree; public IBlockTree BlockTree { get @@ -236,7 +237,7 @@ public async Task Finishes_when_all_downloaded() } [Test] - public async Task Feed_able_to_sync_when_new_pivot_is_set() + public void Feed_able_to_sync_when_new_pivot_is_set() { BlockTree syncedBlockTree = Build.A.BlockTree().OfChainLength(1000).TestObject; Block genesisBlock = syncedBlockTree.FindBlock(syncedBlockTree.GenesisHash, BlockTreeLookupOptions.None)!; @@ -277,7 +278,7 @@ public async Task Feed_able_to_connect_to_existing_chain_through_block_hash() Block genesisBlock = syncedBlockTree.FindBlock(syncedBlockTree.GenesisHash, BlockTreeLookupOptions.None)!; BlockTree blockTree = Build.A.BlockTree().TestObject; blockTree.SuggestBlock(genesisBlock); - Block? firstBlock = syncedBlockTree.FindBlock(1, BlockTreeLookupOptions.None); + Block? firstBlock = syncedBlockTree.FindBlock(1, BlockTreeLookupOptions.None)!; blockTree.SuggestBlock(firstBlock); BlockHeader? pivotHeader = syncedBlockTree.FindHeader(500, BlockTreeLookupOptions.None); IBeaconPivot pivot = PreparePivot(500, new SyncConfig(), blockTree, pivotHeader); @@ -295,7 +296,7 @@ public async Task Feed_able_to_connect_to_existing_chain_through_block_hash() ctx.BeaconSync.ShouldBeInBeaconHeaders().Should().BeTrue(); blockTree.BestKnownNumber.Should().Be(6); BuildHeadersSyncBatches(ctx, blockTree, syncedBlockTree, pivot, 2); - HeadersSyncBatch result = await ctx.Feed.PrepareRequest(); + HeadersSyncBatch? result = await ctx.Feed.PrepareRequest(); result.Should().BeNull(); blockTree.BestKnownNumber.Should().Be(6); ctx.Feed.CurrentState.Should().Be(SyncFeedState.Dormant); @@ -314,15 +315,15 @@ public void Feed_connect_invalid_chain() ctx.BeaconPivot = PreparePivot(99, new SyncConfig(), ctx.BlockTree, syncedBlockTree.FindHeader(99, BlockTreeLookupOptions.None)); ctx.Feed.InitializeFeed(); - HeadersSyncBatch batch = ctx.Feed.PrepareRequest().Result; - batch.Response = syncedBlockTree.FindHeaders(syncedBlockTree.FindHeader(batch.StartNumber, BlockTreeLookupOptions.None)!.Hash, batch.RequestSize, 0, false); + HeadersSyncBatch? batch = ctx.Feed.PrepareRequest().Result; + batch!.Response = syncedBlockTree.FindHeaders(syncedBlockTree.FindHeader(batch.StartNumber, BlockTreeLookupOptions.None)!.Hash, batch.RequestSize, 0, false); ctx.Feed.HandleResponse(batch); - Keccak lastHeader = syncedBlockTree.FindHeader(batch.EndNumber, BlockTreeLookupOptions.None).Hash; - Keccak headerToInvalidate = syncedBlockTree.FindHeader(batch.StartNumber + 10, BlockTreeLookupOptions.None).Hash; - Keccak lastValidHeader = syncedBlockTree.FindHeader(batch.StartNumber + 9, BlockTreeLookupOptions.None).Hash; + Keccak lastHeader = syncedBlockTree.FindHeader(batch.EndNumber, BlockTreeLookupOptions.None)!.GetOrCalculateHash(); + Keccak headerToInvalidate = syncedBlockTree.FindHeader(batch.StartNumber + 10, BlockTreeLookupOptions.None)!.GetOrCalculateHash(); + Keccak lastValidHeader = syncedBlockTree.FindHeader(batch.StartNumber + 9, BlockTreeLookupOptions.None)!.GetOrCalculateHash(); invalidChainTracker.OnInvalidBlock(headerToInvalidate, lastValidHeader); - invalidChainTracker.IsOnKnownInvalidChain(lastHeader, out Keccak storedLastValidHash).Should().BeTrue(); + invalidChainTracker.IsOnKnownInvalidChain(lastHeader, out Keccak? storedLastValidHash).Should().BeTrue(); storedLastValidHash.Should().Be(lastValidHeader); } @@ -353,8 +354,8 @@ public async Task When_pivot_changed_during_header_sync_after_chain_merged__do_n // First batch, should be enough to merge chain HeadersSyncBatch? request = await ctx.Feed.PrepareRequest(); - request.Should().NotBeNull(); - request.Response = Enumerable.Range((int)request.StartNumber, request.RequestSize) + request!.Should().NotBeNull(); + request!.Response = Enumerable.Range((int)request.StartNumber, request.RequestSize) .Select((blockNumber) => ctx.RemoteBlockTree.FindHeader(blockNumber)) .ToArray(); @@ -369,7 +370,7 @@ public async Task When_pivot_changed_during_header_sync_after_chain_merged__do_n request.Should().NotBeNull(); // We respond it again - request.Response = Enumerable.Range((int)request.StartNumber, request.RequestSize) + request!.Response = Enumerable.Range((int)request.StartNumber, request.RequestSize) .Select((blockNumber) => ctx.RemoteBlockTree.FindHeader(blockNumber)) .ToArray(); ctx.Feed.HandleResponse(request); @@ -396,7 +397,7 @@ private async void BuildAndProcessHeaderSyncBatches( BuildHeadersSyncBatches(ctx, blockTree, syncedBlockTree, pivot, endLowestBeaconHeader); - HeadersSyncBatch result = await ctx.Feed.PrepareRequest(); + HeadersSyncBatch? result = await ctx.Feed.PrepareRequest(); result.Should().BeNull(); // check headers are inserted into block tree during sync blockTree.FindHeader(pivot.PivotNumber - 1, BlockTreeLookupOptions.TotalDifficultyNotNeeded).Should().NotBeNull(); @@ -418,11 +419,11 @@ private async void BuildHeadersSyncBatches( long lowestHeaderNumber = pivot.PivotNumber; while (lowestHeaderNumber > endLowestBeaconHeader) { - HeadersSyncBatch batch = await ctx.Feed.PrepareRequest(); + HeadersSyncBatch? batch = await ctx.Feed.PrepareRequest(); batch.Should().NotBeNull(); BuildHeadersSyncBatchResponse(batch, syncedBlockTree); ctx.Feed.HandleResponse(batch); - lowestHeaderNumber = lowestHeaderNumber - batch.RequestSize < endLowestBeaconHeader + lowestHeaderNumber = lowestHeaderNumber - batch!.RequestSize < endLowestBeaconHeader ? endLowestBeaconHeader : lowestHeaderNumber - batch.RequestSize; @@ -431,9 +432,9 @@ private async void BuildHeadersSyncBatches( } } - private void BuildHeadersSyncBatchResponse(HeadersSyncBatch batch, IBlockTree blockTree) + private void BuildHeadersSyncBatchResponse(HeadersSyncBatch? batch, IBlockTree blockTree) { - batch.MarkSent(); + batch!.MarkSent(); BlockHeader? startHeader = blockTree.FindHeader(batch.StartNumber); if (startHeader is null) { diff --git a/src/Nethermind/Nethermind.Merge.Plugin.Test/Synchronization/BeaconPivotTests.cs b/src/Nethermind/Nethermind.Merge.Plugin.Test/Synchronization/BeaconPivotTests.cs index 8e19239aadc..2dbe02bd60a 100644 --- a/src/Nethermind/Nethermind.Merge.Plugin.Test/Synchronization/BeaconPivotTests.cs +++ b/src/Nethermind/Nethermind.Merge.Plugin.Test/Synchronization/BeaconPivotTests.cs @@ -7,6 +7,7 @@ using Nethermind.Core; using Nethermind.Core.Crypto; using Nethermind.Core.Test.Builders; +using Nethermind.Crypto; using Nethermind.Db; using Nethermind.Logging; using Nethermind.Merge.Plugin.Synchronization; @@ -37,7 +38,7 @@ public void Setup() public void Beacon_pivot_defaults_to_sync_config_values_when_there_is_no_pivot() { IBeaconPivot pivot = new BeaconPivot(_syncConfig, new MemDb(), Substitute.For(), LimboLogs.Instance); - pivot.PivotHash.Should().Be(_syncConfig.PivotHashParsed); + pivot.PivotHash.Should().Be(_syncConfig.PivotHashParsed!); pivot.PivotNumber.Should().Be(_syncConfig.PivotNumberParsed); pivot.PivotDestinationNumber.Should().Be(0); } @@ -51,9 +52,9 @@ public void Beacon_pivot_set_to_pivot_when_set(int processedBlocks, int expected .TestObject; IBeaconPivot pivot = new BeaconPivot(_syncConfig, new MemDb(), blockTree, LimboLogs.Instance); - BlockHeader pivotHeader = blockTree.FindHeader(10, BlockTreeLookupOptions.AllowInvalid); + BlockHeader pivotHeader = blockTree.FindHeader(10, BlockTreeLookupOptions.AllowInvalid)!; pivot.EnsurePivot(pivotHeader); - pivot.PivotHash.Should().Be(pivotHeader.Hash); + pivot.PivotHash.Should().Be(pivotHeader.GetOrCalculateHash()); pivot.PivotNumber.Should().Be(pivotHeader.Number); pivot.PivotDestinationNumber.Should().Be(expectedPivotDestinationNumber); } diff --git a/src/tests b/src/tests index ccb8a77534b..9b00b68593f 160000 --- a/src/tests +++ b/src/tests @@ -1 +1 @@ -Subproject commit ccb8a77534be6dd43d7dc42d928b84516ff47e5f +Subproject commit 9b00b68593f5869eb51a6659e1cc983e875e616b From 2a41af641076ee8c80bc16f2379bfbd980c068bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Moraczy=C5=84ski?= Date: Tue, 19 Sep 2023 10:14:59 +0200 Subject: [PATCH 20/50] Update of ethereum tests (#6105) * Update ethereum tests * One more update --- src/tests | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tests b/src/tests index 9b00b68593f..661356317ac 160000 --- a/src/tests +++ b/src/tests @@ -1 +1 @@ -Subproject commit 9b00b68593f5869eb51a6659e1cc983e875e616b +Subproject commit 661356317ac6df52208d54187e692472a25a01f8 From 24445a5cb3a51150542c114fdb49727aac200ec4 Mon Sep 17 00:00:00 2001 From: Alexey Date: Tue, 19 Sep 2023 14:47:46 +0300 Subject: [PATCH 21/50] Partially validate block with unknown parent (#6085) --- .../Validators/TestBlockValidator.cs | 6 +++ .../Validators/AlwaysValid.cs | 6 +++ .../Validators/BlockValidator.cs | 44 ++++++++++++++----- .../Validators/IBlockValidator.cs | 3 ++ .../Validators/NeverValidBlockValidator.cs | 5 +++ .../EngineModuleTests.HelperFunctions.cs | 2 +- .../EngineModuleTests.V3.cs | 24 ++++++++++ .../Handlers/NewPayloadHandler.cs | 6 +++ .../InvalidBlockInterceptor.cs | 2 + .../BlockDownloaderTests.cs | 7 +++ 10 files changed, 94 insertions(+), 11 deletions(-) diff --git a/src/Nethermind/Nethermind.Blockchain.Test/Validators/TestBlockValidator.cs b/src/Nethermind/Nethermind.Blockchain.Test/Validators/TestBlockValidator.cs index 11b632192f7..6edc6277341 100644 --- a/src/Nethermind/Nethermind.Blockchain.Test/Validators/TestBlockValidator.cs +++ b/src/Nethermind/Nethermind.Blockchain.Test/Validators/TestBlockValidator.cs @@ -55,4 +55,10 @@ public bool ValidateWithdrawals(Block block, out string? error) return _alwaysSameResultForSuggested ?? _suggestedValidationResults.Dequeue(); } + + public bool ValidateOrphanedBlock(Block block, out string? error) + { + error = null; + return _alwaysSameResultForSuggested ?? _suggestedValidationResults.Dequeue(); + } } diff --git a/src/Nethermind/Nethermind.Consensus/Validators/AlwaysValid.cs b/src/Nethermind/Nethermind.Consensus/Validators/AlwaysValid.cs index 0dc77b6e60a..be60c6375dc 100644 --- a/src/Nethermind/Nethermind.Consensus/Validators/AlwaysValid.cs +++ b/src/Nethermind/Nethermind.Consensus/Validators/AlwaysValid.cs @@ -80,4 +80,10 @@ public bool ValidateWithdrawals(Block block, out string? error) return _result; } + + public bool ValidateOrphanedBlock(Block block, out string? error) + { + error = null; + return _result; + } } diff --git a/src/Nethermind/Nethermind.Consensus/Validators/BlockValidator.cs b/src/Nethermind/Nethermind.Consensus/Validators/BlockValidator.cs index 9d3dba58e2a..575393308d3 100644 --- a/src/Nethermind/Nethermind.Consensus/Validators/BlockValidator.cs +++ b/src/Nethermind/Nethermind.Consensus/Validators/BlockValidator.cs @@ -46,6 +46,24 @@ public bool Validate(BlockHeader header, bool isUncle) return _headerValidator.Validate(header, isUncle); } + /// + /// Applies to blocks without parent + /// + /// A block to validate + /// Error description in case of failed validation + /// Validation result + /// + /// Parent may be absent during BeaconSync + /// + public bool ValidateOrphanedBlock(Block block, out string? error) + { + if (!ValidateEip4844Fields(block, _specProvider.GetSpec(block.Header), out error)) + return false; + + error = null; + return true; + } + /// /// Suggested block validation runs basic checks that can be executed before going through the expensive EVM processing. /// @@ -60,24 +78,24 @@ public bool ValidateSuggestedBlock(Block block) if (!ValidateTransactions(block, spec)) return false; - if (!ValidateEip4844Fields(block, spec)) + if (!ValidateEip4844Fields(block, spec, out _)) return false; if (spec.MaximumUncleCount < block.Uncles.Length) { - _logger.Debug($"{Invalid(block)} Uncle count of {block.Uncles.Length} exceeds the max limit of {spec.MaximumUncleCount}"); + if (_logger.IsDebug) _logger.Debug($"{Invalid(block)} Uncle count of {block.Uncles.Length} exceeds the max limit of {spec.MaximumUncleCount}"); return false; } - if (!ValidateUnclesHashMatches(block, out var unclesHash)) + if (!ValidateUnclesHashMatches(block, out Keccak unclesHash)) { - _logger.Debug($"{Invalid(block)} Uncles hash mismatch: expected {block.Header.UnclesHash}, got {unclesHash}"); + if (_logger.IsDebug) _logger.Debug($"{Invalid(block)} Uncles hash mismatch: expected {block.Header.UnclesHash}, got {unclesHash}"); return false; } if (!_unclesValidator.Validate(block.Header, block.Uncles)) { - _logger.Debug($"{Invalid(block)} Invalid uncles"); + if (_logger.IsDebug) _logger.Debug($"{Invalid(block)} Invalid uncles"); return false; } @@ -220,10 +238,11 @@ private bool ValidateTransactions(Block block, IReleaseSpec spec) return true; } - private bool ValidateEip4844Fields(Block block, IReleaseSpec spec) + private bool ValidateEip4844Fields(Block block, IReleaseSpec spec, out string? error) { if (!spec.IsEip4844Enabled) { + error = null; return true; } @@ -244,14 +263,16 @@ private bool ValidateEip4844Fields(Block block, IReleaseSpec spec) { if (!BlobGasCalculator.TryCalculateBlobGasPricePerUnit(block.Header, out blobGasPrice)) { - if (_logger.IsDebug) _logger.Debug($"{Invalid(block)} {nameof(blobGasPrice)} overflow."); + error = "{nameof(blobGasPrice)} overflow"; + if (_logger.IsDebug) _logger.Debug($"{Invalid(block)} {error}."); return false; } } if (transaction.MaxFeePerBlobGas < blobGasPrice) { - if (_logger.IsDebug) _logger.Debug($"{Invalid(block)} A transaction has unsufficient {nameof(transaction.MaxFeePerBlobGas)} to cover current blob gas fee: {transaction.MaxFeePerBlobGas} < {blobGasPrice}."); + error = $"A transaction has unsufficient {nameof(transaction.MaxFeePerBlobGas)} to cover current blob gas fee: {transaction.MaxFeePerBlobGas} < {blobGasPrice}"; + if (_logger.IsDebug) _logger.Debug($"{Invalid(block)} {error}."); return false; } @@ -262,16 +283,19 @@ private bool ValidateEip4844Fields(Block block, IReleaseSpec spec) if (blobGasUsed > Eip4844Constants.MaxBlobGasPerBlock) { - if (_logger.IsDebug) _logger.Debug($"{Invalid(block)} A block cannot have more than {Eip4844Constants.MaxBlobGasPerBlock} blob gas."); + error = $"A block cannot have more than {Eip4844Constants.MaxBlobGasPerBlock} blob gas."; + if (_logger.IsDebug) _logger.Debug($"{Invalid(block)} {error}."); return false; } if (blobGasUsed != block.Header.BlobGasUsed) { - if (_logger.IsDebug) _logger.Debug($"{Invalid(block)} {nameof(BlockHeader.BlobGasUsed)} declared in the block header does not match actual blob gas used: {block.Header.BlobGasUsed} != {blobGasUsed}."); + error = $"{Invalid(block)} {nameof(BlockHeader.BlobGasUsed)} declared in the block header does not match actual blob gas used: {block.Header.BlobGasUsed} != {blobGasUsed}."; + if (_logger.IsDebug) _logger.Debug($"{Invalid(block)} {error}."); return false; } + error = null; return true; } diff --git a/src/Nethermind/Nethermind.Consensus/Validators/IBlockValidator.cs b/src/Nethermind/Nethermind.Consensus/Validators/IBlockValidator.cs index 3aea6301417..43f99b149c1 100644 --- a/src/Nethermind/Nethermind.Consensus/Validators/IBlockValidator.cs +++ b/src/Nethermind/Nethermind.Consensus/Validators/IBlockValidator.cs @@ -7,7 +7,10 @@ namespace Nethermind.Consensus.Validators; public interface IBlockValidator : IHeaderValidator, IWithdrawalValidator { + bool ValidateOrphanedBlock(Block block, out string? error); + bool ValidateSuggestedBlock(Block block); bool ValidateProcessedBlock(Block processedBlock, TxReceipt[] receipts, Block suggestedBlock); + } diff --git a/src/Nethermind/Nethermind.Consensus/Validators/NeverValidBlockValidator.cs b/src/Nethermind/Nethermind.Consensus/Validators/NeverValidBlockValidator.cs index 649c8f7885b..d70f10eacd9 100644 --- a/src/Nethermind/Nethermind.Consensus/Validators/NeverValidBlockValidator.cs +++ b/src/Nethermind/Nethermind.Consensus/Validators/NeverValidBlockValidator.cs @@ -35,7 +35,12 @@ public bool ValidateProcessedBlock(Block processedBlock, TxReceipt[] receipts, B public bool ValidateWithdrawals(Block block, out string? error) { error = null; + return false; + } + public bool ValidateOrphanedBlock(Block block, out string? error) + { + error = null; return false; } } diff --git a/src/Nethermind/Nethermind.Merge.Plugin.Test/EngineModuleTests.HelperFunctions.cs b/src/Nethermind/Nethermind.Merge.Plugin.Test/EngineModuleTests.HelperFunctions.cs index e2b86ae6678..89b516d64b5 100644 --- a/src/Nethermind/Nethermind.Merge.Plugin.Test/EngineModuleTests.HelperFunctions.cs +++ b/src/Nethermind/Nethermind.Merge.Plugin.Test/EngineModuleTests.HelperFunctions.cs @@ -93,7 +93,7 @@ private static ExecutionPayload CreateBlockRequest(IReleaseSpec spec, IWorldStat private static ExecutionPayloadV3 CreateBlockRequestV3(IReleaseSpec spec, IWorldState state, ExecutionPayload parent, Address miner, IList? withdrawals = null, ulong? blobGasUsed = null, ulong? excessBlobGas = null, Transaction[]? transactions = null, Keccak? parentBeaconBlockRoot = null) { - var blockRequestV3 = CreateBlockRequestInternal(spec, state, parent, miner, withdrawals, blobGasUsed, excessBlobGas, transactions: transactions, parentBeaconBlockRoot: parentBeaconBlockRoot); + ExecutionPayloadV3 blockRequestV3 = CreateBlockRequestInternal(spec, state, parent, miner, withdrawals, blobGasUsed, excessBlobGas, transactions: transactions, parentBeaconBlockRoot: parentBeaconBlockRoot); blockRequestV3.TryGetBlock(out Block? block); _beaconBlockRootHandler.ApplyContractStateChanges(block!, spec, state); diff --git a/src/Nethermind/Nethermind.Merge.Plugin.Test/EngineModuleTests.V3.cs b/src/Nethermind/Nethermind.Merge.Plugin.Test/EngineModuleTests.V3.cs index 98a68e46382..76c2e7e6450 100644 --- a/src/Nethermind/Nethermind.Merge.Plugin.Test/EngineModuleTests.V3.cs +++ b/src/Nethermind/Nethermind.Merge.Plugin.Test/EngineModuleTests.V3.cs @@ -160,6 +160,30 @@ public virtual async Task NewPayloadV3_should_decline_mempool_encoding(bool inMe result.Data.Status.Should().Be(expectedPayloadStatus); } + [TestCase(false, PayloadStatus.Syncing)] + [TestCase(true, PayloadStatus.Invalid)] + public virtual async Task NewPayloadV3_should_decline_incorrect_blobgasused(bool isBlobGasUsedBroken, string expectedPayloadStatus) + { + (IEngineRpcModule prevRpcModule, string payloadId, Transaction[] transactions) = await BuildAndGetPayloadV3Result(Cancun.Instance, 1); + ExecutionPayloadV3 payload = (await prevRpcModule.engine_getPayloadV3(Bytes.FromHexString(payloadId))).Data!.ExecutionPayload; + + if (isBlobGasUsedBroken) + { + payload.BlobGasUsed += 1; + } + + payload.ParentHash = TestItem.KeccakA; + payload.BlockNumber = 2; + payload.TryGetBlock(out Block? b); + payload.BlockHash = b!.CalculateHash(); + + byte[]?[] blobVersionedHashes = transactions.SelectMany(tx => tx.BlobVersionedHashes ?? Array.Empty()).ToArray(); + ResultWrapper result = await prevRpcModule.engine_newPayloadV3(payload, blobVersionedHashes, payload.ParentBeaconBlockRoot); + + Assert.That(result.ErrorCode, Is.EqualTo(ErrorCodes.None)); + result.Data.Status.Should().Be(expectedPayloadStatus); + } + [Test] public async Task NewPayloadV3_should_decline_null_blobversionedhashes() { diff --git a/src/Nethermind/Nethermind.Merge.Plugin/Handlers/NewPayloadHandler.cs b/src/Nethermind/Nethermind.Merge.Plugin/Handlers/NewPayloadHandler.cs index 8d11c3d4b2c..babc8965e7f 100644 --- a/src/Nethermind/Nethermind.Merge.Plugin/Handlers/NewPayloadHandler.cs +++ b/src/Nethermind/Nethermind.Merge.Plugin/Handlers/NewPayloadHandler.cs @@ -126,6 +126,12 @@ public async Task> HandleAsync(ExecutionPayload r BlockHeader? parentHeader = _blockTree.FindHeader(block.ParentHash!, BlockTreeLookupOptions.DoNotCreateLevelIfMissing); if (parentHeader is null) { + if (!_blockValidator.ValidateOrphanedBlock(block!, out string? error)) + { + if (_logger.IsWarn) _logger.Info($"Invalid block without parent. Result of {requestStr}."); + return NewPayloadV1Result.Invalid(null, $"Invalid block without parent: {error}."); + } + // possible that headers sync finished before this was called, so blocks in cache weren't inserted if (!_beaconSyncStrategy.IsBeaconSyncFinished(parentHeader)) { diff --git a/src/Nethermind/Nethermind.Merge.Plugin/InvalidChainTracker/InvalidBlockInterceptor.cs b/src/Nethermind/Nethermind.Merge.Plugin/InvalidChainTracker/InvalidBlockInterceptor.cs index 3b6449280c5..71034535de8 100644 --- a/src/Nethermind/Nethermind.Merge.Plugin/InvalidChainTracker/InvalidBlockInterceptor.cs +++ b/src/Nethermind/Nethermind.Merge.Plugin/InvalidChainTracker/InvalidBlockInterceptor.cs @@ -23,6 +23,8 @@ public InvalidBlockInterceptor( _logger = logManager.GetClassLogger(typeof(InvalidBlockInterceptor)); } + public bool ValidateOrphanedBlock(Block block, out string? error) => _baseValidator.ValidateOrphanedBlock(block, out error); + public bool Validate(BlockHeader header, BlockHeader? parent, bool isUncle = false) { bool result = _baseValidator.Validate(header, parent, isUncle); diff --git a/src/Nethermind/Nethermind.Synchronization.Test/BlockDownloaderTests.cs b/src/Nethermind/Nethermind.Synchronization.Test/BlockDownloaderTests.cs index 3eb6bbdcefa..e292c1fa10f 100644 --- a/src/Nethermind/Nethermind.Synchronization.Test/BlockDownloaderTests.cs +++ b/src/Nethermind/Nethermind.Synchronization.Test/BlockDownloaderTests.cs @@ -473,6 +473,13 @@ public bool ValidateWithdrawals(Block block, out string? error) error = string.Empty; return true; } + + public bool ValidateOrphanedBlock(Block block, out string? error) + { + Thread.Sleep(1000); + error = null; + return true; + } } [Test, MaxTime(7000)] From 61233f8817d61cf38e09c32e6390198c6f35236d Mon Sep 17 00:00:00 2001 From: Lucas Cullen Date: Wed, 20 Sep 2023 02:31:00 +1000 Subject: [PATCH 22/50] Remove mining methods (#6106) * chore: begin issue #5949 * feat: remove mining methods from interface * chore: fix tests --- .../JsonRpcServiceTests.cs | 11 -------- .../Modules/Eth/EthRpcModuleTests.cs | 24 ------------------ .../Modules/Eth/EthRpcModule.cs | 25 ------------------- .../Modules/Eth/IEthRpcModule.cs | 18 ------------- 4 files changed, 78 deletions(-) diff --git a/src/Nethermind/Nethermind.JsonRpc.Test/JsonRpcServiceTests.cs b/src/Nethermind/Nethermind.JsonRpc.Test/JsonRpcServiceTests.cs index 96f44044049..85c846e3aae 100644 --- a/src/Nethermind/Nethermind.JsonRpc.Test/JsonRpcServiceTests.cs +++ b/src/Nethermind/Nethermind.JsonRpc.Test/JsonRpcServiceTests.cs @@ -150,17 +150,6 @@ public void Eth_call_is_working_with_explicit_null_as_the_last_argument(string n Assert.That(response?.Result, Is.EqualTo("0x")); } - [Test] - public void GetWorkTest() - { - IEthRpcModule ethRpcModule = Substitute.For(); - ethRpcModule.eth_getWork().ReturnsForAnyArgs(x => ResultWrapper>.Success(new[] { Bytes.FromHexString("aa"), Bytes.FromHexString("01") })); - JsonRpcSuccessResponse? response = TestRequest(ethRpcModule, "eth_getWork") as JsonRpcSuccessResponse; - byte[][]? dataList = response?.Result as byte[][]; - Assert.NotNull(dataList?.SingleOrDefault(d => d.ToHexString(true) == "0xaa")); - Assert.NotNull(dataList?.SingleOrDefault(d => d.ToHexString(true) == "0x01")); - } - [Test] public void IncorrectMethodNameTest() { diff --git a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/EthRpcModuleTests.cs b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/EthRpcModuleTests.cs index 1d1957356b5..9616e2073c7 100644 --- a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/EthRpcModuleTests.cs +++ b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/EthRpcModuleTests.cs @@ -704,30 +704,6 @@ public async Task Eth_get_code_default() Assert.That(serialized, Is.EqualTo("{\"jsonrpc\":\"2.0\",\"result\":\"0xabcd\",\"id\":67}")); } - [Test] - public async Task Eth_mining_true() - { - using Context ctx = await Context.Create(); - IBlockchainBridge bridge = Substitute.For(); - bridge.IsMining.Returns(true); - ctx.Test = await TestRpcBlockchain.ForTest(SealEngineType.NethDev).WithBlockchainBridge(bridge).Build(); - - string serialized = await ctx.Test.TestEthRpc("eth_mining"); - Assert.That(serialized, Is.EqualTo("{\"jsonrpc\":\"2.0\",\"result\":true,\"id\":67}")); - } - - [Test] - public async Task Eth_mining_false() - { - using Context ctx = await Context.Create(); - IBlockchainBridge bridge = Substitute.For(); - bridge.IsMining.Returns(false); - ctx.Test = await TestRpcBlockchain.ForTest(SealEngineType.NethDev).WithBlockchainBridge(bridge).Build(); - - string serialized = await ctx.Test.TestEthRpc("eth_mining"); - Assert.That(serialized, Is.EqualTo("{\"jsonrpc\":\"2.0\",\"result\":false,\"id\":67}")); - } - [Test] public async Task Eth_accounts() { diff --git a/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/EthRpcModule.cs b/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/EthRpcModule.cs index b60d9552cbf..27b56d954b8 100644 --- a/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/EthRpcModule.cs +++ b/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/EthRpcModule.cs @@ -110,16 +110,6 @@ public ResultWrapper
eth_coinbase() return ResultWrapper
.Success(Address.Zero); } - public ResultWrapper eth_mining() - { - return ResultWrapper.Success(_blockchainBridge.IsMining); - } - - public ResultWrapper eth_hashrate() - { - return ResultWrapper.Success(0); - } - public ResultWrapper eth_gasPrice() { return ResultWrapper.Success(_gasPriceOracle.GetGasPriceEstimate()); @@ -652,21 +642,6 @@ public ResultWrapper> eth_getLogs(Filter filter) } } - public ResultWrapper> eth_getWork() - { - return ResultWrapper>.Fail("eth_getWork not supported", ErrorCodes.MethodNotFound); - } - - public ResultWrapper eth_submitWork(byte[] nonce, Keccak headerPowHash, byte[] mixDigest) - { - return ResultWrapper.Fail("eth_submitWork not supported", ErrorCodes.MethodNotFound, null); - } - - public ResultWrapper eth_submitHashrate(string hashRate, string id) - { - return ResultWrapper.Fail("eth_submitHashrate not supported", ErrorCodes.MethodNotFound, null); - } - // https://github.com/ethereum/EIPs/issues/1186 public ResultWrapper eth_getProof(Address accountAddress, UInt256[] storageKeys, BlockParameter blockParameter) diff --git a/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/IEthRpcModule.cs b/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/IEthRpcModule.cs index bf844a5d701..79a7ba6f8a0 100644 --- a/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/IEthRpcModule.cs +++ b/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/IEthRpcModule.cs @@ -41,9 +41,6 @@ public interface IEthRpcModule : IRpcModule ExampleResponse = "0x0000000000000000000000000000000000000000")] ResultWrapper
eth_coinbase(); - [JsonRpcMethod(IsImplemented = false, Description = "Returns mining status", IsSharable = true)] - ResultWrapper eth_mining(); - [JsonRpcMethod(IsImplemented = true, Description = "Returns block fee history.", IsSharable = true, @@ -56,12 +53,6 @@ public interface IEthRpcModule : IRpcModule [JsonRpcMethod(IsImplemented = false, Description = "", IsSharable = true)] ResultWrapper eth_maxPriorityFeePerGas(); - [JsonRpcMethod(IsImplemented = false, - Description = "Returns mining hashrate", - IsSharable = true, - ExampleResponse = "0x0")] - ResultWrapper eth_hashrate(); - [JsonRpcMethod(IsImplemented = false, Description = "Returns miner's gas price", IsSharable = true, @@ -258,15 +249,6 @@ ResultWrapper eth_getTransactionByBlockNumberAndIndex( [JsonRpcMethod(IsImplemented = true, Description = "Reads logs", IsSharable = false)] ResultWrapper> eth_getLogs(Filter filter); - [JsonRpcMethod(Description = "", IsImplemented = false, IsSharable = true)] - ResultWrapper> eth_getWork(); - - [JsonRpcMethod(Description = "", IsImplemented = false, IsSharable = false)] - ResultWrapper eth_submitWork(byte[] nonce, Keccak headerPowHash, byte[] mixDigest); - - [JsonRpcMethod(Description = "", IsImplemented = false, IsSharable = false)] - ResultWrapper eth_submitHashrate(string hashRate, string id); - [JsonRpcMethod(Description = "https://github.com/ethereum/EIPs/issues/1186", IsImplemented = true, IsSharable = true, From a38e466e22feeb850e8af9252952060c1d0c2c85 Mon Sep 17 00:00:00 2001 From: Lautaro Emanuel <31224949+emlautarom1@users.noreply.github.com> Date: Tue, 19 Sep 2023 13:31:52 -0300 Subject: [PATCH 23/50] Do not override 'HealthCheckService' log levels (#6109) --- .../Nethermind.Runner/Logging/NLogConfigurator.cs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/Nethermind/Nethermind.Runner/Logging/NLogConfigurator.cs b/src/Nethermind/Nethermind.Runner/Logging/NLogConfigurator.cs index 570c7db86a9..ac0fa79ca1b 100644 --- a/src/Nethermind/Nethermind.Runner/Logging/NLogConfigurator.cs +++ b/src/Nethermind/Nethermind.Runner/Logging/NLogConfigurator.cs @@ -69,10 +69,16 @@ public static void ConfigureLogLevels(CommandOption logLevelOverride) Console.WriteLine($"Enabling log level override: {logLevel.ToUpperInvariant()}"); + // There are some rules for which we don't want to override the log level + // but instead preserve the original config defined in the 'NLog.config' file + string[] ignoredRuleNames = + { + "JsonWebAPI*", + "JsonWebAPI.Microsoft.Extensions.Diagnostics.HealthChecks.DefaultHealthCheckService", + }; foreach (LoggingRule rule in LogManager.Configuration.LoggingRules) { - // WORKAROUND: Skip modifying 'JsonWebAPI*' rules since we want to preserve the original config on the 'NLog.config' file - if (rule.LoggerNamePattern == "JsonWebAPI*") { continue; } + if (ignoredRuleNames.Contains(rule.LoggerNamePattern)) { continue; } foreach (var ruleTarget in rule.Targets) { From 771476322560fe5f5ddfa45bd081cf8bedd00ec3 Mon Sep 17 00:00:00 2001 From: Ruben Buniatyan Date: Tue, 19 Sep 2023 18:35:24 +0200 Subject: [PATCH 24/50] Fix symlinks for macOS packages (#6095) --- scripts/deployment/archive-packages.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/deployment/archive-packages.sh b/scripts/deployment/archive-packages.sh index f4bc2814c1a..77d91775abe 100755 --- a/scripts/deployment/archive-packages.sh +++ b/scripts/deployment/archive-packages.sh @@ -13,8 +13,8 @@ cd $PUB_DIR cd linux-x64 && zip -r -y $GITHUB_WORKSPACE/$PACKAGE_DIR/$PACKAGE_PREFIX-linux-x64.zip . && cd .. cd linux-arm64 && zip -r -y $GITHUB_WORKSPACE/$PACKAGE_DIR/$PACKAGE_PREFIX-linux-arm64.zip . && cd .. cd win-x64 && zip -r $GITHUB_WORKSPACE/$PACKAGE_DIR/$PACKAGE_PREFIX-windows-x64.zip . && cd .. -cd osx-x64 && zip -r $GITHUB_WORKSPACE/$PACKAGE_DIR/$PACKAGE_PREFIX-macos-x64.zip . && cd .. -cd osx-arm64 && zip -r $GITHUB_WORKSPACE/$PACKAGE_DIR/$PACKAGE_PREFIX-macos-arm64.zip . && cd .. +cd osx-x64 && zip -r -y $GITHUB_WORKSPACE/$PACKAGE_DIR/$PACKAGE_PREFIX-macos-x64.zip . && cd .. +cd osx-arm64 && zip -r -y $GITHUB_WORKSPACE/$PACKAGE_DIR/$PACKAGE_PREFIX-macos-arm64.zip . && cd .. cd ref && zip -r $GITHUB_WORKSPACE/$PACKAGE_DIR/$PACKAGE_PREFIX-ref-assemblies.zip . && cd .. echo "Archiving completed" From e61087863d6542e129d26f0f0ae53a48cbdebca4 Mon Sep 17 00:00:00 2001 From: Lautaro Emanuel <31224949+emlautarom1@users.noreply.github.com> Date: Tue, 19 Sep 2023 17:16:35 -0300 Subject: [PATCH 25/50] Reject non-nullable aggregate types when deserializing method parameters (#6104) * Reject non nullable aggregate types on deserialization * Add tests for `eth_getTransactionReceipt` with invalid params * Fix warnings and suggestions * Add 'Type.Missing' instead of throwing exceptions --- .../JsonRpcServiceTests.cs | 44 +++++++++++++------ .../Nethermind.JsonRpc/JsonRpcService.cs | 4 ++ 2 files changed, 34 insertions(+), 14 deletions(-) diff --git a/src/Nethermind/Nethermind.JsonRpc.Test/JsonRpcServiceTests.cs b/src/Nethermind/Nethermind.JsonRpc.Test/JsonRpcServiceTests.cs index 85c846e3aae..652e10cdd81 100644 --- a/src/Nethermind/Nethermind.JsonRpc.Test/JsonRpcServiceTests.cs +++ b/src/Nethermind/Nethermind.JsonRpc.Test/JsonRpcServiceTests.cs @@ -5,7 +5,6 @@ using System.Collections.Generic; using System.IO.Abstractions; using System.Linq; -using System.Reflection; using FluentAssertions; using Nethermind.Blockchain.Find; using Nethermind.Config; @@ -35,7 +34,6 @@ public class JsonRpcServiceTests [SetUp] public void Initialize() { - Assembly jConfig = typeof(JsonRpcConfig).Assembly; _configurationProvider = new ConfigProvider(); _logManager = LimboLogs.Instance; _context = new JsonRpcContext(RpcEndpoint.Http); @@ -49,7 +47,7 @@ public void Initialize() private JsonRpcResponse TestRequest(T module, string method, params string[] parameters) where T : IRpcModule { RpcModuleProvider moduleProvider = new(new FileSystem(), _configurationProvider.GetConfig(), LimboLogs.Instance); - moduleProvider.Register(new SingletonModulePool(new SingletonFactory(module), true)); + moduleProvider.Register(new SingletonModulePool(new SingletonFactory(module), allowExclusive: true)); _jsonRpcService = new JsonRpcService(moduleProvider, _logManager, _configurationProvider.GetConfig()); JsonRpcRequest request = RpcTest.GetJsonRequest(method, parameters); JsonRpcResponse response = _jsonRpcService.SendRequestAsync(request, _context).Result; @@ -62,7 +60,7 @@ public void GetBlockByNumberTest() { IEthRpcModule ethRpcModule = Substitute.For(); ISpecProvider specProvider = Substitute.For(); - ethRpcModule.eth_getBlockByNumber(Arg.Any(), true).ReturnsForAnyArgs(x => ResultWrapper.Success(new BlockForRpc(Build.A.Block.WithNumber(2).TestObject, true, specProvider))); + ethRpcModule.eth_getBlockByNumber(Arg.Any(), true).ReturnsForAnyArgs(_ => ResultWrapper.Success(new BlockForRpc(Build.A.Block.WithNumber(2).TestObject, true, specProvider))); JsonRpcSuccessResponse? response = TestRequest(ethRpcModule, "eth_getBlockByNumber", "0x1b4", "true") as JsonRpcSuccessResponse; Assert.That((response?.Result as BlockForRpc)?.Number, Is.EqualTo(2L)); } @@ -72,7 +70,7 @@ public void Eth_module_populates_size_when_returning_block_data() { IEthRpcModule ethRpcModule = Substitute.For(); ISpecProvider specProvider = Substitute.For(); - ethRpcModule.eth_getBlockByNumber(Arg.Any(), true).ReturnsForAnyArgs(x => ResultWrapper.Success(new BlockForRpc(Build.A.Block.WithNumber(2).TestObject, true, specProvider))); + ethRpcModule.eth_getBlockByNumber(Arg.Any(), true).ReturnsForAnyArgs(_ => ResultWrapper.Success(new BlockForRpc(Build.A.Block.WithNumber(2).TestObject, true, specProvider))); JsonRpcSuccessResponse? response = TestRequest(ethRpcModule, "eth_getBlockByNumber", "0x1b4", "true") as JsonRpcSuccessResponse; Assert.That((response?.Result as BlockForRpc)?.Size, Is.EqualTo(513L)); } @@ -83,7 +81,7 @@ public void CanHandleOptionalArguments() EthereumJsonSerializer serializer = new(); string serialized = serializer.Serialize(new TransactionForRpc()); IEthRpcModule ethRpcModule = Substitute.For(); - ethRpcModule.eth_call(Arg.Any()).ReturnsForAnyArgs(x => ResultWrapper.Success("0x1")); + ethRpcModule.eth_call(Arg.Any()).ReturnsForAnyArgs(_ => ResultWrapper.Success("0x1")); JsonRpcSuccessResponse? response = TestRequest(ethRpcModule, "eth_call", serialized) as JsonRpcSuccessResponse; Assert.That(response?.Result, Is.EqualTo("0x1")); } @@ -101,7 +99,7 @@ public void Case_sensitivity_test() public void GetNewFilterTest() { IEthRpcModule ethRpcModule = Substitute.For(); - ethRpcModule.eth_newFilter(Arg.Any()).ReturnsForAnyArgs(x => ResultWrapper.Success(1)); + ethRpcModule.eth_newFilter(Arg.Any()).ReturnsForAnyArgs(_ => ResultWrapper.Success(1)); var parameters = new { @@ -128,7 +126,7 @@ public void Eth_call_is_working_with_implicit_null_as_the_last_argument() { EthereumJsonSerializer serializer = new(); IEthRpcModule ethRpcModule = Substitute.For(); - ethRpcModule.eth_call(Arg.Any(), Arg.Any()).ReturnsForAnyArgs(x => ResultWrapper.Success("0x")); + ethRpcModule.eth_call(Arg.Any(), Arg.Any()).ReturnsForAnyArgs(_ => ResultWrapper.Success("0x")); string serialized = serializer.Serialize(new TransactionForRpc()); @@ -142,7 +140,7 @@ public void Eth_call_is_working_with_explicit_null_as_the_last_argument(string n { EthereumJsonSerializer serializer = new(); IEthRpcModule ethRpcModule = Substitute.For(); - ethRpcModule.eth_call(Arg.Any(), Arg.Any()).ReturnsForAnyArgs(x => ResultWrapper.Success("0x")); + ethRpcModule.eth_call(Arg.Any(), Arg.Any()).ReturnsForAnyArgs(_ => ResultWrapper.Success("0x")); string serialized = serializer.Serialize(new TransactionForRpc()); @@ -150,6 +148,24 @@ public void Eth_call_is_working_with_explicit_null_as_the_last_argument(string n Assert.That(response?.Result, Is.EqualTo("0x")); } + [Test] + public void Eth_getTransactionReceipt_properly_fails_given_wrong_parameters() + { + IEthRpcModule ethRpcModule = Substitute.For(); + + string[] parameters = { + """["0x80757153e93d1b475e203406727b62a501187f63e23b8fa999279e219ee3be71"]""" + }; + JsonRpcResponse response = TestRequest(ethRpcModule, "eth_getTransactionReceipt", parameters); + + response.Should() + .BeAssignableTo() + .Which + .Error.Should().NotBeNull(); + Error error = (response as JsonRpcErrorResponse)!.Error!; + error.Code.Should().Be(ErrorCodes.InvalidParams); + } + [Test] public void IncorrectMethodNameTest() { @@ -161,7 +177,7 @@ public void IncorrectMethodNameTest() public void NetVersionTest() { INetRpcModule netRpcModule = Substitute.For(); - netRpcModule.net_version().ReturnsForAnyArgs(x => ResultWrapper.Success("1")); + netRpcModule.net_version().ReturnsForAnyArgs(_ => ResultWrapper.Success("1")); JsonRpcSuccessResponse? response = TestRequest(netRpcModule, "net_version") as JsonRpcSuccessResponse; Assert.That(response?.Result, Is.EqualTo("1")); Assert.IsNotInstanceOf(response); @@ -171,7 +187,7 @@ public void NetVersionTest() public void Web3ShaTest() { IWeb3RpcModule web3RpcModule = Substitute.For(); - web3RpcModule.web3_sha3(Arg.Any()).ReturnsForAnyArgs(x => ResultWrapper.Success(TestItem.KeccakA)); + web3RpcModule.web3_sha3(Arg.Any()).ReturnsForAnyArgs(_ => ResultWrapper.Success(TestItem.KeccakA)); JsonRpcSuccessResponse? response = TestRequest(web3RpcModule, "web3_sha3", "0x68656c6c6f20776f726c64") as JsonRpcSuccessResponse; Assert.That(response?.Result, Is.EqualTo(TestItem.KeccakA)); } @@ -179,13 +195,13 @@ public void Web3ShaTest() [TestCaseSource(nameof(BlockForRpcTestSource))] public void BlockForRpc_should_expose_withdrawals_if_any((bool Expected, Block Block) item) { - var specProvider = Substitute.For(); - var rpcBlock = new BlockForRpc(item.Block, false, specProvider); + ISpecProvider? specProvider = Substitute.For(); + BlockForRpc rpcBlock = new(item.Block, false, specProvider); rpcBlock.WithdrawalsRoot.Should().BeEquivalentTo(item.Block.WithdrawalsRoot); rpcBlock.Withdrawals.Should().BeEquivalentTo(item.Block.Withdrawals); - var json = new EthereumJsonSerializer().Serialize(rpcBlock); + string? json = new EthereumJsonSerializer().Serialize(rpcBlock); json.Contains("withdrawals\"", StringComparison.Ordinal).Should().Be(item.Expected); json.Contains("withdrawalsRoot", StringComparison.Ordinal).Should().Be(item.Expected); diff --git a/src/Nethermind/Nethermind.JsonRpc/JsonRpcService.cs b/src/Nethermind/Nethermind.JsonRpc/JsonRpcService.cs index 0cba05fee8e..761e49e2e54 100644 --- a/src/Nethermind/Nethermind.JsonRpc/JsonRpcService.cs +++ b/src/Nethermind/Nethermind.JsonRpc/JsonRpcService.cs @@ -325,6 +325,10 @@ private void LogRequest(string methodName, string?[] providedParameters, Paramet if (providedParameter.StartsWith('[') || providedParameter.StartsWith('{')) { executionParam = _serializer.Deserialize(new JsonTextReader(new StringReader(providedParameter)), paramType); + if (executionParam is null && !IsNullableParameter(expectedParameter)) + { + executionParameters.Add(Type.Missing); + } } else { From aad88eec562bfe6a1ef4565d79b9d879ee599738 Mon Sep 17 00:00:00 2001 From: Lautaro Emanuel <31224949+emlautarom1@users.noreply.github.com> Date: Wed, 20 Sep 2023 12:28:57 -0300 Subject: [PATCH 26/50] Remove warnings from `Nethermind.Core.Test` (#6113) * Remove warnings from `Nethermind.Core.Test` * Treat warnings as errors --- .../Builders/ReceiptBuilder.cs | 10 +++---- .../Encoding/BlockInfoDecoderTests.cs | 2 +- .../Encoding/TxDecoderTests.cs | 28 +++++++++---------- .../Nethermind.Core.Test.csproj | 1 + .../RequestSizer/AdaptiveRequestSizerTests.cs | 2 +- .../Nethermind.Core.Test/RlpTests.cs | 8 +++--- 6 files changed, 25 insertions(+), 26 deletions(-) diff --git a/src/Nethermind/Nethermind.Core.Test/Builders/ReceiptBuilder.cs b/src/Nethermind/Nethermind.Core.Test/Builders/ReceiptBuilder.cs index 1703e7d50bc..c20dd7a5990 100644 --- a/src/Nethermind/Nethermind.Core.Test/Builders/ReceiptBuilder.cs +++ b/src/Nethermind/Nethermind.Core.Test/Builders/ReceiptBuilder.cs @@ -48,7 +48,7 @@ public ReceiptBuilder WithTxType(TxType txType) return this; } - public ReceiptBuilder WithTransactionHash(Keccak hash) + public ReceiptBuilder WithTransactionHash(Keccak? hash) { TestObject.TxHash = hash; return this; @@ -60,7 +60,7 @@ public ReceiptBuilder WithBlockNumber(long number) return this; } - public ReceiptBuilder WithBlockHash(Keccak hash) + public ReceiptBuilder WithBlockHash(Keccak? hash) { TestObject.BlockHash = hash; return this; @@ -84,7 +84,7 @@ public ReceiptBuilder WithBloom(Bloom bloom) return this; } - public ReceiptBuilder WithError(string error) + public ReceiptBuilder WithError(string? error) { TestObjectInternal.Error = error; return this; @@ -102,13 +102,13 @@ public ReceiptBuilder WithSender(Address sender) return this; } - public ReceiptBuilder WithContractAddress(Address contractAddress) + public ReceiptBuilder WithContractAddress(Address? contractAddress) { TestObjectInternal.ContractAddress = contractAddress; return this; } - public ReceiptBuilder WithRecipient(Address recipient) + public ReceiptBuilder WithRecipient(Address? recipient) { TestObjectInternal.Recipient = recipient; return this; diff --git a/src/Nethermind/Nethermind.Core.Test/Encoding/BlockInfoDecoderTests.cs b/src/Nethermind/Nethermind.Core.Test/Encoding/BlockInfoDecoderTests.cs index f719f591021..7b339aa1d0e 100644 --- a/src/Nethermind/Nethermind.Core.Test/Encoding/BlockInfoDecoderTests.cs +++ b/src/Nethermind/Nethermind.Core.Test/Encoding/BlockInfoDecoderTests.cs @@ -102,7 +102,7 @@ public static Rlp BlockInfoEncodeDeprecated(BlockInfo? item, bool chainWithFinal stream.Encode(item.IsFinalized); } - return new Rlp(stream.Data); + return new Rlp(stream.Data!); } } } diff --git a/src/Nethermind/Nethermind.Core.Test/Encoding/TxDecoderTests.cs b/src/Nethermind/Nethermind.Core.Test/Encoding/TxDecoderTests.cs index 898b2da33ab..cfb72973507 100644 --- a/src/Nethermind/Nethermind.Core.Test/Encoding/TxDecoderTests.cs +++ b/src/Nethermind/Nethermind.Core.Test/Encoding/TxDecoderTests.cs @@ -79,7 +79,7 @@ public void CanCorrectlyCalculateTxHash_when_called_concurrently((Transaction Tx Keccak expectedHash = Keccak.Compute(rlp.Bytes); - Transaction decodedTx = decoder.Decode(new RlpStream(rlp.Bytes)); + Transaction decodedTx = decoder.Decode(new RlpStream(rlp.Bytes))!; decodedTx.SetPreHash(rlp.Bytes); @@ -149,7 +149,7 @@ public void ValueDecoderContext_DecodeWithMemorySlice_ShouldUseSameBuffer((Trans rlpStream.Position = 0; Transaction? decoded = _txDecoder.Decode(ref decoderContext); - byte[] data1 = decoded.Data.Value.ToArray(); + byte[] data1 = decoded!.Data!.Value.ToArray(); data1.AsSpan().Fill(1); rlpStream.Data.AsSpan().Fill(1); @@ -162,7 +162,7 @@ public void Roundtrip_yolo_v3((string IncomingRlpHex, Keccak Hash) testCase) TestContext.Out.WriteLine($"Testing {testCase.Hash}"); RlpStream incomingTxRlp = Bytes.FromHexString(testCase.IncomingRlpHex).AsRlpStream(); - Transaction decoded = _txDecoder.Decode(incomingTxRlp); + Transaction decoded = _txDecoder.Decode(incomingTxRlp)!; decoded.CalculateHash().Should().Be(testCase.Hash); RlpStream ourRlpOutput = new(incomingTxRlp.Length * 2); @@ -178,10 +178,10 @@ public void CalculateHash_and_tx_hash_after_decoding_return_the_same_value( { TestContext.Out.WriteLine($"Testing {testCase.Hash}"); RlpStream incomingTxRlp = Bytes.FromHexString(testCase.IncomingRlpHex).AsRlpStream(); - Transaction decoded = _txDecoder.Decode(incomingTxRlp); + Transaction decoded = _txDecoder.Decode(incomingTxRlp)!; Rlp encodedForTreeRoot = _txDecoder.Encode(decoded, RlpBehaviors.SkipTypedWrapping); - decoded.CalculateHash().Should().Be(decoded.Hash); + decoded.CalculateHash().Should().Be(decoded.Hash!); decoded.Hash.Should().Be(Keccak.Compute(encodedForTreeRoot.Bytes)); } @@ -190,7 +190,7 @@ public void Hash_calculation_do_not_change_after_roundtrip((string IncomingRlpHe { TestContext.Out.WriteLine($"Testing {testCase.Hash}"); RlpStream incomingTxRlp = Bytes.FromHexString(testCase.IncomingRlpHex).AsRlpStream(); - Transaction decoded = _txDecoder.Decode(incomingTxRlp); + Transaction decoded = _txDecoder.Decode(incomingTxRlp)!; Rlp encodedForTreeRoot = _txDecoder.Encode(decoded, RlpBehaviors.SkipTypedWrapping); decoded.Hash.Should().Be(Keccak.Compute(encodedForTreeRoot.Bytes)); } @@ -200,7 +200,7 @@ public void Hash_calculation_do_not_change_after_roundtrip2((string IncomingRlpH { TestContext.Out.WriteLine($"Testing {testCase.Hash}"); RlpStream incomingTxRlp = Bytes.FromHexString(testCase.IncomingRlpHex).AsRlpStream(); - Transaction decoded = _txDecoder.Decode(incomingTxRlp); + Transaction decoded = _txDecoder.Decode(incomingTxRlp)!; Rlp encodedForTreeRoot = _txDecoder.Encode(decoded, RlpBehaviors.SkipTypedWrapping); decoded.Hash.Should().Be(Keccak.Compute(encodedForTreeRoot.Bytes)); } @@ -226,14 +226,12 @@ private void ValueDecoderContext_return_the_same_transaction_as_rlp_stream( RlpStream incomingTxRlp = Bytes.FromHexString(testCase.IncomingRlpHex).AsRlpStream(); Span spanIncomingTxRlp = Bytes.FromHexString(testCase.IncomingRlpHex).AsSpan(); Rlp.ValueDecoderContext decoderContext = new(spanIncomingTxRlp); - Transaction decodedByValueDecoderContext = _txDecoder.Decode(ref decoderContext, - wrapping ? RlpBehaviors.SkipTypedWrapping : RlpBehaviors.None); - Transaction decoded = _txDecoder.Decode(incomingTxRlp, - wrapping ? RlpBehaviors.SkipTypedWrapping : RlpBehaviors.None); - Rlp encoded = _txDecoder.Encode(decoded!); - Rlp encodedWithDecodedByValueDecoderContext = _txDecoder.Encode(decodedByValueDecoderContext!); - decoded!.Hash.Should().Be(testCase.Hash); - decoded!.Hash.Should().Be(decodedByValueDecoderContext!.Hash); + Transaction decodedByValueDecoderContext = _txDecoder.Decode(ref decoderContext, wrapping ? RlpBehaviors.SkipTypedWrapping : RlpBehaviors.None)!; + Transaction decoded = _txDecoder.Decode(incomingTxRlp, wrapping ? RlpBehaviors.SkipTypedWrapping : RlpBehaviors.None)!; + Rlp encoded = _txDecoder.Encode(decoded); + Rlp encodedWithDecodedByValueDecoderContext = _txDecoder.Encode(decodedByValueDecoderContext); + decoded.Hash.Should().Be(testCase.Hash); + decoded.Hash.Should().Be(decodedByValueDecoderContext.Hash!); Assert.That(encodedWithDecodedByValueDecoderContext.Bytes, Is.EqualTo(encoded.Bytes)); } diff --git a/src/Nethermind/Nethermind.Core.Test/Nethermind.Core.Test.csproj b/src/Nethermind/Nethermind.Core.Test/Nethermind.Core.Test.csproj index 82355dc82b7..3dcb93f2ff2 100644 --- a/src/Nethermind/Nethermind.Core.Test/Nethermind.Core.Test.csproj +++ b/src/Nethermind/Nethermind.Core.Test/Nethermind.Core.Test.csproj @@ -5,6 +5,7 @@ latest true enable + true diff --git a/src/Nethermind/Nethermind.Core.Test/RequestSizer/AdaptiveRequestSizerTests.cs b/src/Nethermind/Nethermind.Core.Test/RequestSizer/AdaptiveRequestSizerTests.cs index f278457bcac..37687d77c1c 100644 --- a/src/Nethermind/Nethermind.Core.Test/RequestSizer/AdaptiveRequestSizerTests.cs +++ b/src/Nethermind/Nethermind.Core.Test/RequestSizer/AdaptiveRequestSizerTests.cs @@ -22,7 +22,7 @@ public async Task Test_Threshold(int minSize, int maxSize, int startingSize, Ada { AdaptiveRequestSizer sizer = new(minSize, maxSize, startingSize); - await sizer.Run((async requestSize => (requestSize, direction))); + await sizer.Run((requestSize => Task.FromResult((requestSize, direction)))); sizer.RequestSize.Should().Be(afterRequestSize); } diff --git a/src/Nethermind/Nethermind.Core.Test/RlpTests.cs b/src/Nethermind/Nethermind.Core.Test/RlpTests.cs index 9810b2cfcf1..502e8e3dae4 100644 --- a/src/Nethermind/Nethermind.Core.Test/RlpTests.cs +++ b/src/Nethermind/Nethermind.Core.Test/RlpTests.cs @@ -41,7 +41,7 @@ public void Serializing_sequence_with_one_int_regression() [Explicit("That was a regression test but now it is failing again and cannot find the reason we needed this behaviour in the first place. Sync works all fine. Leaving it here as it may resurface - make sure to add more explanation to it in such case.")] public void Serializing_object_int_regression() { - Rlp output = Rlp.Encode(new Rlp[] { Rlp.Encode(1) }); + Rlp output = Rlp.Encode(new[] { Rlp.Encode(1) }); Assert.That(output.Bytes, Is.EqualTo(new byte[] { 1 })); } @@ -64,7 +64,7 @@ public void Length_of_uint() public void Long_negative() { Rlp output = Rlp.Encode(-1L); - var context = new RlpStream(output.Bytes); + RlpStream context = new RlpStream(output.Bytes); long value = context.DecodeLong(); Assert.That(value, Is.EqualTo(-1L)); @@ -73,7 +73,7 @@ public void Long_negative() [Test] public void Empty_byte_array() { - byte[] bytes = new byte[0]; + byte[] bytes = Array.Empty(); Rlp rlp = Rlp.Encode(bytes); Rlp rlpSpan = Rlp.Encode(bytes.AsSpan()); Rlp expectedResult = new(new byte[] { 128 }); @@ -241,7 +241,7 @@ public void RlpContextWithSliceMemory_shouldNotCopyUnderlyingData(bool sliceValu { Memory? slice = context.DecodeByteArrayMemory(); slice.Should().NotBeNull(); - MemoryMarshal.TryGetArray(slice.Value, out ArraySegment segment); + MemoryMarshal.TryGetArray(slice!.Value, out ArraySegment segment); bool isACopy = (segment.Offset == 0 && segment.Count == slice.Value.Length); isACopy.Should().NotBe(sliceValue); From 0e4be2fa19eeddb9265c611118f3e508935f6a33 Mon Sep 17 00:00:00 2001 From: Amirul Ashraf Date: Thu, 21 Sep 2023 15:12:22 +0800 Subject: [PATCH 27/50] Perf/set malloc ops (#6110) * Set malloc options * Use a different setting * Adjust config * Split malloc calls to a separate file * More unit test and minor cleanup * Whitespace * Check if linux --- src/Nethermind/Nethermind.Api/IInitConfig.cs | 3 ++ src/Nethermind/Nethermind.Api/InitConfig.cs | 1 + .../Memory/MallocHelperTests.cs | 18 ++++++++++ .../Nethermind.Core/Memory/MallocHelper.cs | 33 +++++++++++++++++++ .../Nethermind.Init/MemoryHintMan.cs | 26 ++++++++++++++- .../MemoryHintManTests.cs | 23 ++++++++++++- 6 files changed, 102 insertions(+), 2 deletions(-) create mode 100644 src/Nethermind/Nethermind.Core.Test/Memory/MallocHelperTests.cs create mode 100644 src/Nethermind/Nethermind.Core/Memory/MallocHelper.cs diff --git a/src/Nethermind/Nethermind.Api/IInitConfig.cs b/src/Nethermind/Nethermind.Api/IInitConfig.cs index 33fad6328dd..4653e101a14 100644 --- a/src/Nethermind/Nethermind.Api/IInitConfig.cs +++ b/src/Nethermind/Nethermind.Api/IInitConfig.cs @@ -73,6 +73,9 @@ public interface IInitConfig : IConfig [ConfigItem(Description = "A hint for the max memory that will allow us to configure the DB and Netty memory allocations.", DefaultValue = "null")] long? MemoryHint { 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; } } public enum DiagnosticMode diff --git a/src/Nethermind/Nethermind.Api/InitConfig.cs b/src/Nethermind/Nethermind.Api/InitConfig.cs index c123d39c432..6ad3c91ff0f 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 bool DisableMallocOpts { get; set; } = false; [Obsolete("Use DiagnosticMode with MemDb instead")] public bool UseMemDb diff --git a/src/Nethermind/Nethermind.Core.Test/Memory/MallocHelperTests.cs b/src/Nethermind/Nethermind.Core.Test/Memory/MallocHelperTests.cs new file mode 100644 index 00000000000..0e96f4b2a16 --- /dev/null +++ b/src/Nethermind/Nethermind.Core.Test/Memory/MallocHelperTests.cs @@ -0,0 +1,18 @@ +// SPDX-FileCopyrightText: 2023 Demerzel Solutions Limited +// SPDX-License-Identifier: LGPL-3.0-only + +using FluentAssertions; +using Nethermind.Core.Extensions; +using Nethermind.Core.Memory; +using NUnit.Framework; + +namespace Nethermind.Core.Test.Memory; + +public class MallocHelperTests +{ + [Test] + public void TestMallOpts() + { + MallocHelper.Instance.MallOpt(MallocHelper.Option.M_MMAP_THRESHOLD, (int)128.KiB()).Should().BeTrue(); + } +} diff --git a/src/Nethermind/Nethermind.Core/Memory/MallocHelper.cs b/src/Nethermind/Nethermind.Core/Memory/MallocHelper.cs new file mode 100644 index 00000000000..528ab1b2cbf --- /dev/null +++ b/src/Nethermind/Nethermind.Core/Memory/MallocHelper.cs @@ -0,0 +1,33 @@ +// SPDX-FileCopyrightText: 2023 Demerzel Solutions Limited +// SPDX-License-Identifier: LGPL-3.0-only + +using System; +using System.Runtime.InteropServices; + +namespace Nethermind.Core.Memory; + +/// +/// Wrapper around malloc apis +/// +public class MallocHelper +{ + [DllImport("libc")] + private static extern int mallopt(int opts, int value); + + private static MallocHelper? _instance; + public static MallocHelper Instance => _instance ??= new MallocHelper(); + + public bool MallOpt(Option option, int value) + { + // Windows can't find libc and osx does not have the method for some reason + // FreeBSD uses jemalloc by default anyway.... + if (!RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) return true; + + return mallopt((int)option, value) == 1; + } + + public enum Option : int + { + M_MMAP_THRESHOLD = -3 + } +} diff --git a/src/Nethermind/Nethermind.Init/MemoryHintMan.cs b/src/Nethermind/Nethermind.Init/MemoryHintMan.cs index 37adba0b4fc..aa22c204598 100644 --- a/src/Nethermind/Nethermind.Init/MemoryHintMan.cs +++ b/src/Nethermind/Nethermind.Init/MemoryHintMan.cs @@ -8,6 +8,7 @@ using Nethermind.Api; using Nethermind.Blockchain.Synchronization; using Nethermind.Core.Extensions; +using Nethermind.Core.Memory; using Nethermind.Db.Rocks.Config; using Nethermind.Init.Steps; using Nethermind.Logging; @@ -22,9 +23,11 @@ namespace Nethermind.Init public class MemoryHintMan { private ILogger _logger; + private MallocHelper _mallocHelper; - public MemoryHintMan(ILogManager logManager) + public MemoryHintMan(ILogManager logManager, MallocHelper? mallocHelper = null) { + _mallocHelper = mallocHelper ?? MallocHelper.Instance; _logger = logManager?.GetClassLogger() ?? throw new ArgumentNullException(nameof(logManager)); } @@ -42,6 +45,8 @@ public void SetMemoryAllowances( checked { + SetupMallocOpts(initConfig); + if (_logger.IsInfo) _logger.Info("Setting up memory allowances"); if (_logger.IsInfo) _logger.Info($" Memory hint: {TotalMemory / 1000 / 1000,5} MB"); _remainingMemory = initConfig.MemoryHint ?? 2.GB(); @@ -69,6 +74,25 @@ public void SetMemoryAllowances( } } + private void SetupMallocOpts(IInitConfig initConfig) + { + if (initConfig.DisableMallocOpts) return; + + if (_logger.IsDebug) _logger.Debug("Setting malloc parameters.."); + + // The MMAP threshold is the minimum size of allocation before glibc uses mmap to allocate the memory + // instead of sbrk. This means the whole allocation can be released on its own without incurring fragmentation + // but its not reusable and incur a system call. It turns out by default this value is dynamically adjusted + // from 128KB up to 32MB in size on 64bit machine, so most of the memory reduction is due to just disabling + // this auto adjustment. + // Setting this essentially reduces the maximum size of a `hole` in the heap, but it causes extra system call. + // On 16C/32T machine, this reduces memory usage by about 7GB. + // There aren't much difference between 16KB to 64KB, but the system cpu time increase slightly as threshold + // lowers. 4k significantly increase cpu system time. + bool success = _mallocHelper.MallOpt(MallocHelper.Option.M_MMAP_THRESHOLD, (int)64.KiB()); + if (!success && _logger.IsDebug) _logger.Debug("Unable to set M_MAP_THRESHOLD"); + } + private long _remainingMemory; public long TotalMemory = 1024 * 1024 * 1024; diff --git a/src/Nethermind/Nethermind.Runner.Test/MemoryHintManTests.cs b/src/Nethermind/Nethermind.Runner.Test/MemoryHintManTests.cs index d76f2c3e2e6..f49d07d2847 100755 --- a/src/Nethermind/Nethermind.Runner.Test/MemoryHintManTests.cs +++ b/src/Nethermind/Nethermind.Runner.Test/MemoryHintManTests.cs @@ -6,11 +6,13 @@ using Nethermind.Api; using Nethermind.Blockchain.Synchronization; using Nethermind.Core.Extensions; +using Nethermind.Core.Memory; using Nethermind.Db.Rocks.Config; using Nethermind.Init; using Nethermind.Logging; using Nethermind.Network.Config; using Nethermind.TxPool; +using NSubstitute; using NUnit.Framework; namespace Nethermind.Runner.Test @@ -27,6 +29,7 @@ public class MemoryHintManTests private ITxPoolConfig _txPoolConfig; private INetworkConfig _networkConfig; private MemoryHintMan _memoryHintMan; + private MallocHelper _mallocHelper; [SetUp] public void Setup() @@ -36,7 +39,8 @@ public void Setup() _initConfig = new InitConfig(); _txPoolConfig = new TxPoolConfig(); _networkConfig = new NetworkConfig(); - _memoryHintMan = new MemoryHintMan(LimboLogs.Instance); + _mallocHelper = Substitute.For(); + _memoryHintMan = new MemoryHintMan(LimboLogs.Instance, _mallocHelper); } private void SetMemoryAllowances(uint cpuCount) @@ -166,5 +170,22 @@ public void Big_value_at_memory_hint(long memoryHint) SetMemoryAllowances(1); Trie.MemoryAllowance.TrieNodeCacheCount.Should().BeGreaterThan(0); } + + [TestCase(true)] + [TestCase(false)] + public void Big_value_at_memory_hint(bool shouldSetMallocOpts) + { + _initConfig.DisableMallocOpts = !shouldSetMallocOpts; + SetMemoryAllowances(1); + + if (shouldSetMallocOpts) + { + _mallocHelper.Received().MallOpt(Arg.Any(), Arg.Any()); + } + else + { + _mallocHelper.DidNotReceive().MallOpt(Arg.Any(), Arg.Any()); + } + } } } From ba96e2c21299e212bad710418179a9e3003e0598 Mon Sep 17 00:00:00 2001 From: Ayman Bouchareb Date: Thu, 21 Sep 2023 02:47:59 -0700 Subject: [PATCH 28/50] update address (#6118) --- .../BeaconBlockRoot/BeaconBlockRootHandler.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Nethermind/Nethermind.Blockchain/BeaconBlockRoot/BeaconBlockRootHandler.cs b/src/Nethermind/Nethermind.Blockchain/BeaconBlockRoot/BeaconBlockRootHandler.cs index f5fe8c2de97..3bd1fcc7fb2 100644 --- a/src/Nethermind/Nethermind.Blockchain/BeaconBlockRoot/BeaconBlockRootHandler.cs +++ b/src/Nethermind/Nethermind.Blockchain/BeaconBlockRoot/BeaconBlockRootHandler.cs @@ -12,7 +12,7 @@ namespace Nethermind.Consensus.BeaconBlockRoot; public class BeaconBlockRootHandler : IBeaconBlockRootHandler { public static UInt256 HISTORICAL_ROOTS_LENGTH = 8191; - private static readonly Address DefaultPbbrContractAddress = new Address("0xbEaC02001Aedb23b4088c853e4C05c57491c8bCA"); + private static readonly Address DefaultPbbrContractAddress = new Address("0xbEAC020008aFF7331c0A389CB2AAb67597567d7a"); public void ApplyContractStateChanges(Block block, IReleaseSpec spec, IWorldState stateProvider) { From 4acacce7980fdf6cfd6d937b7da34b2061a5d0e4 Mon Sep 17 00:00:00 2001 From: Ahmad Bitar <33181301+smartprogrammer93@users.noreply.github.com> Date: Thu, 21 Sep 2023 13:09:03 +0300 Subject: [PATCH 29/50] [Fix][Holesky] timestamps and genesis updates (#6112) * holesky timestamps and genesis updates * fix genesis hash for archive * add fork info tests for holesky --- src/Nethermind/Chains/holesky.json | 12 +++++----- .../Nethermind.Network.Test/ForkInfoTests.cs | 23 ++++--------------- .../Nethermind.Runner/configs/holesky.cfg | 2 +- .../configs/holesky_archive.cfg | 2 +- .../ChainSpecBasedSpecProviderTests.cs | 5 ++-- .../Nethermind.Specs/HoleskySpecProvider.cs | 4 ++-- .../Nethermind.Specs/KnownHashes.cs | 1 + 7 files changed, 19 insertions(+), 30 deletions(-) diff --git a/src/Nethermind/Chains/holesky.json b/src/Nethermind/Chains/holesky.json index e32cd82ae7e..a06501a813c 100644 --- a/src/Nethermind/Chains/holesky.json +++ b/src/Nethermind/Chains/holesky.json @@ -35,10 +35,10 @@ "eip3198Transition": "0x0", "eip3529Transition": "0x0", "eip3541Transition": "0x0", - "eip3651TransitionTimestamp": "0x6505e360", - "eip3855TransitionTimestamp": "0x6505e360", - "eip3860TransitionTimestamp": "0x6505e360", - "eip4895TransitionTimestamp": "0x6505e360", + "eip3651TransitionTimestamp": "0x6516eac0", + "eip3855TransitionTimestamp": "0x6516eac0", + "eip3860TransitionTimestamp": "0x6516eac0", + "eip4895TransitionTimestamp": "0x6516eac0", "terminalTotalDifficulty": "0x0", "gasLimitBoundDivisor": "0x400", "maxCodeSize": "0x6000", @@ -57,10 +57,10 @@ }, "difficulty": "0x01", "author": "0x0000000000000000000000000000000000000000", - "extraData": "0x686f77206d7563682069732074686520666973683f", + "extraData": "", "gasLimit": "0x17D7840", "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000", - "timestamp": "0x65046234" + "timestamp": "0x65156994" }, "nodes": [ "enode://ac906289e4b7f12df423d654c5a962b6ebe5b3a74cc9e06292a85221f9a64a6f1cfdd6b714ed6dacef51578f92b34c60ee91e9ede9c7f8fadc4d347326d95e2b@146.190.13.128:30303", diff --git a/src/Nethermind/Nethermind.Network.Test/ForkInfoTests.cs b/src/Nethermind/Nethermind.Network.Test/ForkInfoTests.cs index 6a5ee7a3995..804f492e84b 100644 --- a/src/Nethermind/Nethermind.Network.Test/ForkInfoTests.cs +++ b/src/Nethermind/Nethermind.Network.Test/ForkInfoTests.cs @@ -112,25 +112,12 @@ public void Fork_id_and_hash_as_expected_on_goerli(long head, ulong headTimestam Test(head, headTimestamp, KnownHashes.GoerliGenesis, forkHashHex, next, description, GoerliSpecProvider.Instance, "goerli.json"); } - [TestCase(0, 0ul, "0x3b8e0691", 1ul, "Unsynced, last Frontier block")] - [TestCase(1, 0ul, "0x60949295", 2ul, "First and last Homestead block")] - [TestCase(2, 0ul, "0x8bde40dd", 3ul, "First and last Tangerine block")] - [TestCase(3, 0ul, "0xcb3a64bb", 1035301ul, "First Spurious block")] - [TestCase(1_035_300L, 0ul, "0xcb3a64bb", 1_035_301ul, "Last Spurious block")] - [TestCase(1_035_301L, 0ul, "0x8d748b57", 3_660_663ul, "First Byzantium block")] - [TestCase(3_660_662L, 0ul, "0x8d748b57", 3_660_663ul, "Last Byzantium block")] - [TestCase(3_660_663L, 0ul, "0xe49cab14", 4_321_234ul, "First Constantinople block")] - [TestCase(4_321_233L, 0ul, "0xe49cab14", 4_321_234ul, "Last Constantinople block")] - [TestCase(4_321_234L, 0ul, "0xafec6b27", 5_435_345ul, "First Petersburg block")] - [TestCase(5_435_344L, 0ul, "0xafec6b27", 5_435_345ul, "Last Petersburg block")] - [TestCase(5_435_345L, 0ul, "0xcbdb8838", 8_290_928ul, "First Istanbul block")] - [TestCase(8_290_928L, 0ul, "0x6910c8bd", 8_897_988ul, "First Berlin block")] - [TestCase(8_700_000L, 0ul, "0x6910c8bd", 8_897_988ul, "Future Berlin block")] - [TestCase(8_897_988L, 0ul, "0x8E29F2F3", 0ul, "First London block")] - [TestCase(9_000_000L, 0ul, "0x8E29F2F3", 0ul, "Future London block")] - public void Fork_id_and_hash_as_expected_on_rinkeby(long head, ulong headTimestamp, string forkHashHex, ulong next, string description) + [TestCase(0, 0ul, "0xc61a6098", 1_696_000_704ul, "Unsynced")] + [TestCase(1, 1_696_000_703ul, "0xc61a6098", 1_696_000_704ul, "Last genesis spec block")] + [TestCase(2, 1_696_000_704ul, "0xfd4f016b", 0ul, "First Shanghai block")] + public void Fork_id_and_hash_as_expected_on_holesky(long head, ulong headTimestamp, string forkHashHex, ulong next, string description) { - Test(head, headTimestamp, KnownHashes.RinkebyGenesis, forkHashHex, next, description, RinkebySpecProvider.Instance, "rinkeby.json"); + Test(head, headTimestamp, KnownHashes.HoleskyGenesis, forkHashHex, next, description, HoleskySpecProvider.Instance, "holesky.json"); } [TestCase(0, 0ul, "0xFE3366E7", 1735371ul, "Sepolia genesis")] diff --git a/src/Nethermind/Nethermind.Runner/configs/holesky.cfg b/src/Nethermind/Nethermind.Runner/configs/holesky.cfg index c6de49ac1bf..a66c834aeda 100644 --- a/src/Nethermind/Nethermind.Runner/configs/holesky.cfg +++ b/src/Nethermind/Nethermind.Runner/configs/holesky.cfg @@ -1,7 +1,7 @@ { "Init": { "ChainSpecPath": "chainspec/holesky.json", - "GenesisHash": "0xff9006519a8ce843ac9c28549d24211420b546e12ce2d170c77a8cca7964f23d", + "GenesisHash": "0xb5f7f912443c940f21fd611f12828d75b534364ed9e95ca4e307729a4661bde4", "BaseDbPath": "nethermind_db/holesky", "LogFileName": "holesky.logs.txt" }, diff --git a/src/Nethermind/Nethermind.Runner/configs/holesky_archive.cfg b/src/Nethermind/Nethermind.Runner/configs/holesky_archive.cfg index 5f3da6cd660..ebd9b36add2 100644 --- a/src/Nethermind/Nethermind.Runner/configs/holesky_archive.cfg +++ b/src/Nethermind/Nethermind.Runner/configs/holesky_archive.cfg @@ -1,7 +1,7 @@ { "Init": { "ChainSpecPath": "chainspec/holesky.json", - "GenesisHash": "0xff9006519a8ce843ac9c28549d24211420b546e12ce2d170c77a8cca7964f23d", + "GenesisHash": "0xb5f7f912443c940f21fd611f12828d75b534364ed9e95ca4e307729a4661bde4", "BaseDbPath": "nethermind_db/holesky_archive", "LogFileName": "holesky_archive.logs.txt" }, diff --git a/src/Nethermind/Nethermind.Specs.Test/ChainSpecStyle/ChainSpecBasedSpecProviderTests.cs b/src/Nethermind/Nethermind.Specs.Test/ChainSpecStyle/ChainSpecBasedSpecProviderTests.cs index 555fb8faa9b..b5180ea82c6 100644 --- a/src/Nethermind/Nethermind.Specs.Test/ChainSpecStyle/ChainSpecBasedSpecProviderTests.cs +++ b/src/Nethermind/Nethermind.Specs.Test/ChainSpecStyle/ChainSpecBasedSpecProviderTests.cs @@ -166,8 +166,9 @@ public void Holesky_loads_properly() Assert.That(provider.ChainId, Is.EqualTo(BlockchainIds.Holesky)); Assert.That(provider.NetworkId, Is.EqualTo(BlockchainIds.Holesky)); - GetTransitionTimestamps(chainSpec.Parameters).Should().AllSatisfy( - t => ValidateSlotByTimestamp(t, HoleskySpecProvider.GenesisTimestamp).Should().BeTrue()); + // because genesis time for holesky is set 5 minutes before the launch of the chain. this test fails. + //GetTransitionTimestamps(chainSpec.Parameters).Should().AllSatisfy( + // t => ValidateSlotByTimestamp(t, HoleskySpecProvider.GenesisTimestamp).Should().BeTrue()); } [Test] diff --git a/src/Nethermind/Nethermind.Specs/HoleskySpecProvider.cs b/src/Nethermind/Nethermind.Specs/HoleskySpecProvider.cs index 8d6f75754db..006460e0490 100644 --- a/src/Nethermind/Nethermind.Specs/HoleskySpecProvider.cs +++ b/src/Nethermind/Nethermind.Specs/HoleskySpecProvider.cs @@ -10,8 +10,8 @@ namespace Nethermind.Specs; public class HoleskySpecProvider : ISpecProvider { - public const ulong GenesisTimestamp = 0x65046360; - public const ulong ShanghaiTimestamp = 0x6505e360; + public const ulong GenesisTimestamp = 0x65156994; + public const ulong ShanghaiTimestamp = 0x6516eac0; // public const ulong CancunTimestamp = 0x77359400; private HoleskySpecProvider() { } diff --git a/src/Nethermind/Nethermind.Specs/KnownHashes.cs b/src/Nethermind/Nethermind.Specs/KnownHashes.cs index 5e1623d0c4f..437fe89fdcc 100644 --- a/src/Nethermind/Nethermind.Specs/KnownHashes.cs +++ b/src/Nethermind/Nethermind.Specs/KnownHashes.cs @@ -13,5 +13,6 @@ public static class KnownHashes public static readonly Keccak SepoliaGenesis = new("0x25a5cc106eea7138acab33231d7160d69cb777ee0c2c553fcddf5138993e6dd9"); public static readonly Keccak GnosisGenesis = new("0x4f1dd23188aab3a76b463e4af801b52b1248ef073c648cbdc4c9333d3da79756"); public static readonly Keccak ChiadoGenesis = new("0xada44fd8d2ecab8b08f256af07ad3e777f17fb434f8f8e678b312f576212ba9a"); + public static readonly Keccak HoleskyGenesis = new("0xb5f7f912443c940f21fd611f12828d75b534364ed9e95ca4e307729a4661bde4"); } } From c752603073e4c9e0793ec53997cddcf315f66544 Mon Sep 17 00:00:00 2001 From: Lautaro Emanuel <31224949+emlautarom1@users.noreply.github.com> Date: Thu, 21 Sep 2023 10:07:11 -0300 Subject: [PATCH 30/50] Remove warnings from `Nethermind.JsonRpc.Test` (#6114) * Remove warnings from `Nethermind.Core.Test` * Treat warnings as errors * Remove straightforward warnings * Use 'Substitute' for 'Filter' * Handle nullable fields * Treat warnings as errors * Fix typo * Remove null check test - Rely on the type system for these cases --- .../ConsensusHelperTests.JsonRpcDataSource.cs | 6 +-- ...usHelperTests.ReceiptsJsonRpcDataSource.cs | 4 +- .../Data/Eip2930Tests.cs | 2 +- .../JsonRpcProcessorTests.cs | 9 ---- .../Modules/Eth/EthRpcModuleTests.cs | 8 ++-- .../Modules/EvmModuleTests.cs | 2 +- .../Modules/Proof/ProofRpcModuleTests.cs | 47 ++++++++++--------- .../Modules/SubscribeModuleTests.cs | 18 +++---- .../Modules/Trace/ParityStyleTracerTests.cs | 4 +- .../Modules/TraceRpcModuleTests.cs | 21 +++++---- .../Nethermind.JsonRpc.Test.csproj | 1 + .../Nethermind.JsonRpc/JsonRpcProcessor.cs | 35 +++++++------- 12 files changed, 75 insertions(+), 82 deletions(-) diff --git a/src/Nethermind/Nethermind.JsonRpc.Test/ConsensusHelperTests.JsonRpcDataSource.cs b/src/Nethermind/Nethermind.JsonRpc.Test/ConsensusHelperTests.JsonRpcDataSource.cs index fbcf8809278..cc24a2f2260 100644 --- a/src/Nethermind/Nethermind.JsonRpc.Test/ConsensusHelperTests.JsonRpcDataSource.cs +++ b/src/Nethermind/Nethermind.JsonRpc.Test/ConsensusHelperTests.JsonRpcDataSource.cs @@ -48,19 +48,19 @@ protected JsonRpcRequestWithParams CreateRequest(string methodName, params objec public void Dispose() { - _httpClient?.Dispose(); + _httpClient.Dispose(); } protected class JsonRpcSuccessResponse : JsonRpcSuccessResponse { [JsonProperty(PropertyName = "result", NullValueHandling = NullValueHandling.Include, Order = 1)] - public new T Result { get { return (T)base.Result; } set { base.Result = value; } } + public new T Result { get { return (T)base.Result!; } set { base.Result = value; } } } public virtual async Task<(T2, string)> GetData() { string jsonData = await GetJsonData(); - return (_serializer.Deserialize>(jsonData).Result, jsonData); + return (_serializer.Deserialize>(jsonData).Result!, jsonData); } public abstract Task GetJsonData(); diff --git a/src/Nethermind/Nethermind.JsonRpc.Test/ConsensusHelperTests.ReceiptsJsonRpcDataSource.cs b/src/Nethermind/Nethermind.JsonRpc.Test/ConsensusHelperTests.ReceiptsJsonRpcDataSource.cs index 5502d5c5d19..78886a095e5 100644 --- a/src/Nethermind/Nethermind.JsonRpc.Test/ConsensusHelperTests.ReceiptsJsonRpcDataSource.cs +++ b/src/Nethermind/Nethermind.JsonRpc.Test/ConsensusHelperTests.ReceiptsJsonRpcDataSource.cs @@ -31,7 +31,7 @@ private async Task> GetJsonDatas() JsonRpcRequest request = CreateRequest("eth_getBlockByHash", Parameter.ToString(), false); string blockJson = await SendRequest(request); BlockForRpcTxHashes block = _serializer.Deserialize>(blockJson).Result; - List transactionsJsons = new(block.Transactions.Length); + List transactionsJsons = new(block.Transactions!.Length); foreach (string tx in block.Transactions) { transactionsJsons.Add(await SendRequest(CreateRequest("eth_getTransactionReceipt", tx))); @@ -48,7 +48,7 @@ private async Task> GetJsonDatas() private class BlockForRpcTxHashes : BlockForRpc { - public new string[] Transactions { get; set; } + public new string[]? Transactions { get; set; } } } } diff --git a/src/Nethermind/Nethermind.JsonRpc.Test/Data/Eip2930Tests.cs b/src/Nethermind/Nethermind.JsonRpc.Test/Data/Eip2930Tests.cs index 9dc0342c55a..ad2e899b064 100644 --- a/src/Nethermind/Nethermind.JsonRpc.Test/Data/Eip2930Tests.cs +++ b/src/Nethermind/Nethermind.JsonRpc.Test/Data/Eip2930Tests.cs @@ -188,7 +188,7 @@ public void can_serialize_accessList_with_null_storageKeys(TxType txType, string Dictionary> data = new() { { - TestItem.AddressA, null + TestItem.AddressA, null! }, }; Transaction transaction = new() diff --git a/src/Nethermind/Nethermind.JsonRpc.Test/JsonRpcProcessorTests.cs b/src/Nethermind/Nethermind.JsonRpc.Test/JsonRpcProcessorTests.cs index d90f1fdaec7..4fe9d78469e 100644 --- a/src/Nethermind/Nethermind.JsonRpc.Test/JsonRpcProcessorTests.cs +++ b/src/Nethermind/Nethermind.JsonRpc.Test/JsonRpcProcessorTests.cs @@ -380,14 +380,5 @@ public async Task Can_handle_null_request() result[0].BatchedResponses.Should().BeNull(); result[0].Response.Should().BeSameAs(_errorResponse); } - - [Test] - public void Cannot_accept_null_file_system() - { - Assert.Throws(() => new JsonRpcProcessor(Substitute.For(), - Substitute.For(), - Substitute.For(), - null, LimboLogs.Instance)); - } } } diff --git a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/EthRpcModuleTests.cs b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/EthRpcModuleTests.cs index 9616e2073c7..d3366240dea 100644 --- a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/EthRpcModuleTests.cs +++ b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/EthRpcModuleTests.cs @@ -201,9 +201,9 @@ public async Task Eth_get_tx_count(string blockParameter, string expectedResult) Transaction txWithFutureNonce = Build.A.Transaction.To(TestItem.AddressB) .SignedAndResolved(TestItem.PrivateKeyA).WithValue(0.Ether()).WithNonce(5).TestObject; ValueTask<(Keccak? Hash, AcceptTxResult? AddTxResult)> resultNextNonce = - ctx.Test.TxSender.SendTransaction(txWithNextNonce, TxHandlingOptions.None); + ctx.Test.TxSender.SendTransaction(txWithNextNonce, TxHandlingOptions.None)!; ValueTask<(Keccak? Hash, AcceptTxResult? AddTxResult)> resultFutureNonce = - ctx.Test.TxSender.SendTransaction(txWithFutureNonce, TxHandlingOptions.None); + ctx.Test.TxSender.SendTransaction(txWithFutureNonce, TxHandlingOptions.None)!; Assert.That(AcceptTxResult.Accepted, Is.EqualTo(resultNextNonce.Result.AddTxResult)); Assert.That(AcceptTxResult.Accepted, Is.EqualTo(resultFutureNonce.Result.AddTxResult)); @@ -228,7 +228,7 @@ public async Task Eth_get_tx_count_pending_block() Transaction txWithNextNonce = Build.A.Transaction.To(TestItem.AddressA) .SignedAndResolved(TestItem.PrivateKeyB).WithValue(0.Ether()).WithNonce(0).TestObject; ValueTask<(Keccak? Hash, AcceptTxResult? AddTxResult)> resultNextNonce = - ctx.Test.TxSender.SendTransaction(txWithNextNonce, TxHandlingOptions.None); + ctx.Test.TxSender.SendTransaction(txWithNextNonce, TxHandlingOptions.None)!; Assert.That(AcceptTxResult.Accepted, Is.EqualTo(resultNextNonce.Result.AddTxResult)); string serializedLatestAfter = await ctx.Test.TestEthRpc("eth_getTransactionCount", TestItem.AddressB.Bytes.ToHexString(true)); Assert.That(serializedLatestAfter, Is.EqualTo("{\"jsonrpc\":\"2.0\",\"result\":\"0x0\",\"id\":67}")); @@ -667,7 +667,7 @@ public async Task Eth_get_block_by_number_should_not_recover_tx_senders_for_requ { IBlockchainBridge? blockchainBridge = Substitute.For(); TestRpcBlockchain ctx = await TestRpcBlockchain.ForTest(SealEngineType.NethDev).WithBlockchainBridge(blockchainBridge).Build(MainnetSpecProvider.Instance); - ctx.TestEthRpc("eth_getBlockByNumber", blockParameter, "false"); + await ctx.TestEthRpc("eth_getBlockByNumber", blockParameter, "false"); blockchainBridge.Received(0).RecoverTxSenders(Arg.Any()); } diff --git a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/EvmModuleTests.cs b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/EvmModuleTests.cs index 1d5c72cc967..141627bd070 100644 --- a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/EvmModuleTests.cs +++ b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/EvmModuleTests.cs @@ -20,7 +20,7 @@ public async Task Evm_mine() EvmRpcModule rpcModule = new(trigger); string response = await RpcTest.TestSerializedRequest(rpcModule, "evm_mine"); Assert.That(response, Is.EqualTo("{\"jsonrpc\":\"2.0\",\"result\":true,\"id\":67}")); - trigger.Received().BuildBlock(); + await trigger.Received().BuildBlock(); } } } diff --git a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Proof/ProofRpcModuleTests.cs b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Proof/ProofRpcModuleTests.cs index 80d74606932..7960a89c925 100644 --- a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Proof/ProofRpcModuleTests.cs +++ b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Proof/ProofRpcModuleTests.cs @@ -75,7 +75,7 @@ public async Task Setup() [TestCase(false)] public async Task Can_get_transaction(bool withHeader) { - Keccak txHash = _blockTree.FindBlock(1).Transactions[0].Hash; + Keccak txHash = _blockTree.FindBlock(1)!.Transactions[0].Hash!; TransactionWithProof txWithProof = _proofRpcModule.proof_getTransactionByHash(txHash, withHeader).Data; Assert.NotNull(txWithProof.Transaction); Assert.That(txWithProof.TxProof.Length, Is.EqualTo(2)); @@ -140,7 +140,7 @@ public async Task On_incorrect_params_returns_correct_error_code() [TestCase(false, "{\"jsonrpc\":\"2.0\",\"result\":{\"receipt\":{\"transactionHash\":\"0x6db23e4d6e1f23a0f67ae8637cd675363ec59aea22acd86300ac1f1cb42c9011\",\"transactionIndex\":\"0x0\",\"blockHash\":\"0x77f368c23226eee1583f671719f117df588fc5bf19c2a73e190e404a8be570f1\",\"blockNumber\":\"0x1\",\"cumulativeGasUsed\":\"0x0\",\"gasUsed\":\"0x0\",\"effectiveGasPrice\":\"0x1\",\"to\":null,\"contractAddress\":null,\"logs\":[],\"logsBloom\":\"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\",\"status\":\"0x0\",\"type\":\"0x0\"},\"txProof\":[\"0xf851a0e244ea69b68d9f3fd5eff812a4a7e1e105a8c1143ff82206458ad45fe1801c9b80808080808080a08a1641bd871a8d574e81653362ae89e549a9ab0660bd5b180328d00f13e9c6bb8080808080808080\",\"0xf86530b862f860800182520894000000000000000000000000000000000000000001818025a0e7b18371f1b94890bd11e7f67ba7e7a3a6b263d68b2d18e258f6e063d6abd90ea00a015b31944dee0bde211cec1636a3f05bfea0678e240ae8dfe309b2aac22d93\"],\"receiptProof\":[\"0xf851a053e4a8d7d8438fa45d6b75bbd6fb699b08049c1caf1c21ada42a746ddfb61d0b80808080808080a04de834bd23b53a3d82923ae5f359239b326c66758f2ae636ab934844dba2b9658080808080808080\",\"0xf9010f30b9010bf9010880825208b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c0\"]},\"id\":67}")] public async Task Can_get_receipt(bool withHeader, string expectedResult) { - Keccak txHash = _blockTree.FindBlock(1).Transactions[0].Hash; + Keccak txHash = _blockTree.FindBlock(1)!.Transactions[0].Hash!; ReceiptWithProof receiptWithProof = _proofRpcModule.proof_getTransactionReceipt(txHash, withHeader).Data; Assert.NotNull(receiptWithProof.Receipt); Assert.That(receiptWithProof.ReceiptProof.Length, Is.EqualTo(2)); @@ -171,11 +171,11 @@ public async Task Get_receipt_when_block_has_few_receipts(bool withHeader, strin Index = 0, Recipient = TestItem.AddressA, Sender = TestItem.AddressB, - BlockHash = _blockTree.FindBlock(1).Hash, + BlockHash = _blockTree.FindBlock(1)!.Hash, BlockNumber = 1, ContractAddress = TestItem.AddressC, GasUsed = 1000, - TxHash = _blockTree.FindBlock(1).Transactions[0].Hash, + TxHash = _blockTree.FindBlock(1)!.Transactions[0].Hash, StatusCode = 0, GasUsedTotal = 2000, Logs = logEntries @@ -187,22 +187,22 @@ public async Task Get_receipt_when_block_has_few_receipts(bool withHeader, strin Index = 1, Recipient = TestItem.AddressC, Sender = TestItem.AddressD, - BlockHash = _blockTree.FindBlock(1).Hash, + BlockHash = _blockTree.FindBlock(1)!.Hash, BlockNumber = 1, ContractAddress = TestItem.AddressC, GasUsed = 1000, - TxHash = _blockTree.FindBlock(1).Transactions[1].Hash, + TxHash = _blockTree.FindBlock(1)!.Transactions[1].Hash, StatusCode = 0, GasUsedTotal = 2000, Logs = logEntries }; - Block block = _blockTree.FindBlock(1); - Keccak txHash = _blockTree.FindBlock(1).Transactions[1].Hash; + Block block = _blockTree.FindBlock(1)!; + Keccak txHash = _blockTree.FindBlock(1)!.Transactions[1].Hash!; TxReceipt[] receipts = { receipt1, receipt2 }; _receiptFinder.Get(Arg.Any()).Returns(receipts); _receiptFinder.Get(Arg.Any()).Returns(receipts); - _receiptFinder.FindBlockHash(Arg.Any()).Returns(_blockTree.FindBlock(1).Hash); + _receiptFinder.FindBlockHash(Arg.Any()).Returns(_blockTree.FindBlock(1)!.Hash); ProofModuleFactory moduleFactory = new ProofModuleFactory( _dbProvider, @@ -235,7 +235,7 @@ public async Task Can_call() WorldState stateProvider = CreateInitialState(null); Keccak root = stateProvider.StateRoot; - Block block = Build.A.Block.WithParent(_blockTree.Head).WithStateRoot(root).TestObject; + Block block = Build.A.Block.WithParent(_blockTree.Head!).WithStateRoot(root).TestObject; BlockTreeBuilder.AddBlock(_blockTree, block); // would need to setup state root somehow... @@ -260,7 +260,7 @@ public async Task Can_call_by_hash() WorldState stateProvider = CreateInitialState(null); Keccak root = stateProvider.StateRoot; - Block block = Build.A.Block.WithParent(_blockTree.Head).WithStateRoot(root).TestObject; + Block block = Build.A.Block.WithParent(_blockTree.Head!).WithStateRoot(root).TestObject; BlockTreeBuilder.AddBlock(_blockTree, block); // would need to setup state root somehow... @@ -271,7 +271,7 @@ public async Task Can_call_by_hash() To = TestItem.AddressB, GasPrice = _useNonZeroGasPrice ? 10.GWei() : 0 }; - _proofRpcModule.proof_call(tx, new BlockParameter(block.Hash)); + _proofRpcModule.proof_call(tx, new BlockParameter(block.Hash!)); EthereumJsonSerializer serializer = new(); string response = await RpcTest.TestSerializedRequest(_proofRpcModule, "proof_call", $"{serializer.Serialize(tx)}", $"{block.Hash}"); @@ -281,7 +281,7 @@ public async Task Can_call_by_hash() [TestCase] public async Task Can_call_by_hash_canonical() { - Block lastHead = _blockTree.Head; + Block lastHead = _blockTree.Head!; Block block = Build.A.Block.WithParent(lastHead).TestObject; Block newBlockOnMain = Build.A.Block.WithParent(lastHead).WithDifficulty(block.Difficulty + 1).TestObject; BlockTreeBuilder.AddBlock(_blockTree, block); @@ -683,7 +683,7 @@ public async Task Can_call_with_many_storage_writes() } [TestCase] - public void Can_call_with_mix_of_everything() + public async Task Can_call_with_mix_of_everything() { byte[] code = Prepare.EvmCode .PushData(TestItem.AddressC) @@ -704,11 +704,11 @@ public void Can_call_with_mix_of_everything() .Op(Instruction.SSTORE) .Done; - TestCallWithCode(code); + await TestCallWithCode(code); } [TestCase] - public void Can_call_with_mix_of_everything_and_storage() + public async Task Can_call_with_mix_of_everything_and_storage() { byte[] code = Prepare.EvmCode .PushData(TestItem.AddressC) @@ -729,11 +729,11 @@ public void Can_call_with_mix_of_everything_and_storage() .Op(Instruction.SSTORE) .Done; - TestCallWithStorageAndCode(code, _useNonZeroGasPrice ? 10.GWei() : 0); + await TestCallWithStorageAndCode(code, _useNonZeroGasPrice ? 10.GWei() : 0); } [TestCase] - public void Can_call_with_mix_of_everything_and_storage_from_another_account_wrong_nonce() + public async Task Can_call_with_mix_of_everything_and_storage_from_another_account_wrong_nonce() { byte[] code = Prepare.EvmCode .PushData(TestItem.AddressC) @@ -754,7 +754,7 @@ public void Can_call_with_mix_of_everything_and_storage_from_another_account_wro .Op(Instruction.SSTORE) .Done; - TestCallWithStorageAndCode(code, 0, TestItem.AddressD); + await TestCallWithStorageAndCode(code, 0, TestItem.AddressD); } private async Task TestCallWithCode(byte[] code, Address? from = null) @@ -848,17 +848,18 @@ private async Task TestCallWithStorageAndCode(byte[] code, UInt256 gasPrice, Add // the exception will be thrown if the account did not exist before the call try { - new AccountDecoder().Decode(new RlpStream(ProofVerifier.VerifyOneProof(accountProof.Proof, block.StateRoot))); + byte[] verifyOneProof = ProofVerifier.VerifyOneProof(accountProof.Proof!, block.StateRoot!)!; + new AccountDecoder().Decode(new RlpStream(verifyOneProof)); } catch (Exception) { // ignored } - foreach (StorageProof storageProof in accountProof.StorageProofs) + foreach (StorageProof storageProof in accountProof.StorageProofs!) { // we read the values here just to allow easier debugging so you can confirm that the value is same as the one in the proof and in the trie - byte[] value = ProofVerifier.VerifyOneProof(storageProof.Proof, accountProof.StorageRoot); + ProofVerifier.VerifyOneProof(storageProof.Proof!, accountProof.StorageRoot); } } @@ -867,7 +868,7 @@ private async Task TestCallWithStorageAndCode(byte[] code, UInt256 gasPrice, Add Assert.True(response.Contains("\"result\"")); } - private WorldState CreateInitialState(byte[] code) + private WorldState CreateInitialState(byte[]? code) { WorldState stateProvider = new(new TrieStore(_dbProvider.StateDb, LimboLogs.Instance), _dbProvider.CodeDb, LimboLogs.Instance); AddAccount(stateProvider, TestItem.AddressA, 1.Ether()); diff --git a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/SubscribeModuleTests.cs b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/SubscribeModuleTests.cs index 2e75ca387cf..3ea59e9e676 100644 --- a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/SubscribeModuleTests.cs +++ b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/SubscribeModuleTests.cs @@ -283,7 +283,7 @@ public void NewHeadSubscription_on_BlockAddedToMain_event() [Test] public void NewHeadSubscription_on_BlockAddedToMain_event_with_null_block() { - BlockReplacementEventArgs blockReplacementEventArgs = new(null); + BlockReplacementEventArgs blockReplacementEventArgs = new(null!); JsonRpcResult jsonRpcResult = GetBlockAddedToMainResult(blockReplacementEventArgs, out _, shouldReceiveResult: false); @@ -437,7 +437,7 @@ public async Task LogsSubscription_with_invalid_arguments_creating_result() public void LogsSubscription_with_null_arguments_on_NewHeadBlock_event() { int blockNumber = 55555; - Filter filter = null; + Filter filter = Substitute.For(); LogEntry logEntry = Build.A.LogEntry.WithAddress(TestItem.AddressA).WithTopics(TestItem.KeccakA).WithData(TestItem.RandomDataA).TestObject; TxReceipt[] txReceipts = { Build.A.Receipt.WithBlockNumber(blockNumber).WithLogs(logEntry).TestObject }; @@ -458,7 +458,7 @@ public void LogsSubscription_with_null_arguments_on_NewHeadBlock_event() public void LogsSubscription_with_not_matching_block_on_NewHeadBlock_event() { int blockNumber = 22222; - Filter filter = null; + Filter filter = Substitute.For(); LogEntry logEntry = Build.A.LogEntry.WithAddress(TestItem.AddressA).WithTopics(TestItem.KeccakA).WithData(TestItem.RandomDataA).TestObject; TxReceipt[] txReceipts = { Build.A.Receipt.WithBlockNumber(blockNumber).WithLogs(logEntry).TestObject }; @@ -476,7 +476,7 @@ public void LogsSubscription_with_not_matching_block_on_NewHeadBlock_event() public void LogsSubscription_with_null_arguments_on_NewHeadBlock_event_with_one_TxReceipt_with_few_logs() { int blockNumber = 77777; - Filter filter = null; + Filter filter = Substitute.For(); LogEntry logEntryA = Build.A.LogEntry.WithAddress(TestItem.AddressA).WithTopics(TestItem.KeccakA).WithData(TestItem.RandomDataA).TestObject; LogEntry logEntryB = Build.A.LogEntry.WithAddress(TestItem.AddressB).WithTopics(TestItem.KeccakB).TestObject; @@ -508,7 +508,7 @@ public void LogsSubscription_with_null_arguments_on_NewHeadBlock_event_with_one_ public void LogsSubscription_with_null_arguments_on_NewHeadBlock_event_with_few_TxReceipts_with_few_logs() { int blockNumber = 55555; - Filter filter = null; + Filter filter = Substitute.For(); LogEntry logEntryA = Build.A.LogEntry.WithAddress(TestItem.AddressA).WithTopics(TestItem.KeccakA).WithData(TestItem.RandomDataA).TestObject; LogEntry logEntryB = Build.A.LogEntry.WithAddress(TestItem.AddressB).WithTopics(TestItem.KeccakB).TestObject; @@ -698,7 +698,7 @@ public void LogsSubscription_on_NewHeadBlock_event_with_few_TxReceipts_with_few_ public void LogsSubscription_should_not_send_logs_of_new_txs_on_ReceiptsInserted_event_but_on_NewHeadBlock_event() { int blockNumber = 55555; - Filter filter = null; + Filter filter = Substitute.For(); LogsSubscription logsSubscription = new(_jsonRpcDuplexClient, _receiptCanonicalityMonitor, _filterStore, _blockTree, _logManager, filter); @@ -777,7 +777,7 @@ public void NewPendingTransactionsSubscription_on_NewPending_event() [Test] public void NewPendingTransactionsSubscription_on_NewPending_event_with_null_transaction() { - TxEventArgs txEventArgs = new(null); + TxEventArgs txEventArgs = new(null!); JsonRpcResult jsonRpcResult = GetNewPendingTransactionsResult(txEventArgs, out _); @@ -862,7 +862,7 @@ public void DroppedPendingTransactionsSubscription_on_EvictedPending_event() [Test] public void DroppedPendingTransactionsSubscription_on_EvictedPending_event_with_null_transaction() { - TxEventArgs txEventArgs = new(null); + TxEventArgs txEventArgs = new(null!); JsonRpcResult jsonRpcResult = GetDroppedPendingTransactionsResult(txEventArgs, out _); @@ -1045,7 +1045,7 @@ public async Task Subscriptions_remove_after_closing_websockets_client() public void LogsSubscription_can_send_logs_with_removed_txs_when_inserted() { int blockNumber = 55555; - Filter filter = null; + Filter filter = Substitute.For(); LogsSubscription logsSubscription = new(_jsonRpcDuplexClient, _receiptCanonicalityMonitor, _filterStore, _blockTree, _logManager, filter); diff --git a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Trace/ParityStyleTracerTests.cs b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Trace/ParityStyleTracerTests.cs index 3832256c615..75add1e5da1 100644 --- a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Trace/ParityStyleTracerTests.cs +++ b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Trace/ParityStyleTracerTests.cs @@ -107,8 +107,8 @@ public void Can_trace_raw_parity_style_berlin_tx() public void Should_return_correct_block_reward(bool isPostMerge) { Block block = Build.A.Block.WithParent(Build.A.Block.Genesis.TestObject).TestObject; - _blockTree.SuggestBlock(block).Should().Be(AddBlockResult.Added); - _poSSwitcher.IsPostMerge(Arg.Any()).Returns(isPostMerge); + _blockTree!.SuggestBlock(block).Should().Be(AddBlockResult.Added); + _poSSwitcher!.IsPostMerge(Arg.Any()).Returns(isPostMerge); TraceRpcModule traceRpcModule = new(NullReceiptStorage.Instance, _tracer, _blockTree, _jsonRpcConfig, MainnetSpecProvider.Instance, LimboLogs.Instance); ParityTxTraceFromStore[] result = traceRpcModule.trace_block(new BlockParameter(block.Number)).Data.ToArray(); diff --git a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/TraceRpcModuleTests.cs b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/TraceRpcModuleTests.cs index 7846f62062b..9540b744758 100644 --- a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/TraceRpcModuleTests.cs +++ b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/TraceRpcModuleTests.cs @@ -24,6 +24,7 @@ using Nethermind.Consensus.Validators; using Nethermind.Db; using Nethermind.Evm; +using Nethermind.Evm.Tracing.ParityStyle; using Nethermind.Serialization.Json; using Nethermind.Specs.Forks; using Nethermind.Specs.Test; @@ -834,18 +835,18 @@ public async Task Trace_replayBlockTransactions_stateDiff() ResultWrapper> traces = context.TraceRpcModule.trace_replayBlockTransactions(new BlockParameter(blockchain.BlockFinder.FindLatestBlock()!.Number), traceTypes); traces.Data.Should().HaveCount(1); - var state = traces.Data.ElementAt(0).StateChanges; + Dictionary state = traces.Data.ElementAt(0).StateChanges!; state.Count.Should().Be(3); - state[TestItem.AddressA].Nonce.Before.Should().Be(accountA.Nonce); - state[TestItem.AddressD].Balance.Before.Should().Be(accountD.Balance); - state[TestItem.AddressA].Balance.Before.Should().Be(accountA.Balance); - state[TestItem.AddressF].Balance.Before.Should().Be(null); - - state[TestItem.AddressA].Nonce.After.Should().Be(accountA.Nonce + 1); - state[TestItem.AddressD].Balance.After.Should().Be(accountD.Balance + 21000 * tx.GasPrice); - state[TestItem.AddressA].Balance.After.Should().Be(accountA.Balance - 21000 * tx.GasPrice - tx.Value); - state[TestItem.AddressF].Balance.After.Should().Be(accountF.Balance + tx.Value); + state[TestItem.AddressA].Nonce!.Before.Should().Be(accountA.Nonce); + state[TestItem.AddressD].Balance!.Before.Should().Be(accountD.Balance); + state[TestItem.AddressA].Balance!.Before.Should().Be(accountA.Balance); + state[TestItem.AddressF].Balance!.Before.Should().Be(null); + + state[TestItem.AddressA].Nonce!.After.Should().Be(accountA.Nonce + 1); + state[TestItem.AddressD].Balance!.After.Should().Be(accountD.Balance + 21000 * tx.GasPrice); + state[TestItem.AddressA].Balance!.After.Should().Be(accountA.Balance - 21000 * tx.GasPrice - tx.Value); + state[TestItem.AddressF].Balance!.After.Should().Be(accountF.Balance + tx.Value); } } } diff --git a/src/Nethermind/Nethermind.JsonRpc.Test/Nethermind.JsonRpc.Test.csproj b/src/Nethermind/Nethermind.JsonRpc.Test/Nethermind.JsonRpc.Test.csproj index a58fc99534a..96d7c4fb467 100644 --- a/src/Nethermind/Nethermind.JsonRpc.Test/Nethermind.JsonRpc.Test.csproj +++ b/src/Nethermind/Nethermind.JsonRpc.Test/Nethermind.JsonRpc.Test.csproj @@ -4,6 +4,7 @@ false latest enable + true diff --git a/src/Nethermind/Nethermind.JsonRpc/JsonRpcProcessor.cs b/src/Nethermind/Nethermind.JsonRpc/JsonRpcProcessor.cs index 817b20a5018..40dc11b572b 100644 --- a/src/Nethermind/Nethermind.JsonRpc/JsonRpcProcessor.cs +++ b/src/Nethermind/Nethermind.JsonRpc/JsonRpcProcessor.cs @@ -17,6 +17,7 @@ using Newtonsoft.Json.Linq; using Newtonsoft.Json.Serialization; +#nullable enable namespace Nethermind.JsonRpc { public class JsonRpcProcessor : IJsonRpcProcessor @@ -27,16 +28,14 @@ public class JsonRpcProcessor : IJsonRpcProcessor private readonly JsonSerializer _obsoleteBasicJsonSerializer = new(); private readonly IJsonRpcService _jsonRpcService; private readonly IJsonSerializer _jsonSerializer; - private readonly Recorder _recorder; + private readonly Recorder? _recorder; - public JsonRpcProcessor(IJsonRpcService jsonRpcService, IJsonSerializer jsonSerializer, IJsonRpcConfig jsonRpcConfig, IFileSystem fileSystem, ILogManager? logManager) + public JsonRpcProcessor(IJsonRpcService jsonRpcService, IJsonSerializer jsonSerializer, IJsonRpcConfig jsonRpcConfig, IFileSystem fileSystem, ILogManager logManager) { - _logger = logManager?.GetClassLogger() ?? throw new ArgumentNullException(nameof(logManager)); - if (fileSystem is null) throw new ArgumentNullException(nameof(fileSystem)); - - _jsonRpcService = jsonRpcService ?? throw new ArgumentNullException(nameof(jsonRpcService)); - _jsonRpcConfig = jsonRpcConfig ?? throw new ArgumentNullException(nameof(jsonRpcConfig)); - _jsonSerializer = jsonSerializer ?? throw new ArgumentNullException(nameof(jsonSerializer)); + _logger = logManager.GetClassLogger(); + _jsonRpcService = jsonRpcService; + _jsonRpcConfig = jsonRpcConfig; + _jsonSerializer = jsonSerializer; if (_jsonRpcConfig.RpcRecorderState != RpcRecorderState.None) { @@ -67,7 +66,7 @@ private JsonSerializer BuildTraceJsonSerializer() return JsonSerializer.Create(jsonSettings); } - private IEnumerable<(JsonRpcRequest Model, List Collection)> DeserializeObjectOrArray(TextReader json) + private IEnumerable<(JsonRpcRequest? Model, List? Collection)> DeserializeObjectOrArray(TextReader json) { IEnumerable parsedJson = JTokenUtils.ParseMulticontent(json); @@ -112,7 +111,7 @@ private void UpdateParams(JToken token) { if (arrayToken[i].Type == JTokenType.Array || arrayToken[i].Type == JTokenType.Object) { - arrayToken[i].Replace(JToken.Parse(_jsonSerializer.Serialize(arrayToken[i].Value().ToString()))); + arrayToken[i].Replace(JToken.Parse(_jsonSerializer.Serialize(arrayToken[i].Value()!.ToString()))); } } } @@ -121,9 +120,9 @@ public async IAsyncEnumerable ProcessAsync(TextReader request, Js { request = await RecordRequest(request); Stopwatch stopwatch = Stopwatch.StartNew(); - IEnumerable<(JsonRpcRequest Model, List Collection)> rpcRequests = DeserializeObjectOrArray(request); + IEnumerable<(JsonRpcRequest? Model, List? Collection)> rpcRequests = DeserializeObjectOrArray(request); - using IEnumerator<(JsonRpcRequest Model, List Collection)> enumerator = rpcRequests.GetEnumerator(); + using IEnumerator<(JsonRpcRequest? Model, List? Collection)> enumerator = rpcRequests.GetEnumerator(); bool moveNext = true; @@ -158,7 +157,7 @@ public async IAsyncEnumerable ProcessAsync(TextReader request, Js } else if (moveNext) { - (JsonRpcRequest Model, List Collection) rpcRequest = enumerator.Current; + (JsonRpcRequest? Model, List? Collection) rpcRequest = enumerator.Current; if (rpcRequest.Model is not null) { @@ -176,7 +175,7 @@ public async IAsyncEnumerable ProcessAsync(TextReader request, Js if (!context.IsAuthenticated && rpcRequest.Collection.Count > _jsonRpcConfig.MaxBatchSize) { if (_logger.IsWarn) _logger.Warn($"The batch size limit was exceeded. The requested batch size {rpcRequest.Collection.Count}, and the current config setting is JsonRpc.{nameof(_jsonRpcConfig.MaxBatchSize)} = {_jsonRpcConfig.MaxBatchSize}."); - JsonRpcErrorResponse? response = _jsonRpcService.GetErrorResponse(ErrorCodes.LimitExceeded, "Batch size limit exceeded"); + JsonRpcErrorResponse response = _jsonRpcService.GetErrorResponse(ErrorCodes.LimitExceeded, "Batch size limit exceeded"); yield return JsonRpcResult.Single(RecordResponse(response, RpcReport.Error)); continue; @@ -235,11 +234,11 @@ public async IAsyncEnumerable ProcessAsync(TextReader request, Js Stopwatch stopwatch = Stopwatch.StartNew(); JsonRpcResponse response = await _jsonRpcService.SendRequestAsync(request, context); - JsonRpcErrorResponse localErrorResponse = response as JsonRpcErrorResponse; + JsonRpcErrorResponse? localErrorResponse = response as JsonRpcErrorResponse; bool isSuccess = localErrorResponse is null; if (!isSuccess) { - if (localErrorResponse.Error?.SuppressWarning == false) + if (localErrorResponse?.Error?.SuppressWarning == false) { if (_logger.IsWarn) _logger.Warn($"Error when handling {request} | {_jsonSerializer.Serialize(localErrorResponse)}"); } @@ -268,7 +267,7 @@ private JsonRpcResult.Entry RecordResponse(JsonRpcResult.Entry result) { if ((_jsonRpcConfig.RpcRecorderState & RpcRecorderState.Response) != 0) { - _recorder.RecordResponse(_jsonSerializer.Serialize(result)); + _recorder!.RecordResponse(_jsonSerializer.Serialize(result)); } return result; @@ -279,7 +278,7 @@ private async ValueTask RecordRequest(TextReader request) if ((_jsonRpcConfig.RpcRecorderState & RpcRecorderState.Request) != 0) { string requestString = await request.ReadToEndAsync(); - _recorder.RecordRequest(requestString); + _recorder!.RecordRequest(requestString); return new StringReader(requestString); } From c2603b196b90d9f7fcdebcd17c01c529b6c78a5a Mon Sep 17 00:00:00 2001 From: Lautaro Emanuel <31224949+emlautarom1@users.noreply.github.com> Date: Fri, 22 Sep 2023 10:41:37 -0300 Subject: [PATCH 31/50] Remove warnings from `Nethermind.Blockchain.Test` (#6121) * Remove warnings from `Nethermind.Core.Test` * Treat warnings as errors * Remove straightforward warnings * Use 'Substitute' for 'Filter' * Handle nullable fields * Treat warnings as errors * Fix typo * Remove null check test - Rely on the type system for these cases * Remove unused params * Remove warnings * Use 'AnyAddress' * Remove nullable warnings * Remove warnings * Cleanup 'BlockchainProcessorTests' - Make fields readonly - Remove null warnings - Remove unused methods - Discard unused vars * Fix nullables; use explicit types * Remove nullable warnings * Relax null constraints in 'Signer' * Remove 'NullSigner' null warnings * Remove support for null in 'SinglePendingTxSelector' * Relax null constraints in 'NethDevSealEngine' * Replace 'null' with default constructor * Use 'WithAnyAddress' from 'FilterBuilder' * Use explicit types * Cleanup 'BlockTreeTests' * Enable tests that are working * Remove null warnings * Cleanup 'FilterManagerTests' - Use explicit types - Remove null warnings - Remove unused params * Remove warnings * Relax null constraints * Remove null warnings * Remove null warnings * Remove null warnings * Remove nullable warnings * Cleanup 'BlockProducerBaseTests.BaseFee' tests * Cleanup 'DbBlocksLoaderTests' * Remove nullable warnings * Remove unused class * Cleanup 'PersistentReceiptStorageTests' * Remove nullable warnings * Relax null constraints * Fix parameter usage * Remove null checks * Remove null warnings - Use init/required only properties * Remove null warnings * Use 'Substitute' instead of null * Cast local function to delegate * Cleanup 'BlockTreeTests' * Treat warnings as errors * Formatting --- .../BlockFinderExtensionsTests.cs | 6 +- .../BlockProcessorTests.cs | 16 +- .../BlockTreeTests.cs | 170 ++++++++++-------- .../BlockchainProcessorTests.cs | 127 ++++++------- .../BlockhashProviderTests.cs | 26 +-- .../Blocks/BlockStoreTests.cs | 13 +- .../Builders/FilterBuilder.cs | 9 +- .../Consensus/NullSignerTests.cs | 4 +- .../Consensus/OneByOneTxSourceTests.cs | 5 +- .../Consensus/SignerTests.cs | 17 +- .../Consensus/SinglePendingTxSelectorTests.cs | 6 - .../Filters/FilterManagerTests.cs | 134 ++++++-------- .../Filters/LogFilterTests.cs | 65 +++---- .../Find/LogFinderTests.cs | 4 +- .../FullPruning/CopyTreeVisitorTests.cs | 8 +- .../FullPruning/FullPruningDiskTest.cs | 8 +- .../Nethermind.Blockchain.Test.csproj | 4 +- .../BlockProducerBaseTests.BaseFee.cs | 52 +++--- .../BlockProducerBaseTests.FeeCollector.cs | 6 +- .../BuildBlocksOnlyWhenNotProcessingTests.cs | 4 +- .../Producers/DevBlockproducerTests.cs | 6 +- .../Proofs/ReceiptTrieTests.cs | 4 +- .../Receipts/PersistentReceiptStorageTests.cs | 69 +++---- .../Receipts/ReceiptsIteratorTests.cs | 12 +- .../Nethermind.Blockchain.Test/ReorgTests.cs | 4 +- .../Services/HealthHintServiceTests.cs | 24 ++- .../TransactionSelectorTests.cs | 9 +- .../Validators/TestSealValidator.cs | 45 ----- .../Validators/UnclesValidatorTests.cs | 4 +- .../Visitors/DbBlocksLoaderTests.cs | 64 ++++--- .../Visitors/StartupTreeFixerTests.cs | 11 +- .../Nethermind.Consensus/NethDevSealEngine.cs | 6 +- .../Nethermind.Consensus/NullSealEngine.cs | 8 +- .../Nethermind.Consensus/NullSigner.cs | 6 +- src/Nethermind/Nethermind.Consensus/Signer.cs | 4 +- .../Transactions/SinglePendingTxSelector.cs | 3 +- .../Builders/TransactionBuilder.cs | 6 +- 37 files changed, 442 insertions(+), 527 deletions(-) delete mode 100644 src/Nethermind/Nethermind.Blockchain.Test/Validators/TestSealValidator.cs diff --git a/src/Nethermind/Nethermind.Blockchain.Test/BlockFinderExtensionsTests.cs b/src/Nethermind/Nethermind.Blockchain.Test/BlockFinderExtensionsTests.cs index 05412dd27c4..dfd7ef2182a 100644 --- a/src/Nethermind/Nethermind.Blockchain.Test/BlockFinderExtensionsTests.cs +++ b/src/Nethermind/Nethermind.Blockchain.Test/BlockFinderExtensionsTests.cs @@ -23,11 +23,11 @@ public void Can_upgrade_maybe_parent() parent.TotalDifficulty.Should().BeNull(); // just to avoid the testing rig change without this test being updated IBlockFinder blockFinder = Substitute.For(); - blockFinder.FindHeader(child.ParentHash, BlockTreeLookupOptions.TotalDifficultyNotNeeded).Returns(parent); - blockFinder.FindHeader(child.ParentHash, BlockTreeLookupOptions.None).Returns(parentWithTotalDiff); + blockFinder.FindHeader(child.ParentHash!, BlockTreeLookupOptions.TotalDifficultyNotNeeded).Returns(parent); + blockFinder.FindHeader(child.ParentHash!, BlockTreeLookupOptions.None).Returns(parentWithTotalDiff); blockFinder.FindParentHeader(child, BlockTreeLookupOptions.TotalDifficultyNotNeeded).Should().Be(parent); - blockFinder.FindParentHeader(child, BlockTreeLookupOptions.None).TotalDifficulty.Should().Be((UInt256?)UInt256.One); + blockFinder.FindParentHeader(child, BlockTreeLookupOptions.None)!.TotalDifficulty.Should().Be((UInt256?)UInt256.One); } } } diff --git a/src/Nethermind/Nethermind.Blockchain.Test/BlockProcessorTests.cs b/src/Nethermind/Nethermind.Blockchain.Test/BlockProcessorTests.cs index f5896cbb355..a56d98e68d2 100644 --- a/src/Nethermind/Nethermind.Blockchain.Test/BlockProcessorTests.cs +++ b/src/Nethermind/Nethermind.Blockchain.Test/BlockProcessorTests.cs @@ -67,7 +67,7 @@ public void Can_store_a_witness() { IDb stateDb = new MemDb(); IDb codeDb = new MemDb(); - var trieStore = new TrieStore(stateDb, LimboLogs.Instance); + TrieStore trieStore = new TrieStore(stateDb, LimboLogs.Instance); IWorldState stateProvider = new WorldState(trieStore, codeDb, LimboLogs.Instance); ITransactionProcessor transactionProcessor = Substitute.For(); @@ -90,7 +90,7 @@ public void Can_store_a_witness() ProcessingOptions.None, NullBlockTracer.Instance); - witnessCollector.Received(1).Persist(block.Hash); + witnessCollector.Received(1).Persist(block.Hash!); } [Test, Timeout(Timeout.MaxTestTime)] @@ -139,20 +139,20 @@ public void Recovers_state_on_cancel() [TestCase(2000)] public async Task Process_long_running_branch(int blocksAmount) { - var address = TestItem.Addresses[0]; - var spec = new TestSingleReleaseSpecProvider(ConstantinopleFix.Instance); - var testRpc = await TestRpcBlockchain.ForTest(SealEngineType.NethDev) + Address address = TestItem.Addresses[0]; + TestSingleReleaseSpecProvider spec = new TestSingleReleaseSpecProvider(ConstantinopleFix.Instance); + TestRpcBlockchain testRpc = await TestRpcBlockchain.ForTest(SealEngineType.NethDev) .Build(spec); testRpc.TestWallet.UnlockAccount(address, new SecureString()); await testRpc.AddFunds(address, 1.Ether()); await testRpc.AddBlock(); - var suggestedBlockResetEvent = new SemaphoreSlim(0); - testRpc.BlockTree.NewHeadBlock += (s, e) => + SemaphoreSlim suggestedBlockResetEvent = new SemaphoreSlim(0); + testRpc.BlockTree.NewHeadBlock += (_, _) => { suggestedBlockResetEvent.Release(1); }; - var branchLength = blocksAmount + (int)testRpc.BlockTree.BestKnownNumber + 1; + int branchLength = blocksAmount + (int)testRpc.BlockTree.BestKnownNumber + 1; ((BlockTree)testRpc.BlockTree).AddBranch(branchLength, (int)testRpc.BlockTree.BestKnownNumber); (await suggestedBlockResetEvent.WaitAsync(TestBlockchain.DefaultTimeout * 10)).Should().BeTrue(); Assert.That((int)testRpc.BlockTree.BestKnownNumber, Is.EqualTo(branchLength - 1)); diff --git a/src/Nethermind/Nethermind.Blockchain.Test/BlockTreeTests.cs b/src/Nethermind/Nethermind.Blockchain.Test/BlockTreeTests.cs index de5548e0830..07119be768f 100644 --- a/src/Nethermind/Nethermind.Blockchain.Test/BlockTreeTests.cs +++ b/src/Nethermind/Nethermind.Blockchain.Test/BlockTreeTests.cs @@ -33,9 +33,9 @@ namespace Nethermind.Blockchain.Test [TestFixture] public class BlockTreeTests { - private TestMemDb _blocksInfosDb; - private TestMemDb _headersDb; - private TestMemDb _blocksDb; + private TestMemDb _blocksInfosDb = null!; + private TestMemDb _headersDb = null!; + private TestMemDb _blocksDb = null!; private BlockTree BuildBlockTree() { @@ -57,10 +57,10 @@ public void Add_genesis_shall_notify() { bool hasNotified = false; BlockTree blockTree = BuildBlockTree(); - blockTree.NewHeadBlock += (sender, args) => { hasNotified = true; }; + blockTree.NewHeadBlock += (_, _) => { hasNotified = true; }; bool hasNotifiedNewSuggested = false; - blockTree.NewSuggestedBlock += (sender, args) => { hasNotifiedNewSuggested = true; }; + blockTree.NewSuggestedBlock += (_, _) => { hasNotifiedNewSuggested = true; }; Block block = Build.A.Block.WithNumber(0).TestObject; AddBlockResult result = blockTree.SuggestBlock(block); @@ -76,10 +76,10 @@ public void Add_genesis_shall_work_even_with_0_difficulty() { bool hasNotified = false; BlockTree blockTree = BuildBlockTree(); - blockTree.NewBestSuggestedBlock += (sender, args) => { hasNotified = true; }; + blockTree.NewBestSuggestedBlock += (_, _) => { hasNotified = true; }; bool hasNotifiedNewSuggested = false; - blockTree.NewSuggestedBlock += (sender, args) => { hasNotifiedNewSuggested = true; }; + blockTree.NewSuggestedBlock += (_, _) => { hasNotifiedNewSuggested = true; }; Block block = Build.A.Block.WithNumber(0).WithDifficulty(0).TestObject; AddBlockResult result = blockTree.SuggestBlock(block); @@ -107,10 +107,10 @@ public void Shall_notify_on_new_head_block_after_genesis() Block block0 = Build.A.Block.WithNumber(0).WithDifficulty(1).TestObject; Block block1 = Build.A.Block.WithNumber(1).WithDifficulty(2).WithParent(block0).TestObject; blockTree.SuggestBlock(block0); - blockTree.NewHeadBlock += (sender, args) => { hasNotified = true; }; + blockTree.NewHeadBlock += (_, _) => { hasNotified = true; }; bool hasNotifiedNewSuggested = false; - blockTree.NewSuggestedBlock += (sender, args) => { hasNotifiedNewSuggested = true; }; + blockTree.NewSuggestedBlock += (_, _) => { hasNotifiedNewSuggested = true; }; AddBlockResult result = blockTree.SuggestBlock(block1); blockTree.UpdateMainChain(block1); @@ -133,13 +133,13 @@ public void Shall_notify_new_head_block_once_and_block_added_to_main_multiple_ti Block block3 = Build.A.Block.WithNumber(3).WithDifficulty(0).WithParent(block2).TestObject; blockTree.SuggestBlock(block0); - blockTree.NewHeadBlock += (sender, args) => { newHeadBlockNotifications++; }; - blockTree.BlockAddedToMain += (sender, args) => { blockAddedToMainNotifications++; }; + blockTree.NewHeadBlock += (_, _) => { newHeadBlockNotifications++; }; + blockTree.BlockAddedToMain += (_, _) => { blockAddedToMainNotifications++; }; blockTree.SuggestBlock(block1); blockTree.SuggestBlock(block2); blockTree.SuggestBlock(block3); - blockTree.UpdateMainChain(new Block[] { block1, block2, block3 }, true); + blockTree.UpdateMainChain(new[] { block1, block2, block3 }, true); newHeadBlockNotifications.Should().Be(1, "new head block"); blockAddedToMainNotifications.Should().Be(3, "block added to main"); @@ -153,10 +153,10 @@ public void Shall_notify_on_new_suggested_block_after_genesis() Block block0 = Build.A.Block.WithNumber(0).WithDifficulty(1).TestObject; Block block1 = Build.A.Block.WithNumber(1).WithDifficulty(2).WithParent(block0).TestObject; blockTree.SuggestBlock(block0); - blockTree.NewBestSuggestedBlock += (sender, args) => { hasNotified = true; }; + blockTree.NewBestSuggestedBlock += (_, _) => { hasNotified = true; }; bool hasNotifiedNewSuggested = false; - blockTree.NewSuggestedBlock += (sender, args) => { hasNotifiedNewSuggested = true; }; + blockTree.NewSuggestedBlock += (_, _) => { hasNotifiedNewSuggested = true; }; AddBlockResult result = blockTree.SuggestBlock(block1); @@ -176,11 +176,11 @@ public void Shall_not_notify_but_add_on_lower_difficulty() Block block2 = Build.A.Block.WithNumber(1).WithDifficulty(2).WithParent(block0).TestObject; blockTree.SuggestBlock(block0); blockTree.SuggestBlock(block1); - blockTree.NewHeadBlock += (sender, args) => { hasNotifiedHead = true; }; - blockTree.NewBestSuggestedBlock += (sender, args) => { hasNotifiedBest = true; }; + blockTree.NewHeadBlock += (_, _) => { hasNotifiedHead = true; }; + blockTree.NewBestSuggestedBlock += (_, _) => { hasNotifiedBest = true; }; bool hasNotifiedNewSuggested = false; - blockTree.NewSuggestedBlock += (sender, args) => { hasNotifiedNewSuggested = true; }; + blockTree.NewSuggestedBlock += (_, _) => { hasNotifiedNewSuggested = true; }; AddBlockResult result = blockTree.SuggestBlock(block2); @@ -230,16 +230,16 @@ public void Cleans_invalid_blocks_before_starting() tree.SuggestBlock(block2); tree.SuggestBlock(block3); - blockInfosDb.Set(BlockTree.DeletePointerAddressInDb, block1.Hash.Bytes); + blockInfosDb.Set(BlockTree.DeletePointerAddressInDb, block1.Hash!.Bytes); BlockTree tree2 = new(blocksDb, headersDb, blockInfosDb, new ChainLevelInfoRepository(blockInfosDb), MainnetSpecProvider.Instance, NullBloomStorage.Instance, LimboLogs.Instance); Assert.That(tree2.BestKnownNumber, Is.EqualTo(0L), "best known"); Assert.That(tree2.Head, Is.EqualTo(null), "head"); - Assert.That(tree2.BestSuggestedHeader.Number, Is.EqualTo(0L), "suggested"); + Assert.That(tree2.BestSuggestedHeader!.Number, Is.EqualTo(0L), "suggested"); - Assert.IsNull(blocksDb.Get(block2.Hash), "block 1"); - Assert.IsNull(blocksDb.Get(block2.Hash), "block 2"); - Assert.IsNull(blocksDb.Get(block3.Hash), "block 3"); + Assert.IsNull(blocksDb.Get(block2.Hash!), "block 1"); + Assert.IsNull(blocksDb.Get(block2.Hash!), "block 2"); + Assert.IsNull(blocksDb.Get(block3.Hash!), "block 3"); Assert.IsNull(blockInfosDb.Get(2), "level 1"); Assert.IsNull(blockInfosDb.Get(2), "level 2"); @@ -271,16 +271,16 @@ public void When_cleaning_descendants_of_invalid_does_not_touch_other_branches() tree.SuggestBlock(block2B); tree.SuggestBlock(block3B); - blockInfosDb.Set(BlockTree.DeletePointerAddressInDb, block1.Hash.Bytes); + blockInfosDb.Set(BlockTree.DeletePointerAddressInDb, block1.Hash!.Bytes); BlockTree tree2 = new(blocksDb, headersDb, blockInfosDb, new ChainLevelInfoRepository(blockInfosDb), MainnetSpecProvider.Instance, NullBloomStorage.Instance, LimboLogs.Instance); Assert.That(tree2.BestKnownNumber, Is.EqualTo(3L), "best known"); Assert.That(tree2.Head, Is.EqualTo(null), "head"); - Assert.That(tree2.BestSuggestedHeader.Hash, Is.EqualTo(block3B.Hash), "suggested"); + Assert.That(tree2.BestSuggestedHeader!.Hash, Is.EqualTo(block3B.Hash), "suggested"); - blocksDb.Get(block1.Hash).Should().BeNull("block 1"); - blocksDb.Get(block2.Hash).Should().BeNull("block 2"); - blocksDb.Get(block3.Hash).Should().BeNull("block 3"); + blocksDb.Get(block1.Hash!).Should().BeNull("block 1"); + blocksDb.Get(block2.Hash!).Should().BeNull("block 2"); + blocksDb.Get(block3.Hash!).Should().BeNull("block 3"); Assert.NotNull(blockInfosDb.Get(1), "level 1"); Assert.NotNull(blockInfosDb.Get(2), "level 2"); @@ -302,7 +302,7 @@ public void Can_load_best_known_up_to_256million() return chainLevel.Bytes; } - return null; + return null!; }; BlockTree blockTree = new(_blocksDb, _headersDb, blocksInfosDb, new ChainLevelInfoRepository(blocksInfosDb), MainnetSpecProvider.Instance, NullBloomStorage.Instance, LimboLogs.Instance); @@ -336,7 +336,7 @@ public void Add_on_branch_move_find_via_block_finder_interface() BlockTree blockTree = BuildBlockTree(); Block block = Build.A.Block.TestObject; AddToMain(blockTree, block); - Block? found = ((IBlockFinder)blockTree).FindBlock(new BlockParameter(block.Hash, true)); + Block? found = ((IBlockFinder)blockTree).FindBlock(new BlockParameter(block.Hash!, true)); Assert.That(found?.Header.CalculateHash(), Is.EqualTo(block.Hash)); } @@ -356,7 +356,7 @@ public void Add_on_branch_and_not_find_on_main_via_block_finder_interface() BlockTree blockTree = BuildBlockTree(); Block block = Build.A.Block.TestObject; blockTree.SuggestBlock(block); - Block? found = ((IBlockFinder)blockTree).FindBlock(new BlockParameter(block.Hash, true)); + Block? found = ((IBlockFinder)blockTree).FindBlock(new BlockParameter(block.Hash!, true)); Assert.IsNull(found); } @@ -675,7 +675,7 @@ public void Total_difficulty_is_calculated_when_exists_parent_with_total_difficu Block block0 = Build.A.Block.WithNumber(0).WithDifficulty(1).TestObject; blockTree.SuggestBlock(block0); - Block block1 = Build.A.Block.WithNumber(1).WithParentHash(block0.Hash).WithDifficulty(2).TestObject; + Block block1 = Build.A.Block.WithNumber(1).WithParentHash(block0.Hash!).WithDifficulty(2).TestObject; blockTree.SuggestBlock(block1); block1.TotalDifficulty.Should().NotBeNull(); Assert.That((int)block1.TotalDifficulty!, Is.EqualTo(3)); @@ -703,7 +703,7 @@ public void Head_block_gets_updated() AddToMain(blockTree, block0); AddToMain(blockTree, block1); - Assert.That(blockTree.Head.CalculateHash(), Is.EqualTo(block1.Hash)); + Assert.That(blockTree.Head!.CalculateHash(), Is.EqualTo(block1.Hash)); } [Test, Timeout(Timeout.MaxTestTime)] @@ -715,8 +715,8 @@ public void Best_suggested_block_gets_updated() AddToMain(blockTree, block0); blockTree.SuggestBlock(block1); - Assert.That(blockTree.Head.CalculateHash(), Is.EqualTo(block0.Hash), "head block"); - Assert.That(blockTree.BestSuggestedHeader.CalculateHash(), Is.EqualTo(block1.Hash), "best suggested"); + Assert.That(blockTree.Head!.CalculateHash(), Is.EqualTo(block0.Hash), "head block"); + Assert.That(blockTree.BestSuggestedHeader!.CalculateHash(), Is.EqualTo(block1.Hash), "best suggested"); } [Test, Timeout(Timeout.MaxTestTime)] @@ -726,7 +726,7 @@ public void Sets_genesis_block() Block block0 = Build.A.Block.WithNumber(0).WithDifficulty(1).TestObject; AddToMain(blockTree, block0); - Assert.That(blockTree.Genesis.CalculateHash(), Is.EqualTo(block0.Hash)); + Assert.That(blockTree.Genesis!.CalculateHash(), Is.EqualTo(block0.Hash)); } [Test, Timeout(Timeout.MaxTestTime)] @@ -764,12 +764,12 @@ public void Can_init_head_block_from_db_by_hash() MemDb blocksDb = new(); MemDb headersDb = new(); - blocksDb.Set(genesisBlock.Hash, Rlp.Encode(genesisBlock).Bytes); - headersDb.Set(genesisBlock.Hash, Rlp.Encode(genesisBlock.Header).Bytes); + blocksDb.Set(genesisBlock.Hash!, Rlp.Encode(genesisBlock).Bytes); + headersDb.Set(genesisBlock.Hash!, Rlp.Encode(genesisBlock.Header).Bytes); MemDb blockInfosDb = new(); - blockInfosDb.Set(Keccak.Zero, genesisBlock.Hash.Bytes); - ChainLevelInfo level = new(true, new BlockInfo(headBlock.Hash, headBlock.Difficulty)); + blockInfosDb.Set(Keccak.Zero, genesisBlock.Hash!.Bytes); + ChainLevelInfo level = new(true, new BlockInfo(headBlock.Hash!, headBlock.Difficulty)); level.BlockInfos[0].WasProcessed = true; blockInfosDb.Set(0, Rlp.Encode(level).Bytes); @@ -801,7 +801,7 @@ public void Sets_head_block_hash_in_db_on_new_head_block() AddToMain(blockTree, block0); AddToMain(blockTree, block1); - Keccak dec = new Keccak(blockInfosDb.Get(Keccak.Zero)); + Keccak dec = new Keccak(blockInfosDb.Get(Keccak.Zero)!); Assert.That(dec, Is.EqualTo(block1.Hash)); } @@ -814,9 +814,9 @@ public void Can_check_if_block_was_processed() BlockTree blockTree = BuildBlockTree(); blockTree.SuggestBlock(block0); blockTree.SuggestBlock(block1); - Assert.False(blockTree.WasProcessed(block1.Number, block1.Hash), "before"); + Assert.False(blockTree.WasProcessed(block1.Number, block1.Hash!), "before"); blockTree.UpdateMainChain(new[] { block0, block1 }, true); - Assert.True(blockTree.WasProcessed(block1.Number, block1.Hash), "after"); + Assert.True(blockTree.WasProcessed(block1.Number, block1.Hash!), "after"); } [Test, Timeout(Timeout.MaxTestTime)] @@ -840,7 +840,7 @@ public void Is_main_chain_returns_false_when_on_branch() BlockTree blockTree = BuildBlockTree(); blockTree.SuggestBlock(block0); blockTree.SuggestBlock(block1); - Assert.False(blockTree.IsMainChain(block1.Hash)); + Assert.False(blockTree.IsMainChain(block1.Hash!)); } [Test, Timeout(Timeout.MaxTestTime)] @@ -853,7 +853,7 @@ public void Is_main_chain_returns_true_when_on_main() blockTree.SuggestBlock(block0); blockTree.SuggestBlock(block1); blockTree.UpdateMainChain(block1); - Assert.True(blockTree.IsMainChain(block1.Hash)); + Assert.True(blockTree.IsMainChain(block1.Hash!)); } [Test, Timeout(Timeout.MaxTestTime)] @@ -1104,15 +1104,18 @@ public void When_deleting_invalid_block_does_not_delete_blocks_that_are_not_its_ [Test, Timeout(Timeout.MaxTestTime), TestCaseSource(nameof(SourceOfBSearchTestCases))] public void Loads_lowest_inserted_header_correctly(long beginIndex, long insertedBlocks) { - long? expectedResult = insertedBlocks == 0L ? (long?)null : beginIndex - insertedBlocks + 1L; + long? expectedResult = insertedBlocks == 0L ? null : beginIndex - insertedBlocks + 1L; MemDb blocksDb = new(); MemDb blockInfosDb = new(); MemDb headersDb = new(); MemDb metadataDb = new(); - SyncConfig syncConfig = new() { FastSync = true }; - syncConfig.PivotNumber = beginIndex.ToString(); + SyncConfig syncConfig = new() + { + FastSync = true, + PivotNumber = beginIndex.ToString(), + }; BlockTree tree = new(blocksDb, headersDb, blockInfosDb, metadataDb, new ChainLevelInfoRepository(blockInfosDb), MainnetSpecProvider.Instance, NullBloomStorage.Instance, syncConfig, LimboLogs.Instance); tree.SuggestBlock(Build.A.Block.Genesis.TestObject); @@ -1141,8 +1144,10 @@ public void Loads_lowest_inserted_body_correctly(long beginIndex, long insertedB blocksDb.Set(0, Rlp.Encode(1L).Bytes); - SyncConfig syncConfig = new(); - syncConfig.PivotNumber = beginIndex.ToString(); + SyncConfig syncConfig = new() + { + PivotNumber = beginIndex.ToString(), + }; ChainLevelInfoRepository repo = new ChainLevelInfoRepository(blockInfosDb); BlockTree tree = new(blocksDb, headersDb, blockInfosDb, metadataDb, repo, MainnetSpecProvider.Instance, NullBloomStorage.Instance, syncConfig, LimboLogs.Instance); @@ -1189,7 +1194,7 @@ public void Loads_lowest_inserted_body_correctly(long beginIndex, long insertedB new object[] {7280000L, 1L} }; - private ChainLevelInfoRepository _chainLevelInfoRepository; + private ChainLevelInfoRepository _chainLevelInfoRepository = null!; [Test, Timeout(Timeout.MaxTestTime), TestCaseSource(nameof(SourceOfBSearchTestCases))] public void Loads_best_known_correctly_on_inserts(long beginIndex, long insertedBlocks) @@ -1201,9 +1206,11 @@ public void Loads_best_known_correctly_on_inserts(long beginIndex, long inserted MemDb headersDb = new(); MemDb metadataDb = new(); - SyncConfig syncConfig = new(); - syncConfig.PivotNumber = beginIndex.ToString(); - syncConfig.FastSync = true; + SyncConfig syncConfig = new() + { + PivotNumber = beginIndex.ToString(), + FastSync = true, + }; BlockTree tree = new(blocksDb, headersDb, blockInfosDb, metadataDb, new ChainLevelInfoRepository(blockInfosDb), MainnetSpecProvider.Instance, NullBloomStorage.Instance, syncConfig, LimboLogs.Instance); tree.SuggestBlock(Build.A.Block.Genesis.TestObject); @@ -1240,9 +1247,11 @@ public void Loads_best_head_up_to_best_persisted_state() metadataDb.Set(MetadataDbKeys.BeaconSyncPivotNumber, Rlp.Encode(51).Bytes); - SyncConfig syncConfig = new(); - syncConfig.PivotNumber = "0"; - syncConfig.FastSync = true; + SyncConfig syncConfig = new() + { + PivotNumber = "0", + FastSync = true, + }; BlockTree tree = new(blocksDb, headersDb, blockInfosDb, metadataDb, new ChainLevelInfoRepository(blockInfosDb), MainnetSpecProvider.Instance, NullBloomStorage.Instance, syncConfig, LimboLogs.Instance); Block genesis = Build.A.Block.Genesis.TestObject; @@ -1297,13 +1306,15 @@ public void Loads_best_known_correctly_on_inserts_followed_by_suggests(long pivo MemDb headersDb = new(); MemDb metadataDb = new(); - SyncConfig syncConfig = new(); - syncConfig.PivotNumber = pivotNumber.ToString(); + SyncConfig syncConfig = new() + { + PivotNumber = pivotNumber.ToString(), + }; BlockTree tree = new(blocksDb, headersDb, blockInfosDb, metadataDb, new ChainLevelInfoRepository(blockInfosDb), MainnetSpecProvider.Instance, NullBloomStorage.Instance, syncConfig, LimboLogs.Instance); tree.SuggestBlock(Build.A.Block.Genesis.TestObject); - Block pivotBlock = null!; + Block? pivotBlock = null; for (long i = pivotNumber; i > 0; i--) { Block block = Build.A.Block.WithNumber(i).WithTotalDifficulty(i).TestObject; @@ -1326,7 +1337,10 @@ public void Loads_best_known_correctly_when_head_before_pivot() { int pivotNumber = 1000; int head = 10; - SyncConfig syncConfig = new() { PivotNumber = pivotNumber.ToString() }; + SyncConfig syncConfig = new() + { + PivotNumber = pivotNumber.ToString() + }; BlockTreeBuilder treeBuilder = Build.A.BlockTree().OfChainLength(head + 1); @@ -1354,8 +1368,10 @@ public void Cannot_insert_genesis() long pivotNumber = 0L; - SyncConfig syncConfig = new(); - syncConfig.PivotNumber = pivotNumber.ToString(); + SyncConfig syncConfig = new() + { + PivotNumber = pivotNumber.ToString(), + }; BlockTree tree = new(blocksDb, headersDb, blockInfosDb, metadataDb, new ChainLevelInfoRepository(blockInfosDb), MainnetSpecProvider.Instance, NullBloomStorage.Instance, syncConfig, LimboLogs.Instance); Block genesis = Build.A.Block.Genesis.TestObject; @@ -1374,8 +1390,10 @@ public void Should_set_zero_total_difficulty() long pivotNumber = 0L; - SyncConfig syncConfig = new(); - syncConfig.PivotNumber = pivotNumber.ToString(); + SyncConfig syncConfig = new() + { + PivotNumber = pivotNumber.ToString(), + }; CustomSpecProvider specProvider = new(((ForkActivation)0, London.Instance)); specProvider.UpdateMergeTransitionInfo(null, 0); @@ -1402,8 +1420,10 @@ public void Inserts_blooms() long pivotNumber = 5L; - SyncConfig syncConfig = new(); - syncConfig.PivotNumber = pivotNumber.ToString(); + SyncConfig syncConfig = new() + { + PivotNumber = pivotNumber.ToString(), + }; IBloomStorage bloomStorage = Substitute.For(); IChainLevelInfoRepository chainLevelInfoRepository = Substitute.For(); @@ -1430,8 +1450,10 @@ public void Block_loading_is_lazy() MemDb headersDb = new(); MemDb metadataDb = new(); - SyncConfig syncConfig = new(); - syncConfig.PivotNumber = 0L.ToString(); + SyncConfig syncConfig = new() + { + PivotNumber = 0L.ToString(), + }; Block genesis = Build.A.Block.Genesis.TestObject; BlockTree tree = new(blocksDb, headersDb, blockInfosDb, metadataDb, new ChainLevelInfoRepository(blockInfosDb), MainnetSpecProvider.Instance, NullBloomStorage.Instance, syncConfig, LimboLogs.Instance); @@ -1665,7 +1687,7 @@ public void Recovers_total_difficulty(int chainLength, bool deleteAllLevels, ulo ChainLevelInfo? level = blockTreeBuilder.ChainLevelInfoRepository.LoadLevel(i); level.Should().NotBeNull(); - level.BlockInfos.Should().HaveCount(1); + level!.BlockInfos.Should().HaveCount(1); } } @@ -1749,11 +1771,11 @@ public static IEnumerable InvalidBlockTestCases foreach (BlockTreeLookupOptions blockTreeLookupOptions in valueCombinations) { bool allowInvalid = (blockTreeLookupOptions & BlockTreeLookupOptions.AllowInvalid) == BlockTreeLookupOptions.AllowInvalid; - yield return new TestCaseData(FindHeader, blockTreeLookupOptions, allowInvalid) + yield return new TestCaseData((Func)FindHeader, blockTreeLookupOptions, allowInvalid) { TestName = $"InvalidBlock_{nameof(FindHeader)}_({blockTreeLookupOptions})_{(allowInvalid ? "found" : "not_found")}" }; - yield return new TestCaseData(FindBlock, blockTreeLookupOptions, allowInvalid) + yield return new TestCaseData((Func)FindBlock, blockTreeLookupOptions, allowInvalid) { TestName = $"InvalidBlock_{nameof(FindBlock)}_({blockTreeLookupOptions})_{(allowInvalid ? "found" : "not_found")}" }; @@ -1781,9 +1803,9 @@ public TestBlockTreeVisitor(ManualResetEvent manualResetEvent) _manualResetEvent = manualResetEvent; } - public bool PreventsAcceptingNewBlocks { get; } = true; - public long StartLevelInclusive { get; } = 0; - public long EndLevelExclusive { get; } = 3; + public bool PreventsAcceptingNewBlocks => true; + public long StartLevelInclusive => 0; + public long EndLevelExclusive => 3; public async Task VisitLevelStart(ChainLevelInfo chainLevelInfo, long levelNumber, CancellationToken cancellationToken) { if (_wait) diff --git a/src/Nethermind/Nethermind.Blockchain.Test/BlockchainProcessorTests.cs b/src/Nethermind/Nethermind.Blockchain.Test/BlockchainProcessorTests.cs index 3de7098dcba..66e32c4f0c1 100644 --- a/src/Nethermind/Nethermind.Blockchain.Test/BlockchainProcessorTests.cs +++ b/src/Nethermind/Nethermind.Blockchain.Test/BlockchainProcessorTests.cs @@ -108,18 +108,18 @@ public Block[] Process(Keccak newBranchStateRoot, List suggestedBlocks, P } else { - _rootProcessed.Add(suggestedBlocks.Last().StateRoot); + _rootProcessed.Add(suggestedBlocks.Last().StateRoot!); BlockProcessed?.Invoke(this, new BlockProcessedEventArgs(suggestedBlocks.Last(), Array.Empty())); return suggestedBlocks.ToArray(); } } } - public event EventHandler BlocksProcessing; + public event EventHandler? BlocksProcessing; - public event EventHandler BlockProcessed; + public event EventHandler? BlockProcessed; - public event EventHandler TransactionProcessed + public event EventHandler? TransactionProcessed { add { } remove { } @@ -128,11 +128,9 @@ public event EventHandler TransactionProcessed private class RecoveryStepMock : IBlockPreprocessorStep { - private ILogger _logger; - - private ConcurrentDictionary _allowed = new(); - - private ConcurrentDictionary _allowedToFail = new(); + private readonly ILogger _logger; + private readonly ConcurrentDictionary _allowed = new(); + private readonly ConcurrentDictionary _allowedToFail = new(); public RecoveryStepMock(ILogManager logManager) { @@ -145,12 +143,6 @@ public void Allow(Keccak hash) _allowed[hash] = new object(); } - public void AllowToFail(Keccak hash) - { - _logger.Info($"Allowing {hash} to fail recover"); - _allowedToFail[hash] = new object(); - } - public void RecoverData(Block block) { _logger.Info($"Recovering data for {block.ToString(Block.Format.Short)}"); @@ -162,11 +154,12 @@ public void RecoverData(Block block) while (true) { - if (!_allowed.ContainsKey(block.Hash)) + Keccak blockHash = block.Hash!; + if (!_allowed.ContainsKey(blockHash)) { - if (_allowedToFail.ContainsKey(block.Hash)) + if (_allowedToFail.ContainsKey(blockHash)) { - _allowedToFail.Remove(block.Hash, out _); + _allowedToFail.Remove(blockHash, out _); throw new Exception(); } @@ -175,22 +168,23 @@ public void RecoverData(Block block) } block.Header.Author = Address.Zero; - _allowed.Remove(block.Hash, out _); + _allowed.Remove(blockHash, out _); return; } } } - private BlockTree _blockTree; - private AutoResetEvent _resetEvent; - private AutoResetEvent _queueEmptyResetEvent; - private BlockProcessorMock _blockProcessor; - private RecoveryStepMock _recoveryStep; - private BlockchainProcessor _processor; - private ILogger _logger; - private Keccak _headBefore; + private readonly BlockTree _blockTree; + private readonly AutoResetEvent _resetEvent; + private readonly AutoResetEvent _queueEmptyResetEvent; + private readonly BlockProcessorMock _blockProcessor; + private readonly RecoveryStepMock _recoveryStep; + private readonly BlockchainProcessor _processor; + private readonly ILogger _logger; + + private Keccak? _headBefore; private int _processingQueueEmptyFired; - public const int ProcessingWait = 2000; + private const int ProcessingWait = 2000; public ProcessingTestContext(bool startProcessor) { @@ -214,7 +208,7 @@ public ProcessingTestContext(bool startProcessor) _queueEmptyResetEvent.Set(); }; - _blockTree.NewHeadBlock += (sender, args) => + _blockTree.NewHeadBlock += (_, args) => { _logger.Info($"Finished waiting for {args.Block.ToString(Block.Format.Short)} as block became the new head block"); _resetEvent.Set(); @@ -242,7 +236,7 @@ public AfterBlock Processed(Block block) _headBefore = _blockTree.Head?.Hash; ManualResetEvent processedEvent = new(false); bool wasProcessed = false; - _blockProcessor.BlockProcessed += (sender, args) => + _blockProcessor.BlockProcessed += (_, args) => { if (args.Block.Hash == block.Hash) { @@ -252,7 +246,7 @@ public AfterBlock Processed(Block block) }; _logger.Info($"Waiting for {block.ToString(Block.Format.Short)} to process"); - _blockProcessor.Allow(block.Hash); + _blockProcessor.Allow(block.Hash!); processedEvent.WaitOne(ProcessingWait); Assert.True(wasProcessed, $"Expected this block to get processed but it was not: {block.ToString(Block.Format.Short)}"); @@ -263,7 +257,7 @@ public AfterBlock ProcessedSkipped(Block block) { _headBefore = _blockTree.Head?.Hash; _logger.Info($"Waiting for {block.ToString(Block.Format.Short)} to be skipped"); - _blockProcessor.Allow(block.Hash); + _blockProcessor.Allow(block.Hash!); return new AfterBlock(_logManager, this, block); } @@ -272,7 +266,7 @@ public AfterBlock ProcessedFail(Block block) _headBefore = _blockTree.Head?.Hash; ManualResetEvent processedEvent = new(false); bool wasProcessed = false; - _blockProcessor.BlockProcessed += (sender, args) => + _blockProcessor.BlockProcessed += (_, args) => { if (args.Block.Hash == block.Hash) { @@ -282,7 +276,7 @@ public AfterBlock ProcessedFail(Block block) }; _logger.Info($"Waiting for {block.ToString(Block.Format.Short)} to fail processing"); - _blockProcessor.AllowToFail(block.Hash); + _blockProcessor.AllowToFail(block.Hash!); processedEvent.WaitOne(ProcessingWait); Assert.True(wasProcessed, $"Block was never processed {block.ToString(Block.Format.Short)}"); Assert.That(_blockTree.Head?.Hash, Is.EqualTo(_headBefore), $"Processing did not fail - {block.ToString(Block.Format.Short)} became a new head block"); @@ -311,15 +305,8 @@ public ProcessingTestContext SuggestedWithoutProcessingAndMoveToMain(Block block } _blockTree.UpdateMainChain(new[] { block }, false); - _blockProcessor.Allow(block.Hash); - _recoveryStep.Allow(block.Hash); - - return this; - } - - public ProcessingTestContext StartProcessor() - { - _processor.Start(); + _blockProcessor.Allow(block.Hash!); + _recoveryStep.Allow(block.Hash!); return this; } @@ -338,7 +325,7 @@ public ProcessingTestContext Suggested(BlockHeader block) public ProcessingTestContext Recovered(Block block) { - _recoveryStep.Allow(block.Hash); + _recoveryStep.Allow(block.Hash!); return this; } @@ -349,12 +336,6 @@ public ProcessingTestContext CountIs(int expectedCount) return this; } - public ProcessingTestContext ThenRecoveredFail(Block block) - { - _recoveryStep.AllowToFail(block.Hash); - return this; - } - public AfterBlock FullyProcessed(Block block) { return Suggested(block) @@ -385,10 +366,10 @@ public ProcessingTestContext QueueIsEmpty(int count) public class AfterBlock { - private ILogger _logger; public const int IgnoreWait = 200; - private readonly Block _block; + private readonly ILogger _logger; + private readonly Block _block; private readonly ProcessingTestContext _processingTestContext; public AfterBlock(ILogManager logManager, ProcessingTestContext processingTestContext, Block block) @@ -402,7 +383,7 @@ public ProcessingTestContext BecomesGenesis() { _logger.Info($"Waiting for {_block.ToString(Block.Format.Short)} to become genesis block"); _processingTestContext._resetEvent.WaitOne(ProcessingWait); - Assert.That(_processingTestContext._blockTree.Genesis.Hash, Is.EqualTo(_block.Header.Hash), "genesis"); + Assert.That(_processingTestContext._blockTree.Genesis!.Hash, Is.EqualTo(_block.Header.Hash), "genesis"); return _processingTestContext; } @@ -410,7 +391,7 @@ public ProcessingTestContext BecomesNewHead() { _logger.Info($"Waiting for {_block.ToString(Block.Format.Short)} to become the new head block"); _processingTestContext._resetEvent.WaitOne(ProcessingWait); - Assert.That(() => _processingTestContext._blockTree.Head.Hash, Is.EqualTo(_block.Header.Hash).After(1000, 100)); + Assert.That(() => _processingTestContext._blockTree.Head!.Hash, Is.EqualTo(_block.Header.Hash).After(1000, 100)); return _processingTestContext; } @@ -418,7 +399,7 @@ public ProcessingTestContext IsKeptOnBranch() { _logger.Info($"Waiting for {_block.ToString(Block.Format.Short)} to be ignored"); _processingTestContext._resetEvent.WaitOne(IgnoreWait); - Assert.That(_processingTestContext._blockTree.Head.Hash, Is.EqualTo(_processingTestContext._headBefore), "head"); + Assert.That(_processingTestContext._blockTree.Head!.Hash, Is.EqualTo(_processingTestContext._headBefore), "head"); _logger.Info($"Finished waiting for {_block.ToString(Block.Format.Short)} to be ignored"); return _processingTestContext; } @@ -427,7 +408,7 @@ public ProcessingTestContext IsDeletedAsInvalid() { _logger.Info($"Waiting for {_block.ToString(Block.Format.Short)} to be deleted"); _processingTestContext._resetEvent.WaitOne(IgnoreWait); - Assert.That(_processingTestContext._blockTree.Head.Hash, Is.EqualTo(_processingTestContext._headBefore), "head"); + Assert.That(_processingTestContext._blockTree.Head!.Hash, Is.EqualTo(_processingTestContext._headBefore), "head"); _logger.Info($"Finished waiting for {_block.ToString(Block.Format.Short)} to be deleted"); Assert.Null(_processingTestContext._blockTree.FindBlock(_block.Hash, BlockTreeLookupOptions.None)); return _processingTestContext; @@ -448,17 +429,17 @@ private static class When public static ProcessingTestContext ProcessorIsNotStarted => new(false); } - private static Block _block0 = Build.A.Block.WithNumber(0).WithNonce(0).WithDifficulty(0).TestObject; - private static Block _block1D2 = Build.A.Block.WithNumber(1).WithNonce(1).WithParent(_block0).WithDifficulty(2).TestObject; - private static Block _block2D4 = Build.A.Block.WithNumber(2).WithNonce(2).WithParent(_block1D2).WithDifficulty(2).TestObject; - private static Block _block3D6 = Build.A.Block.WithNumber(3).WithNonce(3).WithParent(_block2D4).WithDifficulty(2).TestObject; - private static Block _block4D8 = Build.A.Block.WithNumber(4).WithNonce(4).WithParent(_block3D6).WithDifficulty(2).TestObject; - private static Block _block5D10 = Build.A.Block.WithNumber(5).WithNonce(5).WithParent(_block4D8).WithDifficulty(2).TestObject; - private static Block _blockB2D4 = Build.A.Block.WithNumber(2).WithNonce(6).WithParent(_block1D2).WithDifficulty(2).TestObject; - private static Block _blockB3D8 = Build.A.Block.WithNumber(3).WithNonce(7).WithParent(_blockB2D4).WithDifficulty(4).TestObject; - private static Block _blockC2D100 = Build.A.Block.WithNumber(3).WithNonce(8).WithParent(_block1D2).WithDifficulty(98).TestObject; - private static Block _blockD2D200 = Build.A.Block.WithNumber(3).WithNonce(8).WithParent(_block1D2).WithDifficulty(198).TestObject; - private static Block _blockE2D300 = Build.A.Block.WithNumber(3).WithNonce(8).WithParent(_block1D2).WithDifficulty(298).TestObject; + private static readonly Block _block0 = Build.A.Block.WithNumber(0).WithNonce(0).WithDifficulty(0).TestObject; + private static readonly Block _block1D2 = Build.A.Block.WithNumber(1).WithNonce(1).WithParent(_block0).WithDifficulty(2).TestObject; + private static readonly Block _block2D4 = Build.A.Block.WithNumber(2).WithNonce(2).WithParent(_block1D2).WithDifficulty(2).TestObject; + private static readonly Block _block3D6 = Build.A.Block.WithNumber(3).WithNonce(3).WithParent(_block2D4).WithDifficulty(2).TestObject; + private static readonly Block _block4D8 = Build.A.Block.WithNumber(4).WithNonce(4).WithParent(_block3D6).WithDifficulty(2).TestObject; + private static readonly Block _block5D10 = Build.A.Block.WithNumber(5).WithNonce(5).WithParent(_block4D8).WithDifficulty(2).TestObject; + private static readonly Block _blockB2D4 = Build.A.Block.WithNumber(2).WithNonce(6).WithParent(_block1D2).WithDifficulty(2).TestObject; + private static readonly Block _blockB3D8 = Build.A.Block.WithNumber(3).WithNonce(7).WithParent(_blockB2D4).WithDifficulty(4).TestObject; + private static readonly Block _blockC2D100 = Build.A.Block.WithNumber(3).WithNonce(8).WithParent(_block1D2).WithDifficulty(98).TestObject; + private static readonly Block _blockD2D200 = Build.A.Block.WithNumber(3).WithNonce(8).WithParent(_block1D2).WithDifficulty(198).TestObject; + private static readonly Block _blockE2D300 = Build.A.Block.WithNumber(3).WithNonce(8).WithParent(_block1D2).WithDifficulty(298).TestObject; [Test, Timeout(Timeout.MaxTestTime)] public void Can_ignore_lower_difficulty() @@ -524,12 +505,12 @@ public async Task Can_process_fast_sync() await testBlockchain.BuildSomeBlocks(5); When.ProcessingBlocks - .FullyProcessed(testBlockchain.BlockTree.FindBlock(0)).BecomesGenesis() - .SuggestedWithoutProcessingAndMoveToMain(testBlockchain.BlockTree.FindBlock(1)) - .SuggestedWithoutProcessingAndMoveToMain(testBlockchain.BlockTree.FindBlock(2)) - .SuggestedWithoutProcessingAndMoveToMain(testBlockchain.BlockTree.FindBlock(3)) - .SuggestedWithoutProcessingAndMoveToMain(testBlockchain.BlockTree.FindBlock(4)) - .FullyProcessed(testBlockchain.BlockTree.FindBlock(5)).BecomesNewHead(); + .FullyProcessed(testBlockchain.BlockTree.FindBlock(0)!).BecomesGenesis() + .SuggestedWithoutProcessingAndMoveToMain(testBlockchain.BlockTree.FindBlock(1)!) + .SuggestedWithoutProcessingAndMoveToMain(testBlockchain.BlockTree.FindBlock(2)!) + .SuggestedWithoutProcessingAndMoveToMain(testBlockchain.BlockTree.FindBlock(3)!) + .SuggestedWithoutProcessingAndMoveToMain(testBlockchain.BlockTree.FindBlock(4)!) + .FullyProcessed(testBlockchain.BlockTree.FindBlock(5)!).BecomesNewHead(); } [Test, Timeout(Timeout.MaxTestTime)] diff --git a/src/Nethermind/Nethermind.Blockchain.Test/BlockhashProviderTests.cs b/src/Nethermind/Nethermind.Blockchain.Test/BlockhashProviderTests.cs index 89008b2e606..dd3b8feee26 100644 --- a/src/Nethermind/Nethermind.Blockchain.Test/BlockhashProviderTests.cs +++ b/src/Nethermind/Nethermind.Blockchain.Test/BlockhashProviderTests.cs @@ -37,10 +37,10 @@ public void Can_lookup_up_to_256_before_with_headers_only() BlockTree tree = Build.A.BlockTree(genesis).OfHeadersOnly.OfChainLength(chainLength).TestObject; BlockhashProvider provider = new(tree, LimboLogs.Instance); - BlockHeader head = tree.FindHeader(chainLength - 1, BlockTreeLookupOptions.None); + BlockHeader head = tree.FindHeader(chainLength - 1, BlockTreeLookupOptions.None)!; Block current = Build.A.Block.WithParent(head).TestObject; Keccak result = provider.GetBlockhash(current.Header, chainLength - 256); - Assert.That(result, Is.EqualTo(tree.FindHeader(256, BlockTreeLookupOptions.None).Hash)); + Assert.That(result, Is.EqualTo(tree.FindHeader(256, BlockTreeLookupOptions.None)!.Hash)); } [Test, Timeout(Timeout.MaxTestTime)] @@ -49,7 +49,7 @@ public void Can_lookup_up_to_256_before_with_headers_only_and_competing_branches const int chainLength = 512; Block genesis = Build.A.Block.Genesis.TestObject; - BlockTree tree = Build.A.BlockTree(genesis).OfHeadersOnly.OfChainLength(out Block headBlock, chainLength).OfChainLength(out Block alternativeHeadBlock, chainLength, 1).TestObject; + BlockTree tree = Build.A.BlockTree(genesis).OfHeadersOnly.OfChainLength(out Block headBlock, chainLength).OfChainLength(out Block _, chainLength, 1).TestObject; BlockhashProvider provider = new(tree, LimboLogs.Instance); Block current = Build.A.Block.WithParent(headBlock).TestObject; @@ -64,7 +64,7 @@ public void Can_lookup_up_to_256_before_soon_after_fast_sync() const int chainLength = 512; Block genesis = Build.A.Block.Genesis.TestObject; - BlockTree tree = Build.A.BlockTree(genesis).OfHeadersOnly.OfChainLength(out Block headBlock, chainLength).OfChainLength(out Block alternativeHeadBlock, chainLength, 1).TestObject; + BlockTree tree = Build.A.BlockTree(genesis).OfHeadersOnly.OfChainLength(out Block headBlock, chainLength).OfChainLength(out Block _, chainLength, 1).TestObject; BlockhashProvider provider = new(tree, LimboLogs.Instance); Block current = Build.A.Block.WithParent(headBlock).TestObject; @@ -81,7 +81,7 @@ public void Can_lookup_up_to_256_before_some_blocks_after_fast_sync() const int chainLength = 512; Block genesis = Build.A.Block.Genesis.TestObject; - BlockTree tree = Build.A.BlockTree(genesis).OfHeadersOnly.OfChainLength(out Block headBlock, chainLength).OfChainLength(out Block alternativeHeadBlock, chainLength, 1).TestObject; + BlockTree tree = Build.A.BlockTree(genesis).OfHeadersOnly.OfChainLength(out Block headBlock, chainLength).OfChainLength(out Block _, chainLength, 1).TestObject; BlockhashProvider provider = new(tree, LimboLogs.Instance); @@ -104,7 +104,7 @@ public void Can_handle_non_main_chain_in_fast_sync() const int chainLength = 512; Block genesis = Build.A.Block.Genesis.TestObject; - BlockTree tree = Build.A.BlockTree(genesis).OfHeadersOnly.OfChainLength(out Block headBlock, chainLength).OfChainLength(out Block alternativeHeadBlock, chainLength, 1).TestObject; + BlockTree tree = Build.A.BlockTree(genesis).OfHeadersOnly.OfChainLength(out Block headBlock, chainLength).OfChainLength(out Block _, chainLength, 1).TestObject; Block current = Build.A.Block.WithParent(headBlock).TestObject; for (int i = 0; i < 6; i++) { @@ -129,7 +129,7 @@ public void Can_get_parent_hash() BlockTree tree = Build.A.BlockTree(genesis).OfChainLength(chainLength).TestObject; BlockhashProvider provider = new(tree, LimboLogs.Instance); - BlockHeader head = tree.FindHeader(chainLength - 1, BlockTreeLookupOptions.None); + BlockHeader head = tree.FindHeader(chainLength - 1, BlockTreeLookupOptions.None)!; Block current = Build.A.Block.WithParent(head).TestObject; Keccak result = provider.GetBlockhash(current.Header, chainLength - 1); Assert.That(result, Is.EqualTo(head.Hash)); @@ -144,7 +144,7 @@ public void Cannot_ask_for_self() BlockTree tree = Build.A.BlockTree(genesis).OfChainLength(chainLength).TestObject; BlockhashProvider provider = new(tree, LimboLogs.Instance); - BlockHeader head = tree.FindHeader(chainLength - 1, BlockTreeLookupOptions.None); + BlockHeader head = tree.FindHeader(chainLength - 1, BlockTreeLookupOptions.None)!; Block current = Build.A.Block.WithParent(head).TestObject; Keccak result = provider.GetBlockhash(current.Header, chainLength); Assert.Null(result); @@ -159,7 +159,7 @@ public void Cannot_ask_about_future() BlockTree tree = Build.A.BlockTree(genesis).OfChainLength(chainLength).TestObject; BlockhashProvider provider = new(tree, LimboLogs.Instance); - BlockHeader head = tree.FindHeader(chainLength - 1, BlockTreeLookupOptions.None); + BlockHeader head = tree.FindHeader(chainLength - 1, BlockTreeLookupOptions.None)!; Block current = Build.A.Block.WithParent(head).TestObject; Keccak result = provider.GetBlockhash(current.Header, chainLength + 1); Assert.Null(result); @@ -174,10 +174,10 @@ public void Can_lookup_up_to_256_before() BlockTree tree = Build.A.BlockTree(genesis).OfChainLength(chainLength).TestObject; BlockhashProvider provider = new(tree, LimboLogs.Instance); - BlockHeader head = tree.FindHeader(chainLength - 1, BlockTreeLookupOptions.None); + BlockHeader head = tree.FindHeader(chainLength - 1, BlockTreeLookupOptions.None)!; Block current = Build.A.Block.WithParent(head).TestObject; Keccak result = provider.GetBlockhash(current.Header, chainLength - 256); - Assert.That(result, Is.EqualTo(tree.FindHeader(256, BlockTreeLookupOptions.None).Hash)); + Assert.That(result, Is.EqualTo(tree.FindHeader(256, BlockTreeLookupOptions.None)!.Hash)); } [Test, Timeout(Timeout.MaxTestTime)] @@ -189,7 +189,7 @@ public void No_lookup_more_than_256_before() BlockTree tree = Build.A.BlockTree(genesis).OfChainLength(chainLength).TestObject; BlockhashProvider provider = new(tree, LimboLogs.Instance); - BlockHeader head = tree.FindHeader(chainLength - 1, BlockTreeLookupOptions.None); + BlockHeader head = tree.FindHeader(chainLength - 1, BlockTreeLookupOptions.None)!; Block current = Build.A.Block.WithParent(head).TestObject; Keccak result = provider.GetBlockhash(current.Header, chainLength - 257); Assert.Null(result); @@ -204,7 +204,7 @@ public void UInt_256_overflow() BlockTree tree = Build.A.BlockTree(genesis).OfChainLength(chainLength).TestObject; BlockhashProvider provider = new(tree, LimboLogs.Instance); - BlockHeader head = tree.FindHeader(chainLength - 1, BlockTreeLookupOptions.None); + BlockHeader head = tree.FindHeader(chainLength - 1, BlockTreeLookupOptions.None)!; Block current = Build.A.Block.WithParent(head).TestObject; Keccak result = provider.GetBlockhash(current.Header, 127); Assert.That(result, Is.EqualTo(head.Hash)); diff --git a/src/Nethermind/Nethermind.Blockchain.Test/Blocks/BlockStoreTests.cs b/src/Nethermind/Nethermind.Blockchain.Test/Blocks/BlockStoreTests.cs index 31de5b80c65..0a6f19373d9 100644 --- a/src/Nethermind/Nethermind.Blockchain.Test/Blocks/BlockStoreTests.cs +++ b/src/Nethermind/Nethermind.Blockchain.Test/Blocks/BlockStoreTests.cs @@ -25,12 +25,12 @@ public void Test_can_insert_get_and_remove_blocks(bool cached) Block block = Build.A.Block.WithNumber(1).TestObject; store.Insert(block); - Block? retrieved = store.Get(block.Hash, cached); + Block? retrieved = store.Get(block.Hash!, cached); retrieved.Should().BeEquivalentTo(block); - store.Delete(block.Hash); + store.Delete(block.Hash!); - store.Get(block.Hash, cached).Should().BeNull(); + store.Get(block.Hash!, cached).Should().BeNull(); } [Test] @@ -55,12 +55,12 @@ public void Test_when_cached_does_not_touch_db_on_next_get() Block block = Build.A.Block.WithNumber(1).TestObject; store.Insert(block); - Block? retrieved = store.Get(block.Hash, true); + Block? retrieved = store.Get(block.Hash!, true); retrieved.Should().BeEquivalentTo(block); db.Clear(); - retrieved = store.Get(block.Hash, true); + retrieved = store.Get(block.Hash!, true); retrieved.Should().BeEquivalentTo(block); } @@ -76,8 +76,7 @@ public void Test_getReceiptRecoveryBlock_produce_same_transaction_as_normal_get( store.Insert(block); - ReceiptRecoveryBlock retrieved = store.GetReceiptRecoveryBlock(block.Hash).Value; - retrieved.Should().NotBeNull(); + ReceiptRecoveryBlock retrieved = store.GetReceiptRecoveryBlock(block.Hash!)!.Value; retrieved.Header.Should().BeEquivalentTo(block.Header); retrieved.TransactionCount.Should().Be(block.Transactions.Length); diff --git a/src/Nethermind/Nethermind.Blockchain.Test/Builders/FilterBuilder.cs b/src/Nethermind/Nethermind.Blockchain.Test/Builders/FilterBuilder.cs index dee1a500774..71270f9b4ca 100644 --- a/src/Nethermind/Nethermind.Blockchain.Test/Builders/FilterBuilder.cs +++ b/src/Nethermind/Nethermind.Blockchain.Test/Builders/FilterBuilder.cs @@ -14,7 +14,7 @@ public class FilterBuilder private static int _id; private BlockParameter _fromBlock = new(BlockParameterType.Latest); private BlockParameter _toBlock = new(BlockParameterType.Latest); - private AddressFilter _address = new((Address)null); + private AddressFilter _address = AddressFilter.AnyAddress; private SequenceTopicsFilter _topicsFilter = new(); private FilterBuilder() @@ -109,6 +109,13 @@ public FilterBuilder ToPendingBlock() return this; } + public FilterBuilder WithAnyAddress() + { + _address = AddressFilter.AnyAddress; + + return this; + } + public FilterBuilder WithAddress(Address address) { _address = new AddressFilter(address); diff --git a/src/Nethermind/Nethermind.Blockchain.Test/Consensus/NullSignerTests.cs b/src/Nethermind/Nethermind.Blockchain.Test/Consensus/NullSignerTests.cs index 299dab8411f..2befce006bb 100644 --- a/src/Nethermind/Nethermind.Blockchain.Test/Consensus/NullSignerTests.cs +++ b/src/Nethermind/Nethermind.Blockchain.Test/Consensus/NullSignerTests.cs @@ -26,8 +26,8 @@ public void Test() public async Task Test_signing() { NullSigner signer = NullSigner.Instance; - await signer.Sign((Transaction)null); - signer.Sign((Keccak)null).Bytes.Should().HaveCount(64); + await signer.Sign((Transaction)null!); + signer.Sign((Keccak)null!).Bytes.Should().HaveCount(64); } } } diff --git a/src/Nethermind/Nethermind.Blockchain.Test/Consensus/OneByOneTxSourceTests.cs b/src/Nethermind/Nethermind.Blockchain.Test/Consensus/OneByOneTxSourceTests.cs index c5506cf3f6f..1ba45176618 100644 --- a/src/Nethermind/Nethermind.Blockchain.Test/Consensus/OneByOneTxSourceTests.cs +++ b/src/Nethermind/Nethermind.Blockchain.Test/Consensus/OneByOneTxSourceTests.cs @@ -17,10 +17,11 @@ public class OneByOneTxSourceTests public void Can_serve_one_by_one() { ITxSource source = Substitute.For(); - source.GetTransactions(null, 0).Returns(new Transaction[5]); + BlockHeader blockHeader = new(); + source.GetTransactions(blockHeader, 0).Returns(new Transaction[5]); ITxSource oneByOne = source.ServeTxsOneByOne(); - oneByOne.GetTransactions(null, 0).Count().Should().Be(1); + oneByOne.GetTransactions(blockHeader, 0).Count().Should().Be(1); } } diff --git a/src/Nethermind/Nethermind.Blockchain.Test/Consensus/SignerTests.cs b/src/Nethermind/Nethermind.Blockchain.Test/Consensus/SignerTests.cs index 24f262985ca..43c3e511ace 100644 --- a/src/Nethermind/Nethermind.Blockchain.Test/Consensus/SignerTests.cs +++ b/src/Nethermind/Nethermind.Blockchain.Test/Consensus/SignerTests.cs @@ -18,26 +18,19 @@ namespace Nethermind.Blockchain.Test.Consensus [TestFixture] public class SignerTests { - [Test, Timeout(Timeout.MaxTestTime)] - public void Throws_when_null_log_manager_in_constructor() - { - Assert.Throws(() => new Signer(1, (PrivateKey)null, null)); - Assert.Throws(() => new Signer(1, (ProtectedPrivateKey)null, null)); - } - [Test, Timeout(Timeout.MaxTestTime)] public void Address_is_zero_when_key_is_null() { // not a great fan of using Address.Zero like a null value but let us show in test // what it does - Signer signer = new(1, (PrivateKey)null, LimboLogs.Instance); + Signer signer = new(1, (PrivateKey?)null, LimboLogs.Instance); signer.Address.Should().Be(Address.Zero); } [Test, Timeout(Timeout.MaxTestTime)] public void Cannot_sign_when_null_key() { - Signer signer = new(1, (PrivateKey)null, LimboLogs.Instance); + Signer signer = new(1, (PrivateKey?)null, LimboLogs.Instance); signer.CanSign.Should().BeFalse(); } @@ -46,7 +39,7 @@ public void Can_set_signer_to_null() { Signer signer = new(1, TestItem.PrivateKeyA, LimboLogs.Instance); signer.CanSign.Should().BeTrue(); - signer.SetSigner((PrivateKey)null); + signer.SetSigner((PrivateKey?)null); signer.CanSign.Should().BeFalse(); } @@ -55,14 +48,14 @@ public void Can_set_signer_to_protected_null() { Signer signer = new(1, TestItem.PrivateKeyA, LimboLogs.Instance); signer.CanSign.Should().BeTrue(); - signer.SetSigner((ProtectedPrivateKey)null); + signer.SetSigner((ProtectedPrivateKey?)null); signer.CanSign.Should().BeFalse(); } [Test, Timeout(Timeout.MaxTestTime)] public void Throws_when_trying_to_sign_with_a_null_key() { - Signer signer = new(1, (PrivateKey)null, LimboLogs.Instance); + Signer signer = new(1, (PrivateKey?)null, LimboLogs.Instance); Assert.Throws(() => signer.Sign(Keccak.Zero)); } diff --git a/src/Nethermind/Nethermind.Blockchain.Test/Consensus/SinglePendingTxSelectorTests.cs b/src/Nethermind/Nethermind.Blockchain.Test/Consensus/SinglePendingTxSelectorTests.cs index a0f34510e79..f8d509b7e5d 100644 --- a/src/Nethermind/Nethermind.Blockchain.Test/Consensus/SinglePendingTxSelectorTests.cs +++ b/src/Nethermind/Nethermind.Blockchain.Test/Consensus/SinglePendingTxSelectorTests.cs @@ -24,12 +24,6 @@ public void To_string_does_not_throw() _ = selector.ToString(); } - [Test, Timeout(Timeout.MaxTestTime)] - public void Throws_on_null_argument() - { - Assert.Throws(() => new SinglePendingTxSelector(null)); - } - [Test, Timeout(Timeout.MaxTestTime)] public void When_no_transactions_returns_empty_list() { diff --git a/src/Nethermind/Nethermind.Blockchain.Test/Filters/FilterManagerTests.cs b/src/Nethermind/Nethermind.Blockchain.Test/Filters/FilterManagerTests.cs index 59f85aa73fa..d4b8342142d 100644 --- a/src/Nethermind/Nethermind.Blockchain.Test/Filters/FilterManagerTests.cs +++ b/src/Nethermind/Nethermind.Blockchain.Test/Filters/FilterManagerTests.cs @@ -9,6 +9,7 @@ using Nethermind.Blockchain.Test.Builders; using Nethermind.Consensus.Processing; using Nethermind.Core; +using Nethermind.Core.Crypto; using Nethermind.Core.Test.Builders; using Nethermind.Facade.Filters; using Nethermind.Logging; @@ -20,11 +21,12 @@ namespace Nethermind.Blockchain.Test.Filters { public class FilterManagerTests { - private IFilterStore _filterStore; - private IBlockProcessor _blockProcessor; - private ITxPool _txPool; - private ILogManager _logManager; - private FilterManager _filterManager; + private IFilterStore _filterStore = null!; + private IBlockProcessor _blockProcessor = null!; + private ITxPool _txPool = null!; + private ILogManager _logManager = null!; + private FilterManager _filterManager = null!; + private int _currentFilterId; [SetUp] @@ -39,36 +41,36 @@ public void Setup() [Test, Timeout(Timeout.MaxTestTime)] public void logs_should_not_be_empty_for_default_filter_parameters() - => LogsShouldNotBeEmpty(filter => { }, receipt => { }); + => LogsShouldNotBeEmpty(_ => { }, _ => { }); [Test, Timeout(Timeout.MaxTestTime)] public void many_logs_should_not_be_empty_for_default_filters_parameters() - => LogsShouldNotBeEmpty(new Action[] { filter => { }, filter => { }, filter => { } }, - new Action[] { receipt => { }, receipt => { }, receipt => { } }); + => LogsShouldNotBeEmpty(new Action[] { _ => { }, _ => { }, _ => { } }, + new Action[] { _ => { }, _ => { }, _ => { } }); [Test, Timeout(Timeout.MaxTestTime)] public void logs_should_not_be_empty_for_from_block_earliest_type() - => LogsShouldNotBeEmpty(filter => filter.FromEarliestBlock(), receipt => { }); + => LogsShouldNotBeEmpty(filter => filter.FromEarliestBlock(), _ => { }); [Test, Timeout(Timeout.MaxTestTime)] public void logs_should_not_be_empty_for_from_block_pending_type() - => LogsShouldNotBeEmpty(filter => filter.FromPendingBlock(), receipt => { }); + => LogsShouldNotBeEmpty(filter => filter.FromPendingBlock(), _ => { }); [Test, Timeout(Timeout.MaxTestTime)] public void logs_should_not_be_empty_for_from_block_latest_type() - => LogsShouldNotBeEmpty(filter => filter.FromLatestBlock(), receipt => { }); + => LogsShouldNotBeEmpty(filter => filter.FromLatestBlock(), _ => { }); [Test, Timeout(Timeout.MaxTestTime)] public void logs_should_not_be_empty_for_to_block_earliest_type() - => LogsShouldNotBeEmpty(filter => filter.ToEarliestBlock(), receipt => { }); + => LogsShouldNotBeEmpty(filter => filter.ToEarliestBlock(), _ => { }); [Test, Timeout(Timeout.MaxTestTime)] public void logs_should_not_be_empty_for_to_block_pending_type() - => LogsShouldNotBeEmpty(filter => filter.ToPendingBlock(), receipt => { }); + => LogsShouldNotBeEmpty(filter => filter.ToPendingBlock(), _ => { }); [Test, Timeout(Timeout.MaxTestTime)] public void logs_should_not_be_empty_for_to_block_latest_type() - => LogsShouldNotBeEmpty(filter => filter.ToLatestBlock(), receipt => { }); + => LogsShouldNotBeEmpty(filter => filter.ToLatestBlock(), _ => { }); [Test, Timeout(Timeout.MaxTestTime)] public void logs_should_not_be_empty_for_from_block_number_in_range() @@ -145,73 +147,60 @@ public void logs_should_be_empty_for_from_block_number_not_in_range_and_to_block [Test, Timeout(Timeout.MaxTestTime)] public void logs_should_not_be_empty_for_existing_address() => LogsShouldNotBeEmpty(filter => filter.WithAddress(TestItem.AddressA), - receipt => receipt.WithLogs(new[] { Build.A.LogEntry.WithAddress(TestItem.AddressA).TestObject })); + receipt => receipt.WithLogs(Build.A.LogEntry.WithAddress(TestItem.AddressA).TestObject)); [Test, Timeout(Timeout.MaxTestTime)] public void logs_should_be_empty_for_non_existing_address() => LogsShouldBeEmpty(filter => filter.WithAddress(TestItem.AddressA), receipt => receipt - .WithLogs(new[] { Build.A.LogEntry.WithAddress(TestItem.AddressB).TestObject })); + .WithLogs(Build.A.LogEntry.WithAddress(TestItem.AddressB).TestObject)); [Test, Timeout(Timeout.MaxTestTime)] public void logs_should_not_be_empty_for_existing_addresses() - => LogsShouldNotBeEmpty(filter => filter.WithAddresses(new[] { TestItem.AddressA, TestItem.AddressB }), + => LogsShouldNotBeEmpty(filter => filter.WithAddresses(TestItem.AddressA, TestItem.AddressB), receipt => receipt - .WithLogs(new[] { Build.A.LogEntry.WithAddress(TestItem.AddressB).TestObject })); + .WithLogs(Build.A.LogEntry.WithAddress(TestItem.AddressB).TestObject)); [Test, Timeout(Timeout.MaxTestTime)] public void logs_should_be_empty_for_non_existing_addresses() - => LogsShouldBeEmpty(filter => filter.WithAddresses(new[] { TestItem.AddressA, TestItem.AddressB }), + => LogsShouldBeEmpty(filter => filter.WithAddresses(TestItem.AddressA, TestItem.AddressB), receipt => receipt - .WithLogs(new[] { Build.A.LogEntry.WithAddress(TestItem.AddressC).TestObject })); + .WithLogs(Build.A.LogEntry.WithAddress(TestItem.AddressC).TestObject)); [Test, Timeout(Timeout.MaxTestTime)] public void logs_should_not_be_empty_for_existing_specific_topic() => LogsShouldNotBeEmpty(filter => filter .WithTopicExpressions(TestTopicExpressions.Specific(TestItem.KeccakA)), receipt => receipt - .WithLogs(new[] - {Build.A.LogEntry.WithTopics(new[] {TestItem.KeccakA, TestItem.KeccakB}).TestObject})); + .WithLogs(Build.A.LogEntry.WithTopics(TestItem.KeccakA, TestItem.KeccakB).TestObject)); [Test, Timeout(Timeout.MaxTestTime)] public void logs_should_be_empty_for_non_existing_specific_topic() => LogsShouldBeEmpty(filter => filter .WithTopicExpressions(TestTopicExpressions.Specific(TestItem.KeccakA)), receipt => receipt - .WithLogs(new[] - {Build.A.LogEntry.WithTopics(new[] {TestItem.KeccakB, TestItem.KeccakC}).TestObject})); + .WithLogs(Build.A.LogEntry.WithTopics(TestItem.KeccakB, TestItem.KeccakC).TestObject)); [Test, Timeout(Timeout.MaxTestTime)] public void logs_should_not_be_empty_for_existing_any_topic() => LogsShouldNotBeEmpty(filter => filter .WithTopicExpressions(TestTopicExpressions.Any), receipt => receipt - .WithLogs(new[] - {Build.A.LogEntry.WithTopics(new[] {TestItem.KeccakA, TestItem.KeccakB}).TestObject})); + .WithLogs(Build.A.LogEntry.WithTopics(TestItem.KeccakA, TestItem.KeccakB).TestObject)); [Test, Timeout(Timeout.MaxTestTime)] public void logs_should_not_be_empty_for_existing_or_topic() => LogsShouldNotBeEmpty(filter => filter - .WithTopicExpressions(TestTopicExpressions.Or(new[] - { - TestTopicExpressions.Specific(TestItem.KeccakB), - TestTopicExpressions.Specific(TestItem.KeccakD) - })), + .WithTopicExpressions(TestTopicExpressions.Or(TestTopicExpressions.Specific(TestItem.KeccakB), TestTopicExpressions.Specific(TestItem.KeccakD))), receipt => receipt - .WithLogs(new[] - {Build.A.LogEntry.WithTopics(new[] {TestItem.KeccakB, TestItem.KeccakC}).TestObject})); + .WithLogs(Build.A.LogEntry.WithTopics(TestItem.KeccakB, TestItem.KeccakC).TestObject)); [Test, Timeout(Timeout.MaxTestTime)] public void logs_should_be_empty_for_non_existing_or_topic() => LogsShouldBeEmpty(filter => filter - .WithTopicExpressions(TestTopicExpressions.Or(new[] - { - TestTopicExpressions.Specific(TestItem.KeccakA), - TestTopicExpressions.Specific(TestItem.KeccakD) - })), + .WithTopicExpressions(TestTopicExpressions.Or(TestTopicExpressions.Specific(TestItem.KeccakA), TestTopicExpressions.Specific(TestItem.KeccakD))), receipt => receipt - .WithLogs(new[] - {Build.A.LogEntry.WithTopics(new[] {TestItem.KeccakB, TestItem.KeccakC}).TestObject})); + .WithLogs(Build.A.LogEntry.WithTopics(TestItem.KeccakB, TestItem.KeccakC).TestObject)); [Test, Timeout(Timeout.MaxTestTime)] public void logs_should_not_be_empty_for_existing_block_and_address_and_topics() @@ -219,56 +208,35 @@ public void logs_should_not_be_empty_for_existing_block_and_address_and_topics() .FromBlock(1L) .ToBlock(10L) .WithAddress(TestItem.AddressA) - .WithTopicExpressions(TestTopicExpressions.Or(new[] - { - TestTopicExpressions.Specific(TestItem.KeccakB), - TestTopicExpressions.Specific(TestItem.KeccakD) - })), + .WithTopicExpressions(TestTopicExpressions.Or(TestTopicExpressions.Specific(TestItem.KeccakB), TestTopicExpressions.Specific(TestItem.KeccakD))), receipt => receipt .WithBlockNumber(6L) - .WithLogs(new[] - { - Build.A.LogEntry.WithAddress(TestItem.AddressA) - .WithTopics(new[] {TestItem.KeccakB, TestItem.KeccakC}).TestObject - })); + .WithLogs(Build.A.LogEntry.WithAddress(TestItem.AddressA) + .WithTopics(TestItem.KeccakB, TestItem.KeccakC).TestObject)); [Test, Timeout(Timeout.MaxTestTime)] public void logs_should_not_be_empty_for_existing_block_and_addresses_and_topics() => LogsShouldNotBeEmpty(filter => filter .FromBlock(1L) .ToBlock(10L) - .WithAddresses(new[] { TestItem.AddressA, TestItem.AddressB }) - .WithTopicExpressions(TestTopicExpressions.Or(new[] - { - TestTopicExpressions.Specific(TestItem.KeccakB), - TestTopicExpressions.Specific(TestItem.KeccakD) - })), + .WithAddresses(TestItem.AddressA, TestItem.AddressB) + .WithTopicExpressions(TestTopicExpressions.Or(TestTopicExpressions.Specific(TestItem.KeccakB), TestTopicExpressions.Specific(TestItem.KeccakD))), receipt => receipt .WithBlockNumber(6L) - .WithLogs(new[] - { - Build.A.LogEntry.WithAddress(TestItem.AddressA) - .WithTopics(new[] {TestItem.KeccakB, TestItem.KeccakC}).TestObject - })); + .WithLogs(Build.A.LogEntry.WithAddress(TestItem.AddressA) + .WithTopics(TestItem.KeccakB, TestItem.KeccakC).TestObject)); [Test, Timeout(Timeout.MaxTestTime)] public void logs_should_be_empty_for_existing_block_and_addresses_and_non_existing_topic() => LogsShouldBeEmpty(filter => filter .FromBlock(1L) .ToBlock(10L) - .WithAddresses(new[] { TestItem.AddressA, TestItem.AddressB }) - .WithTopicExpressions(TestTopicExpressions.Or(new[] - { - TestTopicExpressions.Specific(TestItem.KeccakC), - TestTopicExpressions.Specific(TestItem.KeccakD) - })), + .WithAddresses(TestItem.AddressA, TestItem.AddressB) + .WithTopicExpressions(TestTopicExpressions.Or(TestTopicExpressions.Specific(TestItem.KeccakC), TestTopicExpressions.Specific(TestItem.KeccakD))), receipt => receipt .WithBlockNumber(6L) - .WithLogs(new[] - { - Build.A.LogEntry.WithAddress(TestItem.AddressA) - .WithTopics(new[] {TestItem.KeccakB, TestItem.KeccakC}).TestObject - })); + .WithLogs(Build.A.LogEntry.WithAddress(TestItem.AddressA) + .WithTopics(TestItem.KeccakB, TestItem.KeccakC).TestObject)); private void LogsShouldNotBeEmpty(Action filterBuilder, @@ -291,14 +259,14 @@ private void Assert(IEnumerable> filterBuilders, IEnumerable> receiptBuilders, Action> logsAssertion) { - var filters = new List(); - var receipts = new List(); - foreach (var filterBuilder in filterBuilders) + List filters = new List(); + List receipts = new List(); + foreach (Action filterBuilder in filterBuilders) { filters.Add(BuildFilter(filterBuilder)); } - foreach (var receiptBuilder in receiptBuilders) + foreach (Action receiptBuilder in receiptBuilders) { receipts.Add(BuildReceipt(receiptBuilder)); } @@ -314,8 +282,8 @@ private void Assert(IEnumerable> filterBuilders, _blockProcessor.BlockProcessed += Raise.EventWith(_blockProcessor, new BlockProcessedEventArgs(block, Array.Empty())); - var index = 1; - foreach (var receipt in receipts) + int index = 1; + foreach (TxReceipt receipt in receipts) { _blockProcessor.TransactionProcessed += Raise.EventWith(_blockProcessor, new TxProcessedEventArgs(index, Build.A.Transaction.TestObject, receipt)); @@ -324,20 +292,20 @@ private void Assert(IEnumerable> filterBuilders, NUnit.Framework.Assert.Multiple(() => { - foreach (var filter in filters.OfType()) + foreach (LogFilter filter in filters.OfType()) { - var logs = _filterManager.GetLogs(filter.Id); + FilterLog[] logs = _filterManager.GetLogs(filter.Id); logsAssertion(logs); } - var hashes = _filterManager.GetBlocksHashes(blockFilter.Id); + Keccak[] hashes = _filterManager.GetBlocksHashes(blockFilter.Id); NUnit.Framework.Assert.That(hashes.Length, Is.EqualTo(1)); }); } private LogFilter BuildFilter(Action builder) { - var builderInstance = FilterBuilder.New(ref _currentFilterId); + FilterBuilder builderInstance = FilterBuilder.New(ref _currentFilterId); builder(builderInstance); return builderInstance.Build(); @@ -345,7 +313,7 @@ private LogFilter BuildFilter(Action builder) private static TxReceipt BuildReceipt(Action builder) { - var builderInstance = new ReceiptBuilder(); + ReceiptBuilder builderInstance = new(); builder(builderInstance); return builderInstance.TestObject; diff --git a/src/Nethermind/Nethermind.Blockchain.Test/Filters/LogFilterTests.cs b/src/Nethermind/Nethermind.Blockchain.Test/Filters/LogFilterTests.cs index 8d016bf3f44..d8248aed918 100644 --- a/src/Nethermind/Nethermind.Blockchain.Test/Filters/LogFilterTests.cs +++ b/src/Nethermind/Nethermind.Blockchain.Test/Filters/LogFilterTests.cs @@ -3,6 +3,7 @@ using System; using FluentAssertions; +using Nethermind.Blockchain.Filters; using Nethermind.Blockchain.Test.Builders; using Nethermind.Core; using Nethermind.Core.Crypto; @@ -18,8 +19,8 @@ public class LogFilterTests [Test, Timeout(Timeout.MaxTestTime)] public void any_address_filter_matches_bloom() { - var filter = FilterBuilder.New(ref _filterCounter) - .WithAddress(null) + LogFilter filter = FilterBuilder.New(ref _filterCounter) + .WithAnyAddress() .Build(); filter.Matches(Core.Bloom.Empty).Should().BeTrue(); @@ -28,11 +29,11 @@ public void any_address_filter_matches_bloom() [Test, Timeout(Timeout.MaxTestTime)] public void address_filter_matches_bloom() { - var filter = FilterBuilder.New(ref _filterCounter) + LogFilter filter = FilterBuilder.New(ref _filterCounter) .WithAddress(TestItem.AddressA) .Build(); - var bloom = GetBloom(GetLogEntry(TestItem.AddressA)); + Core.Bloom bloom = GetBloom(GetLogEntry(TestItem.AddressA)); filter.Matches(bloom).Should().BeTrue(); } @@ -40,11 +41,11 @@ public void address_filter_matches_bloom() [Test, Timeout(Timeout.MaxTestTime)] public void addresses_filter_matches_bloom() { - var filter = FilterBuilder.New(ref _filterCounter) + LogFilter filter = FilterBuilder.New(ref _filterCounter) .WithAddresses(TestItem.AddressA, TestItem.AddressB, TestItem.AddressC) .Build(); - var bloom = GetBloom(GetLogEntry(TestItem.AddressB)); + Core.Bloom bloom = GetBloom(GetLogEntry(TestItem.AddressB)); filter.Matches(bloom).Should().BeTrue(); } @@ -52,7 +53,7 @@ public void addresses_filter_matches_bloom() [Test, Timeout(Timeout.MaxTestTime)] public void any_topics_filter_matches_bloom() { - var filter = FilterBuilder.New(ref _filterCounter) + LogFilter filter = FilterBuilder.New(ref _filterCounter) .WithTopicExpressions(TestTopicExpressions.Any) .Build(); @@ -62,11 +63,11 @@ public void any_topics_filter_matches_bloom() [Test, Timeout(Timeout.MaxTestTime)] public void specific_topics_filter_matches_bloom() { - var filter = FilterBuilder.New(ref _filterCounter) + LogFilter filter = FilterBuilder.New(ref _filterCounter) .WithTopicExpressions(TestTopicExpressions.Specific(TestItem.KeccakA)) .Build(); - var bloom = GetBloom(GetLogEntry(TestItem.AddressB, TestItem.KeccakA, TestItem.KeccakB)); + Core.Bloom bloom = GetBloom(GetLogEntry(TestItem.AddressB, TestItem.KeccakA, TestItem.KeccakB)); filter.Matches(bloom).Should().BeTrue(); } @@ -74,11 +75,11 @@ public void specific_topics_filter_matches_bloom() [Test, Timeout(Timeout.MaxTestTime)] public void multiple_specific_topics_filter_matches_bloom() { - var filter = FilterBuilder.New(ref _filterCounter) + LogFilter filter = FilterBuilder.New(ref _filterCounter) .WithTopicExpressions(TestTopicExpressions.Specific(TestItem.KeccakA), TestTopicExpressions.Specific(TestItem.KeccakB)) .Build(); - var bloom = GetBloom(GetLogEntry(TestItem.AddressA, TestItem.KeccakA, TestItem.KeccakB)); + Core.Bloom bloom = GetBloom(GetLogEntry(TestItem.AddressA, TestItem.KeccakA, TestItem.KeccakB)); filter.Matches(bloom).Should().BeTrue(); } @@ -86,11 +87,11 @@ public void multiple_specific_topics_filter_matches_bloom() [Test, Timeout(Timeout.MaxTestTime)] public void or_topics_filter_matches_bloom() { - var filter = FilterBuilder.New(ref _filterCounter) + LogFilter filter = FilterBuilder.New(ref _filterCounter) .WithTopicExpressions(TestTopicExpressions.Or(TestTopicExpressions.Specific(TestItem.KeccakB), TestTopicExpressions.Specific(TestItem.KeccakA))) .Build(); - var bloom = GetBloom(GetLogEntry(TestItem.AddressB, TestItem.KeccakB)); + Core.Bloom bloom = GetBloom(GetLogEntry(TestItem.AddressB, TestItem.KeccakB)); filter.Matches(bloom).Should().BeTrue(); } @@ -98,11 +99,11 @@ public void or_topics_filter_matches_bloom() [Test, Timeout(Timeout.MaxTestTime)] public void complex_topics_filter_matches_bloom() { - var filter = FilterBuilder.New(ref _filterCounter) + LogFilter filter = FilterBuilder.New(ref _filterCounter) .WithTopicExpressions(TestTopicExpressions.Specific(TestItem.KeccakA), TestTopicExpressions.Or(TestTopicExpressions.Specific(TestItem.KeccakB), TestTopicExpressions.Specific(TestItem.KeccakA))) .Build(); - var bloom = GetBloom(GetLogEntry(TestItem.AddressA, TestItem.KeccakA)); + Core.Bloom bloom = GetBloom(GetLogEntry(TestItem.AddressA, TestItem.KeccakA)); filter.Matches(bloom).Should().BeTrue(); } @@ -110,12 +111,12 @@ public void complex_topics_filter_matches_bloom() [Test, Timeout(Timeout.MaxTestTime)] public void complex_filter_matches_bloom() { - var filter = FilterBuilder.New(ref _filterCounter) + LogFilter filter = FilterBuilder.New(ref _filterCounter) .WithTopicExpressions(TestTopicExpressions.Specific(TestItem.KeccakA), TestTopicExpressions.Or(TestTopicExpressions.Specific(TestItem.KeccakB), TestTopicExpressions.Specific(TestItem.KeccakC))) .WithAddress(TestItem.AddressD) .Build(); - var bloom = GetBloom(GetLogEntry(TestItem.AddressD, TestItem.KeccakA, TestItem.KeccakC)); + Core.Bloom bloom = GetBloom(GetLogEntry(TestItem.AddressD, TestItem.KeccakA, TestItem.KeccakC)); filter.Matches(bloom).Should().BeTrue(); } @@ -123,11 +124,11 @@ public void complex_filter_matches_bloom() [Test, Timeout(Timeout.MaxTestTime)] public void address_filter_doesnt_match_bloom() { - var filter = FilterBuilder.New(ref _filterCounter) + LogFilter filter = FilterBuilder.New(ref _filterCounter) .WithAddress(TestItem.AddressA) .Build(); - var bloom = GetBloom(GetLogEntry(TestItem.AddressD), GetLogEntry(TestItem.AddressC)); + Core.Bloom bloom = GetBloom(GetLogEntry(TestItem.AddressD), GetLogEntry(TestItem.AddressC)); filter.Matches(bloom).Should().BeFalse(); } @@ -135,11 +136,11 @@ public void address_filter_doesnt_match_bloom() [Test, Timeout(Timeout.MaxTestTime)] public void addresses_filter_doesnt_match_bloom() { - var filter = FilterBuilder.New(ref _filterCounter) + LogFilter filter = FilterBuilder.New(ref _filterCounter) .WithAddresses(TestItem.AddressA, TestItem.AddressB, TestItem.AddressC) .Build(); - var bloom = GetBloom(GetLogEntry(TestItem.AddressD)); + Core.Bloom bloom = GetBloom(GetLogEntry(TestItem.AddressD)); filter.Matches(bloom).Should().BeFalse(); } @@ -147,11 +148,11 @@ public void addresses_filter_doesnt_match_bloom() [Test, Timeout(Timeout.MaxTestTime)] public void specific_topics_filter_doesnt_match_bloom() { - var filter = FilterBuilder.New(ref _filterCounter) + LogFilter filter = FilterBuilder.New(ref _filterCounter) .WithTopicExpressions(TestTopicExpressions.Specific(TestItem.KeccakA), TestTopicExpressions.Specific(TestItem.KeccakC)) .Build(); - var bloom = GetBloom(GetLogEntry(TestItem.AddressB, TestItem.KeccakA, TestItem.KeccakB)); + Core.Bloom bloom = GetBloom(GetLogEntry(TestItem.AddressB, TestItem.KeccakA, TestItem.KeccakB)); filter.Matches(bloom).Should().BeFalse(); } @@ -159,11 +160,11 @@ public void specific_topics_filter_doesnt_match_bloom() [Test, Timeout(Timeout.MaxTestTime)] public void multiple_specific_topics_filter_doesnt_match_bloom() { - var filter = FilterBuilder.New(ref _filterCounter) + LogFilter filter = FilterBuilder.New(ref _filterCounter) .WithTopicExpressions(TestTopicExpressions.Specific(TestItem.KeccakA), TestTopicExpressions.Specific(TestItem.KeccakB)) .Build(); - var bloom = GetBloom(GetLogEntry(TestItem.AddressB, TestItem.KeccakC)); + Core.Bloom bloom = GetBloom(GetLogEntry(TestItem.AddressB, TestItem.KeccakC)); filter.Matches(bloom).Should().BeFalse(); } @@ -171,11 +172,11 @@ public void multiple_specific_topics_filter_doesnt_match_bloom() [Test, Timeout(Timeout.MaxTestTime)] public void or_topics_filter_doesnt_match_bloom() { - var filter = FilterBuilder.New(ref _filterCounter) + LogFilter filter = FilterBuilder.New(ref _filterCounter) .WithTopicExpressions(TestTopicExpressions.Or(TestTopicExpressions.Specific(TestItem.KeccakB), TestTopicExpressions.Specific(TestItem.KeccakA))) .Build(); - var bloom = GetBloom(GetLogEntry(TestItem.AddressB, TestItem.KeccakC)); + Core.Bloom bloom = GetBloom(GetLogEntry(TestItem.AddressB, TestItem.KeccakC)); filter.Matches(bloom).Should().BeFalse(); } @@ -183,11 +184,11 @@ public void or_topics_filter_doesnt_match_bloom() [Test, Timeout(Timeout.MaxTestTime)] public void complex_topics_filter_doesnt_match_bloom() { - var filter = FilterBuilder.New(ref _filterCounter) + LogFilter filter = FilterBuilder.New(ref _filterCounter) .WithTopicExpressions(TestTopicExpressions.Specific(TestItem.KeccakA), TestTopicExpressions.Or(TestTopicExpressions.Specific(TestItem.KeccakB), TestTopicExpressions.Specific(TestItem.KeccakA))) .Build(); - var bloom = GetBloom(GetLogEntry(TestItem.AddressA, TestItem.KeccakC)); + Core.Bloom bloom = GetBloom(GetLogEntry(TestItem.AddressA, TestItem.KeccakC)); filter.Matches(bloom).Should().BeFalse(); } @@ -195,19 +196,19 @@ public void complex_topics_filter_doesnt_match_bloom() [Test, Timeout(Timeout.MaxTestTime)] public void complex_filter_doesnt_match_bloom() { - var filter = FilterBuilder.New(ref _filterCounter) + LogFilter filter = FilterBuilder.New(ref _filterCounter) .WithTopicExpressions(TestTopicExpressions.Specific(TestItem.KeccakA), TestTopicExpressions.Or(TestTopicExpressions.Specific(TestItem.KeccakB), TestTopicExpressions.Specific(TestItem.KeccakC))) .WithAddress(TestItem.AddressD) .Build(); - var bloom = GetBloom(GetLogEntry(TestItem.AddressA, TestItem.KeccakA, TestItem.KeccakD)); + Core.Bloom bloom = GetBloom(GetLogEntry(TestItem.AddressA, TestItem.KeccakA, TestItem.KeccakD)); filter.Matches(bloom).Should().BeFalse(); } private Core.Bloom GetBloom(params LogEntry[] logEntries) { - var bloom = new Core.Bloom(); + Core.Bloom bloom = new Core.Bloom(); bloom.Add(logEntries); return bloom; } diff --git a/src/Nethermind/Nethermind.Blockchain.Test/Find/LogFinderTests.cs b/src/Nethermind/Nethermind.Blockchain.Test/Find/LogFinderTests.cs index 5e00415a99e..76edfd90ec5 100644 --- a/src/Nethermind/Nethermind.Blockchain.Test/Find/LogFinderTests.cs +++ b/src/Nethermind/Nethermind.Blockchain.Test/Find/LogFinderTests.cs @@ -344,9 +344,9 @@ private void StoreTreeBlooms(bool withBloomDb) { if (withBloomDb) { - for (int i = 0; i <= _blockTree.Head.Number; i++) + for (int i = 0; i <= _blockTree.Head!.Number; i++) { - _bloomStorage.Store(i, _blockTree.FindHeader(i).Bloom); + _bloomStorage.Store(i, _blockTree.FindHeader(i)!.Bloom!); } } } diff --git a/src/Nethermind/Nethermind.Blockchain.Test/FullPruning/CopyTreeVisitorTests.cs b/src/Nethermind/Nethermind.Blockchain.Test/FullPruning/CopyTreeVisitorTests.cs index 233dcb34040..7150f0fbabb 100644 --- a/src/Nethermind/Nethermind.Blockchain.Test/FullPruning/CopyTreeVisitorTests.cs +++ b/src/Nethermind/Nethermind.Blockchain.Test/FullPruning/CopyTreeVisitorTests.cs @@ -41,7 +41,7 @@ public void copies_state_between_dbs(int fullPruningMemoryBudgetMb, int maxDegre }; IPruningContext ctx = StartPruning(trieDb, clonedDb); - CopyDb(ctx, trieDb, clonedDb, visitingOptions, writeFlags: WriteFlags.LowPriority); + CopyDb(ctx, trieDb, visitingOptions, writeFlags: WriteFlags.LowPriority); List keys = trieDb.Keys.ToList(); List values = trieDb.Values.ToList(); @@ -61,16 +61,16 @@ public async Task cancel_coping_state_between_dbs() MemDb trieDb = new(); MemDb clonedDb = new(); IPruningContext pruningContext = StartPruning(trieDb, clonedDb); - Task task = Task.Run(() => CopyDb(pruningContext, trieDb, clonedDb)); + Task task = Task.Run(() => CopyDb(pruningContext, trieDb)); - pruningContext?.CancellationTokenSource.Cancel(); + pruningContext.CancellationTokenSource.Cancel(); await task; clonedDb.Count.Should().BeLessThan(trieDb.Count); } - private static IPruningContext CopyDb(IPruningContext pruningContext, MemDb trieDb, MemDb clonedDb, VisitingOptions visitingOptions = null, WriteFlags writeFlags = WriteFlags.None) + private static IPruningContext CopyDb(IPruningContext pruningContext, MemDb trieDb, VisitingOptions? visitingOptions = null, WriteFlags writeFlags = WriteFlags.None) { LimboLogs logManager = LimboLogs.Instance; PatriciaTree trie = Build.A.Trie(trieDb).WithAccountsByIndex(0, 100).TestObject; diff --git a/src/Nethermind/Nethermind.Blockchain.Test/FullPruning/FullPruningDiskTest.cs b/src/Nethermind/Nethermind.Blockchain.Test/FullPruning/FullPruningDiskTest.cs index 8e3e3f28453..999a0c9030f 100644 --- a/src/Nethermind/Nethermind.Blockchain.Test/FullPruning/FullPruningDiskTest.cs +++ b/src/Nethermind/Nethermind.Blockchain.Test/FullPruning/FullPruningDiskTest.cs @@ -33,10 +33,10 @@ public class FullPruningDiskTest { public class PruningTestBlockchain : TestBlockchain { - public IFullPruningDb PruningDb { get; private set; } + public IFullPruningDb PruningDb { get; private set; } = null!; public TempPath TempDirectory { get; } public IPruningTrigger PruningTrigger { get; } = Substitute.For(); - public FullTestPruner FullPruner { get; private set; } + public FullTestPruner FullPruner { get; private set; } = null!; public IPruningConfig PruningConfig { get; set; } = new PruningConfig(); public IDriveInfo DriveInfo { get; set; } = Substitute.For(); public IChainEstimations _chainEstimations = Substitute.For(); @@ -49,7 +49,7 @@ public PruningTestBlockchain() protected override async Task Build(ISpecProvider? specProvider = null, UInt256? initialValues = null, bool addBlockOnStart = true) { - TestBlockchain chain = await base.Build(specProvider, initialValues); + TestBlockchain chain = await base.Build(specProvider, initialValues, addBlockOnStart); PruningDb = (IFullPruningDb)DbProvider.StateDb; DriveInfo.AvailableFreeSpace.Returns(long.MaxValue); _chainEstimations.StateSize.Returns((long?)null); @@ -74,7 +74,7 @@ public override void Dispose() protected override Task AddBlocksOnStart() => Task.CompletedTask; - public static async Task Create(IPruningConfig pruningConfig = null) + public static async Task Create(IPruningConfig? pruningConfig = null) { PruningTestBlockchain chain = new() { PruningConfig = pruningConfig ?? new PruningConfig() }; await chain.Build(); diff --git a/src/Nethermind/Nethermind.Blockchain.Test/Nethermind.Blockchain.Test.csproj b/src/Nethermind/Nethermind.Blockchain.Test/Nethermind.Blockchain.Test.csproj index e9b719ed235..71c02ad2856 100644 --- a/src/Nethermind/Nethermind.Blockchain.Test/Nethermind.Blockchain.Test.csproj +++ b/src/Nethermind/Nethermind.Blockchain.Test/Nethermind.Blockchain.Test.csproj @@ -4,9 +4,7 @@ false latest enable - - - + true diff --git a/src/Nethermind/Nethermind.Blockchain.Test/Producers/BlockProducerBaseTests.BaseFee.cs b/src/Nethermind/Nethermind.Blockchain.Test/Producers/BlockProducerBaseTests.BaseFee.cs index a3b762a502a..4e66e5bd708 100644 --- a/src/Nethermind/Nethermind.Blockchain.Test/Producers/BlockProducerBaseTests.BaseFee.cs +++ b/src/Nethermind/Nethermind.Blockchain.Test/Producers/BlockProducerBaseTests.BaseFee.cs @@ -21,20 +21,22 @@ public partial class BlockProducerBaseTests { public static class BadContract { - public static readonly AbiSignature Divide = new("divide"); // divide + public static AbiSignature Divide { get; } = new("divide"); // divide } public static partial class BaseFeeTestScenario { public partial class ScenarioBuilder { - private Address _address = TestItem.Addresses[0]; - private Address _contractAddress; - private IAbiEncoder _abiEncoder = new AbiEncoder(); + private readonly Address _address = TestItem.Addresses[0]; + private readonly IAbiEncoder _abiEncoder = new AbiEncoder(); + + private Address _contractAddress = null!; + private TestRpcBlockchain _testRpcBlockchain = null!; + private long _eip1559TransitionBlock; private bool _eip1559Enabled; - private TestRpcBlockchain _testRpcBlockchain; - private Task _antecedent; + private Task? _antecedent; private UInt256 _currentNonce = 1; public ScenarioBuilder WithEip1559TransitionBlock(long transitionBlock) @@ -81,12 +83,14 @@ private async Task DeployContractAsync() await ExecuteAntecedentIfNeeded(); _contractAddress = ContractAddress.From(_address, 0L); byte[] bytecode = await GetContractBytecode("BadContract"); - Transaction tx = new(); - tx.Value = 0; - tx.Data = bytecode; - tx.GasLimit = 1000000; - tx.GasPrice = 20.GWei(); - tx.SenderAddress = _address; + Transaction tx = new() + { + Value = 0, + Data = bytecode, + GasLimit = 1000000, + GasPrice = 20.GWei(), + SenderAddress = _address, + }; await _testRpcBlockchain.TxSender.SendTransaction(tx, TxHandlingOptions.ManagedNonce | TxHandlingOptions.PersistentBroadcast); return this; } @@ -154,13 +158,13 @@ private async Task BlocksBeforeTransitionShouldHaveZeroBaseFeeA { await ExecuteAntecedentIfNeeded(); IBlockTree blockTree = _testRpcBlockchain.BlockTree; - Block startingBlock = blockTree.Head; - Assert.That(startingBlock!.Header.BaseFeePerGas, Is.EqualTo(UInt256.Zero)); + Block startingBlock = blockTree.Head!; + Assert.That(startingBlock.Header.BaseFeePerGas, Is.EqualTo(UInt256.Zero)); for (long i = startingBlock.Number; i < _eip1559TransitionBlock - 1; ++i) { await _testRpcBlockchain.AddBlock(); - Block currentBlock = blockTree.Head; - Assert.That(currentBlock!.Header.BaseFeePerGas, Is.EqualTo(UInt256.Zero)); + Block currentBlock = blockTree.Head!; + Assert.That(currentBlock.Header.BaseFeePerGas, Is.EqualTo(UInt256.Zero)); } return this; @@ -172,8 +176,8 @@ private async Task AssertNewBlockAsync(UInt256 expectedBaseFee, await ExecuteAntecedentIfNeeded(); await _testRpcBlockchain.AddBlock(transactions); IBlockTree blockTree = _testRpcBlockchain.BlockTree; - Block headBlock = blockTree.Head; - Assert.That(headBlock!.Header.BaseFeePerGas, Is.EqualTo(expectedBaseFee)); + Block headBlock = blockTree.Head!; + Assert.That(headBlock.Header.BaseFeePerGas, Is.EqualTo(expectedBaseFee)); return this; } @@ -183,10 +187,10 @@ private async Task AssertNewBlockWithDecreasedBaseFeeAsync() await ExecuteAntecedentIfNeeded(); IBlockTree blockTree = _testRpcBlockchain.BlockTree; - Block startingBlock = blockTree.Head; + Block startingBlock = blockTree.Head!; await _testRpcBlockchain.AddBlock(); - Block newBlock = blockTree.Head; - Assert.Less(newBlock!.Header.BaseFeePerGas, startingBlock!.Header.BaseFeePerGas); + Block newBlock = blockTree.Head!; + Assert.Less(newBlock.Header.BaseFeePerGas, startingBlock.Header.BaseFeePerGas); return this; } @@ -196,10 +200,10 @@ private async Task AssertNewBlockWithIncreasedBaseFeeAsync() await ExecuteAntecedentIfNeeded(); IBlockTree blockTree = _testRpcBlockchain.BlockTree; - Block startingBlock = blockTree.Head; + Block startingBlock = blockTree.Head!; await _testRpcBlockchain.AddBlock(); - Block newBlock = blockTree.Head; - Assert.Less(startingBlock!.Header.BaseFeePerGas, newBlock!.Header.BaseFeePerGas); + Block newBlock = blockTree.Head!; + Assert.Less(startingBlock.Header.BaseFeePerGas, newBlock.Header.BaseFeePerGas); return this; } diff --git a/src/Nethermind/Nethermind.Blockchain.Test/Producers/BlockProducerBaseTests.FeeCollector.cs b/src/Nethermind/Nethermind.Blockchain.Test/Producers/BlockProducerBaseTests.FeeCollector.cs index 742d3644a36..acd93014c43 100644 --- a/src/Nethermind/Nethermind.Blockchain.Test/Producers/BlockProducerBaseTests.FeeCollector.cs +++ b/src/Nethermind/Nethermind.Blockchain.Test/Producers/BlockProducerBaseTests.FeeCollector.cs @@ -17,7 +17,7 @@ public static partial class BaseFeeTestScenario { public partial class ScenarioBuilder { - private Address _eip1559FeeCollector; + private Address _eip1559FeeCollector = null!; public ScenarioBuilder WithEip1559FeeCollector(Address address) { @@ -34,10 +34,6 @@ public ScenarioBuilder AssertNewBlockFeeCollected(UInt256 expectedFeeCollected, private async Task AssertNewBlockFeeCollectedAsync(UInt256 expectedFeeCollected, params Transaction[] transactions) { await ExecuteAntecedentIfNeeded(); - if (_eip1559FeeCollector is null) - { - Assert.Fail($"{nameof(IReleaseSpec.Eip1559FeeCollector)} not set"); - } UInt256 balanceBefore = _testRpcBlockchain.State.GetBalance(_eip1559FeeCollector); await _testRpcBlockchain.AddBlock(transactions); UInt256 balanceAfter = _testRpcBlockchain.State.GetBalance(_eip1559FeeCollector); diff --git a/src/Nethermind/Nethermind.Blockchain.Test/Producers/BuildBlocksOnlyWhenNotProcessingTests.cs b/src/Nethermind/Nethermind.Blockchain.Test/Producers/BuildBlocksOnlyWhenNotProcessingTests.cs index eb6707f5f68..a3574121765 100644 --- a/src/Nethermind/Nethermind.Blockchain.Test/Producers/BuildBlocksOnlyWhenNotProcessingTests.cs +++ b/src/Nethermind/Nethermind.Blockchain.Test/Producers/BuildBlocksOnlyWhenNotProcessingTests.cs @@ -23,7 +23,7 @@ public async Task should_trigger_block_production_on_empty_queue() { Context context = new(); context.BlockProcessingQueue.IsEmpty.Returns(true); - Block block = await context.MainBlockProductionTrigger.BuildBlock(); + Block block = (await context.MainBlockProductionTrigger.BuildBlock())!; block.Should().Be(context.DefaultBlock); context.TriggeredCount.Should().Be(1); } @@ -50,7 +50,7 @@ public async Task should_cancel_triggering_block_production() Context context = new(); context.BlockProcessingQueue.IsEmpty.Returns(false); using CancellationTokenSource cancellationTokenSource = new(); - Task buildTask = context.MainBlockProductionTrigger.BuildBlock(cancellationToken: cancellationTokenSource.Token); + Task buildTask = context.MainBlockProductionTrigger.BuildBlock(cancellationToken: cancellationTokenSource.Token); await Task.Delay(BuildBlocksOnlyWhenNotProcessing.ChainNotYetProcessedMillisecondsDelay * 2); buildTask.IsCanceled.Should().BeFalse(); diff --git a/src/Nethermind/Nethermind.Blockchain.Test/Producers/DevBlockproducerTests.cs b/src/Nethermind/Nethermind.Blockchain.Test/Producers/DevBlockproducerTests.cs index 95d2a5d3ddc..d4167162e52 100644 --- a/src/Nethermind/Nethermind.Blockchain.Test/Producers/DevBlockproducerTests.cs +++ b/src/Nethermind/Nethermind.Blockchain.Test/Producers/DevBlockproducerTests.cs @@ -98,18 +98,18 @@ public void Test() blockchainProcessor.Start(); devBlockProducer.Start(); - ProducedBlockSuggester suggester = new ProducedBlockSuggester(blockTree, devBlockProducer); + ProducedBlockSuggester _ = new ProducedBlockSuggester(blockTree, devBlockProducer); AutoResetEvent autoResetEvent = new(false); - blockTree.NewHeadBlock += (s, e) => autoResetEvent.Set(); + blockTree.NewHeadBlock += (_, _) => autoResetEvent.Set(); blockTree.SuggestBlock(Build.A.Block.Genesis.TestObject); autoResetEvent.WaitOne(1000).Should().BeTrue("genesis"); trigger.BuildBlock(); autoResetEvent.WaitOne(1000).Should().BeTrue("1"); - blockTree.Head.Number.Should().Be(1); + blockTree.Head!.Number.Should().Be(1); } } } diff --git a/src/Nethermind/Nethermind.Blockchain.Test/Proofs/ReceiptTrieTests.cs b/src/Nethermind/Nethermind.Blockchain.Test/Proofs/ReceiptTrieTests.cs index 212622a735a..d43496eb342 100644 --- a/src/Nethermind/Nethermind.Blockchain.Test/Proofs/ReceiptTrieTests.cs +++ b/src/Nethermind/Nethermind.Blockchain.Test/Proofs/ReceiptTrieTests.cs @@ -11,6 +11,8 @@ using Nethermind.Specs; using Nethermind.State.Proofs; using Nethermind.Trie; +using Nethermind.Trie.Pruning; +using NSubstitute; using NUnit.Framework; namespace Nethermind.Blockchain.Test.Proofs @@ -49,7 +51,7 @@ public void Can_collect_proof_with_branch() private static void VerifyProof(byte[][] proof, Keccak receiptRoot) { TrieNode node = new(NodeType.Unknown, proof.Last()); - node.ResolveNode(null); + node.ResolveNode(Substitute.For()); TxReceipt receipt = new ReceiptMessageDecoder().Decode(node.Value.AsRlpStream()); Assert.NotNull(receipt.Bloom); diff --git a/src/Nethermind/Nethermind.Blockchain.Test/Receipts/PersistentReceiptStorageTests.cs b/src/Nethermind/Nethermind.Blockchain.Test/Receipts/PersistentReceiptStorageTests.cs index 4c89598465e..991a0f577dc 100644 --- a/src/Nethermind/Nethermind.Blockchain.Test/Receipts/PersistentReceiptStorageTests.cs +++ b/src/Nethermind/Nethermind.Blockchain.Test/Receipts/PersistentReceiptStorageTests.cs @@ -2,6 +2,7 @@ // SPDX-License-Identifier: LGPL-3.0-only using System; +using System.Collections.Generic; using System.Linq; using System.Threading; using FluentAssertions; @@ -18,6 +19,7 @@ using Nethermind.Serialization.Rlp; using Nethermind.Specs; using NSubstitute; +using NSubstitute.Core; using NUnit.Framework; namespace Nethermind.Blockchain.Test.Receipts @@ -28,13 +30,13 @@ namespace Nethermind.Blockchain.Test.Receipts public class PersistentReceiptStorageTests { private TestMemColumnsDb _receiptsDb = null!; - private ReceiptsRecovery _receiptsRecovery; - private IBlockTree _blockTree; - private IBlockStore _blockStore; + private ReceiptsRecovery _receiptsRecovery = null!; + private IBlockTree _blockTree = null!; + private IBlockStore _blockStore = null!; private readonly bool _useCompactReceipts; - private ReceiptConfig _receiptConfig; - private PersistentReceiptStorage _storage; - private ReceiptArrayStorageDecoder _decoder; + private ReceiptConfig _receiptConfig = null!; + private PersistentReceiptStorage _storage = null!; + private ReceiptArrayStorageDecoder _decoder = null!; public PersistentReceiptStorageTests(bool useCompactReceipts) { @@ -80,7 +82,7 @@ public void Returns_null_for_missing_tx() [Test, Timeout(Timeout.MaxTestTime)] public void ReceiptsIterator_doesnt_throw_on_empty_span() { - _storage.TryGetReceiptsIterator(1, Keccak.Zero, out var iterator); + _storage.TryGetReceiptsIterator(1, Keccak.Zero, out ReceiptsIterator iterator); iterator.TryGetNext(out _).Should().BeFalse(); } @@ -88,7 +90,7 @@ public void ReceiptsIterator_doesnt_throw_on_empty_span() public void ReceiptsIterator_doesnt_throw_on_null() { _receiptsDb.GetColumnDb(ReceiptsColumns.Blocks).Set(Keccak.Zero, null!); - _storage.TryGetReceiptsIterator(1, Keccak.Zero, out var iterator); + _storage.TryGetReceiptsIterator(1, Keccak.Zero, out ReceiptsIterator iterator); iterator.TryGetNext(out _).Should().BeFalse(); } @@ -111,7 +113,7 @@ public void Adds_and_retrieves_receipts_for_block() [Test] public void Adds_should_prefix_key_with_blockNumber() { - var (block, receipts) = InsertBlock(); + (Block block, _) = InsertBlock(); Span blockNumPrefixed = stackalloc byte[40]; block.Number.ToBigEndianByteArray().CopyTo(blockNumPrefixed); // TODO: We don't need to create an array here... @@ -123,10 +125,10 @@ public void Adds_should_prefix_key_with_blockNumber() [Test] public void Adds_should_attempt_hash_key_first_if_inserted_with_hashkey() { - var (block, receipts) = PrepareBlock(); + (Block block, TxReceipt[] receipts) = PrepareBlock(); using NettyRlpStream rlpStream = _decoder.EncodeToNewNettyStream(receipts, RlpBehaviors.Storage); - _receiptsDb.GetColumnDb(ReceiptsColumns.Blocks)[block.Hash.Bytes] = rlpStream.AsSpan().ToArray(); + _receiptsDb.GetColumnDb(ReceiptsColumns.Blocks)[block.Hash!.Bytes] = rlpStream.AsSpan().ToArray(); CreateStorage(); _storage.Get(block); @@ -136,14 +138,14 @@ public void Adds_should_attempt_hash_key_first_if_inserted_with_hashkey() block.Hash!.Bytes.CopyTo(blockNumPrefixed[8..]); TestMemDb blocksDb = (TestMemDb)_receiptsDb.GetColumnDb(ReceiptsColumns.Blocks); - blocksDb.KeyWasRead(blockNumPrefixed.ToArray(), 0); - blocksDb.KeyWasRead(block.Hash.BytesToArray(), 1); + blocksDb.KeyWasRead(blockNumPrefixed.ToArray(), times: 0); + blocksDb.KeyWasRead(block.Hash.BytesToArray(), times: 1); } [Test] public void Should_be_able_to_get_block_with_hash_address() { - var (block, receipts) = PrepareBlock(); + (Block block, TxReceipt[] receipts) = PrepareBlock(); Span blockNumPrefixed = stackalloc byte[40]; block.Number.ToBigEndianByteArray().CopyTo(blockNumPrefixed); // TODO: We don't need to create an array here... @@ -158,16 +160,16 @@ public void Should_be_able_to_get_block_with_hash_address() [Test, Timeout(Timeout.MaxTestTime)] public void Should_not_cache_empty_non_processed_blocks() { - var block = Build.A.Block + Block block = Build.A.Block .WithTransactions(Build.A.Transaction.SignedAndResolved().TestObject) .WithReceiptsRoot(TestItem.KeccakA) .TestObject; - var emptyReceipts = Array.Empty(); + TxReceipt[] emptyReceipts = Array.Empty(); _storage.Get(block).Should().BeEquivalentTo(emptyReceipts); // can be from cache: _storage.Get(block).Should().BeEquivalentTo(emptyReceipts); - var (_, receipts) = InsertBlock(block); + (_, TxReceipt[] receipts) = InsertBlock(block); // before should not be cached _storage.Get(block).Should().BeEquivalentTo(receipts); } @@ -178,7 +180,7 @@ public void Adds_and_retrieves_receipts_for_block_with_iterator_from_cache_after var (block, receipts) = InsertBlock(); _storage.TryGetReceiptsIterator(0, block.Hash!, out ReceiptsIterator iterator).Should().BeTrue(); - iterator.TryGetNext(out var receiptStructRef).Should().BeTrue(); + iterator.TryGetNext(out TxReceiptStructRef receiptStructRef).Should().BeTrue(); receiptStructRef.LogsRlp.ToArray().Should().BeEmpty(); receiptStructRef.Logs.Should().BeEquivalentTo(receipts.First().Logs); iterator.TryGetNext(out receiptStructRef).Should().BeFalse(); @@ -262,16 +264,17 @@ public void EnsureCanonical_should_change_tx_blockhash( } [Test] - public void EnsureCanonical_should_use_blocknumber_if_finalized() + public void EnsureCanonical_should_use_blockNumber_if_finalized() { (Block block, TxReceipt[] receipts) = InsertBlock(isFinalized: true); + Span txHashBytes = receipts[0].TxHash!.Bytes; if (_receiptConfig.CompactTxIndex) { - _receiptsDb.GetColumnDb(ReceiptsColumns.Transactions)[receipts[0].TxHash.Bytes].Should().BeEquivalentTo(Rlp.Encode(block.Number).Bytes); + _receiptsDb.GetColumnDb(ReceiptsColumns.Transactions)[txHashBytes].Should().BeEquivalentTo(Rlp.Encode(block.Number).Bytes); } else { - _receiptsDb.GetColumnDb(ReceiptsColumns.Transactions)[receipts[0].TxHash.Bytes].Should().NotBeNull(); + _receiptsDb.GetColumnDb(ReceiptsColumns.Transactions)[txHashBytes].Should().NotBeNull(); } } @@ -283,11 +286,10 @@ public void When_TxLookupLimitIs_NegativeOne_DoNotIndexTxHash() (Block block, TxReceipt[] receipts) = InsertBlock(isFinalized: true); _blockTree.BlockAddedToMain += Raise.EventWith(new BlockReplacementEventArgs(block)); Thread.Sleep(100); - _receiptsDb.GetColumnDb(ReceiptsColumns.Transactions)[receipts[0].TxHash.Bytes].Should().BeNull(); + _receiptsDb.GetColumnDb(ReceiptsColumns.Transactions)[receipts[0].TxHash!.Bytes].Should().BeNull(); } [Test] - [Ignore("Needs to be fixed, details https://github.com/NethermindEth/nethermind/pull/5621")] public void Should_not_index_tx_hash_if_blockNumber_is_negative() { _receiptConfig.TxLookupLimit = 10; @@ -295,7 +297,7 @@ public void Should_not_index_tx_hash_if_blockNumber_is_negative() _blockTree.BlockAddedToMain += Raise.EventWith(new BlockReplacementEventArgs(Build.A.Block.WithNumber(1).TestObject)); Thread.Sleep(100); - var calls = _blockTree.ReceivedCalls() + IEnumerable calls = _blockTree.ReceivedCalls() .Where(call => !call.GetMethodInfo().Name.EndsWith(nameof(_blockTree.BlockAddedToMain))); calls.Should().BeEmpty(); } @@ -308,7 +310,7 @@ public void When_HeadBlockIsFarAhead_DoNotIndexTxHash() (Block block, TxReceipt[] receipts) = InsertBlock(isFinalized: true, headNumber: 1001); _blockTree.BlockAddedToMain += Raise.EventWith(new BlockReplacementEventArgs(block)); Thread.Sleep(100); - _receiptsDb.GetColumnDb(ReceiptsColumns.Transactions)[receipts[0].TxHash.Bytes].Should().BeNull(); + _receiptsDb.GetColumnDb(ReceiptsColumns.Transactions)[receipts[0].TxHash!.Bytes].Should().BeNull(); } [Test] @@ -319,11 +321,11 @@ public void When_NewHeadBlock_Remove_TxIndex_OfRemovedBlock() if (_receiptConfig.CompactTxIndex) { - _receiptsDb.GetColumnDb(ReceiptsColumns.Transactions)[receipts[0].TxHash.Bytes].Should().BeEquivalentTo(Rlp.Encode(block.Number).Bytes); + _receiptsDb.GetColumnDb(ReceiptsColumns.Transactions)[receipts[0].TxHash!.Bytes].Should().BeEquivalentTo(Rlp.Encode(block.Number).Bytes); } else { - _receiptsDb.GetColumnDb(ReceiptsColumns.Transactions)[receipts[0].TxHash.Bytes].Should().NotBeNull(); + _receiptsDb.GetColumnDb(ReceiptsColumns.Transactions)[receipts[0].TxHash!.Bytes].Should().NotBeNull(); } Block newHead = Build.A.Block.WithNumber(1).TestObject; @@ -331,7 +333,7 @@ public void When_NewHeadBlock_Remove_TxIndex_OfRemovedBlock() _blockTree.BlockAddedToMain += Raise.EventWith(new BlockReplacementEventArgs(newHead, block)); Assert.That( - () => _receiptsDb.GetColumnDb(ReceiptsColumns.Transactions)[receipts[0].TxHash.Bytes], + () => _receiptsDb.GetColumnDb(ReceiptsColumns.Transactions)[receipts[0].TxHash!.Bytes], Is.Null.After(1000, 100) ); } @@ -343,13 +345,14 @@ public void When_NewHeadBlock_ClearOldTxIndex() CreateStorage(); (Block block, TxReceipt[] receipts) = InsertBlock(); + Span txHashBytes = receipts[0].TxHash!.Bytes; if (_receiptConfig.CompactTxIndex) { - _receiptsDb.GetColumnDb(ReceiptsColumns.Transactions)[receipts[0].TxHash.Bytes].Should().BeEquivalentTo(Rlp.Encode(block.Number).Bytes); + _receiptsDb.GetColumnDb(ReceiptsColumns.Transactions)[txHashBytes].Should().BeEquivalentTo(Rlp.Encode(block.Number).Bytes); } else { - _receiptsDb.GetColumnDb(ReceiptsColumns.Transactions)[receipts[0].TxHash.Bytes].Should().NotBeNull(); + _receiptsDb.GetColumnDb(ReceiptsColumns.Transactions)[txHashBytes].Should().NotBeNull(); } Block newHead = Build.A.Block.WithNumber(_receiptConfig.TxLookupLimit.Value + 1).TestObject; @@ -357,7 +360,7 @@ public void When_NewHeadBlock_ClearOldTxIndex() _blockTree.BlockAddedToMain += Raise.EventWith(new BlockReplacementEventArgs(newHead)); Assert.That( - () => _receiptsDb.GetColumnDb(ReceiptsColumns.Transactions)[receipts[0].TxHash.Bytes], + () => _receiptsDb.GetColumnDb(ReceiptsColumns.Transactions)[receipts[0].TxHash!.Bytes], Is.Null.After(1000, 100) ); } @@ -370,7 +373,7 @@ public void When_NewHeadBlock_ClearOldTxIndex() .WithReceiptsRoot(TestItem.KeccakA) .TestObject; - _blockTree.FindBlock(block.Hash).Returns(block); + _blockTree.FindBlock(block.Hash!).Returns(block); _blockTree.FindBlock(block.Number).Returns(block); _blockTree.FindHeader(block.Number).Returns(block.Header); _blockTree.FindBlockHash(block.Number).Returns(block.Hash); @@ -389,7 +392,7 @@ public void When_NewHeadBlock_ClearOldTxIndex() .TestObject; _blockTree.FindBestSuggestedHeader().Returns(farHead); } - var receipts = new[] { Build.A.Receipt.WithCalculatedBloom().TestObject }; + TxReceipt[] receipts = { Build.A.Receipt.WithCalculatedBloom().TestObject }; return (block, receipts); } diff --git a/src/Nethermind/Nethermind.Blockchain.Test/Receipts/ReceiptsIteratorTests.cs b/src/Nethermind/Nethermind.Blockchain.Test/Receipts/ReceiptsIteratorTests.cs index 1c30fb07ee7..6201e017336 100644 --- a/src/Nethermind/Nethermind.Blockchain.Test/Receipts/ReceiptsIteratorTests.cs +++ b/src/Nethermind/Nethermind.Blockchain.Test/Receipts/ReceiptsIteratorTests.cs @@ -38,15 +38,15 @@ public void SmokeTestWithRecovery() iterator.TryGetNext(out TxReceiptStructRef receipt).Should().BeTrue(); iterator.RecoverIfNeeded(ref receipt); receipt.Sender.Bytes.ToArray().Should().BeEquivalentTo(TestItem.AddressA.Bytes); - receipt.TxHash.Bytes.ToArray().Should().BeEquivalentTo(block.Transactions[0].Hash.BytesToArray()); + receipt.TxHash.Bytes.ToArray().Should().BeEquivalentTo(block.Transactions[0].Hash!.BytesToArray()); iterator.TryGetNext(out receipt).Should().BeTrue(); iterator.RecoverIfNeeded(ref receipt); receipt.Sender.Bytes.ToArray().Should().BeEquivalentTo(TestItem.AddressB.Bytes); - receipt.TxHash.Bytes.ToArray().Should().BeEquivalentTo(block.Transactions[1].Hash.BytesToArray()); + receipt.TxHash.Bytes.ToArray().Should().BeEquivalentTo(block.Transactions[1].Hash!.BytesToArray()); iterator.TryGetNext(out receipt).Should().BeTrue(); iterator.RecoverIfNeeded(ref receipt); receipt.Sender.Bytes.ToArray().Should().BeEquivalentTo(TestItem.AddressC.Bytes); - receipt.TxHash.Bytes.ToArray().Should().BeEquivalentTo(block.Transactions[1].Hash.BytesToArray()); + receipt.TxHash.Bytes.ToArray().Should().BeEquivalentTo(block.Transactions[1].Hash!.BytesToArray()); } [Test] @@ -56,7 +56,7 @@ public void SmokeTestWithDelayedRecovery() .Block .WithTransactions(3, MainnetSpecProvider.Instance) .TestObject; - TxReceipt[] receipts = new[] + TxReceipt[] receipts = { Build.A.Receipt.WithAllFieldsFilled.WithSender(TestItem.AddressA).TestObject, Build.A.Receipt.WithAllFieldsFilled.WithSender(TestItem.AddressB).TestObject, @@ -74,7 +74,7 @@ public void SmokeTestWithDelayedRecovery() iterator.TryGetNext(out receipt).Should().BeTrue(); iterator.RecoverIfNeeded(ref receipt); receipt.Sender.Bytes.ToArray().Should().BeEquivalentTo(TestItem.AddressC.Bytes); - receipt.TxHash.Bytes.ToArray().Should().BeEquivalentTo(block.Transactions[1].Hash.BytesToArray()); + receipt.TxHash.Bytes.ToArray().Should().BeEquivalentTo(block.Transactions[1].Hash!.BytesToArray()); } [Test] @@ -84,7 +84,7 @@ public void SmokeTest() .Block .WithTransactions(3, MainnetSpecProvider.Instance) .TestObject; - TxReceipt[] receipts = new[] + TxReceipt[] receipts = { Build.A.Receipt.WithAllFieldsFilled.WithSender(TestItem.AddressA).TestObject, Build.A.Receipt.WithAllFieldsFilled.WithSender(TestItem.AddressB).TestObject, diff --git a/src/Nethermind/Nethermind.Blockchain.Test/ReorgTests.cs b/src/Nethermind/Nethermind.Blockchain.Test/ReorgTests.cs index 05291777503..159755b7824 100644 --- a/src/Nethermind/Nethermind.Blockchain.Test/ReorgTests.cs +++ b/src/Nethermind/Nethermind.Blockchain.Test/ReorgTests.cs @@ -123,8 +123,8 @@ public void Test() Assert.That(() => _blockTree.Head, Is.EqualTo(block2B).After(10000, 500)); events.Should().HaveCount(6); - events[4].Hash.Should().Be(block1B.Hash); - events[5].Hash.Should().Be(block2B.Hash); + events[4].Hash.Should().Be(block1B.Hash!); + events[5].Hash.Should().Be(block2B.Hash!); } } } diff --git a/src/Nethermind/Nethermind.Blockchain.Test/Services/HealthHintServiceTests.cs b/src/Nethermind/Nethermind.Blockchain.Test/Services/HealthHintServiceTests.cs index 4099cb06d41..e9c3ecc2280 100644 --- a/src/Nethermind/Nethermind.Blockchain.Test/Services/HealthHintServiceTests.cs +++ b/src/Nethermind/Nethermind.Blockchain.Test/Services/HealthHintServiceTests.cs @@ -25,11 +25,9 @@ public void GetBlockProcessorAndProducerIntervalHint_returns_expected_result( public class BlockProcessorIntervalHint { - public ChainSpec ChainSpec { get; set; } - - public ulong? ExpectedProcessingHint { get; set; } - - public ulong? ExpectedProducingHint { get; set; } + public required ChainSpec ChainSpec { get; init; } + public ulong? ExpectedProcessingHint { get; init; } + public ulong? ExpectedProducingHint { get => null; } public override string ToString() => $"SealEngineType: {ChainSpec.SealEngineType}, ExpectedProcessingHint: {ExpectedProcessingHint}, ExpectedProducingHint: {ExpectedProducingHint}"; @@ -39,22 +37,22 @@ public static IEnumerable BlockProcessorIntervalHint { get { - yield return new BlockProcessorIntervalHint() + yield return new BlockProcessorIntervalHint { - ChainSpec = new ChainSpec() { SealEngineType = SealEngineType.NethDev, } + ChainSpec = new ChainSpec { SealEngineType = SealEngineType.NethDev, } }; - yield return new BlockProcessorIntervalHint() + yield return new BlockProcessorIntervalHint { - ChainSpec = new ChainSpec() { SealEngineType = SealEngineType.Ethash }, + ChainSpec = new ChainSpec { SealEngineType = SealEngineType.Ethash }, ExpectedProcessingHint = 180 }; - yield return new BlockProcessorIntervalHint() + yield return new BlockProcessorIntervalHint { - ChainSpec = new ChainSpec() { SealEngineType = "Interval" } + ChainSpec = new ChainSpec { SealEngineType = "Interval" } }; - yield return new BlockProcessorIntervalHint() + yield return new BlockProcessorIntervalHint { - ChainSpec = new ChainSpec() { SealEngineType = SealEngineType.None } + ChainSpec = new ChainSpec { SealEngineType = SealEngineType.None } }; } } diff --git a/src/Nethermind/Nethermind.Blockchain.Test/TransactionSelectorTests.cs b/src/Nethermind/Nethermind.Blockchain.Test/TransactionSelectorTests.cs index eae3b63c686..5281b0a37ce 100644 --- a/src/Nethermind/Nethermind.Blockchain.Test/TransactionSelectorTests.cs +++ b/src/Nethermind/Nethermind.Blockchain.Test/TransactionSelectorTests.cs @@ -180,7 +180,7 @@ public static IEnumerable EnoughShardBlobTransactionsSelectedTestCases expectedSelectedTransactions[1].BlobVersionedHashes = new byte[1][]; expectedSelectedTransactions[1].MaxFeePerBlobGas = 1; enoughTransactionsSelected.ExpectedSelectedTransactions.AddRange( - expectedSelectedTransactions.Where((tx, index) => index != 1)); + expectedSelectedTransactions.Where((_, index) => index != 1)); yield return new TestCaseData(enoughTransactionsSelected).SetName( "Enough shard blob transactions and others selected"); } @@ -196,8 +196,7 @@ public void Proper_transactions_selected(ProperTransactionsSelectedTestCase test MemDb codeDb = new(); TrieStore trieStore = new(stateDb, LimboLogs.Instance); WorldState stateProvider = new(trieStore, codeDb, LimboLogs.Instance); - StateReader stateReader = - new(new TrieStore(stateDb, LimboLogs.Instance), codeDb, LimboLogs.Instance); + StateReader _ = new(new TrieStore(stateDb, LimboLogs.Instance), codeDb, LimboLogs.Instance); ISpecProvider specProvider = Substitute.For(); void SetAccountStates(IEnumerable
missingAddresses) @@ -231,7 +230,7 @@ void SetAccountStates(IEnumerable
missingAddresses) IComparer defaultComparer = transactionComparerProvider.GetDefaultComparer(); IComparer comparer = CompareTxByNonce.Instance.ThenBy(defaultComparer); Dictionary transactions = testCase.Transactions - .Where(t => t?.SenderAddress is not null) + .Where(t => t.SenderAddress is not null) .GroupBy(t => t.SenderAddress) .ToDictionary( g => g.Key!, @@ -270,7 +269,7 @@ public class ProperTransactionsSelectedTestCase public List ExpectedSelectedTransactions { get; } = new(); public UInt256 MinGasPriceForMining { get; set; } = 1; - public IReleaseSpec ReleaseSpec { get; set; } + public required IReleaseSpec ReleaseSpec { get; set; } public UInt256 BaseFee { get; set; } diff --git a/src/Nethermind/Nethermind.Blockchain.Test/Validators/TestSealValidator.cs b/src/Nethermind/Nethermind.Blockchain.Test/Validators/TestSealValidator.cs deleted file mode 100644 index 77f496bafef..00000000000 --- a/src/Nethermind/Nethermind.Blockchain.Test/Validators/TestSealValidator.cs +++ /dev/null @@ -1,45 +0,0 @@ -// SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited -// SPDX-License-Identifier: LGPL-3.0-only - -using System; -using System.Collections.Generic; -using Nethermind.Consensus; -using Nethermind.Consensus.Validators; -using Nethermind.Core; - -namespace Nethermind.Blockchain.Test.Validators -{ - // ReSharper disable once ClassNeverInstantiated.Global - public class TestSealValidator : ISealValidator - { - public static ISealValidator AlwaysValid = Always.Valid; - public static ISealValidator NeverValid = Always.Invalid; - - private readonly Queue _processedValidationResults; - private readonly Queue _suggestedValidationResults; - private bool? _alwaysSameResultForSeal; - private bool? _alwaysSameResultForParams; - - public TestSealValidator(bool validateParamsResult, bool validateSealResult) - { - _alwaysSameResultForParams = validateParamsResult; - _alwaysSameResultForSeal = validateSealResult; - } - - public TestSealValidator(Queue suggestedValidationResults, Queue processedValidationResults) - { - _suggestedValidationResults = suggestedValidationResults ?? throw new ArgumentNullException(nameof(suggestedValidationResults)); - _processedValidationResults = processedValidationResults ?? throw new ArgumentNullException(nameof(processedValidationResults)); - } - - public bool ValidateParams(BlockHeader parent, BlockHeader header, bool isUncle) - { - return _alwaysSameResultForParams ?? _suggestedValidationResults.Dequeue(); - } - - public bool ValidateSeal(BlockHeader header, bool force) - { - return _alwaysSameResultForSeal ?? _processedValidationResults.Dequeue(); - } - } -} diff --git a/src/Nethermind/Nethermind.Blockchain.Test/Validators/UnclesValidatorTests.cs b/src/Nethermind/Nethermind.Blockchain.Test/Validators/UnclesValidatorTests.cs index 31cfc7108e7..f0d01c68da3 100644 --- a/src/Nethermind/Nethermind.Blockchain.Test/Validators/UnclesValidatorTests.cs +++ b/src/Nethermind/Nethermind.Blockchain.Test/Validators/UnclesValidatorTests.cs @@ -19,7 +19,7 @@ public class UnclesValidatorTests private readonly Block _parent; private readonly Block _block; private readonly IBlockTree _blockTree; - private IHeaderValidator _headerValidator; + private IHeaderValidator _headerValidator = null!; private readonly Block _duplicateUncle; @@ -33,7 +33,7 @@ public void Setup() public UnclesValidatorTests() { _blockTree = Build.A.BlockTree().OfChainLength(1).TestObject; - _grandgrandparent = _blockTree.FindBlock(0, BlockTreeLookupOptions.None); + _grandgrandparent = _blockTree.FindBlock(0, BlockTreeLookupOptions.None)!; _grandparent = Build.A.Block.WithParent(_grandgrandparent).TestObject; _duplicateUncle = Build.A.Block.WithParent(_grandgrandparent).TestObject; _parent = Build.A.Block.WithParent(_grandparent).WithUncles(_duplicateUncle).TestObject; diff --git a/src/Nethermind/Nethermind.Blockchain.Test/Visitors/DbBlocksLoaderTests.cs b/src/Nethermind/Nethermind.Blockchain.Test/Visitors/DbBlocksLoaderTests.cs index 417c6fdbc30..d627c93e130 100644 --- a/src/Nethermind/Nethermind.Blockchain.Test/Visitors/DbBlocksLoaderTests.cs +++ b/src/Nethermind/Nethermind.Blockchain.Test/Visitors/DbBlocksLoaderTests.cs @@ -21,7 +21,7 @@ namespace Nethermind.Blockchain.Test.Visitors [TestFixture] public class DbBlocksLoaderTests { - private int _dbLoadTimeout = 5000; + private readonly int _dbLoadTimeout = 5000; [Test, Timeout(Timeout.MaxTestTime)] public async Task Can_load_blocks_from_db() @@ -35,23 +35,23 @@ public async Task Can_load_blocks_from_db() MemDb headersDb = new(); BlockTree testTree = Build.A.BlockTree(genesisBlock).OfChainLength(chainLength).TestObject; - for (int i = 0; i < testTree.Head.Number + 1; i++) + for (int i = 0; i < testTree.Head!.Number + 1; i++) { - Block ithBlock = testTree.FindBlock(i, BlockTreeLookupOptions.None); - blocksDb.Set(ithBlock.Hash, Rlp.Encode(ithBlock).Bytes); + Block ithBlock = testTree.FindBlock(i, BlockTreeLookupOptions.None)!; + blocksDb.Set(ithBlock.Hash!, Rlp.Encode(ithBlock).Bytes); - headersDb.Set(ithBlock.Hash, Rlp.Encode(ithBlock.Header).Bytes); + headersDb.Set(ithBlock.Hash!, Rlp.Encode(ithBlock.Header).Bytes); ChainLevelInfo ithLevel = new( true, - new BlockInfo[] + blockInfos: new[] { - new(ithBlock.Hash, ithBlock.TotalDifficulty.Value) {WasProcessed = true} + new BlockInfo(ithBlock.Hash!, ithBlock.TotalDifficulty!.Value) {WasProcessed = true} }); blockInfosDb.Set(i, Rlp.Encode(ithLevel).Bytes); } - blockInfosDb.Set(Keccak.Zero, genesisBlock.Header.Hash.Bytes); + blockInfosDb.Set(Keccak.Zero, genesisBlock.Header.Hash!.Bytes); headersDb.Set(genesisBlock.Header.Hash, Rlp.Encode(genesisBlock.Header).Bytes); BlockTree blockTree = new( @@ -66,7 +66,7 @@ public async Task Can_load_blocks_from_db() DbBlocksLoader loader = new(blockTree, LimboNoErrorLogger.Instance); await blockTree.Accept(loader, CancellationToken.None); - Assert.That(blockTree.BestSuggestedHeader.Hash, Is.EqualTo(testTree.Head.Hash), $"head {chainLength}"); + Assert.That(blockTree.BestSuggestedHeader!.Hash, Is.EqualTo(testTree.Head.Hash), $"head {chainLength}"); } } @@ -82,22 +82,22 @@ public async Task Can_load_blocks_from_db_odd() MemDb headersDb = new(); BlockTree testTree = Build.A.BlockTree(genesisBlock).OfChainLength(chainLength).TestObject; - for (int i = 0; i < testTree.Head.Number + 1; i++) + for (int i = 0; i < testTree.Head!.Number + 1; i++) { - Block ithBlock = testTree.FindBlock(i, BlockTreeLookupOptions.None); - blocksDb.Set(ithBlock.Hash, Rlp.Encode(ithBlock).Bytes); + Block ithBlock = testTree.FindBlock(i, BlockTreeLookupOptions.None)!; + blocksDb.Set(ithBlock.Hash!, Rlp.Encode(ithBlock).Bytes); - headersDb.Set(ithBlock.Hash, Rlp.Encode(ithBlock.Header).Bytes); + headersDb.Set(ithBlock.Hash!, Rlp.Encode(ithBlock.Header).Bytes); - ChainLevelInfo ithLevel = new(true, new BlockInfo[1] + ChainLevelInfo ithLevel = new(true, blockInfos: new[] { - new(ithBlock.Hash, ithBlock.TotalDifficulty.Value) + new BlockInfo(ithBlock.Hash!, ithBlock.TotalDifficulty!.Value) }); blockInfosDb.Set(i, Rlp.Encode(ithLevel).Bytes); } - blockInfosDb.Set(Keccak.Zero, genesisBlock.Header.Hash.Bytes); + blockInfosDb.Set(Keccak.Zero, genesisBlock.Header.Hash!.Bytes); headersDb.Set(genesisBlock.Header.Hash, Rlp.Encode(genesisBlock.Header).Bytes); BlockTree blockTree = new( @@ -112,7 +112,7 @@ public async Task Can_load_blocks_from_db_odd() DbBlocksLoader loader = new(blockTree, LimboNoErrorLogger.Instance); await blockTree.Accept(loader, CancellationToken.None); - Assert.That(blockTree.BestSuggestedHeader.Hash, Is.EqualTo(testTree.Head.Hash), $"head {chainLength}"); + Assert.That(blockTree.BestSuggestedHeader!.Hash, Is.EqualTo(testTree.Head.Hash), $"head {chainLength}"); } } @@ -162,11 +162,9 @@ public async Task Can_load_from_DB_when_there_is_an_invalid_block_in_DB_and_a_va LimboLogs.Instance); CancellationTokenSource tokenSource = new(); -#pragma warning disable 4014 - Task.Delay(_dbLoadTimeout).ContinueWith(t => tokenSource.Cancel()); -#pragma warning restore 4014 + tokenSource.CancelAfter(_dbLoadTimeout); - tree2.NewBestSuggestedBlock += (sender, args) => + tree2.NewBestSuggestedBlock += (_, args) => { if (args.Block.Hash == block1.Hash) { @@ -182,12 +180,12 @@ public async Task Can_load_from_DB_when_there_is_an_invalid_block_in_DB_and_a_va await tree2.Accept(loader, tokenSource.Token); Assert.That(tree2.BestKnownNumber, Is.EqualTo(3L), "best known"); - tree2.Head.Header.Should().BeEquivalentTo(block3B.Header, options => { return options.Excluding(t => t.MaybeParent); }); + tree2.Head!.Header.Should().BeEquivalentTo(block3B.Header, options => { return options.Excluding(t => t.MaybeParent); }); tree2.BestSuggestedHeader.Should().BeEquivalentTo(block3B.Header, options => { return options.Excluding(t => t.MaybeParent); }); - Assert.IsNull(blocksDb.Get(block1.Hash), "block 1"); - Assert.IsNull(blocksDb.Get(block2.Hash), "block 2"); - Assert.IsNull(blocksDb.Get(block3.Hash), "block 3"); + Assert.IsNull(blocksDb.Get(block1.Hash!), "block 1"); + Assert.IsNull(blocksDb.Get(block2.Hash!), "block 2"); + Assert.IsNull(blocksDb.Get(block3.Hash!), "block 3"); Assert.NotNull(blockInfosDb.Get(1), "level 1"); Assert.NotNull(blockInfosDb.Get(2), "level 2"); @@ -232,11 +230,9 @@ public async Task Can_load_from_DB_when_there_is_only_an_invalid_chain_in_DB() LimboLogs.Instance); CancellationTokenSource tokenSource = new(); -#pragma warning disable 4014 - Task.Delay(_dbLoadTimeout).ContinueWith(t => tokenSource.Cancel()); -#pragma warning restore 4014 + tokenSource.CancelAfter(_dbLoadTimeout); - tree2.NewBestSuggestedBlock += (sender, args) => + tree2.NewBestSuggestedBlock += (_, args) => { if (args.Block.Hash == block1.Hash) { @@ -254,12 +250,12 @@ public async Task Can_load_from_DB_when_there_is_only_an_invalid_chain_in_DB() /* note the block tree historically loads one less block than it could */ Assert.That(tree2.BestKnownNumber, Is.EqualTo(0L), "best known"); - Assert.That(tree2.Head.Hash, Is.EqualTo(block0.Hash), "head"); - Assert.That(tree2.BestSuggestedHeader.Hash, Is.EqualTo(block0.Hash), "suggested"); + Assert.That(tree2.Head!.Hash, Is.EqualTo(block0.Hash), "head"); + Assert.That(tree2.BestSuggestedHeader!.Hash, Is.EqualTo(block0.Hash), "suggested"); - Assert.IsNull(blocksDb.Get(block1.Hash), "block 1"); - Assert.IsNull(blocksDb.Get(block2.Hash), "block 2"); - Assert.IsNull(blocksDb.Get(block3.Hash), "block 3"); + Assert.IsNull(blocksDb.Get(block1.Hash!), "block 1"); + Assert.IsNull(blocksDb.Get(block2.Hash!), "block 2"); + Assert.IsNull(blocksDb.Get(block3.Hash!), "block 3"); Assert.IsNull(blockInfosDb.Get(1), "level 1"); Assert.IsNull(blockInfosDb.Get(2), "level 2"); diff --git a/src/Nethermind/Nethermind.Blockchain.Test/Visitors/StartupTreeFixerTests.cs b/src/Nethermind/Nethermind.Blockchain.Test/Visitors/StartupTreeFixerTests.cs index 9c06ec22795..08032d394f6 100644 --- a/src/Nethermind/Nethermind.Blockchain.Test/Visitors/StartupTreeFixerTests.cs +++ b/src/Nethermind/Nethermind.Blockchain.Test/Visitors/StartupTreeFixerTests.cs @@ -74,7 +74,7 @@ public async Task Deletes_everything_after_the_missing_level() Assert.Null(blockInfosDb.Get(4), "level 4"); Assert.Null(blockInfosDb.Get(5), "level 5"); - tree.Head.Header.Should().BeEquivalentTo(block2.Header, options => options.Excluding(t => t.MaybeParent)); + tree.Head!.Header.Should().BeEquivalentTo(block2.Header, options => options.Excluding(t => t.MaybeParent)); tree.BestSuggestedHeader.Should().BeEquivalentTo(block2.Header, options => options.Excluding(t => t.MaybeParent)); tree.BestSuggestedBody?.Body.Should().BeEquivalentTo(block2.Body); tree.BestKnownNumber.Should().Be(2); @@ -162,18 +162,18 @@ public async Task Fixer_should_not_suggest_block_with_null_block() testRpc.BlockchainProcessor = newBlockchainProcessor; IBlockTreeVisitor fixer = new StartupBlockTreeFixer(new SyncConfig(), tree, testRpc.DbProvider.StateDb, LimboNoErrorLogger.Instance, 5); - BlockVisitOutcome result = await fixer.VisitBlock(null, CancellationToken.None); + BlockVisitOutcome result = await fixer.VisitBlock(null!, CancellationToken.None); Assert.That(result, Is.EqualTo(BlockVisitOutcome.None)); } private static void SuggestNumberOfBlocks(IBlockTree blockTree, int blockAmount) { - Block newParent = blockTree.Head; + Block newParent = blockTree.Head!; for (int i = 0; i < blockAmount; ++i) { Block newBlock = Build.A.Block - .WithNumber(newParent!.Number + 1) + .WithNumber(newParent.Number + 1) .WithDifficulty(newParent.Difficulty + 1) .WithParent(newParent) .WithStateRoot(newParent.StateRoot!).TestObject; @@ -182,7 +182,6 @@ private static void SuggestNumberOfBlocks(IBlockTree blockTree, int blockAmount) } } - [Ignore("It is causing some trouble now. Disabling it while the restarts logic is under review")] [Test, Timeout(Timeout.MaxTestTime)] public async Task When_head_block_is_followed_by_a_block_bodies_gap_it_should_delete_all_levels_after_the_gap_start() { @@ -215,7 +214,7 @@ public async Task When_head_block_is_followed_by_a_block_bodies_gap_it_should_de Assert.That(tree.BestKnownNumber, Is.EqualTo(2L), "best known"); Assert.That(tree.Head?.Header, Is.EqualTo(block2.Header), "head"); - Assert.That(tree.BestSuggestedHeader.Hash, Is.EqualTo(block2.Hash), "suggested"); + Assert.That(tree.BestSuggestedHeader!.Hash, Is.EqualTo(block2.Hash), "suggested"); } } } diff --git a/src/Nethermind/Nethermind.Consensus/NethDevSealEngine.cs b/src/Nethermind/Nethermind.Consensus/NethDevSealEngine.cs index b28161da23d..082e096f413 100644 --- a/src/Nethermind/Nethermind.Consensus/NethDevSealEngine.cs +++ b/src/Nethermind/Nethermind.Consensus/NethDevSealEngine.cs @@ -11,7 +11,7 @@ namespace Nethermind.Consensus { public class NethDevSealEngine : ISealer, ISealValidator { - public NethDevSealEngine(Address address = null) + public NethDevSealEngine(Address? address = null) { Address = address ?? Address.Zero; } @@ -30,12 +30,12 @@ public bool CanSeal(long blockNumber, Keccak parentHash) public Address Address { get; } - public bool ValidateParams(BlockHeader parent, BlockHeader header, bool isUncle = false) + public bool ValidateParams(BlockHeader? parent, BlockHeader? header, bool isUncle = false) { return true; } - public bool ValidateSeal(BlockHeader header, bool force) + public bool ValidateSeal(BlockHeader? header, bool force) { return true; } diff --git a/src/Nethermind/Nethermind.Consensus/NullSealEngine.cs b/src/Nethermind/Nethermind.Consensus/NullSealEngine.cs index e743b9fb857..ac599278d0d 100644 --- a/src/Nethermind/Nethermind.Consensus/NullSealEngine.cs +++ b/src/Nethermind/Nethermind.Consensus/NullSealEngine.cs @@ -18,22 +18,22 @@ private NullSealEngine() public Address Address => Address.Zero; - public Task SealBlock(Block block, CancellationToken cancellationToken) + public Task SealBlock(Block? block, CancellationToken cancellationToken) { return Task.FromResult(block); } - public bool CanSeal(long blockNumber, Keccak parentHash) + public bool CanSeal(long blockNumber, Keccak? parentHash) { return true; } - public bool ValidateParams(BlockHeader parent, BlockHeader header, bool isUncle = false) + public bool ValidateParams(BlockHeader? parent, BlockHeader? header, bool isUncle = false) { return true; } - public bool ValidateSeal(BlockHeader header, bool force) + public bool ValidateSeal(BlockHeader? header, bool force) { return true; } diff --git a/src/Nethermind/Nethermind.Consensus/NullSigner.cs b/src/Nethermind/Nethermind.Consensus/NullSigner.cs index c0ec72c2d4c..ce587807924 100644 --- a/src/Nethermind/Nethermind.Consensus/NullSigner.cs +++ b/src/Nethermind/Nethermind.Consensus/NullSigner.cs @@ -10,9 +10,9 @@ namespace Nethermind.Consensus { public class NullSigner : ISigner, ISignerStore { - public static readonly NullSigner Instance = new(); + public static NullSigner Instance { get; } = new(); - public Address Address { get; } = Address.Zero; // TODO: why zero address + public Address Address { get; } = Address.Zero; // TODO: why zero address public ValueTask Sign(Transaction tx) => default; @@ -20,7 +20,7 @@ public class NullSigner : ISigner, ISignerStore public bool CanSign { get; } = true; // TODO: why true? - public PrivateKey Key { get; } + public PrivateKey? Key { get; } = null; public void SetSigner(PrivateKey key) { } diff --git a/src/Nethermind/Nethermind.Consensus/Signer.cs b/src/Nethermind/Nethermind.Consensus/Signer.cs index 25c79743c49..8b36bcf08ef 100644 --- a/src/Nethermind/Nethermind.Consensus/Signer.cs +++ b/src/Nethermind/Nethermind.Consensus/Signer.cs @@ -21,10 +21,10 @@ public class Signer : ISigner, ISignerStore public bool CanSign => _key is not null; - public Signer(ulong chainId, PrivateKey key, ILogManager logManager) + public Signer(ulong chainId, PrivateKey? key, ILogManager logManager) { _chainId = chainId; - _logger = logManager?.GetClassLogger() ?? throw new ArgumentNullException(nameof(logManager)); + _logger = logManager.GetClassLogger(); SetSigner(key); } diff --git a/src/Nethermind/Nethermind.Consensus/Transactions/SinglePendingTxSelector.cs b/src/Nethermind/Nethermind.Consensus/Transactions/SinglePendingTxSelector.cs index 17aae85d7f2..7c24771203f 100644 --- a/src/Nethermind/Nethermind.Consensus/Transactions/SinglePendingTxSelector.cs +++ b/src/Nethermind/Nethermind.Consensus/Transactions/SinglePendingTxSelector.cs @@ -1,7 +1,6 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only -using System; using System.Collections.Generic; using System.Linq; using Nethermind.Core; @@ -14,7 +13,7 @@ public class SinglePendingTxSelector : ITxSource public SinglePendingTxSelector(ITxSource innerSource) { - _innerSource = innerSource ?? throw new ArgumentNullException(nameof(innerSource)); + _innerSource = innerSource; } public IEnumerable GetTransactions(BlockHeader parent, long gasLimit) => diff --git a/src/Nethermind/Nethermind.Core.Test/Builders/TransactionBuilder.cs b/src/Nethermind/Nethermind.Core.Test/Builders/TransactionBuilder.cs index 54da3acfc6e..654d004eaca 100644 --- a/src/Nethermind/Nethermind.Core.Test/Builders/TransactionBuilder.cs +++ b/src/Nethermind/Nethermind.Core.Test/Builders/TransactionBuilder.cs @@ -121,7 +121,7 @@ public TransactionBuilder WithValue(int value) return this; } - public TransactionBuilder WithAccessList(AccessList accessList) + public TransactionBuilder WithAccessList(AccessList? accessList) { TestObjectInternal.AccessList = accessList; TestObjectInternal.ChainId = TestObjectInternal.Signature?.ChainId ?? TestObjectInternal.ChainId; @@ -153,7 +153,7 @@ public TransactionBuilder WithBlobVersionedHashes(int? count) return this; } - TestObjectInternal.BlobVersionedHashes = Enumerable.Range(0, count.Value).Select(x => + TestObjectInternal.BlobVersionedHashes = Enumerable.Range(0, count.Value).Select(_ => { byte[] bvh = new byte[32]; bvh[0] = KzgPolynomialCommitments.KzgBlobHashVersionV1; @@ -241,7 +241,7 @@ public TransactionBuilder Signed(PrivateKey? privateKey = null) privateKey ??= TestItem.IgnoredPrivateKey; EthereumEcdsa ecdsa = new(TestObjectInternal.ChainId ?? TestBlockchainIds.ChainId, LimboLogs.Instance); - return Signed(ecdsa, privateKey, true); + return Signed(ecdsa, privateKey, isEip155Enabled: true); } // TODO: auto create ecdsa here From 8368be7bf5d53fbccb6ee6400ff47c0b75fc2701 Mon Sep 17 00:00:00 2001 From: Amirul Ashraf Date: Fri, 22 Sep 2023 22:02:17 +0800 Subject: [PATCH 32/50] Perf/Malloc trimmer (#6111) * Malloc trimmer * Set malloc options * Use a different setting * Adjust config * Split malloc calls to a separate file * Refactored to use MallocHelper * Comment * Malloc trim test * Whitespace * Trim on GCKeeper and during sync only * No need for this config * Minor cleanup * Do nothing if interval is zero * Make pad higher * Minor adjustment --- .../Synchronization/ISyncConfig.cs | 3 + .../Synchronization/SyncConfig.cs | 2 +- .../Memory/MallocHelperTests.cs | 6 ++ .../Nethermind.Core/Memory/MallocHelper.cs | 12 ++++ .../Nethermind.Merge.Plugin/GC/GCKeeper.cs | 3 + .../MallocTrimmerTests.cs | 43 ++++++++++++++ .../MallocTrimmer.cs | 57 +++++++++++++++++++ .../Synchronizer.cs | 2 + 8 files changed, 127 insertions(+), 1 deletion(-) create mode 100644 src/Nethermind/Nethermind.Synchronization.Test/MallocTrimmerTests.cs create mode 100644 src/Nethermind/Nethermind.Synchronization/MallocTrimmer.cs diff --git a/src/Nethermind/Nethermind.Blockchain/Synchronization/ISyncConfig.cs b/src/Nethermind/Nethermind.Blockchain/Synchronization/ISyncConfig.cs index e71408b912b..21c8e7ad006 100644 --- a/src/Nethermind/Nethermind.Blockchain/Synchronization/ISyncConfig.cs +++ b/src/Nethermind/Nethermind.Blockchain/Synchronization/ISyncConfig.cs @@ -121,5 +121,8 @@ public interface ISyncConfig : IConfig [ConfigItem(Description = "Specify wait time after sync finished.", DefaultValue = "60")] public int ExitOnSyncedWaitTimeSec { get; set; } + + [ConfigItem(Description = "[TECHNICAL] specify interval between malloc_trim during sync", DefaultValue = "300", HiddenFromDocs = true)] + public int MallocTrimIntervalSec { get; set; } } } diff --git a/src/Nethermind/Nethermind.Blockchain/Synchronization/SyncConfig.cs b/src/Nethermind/Nethermind.Blockchain/Synchronization/SyncConfig.cs index c584ca0397d..aecef33795e 100644 --- a/src/Nethermind/Nethermind.Blockchain/Synchronization/SyncConfig.cs +++ b/src/Nethermind/Nethermind.Blockchain/Synchronization/SyncConfig.cs @@ -65,7 +65,7 @@ public string? PivotHash public int MaxProcessingThreads { get; set; } public bool ExitOnSynced { get; set; } = false; public int ExitOnSyncedWaitTimeSec { get; set; } = 60; - + public int MallocTrimIntervalSec { get; set; } = 300; public bool TrieHealing { get; set; } = true; public override string ToString() diff --git a/src/Nethermind/Nethermind.Core.Test/Memory/MallocHelperTests.cs b/src/Nethermind/Nethermind.Core.Test/Memory/MallocHelperTests.cs index 0e96f4b2a16..fecc70483a0 100644 --- a/src/Nethermind/Nethermind.Core.Test/Memory/MallocHelperTests.cs +++ b/src/Nethermind/Nethermind.Core.Test/Memory/MallocHelperTests.cs @@ -15,4 +15,10 @@ public void TestMallOpts() { MallocHelper.Instance.MallOpt(MallocHelper.Option.M_MMAP_THRESHOLD, (int)128.KiB()).Should().BeTrue(); } + + [Test] + public void TestMallocTrim() + { + MallocHelper.Instance.MallocTrim(0).Should().BeTrue(); + } } diff --git a/src/Nethermind/Nethermind.Core/Memory/MallocHelper.cs b/src/Nethermind/Nethermind.Core/Memory/MallocHelper.cs index 528ab1b2cbf..d4063030198 100644 --- a/src/Nethermind/Nethermind.Core/Memory/MallocHelper.cs +++ b/src/Nethermind/Nethermind.Core/Memory/MallocHelper.cs @@ -14,6 +14,9 @@ public class MallocHelper [DllImport("libc")] private static extern int mallopt(int opts, int value); + [DllImport("libc")] + private static extern int malloc_trim(UIntPtr trailingSpace); + private static MallocHelper? _instance; public static MallocHelper Instance => _instance ??= new MallocHelper(); @@ -26,6 +29,15 @@ public bool MallOpt(Option option, int value) return mallopt((int)option, value) == 1; } + public virtual bool MallocTrim(uint trailingSpace) + { + // Windows can't find libc and osx does not have the method for some reason + // FreeBSD uses jemalloc by default anyway.... + if (!RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) return true; + + return malloc_trim(trailingSpace) == 1; + } + public enum Option : int { M_MMAP_THRESHOLD = -3 diff --git a/src/Nethermind/Nethermind.Merge.Plugin/GC/GCKeeper.cs b/src/Nethermind/Nethermind.Merge.Plugin/GC/GCKeeper.cs index 0acdc6f4b64..17d736dd280 100644 --- a/src/Nethermind/Nethermind.Merge.Plugin/GC/GCKeeper.cs +++ b/src/Nethermind/Nethermind.Merge.Plugin/GC/GCKeeper.cs @@ -7,6 +7,7 @@ using System.Threading.Tasks; using FastEnumUtility; using Nethermind.Core.Extensions; +using Nethermind.Core.Memory; using Nethermind.Logging; namespace Nethermind.Merge.Plugin.GC; @@ -179,6 +180,8 @@ private async Task ScheduleGCInternal() } System.GC.Collect((int)generation, mode, blocking: true, compacting: compacting > 0); + + MallocHelper.Instance.MallocTrim((uint)1.MiB()); } } } diff --git a/src/Nethermind/Nethermind.Synchronization.Test/MallocTrimmerTests.cs b/src/Nethermind/Nethermind.Synchronization.Test/MallocTrimmerTests.cs new file mode 100644 index 00000000000..26c544963f6 --- /dev/null +++ b/src/Nethermind/Nethermind.Synchronization.Test/MallocTrimmerTests.cs @@ -0,0 +1,43 @@ +// SPDX-FileCopyrightText: 2023 Demerzel Solutions Limited +// SPDX-License-Identifier: LGPL-3.0-only + +using System; +using System.Threading.Tasks; +using Nethermind.Core.Memory; +using Nethermind.Logging; +using Nethermind.Synchronization.ParallelSync; +using NSubstitute; +using NUnit.Framework; + +namespace Nethermind.Synchronization.Test; + +public class MallocTrimmerTests +{ + [TestCase(SyncMode.None, false)] + [TestCase(SyncMode.WaitingForBlock, false)] + [TestCase(SyncMode.FastBlocks, true)] + public async Task TestTrim(SyncMode mode, bool doReceive) + { + MallocHelper helper = Substitute.For(); + + ISyncModeSelector syncModeSelector = Substitute.For(); + new MallocTrimmer(syncModeSelector, TimeSpan.FromMilliseconds(1), NullLogManager.Instance, helper); + + syncModeSelector.Changed += Raise.EventWith(null, + new SyncModeChangedEventArgs(SyncMode.FastSync, mode)); + + await Task.Delay(TimeSpan.FromMilliseconds(100)); + + syncModeSelector.Changed += Raise.EventWith(null, + new SyncModeChangedEventArgs(SyncMode.None, SyncMode.None)); + + if (doReceive) + { + helper.Received().MallocTrim(Arg.Any()); + } + else + { + helper.DidNotReceive().MallocTrim(Arg.Any()); + } + } +} diff --git a/src/Nethermind/Nethermind.Synchronization/MallocTrimmer.cs b/src/Nethermind/Nethermind.Synchronization/MallocTrimmer.cs new file mode 100644 index 00000000000..4574e37c9b9 --- /dev/null +++ b/src/Nethermind/Nethermind.Synchronization/MallocTrimmer.cs @@ -0,0 +1,57 @@ +// SPDX-FileCopyrightText: 2023 Demerzel Solutions Limited +// SPDX-License-Identifier: LGPL-3.0-only + +using System; +using System.Diagnostics; +using Nethermind.Core.Extensions; +using Nethermind.Core.Memory; +using Nethermind.Logging; +using Nethermind.Synchronization.ParallelSync; +using Timer = System.Timers.Timer; + +namespace Nethermind.Synchronization; + +public class MallocTrimmer +{ + private MallocHelper _mallocHelper; + private ILogger _logger; + + public MallocTrimmer( + ISyncModeSelector syncModeSelector, + TimeSpan interval, + ILogManager logManager, + MallocHelper? mallocHelper = null + ) + { + _mallocHelper = mallocHelper ?? new MallocHelper(); + _logger = logManager.GetClassLogger(); + + if (interval == TimeSpan.Zero) return; + + Timer timer = new(interval); + timer.Elapsed += (sender, args) => Trim(); + + syncModeSelector.Changed += (_, args) => + { + bool notSyncing = args.Current is SyncMode.None or SyncMode.WaitingForBlock; + timer.Enabled = !notSyncing; + }; + } + + private void Trim() + { + // Unlike a GC, this seems to be single threaded, going through each arena one by one. + // It does however, lock the arena. On 32 thread machine, 256 arena, this take between 300ms to 1 second + // in total, so about 1 to 4 ms for each arena, which is the possible hang when allocating via malloc. + // This does not apply to managed code though, so this is largely the concern of rocksdb when reading + // from uncached block. + // + // Unlike the standard free(), in addition to always clearing fastbin and consolidating chunks, this + // also MADV_DONTNEED large enough free section of the heap. This also means private/virtual memory + // does not go down, but RSS and GC load does. + long startTime = Stopwatch.GetTimestamp(); + if (_logger.IsDebug) _logger.Debug("Trimming malloc heaps"); + bool wasReleased = _mallocHelper.MallocTrim((uint)1.MiB()); + if (_logger.IsDebug) _logger.Debug($"Trimming malloc heap took {Stopwatch.GetElapsedTime(startTime)}. wasReleased: {wasReleased}"); + } +} diff --git a/src/Nethermind/Nethermind.Synchronization/Synchronizer.cs b/src/Nethermind/Nethermind.Synchronization/Synchronizer.cs index 26c0f0f78a3..3dbf33d4ba2 100644 --- a/src/Nethermind/Nethermind.Synchronization/Synchronizer.cs +++ b/src/Nethermind/Nethermind.Synchronization/Synchronizer.cs @@ -91,6 +91,8 @@ public Synchronizer( _exitSource = processExitSource ?? throw new ArgumentNullException(nameof(processExitSource)); _logManager = logManager ?? throw new ArgumentNullException(nameof(logManager)); _syncReport = syncReport ?? throw new ArgumentNullException(nameof(syncReport)); + + new MallocTrimmer(syncModeSelector, TimeSpan.FromSeconds(syncConfig.MallocTrimIntervalSec), _logManager); } public virtual void Start() From a09b867d3d67c9440e9850124eef1f83a499c683 Mon Sep 17 00:00:00 2001 From: Lukasz Rozmej Date: Fri, 22 Sep 2023 18:44:53 +0200 Subject: [PATCH 33/50] fix AggregateException being thrown instead of TimeoutException (#6123) --- .../P2P/ProtocolHandlers/ZeroProtocolHandlerBase.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Nethermind/Nethermind.Network/P2P/ProtocolHandlers/ZeroProtocolHandlerBase.cs b/src/Nethermind/Nethermind.Network/P2P/ProtocolHandlers/ZeroProtocolHandlerBase.cs index 3df17814be6..5fa02d2969a 100644 --- a/src/Nethermind/Nethermind.Network/P2P/ProtocolHandlers/ZeroProtocolHandlerBase.cs +++ b/src/Nethermind/Nethermind.Network/P2P/ProtocolHandlers/ZeroProtocolHandlerBase.cs @@ -73,7 +73,7 @@ CancellationToken token if (Logger.IsTrace) Logger.Trace($"{this} speed is {request.ResponseSize}/{elapsed} = {bytesPerMillisecond}"); StatsManager.ReportTransferSpeedEvent(Session.Node, speedType, bytesPerMillisecond); - return task.Result; + return await task; } StatsManager.ReportTransferSpeedEvent(Session.Node, speedType, 0L); From 29c51919e7bdec4852760b009bf76dec257eca6a Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sun, 24 Sep 2023 11:29:42 +0200 Subject: [PATCH 34/50] Updating Fast Sync config files (#6124) Co-authored-by: LukaszRozmej --- src/Nethermind/Nethermind.Runner/configs/chiado.cfg | 4 ++-- src/Nethermind/Nethermind.Runner/configs/energyweb.cfg | 6 +++--- src/Nethermind/Nethermind.Runner/configs/exosama.cfg | 6 +++--- src/Nethermind/Nethermind.Runner/configs/gnosis.cfg | 4 ++-- src/Nethermind/Nethermind.Runner/configs/goerli.cfg | 4 ++-- src/Nethermind/Nethermind.Runner/configs/mainnet.cfg | 4 ++-- src/Nethermind/Nethermind.Runner/configs/sepolia.cfg | 4 ++-- src/Nethermind/Nethermind.Runner/configs/volta.cfg | 6 +++--- 8 files changed, 19 insertions(+), 19 deletions(-) diff --git a/src/Nethermind/Nethermind.Runner/configs/chiado.cfg b/src/Nethermind/Nethermind.Runner/configs/chiado.cfg index 0b9e24df756..05322221976 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": 5950000, - "PivotHash": "0xa1f714043f233352e96c9ce7352f38251fb59f1294206f9a2f1937179ffb3cf1", + "PivotNumber": 6190000, + "PivotHash": "0x19afb16e00cde2cb8546b9f97b34cb80f1a841b15f4d4b2bba5c611cdcbcaca2", "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 61131c20f37..573479a70ce 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": 25930000, - "PivotHash": "0x59f0e0f2bda0ad332648ee42328f5e62a82a01c4f6b99007d5d4d148601d3f43", - "PivotTotalDifficulty": "8823521774259934357605303570705749722689434693", + "PivotNumber": 26150000, + "PivotHash": "0x1c5fb2be00ab0e60ee511c8473fde1e090f9d41361d2458a58cb4b7f677c56a8", + "PivotTotalDifficulty": "8898383894982540819567245984340738729209295560", "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 f59f98bc1b1..9456f06296b 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": 5570000, - "PivotHash": "0x848a9f0145cf43a78dd02e8f73a8b6a918d3e29cb8dd1092fccf445db46c215f", - "PivotTotalDifficulty": "1895372783749627241490996563394948937465633290", + "PivotNumber": 5810000, + "PivotHash": "0x7411e4c1ff2241383f7218445676d90b3e593261f2beb4e17796bfd33d55daf9", + "PivotTotalDifficulty": "1977040551810652472722206469178573308214593289", "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 b4b7cce9560..d61cddc1227 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": 29880000, - "PivotHash": "0xba2df29e0259704daada7c599558e2135d41b5b6138bac4341f75505f6605050", + "PivotNumber": 30110000, + "PivotHash": "0x7b630b4abff0921c930b79a259934babd51c8460408c5ced0269d83589070972", "PivotTotalDifficulty": "8626000110427538733349499292577475819600160930", "FastBlocks": true, "UseGethLimitsInFastBlocks": false, diff --git a/src/Nethermind/Nethermind.Runner/configs/goerli.cfg b/src/Nethermind/Nethermind.Runner/configs/goerli.cfg index c133ef507ad..7e6dff6c8b0 100644 --- a/src/Nethermind/Nethermind.Runner/configs/goerli.cfg +++ b/src/Nethermind/Nethermind.Runner/configs/goerli.cfg @@ -15,8 +15,8 @@ "Sync": { "FastSync": true, "SnapSync": true, - "PivotNumber": 9630000, - "PivotHash": "0xfc325661d6b05868c03781d65df95fb63846f8b99707ebd907614008624ffdb0", + "PivotNumber": 9720000, + "PivotHash": "0xc611dbb72cdcd5abcf9b25e56295242e5851efd4571cbf5c539c9084a69d92d4", "PivotTotalDifficulty": "10790000", "FastBlocks": true, "UseGethLimitsInFastBlocks": true, diff --git a/src/Nethermind/Nethermind.Runner/configs/mainnet.cfg b/src/Nethermind/Nethermind.Runner/configs/mainnet.cfg index 4238c93d7fa..8106c644d60 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": 18101000, - "PivotHash": "0x8c873e8c8bddd8202ea368e00339f1e8dd31c11b48fce562af79911d15496c2b", + "PivotNumber": 18200000, + "PivotHash": "0xb03f1070c7ed301fc72f310181192ad740f6ea09ff1376482d1e0f431b8a6a35", "PivotTotalDifficulty": "58750003716598352816469", "FastBlocks": true, "AncientBodiesBarrier": 11052984, diff --git a/src/Nethermind/Nethermind.Runner/configs/sepolia.cfg b/src/Nethermind/Nethermind.Runner/configs/sepolia.cfg index ef45d5da42f..e72bdf8b231 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": 4256000, - "PivotHash": "0xbcd98e48fc103281613092e4f438443c57d83e48659ce6c49c463c38e3c0b95b", + "PivotNumber": 4349000, + "PivotHash": "0x6fc5c49d62481c262d61e94c386f7a0dd6150f5d4384be926629267c5879d2ae", "PivotTotalDifficulty": "17000018015853232", "FastSyncCatchUpHeightDelta": "10000000000" }, diff --git a/src/Nethermind/Nethermind.Runner/configs/volta.cfg b/src/Nethermind/Nethermind.Runner/configs/volta.cfg index 2462c7397d8..c69117dc784 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": 24630000, - "PivotHash": "0x6656a988ec331a0140c2347e71d6f17ecad3ee804de6fa9f9ec36ec6432af7eb", - "PivotTotalDifficulty": "8381154697262714355102916581044451047797938883", + "PivotNumber": 24820000, + "PivotHash": "0xde7503303f0a803ce04503bf7cc1fcf9821f9628384a14a4babca2b5fe414125", + "PivotTotalDifficulty": "8445808346977692663160957756456487007974147358", "FastBlocks": true, "UseGethLimitsInFastBlocks": false, "FastSyncCatchUpHeightDelta": 10000000000 From b2d05abbd28e37e618afa157954b3d293e74694a Mon Sep 17 00:00:00 2001 From: Amirul Ashraf Date: Tue, 26 Sep 2023 11:44:22 +0800 Subject: [PATCH 35/50] Perf/buffersize adjustment (#6122) * Always use 8MB of write buffer size on heavy write * Expose max bytes for level base * Enable write bias by default * Increase available for buffer memory * Some comment * Minor cleanup * Update state and tweak buffer * Missed disable compaction options * Add disable compaction options --- .../Synchronization/ISyncConfig.cs | 2 +- .../Synchronization/SyncConfig.cs | 2 +- .../Nethermind.Db.Rocks/Config/DbConfig.cs | 2 + .../Nethermind.Db.Rocks/Config/IDbConfig.cs | 2 + .../Config/PerTableDbConfig.cs | 1 + .../Nethermind.Db.Rocks/DbOnTheRocks.cs | 82 +++++++++++++------ .../Nethermind.Init/MemoryHintMan.cs | 48 +++++------ 7 files changed, 89 insertions(+), 50 deletions(-) diff --git a/src/Nethermind/Nethermind.Blockchain/Synchronization/ISyncConfig.cs b/src/Nethermind/Nethermind.Blockchain/Synchronization/ISyncConfig.cs index 21c8e7ad006..9aaacca9e6b 100644 --- a/src/Nethermind/Nethermind.Blockchain/Synchronization/ISyncConfig.cs +++ b/src/Nethermind/Nethermind.Blockchain/Synchronization/ISyncConfig.cs @@ -104,7 +104,7 @@ public interface ISyncConfig : IConfig [ConfigItem(Description = "[EXPERIMENTAL] Only for non validator nodes! If set to true, DownloadReceiptsInFastSync and/or DownloadBodiesInFastSync can be set to false.", DefaultValue = "false")] public bool NonValidatorNode { get; set; } - [ConfigItem(Description = "[EXPERIMENTAL] Optimize db for write during sync. Significantly reduce total writes written and some sync time if you are not network limited.", DefaultValue = "Default")] + [ConfigItem(Description = "[EXPERIMENTAL] Optimize db for write during sync. Significantly reduce total writes written and some sync time if you are not network limited.", DefaultValue = "WriteBias")] public ITunableDb.TuneType TuneDbMode { get; set; } [ConfigItem(Description = "[EXPERIMENTAL] Optimize db for write during sync just for blocks db. Useful for turning on blobs file.", DefaultValue = "EnableBlobFiles")] diff --git a/src/Nethermind/Nethermind.Blockchain/Synchronization/SyncConfig.cs b/src/Nethermind/Nethermind.Blockchain/Synchronization/SyncConfig.cs index aecef33795e..47ffa44b655 100644 --- a/src/Nethermind/Nethermind.Blockchain/Synchronization/SyncConfig.cs +++ b/src/Nethermind/Nethermind.Blockchain/Synchronization/SyncConfig.cs @@ -60,7 +60,7 @@ public string? PivotHash public bool StrictMode { get; set; } = false; public bool BlockGossipEnabled { get; set; } = true; public bool NonValidatorNode { get; set; } = false; - public ITunableDb.TuneType TuneDbMode { get; set; } = ITunableDb.TuneType.Default; + public ITunableDb.TuneType TuneDbMode { get; set; } = ITunableDb.TuneType.WriteBias; public ITunableDb.TuneType BlocksDbTuneDbMode { get; set; } = ITunableDb.TuneType.EnableBlobFiles; public int MaxProcessingThreads { get; set; } public bool ExitOnSynced { get; set; } = false; diff --git a/src/Nethermind/Nethermind.Db.Rocks/Config/DbConfig.cs b/src/Nethermind/Nethermind.Db.Rocks/Config/DbConfig.cs index ffad9626260..7691485e8de 100644 --- a/src/Nethermind/Nethermind.Db.Rocks/Config/DbConfig.cs +++ b/src/Nethermind/Nethermind.Db.Rocks/Config/DbConfig.cs @@ -26,6 +26,7 @@ public class DbConfig : IDbConfig public bool? DisableCompression { get; set; } = false; public ulong? CompactionReadAhead { get; set; } public IDictionary? AdditionalRocksDbOptions { get; set; } + public ulong? MaxBytesForLevelBase { get; set; } = (ulong)256.MiB(); public ulong ReceiptsDbWriteBufferSize { get; set; } = (ulong)8.MiB(); public uint ReceiptsDbWriteBufferNumber { get; set; } = 4; @@ -62,6 +63,7 @@ public class DbConfig : IDbConfig public bool? HeadersDbUseDirectIoForFlushAndCompactions { get; set; } public ulong? HeadersDbCompactionReadAhead { get; set; } public IDictionary? HeadersDbAdditionalRocksDbOptions { get; set; } + public ulong? HeadersDbMaxBytesForLevelBase { get; set; } = (ulong)128.MiB(); public ulong BlockInfosDbWriteBufferSize { get; set; } = (ulong)8.MiB(); public uint BlockInfosDbWriteBufferNumber { get; set; } = 4; diff --git a/src/Nethermind/Nethermind.Db.Rocks/Config/IDbConfig.cs b/src/Nethermind/Nethermind.Db.Rocks/Config/IDbConfig.cs index 2a8d1e7a813..e0e8933c061 100644 --- a/src/Nethermind/Nethermind.Db.Rocks/Config/IDbConfig.cs +++ b/src/Nethermind/Nethermind.Db.Rocks/Config/IDbConfig.cs @@ -27,6 +27,7 @@ public interface IDbConfig : IConfig bool? DisableCompression { get; set; } ulong? CompactionReadAhead { get; set; } IDictionary? AdditionalRocksDbOptions { get; set; } + ulong? MaxBytesForLevelBase { get; set; } ulong ReceiptsDbWriteBufferSize { get; set; } uint ReceiptsDbWriteBufferNumber { get; set; } @@ -63,6 +64,7 @@ public interface IDbConfig : IConfig bool? HeadersDbUseDirectIoForFlushAndCompactions { get; set; } ulong? HeadersDbCompactionReadAhead { get; set; } IDictionary? HeadersDbAdditionalRocksDbOptions { get; set; } + ulong? HeadersDbMaxBytesForLevelBase { get; set; } ulong BlockInfosDbWriteBufferSize { get; set; } uint BlockInfosDbWriteBufferNumber { get; set; } diff --git a/src/Nethermind/Nethermind.Db.Rocks/Config/PerTableDbConfig.cs b/src/Nethermind/Nethermind.Db.Rocks/Config/PerTableDbConfig.cs index dea9c3347b9..0ff698c63c5 100644 --- a/src/Nethermind/Nethermind.Db.Rocks/Config/PerTableDbConfig.cs +++ b/src/Nethermind/Nethermind.Db.Rocks/Config/PerTableDbConfig.cs @@ -48,6 +48,7 @@ public PerTableDbConfig(IDbConfig dbConfig, RocksDbSettings rocksDbSettings, str public uint StatsDumpPeriodSec => _dbConfig.StatsDumpPeriodSec; public bool? DisableCompression => ReadConfig(nameof(DisableCompression)); public ulong? CompactionReadAhead => ReadConfig(nameof(CompactionReadAhead)); + public ulong MaxBytesForLevelBase => ReadConfig(nameof(MaxBytesForLevelBase)); private T? ReadConfig(string propertyName) { diff --git a/src/Nethermind/Nethermind.Db.Rocks/DbOnTheRocks.cs b/src/Nethermind/Nethermind.Db.Rocks/DbOnTheRocks.cs index bf3b3390221..7aba5e70890 100644 --- a/src/Nethermind/Nethermind.Db.Rocks/DbOnTheRocks.cs +++ b/src/Nethermind/Nethermind.Db.Rocks/DbOnTheRocks.cs @@ -369,6 +369,11 @@ protected virtual void BuildOptions(PerTableDbConfig dbConfig, Options opt options.SetWriteBufferSize(writeBufferSize); int writeBufferNumber = (int)dbConfig.WriteBufferNumber; options.SetMaxWriteBufferNumber(writeBufferNumber); + + // Memtable is slower to writes the bigger it gets, but small memtable means small l0 file size, which means + // higher write amp for l0->l1 compaction. This allows multiple memtable to go into one l0 file so that it is + // not too small so it helps with write amp when setting small write buffer. AFAIK that is its only use compared + // to just specifying large write buffer. Sadly, this setting can't dynamically change. options.SetMinWriteBufferNumberToMerge(2); lock (_dbsByPath) @@ -389,6 +394,7 @@ protected virtual void BuildOptions(PerTableDbConfig dbConfig, Options opt options.SetRecycleLogFileNum(dbConfig .RecycleLogFileNum); // potential optimization for reusing allocated log files + options.SetMaxBytesForLevelBase(dbConfig.MaxBytesForLevelBase); options.SetUseDirectReads(dbConfig.UseDirectReads.GetValueOrDefault()); options.SetUseDirectIoForFlushAndCompaction(dbConfig.UseDirectIoForFlushAndCompactions.GetValueOrDefault()); @@ -1067,25 +1073,25 @@ public virtual void Tune(ITunableDb.TuneType type) // smoothens this spike somewhat by not blocking writes while allowing compaction to happen in background // at 1/10th the specified speed (if rate limited). // - // Read and writes written on different tune during mainnet sync in TB. - // +-----------------------------+----------------+--------------+---------------+---------------+--------------+----------------+---------------------+ - // | L0FileNumTarget | Total (R/W) | State | Code | Header | Blocks | Receipts_Blocks | Receipt_Transactions | - // +-----------------------------+----------------+--------------+---------------+---------------+--------------+----------------+---------------------+ - // | 4 (Default) | 7.853 / 8.41 | 2.58 / 2.78 | 0.104 / 0.107 | 0.133 / 0.141 | 4.34 / 4.58 | 0.502 / 0.593 | 0.194 / 0.209 | - // | 4 (8GB memory hint) | 7.875 / 8.393 | 2.40 / 2.56 | 0.103 / 0.106 | 0.114 / 0.122 | 4.51 / 4.75 | 0.556 / 0.648 | 0.192 / 0.207 | - // | 14 | 7.001 / 7.514 | 2.38 / 2.54 | 0.029 / 0.032 | 0.132 / 0.141 | 4.04 / 4.27 | 0.287 / 0.378 | 0.138 / 0.153 | - // | 64 (WriteBias) | 5.986 / 6.493 | 1.63 / 1.79 | 0.023 / 0.026 | 0.120 / 0.128 | 3.82 / 4.05 | 0.280 / 0.371 | 0.113 / 0.128 | - // | 256 (HeavyWrite) | 4.386 / 4.895 | 1.12 / 1.28 | 0.013 / 0.016 | 0.131 / 0.140 | 2.89 / 3.12 | 0.178 / 0.270 | 0.054 / 0.069 | - // | 1024 (AggressiveHeavyWrite) | 2.942 / 3.452 | 0.60 / 0.76 | 0.006 / 0.009 | 0.133 / 0.142 | 2.01 / 2.24 | 0.171 / 0.263 | 0.022 / 0.038 | - // +-----------------------------+-----------------+--------------+---------------+--------------+--------------+----------------+---------------------+ + // Total writes written on different tune during mainnet sync in TB. + // +-----------------------+-------+-------+-------+-------+-------+---------+ + // | L0FileNumTarget | Total | State | Code | Header| Blocks| Receipts | + // +-----------------------+-------+-------+-------+-------+-------+---------+ + // | Default | 5.055 | 2.27 | 0.242 | 0.123 | 1.14 | 1.280 | + // | WriteBias | 4.962 | 2.12 | 0.049 | 0.132 | 1.14 | 1.080 | + // | HeavyWrite | 3.592 | 1.32 | 0.032 | 0.116 | 1.14 | 0.984 | + // | AggressiveHeavyWrite | 3.029 | 0.92 | 0.024 | 0.118 | 1.14 | 0.827 | + // | DisableCompaction | 2.215 | 0.36 | 0.031 | 0.137 | 1.14 | 0.547 | + // +-----------------------+-------+-------+-------+-------+-------+---------+ // Note, in practice on my machine, the reads does not reach the SSD. Read measured from SSD is much lower // than read measured from process. It is likely that most files are cached as I have 128GB of RAM. // Also notice that the heavier the tune, the higher the reads. case ITunableDb.TuneType.WriteBias: - // The default l1SizeTarget is 256MB, so the compaction is fairly light. But the default options is not very - // efficient for write amplification to conserve memory, so the write amplification reduction is noticeable. - // Does not seems to impact sync performance, might improve sync time slightly if user is IO limited. - ApplyOptions(GetHeavyWriteOptions(64)); + // Keep the same l1 size but apply other adjustment which should increase buffer number and make + // l0 the same size as l1, but keep the LSM the same. This improve flush parallelization, and + // write amplification due to mismatch of l0 and l1 size, but does not reduce compaction from other + // levels. + ApplyOptions(GetHeavyWriteOptions(_perTableDbConfig.MaxBytesForLevelBase / (ulong)8.MiB())); break; case ITunableDb.TuneType.HeavyWrite: // Compaction spikes are clear at this point. Will definitely affect attestation performance. @@ -1118,9 +1124,7 @@ public virtual void Tune(ITunableDb.TuneType type) // user config may not be able to handle this. // With all those cons, this result in the minimum write amplification possible via tweaking compaction // without changing memory budget. Not recommended for mainnet, unless you are very desperate. - IDictionary heavyWriteOption = GetHeavyWriteOptions(2048); - heavyWriteOption["disable_auto_compactions"] = "true"; - ApplyOptions(heavyWriteOption); + ApplyOptions(GetDisableCompactionOptions()); break; case ITunableDb.TuneType.EnableBlobFiles: ApplyOptions(GetBlobFilesOptions()); @@ -1144,15 +1148,17 @@ private IDictionary GetStandardOptions() // Defaults are from rocksdb source code return new Dictionary() { + { "write_buffer_size", _perTableDbConfig.WriteBufferSize.ToString() }, + { "max_write_buffer_number", _perTableDbConfig.WriteBufferNumber.ToString() }, + { "level0_file_num_compaction_trigger", 4.ToString() }, { "level0_slowdown_writes_trigger", 20.ToString() }, { "level0_stop_writes_trigger", 36.ToString() }, - { "max_bytes_for_level_base", 256.MiB().ToString() }, + { "max_bytes_for_level_base", _perTableDbConfig.MaxBytesForLevelBase.ToString() }, { "target_file_size_base", 64.MiB().ToString() }, { "disable_auto_compactions", "false" }, - { "write_buffer_size", _perTableDbConfig.WriteBufferSize.ToString() }, { "enable_blob_files", "false" }, { "soft_pending_compaction_bytes_limit", 64.GiB().ToString() }, @@ -1173,17 +1179,30 @@ private IDictionary GetStandardOptions() /// private IDictionary GetHeavyWriteOptions(ulong l0FileNumTarget) { + // Make buffer (probably) smaller so that it does not take too much memory to have many of them. + // More buffer means more parallel flush, but each read have to go through all buffer one by one much like l0 + // but no io, only cpu. + // bufferSize*maxBufferNumber = 128MB, which is the max memory used, which tend to be the case as its now + // stalled by compaction instead of flush. + // The skiplist (memtable) have a branching factor of 4, so I assume it slows down a little as num of record + // grows by 4x. So we are looking at 1,4,16,64,256,1k,4k,16k,64k and so on num of keys. Assuming average size of + // 120 bytes per key for state db, we are targeting between 4k to 16k of keys per memtable. + // A small memtable however, have the drawback of making l0 files smaller. Causing more compaction overhead. + ulong bufferSize = (ulong)4.MiB(); + ulong writeBufferToMerge = 2; + ulong maxBufferNumber = 16 * writeBufferToMerge; + // Guide recommend to have l0 and l1 to be the same size. They have to be compacted together so if l1 is larger, // the extra size in l1 is basically extra rewrites. If l0 is larger... then I don't know why not. Even so, it seems to // always get triggered when l0 size exceed max_bytes_for_level_base even if file num is less than l0FileNumTarget. - // The 2 here is MinWriteBufferToMerge. Note, that this does highly depends on the WriteBufferSize as do standard - // config. - ulong l1SizeTarget = l0FileNumTarget * _perTableDbConfig.WriteBufferSize * 2; + ulong l1SizeTarget = l0FileNumTarget * bufferSize * writeBufferToMerge; return new Dictionary() { - { "max_bytes_for_level_base", l1SizeTarget.ToString() }, + { "write_buffer_size", bufferSize.ToString() }, + { "max_write_buffer_number", maxBufferNumber.ToString() }, + { "max_bytes_for_level_base", l1SizeTarget.ToString() }, { "level0_file_num_compaction_trigger", l0FileNumTarget.ToString() }, // Note: If ratelimiter is not specified and if delayed_write_rate is not specified, the default is 16MBps. @@ -1197,6 +1216,21 @@ private IDictionary GetHeavyWriteOptions(ulong l0FileNumTarget) }; } + private IDictionary GetDisableCompactionOptions() + { + IDictionary heavyWriteOption = GetHeavyWriteOptions(2048); + + heavyWriteOption["disable_auto_compactions"] = "true"; + // Increase the size of the write buffer, which reduces the number of l0 file by 4x. This does slows down + // the memtable a little bit. So if you are not write limited, you'll get memtable limited instead. + // This does increase the total memory buffer size, but counterintuitively, this reduces overall memory usage + // as it ran out of bloom filter cache so it need to do actual IO. + heavyWriteOption["write_buffer_size"] = 16.MiB().ToString(); + + return heavyWriteOption; + } + + private IDictionary GetBlobFilesOptions() { // Enable blob files, see: https://rocksdb.org/blog/2021/05/26/integrated-blob-db.html diff --git a/src/Nethermind/Nethermind.Init/MemoryHintMan.cs b/src/Nethermind/Nethermind.Init/MemoryHintMan.cs index aa22c204598..c5b47d218ba 100644 --- a/src/Nethermind/Nethermind.Init/MemoryHintMan.cs +++ b/src/Nethermind/Nethermind.Init/MemoryHintMan.cs @@ -171,49 +171,49 @@ private void UpdateDbConfig(uint cpuCount, ISyncConfig syncConfig, IDbConfig dbC DbMemory = _remainingMemory; long remaining = DbMemory; - DbNeeds dbNeeds = GetHeaderNeeds(cpuCount, syncConfig); + DbNeeds dbNeeds = GetHeaderNeeds(cpuCount); DbGets dbGets = GiveItWhatYouCan(dbNeeds, DbMemory, remaining); remaining -= dbGets.CacheMem + dbGets.Buffers * dbGets.SingleBufferMem; dbConfig.HeadersDbWriteBufferNumber = dbGets.Buffers; dbConfig.HeadersDbWriteBufferSize = (ulong)dbGets.SingleBufferMem; dbConfig.HeadersDbBlockCacheSize = (ulong)dbGets.CacheMem; - dbNeeds = GetBlocksNeeds(cpuCount, syncConfig); + dbNeeds = GetBlocksNeeds(cpuCount); dbGets = GiveItWhatYouCan(dbNeeds, DbMemory, remaining); remaining -= dbGets.CacheMem + dbGets.Buffers * dbGets.SingleBufferMem; dbConfig.BlocksDbWriteBufferNumber = dbGets.Buffers; dbConfig.BlocksDbWriteBufferSize = (ulong)dbGets.SingleBufferMem; dbConfig.BlocksDbBlockCacheSize = (ulong)dbGets.CacheMem; - dbNeeds = GetBlockInfosNeeds(cpuCount, syncConfig); + dbNeeds = GetBlockInfosNeeds(cpuCount); dbGets = GiveItWhatYouCan(dbNeeds, DbMemory, remaining); remaining -= dbGets.CacheMem + dbGets.Buffers * dbGets.SingleBufferMem; dbConfig.BlockInfosDbWriteBufferNumber = dbGets.Buffers; dbConfig.BlockInfosDbWriteBufferSize = (ulong)dbGets.SingleBufferMem; dbConfig.BlockInfosDbBlockCacheSize = (ulong)dbGets.CacheMem; - dbNeeds = GetReceiptsNeeds(cpuCount, syncConfig); + dbNeeds = GetReceiptsNeeds(cpuCount); dbGets = GiveItWhatYouCan(dbNeeds, DbMemory, remaining); remaining -= dbGets.CacheMem + dbGets.Buffers * dbGets.SingleBufferMem; dbConfig.ReceiptsDbWriteBufferNumber = dbGets.Buffers; dbConfig.ReceiptsDbWriteBufferSize = (ulong)dbGets.SingleBufferMem; dbConfig.ReceiptsDbBlockCacheSize = (ulong)dbGets.CacheMem; - dbNeeds = GetCodeNeeds(cpuCount, syncConfig); + dbNeeds = GetCodeNeeds(cpuCount); dbGets = GiveItWhatYouCan(dbNeeds, DbMemory, remaining); remaining -= dbGets.CacheMem + dbGets.Buffers * dbGets.SingleBufferMem; dbConfig.CodeDbWriteBufferNumber = dbGets.Buffers; dbConfig.CodeDbWriteBufferSize = (ulong)dbGets.SingleBufferMem; dbConfig.CodeDbBlockCacheSize = (ulong)dbGets.CacheMem; - dbNeeds = GetPendingTxNeeds(cpuCount, syncConfig); + dbNeeds = GetPendingTxNeeds(cpuCount); dbGets = GiveItWhatYouCan(dbNeeds, DbMemory, remaining); remaining -= dbGets.CacheMem + dbGets.Buffers * dbGets.SingleBufferMem; dbConfig.PendingTxsDbWriteBufferNumber = dbGets.Buffers; dbConfig.PendingTxsDbWriteBufferSize = (ulong)dbGets.SingleBufferMem; dbConfig.PendingTxsDbBlockCacheSize = (ulong)dbGets.CacheMem; - dbNeeds = GetStateNeeds(cpuCount, syncConfig); + dbNeeds = GetStateNeeds(cpuCount); dbGets = GiveItWhatYouCan(dbNeeds, DbMemory, remaining); remaining -= dbGets.CacheMem + dbGets.Buffers * dbGets.SingleBufferMem; dbConfig.StateDbWriteBufferNumber = dbGets.Buffers; @@ -239,7 +239,7 @@ private DbGets GiveItWhatYouCan(DbNeeds dbNeeds, long memoryHint, long remaining long maxWantedMemory = Math.Max(minMemory, (long)(memoryHint * maxPercentage)); long availableDynamic = minMemory >= maxWantedMemory ? 0L : maxWantedMemory - minMemory; - long availableForBuffer = (long)(availableDynamic * 0.05m); + long availableForBuffer = (long)(availableDynamic * 0.2m); long bufferDynamic = Math.Min(maxBufferMem, availableForBuffer); long bufferMem = minBufferMem + bufferDynamic; long cacheDynamic = availableDynamic - bufferDynamic; @@ -293,9 +293,9 @@ public DbNeeds( public decimal PreferredMemoryPercentage { get; set; } } - private DbNeeds GetStateNeeds(uint cpuCount, ISyncConfig syncConfig) + private DbNeeds GetStateNeeds(uint cpuCount) { - uint preferredBuffers = Math.Min(cpuCount, syncConfig.FastSync ? 8u : 4u); + uint preferredBuffers = Math.Min(cpuCount, 2u); // remove optimize for point lookup here? return new DbNeeds( preferredBuffers, @@ -306,9 +306,9 @@ private DbNeeds GetStateNeeds(uint cpuCount, ISyncConfig syncConfig) 1m); // db memory % } - private DbNeeds GetBlockInfosNeeds(uint cpuCount, ISyncConfig syncConfig) + private DbNeeds GetBlockInfosNeeds(uint cpuCount) { - uint preferredBuffers = Math.Min(cpuCount, syncConfig.FastBlocks ? 4u : 2u); + uint preferredBuffers = Math.Min(cpuCount, 2u); // remove optimize for point lookup here? return new DbNeeds( preferredBuffers, @@ -319,21 +319,21 @@ private DbNeeds GetBlockInfosNeeds(uint cpuCount, ISyncConfig syncConfig) 0.02m); // db memory % } - private DbNeeds GetHeaderNeeds(uint cpuCount, ISyncConfig syncConfig) + private DbNeeds GetHeaderNeeds(uint cpuCount) { - uint preferredBuffers = Math.Min(cpuCount, syncConfig.FastBlocks ? 4u : 2u); + uint preferredBuffers = Math.Min(cpuCount, 2u); return new DbNeeds( preferredBuffers, - 1.MB(), // min buffer size - 8.MB(), // max buffer size + 4.MB(), // min buffer size + 16.MB(), // max buffer size 1.MB(), // min block cache 1.GB(), // max block cache - 0.02m); // db memory % + 0.05m); // db memory % } - private DbNeeds GetBlocksNeeds(uint cpuCount, ISyncConfig syncConfig) + private DbNeeds GetBlocksNeeds(uint cpuCount) { - uint preferredBuffers = Math.Min(cpuCount, syncConfig.FastBlocks ? 4u : 2u); + uint preferredBuffers = Math.Min(cpuCount, 2u); return new DbNeeds( preferredBuffers, 4.MB(), // min buffer size @@ -343,9 +343,9 @@ private DbNeeds GetBlocksNeeds(uint cpuCount, ISyncConfig syncConfig) 0.04m); // db memory % } - private DbNeeds GetReceiptsNeeds(uint cpuCount, ISyncConfig syncConfig) + private DbNeeds GetReceiptsNeeds(uint cpuCount) { - uint preferredBuffers = Math.Min(cpuCount, syncConfig.FastBlocks ? 4u : 2u); + uint preferredBuffers = Math.Min(cpuCount, 2u); return new DbNeeds( preferredBuffers, 2.MB(), // min buffer size @@ -355,7 +355,7 @@ private DbNeeds GetReceiptsNeeds(uint cpuCount, ISyncConfig syncConfig) 0.01m); // db memory % } - private DbNeeds GetPendingTxNeeds(uint cpuCount, ISyncConfig syncConfig) + private DbNeeds GetPendingTxNeeds(uint cpuCount) { return new DbNeeds( 4, @@ -366,9 +366,9 @@ private DbNeeds GetPendingTxNeeds(uint cpuCount, ISyncConfig syncConfig) 0.01m); // db memory % } - private DbNeeds GetCodeNeeds(uint cpuCount, ISyncConfig syncConfig) + private DbNeeds GetCodeNeeds(uint cpuCount) { - uint preferredBuffers = Math.Min(cpuCount, syncConfig.FastSync ? 4u : 2u); + uint preferredBuffers = Math.Min(cpuCount, 2u); return new DbNeeds( preferredBuffers, 1.MB(), // min buffer size From d938888aa62f0e89cb0eb0737d846fe080c17ca0 Mon Sep 17 00:00:00 2001 From: Lautaro Emanuel <31224949+emlautarom1@users.noreply.github.com> Date: Tue, 26 Sep 2023 08:44:28 -0300 Subject: [PATCH 36/50] Remove warnings from `Nethermind.Synchronization.Test` (#6128) * Cleanup 'SyncDispatcherTests' * Cleanup 'StateSyncFeedTestsBase' * Remove commented out code * Cleanup 'BlockDownloaderTests' * Relax null constraints - It seems that we might pass some nulls here * Cleanup 'SyncDbTunerTests' * Cleanup 'BySpeedStrategyTests' * Remove unused class * Cleanup 'FastHeadersSyncTests' * Relax null constraints * Cleanup 'OldStyleFullSynchronizerTests' * Cleanup 'TrieScenarios' * Cleanup 'ReceiptsSyncFeedTests' * Cleanup 'SyncServerTests' * Cleanup 'ProgressTrackerTests' * Relax null constraints * Cleanup 'StateSyncFeedTests' * More cleanup on 'StateSyncFeedTests' * Remove unused var * Remove commented out code * Cleanup 'MultiSyncModeSelectorFastSyncTests' * Cleanup 'StateSyncDispatcherTests' * Cleanup 'SyncPeerMock' * Cleanup 'StateSyncFeedHealingTests' * Cleanup 'StateSyncDispatcherTester' * Cleanup 'SynchronizerTests' * Use 'GetAwaiter().GetResult()' to run synchronously * Cleanup 'MultiSyncModeSelectorTestsBase' * Cleanup 'SyncProgressResolverTests' * Cleanup 'SyncReportTest' * Cleanup 'SyncPeerPoolTests' * Remove nullable annotation * Cleanup 'SyncPeersReportTest' * Cleanup 'BlockDownloaderTests' * Fix 'events not used' warning * Fix compound assignment and nullability * Treat warnings as errors * Formatting --- .../BySpeedStrategyTests.cs | 39 +-- .../BlockDownloaderTests.Merge.cs | 98 +++--- .../BlockDownloaderTests.cs | 302 +++++++++--------- .../DbTuner/SyncDbTunerTests.cs | 17 +- .../FastBlocks/FastHeadersSyncTests.cs | 219 +++++++++---- .../FastSync/ReceiptsSyncFeedTests.cs | 62 ++-- .../StateSyncDispatcherTester.cs | 2 +- .../StateSyncDispatcherTests.cs | 44 +-- .../FastSync/StateSyncFeedHealingTests.cs | 12 +- .../FastSync/StateSyncFeedTests.cs | 84 ++--- .../FastSync/StateSyncFeedTestsBase.cs | 188 +++++------ .../LatencySyncPeerMock.cs | 117 ------- .../Nethermind.Synchronization.Test.csproj | 1 + .../OldStyleFullSynchronizerTests.cs | 92 +++--- .../MultiSyncModeSelectorFastSyncTests.cs | 4 +- .../MultiSyncModeSelectorTests.Scenario.cs | 114 ++++--- .../ParallelSync/SyncDispatcherTests.cs | 29 +- .../SnapSync/ProgressTrackerTests.cs | 14 +- .../SyncPeerMock.cs | 6 +- .../SyncPeerPoolTests.cs | 102 +++--- .../SyncPeersReportTests.cs | 39 ++- .../SyncProgressResolverTests.cs | 131 ++++---- .../SyncReportTest.cs | 46 +-- .../SyncServerTests.cs | 138 +++++--- .../SynchronizerTests.cs | 77 ++--- .../TrieScenarios.cs | 88 ++--- .../Blocks/BlockDownloader.cs | 5 +- .../FastSync/DetailedProgress.cs | 44 +-- .../FastSync/StateSyncFeed.cs | 2 +- .../Peers/SyncPeersReport.cs | 2 +- 30 files changed, 1079 insertions(+), 1039 deletions(-) delete mode 100644 src/Nethermind/Nethermind.Synchronization.Test/LatencySyncPeerMock.cs diff --git a/src/Nethermind/Nethermind.Synchronization.Test/AllocationStrategies/BySpeedStrategyTests.cs b/src/Nethermind/Nethermind.Synchronization.Test/AllocationStrategies/BySpeedStrategyTests.cs index 288cbcf02f6..09df2772e7b 100644 --- a/src/Nethermind/Nethermind.Synchronization.Test/AllocationStrategies/BySpeedStrategyTests.cs +++ b/src/Nethermind/Nethermind.Synchronization.Test/AllocationStrategies/BySpeedStrategyTests.cs @@ -20,7 +20,7 @@ namespace Nethermind.Synchronization.Test.AllocationStrategies; public class BySpeedStrategyTests { - private static PublicKey TestPublicKey = new(Bytes.FromHexString( + private static PublicKey TestPublicKey { get; } = new(Bytes.FromHexString( "0x13a1107b6f78a4977222d2d5a4cd05a8a042b75222c8ec99129b83793eda3d214208d4e835617512fc8d148d3d1b4d89530861644f531675b1fb64b785c6c152")); [TestCase(1, 0, 0, 2)] @@ -33,7 +33,7 @@ public class BySpeedStrategyTests [TestCase(1, 0.1, 0, 2)] public void TestShouldSelectHighestSpeed(int? currentPeerIdx, decimal minDiffPercentageForSpeedSwitch, int minDiffSpeed, int expectedSelectedPeerIdx) { - long[] peerSpeeds = new long[] + long[] peerSpeeds = { 100, 90, @@ -43,19 +43,16 @@ public void TestShouldSelectHighestSpeed(int? currentPeerIdx, decimal minDiffPer INodeStatsManager nodeStatsManager = Substitute.For(); - List peers = new(); - for (int i = 0; i < peerSpeeds.Length; i++) - { - PeerInfo pInfo = CreatePeerInfoWithSpeed(peerSpeeds[i], nodeStatsManager); - peers.Add(pInfo); - } + List peers = peerSpeeds + .Select(peerSpeed => CreatePeerInfoWithSpeed(peerSpeed, nodeStatsManager)) + .ToList(); BySpeedStrategy strategy = new(TransferSpeedType.Bodies, true, minDiffPercentageForSpeedSwitch, minDiffSpeed, 0, 0); PeerInfo? currentPeer = null; if (currentPeerIdx is not null) currentPeer = peers[currentPeerIdx.Value]; - PeerInfo? selectedPeer = strategy.Allocate(currentPeer, peers, nodeStatsManager, Build.A.BlockTree().TestObject); + PeerInfo selectedPeer = strategy.Allocate(currentPeer, peers, nodeStatsManager, Build.A.BlockTree().TestObject)!; int selectedPeerIdx = peers.IndexOf(selectedPeer); selectedPeerIdx.Should().Be(expectedSelectedPeerIdx); @@ -76,16 +73,13 @@ public void TestMinimumKnownSpeed(int peerWithKnownSpeed, int peerWithUnknownSpe INodeStatsManager nodeStatsManager = Substitute.For(); - List peers = new(); - for (int i = 0; i < peerSpeeds.Length; i++) - { - PeerInfo pInfo = CreatePeerInfoWithSpeed(peerSpeeds[i], nodeStatsManager); - peers.Add(pInfo); - } + List peers = peerSpeeds + .Select(peerSpeed => CreatePeerInfoWithSpeed(peerSpeed, nodeStatsManager)) + .ToList(); BySpeedStrategy strategy = new(TransferSpeedType.Bodies, true, 0, 0, 0, desiredKnownPeer); - PeerInfo? selectedPeer = strategy.Allocate(null, peers, nodeStatsManager, Build.A.BlockTree().TestObject); + PeerInfo selectedPeer = strategy.Allocate(null, peers, nodeStatsManager, Build.A.BlockTree().TestObject)!; int selectedPeerIdx = peers.IndexOf(selectedPeer); if (pickedNewPeer) @@ -110,7 +104,7 @@ public void TestWhenSameSpeed_RandomlyTryOtherPeer() BySpeedStrategy strategy = new(TransferSpeedType.Bodies, true, 0, 0, 0, 0); - PeerInfo? selectedPeer = strategy.Allocate(null, peers, nodeStatsManager, Build.A.BlockTree().TestObject); + PeerInfo selectedPeer = strategy.Allocate(null, peers, nodeStatsManager, Build.A.BlockTree().TestObject)!; int selectedPeerIdx = peers.IndexOf(selectedPeer); selectedPeerIdx.Should().BeGreaterThan(50); } @@ -128,12 +122,9 @@ public void TestRecalculateSpeedProbability(int peerWithKnownSpeed, int peerWith INodeStatsManager nodeStatsManager = Substitute.For(); - List peers = new(); - for (int i = 0; i < peerSpeeds.Length; i++) - { - PeerInfo pInfo = CreatePeerInfoWithSpeed(peerSpeeds[i], nodeStatsManager); - peers.Add(pInfo); - } + List peers = peerSpeeds + .Select(peerSpeed => CreatePeerInfoWithSpeed(peerSpeed, nodeStatsManager)) + .ToList(); BySpeedStrategy strategy = new(TransferSpeedType.Bodies, true, 0, 0, recalculateSpeedProbability, 0); @@ -142,7 +133,7 @@ public void TestRecalculateSpeedProbability(int peerWithKnownSpeed, int peerWith for (int i = 0; i < 100; i++) { - PeerInfo? selectedPeer = strategy.Allocate(null, peers, nodeStatsManager, Build.A.BlockTree().TestObject); + PeerInfo selectedPeer = strategy.Allocate(null, peers, nodeStatsManager, Build.A.BlockTree().TestObject)!; int selectedPeerIdx = peers.IndexOf(selectedPeer); if (peerSpeeds[selectedPeerIdx] is null) { diff --git a/src/Nethermind/Nethermind.Synchronization.Test/BlockDownloaderTests.Merge.cs b/src/Nethermind/Nethermind.Synchronization.Test/BlockDownloaderTests.Merge.cs index 74447c505c0..14596b34c35 100644 --- a/src/Nethermind/Nethermind.Synchronization.Test/BlockDownloaderTests.Merge.cs +++ b/src/Nethermind/Nethermind.Synchronization.Test/BlockDownloaderTests.Merge.cs @@ -50,12 +50,14 @@ public async Task Merge_Happy_path(long pivot, long headNumber, int options, int .InsertBeaconHeaders(4, pivot - 1) .InsertBeaconBlocks(pivot + 1, insertedBeaconBlocks, BlockTreeTests.BlockTreeTestScenario.ScenarioBuilder.TotalDifficultyMode.Null); BlockTree syncedTree = blockTrees.SyncedTree; - PostMergeContext ctx = new(); - ctx.BlockTreeScenario = blockTrees; + PostMergeContext ctx = new() + { + BlockTreeScenario = blockTrees, + }; DownloaderOptions downloaderOptions = (DownloaderOptions)options; bool withReceipts = downloaderOptions == DownloaderOptions.WithReceipts; - ctx.MergeConfig = new MergeConfig() { TerminalTotalDifficulty = "0" }; + ctx.MergeConfig = new MergeConfig { TerminalTotalDifficulty = "0" }; ctx.BeaconPivot.EnsurePivot(blockTrees.SyncedTree.FindHeader(pivot, BlockTreeLookupOptions.None)); ctx.BeaconPivot.ProcessDestination = blockTrees.SyncedTree.FindHeader(pivot, BlockTreeLookupOptions.None); @@ -70,7 +72,7 @@ public async Task Merge_Happy_path(long pivot, long headNumber, int options, int SyncPeerMock syncPeer = new(syncedTree, withReceipts, responseOptions, 16000000); PeerInfo peerInfo = new(syncPeer); await downloader.DownloadBlocks(peerInfo, new BlocksRequest(downloaderOptions), CancellationToken.None); - ctx.BlockTree.BestSuggestedHeader.Number.Should().Be(Math.Max(0, insertedBeaconBlocks)); + ctx.BlockTree.BestSuggestedHeader!.Number.Should().Be(Math.Max(0, insertedBeaconBlocks)); ctx.BlockTree.BestKnownNumber.Should().Be(Math.Max(0, insertedBeaconBlocks)); int receiptCount = 0; @@ -97,13 +99,14 @@ public async Task Can_reach_terminal_block(long headNumber, int options, int thr .InsertBeaconPivot(16) .InsertBeaconHeaders(4, 15) .InsertBeaconBlocks(17, headNumber, BlockTreeTests.BlockTreeTestScenario.ScenarioBuilder.TotalDifficultyMode.Null); - BlockTree notSyncedTree = blockTrees.NotSyncedTree; BlockTree syncedTree = blockTrees.SyncedTree; - PostMergeContext ctx = new(); - ctx.BlockTreeScenario = blockTrees; + PostMergeContext ctx = new() + { + BlockTreeScenario = blockTrees, + }; DownloaderOptions downloaderOptions = (DownloaderOptions)options; - ctx.MergeConfig = new MergeConfig() { TerminalTotalDifficulty = $"{ttd}" }; + ctx.MergeConfig = new MergeConfig { TerminalTotalDifficulty = $"{ttd}" }; if (withBeaconPivot) ctx.BeaconPivot.EnsurePivot(blockTrees.SyncedTree.FindHeader(16, BlockTreeLookupOptions.None)); @@ -134,11 +137,13 @@ public async Task IfNoBeaconPivot_thenStopAtPoS(long headNumber, int options, in BlockTree notSyncedTree = blockTrees.NotSyncedTree; BlockTree syncedTree = blockTrees.SyncedTree; - PostMergeContext ctx = new(); - ctx.BlockTreeScenario = blockTrees; + PostMergeContext ctx = new() + { + BlockTreeScenario = blockTrees, + }; DownloaderOptions downloaderOptions = (DownloaderOptions)options; - ctx.MergeConfig = new MergeConfig() { TerminalTotalDifficulty = $"{ttd}" }; + ctx.MergeConfig = new MergeConfig { TerminalTotalDifficulty = $"{ttd}" }; if (withBeaconPivot) ctx.BeaconPivot.EnsurePivot(blockTrees.SyncedTree.FindHeader(16, BlockTreeLookupOptions.None)); @@ -161,8 +166,10 @@ public async Task WillSkipBlocksToIgnore(long pivot, long headNumber, int blocks .InsertBeaconHeaders(4, pivot - 1); BlockTree syncedTree = blockTrees.SyncedTree; - PostMergeContext ctx = new(); - ctx.BlockTreeScenario = blockTrees; + PostMergeContext ctx = new() + { + BlockTreeScenario = blockTrees, + }; ctx.BeaconPivot.EnsurePivot(blockTrees.SyncedTree.FindHeader(pivot, BlockTreeLookupOptions.None)); ctx.BeaconPivot.ProcessDestination = blockTrees.SyncedTree.FindHeader(pivot, BlockTreeLookupOptions.None); @@ -194,11 +201,13 @@ public async Task Recalculate_header_total_difficulty() .InsertOtherChainToMain(notSyncedTree, 1, 3) // Need to have the header inserted to LRU which mean we need to move the head forward .InsertBeaconHeaders(1, 3, tdMode: BlockTreeTests.BlockTreeTestScenario.ScenarioBuilder.TotalDifficultyMode.Null); - PostMergeContext ctx = new(); - ctx.BlockTreeScenario = blockTrees; - ctx.MergeConfig = new MergeConfig() { TerminalTotalDifficulty = $"{ttd}" }; + PostMergeContext ctx = new() + { + BlockTreeScenario = blockTrees, + MergeConfig = new MergeConfig { TerminalTotalDifficulty = $"{ttd}" }, + }; - BlockHeader lastHeader = syncedTree.FindHeader(3, BlockTreeLookupOptions.None); + BlockHeader lastHeader = syncedTree.FindHeader(3, BlockTreeLookupOptions.None)!; // Because the FindHeader recalculated the TD. lastHeader.TotalDifficulty = 0; @@ -221,14 +230,14 @@ public async Task Recalculate_header_total_difficulty() Block? lastBestSuggestedBlock = null; - notSyncedTree.NewBestSuggestedBlock += (sender, args) => + notSyncedTree.NewBestSuggestedBlock += (_, args) => { lastBestSuggestedBlock = args.Block; }; await downloader.DownloadBlocks(peerInfo, new BlocksRequest(DownloaderOptions.Process | DownloaderOptions.WithBodies | DownloaderOptions.WithReceipts), CancellationToken.None); - lastBestSuggestedBlock.Hash.Should().Be(lastHeader.Hash); + lastBestSuggestedBlock!.Hash.Should().Be(lastHeader.Hash!); lastBestSuggestedBlock.TotalDifficulty.Should().NotBeEquivalentTo(UInt256.Zero); } @@ -239,16 +248,18 @@ public async Task Does_not_deadlock_on_replace_peer() .GoesLikeThis() .WithBlockTrees(0, 4) .InsertBeaconPivot(3); - PostMergeContext ctx = new(); - ctx.MergeConfig = new MergeConfig() { TerminalTotalDifficulty = "0" }; - ctx.BlockTreeScenario = blockTrees; + PostMergeContext ctx = new() + { + MergeConfig = new MergeConfig { TerminalTotalDifficulty = "0" }, + BlockTreeScenario = blockTrees, + }; ctx.BeaconPivot.EnsurePivot(blockTrees.SyncedTree.FindHeader(3, BlockTreeLookupOptions.None)); ManualResetEventSlim chainLevelHelperBlocker = new ManualResetEventSlim(false); IChainLevelHelper chainLevelHelper = Substitute.For(); chainLevelHelper - .When((clh) => clh.GetNextHeaders(Arg.Any(), Arg.Any())) - .Do((args) => + .When(clh => clh.GetNextHeaders(Arg.Any(), Arg.Any())) + .Do(_ => { chainLevelHelperBlocker.Wait(); }); @@ -275,7 +286,7 @@ public async Task Does_not_deadlock_on_replace_peer() CancellationTokenSource cts = new CancellationTokenSource(); - Task ignored = ctx.Dispatcher.Start(cts.Token); + Task _ = ctx.Dispatcher.Start(cts.Token); await Task.Delay(TimeSpan.FromMilliseconds(100)); // Feed should activate and allocate the first peer @@ -307,7 +318,7 @@ public async Task Does_not_deadlock_on_replace_peer() } [Test] - public async Task No_old_bodies_and_receipts() + public void No_old_bodies_and_receipts() { BlockTreeTests.BlockTreeTestScenario.ScenarioBuilder blockTrees = BlockTreeTests.BlockTreeTestScenario .GoesLikeThis() @@ -315,8 +326,10 @@ public async Task No_old_bodies_and_receipts() .InsertBeaconPivot(64) .InsertBeaconHeaders(4, 128); BlockTree syncedTree = blockTrees.SyncedTree; - PostMergeContext ctx = new(); - ctx.BlockTreeScenario = blockTrees; + PostMergeContext ctx = new() + { + BlockTreeScenario = blockTrees, + }; ctx.Feed = new FastSyncFeed(ctx.SyncModeSelector, new SyncConfig @@ -324,7 +337,7 @@ public async Task No_old_bodies_and_receipts() NonValidatorNode = true, DownloadBodiesInFastSync = false, DownloadReceiptsInFastSync = false - }, LimboLogs.Instance); + }, LimboLogs.Instance)!; ctx.BeaconPivot.EnsurePivot(blockTrees.SyncedTree.FindHeader(64, BlockTreeLookupOptions.None)); @@ -346,7 +359,7 @@ public async Task No_old_bodies_and_receipts() ctx.Feed.Activate(); CancellationTokenSource cts = new(); - ctx.Dispatcher.Start(cts.Token); + Task _ = ctx.Dispatcher.Start(cts.Token); Assert.That( () => ctx.BlockTree.BestKnownNumber, @@ -389,15 +402,15 @@ public async Task BlockDownloader_works_correctly_with_withdrawals(int options) .Returns(async ci => await syncPeerInternal.GetReceipts(ci.ArgAt>(0), ci.ArgAt(1))); - syncPeer.TotalDifficulty.Returns(ci => syncPeerInternal.TotalDifficulty); - syncPeer.HeadHash.Returns(ci => syncPeerInternal.HeadHash); - syncPeer.HeadNumber.Returns(ci => syncPeerInternal.HeadNumber); + syncPeer.TotalDifficulty.Returns(_ => syncPeerInternal.TotalDifficulty); + syncPeer.HeadHash.Returns(_ => syncPeerInternal.HeadHash); + syncPeer.HeadNumber.Returns(_ => syncPeerInternal.HeadNumber); PeerInfo peerInfo = new(syncPeer); int threshold = 2; await downloader.DownloadHeaders(peerInfo, new BlocksRequest(DownloaderOptions.None, threshold), CancellationToken.None); - ctx.BlockTree.BestSuggestedHeader.Number.Should().Be(Math.Max(0, Math.Min(headNumber, headNumber - threshold))); + ctx.BlockTree.BestSuggestedHeader!.Number.Should().Be(Math.Max(0, Math.Min(headNumber, headNumber - threshold))); syncPeerInternal.ExtendTree(chainLength * 2); Func action = async () => await downloader.DownloadBlocks(peerInfo, new BlocksRequest(downloaderOptions), CancellationToken.None); @@ -409,7 +422,7 @@ class PostMergeContext : Context { protected override ISpecProvider SpecProvider => _specProvider ??= new MainnetSpecProvider(); // PoSSwitcher changes TTD, so can't use MainnetSpecProvider.Instance - private BlockTreeTests.BlockTreeTestScenario.ScenarioBuilder? _blockTreeScenario = null; + private BlockTreeTests.BlockTreeTestScenario.ScenarioBuilder? _blockTreeScenario; public BlockTreeTests.BlockTreeTestScenario.ScenarioBuilder BlockTreeScenario { @@ -421,21 +434,22 @@ public BlockTreeTests.BlockTreeTestScenario.ScenarioBuilder BlockTreeScenario public override IBlockTree BlockTree => _blockTreeScenario?.NotSyncedTree ?? base.BlockTree; - private MemDb? _metadataDb = null; - private MemDb MetadataDb => (_metadataDb ?? _blockTreeScenario?.NotSyncedTreeBuilder?.MetadataDb) ?? (_metadataDb ??= new MemDb()); + private MemDb? _metadataDb; + private MemDb MetadataDb => (_metadataDb ?? _blockTreeScenario?.NotSyncedTreeBuilder.MetadataDb) ?? (_metadataDb ??= new MemDb()); - private MergeConfig _mergeConfig; + private MergeConfig? _mergeConfig; public MergeConfig MergeConfig { - get => _mergeConfig ??= new MergeConfig() { TerminalTotalDifficulty = "58750000000000000000000" }; // Main block downloader test assume pre-merge + get => _mergeConfig ??= new MergeConfig + { TerminalTotalDifficulty = "58750000000000000000000" }; // Main block downloader test assume pre-merge set => _mergeConfig = value; } - private BeaconPivot? _beaconPivot = null; + private BeaconPivot? _beaconPivot; public BeaconPivot BeaconPivot => _beaconPivot ??= new(new SyncConfig(), MetadataDb, BlockTree, LimboLogs.Instance); - private PoSSwitcher? _posSwitcher = null; + private PoSSwitcher? _posSwitcher; public PoSSwitcher PosSwitcher => _posSwitcher ??= new( MergeConfig, @@ -448,7 +462,7 @@ public MergeConfig MergeConfig protected override IBetterPeerStrategy BetterPeerStrategy => _betterPeerStrategy ??= new MergeBetterPeerStrategy(new TotalDifficultyBetterPeerStrategy(LimboLogs.Instance), PosSwitcher, BeaconPivot, LimboLogs.Instance); - private IChainLevelHelper? _chainLevelHelper = null; + private IChainLevelHelper? _chainLevelHelper; public IChainLevelHelper ChainLevelHelper { diff --git a/src/Nethermind/Nethermind.Synchronization.Test/BlockDownloaderTests.cs b/src/Nethermind/Nethermind.Synchronization.Test/BlockDownloaderTests.cs index e292c1fa10f..37157f43f0f 100644 --- a/src/Nethermind/Nethermind.Synchronization.Test/BlockDownloaderTests.cs +++ b/src/Nethermind/Nethermind.Synchronization.Test/BlockDownloaderTests.cs @@ -84,12 +84,12 @@ public async Task Happy_path(long headNumber, int options, int threshold) await downloader.DownloadHeaders(peerInfo, new BlocksRequest(DownloaderOptions.None, threshold), CancellationToken.None); - ctx.BlockTree!.BestSuggestedHeader!.Number.Should().Be(Math.Max(0, Math.Min(headNumber, headNumber - threshold))); + ctx.BlockTree.BestSuggestedHeader!.Number.Should().Be(Math.Max(0, Math.Min(headNumber, headNumber - threshold))); syncPeer.ExtendTree(chainLength * 2); await downloader.DownloadBlocks(peerInfo, new BlocksRequest(downloaderOptions), CancellationToken.None); - ctx.BlockTree!.BestSuggestedHeader!.Number.Should().Be(Math.Max(0, peerInfo.HeadNumber)); - ctx.BlockTree.IsMainChain(ctx.BlockTree!.BestSuggestedHeader!.Hash!).Should().Be(downloaderOptions != DownloaderOptions.Process); + ctx.BlockTree.BestSuggestedHeader!.Number.Should().Be(Math.Max(0, peerInfo.HeadNumber)); + ctx.BlockTree.IsMainChain(ctx.BlockTree.BestSuggestedHeader!.Hash!).Should().Be(downloaderOptions != DownloaderOptions.Process); int receiptCount = 0; for (int i = (int)Math.Max(0, headNumber - threshold); i < peerInfo.HeadNumber; i++) @@ -106,8 +106,10 @@ public async Task Happy_path(long headNumber, int options, int threshold) [Test] public async Task Ancestor_lookup_simple() { - Context ctx = new(); - ctx.BlockTree = Build.A.BlockTree().OfChainLength(1024).TestObject; + Context ctx = new() + { + BlockTree = Build.A.BlockTree().OfChainLength(1024).TestObject, + }; BlockDownloader downloader = ctx.BlockDownloader; Response blockResponseOptions = Response.AllCorrect; @@ -115,7 +117,7 @@ public async Task Ancestor_lookup_simple() PeerInfo peerInfo = new(syncPeer); - Block block1024 = Build.A.Block.WithParent(ctx.BlockTree.Head).WithDifficulty(ctx.BlockTree.Head.Difficulty + 1).TestObject; + Block block1024 = Build.A.Block.WithParent(ctx.BlockTree.Head!).WithDifficulty(ctx.BlockTree.Head!.Difficulty + 1).TestObject; Block block1025 = Build.A.Block.WithParent(block1024).WithDifficulty(block1024.Difficulty + 1).TestObject; Block block1026 = Build.A.Block.WithParent(block1025).WithDifficulty(block1025.Difficulty + 1).TestObject; ctx.BlockTree.SuggestBlock(block1024); @@ -124,26 +126,28 @@ public async Task Ancestor_lookup_simple() for (int i = 0; i < 1023; i++) { - Assert.That(syncPeer.BlockTree.FindBlock(i, BlockTreeLookupOptions.None).Hash, Is.EqualTo(ctx.BlockTree.FindBlock(i, BlockTreeLookupOptions.None).Hash), i.ToString()); + Assert.That(syncPeer.BlockTree.FindBlock(i, BlockTreeLookupOptions.None)!.Hash, Is.EqualTo(ctx.BlockTree.FindBlock(i, BlockTreeLookupOptions.None)!.Hash), i.ToString()); } await downloader.DownloadBlocks(peerInfo, new BlocksRequest(DownloaderOptions.WithReceipts, 0), CancellationToken.None); - ctx.BlockTree.BestSuggestedHeader.Number.Should().Be(peerInfo.HeadNumber); + ctx.BlockTree.BestSuggestedHeader!.Number.Should().Be(peerInfo.HeadNumber); ctx.BlockTree.IsMainChain(ctx.BlockTree.BestSuggestedHeader.GetOrCalculateHash()).Should().Be(true); } [Test] public async Task Ancestor_lookup_headers() { - Context ctx = new(); - ctx.BlockTree = Build.A.BlockTree().OfChainLength(1024).TestObject; + Context ctx = new() + { + BlockTree = Build.A.BlockTree().OfChainLength(1024).TestObject, + }; BlockDownloader downloader = ctx.BlockDownloader; Response responseOptions = Response.AllCorrect; SyncPeerMock syncPeer = new(2048 + 1, false, responseOptions); PeerInfo peerInfo = new(syncPeer); - Block block1024 = Build.A.Block.WithParent(ctx.BlockTree.Head).WithDifficulty(ctx.BlockTree.Head.Difficulty + 1).TestObject; + Block block1024 = Build.A.Block.WithParent(ctx.BlockTree.Head!).WithDifficulty(ctx.BlockTree.Head!.Difficulty + 1).TestObject; Block block1025 = Build.A.Block.WithParent(block1024).WithDifficulty(block1024.Difficulty + 1).TestObject; Block block1026 = Build.A.Block.WithParent(block1025).WithDifficulty(block1025.Difficulty + 1).TestObject; ctx.BlockTree.SuggestBlock(block1024); @@ -152,18 +156,20 @@ public async Task Ancestor_lookup_headers() for (int i = 0; i < 1023; i++) { - Assert.That(syncPeer.BlockTree.FindBlock(i, BlockTreeLookupOptions.None).Hash, Is.EqualTo(ctx.BlockTree.FindBlock(i, BlockTreeLookupOptions.None).Hash), i.ToString()); + Assert.That(syncPeer.BlockTree.FindBlock(i, BlockTreeLookupOptions.None)!.Hash, Is.EqualTo(ctx.BlockTree.FindBlock(i, BlockTreeLookupOptions.None)!.Hash), i.ToString()); } await downloader.DownloadHeaders(peerInfo, new BlocksRequest(), CancellationToken.None); - ctx.BlockTree.BestSuggestedHeader.Number.Should().Be(peerInfo.HeadNumber); + ctx.BlockTree.BestSuggestedHeader!.Number.Should().Be(peerInfo.HeadNumber); } [Test] public void Ancestor_failure() { - Context ctx = new(); - ctx.BlockTree = Build.A.BlockTree().OfChainLength(2048 + 1).TestObject; + Context ctx = new() + { + BlockTree = Build.A.BlockTree().OfChainLength(2048 + 1).TestObject, + }; BlockDownloader downloader = ctx.BlockDownloader; Response blockResponseOptions = Response.AllCorrect; @@ -172,14 +178,16 @@ public void Ancestor_failure() PeerInfo peerInfo = new(syncPeer); Assert.ThrowsAsync(() => downloader.DownloadHeaders(peerInfo, new BlocksRequest(), CancellationToken.None)); - ctx.BlockTree.BestSuggestedHeader.Number.Should().Be(2048); + ctx.BlockTree.BestSuggestedHeader!.Number.Should().Be(2048); } [Test] public void Ancestor_failure_blocks() { - Context ctx = new(); - ctx.BlockTree = Build.A.BlockTree().OfChainLength(2048 + 1).TestObject; + Context ctx = new() + { + BlockTree = Build.A.BlockTree().OfChainLength(2048 + 1).TestObject, + }; BlockDownloader downloader = ctx.BlockDownloader; Response responseOptions = Response.AllCorrect; @@ -188,7 +196,7 @@ public void Ancestor_failure_blocks() PeerInfo peerInfo = new(syncPeer); Assert.ThrowsAsync(() => downloader.DownloadBlocks(peerInfo, new BlocksRequest(), CancellationToken.None)); - ctx.BlockTree.BestSuggestedHeader.Number.Should().Be(2048); + ctx.BlockTree.BestSuggestedHeader!.Number.Should().Be(2048); } [TestCase(32, true)] @@ -217,12 +225,12 @@ public async Task Can_sync_with_peer_when_it_times_out_on_full_batch(int ignored PeerInfo peerInfo = new(syncPeer); - await downloader.DownloadHeaders(peerInfo, new BlocksRequest(DownloaderOptions.WithBodies, ignoredBlocks), CancellationToken.None).ContinueWith(t => { }); + await downloader.DownloadHeaders(peerInfo, new BlocksRequest(DownloaderOptions.WithBodies, ignoredBlocks), CancellationToken.None).ContinueWith(_ => { }); await downloader.DownloadHeaders(peerInfo, new BlocksRequest(DownloaderOptions.WithBodies, ignoredBlocks), CancellationToken.None); - Assert.That(ctx.BlockTree.BestSuggestedHeader.Number, Is.EqualTo(Math.Max(0, peerInfo.HeadNumber - ignoredBlocks))); + Assert.That(ctx.BlockTree.BestSuggestedHeader!.Number, Is.EqualTo(Math.Max(0, peerInfo.HeadNumber - ignoredBlocks))); syncPeer.HeadNumber.Returns((int)Math.Ceiling(SyncBatchSize.Max * SyncBatchSize.AdjustmentFactor) + ignoredBlocks); - await downloader.DownloadBlocks(peerInfo, new BlocksRequest(), CancellationToken.None).ContinueWith(t => { }); + await downloader.DownloadBlocks(peerInfo, new BlocksRequest(), CancellationToken.None).ContinueWith(continuationAction: _ => { }); await downloader.DownloadBlocks(peerInfo, new BlocksRequest(), CancellationToken.None); Assert.That(ctx.BlockTree.BestSuggestedHeader.Number, Is.EqualTo(Math.Max(0, peerInfo.HeadNumber))); } @@ -261,11 +269,11 @@ public async Task Can_sync_partially_when_only_some_bodies_is_available(int bloc BlockBody?[] response = ctx.ResponseBuilder .BuildBlocksResponse(blockHashes, Response.AllCorrect | Response.WithTransactions & ~Response.AllKnown) .Result - .Bodies; + .Bodies!; if (response.Length < minResponseLength) { - BlockBody[] nullPaddedResponse = new BlockBody[minResponseLength]; + BlockBody?[] nullPaddedResponse = new BlockBody[minResponseLength]; for (int i = 0; i < response.Length; i++) { nullPaddedResponse[i] = response[i]; @@ -281,8 +289,8 @@ public async Task Can_sync_partially_when_only_some_bodies_is_available(int bloc PeerInfo peerInfo = new(syncPeer); - ctx.BlockTree.BestSuggestedBody.Number.Should().Be(0); - await downloader.DownloadBlocks(peerInfo, new BlocksRequest(DownloaderOptions.Process), CancellationToken.None).ContinueWith(t => { }); + ctx.BlockTree.BestSuggestedBody!.Number.Should().Be(0); + await downloader.DownloadBlocks(peerInfo, new BlocksRequest(DownloaderOptions.Process), CancellationToken.None).ContinueWith(_ => { }); ctx.BlockTree.BestSuggestedBody.Number.Should().Be(availableBlock); } @@ -318,7 +326,7 @@ public async Task Peer_only_advertise_one_header() ISyncPeer syncPeer = Substitute.For(); syncPeer.GetBlockHeaders(Arg.Any(), Arg.Any(), Arg.Any(), Arg.Any()) - .Returns(ci => ctx.ResponseBuilder.BuildHeaderResponse(0, 1, Response.AllCorrect)); + .Returns(_ => ctx.ResponseBuilder.BuildHeaderResponse(0, 1, Response.AllCorrect)); PeerInfo peerInfo = new(syncPeer); syncPeer.TotalDifficulty.Returns(UInt256.MaxValue); @@ -350,7 +358,7 @@ public async Task Peer_sends_just_one_item_when_advertising_more_blocks_but_no_b Task task = downloader.DownloadBlocks(peerInfo, new BlocksRequest(), CancellationToken.None); await task.ContinueWith(t => Assert.False(t.IsFaulted)); - Assert.That(ctx.BlockTree.BestSuggestedHeader.Number, Is.EqualTo(headNumber)); + Assert.That(ctx.BlockTree.BestSuggestedHeader!.Number, Is.EqualTo(headNumber)); } [Test] @@ -385,8 +393,10 @@ public async Task Throws_on_inconsistent_batch() [Test] public async Task Throws_on_invalid_seal() { - Context ctx = new(); - ctx.SealValidator = Always.Invalid; + Context ctx = new() + { + SealValidator = Always.Invalid, + }; BlockDownloader downloader = ctx.BlockDownloader; ISyncPeer syncPeer = Substitute.For(); @@ -404,8 +414,10 @@ public async Task Throws_on_invalid_seal() [Test] public async Task Throws_on_invalid_header() { - Context ctx = new(); - ctx.BlockValidator = Always.Invalid; + Context ctx = new() + { + BlockValidator = Always.Invalid, + }; BlockDownloader downloader = ctx.BlockDownloader; ISyncPeer syncPeer = Substitute.For(); @@ -437,11 +449,6 @@ public bool ValidateSeal(BlockHeader header, bool force) private class SlowHeaderValidator : IBlockValidator { - public bool ValidateHash(BlockHeader header) - { - Thread.Sleep(1000); - return true; - } public bool Validate(BlockHeader header, BlockHeader? parent, bool isUncle) { @@ -486,8 +493,10 @@ public bool ValidateOrphanedBlock(Block block, out string? error) [Ignore("Fails OneLoggerLogManager Travis only")] public async Task Can_cancel_seal_validation() { - Context ctx = new(); - ctx.SealValidator = new SlowSealValidator(); + Context ctx = new() + { + SealValidator = new SlowSealValidator(), + }; BlockDownloader downloader = ctx.BlockDownloader; ISyncPeer syncPeer = Substitute.For(); @@ -506,7 +515,6 @@ public async Task Can_cancel_seal_validation() Task task = downloader.DownloadHeaders(peerInfo, new BlocksRequest(DownloaderOptions.WithBodies, 0), cancellation.Token); await task.ContinueWith(t => Assert.True(t.IsCanceled, $"headers {t.Status}")); - // peerInfo.HeadNumber = 2000; syncPeer.HeadNumber.Returns(2000); cancellation = new CancellationTokenSource(); cancellation.CancelAfter(1000); @@ -517,8 +525,10 @@ public async Task Can_cancel_seal_validation() [Test, MaxTime(15000)] public async Task Can_cancel_adding_headers() { - Context ctx = new(); - ctx.BlockValidator = new SlowHeaderValidator(); + Context ctx = new() + { + BlockValidator = new SlowHeaderValidator(), + }; BlockDownloader downloader = ctx.BlockDownloader; ISyncPeer syncPeer = Substitute.For(); @@ -551,8 +561,10 @@ public async Task Validate_always_the_last_seal_and_random_seal_in_the_package() { ISealValidator sealValidator = Substitute.For(); sealValidator.ValidateSeal(Arg.Any(), Arg.Any()).Returns(true); - Context ctx = new(); - ctx.SealValidator = sealValidator; + Context ctx = new() + { + SealValidator = sealValidator, + }; BlockDownloader downloader = ctx.BlockDownloader; BlockHeader[] blockHeaders = await ctx.ResponseBuilder.BuildHeaderResponse(0, 512, Response.AllCorrect); @@ -574,23 +586,23 @@ public async Task Validate_always_the_last_seal_and_random_seal_in_the_package() private class ThrowingPeer : ISyncPeer { - public ThrowingPeer(long number, UInt256 totalDiff, Keccak headHash = null) + public ThrowingPeer(long number, UInt256? totalDiff, Keccak? headHash = null) { HeadNumber = number; - TotalDifficulty = totalDiff; + TotalDifficulty = totalDiff ?? UInt256.MaxValue; HeadHash = headHash ?? Keccak.Zero; } public string Name => "Throwing"; - public Node Node { get; } public string ClientId => "EX peer"; + public Node Node { get; } = null!; + public string ProtocolCode { get; } = null!; + public byte ProtocolVersion { get; } = default; public Keccak HeadHash { get; set; } public long HeadNumber { get; set; } - public UInt256 TotalDifficulty { get; set; } = UInt256.MaxValue; + public UInt256 TotalDifficulty { get; set; } public bool IsInitialized { get; set; } public bool IsPriority { get; set; } - public byte ProtocolVersion { get; } - public string ProtocolCode { get; } public void Disconnect(DisconnectReason reason, string details) { @@ -671,9 +683,8 @@ public async Task Throws_on_block_task_exception() ISyncPeer syncPeer = Substitute.For(); syncPeer.TotalDifficulty.Returns(UInt256.MaxValue); - Task? buildHeadersResponse = null; syncPeer.GetBlockHeaders(Arg.Any(), Arg.Any(), Arg.Any(), Arg.Any()) - .Returns(ci => buildHeadersResponse = ctx.ResponseBuilder.BuildHeaderResponse(ci.ArgAt(0), ci.ArgAt(1), Response.AllCorrect | Response.WithTransactions)); + .Returns(ci => ctx.ResponseBuilder.BuildHeaderResponse(ci.ArgAt(0), ci.ArgAt(1), Response.AllCorrect | Response.WithTransactions)); syncPeer.GetBlockBodies(Arg.Any>(), Arg.Any()) .Returns(Task.FromException(new TimeoutException())); @@ -703,13 +714,11 @@ public async Task Throws_on_receipt_task_exception_when_downloading_receipts(int ISyncPeer syncPeer = Substitute.For(); syncPeer.TotalDifficulty.Returns(UInt256.MaxValue); - Task? buildHeadersResponse = null; syncPeer.GetBlockHeaders(Arg.Any(), Arg.Any(), Arg.Any(), Arg.Any()) - .Returns(ci => buildHeadersResponse = ctx.ResponseBuilder.BuildHeaderResponse(ci.ArgAt(0), ci.ArgAt(1), Response.AllCorrect | Response.WithTransactions)); + .Returns(ci => ctx.ResponseBuilder.BuildHeaderResponse(ci.ArgAt(0), ci.ArgAt(1), Response.AllCorrect | Response.WithTransactions)); - Task? buildBlocksResponse = null; syncPeer.GetBlockBodies(Arg.Any>(), Arg.Any()) - .Returns(ci => buildBlocksResponse = ctx.ResponseBuilder.BuildBlocksResponse(ci.ArgAt>(0), Response.AllCorrect | Response.WithTransactions)); + .Returns(ci => ctx.ResponseBuilder.BuildBlocksResponse(ci.ArgAt>(0), Response.AllCorrect | Response.WithTransactions)); syncPeer.GetReceipts(Arg.Any>(), Arg.Any()) .Returns(Task.FromException(new TimeoutException())); @@ -719,7 +728,6 @@ public async Task Throws_on_receipt_task_exception_when_downloading_receipts(int await downloader.DownloadHeaders(peerInfo, new BlocksRequest(DownloaderOptions.WithBodies, 0), CancellationToken.None); syncPeer.HeadNumber.Returns(2); - // peerInfo.HeadNumber *= 2; Func action = async () => await downloader.DownloadBlocks(peerInfo, new BlocksRequest(downloaderOptions), CancellationToken.None); if (shouldThrow) @@ -769,15 +777,15 @@ public async Task Throws_on_null_receipt_downloaded(int options, bool shouldThro return receipts; }); - syncPeer.TotalDifficulty.Returns(ci => syncPeerInternal.TotalDifficulty); - syncPeer.HeadHash.Returns(ci => syncPeerInternal.HeadHash); - syncPeer.HeadNumber.Returns(ci => syncPeerInternal.HeadNumber); + syncPeer.TotalDifficulty.Returns(_ => syncPeerInternal.TotalDifficulty); + syncPeer.HeadHash.Returns(_ => syncPeerInternal.HeadHash); + syncPeer.HeadNumber.Returns(_ => syncPeerInternal.HeadNumber); PeerInfo peerInfo = new(syncPeer); int threshold = 2; await downloader.DownloadHeaders(peerInfo, new BlocksRequest(DownloaderOptions.None, threshold), CancellationToken.None); - ctx.BlockTree.BestSuggestedHeader.Number.Should().Be(Math.Max(0, Math.Min(headNumber, headNumber - threshold))); + ctx.BlockTree.BestSuggestedHeader!.Number.Should().Be(Math.Max(0, Math.Min(headNumber, headNumber - threshold))); syncPeerInternal.ExtendTree(chainLength * 2); Func action = async () => await downloader.DownloadBlocks(peerInfo, new BlocksRequest(downloaderOptions), CancellationToken.None); @@ -803,13 +811,11 @@ public async Task Throws_on_block_bodies_count_higher_than_receipts_list_count(i ISyncPeer syncPeer = Substitute.For(); syncPeer.TotalDifficulty.Returns(UInt256.MaxValue); - Task? buildHeadersResponse = null; syncPeer.GetBlockHeaders(Arg.Any(), Arg.Any(), Arg.Any(), Arg.Any()) - .Returns(ci => buildHeadersResponse = ctx.ResponseBuilder.BuildHeaderResponse(ci.ArgAt(0), ci.ArgAt(1), Response.AllCorrect | Response.WithTransactions)); + .Returns(ci => ctx.ResponseBuilder.BuildHeaderResponse(ci.ArgAt(0), ci.ArgAt(1), Response.AllCorrect | Response.WithTransactions)); - Task? buildBlocksResponse = null; syncPeer.GetBlockBodies(Arg.Any>(), Arg.Any()) - .Returns(ci => buildBlocksResponse = ctx.ResponseBuilder.BuildBlocksResponse(ci.ArgAt>(0), Response.AllCorrect | Response.WithTransactions)); + .Returns(ci => ctx.ResponseBuilder.BuildBlocksResponse(ci.ArgAt>(0), Response.AllCorrect | Response.WithTransactions)); syncPeer.GetReceipts(Arg.Any>(), Arg.Any()) .Returns(ci => ctx.ResponseBuilder.BuildReceiptsResponse(ci.ArgAt>(0), Response.AllCorrect | Response.WithTransactions).Result.Skip(1).ToArray()); @@ -833,13 +839,11 @@ public async Task Does_throw_on_transaction_count_different_than_receipts_count_ ISyncPeer syncPeer = Substitute.For(); syncPeer.TotalDifficulty.Returns(UInt256.MaxValue); - Task? buildHeadersResponse = null; syncPeer.GetBlockHeaders(Arg.Any(), Arg.Any(), Arg.Any(), Arg.Any()) - .Returns(ci => buildHeadersResponse = ctx.ResponseBuilder.BuildHeaderResponse(ci.ArgAt(0), ci.ArgAt(1), Response.AllCorrect | Response.WithTransactions)); + .Returns(ci => ctx.ResponseBuilder.BuildHeaderResponse(ci.ArgAt(0), ci.ArgAt(1), Response.AllCorrect | Response.WithTransactions)); - Task? buildBlocksResponse = null; syncPeer.GetBlockBodies(Arg.Any>(), Arg.Any()) - .Returns(ci => buildBlocksResponse = ctx.ResponseBuilder.BuildBlocksResponse(ci.ArgAt>(0), Response.AllCorrect | Response.WithTransactions)); + .Returns(ci => ctx.ResponseBuilder.BuildBlocksResponse(ci.ArgAt>(0), Response.AllCorrect | Response.WithTransactions)); syncPeer.GetReceipts(Arg.Any>(), Arg.Any()) .Returns(ci => ctx.ResponseBuilder.BuildReceiptsResponse(ci.ArgAt>(0), Response.AllCorrect | Response.WithTransactions) @@ -865,13 +869,11 @@ public async Task Throws_on_incorrect_receipts_root(int threshold) ISyncPeer syncPeer = Substitute.For(); syncPeer.TotalDifficulty.Returns(UInt256.MaxValue); - Task? buildHeadersResponse = null; syncPeer.GetBlockHeaders(Arg.Any(), Arg.Any(), Arg.Any(), Arg.Any()) - .Returns(ci => buildHeadersResponse = ctx.ResponseBuilder.BuildHeaderResponse(ci.ArgAt(0), ci.ArgAt(1), Response.IncorrectReceiptRoot)); + .Returns(ci => ctx.ResponseBuilder.BuildHeaderResponse(ci.ArgAt(0), ci.ArgAt(1), Response.IncorrectReceiptRoot)); - Task? buildBlocksResponse = null; syncPeer.GetBlockBodies(Arg.Any>(), Arg.Any()) - .Returns(ci => buildBlocksResponse = ctx.ResponseBuilder.BuildBlocksResponse(ci.ArgAt>(0), Response.AllCorrect | Response.WithTransactions)); + .Returns(ci => ctx.ResponseBuilder.BuildBlocksResponse(ci.ArgAt>(0), Response.AllCorrect | Response.WithTransactions)); syncPeer.GetReceipts(Arg.Any>(), Arg.Any()) .Returns(ci => ctx.ResponseBuilder.BuildReceiptsResponse(ci.ArgAt>(0), Response.AllCorrect | Response.WithTransactions).Result); @@ -901,13 +903,13 @@ private enum Response private class Context { - private Block genesis = Build.A.Block.Genesis.TestObject; - private MemDb _stateDb = new(); - private MemDb _blockInfoDb = new(); - private SyncConfig syncConfig = new(); + private readonly Block _genesis = Build.A.Block.Genesis.TestObject; + private readonly MemDb _stateDb = new(); + private readonly MemDb _blockInfoDb = new(); + private readonly SyncConfig _syncConfig = new(); private IBlockTree? _blockTree { get; set; } private Dictionary TestHeaderMapping { get; } - public InMemoryReceiptStorage ReceiptStorage = new(); + public InMemoryReceiptStorage ReceiptStorage { get; } = new(); private SyncBatchSize? _syncBatchSize; @@ -927,7 +929,7 @@ public virtual IBlockTree BlockTree if (_blockTree is null) { _blockTree = new BlockTree(new MemDb(), new MemDb(), _blockInfoDb, new ChainLevelInfoRepository(_blockInfoDb), SpecProvider, NullBloomStorage.Instance, LimboLogs.Instance); - _blockTree.SuggestBlock(genesis); + _blockTree.SuggestBlock(_genesis); } return _blockTree; @@ -938,10 +940,10 @@ public virtual IBlockTree BlockTree } } - private ISyncPeerPool _peerPool; + private ISyncPeerPool? _peerPool; public ISyncPeerPool PeerPool => _peerPool ??= Substitute.For(); - private ResponseBuilder? _responseBuilder = null; + private ResponseBuilder? _responseBuilder; public ResponseBuilder ResponseBuilder => _responseBuilder ??= new ResponseBuilder(BlockTree, TestHeaderMapping); @@ -952,25 +954,25 @@ public virtual IBlockTree BlockTree private ISyncProgressResolver? _syncProgressResolver; - private ISyncProgressResolver? SyncProgressResolver => _syncProgressResolver ??= + private ISyncProgressResolver SyncProgressResolver => _syncProgressResolver ??= new SyncProgressResolver( BlockTree, ReceiptStorage, _stateDb, new TrieStore(_stateDb, LimboLogs.Instance), ProgressTracker, - syncConfig, + _syncConfig, LimboLogs.Instance); - private MultiSyncModeSelector _syncModeSelector; + private MultiSyncModeSelector? _syncModeSelector; - protected IBetterPeerStrategy _betterPeerStrategy; + protected IBetterPeerStrategy? _betterPeerStrategy; protected virtual IBetterPeerStrategy BetterPeerStrategy => _betterPeerStrategy ??= new TotalDifficultyBetterPeerStrategy(LimboLogs.Instance); public ISyncModeSelector SyncModeSelector => _syncModeSelector ??= - new MultiSyncModeSelector(SyncProgressResolver, PeerPool, syncConfig, No.BeaconSync, BetterPeerStrategy, LimboLogs.Instance); + new MultiSyncModeSelector(SyncProgressResolver, PeerPool, _syncConfig, No.BeaconSync, BetterPeerStrategy, LimboLogs.Instance); private ActivatedSyncFeed? _feed; @@ -987,14 +989,14 @@ public ISealValidator SealValidator set => _sealValidator = value; } - private IBlockValidator _blockValidator; + private IBlockValidator? _blockValidator; public IBlockValidator BlockValidator { get => _blockValidator ??= Always.Valid; set => _blockValidator = value; } - private BlockDownloader _blockDownloader; + private BlockDownloader? _blockDownloader; public virtual BlockDownloader BlockDownloader => _blockDownloader ??= new BlockDownloader( Feed, PeerPool, @@ -1009,10 +1011,10 @@ public IBlockValidator BlockValidator SyncBatchSize ); - private SyncDispatcher _dispatcher; + private SyncDispatcher? _dispatcher; public SyncDispatcher Dispatcher => _dispatcher ??= new SyncDispatcher( 0, - Feed, + Feed!, BlockDownloader, PeerPool, PeerAllocationStrategy, @@ -1024,15 +1026,14 @@ public IBlockValidator BlockValidator protected virtual IPeerAllocationStrategyFactory PeerAllocationStrategy => _peerAllocationStrategy ??= new BlocksSyncPeerAllocationStrategyFactory(); - public Context(BlockTree? blockTree = null) + public Context() { - if (blockTree != null) + TestHeaderMapping = new Dictionary { - BlockTree = blockTree; - } - - TestHeaderMapping = new Dictionary(); - TestHeaderMapping.Add(0, genesis.Hash!); + { + 0, _genesis.Hash! + }, + }; } } @@ -1043,19 +1044,18 @@ private class SyncPeerMock : ISyncPeer private readonly BlockHeadersMessageSerializer _headersSerializer = new(); private readonly BlockBodiesMessageSerializer _bodiesSerializer = new(); private readonly ReceiptsMessageSerializer _receiptsSerializer = new(MainnetSpecProvider.Instance); + private readonly Response _flags; - private IDb _blockInfoDb = new MemDb(); - public BlockTree BlockTree { get; private set; } + public BlockTree BlockTree { get; private set; } = null!; private IReceiptStorage _receiptStorage = new InMemoryReceiptStorage(); - public Response Flags { get; set; } public string Name => "Mock"; public SyncPeerMock(long chainLength, bool withReceipts, Response flags, bool withWithdrawals = false) { _withReceipts = withReceipts; _withWithdrawals = withWithdrawals; - Flags = flags; + _flags = flags; BuildTree(chainLength, withReceipts); } @@ -1063,10 +1063,10 @@ public SyncPeerMock(BlockTree blockTree, bool withReceipts, Response flags, UInt { _withReceipts = withReceipts; _withWithdrawals = withWithdrawals; - Flags = flags; + _flags = flags; BlockTree = blockTree; - HeadNumber = BlockTree.Head.Number; - HeadHash = BlockTree.HeadHash; + HeadNumber = BlockTree.Head!.Number; + HeadHash = BlockTree.HeadHash!; TotalDifficulty = peerTotalDifficulty; } @@ -1082,8 +1082,8 @@ private void BuildTree(long chainLength, bool withReceipts) builder = builder.OfChainLength((int)chainLength, 0, 0, _withWithdrawals); BlockTree = builder.TestObject; - HeadNumber = BlockTree.Head.Number; - HeadHash = BlockTree.HeadHash; + HeadNumber = BlockTree.Head!.Number; + HeadHash = BlockTree.HeadHash!; TotalDifficulty = BlockTree.Head.TotalDifficulty ?? 0; } @@ -1092,47 +1092,35 @@ public void ExtendTree(long newLength) BuildTree(newLength, _withReceipts); } - public Node Node { get; } - public string ClientId { get; } - public Keccak HeadHash { get; set; } + public Node Node { get; } = null!; + public string ClientId { get; } = null!; + public byte ProtocolVersion { get; } = default; + public string ProtocolCode { get; } = null!; + public Keccak HeadHash { get; set; } = null!; + public PublicKey Id => Node.Id; public long HeadNumber { get; set; } public UInt256 TotalDifficulty { get; set; } public bool IsInitialized { get; set; } public bool IsPriority { get; set; } - public byte ProtocolVersion { get; } - public string ProtocolCode { get; } - - public void Disconnect(DisconnectReason reason, string details) - { - throw new NotImplementedException(); - } public async Task GetBlockBodies(IReadOnlyList blockHashes, CancellationToken token) { - bool consistent = Flags.HasFlag(Response.Consistent); - bool justFirst = Flags.HasFlag(Response.JustFirst); - bool allKnown = Flags.HasFlag(Response.AllKnown); - bool noBody = Flags.HasFlag(Response.NoBody); - BlockBody[] headers = new BlockBody[blockHashes.Count]; int i = 0; foreach (Keccak blockHash in blockHashes) { - headers[i++] = BlockTree.FindBlock(blockHash, BlockTreeLookupOptions.None).Body; + headers[i++] = BlockTree.FindBlock(blockHash, BlockTreeLookupOptions.None)!.Body; } BlockBodiesMessage message = new(headers); byte[] messageSerialized = _bodiesSerializer.Serialize(message); - return await Task.FromResult(_bodiesSerializer.Deserialize(messageSerialized).Bodies); + return await Task.FromResult(_bodiesSerializer.Deserialize(messageSerialized).Bodies!); } public async Task GetBlockHeaders(long number, int maxBlocks, int skip, CancellationToken token) { - bool consistent = Flags.HasFlag(Response.Consistent); - bool justFirst = Flags.HasFlag(Response.JustFirst); - bool allKnown = Flags.HasFlag(Response.AllKnown); - bool timeoutOnFullBatch = Flags.HasFlag(Response.TimeoutOnFullBatch); - bool noBody = Flags.HasFlag(Response.NoBody); + bool justFirst = _flags.HasFlag(Response.JustFirst); + bool timeoutOnFullBatch = _flags.HasFlag(Response.TimeoutOnFullBatch); if (timeoutOnFullBatch && number == SyncBatchSize.Max) { @@ -1142,7 +1130,7 @@ public async Task GetBlockHeaders(long number, int maxBlocks, int BlockHeader[] headers = new BlockHeader[maxBlocks]; for (int i = 0; i < (justFirst ? 1 : maxBlocks); i++) { - headers[i] = BlockTree.FindHeader(number + i, BlockTreeLookupOptions.None); + headers[i] = BlockTree.FindHeader(number + i, BlockTreeLookupOptions.None)!; } BlockHeadersMessage message = new(headers); @@ -1150,6 +1138,27 @@ public async Task GetBlockHeaders(long number, int maxBlocks, int return await Task.FromResult(_headersSerializer.Deserialize(messageSerialized).BlockHeaders); } + public async Task GetReceipts(IReadOnlyList blockHash, CancellationToken token) + { + TxReceipt[][] receipts = new TxReceipt[blockHash.Count][]; + int i = 0; + foreach (Keccak keccak in blockHash) + { + Block? block = BlockTree.FindBlock(keccak, BlockTreeLookupOptions.None); + TxReceipt[] blockReceipts = _receiptStorage.Get(block!); + receipts[i++] = blockReceipts; + } + + ReceiptsMessage message = new(receipts); + byte[] messageSerialized = _receiptsSerializer.Serialize(message); + return await Task.FromResult(_receiptsSerializer.Deserialize(messageSerialized).TxReceipts); + } + + public void Disconnect(DisconnectReason reason, string details) + { + throw new NotImplementedException(); + } + public Task GetBlockHeaders(Keccak startHash, int maxBlocks, int skip, CancellationToken token) { throw new NotImplementedException(); @@ -1165,29 +1174,11 @@ public void NotifyOfNewBlock(Block block, SendBlockMode mode) throw new NotImplementedException(); } - public PublicKey Id => Node.Id; - public void SendNewTransactions(IEnumerable txs, bool sendFullTx) { throw new NotImplementedException(); } - public async Task GetReceipts(IReadOnlyList blockHash, CancellationToken token) - { - TxReceipt[][] receipts = new TxReceipt[blockHash.Count][]; - int i = 0; - foreach (Keccak keccak in blockHash) - { - Block? block = BlockTree.FindBlock(keccak, BlockTreeLookupOptions.None); - TxReceipt[] blockReceipts = _receiptStorage.Get(block!); - receipts[i++] = blockReceipts; - } - - ReceiptsMessage message = new(receipts); - byte[] messageSerialized = _receiptsSerializer.Serialize(message); - return await Task.FromResult(_receiptsSerializer.Deserialize(messageSerialized).TxReceipts); - } - public Task GetNodeData(IReadOnlyList hashes, CancellationToken token) { throw new NotImplementedException(); @@ -1206,7 +1197,7 @@ public bool TryGetSatelliteProtocol(string protocol, out T protocolHandler) w private class ResponseBuilder { - private IBlockTree _blockTree; + private readonly IBlockTree _blockTree; private readonly Dictionary _testHeaderMapping; public ResponseBuilder(IBlockTree blockTree, Dictionary testHeaderMapping) @@ -1228,7 +1219,7 @@ public async Task BuildHeaderResponse(long startNumber, int numbe throw new TimeoutException(); } - BlockHeader startBlock = _blockTree.FindHeader(_testHeaderMapping[startNumber], BlockTreeLookupOptions.None); + BlockHeader startBlock = _blockTree.FindHeader(_testHeaderMapping[startNumber], BlockTreeLookupOptions.None)!; BlockHeader[] headers = new BlockHeader[number]; headers[0] = startBlock; if (!justFirst) @@ -1254,13 +1245,13 @@ public async Task BuildHeaderResponse(long startNumber, int numbe _blockTree.SuggestHeader(headers[i]); } - _testHeaderMapping[startNumber + i] = headers[i].Hash; + _testHeaderMapping[startNumber + i] = headers[i].Hash!; } } foreach (BlockHeader header in headers) { - _headers[header.Hash] = header; + _headers[header.Hash!] = header; } BlockHeadersMessage message = new(headers); @@ -1271,9 +1262,8 @@ public async Task BuildHeaderResponse(long startNumber, int numbe private readonly BlockHeadersMessageSerializer _headersSerializer = new(); private readonly BlockBodiesMessageSerializer _bodiesSerializer = new(); private readonly ReceiptsMessageSerializer _receiptsSerializer = new(MainnetSpecProvider.Instance); - - private Dictionary _headers = new(); - private Dictionary _bodies = new(); + private readonly Dictionary _headers = new(); + private readonly Dictionary _bodies = new(); public async Task BuildBlocksResponse(IList blockHashes, Response flags) { @@ -1339,7 +1329,7 @@ Block BuildBlockForHeader(BlockHeader header, int txSeed) BlockBodiesMessage message = new(blockBodies); byte[] messageSerialized = _bodiesSerializer.Serialize(message); - return await Task.FromResult(_bodiesSerializer.Deserialize(messageSerialized).Bodies); + return await Task.FromResult(_bodiesSerializer.Deserialize(messageSerialized).Bodies!); } public async Task BuildReceiptsResponse(IList blockHashes, Response flags = Response.AllCorrect) @@ -1352,7 +1342,7 @@ Block BuildBlockForHeader(BlockHeader header, int txSeed) .Select(t => Build.A.Receipt .WithStatusCode(StatusCode.Success) .WithGasUsed(10) - .WithBloom(Core.Bloom.Empty) + .WithBloom(Bloom.Empty) .WithLogs(Build.A.LogEntry.WithAddress(t.SenderAddress!).WithTopics(TestItem.KeccakA).TestObject) .TestObject) .ToArray(); diff --git a/src/Nethermind/Nethermind.Synchronization.Test/DbTuner/SyncDbTunerTests.cs b/src/Nethermind/Nethermind.Synchronization.Test/DbTuner/SyncDbTunerTests.cs index cada89c54b9..54d7c7d401f 100644 --- a/src/Nethermind/Nethermind.Synchronization.Test/DbTuner/SyncDbTunerTests.cs +++ b/src/Nethermind/Nethermind.Synchronization.Test/DbTuner/SyncDbTunerTests.cs @@ -17,14 +17,13 @@ public class SyncDbTunerTests private ITunableDb.TuneType _tuneType = ITunableDb.TuneType.HeavyWrite; private ITunableDb.TuneType _blocksTuneType = ITunableDb.TuneType.AggressiveHeavyWrite; private SyncConfig _syncConfig = null!; - private ISyncFeed? _snapSyncFeed; - private ISyncFeed? _bodiesSyncFeed; - private ISyncFeed? _receiptSyncFeed; + private ISyncFeed _snapSyncFeed = null!; + private ISyncFeed _bodiesSyncFeed = null!; + private ISyncFeed _receiptSyncFeed = null!; private ITunableDb _stateDb = null!; private ITunableDb _codeDb = null!; private ITunableDb _blockDb = null!; private ITunableDb _receiptDb = null!; - private SyncDbTuner _tuner = null!; [SetUp] public void Setup() @@ -35,15 +34,15 @@ public void Setup() TuneDbMode = _tuneType, BlocksDbTuneDbMode = _blocksTuneType, }; - _snapSyncFeed = Substitute.For?>(); - _bodiesSyncFeed = Substitute.For?>(); - _receiptSyncFeed = Substitute.For?>(); + _snapSyncFeed = Substitute.For>(); + _bodiesSyncFeed = Substitute.For>(); + _receiptSyncFeed = Substitute.For>(); _stateDb = Substitute.For(); _codeDb = Substitute.For(); _blockDb = Substitute.For(); _receiptDb = Substitute.For(); - _tuner = new SyncDbTuner( + SyncDbTuner _ = new SyncDbTuner( _syncConfig, _snapSyncFeed, _bodiesSyncFeed, @@ -78,7 +77,7 @@ public void WhenReceiptsIsOn_TriggerReceiptsDbTune() TestFeedAndDbTune(_receiptSyncFeed, _receiptDb); } - public void TestFeedAndDbTune(ISyncFeed feed, ITunableDb db, ITunableDb.TuneType? tuneType = null) + private void TestFeedAndDbTune(ISyncFeed feed, ITunableDb db, ITunableDb.TuneType? tuneType = null) { feed.StateChanged += Raise.EventWith(new SyncFeedStateEventArgs(SyncFeedState.Active)); diff --git a/src/Nethermind/Nethermind.Synchronization.Test/FastBlocks/FastHeadersSyncTests.cs b/src/Nethermind/Nethermind.Synchronization.Test/FastBlocks/FastHeadersSyncTests.cs index 9a428022089..f0956ccf78b 100644 --- a/src/Nethermind/Nethermind.Synchronization.Test/FastBlocks/FastHeadersSyncTests.cs +++ b/src/Nethermind/Nethermind.Synchronization.Test/FastBlocks/FastHeadersSyncTests.cs @@ -38,19 +38,57 @@ public class FastHeadersSyncTests public async Task Will_fail_if_launched_without_fast_blocks_enabled() { IDbProvider memDbProvider = await TestMemDbProvider.InitAsync(); - BlockTree blockTree = new(memDbProvider.BlocksDb, memDbProvider.HeadersDb, memDbProvider.BlockInfosDb, new ChainLevelInfoRepository(memDbProvider.BlockInfosDb), MainnetSpecProvider.Instance, NullBloomStorage.Instance, LimboLogs.Instance); - Assert.Throws(() => new HeadersSyncFeed(Substitute.For(), blockTree, Substitute.For(), new SyncConfig(), Substitute.For(), LimboLogs.Instance)); + BlockTree blockTree = new( + blockDb: memDbProvider.BlocksDb, + headerDb: memDbProvider.HeadersDb, + blockInfoDb: memDbProvider.BlockInfosDb, + chainLevelInfoRepository: new ChainLevelInfoRepository(memDbProvider.BlockInfosDb), + specProvider: MainnetSpecProvider.Instance, + bloomStorage: NullBloomStorage.Instance, + logManager: LimboLogs.Instance); + + Assert.Throws(() => + { + HeadersSyncFeed _ = new HeadersSyncFeed( + syncModeSelector: Substitute.For(), + blockTree: blockTree, + syncPeerPool: Substitute.For(), + syncConfig: new SyncConfig(), + syncReport: Substitute.For(), + logManager: LimboLogs.Instance); + }); } [Test] public async Task Can_prepare_3_requests_in_a_row() { IDbProvider memDbProvider = await TestMemDbProvider.InitAsync(); - BlockTree blockTree = new(memDbProvider.BlocksDb, memDbProvider.HeadersDb, memDbProvider.BlockInfosDb, new ChainLevelInfoRepository(memDbProvider.BlockInfosDb), MainnetSpecProvider.Instance, NullBloomStorage.Instance, LimboLogs.Instance); - HeadersSyncFeed feed = new(Substitute.For(), blockTree, Substitute.For(), new SyncConfig { FastSync = true, FastBlocks = true, PivotNumber = "1000", PivotHash = Keccak.Zero.ToString(), PivotTotalDifficulty = "1000" }, Substitute.For(), LimboLogs.Instance); - HeadersSyncBatch? batch1 = await feed.PrepareRequest(); - HeadersSyncBatch? batch2 = await feed.PrepareRequest(); - HeadersSyncBatch? batch3 = await feed.PrepareRequest(); + BlockTree blockTree = new( + blockDb: memDbProvider.BlocksDb, + headerDb: memDbProvider.HeadersDb, + blockInfoDb: memDbProvider.BlockInfosDb, + chainLevelInfoRepository: new ChainLevelInfoRepository(memDbProvider.BlockInfosDb), + specProvider: MainnetSpecProvider.Instance, + bloomStorage: NullBloomStorage.Instance, + logManager: LimboLogs.Instance); + HeadersSyncFeed feed = new( + syncModeSelector: Substitute.For(), + blockTree: blockTree, + syncPeerPool: Substitute.For(), + syncConfig: new SyncConfig + { + FastSync = true, + FastBlocks = true, + PivotNumber = "1000", + PivotHash = Keccak.Zero.ToString(), + PivotTotalDifficulty = "1000" + }, + syncReport: Substitute.For(), + logManager: LimboLogs.Instance); + + await feed.PrepareRequest(); + await feed.PrepareRequest(); + await feed.PrepareRequest(); } [Test] @@ -71,19 +109,19 @@ public async Task When_next_header_hash_update_is_delayed_do_not_drop_peer() ManualResetEventSlim hangLatch = new(false); BlockHeader pivot = remoteBlockTree.FindHeader(1000, BlockTreeLookupOptions.None)!; ResettableHeaderSyncFeed feed = new( - Substitute.For(), - blockTree, - syncPeerPool, - new SyncConfig + syncModeSelector: Substitute.For(), + blockTree: blockTree, + syncPeerPool: syncPeerPool, + syncConfig: new SyncConfig { FastSync = true, FastBlocks = true, PivotNumber = "1000", - PivotHash = pivot.Hash.Bytes.ToHexString(), - PivotTotalDifficulty = pivot.TotalDifficulty!.ToString() + PivotHash = pivot.Hash!.Bytes.ToHexString(), + PivotTotalDifficulty = pivot.TotalDifficulty.ToString()! }, - syncReport, - LimboLogs.Instance, + syncReport: syncReport, + logManager: LimboLogs.Instance, hangOnBlockNumberAfterInsert: 425, hangLatch: hangLatch ); @@ -98,10 +136,10 @@ void FulfillBatch(HeadersSyncBatch batch) batch.ResponseSourcePeer = peerInfo; } - HeadersSyncBatch? batch1 = await feed.PrepareRequest(); - HeadersSyncBatch? batch2 = await feed.PrepareRequest(); - HeadersSyncBatch? batch3 = await feed.PrepareRequest(); - HeadersSyncBatch? batch4 = await feed.PrepareRequest(); + HeadersSyncBatch batch1 = (await feed.PrepareRequest())!; + HeadersSyncBatch batch2 = (await feed.PrepareRequest())!; + HeadersSyncBatch batch3 = (await feed.PrepareRequest())!; + HeadersSyncBatch batch4 = (await feed.PrepareRequest())!; FulfillBatch(batch1); FulfillBatch(batch2); @@ -112,10 +150,7 @@ void FulfillBatch(HeadersSyncBatch batch) feed.HandleResponse(batch1); feed.HandleResponse(batch3); feed.HandleResponse(batch2); - Task.Factory.StartNew(() => - { - feed.PrepareRequest(); - }, TaskCreationOptions.LongRunning); + Task _ = Task.Factory.StartNew(() => feed.PrepareRequest(), TaskCreationOptions.LongRunning); await Task.Delay(TimeSpan.FromMilliseconds(100)); @@ -137,7 +172,21 @@ public async Task Can_prepare_several_request_and_ignore_request_from_previous_s syncReport.HeadersInQueue.Returns(new MeasuredProgress()); BlockHeader pivot = remoteBlockTree.FindHeader(500, BlockTreeLookupOptions.None)!; - ResettableHeaderSyncFeed feed = new(Substitute.For(), blockTree, Substitute.For(), new SyncConfig { FastSync = true, FastBlocks = true, PivotNumber = "500", PivotHash = pivot.Hash.Bytes.ToHexString(), PivotTotalDifficulty = pivot.TotalDifficulty!.ToString() }, syncReport, LimboLogs.Instance); + ResettableHeaderSyncFeed feed = new( + syncModeSelector: Substitute.For(), + blockTree: blockTree, + syncPeerPool: Substitute.For(), + syncConfig: new SyncConfig + { + FastSync = true, + FastBlocks = true, + PivotNumber = "500", + PivotHash = pivot.Hash!.Bytes.ToHexString(), + PivotTotalDifficulty = pivot.TotalDifficulty!.ToString()! + }, + syncReport: syncReport, + logManager: LimboLogs.Instance); + feed.InitializeFeed(); void FulfillBatch(HeadersSyncBatch batch) @@ -148,13 +197,13 @@ void FulfillBatch(HeadersSyncBatch batch) } await feed.PrepareRequest(); - HeadersSyncBatch? batch1 = await feed.PrepareRequest(); + HeadersSyncBatch batch1 = (await feed.PrepareRequest())!; FulfillBatch(batch1); feed.Reset(); await feed.PrepareRequest(); - HeadersSyncBatch? batch2 = await feed.PrepareRequest(); + HeadersSyncBatch batch2 = (await feed.PrepareRequest())!; FulfillBatch(batch2); feed.HandleResponse(batch2); @@ -167,7 +216,14 @@ public async Task Will_dispatch_when_only_partially_processed_dependency() IDbProvider memDbProvider = await TestMemDbProvider.InitAsync(); BlockTree remoteBlockTree = Build.A.BlockTree().OfHeadersOnly.OfChainLength(2001).TestObject; - BlockTree blockTree = new(memDbProvider.BlocksDb, memDbProvider.HeadersDb, memDbProvider.BlockInfosDb, new ChainLevelInfoRepository(memDbProvider.BlockInfosDb), MainnetSpecProvider.Instance, NullBloomStorage.Instance, LimboLogs.Instance); + BlockTree blockTree = new( + blockDb: memDbProvider.BlocksDb, + headerDb: memDbProvider.HeadersDb, + blockInfoDb: memDbProvider.BlockInfosDb, + chainLevelInfoRepository: new ChainLevelInfoRepository(memDbProvider.BlockInfosDb), + specProvider: MainnetSpecProvider.Instance, + bloomStorage: NullBloomStorage.Instance, + logManager: LimboLogs.Instance); ISyncReport syncReport = Substitute.For(); syncReport.FastBlocksHeaders.Returns(new MeasuredProgress()); @@ -175,19 +231,20 @@ public async Task Will_dispatch_when_only_partially_processed_dependency() BlockHeader pivot = remoteBlockTree.FindHeader(2000, BlockTreeLookupOptions.None)!; HeadersSyncFeed feed = new( - Substitute.For(), - blockTree, - Substitute.For(), - new SyncConfig + syncModeSelector: Substitute.For(), + blockTree: blockTree, + syncPeerPool: Substitute.For(), + syncConfig: new SyncConfig { FastSync = true, FastBlocks = true, PivotNumber = pivot.Number.ToString(), - PivotHash = pivot.Hash.ToString(), - PivotTotalDifficulty = pivot.TotalDifficulty.ToString(), + PivotHash = pivot.Hash!.ToString(), + PivotTotalDifficulty = pivot.TotalDifficulty.ToString()!, }, - syncReport, - LimboLogs.Instance); + syncReport: syncReport, + logManager: LimboLogs.Instance); + feed.InitializeFeed(); void FulfillBatch(HeadersSyncBatch batch) @@ -198,18 +255,18 @@ void FulfillBatch(HeadersSyncBatch batch) } // First batch need to be handled first before handle dependencies can do anything - HeadersSyncBatch? batch1 = await feed.PrepareRequest(); + HeadersSyncBatch batch1 = (await feed.PrepareRequest())!; FulfillBatch(batch1); feed.HandleResponse(batch1); - HeadersSyncBatch? batch2 = await feed.PrepareRequest(); + HeadersSyncBatch batch2 = (await feed.PrepareRequest())!; FulfillBatch(batch2); int maxHeaderBatchToProcess = 4; - HeadersSyncBatch[] batches = Enumerable.Range(0, maxHeaderBatchToProcess + 1).Select((_) => + HeadersSyncBatch[] batches = Enumerable.Range(0, maxHeaderBatchToProcess + 1).Select(_ => { - HeadersSyncBatch? batch = feed.PrepareRequest().Result; + HeadersSyncBatch batch = feed.PrepareRequest().Result!; FulfillBatch(batch); return batch; }).ToArray(); @@ -224,7 +281,7 @@ void FulfillBatch(HeadersSyncBatch batch) feed.HandleResponse(batch2); // HandleDependantBatch would start from first batch in batches, stopped at second last, not processing the last one - HeadersSyncBatch? newBatch = await feed.PrepareRequest(); + HeadersSyncBatch newBatch = (await feed.PrepareRequest())!; blockTree.LowestInsertedHeader!.Number.Should().Be(batches[^2].StartNumber); // New batch would be at end of batch 5 (batch 6). @@ -237,7 +294,14 @@ public async Task Can_reset_and_not_hang_when_a_batch_is_processing() IDbProvider memDbProvider = await TestMemDbProvider.InitAsync(); BlockTree remoteBlockTree = Build.A.BlockTree().OfHeadersOnly.OfChainLength(501).TestObject; - BlockTree blockTree = new(memDbProvider.BlocksDb, memDbProvider.HeadersDb, memDbProvider.BlockInfosDb, new ChainLevelInfoRepository(memDbProvider.BlockInfosDb), MainnetSpecProvider.Instance, NullBloomStorage.Instance, LimboLogs.Instance); + BlockTree blockTree = new( + blockDb: memDbProvider.BlocksDb, + headerDb: memDbProvider.HeadersDb, + blockInfoDb: memDbProvider.BlockInfosDb, + chainLevelInfoRepository: new ChainLevelInfoRepository(memDbProvider.BlockInfosDb), + specProvider: MainnetSpecProvider.Instance, + bloomStorage: NullBloomStorage.Instance, + logManager: LimboLogs.Instance); ISyncReport syncReport = Substitute.For(); syncReport.FastBlocksHeaders.Returns(new MeasuredProgress()); @@ -247,12 +311,19 @@ public async Task Can_reset_and_not_hang_when_a_batch_is_processing() BlockHeader pivot = remoteBlockTree.FindHeader(500, BlockTreeLookupOptions.None)!; ResettableHeaderSyncFeed feed = new( - Substitute.For(), - blockTree, - Substitute.For(), - new SyncConfig { FastSync = true, FastBlocks = true, PivotNumber = "500", PivotHash = pivot.Hash.Bytes.ToHexString(), PivotTotalDifficulty = pivot.TotalDifficulty!.ToString() }, - syncReport, - LimboLogs.Instance, + syncModeSelector: Substitute.For(), + blockTree: blockTree, + syncPeerPool: Substitute.For(), + syncConfig: new SyncConfig + { + FastSync = true, + FastBlocks = true, + PivotNumber = "500", + PivotHash = pivot.Hash!.Bytes.ToHexString(), + PivotTotalDifficulty = pivot.TotalDifficulty!.ToString()! + }, + syncReport: syncReport, + logManager: LimboLogs.Instance, hangOnBlockNumber: 400, hangLatch: hangLatch ); @@ -266,7 +337,7 @@ void FulfillBatch(HeadersSyncBatch batch) false); } - HeadersSyncBatch? batch1 = await feed.PrepareRequest(); + HeadersSyncBatch batch1 = (await feed.PrepareRequest())!; FulfillBatch(batch1); // Initiate a process batch which should hang in the middle @@ -282,27 +353,48 @@ void FulfillBatch(HeadersSyncBatch batch) await resetTask; // A new batch is creating, starting at hang block - HeadersSyncBatch? batch2 = await feed.PrepareRequest(); + HeadersSyncBatch batch2 = (await feed.PrepareRequest())!; FulfillBatch(batch2); feed.HandleResponse(batch2); // The whole new batch should get processed instead of skipping due to concurrently modified _nextHeaderHash. - blockTree.LowestInsertedHeader.Number.Should().Be(batch2.StartNumber); + blockTree.LowestInsertedHeader!.Number.Should().Be(batch2.StartNumber); } [Test] public async Task Can_keep_returning_nulls_after_all_batches_were_prepared() { IDbProvider memDbProvider = await TestMemDbProvider.InitAsync(); - BlockTree blockTree = new(memDbProvider.BlocksDb, memDbProvider.HeadersDb, memDbProvider.BlockInfosDb, new ChainLevelInfoRepository(memDbProvider.BlockInfosDb), MainnetSpecProvider.Instance, NullBloomStorage.Instance, LimboLogs.Instance); - HeadersSyncFeed feed = new(Substitute.For(), blockTree, Substitute.For(), new SyncConfig { FastSync = true, FastBlocks = true, PivotNumber = "1000", PivotHash = Keccak.Zero.ToString(), PivotTotalDifficulty = "1000" }, Substitute.For(), LimboLogs.Instance); + BlockTree blockTree = new( + blockDb: memDbProvider.BlocksDb, + headerDb: memDbProvider.HeadersDb, + blockInfoDb: memDbProvider.BlockInfosDb, + chainLevelInfoRepository: new ChainLevelInfoRepository(memDbProvider.BlockInfosDb), + specProvider: MainnetSpecProvider.Instance, + bloomStorage: NullBloomStorage.Instance, + logManager: LimboLogs.Instance); + HeadersSyncFeed feed = new( + syncModeSelector: Substitute.For(), + blockTree: blockTree, + syncPeerPool: Substitute.For(), + syncConfig: new SyncConfig + { + FastSync = true, + FastBlocks = true, + PivotNumber = "1000", + PivotHash = Keccak.Zero.ToString(), + PivotTotalDifficulty = "1000" + }, + syncReport: Substitute.For(), + logManager: LimboLogs.Instance); + for (int i = 0; i < 10; i++) { await feed.PrepareRequest(); } - var result = await feed.PrepareRequest(); + HeadersSyncBatch? result = await feed.PrepareRequest(); result.Should().BeNull(); } @@ -318,7 +410,8 @@ public async Task Finishes_when_all_downloaded() HeadersSyncFeed feed = new(Substitute.For(), blockTree, Substitute.For(), new SyncConfig { FastSync = true, FastBlocks = true, PivotNumber = "1000", PivotHash = Keccak.Zero.ToString(), PivotTotalDifficulty = "1000" }, report, LimboLogs.Instance); await feed.PrepareRequest(); blockTree.LowestInsertedHeader.Returns(Build.A.BlockHeader.WithNumber(1).TestObject); - var result = await feed.PrepareRequest(); + HeadersSyncBatch? result = await feed.PrepareRequest(); + result.Should().BeNull(); feed.CurrentState.Should().Be(SyncFeedState.Finished); measuredProgress.HasEnded.Should().BeTrue(); @@ -339,8 +432,10 @@ public async Task Can_resume_downloading_from_parent_of_lowest_inserted_header() HeadersSyncFeed feed = new(Substitute.For(), blockTree, Substitute.For(), new SyncConfig { FastSync = true, FastBlocks = true, PivotNumber = "1000", PivotHash = Keccak.Zero.ToString(), PivotTotalDifficulty = "1000" }, report, LimboLogs.Instance); feed.InitializeFeed(); - var result = await feed.PrepareRequest(); - result.EndNumber.Should().Be(499); + HeadersSyncBatch? result = await feed.PrepareRequest(); + + result.Should().NotBeNull(); + result!.EndNumber.Should().Be(499); } [Test] @@ -386,7 +481,7 @@ public async Task Will_never_lose_batch_on_invalid_batch() { for (int i = 0; i < 100000; i++) { - var batch = await feed.PrepareRequest(); + HeadersSyncBatch? batch = await feed.PrepareRequest(); if (batch == null) { await Task.Delay(1); @@ -415,12 +510,12 @@ public async Task Will_never_lose_batch_on_invalid_batch() batches.Add(batch); } - batches.Count().Should().Be(totalBatchCount); + batches.Count.Should().Be(totalBatchCount); } private class ResettableHeaderSyncFeed : HeadersSyncFeed { - private ManualResetEventSlim? _hangLatch; + private readonly ManualResetEventSlim? _hangLatch; private readonly long? _hangOnBlockNumber; private readonly long? _hangOnBlockNumberAfterInsert; @@ -452,15 +547,15 @@ protected override AddBlockResult InsertToBlockTree(BlockHeader header) { if (header.Number == _hangOnBlockNumber) { - _hangLatch.Wait(); + _hangLatch!.Wait(); } AddBlockResult insertOutcome = _blockTree.Insert(header); if (header.Number == _hangOnBlockNumberAfterInsert) { - _hangLatch.Wait(); + _hangLatch!.Wait(); } - if (insertOutcome == AddBlockResult.Added || insertOutcome == AddBlockResult.AlreadyKnown) + if (insertOutcome is AddBlockResult.Added or AddBlockResult.AlreadyKnown) { SetExpectedNextHeaderToParent(header); } diff --git a/src/Nethermind/Nethermind.Synchronization.Test/FastSync/ReceiptsSyncFeedTests.cs b/src/Nethermind/Nethermind.Synchronization.Test/FastSync/ReceiptsSyncFeedTests.cs index 7838c3ec523..794547436e3 100644 --- a/src/Nethermind/Nethermind.Synchronization.Test/FastSync/ReceiptsSyncFeedTests.cs +++ b/src/Nethermind/Nethermind.Synchronization.Test/FastSync/ReceiptsSyncFeedTests.cs @@ -36,7 +36,7 @@ public Scenario(ISpecProvider specProvider, int nonEmptyBlocks, int txPerBlock, Blocks = new Block[_pivotNumber + 1]; Blocks[0] = Build.A.Block.Genesis.TestObject; - Block parent = Blocks[0]; + Block parent = Blocks[0]!; for (int blockNumber = 1; blockNumber <= _pivotNumber; blockNumber++) { Block block = Build.A.Block @@ -56,34 +56,34 @@ public Scenario(ISpecProvider specProvider, int nonEmptyBlocks, int txPerBlock, parent = block; } - BlocksByHash = Blocks.Where(b => b is not null).ToDictionary(b => b.Hash!, b => b); + BlocksByHash = Blocks + .Where(b => b is not null) + .ToDictionary(b => b!.Hash!, b => b!); } - public Dictionary BlocksByHash; - - public Block[] Blocks; - - public Block LowestInsertedBody; + public Dictionary BlocksByHash { get; } + public Block?[] Blocks { get; } + public Block? LowestInsertedBody { get; } } - private static ISpecProvider _specProvider; - private IReceiptStorage _receiptStorage; - private ISyncPeerPool _syncPeerPool; - private ISyncModeSelector _selector; - private ReceiptsSyncFeed _feed; - private ISyncConfig _syncConfig; - private ISyncReport _syncReport; - private IBlockTree _blockTree; + private static readonly ISpecProvider _specProvider; + private IReceiptStorage _receiptStorage = null!; + private ISyncPeerPool _syncPeerPool = null!; + private ISyncModeSelector _selector = null!; + private ReceiptsSyncFeed _feed = null!; + private ISyncConfig _syncConfig = null!; + private ISyncReport _syncReport = null!; + private IBlockTree _blockTree = null!; - private static long _pivotNumber = 1024; + private static readonly long _pivotNumber = 1024; - private static Scenario _1024BodiesWithOneTxEach; - private static Scenario _256BodiesWithOneTxEach; - private static Scenario _64BodiesWithOneTxEach; - private static Scenario _64BodiesWithOneTxEachFollowedByEmpty; + private static readonly Scenario _1024BodiesWithOneTxEach; + private static readonly Scenario _256BodiesWithOneTxEach; + private static readonly Scenario _64BodiesWithOneTxEach; + private static readonly Scenario _64BodiesWithOneTxEachFollowedByEmpty; - private MeasuredProgress _measuredProgress; - private MeasuredProgress _measuredProgressQueue; + private MeasuredProgress _measuredProgress = null!; + private MeasuredProgress _measuredProgressQueue = null!; static ReceiptsSyncFeedTests() { @@ -154,7 +154,7 @@ public async Task Should_finish_on_start_when_receipts_not_stored() _syncReport, LimboLogs.Instance); - var request = await _feed.PrepareRequest(); + ReceiptsSyncBatch? request = await _feed.PrepareRequest(); request.Should().BeNull(); _feed.CurrentState.Should().Be(SyncFeedState.Finished); } @@ -181,7 +181,7 @@ public void Should_start_dormant() public void When_activating_should_emit_an_event() { SyncFeedState state = SyncFeedState.Dormant; - _feed.StateChanged += (s, e) => state = e.NewState; + _feed.StateChanged += (_, e) => state = e.NewState; _feed.Activate(); state.Should().Be(SyncFeedState.Active); } @@ -240,7 +240,7 @@ private void LoadScenario(Scenario scenario, ISyncConfig syncConfig) { _syncConfig = syncConfig; _syncConfig.PivotNumber = _pivotNumber.ToString(); - _syncConfig.PivotHash = scenario.Blocks.Last().Hash?.ToString(); + _syncConfig.PivotHash = scenario.Blocks.Last()?.Hash?.ToString(); _feed = new ReceiptsSyncFeed( _selector, @@ -252,18 +252,20 @@ private void LoadScenario(Scenario scenario, ISyncConfig syncConfig) _syncReport, LimboLogs.Instance); - _blockTree.Genesis.Returns(scenario.Blocks[0].Header); + _blockTree.Genesis.Returns(scenario.Blocks[0]!.Header); _blockTree.FindCanonicalBlockInfo(Arg.Any()).Returns( ci => { - Block block = scenario.Blocks[ci.Arg()]; + Block? block = scenario.Blocks[ci.Arg()]; if (block is null) { return null; } - BlockInfo blockInfo = new(block.Hash!, block.TotalDifficulty ?? 0); - blockInfo.BlockNumber = ci.Arg(); + BlockInfo blockInfo = new(block.Hash!, block.TotalDifficulty ?? 0) + { + BlockNumber = ci.Arg(), + }; return blockInfo; }); @@ -277,7 +279,7 @@ private void LoadScenario(Scenario scenario, ISyncConfig syncConfig) : null); _receiptStorage.LowestInsertedReceiptBlockNumber.Returns((long?)null); - _blockTree.LowestInsertedBodyNumber.Returns(scenario.LowestInsertedBody.Number); + _blockTree.LowestInsertedBodyNumber.Returns(scenario.LowestInsertedBody!.Number); } [Test] diff --git a/src/Nethermind/Nethermind.Synchronization.Test/FastSync/SnapProtocolTests/StateSyncDispatcherTester.cs b/src/Nethermind/Nethermind.Synchronization.Test/FastSync/SnapProtocolTests/StateSyncDispatcherTester.cs index 2625f6c60bd..f207e33df7b 100644 --- a/src/Nethermind/Nethermind.Synchronization.Test/FastSync/SnapProtocolTests/StateSyncDispatcherTester.cs +++ b/src/Nethermind/Nethermind.Synchronization.Test/FastSync/SnapProtocolTests/StateSyncDispatcherTester.cs @@ -30,7 +30,7 @@ public async Task ExecuteDispatch(StateSyncBatch batch, int times) for (int i = 0; i < times; i++) { - await _downloader.Dispatch(allocation.Current, batch, CancellationToken.None); + await _downloader.Dispatch(allocation.Current!, batch, CancellationToken.None); } } } diff --git a/src/Nethermind/Nethermind.Synchronization.Test/FastSync/SnapProtocolTests/StateSyncDispatcherTests.cs b/src/Nethermind/Nethermind.Synchronization.Test/FastSync/SnapProtocolTests/StateSyncDispatcherTests.cs index 26717fd067f..2eaaf9dcef4 100644 --- a/src/Nethermind/Nethermind.Synchronization.Test/FastSync/SnapProtocolTests/StateSyncDispatcherTests.cs +++ b/src/Nethermind/Nethermind.Synchronization.Test/FastSync/SnapProtocolTests/StateSyncDispatcherTests.cs @@ -2,7 +2,6 @@ // SPDX-License-Identifier: LGPL-3.0-only using System; -using System.Linq; using System.Threading; using System.Threading.Tasks; using Nethermind.Blockchain.Synchronization; @@ -27,12 +26,13 @@ namespace Nethermind.Synchronization.Test.FastSync.SnapProtocolTests [Parallelizable(ParallelScope.Self)] public class StateSyncDispatcherTests { - private static IBlockTree _blockTree; - private ILogManager _logManager; - SyncPeerPool _pool; - StateSyncDispatcherTester _dispatcher; + private static IBlockTree _blockTree = null!; - private PublicKey _publicKey = new("0x000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f"); + private ILogManager _logManager = null!; + private SyncPeerPool _pool = null!; + private StateSyncDispatcherTester _dispatcher = null!; + + private readonly PublicKey _publicKey = new("0x000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f"); private static IBlockTree BlockTree => LazyInitializer.EnsureInitialized(ref _blockTree, () => Build.A.BlockTree().OfChainLength(100).TestObject); @@ -46,7 +46,7 @@ public void Setup() _pool = new SyncPeerPool(blockTree, new NodeStatsManager(timerFactory, LimboLogs.Instance), new TotalDifficultyBetterPeerStrategy(LimboLogs.Instance), LimboLogs.Instance, 25); _pool.Start(); - var feed = Substitute.For>(); + ISyncFeed? feed = Substitute.For>(); _dispatcher = new StateSyncDispatcherTester(feed, new StateSyncDownloader(_logManager), _pool, new StateSyncAllocationStrategyFactory(), _logManager); } @@ -61,12 +61,14 @@ public async Task Eth66Peer_RunGetNodeData() peer.TotalDifficulty.Returns(new Int256.UInt256(1_000_000_000)); _pool.AddPeer(peer); - StateSyncBatch batch = new StateSyncBatch(Keccak.OfAnEmptyString, NodeDataType.State, - new StateSyncItem[] { new StateSyncItem(Keccak.EmptyTreeHash, Array.Empty(), Array.Empty(), NodeDataType.State) }); + StateSyncBatch batch = new( + Keccak.OfAnEmptyString, + NodeDataType.State, + new[] { new StateSyncItem(Keccak.EmptyTreeHash, Array.Empty(), Array.Empty(), NodeDataType.State) }); await _dispatcher.ExecuteDispatch(batch, 1); - await peer.ReceivedWithAnyArgs(1).GetNodeData(default, default); + await peer.ReceivedWithAnyArgs(1).GetNodeData(default!, default); } [Test] @@ -86,20 +88,22 @@ public async Task GroupMultipleStorageSlotsByAccount() }); _pool.AddPeer(peer); - var item01 = new StateSyncItem(Keccak.EmptyTreeHash, null, new byte[] { 3 }, NodeDataType.State); - var item02 = new StateSyncItem(Keccak.EmptyTreeHash, new byte[] { 11 }, new byte[] { 2 }, NodeDataType.State); - var item03 = new StateSyncItem(Keccak.EmptyTreeHash, null, new byte[] { 1 }, NodeDataType.State); - var item04 = new StateSyncItem(Keccak.EmptyTreeHash, new byte[] { 22 }, new byte[] { 21 }, NodeDataType.State); - var item05 = new StateSyncItem(Keccak.EmptyTreeHash, new byte[] { 11 }, new byte[] { 1 }, NodeDataType.State); - var item06 = new StateSyncItem(Keccak.EmptyTreeHash, new byte[] { 22 }, new byte[] { 22 }, NodeDataType.State); + StateSyncItem item01 = new(Keccak.EmptyTreeHash, null, new byte[] { 3 }, NodeDataType.State); + StateSyncItem item02 = new(Keccak.EmptyTreeHash, new byte[] { 11 }, new byte[] { 2 }, NodeDataType.State); + StateSyncItem item03 = new(Keccak.EmptyTreeHash, null, new byte[] { 1 }, NodeDataType.State); + StateSyncItem item04 = new(Keccak.EmptyTreeHash, new byte[] { 22 }, new byte[] { 21 }, NodeDataType.State); + StateSyncItem item05 = new(Keccak.EmptyTreeHash, new byte[] { 11 }, new byte[] { 1 }, NodeDataType.State); + StateSyncItem item06 = new(Keccak.EmptyTreeHash, new byte[] { 22 }, new byte[] { 22 }, NodeDataType.State); - StateSyncBatch batch = new StateSyncBatch(Keccak.OfAnEmptyString, NodeDataType.State, new StateSyncItem[] { - item01, item02, item03, item04, item05, item06 - }); + StateSyncBatch batch = new( + Keccak.OfAnEmptyString, + NodeDataType.State, + new[] { item01, item02, item03, item04, item05, item06 }); await _dispatcher.ExecuteDispatch(batch, 1); - batch.RequestedNodes.Count().Should().Be(6); + batch.RequestedNodes.Should().NotBeNull(); + batch.RequestedNodes!.Count.Should().Be(6); batch.RequestedNodes[0].Should().Be(item01); batch.RequestedNodes[1].Should().Be(item03); batch.RequestedNodes[2].Should().Be(item02); diff --git a/src/Nethermind/Nethermind.Synchronization.Test/FastSync/StateSyncFeedHealingTests.cs b/src/Nethermind/Nethermind.Synchronization.Test/FastSync/StateSyncFeedHealingTests.cs index 33e005b66a5..94db85ce17c 100644 --- a/src/Nethermind/Nethermind.Synchronization.Test/FastSync/StateSyncFeedHealingTests.cs +++ b/src/Nethermind/Nethermind.Synchronization.Test/FastSync/StateSyncFeedHealingTests.cs @@ -52,8 +52,6 @@ public async Task HealBigSqueezedRandomTree() int pathPoolCount = 100_000; Keccak[] pathPool = new Keccak[pathPoolCount]; SortedDictionary accounts = new(); - int updatesCount = 0; - int deletionsCount = 0; for (int i = 0; i < pathPoolCount; i++) { @@ -76,7 +74,7 @@ public async Task HealBigSqueezedRandomTree() dbContext.RemoteStateTree.Commit(0); int startingHashIndex = 0; - int endHashIndex = 0; + int endHashIndex; int blockJumps = 5; for (int blockNumber = 1; blockNumber <= blockJumps; blockNumber++) { @@ -101,13 +99,11 @@ public async Task HealBigSqueezedRandomTree() { dbContext.RemoteStateTree.Set(path, account); accounts[path] = account; - updatesCount++; } else { dbContext.RemoteStateTree.Set(path, null); accounts.Remove(path); - deletionsCount++; } @@ -159,12 +155,12 @@ private static void ProcessAccountRange(StateTree remoteStateTree, StateTree loc AccountProofCollector accountProofCollector = new(startingHash.Bytes); remoteStateTree.Accept(accountProofCollector, remoteStateTree.RootHash); - byte[][] firstProof = accountProofCollector.BuildResult().Proof; + byte[][] firstProof = accountProofCollector.BuildResult().Proof!; accountProofCollector = new(endHash.Bytes); remoteStateTree.Accept(accountProofCollector, remoteStateTree.RootHash); - byte[][] lastProof = accountProofCollector.BuildResult().Proof; + byte[][] lastProof = accountProofCollector.BuildResult().Proof!; - (_, _, _, _) = SnapProviderHelper.AddAccountRange(localStateTree, blockNumber, rootHash, startingHash, limitHash, accounts, firstProof!.Concat(lastProof!).ToArray()); + _ = SnapProviderHelper.AddAccountRange(localStateTree, blockNumber, rootHash, startingHash, limitHash, accounts, firstProof.Concat(lastProof).ToArray()); } } } diff --git a/src/Nethermind/Nethermind.Synchronization.Test/FastSync/StateSyncFeedTests.cs b/src/Nethermind/Nethermind.Synchronization.Test/FastSync/StateSyncFeedTests.cs index 58df8c9c62a..45c12fc64bc 100644 --- a/src/Nethermind/Nethermind.Synchronization.Test/FastSync/StateSyncFeedTests.cs +++ b/src/Nethermind/Nethermind.Synchronization.Test/FastSync/StateSyncFeedTests.cs @@ -7,6 +7,7 @@ using FluentAssertions; using Nethermind.Blockchain; using Nethermind.Blockchain.Synchronization; +using Nethermind.Core; using Nethermind.Core.Crypto; using Nethermind.Core.Extensions; using Nethermind.Core.Test.Builders; @@ -42,16 +43,21 @@ public StateSyncFeedTests(int peerCount, int maxNodeLatency) : base(peerCount, m [Repeat(TestRepeatCount)] public async Task Big_test((string Name, Action SetupTree) testCase) { - DbContext dbContext = new(_logger, _logManager); - dbContext.RemoteCodeDb[Keccak.Compute(TrieScenarios.Code0).Bytes] = TrieScenarios.Code0; - dbContext.RemoteCodeDb[Keccak.Compute(TrieScenarios.Code1).Bytes] = TrieScenarios.Code1; - dbContext.RemoteCodeDb[Keccak.Compute(TrieScenarios.Code2).Bytes] = TrieScenarios.Code2; - dbContext.RemoteCodeDb[Keccak.Compute(TrieScenarios.Code3).Bytes] = TrieScenarios.Code3; + DbContext dbContext = new(_logger, _logManager) + { + RemoteCodeDb = + { + [Keccak.Compute(TrieScenarios.Code0).Bytes] = TrieScenarios.Code0, + [Keccak.Compute(TrieScenarios.Code1).Bytes] = TrieScenarios.Code1, + [Keccak.Compute(TrieScenarios.Code2).Bytes] = TrieScenarios.Code2, + [Keccak.Compute(TrieScenarios.Code3).Bytes] = TrieScenarios.Code3, + }, + }; testCase.SetupTree(dbContext.RemoteStateTree, dbContext.RemoteTrieStore, dbContext.RemoteCodeDb); dbContext.CompareTrees("BEFORE FIRST SYNC", true); - SafeContext ctx = PrepareDownloader(dbContext, (mock) => + SafeContext ctx = PrepareDownloader(dbContext, mock => mock.SetFilter(((MemDb)dbContext.RemoteStateDb).Keys.Take(((MemDb)dbContext.RemoteStateDb).Keys.Count - 4).Select(k => new Keccak(k)).ToArray())); await ActivateAndWait(ctx, dbContext, 1024); @@ -90,16 +96,14 @@ public async Task Big_test((string Name, Action Setu ctx.Feed.FallAsleep(); ctx.Pool.WakeUpAll(); - for (int index = 0; index < ctx.SyncPeerMocks.Length; index++) + foreach (SyncPeerMock mock in ctx.SyncPeerMocks) { - SyncPeerMock mock = ctx.SyncPeerMocks[index]; mock.SetFilter(null); } await ActivateAndWait(ctx, dbContext, 1024); dbContext.CompareTrees("END"); - dbContext.CompareCodeDbs(); dbContext.AssertFlushed(); } @@ -139,15 +143,14 @@ public async Task Can_download_in_multiple_connections((string Name, Action + SafeContext ctx = PrepareDownloader(dbContext, mock => mock.SetFilter(new[] { dbContext.RemoteStateTree.RootHash })); await ActivateAndWait(ctx, dbContext, 1024, 1000); ctx.Pool.WakeUpAll(); - for (int index = 0; index < ctx.SyncPeerMocks.Length; index++) + foreach (SyncPeerMock mock in ctx.SyncPeerMocks) { - SyncPeerMock mock = ctx.SyncPeerMocks[index]; mock.SetFilter(null); } @@ -169,7 +172,7 @@ public async Task Can_download_when_executor_sends_shorter_responses((string Nam dbContext.CompareTrees("BEGIN"); - SafeContext ctx = PrepareDownloader(dbContext, (mock) => mock.MaxResponseLength = 1); + SafeContext ctx = PrepareDownloader(dbContext, mock => mock.MaxResponseLength = 1); await ActivateAndWait(ctx, dbContext, 1024); @@ -205,7 +208,7 @@ public async Task Can_download_with_moving_target((string Name, Action + SafeContext ctx = PrepareDownloader(dbContext, mock => mock.SetFilter(((MemDb)dbContext.RemoteStateDb).Keys.Take(((MemDb)dbContext.RemoteStateDb).Keys.Count - 1).Select(k => new Keccak(k)).ToArray())); await ActivateAndWait(ctx, dbContext, 1024, 1000); @@ -230,9 +233,8 @@ public async Task Can_download_with_moving_target((string Name, Action - // { - // Assert.AreEqual(0, _pool.InitializedPeers.Count(p => p.CanBeAllocated(AllocationContexts.All))); - // }); - // } - - // [Test] - // [Retry(3)] - // public async Task Silences_when_peer_sends_empty_byte_arrays() - // { - // DbContext dbContext = new DbContext(_logger, _logManager); - // SyncPeerMock mock = new SyncPeerMock(dbContext.RemoteStateDb, dbContext.RemoteCodeDb, SyncPeerMock.EmptyArraysInResponses); - // SafeContext ctx = PrepareDownloader(mock); - // _feed.SetNewStateRoot(1024, Keccak.Compute("the_peer_has_no_data")); - // _feed.Activate(); - // await Task.WhenAny(_stateSyncDispatcher.Start(CancellationToken.None), Task.Delay(1000)).Unwrap() - // .ContinueWith(t => - // { - // _pool.InitializedPeers.Count(p => p.CanBeAllocated(AllocationContexts.All)).Should().Be(0); - // }); - // } } } diff --git a/src/Nethermind/Nethermind.Synchronization.Test/FastSync/StateSyncFeedTestsBase.cs b/src/Nethermind/Nethermind.Synchronization.Test/FastSync/StateSyncFeedTestsBase.cs index 9d556abd6f5..dd8fe63eece 100644 --- a/src/Nethermind/Nethermind.Synchronization.Test/FastSync/StateSyncFeedTestsBase.cs +++ b/src/Nethermind/Nethermind.Synchronization.Test/FastSync/StateSyncFeedTestsBase.cs @@ -3,7 +3,6 @@ using System; using System.Collections.Generic; -using System.Diagnostics; using System.Linq; using System.Threading; using System.Threading.Tasks; @@ -37,11 +36,11 @@ public class StateSyncFeedTestsBase { private const int TimeoutLength = 5000; - protected static IBlockTree _blockTree; + private static IBlockTree? _blockTree; protected static IBlockTree BlockTree => LazyInitializer.EnsureInitialized(ref _blockTree, () => Build.A.BlockTree().OfChainLength(100).TestObject); - protected ILogger _logger; - protected ILogManager _logManager; + protected ILogger _logger = null!; + protected ILogManager _logManager = null!; private readonly int _defaultPeerCount; private readonly int _defaultPeerMaxRandomLatency; @@ -96,35 +95,38 @@ protected SafeContext PrepareDownloader(DbContext dbContext, Action syncPeers) { - SafeContext ctx = new SafeContext(); - ctx = new SafeContext(); - BlockTree blockTree = Build.A.BlockTree().OfChainLength((int)BlockTree.BestSuggestedHeader.Number).TestObject; + SafeContext ctx = new(); + BlockTree blockTree = Build.A.BlockTree().OfChainLength((int)BlockTree.BestSuggestedHeader!.Number).TestObject; ITimerFactory timerFactory = Substitute.For(); ctx.Pool = new SyncPeerPool(blockTree, new NodeStatsManager(timerFactory, LimboLogs.Instance), new TotalDifficultyBetterPeerStrategy(LimboLogs.Instance), LimboLogs.Instance, 25); ctx.Pool.Start(); - for (int i = 0; i < syncPeers.Length; i++) + foreach (ISyncPeer syncPeer in syncPeers) { - ctx.Pool.AddPeer(syncPeers[i]); + ctx.Pool.AddPeer(syncPeer); } - SyncConfig syncConfig = new SyncConfig(); - syncConfig.FastSync = true; ctx.SyncModeSelector = StaticSelector.StateNodesWithFastBlocks; ctx.TreeFeed = new(SyncMode.StateNodes, dbContext.LocalCodeDb, dbContext.LocalStateDb, blockTree, _logManager); ctx.Feed = new StateSyncFeed(ctx.SyncModeSelector, ctx.TreeFeed, _logManager); ctx.Downloader = new StateSyncDownloader(_logManager); - ctx.StateSyncDispatcher = new SyncDispatcher(0, ctx.Feed, ctx.Downloader, ctx.Pool, new StateSyncAllocationStrategyFactory(), _logManager); - ctx.StateSyncDispatcher.Start(CancellationToken.None); + ctx.StateSyncDispatcher = new SyncDispatcher( + 0, + ctx.Feed!, + ctx.Downloader, + ctx.Pool, + new StateSyncAllocationStrategyFactory(), + _logManager); + Task _ = ctx.StateSyncDispatcher.Start(CancellationToken.None); return ctx; } protected async Task ActivateAndWait(SafeContext safeContext, DbContext dbContext, long blockNumber, int timeout = TimeoutLength) { - DotNetty.Common.Concurrency.TaskCompletionSource dormantAgainSource = new DotNetty.Common.Concurrency.TaskCompletionSource(); - safeContext.Feed.StateChanged += (s, e) => + DotNetty.Common.Concurrency.TaskCompletionSource dormantAgainSource = new(); + safeContext.Feed.StateChanged += (_, e) => { if (e.NewState == SyncFeedState.Dormant) { @@ -134,7 +136,7 @@ protected async Task ActivateAndWait(SafeContext safeContext, DbContext dbContex safeContext.TreeFeed.ResetStateRoot(blockNumber, dbContext.RemoteStateTree.RootHash, safeContext.Feed.CurrentState); safeContext.Feed.Activate(); - var watch = Stopwatch.StartNew(); + await Task.WhenAny( dormantAgainSource.Task, Task.Delay(timeout)); @@ -142,13 +144,13 @@ await Task.WhenAny( protected class SafeContext { - public ISyncModeSelector SyncModeSelector; - public SyncPeerMock[] SyncPeerMocks; - public ISyncPeerPool Pool; - public TreeSync TreeFeed; - public StateSyncFeed Feed; - public StateSyncDownloader Downloader; - public SyncDispatcher StateSyncDispatcher; + public ISyncModeSelector SyncModeSelector { get; set; } = null!; + public SyncPeerMock[] SyncPeerMocks { get; set; } = null!; + public ISyncPeerPool Pool { get; set; } = null!; + public TreeSync TreeFeed { get; set; } = null!; + public StateSyncFeed Feed { get; set; } = null!; + public StateSyncDownloader Downloader { get; set; } = null!; + public SyncDispatcher StateSyncDispatcher { get; set; } = null!; } protected class DbContext @@ -204,21 +206,6 @@ public void CompareTrees(string stage, bool skipLogs = false) Assert.That(collector.Stats.MissingNodes, Is.EqualTo(0)); Assert.That(collector.Stats.MissingCode, Is.EqualTo(0)); } - - // Assert.AreEqual(dbContext._remoteCodeDb.Keys.OrderBy(k => k, Bytes.Comparer).ToArray(), dbContext._localCodeDb.Keys.OrderBy(k => k, Bytes.Comparer).ToArray(), "keys"); - // Assert.AreEqual(dbContext._remoteCodeDb.Values.OrderBy(k => k, Bytes.Comparer).ToArray(), dbContext._localCodeDb.Values.OrderBy(k => k, Bytes.Comparer).ToArray(), "values"); - // - // Assert.AreEqual(dbContext._remoteDb.Keys.OrderBy(k => k, Bytes.Comparer).ToArray(), _localDb.Keys.OrderBy(k => k, Bytes.Comparer).ToArray(), "keys"); - // Assert.AreEqual(dbContext._remoteDb.Values.OrderBy(k => k, Bytes.Comparer).ToArray(), _localDb.Values.OrderBy(k => k, Bytes.Comparer).ToArray(), "values"); - } - - public void CompareCodeDbs() - { - // Assert.AreEqual(dbContext._remoteCodeDb.Keys.OrderBy(k => k, Bytes.Comparer).ToArray(), dbContext._localCodeDb.Keys.OrderBy(k => k, Bytes.Comparer).ToArray(), "keys"); - // Assert.AreEqual(dbContext._remoteCodeDb.Values.OrderBy(k => k, Bytes.Comparer).ToArray(), dbContext._localCodeDb.Values.OrderBy(k => k, Bytes.Comparer).ToArray(), "values"); - - // Assert.AreEqual(dbContext._remoteDb.Keys.OrderBy(k => k, Bytes.Comparer).ToArray(), _localDb.Keys.OrderBy(k => k, Bytes.Comparer).ToArray(), "keys"); - // Assert.AreEqual(dbContext._remoteDb.Values.OrderBy(k => k, Bytes.Comparer).ToArray(), _localDb.Values.OrderBy(k => k, Bytes.Comparer).ToArray(), "values"); } public void AssertFlushed() @@ -232,145 +219,122 @@ protected class SyncPeerMock : ISyncPeer { public string Name => "Mock"; - public static Func, Task> NotPreimage = request => - { - var result = new byte[request.Count][]; - - int i = 0; - foreach (Keccak _ in request) result[i++] = new byte[] { 1, 2, 3 }; - - return Task.FromResult(result); - }; - - public static Func, Task> EmptyArraysInResponses = request => - { - var result = new byte[request.Count][]; - - int i = 0; - foreach (Keccak _ in request) result[i++] = new byte[0]; - - return Task.FromResult(result); - }; - private readonly IDb _codeDb; private readonly IDb _stateDb; - private Func, Task> _executorResultFunction; - - private Keccak[] _filter; - + private Keccak[]? _filter; + private readonly Func, Task>? _executorResultFunction; private readonly long _maxRandomizedLatencyMs; public SyncPeerMock( IDb stateDb, IDb codeDb, - Func, Task> executorResultFunction = null, + Func, Task>? executorResultFunction = null, long? maxRandomizedLatencyMs = null, Node? node = null ) { _stateDb = stateDb; _codeDb = codeDb; - - if (executorResultFunction is not null) _executorResultFunction = executorResultFunction; + _executorResultFunction = executorResultFunction; Node = node ?? new Node(TestItem.PublicKeyA, "127.0.0.1", 30302, true) { EthDetails = "eth66" }; _maxRandomizedLatencyMs = maxRandomizedLatencyMs ?? 0; } public int MaxResponseLength { get; set; } = int.MaxValue; - - public Node Node { get; } + public Keccak HeadHash { get; set; } = null!; + public string ProtocolCode { get; } = null!; + public byte ProtocolVersion { get; } = default; public string ClientId => "executorMock"; - public Keccak HeadHash { get; set; } + public Node Node { get; } public long HeadNumber { get; set; } public UInt256 TotalDifficulty { get; set; } public bool IsInitialized { get; set; } public bool IsPriority { get; set; } - public byte ProtocolVersion { get; } - public string ProtocolCode { get; } - public void Disconnect(DisconnectReason reason, string details) + public PublicKey Id => Node.Id; + + public async Task GetNodeData(IReadOnlyList hashes, CancellationToken token) { - throw new NotImplementedException(); + if (_maxRandomizedLatencyMs != 0) + { + await Task.Delay(TimeSpan.FromMilliseconds(TestContext.CurrentContext.Random.NextLong() % _maxRandomizedLatencyMs)); + } + + if (_executorResultFunction is not null) return await _executorResultFunction(hashes); + + byte[][] responses = new byte[hashes.Count][]; + + int i = 0; + foreach (Keccak item in hashes) + { + if (i >= MaxResponseLength) break; + + if (_filter is null || _filter.Contains(item)) responses[i] = _stateDb[item.Bytes] ?? _codeDb[item.Bytes]!; + + i++; + } + + return responses; } - public Task GetBlockBodies(IReadOnlyList blockHashes, CancellationToken token) + public void SetFilter(Keccak[]? availableHashes) { - throw new NotImplementedException(); + _filter = availableHashes; } - public Task GetBlockHeaders(Keccak blockHash, int maxBlocks, int skip, CancellationToken token) + public bool TryGetSatelliteProtocol(string protocol, out T protocolHandler) where T : class { - throw new NotImplementedException(); + protocolHandler = null!; + return false; } - public Task GetBlockHeaders(long number, int maxBlocks, int skip, CancellationToken token) + public void RegisterSatelliteProtocol(string protocol, T protocolHandler) where T : class { throw new NotImplementedException(); } - public Task GetHeadBlockHeader(Keccak? hash, CancellationToken token) + public void Disconnect(DisconnectReason reason, string details) { - return Task.FromResult(BlockTree.Head?.Header); + throw new NotImplementedException(); } - public void NotifyOfNewBlock(Block block, SendBlockMode mode) + public Task GetBlockBodies(IReadOnlyList blockHashes, CancellationToken token) { throw new NotImplementedException(); } - public PublicKey Id => Node.Id; - - public void SendNewTransactions(IEnumerable txs, bool sendFullTx) + public Task GetBlockHeaders(Keccak blockHash, int maxBlocks, int skip, CancellationToken token) { throw new NotImplementedException(); } - public Task GetReceipts(IReadOnlyList blockHash, CancellationToken token) + public Task GetBlockHeaders(long number, int maxBlocks, int skip, CancellationToken token) { throw new NotImplementedException(); } - public async Task GetNodeData(IReadOnlyList hashes, CancellationToken token) + public Task GetHeadBlockHeader(Keccak? hash, CancellationToken token) { - if (_maxRandomizedLatencyMs != 0) - { - await Task.Delay(TimeSpan.FromMilliseconds(TestContext.CurrentContext.Random.NextLong() % _maxRandomizedLatencyMs)); - } - - if (_executorResultFunction is not null) return await _executorResultFunction(hashes); - - var responses = new byte[hashes.Count][]; - - int i = 0; - foreach (Keccak item in hashes) - { - if (i >= MaxResponseLength) break; - - if (_filter is null || _filter.Contains(item)) responses[i] = _stateDb[item.Bytes] ?? _codeDb[item.Bytes]; - - i++; - } - - return responses; + return Task.FromResult(BlockTree.Head?.Header); } - public void SetFilter(Keccak[] availableHashes) + public void NotifyOfNewBlock(Block block, SendBlockMode mode) { - _filter = availableHashes; + throw new NotImplementedException(); } - public void RegisterSatelliteProtocol(string protocol, T protocolHandler) where T : class + public void SendNewTransactions(IEnumerable txs, bool sendFullTx) { throw new NotImplementedException(); } - public bool TryGetSatelliteProtocol(string protocol, out T protocolHandler) where T : class + public Task GetReceipts(IReadOnlyList blockHash, CancellationToken token) { - protocolHandler = null!; - return false; + throw new NotImplementedException(); } + } } } diff --git a/src/Nethermind/Nethermind.Synchronization.Test/LatencySyncPeerMock.cs b/src/Nethermind/Nethermind.Synchronization.Test/LatencySyncPeerMock.cs deleted file mode 100644 index 8047fa3e557..00000000000 --- a/src/Nethermind/Nethermind.Synchronization.Test/LatencySyncPeerMock.cs +++ /dev/null @@ -1,117 +0,0 @@ -// SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited -// SPDX-License-Identifier: LGPL-3.0-only - -using System; -using System.Collections.Generic; -using System.Threading; -using System.Threading.Tasks; -using Nethermind.Blockchain; -using Nethermind.Blockchain.Synchronization; -using Nethermind.Core; -using Nethermind.Core.Crypto; -using Nethermind.Core.Test.Builders; -using Nethermind.Int256; -using Nethermind.Stats.Model; - -namespace Nethermind.Synchronization.Test -{ - /// - /// Mock of a sync peer that allows controlling concurrency issues without spawning tasks. - /// By controlling latency parameters we can test various ordering of responses, timeouts and other issues without unpredictable results from tests running on multiple threads. - /// - public class LatencySyncPeerMock : ISyncPeer - { - public string Name => "Latency"; - public IBlockTree Tree { get; } - public bool IsReported { get; set; } = false; - public long? BusyUntil { get; set; } - public int Latency { get; set; } - public static int RemoteIndex { get; set; } = 1; - - public LatencySyncPeerMock(IBlockTree tree, int latency = 5) - { - Latency = latency; - string localHost = "0.0.0.0"; - string remoteHost = $"{RemoteIndex}.{RemoteIndex}.{RemoteIndex}.{RemoteIndex}"; - - Tree = tree; - HeadNumber = Tree.Head.Number; - HeadHash = Tree.Head.Hash; - TotalDifficulty = Tree.Head.TotalDifficulty ?? 0; - - Node = new Node(TestItem.PrivateKeys[RemoteIndex].PublicKey, remoteHost, 30303); - LocalNode = new Node(TestItem.PrivateKeys[0].PublicKey, localHost, 30303); - Node.ClientId = $"remote {RemoteIndex}"; - LocalNode.ClientId = "local nethermind"; - RemoteIndex++; - } - - public Node Node { get; } - public Node LocalNode { get; } - public string ClientId => Node.ClientId; - public long HeadNumber { get; set; } - public Keccak HeadHash { get; set; } - public UInt256 TotalDifficulty { get; set; } - public bool IsInitialized { get; set; } = true; - public bool IsPriority { get; set; } - public byte ProtocolVersion { get; } - public string ProtocolCode { get; } - - public void Disconnect(DisconnectReason reason, string details) - { - throw new NotImplementedException(); - } - - public Task GetBlockBodies(IReadOnlyList blockHashes, CancellationToken token) - { - throw new NotImplementedException(); - } - - public Task GetBlockHeaders(Keccak blockHash, int maxBlocks, int skip, CancellationToken token) - { - throw new NotImplementedException(); - } - - public Task GetBlockHeaders(long number, int maxBlocks, int skip, CancellationToken token) - { - throw new NotImplementedException(); - } - - public Task GetHeadBlockHeader(Keccak? hash, CancellationToken token) - { - throw new NotImplementedException(); - } - - public void NotifyOfNewBlock(Block block, SendBlockMode mode) - { - throw new NotImplementedException(); - } - - public PublicKey Id => Node.Id; - - public void SendNewTransactions(IEnumerable txs, bool sendFullTx) - { - throw new NotImplementedException(); - } - - public Task GetReceipts(IReadOnlyList blockHash, CancellationToken token) - { - throw new NotImplementedException(); - } - - public Task GetNodeData(IReadOnlyList hashes, CancellationToken token) - { - throw new NotImplementedException(); - } - - public void RegisterSatelliteProtocol(string protocol, T protocolHandler) where T : class - { - throw new NotImplementedException(); - } - - public bool TryGetSatelliteProtocol(string protocol, out T protocolHandler) where T : class - { - throw new NotImplementedException(); - } - } -} diff --git a/src/Nethermind/Nethermind.Synchronization.Test/Nethermind.Synchronization.Test.csproj b/src/Nethermind/Nethermind.Synchronization.Test/Nethermind.Synchronization.Test.csproj index 0972afd2cf9..f6111e7e6ac 100644 --- a/src/Nethermind/Nethermind.Synchronization.Test/Nethermind.Synchronization.Test.csproj +++ b/src/Nethermind/Nethermind.Synchronization.Test/Nethermind.Synchronization.Test.csproj @@ -4,6 +4,7 @@ net7.0 false enable + true diff --git a/src/Nethermind/Nethermind.Synchronization.Test/OldStyleFullSynchronizerTests.cs b/src/Nethermind/Nethermind.Synchronization.Test/OldStyleFullSynchronizerTests.cs index 088a4de1354..03a02069fc5 100644 --- a/src/Nethermind/Nethermind.Synchronization.Test/OldStyleFullSynchronizerTests.cs +++ b/src/Nethermind/Nethermind.Synchronization.Test/OldStyleFullSynchronizerTests.cs @@ -118,15 +118,15 @@ public async Task TearDown() await _synchronizer.StopAsync(); } - private IDb _stateDb; - private IDb _codeDb; - private IBlockTree _blockTree; - private IBlockTree _remoteBlockTree; - private IReceiptStorage _receiptStorage; - private Block _genesisBlock; - private ISyncPeerPool _pool; - private ISyncServer _syncServer; - private ISynchronizer _synchronizer; + private IDb _stateDb = null!; + private IDb _codeDb = null!; + private IBlockTree _blockTree = null!; + private IBlockTree _remoteBlockTree = null!; + private IReceiptStorage _receiptStorage = null!; + private Block _genesisBlock = null!; + private ISyncPeerPool _pool = null!; + private ISyncServer _syncServer = null!; + private ISynchronizer _synchronizer = null!; [Test, Ignore("travis")] public void Retrieves_missing_blocks_in_batches() @@ -135,7 +135,7 @@ public void Retrieves_missing_blocks_in_batches() ISyncPeer peer = new SyncPeerMock(_remoteBlockTree); ManualResetEvent resetEvent = new(false); - _synchronizer.SyncEvent += (sender, args) => + _synchronizer.SyncEvent += (_, args) => { if (args.SyncEvent == SyncEvent.Completed || args.SyncEvent == SyncEvent.Failed) resetEvent.Set(); }; @@ -144,7 +144,7 @@ public void Retrieves_missing_blocks_in_batches() _pool.AddPeer(peer); resetEvent.WaitOne(_standardTimeoutUnit); - Assert.That((int)_blockTree.BestSuggestedHeader.Number, Is.EqualTo(SyncBatchSize.Max * 2 - 1)); + Assert.That(_blockTree.BestSuggestedHeader!.Number, Is.EqualTo(SyncBatchSize.Max * 2 - 1)); } [Test] @@ -157,7 +157,7 @@ public void Syncs_with_empty_peer() _synchronizer.Start(); _pool.AddPeer(peer); - Assert.That((int)_blockTree.BestSuggestedHeader.Number, Is.EqualTo(0)); + Assert.That(_blockTree.BestSuggestedHeader!.Number, Is.EqualTo(0)); } [Test] @@ -168,13 +168,13 @@ public void Syncs_when_knows_more_blocks() ISyncPeer peer = new SyncPeerMock(_remoteBlockTree); ManualResetEvent resetEvent = new(false); - _synchronizer.SyncEvent += (sender, args) => { resetEvent.Set(); }; + _synchronizer.SyncEvent += (_, _) => { resetEvent.Set(); }; _pool.Start(); _synchronizer.Start(); _pool.AddPeer(peer); resetEvent.WaitOne(_standardTimeoutUnit); - Assert.That((int)_blockTree.BestSuggestedHeader.Number, Is.EqualTo(SyncBatchSize.Max * 2 - 1)); + Assert.That(_blockTree.BestSuggestedHeader!.Number, Is.EqualTo(SyncBatchSize.Max * 2 - 1)); } [Test] @@ -185,7 +185,7 @@ public void Can_resync_if_missed_a_block() ISyncPeer peer = new SyncPeerMock(_remoteBlockTree); SemaphoreSlim semaphore = new(0); - _synchronizer.SyncEvent += (sender, args) => + _synchronizer.SyncEvent += (_, args) => { if (args.SyncEvent == SyncEvent.Completed || args.SyncEvent == SyncEvent.Failed) semaphore.Release(1); }; @@ -194,22 +194,24 @@ public void Can_resync_if_missed_a_block() _pool.AddPeer(peer); BlockTreeBuilder.ExtendTree(_remoteBlockTree, SyncBatchSize.Max * 2); - _syncServer.AddNewBlock(_remoteBlockTree.RetrieveHeadBlock(), peer); + _syncServer.AddNewBlock(_remoteBlockTree.RetrieveHeadBlock()!, peer); semaphore.Wait(_standardTimeoutUnit); semaphore.Wait(_standardTimeoutUnit); - Assert.That((int)_blockTree.BestSuggestedHeader.Number, Is.EqualTo(SyncBatchSize.Max * 2 - 1)); + Assert.That(_blockTree.BestSuggestedHeader!.Number, Is.EqualTo(SyncBatchSize.Max * 2 - 1)); } [Test, Ignore("travis")] public void Can_add_new_block() { - _remoteBlockTree = Build.A.BlockTree(_genesisBlock).OfChainLength(SyncBatchSize.Max).TestObject; + _remoteBlockTree = Build.A + .BlockTree(_genesisBlock) + .OfChainLength(SyncBatchSize.Max).TestObject; ISyncPeer peer = new SyncPeerMock(_remoteBlockTree); ManualResetEvent resetEvent = new(false); - _synchronizer.SyncEvent += (sender, args) => + _synchronizer.SyncEvent += (_, args) => { if (args.SyncEvent == SyncEvent.Completed || args.SyncEvent == SyncEvent.Failed) resetEvent.Set(); }; @@ -218,12 +220,15 @@ public void Can_add_new_block() _synchronizer.Start(); _pool.AddPeer(peer); - Block block = Build.A.Block.WithParent(_remoteBlockTree.Head).WithTotalDifficulty((_remoteBlockTree.Head.TotalDifficulty ?? 0) + 1).TestObject; + Block block = Build.A.Block + .WithParent(_remoteBlockTree.Head!) + .WithTotalDifficulty((_remoteBlockTree.Head!.TotalDifficulty ?? 0) + 1) + .TestObject; _syncServer.AddNewBlock(block, peer); resetEvent.WaitOne(_standardTimeoutUnit); - Assert.That((int)_blockTree.BestSuggestedHeader.Number, Is.EqualTo(SyncBatchSize.Max - 1)); + Assert.That(_blockTree.BestSuggestedHeader!.Number, Is.EqualTo(SyncBatchSize.Max - 1)); } [Test] @@ -233,7 +238,7 @@ public void Can_sync_on_split_of_length_1() ISyncPeer miner1 = new SyncPeerMock(miner1Tree); ManualResetEvent resetEvent = new(false); - _synchronizer.SyncEvent += (sender, args) => + _synchronizer.SyncEvent += (_, args) => { if (args.SyncEvent == SyncEvent.Completed || args.SyncEvent == SyncEvent.Failed) resetEvent.Set(); }; @@ -246,7 +251,10 @@ public void Can_sync_on_split_of_length_1() miner1Tree.BestSuggestedHeader.Should().BeEquivalentTo(_blockTree.BestSuggestedHeader, "client agrees with miner before split"); - Block splitBlock = Build.A.Block.WithParent(miner1Tree.FindParent(miner1Tree.Head, BlockTreeLookupOptions.TotalDifficultyNotNeeded)).WithDifficulty(miner1Tree.Head.Difficulty - 1).TestObject; + Block splitBlock = Build.A.Block + .WithParent(miner1Tree.FindParent(miner1Tree.Head!, BlockTreeLookupOptions.TotalDifficultyNotNeeded)!) + .WithDifficulty(miner1Tree.Head!.Difficulty - 1) + .TestObject; Block splitBlockChild = Build.A.Block.WithParent(splitBlock).TestObject; miner1Tree.SuggestBlock(splitBlock); @@ -262,7 +270,7 @@ public void Can_sync_on_split_of_length_1() resetEvent.WaitOne(_standardTimeoutUnit); - Assert.That(_blockTree.BestSuggestedHeader.Hash, Is.EqualTo(miner1Tree.BestSuggestedHeader.Hash), "client agrees with miner after split"); + Assert.That(_blockTree.BestSuggestedHeader!.Hash, Is.EqualTo(miner1Tree.BestSuggestedHeader!.Hash), "client agrees with miner after split"); } [Test] @@ -272,7 +280,7 @@ public void Can_sync_on_split_of_length_6() ISyncPeer miner1 = new SyncPeerMock(miner1Tree); ManualResetEvent resetEvent = new(false); - _synchronizer.SyncEvent += (sender, args) => + _synchronizer.SyncEvent += (_, args) => { if (args.SyncEvent == SyncEvent.Completed || args.SyncEvent == SyncEvent.Failed) resetEvent.Set(); }; @@ -283,7 +291,7 @@ public void Can_sync_on_split_of_length_6() resetEvent.WaitOne(_standardTimeoutUnit); - Assert.That(_blockTree.BestSuggestedHeader.Hash, Is.EqualTo(miner1Tree.BestSuggestedHeader.Hash), "client agrees with miner before split"); + Assert.That(_blockTree.BestSuggestedHeader!.Hash, Is.EqualTo(miner1Tree.BestSuggestedHeader!.Hash), "client agrees with miner before split"); miner1Tree.AddBranch(7, 0, 1); @@ -291,7 +299,7 @@ public void Can_sync_on_split_of_length_6() resetEvent.Reset(); - _syncServer.AddNewBlock(miner1Tree.RetrieveHeadBlock(), miner1); + _syncServer.AddNewBlock(miner1Tree.RetrieveHeadBlock()!, miner1); resetEvent.WaitOne(_standardTimeoutUnit); @@ -306,7 +314,7 @@ public async Task Does_not_do_full_sync_when_not_needed() ISyncPeer miner1 = new SyncPeerMock(minerTree); AutoResetEvent resetEvent = new(false); - _synchronizer.SyncEvent += (sender, args) => + _synchronizer.SyncEvent += (_, args) => { if (args.SyncEvent == SyncEvent.Completed || args.SyncEvent == SyncEvent.Failed) resetEvent.Set(); }; @@ -316,9 +324,9 @@ public async Task Does_not_do_full_sync_when_not_needed() _pool.AddPeer(miner1); resetEvent.WaitOne(_standardTimeoutUnit); - Assert.That(_blockTree.BestSuggestedHeader.Hash, Is.EqualTo(minerTree.BestSuggestedHeader.Hash), "client agrees with miner before split"); + Assert.That(_blockTree.BestSuggestedHeader!.Hash, Is.EqualTo(minerTree.BestSuggestedHeader!.Hash), "client agrees with miner before split"); - Block newBlock = Build.A.Block.WithParent(minerTree.Head).TestObject; + Block newBlock = Build.A.Block.WithParent(minerTree.Head!).TestObject; minerTree.SuggestBlock(newBlock); minerTree.UpdateMainChain(newBlock); @@ -344,7 +352,7 @@ public async Task Does_not_do_full_sync_when_not_needed_with_split() ISyncPeer miner1 = new SyncPeerMock(minerTree); AutoResetEvent resetEvent = new(false); - _synchronizer.SyncEvent += (sender, args) => + _synchronizer.SyncEvent += (_, args) => { if (args.SyncEvent == SyncEvent.Completed || args.SyncEvent == SyncEvent.Failed) resetEvent.Set(); }; @@ -354,9 +362,9 @@ public async Task Does_not_do_full_sync_when_not_needed_with_split() _pool.AddPeer(miner1); resetEvent.WaitOne(_standardTimeoutUnit); - Assert.That(_blockTree.BestSuggestedHeader.Hash, Is.EqualTo(minerTree.BestSuggestedHeader.Hash), "client agrees with miner before split"); + Assert.That(_blockTree.BestSuggestedHeader!.Hash, Is.EqualTo(minerTree.BestSuggestedHeader!.Hash), "client agrees with miner before split"); - Block newBlock = Build.A.Block.WithParent(minerTree.Head).TestObject; + Block newBlock = Build.A.Block.WithParent(minerTree.Head!).TestObject; minerTree.SuggestBlock(newBlock); minerTree.UpdateMainChain(newBlock); @@ -378,21 +386,23 @@ public async Task Does_not_do_full_sync_when_not_needed_with_split() public void Can_retrieve_node_values() { _stateDb.Set(TestItem.KeccakA, TestItem.RandomDataA); - byte[][] values = _syncServer.GetNodeData(new[] { TestItem.KeccakA, TestItem.KeccakB }); - Assert.That(values.Length, Is.EqualTo(2), "data.Length"); - Assert.That(values[0], Is.EqualTo(TestItem.RandomDataA), "data[0]"); - Assert.That(values[1], Is.EqualTo(null), "data[1]"); + byte[]?[] data = _syncServer.GetNodeData(new[] { TestItem.KeccakA, TestItem.KeccakB }); + + Assert.That(data, Is.Not.Null); + Assert.That(data.Length, Is.EqualTo(2), "data.Length"); + Assert.That(data[0], Is.EqualTo(TestItem.RandomDataA), "data[0]"); + Assert.That(data[1], Is.EqualTo(null), "data[1]"); } [Test] public void Can_retrieve_empty_receipts() { _blockTree = Build.A.BlockTree(_genesisBlock).OfChainLength(2).TestObject; - Block block0 = _blockTree.FindBlock(0, BlockTreeLookupOptions.None); - Block block1 = _blockTree.FindBlock(1, BlockTreeLookupOptions.None); + Block? block0 = _blockTree.FindBlock(0, BlockTreeLookupOptions.None); + Block? block1 = _blockTree.FindBlock(1, BlockTreeLookupOptions.None); - _syncServer.GetReceipts(block0.Hash).Should().HaveCount(0); - _syncServer.GetReceipts(block1.Hash).Should().HaveCount(0); + _syncServer.GetReceipts(block0!.Hash!).Should().HaveCount(0); + _syncServer.GetReceipts(block1!.Hash!).Should().HaveCount(0); _syncServer.GetReceipts(TestItem.KeccakA).Should().HaveCount(0); } } diff --git a/src/Nethermind/Nethermind.Synchronization.Test/ParallelSync/MultiSyncModeSelectorFastSyncTests.cs b/src/Nethermind/Nethermind.Synchronization.Test/ParallelSync/MultiSyncModeSelectorFastSyncTests.cs index 33f96b1ec42..fdcf1180d56 100644 --- a/src/Nethermind/Nethermind.Synchronization.Test/ParallelSync/MultiSyncModeSelectorFastSyncTests.cs +++ b/src/Nethermind/Nethermind.Synchronization.Test/ParallelSync/MultiSyncModeSelectorFastSyncTests.cs @@ -614,7 +614,7 @@ public void Switch_correctly_from_full_sync_to_state_nodes_catch_up() syncPeers.Add(syncPeer); ISyncPeerPool syncPeerPool = Substitute.For(); - IEnumerable peerInfos = syncPeers.Select(p => new PeerInfo(p)); + IEnumerable peerInfos = syncPeers.Select(p => new PeerInfo(p)).ToArray(); syncPeerPool.InitializedPeers.Returns(peerInfos); syncPeerPool.AllPeers.Returns(peerInfos); @@ -632,7 +632,7 @@ public void Switch_correctly_from_full_sync_to_state_nodes_catch_up() { long number = header.Number + i; syncPeer.HeadNumber.Returns(number); - syncPeer.TotalDifficulty.Returns(header.TotalDifficulty.Value + i); + syncPeer.TotalDifficulty.Returns(header.TotalDifficulty!.Value + i); syncProgressResolver.FindBestHeader().Returns(number); syncProgressResolver.FindBestFullBlock().Returns(number); selector.Update(); diff --git a/src/Nethermind/Nethermind.Synchronization.Test/ParallelSync/MultiSyncModeSelectorTests.Scenario.cs b/src/Nethermind/Nethermind.Synchronization.Test/ParallelSync/MultiSyncModeSelectorTests.Scenario.cs index e73d09238ab..eca3ae733e2 100644 --- a/src/Nethermind/Nethermind.Synchronization.Test/ParallelSync/MultiSyncModeSelectorTests.Scenario.cs +++ b/src/Nethermind/Nethermind.Synchronization.Test/ParallelSync/MultiSyncModeSelectorTests.Scenario.cs @@ -25,17 +25,33 @@ public static class Scenario { public const long FastSyncCatchUpHeightDelta = 64; - public static BlockHeader Pivot { get; set; } = Build.A.Block.WithDifficulty(1).WithTotalDifficulty((UInt256)1024).WithNumber(1024).TestObject.Header; - - public static BlockHeader MidWayToPivot { get; set; } = Build.A.Block.WithDifficulty(1).WithTotalDifficulty((UInt256)512).WithNumber(512).TestObject.Header; - - public static BlockHeader ChainHead { get; set; } = Build.A.Block.WithDifficulty(1).WithTotalDifficulty(Pivot.TotalDifficulty + 2048).WithNumber(Pivot.Number + 2048).TestObject.Header; + public static BlockHeader Pivot { get; } = Build.A.Block + .WithDifficulty(1) + .WithTotalDifficulty((UInt256)1024) + .WithNumber(1024) + .TestObject.Header; + + public static BlockHeader MidWayToPivot { get; } = Build.A.Block + .WithDifficulty(1) + .WithTotalDifficulty((UInt256)512) + .WithNumber(512) + .TestObject.Header; + + public static BlockHeader ChainHead { get; } = Build.A.Block + .WithDifficulty(1) + .WithTotalDifficulty(Pivot.TotalDifficulty + 2048) + .WithNumber(Pivot.Number + 2048) + .TestObject.Header; public static BlockHeader ChainHeadWrongDifficulty { get { - BlockHeader header = Build.A.Block.WithDifficulty(1).WithTotalDifficulty(Pivot.TotalDifficulty + 2048 + 128).WithNumber(Pivot.Number + 2048).TestObject.Header; + BlockHeader header = Build.A.Block + .WithDifficulty(1) + .WithTotalDifficulty(Pivot.TotalDifficulty + 2048 + 128) + .WithNumber(Pivot.Number + 2048) + .TestObject.Header; header.Hash = ChainHead.Hash; return header; } @@ -51,21 +67,53 @@ public static BlockHeader ChainHeadParentWrongDifficulty } } - public static BlockHeader FutureHead { get; set; } = Build.A.Block.WithDifficulty(1).WithTotalDifficulty(Pivot.TotalDifficulty + 2048 + 128).WithNumber(Pivot.Number + 2048 + 128).TestObject.Header; - - public static BlockHeader SlightlyFutureHead { get; set; } = Build.A.Block.WithDifficulty(1).WithTotalDifficulty(Pivot.TotalDifficulty + 2048 + 4).WithNumber(Pivot.Number + 2048 + 4).TestObject.Header; - - public static BlockHeader SlightlyFutureHeadWithFastSyncLag { get; set; } = Build.A.Block.WithDifficulty(1).WithTotalDifficulty(Pivot.TotalDifficulty + 2048 + 4).WithNumber(ChainHead.Number + MultiSyncModeSelector.FastSyncLag + 1).TestObject.Header; - - public static BlockHeader MaliciousPrePivot { get; set; } = Build.A.Block.WithDifficulty(1).WithTotalDifficulty((UInt256)1000000).WithNumber(512).TestObject.Header; - - public static BlockHeader NewBetterBranchWithLowerNumber { get; set; } = Build.A.Block.WithDifficulty(1).WithTotalDifficulty((UInt256)1000000).WithNumber(ChainHead.Number - 16).TestObject.Header; - - public static BlockHeader ValidGenesis { get; set; } = Build.A.Block.WithDifficulty(1).WithTotalDifficulty(UInt256.One).Genesis.TestObject.Header; - - public static BlockHeader InvalidGenesis { get; set; } = Build.A.Block.WithDifficulty(1).WithTotalDifficulty(UInt256.One).Genesis.TestObject.Header; - - public static BlockHeader InvalidGenesisWithHighTotalDifficulty { get; set; } = Build.A.Block.Genesis.WithDifficulty((UInt256)1000000).WithTotalDifficulty((UInt256)1000000).TestObject.Header; + public static BlockHeader FutureHead { get; } = Build.A.Block + .WithDifficulty(1) + .WithTotalDifficulty(Pivot.TotalDifficulty + 2048 + 128) + .WithNumber(Pivot.Number + 2048 + 128) + .TestObject.Header; + + public static BlockHeader SlightlyFutureHead { get; } = Build.A.Block + .WithDifficulty(1) + .WithTotalDifficulty(Pivot.TotalDifficulty + 2048 + 4) + .WithNumber(Pivot.Number + 2048 + 4) + .TestObject.Header; + + public static BlockHeader SlightlyFutureHeadWithFastSyncLag { get; } = Build.A.Block + .WithDifficulty(1) + .WithTotalDifficulty(Pivot.TotalDifficulty + 2048 + 4) + .WithNumber(ChainHead.Number + MultiSyncModeSelector.FastSyncLag + 1) + .TestObject.Header; + + public static BlockHeader MaliciousPrePivot { get; } = Build.A.Block + .WithDifficulty(1) + .WithTotalDifficulty((UInt256)1000000) + .WithNumber(512) + .TestObject.Header; + + public static BlockHeader NewBetterBranchWithLowerNumber { get; } = Build.A.Block + .WithDifficulty(1) + .WithTotalDifficulty((UInt256)1000000) + .WithNumber(ChainHead.Number - 16) + .TestObject.Header; + + public static BlockHeader ValidGenesis { get; } = Build.A.Block + .WithDifficulty(1) + .WithTotalDifficulty(UInt256.One) + .Genesis + .TestObject.Header; + + public static BlockHeader InvalidGenesis { get; } = Build.A.Block + .WithDifficulty(1) + .WithTotalDifficulty(UInt256.One) + .Genesis + .TestObject.Header; + + public static BlockHeader InvalidGenesisWithHighTotalDifficulty { get; } = Build.A.Block + .Genesis + .WithDifficulty((UInt256)1000000) + .WithTotalDifficulty((UInt256)1000000) + .TestObject.Header; public static IEnumerable ScenarioHeaders { @@ -99,20 +147,19 @@ public class ScenarioBuilder private readonly List _peers = new(); private bool _needToWaitForHeaders; - public ISyncPeerPool SyncPeerPool { get; set; } + public ISyncPeerPool SyncPeerPool { get; set; } = null!; - public ISyncProgressResolver SyncProgressResolver { get; set; } + public ISyncProgressResolver SyncProgressResolver { get; set; } = null!; - public ISyncConfig SyncConfig { get; set; } = new SyncConfig(); + public ISyncConfig SyncConfig { get; } = new SyncConfig(); public IBeaconSyncStrategy BeaconSyncStrategy { get; set; } = No.BeaconSync; private void SetDefaults() { SyncPeerPool = Substitute.For(); - var peerInfos = _peers.Select(p => new PeerInfo(p)); - SyncPeerPool.InitializedPeers.Returns(peerInfos); - SyncPeerPool.AllPeers.Returns(peerInfos); + SyncPeerPool.InitializedPeers.Returns(_peers.Select(p => new PeerInfo(p))); + SyncPeerPool.AllPeers.Returns(_peers.Select(p => new PeerInfo(p))); SyncProgressResolver = Substitute.For(); SyncProgressResolver.ChainDifficulty.Returns(ValidGenesis.TotalDifficulty ?? 0); @@ -814,16 +861,11 @@ void Test() { foreach (Func configSetups in _configActions) { - string syncProgressSetupName = syncProgressSetup.Invoke(); - string peeringSetupName = peeringSetup.Invoke(); - string configSetupName = configSetups.Invoke(); - - // Console.WriteLine("====================="); - // Console.WriteLine(syncProgressSetupName); - // Console.WriteLine(peeringSetupName); - // Console.WriteLine(configSetupName); + syncProgressSetup.Invoke(); + peeringSetup.Invoke(); + configSetups.Invoke(); + Test(); - // Console.WriteLine("====================="); } } } diff --git a/src/Nethermind/Nethermind.Synchronization.Test/ParallelSync/SyncDispatcherTests.cs b/src/Nethermind/Nethermind.Synchronization.Test/ParallelSync/SyncDispatcherTests.cs index eab673a53ea..bdd075712c3 100644 --- a/src/Nethermind/Nethermind.Synchronization.Test/ParallelSync/SyncDispatcherTests.cs +++ b/src/Nethermind/Nethermind.Synchronization.Test/ParallelSync/SyncDispatcherTests.cs @@ -106,13 +106,13 @@ public Task StopAsync() return Task.CompletedTask; } - public PeerInfo GetPeer(Node node) + public PeerInfo? GetPeer(Node node) { return null; } - public event EventHandler NotifyPeerBlock; - public event EventHandler PeerRefreshed; + public event EventHandler NotifyPeerBlock = delegate { }; + public event EventHandler PeerRefreshed = delegate { }; } private class TestBatch @@ -125,7 +125,7 @@ public TestBatch(int start, int length) public int Start { get; } public int Length { get; } - public int[] Result { get; set; } + public int[]? Result { get; set; } } private class TestDownloader : ISyncDownloader @@ -159,15 +159,12 @@ public TestSyncFeed(bool isMultiFeed = true, int max = 64) Max = max; } - public int Max; + public int Max { get; } + public int HighestRequested { get; private set; } - public int HighestRequested; - - public HashSet _results = new(); - - private ConcurrentQueue _returned = new(); - - private ManualResetEvent _responseLock = new ManualResetEvent(true); + public readonly HashSet _results = new(); + private readonly ConcurrentQueue _returned = new(); + private readonly ManualResetEvent _responseLock = new ManualResetEvent(true); public void LockResponse() { @@ -179,7 +176,7 @@ public void UnlockResponse() _responseLock.Set(); } - public override SyncResponseHandlingResult HandleResponse(TestBatch response, PeerInfo peer = null) + public override SyncResponseHandlingResult HandleResponse(TestBatch response, PeerInfo? peer = null) { _responseLock.WaitOne(); if (response.Result is null) @@ -211,7 +208,7 @@ public override SyncResponseHandlingResult HandleResponse(TestBatch response, Pe public override async Task PrepareRequest(CancellationToken token = default) { TestBatch testBatch; - if (_returned.TryDequeue(out TestBatch returned)) + if (_returned.TryDequeue(out TestBatch? returned)) { Console.WriteLine("Sending previously failed batch"); testBatch = returned; @@ -231,7 +228,7 @@ public override async Task PrepareRequest(CancellationToken token = d Finish(); } - return null; + return null!; } lock (_results) @@ -288,7 +285,7 @@ public async Task Test_release_before_processing_complete(bool isMultiSync, int new StaticPeerAllocationStrategyFactory(FirstFree.Instance), LimboLogs.Instance); - Task executorTask = dispatcher.Start(CancellationToken.None); + Task _ = dispatcher.Start(CancellationToken.None); syncFeed.Activate(); await Task.Delay(100); diff --git a/src/Nethermind/Nethermind.Synchronization.Test/SnapSync/ProgressTrackerTests.cs b/src/Nethermind/Nethermind.Synchronization.Test/SnapSync/ProgressTrackerTests.cs index 21aa1208e75..f702e409258 100644 --- a/src/Nethermind/Nethermind.Synchronization.Test/SnapSync/ProgressTrackerTests.cs +++ b/src/Nethermind/Nethermind.Synchronization.Test/SnapSync/ProgressTrackerTests.cs @@ -22,7 +22,7 @@ public class ProgressTrackerTests public async Task Did_not_have_race_issue() { BlockTree blockTree = Build.A.BlockTree().WithBlocks(Build.A.Block.TestObject).TestObject; - ProgressTracker progressTracker = new ProgressTracker(blockTree, new MemDb(), LimboLogs.Instance); + ProgressTracker progressTracker = new(blockTree, new MemDb(), LimboLogs.Instance); progressTracker.EnqueueStorageRange(new StorageRange() { Accounts = Array.Empty(), @@ -60,25 +60,25 @@ public void Will_create_multiple_get_address_range_request() (SnapSyncBatch request, bool finished) = progressTracker.GetNextRequest(); request.AccountRangeRequest.Should().NotBeNull(); request.AccountRangeRequest!.StartingHash.Bytes[0].Should().Be(0); - request.AccountRangeRequest.LimitHash.Value.Bytes[0].Should().Be(64); + request.AccountRangeRequest.LimitHash!.Value.Bytes[0].Should().Be(64); finished.Should().BeFalse(); (request, finished) = progressTracker.GetNextRequest(); request.AccountRangeRequest.Should().NotBeNull(); request.AccountRangeRequest!.StartingHash.Bytes[0].Should().Be(64); - request.AccountRangeRequest.LimitHash.Value.Bytes[0].Should().Be(128); + request.AccountRangeRequest.LimitHash!.Value.Bytes[0].Should().Be(128); finished.Should().BeFalse(); (request, finished) = progressTracker.GetNextRequest(); request.AccountRangeRequest.Should().NotBeNull(); request.AccountRangeRequest!.StartingHash.Bytes[0].Should().Be(128); - request.AccountRangeRequest.LimitHash.Value.Bytes[0].Should().Be(192); + request.AccountRangeRequest.LimitHash!.Value.Bytes[0].Should().Be(192); finished.Should().BeFalse(); (request, finished) = progressTracker.GetNextRequest(); request.AccountRangeRequest.Should().NotBeNull(); request.AccountRangeRequest!.StartingHash.Bytes[0].Should().Be(192); - request.AccountRangeRequest.LimitHash.Value.Bytes[0].Should().Be(255); + request.AccountRangeRequest.LimitHash!.Value.Bytes[0].Should().Be(255); finished.Should().BeFalse(); (request, finished) = progressTracker.GetNextRequest(); @@ -102,7 +102,7 @@ public void Will_deque_code_request_if_high_even_if_storage_queue_is_not_empty() for (int i = 0; i < ProgressTracker.HIGH_CODES_QUEUE_SIZE; i++) { - progressTracker.EnqueueCodeHashes(new ValueKeccak[] { TestItem.ValueKeccaks[0] }); + progressTracker.EnqueueCodeHashes(new[] { TestItem.ValueKeccaks[0] }); } (SnapSyncBatch request, bool _) = progressTracker.GetNextRequest(); @@ -127,7 +127,7 @@ public void Will_deque_storage_request_if_high() for (int i = 0; i < ProgressTracker.HIGH_CODES_QUEUE_SIZE; i++) { - progressTracker.EnqueueCodeHashes(new ValueKeccak[] { TestItem.ValueKeccaks[0] }); + progressTracker.EnqueueCodeHashes(new[] { TestItem.ValueKeccaks[0] }); } (SnapSyncBatch request, bool _) = progressTracker.GetNextRequest(); diff --git a/src/Nethermind/Nethermind.Synchronization.Test/SyncPeerMock.cs b/src/Nethermind/Nethermind.Synchronization.Test/SyncPeerMock.cs index 0323a5a98c0..52018d6f79a 100644 --- a/src/Nethermind/Nethermind.Synchronization.Test/SyncPeerMock.cs +++ b/src/Nethermind/Nethermind.Synchronization.Test/SyncPeerMock.cs @@ -64,15 +64,15 @@ private void RunQueue() public Node Node { get; } - public Node LocalNode { get; } + private Node LocalNode { get; } + public byte ProtocolVersion { get; } = default; + public string ProtocolCode { get; } = null!; public string ClientId => Node.ClientId; public Keccak HeadHash { get; set; } public long HeadNumber { get; set; } public UInt256 TotalDifficulty { get; set; } public bool IsInitialized { get; set; } public bool IsPriority { get; set; } - public byte ProtocolVersion { get; } - public string ProtocolCode { get; } public void Disconnect(DisconnectReason reason, string details) { diff --git a/src/Nethermind/Nethermind.Synchronization.Test/SyncPeerPoolTests.cs b/src/Nethermind/Nethermind.Synchronization.Test/SyncPeerPoolTests.cs index 2a6cf4107ac..e4450756fb8 100644 --- a/src/Nethermind/Nethermind.Synchronization.Test/SyncPeerPoolTests.cs +++ b/src/Nethermind/Nethermind.Synchronization.Test/SyncPeerPoolTests.cs @@ -29,10 +29,10 @@ public class SyncPeerPoolTests { private class Context : IAsyncDisposable { - public INodeStatsManager Stats; - public IBlockTree BlockTree; - public IBetterPeerStrategy PeerStrategy; - public SyncPeerPool Pool; + public INodeStatsManager Stats { get; } + public IBlockTree BlockTree { get; } + public IBetterPeerStrategy PeerStrategy { get; } + public SyncPeerPool Pool { get; set; } public Context() { @@ -57,17 +57,17 @@ public SimpleSyncPeerMock(PublicKey publicKey, string description = "simple mock ClientId = description; } + public Keccak HeadHash { get; set; } = null!; + public byte ProtocolVersion { get; } = default; + public string ProtocolCode { get; } = null!; public Node Node { get; } public string ClientId { get; } - public Keccak HeadHash { get; set; } public long HeadNumber { get; set; } public UInt256 TotalDifficulty { get; set; } = 1; public bool IsInitialized { get; set; } public bool IsPriority { get; set; } - public byte ProtocolVersion { get; } - public string ProtocolCode { get; } - public bool DisconnectRequested { get; set; } + public bool DisconnectRequested { get; private set; } public void Disconnect(DisconnectReason reason, string details) { @@ -175,7 +175,7 @@ public async Task Cannot_add_when_not_started() public async Task Will_disconnect_one_when_at_max() { await using Context ctx = new(); - var peers = await SetupPeers(ctx, 25); + SimpleSyncPeerMock[] peers = await SetupPeers(ctx, 25); await WaitForPeersInitialization(ctx); ctx.Pool.DropUselessPeers(true); Assert.True(peers.Any(p => p.DisconnectRequested)); @@ -186,10 +186,10 @@ public async Task Will_disconnect_one_when_at_max() public async Task Will_disconnect_when_refresh_exception_is_not_cancelled(bool isExceptionOperationCanceled, bool isDisconnectRequested) { await using Context ctx = new(); - var peers = await SetupPeers(ctx, 25); - var peer = peers[0]; + SimpleSyncPeerMock[] peers = await SetupPeers(ctx, 25); + SimpleSyncPeerMock peer = peers[0]; - var refreshException = isExceptionOperationCanceled ? new OperationCanceledException() : new Exception(); + Exception refreshException = isExceptionOperationCanceled ? new OperationCanceledException() : new Exception(); ctx.Pool.ReportRefreshFailed(peer, "test with cancellation", refreshException); peer.DisconnectRequested.Should().Be(isDisconnectRequested); } @@ -203,7 +203,7 @@ public async Task Will_not_disconnect_any_priority_peer_if_their_amount_is_lower const int priorityPeersMaxCount = 25; await using Context ctx = new(); ctx.Pool = new SyncPeerPool(ctx.BlockTree, ctx.Stats, ctx.PeerStrategy, LimboLogs.Instance, peersMaxCount, priorityPeersMaxCount, 50); - var peers = await SetupPeers(ctx, peersMaxCount); + SimpleSyncPeerMock[] peers = await SetupPeers(ctx, peersMaxCount); // setting priority to all peers except one - peers[number] for (int i = 0; i < priorityPeersMaxCount; i++) @@ -225,7 +225,7 @@ public async Task Can_disconnect_priority_peer_if_their_amount_is_max() const int priorityPeersMaxCount = 25; await using Context ctx = new(); ctx.Pool = new SyncPeerPool(ctx.BlockTree, ctx.Stats, ctx.PeerStrategy, LimboLogs.Instance, peersMaxCount, priorityPeersMaxCount, 50); - var peers = await SetupPeers(ctx, peersMaxCount); + SimpleSyncPeerMock[] peers = await SetupPeers(ctx, peersMaxCount); foreach (SimpleSyncPeerMock peer in peers) { @@ -364,10 +364,10 @@ public async Task Can_refresh() { await using Context ctx = new(); ctx.Pool.Start(); - var syncPeer = Substitute.For(); + ISyncPeer? syncPeer = Substitute.For(); syncPeer.Node.Returns(new Node(TestItem.PublicKeyA, "127.0.0.1", 30303)); ctx.Pool.AddPeer(syncPeer); - ctx.Pool.RefreshTotalDifficulty(syncPeer, null); + ctx.Pool.RefreshTotalDifficulty(syncPeer, Keccak.Zero); await Task.Delay(100); Assert.That(() => @@ -396,12 +396,12 @@ public async Task Can_replace_peer_with_better() ctx.Pool.Start(); ctx.Pool.AddPeer(new SimpleSyncPeerMock(TestItem.PublicKeyA, "A")); await WaitForPeersInitialization(ctx); - var allocation = await ctx.Pool.Allocate(new BlocksSyncPeerAllocationStrategy(null)); + SyncPeerAllocation allocation = await ctx.Pool.Allocate(new BlocksSyncPeerAllocationStrategy(null)); bool replaced = false; - allocation.Replaced += (sender, args) => replaced = true; + allocation.Replaced += (_, _) => replaced = true; ctx.Pool.AddPeer(new SimpleSyncPeerMock(TestItem.PublicKeyB, "B")); - await WaitFor(() => replaced, "peer to get replaced"); + await WaitFor(() => replaced); Assert.True(replaced); } @@ -417,7 +417,7 @@ public async Task Does_not_replace_with_a_worse_peer() await WaitForPeersInitialization(ctx); SyncPeerAllocation allocation = await ctx.Pool.Allocate(new BySpeedStrategy(TransferSpeedType.Headers, true)); bool replaced = false; - allocation.Replaced += (sender, args) => replaced = true; + allocation.Replaced += (_, _) => replaced = true; ctx.Pool.AddPeer(new SimpleSyncPeerMock(TestItem.PublicKeyB)); await WaitForPeersInitialization(ctx); @@ -436,7 +436,7 @@ public async Task Does_not_replace_if_too_small_percentage_change() await WaitForPeersInitialization(ctx); SyncPeerAllocation allocation = await ctx.Pool.Allocate(new BySpeedStrategy(TransferSpeedType.Headers, true)); bool replaced = false; - allocation.Replaced += (sender, args) => replaced = true; + allocation.Replaced += (_, _) => replaced = true; ctx.Pool.AddPeer(new SimpleSyncPeerMock(TestItem.PublicKeyB)); await WaitForPeersInitialization(ctx); @@ -455,7 +455,7 @@ public async Task Does_not_replace_on_small_difference_in_low_numbers() await WaitForPeersInitialization(ctx); SyncPeerAllocation allocation = await ctx.Pool.Allocate(new BySpeedStrategy(TransferSpeedType.Headers, true)); bool replaced = false; - allocation.Replaced += (sender, args) => replaced = true; + allocation.Replaced += (_, _) => replaced = true; ctx.Pool.AddPeer(new SimpleSyncPeerMock(TestItem.PublicKeyB)); await WaitForPeersInitialization(ctx); @@ -474,7 +474,7 @@ public async Task Can_stay_when_current_is_best() await WaitForPeersInitialization(ctx); SyncPeerAllocation allocation = await ctx.Pool.Allocate(new BySpeedStrategy(TransferSpeedType.Headers, true)); bool replaced = false; - allocation.Replaced += (sender, args) => replaced = true; + allocation.Replaced += (_, _) => replaced = true; ctx.Pool.AddPeer(new SimpleSyncPeerMock(TestItem.PublicKeyB)); await WaitForPeersInitialization(ctx); Assert.False(replaced); @@ -492,9 +492,9 @@ public async Task Can_list_all_peers() public async Task Can_borrow_peer() { await using Context ctx = new(); - var peers = await SetupPeers(ctx, 1); + SimpleSyncPeerMock[] peers = await SetupPeers(ctx, 1); - var allocation = await ctx.Pool.Allocate(new BySpeedStrategy(TransferSpeedType.Headers, true)); + SyncPeerAllocation allocation = await ctx.Pool.Allocate(new BySpeedStrategy(TransferSpeedType.Headers, true)); Assert.That(allocation.Current?.SyncPeer, Is.SameAs(peers[0])); } @@ -503,9 +503,9 @@ public async Task Can_borrow_peer() public async Task Can_borrow_return_and_borrow_again() { await using Context ctx = new(); - var peers = await SetupPeers(ctx, 1); + SimpleSyncPeerMock[] peers = await SetupPeers(ctx, 1); - var allocation = await ctx.Pool.Allocate(new BySpeedStrategy(TransferSpeedType.Headers, true)); + SyncPeerAllocation allocation = await ctx.Pool.Allocate(new BySpeedStrategy(TransferSpeedType.Headers, true)); ctx.Pool.Free(allocation); allocation = await ctx.Pool.Allocate(new BySpeedStrategy(TransferSpeedType.Headers, true)); ctx.Pool.Free(allocation); @@ -588,8 +588,8 @@ public async Task Initialized_peers() public async Task Report_invalid_invokes_disconnection() { await using Context ctx = new(); - var peers = await SetupPeers(ctx, 3); - var peerInfo = ctx.Pool.InitializedPeers.First(); + SimpleSyncPeerMock[] _ = await SetupPeers(ctx, 3); + PeerInfo peerInfo = ctx.Pool.InitializedPeers.First(); ctx.Pool.ReportBreachOfProtocol(peerInfo, DisconnectReason.Other, "issue details"); Assert.True(((SimpleSyncPeerMock)peerInfo.SyncPeer).DisconnectRequested); @@ -599,10 +599,10 @@ public async Task Report_invalid_invokes_disconnection() public async Task Will_not_allocate_same_peer_to_two_allocations() { await using Context ctx = new(); - var peers = await SetupPeers(ctx, 1); + SimpleSyncPeerMock[] peers = await SetupPeers(ctx, 1); - var allocation1 = await ctx.Pool.Allocate(new BySpeedStrategy(TransferSpeedType.Headers, true)); - var allocation2 = await ctx.Pool.Allocate(new BySpeedStrategy(TransferSpeedType.Headers, true)); + SyncPeerAllocation allocation1 = await ctx.Pool.Allocate(new BySpeedStrategy(TransferSpeedType.Headers, true)); + SyncPeerAllocation allocation2 = await ctx.Pool.Allocate(new BySpeedStrategy(TransferSpeedType.Headers, true)); Assert.That(allocation1.Current?.SyncPeer, Is.SameAs(peers[0])); Assert.Null(allocation2.Current); @@ -612,9 +612,9 @@ public async Task Will_not_allocate_same_peer_to_two_allocations() public async Task Can_remove_borrowed_peer() { await using Context ctx = new(); - var peers = await SetupPeers(ctx, 1); + SimpleSyncPeerMock[] peers = await SetupPeers(ctx, 1); - var allocation = await ctx.Pool.Allocate(new BlocksSyncPeerAllocationStrategy(null)); + SyncPeerAllocation allocation = await ctx.Pool.Allocate(new BlocksSyncPeerAllocationStrategy(null)); ctx.Pool.RemovePeer(peers[0]); Assert.Null(allocation.Current); @@ -624,7 +624,7 @@ public async Task Can_remove_borrowed_peer() public async Task Will_remove_peer_if_times_out_on_init() { await using Context ctx = new(); - var peer = new SimpleSyncPeerMock(TestItem.PublicKeyA); + SimpleSyncPeerMock peer = new SimpleSyncPeerMock(TestItem.PublicKeyA); peer.SetHeaderResponseTime(int.MaxValue); ctx.Pool.Start(); ctx.Pool.AddPeer(peer); @@ -637,12 +637,12 @@ public async Task Will_remove_peer_if_times_out_on_init() public async Task Can_remove_during_init() { await using Context ctx = new(); - var peer = new SimpleSyncPeerMock(TestItem.PublicKeyA); + SimpleSyncPeerMock peer = new SimpleSyncPeerMock(TestItem.PublicKeyA); peer.SetHeaderResponseTime(500); ctx.Pool.Start(); ctx.Pool.AddPeer(peer); - var allocation = await ctx.Pool.Allocate(new BySpeedStrategy(TransferSpeedType.Headers, true)); + SyncPeerAllocation allocation = await ctx.Pool.Allocate(new BySpeedStrategy(TransferSpeedType.Headers, true)); ctx.Pool.RemovePeer(peer); Assert.That(allocation.Current, Is.EqualTo(null)); @@ -653,13 +653,13 @@ public async Task Can_remove_during_init() public async Task It_is_fine_to_fail_init() { await using Context ctx = new(); - var peer = new SimpleSyncPeerMock(TestItem.PublicKeyA); + SimpleSyncPeerMock peer = new SimpleSyncPeerMock(TestItem.PublicKeyA); peer.SetHeaderFailure(true); ctx.Pool.Start(); ctx.Pool.AddPeer(peer); await WaitForPeersInitialization(ctx); - var allocation = await ctx.Pool.Allocate(new BySpeedStrategy(TransferSpeedType.Headers, true)); + SyncPeerAllocation allocation = await ctx.Pool.Allocate(new BySpeedStrategy(TransferSpeedType.Headers, true)); ctx.Pool.RemovePeer(peer); Assert.That(allocation.Current, Is.EqualTo(null)); @@ -672,7 +672,7 @@ public async Task Can_return() await using Context ctx = new(); await SetupPeers(ctx, 1); - var allocation = await ctx.Pool.Allocate(new BySpeedStrategy(TransferSpeedType.Headers, true)); + SyncPeerAllocation allocation = await ctx.Pool.Allocate(new BySpeedStrategy(TransferSpeedType.Headers, true)); ctx.Pool.Free(allocation); } @@ -682,7 +682,7 @@ public async Task Does_not_fail_when_receiving_a_new_block_and_allocation_has_no await using Context ctx = new(); await SetupPeers(ctx, 1); - var allocation = await ctx.Pool.Allocate(new BySpeedStrategy(TransferSpeedType.Headers, true)); + SyncPeerAllocation allocation = await ctx.Pool.Allocate(new BySpeedStrategy(TransferSpeedType.Headers, true)); allocation.Cancel(); ctx.BlockTree.NewHeadBlock += Raise.EventWith(new object(), new BlockEventArgs(Build.A.Block.WithTotalDifficulty(1L).TestObject)); @@ -694,7 +694,7 @@ public async Task Can_borrow_async_many() await using Context ctx = new(); await SetupPeers(ctx, 2); - var allocationTasks = new Task[3]; + Task[] allocationTasks = new Task[3]; for (int i = 0; i < allocationTasks.Length; i++) { allocationTasks[i] = ctx.Pool.Allocate(new BySpeedStrategy(TransferSpeedType.Headers, true), AllocationContexts.All, 50); @@ -702,13 +702,13 @@ public async Task Can_borrow_async_many() await Task.WhenAll(allocationTasks); - var allocations = allocationTasks.Select(t => t.Result).ToArray(); - var successfulAllocations = allocations.Where(r => r.Current is not null).ToArray(); + SyncPeerAllocation[] allocations = allocationTasks.Select(t => t.Result).ToArray(); + SyncPeerAllocation[] successfulAllocations = allocations.Where(r => r.Current is not null).ToArray(); // we had only two peers and 3 borrow calls so only two are successful Assert.That(successfulAllocations.Length, Is.EqualTo(2)); - foreach (var allocation in successfulAllocations) + foreach (SyncPeerAllocation allocation in successfulAllocations) { // free allocated peers ctx.Pool.Free(allocation); @@ -723,7 +723,7 @@ public async Task Can_borrow_async_many() private int _pendingRequests; - private Random _workRandomDelay = new(42); + private readonly Random _workRandomDelay = new(42); private async Task DoWork(string desc, SyncPeerAllocation allocation) { @@ -763,9 +763,7 @@ public async Task Try_to_break_multithreaded() Task task = DoWork(iterationsLocal.ToString(), allocation); -#pragma warning disable 4014 - task.ContinueWith(t => -#pragma warning restore 4014 + Task _ = task.ContinueWith(t => { Console.WriteLine($"{iterationsLocal} Decrement on {t.IsCompleted}"); Interlocked.Decrement(ref _pendingRequests); @@ -783,7 +781,7 @@ public async Task Try_to_break_multithreaded() private async Task SetupPeers(Context ctx, int count) { - var peers = new SimpleSyncPeerMock[count]; + SimpleSyncPeerMock[] peers = new SimpleSyncPeerMock[count]; for (int i = 0; i < count; i++) { peers[i] = new SimpleSyncPeerMock(TestItem.PublicKeys[i]); @@ -802,10 +800,10 @@ private async Task SetupPeers(Context ctx, int count) private async Task WaitForPeersInitialization(Context ctx) { - await WaitFor(() => ctx.Pool.AllPeers.All(p => p.IsInitialized), "peers to initialize"); + await WaitFor(() => ctx.Pool.AllPeers.All(p => p.IsInitialized)); } - private async Task WaitFor(Func isConditionMet, string description = "condition to be met") + private async Task WaitFor(Func isConditionMet) { const int waitInterval = 50; for (int i = 0; i < 20; i++) diff --git a/src/Nethermind/Nethermind.Synchronization.Test/SyncPeersReportTests.cs b/src/Nethermind/Nethermind.Synchronization.Test/SyncPeersReportTests.cs index 25b2212724e..9d342d14a10 100644 --- a/src/Nethermind/Nethermind.Synchronization.Test/SyncPeersReportTests.cs +++ b/src/Nethermind/Nethermind.Synchronization.Test/SyncPeersReportTests.cs @@ -38,9 +38,9 @@ public void Can_write_one_uninitialized() { ISyncPeerPool syncPeerPool = Substitute.For(); - var syncPeer = BuildPeer(false); + PeerInfo syncPeer = BuildPeer(false); - var peers = new[] { syncPeer }; + PeerInfo[] peers = { syncPeer }; syncPeerPool.PeerCount.Returns(peers.Length); SyncPeersReport report = new(syncPeerPool, Substitute.For(), NoErrorLimboLogs.Instance); @@ -52,10 +52,10 @@ public void Can_write_one_uninitialized() public void Can_write_one_uninitialized_one_initialized() { ISyncPeerPool syncPeerPool = Substitute.For(); - var syncPeer = BuildPeer(false); - var syncPeer2 = BuildPeer(true); + PeerInfo syncPeer = BuildPeer(false); + PeerInfo syncPeer2 = BuildPeer(true); - var peers = new[] { syncPeer, syncPeer2 }; + PeerInfo[] peers = { syncPeer, syncPeer2 }; syncPeerPool.PeerCount.Returns(peers.Length); @@ -70,9 +70,9 @@ public void Can_write_report_update() ISyncPeerPool syncPeerPool = Substitute.For(); (PeerInfo syncPeer, StubSyncPeer syncPeerSyncPeer) = BuildPeerWithStubSyncPeer(false); - var syncPeer2 = BuildPeer(true); + PeerInfo syncPeer2 = BuildPeer(true); - var peers = new[] { syncPeer, syncPeer2 }; + PeerInfo[] peers = { syncPeer, syncPeer2 }; syncPeerPool.PeerCount.Returns(peers.Length); @@ -130,9 +130,9 @@ public void Can_write_report_update_with_allocations() { ISyncPeerPool syncPeerPool = Substitute.For(); (PeerInfo syncPeer, StubSyncPeer syncPeerSyncPeer) = BuildPeerWithStubSyncPeer(false); - var syncPeer2 = BuildPeer(true); + PeerInfo syncPeer2 = BuildPeer(true); - var peers = new[] { syncPeer, syncPeer2 }; + PeerInfo[] peers = { syncPeer, syncPeer2 }; syncPeerPool.PeerCount.Returns(peers.Length); syncPeerPool.AllPeers.Returns(peers); @@ -148,13 +148,13 @@ public void Can_write_report_update_with_allocations() [Test] public void PeerFormatIsCorrect() { - var syncPeer = BuildPeer(false); + PeerInfo syncPeer = BuildPeer(false); syncPeer.TryAllocate(AllocationContexts.All); - var syncPeer2 = BuildPeer(true, direction: ConnectionDirection.In); + PeerInfo syncPeer2 = BuildPeer(true, direction: ConnectionDirection.In); syncPeer2.PutToSleep(AllocationContexts.All, DateTime.Now); - var peers = new[] { syncPeer, syncPeer2 }; + PeerInfo[] peers = { syncPeer, syncPeer2 }; ISyncPeerPool syncPeerPool = Substitute.For(); syncPeerPool.PeerCount.Returns(peers.Length); @@ -188,27 +188,24 @@ public StubSyncPeer(bool initialized, string protocolVersion, ISession session, } public override string Name { get; } - public override byte ProtocolVersion { get; } - public override string ProtocolCode { get; } - public override int MessageIdSpaceSize { get; } + public override byte ProtocolVersion { get; } = default; + public override string ProtocolCode { get; } = default!; + public override int MessageIdSpaceSize { get; } = default; + protected override TimeSpan InitTimeout { get; } = default; + public override event EventHandler ProtocolInitialized = delegate { }; + public override event EventHandler SubprotocolRequested = delegate { }; public override void Init() { throw new NotImplementedException(); } - - public override event EventHandler ProtocolInitialized; - public override event EventHandler SubprotocolRequested; - protected override TimeSpan InitTimeout { get; } public override void HandleMessage(ZeroPacket message) { throw new NotImplementedException(); } - public override void NotifyOfNewBlock(Block block, SendBlockMode mode) { throw new NotImplementedException(); } - protected override void OnDisposed() { throw new NotImplementedException(); diff --git a/src/Nethermind/Nethermind.Synchronization.Test/SyncProgressResolverTests.cs b/src/Nethermind/Nethermind.Synchronization.Test/SyncProgressResolverTests.cs index 9a2915b5f92..60cbc1db2f4 100644 --- a/src/Nethermind/Nethermind.Synchronization.Test/SyncProgressResolverTests.cs +++ b/src/Nethermind/Nethermind.Synchronization.Test/SyncProgressResolverTests.cs @@ -13,6 +13,7 @@ using Nethermind.Synchronization.SnapSync; using Nethermind.Trie.Pruning; using NSubstitute; +using NSubstitute.ReturnsExtensions; using NUnit.Framework; namespace Nethermind.Synchronization.Test @@ -27,12 +28,14 @@ public void Header_block_is_0_when_no_header_was_suggested() IBlockTree blockTree = Substitute.For(); IReceiptStorage receiptStorage = Substitute.For(); IDb stateDb = new MemDb(); - SyncConfig syncConfig = new(); - syncConfig.PivotNumber = "1"; + SyncConfig syncConfig = new() + { + PivotNumber = "1", + }; ProgressTracker progressTracker = new(blockTree, stateDb, LimboLogs.Instance); SyncProgressResolver syncProgressResolver = new(blockTree, receiptStorage, stateDb, NullTrieNodeResolver.Instance, progressTracker, syncConfig, LimboLogs.Instance); - blockTree.BestSuggestedHeader.Returns((BlockHeader)null); + blockTree.BestSuggestedHeader.ReturnsNull(); Assert.That(syncProgressResolver.FindBestHeader(), Is.EqualTo(0)); } @@ -42,12 +45,14 @@ public void Best_block_is_0_when_no_block_was_suggested() IBlockTree blockTree = Substitute.For(); IReceiptStorage receiptStorage = Substitute.For(); IDb stateDb = new MemDb(); - SyncConfig syncConfig = new(); - syncConfig.PivotNumber = "1"; + SyncConfig syncConfig = new() + { + PivotNumber = "1", + }; ProgressTracker progressTracker = new(blockTree, stateDb, LimboLogs.Instance); SyncProgressResolver syncProgressResolver = new(blockTree, receiptStorage, stateDb, NullTrieNodeResolver.Instance, progressTracker, syncConfig, LimboLogs.Instance); - blockTree.BestSuggestedBody.Returns((Block)null); + blockTree.BestSuggestedBody.ReturnsNull(); Assert.That(syncProgressResolver.FindBestFullBlock(), Is.EqualTo(0)); } @@ -57,15 +62,17 @@ public void Best_state_is_head_when_there_are_no_suggested_blocks() IBlockTree blockTree = Substitute.For(); IReceiptStorage receiptStorage = Substitute.For(); IDb stateDb = new MemDb(); - SyncConfig syncConfig = new(); - syncConfig.PivotNumber = "1"; + SyncConfig syncConfig = new() + { + PivotNumber = "1", + }; ProgressTracker progressTracker = new(blockTree, stateDb, LimboLogs.Instance); SyncProgressResolver syncProgressResolver = new(blockTree, receiptStorage, stateDb, NullTrieNodeResolver.Instance, progressTracker, syncConfig, LimboLogs.Instance); - var head = Build.A.Block.WithHeader(Build.A.BlockHeader.WithNumber(5).WithStateRoot(TestItem.KeccakA).TestObject).TestObject; + Block head = Build.A.Block.WithHeader(Build.A.BlockHeader.WithNumber(5).WithStateRoot(TestItem.KeccakA).TestObject).TestObject; blockTree.Head.Returns(head); blockTree.BestSuggestedHeader.Returns(head.Header); - stateDb[head.StateRoot.Bytes] = new byte[] { 1 }; + stateDb[head.StateRoot!.Bytes] = new byte[] { 1 }; Assert.That(syncProgressResolver.FindBestFullState(), Is.EqualTo(head.Number)); } @@ -75,19 +82,21 @@ public void Best_state_is_suggested_if_there_is_suggested_block_with_state() IBlockTree blockTree = Substitute.For(); IReceiptStorage receiptStorage = Substitute.For(); IDb stateDb = new MemDb(); - SyncConfig syncConfig = new(); - syncConfig.PivotNumber = "1"; + SyncConfig syncConfig = new() + { + PivotNumber = "1", + }; ProgressTracker progressTracker = new(blockTree, stateDb, LimboLogs.Instance); SyncProgressResolver syncProgressResolver = new(blockTree, receiptStorage, stateDb, NullTrieNodeResolver.Instance, progressTracker, syncConfig, LimboLogs.Instance); - var head = Build.A.Block.WithHeader(Build.A.BlockHeader.WithNumber(5).WithStateRoot(TestItem.KeccakA).TestObject).TestObject; - var suggested = Build.A.BlockHeader.WithNumber(6).WithStateRoot(TestItem.KeccakB).TestObject; + Block head = Build.A.Block.WithHeader(Build.A.BlockHeader.WithNumber(5).WithStateRoot(TestItem.KeccakA).TestObject).TestObject; + BlockHeader suggested = Build.A.BlockHeader.WithNumber(6).WithStateRoot(TestItem.KeccakB).TestObject; blockTree.Head.Returns(head); blockTree.BestSuggestedHeader.Returns(suggested); blockTree.FindHeader(Arg.Any(), BlockTreeLookupOptions.TotalDifficultyNotNeeded).Returns(head.Header); - stateDb[head.StateRoot.Bytes] = new byte[] { 1 }; - stateDb[suggested.StateRoot.Bytes] = new byte[] { 1 }; + stateDb[head.StateRoot!.Bytes] = new byte[] { 1 }; + stateDb[suggested.StateRoot!.Bytes] = new byte[] { 1 }; Assert.That(syncProgressResolver.FindBestFullState(), Is.EqualTo(suggested.Number)); } @@ -97,18 +106,20 @@ public void Best_state_is_head_if_there_is_suggested_block_without_state() IBlockTree blockTree = Substitute.For(); IReceiptStorage receiptStorage = Substitute.For(); IDb stateDb = new MemDb(); - SyncConfig syncConfig = new(); - syncConfig.PivotNumber = "1"; + SyncConfig syncConfig = new() + { + PivotNumber = "1", + }; ProgressTracker progressTracker = new(blockTree, stateDb, LimboLogs.Instance); SyncProgressResolver syncProgressResolver = new(blockTree, receiptStorage, stateDb, NullTrieNodeResolver.Instance, progressTracker, syncConfig, LimboLogs.Instance); - var head = Build.A.Block.WithHeader(Build.A.BlockHeader.WithNumber(5).WithStateRoot(TestItem.KeccakA).TestObject).TestObject; - var suggested = Build.A.BlockHeader.WithNumber(6).WithStateRoot(TestItem.KeccakB).TestObject; + Block head = Build.A.Block.WithHeader(Build.A.BlockHeader.WithNumber(5).WithStateRoot(TestItem.KeccakA).TestObject).TestObject; + BlockHeader suggested = Build.A.BlockHeader.WithNumber(6).WithStateRoot(TestItem.KeccakB).TestObject; blockTree.Head.Returns(head); blockTree.BestSuggestedHeader.Returns(suggested); - blockTree.FindHeader(Arg.Any(), BlockTreeLookupOptions.TotalDifficultyNotNeeded).Returns(head?.Header); - stateDb[head.StateRoot.Bytes] = new byte[] { 1 }; - stateDb[suggested.StateRoot.Bytes] = null; + blockTree.FindHeader(Arg.Any(), BlockTreeLookupOptions.TotalDifficultyNotNeeded).Returns(head.Header); + stateDb[head.StateRoot!.Bytes] = new byte[] { 1 }; + stateDb[suggested.StateRoot!.Bytes] = null; Assert.That(syncProgressResolver.FindBestFullState(), Is.EqualTo(head.Number)); } @@ -118,9 +129,11 @@ public void Is_fast_block_finished_returns_true_when_no_fast_block_sync_is_used( IBlockTree blockTree = Substitute.For(); IReceiptStorage receiptStorage = Substitute.For(); IDb stateDb = new MemDb(); - SyncConfig syncConfig = new(); - syncConfig.FastBlocks = false; - syncConfig.PivotNumber = "1"; + SyncConfig syncConfig = new() + { + FastBlocks = false, + PivotNumber = "1", + }; ProgressTracker progressTracker = new(blockTree, stateDb, LimboLogs.Instance); SyncProgressResolver syncProgressResolver = new(blockTree, receiptStorage, stateDb, NullTrieNodeResolver.Instance, progressTracker, syncConfig, LimboLogs.Instance); @@ -135,12 +148,14 @@ public void Is_fast_block_headers_finished_returns_false_when_headers_not_downlo IBlockTree blockTree = Substitute.For(); IReceiptStorage receiptStorage = Substitute.For(); IDb stateDb = new MemDb(); - SyncConfig syncConfig = new(); - syncConfig.FastBlocks = true; - syncConfig.FastSync = true; - syncConfig.DownloadBodiesInFastSync = true; - syncConfig.DownloadReceiptsInFastSync = true; - syncConfig.PivotNumber = "1"; + SyncConfig syncConfig = new() + { + FastBlocks = true, + FastSync = true, + DownloadBodiesInFastSync = true, + DownloadReceiptsInFastSync = true, + PivotNumber = "1", + }; ProgressTracker progressTracker = new(blockTree, stateDb, LimboLogs.Instance); blockTree.LowestInsertedHeader.Returns(Build.A.BlockHeader.WithNumber(2).WithStateRoot(TestItem.KeccakA).TestObject); @@ -155,12 +170,14 @@ public void Is_fast_block_bodies_finished_returns_false_when_blocks_not_download IBlockTree blockTree = Substitute.For(); IReceiptStorage receiptStorage = Substitute.For(); IDb stateDb = new MemDb(); - SyncConfig syncConfig = new(); - syncConfig.FastBlocks = true; - syncConfig.FastSync = true; - syncConfig.DownloadBodiesInFastSync = true; - syncConfig.DownloadReceiptsInFastSync = true; - syncConfig.PivotNumber = "1"; + SyncConfig syncConfig = new() + { + FastBlocks = true, + FastSync = true, + DownloadBodiesInFastSync = true, + DownloadReceiptsInFastSync = true, + PivotNumber = "1", + }; ProgressTracker progressTracker = new(blockTree, stateDb, LimboLogs.Instance); blockTree.LowestInsertedHeader.Returns(Build.A.BlockHeader.WithNumber(1).WithStateRoot(TestItem.KeccakA).TestObject); @@ -176,12 +193,14 @@ public void Is_fast_block_receipts_finished_returns_false_when_receipts_not_down IBlockTree blockTree = Substitute.For(); IReceiptStorage receiptStorage = Substitute.For(); IDb stateDb = new MemDb(); - SyncConfig syncConfig = new(); - syncConfig.FastBlocks = true; - syncConfig.FastSync = true; - syncConfig.DownloadBodiesInFastSync = true; - syncConfig.DownloadReceiptsInFastSync = true; - syncConfig.PivotNumber = "1"; + SyncConfig syncConfig = new() + { + FastBlocks = true, + FastSync = true, + DownloadBodiesInFastSync = true, + DownloadReceiptsInFastSync = true, + PivotNumber = "1", + }; ProgressTracker progressTracker = new(blockTree, stateDb, LimboLogs.Instance); blockTree.LowestInsertedHeader.Returns(Build.A.BlockHeader.WithNumber(1).WithStateRoot(TestItem.KeccakA).TestObject); @@ -199,11 +218,13 @@ public void Is_fast_block_bodies_finished_returns_true_when_bodies_not_downloade IBlockTree blockTree = Substitute.For(); IReceiptStorage receiptStorage = Substitute.For(); IDb stateDb = new MemDb(); - SyncConfig syncConfig = new(); - syncConfig.FastBlocks = true; - syncConfig.DownloadBodiesInFastSync = false; - syncConfig.DownloadReceiptsInFastSync = true; - syncConfig.PivotNumber = "1"; + SyncConfig syncConfig = new() + { + FastBlocks = true, + DownloadBodiesInFastSync = false, + DownloadReceiptsInFastSync = true, + PivotNumber = "1", + }; ProgressTracker progressTracker = new(blockTree, stateDb, LimboLogs.Instance); blockTree.LowestInsertedHeader.Returns(Build.A.BlockHeader.WithNumber(1).WithStateRoot(TestItem.KeccakA).TestObject); @@ -220,11 +241,13 @@ public void Is_fast_block_receipts_finished_returns_true_when_receipts_not_downl IBlockTree blockTree = Substitute.For(); IReceiptStorage receiptStorage = Substitute.For(); IDb stateDb = new MemDb(); - SyncConfig syncConfig = new(); - syncConfig.FastBlocks = true; - syncConfig.DownloadBodiesInFastSync = true; - syncConfig.DownloadReceiptsInFastSync = false; - syncConfig.PivotNumber = "1"; + SyncConfig syncConfig = new() + { + FastBlocks = true, + DownloadBodiesInFastSync = true, + DownloadReceiptsInFastSync = false, + PivotNumber = "1", + }; ProgressTracker progressTracker = new(blockTree, stateDb, LimboLogs.Instance); blockTree.LowestInsertedHeader.Returns(Build.A.BlockHeader.WithNumber(1).WithStateRoot(TestItem.KeccakA).TestObject); diff --git a/src/Nethermind/Nethermind.Synchronization.Test/SyncReportTest.cs b/src/Nethermind/Nethermind.Synchronization.Test/SyncReportTest.cs index 41c211e0ccd..3c12bcd1ae9 100644 --- a/src/Nethermind/Nethermind.Synchronization.Test/SyncReportTest.cs +++ b/src/Nethermind/Nethermind.Synchronization.Test/SyncReportTest.cs @@ -23,7 +23,7 @@ public class SyncReportTest [TestCase(true, false)] [TestCase(true, true)] [TestCase(false, false)] - public async Task Smoke(bool fastSync, bool fastBlocks) + public void Smoke(bool fastSync, bool fastBlocks) { ISyncModeSelector selector = Substitute.For(); ISyncPeerPool pool = Substitute.For(); @@ -32,20 +32,22 @@ public async Task Smoke(bool fastSync, bool fastBlocks) ITimer timer = Substitute.For(); timerFactory.CreateTimer(Arg.Any()).Returns(timer); - Queue _syncModes = new(); - _syncModes.Enqueue(SyncMode.WaitingForBlock); - _syncModes.Enqueue(SyncMode.FastSync); - _syncModes.Enqueue(SyncMode.Full); - _syncModes.Enqueue(SyncMode.FastBlocks); - _syncModes.Enqueue(SyncMode.StateNodes); - _syncModes.Enqueue(SyncMode.Disconnected); + Queue syncModes = new(); + syncModes.Enqueue(SyncMode.WaitingForBlock); + syncModes.Enqueue(SyncMode.FastSync); + syncModes.Enqueue(SyncMode.Full); + syncModes.Enqueue(SyncMode.FastBlocks); + syncModes.Enqueue(SyncMode.StateNodes); + syncModes.Enqueue(SyncMode.Disconnected); - SyncConfig syncConfig = new(); - syncConfig.FastBlocks = fastBlocks; - syncConfig.FastSync = fastSync; + SyncConfig syncConfig = new() + { + FastBlocks = fastBlocks, + FastSync = fastSync, + }; SyncReport syncReport = new(pool, Substitute.For(), selector, syncConfig, Substitute.For(), LimboLogs.Instance, timerFactory); - selector.Current.Returns((ci) => _syncModes.Count > 0 ? _syncModes.Dequeue() : SyncMode.Full); + selector.Current.Returns(_ => syncModes.Count > 0 ? syncModes.Dequeue() : SyncMode.Full); timer.Elapsed += Raise.Event(); syncReport.FastBlocksHeaders.MarkEnd(); syncReport.FastBlocksBodies.MarkEnd(); @@ -69,22 +71,24 @@ public void Ancient_bodies_and_receipts_are_reported_correctly(bool setBarriers) logger.IsInfo.Returns(true); logManager.GetClassLogger().Returns(logger); - Queue _syncModes = new(); - _syncModes.Enqueue(SyncMode.FastHeaders); - _syncModes.Enqueue(SyncMode.FastBodies); - _syncModes.Enqueue(SyncMode.FastReceipts); + Queue syncModes = new(); + syncModes.Enqueue(SyncMode.FastHeaders); + syncModes.Enqueue(SyncMode.FastBodies); + syncModes.Enqueue(SyncMode.FastReceipts); - SyncConfig syncConfig = new(); - syncConfig.FastBlocks = true; - syncConfig.FastSync = true; - syncConfig.PivotNumber = "100"; + SyncConfig syncConfig = new() + { + FastBlocks = true, + FastSync = true, + PivotNumber = "100", + }; if (setBarriers) { syncConfig.AncientBodiesBarrier = 30; syncConfig.AncientReceiptsBarrier = 35; } - SyncReport syncReport = new(pool, Substitute.For(), selector, syncConfig, Substitute.For(), logManager, timerFactory); + SyncReport _ = new(pool, Substitute.For(), selector, syncConfig, Substitute.For(), logManager, timerFactory); selector.Current.Returns(_ => SyncMode.FastHeaders | SyncMode.FastBodies | SyncMode.FastReceipts); timer.Elapsed += Raise.Event(); diff --git a/src/Nethermind/Nethermind.Synchronization.Test/SyncServerTests.cs b/src/Nethermind/Nethermind.Synchronization.Test/SyncServerTests.cs index bfabaefef7f..ef2a31e200c 100644 --- a/src/Nethermind/Nethermind.Synchronization.Test/SyncServerTests.cs +++ b/src/Nethermind/Nethermind.Synchronization.Test/SyncServerTests.cs @@ -45,7 +45,7 @@ public void When_finding_hash_it_does_not_load_headers() { Context ctx = new(); ctx.BlockTree.FindHash(123).Returns(TestItem.KeccakA); - Keccak result = ctx.SyncServer.FindHash(123); + Keccak result = ctx.SyncServer.FindHash(123)!; ctx.BlockTree.DidNotReceive().FindHeader(Arg.Any(), Arg.Any()); ctx.BlockTree.DidNotReceive().FindHeader(Arg.Any(), Arg.Any()); @@ -105,7 +105,7 @@ public void Can_accept_new_valid_blocks(bool sealOk, bool validationOk, bool acc MainnetSpecProvider.Instance, LimboLogs.Instance); - Block block = remoteBlockTree.FindBlock(9, BlockTreeLookupOptions.None); + Block block = remoteBlockTree.FindBlock(9, BlockTreeLookupOptions.None)!; if (!accepted) { @@ -148,7 +148,7 @@ public void Can_accept_blocks_that_are_fine() MainnetSpecProvider.Instance, LimboLogs.Instance); - Block block = remoteBlockTree.FindBlock(9, BlockTreeLookupOptions.None); + Block block = remoteBlockTree.FindBlock(9, BlockTreeLookupOptions.None)!; ctx.SyncServer.AddNewBlock(block, ctx.NodeWhoSentTheBlock); @@ -161,20 +161,39 @@ public void Terminal_block_with_lower_td_should_not_change_best_suggested_but_sh Context ctx = new(); BlockTree remoteBlockTree = Build.A.BlockTree().OfChainLength(10).TestObject; BlockTree localBlockTree = Build.A.BlockTree().OfChainLength(9).TestObject; - TestSpecProvider testSpecProvider = new(London.Instance); - testSpecProvider.TerminalTotalDifficulty = 10_000_000; + TestSpecProvider testSpecProvider = new(London.Instance) + { + TerminalTotalDifficulty = 10_000_000, + }; - Block newBestLocalBlock = Build.A.Block.WithNumber(localBlockTree.Head!.Number + 1).WithParent(localBlockTree.Head!).WithDifficulty(10_000_002L).TestObject; + Block newBestLocalBlock = Build.A.Block + .WithNumber(localBlockTree.Head!.Number + 1) + .WithParent(localBlockTree.Head!).WithDifficulty(10_000_002L).TestObject; localBlockTree.SuggestBlock(newBestLocalBlock); - PoSSwitcher poSSwitcher = new(new MergeConfig() { TerminalTotalDifficulty = $"{testSpecProvider.TerminalTotalDifficulty}" }, new SyncConfig(), new MemDb(), localBlockTree, testSpecProvider, LimboLogs.Instance); + PoSSwitcher poSSwitcher = new( + new MergeConfig + { + TerminalTotalDifficulty = $"{testSpecProvider.TerminalTotalDifficulty}" + }, + new SyncConfig(), + new MemDb(), + localBlockTree, + testSpecProvider, + LimboLogs.Instance); HeaderValidator headerValidator = new( localBlockTree, Always.Valid, testSpecProvider, LimboLogs.Instance); - MergeHeaderValidator mergeHeaderValidator = new(poSSwitcher, headerValidator, localBlockTree, testSpecProvider, Always.Valid, LimboLogs.Instance); + MergeHeaderValidator mergeHeaderValidator = new( + poSSwitcher, + headerValidator, + localBlockTree, + testSpecProvider, + Always.Valid, + LimboLogs.Instance); BlockValidator blockValidator = new( Always.Valid, mergeHeaderValidator, @@ -211,13 +230,13 @@ public void Fake_total_difficulty_from_peer_does_not_trick_the_node(long ttd) BlockTree remoteBlockTree = Build.A.BlockTree().OfChainLength(10).TestObject; Context ctx = CreateMergeContext(9, (UInt256)ttd); - Block? block = remoteBlockTree.FindBlock(9, BlockTreeLookupOptions.None); - block!.Header.TotalDifficulty *= 2; + Block block = remoteBlockTree.FindBlock(9, BlockTreeLookupOptions.None)!; + block.Header.TotalDifficulty = block.Header.TotalDifficulty * 2; ctx.SyncServer.AddNewBlock(block, ctx.NodeWhoSentTheBlock); Assert.That(block.Header.Hash, Is.EqualTo(ctx.LocalBlockTree.BestSuggestedHeader!.Hash)); - Block? parentBlock = remoteBlockTree.FindBlock(8, BlockTreeLookupOptions.None); + Block parentBlock = remoteBlockTree.FindBlock(8, BlockTreeLookupOptions.None)!; Assert.That(ctx.LocalBlockTree.BestSuggestedHeader.TotalDifficulty, Is.EqualTo(parentBlock.TotalDifficulty + block.Difficulty)); } @@ -229,10 +248,10 @@ public void Can_reject_block_POW_block_after_TTD(long ttd, bool sendFakeTd) BlockTree remoteBlockTree = Build.A.BlockTree().OfChainLength(10).TestObject; Context ctx = CreateMergeContext(9, (UInt256)ttd); - Block block = remoteBlockTree.FindBlock(9, BlockTreeLookupOptions.None); + Block block = remoteBlockTree.FindBlock(9, BlockTreeLookupOptions.None)!; if (sendFakeTd) { - block.Header.TotalDifficulty *= 2; + block.Header.TotalDifficulty = block.Header.TotalDifficulty * 2; } Assert.Throws(() => ctx.SyncServer.AddNewBlock(block, ctx.NodeWhoSentTheBlock)); @@ -245,14 +264,19 @@ public void Can_reject_block_POW_block_after_TTD(long ttd, bool sendFakeTd) public void Post_merge_blocks_wont_be_accepted_by_gossip(long ttd, bool sendFakeTd) { BlockTree remoteBlockTree = Build.A.BlockTree().OfChainLength(9).TestObject; - Block postMergeBlock = Build.A.Block.WithDifficulty(0).WithParent(remoteBlockTree.Head).WithTotalDifficulty(remoteBlockTree.Head.TotalDifficulty).WithNonce(0u).TestObject; + Block postMergeBlock = Build.A.Block + .WithDifficulty(0) + .WithParent(remoteBlockTree.Head!) + .WithTotalDifficulty(remoteBlockTree.Head!.TotalDifficulty) + .WithNonce(0u) + .TestObject; remoteBlockTree.SuggestBlock(postMergeBlock); Context ctx = CreateMergeContext(9, (UInt256)ttd); - Block block = remoteBlockTree.FindBlock(9, BlockTreeLookupOptions.None); + Block block = remoteBlockTree.FindBlock(9, BlockTreeLookupOptions.None)!; if (sendFakeTd) { - block.Header.TotalDifficulty *= 2; + block.Header.TotalDifficulty = block.Header.TotalDifficulty * 2; } ctx.SyncServer.AddNewBlock(block, ctx.NodeWhoSentTheBlock); @@ -267,15 +291,20 @@ public void Post_merge_blocks_wont_be_accepted_by_gossip(long ttd, bool sendFake public void Can_inject_terminal_block_with_not_higher_td_than_head(long ttd, bool sendFakeTd, long difficulty) { BlockTree remoteBlockTree = Build.A.BlockTree().OfChainLength(9).TestObject; - Block terminalBlockWithLowerDifficulty = Build.A.Block.WithDifficulty((UInt256)difficulty).WithParent(remoteBlockTree.Head).WithGasLimit(remoteBlockTree.Head.GasLimit + 1).WithTotalDifficulty(remoteBlockTree.Head.TotalDifficulty + (UInt256)difficulty).TestObject; + Block terminalBlockWithLowerDifficulty = Build.A.Block + .WithDifficulty((UInt256)difficulty) + .WithParent(remoteBlockTree.Head!) + .WithGasLimit(remoteBlockTree.Head!.GasLimit + 1) + .WithTotalDifficulty(remoteBlockTree.Head.TotalDifficulty + (UInt256)difficulty) + .TestObject; remoteBlockTree.SuggestBlock(terminalBlockWithLowerDifficulty); Context ctx = CreateMergeContext(10, (UInt256)ttd); Assert.True(terminalBlockWithLowerDifficulty.IsTerminalBlock(ctx.SpecProvider)); - Block block = remoteBlockTree.FindBlock(9, BlockTreeLookupOptions.None); + Block block = remoteBlockTree.FindBlock(9, BlockTreeLookupOptions.None)!; if (sendFakeTd) { - block.Header.TotalDifficulty *= 2; + block.Header.TotalDifficulty = block.Header.TotalDifficulty * 2; } ctx.SyncServer.AddNewBlock(block, ctx.NodeWhoSentTheBlock); @@ -289,15 +318,19 @@ public void Can_inject_terminal_block_with_not_higher_td_than_head(long ttd, boo public void Can_inject_terminal_block_with_higher_td_than_head(long ttd, bool sendFakeTd) { BlockTree remoteBlockTree = Build.A.BlockTree().OfChainLength(9).TestObject; - Block terminalBlockWithHigherTotalDifficulty = Build.A.Block.WithDifficulty(1000010).WithParent(remoteBlockTree.Head).WithTotalDifficulty(remoteBlockTree.Head.TotalDifficulty + 1000010).TestObject; + Block terminalBlockWithHigherTotalDifficulty = Build.A.Block + .WithDifficulty(1000010) + .WithParent(remoteBlockTree.Head!) + .WithTotalDifficulty(remoteBlockTree.Head!.TotalDifficulty + 1000010) + .TestObject; remoteBlockTree.SuggestBlock(terminalBlockWithHigherTotalDifficulty); Context ctx = CreateMergeContext(10, (UInt256)ttd); Assert.True(terminalBlockWithHigherTotalDifficulty.IsTerminalBlock(ctx.SpecProvider)); - Block? block = remoteBlockTree.FindBlock(9, BlockTreeLookupOptions.None); + Block block = remoteBlockTree.FindBlock(9, BlockTreeLookupOptions.None)!; if (sendFakeTd) { - block.Header.TotalDifficulty *= 2; + block.Header.TotalDifficulty = block.Header.TotalDifficulty * 2; } ctx.SyncServer.AddNewBlock(block, ctx.NodeWhoSentTheBlock); @@ -311,40 +344,69 @@ public void Can_inject_terminal_block_with_higher_td_than_head(long ttd, bool se public void PostMerge_block_from_gossip_should_not_override_main_chain(long ttd) { BlockTree remoteBlockTree = Build.A.BlockTree().OfChainLength(9).TestObject; - Block poWBlockPostMerge = Build.A.Block.WithDifficulty(1000010).WithParent(remoteBlockTree.Head).WithTotalDifficulty(remoteBlockTree.Head.TotalDifficulty + 1000010).TestObject; + Block poWBlockPostMerge = Build.A.Block + .WithDifficulty(1000010) + .WithParent(remoteBlockTree.Head!) + .WithTotalDifficulty(remoteBlockTree.Head!.TotalDifficulty + 1000010) + .TestObject; remoteBlockTree.SuggestBlock(poWBlockPostMerge); Context ctx = CreateMergeContext(10, (UInt256)ttd); - Block newPostMergeBlock = Build.A.Block.WithDifficulty(0).WithParent(ctx.LocalBlockTree.Head).WithTotalDifficulty(ctx.LocalBlockTree.Head.TotalDifficulty).TestObject; + Block newPostMergeBlock = Build.A.Block + .WithDifficulty(0) + .WithParent(ctx.LocalBlockTree.Head!) + .WithTotalDifficulty(ctx.LocalBlockTree.Head!.TotalDifficulty) + .TestObject; ctx.LocalBlockTree.SuggestBlock(newPostMergeBlock); ctx.LocalBlockTree.UpdateMainChain(new[] { newPostMergeBlock }, true, true); - Block block = remoteBlockTree.FindBlock(9, BlockTreeLookupOptions.None); + Block block = remoteBlockTree.FindBlock(9, BlockTreeLookupOptions.None)!; ctx.SyncServer.AddNewBlock(block, ctx.NodeWhoSentTheBlock); Assert.That(ctx.LocalBlockTree.BestSuggestedHeader!.Number, Is.EqualTo(10)); ctx.LocalBlockTree.FindBlock(poWBlockPostMerge.Hash!, BlockTreeLookupOptions.None).Should().NotBeNull(); ctx.LocalBlockTree.BestSuggestedHeader!.Hash.Should().Be(newPostMergeBlock.Hash!); - ctx.LocalBlockTree.FindCanonicalBlockInfo(poWBlockPostMerge.Number).BlockHash.Should().NotBe(poWBlockPostMerge.Hash); + ctx.LocalBlockTree.FindCanonicalBlockInfo(poWBlockPostMerge.Number).BlockHash.Should().NotBe(poWBlockPostMerge.Hash!); } private Context CreateMergeContext(int blockTreeChainLength, UInt256 ttd) { Context ctx = new(); - TestSpecProvider testSpecProvider = new(London.Instance); - testSpecProvider.TerminalTotalDifficulty = ttd; + TestSpecProvider testSpecProvider = new(London.Instance) + { + TerminalTotalDifficulty = ttd, + }; Block genesis = Build.A.Block.Genesis.TestObject; BlockTree localBlockTree = Build.A.BlockTree(genesis, testSpecProvider).OfChainLength(blockTreeChainLength).TestObject; - PoSSwitcher poSSwitcher = new(new MergeConfig() { TerminalTotalDifficulty = $"{ttd}" }, new SyncConfig(), new MemDb(), localBlockTree, testSpecProvider, LimboLogs.Instance); - MergeSealEngine sealEngine = new(new SealEngine(new NethDevSealEngine(), Always.Valid), poSSwitcher, new MergeSealValidator(poSSwitcher, Always.Valid), LimboLogs.Instance); + PoSSwitcher poSSwitcher = new( + new MergeConfig + { + TerminalTotalDifficulty = $"{ttd}" + }, + new SyncConfig(), + new MemDb(), + localBlockTree, + testSpecProvider, + LimboLogs.Instance); + MergeSealEngine sealEngine = new( + new SealEngine(new NethDevSealEngine(), Always.Valid), + poSSwitcher, + new MergeSealValidator(poSSwitcher, Always.Valid), + LimboLogs.Instance); HeaderValidator headerValidator = new( localBlockTree, sealEngine, testSpecProvider, LimboLogs.Instance); - MergeHeaderValidator mergeHeaderValidator = new(poSSwitcher, headerValidator, localBlockTree, testSpecProvider, Always.Valid, LimboLogs.Instance); + MergeHeaderValidator mergeHeaderValidator = new( + poSSwitcher, + headerValidator, + localBlockTree, + testSpecProvider, + Always.Valid, + LimboLogs.Instance); InvalidChainTracker invalidChainTracker = new( poSSwitcher, @@ -418,14 +480,14 @@ public void Will_not_reject_block_with_bad_total_diff_but_will_reset_diff_to_nul MainnetSpecProvider.Instance, LimboLogs.Instance); - Block? block = remoteBlockTree.FindBlock(9, BlockTreeLookupOptions.None); - block!.Header!.TotalDifficulty *= 2; + Block block = remoteBlockTree.FindBlock(9, BlockTreeLookupOptions.None)!; + block.Header.TotalDifficulty = block.Header.TotalDifficulty * 2; ctx.SyncServer.AddNewBlock(block, ctx.NodeWhoSentTheBlock); Assert.That(block.Header.Hash, Is.EqualTo(localBlockTree.BestSuggestedHeader!.Hash)); Block? parentBlock = remoteBlockTree.FindBlock(8, BlockTreeLookupOptions.None); - Assert.That(localBlockTree.BestSuggestedHeader.TotalDifficulty, Is.EqualTo(parentBlock.TotalDifficulty + block.Difficulty)); + Assert.That(localBlockTree.BestSuggestedHeader.TotalDifficulty, Is.EqualTo(parentBlock!.TotalDifficulty + block.Difficulty)); } [Test] @@ -451,7 +513,7 @@ public void Rejects_new_old_blocks() MainnetSpecProvider.Instance, LimboLogs.Instance); - Block block = remoteBlockTree.FindBlock(9, BlockTreeLookupOptions.None); + Block block = remoteBlockTree.FindBlock(9, BlockTreeLookupOptions.None)!; ctx.SyncServer.AddNewBlock(block, ctx.NodeWhoSentTheBlock); @@ -564,7 +626,7 @@ public async Task Broadcast_NewBlock_on_arrival_to_sqrt_of_peers([Values(1, 2, 3 .When(r => r.AddNewBlock(Arg.Is(b => b.Hash == remoteBlockTree.Head!.Hash), Arg.Any())) .Do(_ => count++); PeerInfo[] peers = Enumerable.Range(0, peerCount).Take(peerCount) - .Select(k => new PeerInfo(new SyncPeerMock(remoteBlockTree, remoteSyncServer: remoteServer))) + .Select(_ => new PeerInfo(new SyncPeerMock(remoteBlockTree, remoteSyncServer: remoteServer))) .ToArray(); ctx.PeerPool.AllPeers.Returns(peers); ctx.PeerPool.PeerCount.Returns(peers.Length); @@ -635,9 +697,9 @@ public Context() public IBlockTree BlockTree { get; } public ISyncPeerPool PeerPool { get; } public SyncServer SyncServer { get; set; } - public ISpecProvider SpecProvider { get; set; } + public ISpecProvider SpecProvider { get; set; } = null!; - public IBlockTree LocalBlockTree { get; set; } + public IBlockTree LocalBlockTree { get; set; } = null!; public ISyncPeer NodeWhoSentTheBlock { get; } } } diff --git a/src/Nethermind/Nethermind.Synchronization.Test/SynchronizerTests.cs b/src/Nethermind/Nethermind.Synchronization.Test/SynchronizerTests.cs index 4a266f8af2b..86fff95793a 100644 --- a/src/Nethermind/Nethermind.Synchronization.Test/SynchronizerTests.cs +++ b/src/Nethermind/Nethermind.Synchronization.Test/SynchronizerTests.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Concurrent; using System.Collections.Generic; +using System.Globalization; using System.Linq; using System.Threading; using System.Threading.Tasks; @@ -27,7 +28,6 @@ using Nethermind.Stats.Model; using Nethermind.Db.Blooms; using Nethermind.Merge.Plugin; -using Nethermind.Merge.Plugin.Handlers; using Nethermind.Merge.Plugin.InvalidChainTracker; using Nethermind.Merge.Plugin.Synchronization; using Nethermind.Merge.Plugin.Test; @@ -59,7 +59,9 @@ public SynchronizerTests(SynchronizerType synchronizerType) _synchronizerType = synchronizerType; } - private static Block _genesisBlock = Build.A.Block.Genesis.WithDifficulty(100000) + private static readonly Block _genesisBlock = Build.A.Block + .Genesis + .WithDifficulty(100000) .WithTotalDifficulty((UInt256)100000).TestObject; private class SyncPeerMock : ISyncPeer @@ -75,7 +77,10 @@ private class SyncPeerMock : ISyncPeer public BlockHeader HeadHeader => HeadBlock.Header; - public SyncPeerMock(string peerName, bool causeTimeoutOnInit = false, bool causeTimeoutOnBlocks = false, + public SyncPeerMock( + string peerName, + bool causeTimeoutOnInit = false, + bool causeTimeoutOnBlocks = false, bool causeTimeoutOnHeaders = false) { _causeTimeoutOnInit = causeTimeoutOnInit; @@ -88,7 +93,7 @@ public SyncPeerMock(string peerName, bool causeTimeoutOnInit = false, bool cause private void UpdateHead() { - HeadHash = HeadBlock.Hash; + HeadHash = HeadBlock.Hash!; HeadNumber = HeadBlock.Number; TotalDifficulty = HeadBlock.TotalDifficulty ?? 0; } @@ -96,14 +101,14 @@ private void UpdateHead() public Node Node { get; } = new Node(Build.A.PrivateKey.TestObject.PublicKey, "127.0.0.1", 1234); public string ClientId { get; } - public Keccak HeadHash { get; set; } + public Keccak HeadHash { get; set; } = null!; + public byte ProtocolVersion { get; } = default; + public string ProtocolCode { get; } = null!; public long HeadNumber { get; set; } public UInt256 TotalDifficulty { get; set; } public bool IsInitialized { get; set; } public bool IsPriority { get; set; } - public byte ProtocolVersion { get; } - public string ProtocolCode { get; } public void Disconnect(DisconnectReason reason, string details) { @@ -199,7 +204,7 @@ public void NotifyOfNewBlock(Block block, SendBlockMode mode) public ConcurrentStack ReceivedBlocks { get; } = new(); - public event EventHandler Disconnected; + public event EventHandler? Disconnected; public PublicKey Id => Node.Id; @@ -270,9 +275,9 @@ public WhenImplementation(SynchronizerType synchronizerType) public class SyncingContext { - public static ConcurrentQueue AllInstances = new(); + public static ConcurrentQueue AllInstances { get; } = new(); - private Dictionary _peers = new(); + private readonly Dictionary _peers = new(); private BlockTree BlockTree { get; } private ISyncServer SyncServer { get; } @@ -281,10 +286,9 @@ public class SyncingContext private ISyncPeerPool SyncPeerPool { get; } - // ILogManager _logManager = LimboLogs.Instance; - ILogManager _logManager = LimboLogs.Instance; + readonly ILogManager _logManager = LimboLogs.Instance; - private ILogger _logger; + private readonly ILogger _logger; public SyncingContext(SynchronizerType synchronizerType) { @@ -312,12 +316,11 @@ ISyncConfig GetSyncConfig() => ITimerFactory timerFactory = Substitute.For(); NodeStatsManager stats = new(timerFactory, _logManager); - MergeConfig? mergeConfig = new() { }; + MergeConfig mergeConfig = new(); if (WithTTD(synchronizerType)) { - mergeConfig.TerminalTotalDifficulty = UInt256.MaxValue.ToString(); + mergeConfig.TerminalTotalDifficulty = UInt256.MaxValue.ToString(CultureInfo.InvariantCulture); } - IBlockCacheService blockCacheService = new BlockCacheService(); PoSSwitcher poSSwitcher = new(mergeConfig, syncConfig, dbProvider.MetadataDb, BlockTree, new TestSingleReleaseSpecProvider(Constantinople.Instance), _logManager); IBeaconPivot beaconPivot = new BeaconPivot(syncConfig, dbProvider.MetadataDb, BlockTree, _logManager); @@ -443,22 +446,22 @@ public SyncingContext BestKnownNumberIs(long number) public SyncingContext BlockIsKnown() { - Assert.True(BlockTree.IsKnownBlock(_blockHeader.Number, _blockHeader.Hash), "block is known"); + Assert.True(BlockTree.IsKnownBlock(_blockHeader.Number, _blockHeader.Hash!), "block is known"); return this; } - private const int dynamicTimeout = 5000; + private const int DynamicTimeout = 5000; public SyncingContext BestSuggestedHeaderIs(BlockHeader header) { int waitTimeSoFar = 0; - _blockHeader = BlockTree.BestSuggestedHeader; - while (header != _blockHeader && waitTimeSoFar <= dynamicTimeout) + _blockHeader = BlockTree.BestSuggestedHeader!; + while (header != _blockHeader && waitTimeSoFar <= DynamicTimeout) { - _logger.Info($"ASSERTING THAT HEADER IS {header.Number} (WHEN ACTUALLY IS {_blockHeader?.Number})"); + _logger.Info($"ASSERTING THAT HEADER IS {header.Number} (WHEN ACTUALLY IS {_blockHeader.Number})"); Thread.Sleep(100); waitTimeSoFar += 100; - _blockHeader = BlockTree.BestSuggestedHeader; + _blockHeader = BlockTree.BestSuggestedHeader!; } Assert.That(_blockHeader, Is.SameAs(header), "header"); @@ -470,15 +473,15 @@ public SyncingContext BestSuggestedBlockHasNumber(long number) _logger.Info($"ASSERTING THAT NUMBER IS {number}"); int waitTimeSoFar = 0; - _blockHeader = BlockTree.BestSuggestedHeader; - while (number != _blockHeader?.Number && waitTimeSoFar <= dynamicTimeout) + _blockHeader = BlockTree.BestSuggestedHeader!; + while (number != _blockHeader.Number && waitTimeSoFar <= DynamicTimeout) { Thread.Sleep(10); waitTimeSoFar += 10; - _blockHeader = BlockTree.BestSuggestedHeader; + _blockHeader = BlockTree.BestSuggestedHeader!; } - Assert.That(_blockHeader?.Number, Is.EqualTo(number), "block number"); + Assert.That(_blockHeader.Number, Is.EqualTo(number), "block number"); return this; } @@ -488,18 +491,18 @@ public SyncingContext BlockIsSameAsGenesis() return this; } - private BlockHeader _blockHeader; + private BlockHeader _blockHeader = null!; public SyncingContext Genesis { get { - _blockHeader = BlockTree.Genesis; + _blockHeader = BlockTree.Genesis!; return this; } } - public SyncingContext Wait(int milliseconds) + private SyncingContext Wait(int milliseconds) { if (_logger.IsInfo) _logger.Info($"WAIT {milliseconds}"); Thread.Sleep(milliseconds); @@ -513,7 +516,7 @@ public SyncingContext Wait() public SyncingContext WaitUntilInitialized() { - SpinWait.SpinUntil(() => SyncPeerPool.AllPeers.All(p => p.IsInitialized), dynamicTimeout); + SpinWait.SpinUntil(() => SyncPeerPool.AllPeers.All(p => p.IsInitialized), DynamicTimeout); return this; } @@ -527,7 +530,7 @@ public SyncingContext BestSuggested { get { - _blockHeader = BlockTree.BestSuggestedHeader; + _blockHeader = BlockTree.BestSuggestedHeader!; return this; } } @@ -542,7 +545,7 @@ public SyncingContext AfterProcessingGenesis() public SyncingContext AfterPeerIsAdded(ISyncPeer syncPeer) { - ((SyncPeerMock)syncPeer).Disconnected += (s, e) => SyncPeerPool.RemovePeer(syncPeer); + ((SyncPeerMock)syncPeer).Disconnected += (_, _) => SyncPeerPool.RemovePeer(syncPeer); _logger.Info($"PEER ADDED {syncPeer.ClientId}"); _peers.TryAdd(syncPeer.ClientId, syncPeer); @@ -568,7 +571,7 @@ public SyncingContext AfterNewBlockMessage(Block block, ISyncPeer peer) public SyncingContext AfterHintBlockMessage(Block block, ISyncPeer peer) { _logger.Info($"HINT BLOCK MESSAGE {block.Number}"); - SyncServer.HintBlock(block.Hash, block.Number, peer); + SyncServer.HintBlock(block.Hash!, block.Number, peer); return this; } @@ -591,13 +594,13 @@ public SyncingContext WaitAMoment() public void Stop() { - Task task = new(async () => + Task task = Task.Run(async () => { await Synchronizer.StopAsync(); await SyncPeerPool.StopAsync(); }); - task.RunSynchronously(); + task.GetAwaiter().GetResult(); } } @@ -795,11 +798,11 @@ public void Will_inform_connecting_peer_about_the_alternative_branch_with_same_d Assert.That(peerA.HeadBlock.Hash, Is.Not.EqualTo(peerB.HeadBlock.Hash)); - Block peerBNewBlock = null; + Block? peerBNewBlock = null; SpinWait.SpinUntil(() => { bool receivedBlock = peerB.ReceivedBlocks.TryPeek(out peerBNewBlock); - return receivedBlock && peerBNewBlock.Hash == peerA.HeadBlock.Hash; + return receivedBlock && peerBNewBlock!.Hash == peerA.HeadBlock.Hash; }, WaitTime); Assert.That(peerA.HeadBlock.Hash, Is.EqualTo(peerBNewBlock?.Header.Hash!)); diff --git a/src/Nethermind/Nethermind.Synchronization.Test/TrieScenarios.cs b/src/Nethermind/Nethermind.Synchronization.Test/TrieScenarios.cs index 7926d841f06..a826be25ee2 100644 --- a/src/Nethermind/Nethermind.Synchronization.Test/TrieScenarios.cs +++ b/src/Nethermind/Nethermind.Synchronization.Test/TrieScenarios.cs @@ -18,14 +18,16 @@ namespace Nethermind.Synchronization.Test { public static class TrieScenarios { - public static Account Empty; - public static Account AccountJustState0; - public static Account AccountJustState1; - public static Account AccountJustState2; - public static Account Account0; - public static Account Account1; - public static Account Account2; - public static Account Account3; + private static bool Inited; + + public static Account Empty = null!; + public static Account AccountJustState0 = null!; + public static Account AccountJustState1 = null!; + public static Account AccountJustState2 = null!; + public static Account Account0 = null!; + public static Account Account1 = null!; + public static Account Account2 = null!; + public static Account Account3 = null!; public static readonly byte[] Code0 = { 0, 0 }; public static readonly byte[] Code1 = { 0, 1 }; @@ -35,11 +37,8 @@ public static class TrieScenarios [MethodImpl(MethodImplOptions.Synchronized)] public static void InitOnce() { - if (Empty is null) + if (!Inited) { - // _logger = new ConsoleAsyncLogger(LogLevel.Debug); - // _logManager = new OneLoggerLogManager(_logger); - // this setup is just for finding the storage root StorageTree remoteStorageTree = SetStorage(new TrieStore(new MemDb(), LimboLogs.Instance)); Keccak storageRoot = remoteStorageTree.RootHash; @@ -53,10 +52,12 @@ public static void InitOnce() AccountJustState0 = Build.An.Account.WithBalance(1).TestObject; AccountJustState1 = Build.An.Account.WithBalance(2).TestObject; AccountJustState2 = Build.An.Account.WithBalance(3).TestObject; + + Inited = true; } } - private static (string Name, Action Action)[] _scenarios; + private static (string Name, Action Action)[]? _scenarios; public static (string Name, Action Action)[] Scenarios => LazyInitializer.EnsureInitialized(ref _scenarios, InitScenarios); @@ -65,7 +66,7 @@ private static (string Name, Action Action)[] InitSc { return new (string, Action)[] { - ("empty", (tree, stateDb, codeDb) => + ("empty", (tree, _, codeDb) => { codeDb[Keccak.Compute(Code0).Bytes] = Code0; tree.Commit(0); @@ -81,7 +82,7 @@ private static (string Name, Action Action)[] InitSc }), ("storage_hash_and_code_hash_same", (tree, stateDb, codeDb) => { - var code = Bytes.FromHexString("e3a120b10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf601"); + byte[] code = Bytes.FromHexString("e3a120b10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf601"); Keccak codeHash = Keccak.Compute(code); StorageTree remoteStorageTree = new(stateDb, Keccak.EmptyTreeHash, LimboLogs.Instance); remoteStorageTree.Set((UInt256) 1, new byte[] {1}); @@ -93,7 +94,7 @@ private static (string Name, Action Action)[] InitSc }), ("storage_hash_and_code_hash_same_with_additional_account_of_same_storage_root", (tree, stateDb, codeDb) => { - var code = Bytes.FromHexString("e3a120b10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf601"); + byte[] code = Bytes.FromHexString("e3a120b10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf601"); Keccak codeHash = Keccak.Compute(code); StorageTree remoteStorageTree = new(stateDb, Keccak.EmptyTreeHash, LimboLogs.Instance); remoteStorageTree.Set((UInt256) 1, new byte[] {1}); @@ -106,7 +107,7 @@ private static (string Name, Action Action)[] InitSc }), ("storage_hash_and_code_hash_same_with_additional_account_of_same_code", (tree, stateDb, codeDb) => { - var code = Bytes.FromHexString("e3a120b10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf601"); + byte[] code = Bytes.FromHexString("e3a120b10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf601"); Keccak codeHash = Keccak.Compute(code); StorageTree remoteStorageTree = new(stateDb, Keccak.EmptyTreeHash, LimboLogs.Instance); remoteStorageTree.Set((UInt256) 1, new byte[] {1}); @@ -117,7 +118,7 @@ private static (string Name, Action Action)[] InitSc tree.Set(new Keccak("bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"), AccountJustState0.WithChangedStorageRoot(remoteStorageTree.RootHash).WithChangedCodeHash(codeHash)); tree.Commit(0); }), - ("branch_with_same_accounts_at_different_addresses", (tree, stateDb, codeDb) => + ("branch_with_same_accounts_at_different_addresses", (tree, _, codeDb) => { codeDb[Keccak.Compute(Code0).Bytes] = Code0; tree.Set(new Keccak("1baaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"), AccountJustState0); @@ -145,7 +146,7 @@ private static (string Name, Action Action)[] InitSc tree.Set(new Keccak("eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeb1eeeeeb1"), null); tree.Commit(0); }), - ("set_3_delete_all", (tree, stateDb, codeDb) => + ("set_3_delete_all", (tree, _, _) => { // SetStorage(stateDb); tree.Set(new Keccak("eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeb00000000"), Account0); @@ -163,9 +164,9 @@ private static (string Name, Action Action)[] InitSc codeDb[Keccak.Compute(Code1).Bytes] = Code1; tree.Set(new Keccak("eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeb00000000"), Account0); tree.Set(new Keccak("eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeb11111111"), Account1); - Account account = tree.Get(new Keccak("eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeb11111111")); + Account _ = tree.Get(new Keccak("eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeb11111111"))!; tree.UpdateRootHash(); - Keccak rootHash = tree.RootHash; + Keccak __ = tree.RootHash; tree.Commit(0); }), ("extension_read_missing", (tree, stateDb, codeDb) => @@ -175,9 +176,9 @@ private static (string Name, Action Action)[] InitSc codeDb[Keccak.Compute(Code1).Bytes] = Code1; tree.Set(new Keccak("eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeb00000000"), Account0); tree.Set(new Keccak("eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeb11111111"), Account1); - Account account = tree.Get(new Keccak("eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeedddddddddddddddddddddddd")); + Account _ = tree.Get(new Keccak("eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeedddddddddddddddddddddddd"))!; tree.UpdateRootHash(); - Keccak rootHash = tree.RootHash; + Keccak __ = tree.RootHash; tree.Commit(0); }), ("extension_new_branch", (tree, stateDb, codeDb) => @@ -190,16 +191,16 @@ private static (string Name, Action Action)[] InitSc tree.Set(new Keccak("eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeb11111111"), Account1); tree.Set(new Keccak("eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeedddddddddddddddddddddddd"), Account2); tree.UpdateRootHash(); - Keccak rootHash = tree.RootHash; + Keccak _ = tree.RootHash; tree.Commit(0); }), - ("just_state", (tree, stateDb, codeDb) => + ("just_state", (tree, _, _) => { tree.Set(new Keccak("eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeb00000000"), AccountJustState0); tree.Set(new Keccak("eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeb11111111"), AccountJustState1); tree.Set(new Keccak("eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeedddddddddddddddddddddddd"), AccountJustState2); tree.UpdateRootHash(); - Keccak rootHash = tree.RootHash; + Keccak _ = tree.RootHash; tree.Commit(0); }), ("extension_delete_missing", (tree, stateDb, codeDb) => @@ -211,10 +212,10 @@ private static (string Name, Action Action)[] InitSc tree.Set(new Keccak("eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeb11111111"), Account1); tree.Set(new Keccak("eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeddddddddddddddddddddddddd"), null); tree.UpdateRootHash(); - Keccak rootHash = tree.RootHash; + Keccak _ = tree.RootHash; tree.Commit(0); }), - ("extenson_create_new_extension", (tree, stateDb, codeDb) => + ("extension_create_new_extension", (tree, stateDb, codeDb) => { SetStorage(stateDb); codeDb[Keccak.Compute(Code0).Bytes] = Code0; @@ -226,7 +227,7 @@ private static (string Name, Action Action)[] InitSc tree.Set(new Keccak("eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeaaaaaaaaaaaaaaaab00000000"), Account2); tree.Set(new Keccak("eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeaaaaaaaaaaaaaaaab11111111"), Account3); tree.UpdateRootHash(); - Keccak rootHash = tree.RootHash; + Keccak _ = tree.RootHash; tree.Commit(0); }), ("leaf_new_value", (tree, stateDb, codeDb) => @@ -236,7 +237,7 @@ private static (string Name, Action Action)[] InitSc tree.Set(new Keccak("1111111111111111111111111111111111111111111111111111111111111111"), Account0); tree.Set(new Keccak("1111111111111111111111111111111111111111111111111111111111111111"), Account1); tree.UpdateRootHash(); - Keccak rootHash = tree.RootHash; + Keccak _ = tree.RootHash; tree.Commit(0); }), ("leaf_no_change", (tree, stateDb, codeDb) => @@ -246,16 +247,15 @@ private static (string Name, Action Action)[] InitSc tree.Set(new Keccak("1111111111111111111111111111111111111111111111111111111111111111"), Account0); tree.Set(new Keccak("1111111111111111111111111111111111111111111111111111111111111111"), Account0); tree.UpdateRootHash(); - Keccak rootHash = tree.RootHash; + Keccak _ = tree.RootHash; tree.Commit(0); }), - ("leaf_delete", (tree, stateDb, codeDb) => + ("leaf_delete", (tree, _, _) => { -// SetStorage(stateDb); tree.Set(new Keccak("1111111111111111111111111111111111111111111111111111111111111111"), Account0); tree.Set(new Keccak("1111111111111111111111111111111111111111111111111111111111111111"), null); tree.UpdateRootHash(); - Keccak rootHash = tree.RootHash; + Keccak _ = tree.RootHash; tree.Commit(0); }), ("leaf_delete_missing", (tree, stateDb, codeDb) => @@ -265,7 +265,7 @@ private static (string Name, Action Action)[] InitSc tree.Set(new Keccak("1111111111111111111111111111111111111111111111111111111111111111"), Account0); tree.Set(new Keccak("1111111111111111111111111111111ddddddddddddddddddddddddddddddddd"), null); tree.UpdateRootHash(); - Keccak rootHash = tree.RootHash; + Keccak _ = tree.RootHash; tree.Commit(0); }), ("leaf_update_extension", (tree, stateDb, codeDb) => @@ -276,7 +276,7 @@ private static (string Name, Action Action)[] InitSc tree.Set(new Keccak("eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeb11111111111111111111111111111111"), Account0); tree.Set(new Keccak("eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeb00000000000000000000000000000000"), Account1); tree.UpdateRootHash(); - Keccak rootHash = tree.RootHash; + Keccak _ = tree.RootHash; tree.Commit(0); }), ("leaf_read", (tree, stateDb, codeDb) => @@ -284,9 +284,9 @@ private static (string Name, Action Action)[] InitSc SetStorage(stateDb); codeDb[Keccak.Compute(Code0).Bytes] = Code0; tree.Set(new Keccak("1111111111111111111111111111111111111111111111111111111111111111"), Account0); - Account account = tree.Get(new Keccak("1111111111111111111111111111111111111111111111111111111111111111")); + Account _ = tree.Get(new Keccak("1111111111111111111111111111111111111111111111111111111111111111"))!; tree.UpdateRootHash(); - Keccak rootHash = tree.RootHash; + Keccak __ = tree.RootHash; tree.Commit(0); }), ("leaf_update_missing", (tree, stateDb, codeDb) => @@ -294,9 +294,9 @@ private static (string Name, Action Action)[] InitSc SetStorage(stateDb); codeDb[Keccak.Compute(Code0).Bytes] = Code0; tree.Set(new Keccak("1111111111111111111111111111111111111111111111111111111111111111"), Account0); - Account account = tree.Get(new Keccak("111111111111111111111111111111111111111111111111111111111ddddddd")); + Account _ = tree.Get(new Keccak("111111111111111111111111111111111111111111111111111111111ddddddd"))!; tree.UpdateRootHash(); - Keccak rootHash = tree.RootHash; + Keccak __ = tree.RootHash; tree.Commit(0); }), ("branch_update_missing", (tree, stateDb, codeDb) => @@ -309,7 +309,7 @@ private static (string Name, Action Action)[] InitSc tree.Set(new Keccak("eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeb11111"), Account1); tree.Set(new Keccak("eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeb22222"), Account2); tree.UpdateRootHash(); - Keccak rootHash = tree.RootHash; + Keccak _ = tree.RootHash; tree.Commit(0); }), ("branch_read_missing", (tree, stateDb, codeDb) => @@ -319,9 +319,9 @@ private static (string Name, Action Action)[] InitSc codeDb[Keccak.Compute(Code1).Bytes] = Code1; tree.Set(new Keccak("eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeb00000"), Account0); tree.Set(new Keccak("eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeb11111"), Account1); - Account account = tree.Get(new Keccak("eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeb22222")); + Account _ = tree.Get(new Keccak("eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeb22222"))!; tree.UpdateRootHash(); - Keccak rootHash = tree.RootHash; + Keccak __ = tree.RootHash; tree.Commit(0); }), ("branch_delete_missing", (tree, stateDb, codeDb) => @@ -333,7 +333,7 @@ private static (string Name, Action Action)[] InitSc tree.Set(new Keccak("eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeb11111"), Account1); tree.Set(new Keccak("eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeb22222"), null); tree.UpdateRootHash(); - Keccak rootHash = tree.RootHash; + Keccak _ = tree.RootHash; tree.Commit(0); }) }; diff --git a/src/Nethermind/Nethermind.Synchronization/Blocks/BlockDownloader.cs b/src/Nethermind/Nethermind.Synchronization/Blocks/BlockDownloader.cs index c88b9be35e0..d48dd4ff6ec 100644 --- a/src/Nethermind/Nethermind.Synchronization/Blocks/BlockDownloader.cs +++ b/src/Nethermind/Nethermind.Synchronization/Blocks/BlockDownloader.cs @@ -137,7 +137,7 @@ await DownloadHeaders(bestPeer, blocksRequest, cancellation) } } - public async Task DownloadHeaders(PeerInfo bestPeer, BlocksRequest blocksRequest, CancellationToken cancellation) + public async Task DownloadHeaders(PeerInfo? bestPeer, BlocksRequest blocksRequest, CancellationToken cancellation) { if (bestPeer is null) { @@ -240,8 +240,7 @@ bool HasMoreToSync() return headersSynced; } - public virtual async Task DownloadBlocks(PeerInfo? bestPeer, BlocksRequest blocksRequest, - CancellationToken cancellation) + public virtual async Task DownloadBlocks(PeerInfo? bestPeer, BlocksRequest blocksRequest, CancellationToken cancellation) { if (bestPeer is null) { diff --git a/src/Nethermind/Nethermind.Synchronization/FastSync/DetailedProgress.cs b/src/Nethermind/Nethermind.Synchronization/FastSync/DetailedProgress.cs index d0ca7497b90..febb468f2ad 100644 --- a/src/Nethermind/Nethermind.Synchronization/FastSync/DetailedProgress.cs +++ b/src/Nethermind/Nethermind.Synchronization/FastSync/DetailedProgress.cs @@ -46,7 +46,7 @@ public class DetailedProgress private readonly IChainEstimations _chainEstimations; - public DetailedProgress(ulong chainId, byte[] serializedInitialState) + public DetailedProgress(ulong chainId, byte[]? serializedInitialState) { _chainEstimations = ChainSizes.CreateChainSizeInfo(chainId); @@ -100,28 +100,30 @@ internal void DisplayProgressReport(int pendingRequestsCount, BranchProgress bra } } - private void LoadFromSerialized(byte[] serializedData) + private void LoadFromSerialized(byte[]? serializedData) { - if (serializedData != null) + if (serializedData == null) { - RlpStream rlpStream = new(serializedData); - rlpStream.ReadSequenceLength(); - ConsumedNodesCount = rlpStream.DecodeLong(); - SavedStorageCount = rlpStream.DecodeLong(); - SavedStateCount = rlpStream.DecodeLong(); - SavedNodesCount = rlpStream.DecodeLong(); - SavedAccounts = rlpStream.DecodeLong(); - SavedCode = rlpStream.DecodeLong(); - RequestedNodesCount = rlpStream.DecodeLong(); - DbChecks = rlpStream.DecodeLong(); - StateWasThere = rlpStream.DecodeLong(); - StateWasNotThere = rlpStream.DecodeLong(); - DataSize = rlpStream.DecodeLong(); - - if (rlpStream.Position != rlpStream.Length) - { - SecondsInSync = rlpStream.DecodeLong(); - } + return; + } + + RlpStream rlpStream = new(serializedData); + rlpStream.ReadSequenceLength(); + ConsumedNodesCount = rlpStream.DecodeLong(); + SavedStorageCount = rlpStream.DecodeLong(); + SavedStateCount = rlpStream.DecodeLong(); + SavedNodesCount = rlpStream.DecodeLong(); + SavedAccounts = rlpStream.DecodeLong(); + SavedCode = rlpStream.DecodeLong(); + RequestedNodesCount = rlpStream.DecodeLong(); + DbChecks = rlpStream.DecodeLong(); + StateWasThere = rlpStream.DecodeLong(); + StateWasNotThere = rlpStream.DecodeLong(); + DataSize = rlpStream.DecodeLong(); + + if (rlpStream.Position != rlpStream.Length) + { + SecondsInSync = rlpStream.DecodeLong(); } } diff --git a/src/Nethermind/Nethermind.Synchronization/FastSync/StateSyncFeed.cs b/src/Nethermind/Nethermind.Synchronization/FastSync/StateSyncFeed.cs index b99b6070859..e22792cb7d6 100644 --- a/src/Nethermind/Nethermind.Synchronization/FastSync/StateSyncFeed.cs +++ b/src/Nethermind/Nethermind.Synchronization/FastSync/StateSyncFeed.cs @@ -61,7 +61,7 @@ public StateSyncFeed( } } - public override SyncResponseHandlingResult HandleResponse(StateSyncBatch? batch, PeerInfo peer = null) + public override SyncResponseHandlingResult HandleResponse(StateSyncBatch? batch, PeerInfo? peer = null) { return _treeSync.HandleResponse(batch, peer); } diff --git a/src/Nethermind/Nethermind.Synchronization/Peers/SyncPeersReport.cs b/src/Nethermind/Nethermind.Synchronization/Peers/SyncPeersReport.cs index 1dbac61f148..5f80e4a9699 100644 --- a/src/Nethermind/Nethermind.Synchronization/Peers/SyncPeersReport.cs +++ b/src/Nethermind/Nethermind.Synchronization/Peers/SyncPeersReport.cs @@ -155,7 +155,7 @@ static void CountContexts(AllocationContexts contexts, ref PeersContextCounts co } } - internal string? MakeReportForPeers(IEnumerable peers, string header) + internal string MakeReportForPeers(IEnumerable peers, string header) { _stringBuilder.Append(header); bool headerAdded = false; From 8e9f7da352dc42c4495c23a7d391a0d270314f71 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Moraczy=C5=84ski?= Date: Tue, 26 Sep 2023 14:13:29 +0200 Subject: [PATCH 37/50] update goerli pruning in tests (#6133) --- .../Nethermind.Blockchain.Test/KnownChainSizesTests.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Nethermind/Nethermind.Blockchain.Test/KnownChainSizesTests.cs b/src/Nethermind/Nethermind.Blockchain.Test/KnownChainSizesTests.cs index 415245bf21d..980713cdae0 100644 --- a/src/Nethermind/Nethermind.Blockchain.Test/KnownChainSizesTests.cs +++ b/src/Nethermind/Nethermind.Blockchain.Test/KnownChainSizesTests.cs @@ -15,7 +15,7 @@ public void Update_known_chain_sizes() { // Pruning size have to be updated frequently ChainSizes.CreateChainSizeInfo(BlockchainIds.Mainnet).PruningSize.Should().BeLessThan(210.GB()); - ChainSizes.CreateChainSizeInfo(BlockchainIds.Goerli).PruningSize.Should().BeLessThan(70.GB()); + ChainSizes.CreateChainSizeInfo(BlockchainIds.Goerli).PruningSize.Should().BeLessThan(90.GB()); ChainSizes.CreateChainSizeInfo(BlockchainIds.Sepolia).PruningSize.Should().BeLessThan(11.GB()); ChainSizes.CreateChainSizeInfo(BlockchainIds.Chiado).PruningSize.Should().Be(null); From 1f90fc2e68578b286c9bcd2d6ae96a556d1894ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Moraczy=C5=84ski?= Date: Tue, 26 Sep 2023 16:30:52 +0200 Subject: [PATCH 38/50] regular update of 4788 address (#6130) --- .../BeaconBlockRoot/BeaconBlockRootHandler.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Nethermind/Nethermind.Blockchain/BeaconBlockRoot/BeaconBlockRootHandler.cs b/src/Nethermind/Nethermind.Blockchain/BeaconBlockRoot/BeaconBlockRootHandler.cs index 3bd1fcc7fb2..925530833b6 100644 --- a/src/Nethermind/Nethermind.Blockchain/BeaconBlockRoot/BeaconBlockRootHandler.cs +++ b/src/Nethermind/Nethermind.Blockchain/BeaconBlockRoot/BeaconBlockRootHandler.cs @@ -12,7 +12,7 @@ namespace Nethermind.Consensus.BeaconBlockRoot; public class BeaconBlockRootHandler : IBeaconBlockRootHandler { public static UInt256 HISTORICAL_ROOTS_LENGTH = 8191; - private static readonly Address DefaultPbbrContractAddress = new Address("0xbEAC020008aFF7331c0A389CB2AAb67597567d7a"); + private static readonly Address DefaultPbbrContractAddress = new Address("0x000F3df6D732807Ef1319fB7B8bB8522d0Beac02"); public void ApplyContractStateChanges(Block block, IReleaseSpec spec, IWorldState stateProvider) { From fda03cbf33a39aaf3060e40abaf34db6ac71c669 Mon Sep 17 00:00:00 2001 From: Lautaro Emanuel <31224949+emlautarom1@users.noreply.github.com> Date: Tue, 26 Sep 2023 12:19:15 -0300 Subject: [PATCH 39/50] Cleanup Rider/Resharper specific warnings (#6135) - Show up as errors only in the IDE --- .../ReadOnlyBlockTreeTests.cs | 4 ++-- .../Receipts/ReceiptsRecoveryTests.cs | 2 +- .../Nethermind.Blockchain.Test/ReorgTests.cs | 4 ++-- .../Validators/HeaderValidatorTests.cs | 14 +++++------ .../Nethermind.Core.Test/AddressTests.cs | 14 ++++++----- .../Nethermind.Init/Cpu/TimeUnit.cs | 2 +- .../Modules/Proof/ProofRpcModuleTests.cs | 8 +++---- .../Modules/RpcModuleProviderTests.cs | 6 ++--- .../Modules/SubscribeModuleTests.cs | 24 +++++++++---------- .../EngineModuleTests.V3.cs | 6 ++--- .../InvalidBlockInterceptorTest.cs | 6 ++--- .../InvalidChainTrackerTest.cs | 2 +- .../InvalidHeaderInterceptorTest.cs | 6 ++--- 13 files changed, 50 insertions(+), 48 deletions(-) diff --git a/src/Nethermind/Nethermind.Blockchain.Test/ReadOnlyBlockTreeTests.cs b/src/Nethermind/Nethermind.Blockchain.Test/ReadOnlyBlockTreeTests.cs index 8a537419d0e..11188208105 100644 --- a/src/Nethermind/Nethermind.Blockchain.Test/ReadOnlyBlockTreeTests.cs +++ b/src/Nethermind/Nethermind.Blockchain.Test/ReadOnlyBlockTreeTests.cs @@ -11,8 +11,8 @@ namespace Nethermind.Blockchain.Test { public class ReadOnlyBlockTreeTests { - private IBlockTree _innerBlockTree; - private ReadOnlyBlockTree _blockTree; + private IBlockTree _innerBlockTree = null!; + private ReadOnlyBlockTree _blockTree = null!; [SetUp] public void SetUp() diff --git a/src/Nethermind/Nethermind.Blockchain.Test/Receipts/ReceiptsRecoveryTests.cs b/src/Nethermind/Nethermind.Blockchain.Test/Receipts/ReceiptsRecoveryTests.cs index 9244195867a..fbf4bf4cde7 100644 --- a/src/Nethermind/Nethermind.Blockchain.Test/Receipts/ReceiptsRecoveryTests.cs +++ b/src/Nethermind/Nethermind.Blockchain.Test/Receipts/ReceiptsRecoveryTests.cs @@ -14,7 +14,7 @@ namespace Nethermind.Blockchain.Test.Receipts; public class ReceiptsRecoveryTests { - private IReceiptsRecovery _receiptsRecovery; + private IReceiptsRecovery _receiptsRecovery = null!; [SetUp] public void Setup() diff --git a/src/Nethermind/Nethermind.Blockchain.Test/ReorgTests.cs b/src/Nethermind/Nethermind.Blockchain.Test/ReorgTests.cs index 159755b7824..fc8005305ee 100644 --- a/src/Nethermind/Nethermind.Blockchain.Test/ReorgTests.cs +++ b/src/Nethermind/Nethermind.Blockchain.Test/ReorgTests.cs @@ -31,8 +31,8 @@ namespace Nethermind.Blockchain.Test [TestFixture] public class ReorgTests { - private BlockchainProcessor _blockchainProcessor; - private BlockTree _blockTree; + private BlockchainProcessor _blockchainProcessor = null!; + private BlockTree _blockTree = null!; [SetUp] public void Setup() diff --git a/src/Nethermind/Nethermind.Blockchain.Test/Validators/HeaderValidatorTests.cs b/src/Nethermind/Nethermind.Blockchain.Test/Validators/HeaderValidatorTests.cs index 67d8fa804fe..8021996cf6b 100644 --- a/src/Nethermind/Nethermind.Blockchain.Test/Validators/HeaderValidatorTests.cs +++ b/src/Nethermind/Nethermind.Blockchain.Test/Validators/HeaderValidatorTests.cs @@ -28,13 +28,13 @@ namespace Nethermind.Blockchain.Test.Validators [TestFixture] public class HeaderValidatorTests { - private IHeaderValidator _validator; - private ISealValidator _ethash; - private TestLogger _testLogger; - private Block _parentBlock; - private Block _block; - private IBlockTree _blockTree; - private ISpecProvider _specProvider; + private IHeaderValidator _validator = null!; + private ISealValidator _ethash = null!; + private TestLogger _testLogger = null!; + private Block _parentBlock = null!; + private Block _block = null!; + private IBlockTree _blockTree = null!; + private ISpecProvider _specProvider = null!; [SetUp] public void Setup() diff --git a/src/Nethermind/Nethermind.Core.Test/AddressTests.cs b/src/Nethermind/Nethermind.Core.Test/AddressTests.cs index 4c61eee2ef4..b3a847049d2 100644 --- a/src/Nethermind/Nethermind.Core.Test/AddressTests.cs +++ b/src/Nethermind/Nethermind.Core.Test/AddressTests.cs @@ -91,9 +91,10 @@ public void Equals_operator_works() Assert.False(addressA == addressB); Assert.False(addressA is null); Assert.False(null == addressA); -#pragma warning disable CS8520 - Assert.True((Address?)null is null); -#pragma warning restore CS8520 + { + Address? address = null; + Assert.True(address is null); + } } [Test] @@ -110,9 +111,10 @@ public void Not_equals_operator_works() Assert.True(addressA != addressB); Assert.True(addressA is not null); Assert.True(null != addressA); -#pragma warning disable CS8519 - Assert.False((Address?)null is not null); -#pragma warning restore CS8519 + { + Address? address = null; + Assert.False(address is not null); + } } [Test] diff --git a/src/Nethermind/Nethermind.Init/Cpu/TimeUnit.cs b/src/Nethermind/Nethermind.Init/Cpu/TimeUnit.cs index 9e5ea1a3dfa..475ce19be3b 100644 --- a/src/Nethermind/Nethermind.Init/Cpu/TimeUnit.cs +++ b/src/Nethermind/Nethermind.Init/Cpu/TimeUnit.cs @@ -77,7 +77,7 @@ public bool Equals(TimeUnit? other) return false; } - if ((object)this == other) + if (ReferenceEquals((object)this, other)) { return true; } diff --git a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Proof/ProofRpcModuleTests.cs b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Proof/ProofRpcModuleTests.cs index 7960a89c925..4cb6b4541c1 100644 --- a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Proof/ProofRpcModuleTests.cs +++ b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Proof/ProofRpcModuleTests.cs @@ -40,10 +40,10 @@ public class ProofRpcModuleTests { private readonly bool _createSystemAccount; private readonly bool _useNonZeroGasPrice; - private IProofRpcModule _proofRpcModule; - private IBlockTree _blockTree; - private IDbProvider _dbProvider; - private TestSpecProvider _specProvider; + private IProofRpcModule _proofRpcModule = null!; + private IBlockTree _blockTree = null!; + private IDbProvider _dbProvider = null!; + private TestSpecProvider _specProvider = null!; public ProofRpcModuleTests(bool createSystemAccount, bool useNonZeroGasPrice) { diff --git a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/RpcModuleProviderTests.cs b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/RpcModuleProviderTests.cs index 9ba5ec17022..980d8f169c2 100644 --- a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/RpcModuleProviderTests.cs +++ b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/RpcModuleProviderTests.cs @@ -16,9 +16,9 @@ namespace Nethermind.JsonRpc.Test.Modules [TestFixture] public class RpcModuleProviderTests { - private RpcModuleProvider _moduleProvider; - private IFileSystem _fileSystem; - private JsonRpcContext _context; + private RpcModuleProvider _moduleProvider = null!; + private IFileSystem _fileSystem = null!; + private JsonRpcContext _context = null!; [SetUp] public void Initialize() diff --git a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/SubscribeModuleTests.cs b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/SubscribeModuleTests.cs index 3ea59e9e676..68419d76ffd 100644 --- a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/SubscribeModuleTests.cs +++ b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/SubscribeModuleTests.cs @@ -40,18 +40,18 @@ namespace Nethermind.JsonRpc.Test.Modules [TestFixture] public class SubscribeModuleTests { - private ISubscribeRpcModule _subscribeRpcModule; - private ILogManager _logManager; - private IBlockTree _blockTree; - private ITxPool _txPool; - private IReceiptStorage _receiptStorage; - private IFilterStore _filterStore; - private ISubscriptionManager _subscriptionManager; - private IJsonRpcDuplexClient _jsonRpcDuplexClient; - private IJsonSerializer _jsonSerializer; - private ISpecProvider _specProvider; - private IReceiptMonitor _receiptCanonicalityMonitor; - private ISyncConfig _syncConfig; + private ISubscribeRpcModule _subscribeRpcModule = null!; + private ILogManager _logManager = null!; + private IBlockTree _blockTree = null!; + private ITxPool _txPool = null!; + private IReceiptStorage _receiptStorage = null!; + private IFilterStore _filterStore = null!; + private ISubscriptionManager _subscriptionManager = null!; + private IJsonRpcDuplexClient _jsonRpcDuplexClient = null!; + private IJsonSerializer _jsonSerializer = null!; + private ISpecProvider _specProvider = null!; + private IReceiptMonitor _receiptCanonicalityMonitor = null!; + private ISyncConfig _syncConfig = null!; [SetUp] public void Setup() diff --git a/src/Nethermind/Nethermind.Merge.Plugin.Test/EngineModuleTests.V3.cs b/src/Nethermind/Nethermind.Merge.Plugin.Test/EngineModuleTests.V3.cs index 76c2e7e6450..ee8525f200e 100644 --- a/src/Nethermind/Nethermind.Merge.Plugin.Test/EngineModuleTests.V3.cs +++ b/src/Nethermind/Nethermind.Merge.Plugin.Test/EngineModuleTests.V3.cs @@ -197,7 +197,7 @@ public async Task NewPayloadV3_should_decline_null_blobversionedhashes() executionPayloadString, null!); JsonRpcErrorResponse? response = (await jsonRpcService.SendRequestAsync(request, context)) as JsonRpcErrorResponse; Assert.That(response?.Error, Is.Not.Null); - Assert.That(response.Error.Code, Is.EqualTo(ErrorCodes.InvalidParams)); + Assert.That(response!.Error!.Code, Is.EqualTo(ErrorCodes.InvalidParams)); } private async Task<(JsonRpcService jsonRpcService, JsonRpcContext context, EthereumJsonSerializer serializer, ExecutionPayloadV3 correctExecutionPayload)> @@ -246,7 +246,7 @@ public async Task NewPayloadV3_should_decline_empty_fields() serializer.Serialize(executionPayloadAsJObject), blobsString); JsonRpcErrorResponse? response = (await jsonRpcService.SendRequestAsync(request, context)) as JsonRpcErrorResponse; Assert.That(response?.Error, Is.Not.Null); - Assert.That(response.Error.Code, Is.EqualTo(ErrorCodes.InvalidParams)); + Assert.That(response!.Error!.Code, Is.EqualTo(ErrorCodes.InvalidParams)); } foreach (string prop in props) @@ -258,7 +258,7 @@ public async Task NewPayloadV3_should_decline_empty_fields() serializer.Serialize(executionPayloadAsJObject), blobsString); JsonRpcErrorResponse? response = (await jsonRpcService.SendRequestAsync(request, context)) as JsonRpcErrorResponse; Assert.That(response?.Error, Is.Not.Null); - Assert.That(response.Error.Code, Is.EqualTo(ErrorCodes.InvalidParams)); + Assert.That(response!.Error!.Code, Is.EqualTo(ErrorCodes.InvalidParams)); } } diff --git a/src/Nethermind/Nethermind.Merge.Plugin.Test/InvalidChainTracker/InvalidBlockInterceptorTest.cs b/src/Nethermind/Nethermind.Merge.Plugin.Test/InvalidChainTracker/InvalidBlockInterceptorTest.cs index c1dce709da9..90e1e1d1955 100644 --- a/src/Nethermind/Nethermind.Merge.Plugin.Test/InvalidChainTracker/InvalidBlockInterceptorTest.cs +++ b/src/Nethermind/Nethermind.Merge.Plugin.Test/InvalidChainTracker/InvalidBlockInterceptorTest.cs @@ -17,9 +17,9 @@ namespace Nethermind.Merge.Plugin.Test; public class InvalidBlockInterceptorTest { - private IBlockValidator _baseValidator; - private IInvalidChainTracker _tracker; - private InvalidBlockInterceptor _invalidBlockInterceptor; + private IBlockValidator _baseValidator = null!; + private IInvalidChainTracker _tracker = null!; + private InvalidBlockInterceptor _invalidBlockInterceptor = null!; [SetUp] public void Setup() diff --git a/src/Nethermind/Nethermind.Merge.Plugin.Test/InvalidChainTracker/InvalidChainTrackerTest.cs b/src/Nethermind/Nethermind.Merge.Plugin.Test/InvalidChainTracker/InvalidChainTrackerTest.cs index 0faafd424ac..bc702268373 100644 --- a/src/Nethermind/Nethermind.Merge.Plugin.Test/InvalidChainTracker/InvalidChainTrackerTest.cs +++ b/src/Nethermind/Nethermind.Merge.Plugin.Test/InvalidChainTracker/InvalidChainTrackerTest.cs @@ -20,7 +20,7 @@ namespace Nethermind.Merge.Plugin.Test; [TestFixture] public class InvalidChainTrackerTest { - private InvalidChainTracker.InvalidChainTracker _tracker; + private InvalidChainTracker.InvalidChainTracker _tracker = null!; [SetUp] public void Setup() diff --git a/src/Nethermind/Nethermind.Merge.Plugin.Test/InvalidChainTracker/InvalidHeaderInterceptorTest.cs b/src/Nethermind/Nethermind.Merge.Plugin.Test/InvalidChainTracker/InvalidHeaderInterceptorTest.cs index 1a082adb524..9e876ec8552 100644 --- a/src/Nethermind/Nethermind.Merge.Plugin.Test/InvalidChainTracker/InvalidHeaderInterceptorTest.cs +++ b/src/Nethermind/Nethermind.Merge.Plugin.Test/InvalidChainTracker/InvalidHeaderInterceptorTest.cs @@ -15,9 +15,9 @@ namespace Nethermind.Merge.Plugin.Test; public class InvalidHeaderInterceptorTest { - private IHeaderValidator _baseValidator; - private IInvalidChainTracker _tracker; - private InvalidHeaderInterceptor _invalidHeaderInterceptor; + private IHeaderValidator _baseValidator = null!; + private IInvalidChainTracker _tracker = null!; + private InvalidHeaderInterceptor _invalidHeaderInterceptor = null!; [SetUp] public void Setup() From 7c5ead2d43e3127015c5e347c92ac59500974aac Mon Sep 17 00:00:00 2001 From: Nikita Mescheryakov Date: Wed, 27 Sep 2023 11:54:48 +0300 Subject: [PATCH 40/50] Update pruning estimations for mainnet (#6138) --- src/Nethermind/Nethermind.Blockchain/KnownChainSizes.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Nethermind/Nethermind.Blockchain/KnownChainSizes.cs b/src/Nethermind/Nethermind.Blockchain/KnownChainSizes.cs index cef3caa8cee..28724697b02 100644 --- a/src/Nethermind/Nethermind.Blockchain/KnownChainSizes.cs +++ b/src/Nethermind/Nethermind.Blockchain/KnownChainSizes.cs @@ -76,8 +76,8 @@ public static IChainEstimations CreateChainSizeInfo(ulong chainId) BlockchainIds.Mainnet => new ChainEstimations( new LinearExtrapolation(167.GB(), 70.MB(), new DateTime(2023, 07, 14)), new LinearExtrapolation( - 172553555637, new DateTime(2023, 05, 18, 18, 12, 0), - 177439054863, new DateTime(2023, 06, 8, 02, 36, 0))), + 177439054863, new DateTime(2023, 06, 8, 02, 36, 0), + 188742060333, new DateTime(2023, 09, 26, 19, 32, 0))), BlockchainIds.Gnosis => new ChainEstimations( new LinearExtrapolation(18000.MB(), 48.MB(), new DateTime(2021, 12, 7))), BlockchainIds.EnergyWeb => new ChainEstimations( From dc1781d8b1caf7f56acfc2ea0f7ccb94eba9ec94 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20Chodo=C5=82a?= <43241881+kamilchodola@users.noreply.github.com> Date: Wed, 27 Sep 2023 12:55:11 +0200 Subject: [PATCH 41/50] Change TuneDb default to HeavyWrite (#6136) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Kamil Chodoła --- .../Nethermind.Blockchain/Synchronization/ISyncConfig.cs | 2 +- .../Nethermind.Blockchain/Synchronization/SyncConfig.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Nethermind/Nethermind.Blockchain/Synchronization/ISyncConfig.cs b/src/Nethermind/Nethermind.Blockchain/Synchronization/ISyncConfig.cs index 9aaacca9e6b..7b62189c959 100644 --- a/src/Nethermind/Nethermind.Blockchain/Synchronization/ISyncConfig.cs +++ b/src/Nethermind/Nethermind.Blockchain/Synchronization/ISyncConfig.cs @@ -104,7 +104,7 @@ public interface ISyncConfig : IConfig [ConfigItem(Description = "[EXPERIMENTAL] Only for non validator nodes! If set to true, DownloadReceiptsInFastSync and/or DownloadBodiesInFastSync can be set to false.", DefaultValue = "false")] public bool NonValidatorNode { get; set; } - [ConfigItem(Description = "[EXPERIMENTAL] Optimize db for write during sync. Significantly reduce total writes written and some sync time if you are not network limited.", DefaultValue = "WriteBias")] + [ConfigItem(Description = "[EXPERIMENTAL] Optimize db for write during sync. Significantly reduce total writes written and some sync time if you are not network limited.", DefaultValue = "HeavyWrite")] public ITunableDb.TuneType TuneDbMode { get; set; } [ConfigItem(Description = "[EXPERIMENTAL] Optimize db for write during sync just for blocks db. Useful for turning on blobs file.", DefaultValue = "EnableBlobFiles")] diff --git a/src/Nethermind/Nethermind.Blockchain/Synchronization/SyncConfig.cs b/src/Nethermind/Nethermind.Blockchain/Synchronization/SyncConfig.cs index 47ffa44b655..97608552ae9 100644 --- a/src/Nethermind/Nethermind.Blockchain/Synchronization/SyncConfig.cs +++ b/src/Nethermind/Nethermind.Blockchain/Synchronization/SyncConfig.cs @@ -60,7 +60,7 @@ public string? PivotHash public bool StrictMode { get; set; } = false; public bool BlockGossipEnabled { get; set; } = true; public bool NonValidatorNode { get; set; } = false; - public ITunableDb.TuneType TuneDbMode { get; set; } = ITunableDb.TuneType.WriteBias; + public ITunableDb.TuneType TuneDbMode { get; set; } = ITunableDb.TuneType.HeavyWrite; public ITunableDb.TuneType BlocksDbTuneDbMode { get; set; } = ITunableDb.TuneType.EnableBlobFiles; public int MaxProcessingThreads { get; set; } public bool ExitOnSynced { get; set; } = false; From 90aceb6901ae3cf90adda51218c95e0dba9f24d1 Mon Sep 17 00:00:00 2001 From: AKABABA-ETH <111528650+AKABABA-ETH@users.noreply.github.com> Date: Thu, 28 Sep 2023 23:46:13 +0800 Subject: [PATCH 42/50] fix typos (#6137) --- src/Nethermind/Ethereum.KeyAddress.Test/KeyAddressTests.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Nethermind/Ethereum.KeyAddress.Test/KeyAddressTests.cs b/src/Nethermind/Ethereum.KeyAddress.Test/KeyAddressTests.cs index 7881bf48506..cc25a50d7e6 100644 --- a/src/Nethermind/Ethereum.KeyAddress.Test/KeyAddressTests.cs +++ b/src/Nethermind/Ethereum.KeyAddress.Test/KeyAddressTests.cs @@ -75,7 +75,7 @@ public void Signature_as_expected(KeyAddressTest test) string expectedSigHex = expectedSig.ToString(); Address expectedAddress = new Address(test.Address); - Assert.That(actualAddress, Is.EqualTo(expectedAddress), "address vs adress from private key"); + Assert.That(actualAddress, Is.EqualTo(expectedAddress), "address vs address from private key"); Address recoveredActualAddress = _ecdsa.RecoverAddress(actualSig, Keccak.OfAnEmptyString); Assert.That(recoveredActualAddress, Is.EqualTo(actualAddress)); From 27a4807cf2b4164ce71cd2c27e3a9c7d9f2dd61b Mon Sep 17 00:00:00 2001 From: Ruben Buniatyan Date: Thu, 28 Sep 2023 23:00:57 +0200 Subject: [PATCH 43/50] Fix PPA package post-install script (#5991) * Fix PPA post install script to download from the latest release branch * Remove redundant space * Update Nethermind executable name --- scripts/deployment/debian/postinst | 10 ++++++---- scripts/execution.sh | 6 +++--- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/scripts/deployment/debian/postinst b/scripts/deployment/debian/postinst index 303c1b7d234..2a279274886 100644 --- a/scripts/deployment/debian/postinst +++ b/scripts/deployment/debian/postinst @@ -1,12 +1,14 @@ #!/bin/bash arch=$(uname -m) +json=$(curl -sSL https://api.github.com/repos/NethermindEth/nethermind/releases/latest) +tag_name=$(echo $json | jq -r '.tag_name') if [[ $arch == x86_64* ]]; then - curl -s https://api.github.com/repos/NethermindEth/nethermind/releases/latest | jq -r ".assets[] | select(.name) | .browser_download_url" | grep linux-x64 | xargs wget -O nethermind.zip -q + echo $json | jq -r '.assets[].browser_download_url | select(contains("linux-x64"))' | xargs -I % curl -sSL % -o nethermind.zip ln -s /usr/lib/x86_64-linux-gnu/libdl.so.2 /usr/lib/x86_64-linux-gnu/libdl.so > /dev/null 2>&1 -elif [[ $arch == arm* ]] || [[ $arch = aarch64 ]]; then - curl -s https://api.github.com/repos/NethermindEth/nethermind/releases/latest | jq -r ".assets[] | select(.name) | .browser_download_url" | grep linux-arm64 | xargs wget -O nethermind.zip -q +elif [[ $arch == arm* ]] || [[ $arch = aarch64 ]]; then + echo $json | jq -r '.assets[].browser_download_url | select(contains("linux-arm64"))' | xargs -I % curl -sSL % -o nethermind.zip ln -s /usr/lib/aarch64-linux-gnu/libdl.so.2 /usr/lib/aarch64-linux-gnu/libdl.so > /dev/null 2>&1 apt update > /dev/null 2>&1 && apt install libgflags-dev -y > /dev/null 2>&1 fi @@ -17,5 +19,5 @@ mkdir -p /usr/share/nethermind cp -r nethermind/* /usr/share/nethermind rm -rf nethermind -wget https://raw.githubusercontent.com/NethermindEth/nethermind/master/scripts/execution.sh -O /usr/bin/nethermind +curl -sSL https://raw.githubusercontent.com/NethermindEth/nethermind/release/$tag_name/scripts/execution.sh -o /usr/bin/nethermind chmod +x /usr/bin/nethermind diff --git a/scripts/execution.sh b/scripts/execution.sh index 6869c15af3c..ebb8c54f2fe 100644 --- a/scripts/execution.sh +++ b/scripts/execution.sh @@ -7,9 +7,9 @@ opts=$@ if [ ${#opts} -gt 0 ] then echo 'Executing Nethermind' - sudo /usr/share/nethermind/Nethermind.Runner $@ + sudo /usr/share/nethermind/nethermind $@ else - echo 'Executing Nethermind Launcher' + echo 'Executing Nethermind launcher' cd /usr/share/nethermind - sudo /usr/share/nethermind/Nethermind.Launcher + sudo /usr/share/nethermind/nethermind-launcher fi From 63070a3e271be6ade352edaea97c056d5ae54610 Mon Sep 17 00:00:00 2001 From: Ruben Buniatyan Date: Thu, 28 Sep 2023 23:01:08 +0200 Subject: [PATCH 44/50] Update executable and networks (#6141) --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 80bf4b60c8e..03068c709ec 100644 --- a/README.md +++ b/README.md @@ -22,7 +22,7 @@ Nethermind documentation is available at [docs.nethermind.io](https://docs.nethe ### Supported networks -**`Mainnet`** **`Goerli`** **`Sepolia`** **`Gnosis (xDai)`** **`Energy Web`** **`Volta`** +**`Mainnet`** **`Goerli`** **`Sepolia`** **`Holesky`** **`Gnosis (xDai)`** **`Chiado`** **`Energy Web`** **`Volta`** ## Download and run @@ -65,8 +65,8 @@ winget install Microsoft.VCRedist.2015+.x64 #### Install using Windows Package Manager 1. `winget install nethermind` -2. To run directly: `nethermind.runner.exe -c mainnet` \ - or with the assistant: `nethermind.launcher.exe` +2. To run directly: `nethermind.exe -c mainnet` \ + or with the assistant: `nethermind-launcher.exe` ### On macOS @@ -106,7 +106,7 @@ Install [.NET SDK](https://dotnet.microsoft.com/en-us/download) ### Clone the repository ```sh -git clone https://github.com/nethermindeth/nethermind --recursive +git clone --recursive https://github.com/nethermindeth/nethermind.git ``` ### Build and run From b3bc144478f8c5cca1381865769b06bdabb3d539 Mon Sep 17 00:00:00 2001 From: Amirul Ashraf Date: Fri, 29 Sep 2023 18:02:09 +0800 Subject: [PATCH 45/50] Perf/sorted batch (#6142) * Sorted keccak batch * Using list only * Change algo * Remove valuekeccak key * Whitespace --- .../Receipts/PersistentReceiptStorage.cs | 2 +- .../Nethermind.Core.Test/SortedBatchTests.cs | 60 ++++++++++++ src/Nethermind/Nethermind.Core/SortedBatch.cs | 96 +++++++++++++++++++ .../Nethermind.Db.Rocks/ColumnDb.cs | 2 +- .../Nethermind.Db.Rocks/DbOnTheRocks.cs | 72 +++----------- .../Nethermind.State.Test/StateTreeTests.cs | 2 +- .../Nethermind.Trie.Test/TrieNodeTests.cs | 1 + .../Nethermind.Trie/Pruning/TrieStore.cs | 6 +- 8 files changed, 174 insertions(+), 67 deletions(-) create mode 100644 src/Nethermind/Nethermind.Core.Test/SortedBatchTests.cs create mode 100644 src/Nethermind/Nethermind.Core/SortedBatch.cs diff --git a/src/Nethermind/Nethermind.Blockchain/Receipts/PersistentReceiptStorage.cs b/src/Nethermind/Nethermind.Blockchain/Receipts/PersistentReceiptStorage.cs index 24425624ead..1d89f990927 100644 --- a/src/Nethermind/Nethermind.Blockchain/Receipts/PersistentReceiptStorage.cs +++ b/src/Nethermind/Nethermind.Blockchain/Receipts/PersistentReceiptStorage.cs @@ -342,7 +342,7 @@ public bool HasBlock(long blockNumber, Keccak blockHash) public void EnsureCanonical(Block block) { - using IBatch batch = _transactionDb.StartBatch(); + using IBatch batch = _transactionDb.StartBatch().ToSortedBatch(); long headNumber = _blockTree.FindBestSuggestedHeader()?.Number ?? 0; diff --git a/src/Nethermind/Nethermind.Core.Test/SortedBatchTests.cs b/src/Nethermind/Nethermind.Core.Test/SortedBatchTests.cs new file mode 100644 index 00000000000..835ed0aab4e --- /dev/null +++ b/src/Nethermind/Nethermind.Core.Test/SortedBatchTests.cs @@ -0,0 +1,60 @@ +// SPDX-FileCopyrightText: 2023 Demerzel Solutions Limited +// SPDX-License-Identifier: LGPL-3.0-only + +using System; +using System.Collections.Generic; +using System.Linq; +using FluentAssertions; +using Nethermind.Core.Extensions; +using Nethermind.Core.Test.Builders; +using NUnit.Framework; + +namespace Nethermind.Core.Test; + +public class SortedBatchTests +{ + [Test] + public void Test_BatchWillSort() + { + TestBatch baseBatch = new TestBatch(); + + IBatch sortedBatch = baseBatch.ToSortedBatch(); + + IList expectedOrder = new List(); + for (int i = 0; i < 10; i++) + { + sortedBatch[TestItem.ValueKeccaks[i].ToByteArray()] = TestItem.ValueKeccaks[i].ToByteArray(); + expectedOrder.Add(TestItem.ValueKeccaks[i].ToByteArray()); + } + + baseBatch.DisposeCalled.Should().BeFalse(); + baseBatch.SettedValues.Count.Should().Be(0); + + sortedBatch.Dispose(); + + baseBatch.DisposeCalled.Should().BeTrue(); + expectedOrder = expectedOrder.Order(Bytes.Comparer).ToList(); + baseBatch.SettedValues.Should().BeEquivalentTo(expectedOrder); + } + + private class TestBatch : IBatch + { + public bool DisposeCalled { get; set; } + public List SettedValues { get; set; } = new(); + + public void Dispose() + { + DisposeCalled = true; + } + + public byte[]? Get(ReadOnlySpan key, ReadFlags flags = ReadFlags.None) + { + return null; + } + + public void Set(ReadOnlySpan key, byte[]? value, WriteFlags flags = WriteFlags.None) + { + SettedValues.Add(key.ToArray()); + } + } +} diff --git a/src/Nethermind/Nethermind.Core/SortedBatch.cs b/src/Nethermind/Nethermind.Core/SortedBatch.cs new file mode 100644 index 00000000000..2f37127dc31 --- /dev/null +++ b/src/Nethermind/Nethermind.Core/SortedBatch.cs @@ -0,0 +1,96 @@ +// SPDX-FileCopyrightText: 2023 Demerzel Solutions Limited +// SPDX-License-Identifier: LGPL-3.0-only + +using System; +using System.Collections.Concurrent; +using System.Linq; +using Nethermind.Core.Collections; +using Nethermind.Core.Extensions; + +namespace Nethermind.Core; + +/// +/// Rocksdb's skiplist memtable have a fast path when the keys are inserted in ascending order. Otherwise, its seems +/// to be limited to 1Mil writes per second. +/// TODO: FlatDB layout need different key type to match the DB ordering. +/// +public class SortedBatch : IBatch +{ + private const int InitialBatchSize = 300; + private static readonly int MaxCached = Environment.ProcessorCount; + + private static ConcurrentQueue> s_cache = new(); + + private readonly IBatch _baseBatch; + private WriteFlags _writeFlags = WriteFlags.None; + + private SpanDictionary _batchData = CreateOrGetFromCache(); + + public SortedBatch(IBatch dbOnTheRocks) + { + _baseBatch = dbOnTheRocks; + } + + public void Dispose() + { + SpanDictionary batchData = _batchData; + // Clear the _batchData reference so is null if Get is called. + _batchData = null!; + if (batchData.Count == 0) + { + // No data to write, skip empty batches + ReturnToCache(batchData); + _baseBatch.Dispose(); + return; + } + + // Sort the batch by key + foreach (var kv in batchData.OrderBy(i => i.Key, Bytes.Comparer)) + { + _baseBatch.Set(kv.Key, kv.Value, _writeFlags); + } + ReturnToCache(batchData); + + _baseBatch.Dispose(); + } + + public byte[]? Get(ReadOnlySpan key, ReadFlags flags = ReadFlags.None) + { + // Not checking _isDisposing here as for some reason, sometimes is is read after dispose + return _batchData?.TryGetValue(key, out byte[]? value) ?? false ? value : _baseBatch.Get(key); + } + + public void Set(ReadOnlySpan key, byte[]? value, WriteFlags flags = WriteFlags.None) + { + _batchData[key] = value; + + _writeFlags = flags; + } + + private static SpanDictionary CreateOrGetFromCache() + { + if (s_cache.TryDequeue(out SpanDictionary? batchData)) + { + return batchData; + } + + return new SpanDictionary(InitialBatchSize, Bytes.SpanEqualityComparer); + } + + private static void ReturnToCache(SpanDictionary batchData) + { + if (s_cache.Count >= MaxCached) return; + + batchData.Clear(); + batchData.TrimExcess(capacity: InitialBatchSize); + s_cache.Enqueue(batchData); + } +} + +public static class BatchExtensions +{ + public static SortedBatch ToSortedBatch(this IBatch batch) + { + return new SortedBatch(batch); + } +} diff --git a/src/Nethermind/Nethermind.Db.Rocks/ColumnDb.cs b/src/Nethermind/Nethermind.Db.Rocks/ColumnDb.cs index dceb3599a21..1b86a363d86 100644 --- a/src/Nethermind/Nethermind.Db.Rocks/ColumnDb.cs +++ b/src/Nethermind/Nethermind.Db.Rocks/ColumnDb.cs @@ -92,7 +92,7 @@ public void Set(ReadOnlySpan key, byte[]? value, WriteFlags flags = WriteF } else { - _underlyingBatch.Set(key, value, _columnDb._columnFamily); + _underlyingBatch.Set(key, value, _columnDb._columnFamily, flags); } } } diff --git a/src/Nethermind/Nethermind.Db.Rocks/DbOnTheRocks.cs b/src/Nethermind/Nethermind.Db.Rocks/DbOnTheRocks.cs index 7aba5e70890..b54a8be7a35 100644 --- a/src/Nethermind/Nethermind.Db.Rocks/DbOnTheRocks.cs +++ b/src/Nethermind/Nethermind.Db.Rocks/DbOnTheRocks.cs @@ -788,20 +788,15 @@ public IBatch StartBatch() internal class RocksDbBatch : IBatch { - private const int InitialBatchSize = 300; - private static readonly int MaxCached = Environment.ProcessorCount; - - private static ConcurrentQueue> s_cache = new(); - private readonly DbOnTheRocks _dbOnTheRocks; + private readonly WriteBatch _rocksBatch; private WriteFlags _writeFlags = WriteFlags.None; private bool _isDisposed; - private SpanDictionary _batchData = CreateOrGetFromCache(); - public RocksDbBatch(DbOnTheRocks dbOnTheRocks) { _dbOnTheRocks = dbOnTheRocks; + _rocksBatch = new WriteBatch(); if (_dbOnTheRocks._isDisposing) { @@ -822,37 +817,11 @@ public void Dispose() } _isDisposed = true; - SpanDictionary batchData = _batchData; - // Clear the _batchData reference so is null if Get is called. - _batchData = null!; - if (batchData.Count == 0) - { - // No data to write, skip empty batches - ReturnToCache(batchData); - _dbOnTheRocks._currentBatches.TryRemove(this); - return; - } - try { - WriteBatch rocksBatch = new(); - // Sort the batch by key - foreach (var kv in batchData.OrderBy(i => i.Key, Bytes.Comparer)) - { - if (kv.Value.data is null) - { - rocksBatch.Delete(kv.Key, kv.Value.cf); - } - else - { - rocksBatch.Put(kv.Key, kv.Value.data, kv.Value.cf); - } - } - ReturnToCache(batchData); - - _dbOnTheRocks._db.Write(rocksBatch, _dbOnTheRocks.WriteFlagsToWriteOptions(_writeFlags)); + _dbOnTheRocks._db.Write(_rocksBatch, _dbOnTheRocks.WriteFlagsToWriteOptions(_writeFlags)); _dbOnTheRocks._currentBatches.TryRemove(this); - rocksBatch.Dispose(); + _rocksBatch.Dispose(); } catch (RocksDbSharpException e) { @@ -864,7 +833,9 @@ public void Dispose() public byte[]? Get(ReadOnlySpan key, ReadFlags flags = ReadFlags.None) { // Not checking _isDisposing here as for some reason, sometimes is is read after dispose - return _batchData?.TryGetValue(key, out var value) ?? false ? value.data : _dbOnTheRocks.Get(key, flags); + // Note: The batch itself is not checked. Will need to use WriteBatchWithIndex to do that, but that will + // hurt perf. + return _dbOnTheRocks.Get(key, flags); } public void Delete(ReadOnlySpan key, ColumnFamilyHandle? cf = null) @@ -874,17 +845,18 @@ public void Delete(ReadOnlySpan key, ColumnFamilyHandle? cf = null) throw new ObjectDisposedException($"Attempted to write a disposed batch {_dbOnTheRocks.Name}"); } - _batchData[key] = (null, cf); + _rocksBatch.Delete(key, cf); } - public void Set(ReadOnlySpan key, byte[]? value, ColumnFamilyHandle? cf = null) + public void Set(ReadOnlySpan key, byte[]? value, ColumnFamilyHandle? cf = null, WriteFlags flags = WriteFlags.None) { if (_isDisposed) { throw new ObjectDisposedException($"Attempted to write a disposed batch {_dbOnTheRocks.Name}"); } - _batchData[key] = (value, cf); + _rocksBatch.Put(key, value, cf); + _writeFlags = flags; } public void Set(ReadOnlySpan key, byte[]? value, WriteFlags flags = WriteFlags.None) @@ -894,29 +866,9 @@ public void Set(ReadOnlySpan key, byte[]? value, WriteFlags flags = WriteF throw new ObjectDisposedException($"Attempted to write a disposed batch {_dbOnTheRocks.Name}"); } - _batchData[key] = (value, null); - + _rocksBatch.Put(key, value); _writeFlags = flags; } - - private static SpanDictionary CreateOrGetFromCache() - { - if (s_cache.TryDequeue(out SpanDictionary? batchData)) - { - return batchData; - } - - return new(InitialBatchSize, Bytes.SpanEqualityComparer); - } - - private static void ReturnToCache(SpanDictionary batchData) - { - if (s_cache.Count >= MaxCached) return; - - batchData.Clear(); - batchData.TrimExcess(capacity: InitialBatchSize); - s_cache.Enqueue(batchData); - } } public void Flush() diff --git a/src/Nethermind/Nethermind.State.Test/StateTreeTests.cs b/src/Nethermind/Nethermind.State.Test/StateTreeTests.cs index b0f9662e558..dd3db842bed 100644 --- a/src/Nethermind/Nethermind.State.Test/StateTreeTests.cs +++ b/src/Nethermind/Nethermind.State.Test/StateTreeTests.cs @@ -62,7 +62,7 @@ public void Minimal_writes_when_setting_on_empty_scenario_2() tree.Set(new Keccak("eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeb1eeeeeb0"), _account0); tree.Set(new Keccak("eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeb1eeeeeb1"), _account0); tree.Commit(0); - Assert.That(db.WritesCount, Is.EqualTo(7), "writes"); // extension, branch, leaf, extension, branch, 2x same leaf + Assert.That(db.WritesCount, Is.EqualTo(6), "writes"); // extension, branch, leaf, extension, branch, 2x same leaf Assert.That(Trie.Metrics.TreeNodeHashCalculations, Is.EqualTo(7), "hashes"); Assert.That(Trie.Metrics.TreeNodeRlpEncodings, Is.EqualTo(7), "encodings"); } diff --git a/src/Nethermind/Nethermind.Trie.Test/TrieNodeTests.cs b/src/Nethermind/Nethermind.Trie.Test/TrieNodeTests.cs index 756f2e7548a..dea83ed4a89 100644 --- a/src/Nethermind/Nethermind.Trie.Test/TrieNodeTests.cs +++ b/src/Nethermind/Nethermind.Trie.Test/TrieNodeTests.cs @@ -908,6 +908,7 @@ public void Rlp_is_cloned_when_cloning() leaf2.ResolveKey(trieStore, false); leaf2.Seal(); trieStore.CommitNode(0, new NodeCommitInfo(leaf2)); + trieStore.FinishBlockCommit(TrieType.State, 0, leaf2); TrieNode trieNode = new(NodeType.Branch); trieNode.SetChild(1, leaf1); diff --git a/src/Nethermind/Nethermind.Trie/Pruning/TrieStore.cs b/src/Nethermind/Nethermind.Trie/Pruning/TrieStore.cs index 66c5cd18d88..64b13468f7b 100644 --- a/src/Nethermind/Nethermind.Trie/Pruning/TrieStore.cs +++ b/src/Nethermind/Nethermind.Trie/Pruning/TrieStore.cs @@ -8,12 +8,10 @@ using System.Threading; using System.Threading.Tasks; using Nethermind.Core; -using Nethermind.Core.Buffers; using Nethermind.Core.Collections; using Nethermind.Core.Crypto; using Nethermind.Core.Extensions; using Nethermind.Logging; -using Nethermind.Serialization.Rlp; namespace Nethermind.Trie.Pruning { @@ -614,7 +612,7 @@ private void Persist(BlockCommitSet commitSet, WriteFlags writeFlags = WriteFlag try { - _currentBatch ??= _keyValueStore.StartBatch(); + _currentBatch ??= _keyValueStore.StartBatch().ToSortedBatch(); if (_logger.IsDebug) _logger.Debug($"Persisting from root {commitSet.Root} in {commitSet.BlockNumber}"); Stopwatch stopwatch = Stopwatch.StartNew(); @@ -639,7 +637,7 @@ private void Persist(BlockCommitSet commitSet, WriteFlags writeFlags = WriteFlag private void Persist(TrieNode currentNode, long blockNumber, WriteFlags writeFlags = WriteFlags.None) { - _currentBatch ??= _keyValueStore.StartBatch(); + _currentBatch ??= _keyValueStore.StartBatch().ToSortedBatch(); if (currentNode is null) { throw new ArgumentNullException(nameof(currentNode)); From 4f886ada50d08c27acd5de51278d32e750e89a34 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 2 Oct 2023 11:06:53 +0200 Subject: [PATCH 46/50] Updating Fast Sync config files (#6149) Co-authored-by: LukaszRozmej --- src/Nethermind/Nethermind.Runner/configs/chiado.cfg | 4 ++-- src/Nethermind/Nethermind.Runner/configs/energyweb.cfg | 6 +++--- src/Nethermind/Nethermind.Runner/configs/exosama.cfg | 6 +++--- src/Nethermind/Nethermind.Runner/configs/gnosis.cfg | 4 ++-- src/Nethermind/Nethermind.Runner/configs/goerli.cfg | 4 ++-- src/Nethermind/Nethermind.Runner/configs/mainnet.cfg | 4 ++-- src/Nethermind/Nethermind.Runner/configs/sepolia.cfg | 4 ++-- src/Nethermind/Nethermind.Runner/configs/volta.cfg | 6 +++--- 8 files changed, 19 insertions(+), 19 deletions(-) diff --git a/src/Nethermind/Nethermind.Runner/configs/chiado.cfg b/src/Nethermind/Nethermind.Runner/configs/chiado.cfg index 05322221976..b71ef3a2d26 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": 6190000, - "PivotHash": "0x19afb16e00cde2cb8546b9f97b34cb80f1a841b15f4d4b2bba5c611cdcbcaca2", + "PivotNumber": 6310000, + "PivotHash": "0xdb60c645fa2f288eb91d889fd0b8819c6e37bee0f69d2d0763179e649b85c09a", "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 573479a70ce..171bfb07952 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": 26150000, - "PivotHash": "0x1c5fb2be00ab0e60ee511c8473fde1e090f9d41361d2458a58cb4b7f677c56a8", - "PivotTotalDifficulty": "8898383894982540819567245984340738729209295560", + "PivotNumber": 26270000, + "PivotHash": "0xf2dc4d73f0d6f790a7eeb4edd1a2f63b8a61edbe36998feef49065cc7cb8fdf6", + "PivotTotalDifficulty": "8939217779013053435182850937232550914583767819", "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 9456f06296b..d11fe9ad6a2 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": 5810000, - "PivotHash": "0x7411e4c1ff2241383f7218445676d90b3e593261f2beb4e17796bfd33d55daf9", - "PivotTotalDifficulty": "1977040551810652472722206469178573308214593289", + "PivotNumber": 5930000, + "PivotHash": "0x7c10e55a4c3c0fa900d0989879e389a2b86398a03b90e75a22ac5109a6e6b3b9", + "PivotTotalDifficulty": "2017874435841165088337811422070385493589073289", "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 d61cddc1227..b32ed29cdba 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": 30110000, - "PivotHash": "0x7b630b4abff0921c930b79a259934babd51c8460408c5ced0269d83589070972", + "PivotNumber": 30220000, + "PivotHash": "0x23a088814d684a96780ae26e640c3d4dee8e6c18699706597a5a6b704b43a20f", "PivotTotalDifficulty": "8626000110427538733349499292577475819600160930", "FastBlocks": true, "UseGethLimitsInFastBlocks": false, diff --git a/src/Nethermind/Nethermind.Runner/configs/goerli.cfg b/src/Nethermind/Nethermind.Runner/configs/goerli.cfg index 7e6dff6c8b0..43c3e7f38e6 100644 --- a/src/Nethermind/Nethermind.Runner/configs/goerli.cfg +++ b/src/Nethermind/Nethermind.Runner/configs/goerli.cfg @@ -15,8 +15,8 @@ "Sync": { "FastSync": true, "SnapSync": true, - "PivotNumber": 9720000, - "PivotHash": "0xc611dbb72cdcd5abcf9b25e56295242e5851efd4571cbf5c539c9084a69d92d4", + "PivotNumber": 9750000, + "PivotHash": "0xfd773896e9913d63b264ac23c5feb6e930b904ab944339523f792a147f63fbe9", "PivotTotalDifficulty": "10790000", "FastBlocks": true, "UseGethLimitsInFastBlocks": true, diff --git a/src/Nethermind/Nethermind.Runner/configs/mainnet.cfg b/src/Nethermind/Nethermind.Runner/configs/mainnet.cfg index 8106c644d60..fb2696cf3e5 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": 18200000, - "PivotHash": "0xb03f1070c7ed301fc72f310181192ad740f6ea09ff1376482d1e0f431b8a6a35", + "PivotNumber": 18250000, + "PivotHash": "0x031f40971a52212af60463cd5042138d6a4c4b7eb9b23765b731da057ea5a9e1", "PivotTotalDifficulty": "58750003716598352816469", "FastBlocks": true, "AncientBodiesBarrier": 11052984, diff --git a/src/Nethermind/Nethermind.Runner/configs/sepolia.cfg b/src/Nethermind/Nethermind.Runner/configs/sepolia.cfg index e72bdf8b231..2cf6a784a80 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": 4349000, - "PivotHash": "0x6fc5c49d62481c262d61e94c386f7a0dd6150f5d4384be926629267c5879d2ae", + "PivotNumber": 4397000, + "PivotHash": "0xa6320283e0831ad392e4b339eb0d8b5e99725a3b849ff40a678ebd70799b6e49", "PivotTotalDifficulty": "17000018015853232", "FastSyncCatchUpHeightDelta": "10000000000" }, diff --git a/src/Nethermind/Nethermind.Runner/configs/volta.cfg b/src/Nethermind/Nethermind.Runner/configs/volta.cfg index c69117dc784..1b8d36bc3b7 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": 24820000, - "PivotHash": "0xde7503303f0a803ce04503bf7cc1fcf9821f9628384a14a4babca2b5fe414125", - "PivotTotalDifficulty": "8445808346977692663160957756456487007974147358", + "PivotNumber": 24910000, + "PivotHash": "0xc2c29e9469c4c30b8fca15e43613d9522f3f2adc3b7b39a94ba94af4a80e03e2", + "PivotTotalDifficulty": "8476433760000577124872661471125346147004978933", "FastBlocks": true, "UseGethLimitsInFastBlocks": false, "FastSyncCatchUpHeightDelta": 10000000000 From 2c0972f9eef90085a1eade93d5e7a3163d4998af Mon Sep 17 00:00:00 2001 From: Lautaro Emanuel <31224949+emlautarom1@users.noreply.github.com> Date: Mon, 2 Oct 2023 12:31:40 -0300 Subject: [PATCH 47/50] Support configurable `ethstats` update interval (#6147) * Support configurable send intervals * Fix `EthStatsConfig` class * Use `TimeSpan` for intervals --- .../Configs/EthStatsConfig.cs | 1 + .../Nethermind.EthStats/EthStatsPlugin.cs | 12 +++--- .../Nethermind.EthStats/IEthStatsConfig.cs | 9 +++-- .../Integrations/EthStatsIntegration.cs | 39 +++++++++++-------- 4 files changed, 36 insertions(+), 25 deletions(-) diff --git a/src/Nethermind/Nethermind.EthStats/Configs/EthStatsConfig.cs b/src/Nethermind/Nethermind.EthStats/Configs/EthStatsConfig.cs index 6fe7dbae153..74c5429a757 100644 --- a/src/Nethermind/Nethermind.EthStats/Configs/EthStatsConfig.cs +++ b/src/Nethermind/Nethermind.EthStats/Configs/EthStatsConfig.cs @@ -10,5 +10,6 @@ public class EthStatsConfig : IEthStatsConfig public string? Name { get; set; } = "Nethermind"; public string? Secret { get; set; } = "secret"; public string? Contact { get; set; } = "hello@nethermind.io"; + public int SendInterval { get; set; } = 15; } } diff --git a/src/Nethermind/Nethermind.EthStats/EthStatsPlugin.cs b/src/Nethermind/Nethermind.EthStats/EthStatsPlugin.cs index 0ba666dc9ab..4a4b80459ef 100644 --- a/src/Nethermind/Nethermind.EthStats/EthStatsPlugin.cs +++ b/src/Nethermind/Nethermind.EthStats/EthStatsPlugin.cs @@ -1,6 +1,7 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using System; using System.Threading.Tasks; using Nethermind.Api; using Nethermind.Api.Extensions; @@ -64,7 +65,7 @@ public Task Init(INethermindApi nethermindApi) public async Task InitNetworkProtocol() { - var (getFromAPi, _) = _api.ForNetwork; + (IApiWithNetwork getFromAPi, _) = _api.ForNetwork; INetworkConfig networkConfig = _api.Config(); IInitConfig initConfig = _api.Config(); @@ -104,12 +105,13 @@ public async Task InitNetworkProtocol() _ethStatsConfig.Secret!, _ethStatsClient, sender, - getFromAPi.TxPool, - getFromAPi.BlockTree, - getFromAPi.PeerManager, - getFromAPi.GasPriceOracle, + getFromAPi.TxPool!, + getFromAPi.BlockTree!, + getFromAPi.PeerManager!, + getFromAPi.GasPriceOracle!, getFromAPi.EthSyncingInfo!, initConfig.IsMining, + TimeSpan.FromSeconds(_ethStatsConfig.SendInterval), getFromAPi.LogManager); await _ethStatsIntegration.InitAsync(); diff --git a/src/Nethermind/Nethermind.EthStats/IEthStatsConfig.cs b/src/Nethermind/Nethermind.EthStats/IEthStatsConfig.cs index aec88a48735..d7328d7bf7c 100644 --- a/src/Nethermind/Nethermind.EthStats/IEthStatsConfig.cs +++ b/src/Nethermind/Nethermind.EthStats/IEthStatsConfig.cs @@ -13,13 +13,16 @@ public interface IEthStatsConfig : IConfig [ConfigItem(Description = "EthStats server wss://hostname:port/api/", DefaultValue = "ws://localhost:3000/api")] string? Server { get; } - [ConfigItem(Description = "Node name displayed on the given ethstats server.", DefaultValue = "Nethermind")] + [ConfigItem(Description = "Node name displayed on the given EthStats server.", DefaultValue = "Nethermind")] string? Name { get; } - [ConfigItem(Description = "Password for publishing to a given ethstats server.", DefaultValue = "secret")] + [ConfigItem(Description = "Password for publishing to a given EthStats server.", DefaultValue = "secret")] string? Secret { get; } - [ConfigItem(Description = "Node owner contact details displayed on the ethstats page.", DefaultValue = "hello@nethermind.io")] + [ConfigItem(Description = "Node owner contact details displayed on the EthStats page.", DefaultValue = "hello@nethermind.io")] string? Contact { get; } + + [ConfigItem(Description = "Time in seconds between statistics updates", DefaultValue = "15")] + int SendInterval { get; } } } diff --git a/src/Nethermind/Nethermind.EthStats/Integrations/EthStatsIntegration.cs b/src/Nethermind/Nethermind.EthStats/Integrations/EthStatsIntegration.cs index 3c02c95b417..238d5772f0a 100644 --- a/src/Nethermind/Nethermind.EthStats/Integrations/EthStatsIntegration.cs +++ b/src/Nethermind/Nethermind.EthStats/Integrations/EthStatsIntegration.cs @@ -45,12 +45,13 @@ public class EthStatsIntegration : IEthStatsIntegration private readonly IGasPriceOracle _gasPriceOracle; private readonly IEthSyncingInfo _ethSyncingInfo; private readonly bool _isMining; + private readonly TimeSpan _sendStatsInterval; + private IWebsocketClient? _websocketClient; private bool _connected; private long _lastBlockProcessedTimestamp; private Timer? _timer; private const int ThrottlingThreshold = 250; - private const int SendStatsInterval = 1000; public EthStatsIntegration( string name, @@ -63,15 +64,16 @@ public EthStatsIntegration( string contact, bool canUpdateHistory, string secret, - IEthStatsClient? ethStatsClient, - IMessageSender? sender, - ITxPool? txPool, - IBlockTree? blockTree, - IPeerManager? peerManager, - IGasPriceOracle? gasPriceOracle, + IEthStatsClient ethStatsClient, + IMessageSender sender, + ITxPool txPool, + IBlockTree blockTree, + IPeerManager peerManager, + IGasPriceOracle gasPriceOracle, IEthSyncingInfo ethSyncingInfo, bool isMining, - ILogManager? logManager) + TimeSpan sendStatsInterval, + ILogManager logManager) { _name = name; _node = node; @@ -83,20 +85,23 @@ public EthStatsIntegration( _contact = contact; _canUpdateHistory = canUpdateHistory; _secret = secret; - _ethStatsClient = ethStatsClient ?? throw new ArgumentNullException(nameof(ethStatsClient)); - _sender = sender ?? throw new ArgumentNullException(nameof(sender)); - _txPool = txPool ?? throw new ArgumentNullException(nameof(txPool)); - _blockTree = blockTree ?? throw new ArgumentNullException(nameof(blockTree)); - _peerManager = peerManager ?? throw new ArgumentNullException(nameof(peerManager)); - _gasPriceOracle = gasPriceOracle ?? throw new ArgumentNullException(nameof(gasPriceOracle)); - _ethSyncingInfo = ethSyncingInfo ?? throw new ArgumentNullException(nameof(ethSyncingInfo)); + _ethStatsClient = ethStatsClient; + _sender = sender; + _txPool = txPool; + _blockTree = blockTree; + _peerManager = peerManager; + _gasPriceOracle = gasPriceOracle; + _ethSyncingInfo = ethSyncingInfo; _isMining = isMining; - _logger = logManager?.GetClassLogger() ?? throw new ArgumentNullException(nameof(logManager)); + _sendStatsInterval = sendStatsInterval > TimeSpan.Zero + ? sendStatsInterval + : throw new ArgumentOutOfRangeException(nameof(sendStatsInterval)); + _logger = logManager.GetClassLogger(); } public async Task InitAsync() { - _timer = new Timer { Interval = SendStatsInterval }; + _timer = new Timer { Interval = _sendStatsInterval.TotalMilliseconds }; _timer.Elapsed += TimerOnElapsed; _blockTree.NewHeadBlock += BlockTreeOnNewHeadBlock; _websocketClient = await _ethStatsClient.InitAsync(); From 0ed858dd4a3216d3bb7a266009910b4724719cc9 Mon Sep 17 00:00:00 2001 From: Amirul Ashraf Date: Tue, 3 Oct 2023 12:52:00 +0800 Subject: [PATCH 48/50] Perf/improve writebatch parallelism (#6151) * Add insert hint per batch * Improve writebatch parallelism * Make sure items is saved * Atomic replace * Reuse write batch * Change threshold * Remove batch sort * Whitespace --- .../Receipts/PersistentReceiptStorage.cs | 2 +- .../Nethermind.Core.Test/SortedBatchTests.cs | 60 -------- src/Nethermind/Nethermind.Core/SortedBatch.cs | 96 ------------- .../Nethermind.Db.Rocks/DbOnTheRocks.cs | 132 ++++++++++++------ .../Nethermind.Db.Test/DbOnTheRocksTests.cs | 18 +++ .../Nethermind.State.Test/StateTreeTests.cs | 2 +- .../Nethermind.Trie/Pruning/TrieStore.cs | 4 +- 7 files changed, 111 insertions(+), 203 deletions(-) delete mode 100644 src/Nethermind/Nethermind.Core.Test/SortedBatchTests.cs delete mode 100644 src/Nethermind/Nethermind.Core/SortedBatch.cs diff --git a/src/Nethermind/Nethermind.Blockchain/Receipts/PersistentReceiptStorage.cs b/src/Nethermind/Nethermind.Blockchain/Receipts/PersistentReceiptStorage.cs index 1d89f990927..24425624ead 100644 --- a/src/Nethermind/Nethermind.Blockchain/Receipts/PersistentReceiptStorage.cs +++ b/src/Nethermind/Nethermind.Blockchain/Receipts/PersistentReceiptStorage.cs @@ -342,7 +342,7 @@ public bool HasBlock(long blockNumber, Keccak blockHash) public void EnsureCanonical(Block block) { - using IBatch batch = _transactionDb.StartBatch().ToSortedBatch(); + using IBatch batch = _transactionDb.StartBatch(); long headNumber = _blockTree.FindBestSuggestedHeader()?.Number ?? 0; diff --git a/src/Nethermind/Nethermind.Core.Test/SortedBatchTests.cs b/src/Nethermind/Nethermind.Core.Test/SortedBatchTests.cs deleted file mode 100644 index 835ed0aab4e..00000000000 --- a/src/Nethermind/Nethermind.Core.Test/SortedBatchTests.cs +++ /dev/null @@ -1,60 +0,0 @@ -// SPDX-FileCopyrightText: 2023 Demerzel Solutions Limited -// SPDX-License-Identifier: LGPL-3.0-only - -using System; -using System.Collections.Generic; -using System.Linq; -using FluentAssertions; -using Nethermind.Core.Extensions; -using Nethermind.Core.Test.Builders; -using NUnit.Framework; - -namespace Nethermind.Core.Test; - -public class SortedBatchTests -{ - [Test] - public void Test_BatchWillSort() - { - TestBatch baseBatch = new TestBatch(); - - IBatch sortedBatch = baseBatch.ToSortedBatch(); - - IList expectedOrder = new List(); - for (int i = 0; i < 10; i++) - { - sortedBatch[TestItem.ValueKeccaks[i].ToByteArray()] = TestItem.ValueKeccaks[i].ToByteArray(); - expectedOrder.Add(TestItem.ValueKeccaks[i].ToByteArray()); - } - - baseBatch.DisposeCalled.Should().BeFalse(); - baseBatch.SettedValues.Count.Should().Be(0); - - sortedBatch.Dispose(); - - baseBatch.DisposeCalled.Should().BeTrue(); - expectedOrder = expectedOrder.Order(Bytes.Comparer).ToList(); - baseBatch.SettedValues.Should().BeEquivalentTo(expectedOrder); - } - - private class TestBatch : IBatch - { - public bool DisposeCalled { get; set; } - public List SettedValues { get; set; } = new(); - - public void Dispose() - { - DisposeCalled = true; - } - - public byte[]? Get(ReadOnlySpan key, ReadFlags flags = ReadFlags.None) - { - return null; - } - - public void Set(ReadOnlySpan key, byte[]? value, WriteFlags flags = WriteFlags.None) - { - SettedValues.Add(key.ToArray()); - } - } -} diff --git a/src/Nethermind/Nethermind.Core/SortedBatch.cs b/src/Nethermind/Nethermind.Core/SortedBatch.cs deleted file mode 100644 index 2f37127dc31..00000000000 --- a/src/Nethermind/Nethermind.Core/SortedBatch.cs +++ /dev/null @@ -1,96 +0,0 @@ -// SPDX-FileCopyrightText: 2023 Demerzel Solutions Limited -// SPDX-License-Identifier: LGPL-3.0-only - -using System; -using System.Collections.Concurrent; -using System.Linq; -using Nethermind.Core.Collections; -using Nethermind.Core.Extensions; - -namespace Nethermind.Core; - -/// -/// Rocksdb's skiplist memtable have a fast path when the keys are inserted in ascending order. Otherwise, its seems -/// to be limited to 1Mil writes per second. -/// TODO: FlatDB layout need different key type to match the DB ordering. -/// -public class SortedBatch : IBatch -{ - private const int InitialBatchSize = 300; - private static readonly int MaxCached = Environment.ProcessorCount; - - private static ConcurrentQueue> s_cache = new(); - - private readonly IBatch _baseBatch; - private WriteFlags _writeFlags = WriteFlags.None; - - private SpanDictionary _batchData = CreateOrGetFromCache(); - - public SortedBatch(IBatch dbOnTheRocks) - { - _baseBatch = dbOnTheRocks; - } - - public void Dispose() - { - SpanDictionary batchData = _batchData; - // Clear the _batchData reference so is null if Get is called. - _batchData = null!; - if (batchData.Count == 0) - { - // No data to write, skip empty batches - ReturnToCache(batchData); - _baseBatch.Dispose(); - return; - } - - // Sort the batch by key - foreach (var kv in batchData.OrderBy(i => i.Key, Bytes.Comparer)) - { - _baseBatch.Set(kv.Key, kv.Value, _writeFlags); - } - ReturnToCache(batchData); - - _baseBatch.Dispose(); - } - - public byte[]? Get(ReadOnlySpan key, ReadFlags flags = ReadFlags.None) - { - // Not checking _isDisposing here as for some reason, sometimes is is read after dispose - return _batchData?.TryGetValue(key, out byte[]? value) ?? false ? value : _baseBatch.Get(key); - } - - public void Set(ReadOnlySpan key, byte[]? value, WriteFlags flags = WriteFlags.None) - { - _batchData[key] = value; - - _writeFlags = flags; - } - - private static SpanDictionary CreateOrGetFromCache() - { - if (s_cache.TryDequeue(out SpanDictionary? batchData)) - { - return batchData; - } - - return new SpanDictionary(InitialBatchSize, Bytes.SpanEqualityComparer); - } - - private static void ReturnToCache(SpanDictionary batchData) - { - if (s_cache.Count >= MaxCached) return; - - batchData.Clear(); - batchData.TrimExcess(capacity: InitialBatchSize); - s_cache.Enqueue(batchData); - } -} - -public static class BatchExtensions -{ - public static SortedBatch ToSortedBatch(this IBatch batch) - { - return new SortedBatch(batch); - } -} diff --git a/src/Nethermind/Nethermind.Db.Rocks/DbOnTheRocks.cs b/src/Nethermind/Nethermind.Db.Rocks/DbOnTheRocks.cs index b54a8be7a35..e0fa2cc004f 100644 --- a/src/Nethermind/Nethermind.Db.Rocks/DbOnTheRocks.cs +++ b/src/Nethermind/Nethermind.Db.Rocks/DbOnTheRocks.cs @@ -370,12 +370,6 @@ protected virtual void BuildOptions(PerTableDbConfig dbConfig, Options opt int writeBufferNumber = (int)dbConfig.WriteBufferNumber; options.SetMaxWriteBufferNumber(writeBufferNumber); - // Memtable is slower to writes the bigger it gets, but small memtable means small l0 file size, which means - // higher write amp for l0->l1 compaction. This allows multiple memtable to go into one l0 file so that it is - // not too small so it helps with write amp when setting small write buffer. AFAIK that is its only use compared - // to just specifying large write buffer. Sadly, this setting can't dynamically change. - options.SetMinWriteBufferNumberToMerge(2); - lock (_dbsByPath) { _maxThisDbSize += (long)writeBufferSize * writeBufferNumber; @@ -401,21 +395,31 @@ protected virtual void BuildOptions(PerTableDbConfig dbConfig, Options opt // VERY important to reduce stalls. Allow L0->L1 compaction to happen with multiple thread. _rocksDbNative.rocksdb_options_set_max_subcompactions(options.Handle, (uint)Environment.ProcessorCount); - // options.SetLevelCompactionDynamicLevelBytes(true); // only switch on on empty DBs - WriteOptions = new WriteOptions(); - WriteOptions.SetSync(dbConfig - .WriteAheadLogSync); // potential fix for corruption on hard process termination, may cause performance degradation + if (dbConfig.CompactionReadAhead != null && dbConfig.CompactionReadAhead != 0) + { + options.SetCompactionReadaheadSize(dbConfig.CompactionReadAhead.Value); + } + + if (dbConfig.DisableCompression == true) + { + options.SetCompression(Compression.No); + } + + if (dbConfig.EnableDbStatistics) + { + options.EnableStatistics(); + } + options.SetStatsDumpPeriodSec(dbConfig.StatsDumpPeriodSec); - _noWalWrite = new WriteOptions(); - _noWalWrite.SetSync(dbConfig.WriteAheadLogSync); + WriteOptions = CreateWriteOptions(dbConfig); + + _noWalWrite = CreateWriteOptions(dbConfig); _noWalWrite.DisableWal(1); - _lowPriorityWriteOptions = new WriteOptions(); - _lowPriorityWriteOptions.SetSync(dbConfig.WriteAheadLogSync); + _lowPriorityWriteOptions = CreateWriteOptions(dbConfig); Native.Instance.rocksdb_writeoptions_set_low_pri(_lowPriorityWriteOptions.Handle, true); - _lowPriorityAndNoWalWrite = new WriteOptions(); - _lowPriorityAndNoWalWrite.SetSync(dbConfig.WriteAheadLogSync); + _lowPriorityAndNoWalWrite = CreateWriteOptions(dbConfig); _lowPriorityAndNoWalWrite.DisableWal(1); Native.Instance.rocksdb_writeoptions_set_low_pri(_lowPriorityAndNoWalWrite.Handle, true); @@ -430,22 +434,14 @@ protected virtual void BuildOptions(PerTableDbConfig dbConfig, Options opt _readAheadReadOptions.SetReadaheadSize(dbConfig.ReadAheadSize ?? (ulong)256.KiB()); _readAheadReadOptions.SetTailing(true); } + } - if (dbConfig.CompactionReadAhead != null && dbConfig.CompactionReadAhead != 0) - { - options.SetCompactionReadaheadSize(dbConfig.CompactionReadAhead.Value); - } - - if (dbConfig.DisableCompression == true) - { - options.SetCompression(Compression.No); - } - - if (dbConfig.EnableDbStatistics) - { - options.EnableStatistics(); - } - options.SetStatsDumpPeriodSec(dbConfig.StatsDumpPeriodSec); + private WriteOptions CreateWriteOptions(PerTableDbConfig dbConfig) + { + WriteOptions options = new(); + // potential fix for corruption on hard process termination, may cause performance degradation + options.SetSync(dbConfig.WriteAheadLogSync); + return options; } public byte[]? this[ReadOnlySpan key] @@ -789,14 +785,25 @@ public IBatch StartBatch() internal class RocksDbBatch : IBatch { private readonly DbOnTheRocks _dbOnTheRocks; - private readonly WriteBatch _rocksBatch; + private WriteBatch _rocksBatch; private WriteFlags _writeFlags = WriteFlags.None; private bool _isDisposed; + [ThreadStatic] + private static WriteBatch? _reusableWriteBatch; + + /// + /// Because of how rocksdb parallelize writes, a large write batch can stall other new concurrent writes, so + /// we writes the batch in smaller batches. This removes atomicity so its only turned on when NoWAL flag is on. + /// It does not work as well as just turning on unordered_write, but Snapshot and Iterator can still works. + /// + private const int MaxWritesOnNoWal = 128; + private int _writeCount; + public RocksDbBatch(DbOnTheRocks dbOnTheRocks) { _dbOnTheRocks = dbOnTheRocks; - _rocksBatch = new WriteBatch(); + _rocksBatch = CreateWriteBatch(); if (_dbOnTheRocks._isDisposing) { @@ -804,6 +811,28 @@ public RocksDbBatch(DbOnTheRocks dbOnTheRocks) } } + private static WriteBatch CreateWriteBatch() + { + if (_reusableWriteBatch == null) return new WriteBatch(); + + WriteBatch batch = _reusableWriteBatch; + _reusableWriteBatch = null; + return batch; + } + + private static void ReturnWriteBatch(WriteBatch batch) + { + Native.Instance.rocksdb_writebatch_data(batch.Handle, out UIntPtr size); + if (size > (uint)16.KiB() || _reusableWriteBatch != null) + { + batch.Dispose(); + return; + } + + batch.Clear(); + _reusableWriteBatch = batch; + } + public void Dispose() { if (_dbOnTheRocks._isDisposed) @@ -821,7 +850,7 @@ public void Dispose() { _dbOnTheRocks._db.Write(_rocksBatch, _dbOnTheRocks.WriteFlagsToWriteOptions(_writeFlags)); _dbOnTheRocks._currentBatches.TryRemove(this); - _rocksBatch.Dispose(); + ReturnWriteBatch(_rocksBatch); } catch (RocksDbSharpException e) { @@ -857,6 +886,8 @@ public void Set(ReadOnlySpan key, byte[]? value, ColumnFamilyHandle? cf = _rocksBatch.Put(key, value, cf); _writeFlags = flags; + + if ((flags & WriteFlags.DisableWAL) != 0) FlushOnTooManyWrites(); } public void Set(ReadOnlySpan key, byte[]? value, WriteFlags flags = WriteFlags.None) @@ -868,6 +899,26 @@ public void Set(ReadOnlySpan key, byte[]? value, WriteFlags flags = WriteF _rocksBatch.Put(key, value); _writeFlags = flags; + + if ((flags & WriteFlags.DisableWAL) != 0) FlushOnTooManyWrites(); + } + + private void FlushOnTooManyWrites() + { + if (Interlocked.Increment(ref _writeCount) % MaxWritesOnNoWal != 0) return; + + WriteBatch currentBatch = Interlocked.Exchange(ref _rocksBatch, CreateWriteBatch()); + + try + { + _dbOnTheRocks._db.Write(currentBatch, _dbOnTheRocks.WriteFlagsToWriteOptions(_writeFlags)); + ReturnWriteBatch(currentBatch); + } + catch (RocksDbSharpException e) + { + _dbOnTheRocks.CreateMarkerIfCorrupt(e); + throw; + } } } @@ -1136,18 +1187,13 @@ private IDictionary GetHeavyWriteOptions(ulong l0FileNumTarget) // but no io, only cpu. // bufferSize*maxBufferNumber = 128MB, which is the max memory used, which tend to be the case as its now // stalled by compaction instead of flush. - // The skiplist (memtable) have a branching factor of 4, so I assume it slows down a little as num of record - // grows by 4x. So we are looking at 1,4,16,64,256,1k,4k,16k,64k and so on num of keys. Assuming average size of - // 120 bytes per key for state db, we are targeting between 4k to 16k of keys per memtable. - // A small memtable however, have the drawback of making l0 files smaller. Causing more compaction overhead. - ulong bufferSize = (ulong)4.MiB(); - ulong writeBufferToMerge = 2; - ulong maxBufferNumber = 16 * writeBufferToMerge; + ulong bufferSize = (ulong)16.MiB(); + ulong maxBufferNumber = 8; // Guide recommend to have l0 and l1 to be the same size. They have to be compacted together so if l1 is larger, // the extra size in l1 is basically extra rewrites. If l0 is larger... then I don't know why not. Even so, it seems to // always get triggered when l0 size exceed max_bytes_for_level_base even if file num is less than l0FileNumTarget. - ulong l1SizeTarget = l0FileNumTarget * bufferSize * writeBufferToMerge; + ulong l1SizeTarget = l0FileNumTarget * bufferSize; return new Dictionary() { @@ -1177,7 +1223,7 @@ private IDictionary GetDisableCompactionOptions() // the memtable a little bit. So if you are not write limited, you'll get memtable limited instead. // This does increase the total memory buffer size, but counterintuitively, this reduces overall memory usage // as it ran out of bloom filter cache so it need to do actual IO. - heavyWriteOption["write_buffer_size"] = 16.MiB().ToString(); + heavyWriteOption["write_buffer_size"] = 64.MiB().ToString(); return heavyWriteOption; } diff --git a/src/Nethermind/Nethermind.Db.Test/DbOnTheRocksTests.cs b/src/Nethermind/Nethermind.Db.Test/DbOnTheRocksTests.cs index b29e0304284..770256d056d 100644 --- a/src/Nethermind/Nethermind.Db.Test/DbOnTheRocksTests.cs +++ b/src/Nethermind/Nethermind.Db.Test/DbOnTheRocksTests.cs @@ -235,6 +235,24 @@ public void Smoke_test() Assert.That(_db[new byte[] { 2, 3, 4 }], Is.EqualTo(new byte[] { 5, 6, 7 })); } + [Test] + public void Smoke_test_large_writes_with_nowal() + { + IBatch batch = _db.StartBatch(); + + for (int i = 0; i < 1000; i++) + { + batch.Set(i.ToBigEndianByteArray(), i.ToBigEndianByteArray(), WriteFlags.DisableWAL); + } + + batch.Dispose(); + + for (int i = 0; i < 1000; i++) + { + _db[i.ToBigEndianByteArray()].Should().BeEquivalentTo(i.ToBigEndianByteArray()); + } + } + [Test] public void Smoke_test_readahead() { diff --git a/src/Nethermind/Nethermind.State.Test/StateTreeTests.cs b/src/Nethermind/Nethermind.State.Test/StateTreeTests.cs index dd3db842bed..b0f9662e558 100644 --- a/src/Nethermind/Nethermind.State.Test/StateTreeTests.cs +++ b/src/Nethermind/Nethermind.State.Test/StateTreeTests.cs @@ -62,7 +62,7 @@ public void Minimal_writes_when_setting_on_empty_scenario_2() tree.Set(new Keccak("eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeb1eeeeeb0"), _account0); tree.Set(new Keccak("eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeb1eeeeeb1"), _account0); tree.Commit(0); - Assert.That(db.WritesCount, Is.EqualTo(6), "writes"); // extension, branch, leaf, extension, branch, 2x same leaf + Assert.That(db.WritesCount, Is.EqualTo(7), "writes"); // extension, branch, leaf, extension, branch, 2x same leaf Assert.That(Trie.Metrics.TreeNodeHashCalculations, Is.EqualTo(7), "hashes"); Assert.That(Trie.Metrics.TreeNodeRlpEncodings, Is.EqualTo(7), "encodings"); } diff --git a/src/Nethermind/Nethermind.Trie/Pruning/TrieStore.cs b/src/Nethermind/Nethermind.Trie/Pruning/TrieStore.cs index 64b13468f7b..19d134e63c7 100644 --- a/src/Nethermind/Nethermind.Trie/Pruning/TrieStore.cs +++ b/src/Nethermind/Nethermind.Trie/Pruning/TrieStore.cs @@ -612,7 +612,7 @@ private void Persist(BlockCommitSet commitSet, WriteFlags writeFlags = WriteFlag try { - _currentBatch ??= _keyValueStore.StartBatch().ToSortedBatch(); + _currentBatch ??= _keyValueStore.StartBatch(); if (_logger.IsDebug) _logger.Debug($"Persisting from root {commitSet.Root} in {commitSet.BlockNumber}"); Stopwatch stopwatch = Stopwatch.StartNew(); @@ -637,7 +637,7 @@ private void Persist(BlockCommitSet commitSet, WriteFlags writeFlags = WriteFlag private void Persist(TrieNode currentNode, long blockNumber, WriteFlags writeFlags = WriteFlags.None) { - _currentBatch ??= _keyValueStore.StartBatch().ToSortedBatch(); + _currentBatch ??= _keyValueStore.StartBatch(); if (currentNode is null) { throw new ArgumentNullException(nameof(currentNode)); From f7838a308bab7758f1470585fb56592066c57722 Mon Sep 17 00:00:00 2001 From: Lautaro Emanuel <31224949+emlautarom1@users.noreply.github.com> Date: Tue, 3 Oct 2023 10:55:39 -0300 Subject: [PATCH 49/50] Properly handle duplicates in `accessList` (#6145) * Add storage keys duplicates tests * Make Builder return `this` * Add `AccessListTests` * Preserve original order/duplicates when `accessList` is not normalized * Document duplicates in access list * Throw on invalid `accessList` - Should not happen during runtime - Added to prevent invalid states * Code cleanup * Rename tests * Formatting * Refactor `AccessList` - Replace `List` with list of specific variants - Add `AsDictionary` API - Only construct through `Builder` * Fix `TxValidatorTests` - Use `AccessList.Empty()` * Use new Builder * Use `Builder` instead of explicit dictionary * Use `AsDictionary` * Fix `AccessListCost` - Use explicit variants through switch * Use `AsDictionary` * Use new `Builder` * Fix `FromAccessList` and `ToAccessList` - Use new builder - Use `AccessListItem` variants * Use new `Builder` * Cleanup `Eip2930Tests` - Use new `Builder` - Remove impossible case (null storage keys) * Formatting * Use new `Builder` * Use new `Builder` * Fix `AccessListDecoder` - Use new `Builder` - Remove `IsNormalized` branches - Use variants for `AccessList` elements * Formatting * Fix `Ethereum` solution - Use new `Builder` * Update test case names * Add more `AccessList` tests * Add `AsEnumerable` * Remove `AsDictionary` * Simplify `FromAccessList` using `AccessList.AsEnumerable` * Use `AsEnumerable` instead of `Raw` * Simplify `AccessListDecoder` - Use `AccessList.AsEnumerable` - Inline methods - Remove unused struct * Remove unused code * Go back to internal `List` - Since it's never exposed there is no point in adding extra wrapper classes. * Formatting * Fix `JsonToEthereumTest` * Simplify even more by implementing IEnumerable on access list. Optimize with struct enumerables - no heap allocations. * more struct usage * whitespace * fix struct equality * Remove known not-null annotations * Add 'Single_address_with_no_storage' test * Rollback nullable removal - Used in JSON deserialization --------- Co-authored-by: lukasz.rozmej --- .../Ethereum.Test.Base/JsonToEthereumTest.cs | 8 +- .../Validators/TxValidatorTests.cs | 8 +- .../Builders/AccessListBuilder.cs | 4 +- .../Eip2930/AccessListTests.cs | 200 ++++++++++++++++++ .../Encoding/AccessListDecoderTests.cs | 121 ++++++----- .../Encoding/TxDecoderTests.cs | 47 +++- .../Collections/EnuberableExtensions.cs | 3 + .../Nethermind.Core/Eip2930/AccessList.cs | 113 ++++++++-- .../Eip2930/AccessListBuilder.cs | 62 ------ .../IntrinsicGasCalculatorTests.cs | 4 +- .../Tracing/AccessTxTracerTests.cs | 17 +- .../TransactionProcessorTests.cs | 4 +- src/Nethermind/Nethermind.Evm/EvmState.cs | 4 +- .../Nethermind.Evm/IntrinsicGasCalculator.cs | 36 +--- .../Nethermind.Evm/Tracing/AccessTxTracer.cs | 12 +- .../Data/AccessListItemForRpcTests.cs | 115 ++++++++++ .../Data/Eip2930Tests.cs | 64 ++---- .../Data/AccessListForRpc.cs | 7 +- .../Data/AccessListItemForRpc.cs | 33 +-- .../Data/TransactionForRpc.cs | 3 +- .../Eth/EthRpcModule.TransactionExecutor.cs | 6 +- .../Eip2930/AccessListDecoder.cs | 174 +++------------ 22 files changed, 639 insertions(+), 406 deletions(-) create mode 100644 src/Nethermind/Nethermind.Core.Test/Eip2930/AccessListTests.cs delete mode 100644 src/Nethermind/Nethermind.Core/Eip2930/AccessListBuilder.cs create mode 100644 src/Nethermind/Nethermind.JsonRpc.Test/Data/AccessListItemForRpcTests.cs diff --git a/src/Nethermind/Ethereum.Test.Base/JsonToEthereumTest.cs b/src/Nethermind/Ethereum.Test.Base/JsonToEthereumTest.cs index 0d35a806141..1e744eb6f8e 100644 --- a/src/Nethermind/Ethereum.Test.Base/JsonToEthereumTest.cs +++ b/src/Nethermind/Ethereum.Test.Base/JsonToEthereumTest.cs @@ -136,13 +136,13 @@ public static Transaction Convert(PostStateJson postStateJson, TransactionJson t transaction.Signature = new Signature(1, 1, 27); transaction.Hash = transaction.CalculateHash(); - AccessListBuilder builder = new(); + AccessList.Builder builder = new(); ProcessAccessList(transactionJson.AccessLists is not null ? transactionJson.AccessLists[postStateJson.Indexes.Data] : transactionJson.AccessList, builder); - transaction.AccessList = builder.ToAccessList(); + transaction.AccessList = builder.Build(); - if (transaction.AccessList.Data.Count != 0) + if (transaction.AccessList.AsEnumerable().Count() != 0) transaction.Type = TxType.AccessList; else transaction.AccessList = null; @@ -153,7 +153,7 @@ public static Transaction Convert(PostStateJson postStateJson, TransactionJson t return transaction; } - private static void ProcessAccessList(AccessListItemJson[]? accessList, AccessListBuilder builder) + private static void ProcessAccessList(AccessListItemJson[]? accessList, AccessList.Builder builder) { foreach (AccessListItemJson accessListItemJson in accessList ?? Array.Empty()) { diff --git a/src/Nethermind/Nethermind.Blockchain.Test/Validators/TxValidatorTests.cs b/src/Nethermind/Nethermind.Blockchain.Test/Validators/TxValidatorTests.cs index 3748d32c837..e952d079701 100644 --- a/src/Nethermind/Nethermind.Blockchain.Test/Validators/TxValidatorTests.cs +++ b/src/Nethermind/Nethermind.Blockchain.Test/Validators/TxValidatorTests.cs @@ -154,7 +154,7 @@ public bool Before_eip_2930_has_to_be_legacy_tx(TxType txType, bool eip2930) .WithType(txType > TxType.AccessList ? TxType.Legacy : txType) .WithChainId(TestBlockchainIds.ChainId) .WithAccessList(txType == TxType.AccessList - ? new AccessList(new Dictionary>()) + ? AccessList.Empty() : null) .WithSignature(signature).TestObject; @@ -185,7 +185,7 @@ public bool Before_eip_1559_has_to_be_legacy_or_access_list_tx(TxType txType, bo .WithMaxPriorityFeePerGas(txType == TxType.EIP1559 ? 10.GWei() : 5.GWei()) .WithMaxFeePerGas(txType == TxType.EIP1559 ? 10.GWei() : 5.GWei()) .WithAccessList(txType == TxType.AccessList || txType == TxType.EIP1559 - ? new AccessList(new Dictionary>()) + ? AccessList.Empty() : null) .WithSignature(signature).TestObject; @@ -210,7 +210,7 @@ public bool Chain_Id_required_for_non_legacy_transactions_after_Berlin(TxType tx Transaction tx = Build.A.Transaction .WithType(txType > TxType.AccessList ? TxType.Legacy : txType) .WithAccessList(txType == TxType.AccessList - ? new AccessList(new Dictionary>()) + ? AccessList.Empty() : null) .WithSignature(signature).TestObject; @@ -240,7 +240,7 @@ public bool MaxFeePerGas_is_required_to_be_greater_than_MaxPriorityFeePerGas(TxT .WithMaxPriorityFeePerGas((UInt256)maxPriorityFeePerGas) .WithMaxFeePerGas((UInt256)maxFeePerGas) .WithAccessList(txType == TxType.AccessList - ? new AccessList(new Dictionary>()) + ? AccessList.Empty() : null) .WithChainId(TestBlockchainIds.ChainId) .WithSignature(signature).TestObject; diff --git a/src/Nethermind/Nethermind.Core.Test/Builders/AccessListBuilder.cs b/src/Nethermind/Nethermind.Core.Test/Builders/AccessListBuilder.cs index 1bfc8b34b9c..2076ff7d95d 100644 --- a/src/Nethermind/Nethermind.Core.Test/Builders/AccessListBuilder.cs +++ b/src/Nethermind/Nethermind.Core.Test/Builders/AccessListBuilder.cs @@ -9,12 +9,12 @@ public class TestAccessListBuilder : BuilderBase { public TestAccessListBuilder() { - AccessListBuilder accessListBuilder = new(); + AccessList.Builder accessListBuilder = new(); foreach (Address address in TestItem.Addresses.Take(5)) { accessListBuilder.AddAddress(address); } - TestObjectInternal = accessListBuilder.ToAccessList(); + TestObjectInternal = accessListBuilder.Build(); } } diff --git a/src/Nethermind/Nethermind.Core.Test/Eip2930/AccessListTests.cs b/src/Nethermind/Nethermind.Core.Test/Eip2930/AccessListTests.cs new file mode 100644 index 00000000000..c6978eda415 --- /dev/null +++ b/src/Nethermind/Nethermind.Core.Test/Eip2930/AccessListTests.cs @@ -0,0 +1,200 @@ +// SPDX-FileCopyrightText: 2023 Demerzel Solutions Limited +// SPDX-License-Identifier: LGPL-3.0-only + +using System; +using System.Collections.Generic; +using FluentAssertions; +using Nethermind.Core.Eip2930; +using Nethermind.Core.Test.Builders; +using Nethermind.Int256; +using NUnit.Framework; + +namespace Nethermind.Core.Test.Eip2930; + +public class AccessListTests +{ + [Test] + public void Single_address_with_multiple_storage_keys() + { + Address address = TestItem.AddressA; + UInt256 storageKey1 = (UInt256)1; + UInt256 storageKey2 = (UInt256)2; + UInt256 storageKey3 = (UInt256)3; + + AccessList accessList = new AccessList.Builder() + .AddAddress(address) + .AddStorage(storageKey1) + .AddStorage(storageKey2) + .AddStorage(storageKey3) + .Build(); + + IEnumerable<(Address, IEnumerable)> expected = new List<(Address, IEnumerable)> + { + (address, new[] { storageKey1, storageKey2, storageKey3 }) + }; + + accessList.Should().BeEquivalentTo(expected); + } + + [Test] + public void Single_address_with_duplicated_storage_keys() + { + Address address = TestItem.AddressA; + UInt256 storageKey1 = (UInt256)1; + UInt256 storageKey2 = (UInt256)2; + UInt256 storageKey3 = (UInt256)3; + + AccessList accessList = new AccessList.Builder() + .AddAddress(address) + .AddStorage(storageKey1) + .AddStorage(storageKey2) + .AddStorage(storageKey3) + .AddStorage(storageKey1) + .Build(); + + IEnumerable<(Address, IEnumerable)> expected = new List<(Address, IEnumerable)> + { + (address, new[] { storageKey1, storageKey2, storageKey3, storageKey1 }) + }; + + accessList.Should().BeEquivalentTo(expected); + } + + [Test] + public void Duplicated_address_with_multiple_storage_keys() + { + Address address = TestItem.AddressA; + UInt256 storageKey1 = (UInt256)1; + UInt256 storageKey2 = (UInt256)2; + UInt256 storageKey3 = (UInt256)3; + + AccessList accessList = new AccessList.Builder() + .AddAddress(address) + .AddStorage(storageKey1) + .AddStorage(storageKey2) + .AddAddress(address) + .AddStorage(storageKey3) + .Build(); + + IEnumerable<(Address, IEnumerable)> expected = new List<(Address, IEnumerable)> + { + (address, new[] { storageKey1, storageKey2 }), + (address, new[] { storageKey3 }) + }; + + accessList.Should().BeEquivalentTo(expected); + } + + [Test] + public void Duplicated_address_with_duplicated_storage_keys() + { + Address address = TestItem.AddressA; + UInt256 storageKey1 = (UInt256)1; + UInt256 storageKey2 = (UInt256)2; + UInt256 storageKey3 = (UInt256)3; + + AccessList accessList = new AccessList.Builder() + .AddAddress(address) + .AddStorage(storageKey1) + .AddStorage(storageKey2) + .AddAddress(address) + .AddStorage(storageKey1) + .AddStorage(storageKey3) + .Build(); + + IEnumerable<(Address, IEnumerable)> expected = new List<(Address, IEnumerable)> + { + (address, new[] { storageKey1, storageKey2 }), + (address, new[] { storageKey1, storageKey3 }) + }; + + accessList.Should().BeEquivalentTo(expected); + } + + [Test] + public void Multiple_addresses_no_storage() + { + Address address1 = TestItem.AddressA; + Address address2 = TestItem.AddressB; + + AccessList accessList = new AccessList.Builder() + .AddAddress(address1) + .AddAddress(address2) + .Build(); + + IEnumerable<(Address, IEnumerable)> expected = new List<(Address, IEnumerable)> + { + (address1, new UInt256[] { }), + (address2, new UInt256[] { }) + }; + + accessList.Should().BeEquivalentTo(expected); + } + + [Test] + public void Multiple_addresses_with_storage() + { + Address address1 = TestItem.AddressA; + Address address2 = TestItem.AddressB; + UInt256 storageKey1 = (UInt256)1; + UInt256 storageKey2 = (UInt256)2; + UInt256 storageKey3 = (UInt256)3; + + AccessList accessList = new AccessList.Builder() + .AddAddress(address1) + .AddStorage(storageKey1) + .AddStorage(storageKey2) + .AddAddress(address2) + .AddStorage(storageKey3) + .Build(); + + IEnumerable<(Address, IEnumerable)> expected = new List<(Address, IEnumerable)> + { + (address1, new[] { storageKey1, storageKey2 }), + (address2, new[] { storageKey3 }) + }; + + accessList.Should().BeEquivalentTo(expected); + } + + [Test] + public void Multiple_duplicated_addresses_with_storage() + { + Address address1 = TestItem.AddressA; + Address address2 = TestItem.AddressB; + UInt256 storageKey1 = (UInt256)1; + UInt256 storageKey2 = (UInt256)2; + UInt256 storageKey3 = (UInt256)3; + + AccessList accessList = new AccessList.Builder() + .AddAddress(address1) + .AddStorage(storageKey1) + .AddStorage(storageKey2) + .AddAddress(address2) + .AddStorage(storageKey3) + .AddAddress(address1) + .AddStorage(storageKey1) + .AddAddress(address2) + .Build(); + + IEnumerable<(Address, IEnumerable)> expected = new List<(Address, IEnumerable)> + { + (address1, new[] { storageKey1, storageKey2 }), + (address2, new[] { storageKey3 }), + (address1, new[] { storageKey1 }), + (address2, new UInt256[] { }), + }; + + accessList.Should().BeEquivalentTo(expected); + } + + [Test] + public void Invalid_storage_when_no_previous_address() + { + Assert.Throws(() => + { + AccessList.Builder _ = new AccessList.Builder() + .AddStorage(UInt256.Zero); + }); + } +} diff --git a/src/Nethermind/Nethermind.Core.Test/Encoding/AccessListDecoderTests.cs b/src/Nethermind/Nethermind.Core.Test/Encoding/AccessListDecoderTests.cs index 5cd844d9733..76579f93489 100644 --- a/src/Nethermind/Nethermind.Core.Test/Encoding/AccessListDecoderTests.cs +++ b/src/Nethermind/Nethermind.Core.Test/Encoding/AccessListDecoderTests.cs @@ -5,7 +5,6 @@ using FluentAssertions; using Nethermind.Core.Eip2930; using Nethermind.Core.Test.Builders; -using Nethermind.Int256; using Nethermind.Serialization.Rlp; using Nethermind.Serialization.Rlp.Eip2930; using NUnit.Framework; @@ -17,71 +16,77 @@ public class AccessListDecoderTests { private readonly AccessListDecoder _decoder = new(); - public static IEnumerable<(string, AccessList)> TestCaseSource() + public static IEnumerable<(string, AccessList?)> TestCaseSource() { - yield return ("null", null!); + yield return ( + "null", + null); - HashSet indexes = new(); - Dictionary> data = new(); - // yield return ("empty", new AccessList(data)); <-- null and empty are equivalent here - // - indexes = new HashSet(); - data = new Dictionary>(); - data.Add(TestItem.AddressA, indexes); - yield return ("no storage", new AccessList(data)); + // yield return ("empty", AccessList.Empty()); <-- null and empty are equivalent here - indexes = new HashSet(); - data = new Dictionary>(); - data.Add(TestItem.AddressA, indexes); - data.Add(TestItem.AddressB, indexes); - yield return ("no storage 2", new AccessList(data)); + yield return ( + "no storage", + new AccessList.Builder() + .AddAddress(TestItem.AddressA) + .Build()); - indexes = new HashSet(); - data = new Dictionary>(); - data.Add(TestItem.AddressA, indexes); - indexes.Add(1); - yield return ("1-1", new AccessList(data)); + yield return ( + "no storage 2", + new AccessList.Builder() + .AddAddress(TestItem.AddressA) + .AddAddress(TestItem.AddressB) + .Build()); - indexes = new HashSet(); - data = new Dictionary>(); - data.Add(TestItem.AddressA, indexes); - indexes.Add(1); - indexes.Add(2); - yield return ("1-2", new AccessList(data)); + yield return ( + "1-1", + new AccessList.Builder() + .AddAddress(TestItem.AddressA) + .AddStorage(1) + .Build()); - indexes = new HashSet(); - data = new Dictionary>(); - indexes.Add(1); - indexes.Add(2); - data.Add(TestItem.AddressA, indexes); - data.Add(TestItem.AddressB, indexes); - yield return ("2-2", new AccessList(data)); + yield return ( + "1-2", + new AccessList.Builder() + .AddAddress(TestItem.AddressA) + .AddStorage(1) + .AddStorage(2) + .Build()); - indexes = new HashSet(); - var indexes2 = new HashSet(); - data = new Dictionary>(); - indexes.Add(1); - indexes2.Add(2); - data.Add(TestItem.AddressA, indexes); - data.Add(TestItem.AddressB, indexes2); - AccessList accessList = new(data, - new Queue(new List { TestItem.AddressA, (UInt256)1, TestItem.AddressB, (UInt256)2 })); - yield return ("with order queue", accessList); + yield return ( + "2-1", + new AccessList.Builder() + .AddAddress(TestItem.AddressA) + .AddStorage(1) + .AddAddress(TestItem.AddressB) + .AddStorage(2) + .Build()); - indexes = new HashSet(); - indexes2 = new HashSet(); - data = new Dictionary>(); - indexes.Add(1); - indexes2.Add(2); - data.Add(TestItem.AddressA, indexes); - data.Add(TestItem.AddressB, indexes2); - accessList = new AccessList(data, - new Queue(new List { TestItem.AddressA, (UInt256)1, (UInt256)1, TestItem.AddressB, (UInt256)2, TestItem.AddressB, (UInt256)2 })); - yield return ("with order queue and duplicates", accessList); + yield return ( + "2-2", + new AccessList.Builder() + .AddAddress(TestItem.AddressA) + .AddStorage(1) + .AddStorage(2) + .AddAddress(TestItem.AddressB) + .AddStorage(1) + .AddStorage(2) + .Build()); + + yield return ( + "with duplicates", + new AccessList.Builder() + .AddAddress(TestItem.AddressA) + .AddStorage(1) + .AddStorage(1) + .AddAddress(TestItem.AddressB) + .AddStorage(2) + .AddAddress(TestItem.AddressB) + .AddStorage(2) + .Build()); } [TestCaseSource(nameof(TestCaseSource))] - public void Roundtrip((string TestName, AccessList AccessList) testCase) + public void Roundtrip((string TestName, AccessList? AccessList) testCase) { RlpStream rlpStream = new(10000); _decoder.Encode(rlpStream, testCase.AccessList); @@ -93,12 +98,12 @@ public void Roundtrip((string TestName, AccessList AccessList) testCase) } else { - decoded!.Data.Should().BeEquivalentTo(testCase.AccessList.Data, testCase.TestName); + decoded.Should().BeEquivalentTo(testCase.AccessList, testCase.TestName); } } [TestCaseSource(nameof(TestCaseSource))] - public void Roundtrip_value((string TestName, AccessList AccessList) testCase) + public void Roundtrip_value((string TestName, AccessList? AccessList) testCase) { RlpStream rlpStream = new(10000); _decoder.Encode(rlpStream, testCase.AccessList); @@ -111,7 +116,7 @@ public void Roundtrip_value((string TestName, AccessList AccessList) testCase) } else { - decoded!.Data.Should().BeEquivalentTo(testCase.AccessList.Data, testCase.TestName); + decoded.Should().BeEquivalentTo(testCase.AccessList, testCase.TestName); } } diff --git a/src/Nethermind/Nethermind.Core.Test/Encoding/TxDecoderTests.cs b/src/Nethermind/Nethermind.Core.Test/Encoding/TxDecoderTests.cs index cfb72973507..09f7395c85c 100644 --- a/src/Nethermind/Nethermind.Core.Test/Encoding/TxDecoderTests.cs +++ b/src/Nethermind/Nethermind.Core.Test/Encoding/TxDecoderTests.cs @@ -33,11 +33,10 @@ public class TxDecoderTests .WithType(TxType.AccessList) .WithChainId(TestBlockchainIds.ChainId) .WithAccessList( - new AccessList( - new Dictionary> - { - { Address.Zero, new HashSet { (UInt256)1 } } - }, new Queue(new List { Address.Zero, (UInt256)1 }))) + new AccessList.Builder() + .AddAddress(Address.Zero) + .AddStorage(1) + .Build()) .SignedAndResolved(), "access list"); yield return (Build.A.Transaction .WithData(new byte[] { 1, 2, 3 }) @@ -45,11 +44,10 @@ public class TxDecoderTests .WithMaxFeePerGas(30) .WithChainId(TestBlockchainIds.ChainId) .WithAccessList( - new AccessList( - new Dictionary> - { - { Address.Zero, new HashSet { (UInt256)1 } } - }, new Queue(new List { Address.Zero, (UInt256)1 }))) + new AccessList.Builder() + .AddAddress(Address.Zero) + .AddStorage(1) + .Build()) .SignedAndResolved(), "EIP1559 - access list"); yield return (Build.A.Transaction .WithType(TxType.EIP1559) @@ -244,6 +242,35 @@ public void Rlp_encode_should_return_the_same_as_rlp_stream_encoding( Assert.That(rlpStreamResult.Bytes, Is.EqualTo(rlpResult.Bytes)); } + [Test] + public void Duplicate_storage_keys_result_in_different_hashes() + { + Transaction noDuplicates = Build.A.Transaction + .WithType(TxType.EIP1559) + .WithChainId(TestBlockchainIds.ChainId) + .WithAccessList( + new AccessList.Builder() + .AddAddress(Address.Zero) + .AddStorage(1) + .Build()) + .SignedAndResolved() + .TestObject; + + Transaction duplicates = Build.A.Transaction + .WithType(TxType.EIP1559) + .WithChainId(TestBlockchainIds.ChainId) + .WithAccessList( + new AccessList.Builder() + .AddAddress(Address.Zero) + .AddStorage(1) + .AddStorage(1) + .Build()) + .SignedAndResolved() + .TestObject; + + duplicates.CalculateHash().Should().NotBe(noDuplicates.CalculateHash()); + } + public static IEnumerable<(string, Keccak)> SkipTypedWrappingTestCases() { yield return diff --git a/src/Nethermind/Nethermind.Core/Collections/EnuberableExtensions.cs b/src/Nethermind/Nethermind.Core/Collections/EnuberableExtensions.cs index f9f1058b60a..117e202d8a5 100644 --- a/src/Nethermind/Nethermind.Core/Collections/EnuberableExtensions.cs +++ b/src/Nethermind/Nethermind.Core/Collections/EnuberableExtensions.cs @@ -13,4 +13,7 @@ public static void ForEach(this IEnumerable list, Action action) { list.ToList().ForEach(action); } + + public static bool NullableSequenceEqual(this IEnumerable? first, IEnumerable? second) => + first is not null ? second is not null && first.SequenceEqual(second) : second is null; } diff --git a/src/Nethermind/Nethermind.Core/Eip2930/AccessList.cs b/src/Nethermind/Nethermind.Core/Eip2930/AccessList.cs index ab081f810cd..abe0233978b 100644 --- a/src/Nethermind/Nethermind.Core/Eip2930/AccessList.cs +++ b/src/Nethermind/Nethermind.Core/Eip2930/AccessList.cs @@ -1,30 +1,113 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using System; +using System.Collections; using System.Collections.Generic; using Nethermind.Int256; -namespace Nethermind.Core.Eip2930 +namespace Nethermind.Core.Eip2930; + +public class AccessList : IEnumerable<(Address Address, AccessList.StorageKeysEnumerable StorageKeys)> { - public class AccessList + private readonly List _items; + + private AccessList(List items) + { + _items = items; + } + + public static AccessList Empty() => new(new List()); + + public class Builder { - public AccessList(IReadOnlyDictionary> data, - Queue? orderQueue = null) + private readonly List _items = new(); + private Address? _currentAddress; + + public Builder AddAddress(Address address) { - Data = data; - OrderQueue = orderQueue; + _items.Add(address); + _currentAddress = address; + + return this; } - public IReadOnlyDictionary> Data { get; } + public Builder AddStorage(in UInt256 index) + { + if (_currentAddress is null) + { + throw new InvalidOperationException("No address known when adding index to the access list"); + } + _items.Add(index); - /// - /// Only used for access lists generated outside of Nethermind - /// - public IReadOnlyCollection? OrderQueue { get; } + return this; + } + + public AccessList Build() + { + return new AccessList(_items); + } + } + + public Enumerator GetEnumerator() => new(_items); + IEnumerator<(Address Address, StorageKeysEnumerable StorageKeys)> IEnumerable<(Address Address, StorageKeysEnumerable StorageKeys)>.GetEnumerator() => GetEnumerator(); + IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); + + public struct Enumerator : IEnumerator<(Address Address, StorageKeysEnumerable StorageKeys)>, IEnumerator<(Address Address, IEnumerable StorageKeys)> + { + private readonly List _items; + private int _index = -1; + + public Enumerator(List items) + { + _items = items; + } + + public bool MoveNext() + { + while (++_index < _items.Count && _items[_index] is not Address) { } + return _index < _items.Count; + } + + public void Reset() => _index = -1; + public (Address Address, StorageKeysEnumerable StorageKeys) Current => ((Address)_items[_index], new StorageKeysEnumerable(_items, _index)); + (Address Address, IEnumerable StorageKeys) IEnumerator<(Address Address, IEnumerable StorageKeys)>.Current => Current; + object IEnumerator.Current => Current; + public void Dispose() { } + } + + public readonly struct StorageKeysEnumerable : IEnumerable + { + private readonly List _items; + private readonly int _index; + + public StorageKeysEnumerable(List items, int index) + { + _items = items; + _index = index; + } + + StorageKeysEnumerator GetEnumerator() => new(_items, _index); + IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); + IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); + } + + public struct StorageKeysEnumerator : IEnumerator + { + private readonly List _items; + private readonly int _startingIndex; + private int _index; + + public StorageKeysEnumerator(List items, int index) + { + _items = items; + _startingIndex = _index = index; + } - /// - /// Has no duplicate entries (allows for more efficient serialization / deserialization) - /// - public bool IsNormalized => OrderQueue is null; + public bool MoveNext() => ++_index < _items.Count && _items[_index] is UInt256; + public void Reset() => _index = _startingIndex; + public UInt256 Current => (UInt256)_items[_index]; + object IEnumerator.Current => Current; + public void Dispose() { } } } diff --git a/src/Nethermind/Nethermind.Core/Eip2930/AccessListBuilder.cs b/src/Nethermind/Nethermind.Core/Eip2930/AccessListBuilder.cs deleted file mode 100644 index ff1d6821bdb..00000000000 --- a/src/Nethermind/Nethermind.Core/Eip2930/AccessListBuilder.cs +++ /dev/null @@ -1,62 +0,0 @@ -// SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited -// SPDX-License-Identifier: LGPL-3.0-only - -using System; -using System.Collections.Generic; -using Nethermind.Int256; - -namespace Nethermind.Core.Eip2930 -{ - /// - /// We store the extra information here to be able to recreate the order of the incoming transactions. - /// EIP-2930 (https://eips.ethereum.org/EIPS/eip-2930) states that: - /// 'Allowing duplicates - /// This is done because it maximizes simplicity, avoiding questions of what to prevent duplication against: - /// just between two addresses/keys in the access list, - /// between the access list and the tx sender/recipient/newly created contract, - /// other restrictions? - /// Because gas is charged per item, there is no gain and only cost in including a value in the access list twice, - /// so this should not lead to extra chain bloat in practice.' - /// - /// While spec is simplified in this matter (somewhat) it leads to a bit more edge cases. - /// We can no longer simply store the access list as a dictionary, we need to store the order of items - /// and info on duplicates. The way that I suggest is by adding an additional queue structure. - /// It be further optimized by only including a queue of integers and a strict ordering algorithm for the dictionary. - /// - /// I leave it for later in case such an optimization is needed. - /// - public class AccessListBuilder - { - private readonly Dictionary> _data = new(); - - private readonly Queue _orderQueue = new(); - - private Address? _currentAddress; - - public void AddAddress(Address address) - { - _currentAddress = address; - _orderQueue.Enqueue(_currentAddress); - if (!_data.ContainsKey(_currentAddress)) - { - _data[_currentAddress] = new HashSet(); - } - } - - public void AddStorage(in UInt256 index) - { - if (_currentAddress is null) - { - throw new InvalidOperationException("No address known when adding index to the access list"); - } - - _orderQueue.Enqueue(index); - (_data[_currentAddress] as HashSet)!.Add(index); - } - - public AccessList ToAccessList() - { - return new(_data, _orderQueue); - } - } -} diff --git a/src/Nethermind/Nethermind.Evm.Test/IntrinsicGasCalculatorTests.cs b/src/Nethermind/Nethermind.Evm.Test/IntrinsicGasCalculatorTests.cs index f830b2483cc..126efa7438b 100644 --- a/src/Nethermind/Nethermind.Evm.Test/IntrinsicGasCalculatorTests.cs +++ b/src/Nethermind/Nethermind.Evm.Test/IntrinsicGasCalculatorTests.cs @@ -49,7 +49,7 @@ public void Intrinsic_cost_is_calculated_properly((Transaction Tx, long Cost, st [TestCaseSource(nameof(AccessTestCaseSource))] public void Intrinsic_cost_is_calculated_properly((List orderQueue, long Cost) testCase) { - AccessListBuilder accessListBuilder = new(); + AccessList.Builder accessListBuilder = new(); foreach (object o in testCase.orderQueue) { if (o is Address address) @@ -62,7 +62,7 @@ public void Intrinsic_cost_is_calculated_properly((List orderQueue, long } } - AccessList accessList = accessListBuilder.ToAccessList(); + AccessList accessList = accessListBuilder.Build(); Transaction tx = Build.A.Transaction.SignedAndResolved().WithAccessList(accessList).TestObject; void Test(IReleaseSpec spec, bool supportsAccessLists) diff --git a/src/Nethermind/Nethermind.Evm.Test/Tracing/AccessTxTracerTests.cs b/src/Nethermind/Nethermind.Evm.Test/Tracing/AccessTxTracerTests.cs index 68975281e51..d291685f3a4 100644 --- a/src/Nethermind/Nethermind.Evm.Test/Tracing/AccessTxTracerTests.cs +++ b/src/Nethermind/Nethermind.Evm.Test/Tracing/AccessTxTracerTests.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Collections.Immutable; +using System.Linq; using FluentAssertions; using Nethermind.Core; using Nethermind.Core.Specs; @@ -30,12 +31,11 @@ public void Records_get_correct_accessed_addresses() (AccessTxTracer tracer, _, _) = ExecuteAndTraceAccessCall(SenderRecipientAndMiner.Default, code); - IEnumerable
addressesAccessed = tracer.AccessList.Data.Keys; + IEnumerable
addressesAccessed = tracer.AccessList!.Select(tuples => tuples.Address); IEnumerable
expected = new[] { SenderRecipientAndMiner.Default.Sender, SenderRecipientAndMiner.Default.Recipient, TestItem.AddressC }; - Assert.IsNotEmpty(addressesAccessed); addressesAccessed.Should().BeEquivalentTo(expected); } @@ -50,13 +50,12 @@ public void Records_get_correct_accessed_keys() (AccessTxTracer tracer, _, _) = ExecuteAndTraceAccessCall(SenderRecipientAndMiner.Default, code); - IReadOnlyDictionary> accessedData = tracer.AccessList.Data; - - Assert.IsNotEmpty(accessedData); - accessedData.Should().BeEquivalentTo( - new Dictionary>{ - {SenderRecipientAndMiner.Default.Sender, ImmutableHashSet.Empty}, - {SenderRecipientAndMiner.Default.Recipient, new HashSet{105}}}); + tracer.AccessList!.Should().BeEquivalentTo( + new[] + { + (SenderRecipientAndMiner.Default.Sender, new UInt256[] { }), + (SenderRecipientAndMiner.Default.Recipient, new UInt256[] { 105 }) + }); } protected override ISpecProvider SpecProvider => new TestSpecProvider(Berlin.Instance); diff --git a/src/Nethermind/Nethermind.Evm.Test/TransactionProcessorTests.cs b/src/Nethermind/Nethermind.Evm.Test/TransactionProcessorTests.cs index 13159d48f24..286829ec99d 100644 --- a/src/Nethermind/Nethermind.Evm.Test/TransactionProcessorTests.cs +++ b/src/Nethermind/Nethermind.Evm.Test/TransactionProcessorTests.cs @@ -172,7 +172,7 @@ public void Can_handle_quick_fail_on_invalid_nonce(bool withStateDiff, bool with [TestCase(false, false)] public void Can_handle_quick_fail_on_not_enough_balance_on_intrinsic_gas(bool withStateDiff, bool withTrace) { - AccessListBuilder accessListBuilder = new(); + AccessList.Builder accessListBuilder = new(); foreach (Address address in TestItem.Addresses) { accessListBuilder.AddAddress(address); @@ -180,7 +180,7 @@ public void Can_handle_quick_fail_on_not_enough_balance_on_intrinsic_gas(bool wi Transaction tx = Build.A.Transaction .WithGasLimit(GasCostOf.Transaction * 2) - .WithAccessList(accessListBuilder.ToAccessList()) + .WithAccessList(accessListBuilder.Build()) .SignedAndResolved(_ethereumEcdsa, TestItem.PrivateKeyA, _isEip155Enabled) .TestObject; diff --git a/src/Nethermind/Nethermind.Evm/EvmState.cs b/src/Nethermind/Nethermind.Evm/EvmState.cs index 47f5a2b15ec..23604d3e79f 100644 --- a/src/Nethermind/Nethermind.Evm/EvmState.cs +++ b/src/Nethermind/Nethermind.Evm/EvmState.cs @@ -38,7 +38,7 @@ public StackPool(int maxCallStackDepth = VirtualMachine.MaxCallDepth * 2) /// /// The word 'return' acts here once as a verb 'to return stack to the pool' and once as a part of the - /// compound noun 'return stack' which is a stack of subroutine return values. + /// compound noun 'return stack' which is a stack of subroutine return values. /// /// /// @@ -275,7 +275,7 @@ public void WarmUp(AccessList? accessList) { if (accessList is not null) { - foreach ((Address address, IReadOnlySet storages) in accessList.Data) + foreach ((Address address, AccessList.StorageKeysEnumerable storages) in accessList) { WarmUp(address); foreach (UInt256 storage in storages) diff --git a/src/Nethermind/Nethermind.Evm/IntrinsicGasCalculator.cs b/src/Nethermind/Nethermind.Evm/IntrinsicGasCalculator.cs index b030b204bb2..bb90b262e99 100644 --- a/src/Nethermind/Nethermind.Evm/IntrinsicGasCalculator.cs +++ b/src/Nethermind/Nethermind.Evm/IntrinsicGasCalculator.cs @@ -2,8 +2,8 @@ // SPDX-License-Identifier: LGPL-3.0-only using System; +using System.Collections.Generic; using System.IO; -using System.Linq; using Nethermind.Core; using Nethermind.Core.Eip2930; using Nethermind.Core.Specs; @@ -61,34 +61,20 @@ private static long AccessListCost(Transaction transaction, IReleaseSpec release long accessListCost = 0; if (accessList is not null) { - if (releaseSpec.UseTxAccessLists) - { - if (accessList.IsNormalized) - { - accessListCost += accessList.Data.Count * GasCostOf.AccessAccountListEntry; - accessListCost += accessList.Data.Sum(d => d.Value.Count) * - GasCostOf.AccessStorageListEntry; - } - else - { - foreach (object o in accessList.OrderQueue!) - { - if (o is Address) - { - accessListCost += GasCostOf.AccessAccountListEntry; - } - else - { - accessListCost += GasCostOf.AccessStorageListEntry; - } - } - } - } - else + if (!releaseSpec.UseTxAccessLists) { throw new InvalidDataException( $"Transaction with an access list received within the context of {releaseSpec.Name}. Eip-2930 is not enabled."); } + + foreach ((Address address, AccessList.StorageKeysEnumerable storageKeys) entry in accessList) + { + accessListCost += GasCostOf.AccessAccountListEntry; + foreach (UInt256 _ in entry.storageKeys) + { + accessListCost += GasCostOf.AccessStorageListEntry; + } + } } return accessListCost; diff --git a/src/Nethermind/Nethermind.Evm/Tracing/AccessTxTracer.cs b/src/Nethermind/Nethermind.Evm/Tracing/AccessTxTracer.cs index 6f839790ff4..9959ecf1b1a 100644 --- a/src/Nethermind/Nethermind.Evm/Tracing/AccessTxTracer.cs +++ b/src/Nethermind/Nethermind.Evm/Tracing/AccessTxTracer.cs @@ -2,7 +2,6 @@ // SPDX-License-Identifier: LGPL-3.0-only using System.Collections.Generic; -using System.Linq; using Nethermind.Core; using Nethermind.Core.Crypto; using Nethermind.Core.Eip2930; @@ -63,7 +62,16 @@ public override void ReportAccess(IReadOnlySet
accessedAddresses, IRead } } - AccessList = new AccessList(dictionary.ToDictionary(k => k.Key, v => (IReadOnlySet)v.Value)); + AccessList.Builder builder = new(); + foreach ((Address address, ISet storageKeys) in dictionary) + { + builder.AddAddress(address); + foreach (UInt256 storageKey in storageKeys) + { + builder.AddStorage(storageKey); + } + } + AccessList = builder.Build(); } public long GasSpent { get; set; } diff --git a/src/Nethermind/Nethermind.JsonRpc.Test/Data/AccessListItemForRpcTests.cs b/src/Nethermind/Nethermind.JsonRpc.Test/Data/AccessListItemForRpcTests.cs new file mode 100644 index 00000000000..31345ac4e63 --- /dev/null +++ b/src/Nethermind/Nethermind.JsonRpc.Test/Data/AccessListItemForRpcTests.cs @@ -0,0 +1,115 @@ +// SPDX-FileCopyrightText: 2023 Demerzel Solutions Limited +// SPDX-License-Identifier: LGPL-3.0-only + +using System.Collections.Generic; +using FluentAssertions; +using Nethermind.Core; +using Nethermind.Core.Eip2930; +using Nethermind.Core.Test.Builders; +using Nethermind.Int256; +using Nethermind.JsonRpc.Data; +using NUnit.Framework; + +namespace Nethermind.JsonRpc.Test.Data; + +public class AccessListItemForRpcTests +{ + [Test] + public void Single_address_with_no_storage() + { + Address address = TestItem.AddressA; + AccessList accessList = new AccessList.Builder() + .AddAddress(address) + .Build(); + + IEnumerable forRpc = AccessListItemForRpc.FromAccessList(accessList); + AccessListItemForRpc[] expected = { new(address, new UInt256[] { }) }; + forRpc.Should().BeEquivalentTo(expected); + } + + [Test] + public void Single_address_with_multiple_storage_keys() + { + Address address = TestItem.AddressA; + UInt256 storageKey1 = (UInt256)1; + UInt256 storageKey2 = (UInt256)2; + UInt256 storageKey3 = (UInt256)3; + + AccessList accessList = new AccessList.Builder() + .AddAddress(address) + .AddStorage(storageKey1) + .AddStorage(storageKey2) + .AddStorage(storageKey3) + .Build(); + + IEnumerable forRpc = AccessListItemForRpc.FromAccessList(accessList); + AccessListItemForRpc[] expected = { new(address, new[] { storageKey1, storageKey2, storageKey3 }) }; + forRpc.Should().BeEquivalentTo(expected); + } + + [Test] + public void Single_address_with_duplicated_storage_keys() + { + Address address = TestItem.AddressA; + UInt256 storageKey1 = (UInt256)1; + UInt256 storageKey2 = (UInt256)2; + UInt256 storageKey3 = (UInt256)3; + + AccessList accessList = new AccessList.Builder() + .AddAddress(address) + .AddStorage(storageKey1) + .AddStorage(storageKey2) + .AddStorage(storageKey3) + .AddStorage(storageKey1) + .Build(); + + IEnumerable forRpc = AccessListItemForRpc.FromAccessList(accessList); + + AccessListItemForRpc[] expected = { new(address, new[] { storageKey1, storageKey2, storageKey3, storageKey1 }) }; + forRpc.Should().BeEquivalentTo(expected); + } + + [Test] + public void Duplicated_address_with_multiple_storage_keys() + { + Address address = TestItem.AddressA; + UInt256 storageKey1 = (UInt256)1; + UInt256 storageKey2 = (UInt256)2; + UInt256 storageKey3 = (UInt256)3; + + AccessList accessList = new AccessList.Builder() + .AddAddress(address) + .AddStorage(storageKey1) + .AddStorage(storageKey2) + .AddAddress(address) + .AddStorage(storageKey3) + .Build(); + + IEnumerable forRpc = AccessListItemForRpc.FromAccessList(accessList); + + AccessListItemForRpc[] expected = { new(address, new[] { storageKey1, storageKey2 }), new(address, new[] { storageKey3 }) }; + forRpc.Should().BeEquivalentTo(expected); + } + + [Test] + public void Duplicated_address_with_duplicated_storage_keys() + { + Address address = TestItem.AddressA; + UInt256 storageKey1 = (UInt256)1; + UInt256 storageKey2 = (UInt256)2; + UInt256 storageKey3 = (UInt256)3; + + AccessList accessList = new AccessList.Builder() + .AddAddress(address) + .AddStorage(storageKey1) + .AddStorage(storageKey2) + .AddAddress(address) + .AddStorage(storageKey1) + .AddStorage(storageKey3) + .Build(); + + IEnumerable forRpc = AccessListItemForRpc.FromAccessList(accessList); + AccessListItemForRpc[] expected = { new(address, new[] { storageKey1, storageKey2 }), new(address, new[] { storageKey1, storageKey3 }) }; + forRpc.Should().BeEquivalentTo(expected); + } +} diff --git a/src/Nethermind/Nethermind.JsonRpc.Test/Data/Eip2930Tests.cs b/src/Nethermind/Nethermind.JsonRpc.Test/Data/Eip2930Tests.cs index ad2e899b064..a9176491bdf 100644 --- a/src/Nethermind/Nethermind.JsonRpc.Test/Data/Eip2930Tests.cs +++ b/src/Nethermind/Nethermind.JsonRpc.Test/Data/Eip2930Tests.cs @@ -22,18 +22,16 @@ public class Eip2930Tests private AccessList GetTestAccessList() { - AccessListBuilder accessListBuilder = new(); - - accessListBuilder.AddAddress(TestItem.AddressA); - accessListBuilder.AddStorage(1); - accessListBuilder.AddStorage(2); - accessListBuilder.AddStorage(3); - accessListBuilder.AddStorage(5); - accessListBuilder.AddStorage(8); - accessListBuilder.AddAddress(TestItem.AddressB); - accessListBuilder.AddStorage(42); - - return accessListBuilder.ToAccessList(); + return new AccessList.Builder() + .AddAddress(TestItem.AddressA) + .AddStorage(1) + .AddStorage(2) + .AddStorage(3) + .AddStorage(5) + .AddStorage(8) + .AddAddress(TestItem.AddressB) + .AddStorage(42) + .Build(); } [TestCase(TxType.AccessList, """{"nonce":"0x0","blockHash":null,"blockNumber":null,"transactionIndex":null,"to":null,"value":"0x0","gasPrice":"0x0","gas":"0x0","input":null,"type":"0x1","chainId":"0x1","accessList":[{"address":"0xb7705ae4c6f81b66cdb323c65f4e8133690fc099","storageKeys":["0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000003","0x0000000000000000000000000000000000000000000000000000000000000005","0x0000000000000000000000000000000000000000000000000000000000000008"]},{"address":"0x942921b14f1b1c385cd7e0cc2ef7abe5598c8358","storageKeys":["0x000000000000000000000000000000000000000000000000000000000000002a"]}]}""")] @@ -123,11 +121,11 @@ public void can_deserialize_no_accessList() [TestCase(TxType.EIP1559, """{"nonce":"0x0","blockHash":null,"blockNumber":null,"transactionIndex":null,"to":null,"value":"0x0","gasPrice":"0x0","maxPriorityFeePerGas":"0x0","maxFeePerGas":"0x0","gas":"0x0","input":null,"type":"0x2","chainId":"0x1","accessList":[]}""")] public void can_serialize_empty_accessList(TxType txType, string txJson) { - Dictionary> data = new(); + AccessList.Builder builder = new(); Transaction transaction = new() { Type = txType, - AccessList = new AccessList(data), + AccessList = builder.Build(), }; TransactionForRpc transactionForRpc = new(transaction); @@ -144,24 +142,21 @@ public void can_deserialize_empty_accessList() TransactionForRpc transactionForRpc = _serializer.Deserialize(json); transactionForRpc.Type.Should().Be(TxType.AccessList); - transactionForRpc.AccessList!.Length.Should().Be(0); + transactionForRpc.AccessList!.Should().BeEmpty(); } [TestCase(TxType.AccessList, """{"nonce":"0x0","blockHash":null,"blockNumber":null,"transactionIndex":null,"to":null,"value":"0x0","gasPrice":"0x0","gas":"0x0","input":null,"type":"0x1","chainId":"0x1","accessList":[{"address":"0xb7705ae4c6f81b66cdb323c65f4e8133690fc099","storageKeys":[]}]}""")] [TestCase(TxType.EIP1559, """{"nonce":"0x0","blockHash":null,"blockNumber":null,"transactionIndex":null,"to":null,"value":"0x0","gasPrice":"0x0","maxPriorityFeePerGas":"0x0","maxFeePerGas":"0x0","gas":"0x0","input":null,"type":"0x2","chainId":"0x1","accessList":[{"address":"0xb7705ae4c6f81b66cdb323c65f4e8133690fc099","storageKeys":[]}]}""")] public void can_serialize_accessList_with_empty_storageKeys(TxType txType, string txJson) { - Dictionary> data = new() - { - { - TestItem.AddressA, new HashSet() - }, - }; + AccessList.Builder builder = new AccessList.Builder() + .AddAddress(TestItem.AddressA); Transaction transaction = new() { Type = txType, - AccessList = new AccessList(data), + AccessList = builder.Build(), }; + TransactionForRpc transactionForRpc = new(transaction); string serialized = _serializer.Serialize(transactionForRpc); @@ -181,29 +176,6 @@ public void can_deserialize_accessList_with_empty_storageKeys() transactionForRpc.AccessList.Should().BeEquivalentTo(accessList); } - [TestCase(TxType.AccessList, """{"nonce":"0x0","blockHash":null,"blockNumber":null,"transactionIndex":null,"to":null,"value":"0x0","gasPrice":"0x0","gas":"0x0","input":null,"type":"0x1","chainId":"0x1","accessList":[{"address":"0xb7705ae4c6f81b66cdb323c65f4e8133690fc099","storageKeys":[]}]}""")] - [TestCase(TxType.EIP1559, """{"nonce":"0x0","blockHash":null,"blockNumber":null,"transactionIndex":null,"to":null,"value":"0x0","gasPrice":"0x0","maxPriorityFeePerGas":"0x0","maxFeePerGas":"0x0","gas":"0x0","input":null,"type":"0x2","chainId":"0x1","accessList":[{"address":"0xb7705ae4c6f81b66cdb323c65f4e8133690fc099","storageKeys":[]}]}""")] - public void can_serialize_accessList_with_null_storageKeys(TxType txType, string txJson) - { - Dictionary> data = new() - { - { - TestItem.AddressA, null! - }, - }; - Transaction transaction = new() - { - Type = txType, - AccessList = new AccessList(data), - }; - - TransactionForRpc transactionForRpc = new(transaction); - - string serialized = _serializer.Serialize(transactionForRpc); - - JToken.Parse(serialized).Should().BeEquivalentTo(JToken.Parse(txJson)); - } - [Test] public void can_deserialize_accessList_with_null_storageKeys() { @@ -213,7 +185,6 @@ public void can_deserialize_accessList_with_null_storageKeys() TransactionForRpc transactionForRpc = _serializer.Deserialize(json); transactionForRpc.Type.Should().Be(TxType.AccessList); - transactionForRpc.AccessList!.Length.Should().Be(1); transactionForRpc.AccessList.Should().BeEquivalentTo(accessList); } @@ -226,7 +197,6 @@ public void can_deserialize_accessList_with_null_storageKeys_and_eip1559_txType( TransactionForRpc transactionForRpc = _serializer.Deserialize(json); transactionForRpc.Type.Should().Be(TxType.EIP1559); - transactionForRpc.AccessList!.Length.Should().Be(1); transactionForRpc.AccessList.Should().BeEquivalentTo(accessList); } diff --git a/src/Nethermind/Nethermind.JsonRpc/Data/AccessListForRpc.cs b/src/Nethermind/Nethermind.JsonRpc/Data/AccessListForRpc.cs index 725e2a197fe..f4d05e7575b 100644 --- a/src/Nethermind/Nethermind.JsonRpc/Data/AccessListForRpc.cs +++ b/src/Nethermind/Nethermind.JsonRpc/Data/AccessListForRpc.cs @@ -1,19 +1,20 @@ // SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited // SPDX-License-Identifier: LGPL-3.0-only +using System.Collections.Generic; using Nethermind.Int256; namespace Nethermind.JsonRpc.Data { - public class AccessListForRpc + public struct AccessListForRpc { - public AccessListForRpc(AccessListItemForRpc[] accessList, in UInt256 gasUsed) + public AccessListForRpc(IEnumerable accessList, in UInt256 gasUsed) { AccessList = accessList; GasUsed = gasUsed; } - public AccessListItemForRpc[] AccessList { get; } + public IEnumerable AccessList { get; } public UInt256 GasUsed { get; } } diff --git a/src/Nethermind/Nethermind.JsonRpc/Data/AccessListItemForRpc.cs b/src/Nethermind/Nethermind.JsonRpc/Data/AccessListItemForRpc.cs index 512cb2977c4..1eed1d5a03d 100644 --- a/src/Nethermind/Nethermind.JsonRpc/Data/AccessListItemForRpc.cs +++ b/src/Nethermind/Nethermind.JsonRpc/Data/AccessListItemForRpc.cs @@ -5,6 +5,7 @@ using System.Collections.Generic; using System.Linq; using Nethermind.Core; +using Nethermind.Core.Collections; using Nethermind.Core.Eip2930; using Nethermind.Int256; using Nethermind.Serialization.Json; @@ -12,38 +13,42 @@ namespace Nethermind.JsonRpc.Data { - public class AccessListItemForRpc + public struct AccessListItemForRpc : IEquatable { - public AccessListItemForRpc(Address address, IReadOnlyCollection? storageKeys) + public AccessListItemForRpc(Address address, IEnumerable? storageKeys) { Address = address; - StorageKeys = storageKeys?.ToArray() ?? Array.Empty(); + StorageKeys = storageKeys; } public Address Address { get; set; } [JsonProperty(ItemConverterType = typeof(StorageCellIndexConverter))] - public UInt256[]? StorageKeys { get; set; } + public IEnumerable? StorageKeys { get; set; } - public static AccessListItemForRpc[] FromAccessList(AccessList accessList) => - accessList.Data.Select(kvp => new AccessListItemForRpc(kvp.Key, kvp.Value)).ToArray(); + public static IEnumerable FromAccessList(AccessList accessList) => + accessList.Select(tuple => new AccessListItemForRpc(tuple.Address, tuple.StorageKeys)); - public static AccessList ToAccessList(AccessListItemForRpc[] accessList) + public static AccessList ToAccessList(IEnumerable accessList) { - AccessListBuilder accessListBuilder = new(); - for (int i = 0; i < accessList.Length; i++) + AccessList.Builder builder = new(); + foreach (AccessListItemForRpc accessListItem in accessList) { - var accessListItem = accessList[i]; - accessListBuilder.AddAddress(accessListItem.Address); + builder.AddAddress(accessListItem.Address); if (accessListItem.StorageKeys is not null) { - for (int j = 0; j < accessListItem.StorageKeys.Length; j++) + foreach (UInt256 index in accessListItem.StorageKeys) { - accessListBuilder.AddStorage(accessListItem.StorageKeys[j]); + builder.AddStorage(index); } } } - return accessListBuilder.ToAccessList(); + + return builder.Build(); } + + public bool Equals(AccessListItemForRpc other) => Equals(Address, other.Address) && StorageKeys.NullableSequenceEqual(other.StorageKeys); + public override bool Equals(object? obj) => obj is AccessListItemForRpc other && Equals(other); + public override int GetHashCode() => HashCode.Combine(Address, StorageKeys); } } diff --git a/src/Nethermind/Nethermind.JsonRpc/Data/TransactionForRpc.cs b/src/Nethermind/Nethermind.JsonRpc/Data/TransactionForRpc.cs index ca340403e22..9116a6c8eea 100644 --- a/src/Nethermind/Nethermind.JsonRpc/Data/TransactionForRpc.cs +++ b/src/Nethermind/Nethermind.JsonRpc/Data/TransactionForRpc.cs @@ -2,6 +2,7 @@ // SPDX-License-Identifier: LGPL-3.0-only using System; +using System.Collections.Generic; using Nethermind.Core; using Nethermind.Core.Crypto; using Nethermind.Core.Eip2930; @@ -118,7 +119,7 @@ public TransactionForRpc() public TxType Type { get; set; } - public AccessListItemForRpc[]? AccessList { get; set; } + public IEnumerable? AccessList { get; set; } [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] diff --git a/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/EthRpcModule.TransactionExecutor.cs b/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/EthRpcModule.TransactionExecutor.cs index 8ff24d73ed1..101ce8e5cb8 100644 --- a/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/EthRpcModule.TransactionExecutor.cs +++ b/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/EthRpcModule.TransactionExecutor.cs @@ -2,6 +2,8 @@ // SPDX-License-Identifier: LGPL-3.0-only using System; +using System.Collections.Generic; +using System.Linq; using System.Threading; using Nethermind.Blockchain.Find; using Nethermind.Core; @@ -128,10 +130,10 @@ protected override ResultWrapper ExecuteTx(BlockHeader header, : ResultWrapper.Fail(result.Error, ErrorCodes.ExecutionError, new AccessListForRpc(GetResultAccessList(tx, result), GetResultGas(tx, result))); } - private static AccessListItemForRpc[] GetResultAccessList(Transaction tx, BlockchainBridge.CallOutput result) + private static IEnumerable GetResultAccessList(Transaction tx, BlockchainBridge.CallOutput result) { AccessList? accessList = result.AccessList ?? tx.AccessList; - return accessList is null ? Array.Empty() : AccessListItemForRpc.FromAccessList(accessList); + return accessList is null ? Enumerable.Empty() : AccessListItemForRpc.FromAccessList(accessList); } private static UInt256 GetResultGas(Transaction transaction, BlockchainBridge.CallOutput result) diff --git a/src/Nethermind/Nethermind.Serialization.Rlp/Eip2930/AccessListDecoder.cs b/src/Nethermind/Nethermind.Serialization.Rlp/Eip2930/AccessListDecoder.cs index db6bd5048d9..bd3a668cc2a 100644 --- a/src/Nethermind/Nethermind.Serialization.Rlp/Eip2930/AccessListDecoder.cs +++ b/src/Nethermind/Nethermind.Serialization.Rlp/Eip2930/AccessListDecoder.cs @@ -2,7 +2,7 @@ // SPDX-License-Identifier: LGPL-3.0-only using System.Collections.Generic; -using System.IO; +using System.Linq; using Nethermind.Core; using Nethermind.Core.Eip2930; using Nethermind.Int256; @@ -29,7 +29,7 @@ public class AccessListDecoder : IRlpStreamDecoder, IRlpValueDecode int length = rlpStream.ReadSequenceLength(); int check = rlpStream.Position + length; - AccessListBuilder accessListBuilder = new(); + AccessList.Builder accessListBuilder = new(); while (rlpStream.Position < check) { int accessListItemLength = rlpStream.ReadSequenceLength(); @@ -72,7 +72,7 @@ public class AccessListDecoder : IRlpStreamDecoder, IRlpValueDecode rlpStream.Check(check); } - return accessListBuilder.ToAccessList(); + return accessListBuilder.Build(); } /// @@ -94,7 +94,7 @@ public class AccessListDecoder : IRlpStreamDecoder, IRlpValueDecode int length = decoderContext.ReadSequenceLength(); int check = decoderContext.Position + length; - AccessListBuilder accessListBuilder = new(); + AccessList.Builder accessListBuilder = new(); while (decoderContext.Position < check) { int accessListItemLength = decoderContext.ReadSequenceLength(); @@ -137,20 +137,7 @@ public class AccessListDecoder : IRlpStreamDecoder, IRlpValueDecode decoderContext.Check(check); } - return accessListBuilder.ToAccessList(); - } - - private readonly struct AccessListItem - { - public AccessListItem(Address address, List indexes) - { - Address = address; - Indexes = indexes; - } - - public Address Address { get; } - - public List Indexes { get; } + return accessListBuilder.Build(); } public void Encode(RlpStream stream, AccessList? item, RlpBehaviors rlpBehaviors = RlpBehaviors.None) @@ -158,86 +145,44 @@ public void Encode(RlpStream stream, AccessList? item, RlpBehaviors rlpBehaviors if (item is null) { stream.WriteByte(Rlp.NullObjectByte); + return; } - else - { - int contentLength = GetContentLength(item); - stream.StartSequence(contentLength); - if (!item.IsNormalized) + int contentLength = GetContentLength(item); + stream.StartSequence(contentLength); + foreach ((Address? address, AccessList.StorageKeysEnumerable storageKeys) in item) + { + // {} brackets applied to show the content structure + // Address + // Index1 + // Index2 + // ... + // IndexN + AccessItemLengths lengths = new(storageKeys.Count()); + stream.StartSequence(lengths.ContentLength); { - AccessListItem? currentItem = default; - - void SerializeCurrent() + stream.Encode(address); + stream.StartSequence(lengths.IndexesContentLength); { - if (currentItem is not null) + foreach (UInt256 index in storageKeys) { - AccessListItem toEncode = currentItem.Value; - EncodeListItem(stream, toEncode.Address, toEncode.Indexes, toEncode.Indexes.Count); - } - } - - foreach (object accessListEntry in item.OrderQueue!) - { - if (accessListEntry is Address address) - { - // serialize any element that is not the last - SerializeCurrent(); - currentItem = new AccessListItem(address, new List()); - } - else - { - if (currentItem is null) - { - throw new InvalidDataException( - $"{nameof(AccessList)} order looks corrupted - processing index ahead of address"); - } - - currentItem.Value.Indexes.Add((UInt256)accessListEntry); + // storage indices are encoded as 32 bytes data arrays + stream.Encode(index, 32); } } - - // serialize the last element - SerializeCurrent(); - } - else - { - foreach ((Address address, IReadOnlySet indexes) in item.Data) - { - EncodeListItem(stream, address, indexes, indexes.Count); - } } } } - /// - /// Spend some time trying to find some base interface like ICountableEnumerable, none of such in .NET Core - /// - private static void EncodeListItem( - RlpStream stream, - Address address, - IEnumerable indexes, - int indexesCount) + public int GetLength(AccessList? accessList, RlpBehaviors rlpBehaviors) { - // {} brackets applied to show the content structure - // Address - // Index1 - // Index2 - // ... - // IndexN - AccessItemLengths lengths = new(indexesCount); - stream.StartSequence(lengths.ContentLength); + if (accessList is null) { - stream.Encode(address); - stream.StartSequence(lengths.IndexesContentLength); - { - foreach (UInt256 index in indexes) - { - // storage indices are encoded as 32 bytes data arrays - stream.Encode(index, 32); - } - } + return 1; } + + int contentLength = GetContentLength(accessList); + return Rlp.LengthOfSequence(contentLength); } /// @@ -261,64 +206,9 @@ public AccessItemLengths(int indexesCount) private static int GetContentLength(AccessList accessList) { - int contentLength = 0; - if (accessList.IsNormalized) - { - foreach ((_, IReadOnlySet indexes) in accessList.Data) - { - contentLength += new AccessItemLengths(indexes.Count).SequenceLength; - } - } - else - { - IReadOnlyCollection orderQueue = accessList.OrderQueue; - bool isOpen = false; - int indexCounter = 0; - foreach (object accessListEntry in orderQueue!) - { - if (accessListEntry is Address) - { - if (isOpen) - { - contentLength += new AccessItemLengths(indexCounter).SequenceLength; - indexCounter = 0; - } - else - { - isOpen = true; - } - } - else - { - indexCounter++; - } - } - - if (isOpen) - { - contentLength += new AccessItemLengths(indexCounter).SequenceLength; - } - } - - return contentLength; - } - - public int GetLength(AccessList? accessList, RlpBehaviors rlpBehaviors) - { - if (accessList is null) - { - return 1; - } - - int contentLength = GetContentLength(accessList); - return Rlp.LengthOfSequence(contentLength); - } - - public Rlp Encode(AccessList? accessList, RlpBehaviors rlpBehaviors = RlpBehaviors.None) - { - RlpStream rlpStream = new(GetLength(accessList, rlpBehaviors)); - Encode(rlpStream, accessList, rlpBehaviors); - return new Rlp(rlpStream.Data); + return accessList + .Select(entry => new AccessItemLengths(entry.StorageKeys.Count())) + .Sum(lengths => lengths.SequenceLength); } } } From 6472650d2c21a6b73fea0980431a34e579a731e9 Mon Sep 17 00:00:00 2001 From: Alexey Date: Wed, 4 Oct 2023 11:16:08 +0300 Subject: [PATCH 50/50] Set head according to fcuState even when attributes are incorrect (#6144) --- .../AuRaMergeEngineModuleTests.cs | 108 +++++++++--------- .../EngineModuleTests.HelperFunctions.cs | 46 +++++--- .../EngineModuleTests.Setup.cs | 14 ++- .../EngineModuleTests.Synchronization.cs | 42 +++---- .../EngineModuleTests.V1.cs | 61 ++++------ .../EngineModuleTests.V2.cs | 8 +- .../EngineModuleTests.V3.cs | 90 +++++++++++---- .../EngineRpcModule.Paris.cs | 11 +- .../Handlers/ForkchoiceUpdatedHandler.cs | 38 +++++- .../Handlers/IForkchoiceUpdatedHandler.cs | 2 +- .../Nethermind.Merge.Plugin/MergePlugin.cs | 1 + 11 files changed, 250 insertions(+), 171 deletions(-) diff --git a/src/Nethermind/Nethermind.Merge.AuRa.Test/AuRaMergeEngineModuleTests.cs b/src/Nethermind/Nethermind.Merge.AuRa.Test/AuRaMergeEngineModuleTests.cs index 7d3962a5a8f..e640c01301d 100644 --- a/src/Nethermind/Nethermind.Merge.AuRa.Test/AuRaMergeEngineModuleTests.cs +++ b/src/Nethermind/Nethermind.Merge.AuRa.Test/AuRaMergeEngineModuleTests.cs @@ -9,8 +9,10 @@ using Nethermind.Consensus; using Nethermind.Consensus.AuRa; using Nethermind.Consensus.AuRa.Config; +using Nethermind.Consensus.AuRa.InitializationSteps; using Nethermind.Consensus.AuRa.Validators; using Nethermind.Consensus.Comparers; +using Nethermind.Consensus.Processing; using Nethermind.Consensus.Producers; using Nethermind.Consensus.Rewards; using Nethermind.Core; @@ -20,6 +22,7 @@ using Nethermind.Facade.Eth; using Nethermind.Int256; using Nethermind.Logging; +using Nethermind.Merge.AuRa.Withdrawals; using Nethermind.Merge.Plugin; using Nethermind.Merge.Plugin.BlockProduction; using Nethermind.Merge.Plugin.Handlers; @@ -27,6 +30,7 @@ using Nethermind.Serialization.Json; using Nethermind.Specs; using Nethermind.Specs.ChainSpecStyle; +using Nethermind.State; using Nethermind.Synchronization.ParallelSync; using NSubstitute; using NUnit.Framework; @@ -51,12 +55,11 @@ string BlockHash ) input) => base.forkchoiceUpdatedV2_should_validate_withdrawals(input); - [Ignore("engine_newPayloadV2 fails")] [TestCase( "0xe168b70ac8a6f7d90734010030801fbb2dcce03a657155c4024b36ba8d1e3926", "0x3e604e45a9a74b66a7e03f828cc2597f0cb5f5e7dc50c9211be3a62fbcd6396d", "0xdbd87b98a6be7d4e3f11ff8500c38a0736d9a5e7a47b5cb25628d37187a98cb9", - "0x78ecfec08729d895")] + "0x80ac487e132512b1")] public override Task Should_process_block_as_expected_V2(string latestValidHash, string blockHash, string stateRoot, string payloadId) => base.Should_process_block_as_expected_V2(latestValidHash, blockHash, stateRoot, payloadId); @@ -77,56 +80,64 @@ public override Task processing_block_should_serialize_valid_responses(string bl public override Task forkchoiceUpdatedV1_should_communicate_with_boost_relay_through_http(string blockHash, string parentHash) => base.forkchoiceUpdatedV1_should_communicate_with_boost_relay_through_http(blockHash, parentHash); - [Ignore("engine_newPayloadV2 fails")] + [Ignore("Withdrawals are not withdrawan due to lack of Aura contract in tests")] public override Task Can_apply_withdrawals_correctly((Withdrawal[][] Withdrawals, (Address Account, UInt256 BalanceIncrease)[] ExpectedAccountIncrease) input) { return base.Can_apply_withdrawals_correctly(input); } - [Ignore("engine_newPayloadV2 fails")] - public override Task Empty_block_is_valid_with_withdrawals_V2() - { - return base.Empty_block_is_valid_with_withdrawals_V2(); - } - - [Ignore("engine_newPayloadV2 fails")] - public override Task Should_handle_withdrawals_transition_when_Shanghai_fork_activated() - { - return base.Should_handle_withdrawals_transition_when_Shanghai_fork_activated(); - } - - [Ignore("engine_newPayloadV2 fails")] - public override Task getPayloadBodiesByHashV1_should_return_payload_bodies_in_order_of_request_block_hashes_and_null_for_unknown_hashes(IList withdrawals) - { - return base.getPayloadBodiesByHashV1_should_return_payload_bodies_in_order_of_request_block_hashes_and_null_for_unknown_hashes(withdrawals); - } - - [Ignore("engine_newPayloadV2 fails")] - public override Task getPayloadBodiesByRangeV1_should_return_canonical(IList withdrawals) - { - return base.getPayloadBodiesByRangeV1_should_return_canonical(withdrawals); - } - - [Ignore("engine_newPayloadV2 fails")] - public override Task getPayloadBodiesByRangeV1_should_return_payload_bodies_in_order_of_request_range_and_null_for_unknown_indexes(IList withdrawals) - { - return base.getPayloadBodiesByRangeV1_should_return_payload_bodies_in_order_of_request_range_and_null_for_unknown_indexes(withdrawals); - } - - [Ignore("engine_newPayloadV3 fails")] - public override Task NewPayloadV3_should_decline_mempool_encoding(bool inMempoolForm, string expectedPayloadStatus) - { - return base.NewPayloadV3_should_decline_mempool_encoding(inMempoolForm, expectedPayloadStatus); - } - class MergeAuRaTestBlockchain : MergeTestBlockchain { + private AuRaNethermindApi? _api; + public MergeAuRaTestBlockchain(IMergeConfig? mergeConfig = null, IPayloadPreparationService? mockedPayloadPreparationService = null) : base(mergeConfig, mockedPayloadPreparationService) { SealEngineType = Core.SealEngineType.AuRa; } + protected override IBlockProcessor CreateBlockProcessor() + { + _api = new(new ConfigProvider(), new EthereumJsonSerializer(), LogManager, + new ChainSpec + { + AuRa = new() + { + WithdrawalContractAddress = new("0xbabe2bed00000000000000000000000000000003") + }, + Parameters = new() + }) + { + BlockTree = BlockTree, + DbProvider = DbProvider, + ReadOnlyTrieStore = ReadOnlyTrieStore, + SpecProvider = SpecProvider, + TransactionComparerProvider = TransactionComparerProvider, + TxPool = TxPool + }; + + WithdrawalContractFactory withdrawalContractFactory = new(_api.ChainSpec!.AuRa, _api.AbiEncoder); + WithdrawalProcessor = new AuraWithdrawalProcessor( + withdrawalContractFactory.Create(TxProcessor), + LogManager + ); + + BlockValidator = CreateBlockValidator(); + IBlockProcessor processor = new BlockProcessor( + SpecProvider, + BlockValidator, + NoBlockRewards.Instance, + new BlockProcessor.BlockValidationTransactionsExecutor(TxProcessor, State), + State, + ReceiptStorage, + NullWitnessCollector.Instance, + LogManager, + WithdrawalProcessor); + + return new TestBlockProcessorInterceptor(processor, _blockProcessingThrottle); + } + + protected override IBlockProducer CreateTestBlockProducer(TxPoolTxSource txPoolTxSource, ISealer sealer, ITransactionComparerProvider transactionComparerProvider) { SealEngine = new MergeSealEngine(SealEngine, PoSSwitcher, SealValidator!, LogManager); @@ -143,23 +154,7 @@ protected override IBlockProducer CreateTestBlockProducer(TxPoolTxSource txPoolT targetAdjustedGasLimitCalculator); AuRaMergeBlockProducerEnvFactory blockProducerEnvFactory = new( - new(new ConfigProvider(), new EthereumJsonSerializer(), LogManager, - new ChainSpec - { - AuRa = new() - { - WithdrawalContractAddress = new("0xbabe2bed00000000000000000000000000000003") - }, - Parameters = new() - }) - { - BlockTree = BlockTree, - DbProvider = DbProvider, - ReadOnlyTrieStore = ReadOnlyTrieStore, - SpecProvider = SpecProvider, - TransactionComparerProvider = TransactionComparerProvider, - TxPool = TxPool - }, + _api!, new AuRaConfig(), new DisposableStack(), DbProvider, @@ -213,4 +208,3 @@ protected override IBlockProducer CreateTestBlockProducer(TxPoolTxSource txPoolT } } } - diff --git a/src/Nethermind/Nethermind.Merge.Plugin.Test/EngineModuleTests.HelperFunctions.cs b/src/Nethermind/Nethermind.Merge.Plugin.Test/EngineModuleTests.HelperFunctions.cs index 89b516d64b5..55b3df0ac92 100644 --- a/src/Nethermind/Nethermind.Merge.Plugin.Test/EngineModuleTests.HelperFunctions.cs +++ b/src/Nethermind/Nethermind.Merge.Plugin.Test/EngineModuleTests.HelperFunctions.cs @@ -22,6 +22,8 @@ using Nethermind.State; using Nethermind.Core.Specs; using Nethermind.Consensus.BeaconBlockRoot; +using Nethermind.Consensus.Withdrawals; +using Nethermind.Core.Test.Blockchain; namespace Nethermind.Merge.Plugin.Test { @@ -86,28 +88,46 @@ private ExecutionPayload CreateParentBlockRequestOnHead(IBlockTree blockTree) }; } - private static ExecutionPayload CreateBlockRequest(IReleaseSpec spec, IWorldState state, ExecutionPayload parent, Address miner, IList? withdrawals = null, - ulong? blobGasUsed = null, ulong? excessBlobGas = null, Transaction[]? transactions = null, Keccak? parentBeaconBlockRoot = null) - => CreateBlockRequestInternal(spec, state, parent, miner, withdrawals, blobGasUsed, excessBlobGas, transactions: transactions, parentBeaconBlockRoot: parentBeaconBlockRoot); + private static ExecutionPayload CreateBlockRequest(MergeTestBlockchain chain, ExecutionPayload parent, Address miner, IList? withdrawals = null, + ulong? blobGasUsed = null, ulong? excessBlobGas = null, Transaction[]? transactions = null, Keccak? parentBeaconBlockRoot = null) + { + ExecutionPayload blockRequest = CreateBlockRequestInternal(parent, miner, withdrawals, blobGasUsed, excessBlobGas, transactions: transactions, parentBeaconBlockRoot: parentBeaconBlockRoot); + blockRequest.TryGetBlock(out Block? block); + + Snapshot before = chain.State.TakeSnapshot(); + chain.WithdrawalProcessor?.ProcessWithdrawals(block!, chain.SpecProvider.GenesisSpec); + + chain.State.Commit(chain.SpecProvider.GenesisSpec); + chain.State.RecalculateStateRoot(); + blockRequest.StateRoot = chain.State.StateRoot; + chain.State.Restore(before); + + TryCalculateHash(blockRequest, out Keccak? hash); + blockRequest.BlockHash = hash; + return blockRequest; + } - private static ExecutionPayloadV3 CreateBlockRequestV3(IReleaseSpec spec, IWorldState state, ExecutionPayload parent, Address miner, IList? withdrawals = null, + private static ExecutionPayloadV3 CreateBlockRequestV3(MergeTestBlockchain chain, ExecutionPayload parent, Address miner, IList? withdrawals = null, ulong? blobGasUsed = null, ulong? excessBlobGas = null, Transaction[]? transactions = null, Keccak? parentBeaconBlockRoot = null) { - ExecutionPayloadV3 blockRequestV3 = CreateBlockRequestInternal(spec, state, parent, miner, withdrawals, blobGasUsed, excessBlobGas, transactions: transactions, parentBeaconBlockRoot: parentBeaconBlockRoot); + ExecutionPayloadV3 blockRequestV3 = CreateBlockRequestInternal(parent, miner, withdrawals, blobGasUsed, excessBlobGas, transactions: transactions, parentBeaconBlockRoot: parentBeaconBlockRoot); blockRequestV3.TryGetBlock(out Block? block); - _beaconBlockRootHandler.ApplyContractStateChanges(block!, spec, state); - state.Commit(spec); - state.CommitTree(blockRequestV3.BlockNumber); + Snapshot before = chain.State.TakeSnapshot(); + _beaconBlockRootHandler.ApplyContractStateChanges(block!, chain.SpecProvider.GenesisSpec, chain.State); + chain.WithdrawalProcessor?.ProcessWithdrawals(block!, chain.SpecProvider.GenesisSpec); + + chain.State.Commit(chain.SpecProvider.GenesisSpec); + chain.State.RecalculateStateRoot(); + blockRequestV3.StateRoot = chain.State.StateRoot; + chain.State.Restore(before); - state.RecalculateStateRoot(); - blockRequestV3.StateRoot = state.StateRoot; TryCalculateHash(blockRequestV3, out Keccak? hash); blockRequestV3.BlockHash = hash; return blockRequestV3; } - private static T CreateBlockRequestInternal(IReleaseSpec spec, IWorldState state, ExecutionPayload parent, Address miner, IList? withdrawals = null, + private static T CreateBlockRequestInternal(ExecutionPayload parent, Address miner, IList? withdrawals = null, ulong? blobGasUsed = null, ulong? excessBlobGas = null, Transaction[]? transactions = null, Keccak? parentBeaconBlockRoot = null) where T : ExecutionPayload, new() { T blockRequest = new() @@ -133,13 +153,13 @@ private static T CreateBlockRequestInternal(IReleaseSpec spec, IWorldState st return blockRequest; } - private static ExecutionPayload[] CreateBlockRequestBranch(IReleaseSpec spec, IWorldState state, ExecutionPayload parent, Address miner, int count) + private static ExecutionPayload[] CreateBlockRequestBranch(MergeTestBlockchain chain, ExecutionPayload parent, Address miner, int count) { ExecutionPayload currentBlock = parent; ExecutionPayload[] blockRequests = new ExecutionPayload[count]; for (int i = 0; i < count; i++) { - currentBlock = CreateBlockRequest(spec, state, currentBlock, miner); + currentBlock = CreateBlockRequest(chain, currentBlock, miner); blockRequests[i] = currentBlock; } diff --git a/src/Nethermind/Nethermind.Merge.Plugin.Test/EngineModuleTests.Setup.cs b/src/Nethermind/Nethermind.Merge.Plugin.Test/EngineModuleTests.Setup.cs index abe7a3f24e6..feab59ee82e 100644 --- a/src/Nethermind/Nethermind.Merge.Plugin.Test/EngineModuleTests.Setup.cs +++ b/src/Nethermind/Nethermind.Merge.Plugin.Test/EngineModuleTests.Setup.cs @@ -15,6 +15,7 @@ using Nethermind.Consensus.Producers; using Nethermind.Consensus.Rewards; using Nethermind.Consensus.Validators; +using Nethermind.Consensus.Withdrawals; using Nethermind.Core; using Nethermind.Core.Crypto; using Nethermind.Core.Specs; @@ -116,6 +117,7 @@ private IEngineRpcModule CreateEngineModule(MergeTestBlockchain chain, ISyncConf chain.BeaconSync, chain.BeaconPivot, peerRefresher, + chain.SpecProvider, chain.LogManager), new GetPayloadBodiesByHashV1Handler(chain.BlockTree, chain.LogManager), new GetPayloadBodiesByRangeV1Handler(chain.BlockTree, chain.LogManager), @@ -140,7 +142,9 @@ public class MergeTestBlockchain : TestBlockchain public BeaconSync? BeaconSync { get; set; } - private int _blockProcessingThrottle = 0; + public IWithdrawalProcessor? WithdrawalProcessor { get; set; } + + protected int _blockProcessingThrottle = 0; public MergeTestBlockchain ThrottleBlockProcessor(int delayMs) { @@ -215,6 +219,7 @@ protected override IBlockProducer CreateTestBlockProducer(TxPoolTxSource txPoolT protected override IBlockProcessor CreateBlockProcessor() { BlockValidator = CreateBlockValidator(); + WithdrawalProcessor = new WithdrawalProcessor(State, LogManager); IBlockProcessor processor = new BlockProcessor( SpecProvider, BlockValidator, @@ -223,12 +228,13 @@ protected override IBlockProcessor CreateBlockProcessor() State, ReceiptStorage, NullWitnessCollector.Instance, - LogManager); + LogManager, + WithdrawalProcessor); return new TestBlockProcessorInterceptor(processor, _blockProcessingThrottle); } - private IBlockValidator CreateBlockValidator() + protected IBlockValidator CreateBlockValidator() { IBlockCacheService blockCacheService = new BlockCacheService(); PoSSwitcher = new PoSSwitcher(MergeConfig, SyncConfig.Default, new MemDb(), BlockTree, SpecProvider, LogManager); @@ -257,7 +263,7 @@ public async Task Build(ISpecProvider? specProvider = null) } } -internal class TestBlockProcessorInterceptor : IBlockProcessor +public class TestBlockProcessorInterceptor : IBlockProcessor { private readonly IBlockProcessor _blockProcessorImplementation; public int DelayMs { get; set; } diff --git a/src/Nethermind/Nethermind.Merge.Plugin.Test/EngineModuleTests.Synchronization.cs b/src/Nethermind/Nethermind.Merge.Plugin.Test/EngineModuleTests.Synchronization.cs index 32d15a54fda..f97848f41dd 100644 --- a/src/Nethermind/Nethermind.Merge.Plugin.Test/EngineModuleTests.Synchronization.cs +++ b/src/Nethermind/Nethermind.Merge.Plugin.Test/EngineModuleTests.Synchronization.cs @@ -202,14 +202,14 @@ public async Task should_return_invalid_lvh_null_on_invalid_blocks_during_the_sy forkchoiceUpdatedResult.Data.PayloadStatus.Status.Should() .Be(nameof(PayloadStatusV1.Syncing).ToUpper()); - ExecutionPayload[] requests = CreateBlockRequestBranch(chain.SpecProvider.GenesisSpec, chain.State, startingNewPayload, TestItem.AddressD, 1); + ExecutionPayload[] requests = CreateBlockRequestBranch(chain, startingNewPayload, TestItem.AddressD, 1); foreach (ExecutionPayload r in requests) { ResultWrapper payloadStatus = await rpc.engine_newPayloadV1(r); payloadStatus.Data.Status.Should().Be(nameof(PayloadStatusV1.Syncing).ToUpper()); } - ExecutionPayload[] invalidRequests = CreateBlockRequestBranch(chain.SpecProvider.GenesisSpec, chain.State, requests[0], TestItem.AddressD, 1); + ExecutionPayload[] invalidRequests = CreateBlockRequestBranch(chain, requests[0], TestItem.AddressD, 1); foreach (ExecutionPayload r in invalidRequests) { r.TryGetBlock(out Block? newBlock); @@ -229,7 +229,7 @@ public async Task newPayloadV1_can_insert_blocks_from_cache_when_syncing() Keccak startingHead = chain.BlockTree.HeadHash; ExecutionPayload parentBlockRequest = new(Build.A.Block.WithNumber(2).TestObject); - ExecutionPayload[] requests = CreateBlockRequestBranch(chain.SpecProvider.GenesisSpec, chain.State, parentBlockRequest, Address.Zero, 7); + ExecutionPayload[] requests = CreateBlockRequestBranch(chain, parentBlockRequest, Address.Zero, 7); ResultWrapper payloadStatus; foreach (ExecutionPayload r in requests) { @@ -293,7 +293,7 @@ public async Task first_new_payload_set_beacon_main_chain() await rpc.engine_forkchoiceUpdatedV1(forkchoiceStateV1); forkchoiceUpdatedResult.Data.PayloadStatus.Status.Should() .Be(nameof(PayloadStatusV1.Syncing).ToUpper()); - ExecutionPayload[] requests = CreateBlockRequestBranch(chain.SpecProvider.GenesisSpec, chain.State, startingNewPayload, Address.Zero, 4); + ExecutionPayload[] requests = CreateBlockRequestBranch(chain, startingNewPayload, Address.Zero, 4); foreach (ExecutionPayload r in requests) { ResultWrapper payloadStatus = await rpc.engine_newPayloadV1(r); @@ -334,7 +334,7 @@ public async Task repeated_new_payloads_do_not_change_metadata() await rpc.engine_forkchoiceUpdatedV1(forkchoiceStateV1); forkchoiceUpdatedResult.Data.PayloadStatus.Status.Should() .Be(nameof(PayloadStatusV1.Syncing).ToUpper()); - ExecutionPayload[] requests = CreateBlockRequestBranch(chain.SpecProvider.GenesisSpec, chain.State, startingNewPayload, Address.Zero, 4); + ExecutionPayload[] requests = CreateBlockRequestBranch(chain, startingNewPayload, Address.Zero, 4); foreach (ExecutionPayload r in requests) { ResultWrapper payloadStatus = await rpc.engine_newPayloadV1(r); @@ -492,7 +492,7 @@ public async Task second_new_payload_should_not_set_beacon_main_chain() await rpc.engine_forkchoiceUpdatedV1(forkchoiceStateV1); forkchoiceUpdatedResult.Data.PayloadStatus.Status.Should() .Be(nameof(PayloadStatusV1.Syncing).ToUpper()); - ExecutionPayload[] requests = CreateBlockRequestBranch(chain.SpecProvider.GenesisSpec, chain.State, startingNewPayload, Address.Zero, 4); + ExecutionPayload[] requests = CreateBlockRequestBranch(chain, startingNewPayload, Address.Zero, 4); foreach (ExecutionPayload r in requests) { ResultWrapper payloadStatus = await rpc.engine_newPayloadV1(r); @@ -503,7 +503,7 @@ public async Task second_new_payload_should_not_set_beacon_main_chain() lvl!.BlockInfos[0].Metadata.Should().Be(BlockMetadata.BeaconBody | BlockMetadata.BeaconHeader | BlockMetadata.BeaconMainChain); } - ExecutionPayload[] secondNewPayloads = CreateBlockRequestBranch(chain.SpecProvider.GenesisSpec, chain.State, startingNewPayload, TestItem.AddressD, 4); + ExecutionPayload[] secondNewPayloads = CreateBlockRequestBranch(chain, startingNewPayload, TestItem.AddressD, 4); foreach (ExecutionPayload r in secondNewPayloads) { ResultWrapper payloadStatus = await rpc.engine_newPayloadV1(r); @@ -549,13 +549,13 @@ public async Task should_reorg_during_the_sync(int initialChainPayloadsCount, in await rpc.engine_newPayloadV1(startingNewPayload); ForkchoiceStateV1 forkchoiceStateV1 = new(block.Hash!, startingHead, startingHead); await rpc.engine_forkchoiceUpdatedV1(forkchoiceStateV1); - ExecutionPayload[] initialBranchPayloads = CreateBlockRequestBranch(chain.SpecProvider.GenesisSpec, chain.State, startingNewPayload, Address.Zero, initialChainPayloadsCount); + ExecutionPayload[] initialBranchPayloads = CreateBlockRequestBranch(chain, startingNewPayload, Address.Zero, initialChainPayloadsCount); foreach (ExecutionPayload r in initialBranchPayloads) { await rpc.engine_newPayloadV1(r); } - ExecutionPayload[] newBranchPayloads = CreateBlockRequestBranch(chain.SpecProvider.GenesisSpec, chain.State, startingNewPayload, TestItem.AddressD, reorgedChainPayloadCount); + ExecutionPayload[] newBranchPayloads = CreateBlockRequestBranch(chain, startingNewPayload, TestItem.AddressD, reorgedChainPayloadCount); foreach (ExecutionPayload r in newBranchPayloads) { await rpc.engine_newPayloadV1(r); @@ -586,7 +586,7 @@ public async Task Blocks_from_cache_inserted_when_fast_headers_sync_finish_befor using MergeTestBlockchain chain = await CreateBlockchain(); Keccak startingHead = chain.BlockTree.HeadHash; IEngineRpcModule rpc = CreateEngineModule(chain); - ExecutionPayload[] requests = CreateBlockRequestBranch(chain.SpecProvider.GenesisSpec, chain.State, new ExecutionPayload(chain.BlockTree.Head!), Address.Zero, 7); + ExecutionPayload[] requests = CreateBlockRequestBranch(chain, new ExecutionPayload(chain.BlockTree.Head!), Address.Zero, 7); ResultWrapper payloadStatus; for (int i = 4; i < requests.Length - 1; i++) @@ -638,13 +638,13 @@ public async Task Maintain_correct_pointers_for_beacon_sync_in_archive_sync() Block[] missingBlocks = new Block[gap]; for (int i = 0; i < gap; i++) { - headBlockRequest = CreateBlockRequest(chain.SpecProvider.GenesisSpec, chain.State, headBlockRequest, Address.Zero); + headBlockRequest = CreateBlockRequest(chain, headBlockRequest, Address.Zero); headBlockRequest.TryGetBlock(out Block? block); missingBlocks[i] = block!; } // setting up beacon pivot - ExecutionPayload pivotRequest = CreateBlockRequest(chain.SpecProvider.GenesisSpec, chain.State, headBlockRequest, Address.Zero); + ExecutionPayload pivotRequest = CreateBlockRequest(chain, headBlockRequest, Address.Zero); ResultWrapper payloadStatus = await rpc.engine_newPayloadV1(pivotRequest); payloadStatus.Data.Status.Should().Be(nameof(PayloadStatusV1.Syncing).ToUpper()); pivotRequest.TryGetBlock(out Block? pivotBlock); @@ -666,7 +666,7 @@ public async Task Maintain_correct_pointers_for_beacon_sync_in_archive_sync() forkchoiceUpdatedResult.Data.PayloadStatus.Status.Should() .Be(nameof(PayloadStatusV1.Syncing).ToUpper()); // trigger insertion of blocks in cache into block tree by adding new block - ExecutionPayload bestBeaconBlockRequest = CreateBlockRequest(chain.SpecProvider.GenesisSpec, chain.State, pivotRequest, Address.Zero); + ExecutionPayload bestBeaconBlockRequest = CreateBlockRequest(chain, pivotRequest, Address.Zero); payloadStatus = await rpc.engine_newPayloadV1(bestBeaconBlockRequest); payloadStatus.Data.Status.Should().Be(nameof(PayloadStatusV1.Syncing).ToUpper()); // simulate headers sync by inserting 3 headers from pivot backwards @@ -720,7 +720,7 @@ public async Task Maintain_correct_pointers_for_beacon_sync_in_archive_sync() await bestBlockProcessed.WaitAsync(); // beacon sync should be finished, eventually - bestBeaconBlockRequest = CreateBlockRequest(chain.SpecProvider.GenesisSpec, chain.State, bestBeaconBlockRequest, Address.Zero); + bestBeaconBlockRequest = CreateBlockRequest(chain, bestBeaconBlockRequest, Address.Zero); Assert.That( () => rpc.engine_newPayloadV1(bestBeaconBlockRequest).Result.Data.Status, Is.EqualTo(PayloadStatus.Valid).After(1000, 100) @@ -796,9 +796,9 @@ public async Task Maintain_correct_pointers_for_beacon_sync_in_fast_sync() // create block gap from fast sync pivot int gap = 7; ExecutionPayload[] requests = - CreateBlockRequestBranch(chain.SpecProvider.GenesisSpec, chain.State, new ExecutionPayload(syncedBlockTree.Head!), Address.Zero, gap); + CreateBlockRequestBranch(chain, new ExecutionPayload(syncedBlockTree.Head!), Address.Zero, gap); // setting up beacon pivot - ExecutionPayload pivotRequest = CreateBlockRequest(chain.SpecProvider.GenesisSpec, chain.State, requests[^1], Address.Zero); + ExecutionPayload pivotRequest = CreateBlockRequest(chain, requests[^1], Address.Zero); ResultWrapper payloadStatus = await rpc.engine_newPayloadV1(pivotRequest); payloadStatus.Data.Status.Should().Be(nameof(PayloadStatusV1.Syncing).ToUpper()); pivotRequest.TryGetBlock(out Block? pivotBlock); @@ -821,7 +821,7 @@ public async Task Maintain_correct_pointers_for_beacon_sync_in_fast_sync() forkchoiceUpdatedResult.Data.PayloadStatus.Status.Should() .Be(nameof(PayloadStatusV1.Syncing).ToUpper()); // trigger insertion of blocks in cache into block tree by adding new block - ExecutionPayload bestBeaconBlockRequest = CreateBlockRequest(chain.SpecProvider.GenesisSpec, chain.State, pivotRequest, Address.Zero); + ExecutionPayload bestBeaconBlockRequest = CreateBlockRequest(chain, pivotRequest, Address.Zero); payloadStatus = await rpc.engine_newPayloadV1(bestBeaconBlockRequest); payloadStatus.Data.Status.Should().Be(nameof(PayloadStatusV1.Syncing).ToUpper()); // fill in beacon headers until fast headers pivot @@ -855,12 +855,12 @@ public async Task Invalid_block_can_create_invalid_best_state_issue_but_recalcul chain.BlockTree.HeadHash.Should().Be(lastHash); // send newPayload - ExecutionPayload validBlockOnTopOfHead = CreateBlockRequest(chain.SpecProvider.GenesisSpec, chain.State, CreateParentBlockRequestOnHead(chain.BlockTree), TestItem.AddressD); + ExecutionPayload validBlockOnTopOfHead = CreateBlockRequest(chain, CreateParentBlockRequestOnHead(chain.BlockTree), TestItem.AddressD); PayloadStatusV1 payloadStatusResponse = (await rpc.engine_newPayloadV1(validBlockOnTopOfHead)).Data; payloadStatusResponse.Status.Should().Be(PayloadStatus.Valid); // send block with invalid state root - ExecutionPayload blockWithInvalidStateRoot = CreateBlockRequest(chain.SpecProvider.GenesisSpec, chain.State, validBlockOnTopOfHead, TestItem.AddressA); + ExecutionPayload blockWithInvalidStateRoot = CreateBlockRequest(chain, validBlockOnTopOfHead, TestItem.AddressA); blockWithInvalidStateRoot.StateRoot = TestItem.KeccakB; TryCalculateHash(blockWithInvalidStateRoot, out Keccak? hash); blockWithInvalidStateRoot.BlockHash = hash; @@ -892,12 +892,12 @@ public async Task MultiSyncModeSelector_should_fix_block_tree_levels_if_needed() chain.BlockTree.HeadHash.Should().Be(lastHash); // send newPayload - ExecutionPayload validBlockOnTopOfHead = CreateBlockRequest(chain.SpecProvider.GenesisSpec, chain.State, CreateParentBlockRequestOnHead(chain.BlockTree), TestItem.AddressD); + ExecutionPayload validBlockOnTopOfHead = CreateBlockRequest(chain, CreateParentBlockRequestOnHead(chain.BlockTree), TestItem.AddressD); PayloadStatusV1 payloadStatusResponse = (await rpc.engine_newPayloadV1(validBlockOnTopOfHead)).Data; payloadStatusResponse.Status.Should().Be(PayloadStatus.Valid); // send block with invalid state root - ExecutionPayload blockWithInvalidStateRoot = CreateBlockRequest(chain.SpecProvider.GenesisSpec, chain.State, validBlockOnTopOfHead, TestItem.AddressA); + ExecutionPayload blockWithInvalidStateRoot = CreateBlockRequest(chain, validBlockOnTopOfHead, TestItem.AddressA); blockWithInvalidStateRoot.StateRoot = TestItem.KeccakB; TryCalculateHash(blockWithInvalidStateRoot, out Keccak? hash); blockWithInvalidStateRoot.BlockHash = hash; diff --git a/src/Nethermind/Nethermind.Merge.Plugin.Test/EngineModuleTests.V1.cs b/src/Nethermind/Nethermind.Merge.Plugin.Test/EngineModuleTests.V1.cs index 878cd9a4665..1dd1e1d5a6f 100644 --- a/src/Nethermind/Nethermind.Merge.Plugin.Test/EngineModuleTests.V1.cs +++ b/src/Nethermind/Nethermind.Merge.Plugin.Test/EngineModuleTests.V1.cs @@ -450,7 +450,7 @@ public async Task executePayloadV1_result_is_fail_when_blockchainprocessor_repor ((TestBlockProcessorInterceptor)chain.BlockProcessor).ExceptionToThrow = new Exception("unxpected exception"); - ExecutionPayload executionPayload = CreateBlockRequest(chain.SpecProvider.GenesisSpec, chain.State, CreateParentBlockRequestOnHead(chain.BlockTree), TestItem.AddressD); + ExecutionPayload executionPayload = CreateBlockRequest(chain, CreateParentBlockRequestOnHead(chain.BlockTree), TestItem.AddressD); ResultWrapper resultWrapper = await rpc.engine_newPayloadV1(executionPayload); resultWrapper.Result.ResultType.Should().Be(ResultType.Failure); } @@ -786,7 +786,7 @@ public async Task executePayloadV1_should_not_accept_blocks_with_incorrect_ttd(l TerminalTotalDifficulty = $"{terminalTotalDifficulty}" }); IEngineRpcModule rpc = CreateEngineModule(chain); - ExecutionPayload executionPayload = CreateBlockRequest(chain.SpecProvider.GenesisSpec, chain.State, CreateParentBlockRequestOnHead(chain.BlockTree), TestItem.AddressD); + ExecutionPayload executionPayload = CreateBlockRequest(chain, CreateParentBlockRequestOnHead(chain.BlockTree), TestItem.AddressD); ResultWrapper resultWrapper = await rpc.engine_newPayloadV1(executionPayload); resultWrapper.Data.Status.Should().Be(PayloadStatus.Invalid); resultWrapper.Data.LatestValidHash.Should().Be(Keccak.Zero); @@ -903,7 +903,7 @@ public async Task executePayloadV1_accepts_first_block() { using MergeTestBlockchain chain = await CreateBlockchain(); IEngineRpcModule rpc = CreateEngineModule(chain); - ExecutionPayload executionPayload = CreateBlockRequest(chain.SpecProvider.GenesisSpec, chain.State, CreateParentBlockRequestOnHead(chain.BlockTree), TestItem.AddressD); + ExecutionPayload executionPayload = CreateBlockRequest(chain, CreateParentBlockRequestOnHead(chain.BlockTree), TestItem.AddressD); ResultWrapper resultWrapper = await rpc.engine_newPayloadV1(executionPayload); resultWrapper.Data.Status.Should().Be(PayloadStatus.Valid); new ExecutionPayload(chain.BlockTree.BestSuggestedBody!).Should().BeEquivalentTo(executionPayload); @@ -915,8 +915,7 @@ public async Task executePayloadV1_calculate_hash_for_cached_blocks() using MergeTestBlockchain chain = await CreateBlockchain(); IEngineRpcModule rpc = CreateEngineModule(chain); ExecutionPayload executionPayload = CreateBlockRequest( - chain.SpecProvider.GenesisSpec, chain.State, - CreateParentBlockRequestOnHead(chain.BlockTree), + chain, CreateParentBlockRequestOnHead(chain.BlockTree), TestItem.AddressD); ResultWrapper resultWrapper = await rpc.engine_newPayloadV1(executionPayload); resultWrapper.Data.Status.Should().Be(PayloadStatus.Valid); @@ -1001,7 +1000,7 @@ public async Task newPayloadV1_should_return_accepted_for_side_branch() { using MergeTestBlockchain chain = await CreateBlockchain(); IEngineRpcModule rpc = CreateEngineModule(chain); - ExecutionPayload executionPayload = CreateBlockRequest(chain.SpecProvider.GenesisSpec, chain.State, CreateParentBlockRequestOnHead(chain.BlockTree), TestItem.AddressD); + ExecutionPayload executionPayload = CreateBlockRequest(chain, CreateParentBlockRequestOnHead(chain.BlockTree), TestItem.AddressD); ResultWrapper resultWrapper = await rpc.engine_newPayloadV1(executionPayload); resultWrapper.Data.Status.Should().Be(PayloadStatus.Valid); ForkchoiceStateV1 forkChoiceUpdatedRequest = new(executionPayload.BlockHash, executionPayload.BlockHash, executionPayload.BlockHash); @@ -1026,7 +1025,7 @@ public async Task executePayloadV1_processes_passed_transactions(bool moveHead) foreach (ExecutionPayload block in branch) { uint count = 10; - ExecutionPayload executePayloadRequest = CreateBlockRequest(chain.SpecProvider.GenesisSpec, chain.State, block, TestItem.AddressA); + ExecutionPayload executePayloadRequest = CreateBlockRequest(chain, block, TestItem.AddressA); PrivateKey from = TestItem.PrivateKeyB; Address to = TestItem.AddressD; (_, UInt256 toBalanceAfter) = AddTransactions(chain, executePayloadRequest, from, to, count, 1, out BlockHeader? parentHeader); @@ -1063,7 +1062,7 @@ public async Task executePayloadV1_transactions_produce_receipts() foreach (ExecutionPayload block in branch) { uint count = 10; - ExecutionPayload executionPayload = CreateBlockRequest(chain.SpecProvider.GenesisSpec, chain.State, block, TestItem.AddressA); + ExecutionPayload executionPayload = CreateBlockRequest(chain, block, TestItem.AddressA); PrivateKey from = TestItem.PrivateKeyB; Address to = TestItem.AddressD; (_, UInt256 toBalanceAfter) = AddTransactions(chain, executionPayload, from, to, count, 1, out BlockHeader parentHeader); @@ -1216,8 +1215,7 @@ public async Task exchangeTransitionConfiguration_return_with_empty_Nethermind_c private async Task SendNewBlockV1(IEngineRpcModule rpc, MergeTestBlockchain chain) { ExecutionPayload executionPayload = CreateBlockRequest( - chain.SpecProvider.GenesisSpec, chain.State, - CreateParentBlockRequestOnHead(chain.BlockTree), + chain, CreateParentBlockRequestOnHead(chain.BlockTree), TestItem.AddressD); ResultWrapper executePayloadResult = await rpc.engine_newPayloadV1(executionPayload); @@ -1264,8 +1262,7 @@ public async Task repeat_the_same_payload_after_fcu_should_return_valid_and_be_i // Correct new payload ExecutionPayload executionPayloadV11 = CreateBlockRequest( - chain.SpecProvider.GenesisSpec, chain.State, - CreateParentBlockRequestOnHead(chain.BlockTree), + chain, CreateParentBlockRequestOnHead(chain.BlockTree), TestItem.AddressA); ResultWrapper newPayloadResult1 = await rpc.engine_newPayloadV1(executionPayloadV11); newPayloadResult1.Data.Status.Should().Be(PayloadStatus.Valid); @@ -1292,8 +1289,7 @@ public async Task payloadV1_invalid_parent_hash() // Correct new payload ExecutionPayload executionPayloadV11 = CreateBlockRequest( - chain.SpecProvider.GenesisSpec, chain.State, - CreateParentBlockRequestOnHead(chain.BlockTree), + chain, CreateParentBlockRequestOnHead(chain.BlockTree), TestItem.AddressA); ResultWrapper newPayloadResult1 = await rpc.engine_newPayloadV1(executionPayloadV11); newPayloadResult1.Data.Status.Should().Be(PayloadStatus.Valid); @@ -1305,7 +1301,7 @@ public async Task payloadV1_invalid_parent_hash() forkchoiceUpdatedResult1.Data.PayloadStatus.Status.Should().Be(PayloadStatus.Valid); // New payload unknown parent hash - ExecutionPayload executionPayloadV12A = CreateBlockRequest(chain.SpecProvider.GenesisSpec, chain.State, executionPayloadV11, TestItem.AddressA); + ExecutionPayload executionPayloadV12A = CreateBlockRequest(chain, executionPayloadV11, TestItem.AddressA); executionPayloadV12A.ParentHash = TestItem.KeccakB; TryCalculateHash(executionPayloadV12A, out Keccak? hash); executionPayloadV12A.BlockHash = hash; @@ -1320,7 +1316,7 @@ public async Task payloadV1_invalid_parent_hash() forkchoiceUpdatedResult2A.Data.PayloadStatus.Status.Should().Be(PayloadStatus.Syncing); // New payload with correct parent hash - ExecutionPayload executionPayloadV12B = CreateBlockRequest(chain.SpecProvider.GenesisSpec, chain.State, executionPayloadV11, TestItem.AddressA); + ExecutionPayload executionPayloadV12B = CreateBlockRequest(chain, executionPayloadV11, TestItem.AddressA); ResultWrapper newPayloadResult2B = await rpc.engine_newPayloadV1(executionPayloadV12B); newPayloadResult2B.Data.Status.Should().Be(PayloadStatus.Valid); @@ -1331,7 +1327,7 @@ public async Task payloadV1_invalid_parent_hash() forkchoiceUpdatedResult2B.Data.PayloadStatus.Status.Should().Be(PayloadStatus.Valid); // New payload unknown parent hash - ExecutionPayload executionPayloadV13A = CreateBlockRequest(chain.SpecProvider.GenesisSpec, chain.State, executionPayloadV12A, TestItem.AddressA); + ExecutionPayload executionPayloadV13A = CreateBlockRequest(chain, executionPayloadV12A, TestItem.AddressA); ResultWrapper newPayloadResult3A = await rpc.engine_newPayloadV1(executionPayloadV13A); newPayloadResult3A.Data.Status.Should().Be(PayloadStatus.Syncing); @@ -1342,7 +1338,7 @@ public async Task payloadV1_invalid_parent_hash() ResultWrapper forkchoiceUpdatedResult3A = await rpc.engine_forkchoiceUpdatedV1(forkChoiceState3A); forkchoiceUpdatedResult3A.Data.PayloadStatus.Status.Should().Be(PayloadStatus.Syncing); - ExecutionPayload executionPayloadV13B = CreateBlockRequest(chain.SpecProvider.GenesisSpec, chain.State, executionPayloadV12B, TestItem.AddressA); + ExecutionPayload executionPayloadV13B = CreateBlockRequest(chain, executionPayloadV12B, TestItem.AddressA); ResultWrapper newPayloadResult3B = await rpc.engine_newPayloadV1(executionPayloadV13B); newPayloadResult3B.Data.Status.Should().Be(PayloadStatus.Valid); @@ -1361,8 +1357,7 @@ public async Task inconsistent_finalized_hash() IEngineRpcModule rpc = CreateEngineModule(chain); ExecutionPayload blockRequestResult1 = CreateBlockRequest( - chain.SpecProvider.GenesisSpec, chain.State, - CreateParentBlockRequestOnHead(chain.BlockTree), + chain, CreateParentBlockRequestOnHead(chain.BlockTree), TestItem.AddressA); ResultWrapper newPayloadResult1 = await rpc.engine_newPayloadV1(blockRequestResult1); newPayloadResult1.Data.Status.Should().Be(PayloadStatus.Valid); @@ -1372,15 +1367,15 @@ public async Task inconsistent_finalized_hash() ResultWrapper forkchoiceUpdatedResult1 = await rpc.engine_forkchoiceUpdatedV1(forkChoiceState1); forkchoiceUpdatedResult1.Data.PayloadStatus.Status.Should().Be(PayloadStatus.Valid); - ExecutionPayload blockRequestResult2A = CreateBlockRequest(chain.SpecProvider.GenesisSpec, chain.State, blockRequestResult1, TestItem.AddressB); + ExecutionPayload blockRequestResult2A = CreateBlockRequest(chain, blockRequestResult1, TestItem.AddressB); ResultWrapper newPayloadResult2A = await rpc.engine_newPayloadV1(blockRequestResult2A); newPayloadResult2A.Data.Status.Should().Be(PayloadStatus.Valid); - ExecutionPayload blockRequestResult2B = CreateBlockRequest(chain.SpecProvider.GenesisSpec, chain.State, blockRequestResult1, TestItem.AddressA); + ExecutionPayload blockRequestResult2B = CreateBlockRequest(chain, blockRequestResult1, TestItem.AddressA); ResultWrapper newPayloadResult2B = await rpc.engine_newPayloadV1(blockRequestResult2B); newPayloadResult2B.Data.Status.Should().Be(PayloadStatus.Valid); - ExecutionPayload blockRequestResult3B = CreateBlockRequest(chain.SpecProvider.GenesisSpec, chain.State, blockRequestResult2B, TestItem.AddressA); + ExecutionPayload blockRequestResult3B = CreateBlockRequest(chain, blockRequestResult2B, TestItem.AddressA); ResultWrapper newPayloadResult3B = await rpc.engine_newPayloadV1(blockRequestResult3B); newPayloadResult3B.Data.Status.Should().Be(PayloadStatus.Valid); @@ -1398,8 +1393,7 @@ public async Task inconsistent_safe_hash() IEngineRpcModule rpc = CreateEngineModule(chain); ExecutionPayload blockRequestResult1 = CreateBlockRequest( - chain.SpecProvider.GenesisSpec, chain.State, - CreateParentBlockRequestOnHead(chain.BlockTree), + chain, CreateParentBlockRequestOnHead(chain.BlockTree), TestItem.AddressA); ResultWrapper newPayloadResult1 = await rpc.engine_newPayloadV1(blockRequestResult1); newPayloadResult1.Data.Status.Should().Be(PayloadStatus.Valid); @@ -1409,15 +1403,15 @@ public async Task inconsistent_safe_hash() ResultWrapper forkchoiceUpdatedResult1 = await rpc.engine_forkchoiceUpdatedV1(forkChoiceState1); forkchoiceUpdatedResult1.Data.PayloadStatus.Status.Should().Be(PayloadStatus.Valid); - ExecutionPayload blockRequestResult2A = CreateBlockRequest(chain.SpecProvider.GenesisSpec, chain.State, blockRequestResult1, TestItem.AddressB); + ExecutionPayload blockRequestResult2A = CreateBlockRequest(chain, blockRequestResult1, TestItem.AddressB); ResultWrapper newPayloadResult2A = await rpc.engine_newPayloadV1(blockRequestResult2A); newPayloadResult2A.Data.Status.Should().Be(PayloadStatus.Valid); - ExecutionPayload blockRequestResult2B = CreateBlockRequest(chain.SpecProvider.GenesisSpec, chain.State, blockRequestResult1, TestItem.AddressA); + ExecutionPayload blockRequestResult2B = CreateBlockRequest(chain, blockRequestResult1, TestItem.AddressA); ResultWrapper newPayloadResult2B = await rpc.engine_newPayloadV1(blockRequestResult2B); newPayloadResult2B.Data.Status.Should().Be(PayloadStatus.Valid); - ExecutionPayload blockRequestResult3B = CreateBlockRequest(chain.SpecProvider.GenesisSpec, chain.State, blockRequestResult2B, TestItem.AddressA); + ExecutionPayload blockRequestResult3B = CreateBlockRequest(chain, blockRequestResult2B, TestItem.AddressA); ResultWrapper newPayloadResult3B = await rpc.engine_newPayloadV1(blockRequestResult3B); newPayloadResult3B.Data.Status.Should().Be(PayloadStatus.Valid); @@ -1455,8 +1449,7 @@ await rpc.engine_forkchoiceUpdatedV1(forkChoiceStateGen, // Add one block ExecutionPayload executionPayloadV11 = CreateBlockRequest( - chain.SpecProvider.GenesisSpec, chain.State, - CreateParentBlockRequestOnHead(chain.BlockTree), + chain, CreateParentBlockRequestOnHead(chain.BlockTree), TestItem.AddressA); executionPayloadV11.PrevRandao = prevRandao1; @@ -1481,8 +1474,7 @@ await rpc.engine_forkchoiceUpdatedV1(forkChoiceState1, { ExecutionPayload executionPayloadV12 = CreateBlockRequest( - chain.SpecProvider.GenesisSpec, chain.State, - executionPayloadV11, + chain, executionPayloadV11, TestItem.AddressA); executionPayloadV12.PrevRandao = prevRandao3; @@ -1505,10 +1497,7 @@ await rpc.engine_forkchoiceUpdatedV1(forkChoiceState1, // re-org { - ExecutionPayload executionPayloadV13 = CreateBlockRequest( - chain.SpecProvider.GenesisSpec, chain.State, - executionPayloadV11, - TestItem.AddressA); + ExecutionPayload executionPayloadV13 = CreateBlockRequest(chain, executionPayloadV11, TestItem.AddressA); executionPayloadV13.PrevRandao = prevRandao2; diff --git a/src/Nethermind/Nethermind.Merge.Plugin.Test/EngineModuleTests.V2.cs b/src/Nethermind/Nethermind.Merge.Plugin.Test/EngineModuleTests.V2.cs index faf7149f163..88afacbe088 100644 --- a/src/Nethermind/Nethermind.Merge.Plugin.Test/EngineModuleTests.V2.cs +++ b/src/Nethermind/Nethermind.Merge.Plugin.Test/EngineModuleTests.V2.cs @@ -637,7 +637,8 @@ public async Task executePayloadV2_works_correctly_when_0_withdrawals_applied(( { using MergeTestBlockchain chain = await CreateBlockchain(input.ReleaseSpec); IEngineRpcModule rpc = CreateEngineModule(chain); - ExecutionPayload executionPayload = CreateBlockRequest(chain.SpecProvider.GenesisSpec, chain.State, CreateParentBlockRequestOnHead(chain.BlockTree), + ExecutionPayload executionPayload = CreateBlockRequest(chain, + CreateParentBlockRequestOnHead(chain.BlockTree), TestItem.AddressD, input.Withdrawals); ResultWrapper resultWrapper = await rpc.engine_newPayloadV2(executionPayload); @@ -706,7 +707,7 @@ public virtual async Task Should_handle_withdrawals_transition_when_Shanghai_for // Block without withdrawals, Timestamp = 2 ExecutionPayload executionPayload = - CreateBlockRequest(chain.SpecProvider.GenesisSpec, chain.State, CreateParentBlockRequestOnHead(chain.BlockTree), TestItem.AddressD); + CreateBlockRequest(chain, CreateParentBlockRequestOnHead(chain.BlockTree), TestItem.AddressD); ResultWrapper resultWrapper = await rpc.engine_newPayloadV2(executionPayload); resultWrapper.Data.Status.Should().Be(PayloadStatus.Valid); @@ -872,8 +873,7 @@ private async Task BuildAndSendNewBlockV2( private async Task SendNewBlockV2(IEngineRpcModule rpc, MergeTestBlockchain chain, IList? withdrawals) { - ExecutionPayload executionPayload = CreateBlockRequest(chain.SpecProvider.GenesisSpec, chain.State, - CreateParentBlockRequestOnHead(chain.BlockTree), TestItem.AddressD, withdrawals); + ExecutionPayload executionPayload = CreateBlockRequest(chain, CreateParentBlockRequestOnHead(chain.BlockTree), TestItem.AddressD, withdrawals); ResultWrapper executePayloadResult = await rpc.engine_newPayloadV2(executionPayload); executePayloadResult.Data.Status.Should().Be(PayloadStatus.Valid); diff --git a/src/Nethermind/Nethermind.Merge.Plugin.Test/EngineModuleTests.V3.cs b/src/Nethermind/Nethermind.Merge.Plugin.Test/EngineModuleTests.V3.cs index ee8525f200e..43b935389f2 100644 --- a/src/Nethermind/Nethermind.Merge.Plugin.Test/EngineModuleTests.V3.cs +++ b/src/Nethermind/Nethermind.Merge.Plugin.Test/EngineModuleTests.V3.cs @@ -8,6 +8,7 @@ using System.Threading; using System.Threading.Tasks; using FluentAssertions; +using k8s.Models; using Nethermind.Consensus.Producers; using Nethermind.Core; using Nethermind.Core.Crypto; @@ -25,6 +26,7 @@ using Nethermind.Merge.Plugin.Handlers; using Nethermind.Serialization.Json; using Nethermind.Serialization.Rlp; +using Nethermind.Specs; using Nethermind.Specs.Forks; using Newtonsoft.Json.Linq; using NSubstitute; @@ -40,8 +42,7 @@ public async Task NewPayloadV1_should_decline_post_cancun() MergeTestBlockchain chain = await CreateBlockchain(releaseSpec: Cancun.Instance); IEngineRpcModule rpcModule = CreateEngineModule(chain); ExecutionPayload executionPayload = CreateBlockRequest( - chain.SpecProvider.GenesisSpec, chain.State, - CreateParentBlockRequestOnHead(chain.BlockTree), TestItem.AddressD, withdrawals: Array.Empty()); + chain, CreateParentBlockRequestOnHead(chain.BlockTree), TestItem.AddressD, withdrawals: Array.Empty()); ResultWrapper result = await rpcModule.engine_newPayloadV1(executionPayload); @@ -54,8 +55,7 @@ public async Task NewPayloadV2_should_decline_post_cancun() MergeTestBlockchain chain = await CreateBlockchain(releaseSpec: Cancun.Instance); IEngineRpcModule rpcModule = CreateEngineModule(chain); ExecutionPayload executionPayload = CreateBlockRequest( - chain.SpecProvider.GenesisSpec, chain.State, - CreateParentBlockRequestOnHead(chain.BlockTree), TestItem.AddressD, withdrawals: Array.Empty()); + chain, CreateParentBlockRequestOnHead(chain.BlockTree), TestItem.AddressD, withdrawals: Array.Empty()); ResultWrapper result = await rpcModule.engine_newPayloadV2(executionPayload); @@ -68,8 +68,7 @@ public async Task NewPayloadV2_should_decline_pre_cancun_with_cancun_fields MergeTestBlockchain chain = await CreateBlockchain(releaseSpec: Shanghai.Instance); IEngineRpcModule rpcModule = CreateEngineModule(chain); ExecutionPayload executionPayload = CreateBlockRequest( - chain.SpecProvider.GenesisSpec, chain.State, - CreateParentBlockRequestOnHead(chain.BlockTree), TestItem.AddressD, withdrawals: Array.Empty(), + chain, CreateParentBlockRequestOnHead(chain.BlockTree), TestItem.AddressD, withdrawals: Array.Empty(), blobGasUsed: blobGasUsed, excessBlobGas: excessBlobGas, parentBeaconBlockRoot: parentBlockBeaconRoot); ResultWrapper result = await rpcModule.engine_newPayloadV2(executionPayload); @@ -83,8 +82,7 @@ public async Task NewPayloadV3_should_decline_pre_cancun_payloads() MergeTestBlockchain chain = await CreateBlockchain(releaseSpec: Shanghai.Instance); IEngineRpcModule rpcModule = CreateEngineModule(chain); ExecutionPayloadV3 executionPayload = CreateBlockRequestV3( - chain.SpecProvider.GenesisSpec, chain.State, - CreateParentBlockRequestOnHead(chain.BlockTree), TestItem.AddressD, withdrawals: Array.Empty()); + chain, CreateParentBlockRequestOnHead(chain.BlockTree), TestItem.AddressD, withdrawals: Array.Empty()); ResultWrapper result = await rpcModule.engine_newPayloadV3(executionPayload, new byte[0][], executionPayload.ParentBeaconBlockRoot); @@ -94,7 +92,7 @@ public async Task NewPayloadV3_should_decline_pre_cancun_payloads() [Test] public async Task GetPayloadV3_should_decline_pre_cancun_payloads() { - (IEngineRpcModule rpcModule, string payloadId, _) = await BuildAndGetPayloadV3Result(Shanghai.Instance); + (IEngineRpcModule rpcModule, string payloadId, _, _) = await BuildAndGetPayloadV3Result(Shanghai.Instance); ResultWrapper getPayloadResult = await rpcModule.engine_getPayloadV3(Bytes.FromHexString(payloadId)); Assert.That(getPayloadResult.ErrorCode, @@ -104,7 +102,7 @@ public async Task GetPayloadV3_should_decline_pre_cancun_payloads() [Test] public async Task GetPayloadV2_should_decline_post_cancun_payloads() { - (IEngineRpcModule rpcModule, string payloadId, _) = await BuildAndGetPayloadV3Result(Cancun.Instance); + (IEngineRpcModule rpcModule, string payloadId, _, _) = await BuildAndGetPayloadV3Result(Cancun.Instance); ResultWrapper getPayloadResult = await rpcModule.engine_getPayloadV2(Bytes.FromHexString(payloadId)); Assert.That(getPayloadResult.ErrorCode, @@ -132,7 +130,7 @@ public async Task GetPayloadV3_should_fail_on_unknown_payload() [TestCase(4)] public async Task GetPayloadV3_should_return_all_the_blobs(int blobTxCount) { - (IEngineRpcModule rpcModule, string payloadId, _) = await BuildAndGetPayloadV3Result(Cancun.Instance, blobTxCount); + (IEngineRpcModule rpcModule, string payloadId, _, _) = await BuildAndGetPayloadV3Result(Cancun.Instance, blobTxCount); ResultWrapper result = await rpcModule.engine_getPayloadV3(Bytes.FromHexString(payloadId)); BlobsBundleV1 getPayloadResultBlobsBundle = result.Data!.BlobsBundle!; Assert.That(result.Data.ExecutionPayload.BlobGasUsed, Is.EqualTo(BlobGasCalculator.CalculateBlobGas(blobTxCount))); @@ -145,7 +143,7 @@ public async Task GetPayloadV3_should_return_all_the_blobs(int blobTxCount) [TestCase(true, PayloadStatus.Invalid)] public virtual async Task NewPayloadV3_should_decline_mempool_encoding(bool inMempoolForm, string expectedPayloadStatus) { - (IEngineRpcModule rpcModule, string payloadId, Transaction[] transactions) = await BuildAndGetPayloadV3Result(Cancun.Instance, 1); + (IEngineRpcModule rpcModule, string payloadId, Transaction[] transactions, _) = await BuildAndGetPayloadV3Result(Cancun.Instance, 1); ExecutionPayloadV3 payload = (await rpcModule.engine_getPayloadV3(Bytes.FromHexString(payloadId))).Data!.ExecutionPayload; @@ -164,7 +162,7 @@ public virtual async Task NewPayloadV3_should_decline_mempool_encoding(bool inMe [TestCase(true, PayloadStatus.Invalid)] public virtual async Task NewPayloadV3_should_decline_incorrect_blobgasused(bool isBlobGasUsedBroken, string expectedPayloadStatus) { - (IEngineRpcModule prevRpcModule, string payloadId, Transaction[] transactions) = await BuildAndGetPayloadV3Result(Cancun.Instance, 1); + (IEngineRpcModule prevRpcModule, string payloadId, Transaction[] transactions, _) = await BuildAndGetPayloadV3Result(Cancun.Instance, 1); ExecutionPayloadV3 payload = (await prevRpcModule.engine_getPayloadV3(Bytes.FromHexString(payloadId))).Data!.ExecutionPayload; if (isBlobGasUsedBroken) @@ -210,8 +208,7 @@ public async Task NewPayloadV3_should_decline_null_blobversionedhashes() moduleProvider.Register(new SingletonModulePool(new SingletonFactory(rpcModule), true)); ExecutionPayloadV3 executionPayload = CreateBlockRequestV3( - chain.SpecProvider.GenesisSpec, chain.State, - CreateParentBlockRequestOnHead(chain.BlockTree), TestItem.AddressD, withdrawals: Array.Empty(), blobGasUsed: 0, excessBlobGas: 0, parentBeaconBlockRoot: TestItem.KeccakA); + chain, CreateParentBlockRequestOnHead(chain.BlockTree), TestItem.AddressD, withdrawals: Array.Empty(), blobGasUsed: 0, excessBlobGas: 0, parentBeaconBlockRoot: TestItem.KeccakA); return (new(moduleProvider, LimboLogs.Instance, jsonRpcConfig), new(RpcEndpoint.Http), new(), executionPayload); } @@ -368,13 +365,65 @@ public async Task NewPayloadV3_should_verify_blob_versioned_hashes_again (byte[][] blobVersionedHashes, Transaction[] transactions) = BuildTransactionsAndBlobVersionedHashesList(hashesFirstBytes, transactionsAndFirstBytesOfTheirHashes, blockchain.SpecProvider.ChainId); ExecutionPayloadV3 executionPayload = CreateBlockRequestV3( - blockchain.SpecProvider.GenesisSpec, blockchain.State, - CreateParentBlockRequestOnHead(blockchain.BlockTree), TestItem.AddressD, withdrawals: Array.Empty(), 0, 0, transactions: transactions, parentBeaconBlockRoot: Keccak.Zero); + blockchain, CreateParentBlockRequestOnHead(blockchain.BlockTree), TestItem.AddressD, withdrawals: Array.Empty(), 0, 0, transactions: transactions, parentBeaconBlockRoot: Keccak.Zero); ResultWrapper result = await engineRpcModule.engine_newPayloadV3(executionPayload, blobVersionedHashes, Keccak.Zero); return result.Data.Status; } + [Test] + public async Task ForkChoiceUpdated_should_return_invalid_params_but_change_latest_block() + { + (IEngineRpcModule rpcModule, string payloadId, Transaction[] transactions, MergeTestBlockchain chain) = + await BuildAndGetPayloadV3Result(Cancun.Instance, 0); + ExecutionPayloadV3 payload = (await rpcModule.engine_getPayloadV3(Bytes.FromHexString(payloadId))).Data!.ExecutionPayload; + + ForkchoiceStateV1 fcuState = new(payload.BlockHash, payload.BlockHash, payload.BlockHash); + PayloadAttributes payloadAttributes = new() + { + Timestamp = payload.Timestamp + 1, + PrevRandao = Keccak.Zero, + SuggestedFeeRecipient = Address.Zero, + Withdrawals = new List(), + ParentBeaconBlockRoot = null, + }; + + await rpcModule.engine_newPayloadV3(payload, Array.Empty(), payload.ParentBeaconBlockRoot); + ResultWrapper fcuResponse = await rpcModule.engine_forkchoiceUpdatedV3(fcuState, payloadAttributes); + Assert.Multiple(() => + { + Assert.That(fcuResponse.Result.ResultType, Is.EqualTo(ResultType.Failure)); + Assert.That(fcuResponse.ErrorCode, Is.EqualTo(ErrorCodes.InvalidParams)); + Assert.That(chain.BlockTree.Head!.Hash, Is.EqualTo(payload.BlockHash)); + }); + } + + [Test] + public async Task ForkChoiceUpdated_should_return_unsupported_fork_but_change_latest_block() + { + (IEngineRpcModule rpcModule, string payloadId, Transaction[] transactions, MergeTestBlockchain chain) = + await BuildAndGetPayloadV3Result(Cancun.Instance, 0); + ExecutionPayloadV3 payload = (await rpcModule.engine_getPayloadV3(Bytes.FromHexString(payloadId))).Data!.ExecutionPayload; + + ForkchoiceStateV1 fcuState = new(payload.BlockHash, payload.BlockHash, payload.BlockHash); + PayloadAttributes payloadAttributes = new() + { + Timestamp = payload.Timestamp + 1, + PrevRandao = Keccak.Zero, + SuggestedFeeRecipient = Address.Zero, + Withdrawals = new List(), + }; + + await rpcModule.engine_newPayloadV3(payload, Array.Empty(), payload.ParentBeaconBlockRoot); + ResultWrapper fcuResponse = await rpcModule.engine_forkchoiceUpdatedV2(fcuState, payloadAttributes); + Assert.Multiple(() => + { + Assert.That(fcuResponse.Result.ResultType, Is.EqualTo(ResultType.Failure)); + Assert.That(fcuResponse.ErrorCode, Is.EqualTo(ErrorCodes.UnsupportedFork)); + Assert.That(chain.BlockTree.Head!.Hash, Is.EqualTo(payload.BlockHash)); + }); + } + public static IEnumerable ForkchoiceUpdatedV3DeclinedTestCaseSource { get @@ -529,8 +578,7 @@ public static IEnumerable CancunFieldsTestSource private async Task SendNewBlockV3(IEngineRpcModule rpc, MergeTestBlockchain chain, IList? withdrawals) { ExecutionPayloadV3 executionPayload = CreateBlockRequestV3( - chain.SpecProvider.GenesisSpec, chain.State, - CreateParentBlockRequestOnHead(chain.BlockTree), TestItem.AddressD, withdrawals, 0, 0, parentBeaconBlockRoot: TestItem.KeccakE); + chain, CreateParentBlockRequestOnHead(chain.BlockTree), TestItem.AddressD, withdrawals, 0, 0, parentBeaconBlockRoot: TestItem.KeccakE); ResultWrapper executePayloadResult = await rpc.engine_newPayloadV3(executionPayload, Array.Empty(), executionPayload.ParentBeaconBlockRoot); executePayloadResult.Data.Status.Should().Be(PayloadStatus.Valid); @@ -538,7 +586,7 @@ private async Task SendNewBlockV3(IEngineRpcModule rpc, MergeT return executionPayload; } - private async Task<(IEngineRpcModule, string, Transaction[])> BuildAndGetPayloadV3Result( + private async Task<(IEngineRpcModule, string, Transaction[], MergeTestBlockchain chain)> BuildAndGetPayloadV3Result( IReleaseSpec spec, int transactionCount = 0) { MergeTestBlockchain chain = await CreateBlockchain(releaseSpec: spec, null); @@ -573,6 +621,6 @@ private async Task SendNewBlockV3(IEngineRpcModule rpc, MergeT string payloadId = spec.IsBeaconBlockRootAvailable ? rpcModule.engine_forkchoiceUpdatedV3(forkchoiceState, payloadAttributes).Result.Data.PayloadId! : rpcModule.engine_forkchoiceUpdatedV2(forkchoiceState, payloadAttributes).Result.Data.PayloadId!; - return (rpcModule, payloadId, txs); + return (rpcModule, payloadId, txs, chain); } } diff --git a/src/Nethermind/Nethermind.Merge.Plugin/EngineRpcModule.Paris.cs b/src/Nethermind/Nethermind.Merge.Plugin/EngineRpcModule.Paris.cs index ac4514765d9..f444d926b2d 100644 --- a/src/Nethermind/Nethermind.Merge.Plugin/EngineRpcModule.Paris.cs +++ b/src/Nethermind/Nethermind.Merge.Plugin/EngineRpcModule.Paris.cs @@ -39,21 +39,12 @@ public async Task> engine_newPayloadV1(ExecutionP private async Task> ForkchoiceUpdated(ForkchoiceStateV1 forkchoiceState, PayloadAttributes? payloadAttributes, int version) { - string? error = null; - switch (payloadAttributes?.Validate(_specProvider, version, out error)) - { - case PayloadAttributesValidationResult.InvalidParams: - return ResultWrapper.Fail(error!, ErrorCodes.InvalidParams); - case PayloadAttributesValidationResult.UnsupportedFork: - return ResultWrapper.Fail(error!, ErrorCodes.UnsupportedFork); - } - if (await _locker.WaitAsync(_timeout)) { Stopwatch watch = Stopwatch.StartNew(); try { - return await _forkchoiceUpdatedV1Handler.Handle(forkchoiceState, payloadAttributes); + return await _forkchoiceUpdatedV1Handler.Handle(forkchoiceState, payloadAttributes, version); } finally { diff --git a/src/Nethermind/Nethermind.Merge.Plugin/Handlers/ForkchoiceUpdatedHandler.cs b/src/Nethermind/Nethermind.Merge.Plugin/Handlers/ForkchoiceUpdatedHandler.cs index e332eb2d5af..6dfec16e0a5 100644 --- a/src/Nethermind/Nethermind.Merge.Plugin/Handlers/ForkchoiceUpdatedHandler.cs +++ b/src/Nethermind/Nethermind.Merge.Plugin/Handlers/ForkchoiceUpdatedHandler.cs @@ -11,6 +11,7 @@ using Nethermind.Consensus.Producers; using Nethermind.Core; using Nethermind.Core.Crypto; +using Nethermind.Core.Specs; using Nethermind.Crypto; using Nethermind.JsonRpc; using Nethermind.Logging; @@ -42,6 +43,7 @@ public class ForkchoiceUpdatedHandler : IForkchoiceUpdatedHandler private readonly IBeaconPivot _beaconPivot; private readonly ILogger _logger; private readonly IPeerRefresher _peerRefresher; + private readonly ISpecProvider _specProvider; public ForkchoiceUpdatedHandler( IBlockTree blockTree, @@ -54,6 +56,7 @@ public ForkchoiceUpdatedHandler( IMergeSyncController mergeSyncController, IBeaconPivot beaconPivot, IPeerRefresher peerRefresher, + ISpecProvider specProvider, ILogManager logManager) { _blockTree = blockTree ?? throw new ArgumentNullException(nameof(blockTree)); @@ -66,10 +69,22 @@ public ForkchoiceUpdatedHandler( _mergeSyncController = mergeSyncController; _beaconPivot = beaconPivot; _peerRefresher = peerRefresher; + _specProvider = specProvider; _logger = logManager.GetClassLogger(); } - public Task> Handle(ForkchoiceStateV1 forkchoiceState, PayloadAttributes? payloadAttributes) + public Task> Handle(ForkchoiceStateV1 forkchoiceState, PayloadAttributes? payloadAttributes, int version) + { + Block? newHeadBlock = GetBlock(forkchoiceState.HeadBlockHash); + ResultWrapper? payloadUpdateResult = ApplyForkchoiceUpdate(newHeadBlock, forkchoiceState, payloadAttributes); + return Task.FromResult( + ValidateAttributes(payloadAttributes, version) ?? + payloadUpdateResult ?? + StartBuildingPayload(newHeadBlock!, forkchoiceState, payloadAttributes) + ); + } + + public ResultWrapper? ApplyForkchoiceUpdate(Block? newHeadBlock, ForkchoiceStateV1 forkchoiceState, PayloadAttributes? payloadAttributes) { if (_invalidChainTracker.IsOnKnownInvalidChain(forkchoiceState.HeadBlockHash, out Keccak? lastValidHash)) { @@ -77,7 +92,6 @@ public Task> Handle(ForkchoiceStateV1 f return ForkchoiceUpdatedV1Result.Invalid(lastValidHash); } - Block? newHeadBlock = GetBlock(forkchoiceState.HeadBlockHash); if (newHeadBlock is null) // if a head is unknown we are syncing { string simpleRequestStr = payloadAttributes is null ? forkchoiceState.ToString() : $"{forkchoiceState} {payloadAttributes}"; @@ -223,6 +237,11 @@ public Task> Handle(ForkchoiceStateV1 f if (_logger.IsInfo) _logger.Info($"Synced chain Head to {newHeadBlock.ToString(Block.Format.Short)}"); } + return null; + } + + public ResultWrapper StartBuildingPayload(Block newHeadBlock, ForkchoiceStateV1 forkchoiceState, PayloadAttributes? payloadAttributes) + { string? payloadId = null; if (payloadAttributes is not null) { @@ -239,12 +258,23 @@ public Task> Handle(ForkchoiceStateV1 f payloadId = _payloadPreparationService.StartPreparingPayload(newHeadBlock.Header, payloadAttributes); } - if (_logger.IsDebug) _logger.Debug($"Valid. Request: {requestStr}."); - _blockTree.ForkChoiceUpdated(forkchoiceState.FinalizedBlockHash, forkchoiceState.SafeBlockHash); return ForkchoiceUpdatedV1Result.Valid(payloadId, forkchoiceState.HeadBlockHash); } + private ResultWrapper? ValidateAttributes(PayloadAttributes? payloadAttributes, int version) + { + string? error = null; + return payloadAttributes?.Validate(_specProvider, version, out error) switch + { + PayloadAttributesValidationResult.InvalidParams => + ResultWrapper.Fail(error!, ErrorCodes.InvalidParams), + PayloadAttributesValidationResult.UnsupportedFork => + ResultWrapper.Fail(error!, ErrorCodes.UnsupportedFork), + _ => null, + }; + } + private void StartNewBeaconHeaderSync(ForkchoiceStateV1 forkchoiceState, Block block, string requestStr) { _mergeSyncController.InitBeaconHeaderSync(block.Header); diff --git a/src/Nethermind/Nethermind.Merge.Plugin/Handlers/IForkchoiceUpdatedHandler.cs b/src/Nethermind/Nethermind.Merge.Plugin/Handlers/IForkchoiceUpdatedHandler.cs index b390eb798af..d3e92a0654d 100644 --- a/src/Nethermind/Nethermind.Merge.Plugin/Handlers/IForkchoiceUpdatedHandler.cs +++ b/src/Nethermind/Nethermind.Merge.Plugin/Handlers/IForkchoiceUpdatedHandler.cs @@ -10,5 +10,5 @@ namespace Nethermind.Merge.Plugin.Handlers; public interface IForkchoiceUpdatedHandler { - Task> Handle(ForkchoiceStateV1 forkchoiceState, PayloadAttributes? payloadAttributes); + Task> Handle(ForkchoiceStateV1 forkchoiceState, PayloadAttributes? payloadAttributes, int fcuVersion); } diff --git a/src/Nethermind/Nethermind.Merge.Plugin/MergePlugin.cs b/src/Nethermind/Nethermind.Merge.Plugin/MergePlugin.cs index 7214b8ceb26..8a3569edd1d 100644 --- a/src/Nethermind/Nethermind.Merge.Plugin/MergePlugin.cs +++ b/src/Nethermind/Nethermind.Merge.Plugin/MergePlugin.cs @@ -335,6 +335,7 @@ public Task InitRpcModules() _beaconSync, _beaconPivot, _peerRefresher, + _api.SpecProvider, _api.LogManager), new GetPayloadBodiesByHashV1Handler(_api.BlockTree, _api.LogManager), new GetPayloadBodiesByRangeV1Handler(_api.BlockTree, _api.LogManager),