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