public Block Decode(ref Rlp.ValueDecoderContext decoderContext, RlpBehaviors rlpBehaviors = RlpBehaviors.None) { if (decoderContext.IsNextItemNull()) { decoderContext.ReadByte(); return(null); } int sequenceLength = decoderContext.ReadSequenceLength(); int blockCheck = decoderContext.Position + sequenceLength; BlockHeader header = Rlp.Decode <BlockHeader>(ref decoderContext); int transactionsSequenceLength = decoderContext.ReadSequenceLength(); int transactionsCheck = decoderContext.Position + transactionsSequenceLength; List <Transaction> transactions = new List <Transaction>(); while (decoderContext.Position < transactionsCheck) { transactions.Add(Rlp.Decode <Transaction>(ref decoderContext)); } decoderContext.Check(transactionsCheck); int ommersSequenceLength = decoderContext.ReadSequenceLength(); int ommersCheck = decoderContext.Position + ommersSequenceLength; List <BlockHeader> ommerHeaders = new List <BlockHeader>(); while (decoderContext.Position < ommersCheck) { ommerHeaders.Add(Rlp.Decode <BlockHeader>(ref decoderContext, rlpBehaviors)); } decoderContext.Check(ommersCheck); if ((rlpBehaviors & RlpBehaviors.AllowExtraData) != RlpBehaviors.AllowExtraData) { decoderContext.Check(blockCheck); } return(new Block(header, transactions, ommerHeaders)); }
public static void DecodeStructRef(ref Rlp.ValueDecoderContext decoderContext, RlpBehaviors storage, out LogEntryStructRef item) { if (decoderContext.IsNextItemNull()) { decoderContext.ReadByte(); item = new LogEntryStructRef(); return; } decoderContext.ReadSequenceLength(); decoderContext.DecodeAddressStructRef(out var address); var peekPrefixAndContentLength = decoderContext.PeekPrefixAndContentLength(); var sequenceLength = peekPrefixAndContentLength.PrefixLength + peekPrefixAndContentLength.ContentLength; var topics = decoderContext.Data.Slice(decoderContext.Position, sequenceLength); decoderContext.SkipItem(); var data = decoderContext.DecodeByteArraySpan(); item = new LogEntryStructRef(address, data, topics); }
public BlockInfo?Decode(ref Rlp.ValueDecoderContext decoderContext, RlpBehaviors rlpBehaviors = RlpBehaviors.None) { if (decoderContext.IsNextItemNull()) { decoderContext.ReadByte(); return(null); } int lastCheck = decoderContext.ReadSequenceLength() + decoderContext.Position; Keccak? blockHash = decoderContext.DecodeKeccak(); bool wasProcessed = decoderContext.DecodeBool(); UInt256 totalDifficulty = decoderContext.DecodeUInt256(); BlockMetadata metadata = BlockMetadata.None; // if we hadn't reached the end of the stream, assume we have metadata to decode if (decoderContext.Position != lastCheck) { metadata = (BlockMetadata)decoderContext.DecodeInt(); } if ((rlpBehaviors & RlpBehaviors.AllowExtraData) != RlpBehaviors.AllowExtraData) { decoderContext.Check(lastCheck); } if (blockHash is null) { return(null); } BlockInfo blockInfo = new(blockHash, totalDifficulty) { WasProcessed = wasProcessed, Metadata = metadata }; return(blockInfo); } }
public BlockInfo?Decode(ref Rlp.ValueDecoderContext decoderContext, RlpBehaviors rlpBehaviors = RlpBehaviors.None) { if (decoderContext.IsNextItemNull()) { decoderContext.ReadByte(); return(null); } int lastCheck = decoderContext.ReadSequenceLength() + decoderContext.Position; Keccak? blockHash = decoderContext.DecodeKeccak(); bool wasProcessed = decoderContext.DecodeBool(); UInt256 totalDifficulty = decoderContext.DecodeUInt256(); bool isFinalized = false; if (_chainWithFinalization) { isFinalized = decoderContext.DecodeBool(); } if ((rlpBehaviors & RlpBehaviors.AllowExtraData) != RlpBehaviors.AllowExtraData) { decoderContext.Check(lastCheck); } if (blockHash is null) { return(null); } BlockInfo blockInfo = new(blockHash, totalDifficulty) { WasProcessed = wasProcessed, IsFinalized = isFinalized }; return(blockInfo); } }
public LogEntry?Decode(ref Rlp.ValueDecoderContext decoderContext, RlpBehaviors rlpBehaviors = RlpBehaviors.None) { if (decoderContext.IsNextItemNull()) { decoderContext.ReadByte(); return(null); } decoderContext.ReadSequenceLength(); Address?address = decoderContext.DecodeAddress(); long sequenceLength = decoderContext.ReadSequenceLength(); Keccak[] topics = new Keccak[sequenceLength / 33]; for (int i = 0; i < topics.Length; i++) { topics[i] = decoderContext.DecodeKeccak(); } byte[] data = decoderContext.DecodeByteArray(); return(new LogEntry(address, data, topics)); }
public void DecodeStructRef(ref Rlp.ValueDecoderContext decoderContext, RlpBehaviors rlpBehaviors, out TxReceiptStructRef item) { item = new TxReceiptStructRef(); if (decoderContext.IsNextItemNull()) { decoderContext.ReadByte(); return; } bool isStorage = (rlpBehaviors & RlpBehaviors.Storage) != 0; decoderContext.ReadSequenceLength(); Span <byte> firstItem = decoderContext.DecodeByteArraySpan(); if (firstItem.Length == 1) { item.StatusCode = firstItem[0]; } else { item.PostTransactionState = firstItem.Length == 0 ? new ValueKeccak() : new ValueKeccak(firstItem); } if (isStorage) { decoderContext.DecodeValueKeccak(out item.BlockHash); } if (isStorage) { item.BlockNumber = (long)decoderContext.DecodeUInt256(); } if (isStorage) { item.Index = decoderContext.DecodeInt(); } if (isStorage) { decoderContext.DecodeAddressStructRef(out item.Sender); } if (isStorage) { decoderContext.DecodeAddressStructRef(out item.Recipient); } if (isStorage) { decoderContext.DecodeAddressStructRef(out item.ContractAddress); } if (isStorage) { item.GasUsed = (long)decoderContext.DecodeUBigInt(); } item.GasUsedTotal = (long)decoderContext.DecodeUBigInt(); decoderContext.DecodeBloomStructRef(out item.Bloom); var peekPrefixAndContentLength = decoderContext.PeekPrefixAndContentLength(); var logsBytes = peekPrefixAndContentLength.ContentLength + peekPrefixAndContentLength.PrefixLength; item.LogsRlp = decoderContext.Data.Slice(decoderContext.Position, logsBytes); decoderContext.SkipItem(); bool allowExtraData = (rlpBehaviors & RlpBehaviors.AllowExtraData) != 0; 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 (decoderContext.PeekByte() == MarkTxHashByte) { decoderContext.ReadByte(); decoderContext.DecodeValueKeccak(out item.TxHash); } } // 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 (decoderContext.Position != decoderContext.Length) { item.Error = decoderContext.DecodeString(); } } }
public TxReceipt Decode(ref Rlp.ValueDecoderContext decoderContext, RlpBehaviors rlpBehaviors = RlpBehaviors.None) { if (decoderContext.IsNextItemNull()) { decoderContext.ReadByte(); return(null); } bool isStorage = (rlpBehaviors & RlpBehaviors.Storage) != 0; TxReceipt txReceipt = new TxReceipt(); decoderContext.ReadSequenceLength(); byte[] firstItem = decoderContext.DecodeByteArray(); if (firstItem.Length == 1) { txReceipt.StatusCode = firstItem[0]; } else { txReceipt.PostTransactionState = firstItem.Length == 0 ? null : new Keccak(firstItem); } if (isStorage) { txReceipt.BlockHash = decoderContext.DecodeKeccak(); } if (isStorage) { txReceipt.BlockNumber = (long)decoderContext.DecodeUInt256(); } if (isStorage) { txReceipt.Index = decoderContext.DecodeInt(); } if (isStorage) { txReceipt.Sender = decoderContext.DecodeAddress(); } if (isStorage) { txReceipt.Recipient = decoderContext.DecodeAddress(); } if (isStorage) { txReceipt.ContractAddress = decoderContext.DecodeAddress(); } if (isStorage) { txReceipt.GasUsed = (long)decoderContext.DecodeUBigInt(); } txReceipt.GasUsedTotal = (long)decoderContext.DecodeUBigInt(); txReceipt.Bloom = decoderContext.DecodeBloom(); int lastCheck = decoderContext.ReadSequenceLength() + decoderContext.Position; List <LogEntry> logEntries = new List <LogEntry>(); while (decoderContext.Position < lastCheck) { logEntries.Add(Rlp.Decode <LogEntry>(ref decoderContext, RlpBehaviors.AllowExtraData)); } bool allowExtraData = (rlpBehaviors & RlpBehaviors.AllowExtraData) != 0; if (!allowExtraData) { decoderContext.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 (decoderContext.PeekByte() == MarkTxHashByte) { decoderContext.ReadByte(); txReceipt.TxHash = decoderContext.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 (decoderContext.Position != decoderContext.Length) { txReceipt.Error = decoderContext.DecodeString(); } } txReceipt.Logs = logEntries.ToArray(); return(txReceipt); }
public BlockHeader?Decode(ref Rlp.ValueDecoderContext decoderContext, RlpBehaviors rlpBehaviors = RlpBehaviors.None) { if (decoderContext.IsNextItemNull()) { return(null); } var headerRlp = decoderContext.PeekNextItem(); int headerSequenceLength = decoderContext.ReadSequenceLength(); int headerCheck = decoderContext.Position + headerSequenceLength; Keccak? parentHash = decoderContext.DecodeKeccak(); Keccak? unclesHash = decoderContext.DecodeKeccak(); Address?beneficiary = decoderContext.DecodeAddress(); Keccak? stateRoot = decoderContext.DecodeKeccak(); Keccak? transactionsRoot = decoderContext.DecodeKeccak(); Keccak? receiptsRoot = decoderContext.DecodeKeccak(); Bloom? bloom = decoderContext.DecodeBloom(); UInt256 difficulty = decoderContext.DecodeUInt256(); long number = decoderContext.DecodeLong(); long gasLimit = decoderContext.DecodeLong(); long gasUsed = decoderContext.DecodeLong(); UInt256 timestamp = decoderContext.DecodeUInt256(); byte[]? extraData = decoderContext.DecodeByteArray(); BlockHeader blockHeader = new( parentHash, unclesHash, beneficiary, difficulty, number, gasLimit, timestamp, extraData) { StateRoot = stateRoot, TxRoot = transactionsRoot, ReceiptsRoot = receiptsRoot, Bloom = bloom, GasUsed = gasUsed, Hash = Keccak.Compute(headerRlp) }; if (decoderContext.PeekPrefixAndContentLength().ContentLength == Keccak.Size) { blockHeader.MixHash = decoderContext.DecodeKeccak(); blockHeader.Nonce = (ulong)decoderContext.DecodeUBigInt(); } else { blockHeader.AuRaStep = (long)decoderContext.DecodeUInt256(); blockHeader.AuRaSignature = decoderContext.DecodeByteArray(); } if (blockHeader.Number >= Eip1559TransitionBlock) { blockHeader.BaseFeePerGas = decoderContext.DecodeUInt256(); } if ((rlpBehaviors & RlpBehaviors.AllowExtraData) != RlpBehaviors.AllowExtraData) { decoderContext.Check(headerCheck); } return(blockHeader); }
public Keccak Decode(ref Rlp.ValueDecoderContext decoderContext, RlpBehaviors rlpBehaviors = RlpBehaviors.None) => decoderContext.DecodeKeccak();
public BlockHeader Decode(Rlp.ValueDecoderContext decoderContext, RlpBehaviors rlpBehaviors = RlpBehaviors.None) { if (decoderContext.IsNextItemNull()) { return(null); } var headerRlp = decoderContext.PeekNextItem(); int headerSequenceLength = decoderContext.ReadSequenceLength(); int headerCheck = decoderContext.Position + headerSequenceLength; Keccak parentHash = decoderContext.DecodeKeccak(); Keccak ommersHash = decoderContext.DecodeKeccak(); Address beneficiary = decoderContext.DecodeAddress(); Keccak stateRoot = decoderContext.DecodeKeccak(); Keccak transactionsRoot = decoderContext.DecodeKeccak(); Keccak receiptsRoot = decoderContext.DecodeKeccak(); Bloom bloom = decoderContext.DecodeBloom(); UInt256 difficulty = decoderContext.DecodeUInt256(); UInt256 number = decoderContext.DecodeUInt256(); UInt256 gasLimit = decoderContext.DecodeUInt256(); UInt256 gasUsed = decoderContext.DecodeUInt256(); UInt256 timestamp = decoderContext.DecodeUInt256(); byte[] extraData = decoderContext.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 (decoderContext.PeekPrefixAndContentLength().ContentLength == Keccak.Size) { blockHeader.MixHash = decoderContext.DecodeKeccak(); blockHeader.Nonce = (ulong)decoderContext.DecodeUBigInt(); } else { blockHeader.AuRaStep = (long)decoderContext.DecodeUInt256(); blockHeader.AuRaSignature = decoderContext.DecodeByteArray(); } if ((rlpBehaviors & RlpBehaviors.AllowExtraData) != RlpBehaviors.AllowExtraData) { decoderContext.Check(headerCheck); } return(blockHeader); }
public Transaction Decode(ref Rlp.ValueDecoderContext decoderContext, RlpBehaviors rlpBehaviors = RlpBehaviors.None) { if (decoderContext.IsNextItemNull()) { decoderContext.ReadByte(); return(null); } var transactionSequence = decoderContext.PeekNextItem(); int transactionLength = decoderContext.ReadSequenceLength(); int lastCheck = decoderContext.Position + transactionLength; Transaction transaction = new Transaction(); transaction.Nonce = decoderContext.DecodeUInt256(); transaction.GasPrice = decoderContext.DecodeUInt256(); transaction.GasLimit = decoderContext.DecodeLong(); transaction.To = decoderContext.DecodeAddress(); transaction.Value = decoderContext.DecodeUInt256(); if (transaction.To == null) { transaction.Init = decoderContext.DecodeByteArray(); } else { transaction.Data = decoderContext.DecodeByteArray(); } if (decoderContext.Position < lastCheck) { Span <byte> vBytes = decoderContext.DecodeByteArraySpan(); Span <byte> rBytes = decoderContext.DecodeByteArraySpan(); Span <byte> sBytes = decoderContext.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) { decoderContext.Check(lastCheck); } return(transaction); }