Ejemplo n.º 1
0
        public BlockInfo Decode(ref Rlp.ValueDecoderContext decoderContext, RlpBehaviors rlpBehaviors = RlpBehaviors.None)
        {
            if (decoderContext.IsNextItemNull())
            {
                decoderContext.ReadByte();
                return(null);
            }

            int lastCheck = decoderContext.ReadSequenceLength() + decoderContext.Position;

            BlockInfo blockInfo = new BlockInfo
            {
                BlockHash       = decoderContext.DecodeKeccak(),
                WasProcessed    = decoderContext.DecodeBool(),
                TotalDifficulty = decoderContext.DecodeUInt256()
            };

            if (_chainWithFinalization)
            {
                blockInfo.IsFinalized = decoderContext.DecodeBool();
            }

            if ((rlpBehaviors & RlpBehaviors.AllowExtraData) != RlpBehaviors.AllowExtraData)
            {
                decoderContext.Check(lastCheck);
            }

            return(blockInfo);
        }
Ejemplo n.º 2
0
        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));
        }
Ejemplo n.º 3
0
        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);
        }
Ejemplo n.º 4
0
        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);
        }
    }
Ejemplo n.º 5
0
        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);
        }
    }
Ejemplo n.º 6
0
        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));
        }
Ejemplo n.º 7
0
        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();
                }
            }
        }
Ejemplo n.º 8
0
        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);
        }
Ejemplo n.º 9
0
        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);
        }