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