def test_deduct_execution_cost_from_account(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 account1 = network.test_account(node0, 10**8) account1_block_hash = parse_show_blocks( node0.d_client.show_blocks(1000))[0].summary.block_hash deploys = node0.client.show_deploys(account1_block_hash) deploy_cost = deploys[0].cost assert deploy_cost != 0 account1_balance = node0.client.get_balance( account_address=account1.public_key_hex, block_hash=account1_block_hash) assert account1_balance == 10**8 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 + account1_balance + deploy_cost * CONV_RATE)
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(bytes.fromhex(GENESIS_ACCOUNT.public_key_hex)), ABI.u32(10**7) ]) _, deploy_hash = 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(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_no_min_balance_in_account(payment_node_network_no_min_balance): network = payment_node_network_no_min_balance 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 == 10**3 block_hash = node0.transfer_to_account(1, amount=10**7, is_deploy_error_check=False) deploy = node0.client.show_deploys(block_hash)[0] assert deploy.is_error is True assert deploy.error_message == "Insufficient payment" cost_of_execution = deploy.cost assert cost_of_execution == 0 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_error_in_session_contract(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 block_hash = node0.transfer_to_account( 1, session_contract=Contract.ERR_STANDARD_PAYMENT, amount=10**7, is_deploy_error_check=False, ) deploy = node0.d_client.show_deploys(block_hash)[0] assert deploy.is_error is True assert deploy.error_message == "Exit code: 1" cost_of_execution = deploy.cost assert cost_of_execution > 0 genesis_balance_after_transfer = node0.d_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, ) expected_sum = genesis_balance_after_transfer + cost_of_execution * CONV_RATE assert genesis_balance == expected_sum
def test_not_enough_to_run_session(trillion_payment_node_network): """ The caller has not transferred enough funds to the payment purse to completely run the session code. The deploy will fail and the caller will not receive a refund. """ network = trillion_payment_node_network node0: DockerNode = network.docker_nodes[0] blocks = parse_show_blocks(node0.d_client.show_blocks(10)) 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 == 1000000000000 transfer_amount = 10**8 account1 = network.test_account(node0, transfer_amount) account1_starting_balance = node0.d_client.get_balance( account_address=account1.public_key_hex, block_hash=get_latest_hash(node0)) assert account1_starting_balance == 10**8 _, _ = node0.p_client.deploy( from_address=account1.public_key_hex, payment_contract=Contract.STANDARD_PAYMENT, session_contract=Contract.ENDLESS_LOOP, public_key=account1.public_key_path, private_key=account1.private_key_path, gas_price=1, session_args=None, payment_args=MAX_PAYMENT_ABI, ) try: node0.p_client.propose() except Exception as ex: print(ex) latest_blocks = parse_show_blocks(node0.d_client.show_blocks(100)) block_hash = latest_blocks[0].summary.block_hash deploy = node0.d_client.show_deploys(block_hash)[0] assert deploy.cost > 0 motes = deploy.cost * CONV_RATE account1_balance_after_computation = node0.d_client.get_balance( account_address=account1.public_key_hex, block_hash=block_hash) assert account1_balance_after_computation == account1_starting_balance - motes
def parse_output(self, 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"): 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 test_deploy_with_higher_nonce(node, contracts: List[str]): """ Feature file: deploy.feature Scenario: Deploy with higher nonce """ # Deploy successfully with nonce 1 => Nonce is 1 for account. deploy_and_propose(node, contracts[0], 1) # Now there should be the genesis block and the one we just deployed and proposed. wait_for_blocks_count_at_least(node, 2, 2, node.timeout) node.client.deploy(session_contract = contracts[2], payment_contract = contracts[2], nonce = 3) with pytest.raises(NonZeroExitCodeError): node.client.propose() deploy_and_propose(node, contracts[1], 2) # The deploy with nonce 3 can be proposed now. node.client.propose() blocks = parse_show_blocks(node.client.show_blocks(100)) # Deploy counts of all blocks except the genesis block. deploy_counts = [b.summary.header.deploy_count for b in blocks][:-1] assert sum(deploy_counts) == len(contracts)
def test_not_enough_to_run_session(trillion_payment_node_network): network = trillion_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 == 10**12 transfer_amount = 10**8 account1 = network.test_account(node0, transfer_amount) account1_starting_balance = node0.client.get_balance( account_address=account1.public_key_hex, block_hash=get_latest_hash(node0)) assert account1_starting_balance == 10**8 ABI = node0.p_client.abi _, _ = node0.p_client.deploy( from_address=account1.public_key_hex, payment_contract="standard_payment.wasm", session_contract="endless_loop.wasm", public_key=account1.public_key_path, private_key=account1.private_key_path, gas_price=1, gas_limit=MAX_PAYMENT_COST, session_args=None, payment_args=ABI.args([ABI.u512(MAX_PAYMENT_COST)]), ) try: node0.p_client.propose() except Exception as ex: print(ex) latest_blocks = parse_show_blocks(node0.d_client.show_blocks(1000)) deploy_hash = latest_blocks[0].summary.block_hash deploy = node0.client.show_deploys(deploy_hash)[0] assert deploy.cost == MAX_PAYMENT_COST / CONV_RATE account1_balance_after_computation = node0.client.get_balance( account_address=account1.public_key_hex, block_hash=latest_blocks[0].summary.block_hash, ) assert (account1_balance_after_computation == account1_starting_balance - MAX_PAYMENT_COST)
def test_cli_show_blocks_and_show_block(cli): blocks = parse_show_blocks(cli("show-blocks", "--depth", "1")) assert len(blocks) > 0 for block in blocks: block_hash = block.summary.block_hash assert len(block_hash) == 32 * 2 # hex b = parse(cli("show-block", block_hash)) assert block_hash == b.summary.block_hash
def assert_pre_state_of_network(network: OneNodeNetwork, stakes: List[int]): node0 = network.docker_nodes[0] blocks = parse_show_blocks(node0.client.show_blocks(1000)) assert len(blocks) == 1 genesis_block = blocks[0] item = list( filter( lambda x: x.stake in stakes and x.validator_public_key == node0. from_address, genesis_block.summary.header.state.bonds, )) assert len(item) == 0
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(bytes.fromhex(to_account.public_key_hex)), ABI.u32(10**7) ]) payment_args = ABI.args([ABI.u512(10**6)]) response, deploy_hash_bytes = node0.p_client.deploy( from_address=from_account.public_key_hex, session_contract=Contract.TRANSFER_TO_ACCOUNT, payment_contract=Contract.ERR_STANDARD_PAYMENT, 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 is_satisfied(self) -> bool: n = self.prefix_length return all( ( self.block_hashes.issubset( set( b.summary.block_hash[:n] for b in parse_show_blocks(node.d_client.show_blocks(1000)) ) ) for node in self.nodes ) )
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 == 10**9 from_account = Account("genesis") to_account = Account(1) args_json = json.dumps([{ "account": to_account.public_key_hex }, { "u32": 10**7 }]) ABI = node0.p_client.abi response, deploy_hash_bytes = node0.p_client.deploy( from_address=from_account.public_key_hex, session_contract="transfer_to_account.wasm", payment_contract="err_standard_payment.wasm", public_key=from_account.public_key_path, private_key=from_account.private_key_path, gas_price=1, gas_limit=MAX_PAYMENT_COST / CONV_RATE, session_args=ABI.args_from_json(args_json), payment_args=ABI.args([ABI.u512(10**6)]), ) 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_refund_after_session_code_error(payment_node_network): network = payment_node_network node0: DockerNode = network.docker_nodes[0] blocks = parse_show_blocks(node0.d_client.show_blocks(1000)) genesis_init_balance = node0.client.get_balance( account_address=GENESIS_ACCOUNT.public_key_hex, block_hash=blocks[0].summary.block_hash, ) args_json = json.dumps([{"u32": 10**6}]) ABI = node0.p_client.abi _, deploy_hash = node0.p_client.deploy( from_address=GENESIS_ACCOUNT.public_key_hex, session_contract="test_args_u512.wasm", payment_contract="standard_payment.wasm", public_key=GENESIS_ACCOUNT.public_key_path, private_key=GENESIS_ACCOUNT.private_key_path, gas_price=1, gas_limit=MAX_PAYMENT_COST / CONV_RATE, session_args=ABI.args([ABI.u512(100)]), payment_args=ABI.args_from_json(args_json) # 100 is a revert code. ) try: node0.p_client.propose() except Exception as ex: print(ex) latest_blocks = parse_show_blocks(node0.d_client.show_blocks(1000)) deploy_hash = latest_blocks[0].summary.block_hash deploy = node0.client.show_deploys(deploy_hash)[0] assert deploy.cost == MAX_PAYMENT_COST / CONV_RATE motes = deploy.cost * CONV_RATE later_balance = node0.client.get_balance( account_address=GENESIS_ACCOUNT.public_key_hex, block_hash=deploy_hash) expected_sum = later_balance + motes assert genesis_init_balance == expected_sum
def test_deploy_with_higher_nonce_does_not_include_previous_deploy(node, contracts: List[str]): """ Feature file: deploy.feature Scenario: Deploy with higher nonce and created block does not include previously deployed contract. """ # Deploy successfully with nonce 1 => Nonce is 1 for account. deploy_and_propose(node, contracts[0], 1) # Now there should be the genesis block and the one we just deployed and proposed. wait_for_blocks_count_at_least(node, 2, 2, node.timeout) node.client.deploy(session_contract=contracts[1], payment_contract=contracts[1], nonce=4) with pytest.raises(NonZeroExitCodeError): node.client.propose() node.client.deploy(session_contract=contracts[2], payment_contract=contracts[2], nonce=2) # The deploy with nonce 4 cannot be proposed now. It will be in the deploy buffer but does not include # in the new block created now. node.client.propose() wait_for_blocks_count_at_least(node, 3, 3, node.timeout) blocks = parse_show_blocks(node.client.show_blocks(100)) # Deploy counts of all blocks except the genesis block. deploy_counts = [b.summary.header.deploy_count for b in blocks][:-1] assert sum(deploy_counts) == 2 deploy_and_propose(node, contracts[3], 3) node.client.propose() wait_for_blocks_count_at_least(node, 5, 5, node.timeout) blocks = parse_show_blocks(node.client.show_blocks(100)) # Deploy counts of all blocks except the genesis block. deploy_counts = [b.summary.header.deploy_count for b in blocks][:-1] assert sum(deploy_counts) == len(contracts)
def test_not_enough_funds_to_run_payment_code(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 == 10**9 args_json = json.dumps([{ "account": GENESIS_ACCOUNT.public_key_hex }, { "u32": 10**7 }]) ABI = node0.p_client.abi _, deploy_hash = node0.p_client.deploy( from_address=GENESIS_ACCOUNT.public_key_hex, session_contract="transfer_to_account.wasm", payment_contract="standard_payment.wasm", public_key=GENESIS_ACCOUNT.public_key_path, private_key=GENESIS_ACCOUNT.private_key_path, gas_price=1, gas_limit=MAX_PAYMENT_COST / CONV_RATE, session_args=ABI.args_from_json(args_json), payment_args=ABI.args([ABI.u512(450)]), ) latest_block_hash = parse_show_blocks( node0.d_client.show_blocks(1000))[0].summary.block_hash genesis_balance_after_transfer = node0.client.get_balance( account_address=GENESIS_ACCOUNT.public_key_hex, block_hash=latest_block_hash) # assert genesis_balance == genesis_balance_after_transfer + 450 * CONV_RATE ? assert genesis_balance == genesis_balance_after_transfer
def test_multiple_deploys_at_once(three_node_network, contract_paths: List[List[str]], expected_deploy_counts_in_blocks): """ Feature file : multiple_simultaneous_deploy.feature Scenario: Multiple simultaneous deploy after single deploy """ nodes = three_node_network.docker_nodes # Wait for the genesis block reacing each node. for node in nodes: wait_for_blocks_count_at_least(node, 1, 1, node.timeout) deploy_threads = [ DeployThread("node" + str(i + 1), node, contract_paths, max_attempts=5, retry_seconds=3) for i, node in enumerate(nodes) ] for t in deploy_threads: t.start() for t in deploy_threads: t.join() # See COMMENT_EXPECTED_BLOCKS for node in nodes: wait_for_blocks_count_at_least( node, len(expected_deploy_counts_in_blocks), len(expected_deploy_counts_in_blocks) * 2, node.timeout) for node in nodes: blocks = parse_show_blocks( node.client.show_blocks( len(expected_deploy_counts_in_blocks) * 100)) n_blocks = len(expected_deploy_counts_in_blocks) assert [ b.summary.header.deploy_count for b in blocks ][: n_blocks] == expected_deploy_counts_in_blocks, 'Unexpected deploy counts in blocks'
def get_latest_hash(node0): blocks = parse_show_blocks(node0.d_client.show_blocks(1000)) return blocks[0].summary.block_hash
def test_client_parser_show_blocks(): r = parse_show_blocks(SHOW_BLOCKS)[0] bonds = r.summary.header.state.bonds assert len(bonds) == 10 assert sum(bond.stake for bond in bonds) == 190