From 87dadb9ae08d0c7d6be9f2c2e54e91718d225e03 Mon Sep 17 00:00:00 2001 From: zhiqiangxu <652732310@qq.com> Date: Fri, 21 Oct 2022 12:22:51 +0800 Subject: [PATCH 1/2] fix nodesByDistance.push --- p2p/discover/table.go | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/p2p/discover/table.go b/p2p/discover/table.go index d08f8a6c69cb..5b79ae4fde67 100644 --- a/p2p/discover/table.go +++ b/p2p/discover/table.go @@ -672,16 +672,23 @@ func (h *nodesByDistance) push(n *node, maxElems int) { ix := sort.Search(len(h.entries), func(i int) bool { return enode.DistCmp(h.target, h.entries[i].ID(), n.ID()) > 0 }) - if len(h.entries) < maxElems { - h.entries = append(h.entries, n) - } + if ix == len(h.entries) { // farther away than all nodes we already have. - // if there was room for it, the node is now the last element. + if len(h.entries) < maxElems { + h.entries = append(h.entries, n) + } } else { // slide existing entries down to make room - // this will overwrite the entry we just appended. + // note here len(h.entries) is guaranteed > 0 + var last *node + if len(h.entries) < maxElems { + last = h.entries[len(h.entries)-1] + } copy(h.entries[ix+1:], h.entries[ix:]) h.entries[ix] = n + if last != nil { + h.entries = append(h.entries, n) + } } } From 2484548292766415f79d2236b623d5140fbfb5d1 Mon Sep 17 00:00:00 2001 From: Felix Lange Date: Wed, 7 Dec 2022 21:32:38 +0100 Subject: [PATCH 2/2] p2p/discover: update & add test --- p2p/discover/table.go | 22 +++++----------- p2p/discover/table_test.go | 53 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 60 insertions(+), 15 deletions(-) diff --git a/p2p/discover/table.go b/p2p/discover/table.go index 5b79ae4fde67..41d5ac6e34e7 100644 --- a/p2p/discover/table.go +++ b/p2p/discover/table.go @@ -673,22 +673,14 @@ func (h *nodesByDistance) push(n *node, maxElems int) { return enode.DistCmp(h.target, h.entries[i].ID(), n.ID()) > 0 }) - if ix == len(h.entries) { - // farther away than all nodes we already have. - if len(h.entries) < maxElems { - h.entries = append(h.entries, n) - } - } else { - // slide existing entries down to make room - // note here len(h.entries) is guaranteed > 0 - var last *node - if len(h.entries) < maxElems { - last = h.entries[len(h.entries)-1] - } + end := len(h.entries) + if len(h.entries) < maxElems { + h.entries = append(h.entries, n) + } + if ix < end { + // Slide existing entries down to make room. + // This will overwrite the entry we just appended. copy(h.entries[ix+1:], h.entries[ix:]) h.entries[ix] = n - if last != nil { - h.entries = append(h.entries, n) - } } } diff --git a/p2p/discover/table_test.go b/p2p/discover/table_test.go index 5f40c967fd5b..1ef63fe01019 100644 --- a/p2p/discover/table_test.go +++ b/p2p/discover/table_test.go @@ -396,6 +396,59 @@ func TestTable_revalidateSyncRecord(t *testing.T) { } } +func TestNodesPush(t *testing.T) { + var target enode.ID + n1 := nodeAtDistance(target, 255, intIP(1)) + n2 := nodeAtDistance(target, 254, intIP(2)) + n3 := nodeAtDistance(target, 253, intIP(3)) + perm := [][]*node{ + {n3, n2, n1}, + {n3, n1, n2}, + {n2, n3, n1}, + {n2, n1, n3}, + {n1, n3, n2}, + {n1, n2, n3}, + } + + // Insert all permutations into lists with size limit 3. + for _, nodes := range perm { + list := nodesByDistance{target: target} + for _, n := range nodes { + list.push(n, 3) + } + if !slicesEqual(list.entries, perm[0], nodeIDEqual) { + t.Fatal("not equal") + } + } + + // Insert all permutations into lists with size limit 2. + for _, nodes := range perm { + list := nodesByDistance{target: target} + for _, n := range nodes { + list.push(n, 2) + } + if !slicesEqual(list.entries, perm[0][:2], nodeIDEqual) { + t.Fatal("not equal") + } + } +} + +func nodeIDEqual(n1, n2 *node) bool { + return n1.ID() == n2.ID() +} + +func slicesEqual[T any](s1, s2 []T, check func(e1, e2 T) bool) bool { + if len(s1) != len(s2) { + return false + } + for i := range s1 { + if !check(s1[i], s2[i]) { + return false + } + } + return true +} + // gen wraps quick.Value so it's easier to use. // it generates a random value of the given value's type. func gen(typ interface{}, rand *rand.Rand) interface{} {