Пример #1
0
        public static Signature DecodeSignature(RlpStream rlpStream)
        {
            Span <byte> vBytes = rlpStream.DecodeByteArraySpan();
            Span <byte> rBytes = rlpStream.DecodeByteArraySpan();
            Span <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");
            }

            int v = vBytes.ToInt32();

            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 AuthEip8Message Deserialize(byte[] msgBytes)
        {
            RlpStream       rlpStream   = msgBytes.AsRlpStream();
            AuthEip8Message authMessage = new();

            rlpStream.ReadSequenceLength();
            ReadOnlySpan <byte> sigAllBytes = rlpStream.DecodeByteArraySpan();
            Signature           signature   = new(sigAllBytes.Slice(0, 64), sigAllBytes[64]); // since Signature class is Ethereum style it expects V as the 65th byte, hence we use RecoveryID constructor

            authMessage.Signature = signature;
            authMessage.PublicKey = new PublicKey(rlpStream.DecodeByteArraySpan());
            authMessage.Nonce     = rlpStream.DecodeByteArray();
            int version = rlpStream.DecodeInt();

            return(authMessage);
        }
Пример #3
0
    public PingMsg Deserialize(byte[] msgBytes)
    {
        (PublicKey FarPublicKey, byte[] Mdc, byte[] Data)results = PrepareForDeserialization(msgBytes);
        RlpStream rlp = results.Data.AsRlpStream();

        rlp.ReadSequenceLength();
        int version = rlp.DecodeInt();

        rlp.ReadSequenceLength();
        ReadOnlySpan <byte> sourceAddress = rlp.DecodeByteArraySpan();

        // TODO: please note that we decode only one field for port and if the UDP is different from TCP then
        // our discovery messages will not be routed correctly (the fix will not be part of this commit)
        rlp.DecodeInt();               // UDP port
        int tcpPort = rlp.DecodeInt(); // we assume here that UDP and TCP port are same

        IPEndPoint source = GetAddress(sourceAddress, tcpPort);

        rlp.ReadSequenceLength();
        ReadOnlySpan <byte> destinationAddress = rlp.DecodeByteArraySpan();
        IPEndPoint          destination        = GetAddress(destinationAddress, rlp.DecodeInt());

        rlp.DecodeInt(); // UDP port

        long    expireTime = rlp.DecodeLong();
        PingMsg msg        = new(results.FarPublicKey, expireTime, source, destination, results.Mdc);

        msg.Version = version;
        if (version == 4)
        {
            if (!rlp.HasBeenRead)
            {
                long enrSequence = rlp.DecodeLong();
                msg.EnrSequence = enrSequence;
            }
        }
        else
        {
            // what do we do when receive version 5?
        }

        return(msg);
    }
        public AckEip8Message Deserialize(byte[] msgBytes)
        {
            RlpStream      rlpStream       = msgBytes.AsRlpStream();
            AckEip8Message authEip8Message = new();

            rlpStream.ReadSequenceLength();
            authEip8Message.EphemeralPublicKey = new PublicKey(rlpStream.DecodeByteArraySpan());
            authEip8Message.Nonce = rlpStream.DecodeByteArray();
            return(authEip8Message);
        }
Пример #5
0
        public PingMessage Deserialize(byte[] msg)
        {
            (PingMessage Message, byte[] Mdc, byte[] Data)results = PrepareForDeserialization <PingMessage>(msg);

            RlpStream rlp = results.Data.AsRlpStream();

            rlp.ReadSequenceLength();
            int version = rlp.DecodeInt();

            rlp.ReadSequenceLength();
            ReadOnlySpan <byte> sourceAddress = rlp.DecodeByteArraySpan();

            // TODO: please note that we decode only one field for port and if the UDP is different from TCP then
            // our discovery messages will not be routed correctly (the fix will not be part of this commit)
            rlp.DecodeInt();               // UDP port
            int tcpPort = rlp.DecodeInt(); // we assume here that UDP and TCP port are same

            IPEndPoint source = GetAddress(sourceAddress, tcpPort);

            rlp.ReadSequenceLength();
            ReadOnlySpan <byte> destinationAddress = rlp.DecodeByteArraySpan();
            IPEndPoint          destination        = GetAddress(destinationAddress, rlp.DecodeInt());

            rlp.DecodeInt(); // UDP port

            long expireTime = rlp.DecodeLong();

            PingMessage message = results.Message;

            message.SourceAddress      = source;
            message.DestinationAddress = destination;
            message.Mdc            = results.Mdc;
            message.Version        = version;
            message.ExpirationTime = expireTime;

            return(message);
        }
        public NetworkNode Decode(RlpStream rlpStream, RlpBehaviors rlpBehaviors = RlpBehaviors.None)
        {
            rlpStream.ReadSequenceLength();

            PublicKey publicKey = new(rlpStream.DecodeByteArraySpan());
            string    ip        = rlpStream.DecodeString();
            int       port      = (int)rlpStream.DecodeByteArraySpan().ReadEthUInt64();

            rlpStream.SkipItem();
            long reputation = 0L;

            try
            {
                reputation = rlpStream.DecodeLong();
            }
            catch (RlpException)
            {
                // regression - old format
            }

            NetworkNode networkNode = new(publicKey, ip != string.Empty ? ip : null, port, reputation);

            return(networkNode);
        }
Пример #7
0
        public ParityLikeTxTrace Decode(RlpStream rlpStream, RlpBehaviors rlpBehaviors = RlpBehaviors.None)
        {
            ParityLikeTxTrace trace = new ParityLikeTxTrace();

            rlpStream.ReadSequenceLength();
            trace.BlockHash       = rlpStream.DecodeKeccak();
            trace.BlockNumber     = (long)rlpStream.DecodeUInt256();
            trace.TransactionHash = rlpStream.DecodeKeccak();
            Span <byte> txPosBytes = rlpStream.DecodeByteArraySpan();

            trace.TransactionPosition = txPosBytes.Length == 0 ? (int?)null : txPosBytes.ReadEthInt32();
            rlpStream.ReadSequenceLength();
            trace.Action       = DecodeAction(rlpStream);
            trace.StateChanges = DecodeStateDiff(rlpStream);
            // stateChanges

            return(trace);
        }
Пример #8
0
    public PongMsg Deserialize(byte[] msgBytes)
    {
        (PublicKey FarPublicKey, byte[] Mdc, byte[] Data)results = PrepareForDeserialization(msgBytes);

        RlpStream rlp = results.Data.AsRlpStream();

        rlp.ReadSequenceLength();
        rlp.ReadSequenceLength();

        // GetAddress(rlp.DecodeByteArray(), rlp.DecodeInt());
        rlp.DecodeByteArraySpan();
        rlp.DecodeInt(); // UDP port (we ignore and take it from Netty)
        rlp.DecodeInt(); // TCP port
        byte[] token          = rlp.DecodeByteArray();
        long   expirationTime = rlp.DecodeLong();

        PongMsg msg = new(results.FarPublicKey, expirationTime, token);

        return(msg);
    }
Пример #9
0
        public PongMessage Deserialize(byte[] msg)
        {
            (PongMessage Message, byte[] Mdc, byte[] Data)results = PrepareForDeserialization <PongMessage>(msg);

            RlpStream rlp = results.Data.AsRlpStream();

            rlp.ReadSequenceLength();
            rlp.ReadSequenceLength();

            // GetAddress(rlp.DecodeByteArray(), rlp.DecodeInt());
            rlp.DecodeByteArraySpan();
            rlp.DecodeInt(); // UDP port (we ignore and take it from Netty)
            rlp.DecodeInt(); // TCP port
            byte[] token          = rlp.DecodeByteArray();
            long   expirationTime = rlp.DecodeLong();

            PongMessage message = results.Message;

            message.PingMdc        = token;
            message.ExpirationTime = expirationTime;

            return(message);
        }
Пример #10
0
        public HelloMessage Deserialize(byte[] bytes)
        {
            RlpStream rlpStream = bytes.AsRlpStream();

            rlpStream.ReadSequenceLength();

            HelloMessage helloMessage = new HelloMessage();

            helloMessage.P2PVersion   = rlpStream.DecodeByte();
            helloMessage.ClientId     = string.Intern(rlpStream.DecodeString());
            helloMessage.Capabilities = rlpStream.DecodeArray(ctx =>
            {
                ctx.ReadSequenceLength();
                string protocolCode = string.Intern(ctx.DecodeString());
                int version         = ctx.DecodeByte();
                return(new Capability(protocolCode, version));
            }).ToList();

            helloMessage.ListenPort = rlpStream.DecodeInt();

            ReadOnlySpan <byte> publicKeyBytes = rlpStream.DecodeByteArraySpan();

            if (publicKeyBytes.Length != PublicKey.LengthInBytes &&
                publicKeyBytes.Length != PublicKey.PrefixedLengthInBytes)
            {
                throw new NetworkingException(
                          $"Client {helloMessage.ClientId} sent an invalid public key format " +
                          $"(length was {publicKeyBytes.Length})",
                          NetworkExceptionType.HandshakeOrInit);
            }
            else
            {
                helloMessage.NodeId = new PublicKey(publicKeyBytes);
            }

            return(helloMessage);
        }
Пример #11
0
    /// <summary>
    /// Deserializes a <see cref="NodeRecord"/> from an <see cref="RlpStream"/>.
    /// </summary>
    /// <param name="rlpStream">A stream to read the serialized data from.</param>
    /// <returns>A deserialized <see cref="NodeRecord"/></returns>
    public NodeRecord Deserialize(RlpStream rlpStream)
    {
        int startPosition   = rlpStream.Position;
        int recordRlpLength = rlpStream.ReadSequenceLength();

        NodeRecord nodeRecord = new();

        ReadOnlySpan <byte> sigBytes  = rlpStream.DecodeByteArraySpan();
        Signature           signature = new(sigBytes, 0);

        bool canVerify   = true;
        long enrSequence = rlpStream.DecodeLong();

        while (rlpStream.Position < startPosition + recordRlpLength)
        {
            string key = rlpStream.DecodeString();
            switch (key)
            {
            case EnrContentKey.Eth:
                _ = rlpStream.ReadSequenceLength();
                _ = rlpStream.ReadSequenceLength();
                byte[] forkHash  = rlpStream.DecodeByteArray();
                long   nextBlock = rlpStream.DecodeLong();
                nodeRecord.SetEntry(new EthEntry(forkHash, nextBlock));
                break;

            case EnrContentKey.Id:
                rlpStream.SkipItem();
                nodeRecord.SetEntry(IdEntry.Instance);
                break;

            case EnrContentKey.Ip:
                ReadOnlySpan <byte> ipBytes = rlpStream.DecodeByteArraySpan();
                IPAddress           address = new(ipBytes);
                nodeRecord.SetEntry(new IpEntry(address));
                break;

            case EnrContentKey.Tcp:
                int tcpPort = rlpStream.DecodeInt();
                nodeRecord.SetEntry(new TcpEntry(tcpPort));
                break;

            case EnrContentKey.Udp:
                int udpPort = rlpStream.DecodeInt();
                nodeRecord.SetEntry(new UdpEntry(udpPort));
                break;

            case EnrContentKey.Secp256K1:
                ReadOnlySpan <byte> keyBytes    = rlpStream.DecodeByteArraySpan();
                CompressedPublicKey reportedKey = new(keyBytes);
                nodeRecord.SetEntry(new Secp256K1Entry(reportedKey));
                break;

            // snap
            default:
                canVerify = false;
                rlpStream.SkipItem();
                nodeRecord.Snap = true;
                break;
            }
        }

        if (!canVerify)
        {
            rlpStream.Position = startPosition;
            rlpStream.ReadSequenceLength();
            rlpStream.SkipItem(); // signature
            int       noSigContentLength    = rlpStream.Length - rlpStream.Position;
            int       noSigSequenceLength   = Rlp.LengthOfSequence(noSigContentLength);
            byte[]    originalContent       = new byte[noSigSequenceLength];
            RlpStream originalContentStream = new (originalContent);
            originalContentStream.StartSequence(noSigContentLength);
            originalContentStream.Write(rlpStream.Read(noSigContentLength));
            rlpStream.Position            = startPosition;
            nodeRecord.OriginalContentRlp = originalContentStream.Data !;
        }

        nodeRecord.EnrSequence = enrSequence;
        nodeRecord.Signature   = signature;

        return(nodeRecord);
    }