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 }