1- using Lantern . Discv5 . Enr . Entries ;
1+ using Lantern . Discv5 . Enr . Entries ;
22using Lantern . Discv5 . Enr . Identity ;
33using Lantern . Discv5 . Rlp ;
44using Multiformats . Base ;
@@ -8,13 +8,14 @@ namespace Lantern.Discv5.Enr;
88
99public class Enr : IEnr , IEquatable < IEnr >
1010{
11- private readonly IDictionary < string , IEntry > _entries ;
11+ private readonly Dictionary < string , IEntry > _entries ;
1212 private readonly IIdentitySigner ? _signer ;
1313 private readonly IIdentityVerifier ? _verifier ;
1414 private byte [ ] ? _cachedNodeId ;
15+ private int ? _cachedHashCode ;
1516
1617 public Enr (
17- IDictionary < string , IEntry > initialEntries ,
18+ Dictionary < string , IEntry > initialEntries ,
1819 IIdentityVerifier verifier ,
1920 IIdentitySigner ? signer = null ,
2021 byte [ ] ? signature = null ,
@@ -51,20 +52,12 @@ public byte[] NodeId
5152 }
5253
5354 public T GetEntry < T > ( string key , T defaultValue = default ! ) where T : IEntry
54- {
55- var entry = _entries . Values . FirstOrDefault ( e => e . Key == key ) ;
56-
57- return entry is T result ? result : defaultValue ;
58- }
55+ => _entries . TryGetValue ( key , out var entry ) && entry is T result ? result : defaultValue ;
5956
6057 public void UpdateEntry < T > ( T value ) where T : class , IEntry
6158 {
62- foreach ( var existingKey in _entries . Where ( entry => entry . Value . Key . Equals ( value . Key ) ) . ToList ( ) )
63- {
64- _entries . Remove ( existingKey . Key ) ;
65- }
66-
67- _entries [ value . Key ] = value ;
59+ string key = value . Key ;
60+ _entries [ key ] = value ;
6861 IncrementSequenceNumber ( ) ;
6962 }
7063
@@ -104,20 +97,45 @@ public bool Equals(IEnr? other)
10497 return other != null && NodeId . AsSpan ( ) . SequenceEqual ( other . NodeId . AsSpan ( ) ) ;
10598 }
10699
100+ public override bool Equals ( object ? obj )
101+ {
102+ return obj is IEnr other && Equals ( other ) ;
103+ }
104+
105+ public override int GetHashCode ( )
106+ {
107+ if ( _cachedHashCode . HasValue )
108+ return _cachedHashCode . Value ;
109+
110+ var nodeId = NodeId ;
111+ var hash = new HashCode ( ) ;
112+
113+ foreach ( var b in nodeId )
114+ {
115+ hash . Add ( b ) ;
116+ }
117+
118+ _cachedHashCode = hash . ToHashCode ( ) ;
119+ return _cachedHashCode . Value ;
120+ }
121+
107122 public override string ToString ( )
108123 {
109124 return $ "enr:{ Base64Url . ToString ( EncodeRecord ( ) ) } ";
110125 }
111126
112127 public string ToEnode ( )
113128 {
114- if ( Signature == null )
115- throw new InvalidOperationException ( "Signature must be set before encoding." ) ;
129+ var publicKey = GetEntry < EntrySecp256K1 > ( EnrEntryKey . Secp256K1 ) . Value ;
130+ if ( publicKey == null )
131+ throw new InvalidOperationException ( "Public key must be present in ENR for enode format." ) ;
132+
133+ var publicKeyHex = Convert . ToHexString ( publicKey ) . ToLower ( ) ;
116134
117135 if ( ! HasKey ( EnrEntryKey . Tcp ) )
118- return $ "enode://{ Convert . ToHexString ( Signature ) . ToLower ( ) } @{ GetEntry < EntryIp > ( EnrEntryKey . Ip ) . Value } ?discport={ GetEntry < EntryUdp > ( EnrEntryKey . Udp ) . Value } ";
136+ return $ "enode://{ publicKeyHex } @{ GetEntry < EntryIp > ( EnrEntryKey . Ip ) . Value } ?discport={ GetEntry < EntryUdp > ( EnrEntryKey . Udp ) . Value } ";
119137
120- return $ "enode://{ Convert . ToHexString ( Signature ) . ToLower ( ) } @{ GetEntry < EntryIp > ( EnrEntryKey . Ip ) . Value } :{ GetEntry < EntryTcp > ( EnrEntryKey . Tcp ) . Value } ?discport={ GetEntry < EntryUdp > ( EnrEntryKey . Udp ) . Value } ";
138+ return $ "enode://{ publicKeyHex } @{ GetEntry < EntryIp > ( EnrEntryKey . Ip ) . Value } :{ GetEntry < EntryTcp > ( EnrEntryKey . Tcp ) . Value } ?discport={ GetEntry < EntryUdp > ( EnrEntryKey . Udp ) . Value } ";
121139 }
122140
123141 public string ToPeerId ( )
@@ -143,4 +161,4 @@ private byte[] EncodeEnrContent()
143161 . SelectMany ( e => e . Value . EncodeEntry ( ) )
144162 . ToArray ( ) ;
145163 }
146- }
164+ }
0 commit comments