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

        base_asset_name = "FROZEN_GLOBAL"
        asset_name = f"${base_asset_name}"
        qty = 10000
        verifier = "true"
        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)

        # pre-freeze validation
        assert_does_not_contain(asset_name, n0.listglobalrestrictions())
        assert not n0.checkglobalrestriction(asset_name)
        assert_equal(10000, n0.listassetbalancesbyaddress(address)[asset_name])
        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 change address", n0.freezerestrictedasset, asset_name, "garbagechangeaddress")

        n0.freezerestrictedasset(asset_name, spl_change_address)  # Can only freeze once!
        assert_raises_rpc_error(-26, "Freezing transaction already in mempool", n0.freezerestrictedasset, asset_name, spl_change_address)
        n0.generate(1)
        assert_raises_rpc_error(None, "global-freeze-when-already-frozen", n0.freezerestrictedasset, asset_name, spl_change_address)

        # post-freeze validation
        assert_contains(asset_name, n0.listglobalrestrictions())
        assert n0.checkglobalrestriction(asset_name)
        assert_raises_rpc_error(-8, "restricted asset has been globally frozen", n0.transferfromaddress, asset_name, address, 1000, n1.getnewaddress())
        assert_raises_rpc_error(None, "Invalid Splendid change address", n0.unfreezerestrictedasset, asset_name, "garbagechangeaddress")

        n0.unfreezerestrictedasset(asset_name, spl_change_address)  # Can only un-freeze once!
        assert_raises_rpc_error(-26, "Unfreezing transaction already in mempool", n0.unfreezerestrictedasset, asset_name, spl_change_address)
        n0.generate(1)
        assert_raises_rpc_error(None, "global-unfreeze-when-not-frozen", n0.unfreezerestrictedasset, asset_name, spl_change_address)

        # post-unfreeze validation
        assert_does_not_contain(asset_name, n0.listglobalrestrictions())
        assert not n0.checkglobalrestriction(asset_name)
        assert_equal(9000, n0.listassetbalancesbyaddress(address)[asset_name])
        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])
示例#2
0
    def issue_invalid(self):
        self.log.info("Trying some invalid calls...")
        n0, n1 = self.nodes[0], self.nodes[1]
        n1.generate(10)
        self.sync_all()

        root = gen_root_asset_name()
        asset_name = gen_unique_asset_name(root)

        # no root
        assert_raises_rpc_error(-32600, f"Wallet doesn't have asset: {root}!",
                                n0.issue, asset_name)

        # don't own root
        n0.sendtoaddress(n1.getnewaddress(), 501)
        n0.generate(1)
        self.sync_all()
        n1.issue(root)
        n1.generate(1)
        self.sync_all()
        assert_contains(root, n0.listassets())
        assert_raises_rpc_error(-32600, f"Wallet doesn't have asset: {root}!",
                                n0.issue, asset_name)
        n1.transfer(f"{root}!", 1, n0.getnewaddress())
        n1.generate(1)
        self.sync_all()

        # bad qty
        assert_raises_rpc_error(
            -8, "Invalid parameters for issuing a unique asset.", n0.issue,
            asset_name, 2)

        # bad units
        assert_raises_rpc_error(
            -8, "Invalid parameters for issuing a unique asset.", n0.issue,
            asset_name, 1, "", "", 1)

        # reissuable
        assert_raises_rpc_error(
            -8, "Invalid parameters for issuing a unique asset.", n0.issue,
            asset_name, 1, "", "", 0, True)

        # already exists
        n0.issue(asset_name)
        n0.generate(1)
        self.sync_all()
        assert_raises_rpc_error(
            -8,
            f"Invalid parameter: asset_name '{asset_name}' has already been used",
            n0.issue, asset_name)
示例#3
0
    def issue_unique_test(self):
        self.log.info("Testing issueunique RPC...")
        n0, n1 = self.nodes[0], self.nodes[1]
        n0.sendtoaddress(n1.getnewaddress(), 501)

        root = gen_root_asset_name()
        n0.issue(asset_name=root)
        asset_tags = ["first", "second"]
        ipfs_hashes = ["QmWWQSuPMS6aXCbZKpEjPHPUZN2NjB3YrhJTHsV4X3vb2t"
                       ] * len(asset_tags)
        n0.issueunique(root, asset_tags, ipfs_hashes)
        block_hash = n0.generate(1)[0]

        asset_name = ""
        for tag in asset_tags:
            asset_name = f"{root}#{tag}"
            assert_equal(1, n0.listmyassets()[asset_name])
            assert_equal(
                1,
                n0.listassets(asset_name, True)[asset_name]['has_ipfs'])
            assert_equal(
                ipfs_hashes[0],
                n0.listassets(asset_name, True)[asset_name]['ipfs_hash'])

        # invalidate
        n0.invalidateblock(block_hash)
        assert (root in n0.listmyassets())
        assert_does_not_contain_key(
            asset_name,
            n0.listmyassets(asset="*",
                            verbose=False,
                            count=100000,
                            start=0,
                            confs=1))

        # reconsider
        n0.reconsiderblock(block_hash)
        assert_contains(root, n0.listmyassets())
        assert_contains(asset_name, n0.listmyassets())

        # root doesn't exist
        missing_asset = "VAPOUR"
        assert_raises_rpc_error(
            -32600, f"Wallet doesn't have asset: {missing_asset}!",
            n0.issueunique, missing_asset, asset_tags)

        # don't own root
        n1.issue(missing_asset)
        n1.generate(1)
        self.sync_all()
        assert_contains(missing_asset, n0.listassets())
        assert_raises_rpc_error(
            -32600, f"Wallet doesn't have asset: {missing_asset}!",
            n0.issueunique, missing_asset, asset_tags)
    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)
示例#6
0
    def run_test(self):
        nodes = self.nodes

        # BIP39 list should contain 2048 words
        assert_equal(len(bip39_english), 2048)

        # Node 0 has 12 words and a passphrase
        self.log.info("Testing BIP-44 Word-Lists and passphrases")
        assert_equal(len(nodes[0].getmywords()['word_list'].split(' ')), 12) # Contains 12 words
        assert_equal(nodes[0].getmywords()['word_list'], MNEMONIC_0) # Word list matches
        assert_equal(nodes[0].getmywords()['passphrase'], MNEMONIC_PASS_0) # Passphrase matches

        # Node 1 has 12 words but no passphrase
        assert_equal(len(nodes[1].getmywords()['word_list'].split(' ')), 12) # Contains 12 words
        assert_equal(nodes[1].getmywords()['word_list'], MNEMONIC_1) # Word list matches
        assert_does_not_contain(str(nodes[1].getmywords()), 'passphrase') # Passphrase does not exist

        # Node 2 was not created with specific 12 words (using random-auto-generated), and a passphrase
        assert_equal(len(nodes[2].getmywords()['word_list'].split(' ')), 12) # Contains 12 words
        assert(nodes[2].getmywords()['word_list'] != nodes[3].getmywords()['word_list']) # auto-generated word-lists should not match
        assert_equal(nodes[2].getmywords()['passphrase'], MNEMONIC_PASS_2)

        # Node 3 was not created with specific 12 words (using random-auto-generated), and no passphrase
        assert_equal(len(nodes[3].getmywords()['word_list'].split(' ')), 12) # Contains 12 words
        assert_does_not_contain(str(nodes[3].getmywords()), 'passphrase') # Passphrase does not exist

        # Nodes 4 & 5 are not BIP44 and should not have 12-words or passphrase
        assert_raises_rpc_error(-4, "Wallet doesn't have 12 words.", nodes[4].getmywords)
        assert_raises_rpc_error(-4, "Wallet doesn't have 12 words.", nodes[5].getmywords)

        # Cannot change from a non-BIP44 to a BIP44 wallet
        self.log.info("Testing that BIP-44 wallets are intransigent")
        self.stop_node(4)
        self.stop_node(5)
        self.start_node(4, extra_args=['-bip44=1', '-mnemonicpassphrase=test4'])
        self.start_node(5, extra_args=['-bip44=1', '-mnemonic=' + MNEMONIC_0, '-mnemonicpassphrase=' + MNEMONIC_PASS_0])
        assert_raises_rpc_error(-4, "Wallet doesn't have 12 words.", nodes[4].getmywords)
        assert_raises_rpc_error(-4, "Wallet doesn't have 12 words.", nodes[5].getmywords)

        # Try to add a passphrase to an existing bip44 wallet (should not add passphrase)
        self.stop_node(3)
        self.start_node(3, extra_args=['-mnemonicpassphrase=test3'])
        assert_does_not_contain(str(nodes[3].getmywords()), 'passphrase') # Passphrase does not exist

        # Cannot change an already created bip44 wallet to a non-bip44 wallet
        word_list_3 = nodes[3].getmywords()['word_list']
        self.stop_node(3)
        self.start_node(3, extra_args=['-bip44=0'])
        assert_equal(nodes[3].getmywords()['word_list'], word_list_3) # Word list matches

        # All 4 bip44 enabled wallets word-lists are in the bip39 word-list
        self.log.info("Testing that BIP-44 wallets words are valid")
        word_list_0 = MNEMONIC_0.split(' ')
        word_list_1 = MNEMONIC_1.split(' ')
        word_list_2 = nodes[2].getmywords()['word_list'].split(' ')
        word_list_3 = word_list_3.split(' ')
        for i in range(0, 12):
            assert_contains(word_list_0[i], bip39_english)
            assert_contains(word_list_1[i], bip39_english)
            assert_contains(word_list_2[i], bip39_english)
            assert_contains(word_list_3[i], bip39_english)

        # None of the words should be text-readable in the log files
        self.log.info("Testing that BIP-44 words aren't text readable")
        mnemonic_2 = nodes[2].getmywords()['word_list']
        mnemonic_3 = nodes[3].getmywords()['word_list']
        self.stop_nodes()
        with open(os.path.join(self.options.tmpdir+"/node0/regtest/", "debug.log"), 'r', encoding='utf8') as f:
            assert_does_not_contain(MNEMONIC_0, f.read())
        with open(os.path.join(self.options.tmpdir+"/node1/regtest/", "debug.log"), 'r', encoding='utf8') as f:
            assert_does_not_contain(MNEMONIC_1, f.read())
        with open(os.path.join(self.options.tmpdir+"/node2/regtest/", "debug.log"), 'r', encoding='utf8') as f:
            assert_does_not_contain(mnemonic_2, f.read())
        with open(os.path.join(self.options.tmpdir+"/node3/regtest/", "debug.log"), 'r', encoding='utf8') as f:
            assert_does_not_contain(mnemonic_3, f.read())

        # But words are readable in a non-encrypted wallet
        with open(os.path.join(self.options.tmpdir+"/node0/regtest/", "wallet.dat"), 'rb') as f:
            assert_contains(MNEMONIC_0, str(f.read()))
        with open(os.path.join(self.options.tmpdir+"/node1/regtest/", "wallet.dat"), 'rb') as f:
            assert_contains(MNEMONIC_1, str(f.read()))
        with open(os.path.join(self.options.tmpdir+"/node2/regtest/", "wallet.dat"), 'rb') as f:
            assert_contains(mnemonic_2, str(f.read()))
        with open(os.path.join(self.options.tmpdir+"/node3/regtest/", "wallet.dat"), 'rb') as f:
            assert_contains(mnemonic_3, str(f.read()))

        # After encryption the words are no longer readable
        self.log.info("Testing that BIP-44 wallet encryption")
        self.start_nodes()
        nodes[0].node_encrypt_wallet("password0")
        nodes[1].node_encrypt_wallet("password1")
        nodes[2].node_encrypt_wallet("password2")
        nodes[3].node_encrypt_wallet("password3")
        self.stop_nodes()
        # But words are not readable in an encrypted wallet
        with open(os.path.join(self.options.tmpdir+"/node0/regtest/", "wallet.dat"), 'rb') as f:
            assert_does_not_contain(MNEMONIC_0, str(f.read()))
        with open(os.path.join(self.options.tmpdir+"/node1/regtest/", "wallet.dat"), 'rb') as f:
            assert_does_not_contain(MNEMONIC_1, str(f.read()))
        with open(os.path.join(self.options.tmpdir+"/node2/regtest/", "wallet.dat"), 'rb') as f:
            assert_does_not_contain(mnemonic_2, str(f.read()))
        with open(os.path.join(self.options.tmpdir+"/node3/regtest/", "wallet.dat"), 'rb') as f:
            assert_does_not_contain(mnemonic_3, str(f.read()))

        # But the words are still available using getmywords after entering the passphrase
        self.start_nodes()
        assert_raises_rpc_error(-13, "Please enter the wallet passphrase with walletpassphrase first.", nodes[0].getmywords)
        nodes[0].walletpassphrase("password0", 48)
        assert_equal(nodes[0].getmywords()['word_list'], MNEMONIC_0) # Word list matches

        # Words can also be retrieved from the dumpwallet command
        nodes[0].dumpwallet(os.path.join(self.options.tmpdir+"/node0/regtest/", "dump_wallet_0.txt"))
        with open(os.path.join(self.options.tmpdir+"/node0/regtest/", "dump_wallet_0.txt"), 'r') as f:
            assert_contains(MNEMONIC_0, str(f.read()))
示例#7
0
    def run_test(self):
        """Main test logic"""
        # prepare
        node = self.nodes[0]
        node2 = self.nodes[1]
        node.generate(nblocks=2)  # make some coins
        self.sync_all()

        # publish
        contract = generate_contract(self.options.tmpdir)
        result = node.publishcontract(contract)
        contract_id = result['contractaddress']
        sender = result['senderaddress']

        call_contract = caller_factory(self, contract_id, sender)
        # call
        # no coins
        assert_contains(call_contract(PAYABLE, amount=10000000), "Insufficient funds")

        # # 非法的入参
        for amount in [10000000000, -1, 0, Decimal("0.00000009").quantize(Decimal("0.000000"))]:
            call_contract(PAYABLE, amount=amount)

        # 非法sender
        for sender_addr in [sender + "x", contract_id]:
            assert_contains(caller_factory(self, contract_id, sender_addr)(PAYABLE), "Invalid sender address")

        # # 合约不存在
        assert_contains(caller_factory(self, "2PPWpHssgXjA8yEgfd3Vo36Hhx1eimbGCcP", sender)(PAYABLE),
                        "GetContractInfo fail")

        # # 地址错误
        for addr in [contract_id + 'x', sender]:
            caller_factory(self, addr, sender)(PAYABLE)

        # 函数不存在
        if not SKIP:
            assert_contains(call_contract("payable2"), "can not find function")

        # send不能被裸调用
        # bug被修复前,暂时跳过
        if not SKIP:
            assert_contains(call_contract("send",sender,0),'can not call lua internal function directly')
            assert_contains(call_contract("rpcSendTest"), 'can not call lua internal function directly')

        # when not commit transaction, make sure contract tx is not in mempool
        if not SKIP:
            mempool = node.getrawmempool()
            node.callcontract(False, 1, contract_id, sender, PAYABLE)
            assert mempool == node.getrawmempool()

        # recharge to contract
        txid = call_contract(PAYABLE,amount = 1000)['txid']
        sync_mempools(self.nodes)
        assert txid in node.getrawmempool()
        assert txid in node2.getrawmempool()
        assert_equal(node.getbalanceof(contract_id), 0)  #合约的余额只会在一定的确认数之后才可以查看,在内存池中是不生效的
        node.generate(nblocks=1)
        self.sync_all()
        assert txid not in node.getrawmempool()
        assert txid not in node2.getrawmempool()
        assert_equal(node.getbalanceof(contract_id), 1000)  # 确认合约余额

        # doubleSpendTest
        self.test_double_spend(mineblock=False)
        self.test_double_spend()
        call_contract("doubleSpendTest", node.getnewaddress(),throw_exception = True)

        # cmsgpackTest
        if not SKIP:
            assert_contains(call_contract("cmsgpackTest", node.getnewaddress(), 0), 'cmsgpack => sc >= LUACMSGPACK_MAX_NESTING')
        self.sync_all()


        # # tailLoopTest
        call_contract("tailLoopTest", 896)  # v452,594 is the limit
        assert_contains(call_contract("tailLoopTest", 897), "run out of limit instruction")


        # # tailLoopTest2
        call_contract("tailLoopTest2", 11)
        assert_contains(call_contract("tailLoopTest2", 12), "Too many args in lua function")

        # # unpackTest
        assert_contains(call_contract("unpackTest"), "too many results to unpack")

        # localFuncTest
        if not SKIP:
            assert_contains(call_contract("localFuncTest"), "can not find function")

        # longReturnTest
        if not SKIP:
            c = generate_contract(self.options.tmpdir, err_type="long_string_return")
            addre = node.publishcontract(c)['contractaddress']
            node.callcontract(True,1,addre,sender,'longReturnTest')

        # contractDataTest
        call_contract("contractDataTest")
        assert_equal(call_contract("get", "size")['return'][0], 127)

        # make sure node1 mempool is empty
        node.generate(nblocks=2)
        assert_equal([], node.getrawmempool())
        # sendCoinTest
        # send to mgc address
        new_address = node.getnewaddress()
        txid = call_contract("sendCoinTest", new_address, 1)['txid']
        assert txid in node.getrawmempool()
        call_contract("sendCoinTest", new_address, "1e-3")
        assert_contains(call_contract("sendCoinTest", new_address, 2 ** 31 - 1), "not enough amount ")
        assert_contains(call_contract("sendCoinTest", new_address, 0.1), "JSON integer out of range")
        assert_contains(call_contract("sendCoinTest", new_address, 0), "SendCoins => amount(0) out of range")
        assert_contains(call_contract("sendCoinTest", new_address, -1), "SendCoins => amount(-100000000) out of range")
        # send all balance
        tmp_id = node.publishcontract(contract)["contractaddress"]
        tmp_caller = caller_factory(self, tmp_id, sender)
        tmp_caller(PAYABLE, amount=Decimal("1"))
        tmp_txid = tmp_caller("sendCoinTest", new_address, 1, amount=Decimal("0"),throw_exception = True)['txid']
        # 利用节点2挖矿,确保节点1的交易可以打包的块
        self.sync_all()
        node2.generate(nblocks=2)  # 这里需要挖2个,因为send的输出需要达到成熟度才可以使用
        self.sync_all()
        # make sure two transactions not in mempool
        # if assert failed it should be bug here
        assert txid not in node.getrawmempool()
        assert tmp_txid not in node.getrawmempool()
        self.sync_all()
        assert_equal(node.getbalanceof(tmp_id), 0)
        assert_equal(node.getbalanceof(new_address), 2)
        assert_equal(node2.getbalanceof(new_address), 2)
        assert_equal(node2.getbalanceof(tmp_id), 0)
        assert_contains(tmp_caller("sendCoinTest", new_address, 1), "not enough amount ")

        # send to contract
        tmp_id = node.publishcontract(contract)["contractaddress"]
        assert_contains(call_contract("sendCoinTest", tmp_id, 100), "Invalid destination address")
        node.generate(nblocks=1)

        # batchSendTest
        # 12个参数是上限,除去内部调用之后,实际能用的就只有7个参数位,并且不支持数组
        for to in range(4):
            to_list = [node.getnewaddress() for i in range(7)]
            call_contract("addWithdrawList", *to_list)
        call_contract("batchSendTest")
        node.generate(nblocks=2)
        for addr in to_list:
            assert_equal(node.getbalanceof(addr), 1)

        # updateContractTest
        call_contract("updateContract", "self", "weigun")
        assert_equal(call_contract("get", "self")['return'][0], "weigun")
        node.generate(1)

        assert_equal([],node.getrawmempool()) # make sure mempool is empty
        # cycleSelfTest
        self.log.info("begin cycleSelfTest")
        if not SKIP:
            for i in range(100):
                call_contract("cycleSelf",throw_exception = False)
                call_contract("updateContract", "this", "",throw_exception = False)
                if i % 5 == 0:
                    # print("generate block at :",i)
                    node.generate(1)
            node.generate(1)

        # assert_equal([], node.getrawmempool())  # make sure mempool is empty
        # maxContractCallTest
        call_contract("maxContractCallTest", 15)  # 15 is the limit
        assert_contains(call_contract("maxContractCallTest", 16), "run out of limit instruction")
        # callOtherContractTest
        # cycle call
        # step1 create contracts
        ca_id = contract_id
        cb_id = node.publishcontract(contract)["contractaddress"]
        cc_id = node.publishcontract(contract)["contractaddress"]
        caller_b = caller_factory(self, cb_id, sender)
        node.generate(nblocks=1)

        # step2  a->b->c->a(send will be call in last a)
        new_address = node.getnewaddress()
        if not SKIP:
            call_contract(CYCLE_CALL, cb_id, CYCLE_CALL, cc_id, CYCLE_CALL, ca_id, "sendCoinTest", new_address,throw_exception = True)
            node.generate(nblocks=1)
            assert_equal(node.getbalanceof(new_address), 1)

        # step3 a->b->c->b,modify PersistentData
        if not SKIP:
            caller_b("contractDataTest")  # after called,size should be 127
            assert_equal(caller_b("get", "size")['return'][0], 127)
            call_contract(CYCLE_CALL, cb_id, CYCLE_CALL, cc_id, CYCLE_CALL, cb_id, "reentrancyTest",
                          new_address,throw_exception = True)  # after called,size should be 127,because of replace dump
            call_contract(CYCLE_CALL, cb_id, CYCLE_CALL, cc_id, CYCLE_CALL, cb_id, "contractDataTest",
                          new_address,throw_exception = True)  # after called,size should be 127,because of replace dump
            node.generate(nblocks=1)
            assert_equal(caller_b("get", "size")['return'][0], 127)

        # lots of dust vin in contract's send transaction
        # TODO:maybe  need to set payfee param in magnachaind
        if not SKIP:
            cd_id = node.publishcontract(contract)["contractaddress"]
            caller_d = caller_factory(self, cd_id, sender)
            for i in range(2000):
                caller_d(PAYABLE, amount=Decimal("1"),throw_exception = True)
                if i % 30 == 0:
                    node.generate(nblocks=1)
            new_address = node.getnewaddress()
            caller_d("sendCoinTest", new_address, 1900, amount=Decimal("0"))
            node.generate(nblocks=2)
            assert_equal(node.getbalanceof(new_address), 1900)

        # dust change vout in send
        # node.sendtoaddress(new_sender,2)
        if not SKIP:
            tmp_id = node.publishcontract(contract)['contractaddress']
            caller_tmp = caller_factory(self, tmp_id, sender)
            senders = [node.getnewaddress() for i in range(101)]
            i = 0
            for _ in senders:
                # 充值101次,每次1个MGC
                caller_tmp(PAYABLE, amount=1,throw_exception = True)
                if i % 30 == 0:
                    node.generate(1)
                i += 1
            node.generate(2)
            assert_equal(node.getbalanceof(tmp_id), 101)
            i = 0
            for to in senders:
                # 向每个地址发送cell - 999(最小单位),cell = 100000000。这里应该有101个微交易的找零
                assert_equal(isinstance(caller_tmp("dustChangeTest", to, amount=Decimal("0"),throw_exception = True), dict), True)
                if i % 30 == 0:
                    node.generate(1)
                i += 1
            node.generate(nblocks=2)
            assert_equal(node.getbalanceof(tmp_id) * COIN, 101 * COIN - (COIN - 999 ) * 101) #因为lua没有浮点数,所以小数部分会截断掉
            bal = node.getbalanceof(tmp_id)
            print(bal)
            tmp_sender = node.getnewaddress()
            assert_equal(isinstance(caller_tmp("sendCoinTest2", tmp_sender,amount=Decimal("0"),throw_exception = True), dict),
                         True)  # 组合所有微交易的找零,应该足够0.001个MGC的
            node.generate(nblocks=2)
            assert_equal(node.getbalanceof(tmp_sender), Decimal("0.001"))
            assert_equal(node.getbalanceof(tmp_id), bal - Decimal("0.001"))

        # reentrancyTest
        last_id = node.publishcontract(contract)['contractaddress']
        caller_last = caller_factory(self, last_id, sender)
        if not SKIP:
            caller_last("reentrancyTest")
            node.generate(nblocks=1)
            assert_equal(caller_last("get", "this")['return'], [])

        # 疲劳测试
        if not SKIP:
            to_list = [node.getnewaddress() for i in range(1000)]
            for i,to in enumerate(to_list):
                caller_last(PAYABLE, amount=10)
                caller_last(CYCLE_CALL, last_id, "contractDataTest",amount=0)
                caller_last(CYCLE_CALL, last_id, "dustChangeTest",to,amount=0)
                caller_last(CYCLE_CALL, last_id, "addWithdrawList",to,amount=0)
                # caller_last(CYCLE_CALL, last_id, "batchSendTest",amount=0)
                if random.randint(1,100) > 70:
                    node.generate(nblocks=1)
                else:
                    if i % 30 == 0:
                        node.generate(nblocks=1)
示例#8
0
    def test_messaging(self):
        self.log.info("Testing messaging!")
        n0, n1 = self.nodes[0], self.nodes[1]

        spam_name = "SPAM"
        asset_name = "MESSAGING"
        owner_name = "MESSAGING!"
        channel_one = "MESSAGING~ONE"
        channel_two = "MESSAGING~TWO"
        ipfs_hash = "QmZPGfJojdTzaqCWJu2m3krark38X1rqEHBo4SjeqHKB26"

        # need ownership before channels can be created
        assert_raises_rpc_error(-32600,
                                "Wallet doesn't have asset: " + owner_name,
                                n0.issue, channel_one)

        n0.issue(asset_name, 100)
        n0.issue(channel_one)
        n0.issue(channel_two)
        n0.issue(spam_name, 100)

        n0.generate(1)
        self.sync_all()

        # you're auto-subscribed to your own channels
        n0_channels = n0.viewallmessagechannels()
        assert_contains(owner_name, n0_channels)
        assert_contains(channel_one, n0_channels)
        assert_contains(channel_two, n0_channels)

        # n1 subscribes to owner and channel one
        assert_equal([], n1.viewallmessagechannels())
        n1.subscribetochannel(owner_name)
        n1.subscribetochannel(channel_one)
        n1_channels = n1.viewallmessagechannels()
        assert_contains(owner_name, n1_channels)
        assert_contains(channel_one, n1_channels)
        assert_does_not_contain(channel_two, n1_channels)

        # n0 sends a message on owner
        n0.sendmessage(owner_name, ipfs_hash)
        n0.generate(1)
        self.sync_all()

        # n1 views then clears messages
        n1_messages = n1.viewallmessages()
        assert_equal(1, len(n1_messages))
        message = n1_messages[0]
        assert_contains_pair("Asset Name", owner_name, message)
        assert_contains_pair("Message", ipfs_hash, message)
        n1.clearmessages()
        n1_messages = n1.viewallmessages()
        assert_equal(0, len(n1_messages))

        # n0 sends more messages on channels one and two
        n0.sendmessage(channel_one, ipfs_hash)
        n0.sendmessage(channel_two, ipfs_hash)
        n0.generate(1)
        self.sync_all()

        # n1 views then clears messages
        n1_messages = n1.viewallmessages()
        assert_equal(1, len(n1_messages))
        message = n1_messages[0]
        assert_contains_pair("Asset Name", channel_one, message)
        assert_contains_pair("Message", ipfs_hash, message)
        n1.clearmessages()
        n1_messages = n1.viewallmessages()
        assert_equal(0, len(n1_messages))

        # n1 unsubscribes
        n1.unsubscribefromchannel(owner_name)
        n1.unsubscribefromchannel(channel_one)
        assert_equal(0, len(n1.viewallmessagechannels()))

        # auto-subscribe / spam protection (first address use only)
        addr1 = n1.getnewaddress()
        n0.transfer(asset_name, 10, addr1)
        n0.generate(1)
        self.sync_all()
        n0.transfer(spam_name, 10, addr1)
        n1_channels = n1.viewallmessagechannels()
        assert_equal(1, len(n1_channels))
        assert_contains(owner_name, n1_channels)
        assert_does_not_contain(spam_name, n1_channels)
        n1.unsubscribefromchannel(owner_name)

        # pre-existing messages (don't see w/o rescan)
        assert_equal(0, len(n1.viewallmessages()))
        n0.sendmessage(channel_two, ipfs_hash)
        n0.generate(1)
        self.sync_all()
        assert_equal(0, len(n1.viewallmessages()))
        n1.subscribetochannel(channel_two)
        assert_equal(0, len(n1.viewallmessages()))
        n0.sendmessage(channel_two, ipfs_hash)
        n0.generate(1)
        self.sync_all()
        assert_equal(1, len(n1.viewallmessages()))
        assert_contains_pair("Asset Name", channel_two,
                             n1.viewallmessages()[0])
        n1.clearmessages()
        n1.unsubscribefromchannel(channel_two)