github.com/Finschia/ostracon@v1.1.5/node/node_test.go (about)

     1  package node
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"net"
     7  	"os"
     8  	"strings"
     9  	"syscall"
    10  	"testing"
    11  	"time"
    12  
    13  	"github.com/ory/dockertest"
    14  	"github.com/ory/dockertest/docker"
    15  
    16  	"github.com/stretchr/testify/assert"
    17  	"github.com/stretchr/testify/require"
    18  
    19  	dbm "github.com/tendermint/tm-db"
    20  
    21  	"github.com/Finschia/ostracon/abci/example/kvstore"
    22  	cfg "github.com/Finschia/ostracon/config"
    23  	"github.com/Finschia/ostracon/crypto/ed25519"
    24  	"github.com/Finschia/ostracon/evidence"
    25  	"github.com/Finschia/ostracon/libs/log"
    26  	tmrand "github.com/Finschia/ostracon/libs/rand"
    27  	mempl "github.com/Finschia/ostracon/mempool"
    28  	mempoolv0 "github.com/Finschia/ostracon/mempool/v0"
    29  
    30  	//mempoolv1 "github.com/Finschia/ostracon/mempool/v1"
    31  	"github.com/Finschia/ostracon/p2p"
    32  	"github.com/Finschia/ostracon/p2p/conn"
    33  	p2pmock "github.com/Finschia/ostracon/p2p/mock"
    34  	p2pmocks "github.com/Finschia/ostracon/p2p/mocks"
    35  	"github.com/Finschia/ostracon/privval"
    36  	"github.com/Finschia/ostracon/proxy"
    37  	sm "github.com/Finschia/ostracon/state"
    38  	"github.com/Finschia/ostracon/store"
    39  	"github.com/Finschia/ostracon/types"
    40  	tmtime "github.com/Finschia/ostracon/types/time"
    41  )
    42  
    43  func TestNewOstraconNode(t *testing.T) {
    44  	config := cfg.ResetTestRootWithChainID("TestNewOstraconNode", "new_ostracon_node")
    45  	defer os.RemoveAll(config.RootDir)
    46  	require.Equal(t, "", config.PrivValidatorListenAddr)
    47  	node, err := NewOstraconNode(config, log.TestingLogger())
    48  	require.NoError(t, err)
    49  	pubKey, err := node.PrivValidator().GetPubKey()
    50  	require.NoError(t, err)
    51  	require.NotNil(t, pubKey)
    52  }
    53  
    54  func TestNewOstraconNode_WithoutNodeKey(t *testing.T) {
    55  	config := cfg.ResetTestRootWithChainID("TestNewOstraconNode", "new_ostracon_node_wo_node_key")
    56  	defer os.RemoveAll(config.RootDir)
    57  	_ = os.Remove(config.NodeKeyFile())
    58  	_, err := NewOstraconNode(config, log.TestingLogger())
    59  	require.Error(t, err)
    60  }
    61  
    62  func TestNodeStartStop(t *testing.T) {
    63  	config := cfg.ResetTestRoot("node_node_test")
    64  	defer os.RemoveAll(config.RootDir)
    65  
    66  	// create & start node
    67  	n, err := DefaultNewNode(config, log.TestingLogger())
    68  	require.NoError(t, err)
    69  	err = n.Start()
    70  	require.NoError(t, err)
    71  
    72  	t.Logf("Started node %v", n.sw.NodeInfo())
    73  
    74  	// wait for the node to produce a block
    75  	blocksSub, err := n.EventBus().Subscribe(context.Background(), "node_test", types.EventQueryNewBlock)
    76  	require.NoError(t, err)
    77  	select {
    78  	case <-blocksSub.Out():
    79  	case <-blocksSub.Cancelled():
    80  		t.Fatal("blocksSub was cancelled")
    81  	case <-time.After(10 * time.Second):
    82  		t.Fatal("timed out waiting for the node to produce a block")
    83  	}
    84  
    85  	// stop the node
    86  	go func() {
    87  		err = n.Stop()
    88  		require.NoError(t, err)
    89  	}()
    90  
    91  	select {
    92  	case <-n.Quit():
    93  	case <-time.After(5 * time.Second):
    94  		pid := os.Getpid()
    95  		p, err := os.FindProcess(pid)
    96  		if err != nil {
    97  			panic(err)
    98  		}
    99  		err = p.Signal(syscall.SIGABRT)
   100  		fmt.Println(err)
   101  		t.Fatal("timed out waiting for shutdown")
   102  	}
   103  }
   104  
   105  func TestSplitAndTrimEmpty(t *testing.T) {
   106  	testCases := []struct {
   107  		s        string
   108  		sep      string
   109  		cutset   string
   110  		expected []string
   111  	}{
   112  		{"a,b,c", ",", " ", []string{"a", "b", "c"}},
   113  		{" a , b , c ", ",", " ", []string{"a", "b", "c"}},
   114  		{" a, b, c ", ",", " ", []string{"a", "b", "c"}},
   115  		{" a, ", ",", " ", []string{"a"}},
   116  		{"   ", ",", " ", []string{}},
   117  	}
   118  
   119  	for _, tc := range testCases {
   120  		assert.Equal(t, tc.expected, splitAndTrimEmpty(tc.s, tc.sep, tc.cutset), "%s", tc.s)
   121  	}
   122  }
   123  
   124  func TestNodeDelayedStart(t *testing.T) {
   125  	config := cfg.ResetTestRoot("node_delayed_start_test")
   126  	defer os.RemoveAll(config.RootDir)
   127  	now := tmtime.Now()
   128  
   129  	// create & start node
   130  	n, err := DefaultNewNode(config, log.TestingLogger())
   131  	n.GenesisDoc().GenesisTime = now.Add(2 * time.Second)
   132  	require.NoError(t, err)
   133  
   134  	err = n.Start()
   135  	require.NoError(t, err)
   136  	defer n.Stop() //nolint:errcheck // ignore for tests
   137  
   138  	startTime := tmtime.Now()
   139  	assert.Equal(t, true, startTime.After(n.GenesisDoc().GenesisTime))
   140  }
   141  
   142  func TestNodeSetAppVersion(t *testing.T) {
   143  	config := cfg.ResetTestRoot("node_app_version_test")
   144  	defer os.RemoveAll(config.RootDir)
   145  
   146  	// create & start node
   147  	n, err := DefaultNewNode(config, log.TestingLogger())
   148  	require.NoError(t, err)
   149  
   150  	// default config uses the kvstore app
   151  	var appVersion = kvstore.ProtocolVersion
   152  
   153  	// check version is set in state
   154  	state, err := n.stateStore.Load()
   155  	require.NoError(t, err)
   156  	assert.Equal(t, state.Version.Consensus.App, appVersion)
   157  
   158  	// check version is set in node info
   159  	assert.Equal(t, n.nodeInfo.(p2p.DefaultNodeInfo).ProtocolVersion.App, appVersion)
   160  }
   161  
   162  func TestNodeSetPrivValTCP(t *testing.T) {
   163  	address := testFreeAddr(t)
   164  	addr := "tcp://" + testFreeAddr(t)
   165  
   166  	config := cfg.ResetTestRoot("node_priv_val_tcp_test")
   167  	defer os.RemoveAll(config.RootDir)
   168  	config.BaseConfig.PrivValidatorListenAddr = addr
   169  	addrPart, _, err := net.SplitHostPort(address)
   170  	if err != nil {
   171  		return
   172  	}
   173  	config.BaseConfig.PrivValidatorRemoteAddresses = []string{addrPart}
   174  
   175  	dialer := privval.DialTCPFn(addr, 100*time.Millisecond, ed25519.GenPrivKey())
   176  	dialerEndpoint := privval.NewSignerDialerEndpoint(
   177  		log.TestingLogger(),
   178  		dialer,
   179  	)
   180  	privval.SignerDialerEndpointTimeoutReadWrite(100 * time.Millisecond)(dialerEndpoint)
   181  
   182  	signerServer := privval.NewSignerServer(
   183  		dialerEndpoint,
   184  		config.ChainID(),
   185  		types.NewMockPV(),
   186  	)
   187  
   188  	go func() {
   189  		err := signerServer.Start()
   190  		if err != nil {
   191  			panic(err)
   192  		}
   193  	}()
   194  	defer signerServer.Stop() //nolint:errcheck // ignore for tests
   195  
   196  	n, err := DefaultNewNode(config, log.TestingLogger())
   197  	require.NoError(t, err)
   198  	assert.IsType(t, &privval.RetrySignerClient{}, n.PrivValidator())
   199  }
   200  
   201  // address without a protocol must result in error
   202  func TestPrivValidatorListenAddrNoProtocol(t *testing.T) {
   203  	addrNoPrefix := testFreeAddr(t)
   204  
   205  	config := cfg.ResetTestRoot("node_priv_val_tcp_test")
   206  	defer os.RemoveAll(config.RootDir)
   207  	config.BaseConfig.PrivValidatorListenAddr = addrNoPrefix
   208  
   209  	_, err := DefaultNewNode(config, log.TestingLogger())
   210  	assert.Error(t, err)
   211  }
   212  
   213  func TestNodeSetPrivValIPC(t *testing.T) {
   214  	tmpfile := "/tmp/kms." + tmrand.Str(6) + ".sock"
   215  	defer os.Remove(tmpfile) // clean up
   216  
   217  	config := cfg.ResetTestRoot("node_priv_val_tcp_test")
   218  	defer os.RemoveAll(config.RootDir)
   219  	config.BaseConfig.PrivValidatorListenAddr = "unix://" + tmpfile
   220  
   221  	dialer := privval.DialUnixFn(tmpfile)
   222  	dialerEndpoint := privval.NewSignerDialerEndpoint(
   223  		log.TestingLogger(),
   224  		dialer,
   225  	)
   226  	privval.SignerDialerEndpointTimeoutReadWrite(100 * time.Millisecond)(dialerEndpoint)
   227  
   228  	pvsc := privval.NewSignerServer(
   229  		dialerEndpoint,
   230  		config.ChainID(),
   231  		types.NewMockPV(),
   232  	)
   233  
   234  	go func() {
   235  		err := pvsc.Start()
   236  		require.NoError(t, err)
   237  	}()
   238  	defer pvsc.Stop() //nolint:errcheck // ignore for tests
   239  
   240  	n, err := DefaultNewNode(config, log.TestingLogger())
   241  	require.NoError(t, err)
   242  	assert.IsType(t, &privval.RetrySignerClient{}, n.PrivValidator())
   243  }
   244  
   245  // testFreeAddr claims a free port so we don't block on listener being ready.
   246  func testFreeAddr(t *testing.T) string {
   247  	ln, err := net.Listen("tcp", "127.0.0.1:0")
   248  	require.NoError(t, err)
   249  	defer ln.Close()
   250  
   251  	return fmt.Sprintf("127.0.0.1:%d", ln.Addr().(*net.TCPAddr).Port)
   252  }
   253  
   254  // create a proposal block using real and full
   255  // mempool and evidence pool and validate it.
   256  func TestCreateProposalBlock(t *testing.T) {
   257  	config := cfg.ResetTestRoot("node_create_proposal")
   258  	defer os.RemoveAll(config.RootDir)
   259  	cc := proxy.NewLocalClientCreator(kvstore.NewApplication())
   260  	proxyApp := proxy.NewAppConns(cc)
   261  	err := proxyApp.Start()
   262  	require.Nil(t, err)
   263  	defer proxyApp.Stop() //nolint:errcheck // ignore for tests
   264  
   265  	logger := log.TestingLogger()
   266  
   267  	var height int64 = 1
   268  	state, stateDB, privVals := state(1, height)
   269  	stateStore := sm.NewStore(stateDB, sm.StoreOptions{
   270  		DiscardABCIResponses: false,
   271  	})
   272  	maxBytes := 16384
   273  	var partSize uint32 = 256
   274  	maxEvidenceBytes := int64(maxBytes / 2)
   275  	state.ConsensusParams.Block.MaxBytes = int64(maxBytes)
   276  	state.ConsensusParams.Evidence.MaxBytes = maxEvidenceBytes
   277  	proposerAddr, _ := state.Validators.GetByIndex(0)
   278  
   279  	// Make Mempool
   280  	memplMetrics := mempl.NopMetrics()
   281  	var mempool mempl.Mempool
   282  
   283  	switch config.Mempool.Version {
   284  	case cfg.MempoolV0:
   285  		mempool = mempoolv0.NewCListMempool(config.Mempool,
   286  			proxyApp.Mempool(),
   287  			state.LastBlockHeight,
   288  			mempoolv0.WithMetrics(memplMetrics),
   289  			mempoolv0.WithPreCheck(sm.TxPreCheck(state)),
   290  			mempoolv0.WithPostCheck(sm.TxPostCheck(state)))
   291  	case cfg.MempoolV1: // XXX Deprecated MempoolV1
   292  		panic("Deprecated MempoolV1")
   293  		/*
   294  			mempool = mempoolv1.NewTxMempool(logger,
   295  				config.Mempool,
   296  				proxyApp.Mempool(),
   297  				state.LastBlockHeight,
   298  				mempoolv1.WithMetrics(memplMetrics),
   299  				mempoolv1.WithPreCheck(sm.TxPreCheck(state)),
   300  				mempoolv1.WithPostCheck(sm.TxPostCheck(state)),
   301  			)
   302  		*/
   303  	}
   304  
   305  	// Make EvidencePool
   306  	evidenceDB := dbm.NewMemDB()
   307  	blockStore := store.NewBlockStore(dbm.NewMemDB())
   308  	evidencePool, err := evidence.NewPool(evidenceDB, stateStore, blockStore)
   309  	require.NoError(t, err)
   310  	evidencePool.SetLogger(logger)
   311  
   312  	// fill the evidence pool with more evidence
   313  	// than can fit in a block
   314  	var currentBytes int64
   315  	for currentBytes <= maxEvidenceBytes {
   316  		ev := types.NewMockDuplicateVoteEvidenceWithValidator(height, time.Now(), privVals[0], "test-chain")
   317  		currentBytes += int64(len(ev.Bytes()))
   318  		evidencePool.ReportConflictingVotes(ev.VoteA, ev.VoteB)
   319  	}
   320  
   321  	evList, size := evidencePool.PendingEvidence(state.ConsensusParams.Evidence.MaxBytes)
   322  	require.Less(t, size, state.ConsensusParams.Evidence.MaxBytes+1)
   323  	evData := &types.EvidenceData{Evidence: evList}
   324  	require.EqualValues(t, size, evData.ByteSize())
   325  
   326  	// fill the mempool with more txs
   327  	// than can fit in a block
   328  	txLength := 100
   329  	for i := 0; i <= maxBytes/txLength; i++ {
   330  		tx := tmrand.Bytes(txLength)
   331  		err := mempool.CheckTxSync(tx, nil, mempl.TxInfo{})
   332  		assert.NoError(t, err)
   333  	}
   334  
   335  	blockExec := sm.NewBlockExecutor(
   336  		stateStore,
   337  		logger,
   338  		proxyApp.Consensus(),
   339  		mempool,
   340  		evidencePool,
   341  	)
   342  
   343  	commit := types.NewCommit(height-1, 0, types.BlockID{}, nil)
   344  	message := state.MakeHashMessage(0)
   345  	proof, _ := privVals[0].GenerateVRFProof(message)
   346  	block, _ := blockExec.CreateProposalBlock(
   347  		height,
   348  		state, commit,
   349  		proposerAddr,
   350  		0,
   351  		proof,
   352  		0,
   353  	)
   354  
   355  	// check that the part set does not exceed the maximum block size
   356  	partSet := block.MakePartSet(partSize)
   357  	assert.Less(t, partSet.ByteSize(), int64(maxBytes))
   358  
   359  	partSetFromHeader := types.NewPartSetFromHeader(partSet.Header())
   360  	for partSetFromHeader.Count() < partSetFromHeader.Total() {
   361  		added, err := partSetFromHeader.AddPart(partSet.GetPart(int(partSetFromHeader.Count())))
   362  		require.NoError(t, err)
   363  		require.True(t, added)
   364  	}
   365  	assert.EqualValues(t, partSetFromHeader.ByteSize(), partSet.ByteSize())
   366  
   367  	err = blockExec.ValidateBlock(state, 0, block)
   368  	assert.NoError(t, err)
   369  }
   370  
   371  func TestMaxProposalBlockSize(t *testing.T) {
   372  	config := cfg.ResetTestRoot("node_create_proposal")
   373  	defer os.RemoveAll(config.RootDir)
   374  	cc := proxy.NewLocalClientCreator(kvstore.NewApplication())
   375  	proxyApp := proxy.NewAppConns(cc)
   376  	err := proxyApp.Start()
   377  	require.Nil(t, err)
   378  	defer proxyApp.Stop() //nolint:errcheck // ignore for tests
   379  
   380  	logger := log.TestingLogger()
   381  
   382  	var height int64 = 1
   383  	state, stateDB, privVals := state(1, height)
   384  	stateStore := sm.NewStore(stateDB, sm.StoreOptions{
   385  		DiscardABCIResponses: false,
   386  	})
   387  	var maxBytes int64 = 16384
   388  	var partSize uint32 = 256
   389  	state.ConsensusParams.Block.MaxBytes = maxBytes
   390  	proposerAddr, _ := state.Validators.GetByIndex(0)
   391  
   392  	// Make Mempool
   393  	memplMetrics := mempl.NopMetrics()
   394  	var mempool mempl.Mempool
   395  	switch config.Mempool.Version {
   396  	case cfg.MempoolV0:
   397  		mempool = mempoolv0.NewCListMempool(config.Mempool,
   398  			proxyApp.Mempool(),
   399  			state.LastBlockHeight,
   400  			mempoolv0.WithMetrics(memplMetrics),
   401  			mempoolv0.WithPreCheck(sm.TxPreCheck(state)),
   402  			mempoolv0.WithPostCheck(sm.TxPostCheck(state)))
   403  	case cfg.MempoolV1: // XXX Deprecated
   404  		/*
   405  			mempool = mempoolv1.NewTxMempool(logger,
   406  				config.Mempool,
   407  				proxyApp.Mempool(),
   408  				state.LastBlockHeight,
   409  				mempoolv1.WithMetrics(memplMetrics),
   410  				mempoolv1.WithPreCheck(sm.TxPreCheck(state)),
   411  				mempoolv1.WithPostCheck(sm.TxPostCheck(state)),
   412  			)
   413  		*/
   414  	}
   415  
   416  	// fill the mempool with one txs just below the maximum size
   417  	txLength := int(types.MaxDataBytesNoEvidence(maxBytes, 1))
   418  	tx := tmrand.Bytes(txLength - 4) // to account for the varint
   419  	err = mempool.CheckTxSync(tx, nil, mempl.TxInfo{})
   420  	assert.NoError(t, err)
   421  
   422  	blockExec := sm.NewBlockExecutor(
   423  		stateStore,
   424  		logger,
   425  		proxyApp.Consensus(),
   426  		mempool,
   427  		sm.EmptyEvidencePool{},
   428  	)
   429  
   430  	commit := types.NewCommit(height-1, 0, types.BlockID{}, nil)
   431  	message := state.MakeHashMessage(0)
   432  	proof, _ := privVals[0].GenerateVRFProof(message)
   433  	block, _ := blockExec.CreateProposalBlock(
   434  		height,
   435  		state, commit,
   436  		proposerAddr,
   437  		0,
   438  		proof,
   439  		0,
   440  	)
   441  
   442  	pb, err := block.ToProto()
   443  	require.NoError(t, err)
   444  	assert.Less(t, int64(pb.Size()), maxBytes)
   445  
   446  	// check that the part set does not exceed the maximum block size
   447  	partSet := block.MakePartSet(partSize)
   448  	assert.EqualValues(t, partSet.ByteSize(), int64(pb.Size()))
   449  }
   450  
   451  func TestNodeNewNodeCustomReactors(t *testing.T) {
   452  	config := cfg.ResetTestRoot("node_new_node_custom_reactors_test")
   453  	defer os.RemoveAll(config.RootDir)
   454  
   455  	cr := p2pmock.NewReactor()
   456  	cr.Channels = []*conn.ChannelDescriptor{
   457  		{
   458  			ID:                  byte(0x31),
   459  			Priority:            5,
   460  			SendQueueCapacity:   100,
   461  			RecvMessageCapacity: 100,
   462  		},
   463  	}
   464  	customBlockchainReactor := p2pmock.NewReactor()
   465  
   466  	nodeKey, err := p2p.LoadOrGenNodeKey(config.NodeKeyFile())
   467  	require.NoError(t, err)
   468  
   469  	n, err := NewNode(config,
   470  		privval.LoadOrGenFilePV(config.PrivValidatorKeyFile(), config.PrivValidatorStateFile()),
   471  		nodeKey,
   472  		proxy.DefaultClientCreator(config.ProxyApp, config.ABCI, config.DBDir()),
   473  		DefaultGenesisDocProviderFunc(config),
   474  		DefaultDBProvider,
   475  		DefaultMetricsProvider(config.Instrumentation),
   476  		log.TestingLogger(),
   477  		CustomReactors(map[string]p2p.Reactor{"FOO": cr, "BLOCKCHAIN": customBlockchainReactor}),
   478  	)
   479  	require.NoError(t, err)
   480  
   481  	err = n.Start()
   482  	require.NoError(t, err)
   483  	defer n.Stop() //nolint:errcheck // ignore for tests
   484  
   485  	assert.True(t, cr.IsRunning())
   486  	assert.Equal(t, cr, n.Switch().Reactor("FOO"))
   487  
   488  	assert.True(t, customBlockchainReactor.IsRunning())
   489  	assert.Equal(t, customBlockchainReactor, n.Switch().Reactor("BLOCKCHAIN"))
   490  
   491  	channels := n.NodeInfo().(p2p.DefaultNodeInfo).Channels
   492  	assert.Contains(t, channels, mempl.MempoolChannel)
   493  	assert.Contains(t, channels, cr.Channels[0].ID)
   494  }
   495  
   496  func TestNodeNewNodeTxIndexIndexer(t *testing.T) {
   497  	config := cfg.ResetTestRoot("node_new_node_tx_index_indexer_test")
   498  	defer os.RemoveAll(config.RootDir)
   499  
   500  	doTest := func(doProvider func(ctx *DBContext) (dbm.DB, error)) (*Node, error) {
   501  		nodeKey, err := p2p.LoadOrGenNodeKey(config.NodeKeyFile())
   502  		require.NoError(t, err)
   503  
   504  		return NewNode(config,
   505  			privval.LoadOrGenFilePV(config.PrivValidatorKeyFile(), config.PrivValidatorStateFile()),
   506  			nodeKey,
   507  			proxy.DefaultClientCreator(config.ProxyApp, config.ABCI, config.DBDir()),
   508  			DefaultGenesisDocProviderFunc(config),
   509  			doProvider,
   510  			DefaultMetricsProvider(config.Instrumentation),
   511  			log.TestingLogger(),
   512  		)
   513  	}
   514  
   515  	{
   516  		// Change to panic-provider for test
   517  		n, err := doTest(func(ctx *DBContext) (dbm.DB, error) { return nil, fmt.Errorf("test error") })
   518  		require.Error(t, err)
   519  		require.Nil(t, n)
   520  	}
   521  	{
   522  		// Change to non-default-value for test
   523  		config.TxIndex.Indexer = ""
   524  		n, err := doTest(DefaultDBProvider)
   525  		require.NoError(t, err)
   526  		require.NotNil(t, n)
   527  	}
   528  	{
   529  		// Change to psql for test
   530  		config.TxIndex.Indexer = "psql"
   531  		n, err := doTest(DefaultDBProvider)
   532  		require.Error(t, err)
   533  		require.Equal(t, "no psql-conn is set for the \"psql\" indexer", err.Error())
   534  		require.Nil(t, n)
   535  
   536  		// config.TxIndex.PsqlConn = "cannot test with no-import postgres driver"
   537  		// n, err = doTest(DefaultDBProvider)
   538  		// require.Error(t, err)
   539  		// require.Equal(t, "creating psql indexer: sql: unknown driver \"postgres\" (forgotten import?)", err.Error())
   540  		// require.Nil(t, n)
   541  
   542  		config.TxIndex.PsqlConn = makeTestPsqlConn(t)
   543  		n, err = doTest(DefaultDBProvider)
   544  		require.NoError(t, err)
   545  		require.NotNil(t, n)
   546  	}
   547  }
   548  
   549  func makeTestPsqlConn(t *testing.T) string {
   550  	user := "postgres"
   551  	password := "secret"
   552  	port := "5432"
   553  	dsn := "postgres://%s:%s@localhost:%s/%s?sslmode=disable"
   554  	dbName := "postgres"
   555  
   556  	pool, err := dockertest.NewPool(os.Getenv("DOCKER_URL"))
   557  	if err != nil {
   558  		require.NoError(t, err)
   559  	}
   560  	resource, err := pool.RunWithOptions(&dockertest.RunOptions{
   561  		Repository: "postgres",
   562  		Tag:        "13",
   563  		Env: []string{
   564  			"POSTGRES_USER=" + user,
   565  			"POSTGRES_PASSWORD=" + password,
   566  			"POSTGRES_DB=" + dbName,
   567  			"listen_addresses = '*'",
   568  		},
   569  		ExposedPorts: []string{port},
   570  	}, func(config *docker.HostConfig) {
   571  		// set AutoRemove to true so that stopped container goes away by itself
   572  		config.AutoRemove = true
   573  		config.RestartPolicy = docker.RestartPolicy{
   574  			Name: "no",
   575  		}
   576  	})
   577  	if err != nil {
   578  		require.NoError(t, err)
   579  	}
   580  	return fmt.Sprintf(dsn, user, password, resource.GetPort(port+"/tcp"), dbName)
   581  }
   582  
   583  func state(nVals int, height int64) (sm.State, dbm.DB, []types.PrivValidator) {
   584  	privVals := make([]types.PrivValidator, nVals)
   585  	vals := make([]types.GenesisValidator, nVals)
   586  	for i := 0; i < nVals; i++ {
   587  		secret := []byte(fmt.Sprintf("test%d", i))
   588  		pk := ed25519.GenPrivKeyFromSecret(secret)
   589  		privVal := types.NewMockPVWithParams(pk, false, false)
   590  		privVals[i] = privVal
   591  		vals[i] = types.GenesisValidator{
   592  			Address: privVal.PrivKey.PubKey().Address(),
   593  			PubKey:  privVal.PrivKey.PubKey(),
   594  			Power:   1000,
   595  			Name:    fmt.Sprintf("test%d", i),
   596  		}
   597  	}
   598  	s, _ := sm.MakeGenesisState(&types.GenesisDoc{
   599  		ChainID:    "test-chain",
   600  		Validators: vals,
   601  		AppHash:    nil,
   602  	})
   603  
   604  	// save validators to db for 2 heights
   605  	stateDB := dbm.NewMemDB()
   606  	stateStore := sm.NewStore(stateDB, sm.StoreOptions{
   607  		DiscardABCIResponses: false,
   608  	})
   609  	if err := stateStore.Save(s); err != nil {
   610  		panic(err)
   611  	}
   612  
   613  	for i := 1; i < int(height); i++ {
   614  		s.LastBlockHeight++
   615  		s.LastValidators = s.Validators.Copy()
   616  		if err := stateStore.Save(s); err != nil {
   617  			panic(err)
   618  		}
   619  	}
   620  	return s, stateDB, privVals
   621  }
   622  
   623  func TestNodeInvalidNodeInfoCustomReactors(t *testing.T) {
   624  	config := cfg.ResetTestRoot("node_new_node_custom_reactors_test")
   625  	defer os.RemoveAll(config.RootDir)
   626  
   627  	cr := p2pmock.NewReactor()
   628  	cr.Channels = []*conn.ChannelDescriptor{
   629  		{
   630  			ID:                  byte(0x31),
   631  			Priority:            5,
   632  			SendQueueCapacity:   100,
   633  			RecvMessageCapacity: 100,
   634  		},
   635  	}
   636  	customBlockchainReactor := p2pmock.NewReactor()
   637  
   638  	nodeKey, err := p2p.LoadOrGenNodeKey(config.NodeKeyFile())
   639  	require.NoError(t, err)
   640  
   641  	_, err = NewInvalidNode(config,
   642  		privval.LoadOrGenFilePV(config.PrivValidatorKeyFile(), config.PrivValidatorStateFile()),
   643  		nodeKey,
   644  		proxy.DefaultClientCreator(config.ProxyApp, config.ABCI, config.DBDir()),
   645  		DefaultGenesisDocProviderFunc(config),
   646  		DefaultDBProvider,
   647  		DefaultMetricsProvider(config.Instrumentation),
   648  		log.TestingLogger(),
   649  		CustomReactors(map[string]p2p.Reactor{"FOO": cr, "BLOCKCHAIN": customBlockchainReactor}),
   650  	)
   651  	require.NoError(t, err)
   652  }
   653  
   654  func TestSaveAndLoadBigGensisFile(t *testing.T) {
   655  	stateDB, err := dbm.NewGoLevelDB("state", os.TempDir())
   656  	require.NoError(t, err)
   657  	config := cfg.ResetTestRoot("node_big_genesis_test")
   658  	defer os.RemoveAll(config.RootDir)
   659  	n, err := DefaultNewNode(config, log.TestingLogger())
   660  	require.NoError(t, err)
   661  	newChainID := strings.Repeat("a", 200000000) // about 200MB
   662  	n.genesisDoc.ChainID = newChainID
   663  	err = saveGenesisDoc(stateDB, n.genesisDoc)
   664  	require.NoError(t, err)
   665  	g, err := loadGenesisDoc(stateDB)
   666  	require.NoError(t, err)
   667  	require.Equal(t, newChainID, g.ChainID)
   668  	stateDB.Close()
   669  }
   670  
   671  func NewInvalidNode(config *cfg.Config,
   672  	privValidator types.PrivValidator,
   673  	nodeKey *p2p.NodeKey,
   674  	clientCreator proxy.ClientCreator,
   675  	genesisDocProvider GenesisDocProvider,
   676  	dbProvider DBProvider,
   677  	metricsProvider MetricsProvider,
   678  	logger log.Logger,
   679  	options ...Option) (*Node, error) {
   680  	n, err := NewNode(config,
   681  		privValidator,
   682  		nodeKey,
   683  		clientCreator,
   684  		genesisDocProvider,
   685  		dbProvider,
   686  		metricsProvider,
   687  		logger,
   688  	)
   689  	if err != nil {
   690  		return nil, err
   691  	}
   692  
   693  	transport, _ := createTransport(config, &p2pmocks.NodeInfo{}, nodeKey, n.proxyApp)
   694  	n.transport = transport
   695  
   696  	for _, option := range options {
   697  		option(n)
   698  	}
   699  
   700  	return n, nil
   701  }