Exemplo n.º 1
0
        public TxReceipt Decode(RlpStream rlpStream, RlpBehaviors rlpBehaviors = RlpBehaviors.None)
        {
            if (rlpStream.IsNextItemNull())
            {
                rlpStream.ReadByte();
                return(null);
            }

            TxReceipt txReceipt = new TxReceipt();

            _ = rlpStream.ReadSequenceLength();
            byte[] firstItem = rlpStream.DecodeByteArray();
            if (firstItem.Length == 1 && (firstItem[0] == 0 || firstItem[0] == 1))
            {
                txReceipt.StatusCode   = firstItem[0];
                txReceipt.GasUsedTotal = (long)rlpStream.DecodeUBigInt();
            }
            else if (firstItem.Length >= 1 && firstItem.Length <= 4)
            {
                txReceipt.GasUsedTotal            = (long)firstItem.ToUnsignedBigInteger();
                txReceipt.SkipStateAndStatusInRlp = true;
            }
            else
            {
                txReceipt.PostTransactionState = firstItem.Length == 0 ? null : new Keccak(firstItem);
                txReceipt.GasUsedTotal         = (long)rlpStream.DecodeUBigInt();
            }

            txReceipt.Bloom = rlpStream.DecodeBloom();

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

            int numberOfReceipts = rlpStream.ReadNumberOfItemsRemaining(lastCheck);

            LogEntry[] entries = new LogEntry[numberOfReceipts];
            for (int i = 0; i < numberOfReceipts; i++)
            {
                entries[i] = Rlp.Decode <LogEntry>(rlpStream, RlpBehaviors.AllowExtraData);
            }

            txReceipt.Logs = entries;
            return(txReceipt);
        }
Exemplo n.º 2
0
        public Block Decode(RlpStream rlpStream, RlpBehaviors rlpBehaviors = RlpBehaviors.None)
        {
            if (rlpStream.IsNextItemNull())
            {
                rlpStream.ReadByte();
                return(null);
            }

            int sequenceLength = rlpStream.ReadSequenceLength();
            int blockCheck     = rlpStream.Position + sequenceLength;

            BlockHeader header = Rlp.Decode <BlockHeader>(rlpStream);

            int transactionsSequenceLength  = rlpStream.ReadSequenceLength();
            int transactionsCheck           = rlpStream.Position + transactionsSequenceLength;
            List <Transaction> transactions = new List <Transaction>();

            while (rlpStream.Position < transactionsCheck)
            {
                transactions.Add(Rlp.Decode <Transaction>(rlpStream));
            }

            rlpStream.Check(transactionsCheck);

            int ommersSequenceLength        = rlpStream.ReadSequenceLength();
            int ommersCheck                 = rlpStream.Position + ommersSequenceLength;
            List <BlockHeader> ommerHeaders = new List <BlockHeader>();

            while (rlpStream.Position < ommersCheck)
            {
                ommerHeaders.Add(Rlp.Decode <BlockHeader>(rlpStream, rlpBehaviors));
            }

            rlpStream.Check(ommersCheck);

            if ((rlpBehaviors & RlpBehaviors.AllowExtraData) != RlpBehaviors.AllowExtraData)
            {
                rlpStream.Check(blockCheck);
            }

            return(new Block(header, transactions, ommerHeaders));
        }
Exemplo n.º 3
0
        public Account Decode(RlpStream rlpStream, RlpBehaviors rlpBehaviors = RlpBehaviors.None)
        {
            rlpStream.ReadSequenceLength();
            UInt256 nonce       = rlpStream.DecodeUInt256();
            UInt256 balance     = rlpStream.DecodeUInt256();
            Keccak  storageRoot = rlpStream.DecodeKeccak();
            Keccak  codeHash    = rlpStream.DecodeKeccak();
            Account account     = new Account(nonce, balance, storageRoot, codeHash);

            return(account);
        }
Exemplo n.º 4
0
        public TxReceipt Decode(RlpStream rlpStream, RlpBehaviors rlpBehaviors = RlpBehaviors.None)
        {
            if (rlpStream.IsNextItemNull())
            {
                rlpStream.ReadByte();
                return(null);
            }

            TxReceipt txReceipt = new TxReceipt();
            var       lenght    = rlpStream.ReadSequenceLength();

            byte[] firstItem = rlpStream.DecodeByteArray();
            if (firstItem.Length == 1 && (firstItem[0] == 0 || firstItem[0] == 1))
            {
                txReceipt.StatusCode   = firstItem[0];
                txReceipt.GasUsedTotal = (long)rlpStream.DecodeUBigInt();
            }
            else if (firstItem.Length >= 1 && firstItem.Length <= 4)
            {
                txReceipt.GasUsedTotal            = (long)firstItem.ToUnsignedBigInteger();
                txReceipt.SkipStateAndStatusInRlp = true;
            }
            else
            {
                txReceipt.PostTransactionState = firstItem.Length == 0 ? null : new Keccak(firstItem);
                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));
            }

            txReceipt.Logs = logEntries.ToArray();
            return(txReceipt);
        }
Exemplo n.º 5
0
        public LogEntry?Decode(RlpStream rlpStream, RlpBehaviors rlpBehaviors = RlpBehaviors.None)
        {
            if (rlpStream.IsNextItemNull())
            {
                rlpStream.ReadByte();
                return(null);
            }

            rlpStream.ReadSequenceLength();
            Address?address        = rlpStream.DecodeAddress();
            long    sequenceLength = rlpStream.ReadSequenceLength();

            Keccak[] topics = new Keccak[sequenceLength / 33];
            for (int i = 0; i < topics.Length; i++)
            {
                topics[i] = rlpStream.DecodeKeccak();
            }

            byte[] data = rlpStream.DecodeByteArray();

            return(new LogEntry(address, data, topics));
        }
Exemplo n.º 6
0
        public ChainLevelInfo?Decode(RlpStream rlpStream, RlpBehaviors rlpBehaviors = RlpBehaviors.None)
        {
            if (rlpStream.Length == 0)
            {
                throw new RlpException($"Received a 0 length stream when decoding a {nameof(ChainLevelInfo)}");
            }

            if (rlpStream.IsNextItemNull())
            {
                return(null);
            }

            int  lastCheck         = rlpStream.ReadSequenceLength() + rlpStream.Position;
            bool hasMainChainBlock = rlpStream.DecodeBool();

            List <BlockInfo> blockInfos = new();

            rlpStream.ReadSequenceLength();
            while (rlpStream.Position < lastCheck)
            {
                // block info can be null for corrupted states (also cases where block hash is null from the old DBs)
                BlockInfo?blockInfo = Rlp.Decode <BlockInfo?>(rlpStream, RlpBehaviors.AllowExtraData);
                if (blockInfo is not null)
                {
                    blockInfos.Add(blockInfo);
                }
            }

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

            ChainLevelInfo info = new(hasMainChainBlock, blockInfos.ToArray());

            return(info);
        }
Exemplo n.º 7
0
        public static T[] DecodeArray <T>(RlpStream rlpStream, RlpBehaviors rlpBehaviors = RlpBehaviors.None)
        {
            if (Decoders.ContainsKey(typeof(T)))
            {
                IRlpDecoder <T> decoder       = (IRlpDecoder <T>)Decoders[typeof(T)];
                int             checkPosition = rlpStream.ReadSequenceLength() + rlpStream.Position;
                T[]             result        = new T[rlpStream.ReadNumberOfItemsRemaining(checkPosition)];
                for (int i = 0; i < result.Length; i++)
                {
                    result[i] = decoder.Decode(rlpStream, rlpBehaviors);
                }

                return(result);
            }

            throw new RlpException($"{nameof(Rlp)} does not support decoding {typeof(T).Name}");
        }
Exemplo n.º 8
0
        public Account?Decode(RlpStream rlpStream, RlpBehaviors rlpBehaviors = RlpBehaviors.None)
        {
            int length = rlpStream.ReadSequenceLength();

            if (length == 1)
            {
                return(null);
            }

            UInt256 nonce       = rlpStream.DecodeUInt256();
            UInt256 balance     = rlpStream.DecodeUInt256();
            Keccak  storageRoot = DecodeStorageRoot(rlpStream);
            Keccak  codeHash    = DecodeCodeHash(rlpStream);
            Account account     = new(nonce, balance, storageRoot, codeHash);

            return(account);
        }
Exemplo n.º 9
0
        public BlockInfo?Decode(RlpStream rlpStream, RlpBehaviors rlpBehaviors = RlpBehaviors.None)
        {
            if (rlpStream.IsNextItemNull())
            {
                rlpStream.ReadByte();
                return(null);
            }

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

            Keccak?blockHash = rlpStream.DecodeKeccak();

            bool    wasProcessed    = rlpStream.DecodeBool();
            UInt256 totalDifficulty = rlpStream.DecodeUInt256();

            BlockMetadata metadata = BlockMetadata.None;

            // if we hadn't reached the end of the stream, assume we have metadata to decode
            if (rlpStream.Position != lastCheck)
            {
                metadata = (BlockMetadata)rlpStream.DecodeInt();
            }

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

            if (blockHash is null)
            {
                return(null);
            }

            BlockInfo blockInfo = new(blockHash, totalDifficulty)
            {
                WasProcessed = wasProcessed,
                Metadata     = metadata,
            };

            return(blockInfo);
        }
Exemplo n.º 10
0
        public BlockInfo?Decode(RlpStream rlpStream, RlpBehaviors rlpBehaviors = RlpBehaviors.None)
        {
            if (rlpStream.IsNextItemNull())
            {
                rlpStream.ReadByte();
                return(null);
            }

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

            Keccak?blockHash = rlpStream.DecodeKeccak();

            bool    wasProcessed    = rlpStream.DecodeBool();
            UInt256 totalDifficulty = rlpStream.DecodeUInt256();

            bool isFinalized = false;

            if (_chainWithFinalization)
            {
                isFinalized = rlpStream.DecodeBool();
            }

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

            if (blockHash is null)
            {
                return(null);
            }

            BlockInfo blockInfo = new(blockHash, totalDifficulty)
            {
                WasProcessed = wasProcessed,
                IsFinalized  = isFinalized
            };

            return(blockInfo);
        }
Exemplo n.º 11
0
        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);
        }
Exemplo n.º 12
0
        public BlockHeader?Decode(RlpStream rlpStream, RlpBehaviors rlpBehaviors = RlpBehaviors.None)
        {
            if (rlpStream.IsNextItemNull())
            {
                rlpStream.ReadByte();
                return(null);
            }

            Span <byte> headerRlp            = rlpStream.PeekNextItem();
            int         headerSequenceLength = rlpStream.ReadSequenceLength();
            int         headerCheck          = rlpStream.Position + headerSequenceLength;

            Keccak? parentHash       = rlpStream.DecodeKeccak();
            Keccak? unclesHash       = 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();
            long    number           = rlpStream.DecodeLong();
            long    gasLimit         = rlpStream.DecodeLong();
            long    gasUsed          = rlpStream.DecodeLong();
            UInt256 timestamp        = rlpStream.DecodeUInt256();

            byte[]? extraData = rlpStream.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 (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 (blockHeader.Number >= Eip1559TransitionBlock)
            {
                blockHeader.BaseFeePerGas = rlpStream.DecodeUInt256();
            }

            if ((rlpBehaviors & RlpBehaviors.AllowExtraData) != RlpBehaviors.AllowExtraData)
            {
                rlpStream.Check(headerCheck);
            }

            return(blockHeader);
        }
Exemplo n.º 13
0
        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);
        }
Exemplo n.º 14
0
        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);
        }