github.com/gnolang/gno@v0.0.0-20240520182011-228e9d0192ce/tm2/pkg/p2p/peer_test.go (about) 1 package p2p 2 3 import ( 4 "fmt" 5 golog "log" 6 "net" 7 "testing" 8 "time" 9 10 "github.com/stretchr/testify/assert" 11 "github.com/stretchr/testify/require" 12 13 "github.com/gnolang/gno/tm2/pkg/crypto" 14 "github.com/gnolang/gno/tm2/pkg/crypto/ed25519" 15 "github.com/gnolang/gno/tm2/pkg/errors" 16 "github.com/gnolang/gno/tm2/pkg/log" 17 "github.com/gnolang/gno/tm2/pkg/p2p/config" 18 "github.com/gnolang/gno/tm2/pkg/p2p/conn" 19 ) 20 21 func TestPeerBasic(t *testing.T) { 22 t.Parallel() 23 24 assert, require := assert.New(t), require.New(t) 25 26 // simulate remote peer 27 rp := &remotePeer{PrivKey: ed25519.GenPrivKey(), Config: cfg} 28 rp.Start() 29 defer rp.Stop() 30 31 p, err := createOutboundPeerAndPerformHandshake(t, rp.Addr(), cfg, conn.DefaultMConnConfig()) 32 require.Nil(err) 33 34 err = p.Start() 35 require.Nil(err) 36 defer p.Stop() 37 38 assert.True(p.IsRunning()) 39 assert.True(p.IsOutbound()) 40 assert.False(p.IsPersistent()) 41 p.persistent = true 42 assert.True(p.IsPersistent()) 43 assert.Equal(rp.Addr().DialString(), p.RemoteAddr().String()) 44 assert.Equal(rp.ID(), p.ID()) 45 } 46 47 func TestPeerSend(t *testing.T) { 48 t.Parallel() 49 50 assert, require := assert.New(t), require.New(t) 51 52 config := cfg 53 54 // simulate remote peer 55 rp := &remotePeer{PrivKey: ed25519.GenPrivKey(), Config: config} 56 rp.Start() 57 defer rp.Stop() 58 59 p, err := createOutboundPeerAndPerformHandshake(t, rp.Addr(), config, conn.DefaultMConnConfig()) 60 require.Nil(err) 61 62 err = p.Start() 63 require.Nil(err) 64 65 defer p.Stop() 66 67 assert.True(p.CanSend(testCh)) 68 assert.True(p.Send(testCh, []byte("Asylum"))) 69 } 70 71 func createOutboundPeerAndPerformHandshake( 72 t *testing.T, 73 addr *NetAddress, 74 config *config.P2PConfig, 75 mConfig conn.MConnConfig, 76 ) (*peer, error) { 77 t.Helper() 78 79 chDescs := []*conn.ChannelDescriptor{ 80 {ID: testCh, Priority: 1}, 81 } 82 reactorsByCh := map[byte]Reactor{testCh: NewTestReactor(chDescs, true)} 83 pk := ed25519.GenPrivKey() 84 pc, err := testOutboundPeerConn(addr, config, false, pk) 85 if err != nil { 86 return nil, err 87 } 88 timeout := 1 * time.Second 89 ourNodeInfo := testNodeInfo(addr.ID, "host_peer") 90 peerNodeInfo, err := handshake(pc.conn, timeout, ourNodeInfo) 91 if err != nil { 92 return nil, err 93 } 94 95 p := newPeer(pc, mConfig, peerNodeInfo, reactorsByCh, chDescs, func(p Peer, r interface{}) {}) 96 p.SetLogger(log.NewTestingLogger(t).With("peer", addr)) 97 return p, nil 98 } 99 100 func testDial(addr *NetAddress, cfg *config.P2PConfig) (net.Conn, error) { 101 if cfg.TestDialFail { 102 return nil, fmt.Errorf("dial err (peerConfig.DialFail == true)") 103 } 104 105 conn, err := addr.DialTimeout(cfg.DialTimeout) 106 if err != nil { 107 return nil, err 108 } 109 return conn, nil 110 } 111 112 func testOutboundPeerConn( 113 addr *NetAddress, 114 config *config.P2PConfig, 115 persistent bool, 116 ourNodePrivKey crypto.PrivKey, 117 ) (peerConn, error) { 118 var pc peerConn 119 conn, err := testDial(addr, config) 120 if err != nil { 121 return pc, errors.Wrap(err, "Error creating peer") 122 } 123 124 pc, err = testPeerConn(conn, config, true, persistent, ourNodePrivKey, addr) 125 if err != nil { 126 if cerr := conn.Close(); cerr != nil { 127 return pc, errors.Wrap(err, cerr.Error()) 128 } 129 return pc, err 130 } 131 132 // ensure dialed ID matches connection ID 133 if addr.ID != pc.ID() { 134 if cerr := conn.Close(); cerr != nil { 135 return pc, errors.Wrap(err, cerr.Error()) 136 } 137 return pc, SwitchAuthenticationFailureError{addr, pc.ID()} 138 } 139 140 return pc, nil 141 } 142 143 type remotePeer struct { 144 PrivKey crypto.PrivKey 145 Config *config.P2PConfig 146 addr *NetAddress 147 channels []byte 148 listenAddr string 149 listener net.Listener 150 } 151 152 func (rp *remotePeer) Addr() *NetAddress { 153 return rp.addr 154 } 155 156 func (rp *remotePeer) ID() ID { 157 return rp.PrivKey.PubKey().Address().ID() 158 } 159 160 func (rp *remotePeer) Start() { 161 if rp.listenAddr == "" { 162 rp.listenAddr = "127.0.0.1:0" 163 } 164 165 l, e := net.Listen("tcp", rp.listenAddr) // any available address 166 if e != nil { 167 golog.Fatalf("net.Listen tcp :0: %+v", e) 168 } 169 rp.listener = l 170 rp.addr = NewNetAddress(rp.PrivKey.PubKey().Address().ID(), l.Addr()) 171 if rp.channels == nil { 172 rp.channels = []byte{testCh} 173 } 174 go rp.accept() 175 } 176 177 func (rp *remotePeer) Stop() { 178 rp.listener.Close() 179 } 180 181 func (rp *remotePeer) Dial(addr *NetAddress) (net.Conn, error) { 182 conn, err := addr.DialTimeout(1 * time.Second) 183 if err != nil { 184 return nil, err 185 } 186 pc, err := testInboundPeerConn(conn, rp.Config, rp.PrivKey) 187 if err != nil { 188 return nil, err 189 } 190 _, err = handshake(pc.conn, time.Second, rp.nodeInfo()) 191 if err != nil { 192 return nil, err 193 } 194 return conn, err 195 } 196 197 func (rp *remotePeer) accept() { 198 conns := []net.Conn{} 199 200 for { 201 conn, err := rp.listener.Accept() 202 if err != nil { 203 golog.Printf("Failed to accept conn: %+v", err) 204 for _, conn := range conns { 205 _ = conn.Close() 206 } 207 return 208 } 209 210 pc, err := testInboundPeerConn(conn, rp.Config, rp.PrivKey) 211 if err != nil { 212 golog.Fatalf("Failed to create a peer: %+v", err) 213 } 214 215 _, err = handshake(pc.conn, time.Second, rp.nodeInfo()) 216 if err != nil { 217 golog.Fatalf("Failed to perform handshake: %+v", err) 218 } 219 220 conns = append(conns, conn) 221 } 222 } 223 224 func (rp *remotePeer) nodeInfo() NodeInfo { 225 return NodeInfo{ 226 VersionSet: testVersionSet(), 227 NetAddress: rp.Addr(), 228 Network: "testing", 229 Version: "1.2.3-rc0-deadbeef", 230 Channels: rp.channels, 231 Moniker: "remote_peer", 232 } 233 }