def bond_command(casperlabs_client, args): logging.info(f"BOND {args}") _set_session(args, "bonding.wasm") if not args.session_args: args.session_args = ABI.args_to_json( ABI.args([ABI.long_value("amount", args.amount)])) return deploy_command(casperlabs_client, args)
def _deploy_kwargs(args, private_key_accepted=True): from_addr = ( getattr(args, "from") and bytes.fromhex(getattr(args, "from")) or getattr(args, "public_key") and read_pem_key(args.public_key) or private_to_public_key(args.private_key) ) if from_addr and len(from_addr) != 32: raise Exception( "--from must be 32 bytes encoded as 64 characters long hexadecimal" ) if not (args.payment_amount or args.payment_args): args.payment_amount = DEFAULT_PAYMENT_AMOUNT if args.payment_amount: args.payment_args = ABI.args_to_json( ABI.args([ABI.big_int("amount", int(args.payment_amount))]) ) d = dict( from_addr=from_addr, gas_price=args.gas_price, payment=args.payment, session=args.session, public_key=args.public_key or None, session_args=args.session_args and ABI.args_from_json(args.session_args) or None, payment_args=args.payment_args and ABI.args_from_json(args.payment_args) or None, payment_hash=args.payment_hash and bytes.fromhex(args.payment_hash), payment_name=args.payment_name, payment_uref=args.payment_uref and bytes.fromhex(args.payment_uref), session_hash=args.session_hash and bytes.fromhex(args.session_hash), session_name=args.session_name, session_uref=args.session_uref and bytes.fromhex(args.session_uref), ttl_millis=args.ttl_millis, dependencies=args.dependencies, chain_name=args.chain_name, ) if private_key_accepted: d["private_key"] = args.private_key or None return d
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 check_cli_abi_unsigned(cli, unsigned_type, value, test_contract): account = GENESIS_ACCOUNT for number in [2, 256, 1024]: args = ABI.args([getattr(ABI, unsigned_type)("number", number)]) session_args = ABI.args_to_json(args) args = ('deploy', '--from', account.public_key_hex, '--session', cli.resource(test_contract), '--session-args', cli.format_json_str(session_args), '--payment', cli.resource(Contract.STANDARD_PAYMENT), '--payment-args', cli.payment_json, '--private-key', cli.private_key_path(account), '--public-key', cli.public_key_path(account)) logging.info(f"EXECUTING {' '.join(cli.expand_args(args))}") deploy_hash = cli(*args) 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: {number}"
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 _deploy_kwargs(args, private_key_accepted=True): from_addr = (getattr(args, "from") and bytes.fromhex(getattr(args, "from")) or private_to_public_key(args.private_key)) if from_addr and len(from_addr) != 32: raise Exception( "--from must be 32 bytes encoded as 64 characters long hexadecimal" ) if args.payment_amount: args.payment_args = ABI.args_to_json( ABI.args([ABI.big_int("amount", int(args.payment_amount))])) # Unless one of payment* options supplied use bundled standard-payment if not any((args.payment, args.payment_name, args.payment_hash, args.payment_uref)): args.payment = bundled_contract("standard_payment.wasm") d = dict( from_addr=from_addr, gas_price=args.gas_price, payment=args.payment or args.session, session=args.session, public_key=args.public_key or None, session_args=args.session_args and ABI.args_from_json(args.session_args) or None, payment_args=args.payment_args and ABI.args_from_json(args.payment_args) or None, payment_hash=args.payment_hash and bytes.fromhex(args.payment_hash), payment_name=args.payment_name, payment_uref=args.payment_uref and bytes.fromhex(args.payment_uref), session_hash=args.session_hash and bytes.fromhex(args.session_hash), session_name=args.session_name, session_uref=args.session_uref and bytes.fromhex(args.session_uref), ttl_millis=args.ttl_millis, dependencies=args.dependencies, chain_name=args.chain_name, ) if private_key_accepted: d["private_key"] = args.private_key or None return d
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}"
class CLI: _DEFAULT_PAYMENT_JSON = ABI.args_to_json( ABI.args([ABI.big_int("amount", DEFAULT_PAYMENT_COST)])) def __init__(self, node, cli_cmd="casperlabs_client", tls_parameters=None): self.node = node self.host = (os.environ.get("TAG_NAME", None) and node.container_name or "localhost") self.port = node.grpc_external_docker_port self.port_internal = node.grpc_internal_docker_port self.cli_cmd = cli_cmd self.tls_parameters = tls_parameters or {} self.default_deploy_args = [] self.resources_directory = resources_path() def set_default_deploy_args(self, *args): """ Set args that will be appended to subsequent deploy command. """ self.default_deploy_args = [str(arg) for arg in args] def resource(self, file_name): return self.resources_directory / file_name @property def _local_connection_details(self): return [ "--host", f"{self.host}", "--port", f"{self.port}", "--port-internal", f"{self.port_internal}", ] def expand_args(self, args): connection_details = self._local_connection_details if self.tls_parameters: connection_details += reduce( add, [[str(p), str(self.tls_parameters[p])] for p in self.tls_parameters], ) string_args = [str(a) for a in list(args)] if args and args[0] == "deploy": string_args += self.default_deploy_args return "--help" in args and string_args or connection_details + string_args @staticmethod def parse_output(command, binary_output): if command in ("make-deploy", "sign-deploy"): return binary_output output = binary_output.decode("utf-8") if command in ("deploy", "send-deploy", "bond", "unbond", "transfer"): return output.split()[2] # "Success! Deploy 0d4036bebb95de793b28de452d594531a29f8dc3c5394526094d30723fa5ff65 deployed." if command == "show-blocks": return parse_show_blocks(output) if command == "show-deploys": return parse_show_deploys(output) if command in ("show-deploy", "show-block", "query-state"): return parse(output) if command in ("balance", ): # 'Balance:\n9d39b7fba47d07c1af6f711efe604a112ab371e2deefb99a613d2b3dcdfba414 : 1000000000' return int(output.split(":")[-1]) return output def __call__(self, *args): command_line = [str(self.cli_cmd)] + self.expand_args(args) # logging.info(f"EXECUTING []: {command_line}") logging.info(f"EXECUTING: {' '.join(command_line)}") cp = subprocess.run(command_line, stdout=subprocess.PIPE, stderr=subprocess.PIPE) binary_output = cp.stdout if cp.returncode != 0: output = binary_output try: output = binary_output.decode("utf-8") except UnicodeDecodeError: pass raise CLIErrorExit(cp, output) return self.parse_output(args[0], binary_output) def public_key_path(self, account): return account.public_key_path def private_key_path(self, account): return account.private_key_path def format_json_str(self, args: str) -> str: return args @property def payment_json(self) -> str: return self.format_json_str(self._DEFAULT_PAYMENT_JSON)
def disable_test_multiple_deploys_per_block(cli): """ Two deploys from the same account then propose. Both deploys should be be included in the new block. Create named purses to pay from for each deploy (standard payment cannot be used because it causes a WRITE against the main purse balance, but every deploy has a READ against that balance to check it meets the minimum balance condition, so standard payment calls always conflict with any other deploy from the same account) """ account = cli.node.test_account cli.set_default_deploy_args('--from', account.public_key_hex, '--private-key', cli.private_key_path(account), '--public-key', cli.public_key_path(account)) # Create purse_1 deploy_hash = cli( 'deploy', '--session', cli.resource(Contract.CREATE_NAMED_PURSE), '--session-args', ABI.args_to_json( ABI.args([ ABI.big_int("amount", 100000000), ABI.string_value("purse-name", "purse_1") ])), '--payment', cli.resource(Contract.STANDARD_PAYMENT), '--payment-args', ABI.args_to_json(ABI.args([ABI.big_int("amount", 100000000)]))) check_no_errors(cli, deploy_hash) # Create purse_2 deploy_hash = cli( 'deploy', '--session', cli.resource(Contract.CREATE_NAMED_PURSE), '--session-args', ABI.args_to_json( ABI.args([ ABI.big_int("amount", 100000000), ABI.string_value("purse-name", "purse_2") ])), '--payment', cli.resource(Contract.STANDARD_PAYMENT), '--payment-args', ABI.args_to_json(ABI.args([ABI.big_int("amount", 100000000)]))) check_no_errors(cli, deploy_hash) # First deploy uses first purse for payment deploy_hash1 = cli( 'deploy', '--from', account.public_key_hex, '--session', cli.resource(Contract.COUNTER_DEFINE), '--payment', cli.resource(Contract.PAYMENT_FROM_NAMED_PURSE), '--payment-args', ABI.args_to_json( ABI.args([ ABI.big_int("amount", 100000000), ABI.string_value("purse-name", "purse_1") ]))) # Second deploy uses second purse for payment deploy_hash2 = cli( 'deploy', '--from', account.public_key_hex, '--session', cli.resource(Contract.MAILING_LIST_DEFINE), '--payment', cli.resource(Contract.PAYMENT_FROM_NAMED_PURSE), '--payment-args', ABI.args_to_json( ABI.args([ ABI.big_int("amount", 100000000), ABI.string_value("purse-name", "purse_2") ]))) block_hash = check_no_errors(cli, deploy_hash2) # Propose should include both deploys. deploys = list(cli("show-deploys", block_hash)) # TODO: with auto-propose this may fail: assert len(deploys) == 2 assert set(d.deploy.deploy_hash for d in deploys) == set( (deploy_hash1, deploy_hash2))