コード例 #1
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);
        }
コード例 #2
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);
        }