Skip to content

Commit f014d4e

Browse files
Merge pull request BurntSushi#1 from libp2p/fix/bootstrapping
Fix bootstrapping id generation logic
2 parents 4c093b4 + 922f2ae commit f014d4e

File tree

3 files changed

+19
-97
lines changed

3 files changed

+19
-97
lines changed

table.go

+19-48
Original file line numberDiff line numberDiff line change
@@ -76,61 +76,32 @@ func (rt *RoutingTable) GenRandPeerID(bucketID int) (peer.ID, error) {
7676
bucketLen := len(rt.Buckets)
7777
rt.tabLock.RUnlock()
7878

79-
var targetCpl int
80-
if bucketID >= bucketLen-1 {
81-
targetCpl = bucketLen
79+
var targetCpl uint
80+
if bucketID > (bucketLen - 1) {
81+
targetCpl = uint(bucketLen) - 1
8282
} else {
83-
targetCpl = bucketID
83+
targetCpl = uint(bucketID)
8484
}
8585

86-
// generate random 16 bits
87-
r := rand.New(rand.NewSource(time.Now().UnixNano()))
88-
buf := make([]byte, 2)
89-
_, err := r.Read(buf)
90-
if err != nil {
91-
return "", err
86+
// We can only handle 16 bit prefixes.
87+
if targetCpl > 16 {
88+
targetCpl = 16
9289
}
9390

94-
// replace the first targetCPL bits with those from the hashed local peer ID & toggle the (targetCpl+1)th bit
95-
// so that exactly targetCpl bits match
96-
numBytes := targetCpl / 8 // number of bytes we need to replace
97-
numBits := targetCpl % 8 // number of bits we need to replace after numBytes have been replaced
91+
// Extract the local prefix and a random prefix.
92+
localPrefix := binary.BigEndian.Uint16(rt.local)
93+
randPrefix := uint16(rand.Uint32())
9894

99-
// replace the bytes
100-
byteIndex := 0
101-
for ; byteIndex < numBytes; byteIndex++ {
102-
buf[byteIndex] = rt.local[byteIndex]
103-
}
104-
105-
// replace the bits
106-
if byteIndex < len(buf) {
107-
dstByte := buf[byteIndex]
108-
srcByte := rt.local[byteIndex]
109-
j := uint(7)
110-
for k := 1; k <= numBits; k++ {
111-
if isSet(srcByte, j) {
112-
dstByte = setBit(dstByte, j)
113-
} else {
114-
dstByte = clearBit(dstByte, j)
115-
}
116-
j--
117-
}
118-
119-
// toggle the next bit
120-
if isSet(srcByte, j) {
121-
dstByte = clearBit(dstByte, j)
122-
} else {
123-
dstByte = setBit(dstByte, j)
124-
}
125-
buf[byteIndex] = dstByte
126-
}
95+
// Combine the local prefix and the random bits at the correct offset
96+
// such that the first `bucketID` bits match the local ID.
97+
mask := (^uint16(0)) << targetCpl
98+
targetPrefix := (localPrefix & mask) | (randPrefix & ^mask)
12799

128-
// get the seed using buf & use it as the hash digest for a SHA2-256 Multihash to get the desired peer ID
129-
prefix := binary.BigEndian.Uint16(buf)
130-
key := keyPrefixMap[prefix]
131-
h := [34]byte{mh.SHA2_256, 32}
132-
binary.BigEndian.PutUint64(h[2:], key)
133-
return peer.ID(h[:]), err
100+
// Convert to a known peer ID.
101+
key := keyPrefixMap[targetPrefix]
102+
id := [34]byte{mh.SHA2_256, 32}
103+
binary.BigEndian.PutUint64(id[2:], key)
104+
return peer.ID(id[:]), nil
134105
}
135106

136107
// Returns the bucket for a given peer

util.go

-16
Original file line numberDiff line numberDiff line change
@@ -35,22 +35,6 @@ func xor(a, b ID) ID {
3535
return ID(u.XOR(a, b))
3636
}
3737

38-
func setBit(n byte, pos uint) byte {
39-
n |= (1 << pos)
40-
return n
41-
}
42-
43-
func clearBit(n byte, pos uint) byte {
44-
mask := byte(^(1 << pos))
45-
n &= mask
46-
return n
47-
}
48-
49-
func isSet(n byte, pos uint) bool {
50-
val := n & (1 << pos)
51-
return (val > 0)
52-
}
53-
5438
func CommonPrefixLen(a, b ID) int {
5539
return ks.ZeroPrefixLen(u.XOR(a, b))
5640
}

util_test.go

-33
This file was deleted.

0 commit comments

Comments
 (0)