Exemplo n.º 1
0
    def run_test(self):
        self.disable_mocktime()

        # Additional connections to miner and owner
        for nodePos in [self.minerPos, self.controllerPos]:
            self.connect_to_all(nodePos)
        miner = self.nodes[self.minerPos]
        controller = self.nodes[self.controllerPos]

        dummy_add = controller.getnewaddress("dummy")

        # Enforce mn payments and reject legacy mns at block 131
        self.activate_spork(0, "SPORK_8_MASTERNODE_PAYMENT_ENFORCEMENT")
        assert_equal("success", self.set_spork(self.minerPos, "SPORK_21_LEGACY_MNS_MAX_HEIGHT", 130))
        time.sleep(1)
        assert_equal([130] * self.num_nodes, [self.get_spork(x, "SPORK_21_LEGACY_MNS_MAX_HEIGHT")
                                              for x in range(self.num_nodes)])
        mns = []

        # Mine 100 blocks
        self.log.info("Mining...")
        miner.generate(110)
        self.sync_blocks()
        self.assert_equal_for_all(110, "getblockcount")

        # Test rejection before enforcement
        self.log.info("Testing rejection of ProRegTx before DIP3 activation...")
        assert_raises_rpc_error(-1, "Evo upgrade is not active yet", self.add_new_dmn, mns, "internal")
        assert_raises_rpc_error(-1, "Evo upgrade is not active yet", self.add_new_dmn, mns, "fund")
        # Can create the raw proReg
        dmn = create_new_dmn(2, controller, dummy_add, None)
        tx, sig = self.protx_register_ext(miner, controller, dmn, None, False)
        # but cannot send it
        assert_raises_rpc_error(-1, "Evo upgrade is not active yet", miner.protx_register_submit, tx, sig)
        self.log.info("Done. Now mine blocks till enforcement...")

        # Check that no coin has been locked by the controller yet
        assert_equal(len(controller.listlockunspent()), 0)

        # DIP3 activates at block 130.
        miner.generate(130 - miner.getblockcount())
        self.sync_blocks()
        self.assert_equal_for_all(130, "getblockcount")

        # -- DIP3 enforced and SPORK_21 active here --
        self.wait_until_mnsync_completed()

        # enabled/total masternodes: 0/0
        self.check_mn_enabled_count(0, 0)

        # Create 3 DMNs and init the remote nodes
        self.log.info("Initializing masternodes...")
        self.add_new_dmn(mns, "internal")
        self.add_new_dmn(mns, "external")
        self.add_new_dmn(mns, "fund")
        for mn in mns:
            self.nodes[mn.idx].initmasternode(mn.operator_sk)
            time.sleep(1)
        miner.generate(1)
        self.sync_blocks()

        # enabled/total masternodes: 3/3
        self.check_mn_enabled_count(3, 3)

        # Init the other 3 remote nodes before creating the ProReg tx
        self.log.info("Initializing more masternodes...")
        op_keys = []
        for i in range(3):
            idx = 2 + len(mns) + i
            bls_keypair = controller.generateblskeypair()
            self.nodes[idx].initmasternode(bls_keypair["secret"])
            op_keys.append([bls_keypair["public"], bls_keypair["secret"]])
            time.sleep(1)

        # Now send the ProReg txes and check list
        self.add_new_dmn(mns, "internal", op_keys[0])
        self.add_new_dmn(mns, "external", op_keys[1])
        self.add_new_dmn(mns, "fund", op_keys[2])
        miner.generate(2)
        self.sync_blocks()
        time.sleep(1)
        self.log.info("Masternodes started.")

        # enabled/total masternodes: 6/6
        self.check_mn_enabled_count(6, 6)
        self.check_mn_list(mns)

        # Check status from remote nodes
        assert_equal([self.nodes[idx].getmasternodestatus()['status'] for idx in range(2, self.num_nodes)],
                     ["Ready"] * (self.num_nodes - 2))
        self.log.info("All masternodes ready.")

        # Restart the controller and check that the collaterals are still locked
        self.log.info("Restarting controller...")
        self.restart_controller()
        time.sleep(1)
        for mn in mns:
            if not is_coin_locked_by(controller, mn.collateral):
                raise Exception(
                    "Collateral %s of mn with idx=%d is not locked" % (mn.collateral, mn.idx)
                )
        self.log.info("Collaterals still locked.")

        # Test collateral spending
        dmn = mns.pop(randrange(len(mns)))  # pop one at random
        self.log.info("Spending collateral of mn with idx=%d..." % dmn.idx)
        spend_txid = spend_mn_collateral(controller, dmn)
        self.sync_mempools([miner, controller])
        miner.generate(1)
        self.sync_blocks()
        assert_greater_than(miner.getrawtransaction(spend_txid, True)["confirmations"], 0)

        # enabled/total masternodes: 5/5
        self.check_mn_enabled_count(5, 5)
        self.check_mn_list(mns)

        # Register dmn again, with the collateral of dmn2
        # dmn must be added again to the list, and dmn2 must be removed
        dmn2 = mns.pop(randrange(len(mns)))  # pop one at random
        dmn_keys = [dmn.operator_pk, dmn.operator_sk]
        dmn2_keys = [dmn2.operator_pk, dmn2.operator_sk]
        self.log.info("Reactivating node %d reusing the collateral of node %d..." % (dmn.idx, dmn2.idx))
        mns.append(self.register_new_dmn(dmn.idx, self.minerPos, self.controllerPos, "external",
                                         outpoint=dmn2.collateral, op_blskeys=dmn_keys))
        miner.generate(1)
        self.sync_blocks()

        # enabled/total masternodes: 5/5
        self.check_mn_enabled_count(5, 5)
        self.check_mn_list(mns)

        # Now try to register dmn2 again with an already-used IP
        self.log.info("Trying duplicate IP...")
        rand_idx = mns[randrange(len(mns))].idx
        assert_raises_rpc_error(-1, "bad-protx-dup-IP-address",
                                self.register_new_dmn, rand_idx, self.minerPos, self.controllerPos, "fund",
                                op_blskeys=dmn2_keys)

        # Now try with duplicate operator key
        self.log.info("Trying duplicate operator key...")
        dmn2b = create_new_dmn(dmn2.idx, controller, dummy_add, dmn_keys)
        assert_raises_rpc_error(-1, "bad-protx-dup-operator-key",
                                self.protx_register_fund, miner, controller, dmn2b, dummy_add)

        # Now try with duplicate owner key
        self.log.info("Trying duplicate owner key...")
        dmn2c = create_new_dmn(dmn2.idx, controller, dummy_add, dmn2_keys)
        dmn2c.owner = mns[randrange(len(mns))].owner
        assert_raises_rpc_error(-1, "bad-protx-dup-owner-key",
                                self.protx_register_fund, miner, controller, dmn2c, dummy_add)

        # Finally, register it properly. This time setting 10% of the reward for the operator
        op_rew = {"reward": 10.00, "address": self.nodes[dmn2.idx].getnewaddress()}
        self.log.info("Reactivating the node with a new registration (with operator reward)...")
        dmn2c = create_new_dmn(dmn2.idx, controller, dummy_add, dmn2_keys)
        self.protx_register_fund(miner, controller, dmn2c, dummy_add, op_rew)
        mns.append(dmn2c)
        time.sleep(1)
        self.sync_mempools([miner, controller])
        miner.generate(6)
        self.sync_blocks()
        json_tx = self.nodes[dmn2c.idx].getrawtransaction(dmn2c.proTx, True)
        assert_greater_than(json_tx['confirmations'], 0)
        self.check_proreg_payload(dmn2c, json_tx)

        # enabled/total masternodes: 6/6
        self.check_mn_enabled_count(6, 6)
        self.check_mn_list(mns)     # 6 masternodes again

        # Test payments.
        # Mine 12 blocks and check that each masternode has been paid exactly twice.
        # Save last paid masternode. Check that it's the last paid also after the 12 blocks.
        # Note: dmn2 sends (2 * 0.3 PIV) to the operator, and (2 * 2.7 PIV) to the owner
        self.log.info("Testing masternode payments...")
        last_paid_mn = self.get_last_paid_mn()
        starting_balances = {"operator": self.get_addr_balance(self.nodes[dmn2c.idx], op_rew["address"])}
        for mn in mns:
            starting_balances[mn.payee] = self.get_addr_balance(controller, mn.payee)
        miner.generate(12)
        self.sync_blocks()
        for mn in mns:
            bal = self.get_addr_balance(controller, mn.payee)
            expected = starting_balances[mn.payee] + (Decimal('6.0') if mn.idx != dmn2c.idx else Decimal('5.4'))
            if bal != expected:
                raise Exception("Invalid balance (%s != %s) for node %d" % (bal, expected, mn.idx))
        self.log.info("All masternodes paid twice.")
        assert_equal(self.get_addr_balance(self.nodes[dmn2c.idx], op_rew["address"]),
                     starting_balances["operator"] + Decimal('0.6'))
        self.log.info("Operator paid twice.")
        assert_equal(last_paid_mn, self.get_last_paid_mn())
        self.log.info("Order preserved.")

        # Test invalid payment
        self.wait_until_mnsync_completed()   # just to be sure
        self.log.info("Testing invalid masternode payment...")
        mn_payee_script = miner.validateaddress(miner.getnewaddress())['scriptPubKey']
        block = self.create_block(mn_payee_script, miner.getblock(miner.getbestblockhash(), True))
        block.solve()
        assert_equal(miner.submitblock(bytes_to_hex_str(block.serialize())), "bad-cb-payee")

        # Test ProUpServ txes
        self.log.info("Trying to update a non-existent masternode...")
        assert_raises_rpc_error(-8, "not found", miner.protx_update_service,
                                "%064x" % getrandbits(256), "127.0.0.1:1000")
        self.log.info("Trying to update an IP address to an already used one...")
        assert_raises_rpc_error(-1, "bad-protx-dup-addr", miner.protx_update_service,
                                mns[0].proTx, mns[1].ipport, "", mns[0].operator_sk)
        self.log.info("Trying to update the payout address when the reward is 0...")
        assert_raises_rpc_error(-8, "Operator reward is 0. Cannot set operator payout address",
                                miner.protx_update_service, mns[0].proTx, "",
                                miner.getnewaddress(), mns[0].operator_sk)
        self.log.info("Trying to update the operator payee to an invalid address...")
        assert_raises_rpc_error(-5, "invalid PIVX address InvalidPayee",
                                miner.protx_update_service, dmn2c.proTx, "", "InvalidPayee", "")
        self.log.info("Update IP address...")
        mns[0].ipport = "127.0.0.1:1000"
        # Do it from the remote node (so no need to pass the operator BLS secret key)
        remote_node = self.nodes[mns[0].idx]
        # Send first some funds
        miner.sendtoaddress(remote_node.getnewaddress(), 1.0)
        miner.generate(1)
        self.sync_blocks()
        # Then send the ProUpServ tx from the masternode
        remote_node.protx_update_service(mns[0].proTx, mns[0].ipport)
        self.sync_mempools([miner, remote_node])
        miner.generate(1)
        self.sync_blocks()
        self.check_mn_list(mns)
        self.log.info("Update operator payout address...")
        # This time send the ProUpServ tx directly from the miner, giving the operator BLS secret key
        new_address = self.nodes[dmn2c.idx].getnewaddress()
        miner.protx_update_service(dmn2c.proTx, dmn2c.ipport, new_address, dmn2c.operator_sk)
        miner.generate(len(mns) + 1)
        self.sync_blocks()
        # Check payment to new address
        self.log.info("Checking payment...")
        assert_equal(self.get_addr_balance(self.nodes[dmn2c.idx], new_address), Decimal('0.3'))

        # Test ProUpReg txes
        self.log.info("Trying to update a non-existent masternode...")
        assert_raises_rpc_error(-8, "not found", miner.protx_update_registrar,
                                "%064x" % getrandbits(256), "", "", "")
        self.log.info("Trying to update an operator address to an already used one...")
        assert_raises_rpc_error(-1, "bad-protx-dup-key", controller.protx_update_registrar,
                                mns[0].proTx, mns[1].operator_pk, "", "")
        self.log.info("Trying to update the payee to an invalid address...")
        assert_raises_rpc_error(-5, "invalid PIVX address InvalidPayee", controller.protx_update_registrar,
                                mns[0].proTx, "", "", "InvalidPayee")
        self.log.info("Update operator keys...")
        bls_keypair = self.nodes[mns[0].idx].generateblskeypair()
        mns[0].operator_pk = bls_keypair["public"]
        mns[0].operator_sk = bls_keypair["secret"]
        # Controller should already have the key (as it was generated there), no need to pass it
        controller.protx_update_registrar(mns[0].proTx, mns[0].operator_pk, "", "")
        self.sync_mempools([miner, controller])
        miner.generate(1)
        self.sync_blocks()

        # enabled/total masternodes: 5/6
        # Updating the operator key, clears the IP (and puts the mn in PoSe banned state)
        self.check_mn_enabled_count(5, 6)
        mns[0].ipport = "[::]:0"
        self.check_mn_list(mns)

        old_mn0_balance = self.get_addr_balance(controller, mns[0].payee)
        self.log.info("Update operator address (with external key)...")
        bls_keypair = self.nodes[mns[0].idx].generateblskeypair()
        mns[0].operator_pk = bls_keypair["public"]
        mns[0].operator_sk = bls_keypair["secret"]
        ownerKey = controller.dumpprivkey(mns[0].owner)
        miner.protx_update_registrar(mns[0].proTx, mns[0].operator_pk, "", "", ownerKey)
        miner.generate(1)
        self.sync_blocks()
        self.check_mn_enabled_count(5, 6) # stil not valid until new operator sends proUpServ
        self.check_mn_list(mns)
        self.log.info("Update voting address...")
        mns[1].voting = controller.getnewaddress()
        controller.protx_update_registrar(mns[1].proTx, "", mns[1].voting, "")
        self.sync_mempools([miner, controller])
        miner.generate(1)
        self.sync_blocks()
        self.check_mn_enabled_count(5, 6)
        self.check_mn_list(mns)
        self.log.info("Update payout address...")
        old_payee = mns[2].payee
        mns[2].payee = controller.getnewaddress()
        controller.protx_update_registrar(mns[2].proTx, "", "", mns[2].payee)
        self.sync_mempools([miner, controller])
        miner.generate(1)
        self.sync_blocks()
        old_mn2_bal = self.get_addr_balance(controller, old_payee)
        miner.generate(len(mns)-1)
        self.sync_blocks()
        self.check_mn_enabled_count(5, 6)
        self.check_mn_list(mns)
        # Check payment to new address
        self.log.info("Checking payments...")
        assert_equal(self.get_addr_balance(controller, old_payee), old_mn2_bal)
        assert_equal(self.get_addr_balance(controller, mns[2].payee), Decimal('3'))
        # The PoSe banned node didn't receive any more payment
        assert_equal(self.get_addr_balance(controller, mns[0].payee), old_mn0_balance)

        # Test ProUpRev txes
        self.log.info("Trying to revoke a non-existent masternode...")
        assert_raises_rpc_error(-8, "not found", miner.protx_revoke,
                                "%064x" % getrandbits(256))
        self.log.info("Trying to revoke with invalid reason...")
        assert_raises_rpc_error(-8, "invalid reason", controller.protx_revoke, mns[3].proTx, mns[3].operator_sk, 100)
        self.log.info("Revoke masternode...")
        # Do it from the remote node (so no need to pass the operator BLS secret key)
        remote_node = self.nodes[mns[3].idx]
        # Send first some funds
        miner.sendtoaddress(remote_node.getnewaddress(), 1.0)
        miner.generate(1)
        self.sync_blocks()
        # Then send the ProUpRev tx from the masternode
        remote_node.protx_revoke(mns[3].proTx, "", 1)
        mns[3].revoked()
        self.sync_mempools([miner, remote_node])
        miner.generate(1)
        self.sync_blocks()
        self.check_mn_enabled_count(4, 6)   # mn3 has been revoked
        self.check_mn_list(mns)
        old_mn3_bal = self.get_addr_balance(controller, mns[3].payee)
        # This time send the ProUpRev tx directly from the miner, giving the operator BLS secret key
        self.log.info("Revoke masternode (with external key)...")
        miner.protx_revoke(mns[4].proTx, mns[4].operator_sk, 2)
        mns[4].revoked()
        miner.generate(1)
        self.sync_blocks()
        self.check_mn_list(mns)
        old_mn4_bal = self.get_addr_balance(controller, mns[4].payee)
        miner.generate(len(mns) + 1)
        self.sync_blocks()

        # enabled/total masternodes: 3/6 (mn0 banned, mn3 and mn4 revoked)
        self.check_mn_enabled_count(3, 6)
        self.check_mn_list(mns)

        # Check (no) payments
        self.log.info("Checking payments...")
        assert_equal(self.get_addr_balance(controller, mns[3].payee), old_mn3_bal)
        assert_equal(self.get_addr_balance(controller, mns[4].payee), old_mn4_bal)

        # Test reviving a masternode
        self.log.info("Reviving a masternode...")
        bls_keypair = controller.generateblskeypair()
        mns[3].operator_pk = bls_keypair["public"]
        mns[3].operator_sk = bls_keypair["secret"]
        miner.protx_update_registrar(mns[3].proTx, mns[3].operator_pk, "", "", controller.dumpprivkey(mns[3].owner))
        miner.generate(1)
        mns[3].ipport = "127.0.0.1:3000"
        miner.protx_update_service(mns[3].proTx, mns[3].ipport, "", mns[3].operator_sk)
        miner.generate(len(mns))
        self.sync_blocks()

        # enabled/total masternodes: 4/6 (mn3 is back)
        self.check_mn_enabled_count(4, 6)
        self.check_mn_list(mns)

        self.log.info("Checking payments...")
        assert_equal(self.get_addr_balance(controller, mns[3].payee), old_mn3_bal + Decimal('3'))

        self.log.info("All good.")
Exemplo n.º 2
0
    def run_test(self):
        self.disable_mocktime()
        nodeA = self.nodes[0]
        nodeB = self.nodes[1]
        free_idx = 1  # unique id for masternodes. first available.

        # Enforce mn payments and reject legacy mns at block 202
        self.activate_spork(0, "SPORK_8_MASTERNODE_PAYMENT_ENFORCEMENT")
        assert_equal("success",
                     self.set_spork(0, "SPORK_21_LEGACY_MNS_MAX_HEIGHT", 201))
        time.sleep(1)
        assert_equal([201] * self.num_nodes, [
            self.get_spork(x, "SPORK_21_LEGACY_MNS_MAX_HEIGHT")
            for x in range(self.num_nodes)
        ])

        # Mine 201 blocks
        self.log.info("Mining...")
        nodeA.generate(25)
        self.sync_blocks()
        nodeB.generate(25)
        self.sync_blocks()
        nodeA.generate(50)
        self.sync_blocks()
        nodeB.generate(101)
        self.sync_blocks()
        self.assert_equal_for_all(201, "getblockcount")

        # Register two masternodes before the split
        collateral_addr = nodeA.getnewaddress(
        )  # for both collateral and payouts
        pre_split_mn1 = create_new_dmn(100, nodeA, nodeA.getnewaddress(), None)
        pre_split_mn2 = create_new_dmn(200, nodeA, nodeA.getnewaddress(), None)
        self.register_masternode(nodeA, pre_split_mn1, collateral_addr)
        self.register_masternode(nodeA, pre_split_mn2, collateral_addr)
        nodeA.generate(1)
        self.sync_blocks()
        mnsA = [pre_split_mn1, pre_split_mn2]
        mnsB = [pre_split_mn1, pre_split_mn2]
        self.check_mn_list_on_node(0, mnsA)
        self.check_mn_list_on_node(1, mnsB)
        self.log.info("Pre-split masternodes registered.")

        # Disconnect the nodes
        self.disconnect_all()  # network splits at block 203

        #
        # -- CHAIN A --
        #

        # Register 5 masternodes, then mine 5 blocks
        self.log.info("Registering masternodes on chain A...")
        for _ in range(5):
            dmn = create_new_dmn(free_idx, nodeA, collateral_addr, None)
            free_idx += 1
            self.register_masternode(nodeA, dmn, collateral_addr)
            mnsA.append(dmn)
        nodeA.generate(5)
        self.check_mn_list_on_node(0, mnsA)
        self.log.info("Masternodes registered on chain A.")

        # Now create a collateral (which will be used later to register a masternode)
        funding_txid = nodeA.sendtoaddress(collateral_addr, Decimal('100'))
        nodeA.generate(1)
        funding_tx_json = nodeA.getrawtransaction(funding_txid, True)
        assert_greater_than(funding_tx_json["confirmations"], 0)
        initial_collateral = COutPoint(int(funding_txid, 16),
                                       get_collateral_vout(funding_tx_json))

        # Lock any utxo with less than 106 confs (e.g. change), so we can resurrect everything
        for x in nodeA.listunspent(0, 106):
            nodeA.lockunspent(False, [{"txid": x["txid"], "vout": x["vout"]}])

        # Now send a valid proReg tx to the mempool, without mining it
        mempool_dmn1 = create_new_dmn(free_idx, nodeA, collateral_addr, None)
        free_idx += 1
        self.register_masternode(nodeA, mempool_dmn1, collateral_addr)
        assert mempool_dmn1.proTx in nodeA.getrawmempool()

        # Try sending a proReg tx with same owner
        self.log.info("Testing in-mempool duplicate-owner rejection...")
        dmn_A1 = create_new_dmn(free_idx, nodeA, collateral_addr, None)
        free_idx += 1
        dmn_A1.owner = mempool_dmn1.owner
        assert_raises_rpc_error(-26, "protx-dup", self.register_masternode,
                                nodeA, dmn_A1, collateral_addr)
        assert dmn_A1.proTx not in nodeA.getrawmempool()

        # Try sending a proReg tx with same operator
        self.log.info("Testing in-mempool duplicate-operator rejection...")
        dmn_A2 = create_new_dmn(free_idx, nodeA, collateral_addr, None)
        free_idx += 1
        dmn_A2.operator_pk = mempool_dmn1.operator_pk
        assert_raises_rpc_error(-26, "protx-dup", self.register_masternode,
                                nodeA, dmn_A2, collateral_addr)
        assert dmn_A2.proTx not in nodeA.getrawmempool()

        # Try sending a proReg tx with same IP
        self.log.info("Testing proReg in-mempool duplicate-IP rejection...")
        dmn_A3 = create_new_dmn(free_idx, nodeA, collateral_addr, None)
        free_idx += 1
        dmn_A3.ipport = mempool_dmn1.ipport
        assert_raises_rpc_error(-26, "protx-dup", self.register_masternode,
                                nodeA, dmn_A3, collateral_addr)
        assert dmn_A3.proTx not in nodeA.getrawmempool()

        # Now send other 2 valid proReg tx to the mempool, without mining them
        self.log.info("Sending more ProReg txes to the mempool...")
        mempool_dmn2 = create_new_dmn(free_idx, nodeA, collateral_addr, None)
        free_idx += 1
        mempool_dmn3 = create_new_dmn(free_idx, nodeA, collateral_addr, None)
        free_idx += 1
        self.register_masternode(nodeA, mempool_dmn2, collateral_addr)
        self.register_masternode(nodeA, mempool_dmn3, collateral_addr)

        # Send to the mempool a ProRegTx using the collateral mined after the split
        mempool_dmn4 = create_new_dmn(free_idx, nodeA, collateral_addr, None)
        mempool_dmn4.collateral = initial_collateral
        self.protx_register_ext(nodeA, nodeA, mempool_dmn4,
                                mempool_dmn4.collateral, True)

        # Now send a valid proUpServ tx to the mempool, without mining it
        proupserv1_txid = nodeA.protx_update_service(pre_split_mn1.proTx,
                                                     "127.0.0.1:1000", "",
                                                     pre_split_mn1.operator_sk)

        # Try sending another update, reusing the same ip of the previous mempool tx
        self.log.info("Testing proUpServ in-mempool duplicate-IP rejection...")
        assert_raises_rpc_error(-26, "protx-dup", nodeA.protx_update_service,
                                mnsA[0].proTx, "127.0.0.1:1000", "",
                                mnsA[0].operator_sk)

        # Now send other two valid proUpServ txes to the mempool, without mining them
        proupserv2_txid = nodeA.protx_update_service(mnsA[3].proTx,
                                                     "127.0.0.1:2000", "",
                                                     mnsA[3].operator_sk)
        proupserv3_txid = nodeA.protx_update_service(pre_split_mn1.proTx,
                                                     "127.0.0.1:1001", "",
                                                     pre_split_mn1.operator_sk)

        # Send valid proUpReg tx to the mempool
        operator_to_reuse = nodeA.generateblskeypair()["public"]
        proupreg1_txid = nodeA.protx_update_registrar(mnsA[4].proTx,
                                                      operator_to_reuse, "",
                                                      "")

        # Try sending another one, reusing the operator key used by another mempool proTx
        self.log.info(
            "Testing proUpReg in-mempool duplicate-operator-key rejection...")
        assert_raises_rpc_error(-26, "protx-dup", nodeA.protx_update_registrar,
                                mnsA[5].proTx, mempool_dmn1.operator_pk, "",
                                "")

        # Now send other two valid proUpServ txes to the mempool, without mining them
        new_voting_address = nodeA.getnewaddress()
        proupreg2_txid = nodeA.protx_update_registrar(mnsA[5].proTx, "",
                                                      new_voting_address, "")
        proupreg3_txid = nodeA.protx_update_registrar(pre_split_mn1.proTx, "",
                                                      new_voting_address, "")

        # Send two valid proUpRev txes to the mempool, without mining them
        self.log.info("Revoking two masternodes...")
        prouprev1_txid = nodeA.protx_revoke(mnsA[6].proTx, mnsA[6].operator_sk)
        prouprev2_txid = nodeA.protx_revoke(pre_split_mn2.proTx,
                                            pre_split_mn2.operator_sk)

        # Now nodeA has 4 proReg txes in its mempool, 3 proUpServ txes, 3 proUpReg txes, and 2 proUpRev
        mempoolA = nodeA.getrawmempool()
        assert mempool_dmn1.proTx in mempoolA
        assert mempool_dmn2.proTx in mempoolA
        assert mempool_dmn3.proTx in mempoolA
        assert mempool_dmn4.proTx in mempoolA
        assert proupserv1_txid in mempoolA
        assert proupserv2_txid in mempoolA
        assert proupserv3_txid in mempoolA
        assert proupreg1_txid in mempoolA
        assert proupreg2_txid in mempoolA
        assert proupreg3_txid in mempoolA
        assert prouprev1_txid in mempoolA
        assert prouprev2_txid in mempoolA

        assert_equal(nodeA.getblockcount(), 208)

        #
        # -- CHAIN B --
        #
        collateral_addr = nodeB.getnewaddress()
        self.log.info("Registering masternodes on chain B...")

        # Register first the 3 nodes that conflict with the mempool of nodes[0]
        # mine one block after each registration
        for dmn in [dmn_A1, dmn_A2, dmn_A3]:
            self.register_masternode(nodeB, dmn, collateral_addr)
            mnsB.append(dmn)
            nodeB.generate(1)
        self.check_mn_list_on_node(1, mnsB)

        # Pick the proReg for the first MN registered on chain A, and replay it on chain B
        self.log.info("Replaying a masternode on a different chain...")
        mnsA.remove(pre_split_mn1)
        mnsA.remove(pre_split_mn2)
        replay_mn = mnsA.pop(0)
        mnsB.append(replay_mn)  # same proTx hash
        nodeB.sendrawtransaction(
            nodeA.getrawtransaction(replay_mn.proTx, False))
        nodeB.generate(1)
        self.check_mn_list_on_node(1, mnsB)

        # Now pick a proReg for another MN registered on chain A, and re-register it on chain B
        self.log.info("Re-registering a masternode on a different chain...")
        rereg_mn = random.choice(mnsA)
        mnsA.remove(rereg_mn)
        self.register_masternode(nodeB, rereg_mn, collateral_addr)
        mnsB.append(rereg_mn)  # changed proTx hash
        nodeB.generate(1)
        self.check_mn_list_on_node(1, mnsB)

        # Register 5 more masternodes. One per block.
        for _ in range(5):
            dmn = create_new_dmn(free_idx, nodeB, collateral_addr, None)
            free_idx += 1
            self.register_masternode(nodeB, dmn, collateral_addr)
            mnsB.append(dmn)
            nodeB.generate(1)
        self.check_mn_list_on_node(1, mnsB)

        # Register one masternode reusing the IP of the proUpServ mempool tx on chainA
        dmn1000 = create_new_dmn(free_idx, nodeB, collateral_addr, None)
        free_idx += 1
        dmn1000.ipport = "127.0.0.1:1000"
        mnsB.append(dmn1000)
        self.register_masternode(nodeB, dmn1000, collateral_addr)

        # Register one masternode reusing the operator-key of the proUpReg mempool tx on chainA
        dmnop = create_new_dmn(free_idx, nodeB, collateral_addr, None)
        free_idx += 1
        dmnop.operator_pk = operator_to_reuse
        mnsB.append(dmnop)
        self.register_masternode(nodeB, dmnop, collateral_addr)

        # Then mine 10 more blocks on chain B
        nodeB.generate(10)
        self.check_mn_list_on_node(1, mnsB)
        self.log.info("Masternodes registered on chain B.")

        assert_equal(nodeB.getblockcount(), 222)

        #
        # -- RECONNECT --
        #

        # Reconnect and sync (give it some more time)
        self.log.info("Reconnecting nodes...")
        self.connect_all()
        self.sync_blocks(wait=3, timeout=180)

        # Both nodes have the same list (mnB)
        self.log.info("Checking masternode list...")
        self.check_mn_list_on_node(0, mnsB)
        self.check_mn_list_on_node(1, mnsB)

        self.log.info("Checking mempool...")
        mempoolA = nodeA.getrawmempool()
        # The first mempool proReg tx has been removed from nodeA's mempool due to
        # conflicts with the masternodes of chain B, now connected.
        # The fourth mempool proReg tx has been removed because the collateral it
        # was referencing has been disconnected.
        assert mempool_dmn1.proTx not in mempoolA
        assert mempool_dmn2.proTx in mempoolA
        assert mempool_dmn3.proTx in mempoolA
        assert mempool_dmn4.proTx not in mempoolA
        # The first mempool proUpServ tx has been removed as the IP (port=1000) is
        # now used by a newly connected masternode.
        # The second mempool proUpServ tx has been removed as it was meant to update
        # a masternode that is not in the deterministic list anymore.
        assert proupserv1_txid not in mempoolA
        assert proupserv2_txid not in mempoolA
        assert proupserv3_txid in mempoolA
        # The first mempool proUpReg tx has been removed as the operator key is
        # now used by a newly connected masternode.
        # The second mempool proUpReg tx has been removed as it was meant to update
        # a masternode that is not in the deterministic list anymore.
        assert proupreg1_txid not in mempoolA
        assert proupreg2_txid not in mempoolA
        assert proupreg3_txid in mempoolA
        # The frist mempool proUpRev tx has been removed as it was meant to revoke
        # a masternode that is not in the deterministic list anymore.
        assert prouprev1_txid not in mempoolA
        assert prouprev2_txid in mempoolA
        # The mempool contains also all the ProReg from the disconnected blocks,
        # except the ones re-registered and replayed on chain B.
        for mn in mnsA:
            assert mn.proTx in mempoolA
        assert rereg_mn.proTx not in mempoolA
        assert replay_mn.proTx not in mempoolA
        assert pre_split_mn1.proTx not in mempoolA
        assert pre_split_mn2.proTx not in mempoolA

        # Mine a block from nodeA so the mempool txes get included
        self.log.info("Mining mempool txes...")
        nodeA.generate(1)
        self.sync_all()
        # mempool_dmn2 and mempool_dmn3 have been included
        mnsB.append(mempool_dmn2)
        mnsB.append(mempool_dmn3)
        # proupserv3 has changed the IP of the pre_split masternode 1
        # and proupreg3 has changed its voting address
        mnsB.remove(pre_split_mn1)
        pre_split_mn1.ipport = "127.0.0.1:1001"
        pre_split_mn1.voting = new_voting_address
        mnsB.append(pre_split_mn1)
        # prouprev2 has revoked pre_split masternode 2
        mnsB.remove(pre_split_mn2)
        pre_split_mn2.revoked()
        mnsB.append(pre_split_mn2)

        # the ProReg txes, that were added back to the mempool from the
        # disconnected blocks, have been mined again
        mns_all = mnsA + mnsB
        # Check new mn list
        self.check_mn_list_on_node(0, mns_all)
        self.check_mn_list_on_node(1, mns_all)
        self.log.info("Both nodes have %d registered masternodes." %
                      len(mns_all))

        self.log.info("All good.")
Exemplo n.º 3
0
    def run_test(self):
        self.disable_mocktime()

        # Additional connections to miner and owner
        for nodePos in [self.minerPos, self.controllerPos]:
            self.connect_to_all(nodePos)
        miner = self.nodes[self.minerPos]
        controller = self.nodes[self.controllerPos]

        dummy_add = controller.getnewaddress("dummy")

        # Enforce mn payments and reject legacy mns at block 131
        self.activate_spork(0, "SPORK_8_MASTERNODE_PAYMENT_ENFORCEMENT")
        assert_equal(
            "success",
            self.set_spork(self.minerPos, "SPORK_21_LEGACY_MNS_MAX_HEIGHT",
                           130))
        time.sleep(1)
        assert_equal([130] * self.num_nodes, [
            self.get_spork(x, "SPORK_21_LEGACY_MNS_MAX_HEIGHT")
            for x in range(self.num_nodes)
        ])
        mns = []

        # Mine 100 blocks
        self.log.info("Mining...")
        miner.generate(110)
        self.sync_blocks()
        self.assert_equal_for_all(110, "getblockcount")

        # Test rejection before enforcement
        self.log.info(
            "Testing rejection of ProRegTx before DIP3 activation...")
        assert_raises_rpc_error(-1, "Evo upgrade is not active yet",
                                self.add_new_dmn, mns, "internal")
        assert_raises_rpc_error(-1, "Evo upgrade is not active yet",
                                self.add_new_dmn, mns, "fund")
        # Can create the raw proReg
        dmn = create_new_dmn(2, controller, dummy_add, None)
        tx, sig = self.protx_register_ext(miner, controller, dmn, None, False)
        # but cannot send it
        assert_raises_rpc_error(-1, "Evo upgrade is not active yet",
                                miner.protx_register_submit, tx, sig)
        self.log.info("Done. Now mine blocks till enforcement...")

        # Check that no coin has been locked by the controller yet
        assert_equal(len(controller.listlockunspent()), 0)

        # DIP3 activates at block 130.
        miner.generate(130 - miner.getblockcount())
        self.sync_blocks()
        self.assert_equal_for_all(130, "getblockcount")

        # -- DIP3 enforced and SPORK_21 active here --
        self.wait_until_mnsync_completed()

        # Create 3 DMNs and init the remote nodes
        self.log.info("Initializing masternodes...")
        self.add_new_dmn(mns, "internal")
        self.add_new_dmn(mns, "external")
        self.add_new_dmn(mns, "fund")
        for mn in mns:
            self.nodes[mn.idx].initmasternode(mn.operator_key, "", True)
            time.sleep(1)
        miner.generate(1)
        self.sync_blocks()

        # Init the other 3 remote nodes before creating the ProReg tx
        self.log.info("Initializing more masternodes...")
        op_keys = []
        for i in range(3):
            idx = 2 + len(mns) + i
            add_and_key = []
            add_and_key.append(miner.getnewaddress("oper-%d-key" % idx))
            add_and_key.append(miner.dumpprivkey(add_and_key[0]))
            self.nodes[idx].initmasternode(add_and_key[1], "", True)
            op_keys.append(add_and_key)
            time.sleep(1)

        # Now send the ProReg txes and check list
        self.add_new_dmn(mns, "internal", op_keys[0])
        self.add_new_dmn(mns, "external", op_keys[1])
        self.add_new_dmn(mns, "fund", op_keys[2])
        miner.generate(2)
        self.sync_blocks()
        time.sleep(1)
        self.log.info("Masternodes started.")
        self.check_mn_list(mns)

        # Check status from remote nodes
        assert_equal([
            self.nodes[idx].getmasternodestatus()['status']
            for idx in range(2, self.num_nodes)
        ], ["Ready"] * (self.num_nodes - 2))
        self.log.info("All masternodes ready.")

        # Restart the controller and check that the collaterals are still locked
        self.log.info("Restarting controller...")
        self.restart_controller()
        time.sleep(1)
        for mn in mns:
            if not is_coin_locked_by(controller, mn.collateral):
                raise Exception(
                    "Collateral %s of mn with idx=%d is not locked" %
                    (mn.collateral, mn.idx))
        self.log.info("Collaterals still locked.")

        # Test collateral spending
        dmn = mns.pop(randrange(len(mns)))  # pop one at random
        self.log.info("Spending collateral of mn with idx=%d..." % dmn.idx)
        spend_txid = spend_mn_collateral(controller, dmn)
        self.sync_mempools([miner, controller])
        miner.generate(1)
        self.sync_blocks()
        assert_greater_than(
            miner.getrawtransaction(spend_txid, True)["confirmations"], 0)
        self.check_mn_list(mns)

        # Register dmn again, with the collateral of dmn2
        # dmn must be added again to the list, and dmn2 must be removed
        dmn2 = mns.pop(randrange(len(mns)))  # pop one at random
        dmn_keys = [dmn.operator, dmn.operator_key]
        dmn2_keys = [dmn2.operator, dmn2.operator_key]
        self.log.info(
            "Reactivating node %d reusing the collateral of node %d..." %
            (dmn.idx, dmn2.idx))
        mns.append(
            self.register_new_dmn(dmn.idx,
                                  self.minerPos,
                                  self.controllerPos,
                                  "external",
                                  outpoint=dmn2.collateral,
                                  op_addr_and_key=dmn_keys))
        miner.generate(1)
        self.sync_blocks()
        self.check_mn_list(mns)

        # Now try to register dmn2 again with an already-used IP
        self.log.info("Trying duplicate IP...")
        rand_idx = mns[randrange(len(mns))].idx
        assert_raises_rpc_error(-1,
                                "bad-protx-dup-IP-address",
                                self.register_new_dmn,
                                rand_idx,
                                self.minerPos,
                                self.controllerPos,
                                "fund",
                                op_addr_and_key=dmn2_keys)

        # Now try with duplicate operator key
        self.log.info("Trying duplicate operator key...")
        dmn2b = create_new_dmn(dmn2.idx, controller, dummy_add, dmn_keys)
        assert_raises_rpc_error(-1, "bad-protx-dup-operator-key",
                                self.protx_register_fund, miner, controller,
                                dmn2b, dummy_add)

        # Now try with duplicate owner key
        self.log.info("Trying duplicate owner key...")
        dmn2c = create_new_dmn(dmn2.idx, controller, dummy_add, dmn2_keys)
        dmn2c.owner = mns[randrange(len(mns))].owner
        assert_raises_rpc_error(-1, "bad-protx-dup-owner-key",
                                self.protx_register_fund, miner, controller,
                                dmn2c, dummy_add)

        # Finally, register it properly. This time setting 10% of the reward for the operator
        op_rew = {
            "reward": 10.00,
            "address": self.nodes[dmn2.idx].getnewaddress()
        }
        self.log.info(
            "Reactivating the node with a new registration (with operator reward)..."
        )
        dmn2c = create_new_dmn(dmn2.idx, controller, dummy_add, dmn2_keys)
        self.protx_register_fund(miner, controller, dmn2c, dummy_add, op_rew)
        mns.append(dmn2c)
        time.sleep(1)
        self.sync_mempools([miner, controller])
        miner.generate(6)
        self.sync_blocks()
        json_tx = self.nodes[dmn2c.idx].getrawtransaction(dmn2c.proTx, True)
        assert_greater_than(json_tx['confirmations'], 0)
        self.check_proreg_payload(dmn2c, json_tx)
        self.check_mn_list(mns)  # 6 masternodes again

        # Test payments.
        # Mine 12 blocks and check that each masternode has been paid exactly twice.
        # Save last paid masternode. Check that it's the last paid also after the 12 blocks.
        # Note: dmn2 sends (2 * 0.3 OMEGA) to the operator, and (2 * 2.7 OMEGA) to the owner
        self.log.info("Testing masternode payments...")
        last_paid_mn = self.get_last_paid_mn()
        starting_balances = {
            "operator":
            self.get_addr_balance(self.nodes[dmn2c.idx], op_rew["address"])
        }
        for mn in mns:
            starting_balances[mn.payee] = self.get_addr_balance(
                controller, mn.payee)
        miner.generate(12)
        self.sync_blocks()
        for mn in mns:
            bal = self.get_addr_balance(controller, mn.payee)
            expected = starting_balances[mn.payee] + (
                Decimal('6.0') if mn.idx != dmn2c.idx else Decimal('5.4'))
            if bal != expected:
                raise Exception("Invalid balance (%s != %s) for node %d" %
                                (bal, expected, mn.idx))
        self.log.info("All masternodes paid twice.")
        assert_equal(
            self.get_addr_balance(self.nodes[dmn2c.idx], op_rew["address"]),
            starting_balances["operator"] + Decimal('0.6'))
        self.log.info("Operator paid twice.")
        assert_equal(last_paid_mn, self.get_last_paid_mn())
        self.log.info("Order preserved.")

        # Test invalid payment
        self.wait_until_mnsync_completed()  # just to be sure
        self.log.info("Testing invalid masternode payment...")
        mn_payee_script = miner.validateaddress(
            miner.getnewaddress())['scriptPubKey']
        block = self.create_block(
            mn_payee_script, miner.getblock(miner.getbestblockhash(), True))
        block.solve()
        assert_equal(miner.submitblock(bytes_to_hex_str(block.serialize())),
                     "bad-cb-payee")

        self.log.info("All good.")
Exemplo n.º 4
0
    def run_test(self):
        self.disable_mocktime()
        nodeA = self.nodes[0]
        nodeB = self.nodes[1]
        free_idx = 1  # unique id for masternodes. first available.

        # Enforce mn payments and reject legacy mns at block 202
        self.activate_spork(0, "SPORK_8_MASTERNODE_PAYMENT_ENFORCEMENT")
        assert_equal("success",
                     self.set_spork(0, "SPORK_21_LEGACY_MNS_MAX_HEIGHT", 201))
        time.sleep(1)
        assert_equal([201] * self.num_nodes, [
            self.get_spork(x, "SPORK_21_LEGACY_MNS_MAX_HEIGHT")
            for x in range(self.num_nodes)
        ])

        # Mine 201 blocks
        self.log.info("Mining...")
        nodeA.generate(25)
        self.sync_blocks()
        nodeB.generate(25)
        self.sync_blocks()
        nodeA.generate(50)
        self.sync_blocks()
        nodeB.generate(101)
        self.sync_blocks()
        self.assert_equal_for_all(201, "getblockcount")

        # Register one masternode before the split
        collateral_addr = nodeA.getnewaddress(
        )  # for both collateral and payouts
        pre_split_mn = create_new_dmn(100, nodeA, nodeA.getnewaddress(), None)
        self.register_masternode(nodeA, pre_split_mn, collateral_addr)
        nodeA.generate(1)
        self.sync_blocks()
        mnsA = [pre_split_mn]
        mnsB = [pre_split_mn]
        self.check_mn_list_on_node(0, mnsA)
        self.check_mn_list_on_node(1, mnsB)
        self.log.info("Pre-split masternode registered.")

        # Disconnect the nodes
        self.disconnect_all()  # network splits at block 203

        #
        # -- CHAIN A --
        #

        # Register 5 masternodes, then mine 5 blocks
        self.log.info("Registering masternodes on chain A...")
        for _ in range(5):
            dmn = create_new_dmn(free_idx, nodeA, collateral_addr, None)
            free_idx += 1
            self.register_masternode(nodeA, dmn, collateral_addr)
            mnsA.append(dmn)
        nodeA.generate(5)
        self.check_mn_list_on_node(0, mnsA)
        self.log.info("Masternodes registered on chain A.")

        # Lock any utxo with less than 101 confs (e.g. change), so we can resurrect everything
        for x in nodeA.listunspent(0, 101):
            nodeA.lockunspent(False, [{"txid": x["txid"], "vout": x["vout"]}])

        # Now send a valid proReg tx to the mempool, without mining it
        mempool_dmn1 = create_new_dmn(free_idx, nodeA, collateral_addr, None)
        free_idx += 1
        self.register_masternode(nodeA, mempool_dmn1, collateral_addr)
        assert mempool_dmn1.proTx in nodeA.getrawmempool()

        # Try sending a proReg tx with same owner
        self.log.info("Testing in-mempool duplicate-owner rejection...")
        dmn_A1 = create_new_dmn(free_idx, nodeA, collateral_addr, None)
        free_idx += 1
        dmn_A1.owner = mempool_dmn1.owner
        assert_raises_rpc_error(-26, "protx-dup", self.register_masternode,
                                nodeA, dmn_A1, collateral_addr)
        assert dmn_A1.proTx not in nodeA.getrawmempool()

        # Try sending a proReg tx with same operator
        self.log.info("Testing in-mempool duplicate-operator rejection...")
        dmn_A2 = create_new_dmn(free_idx, nodeA, collateral_addr, None)
        free_idx += 1
        dmn_A2.operator = mempool_dmn1.operator
        assert_raises_rpc_error(-26, "protx-dup", self.register_masternode,
                                nodeA, dmn_A2, collateral_addr)
        assert dmn_A2.proTx not in nodeA.getrawmempool()

        # Try sending a proReg tx with same IP
        self.log.info("Testing proReg in-mempool duplicate-IP rejection...")
        dmn_A3 = create_new_dmn(free_idx, nodeA, collateral_addr, None)
        free_idx += 1
        dmn_A3.ipport = mempool_dmn1.ipport
        assert_raises_rpc_error(-26, "protx-dup", self.register_masternode,
                                nodeA, dmn_A3, collateral_addr)
        assert dmn_A3.proTx not in nodeA.getrawmempool()

        # Now send other 2 valid proReg tx to the mempool, without mining it
        mempool_dmn2 = create_new_dmn(free_idx, nodeA, collateral_addr, None)
        free_idx += 1
        mempool_dmn3 = create_new_dmn(free_idx, nodeA, collateral_addr, None)
        free_idx += 1
        self.register_masternode(nodeA, mempool_dmn2, collateral_addr)
        self.register_masternode(nodeA, mempool_dmn3, collateral_addr)

        # Now nodeA has 3 proReg txes in its mempool
        mempoolA = nodeA.getrawmempool()
        assert mempool_dmn1.proTx in mempoolA
        assert mempool_dmn2.proTx in mempoolA
        assert mempool_dmn3.proTx in mempoolA

        assert_equal(nodeA.getblockcount(), 207)

        #
        # -- CHAIN B --
        #
        collateral_addr = nodeB.getnewaddress()
        self.log.info("Registering masternodes on chain B...")

        # Register first the 3 nodes that conflict with the mempool of nodes[0]
        # mine one block after each registration
        for dmn in [dmn_A1, dmn_A2, dmn_A3]:
            self.register_masternode(nodeB, dmn, collateral_addr)
            mnsB.append(dmn)
            nodeB.generate(1)
        self.check_mn_list_on_node(1, mnsB)

        # Pick the proReg for the first MN registered on chain A, and replay it on chain B
        self.log.info("Replaying a masternode on a different chain...")
        mnsA.remove(pre_split_mn)
        replay_mn = mnsA.pop(0)
        mnsB.append(replay_mn)  # same proTx hash
        nodeB.sendrawtransaction(
            nodeA.getrawtransaction(replay_mn.proTx, False))
        nodeB.generate(1)
        self.check_mn_list_on_node(1, mnsB)

        # Now pick a proReg for another MN registered on chain A, and re-register it on chain B
        self.log.info("Re-registering a masternode on a different chain...")
        rereg_mn = random.choice(mnsA)
        mnsA.remove(rereg_mn)
        self.register_masternode(nodeB, rereg_mn, collateral_addr)
        mnsB.append(rereg_mn)  # changed proTx hash
        nodeB.generate(1)
        self.check_mn_list_on_node(1, mnsB)

        # Register 5 more masternodes. One per block.
        for _ in range(5):
            dmn = create_new_dmn(free_idx, nodeB, collateral_addr, None)
            free_idx += 1
            self.register_masternode(nodeB, dmn, collateral_addr)
            mnsB.append(dmn)
            nodeB.generate(1)

        # Then mine 10 more blocks on chain B
        nodeB.generate(10)
        self.check_mn_list_on_node(1, mnsB)
        self.log.info("Masternodes registered on chain B.")

        assert_equal(nodeB.getblockcount(), 222)

        #
        # -- RECONNECT --
        #

        # Reconnect and sync (give it some more time)
        self.log.info("Reconnecting nodes...")
        self.connect_all()
        self.sync_blocks(wait=3, timeout=180)

        # Both nodes have the same list (mnB)
        self.log.info("Checking masternode list...")
        self.check_mn_list_on_node(0, mnsB)
        self.check_mn_list_on_node(1, mnsB)
        self.log.info("Both nodes have %d registered masternodes." % len(mnsB))

        # The first mempool proReg tx has been removed from nodeA's mempool due to
        # conflicts with the masternodes of chain B, now connected.
        self.log.info("Checking mempool...")
        mempoolA = nodeA.getrawmempool()
        assert mempool_dmn1.proTx not in mempoolA
        assert mempool_dmn2.proTx in mempoolA
        assert mempool_dmn3.proTx in mempoolA
        # The mempool contains also all the ProReg from the disconnected blocks,
        # except the ones re-registered and replayed on chain B.
        for mn in mnsA:
            assert mn.proTx in mempoolA
        assert rereg_mn.proTx not in mempoolA
        assert replay_mn.proTx not in mempoolA
        assert pre_split_mn.proTx not in mempoolA

        self.log.info("All good.")