def test_not_enough_funds_to_run_payment_code(payment_node_network): network = payment_node_network node0: DockerNode = network.docker_nodes[0] blocks = parse_show_blocks(node0.d_client.show_blocks(1000)) genesis_hash = blocks[0].summary.block_hash assert len( blocks) == 1 # There should be only one block - the genesis block genesis_balance = node0.d_client.get_balance( account_address=GENESIS_ACCOUNT.public_key_hex, block_hash=genesis_hash) assert genesis_balance == INITIAL_MOTES_AMOUNT session_args = ABI.args([ ABI.account("account", GENESIS_ACCOUNT.public_key_hex), ABI.u64("amount", 10**7), ]) node0.p_client.deploy( from_address=GENESIS_ACCOUNT.public_key_hex, session_contract=Contract.TRANSFER_TO_ACCOUNT, payment_contract=Contract.STANDARD_PAYMENT, public_key=GENESIS_ACCOUNT.public_key_path, private_key=GENESIS_ACCOUNT.private_key_path, gas_price=1, session_args=session_args, payment_args=ABI.args([ABI.u512("amount", 450)]), ) latest_block_hash = parse_show_blocks( node0.d_client.show_blocks(1000))[0].summary.block_hash genesis_balance_after_transfer = node0.d_client.get_balance( account_address=GENESIS_ACCOUNT.public_key_hex, block_hash=latest_block_hash) assert genesis_balance == genesis_balance_after_transfer
def test_deploy_do_nothing_and_call_by_entry_point_and_version( casperlabs_client, faucet_funded_accounts, algorithm ): key_holder, private_key_pem_path = faucet_funded_accounts[algorithm] deploy_hash = casperlabs_client.deploy( session=WASM_DIRECTORY / "test_payment_stored.wasm", payment_amount=10000000, private_key=private_key_pem_path, ) result = casperlabs_client.show_deploy( deploy_hash, wait_for_processed=True, timeout_seconds=300 ) for block_info in result.processing_results: assert ( not block_info.is_error ), f"block_info.is_error: {block_info.error_message}" assert len(result.processing_results) > 0, "No block_info returned" deploy_hash = casperlabs_client.deploy( session=WASM_DIRECTORY / "transfer_to_account_u512_stored.wasm", payment_name="test_payment_hash", payment_entry_point="pay", payment_args=ABI.args([ABI.big_int("amount", 10000000)]), private_key=private_key_pem_path, ) result = casperlabs_client.show_deploy( deploy_hash, wait_for_processed=True, timeout_seconds=300 ) for block_info in result.processing_results: assert ( not block_info.is_error ), f"block_info.is_error: {block_info.error_message}" assert len(result.processing_results) > 0, "No block_info returned" session_args = ABI.args( [ ABI.account( "target", "1000000000000000000000000000000000000000000000000000000000000000", ), ABI.big_int("amount", 123), ] ) deploy_hash = casperlabs_client.deploy( session_name="transfer_to_account", session_entry_point="transfer", session_args=session_args, payment_amount=10000000, private_key=private_key_pem_path, ) result = casperlabs_client.show_deploy( deploy_hash, wait_for_processed=True, timeout_seconds=300 ) for block_info in result.processing_results: assert ( not block_info.is_error ), f"block_info.is_error: {block_info.error_message}" assert len(result.processing_results) > 0, "No block_info returned"
def faucet_fund_account(casperlabs_client, account_hash_hex, amount=10000000000): faucet_wasm_path = WASM_DIRECTORY / "faucet.wasm" assert faucet_wasm_path.exists(), ( f"Needed wasm file: {faucet_wasm_path} does not exist.\n" "It should be built in `build_contracts.sh`.") session_args = ABI.args([ ABI.account("target", account_hash_hex), ABI.big_int("amount", amount) ]) deploy_hash = casperlabs_client.deploy( private_key=FAUCET_PRIVATE_KEY_PEM_PATH, session=faucet_wasm_path, session_args=session_args, payment_amount=1000000, ) result = casperlabs_client.show_deploy(deploy_hash, wait_for_processed=True) assert (len(result.processing_results) > 0), "No processing results from faucet transfer" block_hash = result.processing_results[0].block_info.summary.block_hash result = casperlabs_client.balance(account_hash_hex, block_hash.hex()) assert result > 0, "balance of new account is not correct"
def test_deploy_with_args(one_node_network, genesis_public_signing_key): """ Deploys test contracts that do: revert(get_arg(0)); // for u32 and u512 and revert(sum(address_bytes[u8; 32]) + u32); for multiple argument test. Tests args get correctly encoded and decoded in the contract. Test expects the test contracts args_u32.wasm and args_u512.wasm to deserialize correctly their arguments and then call revert with value of the argument (converted to a Rust native int, as expected by revert). If the test contracts don't fail or if their exit code is different than expected, the test will fail. """ node = one_node_network.docker_nodes[0] client = node.p_client.client for wasm, encode in [ (resources_path() / Contract.ARGS_U32, ABI.int_value), (resources_path() / Contract.ARGS_U512, ABI.big_int), ]: for number in [1, 12, 256, 1024]: block_hash = node.deploy_and_get_block_hash( GENESIS_ACCOUNT, wasm, on_error_raise=False, session_args=ABI.args([encode("number", number)]), ) for deploy_info in client.showDeploys(block_hash): exit_code = number + USER_ERROR_MIN assert deploy_info.is_error is True assert deploy_info.error_message == f"Exit code: {exit_code}" wasm = resources_path() / Contract.ARGS_MULTI account_hex = "0101010102020202030303030404040405050505060606060707070708080808" number = 1000 total_sum = sum([1, 2, 3, 4, 5, 6, 7, 8]) * 4 + number block_hash = node.deploy_and_get_block_hash( GENESIS_ACCOUNT, wasm, on_error_raise=False, session_args=ABI.args( [ABI.account("account", account_hex), ABI.u32("number", number)]), ) for deploy_info in client.showDeploys(block_hash): exit_code = total_sum + USER_ERROR_MIN assert deploy_info.is_error is True assert deploy_info.error_message == f"Exit code: {exit_code}" for blockInfo in client.showBlocks(10): assert blockInfo.status.stats.block_size_bytes > 0
def do_transfer( ctx: ExecutionContext, cp1: Account, cp2: Account, amount: int, contract: ClientContract = None, is_refundable: bool = True, deploy_type: DeployType = DeployType.TRANSFER ) -> typing.Tuple[Deploy, Transfer]: """Executes a transfer between 2 counter-parties & returns resulting deploy hash. :param ctx: Execution context information. :param cp1: Account information of counter party 1. :param cp2: Account information of counter party 2. :param amount: Amount in motes to be transferred. :param contract: The transfer contract to call (if any). :param is_refundable: Flag indicating whether a refund is required. :param deploy_type: The type of deploy to dispatch. :returns: Dispatched deploy & transfer. """ # Set client. node, client = utils.get_client(ctx) # Transfer using called contract - does not dispatch wasm. if contract: session_args = ABI.args([ ABI.account("address", cp2.public_key), ABI.big_int("amount", amount) ]) dhash = client.deploy( session_hash=bytes.fromhex(contract.chash), session_args=session_args, from_addr=cp1.public_key, private_key=cp1.private_key_as_pem_filepath, # TODO: allow these to be passed in via standard arguments payment_amount=defaults.CLX_TX_FEE, gas_price=defaults.CLX_TX_GAS_PRICE) # Transfer using stored contract - dispatches wasm. else: dhash = client.transfer( amount=amount, from_addr=cp1.public_key, private_key=cp1.private_key_as_pem_filepath, target_account_hex=cp2.public_key, # TODO: allow these to be passed in via standard arguments payment_amount=defaults.CLX_TX_FEE, gas_price=defaults.CLX_TX_GAS_PRICE) logger.log( f"PYCLX :: transfer :: {dhash} :: {amount} CLX :: {cp1.public_key[:8]} -> {cp2.public_key[:8]}" ) return (node, dhash)
def remove_associated_key(node, weight_key: Account, key: Account): """ Removes a key from the IDENTITY_KEY account """ args = ABI.args([ABI.account("account", key.public_key_hex)]) return node.deploy_and_get_block_hash( weight_key, Contract.REMOVE_ASSOCIATED_KEY, on_error_raise=False, from_addr=IDENTITY_KEY.public_key_hex, public_key=weight_key.public_key_path, private_key=weight_key.private_key_path, session_args=args, )
def test_legacy_args_from_json(): json_str = json.dumps(LEGACY_ARGS) args = ABI.args_from_json(json_str) assert args[0] == ABI.long_value("amount", long_value) assert args[1] == ABI.account("account", account) assert args[2] == ABI.optional_value("main_purse", None) assert args[3] == ABI.big_int("number", big_int_value) assert args[4] == ABI.bytes_value("my_bytes", account) assert args[5] == ABI.key_hash("my_hash", account) assert args[6] == ABI.key_address("my_address", account) assert args[7] == ABI.key_uref("my_uref", account, access_rights=5) assert args[8] == ABI.key_local("my_local", account)
def create_associate_deploy(acct_num: int): """ Add associated key of acct_num + 1 to acct_num account """ acct = Account(acct_num) associated_acct = Account(acct_num + 1) args = ABI.args([ ABI.account("account", associated_acct.public_key_binary), ABI.u32("amount", 1), ]) return node.p_client.deploy( from_address=acct.public_key_hex, session_contract=Contract.ADD_ASSOCIATED_KEY, public_key=acct.public_key_path, private_key=acct.private_key_path, session_args=args, )
def _add_update_associate_key( node, weight_key: Account, key: Account, weight: int, contract: str ): """ Handles both add and update calls due to commonality """ session_args = ABI.args( [ABI.account("account", key.public_key_hex), ABI.u32("amount", weight)] ) return node.deploy_and_get_block_hash( weight_key, contract, on_error_raise=False, from_addr=IDENTITY_KEY.public_key_hex, public_key=weight_key.public_key_path, private_key=weight_key.private_key_path, session_args=session_args, )
def test_args_to_json(): args = [ ABI.long_value("amount", long_value), ABI.account("account", account), ABI.optional_value("purse_id", None), ABI.big_int("number", big_int_value), ABI.bytes_value("my_bytes", account), ABI.key_hash("my_hash", account), ABI.key_address("my_address", account), ABI.key_uref("my_uref", account, access_rights=5), ABI.key_local("my_local", account), ] json_str1 = json.dumps(ARGS, ensure_ascii=True, sort_keys=True, indent=2) json_str2 = ABI.args_to_json(ABI.args(args), ensure_ascii=True, sort_keys=True, indent=2) assert json_str1 == json_str2
def transfer_command(casperlabs_client, args): _set_session(args, "transfer_to_account_u512.wasm") if not args.session_args: target_account_bytes = base64.b64decode(args.target_account) if len(target_account_bytes) != 32: target_account_bytes = bytes.fromhex(args.target_account) if len(target_account_bytes) != 32: raise Exception( "--target_account must be 32 bytes base64 or base16 encoded" ) args.session_args = ABI.args_to_json( ABI.args([ ABI.account("account", target_account_bytes), ABI.u512("amount", args.amount), ])) return deploy_command(casperlabs_client, args)
def faucet_fund_account(casperlabs_client, account_hash_hex, amount=1000000000): faucet_wasm_path = WASM_DIRECTORY / "faucet.wasm" session_args = ABI.args([ ABI.account("target", account_hash_hex), ABI.big_int("amount", amount) ]) # TODO: validate faucet key path to make sure key gen worked during standup. deploy_hash = casperlabs_client.deploy( private_key=FAUCET_PRIVATE_KEY_PEM_PATH, session=faucet_wasm_path, session_args=session_args, ) result = casperlabs_client.show_deploy(deploy_hash, wait_for_processed=True) block_hash = result.processing_results[0].block_info.summary.block_hash result = casperlabs_client.balance(account_hash_hex, block_hash.hex()) assert result > 0
def make_transfers(client, account, target_account, amount, n): """ Makes n transfers from account to account_target, n must be greater than 1. First n-1 deploys depends on a deploy that is sent to the node as the last one. This is in order to ensure that node doesn't put part of the set of deploys on a block before receiving all of them. Returns tuple (deploy_hash, [deploy_hashes]), where deploy_hash is the special deploy that all other deploys depend on. """ if not n > 1: raise Exception("n must be > 1") deploy = client.make_deploy( from_addr=account.public_key_hex, session=bundled_contract("transfer_to_account_u512.wasm"), session_args=ABI.args([ ABI.account("account", bytes.fromhex(target_account.public_key_hex)), ABI.u512("amount", amount), ]), payment_amount=10000000, ) deploy = client.sign_deploy(deploy, account.public_key_hex, account.private_key_path) deploy_hash = deploy.deploy_hash.hex() deploy_hashes = [ client.transfer( private_key=account.private_key_path, from_addr=account.public_key_hex, target_account_hex=target_account.public_key_hex, payment_amount=10000000, amount=1, dependencies=[deploy_hash], ) for _ in range(n - 1) ] client.send_deploy(deploy) return deploy_hash, deploy_hashes
def test_args_to_json(): args = [ ABI.long_value("amount", long_value), ABI.account("account", account), ABI.optional_value("main_purse", None), ABI.big_int("number", big_int_value), ABI.bytes_value("my_bytes", account), ABI.key_hash("my_hash", account), ABI.key_address("my_address", account), ABI.key_uref("my_uref", account, access_rights=5), ABI.key_local("my_local", account), ] json_str1 = json.dumps(LEGACY_ARGS, ensure_ascii=True, sort_keys=True, indent=2) json_str2 = ABI.args_to_json(ABI.args(args), ensure_ascii=True, sort_keys=True, indent=2) # TODO: fix this test to use new json format assert json_str1 != json_str2
def test_error_in_payment_contract(payment_node_network): network = payment_node_network node0: DockerNode = network.docker_nodes[0] node0.use_docker_client() blocks = parse_show_blocks(node0.d_client.show_blocks(1000)) genesis_hash = blocks[0].summary.block_hash assert len( blocks) == 1 # There should be only one block - the genesis block genesis_balance = node0.client.get_balance( account_address=GENESIS_ACCOUNT.public_key_hex, block_hash=genesis_hash) assert genesis_balance == INITIAL_MOTES_AMOUNT from_account = Account("genesis") to_account = Account(1) session_args = ABI.args([ ABI.account("account", to_account.public_key_hex), ABI.u64("amount", 10**7) ]) payment_args = ABI.args([ABI.u512("amount", 10**6)]) node0.p_client.deploy( from_address=from_account.public_key_hex, session_contract=Contract.TRANSFER_TO_ACCOUNT, payment_contract=Contract.DIRECT_REVERT, public_key=from_account.public_key_path, private_key=from_account.private_key_path, gas_price=1, session_args=session_args, payment_args=payment_args, ) genesis_balance_after_transfer = node0.client.get_balance( account_address=GENESIS_ACCOUNT.public_key_hex, block_hash=parse_show_blocks( node0.d_client.show_blocks(1000))[0].summary.block_hash, ) assert genesis_balance == genesis_balance_after_transfer
def test_cli_abi_multiple(cli): account = GENESIS_ACCOUNT account_hex = "0101010102020202030303030404040405050505060606060707070708080808" number = 1000 total_sum = sum([1, 2, 3, 4, 5, 6, 7, 8]) * 4 + number args = ABI.args( [ABI.account("account", account_hex), ABI.int_value("number", number)]) session_args = ABI.args_to_json(args) deploy_hash = cli('deploy', '--from', account.public_key_hex, '--session', cli.resource(Contract.ARGS_MULTI), '--session-args', session_args, '--private-key', cli.private_key_path(account), '--public-key', cli.public_key_path(account), '--payment', cli.resource(Contract.STANDARD_PAYMENT), '--payment-args', cli.payment_json) cli.node.wait_for_deploy_processed_and_get_block_hash(deploy_hash, on_error_raise=False) deploy_info = cli("show-deploy", deploy_hash) assert deploy_info.processing_results[0].is_error is True assert deploy_info.processing_results[ 0].error_message == f"User error: {total_sum}"
def transfer_to_account( self, to_account_id: int, amount: int, from_account_id: Union[str, int] = "genesis", session_contract: str = Contract.TRANSFER_TO_ACCOUNT, payment_contract: str = Contract.STANDARD_PAYMENT, payment_args: bytes = MAX_PAYMENT_ABI, gas_price: int = 1, is_deploy_error_check: bool = True, ) -> str: """ Performs a transfer using the from account if given (or genesis if not) :param to_account_id: 1-20 index of test account for transfer into :param amount: amount of motes to transfer (mote = smallest unit of token) :param from_account_id: default 'genesis' account, but previously funded account_id is also valid. :param session_contract: session contract to execute. :param payment_contract: Payment contract to execute. :param payment_args: Payment Amount ABI :param gas_price: Gas price :param is_deploy_error_check: Check that amount transfer is success. :returns block_hash in hex str """ logging.info(f"=== Transferring {amount} to {to_account_id}") assert ( is_valid_account(to_account_id) and to_account_id != "genesis" ), "Can transfer only to non-genesis accounts in test framework (1-20)." assert is_valid_account( from_account_id ), "Must transfer from a valid account_id: 1-20 or 'genesis'" from_account = Account(from_account_id) to_account = Account(to_account_id) session_args = ABI.args([ ABI.account("account", to_account.public_key_binary), ABI.u64("amount", amount), ]) deploy_hash = self.p_client.deploy( from_address=from_account.public_key_hex, session_contract=session_contract, payment_contract=payment_contract, public_key=from_account.public_key_path, private_key=from_account.private_key_path, gas_price=gas_price, session_args=session_args, payment_args=payment_args, ) client = self.p_client.client result = client.wait_for_deploy_processed( deploy_hash, on_error_raise=is_deploy_error_check) last_processing_result = result.processing_results[0] block_hash = last_processing_result.block_info.summary.block_hash.hex() if is_deploy_error_check and last_processing_result.is_error: raise Exception( f"transfer_to_account: {last_processing_result.error_message}") return block_hash