github.com/ethereum/go-ethereum@v1.16.1/p2p/discover/table_reval_test.go (about)

     1  // Copyright 2024 The go-ethereum Authors
     2  // This file is part of the go-ethereum library.
     3  //
     4  // The go-ethereum library is free software: you can redistribute it and/or modify
     5  // it under the terms of the GNU Lesser General Public License as published by
     6  // the Free Software Foundation, either version 3 of the License, or
     7  // (at your option) any later version.
     8  //
     9  // The go-ethereum library is distributed in the hope that it will be useful,
    10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    12  // GNU Lesser General Public License for more details.
    13  //
    14  // You should have received a copy of the GNU Lesser General Public License
    15  // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  package discover
    18  
    19  import (
    20  	"net"
    21  	"testing"
    22  	"time"
    23  
    24  	"github.com/ethereum/go-ethereum/common/mclock"
    25  	"github.com/ethereum/go-ethereum/p2p/enode"
    26  	"github.com/ethereum/go-ethereum/p2p/enr"
    27  )
    28  
    29  // This test checks that revalidation can handle a node disappearing while
    30  // a request is active.
    31  func TestRevalidation_nodeRemoved(t *testing.T) {
    32  	var (
    33  		clock     mclock.Simulated
    34  		transport = newPingRecorder()
    35  		tab, db   = newInactiveTestTable(transport, Config{Clock: &clock})
    36  		tr        = &tab.revalidation
    37  	)
    38  	defer db.Close()
    39  
    40  	// Add a node to the table.
    41  	node := nodeAtDistance(tab.self().ID(), 255, net.IP{77, 88, 99, 1})
    42  	tab.handleAddNode(addNodeOp{node: node})
    43  
    44  	// Start a revalidation request. Schedule once to get the next start time,
    45  	// then advance the clock to that point and schedule again to start.
    46  	next := tr.run(tab, clock.Now())
    47  	clock.Run(time.Duration(next + 1))
    48  	tr.run(tab, clock.Now())
    49  	if len(tr.activeReq) != 1 {
    50  		t.Fatal("revalidation request did not start:", tr.activeReq)
    51  	}
    52  
    53  	// Delete the node.
    54  	tab.deleteInBucket(tab.bucket(node.ID()), node.ID())
    55  
    56  	// Now finish the revalidation request.
    57  	var resp revalidationResponse
    58  	select {
    59  	case resp = <-tab.revalResponseCh:
    60  	case <-time.After(1 * time.Second):
    61  		t.Fatal("timed out waiting for revalidation")
    62  	}
    63  	tr.handleResponse(tab, resp)
    64  
    65  	// Ensure the node was not re-added to the table.
    66  	if tab.getNode(node.ID()) != nil {
    67  		t.Fatal("node was re-added to Table")
    68  	}
    69  	if tr.fast.contains(node.ID()) || tr.slow.contains(node.ID()) {
    70  		t.Fatal("removed node contained in revalidation list")
    71  	}
    72  }
    73  
    74  // This test checks that nodes with an updated endpoint remain in the fast revalidation list.
    75  func TestRevalidation_endpointUpdate(t *testing.T) {
    76  	var (
    77  		clock     mclock.Simulated
    78  		transport = newPingRecorder()
    79  		tab, db   = newInactiveTestTable(transport, Config{Clock: &clock})
    80  		tr        = &tab.revalidation
    81  	)
    82  	defer db.Close()
    83  
    84  	// Add node to table.
    85  	node := nodeAtDistance(tab.self().ID(), 255, net.IP{77, 88, 99, 1})
    86  	tab.handleAddNode(addNodeOp{node: node})
    87  
    88  	// Update the record in transport, including endpoint update.
    89  	record := node.Record()
    90  	record.Set(enr.IP{100, 100, 100, 100})
    91  	record.Set(enr.UDP(9999))
    92  	nodev2 := enode.SignNull(record, node.ID())
    93  	transport.updateRecord(nodev2)
    94  
    95  	// Start a revalidation request. Schedule once to get the next start time,
    96  	// then advance the clock to that point and schedule again to start.
    97  	next := tr.run(tab, clock.Now())
    98  	clock.Run(time.Duration(next + 1))
    99  	tr.run(tab, clock.Now())
   100  	if len(tr.activeReq) != 1 {
   101  		t.Fatal("revalidation request did not start:", tr.activeReq)
   102  	}
   103  
   104  	// Now finish the revalidation request.
   105  	var resp revalidationResponse
   106  	select {
   107  	case resp = <-tab.revalResponseCh:
   108  	case <-time.After(1 * time.Second):
   109  		t.Fatal("timed out waiting for revalidation")
   110  	}
   111  	tr.handleResponse(tab, resp)
   112  
   113  	if tr.fast.nodes[0].ID() != node.ID() {
   114  		t.Fatal("node not contained in fast revalidation list")
   115  	}
   116  	if tr.fast.nodes[0].isValidatedLive {
   117  		t.Fatal("node is marked live after endpoint change")
   118  	}
   119  }