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