github.com/onflow/flow-go@v0.35.7-crescendo-preview.23-atree-inlining/network/p2p/node/disallow_listing_test.go (about) 1 package p2pnode_test 2 3 import ( 4 "context" 5 "testing" 6 "time" 7 8 "github.com/libp2p/go-libp2p/core/peer" 9 10 "github.com/onflow/flow-go/model/flow" 11 "github.com/onflow/flow-go/module/irrecoverable" 12 mockmodule "github.com/onflow/flow-go/module/mock" 13 "github.com/onflow/flow-go/network" 14 "github.com/onflow/flow-go/network/p2p" 15 p2pbuilderconfig "github.com/onflow/flow-go/network/p2p/builder/config" 16 "github.com/onflow/flow-go/network/p2p/connection" 17 p2ptest "github.com/onflow/flow-go/network/p2p/test" 18 "github.com/onflow/flow-go/utils/unittest" 19 ) 20 21 // TestDisconnectingFromDisallowListedNode ensures that: 22 // (1) the node disconnects from a disallow listed node while the node is connected to other (allow listed) nodes. 23 // (2) new inbound or outbound connections to and from disallow-listed nodes are rejected. 24 // (3) When a disallow-listed node is allow-listed again, the node reconnects to it. 25 func TestDisconnectingFromDisallowListedNode(t *testing.T) { 26 ctx, cancel := context.WithCancel(context.Background()) 27 signalerCtx := irrecoverable.NewMockSignalerContext(t, ctx) 28 29 sporkID := unittest.IdentifierFixture() 30 idProvider := mockmodule.NewIdentityProvider(t) 31 32 peerIDSlice := peer.IDSlice{} 33 // node 1 is the node that will be disallow-listing another node (node 2). 34 node1, identity1 := p2ptest.NodeFixture(t, 35 sporkID, 36 t.Name(), 37 idProvider, 38 p2ptest.WithPeerManagerEnabled(&p2pbuilderconfig.PeerManagerConfig{ 39 ConnectionPruning: true, 40 UpdateInterval: connection.DefaultPeerUpdateInterval, 41 ConnectorFactory: connection.DefaultLibp2pBackoffConnectorFactory(), 42 }, 43 func() peer.IDSlice { 44 return peerIDSlice 45 }), 46 p2ptest.WithConnectionGater(p2ptest.NewConnectionGater(idProvider, func(p peer.ID) error { 47 // allow all the connections, except for the ones that are disallow-listed, which are determined when 48 // this connection gater object queries the disallow listing oracle that will be provided to it by 49 // the libp2p node. So, here, we don't need to do anything except just enabling the connection gater. 50 return nil 51 }))) 52 idProvider.On("ByPeerID", node1.ID()).Return(&identity1, true).Maybe() 53 peerIDSlice = append(peerIDSlice, node1.ID()) 54 55 // node 2 is the node that will be disallow-listed by node 1. 56 node2, identity2 := p2ptest.NodeFixture(t, sporkID, t.Name(), idProvider) 57 idProvider.On("ByPeerID", node2.ID()).Return(&identity2, true).Maybe() 58 peerIDSlice = append(peerIDSlice, node2.ID()) 59 60 // node 3 is the node that will be connected to node 1 (to ensure that node 1 is still able to connect to other nodes 61 // after disallow-listing node 2). 62 node3, identity3 := p2ptest.NodeFixture(t, sporkID, t.Name(), idProvider) 63 idProvider.On("ByPeerID", node3.ID()).Return(&identity3, true).Maybe() 64 peerIDSlice = append(peerIDSlice, node3.ID()) 65 66 nodes := []p2p.LibP2PNode{node1, node2, node3} 67 ids := flow.IdentityList{&identity1, &identity2, &identity3} 68 69 p2ptest.StartNodes(t, signalerCtx, nodes) 70 defer p2ptest.StopNodes(t, nodes, cancel) 71 72 p2ptest.LetNodesDiscoverEachOther(t, ctx, nodes, ids) 73 74 // initially all nodes should be connected to each other. 75 p2ptest.RequireConnectedEventually(t, nodes, 100*time.Millisecond, 2*time.Second) 76 77 // phase-1: node 1 disallow-lists node 2. 78 node1.OnDisallowListNotification(node2.ID(), network.DisallowListedCauseAlsp) 79 80 // eventually node 1 should be disconnected from node 2 while other nodes should remain connected. 81 // we choose a timeout of 2 seconds because peer manager updates peers every 1 second. 82 p2ptest.RequireEventuallyNotConnected(t, []p2p.LibP2PNode{node1}, []p2p.LibP2PNode{node2}, 100*time.Millisecond, 2*time.Second) 83 84 // but nodes 1 and 3 should remain connected as well as nodes 2 and 3. 85 // we choose a short timeout because we expect the nodes to remain connected. 86 p2ptest.RequireConnectedEventually(t, []p2p.LibP2PNode{node1, node3}, 1*time.Millisecond, 100*time.Millisecond) 87 p2ptest.RequireConnectedEventually(t, []p2p.LibP2PNode{node2, node3}, 1*time.Millisecond, 100*time.Millisecond) 88 89 // while node 2 is disallow-listed, it cannot connect to node 1. Also, node 1 cannot directly dial and connect to node 2, unless 90 // it is allow-listed again. 91 p2ptest.EnsureNotConnectedBetweenGroups(t, ctx, []p2p.LibP2PNode{node1}, []p2p.LibP2PNode{node2}) 92 93 // phase-2: now we allow-list node 1 back 94 node1.OnAllowListNotification(node2.ID(), network.DisallowListedCauseAlsp) 95 96 // eventually node 1 should be connected to node 2 again, hence all nodes should be connected to each other. 97 // we choose a timeout of 5 seconds because peer manager updates peers every 1 second and we need to wait for 98 // any potential random backoffs to expire (min 1 second). 99 p2ptest.RequireConnectedEventually(t, nodes, 100*time.Millisecond, 5*time.Second) 100 }