|
| 1 | +#!/usr/bin/env python3 |
| 2 | +# Copyright (c) 2020 The PIVX developers |
| 3 | +# Distributed under the MIT software license, see the accompanying |
| 4 | +# file COPYING or https://www.opensource.org/licenses/mit-license.php . |
| 5 | + |
| 6 | +from test_framework.test_framework import PivxTestFramework |
| 7 | + |
| 8 | +from test_framework.util import ( |
| 9 | + assert_greater_than, |
| 10 | + assert_greater_than_or_equal, |
| 11 | + assert_equal, |
| 12 | + Decimal, |
| 13 | + satoshi_round, |
| 14 | + sync_blocks, |
| 15 | + sync_mempools, |
| 16 | +) |
| 17 | + |
| 18 | +import time |
| 19 | + |
| 20 | +def timed(f): |
| 21 | + start = time.time() |
| 22 | + ret = f() |
| 23 | + elapsed = time.time() - start |
| 24 | + return ret, elapsed |
| 25 | + |
| 26 | +MAX_SHIELDED_BLOCKSIZE = 750000 |
| 27 | + |
| 28 | +class SaplingFillBlockTest(PivxTestFramework): |
| 29 | + |
| 30 | + def set_test_params(self): |
| 31 | + self.num_nodes = 2 |
| 32 | + self.setup_clean_chain = True |
| 33 | + self.extra_args = [["-blockmaxsize=1999000"], []] |
| 34 | + |
| 35 | + def utxo_splitter(self, node_from, n_inputs, node_to): |
| 36 | + txids = [] |
| 37 | + # collect utxos |
| 38 | + utxos = node_from.listunspent() |
| 39 | + assert_greater_than_or_equal(len(utxos), n_inputs) |
| 40 | + # sort by size |
| 41 | + sorted(utxos, key=lambda utxo: utxo["amount"], reverse=True) |
| 42 | + # pick the first N |
| 43 | + utxos = utxos[:n_inputs] |
| 44 | + # split each one in 100 (use fixed 0.05 PIV fee) |
| 45 | + for u in utxos: |
| 46 | + prevout = [{"txid": u["txid"], "vout": u["vout"]}] |
| 47 | + output_amt = satoshi_round((u["amount"] - Decimal("0.05")) / 100) |
| 48 | + recipients = {node_to.getnewaddress(): output_amt for _ in range(100)} |
| 49 | + rawTx_unsigned = node_from.createrawtransaction(prevout, recipients) |
| 50 | + rawTx_signed = node_from.signrawtransaction(rawTx_unsigned)["hex"] |
| 51 | + txids.append(node_from.sendrawtransaction(rawTx_signed)) |
| 52 | + return txids |
| 53 | + |
| 54 | + def check_mempool(self, miner, txids): |
| 55 | + self.log.info("Checking mempool...") |
| 56 | + sync_mempools(self.nodes) |
| 57 | + mempool_info = miner.getmempoolinfo() |
| 58 | + assert_equal(mempool_info['size'], len(txids)) |
| 59 | + mempool_bytes = mempool_info['bytes'] |
| 60 | + self.log.info("Miner's mempool size: %d bytes" % mempool_bytes) |
| 61 | + assert_greater_than_or_equal(mempool_bytes, 1000000) |
| 62 | + |
| 63 | + def mine_and_checkblock(self, miner, alice): |
| 64 | + self.log.info("Mining the block...") |
| 65 | + bhash, elapsed = timed(lambda: miner.generate(1)[0]) |
| 66 | + self.log.info("Block mined in %d seconds" % elapsed) |
| 67 | + _, elapsed = timed(lambda: self.sync_all()) |
| 68 | + bsize = alice.getblock(bhash, True)["size"] |
| 69 | + self.log.info("Peers synced in %d seconds. Block size: %d" % (elapsed, bsize)) |
| 70 | + # Only shielded txes in mempool. Block size must be below |
| 71 | + # MAX_SHIELDED_BLOCKSIZE + 513 (header + coinbase + coinstake) |
| 72 | + assert_greater_than(MAX_SHIELDED_BLOCKSIZE + 513, bsize) |
| 73 | + |
| 74 | + def send_shielded(self, node, n_txes, from_address, shield_to): |
| 75 | + txids = [] |
| 76 | + for i in range(n_txes): |
| 77 | + txids.append(node.shieldedsendmany(from_address, shield_to)) |
| 78 | + if (i + 1) % 200 == 0: |
| 79 | + self.log.info("...%d Transactions created..." % (i + 1)) |
| 80 | + return txids |
| 81 | + |
| 82 | + |
| 83 | + def run_test(self): |
| 84 | + miner = self.nodes[0] |
| 85 | + alice = self.nodes[1] |
| 86 | + # First mine 300 blocks |
| 87 | + self.log.info("Generating 300 blocks...") |
| 88 | + miner.generate(300) |
| 89 | + sync_blocks(self.nodes) |
| 90 | + assert_equal(self.nodes[0].getblockchaininfo()['upgrades']['v5 shield']['status'], 'active') |
| 91 | + |
| 92 | + ## -- First check that the miner never produces blocks with more than 750kB of shielded txes |
| 93 | + |
| 94 | + # Split 10 utxos (of 250 PIV each) in 1000 new utxos of ~2.5 PIV each (to alice) |
| 95 | + UTXOS_TO_SPLIT = 10 |
| 96 | + UTXOS_TO_SHIELD = UTXOS_TO_SPLIT * 100 |
| 97 | + self.log.info("Creating %d utxos..." % UTXOS_TO_SHIELD) |
| 98 | + txids = self.utxo_splitter(miner, UTXOS_TO_SPLIT, alice) |
| 99 | + assert_equal(len(txids), UTXOS_TO_SPLIT) |
| 100 | + miner.generate(2) |
| 101 | + sync_blocks(self.nodes) |
| 102 | + new_utxos = alice.listunspent() |
| 103 | + assert_equal(len(new_utxos), UTXOS_TO_SHIELD) |
| 104 | + |
| 105 | + # Now alice shields the new utxos individually (fixed 0.2 PIV fee --> ~2.3 PIV notes) |
| 106 | + self.log.info("Shielding utxos...") |
| 107 | + alice_z_addr = alice.getnewshieldedaddress() |
| 108 | + shield_to = [{"address": alice_z_addr, "amount": new_utxos[0]["amount"] - Decimal("0.2")}] |
| 109 | + txids = self.send_shielded(alice, UTXOS_TO_SHIELD, "from_transparent", shield_to) |
| 110 | + |
| 111 | + # Check mempool |
| 112 | + self.check_mempool(miner, txids) |
| 113 | + |
| 114 | + # Mine the block |
| 115 | + self.mine_and_checkblock(miner, alice) |
| 116 | + self.log.info("Done. %d txes still in mempool." % miner.getmempoolinfo()['size']) |
| 117 | + |
| 118 | + |
| 119 | +if __name__ == '__main__': |
| 120 | + SaplingFillBlockTest().main() |
0 commit comments