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