def test_utxo_reuse(helpers, addresses, initial_mint): # Reproducing a test from libsovtoken address1, address2, address3, _, _ = addresses mint_seq_no = get_seq_no(initial_mint) inputs = [ { "source": utxo_from_addr_and_seq_no(address1, mint_seq_no) }, ] outputs = [ { "address": address1, "amount": 100 }, ] request = helpers.request.transfer(inputs, outputs) helpers.sdk.send_and_check_request_objects([request]) inputs = [ { "source": utxo_from_addr_and_seq_no(address2, mint_seq_no) }, { "source": utxo_from_addr_and_seq_no(address1, mint_seq_no) }, ] outputs = [ { "address": address3, "amount": 100 }, ] request = helpers.request.transfer(inputs, outputs) with pytest.raises(RequestRejectedException): helpers.sdk.send_and_check_request_objects([request])
def test_send_claim_def_with_fees(helpers, looper, nodeSetWithIntegratedTokenPlugin, sdk_wallet_trustee, sdk_pool_handle, schema_json, fees_set, address_main, mint_tokens): req = helpers.request.claim_def(schema_json, sdk_wallet=sdk_wallet_trustee) amount = get_amount_from_token_txn(mint_tokens) init_seq_no = 1 utxos = [{"source": utxo_from_addr_and_seq_no(address_main, init_seq_no), AMOUNT: amount}] req = Request(**json.loads(req)) req = add_fees_request_with_address( helpers, fees_set, req, address_main, utxos=utxos ) token_len = len(nodeSetWithIntegratedTokenPlugin[0].ledgers[-1]) write_rep = helpers.sdk.send_and_check_request_objects([req], wallet=sdk_wallet_trustee) assert token_len == len(nodeSetWithIntegratedTokenPlugin[0].ledgers[-1]) - 1 assert get_last_token_txn(nodeSetWithIntegratedTokenPlugin)[1]['txn']['data']['fees'] == CLAIM_DEF_FEE added_claim_def_id = write_rep[0][1]['result'][TXN_METADATA][TXN_METADATA_ID] request = looper.loop.run_until_complete(build_get_cred_def_request(sdk_wallet_trustee[1], added_claim_def_id)) read_rep = sdk_get_and_check_replies(looper, [sdk_sign_and_submit_req(sdk_pool_handle, sdk_wallet_trustee, request)]) assert req.operation[DATA] == read_rep[0][1]['result'][DATA]
def test_create_did_without_endorser_payment(looper, nodeSetWithIntegratedTokenPlugin, nym_txn_data, sdk_pool_handle, fees_set, address_main, mint_tokens, changed_auth_rule, sdk_wallet_trustee, helpers): sdk_add_new_nym(looper, sdk_pool_handle, sdk_wallet_trustee) wh, alias, sender_did, sender_verkey = nym_txn_data req = looper.loop.run_until_complete( build_nym_request(sender_did, sender_did, sender_verkey, alias, NEW_ROLE)) amount = get_amount_from_token_txn(mint_tokens) init_seq_no = 1 utxos = [{"source": utxo_from_addr_and_seq_no(address_main, init_seq_no), AMOUNT: amount}] req = Request(**json.loads(req)) req = add_fees_request_with_address( helpers, fees_set, req, address_main, utxos=utxos ) rep = helpers.sdk.send_and_check_request_objects([req], wallet=(wh, sender_did)) details = get_nym_details(nodeSetWithIntegratedTokenPlugin[0].states[1], sender_did, is_committed=True) assert details[ROLE] == NEW_ROLE assert details[VERKEY] == sender_verkey
def test_send_nym_with_fees(helpers, looper, nodeSetWithIntegratedTokenPlugin, sdk_wallet_trustee, sdk_wallet_steward, sdk_pool_handle, fees_set, address_main, mint_tokens): req = helpers.request.nym_new(sdk_wallet=sdk_wallet_trustee) amount = get_amount_from_token_txn(mint_tokens) init_seq_no = 1 utxos = [{ "source": utxo_from_addr_and_seq_no(address_main, init_seq_no), AMOUNT: amount }] req = Request(**json.loads(req)) req = add_fees_request_with_address(helpers, fees_set, req, address_main, utxos=utxos) token_len = len(nodeSetWithIntegratedTokenPlugin[0].ledgers[-1]) helpers.sdk.send_and_check_request_objects([req], wallet=sdk_wallet_trustee) assert token_len == len( nodeSetWithIntegratedTokenPlugin[0].ledgers[-1]) - 1 assert get_last_token_txn( nodeSetWithIntegratedTokenPlugin)[1]['txn']['data']['fees'] == NYM_FEE request = looper.loop.run_until_complete( build_get_nym_request(sdk_wallet_trustee[1], req.operation['dest'])) read_rep = sdk_get_and_check_replies(looper, [ sdk_sign_and_submit_req(sdk_pool_handle, sdk_wallet_trustee, request) ]) reply = json.loads(read_rep[0][1]['result'][DATA]) assert req.operation['dest'] == reply['dest'] assert req.operation['verkey'] == reply['verkey']
def test_non_existent_input_non_xfer(helpers, fees_authorizer): """ Expect an InvalidFundsError on a nym request with inputs which don't contain a valid utxo. """ helpers.general.do_set_fees(VALID_FEES) utxos = [{ "source": utxo_from_addr_and_seq_no(helpers.wallet.create_address(), 1), AMOUNT: 291 }] request = helpers.request.nym() request = helpers.request.add_fees(request, utxos, 10)[0] request = json.loads(request) fees = request[FEES] request = helpers.sdk.sdk_json_to_request_object(request) setattr(request, FEES, fees) authorized, error = fees_authorizer.can_pay_fees( request, required_fees=VALID_FEES.get(NYM_FEES_ALIAS)) assert not authorized assert 'was not found' in error
def test_token_req_handler_apply_xfer_public_success(helpers, addresses, xfer_handler_a): [address1, address2] = addresses inputs = [{"source": utxo_from_addr_and_seq_no(address2, 1)}] outputs = [{ "address": address1, "amount": 30 }, { "address": address2, "amount": 30 }] request = helpers.request.transfer(inputs, outputs) # test xfer now address1 = libsovtoken_address_to_address(address1) address2 = libsovtoken_address_to_address(address2) utxo_cache = xfer_handler_a.database_manager.get_store(UTXO_CACHE_LABEL) pre_apply_outputs_addr_1 = utxo_cache.get_unspent_outputs(address1) pre_apply_outputs_addr_2 = utxo_cache.get_unspent_outputs(address2) assert pre_apply_outputs_addr_1 == [Output(address1, 1, 40)] assert pre_apply_outputs_addr_2 == [Output(address2, 1, 60)] xfer_handler_a.apply_request(request, CONS_TIME, None) post_apply_outputs_addr_1 = utxo_cache.get_unspent_outputs(address1) post_apply_outputs_addr_2 = utxo_cache.get_unspent_outputs(address2) assert post_apply_outputs_addr_1 == [ Output(address1, 1, 40), Output(address1, 2, 30) ] assert post_apply_outputs_addr_2 == [Output(address2, 2, 30)]
def nyms_with_fees(req_count, helpers, fees_set, address_main, all_amount, init_seq_no): amount = all_amount seq_no = init_seq_no fee_amount = fees_set[FEES].get(NYM_FEES_ALIAS, 0) reqs = [] for i in range(req_count): req = helpers.request.nym() if fee_amount: utxos = [{"source": utxo_from_addr_and_seq_no(address_main, seq_no), AMOUNT: amount}] req = add_fees_request_with_address( helpers, fees_set, req, address_main, utxos=utxos ) seq_no += 1 amount -= fee_amount reqs.append(req) return reqs
def test_token_req_handler_commit_success( helpers, addresses, token_handler_b, nodeSet ): [address1, address2] = addresses inputs = [{"source": utxo_from_addr_and_seq_no(address1, 1)}] outputs = [{"address": address1, "amount": 30}, {"address": address2, "amount": 30}] request = helpers.request.transfer(inputs, outputs) # apply transaction state_root = nodeSet[1].master_replica.stateRootHash(TOKEN_LEDGER_ID) txn_root = nodeSet[1].master_replica.txnRootHash(TOKEN_LEDGER_ID) token_handler_b.apply(request, CONS_TIME) address1 = address1.replace("pay:sov:", "") address2 = address2.replace("pay:sov:", "") new_state_root = nodeSet[1].master_replica.stateRootHash(TOKEN_LEDGER_ID) new_txn_root = nodeSet[1].master_replica.txnRootHash(TOKEN_LEDGER_ID) # add batch token_handler_b.onBatchCreated(base58.b58decode(new_state_root.encode()), CONS_TIME) # commit batch assert token_handler_b.utxo_cache.get_unspent_outputs(address1, True) == [Output(address1, 1, 40)] assert token_handler_b.utxo_cache.get_unspent_outputs(address2, True) == [Output(address2, 1, 60)] commit_ret_val = token_handler_b.commit(1, new_state_root, new_txn_root, None) assert token_handler_b.utxo_cache.get_unspent_outputs(address1, True) == [Output(address1, 2, 30)] assert token_handler_b.utxo_cache.get_unspent_outputs(address2, True) == [ Output(address2, 1, 60), Output(address2, 2, 30) ] assert new_state_root != state_root assert new_txn_root != txn_root
def test_incorrect_funds(helpers, addresses, initial_mint): # Test doing lot of invalid (incorrect funds) txns and then finally # a valid txn to make sure the pool works. _, _, _, address4, address5 = addresses mint_seq_no = get_seq_no(initial_mint) inputs = [ { "source": utxo_from_addr_and_seq_no(address4, mint_seq_no) }, ] for i in range(200): if i < 100: amount = randint(1, 99) else: amount = randint(101, 200) outputs = [ { "address": address5, "amount": amount }, ] request = helpers.request.transfer(inputs, outputs) with pytest.raises(RequestRejectedException): helpers.sdk.send_and_check_request_objects([request]) outputs = [ { "address": address5, "amount": 100 }, ] request = helpers.request.transfer(inputs, outputs) helpers.sdk.send_and_check_request_objects([request])
def test_token_req_handler_validate_XFER_PUBLIC_invalid( helpers, addresses, xfer_handler_a): [address1, address2] = addresses inputs = [{"source": utxo_from_addr_and_seq_no(address2, 2)}] outputs = [{"address": address1, "amount": 40}] request = helpers.request.transfer(inputs, outputs) # This test should raise an issue because the inputs are not on the ledger with pytest.raises(InvalidClientMessageException): xfer_handler_a.dynamic_validation(request)
def test_token_req_handler_get_result_invalid_txn_type(helpers, addresses, get_utxo_handler): [address1, address2] = addresses inputs = [{"source": utxo_from_addr_and_seq_no(address1, 1)}] outputs = [{"address": address2, "amount": 40}] request = helpers.request.transfer(inputs, outputs) # A KeyError is expected because get_results can only handle query transaction types with pytest.raises(KeyError): get_utxo_handler.get_result(request)
def test_xfer_breakdown_and_consolidate(helpers, addresses): """ Breakdown utxo into separate utxos with different sequence numbers and then combine them. """ amount = 10 [address1, address2] = addresses # Mint an extra token, so all xfer requests can have a change value. outputs = [{ADDRESS: address1, AMOUNT: amount + 1}] mint_result = helpers.general.do_mint(outputs) seq_no = get_seq_no(mint_result) xfer_seq_no = seq_no + 1 for change in range(0, amount): inputs = [{"source": utxo_from_addr_and_seq_no(address1, seq_no)}] outputs = [ {ADDRESS: address2, AMOUNT: 1}, {ADDRESS: address1, AMOUNT: amount - change} ] result = helpers.general.do_transfer(inputs, outputs) seq_no = get_seq_no(result) utxos = helpers.general.get_utxo_addresses([address2])[0] for seq_no in range(xfer_seq_no, xfer_seq_no + amount): assert utxos[seq_no - xfer_seq_no][PAYMENT_ADDRESS] == address2 assert utxos[seq_no - xfer_seq_no][AMOUNT] == 1 expected_utxos = [ {"source": utxo_from_addr_and_seq_no(address2, seq_no)} for seq_no in range(xfer_seq_no, xfer_seq_no + amount) ] outputs = [{ADDRESS: address2, AMOUNT: amount}] result = helpers.general.do_transfer(expected_utxos, outputs) utxos = helpers.general.get_utxo_addresses([address2])[0] assert utxos[0][PAYMENT_ADDRESS] == address2 assert utxos[0][AMOUNT] == amount
def test_token_req_handler_validate_XFER_PUBLIC_invalid_underspend( helpers, addresses, token_handler_a ): [address1, address2] = addresses inputs = [{"source": utxo_from_addr_and_seq_no(address2, 1)}] outputs = [{"address": address1, "amount": 1}, {"address": address2, "amount": 1}] request = helpers.request.transfer(inputs, outputs) # This test is expected to fail because with pytest.raises(ExtraFundsError): token_handler_a.validate(request)
def req_with_fees(helpers, fees_set, address_main, fees): request = helpers.request.nym() utxos = [{ "source": utxo_from_addr_and_seq_no(address_main, 1), AMOUNT: fees.get(NYM_FEES_ALIAS) }] return add_fees_request_with_address( helpers, fees_set, request, address_main, utxos=utxos, )
def test_token_req_handler_validate_XFER_PUBLIC_success( helpers, addresses, token_handler_a ): [address1, address2] = addresses inputs = [{"source": utxo_from_addr_and_seq_no(address2, 1)}] outputs = [{"address": address1, "amount": 40}, {"address": address2, "amount": 20}] request = helpers.request.transfer(inputs, outputs) try: token_handler_a.validate(request) except Exception: pytest.fail("This test failed to validate")
def test_token_req_handler_apply_xfer_public_invalid( helpers, addresses, token_handler_a ): [address1, address2] = addresses inputs = [{"source": utxo_from_addr_and_seq_no(address2, 3)}] outputs = [{"address": address1, "amount": 40}, {"address": address2, "amount": 20}] request = helpers.request.transfer(inputs, outputs) # test xfer now # This raises a OperationError because the input transaction isn't already in the UTXO_Cache with pytest.raises(OperationError): token_handler_a.apply(request, CONS_TIME)
def prepare_inputs(helpers, addresses, strategy=InputsStrategy.all_utxos): assert strategy in InputsStrategy, "Unknown input strategy {}".format( strategy) addresses = [ helpers.wallet.address_map[addr.replace("pay:sov:", "")] for addr in addresses ] inputs = [] if strategy == InputsStrategy.all_utxos: for addr in addresses: if not addr.all_seq_nos: raise ValueError("no seq_nos for {}".format(addr.address)) for seq_no in addr.all_seq_nos: inputs.append({ "source": utxo_from_addr_and_seq_no(addr.address, seq_no), ADDRESS: addr.address, SEQNO: seq_no }) else: # InputsStrategy.first_utxo_only for addr in addresses: if not addr.all_seq_nos: raise ValueError("no seq_nos for {}".format(addr.address)) inputs.append({ "source": utxo_from_addr_and_seq_no(addr.address, addr.all_seq_nos[0]), ADDRESS: addr.address, SEQNO: addr.all_seq_nos[0] }) return inputs
def test_token_req_handler_doStaticValidation_XFER_PUBLIC_success( helpers, addresses, token_handler_a ): [address1, address2] = addresses inputs = [{"source": utxo_from_addr_and_seq_no(address2, 1)}] outputs = [{"address": address1, "amount": 40}, {"address": address2, "amount": 20}] request = helpers.request.transfer(inputs, outputs) try: token_handler_a.doStaticValidation(request) except InvalidClientRequest: pytest.fail("This test failed because error is not None") except Exception: pytest.fail("This test failed outside the doStaticValidation method")
def test_token_req_handler_validate_XFER_PUBLIC_invalid_overspend( helpers, addresses, xfer_handler_a): [address1, address2] = addresses inputs = [{"source": utxo_from_addr_and_seq_no(address2, 1)}] outputs = [{ "address": address1, "amount": 40 }, { "address": address2, "amount": 40 }] request = helpers.request.transfer(inputs, outputs) # This test is expected to fail because with pytest.raises(InsufficientFundsError): xfer_handler_a.dynamic_validation(request)
def test_authenticate_xfer_with_taa(helpers, node, addresses): [SF_address, user1_address] = addresses token_authnr = TokenAuthNr(node[0].states[DOMAIN_LEDGER_ID]) inputs = [{"source": utxo_from_addr_and_seq_no(SF_address, 1)}] outputs = [{ "address": user1_address, "amount": 10 }, { "address": SF_address, "amount": 10 }] extra = helpers.request.add_transaction_author_agreement_to_extra( None, "text", "mechanism", "version") request = helpers.request.transfer(inputs, outputs, extra) req_data = request.as_dict token_authnr.authenticate_xfer(req_data, AddressSigVerifier)
def test_valid_txn_with_fees(helpers, mint_tokens, fees_set, nodeSetWithIntegratedTokenPlugin, looper, address_main, addresses, tdir, tconf): seq_no = get_seq_no(mint_tokens) remaining = 1000 last_node = nodeSetWithIntegratedTokenPlugin[-1] last_node.cleanupOnStopping = False last_node.stop() looper.removeProdable(last_node) nodeSetWithIntegratedTokenPlugin = nodeSetWithIntegratedTokenPlugin[:-1] for address in addresses: inputs = [{ "source": utxo_from_addr_and_seq_no(address_main, seq_no) }] outputs = [ {ADDRESS: address, AMOUNT: 1}, {ADDRESS: address_main, AMOUNT: remaining - 2}, # XFER fee is 1 ] request = helpers.request.transfer(inputs, outputs) response = helpers.sdk.send_and_check_request_objects([request]) result = helpers.sdk.get_first_result(response) seq_no = get_seq_no(result) remaining -= 2 for _ in range(5): pay_fees(helpers, fees_set, address_main) config_helper = NodeConfigHelper(last_node.name, tconf, chroot=tdir) restarted_node = TestNode(last_node.name, config_helper=config_helper, config=tconf, ha=last_node.nodestack.ha, cliha=last_node.clientstack.ha) integrate_token_plugin_in_node(restarted_node) integrate_fees_plugin_in_node(restarted_node) tl = restarted_node.getLedger(TOKEN_LEDGER_ID) for node in nodeSetWithIntegratedTokenPlugin: token_ledger = node.getLedger(TOKEN_LEDGER_ID) assert token_ledger.size > tl.size looper.add(restarted_node) nodeSetWithIntegratedTokenPlugin.append(restarted_node) ensure_all_nodes_have_same_data(looper, nodeSetWithIntegratedTokenPlugin)
def prepare_inputs( helpers, addresses, strategy=InputsStrategy.all_utxos ): assert strategy in InputsStrategy, "Unknown input strategy {}".format(strategy) inputs = [] addresses = [helpers.wallet.address_map[addr] for addr in addresses] for addr in addresses: if not addr.all_seq_nos: raise ValueError("no seq_nos for {}".format(addr.address)) for seq_no in addr.all_seq_nos: inputs.append( {"source": utxo_from_addr_and_seq_no(addr.address, seq_no), ADDRESS: addr.address, SEQNO: seq_no}) if strategy == InputsStrategy.first_utxo_only: break return inputs
def test_authenticate_calls_authenticate_xfer(helpers, node, addresses): [SF_address, user1_address] = addresses token_authnr = TokenAuthNr(node[0].states[DOMAIN_LEDGER_ID]) inputs = [{"source": utxo_from_addr_and_seq_no(SF_address, 1)}] outputs = [{ "address": user1_address, "amount": 10 }, { "address": SF_address, "amount": 10 }] request = helpers.request.transfer(inputs, outputs) req_data = request.as_dict token_authnr.authenticate_xfer = mock.Mock() token_authnr.authenticate(req_data) token_authnr.authenticate_xfer.assert_called()
def test_authenticate_xfer_with_extra(helpers, node, addresses): [SF_address, user1_address] = addresses token_authnr = TokenAuthNr(node[0].states[DOMAIN_LEDGER_ID]) inputs = [{"source": utxo_from_addr_and_seq_no(SF_address, 1)}] outputs = [{ "address": user1_address, "amount": 10 }, { "address": SF_address, "amount": 10 }] request = helpers.request.transfer(inputs, outputs, extra=json.dumps({"aaa": "bbb"})) req_data = request.as_dict token_authnr.authenticate_xfer(req_data, AddressSigVerifier)
def test_authenticate_xfer_with_extra_not_signed(helpers, node, addresses): [SF_address, user1_address] = addresses token_authnr = TokenAuthNr(node[0].states[DOMAIN_LEDGER_ID]) inputs = [{"source": utxo_from_addr_and_seq_no(SF_address, 1)}] outputs = [{ "address": user1_address, "amount": 10 }, { "address": SF_address, "amount": 10 }] request = helpers.request.transfer(inputs, outputs) req_data = request.as_dict token_authnr.authenticate_xfer(req_data, AddressSigVerifier) req_data[OPERATION][EXTRA] = {"aaa": "bbb"} with pytest.raises(InsufficientCorrectSignatures): token_authnr.authenticate_xfer(req_data, AddressSigVerifier)
def test_authenticate_xfer_with_taa(helpers, node, addresses): [SF_address, user1_address] = addresses token_authnr = TokenAuthNr(ACCEPTABLE_WRITE_TYPES, ACCEPTABLE_QUERY_TYPES, ACCEPTABLE_ACTION_TYPES, node[0].db_manager.idr_cache) inputs = [{"source": utxo_from_addr_and_seq_no(SF_address, 1)}] outputs = [{ "address": user1_address, "amount": 10 }, { "address": SF_address, "amount": 10 }] extra = helpers.request.add_transaction_author_agreement_to_extra( None, "text", "mechanism", "version") request = helpers.request.transfer(inputs, outputs, extra) req_data = request.as_dict token_authnr.authenticate_xfer(req_data, AddressSigVerifier)
def test_authenticate_xfer_with_extra_not_signed(helpers, node, addresses): [SF_address, user1_address] = addresses token_authnr = TokenAuthNr(ACCEPTABLE_WRITE_TYPES, ACCEPTABLE_QUERY_TYPES, ACCEPTABLE_ACTION_TYPES, node[0].db_manager.idr_cache) inputs = [{"source": utxo_from_addr_and_seq_no(SF_address, 1)}] outputs = [{ "address": user1_address, "amount": 10 }, { "address": SF_address, "amount": 10 }] request = helpers.request.transfer(inputs, outputs) req_data = request.as_dict token_authnr.authenticate_xfer(req_data, AddressSigVerifier) req_data[OPERATION][EXTRA] = {"aaa": "bbb"} with pytest.raises(InsufficientCorrectSignatures): token_authnr.authenticate_xfer(req_data, AddressSigVerifier)
def test_authenticate_xfer_with_extra(helpers, node, addresses): [SF_address, user1_address] = addresses token_authnr = TokenAuthNr(ACCEPTABLE_WRITE_TYPES, ACCEPTABLE_QUERY_TYPES, ACCEPTABLE_ACTION_TYPES, node[0].db_manager.idr_cache) inputs = [{"source": utxo_from_addr_and_seq_no(SF_address, 1)}] outputs = [{ "address": user1_address, "amount": 10 }, { "address": SF_address, "amount": 10 }] request = helpers.request.transfer(inputs, outputs, extra=json.dumps({"aaa": "bbb"})) req_data = request.as_dict token_authnr.authenticate_xfer(req_data, AddressSigVerifier)
def test_authenticate_calls_authenticate_xfer(helpers, node, addresses): [SF_address, user1_address] = addresses token_authnr = TokenAuthNr(ACCEPTABLE_WRITE_TYPES, ACCEPTABLE_QUERY_TYPES, ACCEPTABLE_ACTION_TYPES, node[0].db_manager.idr_cache) inputs = [{"source": utxo_from_addr_and_seq_no(SF_address, 1)}] outputs = [{ "address": user1_address, "amount": 10 }, { "address": SF_address, "amount": 10 }] request = helpers.request.transfer(inputs, outputs) req_data = request.as_dict token_authnr.authenticate_xfer = mock.Mock() token_authnr.authenticate(req_data) token_authnr.authenticate_xfer.assert_called()
def test_non_existent_input_xfer(helpers, fees_authorizer): """ Expect an InvalidFundsError on a xfer request with inputs which don't contain a valid utxo. """ helpers.general.do_set_fees(VALID_FEES) [address1, address2] = helpers.wallet.create_new_addresses(2) inputs = [{"source": utxo_from_addr_and_seq_no(address1, 1), AMOUNT: 291}] outputs = [{ADDRESS: address2, AMOUNT: 290}] request = helpers.request.transfer(inputs, outputs) authorized, error = fees_authorizer.can_pay_fees( request, required_fees=VALID_FEES.get(NYM_FEES_ALIAS)) assert not authorized assert 'was not found' in error