diff --git a/test/functional/feature_block.py b/test/functional/feature_block.py index 58ef1e761d..ba628b6112 100755 --- a/test/functional/feature_block.py +++ b/test/functional/feature_block.py @@ -56,6 +56,7 @@ from test_framework.wallet_util import generate_keypair from data import invalid_txs +from test_framework.qtumconfig import * # Use this class for tests that require behavior other than normal p2p behavior. # For now, it is used to serialize a bloated varint (b64). @@ -104,13 +105,13 @@ def run_test(self): self.block_heights[self.genesis_hash] = 0 self.spendable_outputs = [] - # Create a new block - b_dup_cb = self.next_block('dup_cb') - b_dup_cb.vtx[0].vin[0].scriptSig = DUPLICATE_COINBASE_SCRIPT_SIG - b_dup_cb.vtx[0].rehash() - duplicate_tx = b_dup_cb.vtx[0] - b_dup_cb = self.update_block('dup_cb', []) - self.send_blocks([b_dup_cb]) + # Create a new block -> QTUM: not possible since the coinbase script must strictly conform to bip34 from genesis + #b_dup_cb = self.next_block('dup_cb') + #b_dup_cb.vtx[0].vin[0].scriptSig = DUPLICATE_COINBASE_SCRIPT_SIG + #b_dup_cb.vtx[0].rehash() + #duplicate_tx = b_dup_cb.vtx[0] + #b_dup_cb = self.update_block('dup_cb', []) + #self.send_blocks([b_dup_cb]) b0 = self.next_block(0) self.save_spendable_output() @@ -118,15 +119,18 @@ def run_test(self): # These constants chosen specifically to trigger an immature coinbase spend # at a certain time below. - NUM_BUFFER_BLOCKS_TO_GENERATE = 99 + # NUM_BUFFER_BLOCKS_TO_GENERATE = 98-15+COINBASE_MATURITY + NUM_BUFFER_BLOCKS_TO_GENERATE = COINBASE_MATURITY-1 NUM_OUTPUTS_TO_COLLECT = 33 # Allow the block to mature blocks = [] for i in range(NUM_BUFFER_BLOCKS_TO_GENERATE): blocks.append(self.next_block(f"maturitybuffer.{i}")) - self.save_spendable_output() - self.send_blocks(blocks) + self.save_spendable_output() + for i in range(0, len(blocks), 100): + self.send_blocks(blocks[i:i+100]) + self.send_blocks(blocks[i:]) # collect spendable outputs now to avoid cluttering the code later on out = [] @@ -222,7 +226,7 @@ def run_test(self): self.log.info("Reject a block where the miner creates too much coinbase reward") self.move_tip(6) b9 = self.next_block(9, spend=out[4], additional_coinbase_value=1) - self.send_blocks([b9], success=False, reject_reason='bad-cb-amount', reconnect=True) + self.send_blocks([b9], success=False, reject_reason='Reward check failed', reconnect=True) # Create a fork that ends in a block with too much fee (the one that causes the reorg) # genesis -> b1 (0) -> b2 (1) -> b5 (2) -> b6 (3) @@ -234,7 +238,7 @@ def run_test(self): self.send_blocks([b10], False) b11 = self.next_block(11, spend=out[4], additional_coinbase_value=1) - self.send_blocks([b11], success=False, reject_reason='bad-cb-amount', reconnect=True) + self.send_blocks([b11], success=False, reject_reason='Reward check failed', reconnect=True) # Try again, but with a valid fork first # genesis -> b1 (0) -> b2 (1) -> b5 (2) -> b6 (3) @@ -247,7 +251,7 @@ def run_test(self): b13 = self.next_block(13, spend=out[4]) self.save_spendable_output() b14 = self.next_block(14, spend=out[5], additional_coinbase_value=1) - self.send_blocks([b12, b13, b14], success=False, reject_reason='bad-cb-amount', reconnect=True) + self.send_blocks([b12, b13, b14], success=False, reject_reason='Reward check failed', reconnect=True) # New tip should be b13. assert_equal(node.getbestblockhash(), b13.hash) @@ -332,7 +336,7 @@ def run_test(self): self.save_spendable_output() self.log.info("Reject a block of weight MAX_BLOCK_WEIGHT + 4") - self.move_tip(15) + self.move_tip(23) b24 = self.next_block(24, spend=out[6]) script_length = (MAX_BLOCK_WEIGHT - b24.get_weight() - 276) // 4 script_output = CScript([b'\x00' * (script_length + 1)]) @@ -340,6 +344,7 @@ def run_test(self): b24 = self.update_block(24, [tx]) assert_equal(b24.get_weight(), MAX_BLOCK_WEIGHT + 1 * 4) self.send_blocks([b24], success=False, reject_reason='bad-blk-length', reconnect=True) + self.move_tip(15) b25 = self.next_block(25, spend=out[7]) self.send_blocks([b25], False) @@ -379,7 +384,7 @@ def run_test(self): self.move_tip(23) b30 = self.next_block(30) b30.vtx[0].vin[0].scriptSig = bytes(b30.vtx[0].vin[0].scriptSig) # Convert CScript to raw bytes - b30.vtx[0].vin[0].scriptSig += b'\x00' * (100 - len(b30.vtx[0].vin[0].scriptSig)) # Fill with 0s + b30.vtx[0].vin[0].scriptSig += b'\x00' * 97 assert_equal(len(b30.vtx[0].vin[0].scriptSig), 100) b30.vtx[0].rehash() b30 = self.update_block(30, []) @@ -629,7 +634,7 @@ def run_test(self): self.tip = b46 assert 46 not in self.blocks self.blocks[46] = b46 - self.send_blocks([b46], success=False, reject_reason='bad-blk-length', reconnect=True) + self.send_blocks([b46], success=False, reject_reason='bad-cb-missing', reconnect=True) self.log.info("Reject a block with invalid work") self.move_tip(44) @@ -644,10 +649,10 @@ def run_test(self): self.log.info("Reject a block with a timestamp >2 hours in the future") self.move_tip(44) b48 = self.next_block(48) - b48.nTime = int(time.time()) + 60 * 60 * 3 + b48.nBits -= 1 # Header timestamp has changed. Re-solve the block. b48.solve() - self.send_blocks([b48], False, force_send=True, reject_reason='time-too-new') + self.send_blocks([b48], False, force_send=True, reconnect=True) self.log.info("Reject a block with invalid merkle hash") self.move_tip(44) @@ -689,9 +694,9 @@ def run_test(self): self.log.info("Reject a block with timestamp before MedianTimePast") b54 = self.next_block(54, spend=out[15]) - b54.nTime = b35.nTime - 1 + b54.nBits -= 1 b54.solve() - self.send_blocks([b54], False, force_send=True, reject_reason='time-too-old', reconnect=True) + self.send_blocks([b54], False, force_send=True, reconnect=True) # valid timestamp self.move_tip(53) @@ -707,14 +712,14 @@ def run_test(self): # -> b31 (8) -> b33 (9) -> b35 (10) -> b39 (11) -> b42 (12) -> b43 (13) -> b53 (14) -> b55 (15) # \-> b54 (15) # -> b44 (14)\-> b48 () -> b48p () - self.log.info("Accept a previously rejected future block at a later time") - node.setmocktime(int(time.time()) + 2*60*60) - self.move_tip(48) - self.block_heights[b48.sha256] = self.block_heights[b44.sha256] + 1 # b48 is a parent of b44 - b48p = self.next_block("48p") - self.send_blocks([b48, b48p], success=True) # Reorg to the longer chain - node.invalidateblock(b48p.hash) # mark b48p as invalid - node.setmocktime(0) + # self.log.info("Accept a previously rejected future block at a later time") + # node.setmocktime(int(time.time()) + 2*60*60) + # self.move_tip(48) + # self.block_heights[b48.sha256] = self.block_heights[b44.sha256] + 1 # b48 is a parent of b44 + # b48p = self.next_block("48p") + # self.send_blocks([b48, b48p], success=True) # Reorg to the longer chain + # node.invalidateblock(b48p.hash) # mark b48p as invalid + # node.setmocktime(0) # Test Merkle tree malleability # @@ -800,16 +805,16 @@ def run_test(self): tx = CTransaction() assert len(out[17].vout) < 42 tx.vin.append(CTxIn(COutPoint(out[17].sha256, 42), CScript([OP_TRUE]), SEQUENCE_FINAL)) - tx.vout.append(CTxOut(0, b"")) + tx.vout.append(CTxOut(0, CScript([OP_TRUE]))) tx.calc_sha256() b58 = self.update_block(58, [tx]) self.send_blocks([b58], success=False, reject_reason='bad-txns-inputs-missingorspent', reconnect=True) # tx with output value > input value self.log.info("Reject a block with a transaction with outputs > inputs") - self.move_tip(57) + self.move_tip("57p2") self.next_block(59) - tx = self.create_and_sign_transaction(out[17], 51 * COIN) + tx = self.create_and_sign_transaction(out[17], int(INITIAL_BLOCK_REWARD+1) * COIN) b59 = self.update_block(59, [tx]) self.send_blocks([b59], success=False, reject_reason='bad-txns-in-belowout', reconnect=True) @@ -828,47 +833,50 @@ def run_test(self): # not-fully-spent transaction in the same chain. To test, make identical coinbases; # the second one should be rejected. See also CVE-2012-1909. # - self.log.info("Reject a block with a transaction with a duplicate hash of a previous transaction (BIP30)") - self.move_tip(60) - b61 = self.next_block(61) - b61.vtx[0].vin[0].scriptSig = DUPLICATE_COINBASE_SCRIPT_SIG - b61.vtx[0].rehash() - b61 = self.update_block(61, []) - assert_equal(duplicate_tx.serialize(), b61.vtx[0].serialize()) - # BIP30 is always checked on regtest, regardless of the BIP34 activation height - self.send_blocks([b61], success=False, reject_reason='bad-txns-BIP30', reconnect=True) + #self.log.info("Reject a block with a transaction with a duplicate hash of a previous transaction (BIP30)") + #self.move_tip(60) + # QTUM: Since we enable BIP34 from block 0, this BIP30 test is no longer relevant. This test has therefore been removed. + # QTUM: Since we enable BIP34 from block 0, this BIP30 test is no longer relevant. This test has therefore been removed. + #self.log.info("Reject a block with a transaction with a duplicate hash of a previous transaction (BIP30)") + #self.move_tip(60) + #b61 = self.next_block(61, spend=out[18]) + #b61.vtx[0].vin[0].scriptSig = b60.vtx[0].vin[0].scriptSig # Equalize the coinbases + #b61.vtx[0].rehash() + #b61 = self.update_block(61, []) + #assert_equal(b60.vtx[0].serialize(), b61.vtx[0].serialize()) + #self.send_blocks([b61], success=False, reject_reason='bad-txns-BIP30', reconnect=True) # Test BIP30 (allow duplicate if spent) # # -> b57 (16) -> b60 () # \-> b_spend_dup_cb (b_dup_cb) -> b_dup_2 () # - self.move_tip(57) - self.next_block('spend_dup_cb') - tx = CTransaction() - tx.vin.append(CTxIn(COutPoint(duplicate_tx.sha256, 0))) - tx.vout.append(CTxOut(0, CScript([OP_TRUE]))) - self.sign_tx(tx, duplicate_tx) - tx.rehash() - b_spend_dup_cb = self.update_block('spend_dup_cb', [tx]) - - b_dup_2 = self.next_block('dup_2') - b_dup_2.vtx[0].vin[0].scriptSig = DUPLICATE_COINBASE_SCRIPT_SIG - b_dup_2.vtx[0].rehash() - b_dup_2 = self.update_block('dup_2', []) - assert_equal(duplicate_tx.serialize(), b_dup_2.vtx[0].serialize()) - assert_equal(self.nodes[0].gettxout(txid=duplicate_tx.hash, n=0)['confirmations'], 119) - self.send_blocks([b_spend_dup_cb, b_dup_2], success=True) - # The duplicate has less confirmations - assert_equal(self.nodes[0].gettxout(txid=duplicate_tx.hash, n=0)['confirmations'], 1) + # self.move_tip(57) + # b_spend_dup_cb = self.next_block('spend_dup_cb') + # tx = CTransaction() + # tx.vin.append(CTxIn(COutPoint(duplicate_tx.sha256, 0))) + # tx.vout.append(CTxOut(0, CScript([OP_TRUE]))) + # self.sign_tx(tx, duplicate_tx) + # tx.rehash() + # b_spend_dup_cb = self.update_block('spend_dup_cb', [tx]) + # + # b_dup_2 = self.next_block('dup_2') + # b_dup_2.vtx[0].vin[0].scriptSig = DUPLICATE_COINBASE_SCRIPT_SIG + # b_dup_2.vtx[0].rehash() + # b_dup_2 = self.update_block('dup_2', []) + # assert_equal(duplicate_tx.serialize(), b_dup_2.vtx[0].serialize()) + # assert_equal(self.nodes[0].gettxout(txid=duplicate_tx.hash, n=0)['confirmations'], 119) + # self.send_blocks([b_spend_dup_cb, b_dup_2], success=True) + # # The duplicate has less confirmations + # assert_equal(self.nodes[0].gettxout(txid=duplicate_tx.hash, n=0)['confirmations'], 1) # Test tx.isFinal is properly rejected (not an exhaustive tx.isFinal test, that should be in data-driven transaction tests) # - # -> b_spend_dup_cb (b_dup_cb) -> b_dup_2 () + # -> b39 (11) -> b42 (12) -> b43 (13) -> b53 (14) -> b55 (15) -> b57 (16) -> b60 (17) # \-> b62 (18) # self.log.info("Reject a block with a transaction with a nonfinal locktime") - self.move_tip('dup_2') + self.move_tip(60) self.next_block(62) tx = CTransaction() tx.nLockTime = 0xffffffff # this locktime is non-final @@ -885,7 +893,7 @@ def run_test(self): # \-> b63 (-) # self.log.info("Reject a block with a coinbase transaction with a nonfinal locktime") - self.move_tip('dup_2') + self.move_tip(60) b63 = self.next_block(63) b63.vtx[0].nLockTime = 0xffffffff b63.vtx[0].vin[0].nSequence = 0xDEADBEEF @@ -894,7 +902,7 @@ def run_test(self): self.send_blocks([b63], success=False, reject_reason='bad-txns-nonfinal', reconnect=True) # This checks that a block with a bloated VARINT between the block_header and the array of tx such that - # the block is > MAX_BLOCK_WEIGHT with the bloated varint, but <= MAX_BLOCK_WEIGHT without the bloated varint, + # the block is > MAX_BLOCK_BASE_SIZE with the bloated varint, but <= MAX_BLOCK_BASE_SIZE without the bloated varint, # does not cause a subsequent, identical block with canonical encoding to be rejected. The test does not # care whether the bloated block is accepted or rejected; it only cares that the second block is accepted. # @@ -908,7 +916,7 @@ def run_test(self): # b64 is a good block (same as b64 but w/ canonical varint) # self.log.info("Accept a valid block even if a bloated version of the block has previously been sent") - self.move_tip('dup_2') + self.move_tip(60) regular_block = self.next_block("64a", spend=out[18]) # make it a "broken_block," with non-canonical serialization @@ -934,7 +942,7 @@ def run_test(self): node.disconnect_p2ps() self.reconnect_p2p() - self.move_tip('dup_2') + self.move_tip(60) b64 = CBlock(b64a) b64.vtx = copy.deepcopy(b64a.vtx) assert_equal(b64.hash, b64a.hash) @@ -1001,7 +1009,7 @@ def run_test(self): self.next_block(68, additional_coinbase_value=10) tx = self.create_and_sign_transaction(out[20], out[20].vout[0].nValue - 9) b68 = self.update_block(68, [tx]) - self.send_blocks([b68], success=False, reject_reason='bad-cb-amount', reconnect=True) + self.send_blocks([b68], success=False, reject_reason='block-reward-invalid', reconnect=True) self.log.info("Accept a block claiming the correct subsidy in the coinbase transaction") self.move_tip(65) @@ -1266,7 +1274,7 @@ def run_test(self): self.log.info("Test a re-org of one week's worth of blocks (1088 blocks)") self.move_tip(88) - LARGE_REORG_SIZE = 1088 + LARGE_REORG_SIZE = 200 blocks = [] spend = out[32] for i in range(89, LARGE_REORG_SIZE + 89): @@ -1282,7 +1290,7 @@ def run_test(self): self.save_spendable_output() spend = self.get_spendable_output() - self.send_blocks(blocks, True, timeout=2440) + self.send_blocks(blocks, True, timeout=480) chain1_tip = i # now create alt chain of same length @@ -1290,18 +1298,18 @@ def run_test(self): blocks2 = [] for i in range(89, LARGE_REORG_SIZE + 89): blocks2.append(self.next_block("alt" + str(i))) - self.send_blocks(blocks2, False, force_send=False) + self.send_blocks(blocks2, False, force_send=True) # extend alt chain to trigger re-org block = self.next_block("alt" + str(chain1_tip + 1)) - self.send_blocks([block], True, timeout=2440) + self.send_blocks([block], True, timeout=480) # ... and re-org back to the first chain self.move_tip(chain1_tip) block = self.next_block(chain1_tip + 1) self.send_blocks([block], False, force_send=True) block = self.next_block(chain1_tip + 2) - self.send_blocks([block], True, timeout=2440) + self.send_blocks([block], True, timeout=480) self.log.info("Reject a block with an invalid block header version") b_v1 = self.next_block('b_v1', version=1) @@ -1313,7 +1321,7 @@ def run_test(self): b_cb34.vtx[0].rehash() b_cb34.hashMerkleRoot = b_cb34.calc_merkle_root() b_cb34.solve() - self.send_blocks([b_cb34], success=False, reject_reason='bad-cb-height', reconnect=True) + self.send_blocks([b_cb34], success=False, reject_reason='block height mismatch in coinbase', force_send=True, reconnect=True) # Helper methods ################ diff --git a/test/functional/feature_coinstatsindex.py b/test/functional/feature_coinstatsindex.py index d6c1567e64..abfc06da9f 100755 --- a/test/functional/feature_coinstatsindex.py +++ b/test/functional/feature_coinstatsindex.py @@ -55,7 +55,7 @@ def run_test(self): self._test_init_index_after_reorg() def block_sanity_check(self, block_info): - block_subsidy = 50 + block_subsidy = 20000 assert_equal( block_info['prevout_spent'] + block_subsidy, block_info['new_outputs_ex_coinbase'] + block_info['coinbase'] + block_info['unspendable'] @@ -97,7 +97,7 @@ def _test_coin_stats_index(self): for hash_option in index_hash_options: # Fetch old stats by height - res2 = index_node.gettxoutsetinfo(hash_option, 102) + res2 = index_node.gettxoutsetinfo(hash_option, 2002) del res2['block_info'], res2['total_unspendable_amount'] res2.pop('muhash', None) assert_equal(res0, res2) @@ -116,14 +116,14 @@ def _test_coin_stats_index(self): for hash_option in index_hash_options: # Genesis block is unspendable res4 = index_node.gettxoutsetinfo(hash_option, 0) - assert_equal(res4['total_unspendable_amount'], 50) + assert_equal(res4['total_unspendable_amount'], 20000) assert_equal(res4['block_info'], { - 'unspendable': 50, + 'unspendable': 20000, 'prevout_spent': 0, 'new_outputs_ex_coinbase': 0, 'coinbase': 0, 'unspendables': { - 'genesis_block': 50, + 'genesis_block': 20000, 'bip30': 0, 'scripts': 0, 'unclaimed_rewards': 0 @@ -132,18 +132,18 @@ def _test_coin_stats_index(self): self.block_sanity_check(res4['block_info']) # Test an older block height that included a normal tx - res5 = index_node.gettxoutsetinfo(hash_option, 102) - assert_equal(res5['total_unspendable_amount'], 50) + res5 = index_node.gettxoutsetinfo(hash_option, 2002) + assert_equal(res5['total_unspendable_amount'], 20000) assert_equal(res5['block_info'], { - 'unspendable': 0, - 'prevout_spent': 50, - 'new_outputs_ex_coinbase': Decimal('49.99968800'), - 'coinbase': Decimal('50.00031200'), + 'unspendable': Decimal('0E-8'), + 'prevout_spent': Decimal('20000.00000000'), + 'new_outputs_ex_coinbase': Decimal('19999.99688000'), + 'coinbase': Decimal('20000.00312000'), 'unspendables': { - 'genesis_block': 0, - 'bip30': 0, - 'scripts': 0, - 'unclaimed_rewards': 0, + 'genesis_block': Decimal('0E-8'), + 'bip30': Decimal('0E-8'), + 'scripts': Decimal('0E-8'), + 'unclaimed_rewards': Decimal('0E-8'), } }) self.block_sanity_check(res5['block_info']) @@ -170,26 +170,26 @@ def _test_coin_stats_index(self): for hash_option in index_hash_options: # Check all amounts were registered correctly - res6 = index_node.gettxoutsetinfo(hash_option, 108) - assert_equal(res6['total_unspendable_amount'], Decimal('70.99000000')) + res6 = index_node.gettxoutsetinfo(hash_option, 2008) + assert_equal(res6['total_unspendable_amount'], Decimal('20020.99000000')) assert_equal(res6['block_info'], { 'unspendable': Decimal('20.99000000'), - 'prevout_spent': 71, - 'new_outputs_ex_coinbase': Decimal('49.99999000'), - 'coinbase': Decimal('50.01001000'), + 'prevout_spent': Decimal('20021.00000000'), + 'new_outputs_ex_coinbase': Decimal('19999.99920000'), + 'coinbase': Decimal('20000.01080000'), 'unspendables': { - 'genesis_block': 0, - 'bip30': 0, + 'genesis_block': Decimal('0E-8'), + 'bip30': Decimal('0E-8'), 'scripts': Decimal('20.99000000'), - 'unclaimed_rewards': 0, + 'unclaimed_rewards': Decimal('0E-8'), } }) self.block_sanity_check(res6['block_info']) # Create a coinbase that does not claim full subsidy and also # has two outputs - cb = create_coinbase(109, nValue=35) - cb.vout.append(CTxOut(5 * COIN, CScript([OP_FALSE]))) + cb = create_coinbase(2009, nValue=35) + cb.vout.append(CTxOut(5000 * COIN, CScript([OP_FALSE]))) cb.rehash() # Generate a block that includes previous coinbase @@ -201,18 +201,18 @@ def _test_coin_stats_index(self): self.sync_all() for hash_option in index_hash_options: - res7 = index_node.gettxoutsetinfo(hash_option, 109) - assert_equal(res7['total_unspendable_amount'], Decimal('80.99000000')) + res7 = index_node.gettxoutsetinfo(hash_option, 2009) + assert_equal(res7['total_unspendable_amount'], Decimal('35020.98999965')) assert_equal(res7['block_info'], { - 'unspendable': 10, + 'unspendable': Decimal('14999.99999965'), 'prevout_spent': 0, 'new_outputs_ex_coinbase': 0, - 'coinbase': 40, + 'coinbase': Decimal('5000.00000035'), 'unspendables': { 'genesis_block': 0, 'bip30': 0, 'scripts': 0, - 'unclaimed_rewards': 10 + 'unclaimed_rewards': Decimal('14999.99999965') } }) self.block_sanity_check(res7['block_info']) @@ -246,7 +246,7 @@ def _test_use_index_option(self): self.log.info("Test use_index option for nodes running the index") self.connect_nodes(0, 1) - self.nodes[0].waitforblockheight(110) + self.nodes[0].waitforblockheight(2010) res = self.nodes[0].gettxoutsetinfo('muhash') option_res = self.nodes[1].gettxoutsetinfo(hash_type='muhash', hash_or_height=None, use_index=False) del res['disk_size'], option_res['disk_size'] @@ -262,14 +262,14 @@ def _test_reorg_index(self): self.sync_index_node() res_invalid = index_node.gettxoutsetinfo('muhash') index_node.invalidateblock(reorg_blocks[0]) - assert_equal(index_node.gettxoutsetinfo('muhash')['height'], 110) + assert_equal(index_node.gettxoutsetinfo('muhash')['height'], 2010) # Add two new blocks block = self.generate(index_node, 2, sync_fun=self.no_op)[1] res = index_node.gettxoutsetinfo(hash_type='muhash', hash_or_height=None, use_index=False) # Test that the result of the reorged block is not returned for its old block height - res2 = index_node.gettxoutsetinfo(hash_type='muhash', hash_or_height=112) + res2 = index_node.gettxoutsetinfo(hash_type='muhash', hash_or_height=2012) assert_equal(res["bestblock"], block) assert_equal(res["muhash"], res2["muhash"]) assert res["muhash"] != res_invalid["muhash"] @@ -284,20 +284,20 @@ def _test_reorg_index(self): self.generate(index_node, 1) # Ensure that removing and re-adding blocks yields consistent results - block = index_node.getblockhash(99) + block = index_node.getblockhash(1999) index_node.invalidateblock(block) index_node.reconsiderblock(block) - res3 = index_node.gettxoutsetinfo(hash_type='muhash', hash_or_height=112) + res3 = index_node.gettxoutsetinfo(hash_type='muhash', hash_or_height=2012) assert_equal(res2, res3) def _test_index_rejects_hash_serialized(self): self.log.info("Test that the rpc raises if the legacy hash is passed with the index") msg = "hash_serialized_3 hash type cannot be queried for a specific block" - assert_raises_rpc_error(-8, msg, self.nodes[1].gettxoutsetinfo, hash_type='hash_serialized_3', hash_or_height=111) + assert_raises_rpc_error(-8, msg, self.nodes[1].gettxoutsetinfo, hash_type='hash_serialized_3', hash_or_height=2011) for use_index in {True, False, None}: - assert_raises_rpc_error(-8, msg, self.nodes[1].gettxoutsetinfo, hash_type='hash_serialized_3', hash_or_height=111, use_index=use_index) + assert_raises_rpc_error(-8, msg, self.nodes[1].gettxoutsetinfo, hash_type='hash_serialized_3', hash_or_height=2011, use_index=use_index) def _test_init_index_after_reorg(self): self.log.info("Test a reorg while the index is deactivated") diff --git a/test/functional/feature_segwit.py b/test/functional/feature_segwit.py index 6c467fa613..7d39ee014d 100755 --- a/test/functional/feature_segwit.py +++ b/test/functional/feature_segwit.py @@ -5,6 +5,8 @@ """Test the SegWit changeover logic.""" from decimal import Decimal +from io import BytesIO +import time from test_framework.address import ( key_to_p2pkh, @@ -16,6 +18,8 @@ from test_framework.blocktools import ( send_to_witness, witness_script, + create_block, + create_coinbase, ) from test_framework.descriptors import descsum_create from test_framework.messages import ( @@ -47,11 +51,15 @@ assert_greater_than_or_equal, assert_is_hex_string, assert_raises_rpc_error, + bytes_to_hex_str, + hex_str_to_bytes, try_rpc, ) from test_framework.wallet_util import ( get_generate_key, ) +from test_framework.qtumconfig import COINBASE_MATURITY, INITIAL_BLOCK_REWARD, ENABLE_REDUCED_BLOCK_TIME, MAX_BLOCK_BASE_SIZE, MAX_BLOCK_SIGOPS, FACTOR_REDUCED_BLOCK_TIME +from test_framework.qtum import convert_btc_address_to_qtum, generatesynchronized NODE_0 = 0 NODE_2 = 2 @@ -65,6 +73,10 @@ def getutxo(txid): utxo["txid"] = txid return utxo +def find_unspent(node, min_value): + for utxo in node.listunspent(): + if utxo['amount'] >= min_value: + return utxo def find_spendable_utxo(node, min_value): for utxo in node.listunspent(query_options={'minimumAmount': min_value}): @@ -90,18 +102,18 @@ def set_test_params(self): "-acceptnonstdtxn=1", "-rpcserialversion=0", "-deprecatedrpc=serialversion", - "-testactivationheight=segwit@165", + "-testactivationheight=segwit@2357" if ENABLE_REDUCED_BLOCK_TIME else "-testactivationheight=segwit@857", "-addresstype=legacy", ], [ "-acceptnonstdtxn=1", "-rpcserialversion=1", - "-testactivationheight=segwit@165", + "-testactivationheight=segwit@2357" if ENABLE_REDUCED_BLOCK_TIME else "-testactivationheight=segwit@857", "-addresstype=legacy", ], [ "-acceptnonstdtxn=1", - "-testactivationheight=segwit@165", + "-testactivationheight=segwit@2357" if ENABLE_REDUCED_BLOCK_TIME else "-testactivationheight=segwit@857", "-addresstype=legacy", ], ] @@ -116,23 +128,31 @@ def setup_network(self): self.sync_all() def success_mine(self, node, txid, sign, redeem_script=""): - send_to_witness(1, node, getutxo(txid), self.pubkey[0], False, Decimal("49.998"), sign, redeem_script) + send_to_witness(1, node, getutxo(txid), self.pubkey[0], False, INITIAL_BLOCK_REWARD - Decimal("0.002"), sign, redeem_script) block = self.generate(node, 1) assert_equal(len(node.getblock(block[0])["tx"]), 2) self.sync_blocks() def fail_accept(self, node, error_msg, txid, sign, redeem_script=""): - assert_raises_rpc_error(-26, error_msg, send_to_witness, use_p2wsh=1, node=node, utxo=getutxo(txid), pubkey=self.pubkey[0], encode_p2sh=False, amount=Decimal("49.998"), sign=sign, insert_redeem_script=redeem_script) + assert_raises_rpc_error(-26, error_msg, send_to_witness, use_p2wsh=1, node=node, utxo=getutxo(txid), pubkey=self.pubkey[0], encode_p2sh=False, amount=INITIAL_BLOCK_REWARD - Decimal("0.002"), sign=sign, insert_redeem_script=redeem_script) def run_test(self): self.generate(self.nodes[0], 161) # block 161 + for i in range((4*4*144 if ENABLE_REDUCED_BLOCK_TIME else 4*144) - 161): + block = create_block(int(self.nodes[0].getbestblockhash(), 16), create_coinbase(self.nodes[0].getblockcount() + 1), int(time.time())+2+i) + block.nVersion = 4 + block.hashMerkleRoot = block.calc_merkle_root() + block.rehash() + block.solve() + self.nodes[0].submitblock(bytes_to_hex_str(block.serialize())) + generatesynchronized(self.nodes[0], 18, None, self.nodes) self.log.info("Verify sigops are counted in GBT with pre-BIP141 rules before the fork") txid = self.nodes[0].sendtoaddress(self.nodes[0].getnewaddress(), 1) tmpl = self.nodes[0].getblocktemplate({'rules': ['segwit']}) - assert_equal(tmpl['sizelimit'], 1000000) + assert_equal(tmpl['sizelimit'], MAX_BLOCK_BASE_SIZE) assert 'weightlimit' not in tmpl - assert_equal(tmpl['sigoplimit'], 20000) + assert_equal(tmpl['sigoplimit'], MAX_BLOCK_SIGOPS) assert_equal(tmpl['transactions'][0]['hash'], txid) assert_equal(tmpl['transactions'][0]['sigops'], 2) assert '!segwit' not in tmpl['rules'] @@ -185,15 +205,16 @@ def run_test(self): for _ in range(5): for n in range(3): for v in range(2): - wit_ids[n][v].append(send_to_witness(v, self.nodes[0], find_spendable_utxo(self.nodes[0], 50), self.pubkey[n], False, Decimal("49.999"))) - p2sh_ids[n][v].append(send_to_witness(v, self.nodes[0], find_spendable_utxo(self.nodes[0], 50), self.pubkey[n], True, Decimal("49.999"))) + wit_ids[n][v].append(send_to_witness(v, self.nodes[0], find_spendable_utxo(self.nodes[0], INITIAL_BLOCK_REWARD), self.pubkey[n], False, INITIAL_BLOCK_REWARD - Decimal("0.001"))) + p2sh_ids[n][v].append(send_to_witness(v, self.nodes[0], find_spendable_utxo(self.nodes[0], INITIAL_BLOCK_REWARD), self.pubkey[n], True, INITIAL_BLOCK_REWARD - Decimal("0.001"))) self.generate(self.nodes[0], 1) # block 163 # Make sure all nodes recognize the transactions as theirs - assert_equal(self.nodes[0].getbalance(), balance_presetup - 60 * 50 + 20 * Decimal("49.999") + 50) - assert_equal(self.nodes[1].getbalance(), 20 * Decimal("49.999")) - assert_equal(self.nodes[2].getbalance(), 20 * Decimal("49.999")) + assert_equal(self.nodes[0].getbalance(), balance_presetup - 60 * INITIAL_BLOCK_REWARD + 20 * (INITIAL_BLOCK_REWARD - Decimal("0.001")) + (0 if ENABLE_REDUCED_BLOCK_TIME else INITIAL_BLOCK_REWARD)) + assert_equal(self.nodes[1].getbalance(), 20 * (INITIAL_BLOCK_REWARD - Decimal("0.001"))) + assert_equal(self.nodes[2].getbalance(), 20 * (INITIAL_BLOCK_REWARD - Decimal("0.001"))) + self.nodes[0].generate(32 if ENABLE_REDUCED_BLOCK_TIME else 260) # block 423 self.log.info("Verify unsigned p2sh witness txs without a redeem script are invalid") self.fail_accept(self.nodes[2], "mandatory-script-verify-flag-failed (Operation not valid with the current stack size)", p2sh_ids[NODE_2][P2WPKH][1], sign=False) @@ -203,10 +224,10 @@ def run_test(self): self.log.info("Verify witness txs are mined as soon as segwit activates") - send_to_witness(1, self.nodes[2], getutxo(wit_ids[NODE_2][P2WPKH][0]), self.pubkey[0], encode_p2sh=False, amount=Decimal("49.998"), sign=True) - send_to_witness(1, self.nodes[2], getutxo(wit_ids[NODE_2][P2WSH][0]), self.pubkey[0], encode_p2sh=False, amount=Decimal("49.998"), sign=True) - send_to_witness(1, self.nodes[2], getutxo(p2sh_ids[NODE_2][P2WPKH][0]), self.pubkey[0], encode_p2sh=False, amount=Decimal("49.998"), sign=True) - send_to_witness(1, self.nodes[2], getutxo(p2sh_ids[NODE_2][P2WSH][0]), self.pubkey[0], encode_p2sh=False, amount=Decimal("49.998"), sign=True) + send_to_witness(1, self.nodes[2], getutxo(wit_ids[NODE_2][P2WPKH][0]), self.pubkey[0], encode_p2sh=False, amount=INITIAL_BLOCK_REWARD - Decimal("0.002"), sign=True) + send_to_witness(1, self.nodes[2], getutxo(wit_ids[NODE_2][P2WSH][0]), self.pubkey[0], encode_p2sh=False, amount=INITIAL_BLOCK_REWARD - Decimal("0.002"), sign=True) + send_to_witness(1, self.nodes[2], getutxo(p2sh_ids[NODE_2][P2WPKH][0]), self.pubkey[0], encode_p2sh=False, amount=INITIAL_BLOCK_REWARD - Decimal("0.002"), sign=True) + send_to_witness(1, self.nodes[2], getutxo(p2sh_ids[NODE_2][P2WSH][0]), self.pubkey[0], encode_p2sh=False, amount=INITIAL_BLOCK_REWARD - Decimal("0.002"), sign=True) assert_equal(len(self.nodes[2].getrawmempool()), 4) blockhash = self.generate(self.nodes[2], 1)[0] # block 165 (first block with new rules) @@ -260,9 +281,9 @@ def run_test(self): txid = self.nodes[0].sendtoaddress(self.nodes[0].getnewaddress(), 1) raw_tx = self.nodes[0].getrawtransaction(txid, True) tmpl = self.nodes[0].getblocktemplate({'rules': ['segwit']}) - assert_greater_than_or_equal(tmpl['sizelimit'], 3999577) # actual maximum size is lower due to minimum mandatory non-witness data - assert_equal(tmpl['weightlimit'], 4000000) - assert_equal(tmpl['sigoplimit'], 80000) + assert_greater_than_or_equal(tmpl['sizelimit'], 7999577/FACTOR_REDUCED_BLOCK_TIME) # actual maximum size is lower due to minimum mandatory non-witness data + assert_equal(tmpl['weightlimit'], 8000000//FACTOR_REDUCED_BLOCK_TIME) + assert_equal(tmpl['sigoplimit'], 80000//FACTOR_REDUCED_BLOCK_TIME) assert_equal(tmpl['transactions'][0]['txid'], txid) expected_sigops = 9 if 'txinwitness' in raw_tx["vin"][0] else 8 assert_equal(tmpl['transactions'][0]['sigops'], expected_sigops) @@ -275,7 +296,7 @@ def run_test(self): # tx2 (segwit input, paying to a non-segwit output) -> # tx3 (non-segwit input, paying to a non-segwit output). # tx1 is allowed to appear in the block, but no others. - txid1 = send_to_witness(1, self.nodes[0], find_spendable_utxo(self.nodes[0], 50), self.pubkey[0], False, Decimal("49.996")) + txid1 = send_to_witness(1, self.nodes[0], find_spendable_utxo(self.nodes[0], INITIAL_BLOCK_REWARD), self.pubkey[0], False, INITIAL_BLOCK_REWARD - Decimal("0.004")) hex_tx = self.nodes[0].gettransaction(txid)['hex'] tx = tx_from_hex(hex_tx) assert tx.wit.is_null() # This should not be a segwit input @@ -294,7 +315,7 @@ def run_test(self): # Now create tx2, which will spend from txid1. tx = CTransaction() tx.vin.append(CTxIn(COutPoint(int(txid1, 16), 0), b'')) - tx.vout.append(CTxOut(int(49.99 * COIN), CScript([OP_TRUE, OP_DROP] * 15 + [OP_TRUE]))) + tx.vout.append(CTxOut(int((INITIAL_BLOCK_REWARD-Decimal('0.01')) * COIN), CScript([OP_TRUE, OP_DROP] * 15 + [OP_TRUE]))) tx2_hex = self.nodes[0].signrawtransactionwithwallet(tx.serialize().hex())['hex'] txid2 = self.nodes[0].sendrawtransaction(tx2_hex) tx = tx_from_hex(tx2_hex) @@ -310,7 +331,7 @@ def run_test(self): # Now create tx3, which will spend from txid2 tx = CTransaction() tx.vin.append(CTxIn(COutPoint(int(txid2, 16), 0), b"")) - tx.vout.append(CTxOut(int(49.95 * COIN), CScript([OP_TRUE, OP_DROP] * 15 + [OP_TRUE]))) # Huge fee + tx.vout.append(CTxOut(int((INITIAL_BLOCK_REWARD-Decimal('0.05')) * COIN), CScript([OP_TRUE, OP_DROP] * 15 + [OP_TRUE]))) # Huge fee tx.calc_sha256() txid3 = self.nodes[0].sendrawtransaction(hexstring=tx.serialize().hex(), maxfeerate=0) assert tx.wit.is_null() @@ -349,9 +370,9 @@ def run_test(self): # Import a compressed key and an uncompressed key, generate some multisig addresses self.nodes[0].importprivkey("92e6XLo5jVAVwrQKPNTs93oQco8f8sDNBcpv73Dsrs397fQtFQn") - uncompressed_spendable_address = ["mvozP4UwyGD2mGZU4D2eMvMLPB9WkMmMQu"] + uncompressed_spendable_address = [convert_btc_address_to_qtum("mvozP4UwyGD2mGZU4D2eMvMLPB9WkMmMQu")] self.nodes[0].importprivkey("cNC8eQ5dg3mFAVePDX4ddmPYpPbw41r9bm2jd1nLJT77e6RrzTRR") - compressed_spendable_address = ["mmWQubrDomqpgSYekvsU7HWEVjLFHAakLe"] + compressed_spendable_address = [convert_btc_address_to_qtum("mmWQubrDomqpgSYekvsU7HWEVjLFHAakLe")] assert not self.nodes[0].getaddressinfo(uncompressed_spendable_address[0])['iscompressed'] assert self.nodes[0].getaddressinfo(compressed_spendable_address[0])['iscompressed'] @@ -375,6 +396,7 @@ def run_test(self): uncompressed_solvable_address.append(self.nodes[0].addmultisigaddress(2, [compressed_spendable_address[0], uncompressed_solvable_address[0]])['address']) compressed_solvable_address.append(self.nodes[0].addmultisigaddress(2, [compressed_spendable_address[0], compressed_solvable_address[0]])['address']) compressed_solvable_address.append(self.nodes[0].addmultisigaddress(2, [compressed_solvable_address[0], compressed_solvable_address[1]])['address']) + unknown_address = [convert_btc_address_to_qtum("mtKKyoHabkk6e4ppT7NaM7THqPUt7AzPrT"), convert_btc_address_to_qtum("2NDP3jLWAFT8NDAiUa9qiE6oBt2awmMq7Dx")] # Test multisig_without_privkey # We have 2 public keys without private keys, use addmultisigaddress to add to wallet. @@ -455,6 +477,7 @@ def run_test(self): op1 = CScript([OP_1]) op0 = CScript([OP_0]) # 2N7MGY19ti4KDMSzRfPAssP6Pxyuxoi6jLe is the P2SH(P2PKH) version of mjoE3sSrb8ByYEvgnC3Aox86u1CHnfJA4V + unsolvable_address = [convert_btc_address_to_qtum("mjoE3sSrb8ByYEvgnC3Aox86u1CHnfJA4V"), convert_btc_address_to_qtum("2N7MGY19ti4KDMSzRfPAssP6Pxyuxoi6jLe"), script_to_p2sh(op1), script_to_p2sh(op0)] unsolvable_address_key = bytes.fromhex("02341AEC7587A51CDE5279E0630A531AEA2615A9F80B17E8D9376327BAEAA59E3D") unsolvablep2pkh = key_to_p2pkh_script(unsolvable_address_key) unsolvablep2wshp2pkh = script_to_p2wsh_script(unsolvablep2pkh) @@ -516,9 +539,9 @@ def run_test(self): # Repeat some tests. This time we don't add witness scripts with importaddress # Import a compressed key and an uncompressed key, generate some multisig addresses self.nodes[0].importprivkey("927pw6RW8ZekycnXqBQ2JS5nPyo1yRfGNN8oq74HeddWSpafDJH") - uncompressed_spendable_address = ["mguN2vNSCEUh6rJaXoAVwY3YZwZvEmf5xi"] + uncompressed_spendable_address = [convert_btc_address_to_qtum("mguN2vNSCEUh6rJaXoAVwY3YZwZvEmf5xi")] self.nodes[0].importprivkey("cMcrXaaUC48ZKpcyydfFo8PxHAjpsYLhdsp6nmtB3E2ER9UUHWnw") - compressed_spendable_address = ["n1UNmpmbVUJ9ytXYXiurmGPQ3TRrXqPWKL"] + compressed_spendable_address = [convert_btc_address_to_qtum("n1UNmpmbVUJ9ytXYXiurmGPQ3TRrXqPWKL")] self.nodes[0].importpubkey(pubkeys[5]) compressed_solvable_address = [key_to_p2pkh(pubkeys[5])] @@ -668,11 +691,13 @@ def p2pkh_address_to_script(self, v): def create_and_mine_tx_from_txids(self, txids, success=True): tx = CTransaction() for i in txids: + txtmp = CTransaction() txraw = self.nodes[0].getrawtransaction(i, 0, txs_mined[i]) - txtmp = tx_from_hex(txraw) + f = BytesIO(hex_str_to_bytes(txraw)) + txtmp.deserialize(f) for j in range(len(txtmp.vout)): tx.vin.append(CTxIn(COutPoint(int('0x' + i, 0), j))) - tx.vout.append(CTxOut(0, CScript())) + tx.vout.append(CTxOut(0, CScript([OP_TRUE]))) tx.rehash() signresults = self.nodes[0].signrawtransactionwithwallet(tx.serialize_without_witness().hex())['hex'] self.nodes[0].sendrawtransaction(hexstring=signresults, maxfeerate=0) diff --git a/test/functional/p2p_segwit.py b/test/functional/p2p_segwit.py index d316c4b602..34d3073f4d 100755 --- a/test/functional/p2p_segwit.py +++ b/test/functional/p2p_segwit.py @@ -86,14 +86,18 @@ assert_equal, softfork_active, assert_raises_rpc_error, + bytes_to_hex_str, + hex_str_to_bytes, ) from test_framework.wallet import MiniWallet from test_framework.wallet_util import generate_keypair +from test_framework.qtumconfig import * +from test_framework.qtum import generatesynchronized +from test_framework.messages import COIN +MAX_SIGOP_COST = 80000 // FACTOR_REDUCED_BLOCK_TIME -MAX_SIGOP_COST = 80000 - -SEGWIT_HEIGHT = 120 +SEGWIT_HEIGHT = 2020 if ENABLE_REDUCED_BLOCK_TIME else 520 class UTXO(): """Used to keep track of anyone-can-spend outputs that we can use in the tests.""" @@ -124,6 +128,23 @@ def sign_p2pk_witness_input(script, tx_to, in_idx, hashtype, value, key): tx_to.wit.vtxinwit[in_idx].scriptWitness.stack = [script] sign_input_segwitv0(tx_to, in_idx, script, value, key, hashtype) +def submit_old_blocks(node, n): + node.importprivkey("cRComRro8wTGnDTGqgpyP5vwwo24Tn831cPu3PZEdr2532JVPjrZ") + pubkey = "03716d5678c829d09cdfdb4bec058712de3ecd99968a4a064336ffb592342e21f9" + num_blocks_old = node.getblockcount() + for i in range(0, n): + tip = node.getbestblockhash() + height = node.getblockcount() + 1 + block_time = node.getblockheader(tip)["mediantime"] + 1 + block = create_block(int(tip, 16), create_coinbase(height), block_time) + block.vtx[0].vout[0].scriptPubKey = CScript([hex_str_to_bytes(pubkey), OP_CHECKSIG]) + block.vtx[0].rehash() + block.hashMerkleRoot = block.calc_merkle_root() + block.rehash() + block.solve() + node.submitblock(bytes_to_hex_str(block.serialize())) + assert_equal(node.getblockcount(), num_blocks_old+n) + def test_transaction_acceptance(node, p2p, tx, with_witness, accepted, reason=None): """Send a transaction to the node and check that it's accepted to the mempool @@ -222,12 +243,13 @@ def set_test_params(self): # Helper functions - def build_next_block(self): + def build_next_block(self, version=4): """Build a block on top of node0's tip.""" tip = self.nodes[0].getbestblockhash() height = self.nodes[0].getblockcount() + 1 block_time = self.nodes[0].getblockheader(tip)["mediantime"] + 1 block = create_block(int(tip, 16), create_coinbase(height), block_time) + block.nVersion = version block.rehash() return block @@ -299,17 +321,18 @@ def test_non_witness_transaction(self): # Mine a block with an anyone-can-spend coinbase, # let it mature, then try to spend it. - block = self.build_next_block() + block = self.build_next_block(version=4) block.solve() self.test_node.send_and_ping(msg_no_witness_block(block)) # make sure the block was processed txid = block.vtx[0].sha256 - self.generate(self.wallet, 99) # let the block mature + # submit_old_blocks(self.nodes[0], COINBASE_MATURITY - 1) # let the block mature + self.generate(self.nodes[0], COINBASE_MATURITY - 1) # let the block mature # Create a transaction that spends the coinbase tx = CTransaction() tx.vin.append(CTxIn(COutPoint(txid, 0), b"")) - tx.vout.append(CTxOut(49 * 100000000, CScript([OP_TRUE, OP_DROP] * 15 + [OP_TRUE]))) + tx.vout.append(CTxOut(int((INITIAL_BLOCK_REWARD-Decimal('0.01')) * COIN), CScript([OP_TRUE, OP_DROP] * 15 + [OP_TRUE]))) tx.calc_sha256() # Check that serializing it with or without witness is the same @@ -319,7 +342,7 @@ def test_non_witness_transaction(self): self.test_node.send_and_ping(msg_tx(tx)) # make sure the block was processed assert tx.hash in self.nodes[0].getrawmempool() # Save this transaction for later - self.utxo.append(UTXO(tx.sha256, 0, 49 * 100000000)) + self.utxo.append(UTXO(tx.sha256, 0, (INITIAL_BLOCK_REWARD - 1) * 100000000)) self.generate(self.nodes[0], 1) @subtest @@ -526,7 +549,7 @@ def test_witness_tx_relay_before_segwit_activation(self): # not be added to recently rejected list. tx = CTransaction() tx.vin.append(CTxIn(COutPoint(self.utxo[0].sha256, self.utxo[0].n), b"")) - tx.vout.append(CTxOut(self.utxo[0].nValue - 1000, CScript([OP_TRUE, OP_DROP] * 15 + [OP_TRUE]))) + tx.vout.append(CTxOut(self.utxo[0].nValue - 100000, CScript([OP_TRUE, OP_DROP] * 15 + [OP_TRUE]))) tx.wit.vtxinwit.append(CTxInWitness()) tx.wit.vtxinwit[0].scriptWitness.stack = [b'a'] tx.rehash() @@ -574,7 +597,7 @@ def test_standardness_v0(self): # First prepare a p2sh output (so that spending it will pass standardness) p2sh_tx = CTransaction() p2sh_tx.vin = [CTxIn(COutPoint(self.utxo[0].sha256, self.utxo[0].n), b"")] - p2sh_tx.vout = [CTxOut(self.utxo[0].nValue - 1000, p2sh_script_pubkey)] + p2sh_tx.vout = [CTxOut(self.utxo[0].nValue - 100000, p2sh_script_pubkey)] p2sh_tx.rehash() # Mine it on test_node to create the confirmed output. @@ -585,8 +608,8 @@ def test_standardness_v0(self): # Start by creating a transaction with two outputs. tx = CTransaction() tx.vin = [CTxIn(COutPoint(p2sh_tx.sha256, 0), CScript([witness_script]))] - tx.vout = [CTxOut(p2sh_tx.vout[0].nValue - 10000, script_pubkey)] - tx.vout.append(CTxOut(8000, script_pubkey)) # Might burn this later + tx.vout = [CTxOut(p2sh_tx.vout[0].nValue - 1000000, script_pubkey)] + tx.vout.append(CTxOut(800000, script_pubkey)) # Might burn this later tx.vin[0].nSequence = MAX_BIP125_RBF_SEQUENCE # Just to have the option to bump this tx from the mempool tx.rehash() @@ -600,7 +623,7 @@ def test_standardness_v0(self): tx2 = CTransaction() # tx was accepted, so we spend the second output. tx2.vin = [CTxIn(COutPoint(tx.sha256, 1), b"")] - tx2.vout = [CTxOut(7000, script_pubkey)] + tx2.vout = [CTxOut(700000, script_pubkey)] tx2.wit.vtxinwit.append(CTxInWitness()) tx2.wit.vtxinwit[0].scriptWitness.stack = [witness_script] tx2.rehash() @@ -613,7 +636,7 @@ def test_standardness_v0(self): # P2PKH output; just send tx's first output back to an anyone-can-spend. self.sync_mempools([self.nodes[0], self.nodes[1]]) tx3.vin = [CTxIn(COutPoint(tx.sha256, 0), b"")] - tx3.vout = [CTxOut(tx.vout[0].nValue - 1000, CScript([OP_TRUE, OP_DROP] * 15 + [OP_TRUE]))] + tx3.vout = [CTxOut(tx.vout[0].nValue - 100000, CScript([OP_TRUE, OP_DROP] * 15 + [OP_TRUE]))] tx3.wit.vtxinwit.append(CTxInWitness()) tx3.wit.vtxinwit[0].scriptWitness.stack = [witness_script] tx3.rehash() @@ -630,7 +653,7 @@ def test_standardness_v0(self): 'allowed': True, 'vsize': tx3.get_vsize(), 'fees': { - 'base': Decimal('0.00001000'), + 'base': Decimal('0.00100000'), }, }], ) @@ -649,7 +672,7 @@ def test_standardness_v0(self): 'allowed': True, 'vsize': tx3.get_vsize(), 'fees': { - 'base': Decimal('0.00011000'), + 'base': Decimal('0.01100000'), }, }], ) @@ -684,7 +707,7 @@ def test_p2sh_witness(self): # Fund the P2SH output tx = CTransaction() tx.vin.append(CTxIn(COutPoint(self.utxo[0].sha256, self.utxo[0].n), b"")) - tx.vout.append(CTxOut(self.utxo[0].nValue - 1000, script_pubkey)) + tx.vout.append(CTxOut(self.utxo[0].nValue - 100000, script_pubkey)) tx.rehash() # Verify mempool acceptance and block validity @@ -697,7 +720,7 @@ def test_p2sh_witness(self): # Now test attempts to spend the output. spend_tx = CTransaction() spend_tx.vin.append(CTxIn(COutPoint(tx.sha256, 0), script_sig)) - spend_tx.vout.append(CTxOut(tx.vout[0].nValue - 1000, CScript([OP_TRUE]))) + spend_tx.vout.append(CTxOut(tx.vout[0].nValue - 100000, CScript([OP_TRUE]))) spend_tx.rehash() # This transaction should not be accepted into the mempool pre- or @@ -773,7 +796,7 @@ def test_witness_commitments(self): # Let's construct a witness script witness_script = CScript([OP_TRUE]) script_pubkey = script_to_p2wsh_script(witness_script) - tx.vout.append(CTxOut(self.utxo[0].nValue - 1000, script_pubkey)) + tx.vout.append(CTxOut(self.utxo[0].nValue - 100000, script_pubkey)) tx.rehash() # tx2 will spend tx1, and send back to a regular anyone-can-spend address @@ -835,7 +858,7 @@ def test_block_malleability(self): add_witness_commitment(block) block.solve() - block.vtx[0].wit.vtxinwit[0].scriptWitness.stack.append(b'a' * 5000000) + block.vtx[0].wit.vtxinwit[0].scriptWitness.stack.append(b'a' * 10000000) assert block.get_weight() > MAX_BLOCK_WEIGHT # We can't send over the p2p network, because this is too big to relay @@ -880,7 +903,7 @@ def test_witness_block_size(self): # This should give us plenty of room to tweak the spending tx's # virtual size. NUM_DROPS = 200 # 201 max ops per script! - NUM_OUTPUTS = 50 + NUM_OUTPUTS = 100 // FACTOR_REDUCED_BLOCK_TIME witness_script = CScript([OP_2DROP] * NUM_DROPS + [OP_TRUE]) script_pubkey = script_to_p2wsh_script(witness_script) @@ -916,23 +939,28 @@ def test_witness_block_size(self): additional_bytes -= extra_bytes i += 1 + update_vtixinwit_index = int(i/(2*NUM_DROPS)) + update_stack_index = i%(2*NUM_DROPS) + update_base_length = len(block.vtx[-1].wit.vtxinwit[update_vtixinwit_index].scriptWitness.stack[update_stack_index]) + block.vtx[-1].wit.vtxinwit[update_vtixinwit_index].scriptWitness.stack[update_stack_index] += b'a'*4 block.vtx[0].vout.pop() # Remove old commitment add_witness_commitment(block) block.solve() - assert_equal(block.get_weight(), MAX_BLOCK_WEIGHT + 1) + assert_equal(block.get_weight(), MAX_BLOCK_WEIGHT + 5) # Make sure that our test case would exceed the old max-network-message # limit - assert len(block.serialize()) > 2 * 1024 * 1024 + assert len(block.serialize()) > (2 * 1024 * 1024) // FACTOR_REDUCED_BLOCK_TIME test_witness_block(self.nodes[0], self.test_node, block, accepted=False, reason='bad-blk-weight') # Now resize the second transaction to make the block fit. - cur_length = len(block.vtx[-1].wit.vtxinwit[0].scriptWitness.stack[0]) - block.vtx[-1].wit.vtxinwit[0].scriptWitness.stack[0] = b'a' * (cur_length - 1) - block.vtx[0].vout.pop() + #cur_length = len(block.vtx[-1].wit.vtxinwit[0].scriptWitness.stack[0]) + #block.vtx[-1].wit.vtxinwit[0].scriptWitness.stack[0] = b'a' * (cur_length - 1) + #block.vtx[0].vout.pop() + block.vtx[-1].wit.vtxinwit[update_vtixinwit_index].scriptWitness.stack[update_stack_index] = b'a'*4 if ENABLE_REDUCED_BLOCK_TIME else b'a'*8 add_witness_commitment(block) block.solve() - assert block.get_weight() == MAX_BLOCK_WEIGHT + assert block.get_weight() == MAX_BLOCK_WEIGHT - 2 test_witness_block(self.nodes[0], self.test_node, block, accepted=True) @@ -1055,22 +1083,24 @@ def test_extra_witness_data(self): def test_max_witness_push_length(self): """Test that witness stack can only allow up to 520 byte pushes.""" + MAX_SCRIPT_ELEMENT_SIZE = 128000 + block = self.build_next_block() - witness_script = CScript([OP_DROP, OP_TRUE]) - script_pubkey = script_to_p2wsh_script(witness_script) + witness_program = CScript([OP_DROP, OP_TRUE]) + script_pubkey = script_to_p2wsh_script(witness_program) tx = CTransaction() tx.vin.append(CTxIn(COutPoint(self.utxo[0].sha256, self.utxo[0].n), b"")) - tx.vout.append(CTxOut(self.utxo[0].nValue - 1000, script_pubkey)) + tx.vout.append(CTxOut(self.utxo[0].nValue - 100000, script_pubkey)) tx.rehash() tx2 = CTransaction() tx2.vin.append(CTxIn(COutPoint(tx.sha256, 0), b"")) - tx2.vout.append(CTxOut(tx.vout[0].nValue - 1000, CScript([OP_TRUE]))) + tx2.vout.append(CTxOut(tx.vout[0].nValue - 100000, CScript([OP_TRUE]))) tx2.wit.vtxinwit.append(CTxInWitness()) # First try a 521-byte stack element - tx2.wit.vtxinwit[0].scriptWitness.stack = [b'a' * (MAX_SCRIPT_ELEMENT_SIZE + 1), witness_script] + tx2.wit.vtxinwit[0].scriptWitness.stack = [b'a' * (MAX_SCRIPT_ELEMENT_SIZE + 1), witness_program] tx2.rehash() self.update_witness_block_with_transactions(block, [tx, tx2]) @@ -1092,25 +1122,26 @@ def test_max_witness_push_length(self): def test_max_witness_script_length(self): """Test that witness outputs greater than 10kB can't be spent.""" - MAX_WITNESS_SCRIPT_LENGTH = 10000 + MAX_SCRIPT_ELEMENT_SIZE = 128000 + MAX_PROGRAM_LENGTH = 129000 - # This script is 19 max pushes (9937 bytes), then 64 more opcode-bytes. - long_witness_script = CScript([b'a' * MAX_SCRIPT_ELEMENT_SIZE] * 19 + [OP_DROP] * 63 + [OP_TRUE]) - assert len(long_witness_script) == MAX_WITNESS_SCRIPT_LENGTH + 1 - long_script_pubkey = script_to_p2wsh_script(long_witness_script) + # This program is 19 max pushes (9937 bytes), then 64 more opcode-bytes. + long_witness_program = CScript([b'a' * (MAX_SCRIPT_ELEMENT_SIZE-50)] + [b'a'*996] + [OP_DROP]*46 + [OP_TRUE]) + assert len(long_witness_program) == MAX_PROGRAM_LENGTH + 1 + long_script_pubkey = script_to_p2wsh_script(long_witness_program) block = self.build_next_block() tx = CTransaction() tx.vin.append(CTxIn(COutPoint(self.utxo[0].sha256, self.utxo[0].n), b"")) - tx.vout.append(CTxOut(self.utxo[0].nValue - 1000, long_script_pubkey)) + tx.vout.append(CTxOut(self.utxo[0].nValue - 100000, long_script_pubkey)) tx.rehash() tx2 = CTransaction() tx2.vin.append(CTxIn(COutPoint(tx.sha256, 0), b"")) - tx2.vout.append(CTxOut(tx.vout[0].nValue - 1000, CScript([OP_TRUE]))) + tx2.vout.append(CTxOut(tx.vout[0].nValue - 100000, CScript([OP_TRUE]))) tx2.wit.vtxinwit.append(CTxInWitness()) - tx2.wit.vtxinwit[0].scriptWitness.stack = [b'a'] * 44 + [long_witness_script] + tx2.wit.vtxinwit[0].scriptWitness.stack = [b'a'] * 44 + [long_witness_program] tx2.rehash() self.update_witness_block_with_transactions(block, [tx, tx2]) @@ -1118,15 +1149,15 @@ def test_max_witness_script_length(self): test_witness_block(self.nodes[0], self.test_node, block, accepted=False, reason='mandatory-script-verify-flag-failed (Script is too big)') - # Try again with one less byte in the witness script - witness_script = CScript([b'a' * MAX_SCRIPT_ELEMENT_SIZE] * 19 + [OP_DROP] * 62 + [OP_TRUE]) - assert len(witness_script) == MAX_WITNESS_SCRIPT_LENGTH - script_pubkey = script_to_p2wsh_script(witness_script) + # Try again with one less byte in the witness program + witness_program = CScript([b'a' * (MAX_SCRIPT_ELEMENT_SIZE-50)] + [b'a'*996] + [OP_DROP]*45 + [OP_TRUE]) + assert len(witness_program) == MAX_PROGRAM_LENGTH + script_pubkey = script_to_p2wsh_script(witness_program) tx.vout[0] = CTxOut(tx.vout[0].nValue, script_pubkey) tx.rehash() tx2.vin[0].prevout.hash = tx.sha256 - tx2.wit.vtxinwit[0].scriptWitness.stack = [b'a'] * 43 + [witness_script] + tx2.wit.vtxinwit[0].scriptWitness.stack = [b'a'] * 43 + [witness_program] tx2.rehash() block.vtx = [block.vtx[0]] self.update_witness_block_with_transactions(block, [tx, tx2]) @@ -1233,7 +1264,7 @@ def test_tx_relay_after_segwit_activation(self): # when spending a non-witness output. tx = CTransaction() tx.vin.append(CTxIn(COutPoint(self.utxo[0].sha256, self.utxo[0].n), b"")) - tx.vout.append(CTxOut(self.utxo[0].nValue - 1000, CScript([OP_TRUE, OP_DROP] * 15 + [OP_TRUE]))) + tx.vout.append(CTxOut(self.utxo[0].nValue - 100000, CScript([OP_TRUE, OP_DROP] * 15 + [OP_TRUE]))) tx.wit.vtxinwit.append(CTxInWitness()) tx.wit.vtxinwit[0].scriptWitness.stack = [b'a'] tx.rehash() @@ -1249,11 +1280,11 @@ def test_tx_relay_after_segwit_activation(self): test_transaction_acceptance(self.nodes[0], self.test_node, tx, with_witness=False, accepted=True) # Now try to add extra witness data to a valid witness tx. - witness_script = CScript([OP_TRUE]) - script_pubkey = script_to_p2wsh_script(witness_script) + witness_program = CScript([OP_TRUE]) + script_pubkey = script_to_p2wsh_script(witness_program) tx2 = CTransaction() tx2.vin.append(CTxIn(COutPoint(tx_hash, 0), b"")) - tx2.vout.append(CTxOut(tx.vout[0].nValue - 1000, script_pubkey)) + tx2.vout.append(CTxOut(tx.vout[0].nValue - 100000, script_pubkey)) tx2.rehash() tx3 = CTransaction() @@ -1261,10 +1292,10 @@ def test_tx_relay_after_segwit_activation(self): tx3.wit.vtxinwit.append(CTxInWitness()) # Add too-large for IsStandard witness and check that it does not enter reject filter - p2sh_script = CScript([OP_TRUE]) - witness_script2 = CScript([b'a' * 400000]) - tx3.vout.append(CTxOut(tx2.vout[0].nValue - 1000, script_to_p2sh_script(p2sh_script))) - tx3.wit.vtxinwit[0].scriptWitness.stack = [witness_script2] + p2sh_program = CScript([OP_TRUE]) + witness_program2 = CScript([b'a' * 400000]) + tx3.vout.append(CTxOut(tx2.vout[0].nValue - 1000, script_to_p2sh_script(p2sh_program))) + tx3.wit.vtxinwit[0].scriptWitness.stack = [witness_program2] tx3.rehash() # Node will not be blinded to the transaction, requesting it any number of times @@ -1277,15 +1308,15 @@ def test_tx_relay_after_segwit_activation(self): self.std_wtx_node.announce_tx_and_wait_for_getdata(tx3, use_wtxid=True, success=False) # Remove witness stuffing, instead add extra witness push on stack - tx3.vout[0] = CTxOut(tx2.vout[0].nValue - 1000, CScript([OP_TRUE, OP_DROP] * 15 + [OP_TRUE])) - tx3.wit.vtxinwit[0].scriptWitness.stack = [CScript([CScriptNum(1)]), witness_script] + tx3.vout[0] = CTxOut(tx2.vout[0].nValue - 100000, CScript([OP_TRUE, OP_DROP] * 15 + [OP_TRUE])) + tx3.wit.vtxinwit[0].scriptWitness.stack = [CScript([CScriptNum(1)]), witness_program] tx3.rehash() test_transaction_acceptance(self.nodes[0], self.test_node, tx2, with_witness=True, accepted=True) test_transaction_acceptance(self.nodes[0], self.test_node, tx3, with_witness=True, accepted=False) # Get rid of the extra witness, and verify acceptance. - tx3.wit.vtxinwit[0].scriptWitness.stack = [witness_script] + tx3.wit.vtxinwit[0].scriptWitness.stack = [witness_program] # Also check that old_node gets a tx announcement, even though this is # a witness transaction. self.old_node.wait_for_inv([CInv(MSG_TX, tx2.sha256)]) # wait until tx2 was inv'ed @@ -1301,7 +1332,7 @@ def test_tx_relay_after_segwit_activation(self): assert_equal(raw_tx["vsize"], vsize) assert_equal(raw_tx["weight"], tx3.get_weight()) assert_equal(len(raw_tx["vin"][0]["txinwitness"]), 1) - assert_equal(raw_tx["vin"][0]["txinwitness"][0], witness_script.hex()) + assert_equal(raw_tx["vin"][0]["txinwitness"][0], witness_program.hex()) assert vsize != raw_tx["size"] # Cleanup: mine the transactions and update utxo for next test @@ -1323,7 +1354,7 @@ def test_segwit_versions(self): if len(self.utxo) < NUM_SEGWIT_VERSIONS: tx = CTransaction() tx.vin.append(CTxIn(COutPoint(self.utxo[0].sha256, self.utxo[0].n), b"")) - split_value = (self.utxo[0].nValue - 4000) // NUM_SEGWIT_VERSIONS + split_value = (self.utxo[0].nValue - 400000) // NUM_SEGWIT_VERSIONS for _ in range(NUM_SEGWIT_VERSIONS): tx.vout.append(CTxOut(split_value, CScript([OP_TRUE]))) tx.rehash() @@ -1348,7 +1379,7 @@ def test_segwit_versions(self): else: script_pubkey = CScript([CScriptOp(version), witness_hash]) tx.vin = [CTxIn(COutPoint(self.utxo[0].sha256, self.utxo[0].n), b"")] - tx.vout = [CTxOut(self.utxo[0].nValue - 1000, script_pubkey)] + tx.vout = [CTxOut(self.utxo[0].nValue - 100000, script_pubkey)] tx.rehash() test_transaction_acceptance(self.nodes[1], self.std_node, tx, with_witness=True, accepted=False) test_transaction_acceptance(self.nodes[0], self.test_node, tx, with_witness=True, accepted=True) @@ -1363,7 +1394,7 @@ def test_segwit_versions(self): script_pubkey = CScript([CScriptOp(OP_2), witness_hash]) tx2 = CTransaction() tx2.vin = [CTxIn(COutPoint(tx.sha256, 0), b"")] - tx2.vout = [CTxOut(tx.vout[0].nValue - 1000, script_pubkey)] + tx2.vout = [CTxOut(tx.vout[0].nValue - 100000, script_pubkey)] tx2.wit.vtxinwit.append(CTxInWitness()) tx2.wit.vtxinwit[0].scriptWitness.stack = [witness_script] tx2.rehash() @@ -1381,7 +1412,7 @@ def test_segwit_versions(self): tx3.wit.vtxinwit.append(CTxInWitness()) total_value += i.nValue tx3.wit.vtxinwit[-1].scriptWitness.stack = [witness_script] - tx3.vout.append(CTxOut(total_value - 1000, script_pubkey)) + tx3.vout.append(CTxOut(total_value - 1000000, script_pubkey)) tx3.rehash() # First we test this transaction against std_node @@ -1425,7 +1456,7 @@ def test_premature_coinbase_witness_spend(self): spend_tx.rehash() # Now test a premature spend. - self.generate(self.nodes[0], 98) + self.generate(self.nodes[0], COINBASE_MATURITY - 2) block2 = self.build_next_block() self.update_witness_block_with_transactions(block2, [spend_tx]) test_witness_block(self.nodes[0], self.test_node, block2, accepted=False, reason='bad-txns-premature-spend-of-coinbase') @@ -1457,7 +1488,7 @@ def test_uncompressed_pubkey(self): script_pkh = key_to_p2wpkh_script(pubkey) tx = CTransaction() tx.vin.append(CTxIn(COutPoint(utxo.sha256, utxo.n), b"")) - tx.vout.append(CTxOut(utxo.nValue - 1000, script_pkh)) + tx.vout.append(CTxOut(utxo.nValue - 100000, script_pkh)) tx.rehash() # Confirm it in a block. @@ -1472,7 +1503,7 @@ def test_uncompressed_pubkey(self): tx2 = CTransaction() tx2.vin.append(CTxIn(COutPoint(tx.sha256, 0), b"")) - tx2.vout.append(CTxOut(tx.vout[0].nValue - 1000, script_wsh)) + tx2.vout.append(CTxOut(tx.vout[0].nValue - 100000, script_wsh)) script = keyhash_to_p2pkh_script(pubkeyhash) tx2.wit.vtxinwit.append(CTxInWitness()) tx2.wit.vtxinwit[0].scriptWitness.stack = [pubkey] @@ -1493,7 +1524,7 @@ def test_uncompressed_pubkey(self): tx3 = CTransaction() tx3.vin.append(CTxIn(COutPoint(tx2.sha256, 0), b"")) - tx3.vout.append(CTxOut(tx2.vout[0].nValue - 1000, script_p2sh)) + tx3.vout.append(CTxOut(tx2.vout[0].nValue - 100000, script_p2sh)) tx3.wit.vtxinwit.append(CTxInWitness()) sign_p2pk_witness_input(witness_script, tx3, 0, SIGHASH_ALL, tx2.vout[0].nValue, key) @@ -1510,7 +1541,7 @@ def test_uncompressed_pubkey(self): script_pubkey = keyhash_to_p2pkh_script(pubkeyhash) tx4 = CTransaction() tx4.vin.append(CTxIn(COutPoint(tx3.sha256, 0), script_sig)) - tx4.vout.append(CTxOut(tx3.vout[0].nValue - 1000, script_pubkey)) + tx4.vout.append(CTxOut(tx3.vout[0].nValue - 100000, script_pubkey)) tx4.wit.vtxinwit.append(CTxInWitness()) sign_p2pk_witness_input(witness_script, tx4, 0, SIGHASH_ALL, tx3.vout[0].nValue, key) @@ -1524,7 +1555,7 @@ def test_uncompressed_pubkey(self): # transactions. tx5 = CTransaction() tx5.vin.append(CTxIn(COutPoint(tx4.sha256, 0), b"")) - tx5.vout.append(CTxOut(tx4.vout[0].nValue - 1000, CScript([OP_TRUE]))) + tx5.vout.append(CTxOut(tx4.vout[0].nValue - 100000, CScript([OP_TRUE]))) tx5.vin[0].scriptSig = CScript([pubkey]) sign_input_legacy(tx5, 0, script_pubkey, key) # Should pass policy and consensus. @@ -1543,7 +1574,7 @@ def test_signature_version_1(self): # First create a witness output for use in the tests. tx = CTransaction() tx.vin.append(CTxIn(COutPoint(self.utxo[0].sha256, self.utxo[0].n), b"")) - tx.vout.append(CTxOut(self.utxo[0].nValue - 1000, script_pubkey)) + tx.vout.append(CTxOut(self.utxo[0].nValue - 100000, script_pubkey)) tx.rehash() test_transaction_acceptance(self.nodes[0], self.test_node, tx, with_witness=True, accepted=True) @@ -1562,7 +1593,7 @@ def test_signature_version_1(self): block = self.build_next_block() tx = CTransaction() tx.vin.append(CTxIn(COutPoint(prev_utxo.sha256, prev_utxo.n), b"")) - tx.vout.append(CTxOut(prev_utxo.nValue - 1000, script_pubkey)) + tx.vout.append(CTxOut(prev_utxo.nValue - 100000, script_pubkey)) tx.wit.vtxinwit.append(CTxInWitness()) # Too-large input value sign_p2pk_witness_input(witness_script, tx, 0, hashtype, prev_utxo.nValue + 1, key) @@ -1732,7 +1763,7 @@ def test_non_standard_witness_blinding(self): # to a transaction, eg by violating standardness checks. tx = CTransaction() tx.vin.append(CTxIn(COutPoint(self.utxo[0].sha256, self.utxo[0].n), b"")) - tx.vout.append(CTxOut(self.utxo[0].nValue - 1000, script_pubkey)) + tx.vout.append(CTxOut(self.utxo[0].nValue - 100000, script_pubkey)) tx.rehash() test_transaction_acceptance(self.nodes[0], self.test_node, tx, False, True) self.generate(self.nodes[0], 1) @@ -1744,7 +1775,7 @@ def test_non_standard_witness_blinding(self): # to the rejection cache. tx2 = CTransaction() tx2.vin.append(CTxIn(COutPoint(tx.sha256, 0), CScript([p2sh_program]))) - tx2.vout.append(CTxOut(tx.vout[0].nValue - 1000, script_pubkey)) + tx2.vout.append(CTxOut(tx.vout[0].nValue - 100000, script_pubkey)) tx2.wit.vtxinwit.append(CTxInWitness()) tx2.wit.vtxinwit[0].scriptWitness.stack = [b'a' * 400] tx2.rehash() @@ -1758,7 +1789,7 @@ def test_non_standard_witness_blinding(self): # Now create a new anyone-can-spend utxo for the next test. tx3 = CTransaction() tx3.vin.append(CTxIn(COutPoint(tx2.sha256, 0), CScript([p2sh_program]))) - tx3.vout.append(CTxOut(tx2.vout[0].nValue - 1000, CScript([OP_TRUE, OP_DROP] * 15 + [OP_TRUE]))) + tx3.vout.append(CTxOut(tx2.vout[0].nValue - 100000, CScript([OP_TRUE, OP_DROP] * 15 + [OP_TRUE]))) tx3.rehash() test_transaction_acceptance(self.nodes[0], self.test_node, tx2, False, True) test_transaction_acceptance(self.nodes[0], self.test_node, tx3, False, True) @@ -1787,7 +1818,7 @@ def test_non_standard_witness(self): tx.vin.append(CTxIn(COutPoint(self.utxo[0].sha256, self.utxo[0].n), b"")) # For each script, generate a pair of P2WSH and P2SH-P2WSH output. - outputvalue = (self.utxo[0].nValue - 1000) // (len(scripts) * 2) + outputvalue = (self.utxo[0].nValue - 1000000) // (len(scripts) * 2) for i in scripts: p2wsh = script_to_p2wsh_script(i) p2wsh_scripts.append(p2wsh) @@ -1805,13 +1836,13 @@ def test_non_standard_witness(self): for i in range(len(scripts)): p2wsh_tx = CTransaction() p2wsh_tx.vin.append(CTxIn(COutPoint(txid, i * 2))) - p2wsh_tx.vout.append(CTxOut(outputvalue - 5000, CScript([OP_0, hash160(b"")]))) + p2wsh_tx.vout.append(CTxOut(outputvalue - 5000000, CScript([OP_0, hash160(b"")]))) p2wsh_tx.wit.vtxinwit.append(CTxInWitness()) p2wsh_tx.rehash() p2wsh_txs.append(p2wsh_tx) p2sh_tx = CTransaction() p2sh_tx.vin.append(CTxIn(COutPoint(txid, i * 2 + 1), CScript([p2wsh_scripts[i]]))) - p2sh_tx.vout.append(CTxOut(outputvalue - 5000, CScript([OP_0, hash160(b"")]))) + p2sh_tx.vout.append(CTxOut(outputvalue - 5000000, CScript([OP_0, hash160(b"")]))) p2sh_tx.wit.vtxinwit.append(CTxInWitness()) p2sh_tx.rehash() p2sh_txs.append(p2sh_tx) @@ -1996,6 +2027,7 @@ class msg_bogus_tx(msg_tx): def serialize(self): return serialize_with_bogus_witness(self.tx) + self.wallet.generate(1) tx = self.wallet.create_self_transfer()['tx'] assert_raises_rpc_error(-22, "TX decode failed", self.nodes[0].decoderawtransaction, hexstring=serialize_with_bogus_witness(tx).hex(), iswitness=True) with self.nodes[0].assert_debug_log(['Unknown transaction optional data']): @@ -2023,13 +2055,13 @@ def received_wtxidrelay(): tx = CTransaction() tx.vin.append(CTxIn(COutPoint(self.utxo[0].sha256, self.utxo[0].n), b"")) - tx.vout.append(CTxOut(self.utxo[0].nValue - 1000, script_pubkey)) + tx.vout.append(CTxOut(self.utxo[0].nValue - 1000000, script_pubkey)) tx.rehash() # Create a Segwit transaction tx2 = CTransaction() tx2.vin.append(CTxIn(COutPoint(tx.sha256, 0), b"")) - tx2.vout.append(CTxOut(tx.vout[0].nValue - 1000, script_pubkey)) + tx2.vout.append(CTxOut(tx.vout[0].nValue - 1000000, script_pubkey)) tx2.wit.vtxinwit.append(CTxInWitness()) tx2.wit.vtxinwit[0].scriptWitness.stack = [witness_script] tx2.rehash() diff --git a/test/functional/rpc_blockchain.py b/test/functional/rpc_blockchain.py index 53163720bb..7aaff0ec07 100755 --- a/test/functional/rpc_blockchain.py +++ b/test/functional/rpc_blockchain.py @@ -53,8 +53,8 @@ from test_framework.wallet import MiniWallet -HEIGHT = 200 # blocks mined -TIME_RANGE_STEP = 600 # ten-minute steps +HEIGHT = 2100 # blocks mined +TIME_RANGE_STEP = 32 # ten-minute steps TIME_RANGE_MTP = TIME_GENESIS_BLOCK + (HEIGHT - 6) * TIME_RANGE_STEP TIME_RANGE_TIP = TIME_GENESIS_BLOCK + (HEIGHT - 1) * TIME_RANGE_STEP TIME_RANGE_END = TIME_GENESIS_BLOCK + HEIGHT * TIME_RANGE_STEP @@ -70,11 +70,11 @@ def run_test(self): self.wallet = MiniWallet(self.nodes[0]) self._test_prune_disk_space() self.mine_chain() - self._test_max_future_block_time() + # self._test_max_future_block_time() self.restart_node( 0, extra_args=[ - "-stopatheight=207", + "-stopatheight=2107", "-checkblocks=-1", # Check all blocks "-prune=1", # Set pruning after rescan is complete ], @@ -95,10 +95,10 @@ def run_test(self): def mine_chain(self): self.log.info(f"Generate {HEIGHT} blocks after the genesis block in ten-minute steps") - for t in range(TIME_GENESIS_BLOCK, TIME_RANGE_END, TIME_RANGE_STEP): + for t in range(TIME_GENESIS_BLOCK, TIME_GENESIS_BLOCK + 32 * 2100, 32): self.nodes[0].setmocktime(t) self.generate(self.wallet, 1) - assert_equal(self.nodes[0].getblockchaininfo()['blocks'], HEIGHT) + assert_equal(self.nodes[0].getblockchaininfo()['blocks'], 2100) def _test_prune_disk_space(self): self.log.info("Test that a manually pruned node does not run into " @@ -132,6 +132,7 @@ def _test_getblockchaininfo(self): 'headers', 'initialblockdownload', 'mediantime', + 'moneysupply', 'pruned', 'size_on_disk', 'time', @@ -156,7 +157,7 @@ def _test_getblockchaininfo(self): assert res['pruned'] assert not res['automatic_pruning'] - self.restart_node(0, ['-stopatheight=207']) + self.restart_node(0, ['-stopatheight=2107']) res = self.nodes[0].getblockchaininfo() # should have exact keys assert_equal(sorted(res.keys()), keys) @@ -175,7 +176,7 @@ def _test_getblockchaininfo(self): expected_msg='Error: Invalid format () for -testactivationheight=name@height.', ) self.start_node(0, extra_args=[ - '-stopatheight=207', + '-stopatheight=2107', '-prune=550', ]) @@ -191,27 +192,27 @@ def _test_getblockchaininfo(self): assert_greater_than(res['size_on_disk'], 0) def check_signalling_deploymentinfo_result(self, gdi_result, height, blockhash, status_next): - assert height >= 144 and height <= 287 + assert height >= 2044 and height <= 2187 assert_equal(gdi_result, { "hash": blockhash, "height": height, "deployments": { - 'bip34': {'type': 'buried', 'active': True, 'height': 2}, - 'bip66': {'type': 'buried', 'active': True, 'height': 3}, - 'bip65': {'type': 'buried', 'active': True, 'height': 4}, - 'csv': {'type': 'buried', 'active': True, 'height': 5}, - 'segwit': {'type': 'buried', 'active': True, 'height': 6}, + 'bip34': {'type': 'buried', 'active': True, 'height': 0}, + 'bip66': {'type': 'buried', 'active': True, 'height': 0}, + 'bip65': {'type': 'buried', 'active': True, 'height': 0}, + 'csv': {'type': 'buried', 'active': True, 'height': 432}, + 'segwit': {'type': 'buried', 'active': True, 'height': 0}, 'testdummy': { 'type': 'bip9', 'bip9': { 'bit': 28, 'start_time': 0, - 'timeout': 0x7fffffffffffffff, # testdummy does not have a timeout so is set to the max int64 value + 'timeout': 9223372036854775807, 'min_activation_height': 0, 'status': 'started', 'status_next': status_next, - 'since': 144, + 'since': 432, 'statistics': { 'period': 144, 'threshold': 108, @@ -246,18 +247,18 @@ def _test_getdeploymentinfo(self): self.log.info("Test getdeploymentinfo") self.stop_node(0) self.start_node(0, extra_args=[ - '-testactivationheight=bip34@2', - '-testactivationheight=dersig@3', - '-testactivationheight=cltv@4', - '-testactivationheight=csv@5', - '-testactivationheight=segwit@6', + '-testactivationheight=bip34@0', + '-testactivationheight=dersig@0', + '-testactivationheight=cltv@0', + '-testactivationheight=csv@432', + '-testactivationheight=segwit@0', ]) gbci207 = self.nodes[0].getblockchaininfo() self.check_signalling_deploymentinfo_result(self.nodes[0].getdeploymentinfo(), gbci207["blocks"], gbci207["bestblockhash"], "started") # block just prior to lock in - self.generate(self.wallet, 287 - gbci207["blocks"]) + self.generate(self.wallet, 2187 - gbci207["blocks"]) gbci287 = self.nodes[0].getblockchaininfo() self.check_signalling_deploymentinfo_result(self.nodes[0].getdeploymentinfo(), gbci287["blocks"], gbci287["bestblockhash"], "locked_in") @@ -288,33 +289,33 @@ def _test_getchaintxstats(self): assert_raises_rpc_error(-8, "blockhash must be of length 64 (not 1, for '0')", self.nodes[0].getchaintxstats, blockhash='0') assert_raises_rpc_error(-8, "blockhash must be hexadecimal string (not 'ZZZ0000000000000000000000000000000000000000000000000000000000000')", self.nodes[0].getchaintxstats, blockhash='ZZZ0000000000000000000000000000000000000000000000000000000000000') assert_raises_rpc_error(-5, "Block not found", self.nodes[0].getchaintxstats, blockhash='0000000000000000000000000000000000000000000000000000000000000000') - blockhash = self.nodes[0].getblockhash(HEIGHT) + blockhash = self.nodes[0].getblockhash(2100) self.nodes[0].invalidateblock(blockhash) assert_raises_rpc_error(-8, "Block is not in main chain", self.nodes[0].getchaintxstats, blockhash=blockhash) self.nodes[0].reconsiderblock(blockhash) chaintxstats = self.nodes[0].getchaintxstats(nblocks=1) # 200 txs plus genesis tx - assert_equal(chaintxstats['txcount'], HEIGHT + 1) + assert_equal(chaintxstats['txcount'], 2101) # tx rate should be 1 per 10 minutes, or 1/600 # we have to round because of binary math - assert_equal(round(chaintxstats['txrate'] * TIME_RANGE_STEP, 10), Decimal(1)) + assert_equal(round(chaintxstats['txrate'] * 16 * 2, 10), Decimal(1)) b1_hash = self.nodes[0].getblockhash(1) b1 = self.nodes[0].getblock(b1_hash) - b200_hash = self.nodes[0].getblockhash(HEIGHT) + b200_hash = self.nodes[0].getblockhash(2100) b200 = self.nodes[0].getblock(b200_hash) time_diff = b200['mediantime'] - b1['mediantime'] chaintxstats = self.nodes[0].getchaintxstats() assert_equal(chaintxstats['time'], b200['time']) - assert_equal(chaintxstats['txcount'], HEIGHT + 1) + assert_equal(chaintxstats['txcount'], 2101) assert_equal(chaintxstats['window_final_block_hash'], b200_hash) - assert_equal(chaintxstats['window_final_block_height'], HEIGHT ) - assert_equal(chaintxstats['window_block_count'], HEIGHT - 1) - assert_equal(chaintxstats['window_tx_count'], HEIGHT - 1) + assert_equal(chaintxstats['window_final_block_height'], 2100) + assert_equal(chaintxstats['window_block_count'], 2099) + assert_equal(chaintxstats['window_tx_count'], 2099) assert_equal(chaintxstats['window_interval'], time_diff) - assert_equal(round(chaintxstats['txrate'] * time_diff, 10), Decimal(HEIGHT - 1)) + assert_equal(round(chaintxstats['txrate'] * time_diff, 10), Decimal(2099)) chaintxstats = self.nodes[0].getchaintxstats(blockhash=b1_hash) assert_equal(chaintxstats['time'], b1['time']) @@ -330,29 +331,29 @@ def _test_gettxoutsetinfo(self): node = self.nodes[0] res = node.gettxoutsetinfo() - assert_equal(res['total_amount'], Decimal('8725.00000000')) - assert_equal(res['transactions'], HEIGHT) - assert_equal(res['height'], HEIGHT) - assert_equal(res['txouts'], HEIGHT) - assert_equal(res['bogosize'], 16800), - assert_equal(res['bestblock'], node.getblockhash(HEIGHT)) + assert_equal(res['total_amount'], Decimal('42000000.00000000')) + assert_equal(res['transactions'], 2100) + assert_equal(res['height'], 2100) + assert_equal(res['txouts'], 2100) + assert_equal(res['bogosize'], 176400), + assert_equal(res['bestblock'], node.getblockhash(2100)) size = res['disk_size'] assert size > 6400 - assert size < 64000 + assert size < 192000 assert_equal(len(res['bestblock']), 64) assert_equal(len(res['hash_serialized_3']), 64) self.log.info("Test gettxoutsetinfo works for blockchain with just the genesis block") - b1hash = node.getblockhash(1) + b1hash = node.getblockhash(2001) node.invalidateblock(b1hash) res2 = node.gettxoutsetinfo() - assert_equal(res2['transactions'], 0) - assert_equal(res2['total_amount'], Decimal('0')) - assert_equal(res2['height'], 0) - assert_equal(res2['txouts'], 0) - assert_equal(res2['bogosize'], 0), - assert_equal(res2['bestblock'], node.getblockhash(0)) + assert_equal(res2['transactions'], 2000) + assert_equal(res2['total_amount'], Decimal('40000000')) + assert_equal(res2['height'], 2000) + assert_equal(res2['txouts'], 2000) + assert_equal(res2['bogosize'], 168000), + assert_equal(res2['bestblock'], node.getblockhash(2000)) assert_equal(len(res2['hash_serialized_3']), 64) self.log.info("Test gettxoutsetinfo returns the same result after invalidate/reconsider block") @@ -396,11 +397,11 @@ def _test_getblockheader(self): assert_raises_rpc_error(-5, "Block not found", node.getblockheader, "0cf7bb8b1697ea987f3b223ba7819250cae33efacb068d23dc24859824a77844") besthash = node.getbestblockhash() - secondbesthash = node.getblockhash(HEIGHT - 1) + secondbesthash = node.getblockhash(2099) header = node.getblockheader(blockhash=besthash) assert_equal(header['hash'], besthash) - assert_equal(header['height'], HEIGHT) + assert_equal(header['height'], 2100) assert_equal(header['confirmations'], 1) assert_equal(header['previousblockhash'], secondbesthash) assert_is_hex_string(header['chainwork']) @@ -432,7 +433,7 @@ def _test_getdifficulty(self): difficulty = self.nodes[0].getdifficulty() # 1 hash in 2 should be valid, so difficulty should be 1/2**31 # binary => decimal => binary math is why we do this check - assert abs(difficulty * 2**31 - 1) < 0.0001 + assert abs(difficulty['proof-of-work'] * 2**31 - 1) < 0.0001 def _test_getnetworkhashps(self): self.log.info("Test getnetworkhashps") @@ -449,13 +450,13 @@ def _test_getnetworkhashps(self): lambda: self.nodes[0].getnetworkhashps("a", []), ) # This should be 2 hashes every 10 minutes or 1/300 - assert abs(hashes_per_second * 300 - 1) < 0.0001 + assert abs(hashes_per_second * 300 - 1) < 20 def _test_stopatheight(self): self.log.info("Test stopping at height") - assert_equal(self.nodes[0].getblockcount(), HEIGHT) + assert_equal(self.nodes[0].getblockcount(), 2100) self.generate(self.wallet, 6) - assert_equal(self.nodes[0].getblockcount(), HEIGHT + 6) + assert_equal(self.nodes[0].getblockcount(), 2106) self.log.debug('Node should not stop at this height') assert_raises(subprocess.TimeoutExpired, lambda: self.nodes[0].process.wait(timeout=3)) try: @@ -465,7 +466,7 @@ def _test_stopatheight(self): self.log.debug('Node should stop at this height...') self.nodes[0].wait_until_stopped() self.start_node(0) - assert_equal(self.nodes[0].getblockcount(), HEIGHT + 7) + assert_equal(self.nodes[0].getblockcount(), 2107) def _test_waitforblockheight(self): self.log.info("Test waitforblockheight") @@ -481,7 +482,7 @@ def _test_waitforblockheight(self): # (Previously this was broken based on setting # `rpc/blockchain.cpp:latestblock` incorrectly.) # - fork_height = current_height - 100 # choose something vaguely near our tip + fork_height = current_height - 2000 # choose something vaguely near our tip fork_hash = node.getblockhash(fork_height) fork_block = node.getblock(fork_hash) @@ -508,7 +509,7 @@ def assert_waitforheight(height, timeout=2): def _test_getblock(self): node = self.nodes[0] - fee_per_byte = Decimal('0.00000010') + fee_per_byte = Decimal('0.00001') fee_per_kb = 1000 * fee_per_byte self.wallet.send_self_transfer(fee_rate=fee_per_kb, from_node=node) @@ -516,7 +517,7 @@ def _test_getblock(self): def assert_hexblock_hashes(verbosity): block = node.getblock(blockhash, verbosity) - assert_equal(blockhash, hash256(bytes.fromhex(block[:160]))[::-1].hex()) + assert_equal(blockhash, hash256(bytes.fromhex(block[:362]))[::-1].hex()) def assert_fee_not_in_block(verbosity): block = node.getblock(blockhash, verbosity) diff --git a/test/functional/wallet_basic.py b/test/functional/wallet_basic.py index 01149a0977..139bfb4555 100755 --- a/test/functional/wallet_basic.py +++ b/test/functional/wallet_basic.py @@ -22,6 +22,8 @@ ) from test_framework.wallet_util import test_address from test_framework.wallet import MiniWallet +from test_framework.qtumconfig import * +from test_framework.qtum import convert_btc_address_to_qtum, generatesynchronized, convert_btc_bech32_address_to_qtum NOT_A_NUMBER_OR_STRING = "Amount is not a number or string" OUT_OF_RANGE = "Amount out of range" @@ -72,14 +74,14 @@ def run_test(self): self.generate(self.nodes[0], 1, sync_fun=self.no_op) walletinfo = self.nodes[0].getwalletinfo() - assert_equal(walletinfo['immature_balance'], 50) + assert_equal(walletinfo['immature_balance'], INITIAL_BLOCK_REWARD) assert_equal(walletinfo['balance'], 0) self.sync_all(self.nodes[0:3]) - self.generate(self.nodes[1], COINBASE_MATURITY + 1, sync_fun=lambda: self.sync_all(self.nodes[0:3])) + generatesynchronized(self.nodes[1], COINBASE_MATURITY + 1, None, self.nodes[0:3]) - assert_equal(self.nodes[0].getbalance(), 50) - assert_equal(self.nodes[1].getbalance(), 50) + assert_equal(self.nodes[0].getbalance(), INITIAL_BLOCK_REWARD) + assert_equal(self.nodes[1].getbalance(), INITIAL_BLOCK_REWARD) assert_equal(self.nodes[2].getbalance(), 0) # Check that only first and second nodes have UTXOs @@ -93,9 +95,9 @@ def run_test(self): # First, outputs that are unspent both in the chain and in the # mempool should appear with or without include_mempool txout = self.nodes[0].gettxout(txid=confirmed_txid, n=confirmed_index, include_mempool=False) - assert_equal(txout['value'], 50) + assert_equal(txout['value'], INITIAL_BLOCK_REWARD) txout = self.nodes[0].gettxout(txid=confirmed_txid, n=confirmed_index, include_mempool=True) - assert_equal(txout['value'], 50) + assert_equal(txout['value'], INITIAL_BLOCK_REWARD) # Send 21 BTC from 0 to 2 using sendtoaddress call. self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), 11) @@ -105,7 +107,7 @@ def run_test(self): # utxo spent in mempool should be visible if you exclude mempool # but invisible if you include mempool txout = self.nodes[0].gettxout(confirmed_txid, confirmed_index, False) - assert_equal(txout['value'], 50) + assert_equal(txout['value'], INITIAL_BLOCK_REWARD) txout = self.nodes[0].gettxout(confirmed_txid, confirmed_index) # by default include_mempool=True assert txout is None txout = self.nodes[0].gettxout(confirmed_txid, confirmed_index, True) @@ -203,11 +205,11 @@ def run_test(self): assert_equal(len(self.nodes[1].listlockunspent()), 0) # Have node1 generate 100 blocks (so node0 can recover the fee) - self.generate(self.nodes[1], COINBASE_MATURITY, sync_fun=lambda: self.sync_all(self.nodes[0:3])) + generatesynchronized(self.nodes[1], COINBASE_MATURITY, None, self.nodes[0:3]) # node0 should end up with 100 btc in block rewards plus fees, but # minus the 21 plus fees sent to node2 - assert_equal(self.nodes[0].getbalance(), 100 - 21) + assert_equal(self.nodes[0].getbalance(), 2 * INITIAL_BLOCK_REWARD - 21) assert_equal(self.nodes[2].getbalance(), 21) # Node0 should have two unspent outputs. @@ -234,7 +236,7 @@ def run_test(self): self.generate(self.nodes[1], 1, sync_fun=lambda: self.sync_all(self.nodes[0:3])) assert_equal(self.nodes[0].getbalance(), 0) - assert_equal(self.nodes[2].getbalance(), 94) + assert_equal(self.nodes[2].getbalance(), 2 * INITIAL_BLOCK_REWARD - 6) # Verify that a spent output cannot be locked anymore spent_0 = {"txid": node0utxos[0]["txid"], "vout": node0utxos[0]["vout"]} @@ -242,11 +244,11 @@ def run_test(self): # Send 10 BTC normal address = self.nodes[0].getnewaddress("test") - fee_per_byte = Decimal('0.001') / 1000 + fee_per_byte = Decimal('0.004') / 1000 self.nodes[2].settxfee(fee_per_byte * 1000) txid = self.nodes[2].sendtoaddress(address, 10, "", "", False) self.generate(self.nodes[2], 1, sync_fun=lambda: self.sync_all(self.nodes[0:3])) - node_2_bal = self.check_fee_amount(self.nodes[2].getbalance(), Decimal('84'), fee_per_byte, self.get_vsize(self.nodes[2].gettransaction(txid)['hex'])) + node_2_bal = self.check_fee_amount(self.nodes[2].getbalance(), 2 * INITIAL_BLOCK_REWARD - 16, fee_per_byte, self.get_vsize(self.nodes[2].gettransaction(txid)['hex'])) assert_equal(self.nodes[0].getbalance(), Decimal('10')) # Send 10 BTC with subtract fee from amount @@ -287,7 +289,7 @@ def run_test(self): assert_equal(self.nodes[0].getreceivedbyaddress(a1), expected_bal) self.log.info("Test sendmany with fee_rate param (explicit fee rate in sat/vB)") - fee_rate_sat_vb = 2 + fee_rate_sat_vb = 400 fee_rate_btc_kvb = fee_rate_sat_vb * 1e3 / 1e8 explicit_fee_rate_btc_kvb = Decimal(fee_rate_btc_kvb) / 1000 @@ -301,7 +303,7 @@ def run_test(self): assert_equal(self.nodes[0].getbalance(), node_0_bal) # Test passing fee_rate as an integer - amount = Decimal("0.0001") + amount = Decimal("0.01") txid = self.nodes[2].sendmany(amounts={address: amount}, fee_rate=fee_rate_sat_vb) self.generate(self.nodes[2], 1, sync_fun=lambda: self.sync_all(self.nodes[0:3])) balance = self.nodes[2].getbalance() @@ -314,12 +316,12 @@ def run_test(self): # Test setting explicit fee rate just below the minimum. self.log.info("Test sendmany raises 'fee rate too low' if fee_rate of 0.99999999 is passed") - assert_raises_rpc_error(-6, "Fee rate (0.999 sat/vB) is lower than the minimum fee rate setting (1.000 sat/vB)", + assert_raises_rpc_error(-6, "Fee rate (0.999 sat/vB) is lower than the minimum fee rate setting (400.000 sat/vB)", self.nodes[2].sendmany, amounts={address: 10}, fee_rate=0.999) self.log.info("Test sendmany raises if an invalid fee_rate is passed") # Test fee_rate with zero values. - msg = "Fee rate (0.000 sat/vB) is lower than the minimum fee rate setting (1.000 sat/vB)" + msg = "Fee rate (0.000 sat/vB) is lower than the minimum fee rate setting (400.000 sat/vB)" for zero_value in [0, 0.000, 0.00000000, "0", "0.000", "0.00000000"]: assert_raises_rpc_error(-6, msg, self.nodes[2].sendmany, amounts={address: 1}, fee_rate=zero_value) msg = "Invalid amount" @@ -354,7 +356,7 @@ def run_test(self): # 4. check if recipient (node0) can list the zero value tx usp = self.nodes[1].listunspent(query_options={'minimumAmount': '49.998'})[0] inputs = [{"txid": usp['txid'], "vout": usp['vout']}] - outputs = {self.nodes[1].getnewaddress(): 49.998, self.nodes[0].getnewaddress(): 11.11} + outputs = {self.nodes[1].getnewaddress(): INITIAL_BLOCK_REWARD - 0.002, self.nodes[0].getnewaddress(): 11.11} raw_tx = self.nodes[1].createrawtransaction(inputs, outputs).replace("c0833842", "00000000") # replace 11.11 with 0.0 (int32) signed_raw_tx = self.nodes[1].signrawtransactionwithwallet(raw_tx) @@ -419,14 +421,14 @@ def run_test(self): tx_obj = self.nodes[0].gettransaction(txid) assert_equal(tx_obj['amount'], Decimal('-2')) - txid = self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), "0.0001") + txid = self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), "0.01") tx_obj = self.nodes[0].gettransaction(txid) - assert_equal(tx_obj['amount'], Decimal('-0.0001')) + assert_equal(tx_obj['amount'], Decimal('-0.01')) # check if JSON parser can handle scientific notation in strings - txid = self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), "1e-4") + txid = self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), "1e-1") tx_obj = self.nodes[0].gettransaction(txid) - assert_equal(tx_obj['amount'], Decimal('-0.0001')) + assert_equal(tx_obj['amount'], Decimal('-0.1')) # General checks for errors from incorrect inputs # This will raise an exception because the amount is negative @@ -451,13 +453,13 @@ def run_test(self): assert_raises_rpc_error(-3, "Address does not refer to a key", self.nodes[0].dumpprivkey, temp_address) # This will raise an exception for attempting to get the private key of an invalid Bitcoin address - assert_raises_rpc_error(-5, "Invalid Bitcoin address", self.nodes[0].dumpprivkey, "invalid") + assert_raises_rpc_error(-5, "Invalid Qtum address", self.nodes[0].dumpprivkey, "invalid") # This will raise an exception for attempting to set a label for an invalid Bitcoin address - assert_raises_rpc_error(-5, "Invalid Bitcoin address", self.nodes[0].setlabel, "invalid address", "label") + assert_raises_rpc_error(-5, "Invalid Qtum address", self.nodes[0].setlabel, "invalid address", "label") # This will raise an exception for importing an invalid address - assert_raises_rpc_error(-5, "Invalid Bitcoin address or script", self.nodes[0].importaddress, "invalid") + assert_raises_rpc_error(-5, "Invalid Qtum address or script", self.nodes[0].importaddress, "invalid") # This will raise an exception for attempting to import a pubkey that isn't in hex assert_raises_rpc_error(-5, "Pubkey must be a hex string", self.nodes[0].importpubkey, "not hex") @@ -466,7 +468,7 @@ def run_test(self): assert_raises_rpc_error(-5, "Pubkey is not a valid public key", self.nodes[0].importpubkey, "5361746f736869204e616b616d6f746f") # Bech32m addresses cannot be imported into a legacy wallet - assert_raises_rpc_error(-5, "Bech32m addresses cannot be imported into legacy wallets", self.nodes[0].importaddress, "bcrt1p0xlxvlhemja6c4dqv22uapctqupfhlxm9h8z3k2e72q4k9hcz7vqc8gma6") + assert_raises_rpc_error(-5, "Bech32m addresses cannot be imported into legacy wallets", self.nodes[0].importaddress, convert_btc_bech32_address_to_qtum("bcrt1p0xlxvlhemja6c4dqv22uapctqupfhlxm9h8z3k2e72q4k9hcz7vqc8gma6")) # Import address and private key to check correct behavior of spendable unspents # 1. Send some coins to generate new UTXO @@ -482,7 +484,7 @@ def run_test(self): assert prebalance > 2 address = self.nodes[1].getnewaddress() amount = 3 - fee_rate_sat_vb = 2 + fee_rate_sat_vb = 400 fee_rate_btc_kvb = fee_rate_sat_vb * 1e3 / 1e8 # Test passing fee_rate as an integer txid = self.nodes[2].sendtoaddress(address=address, amount=amount, fee_rate=fee_rate_sat_vb) @@ -494,7 +496,7 @@ def run_test(self): prebalance = self.nodes[2].getbalance() amount = Decimal("0.001") - fee_rate_sat_vb = 1.23 + fee_rate_sat_vb = 423 fee_rate_btc_kvb = fee_rate_sat_vb * 1e3 / 1e8 # Test passing fee_rate as a string txid = self.nodes[2].sendtoaddress(address=address, amount=amount, fee_rate=str(fee_rate_sat_vb)) @@ -506,12 +508,12 @@ def run_test(self): # Test setting explicit fee rate just below the minimum. self.log.info("Test sendtoaddress raises 'fee rate too low' if fee_rate of 0.99999999 is passed") - assert_raises_rpc_error(-6, "Fee rate (0.999 sat/vB) is lower than the minimum fee rate setting (1.000 sat/vB)", + assert_raises_rpc_error(-6, "Fee rate (0.999 sat/vB) is lower than the minimum fee rate setting (400.000 sat/vB)", self.nodes[2].sendtoaddress, address=address, amount=1, fee_rate=0.999) self.log.info("Test sendtoaddress raises if an invalid fee_rate is passed") # Test fee_rate with zero values. - msg = "Fee rate (0.000 sat/vB) is lower than the minimum fee rate setting (1.000 sat/vB)" + msg = "Fee rate (0.000 sat/vB) is lower than the minimum fee rate setting (400.000 sat/vB)" for zero_value in [0, 0.000, 0.00000000, "0", "0.000", "0.00000000"]: assert_raises_rpc_error(-6, msg, self.nodes[2].sendtoaddress, address=address, amount=1, fee_rate=zero_value) msg = "Invalid amount" @@ -615,13 +617,13 @@ def run_test(self): sending_addr = self.nodes[1].getnewaddress() txid_list = [] for _ in range(chainlimit * 2): - txid_list.append(self.nodes[0].sendtoaddress(sending_addr, Decimal('0.0001'))) + txid_list.append(self.nodes[0].sendtoaddress(sending_addr, Decimal('0.1'))) assert_equal(self.nodes[0].getmempoolinfo()['size'], chainlimit * 2) assert_equal(len(txid_list), chainlimit * 2) # Without walletrejectlongchains, we will still generate a txid # The tx will be stored in the wallet but not accepted to the mempool - extra_txid = self.nodes[0].sendtoaddress(sending_addr, Decimal('0.0001')) + extra_txid = self.nodes[0].sendtoaddress(sending_addr, Decimal('0.1')) assert extra_txid not in self.nodes[0].getrawmempool() assert extra_txid in [tx["txid"] for tx in self.nodes[0].listtransactions()] self.nodes[0].abandontransaction(extra_txid) @@ -648,8 +650,8 @@ def run_test(self): # Test getaddressinfo on external address. Note that these addresses are taken from disablewallet.py assert_raises_rpc_error(-5, "Invalid or unsupported Base58-encoded address.", self.nodes[0].getaddressinfo, "3J98t1WpEZ73CNmQviecrnyiWrnqRhWNLy") - address_info = self.nodes[0].getaddressinfo("mneYUmWYsuk7kySiURxCi3AGxrAqZxLgPZ") - assert_equal(address_info['address'], "mneYUmWYsuk7kySiURxCi3AGxrAqZxLgPZ") + address_info = self.nodes[0].getaddressinfo(convert_btc_address_to_qtum("mneYUmWYsuk7kySiURxCi3AGxrAqZxLgPZ")) + assert_equal(address_info['address'], convert_btc_address_to_qtum("mneYUmWYsuk7kySiURxCi3AGxrAqZxLgPZ")) assert_equal(address_info["scriptPubKey"], "76a9144e3854046c7bd1594ac904e4793b6a45b36dea0988ac") assert not address_info["ismine"] assert not address_info["iswatchonly"] @@ -704,9 +706,9 @@ def run_test(self): self.log.info("Test send* RPCs with verbose=True") address = self.nodes[0].getnewaddress("test") txid_feeReason_one = self.nodes[2].sendtoaddress(address=address, amount=5, verbose=True) - assert_equal(txid_feeReason_one["fee_reason"], "Fallback fee") + assert_equal(txid_feeReason_one["fee_reason"], "Minimum Required Fee") txid_feeReason_two = self.nodes[2].sendmany(dummy='', amounts={address: 5}, verbose=True) - assert_equal(txid_feeReason_two["fee_reason"], "Fallback fee") + assert_equal(txid_feeReason_two["fee_reason"], "Minimum Required Fee") self.log.info("Test send* RPCs with verbose=False") txid_feeReason_three = self.nodes[2].sendtoaddress(address=address, amount=5, verbose=False) assert_equal(self.nodes[2].gettransaction(txid_feeReason_three)['txid'], txid_feeReason_three) diff --git a/test/functional/wallet_bumpfee.py b/test/functional/wallet_bumpfee.py index fea933a93b..349dd21b2a 100755 --- a/test/functional/wallet_bumpfee.py +++ b/test/functional/wallet_bumpfee.py @@ -31,6 +31,7 @@ find_vout_for_address, ) from test_framework.wallet import MiniWallet +from test_framework.qtumconfig import COINBASE_MATURITY WALLET_PASSPHRASE = "test" @@ -38,10 +39,10 @@ # Fee rates (sat/vB) INSUFFICIENT = 1 -ECONOMICAL = 50 -NORMAL = 100 -HIGH = 500 -TOO_HIGH = 100000 +ECONOMICAL = 10000 +NORMAL = 15000 +HIGH = 50000 +TOO_HIGH = 10000000 def get_change_address(tx, node): tx_details = node.getrawtransaction(tx, 1) @@ -57,7 +58,7 @@ def set_test_params(self): self.setup_clean_chain = True self.extra_args = [[ "-walletrbf={}".format(i), - "-mintxfee=0.00002", + "-mintxfee=0.005", "-addresstype=bech32", "-whitelist=noban@127.0.0.1", ] for i in range(self.num_nodes)] @@ -79,12 +80,12 @@ def run_test(self): # fund rbf node with 10 coins of 0.001 btc (100,000 satoshis) self.log.info("Mining blocks...") - self.generate(peer_node, 110) + self.generate(peer_node, COINBASE_MATURITY + 10) for _ in range(25): - peer_node.sendtoaddress(rbf_node_address, 0.001) - self.sync_all() + peer_node.sendtoaddress(rbf_node_address, 0.1) self.generate(peer_node, 1) - assert_equal(rbf_node.getbalance(), Decimal("0.025")) + self.sync_all() + assert_equal(rbf_node.getbalance(), Decimal("2.5")) self.log.info("Running tests") dest_address = peer_node.getnewaddress() @@ -130,7 +131,7 @@ def test_invalid_parameters(self, rbf_node, peer_node, dest_address): assert_raises_rpc_error(-8, "Insufficient total fee 0.00000141", rbf_node.bumpfee, rbfid, fee_rate=INSUFFICIENT) self.log.info("Test invalid fee rate settings") - assert_raises_rpc_error(-4, "Specified or calculated fee 0.141 is too high (cannot be higher than -maxtxfee 0.10", + assert_raises_rpc_error(-4, "Specified or calculated fee 14.10 is too high (cannot be higher than -maxtxfee 1.00", rbf_node.bumpfee, rbfid, fee_rate=TOO_HIGH) # Test fee_rate with zero values. msg = "Insufficient total fee 0.00" @@ -351,14 +352,14 @@ def test_segwit_bumpfee_succeeds(self, rbf_node, dest_address): # which spends it, and make sure bumpfee can be called on it. segwit_out = rbf_node.getnewaddress(address_type='bech32') - segwitid = rbf_node.send({segwit_out: "0.0009"}, options={"change_position": 1})["txid"] + segwitid = rbf_node.send({segwit_out: "0.09"}, options={"change_position": 1})["txid"] rbfraw = rbf_node.createrawtransaction([{ 'txid': segwitid, 'vout': 0, "sequence": MAX_BIP125_RBF_SEQUENCE - }], {dest_address: Decimal("0.0005"), - rbf_node.getrawchangeaddress(): Decimal("0.0003")}) + }], {dest_address: Decimal("0.05"), + rbf_node.getrawchangeaddress(): Decimal("0.03")}) rbfsigned = rbf_node.signrawtransactionwithwallet(rbfraw) rbfid = rbf_node.sendrawtransaction(rbfsigned["hex"]) assert rbfid in rbf_node.getrawmempool() @@ -381,7 +382,7 @@ def test_notmine_bumpfee(self, rbf_node, peer_node, dest_address): # here, the rbftx has a peer_node coin and then adds a rbf_node input # Note that this test depends upon the RPC code checking input ownership prior to change outputs # (since it can't use fundrawtransaction, it lacks a proper change output) - fee = Decimal("0.001") + fee = Decimal("0.01") utxos = [node.listunspent(minimumAmount=fee)[-1] for node in (rbf_node, peer_node)] inputs = [{ "txid": utxo["txid"], @@ -411,7 +412,7 @@ def finish_psbtbumpfee(psbt): psbt = rbf_node.psbtbumpfee(txid=rbfid) finish_psbtbumpfee(psbt["psbt"]) - psbt = rbf_node.psbtbumpfee(txid=rbfid, fee_rate=old_feerate + 10) + psbt = rbf_node.psbtbumpfee(txid=rbfid, fee_rate=old_feerate + 1000) finish_psbtbumpfee(psbt["psbt"]) self.clear_mempool() @@ -421,7 +422,7 @@ def test_bumpfee_with_descendant_fails(self, rbf_node, rbf_node_address, dest_ad self.log.info('Test that fee cannot be bumped when it has descendant') # parent is send-to-self, so we don't have to check which output is change when creating the child tx parent_id = spend_one_input(rbf_node, rbf_node_address) - tx = rbf_node.createrawtransaction([{"txid": parent_id, "vout": 0}], {dest_address: 0.00020000}) + tx = rbf_node.createrawtransaction([{"txid": parent_id, "vout": 0}], {dest_address: 0.02000000}) tx = rbf_node.signrawtransactionwithwallet(tx) rbf_node.sendrawtransaction(tx["hex"]) assert_raises_rpc_error(-8, "Transaction has descendants in the wallet", rbf_node.bumpfee, parent_id) @@ -441,12 +442,12 @@ def test_bumpfee_with_abandoned_descendant_succeeds(self, rbf_node, rbf_node_add # parent is send-to-self, so we don't have to check which output is change when creating the child tx parent_id = spend_one_input(rbf_node, rbf_node_address) # Submit child transaction with low fee - child_id = rbf_node.send(outputs={dest_address: 0.00020000}, - options={"inputs": [{"txid": parent_id, "vout": 0}], "fee_rate": 2})["txid"] + child_id = rbf_node.send(outputs={dest_address: 0.020000}, + options={"inputs": [{"txid": parent_id, "vout": 0}], "fee_rate": 500})["txid"] assert child_id in rbf_node.getrawmempool() # Restart the node with higher min relay fee so the descendant tx is no longer in mempool so that we can abandon it - self.restart_node(1, ['-minrelaytxfee=0.00005'] + self.extra_args[1]) + self.restart_node(1, ['-minrelaytxfee=0.006'] + self.extra_args[1]) rbf_node.walletpassphrase(WALLET_PASSPHRASE, WALLET_PASSPHRASE_TIMEOUT) self.connect_nodes(1, 0) assert parent_id in rbf_node.getrawmempool() @@ -476,22 +477,24 @@ def test_small_output_with_feerate_succeeds(self, rbf_node, dest_address): original_txin = input_list[0] self.log.info('Keep bumping until transaction fee out-spends non-destination value') tx_fee = 0 + i = 0 while True: input_list = rbf_node.getrawtransaction(rbfid, 1)["vin"] new_item = list(input_list)[0] assert_equal(len(input_list), 1) assert_equal(original_txin["txid"], new_item["txid"]) assert_equal(original_txin["vout"], new_item["vout"]) - rbfid_new_details = rbf_node.bumpfee(rbfid) + rbfid_new_details = rbf_node.bumpfee(rbfid, {"fee_rate": round(30000+i*20000,8)}) rbfid_new = rbfid_new_details["txid"] raw_pool = rbf_node.getrawmempool() assert rbfid not in raw_pool assert rbfid_new in raw_pool rbfid = rbfid_new tx_fee = rbfid_new_details["fee"] + i = i+1 # Total value from input not going to destination - if tx_fee > Decimal('0.00050000'): + if tx_fee > Decimal('0.05000000'): break # input(s) have been added @@ -517,37 +520,37 @@ def test_dust_to_fee(self, rbf_node, dest_address): # boundary. Thus expected transaction size (p2wpkh, 1 input, 2 outputs) is 140-141 vbytes, usually 141. if not 140 <= fulltx["vsize"] <= 141: raise AssertionError("Invalid tx vsize of {} (140-141 expected), full tx: {}".format(fulltx["vsize"], fulltx)) - # Bump with fee_rate of 350.25 sat/vB vbytes to create dust. + # Bump with fee_rate of 35300 sat/vB vbytes to create dust. # Expected fee is 141 vbytes * fee_rate 0.00350250 BTC / 1000 vbytes = 0.00049385 BTC. # or occasionally 140 vbytes * fee_rate 0.00350250 BTC / 1000 vbytes = 0.00049035 BTC. # Dust should be dropped to the fee, so actual bump fee is 0.00050000 BTC. - bumped_tx = rbf_node.bumpfee(rbfid, fee_rate=350.25) + bumped_tx = rbf_node.bumpfee(rbfid, fee_rate=35300) full_bumped_tx = rbf_node.getrawtransaction(bumped_tx["txid"], 1) - assert_equal(bumped_tx["fee"], Decimal("0.00050000")) + assert_equal(bumped_tx["fee"], Decimal("0.05000000")) assert_equal(len(fulltx["vout"]), 2) assert_equal(len(full_bumped_tx["vout"]), 1) # change output is eliminated - assert_equal(full_bumped_tx["vout"][0]['value'], Decimal("0.00050000")) + assert_equal(full_bumped_tx["vout"][0]['value'], Decimal("0.05000000")) self.clear_mempool() def test_settxfee(self, rbf_node, dest_address): self.log.info('Test settxfee') assert_raises_rpc_error(-8, "txfee cannot be less than min relay tx fee", rbf_node.settxfee, Decimal('0.000005')) - assert_raises_rpc_error(-8, "txfee cannot be less than wallet min fee", rbf_node.settxfee, Decimal('0.000015')) + assert_raises_rpc_error(-8, "txfee cannot be less than wallet min fee", rbf_node.settxfee, Decimal('0.0049')) # check that bumpfee reacts correctly to the use of settxfee (paytxfee) rbfid = spend_one_input(rbf_node, dest_address) - requested_feerate = Decimal("0.00025000") + requested_feerate = Decimal("0.02500000") rbf_node.settxfee(requested_feerate) bumped_tx = rbf_node.bumpfee(rbfid) actual_feerate = bumped_tx["fee"] * 1000 / rbf_node.getrawtransaction(bumped_tx["txid"], True)["vsize"] # Assert that the difference between the requested feerate and the actual # feerate of the bumped transaction is small. - assert_greater_than(Decimal("0.00001000"), abs(requested_feerate - actual_feerate)) + assert_greater_than(Decimal("0.00100000"), abs(requested_feerate - actual_feerate)) rbf_node.settxfee(Decimal("0.00000000")) # unset paytxfee # check that settxfee respects -maxtxfee - self.restart_node(1, ['-maxtxfee=0.000025'] + self.extra_args[1]) - assert_raises_rpc_error(-8, "txfee cannot be more than wallet max tx fee", rbf_node.settxfee, Decimal('0.00003')) + self.restart_node(1, ['-maxtxfee=0.0250000'] + self.extra_args[1]) + assert_raises_rpc_error(-8, "txfee cannot be more than wallet max tx fee", rbf_node.settxfee, Decimal('0.03')) self.restart_node(1, self.extra_args[1]) rbf_node.walletpassphrase(WALLET_PASSPHRASE, WALLET_PASSPHRASE_TIMEOUT) self.connect_nodes(1, 0) @@ -559,7 +562,7 @@ def test_maxtxfee_fails(self, rbf_node, dest_address): # size of bumped transaction (p2wpkh, 1 input, 2 outputs): 141 vbytes # expected bump fee of 141 vbytes * 0.00200000 BTC / 1000 vbytes = 0.00002820 BTC # which exceeds maxtxfee and is expected to raise - self.restart_node(1, ['-maxtxfee=0.000025'] + self.extra_args[1]) + self.restart_node(1, ['-maxtxfee=0.00003', "-minrelaytxfee=0.00003", "-mintxfee=0.000005"] + self.extra_args[1]) rbf_node.walletpassphrase(WALLET_PASSPHRASE, WALLET_PASSPHRASE_TIMEOUT) rbfid = spend_one_input(rbf_node, dest_address) assert_raises_rpc_error(-4, "Unable to create transaction. Fee exceeds maximum configured by user (e.g. -maxtxfee, maxfeerate)", rbf_node.bumpfee, rbfid) @@ -629,13 +632,13 @@ def test_watchonly_psbt(self, peer_node, rbf_node, dest_address): funding_address1 = watcher.getnewaddress(address_type='bech32') funding_address2 = watcher.getnewaddress(address_type='bech32') - peer_node.sendmany("", {funding_address1: 0.001, funding_address2: 0.001}) + peer_node.sendmany("", {funding_address1: 0.1, funding_address2: 0.1}) self.generate(peer_node, 1) # Create single-input PSBT for transaction to be bumped # Ensure the payment amount + change can be fully funded using one of the 0.001BTC inputs. - psbt = watcher.walletcreatefundedpsbt([watcher.listunspent()[0]], {dest_address: 0.0005}, 0, - {"fee_rate": 1, "add_inputs": False}, True)['psbt'] + psbt = watcher.walletcreatefundedpsbt([watcher.listunspent()[0]], {dest_address: 0.05}, 0, + {"fee_rate": 1000, "add_inputs": False}, True)['psbt'] psbt_signed = signer.walletprocesspsbt(psbt=psbt, sign=True, sighashtype="ALL", bip32derivs=True) original_txid = watcher.sendrawtransaction(psbt_signed["hex"]) assert_equal(len(watcher.decodepsbt(psbt)["tx"]["vin"]), 1) @@ -740,7 +743,7 @@ def test_unconfirmed_not_spendable(self, rbf_node, rbf_node_address): def test_bumpfee_metadata(self, rbf_node, dest_address): self.log.info('Test that bumped txn metadata persists to new txn record') assert rbf_node.getbalance() < 49 - self.generatetoaddress(rbf_node, 101, rbf_node.getnewaddress()) + self.generatetoaddress(rbf_node, COINBASE_MATURITY + 1, rbf_node.getnewaddress()) rbfid = rbf_node.sendtoaddress(dest_address, 49, "comment value", "to value") bumped_tx = rbf_node.bumpfee(rbfid) bumped_wtx = rbf_node.gettransaction(bumped_tx["txid"]) @@ -775,10 +778,10 @@ def test_change_script_match(self, rbf_node, dest_address): self.clear_mempool() -def spend_one_input(node, dest_address, change_size=Decimal("0.00049000"), data=None): +def spend_one_input(node, dest_address, change_size=Decimal("0.04900000"), data=None): tx_input = dict( - sequence=MAX_BIP125_RBF_SEQUENCE, **next(u for u in node.listunspent() if u["amount"] == Decimal("0.00100000"))) - destinations = {dest_address: Decimal("0.00050000")} + sequence=MAX_BIP125_RBF_SEQUENCE, **next(u for u in node.listunspent() if u["amount"] == Decimal("0.10000000"))) + destinations = {dest_address: Decimal("0.05000000")} if change_size > 0: destinations[node.getrawchangeaddress()] = change_size if data: @@ -790,6 +793,8 @@ def spend_one_input(node, dest_address, change_size=Decimal("0.00049000"), data= def test_no_more_inputs_fails(self, rbf_node, dest_address): + # Throw away some coins to a dummy address so that the test does not hit the max tx size error + rbf_node.sendtoaddress("qc4bREjo85FRxUMatqVTVAeaD4XKGHswgm", rbf_node.getbalance()/2) self.log.info('Test that bumpfee fails when there are no available confirmed outputs') # feerate rbf requires confirmed outputs when change output doesn't exist or is insufficient self.generatetoaddress(rbf_node, 1, dest_address)