mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-19 18:32:23 +00:00
p2p/discover: be more strict about sequence updates
This commit is contained in:
parent
7afcb398e5
commit
413bdb02c2
3 changed files with 27 additions and 23 deletions
|
|
@ -513,16 +513,9 @@ func (tab *Table) handleAddNode(req addNodeOp) bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
b := tab.bucket(req.node.ID())
|
b := tab.bucket(req.node.ID())
|
||||||
if !req.isInbound && req.node.Seq() == 0 && contains(b.entries, req.node.ID()) {
|
exists, _ := tab.bumpInBucket(b, req.node.Node, req.isInbound)
|
||||||
// Special case for discv4: because endpoint information is not
|
if exists {
|
||||||
// authenticated, do not update until the node is successfully communicated
|
// Already in bucket.
|
||||||
// with. Therefore, non-inbounds which are already in the bucket should be
|
|
||||||
// skipped.
|
|
||||||
return false
|
|
||||||
|
|
||||||
}
|
|
||||||
if tab.bumpInBucket(b, req.node.Node) {
|
|
||||||
// Already in bucket, update record.
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
if len(b.entries) >= bucketSize {
|
if len(b.entries) >= bucketSize {
|
||||||
|
|
@ -613,26 +606,37 @@ func (tab *Table) deleteInBucket(b *bucket, id enode.ID) *node {
|
||||||
return rep
|
return rep
|
||||||
}
|
}
|
||||||
|
|
||||||
// bumpInBucket updates the node record of n in the bucket.
|
// bumpInBucket updates a node record if it exists in the bucket.
|
||||||
func (tab *Table) bumpInBucket(b *bucket, newRecord *enode.Node) bool {
|
func (tab *Table) bumpInBucket(b *bucket, newRecord *enode.Node, isInbound bool) (exists, updated bool) {
|
||||||
i := slices.IndexFunc(b.entries, func(elem *node) bool {
|
i := slices.IndexFunc(b.entries, func(elem *node) bool {
|
||||||
return elem.ID() == newRecord.ID()
|
return elem.ID() == newRecord.ID()
|
||||||
})
|
})
|
||||||
if i == -1 {
|
if i == -1 {
|
||||||
return false
|
return false, false // node not in bucket
|
||||||
}
|
}
|
||||||
|
|
||||||
if !newRecord.IP().Equal(b.entries[i].IP()) {
|
// Disallow updates unless the sequence number is increased.
|
||||||
// Endpoint has changed, ensure that the new IP fits into table limits.
|
// Note there is a special case for discv4: if the node contacts us (isInbound),
|
||||||
tab.removeIP(b, b.entries[i].IP())
|
// it is allowed to update its own entry.
|
||||||
|
oldRecord := b.entries[i]
|
||||||
|
isUpdate := newRecord.Seq() > oldRecord.Seq()
|
||||||
|
isDiscv4Update := oldRecord.Seq() == 0 && newRecord.Seq() == 0 && isInbound
|
||||||
|
if !(isUpdate || isDiscv4Update) {
|
||||||
|
return true, false
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if there is an endpoint update and validate against IP limits.
|
||||||
|
if newRecord.IPAddr() != b.entries[i].IPAddr() {
|
||||||
|
tab.removeIP(b, oldRecord.IP())
|
||||||
if !tab.addIP(b, newRecord.IP()) {
|
if !tab.addIP(b, newRecord.IP()) {
|
||||||
// It doesn't, put the previous one back.
|
// It doesn't fit with the limit, put the previous record back.
|
||||||
tab.addIP(b, b.entries[i].IP())
|
tab.addIP(b, oldRecord.IP())
|
||||||
return false
|
return true, false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
b.entries[i].Node = newRecord
|
b.entries[i].Node = newRecord
|
||||||
return true
|
return true, true
|
||||||
}
|
}
|
||||||
|
|
||||||
func (tab *Table) handleTrackRequest(op trackRequestOp) {
|
func (tab *Table) handleTrackRequest(op trackRequestOp) {
|
||||||
|
|
|
||||||
|
|
@ -161,7 +161,7 @@ func (tr *tableRevalidation) handleResponse(tab *Table, resp revalidationRespons
|
||||||
n.isValidatedLive = true
|
n.isValidatedLive = true
|
||||||
var endpointChanged bool
|
var endpointChanged bool
|
||||||
if resp.newRecord != nil {
|
if resp.newRecord != nil {
|
||||||
endpointChanged = tab.bumpInBucket(b, resp.newRecord)
|
_, endpointChanged = tab.bumpInBucket(b, resp.newRecord, false)
|
||||||
if endpointChanged {
|
if endpointChanged {
|
||||||
// If the node changed its advertised endpoint, the updated ENR is not served
|
// If the node changed its advertised endpoint, the updated ENR is not served
|
||||||
// until it has been revalidated.
|
// until it has been revalidated.
|
||||||
|
|
|
||||||
|
|
@ -275,7 +275,7 @@ func (*closeTest) Generate(rand *rand.Rand, size int) reflect.Value {
|
||||||
return reflect.ValueOf(t)
|
return reflect.ValueOf(t)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestTable_addVerifiedNode(t *testing.T) {
|
func TestTable_addInboundNode(t *testing.T) {
|
||||||
tab, db := newTestTable(newPingRecorder(), Config{})
|
tab, db := newTestTable(newPingRecorder(), Config{})
|
||||||
<-tab.initDone
|
<-tab.initDone
|
||||||
defer db.Close()
|
defer db.Close()
|
||||||
|
|
@ -308,7 +308,7 @@ func TestTable_addVerifiedNode(t *testing.T) {
|
||||||
checkIPLimitInvariant(t, tab)
|
checkIPLimitInvariant(t, tab)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestTable_addSeenNode(t *testing.T) {
|
func TestTable_addFoundNode(t *testing.T) {
|
||||||
tab, db := newTestTable(newPingRecorder(), Config{})
|
tab, db := newTestTable(newPingRecorder(), Config{})
|
||||||
<-tab.initDone
|
<-tab.initDone
|
||||||
defer db.Close()
|
defer db.Close()
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue