コード例 #1
0
ファイル: BlockDecoder.cs プロジェクト: vicnaum/nethermind
        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.HasFlag(RlpBehaviors.AllowExtraData))
            {
                rlpStream.Check(blockCheck);
            }

            return(new Block(header, transactions, ommerHeaders));
        }
コード例 #2
0
        public Block Decode(Rlp.DecoderContext context, RlpBehaviors rlpBehaviors = RlpBehaviors.None)
        {
            int sequenceLength = context.ReadSequenceLength();

            if (sequenceLength == 0)
            {
                return(null);
            }

            int blockCheck = context.Position + sequenceLength;

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

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

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

            context.Check(transactionsCheck);

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

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

            context.Check(ommersCheck);

            if (!rlpBehaviors.HasFlag(RlpBehaviors.AllowExtraData))
            {
                context.Check(blockCheck);
            }

            return(new Block(header, transactions, ommerHeaders));
        }
コード例 #3
0
        private (int Total, int Logs) GetContentLength(TxReceipt item, RlpBehaviors rlpBehaviors)
        {
            var contentLength = 0;
            var logsLength    = 0;

            if (item == null)
            {
                return(contentLength, 0);
            }
            bool isStorage = (rlpBehaviors & RlpBehaviors.Storage) != 0;

            if (isStorage)
            {
                contentLength += Rlp.LengthOf(item.BlockHash);
                contentLength += Rlp.LengthOf(item.BlockNumber);
                contentLength += Rlp.LengthOf(item.Index);
                contentLength += Rlp.LengthOf(item.Sender);
                contentLength += Rlp.LengthOf(item.Recipient);
                contentLength += Rlp.LengthOf(item.ContractAddress);
                contentLength += Rlp.LengthOf(item.GasUsed);
                contentLength += Rlp.LengthOf(item.Error);
            }

            contentLength += Rlp.LengthOf(item.GasUsedTotal);
            contentLength += Rlp.LengthOf(item.Bloom);

            logsLength     = GetLogsLength(item);
            contentLength += Rlp.GetSequenceRlpLength(logsLength);

            bool isEip658receipts = (rlpBehaviors & RlpBehaviors.Eip658Receipts) == RlpBehaviors.Eip658Receipts;

            if (isEip658receipts)
            {
                contentLength += Rlp.LengthOf(item.StatusCode);
            }
            else
            {
                contentLength += Rlp.LengthOf(item.PostTransactionState);
            }

            return(contentLength, logsLength);
        }
コード例 #4
0
        public static Rlp Encode(
            Transaction transaction,
            bool forSigning,
            bool isEip155Enabled = false,
            int chainId          = 0)
        {
            Rlp[] sequence = new Rlp[forSigning && !(isEip155Enabled && chainId != 0) ? 6 : 9];
            sequence[0] = Encode(transaction.Nonce);
            sequence[1] = Encode(transaction.GasPrice);
            sequence[2] = Encode(transaction.GasLimit);
            sequence[3] = Encode(transaction.To);
            sequence[4] = Encode(transaction.Value);
            sequence[5] = Encode(transaction.To == null ? transaction.Init : transaction.Data);

            if (forSigning)
            {
                if (isEip155Enabled && chainId != 0)
                {
                    sequence[6] = Encode(chainId);
                    sequence[7] = OfEmptyByteArray;
                    sequence[8] = OfEmptyByteArray;
                }
            }
            else
            {
                // TODO: below obviously fails when Signature is null
                sequence[6] = transaction.Signature == null ? OfEmptyByteArray : Encode(transaction.Signature.V);
                sequence[7] =
                    Encode(transaction.Signature == null
                        ? null
                        : transaction.Signature.R
                           .WithoutLeadingZeros());  // TODO: consider storing R and S differently
                sequence[8] =
                    Encode(transaction.Signature == null
                        ? null
                        : transaction.Signature.S
                           .WithoutLeadingZeros());  // TODO: consider storing R and S differently
            }

            return(Encode(sequence));
        }
コード例 #5
0
        public static Rlp Encode <T>(T[] items, RlpBehaviors behaviors = RlpBehaviors.None)
        {
            if (items == null)
            {
                return(OfEmptySequence);
            }

            if (Decoders.ContainsKey(typeof(T)))
            {
                IRlpDecoder <T> decoder     = (IRlpDecoder <T>)Decoders[typeof(T)];
                Rlp[]           rlpSequence = new Rlp[items.Length];
                for (int i = 0; i < items.Length; i++)
                {
                    rlpSequence[i] = items[i] == null ? OfEmptySequence : decoder.Encode(items[i], behaviors);
                }

                return(Encode(rlpSequence));
            }

            throw new RlpException($"{nameof(Rlp)} does not support encoding {typeof(T).Name}");
        }
コード例 #6
0
        public Rlp Encode(ChainLevelInfo item, RlpBehaviors rlpBehaviors = RlpBehaviors.None)
        {
            if (item == null)
            {
                return(Rlp.OfEmptySequence);
            }

            Rlp[] elements = new Rlp[2];
            elements[0] = Rlp.Encode(item.HasBlockOnMainChain);
            elements[1] = Rlp.Encode(item.BlockInfos);

            if (item.BlockInfos.Any(bi => bi == null))
            {
                throw new InvalidOperationException($"{nameof(BlockInfo)} is null when encoding {nameof(ChainLevelInfo)}");
            }

            Rlp rlp = Rlp.Encode(elements);


            return(rlp);
        }
コード例 #7
0
        public Rlp Encode(ChainLevelInfo item, RlpBehaviors rlpBehaviors = RlpBehaviors.None)
        {
            if (item == null)
            {
                return(Rlp.OfEmptySequence);
            }

            Rlp[] elements = new Rlp[2];
            elements[0] = Rlp.Encode(item.HasBlockOnMainChain);
            elements[1] = Rlp.Encode(item.BlockInfos);

            if (item.BlockInfos.Any(bi => bi == null))
            {
                throw new Exception();
            }

            Rlp rlp = Rlp.Encode(elements);


            return(rlp);
        }
コード例 #8
0
        public ChainLevelInfo Decode(Rlp.DecoderContext context, RlpBehaviors rlpBehaviors = RlpBehaviors.None)
        {
            int  lastCheck         = context.ReadSequenceLength() + context.Position;
            bool hasMainChainBlock = context.DecodeBool();

            List <BlockInfo> blockInfos = new List <BlockInfo>();

            context.ReadSequenceLength();
            while (context.Position < lastCheck)
            {
                blockInfos.Add(Rlp.Decode <BlockInfo>(context, RlpBehaviors.AllowExtraData));
            }

            if (!rlpBehaviors.HasFlag(RlpBehaviors.AllowExtraData))
            {
                context.Check(lastCheck);
            }

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

            return(info);
        }
コード例 #9
0
        public void Encode(MemoryStream stream, Block item, RlpBehaviors rlpBehaviors = RlpBehaviors.None)
        {
            if (item == null)
            {
                stream.Write(Rlp.OfEmptySequence.Bytes);
                return;
            }

            (int contentLength, int txsLength, int ommersLength) = GetContentLength(item, rlpBehaviors);
            Rlp.StartSequence(stream, contentLength);
            _headerDecoder.Encode(stream, item.Header);
            Rlp.StartSequence(stream, txsLength);
            for (int i = 0; i < item.Transactions.Length; i++)
            {
                _txDecoder.Encode(stream, item.Transactions[i]);
            }

            Rlp.StartSequence(stream, ommersLength);
            for (int i = 0; i < item.Ommers.Length; i++)
            {
                _headerDecoder.Encode(stream, item.Ommers[i]);
            }
        }
コード例 #10
0
        public Rlp Encode(TxReceipt item, RlpBehaviors rlpBehaviors = RlpBehaviors.None)
        {
            if (rlpBehaviors.HasFlag(RlpBehaviors.Storage))
            {
                return(Rlp.Encode(
                           rlpBehaviors.HasFlag(RlpBehaviors.Eip658Receipts) ? Rlp.Encode(item.StatusCode) : Rlp.Encode(item.PostTransactionState),
                           Rlp.Encode(item.BlockHash),
                           Rlp.Encode(item.BlockNumber),
                           Rlp.Encode(item.Index),
                           Rlp.Encode(item.Sender),
                           Rlp.Encode(item.Recipient),
                           Rlp.Encode(item.ContractAddress),
                           Rlp.Encode(item.GasUsed),
                           Rlp.Encode(item.GasUsedTotal),
                           Rlp.Encode(item.Bloom),
                           Rlp.Encode(item.Logs),
                           Rlp.Encode(item.Error)));
            }

            return(Rlp.Encode(
                       rlpBehaviors.HasFlag(RlpBehaviors.Eip658Receipts) ? Rlp.Encode(item.StatusCode) : Rlp.Encode(item.PostTransactionState),
                       Rlp.Encode(item.GasUsedTotal),
                       Rlp.Encode(item.Bloom),
                       Rlp.Encode(item.Logs)));
        }
コード例 #11
0
        public TxReceipt Decode(Rlp.DecoderContext context, RlpBehaviors rlpBehaviors = RlpBehaviors.None)
        {
            bool      isStorage = (rlpBehaviors & RlpBehaviors.Storage) != 0;
            TxReceipt txReceipt = new TxReceipt();

            context.ReadSequenceLength();
            byte[] firstItem = context.DecodeByteArray();
            if (firstItem.Length == 1)
            {
                txReceipt.StatusCode = firstItem[0];
            }
            else
            {
                txReceipt.PostTransactionState = firstItem.Length == 0 ? null : new Keccak(firstItem);
            }

            if (isStorage)
            {
                txReceipt.BlockHash = context.DecodeKeccak();
            }
            if (isStorage)
            {
                txReceipt.BlockNumber = (long)context.DecodeUInt256();
            }
            if (isStorage)
            {
                txReceipt.Index = context.DecodeInt();
            }
            if (isStorage)
            {
                txReceipt.Sender = context.DecodeAddress();
            }
            if (isStorage)
            {
                txReceipt.Recipient = context.DecodeAddress();
            }
            if (isStorage)
            {
                txReceipt.ContractAddress = context.DecodeAddress();
            }
            if (isStorage)
            {
                txReceipt.GasUsed = (long)context.DecodeUBigInt();
            }
            txReceipt.GasUsedTotal = (long)context.DecodeUBigInt();
            txReceipt.Bloom        = context.DecodeBloom();

            int             lastCheck  = context.ReadSequenceLength() + context.Position;
            List <LogEntry> logEntries = new List <LogEntry>();

            while (context.Position < lastCheck)
            {
                logEntries.Add(Rlp.Decode <LogEntry>(context, RlpBehaviors.AllowExtraData));
            }

            bool allowExtraData = (rlpBehaviors & RlpBehaviors.AllowExtraData) != 0;

            if (!allowExtraData)
            {
                context.Check(lastCheck);
            }

            // since error was added later we can only rely on it in cases where we read receipt only and no data follows
            if (isStorage && !allowExtraData && context.Position != context.Length)
            {
                txReceipt.Error = context.DecodeString();
            }

            txReceipt.Logs = logEntries.ToArray();
            return(txReceipt);
        }
コード例 #12
0
 public int GetLength(Transaction item, RlpBehaviors rlpBehaviors)
 {
     return(Rlp.GetSequenceRlpLength(GetContentLength(item, false)));
 }
コード例 #13
0
 public int GetLength(TxReceipt item, RlpBehaviors rlpBehaviors)
 {
     return(Rlp.LengthOfSequence(GetContentLength(item, rlpBehaviors).Total));
 }
コード例 #14
0
 public int GetLength(BlockHeader item, RlpBehaviors rlpBehaviors)
 {
     return(Rlp.LengthOfSequence(GetContentLength(item, rlpBehaviors)));
 }
コード例 #15
0
 public int GetHashCode(Rlp obj)
 {
     return(obj.Bytes.GetXxHashCode());
 }
コード例 #16
0
 public Rlp Encode(Transaction item, RlpBehaviors rlpBehaviors = RlpBehaviors.None)
 {
     return(Rlp.Encode(item, false));
 }
コード例 #17
0
 public static T Decode <T>(Rlp oldRlp, RlpBehaviors rlpBehaviors = RlpBehaviors.None)
 {
     return(Decode <T>(oldRlp.Bytes.AsRlpContext(), rlpBehaviors));
 }
コード例 #18
0
 public bool Equals(Rlp other)
 {
     return(null != other && Extensions.Bytes.AreEqual(Bytes, other.Bytes));
 }
コード例 #19
0
 public Rlp Encode(TransactionReceipt item, RlpBehaviors rlpBehaviors = RlpBehaviors.None)
 {
     return(Rlp.Encode(
                rlpBehaviors.HasFlag(RlpBehaviors.Eip658Receipts) ? Rlp.Encode(item.StatusCode) : Rlp.Encode(item.PostTransactionState),
                Rlp.Encode(item.GasUsed),
                Rlp.Encode(item.Bloom),
                Rlp.Encode(item.Logs)));
 }
コード例 #20
0
 public static Rlp[] ExtractRlpList(Rlp rlp)
 {
     return(ExtractRlpList(new DecoderContext(rlp.Bytes)));
 }