github.com/project-88388/tendermint-v0.34.14-terra.2@v1.0.0/p2p/test_util.go (about)

     1  package p2p
     2  
     3  import (
     4  	"fmt"
     5  	"net"
     6  	"time"
     7  
     8  	"github.com/tendermint/tendermint/crypto"
     9  	"github.com/tendermint/tendermint/crypto/ed25519"
    10  	"github.com/tendermint/tendermint/libs/log"
    11  	tmnet "github.com/tendermint/tendermint/libs/net"
    12  	tmrand "github.com/tendermint/tendermint/libs/rand"
    13  
    14  	"github.com/tendermint/tendermint/config"
    15  	"github.com/tendermint/tendermint/p2p/conn"
    16  )
    17  
    18  const testCh = 0x01
    19  
    20  //------------------------------------------------
    21  
    22  type mockNodeInfo struct {
    23  	addr *NetAddress
    24  }
    25  
    26  func (ni mockNodeInfo) ID() ID                              { return ni.addr.ID }
    27  func (ni mockNodeInfo) NetAddress() (*NetAddress, error)    { return ni.addr, nil }
    28  func (ni mockNodeInfo) Validate() error                     { return nil }
    29  func (ni mockNodeInfo) CompatibleWith(other NodeInfo) error { return nil }
    30  
    31  func AddPeerToSwitchPeerSet(sw *Switch, peer Peer) {
    32  	sw.peers.Add(peer) //nolint:errcheck // ignore error
    33  }
    34  
    35  func CreateRandomPeer(outbound bool) Peer {
    36  	addr, netAddr := CreateRoutableAddr()
    37  	p := &peer{
    38  		peerConn: peerConn{
    39  			outbound:   outbound,
    40  			socketAddr: netAddr,
    41  		},
    42  		nodeInfo: mockNodeInfo{netAddr},
    43  		mconn:    &conn.MConnection{},
    44  		metrics:  NopMetrics(),
    45  	}
    46  	p.SetLogger(log.TestingLogger().With("peer", addr))
    47  	return p
    48  }
    49  
    50  func CreateRoutableAddr() (addr string, netAddr *NetAddress) {
    51  	for {
    52  		var err error
    53  		addr = fmt.Sprintf("%X@%v.%v.%v.%v:26656",
    54  			tmrand.Bytes(20),
    55  			tmrand.Int()%256,
    56  			tmrand.Int()%256,
    57  			tmrand.Int()%256,
    58  			tmrand.Int()%256)
    59  		netAddr, err = NewNetAddressString(addr)
    60  		if err != nil {
    61  			panic(err)
    62  		}
    63  		if netAddr.Routable() {
    64  			break
    65  		}
    66  	}
    67  	return
    68  }
    69  
    70  //------------------------------------------------------------------
    71  // Connects switches via arbitrary net.Conn. Used for testing.
    72  
    73  const TestHost = "localhost"
    74  
    75  // MakeConnectedSwitches returns n switches, connected according to the connect func.
    76  // If connect==Connect2Switches, the switches will be fully connected.
    77  // initSwitch defines how the i'th switch should be initialized (ie. with what reactors).
    78  // NOTE: panics if any switch fails to start.
    79  func MakeConnectedSwitches(cfg *config.P2PConfig,
    80  	n int,
    81  	initSwitch func(int, *Switch) *Switch,
    82  	connect func([]*Switch, int, int),
    83  ) []*Switch {
    84  	switches := make([]*Switch, n)
    85  	for i := 0; i < n; i++ {
    86  		switches[i] = MakeSwitch(cfg, i, TestHost, "123.123.123", initSwitch)
    87  	}
    88  
    89  	if err := StartSwitches(switches); err != nil {
    90  		panic(err)
    91  	}
    92  
    93  	for i := 0; i < n; i++ {
    94  		for j := i + 1; j < n; j++ {
    95  			connect(switches, i, j)
    96  		}
    97  	}
    98  
    99  	return switches
   100  }
   101  
   102  // Connect2Switches will connect switches i and j via net.Pipe().
   103  // Blocks until a connection is established.
   104  // NOTE: caller ensures i and j are within bounds.
   105  func Connect2Switches(switches []*Switch, i, j int) {
   106  	switchI := switches[i]
   107  	switchJ := switches[j]
   108  
   109  	c1, c2 := conn.NetPipe()
   110  
   111  	doneCh := make(chan struct{})
   112  	go func() {
   113  		err := switchI.addPeerWithConnection(c1)
   114  		if err != nil {
   115  			panic(err)
   116  		}
   117  		doneCh <- struct{}{}
   118  	}()
   119  	go func() {
   120  		err := switchJ.addPeerWithConnection(c2)
   121  		if err != nil {
   122  			panic(err)
   123  		}
   124  		doneCh <- struct{}{}
   125  	}()
   126  	<-doneCh
   127  	<-doneCh
   128  }
   129  
   130  func (sw *Switch) addPeerWithConnection(conn net.Conn) error {
   131  	pc, err := testInboundPeerConn(conn, sw.config, sw.nodeKey.PrivKey)
   132  	if err != nil {
   133  		if err := conn.Close(); err != nil {
   134  			sw.Logger.Error("Error closing connection", "err", err)
   135  		}
   136  		return err
   137  	}
   138  
   139  	ni, err := handshake(conn, time.Second, sw.nodeInfo)
   140  	if err != nil {
   141  		if err := conn.Close(); err != nil {
   142  			sw.Logger.Error("Error closing connection", "err", err)
   143  		}
   144  		return err
   145  	}
   146  
   147  	p := newPeer(
   148  		pc,
   149  		MConnConfig(sw.config),
   150  		ni,
   151  		sw.reactorsByCh,
   152  		sw.chDescs,
   153  		sw.StopPeerForError,
   154  	)
   155  
   156  	if err = sw.addPeer(p); err != nil {
   157  		pc.CloseConn()
   158  		return err
   159  	}
   160  
   161  	return nil
   162  }
   163  
   164  // StartSwitches calls sw.Start() for each given switch.
   165  // It returns the first encountered error.
   166  func StartSwitches(switches []*Switch) error {
   167  	for _, s := range switches {
   168  		err := s.Start() // start switch and reactors
   169  		if err != nil {
   170  			return err
   171  		}
   172  	}
   173  	return nil
   174  }
   175  
   176  func MakeSwitch(
   177  	cfg *config.P2PConfig,
   178  	i int,
   179  	network, version string,
   180  	initSwitch func(int, *Switch) *Switch,
   181  	opts ...SwitchOption,
   182  ) *Switch {
   183  
   184  	nodeKey := NodeKey{
   185  		PrivKey: ed25519.GenPrivKey(),
   186  	}
   187  	nodeInfo := testNodeInfo(nodeKey.ID(), fmt.Sprintf("node%d", i))
   188  	addr, err := NewNetAddressString(
   189  		IDAddressString(nodeKey.ID(), nodeInfo.(DefaultNodeInfo).ListenAddr),
   190  	)
   191  	if err != nil {
   192  		panic(err)
   193  	}
   194  
   195  	t := NewMultiplexTransport(nodeInfo, nodeKey, MConnConfig(cfg))
   196  
   197  	if err := t.Listen(*addr); err != nil {
   198  		panic(err)
   199  	}
   200  
   201  	// TODO: let the config be passed in?
   202  	sw := initSwitch(i, NewSwitch(cfg, t, opts...))
   203  	sw.SetLogger(log.TestingLogger().With("switch", i))
   204  	sw.SetNodeKey(&nodeKey)
   205  
   206  	ni := nodeInfo.(DefaultNodeInfo)
   207  	for ch := range sw.reactorsByCh {
   208  		ni.Channels = append(ni.Channels, ch)
   209  	}
   210  	nodeInfo = ni
   211  
   212  	// TODO: We need to setup reactors ahead of time so the NodeInfo is properly
   213  	// populated and we don't have to do those awkward overrides and setters.
   214  	t.nodeInfo = nodeInfo
   215  	sw.SetNodeInfo(nodeInfo)
   216  
   217  	return sw
   218  }
   219  
   220  func testInboundPeerConn(
   221  	conn net.Conn,
   222  	config *config.P2PConfig,
   223  	ourNodePrivKey crypto.PrivKey,
   224  ) (peerConn, error) {
   225  	return testPeerConn(conn, config, false, false, ourNodePrivKey, nil)
   226  }
   227  
   228  func testPeerConn(
   229  	rawConn net.Conn,
   230  	cfg *config.P2PConfig,
   231  	outbound, persistent bool,
   232  	ourNodePrivKey crypto.PrivKey,
   233  	socketAddr *NetAddress,
   234  ) (pc peerConn, err error) {
   235  	conn := rawConn
   236  
   237  	// Fuzz connection
   238  	if cfg.TestFuzz {
   239  		// so we have time to do peer handshakes and get set up
   240  		conn = FuzzConnAfterFromConfig(conn, 10*time.Second, cfg.TestFuzzConfig)
   241  	}
   242  
   243  	// Encrypt connection
   244  	conn, err = upgradeSecretConn(conn, cfg.HandshakeTimeout, ourNodePrivKey)
   245  	if err != nil {
   246  		return pc, fmt.Errorf("error creating peer: %w", err)
   247  	}
   248  
   249  	// Only the information we already have
   250  	return newPeerConn(outbound, persistent, conn, socketAddr), nil
   251  }
   252  
   253  //----------------------------------------------------------------
   254  // rand node info
   255  
   256  func testNodeInfo(id ID, name string) NodeInfo {
   257  	return testNodeInfoWithNetwork(id, name, "testing")
   258  }
   259  
   260  func testNodeInfoWithNetwork(id ID, name, network string) NodeInfo {
   261  	return DefaultNodeInfo{
   262  		ProtocolVersion: defaultProtocolVersion,
   263  		DefaultNodeID:   id,
   264  		ListenAddr:      fmt.Sprintf("127.0.0.1:%d", getFreePort()),
   265  		Network:         network,
   266  		Version:         "1.2.3-rc0-deadbeef",
   267  		Channels:        []byte{testCh},
   268  		Moniker:         name,
   269  		Other: DefaultNodeInfoOther{
   270  			TxIndex:    "on",
   271  			RPCAddress: fmt.Sprintf("127.0.0.1:%d", getFreePort()),
   272  		},
   273  	}
   274  }
   275  
   276  func getFreePort() int {
   277  	port, err := tmnet.GetFreePort()
   278  	if err != nil {
   279  		panic(err)
   280  	}
   281  	return port
   282  }
   283  
   284  type AddrBookMock struct {
   285  	Addrs        map[string]struct{}
   286  	OurAddrs     map[string]struct{}
   287  	PrivateAddrs map[string]struct{}
   288  }
   289  
   290  var _ AddrBook = (*AddrBookMock)(nil)
   291  
   292  func (book *AddrBookMock) AddAddress(addr *NetAddress, src *NetAddress) error {
   293  	book.Addrs[addr.String()] = struct{}{}
   294  	return nil
   295  }
   296  func (book *AddrBookMock) AddOurAddress(addr *NetAddress) { book.OurAddrs[addr.String()] = struct{}{} }
   297  func (book *AddrBookMock) OurAddress(addr *NetAddress) bool {
   298  	_, ok := book.OurAddrs[addr.String()]
   299  	return ok
   300  }
   301  func (book *AddrBookMock) MarkGood(ID) {}
   302  func (book *AddrBookMock) HasAddress(addr *NetAddress) bool {
   303  	_, ok := book.Addrs[addr.String()]
   304  	return ok
   305  }
   306  func (book *AddrBookMock) RemoveAddress(addr *NetAddress) {
   307  	delete(book.Addrs, addr.String())
   308  }
   309  func (book *AddrBookMock) Save() {}
   310  func (book *AddrBookMock) AddPrivateIDs(addrs []string) {
   311  	for _, addr := range addrs {
   312  		book.PrivateAddrs[addr] = struct{}{}
   313  	}
   314  }