github.com/Synthesix/Sia@v1.3.3-0.20180413141344-f863baeed3ca/modules/explorer/info_test.go (about) 1 package explorer 2 3 import ( 4 "testing" 5 6 "github.com/Synthesix/Sia/crypto" 7 "github.com/Synthesix/Sia/types" 8 "github.com/NebulousLabs/fastrand" 9 ) 10 11 // TestImmediateBlockFacts grabs the block facts object from the block explorer 12 // at the current height and verifies that the data has been filled out. 13 func TestImmediateBlockFacts(t *testing.T) { 14 if testing.Short() { 15 t.SkipNow() 16 } 17 et, err := createExplorerTester(t.Name()) 18 if err != nil { 19 t.Fatal(err) 20 } 21 22 facts := et.explorer.LatestBlockFacts() 23 var explorerHeight types.BlockHeight 24 err = et.explorer.db.View(dbGetInternal(internalBlockHeight, &explorerHeight)) 25 if err != nil { 26 t.Fatal(err) 27 } 28 if facts.Height != explorerHeight || explorerHeight == 0 { 29 t.Error("wrong height reported in facts object") 30 } 31 if !facts.TotalCoins.Equals(types.CalculateNumSiacoins(et.cs.Height())) { 32 t.Error("wrong number of total coins:", facts.TotalCoins, et.cs.Height()) 33 } 34 } 35 36 // TestBlock probes the Block function of the explorer. 37 func TestBlock(t *testing.T) { 38 if testing.Short() { 39 t.SkipNow() 40 } 41 et, err := createExplorerTester(t.Name()) 42 if err != nil { 43 t.Fatal(err) 44 } 45 46 gb := types.GenesisBlock 47 gbFetch, height, exists := et.explorer.Block(gb.ID()) 48 if !exists || height != 0 || gbFetch.ID() != gb.ID() { 49 t.Error("call to 'Block' inside explorer failed") 50 } 51 } 52 53 // TestBlockFacts checks that the correct block facts are returned for a query. 54 func TestBlockFacts(t *testing.T) { 55 if testing.Short() { 56 t.SkipNow() 57 } 58 et, err := createExplorerTester(t.Name()) 59 if err != nil { 60 t.Fatal(err) 61 } 62 63 gb := types.GenesisBlock 64 bf, exists := et.explorer.BlockFacts(0) 65 if !exists || bf.BlockID != gb.ID() || bf.Height != 0 { 66 t.Error("call to 'BlockFacts' inside explorer failed") 67 t.Error("Expecting true ->", exists) 68 t.Error("Expecting", gb.ID(), "->", bf.BlockID) 69 t.Error("Expecting 0 ->", bf.Height) 70 } 71 72 bf, exists = et.explorer.BlockFacts(1) 73 if !exists || bf.Height != 1 { 74 t.Error("call to 'BlockFacts' has failed") 75 } 76 } 77 78 // TestFileContractPayouts checks that file contract outputs are tracked by the explorer 79 func TestFileContractPayoutsMissingProof(t *testing.T) { 80 if testing.Short() { 81 t.SkipNow() 82 } 83 84 et, err := createExplorerTester(t.Name()) 85 if err != nil { 86 t.Fatal(err) 87 } 88 89 // Create and fund valid file contracts. 90 builder := et.wallet.StartTransaction() 91 payout := types.NewCurrency64(1e9) 92 err = builder.FundSiacoins(payout) 93 if err != nil { 94 t.Fatal(err) 95 } 96 97 windowStart := et.cs.Height() + 2 98 windowEnd := et.cs.Height() + 5 99 100 fc := types.FileContract{ 101 WindowStart: windowStart, 102 WindowEnd: windowEnd, 103 Payout: payout, 104 ValidProofOutputs: []types.SiacoinOutput{{Value: types.PostTax(et.cs.Height(), payout)}}, 105 MissedProofOutputs: []types.SiacoinOutput{{Value: types.PostTax(et.cs.Height(), payout)}}, 106 UnlockHash: types.UnlockConditions{}.UnlockHash(), 107 } 108 109 fcIndex := builder.AddFileContract(fc) 110 tSet, err := builder.Sign(true) 111 if err != nil { 112 t.Fatal(err) 113 } 114 115 if err != nil { 116 t.Fatal(err) 117 } 118 119 err = et.tpool.AcceptTransactionSet(tSet) 120 if err != nil { 121 t.Fatal(err) 122 } 123 124 // Mine until contract payout is in consensus 125 for i := et.cs.Height(); i < windowEnd+types.MaturityDelay; i++ { 126 _, err := et.miner.AddBlock() 127 if err != nil { 128 t.Fatal(err) 129 } 130 } 131 132 ti := len(tSet) - 1 133 fcid := tSet[ti].FileContractID(fcIndex) 134 txns := et.explorer.FileContractID(fcid) 135 if len(txns) == 0 { 136 t.Error("Filecontract ID does not appear in blockchain") 137 } 138 139 outputs, err := et.explorer.FileContractPayouts(fcid) 140 if err != nil { 141 t.Fatal(err) 142 } 143 144 // Check if MissedProofOutputs were added to spendable outputs 145 if len(outputs) != len(fc.MissedProofOutputs) { 146 t.Error("Incorrect number of outputs returned") 147 t.Error("Expecting -> ", len(fc.MissedProofOutputs)) 148 t.Error("But was -> ", len(outputs)) 149 } 150 } 151 152 func TestFileContractsPayoutValidProof(t *testing.T) { 153 if testing.Short() { 154 t.SkipNow() 155 } 156 157 et, err := createExplorerTester(t.Name()) 158 if err != nil { 159 t.Fatal(err) 160 } 161 162 // COMPATv0.4.0 - Step the block height up past the hardfork amount. This 163 // code stops nondeterministic failures when producing storage proofs that 164 // is related to buggy old code. 165 for et.cs.Height() <= 10 { 166 _, err := et.miner.AddBlock() 167 if err != nil { 168 t.Fatal(err) 169 } 170 } 171 172 // Create a file (as a bytes.Buffer) that will be used for the file 173 // contract. 174 filesize := uint64(4e3) 175 file := fastrand.Bytes(int(filesize)) 176 merkleRoot := crypto.MerkleRoot(file) 177 178 // Create a funded file contract 179 payout := types.NewCurrency64(400e6) 180 fc := types.FileContract{ 181 FileSize: filesize, 182 FileMerkleRoot: merkleRoot, 183 WindowStart: et.cs.Height() + 1, 184 WindowEnd: et.cs.Height() + 2, 185 Payout: payout, 186 ValidProofOutputs: []types.SiacoinOutput{{Value: types.PostTax(et.cs.Height(), payout)}}, 187 MissedProofOutputs: []types.SiacoinOutput{{Value: types.PostTax(et.cs.Height(), payout)}}, 188 } 189 190 // Submit a transaction with the file contract. 191 //oldSiafundPool := cst.cs.dbGetSiafundPool() 192 builder := et.wallet.StartTransaction() 193 err = builder.FundSiacoins(payout) 194 if err != nil { 195 t.Fatal(err) 196 } 197 198 fcIndex := builder.AddFileContract(fc) 199 tSet, err := builder.Sign(true) 200 if err != nil { 201 t.Fatal(err) 202 } 203 204 err = et.tpool.AcceptTransactionSet(tSet) 205 if err != nil { 206 t.Fatal(err) 207 } 208 _, err = et.miner.AddBlock() 209 if err != nil { 210 t.Fatal(err) 211 } 212 213 ti := len(tSet) - 1 214 fcid := tSet[ti].FileContractID(fcIndex) 215 216 // Create and submit a storage proof for the file contract. 217 segmentIndex, err := et.cs.StorageProofSegment(fcid) 218 if err != nil { 219 t.Fatal(err) 220 } 221 segment, hashSet := crypto.MerkleProof(file, segmentIndex) 222 sp := types.StorageProof{ 223 ParentID: fcid, 224 HashSet: hashSet, 225 } 226 copy(sp.Segment[:], segment) 227 builder = et.wallet.StartTransaction() 228 builder.AddStorageProof(sp) 229 tSet, err = builder.Sign(true) 230 if err != nil { 231 t.Fatal(err) 232 } 233 err = et.tpool.AcceptTransactionSet(tSet) 234 if err != nil { 235 t.Fatal(err) 236 } 237 238 // Mine until contract payout is in consensus 239 for i := types.BlockHeight(0); i < types.MaturityDelay+1; i++ { 240 _, err := et.miner.AddBlock() 241 if err != nil { 242 t.Fatal(err) 243 } 244 } 245 246 txns := et.explorer.FileContractID(fcid) 247 if len(txns) == 0 { 248 t.Error("Filecontract ID does not appear in blockchain") 249 } 250 251 // Check that the storageproof was added to the explorer after 252 // the filecontract was removed from the consensus set 253 outputs, err := et.explorer.FileContractPayouts(fcid) 254 if err != nil { 255 t.Fatal(err) 256 } 257 258 if len(outputs) != len(fc.ValidProofOutputs) { 259 t.Errorf("expected %v, got %v ", fc.MissedProofOutputs, outputs) 260 } 261 }