github.com/pokt-network/tendermint@v0.32.11-0.20230426215212-59310158d3e9/node/node_test.go (about) 1 package node 2 3 import ( 4 "context" 5 "fmt" 6 "net" 7 "os" 8 "syscall" 9 "testing" 10 "time" 11 12 "github.com/stretchr/testify/assert" 13 "github.com/stretchr/testify/require" 14 15 dbm "github.com/tendermint/tm-db" 16 17 "github.com/tendermint/tendermint/abci/example/kvstore" 18 cfg "github.com/tendermint/tendermint/config" 19 "github.com/tendermint/tendermint/crypto/ed25519" 20 "github.com/tendermint/tendermint/evidence" 21 "github.com/tendermint/tendermint/libs/log" 22 tmrand "github.com/tendermint/tendermint/libs/rand" 23 mempl "github.com/tendermint/tendermint/mempool" 24 "github.com/tendermint/tendermint/p2p" 25 p2pmock "github.com/tendermint/tendermint/p2p/mock" 26 "github.com/tendermint/tendermint/privval" 27 "github.com/tendermint/tendermint/proxy" 28 sm "github.com/tendermint/tendermint/state" 29 "github.com/tendermint/tendermint/types" 30 tmtime "github.com/tendermint/tendermint/types/time" 31 "github.com/tendermint/tendermint/version" 32 ) 33 34 func TestNodeStartStop(t *testing.T) { 35 config := cfg.ResetTestRoot("node_node_test") 36 defer os.RemoveAll(config.RootDir) 37 38 // create & start node 39 n, err := DefaultNewNode(config, log.TestingLogger()) 40 require.NoError(t, err) 41 err = n.Start() 42 require.NoError(t, err) 43 44 t.Logf("Started node %v", n.sw.NodeInfo()) 45 46 // wait for the node to produce a block 47 blocksSub, err := n.EventBus().Subscribe(context.Background(), "node_test", types.EventQueryNewBlock) 48 require.NoError(t, err) 49 select { 50 case <-blocksSub.Out(): 51 case <-blocksSub.Cancelled(): 52 t.Fatal("blocksSub was cancelled") 53 case <-time.After(10 * time.Second): 54 t.Fatal("timed out waiting for the node to produce a block") 55 } 56 57 // stop the node 58 go func() { 59 n.Stop() 60 }() 61 62 select { 63 case <-n.Quit(): 64 case <-time.After(5 * time.Second): 65 pid := os.Getpid() 66 p, err := os.FindProcess(pid) 67 if err != nil { 68 panic(err) 69 } 70 err = p.Signal(syscall.SIGABRT) 71 fmt.Println(err) 72 t.Fatal("timed out waiting for shutdown") 73 } 74 } 75 76 func TestSplitAndTrimEmpty(t *testing.T) { 77 testCases := []struct { 78 s string 79 sep string 80 cutset string 81 expected []string 82 }{ 83 {"a,b,c", ",", " ", []string{"a", "b", "c"}}, 84 {" a , b , c ", ",", " ", []string{"a", "b", "c"}}, 85 {" a, b, c ", ",", " ", []string{"a", "b", "c"}}, 86 {" a, ", ",", " ", []string{"a"}}, 87 {" ", ",", " ", []string{}}, 88 } 89 90 for _, tc := range testCases { 91 assert.Equal(t, tc.expected, splitAndTrimEmpty(tc.s, tc.sep, tc.cutset), "%s", tc.s) 92 } 93 } 94 95 func TestNodeDelayedStart(t *testing.T) { 96 config := cfg.ResetTestRoot("node_delayed_start_test") 97 defer os.RemoveAll(config.RootDir) 98 now := tmtime.Now() 99 100 // create & start node 101 n, err := DefaultNewNode(config, log.TestingLogger()) 102 n.GenesisDoc().GenesisTime = now.Add(2 * time.Second) 103 require.NoError(t, err) 104 105 err = n.Start() 106 require.NoError(t, err) 107 defer n.Stop() 108 109 startTime := tmtime.Now() 110 assert.Equal(t, true, startTime.After(n.GenesisDoc().GenesisTime)) 111 } 112 113 func TestNodeSetAppVersion(t *testing.T) { 114 config := cfg.ResetTestRoot("node_app_version_test") 115 defer os.RemoveAll(config.RootDir) 116 117 // create & start node 118 n, err := DefaultNewNode(config, log.TestingLogger()) 119 require.NoError(t, err) 120 121 // default config uses the kvstore app 122 var appVersion version.Protocol = kvstore.ProtocolVersion 123 124 // check version is set in state 125 state := sm.LoadState(n.stateDB) 126 assert.Equal(t, state.Version.Consensus.App, appVersion) 127 128 // check version is set in node info 129 assert.Equal(t, n.nodeInfo.(p2p.DefaultNodeInfo).ProtocolVersion.App, appVersion) 130 } 131 132 func TestNodeSetPrivValTCP(t *testing.T) { 133 addr := "tcp://" + testFreeAddr(t) 134 135 config := cfg.ResetTestRoot("node_priv_val_tcp_test") 136 defer os.RemoveAll(config.RootDir) 137 config.BaseConfig.PrivValidatorListenAddr = addr 138 139 dialer := privval.DialTCPFn(addr, 100*time.Millisecond, ed25519.GenPrivKey()) 140 dialerEndpoint := privval.NewSignerDialerEndpoint( 141 log.TestingLogger(), 142 dialer, 143 ) 144 privval.SignerDialerEndpointTimeoutReadWrite(100 * time.Millisecond)(dialerEndpoint) 145 146 signerServer := privval.NewSignerServer( 147 dialerEndpoint, 148 config.ChainID(), 149 types.NewMockPV(), 150 ) 151 152 go func() { 153 err := signerServer.Start() 154 if err != nil { 155 panic(err) 156 } 157 }() 158 defer signerServer.Stop() 159 160 n, err := DefaultNewNode(config, log.TestingLogger()) 161 require.NoError(t, err) 162 assert.IsType(t, &privval.RetrySignerClient{}, n.PrivValidator()) 163 } 164 165 // address without a protocol must result in error 166 func TestPrivValidatorListenAddrNoProtocol(t *testing.T) { 167 addrNoPrefix := testFreeAddr(t) 168 169 config := cfg.ResetTestRoot("node_priv_val_tcp_test") 170 defer os.RemoveAll(config.RootDir) 171 config.BaseConfig.PrivValidatorListenAddr = addrNoPrefix 172 173 _, err := DefaultNewNode(config, log.TestingLogger()) 174 assert.Error(t, err) 175 } 176 177 func TestNodeSetPrivValIPC(t *testing.T) { 178 tmpfile := "/tmp/kms." + tmrand.Str(6) + ".sock" 179 defer os.Remove(tmpfile) // clean up 180 181 config := cfg.ResetTestRoot("node_priv_val_tcp_test") 182 defer os.RemoveAll(config.RootDir) 183 config.BaseConfig.PrivValidatorListenAddr = "unix://" + tmpfile 184 185 dialer := privval.DialUnixFn(tmpfile) 186 dialerEndpoint := privval.NewSignerDialerEndpoint( 187 log.TestingLogger(), 188 dialer, 189 ) 190 privval.SignerDialerEndpointTimeoutReadWrite(100 * time.Millisecond)(dialerEndpoint) 191 192 pvsc := privval.NewSignerServer( 193 dialerEndpoint, 194 config.ChainID(), 195 types.NewMockPV(), 196 ) 197 198 go func() { 199 err := pvsc.Start() 200 require.NoError(t, err) 201 }() 202 defer pvsc.Stop() 203 204 n, err := DefaultNewNode(config, log.TestingLogger()) 205 require.NoError(t, err) 206 assert.IsType(t, &privval.RetrySignerClient{}, n.PrivValidator()) 207 } 208 209 // testFreeAddr claims a free port so we don't block on listener being ready. 210 func testFreeAddr(t *testing.T) string { 211 ln, err := net.Listen("tcp", "127.0.0.1:0") 212 require.NoError(t, err) 213 defer ln.Close() 214 215 return fmt.Sprintf("127.0.0.1:%d", ln.Addr().(*net.TCPAddr).Port) 216 } 217 218 // create a proposal block using real and full 219 // mempool and evidence pool and validate it. 220 func TestCreateProposalBlock(t *testing.T) { 221 config := cfg.ResetTestRoot("node_create_proposal") 222 defer os.RemoveAll(config.RootDir) 223 cc := proxy.NewLocalClientCreator(kvstore.NewApplication()) 224 proxyApp := proxy.NewAppConns(cc) 225 err := proxyApp.Start() 226 require.Nil(t, err) 227 defer proxyApp.Stop() 228 229 logger := log.TestingLogger() 230 231 var height int64 = 1 232 state, stateDB := state(1, height) 233 maxBytes := 16384 234 state.ConsensusParams.Block.MaxBytes = int64(maxBytes) 235 proposerAddr, _ := state.Validators.GetByIndex(0) 236 237 // Make Mempool 238 memplMetrics := mempl.PrometheusMetrics("node_test") 239 mempool := mempl.NewCListMempool( 240 config.Mempool, 241 proxyApp.Mempool(), 242 state.LastBlockHeight, 243 mempl.WithMetrics(memplMetrics), 244 mempl.WithPreCheck(sm.TxPreCheck(state)), 245 mempl.WithPostCheck(sm.TxPostCheck(state)), 246 ) 247 mempool.SetLogger(logger) 248 249 // Make EvidencePool 250 types.RegisterMockEvidencesGlobal() // XXX! 251 evidence.RegisterMockEvidences() 252 evidenceDB := dbm.NewMemDB() 253 evidencePool := evidence.NewPool(stateDB, evidenceDB) 254 evidencePool.SetLogger(logger) 255 256 // fill the evidence pool with more evidence 257 // than can fit in a block 258 minEvSize := 12 259 numEv := (maxBytes / types.MaxEvidenceBytesDenominator) / minEvSize 260 for i := 0; i < numEv; i++ { 261 ev := types.NewMockRandomEvidence(1, time.Now(), proposerAddr, tmrand.Bytes(minEvSize)) 262 err := evidencePool.AddEvidence(ev) 263 assert.NoError(t, err) 264 } 265 266 // fill the mempool with more txs 267 // than can fit in a block 268 txLength := 1000 269 for i := 0; i < maxBytes/txLength; i++ { 270 tx := tmrand.Bytes(txLength) 271 err := mempool.CheckTx(tx, nil, mempl.TxInfo{}) 272 assert.NoError(t, err) 273 } 274 275 blockExec := sm.NewBlockExecutor( 276 stateDB, 277 logger, 278 proxyApp.Consensus(), 279 mempool, 280 evidencePool, 281 nil, 282 ) 283 284 commit := types.NewCommit(height-1, 0, types.BlockID{}, nil) 285 block, _ := blockExec.CreateProposalBlock( 286 height, 287 state, commit, 288 proposerAddr, 289 ) 290 291 err = blockExec.ValidateBlock(state, block) 292 assert.NoError(t, err) 293 } 294 295 func TestNodeNewNodeCustomReactors(t *testing.T) { 296 config := cfg.ResetTestRoot("node_new_node_custom_reactors_test") 297 defer os.RemoveAll(config.RootDir) 298 299 cr := p2pmock.NewReactor() 300 customBlockchainReactor := p2pmock.NewReactor() 301 302 nodeKey, err := p2p.LoadOrGenNodeKey(config.NodeKeyFile()) 303 require.NoError(t, err) 304 305 n, err := NewNode(nil, config, 0, 306 privval.LoadOrGenFilePV(config.PrivValidatorKeyFile(), config.PrivValidatorStateFile()), 307 nodeKey, 308 proxy.DefaultClientCreator(config.ProxyApp, config.ABCI, config.DBDir()), 309 DefaultGenesisDocProviderFunc(config), 310 DefaultDBProvider, 311 nil, 312 DefaultMetricsProvider(config.Instrumentation), 313 log.TestingLogger(), 314 CustomReactors(map[string]p2p.Reactor{"FOO": cr, "BLOCKCHAIN": customBlockchainReactor}), 315 ) 316 require.NoError(t, err) 317 318 err = n.Start() 319 require.NoError(t, err) 320 defer n.Stop() 321 322 assert.True(t, cr.IsRunning()) 323 assert.Equal(t, cr, n.Switch().Reactor("FOO")) 324 325 assert.True(t, customBlockchainReactor.IsRunning()) 326 assert.Equal(t, customBlockchainReactor, n.Switch().Reactor("BLOCKCHAIN")) 327 } 328 329 func state(nVals int, height int64) (sm.State, dbm.DB) { 330 vals := make([]types.GenesisValidator, nVals) 331 for i := 0; i < nVals; i++ { 332 secret := []byte(fmt.Sprintf("test%d", i)) 333 pk := ed25519.GenPrivKeyFromSecret(secret) 334 vals[i] = types.GenesisValidator{ 335 Address: pk.PubKey().Address(), 336 PubKey: pk.PubKey(), 337 Power: 1000, 338 Name: fmt.Sprintf("test%d", i), 339 } 340 } 341 s, _ := sm.MakeGenesisState(&types.GenesisDoc{ 342 ChainID: "test-chain", 343 Validators: vals, 344 AppHash: nil, 345 }) 346 347 // save validators to db for 2 heights 348 stateDB := dbm.NewMemDB() 349 sm.SaveState(stateDB, s) 350 351 for i := 1; i < int(height); i++ { 352 s.LastBlockHeight++ 353 s.LastValidators = s.Validators.Copy() 354 sm.SaveState(stateDB, s) 355 } 356 return s, stateDB 357 }