gitlab.com/jokerrs1/Sia@v1.3.2/modules/consensus/consensusset_test.go (about)

     1  package consensus
     2  
     3  import (
     4  	"path/filepath"
     5  	"testing"
     6  
     7  	"github.com/NebulousLabs/Sia/build"
     8  	"github.com/NebulousLabs/Sia/crypto"
     9  	"github.com/NebulousLabs/Sia/modules"
    10  	"github.com/NebulousLabs/Sia/modules/gateway"
    11  	"github.com/NebulousLabs/Sia/modules/miner"
    12  	"github.com/NebulousLabs/Sia/modules/transactionpool"
    13  	"github.com/NebulousLabs/Sia/modules/wallet"
    14  	"github.com/NebulousLabs/Sia/types"
    15  	"github.com/NebulousLabs/fastrand"
    16  )
    17  
    18  // A consensusSetTester is the helper object for consensus set testing,
    19  // including helper modules and methods for controlling synchronization between
    20  // the tester and the modules.
    21  type consensusSetTester struct {
    22  	gateway   modules.Gateway
    23  	miner     modules.TestMiner
    24  	tpool     modules.TransactionPool
    25  	wallet    modules.Wallet
    26  	walletKey crypto.TwofishKey
    27  
    28  	cs *ConsensusSet
    29  
    30  	persistDir string
    31  }
    32  
    33  // randAddress returns a random address that is not spendable.
    34  func randAddress() (uh types.UnlockHash) {
    35  	fastrand.Read(uh[:])
    36  	return
    37  }
    38  
    39  // addSiafunds makes a transaction that moves some testing genesis siafunds
    40  // into the wallet.
    41  func (cst *consensusSetTester) addSiafunds() {
    42  	// Get an address to receive the siafunds.
    43  	uc, err := cst.wallet.NextAddress()
    44  	if err != nil {
    45  		panic(err)
    46  	}
    47  
    48  	// Create the transaction that sends the anyone-can-spend siafund output to
    49  	// the wallet address (output only available during testing).
    50  	txn := types.Transaction{
    51  		SiafundInputs: []types.SiafundInput{{
    52  			ParentID:         cst.cs.blockRoot.Block.Transactions[0].SiafundOutputID(2),
    53  			UnlockConditions: types.UnlockConditions{},
    54  		}},
    55  		SiafundOutputs: []types.SiafundOutput{{
    56  			Value:      types.NewCurrency64(1e3),
    57  			UnlockHash: uc.UnlockHash(),
    58  		}},
    59  	}
    60  
    61  	// Mine the transaction into the blockchain.
    62  	err = cst.tpool.AcceptTransactionSet([]types.Transaction{txn})
    63  	if err != nil {
    64  		panic(err)
    65  	}
    66  	_, err = cst.miner.AddBlock()
    67  	if err != nil {
    68  		panic(err)
    69  	}
    70  
    71  	// Check that the siafunds made it to the wallet.
    72  	_, siafundBalance, _ := cst.wallet.ConfirmedBalance()
    73  	if !siafundBalance.Equals64(1e3) {
    74  		panic("wallet does not have the siafunds")
    75  	}
    76  }
    77  
    78  // mineCoins mines blocks until there are siacoins in the wallet.
    79  func (cst *consensusSetTester) mineSiacoins() {
    80  	for i := types.BlockHeight(0); i <= types.MaturityDelay; i++ {
    81  		b, _ := cst.miner.FindBlock()
    82  		err := cst.cs.AcceptBlock(b)
    83  		if err != nil {
    84  			panic(err)
    85  		}
    86  	}
    87  }
    88  
    89  // blankConsensusSetTester creates a consensusSetTester that has only the
    90  // genesis block.
    91  func blankConsensusSetTester(name string) (*consensusSetTester, error) {
    92  	testdir := build.TempDir(modules.ConsensusDir, name)
    93  
    94  	// Create modules.
    95  	g, err := gateway.New("localhost:0", false, filepath.Join(testdir, modules.GatewayDir))
    96  	if err != nil {
    97  		return nil, err
    98  	}
    99  	cs, err := New(g, false, filepath.Join(testdir, modules.ConsensusDir))
   100  	if err != nil {
   101  		return nil, err
   102  	}
   103  	tp, err := transactionpool.New(cs, g, filepath.Join(testdir, modules.ConsensusDir))
   104  	if err != nil {
   105  		return nil, err
   106  	}
   107  	w, err := wallet.New(cs, tp, filepath.Join(testdir, modules.WalletDir))
   108  	if err != nil {
   109  		return nil, err
   110  	}
   111  	key := crypto.GenerateTwofishKey()
   112  	_, err = w.Encrypt(key)
   113  	if err != nil {
   114  		return nil, err
   115  	}
   116  	err = w.Unlock(key)
   117  	if err != nil {
   118  		return nil, err
   119  	}
   120  	m, err := miner.New(cs, tp, w, filepath.Join(testdir, modules.MinerDir))
   121  	if err != nil {
   122  		return nil, err
   123  	}
   124  
   125  	// Assemble all objects into a consensusSetTester.
   126  	cst := &consensusSetTester{
   127  		gateway:   g,
   128  		miner:     m,
   129  		tpool:     tp,
   130  		wallet:    w,
   131  		walletKey: key,
   132  
   133  		cs: cs,
   134  
   135  		persistDir: testdir,
   136  	}
   137  	return cst, nil
   138  }
   139  
   140  // createConsensusSetTester creates a consensusSetTester that's ready for use,
   141  // including siacoins and siafunds available in the wallet.
   142  func createConsensusSetTester(name string) (*consensusSetTester, error) {
   143  	cst, err := blankConsensusSetTester(name)
   144  	if err != nil {
   145  		return nil, err
   146  	}
   147  	cst.addSiafunds()
   148  	cst.mineSiacoins()
   149  	return cst, nil
   150  }
   151  
   152  // Close safely closes the consensus set tester. Because there's not a good way
   153  // to errcheck when deferring a close, a panic is called in the event of an
   154  // error.
   155  func (cst *consensusSetTester) Close() error {
   156  	errs := []error{
   157  		cst.cs.Close(),
   158  		cst.gateway.Close(),
   159  		cst.miner.Close(),
   160  	}
   161  	if err := build.JoinErrors(errs, "; "); err != nil {
   162  		panic(err)
   163  	}
   164  	return nil
   165  }
   166  
   167  // TestNilInputs tries to create new consensus set modules using nil inputs.
   168  func TestNilInputs(t *testing.T) {
   169  	if testing.Short() {
   170  		t.SkipNow()
   171  	}
   172  	t.Parallel()
   173  	testdir := build.TempDir(modules.ConsensusDir, t.Name())
   174  	_, err := New(nil, false, testdir)
   175  	if err != errNilGateway {
   176  		t.Fatal(err)
   177  	}
   178  }
   179  
   180  // TestClosing tries to close a consenuss set.
   181  func TestDatabaseClosing(t *testing.T) {
   182  	if testing.Short() {
   183  		t.SkipNow()
   184  	}
   185  	t.Parallel()
   186  	testdir := build.TempDir(modules.ConsensusDir, t.Name())
   187  
   188  	// Create the gateway.
   189  	g, err := gateway.New("localhost:0", false, filepath.Join(testdir, modules.GatewayDir))
   190  	if err != nil {
   191  		t.Fatal(err)
   192  	}
   193  	cs, err := New(g, false, testdir)
   194  	if err != nil {
   195  		t.Fatal(err)
   196  	}
   197  	err = cs.Close()
   198  	if err != nil {
   199  		t.Error(err)
   200  	}
   201  }