/// <summary>
        /// We pay a big copy-paste tax to maintain ValueDecoders but we believe that the amount of allocations saved
        /// make it worth it. To be reviewed periodically.
        /// Question to Lukasz here -> would it be fine to always use ValueDecoderContext only?
        /// I believe it cannot be done for the network items decoding and is only relevant for the DB loads.
        /// </summary>
        public AccessList?Decode(
            ref Rlp.ValueDecoderContext decoderContext,
            RlpBehaviors rlpBehaviors = RlpBehaviors.None)
        {
            if (decoderContext.IsNextItemNull())
            {
                decoderContext.ReadByte();
                return(null);
            }

            int length = decoderContext.PeekNextRlpLength();
            int check  = decoderContext.Position + length;

            decoderContext.SkipLength();

            AccessListBuilder accessListBuilder = new();

            while (decoderContext.Position < check)
            {
                decoderContext.SkipLength();
                Address address = decoderContext.DecodeAddress();
                if (address == null)
                {
                    throw new RlpException("Invalid tx access list format - address is null");
                }

                accessListBuilder.AddAddress(address);

                if (decoderContext.Position < check)
                {
                    int storageCheck = decoderContext.Position + decoderContext.PeekNextRlpLength();
                    decoderContext.SkipLength();
                    while (decoderContext.Position < storageCheck)
                    {
                        UInt256 index = decoderContext.DecodeUInt256();
                        accessListBuilder.AddStorage(index);
                    }
                }
            }

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

            return(accessListBuilder.ToAccessList());
        }
Example #2
0
        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);
        }