def register_token_and_return_the_network_proxy( contract_manager: ContractManager, deploy_client: JSONRPCClient, token_proxy: Token, token_network_registry_address: TokenNetworkRegistryAddress, ) -> TokenNetwork: blockchain_service = ProxyManager( rpc_client=deploy_client, contract_manager=contract_manager, metadata=ProxyManagerMetadata( token_network_registry_deployed_at=GENESIS_BLOCK_NUMBER, filters_start_at=GENESIS_BLOCK_NUMBER, ), ) token_network_registry_proxy = blockchain_service.token_network_registry( token_network_registry_address) token_network_address = token_network_registry_proxy.add_token( token_address=token_proxy.address, channel_participant_deposit_limit= RED_EYES_PER_CHANNEL_PARTICIPANT_LIMIT, token_network_deposit_limit=RED_EYES_PER_TOKEN_NETWORK_LIMIT, block_identifier=deploy_client.get_confirmed_blockhash(), ) blockchain_service = ProxyManager( rpc_client=deploy_client, contract_manager=contract_manager, metadata=ProxyManagerMetadata( token_network_registry_deployed_at=GENESIS_BLOCK_NUMBER, filters_start_at=GENESIS_BLOCK_NUMBER, ), ) return blockchain_service.token_network(token_network_address)
def jsonrpc_services( proxy_manager: ProxyManager, private_keys: List[PrivateKey], secret_registry_address: SecretRegistryAddress, service_registry_address: ServiceRegistryAddress, token_network_registry_address: TokenNetworkRegistryAddress, web3: Web3, contract_manager: ContractManager, ) -> BlockchainServices: secret_registry = proxy_manager.secret_registry(secret_registry_address) service_registry = None if service_registry_address: service_registry = proxy_manager.service_registry(service_registry_address) deploy_registry = proxy_manager.token_network_registry(token_network_registry_address) blockchain_services = list() for privkey in private_keys: rpc_client = JSONRPCClient(web3, privkey) proxy_manager = ProxyManager( rpc_client=rpc_client, contract_manager=contract_manager, metadata=ProxyManagerMetadata( token_network_registry_deployed_at=GENESIS_BLOCK_NUMBER, filters_start_at=GENESIS_BLOCK_NUMBER, ), ) blockchain_services.append(proxy_manager) return BlockchainServices( deploy_registry=deploy_registry, secret_registry=secret_registry, service_registry=service_registry, proxy_manager=proxy_manager, blockchain_services=blockchain_services, )
def proxy_manager(deploy_key, deploy_client, contract_manager): return ProxyManager( rpc_client=deploy_client, contract_manager=contract_manager, metadata=ProxyManagerMetadata( token_network_registry_deployed_at=GENESIS_BLOCK_NUMBER, filters_start_at=GENESIS_BLOCK_NUMBER, ), )
def test_token_network_registry_max_token_networks( deploy_client, token_network_registry_address, contract_manager): """ get_max_token_networks() should return an integer """ proxy_manager = ProxyManager( rpc_client=deploy_client, contract_manager=contract_manager, metadata=ProxyManagerMetadata( token_network_registry_deployed_at=GENESIS_BLOCK_NUMBER, filters_start_at=GENESIS_BLOCK_NUMBER, ), ) token_network_registry_proxy = proxy_manager.token_network_registry( to_canonical_address(token_network_registry_address)) assert (token_network_registry_proxy.get_max_token_networks( block_identifier="latest") == UINT256_MAX)
def test_token_network_deposit_race( token_network_proxy, private_keys, token_proxy, web3, contract_manager ): assert token_network_proxy.settlement_timeout_min() == TEST_SETTLE_TIMEOUT_MIN assert token_network_proxy.settlement_timeout_max() == TEST_SETTLE_TIMEOUT_MAX token_network_address = to_canonical_address(token_network_proxy.proxy.address) c1_client = JSONRPCClient(web3, private_keys[1]) c2_client = JSONRPCClient(web3, private_keys[2]) proxy_manager = ProxyManager( rpc_client=c1_client, contract_manager=contract_manager, metadata=ProxyManagerMetadata( token_network_registry_deployed_at=GENESIS_BLOCK_NUMBER, filters_start_at=GENESIS_BLOCK_NUMBER, ), ) c1_token_network_proxy = proxy_manager.token_network( address=token_network_address, block_identifier=BLOCK_ID_LATEST ) token_proxy.transfer(c1_client.address, 10) channel_details = c1_token_network_proxy.new_netting_channel( partner=c2_client.address, settle_timeout=TEST_SETTLE_TIMEOUT_MIN, given_block_identifier=BLOCK_ID_LATEST, ) assert is_tx_hash_bytes(channel_details.transaction_hash) channel_identifier = channel_details.channel_identifier assert channel_identifier is not None c1_token_network_proxy.approve_and_set_total_deposit( given_block_identifier=BLOCK_ID_LATEST, channel_identifier=channel_identifier, total_deposit=2, partner=c2_client.address, ) with pytest.raises(BrokenPreconditionError): c1_token_network_proxy.approve_and_set_total_deposit( given_block_identifier=BLOCK_ID_LATEST, channel_identifier=channel_identifier, total_deposit=1, partner=c2_client.address, )
def test_register_secret_batch_with_pruned_block(secret_registry_proxy, web3, private_keys, contract_manager): """Test secret registration with a pruned given block.""" c1_client = JSONRPCClient(web3, private_keys[1]) c1_proxy_manager = ProxyManager( rpc_client=c1_client, contract_manager=contract_manager, metadata=ProxyManagerMetadata( token_network_registry_deployed_at=GENESIS_BLOCK_NUMBER, filters_start_at=GENESIS_BLOCK_NUMBER, ), ) # Now wait until this block becomes pruned pruned_number = c1_proxy_manager.client.block_number() c1_proxy_manager.wait_until_block(target_block_number=pruned_number + STATE_PRUNING_AFTER_BLOCKS) secret_registry_batch_happy_path(secret_registry_proxy)
def test_query_pruned_state(token_network_proxy, private_keys, web3, contract_manager): """A test for https://github.com/raiden-network/raiden/issues/3566 If pruning limit blocks pass make sure that can_query_state_for_block returns False. """ token_network_address = to_canonical_address( token_network_proxy.proxy.contract.address) c1_client = JSONRPCClient(web3, private_keys[1]) c1_proxy_manager = ProxyManager( rpc_client=c1_client, contract_manager=contract_manager, metadata=ProxyManagerMetadata( token_network_registry_deployed_at=GENESIS_BLOCK_NUMBER, filters_start_at=GENESIS_BLOCK_NUMBER, ), ) c2_client = JSONRPCClient(web3, private_keys[2]) c1_token_network_proxy = c1_proxy_manager.token_network( token_network_address) # create a channel and query the state at the current block hash channel_identifier = c1_token_network_proxy.new_netting_channel( partner=c2_client.address, settle_timeout=10, given_block_identifier="latest") block = c1_client.web3.eth.getBlock("latest") block_number = int(block["number"]) block_hash = bytes(block["hash"]) channel_id = c1_token_network_proxy.get_channel_identifier( participant1=c1_client.address, participant2=c2_client.address, block_identifier=block_hash) assert channel_id == channel_identifier assert c1_client.can_query_state_for_block(block_hash) # wait until state pruning kicks in target_block = block_number + STATE_PRUNING_AFTER_BLOCKS + 1 c1_proxy_manager.wait_until_block(target_block_number=target_block) # and now query again for the old block identifier and see we can't query assert not c1_client.can_query_state_for_block(block_hash)
def test_token_network_registry_with_zero_token_address( deploy_client, token_network_registry_address, contract_manager): """ Try to register a token at 0x0000..00 """ proxy_manager = ProxyManager( rpc_client=deploy_client, contract_manager=contract_manager, metadata=ProxyManagerMetadata( token_network_registry_deployed_at=GENESIS_BLOCK_NUMBER, filters_start_at=GENESIS_BLOCK_NUMBER, ), ) token_network_registry_proxy = proxy_manager.token_network_registry( token_network_registry_address) with pytest.raises(InvalidTokenAddress, match="0x00..00 will fail"): token_network_registry_proxy.add_token( token_address=NULL_ADDRESS_BYTES, channel_participant_deposit_limit=TokenAmount(UINT256_MAX), token_network_deposit_limit=TokenAmount(UINT256_MAX), block_identifier=deploy_client.get_confirmed_blockhash(), )
def get_proxy_manager(client: JSONRPCClient, deploy: DeployedContracts) -> ProxyManager: contract_manager = ContractManager( contracts_precompiled_path(RAIDEN_CONTRACT_VERSION)) assert "contracts" in deploy, deploy token_network_deployment_details = deploy["contracts"][ CONTRACT_TOKEN_NETWORK_REGISTRY] deployed_at = token_network_deployment_details["block_number"] token_network_registry_deployed_at = BlockNumber(deployed_at) return ProxyManager( client, contract_manager, ProxyManagerMetadata( token_network_registry_deployed_at= token_network_registry_deployed_at, filters_start_at=token_network_registry_deployed_at, ), )
def setup_raiden( transport, matrix_server, print_step, contracts_version, eth_client, eth_rpc_endpoint, web3, base_datadir, keystore, ): print_step("Deploying Raiden contracts") if eth_client is EthClient.PARITY: client = JSONRPCClient(web3, get_private_key(keystore), gas_estimate_correction=lambda gas: gas * 2) else: client = JSONRPCClient(web3, get_private_key(keystore)) contract_manager = ContractManager( contracts_precompiled_path(contracts_version)) proxy_manager = ProxyManager( rpc_client=client, contract_manager=contract_manager, metadata=ProxyManagerMetadata( token_network_registry_deployed_at=GENESIS_BLOCK_NUMBER, filters_start_at=GENESIS_BLOCK_NUMBER, ), ) token = deploy_token( deploy_client=client, contract_manager=contract_manager, initial_amount=1000, decimals=0, token_name="TKN", token_symbol="TKN", token_contract_name=CONTRACT_HUMAN_STANDARD_TOKEN, ) contract_addresses = deploy_smoketest_contracts( client=client, chain_id=NETWORKNAME_TO_ID["smoketest"], contract_manager=contract_manager, token_address=to_canonical_address(token.contract.address), ) registry = proxy_manager.token_network_registry( contract_addresses[CONTRACT_TOKEN_NETWORK_REGISTRY]) registry.add_token( token_address=to_canonical_address(token.contract.address), channel_participant_deposit_limit=UINT256_MAX, token_network_deposit_limit=UINT256_MAX, block_identifier=client.get_confirmed_blockhash(), ) print_step("Setting up Raiden") tokennetwork_registry_contract_address = to_checksum_address( contract_addresses[CONTRACT_TOKEN_NETWORK_REGISTRY]) secret_registry_contract_address = to_checksum_address( contract_addresses[CONTRACT_SECRET_REGISTRY]) args = { "address": to_checksum_address(TEST_ACCOUNT_ADDRESS), "datadir": keystore, "eth_rpc_endpoint": eth_rpc_endpoint, "gas_price": "fast", "keystore_path": keystore, "matrix_server": matrix_server, "network_id": str(NETWORKNAME_TO_ID["smoketest"]), "password_file": click.File()(os.path.join(base_datadir, "pw")), "tokennetwork_registry_contract_address": tokennetwork_registry_contract_address, "secret_registry_contract_address": secret_registry_contract_address, "sync_check": False, "transport": transport, } service_registry_contract_address = to_checksum_address( contract_addresses[CONTRACT_SERVICE_REGISTRY]) args[ "service_registry_contract_address"] = service_registry_contract_address monitoring_service_contract_address = to_checksum_address( contract_addresses[CONTRACT_MONITORING_SERVICE]) args[ "monitoring_service_contract_address"] = monitoring_service_contract_address one_to_n_contract_address = to_checksum_address( contract_addresses[CONTRACT_ONE_TO_N]) args["one_to_n_contract_address"] = one_to_n_contract_address # Wait until the secret registry is confirmed, otherwise the App # inialization will fail, needed for the check # `check_ethereum_confirmed_block_is_not_pruned`. current_block = client.block_number() target_block_number = current_block + DEFAULT_NUMBER_OF_BLOCK_CONFIRMATIONS while current_block < target_block_number: current_block = client.block_number() sleep(0.5) return { "args": args, "contract_addresses": contract_addresses, "token": token }
def run_app( address: Address, keystore_path: str, gas_price: Callable, eth_rpc_endpoint: str, user_deposit_contract_address: Optional[UserDepositAddress], api_address: Endpoint, rpc: bool, rpccorsdomain: str, sync_check: bool, console: bool, password_file: TextIO, web_ui: bool, datadir: Optional[str], matrix_server: str, network_id: ChainID, environment_type: Environment, unrecoverable_error_should_crash: bool, pathfinding_service_address: str, pathfinding_max_paths: int, enable_monitoring: bool, resolver_endpoint: str, default_reveal_timeout: BlockTimeout, default_settle_timeout: BlockTimeout, routing_mode: RoutingMode, flat_fee: Tuple[Tuple[TokenAddress, FeeAmount], ...], proportional_fee: Tuple[Tuple[TokenAddress, ProportionalFeeAmount], ...], proportional_imbalance_fee: Tuple[Tuple[TokenAddress, ProportionalFeeAmount], ...], blockchain_query_interval: float, cap_mediation_fees: bool, ** kwargs: Any, # FIXME: not used here, but still receives stuff in smoketest ) -> App: # pylint: disable=too-many-locals,too-many-branches,too-many-statements,unused-argument token_network_registry_deployed_at: Optional[BlockNumber] smart_contracts_start_at: BlockNumber if datadir is None: datadir = os.path.join(os.path.expanduser("~"), ".raiden") account_manager = AccountManager(keystore_path) web3 = Web3(HTTPProvider(rpc_normalized_endpoint(eth_rpc_endpoint))) check_sql_version() check_ethereum_has_accounts(account_manager) check_ethereum_client_is_supported(web3) check_ethereum_network_id(network_id, web3) address, privatekey = get_account_and_private_key(account_manager, address, password_file) api_host, api_port = split_endpoint(api_address) if not api_port: api_port = DEFAULT_HTTP_SERVER_PORT domain_list = [] if rpccorsdomain: if "," in rpccorsdomain: for domain in rpccorsdomain.split(","): domain_list.append(str(domain)) else: domain_list.append(str(rpccorsdomain)) # Set up config fee_config = prepare_mediation_fee_config( cli_token_to_flat_fee=flat_fee, cli_token_to_proportional_fee=proportional_fee, cli_token_to_proportional_imbalance_fee=proportional_imbalance_fee, cli_cap_mediation_fees=cap_mediation_fees, ) rest_api_config = RestApiConfig( rest_api_enabled=rpc, web_ui_enabled=rpc and web_ui, cors_domain_list=domain_list, eth_rpc_endpoint=eth_rpc_endpoint, host=api_host, port=api_port, ) config = RaidenConfig( chain_id=network_id, environment_type=environment_type, reveal_timeout=default_reveal_timeout, settle_timeout=default_settle_timeout, console=console, mediation_fees=fee_config, unrecoverable_error_should_crash=unrecoverable_error_should_crash, resolver_endpoint=resolver_endpoint, rest_api=rest_api_config, ) config.blockchain.query_interval = blockchain_query_interval config.services.monitoring_enabled = enable_monitoring config.services.pathfinding_max_paths = pathfinding_max_paths config.transport.server = matrix_server contracts = load_deployed_contracts_data(config, network_id) rpc_client = JSONRPCClient( web3=web3, privkey=privatekey, gas_price_strategy=gas_price, block_num_confirmations=DEFAULT_NUMBER_OF_BLOCK_CONFIRMATIONS, ) token_network_registry_deployed_at = None if "TokenNetworkRegistry" in contracts: token_network_registry_deployed_at = BlockNumber( contracts[CONTRACT_TOKEN_NETWORK_REGISTRY]["block_number"]) if token_network_registry_deployed_at is None: smart_contracts_start_at = get_smart_contracts_start_at(network_id) else: smart_contracts_start_at = token_network_registry_deployed_at proxy_manager = ProxyManager( rpc_client=rpc_client, contract_manager=ContractManager(config.contracts_path), metadata=ProxyManagerMetadata( token_network_registry_deployed_at= token_network_registry_deployed_at, filters_start_at=smart_contracts_start_at, ), ) api_server: Optional[APIServer] = None if config.rest_api.rest_api_enabled: api_server = start_api_server(rpc_client=rpc_client, config=config.rest_api, eth_rpc_endpoint=eth_rpc_endpoint) if sync_check: check_synced(rpc_client) # The user has the option to launch Raiden with a custom # user deposit contract address. This can be used to load # the addresses for the rest of the deployed contracts. # The steps done here make sure that if a UDC address is provided, # the address has to be valid and all the connected contracts # are configured properly. # If a UDC address was not provided, Raiden would fall back # to using the ones deployed and provided by the raiden-contracts package. if user_deposit_contract_address is not None: if not is_address(user_deposit_contract_address): raise RaidenError("The user deposit address is invalid") deployed_addresses = load_deployment_addresses_from_udc( proxy_manager=proxy_manager, user_deposit_address=user_deposit_contract_address, block_identifier=BLOCK_ID_LATEST, ) else: deployed_addresses = load_deployment_addresses_from_contracts( contracts=contracts) # Load the available matrix servers when no matrix server is given # The list is used in a PFS check if config.transport.server == MATRIX_AUTO_SELECT_SERVER: fetch_available_matrix_servers(config.transport, environment_type) raiden_bundle = raiden_bundle_from_contracts_deployment( proxy_manager=proxy_manager, token_network_registry_address=deployed_addresses. token_network_registry_address, secret_registry_address=deployed_addresses.secret_registry_address, ) services_bundle = services_bundle_from_contracts_deployment( config=config, deployed_addresses=deployed_addresses, proxy_manager=proxy_manager, routing_mode=routing_mode, pathfinding_service_address=pathfinding_service_address, enable_monitoring=enable_monitoring, ) check_ethereum_confirmed_block_is_not_pruned( jsonrpc_client=rpc_client, secret_registry=raiden_bundle.secret_registry, confirmation_blocks=config.blockchain.confirmation_blocks, ) database_path = Path( os.path.join( datadir, f"node_{pex(address)}", f"netid_{network_id}", f"network_{pex(raiden_bundle.token_network_registry.address)}", f"v{RAIDEN_DB_VERSION}_log.db", )) config.database_path = database_path print(f"Raiden is running in {environment_type.value.lower()} mode") print("\nYou are connected to the '{}' network and the DB path is: {}". format(ID_TO_CHAINNAME.get(network_id, network_id), database_path)) matrix_transport = setup_matrix(config.transport, config.services, environment_type, routing_mode) event_handler: EventHandler = RaidenEventHandler() # User should be told how to set fees, if using default fee settings log.debug("Fee Settings", fee_settings=fee_config) has_default_fees = (len(fee_config.token_to_flat_fee) == 0 and len(fee_config.token_to_proportional_fee) == 0 and len(fee_config.token_to_proportional_imbalance_fee) == 0) if has_default_fees: click.secho( "Default fee settings are used. " "If you want use Raiden with mediation fees - flat, proportional and imbalance fees - " "see https://raiden-network.readthedocs.io/en/latest/overview_and_guide.html#firing-it-up", # noqa: E501 fg="yellow", ) # Only send feedback when PFS is used if routing_mode == RoutingMode.PFS: event_handler = PFSFeedbackEventHandler(event_handler) message_handler = MessageHandler() one_to_n_address = (services_bundle.one_to_n.address if services_bundle.one_to_n is not None else None) monitoring_service_address = (services_bundle.monitoring_service.address if services_bundle.monitoring_service is not None else None) raiden_app = App( config=config, rpc_client=rpc_client, proxy_manager=proxy_manager, query_start_block=smart_contracts_start_at, default_registry=raiden_bundle.token_network_registry, default_secret_registry=raiden_bundle.secret_registry, default_service_registry=services_bundle.service_registry, default_user_deposit=services_bundle.user_deposit, default_one_to_n_address=one_to_n_address, default_msc_address=monitoring_service_address, transport=matrix_transport, raiden_event_handler=event_handler, message_handler=message_handler, routing_mode=routing_mode, api_server=api_server, ) raiden_app.start() return raiden_app
def test_register_secret_happy_path(web3: Web3, secret_registry_proxy: SecretRegistry, contract_manager: ContractManager) -> None: """Test happy path of SecretRegistry with a single secret. Test that `register_secret` changes the smart contract state by registering the secret, this can be verified by the block height and the existence of the SecretRegistered event. """ secret = make_secret() secrethash = sha256_secrethash(secret) secret_unregistered = make_secret() secrethash_unregistered = sha256_secrethash(secret_unregistered) secret_registered_filter = secret_registry_proxy.secret_registered_filter( GENESIS_BLOCK_NUMBER) assert not secret_registry_proxy.is_secret_registered( secrethash=secrethash, block_identifier="latest" ), "Test setup is invalid, secret must be unknown" assert not secret_registry_proxy.is_secret_registered( secrethash=secrethash_unregistered, block_identifier="latest" ), "Test setup is invalid, secret must be unknown" proxy_manager = ProxyManager( rpc_client=secret_registry_proxy.client, contract_manager=contract_manager, metadata=ProxyManagerMetadata( token_network_registry_deployed_at=GENESIS_BLOCK_NUMBER, filters_start_at=GENESIS_BLOCK_NUMBER, ), ) proxy_manager.wait_until_block(BlockNumber(STATE_PRUNING_AFTER_BLOCKS + 1)) with pytest.raises(NoStateForBlockIdentifier): secret_registry_proxy.is_secret_registered( secrethash=secrethash_unregistered, block_identifier=0) secret_registry_proxy.register_secret(secret=secret) logs = [ secret_registry_proxy.proxy.decode_event(encoded_log) for encoded_log in secret_registered_filter.get_new_entries(web3.eth.blockNumber) ] secret_registered = must_have_event(logs, { "event": "SecretRevealed", "args": { "secrethash": secrethash } }) msg = "SecretRegistry.register_secret returned but the SecretRevealed event was not emitted." assert secret_registered, msg registered_block = secret_registry_proxy.get_secret_registration_block_by_secrethash( secrethash=secrethash, block_identifier="latest") msg = ( "Block height returned by the SecretRegistry.get_secret_registration_block_by_secrethash " "does not match the block from the SecretRevealed event.") assert secret_registered["blockNumber"] == registered_block, msg block = secret_registry_proxy.get_secret_registration_block_by_secrethash( secrethash=secrethash_unregistered, block_identifier="latest") assert block is None, "The secret that was not registered must not change block height!"
def test_token_network_registry_allows_the_last_slot_to_be_used( deploy_client, token_network_registry_address, contract_manager, token_contract_name): proxy_manager = ProxyManager( rpc_client=deploy_client, contract_manager=contract_manager, metadata=ProxyManagerMetadata( token_network_registry_deployed_at=GENESIS_BLOCK_NUMBER, filters_start_at=GENESIS_BLOCK_NUMBER, ), ) confirmed_block_identifier = deploy_client.get_confirmed_blockhash() token_network_registry_proxy = proxy_manager.token_network_registry( token_network_registry_address, block_identifier=confirmed_block_identifier) assert (token_network_registry_proxy.get_token_network_created( block_identifier=BLOCK_ID_LATEST) == 0) test_token = deploy_token( deploy_client=deploy_client, contract_manager=contract_manager, initial_amount=TokenAmount(1000), decimals=0, token_name="TKN", token_symbol="TKN", token_contract_name=token_contract_name, ) first_token_address = TokenAddress(to_canonical_address( test_token.address)) preblockhash = deploy_client.get_confirmed_blockhash() # Register a valid token, this is the last slot and should succeeded token_network_registry_proxy.add_token( token_address=first_token_address, channel_participant_deposit_limit=TokenAmount(UINT256_MAX), token_network_deposit_limit=TokenAmount(UINT256_MAX), given_block_identifier=preblockhash, ) test_token = deploy_token( deploy_client=deploy_client, contract_manager=contract_manager, initial_amount=TokenAmount(1000), decimals=0, token_name="TKN", token_symbol="TKN", token_contract_name=token_contract_name, ) second_token_address = TokenAddress( to_canonical_address(test_token.address)) preblockhash = deploy_client.get_confirmed_blockhash() # Tries to register a new valid token after all slots have been used. This # has to fail. with pytest.raises(MaxTokenNetworkNumberReached): token_network_registry_proxy.add_token( token_address=second_token_address, channel_participant_deposit_limit=TokenAmount(UINT256_MAX), token_network_deposit_limit=TokenAmount(UINT256_MAX), given_block_identifier=preblockhash, )
def test_token_network_registry( deploy_client: JSONRPCClient, contract_manager: ContractManager, token_network_registry_address: TokenNetworkRegistryAddress, token_contract_name: str, ) -> None: proxy_manager = ProxyManager( rpc_client=deploy_client, contract_manager=contract_manager, metadata=ProxyManagerMetadata( token_network_registry_deployed_at=GENESIS_BLOCK_NUMBER, filters_start_at=GENESIS_BLOCK_NUMBER, ), ) confirmed_block_identifier = deploy_client.get_confirmed_blockhash() token_network_registry_proxy = proxy_manager.token_network_registry( token_network_registry_address, block_identifier=confirmed_block_identifier) assert (token_network_registry_proxy.settlement_timeout_min( BLOCK_ID_LATEST) == TEST_SETTLE_TIMEOUT_MIN) assert (token_network_registry_proxy.settlement_timeout_max( BLOCK_ID_LATEST) == TEST_SETTLE_TIMEOUT_MAX) assert (token_network_registry_proxy.get_token_network_created( block_identifier=BLOCK_ID_LATEST) == 0) bad_token_address = make_token_address() # Registering a non-existing token network should fail with pytest.raises(AddressWithoutCode): token_network_registry_proxy.add_token( token_address=bad_token_address, channel_participant_deposit_limit=TokenAmount(UINT256_MAX), token_network_deposit_limit=TokenAmount(UINT256_MAX), given_block_identifier=confirmed_block_identifier, ) test_token = deploy_token( deploy_client=deploy_client, contract_manager=contract_manager, initial_amount=TokenAmount(1000), decimals=0, token_name="TKN", token_symbol="TKN", token_contract_name=token_contract_name, ) test_token_address = TokenAddress(to_canonical_address(test_token.address)) # Check the proper exception is raised if the token does not comply to the # ERC20 interface. In this case the token does not have the totalSupply() # function implemented #3697 which is validated in the smart contract. with patch.object(Token, "total_supply", return_value=None): with pytest.raises(InvalidToken): token_network_registry_proxy.add_token( token_address=test_token_address, channel_participant_deposit_limit=TokenAmount(UINT256_MAX), token_network_deposit_limit=TokenAmount(UINT256_MAX), given_block_identifier=deploy_client.get_confirmed_blockhash(), ) # Register a valid token preblockhash = deploy_client.get_confirmed_blockhash() token_network_address = token_network_registry_proxy.add_token( token_address=test_token_address, channel_participant_deposit_limit=TokenAmount(UINT256_MAX), token_network_deposit_limit=TokenAmount(UINT256_MAX), given_block_identifier=preblockhash, ) assert token_network_address is not None assert (token_network_registry_proxy.get_token_network_created( block_identifier=BLOCK_ID_LATEST) == 1) # Re-registering the same token should fail with a recoverable error # because it is a race condition. with pytest.raises(RaidenRecoverableError): token_network_registry_proxy.add_token( token_address=test_token_address, channel_participant_deposit_limit=TokenAmount(UINT256_MAX), token_network_deposit_limit=TokenAmount(UINT256_MAX), given_block_identifier=preblockhash, ) logs = token_network_registry_proxy.filter_token_added_events() assert is_same_address(logs[0]["args"]["token_address"], test_token.address) assert is_same_address(logs[0]["args"]["token_network_address"], token_network_address) assert (token_network_registry_proxy.get_token_network( bad_token_address, BLOCK_ID_LATEST) is None) result_address = token_network_registry_proxy.get_token_network( test_token_address, BLOCK_ID_LATEST) assert result_address assert to_normalized_address(result_address) == to_normalized_address( token_network_address) with pytest.raises(ValueError): assert token_network_registry_proxy.get_token_network( None, BLOCK_ID_LATEST # type: ignore ) # These are not registered token addresses assert (token_network_registry_proxy.get_token_network( bad_token_address, BLOCK_ID_LATEST) is None) assert (token_network_registry_proxy.get_token_network( test_token_address, BLOCK_ID_LATEST) is not None) address = token_network_registry_proxy.get_token_network( TokenAddress(token_network_address), BLOCK_ID_LATEST) assert address is None
def test_token_network_proxy(token_network_proxy, private_keys, token_proxy, chain_id, web3, contract_manager): assert token_network_proxy.settlement_timeout_min( ) == TEST_SETTLE_TIMEOUT_MIN assert token_network_proxy.settlement_timeout_max( ) == TEST_SETTLE_TIMEOUT_MAX token_network_address = to_canonical_address( token_network_proxy.proxy.contract.address) c1_signer = LocalSigner(private_keys[1]) c1_client = JSONRPCClient(web3, private_keys[1]) c1_proxy_manager = ProxyManager( rpc_client=c1_client, contract_manager=contract_manager, metadata=ProxyManagerMetadata( token_network_registry_deployed_at=GENESIS_BLOCK_NUMBER, filters_start_at=GENESIS_BLOCK_NUMBER, ), ) c2_client = JSONRPCClient(web3, private_keys[2]) c2_proxy_manager = ProxyManager( rpc_client=c2_client, contract_manager=contract_manager, metadata=ProxyManagerMetadata( token_network_registry_deployed_at=GENESIS_BLOCK_NUMBER, filters_start_at=GENESIS_BLOCK_NUMBER, ), ) c2_signer = LocalSigner(private_keys[2]) c1_token_network_proxy = c1_proxy_manager.token_network( token_network_address) c2_token_network_proxy = c2_proxy_manager.token_network( token_network_address) initial_token_balance = 100 token_proxy.transfer(c1_client.address, initial_token_balance) token_proxy.transfer(c2_client.address, initial_token_balance) initial_balance_c1 = token_proxy.balance_of(c1_client.address) assert initial_balance_c1 == initial_token_balance initial_balance_c2 = token_proxy.balance_of(c2_client.address) assert initial_balance_c2 == initial_token_balance # instantiating a new channel - test basic assumptions assert (c1_token_network_proxy.get_channel_identifier_or_none( participant1=c1_client.address, participant2=c2_client.address, block_identifier="latest", ) is None) msg = "Hex encoded addresses are not supported, an assertion must be raised" with pytest.raises(AssertionError): c1_token_network_proxy.get_channel_identifier( participant1=to_checksum_address(c1_client.address), participant2=to_checksum_address(c2_client.address), block_identifier="latest", ) pytest.fail(msg) msg = "Zero is not a valid channel_identifier identifier, an exception must be raised." with pytest.raises(InvalidChannelID): assert c1_token_network_proxy.channel_is_opened( participant1=c1_client.address, participant2=c2_client.address, block_identifier="latest", channel_identifier=0, ) pytest.fail(msg) msg = "Zero is not a valid channel_identifier identifier. an exception must be raised." with pytest.raises(InvalidChannelID): assert c1_token_network_proxy.channel_is_closed( participant1=c1_client.address, participant2=c2_client.address, block_identifier="latest", channel_identifier=0, ) pytest.fail(msg) msg = ("Opening a channel with a settle_timeout lower then token " "network's minimum will fail. This must be validated and the " "transaction must not be sent.") with pytest.raises(InvalidSettleTimeout): c1_token_network_proxy.new_netting_channel( partner=c2_client.address, settle_timeout=TEST_SETTLE_TIMEOUT_MIN - 1, given_block_identifier="latest", ) pytest.fail(msg) # Using exactly the minimal timeout must succeed c1_token_network_proxy.new_netting_channel( partner=make_address(), settle_timeout=TEST_SETTLE_TIMEOUT_MIN, given_block_identifier="latest", ) msg = ("Opening a channel with a settle_timeout larger then token " "network's maximum will fail. This must be validated and the " "transaction must not be sent.") with pytest.raises(InvalidSettleTimeout): c1_token_network_proxy.new_netting_channel( partner=c2_client.address, settle_timeout=TEST_SETTLE_TIMEOUT_MAX + 1, given_block_identifier="latest", ) pytest.fail(msg) # Using exactly the maximal timeout must succeed c1_token_network_proxy.new_netting_channel( partner=make_address(), settle_timeout=TEST_SETTLE_TIMEOUT_MAX, given_block_identifier="latest", ) msg = ( "Opening a channel with itself is not allow. This must be validated and " "the transaction must not be sent.") with pytest.raises(SamePeerAddress): c1_token_network_proxy.new_netting_channel( partner=c1_client.address, settle_timeout=TEST_SETTLE_TIMEOUT_MIN, given_block_identifier="latest", ) pytest.fail(msg) msg = "Trying a deposit to an inexisting channel must fail." with pytest.raises(BrokenPreconditionError): c1_token_network_proxy.set_total_deposit( given_block_identifier="latest", channel_identifier=100, total_deposit=1, partner=c2_client.address, ) pytest.fail(msg) empty_balance_proof = BalanceProof( channel_identifier=100, token_network_address=c1_token_network_proxy.address, balance_hash=encode_hex(EMPTY_BALANCE_HASH), nonce=0, chain_id=chain_id, transferred_amount=0, ) closing_data = (empty_balance_proof.serialize_bin( msg_type=MessageTypeId.BALANCE_PROOF) + EMPTY_SIGNATURE) msg = "Trying to close an inexisting channel must fail." match = "The channel was not open at the provided block" with pytest.raises(RaidenUnrecoverableError, match=match): c1_token_network_proxy.close( channel_identifier=100, partner=c2_client.address, balance_hash=EMPTY_HASH, nonce=0, additional_hash=EMPTY_HASH, non_closing_signature=EMPTY_SIGNATURE, closing_signature=c1_signer.sign(data=closing_data), given_block_identifier="latest", ) pytest.fail(msg) channel_identifier = c1_token_network_proxy.new_netting_channel( partner=c2_client.address, settle_timeout=TEST_SETTLE_TIMEOUT_MIN, given_block_identifier="latest", ) msg = "new_netting_channel did not return a valid channel id" assert isinstance(channel_identifier, T_ChannelID), msg msg = "multiple channels with the same peer are not allowed" with pytest.raises(BrokenPreconditionError): c1_token_network_proxy.new_netting_channel( partner=c2_client.address, settle_timeout=TEST_SETTLE_TIMEOUT_MIN, given_block_identifier="latest", ) pytest.fail(msg) assert (c1_token_network_proxy.get_channel_identifier_or_none( participant1=c1_client.address, participant2=c2_client.address, block_identifier="latest", ) is not None) assert (c1_token_network_proxy.channel_is_opened( participant1=c1_client.address, participant2=c2_client.address, block_identifier="latest", channel_identifier=channel_identifier, ) is True) msg = "set_total_deposit must fail if the amount exceed the account's balance" with pytest.raises(BrokenPreconditionError): c1_token_network_proxy.set_total_deposit( given_block_identifier="latest", channel_identifier=channel_identifier, total_deposit=initial_token_balance + 1, partner=c2_client.address, ) pytest.fail(msg) msg = "set_total_deposit must fail with a negative amount" with pytest.raises(BrokenPreconditionError): c1_token_network_proxy.set_total_deposit( given_block_identifier="latest", channel_identifier=channel_identifier, total_deposit=-1, partner=c2_client.address, ) pytest.fail(msg) msg = "set_total_deposit must fail with a zero amount" with pytest.raises(BrokenPreconditionError): c1_token_network_proxy.set_total_deposit( given_block_identifier="latest", channel_identifier=channel_identifier, total_deposit=0, partner=c2_client.address, ) pytest.fail(msg) c1_token_network_proxy.set_total_deposit( given_block_identifier="latest", channel_identifier=channel_identifier, total_deposit=10, partner=c2_client.address, ) transferred_amount = 3 balance_proof = BalanceProof( channel_identifier=channel_identifier, token_network_address=to_checksum_address(token_network_address), nonce=1, chain_id=chain_id, transferred_amount=transferred_amount, ) signature = c1_signer.sign(data=balance_proof.serialize_bin()) balance_proof.signature = encode_hex(signature) signature_number = int.from_bytes(signature, "big") bit_to_change = random.randint(0, SIGNATURE_SIZE_IN_BITS - 1) signature_number_bit_flipped = signature_number ^ (2**bit_to_change) invalid_signatures = [ EMPTY_SIGNATURE, b"\x11" * 65, signature_number_bit_flipped.to_bytes(len(signature), "big"), ] msg = "close must fail if the closing_signature is invalid" for invalid_signature in invalid_signatures: closing_data = ( balance_proof.serialize_bin(msg_type=MessageTypeId.BALANCE_PROOF) + invalid_signature) with pytest.raises(RaidenUnrecoverableError): c2_token_network_proxy.close( channel_identifier=channel_identifier, partner=c1_client.address, balance_hash=decode_hex(balance_proof.balance_hash), nonce=balance_proof.nonce, additional_hash=decode_hex(balance_proof.additional_hash), non_closing_signature=invalid_signature, closing_signature=c2_signer.sign(data=closing_data), given_block_identifier="latest", ) pytest.fail(msg) blocknumber_prior_to_close = c2_client.block_number() closing_data = balance_proof.serialize_bin( msg_type=MessageTypeId.BALANCE_PROOF) + decode_hex( balance_proof.signature) c2_token_network_proxy.close( channel_identifier=channel_identifier, partner=c1_client.address, balance_hash=decode_hex(balance_proof.balance_hash), nonce=balance_proof.nonce, additional_hash=decode_hex(balance_proof.additional_hash), non_closing_signature=decode_hex(balance_proof.signature), closing_signature=c2_signer.sign(data=closing_data), given_block_identifier="latest", ) assert (c1_token_network_proxy.channel_is_closed( participant1=c1_client.address, participant2=c2_client.address, block_identifier="latest", channel_identifier=channel_identifier, ) is True) assert (c1_token_network_proxy.get_channel_identifier_or_none( participant1=c1_client.address, participant2=c2_client.address, block_identifier="latest", ) is not None) msg = ( "given_block_identifier is the block at which the transaction is being " "sent. If the channel is already closed at that block the client code " "has a programming error. An exception is raised for that.") with pytest.raises(RaidenUnrecoverableError): c2_token_network_proxy.close( channel_identifier=channel_identifier, partner=c1_client.address, balance_hash=decode_hex(balance_proof.balance_hash), nonce=balance_proof.nonce, additional_hash=decode_hex(balance_proof.additional_hash), non_closing_signature=decode_hex(balance_proof.signature), closing_signature=c2_signer.sign(data=closing_data), given_block_identifier="latest", ) pytest.fail(msg) msg = ("The channel cannot be closed two times. If it was not closed at " "given_block_identifier but it is closed at the time the proxy is " "called an exception must be raised.") with pytest.raises(RaidenRecoverableError): c2_token_network_proxy.close( channel_identifier=channel_identifier, partner=c1_client.address, balance_hash=decode_hex(balance_proof.balance_hash), nonce=balance_proof.nonce, additional_hash=decode_hex(balance_proof.additional_hash), non_closing_signature=decode_hex(balance_proof.signature), closing_signature=c2_signer.sign(data=closing_data), given_block_identifier=blocknumber_prior_to_close, ) pytest.fail(msg) msg = "depositing to a closed channel must fail" match = "closed" with pytest.raises(RaidenRecoverableError, match=match): c2_token_network_proxy.set_total_deposit( given_block_identifier=blocknumber_prior_to_close, channel_identifier=channel_identifier, total_deposit=20, partner=c1_client.address, ) pytest.fail(msg) c1_proxy_manager.wait_until_block( target_block_number=c1_proxy_manager.client.block_number() + TEST_SETTLE_TIMEOUT_MIN) invalid_transferred_amount = 1 msg = "settle with invalid transferred_amount data must fail" with pytest.raises(BrokenPreconditionError): c2_token_network_proxy.settle( channel_identifier=channel_identifier, transferred_amount=invalid_transferred_amount, locked_amount=0, locksroot=LOCKSROOT_OF_NO_LOCKS, partner=c1_client.address, partner_transferred_amount=transferred_amount, partner_locked_amount=0, partner_locksroot=LOCKSROOT_OF_NO_LOCKS, given_block_identifier="latest", ) pytest.fail(msg) c2_token_network_proxy.settle( channel_identifier=channel_identifier, transferred_amount=0, locked_amount=0, locksroot=LOCKSROOT_OF_NO_LOCKS, partner=c1_client.address, partner_transferred_amount=transferred_amount, partner_locked_amount=0, partner_locksroot=LOCKSROOT_OF_NO_LOCKS, given_block_identifier="latest", ) assert (c1_token_network_proxy.get_channel_identifier_or_none( participant1=c1_client.address, participant2=c2_client.address, block_identifier="latest", ) is None) assert token_proxy.balance_of(c1_client.address) == (initial_balance_c1 - transferred_amount) assert token_proxy.balance_of(c2_client.address) == (initial_balance_c2 + transferred_amount) msg = "depositing to a settled channel must fail" with pytest.raises(BrokenPreconditionError): c1_token_network_proxy.set_total_deposit( given_block_identifier="latest", channel_identifier=channel_identifier, total_deposit=10, partner=c2_client.address, ) pytest.fail(msg)
def test_payment_channel_proxy_basics( token_network_registry_address: TokenNetworkRegistryAddress, token_network_proxy: TokenNetwork, token_proxy: Token, chain_id: ChainID, private_keys: List[PrivateKey], web3: Web3, contract_manager: ContractManager, reveal_timeout: BlockTimeout, ) -> None: token_network_address = token_network_proxy.address partner = privatekey_to_address(private_keys[0]) rpc_client = JSONRPCClient(web3, private_keys[1]) proxy_manager = ProxyManager( rpc_client=rpc_client, contract_manager=contract_manager, metadata=ProxyManagerMetadata( token_network_registry_deployed_at=GENESIS_BLOCK_NUMBER, filters_start_at=GENESIS_BLOCK_NUMBER, ), ) token_network_proxy = proxy_manager.token_network( address=token_network_address, block_identifier=BLOCK_ID_LATEST ) start_block = web3.eth.blockNumber channel_details = token_network_proxy.new_netting_channel( partner=partner, settle_timeout=TEST_SETTLE_TIMEOUT_MIN, given_block_identifier=BLOCK_ID_LATEST, ) channel_identifier = channel_details.channel_identifier assert channel_identifier is not None channel_state = NettingChannelState( canonical_identifier=CanonicalIdentifier( chain_identifier=chain_id, token_network_address=token_network_address, channel_identifier=channel_identifier, ), token_address=token_network_proxy.token_address(), token_network_registry_address=token_network_registry_address, reveal_timeout=reveal_timeout, settle_timeout=BlockTimeout(TEST_SETTLE_TIMEOUT_MIN), fee_schedule=FeeScheduleState(), our_state=NettingChannelEndState( address=token_network_proxy.client.address, contract_balance=Balance(0) ), partner_state=NettingChannelEndState(address=partner, contract_balance=Balance(0)), open_transaction=SuccessfulTransactionState(finished_block_number=BlockNumber(0)), ) channel_proxy_1 = proxy_manager.payment_channel( channel_state=channel_state, block_identifier=BLOCK_ID_LATEST ) assert channel_proxy_1.channel_identifier == channel_identifier assert channel_proxy_1.opened(BLOCK_ID_LATEST) is True # Test deposit initial_token_balance = 100 token_proxy.transfer(rpc_client.address, TokenAmount(initial_token_balance)) assert token_proxy.balance_of(rpc_client.address) == initial_token_balance assert token_proxy.balance_of(partner) == 0 channel_proxy_1.approve_and_set_total_deposit( total_deposit=TokenAmount(10), block_identifier=BLOCK_ID_LATEST ) # ChannelOpened, ChannelNewDeposit channel_events = get_all_netting_channel_events( proxy_manager=proxy_manager, token_network_address=token_network_address, netting_channel_identifier=channel_proxy_1.channel_identifier, contract_manager=contract_manager, from_block=start_block, to_block=web3.eth.blockNumber, ) assert len(channel_events) == 2 block_before_close = web3.eth.blockNumber empty_balance_proof = BalanceProof( channel_identifier=channel_proxy_1.channel_identifier, token_network_address=token_network_address, balance_hash=EMPTY_BALANCE_HASH, nonce=0, chain_id=chain_id, transferred_amount=TokenAmount(0), ) closing_data = ( empty_balance_proof.serialize_bin(msg_type=MessageTypeId.BALANCE_PROOF) + EMPTY_SIGNATURE ) channel_proxy_1.close( nonce=Nonce(0), balance_hash=EMPTY_BALANCE_HASH, additional_hash=EMPTY_MESSAGE_HASH, non_closing_signature=EMPTY_SIGNATURE, closing_signature=LocalSigner(private_keys[1]).sign(data=closing_data), block_identifier=BLOCK_ID_LATEST, ) assert channel_proxy_1.closed(BLOCK_ID_LATEST) is True # ChannelOpened, ChannelNewDeposit, ChannelClosed channel_events = get_all_netting_channel_events( proxy_manager=proxy_manager, token_network_address=token_network_address, netting_channel_identifier=channel_proxy_1.channel_identifier, contract_manager=contract_manager, from_block=start_block, to_block=web3.eth.blockNumber, ) assert len(channel_events) == 3 # check the settlement timeouts again assert channel_proxy_1.settle_timeout() == TEST_SETTLE_TIMEOUT_MIN # update transfer -- we need to wait on +1 since we use the latest block on parity for # estimate gas and at the time the latest block is the settle timeout block. # More info: https://github.com/raiden-network/raiden/pull/3699#discussion_r270477227 rpc_client.wait_until_block( target_block_number=BlockNumber(rpc_client.block_number() + TEST_SETTLE_TIMEOUT_MIN + 1) ) transaction_hash = channel_proxy_1.settle( transferred_amount=TokenAmount(0), locked_amount=LockedAmount(0), locksroot=LOCKSROOT_OF_NO_LOCKS, partner_transferred_amount=TokenAmount(0), partner_locked_amount=LockedAmount(0), partner_locksroot=LOCKSROOT_OF_NO_LOCKS, block_identifier=BLOCK_ID_LATEST, ) assert is_tx_hash_bytes(transaction_hash) assert channel_proxy_1.settled(BLOCK_ID_LATEST) is True # ChannelOpened, ChannelNewDeposit, ChannelClosed, ChannelSettled channel_events = get_all_netting_channel_events( proxy_manager=proxy_manager, token_network_address=token_network_address, netting_channel_identifier=channel_proxy_1.channel_identifier, contract_manager=contract_manager, from_block=start_block, to_block=web3.eth.blockNumber, ) assert len(channel_events) == 4 channel_details = token_network_proxy.new_netting_channel( partner=partner, settle_timeout=TEST_SETTLE_TIMEOUT_MIN, given_block_identifier=BLOCK_ID_LATEST, ) new_channel_identifier = channel_details.channel_identifier assert new_channel_identifier is not None channel_state = NettingChannelState( canonical_identifier=CanonicalIdentifier( chain_identifier=chain_id, token_network_address=token_network_address, channel_identifier=new_channel_identifier, ), token_address=token_network_proxy.token_address(), token_network_registry_address=token_network_registry_address, reveal_timeout=reveal_timeout, settle_timeout=BlockTimeout(TEST_SETTLE_TIMEOUT_MIN), fee_schedule=FeeScheduleState(), our_state=NettingChannelEndState( address=token_network_proxy.client.address, contract_balance=Balance(0) ), partner_state=NettingChannelEndState(address=partner, contract_balance=Balance(0)), open_transaction=SuccessfulTransactionState(finished_block_number=BlockNumber(0)), ) channel_proxy_2 = proxy_manager.payment_channel( channel_state=channel_state, block_identifier=BLOCK_ID_LATEST ) assert channel_proxy_2.channel_identifier == new_channel_identifier assert channel_proxy_2.opened(BLOCK_ID_LATEST) is True msg = "The channel was already closed, the second call must fail" with pytest.raises(RaidenRecoverableError): channel_proxy_1.close( nonce=Nonce(0), balance_hash=EMPTY_BALANCE_HASH, additional_hash=EMPTY_MESSAGE_HASH, non_closing_signature=EMPTY_SIGNATURE, closing_signature=LocalSigner(private_keys[1]).sign(data=closing_data), block_identifier=block_before_close, ) pytest.fail(msg) msg = "The channel is not open at latest, this must raise" with pytest.raises(RaidenUnrecoverableError): channel_proxy_1.close( nonce=Nonce(0), balance_hash=EMPTY_BALANCE_HASH, additional_hash=EMPTY_MESSAGE_HASH, non_closing_signature=EMPTY_SIGNATURE, closing_signature=LocalSigner(private_keys[1]).sign(data=closing_data), block_identifier=BLOCK_ID_LATEST, ) pytest.fail(msg) msg = ( "The channel was not opened at the provided block (latest). " "This call should never have been attempted." ) with pytest.raises(BrokenPreconditionError): channel_proxy_1.approve_and_set_total_deposit( total_deposit=TokenAmount(20), block_identifier=BLOCK_ID_LATEST ) pytest.fail(msg)
def test_payment_channel_proxy_basics(token_network_proxy, token_proxy, chain_id, private_keys, web3, contract_manager): token_network_address = token_network_proxy.address partner = privatekey_to_address(private_keys[0]) client = JSONRPCClient(web3, private_keys[1]) proxy_manager = ProxyManager( rpc_client=client, contract_manager=contract_manager, metadata=ProxyManagerMetadata( token_network_registry_deployed_at=GENESIS_BLOCK_NUMBER, filters_start_at=GENESIS_BLOCK_NUMBER, ), ) token_network_proxy = proxy_manager.token_network( address=token_network_address) start_block = web3.eth.blockNumber channel_identifier = token_network_proxy.new_netting_channel( partner=partner, settle_timeout=TEST_SETTLE_TIMEOUT_MIN, given_block_identifier="latest") assert channel_identifier is not None channel_proxy_1 = proxy_manager.payment_channel( canonical_identifier=CanonicalIdentifier( chain_identifier=chain_id, token_network_address=token_network_address, channel_identifier=channel_identifier, )) channel_filter = channel_proxy_1.all_events_filter(from_block=start_block, to_block="latest") assert channel_proxy_1.channel_identifier == channel_identifier assert channel_proxy_1.opened("latest") is True # Test deposit initial_token_balance = 100 token_proxy.transfer(client.address, initial_token_balance) assert token_proxy.balance_of(client.address) == initial_token_balance assert token_proxy.balance_of(partner) == 0 channel_proxy_1.set_total_deposit(total_deposit=10, block_identifier="latest") assert len(channel_filter.get_all_entries() ) == 2 # ChannelOpened, ChannelNewDeposit block_before_close = web3.eth.blockNumber empty_balance_proof = BalanceProof( channel_identifier=channel_proxy_1.channel_identifier, token_network_address=token_network_address, balance_hash=encode_hex(EMPTY_BALANCE_HASH), nonce=0, chain_id=chain_id, transferred_amount=0, ) closing_data = (empty_balance_proof.serialize_bin( msg_type=MessageTypeId.BALANCE_PROOF) + EMPTY_SIGNATURE) channel_proxy_1.close( nonce=0, balance_hash=EMPTY_HASH, additional_hash=EMPTY_HASH, non_closing_signature=EMPTY_SIGNATURE, closing_signature=LocalSigner(private_keys[1]).sign(data=closing_data), block_identifier="latest", ) assert channel_proxy_1.closed("latest") is True # ChannelOpened, ChannelNewDeposit, ChannelClosed assert len(channel_filter.get_all_entries()) == 3 # check the settlement timeouts again assert channel_proxy_1.settle_timeout() == TEST_SETTLE_TIMEOUT_MIN # update transfer -- we need to wait on +1 since we use the latest block on parity for # estimate gas and at the time the latest block is the settle timeout block. # More info: https://github.com/raiden-network/raiden/pull/3699#discussion_r270477227 proxy_manager.wait_until_block(target_block_number=client.block_number() + TEST_SETTLE_TIMEOUT_MIN + 1) channel_proxy_1.settle( transferred_amount=0, locked_amount=0, locksroot=LOCKSROOT_OF_NO_LOCKS, partner_transferred_amount=0, partner_locked_amount=0, partner_locksroot=LOCKSROOT_OF_NO_LOCKS, block_identifier="latest", ) assert channel_proxy_1.settled("latest") is True # ChannelOpened, ChannelNewDeposit, ChannelClosed, ChannelSettled assert len(channel_filter.get_all_entries()) == 4 new_channel_identifier = token_network_proxy.new_netting_channel( partner=partner, settle_timeout=TEST_SETTLE_TIMEOUT_MIN, given_block_identifier="latest") assert new_channel_identifier is not None channel_proxy_2 = proxy_manager.payment_channel( canonical_identifier=CanonicalIdentifier( chain_identifier=chain_id, token_network_address=token_network_address, channel_identifier=new_channel_identifier, )) assert channel_proxy_2.channel_identifier == new_channel_identifier assert channel_proxy_2.opened("latest") is True msg = "The channel was already closed, the second call must fail" with pytest.raises(RaidenRecoverableError): channel_proxy_1.close( nonce=0, balance_hash=EMPTY_HASH, additional_hash=EMPTY_HASH, non_closing_signature=EMPTY_SIGNATURE, closing_signature=LocalSigner( private_keys[1]).sign(data=closing_data), block_identifier=block_before_close, ) pytest.fail(msg) msg = "The channel is not open at latest, this must raise" with pytest.raises(RaidenUnrecoverableError): channel_proxy_1.close( nonce=0, balance_hash=EMPTY_HASH, additional_hash=EMPTY_HASH, non_closing_signature=EMPTY_SIGNATURE, closing_signature=LocalSigner( private_keys[1]).sign(data=closing_data), block_identifier="latest", ) pytest.fail(msg) msg = ("The channel was not opened at the provided block (latest). " "This call should never have been attempted.") with pytest.raises(BrokenPreconditionError): channel_proxy_1.set_total_deposit(total_deposit=20, block_identifier="latest") pytest.fail(msg)
def test_token_network_actions_at_pruned_blocks(token_network_proxy, private_keys, token_proxy, web3, chain_id, contract_manager): token_network_address = to_canonical_address( token_network_proxy.proxy.contract.address) c1_client = JSONRPCClient(web3, private_keys[1]) c1_proxy_manager = ProxyManager( rpc_client=c1_client, contract_manager=contract_manager, metadata=ProxyManagerMetadata( token_network_registry_deployed_at=GENESIS_BLOCK_NUMBER, filters_start_at=GENESIS_BLOCK_NUMBER, ), ) c1_token_network_proxy = c1_proxy_manager.token_network( token_network_address) c2_client = JSONRPCClient(web3, private_keys[2]) c2_proxy_manager = ProxyManager( rpc_client=c2_client, contract_manager=contract_manager, metadata=ProxyManagerMetadata( token_network_registry_deployed_at=GENESIS_BLOCK_NUMBER, filters_start_at=GENESIS_BLOCK_NUMBER, ), ) c2_token_network_proxy = c2_proxy_manager.token_network( token_network_address) initial_token_balance = 100 token_proxy.transfer(c1_client.address, initial_token_balance) token_proxy.transfer(c2_client.address, initial_token_balance) initial_balance_c1 = token_proxy.balance_of(c1_client.address) assert initial_balance_c1 == initial_token_balance initial_balance_c2 = token_proxy.balance_of(c2_client.address) assert initial_balance_c2 == initial_token_balance # create a channel settle_timeout = STATE_PRUNING_AFTER_BLOCKS + 10 channel_identifier = c1_token_network_proxy.new_netting_channel( partner=c2_client.address, settle_timeout=settle_timeout, given_block_identifier="latest") # Now wait until this block becomes pruned pruned_number = c1_proxy_manager.client.block_number() c1_proxy_manager.wait_until_block(target_block_number=pruned_number + STATE_PRUNING_AFTER_BLOCKS) # deposit with given block being pruned c1_token_network_proxy.set_total_deposit( given_block_identifier=pruned_number, channel_identifier=channel_identifier, total_deposit=2, partner=c2_client.address, ) # balance proof signed by c1 transferred_amount_c1 = 1 balance_proof_c1 = BalanceProof( channel_identifier=channel_identifier, token_network_address=to_checksum_address(token_network_address), nonce=1, chain_id=chain_id, transferred_amount=transferred_amount_c1, ) balance_proof_c1.signature = encode_hex( LocalSigner( private_keys[1]).sign(data=balance_proof_c1.serialize_bin())) non_closing_data = balance_proof_c1.serialize_bin( msg_type=MessageTypeId.BALANCE_PROOF_UPDATE) + decode_hex( balance_proof_c1.signature) non_closing_signature = LocalSigner( c2_client.privkey).sign(data=non_closing_data) # close channel with given block being pruned empty_balance_proof = BalanceProof( channel_identifier=channel_identifier, token_network_address=c1_token_network_proxy.address, balance_hash=encode_hex(EMPTY_BALANCE_HASH), nonce=0, chain_id=chain_id, transferred_amount=0, ) closing_data = (empty_balance_proof.serialize_bin( msg_type=MessageTypeId.BALANCE_PROOF) + EMPTY_SIGNATURE) c1_token_network_proxy.close( channel_identifier=channel_identifier, partner=c2_client.address, balance_hash=EMPTY_HASH, nonce=0, additional_hash=EMPTY_HASH, non_closing_signature=EMPTY_SIGNATURE, closing_signature=LocalSigner( c1_client.privkey).sign(data=closing_data), given_block_identifier=pruned_number, ) close_pruned_number = c1_proxy_manager.client.block_number() assert (c1_token_network_proxy.channel_is_closed( participant1=c1_client.address, participant2=c2_client.address, block_identifier="latest", channel_identifier=channel_identifier, ) is True) assert (c1_token_network_proxy.get_channel_identifier_or_none( participant1=c1_client.address, participant2=c2_client.address, block_identifier="latest", ) is not None) c1_proxy_manager.wait_until_block(target_block_number=close_pruned_number + STATE_PRUNING_AFTER_BLOCKS) # update transfer with given block being pruned c2_token_network_proxy.update_transfer( channel_identifier=channel_identifier, partner=c1_client.address, balance_hash=decode_hex(balance_proof_c1.balance_hash), nonce=balance_proof_c1.nonce, additional_hash=decode_hex(balance_proof_c1.additional_hash), closing_signature=decode_hex(balance_proof_c1.signature), non_closing_signature=non_closing_signature, given_block_identifier=close_pruned_number, ) # update transfer c1_proxy_manager.wait_until_block(target_block_number=close_pruned_number + settle_timeout) # Test that settling will fail because at closed_pruned_number # the settlement period isn't over. with pytest.raises(BrokenPreconditionError): c1_token_network_proxy.settle( channel_identifier=channel_identifier, transferred_amount=transferred_amount_c1, locked_amount=0, locksroot=LOCKSROOT_OF_NO_LOCKS, partner=c2_client.address, partner_transferred_amount=0, partner_locked_amount=0, partner_locksroot=LOCKSROOT_OF_NO_LOCKS, given_block_identifier=close_pruned_number, ) settle_block_number = close_pruned_number + settle_timeout # Wait until the settle block is pruned c1_proxy_manager.wait_until_block(target_block_number=settle_block_number + STATE_PRUNING_AFTER_BLOCKS + 1) c1_token_network_proxy.settle( channel_identifier=channel_identifier, transferred_amount=transferred_amount_c1, locked_amount=0, locksroot=LOCKSROOT_OF_NO_LOCKS, partner=c2_client.address, partner_transferred_amount=0, partner_locked_amount=0, partner_locksroot=LOCKSROOT_OF_NO_LOCKS, # Settle is block number is pruned, we should not fail at pre-conditions. given_block_identifier=settle_block_number, ) assert token_proxy.balance_of( c2_client.address) == (initial_balance_c2 + transferred_amount_c1 - 0) assert token_proxy.balance_of( c1_client.address) == (initial_balance_c1 + 0 - transferred_amount_c1)
def test_register_secret_happy_path( secret_registry_proxy: SecretRegistry, contract_manager: ContractManager ) -> None: """Test happy path of SecretRegistry with a single secret. Test that `register_secret` changes the smart contract state by registering the secret, this can be verified by the block height and the existence of the SecretRegistered event. """ secret = make_secret() secrethash = sha256_secrethash(secret) secret_unregistered = make_secret() secrethash_unregistered = sha256_secrethash(secret_unregistered) assert not secret_registry_proxy.is_secret_registered( secrethash=secrethash, block_identifier=BLOCK_ID_LATEST ), "Test setup is invalid, secret must be unknown" assert not secret_registry_proxy.is_secret_registered( secrethash=secrethash_unregistered, block_identifier=BLOCK_ID_LATEST ), "Test setup is invalid, secret must be unknown" secret_registry_proxy.client.wait_until_block(BlockNumber(STATE_PRUNING_AFTER_BLOCKS + 1)) with pytest.raises(NoStateForBlockIdentifier): secret_registry_proxy.is_secret_registered( secrethash=secrethash_unregistered, block_identifier=BlockNumber(0) ) secret_registry_proxy.register_secret(secret=secret) proxy_manager = ProxyManager( rpc_client=secret_registry_proxy.client, contract_manager=contract_manager, metadata=ProxyManagerMetadata( token_network_registry_deployed_at=GENESIS_BLOCK_NUMBER, filters_start_at=GENESIS_BLOCK_NUMBER, ), ) logs = get_contract_events( proxy_manager=proxy_manager, abi=proxy_manager.contract_manager.get_contract_abi(CONTRACT_SECRET_REGISTRY), contract_address=Address(secret_registry_proxy.address), ) secret_registered = must_have_event( logs, {"event": "SecretRevealed", "args": {"secrethash": secrethash}} ) msg = "SecretRegistry.register_secret returned but the SecretRevealed event was not emitted." assert secret_registered, msg registered_block = secret_registry_proxy.get_secret_registration_block_by_secrethash( secrethash=secrethash, block_identifier=BLOCK_ID_LATEST ) msg = ( "Block height returned by the SecretRegistry.get_secret_registration_block_by_secrethash " "does not match the block from the SecretRevealed event." ) assert secret_registered["block_number"] == registered_block, msg block = secret_registry_proxy.get_secret_registration_block_by_secrethash( secrethash=secrethash_unregistered, block_identifier=BLOCK_ID_LATEST ) assert block is None, "The secret that was not registered must not change block height!"
def test_token_network_proxy_update_transfer(token_network_proxy, private_keys, token_proxy, chain_id, web3, contract_manager): """Tests channel lifecycle, with `update_transfer` before settling""" token_network_address = to_canonical_address( token_network_proxy.proxy.contract.address) c1_client = JSONRPCClient(web3, private_keys[1]) c1_proxy_manager = ProxyManager( rpc_client=c1_client, contract_manager=contract_manager, metadata=ProxyManagerMetadata( token_network_registry_deployed_at=GENESIS_BLOCK_NUMBER, filters_start_at=GENESIS_BLOCK_NUMBER, ), ) c1_signer = LocalSigner(private_keys[1]) c2_client = JSONRPCClient(web3, private_keys[2]) c2_proxy_manager = ProxyManager( rpc_client=c2_client, contract_manager=contract_manager, metadata=ProxyManagerMetadata( token_network_registry_deployed_at=GENESIS_BLOCK_NUMBER, filters_start_at=GENESIS_BLOCK_NUMBER, ), ) c1_token_network_proxy = c1_proxy_manager.token_network( token_network_address) c2_token_network_proxy = c2_proxy_manager.token_network( token_network_address) # create a channel channel_identifier = c1_token_network_proxy.new_netting_channel( partner=c2_client.address, settle_timeout=10, given_block_identifier="latest") # deposit to the channel initial_balance = 100 token_proxy.transfer(c1_client.address, initial_balance) token_proxy.transfer(c2_client.address, initial_balance) initial_balance_c1 = token_proxy.balance_of(c1_client.address) assert initial_balance_c1 == initial_balance initial_balance_c2 = token_proxy.balance_of(c2_client.address) assert initial_balance_c2 == initial_balance c1_token_network_proxy.set_total_deposit( given_block_identifier="latest", channel_identifier=channel_identifier, total_deposit=10, partner=c2_client.address, ) c2_token_network_proxy.set_total_deposit( given_block_identifier="latest", channel_identifier=channel_identifier, total_deposit=10, partner=c1_client.address, ) # balance proof signed by c1 transferred_amount_c1 = 1 transferred_amount_c2 = 3 balance_proof_c1 = BalanceProof( channel_identifier=channel_identifier, token_network_address=to_checksum_address(token_network_address), nonce=1, chain_id=chain_id, transferred_amount=transferred_amount_c1, ) balance_proof_c1.signature = encode_hex( LocalSigner( private_keys[1]).sign(data=balance_proof_c1.serialize_bin())) # balance proof signed by c2 balance_proof_c2 = BalanceProof( channel_identifier=channel_identifier, token_network_address=to_checksum_address(token_network_address), nonce=2, chain_id=chain_id, transferred_amount=transferred_amount_c2, ) balance_proof_c2.signature = encode_hex( LocalSigner( private_keys[2]).sign(data=balance_proof_c2.serialize_bin())) non_closing_data = balance_proof_c1.serialize_bin( msg_type=MessageTypeId.BALANCE_PROOF_UPDATE) + decode_hex( balance_proof_c1.signature) non_closing_signature = LocalSigner( c2_client.privkey).sign(data=non_closing_data) with pytest.raises(RaidenUnrecoverableError) as exc: c2_token_network_proxy.update_transfer( channel_identifier=channel_identifier, partner=c1_client.address, balance_hash=decode_hex(balance_proof_c1.balance_hash), nonce=balance_proof_c1.nonce, additional_hash=decode_hex(balance_proof_c1.additional_hash), closing_signature=decode_hex(balance_proof_c1.signature), non_closing_signature=non_closing_signature, given_block_identifier="latest", ) assert "not in a closed state" in str(exc) # close by c1 closing_data = balance_proof_c2.serialize_bin( msg_type=MessageTypeId.BALANCE_PROOF) + decode_hex( balance_proof_c2.signature) c1_token_network_proxy.close( channel_identifier=channel_identifier, partner=c2_client.address, balance_hash=decode_hex(balance_proof_c2.balance_hash), nonce=balance_proof_c2.nonce, additional_hash=decode_hex(balance_proof_c2.additional_hash), non_closing_signature=decode_hex(balance_proof_c2.signature), closing_signature=c1_signer.sign(data=closing_data), given_block_identifier="latest", ) # update transfer with completely invalid closing signature with pytest.raises(RaidenUnrecoverableError) as excinfo: c2_token_network_proxy.update_transfer( channel_identifier=channel_identifier, partner=c1_client.address, balance_hash=decode_hex(balance_proof_c1.balance_hash), nonce=balance_proof_c1.nonce, additional_hash=decode_hex(balance_proof_c1.additional_hash), closing_signature=b"", non_closing_signature=b"", given_block_identifier="latest", ) assert str(excinfo.value) == "Couldn't verify the balance proof signature" # using invalid non-closing signature # Usual mistake when calling update Transfer - balance proof signature is missing in the data non_closing_data = balance_proof_c1.serialize_bin( msg_type=MessageTypeId.BALANCE_PROOF_UPDATE) non_closing_signature = LocalSigner( c2_client.privkey).sign(data=non_closing_data) with pytest.raises(RaidenUnrecoverableError): c2_token_network_proxy.update_transfer( channel_identifier=channel_identifier, partner=c1_client.address, balance_hash=decode_hex(balance_proof_c1.balance_hash), nonce=balance_proof_c1.nonce, additional_hash=decode_hex(balance_proof_c1.additional_hash), closing_signature=decode_hex(balance_proof_c1.signature), non_closing_signature=non_closing_signature, given_block_identifier="latest", ) non_closing_data = balance_proof_c1.serialize_bin( msg_type=MessageTypeId.BALANCE_PROOF_UPDATE) + decode_hex( balance_proof_c1.signature) non_closing_signature = LocalSigner( c2_client.privkey).sign(data=non_closing_data) c2_token_network_proxy.update_transfer( channel_identifier=channel_identifier, partner=c1_client.address, balance_hash=decode_hex(balance_proof_c1.balance_hash), nonce=balance_proof_c1.nonce, additional_hash=decode_hex(balance_proof_c1.additional_hash), closing_signature=decode_hex(balance_proof_c1.signature), non_closing_signature=non_closing_signature, given_block_identifier="latest", ) with pytest.raises(BrokenPreconditionError) as exc: c1_token_network_proxy.settle( channel_identifier=channel_identifier, transferred_amount=transferred_amount_c1, locked_amount=0, locksroot=LOCKSROOT_OF_NO_LOCKS, partner=c2_client.address, partner_transferred_amount=transferred_amount_c2, partner_locked_amount=0, partner_locksroot=LOCKSROOT_OF_NO_LOCKS, given_block_identifier="latest", ) assert "cannot be settled before settlement window is over" in str(exc) c1_proxy_manager.wait_until_block( target_block_number=c1_proxy_manager.client.block_number() + 10) # settling with an invalid amount with pytest.raises(BrokenPreconditionError): c1_token_network_proxy.settle( channel_identifier=channel_identifier, transferred_amount=2, locked_amount=0, locksroot=LOCKSROOT_OF_NO_LOCKS, partner=c2_client.address, partner_transferred_amount=2, partner_locked_amount=0, partner_locksroot=LOCKSROOT_OF_NO_LOCKS, given_block_identifier="latest", ) # proper settle c1_token_network_proxy.settle( channel_identifier=channel_identifier, transferred_amount=transferred_amount_c1, locked_amount=0, locksroot=LOCKSROOT_OF_NO_LOCKS, partner=c2_client.address, partner_transferred_amount=transferred_amount_c2, partner_locked_amount=0, partner_locksroot=LOCKSROOT_OF_NO_LOCKS, given_block_identifier="latest", ) assert token_proxy.balance_of( c2_client.address) == (initial_balance_c2 + transferred_amount_c1 - transferred_amount_c2) assert token_proxy.balance_of( c1_client.address) == (initial_balance_c1 + transferred_amount_c2 - transferred_amount_c1) # Already settled with pytest.raises(BrokenPreconditionError) as exc: c2_token_network_proxy.set_total_deposit( given_block_identifier="latest", channel_identifier=channel_identifier, total_deposit=20, partner=c1_client.address, ) assert "getChannelIdentifier returned 0" in str(exc)
def test_user_deposit_proxy_withdraw( private_keys: List[bytes], web3: Web3, contract_manager: ContractManager, user_deposit_address: Address, ): c0_client = JSONRPCClient(web3, PrivateKey(private_keys[0])) c0_proxy_manager = ProxyManager( rpc_client=c0_client, contract_manager=contract_manager, metadata=ProxyManagerMetadata( token_network_registry_deployed_at=GENESIS_BLOCK_NUMBER, filters_start_at=GENESIS_BLOCK_NUMBER, ), ) c0_user_deposit_proxy = c0_proxy_manager.user_deposit( UserDepositAddress(user_deposit_address), BLOCK_ID_LATEST) withdraw_plan = c0_user_deposit_proxy.get_withdraw_plan( c0_client.address, BLOCK_ID_LATEST) # There should be no withdraw plan assert withdraw_plan.withdraw_block == 0 assert withdraw_plan.withdraw_amount == 0 current_deposit = c0_user_deposit_proxy.get_total_deposit( c0_client.address, BLOCK_ID_LATEST) # None of these are valid plan_withdraw amounts for value in [-1, 0, current_deposit + 1]: with pytest.raises(BrokenPreconditionError): c0_user_deposit_proxy.plan_withdraw(TokenAmount(value), BLOCK_ID_LATEST) # With no plan any withdraw must fail in the precondition check with pytest.raises(BrokenPreconditionError): c0_user_deposit_proxy.withdraw(TokenAmount(1), BLOCK_ID_LATEST) withdraw_amount = TokenAmount(current_deposit // 2) withdraw_block = c0_user_deposit_proxy.plan_withdraw( withdraw_amount, BLOCK_ID_LATEST) # The effective balance must take the planned withdraw into account effective_balance_after_withdraw_plan = c0_user_deposit_proxy.effective_balance( c0_client.address, BLOCK_ID_LATEST) assert effective_balance_after_withdraw_plan == current_deposit - withdraw_amount # Wait until target block - 1. # We set the retry timeout to 0.1 to make sure there is enough time for the failing case # below. c0_client.wait_until_block(BlockNumber(withdraw_block - 1), retry_timeout=0.1) # Withdraw should still fail with pytest.raises(BrokenPreconditionError): c0_user_deposit_proxy.withdraw(TokenAmount(withdraw_amount), BLOCK_ID_LATEST) # Wait the final block c0_user_deposit_proxy.client.wait_until_block(withdraw_block) # Now withdraw must succeed c0_user_deposit_proxy.withdraw(TokenAmount(withdraw_amount), BLOCK_ID_LATEST) # The total deposit must now match the reduced value new_current_deposit = c0_user_deposit_proxy.get_total_deposit( c0_client.address, BLOCK_ID_LATEST) assert new_current_deposit == current_deposit - withdraw_amount
def test_user_deposit_proxy_withdraw( private_keys: List[bytes], web3: Web3, contract_manager: ContractManager, user_deposit_address: Address, ): c0_client = JSONRPCClient(web3, PrivateKey(private_keys[0])) c0_proxy_manager = ProxyManager( rpc_client=c0_client, contract_manager=contract_manager, metadata=ProxyManagerMetadata( token_network_registry_deployed_at=GENESIS_BLOCK_NUMBER, filters_start_at=GENESIS_BLOCK_NUMBER, ), ) c0_user_deposit_proxy = c0_proxy_manager.user_deposit( UserDepositAddress(user_deposit_address), BLOCK_ID_LATEST) withdraw_plan = c0_user_deposit_proxy.get_withdraw_plan( c0_client.address, BLOCK_ID_LATEST) # There should be no withdraw plan assert withdraw_plan.withdraw_block == 0 assert withdraw_plan.withdraw_amount == 0 initial_deposit = c0_user_deposit_proxy.get_total_deposit( c0_client.address, BLOCK_ID_LATEST) # None of these are valid plan_withdraw amounts for value in [-1, 0, initial_deposit + 1]: with pytest.raises(BrokenPreconditionError): c0_user_deposit_proxy.plan_withdraw(TokenAmount(value), BLOCK_ID_LATEST) # With no plan any withdraw must fail in the precondition check with pytest.raises(BrokenPreconditionError): c0_user_deposit_proxy.withdraw(TokenAmount(1), BLOCK_ID_LATEST) withdraw_amount = TokenAmount(initial_deposit // 2) transaction_hash, withdraw_block = c0_user_deposit_proxy.plan_withdraw( withdraw_amount, BLOCK_ID_LATEST) assert is_tx_hash_bytes(transaction_hash) # The effective balance must take the planned withdraw into account effective_balance_after_withdraw_plan = c0_user_deposit_proxy.effective_balance( c0_client.address, BLOCK_ID_LATEST) assert effective_balance_after_withdraw_plan == initial_deposit - withdraw_amount # Wait until target block - 1. # We set the retry timeout to 0.1 to make sure there is enough time for the failing case # below. c0_client.wait_until_block(BlockNumber(withdraw_block - 1), retry_timeout=0.1) # Withdraw should still fail with pytest.raises(BrokenPreconditionError): c0_user_deposit_proxy.withdraw(TokenAmount(withdraw_amount), BLOCK_ID_LATEST) # Wait the final block c0_user_deposit_proxy.client.wait_until_block(withdraw_block) # Now withdraw must succeed transaction_hash = c0_user_deposit_proxy.withdraw( TokenAmount(withdraw_amount), BLOCK_ID_LATEST) assert is_tx_hash_bytes(transaction_hash) # The current balance must now match the reduced value new_current_balance = c0_user_deposit_proxy.get_balance( c0_client.address, BLOCK_ID_LATEST) assert new_current_balance == initial_deposit - withdraw_amount # Deposit again after the funds were withdrawn amount_to_deposit = 1 tasks = set() # Force a race condition between deposits, letting successive, concurrent calls # wait for the first inflight transaction for _ in range(3): task = gevent.spawn( c0_user_deposit_proxy.approve_and_deposit, beneficiary=c0_client.address, # the total deposit needs to increase monotonically in the contract total_deposit=initial_deposit + amount_to_deposit, given_block_identifier=BLOCK_ID_LATEST, ) tasks.add(task) results = gevent.joinall(tasks, raise_error=True) # All tx have the same deposit, # so one of them should successfully transact, # while all others should wait for the inflight transaction # All calls should then be associated to the same on-chain transaction tx_hashes = set(result.get() for result in results) assert len(tx_hashes) == 1 assert is_tx_hash_bytes(tx_hashes.pop())
def setup_raiden( matrix_server: str, print_step: StepPrinter, contracts_version, eth_rpc_endpoint: str, web3: Web3, base_datadir: Path, keystore: Path, ) -> RaidenTestSetup: print_step("Deploying Raiden contracts") client = JSONRPCClient(web3, get_private_key(keystore)) contract_manager = ContractManager( contracts_precompiled_path(contracts_version)) proxy_manager = ProxyManager( rpc_client=client, contract_manager=contract_manager, metadata=ProxyManagerMetadata( token_network_registry_deployed_at=GENESIS_BLOCK_NUMBER, filters_start_at=GENESIS_BLOCK_NUMBER, ), ) token = deploy_token( deploy_client=client, contract_manager=contract_manager, initial_amount=TokenAmount(1000), decimals=0, token_name="TKN", token_symbol="TKN", token_contract_name=CONTRACT_CUSTOM_TOKEN, ) contract_addresses = deploy_smoketest_contracts( client=client, chain_id=CHAINNAME_TO_ID["smoketest"], contract_manager=contract_manager, token_address=token.address, ) confirmed_block_identifier = client.get_confirmed_blockhash() registry = proxy_manager.token_network_registry( TokenNetworkRegistryAddress( contract_addresses[CONTRACT_TOKEN_NETWORK_REGISTRY]), block_identifier=confirmed_block_identifier, ) registry.add_token( token_address=TokenAddress(to_canonical_address(token.address)), channel_participant_deposit_limit=TokenAmount(UINT256_MAX), token_network_deposit_limit=TokenAmount(UINT256_MAX), given_block_identifier=confirmed_block_identifier, ) print_step("Setting up Raiden") user_deposit_contract_address = to_checksum_address( contract_addresses[CONTRACT_USER_DEPOSIT]) args = { "address": to_checksum_address(TEST_ACCOUNT_ADDRESS), "datadir": keystore, "eth_rpc_endpoint": eth_rpc_endpoint, "gas_price": "fast", "keystore_path": keystore, "matrix_server": matrix_server, "chain_id": str(CHAINNAME_TO_ID["smoketest"]), "password_file": click.File()(os.path.join(base_datadir, "pw")), "user_deposit_contract_address": user_deposit_contract_address, "sync_check": False, "environment_type": Environment.DEVELOPMENT, } # Wait until the secret registry is confirmed, otherwise the RaidenService # inialization will fail, needed for the check # `check_ethereum_confirmed_block_is_not_pruned`. current_block = client.block_number() target_block_number = current_block + DEFAULT_NUMBER_OF_BLOCK_CONFIRMATIONS while current_block < target_block_number: current_block = client.block_number() sleep(0.5) return RaidenTestSetup(args=args, token=token, contract_addresses=contract_addresses)
def deploy_smoketest_contracts( client: JSONRPCClient, chain_id: ChainID, contract_manager: ContractManager, token_address: AddressHex, ) -> Dict[str, Address]: if client.eth_node is EthClient.GETH: client.web3.geth.personal.unlockAccount(client.web3.eth.accounts[0], DEFAULT_PASSPHRASE) elif client.eth_node is EthClient.PARITY: client.web3.parity.personal.unlockAccount(client.web3.eth.accounts[0], DEFAULT_PASSPHRASE) contract_proxy, _ = client.deploy_single_contract( contract_name=CONTRACT_SECRET_REGISTRY, contract=contract_manager.get_contract(CONTRACT_SECRET_REGISTRY), constructor_parameters=None, ) secret_registry_address = Address( to_canonical_address(contract_proxy.address)) secret_registry_constructor_arguments = ( to_checksum_address(secret_registry_address), chain_id, TEST_SETTLE_TIMEOUT_MIN, TEST_SETTLE_TIMEOUT_MAX, UINT256_MAX, ) contract_proxy, _ = client.deploy_single_contract( contract_name=CONTRACT_TOKEN_NETWORK_REGISTRY, contract=contract_manager.get_contract( CONTRACT_TOKEN_NETWORK_REGISTRY), constructor_parameters=secret_registry_constructor_arguments, ) token_network_registry_address = Address( to_canonical_address(contract_proxy.address)) service_registry_constructor_arguments = ( token_address, EMPTY_ADDRESS, int(500e18), 6, 5, 180 * SECONDS_PER_DAY, 1000, 200 * SECONDS_PER_DAY, ) service_registry_contract, _ = client.deploy_single_contract( contract_name=CONTRACT_SERVICE_REGISTRY, contract=contract_manager.get_contract(CONTRACT_SERVICE_REGISTRY), constructor_parameters=service_registry_constructor_arguments, ) service_registry_address = Address( to_canonical_address(service_registry_contract.address)) user_deposit_contract, _ = client.deploy_single_contract( contract_name=CONTRACT_USER_DEPOSIT, contract=contract_manager.get_contract(CONTRACT_USER_DEPOSIT), constructor_parameters=(token_address, UINT256_MAX), ) user_deposit_address = Address( to_canonical_address(user_deposit_contract.address)) monitoring_service_contract, _ = client.deploy_single_contract( contract_name=CONTRACT_MONITORING_SERVICE, contract=contract_manager.get_contract(CONTRACT_MONITORING_SERVICE), constructor_parameters=( token_address, service_registry_address, user_deposit_address, token_network_registry_address, ), ) monitoring_service_address = Address( to_canonical_address(monitoring_service_contract.address)) one_to_n_contract, _ = client.deploy_single_contract( contract_name=CONTRACT_ONE_TO_N, contract=contract_manager.get_contract(CONTRACT_ONE_TO_N), constructor_parameters=(user_deposit_address, chain_id, service_registry_address), ) one_to_n_address = Address(to_canonical_address(one_to_n_contract.address)) proxy_manager = ProxyManager( rpc_client=client, contract_manager=contract_manager, metadata=ProxyManagerMetadata( token_network_registry_deployed_at=GENESIS_BLOCK_NUMBER, filters_start_at=GENESIS_BLOCK_NUMBER, ), ) user_deposit_proxy = UserDeposit( jsonrpc_client=client, user_deposit_address=UserDepositAddress( to_canonical_address(user_deposit_contract.address)), contract_manager=contract_manager, proxy_manager=proxy_manager, block_identifier=BLOCK_ID_LATEST, ) transaction_hash = user_deposit_proxy.init( monitoring_service_address=MonitoringServiceAddress( monitoring_service_address), one_to_n_address=OneToNAddress(one_to_n_address), given_block_identifier=BLOCK_ID_LATEST, ) assert is_tx_hash_bytes(transaction_hash) addresses = { CONTRACT_SECRET_REGISTRY: secret_registry_address, CONTRACT_TOKEN_NETWORK_REGISTRY: token_network_registry_address, CONTRACT_SERVICE_REGISTRY: service_registry_address, CONTRACT_USER_DEPOSIT: user_deposit_address, CONTRACT_MONITORING_SERVICE: monitoring_service_address, CONTRACT_ONE_TO_N: one_to_n_address, } return addresses
def run_app( address: Address, keystore_path: str, gas_price: Callable, eth_rpc_endpoint: str, tokennetwork_registry_contract_address: TokenNetworkRegistryAddress, one_to_n_contract_address: Address, secret_registry_contract_address: Address, service_registry_contract_address: Address, user_deposit_contract_address: Address, monitoring_service_contract_address: Address, api_address: Endpoint, rpc: bool, sync_check: bool, console: bool, password_file: TextIO, web_ui: bool, datadir: str, transport: str, matrix_server: str, network_id: ChainID, environment_type: Environment, unrecoverable_error_should_crash: bool, pathfinding_service_address: str, pathfinding_max_paths: int, enable_monitoring: bool, resolver_endpoint: str, routing_mode: RoutingMode, config: Dict[str, Any], flat_fee: Tuple[Tuple[TokenAddress, FeeAmount], ...], proportional_fee: Tuple[Tuple[TokenAddress, ProportionalFeeAmount], ...], proportional_imbalance_fee: Tuple[Tuple[TokenAddress, ProportionalFeeAmount], ...], blockchain_query_interval: float, cap_mediation_fees: bool, ** kwargs: Any, # FIXME: not used here, but still receives stuff in smoketest ) -> App: # pylint: disable=too-many-locals,too-many-branches,too-many-statements,unused-argument token_network_registry_deployed_at: Optional[BlockNumber] smart_contracts_start_at: BlockNumber if datadir is None: datadir = os.path.join(os.path.expanduser("~"), ".raiden") account_manager = AccountManager(keystore_path) web3 = Web3(HTTPProvider(rpc_normalized_endpoint(eth_rpc_endpoint))) check_sql_version() check_ethereum_has_accounts(account_manager) check_ethereum_client_is_supported(web3) check_ethereum_network_id(network_id, web3) address, privatekey = get_account_and_private_key(account_manager, address, password_file) api_host, api_port = split_endpoint(api_address) if not api_port: api_port = Port(DEFAULT_HTTP_SERVER_PORT) fee_config = prepare_mediation_fee_config( cli_token_to_flat_fee=flat_fee, cli_token_to_proportional_fee=proportional_fee, cli_token_to_proportional_imbalance_fee=proportional_imbalance_fee, cli_cap_mediation_fees=cap_mediation_fees, ) config["console"] = console config["rpc"] = rpc config["web_ui"] = rpc and web_ui config["api_host"] = api_host config["api_port"] = api_port config["resolver_endpoint"] = resolver_endpoint config["transport_type"] = transport config["transport"]["matrix"]["server"] = matrix_server config[ "unrecoverable_error_should_crash"] = unrecoverable_error_should_crash config["services"]["pathfinding_max_paths"] = pathfinding_max_paths config["services"]["monitoring_enabled"] = enable_monitoring config["chain_id"] = network_id config["mediation_fees"] = fee_config config["blockchain"]["query_interval"] = blockchain_query_interval setup_environment(config, environment_type) contracts = setup_contracts_or_exit(config, network_id) rpc_client = JSONRPCClient( web3=web3, privkey=privatekey, gas_price_strategy=gas_price, block_num_confirmations=DEFAULT_NUMBER_OF_BLOCK_CONFIRMATIONS, ) token_network_registry_deployed_at = None if "TokenNetworkRegistry" in contracts: token_network_registry_deployed_at = BlockNumber( contracts["TokenNetworkRegistry"]["block_number"]) if token_network_registry_deployed_at is None: smart_contracts_start_at = get_smart_contracts_start_at(network_id) else: smart_contracts_start_at = token_network_registry_deployed_at proxy_manager = ProxyManager( rpc_client=rpc_client, contract_manager=ContractManager(config["contracts_path"]), metadata=ProxyManagerMetadata( token_network_registry_deployed_at= token_network_registry_deployed_at, filters_start_at=smart_contracts_start_at, ), ) if sync_check: check_synced(proxy_manager) proxies = setup_proxies_or_exit( config=config, tokennetwork_registry_contract_address= tokennetwork_registry_contract_address, secret_registry_contract_address=secret_registry_contract_address, user_deposit_contract_address=user_deposit_contract_address, service_registry_contract_address=service_registry_contract_address, proxy_manager=proxy_manager, contracts=contracts, routing_mode=routing_mode, pathfinding_service_address=pathfinding_service_address, ) check_ethereum_confirmed_block_is_not_pruned( jsonrpc_client=rpc_client, secret_registry=proxies.secret_registry, confirmation_blocks=config["blockchain"]["confirmation_blocks"], ) database_path = os.path.join( datadir, f"node_{pex(address)}", f"netid_{network_id}", f"network_{pex(proxies.token_network_registry.address)}", f"v{RAIDEN_DB_VERSION}_log.db", ) config["database_path"] = database_path print("\nYou are connected to the '{}' network and the DB path is: {}". format(ID_TO_NETWORKNAME.get(network_id, network_id), database_path)) if transport == "matrix": matrix_transport = _setup_matrix(config, routing_mode) else: raise RuntimeError(f'Unknown transport type "{transport}" given') event_handler: EventHandler = RaidenEventHandler() # User should be told how to set fees, if using default fee settings log.debug("Fee Settings", fee_settings=fee_config) has_default_fees = (len(fee_config.token_to_flat_fee) == 0 and len(fee_config.token_to_proportional_fee) == 0 and len(fee_config.token_to_proportional_imbalance_fee) == 0) if has_default_fees: click.secho( "Default fee settings are used. " "If you want use Raiden with mediation fees - flat, proportional and imbalance fees - " "see https://raiden-network.readthedocs.io/en/latest/overview_and_guide.html#firing-it-up", # noqa: E501 fg="yellow", ) monitoring_contract_required = (enable_monitoring and CONTRACT_MONITORING_SERVICE not in contracts) if monitoring_contract_required: click.secho( "Monitoring is enabled but the contract for this ethereum network was not found. " "Please provide monitoring service contract address using " "--monitoring-service-address.", fg="red", ) sys.exit(1) # Only send feedback when PFS is used if routing_mode == RoutingMode.PFS: event_handler = PFSFeedbackEventHandler(event_handler) message_handler = MessageHandler() try: raiden_app = App( config=config, rpc_client=rpc_client, proxy_manager=proxy_manager, query_start_block=smart_contracts_start_at, default_one_to_n_address=(one_to_n_contract_address or contracts[CONTRACT_ONE_TO_N]["address"]), default_registry=proxies.token_network_registry, default_secret_registry=proxies.secret_registry, default_service_registry=proxies.service_registry, default_msc_address=( monitoring_service_contract_address or contracts[CONTRACT_MONITORING_SERVICE]["address"]), transport=matrix_transport, raiden_event_handler=event_handler, message_handler=message_handler, routing_mode=routing_mode, user_deposit=proxies.user_deposit, ) except RaidenError as e: click.secho(f"FATAL: {e}", fg="red") sys.exit(1) try: raiden_app.start() except RuntimeError as e: click.secho(f"FATAL: {e}", fg="red") sys.exit(1) except filelock.Timeout: name_or_id = ID_TO_NETWORKNAME.get(network_id, network_id) click.secho( f"FATAL: Another Raiden instance already running for account " f"{to_checksum_address(address)} on network id {name_or_id}", fg="red", ) sys.exit(1) return raiden_app