diff --git a/src/Nethermind/Nethermind.AccountAbstraction/Source/UserOperationPool.cs b/src/Nethermind/Nethermind.AccountAbstraction/Source/UserOperationPool.cs
index 970dcb46f97..9e689610558 100644
--- a/src/Nethermind/Nethermind.AccountAbstraction/Source/UserOperationPool.cs
+++ b/src/Nethermind/Nethermind.AccountAbstraction/Source/UserOperationPool.cs
@@ -1,19 +1,19 @@
// Copyright (c) 2021 Demerzel Solutions Limited
// This file is part of the Nethermind library.
-//
+//
// The Nethermind library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
-//
+//
// The Nethermind library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
-//
+//
// You should have received a copy of the GNU Lesser General Public License
// along with the Nethermind. If not, see .
-//
+//
using System;
using System.Collections.Concurrent;
@@ -65,11 +65,11 @@ public class UserOperationPool : IUserOperationPool, IDisposable
private readonly Channel _headBlocksReplacementChannel = Channel.CreateUnbounded(new UnboundedChannelOptions() { SingleReader = true, SingleWriter = true });
private readonly Channel _headBlockChannel = Channel.CreateUnbounded(new UnboundedChannelOptions() { SingleReader = true, SingleWriter = true });
-
+
private readonly ulong _chainId;
private UInt256 _currentBaseFee;
-
+
public UserOperationPool(
IAccountAbstractionConfig accountAbstractionConfig,
IBlockTree blockTree,
@@ -106,7 +106,7 @@ ulong chainId
_userOperationEventTopic = new Keccak("0x33fd4d1f25a5461bea901784a6571de6debc16cd0831932c22c6969cd73ba994");
MemoryAllowance.MemPoolSize = accountAbstractionConfig.UserOperationPoolSize;
-
+
_blockTree.BlockAddedToMain += OnBlockAdded;
_blockTree.NewHeadBlock += OnNewHead;
@@ -129,7 +129,7 @@ private void OnBlockAdded(object? sender, BlockReplacementEventArgs e)
$"Couldn't correctly add or remove user operations from UserOperationPool after processing block {e.Block!.ToString(Block.Format.FullHashAndNumber)}.", exception);
}
}
-
+
private void OnNewHead(object? sender, BlockEventArgs e)
{
try
@@ -170,7 +170,7 @@ private void ProcessNewReplacementBlocks()
}
});
}
-
+
private void ProcessNewHeadBlocks()
{
Task.Factory.StartNew(async () =>
@@ -242,14 +242,14 @@ public bool CanInsert(UserOperation userOperation)
}
// we only want to increment opsSeen for ops whose maxFeePerGas passes baseFee
- // else paymasters could be griefed by submitting many ops which might never
+ // else paymasters could be griefed by submitting many ops which might never
// make it on chain but will increase opsSeen
private void IncrementOpsSeenForOpsSurpassingBaseFee()
{
_userOperationSortedPool.UpdatePool(RemoveOpsSurpassingBaseFee);
}
- private IEnumerable<(UserOperation Tx, Action? Change)> RemoveOpsSurpassingBaseFee(Address address, ICollection userOperations)
+ private IEnumerable<(UserOperation Tx, Action? Change)> RemoveOpsSurpassingBaseFee(Address address, IReadOnlyCollection userOperations)
{
foreach (UserOperation op in userOperations)
{
@@ -280,7 +280,7 @@ public ResultWrapper AddUserOperation(UserOperation userOperation)
UserOperationEventArgs userOperationEventArgs = new(userOperation, _entryPointAddress);
NewReceived?.Invoke(this, userOperationEventArgs);
-
+
UpdateCurrentBaseFee();
ResultWrapper result = ValidateUserOperation(userOperation);
if (result.Result == Result.Success)
@@ -295,9 +295,9 @@ public ResultWrapper AddUserOperation(UserOperation userOperation)
_paymasterThrottler.IncrementOpsSeen(userOperation.Paymaster);
}
if (_logger.IsDebug) _logger.Debug($"UserOperation {userOperation.RequestId!} inserted into pool");
- _userOperationBroadcaster.BroadcastOnce(new UserOperationWithEntryPoint(userOperation, _entryPointAddress));
+ _userOperationBroadcaster.BroadcastOnce(new UserOperationWithEntryPoint(userOperation, _entryPointAddress));
NewPending?.Invoke(this, userOperationEventArgs);
-
+
return ResultWrapper.Success(userOperation.RequestId!);
}
@@ -371,7 +371,7 @@ private ResultWrapper ValidateUserOperation(UserOperation userOperation)
{
return ResultWrapper.Fail($"maxFeePerGas must be at least 70% of baseFee to be accepted into pool");
}
-
+
PaymasterStatus paymasterStatus =
_paymasterThrottler.GetPaymasterStatus(userOperation.Paymaster);
diff --git a/src/Nethermind/Nethermind.Core/Collections/DictionarySortedSet.cs b/src/Nethermind/Nethermind.Core/Collections/DictionarySortedSet.cs
index 2640c009363..ad61ee261b5 100644
--- a/src/Nethermind/Nethermind.Core/Collections/DictionarySortedSet.cs
+++ b/src/Nethermind/Nethermind.Core/Collections/DictionarySortedSet.cs
@@ -1,26 +1,26 @@
// Copyright (c) 2021 Demerzel Solutions Limited
// This file is part of the Nethermind library.
-//
+//
// The Nethermind library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
-//
+//
// The Nethermind library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
-//
+//
// You should have received a copy of the GNU Lesser General Public License
// along with the Nethermind. If not, see .
-//
+//
using System.Collections.Generic;
using System.Runtime.Serialization;
namespace Nethermind.Core.Collections
{
- public class DictionarySortedSet : SortedSet>
+ public class DictionarySortedSet : EnhancedSortedSet>
{
public DictionarySortedSet() : base(GetComparer()) { }
@@ -32,12 +32,12 @@ public DictionarySortedSet(IEnumerable> collection) :
public DictionarySortedSet(IEnumerable> collection, IComparer comparer) : base(collection, GetComparer(comparer)) { }
protected DictionarySortedSet(SerializationInfo info, StreamingContext context) : base(info, context) { }
-
- private static IComparer> GetComparer(IComparer? comparer = null) =>
+
+ private static IComparer> GetComparer(IComparer? comparer = null) =>
new KeyValuePairKeyOnlyComparer(comparer ?? Comparer.Default);
-
+
public bool Add(TKey key, TValue value) => Add(new KeyValuePair(key, value));
-
+
#pragma warning disable 8604
// fixed C# 9
public bool Remove(TKey key) => Remove(new KeyValuePair(key, default));
@@ -60,7 +60,7 @@ public bool TryGetValue(TKey key, out TValue value)
#pragma warning restore 8601
return false;
}
-
+
#pragma warning disable 8604
// fixed C# 9
public bool ContainsKey(TKey key) => Contains(new KeyValuePair(key, default));
@@ -75,9 +75,9 @@ public KeyValuePairKeyOnlyComparer(IComparer? keyComparer = null)
_keyComparer = keyComparer ?? Comparer.Default;
}
- public override int Compare(KeyValuePair x, KeyValuePair y)
+ public override int Compare(KeyValuePair x, KeyValuePair y)
=> _keyComparer.Compare(x.Key, y.Key);
}
-
+
}
}
diff --git a/src/Nethermind/Nethermind.Core/Collections/IReadOnlySortedSet.cs b/src/Nethermind/Nethermind.Core/Collections/IReadOnlySortedSet.cs
new file mode 100644
index 00000000000..d0bdeb0d264
--- /dev/null
+++ b/src/Nethermind/Nethermind.Core/Collections/IReadOnlySortedSet.cs
@@ -0,0 +1,26 @@
+// Copyright (c) 2021 Demerzel Solutions Limited
+// This file is part of the Nethermind library.
+//
+// The Nethermind library is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// The Nethermind library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with the Nethermind. If not, see .
+//
+
+using System.Collections.Generic;
+
+namespace Nethermind.Core.Collections;
+
+public interface IReadOnlySortedSet : IReadOnlySet
+{
+ public T? Max { get; }
+ public T? Min { get; }
+}
diff --git a/src/Nethermind/Nethermind.Core/Collections/SortedSet.cs b/src/Nethermind/Nethermind.Core/Collections/SortedSet.cs
new file mode 100644
index 00000000000..39b635f89b6
--- /dev/null
+++ b/src/Nethermind/Nethermind.Core/Collections/SortedSet.cs
@@ -0,0 +1,30 @@
+// Copyright (c) 2021 Demerzel Solutions Limited
+// This file is part of the Nethermind library.
+//
+// The Nethermind library is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// The Nethermind library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with the Nethermind. If not, see .
+//
+
+using System.Collections.Generic;
+using System.Runtime.Serialization;
+
+namespace Nethermind.Core.Collections;
+
+public class EnhancedSortedSet : SortedSet, IReadOnlySortedSet
+{
+ public EnhancedSortedSet() { }
+ public EnhancedSortedSet(IComparer? comparer) : base(comparer) { }
+ public EnhancedSortedSet(IEnumerable collection) : base(collection) { }
+ public EnhancedSortedSet(IEnumerable collection, IComparer? comparer) : base(collection, comparer) { }
+ protected EnhancedSortedSet(SerializationInfo info, StreamingContext context) : base(info, context) { }
+}
diff --git a/src/Nethermind/Nethermind.Facade.Test/Proxy/EthJsonRpcClientProxyTests.cs b/src/Nethermind/Nethermind.Facade.Test/Proxy/EthJsonRpcClientProxyTests.cs
index a3900d56db7..159e1cfd2ff 100644
--- a/src/Nethermind/Nethermind.Facade.Test/Proxy/EthJsonRpcClientProxyTests.cs
+++ b/src/Nethermind/Nethermind.Facade.Test/Proxy/EthJsonRpcClientProxyTests.cs
@@ -1,16 +1,16 @@
// Copyright (c) 2021 Demerzel Solutions Limited
// This file is part of the Nethermind library.
-//
+//
// The Nethermind library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
-//
+//
// The Nethermind library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
-//
+//
// You should have received a copy of the GNU Lesser General Public License
// along with the Nethermind. If not, see .
@@ -75,7 +75,7 @@ public async Task eth_getTransactionCount_should_invoke_client_method()
var address = TestItem.AddressA;
var blockParameter = BlockParameterModel.Latest;
await _proxy.eth_getTransactionCount(address, blockParameter);
- await _client.Received().SendAsync(nameof(_proxy.eth_getTransactionCount),
+ await _client.Received().SendAsync(nameof(_proxy.eth_getTransactionCount),
address, blockParameter.Type);
}
@@ -114,7 +114,7 @@ public async Task eth_getTransactionByHash_should_invoke_client_method()
await _proxy.eth_getTransactionByHash(hash);
await _client.Received().SendAsync(nameof(_proxy.eth_getTransactionByHash), hash);
}
-
+
[Test]
public async Task eth_pendingTransactions_should_invoke_client_method()
{
diff --git a/src/Nethermind/Nethermind.Facade/Proxy/EthJsonRpcClientProxy.cs b/src/Nethermind/Nethermind.Facade/Proxy/EthJsonRpcClientProxy.cs
index cc21cc0c2b1..e3bd56cb2b3 100644
--- a/src/Nethermind/Nethermind.Facade/Proxy/EthJsonRpcClientProxy.cs
+++ b/src/Nethermind/Nethermind.Facade/Proxy/EthJsonRpcClientProxy.cs
@@ -1,16 +1,16 @@
// Copyright (c) 2021 Demerzel Solutions Limited
// This file is part of the Nethermind library.
-//
+//
// The Nethermind library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
-//
+//
// The Nethermind library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
-//
+//
// You should have received a copy of the GNU Lesser General Public License
// along with the Nethermind. If not, see .
@@ -41,12 +41,12 @@ public Task> eth_chainId()
public Task> eth_getBalance(Address address, BlockParameterModel blockParameter = null)
=> _proxy.SendAsync(nameof(eth_getBalance), address, MapBlockParameter(blockParameter));
- public Task> eth_getTransactionCount(Address address, BlockParameterModel blockParameter = null)
- => _proxy.SendAsync(nameof(eth_getTransactionCount), address, MapBlockParameter(blockParameter));
+ public Task> eth_getTransactionCount(Address address, BlockParameterModel blockParameter = null)
+ => _proxy.SendAsync(nameof(eth_getTransactionCount), address, MapBlockParameter(blockParameter));
public Task> eth_getTransactionReceipt(Keccak transactionHash)
=> _proxy.SendAsync(nameof(eth_getTransactionReceipt), transactionHash);
-
+
public Task> eth_call(CallTransactionModel transaction,
BlockParameterModel blockParameter = null)
=> _proxy.SendAsync(nameof(eth_call), transaction, MapBlockParameter(blockParameter));
@@ -56,7 +56,7 @@ public Task> eth_getCode(Address address, BlockParameterModel
public Task> eth_getTransactionByHash(Keccak transactionHash)
=> _proxy.SendAsync(nameof(eth_getTransactionByHash), transactionHash);
-
+
public Task> eth_pendingTransactions()
=> _proxy.SendAsync(nameof(eth_pendingTransactions));
@@ -65,7 +65,7 @@ public Task> eth_sendRawTransaction(byte[] transaction)
public Task> eth_sendTransaction(TransactionModel transaction)
=> _proxy.SendAsync(nameof(eth_sendTransaction), transaction);
-
+
public Task> eth_estimateGas(TransactionModel transaction, BlockParameterModel blockParameter = null)
=> _proxy.SendAsync(nameof(eth_estimateGas), transaction);
@@ -77,12 +77,12 @@ public Task>> eth_getBlockByNumber(BlockParameterMo
bool returnFullTransactionObjects = false)
=> _proxy.SendAsync>(nameof(eth_getBlockByNumber), MapBlockParameter(blockParameter),
returnFullTransactionObjects);
-
+
public Task>> eth_getBlockByNumberWithTransactionDetails(BlockParameterModel blockParameter,
bool returnFullTransactionObjects = false)
=> _proxy.SendAsync>(nameof(eth_getBlockByNumber), MapBlockParameter(blockParameter),
returnFullTransactionObjects);
-
+
public Task> net_version()
=> _proxy.SendAsync(nameof(net_version));
diff --git a/src/Nethermind/Nethermind.Facade/Proxy/IEthJsonRpcClientProxy.cs b/src/Nethermind/Nethermind.Facade/Proxy/IEthJsonRpcClientProxy.cs
index b75784a3675..1e3a293b21e 100644
--- a/src/Nethermind/Nethermind.Facade/Proxy/IEthJsonRpcClientProxy.cs
+++ b/src/Nethermind/Nethermind.Facade/Proxy/IEthJsonRpcClientProxy.cs
@@ -1,16 +1,16 @@
// Copyright (c) 2021 Demerzel Solutions Limited
// This file is part of the Nethermind library.
-//
+//
// The Nethermind library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
-//
+//
// The Nethermind library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
-//
+//
// You should have received a copy of the GNU Lesser General Public License
// along with the Nethermind. If not, see .
@@ -27,7 +27,7 @@ public interface IEthJsonRpcClientProxy
Task> eth_chainId();
Task> eth_blockNumber();
Task> eth_getBalance(Address address, BlockParameterModel blockParameter = null);
- Task> eth_getTransactionCount(Address address, BlockParameterModel blockParameter = null);
+ Task> eth_getTransactionCount(Address address, BlockParameterModel blockParameter = null);
Task> eth_getTransactionReceipt(Keccak transactionHash);
Task> eth_call(CallTransactionModel transaction, BlockParameterModel blockParameter = null);
Task> eth_getCode(Address address, BlockParameterModel blockParameter = null);
diff --git a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/EthRpcModuleTests.cs b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/EthRpcModuleTests.cs
index f480875eabf..409f5f6893a 100644
--- a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/EthRpcModuleTests.cs
+++ b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/EthRpcModuleTests.cs
@@ -1,16 +1,16 @@
// Copyright (c) 2021 Demerzel Solutions Limited
// This file is part of the Nethermind library.
-//
+//
// The Nethermind library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
-//
+//
// The Nethermind library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
-//
+//
// You should have received a copy of the GNU Lesser General Public License
// along with the Nethermind. If not, see .
@@ -71,7 +71,7 @@ public async Task Eth_get_balance_default_block()
string serialized = ctx.Test.TestEthRpc("eth_getBalance", TestItem.AddressA.Bytes.ToHexString(true));
Assert.AreEqual("{\"jsonrpc\":\"2.0\",\"result\":\"0x3635c9adc5de9f09e5\",\"id\":67}", serialized);
}
-
+
[Test]
public async Task Eth_get_eth_feeHistory()
{
@@ -95,7 +95,7 @@ public async Task Eth_get_transaction_by_hash()
string serialized = ctx.Test.TestEthRpc("eth_getTransactionByHash", ctx.Test.BlockTree.FindHeadBlock()!.Transactions.Last().Hash!.ToString());
Assert.AreEqual("{\"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, serialized.Replace("\"", "\\\""));
}
-
+
[Test]
public async Task eth_maxPriorityFeePerGas_test()
{
@@ -112,7 +112,7 @@ public async Task Eth_pending_transactions()
string serialized = ctx.Test.TestEthRpc("eth_pendingTransactions");
Assert.AreEqual("{\"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, serialized.Replace("\"", "\\\""));
}
-
+
[Test]
public async Task Eth_pending_transactions_1559_tx()
{
@@ -122,7 +122,7 @@ public async Task Eth_pending_transactions_1559_tx()
string serialized = ctx.Test.TestEthRpc("eth_pendingTransactions");
serialized.Contains(addedTx).Should().BeTrue();
}
-
+
[Test]
public async Task Eth_pending_transactions_2930_tx()
{
@@ -172,7 +172,7 @@ public async Task Eth_get_uncle_by_block_hash_and_index(bool eip1559, string exp
ReleaseSpec releaseSpec = new() {IsEip1559Enabled = true, Eip1559TransitionBlock = 1 };
specProvider.GetSpec(Arg.Any()).Returns(releaseSpec);
}
-
+
using Context ctx = await Context.Create();
Block block = Build.A.Block.WithUncles(Build.A.BlockHeader.WithNumber(2).TestObject, Build.A.BlockHeader.TestObject).WithNumber(3).TestObject;
IBlockTree blockTree = Substitute.For();
@@ -189,7 +189,7 @@ public async Task Eth_get_uncle_count_by_block_hash()
string serialized = ctx.Test.TestEthRpc("eth_getUncleCountByBlockHash", ctx.Test.BlockTree.FindHeadBlock()!.Hash!.ToString());
Assert.AreEqual("{\"jsonrpc\":\"2.0\",\"result\":\"0x0\",\"id\":67}", serialized, serialized.Replace("\"", "\\\""));
}
-
+
[Test]
public async Task Eth_get_uncle_count_by_block_number()
{
@@ -200,11 +200,24 @@ public async Task Eth_get_uncle_count_by_block_number()
[TestCase("earliest", "0x0")]
[TestCase("latest", "0x3")]
- [TestCase("pending", "0x3")]
+ [TestCase("pending", "0x4")]
[TestCase("0x0", "0x0")]
public async Task Eth_get_tx_count(string blockParameter, string expectedResult)
{
using Context ctx = await Context.Create();
+
+ // Add two transactions, one with the next nonce (nonce=3) and the second one with a gap in nonce (nonce=5, skipping nonce=4)
+ Transaction txWithNextNonce = Build.A.Transaction.To(TestItem.AddressB)
+ .SignedAndResolved(TestItem.PrivateKeyA).WithValue(0.Ether()).WithNonce(3).TestObject;
+ 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);
+ ValueTask<(Keccak? Hash, AcceptTxResult? AddTxResult)> resultFutureNonce =
+ ctx.Test.TxSender.SendTransaction(txWithFutureNonce, TxHandlingOptions.None);
+ Assert.AreEqual(resultNextNonce.Result.AddTxResult, AcceptTxResult.Accepted);
+ Assert.AreEqual(resultFutureNonce.Result.AddTxResult, AcceptTxResult.Accepted);
+
string serialized = ctx.Test.TestEthRpc("eth_getTransactionCount", TestItem.AddressA.Bytes.ToHexString(true), blockParameter);
Assert.AreEqual($"{{\"jsonrpc\":\"2.0\",\"result\":\"{expectedResult}\",\"id\":67}}", serialized);
}
@@ -216,7 +229,24 @@ public async Task Eth_get_tx_count_default_block()
string serialized = ctx.Test.TestEthRpc("eth_getTransactionCount", TestItem.AddressA.Bytes.ToHexString(true));
Assert.AreEqual("{\"jsonrpc\":\"2.0\",\"result\":\"0x3\",\"id\":67}", serialized);
}
-
+
+ [Test]
+ public async Task Eth_get_tx_count_pending_block()
+ {
+ using Context ctx = await Context.Create();
+ string serializedPendingBefore = ctx.Test.TestEthRpc("eth_getTransactionCount", TestItem.AddressB.Bytes.ToHexString(true), "pending");
+ Assert.AreEqual("{\"jsonrpc\":\"2.0\",\"result\":\"0x0\",\"id\":67}", serializedPendingBefore);
+ 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);
+ Assert.AreEqual(resultNextNonce.Result.AddTxResult, AcceptTxResult.Accepted);
+ string serializedLatestAfter = ctx.Test.TestEthRpc("eth_getTransactionCount", TestItem.AddressB.Bytes.ToHexString(true));
+ Assert.AreEqual("{\"jsonrpc\":\"2.0\",\"result\":\"0x0\",\"id\":67}", serializedLatestAfter);
+ string serializedPendingAfter = ctx.Test.TestEthRpc("eth_getTransactionCount", TestItem.AddressB.Bytes.ToHexString(true), "pending");
+ Assert.AreEqual("{\"jsonrpc\":\"2.0\",\"result\":\"0x1\",\"id\":67}", serializedPendingAfter);
+ }
+
[Test]
public async Task Eth_get_filter_changes_empty()
{
@@ -225,7 +255,7 @@ public async Task Eth_get_filter_changes_empty()
string serialized2 = ctx.Test.TestEthRpc("eth_getFilterChanges", "0");
Assert.AreEqual("{\"jsonrpc\":\"2.0\",\"result\":[],\"id\":67}", serialized2);
}
-
+
[Test]
public async Task Eth_uninstall_filter()
{
@@ -234,7 +264,7 @@ public async Task Eth_uninstall_filter()
string serialized2 = ctx.Test.TestEthRpc("eth_uninstallFilter", "0");
Assert.AreEqual("{\"jsonrpc\":\"2.0\",\"result\":true,\"id\":67}", serialized2);
}
-
+
[Test]
public async Task Eth_get_filter_changes_with_block()
{
@@ -245,7 +275,7 @@ public async Task Eth_get_filter_changes_with_block()
Assert.AreEqual("{\"jsonrpc\":\"2.0\",\"result\":[\"0x166781de9c5f3328b7fc59c32e1dd1ec892021d95578258004ee221863a817a0\"],\"id\":67}", serialized2, serialized2.Replace("\"", "\\\""));
}
-
+
[Test]
public async Task Eth_get_filter_changes_with_tx()
{
@@ -366,7 +396,7 @@ public async Task Eth_get_logs(string parameter, string expected)
Assert.AreEqual(expected, serialized);
}
-
+
[TestCase("{\"fromBlock\":\"earliest\",\"toBlock\":\"latest\"}", "{\"jsonrpc\":\"2.0\",\"error\":{\"code\":-32001,\"message\":\"resource not found message\"},\"id\":67}")]
public async Task Eth_get_logs_with_resourceNotFound(string parameter, string expected)
{
@@ -542,7 +572,7 @@ public async Task Eth_accounts()
string serialized = ctx.Test.TestEthRpc("eth_accounts");
Assert.AreEqual("{\"jsonrpc\":\"2.0\",\"result\":[\"0x7e5f4552091a69125d5dfcb7b8c2659029395bdf\",\"0x2b5ad5c4795c026514f8317c7a215e218dccd6cf\",\"0x6813eb9362372eef6200f3b1dbc3f819671cba69\",\"0x1eff47bc3a10a45d4b230b5d10e37751fe6aa718\",\"0xe1ab8145f7e55dc933d51a18c793f901a3a0b276\",\"0xe57bfe9f44b819898f47bf37e5af72a0783e1141\",\"0xd41c057fd1c78805aac12b0a94a405c0461a6fbb\",\"0xf1f6619b38a98d6de0800f1defc0a6399eb6d30c\",\"0xf7edc8fa1ecc32967f827c9043fcae6ba73afa5c\",\"0x4cceba2d7d2b4fdce4304d3e09a1fea9fbeb1528\",\"0x3da8d322cb2435da26e9c9fee670f9fb7fe74e49\",\"0xdbc23ae43a150ff8884b02cea117b22d1c3b9796\",\"0x68e527780872cda0216ba0d8fbd58b67a5d5e351\",\"0x5a83529ff76ac5723a87008c4d9b436ad4ca7d28\",\"0x8735015837bd10e05d9cf5ea43a2486bf4be156f\",\"0xfae394561e33e242c551d15d4625309ea4c0b97f\",\"0x252dae0a4b9d9b80f504f6418acd2d364c0c59cd\",\"0x79196b90d1e952c5a43d4847caa08d50b967c34a\",\"0x4bd1280852cadb002734647305afc1db7ddd6acb\",\"0x811da72aca31e56f770fc33df0e45fd08720e157\",\"0x157bfbecd023fd6384dad2bded5dad7e27bf92e4\",\"0x37da28c050e3c0a1c0ac3be97913ec038783da4c\",\"0x3bc8287f1d872df4217283b7920d363f13cf39d8\",\"0xf4e2b0fcbd0dc4b326d8a52b718a7bb43bdbd072\",\"0x9a5279029e9a2d6e787c5a09cb068ab3d45e209d\",\"0xc39677f5f47d5fe65ab24e66750e8fca127c15be\",\"0x1dc728786e09f862e39be1f39dd218ee37feb68d\",\"0x636cc65783084b9f370789c90f733dbbeb88925d\",\"0x4a7a7c2e09209dbe44a582cd92b0edd7129e74be\",\"0xa56160a359f2eaa66f5c9df5245542b07339a9a6\",\"0x6b09d6433a379752157fd1a9e537c5cae5fa3168\",\"0x32e77de0d74a5c7af861aaed324c6a4c488142a8\",\"0x093d49d617a10f26915553255ec3fee532d2c12f\",\"0x138854708d8b603c9b7d4d6e55b6d32d40557f4d\",\"0x7dc0a40d64d72bb4590652b8f5c687bf7f26400c\",\"0x9358a525cc25aa571af0bcb5b98fbeab045a5e36\",\"0xd8e8ea89d71de89214fa39ba13ba9fcddc0d9467\",\"0xb56ed8f48979e1a948ad129199a600d0562cac51\",\"0xf65ac7003e905d72c666bfec1dc0960ecc9d0d6e\",\"0xd817d23c981472d703be36da777ffdb1abefd972\",\"0xf2adb90aa27a3c61a95c50063b20919d811e1476\",\"0xae3dffee97f92db0201d11cb8877c89738353bce\",\"0xeb3025e7ac2764040384316b33476e048961a71f\",\"0x9e3289708dc5709926a542fcf260fd4b210461f0\",\"0x6c23face014f20b3ebb65ae96d0d7ff32ab94c17\",\"0xb83b6241f966b1685c8b2ffce3956e21f35b4dcb\",\"0x6350872d7465864689def650443026f2f73a08da\",\"0x673c638147fe91e4277646d86d5ae82f775eea5c\",\"0xf472086186382fca55cd182de196520abd76f69d\",\"0x5ae58d2bc5145bff0c1bec0f32bfc2d079bc66ed\",\"0x2b29bea668b044b2b355c370f85b729bcb43ec40\",\"0x3797126345fb5fb6a37629db55ec692173cfb458\",\"0xe6869cc98283ab53e8a1a5312857ef0be9d189fe\",\"0xa5dfe354b3fc30c5c3a8ffefc8f9470d9177c334\",\"0xa1a625ae13b80a9c48b7c0331c83bc4541ac137f\",\"0xa33c9d26e1e33b84247defca631c1d30ffc76f5d\",\"0xf9807a8719ae154e74591cb2d452797707fadf73\",\"0xa1ba6fc3ea0e89f0e79f89d9aa0081d010571e4a\",\"0x366c20b40048556e5682e360997537c3715aca0e\",\"0xeb0e56f32246d043228fac8b63a71687d5199af1\",\"0xdb3ed822b78f0641623a12166607b5fa4df862ad\",\"0xb88c19426f03c6981d1a4281c7414d842b97619a\",\"0x32e04b012ac811c91d36a355a6d2859a0071a965\",\"0xe0dd44773f7657b11019062879d65f3d9862460c\",\"0x756be12856a8f44ab22fdbcbd42b70b843377d09\",\"0x6f4c950442e1af093bcff730381e63ae9171b87a\",\"0x4d1bf28514a4451249908e611366ec967c3d1558\",\"0xb0142d883494197b02c6ece84f571d81bd831124\",\"0x1326324f5a9fb193409e10006e4ea41b970df321\",\"0xf9a2c330a19e2fbfeb50fe7a7195b973bb0a3be9\",\"0x7a601ffa997cede6435aeabf4fa2091f09e149ec\",\"0xa92f4b5c4fddcc37e5139873ac28a4a0a42d68df\",\"0x850cc185d6cae4a7fdfb3dd81f977dd1df7d6503\",\"0xb1b7c87e8a0bf2e7fd1a1c582bd353e4c4529341\",\"0xff844fdb49e00776ad538db9ea2f9fa98ec0caf7\",\"0x1ac6f9601f2f616badcea8a0a307e1a3c14767a4\",\"0xc2aa6271409c10dee630e79df90c968989ccf2b7\",\"0x883d01eae6eaac077e126ddb32cd53550966ed76\",\"0x127688bbc070dd69a4db8c3ba5d43909e13d8f77\",\"0x0b54a50c0409dab2e63c3566324268ed53ec019a\",\"0xafd46e3549cc63d7a240d6177d056857679e6f99\",\"0x752481f35bb1d44d786c7b4dbe40db4a4266f96f\",\"0xac32def421e36b43629f785fd04523260e7f2b28\",\"0xfe6032a0810e90d025a3a39dd29844f964ee102c\",\"0x5cb6f3e6499d1f068b33351d0cae4b68cdf501bf\",\"0x84b743441b7bdf65cb4293126db4c1b709d7d95e\",\"0x8530a26f6c062f55597bd30c1a44e248decb0027\",\"0x5ce162cfa6208d7c50a7cb3525ac126155e7bce4\",\"0x2853dc9ca40d012969e25360cce0d9d326b24a86\",\"0x802271c02f76701929e1ea772e72783d28e4b60f\",\"0x7bd2aa0726ac3b9e752b120de8568e90b0423ae4\",\"0xb540c05d9b2516da9596a5ee75d750717a4be035\",\"0xa72392cd4be285ab6681da1bf1c45f0b370cb7b4\",\"0xcf484269182ac2388a4bfe6d19fb0687e3534b7f\",\"0x994907cb80bfd175f9b0b32672cfde0091368e2e\",\"0x36eab6ce7fededc098ef98c41e83548a89147131\",\"0x440db3ab842910d2a39f4e1be9e017c6823fb658\",\"0x25ac70ea6f44c4531a7117ea3620fa29cdaaca48\",\"0x24d881139ee639c2a774b4b1851cb7a9d0fce122\",\"0xd9a284367b6d3e25a91c91b5a430af2593886eb9\",\"0xe6b3367318c5e11a6eed3cd0d850ec06a02e9b90\",\"0x88c0e901bd1fd1a77bda342f0d2210fdc71cef6b\",\"0x7231c364597f3bfdb72cf52b197cc59111e71794\",\"0x043aed06383f290ee28fa02794ec7215ca099683\",\"0x0c95931d95694b3ef74071241827c09f25d40620\",\"0x417f3b59ef57c641283c2300fae0f27fe98d518c\",\"0xd6b931d8d441b1ec98f55f8ec8adb532dc140c78\",\"0x9220625b1a30680387d542e6b5f753786ca5530e\",\"0x997cf669860a1dcc76344866534d8679a7b562e2\",\"0xb961768b578514debf079017ff78c47b0a6adbf6\",\"0x052b91ad9732d1bce0ddae15a4545e5c65d02443\",\"0x8df64de79608f0ae9e72ecae3a400582aed8101c\",\"0x0e7b23cd1fdb7ea3ccc80320ab43843a2f193c36\",\"0xfbbc41289f834a76e4320ac238512035560467ee\",\"0x61e1da6c7b8b211e6e5dd921efe27e73ad226dac\",\"0x87fcbe64187317c59a944be5b9c5c830b9373730\",\"0x2acf0d6fdac920081a446868b2f09a8dac797448\",\"0x1715eb68afba4d516ef1e068b55f5093bb4a2f59\",\"0x58bab2f728dc4fc227a4c38cab2ec93b73b4e828\",\"0x25346934b4faa00dee0190c2069156bde6010c18\",\"0xa01cca6367a84304b6607b76676c66c360b74741\",\"0x872917cec8992487651ee633dba73bd3a9dca309\",\"0x6c1a01c2ab554930a937b0a2e8105fb47946c679\",\"0x13c0e7c715fdea35c7f9663c719e4d36601275b9\",\"0xe8c5025c803f3279d94ea55598e147f601929bf4\",\"0x639acdbd838b81cea8d6a970136812783fa5bf5e\",\"0xb3087f34edab33a8182ba29adea4d739d9831a94\",\"0xc6a210606f2ee6e64afb9584db054f3476a5cc66\",\"0xd01c9d93efc83c00b30f768f832182beff65696f\",\"0x00edf2d16afbc028fb1e879559b07997af79539f\",\"0xf5d722030d17ca01f2813af9e7be158d7a037997\",\"0xae3d43ab6fdcd35386db427099ff11aa670ee0f4\",\"0x0dc8b8ef8457b1e45ac277d65ac5987b547ba775\",\"0xde521346f9327a4314a18b2cda96b2a33603177a\",\"0x69842e12d6f36f9f93f06086b70795bfc7e02745\",\"0x9b7bdf6ad17d5fc9a168acaa24495e52a65f3b79\",\"0xa2d47d2c42009520075cb15f5855052008d0c44d\",\"0xb0c249f6f92fb2491fc9750a5299d856ba2ea3c6\",\"0x839d96957f21e82fbcca0d42a1f12ef6e1cf82e9\",\"0x2a0d6b92b042497013e5549d6579202608ce0c80\",\"0xa4f8c598927eab2f1898f8f2d6f8121578de2344\",\"0xdb21655b672dacc8da6f538c899f9d6969604117\",\"0x21289cd01f9f58fc44962b6e213a0fbbd015beb6\",\"0x0b62d63c314d94dfa85b11a9c652ffe438382d6c\",\"0x9383e3096133f464d516b518b12851fd10d891f4\",\"0x64e582c17ab7c3b90e171795b504ca3c04108501\",\"0x848406919d014b1e5c27a82f951caff840fd63ef\",\"0x5fe015779fb36006b01f9c5a5dbcaa6ffa56f0c0\",\"0x28b6e15f86025b8ea8beaa6855a81069bfb6ab1e\",\"0x271d65af9a5a7b4cd7af264f251184c2a4b9e7a3\",\"0xddf44e34ed40c40624c7b9f20a1030b505a4fac0\",\"0xe5854075272ca5ef71663d5b87e0cd5ac53b2f36\",\"0x2798ba84d7830c5f60d750f37f87d93277106905\",\"0x7e9961fa09dd52f945f8143844785cf0e51bb4ce\",\"0xf33d2f7d96f92d912ca8418f9d62eb54c1a9889f\",\"0xeec566c793a89f388bbabfc0225183a6a95c4263\",\"0x2001f8cdcdeef1bbcc188ca59cf04fb44133d55a\",\"0x3bf958fa0626e898f548a8f95cf9ab3a4db65169\",\"0xb0d744fde06bbcb6655eb55288ec94fa6a0b2a52\",\"0x18eb36d090eeadf82f3454a6da690fc398d3eba1\",\"0xd2431ca38735c2fd438e2caa23f094191d89675b\",\"0x612b7be154a64292aae070aaa86fcd66ba218071\",\"0x681ce2f439fdc80e70c1eea8b8a085dfb976d32a\",\"0x2174ca3ee9ace7dd8c946c97054c72f2b384c4c2\",\"0x1d694d5ad94f32132ff5c14c901d3ddbee90a550\",\"0x0b6fe046e6fd8d7a7a36d5ad1ffb82d2e3e5c3bb\",\"0x258f4ed0560e290a95066d9dee3628f2f179302b\",\"0xe2a09565167d4e3f826adec6bef82b97e0a4383f\",\"0x9af70704e9ec5f505cdba564ff4dec03503ddaa2\",\"0xeb9afe072c781401bf364224c75a036e4d832f52\",\"0x07748403082b29a45abd6c124a37e6b14e6b1803\",\"0x63486b70d804464766cfd096bba5552c4bcdac30\",\"0x5181be40152caaba8e123a55b7762755d4e8e416\",\"0x9481da7766c043eefeecc9589ee7ade61316b0ff\",\"0x42aba3530dd1ccb1dda27bfaa7c6a832cfdb4446\",\"0x05650444ace15a01762bd97ee8fdeb495b3c2436\",\"0xd83d18a2eae2440e272a53f86e617cd9f33c8d68\",\"0x4a35a802dbd623561040dd50f6293842d0901731\",\"0x4dbaf6c348d8cd1f174a7a6155f80ea8d4a8baf8\",\"0x9efc4e49be8ff70d596ac20efec9b7842e1ea963\",\"0x68efde0cdd917c6da6dab02c23f69e7c9cff51a9\",\"0x99b52813933a46d95bd4265ea2f674e58827da97\",\"0x7b35461cc5adbdc415c1f9562ccc342adbf09bd4\",\"0x8ee8813fb9d41cc58ef87d28b36e948b1234e71d\",\"0x69c1bc7883a7bb7696c7726d025867cd16564c9c\",\"0x31eb18dd6f5a8064ab750eabb281cf162f43ccd0\",\"0xf5d122e123d9d7998d2bea685d11b10fec3e4508\",\"0xf762854586a40a93d1fdcde32c062829f3754de9\",\"0x1e3f8fb9f840325983d6e5c68b6b846ff66a20ac\",\"0x3c1638a25ad7e8c2a84b53b661dd1bd048407e8f\",\"0x2eedf8a799b73bc02e4664183eb72422c377153b\",\"0xcdef6f23a26f960b53468f497967ce74c026af52\",\"0x0a2035683fe5587b0b09db0e757306ad729fe6c1\",\"0x158cc083cfbcffb2f983a3aa8b027eb0711c9831\",\"0x691cb1645a4f21d879973b3a3b98a714fc1970d6\",\"0x754164c0cb85dda1b5b18e5b62adbb4d60c3efbf\",\"0x556330e8d92912ccf133851ba03abd2db70da404\",\"0x1745ceba112b0a41638e235ec59b35adf37b70ab\",\"0xa24c85b16a440587793f82e358fa6b204468735b\",\"0x5304fb08724d73f2bb5e04c582407c33cde6c8d3\",\"0x256a11785fc43141324cf61efb5f491378c10c85\",\"0xa9f161a2badd44f3fe45b91a044a9484b72f1dc4\",\"0xd5cc10c45fc0f9f956acd7559f61edbfec9f6c3d\",\"0x381c7a71035bdb42fb5d77523df2ff00d9f9df1b\",\"0x45cdbeea730d8212f451a6a8d0eb5998b04cccca\",\"0x6367283f25a32be0c28623d787c319e237c3b7bd\",\"0x598e94eb5e050045272d8417f6ab363bd874d568\",\"0x379ff6375f4a44f458683629ef05141d73fae55a\",\"0x18df8ba2ef19083ddff68f8b33976cf22e8419c6\",\"0xffceebc37a7351d5df9aa3b077ed39cc3b5192ff\",\"0x1cd21f00b58894260f7abed65ad23dce3cea0226\",\"0x26324733d604abb6176cf18e4f4a0624ceeddc09\",\"0x4102d394d723ff141b82ef9a6053fb89f90c67f4\",\"0x269c370cb95b63f9b6a7cad47998167f160a2689\",\"0x3bb9557113fbb052dae3008a2801a072c432c018\",\"0x3f588a72d94d0d0986b112c671c2343320a19386\",\"0x7cfa9eee1d752da599211bc8a68d0687708dabfc\",\"0x7bc23966c419eadcb8a2fc5f83e635c4d4ad0c2f\",\"0xc4ad60337b04fc721912531a52a5d77878293fb9\",\"0xfc5ba3041f750f9b6820ce066c153eb396aac1ff\",\"0x32480c2d857941d2fff4e34f0910b20c0f9c23bc\",\"0x8041c9a96585053db2d7214b5de56828645b8e62\",\"0x444ca66b3ceb4187840cb1a205566a1413d5fecb\",\"0xf084bbaabee1a700a8faa404027db620a5aa0059\",\"0x602d562b4ef2544f851587619b56f77a9d965d45\",\"0x216faec139a61329ef8b31d982de427d9c007a9e\",\"0x11eb17b20113ae923d72e52870d40bf59a08b40d\",\"0xe69017fcc36bbc7fb167b9585bdd47a950ba1992\",\"0xe5549f429a72bfa618cf5c1afdac22a730df6a1a\",\"0x161c2e10407e2a87959c0bae1f342c80eaea28f3\",\"0x4161220db043a7d682e0ad123a3f8fea165711aa\",\"0xb33609811fb3d9fc8955dc6e9e086f1f08fc3a65\",\"0x4148555ea4c00e14f81ef399bbe67ef2fd9811b1\",\"0x4f81e991f76276a17ca92a1321f37189b1727f77\",\"0xba95e317ead06b55c8b70276fc63904b3339dfa1\",\"0xf6203c4fb14da640d11fbd9573e3958d017e6745\",\"0x73377d6228266393747efa710017872d6dd5b9a6\",\"0xf7862d105fc6ee69604decc30aa89472ad405961\",\"0xfa1205e19719c248323563bd55cd8bfd08b0cbc6\",\"0x4f46630115b446f8f7cebe1e5961ef7858c25204\",\"0x7492ebbc1e7f2838fc7191edc031581d5712978a\",\"0xc0af3981f9c0dfcb8955fea07a3e4f23806fab51\",\"0x8621dd642245df371b584b48c081e8863313a70d\",\"0xc328de035c91b39efa07d2fe620813253c9b4ec2\",\"0xa11308e3b741227d41973ddb17534ceb27b8206f\",\"0xc4ff1b4565ee203fa12636e100fe9c89cd18acb7\",\"0x63a36aea8570219476ef835f09024acdedfee95a\",\"0xf7205066c153f7c88dc3653ebc72b438884ae109\",\"0xa8ce5c40c4aa9278ddeaa418e775985549960e7a\",\"0x81f58f2194b0413806bf2ce8e1654bc855dc65a1\",\"0xf0218008120201e66b65fce4df9035007e811228\",\"0x90f022e3ca8453f5e5765cd3054003b544526eec\",\"0x1d1f873ba1ddf7915e6e26f93f5624b40efaefe2\",\"0x0311afd3bc2ae250d5f9f2706bae2ef4164d6912\",\"0x5044a80bd3eff58302e638018534bbda8896c48a\"],\"id\":67}", serialized, serialized.Replace("\"", "\\\""));
}
-
+
[Test]
public async Task Eth_get_block_by_number_with_number_bad_number()
{
@@ -574,21 +604,21 @@ public async Task Eth_get_transaction_receipt()
IBlockchainBridge blockchainBridge = Substitute.For();
IBlockFinder blockFinder = Substitute.For();
IReceiptFinder receiptFinder = Substitute.For();
-
+
Block block = Build.A.Block.WithNumber(1)
.WithStateRoot(new Keccak("0x1ef7300d8961797263939a3d29bbba4ccf1702fabf02d8ad7a20b454edb6fd2f"))
.TestObject;
-
+
LogEntry[] entries = new[]
{
Build.A.LogEntry.TestObject,
Build.A.LogEntry.TestObject
};
-
+
TxReceipt receipt = Build.A.Receipt.WithBloom(new Bloom(entries, new Bloom())).WithAllFieldsFilled
.WithLogs(entries).TestObject;
TxReceipt[] receiptsTab = {receipt};
-
+
blockchainBridge.GetReceiptAndEffectiveGasPrice(Arg.Any()).Returns((receipt, UInt256.One, 0));
blockFinder.FindBlock(Arg.Any()).Returns(block);
receiptFinder.Get(Arg.Any()).Returns(receiptsTab);
@@ -599,8 +629,8 @@ public async Task Eth_get_transaction_receipt()
Assert.AreEqual("{\"jsonrpc\":\"2.0\",\"result\":{\"transactionHash\":\"0x03783fac2efed8fbc9ad443e592ee30e61d65f471140c10ca155e937b435b760\",\"transactionIndex\":\"0x2\",\"blockHash\":\"0x017e667f4b8c174291d1543c466717566e206df1bfd6f30271055ddafdb18f72\",\"blockNumber\":\"0x2\",\"cumulativeGasUsed\":\"0x3e8\",\"gasUsed\":\"0x64\",\"effectiveGasPrice\":\"0x1\",\"from\":\"0xb7705ae4c6f81b66cdb323c65f4e8133690fc099\",\"to\":\"0x942921b14f1b1c385cd7e0cc2ef7abe5598c8358\",\"contractAddress\":\"0x76e68a8696537e4141926f3e528733af9e237d69\",\"logs\":[{\"removed\":false,\"logIndex\":\"0x0\",\"transactionIndex\":\"0x2\",\"transactionHash\":\"0x03783fac2efed8fbc9ad443e592ee30e61d65f471140c10ca155e937b435b760\",\"blockHash\":\"0x017e667f4b8c174291d1543c466717566e206df1bfd6f30271055ddafdb18f72\",\"blockNumber\":\"0x2\",\"address\":\"0x0000000000000000000000000000000000000000\",\"data\":\"0x\",\"topics\":[\"0x0000000000000000000000000000000000000000000000000000000000000000\"]},{\"removed\":false,\"logIndex\":\"0x1\",\"transactionIndex\":\"0x2\",\"transactionHash\":\"0x03783fac2efed8fbc9ad443e592ee30e61d65f471140c10ca155e937b435b760\",\"blockHash\":\"0x017e667f4b8c174291d1543c466717566e206df1bfd6f30271055ddafdb18f72\",\"blockNumber\":\"0x2\",\"address\":\"0x0000000000000000000000000000000000000000\",\"data\":\"0x\",\"topics\":[\"0x0000000000000000000000000000000000000000000000000000000000000000\"]}],\"logsBloom\":\"0x00000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000800000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000\",\"root\":\"0x1f675bff07515f5df96737194ea945c36c41e7b4fcef307b7cd4d0e602a69111\",\"status\":\"0x1\",\"error\":\"error\",\"type\":\"0x0\"},\"id\":67}", serialized);
}
-
-
+
+
[Test]
public async Task Eth_get_transaction_receipt_when_block_has_few_receipts()
{
@@ -608,7 +638,7 @@ public async Task Eth_get_transaction_receipt_when_block_has_few_receipts()
IBlockchainBridge blockchainBridge = Substitute.For();
IBlockFinder blockFinder = Substitute.For();
IReceiptFinder receiptFinder = Substitute.For();
-
+
int blockNumber = 1;
Block genesis = Build.A.Block.Genesis
.WithStateRoot(new Keccak("0x1ef7300d8961797263939a3d29bbba4ccf1702fabf02d8ad7a20b454edb6fd2f"))
@@ -617,9 +647,9 @@ public async Task Eth_get_transaction_receipt_when_block_has_few_receipts()
Block block = Build.A.Block.WithNumber(blockNumber).WithParent(previousBlock)
.WithStateRoot(new Keccak("0x1ef7300d8961797263939a3d29bbba4ccf1702fabf02d8ad7a20b454edb6fd2f"))
.TestObject;
-
+
LogEntry[] logEntries = new[] {Build.A.LogEntry.TestObject, Build.A.LogEntry.TestObject};
-
+
TxReceipt receipt1 = new TxReceipt()
{
Bloom = new Bloom(logEntries),
@@ -635,7 +665,7 @@ public async Task Eth_get_transaction_receipt_when_block_has_few_receipts()
GasUsedTotal = 2000,
Logs = logEntries
};
-
+
TxReceipt receipt2 = new TxReceipt()
{
Bloom = new Bloom(logEntries),
@@ -651,11 +681,11 @@ public async Task Eth_get_transaction_receipt_when_block_has_few_receipts()
GasUsedTotal = 2000,
Logs = logEntries
};
-
+
blockchainBridge.GetReceiptAndEffectiveGasPrice(Arg.Any()).Returns((receipt2, UInt256.One, 2));
-
+
TxReceipt[] receipts = {receipt1, receipt2};
-
+
blockFinder.FindBestSuggestedHeader().Returns(Build.A.BlockHeader.WithNumber(blockNumber).TestObject);
blockFinder.Head.Returns(Build.A.Block.WithHeader(Build.A.BlockHeader.WithNumber(blockNumber).TestObject).TestObject);
blockFinder.FindBlock(Arg.Any()).Returns(block);
@@ -675,8 +705,8 @@ public async Task Eth_get_transaction_receipt_returns_null_on_missing_receipt()
string serialized = ctx.Test.TestEthRpc("eth_getTransactionReceipt", TestItem.KeccakA.ToString());
Assert.AreEqual("{\"jsonrpc\":\"2.0\",\"result\":null,\"id\":67}", serialized);
}
-
-
+
+
[Test]
public async Task Eth_getTransactionReceipt_return_info_about_mined_tx()
{
@@ -684,38 +714,38 @@ public async Task Eth_getTransactionReceipt_return_info_about_mined_tx()
IBlockFinder blockFinder = Substitute.For();
IReceiptFinder receiptFinder = Substitute.For();
IBlockchainBridge blockchainBridge = Substitute.For();
-
+
await ctx.Test.AddFunds(new Address("0x723847c97bc651c7e8c013dbbe65a70712f02ad3"), 1.Ether());
Transaction tx = Build.A.Transaction.WithData(new byte[]{0, 1})
.SignedAndResolved().WithChainId(1).WithGasPrice(0).WithValue(0).WithGasLimit(210200).WithGasPrice(20.GWei()).TestObject;
-
+
Block block = Build.A.Block.WithNumber(1)
.WithStateRoot(new Keccak("0x1ef7300d8961797263939a3d29bbba4ccf1702fabf02d8ad7a20b454edb6fd2f"))
.WithTransactions(tx)
.TestObject;
-
+
await ctx.Test.AddBlock(tx);
-
+
LogEntry[] entries = new[]
{
Build.A.LogEntry.TestObject,
};
-
+
TxReceipt receipt = Build.A.Receipt.WithBloom(new Bloom(entries, new Bloom())).WithAllFieldsFilled
.WithLogs(entries).TestObject;
TxReceipt[] receiptsTab = {receipt};
-
+
blockFinder.FindBlock(Arg.Any()).Returns(block);
receiptFinder.Get(Arg.Any()).Returns(receiptsTab);
receiptFinder.Get(Arg.Any()).Returns(receiptsTab);
blockchainBridge.GetReceiptAndEffectiveGasPrice(Arg.Any()).Returns((receipt, UInt256.One, 0));
-
+
ctx.Test = await TestRpcBlockchain.ForTest(SealEngineType.NethDev).WithBlockFinder(blockFinder).WithReceiptFinder(receiptFinder).WithBlockchainBridge(blockchainBridge).Build();
string serialized = ctx.Test.TestEthRpc("eth_getTransactionReceipt", tx.Hash!.ToString());
-
+
Assert.AreEqual("{\"jsonrpc\":\"2.0\",\"result\":{\"transactionHash\":\"0xda6b4df2595675cbee0d4889f41c3d0790204e8ed1b8ad4cadaa45a7d50dace5\",\"transactionIndex\":\"0x2\",\"blockHash\":\"0x017e667f4b8c174291d1543c466717566e206df1bfd6f30271055ddafdb18f72\",\"blockNumber\":\"0x2\",\"cumulativeGasUsed\":\"0x3e8\",\"gasUsed\":\"0x64\",\"effectiveGasPrice\":\"0x1\",\"from\":\"0xb7705ae4c6f81b66cdb323c65f4e8133690fc099\",\"to\":\"0x942921b14f1b1c385cd7e0cc2ef7abe5598c8358\",\"contractAddress\":\"0x76e68a8696537e4141926f3e528733af9e237d69\",\"logs\":[{\"removed\":false,\"logIndex\":\"0x0\",\"transactionIndex\":\"0x2\",\"transactionHash\":\"0x03783fac2efed8fbc9ad443e592ee30e61d65f471140c10ca155e937b435b760\",\"blockHash\":\"0x017e667f4b8c174291d1543c466717566e206df1bfd6f30271055ddafdb18f72\",\"blockNumber\":\"0x2\",\"address\":\"0x0000000000000000000000000000000000000000\",\"data\":\"0x\",\"topics\":[\"0x0000000000000000000000000000000000000000000000000000000000000000\"]}],\"logsBloom\":\"0x00000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000800000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000\",\"root\":\"0x1f675bff07515f5df96737194ea945c36c41e7b4fcef307b7cd4d0e602a69111\",\"status\":\"0x1\",\"error\":\"error\",\"type\":\"0x0\"},\"id\":67}", serialized);
}
-
+
[Test]
[Ignore("This test is flaky on CI. It could be connected with timeouts in block production.")]
public async Task Eth_getTransactionReceipt_return_info_about_mined_1559tx()
@@ -729,7 +759,7 @@ public async Task Eth_getTransactionReceipt_return_info_about_mined_1559tx()
string serialized = ctx.Test.TestEthRpc("eth_getTransactionReceipt", tx.Hash!.ToString());
Assert.AreEqual("{\"jsonrpc\":\"2.0\",\"result\":{\"transactionHash\":\"0x31501f80bf2ec493c368a519cb8ed6f132f0be26202304bbf1e1728642affb7f\",\"transactionIndex\":\"0x0\",\"blockHash\":\"0x54515a11aa6c392ee2e1071fca3a579bc9a520930ef757dbf9b7d85fe155c691\",\"blockNumber\":\"0x5\",\"cumulativeGasUsed\":\"0x521c\",\"gasUsed\":\"0x521c\",\"effectiveGasPrice\":\"0x5e91eb5d\",\"from\":\"0x723847c97bc651c7e8c013dbbe65a70712f02ad3\",\"to\":\"0x0000000000000000000000000000000000000000\",\"contractAddress\":null,\"logs\":[],\"logsBloom\":\"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\",\"status\":\"0x1\",\"type\":\"0x2\"},\"id\":67}", serialized);
}
-
+
[Test]
[Ignore("This test is flaky on CI. It could be connected with timeouts in block production.")]
public async Task Eth_getTransactionByHash_return_info_about_mined_1559tx()
@@ -777,11 +807,11 @@ public async Task Send_transaction_with_signature_will_not_try_to_sign()
ctx.Test = await TestRpcBlockchain.ForTest(SealEngineType.NethDev).WithBlockchainBridge(bridge).WithTxSender(txSender).Build();
Transaction tx = Build.A.Transaction.Signed(new EthereumEcdsa(ChainId.Mainnet, LimboLogs.Instance), TestItem.PrivateKeyA).TestObject;
string serialized = ctx.Test.TestEthRpc("eth_sendRawTransaction", Rlp.Encode(tx, RlpBehaviors.None).Bytes.ToHexString());
-
+
await txSender.Received().SendTransaction(Arg.Any(), TxHandlingOptions.PersistentBroadcast);
Assert.AreEqual($"{{\"jsonrpc\":\"2.0\",\"result\":\"{TestItem.KeccakA.Bytes.ToHexString(true)}\",\"id\":67}}", serialized);
}
-
+
[TestCase("01f85b821e8e8204d7847735940083030d408080853a60005500c080a0f43e70c79190701347517e283ef63753f6143a5225cbb500b14d98eadfb7616ba070893923d8a1fc97499f426524f9e82f8e0322dfac7c3d7e8a9eee515f0bcdc4")]
public async Task Send_raw_transaction_will_send_transaction(string rawTransaction)
{
@@ -792,11 +822,11 @@ public async Task Send_raw_transaction_will_send_transaction(string rawTransacti
ctx.Test = await TestRpcBlockchain.ForTest(SealEngineType.NethDev).WithBlockchainBridge(bridge).WithTxSender(txSender).Build();
string serialized = ctx.Test.TestEthRpc("eth_sendRawTransaction", rawTransaction);
-
+
await txSender.Received().SendTransaction(Arg.Any(), TxHandlingOptions.PersistentBroadcast);
Assert.AreEqual($"{{\"jsonrpc\":\"2.0\",\"result\":\"{TestItem.KeccakA.Bytes.ToHexString(true)}\",\"id\":67}}", serialized);
}
-
+
[Test]
public async Task Send_transaction_without_signature_will_not_set_nonce_when_zero_and_not_null()
{
@@ -816,7 +846,7 @@ public async Task Send_transaction_without_signature_will_not_set_nonce_when_zer
await txSender.Received().SendTransaction(Arg.Any(), TxHandlingOptions.PersistentBroadcast);
Assert.AreEqual($"{{\"jsonrpc\":\"2.0\",\"result\":\"{TestItem.KeccakA.Bytes.ToHexString(true)}\",\"id\":67}}", serialized);
}
-
+
[Test]
public async Task Send_transaction_without_signature_will_manage_nonce_when_null()
{
@@ -832,7 +862,7 @@ public async Task Send_transaction_without_signature_will_manage_nonce_when_null
TransactionForRpc rpcTx = new(tx);
rpcTx.Nonce = null;
string serialized = ctx.Test.TestEthRpc("eth_sendTransaction", new EthereumJsonSerializer().Serialize(rpcTx));
-
+
await txSender.Received().SendTransaction(Arg.Any(), TxHandlingOptions.PersistentBroadcast | TxHandlingOptions.ManagedNonce);
Assert.AreEqual($"{{\"jsonrpc\":\"2.0\",\"result\":\"{TestItem.KeccakA.Bytes.ToHexString(true)}\",\"id\":67}}", serialized);
}
@@ -843,7 +873,7 @@ public async Task Send_transaction_should_return_ErrorCode_if_tx_not_added()
using Context ctx = await Context.Create();
Transaction tx = Build.A.Transaction.WithValue(10000).SignedAndResolved(new PrivateKey("0x0000000000000000000000000000000000000000000000000000000000000001")).WithNonce(0).TestObject;
TransactionForRpc txForRpc = new(tx);
-
+
string serialized = ctx.Test.TestEthRpc("eth_sendTransaction", new EthereumJsonSerializer().Serialize(txForRpc));
Assert.AreEqual("{\"jsonrpc\":\"2.0\",\"error\":{\"code\":-32010,\"message\":\"InsufficientFunds, Account balance: 0, cumulative cost: 31000\"},\"id\":67}", serialized);
@@ -855,11 +885,11 @@ public enum AccessListProvided
Partial,
Full
}
-
+
[TestCase(AccessListProvided.None, false, 2, "{\"jsonrpc\":\"2.0\",\"result\":{\"accessList\":[{\"address\":\"0xfffffffffffffffffffffffffffffffffffffffe\",\"storageKeys\":[\"0x0000000000000000000000000000000000000000000000000000000000000001\",\"0x0000000000000000000000000000000000000000000000000000000000000002\"]},{\"address\":\"0x76e68a8696537e4141926f3e528733af9e237d69\",\"storageKeys\":[]}],\"gasUsed\":\"0xf71b\"},\"id\":67}")]
[TestCase(AccessListProvided.Full, false, 2, "{\"jsonrpc\":\"2.0\",\"result\":{\"accessList\":[{\"address\":\"0xfffffffffffffffffffffffffffffffffffffffe\",\"storageKeys\":[\"0x0000000000000000000000000000000000000000000000000000000000000001\",\"0x0000000000000000000000000000000000000000000000000000000000000002\"]},{\"address\":\"0x76e68a8696537e4141926f3e528733af9e237d69\",\"storageKeys\":[]}],\"gasUsed\":\"0xf71b\"},\"id\":67}")]
[TestCase(AccessListProvided.Partial, false, 2, "{\"jsonrpc\":\"2.0\",\"result\":{\"accessList\":[{\"address\":\"0x76e68a8696537e4141926f3e528733af9e237d69\",\"storageKeys\":[]},{\"address\":\"0xfffffffffffffffffffffffffffffffffffffffe\",\"storageKeys\":[\"0x0000000000000000000000000000000000000000000000000000000000000001\",\"0x0000000000000000000000000000000000000000000000000000000000000002\"]}],\"gasUsed\":\"0xf71b\"},\"id\":67}")]
-
+
[TestCase(AccessListProvided.None, true, 2, "{\"jsonrpc\":\"2.0\",\"result\":{\"accessList\":[{\"address\":\"0x76e68a8696537e4141926f3e528733af9e237d69\",\"storageKeys\":[]}],\"gasUsed\":\"0xee83\"},\"id\":67}")]
[TestCase(AccessListProvided.Full, true, 2, "{\"jsonrpc\":\"2.0\",\"result\":{\"accessList\":[{\"address\":\"0x76e68a8696537e4141926f3e528733af9e237d69\",\"storageKeys\":[]}],\"gasUsed\":\"0xee83\"},\"id\":67}")]
[TestCase(AccessListProvided.Partial, true, 2, "{\"jsonrpc\":\"2.0\",\"result\":{\"accessList\":[{\"address\":\"0x76e68a8696537e4141926f3e528733af9e237d69\",\"storageKeys\":[]}],\"gasUsed\":\"0xee83\"},\"id\":67}")]
@@ -867,15 +897,15 @@ public enum AccessListProvided
[TestCase(AccessListProvided.None, true, AccessTxTracer.MaxStorageAccessToOptimize, "{\"jsonrpc\":\"2.0\",\"result\":{\"accessList\":[{\"address\":\"0x76e68a8696537e4141926f3e528733af9e237d69\",\"storageKeys\":[]}],\"gasUsed\":\"0x14289\"},\"id\":67}")]
[TestCase(AccessListProvided.Full, true, AccessTxTracer.MaxStorageAccessToOptimize, "{\"jsonrpc\":\"2.0\",\"result\":{\"accessList\":[{\"address\":\"0x76e68a8696537e4141926f3e528733af9e237d69\",\"storageKeys\":[]}],\"gasUsed\":\"0x14289\"},\"id\":67}")]
[TestCase(AccessListProvided.Partial, true, AccessTxTracer.MaxStorageAccessToOptimize, "{\"jsonrpc\":\"2.0\",\"result\":{\"accessList\":[{\"address\":\"0x76e68a8696537e4141926f3e528733af9e237d69\",\"storageKeys\":[]}],\"gasUsed\":\"0x14289\"},\"id\":67}")]
-
+
[TestCase(AccessListProvided.None, true, AccessTxTracer.MaxStorageAccessToOptimize + 5, "{\"jsonrpc\":\"2.0\",\"result\":{\"accessList\":[{\"address\":\"0xfffffffffffffffffffffffffffffffffffffffe\",\"storageKeys\":[\"0x0000000000000000000000000000000000000000000000000000000000000001\",\"0x0000000000000000000000000000000000000000000000000000000000000002\",\"0x0000000000000000000000000000000000000000000000000000000000000003\",\"0x0000000000000000000000000000000000000000000000000000000000000004\",\"0x0000000000000000000000000000000000000000000000000000000000000005\",\"0x0000000000000000000000000000000000000000000000000000000000000006\",\"0x0000000000000000000000000000000000000000000000000000000000000007\",\"0x0000000000000000000000000000000000000000000000000000000000000008\",\"0x0000000000000000000000000000000000000000000000000000000000000009\",\"0x000000000000000000000000000000000000000000000000000000000000000a\",\"0x000000000000000000000000000000000000000000000000000000000000000b\",\"0x000000000000000000000000000000000000000000000000000000000000000c\",\"0x000000000000000000000000000000000000000000000000000000000000000d\",\"0x000000000000000000000000000000000000000000000000000000000000000e\",\"0x000000000000000000000000000000000000000000000000000000000000000f\",\"0x0000000000000000000000000000000000000000000000000000000000000010\",\"0x0000000000000000000000000000000000000000000000000000000000000011\"]},{\"address\":\"0x76e68a8696537e4141926f3e528733af9e237d69\",\"storageKeys\":[]}],\"gasUsed\":\"0x16f48\"},\"id\":67}")]
[TestCase(AccessListProvided.Full, true, AccessTxTracer.MaxStorageAccessToOptimize + 5, "{\"jsonrpc\":\"2.0\",\"result\":{\"accessList\":[{\"address\":\"0xfffffffffffffffffffffffffffffffffffffffe\",\"storageKeys\":[\"0x0000000000000000000000000000000000000000000000000000000000000001\",\"0x0000000000000000000000000000000000000000000000000000000000000002\",\"0x0000000000000000000000000000000000000000000000000000000000000003\",\"0x0000000000000000000000000000000000000000000000000000000000000004\",\"0x0000000000000000000000000000000000000000000000000000000000000005\",\"0x0000000000000000000000000000000000000000000000000000000000000006\",\"0x0000000000000000000000000000000000000000000000000000000000000007\",\"0x0000000000000000000000000000000000000000000000000000000000000008\",\"0x0000000000000000000000000000000000000000000000000000000000000009\",\"0x000000000000000000000000000000000000000000000000000000000000000a\",\"0x000000000000000000000000000000000000000000000000000000000000000b\",\"0x000000000000000000000000000000000000000000000000000000000000000c\",\"0x000000000000000000000000000000000000000000000000000000000000000d\",\"0x000000000000000000000000000000000000000000000000000000000000000e\",\"0x000000000000000000000000000000000000000000000000000000000000000f\",\"0x0000000000000000000000000000000000000000000000000000000000000010\",\"0x0000000000000000000000000000000000000000000000000000000000000011\"]},{\"address\":\"0x76e68a8696537e4141926f3e528733af9e237d69\",\"storageKeys\":[]}],\"gasUsed\":\"0x16f48\"},\"id\":67}")]
- [TestCase(AccessListProvided.Partial, true, AccessTxTracer.MaxStorageAccessToOptimize + 5, "{\"jsonrpc\":\"2.0\",\"result\":{\"accessList\":[{\"address\":\"0x76e68a8696537e4141926f3e528733af9e237d69\",\"storageKeys\":[]},{\"address\":\"0xfffffffffffffffffffffffffffffffffffffffe\",\"storageKeys\":[\"0x0000000000000000000000000000000000000000000000000000000000000001\",\"0x0000000000000000000000000000000000000000000000000000000000000002\",\"0x0000000000000000000000000000000000000000000000000000000000000003\",\"0x0000000000000000000000000000000000000000000000000000000000000004\",\"0x0000000000000000000000000000000000000000000000000000000000000005\",\"0x0000000000000000000000000000000000000000000000000000000000000006\",\"0x0000000000000000000000000000000000000000000000000000000000000007\",\"0x0000000000000000000000000000000000000000000000000000000000000008\",\"0x0000000000000000000000000000000000000000000000000000000000000009\",\"0x000000000000000000000000000000000000000000000000000000000000000a\",\"0x000000000000000000000000000000000000000000000000000000000000000b\",\"0x000000000000000000000000000000000000000000000000000000000000000c\",\"0x000000000000000000000000000000000000000000000000000000000000000d\",\"0x000000000000000000000000000000000000000000000000000000000000000e\",\"0x000000000000000000000000000000000000000000000000000000000000000f\",\"0x0000000000000000000000000000000000000000000000000000000000000010\",\"0x0000000000000000000000000000000000000000000000000000000000000011\"]}],\"gasUsed\":\"0x16f48\"},\"id\":67}")]
+ [TestCase(AccessListProvided.Partial, true, AccessTxTracer.MaxStorageAccessToOptimize + 5, "{\"jsonrpc\":\"2.0\",\"result\":{\"accessList\":[{\"address\":\"0x76e68a8696537e4141926f3e528733af9e237d69\",\"storageKeys\":[]},{\"address\":\"0xfffffffffffffffffffffffffffffffffffffffe\",\"storageKeys\":[\"0x0000000000000000000000000000000000000000000000000000000000000001\",\"0x0000000000000000000000000000000000000000000000000000000000000002\",\"0x0000000000000000000000000000000000000000000000000000000000000003\",\"0x0000000000000000000000000000000000000000000000000000000000000004\",\"0x0000000000000000000000000000000000000000000000000000000000000005\",\"0x0000000000000000000000000000000000000000000000000000000000000006\",\"0x0000000000000000000000000000000000000000000000000000000000000007\",\"0x0000000000000000000000000000000000000000000000000000000000000008\",\"0x0000000000000000000000000000000000000000000000000000000000000009\",\"0x000000000000000000000000000000000000000000000000000000000000000a\",\"0x000000000000000000000000000000000000000000000000000000000000000b\",\"0x000000000000000000000000000000000000000000000000000000000000000c\",\"0x000000000000000000000000000000000000000000000000000000000000000d\",\"0x000000000000000000000000000000000000000000000000000000000000000e\",\"0x000000000000000000000000000000000000000000000000000000000000000f\",\"0x0000000000000000000000000000000000000000000000000000000000000010\",\"0x0000000000000000000000000000000000000000000000000000000000000011\"]}],\"gasUsed\":\"0x16f48\"},\"id\":67}")]
public async Task Eth_create_access_list_sample(AccessListProvided accessListProvided, bool optimize, long loads, string expected)
{
TestRpcBlockchain test = await TestRpcBlockchain.ForTest(SealEngineType.NethDev).Build(new TestSpecProvider(Berlin.Instance));
-
+
(byte[] code, AccessListItemForRpc[] _) = GetTestAccessList(loads);
TransactionForRpc transaction = test.JsonSerializer.Deserialize($"{{\"type\":\"0x1\", \"data\": \"{code.ToHexString(true)}\"}}");
@@ -884,7 +914,7 @@ public async Task Eth_create_access_list_sample(AccessListProvided accessListPro
{
transaction.AccessList = GetTestAccessList(2, accessListProvided == AccessListProvided.Full).AccessList;
}
-
+
string serialized = test.TestEthRpc("eth_createAccessList", test.JsonSerializer.Serialize(transaction), "0x0", optimize.ToString().ToLower());
Assert.AreEqual(expected, serialized);
}
@@ -899,7 +929,7 @@ public static void Should_handle_gasCap_as_max_if_null_or_zero(long? gasCap)
Assert.AreEqual(long.MaxValue, rpcTx.Gas, "Gas must be set to max if gasCap is null or 0");
}
-
+
private static (byte[] ByteCode, AccessListItemForRpc[] AccessList) GetTestAccessList(long loads = 2, bool allowSystemUser = true)
{
AccessListItemForRpc[] accessList = allowSystemUser
@@ -910,7 +940,7 @@ private static (byte[] ByteCode, AccessListItemForRpc[] AccessList) GetTestAcces
: new[] {new AccessListItemForRpc(TestItem.AddressC, Array.Empty())};
Prepare code = Prepare.EvmCode;
-
+
for (int i = 1; i <= loads; i++)
{
// accesses Address.SystemUser with storage
@@ -940,18 +970,18 @@ protected class Context : IDisposable
public TestRpcBlockchain AuraTest { get; set; } = null!;
private Context() { }
-
+
public static async Task CreateWithLondonEnabled()
{
OverridableReleaseSpec releaseSpec = new(London.Instance) { Eip1559TransitionBlock = 1 };
TestSpecProvider specProvider = new(releaseSpec) {ChainId = ChainId.Mainnet};
return await Create(specProvider);
}
-
+
public static async Task Create(ISpecProvider? specProvider = null) =>
new()
{
- Test = await TestRpcBlockchain.ForTest(SealEngineType.NethDev).Build(specProvider),
+ Test = await TestRpcBlockchain.ForTest(SealEngineType.NethDev).Build(specProvider),
AuraTest = await TestRpcBlockchain.ForTest(SealEngineType.AuRa).Build(specProvider)
};
diff --git a/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/EthRpcModule.cs b/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/EthRpcModule.cs
index 0504f2e5a3e..aa82e74ae7c 100644
--- a/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/EthRpcModule.cs
+++ b/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/EthRpcModule.cs
@@ -1,16 +1,16 @@
// Copyright (c) 2021 Demerzel Solutions Limited
// This file is part of the Nethermind library.
-//
+//
// The Nethermind library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
-//
+//
// The Nethermind library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
-//
+//
// You should have received a copy of the GNU Lesser General Public License
// along with the Nethermind. If not, see .
@@ -139,7 +139,7 @@ public ResultWrapper eth_coinbase()
{
return ResultWrapper.Success(_gasPriceOracle.GetGasPriceEstimate());
}
-
+
public ResultWrapper eth_maxPriorityFeePerGas()
{
UInt256 gasPriceWithBaseFee = _gasPriceOracle.GetMaxPriorityGasFeeEstimate();
@@ -210,25 +210,33 @@ public ResultWrapper eth_getStorageAt(Address address, UInt256 positionI
return ResultWrapper.Success(storage.PadLeft(32));
}
- public Task> eth_getTransactionCount(Address address, BlockParameter blockParameter)
+ public Task> eth_getTransactionCount(Address address, BlockParameter blockParameter)
{
+
+ if (blockParameter == BlockParameter.Pending)
+ {
+ UInt256 pendingNonce = _txPoolBridge.GetLatestPendingNonce(address);
+ return Task.FromResult(ResultWrapper.Success(pendingNonce));
+
+ }
+
SearchResult searchResult = _blockFinder.SearchForHeader(blockParameter);
if (searchResult.IsError)
{
- return Task.FromResult(ResultWrapper.Fail(searchResult));
+ return Task.FromResult(ResultWrapper.Fail(searchResult));
}
BlockHeader header = searchResult.Object;
if (!HasStateForBlock(_blockchainBridge, header))
{
- return Task.FromResult(ResultWrapper.Fail($"No state available for block {header.Hash}",
+ return Task.FromResult(ResultWrapper.Fail($"No state available for block {header.Hash}",
ErrorCodes.ResourceUnavailable));
}
Account account = _stateReader.GetAccount(header.StateRoot, address);
UInt256 nonce = account?.Nonce ?? 0;
- return Task.FromResult(ResultWrapper.Success(nonce));
+ return Task.FromResult(ResultWrapper.Success(nonce));
}
public ResultWrapper eth_getBlockTransactionCountByHash(Keccak blockHash)
@@ -503,7 +511,7 @@ public Task> eth_getTransactionReceipt(Keccak txHas
{
return Task.FromResult(ResultWrapper.Success(null));
}
-
+
if (_logger.IsTrace) _logger.Trace($"eth_getTransactionReceipt request {txHash}, result: {txHash}");
return Task.FromResult(ResultWrapper.Success(new(txHash, receipt, effectiveGasPrice, logIndexStart)));
}
@@ -644,7 +652,7 @@ IEnumerable GetLogs(IEnumerable logs, CancellationTokenSou
cancellationToken.ThrowIfCancellationRequested();
fromBlockResult = _blockFinder.SearchForHeader(filter.FromBlock);
- }
+ }
if (fromBlockResult.IsError)
{
@@ -693,7 +701,7 @@ public ResultWrapper> eth_getWork()
return ResultWrapper.Fail("eth_submitHashrate not supported", ErrorCodes.MethodNotFound, null);
}
- // https://github.com/ethereum/EIPs/issues/1186
+ // https://github.com/ethereum/EIPs/issues/1186
public ResultWrapper eth_getProof(Address accountAddress, byte[][] storageKeys,
BlockParameter blockParameter)
{
diff --git a/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/EthRpcModuleProxy.cs b/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/EthRpcModuleProxy.cs
index d381eb03038..efd376a9647 100644
--- a/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/EthRpcModuleProxy.cs
+++ b/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/EthRpcModuleProxy.cs
@@ -1,16 +1,16 @@
// Copyright (c) 2021 Demerzel Solutions Limited
// This file is part of the Nethermind library.
-//
+//
// The Nethermind library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
-//
+//
// The Nethermind library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
-//
+//
// You should have received a copy of the GNU Lesser General Public License
// along with the Nethermind. If not, see .
@@ -84,7 +84,7 @@ public ResultWrapper eth_snapshot()
{
throw new NotSupportedException();
}
-
+
public ResultWrapper eth_maxPriorityFeePerGas()
{
throw new NotSupportedException();
@@ -112,8 +112,8 @@ public ResultWrapper eth_getStorageAt(Address address, UInt256 positionI
throw new NotSupportedException();
}
- public async Task> eth_getTransactionCount(Address address, BlockParameter blockParameter)
- => ResultWrapper.From(await _proxy.eth_getTransactionCount(address, MapBlockParameter(blockParameter)));
+ public async Task> eth_getTransactionCount(Address address, BlockParameter blockParameter)
+ => ResultWrapper.From(await _proxy.eth_getTransactionCount(address, MapBlockParameter(blockParameter)));
public ResultWrapper eth_getBlockTransactionCountByHash(Keccak blockHash)
{
@@ -152,9 +152,9 @@ public async Task> eth_sendTransaction(TransactionForRpc r
{
RpcResult chainIdResult = await _proxy.eth_chainId();
ulong chainId = chainIdResult?.IsValid == true ? (ulong)chainIdResult.Result : 0;
- RpcResult nonceResult =
+ RpcResult nonceResult =
await _proxy.eth_getTransactionCount(transaction.SenderAddress, BlockParameterModel.Pending);
- transaction.Nonce = nonceResult?.IsValid == true ? nonceResult.Result ?? UInt256.Zero : UInt256.Zero;
+ transaction.Nonce = nonceResult?.IsValid == true ? nonceResult.Result : UInt256.Zero;
_wallet.Sign(transaction, chainId);
}
@@ -317,7 +317,7 @@ public ResultWrapper eth_getProof(Address accountAddress, byte[][]
Value = transaction.Value
};
}
-
+
private static ReceiptForRpc? MapReceipt(ReceiptModel? receipt)
{
if (receipt is null)
diff --git a/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/IEthRpcModule.cs b/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/IEthRpcModule.cs
index 02aadc4cf03..66fdbeb960d 100644
--- a/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/IEthRpcModule.cs
+++ b/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/IEthRpcModule.cs
@@ -1,16 +1,16 @@
// Copyright (c) 2021 Demerzel Solutions Limited
// This file is part of the Nethermind library.
-//
+//
// The Nethermind library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
-//
+//
// The Nethermind library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
-//
+//
// You should have received a copy of the GNU Lesser General Public License
// along with the Nethermind. If not, see .
@@ -31,258 +31,258 @@ namespace Nethermind.JsonRpc.Modules.Eth
[RpcModule(ModuleType.Eth)]
public interface IEthRpcModule : IRpcModule
{
- [JsonRpcMethod(IsImplemented = true,
- Description = "Returns ChainID",
- IsSharable = true,
+ [JsonRpcMethod(IsImplemented = true,
+ Description = "Returns ChainID",
+ IsSharable = true,
ExampleResponse = "0x4")]
ResultWrapper eth_chainId();
-
+
[JsonRpcMethod(IsImplemented = true,
- Description = "Returns ETH protocol version",
- IsSharable = true,
+ Description = "Returns ETH protocol version",
+ IsSharable = true,
ExampleResponse = "0x41")]
ResultWrapper eth_protocolVersion();
-
- [JsonRpcMethod(IsImplemented = true,
- Description = "Returns syncing status",
- IsSharable = true,
+
+ [JsonRpcMethod(IsImplemented = true,
+ Description = "Returns syncing status",
+ IsSharable = true,
ExampleResponse = "{\"isSyncing\":true,\"startingBlock\":\"0x0\",\"currentBlock\":\"0x0\",\"highestBlock\":\"0x4df8a4\"},\"id\":1}")]
ResultWrapper eth_syncing();
-
- [JsonRpcMethod(IsImplemented = false,
- Description = "Returns miner's coinbase",
- IsSharable = true,
+
+ [JsonRpcMethod(IsImplemented = false,
+ Description = "Returns miner's coinbase",
+ IsSharable = true,
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,
+
+ [JsonRpcMethod(IsImplemented = true,
+ Description = "Returns block fee history.",
+ IsSharable = true,
ExampleResponse = "{\"baseFeePerGas\": [\"0x116c1cbb03\", \"0x10c3714c06\"], \"gasUsedRatio\": [0.3487305666666667, 0.3], \"oldestBlock\": \"0xc7e5ff\", \"reward\": [[\"0x3b9aca00\",\"0x3b9aca00\"], [\"0x0\",\"0x3bb24dfa\"]]}")]
ResultWrapper eth_feeHistory(long blockCount, BlockParameter newestBlock, double[]? rewardPercentiles = null);
-
+
[JsonRpcMethod(IsImplemented = false, Description = "Returns full state snapshot", IsSharable = true)]
ResultWrapper eth_snapshot();
-
+
[JsonRpcMethod(IsImplemented = false, Description = "", IsSharable = true)]
ResultWrapper eth_maxPriorityFeePerGas();
-
- [JsonRpcMethod(IsImplemented = false,
- Description = "Returns mining hashrate",
- IsSharable = true,
+
+ [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,
+
+ [JsonRpcMethod(IsImplemented = false,
+ Description = "Returns miner's gas price",
+ IsSharable = true,
ExampleResponse = "0x4a817c800" )]
ResultWrapper eth_gasPrice();
-
- [JsonRpcMethod(IsImplemented = false,
- Description = "Returns accounts",
- IsSharable = true,
+
+ [JsonRpcMethod(IsImplemented = false,
+ Description = "Returns accounts",
+ IsSharable = true,
ExampleResponse = "[\"0x9b96a7841d6e0b76872c85c86082959189a27342\"]")]
ResultWrapper> eth_accounts();
-
- [JsonRpcMethod(IsImplemented = true,
- Description = "Returns current block number",
- IsSharable = true,
+
+ [JsonRpcMethod(IsImplemented = true,
+ Description = "Returns current block number",
+ IsSharable = true,
ExampleResponse = "0x885480")]
Task> eth_blockNumber();
-
- [JsonRpcMethod(IsImplemented = true,
- Description = "Returns account balance",
+
+ [JsonRpcMethod(IsImplemented = true,
+ Description = "Returns account balance",
IsSharable = true,
ExampleResponse = "0x6c8ae945bfe6e")]
Task> eth_getBalance([JsonRpcParameter(ExampleValue = "[\"0x78467cada5f1883e79fcf0f3ebfa50abeec8c820\"]")] Address address, BlockParameter blockParameter = null);
-
- [JsonRpcMethod(IsImplemented = true,
- Description = "Returns storage data at address. storage_index",
- IsSharable = true,
+
+ [JsonRpcMethod(IsImplemented = true,
+ Description = "Returns storage data at address. storage_index",
+ IsSharable = true,
ExampleResponse = "0x")]
ResultWrapper eth_getStorageAt([JsonRpcParameter(ExampleValue = "[\"0x000000000000000000000000c666d239cbda32aa7ebca894b6dc598ddb881285\",\"0x2\"]")] Address address, UInt256 positionIndex, BlockParameter blockParameter = null);
-
- [JsonRpcMethod(IsImplemented = true,
- Description = "Returns account nonce (number of trnsactions from the account since genesis) at the given block number",
+
+ [JsonRpcMethod(IsImplemented = true,
+ Description = "Returns account nonce (number of trnsactions from the account since genesis) at the given block number",
IsSharable = true,
ExampleResponse = "0x3e")]
- Task> eth_getTransactionCount([JsonRpcParameter(ExampleValue = "[\"0xae3ed7a6ccdddf2914133d0669b5f02ff6fa8ad2\"]")] Address address, BlockParameter blockParameter = null);
-
- [JsonRpcMethod(IsImplemented = true,
- Description = "Returns number of transactions in the block block hash",
- IsSharable = true,
+ Task> eth_getTransactionCount([JsonRpcParameter(ExampleValue = "[\"0xae3ed7a6ccdddf2914133d0669b5f02ff6fa8ad2\"]")] Address address, BlockParameter blockParameter = null);
+
+ [JsonRpcMethod(IsImplemented = true,
+ Description = "Returns number of transactions in the block block hash",
+ IsSharable = true,
ExampleResponse = "0x20")]
ResultWrapper eth_getBlockTransactionCountByHash(
[JsonRpcParameter(ExampleValue = "[\"0x199c2ef63392fb67f929fe0580e11f62fa6c54b9951a624896da91375a6805b1\"]")] Keccak blockHash);
-
- [JsonRpcMethod(IsImplemented = true,
+
+ [JsonRpcMethod(IsImplemented = true,
Description = "Returns number of transactions in the block by block number",
IsSharable = true,
ExampleResponse = "0x20")]
ResultWrapper eth_getBlockTransactionCountByNumber([JsonRpcParameter(ExampleValue = "[\"8934677\"]")] BlockParameter blockParameter);
-
- [JsonRpcMethod(IsImplemented = true,
- Description = "Returns number of uncles in the block by block hash",
- IsSharable = true,
+
+ [JsonRpcMethod(IsImplemented = true,
+ Description = "Returns number of uncles in the block by block hash",
+ IsSharable = true,
ExampleResponse = "0x0")]
ResultWrapper eth_getUncleCountByBlockHash([JsonRpcParameter(ExampleValue = "[\"0xe495c3385bb9162103bc07989d7160c38759e017c37c7d0608268bd5989d6bed \"]")] Keccak blockHash);
-
- [JsonRpcMethod(IsImplemented = true,
- Description = "Returns number of uncles in the block by block number",
- IsSharable = true,
+
+ [JsonRpcMethod(IsImplemented = true,
+ Description = "Returns number of uncles in the block by block number",
+ IsSharable = true,
ExampleResponse = "0x0")]
ResultWrapper eth_getUncleCountByBlockNumber([JsonRpcParameter(ExampleValue = "[\"5127400\"]")] BlockParameter blockParameter);
-
+
[JsonRpcMethod(IsImplemented = true, Description = "Returns account code at given address and block", IsSharable = true)]
ResultWrapper eth_getCode(Address address, BlockParameter blockParameter = null);
-
+
[JsonRpcMethod(IsImplemented = false, Description = "Signs a transaction", IsSharable = true)]
ResultWrapper eth_sign(Address addressData, byte[] message);
-
- [JsonRpcMethod(IsImplemented = true,
- Description = "Send a transaction to the tx pool and broadcasting",
+
+ [JsonRpcMethod(IsImplemented = true,
+ Description = "Send a transaction to the tx pool and broadcasting",
IsSharable = true,
ExampleResponse = "0x03783fac2efed8fbc9ad443e592ee30e61d65f471140c10ca155e937b435b760")]
Task> eth_sendTransaction([JsonRpcParameter(ExampleValue = "[{\"From\": \"0xc2208fe87805279b03c1a8a78d7ee4bfdb0e48ee\", \"Gas\":\"21000\",\"GasPrice\":\"20000000000\", \"Nonce\":\"23794\", \"To\":\"0x2d44c0e097f6cd0f514edac633d82e01280b4a5c\"}]")] TransactionForRpc rpcTx);
-
- [JsonRpcMethod(IsImplemented = true,
- Description = "Send a raw transaction to the tx pool and broadcasting",
+
+ [JsonRpcMethod(IsImplemented = true,
+ Description = "Send a raw transaction to the tx pool and broadcasting",
IsSharable = true,
ExampleResponse = "0x7a5a94d5b5e3ce017ce2c2022f02ec5db10611c43695c3256861bdb19317ab0e"
)]
Task> eth_sendRawTransaction([JsonRpcParameter(ExampleValue = "[\"0xf86380843b9aca0082520894b943b13292086848d8180d75c73361107920bb1a80802ea0385656b91b8f1f5139e9ba3449b946a446c9cfe7adb91b180ddc22c33b17ac4da01fe821879d386b140fd8080dcaaa98b8c709c5025c8c4dea1334609ebac41b6c\"]")] byte[] transaction);
-
- [JsonRpcMethod(IsImplemented = true,
- Description = "Executes a tx call (does not create a transaction)",
+
+ [JsonRpcMethod(IsImplemented = true,
+ Description = "Executes a tx call (does not create a transaction)",
IsSharable = false,
ExampleResponse = "0x")]
ResultWrapper eth_call([JsonRpcParameter(ExampleValue = "[{\"from\":\"0x0001020304050607080910111213141516171819\",\"gasPrice\":\"0x100000\", \"data\": \"0x70a082310000000000000000000000006c1f09f6271fbe133db38db9c9280307f5d22160\", \"to\": \"0x0d8775f648430679a709e98d2b0cb6250d2887ef\"}]")] TransactionForRpc transactionCall, BlockParameter? blockParameter = null);
-
- [JsonRpcMethod(IsImplemented = true,
- Description = "Executes a tx call and returns gas used (does not create a transaction)",
+
+ [JsonRpcMethod(IsImplemented = true,
+ Description = "Executes a tx call and returns gas used (does not create a transaction)",
IsSharable = false,
ExampleResponse = "0x")]
ResultWrapper eth_estimateGas([JsonRpcParameter(ExampleValue = "[\"{\"from\": \"0x0001020304050607080910111213141516171819\", \"gasPrice\": \"1048576\", \"to\": \"0x0d8775f648430679a709e98d2b0cb6250d2887ef\"}\"]")] TransactionForRpc transactionCall, BlockParameter? blockParameter = null);
-
+
[JsonRpcMethod(IsImplemented = true,
Description = "Creates an [EIP2930](https://eips.ethereum.org/EIPS/eip-2930) type AccessList for the given transaction",
EdgeCaseHint = "If your transaction has code executed, then you can generate transaction access list with eth_createAccessList. If you send it with your transaction then it will lower your gas cost on Ethereum",
IsSharable = false,
ExampleResponse = "{\"accessList\":[{\"address\":\"0xfffffffffffffffffffffffffffffffffffffffe\",\"storageKeys\":[\"0x0000000000000000000000000000000000000000000000000000000000000001\",\"0x0000000000000000000000000000000000000000000000000000000000000002\"]},{\"address\":\"0x76e68a8696537e4141926f3e528733af9e237d69\",\"storageKeys\":[]}],\"gasUsed\":\"0xf71b\"}")]
- ResultWrapper eth_createAccessList(
+ ResultWrapper eth_createAccessList(
[JsonRpcParameter(Description = "Transaction's details", ExampleValue = "[\"{\"type\":\"0x1\"]")]
TransactionForRpc transactionCall,
[JsonRpcParameter(Description = "(optional)")]
BlockParameter? blockParameter = null,
[JsonRpcParameter(Description = "(optional)")]
bool optimize = true);
-
- [JsonRpcMethod(IsImplemented = true,
- Description = "Retrieves a block by hash",
+
+ [JsonRpcMethod(IsImplemented = true,
+ Description = "Retrieves a block by hash",
IsSharable = true,
ExampleResponse = "{\"author\":\"0x0000000000000000000000000000000000000000\",\"difficulty\":\"0x1\",\"extraData\":\"0x000000000000436f6e73656e5379732048797065726c656467657220426573754d3f7b71165a8266fcc569c96b6fcf9971ee4a8df59eeec4dcced0df8d778733429988e21d0124918859f988be9debf4b25fb5282ea41a2fc15f827f446ec93200\",\"gasLimit\":\"0x1c9c364\",\"gasUsed\":\"0x3aa87\",\"hash\":\"0xf33507f93a046dbdbb80dee5f47b84283297f6c53f1b665adc3cb6fe4138aa84\",\"logsBloom\":\"0x00000000000020000000000008000060000000000000000000000000000000000000000000000000201000020008000000000000000000000100000000200020000000000000000000000008000000000000000010000000000000000000000000000000000000000000080000000000000000000000002000000010000000000000000000000000000000000000000000040000001000000000000000020000020400000000000000000000000000000000000000000000000000010000000000000002080000000000000000020000000000000000000000000000000000000010020000000000000000000000000100000000000000000000010000000000\",\"miner\":\"0x0000000000000000000000000000000000000000\",\"mixHash\":\"0x0000000000000000000000000000000000000000000000000000000000000000\",\"nonce\":\"0x0000000000000000\",\"number\":\"0x4e3d79\",\"parentHash\":\"0x01dba3a7eb61dc6dba3f9663c8fb632f76f60a476f57df74c3e5bd9d0a246339\",\"receiptsRoot\":\"0x70f3bd929735d8edeb953cd30a27e703e7dd3ec4af32cb74fe8ac302f9e7fb87\",\"sha3Uncles\":\"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347\",\"size\":\"0x754\",\"stateRoot\":\"0x71af7e25302d1baa4c988c267450eb2c7fa20938fac377809c8d77f8ff8108ac\",\"totalDifficulty\":\"0x726275\",\"timestamp\":\"0x60ec1218\",\"baseFeePerGas\":\"0x7\",\"transactions\":[\"0xa65d391d8149ed0906fab923e870d2bc7f6d27c2be10fe1bcfc6f02869b38ef3\",\"0x369a89354041b7a8cb40edce51c36ebb0ee6ffa4d8056f5a658d90f3bbe1a81a\",\"0xf857daf60d03381b9a6ecb341b62798b424d20dc05763858e13955dd866b489d\"],\"transactionsRoot\":\"0x90115f8dc10c08e748675f52f3904615729a014461ca80d72c60239bf75ee209\",\"uncles\":[]}")]
ResultWrapper eth_getBlockByHash([JsonRpcParameter(ExampleValue = "[\"0xf33507f93a046dbdbb80dee5f47b84283297f6c53f1b665adc3cb6fe4138aa84\"]")] Keccak blockHash, bool returnFullTransactionObjects = false);
-
- [JsonRpcMethod(IsImplemented = true,
- Description = "Retrieves a block by number",
+
+ [JsonRpcMethod(IsImplemented = true,
+ Description = "Retrieves a block by number",
IsSharable = true,
ExampleResponse = "{\"author\":\"0x0000000000000000000000000000000000000000\",\"difficulty\":\"0x1\",\"extraData\":\"0x000000000000436f6e73656e5379732048797065726c656467657220426573754d3f7b71165a8266fcc569c96b6fcf9971ee4a8df59eeec4dcced0df8d778733429988e21d0124918859f988be9debf4b25fb5282ea41a2fc15f827f446ec93200\",\"gasLimit\":\"0x1c9c364\",\"gasUsed\":\"0x3aa87\",\"hash\":\"0xf33507f93a046dbdbb80dee5f47b84283297f6c53f1b665adc3cb6fe4138aa84\",\"logsBloom\":\"0x00000000000020000000000008000060000000000000000000000000000000000000000000000000201000020008000000000000000000000100000000200020000000000000000000000008000000000000000010000000000000000000000000000000000000000000080000000000000000000000002000000010000000000000000000000000000000000000000000040000001000000000000000020000020400000000000000000000000000000000000000000000000000010000000000000002080000000000000000020000000000000000000000000000000000000010020000000000000000000000000100000000000000000000010000000000\",\"miner\":\"0x0000000000000000000000000000000000000000\",\"mixHash\":\"0x0000000000000000000000000000000000000000000000000000000000000000\",\"nonce\":\"0x0000000000000000\",\"number\":\"0x4e3d79\",\"parentHash\":\"0x01dba3a7eb61dc6dba3f9663c8fb632f76f60a476f57df74c3e5bd9d0a246339\",\"receiptsRoot\":\"0x70f3bd929735d8edeb953cd30a27e703e7dd3ec4af32cb74fe8ac302f9e7fb87\",\"sha3Uncles\":\"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347\",\"size\":\"0x754\",\"stateRoot\":\"0x71af7e25302d1baa4c988c267450eb2c7fa20938fac377809c8d77f8ff8108ac\",\"totalDifficulty\":\"0x726275\",\"timestamp\":\"0x60ec1218\",\"baseFeePerGas\":\"0x7\",\"transactions\":[\"0xa65d391d8149ed0906fab923e870d2bc7f6d27c2be10fe1bcfc6f02869b38ef3\",\"0x369a89354041b7a8cb40edce51c36ebb0ee6ffa4d8056f5a658d90f3bbe1a81a\",\"0xf857daf60d03381b9a6ecb341b62798b424d20dc05763858e13955dd866b489d\"],\"transactionsRoot\":\"0x90115f8dc10c08e748675f52f3904615729a014461ca80d72c60239bf75ee209\",\"uncles\":[]}")]
ResultWrapper eth_getBlockByNumber([JsonRpcParameter(ExampleValue = "[\"5127545\"]")] BlockParameter blockParameter, bool returnFullTransactionObjects = false);
-
- [JsonRpcMethod(IsImplemented = true,
- Description = "Retrieves a transaction by hash",
- IsSharable = true,
+
+ [JsonRpcMethod(IsImplemented = true,
+ Description = "Retrieves a transaction by hash",
+ IsSharable = true,
ExampleResponse = "{\"hash\":\"0xabca23910646013d608ec671de099447ab60b2b7159ad8319c3c088e8d9ea0fa\",\"nonce\":\"0x1a\",\"blockHash\":\"0xcb6756f69e0469acd5e5bb77966be580786ec2c11de85c9ddfd75257010e34f8\",\"blockNumber\":\"0x4dfbc7\",\"transactionIndex\":\"0xb\",\"from\":\"0xe1e7ab1c643dbe5b24739fdf2a5c7c193b54dd99\",\"to\":\"0x0b10e304088b2ba2b2acfd2f72573faad31a13a5\",\"value\":\"0x0\",\"gasPrice\":\"0x2540be400\",\"gas\":\"0xb4a4\",\"data\":\"0x095ea7b300000000000000000000000092c1576845703089cf6c0788379ed81f75f45dd500000000000000000000000000000000000000000000000000000002540be400\",\"input\":\"0x095ea7b300000000000000000000000092c1576845703089cf6c0788379ed81f75f45dd500000000000000000000000000000000000000000000000000000002540be400\",\"type\":\"0x0\",\"v\":\"0x2d\",\"s\":\"0x496d72d435ead8a8a9a865b14d6a102c1a9f848681d050dbbf11c522c612235\",\"r\":\"0xc8350e831203fecc8bff41f5cf858ac1d121e4b4d9e59c1137cc9440516ca9fd\"}")]
Task> eth_getTransactionByHash(
[JsonRpcParameter(ExampleValue = "\"0xabca23910646013d608ec671de099447ab60b2b7159ad8319c3c088e8d9ea0fa\"")] Keccak transactionHash);
-
- [JsonRpcMethod(IsImplemented = true,
+
+ [JsonRpcMethod(IsImplemented = true,
Description = "Returns the pending transactions list",
- IsSharable = true,
+ IsSharable = true,
ExampleResponse = "[]")]
ResultWrapper eth_pendingTransactions();
-
- [JsonRpcMethod(IsImplemented = true,
- Description = "Retrieves a transaction by block hash and index",
+
+ [JsonRpcMethod(IsImplemented = true,
+ Description = "Retrieves a transaction by block hash and index",
IsSharable = true,
ExampleResponse = "{\"hash\":\"0xb87ec4c8cb36a06f49cdd93c2e9f63e0b7db9af07a605c8bcf1fbe705162344e\",\"nonce\":\"0x5d\",\"blockHash\":\"0xfe47fb3539ccce9d19a032473effdd6ce19e3c921bbae2746152ccf82ceef48e\",\"blockNumber\":\"0x4dfc90\",\"transactionIndex\":\"0x2\",\"from\":\"0xaa9a0f962e433755c843175488fe088fccf8526f\",\"to\":\"0x074b24cef703f17fe123fa1b82081055775b7004\",\"value\":\"0x0\",\"gasPrice\":\"0x2540be401\",\"gas\":\"0x130ab\",\"data\":\"0x428dc451000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000030000000000000000000000005d3c0f4ca5ee99f8e8f59ff9a5fab04f6a7e007f0000000000000000000000009d233a907e065855d2a9c7d4b552ea27fb2e5a36000000000000000000000000cbe56b00d173a26a5978ce90db2e33622fd95a28\",\"input\":\"0x428dc451000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000030000000000000000000000005d3c0f4ca5ee99f8e8f59ff9a5fab04f6a7e007f0000000000000000000000009d233a907e065855d2a9c7d4b552ea27fb2e5a36000000000000000000000000cbe56b00d173a26a5978ce90db2e33622fd95a28\",\"type\":\"0x0\",\"v\":\"0x2e\",\"s\":\"0x696f6db060a6dd30435a7f592506ba3213f81cf4704e211a1a45a99f8984189a\",\"r\":\"0x7e07076186e38b68cb7e4f68a04258a5744c5a2ad1a7153456ee662a07902954\"}")]
ResultWrapper eth_getTransactionByBlockHashAndIndex(
[JsonRpcParameter(ExampleValue = "[\"0xfe47fb3539ccce9d19a032473effdd6ce19e3c921bbae2746152ccf82ceef48e\",\"0x2\"]")] Keccak blockHash, UInt256 positionIndex);
-
- [JsonRpcMethod(IsImplemented = true,
- Description = "Retrieves a transaction by block number and index",
- IsSharable = true,
+
+ [JsonRpcMethod(IsImplemented = true,
+ Description = "Retrieves a transaction by block number and index",
+ IsSharable = true,
ExampleResponse = "{\"hash\":\"0xfd320a4949990929f64b52041c58a74c8ce13289b3d6853bd8073b0580aa031a\",\"nonce\":\"0x5b\",\"blockHash\":\"0xd779e1a5ce8f34544d66d219bb3e5331a7b280fae89a36d7d52813a23e1ca1e3\",\"blockNumber\":\"0x4dfdd8\",\"transactionIndex\":\"0x8\",\"from\":\"0xadb540569e2db497bd973c141b0b63be98461e40\",\"to\":\"0x074b24cef703f17fe123fa1b82081055775b7004\",\"value\":\"0x0\",\"gasPrice\":\"0x12a05f200\",\"gas\":\"0x927c0\",\"data\":\"0x428dc451000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000030000000000000000000000005d3c0f4ca5ee99f8e8f59ff9a5fab04f6a7e007f0000000000000000000000009d233a907e065855d2a9c7d4b552ea27fb2e5a36000000000000000000000000cbe56b00d173a26a5978ce90db2e33622fd95a28\",\"input\":\"0x428dc451000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000030000000000000000000000005d3c0f4ca5ee99f8e8f59ff9a5fab04f6a7e007f0000000000000000000000009d233a907e065855d2a9c7d4b552ea27fb2e5a36000000000000000000000000cbe56b00d173a26a5978ce90db2e33622fd95a28\",\"type\":\"0x0\",\"v\":\"0x2e\",\"s\":\"0x37b90a929884787df717c87258f0434e2f115ce2fbb4bfc230322112fa9d5bbc\",\"r\":\"0x5222eff9e16b5c3e9e8901d9c45fc8e0f9cf774e8a56546a504025ef67ceefec\"}")]
ResultWrapper eth_getTransactionByBlockNumberAndIndex(
[JsonRpcParameter(ExampleValue = "[\"5111256\",\"0x8\"]" )] BlockParameter blockParameter, UInt256 positionIndex);
-
- [JsonRpcMethod(IsImplemented = true,
- Description = "Retrieves a transaction receipt by tx hash",
+
+ [JsonRpcMethod(IsImplemented = true,
+ Description = "Retrieves a transaction receipt by tx hash",
IsSharable = true,
ExampleResponse = "{\"transactionHash\":\"0x80757153e93d1b475e203406727b62a501187f63e23b8fa999279e219ee3be71\",\"transactionIndex\":\"0x7\",\"blockHash\":\"0x42def051b21038905cd2a2bc28d460a94df2249466847f0e1bcb4be4eb21891a\",\"blockNumber\":\"0x4e3f39\",\"cumulativeGasUsed\":\"0x62c9d\",\"gasUsed\":\"0xe384\",\"effectiveGasPrice\":\"0x12a05f200\",\"from\":\"0x0afe0a94415e8974052e7e6cfab19ee1c2ef4f69\",\"to\":\"0x19e8c84d4943e58b035626b064cfc76ee13ee6cb\",\"contractAddress\":null,\"logs\":[{\"removed\":false,\"logIndex\":\"0x0\",\"transactionIndex\":\"0x7\",\"transactionHash\":\"0x80757153e93d1b475e203406727b62a501187f63e23b8fa999279e219ee3be71\",\"blockHash\":\"0x42def051b21038905cd2a2bc28d460a94df2249466847f0e1bcb4be4eb21891a\",\"blockNumber\":\"0x4e3f39\",\"address\":\"0x2ac3c1d3e24b45c6c310534bc2dd84b5ed576335\",\"data\":\"0x0000000000000000000000000000000000000000000000000000000000000000\",\"topics\":[\"0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef\",\"0x00000000000000000000000019e8c84d4943e58b035626b064cfc76ee13ee6cb\",\"0x00000000000000000000000028078300a459a9e136f872285654cdc74463041e\"]},{\"removed\":false,\"logIndex\":\"0x1\",\"transactionIndex\":\"0x7\",\"transactionHash\":\"0x80757153e93d1b475e203406727b62a501187f63e23b8fa999279e219ee3be71\",\"blockHash\":\"0x42def051b21038905cd2a2bc28d460a94df2249466847f0e1bcb4be4eb21891a\",\"blockNumber\":\"0x4e3f39\",\"address\":\"0x19e8c84d4943e58b035626b064cfc76ee13ee6cb\",\"data\":\"0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007735940000000000000000000000000000000000000000000000000000000000000000000\",\"topics\":[\"0x950494fc3642fae5221b6c32e0e45765c95ebb382a04a71b160db0843e74c99f\",\"0x0000000000000000000000000afe0a94415e8974052e7e6cfab19ee1c2ef4f69\",\"0x00000000000000000000000028078300a459a9e136f872285654cdc74463041e\",\"0x0000000000000000000000000afe0a94415e8974052e7e6cfab19ee1c2ef4f69\"]}],\"logsBloom\":\"0x00000000000000000000000000000000000000000000000020000000000000800000000000000000000400000000000000000000000000000000000000002000000000000000000000000008000000000000000000000000000000000000000000000002002000000000000000000000000000000000000000000812000000000000000000000000000001000000000000000000000008000400008000000000000000000000000000000000000000000000000000000000800000000000000000000002000000000000000000000000000000000000100000000000000000002000000000000000000000000010000000000000000000000400000000020000\",\"status\":\"0x1\",\"type\":\"0x0\"}")]
Task> eth_getTransactionReceipt([JsonRpcParameter(ExampleValue = "[\"0x80757153e93d1b475e203406727b62a501187f63e23b8fa999279e219ee3be71\"]")] Keccak txHashData);
-
- [JsonRpcMethod(IsImplemented = true,
- Description = "Retrieves an uncle block header by block hash and uncle index",
+
+ [JsonRpcMethod(IsImplemented = true,
+ Description = "Retrieves an uncle block header by block hash and uncle index",
IsSharable = true)]
ResultWrapper eth_getUncleByBlockHashAndIndex(Keccak blockHashData, UInt256 positionIndex);
-
+
[JsonRpcMethod(IsImplemented = true, Description = "Retrieves an uncle block header by block number and uncle index", IsSharable = true)]
ResultWrapper eth_getUncleByBlockNumberAndIndex(BlockParameter blockParameter, UInt256 positionIndex);
-
- [JsonRpcMethod(IsImplemented = true,
- Description = "Creates an update filter",
+
+ [JsonRpcMethod(IsImplemented = true,
+ Description = "Creates an update filter",
IsSharable = false,
ExampleResponse = "0x9")]
ResultWrapper eth_newFilter([JsonRpcParameter(ExampleValue = "[{\"toBlock\":\"latest\"}]" )] Filter filter);
-
- [JsonRpcMethod(IsImplemented = true,
- Description = "Creates an update filter",
- IsSharable = false,
+
+ [JsonRpcMethod(IsImplemented = true,
+ Description = "Creates an update filter",
+ IsSharable = false,
ExampleResponse = "0x0")]
ResultWrapper eth_newBlockFilter();
-
- [JsonRpcMethod(IsImplemented = true,
- Description = "Creates an update filter",
- IsSharable = false,
+
+ [JsonRpcMethod(IsImplemented = true,
+ Description = "Creates an update filter",
+ IsSharable = false,
ExampleResponse = "0x1")]
ResultWrapper eth_newPendingTransactionFilter();
-
- [JsonRpcMethod(IsImplemented = true,
- Description = "Creates an update filter",
+
+ [JsonRpcMethod(IsImplemented = true,
+ Description = "Creates an update filter",
IsSharable = false)]
ResultWrapper eth_uninstallFilter(UInt256 filterId);
-
- [JsonRpcMethod(IsImplemented = true,
- Description = "Reads filter changes",
+
+ [JsonRpcMethod(IsImplemented = true,
+ Description = "Reads filter changes",
IsSharable = true,
ExampleResponse = "[]")]
ResultWrapper> eth_getFilterChanges([JsonRpcParameter(ExampleValue = "[\"0x9\"]" )] UInt256 filterId);
-
- [JsonRpcMethod(IsImplemented = true,
- Description = "Reads filter changes",
+
+ [JsonRpcMethod(IsImplemented = true,
+ Description = "Reads filter changes",
IsSharable = true,
ExampleResponse = "[]")]
ResultWrapper> eth_getFilterLogs([JsonRpcParameter(ExampleValue = "[\"0x9\"]")] UInt256 filterId);
-
+
[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,
+
+ [JsonRpcMethod(Description = "https://github.com/ethereum/EIPs/issues/1186",
+ IsImplemented = true,
IsSharable = true,
ExampleResponse = " \"accountProof\": [\"0xf90211a0446f43a2d3e433732c75bcf3519f4844e0441a4d39b31395ee9a65700c30d3b4a0b9720db63afe9909418fb6e02c9d9f225310856549cc1b66b486041f2d867250a046e6e560e52d4fe0d2f6609f489ba85f18ad1655fee18452588dc08388fbd711a01e68f36c91bd15cbf65587d6db2a7cbd6635907291e77dd80152161da9a28a48a0d2178a1891c26ccaa2d2cec82c231a0640a26a1f5e07c7b5493761bdb3aa94e5a0fa909327d406980a2e602eadd3f56cf8dc89320d4662340962e9cac2beee3d8da0a0fc71e7dec6320a993b4b65b2f82544910d0a4a7c6f8c5a1ebaa38357d259e3a0680161dec84c5f1c8d5e2a585c9708b1b6fbc2dc664a432e045d99f5e7d89259a0f76a745765be58d46d795c44d3900a4a05b6396530244d50822616c8bbb11e19a0594824352d58f5caff819c8df9581b6a41d0e94eb584ed0431d48b48f320bb5ca0e762eb52b2bcacd728fac605de6229dc83588001ecddcd3b454b64c393ee69eda0d319cf1021af0a8535e4916c3404c84917957d73d0711f71fd6456b4533993bba0878240238a894e6fa798671ac3792563c6666a7c7fba8066d090b65d6a7aa701a03c03fdb4d8f4b241442814cbab24ddb42b75c78874f92fedc162b65d0820fc4da06a3318509aa9ff009b9acb9b348f197a134a46a46295714f436d4fbb19057e69a04139df1b6e0a59b093b35f34f9e5e890bc06832e63b366d768dc29e8638b828480\",\"0xf90211a023459f17e04fba3d19c6993f5be413969842fdbdc85d234a91b2f6b08a38be87a0153060eafecbff55ef0794802ef722b6c66698141cdc0610352d3a426976adeba0bd642b7c5111a1fd09da33feb6df031dc352b6cb20fbbe5ebe3eb328db233bd4a0705bff29e05c7ef69c07fecaa5db2457b2f124befc82f9fe6b0e54c8e35632eba03c1b4ffc076434de97050d2351c24689cfaefaa6cf8dc398dd3b8ce365e652c1a0a1ebf845ea0eb252e2a2e5c422ccd74878a3733144dfd62bcaad34758cc98652a01e4184586f5bdbb17ba74fd87539f02378c7adcef99f1538108f9555520e32d6a0b8acdfd5b644fa2c9a54f68039a3af4c6562c1e7f91ea9e63bda5a849f1260b6a05c1f036a2e7a5829799fc7df2d87eac3e7aee55df461b040c36f5b5c61781059a0a67fd871d32642e44120331f76c2616096d04d7fa1a7db421bafbc39713d8bfba085c15b7ab64f61670f4422adb82176d5808fad4abde6fddda507b0e5ff92ba14a0d95e8f16a39d4e52c67c617eef486adcd947854373ac074ff498150c7ca1ab5da03d9d7be595000872ad6aec05667ad85e1aaaeb2050a692818d3e60d8f1628d8ba0984c657192b052d13fb717051631d67fbc83dd5dcb4d074a2fddc01aa122d95ba03643408862d758aea269c05027a1cd616c957e0db5daea529b56964db8b4f04ba01020dce8d692c3d84d9ae3e42c35e4d8adbddf7b4dd3e09e543fc980849f016e80\",\"0xf90211a04c71b4b56ed723da1c1353ec1b4c23e71dfa821664d4041c1ee1770221f507b6a031c851f261a38df9b2bece1a1cb6985bccfaa10d2bb15954b82cd2ceaad87032a08a4a3d0cc260cf0e0fef54490ce45796fdd3f522451976ca7834563c839c630fa003d074f79074566cd33a3d6a57b6ca8426ca9ea972f66b5dfde00f73287fcfcea07003d29a5bd192038600118ab5941af5c79c1f0fc6184ad564180b809c36c7c4a05f181c50402dcff567abe1c6679a8d5e3825125abca4d969c7cbf76503416813a06a85dfca80e442ef79b66162099d52eaf67718589eb794755ce57dc071a85cdaa085cba9e6937a8a5f0a7d1b5ee9eb9f03c40f89eb13d9d4e0e5fbc574c2b852faa063f93dce441a3373cfc2d1c855884682dfd8d09d1eb9844c73d88eb8d5a7cdfda0e4bc0d2597e5fd0a4cd5e76a03b657ef8959264bdeaf95c4412ebd4ff736ce44a00239290e698aa04485e0c342cfb76ccf27a3e45a161b8b1b534e0c46707b92c8a0080c3439fb84730924539797aad8d017c5f7e008314ed9086450d80ec2b0d7aba0861dbe37b9b9e0f58b6fdb83eec28045c5f7f1861530f47f78fc8a2b18a6bd8da0036697e8dc063e9086d115d468c934a01123adb3c66dcc236ee4aa8141888626a033c6f574ee79d9b1322e9ca1131a5984b33cc8881e6ac8ebd6ca36f3437cedcda07fc2855e6bb0f276202094dffe49f2b62f2366d9aba9db3ffe76d62bcdc29f0d80\",\"0xf90211a06995d919b53eefa0b097d75c2a5dee2c54109a06d3b60586327fa0086437b801a05c7d7c92f9f1e49cf27c5d97b4a96302f033d42df5b1d7c013ef05031d67e567a05278417d007913a1e7d6606fb464e7b81f6cee91b6a1d250c67b3822d9fc68d8a0fba6d9cd68fe72db07af9d99e30c32502e0afb15ee9712f6781014195444b9e1a07dca25ba23f429b5960d9feb23367e2a088e50211f280118b7f1703e6d47103fa0399eb6e0d4390688f6b28df56c7ad72d6b6cbac9066110c6a727fe35cd889e9da08ef84ddaa3b70095fb5624878289744740a9f8761ef1132ba722abc977a218ffa04296811ae184892e2d5ecc18d05fc6279d6168eb0f3abb1f97d8d0a0721c12fba05c46766c579b8a0b8a0b79b84f6cd1e5dae1c53a2988883b0385daa2cf3bdf82a01a4ba17dd1b59147a321dd374a22a0d959f1a79d70132db7f1a8b89968ff6062a0f7ffc6f3921c6bccd47c862519409e63f51d39aaa215819c664b1adb48a940b0a0dc6e636385407900a649917fb772b0972d50d197e9fd5cdb853a1c98a29e6a47a0674b224cf784c59ca937bfebbdcd8dec05ddbd57400b04f5965558a0c2d2299ca0f95ce8c921c5b17ebf74563f2496a88631aa6a697bfd9e3e22b326efa453115ea0fc133bc6b9dd098933c816660df2959074f47dfc4ab3a10fd2059a2b2e0e911aa057cac15218d6013890df78eec099144ba2000e3eea73a3498d0eb9b1f733459080\",\"0xf90211a0400aafe69a1a482277db720d12b9c0b98695f5dd78c6faf5421b3ddac50165a6a0235987542e4b37aa8e6957776c9dff11d6818797db5ad505de5e0049045c7e20a0f573b4776f8b323b7d55850300d53855cfa6fa5fe6e36ba64da6bb263fef774aa0b3a36d14d660c3492785b0f1488a2231b6d83bd51268685b95ba9267aa331fe2a0096e8c65bae8fce7d234710a1e1b8c98bd4fb2d56f8bb2eda7ef20d1cf31c7e2a059194c8bf50c2ac393c4c60a59c7ddf0c515bd9f545fc4ef212629a8b96af62aa0ffe882f4e2f1e8e49c7777f6f9b4438a9f31d4e5cefe82c96fdd3587d9a95173a00127ced7fdbdd57cd5ed8b766c9312c09e0c67a350087d22b4cc7b2d17a45479a0cfc030a250448838caa716cd2767cd1a4837b29019f474980720c94fe2ce412ea079ec358d2b4122692bf70eb73a0ddb0ff4bfeb05d503fe1acafe068e2d3d33cfa0733e2ccdc638ca3c940c566c742a1b9d58f7caaa062e8a121c07f5e3367160a8a0aa1f403798b71c67b821e6f6128cc5366bebe145ebd563714cf9972b2474814ea01b988afc628922aeed3de606a8a462093f1c0c803a563bbe178552a360bad1e1a0082741e2219024bf4e19f5b1b0643e5e885cb7dfb4cdc0a51faf5bd9f92ff9b6a03c86490fe8f0256be44b95815086d95cb62fdbc3ede63ca08d12d68f274b7fc5a03a81565e860ac32921ed4c9f4e0ace3b341c342abd030d4955f2d1e64dd81d2b80\",\"0xf8f1a0bd9a0d9559513a6c7bf427816142d254d5a9049e9ff385f3514b50cb828951fc808080a07d37353f509c9bdc99635bd75fde71a6ef99271154ac4ffd5c437e0b951d5eaca029e3beec2f52c99a1fa73251ed64486f2766af3dcb950900679f7fd740badfdaa09b348c93803521a41bd2a754e3ea5435bb2663724cdfb70a87984458b53f03dea0904e696aceac8c89e2825e0dae8add52a9b46faef2ffbabb932e8bc1267e48ba80a0935dedba6ec5fb5b89285993c5f1be0cb77492e63e11bb38b5aca18011699eb8a06b52f587932dfb669f6cbefe35b251c6d8e6b5e8a2e1c1a7c2a452a4f2917b0d808080808080\"],\"address\":\"0x7f0d15c7faae65896648c8273b6d7e43f58fa842\",\"balance\":\"0x0\",\"codeHash\":\"0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470\",\"nonce\":\"0x0\",\"storageHash\":\"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421\",\"storageProof\":[{\"key\":\"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421\",\"proof\":[],\"value\":\"0x00\"]")]
ResultWrapper eth_getProof([JsonRpcParameter(ExampleValue = "[\"0x7F0d15C7FAae65896648C8273B6d7E43f58Fa842\",[ \"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421\" ],\"latest\"]")] Address accountAddress, byte[][] hashRate, BlockParameter blockParameter);
diff --git a/src/Nethermind/Nethermind.TxPool.Test/TxPoolTests.cs b/src/Nethermind/Nethermind.TxPool.Test/TxPoolTests.cs
index c87d6aa8e21..71fa9e2c2ce 100644
--- a/src/Nethermind/Nethermind.TxPool.Test/TxPoolTests.cs
+++ b/src/Nethermind/Nethermind.TxPool.Test/TxPoolTests.cs
@@ -275,6 +275,53 @@ public void should_ignore_old_nonce_transactions()
result.Should().Be(AcceptTxResult.OldNonce);
}
+ [Test]
+ public void get_next_pending_nonce()
+ {
+ _txPool = CreatePool();
+
+ // LatestPendingNonce=0, when account does not exist
+ UInt256? latestNonce = _txPool.GetLatestPendingNonce(TestItem.AddressA);
+
+ _stateProvider.CreateAccount(TestItem.AddressA, 10.Ether());
+
+ // LatestPendingNonce=0, for a new account
+ latestNonce = _txPool.GetLatestPendingNonce(TestItem.AddressA);
+ Assert.AreEqual(latestNonce, (UInt256)0);
+
+ // LatestPendingNonce=1, when the current nonce of the account=1 and no pending transactions
+ _stateProvider.IncrementNonce(TestItem.AddressA);
+ latestNonce = _txPool.GetLatestPendingNonce(TestItem.AddressA);
+ Assert.AreEqual(latestNonce, (UInt256)1);
+
+ // LatestPendingNonce=1, when a pending transaction added to the pool with a gap in nonce (skipping nonce=1)
+ Transaction tx = Build.A.Transaction.WithNonce(2).SignedAndResolved(_ethereumEcdsa, TestItem.PrivateKeyA).TestObject;
+ AcceptTxResult result = _txPool.SubmitTx(tx, TxHandlingOptions.PersistentBroadcast);
+ result.Should().Be(AcceptTxResult.Accepted);
+ latestNonce = _txPool.GetLatestPendingNonce(TestItem.AddressA);
+ Assert.AreEqual(latestNonce, (UInt256)1);
+
+ // LatestPendingNonce=5, when added pending transactions upto nonce=4
+ tx = Build.A.Transaction.WithNonce(1).SignedAndResolved(_ethereumEcdsa, TestItem.PrivateKeyA).TestObject;
+ result = _txPool.SubmitTx(tx, TxHandlingOptions.PersistentBroadcast);
+ result.Should().Be(AcceptTxResult.Accepted);
+ tx = Build.A.Transaction.WithNonce(3).SignedAndResolved(_ethereumEcdsa, TestItem.PrivateKeyA).TestObject;
+ result = _txPool.SubmitTx(tx, TxHandlingOptions.PersistentBroadcast);
+ result.Should().Be(AcceptTxResult.Accepted);
+ tx = Build.A.Transaction.WithNonce(4).SignedAndResolved(_ethereumEcdsa, TestItem.PrivateKeyA).TestObject;
+ result = _txPool.SubmitTx(tx, TxHandlingOptions.PersistentBroadcast);
+ result.Should().Be(AcceptTxResult.Accepted);
+ latestNonce = _txPool.GetLatestPendingNonce(TestItem.AddressA);
+ Assert.AreEqual(latestNonce, (UInt256)5);
+
+ //LatestPendingNonce=5, when added a new pending transaction with a gap in nonce (skipped nonce=5)
+ tx = Build.A.Transaction.WithNonce(6).SignedAndResolved(_ethereumEcdsa, TestItem.PrivateKeyA).TestObject;
+ result = _txPool.SubmitTx(tx, TxHandlingOptions.PersistentBroadcast);
+ result.Should().Be(AcceptTxResult.Accepted);
+ latestNonce = _txPool.GetLatestPendingNonce(TestItem.AddressA);
+ Assert.AreEqual(latestNonce, (UInt256)5);
+ }
+
[Test]
public void should_ignore_overflow_transactions()
{
diff --git a/src/Nethermind/Nethermind.TxPool/Collections/SortedPool.cs b/src/Nethermind/Nethermind.TxPool/Collections/SortedPool.cs
index b5d85b832d2..35c5327dcba 100644
--- a/src/Nethermind/Nethermind.TxPool/Collections/SortedPool.cs
+++ b/src/Nethermind/Nethermind.TxPool/Collections/SortedPool.cs
@@ -1,16 +1,16 @@
// Copyright (c) 2021 Demerzel Solutions Limited
// This file is part of the Nethermind library.
-//
+//
// The Nethermind library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
-//
+//
// The Nethermind library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
-//
+//
// You should have received a copy of the GNU Lesser General Public License
// along with the Nethermind. If not, see .
@@ -24,28 +24,28 @@
namespace Nethermind.TxPool.Collections
{
///
- /// Keeps a pool of with in groups based on .
+ /// Keeps a pool of with in groups based on .
///
/// Type of keys of items, unique in pool.
/// Type of items that are kept.
/// Type of groups in which the items are organized
- public abstract partial class SortedPool
+ public abstract partial class SortedPool
where TKey : notnull
where TGroupKey : notnull
{
private readonly int _capacity;
-
+
// comparer for a bucket
private readonly IComparer _groupComparer;
-
+
// group buckets, keep the items grouped by group key and sorted in group
- protected readonly IDictionary> _buckets;
-
+ private readonly IDictionary> _buckets;
+
private readonly IDictionary _cacheMap;
-
+
// comparer for worst elements in buckets
private readonly IComparer _sortedComparer;
-
+
// worst element from every group, used to determine element that will be evicted when pool is full
protected readonly DictionarySortedSet _worstSortedValues;
@@ -61,7 +61,7 @@ protected SortedPool(int capacity, IComparer comparer)
_sortedComparer = GetUniqueComparer(comparer ?? throw new ArgumentNullException(nameof(comparer)));
_groupComparer = GetGroupComparer(comparer ?? throw new ArgumentNullException(nameof(comparer)));
_cacheMap = new Dictionary(); // do not initialize it at the full capacity
- _buckets = new Dictionary>();
+ _buckets = new Dictionary>();
_worstSortedValues = new DictionarySortedSet(_sortedComparer);
}
@@ -71,14 +71,14 @@ protected SortedPool(int capacity, IComparer comparer)
/// Original comparer.
/// Identity comparer.
protected abstract IComparer GetUniqueComparer(IComparer comparer);
-
+
///
/// Gets comparer for same group.
///
/// Original comparer.
/// Group comparer.
protected abstract IComparer GetGroupComparer(IComparer comparer);
-
+
///
/// Maps item to group
///
@@ -87,7 +87,7 @@ protected SortedPool(int capacity, IComparer comparer)
protected abstract TGroupKey MapToGroup(TValue value);
public int Count => _cacheMap.Count;
-
+
///
/// Gets all items in random order.
///
@@ -96,14 +96,14 @@ public TValue[] GetSnapshot()
{
return _buckets.SelectMany(b => b.Value).ToArray();
}
-
+
///
/// Gets all items in groups in supplied comparer order in groups.
///
[MethodImpl(MethodImplOptions.Synchronized)]
public IDictionary GetBucketSnapshot(Predicate? where = null)
{
- IEnumerable>> buckets = _buckets;
+ IEnumerable>> buckets = _buckets;
if (where is not null)
{
buckets = buckets.Where(kvp => where(kvp.Key));
@@ -118,9 +118,9 @@ public IDictionary GetBucketSnapshot(Predicate?
public TValue[] GetBucketSnapshot(TGroupKey group)
{
if (group == null) throw new ArgumentNullException(nameof(group));
- return _buckets.TryGetValue(group, out SortedSet bucket) ? bucket.ToArray() : Array.Empty();
+ return _buckets.TryGetValue(group, out EnhancedSortedSet bucket) ? bucket.ToArray() : Array.Empty();
}
-
+
///
/// Gets number of items in requested group.
///
@@ -128,7 +128,7 @@ public TValue[] GetBucketSnapshot(TGroupKey group)
public int GetBucketCount(TGroupKey group)
{
if (group == null) throw new ArgumentNullException(nameof(group));
- return _buckets.TryGetValue(group, out SortedSet bucket) ? bucket.Count : 0;
+ return _buckets.TryGetValue(group, out EnhancedSortedSet bucket) ? bucket.Count : 0;
}
///
@@ -139,22 +139,22 @@ public bool TryTakeFirst(out TValue first)
{
return TryRemove(GetKey(GetFirsts().Min), out first);
}
-
+
///
/// Returns best element of each bucket in supplied comparer order.
///
[MethodImpl(MethodImplOptions.Synchronized)]
- public SortedSet GetFirsts()
+ public EnhancedSortedSet GetFirsts()
{
- SortedSet sortedValues = new(_sortedComparer);
- foreach (KeyValuePair> bucket in _buckets)
+ EnhancedSortedSet sortedValues = new(_sortedComparer);
+ foreach (KeyValuePair> bucket in _buckets)
{
sortedValues.Add(bucket.Value.Min!);
}
return sortedValues;
}
-
+
///
/// Gets last element in supplied comparer order.
///
@@ -173,7 +173,7 @@ public bool TryGetLast(out TValue last)
/// Bucket for same sender transactions.
/// If element was removed. False if element was not present in pool.
[MethodImpl(MethodImplOptions.Synchronized)]
- public bool TryRemove(TKey key, out TValue value, [MaybeNullWhen(false)] out ICollection? bucket) =>
+ public bool TryRemove(TKey key, out TValue value, [MaybeNullWhen(false)] out ICollection? bucket) =>
TryRemove(key, false, out value, out bucket);
private bool TryRemove(TKey key, bool evicted, out TValue value, out ICollection? bucket)
@@ -183,7 +183,7 @@ private bool TryRemove(TKey key, bool evicted, out TValue value, out ICollection
if (Remove(key, value))
{
TGroupKey groupMapping = MapToGroup(value);
- if (_buckets.TryGetValue(groupMapping, out SortedSet bucketSet))
+ if (_buckets.TryGetValue(groupMapping, out EnhancedSortedSet bucketSet))
{
bucket = bucketSet;
TValue? last = bucketSet.Max;
@@ -198,11 +198,11 @@ private bool TryRemove(TKey key, bool evicted, out TValue value, out ICollection
{
UpdateSortedValues(bucketSet, last);
}
-
+
return true;
}
}
-
+
Removed?.Invoke(this, new SortedPoolRemovedEventArgs(key, value, groupMapping, evicted));
}
}
@@ -216,7 +216,7 @@ private bool TryRemove(TKey key, bool evicted, out TValue value, out ICollection
[MethodImpl(MethodImplOptions.Synchronized)]
public bool TryRemove(TKey key, [MaybeNullWhen(false)] out TValue value) => TryRemove(key, out value, out _);
-
+
[MethodImpl(MethodImplOptions.Synchronized)]
public bool TryRemove(TKey key) => TryRemove(key, out _, out _);
@@ -229,9 +229,9 @@ private bool TryRemove(TKey key, bool evicted, out TValue value, out ICollection
[MethodImpl(MethodImplOptions.Synchronized)]
public IEnumerable TakeWhile(TGroupKey groupKey, Predicate where)
{
- if (_buckets.TryGetValue(groupKey, out SortedSet? bucket))
+ if (_buckets.TryGetValue(groupKey, out EnhancedSortedSet? bucket))
{
- using SortedSet.Enumerator enumerator = bucket!.GetEnumerator();
+ using EnhancedSortedSet.Enumerator enumerator = bucket!.GetEnumerator();
List? list = null;
while (enumerator.MoveNext())
@@ -244,7 +244,7 @@ public IEnumerable TakeWhile(TGroupKey groupKey, Predicate where
list ??= new List();
list.Add(enumerator.Current);
}
-
+
return list ?? Enumerable.Empty();
}
return Enumerable.Empty();
@@ -298,7 +298,7 @@ public bool TryInsert(TKey key, TValue value, out TValue? removed)
[MethodImpl(MethodImplOptions.Synchronized)]
public bool TryInsert(TKey key, TValue value) => TryInsert(key, value, out _);
-
+
private void RemoveLast(out TValue? removed)
{
TryRemove(_worstSortedValues.Max.Value, true, out removed, out _);
@@ -316,15 +316,15 @@ protected virtual bool CanInsert(TKey key, TValue value)
return !_cacheMap.ContainsKey(key);
}
-
+
///
/// Actual insert mechanism.
///
protected virtual void InsertCore(TKey key, TValue value, TGroupKey groupKey)
{
- if (!_buckets.TryGetValue(groupKey, out SortedSet bucket))
+ if (!_buckets.TryGetValue(groupKey, out EnhancedSortedSet bucket))
{
- _buckets[groupKey] = bucket = new SortedSet(_groupComparer);
+ _buckets[groupKey] = bucket = new EnhancedSortedSet(_groupComparer);
}
TValue? last = bucket.Max;
@@ -336,7 +336,7 @@ protected virtual void InsertCore(TKey key, TValue value, TGroupKey groupKey)
}
}
- private void UpdateSortedValues(SortedSet