예제 #1
0
        public static Signature DecodeSignature(RlpStream rlpStream)
        {
            ReadOnlySpan <byte> vBytes = rlpStream.DecodeByteArraySpan();
            ReadOnlySpan <byte> rBytes = rlpStream.DecodeByteArraySpan();
            ReadOnlySpan <byte> sBytes = rlpStream.DecodeByteArraySpan();

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

            ulong v = vBytes.ReadEthUInt64();

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

            return(signature);
        }
예제 #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);
        }