diff --git a/tools/Evm/Evm/t8n/JsonTypes/InputData.cs b/tools/Evm/Evm/t8n/JsonTypes/InputData.cs index 355daba38e5..f3945382455 100644 --- a/tools/Evm/Evm/t8n/JsonTypes/InputData.cs +++ b/tools/Evm/Evm/t8n/JsonTypes/InputData.cs @@ -3,7 +3,10 @@ using Ethereum.Test.Base; using Nethermind.Core; +using Nethermind.Core.Crypto; using Nethermind.Core.Extensions; +using Nethermind.Crypto; +using Nethermind.Facade.Eth.RpcTransaction; using Nethermind.Serialization.Rlp; namespace Evm.t8n.JsonTypes; @@ -12,22 +15,49 @@ public class InputData { public Dictionary? Alloc { get; set; } public EnvJson? Env { get; set; } - public TransactionJson[]? Txs { get; set; } + public TransactionForRpc[]? Txs { get; set; } + public TransactionMetaData[]? TransactionMetaDataList { get; set; } public string? TxRlp { get; set; } public Transaction[] GetTransactions(TxDecoder decoder) { - Transaction[] transactions = []; + List transactions = []; if (TxRlp is not null) { RlpStream rlp = new(Bytes.FromHexString(TxRlp)); - transactions = decoder.DecodeArray(rlp); + transactions = decoder.DecodeArray(rlp).ToList(); } - else if (Txs is not null) + else if (Txs is not null && TransactionMetaDataList is not null) { - transactions = Txs.Select(txInfo => txInfo.ConvertToTx()).ToArray(); + for (int i = 0; i < Txs.Length; i++) + { + var tx = Txs[i].ToTransaction(); + tx.SenderAddress = null; // t8n does not accept SenderAddress from input, so need to reset senderAddress + + var txLegacy = (LegacyTransactionForRpc) Txs[i]; + + var secretKey = TransactionMetaDataList[i].SecretKey; + + if (secretKey is not null) + { + var privateKey = new PrivateKey(secretKey); + tx.SenderAddress = privateKey.Address; + + EthereumEcdsa ecdsa = new(tx.ChainId ?? TestBlockchainIds.ChainId); + + ecdsa.Sign(privateKey, tx, TransactionMetaDataList[i].Protected ?? true); + } + else if (txLegacy.R.HasValue && txLegacy.S.HasValue && txLegacy.V.HasValue) + { + tx.Signature = new Signature(txLegacy.R.Value, txLegacy.S.Value, txLegacy.V.Value.ToUInt64(null)); + } + + tx.Hash = tx.CalculateHash(); + + transactions.Add(tx); + } } - return transactions; + return transactions.ToArray(); } } diff --git a/tools/Evm/Evm/t8n/JsonTypes/TransactionJson.cs b/tools/Evm/Evm/t8n/JsonTypes/TransactionJson.cs deleted file mode 100644 index 0602df0f529..00000000000 --- a/tools/Evm/Evm/t8n/JsonTypes/TransactionJson.cs +++ /dev/null @@ -1,81 +0,0 @@ -// SPDX-FileCopyrightText: 2024 Demerzel Solutions Limited -// SPDX-License-Identifier: LGPL-3.0-only - -using Ethereum.Test.Base; -using Nethermind.Core; -using Nethermind.Core.Crypto; -using Nethermind.Core.Eip2930; -using Nethermind.Core.Test.Builders; -using Nethermind.Crypto; -using Nethermind.Int256; - -namespace Evm.t8n.JsonTypes; - -public class TransactionJson -{ - public byte[]? Input { get; set; } - public long Gas { get; set; } - public string? Hash { get; set; } - public UInt256 Nonce { get; set; } - public Address? To { get; set; } - public UInt256 Value { get; set; } - public ulong V { get; set; } - public byte[]? R { get; set; } - public byte[]? S { get; set; } - public byte[]? SecretKey { get; set; } - public ulong? ChainId { get; set; } - public TxType Type { get; set; } = TxType.Legacy; - public UInt256? MaxFeePerGas { get; set; } - public UInt256 GasPrice { get; set; } - public UInt256? MaxPriorityFeePerGas { get; set; } - public AccessListItemJson[]? AccessList { get; set; } - public bool? Protected { get; set; } - - public Transaction ConvertToTx() - { - TransactionBuilder transactionBuilder = new(); - - transactionBuilder.WithValue(Value); - if (Input is not null) - { - transactionBuilder.WithData(Input); - } - transactionBuilder.WithTo(To); - transactionBuilder.WithNonce(Nonce); - transactionBuilder.WithGasLimit(Gas); - transactionBuilder.WithType(Type); - transactionBuilder.WithGasPrice(GasPrice); - if (AccessList is not null) - { - AccessList.Builder builder = new(); - JsonToEthereumTest.ProcessAccessList(AccessList, builder); - transactionBuilder.WithAccessList(builder.Build()); - } - - if (MaxFeePerGas.HasValue) - { - transactionBuilder.WithMaxFeePerGas(MaxFeePerGas.Value); - } - if (MaxPriorityFeePerGas.HasValue) - { - transactionBuilder.WithMaxPriorityFeePerGas(MaxPriorityFeePerGas.Value); - } - - if (ChainId.HasValue) - { - transactionBuilder.WithChainId(ChainId.Value); - } - if (SecretKey is not null) - { - var privateKey = new PrivateKey(SecretKey); - transactionBuilder.WithSenderAddress(privateKey.Address); - transactionBuilder.Signed(privateKey, Protected ?? true); - } - else - { - transactionBuilder.WithSignature(new Signature(R, S, V)); - } - - return transactionBuilder.TestObject; - } -} diff --git a/tools/Evm/Evm/t8n/JsonTypes/TransactionMetaData.cs b/tools/Evm/Evm/t8n/JsonTypes/TransactionMetaData.cs new file mode 100644 index 00000000000..d4b66eae1fe --- /dev/null +++ b/tools/Evm/Evm/t8n/JsonTypes/TransactionMetaData.cs @@ -0,0 +1,10 @@ +// SPDX-FileCopyrightText: 2024 Demerzel Solutions Limited +// SPDX-License-Identifier: LGPL-3.0-only + +namespace Evm.t8n.JsonTypes; + +public class TransactionMetaData +{ + public bool? Protected { get; set; } + public byte[]? SecretKey { get; set; } +} diff --git a/tools/Evm/Evm/t8n/T8NInputReader.cs b/tools/Evm/Evm/t8n/T8NInputReader.cs index dcae50a3397..4cf86c29d2e 100644 --- a/tools/Evm/Evm/t8n/T8NInputReader.cs +++ b/tools/Evm/Evm/t8n/T8NInputReader.cs @@ -6,8 +6,8 @@ using Evm.t8n.Errors; using Evm.t8n.JsonTypes; using Nethermind.Core; +using Nethermind.Facade.Eth.RpcTransaction; using Nethermind.Serialization.Json; -using TransactionJson = Evm.t8n.JsonTypes.TransactionJson; namespace Evm.t8n; @@ -40,7 +40,8 @@ public static InputData ReadInputData(T8NCommandArguments arguments) switch (Path.GetExtension(arguments.InputTxs)) { case ".json": - inputData.Txs = LoadDataFromFile(arguments.InputTxs, "txs"); + inputData.Txs = LoadDataFromFile(arguments.InputTxs, "txs"); + inputData.TransactionMetaDataList = LoadDataFromFile(arguments.InputTxs, "txs"); break; case ".rlp": inputData.TxRlp = File.ReadAllText(arguments.InputTxs).Replace("\"", "").Replace("\n", "");