(self)
| 196 | self.restart_node(0) |
| 197 | |
| 198 | def test_timewarp(self): |
| 199 | self.log.info("Test timewarp attack mitigation (BIP94)") |
| 200 | node = self.nodes[0] |
| 201 | self.restart_node(0, extra_args=['-test=bip94']) |
| 202 | |
| 203 | self.log.info("Mine until the last block of the retarget period") |
| 204 | blockchain_info = self.nodes[0].getblockchaininfo() |
| 205 | n = DIFFICULTY_ADJUSTMENT_INTERVAL - blockchain_info['blocks'] % DIFFICULTY_ADJUSTMENT_INTERVAL - 2 |
| 206 | t = blockchain_info['time'] |
| 207 | |
| 208 | for _ in range(n): |
| 209 | t += 600 |
| 210 | self.nodes[0].setmocktime(t) |
| 211 | self.generate(self.wallet, 1, sync_fun=self.no_op) |
| 212 | |
| 213 | self.log.info("Create block two hours in the future") |
| 214 | self.nodes[0].setmocktime(t + MAX_FUTURE_BLOCK_TIME) |
| 215 | self.generate(self.wallet, 1, sync_fun=self.no_op) |
| 216 | assert_equal(node.getblock(node.getbestblockhash())['time'], t + MAX_FUTURE_BLOCK_TIME) |
| 217 | |
| 218 | self.log.info("First block template of retarget period can't use wall clock time") |
| 219 | self.nodes[0].setmocktime(t) |
| 220 | # The template will have an adjusted timestamp, which we then modify |
| 221 | tmpl = node.getblocktemplate(NORMAL_GBT_REQUEST_PARAMS) |
| 222 | assert_greater_than_or_equal(tmpl['curtime'], t + MAX_FUTURE_BLOCK_TIME - MAX_TIMEWARP) |
| 223 | # mintime and curtime should match |
| 224 | assert_equal(tmpl['mintime'], tmpl['curtime']) |
| 225 | |
| 226 | block = CBlock() |
| 227 | block.nVersion = tmpl["version"] |
| 228 | block.hashPrevBlock = int(tmpl["previousblockhash"], 16) |
| 229 | block.nTime = tmpl["curtime"] |
| 230 | block.nBits = int(tmpl["bits"], 16) |
| 231 | block.nNonce = 0 |
| 232 | block.vtx = [create_coinbase(height=int(tmpl["height"]))] |
| 233 | block.hashMerkleRoot = block.calc_merkle_root() |
| 234 | block.solve() |
| 235 | assert_equal(node.getblocktemplate(template_request={ |
| 236 | 'data': block.serialize().hex(), |
| 237 | 'mode': 'proposal', |
| 238 | **NORMAL_GBT_REQUEST_PARAMS, |
| 239 | }), None) |
| 240 | |
| 241 | bad_block = copy.deepcopy(block) |
| 242 | bad_block.nTime = t |
| 243 | bad_block.solve() |
| 244 | assert_raises_rpc_error(-25, 'time-timewarp-attack', lambda: node.submitheader(hexdata=CBlockHeader(bad_block).serialize().hex())) |
| 245 | |
| 246 | self.log.info("Test timewarp protection boundary") |
| 247 | bad_block.nTime = t + MAX_FUTURE_BLOCK_TIME - MAX_TIMEWARP - 1 |
| 248 | bad_block.solve() |
| 249 | assert_raises_rpc_error(-25, 'time-timewarp-attack', lambda: node.submitheader(hexdata=CBlockHeader(bad_block).serialize().hex())) |
| 250 | |
| 251 | bad_block.nTime = t + MAX_FUTURE_BLOCK_TIME - MAX_TIMEWARP |
| 252 | bad_block.solve() |
| 253 | node.submitheader(hexdata=CBlockHeader(bad_block).serialize().hex()) |
| 254 | |
| 255 | def test_pruning(self): |
no test coverage detected