コード例 #1
0
    def test_compactblock_construction(self, node, test_node, version,
                                       use_witness_address):
        # Generate a bunch of transactions.
        node.generate(101)
        num_transactions = 25
        address = node.getnewaddress()
        if use_witness_address:
            # Want at least one segwit spend, so move all funds to
            # a witness address.
            address = node.addwitnessaddress(address)
            value_to_send = node.getbalance()
            node.sendtoaddress(address,
                               satoshi_round(value_to_send - Decimal(0.1)))
            node.generate(1)

        segwit_tx_generated = False
        for _ in range(num_transactions):
            txid = node.sendtoaddress(address, 0.1)
            hex_tx = node.gettransaction(txid)["hex"]
            tx = from_hex(CTransaction(), hex_tx)
            if not tx.wit.is_null():
                segwit_tx_generated = True

        if use_witness_address:
            assert segwit_tx_generated  # check that our test is not broken

        # Wait until we've seen the block announcement for the resulting tip
        tip = int(node.getbestblockhash(), 16)
        test_node.wait_for_block_announcement(tip)

        # Make sure we will receive a fast-announce compact block
        self.request_cb_announcements(test_node, node, version)

        # Now mine a block, and look at the resulting compact block.
        test_node.clear_block_announcement()
        block_hash = int(node.generate(1)[0], 16)

        # Store the raw block in our internal format.
        block = from_hex(CBlock(), node.getblock("%02x" % block_hash, False))
        for tx in block.vtx:
            tx.calc_x16r()
        block.rehash()

        # Wait until the block was announced (via compact blocks)
        wait_until(test_node.received_block_announcement,
                   timeout=30,
                   lock=mininode_lock,
                   err_msg="test_node.received_block_announcement")

        # Now fetch and check the compact block
        with mininode_lock:
            assert ("cmpctblock" in test_node.last_message)
            # Convert the on-the-wire representation to absolute indexes
            header_and_shortids = HeaderAndShortIDs(
                test_node.last_message["cmpctblock"].header_and_shortids)
        self.check_compactblock_construction_from_block(
            version, header_and_shortids, block_hash, block)

        # Now fetch the compact block using a normal non-announce getdata
        with mininode_lock:
            test_node.clear_block_announcement()
            inv = CInv(4, block_hash)  # 4 == "CompactBlock"
            test_node.send_message(MsgGetdata([inv]))

        wait_until(test_node.received_block_announcement,
                   timeout=30,
                   lock=mininode_lock,
                   err_msg="test_node.received_block_announcement")

        # Now fetch and check the compact block
        with mininode_lock:
            assert ("cmpctblock" in test_node.last_message)
            # Convert the on-the-wire representation to absolute indexes
            header_and_shortids = HeaderAndShortIDs(
                test_node.last_message["cmpctblock"].header_and_shortids)
        self.check_compactblock_construction_from_block(
            version, header_and_shortids, block_hash, block)
コード例 #2
0
ファイル: mining_basic.py プロジェクト: CryptoRekt/VERGE
    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')
コード例 #3
0
 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
コード例 #4
0
ファイル: mining.py プロジェクト: BlenderSleuth/schleems
    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')
コード例 #5
0
    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')
コード例 #6
0
    def mine_using_template(self):
        tmpl = self.nodes[0].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('solved hash', block.hash)
        # print("submit for height", idx)
        submit_result = self.nodes[0].submitblock(ToHex(block))
        print(submit_result)
        assert(submit_result in [None,"inconclusive"])
コード例 #7
0
    def run_test(self):

        # Turn on a webhook server
        self.start_webhook_server()

        # Create a P2P connection
        node = self.nodes[0]
        peer = NodeConnCB()
        connection = NodeConn('127.0.0.1', p2p_port(0), node, peer)
        peer.add_connection(connection)
        NetworkThread().start()
        peer.wait_for_verack()

        # Create an initial block with a coinbase we will split into multiple utxos
        initialBlock, _ = make_block(connection)
        coinbaseTx = initialBlock.vtx[0]

        send_by_headers(connection, [initialBlock], do_send_blocks=True)
        wait_for_tip(connection, initialBlock.hash)

        node.generate(101)
        block101hex = node.getblock(node.getbestblockhash(), False)
        block101dict = node.getblock(node.getbestblockhash(), 2)
        block101 = FromHex(CBlock(), block101hex)
        block101.height = block101dict['height']
        block101.rehash()

        # Create a block with a transaction spending coinbaseTx of a previous block and making multiple outputs for future transactions to spend
        utxoBlock, _ = make_block(connection, parent_block=block101)
        utxoTx = create_tx(coinbaseTx, 0, 1 * COIN)

        # Create additional 48 outputs (we let 1 COIN as fee)
        for _ in range(48):
            utxoTx.vout.append(CTxOut(1 * COIN, CScript([OP_TRUE])))
        # Add to block
        utxoTx.rehash()

        utxoBlock.vtx.append(utxoTx)
        utxoBlock.hashMerkleRoot = utxoBlock.calc_merkle_root()
        utxoBlock.solve()

        send_by_headers(connection, [utxoBlock], do_send_blocks=True)
        wait_for_tip(connection, utxoBlock.hash)

        # Make sure serialization/deserialization works as expected
        # Create dsdetected message. The content is not important here.
        dsdMessage = msg_dsdetected(blocksDetails=[
            BlockDetails(
                [CBlockHeader(utxoBlock),
                 CBlockHeader(initialBlock)],
                DSMerkleProof(1, utxoTx, utxoBlock.hashMerkleRoot,
                              [MerkleProofNode(utxoBlock.vtx[0].sha256)]))
        ])
        dsdBytes = dsdMessage.serialize()
        dsdMessageDeserialized = msg_dsdetected()
        dsdMessageDeserialized.deserialize(BytesIO(dsdBytes))
        assert_equal(str(dsdMessage), str(dsdMessageDeserialized))

        # Send a message containing random bytes. Webhook should not receive the notification.
        peer.send_and_ping(fake_msg_dsdetected())
        assert_equal(self.get_JSON_notification(), None)

        # Create two blocks with transactions spending the same utxo
        blockA, _ = make_block(connection, parent_block=utxoBlock)
        blockB, _ = make_block(connection, parent_block=utxoBlock)
        blockF, _ = make_block(connection, parent_block=utxoBlock)
        txA = create_tx(utxoBlock.vtx[1], 0, int(0.8 * COIN))
        txB = create_tx(utxoBlock.vtx[1], 0, int(0.9 * COIN))
        txF = create_tx(utxoBlock.vtx[1], 0, int(0.7 * COIN))
        txA.rehash()
        txB.rehash()
        txF.rehash()
        blockA.vtx.append(txA)
        blockB.vtx.append(txB)
        blockF.vtx.append(txF)
        blockA.hashMerkleRoot = blockA.calc_merkle_root()
        blockB.hashMerkleRoot = blockB.calc_merkle_root()
        blockF.hashMerkleRoot = blockF.calc_merkle_root()
        blockA.calc_sha256()
        blockB.calc_sha256()
        blockF.calc_sha256()
        blockA.solve()
        blockB.solve()
        blockF.solve()

        start_banscore = node.getpeerinfo()[0]['banscore']

        # Webhook should not receive the notification if we send dsdetected message with only one block detail.
        dsdMessage = msg_dsdetected(blocksDetails=[
            BlockDetails(
                [CBlockHeader(blockA)],
                DSMerkleProof(1, txA, blockA.hashMerkleRoot,
                              [MerkleProofNode(blockA.vtx[0].sha256)]))
        ])
        peer.send_and_ping(dsdMessage)
        assert_equal(self.get_JSON_notification(), None)

        # Webhook should not receive the notification if we send dsdetected message with two block details and one is containing no headers.
        dsdMessage = msg_dsdetected(blocksDetails=[
            BlockDetails(
                [CBlockHeader(blockA)],
                DSMerkleProof(1, txA, blockA.hashMerkleRoot,
                              [MerkleProofNode(blockA.vtx[0].sha256)])),
            BlockDetails(
                [],
                DSMerkleProof(1, txB, blockB.hashMerkleRoot,
                              [MerkleProofNode(blockB.vtx[0].sha256)]))
        ])
        peer.send_and_ping(dsdMessage)
        assert_equal(self.get_JSON_notification(), None)

        # Webhook should not receive the notification if we send dsdetected message where last headers in block details do not have a common previous block hash.
        dsdMessage = msg_dsdetected(blocksDetails=[
            BlockDetails(
                [CBlockHeader(blockA)],
                DSMerkleProof(1, txA, blockA.hashMerkleRoot,
                              [MerkleProofNode(blockA.vtx[0].sha256)])),
            BlockDetails(
                [CBlockHeader(utxoBlock)],
                DSMerkleProof(1, txB, blockB.hashMerkleRoot,
                              [MerkleProofNode(blockB.vtx[0].sha256)]))
        ])
        peer.send_and_ping(dsdMessage)
        assert_equal(self.get_JSON_notification(), None)

        # Webhook should not receive the notification if we send dsdetected message where block details does not have headers in proper order.
        dsdMessage = msg_dsdetected(blocksDetails=[
            BlockDetails(
                [CBlockHeader(blockA)],
                DSMerkleProof(1, txA, blockA.hashMerkleRoot,
                              [MerkleProofNode(blockA.vtx[0].sha256)])),
            BlockDetails(
                [CBlockHeader(utxoBlock),
                 CBlockHeader(blockB)],
                DSMerkleProof(1, txB, blockB.hashMerkleRoot,
                              [MerkleProofNode(blockB.vtx[0].sha256)]))
        ])
        peer.send_and_ping(dsdMessage)
        assert_equal(self.get_JSON_notification(), None)

        # Webhook should not receive the notification if we send dsdetected message with the empty merkle proof.
        dsdMessage = msg_dsdetected(blocksDetails=[
            BlockDetails(
                [CBlockHeader(blockA)],
                DSMerkleProof(1, txA, blockA.hashMerkleRoot,
                              [MerkleProofNode(blockA.vtx[0].sha256)])),
            BlockDetails([CBlockHeader(blockB)], DSMerkleProof())
        ])
        peer.send_and_ping(dsdMessage)
        assert_equal(self.get_JSON_notification(), None)

        # Webhook should not receive the notification if we send dsdetected message with the wrong index in the merkle proof (merkle root validation should fail)
        dsdMessage = msg_dsdetected(blocksDetails=[
            BlockDetails(
                [CBlockHeader(blockA)],
                DSMerkleProof(1, txA, blockA.hashMerkleRoot,
                              [MerkleProofNode(blockA.vtx[0].sha256)])),
            BlockDetails(
                [CBlockHeader(blockB)],
                DSMerkleProof(0, txB, blockB.hashMerkleRoot,
                              [MerkleProofNode(blockB.vtx[0].sha256)]))
        ])
        peer.send_and_ping(dsdMessage)
        assert_equal(self.get_JSON_notification(), None)

        # Webhook should not receive the notification if we send dsdetected message with the wrong transaction in the merkle proof (merkle root validation should fail)
        dsdMessage = msg_dsdetected(blocksDetails=[
            BlockDetails(
                [CBlockHeader(blockA)],
                DSMerkleProof(1, txA, blockA.hashMerkleRoot,
                              [MerkleProofNode(blockA.vtx[0].sha256)])),
            BlockDetails(
                [CBlockHeader(blockB)],
                DSMerkleProof(1, txA, blockB.hashMerkleRoot,
                              [MerkleProofNode(blockB.vtx[0].sha256)]))
        ])
        peer.send_and_ping(dsdMessage)
        assert_equal(self.get_JSON_notification(), None)

        # Webhook should not receive the notification if we send dsdetected message with the wrong merkle root (merkle root validation should fail)
        dsdMessage = msg_dsdetected(blocksDetails=[
            BlockDetails(
                [CBlockHeader(blockA)],
                DSMerkleProof(1, txA, blockA.hashMerkleRoot,
                              [MerkleProofNode(blockA.vtx[0].sha256)])),
            BlockDetails(
                [CBlockHeader(blockB)],
                DSMerkleProof(1, txB, blockA.hashMerkleRoot,
                              [MerkleProofNode(blockB.vtx[0].sha256)]))
        ])
        peer.send_and_ping(dsdMessage)
        assert_equal(self.get_JSON_notification(), None)

        # Webhook should not receive the notification if we send dsdetected message with the wrong merkle proof (merkle root validation should fail)
        dsdMessage = msg_dsdetected(blocksDetails=[
            BlockDetails(
                [CBlockHeader(blockA)],
                DSMerkleProof(1, txA, blockA.hashMerkleRoot,
                              [MerkleProofNode(blockA.vtx[0].sha256)])),
            BlockDetails(
                [CBlockHeader(blockB)],
                DSMerkleProof(1, txB, blockB.hashMerkleRoot,
                              [MerkleProofNode(blockA.hashMerkleRoot)]))
        ])
        peer.send_and_ping(dsdMessage)
        assert_equal(self.get_JSON_notification(), None)

        # Webhook should not receive the notification if we send dsdetected message with the merkle proof having an additional unexpected node (merkle root validation should fail)
        dsdMessage = msg_dsdetected(blocksDetails=[
            BlockDetails(
                [CBlockHeader(blockA)],
                DSMerkleProof(1, txA, blockA.hashMerkleRoot,
                              [MerkleProofNode(blockA.vtx[0].sha256)])),
            BlockDetails([CBlockHeader(blockB)],
                         DSMerkleProof(1, txB, blockB.hashMerkleRoot, [
                             MerkleProofNode(blockB.vtx[0].sha256),
                             MerkleProofNode(blockA.hashMerkleRoot)
                         ]))
        ])
        peer.send_and_ping(dsdMessage)
        assert_equal(self.get_JSON_notification(), None)

        # Webhook should not receive the notification if we send dsdetected message with the valid proof, but transaction is a coinbase transaction
        dsdMessage = msg_dsdetected(blocksDetails=[
            BlockDetails(
                [CBlockHeader(blockA)],
                DSMerkleProof(1, txA, blockA.hashMerkleRoot,
                              [MerkleProofNode(blockA.vtx[0].sha256)])),
            BlockDetails(
                [CBlockHeader(blockB)],
                DSMerkleProof(0, blockB.vtx[0], blockB.hashMerkleRoot,
                              [MerkleProofNode(blockB.vtx[1].sha256)]))
        ])
        peer.send_and_ping(dsdMessage)
        assert_equal(self.get_JSON_notification(), None)

        # Webhook should not receive the notification if we send dsdetected message with transactions that are not double spending
        # Create a block similar as before, but with a transaction spending a different utxo
        blockC, _ = make_block(connection, parent_block=utxoBlock)
        txC = create_tx(utxoBlock.vtx[1], 1, int(0.7 * COIN))
        blockC.vtx.append(txC)
        blockC.hashMerkleRoot = blockC.calc_merkle_root()
        blockC.solve()
        dsdMessage = msg_dsdetected(blocksDetails=[
            BlockDetails(
                [CBlockHeader(blockA)],
                DSMerkleProof(1, txA, blockA.hashMerkleRoot,
                              [MerkleProofNode(blockA.vtx[0].sha256)])),
            BlockDetails(
                [CBlockHeader(blockC)],
                DSMerkleProof(1, txC, blockC.hashMerkleRoot,
                              [MerkleProofNode(blockC.vtx[0].sha256)]))
        ])
        peer.send_and_ping(dsdMessage)
        assert_equal(self.get_JSON_notification(), None)

        # Webhook should not receive the notification if the two double spending transactions are actually the same transaction (having same txid)
        # Create a block similar as before, but with a transaction spending a different utxo
        blockD, _ = make_block(connection, parent_block=utxoBlock)
        blockD.vtx.append(txA)
        blockD.hashMerkleRoot = blockD.calc_merkle_root()
        blockD.solve()
        dsdMessage = msg_dsdetected(blocksDetails=[
            BlockDetails(
                [CBlockHeader(blockA)],
                DSMerkleProof(1, txA, blockA.hashMerkleRoot,
                              [MerkleProofNode(blockA.vtx[0].sha256)])),
            BlockDetails(
                [CBlockHeader(blockD)],
                DSMerkleProof(1, txA, blockD.hashMerkleRoot,
                              [MerkleProofNode(blockD.vtx[0].sha256)]))
        ])
        peer.send_and_ping(dsdMessage)
        assert_equal(self.get_JSON_notification(), None)

        # Webhook should not receive the notification if header cannot pow
        # note hat pow is so easy in regtest that nonce can often be hence we have to select the nonce carefully
        blockE, _ = make_block(connection, parent_block=utxoBlock)
        blockE.vtx.append(txB)
        blockE.hashMerkleRoot = blockE.calc_merkle_root()
        nonce = blockE.nNonce
        while True:
            blockE.solve()
            if blockE.nNonce > nonce:
                blockE.nNonce = nonce
                break
            nonce += 1
            blockE.nNonce = nonce

        dsdMessage = msg_dsdetected(blocksDetails=[
            BlockDetails(
                [CBlockHeader(blockA)],
                DSMerkleProof(1, txA, blockA.hashMerkleRoot,
                              [MerkleProofNode(blockA.vtx[0].sha256)])),
            BlockDetails(
                [CBlockHeader(blockE)],
                DSMerkleProof(1, txB, blockE.hashMerkleRoot,
                              [MerkleProofNode(blockE.vtx[0].sha256)]))
        ])
        peer.send_and_ping(dsdMessage)
        assert_equal(self.get_JSON_notification(), None)

        end_banscore = node.getpeerinfo()[0]['banscore']
        assert ((end_banscore - start_banscore) / 10 == 13
                )  # because we have 13 negative tests so far

        # Finally, webhook should receive the notification if we send a proper dsdetected message
        dsdMessage = msg_dsdetected(blocksDetails=[
            BlockDetails(
                [CBlockHeader(blockA)],
                DSMerkleProof(1, txA, blockA.hashMerkleRoot,
                              [MerkleProofNode(blockA.vtx[0].sha256)])),
            BlockDetails(
                [CBlockHeader(blockB)],
                DSMerkleProof(1, txB, blockB.hashMerkleRoot,
                              [MerkleProofNode(blockB.vtx[0].sha256)]))
        ])
        peer.send_and_ping(dsdMessage)
        json_notification = self.get_JSON_notification()
        # remove diverentBlockHash so we can compare with the ds-message
        assert (json_notification != None)
        for e in json_notification['blocks']:
            del e['divergentBlockHash']
        assert_equal(str(dsdMessage),
                     str(msg_dsdetected(json_notification=json_notification)))

        # Repeat previous test but change the order of the BlockDetails, the node should identify this as a duplicate
        dsdMessage = msg_dsdetected(blocksDetails=[
            BlockDetails(
                [CBlockHeader(blockB)],
                DSMerkleProof(1, txB, blockB.hashMerkleRoot,
                              [MerkleProofNode(blockB.vtx[0].sha256)])),
            BlockDetails(
                [CBlockHeader(blockA)],
                DSMerkleProof(1, txA, blockA.hashMerkleRoot,
                              [MerkleProofNode(blockA.vtx[0].sha256)]))
        ])
        peer.send_and_ping(dsdMessage)
        assert_equal(self.get_JSON_notification(), None)

        # repeat previous test but generate many blocks in the node to age the notificatoin message.
        # very old notification messages shall be ignored. We use the same thresholds as safe mode.
        # We will hardcode this threshold for now until branch we depend on is merged
        node.generate(289)
        dsdMessage = msg_dsdetected(blocksDetails=[
            BlockDetails(
                [CBlockHeader(blockA)],
                DSMerkleProof(1, txA, blockA.hashMerkleRoot,
                              [MerkleProofNode(blockA.vtx[0].sha256)])),
            BlockDetails(
                [CBlockHeader(blockF)],
                DSMerkleProof(1, txF, blockF.hashMerkleRoot,
                              [MerkleProofNode(blockF.vtx[0].sha256)]))
        ])
        peer.send_and_ping(dsdMessage)
        assert_equal(self.get_JSON_notification(), None)

        # Create number of random valid block trees and send dsdetected P2P message for each
        maxNumberOfBranches = 10
        maxNumberOfBlocksPerBranch = 30
        for _ in range(10):
            blockTree = self.createRandomBlockTree(maxNumberOfBranches,
                                                   maxNumberOfBlocksPerBranch,
                                                   utxoBlock,
                                                   [utxoBlock.vtx[1]])
            dsdMessage = self.createDsDetectedMessageFromBlockTree(blockTree)
            peer.send_and_ping(dsdMessage)
            # Notification should be received as generated dsdetected message is valid
            json_notification = self.get_JSON_notification()
            # remove diverentBlockHash so we can compare with the ds-message
            assert (json_notification != None)
            for e in json_notification['blocks']:
                del e['divergentBlockHash']
            assert_equal(
                str(dsdMessage),
                str(msg_dsdetected(json_notification=json_notification)))

        self.stop_webhook_server()
コード例 #8
0
    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')
コード例 #9
0
ファイル: pruning.py プロジェクト: acerix/dogecoin
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
コード例 #10
0
    def CheckForDoubleSpends(self, nodes):
        spent_inputs = []
        seen_transactions = []
        ds_counter = 0
        for node in nodes:
            for height in range(node.getblockcount() + 1):
                blockhash = node.getblockhash(height)
                block = node.getblock(blockhash, 2)
                blockHex = node.getblock(blockhash, False)
                for txraw in block['tx'][1:]:  # exclude coinbase
                    # skip the identical transactions in the two chains, they are no double spends
                    if txraw['txid'] in seen_transactions:
                        continue
                    else:
                        seen_transactions.append(txraw['txid'])
                    for i in txraw['vin']:
                        utxoA = (i['txid'], i['vout'])
                        blockA = FromHex(CBlock(), blockHex)
                        txA = FromHex(CTransaction(), txraw['hex'])
                        foundB = [
                            j for j in spent_inputs if j['utxo'] == utxoA
                        ]
                        if foundB:
                            ds_counter += 1
                            foundB = foundB[0]
                            blockB = foundB['block']
                            txB = foundB['tx']
                            txA.rehash()

                            txB.rehash()

                            blockA.vtx[0].rehash()
                            blockB.vtx[0].rehash()
                            sha256_A = blockA.vtx[0].sha256
                            sha256_B = blockB.vtx[0].sha256

                            dsdMessage = msg_dsdetected(blocksDetails=[
                                BlockDetails([CBlockHeader(blockA)],
                                             DSMerkleProof(
                                                 1, txA, blockA.hashMerkleRoot,
                                                 [MerkleProofNode(sha256_A)])),
                                BlockDetails([CBlockHeader(blockB)],
                                             DSMerkleProof(
                                                 1, txB, blockB.hashMerkleRoot,
                                                 [MerkleProofNode(sha256_B)]))
                            ])
                            self.message = dsdMessage

                            dsdBytes = dsdMessage.serialize()
                            dsdMessageDeserialized = msg_dsdetected()
                            dsdMessageDeserialized.deserialize(
                                BytesIO(dsdBytes))
                            assert_equal(str(dsdMessage),
                                         str(dsdMessageDeserialized))

                            break
                        else:
                            spent_inputs.append({
                                'txid': txraw['txid'],
                                'tx': txA,
                                'utxo': utxoA,
                                'block': blockA
                            })

        return ds_counter
コード例 #11
0
ファイル: mining_template.py プロジェクト: whunmr/walle
    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()[:]))