Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion scripts/known-failing-hive-tests.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -123,27 +123,39 @@ internal static void RegisterTransactionType<T>() 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<JsonObject>(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)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
private Type DeriveTxType(JsonObject untyped, JsonSerializerOptions options)
private Type DeriveTxType(JsonObject untyped)

{
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<TxType?>(options);
TxType? setType = node.Deserialize<TxType?>(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);
}
Comment on lines +152 to +155
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If Legacy is first item in _txTypes we can probably drop this if?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it's last. So we should return Legacy if gasPrice is set. Even if we have blobHashes

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok we have:

// Adding in reverse order so newer tx types are in priority

Interesting, maybe we should do that ignoring index?

So:

int indexOfPreviousTxType = _txTypes.FindIndex(t => t.TxType != TxType.Legacy && t.TxType < typeInfo.TxType); ?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't understand what's typeInfo.TxType. I think now it's very straight-forward


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)
Expand Down
8 changes: 4 additions & 4 deletions src/Nethermind/Nethermind.JsonRpc.Test/Data/Eip2930Tests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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<TransactionForRpc>(json);

Expand Down Expand Up @@ -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<TransactionForRpc>(json);

transactionForRpc.Type.Should().Be(TxType.AccessList);
Expand Down Expand Up @@ -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<TransactionForRpc>(json);

transactionForRpc.Type.Should().Be(TxType.AccessList);
Expand All @@ -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<TransactionForRpc>(json);

transactionForRpc.Type.Should().Be(TxType.AccessList);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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":[]}""");
Expand All @@ -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"]}""");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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<TransactionForRpc> payload = EthSimulateTestsBlocksAndTransactions.CreateEthMovedPayload(chain, nonceA);

Expand Down Expand Up @@ -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<TransactionForRpc> payload = EthSimulateTestsBlocksAndTransactions.CreateTransactionsForcedFail(chain, nonceA);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -141,10 +141,11 @@ public static SimulatePayload<TransactionForRpc> 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,
Expand Down Expand Up @@ -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<TransactionForRpc> payload = CreateEthMovedPayload(chain, nonceA);

Expand Down Expand Up @@ -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<TransactionForRpc> payload = CreateTransactionsForcedFail(chain, nonceA);

Expand Down Expand Up @@ -276,6 +277,7 @@ public static SimulatePayload<TransactionForRpc> CreateTransferLogsAddressPayloa
},
"calls": [
{
"type": "0x3",
"from": "0xc000000000000000000000000000000000000000",
"to": "0xc100000000000000000000000000000000000000",
"gas": "0x5208",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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<TransactionForRpc> payload = EthSimulateTestsBlocksAndTransactions.CreateEthMovedPayload(chain, nonceA);

Expand Down Expand Up @@ -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<TransactionForRpc> payload = EthSimulateTestsBlocksAndTransactions.CreateTransactionsForcedFail(chain, nonceA);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,6 @@ protected override SimulatePayload<TransactionWithSourceDetails> 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;
Expand Down Expand Up @@ -76,30 +75,6 @@ protected override SimulatePayload<TransactionWithSourceDetails> 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<IReadOnlyList<SimulateBlockResult<TTrace>>> Execute(
SimulatePayload<TransactionForRpc> call,
BlockParameter? blockParameter,
Expand Down
Loading