gitlab.com/jokerrs1/Sia@v1.3.2/modules/miner/blockmanager_test.go (about) 1 package miner 2 3 import ( 4 "bytes" 5 "testing" 6 7 "github.com/NebulousLabs/Sia/crypto" 8 "github.com/NebulousLabs/Sia/modules" 9 "github.com/NebulousLabs/Sia/types" 10 "github.com/NebulousLabs/fastrand" 11 ) 12 13 // solveHeader takes a block header as input and returns a solved block header 14 // as output. 15 func solveHeader(header types.BlockHeader, target types.Target) types.BlockHeader { 16 // Solve the header. 17 for { 18 // Increment the nonce first to guarantee that a new header is formed 19 // - this helps check for pointer errors. 20 header.Nonce[0]++ 21 id := crypto.HashObject(header) 22 if bytes.Compare(target[:], id[:]) >= 0 { 23 break 24 } 25 } 26 return header 27 } 28 29 // TestIntegrationHeaderForWork checks that header requesting, solving, and 30 // submitting naively works. 31 func TestIntegrationHeaderForWork(t *testing.T) { 32 if testing.Short() { 33 t.SkipNow() 34 } 35 mt, err := createMinerTester(t.Name()) 36 if err != nil { 37 t.Fatal(err) 38 } 39 40 // Get a header and solve it. 41 header, target, err := mt.miner.HeaderForWork() 42 if err != nil { 43 t.Fatal(err) 44 } 45 solvedHeader := solveHeader(header, target) 46 // Sanity check - header and solvedHeader should be different. (within the 47 // testing file, 'header' should always have a nonce of '0' and 48 // solvedHeader should never have a nonce of '0'.) 49 if header.Nonce == solvedHeader.Nonce { 50 t.Fatal("nonce memory is not independent") 51 } 52 53 // Submit the header. 54 err = mt.miner.SubmitHeader(solvedHeader) 55 if err != nil { 56 t.Fatal(err) 57 } 58 } 59 60 // TestIntegrationHeaderForWorkUpdates checks that HeaderForWork starts 61 // returning headers on the new block after a block has been submitted to the 62 // consensus set. 63 func TestIntegrationHeaderForWorkUpdates(t *testing.T) { 64 if testing.Short() { 65 t.SkipNow() 66 } 67 mt, err := createMinerTester(t.Name()) 68 if err != nil { 69 t.Fatal(err) 70 } 71 72 // Get a header to advance into the header memory. 73 _, _, err = mt.miner.HeaderForWork() 74 if err != nil { 75 t.Fatal(err) 76 } 77 78 // Submit a block, which should trigger a header change. 79 _, err = mt.miner.AddBlock() 80 if err != nil { 81 t.Fatal(err) 82 } 83 84 // Get a header to grind on. 85 header, target, err := mt.miner.HeaderForWork() 86 if err != nil { 87 t.Fatal(err) 88 } 89 solvedHeader := solveHeader(header, target) 90 91 // Submit the header. 92 err = mt.miner.SubmitHeader(solvedHeader) 93 if err != nil { 94 t.Fatal(err) 95 } 96 if !mt.cs.InCurrentPath(types.BlockID(crypto.HashObject(solvedHeader))) { 97 t.Error("header from solved block is not in the current path") 98 } 99 } 100 101 // TestIntegrationManyHeaders checks that requesting a full set of headers in a 102 // row results in all unique headers, and that all of them can be reassembled 103 // into valid blocks. 104 func TestIntegrationManyHeaders(t *testing.T) { 105 if testing.Short() { 106 t.SkipNow() 107 } 108 mt, err := createMinerTester(t.Name()) 109 if err != nil { 110 t.Fatal(err) 111 } 112 113 // Create a suite of headers for imaginary parallel mining. 114 solvedHeaders := make([]types.BlockHeader, HeaderMemory/BlockMemory*2) 115 for i := range solvedHeaders { 116 header, target, err := mt.miner.HeaderForWork() 117 if err != nil { 118 t.Fatal(err) 119 } 120 solvedHeaders[i] = solveHeader(header, target) 121 } 122 123 // Submit the headers randomly and make sure they are all considered valid. 124 for _, selection := range fastrand.Perm(len(solvedHeaders)) { 125 err = mt.miner.SubmitHeader(solvedHeaders[selection]) 126 if err != nil && err != modules.ErrNonExtendingBlock { 127 t.Error(err) 128 } 129 } 130 } 131 132 // TestIntegrationHeaderBlockOverflow triggers a header overflow by requesting 133 // a block that triggers the overflow. 134 func TestIntegrationHeaderBlockOverflow(t *testing.T) { 135 if testing.Short() { 136 t.SkipNow() 137 } 138 mt, err := createMinerTester(t.Name()) 139 if err != nil { 140 t.Fatal(err) 141 } 142 143 // Grab a header that will be overwritten. 144 header, target, err := mt.miner.HeaderForWork() 145 if err != nil { 146 t.Fatal(err) 147 } 148 header = solveHeader(header, target) 149 150 // Mine blocks to wrap the memProgress around and wipe the old header. 151 for i := 0; i < BlockMemory; i++ { 152 _, err = mt.miner.AddBlock() 153 if err != nil { 154 t.Fatal(err) 155 } 156 // Grab a header to advance the mempool progress. 157 _, _, err = mt.miner.HeaderForWork() 158 if err != nil { 159 t.Fatal(err) 160 } 161 } 162 163 // Previous header should no longer be in memory. 164 err = mt.miner.SubmitHeader(header) 165 if err != errLateHeader { 166 t.Error(err) 167 } 168 } 169 170 // TestIntegrationHeaderRequestOverflow triggers a header overflow by 171 // requesting a header that triggers overflow. 172 func TestIntegrationHeaderRequestOverflow(t *testing.T) { 173 if testing.Short() { 174 t.SkipNow() 175 } 176 mt, err := createMinerTester(t.Name()) 177 if err != nil { 178 t.Fatal(err) 179 } 180 181 // Grab a header that will be overwritten. 182 header, target, err := mt.miner.HeaderForWork() 183 if err != nil { 184 t.Fatal(err) 185 } 186 header = solveHeader(header, target) 187 188 // Mine blocks to bring memProgress up to the edge. The number is chosen 189 // specifically so that the overflow happens during the requesting of 200 190 // headers. 191 for i := 0; i < BlockMemory-1; i++ { 192 _, err = mt.miner.AddBlock() 193 if err != nil { 194 t.Fatal(err) 195 } 196 // Grab a header to advance the mempool progress. 197 _, _, err = mt.miner.HeaderForWork() 198 if err != nil { 199 t.Fatal(err) 200 } 201 } 202 203 // Header should still be in memory. 204 err = mt.miner.SubmitHeader(header) 205 if err != modules.ErrNonExtendingBlock { 206 t.Error(err) 207 } 208 209 // Request headers until the overflow is achieved. 210 for i := 0; i < HeaderMemory/BlockMemory; i++ { 211 _, _, err = mt.miner.HeaderForWork() 212 if err != nil { 213 t.Fatal(err) 214 } 215 } 216 217 err = mt.miner.SubmitHeader(header) 218 if err != errLateHeader { 219 t.Error(err) 220 } 221 }