def _run(self, *args, **kwargs): events = query_blockchain_events( web3=self.web3, contract_manager=self._runner.contract_manager, contract_address=self._runner.token_network_address, contract_name=CONTRACT_TOKEN_NETWORK, topics=[], from_block=BlockNumber(self._runner.token_deployment_block), to_block=BlockNumber(self.web3.eth.blockNumber), ) # Filter matching events events = [e for e in events if e['event'] == self.event_name] # Raise exception when events do not match if not self.num_events == len(events): raise ScenarioAssertionError( f'Expected number of events ({self.num_events}) did not match the number ' f'of events found ({len(events)})', )
def test_get_filter_args(contract_manager): channel_identifier = factories.UNIT_CHANNEL_ID token_network_address = factories.UNIT_TOKEN_NETWORK_ADDRESS event_filter_params = get_filter_args_for_all_events_from_channel( token_network_address=token_network_address, channel_identifier=channel_identifier, contract_manager=contract_manager, ) assert event_filter_params["topics"][0] is None assert to_int( hexstr=event_filter_params["topics"][1]) == channel_identifier assert event_filter_params["address"] == to_checksum_address( token_network_address) assert event_filter_params["fromBlock"] == 0 assert event_filter_params["toBlock"] == BLOCK_ID_LATEST with pytest.raises(ValueError): # filter argument generation checks if event type is known get_filter_args_for_specific_event_from_channel( token_network_address=token_network_address, channel_identifier=channel_identifier, event_name="NonexistingEvent", contract_manager=contract_manager, ) event_filter_params = get_filter_args_for_specific_event_from_channel( token_network_address=token_network_address, channel_identifier=channel_identifier, event_name="ChannelOpened", contract_manager=contract_manager, from_block=BlockNumber(100), to_block=BlockNumber(200), ) assert event_filter_params["topics"][0] is not None assert to_int( hexstr=event_filter_params["topics"][1]) == channel_identifier assert event_filter_params["address"] == to_checksum_address( token_network_address) assert event_filter_params["fromBlock"] == 100 assert event_filter_params["toBlock"] == 200
def query_callback(): return query_blockchain_events( web3=web3, contract_manager=contract_manager, contract_address=contract_address, contract_name=CONTRACT_TOKEN_NETWORK_REGISTRY, topics=[], from_block=BlockNumber(0), to_block=web3.eth.blockNumber, )
def get_contract_addresses_and_start_block( chain_id: ChainID, contracts: List[str], address_overwrites: Dict[str, Address], contracts_version: str = None, ) -> Tuple[Dict[str, Address], BlockNumber]: """ Returns contract addresses and start query block for a given chain and contracts version. The default contracts can be overwritten by the additional parameters. Args: chain_id: The chain id to look for deployed contracts. contracts: The list of contracts which should be considered address_overwrites: Dict of addresses which should be used instead of the ones in the requested deployment. contracts_version: The version of the contracts to use. Returns: A dictionary with the contract addresses and start block for the given information """ contract_data = get_contracts_deployment_info(chain_id=chain_id, version=contracts_version) if not contract_data: log.error( "No deployed contracts were found at the default registry", contracts_version=contracts_version, ) sys.exit(1) # Get deployed addresses for those contracts which have no overwrites addresses = { c: address_overwrites.get(c, Address(decode_hex(contract_data["contracts"][c]["address"]))) for c in contracts } # Set start block to zero if any contract addresses are overwritten if any(address_overwrites.values()): start_block = BlockNumber(0) else: start_block = BlockNumber( max(0, min(contract_data["contracts"][c]["block_number"] for c in contracts)) ) return addresses, start_block
def from_dict(cls, data: Dict[str, Any]) -> 'ContractReceiveRouteClosed': return cls( transaction_hash=deserialize_transactionhash(data['transaction_hash']), canonical_identifier=CanonicalIdentifier( chain_identifier=CHAIN_ID_UNSPECIFIED, token_network_address=to_canonical_address(data['token_network_identifier']), channel_identifier=ChannelID(int(data['channel_identifier'])), ), block_number=BlockNumber(int(data['block_number'])), block_hash=BlockHash(deserialize_bytes(data['block_hash'])), )
def __init__( self, filename: str, chain_id: int, msc_address: Address, registry_address: Address, receiver: str, sync_start_block: BlockNumber = BlockNumber(0), ) -> None: super(Database, self).__init__(filename, allow_create=True) self._setup(chain_id, msc_address, registry_address, receiver, sync_start_block)
def from_dict(cls, data: Dict[str, Any]) -> 'ContractReceiveRouteNew': return cls( transaction_hash=deserialize_bytes(data['transaction_hash']), token_network_identifier=to_canonical_address( data['token_network_identifier']), channel_identifier=ChannelID(int(data['channel_identifier'])), participant1=to_canonical_address(data['participant1']), participant2=to_canonical_address(data['participant2']), block_number=BlockNumber(int(data['block_number'])), block_hash=BlockHash(deserialize_bytes(data['block_hash'])), )
def test_channel_closed_event_handler_idempotency(context: Context): context = setup_state_with_open_channel(context) context.web3.eth.blockNumber = BlockNumber(60) event = ReceiveChannelClosedEvent( token_network_address=DEFAULT_TOKEN_NETWORK_ADDRESS, channel_identifier=DEFAULT_CHANNEL_IDENTIFIER, closing_participant=DEFAULT_PARTICIPANT2, block_number=BlockNumber(52), ) channel_closed_event_handler(event, context) # ActionMonitoringTriggeredEvent has been triggered assert context.database.scheduled_event_count() == 1 assert context.database.channel_count() == 1 assert_channel_state(context, ChannelState.CLOSED) # run handler again, check idempotency channel_closed_event_handler(event, context) assert context.database.scheduled_event_count() == 1
def from_dict(cls, data: Dict[str, Any]) -> 'ContractReceiveChannelNewBalance': return cls( transaction_hash=deserialize_bytes(data['transaction_hash']), token_network_identifier=to_canonical_address( data['token_network_identifier']), channel_identifier=ChannelID(int(data['channel_identifier'])), deposit_transaction=data['deposit_transaction'], block_number=BlockNumber(int(data['block_number'])), block_hash=BlockHash(deserialize_bytes(data['block_hash'])), )
def test_recovery_blockchain_events(raiden_network, restart_node, token_addresses, network_wait): """ Close one of the two raiden apps that have a channel between them, have the counterparty close the channel and then make sure the restarted app sees the change """ app0, app1 = raiden_network token_address = token_addresses[0] app0.raiden.stop() new_transport = MatrixTransport( config=app0.raiden.config.transport, environment=app0.raiden.config.environment_type ) app1_api = RaidenAPI(app1.raiden) app1_api.channel_close( registry_address=app0.raiden.default_registry.address, token_address=token_address, partner_address=app0.raiden.address, ) app0.stop() raiden_event_handler = RaidenEventHandler() message_handler = MessageHandler() app0_restart = App( config=app0.config, rpc_client=app0.raiden.rpc_client, proxy_manager=app0.raiden.proxy_manager, query_start_block=BlockNumber(0), default_registry=app0.raiden.default_registry, default_secret_registry=app0.raiden.default_secret_registry, default_service_registry=app0.raiden.default_service_registry, default_user_deposit=app0.raiden.default_user_deposit, default_one_to_n_address=app0.raiden.default_one_to_n_address, default_msc_address=app0.raiden.default_msc_address, transport=new_transport, raiden_event_handler=raiden_event_handler, message_handler=message_handler, routing_mode=RoutingMode.PRIVATE, ) del app0 # from here on the app0_restart should be used restart_node(app0_restart) wal = app0_restart.raiden.wal assert wal # wait for the nodes' healthcheck to update the network statuses waiting.wait_for_healthy(app0_restart.raiden, app1.raiden.address, network_wait) waiting.wait_for_healthy(app1.raiden, app0_restart.raiden.address, network_wait) restarted_state_changes = wal.storage.get_statechanges_by_range(RANGE_ALL_STATE_CHANGES) assert search_for_item(restarted_state_changes, ContractReceiveChannelClosed, {})
def from_dict(cls, data: Dict[str, Any]) -> "ContractReceiveUpdateTransfer": return cls( transaction_hash=deserialize_transactionhash( data["transaction_hash"]), canonical_identifier=CanonicalIdentifier.from_dict( data["canonical_identifier"]), nonce=Nonce(int(data["nonce"])), block_number=BlockNumber(int(data["block_number"])), block_hash=BlockHash(deserialize_bytes(data["block_hash"])), )
def from_dict(cls, data: Dict[str, Any]) -> "ContractReceiveNewTokenNetwork": return cls( transaction_hash=deserialize_transactionhash( data["transaction_hash"]), payment_network_identifier=to_canonical_address( data["payment_network_identifier"]), token_network=data["token_network"], block_number=BlockNumber(int(data["block_number"])), block_hash=BlockHash(deserialize_bytes(data["block_hash"])), )
def from_dict(cls, data: Dict[str, Any]) -> "ContractReceiveRouteNew": return cls( transaction_hash=deserialize_transactionhash( data["transaction_hash"]), canonical_identifier=CanonicalIdentifier.from_dict( data["canonical_identifier"]), participant1=to_canonical_address(data["participant1"]), participant2=to_canonical_address(data["participant2"]), block_number=BlockNumber(int(data["block_number"])), block_hash=BlockHash(deserialize_bytes(data["block_hash"])), )
def get_pessimistic_udc_balance(udc: Contract, address: Address, from_block: BlockNumber, to_block: BlockNumber) -> TokenAmount: """Get the effective UDC balance using the block with the lowest result. Blocks between the latest confirmed block and the latest block are considered. """ return min( udc.functions.effectiveBalance(address).call( block_identifier=BlockNumber(block)) for block in range(from_block, to_block + 1))
def from_dict(cls, data: Dict[str, Any]) -> "ContractReceiveSecretReveal": return cls( transaction_hash=deserialize_transactionhash( data["transaction_hash"]), secret_registry_address=to_canonical_address( data["secret_registry_address"]), secrethash=deserialize_secret_hash(data["secrethash"]), secret=deserialize_secret(data["secret"]), block_number=BlockNumber(int(data["block_number"])), block_hash=BlockHash(deserialize_bytes(data["block_hash"])), )
def new_service(filename): service = PathfindingService( web3=Web3Mock(), private_key=server_private_key, contracts=contracts, sync_start_block=BlockNumber(0), required_confirmations=BlockTimeout(0), poll_interval=0, db_filename=os.path.join(tmpdir, filename), ) return service
def from_dict(cls, data: Dict[str, Any]) -> "ContractReceiveChannelNewBalance": return cls( transaction_hash=deserialize_transactionhash( data["transaction_hash"]), canonical_identifier=CanonicalIdentifier.from_dict( data["canonical_identifier"]), deposit_transaction=data["deposit_transaction"], block_number=BlockNumber(int(data["block_number"])), block_hash=BlockHash(deserialize_bytes(data["block_hash"])), )
def make_request() -> BlockNumber: response = requests.get( "https://api.blockcypher.com/v1/eth/main", headers={ "ACCEPT": "application/json", "USER-AGENT": f"raiden-{pkg_resources.require(raiden.__name__)[0].version}", }, ) return BlockNumber(json.loads(response.content)["height"])
def test_channel_settled_event_handler_settles_existing_channel(context: Context): context = setup_state_with_closed_channel(context) event = ReceiveChannelSettledEvent( token_network_address=DEFAULT_TOKEN_NETWORK_ADDRESS, channel_identifier=DEFAULT_CHANNEL_IDENTIFIER, block_number=BlockNumber(52), ) channel_settled_event_handler(event, context) assert context.database.channel_count() == 1 assert_channel_state(context, ChannelState.SETTLED)
def test_blockchain_events(contract_manager): # TODO Expand this test: multiple listeners, removed listeners, multiple/missed events. # As it is now it only covers the classès helper functions in raiden.utils.filters properly. blockchain_events = BlockchainEvents(UNIT_CHAIN_ID) abi = contract_manager.get_contract_abi("TokenNetwork") stateless_filter = StatelessFilter(web3=stub_web3(event_logs), filter_params=dict(toBlock="pending")) blockchain_events.add_event_listener(event_name="Block", eth_filter=stateless_filter, abi=abi) events = list( blockchain_events.poll_blockchain_events( block_number=BlockNumber(235))) assert len(events) == 1 assert len(stateless_filter.get_all_entries(BlockNumber(235))) == 1 assert check_dict_nested_attrs(events[0].event_data, event1) blockchain_events.uninstall_all_event_listeners()
def setup_channel(pathfinding_service_mock, token_network_model): channel_event = ReceiveChannelOpenedEvent( token_network_address=token_network_model.address, channel_identifier=ChannelID(1), participant1=PARTICIPANT1, participant2=PARTICIPANT2, settle_timeout=20, block_number=BlockNumber(1), ) assert len(pathfinding_service_mock.token_networks) == 1 assert len(token_network_model.channel_id_to_addresses) == 0 pathfinding_service_mock.handle_event(channel_event)
def test_get_blockchain_events_adaptive_reduces_block_interval_after_timeout( web3: Web3, token_network_registry_contract: Contract): chain_state = BlockchainState( chain_id=ChainID(1), token_network_registry_address=to_canonical_address( token_network_registry_contract.address), latest_committed_block=BlockNumber(4), ) assert chain_state.current_event_filter_interval == DEFAULT_FILTER_INTERVAL with patch("raiden_libs.blockchain.get_blockchain_events", side_effect=ReadTimeout): _ = get_blockchain_events_adaptive( web3=web3, token_network_addresses=[], blockchain_state=chain_state, latest_confirmed_block=BlockNumber(1), ) assert chain_state.current_event_filter_interval == DEFAULT_FILTER_INTERVAL // 5
def test_channel_settled_event_handler_leaves_existing_channel(context: Context,): context = setup_state_with_closed_channel(context) event = ReceiveChannelSettledEvent( token_network_address=DEFAULT_TOKEN_NETWORK_ADDRESS, channel_identifier=ChannelID(4), block_number=BlockNumber(52), ) channel_settled_event_handler(event, context) assert context.db.channel_count() == 1 assert_channel_state(context, ChannelState.CLOSED)
def test_channel_bp_updated_event_handler_sets_update_status_if_not_set(context: Context,): context = setup_state_with_closed_channel(context) event_bp = ReceiveNonClosingBalanceProofUpdatedEvent( token_network_address=DEFAULT_TOKEN_NETWORK_ADDRESS, channel_identifier=DEFAULT_CHANNEL_IDENTIFIER, closing_participant=DEFAULT_PARTICIPANT2, nonce=Nonce(2), block_number=BlockNumber(23), ) channel = context.db.get_channel(event_bp.token_network_address, event_bp.channel_identifier) assert channel assert channel.update_status is None non_closing_balance_proof_updated_event_handler(event_bp, context) assert context.db.channel_count() == 1 channel = context.db.get_channel(event_bp.token_network_address, event_bp.channel_identifier) assert channel assert channel.update_status is not None assert channel.update_status.nonce == 2 assert channel.update_status.update_sender_address == DEFAULT_PARTICIPANT1 event_bp2 = ReceiveNonClosingBalanceProofUpdatedEvent( token_network_address=DEFAULT_TOKEN_NETWORK_ADDRESS, channel_identifier=DEFAULT_CHANNEL_IDENTIFIER, closing_participant=DEFAULT_PARTICIPANT2, nonce=Nonce(5), block_number=BlockNumber(53), ) non_closing_balance_proof_updated_event_handler(event_bp2, context) assert context.db.channel_count() == 1 channel = context.db.get_channel(event_bp.token_network_address, event_bp.channel_identifier) assert channel assert channel.update_status is not None assert channel.update_status.nonce == 5 assert channel.update_status.update_sender_address == DEFAULT_PARTICIPANT1
def __init__( self, web3: Web3, contracts: Dict[str, Contract], private_key: str, db_filename: str, sync_start_block: BlockNumber = BlockNumber(0), required_confirmations: int = 8, poll_interval: float = 10, service_fee: int = 0, ): super().__init__() self.web3 = web3 self.registry_address = contracts[CONTRACT_TOKEN_NETWORK_REGISTRY].address self.sync_start_block = sync_start_block self.required_confirmations = required_confirmations self.poll_interval = poll_interval self.chain_id = ChainID(int(web3.net.version)) self.private_key = private_key self.address = private_key_to_address(private_key) self.service_fee = service_fee self.is_running = gevent.event.Event() self.token_networks: Dict[TokenNetworkAddress, TokenNetwork] = {} self.database = PFSDatabase(filename=db_filename, pfs_address=self.address) self.user_deposit_contract = contracts[CONTRACT_USER_DEPOSIT] self.last_known_block = 0 self.blockchain_state = BlockchainState( chain_id=self.chain_id, token_network_registry_address=self.registry_address, monitor_contract_address=Address(''), # FIXME latest_known_block=self.sync_start_block, token_network_addresses=[], ) log.info( 'Listening to token network registry', registry_address=self.registry_address, start_block=sync_start_block, ) try: self.matrix_listener = MatrixListener( private_key=private_key, chain_id=self.chain_id, callback=self.handle_message, service_room_suffix=PATH_FINDING_BROADCASTING_ROOM, ) except ConnectionError as e: log.critical('Could not connect to broadcasting system.', exc=e) sys.exit(1)
def deploy_secret_registry(deploy_client: JSONRPCClient, contract_manager: ContractManager, proxy_manager: ProxyManager) -> SecretRegistry: contract, receipt = deploy_client.deploy_single_contract( contract_name=CONTRACT_SECRET_REGISTRY, contract=contract_manager.get_contract(CONTRACT_SECRET_REGISTRY), constructor_parameters=None, ) return proxy_manager.secret_registry( SecretRegistryAddress(to_canonical_address(contract.address)), BlockNumber(receipt["blockNumber"]), )
def from_dict(cls, data: Dict[str, Any]) -> 'ContractReceiveChannelBatchUnlock': return cls( transaction_hash=deserialize_bytes(data['transaction_hash']), token_network_identifier=to_canonical_address( data['token_network_identifier']), participant=to_canonical_address(data['participant']), partner=to_canonical_address(data['partner']), locksroot=deserialize_bytes(data['locksroot']), unlocked_amount=int(data['unlocked_amount']), returned_tokens=int(data['returned_tokens']), block_number=BlockNumber(int(data['block_number'])), )
def test_channel_closed_event_handler_trigger_action_monitor_event_without_monitor_request( context: Context, ): context = setup_state_with_open_channel(context) event = ReceiveChannelClosedEvent( token_network_address=DEFAULT_TOKEN_NETWORK_ADDRESS, channel_identifier=DEFAULT_CHANNEL_IDENTIFIER, closing_participant=DEFAULT_PARTICIPANT2, block_number=BlockNumber(52), ) channel_closed_event_handler(event, context) assert context.db.scheduled_event_count() == 1
def test_channel_closed_event_handler_leaves_existing_channel(context: Context): context = setup_state_with_open_channel(context) event = ReceiveChannelClosedEvent( token_network_address=DEFAULT_TOKEN_NETWORK_ADDRESS, channel_identifier=ChannelID(4), closing_participant=DEFAULT_PARTICIPANT2, block_number=BlockNumber(52), ) channel_closed_event_handler(event, context) assert context.db.channel_count() == 1 assert_channel_state(context, ChannelState.OPENED)
def test_metrics_iou( # pylint: disable=too-many-locals pathfinding_service_web3_mock: PathfindingService, one_to_n_contract, web3: Web3, deposit_to_udc, get_accounts, get_private_key, ): pfs = pathfinding_service_web3_mock metrics_state = save_metrics_state(metrics.REGISTRY) # Prepare test data account = [decode_hex(acc) for acc in get_accounts(1)][0] local_signer = LocalSigner(private_key=get_private_key(account)) iou = IOU( sender=account, receiver=pfs.address, amount=TokenAmount(100), expiration_block=BlockNumber(100), signature=Signature(bytes([1] * 64)), chain_id=ChainID(61), one_to_n_address=to_canonical_address(one_to_n_contract.address), claimed=False, ) iou.signature = Signature(local_signer.sign(iou.packed_data())) pfs.database.upsert_iou(iou) deposit_to_udc(iou.sender, 300) # Claim IOUs skipped, failures = claim_ious( ious=[iou], claim_cost_rdn=TokenAmount(100), one_to_n_contract=one_to_n_contract, web3=web3, database=pfs.database, ) assert (skipped, failures) == (0, 0) assert ( metrics_state.get_delta( "economics_iou_claims_total", labels=metrics.IouStatus.SUCCESSFUL.to_label_dict() ) == 1.0 ) assert ( metrics_state.get_delta( "economics_iou_claims_token_total", labels=metrics.IouStatus.SUCCESSFUL.to_label_dict(), ) == 100.0 )