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