def create_and_submit_block(node, nVersion, hashPrevBlock, hashMerkleRoot, nTime, nNonce, scriptSig): block = CBlock() block.nVersion = nVersion block.hashPrevBlock = int(hashPrevBlock, 16) block.hashMerkleRoot = int(hashMerkleRoot, 16) block.nTime = nTime block.nBits = int("207fffff", 16) block.nNonce = nNonce block.vtx.append(create_coinbase(0)) block.vtx[0].nVersion = 1 block.vtx[0].vin[0].scriptSig = CScript(hex_str_to_bytes(scriptSig)) block.vtx[0].vin[0].nSequence = 0 block.vtx[0].vout[0].scriptPubKey = CScript( hex_str_to_bytes( "6a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf9" )) block.vtx[0].vout[0].nValue = 0 block.vtx[0].vout.append( CTxOut( 0, CScript( hex_str_to_bytes( "76a9145e53f01cbd5f5ffd50458cfe4a83069e193714f288ac")))) block.vtx[0].vout[1].nValue = 5 * COIN node.submitblock(ToHex(block))
def create_and_submit_first_block(node): block = CBlock() block.nVersion = 536870912 block.hashPrevBlock = int( "07a55485e188ffddb9d199debe06eab965e92a2f14c49c106705f13d4292939b", 16) block.hashMerkleRoot = int( "7f45e89dc0b49bf1c7cb1989541ee24cef220f3a9a4f2c849fb1aa48252d52c8", 16) block.nTime = 1602066398 block.nBits = int("207fffff", 16) block.nNonce = 0 block.vtx.append(create_coinbase(0)) block.vtx[0].nVersion = 2 block.vtx[0].vin[0].scriptSig = CScript(hex_str_to_bytes("510101")) block.vtx[0].vout[0].scriptPubKey = CScript( hex_str_to_bytes( "2102962c441d08d93d08d1c0b46610af8b9292528317b66799d62c57c10e32121ed1ac" )) block.vtx[0].vout.append( CTxOut( 0, CScript( hex_str_to_bytes( "6a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf9" )))) node.submitblock(ToHex(block))
def run_test(self): node = self.nodes[0] # Mine a block to leave initial block download node.generate(1) prevblk = node.getblock(node.getbestblockhash()) tmpl = node.getblocktemplate() self.log.info("getblocktemplate: Test capability advertised") assert 'rules' in tmpl assert 'vbavailable' in tmpl assert 'transactions' in tmpl assert 'coinbaseaux' in tmpl assert 'coinbasetxn' not in tmpl assert 'mutable' in tmpl assert isinstance(tmpl['version'], int) assert isinstance(tmpl['curtime'], int) assert isinstance(tmpl['vbrequired'], int) assert isinstance(tmpl['coinbasevalue'], int) assert_is_hex_string(tmpl['bits']) assert_is_hash_string(tmpl['target']) assert_is_hash_string(tmpl['previousblockhash']) assert_equal(tmpl['sizelimit'], 32000000) assert_equal(tmpl['sigoplimit'], 640000) assert_equal(tmpl['mintime'], prevblk['mediantime'] + 1) assert_equal(tmpl['height'], prevblk['height'] + 1) assert_equal(tmpl['noncerange'], "00000000ffffffff") coinbase_tx = create_coinbase(height=int(tmpl["height"]) + 1) # sequence numbers must not be max for nLockTime to have effect coinbase_tx.vin[0].nSequence = 2 ** 32 - 2 coinbase_tx.rehash() block = CBlock() block.nVersion = tmpl["version"] block.hashPrevBlock = int(tmpl["previousblockhash"], 16) block.nTime = tmpl["curtime"] block.nBits = int(tmpl["bits"], 16) block.nNonce = 0 block.vtx = [coinbase_tx] self.log.info("getblocktemplate: Test valid block") #assert_template(node, block, None) self.log.info("submitblock: Test block decode failure") assert_raises_rpc_error(-22, "Block decode failed", node.submitblock, b2x(block.serialize()[:-15])) block.hashMerkleRoot = block.calc_merkle_root() node.submitblock(b2x(block.serialize()[:]))
def test_api_errors(self, blockNode, otherNode): candidate = blockNode.getminingcandidate() block = CBlock() block.nVersion = candidate["version"] block.hashPrevBlock = int(candidate["prevhash"], 16) block.nTime = candidate["time"] block.nBits = int(candidate["nBits"], 16) block.nNonce = 0 # Submit with wrong ID self.log.info("Submitting to wrong node with unknown ID") assert_raises_rpc_error(-22, "Block candidate ID not found", otherNode.submitminingsolution, { 'id': candidate['id'], 'nonce': block.nNonce }) # Omit nonce self.log.info("Submitting without nonce") assert_raises_rpc_error(-22, "nonce not found", blockNode.submitminingsolution, {'id': candidate['id']}) # Bad coinbase self.log.info("Submitting with bad coinbase") assert_raises_rpc_error( -22, "coinbase decode failed", blockNode.submitminingsolution, { 'id': candidate['id'], 'nonce': block.nNonce, 'coinbase': 'ALoadOfRubbish' }) # Bad POW self.log.info("Submitting with bad POW") coinbase_tx = create_coinbase(height=int(candidate["height"]) + 1) coinbase_tx.rehash() block.vtx = [coinbase_tx] block.hashMerkleRoot = merkle_root_from_merkle_proof( coinbase_tx.sha256, candidate["merkleProof"]) solve_bad(block) submitResult = blockNode.submitminingsolution({ 'id': candidate['id'], 'nonce': block.nNonce, 'coinbase': '{}'.format(ToHex(coinbase_tx)) }) assert submitResult == 'high-hash'
def create_bad_block(self, template): coinbase_tx = create_coinbase(height=int(template["height"]) + 1) coinbase_tx.vin[0].nSequence = 2**32 - 2 coinbase_tx.rehash() block = CBlock() block.nVersion = template["version"] block.nTime = template["curtime"] block.nBits = int(template["bits"], 16) block.nNonce = 0 block.vtx = [coinbase_tx] # Make this block incorrect. block.hashPrevBlock = 123 block.hashMerkleRoot = block.calc_merkle_root() return block
def make_block_withP2SH_coinbase(self): tmpl = self.nodes[0].getblocktemplate() coinbase_tx = create_coinbase_P2SH( int(tmpl["height"]) + 1, example_script_hash) coinbase_tx.vin[0].nSequence = 2**32 - 2 coinbase_tx.rehash() block = CBlock() block.nVersion = tmpl["version"] block.hashPrevBlock = int(tmpl["previousblockhash"], 16) block.nTime = tmpl["curtime"] block.nBits = int(tmpl["bits"], 16) block.nNonce = 0 block.vtx = [coinbase_tx] block.hashMerkleRoot = block.calc_merkle_root() block.solve() block.rehash() return block
def mine_large_blocks(node, n): # Make a large scriptPubKey for the coinbase transaction. This is OP_RETURN # followed by 950k of OP_NOP. This would be non-standard in a non-coinbase # transaction but is consensus valid. # Set the nTime if this is the first time this function has been called. # A static variable ensures that time is monotonicly increasing and is therefore # different for each block created => blockhash is unique. if "nTimes" not in mine_large_blocks.__dict__: mine_large_blocks.nTime = 0 # Get the block parameters for the first block big_script = CScript([OP_RETURN] + [OP_NOP] * 950000) best_block = node.getblock(node.getbestblockhash()) height = int(best_block["height"]) + 1 mine_large_blocks.nTime = max(mine_large_blocks.nTime, int(best_block["time"])) + 1 previousblockhash = int(best_block["hash"], 16) for _ in range(n): # Build the coinbase transaction (with large scriptPubKey) coinbase_tx = create_coinbase(height) coinbase_tx.vin[0].nSequence = 2**32 - 1 coinbase_tx.vout[0].scriptPubKey = big_script coinbase_tx.rehash() # Build the block block = CBlock() block.nVersion = 0x620004 block.hashPrevBlock = previousblockhash block.nTime = mine_large_blocks.nTime block.nBits = int('207fffff', 16) block.nNonce = 0 block.vtx = [coinbase_tx] block.hashMerkleRoot = block.calc_merkle_root() block.calc_sha256() block.solve() # Submit to the node node.submitblock(block.serialize().hex()) previousblockhash = block.sha256 height += 1 mine_large_blocks.nTime += 1
def mine_using_template(self, nodeidx=0): tmpl = self.nodes[nodeidx].getblocktemplate() assert 'proposal' in tmpl['capabilities'] assert 'coinbasetxn' not in tmpl coinbase_tx = create_coinbase(height=int(tmpl["height"])) block = CBlock() block.nVersion = int(tmpl["version"]) block.hashPrevBlock = int(tmpl["previousblockhash"], 16) block.nTime = tmpl["curtime"] block.nBits = int(tmpl["bits"], 16) block.nNonce = 0 # extended block block.nStakeDifficulty = int(tmpl["stakedifficulty"], 16) block.nVoteBits = tmpl["votebits"] block.nTicketPoolSize = tmpl["ticketpoolsize"] block.ticketLotteryState = tmpl["ticketlotterystate"] block.nVoters = tmpl["voters"] block.nFreshStake = tmpl["freshstake"] block.nRevocations = tmpl["revocations"] block.extraData = tmpl["extradata"] block.nStakeVersion = tmpl["stakeversion"] block.vtx = [coinbase_tx] for tx in tmpl["transactions"]: ctx = CTransaction() ctx.deserialize(BytesIO(hex_str_to_bytes(tx['data']))) ctx.rehash() block.vtx.append(ctx) block.hashMerkleRoot = block.calc_merkle_root() add_witness_commitment(block) block.solve() print("-------------") print("mine using template on node:", nodeidx) print('solved hash', block.hash) # print("submit for height", idx) submit_result = self.nodes[nodeidx].submitblock(ToHex(block)) print(submit_result) assert (submit_result in [None, "inconclusive"]) return block.hash
def run_test(self): node = self.nodes[0] self.log.info('getmininginfo') mining_info = node.getmininginfo() assert_equal(mining_info['blocks'], 200) assert_equal(mining_info['chain'], 'regtest') assert_equal(mining_info['currentblocktx'], 0) assert_equal(mining_info['currentblockweight'], 0) assert_equal(mining_info['difficulty'], Decimal('4.656542373906925E-10')) assert_equal(mining_info['networkhashps'], Decimal('0.003333333333333334')) assert_equal(mining_info['pooledtx'], 0) # Mine a block to leave initial block download node.generate(1) tmpl = node.getblocktemplate() self.log.info("getblocktemplate: Test capability advertised") assert 'proposal' in tmpl['capabilities'] assert 'coinbasetxn' not in tmpl coinbase_tx = create_coinbase(height=int(tmpl["height"]) + 1) # sequence numbers must not be max for nLockTime to have effect coinbase_tx.vin[0].nSequence = 2 ** 32 - 2 coinbase_tx.rehash() block = CBlock() block.nVersion = tmpl["version"] block.hashPrevBlock = int(tmpl["previousblockhash"], 16) block.nTime = tmpl["curtime"] block.nBits = int(tmpl["bits"], 16) block.nNonce = 0 block.vtx = [coinbase_tx] self.log.info("getblocktemplate: Test valid block") assert_template(node, block, None) self.log.info("submitblock: Test block decode failure") assert_raises_rpc_error(-22, "Block decode failed", node.submitblock, b2x(block.serialize()[:-15])) self.log.info("getblocktemplate: Test bad input hash for coinbase transaction") bad_block = copy.deepcopy(block) bad_block.vtx[0].vin[0].prevout.hash += 1 bad_block.vtx[0].rehash() assert_template(node, bad_block, 'bad-cb-missing') self.log.info("submitblock: Test invalid coinbase transaction") assert_raises_rpc_error(-22, "Block does not start with a coinbase", node.submitblock, b2x(bad_block.serialize())) self.log.info("getblocktemplate: Test truncated final transaction") assert_raises_rpc_error(-22, "Block decode failed", node.getblocktemplate, {'data': b2x(block.serialize()[:-1]), 'mode': 'proposal'}) self.log.info("getblocktemplate: Test duplicate transaction") bad_block = copy.deepcopy(block) bad_block.vtx.append(bad_block.vtx[0]) assert_template(node, bad_block, 'bad-txns-duplicate') self.log.info("getblocktemplate: Test invalid transaction") bad_block = copy.deepcopy(block) bad_tx = copy.deepcopy(bad_block.vtx[0]) bad_tx.vin[0].prevout.hash = 255 bad_tx.rehash() bad_block.vtx.append(bad_tx) assert_template(node, bad_block, 'bad-txns-inputs-missingorspent') self.log.info("getblocktemplate: Test nonfinal transaction") bad_block = copy.deepcopy(block) bad_block.vtx[0].nLockTime = 2 ** 32 - 1 bad_block.vtx[0].rehash() assert_template(node, bad_block, 'bad-txns-nonfinal') self.log.info("getblocktemplate: Test bad tx count") # The tx count is immediately after the block header TX_COUNT_OFFSET = 80 bad_block_sn = bytearray(block.serialize()) assert_equal(bad_block_sn[TX_COUNT_OFFSET], 1) bad_block_sn[TX_COUNT_OFFSET] += 1 assert_raises_rpc_error(-22, "Block decode failed", node.getblocktemplate, {'data': b2x(bad_block_sn), 'mode': 'proposal'}) self.log.info("getblocktemplate: Test bad bits") bad_block = copy.deepcopy(block) bad_block.nBits = 469762303 # impossible in the real world assert_template(node, bad_block, 'bad-diffbits') self.log.info("getblocktemplate: Test bad merkle root") bad_block = copy.deepcopy(block) bad_block.hashMerkleRoot += 1 assert_template(node, bad_block, 'bad-txnmrklroot', False) self.log.info("getblocktemplate: Test bad timestamps") bad_block = copy.deepcopy(block) bad_block.nTime = 2 ** 31 - 1 assert_template(node, bad_block, 'time-too-new') bad_block.nTime = 0 assert_template(node, bad_block, 'time-too-old') self.log.info("getblocktemplate: Test not best block") bad_block = copy.deepcopy(block) bad_block.hashPrevBlock = 123 assert_template(node, bad_block, 'inconclusive-not-best-prevblk')
def run_test(self): node = self.nodes[0] self.log.info('getmininginfo') mining_info = node.getmininginfo() assert_equal(mining_info['blocks'], 600) assert_equal(mining_info['chain'], 'regtest') assert_equal(mining_info['currentblocktx'], 0) assert_equal(mining_info['currentblockweight'], 0) assert_equal(mining_info['difficulty']['proof-of-work'], Decimal('4.656542373906925E-10')) assert_equal(mining_info['networkhashps'], Decimal('0.015625')) assert_equal(mining_info['pooledtx'], 0) # Mine a block to leave initial block download node.generate(1) tmpl = node.getblocktemplate() self.log.info("getblocktemplate: Test capability advertised") assert 'proposal' in tmpl['capabilities'] assert 'coinbasetxn' not in tmpl coinbase_tx = create_coinbase(height=int(tmpl["height"])) # sequence numbers must not be max for nLockTime to have effect coinbase_tx.vin[0].nSequence = 2**32 - 2 coinbase_tx.rehash() block = CBlock() block.nVersion = tmpl["version"] block.hashPrevBlock = int(tmpl["previousblockhash"], 16) block.nTime = tmpl["curtime"] block.nBits = int(tmpl["bits"], 16) block.nNonce = 0 block.vtx = [coinbase_tx] self.log.info("getblocktemplate: Test valid block") assert_template(node, block, None) self.log.info("submitblock: Test block decode failure") assert_raises_rpc_error(-22, "Block decode failed", node.submitblock, b2x(block.serialize()[:-15])) self.log.info( "getblocktemplate: Test bad input hash for coinbase transaction") bad_block = copy.deepcopy(block) bad_block.vtx[0].vin[0].prevout.hash += 1 bad_block.vtx[0].rehash() assert_template(node, bad_block, 'bad-cb-missing') self.log.info("submitblock: Test invalid coinbase transaction") assert_raises_rpc_error(-22, "Block does not start with a coinbase", node.submitblock, b2x(bad_block.serialize())) self.log.info("getblocktemplate: Test truncated final transaction") assert_raises_rpc_error(-22, "Block decode failed", node.getblocktemplate, { 'data': b2x(block.serialize()[:-1]), 'mode': 'proposal' }) self.log.info("getblocktemplate: Test duplicate transaction") bad_block = copy.deepcopy(block) bad_block.vtx.append(bad_block.vtx[0]) assert_template(node, bad_block, 'bad-txns-duplicate') self.log.info("getblocktemplate: Test invalid transaction") bad_block = copy.deepcopy(block) bad_tx = copy.deepcopy(bad_block.vtx[0]) bad_tx.vin[0].prevout.hash = 255 bad_tx.rehash() bad_block.vtx.append(bad_tx) assert_template(node, bad_block, 'bad-txns-inputs-missingorspent') self.log.info("getblocktemplate: Test nonfinal transaction") bad_block = copy.deepcopy(block) bad_block.vtx[0].nLockTime = 2**32 - 1 bad_block.vtx[0].rehash() assert_template(node, bad_block, 'bad-txns-nonfinal') self.log.info("getblocktemplate: Test bad tx count") # The tx count is immediately after the block header TX_COUNT_OFFSET = 181 bad_block_sn = bytearray(block.serialize()) assert_equal(bad_block_sn[TX_COUNT_OFFSET], 1) bad_block_sn[TX_COUNT_OFFSET] += 1 assert_raises_rpc_error(-22, "Block decode failed", node.getblocktemplate, { 'data': b2x(bad_block_sn), 'mode': 'proposal' }) self.log.info("getblocktemplate: Test bad bits") bad_block = copy.deepcopy(block) bad_block.nBits = 469762303 # impossible in the real world assert_template(node, bad_block, 'bad-diffbits') self.log.info("getblocktemplate: Test bad merkle root") bad_block = copy.deepcopy(block) bad_block.hashMerkleRoot += 1 assert_template(node, bad_block, 'bad-txnmrklroot', False) # These tests do not apply to abp since the timestamps are only checked for PoS blocks. #self.log.info("getblocktemplate: Test bad timestamps") #bad_block = copy.deepcopy(block) #bad_block.nTime = 2 ** 31 - 1 #assert_template(node, bad_block, 'time-too-new') #bad_block.nTime = 0 #assert_template(node, bad_block, 'time-too-old') self.log.info("getblocktemplate: Test not best block") bad_block = copy.deepcopy(block) bad_block.hashPrevBlock = 123 assert_template(node, bad_block, 'inconclusive-not-best-prevblk')
def run_test(self): node = self.nodes[0] # Mine a block to leave initial block download node.generate(1) tmpl = node.getblocktemplate() self.log.info("getblocktemplate: Test capability advertised") assert 'proposal' in tmpl['capabilities'] assert 'coinbasetxn' not in tmpl coinbase_tx = create_coinbase(height=int(tmpl["height"]) + 1) # sequence numbers must not be max for nLockTime to have effect coinbase_tx.vin[0].nSequence = 2**32 - 2 coinbase_tx.rehash() block = CBlock() block.nVersion = tmpl["version"] block.hashPrevBlock = int(tmpl["previousblockhash"], 16) block.nTime = tmpl["curtime"] block.nBits = int(tmpl["bits"], 16) block.nNonce = 0 block.vtx = [coinbase_tx] self.log.info("getblocktemplate: Test valid block") assert_template(node, block, None) self.log.info("submitblock: Test block decode failure") assert_raises_jsonrpc(-22, "Block decode failed", node.submitblock, b2x(block.serialize()[:-15])) self.log.info( "getblocktemplate: Test bad input hash for coinbase transaction") bad_block = copy.deepcopy(block) bad_block.vtx[0].vin[0].prevout.hash += 1 bad_block.vtx[0].rehash() assert_template(node, bad_block, 'bad-cb-missing') self.log.info("submitblock: Test invalid coinbase transaction") assert_raises_jsonrpc(-22, "Block does not start with a coinbase", node.submitblock, b2x(bad_block.serialize())) self.log.info("getblocktemplate: Test truncated final transaction") assert_raises_jsonrpc(-22, "Block decode failed", node.getblocktemplate, { 'data': b2x(block.serialize()[:-1]), 'mode': 'proposal' }) self.log.info("getblocktemplate: Test duplicate transaction") bad_block = copy.deepcopy(block) bad_block.vtx.append(bad_block.vtx[0]) assert_template(node, bad_block, 'bad-txns-duplicate') self.log.info("getblocktemplate: Test invalid transaction") bad_block = copy.deepcopy(block) bad_tx = copy.deepcopy(bad_block.vtx[0]) bad_tx.vin[0].prevout.hash = 255 bad_tx.rehash() bad_block.vtx.append(bad_tx) assert_template(node, bad_block, 'bad-txns-inputs-missingorspent') self.log.info("getblocktemplate: Test nonfinal transaction") bad_block = copy.deepcopy(block) bad_block.vtx[0].nLockTime = 2**32 - 1 bad_block.vtx[0].rehash() assert_template(node, bad_block, 'bad-txns-nonfinal') self.log.info("getblocktemplate: Test bad tx count") # The tx count is immediately after the block header TX_COUNT_OFFSET = 80 bad_block_sn = bytearray(block.serialize()) assert_equal(bad_block_sn[TX_COUNT_OFFSET], 1) bad_block_sn[TX_COUNT_OFFSET] += 1 assert_raises_jsonrpc(-22, "Block decode failed", node.getblocktemplate, { 'data': b2x(bad_block_sn), 'mode': 'proposal' }) self.log.info("getblocktemplate: Test bad bits") bad_block = copy.deepcopy(block) bad_block.nBits = 469762303 # impossible in the real world assert_template(node, bad_block, 'bad-diffbits') self.log.info("getblocktemplate: Test bad merkle root") bad_block = copy.deepcopy(block) bad_block.hashMerkleRoot += 1 assert_template(node, bad_block, 'bad-txnmrklroot', False) self.log.info("getblocktemplate: Test bad timestamps") bad_block = copy.deepcopy(block) bad_block.nTime = 2**31 - 1 assert_template(node, bad_block, 'time-too-new') bad_block.nTime = 0 assert_template(node, bad_block, 'time-too-old') self.log.info("getblocktemplate: Test not best block") bad_block = copy.deepcopy(block) bad_block.hashPrevBlock = 123 assert_template(node, bad_block, 'inconclusive-not-best-prevblk')
def run_test(self): node = self.nodes[0] self.log.info('getmininginfo') mining_info = node.getmininginfo() assert_equal(mining_info['blocks'], 200) assert_equal(mining_info['chain'], 'regtest') assert_equal(mining_info['currentblocktx'], 0) assert_equal(mining_info['currentblockweight'], 0) # assert_equal(mining_info['difficulty'], Decimal('4.159690237829E-9')) # assert_equal(mining_info['networkhashps'], Decimal('0.1841805555555555')) assert_equal(mining_info['pooledtx'], 0) # Mine a block to leave initial block download node.generate(1) tmpl = node.getblocktemplate() self.log.info("getblocktemplate: Test capability advertised") assert 'proposal' in tmpl['capabilities'] assert 'coinbasetxn' not in tmpl newaddress = node.getnewaddress() pubkey = node.validateaddress(newaddress)["pubkey"] next_height = int(tmpl["height"]) coinbase_key = CECKey() coinbase_key.set_secretbytes(b"horsebattery") coinbase_pubkey = coinbase_key.get_pubkey() coinbase_tx = create_coinbase( height=next_height, pubkey=coinbase_pubkey) #bytes(pubkey,encoding='utf-8')) # sequence numbers must not be max for nLockTime to have effect coinbase_tx.vin[0].nSequence = 2**32 - 2 coinbase_tx.rehash() # round-trip the encoded bip34 block height commitment assert_equal(CScriptNum.decode(coinbase_tx.vin[0].scriptSig), next_height) # round-trip negative and multi-byte CScriptNums to catch python regression assert_equal(CScriptNum.decode(CScriptNum.encode(CScriptNum(1500))), 1500) assert_equal(CScriptNum.decode(CScriptNum.encode(CScriptNum(-1500))), -1500) assert_equal(CScriptNum.decode(CScriptNum.encode(CScriptNum(-1))), -1) block = CBlock() block.nVersion = tmpl["version"] block.hashPrevBlock = int(tmpl["previousblockhash"], 16) block.nTime = tmpl["curtime"] block.nBits = int(tmpl["bits"], 16) block.nNonce = 0 block.vtx = [coinbase_tx] self.log.info("getblocktemplate: Test valid block") assert_template(node, block, None) self.log.info("submitblock: Test block decode failure") assert_raises_rpc_error(-22, "Block decode failed", node.submitblock, b2x(block.serialize()[:-15])) self.log.info( "getblocktemplate: Test bad input hash for coinbase transaction") bad_block = copy.deepcopy(block) bad_block.vtx[0].vin[0].prevout.hash += 1 bad_block.vtx[0].rehash() assert_template(node, bad_block, 'bad-cb-missing') self.log.info("submitblock: Test invalid coinbase transaction") assert_raises_rpc_error(-22, "Block does not start with a coinbase", node.submitblock, b2x(bad_block.serialize())) self.log.info("getblocktemplate: Test truncated final transaction") assert_raises_rpc_error(-22, "Block decode failed", node.getblocktemplate, { 'data': b2x(block.serialize()[:-1]), 'mode': 'proposal' }) self.log.info("getblocktemplate: Test duplicate transaction") bad_block = copy.deepcopy(block) bad_block.vtx.append(bad_block.vtx[0]) assert_template(node, bad_block, 'bad-txns-duplicate') self.log.info("getblocktemplate: Test invalid transaction") bad_block = copy.deepcopy(block) bad_tx = copy.deepcopy(bad_block.vtx[0]) bad_tx.vin[0].prevout.hash = 255 bad_tx.rehash() bad_block.vtx.append(bad_tx) assert_template(node, bad_block, 'bad-txns-inputs-missingorspent') self.log.info("getblocktemplate: Test nonfinal transaction") bad_block = copy.deepcopy(block) bad_block.vtx[0].nLockTime = 2**32 - 1 bad_block.vtx[0].rehash() assert_template(node, bad_block, 'bad-txns-nonfinal') self.log.info("getblocktemplate: Test bad tx count") # The tx count is immediately after the block header TX_COUNT_OFFSET = 80 bad_block_sn = bytearray(block.serialize()) assert_equal(bad_block_sn[TX_COUNT_OFFSET], 1) bad_block_sn[TX_COUNT_OFFSET] += 1 assert_raises_rpc_error(-22, "Block decode failed", node.getblocktemplate, { 'data': b2x(bad_block_sn), 'mode': 'proposal' }) self.log.info("getblocktemplate: Test bad bits") bad_block = copy.deepcopy(block) bad_block.nBits = 469762303 # impossible in the real world assert_template(node, bad_block, 'bad-diffbits') self.log.info("getblocktemplate: Test bad merkle root") bad_block = copy.deepcopy(block) bad_block.hashMerkleRoot += 1 assert_template(node, bad_block, 'bad-txnmrklroot', False) self.log.info("getblocktemplate: Test bad timestamps") bad_block = copy.deepcopy(block) bad_block.nTime = 2**31 - 1 assert_template(node, bad_block, 'time-too-new') bad_block.nTime = 0 assert_template(node, bad_block, 'time-too-old') self.log.info("getblocktemplate: Test not best block") bad_block = copy.deepcopy(block) bad_block.hashPrevBlock = 123 assert_template(node, bad_block, 'inconclusive-not-best-prevblk')
def run_test(self): node = self.nodes[0] # Mine a block to leave initial block download node.generate(1) prevblk = node.getblock(node.getbestblockhash()) tmpl = node.getblocktemplate() self.log.info("getblocktemplate: Test capability advertised") assert 'transactions' in tmpl assert 'coinbaseaux' in tmpl assert 'coinbasetxn' not in tmpl assert 'mutable' in tmpl assert isinstance(tmpl['version'], int) assert isinstance(tmpl['curtime'], int) assert isinstance(tmpl['coinbasevalue'], int) assert_is_hex_string(tmpl['bits']) assert_is_hash_string(tmpl['target']) assert_is_hash_string(tmpl['previousblockhash']) assert_equal(tmpl['sizelimit'], 32000000) assert_equal(tmpl['sigoplimit'], 640000) assert_equal(tmpl['mintime'], prevblk['mediantime'] + 1) assert_equal(tmpl['height'], prevblk['height'] + 1) assert_equal(tmpl['noncerange'], "00000000ffffffff") coinbase_tx = create_coinbase(height=int(tmpl["height"]) + 1) # sequence numbers must not be max for nLockTime to have effect coinbase_tx.vin[0].nSequence = 2**32 - 2 coinbase_tx.rehash() block = CBlock() block.nVersion = tmpl["version"] block.hashPrevBlock = int(tmpl["previousblockhash"], 16) block.nTime = tmpl["curtime"] block.nBits = int(tmpl["bits"], 16) block.nNonce = 0 block.vtx = [coinbase_tx] exponent = int(tmpl["bits"][:2], 16) coefficient = int(tmpl["bits"][2:], 16) target = coefficient * 256**(exponent - 3) self.log.info(f"{chr(10)*3}getblocktemplate: Test valid block") assert_template(node, block, None) self.log.info(f"{chr(10)*3}submitblock: Test block decode failure") bhashint = doPow(block, target) self.log.info(f"{'-' * 10} bhash: {bhashint:0<54x} {'-' * 10}") assert_raises_rpc_error(-22, "Block decode failed", node.submitblock, b2x(block.serialize()[:-15])) self.log.info( f"{chr(10)*3}getblocktemplate: Test bad input hash for coinbase transaction" ) bad_block = copy.deepcopy(block) bad_block.vtx[0].vin[0].prevout.hash += 1 bad_block.vtx[0].rehash() assert_template(node, bad_block, 'bad-cb-missing') self.log.info( f"{chr(10)*3}submitblock: Test invalid coinbase transaction") bad_block = copy.deepcopy(block) bad_block.vtx[0].vin[0].prevout.hash += 1 bad_block.vtx[0].rehash() bad_block.hashMerkleRoot = bad_block.calc_merkle_root() bhashint = doPow(bad_block, target) self.log.info(f"{'-' * 10} target: {target:0<54x} {'-' * 10}") self.log.info(f"{'-' * 10} bhash: {bhashint:0<54x} {'-' * 10}") assert_raises_rpc_error(-22, "Block does not start with a coinbase", node.submitblock, b2x(bad_block.serialize())) self.log.info( f"{chr(10)*3}getblocktemplate: Test truncated final transaction") assert_raises_rpc_error(-22, "Block decode failed", node.getblocktemplate, { 'data': b2x(block.serialize()[:-1]), 'mode': 'proposal' }) self.log.info( f"{chr(10)*3}getblocktemplate: Test duplicate transaction") bad_block = copy.deepcopy(block) bad_block.vtx.append(bad_block.vtx[0]) assert_template(node, bad_block, 'bad-txns-duplicate') self.log.info(f"{chr(10)*3}getblocktemplate: Test invalid transaction") bad_block = copy.deepcopy(block) bad_tx = copy.deepcopy(bad_block.vtx[0]) bad_tx.vin[0].prevout.hash = 255 bad_tx.rehash() bad_block.vtx.append(bad_tx) assert_template(node, bad_block, 'bad-txns-inputs-missingorspent') self.log.info( f"{chr(10)*3}getblocktemplate: Test nonfinal transaction") bad_block = copy.deepcopy(block) bad_block.vtx[0].nLockTime = 2**32 - 1 bad_block.vtx[0].rehash() assert_template(node, bad_block, 'bad-txns-nonfinal') self.log.info(f"{chr(10)*3}getblocktemplate: Test bad tx count") # The tx count is immediately after the block header TX_COUNT_OFFSET = 80 bad_block_sn = bytearray(block.serialize()) assert_equal(bad_block_sn[TX_COUNT_OFFSET], 1) bad_block_sn[TX_COUNT_OFFSET] += 1 assert_raises_rpc_error(-22, "Block decode failed", node.getblocktemplate, { 'data': b2x(bad_block_sn), 'mode': 'proposal' }) self.log.info(f"{chr(10)*3}getblocktemplate: Test bad bits") bad_block = copy.deepcopy(block) bad_block.nBits = 469762303 # impossible in the real world assert_template(node, bad_block, 'bad-diffbits') self.log.info(f"{chr(10)*3}getblocktemplate: Test bad merkle root") bad_block = copy.deepcopy(block) bad_block.hashMerkleRoot += 1 assert_template(node, bad_block, 'bad-txnmrklroot', False) self.log.info(f"{chr(10)*3}getblocktemplate: Test bad timestamps") bad_block = copy.deepcopy(block) bad_block.nTime = 2**31 - 1 assert_template(node, bad_block, 'time-too-new') bad_block.nTime = 0 assert_template(node, bad_block, 'time-too-old') self.log.info(f"{chr(10)*3}getblocktemplate: Test not best block") bad_block = copy.deepcopy(block) bad_block.hashPrevBlock = 123 assert_template(node, bad_block, 'inconclusive-not-best-prevblk')
def run_test(self): node = self.nodes[0] self.log.info('getmininginfo') mining_info = node.getmininginfo() assert_equal(mining_info['blocks'], 200) assert_equal(mining_info['chain'], 'regtest') assert_equal(mining_info['currentblocktx'], 0) assert_equal(mining_info['currentblockweight'], 0) assert_equal(mining_info['difficulty'], Decimal('1.999969720836845')) assert_equal(mining_info['networkhashps'], Decimal('0.003333333333333334')) assert_equal(mining_info['pooledtx'], 0) # Mine a block to leave initial block download node.generate(1) tmpl = node.getblocktemplate() self.log.info("getblocktemplate: Test capability advertised") assert 'proposal' in tmpl['capabilities'] assert 'coinbasetxn' not in tmpl coinbase_tx = create_coinbase(height=int(tmpl["height"]) + 1) # sequence numbers must not be max for nLockTime to have effect coinbase_tx.vin[0].nSequence = 2**32 - 2 coinbase_tx.rehash() block = CBlock() block.nVersion = tmpl["version"] block.hashPrevBlock = int(tmpl["previousblockhash"], 16) block.nTime = tmpl["curtime"] block.nBits = int(tmpl["bits"], 16) block.nNonce = 0 block.vtx = [coinbase_tx] block.major_version = 10 block.merkle_root = uint256_from_str( bytes.fromhex( "3cf6c3b6da3f4058853ee70369ee43d473aca91ae8fc8f44a645beb21c392d80" )) block.calc_sha256() self.log.info("getblocktemplate: Test valid block") assert_template(node, block, None) self.log.info("submitblock: Test block decode failure") assert_raises_rpc_error(-22, "Block decode failed", node.submitblock, b2x(block.serialize()[:-15])) self.log.info( "getblocktemplate: Test bad input hash for coinbase transaction") bad_block = copy.deepcopy(block) bad_block.vtx[0].vin[0].prevout.hash += 1 bad_block.vtx[0].rehash() assert_template(node, bad_block, 'bad-cb-missing') self.log.info("submitblock: Test invalid coinbase transaction") assert_raises_rpc_error(-22, "Block does not start with a coinbase", node.submitblock, b2x(bad_block.serialize())) self.log.info("getblocktemplate: Test truncated final transaction") assert_raises_rpc_error(-22, "Block decode failed", node.getblocktemplate, { 'data': b2x(block.serialize()[:-1]), 'mode': 'proposal' }) self.log.info("getblocktemplate: Test duplicate transaction") bad_block = copy.deepcopy(block) bad_block.vtx.append(bad_block.vtx[0]) assert_template(node, bad_block, 'bad-txns-duplicate') self.log.info("getblocktemplate: Test invalid transaction") bad_block = copy.deepcopy(block) bad_tx = copy.deepcopy(bad_block.vtx[0]) bad_tx.vin[0].prevout.hash = 255 bad_tx.rehash() bad_block.vtx.append(bad_tx) # Kevacoin does not have proposal mode. The bad-txns-inputs-missingorspent # error will only be thrown in proposal mode. # assert_template(node, bad_block, 'bad-txns-inputs-missingorspent') self.log.info("getblocktemplate: Test nonfinal transaction") bad_block = copy.deepcopy(block) bad_block.vtx[0].nLockTime = 2**32 - 1 bad_block.vtx[0].rehash() assert_template(node, bad_block, 'bad-txns-nonfinal') self.log.info("getblocktemplate: Test bad tx count") # The tx count is immediately after the block header TX_COUNT_OFFSET = 80 + 78 # Kevacoin: 78 is the size of the cnHeader. bad_block_sn = bytearray(block.serialize()) assert_equal(bad_block_sn[TX_COUNT_OFFSET], 1) bad_block_sn[TX_COUNT_OFFSET] += 1 assert_raises_rpc_error(-22, "Block decode failed", node.getblocktemplate, { 'data': b2x(bad_block_sn), 'mode': 'proposal' }) self.log.info("getblocktemplate: Test bad bits") bad_block = copy.deepcopy(block) bad_block.nBits = 469762303 # impossible in the real world assert_template(node, bad_block, 'bad-diffbits') self.log.info("getblocktemplate: Test bad merkle root") bad_block = copy.deepcopy(block) bad_block.hashMerkleRoot += 1 assert_template(node, bad_block, 'bad-txnmrklroot', False) self.log.info("getblocktemplate: Test bad timestamps") bad_block = copy.deepcopy(block) bad_block.nTime = 2**31 - 1 assert_template(node, bad_block, 'time-too-new') bad_block.nTime = 0 assert_template(node, bad_block, 'time-too-old') self.log.info("getblocktemplate: Test not best block") bad_block = copy.deepcopy(block) bad_block.hashPrevBlock = 123 assert_template(node, bad_block, 'inconclusive-not-best-prevblk')