예제 #1
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 += 1 + Rlp.LengthOf(item.TxHash);
            }

            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);
            }

            contentLength += Rlp.LengthOf(item.Error);

            return(contentLength, logsLength);
        }
예제 #2
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);
        }
예제 #3
0
        public Rlp Encode(BlockInfo item, RlpBehaviors rlpBehaviors = RlpBehaviors.None)
        {
            if (item == null)
            {
                return(Rlp.OfEmptySequence);
            }

            Rlp[] elements = new Rlp[_chainWithFinalization ? 4 : 3];
            elements[0] = Rlp.Encode(item.BlockHash);
            elements[1] = Rlp.Encode(item.WasProcessed);
            elements[2] = Rlp.Encode(item.TotalDifficulty);

            if (_chainWithFinalization)
            {
                elements[3] = Rlp.Encode(item.IsFinalized);
            }

            return(Rlp.Encode(elements));
        }
예제 #4
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));
        }
예제 #5
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));
        }
예제 #6
0
        public Rlp Encode(BlockInfo?item, RlpBehaviors rlpBehaviors = RlpBehaviors.None)
        {
            if (item == null)
            {
                return(Rlp.OfEmptySequence);
            }

            bool hasMetadata = item.Metadata != BlockMetadata.None;

            Rlp[] elements = new Rlp[hasMetadata ? 4 : 3];
            elements[0] = Rlp.Encode(item.BlockHash);
            elements[1] = Rlp.Encode(item.WasProcessed);
            elements[2] = Rlp.Encode(item.TotalDifficulty);
            if (hasMetadata)
            {
                elements[3] = Rlp.Encode((int)item.Metadata);
            }

            return(Rlp.Encode(elements));
        }
예제 #7
0
        private static int GetContentLength(BlockHeader?item, RlpBehaviors rlpBehaviors)
        {
            if (item is null)
            {
                return(0);
            }

            bool notForSealing = (rlpBehaviors & RlpBehaviors.ForSealing) != RlpBehaviors.ForSealing;
            int  contentLength = 0
                                 + Rlp.LengthOf(item.ParentHash)
                                 + Rlp.LengthOf(item.UnclesHash)
                                 + Rlp.LengthOf(item.Beneficiary)
                                 + Rlp.LengthOf(item.StateRoot)
                                 + Rlp.LengthOf(item.TxRoot)
                                 + Rlp.LengthOf(item.ReceiptsRoot)
                                 + Rlp.LengthOf(item.Bloom)
                                 + Rlp.LengthOf(item.Difficulty)
                                 + Rlp.LengthOf(item.Number)
                                 + Rlp.LengthOf(item.GasLimit)
                                 + Rlp.LengthOf(item.GasUsed)
                                 + Rlp.LengthOf(item.Timestamp)
                                 + Rlp.LengthOf(item.ExtraData)
                                 + (item.Number < Eip1559TransitionBlock ? 0 : Rlp.LengthOf(item.BaseFeePerGas));

            if (notForSealing)
            {
                bool isAuRa = item.AuRaSignature != null;
                if (isAuRa)
                {
                    contentLength += Rlp.LengthOf(item.AuRaStep !.Value);
                    contentLength += Rlp.LengthOf(item.AuRaSignature);
                }
                else
                {
                    contentLength += Rlp.LengthOf(item.MixHash);
                    contentLength += Rlp.LengthOfNonce(item.Nonce);
                }
            }

            return(contentLength);
        }
예제 #8
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.RAsSpan
                           .WithoutLeadingZeros());  // TODO: consider storing R and S differently
                sequence[8] =
                    Encode(transaction.Signature == null
                        ? null
                        : transaction.Signature.SAsSpan
                           .WithoutLeadingZeros());  // TODO: consider storing R and S differently
            }

            return(Encode(sequence));
        }
예제 #9
0
        private int GetContentLength(BlockHeader item, RlpBehaviors rlpBehaviors)
        {
            if (item == null)
            {
                return(0);
            }

            bool notForSealing = (rlpBehaviors & RlpBehaviors.ForSealing) != RlpBehaviors.ForSealing;
            int  contentLength = 0
                                 + Rlp.LengthOf(item.ParentHash)
                                 + Rlp.LengthOf(item.OmmersHash)
                                 + Rlp.LengthOf(item.Beneficiary)
                                 + Rlp.LengthOf(item.StateRoot)
                                 + Rlp.LengthOf(item.TxRoot)
                                 + Rlp.LengthOf(item.ReceiptsRoot)
                                 + Rlp.LengthOf(item.Bloom)
                                 + Rlp.LengthOf(item.Difficulty)
                                 + Rlp.LengthOf(item.Number)
                                 + Rlp.LengthOf(item.GasLimit)
                                 + Rlp.LengthOf(item.GasUsed)
                                 + Rlp.LengthOf(item.Timestamp)
                                 + Rlp.LengthOf(item.ExtraData);

            if (notForSealing)
            {
                var isAUra = item.AuRaSignature != null;

                if (isAUra)
                {
                    contentLength += Rlp.LengthOf(item.AuRaStep.Value);
                    contentLength += Rlp.LengthOf(item.AuRaSignature);
                }
                else
                {
                    contentLength += Rlp.LengthOf(item.MixHash);
                    contentLength += Rlp.LengthOf(item.Nonce);
                }
            }

            return(contentLength);
        }
예제 #10
0
        public Rlp Encode(ChainLevelInfo?item, RlpBehaviors rlpBehaviors = RlpBehaviors.None)
        {
            if (item == null)
            {
                return(Rlp.OfEmptySequence);
            }

            for (int i = 0; i < item.BlockInfos.Length; i++)
            {
                if (item.BlockInfos[i] == null)
                {
                    throw new InvalidOperationException($"{nameof(BlockInfo)} is null when encoding {nameof(ChainLevelInfo)}");
                }
            }

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

            return(rlp);
        }
예제 #11
0
        public static Rlp Encode <T>(T[] items, RlpBehaviors behaviors = RlpBehaviors.None)
        {
            if (items == null)
            {
                return(OfEmptySequence);
            }

            var rlpDecoder = GetDecoder <T>();

            if (rlpDecoder != null)
            {
                Rlp[] rlpSequence = new Rlp[items.Length];
                for (int i = 0; i < items.Length; i++)
                {
                    rlpSequence[i] = items[i] == null ? OfEmptySequence : rlpDecoder.Encode(items[i], behaviors);
                }

                return(Encode(rlpSequence));
            }

            throw new RlpException($"{nameof(Rlp)} does not support encoding {typeof(T).Name}");
        }
예제 #12
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);
        }
예제 #13
0
 public Rlp Encode(TxReceipt item, RlpBehaviors rlpBehaviors = RlpBehaviors.None)
 {
     return(Rlp.Encode(
                (rlpBehaviors & RlpBehaviors.Eip658Receipts) == RlpBehaviors.Eip658Receipts ? Rlp.Encode(item.StatusCode) : Rlp.Encode(item.PostTransactionState),
                Rlp.Encode(item.GasUsedTotal),
                Rlp.Encode(item.Bloom),
                Rlp.Encode(item.Logs)));
 }
예제 #14
0
 public int GetLength(TxReceipt item, RlpBehaviors rlpBehaviors)
 {
     return(Rlp.LengthOfSequence(GetContentLength(item, rlpBehaviors).Total));
 }
예제 #15
0
 public static T Decode <T>(Rlp oldRlp, RlpBehaviors rlpBehaviors = RlpBehaviors.None)
 {
     return(Decode <T>(oldRlp.Bytes.AsRlpStream(), rlpBehaviors));
 }
예제 #16
0
        public void Encode(BigInteger bigInteger, int outputLength = -1)
        {
            Rlp rlp = bigInteger == 0 ? Rlp.OfEmptyByteArray : Rlp.Encode(bigInteger.ToBigEndianByteArray(outputLength));

            Write(rlp.Bytes);
        }
예제 #17
0
 public int GetLength(Transaction item, RlpBehaviors rlpBehaviors) => Rlp.GetSequenceRlpLength(GetContentLength(item, false));
예제 #18
0
        public Rlp Encode(TxReceipt item, RlpBehaviors rlpBehaviors = RlpBehaviors.None)
        {
            bool isStorage = (rlpBehaviors & RlpBehaviors.Storage) != 0;

            if (isStorage)
            {
                return(Rlp.Encode(
                           (rlpBehaviors & RlpBehaviors.Eip658Receipts) == 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 & RlpBehaviors.Eip658Receipts) == RlpBehaviors.Eip658Receipts ? Rlp.Encode(item.StatusCode) : Rlp.Encode(item.PostTransactionState),
                       Rlp.Encode(item.GasUsedTotal),
                       Rlp.Encode(item.Bloom),
                       Rlp.Encode(item.Logs)));
        }
예제 #19
0
 public int GetLength(BlockHeader?item, RlpBehaviors rlpBehaviors)
 {
     return(Rlp.LengthOfSequence(GetContentLength(item, rlpBehaviors)));
 }
예제 #20
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);
        }
예제 #21
0
 public int GetLength(Keccak item, RlpBehaviors rlpBehaviors) => Rlp.LengthOf(item);
예제 #22
0
 public Rlp Encode(Keccak item, RlpBehaviors rlpBehaviors = RlpBehaviors.None) => Rlp.Encode(item);