def test_auxpow(nodes): """ Test behaviour of getauxpow. Calling getauxpow should reserve a key from the pool, but it should be released again if the created block is not actually used. On the other hand, if the auxpow is submitted and turned into a block, the keypool should be drained. """ nodes[0].walletpassphrase('test', 12000) nodes[0].keypoolrefill(2) nodes[0].walletlock() assert_equal(nodes[0].getwalletinfo()['keypoolsize'], 2) nodes[0].getauxblock() assert_equal(nodes[0].getwalletinfo()['keypoolsize'], 2) nodes[0].generate(1) assert_equal(nodes[0].getwalletinfo()['keypoolsize'], 1) auxblock = nodes[0].getauxblock() assert_equal(nodes[0].getwalletinfo()['keypoolsize'], 1) target = auxpow.reverseHex(auxblock['_target']) solved = auxpow.computeAuxpow(auxblock['hash'], target, True) res = nodes[0].getauxblock(auxblock['hash'], solved) assert res assert_equal(nodes[0].getwalletinfo()['keypoolsize'], 0) assert_raises_jsonrpc(-12, 'Keypool ran out', nodes[0].getauxblock)
def test_auxpow(nodes): """ Test behaviour of getauxpow. Calling getauxpow should reserve a key from the pool, but it should be released again if the created block is not actually used. On the other hand, if the auxpow is submitted and turned into a block, the keypool should be drained. """ nodes[0].walletpassphrase('test', 12000) nodes[0].keypoolrefill(1) nodes[0].walletlock() assert_equal (nodes[0].getwalletinfo()['keypoolsize'], 2) nodes[0].getauxblock() assert_equal (nodes[0].getwalletinfo()['keypoolsize'], 2) nodes[0].generate(1) assert_equal (nodes[0].getwalletinfo()['keypoolsize'], 1) auxblock = nodes[0].getauxblock() assert_equal (nodes[0].getwalletinfo()['keypoolsize'], 1) target = auxpow.reverseHex(auxblock['_target']) solved = auxpow.computeAuxpow(auxblock['hash'], target, True) res = nodes[0].getauxblock(auxblock['hash'], solved) assert res assert_equal(nodes[0].getwalletinfo()['keypoolsize'], 0) try: nodes[0].getauxblock() raise AssertionError('Keypool should be exhausted by getauxblock') except JSONRPCException as e: assert(e.error['code']==-12)
def test_auxpow(nodes): """ Test behaviour of getauxpow. Calling getauxpow should reserve a key from the pool, but it should be released again if the created block is not actually used. On the other hand, if the auxpow is submitted and turned into a block, the keypool should be drained. """ nodes[0].walletpassphrase('test', 12000) nodes[0].keypoolrefill(2) nodes[0].walletlock() assert_equal (nodes[0].getwalletinfo()['keypoolsize'], 2) nodes[0].getauxblock() assert_equal (nodes[0].getwalletinfo()['keypoolsize'], 2) nodes[0].generate(1) assert_equal (nodes[0].getwalletinfo()['keypoolsize'], 1) auxblock = nodes[0].getauxblock() assert_equal (nodes[0].getwalletinfo()['keypoolsize'], 1) target = auxpow.reverseHex(auxblock['_target']) solved = auxpow.computeAuxpow(auxblock['hash'], target, True) res = nodes[0].getauxblock(auxblock['hash'], solved) assert res assert_equal(nodes[0].getwalletinfo()['keypoolsize'], 0) assert_raises_rpc_error (-12, 'Keypool ran out', nodes[0].getauxblock)
def test_auxpow(nodes): """ Test behaviour of getauxpow. Calling getauxpow should reserve a key from the pool, but it should be released again if the created block is not actually used. On the other hand, if the auxpow is submitted and turned into a block, the keypool should be drained. """ nodes[0].walletpassphrase('test', 12000) nodes[0].keypoolrefill(1) nodes[0].walletlock() assert_equal(nodes[0].getwalletinfo()['keypoolsize'], 2) nodes[0].getauxblock() assert_equal(nodes[0].getwalletinfo()['keypoolsize'], 2) nodes[0].generate(1) assert_equal(nodes[0].getwalletinfo()['keypoolsize'], 1) auxblock = nodes[0].getauxblock() assert_equal(nodes[0].getwalletinfo()['keypoolsize'], 1) target = auxpow.reverseHex(auxblock['_target']) solved = auxpow.computeAuxpow(auxblock['hash'], target, True) res = nodes[0].getauxblock(auxblock['hash'], solved) assert res assert_equal(nodes[0].getwalletinfo()['keypoolsize'], 0) try: nodes[0].getauxblock() raise AssertionError('Keypool should be exhausted by getauxblock') except JSONRPCException as e: assert (e.error['code'] == -12)
def run_test (self): BitcoinTestFramework.run_test (self) # Check for difficulty reports in various RPC calls. Where the "current" # state is involved, we get two (for each algo). Where a particular block # is involved, we just get that block's difficulty (whatever the algo). dual = [] dual.append (self.nodes[0].getinfo ()) dual.append (self.nodes[0].getblockchaininfo ()) dual.append (self.nodes[0].getmininginfo ()) for data in dual: assert 'difficulty_sha256d' in data assert 'difficulty_scrypt' in data assert 'difficulty' not in data bestHash = self.nodes[0].getbestblockhash () data = self.nodes[0].getblock (bestHash) assert 'difficulty' in data assert 'difficulty_sha256d' not in data assert 'difficulty_scrypt' not in data # Check getdifficulty RPC call. diffSHA = self.nodes[0].getdifficulty (0) assert_equal (diffSHA, dual[0]['difficulty_sha256d']) diffScrypt = self.nodes[0].getdifficulty (1) assert_equal (diffScrypt, dual[0]['difficulty_scrypt']) try: self.nodes[0].getdifficulty () raise AssertionError ("getdifficulty without arg accepted") except JSONRPCException as exc: assert_equal (exc.error['code'], -1) # Generate a few blocks with SHA256D. Ensure that they are, indeed, # with the correct algo. arr1 = self.nodes[0].generate (5) arr2 = self.nodes[0].generate (5, 0) for blk in arr1 + arr2: data = self.nodes[0].getblock (blk) assert_equal (data['algo'], 0) # Generate a few blocks with scrypt. Ensure the algo parameter. # Furthermore, at least one of them "should" have an obviously high # hash value. It may, of course, happen that this is not the case, # but the probability for that is negligible (about 2^(-20)). arr = self.nodes[0].generate (20, 1) foundHigh = False for blk in arr: data = self.nodes[0].getblock (blk) assert_equal (data['algo'], 1) if blk[0] in '89abcdef': foundHigh = True assert foundHigh # Verify check for algo parameter. for p in [-1, 2]: try: self.nodes[0].generate (1, p) raise AssertionError ("invalid algo parameter accepted") except JSONRPCException as exc: assert_equal (exc.error['code'], -8) # Briefly test generatetoaddress as well. for algo in [0, 1]: addr = self.nodes[0].getnewaddress () blkhash = self.nodes[0].generatetoaddress (1, addr, algo) assert_equal (1, len (blkhash)) data = self.nodes[0].getblock(blkhash[0]) assert_equal (algo, data['algo']) coinbaseTx = data['tx'][0] utxo = self.nodes[0].gettxout (coinbaseTx, 0) assert_equal ([addr], utxo['scriptPubKey']['addresses']) # Check updates of the returned block (or not) with getauxblock. # Note that this behaviour needs not necessarily be exactly as tested, # but the test ensures that no change is introduced accidentally. auxblock1 = self.nodes[0].getauxblock () auxblock2 = self.nodes[0].getauxblock (0) assert_equal (auxblock1['hash'], auxblock2['hash']) auxblock2 = self.nodes[0].getauxblock (1) auxblock3 = self.nodes[0].getauxblock (1) assert_equal (auxblock2['hash'], auxblock3['hash']) assert auxblock2['hash'] != auxblock1['hash'] auxblock3 = self.nodes[0].getauxblock () assert auxblock1['hash'] != auxblock3['hash'] # Use getauxblock with explicit algo to mine a SHA256D block. # Assert that this works (the block is saved) even if we request # another scrypt block before. auxblock = self.nodes[0].getauxblock () assert_equal (auxblock['chainid'], 6) assert_equal (auxblock['algo'], 0) dummy = self.nodes[0].getauxblock (1) assert_equal (dummy['chainid'], 2) assert_equal (dummy['algo'], 1) # Solve the auxpow requested before. curcnt = self.nodes[0].getblockcount () target = auxpow.reverseHex (auxblock['_target']) apow = auxpow.computeAuxpow (auxblock['hash'], target, True) res = self.nodes[0].getauxblock (auxblock['hash'], apow) assert res # Check submitted data. assert_equal (self.nodes[0].getblockcount (), curcnt + 1) data = self.nodes[0].getblock (auxblock['hash']) assert_equal (data['algo'], 0) # Mine an scrypt auxpow. Since there is no built-in Python # function to scrypt, we do it differently: Simply try submitting # until the block is accepted. Since we need on average 2 trials, # this is no big hit. trials = 0 curcnt = self.nodes[0].getblockcount () ok = False while not ok: if trials > 100: raise AssertionError ("failed to merge-mine scrypt auxpow") trials += 1 # Force an update of the block so we get a new trial. self.nodes[0].getauxblock (0) auxblock = self.nodes[0].getauxblock (1) target = auxpow.reverseHex (auxblock['_target']) apow = auxpow.computeAuxpow (auxblock['hash'], target, False) ok = self.nodes[0].getauxblock (auxblock['hash'], apow) print "Found scrypt block after %d trials." % trials # Check submitted auxblock. assert_equal (self.nodes[0].getblockcount (), curcnt + 1) data = self.nodes[0].getblock (auxblock['hash']) assert_equal (data['algo'], 1)
def run_test(self): # Check for difficulty reports in various RPC calls. Where the "current" # state is involved, we get two (for each algo). Where a particular block # is involved, we just get that block's difficulty (whatever the algo). dual = [] dual.append(self.nodes[0].getblockchaininfo()) dual.append(self.nodes[0].getmininginfo()) for data in dual: assert 'difficulty_sha256d' in data assert 'difficulty_scrypt' in data assert 'difficulty' not in data bestHash = self.nodes[0].getbestblockhash() data = self.nodes[0].getblock(bestHash) assert 'difficulty' in data assert 'difficulty_sha256d' not in data assert 'difficulty_scrypt' not in data # Check getdifficulty RPC call. diffSHA = self.nodes[0].getdifficulty(0) assert_equal(diffSHA, dual[0]['difficulty_sha256d']) diffScrypt = self.nodes[0].getdifficulty(1) assert_equal(diffScrypt, dual[0]['difficulty_scrypt']) assert_raises_jsonrpc(-1, None, self.nodes[0].getdifficulty) # Generate a few blocks with SHA256D. Ensure that they are, indeed, # with the correct algo. arr1 = self.nodes[0].generate(5) arr2 = self.nodes[0].generate(5, 0) for blk in arr1 + arr2: data = self.nodes[0].getblock(blk) assert_equal(data['algo'], 0) # Generate a few blocks with scrypt. Ensure the algo parameter. # Furthermore, at least one of them "should" have an obviously high # hash value. It may, of course, happen that this is not the case, # but the probability for that is negligible (about 2^(-20)). arr = self.nodes[0].generate(20, 1) foundHigh = False for blk in arr: data = self.nodes[0].getblock(blk) assert_equal(data['algo'], 1) if blk[0] in '89abcdef': foundHigh = True assert foundHigh # Verify check for algo parameter. for p in [-1, 2]: assert_raises_jsonrpc(-8, 'invalid algo', self.nodes[0].generate, 1, p) # Briefly test generatetoaddress as well. for algo in [0, 1]: addr = self.nodes[0].getnewaddress() blkhash = self.nodes[0].generatetoaddress(1, addr, algo) assert_equal(1, len(blkhash)) data = self.nodes[0].getblock(blkhash[0]) assert_equal(algo, data['algo']) coinbaseTx = data['tx'][0] utxo = self.nodes[0].gettxout(coinbaseTx, 0) assert_equal([addr], utxo['scriptPubKey']['addresses']) # Check updates of the returned block (or not) with aux mining. # Note that this behaviour needs not necessarily be exactly as tested, # but the test ensures that no change is introduced accidentally. coinbaseAddr = self.nodes[0].getnewaddress() auxblock1 = self.nodes[0].createauxblock(coinbaseAddr) auxblock2 = self.nodes[0].createauxblock(coinbaseAddr, 0) assert_equal(auxblock1['hash'], auxblock2['hash']) auxblock2 = self.nodes[0].createauxblock(coinbaseAddr, 1) auxblock3 = self.nodes[0].createauxblock(coinbaseAddr, 1) assert_equal(auxblock2['hash'], auxblock3['hash']) assert auxblock2['hash'] != auxblock1['hash'] auxblock3 = self.nodes[0].createauxblock(coinbaseAddr) assert auxblock1['hash'] != auxblock3['hash'] # Use createauxblock with explicit algo to mine a SHA256D block. # Assert that this works (the block is saved) even if we request # another scrypt block before. auxblock = self.nodes[0].createauxblock(coinbaseAddr) assert_equal(auxblock['chainid'], 6) assert_equal(auxblock['algo'], 0) dummy = self.nodes[0].createauxblock(coinbaseAddr, 1) assert_equal(dummy['chainid'], 2) assert_equal(dummy['algo'], 1) # Solve the auxpow requested before. curcnt = self.nodes[0].getblockcount() target = auxpow.reverseHex(auxblock['_target']) apow = auxpow.computeAuxpow(auxblock['hash'], target, True) res = self.nodes[0].submitauxblock(auxblock['hash'], apow) assert res # Check submitted data. assert_equal(self.nodes[0].getblockcount(), curcnt + 1) data = self.nodes[0].getblock(auxblock['hash']) assert_equal(data['algo'], 0) # Mine an scrypt auxpow. Since there is no built-in Python # function to scrypt, we do it differently: Simply try submitting # until the block is accepted. Since we need on average 2 trials, # this is no big hit. trials = 0 curcnt = self.nodes[0].getblockcount() ok = False while not ok: if trials > 100: raise AssertionError("failed to merge-mine scrypt auxpow") trials += 1 # Force an update of the block so we get a new trial. self.nodes[0].createauxblock(coinbaseAddr, 0) auxblock = self.nodes[0].createauxblock(coinbaseAddr, 1) target = auxpow.reverseHex(auxblock['_target']) apow = auxpow.computeAuxpow(auxblock['hash'], target, False) ok = self.nodes[0].submitauxblock(auxblock['hash'], apow) print("Found scrypt block after %d trials." % trials) # Check submitted auxblock. assert_equal(self.nodes[0].getblockcount(), curcnt + 1) data = self.nodes[0].getblock(auxblock['hash']) assert_equal(data['algo'], 1)
def run_test (self): BitcoinTestFramework.run_test (self) # Generate a block so that we are not "downloading blocks". self.nodes[0].generate (1) # Compare basic data of getauxblock to getblocktemplate. auxblock = self.nodes[0].getauxblock () blocktemplate = self.nodes[0].getblocktemplate () assert_equal (auxblock['coinbasevalue'], blocktemplate['coinbasevalue']) assert_equal (auxblock['bits'], blocktemplate['bits']) assert_equal (auxblock['height'], blocktemplate['height']) assert_equal (auxblock['previousblockhash'], blocktemplate['previousblockhash']) # Compare target and take byte order into account. target = auxblock['_target'] reversedTarget = auxpow.reverseHex (target) assert_equal (reversedTarget, blocktemplate['target']) # Verify data that can be found in another way. assert_equal (auxblock['chainid'], 1) assert_equal (auxblock['height'], self.nodes[0].getblockcount () + 1) assert_equal (auxblock['previousblockhash'], self.nodes[0].getblockhash (auxblock['height'] - 1)) # Calling again should give the same block. auxblock2 = self.nodes[0].getauxblock () assert_equal (auxblock2, auxblock) # If we receive a new block, the old hash will be replaced. self.sync_all () self.nodes[1].generate (1) self.sync_all () auxblock2 = self.nodes[0].getauxblock () assert auxblock['hash'] != auxblock2['hash'] try: self.nodes[0].getauxblock (auxblock['hash'], "x") raise AssertionError ("invalid block hash accepted") except JSONRPCException as exc: assert_equal (exc.error['code'], -8) # Invalid format for auxpow. try: self.nodes[0].getauxblock (auxblock2['hash'], "x") raise AssertionError ("malformed auxpow accepted") except JSONRPCException as exc: assert_equal (exc.error['code'], -1) # Invalidate the block again, send a transaction and query for the # auxblock to solve that contains the transaction. self.nodes[0].generate (1) addr = self.nodes[1].getnewaddress () txid = self.nodes[0].sendtoaddress (addr, 1) self.sync_all () assert_equal (self.nodes[1].getrawmempool (), [txid]) auxblock = self.nodes[0].getauxblock () blocktemplate = self.nodes[0].getblocktemplate () target = blocktemplate['target'] # Compute invalid auxpow. apow = auxpow.computeAuxpow (auxblock['hash'], target, False) res = self.nodes[0].getauxblock (auxblock['hash'], apow) assert not res # Compute and submit valid auxpow. apow = auxpow.computeAuxpow (auxblock['hash'], target, True) res = self.nodes[0].getauxblock (auxblock['hash'], apow) assert res # Make sure that the block is indeed accepted. self.sync_all () assert_equal (self.nodes[1].getrawmempool (), []) height = self.nodes[1].getblockcount () assert_equal (height, auxblock['height']) assert_equal (self.nodes[1].getblockhash (height), auxblock['hash']) # Call getblock and verify the auxpow field. data = self.nodes[1].getblock (auxblock['hash']) assert 'auxpow' in data auxJson = data['auxpow'] assert_equal (auxJson['index'], 0) assert_equal (auxJson['parentblock'], apow[-160:]) # Check that previous blocks don't have 'auxpow' in their getblock JSON. oldHash = self.nodes[1].getblockhash (100) data = self.nodes[1].getblock (oldHash) assert 'auxpow' not in data # Check that it paid correctly to the first node. t = self.nodes[0].listtransactions ("", 1) assert_equal (len (t), 1) t = t[0] assert_equal (t['category'], "immature") assert_equal (t['blockhash'], auxblock['hash']) assert t['generated'] assert t['amount'] >= Decimal ("25") assert_equal (t['confirmations'], 1) # Verify the coinbase script. Ensure that it includes the block height # to make the coinbase tx unique. The expected block height is around # 200, so that the serialisation of the CScriptNum ends in an extra 00. # The vector has length 2, which makes up for 02XX00 as the serialised # height. Check this. blk = self.nodes[1].getblock (auxblock['hash']) tx = self.nodes[1].getrawtransaction (blk['tx'][0], 1) coinbase = tx['vin'][0]['coinbase'] assert_equal ("02%02x00" % auxblock['height'], coinbase[0 : 6]) # Ensure that the payout address is changed from one block to the next. addr1 = self.getCoinbaseAddr (auxblock['hash']) newHash = auxpow.mineAuxpowBlock (self.nodes[0]) self.sync_all () addr2 = self.getCoinbaseAddr (newHash) assert addr1 != addr2 valid = self.nodes[0].validateaddress (addr1) assert valid['ismine'] valid = self.nodes[0].validateaddress (addr2) assert valid['ismine']
def run_test(self): # Generate a block so that we are not "downloading blocks". self.nodes[0].generate(1) # specify coinbase output coinbaseAddress = self.nodes[0].getnewaddress() # # check params # # missing address assert_raises_jsonrpc(-1, None, self.nodes[0].createauxblock) # invalid address assert_raises_jsonrpc(-8, "Invalid coinbase payout address", self.nodes[0].createauxblock, "this_a_invalid_address") # Verify data that can be found in another way. auxblock = self.nodes[0].createauxblock(coinbaseAddress) assert_equal(auxblock['chainid'], 1) assert_equal(auxblock['height'], self.nodes[0].getblockcount() + 1) assert_equal(auxblock['previousblockhash'], self.nodes[0].getblockhash(auxblock['height'] - 1)) # Calling again should give the same block. auxblock2 = self.nodes[0].createauxblock(coinbaseAddress) assert_equal(auxblock2, auxblock) # If we receive a new block, the old hash will be replaced. self.sync_all() self.nodes[1].generate(1) self.sync_all() auxblock2 = self.nodes[0].createauxblock(coinbaseAddress) assert auxblock['hash'] != auxblock2['hash'] # Invalid format for auxpow. assert_raises_jsonrpc(-8, 'block hash unknown', self.nodes[0].submitauxblock, auxblock['hash'], "x") assert_raises_jsonrpc(-1, None, self.nodes[0].submitauxblock, auxblock2['hash'], "x") # Invalidate the block again, send a transaction and query for the # auxblock to solve that contains the transaction. self.nodes[0].generate(1) addr = self.nodes[1].getnewaddress() txid = self.nodes[0].sendtoaddress(addr, 1) self.sync_all() assert_equal(self.nodes[1].getrawmempool(), [txid]) auxblock = self.nodes[0].createauxblock(coinbaseAddress) target = auxpow.reverseHex(auxblock['_target']) # Compute invalid auxpow. apow = auxpow.computeAuxpow(auxblock['hash'], target, False) res = self.nodes[0].submitauxblock(auxblock['hash'], apow) assert not res # Compute and submit valid auxpow. apow = auxpow.computeAuxpow(auxblock['hash'], target, True) res = self.nodes[0].submitauxblock(auxblock['hash'], apow) assert res # Make sure that the block is indeed accepted. self.sync_all() assert_equal(self.nodes[1].getrawmempool(), []) height = self.nodes[1].getblockcount() assert_equal(height, auxblock['height']) assert_equal(self.nodes[1].getblockhash(height), auxblock['hash']) # Call getblock and verify the auxpow field. data = self.nodes[1].getblock(auxblock['hash']) assert 'auxpow' in data auxJson = data['auxpow'] assert_equal(auxJson['index'], 0) assert_equal(auxJson['chainindex'], 0) assert_equal(auxJson['merklebranch'], []) assert_equal(auxJson['chainmerklebranch'], []) assert_equal(auxJson['parentblock'], apow[-160:]) # Also previous blocks should have 'auxpow', since all blocks (also # those generated by "generate") are merge-mined. oldHash = self.nodes[1].getblockhash(100) data = self.nodes[1].getblock(oldHash) assert 'auxpow' in data # Check that it paid correctly to the first node. t = self.nodes[0].listtransactions("", 1) assert_equal(len(t), 1) t = t[0] assert_equal(t['category'], "immature") assert_equal(t['blockhash'], auxblock['hash']) assert t['generated'] assert t['amount'] >= Decimal("25") assert_equal(t['confirmations'], 1) # Verify the coinbase script. Ensure that it includes the block height # to make the coinbase tx unique. The expected block height is around # 200, so that the serialisation of the CScriptNum ends in an extra 00. # The vector has length 2, which makes up for 02XX00 as the serialised # height. Check this. blk = self.nodes[1].getblock(auxblock['hash']) tx = self.nodes[1].getrawtransaction(blk['tx'][0], 1) coinbase = tx['vin'][0]['coinbase'] assert_equal("02%02x00" % auxblock['height'], coinbase[0:6]) # Ensure that the payout address is the one which we specify addr1 = auxpow.getCoinbaseAddr(self.nodes[1], auxblock['hash']) assert addr1 == coinbaseAddress newHash = auxpow.mineAuxpowBlock2(self.nodes[0], coinbaseAddress) self.sync_all() addr2 = auxpow.getCoinbaseAddr(self.nodes[1], newHash) assert addr2 == coinbaseAddress
def test_common (self, create, submit): """ Common test code that is shared between the tests for getauxblock and the createauxblock / submitauxblock method pair. """ # Verify data that can be found in another way. auxblock = create () assert_equal (auxblock['chainid'], 6) assert_equal (auxblock['algo'], 0) assert_equal (auxblock['height'], self.nodes[0].getblockcount () + 1) assert_equal (auxblock['previousblockhash'], self.nodes[0].getblockhash (auxblock['height'] - 1)) # Calling again should give the same block. # Try using the (default) algo parameter. auxblock2 = create (0) assert_equal (auxblock2, auxblock) # If we receive a new block, the old hash will be replaced. self.sync_all () self.nodes[1].generate (1) self.sync_all () auxblock2 = create () assert auxblock['hash'] != auxblock2['hash'] assert_raises_rpc_error (-8, 'block hash unknown', submit, auxblock['hash'], "x") # Invalid format for auxpow. assert_raises_rpc_error (-1, None, submit, auxblock2['hash'], "x") # Invalidate the block again, send a transaction and query for the # auxblock to solve that contains the transaction. self.nodes[0].generate (1) addr = self.nodes[1].getnewaddress () txid = self.nodes[0].sendtoaddress (addr, 1) self.sync_all () assert_equal (self.nodes[1].getrawmempool (), [txid]) auxblock = create () target = auxpow.reverseHex (auxblock['_target']) # Compute invalid auxpow. apow = auxpow.computeAuxpow (auxblock['hash'], target, False) res = submit (auxblock['hash'], apow) assert not res # Compute and submit valid auxpow. apow = auxpow.computeAuxpow (auxblock['hash'], target, True) res = submit (auxblock['hash'], apow) assert res # Make sure that the block is indeed accepted. self.sync_all () assert_equal (self.nodes[1].getrawmempool (), []) height = self.nodes[1].getblockcount () assert_equal (height, auxblock['height']) assert_equal (self.nodes[1].getblockhash (height), auxblock['hash']) # Call getblock and verify the auxpow field. data = self.nodes[1].getblock (auxblock['hash']) assert 'auxpow' in data auxJson = data['auxpow'] assert_equal (auxJson['index'], 0) assert_equal (auxJson['chainindex'], 0) assert_equal (auxJson['merklebranch'], []) assert_equal (auxJson['chainmerklebranch'], []) assert_equal (auxJson['parentblock'], apow[-160:]) # Also previous blocks should have 'auxpow', since all blocks (also # those generated by "generate") are merge-mined. oldHash = self.nodes[1].getblockhash (100) data = self.nodes[1].getblock (oldHash) assert 'auxpow' in data # Check that it paid correctly to the first node. t = self.nodes[0].listtransactions ("*", 1) assert_equal (len (t), 1) t = t[0] assert_equal (t['category'], "immature") assert_equal (t['blockhash'], auxblock['hash']) assert t['generated'] assert_greater_than_or_equal (t['amount'], Decimal ("0.05")) assert_equal (t['confirmations'], 1) # Verify the coinbase script. Ensure that it includes the block height # to make the coinbase tx unique. The expected block height is around # 200, so that the serialisation of the CScriptNum ends in an extra 00. # The vector has length 2, which makes up for 02XX00 as the serialised # height. Check this. (With segwit, the height is different, so we skip # this for simplicity.) if not self.options.segwit: blk = self.nodes[1].getblock (auxblock['hash']) tx = self.nodes[1].getrawtransaction (blk['tx'][0], 1) coinbase = tx['vin'][0]['coinbase'] assert_equal ("02%02x00" % auxblock['height'], coinbase[0 : 6])
def run_test (self): BitcoinTestFramework.run_test (self) # Generate a block so that we are not "downloading blocks". self.nodes[0].generate (1) # We used to compare to getblocktemplate, but this call is gone # now completely for merge-mining. # Verify data that can be found in another way. auxblock = self.nodes[0].getauxblock () assert_equal (auxblock['chainid'], 1) assert_equal (auxblock['height'], self.nodes[0].getblockcount () + 1) assert_equal (auxblock['previousblockhash'], self.nodes[0].getblockhash (auxblock['height'] - 1)) # Calling again should give the same block. auxblock2 = self.nodes[0].getauxblock () assert_equal (auxblock2, auxblock) # If we receive a new block, the old hash will be replaced. self.sync_all () self.nodes[1].generate (1) self.sync_all () auxblock2 = self.nodes[0].getauxblock () assert auxblock['hash'] != auxblock2['hash'] try: self.nodes[0].getauxblock (auxblock['hash'], "x") raise AssertionError ("invalid block hash accepted") except JSONRPCException as exc: assert_equal (exc.error['code'], -8) # Invalid format for auxpow. try: self.nodes[0].getauxblock (auxblock2['hash'], "x") raise AssertionError ("malformed auxpow accepted") except JSONRPCException as exc: assert_equal (exc.error['code'], -1) # Invalidate the block again, send a transaction and query for the # auxblock to solve that contains the transaction. self.nodes[0].generate (1) addr = self.nodes[1].getnewaddress () txid = self.nodes[0].sendtoaddress (addr, 1) self.sync_all () assert_equal (self.nodes[1].getrawmempool (), [txid]) auxblock = self.nodes[0].getauxblock () target = auxpow.reverseHex (auxblock['_target']) # Compute invalid auxpow. apow = auxpow.computeAuxpow (auxblock['hash'], target, False) res = self.nodes[0].getauxblock (auxblock['hash'], apow) assert not res # Compute and submit valid auxpow. apow = auxpow.computeAuxpow (auxblock['hash'], target, True) res = self.nodes[0].getauxblock (auxblock['hash'], apow) assert res # Make sure that the block is indeed accepted. self.sync_all () assert_equal (self.nodes[1].getrawmempool (), []) height = self.nodes[1].getblockcount () assert_equal (height, auxblock['height']) assert_equal (self.nodes[1].getblockhash (height), auxblock['hash']) # Call getblock and verify the auxpow field. data = self.nodes[1].getblock (auxblock['hash']) assert 'auxpow' in data auxJson = data['auxpow'] assert_equal (auxJson['index'], 0) assert_equal (auxJson['chainindex'], 0) assert_equal (auxJson['merklebranch'], []) assert_equal (auxJson['chainmerklebranch'], []) assert_equal (auxJson['parentblock'], apow[-160:]) # Also previous blocks should have 'auxpow', since all blocks (also # those generated by "generate") are merge-mined. oldHash = self.nodes[1].getblockhash (100) data = self.nodes[1].getblock (oldHash) assert 'auxpow' in data # Check that it paid correctly to the first node. t = self.nodes[0].listtransactions ("", 1) assert_equal (len (t), 1) t = t[0] assert_equal (t['category'], "immature") assert_equal (t['blockhash'], auxblock['hash']) assert t['generated'] assert t['amount'] >= Decimal ("25") assert_equal (t['confirmations'], 1) # Verify the coinbase script. Ensure that it includes the block height # to make the coinbase tx unique. The expected block height is around # 200, so that the serialisation of the CScriptNum ends in an extra 00. # The vector has length 2, which makes up for 02XX00 as the serialised # height. Check this. blk = self.nodes[1].getblock (auxblock['hash']) tx = self.nodes[1].getrawtransaction (blk['tx'][0], 1) coinbase = tx['vin'][0]['coinbase'] assert_equal ("02%02x00" % auxblock['height'], coinbase[0 : 6]) # Ensure that the payout address is changed from one block to the next. addr1 = self.getCoinbaseAddr (auxblock['hash']) newHash = auxpow.mineAuxpowBlock (self.nodes[0]) self.sync_all () addr2 = self.getCoinbaseAddr (newHash) assert addr1 != addr2 valid = self.nodes[0].validateaddress (addr1) assert valid['ismine'] valid = self.nodes[0].validateaddress (addr2) assert valid['ismine']
def run_test(self): BitcoinTestFramework.run_test(self) # Generate a block so that we are not "downloading blocks". self.nodes[0].generate(1) # Compare basic data of getauxblock to getblocktemplate. auxblock = self.nodes[0].getauxblock() blocktemplate = self.nodes[0].getblocktemplate() assert_equal(auxblock['coinbasevalue'], blocktemplate['coinbasevalue']) assert_equal(auxblock['bits'], blocktemplate['bits']) assert_equal(auxblock['height'], blocktemplate['height']) assert_equal(auxblock['previousblockhash'], blocktemplate['previousblockhash']) # Compare target and take byte order into account. target = auxblock['_target'] reversedTarget = auxpow.reverseHex(target) assert_equal(reversedTarget, blocktemplate['target']) # Verify data that can be found in another way. assert_equal(auxblock['chainid'], 1) assert_equal(auxblock['height'], self.nodes[0].getblockcount() + 1) assert_equal(auxblock['previousblockhash'], self.nodes[0].getblockhash(auxblock['height'] - 1)) # Calling again should give the same block. auxblock2 = self.nodes[0].getauxblock() assert_equal(auxblock2, auxblock) # If we receive a new block, the old hash will be replaced. self.sync_all() self.nodes[1].generate(1) self.sync_all() auxblock2 = self.nodes[0].getauxblock() assert auxblock['hash'] != auxblock2['hash'] try: self.nodes[0].getauxblock(auxblock['hash'], "x") raise AssertionError("invalid block hash accepted") except JSONRPCException as exc: assert_equal(exc.error['code'], -8) # Invalid format for auxpow. try: self.nodes[0].getauxblock(auxblock2['hash'], "x") raise AssertionError("malformed auxpow accepted") except JSONRPCException as exc: assert_equal(exc.error['code'], -1) # Invalidate the block again, send a transaction and query for the # auxblock to solve that contains the transaction. self.nodes[0].generate(1) addr = self.nodes[1].getnewaddress() txid = self.nodes[0].sendtoaddress(addr, 1) self.sync_all() assert_equal(self.nodes[1].getrawmempool(), [txid]) auxblock = self.nodes[0].getauxblock() blocktemplate = self.nodes[0].getblocktemplate() target = blocktemplate['target'] # Compute invalid auxpow. apow = auxpow.computeAuxpow(auxblock['hash'], target, False) res = self.nodes[0].getauxblock(auxblock['hash'], apow) assert not res # Compute and submit valid auxpow. apow = auxpow.computeAuxpow(auxblock['hash'], target, True) res = self.nodes[0].getauxblock(auxblock['hash'], apow) assert res # Make sure that the block is indeed accepted. self.sync_all() assert_equal(self.nodes[1].getrawmempool(), []) height = self.nodes[1].getblockcount() assert_equal(height, auxblock['height']) assert_equal(self.nodes[1].getblockhash(height), auxblock['hash']) # Call getblock and verify the auxpow field. data = self.nodes[1].getblock(auxblock['hash']) assert 'auxpow' in data auxJson = data['auxpow'] assert_equal(auxJson['index'], 0) assert_equal(auxJson['parentblock'], apow[-160:]) # Check that previous blocks don't have 'auxpow' in their getblock JSON. oldHash = self.nodes[1].getblockhash(100) data = self.nodes[1].getblock(oldHash) assert 'auxpow' not in data # Check that it paid correctly to the first node. t = self.nodes[0].listtransactions("", 1) assert_equal(len(t), 1) t = t[0] assert_equal(t['category'], "immature") assert_equal(t['blockhash'], auxblock['hash']) assert t['generated'] assert t['amount'] >= Decimal("25") assert_equal(t['confirmations'], 1) # Verify the coinbase script. Ensure that it includes the block height # to make the coinbase tx unique. The expected block height is around # 200, so that the serialisation of the CScriptNum ends in an extra 00. # The vector has length 2, which makes up for 02XX00 as the serialised # height. Check this. blk = self.nodes[1].getblock(auxblock['hash']) tx = self.nodes[1].getrawtransaction(blk['tx'][0], 1) coinbase = tx['vin'][0]['coinbase'] assert_equal("02%02x00" % auxblock['height'], coinbase[0:6])