gitlab.com/SiaPrime/SiaPrime@v1.4.1/modules/explorer/info_test.go (about) 1 package explorer 2 3 import ( 4 "testing" 5 6 "gitlab.com/NebulousLabs/fastrand" 7 "gitlab.com/SiaPrime/SiaPrime/crypto" 8 "gitlab.com/SiaPrime/SiaPrime/types" 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, err := et.wallet.StartTransaction() 91 if err != nil { 92 t.Fatal(err) 93 } 94 payout := types.NewCurrency64(1e9) 95 err = builder.FundSiacoins(payout) 96 if err != nil { 97 t.Fatal(err) 98 } 99 100 windowStart := et.cs.Height() + 2 101 windowEnd := et.cs.Height() + 5 102 103 fc := types.FileContract{ 104 WindowStart: windowStart, 105 WindowEnd: windowEnd, 106 Payout: payout, 107 ValidProofOutputs: []types.SiacoinOutput{{Value: types.PostTax(et.cs.Height(), payout)}}, 108 MissedProofOutputs: []types.SiacoinOutput{{Value: types.PostTax(et.cs.Height(), payout)}}, 109 UnlockHash: types.UnlockConditions{}.UnlockHash(), 110 } 111 112 fcIndex := builder.AddFileContract(fc) 113 tSet, err := builder.Sign(true) 114 if err != nil { 115 t.Fatal(err) 116 } 117 118 if err != nil { 119 t.Fatal(err) 120 } 121 122 err = et.tpool.AcceptTransactionSet(tSet) 123 if err != nil { 124 t.Fatal(err) 125 } 126 127 // Mine until contract payout is in consensus 128 for i := et.cs.Height(); i < windowEnd+types.MaturityDelay; i++ { 129 _, err := et.miner.AddBlock() 130 if err != nil { 131 t.Fatal(err) 132 } 133 } 134 135 ti := len(tSet) - 1 136 fcid := tSet[ti].FileContractID(fcIndex) 137 txns := et.explorer.FileContractID(fcid) 138 if len(txns) == 0 { 139 t.Error("Filecontract ID does not appear in blockchain") 140 } 141 142 outputs, err := et.explorer.FileContractPayouts(fcid) 143 if err != nil { 144 t.Fatal(err) 145 } 146 147 // Check if MissedProofOutputs were added to spendable outputs 148 if len(outputs) != len(fc.MissedProofOutputs) { 149 t.Error("Incorrect number of outputs returned") 150 t.Error("Expecting -> ", len(fc.MissedProofOutputs)) 151 t.Error("But was -> ", len(outputs)) 152 } 153 } 154 155 func TestFileContractsPayoutValidProof(t *testing.T) { 156 if testing.Short() { 157 t.SkipNow() 158 } 159 160 et, err := createExplorerTester(t.Name()) 161 if err != nil { 162 t.Fatal(err) 163 } 164 165 // COMPATv0.4.0 - Step the block height up past the hardfork amount. This 166 // code stops nondeterministic failures when producing storage proofs that 167 // is related to buggy old code. 168 for et.cs.Height() <= 10 { 169 _, err := et.miner.AddBlock() 170 if err != nil { 171 t.Fatal(err) 172 } 173 } 174 175 // Create a file (as a bytes.Buffer) that will be used for the file 176 // contract. 177 filesize := uint64(4e3) 178 file := fastrand.Bytes(int(filesize)) 179 merkleRoot := crypto.MerkleRoot(file) 180 181 // Create a funded file contract 182 payout := types.NewCurrency64(400e6) 183 fc := types.FileContract{ 184 FileSize: filesize, 185 FileMerkleRoot: merkleRoot, 186 WindowStart: et.cs.Height() + 1, 187 WindowEnd: et.cs.Height() + 2, 188 Payout: payout, 189 ValidProofOutputs: []types.SiacoinOutput{{Value: types.PostTax(et.cs.Height(), payout)}}, 190 MissedProofOutputs: []types.SiacoinOutput{{Value: types.PostTax(et.cs.Height(), payout)}}, 191 } 192 193 // Submit a transaction with the file contract. 194 //oldSiafundPool := cst.cs.dbGetSiafundPool() 195 builder, err := et.wallet.StartTransaction() 196 if err != nil { 197 t.Fatal(err) 198 } 199 err = builder.FundSiacoins(payout) 200 if err != nil { 201 t.Fatal(err) 202 } 203 204 fcIndex := builder.AddFileContract(fc) 205 tSet, err := builder.Sign(true) 206 if err != nil { 207 t.Fatal(err) 208 } 209 210 err = et.tpool.AcceptTransactionSet(tSet) 211 if err != nil { 212 t.Fatal(err) 213 } 214 _, err = et.miner.AddBlock() 215 if err != nil { 216 t.Fatal(err) 217 } 218 219 ti := len(tSet) - 1 220 fcid := tSet[ti].FileContractID(fcIndex) 221 222 // Create and submit a storage proof for the file contract. 223 segmentIndex, err := et.cs.StorageProofSegment(fcid) 224 if err != nil { 225 t.Fatal(err) 226 } 227 segment, hashSet := crypto.MerkleProof(file, segmentIndex) 228 sp := types.StorageProof{ 229 ParentID: fcid, 230 HashSet: hashSet, 231 } 232 copy(sp.Segment[:], segment) 233 builder, err = et.wallet.StartTransaction() 234 if err != nil { 235 t.Fatal(err) 236 } 237 builder.AddStorageProof(sp) 238 tSet, err = builder.Sign(true) 239 if err != nil { 240 t.Fatal(err) 241 } 242 err = et.tpool.AcceptTransactionSet(tSet) 243 if err != nil { 244 t.Fatal(err) 245 } 246 247 // Mine until contract payout is in consensus 248 for i := types.BlockHeight(0); i < types.MaturityDelay+1; i++ { 249 _, err := et.miner.AddBlock() 250 if err != nil { 251 t.Fatal(err) 252 } 253 } 254 255 txns := et.explorer.FileContractID(fcid) 256 if len(txns) == 0 { 257 t.Error("Filecontract ID does not appear in blockchain") 258 } 259 260 // Check that the storageproof was added to the explorer after 261 // the filecontract was removed from the consensus set 262 outputs, err := et.explorer.FileContractPayouts(fcid) 263 if err != nil { 264 t.Fatal(err) 265 } 266 267 if len(outputs) != len(fc.ValidProofOutputs) { 268 t.Errorf("expected %v, got %v ", fc.MissedProofOutputs, outputs) 269 } 270 }