def _test_getblockheader(self): node = self.nodes[0] assert_raises_jsonrpc(-5, "Block not found", node.getblockheader, "nonsense") besthash = node.getbestblockhash() secondbesthash = node.getblockhash(199) header = node.getblockheader(besthash) assert_equal(header['hash'], besthash) assert_equal(header['height'], 200) assert_equal(header['confirmations'], 1) assert_equal(header['previousblockhash'], secondbesthash) assert_is_hex_string(header['chainwork']) assert_is_hash_string(header['hash']) assert_is_hash_string(header['previousblockhash']) assert_is_hash_string(header['merkleroot']) assert_is_hash_string(header['bits'], length=None) assert isinstance(header['time'], int) assert isinstance(header['mediantime'], int) assert isinstance(header['nonceUint32'], int) assert_is_hash_string(header['nonce'], length=None) assert isinstance(header['version'], int) assert isinstance(int(header['versionHex'], 16), int) assert isinstance(header['difficulty'], Decimal)
def _test_getblockheader(self): node = self.nodes[0] assert_raises_rpc_error(-8, "hash must be of length 64 (not 8, for 'nonsense')", node.getblockheader, "nonsense") assert_raises_rpc_error(-8, "hash must be hexadecimal string (not 'ZZZ7bb8b1697ea987f3b223ba7819250cae33efacb068d23dc24859824a77844')", node.getblockheader, "ZZZ7bb8b1697ea987f3b223ba7819250cae33efacb068d23dc24859824a77844") assert_raises_rpc_error(-5, "Block not found", node.getblockheader, "0cf7bb8b1697ea987f3b223ba7819250cae33efacb068d23dc24859824a77844") besthash = node.getbestblockhash() secondbesthash = node.getblockhash(199) header = node.getblockheader(blockhash=besthash) assert_equal(header['hash'], besthash) assert_equal(header['height'], 200) assert_equal(header['confirmations'], 1) assert_equal(header['previousblockhash'], secondbesthash) assert_is_hex_string(header['chainwork']) assert_equal(header['nTx'], 1) assert_is_hash_string(header['hash']) assert_is_hash_string(header['previousblockhash']) assert_is_hash_string(header['merkleroot']) assert_is_hash_string(header['bits'], length=None) assert isinstance(header['time'], int) assert isinstance(header['mediantime'], int) assert isinstance(header['nonce'], int) assert isinstance(header['version'], int) assert isinstance(int(header['versionHex'], 16), int) assert isinstance(header['difficulty'], Decimal)
def _test_getblockheader(self): node = self.nodes[0] assert_raises( JSONRPCException, lambda: node.getblockheader('nonsense')) besthash = node.getbestblockhash() secondbesthash = node.getblockhash(COINBASE_MATURITY+100-1) header = node.getblockheader(besthash) assert_equal(header['hash'], besthash) assert_equal(header['height'], COINBASE_MATURITY+100) assert_equal(header['confirmations'], 1) assert_equal(header['previousblockhash'], secondbesthash) assert_is_hex_string(header['chainwork']) assert_is_hash_string(header['hash']) assert_is_hash_string(header['previousblockhash']) assert_is_hash_string(header['merkleroot']) assert_is_hash_string(header['bits'], length=None) assert isinstance(header['time'], int) assert isinstance(header['mediantime'], int) assert isinstance(header['nonce'], int) assert isinstance(header['version'], int) assert isinstance(int(header['versionHex'], 16), int) assert isinstance(header['difficulty'], Decimal)
def _test_getblockheader(self): node = self.nodes[0] assert_raises_rpc_error(-5, "Block not found", node.getblockheader, "nonsense") besthash = node.getbestblockhash() secondbesthash = node.getblockhash(199) header = node.getblockheader(besthash) assert_equal(header['hash'], besthash) assert_equal(header['height'], 200) assert_equal(header['confirmations'], 1) assert_equal(header['previousblockhash'], secondbesthash) assert_is_hex_string(header['chainwork']) assert_is_hash_string(header['hash']) assert_is_hash_string(header['previousblockhash']) assert_is_hash_string(header['merkleroot']) assert_is_hash_string(header['bits'], length=None) assert isinstance(header['time'], int) assert isinstance(header['mediantime'], int) assert isinstance(header['nonce'], int) assert isinstance(header['version'], int) assert isinstance(int(header['versionHex'], 16), int) assert isinstance(header['difficulty'], Decimal)
def _test_getblockheader(self): node = self.nodes[0] assert_raises(JSONRPCException, lambda: node.getblockheader('nonsense')) besthash = node.getbestblockhash() secondbesthash = node.getblockhash(199) header = node.getblockheader(besthash) assert_equal(header['hash'], besthash) assert_equal(header['height'], 200) assert_equal(header['confirmations'], 1) assert_equal(header['previousblockhash'], secondbesthash) assert_is_hex_string(header['chainwork']) assert_is_hash_string(header['hash']) assert_is_hash_string(header['previousblockhash']) assert_is_hash_string(header['merkleroot']) assert_is_hash_string(header['bits'], length=None) assert isinstance(header['time'], int) assert isinstance(header['mediantime'], int) assert isinstance(header['nonce'], int) assert isinstance(header['version'], int) assert isinstance(header['difficulty'], Decimal)
def _test_getblockheader(self): node = self.nodes[0] assert_raises_rpc_error( -8, "hash must be of length 64 (not 8, for 'nonsense')", node.getblockheader, "nonsense") assert_raises_rpc_error( -8, "hash must be hexadecimal string (not 'ZZZ7bb8b1697ea987f3b223ba7819250cae33efacb068d23dc24859824a77844')", node.getblockheader, "ZZZ7bb8b1697ea987f3b223ba7819250cae33efacb068d23dc24859824a77844") assert_raises_rpc_error( -5, "Block not found", node.getblockheader, "0cf7bb8b1697ea987f3b223ba7819250cae33efacb068d23dc24859824a77844") besthash = node.getbestblockhash() secondbesthash = node.getblockhash(199) header = node.getblockheader(blockhash=besthash) assert_equal(header['hash'], besthash) assert_equal(header['height'], 200) assert_equal(header['confirmations'], 1) assert_equal(header['previousblockhash'], secondbesthash) assert_is_hex_string(header['chainwork']) assert_equal(header['nTx'], 1) assert_is_hash_string(header['hash']) assert_is_hash_string(header['previousblockhash']) assert_is_hash_string(header['merkleroot']) assert isinstance(header['time'], int) assert isinstance(header['mediantime'], int) assert isinstance(header['version'], int) assert isinstance(int(header['versionHex'], 16), int) # Test with verbose=False, which should return the header as hex. header_hex = node.getblockheader(blockhash=besthash, verbose=False) assert_is_hex_string(header_hex) header = FromHex(CBlockHeader(), header_hex) header.calc_sha256() assert_equal(header.hash, besthash) assert 'previousblockhash' not in node.getblockheader( node.getblockhash(0)) assert 'nextblockhash' not in node.getblockheader( node.getbestblockhash())
def generate_block_with_parent(self, parent_hash: str, referee: list = [], num_txs: int = 0, adaptive: bool = False, difficulty=None, pos_reference=None) -> str: assert_is_hash_string(parent_hash) for r in referee: assert_is_hash_string(r) assert_greater_than_or_equal(num_txs, 0) # print(parent_hash) block_hash = self.node.generatefixedblock(parent_hash, referee, num_txs, adaptive, difficulty, pos_reference) assert_is_hash_string(block_hash) return block_hash
def _test_getblockheader(self): node = self.nodes[0] assert_raises_rpc_error(-5, "Block not found", node.getblockheader, "nonsense") besthash = node.getbestblockhash() secondbesthash = node.getblockhash(99) header = node.getblockheader(besthash) assert_equal(header['hash'], besthash) assert_equal(header['height'], 100) assert_equal(header['confirmations'], 1) assert_equal(header['previousblockhash'], secondbesthash) assert_equal(header['nTx'], 1) assert_is_hash_string(header['hash']) assert_is_hash_string(header['previousblockhash']) assert_is_hash_string(header['merkleroot']) assert isinstance(header['time'], int) assert isinstance(header['mediantime'], int) assert isinstance(header['features'], int) assert isinstance(int(header['featuresHex'], 16), int)
def _test_getblockheader(self): node = self.nodes[0] assert_raises_rpc_error(-8, "hash must be of length 64 (not 8, for 'nonsense')", node.getblockheader, "nonsense") assert_raises_rpc_error(-8, "hash must be hexadecimal string (not 'ZZZ7bb8b1697ea987f3b223ba7819250cae33efacb068d23dc24859824a77844')", node.getblockheader, "ZZZ7bb8b1697ea987f3b223ba7819250cae33efacb068d23dc24859824a77844") assert_raises_rpc_error(-5, "Block not found", node.getblockheader, "0cf7bb8b1697ea987f3b223ba7819250cae33efacb068d23dc24859824a77844") besthash = node.getbestblockhash() secondbesthash = node.getblockhash(199) header = node.getblockheader(blockhash=besthash) assert_equal(header['hash'], besthash) assert_equal(header['height'], 200) assert_equal(header['confirmations'], 1) assert_equal(header['previousblockhash'], secondbesthash) assert_is_hex_string(header['chainwork']) assert_equal(header['nTx'], 1) assert_is_hash_string(header['hash']) assert_is_hash_string(header['previousblockhash']) assert_is_hash_string(header['merkleroot']) assert isinstance(header['time'], int) assert isinstance(header['mediantime'], int) assert isinstance(header['version'], int) assert isinstance(int(header['versionHex'], 16), int)
def generate_block(self, num_txs: int = 0, block_size_limit_bytes: int = default_config["MAX_BLOCK_SIZE_IN_BYTES"]) -> str: assert_greater_than_or_equal(num_txs, 0) block_hash = self.node.generateoneblock(num_txs, block_size_limit_bytes) assert_is_hash_string(block_hash) return block_hash
def run_test(self): self.nodes[0].importaddress(ADDRESS_WATCHONLY) # Check that nodes don't own any UTXOs assert_equal(len(self.nodes[0].listunspent()), 0) assert_equal(len(self.nodes[1].listunspent()), 0) self.log.info("Check that only node 0 is watching an address") assert 'watchonly' in self.nodes[0].getbalances() assert 'watchonly' not in self.nodes[1].getbalances() self.log.info("Mining blocks ...") self.nodes[0].generate(1) self.sync_all() self.nodes[1].generate(1) self.nodes[1].generatetoaddress(101, ADDRESS_WATCHONLY) self.sync_all() assert_equal(self.nodes[0].getbalances()['mine']['trusted'], 50) assert_equal(self.nodes[0].getwalletinfo()['balance'], 50) assert_equal(self.nodes[1].getbalances()['mine']['trusted'], 50) assert_equal(self.nodes[0].getbalances()['watchonly']['immature'], 5000) assert 'watchonly' not in self.nodes[1].getbalances() assert_equal(self.nodes[0].getbalance(), 50) assert_equal(self.nodes[1].getbalance(), 50) self.log.info("Test getbalance with different arguments") assert_equal(self.nodes[0].getbalance("*"), 50) assert_equal(self.nodes[0].getbalance("*", 1), 50) assert_equal(self.nodes[0].getbalance("*", 1, True), 100) assert_raises_rpc_error(-8, "getbalance minconf option is only currently supported if dummy is set to \"*\"", self.nodes[0].getbalance, minconf=1) assert_raises_rpc_error(-8, "getbalance minconf option is only currently supported if dummy is set to \"*\"", self.nodes[0].getbalance, minconf=0, include_watchonly=True) assert_raises_rpc_error(-8, "getbalance minconf option is only currently supported if dummy is set to \"*\"", self.nodes[1].getbalance, minconf=0, include_watchonly=True) # Send 40 BTC from 0 to 1 and 60 BTC from 1 to 0. txs = create_transactions(self.nodes[0], self.nodes[1].getnewaddress(), 40, [Decimal('0.01')]) self.nodes[0].sendrawtransaction(txs[0]['hex']) self.nodes[1].sendrawtransaction(txs[0]['hex']) # sending on both nodes is faster than waiting for propagation self.sync_all() txs = create_transactions(self.nodes[1], self.nodes[0].getnewaddress(), 60, [Decimal('0.01'), Decimal('0.02')]) self.nodes[1].sendrawtransaction(txs[0]['hex']) self.nodes[0].sendrawtransaction(txs[0]['hex']) # sending on both nodes is faster than waiting for propagation self.sync_all() # First argument of getbalance must be set to "*" assert_raises_rpc_error(-32, "dummy first argument must be excluded or set to \"*\"", self.nodes[1].getbalance, "") self.log.info("Test getbalance and getunconfirmedbalance with unconfirmed inputs") # Before `test_balance()`, we have had two nodes with a balance of 50 # each and then we: # # 1) Sent 40 from node A to node B with fee 0.01 # 2) Sent 60 from node B to node A with fee 0.01 # # Then we check the balances: # # 1) As is # 2) With transaction 2 from above with 2x the fee # # Prior to #16766, in this situation, the node would immediately report # a balance of 30 on node B as unconfirmed and trusted. # # After #16766, we show that balance as unconfirmed. # # The balance is indeed "trusted" and "confirmed" insofar as removing # the mempool transactions would return at least that much money. But # the algorithm after #16766 marks it as unconfirmed because the 'taint' # tracking of transaction trust for summing balances doesn't consider # which inputs belong to a user. In this case, the change output in # question could be "destroyed" by replace the 1st transaction above. # # The post #16766 behavior is correct; we shouldn't be treating those # funds as confirmed. If you want to rely on that specific UTXO existing # which has given you that balance, you cannot, as a third party # spending the other input would destroy that unconfirmed. # # For example, if the test transactions were: # # 1) Sent 40 from node A to node B with fee 0.01 # 2) Sent 10 from node B to node A with fee 0.01 # # Then our node would report a confirmed balance of 40 + 50 - 10 = 80 # BTC, which is more than would be available if transaction 1 were # replaced. def test_balances(*, fee_node_1=0): # getbalance without any arguments includes unconfirmed transactions, but not untrusted transactions assert_equal(self.nodes[0].getbalance(), Decimal('9.99')) # change from node 0's send assert_equal(self.nodes[1].getbalance(), Decimal('0')) # node 1's send had an unsafe input # getbalance with '*' and minconf=0 includes unconfirmed transactions, AND untrusted transactions assert_equal(self.nodes[0].getbalance('*', 0), Decimal('69.99')) assert_equal(self.nodes[1].getbalance('*', 0), Decimal('30') - fee_node_1) # getbalance with '*' and minconf=1 includes only confirmed and sent transactions assert_equal(self.nodes[0].getbalance('*', 1), Decimal('9.99')) assert_equal(self.nodes[1].getbalance('*', 1), Decimal('-10') - fee_node_1) # getunconfirmedbalance assert_equal(self.nodes[0].getunconfirmedbalance(), Decimal('60')) # output of node 1's spend assert_equal(self.nodes[0].getbalances()['mine']['untrusted_pending'], Decimal('60')) assert_equal(self.nodes[0].getwalletinfo()["unconfirmed_balance"], Decimal('60')) assert_equal(self.nodes[1].getunconfirmedbalance(), Decimal('30') - fee_node_1) # Doesn't include output of node 0's send since it was spent assert_equal(self.nodes[1].getbalances()['mine']['untrusted_pending'], Decimal('30') - fee_node_1) assert_equal(self.nodes[1].getwalletinfo()["unconfirmed_balance"], Decimal('30') - fee_node_1) test_balances(fee_node_1=Decimal('0.01')) # Node 1 bumps the transaction fee and resends self.nodes[1].sendrawtransaction(txs[1]['hex']) self.nodes[0].sendrawtransaction(txs[1]['hex']) # sending on both nodes is faster than waiting for propagation self.sync_all() self.log.info("Test getbalance and getunconfirmedbalance with conflicted unconfirmed inputs") test_balances(fee_node_1=Decimal('0.02')) self.nodes[1].generatetoaddress(1, ADDRESS_WATCHONLY) self.sync_all() # balances are correct after the transactions are confirmed assert_equal(self.nodes[0].getbalance(), Decimal('69.99')) # node 1's send plus change from node 0's send assert_equal(self.nodes[1].getbalance(), Decimal('29.98')) # change from node 0's send # Send total balance away from node 1 txs = create_transactions(self.nodes[1], self.nodes[0].getnewaddress(), Decimal('29.97'), [Decimal('0.01')]) self.nodes[1].sendrawtransaction(txs[0]['hex']) self.nodes[1].generatetoaddress(2, ADDRESS_WATCHONLY) self.sync_all() # check mempool transactions count for wallet unconfirmed balance after # dynamically loading the wallet. before = self.nodes[1].getunconfirmedbalance() dst = self.nodes[1].getnewaddress() self.nodes[1].unloadwallet('') self.nodes[0].sendtoaddress(dst, 0.1) self.sync_all() self.nodes[1].loadwallet('') after = self.nodes[1].getunconfirmedbalance() assert_equal(before + Decimal('0.1'), after) # Create 3 more wallet txs, where the last is not accepted to the # mempool because it is the third descendant of the tx above for _ in range(3): # Set amount high enough such that all coins are spent by each tx txid = self.nodes[0].sendtoaddress(self.nodes[0].getnewaddress(), 99) self.log.info('Check that wallet txs not in the mempool are untrusted') assert txid not in self.nodes[0].getrawmempool() assert_equal(self.nodes[0].gettransaction(txid)['trusted'], False) assert_equal(self.nodes[0].getbalances()['mine']['trusted'], 0) self.log.info("Test replacement and reorg of non-mempool tx") tx_orig = self.nodes[0].gettransaction(txid)['hex'] # Increase fee by 1 coin tx_replace = tx_orig.replace( struct.pack("<q", 99 * 10**8).hex(), struct.pack("<q", 98 * 10**8).hex(), ) tx_replace = self.nodes[0].signrawtransactionwithwallet(tx_replace)['hex'] # Total balance is given by the sum of outputs of the tx total_amount = sum([o['value'] for o in self.nodes[0].decoderawtransaction(tx_replace)['vout']]) self.sync_all() self.nodes[1].sendrawtransaction(hexstring=tx_replace, maxfeerate=0) # Now confirm tx_replace block_reorg = self.nodes[1].generatetoaddress(1, ADDRESS_WATCHONLY)[0] self.sync_all() assert_equal(self.nodes[0].getbalances()['mine']['trusted'], total_amount) self.log.info('Put txs back into mempool of node 1 (not node 0)') self.nodes[0].invalidateblock(block_reorg) self.nodes[1].invalidateblock(block_reorg) self.sync_blocks() self.nodes[0].syncwithvalidationinterfacequeue() assert_equal(self.nodes[0].getbalances()['mine']['trusted'], 0) # wallet txs not in the mempool are untrusted self.nodes[0].generatetoaddress(1, ADDRESS_WATCHONLY) assert_equal(self.nodes[0].getbalances()['mine']['trusted'], 0) # wallet txs not in the mempool are untrusted # Now confirm tx_orig self.restart_node(1, ['-persistmempool=0']) connect_nodes(self.nodes[0], 1) sync_blocks(self.nodes) self.nodes[1].sendrawtransaction(tx_orig) self.nodes[1].generatetoaddress(1, ADDRESS_WATCHONLY) self.sync_all() assert_equal(self.nodes[0].getbalances()['mine']['trusted'], total_amount + 1) # The reorg recovered our fee of 1 coin #Tests the lastprocessedblock JSON object in getbalances, getwalletinfo #and gettransaction by checking for valid hex strings and by comparing #the hashes & heights between generated blocks. self.log.info("Test getbalances returns expected lastprocessedblock json object") self.nodes[0].generatetoaddress(2, self.nodes[0].get_deterministic_priv_key().address) balances = self.nodes[0].getbalances() assert_greater_than(balances['mine']['immature'], 0) prev_hash = self.nodes[0].getbestblockhash() prev_height = self.nodes[0].getblock(prev_hash)['height'] self.nodes[0].generatetoaddress(5, self.nodes[0].get_deterministic_priv_key().address) lastblock = self.nodes[0].getbalances()['lastprocessedblock'] assert_is_hash_string(lastblock['hash']) assert_equal((prev_hash == lastblock['hash']), False) assert_greater_than(lastblock['height'], prev_height) self.log.info("Test getwalletinfo returns expected lastprocessedblock json object") walletinfo = self.nodes[0].getwalletinfo() assert_greater_than(walletinfo['lastprocessedblock']['height'], 0) assert_is_hash_string(walletinfo['lastprocessedblock']['hash']) self.log.info("Test gettransaction returns expected lastprocessedblock json object") txid = self.nodes[0].sendtoaddress(self.nodes[0].getnewaddress(), 1) self.nodes[0].generatetoaddress(6, self.nodes[0].get_deterministic_priv_key().address) tx_info = self.nodes[0].gettransaction(txid) assert_is_hash_string(tx_info['lastprocessedblock']['hash'])
def ensure_generate_block(node, txs): block_hash = RpcClient(node).generate_block(txs) assert_is_hash_string(block_hash)
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 get_transaction_receipt(self, tx_hash: str) -> dict: assert_is_hash_string(tx_hash) return self.node.cfx_getTransactionReceipt(tx_hash)
def block_hashes_by_epoch(self, epoch: str) -> list: blocks = self.node.cfx_getBlocksByEpoch(epoch) for b in blocks: assert_is_hash_string(b) return blocks
def run_test(self): self.log.info("Running test!") n0, n1, n2 = self.nodes[0], self.nodes[1], self.nodes[2] self.log.info("Generating XSR for node[0] and activating assets...") n0.generate(1) self.sync_all() n2.generate(431) self.sync_all() assert_equal(n0.getbalance(), 5000) self.log.info("Calling issue()...") address0 = n0.getnewaddress() ipfs_hash = "QmacSRmrkVmvJfbCpmU6pK72furJ8E8fbKHindrLxmYMQo" 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("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 for assaddr in n0.listaddressesbyasset("MY_ASSET").keys(): if n0.validateaddress(assaddr)["ismine"] == True: changeaddress = assaddr assert_equal( n0.listassetbalancesbyaddress(changeaddress)["MY_ASSET"], 800) assert (changeaddress != None) assert_equal(n0.listassetbalancesbyaddress(address0)["MY_ASSET!"], 1) self.log.info("Calling reissue()...") n0.reissue(asset_name="MY_ASSET", qty=2000, to_address=address0, change_address="",\ reissuable=False, new_ipfs=ipfs_hash[::-1]) self.log.info("Waiting for ten confirmations after reissue...") 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_hash[::-1]) self.log.info("Checking listassetbalancesbyaddress()...") assert_equal(n0.listassetbalancesbyaddress(address0)["MY_ASSET"], 2000) self.log.info("Checking listassets()...") n0.issue("SUCRECOIN1", 1000) n0.issue("SUCRECOIN2", 1000) n0.issue("SUCRECOIN3", 1000) n0.generate(10) self.sync_all() sucrecoin_assets = n0.listassets(asset="SUCRECOIN*", verbose=False, count=2, start=-2) assert_equal(len(sucrecoin_assets), 2) assert_equal(sucrecoin_assets[0], "SUCRECOIN2") assert_equal(sucrecoin_assets[1], "SUCRECOIN3")
def _test_getblockbyheight(self): node = self.nodes[0] assert_raises_rpc_error(-5, "Block not found", node.getblockheader, "nonsense") besthash = node.getbestblockhash() secondbesthash = node.getblockhash(199) self.log.info("Test getblockbyheight with verbosity=0") blockhex = node.getblockbyheight(1, 0) assert_is_hex_string(blockhex) self.log.info("Test getblockbyheight with verbosity=RAW_BLOCK") blockhex = node.getblockbyheight(1, "RAW_BLOCK") assert_is_hex_string(blockhex) self.log.info("Test getblockbyheight with verbosity=RaW_BlocK") blockhex = node.getblockbyheight(1, "RaW_BlocK") assert_is_hex_string(blockhex) self.log.info("Test getblockbyheight with verbosity=1") blockjson = node.getblockbyheight(200, 1) assert_equal(blockjson['hash'], besthash) assert_equal(blockjson['height'], 200) assert_equal(blockjson['confirmations'], 1) assert_equal(blockjson['previousblockhash'], secondbesthash) assert_is_hex_string(blockjson['chainwork']) assert_is_hash_string(blockjson['hash']) assert_is_hash_string(blockjson['previousblockhash']) assert_is_hash_string(blockjson['merkleroot']) assert_is_hash_string(blockjson['bits'], length=None) assert isinstance(blockjson['time'], int) assert isinstance(blockjson['mediantime'], int) assert isinstance(blockjson['nonce'], int) assert isinstance(blockjson['version'], int) assert isinstance(int(blockjson['versionHex'], 16), int) assert isinstance(blockjson['difficulty'], Decimal) assert isinstance(blockjson['tx'], list) for tx in blockjson['tx']: assert_is_hash_string(tx) self.log.info("Test getblockbyheight with verbosity=DECODE_HEADER") blockjson = node.getblockbyheight(200, "DECODE_HEADER") assert_equal(blockjson['hash'], besthash) for tx in blockjson['tx']: assert_is_hash_string(tx) self.log.info("Test getblockbyheight with verbosity=2") blockjson = node.getblockbyheight(200, 2) assert_equal(blockjson['hash'], besthash) assert_equal(blockjson['height'], 200) assert_equal(blockjson['confirmations'], 1) assert_equal(blockjson['previousblockhash'], secondbesthash) assert_is_hex_string(blockjson['chainwork']) assert_is_hash_string(blockjson['hash']) assert_is_hash_string(blockjson['previousblockhash']) assert_is_hash_string(blockjson['merkleroot']) assert_is_hash_string(blockjson['bits'], length=None) assert isinstance(blockjson['time'], int) assert isinstance(blockjson['mediantime'], int) assert isinstance(blockjson['nonce'], int) assert isinstance(blockjson['version'], int) assert isinstance(int(blockjson['versionHex'], 16), int) assert isinstance(blockjson['difficulty'], Decimal) for tx in blockjson['tx']: assert isinstance(tx, dict) self.log.info( "Test getblockbyheight with verbosity=DECODE_TRANSACTIONS") blockjson = node.getblockbyheight(200, "DECODE_TRANSACTIONS") assert_equal(blockjson['hash'], besthash) for tx in blockjson['tx']: assert isinstance(tx, dict) self.log.info("Test getblockbyheight with verbosity=3") blockjson = node.getblockbyheight(200, 3) assert_equal(blockjson['hash'], besthash) assert_equal(blockjson['height'], 200) assert_equal(blockjson['confirmations'], 1) assert_equal(blockjson['previousblockhash'], secondbesthash) assert_is_hex_string(blockjson['chainwork']) assert_is_hash_string(blockjson['hash']) assert_is_hash_string(blockjson['previousblockhash']) assert_is_hash_string(blockjson['merkleroot']) assert_is_hash_string(blockjson['bits'], length=None) assert isinstance(blockjson['time'], int) assert isinstance(blockjson['mediantime'], int) assert isinstance(blockjson['nonce'], int) assert isinstance(blockjson['version'], int) assert isinstance(int(blockjson['versionHex'], 16), int) assert isinstance(blockjson['difficulty'], Decimal) #only coinbase tx should be in block assert_equal(len(blockjson['tx']), 1) tx = blockjson['tx'][0] assert isinstance(tx, dict) assert_is_hash_string(tx['vin'][0]['coinbase'], length=None) self.log.info( "Test getblockbyheight with verbosity=DECODE_HEADER_AND_COINBASE") blockjson = node.getblockbyheight(200, "DECODE_HEADER_AND_COINBASE") assert_equal(blockjson['hash'], besthash) #only coinbase tx should be in block assert_equal(len(blockjson['tx']), 1) tx = blockjson['tx'][0] assert isinstance(tx, dict) assert_is_hash_string(tx['vin'][0]['coinbase'], length=None) self.log.info("Test getblock with invalid verbosity fails") assert_raises_rpc_error(-8, "Verbosity value out of range", node.getblockbyheight, 200, 4) assert_raises_rpc_error(-8, "Verbosity value out of range", node.getblockbyheight, 200, -1) assert_raises_rpc_error(-8, "Verbosity value not recognized", node.getblockbyheight, 200, "ASDFG") assert_raises_rpc_error(-8, "Block height out of range", node.getblockbyheight, -1) assert_raises_rpc_error(-8, "Block height out of range", node.getblockbyheight, 300)
def send_raw_tx(self, raw_tx: str) -> str: tx_hash = self.node.cfx_sendRawTransaction(raw_tx) assert_is_hash_string(tx_hash) return tx_hash
def get_code(self, address: str, epoch: str) -> str: assert_is_hash_string(address, length=40) code = self.node.cfx_getCode(address, epoch) assert_is_hex_string(code) return code
def generate_block_with_fake_txs(self, txs: list, adaptive=False, tx_data_len: int = 0) -> str: encoded_txs = eth_utils.encode_hex(rlp.encode(txs)) block_hash = self.node.test_generateblockwithfaketxs(encoded_txs, adaptive, tx_data_len) assert_is_hash_string(block_hash) return block_hash
def _test_getblockheader(self): node = self.nodes[0] assert_raises_rpc_error( -8, "hash_or_height must be of length 64 (not 8, for 'nonsense')", node.getblockheader, "nonsense") assert_raises_rpc_error( -8, "hash_or_height must be hexadecimal string (not 'ZZZ7bb8b1697ea987f3b223ba7819250cae33efacb068d23dc24859824a77844')", node.getblockheader, "ZZZ7bb8b1697ea987f3b223ba7819250cae33efacb068d23dc24859824a77844") assert_raises_rpc_error( -5, "Block not found", node.getblockheader, "0cf7bb8b1697ea987f3b223ba7819250cae33efacb068d23dc24859824a77844") assert_raises_rpc_error( -8, "Target block height 201 after current tip 200", node.getblockheader, 201) assert_raises_rpc_error(-8, "Target block height -10 is negative", node.getblockheader, -10) besthash = node.getbestblockhash() secondbesthash = node.getblockhash(199) header = node.getblockheader(hash_or_height=besthash) assert_equal(header['hash'], besthash) assert_equal(header['height'], 200) assert_equal(header['confirmations'], 1) assert_equal(header['previousblockhash'], secondbesthash) assert_is_hex_string(header['chainwork']) assert_equal(header['nTx'], 1) assert_is_hash_string(header['hash']) assert_is_hash_string(header['previousblockhash']) assert_is_hash_string(header['merkleroot']) assert_is_hash_string(header['bits'], length=None) assert isinstance(header['time'], int) assert isinstance(header['mediantime'], int) assert isinstance(header['nonce'], int) assert isinstance(header['version'], int) assert isinstance(int(header['versionHex'], 16), int) assert isinstance(header['difficulty'], Decimal) header_by_height = node.getblockheader(hash_or_height=200) assert_equal(header, header_by_height) # Next, check that the old alias 'blockhash' still works # and is interchangeable with hash_or_height # First, make sure errors work as expected for unknown named params self.log.info( "Testing that getblockheader(blockhashhh=\"HEX\") produces the proper error" ) assert_raises_rpc_error(-8, "Unknown named parameter blockhashhh", node.getblockheader, blockhashhh=header['hash']) # Next, actually try the old legacy blockhash="xx" style arg self.log.info( "Testing that legacy getblockheader(blockhash=\"HEX\") still works ok" ) header_by_hash2 = node.getblockheader(blockhash=header['hash']) assert_equal(header, header_by_hash2) header_by_height2 = node.getblockheader(blockhash=200) assert_equal(header, header_by_height2) # check that we actually get a hex string back from getblockheader # if verbose is set to false. header_verbose_false = node.getblockheader(200, False) assert not isinstance(header_verbose_false, dict) assert isinstance(header_verbose_false, str) assert (c in string.hexdigits for c in header_verbose_false) assert_is_hex_string(header_verbose_false) # check that header_verbose_false is the same header we get via # getblockheader(hash_or_height=besthash) just in a different "form" h = CBlockHeader() h.deserialize(BytesIO(hex_str_to_bytes(header_verbose_false))) h.calc_sha256() assert_equal(header['version'], h.nVersion) assert_equal(header['time'], h.nTime) assert_equal(header['previousblockhash'], "{:064x}".format(h.hashPrevBlock)) assert_equal(header['merkleroot'], "{:064x}".format(h.hashMerkleRoot)) assert_equal(header['hash'], h.hash) # check that we get the same header by hash and by height in # the case verbose is set to False header_verbose_false_by_hash = node.getblockheader(besthash, False) assert_equal(header_verbose_false_by_hash, header_verbose_false)
def generate_block(self, num_txs: int = 0) -> str: assert_greater_than_or_equal(num_txs, 0) block_hash = self.node.generateoneblock(num_txs) assert_is_hash_string(block_hash) return block_hash
def _test_getblockheader(self): node = self.nodes[0] assert_raises_rpc_error( -8, "hash_or_height must be of length 64 (not 8, for 'nonsense')", node.getblockheader, "nonsense") assert_raises_rpc_error( -8, "hash_or_height must be hexadecimal string (not 'ZZZ7bb8b1697ea987f3b223ba7819250cae33efacb068d23dc24859824a77844')", node.getblockheader, "ZZZ7bb8b1697ea987f3b223ba7819250cae33efacb068d23dc24859824a77844") assert_raises_rpc_error( -5, "Block not found", node.getblockheader, "0cf7bb8b1697ea987f3b223ba7819250cae33efacb068d23dc24859824a77844") assert_raises_rpc_error( -8, "Target block height 201 after current tip 200", node.getblockheader, 201) assert_raises_rpc_error(-8, "Target block height -10 is negative", node.getblockheader, -10) besthash = node.getbestblockhash() secondbesthash = node.getblockhash(199) header = node.getblockheader(hash_or_height=besthash) assert_equal(header['hash'], besthash) assert_equal(header['height'], 200) assert_equal(header['confirmations'], 1) assert_equal(header['previousblockhash'], secondbesthash) assert_is_hex_string(header['chainwork']) assert_equal(header['nTx'], 1) assert_is_hash_string(header['hash']) assert_is_hash_string(header['previousblockhash']) assert_is_hash_string(header['merkleroot']) assert_is_hash_string(header['bits'], length=None) assert isinstance(header['time'], int) assert isinstance(header['mediantime'], int) assert isinstance(header['nonce'], int) assert isinstance(header['version'], int) assert isinstance(int(header['versionHex'], 16), int) assert isinstance(header['difficulty'], Decimal) header_by_height = node.getblockheader(hash_or_height=200) assert_equal(header, header_by_height) # check that we actually get a hex string back from getblockheader # if verbose is set to false. header_verbose_false = node.getblockheader(200, False) assert not isinstance(header_verbose_false, dict) assert isinstance(header_verbose_false, str) assert (c in string.hexdigits for c in header_verbose_false) assert_is_hex_string(header_verbose_false) # check that header_verbose_false is the same header we get via # getblockheader(hash_or_height=besthash) just in a different "form" h = CBlockHeader() h.deserialize(BytesIO(hex_str_to_bytes(header_verbose_false))) h.calc_sha256() assert_equal(header['version'], h.nVersion) assert_equal(header['time'], h.nTime) assert_equal(header['previousblockhash'], "{:064x}".format(h.hashPrevBlock)) assert_equal(header['merkleroot'], "{:064x}".format(h.hashMerkleRoot)) assert_equal(header['hash'], h.hash) # check that we get the same header by hash and by height in # the case verbose is set to False header_verbose_false_by_hash = node.getblockheader(besthash, False) assert_equal(header_verbose_false_by_hash, header_verbose_false)