package kademlia // TODO: Tests const ( threshold = 10 bucketSize = 20 ) // RoutingTableNode interface implemented by both InnerNode and Leaf type RoutingTableNode interface { isNode() findClosest(id [32]byte, numberOfNodes int) []P2PNode insert(node P2PNode) RoutingTableNode } type Leaf struct { bucket []P2PNode hostClientNode P2PNode depth uint64 maxDepth uint64 prefixLen uint64 } // IsNode ensures Leaf and InnerNode implement RoutingTableNode func (i *InnerNode) isNode() {} func (l *Leaf) isNode() {} type RoutingTable struct { root RoutingTableNode hostClientNode P2PNode matchedPrefixLength uint64 } func NewRoutingTable(clientNode P2PNode, matchedPrefixLength uint64) *RoutingTable { return &RoutingTable{ root: &Leaf{bucket: make([]P2PNode, 0), depth: 0, maxDepth: 256, prefixLen: matchedPrefixLength, hostClientNode: clientNode}, hostClientNode: clientNode, matchedPrefixLength: matchedPrefixLength, } } type InnerNode struct { branches []RoutingTableNode hostClientNode P2PNode depth uint64 prefixLength uint64 } // FindClosest Return a list of nodes in the routing table closest to the provided ID func (r *RoutingTable) FindClosest(targetID [32]byte, numberOfNodes int) *[]P2PNode { ret := r.root.findClosest(targetID, numberOfNodes) return &ret } func (i *InnerNode) findClosest(id [32]byte, numberOfNodes int) []P2PNode { distance := uint64(0) result := make([]P2PNode, 0) // go through the buckets in increasing distance from the key until sufficiently many nodes were found for distance < 1< threshold && getBitsAt(node.NodeID, 0, l.depth) == getBitsAt(l.hostClientNode.NodeID, 0, l.depth) { branches := make([]RoutingTableNode, 1<