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