github.com/Team-Kujira/tendermint@v0.34.24-indexer/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 mempoolv0 "github.com/tendermint/tendermint/mempool/v0" 25 mempoolv1 "github.com/tendermint/tendermint/mempool/v1" 26 "github.com/tendermint/tendermint/p2p" 27 "github.com/tendermint/tendermint/p2p/conn" 28 p2pmock "github.com/tendermint/tendermint/p2p/mock" 29 "github.com/tendermint/tendermint/privval" 30 "github.com/tendermint/tendermint/proxy" 31 sm "github.com/tendermint/tendermint/state" 32 "github.com/tendermint/tendermint/store" 33 "github.com/tendermint/tendermint/types" 34 tmtime "github.com/tendermint/tendermint/types/time" 35 ) 36 37 func TestNodeStartStop(t *testing.T) { 38 config := cfg.ResetTestRoot("node_node_test") 39 defer os.RemoveAll(config.RootDir) 40 41 // create & start node 42 n, err := DefaultNewNode(config, log.TestingLogger()) 43 require.NoError(t, err) 44 err = n.Start() 45 require.NoError(t, err) 46 47 t.Logf("Started node %v", n.sw.NodeInfo()) 48 49 // wait for the node to produce a block 50 blocksSub, err := n.EventBus().Subscribe(context.Background(), "node_test", types.EventQueryNewBlock) 51 require.NoError(t, err) 52 select { 53 case <-blocksSub.Out(): 54 case <-blocksSub.Cancelled(): 55 t.Fatal("blocksSub was cancelled") 56 case <-time.After(10 * time.Second): 57 t.Fatal("timed out waiting for the node to produce a block") 58 } 59 60 // stop the node 61 go func() { 62 err = n.Stop() 63 require.NoError(t, err) 64 }() 65 66 select { 67 case <-n.Quit(): 68 case <-time.After(5 * time.Second): 69 pid := os.Getpid() 70 p, err := os.FindProcess(pid) 71 if err != nil { 72 panic(err) 73 } 74 err = p.Signal(syscall.SIGABRT) 75 fmt.Println(err) 76 t.Fatal("timed out waiting for shutdown") 77 } 78 } 79 80 func TestSplitAndTrimEmpty(t *testing.T) { 81 testCases := []struct { 82 s string 83 sep string 84 cutset string 85 expected []string 86 }{ 87 {"a,b,c", ",", " ", []string{"a", "b", "c"}}, 88 {" a , b , c ", ",", " ", []string{"a", "b", "c"}}, 89 {" a, b, c ", ",", " ", []string{"a", "b", "c"}}, 90 {" a, ", ",", " ", []string{"a"}}, 91 {" ", ",", " ", []string{}}, 92 } 93 94 for _, tc := range testCases { 95 assert.Equal(t, tc.expected, splitAndTrimEmpty(tc.s, tc.sep, tc.cutset), "%s", tc.s) 96 } 97 } 98 99 func TestNodeDelayedStart(t *testing.T) { 100 config := cfg.ResetTestRoot("node_delayed_start_test") 101 defer os.RemoveAll(config.RootDir) 102 now := tmtime.Now() 103 104 // create & start node 105 n, err := DefaultNewNode(config, log.TestingLogger()) 106 n.GenesisDoc().GenesisTime = now.Add(2 * time.Second) 107 require.NoError(t, err) 108 109 err = n.Start() 110 require.NoError(t, err) 111 defer n.Stop() //nolint:errcheck // ignore for tests 112 113 startTime := tmtime.Now() 114 assert.Equal(t, true, startTime.After(n.GenesisDoc().GenesisTime)) 115 } 116 117 func TestNodeSetAppVersion(t *testing.T) { 118 config := cfg.ResetTestRoot("node_app_version_test") 119 defer os.RemoveAll(config.RootDir) 120 121 // create & start node 122 n, err := DefaultNewNode(config, log.TestingLogger()) 123 require.NoError(t, err) 124 125 // default config uses the kvstore app 126 var appVersion uint64 = kvstore.ProtocolVersion 127 128 // check version is set in state 129 state, err := n.stateStore.Load() 130 require.NoError(t, err) 131 assert.Equal(t, state.Version.Consensus.App, appVersion) 132 133 // check version is set in node info 134 assert.Equal(t, n.nodeInfo.(p2p.DefaultNodeInfo).ProtocolVersion.App, appVersion) 135 } 136 137 func TestNodeSetPrivValTCP(t *testing.T) { 138 addr := "tcp://" + testFreeAddr(t) 139 140 config := cfg.ResetTestRoot("node_priv_val_tcp_test") 141 defer os.RemoveAll(config.RootDir) 142 config.BaseConfig.PrivValidatorListenAddr = addr 143 144 dialer := privval.DialTCPFn(addr, 100*time.Millisecond, ed25519.GenPrivKey()) 145 dialerEndpoint := privval.NewSignerDialerEndpoint( 146 log.TestingLogger(), 147 dialer, 148 ) 149 privval.SignerDialerEndpointTimeoutReadWrite(100 * time.Millisecond)(dialerEndpoint) 150 151 signerServer := privval.NewSignerServer( 152 dialerEndpoint, 153 config.ChainID(), 154 types.NewMockPV(), 155 ) 156 157 go func() { 158 err := signerServer.Start() 159 if err != nil { 160 panic(err) 161 } 162 }() 163 defer signerServer.Stop() //nolint:errcheck // ignore for tests 164 165 n, err := DefaultNewNode(config, log.TestingLogger()) 166 require.NoError(t, err) 167 assert.IsType(t, &privval.RetrySignerClient{}, n.PrivValidator()) 168 } 169 170 // address without a protocol must result in error 171 func TestPrivValidatorListenAddrNoProtocol(t *testing.T) { 172 addrNoPrefix := testFreeAddr(t) 173 174 config := cfg.ResetTestRoot("node_priv_val_tcp_test") 175 defer os.RemoveAll(config.RootDir) 176 config.BaseConfig.PrivValidatorListenAddr = addrNoPrefix 177 178 _, err := DefaultNewNode(config, log.TestingLogger()) 179 assert.Error(t, err) 180 } 181 182 func TestNodeSetPrivValIPC(t *testing.T) { 183 tmpfile := "/tmp/kms." + tmrand.Str(6) + ".sock" 184 defer os.Remove(tmpfile) // clean up 185 186 config := cfg.ResetTestRoot("node_priv_val_tcp_test") 187 defer os.RemoveAll(config.RootDir) 188 config.BaseConfig.PrivValidatorListenAddr = "unix://" + tmpfile 189 190 dialer := privval.DialUnixFn(tmpfile) 191 dialerEndpoint := privval.NewSignerDialerEndpoint( 192 log.TestingLogger(), 193 dialer, 194 ) 195 privval.SignerDialerEndpointTimeoutReadWrite(100 * time.Millisecond)(dialerEndpoint) 196 197 pvsc := privval.NewSignerServer( 198 dialerEndpoint, 199 config.ChainID(), 200 types.NewMockPV(), 201 ) 202 203 go func() { 204 err := pvsc.Start() 205 require.NoError(t, err) 206 }() 207 defer pvsc.Stop() //nolint:errcheck // ignore for tests 208 209 n, err := DefaultNewNode(config, log.TestingLogger()) 210 require.NoError(t, err) 211 assert.IsType(t, &privval.RetrySignerClient{}, n.PrivValidator()) 212 } 213 214 // testFreeAddr claims a free port so we don't block on listener being ready. 215 func testFreeAddr(t *testing.T) string { 216 ln, err := net.Listen("tcp", "127.0.0.1:0") 217 require.NoError(t, err) 218 defer ln.Close() 219 220 return fmt.Sprintf("127.0.0.1:%d", ln.Addr().(*net.TCPAddr).Port) 221 } 222 223 // create a proposal block using real and full 224 // mempool and evidence pool and validate it. 225 func TestCreateProposalBlock(t *testing.T) { 226 config := cfg.ResetTestRoot("node_create_proposal") 227 defer os.RemoveAll(config.RootDir) 228 cc := proxy.NewLocalClientCreator(kvstore.NewApplication()) 229 proxyApp := proxy.NewAppConns(cc) 230 err := proxyApp.Start() 231 require.Nil(t, err) 232 defer proxyApp.Stop() //nolint:errcheck // ignore for tests 233 234 logger := log.TestingLogger() 235 236 var height int64 = 1 237 state, stateDB, privVals := state(1, height) 238 stateStore := sm.NewStore(stateDB, sm.StoreOptions{ 239 DiscardABCIResponses: false, 240 }) 241 maxBytes := 16384 242 var partSize uint32 = 256 243 maxEvidenceBytes := int64(maxBytes / 2) 244 state.ConsensusParams.Block.MaxBytes = int64(maxBytes) 245 state.ConsensusParams.Evidence.MaxBytes = maxEvidenceBytes 246 proposerAddr, _ := state.Validators.GetByIndex(0) 247 248 // Make Mempool 249 memplMetrics := mempl.NopMetrics() 250 var mempool mempl.Mempool 251 252 switch config.Mempool.Version { 253 case cfg.MempoolV0: 254 mempool = mempoolv0.NewCListMempool(config.Mempool, 255 proxyApp.Mempool(), 256 state.LastBlockHeight, 257 mempoolv0.WithMetrics(memplMetrics), 258 mempoolv0.WithPreCheck(sm.TxPreCheck(state)), 259 mempoolv0.WithPostCheck(sm.TxPostCheck(state))) 260 case cfg.MempoolV1: 261 mempool = mempoolv1.NewTxMempool(logger, 262 config.Mempool, 263 proxyApp.Mempool(), 264 state.LastBlockHeight, 265 mempoolv1.WithMetrics(memplMetrics), 266 mempoolv1.WithPreCheck(sm.TxPreCheck(state)), 267 mempoolv1.WithPostCheck(sm.TxPostCheck(state)), 268 ) 269 } 270 271 // Make EvidencePool 272 evidenceDB := dbm.NewMemDB() 273 blockStore := store.NewBlockStore(dbm.NewMemDB()) 274 evidencePool, err := evidence.NewPool(evidenceDB, stateStore, blockStore) 275 require.NoError(t, err) 276 evidencePool.SetLogger(logger) 277 278 // fill the evidence pool with more evidence 279 // than can fit in a block 280 var currentBytes int64 281 for currentBytes <= maxEvidenceBytes { 282 ev := types.NewMockDuplicateVoteEvidenceWithValidator(height, time.Now(), privVals[0], "test-chain") 283 currentBytes += int64(len(ev.Bytes())) 284 evidencePool.ReportConflictingVotes(ev.VoteA, ev.VoteB) 285 } 286 287 evList, size := evidencePool.PendingEvidence(state.ConsensusParams.Evidence.MaxBytes) 288 require.Less(t, size, state.ConsensusParams.Evidence.MaxBytes+1) 289 evData := &types.EvidenceData{Evidence: evList} 290 require.EqualValues(t, size, evData.ByteSize()) 291 292 // fill the mempool with more txs 293 // than can fit in a block 294 txLength := 100 295 for i := 0; i <= maxBytes/txLength; i++ { 296 tx := tmrand.Bytes(txLength) 297 err := mempool.CheckTx(tx, nil, mempl.TxInfo{}) 298 assert.NoError(t, err) 299 } 300 301 blockExec := sm.NewBlockExecutor( 302 stateStore, 303 logger, 304 proxyApp.Consensus(), 305 mempool, 306 evidencePool, 307 ) 308 309 commit := types.NewCommit(height-1, 0, types.BlockID{}, nil) 310 block, _ := blockExec.CreateProposalBlock( 311 height, 312 state, commit, 313 proposerAddr, 314 ) 315 316 // check that the part set does not exceed the maximum block size 317 partSet := block.MakePartSet(partSize) 318 assert.Less(t, partSet.ByteSize(), int64(maxBytes)) 319 320 partSetFromHeader := types.NewPartSetFromHeader(partSet.Header()) 321 for partSetFromHeader.Count() < partSetFromHeader.Total() { 322 added, err := partSetFromHeader.AddPart(partSet.GetPart(int(partSetFromHeader.Count()))) 323 require.NoError(t, err) 324 require.True(t, added) 325 } 326 assert.EqualValues(t, partSetFromHeader.ByteSize(), partSet.ByteSize()) 327 328 err = blockExec.ValidateBlock(state, block) 329 assert.NoError(t, err) 330 } 331 332 func TestMaxProposalBlockSize(t *testing.T) { 333 config := cfg.ResetTestRoot("node_create_proposal") 334 defer os.RemoveAll(config.RootDir) 335 cc := proxy.NewLocalClientCreator(kvstore.NewApplication()) 336 proxyApp := proxy.NewAppConns(cc) 337 err := proxyApp.Start() 338 require.Nil(t, err) 339 defer proxyApp.Stop() //nolint:errcheck // ignore for tests 340 341 logger := log.TestingLogger() 342 343 var height int64 = 1 344 state, stateDB, _ := state(1, height) 345 stateStore := sm.NewStore(stateDB, sm.StoreOptions{ 346 DiscardABCIResponses: false, 347 }) 348 var maxBytes int64 = 16384 349 var partSize uint32 = 256 350 state.ConsensusParams.Block.MaxBytes = maxBytes 351 proposerAddr, _ := state.Validators.GetByIndex(0) 352 353 // Make Mempool 354 memplMetrics := mempl.NopMetrics() 355 var mempool mempl.Mempool 356 switch config.Mempool.Version { 357 case cfg.MempoolV0: 358 mempool = mempoolv0.NewCListMempool(config.Mempool, 359 proxyApp.Mempool(), 360 state.LastBlockHeight, 361 mempoolv0.WithMetrics(memplMetrics), 362 mempoolv0.WithPreCheck(sm.TxPreCheck(state)), 363 mempoolv0.WithPostCheck(sm.TxPostCheck(state))) 364 case cfg.MempoolV1: 365 mempool = mempoolv1.NewTxMempool(logger, 366 config.Mempool, 367 proxyApp.Mempool(), 368 state.LastBlockHeight, 369 mempoolv1.WithMetrics(memplMetrics), 370 mempoolv1.WithPreCheck(sm.TxPreCheck(state)), 371 mempoolv1.WithPostCheck(sm.TxPostCheck(state)), 372 ) 373 } 374 375 // fill the mempool with one txs just below the maximum size 376 txLength := int(types.MaxDataBytesNoEvidence(maxBytes, 1)) 377 tx := tmrand.Bytes(txLength - 4) // to account for the varint 378 err = mempool.CheckTx(tx, nil, mempl.TxInfo{}) 379 assert.NoError(t, err) 380 381 blockExec := sm.NewBlockExecutor( 382 stateStore, 383 logger, 384 proxyApp.Consensus(), 385 mempool, 386 sm.EmptyEvidencePool{}, 387 ) 388 389 commit := types.NewCommit(height-1, 0, types.BlockID{}, nil) 390 block, _ := blockExec.CreateProposalBlock( 391 height, 392 state, commit, 393 proposerAddr, 394 ) 395 396 pb, err := block.ToProto() 397 require.NoError(t, err) 398 assert.Less(t, int64(pb.Size()), maxBytes) 399 400 // check that the part set does not exceed the maximum block size 401 partSet := block.MakePartSet(partSize) 402 assert.EqualValues(t, partSet.ByteSize(), int64(pb.Size())) 403 } 404 405 func TestNodeNewNodeCustomReactors(t *testing.T) { 406 config := cfg.ResetTestRoot("node_new_node_custom_reactors_test") 407 defer os.RemoveAll(config.RootDir) 408 409 cr := p2pmock.NewReactor() 410 cr.Channels = []*conn.ChannelDescriptor{ 411 { 412 ID: byte(0x31), 413 Priority: 5, 414 SendQueueCapacity: 100, 415 RecvMessageCapacity: 100, 416 }, 417 } 418 customBlockchainReactor := p2pmock.NewReactor() 419 420 nodeKey, err := p2p.LoadOrGenNodeKey(config.NodeKeyFile()) 421 require.NoError(t, err) 422 423 n, err := NewNode(config, 424 privval.LoadOrGenFilePV(config.PrivValidatorKeyFile(), config.PrivValidatorStateFile()), 425 nodeKey, 426 proxy.DefaultClientCreator(config.ProxyApp, config.ABCI, config.DBDir()), 427 DefaultGenesisDocProviderFunc(config), 428 DefaultDBProvider, 429 DefaultMetricsProvider(config.Instrumentation), 430 log.TestingLogger(), 431 CustomReactors(map[string]p2p.Reactor{"FOO": cr, "BLOCKCHAIN": customBlockchainReactor}), 432 ) 433 require.NoError(t, err) 434 435 err = n.Start() 436 require.NoError(t, err) 437 defer n.Stop() //nolint:errcheck // ignore for tests 438 439 assert.True(t, cr.IsRunning()) 440 assert.Equal(t, cr, n.Switch().Reactor("FOO")) 441 442 assert.True(t, customBlockchainReactor.IsRunning()) 443 assert.Equal(t, customBlockchainReactor, n.Switch().Reactor("BLOCKCHAIN")) 444 445 channels := n.NodeInfo().(p2p.DefaultNodeInfo).Channels 446 assert.Contains(t, channels, mempl.MempoolChannel) 447 assert.Contains(t, channels, cr.Channels[0].ID) 448 } 449 450 func state(nVals int, height int64) (sm.State, dbm.DB, []types.PrivValidator) { 451 privVals := make([]types.PrivValidator, nVals) 452 vals := make([]types.GenesisValidator, nVals) 453 for i := 0; i < nVals; i++ { 454 privVal := types.NewMockPV() 455 privVals[i] = privVal 456 vals[i] = types.GenesisValidator{ 457 Address: privVal.PrivKey.PubKey().Address(), 458 PubKey: privVal.PrivKey.PubKey(), 459 Power: 1000, 460 Name: fmt.Sprintf("test%d", i), 461 } 462 } 463 s, _ := sm.MakeGenesisState(&types.GenesisDoc{ 464 ChainID: "test-chain", 465 Validators: vals, 466 AppHash: nil, 467 }) 468 469 // save validators to db for 2 heights 470 stateDB := dbm.NewMemDB() 471 stateStore := sm.NewStore(stateDB, sm.StoreOptions{ 472 DiscardABCIResponses: false, 473 }) 474 if err := stateStore.Save(s); err != nil { 475 panic(err) 476 } 477 478 for i := 1; i < int(height); i++ { 479 s.LastBlockHeight++ 480 s.LastValidators = s.Validators.Copy() 481 if err := stateStore.Save(s); err != nil { 482 panic(err) 483 } 484 } 485 return s, stateDB, privVals 486 }