def prepare_mediation_fee_config( cli_token_to_flat_fee: Tuple[Tuple[TokenAddress, FeeAmount], ...], cli_token_to_proportional_fee: Tuple[Tuple[TokenAddress, ProportionalFeeAmount], ...], cli_token_to_proportional_imbalance_fee: Tuple[Tuple[ TokenAddress, ProportionalFeeAmount], ...], cli_cap_mediation_fees: bool, ) -> MediationFeeConfig: """Converts the mediation fee CLI args to proper per-channel mediation fees.""" tn_to_flat_fee: Dict[TokenAddress, FeeAmount] = { # Add the defaults for flat fees for DAI/WETH WETH_TOKEN_ADDRESS: FeeAmount(DEFAULT_WETH_FLAT_FEE // 2), DAI_TOKEN_ADDRESS: FeeAmount(DEFAULT_DAI_FLAT_FEE // 2), } # Store the flat fee settings for the given token addresses # The given flat fee is for the whole mediation, but that includes two channels. # Therefore divide by 2 here. for address, fee in cli_token_to_flat_fee: tn_to_flat_fee[address] = FeeAmount(fee // 2) tn_to_proportional_fee: Dict[TokenAddress, ProportionalFeeAmount] = { address: ppm_fee_per_channel(prop_fee) for address, prop_fee in cli_token_to_proportional_fee } tn_to_proportional_imbalance_fee: Dict[ TokenAddress, ProportionalFeeAmount] = { address: prop_fee for address, prop_fee in cli_token_to_proportional_imbalance_fee } return MediationFeeConfig( token_to_flat_fee=tn_to_flat_fee, token_to_proportional_fee=tn_to_proportional_fee, token_to_proportional_imbalance_fee=tn_to_proportional_imbalance_fee, cap_meditation_fees=cli_cap_mediation_fees, )
def create_apps( chain_id: ChainID, contracts_path: str, blockchain_services: BlockchainServices, token_network_registry_address: TokenNetworkRegistryAddress, one_to_n_address: Optional[Address], secret_registry_address: SecretRegistryAddress, service_registry_address: Optional[Address], user_deposit_address: Address, monitoring_service_contract_address: Address, reveal_timeout: BlockTimeout, settle_timeout: BlockTimeout, database_basedir: str, retry_interval: float, retries_before_backoff: int, environment_type: Environment, unrecoverable_error_should_crash: bool, local_matrix_url: Optional[ParsedURL], broadcast_rooms: List[str], routing_mode: RoutingMode, blockchain_query_interval: float, resolver_ports: List[Optional[int]], ) -> List[App]: """ Create the apps.""" # pylint: disable=too-many-locals services = blockchain_services apps = [] for idx, proxy_manager in enumerate(services): database_path = database_from_privatekey(base_dir=database_basedir, app_number=idx) assert len(resolver_ports) > idx resolver_port = resolver_ports[idx] config = { "chain_id": chain_id, "environment_type": environment_type, "unrecoverable_error_should_crash": unrecoverable_error_should_crash, "reveal_timeout": reveal_timeout, "settle_timeout": settle_timeout, "contracts_path": contracts_path, "database_path": database_path, "blockchain": { "confirmation_blocks": DEFAULT_NUMBER_OF_BLOCK_CONFIRMATIONS, "query_interval": blockchain_query_interval, }, "transport": {}, "rpc": True, "console": False, "mediation_fees": MediationFeeConfig(), } if local_matrix_url is not None: merge_dict( config, { "transport_type": "matrix", "transport": { "matrix": { "broadcast_rooms": broadcast_rooms, "retries_before_backoff": retries_before_backoff, "retry_interval": retry_interval, "server": local_matrix_url, "server_name": local_matrix_url.netloc, "available_servers": [], } }, }, ) if resolver_port is not None: merge_dict(config, { "resolver_endpoint": "http://localhost:" + str(resolver_port) }) config_copy = deepcopy(App.DEFAULT_CONFIG) config_copy.update(config) registry = proxy_manager.token_network_registry( token_network_registry_address) 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) user_deposit = None if user_deposit_address: user_deposit = proxy_manager.user_deposit(user_deposit_address) transport = MatrixTransport(config["transport"]["matrix"]) raiden_event_handler = RaidenEventHandler() hold_handler = HoldRaidenEventHandler(raiden_event_handler) message_handler = WaitForMessage() app = App( config=config_copy, rpc_client=proxy_manager.client, proxy_manager=proxy_manager, query_start_block=BlockNumber(0), default_registry=registry, default_one_to_n_address=one_to_n_address, default_secret_registry=secret_registry, default_service_registry=service_registry, default_msc_address=monitoring_service_contract_address, transport=transport, raiden_event_handler=hold_handler, message_handler=message_handler, user_deposit=user_deposit, routing_mode=routing_mode, ) apps.append(app) return apps
def create_apps( chain_id: ChainID, contracts_path: Path, blockchain_services: BlockchainServices, token_network_registry_address: TokenNetworkRegistryAddress, one_to_n_address: Optional[OneToNAddress], secret_registry_address: SecretRegistryAddress, service_registry_address: Optional[ServiceRegistryAddress], user_deposit_address: Optional[UserDepositAddress], monitoring_service_contract_address: MonitoringServiceAddress, reveal_timeout: BlockTimeout, settle_timeout: BlockTimeout, database_basedir: str, retry_interval_initial: float, retry_interval_max: float, retries_before_backoff: int, environment_type: Environment, unrecoverable_error_should_crash: bool, local_matrix_url: Optional[ParsedURL], broadcast_rooms: List[str], routing_mode: RoutingMode, blockchain_query_interval: float, resolver_ports: List[Optional[int]], enable_rest_api: bool, port_generator: Iterator[Port], capabilities_config: CapabilitiesConfig, ) -> List[App]: """ Create the apps.""" # pylint: disable=too-many-locals services = blockchain_services apps = [] for idx, proxy_manager in enumerate(services): database_path = database_from_privatekey(base_dir=database_basedir, app_number=idx) assert len(resolver_ports) > idx resolver_port = resolver_ports[idx] config = RaidenConfig( chain_id=chain_id, environment_type=environment_type, unrecoverable_error_should_crash=unrecoverable_error_should_crash, reveal_timeout=reveal_timeout, settle_timeout=settle_timeout, contracts_path=contracts_path, database_path=database_path, blockchain=BlockchainConfig( confirmation_blocks=DEFAULT_NUMBER_OF_BLOCK_CONFIRMATIONS, query_interval=blockchain_query_interval, ), mediation_fees=MediationFeeConfig(), services=ServiceConfig(monitoring_enabled=False), rest_api=RestApiConfig(rest_api_enabled=enable_rest_api, host=Host("localhost"), port=next(port_generator)), console=False, transport_type="matrix", ) config.transport.capabilities_config = capabilities_config if local_matrix_url is not None: config.transport = MatrixTransportConfig( broadcast_rooms=broadcast_rooms, retries_before_backoff=retries_before_backoff, retry_interval_initial=retry_interval_initial, retry_interval_max=retry_interval_max, server=local_matrix_url, available_servers=[], capabilities_config=capabilities_config, ) assert config.transport.capabilities_config is not None if resolver_port is not None: config.resolver_endpoint = f"http://localhost:{resolver_port}" registry = proxy_manager.token_network_registry( token_network_registry_address, block_identifier=BLOCK_ID_LATEST) secret_registry = proxy_manager.secret_registry( secret_registry_address, block_identifier=BLOCK_ID_LATEST) service_registry = None if service_registry_address: service_registry = proxy_manager.service_registry( service_registry_address, block_identifier=BLOCK_ID_LATEST) user_deposit = None if user_deposit_address: user_deposit = proxy_manager.user_deposit( user_deposit_address, block_identifier=BLOCK_ID_LATEST) # Use `TestMatrixTransport` that saves sent messages for assertions in tests assert config.transport.capabilities_config is not None transport = TestMatrixTransport(config=config.transport, environment=environment_type) raiden_event_handler = RaidenEventHandler() hold_handler = HoldRaidenEventHandler(raiden_event_handler) message_handler = WaitForMessage() api_server = None if enable_rest_api: api_server = start_api_server(rpc_client=proxy_manager.client, config=config.rest_api, eth_rpc_endpoint="bla") app = App( config=config, rpc_client=proxy_manager.client, proxy_manager=proxy_manager, query_start_block=BlockNumber(0), default_registry=registry, default_secret_registry=secret_registry, default_service_registry=service_registry, default_user_deposit=user_deposit, default_one_to_n_address=one_to_n_address, default_msc_address=monitoring_service_contract_address, transport=transport, raiden_event_handler=hold_handler, message_handler=message_handler, routing_mode=routing_mode, api_server=api_server, ) apps.append(app) return apps
def test_pfs_send_unique_capacity_and_fee_updates_during_mediated_transfer( raiden_network): """ Tests that PFSCapacityUpdates and PFSFeeUpdates are being sent only once with the most recent state change in a batch. """ app0, app1 = raiden_network chain_state = views.state_from_app(app0) # There have been two PFSCapacityUpdates and two PFSFeeUpdates per channel per node assert len(get_messages(app0)) == 4 # The mediator has two channels assert len(get_messages(app1)) == 4 # Now we create two state_changes (Deposit) regarding the same channel # and trigger handle_state_changes() of node0. The expected outcome # is that only 1 PFSCapacityUpdate and 1 PFSFeeUpdate is being sent # not one per state change pfs_fee_update_1_of_app0 = get_messages(app0)[1] assert isinstance(pfs_fee_update_1_of_app0, PFSFeeUpdate) pfs_capacity_update_2_of_app0 = get_messages(app0)[2] assert isinstance(pfs_capacity_update_2_of_app0, PFSCapacityUpdate) canonical_identifier = pfs_fee_update_1_of_app0.canonical_identifier new_total_deposit_1 = pfs_capacity_update_2_of_app0.other_capacity * 2 deposit_transaction_1 = TransactionChannelDeposit( app1.raiden.address, TokenAmount(new_total_deposit_1), chain_state.block_number) channel_deposit_1 = ContractReceiveChannelDeposit( transaction_hash=make_transaction_hash(), canonical_identifier=canonical_identifier, deposit_transaction=deposit_transaction_1, block_number=chain_state.block_number, block_hash=chain_state.block_hash, fee_config=MediationFeeConfig(), ) new_total_deposit_2 = new_total_deposit_1 * 2 deposit_transaction_2 = TransactionChannelDeposit( app1.raiden.address, TokenAmount(new_total_deposit_2), chain_state.block_number) channel_deposit_2 = ContractReceiveChannelDeposit( transaction_hash=make_transaction_hash(), canonical_identifier=canonical_identifier, deposit_transaction=deposit_transaction_2, block_number=chain_state.block_number, block_hash=chain_state.block_hash, fee_config=MediationFeeConfig(), ) state_changes = [channel_deposit_1, channel_deposit_2] app0.raiden.handle_state_changes(state_changes=state_changes) # Now we should see that app0 send 2 new messages, # one PFSCapacityUpdate and one PFSFeeUpdate with # the updated amount of the initial amount * 4 # so sending should only be triggered by the second state change pfs_capacity_update_3_of_app0 = get_messages(app0)[4] assert isinstance(pfs_capacity_update_3_of_app0, PFSCapacityUpdate) assert len(get_messages(app0)) == 6 assert (pfs_capacity_update_3_of_app0.other_capacity == pfs_capacity_update_2_of_app0.updating_capacity * 4) # Now we want to test if this also works with a state_change # that triggers only a PFSCapacityUpdate and no PFSFeeUpdate. # So at the end we expect 1 more PFSCapacityUpdate in the room. lock_secret_1 = keccak(b"test_end_state") unlock_message_1 = Unlock( chain_id=chain_state.chain_id, message_identifier=MessageID(123132), payment_identifier=PaymentID(1), nonce=Nonce(2), token_network_address=canonical_identifier.token_network_address, channel_identifier=canonical_identifier.channel_identifier, transferred_amount=TokenAmount(400), locked_amount=LockedAmount(0), locksroot=Locksroot(keccak(b"")), secret=Secret(lock_secret_1), signature=Signature(bytes(65)), ) unlock_message_1.sign(app1.raiden.signer) balance_proof_1 = balanceproof_from_envelope(unlock_message_1) unlock_1 = ReceiveUnlock( message_identifier=MessageID(5135), secret=Secret(lock_secret_1), balance_proof=balance_proof_1, sender=balance_proof_1.sender, ) lock_secret_2 = keccak(b"test_end_state_again") unlock_message_2 = Unlock( chain_id=chain_state.chain_id, message_identifier=MessageID(223132), payment_identifier=PaymentID(2), nonce=Nonce(2), token_network_address=canonical_identifier.token_network_address, channel_identifier=canonical_identifier.channel_identifier, transferred_amount=TokenAmount(500), locked_amount=LockedAmount(0), locksroot=Locksroot(keccak(b"")), secret=Secret(lock_secret_2), signature=Signature(bytes(65)), ) unlock_message_2.sign(app1.raiden.signer) balance_proof_2 = balanceproof_from_envelope(unlock_message_2) unlock_2 = ReceiveUnlock( message_identifier=MessageID(5135), secret=Secret(lock_secret_2), balance_proof=balance_proof_2, sender=balance_proof_2.sender, ) state_changes_2 = [unlock_1, unlock_2] app0.raiden.handle_state_changes(state_changes=state_changes_2) assert len(get_messages(app0)) == 7 assert len([ x for x in get_messages(app0) if isinstance(x, PFSCapacityUpdate) ]) == 4