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