def transferqualifier(self): self.log.info("Testing transferqualifier()...") n0, n1 = self.nodes[0], self.nodes[1] asset_name = "#TQA" nonqualifier_asset_name = "NOTAQUALIFIER" n0_change_address = n0.getnewaddress() n1_address = n1.getnewaddress() message = "QmacSRmrkVmvJfbCpmU6pK72furJ8E8fbKHindrLxmYMQo" n0.issuequalifierasset(asset_name) n0.issue(nonqualifier_asset_name) n0.generate(1) self.sync_all() assert_equal(1, n0.listmyassets(asset_name, True)[asset_name]['balance']) assert_does_not_contain_key(asset_name, n1.listmyassets()) assert_raises_rpc_error(None, "Only use this rpc call to send Qualifier assets", n0.transferqualifier, nonqualifier_asset_name, 1, n1_address) assert_raises_rpc_error(None, "Invalid Splendid address", n0.transferqualifier, asset_name, 1, "garbageaddress") assert_raises_rpc_error(None, "Invalid Splendid address", n0.transferqualifier, asset_name, 1, n1_address, "garbagechangeaddress") assert_raises_rpc_error(None, "Invalid IPFS hash", n0.transferqualifier, asset_name, 1, n1_address, n0_change_address, "garbagemessage") # transfer txid = n0.transferqualifier(asset_name, 1, n1_address, n0_change_address, message) n0.generate(1) self.sync_all() # verify assert_equal(64, len(txid[0])) assert_does_not_contain_key(asset_name, n0.listmyassets()) assert_equal(1, n1.listmyassets(asset_name, True)[asset_name]['balance'])
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 big_test(self): self.log.info("Running big test!") n0, n1 = self.nodes[0], self.nodes[1] self.log.info("Calling issue()...") address0 = n0.getnewaddress() ipfs_hash = "QmcvyefkqQX3PpjpY5L8B2yMd47XrVwAipr6cxUt2zvYU8" n0.issue(asset_name="MY_ASSET", qty=1000, to_address=address0, change_address="", units=4, reissuable=True, has_ipfs=True, ipfs_hash=ipfs_hash) self.log.info("Waiting for ten confirmations after issue...") n0.generate(10) self.sync_all() self.log.info("Checkout getassetdata()...") assetdata = n0.getassetdata("MY_ASSET") assert_equal(assetdata["name"], "MY_ASSET") assert_equal(assetdata["amount"], 1000) assert_equal(assetdata["units"], 4) assert_equal(assetdata["reissuable"], 1) assert_equal(assetdata["has_ipfs"], 1) assert_equal(assetdata["ipfs_hash"], ipfs_hash) self.log.info("Checking listmyassets()...") myassets = n0.listmyassets(asset="MY_ASSET*", verbose=True) assert_equal(len(myassets), 2) asset_names = list(myassets.keys()) assert_equal(asset_names.count("MY_ASSET"), 1) assert_equal(asset_names.count("MY_ASSET!"), 1) assert_equal(myassets["MY_ASSET"]["balance"], 1000) assert_equal(myassets["MY_ASSET!"]["balance"], 1) assert_equal(len(myassets["MY_ASSET"]["outpoints"]), 1) assert_equal(len(myassets["MY_ASSET!"]["outpoints"]), 1) assert_is_hash_string(myassets["MY_ASSET"]["outpoints"][0]["txid"]) assert_equal(myassets["MY_ASSET"]["outpoints"][0]["txid"], myassets["MY_ASSET!"]["outpoints"][0]["txid"]) assert (int(myassets["MY_ASSET"]["outpoints"][0]["vout"]) >= 0) assert (int(myassets["MY_ASSET!"]["outpoints"][0]["vout"]) >= 0) assert_equal(myassets["MY_ASSET"]["outpoints"][0]["amount"], 1000) assert_equal(myassets["MY_ASSET!"]["outpoints"][0]["amount"], 1) self.log.info("Checking listassetbalancesbyaddress()...") assert_equal(n0.listassetbalancesbyaddress(address0)["MY_ASSET"], 1000) assert_equal(n0.listassetbalancesbyaddress(address0)["MY_ASSET!"], 1) self.log.info("Checking listassetbalancesbyaddress()...") assert_equal(n0.listaddressesbyasset("MY_ASSET"), n1.listaddressesbyasset("MY_ASSET")) self.log.info("Calling transfer()...") address1 = n1.getnewaddress() n0.transfer(asset_name="MY_ASSET", qty=200, to_address=address1) self.log.info("Waiting for ten confirmations after transfer...") n0.generate(10) self.sync_all() self.log.info("Checking listmyassets()...") myassets = n1.listmyassets(asset="MY_ASSET*", verbose=True) assert_equal(len(myassets), 1) asset_names = list(myassets.keys()) assert_equal(asset_names.count("MY_ASSET"), 1) assert_equal(asset_names.count("MY_ASSET!"), 0) assert_equal(myassets["MY_ASSET"]["balance"], 200) assert_equal(len(myassets["MY_ASSET"]["outpoints"]), 1) assert_is_hash_string(myassets["MY_ASSET"]["outpoints"][0]["txid"]) assert (int(myassets["MY_ASSET"]["outpoints"][0]["vout"]) >= 0) assert_equal(n0.listmyassets(asset="MY_ASSET")["MY_ASSET"], 800) self.log.info("Checking listassetbalancesbyaddress()...") assert_equal(n1.listassetbalancesbyaddress(address1)["MY_ASSET"], 200) changeaddress = None assert_equal(n0.listaddressesbyasset("MY_ASSET"), n1.listaddressesbyasset("MY_ASSET")) assert_equal(sum(n0.listaddressesbyasset("MY_ASSET").values()), 1000) assert_equal(sum(n1.listaddressesbyasset("MY_ASSET").values()), 1000) for assaddr in n0.listaddressesbyasset("MY_ASSET").keys(): if n0.validateaddress(assaddr)["ismine"]: changeaddress = assaddr assert_equal(n0.listassetbalancesbyaddress(changeaddress)["MY_ASSET"], 800) assert (changeaddress is not None) assert_equal(n0.listassetbalancesbyaddress(address0)["MY_ASSET!"], 1) self.log.info("Burning all units to test reissue on zero units...") n0.transfer(asset_name="MY_ASSET", qty=800, to_address="n1BurnXXXXXXXXXXXXXXXXXXXXXXU1qejP") n0.generate(1) assert_does_not_contain_key("MY_ASSET", n0.listmyassets(asset="MY_ASSET", verbose=True)) self.log.info("Calling reissue()...") address1 = n0.getnewaddress() ipfs_hash2 = "QmcvyefkqQX3PpjpY5L8B2yMd47XrVwAipr6cxUt2zvYU8" n0.reissue(asset_name="MY_ASSET", qty=2000, to_address=address0, change_address=address1, reissuable=False, new_units=-1, new_ipfs=ipfs_hash2) self.log.info("Waiting for ten confirmations after reissue...") self.sync_all() n0.generate(10) self.sync_all() self.log.info("Checkout getassetdata()...") assetdata = n0.getassetdata("MY_ASSET") assert_equal(assetdata["name"], "MY_ASSET") assert_equal(assetdata["amount"], 3000) assert_equal(assetdata["units"], 4) assert_equal(assetdata["reissuable"], 0) assert_equal(assetdata["has_ipfs"], 1) assert_equal(assetdata["ipfs_hash"], ipfs_hash2) self.log.info("Checking listassetbalancesbyaddress()...") assert_equal(n0.listassetbalancesbyaddress(address0)["MY_ASSET"], 2000) self.log.info("Checking listassets()...") n0.issue("RAVEN1", 1000) n0.issue("RAVEN2", 1000) n0.issue("RAVEN3", 1000) n0.generate(1) self.sync_all() n0.listassets(asset="RAVEN*", verbose=False, count=2, start=-2) self.log.info("Creating some sub-assets...") n0.issue(asset_name="MY_ASSET/SUB1", qty=1000, to_address=address0, change_address=address0, units=4, reissuable=True, has_ipfs=True, ipfs_hash=ipfs_hash) self.sync_all() self.log.info("Waiting for ten confirmations after issuesubasset...") n0.generate(10) self.sync_all() self.log.info("Checkout getassetdata()...") assetdata = n0.getassetdata("MY_ASSET/SUB1") assert_equal(assetdata["name"], "MY_ASSET/SUB1") assert_equal(assetdata["amount"], 1000) assert_equal(assetdata["units"], 4) assert_equal(assetdata["reissuable"], 1) assert_equal(assetdata["has_ipfs"], 1) assert_equal(assetdata["ipfs_hash"], ipfs_hash) splendid_assets = n0.listassets(asset="RAVEN*", verbose=False, count=2, start=-2) assert_equal(len(splendid_assets), 2) assert_equal(splendid_assets[0], "RAVEN2") assert_equal(splendid_assets[1], "RAVEN3") self.sync_all()
def ipfs_state(self): self.log.info("Checking ipfs hash state changes...") n0 = self.nodes[0] asset_name1 = "ASSET111" asset_name2 = "ASSET222" address1 = n0.getnewaddress() address2 = n0.getnewaddress() ipfs_hash = "QmcvyefkqQX3PpjpY5L8B2yMd47XrVwAipr6cxUt2zvYU8" bad_hash = "RncvyefkqQX3PpjpY5L8B2yMd47XrVwAipr6cxUt2zvYU8" ######################################## # bad hash (isn't a valid multihash sha2-256) self.log.info("Testing issue asset with invalid IPFS...") try: n0.issue(asset_name=asset_name1, qty=1000, to_address=address1, change_address=address2, units=0, reissuable=True, has_ipfs=True, ipfs_hash=bad_hash) except JSONRPCException as e: if "Invalid IPFS/Txid hash" not in e.error['message']: raise AssertionError("Expected substring not found:" + e.error['message']) except Exception as e: raise AssertionError("Unexpected exception raised: " + type(e).__name__) else: raise AssertionError("No exception raised") ######################################## # no hash self.log.info("Testing issue asset with no IPFS...") n0.issue(asset_name=asset_name2, qty=1000, to_address=address1, change_address=address2, units=0, reissuable=True, has_ipfs=False) n0.generate(1) ad = n0.getassetdata(asset_name2) assert_equal(0, ad['has_ipfs']) assert_does_not_contain_key('ipfs_hash', ad) ######################################## # reissue w/ bad hash self.log.info("Testing re-issue asset with invalid IPFS...") try: n0.reissue(asset_name=asset_name2, qty=2000, to_address=address1, change_address=address2, reissuable=True, new_units=-1, new_ipfs=bad_hash) except JSONRPCException as e: if "Invalid IPFS/Txid hash" not in e.error['message']: raise AssertionError("Expected substring not found:" + e.error['message']) except Exception as e: raise AssertionError("Unexpected exception raised: " + type(e).__name__) else: raise AssertionError("No exception raised") ######################################## # reissue w/ hash self.log.info("Testing re-issue asset with valid IPFS...") n0.reissue(asset_name=asset_name2, qty=2000, to_address=address1, change_address=address2, reissuable=True, new_units=-1, new_ipfs=ipfs_hash) n0.generate(1) ad = n0.getassetdata(asset_name2) assert_equal(1, ad['has_ipfs']) assert_equal(ipfs_hash, ad['ipfs_hash']) ######################################## # invalidate and reconsider best = n0.getbestblockhash() n0.invalidateblock(n0.getbestblockhash()) ad = n0.getassetdata(asset_name2) assert_equal(0, ad['has_ipfs']) assert_does_not_contain_key('ipfs_hash', ad) n0.reconsiderblock(best) ad = n0.getassetdata(asset_name2) assert_equal(1, ad['has_ipfs']) assert_equal(ipfs_hash, ad['ipfs_hash'])
def run_test(self): """Main test logic""" self.log.info("Starting test!") # Split the nodes by name src_node = self.nodes[0] ast1_node = self.nodes[1] ast2_node = self.nodes[2] rvn_node = self.nodes[3] all_node = self.nodes[4] fail_node = self.nodes[5] # Activate assets and prime the src node asset_addr = self.prime_src(src_node) privkey = src_node.dumpprivkey(asset_addr) # Sweep single asset self.log.info("Testing sweeping of a single asset") txid_asset = ast1_node.sweep(privkey=privkey, asset_name="ASSET.2") ast1_node.generate(10) self.sync_all() swept_assets = ast1_node.listmyassets(asset="*", verbose=True) swept_keys = list(swept_assets.keys()) assert_does_not_contain_key("ASSET.1", swept_keys) self.check_asset(swept_assets, "ASSET.2", 2) assert_does_not_contain_key( "ASSET.2", src_node.listmyassets(asset="*", verbose=True).keys()) assert_does_not_contain_key("ASSET.3", swept_keys) assert_does_not_contain_key("ASSET.4", swept_keys) # Sweep a different single asset self.log.info("Testing sweeping of a different single asset") txid_asset = ast2_node.sweep(privkey=privkey, asset_name="ASSET.4") ast2_node.generate(10) self.sync_all() swept_assets = ast2_node.listmyassets(asset="*", verbose=True) swept_keys = list(swept_assets.keys()) assert_does_not_contain_key("ASSET.1", swept_keys) assert_does_not_contain_key("ASSET.2", swept_keys) assert_does_not_contain_key("ASSET.3", swept_keys) self.check_asset(swept_assets, "ASSET.4", 4) assert_does_not_contain_key( "ASSET.4", src_node.listmyassets(asset="*", verbose=True).keys()) # Sweep RVN self.log.info("Testing sweeping of all RVN") txid_rvn = rvn_node.sweep(privkey=privkey, asset_name="RVN") rvn_node.generate(10) self.sync_all() assert (rvn_node.getbalance() > 900) # Sweep remaining assets (fail) self.log.info( "Testing failure of sweeping everything else with insufficient funds" ) assert_raises_rpc_error( -6, f"Please add RVN to address '{asset_addr}' to be able to sweep asset ''", all_node.sweep, privkey) # Fund the all_node so that we can fund the transaction src_node.sendtoaddress(all_node.getnewaddress(), 100) src_node.generate(10) self.sync_all() # Sweep remaining assets (pass) self.log.info("Testing sweeping of everything else") txid_all = all_node.sweep(privkey=privkey) all_node.generate(10) self.sync_all() all_assets = all_node.listmyassets(asset="*", verbose=True) self.check_asset(all_assets, "ASSET.1", 1) assert_does_not_contain_key("ASSET.2", all_assets.keys()) self.check_asset(all_assets, "ASSET.3", 3) assert_does_not_contain_key("ASSET.4", all_assets.keys()) # Fail with no assets to sweep self.log.info("Testing failure of sweeping an address with no assets") assert_raises_rpc_error(-26, "No assets to sweep!", all_node.sweep, privkey)
def reorg_test(self): height = int(self.options.height) peers = self.num_nodes tip_age = int(self.options.tip_age) should_reorg = int(self.options.should_reorg) self.log.info(f"Doing a reorg test with height: {height}, peers: {peers}, tip_age: {tip_age}. " + \ f"Should reorg? *{should_reorg}*") asset_name = "MOON_STONES" adversary = self.nodes[0] subject = self.nodes[-1] # enough to activate assets start = 432 self.log.info(f"Setting all node times to {tip_age} seconds ago...") now = int(round(time.time())) set_node_times(self.nodes, now - tip_age) self.log.info( f"Mining {start} starter blocks on all nodes and syncing...") subject.generate(round(start / 2)) self.sync_all() adversary.generate(round(start / 2)) self.sync_all() self.log.info("Stopping adversary node...") self.stop_node(0) self.log.info(f"Subject is issuing asset: {asset_name}...") subject.issue(asset_name) self.log.info(f"Miners are mining {height} blocks...") subject.generate(height) wait_until(lambda: [n.getblockcount() for n in self.nodes[1:]] == [height + start] * (peers - 1), err_msg="Wait for BlockCount") self.log.info("BlockCount: " + str([start] + [n.getblockcount() for n in self.nodes[1:]])) self.log.info("Restarting adversary node...") self.start_node(0) self.log.info(f"Adversary is issuing asset: {asset_name}...") adversary.issue(asset_name) self.log.info( f"Adversary is mining {height*2} (2 x {height}) blocks over the next ~{tip_age} seconds..." ) interval = round(tip_age / (height * 2)) + 1 for i in range(0, height * 2): set_node_times(self.nodes, (now - tip_age) + ((i + 1) * interval)) adversary.generate(1) assert (adversary.getblockcount() - start == (subject.getblockcount() - start) * 2) besttimes = [ n.getblock(n.getbestblockhash())['time'] for n in self.nodes ] self.log.info("BestTimes: " + str(besttimes)) self.log.info( f"Adversary: {besttimes[0]}; subject: {besttimes[-1]}; difference: {besttimes[0] - besttimes[-1]}; expected gte: {tip_age}" ) assert (besttimes[0] - besttimes[-1] >= tip_age) self.log.info("BlockCount: " + str([n.getblockcount() for n in self.nodes])) self.log.info("Reconnecting the network and syncing the chain...") for i in range(1, peers): connect_nodes_bi(self.nodes, 0, i, should_reorg) expected_height = start + height subject_owns_asset = True if should_reorg > 0: self.log.info( f"Expected a reorg -- blockcount should be {expected_height} and subject should own {asset_name} (waiting 5 seconds)..." ) expected_height += height subject_owns_asset = False else: self.log.info( f"Didn't expect a reorg -- blockcount should remain {expected_height} and both subject and adversary should own {asset_name} (waiting 5 seconds)..." ) # noinspection PyBroadException try: wait_until( lambda: [n.getblockcount() for n in self.nodes] == [expected_height] * peers, timeout=5, err_msg="getblockcount") except: pass self.log.info("BlockCount: " + str([n.getblockcount() for n in self.nodes])) assert_equal(subject.getblockcount(), expected_height) assert_contains_pair(asset_name + '!', 1, adversary.listmyassets()) if subject_owns_asset: assert_contains_pair(asset_name + '!', 1, subject.listmyassets()) else: assert_does_not_contain_key(asset_name + '!', subject.listmyassets())