From c84468e3146147c24c198fc437972a7d791837e3 Mon Sep 17 00:00:00 2001 From: Dennis Trautwein Date: Fri, 8 Sep 2023 16:26:58 +0200 Subject: [PATCH] pass addresses through the system --- coord/coordinator.go | 28 +++++++++++----------- coord/coordinator_test.go | 4 +--- query/iter.go | 50 ++++++++++++++++++++------------------- query/node.go | 6 ++--- query/pool.go | 24 +++++++++---------- query/query.go | 35 ++++++++++++++------------- routing/bootstrap.go | 14 +++++------ 7 files changed, 81 insertions(+), 80 deletions(-) diff --git a/coord/coordinator.go b/coord/coordinator.go index a7a3955..0736c83 100644 --- a/coord/coordinator.go +++ b/coord/coordinator.go @@ -218,7 +218,7 @@ func (c *Coordinator[K, A]) advanceBootstrap(ctx context.Context, ev routing.Boo bstate := c.bootstrap.Advance(ctx, ev) switch st := bstate.(type) { case *routing.StateBootstrapMessage[K, A]: - c.sendBootstrapFindNode(ctx, st.NodeID, st.QueryID, st.Stats) + c.sendBootstrapFindNode(ctx, st.Node, st.QueryID, st.Stats) case *routing.StateBootstrapWaiting: // bootstrap waiting for a message response, nothing to do @@ -277,7 +277,7 @@ func (c *Coordinator[K, A]) advancePool(ctx context.Context, ev query.PoolEvent) state := c.pool.Advance(ctx, ev) switch st := state.(type) { case *query.StatePoolQueryMessage[K, A]: - c.sendQueryMessage(ctx, st.ProtocolID, st.NodeID, st.Message, st.QueryID, st.Stats) + c.sendQueryMessage(ctx, st.ProtocolID, st.Node, st.Message, st.QueryID, st.Stats) case *query.StatePoolWaitingAtCapacity: // nothing to do except wait for message response or timeout case *query.StatePoolWaitingWithCapacity: @@ -296,7 +296,7 @@ func (c *Coordinator[K, A]) advancePool(ctx context.Context, ev query.PoolEvent) } } -func (c *Coordinator[K, A]) sendQueryMessage(ctx context.Context, protoID address.ProtocolID, to kad.NodeID[K], msg kad.Request[K, A], queryID query.QueryID, stats query.QueryStats) { +func (c *Coordinator[K, A]) sendQueryMessage(ctx context.Context, protoID address.ProtocolID, to kad.NodeInfo[K, A], msg kad.Request[K, A], queryID query.QueryID, stats query.QueryStats) { ctx, span := util.StartSpan(ctx, "Coordinator.sendQueryMessage") defer span.End() @@ -308,7 +308,7 @@ func (c *Coordinator[K, A]) sendQueryMessage(ctx context.Context, protoID addres } c.advancePool(ctx, &query.EventPoolMessageFailure[K]{ - NodeID: to, + NodeID: to.ID(), QueryID: queryID, Error: err, }) @@ -337,19 +337,19 @@ func (c *Coordinator[K, A]) sendQueryMessage(ctx context.Context, protoID addres } c.advancePool(ctx, &query.EventPoolMessageResponse[K, A]{ - NodeID: to, + Node: to, QueryID: queryID, Response: resp, }) } - err := c.ep.SendRequestHandleResponse(ctx, protoID, to, msg, msg.EmptyResponse(), 0, onMessageResponse) + err := c.ep.SendRequestHandleResponse(ctx, protoID, to.ID(), msg, msg.EmptyResponse(), 0, onMessageResponse) if err != nil { onSendError(ctx, err) } } -func (c *Coordinator[K, A]) sendBootstrapFindNode(ctx context.Context, to kad.NodeID[K], queryID query.QueryID, stats query.QueryStats) { +func (c *Coordinator[K, A]) sendBootstrapFindNode(ctx context.Context, to kad.NodeInfo[K, A], queryID query.QueryID, stats query.QueryStats) { ctx, span := util.StartSpan(ctx, "Coordinator.sendBootstrapFindNode") defer span.End() @@ -361,7 +361,7 @@ func (c *Coordinator[K, A]) sendBootstrapFindNode(ctx context.Context, to kad.No } c.advanceBootstrap(ctx, &routing.EventBootstrapMessageFailure[K]{ - NodeID: to, + NodeID: to.ID(), Error: err, }) } @@ -389,13 +389,13 @@ func (c *Coordinator[K, A]) sendBootstrapFindNode(ctx context.Context, to kad.No } c.advanceBootstrap(ctx, &routing.EventBootstrapMessageResponse[K, A]{ - NodeID: to, + Node: to, Response: resp, }) } protoID, msg := c.findNodeFn(c.self) - err := c.ep.SendRequestHandleResponse(ctx, protoID, to, msg, msg.EmptyResponse(), 0, onMessageResponse) + err := c.ep.SendRequestHandleResponse(ctx, protoID, to.ID(), msg, msg.EmptyResponse(), 0, onMessageResponse) if err != nil { onSendError(ctx, err) } @@ -443,14 +443,14 @@ func (c *Coordinator[K, A]) sendIncludeFindNode(ctx context.Context, to kad.Node func (c *Coordinator[K, A]) StartQuery(ctx context.Context, queryID query.QueryID, protocolID address.ProtocolID, msg kad.Request[K, A]) error { ctx, span := util.StartSpan(ctx, "Coordinator.StartQuery") defer span.End() - knownClosestPeers := c.rt.NearestNodes(msg.Target(), 20) + // knownClosestPeers := c.rt.NearestNodes(msg.Target(), 20) c.schedulePoolEvent(ctx, &query.EventPoolAddQuery[K, A]{ QueryID: queryID, Target: msg.Target(), ProtocolID: protocolID, Message: msg, - KnownClosestNodes: knownClosestPeers, + KnownClosestNodes: nil, }) return nil @@ -488,7 +488,7 @@ func (c *Coordinator[K, A]) AddNodes(ctx context.Context, infos []kad.NodeInfo[K // Bootstrap instructs the coordinator to begin bootstrapping the routing table. // While bootstrap is in progress, no other queries will make progress. -func (c *Coordinator[K, A]) Bootstrap(ctx context.Context, seeds []kad.NodeID[K]) error { +func (c *Coordinator[K, A]) Bootstrap(ctx context.Context, seeds []kad.NodeInfo[K, A]) error { protoID, msg := c.findNodeFn(c.self) c.scheduleBootstrapEvent(ctx, &routing.EventBootstrapStart[K, A]{ @@ -510,7 +510,7 @@ type KademliaEvent interface { // response from a node. type KademliaOutboundQueryProgressedEvent[K kad.Key[K], A kad.Address[A]] struct { QueryID query.QueryID - NodeID kad.NodeID[K] + NodeID kad.NodeInfo[K, A] Response kad.Response[K, A] Stats query.QueryStats } diff --git a/coord/coordinator_test.go b/coord/coordinator_test.go index 4781593..7519aaf 100644 --- a/coord/coordinator_test.go +++ b/coord/coordinator_test.go @@ -314,9 +314,7 @@ func TestBootstrap(t *testing.T) { queryID := query.QueryID("bootstrap") - seeds := []kad.NodeID[key.Key8]{ - nodes[1].ID(), - } + seeds := []kad.NodeInfo[key.Key8, kadtest.StrAddr]{nodes[1]} err = c.Bootstrap(ctx, seeds) require.NoError(t, err) diff --git a/query/iter.go b/query/iter.go index eaa11b9..4a59eb5 100644 --- a/query/iter.go +++ b/query/iter.go @@ -3,53 +3,55 @@ package query import ( "context" + "github.com/plprobelab/go-kademlia/internal/kadtest" + "github.com/plprobelab/go-kademlia/kad" "github.com/plprobelab/go-kademlia/key" "github.com/plprobelab/go-kademlia/key/trie" ) // A NodeIter iterates nodes according to some strategy. -type NodeIter[K kad.Key[K]] interface { +type NodeIter[K kad.Key[K], A kad.Address[A]] interface { // Add adds node information to the iterator - Add(*NodeStatus[K]) + Add(*NodeStatus[K, A]) // Find returns the node information corresponding to the given Kademlia key - Find(K) (*NodeStatus[K], bool) + Find(K) (*NodeStatus[K, A], bool) // Each applies fn to each entry in the iterator in order. Each stops and returns true if fn returns true. // Otherwise Each returns false when there are no further entries. - Each(ctx context.Context, fn func(context.Context, *NodeStatus[K]) bool) bool + Each(ctx context.Context, fn func(context.Context, *NodeStatus[K, A]) bool) bool } // A ClosestNodesIter iterates nodes in order of ascending distance from a key. -type ClosestNodesIter[K kad.Key[K]] struct { +type ClosestNodesIter[K kad.Key[K], A kad.Address[A]] struct { // target is the key whose distance to a node determines the position of that node in the iterator. target K // nodelist holds the nodes discovered so far, ordered by increasing distance from the target. - nodes *trie.Trie[K, *NodeStatus[K]] + nodes *trie.Trie[K, *NodeStatus[K, A]] } -var _ NodeIter[key.Key8] = (*ClosestNodesIter[key.Key8])(nil) +var _ NodeIter[key.Key8, kadtest.StrAddr] = (*ClosestNodesIter[key.Key8, kadtest.StrAddr])(nil) // NewClosestNodesIter creates a new ClosestNodesIter -func NewClosestNodesIter[K kad.Key[K]](target K) *ClosestNodesIter[K] { - return &ClosestNodesIter[K]{ +func NewClosestNodesIter[K kad.Key[K], A kad.Address[A]](target K) *ClosestNodesIter[K, A] { + return &ClosestNodesIter[K, A]{ target: target, - nodes: trie.New[K, *NodeStatus[K]](), + nodes: trie.New[K, *NodeStatus[K, A]](), } } -func (iter *ClosestNodesIter[K]) Add(ni *NodeStatus[K]) { - iter.nodes.Add(ni.NodeID.Key(), ni) +func (iter *ClosestNodesIter[K, A]) Add(ni *NodeStatus[K, A]) { + iter.nodes.Add(ni.Node.ID().Key(), ni) } -func (iter *ClosestNodesIter[K]) Find(k K) (*NodeStatus[K], bool) { +func (iter *ClosestNodesIter[K, A]) Find(k K) (*NodeStatus[K, A], bool) { found, ni := trie.Find(iter.nodes, k) return ni, found } -func (iter *ClosestNodesIter[K]) Each(ctx context.Context, fn func(context.Context, *NodeStatus[K]) bool) bool { +func (iter *ClosestNodesIter[K, A]) Each(ctx context.Context, fn func(context.Context, *NodeStatus[K, A]) bool) bool { // get all the nodes in order of distance from the target // TODO: turn this into a walk or iterator on trie.Trie entries := trie.Closest(iter.nodes, iter.target, iter.nodes.Size()) @@ -63,29 +65,29 @@ func (iter *ClosestNodesIter[K]) Each(ctx context.Context, fn func(context.Conte } // A SequentialIter iterates nodes in the order they were added to the iterator. -type SequentialIter[K kad.Key[K]] struct { +type SequentialIter[K kad.Key[K], A kad.Address[A]] struct { // nodelist holds the nodes discovered so far, ordered by increasing distance from the target. - nodes []*NodeStatus[K] + nodes []*NodeStatus[K, A] } -var _ NodeIter[key.Key8] = (*SequentialIter[key.Key8])(nil) +var _ NodeIter[key.Key8, kadtest.StrAddr] = (*SequentialIter[key.Key8, kadtest.StrAddr])(nil) // NewSequentialIter creates a new SequentialIter -func NewSequentialIter[K kad.Key[K]]() *SequentialIter[K] { - return &SequentialIter[K]{ - nodes: make([]*NodeStatus[K], 0), +func NewSequentialIter[K kad.Key[K], A kad.Address[A]]() *SequentialIter[K, A] { + return &SequentialIter[K, A]{ + nodes: make([]*NodeStatus[K, A], 0), } } -func (iter *SequentialIter[K]) Add(ni *NodeStatus[K]) { +func (iter *SequentialIter[K, A]) Add(ni *NodeStatus[K, A]) { iter.nodes = append(iter.nodes, ni) } // Find returns the node information corresponding to the given Kademlia key. It uses a linear // search which makes it unsuitable for large numbers of entries. -func (iter *SequentialIter[K]) Find(k K) (*NodeStatus[K], bool) { +func (iter *SequentialIter[K, A]) Find(k K) (*NodeStatus[K, A], bool) { for i := range iter.nodes { - if key.Equal(k, iter.nodes[i].NodeID.Key()) { + if key.Equal(k, iter.nodes[i].Node.ID().Key()) { return iter.nodes[i], true } } @@ -93,7 +95,7 @@ func (iter *SequentialIter[K]) Find(k K) (*NodeStatus[K], bool) { return nil, false } -func (iter *SequentialIter[K]) Each(ctx context.Context, fn func(context.Context, *NodeStatus[K]) bool) bool { +func (iter *SequentialIter[K, A]) Each(ctx context.Context, fn func(context.Context, *NodeStatus[K, A]) bool) bool { for _, ns := range iter.nodes { if fn(ctx, ns) { return true diff --git a/query/node.go b/query/node.go index 0fd5960..bf5a682 100644 --- a/query/node.go +++ b/query/node.go @@ -6,9 +6,9 @@ import ( "github.com/plprobelab/go-kademlia/kad" ) -type NodeStatus[K kad.Key[K]] struct { - NodeID kad.NodeID[K] - State NodeState +type NodeStatus[K kad.Key[K], A kad.Address[A]] struct { + Node kad.NodeInfo[K, A] + State NodeState } type NodeState interface { diff --git a/query/pool.go b/query/pool.go index 7e6a469..4f473e3 100644 --- a/query/pool.go +++ b/query/pool.go @@ -135,7 +135,7 @@ func (p *Pool[K, A]) Advance(ctx context.Context, ev PoolEvent) PoolState { case *EventPoolMessageResponse[K, A]: if qry, ok := p.queryIndex[tev.QueryID]; ok { state, terminal := p.advanceQuery(ctx, qry, &EventQueryMessageResponse[K, A]{ - NodeID: tev.NodeID, + Node: tev.Node, Response: tev.Response, }) if terminal { @@ -197,7 +197,7 @@ func (p *Pool[K, A]) advanceQuery(ctx context.Context, qry *Query[K, A], qev Que return &StatePoolQueryMessage[K, A]{ QueryID: st.QueryID, Stats: st.Stats, - NodeID: st.NodeID, + Node: st.Node, ProtocolID: st.ProtocolID, Message: st.Message, }, true @@ -247,18 +247,18 @@ func (p *Pool[K, A]) removeQuery(queryID QueryID) { // addQuery adds a query to the pool, returning the new query id // TODO: remove target argument and use msg.Target -func (p *Pool[K, A]) addQuery(ctx context.Context, queryID QueryID, target K, protocolID address.ProtocolID, msg kad.Request[K, A], knownClosestNodes []kad.NodeID[K]) error { +func (p *Pool[K, A]) addQuery(ctx context.Context, queryID QueryID, target K, protocolID address.ProtocolID, msg kad.Request[K, A], knownClosestNodes []kad.NodeInfo[K, A]) error { if _, exists := p.queryIndex[queryID]; exists { return fmt.Errorf("query id already in use") } - iter := NewClosestNodesIter(target) + iter := NewClosestNodesIter[K, A](target) qryCfg := DefaultQueryConfig[K]() qryCfg.Clock = p.cfg.Clock qryCfg.Concurrency = p.cfg.QueryConcurrency qryCfg.RequestTimeout = p.cfg.RequestTimeout - qry, err := NewQuery[K](p.self, queryID, protocolID, msg, iter, knownClosestNodes, qryCfg) + qry, err := NewQuery[K, A](p.self, queryID, protocolID, msg, iter, knownClosestNodes, qryCfg) if err != nil { return fmt.Errorf("new query: %w", err) } @@ -281,7 +281,7 @@ type StatePoolIdle struct{} // StatePoolQueryMessage indicates that a pool query is waiting to message a node. type StatePoolQueryMessage[K kad.Key[K], A kad.Address[A]] struct { QueryID QueryID - NodeID kad.NodeID[K] + Node kad.NodeInfo[K, A] ProtocolID address.ProtocolID Message kad.Request[K, A] Stats QueryStats @@ -322,11 +322,11 @@ type PoolEvent interface { // EventPoolAddQuery is an event that attempts to add a new query type EventPoolAddQuery[K kad.Key[K], A kad.Address[A]] struct { - QueryID QueryID // the id to use for the new query - Target K // the target key for the query - ProtocolID address.ProtocolID // the protocol that defines how the message should be interpreted - Message kad.Request[K, A] // the message the query should send to each node it traverses - KnownClosestNodes []kad.NodeID[K] // an initial set of close nodes the query should use + QueryID QueryID // the id to use for the new query + Target K // the target key for the query + ProtocolID address.ProtocolID // the protocol that defines how the message should be interpreted + Message kad.Request[K, A] // the message the query should send to each node it traverses + KnownClosestNodes []kad.NodeInfo[K, A] // an initial set of close nodes the query should use } // EventPoolStopQuery notifies a pool to stop a query. @@ -337,7 +337,7 @@ type EventPoolStopQuery struct { // EventPoolMessageResponse notifies a pool that a query that a sent message has received a successful response. type EventPoolMessageResponse[K kad.Key[K], A kad.Address[A]] struct { QueryID QueryID // the id of the query that sent the message - NodeID kad.NodeID[K] // the node the message was sent to + Node kad.NodeInfo[K, A] // the node the message was sent to Response kad.Response[K, A] // the message response sent by the node } diff --git a/query/query.go b/query/query.go index f637f21..7b50dc0 100644 --- a/query/query.go +++ b/query/query.go @@ -40,7 +40,7 @@ type StateQueryFinished struct { type StateQueryWaitingMessage[K kad.Key[K], A kad.Address[A]] struct { QueryID QueryID Stats QueryStats - NodeID kad.NodeID[K] + Node kad.NodeInfo[K, A] ProtocolID address.ProtocolID Message kad.Request[K, A] } @@ -72,7 +72,7 @@ type EventQueryCancel struct{} // EventQueryMessageResponse notifies a query that an attempt to send a message has received a successful response. type EventQueryMessageResponse[K kad.Key[K], A kad.Address[A]] struct { - NodeID kad.NodeID[K] // the node the message was sent to + Node kad.NodeInfo[K, A] // the node the message was sent to Response kad.Response[K, A] // the message response sent by the node } @@ -142,19 +142,19 @@ type Query[K kad.Key[K], A kad.Address[A]] struct { // cfg is a copy of the optional configuration supplied to the query cfg QueryConfig[K] - iter NodeIter[K] + iter NodeIter[K, A] protocolID address.ProtocolID msg kad.Request[K, A] stats QueryStats - // finished indicates that that the query has completed its work or has been stopped. + // finished indicates that the query has completed its work or has been stopped. finished bool // inFlight is number of requests in flight, will be <= concurrency inFlight int } -func NewQuery[K kad.Key[K], A kad.Address[A]](self kad.NodeID[K], id QueryID, protocolID address.ProtocolID, msg kad.Request[K, A], iter NodeIter[K], knownClosestNodes []kad.NodeID[K], cfg *QueryConfig[K]) (*Query[K, A], error) { +func NewQuery[K kad.Key[K], A kad.Address[A]](self kad.NodeID[K], id QueryID, protocolID address.ProtocolID, msg kad.Request[K, A], iter NodeIter[K, A], knownClosestNodes []kad.NodeInfo[K, A], cfg *QueryConfig[K]) (*Query[K, A], error) { if cfg == nil { cfg = DefaultQueryConfig[K]() } else if err := cfg.Validate(); err != nil { @@ -163,12 +163,13 @@ func NewQuery[K kad.Key[K], A kad.Address[A]](self kad.NodeID[K], id QueryID, pr for _, node := range knownClosestNodes { // exclude self from closest nodes - if key.Equal(node.Key(), self.Key()) { + if key.Equal(node.ID().Key(), self.Key()) { continue } - iter.Add(&NodeStatus[K]{ - NodeID: node, - State: &StateNodeNotContacted{}, + + iter.Add(&NodeStatus[K, A]{ + Node: node, + State: &StateNodeNotContacted{}, }) } @@ -200,7 +201,7 @@ func (q *Query[K, A]) Advance(ctx context.Context, ev QueryEvent) QueryState { Stats: q.stats, } case *EventQueryMessageResponse[K, A]: - q.onMessageResponse(ctx, tev.NodeID, tev.Response) + q.onMessageResponse(ctx, tev.Node, tev.Response) case *EventQueryMessageFailure[K]: q.onMessageFailure(ctx, tev.NodeID) case nil: @@ -225,7 +226,7 @@ func (q *Query[K, A]) Advance(ctx context.Context, ev QueryEvent) QueryState { var returnState QueryState - q.iter.Each(ctx, func(ctx context.Context, ni *NodeStatus[K]) bool { + q.iter.Each(ctx, func(ctx context.Context, ni *NodeStatus[K, A]) bool { switch st := ni.State.(type) { case *StateNodeWaiting: if q.cfg.Clock.Now().After(st.Deadline) { @@ -267,7 +268,7 @@ func (q *Query[K, A]) Advance(ctx context.Context, ev QueryEvent) QueryState { q.stats.Start = q.cfg.Clock.Now() } returnState = &StateQueryWaitingMessage[K, A]{ - NodeID: ni.NodeID, + Node: ni.Node, QueryID: q.id, Stats: q.stats, ProtocolID: q.protocolID, @@ -321,8 +322,8 @@ func (q *Query[K, A]) markFinished() { } // onMessageResponse processes the result of a successful response received from a node. -func (q *Query[K, A]) onMessageResponse(ctx context.Context, node kad.NodeID[K], resp kad.Response[K, A]) { - ni, found := q.iter.Find(node.Key()) +func (q *Query[K, A]) onMessageResponse(ctx context.Context, node kad.NodeInfo[K, A], resp kad.Response[K, A]) { + ni, found := q.iter.Find(node.ID().Key()) if !found { // got a rogue message return @@ -354,9 +355,9 @@ func (q *Query[K, A]) onMessageResponse(ctx context.Context, node kad.NodeID[K], if key.Equal(info.ID().Key(), q.self.Key()) { continue } - q.iter.Add(&NodeStatus[K]{ - NodeID: info.ID(), - State: &StateNodeNotContacted{}, + q.iter.Add(&NodeStatus[K, A]{ + Node: info, + State: &StateNodeNotContacted{}, }) } } diff --git a/routing/bootstrap.go b/routing/bootstrap.go index 96e0a4d..a9c8cb1 100644 --- a/routing/bootstrap.go +++ b/routing/bootstrap.go @@ -99,7 +99,7 @@ func (b *Bootstrap[K, A]) Advance(ctx context.Context, ev BootstrapEvent) Bootst case *EventBootstrapStart[K, A]: // TODO: ignore start event if query is already in progress - iter := query.NewClosestNodesIter(b.self.Key()) + iter := query.NewClosestNodesIter[K, A](b.self.Key()) qryCfg := query.DefaultQueryConfig[K]() qryCfg.Clock = b.cfg.Clock @@ -108,7 +108,7 @@ func (b *Bootstrap[K, A]) Advance(ctx context.Context, ev BootstrapEvent) Bootst queryID := query.QueryID("bootstrap") - qry, err := query.NewQuery[K](b.self, queryID, tev.ProtocolID, tev.Message, iter, tev.KnownClosestNodes, qryCfg) + qry, err := query.NewQuery[K, A](b.self, queryID, tev.ProtocolID, tev.Message, iter, tev.KnownClosestNodes, qryCfg) if err != nil { // TODO: don't panic panic(err) @@ -118,7 +118,7 @@ func (b *Bootstrap[K, A]) Advance(ctx context.Context, ev BootstrapEvent) Bootst case *EventBootstrapMessageResponse[K, A]: return b.advanceQuery(ctx, &query.EventQueryMessageResponse[K, A]{ - NodeID: tev.NodeID, + Node: tev.Node, Response: tev.Response, }) case *EventBootstrapMessageFailure[K]: @@ -147,7 +147,7 @@ func (b *Bootstrap[K, A]) advanceQuery(ctx context.Context, qev query.QueryEvent return &StateBootstrapMessage[K, A]{ QueryID: st.QueryID, Stats: st.Stats, - NodeID: st.NodeID, + Node: st.Node, ProtocolID: st.ProtocolID, Message: st.Message, } @@ -188,7 +188,7 @@ type BootstrapState interface { // StateBootstrapMessage indicates that the bootstrap query is waiting to message a node. type StateBootstrapMessage[K kad.Key[K], A kad.Address[A]] struct { QueryID query.QueryID - NodeID kad.NodeID[K] + Node kad.NodeInfo[K, A] ProtocolID address.ProtocolID Message kad.Request[K, A] Stats query.QueryStats @@ -231,12 +231,12 @@ type EventBootstrapPoll struct{} type EventBootstrapStart[K kad.Key[K], A kad.Address[A]] struct { ProtocolID address.ProtocolID Message kad.Request[K, A] - KnownClosestNodes []kad.NodeID[K] + KnownClosestNodes []kad.NodeInfo[K, A] } // EventBootstrapMessageResponse notifies a bootstrap that a sent message has received a successful response. type EventBootstrapMessageResponse[K kad.Key[K], A kad.Address[A]] struct { - NodeID kad.NodeID[K] // the node the message was sent to + Node kad.NodeInfo[K, A] // the node the message was sent to Response kad.Response[K, A] // the message response sent by the node }