def test_args_parser(): account = ( b"\x00\x01\x00\x02\x00\x03\x00\x04\x00\x05\x00\x06\x00\x07\x00\x08" b"\x00\x00\x00\x01\x00\x02\x00\x03\x00\x04\x00\x05\x00\x06\x00\x07" ) amount = 123456 args = [{"name": "amount", "value": {"long_value": amount}}, {"name": "account", "value": {"bytes_value": account.hex()}}, {"name": "purse_id", "value": {"optional_value": {}}}, {"name": "number", "value": {"big_int": {"value": "2", "bit_width": 512}}}] json_str = json.dumps(args) assert ABI.args_from_json(json_str) == ABI.args( [ABI.long_value(amount), ABI.account(account), ABI.optional_value(None), ABI.big_int(2)] )
def test_args_from_json(): account = bytes(range(32)) long_value = 123456 big_int_value = 123456789012345678901234567890 args = [ { "name": "amount", "value": { "long_value": long_value } }, { "name": "account", "value": { "bytes_value": account.hex() } }, { "name": "purse_id", "value": { "optional_value": {} } }, { "name": "number", "value": { "big_int": { "value": f"{big_int_value}", "bit_width": 512 } }, }, ] json_str = json.dumps(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("purse_id", None) assert args[3] == ABI.big_int("number", big_int_value)
STANDARD_PAYMENT = "standard_payment.wasm" SUBCALL_REVERT_CALL = "subcall_revert_call.wasm" SUBCALL_REVERT_DEFINE = "subcall_revert_define.wasm" TRANSFER_TO_ACCOUNT = "transfer_to_account.wasm" UPDATE_ASSOCIATED_KEY = "update_associated_key.wasm" # TEST Account Use Notes # test_transfer_to_accounts: 300, 299, 298 # test_transfer_with_overdraft: 297, 296 # test_bonding: 295 MAX_PAYMENT_COST = 10000000 DEFAULT_PAYMENT_COST = 100000000 INITIAL_MOTES_AMOUNT = 10**20 MAX_PAYMENT_ABI = ABI.args([ABI.big_int("amount", MAX_PAYMENT_COST)]) DEFAULT_PAYMENT_ABI = ABI.args([ABI.big_int("amount", DEFAULT_PAYMENT_COST)]) CONV_RATE = 10 TEST_ACCOUNT_INITIAL_BALANCE = 1000000000 USER_ERROR_MIN = 65536 BOOTSTRAP_PATH = "/root/.casperlabs/bootstrap" CHAINSPEC_PATH = "/root/.casperlabs/chainspec" @dataclasses.dataclass(eq=True, frozen=True) class KeyPair: private_key: str public_key: str
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 def expand_args(self, args): connection_details = [ "--host", f"{self.host}", "--port", f"{self.port}", "--port-internal", f"{self.port_internal}", ] 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"): return output.split()[2] # "Success! Deploy 0d4036bebb95de793b28de452d594531a29f8dc3c5394526094d30723fa5ff65 deployed." if command in ("propose",): # "Response: Success! Block 47338c65992e7d5062aec2200ad8d7284ae49f6c3e7c37fa7eb46fb6fc8ae3d8 created and added." return output.split()[3] 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) 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 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 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)]))) propose_check_no_errors(cli) # Create purse_2 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)]))) propose_check_no_errors(cli) # 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 = propose_check_no_errors(cli) # Propose should include both deploys. deploys = list(cli("show-deploys", block_hash)) assert len(deploys) == 2 assert set(d.deploy.deploy_hash for d in deploys) == set( (deploy_hash1, deploy_hash2))