/ test / functional / rpc_generate.py
rpc_generate.py
  1  #!/usr/bin/env python3
  2  # Copyright (c) 2020-2022 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 generate* RPCs."""
  6  
  7  from test_framework.test_framework import BitcoinTestFramework
  8  from test_framework.wallet import MiniWallet
  9  from test_framework.util import (
 10      assert_equal,
 11      assert_raises_rpc_error,
 12  )
 13  
 14  
 15  class RPCGenerateTest(BitcoinTestFramework):
 16      def set_test_params(self):
 17          self.num_nodes = 1
 18  
 19      def run_test(self):
 20          self.test_generatetoaddress()
 21          self.test_generate()
 22          self.test_generateblock()
 23  
 24      def test_generatetoaddress(self):
 25          self.generatetoaddress(self.nodes[0], 1, 'mneYUmWYsuk7kySiURxCi3AGxrAqZxLgPZ')
 26          assert_raises_rpc_error(-5, "Invalid address", self.generatetoaddress, self.nodes[0], 1, '3J98t1WpEZ73CNmQviecrnyiWrnqRhWNLy')
 27  
 28      def test_generateblock(self):
 29          node = self.nodes[0]
 30          miniwallet = MiniWallet(node)
 31  
 32          self.log.info('Mine an empty block to address and return the hex')
 33          address = miniwallet.get_address()
 34          generated_block = self.generateblock(node, output=address, transactions=[], submit=False)
 35          node.submitblock(hexdata=generated_block['hex'])
 36          assert_equal(generated_block['hash'], node.getbestblockhash())
 37  
 38          self.log.info('Generate an empty block to address')
 39          hash = self.generateblock(node, output=address, transactions=[])['hash']
 40          block = node.getblock(blockhash=hash, verbose=2)
 41          assert_equal(len(block['tx']), 1)
 42          assert_equal(block['tx'][0]['vout'][0]['scriptPubKey']['address'], address)
 43  
 44          self.log.info('Generate an empty block to a descriptor')
 45          hash = self.generateblock(node, 'addr(' + address + ')', [])['hash']
 46          block = node.getblock(blockhash=hash, verbosity=2)
 47          assert_equal(len(block['tx']), 1)
 48          assert_equal(block['tx'][0]['vout'][0]['scriptPubKey']['address'], address)
 49  
 50          self.log.info('Generate an empty block to a combo descriptor with compressed pubkey')
 51          combo_key = '0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798'
 52          combo_address = 'bcrt1qw508d6qejxtdg4y5r3zarvary0c5xw7kygt080'
 53          hash = self.generateblock(node, 'combo(' + combo_key + ')', [])['hash']
 54          block = node.getblock(hash, 2)
 55          assert_equal(len(block['tx']), 1)
 56          assert_equal(block['tx'][0]['vout'][0]['scriptPubKey']['address'], combo_address)
 57  
 58          self.log.info('Generate an empty block to a combo descriptor with uncompressed pubkey')
 59          combo_key = '0408ef68c46d20596cc3f6ddf7c8794f71913add807f1dc55949fa805d764d191c0b7ce6894c126fce0babc6663042f3dde9b0cf76467ea315514e5a6731149c67'
 60          combo_address = 'mkc9STceoCcjoXEXe6cm66iJbmjM6zR9B2'
 61          hash = self.generateblock(node, 'combo(' + combo_key + ')', [])['hash']
 62          block = node.getblock(hash, 2)
 63          assert_equal(len(block['tx']), 1)
 64          assert_equal(block['tx'][0]['vout'][0]['scriptPubKey']['address'], combo_address)
 65  
 66          # Generate some extra mempool transactions to verify they don't get mined
 67          for _ in range(10):
 68              miniwallet.send_self_transfer(from_node=node)
 69  
 70          self.log.info('Generate block with txid')
 71          txid = miniwallet.send_self_transfer(from_node=node)['txid']
 72          hash = self.generateblock(node, address, [txid])['hash']
 73          block = node.getblock(hash, 1)
 74          assert_equal(len(block['tx']), 2)
 75          assert_equal(block['tx'][1], txid)
 76  
 77          self.log.info('Generate block with raw tx')
 78          rawtx = miniwallet.create_self_transfer()['hex']
 79          hash = self.generateblock(node, address, [rawtx])['hash']
 80  
 81          block = node.getblock(hash, 1)
 82          assert_equal(len(block['tx']), 2)
 83          txid = block['tx'][1]
 84          assert_equal(node.getrawtransaction(txid=txid, verbose=False, blockhash=hash), rawtx)
 85  
 86          self.log.info('Fail to generate block with out of order txs')
 87          txid1 = miniwallet.send_self_transfer(from_node=node)['txid']
 88          utxo1 = miniwallet.get_utxo(txid=txid1)
 89          rawtx2 = miniwallet.create_self_transfer(utxo_to_spend=utxo1)['hex']
 90          assert_raises_rpc_error(-25, 'TestBlockValidity failed: bad-txns-inputs-missingorspent', self.generateblock, node, address, [rawtx2, txid1])
 91  
 92          self.log.info('Fail to generate block with txid not in mempool')
 93          missing_txid = '0000000000000000000000000000000000000000000000000000000000000000'
 94          assert_raises_rpc_error(-5, 'Transaction ' + missing_txid + ' not in mempool.', self.generateblock, node, address, [missing_txid])
 95  
 96          self.log.info('Fail to generate block with invalid raw tx')
 97          invalid_raw_tx = '0000'
 98          assert_raises_rpc_error(-22, 'Transaction decode failed for ' + invalid_raw_tx, self.generateblock, node, address, [invalid_raw_tx])
 99  
100          self.log.info('Fail to generate block with invalid address/descriptor')
101          assert_raises_rpc_error(-5, 'Invalid address or descriptor', self.generateblock, node, '1234', [])
102  
103          self.log.info('Fail to generate block with a ranged descriptor')
104          ranged_descriptor = 'pkh(tpubD6NzVbkrYhZ4XgiXtGrdW5XDAPFCL9h7we1vwNCpn8tGbBcgfVYjXyhWo4E1xkh56hjod1RhGjxbaTLV3X4FyWuejifB9jusQ46QzG87VKp/0/*)'
105          assert_raises_rpc_error(-8, 'Ranged descriptor not accepted. Maybe pass through deriveaddresses first?', self.generateblock, node, ranged_descriptor, [])
106  
107          self.log.info('Fail to generate block with a descriptor missing a private key')
108          child_descriptor = 'pkh(tpubD6NzVbkrYhZ4XgiXtGrdW5XDAPFCL9h7we1vwNCpn8tGbBcgfVYjXyhWo4E1xkh56hjod1RhGjxbaTLV3X4FyWuejifB9jusQ46QzG87VKp/0\'/0)'
109          assert_raises_rpc_error(-5, 'Cannot derive script without private keys', self.generateblock, node, child_descriptor, [])
110  
111      def test_generate(self):
112          message = (
113              "generate\n\n"
114              "has been replaced by the -generate "
115              "cli option. Refer to -help for more information.\n"
116          )
117  
118          self.log.info("Test rpc generate raises with message to use cli option")
119          assert_raises_rpc_error(-32601, message, self.nodes[0].rpc.generate)
120  
121          self.log.info("Test rpc generate help prints message to use cli option")
122          assert_equal(message, self.nodes[0].help("generate"))
123  
124          self.log.info("Test rpc generate is a hidden command not discoverable in general help")
125          assert message not in self.nodes[0].help()
126  
127  
128  if __name__ == "__main__":
129      RPCGenerateTest().main()