diff --git a/scripts/known-failing-hive-tests.txt b/scripts/known-failing-hive-tests.txt index e56c4cdfe1da..d7e55daf2b24 100644 --- a/scripts/known-failing-hive-tests.txt +++ b/scripts/known-failing-hive-tests.txt @@ -2,11 +2,11 @@ eth_getStorageAt/get-storage-invalid-key (nethermind) eth_getStorageAt/get-storage-invalid-key-too-large (nethermind) +eth_createAccessList/create-al-abi-revert (nethermind) eth_sendRawTransaction/send-blob-tx (nethermind) eth_simulateV1/ethSimulate-instrict-gas-38013 (nethermind) eth_simulateV1/ethSimulate-run-gas-spending (nethermind) eth_simulateV1/ethSimulate-run-out-of-gas-in-block-38015 (nethermind) -eth_simulateV1/ethSimulate-simple-more-params-validate (nethermind) eth_simulateV1/ethSimulate-two-blocks-with-complete-eth-sends (nethermind) eth_simulateV1/ethSimulate-use-as-many-features-as-possible (nethermind) diff --git a/src/Nethermind/Nethermind.Facade/Eth/RpcTransaction/BlobTransactionForRpc.cs b/src/Nethermind/Nethermind.Facade/Eth/RpcTransaction/BlobTransactionForRpc.cs index f683fcbdadb0..511c638c626c 100644 --- a/src/Nethermind/Nethermind.Facade/Eth/RpcTransaction/BlobTransactionForRpc.cs +++ b/src/Nethermind/Nethermind.Facade/Eth/RpcTransaction/BlobTransactionForRpc.cs @@ -15,7 +15,6 @@ public class BlobTransactionForRpc : EIP1559TransactionForRpc, IFromTransaction< public override TxType? Type => TxType; [JsonIgnore(Condition = JsonIgnoreCondition.Never)] - [JsonDiscriminator] public UInt256? MaxFeePerBlobGas { get; set; } // TODO: Each item should be a 32 byte array diff --git a/src/Nethermind/Nethermind.Facade/Eth/RpcTransaction/TransactionForRpc.cs b/src/Nethermind/Nethermind.Facade/Eth/RpcTransaction/TransactionForRpc.cs index 327514e932aa..b00781325b4f 100644 --- a/src/Nethermind/Nethermind.Facade/Eth/RpcTransaction/TransactionForRpc.cs +++ b/src/Nethermind/Nethermind.Facade/Eth/RpcTransaction/TransactionForRpc.cs @@ -123,27 +123,39 @@ internal static void RegisterTransactionType() where T : TransactionForRpc, I public override TransactionForRpc? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { - const string TypeFieldKey = nameof(TransactionForRpc.Type); // Copy the reader so we can do a double parse: // The first parse is used to check for fields, while the second parses the entire Transaction Utf8JsonReader txTypeReader = reader; JsonObject untyped = JsonSerializer.Deserialize(ref txTypeReader, options); - TxType? txType = null; - if (untyped.TryGetPropertyValue(TypeFieldKey, out JsonNode? node)) + Type concreteTxType = DeriveTxType(untyped, options); + + return (TransactionForRpc?)JsonSerializer.Deserialize(ref reader, concreteTxType, options); + } + + private Type DeriveTxType(JsonObject untyped, JsonSerializerOptions options) + { + Type defaultTxType = typeof(EIP1559TransactionForRpc); + const string gasPriceFieldKey = nameof(LegacyTransactionForRpc.GasPrice); + const string typeFieldKey = nameof(TransactionForRpc.Type); + + if (untyped.TryGetPropertyValue(typeFieldKey, out JsonNode? node)) { - txType = node.Deserialize(options); + TxType? setType = node.Deserialize(options); + if (setType is not null) + { + return _txTypes.FirstOrDefault(p => p.TxType == setType)?.Type ?? + throw new JsonException("Unknown transaction type"); + } } - Type concreteTxType = - ( - txType is not null - ? _txTypes.FirstOrDefault(p => p.TxType == txType) - : _txTypes.FirstOrDefault(p => p.DiscriminatorProperties.Any(name => untyped.ContainsKey(name)), _txTypes[^1]) - )?.Type - ?? throw new JsonException("Unknown transaction type"); + if (untyped.ContainsKey(gasPriceFieldKey)) + { + return typeof(LegacyTransactionForRpc); + } - return (TransactionForRpc?)JsonSerializer.Deserialize(ref reader, concreteTxType, options); + return _txTypes + .FirstOrDefault(p => p.DiscriminatorProperties.Any(untyped.ContainsKey))?.Type ?? defaultTxType; } public override void Write(Utf8JsonWriter writer, TransactionForRpc value, JsonSerializerOptions options) diff --git a/src/Nethermind/Nethermind.JsonRpc.Test/Data/Eip2930Tests.cs b/src/Nethermind/Nethermind.JsonRpc.Test/Data/Eip2930Tests.cs index dc248851c81e..8559d1621e3e 100644 --- a/src/Nethermind/Nethermind.JsonRpc.Test/Data/Eip2930Tests.cs +++ b/src/Nethermind/Nethermind.JsonRpc.Test/Data/Eip2930Tests.cs @@ -98,7 +98,7 @@ public void can_serialize_null_accessList_to_empty_array(TxType txType) [Test] public void can_deserialize_null_accessList() { - string json = """{"nonce":"0x0","blockHash":null,"blockNumber":null,"transactionIndex":null,"to":null,"value":"0x0","gasPrice":"0x0","gas":"0x0","input":null,"accessList":null}"""; + string json = """{"nonce":"0x0","blockHash":null,"blockNumber":null,"transactionIndex":null,"to":null,"value":"0x0","gas":"0x0","input":null,"accessList":null}"""; var transactionForRpc = _serializer.Deserialize(json); @@ -138,7 +138,7 @@ public void can_serialize_empty_accessList(TxType txType, string txJson) [Test] public void can_deserialize_empty_accessList() { - string json = """{"nonce":"0x0","blockHash":null,"blockNumber":null,"transactionIndex":null,"to":null,"value":"0x0","gasPrice":"0x0","gas":"0x0","input":null,"accessList":[]}"""; + string json = """{"nonce":"0x0","blockHash":null,"blockNumber":null,"transactionIndex":null,"to":null,"value":"0x0","gas":"0x0","input":null,"accessList":[]}"""; TransactionForRpc transactionForRpc = _serializer.Deserialize(json); transactionForRpc.Type.Should().Be(TxType.AccessList); @@ -172,7 +172,7 @@ public void can_serialize_accessList_with_empty_storageKeys(TxType txType, strin [Test] public void can_deserialize_accessList_with_empty_storageKeys() { - string json = """{"nonce":"0x0","blockHash":null,"blockNumber":null,"transactionIndex":null,"to":null,"value":"0x0","gasPrice":"0x0","gas":"0x0","input":null,"accessList":[{"address":"0xb7705ae4c6f81b66cdb323c65f4e8133690fc099","storageKeys":[]}]}"""; + string json = """{"nonce":"0x0","blockHash":null,"blockNumber":null,"transactionIndex":null,"to":null,"value":"0x0","gas":"0x0","input":null,"accessList":[{"address":"0xb7705ae4c6f81b66cdb323c65f4e8133690fc099","storageKeys":[]}]}"""; TransactionForRpc transactionForRpc = _serializer.Deserialize(json); transactionForRpc.Type.Should().Be(TxType.AccessList); @@ -185,7 +185,7 @@ public void can_deserialize_accessList_with_empty_storageKeys() [Test] public void can_deserialize_accessList_with_null_storageKeys() { - string json = """{"nonce":"0x0","blockHash":null,"blockNumber":null,"transactionIndex":null,"to":null,"value":"0x0","gasPrice":"0x0","gas":"0x0","input":null,"accessList":[{"address":"0xb7705ae4c6f81b66cdb323c65f4e8133690fc099"}]}"""; + string json = """{"nonce":"0x0","blockHash":null,"blockNumber":null,"transactionIndex":null,"to":null,"value":"0x0","gas":"0x0","input":null,"accessList":[{"address":"0xb7705ae4c6f81b66cdb323c65f4e8133690fc099"}]}"""; TransactionForRpc transactionForRpc = _serializer.Deserialize(json); transactionForRpc.Type.Should().Be(TxType.AccessList); diff --git a/src/Nethermind/Nethermind.JsonRpc.Test/Data/TransactionForRpcDeserializationTests.cs b/src/Nethermind/Nethermind.JsonRpc.Test/Data/TransactionForRpcDeserializationTests.cs index 1b49f26d5e44..6da4e0606c27 100644 --- a/src/Nethermind/Nethermind.JsonRpc.Test/Data/TransactionForRpcDeserializationTests.cs +++ b/src/Nethermind/Nethermind.JsonRpc.Test/Data/TransactionForRpcDeserializationTests.cs @@ -36,10 +36,13 @@ public static IEnumerable TxJsonTestCases yield return Make(TxType.Legacy, """{"nonce":"0x0","to":null,"value":"0x0","gasPrice":"0x0","gas":"0x0","input":null}"""); yield return Make(TxType.Legacy, """{"nonce":"0x0","to":null,"gasPrice":"0x0","gas":"0x0","input":null}"""); yield return Make(TxType.Legacy, """{"nonce":"0x0","to":null,"gasPrice":"0x0","gas":"0x0","input":null}"""); - yield return Make(TxType.Legacy, """{"nonce":"0x0","input":null}"""); - yield return Make(TxType.Legacy, """{}"""); - yield return Make(TxType.Legacy, """{"type":null}"""); - yield return Make(TxType.Legacy, """{"additionalField":""}"""); + yield return Make(TxType.EIP1559, """{"nonce":"0x0","input":null}"""); + yield return Make(TxType.EIP1559, """{}"""); + yield return Make(TxType.EIP1559, """{"type":null}"""); + yield return Make(TxType.EIP1559, """{"additionalField":""}"""); + yield return Make(TxType.EIP1559, """{"MaxFeePerBlobGas":"0x0"}"""); + yield return Make(TxType.Legacy, + """{"nonce":"0x0","blockHash":null,"blockNumber":null,"transactionIndex":null,"to":null,"value":"0x0","gasPrice":"0x1","gas":"0x0","input":null,"maxPriorityFeePerGas":"0x1"}"""); yield return Make(TxType.AccessList, """{"type":null,"accessList":[]}"""); yield return Make(TxType.AccessList, """{"nonce":"0x0","to":null,"value":"0x0","accessList":[]}"""); @@ -55,11 +58,10 @@ public static IEnumerable TxJsonTestCases yield return Make(TxType.EIP1559, """{"maxFeePerGas":"0x0"}"""); yield return Make(TxType.EIP1559, """{"maxPriorityFeePerGas":"0x0"}"""); yield return Make(TxType.EIP1559, """{"MaxPriorityFeePerGas":"0x0"}"""); + yield return Make(TxType.EIP1559, """{"nonce":"0x0","to":null,"value":"0x0","maxPriorityFeePerGas":"0x0", "maxFeePerGas":"0x0","maxFeePerBlobGas":"0x0"}"""); - yield return Make(TxType.Blob, """{"nonce":"0x0","to":null,"value":"0x0","accessList":[],"maxFeePerBlobGas":"0x0"}"""); - yield return Make(TxType.Blob, """{"nonce":"0x0","to":null,"value":"0x0","maxPriorityFeePerGas":"0x0", "maxFeePerGas":"0x0","maxFeePerBlobGas":"0x0"}"""); + yield return Make(TxType.Blob, """{"nonce":"0x0","to":null,"value":"0x0","accessList":[],"blobVersionedHashes":[]}"""); yield return Make(TxType.Blob, """{"maxFeePerBlobGas":"0x0", "blobVersionedHashes":[]}"""); - yield return Make(TxType.Blob, """{"MaxFeePerBlobGas":"0x0"}"""); yield return Make(TxType.Blob, """{"blobVersionedHashes":[]}"""); yield return Make(TxType.Blob, """{"BlobVersionedHashes":null}"""); yield return Make(TxType.Blob, """{"blobVersionedHashes":["0x01f1872d656b7a820d763e6001728b9b883f829b922089ec6ad7f5f1665470dc"]}"""); diff --git a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/DebugSimulateTestsBlocksAndTransactions.cs b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/DebugSimulateTestsBlocksAndTransactions.cs index c3e6c11fdcf6..20fb25101bdd 100644 --- a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/DebugSimulateTestsBlocksAndTransactions.cs +++ b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/DebugSimulateTestsBlocksAndTransactions.cs @@ -55,7 +55,7 @@ public async Task Test_debug_simulate_eth_moved() TestRpcBlockchain chain = await EthRpcSimulateTestsBase.CreateChain(); UInt256 nonceA = chain.ReadOnlyState.GetNonce(TestItem.AddressA); - Transaction txMainnetAtoB = EthSimulateTestsBlocksAndTransactions.GetTransferTxData(nonceA, chain.EthereumEcdsa, TestItem.PrivateKeyA, TestItem.AddressB, 1); + Transaction txMainnetAtoB = EthSimulateTestsBlocksAndTransactions.GetTransferTxData(nonceA, chain.EthereumEcdsa, TestItem.PrivateKeyA, TestItem.AddressB, 1, type: TxType.Legacy); SimulatePayload payload = EthSimulateTestsBlocksAndTransactions.CreateEthMovedPayload(chain, nonceA); @@ -93,7 +93,7 @@ public async Task Test_debug_simulate_transactions_forced_fail() UInt256 nonceA = chain.ReadOnlyState.GetNonce(TestItem.AddressA); Transaction txMainnetAtoB = - EthSimulateTestsBlocksAndTransactions.GetTransferTxData(nonceA, chain.EthereumEcdsa, TestItem.PrivateKeyA, TestItem.AddressB, 1); + EthSimulateTestsBlocksAndTransactions.GetTransferTxData(nonceA, chain.EthereumEcdsa, TestItem.PrivateKeyA, TestItem.AddressB, 1, type: TxType.Legacy); SimulatePayload payload = EthSimulateTestsBlocksAndTransactions.CreateTransactionsForcedFail(chain, nonceA); diff --git a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/Simulate/EthSimulateTestsBlocksAndTransactions.cs b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/Simulate/EthSimulateTestsBlocksAndTransactions.cs index 2d245618bd39..4cae9fee60b9 100644 --- a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/Simulate/EthSimulateTestsBlocksAndTransactions.cs +++ b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Eth/Simulate/EthSimulateTestsBlocksAndTransactions.cs @@ -141,10 +141,11 @@ public static SimulatePayload CreateTransactionsForcedFail(Te }; } - public static Transaction GetTransferTxData(UInt256 nonce, IEthereumEcdsa ethereumEcdsa, PrivateKey from, Address to, UInt256 amount) + public static Transaction GetTransferTxData(UInt256 nonce, IEthereumEcdsa ethereumEcdsa, PrivateKey from, Address to, UInt256 amount, TxType type = TxType.EIP1559) { Transaction tx = new() { + Type = type, Value = amount, Nonce = nonce, GasLimit = 50_000, @@ -192,7 +193,7 @@ public async Task Test_eth_simulate_eth_moved() TestRpcBlockchain chain = await EthRpcSimulateTestsBase.CreateChain(); UInt256 nonceA = chain.ReadOnlyState.GetNonce(TestItem.AddressA); - Transaction txMainnetAtoB = GetTransferTxData(nonceA, chain.EthereumEcdsa, TestItem.PrivateKeyA, TestItem.AddressB, 1); + Transaction txMainnetAtoB = GetTransferTxData(nonceA, chain.EthereumEcdsa, TestItem.PrivateKeyA, TestItem.AddressB, 1, type: TxType.Legacy); SimulatePayload payload = CreateEthMovedPayload(chain, nonceA); @@ -233,7 +234,7 @@ public async Task Test_eth_simulate_transactions_forced_fail() UInt256 nonceA = chain.ReadOnlyState.GetNonce(TestItem.AddressA); Transaction txMainnetAtoB = - GetTransferTxData(nonceA, chain.EthereumEcdsa, TestItem.PrivateKeyA, TestItem.AddressB, 1); + GetTransferTxData(nonceA, chain.EthereumEcdsa, TestItem.PrivateKeyA, TestItem.AddressB, 1, type: TxType.Legacy); SimulatePayload payload = CreateTransactionsForcedFail(chain, nonceA); @@ -276,6 +277,7 @@ public static SimulatePayload CreateTransferLogsAddressPayloa }, "calls": [ { + "type": "0x3", "from": "0xc000000000000000000000000000000000000000", "to": "0xc100000000000000000000000000000000000000", "gas": "0x5208", diff --git a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Trace/ParitySimulateTestsBlocksAndTransactions.cs b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Trace/ParitySimulateTestsBlocksAndTransactions.cs index 5bee79033711..fb5fd892d3f0 100644 --- a/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Trace/ParitySimulateTestsBlocksAndTransactions.cs +++ b/src/Nethermind/Nethermind.JsonRpc.Test/Modules/Trace/ParitySimulateTestsBlocksAndTransactions.cs @@ -51,7 +51,7 @@ public async Task Test_trace_simulate_eth_moved() TestRpcBlockchain chain = await EthRpcSimulateTestsBase.CreateChain(); UInt256 nonceA = chain.ReadOnlyState.GetNonce(TestItem.AddressA); - Transaction txMainnetAtoB = EthSimulateTestsBlocksAndTransactions.GetTransferTxData(nonceA, chain.EthereumEcdsa, TestItem.PrivateKeyA, TestItem.AddressB, 1); + Transaction txMainnetAtoB = EthSimulateTestsBlocksAndTransactions.GetTransferTxData(nonceA, chain.EthereumEcdsa, TestItem.PrivateKeyA, TestItem.AddressB, 1, type: TxType.Legacy); SimulatePayload payload = EthSimulateTestsBlocksAndTransactions.CreateEthMovedPayload(chain, nonceA); @@ -89,7 +89,7 @@ public async Task Test_trace_simulate_transactions_forced_fail() UInt256 nonceA = chain.ReadOnlyState.GetNonce(TestItem.AddressA); Transaction txMainnetAtoB = - EthSimulateTestsBlocksAndTransactions.GetTransferTxData(nonceA, chain.EthereumEcdsa, TestItem.PrivateKeyA, TestItem.AddressB, 1); + EthSimulateTestsBlocksAndTransactions.GetTransferTxData(nonceA, chain.EthereumEcdsa, TestItem.PrivateKeyA, TestItem.AddressB, 1, type: TxType.Legacy); SimulatePayload payload = EthSimulateTestsBlocksAndTransactions.CreateTransactionsForcedFail(chain, nonceA); diff --git a/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/SimulateTxExecutor.cs b/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/SimulateTxExecutor.cs index b6ecef04b02b..276a983e0fde 100644 --- a/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/SimulateTxExecutor.cs +++ b/src/Nethermind/Nethermind.JsonRpc/Modules/Eth/SimulateTxExecutor.cs @@ -46,7 +46,6 @@ protected override SimulatePayload Prepare(Simulat StateOverrides = blockStateCall.StateOverrides, Calls = blockStateCall.Calls?.Select(callTransactionModel => { - callTransactionModel = UpdateTxType(callTransactionModel); LegacyTransactionForRpc asLegacy = callTransactionModel as LegacyTransactionForRpc; bool hadGasLimitInRequest = asLegacy?.Gas is not null; bool hadNonceInRequest = asLegacy?.Nonce is not null; @@ -76,30 +75,6 @@ protected override SimulatePayload Prepare(Simulat return result; } - private static TransactionForRpc UpdateTxType(TransactionForRpc rpcTransaction) - { - // TODO: This is a bit messy since we're changing the transaction type - if (rpcTransaction is LegacyTransactionForRpc legacy && rpcTransaction is not EIP1559TransactionForRpc) - { - rpcTransaction = new EIP1559TransactionForRpc - { - Nonce = legacy.Nonce, - To = legacy.To, - From = legacy.From, - Gas = legacy.Gas, - Value = legacy.Value, - Input = legacy.Input, - GasPrice = legacy.GasPrice, - ChainId = legacy.ChainId, - V = legacy.V, - R = legacy.R, - S = legacy.S, - }; - } - - return rpcTransaction; - } - public override ResultWrapper>> Execute( SimulatePayload call, BlockParameter? blockParameter,