Exemplo n.º 1
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)
            {
                Span <byte> vBytes = rlpStream.DecodeByteArraySpan();
                Span <byte> rBytes = rlpStream.DecodeByteArraySpan();
                Span <byte> sBytes = rlpStream.DecodeByteArraySpan();

                if (vBytes == null || rBytes == null || sBytes == null)
                {
                    throw new RlpException("VRS null when decoding Transaction");
                }

                if (vBytes.Length == 0 || rBytes.Length == 0 || sBytes.Length == 0)
                {
                    throw new RlpException("VRS is 0 length when decoding Transaction");
                }

                if (vBytes[0] == 0 || rBytes[0] == 0 || sBytes[0] == 0)
                {
                    throw new RlpException("VRS starting with 0");
                }

                if (rBytes.Length > 32 || sBytes.Length > 32)
                {
                    throw new RlpException("R and S lengths expected to be less or equal 32");
                }

                int v = vBytes.ReadEthInt32();

                if (rBytes.SequenceEqual(Bytes.Zero32) && sBytes.SequenceEqual(Bytes.Zero32))
                {
                    throw new RlpException("Both 'r' and 's' are zero when decoding a transaction.");
                }

                Signature signature = new Signature(rBytes, sBytes, v);
                transaction.Signature = signature;
                transaction.Hash      = Keccak.Compute(transactionSequence);
            }

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

            return(transaction);
        }