def check_get_bulk_payments(self): print('Checking get_bulk_payments') daemon = Daemon() res = daemon.get_info() height = res.height self.wallet[0].refresh() res = self.wallet[0].get_bulk_payments() assert len(res.payments) >= 83 # at least 83 coinbases res = self.wallet[0].get_bulk_payments(payment_ids = ['1234500000012345abcde00000abcdeff1234500000012345abcde00000abcde']) assert 'payments' not in res or len(res.payments) == 0 res = self.wallet[0].get_bulk_payments(min_block_height = height) assert 'payments' not in res or len(res.payments) == 0 res = self.wallet[0].get_bulk_payments(min_block_height = height - 40) assert len(res.payments) >= 39 # coinbases self.wallet[1].refresh() res = self.wallet[1].get_bulk_payments() assert len(res.payments) >= 3 # two txes to standard address were sent, plus one to integrated address res = self.wallet[1].get_bulk_payments(payment_ids = ['1234500000012345abcde00000abcdeff1234500000012345abcde00000abcde']) assert len(res.payments) >= 2 # two txes were sent with that payment id res = self.wallet[1].get_bulk_payments(payment_ids = ['ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff']) assert 'payments' not in res or len(res.payments) == 0 # none with that payment id res = self.wallet[1].get_bulk_payments(payment_ids = ['1111111122222222' + '0'*48]) assert len(res.payments) >= 1 # one tx to integrated address self.wallet[2].refresh() res = self.wallet[2].get_bulk_payments() assert len(res.payments) >= 1 # one tx was sent res = self.wallet[2].get_bulk_payments(payment_ids = ['1'*64, '1234500000012345abcde00000abcdeff1234500000012345abcde00000abcde', '2'*64]) assert len(res.payments) >= 1 # one tx was sent
def mine(self): print("Mining some blocks") daemon = Daemon() wallet = Wallet() daemon.generateblocks('42ey1afDFnn4886T7196doS9GPMzexD9gXpsZJDwVjeRVdFCSoHnv7KPbBeGpzJBzHRCAs9UxqeoyFQMYbqSWYTfJJQAWDm', 80) wallet.refresh()
def _test_get_info(self): print('Test get_info') daemon = Daemon() res = daemon.get_info() # difficulty should be set to 1 for this test assert 'difficulty' in res.keys() assert res.difficulty == 1; # nettype should not be TESTNET assert 'testnet' in res.keys() assert res.testnet == False; # nettype should not be STAGENET assert 'stagenet' in res.keys() assert res.stagenet == False; # nettype should be FAKECHAIN assert 'nettype' in res.keys() assert res.nettype == "fakechain"; # free_space should be > 0 assert 'free_space' in res.keys() assert res.free_space > 0 # height should be greater or equal to 1 assert 'height' in res.keys() assert res.height >= 1
def check_double_spend_detection(self): print('Checking double spend detection') txes = [[None, None], [None, None]] for i in range(2): self.wallet[0].restore_deterministic_wallet(seed = 'velvet lymph giddy number token physics poetry unquoted nibs useful sabotage limits benches lifestyle eden nitrogen anvil fewest avoid batch vials washing fences goat unquoted') self.wallet[0].refresh() res = self.wallet[0].get_balance() unlocked_balance = res.unlocked_balance res = self.wallet[0].sweep_all(address = '44Kbx4sJ7JDRDV5aAhLJzQCjDz2ViLRduE3ijDZu3osWKBjMGkV1XPk4pfDUMqt1Aiezvephdqm6YD19GKFD9ZcXVUTp6BW', do_not_relay = True, get_tx_hex = True) assert len(res.tx_hash_list) == 1 assert len(res.tx_hash_list[0]) == 32*2 txes[i][0] = res.tx_hash_list[0] assert len(res.fee_list) == 1 assert res.fee_list[0] > 0 assert len(res.amount_list) == 1 assert res.amount_list[0] == unlocked_balance - res.fee_list[0] assert len(res.tx_blob_list) > 0 assert len(res.tx_blob_list[0]) > 0 assert not 'tx_metadata_list' in res or len(res.tx_metadata_list) == 0 assert not 'multisig_txset' in res or len(res.multisig_txset) == 0 assert not 'unsigned_txset' in res or len(res.unsigned_txset) == 0 assert len(res.tx_blob_list) == 1 txes[i][1] = res.tx_blob_list[0] daemon = Daemon() res = daemon.send_raw_transaction(txes[0][1]) assert res.not_relayed == False assert res.low_mixin == False assert res.double_spend == False assert res.invalid_input == False assert res.invalid_output == False assert res.too_big == False assert res.overspend == False assert res.fee_too_low == False assert res.not_rct == False res = daemon.get_transactions([txes[0][0]]) assert len(res.txs) >= 1 tx = [tx for tx in res.txs if tx.tx_hash == txes[0][0]][0] assert tx.in_pool assert not tx.double_spend_seen res = daemon.send_raw_transaction(txes[1][1]) assert res.not_relayed == False assert res.low_mixin == False assert res.double_spend == True assert res.invalid_input == False assert res.invalid_output == False assert res.too_big == False assert res.overspend == False assert res.fee_too_low == False assert res.not_rct == False res = daemon.get_transactions([txes[0][0]]) assert len(res.txs) >= 1 tx = [tx for tx in res.txs if tx.tx_hash == txes[0][0]][0] assert tx.in_pool assert tx.double_spend_seen
def transfer(self): print('Creating transaction') self.wallet[0].refresh() dst = {'address': '44Kbx4sJ7JDRDV5aAhLJzQCjDz2ViLRduE3ijDZu3osWKBjMGkV1XPk4pfDUMqt1Aiezvephdqm6YD19GKFD9ZcXVUTp6BW', 'amount':123456789000} res = self.wallet[0].transfer([dst], get_tx_key = True) assert len(res.tx_hash) == 64 assert len(res.tx_key) == 64 daemon = Daemon() daemon.generateblocks('42ey1afDFnn4886T7196doS9GPMzexD9gXpsZJDwVjeRVdFCSoHnv7KPbBeGpzJBzHRCAs9UxqeoyFQMYbqSWYTfJJQAWDm', 1) return (res.tx_hash, res.tx_key, 123456789000)
def _test_hardfork_info(self): print('Test hard_fork_info') daemon = Daemon() res = daemon.hard_fork_info() # hard_fork version should be set at height 1 assert 'earliest_height' in res.keys() #assert res['earliest_height'] == 1; assert res.earliest_height == 1
def mine(self): print("Mining some blocks") daemon = Daemon() res = daemon.get_info() height = res.height daemon.generateblocks('42ey1afDFnn4886T7196doS9GPMzexD9gXpsZJDwVjeRVdFCSoHnv7KPbBeGpzJBzHRCAs9UxqeoyFQMYbqSWYTfJJQAWDm', 80) for i in range(len(self.wallet)): self.wallet[i].refresh() res = self.wallet[i].get_height() assert res.height == height + 80
def create_txes(self, address, ntxes): print('Creating ' + str(ntxes) + ' transactions') daemon = Daemon() wallet = Wallet() dst = {'address': address, 'amount': 1000000000000} txes = {} for i in range(ntxes): res = wallet.transfer([dst], get_tx_hex=True) txes[res.tx_hash] = res return txes
def check_spend_proof(self, txid): daemon = Daemon() print('Checking spend proof') self.wallet[0].refresh() self.wallet[1].refresh() res = self.wallet[0].get_spend_proof(txid, message='foo') assert len(res.signature) > 0 signature = res.signature res = self.wallet[1].check_spend_proof(txid, message='foo', signature=signature) assert res.good res = self.wallet[0].get_spend_proof(txid, message='foobar') assert len(res.signature) > 0 signature2 = res.signature res = self.wallet[1].check_spend_proof(txid, message='foobar', signature=signature2) assert res.good ok = False try: res = self.wallet[1].check_spend_proof('0' * 64, message='foo', signature=signature) except: ok = True assert ok or not res.good ok = False try: res = self.wallet[1].check_spend_proof(txid, message='bar', signature=signature) except: ok = True assert ok or not res.good ok = False try: res = self.wallet[1].check_spend_proof(txid, message='foo', signature=signature2) except: ok = True assert ok or not res.good
def test_p2p_tx_propagation(self): print('Testing P2P tx propagation') daemon2 = Daemon(idx = 2) daemon3 = Daemon(idx = 3) for daemon in [daemon2, daemon3]: res = daemon.get_transaction_pool_hashes() assert not 'tx_hashes' in res or len(res.tx_hashes) == 0 self.wallet.refresh() res = self.wallet.get_balance() dst = {'address': '42ey1afDFnn4886T7196doS9GPMzexD9gXpsZJDwVjeRVdFCSoHnv7KPbBeGpzJBzHRCAs9UxqeoyFQMYbqSWYTfJJQAWDm', 'amount': 1000000000000} res = self.wallet.transfer([dst]) assert len(res.tx_hash) == 32*2 txid = res.tx_hash time.sleep(5) for daemon in [daemon2, daemon3]: res = daemon.get_transaction_pool_hashes() assert len(res.tx_hashes) == 1 assert res.tx_hashes[0] == txid
def sweep_single(self): daemon = Daemon() print("Sending single output") daemon.generateblocks('42ey1afDFnn4886T7196doS9GPMzexD9gXpsZJDwVjeRVdFCSoHnv7KPbBeGpzJBzHRCAs9UxqeoyFQMYbqSWYTfJJQAWDm', 1) self.wallet[0].refresh() res = self.wallet[0].incoming_transfers(transfer_type = 'available') for t in res.transfers: assert not t.spent assert len(res.transfers) > 8 # we mined a lot index = 8 assert not res.transfers[index].spent assert res.transfers[index].amount > 0 ki = res.transfers[index].key_image amount = res.transfers[index].amount daemon.generateblocks('42ey1afDFnn4886T7196doS9GPMzexD9gXpsZJDwVjeRVdFCSoHnv7KPbBeGpzJBzHRCAs9UxqeoyFQMYbqSWYTfJJQAWDm', 10) # ensure unlocked self.wallet[0].refresh() res = self.wallet[0].get_balance() balance = res.balance res = self.wallet[0].incoming_transfers(transfer_type = 'all') res = self.wallet[0].sweep_single('44Kbx4sJ7JDRDV5aAhLJzQCjDz2ViLRduE3ijDZu3osWKBjMGkV1XPk4pfDUMqt1Aiezvephdqm6YD19GKFD9ZcXVUTp6BW', key_image = ki) assert len(res.tx_hash) == 64 tx_hash = res.tx_hash daemon.generateblocks('44Kbx4sJ7JDRDV5aAhLJzQCjDz2ViLRduE3ijDZu3osWKBjMGkV1XPk4pfDUMqt1Aiezvephdqm6YD19GKFD9ZcXVUTp6BW', 1) self.wallet[0].refresh() res = self.wallet[0].get_balance() new_balance = res.balance res = daemon.get_transactions([tx_hash], decode_as_json = True) assert len(res.txs) == 1 tx = res.txs[0] assert tx.tx_hash == tx_hash assert not tx.in_pool assert len(tx.as_json) > 0 try: j = json.loads(tx.as_json) except: j = None assert j assert new_balance == balance - amount assert len(j['vin']) == 1 assert j['vin'][0]['key']['k_image'] == ki self.wallet[0].refresh() res = self.wallet[0].incoming_transfers(transfer_type = 'available') assert len([t for t in res.transfers if t.key_image == ki]) == 0 res = self.wallet[0].incoming_transfers(transfer_type = 'unavailable') assert len([t for t in res.transfers if t.key_image == ki]) == 1
def check_double_spend_detection(self): print('Checking double spend detection') txes = [[None, None], [None, None]] for i in range(2): self.wallet[0].restore_deterministic_wallet(seed = 'velvet lymph giddy number token physics poetry unquoted nibs useful sabotage limits benches lifestyle eden nitrogen anvil fewest avoid batch vials washing fences goat unquoted') self.wallet[0].refresh() res = self.wallet[0].get_balance() unlocked_balance = res.unlocked_balance res = self.wallet[0].sweep_all(address = '44Kbx4sJ7JDRDV5aAhLJzQCjDz2ViLRduE3ijDZu3osWKBjMGkV1XPk4pfDUMqt1Aiezvephdqm6YD19GKFD9ZcXVUTp6BW', do_not_relay = True, get_tx_hex = True) assert len(res.tx_hash_list) == 1 assert len(res.tx_hash_list[0]) == 32*2 txes[i][0] = res.tx_hash_list[0] assert len(res.fee_list) == 1 assert res.fee_list[0] > 0 assert len(res.amount_list) == 1 assert res.amount_list[0] == unlocked_balance - res.fee_list[0] assert len(res.tx_blob_list) > 0 assert len(res.tx_blob_list[0]) > 0 assert not 'tx_metadata_list' in res or len(res.tx_metadata_list) == 0 assert not 'multisig_txset' in res or len(res.multisig_txset) == 0 assert not 'unsigned_txset' in res or len(res.unsigned_txset) == 0 assert len(res.tx_blob_list) == 1 txes[i][1] = res.tx_blob_list[0] daemon = Daemon() res = daemon.send_raw_transaction(txes[0][1]) assert res.not_relayed == False assert res.low_mixin == False assert res.double_spend == False assert res.invalid_input == False assert res.invalid_output == False assert res.too_big == False assert res.overspend == False assert res.fee_too_low == False res = daemon.get_transactions([txes[0][0]]) assert len(res.txs) >= 1 tx = [tx for tx in res.txs if tx.tx_hash == txes[0][0]][0] assert tx.in_pool assert not tx.double_spend_seen res = daemon.send_raw_transaction(txes[1][1]) assert res.not_relayed == False assert res.low_mixin == False assert res.double_spend == True assert res.invalid_input == False assert res.invalid_output == False assert res.too_big == False assert res.overspend == False assert res.fee_too_low == False assert res.too_few_outputs == False res = daemon.get_transactions([txes[0][0]]) assert len(res.txs) >= 1 tx = [tx for tx in res.txs if tx.tx_hash == txes[0][0]][0] assert tx.in_pool assert tx.double_spend_seen
def run_test(self): daemon = Daemon() wallet = Wallet() destinations = wallet.make_uniform_destinations( '44AFFq5kSiGBoZ4NMDwYtN18obc8AemS33DBLWs3H7otXft3XjrpDtQGv7SqSsaBYBb98uNbr2VBBEt7f2wfn3RVGQBEP3A', 1, 3) self._test_speed_generateblocks(daemon=daemon, blocks=70) for i in range(1, 10): while wallet.get_balance().unlocked_balance == 0: print('Waiting for wallet to refresh...') sleep(1) self._test_speed_transfer_split(wallet=wallet) self._test_speed_generateblocks(daemon=daemon, blocks=10)
def check_tx_notes(self): daemon = Daemon() print('Testing tx notes') res = self.wallet[0].get_transfers() assert len(res['in']) > 0 in_txid = res['in'][0].txid assert len(res['out']) > 0 out_txid = res['out'][0].txid res = self.wallet[0].get_tx_notes([in_txid, out_txid]) assert res.notes == ['', ''] res = self.wallet[0].set_tx_notes([in_txid, out_txid], ['in txid', 'out txid']) res = self.wallet[0].get_tx_notes([in_txid, out_txid]) assert res.notes == ['in txid', 'out txid'] res = self.wallet[0].get_tx_notes([out_txid, in_txid]) assert res.notes == ['out txid', 'in txid']
def check_tx_key(self, txid, tx_key, amount): daemon = Daemon() print('Checking tx key') self.wallet[0].refresh() self.wallet[1].refresh() sending_address = '42ey1afDFnn4886T7196doS9GPMzexD9gXpsZJDwVjeRVdFCSoHnv7KPbBeGpzJBzHRCAs9UxqeoyFQMYbqSWYTfJJQAWDm' receiving_address = '44Kbx4sJ7JDRDV5aAhLJzQCjDz2ViLRduE3ijDZu3osWKBjMGkV1XPk4pfDUMqt1Aiezvephdqm6YD19GKFD9ZcXVUTp6BW' res = self.wallet[0].get_tx_key(txid) assert res.tx_key == tx_key res = self.wallet[0].check_tx_key(txid=txid, tx_key=tx_key, address=receiving_address) assert res.received == amount assert not res.in_pool assert res.confirmations == 1 res = self.wallet[1].check_tx_key(txid=txid, tx_key=tx_key, address=receiving_address) assert res.received == amount assert not res.in_pool assert res.confirmations == 1 self.wallet[1].check_tx_key(txid=txid, tx_key=tx_key, address=sending_address) assert res.received >= 0 # might be change assert not res.in_pool assert res.confirmations == 1 ok = False try: self.wallet[1].check_tx_key(txid='0' * 64, tx_key=tx_key, address=receiving_address) except: ok = True assert ok res = self.wallet[1].check_tx_key(txid=txid, tx_key='0' * 64, address=receiving_address) assert res.received == 0 assert not res.in_pool assert res.confirmations == 1
def check_rescan(self): daemon = Daemon(idx=2) print('Testing rescan_spent') res = self.wallet[0].incoming_transfers(transfer_type='all') transfers = res.transfers res = self.wallet[0].rescan_spent() res = self.wallet[0].incoming_transfers(transfer_type='all') assert transfers == res.transfers for hard in [False, True]: print('Testing %s rescan_blockchain' % ('hard' if hard else 'soft')) res = self.wallet[0].incoming_transfers(transfer_type='all') transfers = res.transfers res = self.wallet[0].get_transfers() t_in = res['in'] t_out = res.out res = self.wallet[0].rescan_blockchain(hard=hard) res = self.wallet[0].incoming_transfers(transfer_type='all') assert transfers == res.transfers res = self.wallet[0].get_transfers() assert t_in == res['in'] # some information can not be recovered for out txes unrecoverable_fields = ['payment_id', 'destinations', 'note'] old_t_out = [] for x in t_out: e = {} for k in x.keys(): if not k in unrecoverable_fields: e[k] = x[k] old_t_out.append(e) new_t_out = [] for x in res.out: e = {} for k in x.keys(): if not k in unrecoverable_fields: e[k] = x[k] new_t_out.append(e) assert sorted(old_t_out, key=lambda k: k['txid']) == sorted( new_t_out, key=lambda k: k['txid'])
def run_test(self): self.reset() daemon = Daemon() wallet = Wallet() # close the wallet if any, will throw if none is loaded try: wallet.close_wallet() except: pass wallet.restore_deterministic_wallet('velvet lymph giddy number token physics poetry unquoted nibs useful sabotage limits benches lifestyle eden nitrogen anvil fewest avoid batch vials washing fences goat unquoted') destinations = [] for i in range(3): destinations.append({"amount":1,"address":'44AFFq5kSiGBoZ4NMDwYtN18obc8AemS33DBLWs3H7otXft3XjrpDtQGv7SqSsaBYBb98uNbr2VBBEt7f2wfn3RVGQBEP3A'}) self._test_speed_generateblocks(daemon=daemon, blocks=70) for i in range(1, 10): while wallet.get_balance().unlocked_balance == 0: print('Waiting for wallet to refresh...') sleep(1) self._test_speed_transfer_split(wallet=wallet) self._test_speed_generateblocks(daemon=daemon, blocks=10)
def test_access_mining(self): print('Testing access mining') daemon = Daemon(idx=1) wallet = Wallet(idx=3) res = daemon.rpc_access_info(client=self.get_signature()) assert len(res.hashing_blob) > 39 assert res.height == 1 assert res.top_hash == '418015bb9ae982a1975da7d79277c2705727a56894ba0fb246adaabb1f4632e3' assert res.credits_per_hash_found == 5000 assert res.diff == 10 assert res.credits == 0 cookie = res.cookie # Try random nonces till we find one that's valid and one that's invalid nonce = 0 found_valid = 0 found_invalid = 0 last_credits = 0 loop_time = time.time() while found_valid == 0 or found_invalid == 0: nonce += 1 try: res = daemon.rpc_access_submit_nonce( nonce=nonce, cookie=cookie, client=self.get_signature()) found_valid += 1 assert res.credits == last_credits + 5000 except Exception as e: found_invalid += 1 res = daemon.rpc_access_info(client=self.get_signature()) cookie = res.cookie loop_time = time.time() assert res.credits < last_credits or res.credits == 0 assert nonce < 1000 # can't find both valid and invalid -> the RPC probably fails last_credits = res.credits if time.time() >= loop_time + 10: res = daemon.rpc_access_info(client=self.get_signature()) cookie = res.cookie loop_time = time.time() # we should now have 1 valid nonce, and a number of bad ones res = daemon.rpc_access_info(client=self.get_signature()) assert len(res.hashing_blob) > 39 assert res.height > 1 assert res.top_hash != '418015bb9ae982a1975da7d79277c2705727a56894ba0fb246adaabb1f4632e3' # here, any share matches network diff assert res.credits_per_hash_found == 5000 assert res.diff == 10 cookie = res.cookie res = daemon.rpc_access_data() assert len(res.entries) > 0 e = [x for x in res.entries if x['client'] == self.public_key] assert len(e) == 1 e = e[0] assert e.nonces_stale == 0 assert e.nonces_bad == found_invalid assert e.nonces_good == found_valid assert e.nonces_dupe == 0 # Try random nonces till we find one that's valid so we get a load of credits loop_time = time.time() while last_credits == 0: nonce += 1 try: res = daemon.rpc_access_submit_nonce( nonce=nonce, cookie=cookie, client=self.get_signature()) found_valid += 1 last_credits = res.credits break except: found_invalid += 1 assert nonce < 1000 # can't find a valid none -> the RPC probably fails if time.time() >= loop_time + 10: res = daemon.rpc_access_info(client=self.get_signature()) cookie = res.cookie loop_time = time.time() # we should now have at least 5000 res = daemon.rpc_access_info(client=self.get_signature()) assert res.credits == last_credits assert res.credits >= 5000 # last one was a valid nonce res = daemon.rpc_access_data() assert len(res.entries) > 0 e = [x for x in res.entries if x['client'] == self.public_key] assert len(e) == 1 e = e[0] assert e.nonces_stale == 0 assert e.nonces_bad == found_invalid assert e.nonces_good == found_valid assert e.nonces_dupe == 0 assert e.balance == 5000 assert e.credits_total >= 5000 # find a valid one, then check dupes aren't allowed res = daemon.rpc_access_info(client=self.get_signature()) cookie = res.cookie old_cookie = cookie # we keep that so can submit a stale later loop_time = time.time() while True: nonce += 1 try: res = daemon.rpc_access_submit_nonce( nonce=nonce, cookie=cookie, client=self.get_signature()) found_valid += 1 break except: found_invalid += 1 assert nonce < 1000 # can't find both valid and invalid -> the RPC probably fails if time.time() >= loop_time + 10: res = daemon.rpc_access_info(client=self.get_signature()) cookie = res.cookie loop_time = time.time() res = daemon.rpc_access_data() assert len(res.entries) > 0 e = [x for x in res.entries if x['client'] == self.public_key] assert len(e) == 1 e = e[0] assert e.nonces_stale == 0 assert e.nonces_bad == found_invalid assert e.nonces_good == found_valid assert e.nonces_dupe == 0 ok = False try: res = daemon.rpc_access_submit_nonce(nonce=nonce, cookie=cookie, client=self.get_signature()) except: ok = True assert ok res = daemon.rpc_access_data() assert len(res.entries) > 0 e = [x for x in res.entries if x['client'] == self.public_key] assert len(e) == 1 e = e[0] assert e.nonces_stale == 0 assert e.nonces_bad == found_invalid assert e.nonces_good == found_valid assert e.nonces_dupe == 1 # find stales without updating cookie, one within 5 seconds (accepted), one later (rejected) res = daemon.rpc_access_info(client=self.get_signature()) cookie = res.cookie # let the daemon update its timestamp, but use old cookie found_close_stale = 0 found_late_stale = 0 loop_time = time.time() while found_close_stale == 0 or found_late_stale == 0: nonce += 1 try: res = daemon.rpc_access_submit_nonce( nonce=nonce, cookie=cookie, client=self.get_signature()) found_close_stale += 1 found_valid += 1 time.sleep( 15 ) # now we've got an early stale, wait till they become late stales except Exception as e: #if e[0]['error']['code'] == -18: # stale if "'code': -18" in str( e ): # stale (ugly version, but also works with python 3) found_late_stale += 1 else: found_invalid += 1 assert nonce < 1000 # can't find both valid and invalid -> the RPC probably fails if time.time() >= loop_time + 10: res = daemon.rpc_access_info(client=self.get_signature()) # cookie = res.cookie # let the daemon update its timestamp, but use old cookie loop_time = time.time() res = daemon.rpc_access_data() assert len(res.entries) > 0 e = [x for x in res.entries if x['client'] == self.public_key] assert len(e) == 1 e = e[0] assert e.nonces_stale == found_late_stale # close stales are accepted, don't count here assert e.nonces_bad == found_invalid assert e.nonces_good == found_valid assert e.nonces_dupe == 1 # find very stale with old cookie (rejected) res = daemon.rpc_access_info(client=self.get_signature()) nonce += 1 ok = False try: res = daemon.rpc_access_submit_nonce(nonce=nonce, cookie=old_cookie, client=self.get_signature()) except: found_late_stale += 1 ok = True assert ok res = daemon.rpc_access_data() assert len(res.entries) > 0 e = [x for x in res.entries if x['client'] == self.public_key] assert len(e) == 1 e = e[0] assert e.nonces_stale == found_late_stale assert e.nonces_bad == found_invalid assert e.nonces_good == found_valid assert e.nonces_dupe == 1
def mine(self, via_daemon): print("Test mining via " + ("daemon" if via_daemon else "wallet")) cores_init = multiprocessing.cpu_count() # RX init uses all cores cores_mine = 1 # Mining uses a parametric number of cores is_mining_measurent = 'MINING_NO_MEASUREMENT' not in os.environ if is_mining_measurent: # A dynamic calculation of the CPU power requested time_pi_single_cpu = self.measure_cpu_power_get_time(cores_mine) time_pi_all_cores = self.measure_cpu_power_get_time(cores_init) # This is the last measurement, since it takes very little time and can be placed timewise-closer to the mining itself. available_ram = self.get_available_ram( ) # So far no ideas how to use this var, other than printing it start = monotonic.monotonic() daemon = Daemon() wallet = Wallet() # check info/height/balance before generating blocks res_info = daemon.get_info() initial_height = res_info.height res_getbalance = wallet.get_balance() prev_balance = res_getbalance.balance res_status = daemon.mining_status() if via_daemon: res = daemon.start_mining( '42ey1afDFnn4886T7196doS9GPMzexD9gXpsZJDwVjeRVdFCSoHnv7KPbBeGpzJBzHRCAs9UxqeoyFQMYbqSWYTfJJQAWDm', threads_count=1) else: res = wallet.start_mining(threads_count=cores_mine) res_status = daemon.mining_status() assert res_status.active == True assert res_status.threads_count == cores_mine assert res_status.address == '42ey1afDFnn4886T7196doS9GPMzexD9gXpsZJDwVjeRVdFCSoHnv7KPbBeGpzJBzHRCAs9UxqeoyFQMYbqSWYTfJJQAWDm' assert res_status.is_background_mining_enabled == False assert res_status.block_reward >= 600000000000 # wait till we mined a few of them target_height = initial_height + 5 height = initial_height if not is_mining_measurent: timeout_init = 600 timeout_mine = 300 else: """ Randomx init has high variance on CI machines due to noisy neighbors, taking up resources in parallel (including by our own jobs). Mining is organized in the following scheme: 1) first loop's pass: RandomX init and mining 2) every next pass: only mining Pass 1) takes much more time than pass 2) Pass 1) uses all cores, pass 2) just one (currently) For the above reasons both passes need separate timeouts and adjustments. After the first pass, the timeout is being reset to a lower value. """ def calc_timeout(seconds_constant, time_pi, cores): """ The time it took to calculate pi under certain conditions is proportional to the time it will take to calculate the real job. The number of cores used decreases the time almost linearly. """ timeout = float(seconds_constant) * time_pi / float(cores) return timeout timeout_base_init = 60 # RX init needs more time timeout_base_mine = 20 timeout_init = calc_timeout(timeout_base_init, time_pi_all_cores, cores_init) timeout_mine = calc_timeout(timeout_base_mine, time_pi_single_cpu, cores_mine) msg_timeout_src = "adjusted for the currently available CPU power" if is_mining_measurent else "selected to have the default value" msg = "Timeout for {} {}, is {:.1f} s" self.print_mining_info( msg.format("init, ", msg_timeout_src, timeout_init)) self.print_mining_info( msg.format("mining,", msg_timeout_src, timeout_mine)) timeout = timeout_init rx_inited = False # Gets initialized in the first pass of the below loop while height < target_height: seen_height = height for _ in range(int(math.ceil(timeout))): time.sleep(1) seconds_passed = monotonic.monotonic() - start height = daemon.get_info().height if height > seen_height: break else: assert False, 'Failed to mine successor to block %d (initial block = %d) after %d s. RX initialized = %r' % ( seen_height, initial_height, round(seconds_passed), rx_inited) if not rx_inited: rx_inited = True timeout = timeout_mine # Resetting the timeout after first mined block and RX init self.print_time_taken(start, "RX init + mining 1st block") else: self.print_time_taken(start, "mining iteration") self.print_time_taken(start, "mining total") if via_daemon: res = daemon.stop_mining() else: res = wallet.stop_mining() res_status = daemon.mining_status() assert res_status.active == False res_info = daemon.get_info() new_height = res_info.height wallet.refresh() res_getbalance = wallet.get_balance() balance = res_getbalance.balance assert balance >= prev_balance + (new_height - initial_height) * 600000000000 if via_daemon: res = daemon.start_mining( '42ey1afDFnn4886T7196doS9GPMzexD9gXpsZJDwVjeRVdFCSoHnv7KPbBeGpzJBzHRCAs9UxqeoyFQMYbqSWYTfJJQAWDm', threads_count=1, do_background_mining=True) else: res = wallet.start_mining(threads_count=1, do_background_mining=True) res_status = daemon.mining_status() assert res_status.active == True assert res_status.threads_count == 1 assert res_status.address == '42ey1afDFnn4886T7196doS9GPMzexD9gXpsZJDwVjeRVdFCSoHnv7KPbBeGpzJBzHRCAs9UxqeoyFQMYbqSWYTfJJQAWDm' assert res_status.is_background_mining_enabled == True assert res_status.block_reward >= 600000000000 # don't wait, might be a while if the machine is busy, which it probably is if via_daemon: res = daemon.stop_mining() else: res = wallet.stop_mining() res_status = daemon.mining_status() assert res_status.active == False
def check_tx_proof(self, txid, amount): daemon = Daemon() print('Checking tx proof') self.wallet[0].refresh() self.wallet[1].refresh() sending_address = '42ey1afDFnn4886T7196doS9GPMzexD9gXpsZJDwVjeRVdFCSoHnv7KPbBeGpzJBzHRCAs9UxqeoyFQMYbqSWYTfJJQAWDm' receiving_address = '44Kbx4sJ7JDRDV5aAhLJzQCjDz2ViLRduE3ijDZu3osWKBjMGkV1XPk4pfDUMqt1Aiezvephdqm6YD19GKFD9ZcXVUTp6BW' res = self.wallet[0].get_tx_proof(txid, sending_address, 'foo'); assert res.signature.startswith('InProof'); signature0i = res.signature res = self.wallet[0].get_tx_proof(txid, receiving_address, 'bar'); assert res.signature.startswith('OutProof'); signature0o = res.signature res = self.wallet[1].get_tx_proof(txid, receiving_address, 'baz'); assert res.signature.startswith('InProof'); signature1 = res.signature res = self.wallet[0].check_tx_proof(txid, sending_address, 'foo', signature0i); assert res.good assert res.received > 0 # likely change assert not res.in_pool assert res.confirmations == 1 ok = False try: res = self.wallet[0].check_tx_proof('0' * 64, sending_address, 'foo', signature0i); except: ok = True assert ok or not res.good ok = False try: res = self.wallet[0].check_tx_proof(txid, receiving_address, 'foo', signature0i); except: ok = True assert ok or not res.good ok = False try: res = self.wallet[0].check_tx_proof(txid, sending_address, '', signature0i); except: ok = True assert ok or not res.good ok = False try: res = self.wallet[0].check_tx_proof(txid, sending_address, 'foo', signature1); except: ok = True assert ok or not res.good res = self.wallet[0].check_tx_proof(txid, receiving_address, 'bar', signature0o); assert res.good assert res.received == amount assert not res.in_pool assert res.confirmations == 1 ok = False try: res = self.wallet[0].check_tx_proof('0' * 64, receiving_address, 'bar', signature0o); except: ok = True assert ok or not res.good ok = False try: res = self.wallet[0].check_tx_proof(txid, sending_address, 'bar', signature0o); except: ok = True assert ok or not res.good ok = False try: res = self.wallet[0].check_tx_proof(txid, receiving_address, '', signature0o); except: ok = True assert ok or not res.good ok = False try: res = self.wallet[0].check_tx_proof(txid, receiving_address, 'bar', signature0i); except: ok = True assert ok or not res.good res = self.wallet[1].check_tx_proof(txid, receiving_address, 'baz', signature1); assert res.good assert res.received == amount assert not res.in_pool assert res.confirmations == 1 ok = False try: res = self.wallet[1].check_tx_proof('0' * 64, receiving_address, 'baz', signature1); except: ok = True assert ok or not res.good ok = False try: res = self.wallet[1].check_tx_proof(txid, sending_address, 'baz', signature1); except: ok = True assert ok or not res.good ok = False try: res = self.wallet[1].check_tx_proof(txid, receiving_address, '', signature1); except: ok = True assert ok or not res.good ok = False try: res = self.wallet[1].check_tx_proof(txid, receiving_address, 'baz', signature0o); except: ok = True assert ok or not res.good
def test_randomx(self): print("Test RandomX") daemon = Daemon() wallet = Wallet() res = daemon.get_height() daemon.pop_blocks(res.height - 1) daemon.flush_txpool() epoch = int(os.environ['SEEDHASH_EPOCH_BLOCKS']) lag = int(os.environ['SEEDHASH_EPOCH_LAG']) address = '42ey1afDFnn4886T7196doS9GPMzexD9gXpsZJDwVjeRVdFCSoHnv7KPbBeGpzJBzHRCAs9UxqeoyFQMYbqSWYTfJJQAWDm' # check we can generate blocks, and that the seed hash changes when expected res = daemon.getblocktemplate(address) first_seed_hash = res.seed_hash daemon.generateblocks(address, 1 + lag) res = daemon.mining_status() assert res.active == False assert res.pow_algorithm == 'RandomX' res = daemon.getblocktemplate(address) seed_hash = res.seed_hash t0 = time.time() daemon.generateblocks(address, epoch - 3) t0 = time.time() - t0 res = daemon.get_info() assert res.height == lag + epoch - 1 res = daemon.getblocktemplate(address) assert seed_hash == res.seed_hash t0 = time.time() daemon.generateblocks(address, 1) t0 = time.time() - t0 res = daemon.get_info() assert res.height == lag + epoch daemon.generateblocks(address, 1) res = daemon.getblocktemplate(address) assert seed_hash != res.seed_hash new_seed_hash = res.seed_hash t0 = time.time() daemon.generateblocks(address, epoch - 1) t0 = time.time() - t0 res = daemon.getblocktemplate(address) assert new_seed_hash == res.seed_hash daemon.generateblocks(address, 1) res = daemon.getblocktemplate(address) assert new_seed_hash != res.seed_hash new_seed_hash = res.seed_hash t0 = time.time() daemon.generateblocks(address, epoch - 1) t0 = time.time() - t0 res = daemon.getblocktemplate(address) assert new_seed_hash == res.seed_hash daemon.generateblocks(address, 1) res = daemon.getblocktemplate(address) assert new_seed_hash != res.seed_hash #print('First mining: ' + str(t0)) # pop all these blocks, and feed them again to monerod print('Recreating the chain') res = daemon.get_info() height = res.height assert height == lag + epoch * 3 + 1 block_hashes = [ x.hash for x in daemon.getblockheadersrange(0, height - 1).headers ] assert len(block_hashes) == height blocks = [] for i in range(len(block_hashes)): res = daemon.getblock(height=i) assert res.block_header.hash == block_hashes[i] blocks.append(res.blob) daemon.pop_blocks(height) res = daemon.get_info() assert res.height == 1 res = daemon.getblocktemplate(address) assert first_seed_hash == res.seed_hash t0 = time.time() for h in range(len(block_hashes)): res = daemon.submitblock(blocks[h]) t0 = time.time() - t0 res = daemon.get_info() assert height == res.height res = daemon.getblocktemplate(address) assert new_seed_hash != res.seed_hash res = daemon.pop_blocks(1) res = daemon.getblocktemplate(address) assert new_seed_hash == res.seed_hash #print('Submit: ' + str(t0)) # start mining from the genesis block again print('Mining from genesis block again') res = daemon.get_height() top_hash = res.hash res = daemon.getblockheaderbyheight(0) genesis_block_hash = res.block_header.hash t0 = time.time() daemon.generateblocks(address, height - 2, prev_block=genesis_block_hash) t0 = time.time() - t0 res = daemon.get_info() assert res.height == height - 1 assert res.top_block_hash == top_hash #print('Second mining: ' + str(t0)) # that one will cause a huge reorg print('Adding one to reorg') res = daemon.generateblocks(address, 1) assert len(res.blocks) == 1 new_top_hash = res.blocks[0] res = daemon.get_info() assert res.height == height assert res.top_block_hash == new_top_hash
def __exit__(self, exc_type, exc_value, traceback): daemon = Daemon() try: daemon.stop_mining() except: pass
def reset(self): print('Resetting blockchain') daemon = Daemon() res = daemon.get_height() daemon.pop_blocks(res.height - 1) daemon.flush_txpool()
def mine(self, address, blocks): print("Mining some blocks") daemon = Daemon() daemon.generateblocks(address, blocks)
def test_access_payment(self): print('Testing access payment') daemon = Daemon(idx=1) wallet = Wallet(idx=3) # Try random nonces till we find one that's valid so we get a load of credits res = daemon.rpc_access_info(client=self.get_signature()) credits = res.credits cookie = res.cookie nonce = 0 while credits <= 100: nonce += 1 try: res = daemon.rpc_access_submit_nonce( nonce=nonce, cookie=cookie, client=self.get_signature()) break except: pass assert nonce < 1000 # can't find both valid and invalid -> the RPC probably fails res = daemon.rpc_access_info(client=self.get_signature()) credits = res.credits assert credits > 0 res = daemon.get_info(client=self.get_signature()) assert res.credits == credits - 1 credits = res.credits res = daemon.generateblocks( '42ey1afDFnn4886T7196doS9GPMzexD9gXpsZJDwVjeRVdFCSoHnv7KPbBeGpzJBzHRCAs9UxqeoyFQMYbqSWYTfJJQAWDm', 100) block_hashes = res.blocks # ask for 1 block -> 1 credit res = daemon.getblockheadersrange(0, 0, client=self.get_signature()) assert res.credits == credits - 1 credits = res.credits # ask for 100 blocks -> >1 credit res = daemon.getblockheadersrange(1, 100, client=self.get_signature()) assert res.credits < credits - 1 credits = res.credits # external users res = daemon.rpc_access_pay(payment=1, paying_for='foo', client=self.get_signature()) assert res.credits == credits - 1 res = daemon.rpc_access_pay(payment=4, paying_for='bar', client=self.get_signature()) assert res.credits == credits - 5 res = daemon.rpc_access_pay(payment=credits, paying_for='baz', client=self.get_signature()) assert "PAYMENT REQUIRED" in res.status res = daemon.rpc_access_pay(payment=2, paying_for='quux', client=self.get_signature()) assert res.credits == credits - 7 res = daemon.rpc_access_pay(payment=3, paying_for='bar', client=self.get_signature()) assert res.credits == credits - 10 # that should be rejected because its cost is massive ok = False try: res = daemon.get_output_histogram(amounts=[], client=self.get_signature()) except Exception as e: print('e: ' + str(e)) ok = "PAYMENT REQUIRED" in e.status assert ok or "PAYMENT REQUIRED" in res.status
def test_access_tracking(self): print('Testing access tracking') daemon = Daemon(idx=1) res = daemon.rpc_access_tracking(True) res = daemon.rpc_access_tracking() data = sorted(res.data, key=lambda k: k['rpc']) assert len(data) == 1 entry = data[0] assert entry.rpc == 'rpc_access_tracking' assert entry.count == 1 assert entry.time >= 0 assert entry.credits == 0 daemon.get_connections() res = daemon.rpc_access_tracking() data = sorted(res.data, key=lambda k: k['rpc']) assert len(data) == 2 entry = data[0] assert entry.rpc == 'get_connections' assert entry.count == 1 assert entry.time >= 0 assert entry.credits == 0 daemon.get_connections() res = daemon.rpc_access_tracking() data = sorted(res.data, key=lambda k: k['rpc']) assert len(data) == 2 entry = data[0] assert entry.rpc == 'get_connections' assert entry.count == 2 assert entry.time >= 0 assert entry.credits == 0 daemon.get_alternate_chains() res = daemon.rpc_access_tracking() data = sorted(res.data, key=lambda k: k['rpc']) assert len(data) == 3 entry = data[0] assert entry.rpc == 'get_alternate_chains' assert entry.count == 1 assert entry.time >= 0 assert entry.credits == 0 entry = res.data[1] assert entry.rpc == 'get_connections' assert entry.count == 2 assert entry.time >= 0 assert entry.credits == 0 res = daemon.rpc_access_tracking(True) res = daemon.rpc_access_tracking() data = sorted(res.data, key=lambda k: k['rpc']) assert len(data) == 1 entry = data[0] assert entry.rpc == 'rpc_access_tracking' assert entry.count == 1
def reset(self): print('Resetting blockchain') daemon = Daemon() daemon.pop_blocks(1000) daemon.flush_txpool()
def test_get_output_distribution(self): print("Test get_output_distribution") daemon = Daemon() res = daemon.get_output_distribution([0], 0, 0) assert len(res.distributions) == 1 d = res.distributions[0] assert d.amount == 0 assert d.base == 0 assert d.binary == False assert len(d.distribution) == 1 assert d.distribution[0] == 0 res = daemon.generateblocks('42ey1afDFnn4886T7196doS9GPMzexD9gXpsZJDwVjeRVdFCSoHnv7KPbBeGpzJBzHRCAs9UxqeoyFQMYbqSWYTfJJQAWDm', 1) res = daemon.get_output_distribution([0], 0, 0) assert len(res.distributions) == 1 d = res.distributions[0] assert d.amount == 0 assert d.base == 0 assert d.binary == False assert len(d.distribution) == 2 assert d.distribution[0] == 0 assert d.distribution[1] == 1 res = daemon.pop_blocks(1) res = daemon.get_output_distribution([0], 0, 0) assert len(res.distributions) == 1 d = res.distributions[0] assert d.amount == 0 assert d.base == 0 assert d.binary == False assert len(d.distribution) == 1 assert d.distribution[0] == 0 res = daemon.generateblocks('42ey1afDFnn4886T7196doS9GPMzexD9gXpsZJDwVjeRVdFCSoHnv7KPbBeGpzJBzHRCAs9UxqeoyFQMYbqSWYTfJJQAWDm', 3) res = daemon.get_output_distribution([0], 0, 0, cumulative = True) assert len(res.distributions) == 1 d = res.distributions[0] assert d.amount == 0 assert d.base == 0 assert d.binary == False assert len(d.distribution) == 4 assert d.distribution[0] == 0 assert d.distribution[1] == 1 assert d.distribution[2] == 2 assert d.distribution[3] == 3 # extend res = daemon.generateblocks('42ey1afDFnn4886T7196doS9GPMzexD9gXpsZJDwVjeRVdFCSoHnv7KPbBeGpzJBzHRCAs9UxqeoyFQMYbqSWYTfJJQAWDm', 80) res = daemon.get_output_distribution([0], 0, 0, cumulative = True) assert len(res.distributions) == 1 d = res.distributions[0] assert d.amount == 0 assert d.base == 0 assert d.binary == False assert len(d.distribution) == 84 for h in range(len(d.distribution)): assert d.distribution[h] == h # pop and replace, this will do through the "trim and extend" path res = daemon.pop_blocks(2) self.wallet.refresh() dst = {'address': '42ey1afDFnn4886T7196doS9GPMzexD9gXpsZJDwVjeRVdFCSoHnv7KPbBeGpzJBzHRCAs9UxqeoyFQMYbqSWYTfJJQAWDm', 'amount': 1000000000000} self.wallet.transfer([dst]) res = daemon.generateblocks('42ey1afDFnn4886T7196doS9GPMzexD9gXpsZJDwVjeRVdFCSoHnv7KPbBeGpzJBzHRCAs9UxqeoyFQMYbqSWYTfJJQAWDm', 1) for step in range(3): # the second will be cached, the third will also be cached, but we get it in non-cumulative mode res = daemon.get_output_distribution([0], 0, 0, cumulative = step < 3) assert len(res.distributions) == 1 d = res.distributions[0] assert d.amount == 0 assert d.base == 0 assert d.binary == False assert len(d.distribution) == 83 for h in range(len(d.distribution)): assert d.distribution[h] == (h if step < 3 else 1) + (2 if h == len(d.distribution) - 1 else 0) # start at 0, end earlier res = daemon.get_output_distribution([0], 0, 40, cumulative = True) assert len(res.distributions) == 1 d = res.distributions[0] assert d.amount == 0 assert d.base == 0 assert d.binary == False assert len(d.distribution) == 41 for h in range(len(d.distribution)): assert d.distribution[h] == h # start after 0, end earlier res = daemon.get_output_distribution([0], 10, 20, cumulative = True) assert len(res.distributions) == 1 d = res.distributions[0] assert d.amount == 0 assert d.base == 9 assert d.binary == False assert len(d.distribution) == 11 for h in range(len(d.distribution)): assert d.distribution[h] == 10 + h # straddling up res = daemon.get_output_distribution([0], 15, 25, cumulative = True) assert len(res.distributions) == 1 d = res.distributions[0] assert d.amount == 0 assert d.base == 14 assert d.binary == False assert len(d.distribution) == 11 for h in range(len(d.distribution)): assert d.distribution[h] == 15 + h # straddling down res = daemon.get_output_distribution([0], 8, 18, cumulative = True) assert len(res.distributions) == 1 d = res.distributions[0] assert d.amount == 0 assert d.base == 7 assert d.binary == False assert len(d.distribution) == 11 for h in range(len(d.distribution)): assert d.distribution[h] == 8 + h # encompassing res = daemon.get_output_distribution([0], 5, 20, cumulative = True) assert len(res.distributions) == 1 d = res.distributions[0] assert d.amount == 0 assert d.base == 4 assert d.binary == False assert len(d.distribution) == 16 for h in range(len(d.distribution)): assert d.distribution[h] == 5 + h # single res = daemon.get_output_distribution([0], 2, 2, cumulative = True) assert len(res.distributions) == 1 d = res.distributions[0] assert d.amount == 0 assert d.base == 1 assert d.binary == False assert len(d.distribution) == 1 assert d.distribution[0] == 2 # a non existent amount res = daemon.get_output_distribution([1], 0, 0) assert len(res.distributions) == 1 d = res.distributions[0] assert d.amount == 1 assert d.base == 0 assert d.binary == False assert len(d.distribution) == 83 for h in range(len(d.distribution)): assert d.distribution[h] == 0
def transfer(self): daemon = Daemon() print("Creating transaction in hot wallet") dst = {'address': '42ey1afDFnn4886T7196doS9GPMzexD9gXpsZJDwVjeRVdFCSoHnv7KPbBeGpzJBzHRCAs9UxqeoyFQMYbqSWYTfJJQAWDm', 'amount': 1000000000000} payment_id = '1234500000012345abcde00000abcdeff1234500000012345abcde00000abcde' self.hot_wallet.refresh() res = self.hot_wallet.export_outputs() self.cold_wallet.import_outputs(res.outputs_data_hex) res = self.cold_wallet.export_key_images(True) self.hot_wallet.import_key_images(res.signed_key_images, offset = res.offset) res = self.hot_wallet.transfer([dst], ring_size = 11, payment_id = payment_id, get_tx_key = False) assert len(res.tx_hash) == 32*2 txid = res.tx_hash assert len(res.tx_key) == 0 assert res.amount > 0 amount = res.amount assert res.fee > 0 fee = res.fee assert len(res.tx_blob) == 0 assert len(res.tx_metadata) == 0 assert len(res.multisig_txset) == 0 assert len(res.unsigned_txset) > 0 unsigned_txset = res.unsigned_txset print('Signing transaction with cold wallet') res = self.cold_wallet.describe_transfer(unsigned_txset = unsigned_txset) assert len(res.desc) == 1 desc = res.desc[0] assert desc.amount_in >= amount + fee assert desc.amount_out == desc.amount_in - fee assert desc.ring_size == 11 assert desc.unlock_time == 0 assert desc.payment_id == payment_id assert desc.change_amount == desc.amount_in - 1000000000000 - fee assert desc.change_address == '42ey1afDFnn4886T7196doS9GPMzexD9gXpsZJDwVjeRVdFCSoHnv7KPbBeGpzJBzHRCAs9UxqeoyFQMYbqSWYTfJJQAWDm' assert desc.fee == fee assert len(desc.recipients) == 1 rec = desc.recipients[0] assert rec.address == '42ey1afDFnn4886T7196doS9GPMzexD9gXpsZJDwVjeRVdFCSoHnv7KPbBeGpzJBzHRCAs9UxqeoyFQMYbqSWYTfJJQAWDm' assert rec.amount == 1000000000000 res = self.cold_wallet.sign_transfer(unsigned_txset) assert len(res.signed_txset) > 0 signed_txset = res.signed_txset assert len(res.tx_hash_list) == 1 txid = res.tx_hash_list[0] assert len(txid) == 64 print('Submitting transaction with hot wallet') res = self.hot_wallet.submit_transfer(signed_txset) assert len(res.tx_hash_list) > 0 assert res.tx_hash_list[0] == txid res = self.hot_wallet.get_transfers() assert len([x for x in (res['pending'] if 'pending' in res else []) if x.txid == txid]) == 1 assert len([x for x in (res['out'] if 'out' in res else []) if x.txid == txid]) == 0 daemon.generateblocks('42ey1afDFnn4886T7196doS9GPMzexD9gXpsZJDwVjeRVdFCSoHnv7KPbBeGpzJBzHRCAs9UxqeoyFQMYbqSWYTfJJQAWDm', 1) self.hot_wallet.refresh() res = self.hot_wallet.get_transfers() assert len([x for x in (res['pending'] if 'pending' in res else []) if x.txid == txid]) == 0 assert len([x for x in (res['out'] if 'out' in res else []) if x.txid == txid]) == 1 res = self.hot_wallet.get_tx_key(txid) assert len(res.tx_key) == 0 or res.tx_key == '01' + '0' * 62 # identity is used as placeholder res = self.cold_wallet.get_tx_key(txid) assert len(res.tx_key) == 64
def run_test(self): print('Testing bans') daemon = Daemon() res = daemon.get_bans() assert 'bans' not in res or len(res.bans) == 0 daemon.set_bans([{'host': '1.2.3.4', 'ban': True, 'seconds': 100}]) res = daemon.get_bans() assert len(res.bans) == 1 assert res.bans[0].host == '1.2.3.4' assert res.bans[0].seconds >= 98 and res.bans[0].seconds <= 100 # allow for slow RPC daemon.set_bans([{'host': '5.6.7.8', 'ban': True, 'seconds': 100}]) res = daemon.get_bans() assert len(res.bans) == 2 for i in range(2): assert res.bans[i].host == '1.2.3.4' or res.bans[i].host == '5.6.7.8' assert res.bans[i].seconds >= 7 and res.bans[0].seconds <= 100 # allow for slow RPC daemon.set_bans([{'host': '1.2.3.4', 'ban': False}]) res = daemon.get_bans() assert len(res.bans) == 1 assert res.bans[0].host == '5.6.7.8' assert res.bans[0].seconds >= 98 and res.bans[0].seconds <= 100 # allow for slow RPC time.sleep(2) res = daemon.get_bans() assert len(res.bans) == 1 assert res.bans[0].host == '5.6.7.8' assert res.bans[0].seconds >= 96 and res.bans[0].seconds <= 98 # allow for slow RPC daemon.set_bans([{'host': '3.4.5.6', 'ban': False}]) res = daemon.get_bans() assert len(res.bans) == 1 assert res.bans[0].host == '5.6.7.8' assert res.bans[0].seconds >= 96 and res.bans[0].seconds <= 98 # allow for slow RPC daemon.set_bans([{'host': '3.4.5.6', 'ban': True, 'seconds': 2}]) res = daemon.get_bans() assert len(res.bans) == 2 for i in range(2): assert res.bans[i].host == '5.6.7.8' or res.bans[i].host == '3.4.5.6' if res.bans[i].host == '5.6.7.8': assert res.bans[i].seconds >= 96 and res.bans[0].seconds <= 98 # allow for slow RPC else: assert res.bans[i].seconds >= 1 and res.bans[0].seconds <= 2 # allow for slow RPC time.sleep(2) res = daemon.get_bans() assert len(res.bans) == 1 assert res.bans[0].host == '5.6.7.8' assert res.bans[0].seconds >= 94 and res.bans[0].seconds <= 96 # allow for slow RPC daemon.set_bans([{'host': '5.6.7.8', 'ban': True, 'seconds': 20}]) res = daemon.get_bans() assert len(res.bans) == 1 assert res.bans[0].host == '5.6.7.8' assert res.bans[0].seconds >= 18 and res.bans[0].seconds <= 20 # allow for slow RPC daemon.set_bans([{'host': '5.6.7.8', 'ban': True, 'seconds': 200}]) res = daemon.get_bans() assert len(res.bans) == 1 assert res.bans[0].host == '5.6.7.8' assert res.bans[0].seconds >= 198 and res.bans[0].seconds <= 200 # allow for slow RPC daemon.set_bans([{'host': '5.6.7.8', 'ban': False}]) res = daemon.get_bans() assert 'bans' not in res or len(res.bans) == 0
def sweep_dust(self): print("Sweeping dust") daemon = Daemon() self.wallet[0].refresh() res = self.wallet[0].sweep_dust() assert not 'tx_hash_list' in res or len(res.tx_hash_list) == 0 # there's just one, but it cannot meet the fee
def transfer(self): daemon = Daemon() print("Creating transfer to self") dst = {'address': '42ey1afDFnn4886T7196doS9GPMzexD9gXpsZJDwVjeRVdFCSoHnv7KPbBeGpzJBzHRCAs9UxqeoyFQMYbqSWYTfJJQAWDm', 'amount': 1000000000000} payment_id = '1234500000012345abcde00000abcdeff1234500000012345abcde00000abcde' start_balances = [0] * len(self.wallet) running_balances = [0] * len(self.wallet) for i in range(len(self.wallet)): res = self.wallet[i].get_balance() start_balances[i] = res.balance running_balances[i] = res.balance assert res.unlocked_balance <= res.balance if i == 0: assert res.blocks_to_unlock == 59 # we've been mining to it else: assert res.blocks_to_unlock == 0 print ('Checking short payment IDs cannot be used when not in an integrated address') ok = False try: self.wallet[0].transfer([dst], ring_size = 11, payment_id = '1234567812345678', get_tx_key = False) except: ok = True assert ok print ('Checking empty destination is rejected') ok = False try: self.wallet[0].transfer([], ring_size = 11, get_tx_key = False) except: ok = True assert ok res = self.wallet[0].transfer([dst], ring_size = 11, payment_id = payment_id, get_tx_key = False) assert len(res.tx_hash) == 32*2 txid = res.tx_hash assert len(res.tx_key) == 0 assert res.amount > 0 amount = res.amount assert res.fee > 0 fee = res.fee assert len(res.tx_blob) == 0 assert len(res.tx_metadata) == 0 assert len(res.multisig_txset) == 0 assert len(res.unsigned_txset) == 0 unsigned_txset = res.unsigned_txset self.wallet[0].refresh() res = daemon.get_info() height = res.height res = self.wallet[0].get_transfers() assert len(res['in']) == height - 1 # coinbases assert not 'out' in res or len(res.out) == 0 # not mined yet assert len(res.pending) == 1 assert not 'pool' in res or len(res.pool) == 0 assert not 'failed' in res or len(res.failed) == 0 for e in res['in']: assert e.type == 'block' e = res.pending[0] assert e.txid == txid assert e.payment_id == payment_id assert e.type == 'pending' assert e.unlock_time == 0 assert e.subaddr_index.major == 0 assert e.subaddr_indices == [{'major': 0, 'minor': 0}] assert e.address == '42ey1afDFnn4886T7196doS9GPMzexD9gXpsZJDwVjeRVdFCSoHnv7KPbBeGpzJBzHRCAs9UxqeoyFQMYbqSWYTfJJQAWDm' assert e.double_spend_seen == False assert e.confirmations == 0 running_balances[0] -= 1000000000000 + fee res = self.wallet[0].get_balance() assert res.balance == running_balances[0] assert res.unlocked_balance <= res.balance assert res.blocks_to_unlock == 59 daemon.generateblocks('42ey1afDFnn4886T7196doS9GPMzexD9gXpsZJDwVjeRVdFCSoHnv7KPbBeGpzJBzHRCAs9UxqeoyFQMYbqSWYTfJJQAWDm', 1) res = daemon.getlastblockheader() running_balances[0] += res.block_header.reward self.wallet[0].refresh() running_balances[0] += 1000000000000 res = self.wallet[0].get_transfers() assert len(res['in']) == height # coinbases assert len(res.out) == 1 # not mined yet assert not 'pending' in res or len(res.pending) == 0 assert not 'pool' in res or len(res.pool) == 0 assert not 'failed' in res or len(res.failed) == 0 for e in res['in']: assert e.type == 'block' e = res.out[0] assert e.txid == txid assert e.payment_id == payment_id assert e.type == 'out' assert e.unlock_time == 0 assert e.subaddr_index.major == 0 assert e.subaddr_indices == [{'major': 0, 'minor': 0}] assert e.address == '42ey1afDFnn4886T7196doS9GPMzexD9gXpsZJDwVjeRVdFCSoHnv7KPbBeGpzJBzHRCAs9UxqeoyFQMYbqSWYTfJJQAWDm' assert e.double_spend_seen == False assert e.confirmations == 1 res = self.wallet[0].get_height() wallet_height = res.height res = self.wallet[0].get_transfer_by_txid(txid) assert len(res.transfers) == 1 assert res.transfers[0] == res.transfer t = res.transfer assert t.txid == txid assert t.payment_id == payment_id assert t.height == wallet_height - 1 assert t.timestamp > 0 assert t.amount == 0 # to self, so it's just "pay a fee" really assert t.fee == fee assert t.note == '' assert len(t.destinations) == 1 assert t.destinations[0] == {'address': '42ey1afDFnn4886T7196doS9GPMzexD9gXpsZJDwVjeRVdFCSoHnv7KPbBeGpzJBzHRCAs9UxqeoyFQMYbqSWYTfJJQAWDm', 'amount': 1000000000000} assert t.type == 'out' assert t.unlock_time == 0 assert t.address == '42ey1afDFnn4886T7196doS9GPMzexD9gXpsZJDwVjeRVdFCSoHnv7KPbBeGpzJBzHRCAs9UxqeoyFQMYbqSWYTfJJQAWDm' assert t.double_spend_seen == False assert t.confirmations == 1 res = self.wallet[0].get_balance() assert res.balance == running_balances[0] assert res.unlocked_balance <= res.balance assert res.blocks_to_unlock == 59 print("Creating transfer to another, manual relay") dst = {'address': '44Kbx4sJ7JDRDV5aAhLJzQCjDz2ViLRduE3ijDZu3osWKBjMGkV1XPk4pfDUMqt1Aiezvephdqm6YD19GKFD9ZcXVUTp6BW', 'amount': 1000000000000} res = self.wallet[0].transfer([dst], ring_size = 11, payment_id = payment_id, get_tx_key = True, do_not_relay = True, get_tx_hex = True) assert len(res.tx_hash) == 32*2 txid = res.tx_hash assert len(res.tx_key) == 32*2 assert res.amount == 1000000000000 amount = res.amount assert res.fee > 0 fee = res.fee assert len(res.tx_blob) > 0 assert len(res.tx_metadata) == 0 assert len(res.multisig_txset) == 0 assert len(res.unsigned_txset) == 0 tx_blob = res.tx_blob res = daemon.send_raw_transaction(tx_blob) assert res.not_relayed == False assert res.low_mixin == False assert res.double_spend == False assert res.invalid_input == False assert res.invalid_output == False assert res.too_big == False assert res.overspend == False assert res.fee_too_low == False assert res.not_rct == False self.wallet[0].refresh() res = self.wallet[0].get_balance() assert res.balance == running_balances[0] assert res.unlocked_balance <= res.balance assert res.blocks_to_unlock == 59 self.wallet[1].refresh() res = self.wallet[1].get_transfers() assert not 'in' in res or len(res['in']) == 0 assert not 'out' in res or len(res.out) == 0 assert not 'pending' in res or len(res.pending) == 0 assert len(res.pool) == 1 assert not 'failed' in res or len(res.failed) == 0 e = res.pool[0] assert e.txid == txid assert e.payment_id == payment_id assert e.type == 'pool' assert e.unlock_time == 0 assert e.subaddr_index.major == 0 assert e.subaddr_indices == [{'major': 0, 'minor': 0}] assert e.address == '44Kbx4sJ7JDRDV5aAhLJzQCjDz2ViLRduE3ijDZu3osWKBjMGkV1XPk4pfDUMqt1Aiezvephdqm6YD19GKFD9ZcXVUTp6BW' assert e.double_spend_seen == False assert e.confirmations == 0 assert e.amount == amount assert e.fee == fee daemon.generateblocks('42ey1afDFnn4886T7196doS9GPMzexD9gXpsZJDwVjeRVdFCSoHnv7KPbBeGpzJBzHRCAs9UxqeoyFQMYbqSWYTfJJQAWDm', 1) res = daemon.getlastblockheader() running_balances[0] -= 1000000000000 + fee running_balances[0] += res.block_header.reward self.wallet[1].refresh() running_balances[1] += 1000000000000 res = self.wallet[1].get_transfers() assert len(res['in']) == 1 assert not 'out' in res or len(res.out) == 0 assert not 'pending' in res or len(res.pending) == 0 assert not 'pool' in res or len(res.pool) == 0 assert not 'failed' in res or len(res.failed) == 0 e = res['in'][0] assert e.txid == txid assert e.payment_id == payment_id assert e.type == 'in' assert e.unlock_time == 0 assert e.subaddr_index.major == 0 assert e.subaddr_indices == [{'major': 0, 'minor': 0}] assert e.address == '44Kbx4sJ7JDRDV5aAhLJzQCjDz2ViLRduE3ijDZu3osWKBjMGkV1XPk4pfDUMqt1Aiezvephdqm6YD19GKFD9ZcXVUTp6BW' assert e.double_spend_seen == False assert e.confirmations == 1 assert e.amount == amount assert e.fee == fee res = self.wallet[1].get_balance() assert res.balance == running_balances[1] assert res.unlocked_balance <= res.balance assert res.blocks_to_unlock == 9 print('Creating multi out transfer') self.wallet[0].refresh() dst0 = {'address': '42ey1afDFnn4886T7196doS9GPMzexD9gXpsZJDwVjeRVdFCSoHnv7KPbBeGpzJBzHRCAs9UxqeoyFQMYbqSWYTfJJQAWDm', 'amount': 1000000000000} dst1 = {'address': '44Kbx4sJ7JDRDV5aAhLJzQCjDz2ViLRduE3ijDZu3osWKBjMGkV1XPk4pfDUMqt1Aiezvephdqm6YD19GKFD9ZcXVUTp6BW', 'amount': 1100000000000} dst2 = {'address': '46r4nYSevkfBUMhuykdK3gQ98XDqDTYW1hNLaXNvjpsJaSbNtdXh1sKMsdVgqkaihChAzEy29zEDPMR3NHQvGoZCLGwTerK', 'amount': 1200000000000} res = self.wallet[0].transfer([dst0, dst1, dst2], ring_size = 11, payment_id = payment_id, get_tx_key = True) assert len(res.tx_hash) == 32*2 txid = res.tx_hash assert len(res.tx_key) == 32*2 assert res.amount == 1000000000000 + 1100000000000 + 1200000000000 amount = res.amount assert res.fee > 0 fee = res.fee assert len(res.tx_blob) == 0 assert len(res.tx_metadata) == 0 assert len(res.multisig_txset) == 0 assert len(res.unsigned_txset) == 0 unsigned_txset = res.unsigned_txset running_balances[0] -= 1000000000000 + 1100000000000 + 1200000000000 + fee res = self.wallet[0].get_balance() assert res.balance == running_balances[0] assert res.unlocked_balance <= res.balance assert res.blocks_to_unlock == 59 daemon.generateblocks('42ey1afDFnn4886T7196doS9GPMzexD9gXpsZJDwVjeRVdFCSoHnv7KPbBeGpzJBzHRCAs9UxqeoyFQMYbqSWYTfJJQAWDm', 1) res = daemon.getlastblockheader() running_balances[0] += res.block_header.reward running_balances[0] += 1000000000000 running_balances[1] += 1100000000000 running_balances[2] += 1200000000000 self.wallet[0].refresh() res = self.wallet[0].get_transfers() assert len(res['in']) == height + 2 assert len(res.out) == 3 assert not 'pending' in res or len(res.pending) == 0 assert not 'pool' in res or len(res.pool) == 1 assert not 'failed' in res or len(res.failed) == 0 e = [o for o in res.out if o.txid == txid] assert len(e) == 1 e = e[0] assert e.txid == txid assert e.payment_id == payment_id assert e.type == 'out' assert e.unlock_time == 0 assert e.subaddr_index.major == 0 assert e.subaddr_indices == [{'major': 0, 'minor': 0}] assert e.address == '42ey1afDFnn4886T7196doS9GPMzexD9gXpsZJDwVjeRVdFCSoHnv7KPbBeGpzJBzHRCAs9UxqeoyFQMYbqSWYTfJJQAWDm' assert e.double_spend_seen == False assert e.confirmations == 1 assert e.amount == amount assert e.fee == fee res = self.wallet[0].get_balance() assert res.balance == running_balances[0] assert res.unlocked_balance <= res.balance assert res.blocks_to_unlock == 59 self.wallet[1].refresh() res = self.wallet[1].get_transfers() assert len(res['in']) == 2 assert not 'out' in res or len(res.out) == 0 assert not 'pending' in res or len(res.pending) == 0 assert not 'pool' in res or len(res.pool) == 0 assert not 'failed' in res or len(res.failed) == 0 e = [o for o in res['in'] if o.txid == txid] assert len(e) == 1 e = e[0] assert e.txid == txid assert e.payment_id == payment_id assert e.type == 'in' assert e.unlock_time == 0 assert e.subaddr_index.major == 0 assert e.subaddr_indices == [{'major': 0, 'minor': 0}] assert e.address == '44Kbx4sJ7JDRDV5aAhLJzQCjDz2ViLRduE3ijDZu3osWKBjMGkV1XPk4pfDUMqt1Aiezvephdqm6YD19GKFD9ZcXVUTp6BW' assert e.double_spend_seen == False assert e.confirmations == 1 assert e.amount == 1100000000000 assert e.fee == fee res = self.wallet[1].get_balance() assert res.balance == running_balances[1] assert res.unlocked_balance <= res.balance assert res.blocks_to_unlock == 9 self.wallet[2].refresh() res = self.wallet[2].get_transfers() assert len(res['in']) == 1 assert not 'out' in res or len(res.out) == 0 assert not 'pending' in res or len(res.pending) == 0 assert not 'pool' in res or len(res.pool) == 0 assert not 'failed' in res or len(res.failed) == 0 e = [o for o in res['in'] if o.txid == txid] assert len(e) == 1 e = e[0] assert e.txid == txid assert e.payment_id == payment_id assert e.type == 'in' assert e.unlock_time == 0 assert e.subaddr_index.major == 0 assert e.subaddr_indices == [{'major': 0, 'minor': 0}] assert e.address == '46r4nYSevkfBUMhuykdK3gQ98XDqDTYW1hNLaXNvjpsJaSbNtdXh1sKMsdVgqkaihChAzEy29zEDPMR3NHQvGoZCLGwTerK' assert e.double_spend_seen == False assert e.confirmations == 1 assert e.amount == 1200000000000 assert e.fee == fee res = self.wallet[2].get_balance() assert res.balance == running_balances[2] assert res.unlocked_balance <= res.balance assert res.blocks_to_unlock == 9 print('Sending to integrated address') self.wallet[0].refresh() res = self.wallet[0].get_balance() i_pid = '1111111122222222' res = self.wallet[0].make_integrated_address(standard_address = '44Kbx4sJ7JDRDV5aAhLJzQCjDz2ViLRduE3ijDZu3osWKBjMGkV1XPk4pfDUMqt1Aiezvephdqm6YD19GKFD9ZcXVUTp6BW', payment_id = i_pid) i_address = res.integrated_address res = self.wallet[0].transfer([{'address': i_address, 'amount': 200000000}]) assert len(res.tx_hash) == 32*2 i_txid = res.tx_hash assert len(res.tx_key) == 32*2 assert res.amount == 200000000 i_amount = res.amount assert res.fee > 0 fee = res.fee assert len(res.tx_blob) == 0 assert len(res.tx_metadata) == 0 assert len(res.multisig_txset) == 0 assert len(res.unsigned_txset) == 0 running_balances[0] -= 200000000 + fee res = self.wallet[0].get_balance() assert res.balance == running_balances[0] assert res.unlocked_balance <= res.balance assert res.blocks_to_unlock == 59 daemon.generateblocks('42ey1afDFnn4886T7196doS9GPMzexD9gXpsZJDwVjeRVdFCSoHnv7KPbBeGpzJBzHRCAs9UxqeoyFQMYbqSWYTfJJQAWDm', 1) res = daemon.getlastblockheader() running_balances[0] += res.block_header.reward running_balances[1] += 200000000 self.wallet[0].refresh() res = self.wallet[0].get_balance() assert res.balance == running_balances[0] assert res.unlocked_balance <= res.balance assert res.blocks_to_unlock == 59 self.wallet[1].refresh() res = self.wallet[1].get_balance() assert res.balance == running_balances[1] assert res.unlocked_balance <= res.balance assert res.blocks_to_unlock == 9 self.wallet[2].refresh() res = self.wallet[2].get_balance() assert res.balance == running_balances[2] assert res.unlocked_balance <= res.balance assert res.blocks_to_unlock == 8 daemon.generateblocks('42ey1afDFnn4886T7196doS9GPMzexD9gXpsZJDwVjeRVdFCSoHnv7KPbBeGpzJBzHRCAs9UxqeoyFQMYbqSWYTfJJQAWDm', 1) res = daemon.getlastblockheader() running_balances[0] += res.block_header.reward self.wallet[0].refresh() res = self.wallet[0].get_balance() assert res.balance == running_balances[0] assert res.unlocked_balance <= res.balance assert res.blocks_to_unlock == 59 self.wallet[1].refresh() res = self.wallet[1].get_balance() assert res.balance == running_balances[1] assert res.unlocked_balance <= res.balance assert res.blocks_to_unlock == 8 self.wallet[2].refresh() res = self.wallet[2].get_balance() assert res.balance == running_balances[2] assert res.unlocked_balance <= res.balance assert res.blocks_to_unlock == 7
def check_txpool(self): daemon = Daemon() wallet = Wallet() res = daemon.get_info() height = res.height txpool_size = res.tx_pool_size txes = self.create_txes('46r4nYSevkfBUMhuykdK3gQ98XDqDTYW1hNLaXNvjpsJaSbNtdXh1sKMsdVgqkaihChAzEy29zEDPMR3NHQvGoZCLGwTerK', 5) res = daemon.get_info() assert res.tx_pool_size == txpool_size + 5 txpool_size = res.tx_pool_size res = daemon.get_transaction_pool() assert len(res.transactions) == txpool_size for txid in txes.keys(): x = [x for x in res.transactions if x.id_hash == txid] assert len(x) == 1 x = x[0] assert x.kept_by_block == False assert x.last_failed_id_hash == '0'*64 assert x.double_spend_seen == False assert x.weight >= x.blob_size assert x.blob_size * 2 == len(txes[txid].tx_blob) assert x.fee == txes[txid].fee assert x.tx_blob == txes[txid].tx_blob res = daemon.get_transaction_pool_hashes() assert sorted(res.tx_hashes) == sorted(txes.keys()) print('Flushing 2 transactions') txes_keys = list(txes.keys()) daemon.flush_txpool([txes_keys[1], txes_keys[3]]) res = daemon.get_transaction_pool() assert len(res.transactions) == txpool_size - 2 assert len([x for x in res.transactions if x.id_hash == txes_keys[1]]) == 0 assert len([x for x in res.transactions if x.id_hash == txes_keys[3]]) == 0 new_keys = list(txes.keys()) new_keys.remove(txes_keys[1]) new_keys.remove(txes_keys[3]) res = daemon.get_transaction_pool_hashes() assert sorted(res.tx_hashes) == sorted(new_keys) print('Flushing unknown transactions') unknown_txids = ['1'*64, '2'*64, '3'*64] daemon.flush_txpool(unknown_txids) res = daemon.get_transaction_pool() assert len(res.transactions) == txpool_size - 2 print('Mining transactions') daemon.generateblocks('42ey1afDFnn4886T7196doS9GPMzexD9gXpsZJDwVjeRVdFCSoHnv7KPbBeGpzJBzHRCAs9UxqeoyFQMYbqSWYTfJJQAWDm', 1) res = daemon.get_transaction_pool() assert not 'transactions' in res or len(res.transactions) == txpool_size - 5 res = daemon.get_transaction_pool_hashes() assert not 'tx_hashes' in res or len(res.tx_hashes) == 0 print('Popping block') daemon.pop_blocks(1) res = daemon.get_transaction_pool_hashes() assert sorted(res.tx_hashes) == sorted(new_keys) res = daemon.get_transaction_pool() assert len(res.transactions) == txpool_size - 2 for txid in new_keys: x = [x for x in res.transactions if x.id_hash == txid] assert len(x) == 1 x = x[0] assert x.kept_by_block == True assert x.last_failed_id_hash == '0'*64 assert x.double_spend_seen == False assert x.weight >= x.blob_size assert x.blob_size * 2 == len(txes[txid].tx_blob) assert x.fee == txes[txid].fee assert x.tx_blob == txes[txid].tx_blob
def test_access_account(self): print('Testing access account') daemon = Daemon(idx=1) wallet = Wallet(idx=3) res = daemon.rpc_access_info(client=self.get_signature()) credits = res.credits res = daemon.rpc_access_account(self.get_signature(), 0) assert res.credits == credits res = daemon.rpc_access_account(self.get_signature(), 50) assert res.credits == credits + 50 res = daemon.rpc_access_account(self.get_signature(), -10) assert res.credits == credits + 40 res = daemon.rpc_access_account(self.get_signature(), -(credits + 50)) assert res.credits == 0 res = daemon.rpc_access_account(self.get_signature(), 2**63 - 5) assert res.credits == 2**63 - 5 res = daemon.rpc_access_account(self.get_signature(), 2**63 - 1) assert res.credits == 2**64 - 6 res = daemon.rpc_access_account(self.get_signature(), 2) assert res.credits == 2**64 - 4 res = daemon.rpc_access_account(self.get_signature(), 8) assert res.credits == 2**64 - 1 res = daemon.rpc_access_account(self.get_signature(), -1) assert res.credits == 2**64 - 2 res = daemon.rpc_access_account(self.get_signature(), -(2**63 - 1)) assert res.credits == 2**64 - 2 - (2**63 - 1) res = daemon.rpc_access_account(self.get_signature(), -(2**63 - 1)) assert res.credits == 0
def transfer(self, signers): assert len(signers) >= 2 daemon = Daemon() print("Creating multisig transaction from wallet " + str(signers[0])) dst = {'address': '42ey1afDFnn4886T7196doS9GPMzexD9gXpsZJDwVjeRVdFCSoHnv7KPbBeGpzJBzHRCAs9UxqeoyFQMYbqSWYTfJJQAWDm', 'amount': 1000000000000} res = self.wallet[signers[0]].transfer([dst]) assert len(res.tx_hash) == 0 # not known yet txid = res.tx_hash assert len(res.tx_key) == 32*2 assert res.amount > 0 amount = res.amount assert res.fee > 0 fee = res.fee assert len(res.tx_blob) == 0 assert len(res.tx_metadata) == 0 assert len(res.multisig_txset) > 0 assert len(res.unsigned_txset) == 0 multisig_txset = res.multisig_txset daemon.generateblocks('42ey1afDFnn4886T7196doS9GPMzexD9gXpsZJDwVjeRVdFCSoHnv7KPbBeGpzJBzHRCAs9UxqeoyFQMYbqSWYTfJJQAWDm', 1) for i in range(len(self.wallet)): self.wallet[i].refresh() for i in range(len(signers[1:])): print('Signing multisig transaction with wallet ' + str(signers[i+1])) res = self.wallet[signers[i+1]].describe_transfer(multisig_txset = multisig_txset) assert len(res.desc) == 1 desc = res.desc[0] assert desc.amount_in >= amount + fee assert desc.amount_out == desc.amount_in - fee assert desc.ring_size == 11 assert desc.unlock_time == 0 assert desc.payment_id == '0000000000000000' assert desc.change_amount == desc.amount_in - 1000000000000 - fee assert desc.change_address == self.wallet_address assert desc.fee == fee assert len(desc.recipients) == 1 rec = desc.recipients[0] assert rec.address == '42ey1afDFnn4886T7196doS9GPMzexD9gXpsZJDwVjeRVdFCSoHnv7KPbBeGpzJBzHRCAs9UxqeoyFQMYbqSWYTfJJQAWDm' assert rec.amount == 1000000000000 res = self.wallet[signers[i+1]].sign_multisig(multisig_txset) multisig_txset = res.tx_data_hex assert len(res.tx_hash_list if 'tx_hash_list' in res else []) == (i == len(signers[1:]) - 1) if i < len(signers[1:]) - 1: print('Submitting multisig transaction prematurely with wallet ' + str(signers[-1])) ok = False try: self.wallet[signers[-1]].submit_multisig(multisig_txset) except: ok = True assert ok print('Submitting multisig transaction with wallet ' + str(signers[-1])) res = self.wallet[signers[-1]].submit_multisig(multisig_txset) assert len(res.tx_hash_list) == 1 txid = res.tx_hash_list[0] for i in range(len(self.wallet)): self.wallet[i].refresh() res = self.wallet[i].get_transfers() assert len([x for x in (res['pending'] if 'pending' in res else []) if x.txid == txid]) == (1 if i == signers[-1] else 0) assert len([x for x in (res['out'] if 'out' in res else []) if x.txid == txid]) == 0 daemon.generateblocks('42ey1afDFnn4886T7196doS9GPMzexD9gXpsZJDwVjeRVdFCSoHnv7KPbBeGpzJBzHRCAs9UxqeoyFQMYbqSWYTfJJQAWDm', 1) return txid
def test_get_output_distribution(self): print("Test get_output_distribution") daemon = Daemon() res = daemon.get_output_distribution([0], 0, 0) assert len(res.distributions) == 1 d = res.distributions[0] assert d.amount == 0 assert d.base == 0 assert d.binary == False assert len(d.distribution) == 1 assert d.distribution[0] == 0 res = daemon.generateblocks( '42ey1afDFnn4886T7196doS9GPMzexD9gXpsZJDwVjeRVdFCSoHnv7KPbBeGpzJBzHRCAs9UxqeoyFQMYbqSWYTfJJQAWDm', 1) res = daemon.get_output_distribution([0], 0, 0) assert len(res.distributions) == 1 d = res.distributions[0] assert d.amount == 0 assert d.base == 0 assert d.binary == False assert len(d.distribution) == 2 assert d.distribution[0] == 0 assert d.distribution[1] == 1 res = daemon.pop_blocks(1) res = daemon.get_output_distribution([0], 0, 0) assert len(res.distributions) == 1 d = res.distributions[0] assert d.amount == 0 assert d.base == 0 assert d.binary == False assert len(d.distribution) == 1 assert d.distribution[0] == 0 res = daemon.generateblocks( '42ey1afDFnn4886T7196doS9GPMzexD9gXpsZJDwVjeRVdFCSoHnv7KPbBeGpzJBzHRCAs9UxqeoyFQMYbqSWYTfJJQAWDm', 3) res = daemon.get_output_distribution([0], 0, 0, cumulative=True) assert len(res.distributions) == 1 d = res.distributions[0] assert d.amount == 0 assert d.base == 0 assert d.binary == False assert len(d.distribution) == 4 assert d.distribution[0] == 0 assert d.distribution[1] == 1 assert d.distribution[2] == 2 assert d.distribution[3] == 3 # extend res = daemon.generateblocks( '42ey1afDFnn4886T7196doS9GPMzexD9gXpsZJDwVjeRVdFCSoHnv7KPbBeGpzJBzHRCAs9UxqeoyFQMYbqSWYTfJJQAWDm', 80) res = daemon.get_output_distribution([0], 0, 0, cumulative=True) assert len(res.distributions) == 1 d = res.distributions[0] assert d.amount == 0 assert d.base == 0 assert d.binary == False assert len(d.distribution) == 84 for h in range(len(d.distribution)): assert d.distribution[h] == h # pop and replace, this will do through the "trim and extend" path res = daemon.pop_blocks(2) self.wallet.refresh() dst = { 'address': '42ey1afDFnn4886T7196doS9GPMzexD9gXpsZJDwVjeRVdFCSoHnv7KPbBeGpzJBzHRCAs9UxqeoyFQMYbqSWYTfJJQAWDm', 'amount': 1000000000000 } self.wallet.transfer([dst]) res = daemon.generateblocks( '42ey1afDFnn4886T7196doS9GPMzexD9gXpsZJDwVjeRVdFCSoHnv7KPbBeGpzJBzHRCAs9UxqeoyFQMYbqSWYTfJJQAWDm', 1) for step in range( 3 ): # the second will be cached, the third will also be cached, but we get it in non-cumulative mode res = daemon.get_output_distribution([0], 0, 0, cumulative=step < 3) assert len(res.distributions) == 1 d = res.distributions[0] assert d.amount == 0 assert d.base == 0 assert d.binary == False assert len(d.distribution) == 83 for h in range(len(d.distribution)): assert d.distribution[h] == (h if step < 3 else 1) + ( 2 if h == len(d.distribution) - 1 else 0) # start at 0, end earlier res = daemon.get_output_distribution([0], 0, 40, cumulative=True) assert len(res.distributions) == 1 d = res.distributions[0] assert d.amount == 0 assert d.base == 0 assert d.binary == False assert len(d.distribution) == 41 for h in range(len(d.distribution)): assert d.distribution[h] == h # start after 0, end earlier res = daemon.get_output_distribution([0], 10, 20, cumulative=True) assert len(res.distributions) == 1 d = res.distributions[0] assert d.amount == 0 assert d.base == 9 assert d.binary == False assert len(d.distribution) == 11 for h in range(len(d.distribution)): assert d.distribution[h] == 10 + h # straddling up res = daemon.get_output_distribution([0], 15, 25, cumulative=True) assert len(res.distributions) == 1 d = res.distributions[0] assert d.amount == 0 assert d.base == 14 assert d.binary == False assert len(d.distribution) == 11 for h in range(len(d.distribution)): assert d.distribution[h] == 15 + h # straddling down res = daemon.get_output_distribution([0], 8, 18, cumulative=True) assert len(res.distributions) == 1 d = res.distributions[0] assert d.amount == 0 assert d.base == 7 assert d.binary == False assert len(d.distribution) == 11 for h in range(len(d.distribution)): assert d.distribution[h] == 8 + h # encompassing res = daemon.get_output_distribution([0], 5, 20, cumulative=True) assert len(res.distributions) == 1 d = res.distributions[0] assert d.amount == 0 assert d.base == 4 assert d.binary == False assert len(d.distribution) == 16 for h in range(len(d.distribution)): assert d.distribution[h] == 5 + h # single res = daemon.get_output_distribution([0], 2, 2, cumulative=True) assert len(res.distributions) == 1 d = res.distributions[0] assert d.amount == 0 assert d.base == 1 assert d.binary == False assert len(d.distribution) == 1 assert d.distribution[0] == 2 # a non existent amount res = daemon.get_output_distribution([1], 0, 0) assert len(res.distributions) == 1 d = res.distributions[0] assert d.amount == 1 assert d.base == 0 assert d.binary == False assert len(d.distribution) == 83 for h in range(len(d.distribution)): assert d.distribution[h] == 0
def check_destinations(self): daemon = Daemon(idx=2) print("Checking transaction destinations") dst = { 'address': '42ey1afDFnn4886T7196doS9GPMzexD9gXpsZJDwVjeRVdFCSoHnv7KPbBeGpzJBzHRCAs9UxqeoyFQMYbqSWYTfJJQAWDm', 'amount': 1000000000000 } res = self.wallet[0].transfer([dst]) assert len(res.tx_hash) == 64 tx_hash = res.tx_hash for i in range(2): res = self.wallet[0].get_transfers(pending=True, out=True) l = [ x for x in (res.pending if i == 0 else res.out) if x.txid == tx_hash ] assert len(l) == 1 e = l[0] assert len(e.destinations) == 1 assert e.destinations[0].amount == 1000000000000 assert e.destinations[ 0].address == '42ey1afDFnn4886T7196doS9GPMzexD9gXpsZJDwVjeRVdFCSoHnv7KPbBeGpzJBzHRCAs9UxqeoyFQMYbqSWYTfJJQAWDm' if i == 0: daemon.generateblocks( '42ey1afDFnn4886T7196doS9GPMzexD9gXpsZJDwVjeRVdFCSoHnv7KPbBeGpzJBzHRCAs9UxqeoyFQMYbqSWYTfJJQAWDm', 1) self.wallet[0].refresh() dst = { 'address': '8AsN91rznfkBGTY8psSNkJBg9SZgxxGGRUhGwRptBhgr5XSQ1XzmA9m8QAnoxydecSh5aLJXdrgXwTDMMZ1AuXsN1EX5Mtm', 'amount': 1000000000000 } res = self.wallet[0].transfer([dst]) assert len(res.tx_hash) == 64 tx_hash = res.tx_hash for i in range(2): res = self.wallet[0].get_transfers(pending=True, out=True) l = [ x for x in (res.pending if i == 0 else res.out) if x.txid == tx_hash ] assert len(l) == 1 e = l[0] assert len(e.destinations) == 1 assert e.destinations[0].amount == 1000000000000 assert e.destinations[ 0].address == '8AsN91rznfkBGTY8psSNkJBg9SZgxxGGRUhGwRptBhgr5XSQ1XzmA9m8QAnoxydecSh5aLJXdrgXwTDMMZ1AuXsN1EX5Mtm' if i == 0: daemon.generateblocks( '42ey1afDFnn4886T7196doS9GPMzexD9gXpsZJDwVjeRVdFCSoHnv7KPbBeGpzJBzHRCAs9UxqeoyFQMYbqSWYTfJJQAWDm', 1) self.wallet[0].refresh() dst = { 'address': '4BxSHvcgTwu25WooY4BVmgdcKwZu5EksVZSZkDd6ooxSVVqQ4ubxXkhLF6hEqtw96i9cf3cVfLw8UWe95bdDKfRQeYtPwLm1Jiw7AKt2LY', 'amount': 1000000000000 } res = self.wallet[0].transfer([dst]) assert len(res.tx_hash) == 64 tx_hash = res.tx_hash for i in range(2): res = self.wallet[0].get_transfers(pending=True, out=True) l = [ x for x in (res.pending if i == 0 else res.out) if x.txid == tx_hash ] assert len(l) == 1 e = l[0] assert len(e.destinations) == 1 assert e.destinations[0].amount == 1000000000000 assert e.destinations[ 0].address == '4BxSHvcgTwu25WooY4BVmgdcKwZu5EksVZSZkDd6ooxSVVqQ4ubxXkhLF6hEqtw96i9cf3cVfLw8UWe95bdDKfRQeYtPwLm1Jiw7AKt2LY' if i == 0: daemon.generateblocks( '42ey1afDFnn4886T7196doS9GPMzexD9gXpsZJDwVjeRVdFCSoHnv7KPbBeGpzJBzHRCAs9UxqeoyFQMYbqSWYTfJJQAWDm', 1) self.wallet[0].refresh()
def _test_alt_chains(self): print('Testing alt chains') daemon = Daemon() res = daemon.get_alt_blocks_hashes() starting_alt_blocks = res.blks_hashes if 'blks_hashes' in res else [] res = daemon.get_info() root_block_hash = res.top_block_hash height = res.height prev_hash = res.top_block_hash res_template = daemon.getblocktemplate( '42ey1afDFnn4886T7196doS9GPMzexD9gXpsZJDwVjeRVdFCSoHnv7KPbBeGpzJBzHRCAs9UxqeoyFQMYbqSWYTfJJQAWDm' ) nonce = 0 # 5 siblings alt_blocks = [None] * 5 for i in range(len(alt_blocks)): res = daemon.generateblocks( '42ey1afDFnn4886T7196doS9GPMzexD9gXpsZJDwVjeRVdFCSoHnv7KPbBeGpzJBzHRCAs9UxqeoyFQMYbqSWYTfJJQAWDm', 1, prev_block=prev_hash, starting_nonce=nonce) assert res.height == height assert len(res.blocks) == 1 txid = res.blocks[0] res = daemon.getblockheaderbyhash(txid) nonce = res.block_header.nonce print('mined ' + ('alt' if res.block_header.orphan_status else 'tip') + ' block ' + str(height) + ', nonce ' + str(nonce)) assert res.block_header.prev_hash == prev_hash assert res.block_header.orphan_status == (i > 0) alt_blocks[i] = txid nonce += 1 print('mining 3 on 1') # three more on [1] chain1 = [] res = daemon.generateblocks( '42ey1afDFnn4886T7196doS9GPMzexD9gXpsZJDwVjeRVdFCSoHnv7KPbBeGpzJBzHRCAs9UxqeoyFQMYbqSWYTfJJQAWDm', 3, prev_block=alt_blocks[1], starting_nonce=nonce) assert res.height == height + 3 assert len(res.blocks) == 3 blk_hash = res.blocks[2] res = daemon.getblockheaderbyhash(blk_hash) nonce = res.block_header.nonce assert not res.block_header.orphan_status nonce += 1 chain1.append(blk_hash) chain1.append(res.block_header.prev_hash) print('Checking alt blocks match') res = daemon.get_alt_blocks_hashes() assert len(res.blks_hashes) == len(starting_alt_blocks) + 4 for txid in alt_blocks: assert txid in res.blks_hashes or txid == alt_blocks[1] print('mining 4 on 3') # 4 more on [3], the chain will reorg when we mine the 4th top_block_hash = blk_hash prev_block = alt_blocks[3] for i in range(4): res = daemon.generateblocks( '42ey1afDFnn4886T7196doS9GPMzexD9gXpsZJDwVjeRVdFCSoHnv7KPbBeGpzJBzHRCAs9UxqeoyFQMYbqSWYTfJJQAWDm', 1, prev_block=prev_block) assert res.height == height + 1 + i assert len(res.blocks) == 1 prev_block = res.blocks[-1] res = daemon.getblockheaderbyhash(res.blocks[-1]) assert res.block_header.orphan_status == (i < 3) res = daemon.get_info() assert res.height == ((height + 4) if i < 3 else height + 5) assert res.top_block_hash == (top_block_hash if i < 3 else prev_block) res = daemon.get_info() assert res.height == height + 5 assert res.top_block_hash == prev_block print('Checking alt blocks match') res = daemon.get_alt_blocks_hashes() blks_hashes = res.blks_hashes assert len(blks_hashes) == len(starting_alt_blocks) + 7 for txid in alt_blocks: assert txid in blks_hashes or txid == alt_blocks[3] for txid in chain1: assert txid in blks_hashes res = daemon.get_alternate_chains() assert len(res.chains) == 4 tips = [chain.block_hash for chain in res.chains] for txid in tips: assert txid in blks_hashes for chain in res.chains: assert chain.length in [1, 4] assert chain.length == len(chain.block_hashes) assert chain.height == height + chain.length - 1 # all happen start at the same height assert chain.main_chain_parent_block == root_block_hash for txid in [alt_blocks[0], alt_blocks[2], alt_blocks[4]]: assert len([ chain for chain in res.chains if chain.block_hash == txid ]) == 1
def sweep_single(self): daemon = Daemon() print("Sending single output") daemon.generateblocks('42ey1afDFnn4886T7196doS9GPMzexD9gXpsZJDwVjeRVdFCSoHnv7KPbBeGpzJBzHRCAs9UxqeoyFQMYbqSWYTfJJQAWDm', 1) self.wallet[0].refresh() res = self.wallet[0].incoming_transfers(transfer_type = 'available') for t in res.transfers: assert not t.spent assert len(res.transfers) > 8 # we mined a lot index = 8 assert not res.transfers[index].spent assert res.transfers[index].amount > 0 ki = res.transfers[index].key_image amount = res.transfers[index].amount daemon.generateblocks('42ey1afDFnn4886T7196doS9GPMzexD9gXpsZJDwVjeRVdFCSoHnv7KPbBeGpzJBzHRCAs9UxqeoyFQMYbqSWYTfJJQAWDm', 10) # ensure unlocked self.wallet[0].refresh() res = self.wallet[0].get_balance() balance = res.balance res = daemon.is_key_image_spent([ki]) assert len(res.spent_status) == 1 assert res.spent_status[0] == 0 res = self.wallet[0].sweep_single('44Kbx4sJ7JDRDV5aAhLJzQCjDz2ViLRduE3ijDZu3osWKBjMGkV1XPk4pfDUMqt1Aiezvephdqm6YD19GKFD9ZcXVUTp6BW', key_image = ki) assert len(res.tx_hash) == 64 tx_hash = res.tx_hash res = daemon.is_key_image_spent([ki]) assert len(res.spent_status) == 1 assert res.spent_status[0] == 2 daemon.generateblocks('44Kbx4sJ7JDRDV5aAhLJzQCjDz2ViLRduE3ijDZu3osWKBjMGkV1XPk4pfDUMqt1Aiezvephdqm6YD19GKFD9ZcXVUTp6BW', 1) res = daemon.is_key_image_spent([ki]) assert len(res.spent_status) == 1 assert res.spent_status[0] == 1 self.wallet[0].refresh() res = self.wallet[0].get_balance() new_balance = res.balance res = daemon.get_transactions([tx_hash], decode_as_json = True) assert len(res.txs) == 1 tx = res.txs[0] assert tx.tx_hash == tx_hash assert not tx.in_pool assert len(tx.as_json) > 0 try: j = json.loads(tx.as_json) except: j = None assert j assert new_balance == balance - amount assert len(j['vin']) == 1 assert j['vin'][0]['key']['k_image'] == ki self.wallet[0].refresh() res = self.wallet[0].incoming_transfers(transfer_type = 'available') assert len([t for t in res.transfers if t.key_image == ki]) == 0 res = self.wallet[0].incoming_transfers(transfer_type = 'unavailable') assert len([t for t in res.transfers if t.key_image == ki]) == 1
def _test_generateblocks(self, blocks): assert blocks >= 2 print("Test generating", blocks, 'blocks') daemon = Daemon() # check info/height before generating blocks res_info = daemon.get_info() height = res_info.height prev_block = res_info.top_block_hash res_height = daemon.get_height() assert res_height.height == height assert int(res_info.wide_cumulative_difficulty) == ( res_info.cumulative_difficulty_top64 << 64) + res_info.cumulative_difficulty cumulative_difficulty = int(res_info.wide_cumulative_difficulty) # we should not see a block at height ok = False try: daemon.getblock(height) except: ok = True assert ok # generate blocks res_generateblocks = daemon.generateblocks( '42ey1afDFnn4886T7196doS9GPMzexD9gXpsZJDwVjeRVdFCSoHnv7KPbBeGpzJBzHRCAs9UxqeoyFQMYbqSWYTfJJQAWDm', blocks) # check info/height after generateblocks blocks assert res_generateblocks.height == height + blocks - 1 res_info = daemon.get_info() assert res_info.height == height + blocks assert res_info.top_block_hash != prev_block res_height = daemon.get_height() assert res_height.height == height + blocks # get the blocks, check they have the right height res_getblock = [] for n in range(blocks): res_getblock.append(daemon.getblock(height + n)) block_header = res_getblock[n].block_header assert abs(block_header.timestamp - time.time()) < 10 # within 10 seconds assert block_header.height == height + n assert block_header.orphan_status == False assert block_header.depth == blocks - n - 1 assert block_header.prev_hash == prev_block, prev_block assert int(block_header.wide_difficulty) == ( block_header.difficulty_top64 << 64) + block_header.difficulty assert int(block_header.wide_cumulative_difficulty) == ( block_header.cumulative_difficulty_top64 << 64) + block_header.cumulative_difficulty assert block_header.reward >= 600000000000 # tail emission cumulative_difficulty += int(block_header.wide_difficulty) assert cumulative_difficulty == int( block_header.wide_cumulative_difficulty) assert block_header.block_size > 0 assert block_header.block_weight >= block_header.block_size assert block_header.long_term_weight > 0 prev_block = block_header.hash # we should not see a block after that ok = False try: daemon.getblock(height + blocks) except: ok = True assert ok # getlastblockheader and by height/hash should return the same block res_getlastblockheader = daemon.getlastblockheader() assert res_getlastblockheader.block_header == block_header res_getblockheaderbyhash = daemon.getblockheaderbyhash(prev_block) assert res_getblockheaderbyhash.block_header == block_header res_getblockheaderbyheight = daemon.getblockheaderbyheight(height + blocks - 1) assert res_getblockheaderbyheight.block_header == block_header # getting a block template after that should have the right height, etc res_getblocktemplate = daemon.getblocktemplate( '42ey1afDFnn4886T7196doS9GPMzexD9gXpsZJDwVjeRVdFCSoHnv7KPbBeGpzJBzHRCAs9UxqeoyFQMYbqSWYTfJJQAWDm' ) assert res_getblocktemplate.height == height + blocks assert res_getblocktemplate.reserved_offset > 0 assert res_getblocktemplate.prev_hash == res_info.top_block_hash assert res_getblocktemplate.expected_reward >= 600000000000 assert len(res_getblocktemplate.blocktemplate_blob) > 0 assert len(res_getblocktemplate.blockhashing_blob) > 0 assert int(res_getblocktemplate.wide_difficulty) == ( res_getblocktemplate.difficulty_top64 << 64) + res_getblocktemplate.difficulty # diff etc should be the same assert res_getblocktemplate.prev_hash == res_info.top_block_hash res_getlastblockheader = daemon.getlastblockheader() # pop a block res_popblocks = daemon.pop_blocks(1) assert res_popblocks.height == height + blocks - 1 res_info = daemon.get_info() assert res_info.height == height + blocks - 1 # getlastblockheader and by height/hash should return the previous block block_header = res_getblock[blocks - 2].block_header block_header.depth = 0 # this will be different, ignore it res_getlastblockheader = daemon.getlastblockheader() assert res_getlastblockheader.block_header == block_header res_getblockheaderbyhash = daemon.getblockheaderbyhash( block_header.hash) assert res_getblockheaderbyhash.block_header == block_header res_getblockheaderbyheight = daemon.getblockheaderbyheight(height + blocks - 2) assert res_getblockheaderbyheight.block_header == block_header # we should not see the popped block anymore ok = False try: daemon.getblock(height + blocks - 1) except: ok = True assert ok # get transactions res = daemon.get_info() assert res.height == height + blocks - 1 nblocks = height + blocks - 1 res = daemon.getblockheadersrange(0, nblocks - 1) assert len(res.headers) == nblocks assert res.headers[-1] == block_header txids = [x.miner_tx_hash for x in res.headers] res = daemon.get_transactions(txs_hashes=txids) assert len(res.txs) == nblocks assert not 'missed_txs' in res or len(res.missed_txs) == 0 running_output_index = 0 for i in range(len(txids)): tx = res.txs[i] assert tx.tx_hash == txids[i] assert not tx.double_spend_seen assert not tx.in_pool assert tx.block_height == i if i > 0: for idx in tx.output_indices: assert idx == running_output_index running_output_index += 1 res_out = daemon.get_outs([{ 'amount': 0, 'index': idx } for idx in tx.output_indices], get_txid=True) assert len(res_out.outs) == len(tx.output_indices) for out in res_out.outs: assert len(out.key) == 64 assert len(out.mask) == 64 assert not out.unlocked assert out.height == i assert out.txid == txids[i] for i in range(height + nblocks - 1): res_sum = daemon.get_coinbase_tx_sum(i, 1) res_header = daemon.getblockheaderbyheight(i) assert res_sum.emission_amount == res_header.block_header.reward res = daemon.get_coinbase_tx_sum(0, 1) assert res.emission_amount == 17592186044415 assert res.fee_amount == 0 sum_blocks = height + nblocks - 1 res = daemon.get_coinbase_tx_sum(0, sum_blocks) extrapolated = 17592186044415 + 17592186044415 * 2 * (sum_blocks - 1) assert res.emission_amount < extrapolated and res.emission_amount > extrapolated - 1e12 assert res.fee_amount == 0 sum_blocks_emission = res.emission_amount res = daemon.get_coinbase_tx_sum(1, sum_blocks) assert res.emission_amount == sum_blocks_emission - 17592186044415 assert res.fee_amount == 0 res = daemon.get_output_distribution([0, 1, 17592186044415], 0, 0) assert len(res.distributions) == 3 for a in range(3): assert res.distributions[a].amount == [0, 1, 17592186044415][a] assert res.distributions[a].start_height == 0 assert res.distributions[a].base == 0 assert len( res.distributions[a].distribution) == height + nblocks - 1 assert res.distributions[a].binary == False for i in range(height + nblocks - 1): assert res.distributions[a].distribution[i] == ( 1 if i > 0 and a == 0 else 1 if a == 2 and i == 0 else 0) res = daemon.get_output_histogram([], min_count=0, max_count=0) assert len(res.histogram) == 2 for i in range(2): assert res.histogram[i].amount in [0, 17592186044415] assert res.histogram[i].total_instances in [ height + nblocks - 2, 1 ] assert res.histogram[i].unlocked_instances == 0 assert res.histogram[i].recent_instances == 0
def transfer(self): daemon = Daemon() print("Creating transfer to self") dst = {'address': '42ey1afDFnn4886T7196doS9GPMzexD9gXpsZJDwVjeRVdFCSoHnv7KPbBeGpzJBzHRCAs9UxqeoyFQMYbqSWYTfJJQAWDm', 'amount': 1000000000000} payment_id = '1234500000012345abcde00000abcdeff1234500000012345abcde00000abcde' start_balances = [0] * len(self.wallet) running_balances = [0] * len(self.wallet) for i in range(len(self.wallet)): res = self.wallet[i].get_balance() start_balances[i] = res.balance running_balances[i] = res.balance assert res.unlocked_balance <= res.balance if i == 0: assert res.blocks_to_unlock == 59 # we've been mining to it else: assert res.blocks_to_unlock == 0 print ('Checking short payment IDs cannot be used when not in an integrated address') ok = False try: self.wallet[0].transfer([dst], ring_size = 11, payment_id = '1234567812345678', get_tx_key = False) except: ok = True assert ok print ('Checking long payment IDs are rejected') ok = False try: self.wallet[0].transfer([dst], ring_size = 11, payment_id = payment_id, get_tx_key = False, get_tx_hex = True) except: ok = True assert ok print ('Checking empty destination is rejected') ok = False try: self.wallet[0].transfer([], ring_size = 11, get_tx_key = False) except: ok = True assert ok res = self.wallet[0].transfer([dst], ring_size = 11, get_tx_key = False, get_tx_hex = True) assert len(res.tx_hash) == 32*2 txid = res.tx_hash assert len(res.tx_key) == 0 assert res.amount > 0 amount = res.amount assert res.fee > 0 fee = res.fee assert len(res.tx_blob) > 0 tx_weight = res.weight assert len(res.tx_metadata) == 0 assert len(res.multisig_txset) == 0 assert len(res.unsigned_txset) == 0 unsigned_txset = res.unsigned_txset res = daemon.get_fee_estimate(10) assert res.fee > 0 assert res.quantization_mask > 0 expected_fee = (res.fee * 1 * tx_weight + res.quantization_mask - 1) // res.quantization_mask * res.quantization_mask assert abs(1 - fee / expected_fee) < 0.01 self.wallet[0].refresh() res = daemon.get_info() height = res.height res = self.wallet[0].get_transfers() assert len(res['in']) == height - 1 # coinbases assert not 'out' in res or len(res.out) == 0 # not mined yet assert len(res.pending) == 1 assert not 'pool' in res or len(res.pool) == 0 assert not 'failed' in res or len(res.failed) == 0 for e in res['in']: assert e.type == 'block' e = res.pending[0] assert e.txid == txid assert e.payment_id in ['', '0000000000000000'] assert e.type == 'pending' assert e.unlock_time == 0 assert e.subaddr_index.major == 0 assert e.subaddr_indices == [{'major': 0, 'minor': 0}] assert e.address == '42ey1afDFnn4886T7196doS9GPMzexD9gXpsZJDwVjeRVdFCSoHnv7KPbBeGpzJBzHRCAs9UxqeoyFQMYbqSWYTfJJQAWDm' assert e.double_spend_seen == False assert not 'confirmations' in e or e.confirmations == 0 running_balances[0] -= fee res = self.wallet[0].get_balance() assert res.balance == running_balances[0] assert res.unlocked_balance <= res.balance assert res.blocks_to_unlock == 59 daemon.generateblocks('42ey1afDFnn4886T7196doS9GPMzexD9gXpsZJDwVjeRVdFCSoHnv7KPbBeGpzJBzHRCAs9UxqeoyFQMYbqSWYTfJJQAWDm', 1) res = daemon.getlastblockheader() running_balances[0] += res.block_header.reward self.wallet[0].refresh() res = self.wallet[0].get_transfers() assert len(res['in']) == height # coinbases assert len(res.out) == 1 # not mined yet assert not 'pending' in res or len(res.pending) == 0 assert not 'pool' in res or len(res.pool) == 0 assert not 'failed' in res or len(res.failed) == 0 for e in res['in']: assert e.type == 'block' e = res.out[0] assert e.txid == txid assert e.payment_id in ['', '0000000000000000'] assert e.type == 'out' assert e.unlock_time == 0 assert e.subaddr_index.major == 0 assert e.subaddr_indices == [{'major': 0, 'minor': 0}] assert e.address == '42ey1afDFnn4886T7196doS9GPMzexD9gXpsZJDwVjeRVdFCSoHnv7KPbBeGpzJBzHRCAs9UxqeoyFQMYbqSWYTfJJQAWDm' assert e.double_spend_seen == False assert e.confirmations == 1 res = self.wallet[0].get_height() wallet_height = res.height res = self.wallet[0].get_transfer_by_txid(txid) assert len(res.transfers) == 1 assert res.transfers[0] == res.transfer t = res.transfer assert t.txid == txid assert t.payment_id in ['', '0000000000000000'] assert t.height == wallet_height - 1 assert t.timestamp > 0 assert t.amount == 0 # to self, so it's just "pay a fee" really assert t.fee == fee assert t.note == '' assert len(t.destinations) == 1 assert t.destinations[0] == {'address': '42ey1afDFnn4886T7196doS9GPMzexD9gXpsZJDwVjeRVdFCSoHnv7KPbBeGpzJBzHRCAs9UxqeoyFQMYbqSWYTfJJQAWDm', 'amount': 1000000000000} assert t.type == 'out' assert t.unlock_time == 0 assert t.address == '42ey1afDFnn4886T7196doS9GPMzexD9gXpsZJDwVjeRVdFCSoHnv7KPbBeGpzJBzHRCAs9UxqeoyFQMYbqSWYTfJJQAWDm' assert t.double_spend_seen == False assert t.confirmations == 1 res = self.wallet[0].get_balance() assert res.balance == running_balances[0] assert res.unlocked_balance <= res.balance assert res.blocks_to_unlock == 59 print("Creating transfer to another, manual relay") dst = {'address': '44Kbx4sJ7JDRDV5aAhLJzQCjDz2ViLRduE3ijDZu3osWKBjMGkV1XPk4pfDUMqt1Aiezvephdqm6YD19GKFD9ZcXVUTp6BW', 'amount': 1000000000000} res = self.wallet[0].transfer([dst], ring_size = 11, get_tx_key = True, do_not_relay = True, get_tx_hex = True) assert len(res.tx_hash) == 32*2 txid = res.tx_hash assert len(res.tx_key) == 32*2 assert res.amount == 1000000000000 amount = res.amount assert res.fee > 0 fee = res.fee assert len(res.tx_blob) > 0 assert len(res.tx_metadata) == 0 assert len(res.multisig_txset) == 0 assert len(res.unsigned_txset) == 0 tx_blob = res.tx_blob res = daemon.send_raw_transaction(tx_blob) assert res.not_relayed == False assert res.low_mixin == False assert res.double_spend == False assert res.invalid_input == False assert res.invalid_output == False assert res.too_big == False assert res.overspend == False assert res.fee_too_low == False self.wallet[0].refresh() res = self.wallet[0].get_balance() assert res.balance == running_balances[0] assert res.unlocked_balance <= res.balance assert res.blocks_to_unlock == 59 self.wallet[1].refresh() res = self.wallet[1].get_transfers() assert not 'in' in res or len(res['in']) == 0 assert not 'out' in res or len(res.out) == 0 assert not 'pending' in res or len(res.pending) == 0 assert len(res.pool) == 1 assert not 'failed' in res or len(res.failed) == 0 e = res.pool[0] assert e.txid == txid assert e.payment_id in ["", "0000000000000000"] # long payment IDs are now ignored assert e.type == 'pool' assert e.unlock_time == 0 assert e.subaddr_index.major == 0 assert e.subaddr_indices == [{'major': 0, 'minor': 0}] assert e.address == '44Kbx4sJ7JDRDV5aAhLJzQCjDz2ViLRduE3ijDZu3osWKBjMGkV1XPk4pfDUMqt1Aiezvephdqm6YD19GKFD9ZcXVUTp6BW' assert e.double_spend_seen == False assert not 'confirmations' in e or e.confirmations == 0 assert e.amount == amount assert e.fee == fee daemon.generateblocks('42ey1afDFnn4886T7196doS9GPMzexD9gXpsZJDwVjeRVdFCSoHnv7KPbBeGpzJBzHRCAs9UxqeoyFQMYbqSWYTfJJQAWDm', 1) res = daemon.getlastblockheader() running_balances[0] -= 1000000000000 + fee running_balances[0] += res.block_header.reward self.wallet[1].refresh() running_balances[1] += 1000000000000 res = self.wallet[1].get_transfers() assert len(res['in']) == 1 assert not 'out' in res or len(res.out) == 0 assert not 'pending' in res or len(res.pending) == 0 assert not 'pool' in res or len(res.pool) == 0 assert not 'failed' in res or len(res.failed) == 0 e = res['in'][0] assert e.txid == txid assert e.payment_id in ["", "0000000000000000"] # long payment IDs are now ignored assert e.type == 'in' assert e.unlock_time == 0 assert e.subaddr_index.major == 0 assert e.subaddr_indices == [{'major': 0, 'minor': 0}] assert e.address == '44Kbx4sJ7JDRDV5aAhLJzQCjDz2ViLRduE3ijDZu3osWKBjMGkV1XPk4pfDUMqt1Aiezvephdqm6YD19GKFD9ZcXVUTp6BW' assert e.double_spend_seen == False assert e.confirmations == 1 assert e.amount == amount assert e.fee == fee res = self.wallet[1].get_balance() assert res.balance == running_balances[1] assert res.unlocked_balance <= res.balance assert res.blocks_to_unlock == 9 print('Creating multi out transfer') self.wallet[0].refresh() dst0 = {'address': '42ey1afDFnn4886T7196doS9GPMzexD9gXpsZJDwVjeRVdFCSoHnv7KPbBeGpzJBzHRCAs9UxqeoyFQMYbqSWYTfJJQAWDm', 'amount': 1000000000000} dst1 = {'address': '44Kbx4sJ7JDRDV5aAhLJzQCjDz2ViLRduE3ijDZu3osWKBjMGkV1XPk4pfDUMqt1Aiezvephdqm6YD19GKFD9ZcXVUTp6BW', 'amount': 1100000000000} dst2 = {'address': '46r4nYSevkfBUMhuykdK3gQ98XDqDTYW1hNLaXNvjpsJaSbNtdXh1sKMsdVgqkaihChAzEy29zEDPMR3NHQvGoZCLGwTerK', 'amount': 1200000000000} res = self.wallet[0].transfer([dst0, dst1, dst2], ring_size = 11, get_tx_key = True) assert len(res.tx_hash) == 32*2 txid = res.tx_hash assert len(res.tx_key) == 32*2 assert res.amount == 1000000000000 + 1100000000000 + 1200000000000 amount = res.amount assert res.fee > 0 fee = res.fee assert len(res.tx_blob) == 0 assert len(res.tx_metadata) == 0 assert len(res.multisig_txset) == 0 assert len(res.unsigned_txset) == 0 unsigned_txset = res.unsigned_txset running_balances[0] -= 1100000000000 + 1200000000000 + fee res = self.wallet[0].get_balance() assert res.balance == running_balances[0] assert res.unlocked_balance <= res.balance assert res.blocks_to_unlock == 59 daemon.generateblocks('42ey1afDFnn4886T7196doS9GPMzexD9gXpsZJDwVjeRVdFCSoHnv7KPbBeGpzJBzHRCAs9UxqeoyFQMYbqSWYTfJJQAWDm', 1) res = daemon.getlastblockheader() running_balances[0] += res.block_header.reward running_balances[1] += 1100000000000 running_balances[2] += 1200000000000 self.wallet[0].refresh() res = self.wallet[0].get_transfers() assert len(res['in']) == height + 2 assert len(res.out) == 3 assert not 'pending' in res or len(res.pending) == 0 assert not 'pool' in res or len(res.pool) == 1 assert not 'failed' in res or len(res.failed) == 0 e = [o for o in res.out if o.txid == txid] assert len(e) == 1 e = e[0] assert e.txid == txid assert e.payment_id in ["", "0000000000000000"] # long payment IDs are now ignored assert e.type == 'out' assert e.unlock_time == 0 assert e.subaddr_index.major == 0 assert e.subaddr_indices == [{'major': 0, 'minor': 0}] assert e.address == '42ey1afDFnn4886T7196doS9GPMzexD9gXpsZJDwVjeRVdFCSoHnv7KPbBeGpzJBzHRCAs9UxqeoyFQMYbqSWYTfJJQAWDm' assert e.double_spend_seen == False assert e.confirmations == 1 assert e.amount == amount assert e.fee == fee res = self.wallet[0].get_balance() assert res.balance == running_balances[0] assert res.unlocked_balance <= res.balance assert res.blocks_to_unlock == 59 self.wallet[1].refresh() res = self.wallet[1].get_transfers() assert len(res['in']) == 2 assert not 'out' in res or len(res.out) == 0 assert not 'pending' in res or len(res.pending) == 0 assert not 'pool' in res or len(res.pool) == 0 assert not 'failed' in res or len(res.failed) == 0 e = [o for o in res['in'] if o.txid == txid] assert len(e) == 1 e = e[0] assert e.txid == txid assert e.payment_id in ["", "0000000000000000"] # long payment IDs are now ignored assert e.type == 'in' assert e.unlock_time == 0 assert e.subaddr_index.major == 0 assert e.subaddr_indices == [{'major': 0, 'minor': 0}] assert e.address == '44Kbx4sJ7JDRDV5aAhLJzQCjDz2ViLRduE3ijDZu3osWKBjMGkV1XPk4pfDUMqt1Aiezvephdqm6YD19GKFD9ZcXVUTp6BW' assert e.double_spend_seen == False assert e.confirmations == 1 assert e.amount == 1100000000000 assert e.fee == fee res = self.wallet[1].get_balance() assert res.balance == running_balances[1] assert res.unlocked_balance <= res.balance assert res.blocks_to_unlock == 9 self.wallet[2].refresh() res = self.wallet[2].get_transfers() assert len(res['in']) == 1 assert not 'out' in res or len(res.out) == 0 assert not 'pending' in res or len(res.pending) == 0 assert not 'pool' in res or len(res.pool) == 0 assert not 'failed' in res or len(res.failed) == 0 e = [o for o in res['in'] if o.txid == txid] assert len(e) == 1 e = e[0] assert e.txid == txid assert e.payment_id in ["", "0000000000000000"] # long payment IDs are now ignored assert e.type == 'in' assert e.unlock_time == 0 assert e.subaddr_index.major == 0 assert e.subaddr_indices == [{'major': 0, 'minor': 0}] assert e.address == '46r4nYSevkfBUMhuykdK3gQ98XDqDTYW1hNLaXNvjpsJaSbNtdXh1sKMsdVgqkaihChAzEy29zEDPMR3NHQvGoZCLGwTerK' assert e.double_spend_seen == False assert e.confirmations == 1 assert e.amount == 1200000000000 assert e.fee == fee res = self.wallet[2].get_balance() assert res.balance == running_balances[2] assert res.unlocked_balance <= res.balance assert res.blocks_to_unlock == 9 print('Sending to integrated address') self.wallet[0].refresh() res = self.wallet[0].get_balance() i_pid = '1111111122222222' res = self.wallet[0].make_integrated_address(standard_address = '44Kbx4sJ7JDRDV5aAhLJzQCjDz2ViLRduE3ijDZu3osWKBjMGkV1XPk4pfDUMqt1Aiezvephdqm6YD19GKFD9ZcXVUTp6BW', payment_id = i_pid) i_address = res.integrated_address res = self.wallet[0].transfer([{'address': i_address, 'amount': 200000000}]) assert len(res.tx_hash) == 32*2 i_txid = res.tx_hash assert len(res.tx_key) == 32*2 assert res.amount == 200000000 i_amount = res.amount assert res.fee > 0 fee = res.fee assert len(res.tx_blob) == 0 assert len(res.tx_metadata) == 0 assert len(res.multisig_txset) == 0 assert len(res.unsigned_txset) == 0 running_balances[0] -= 200000000 + fee res = self.wallet[0].get_balance() assert res.balance == running_balances[0] assert res.unlocked_balance <= res.balance assert res.blocks_to_unlock == 59 daemon.generateblocks('42ey1afDFnn4886T7196doS9GPMzexD9gXpsZJDwVjeRVdFCSoHnv7KPbBeGpzJBzHRCAs9UxqeoyFQMYbqSWYTfJJQAWDm', 1) res = daemon.getlastblockheader() running_balances[0] += res.block_header.reward running_balances[1] += 200000000 self.wallet[0].refresh() res = self.wallet[0].get_balance() assert res.balance == running_balances[0] assert res.unlocked_balance <= res.balance assert res.blocks_to_unlock == 59 self.wallet[1].refresh() res = self.wallet[1].get_balance() assert res.balance == running_balances[1] assert res.unlocked_balance <= res.balance assert res.blocks_to_unlock == 9 self.wallet[2].refresh() res = self.wallet[2].get_balance() assert res.balance == running_balances[2] assert res.unlocked_balance <= res.balance assert res.blocks_to_unlock == 8 daemon.generateblocks('42ey1afDFnn4886T7196doS9GPMzexD9gXpsZJDwVjeRVdFCSoHnv7KPbBeGpzJBzHRCAs9UxqeoyFQMYbqSWYTfJJQAWDm', 1) res = daemon.getlastblockheader() running_balances[0] += res.block_header.reward self.wallet[0].refresh() res = self.wallet[0].get_balance() assert res.balance == running_balances[0] assert res.unlocked_balance <= res.balance assert res.blocks_to_unlock == 59 self.wallet[1].refresh() res = self.wallet[1].get_balance() assert res.balance == running_balances[1] assert res.unlocked_balance <= res.balance assert res.blocks_to_unlock == 8 self.wallet[2].refresh() res = self.wallet[2].get_balance() assert res.balance == running_balances[2] assert res.unlocked_balance <= res.balance assert res.blocks_to_unlock == 7
def check_reserve_proof(self): daemon = Daemon() print('Checking reserve proof') address0 = '42ey1afDFnn4886T7196doS9GPMzexD9gXpsZJDwVjeRVdFCSoHnv7KPbBeGpzJBzHRCAs9UxqeoyFQMYbqSWYTfJJQAWDm' address1 = '44Kbx4sJ7JDRDV5aAhLJzQCjDz2ViLRduE3ijDZu3osWKBjMGkV1XPk4pfDUMqt1Aiezvephdqm6YD19GKFD9ZcXVUTp6BW' self.wallet[0].refresh() res = self.wallet[0].get_balance() balance0 = res.balance self.wallet[1].refresh() res = self.wallet[1].get_balance() balance1 = res.balance res = self.wallet[0].get_reserve_proof(all_=True, message='foo') assert res.signature.startswith('ReserveProof') signature = res.signature for i in range(2): res = self.wallet[i].check_reserve_proof(address=address0, message='foo', signature=signature) assert res.good assert res.total == balance0 ok = False try: res = self.wallet[i].check_reserve_proof(address=address0, message='bar', signature=signature) except: ok = True assert ok or not res.good ok = False try: res = self.wallet[i].check_reserve_proof(address=address1, message='foo', signature=signature) except: ok = True assert ok or not res.good amount = int(balance0 / 10) res = self.wallet[0].get_reserve_proof(all_=False, amount=amount, message='foo') assert res.signature.startswith('ReserveProof') signature = res.signature for i in range(2): res = self.wallet[i].check_reserve_proof(address=address0, message='foo', signature=signature) assert res.good assert res.total >= amount and res.total <= balance0 ok = False try: res = self.wallet[i].check_reserve_proof(address=address0, message='bar', signature=signature) except: ok = True assert ok or not res.good ok = False try: res = self.wallet[i].check_reserve_proof(address=address1, message='foo', signature=signature) except: ok = True assert ok or not res.good ok = False try: self.wallet[0].get_reserve_proof(all_=False, amount=balance0 + 1, message='foo') except: ok = True assert ok
def transfer(self, signers): assert len(signers) >= 2 daemon = Daemon() print("Creating multisig transaction from wallet " + str(signers[0])) dst = { 'address': '42ey1afDFnn4886T7196doS9GPMzexD9gXpsZJDwVjeRVdFCSoHnv7KPbBeGpzJBzHRCAs9UxqeoyFQMYbqSWYTfJJQAWDm', 'amount': 1000000000000 } res = self.wallet[signers[0]].transfer([dst]) assert len(res.tx_hash) == 0 # not known yet txid = res.tx_hash assert len(res.tx_key) == 32 * 2 assert res.amount > 0 amount = res.amount assert res.fee > 0 fee = res.fee assert len(res.tx_blob) == 0 assert len(res.tx_metadata) == 0 assert len(res.multisig_txset) > 0 assert len(res.unsigned_txset) == 0 multisig_txset = res.multisig_txset daemon.generateblocks( '42ey1afDFnn4886T7196doS9GPMzexD9gXpsZJDwVjeRVdFCSoHnv7KPbBeGpzJBzHRCAs9UxqeoyFQMYbqSWYTfJJQAWDm', 1) for i in range(len(self.wallet)): self.wallet[i].refresh() for i in range(len(signers[1:])): print('Signing multisig transaction with wallet ' + str(signers[i + 1])) res = self.wallet[signers[i + 1]].describe_transfer( multisig_txset=multisig_txset) assert len(res.desc) == 1 desc = res.desc[0] assert desc.amount_in >= amount + fee assert desc.amount_out == desc.amount_in - fee assert desc.ring_size == 11 assert desc.unlock_time == 0 assert desc.payment_id == '0000000000000000' assert desc.change_amount == desc.amount_in - 1000000000000 - fee assert desc.change_address == self.wallet_address assert desc.fee == fee assert len(desc.recipients) == 1 rec = desc.recipients[0] assert rec.address == '42ey1afDFnn4886T7196doS9GPMzexD9gXpsZJDwVjeRVdFCSoHnv7KPbBeGpzJBzHRCAs9UxqeoyFQMYbqSWYTfJJQAWDm' assert rec.amount == 1000000000000 res = self.wallet[signers[i + 1]].sign_multisig(multisig_txset) multisig_txset = res.tx_data_hex assert len(res.tx_hash_list if 'tx_hash_list' in res else []) == ( i == len(signers[1:]) - 1) if i < len(signers[1:]) - 1: print( 'Submitting multisig transaction prematurely with wallet ' + str(signers[-1])) ok = False try: self.wallet[signers[-1]].submit_multisig(multisig_txset) except: ok = True assert ok print('Submitting multisig transaction with wallet ' + str(signers[-1])) res = self.wallet[signers[-1]].submit_multisig(multisig_txset) assert len(res.tx_hash_list) == 1 txid = res.tx_hash_list[0] for i in range(len(self.wallet)): self.wallet[i].refresh() res = self.wallet[i].get_transfers() assert len([ x for x in (res['pending'] if 'pending' in res else []) if x.txid == txid ]) == (1 if i == signers[-1] else 0) assert len([ x for x in (res['out'] if 'out' in res else []) if x.txid == txid ]) == 0 daemon.generateblocks( '42ey1afDFnn4886T7196doS9GPMzexD9gXpsZJDwVjeRVdFCSoHnv7KPbBeGpzJBzHRCAs9UxqeoyFQMYbqSWYTfJJQAWDm', 1) return txid
def mine(self): print("Test mining") daemon = Daemon() wallet = Wallet() # check info/height/balance before generating blocks res_info = daemon.get_info() prev_height = res_info.height res_getbalance = wallet.get_balance() prev_balance = res_getbalance.balance res_status = daemon.mining_status() res = daemon.start_mining('42ey1afDFnn4886T7196doS9GPMzexD9gXpsZJDwVjeRVdFCSoHnv7KPbBeGpzJBzHRCAs9UxqeoyFQMYbqSWYTfJJQAWDm', threads_count = 1) res_status = daemon.mining_status() assert res_status.active == True assert res_status.threads_count == 1 assert res_status.address == '42ey1afDFnn4886T7196doS9GPMzexD9gXpsZJDwVjeRVdFCSoHnv7KPbBeGpzJBzHRCAs9UxqeoyFQMYbqSWYTfJJQAWDm' assert res_status.is_background_mining_enabled == False assert res_status.block_reward >= 600000000000 # wait till we mined a few of them timeout = 5 timeout_height = prev_height while True: time.sleep(1) res_info = daemon.get_info() height = res_info.height if height >= prev_height + 5: break if height > timeout_height: timeout = 5 timeout_height = height else: timeout -= 1 assert timeout >= 0 res = daemon.stop_mining() res_status = daemon.mining_status() assert res_status.active == False res_info = daemon.get_info() new_height = res_info.height wallet.refresh() res_getbalance = wallet.get_balance() balance = res_getbalance.balance assert balance >= prev_balance + (new_height - prev_height) * 600000000000 res = daemon.start_mining('42ey1afDFnn4886T7196doS9GPMzexD9gXpsZJDwVjeRVdFCSoHnv7KPbBeGpzJBzHRCAs9UxqeoyFQMYbqSWYTfJJQAWDm', threads_count = 1, do_background_mining = True) res_status = daemon.mining_status() assert res_status.active == True assert res_status.threads_count == 1 assert res_status.address == '42ey1afDFnn4886T7196doS9GPMzexD9gXpsZJDwVjeRVdFCSoHnv7KPbBeGpzJBzHRCAs9UxqeoyFQMYbqSWYTfJJQAWDm' assert res_status.is_background_mining_enabled == True assert res_status.block_reward >= 600000000000 # don't wait, might be a while if the machine is busy, which it probably is res = daemon.stop_mining() res_status = daemon.mining_status() assert res_status.active == False