|
| 1 | +#!/usr/bin/env python3 |
| 2 | +# Copyright (c) 2020 The Bitcoin Core developers |
| 3 | +# Distributed under the MIT software license, see the accompanying |
| 4 | +# file COPYING or http://www.opensource.org/licenses/mit-license.php. |
| 5 | +'''Test generateblock rpc. |
| 6 | +''' |
| 7 | + |
| 8 | +from test_framework.test_framework import BitcoinTestFramework |
| 9 | +from test_framework.util import ( |
| 10 | + assert_equal, |
| 11 | + assert_raises_rpc_error, |
| 12 | +) |
| 13 | + |
| 14 | +class GenerateBlockTest(BitcoinTestFramework): |
| 15 | + def set_test_params(self): |
| 16 | + self.num_nodes = 1 |
| 17 | + |
| 18 | + def skip_test_if_missing_module(self): |
| 19 | + self.skip_if_no_wallet() |
| 20 | + |
| 21 | + def run_test(self): |
| 22 | + node = self.nodes[0] |
| 23 | + |
| 24 | + self.log.info('Generate an empty block to address') |
| 25 | + address = node.getnewaddress() |
| 26 | + hash = node.generateblock(address, [])['hash'] |
| 27 | + block = node.getblock(hash, 2) |
| 28 | + assert_equal(len(block['tx']), 1) |
| 29 | + assert_equal(block['tx'][0]['vout'][0]['scriptPubKey']['addresses'][0], address) |
| 30 | + |
| 31 | + self.log.info('Generate an empty block to a descriptor') |
| 32 | + hash = node.generateblock('addr(' + address + ')', [])['hash'] |
| 33 | + block = node.getblock(hash, 2) |
| 34 | + assert_equal(len(block['tx']), 1) |
| 35 | + assert_equal(block['tx'][0]['vout'][0]['scriptPubKey']['addresses'][0], address) |
| 36 | + |
| 37 | + self.log.info('Generate an empty block to a combo descriptor with compressed pubkey') |
| 38 | + combo_key = '0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798' |
| 39 | + combo_address = 'bcrt1qw508d6qejxtdg4y5r3zarvary0c5xw7kygt080' |
| 40 | + hash = node.generateblock('combo(' + combo_key + ')', [])['hash'] |
| 41 | + block = node.getblock(hash, 2) |
| 42 | + assert_equal(len(block['tx']), 1) |
| 43 | + assert_equal(block['tx'][0]['vout'][0]['scriptPubKey']['addresses'][0], combo_address) |
| 44 | + |
| 45 | + self.log.info('Generate an empty block to a combo descriptor with uncompressed pubkey') |
| 46 | + combo_key = '0408ef68c46d20596cc3f6ddf7c8794f71913add807f1dc55949fa805d764d191c0b7ce6894c126fce0babc6663042f3dde9b0cf76467ea315514e5a6731149c67' |
| 47 | + combo_address = 'mkc9STceoCcjoXEXe6cm66iJbmjM6zR9B2' |
| 48 | + hash = node.generateblock('combo(' + combo_key + ')', [])['hash'] |
| 49 | + block = node.getblock(hash, 2) |
| 50 | + assert_equal(len(block['tx']), 1) |
| 51 | + assert_equal(block['tx'][0]['vout'][0]['scriptPubKey']['addresses'][0], combo_address) |
| 52 | + |
| 53 | + # Generate 110 blocks to spend |
| 54 | + node.generatetoaddress(110, address) |
| 55 | + |
| 56 | + # Generate some extra mempool transactions to verify they don't get mined |
| 57 | + for i in range(10): |
| 58 | + node.sendtoaddress(address, 0.001) |
| 59 | + |
| 60 | + self.log.info('Generate block with txid') |
| 61 | + txid = node.sendtoaddress(address, 1) |
| 62 | + hash = node.generateblock(address, [txid])['hash'] |
| 63 | + block = node.getblock(hash, 1) |
| 64 | + assert_equal(len(block['tx']), 2) |
| 65 | + assert_equal(block['tx'][1], txid) |
| 66 | + |
| 67 | + self.log.info('Generate block with raw tx') |
| 68 | + utxos = node.listunspent(addresses=[address]) |
| 69 | + raw = node.createrawtransaction([{'txid':utxos[0]['txid'], 'vout':utxos[0]['vout']}],[{address:1}]) |
| 70 | + signed_raw = node.signrawtransactionwithwallet(raw)['hex'] |
| 71 | + hash = node.generateblock(address, [signed_raw])['hash'] |
| 72 | + block = node.getblock(hash, 1) |
| 73 | + assert_equal(len(block['tx']), 2) |
| 74 | + txid = block['tx'][1] |
| 75 | + assert_equal(node.gettransaction(txid)['hex'], signed_raw) |
| 76 | + |
| 77 | + self.log.info('Fail to generate block with out of order txs') |
| 78 | + raw1 = node.createrawtransaction([{'txid':txid, 'vout':0}],[{address:0.9999}]) |
| 79 | + signed_raw1 = node.signrawtransactionwithwallet(raw1)['hex'] |
| 80 | + txid1 = node.sendrawtransaction(signed_raw1) |
| 81 | + raw2 = node.createrawtransaction([{'txid':txid1, 'vout':0}],[{address:0.999}]) |
| 82 | + signed_raw2 = node.signrawtransactionwithwallet(raw2)['hex'] |
| 83 | + assert_raises_rpc_error(-25, 'TestBlockValidity failed: bad-txns-inputs-missingorspent', node.generateblock, address, [signed_raw2, txid1]) |
| 84 | + |
| 85 | + self.log.info('Fail to generate block with txid not in mempool') |
| 86 | + missing_txid = '0000000000000000000000000000000000000000000000000000000000000000' |
| 87 | + assert_raises_rpc_error(-5, 'Transaction ' + missing_txid + ' not in mempool.', node.generateblock, address, [missing_txid]) |
| 88 | + |
| 89 | + self.log.info('Fail to generate block with invalid raw tx') |
| 90 | + invalid_raw_tx = '0000' |
| 91 | + assert_raises_rpc_error(-22, 'Transaction decode failed for ' + invalid_raw_tx, node.generateblock, address, [invalid_raw_tx]) |
| 92 | + |
| 93 | + self.log.info('Fail to generate block with invalid address/descriptor') |
| 94 | + assert_raises_rpc_error(-5, 'Invalid address or descriptor', node.generateblock, '1234', []) |
| 95 | + |
| 96 | + self.log.info('Fail to generate block with a ranged descriptor') |
| 97 | + ranged_descriptor = 'pkh(tpubD6NzVbkrYhZ4XgiXtGrdW5XDAPFCL9h7we1vwNCpn8tGbBcgfVYjXyhWo4E1xkh56hjod1RhGjxbaTLV3X4FyWuejifB9jusQ46QzG87VKp/0/*)' |
| 98 | + assert_raises_rpc_error(-8, 'Ranged descriptor not accepted. Maybe pass through deriveaddresses first?', node.generateblock, ranged_descriptor, []) |
| 99 | + |
| 100 | + self.log.info('Fail to generate block with a descriptor missing a private key') |
| 101 | + child_descriptor = 'pkh(tpubD6NzVbkrYhZ4XgiXtGrdW5XDAPFCL9h7we1vwNCpn8tGbBcgfVYjXyhWo4E1xkh56hjod1RhGjxbaTLV3X4FyWuejifB9jusQ46QzG87VKp/0\'/0)' |
| 102 | + assert_raises_rpc_error(-5, 'Cannot derive script without private keys', node.generateblock, child_descriptor, []) |
| 103 | + |
| 104 | +if __name__ == '__main__': |
| 105 | + GenerateBlockTest().main() |
0 commit comments