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