def freezing(self):
        self.log.info("Testing freezing...")
        n0, n1 = self.nodes[0], self.nodes[1]

        base_asset_name = "FROZEN_TM"
        asset_name = f"${base_asset_name}"
        qty = 11000
        verifier = "true"
        address = n0.getnewaddress()
        safe_address = n0.getnewaddress()
        spl_change_address = n0.getnewaddress()

        n0.issue(base_asset_name)
        n0.generate(1)

        n0.issuerestrictedasset(asset_name, qty, verifier, address)
        n0.generate(1)

        # squirrel some away
        change_address = n0.getnewaddress()
        n0.transferfromaddress(asset_name, address, 1000, safe_address, "", "", "", change_address)
        n0.generate(1)
        address = change_address

        # pre-freezing verification
        assert_does_not_contain(asset_name, n0.listaddressrestrictions(address))
        assert not n0.checkaddressrestriction(address, address)
        assert_equal(10000, n0.listassetbalancesbyaddress(address)[asset_name])

        # Isolate this test from other freezing on n0...
        def viewmyrestrictedaddresses():
            return list(filter(lambda x: asset_name == x['Asset Name'], n0.viewmyrestrictedaddresses()))

        # viewmyrestrictedaddresses
        assert_equal(0, len(viewmyrestrictedaddresses()))

        change_address = n0.getnewaddress()
        n0.transferfromaddress(asset_name, address, 1000, n1.getnewaddress(), "", "", "", change_address)
        n0.generate(1)
        self.sync_all()
        assert_equal(9000, n0.listassetbalancesbyaddress(change_address)[asset_name])
        assert_equal(1000, n1.listmyassets()[asset_name])
        address = change_address  # assets have moved

        assert_raises_rpc_error(None, "Invalid Splendid address", n0.freezeaddress, asset_name, "garbageaddress")
        assert_raises_rpc_error(None, "Invalid Splendid change address", n0.freezeaddress, asset_name, address, "garbagechangeaddress")

        n0.freezeaddress(asset_name, address, spl_change_address)
        n0.generate(1)

        assert_raises_rpc_error(-32600, "freeze-address-when-already-frozen", n0.freezeaddress, asset_name, address, spl_change_address)

        # post-freezing verification
        assert_contains(asset_name, n0.listaddressrestrictions(address))
        assert n0.checkaddressrestriction(address, asset_name)

        # viewmyrestrictedaddresses
        restrictions = viewmyrestrictedaddresses()
        assert_equal(1, len(restrictions))
        r = restrictions[0]
        assert_equal(address, r['Address'])
        assert_equal(asset_name, r['Asset Name'])
        assert_happening(r['Restricted'])

        assert_raises_rpc_error(-8, "No asset outpoints are selected from the given address", n0.transferfromaddress, asset_name, address, 1000, n1.getnewaddress())

        assert_raises_rpc_error(None, "Invalid Splendid address", n0.unfreezeaddress, asset_name, "garbageaddress")
        assert_raises_rpc_error(None, "Invalid Splendid change address", n0.unfreezeaddress, asset_name, address, "garbagechangeaddress")

        n0.unfreezeaddress(asset_name, address, spl_change_address)
        n0.generate(1)

        assert_raises_rpc_error(-32600, "unfreeze-address-when-not-frozen", n0.unfreezeaddress, asset_name, address, spl_change_address)

        # post-unfreezing verification
        assert_does_not_contain(asset_name, n0.listaddressrestrictions(address))
        assert not n0.checkaddressrestriction(address, asset_name)
        assert_equal(9000, n0.listassetbalancesbyaddress(address)[asset_name])

        # viewmyrestrictedaddresses
        restrictions = viewmyrestrictedaddresses()
        assert_equal(1, len(restrictions))
        r = restrictions[0]
        assert_equal(address, r['Address'])
        assert_equal(asset_name, r['Asset Name'])
        assert_happening(r['Derestricted'])

        change_address = n0.getnewaddress()
        n0.transferfromaddress(asset_name, address, 1000, n1.getnewaddress(), "", "", "", change_address)
        n0.generate(1)
        self.sync_all()
        assert_equal(8000, n0.listassetbalancesbyaddress(change_address)[asset_name])
        assert_equal(2000, n1.listmyassets()[asset_name])
    def tagging(self):
        self.log.info("Testing tagging...")
        n0 = self.nodes[0]

        tag = "#TAG"
        address = n0.getnewaddress()
        change_address = n0.getnewaddress()

        n0.issuequalifierasset(tag)
        n0.generate(1)

        base_asset_name = "TAG_RESTRICTED"
        asset_name = f"${base_asset_name}"
        qty = 1000
        verifier = tag
        issue_address = n0.getnewaddress()
        n0.issue(base_asset_name)
        assert_raises_rpc_error(-8, "bad-txns-null-verifier-address-failed-verification", n0.issuerestrictedasset, asset_name, qty, verifier, issue_address)

        # Isolate this test from other tagging on n0...
        def viewmytaggedaddresses():
            return list(filter(lambda x: tag == x['Tag Name'], n0.viewmytaggedaddresses()))

        assert_equal(0, len(viewmytaggedaddresses()))

        n0.addtagtoaddress(tag, issue_address, change_address)
        n0.generate(1)
        n0.issuerestrictedasset(asset_name, qty, verifier, issue_address)
        n0.generate(1)

        # pre-tagging verification
        assert_does_not_contain(address, n0.listaddressesfortag(tag))
        assert_does_not_contain(tag, n0.listtagsforaddress(address))
        assert not n0.checkaddresstag(address, tag)

        # viewmytaggedaddresses
        tagged = viewmytaggedaddresses()
        assert_equal(1, len(tagged))
        t1 = tagged[0]
        assert_equal(issue_address, t1['Address'])
        assert_equal(tag, t1['Tag Name'])
        assert_contains_key('Assigned', t1)
        assert_happening(t1['Assigned'])

        assert_raises_rpc_error(-8, "bad-txns-null-verifier-address-failed-verification", n0.transfer, asset_name, 100, address)

        # special case: make sure transfer fails if change address(es) are verified even though to address isn't
        spl_change_address = n0.getnewaddress()
        asset_change_address = n0.getnewaddress()
        n0.addtagtoaddress(tag, spl_change_address)
        n0.addtagtoaddress(tag, asset_change_address)
        n0.generate(1)
        assert_raises_rpc_error(-8, "bad-txns-null-verifier-address-failed-verification", n0.transfer, asset_name, 100, address, "", 0, spl_change_address, asset_change_address)
        n0.removetagfromaddress(tag, spl_change_address)
        n0.removetagfromaddress(tag, asset_change_address)
        n0.generate(1)
        ##

        assert_raises_rpc_error(None, "Invalid Splendid address", n0.addtagtoaddress, tag, "garbageaddress")
        assert_raises_rpc_error(None, "Invalid Splendid change address", n0.addtagtoaddress, tag, address, "garbagechangeaddress")

        n0.addtagtoaddress(tag, address, change_address)
        n0.generate(1)

        assert_raises_rpc_error(-32600, "add-qualifier-when-already-assigned", n0.addtagtoaddress, tag, address, change_address)

        # post-tagging verification
        assert_contains(address, n0.listaddressesfortag(tag))
        assert_contains(tag, n0.listtagsforaddress(address))
        assert n0.checkaddresstag(address, tag)

        # viewmytaggedaddresses
        tagged = viewmytaggedaddresses()
        assert_equal(4, len(tagged))
        assert_contains(issue_address, list(map(lambda x: x['Address'], tagged)))
        assert_contains(address, list(map(lambda x: x['Address'], tagged)))
        for t in tagged:
            assert_equal(tag, t['Tag Name'])
            if 'Assigned' in t:
                assert_happening(t['Assigned'])
            else:
                assert_happening(t['Removed'])

        # special case: make sure transfer fails if the asset change address isn't verified (even if the spl change address is)
        spl_change_address = n0.getnewaddress()
        asset_change_address = n0.getnewaddress()
        assert_raises_rpc_error(-20, "bad-txns-null-verifier-address-failed-verification", n0.transfer, asset_name, 100, address, "", 0, spl_change_address, asset_change_address)
        n0.addtagtoaddress(tag, spl_change_address)
        n0.generate(1)
        assert_raises_rpc_error(-20, "bad-txns-null-verifier-address-failed-verification", n0.transfer, asset_name, 100, address, "", 0, spl_change_address, asset_change_address)
        n0.removetagfromaddress(tag, spl_change_address)
        n0.generate(1)

        # do the transfer already!
        txid = n0.transfer(asset_name, 100, address)
        n0.generate(1)
        assert_equal(64, len(txid[0]))
        assert_equal(100, n0.listassetbalancesbyaddress(address)[asset_name])

        # do another transfer with specified, tagged asset change address
        asset_change_address = n0.getnewaddress()
        n0.addtagtoaddress(tag, asset_change_address)
        n0.generate(1)
        txid = n0.transfer(asset_name, 1, issue_address, "", 0, "", asset_change_address)
        n0.generate(1)
        assert_equal(64, len(txid[0]))
        assert (n0.listassetbalancesbyaddress(asset_change_address)[asset_name] > 0)

        assert_raises_rpc_error(None, "Invalid Splendid address", n0.removetagfromaddress, tag, "garbageaddress")
        assert_raises_rpc_error(None, "Invalid Splendid change address", n0.removetagfromaddress, tag, address, "garbagechangeaddress")

        n0.removetagfromaddress(tag, address, change_address)
        n0.generate(1)

        assert_raises_rpc_error(-32600, "removing-qualifier-when-not-assigned", n0.removetagfromaddress, tag, address, change_address)

        # TODO: test without specifying change address when there are no valid change addresses (all untagged)

        # post-untagging verification
        assert_does_not_contain(address, n0.listaddressesfortag(tag))
        assert_does_not_contain(tag, n0.listtagsforaddress(address))
        assert not n0.checkaddresstag(address, tag)

        # viewmytaggedaddresses
        tagged = viewmytaggedaddresses()
        assert_equal(6, len(tagged))  # includes removed
        assert_contains(issue_address, list(map(lambda x: x['Address'], tagged)))
        assert_contains(address, list(map(lambda x: x['Address'], tagged)))
        for t in tagged:
            assert_equal(tag, t['Tag Name'])
            if issue_address == t['Address']:
                assert_happening(t['Assigned'])
            if address == t['Address']:
                assert_happening(t['Removed'])

        assert_raises_rpc_error(-8, "bad-txns-null-verifier-address-failed-verification", n0.transfer, asset_name, 100, address)