/// <summary> /// Given a trie node directly or by reference, obtains the direct node to operate on. /// </summary> /// <param name="nodeOrReference">The trie node or trie node reference used to obtain the actual trie node.</param> /// <returns>Returns the representing trie node for this value.</returns> private RLPList DecodeNode(RLPItem nodeOrReference) { // If it's an RLP list, it's a direct representation of the node. if (nodeOrReference.IsList) { return((RLPList)nodeOrReference); } else { // If it's a RLP byte array/32 byte hash, it's the key used to look up the node (a reference) byte[] nodeHash = nodeOrReference; // If this matches our blank node hash, return our blank node. if (IsBlankNodeHash(nodeHash)) { return(null); } // Otherwise we decode our node from RLP after fetching it from our database. if (!Database.TryGet(nodeHash, out var nodeData)) { throw new Exception($"Could not fetch node from database with node hash: {nodeHash.ToHexString(hexPrefix: true)}"); } return((RLPList)RLP.Decode(nodeData)); } }
/// <inheritdoc/> public Transaction CreateTransaction(byte[] rlpEncodedTrasaction) { Transaction transaction = new Transaction(); RLPCollection decodedList = (RLPCollection)RLP.Decode(rlpEncodedTrasaction)[0]; bool isSigned = (decodedList.Count == 4); int inputIdx = isSigned ? 1 : 0; int outputIdx = isSigned ? 2 : 1; int metadataIdx = isSigned ? 3 : 2; RLPCollection inputData = (RLPCollection)decodedList[inputIdx]; foreach (RLPCollection input in inputData) { if (input.Count == 3) { transaction.AddInput(Transaction.ToUInt64FromRLPDecoded(input[0].RLPData), Transaction.ToUInt16FromRLPDecoded(input[1].RLPData), Transaction.ToUInt16FromRLPDecoded(input[2].RLPData)); } } RLPCollection outputData = (RLPCollection)decodedList[outputIdx]; foreach (RLPCollection output in outputData) { if (output.Count == 3) { transaction.AddOutput(output[0].RLPData.ToHex().PadLeft(32, '0').EnsureHexPrefix(), output[1].RLPData.ToHex().PadLeft(32, '0').EnsureHexPrefix(), output[2].RLPData.ToBigIntegerFromRLPDecoded()); } } if (metadataIdx < decodedList.Count) { RLPItem metadata = (RLPItem)decodedList[metadataIdx]; transaction.SetMetadata(metadata.RLPData.ToHex().HexToByteArray()); } if (isSigned) { RLPCollection signatureData = (RLPCollection)decodedList[0]; for (Int32 i = 0; i < signatureData.Count; ++i) { transaction.SetSignature(i, signatureData[i].RLPData); } } return(transaction); }
/// <summary> /// Deserializes the given RLP serialized receipt and sets all values accordingly. /// </summary> /// <param name="item">The RLP item to deserialize and obtain values from.</param> public void Deserialize(RLPItem item) { // Verify this is a list if (!item.IsList) { throw new ArgumentException(); } // Verify it has 4 items. RLPList rlpReceipt = (RLPList)item; if (rlpReceipt.Items.Count != 4) { throw new ArgumentException(); } // Verify the types of all items if (!rlpReceipt.Items[0].IsByteArray || !rlpReceipt.Items[1].IsByteArray || !rlpReceipt.Items[2].IsByteArray || !rlpReceipt.Items[3].IsList) { throw new ArgumentException(); } // Set our state root RLPByteArray rlpStateRoot = (RLPByteArray)rlpReceipt.Items[0]; StateRoot = rlpStateRoot.Data.ToArray(); // Set our gas used RLPByteArray rlpGasUsed = (RLPByteArray)rlpReceipt.Items[1]; GasUsed = RLP.ToInteger(rlpGasUsed, EVMDefinitions.WORD_SIZE); // Set our bloom RLPByteArray rlpBloom = (RLPByteArray)rlpReceipt.Items[2]; Bloom = RLP.ToInteger(rlpBloom, EVMDefinitions.BLOOM_FILTER_SIZE); // Obtain our logs RLPList rlpLogs = (RLPList)rlpReceipt.Items[3]; Logs = new List <Log>(); foreach (RLPItem rlpLog in rlpLogs.Items) { // Add our log Logs.Add(new Log(rlpLog)); } }
/// <summary> /// Deserializes the given RLP serialized log and sets all values accordingly. /// </summary> /// <param name="item">The RLP item to deserialize and obtain values from.</param> public void Deserialize(RLPItem item) { // Verify this is a list if (!item.IsList) { throw new ArgumentException(); } // Verify it has 3 items. RLPList rlpLog = (RLPList)item; if (rlpLog.Items.Count != 3) { throw new ArgumentException(); } // Verify the types of all items if (!rlpLog.Items[0].IsByteArray || !rlpLog.Items[1].IsList || !rlpLog.Items[2].IsByteArray) { throw new ArgumentException(); } // Set our address RLPByteArray rlpAddress = (RLPByteArray)rlpLog.Items[0]; Address = new Address(rlpAddress.Data.Span); // Obtain our topics RLPList rlpTopicsList = (RLPList)rlpLog.Items[1]; Topics = new List <BigInteger>(); foreach (RLPItem rlpTopic in rlpTopicsList.Items) { // Verify all of our items are data if (rlpTopic.GetType() != typeof(RLPByteArray)) { throw new ArgumentException(); } // Add our topic. Topics.Add(RLP.ToInteger((RLPByteArray)rlpTopic, EVMDefinitions.WORD_SIZE)); } // Obtain our data RLPByteArray rlpData = (RLPByteArray)rlpLog.Items[2]; Data = rlpData.Data.ToArray(); }
/// <summary> /// Deserializes the given RLP serialized block and sets all values accordingly. /// </summary> /// <param name="item">The RLP item to deserialize and obtain values from.</param> public void Deserialize(RLPItem item) { // Verify this is a list if (!item.IsList) { throw new ArgumentException(); } // Verify it has 3 items. RLPList rlpBlock = (RLPList)item; if (rlpBlock.Items.Count != 3) { throw new ArgumentException(); } // Verify the types of all items (should all be lists) for (int i = 0; i < rlpBlock.Items.Count; i++) { if (!rlpBlock.Items[i].IsList) { throw new ArgumentException(); } } // Obtain the block header Header = new BlockHeader(rlpBlock.Items[0]); // Obtain the list of transactions RLPList rlpTransactions = (RLPList)rlpBlock.Items[1]; Transactions = new Transaction[rlpTransactions.Items.Count]; for (int i = 0; i < rlpTransactions.Items.Count; i++) { Transactions[i] = new Transaction(rlpTransactions.Items[i]); } // Obtain the list of uncles. RLPList rlpUncles = (RLPList)rlpBlock.Items[2]; Uncles = new BlockHeader[rlpUncles.Items.Count]; for (int i = 0; i < rlpUncles.Items.Count; i++) { Uncles[i] = new BlockHeader(rlpUncles.Items[i]); } }
private void RLPStringEncodeDecodeTest(string s) { RLPItem s1 = s; byte[] encoded = RLP.Encode(s); RLPItem s2 = RLP.Decode(encoded); string ss1 = s1; string ss2 = s2; if (s.Length == 0) { Assert.Null((string)s2); } else { Assert.Equal((string)s1, (string)s2); } }
public void RLPLogTest() { Meadow.EVM.Data_Types.Transactions.Log log = new Meadow.EVM.Data_Types.Transactions.Log((BigInteger)0x11223344, new List <BigInteger>() { 3, 2, 1 }, new byte[] { 00, 77, 00, 77 }); RLPItem item = log.Serialize(); byte[] data = RLP.Encode(item); item = RLP.Decode(data); log.Deserialize(item); item = log.Serialize(); byte[] data2 = RLP.Encode(item); Assert.True(data.ValuesEqual(data2)); Assert.Equal(0x11223344, (BigInteger)log.Address); Assert.True(log.Topics.Count == 3 && log.Topics[0] == 3 && log.Topics[1] == 2 && log.Topics[2] == 1); Assert.True(log.Data.ValuesEqual(new byte[] { 00, 77, 00, 77 })); }
/// <summary> /// Deserializes the given RLP serialized account and sets all values accordingly. /// </summary> /// <param name="item">The RLP item to deserialize and obtain values from.</param> public void Deserialize(RLPItem item) { // Verify this is a list if (!item.IsList) { throw new ArgumentException(); } // Verify it has 4 items. RLPList rlpAccount = (RLPList)item; if (rlpAccount.Items.Count != 4) { throw new ArgumentException(); } // Verify the types of all items if (!rlpAccount.Items[0].IsByteArray || !rlpAccount.Items[1].IsByteArray || !rlpAccount.Items[2].IsByteArray || !rlpAccount.Items[3].IsByteArray) { throw new ArgumentException(); } // Set our nonce, balance, storage, and code hash. Nonce = RLP.ToInteger((RLPByteArray)rlpAccount.Items[0]); Balance = RLP.ToInteger((RLPByteArray)rlpAccount.Items[1]); StorageRoot = rlpAccount.Items[2]; CodeHash = rlpAccount.Items[3]; // Verify the length of our storage root and code hash. if (StorageRoot.Length != KeccakHash.HASH_SIZE || CodeHash.Length != KeccakHash.HASH_SIZE) { throw new ArgumentException(); } // Initialize our storage change cache StorageCache = new Dictionary <Memory <byte>, byte[]>(new MemoryComparer <byte>()); // Load our trie given our storage root StorageTrie = new Trie(Configuration.Database, StorageRoot); }
public Block(RLPItem rlpBlockHeader) { Deserialize(rlpBlockHeader); }
/// <summary> /// Creates a receipt instance given an RLP serialized Receipt we can decode to obtain values for. /// </summary> /// <param name="rlpReceipt">The RLP serialized receipt to decode and set values from.</param> public Receipt(RLPItem rlpReceipt) { Deserialize(rlpReceipt); }
/// <summary> /// Deserializes the given RLP serialized block header and sets all values accordingly. /// </summary> /// <param name="item">The RLP item to block header and obtain values from.</param> public void Deserialize(RLPItem item) { // Verify this is a list if (!item.IsList) { throw new ArgumentException(); } // Verify it has 15 items. RLPList rlpBlockHeader = (RLPList)item; if (rlpBlockHeader.Items.Count != 15) { throw new ArgumentException(); } // Verify the types of all items for (int i = 0; i < rlpBlockHeader.Items.Count; i++) { if (!rlpBlockHeader.Items[i].IsByteArray) { throw new ArgumentException(); } } // Verify our items are the correct length if (((RLPByteArray)rlpBlockHeader.Items[0]).Data.Length != KeccakHash.HASH_SIZE) { throw new ArgumentException(); } if (((RLPByteArray)rlpBlockHeader.Items[1]).Data.Length != KeccakHash.HASH_SIZE) { throw new ArgumentException(); } if (((RLPByteArray)rlpBlockHeader.Items[2]).Data.Length != Address.ADDRESS_SIZE) { throw new ArgumentException(); } if (((RLPByteArray)rlpBlockHeader.Items[3]).Data.Length != KeccakHash.HASH_SIZE) { throw new ArgumentException(); } if (((RLPByteArray)rlpBlockHeader.Items[4]).Data.Length != KeccakHash.HASH_SIZE) { throw new ArgumentException(); } if (((RLPByteArray)rlpBlockHeader.Items[5]).Data.Length != KeccakHash.HASH_SIZE) { throw new ArgumentException(); } if (((RLPByteArray)rlpBlockHeader.Items[6]).Data.Length != EVMDefinitions.BLOOM_FILTER_SIZE) { throw new ArgumentException(); } // Obtain our items PreviousHash = rlpBlockHeader.Items[0]; UnclesHash = rlpBlockHeader.Items[1]; Coinbase = RLP.ToInteger((RLPByteArray)rlpBlockHeader.Items[2], Address.ADDRESS_SIZE); StateRootHash = rlpBlockHeader.Items[3]; TransactionsRootHash = rlpBlockHeader.Items[4]; ReceiptsRootHash = rlpBlockHeader.Items[5]; Bloom = RLP.ToInteger((RLPByteArray)rlpBlockHeader.Items[6], EVMDefinitions.BLOOM_FILTER_SIZE); Difficulty = RLP.ToInteger((RLPByteArray)rlpBlockHeader.Items[7]); BlockNumber = RLP.ToInteger((RLPByteArray)rlpBlockHeader.Items[8]); GasLimit = RLP.ToInteger((RLPByteArray)rlpBlockHeader.Items[9]); GasUsed = RLP.ToInteger((RLPByteArray)rlpBlockHeader.Items[10]); Timestamp = RLP.ToInteger((RLPByteArray)rlpBlockHeader.Items[11]); ExtraData = rlpBlockHeader.Items[12]; MixHash = rlpBlockHeader.Items[13]; Nonce = rlpBlockHeader.Items[14]; }
/// <summary> /// Creates a log instance given an RLP serialized Log we can decode to obtain values for. /// </summary> /// <param name="rlpList">The RLP serialized log to decode and set values from.</param> public Log(RLPItem rlpList) { Deserialize(rlpList); }