public Transaction Decode(RlpStream rlpStream, RlpBehaviors rlpBehaviors = RlpBehaviors.None) { if (rlpStream.IsNextItemNull()) { rlpStream.ReadByte(); return(null); } var transactionSequence = rlpStream.PeekNextItem(); int transactionLength = rlpStream.ReadSequenceLength(); int lastCheck = rlpStream.Position + transactionLength; Transaction transaction = new Transaction(); transaction.Nonce = rlpStream.DecodeUInt256(); transaction.GasPrice = rlpStream.DecodeUInt256(); transaction.GasLimit = rlpStream.DecodeLong(); transaction.To = rlpStream.DecodeAddress(); transaction.Value = rlpStream.DecodeUInt256(); if (transaction.To == null) { transaction.Init = rlpStream.DecodeByteArray(); } else { transaction.Data = rlpStream.DecodeByteArray(); } if (rlpStream.Position < lastCheck) { ReadOnlySpan <byte> vBytes = rlpStream.DecodeByteArraySpan(); ReadOnlySpan <byte> rBytes = rlpStream.DecodeByteArraySpan(); ReadOnlySpan <byte> sBytes = rlpStream.DecodeByteArraySpan(); bool allowUnsigned = (rlpBehaviors & RlpBehaviors.AllowUnsigned) == RlpBehaviors.AllowUnsigned; bool isSignatureOk = true; string signatureError = null; if (vBytes == null || rBytes == null || sBytes == null) { isSignatureOk = false; signatureError = "VRS null when decoding Transaction"; } else if (vBytes.Length == 0 || rBytes.Length == 0 || sBytes.Length == 0) { isSignatureOk = false; signatureError = "VRS is 0 length when decoding Transaction"; } else if (vBytes[0] == 0 || rBytes[0] == 0 || sBytes[0] == 0) { isSignatureOk = false; signatureError = "VRS starting with 0"; } else if (rBytes.Length > 32 || sBytes.Length > 32) { isSignatureOk = false; signatureError = "R and S lengths expected to be less or equal 32"; } else if (rBytes.SequenceEqual(Bytes.Zero32) && sBytes.SequenceEqual(Bytes.Zero32)) { isSignatureOk = false; signatureError = "Both 'r' and 's' are zero when decoding a transaction."; } if (isSignatureOk) { int v = vBytes.ReadEthInt32(); Signature signature = new Signature(rBytes, sBytes, v); transaction.Signature = signature; transaction.Hash = Keccak.Compute(transactionSequence); } else { if (!allowUnsigned) { throw new RlpException(signatureError); } } } if ((rlpBehaviors & RlpBehaviors.AllowExtraData) != RlpBehaviors.AllowExtraData) { rlpStream.Check(lastCheck); } return(transaction); }
SystemTransaction IRlpDecoder <SystemTransaction> .Decode(RlpStream rlpStream, RlpBehaviors rlpBehaviors) { throw new NotSupportedException(); }
public BlockHeader Decode(RlpStream rlpStream, RlpBehaviors rlpBehaviors = RlpBehaviors.None) { if (rlpStream.IsNextItemNull()) { rlpStream.ReadByte(); return(null); } var headerRlp = rlpStream.PeekNextItem(); int headerSequenceLength = rlpStream.ReadSequenceLength(); int headerCheck = rlpStream.Position + headerSequenceLength; Keccak parentHash = rlpStream.DecodeKeccak(); Keccak ommersHash = rlpStream.DecodeKeccak(); Address beneficiary = rlpStream.DecodeAddress(); Keccak stateRoot = rlpStream.DecodeKeccak(); Keccak transactionsRoot = rlpStream.DecodeKeccak(); Keccak receiptsRoot = rlpStream.DecodeKeccak(); Bloom bloom = rlpStream.DecodeBloom(); UInt256 difficulty = rlpStream.DecodeUInt256(); UInt256 number = rlpStream.DecodeUInt256(); UInt256 gasLimit = rlpStream.DecodeUInt256(); UInt256 gasUsed = rlpStream.DecodeUInt256(); UInt256 timestamp = rlpStream.DecodeUInt256(); byte[] extraData = rlpStream.DecodeByteArray(); BlockHeader blockHeader = new BlockHeader( parentHash, ommersHash, beneficiary, difficulty, (long)number, (long)gasLimit, timestamp, extraData) { StateRoot = stateRoot, TxRoot = transactionsRoot, ReceiptsRoot = receiptsRoot, Bloom = bloom, GasUsed = (long)gasUsed, Hash = Keccak.Compute(headerRlp) }; if (rlpStream.PeekPrefixAndContentLength().ContentLength == Keccak.Size) { blockHeader.MixHash = rlpStream.DecodeKeccak(); blockHeader.Nonce = (ulong)rlpStream.DecodeUBigInt(); } else { blockHeader.AuRaStep = (long)rlpStream.DecodeUInt256(); blockHeader.AuRaSignature = rlpStream.DecodeByteArray(); } if ((rlpBehaviors & RlpBehaviors.AllowExtraData) != RlpBehaviors.AllowExtraData) { rlpStream.Check(headerCheck); } return(blockHeader); }
public void Encode(RlpStream stream, BlockInfo item, RlpBehaviors rlpBehaviors = RlpBehaviors.None) { throw new NotImplementedException(); }
public TxReceipt Decode(RlpStream rlpStream, RlpBehaviors rlpBehaviors = RlpBehaviors.None) { if (rlpStream.IsNextItemNull()) { rlpStream.ReadByte(); return(null); } bool isStorage = (rlpBehaviors & RlpBehaviors.Storage) != 0; TxReceipt txReceipt = new TxReceipt(); rlpStream.ReadSequenceLength(); byte[] firstItem = rlpStream.DecodeByteArray(); if (firstItem.Length == 1) { txReceipt.StatusCode = firstItem[0]; } else { txReceipt.PostTransactionState = firstItem.Length == 0 ? null : new Keccak(firstItem); } if (isStorage) { txReceipt.BlockHash = rlpStream.DecodeKeccak(); } if (isStorage) { txReceipt.BlockNumber = (long)rlpStream.DecodeUInt256(); } if (isStorage) { txReceipt.Index = rlpStream.DecodeInt(); } if (isStorage) { txReceipt.Sender = rlpStream.DecodeAddress(); } if (isStorage) { txReceipt.Recipient = rlpStream.DecodeAddress(); } if (isStorage) { txReceipt.ContractAddress = rlpStream.DecodeAddress(); } if (isStorage) { txReceipt.GasUsed = (long)rlpStream.DecodeUBigInt(); } txReceipt.GasUsedTotal = (long)rlpStream.DecodeUBigInt(); txReceipt.Bloom = rlpStream.DecodeBloom(); int lastCheck = rlpStream.ReadSequenceLength() + rlpStream.Position; List <LogEntry> logEntries = new List <LogEntry>(); while (rlpStream.Position < lastCheck) { logEntries.Add(Rlp.Decode <LogEntry>(rlpStream, RlpBehaviors.AllowExtraData)); } bool allowExtraData = (rlpBehaviors & RlpBehaviors.AllowExtraData) != 0; if (!allowExtraData) { rlpStream.Check(lastCheck); } if (!allowExtraData) { if (isStorage && _supportTxHash) { // since txHash was added later and may not be in rlp, we provide special mark byte that it will be next if (rlpStream.PeekByte() == MarkTxHashByte) { rlpStream.ReadByte(); txReceipt.TxHash = rlpStream.DecodeKeccak(); } } // since error was added later we can only rely on it in cases where we read receipt only and no data follows, empty errors might not be serialized if (rlpStream.Position != rlpStream.Length) { txReceipt.Error = rlpStream.DecodeString(); } } txReceipt.Logs = logEntries.ToArray(); return(txReceipt); }
public void Encode(RlpStream rlpStream, TxReceipt item, RlpBehaviors rlpBehaviors = RlpBehaviors.None) { if (item == null) { rlpStream.EncodeNullObject(); return; } var(totalLength, logsLength) = GetContentLength(item, rlpBehaviors); bool isStorage = (rlpBehaviors & RlpBehaviors.Storage) != 0; bool isEip658receipts = (rlpBehaviors & RlpBehaviors.Eip658Receipts) == RlpBehaviors.Eip658Receipts; rlpStream.StartSequence(totalLength); if (isEip658receipts) { rlpStream.Encode(item.StatusCode); } else { rlpStream.Encode(item.PostTransactionState); } if (isStorage) { rlpStream.Encode(item.BlockHash); rlpStream.Encode(item.BlockNumber); rlpStream.Encode(item.Index); rlpStream.Encode(item.Sender); rlpStream.Encode(item.Recipient); rlpStream.Encode(item.ContractAddress); rlpStream.Encode(item.GasUsed); rlpStream.Encode(item.GasUsedTotal); rlpStream.Encode(item.Bloom); rlpStream.StartSequence(logsLength); for (var i = 0; i < item.Logs.Length; i++) { rlpStream.Encode(item.Logs[i]); } if (_supportTxHash) { rlpStream.WriteByte(MarkTxHashByte); rlpStream.Encode(item.TxHash); } rlpStream.Encode(item.Error); } else { rlpStream.Encode(item.GasUsedTotal); rlpStream.Encode(item.Bloom); rlpStream.StartSequence(logsLength); for (var i = 0; i < item.Logs.Length; i++) { rlpStream.Encode(item.Logs[i]); } rlpStream.Encode(item.Error); } }
public static T Decode <T>(RlpStream rlpStream, RlpBehaviors rlpBehaviors = RlpBehaviors.None) { var rlpDecoder = GetDecoder <T>(); return(rlpDecoder != null?rlpDecoder.Decode(rlpStream, rlpBehaviors) : throw new RlpException($"{nameof(Rlp)} does not support decoding {typeof(T).Name}")); }