def contract_manager_meta(contracts_path): manager = ContractManager(contracts_path) abi = manager.get_contract_abi('TokenNetwork') assert isinstance(abi, list) with pytest.raises(KeyError): manager.get_contract_abi('SomeName') abi = manager.get_event_abi('TokenNetwork', 'ChannelClosed') assert isinstance(abi, dict) with pytest.raises(KeyError): manager.get_event_abi('TokenNetwork', 'NonExistant')
def contract_manager_meta(contracts_path): manager = ContractManager(contracts_path) abi = manager.get_contract_abi(CONTRACT_TOKEN_NETWORK) assert isinstance(abi, list) with pytest.raises(KeyError): manager.get_contract_abi('SomeName') abi = manager.get_event_abi(CONTRACT_TOKEN_NETWORK, EVENT_CHANNEL_CLOSED) assert isinstance(abi, dict) with pytest.raises(ValueError): manager.get_event_abi(CONTRACT_TOKEN_NETWORK, 'NonExistant')
def contract_manager_meta(contracts_path): """ See failures in looking up non-existent ABI entries of TokenNetwork and CLOSED """ manager = ContractManager(contracts_path) abi = manager.get_contract_abi(CONTRACT_TOKEN_NETWORK) assert isinstance(abi, list) with pytest.raises(KeyError): manager.get_contract_abi('SomeName') abi = manager.get_event_abi(CONTRACT_TOKEN_NETWORK, ChannelEvent.CLOSED) assert isinstance(abi, dict) with pytest.raises(ValueError): manager.get_event_abi(CONTRACT_TOKEN_NETWORK, 'NonExistant')
def get_netting_channel_deposit_events( proxy_manager: ProxyManager, token_network_address: TokenNetworkAddress, netting_channel_identifier: ChannelID, contract_manager: ContractManager, from_block: BlockSpecification = GENESIS_BLOCK_NUMBER, to_block: BlockSpecification = "latest", ) -> List[Dict]: deposit_event_abi = contract_manager.get_event_abi(CONTRACT_TOKEN_NETWORK, ChannelEvent.DEPOSIT) topic_set = construct_event_topic_set( event_abi=deposit_event_abi, arguments={"channel_identifier": netting_channel_identifier}) if len(topic_set) == 1 and is_list_like(topic_set[0]): topics = topic_set[0] else: topics = topic_set return get_contract_events( proxy_manager, contract_manager.get_contract_abi(CONTRACT_TOKEN_NETWORK), Address(token_network_address), topics, from_block, to_block, )
def get_filter_args_for_specific_event_from_channel( token_network_address: TokenNetworkAddress, channel_identifier: ChannelID, event_name: str, contract_manager: ContractManager, from_block: BlockIdentifier = GENESIS_BLOCK_NUMBER, to_block: BlockIdentifier = BLOCK_ID_LATEST, ) -> FilterParams: """ Return the filter params for a specific event of a given channel. """ event_abi = contract_manager.get_event_abi(CONTRACT_TOKEN_NETWORK, event_name) # Here the topics for a specific event are created # The first entry of the topics list is the event name, then the first parameter is encoded, # in the case of a token network, the first parameter is always the channel identifier _, event_filter_params = construct_event_filter_params( event_abi=event_abi, abi_codec=ABI_CODEC, contract_address=to_checksum_address(token_network_address), argument_filters={"channel_identifier": channel_identifier}, fromBlock=from_block, toBlock=to_block, ) return event_filter_params
def get_filter_args_for_specific_event_from_channel( token_network_address: TokenNetworkAddress, channel_identifier: ChannelID, event_name: str, contract_manager: ContractManager, from_block: BlockSpecification = GENESIS_BLOCK_NUMBER, to_block: BlockSpecification = 'latest', ): """ Return the filter params for a specific event of a given channel. """ if not event_name: raise ValueError('Event name must be given') event_abi = contract_manager.get_event_abi(CONTRACT_TOKEN_NETWORK, event_name) # Here the topics for a specific event are created # The first entry of the topics list is the event name, then the first parameter is encoded, # in the case of a token network, the first parameter is always the channel identifier _, event_filter_params = construct_event_filter_params( event_abi=event_abi, contract_address=to_checksum_address(token_network_address), argument_filters={ 'channel_identifier': channel_identifier, }, fromBlock=from_block, toBlock=to_block, ) return event_filter_params
def test_filter( generate_raiden_client, web3, contracts_manager: ContractManager, ): """test if filter returns past events""" c1 = generate_raiden_client() c2 = generate_raiden_client() c3 = generate_raiden_client() channel_id = c1.open_channel(c2.address) bp = c2.get_balance_proof(c1.address, transferred_amount=1, nonce=1) c1.close_channel(c2.address, bp) gevent.sleep(0) abi = contracts_manager.get_event_abi('TokenNetwork', 'ChannelClosed') assert abi is not None f = make_filter(web3, abi, fromBlock=0) entries = f.get_new_entries() assert len([ x for x in entries if (x['args']['channel_identifier'] == channel_id and x['address'] == c1.contract.address) ]) == 1 channel_id = c1.open_channel(c3.address) bp = c3.get_balance_proof(c1.address, transferred_amount=1, nonce=1) c1.close_channel(c3.address, bp) entries = f.get_new_entries() assert len([ x for x in entries if (x['args']['channel_identifier'] == channel_id and x['address'] == c1.contract.address) ]) == 1 assert len(f.get_all_entries()) > 0
def test_setURL(custom_token: Contract, service_registry: Contract, get_accounts: Callable, web3: Web3) -> None: """A ServiceRegistry allows registered service providers to set their URLs""" (A, ) = get_accounts(1) url1 = "http://example.com" url2 = "http://raiden.example.com" call_and_transact(custom_token.functions.mint(SERVICE_DEPOSIT), {"from": A}) call_and_transact( custom_token.functions.approve(service_registry.address, SERVICE_DEPOSIT), {"from": A}, ) tx = call_and_transact(service_registry.functions.deposit(SERVICE_DEPOSIT), {"from": A}) tx_receipt = web3.eth.get_transaction_receipt(tx) contract_manager = ContractManager( contracts_precompiled_path(version=None)) event_abi = contract_manager.get_event_abi(CONTRACT_SERVICE_REGISTRY, EVENT_REGISTERED_SERVICE) event_data = get_event_data(web3.codec, event_abi, tx_receipt["logs"][-1]) assert event_data["args"]["service"] == A assert event_data["args"]["deposit_contract"] != EMPTY_ADDRESS call_and_transact(service_registry.functions.setURL(url1), {"from": A}) assert service_registry.functions.urls(A).call() == url1 call_and_transact(service_registry.functions.setURL(url2), {"from": A}) assert service_registry.functions.urls(A).call() == url2
def get_filter_args_for_specific_event_from_channel( token_network_address: TokenNetworkAddress, channel_identifier: ChannelID, event_name: str, contract_manager: ContractManager, from_block: BlockSpecification = GENESIS_BLOCK_NUMBER, to_block: BlockSpecification = "latest", ): """ Return the filter params for a specific event of a given channel. """ if not event_name: raise ValueError("Event name must be given") event_abi = contract_manager.get_event_abi(CONTRACT_TOKEN_NETWORK, event_name) # Here the topics for a specific event are created # The first entry of the topics list is the event name, then the first parameter is encoded, # in the case of a token network, the first parameter is always the channel identifier _, event_filter_params = construct_event_filter_params( event_abi=event_abi, contract_address=to_checksum_address(token_network_address), argument_filters={"channel_identifier": channel_identifier}, fromBlock=from_block, toBlock=to_block, ) return event_filter_params
def get_events( w3: Web3, contract_manager: ContractManager, contract_name: str, event_name: str, from_block: Union[int, str] = 0, to_block: Union[int, str] = 'latest', ) -> List: """Returns events emmitted by a contract for a given event name, within a certain range. Args: w3: A Web3 instance contract_manager: A contract manager contract_name: The name of the contract event_name: The name of the event from_block: The block to start search events to_block: The block to stop searching for events Returns: All matching events""" filter = create_event_filter( web3=w3, event_name=event_name, event_abi=contract_manager.get_event_abi(contract_name, event_name), filter_params={ 'fromBlock': from_block, 'toBlock': to_block, } ) events = filter.get_all_entries() w3.eth.uninstallFilter(filter.filter_id) return events
def get_netting_channel_deposit_events( chain: BlockChainService, token_network_address: Address, netting_channel_identifier: ChannelID, contract_manager: ContractManager, from_block: BlockSpecification = GENESIS_BLOCK_NUMBER, to_block: BlockSpecification = 'latest', ) -> List[Dict]: deposit_event_abi = contract_manager.get_event_abi( CONTRACT_TOKEN_NETWORK, ChannelEvent.DEPOSIT, ) topic_set = construct_event_topic_set( event_abi=deposit_event_abi, arguments={'channel_identifier': netting_channel_identifier}, ) if len(topic_set) == 1 and is_list_like(topic_set[0]): topics = topic_set[0] else: topics = topic_set return get_contract_events( chain, contract_manager.get_contract_abi(CONTRACT_TOKEN_NETWORK), token_network_address, topics, from_block, to_block, )
def get_netting_channel_closed_events( proxy_manager: ProxyManager, token_network_address: TokenNetworkAddress, netting_channel_identifier: ChannelID, contract_manager: ContractManager, from_block: BlockIdentifier = GENESIS_BLOCK_NUMBER, to_block: BlockIdentifier = BLOCK_ID_LATEST, ) -> List[Dict]: closed_event_abi = contract_manager.get_event_abi(CONTRACT_TOKEN_NETWORK, ChannelEvent.CLOSED) topic_set = construct_event_topic_set( event_abi=closed_event_abi, abi_codec=proxy_manager.client.web3.codec, arguments={"channel_identifier": netting_channel_identifier}, ) return get_contract_events( proxy_manager=proxy_manager, abi=contract_manager.get_contract_abi(CONTRACT_TOKEN_NETWORK), contract_address=Address(token_network_address), topics=topic_set, # type: ignore from_block=from_block, to_block=to_block, )
def get_netting_channel_closed_events( chain: BlockChainService, token_network_address: Address, netting_channel_identifier: ChannelID, contract_manager: ContractManager, from_block: BlockSpecification = 0, to_block: BlockSpecification = 'latest', ) -> List[Dict]: closed_event_abi = contract_manager.get_event_abi( CONTRACT_TOKEN_NETWORK, ChannelEvent.CLOSED, ) topic_set = construct_event_topic_set( event_abi=closed_event_abi, arguments={'channel_identifier': netting_channel_identifier}, ) if len(topic_set) == 1 and is_list_like(topic_set[0]): topics = topic_set[0] else: topics = topic_set return get_contract_events( chain=chain, abi=contract_manager.get_contract_abi(CONTRACT_TOKEN_NETWORK), contract_address=token_network_address, topics=topics, from_block=from_block, to_block=to_block, )
def test_set_deprecation_switch(get_accounts: Callable, token_network: Contract, web3: Web3, contracts_manager: ContractManager) -> None: """ The deprecation executor deprecates a TokenNetwork contract """ (A) = get_accounts(1)[0] deprecation_executor = token_network.functions.deprecation_executor().call( ) assert token_network.functions.safety_deprecation_switch().call() is False with pytest.raises(TransactionFailed): token_network.functions.deprecate().call({"from": A}) tx = token_network.functions.deprecate().call_and_transact( {"from": deprecation_executor}) assert token_network.functions.safety_deprecation_switch().call() is True tx_receipt = web3.eth.getTransactionReceipt(tx) event_abi = contracts_manager.get_event_abi(CONTRACT_TOKEN_NETWORK, EVENT_DEPRECATION_SWITCH) event_data = get_event_data(event_abi, tx_receipt["logs"][0]) assert event_data["args"]["new_value"] # We should not be able to call it again with pytest.raises(TransactionFailed): token_network.functions.deprecate().call({"from": A})
def get_filter_args_for_specific_event_from_channel( token_network_address: Address, channel_identifier: ChannelID, event_name: str, from_block: BlockSpecification = 0, to_block: BlockSpecification = 'latest', ): """ Return the filter params for a specific event of a given channel. """ if not event_name: raise ValueError('Event name must be given') contract_manager = ContractManager(CONTRACTS_PRECOMPILED_PATH) event_abi = contract_manager.get_event_abi(CONTRACT_TOKEN_NETWORK, event_name) # Here the topics for a specific event are created # The first entry of the topics list is the event name, then the first parameter is encoded, # in the case of a token network, the first parameter is always the channel identifier _, event_filter_params = construct_event_filter_params( event_abi=event_abi, contract_address=to_checksum_address(token_network_address), argument_filters={ 'channel_identifier': channel_identifier, }, fromBlock=from_block, toBlock=to_block, ) return event_filter_params
def test_deprecation_immediate_payout(create_account: Callable, custom_token: Contract, service_registry: Contract, web3: Web3) -> None: """When the deprecation switch is on, deposits can be withdrawn immediately.""" # A user makes a deposit A = create_account() minted = service_registry.functions.currentPrice().call() call_and_transact(custom_token.functions.mint(minted), {"from": A}) call_and_transact( custom_token.functions.approve(service_registry.address, minted), {"from": A}) deposit_tx = call_and_transact(service_registry.functions.deposit(minted), {"from": A}) # The user obtains the deposit address deposit_tx_receipt = web3.eth.get_transaction_receipt(deposit_tx) contract_manager = ContractManager( contracts_precompiled_path(version=None)) event_abi = contract_manager.get_event_abi(CONTRACT_SERVICE_REGISTRY, EVENT_REGISTERED_SERVICE) event_data = get_event_data(web3.codec, event_abi, deposit_tx_receipt["logs"][-1]) deposit_address = event_data["args"]["deposit_contract"] # And obtains the Deposit contract instance deposit_abi = contract_manager.get_contract_abi(CONTRACT_DEPOSIT) deposit = web3.eth.contract(abi=deposit_abi, address=deposit_address) # The controller turns on the deprecation switch call_and_transact(service_registry.functions.setDeprecationSwitch(), {"from": DEPLOYER_ADDRESS}) # The user successfully withdraws the deposit call_and_transact(deposit.functions.withdraw(A), {"from": A}) # The user has all the balance it has minted assert minted == custom_token.functions.balanceOf(A).call() # The Deposit contract has destroyed itself assert web3.eth.get_code(deposit.address) == HexBytes("0x")
def get_netting_channel_deposit_events( chain: BlockChainService, token_network_address: Address, netting_channel_identifier: ChannelID, contract_manager: ContractManager, from_block: BlockSpecification = GENESIS_BLOCK_NUMBER, to_block: BlockSpecification = 'latest', ) -> List[Dict]: deposit_event_abi = contract_manager.get_event_abi( CONTRACT_TOKEN_NETWORK, ChannelEvent.DEPOSIT, ) topic_set = construct_event_topic_set( event_abi=deposit_event_abi, arguments={'channel_identifier': netting_channel_identifier}, ) if len(topic_set) == 1 and is_list_like(topic_set[0]): topics = topic_set[0] else: topics = topic_set return get_contract_events( chain, contract_manager.get_contract_abi(CONTRACT_TOKEN_NETWORK), token_network_address, topics, from_block, to_block, )
def get_events( web3: Web3, contract_manager: ContractManager, contract_name: str, event_name: str, contract_address: str = None, from_block: Union[int, str] = 0, to_block: Union[int, str] = 'latest', ) -> List: """Returns events emmitted by a contract for a given event name, within a certain range. Args: web3: A Web3 instance contract_manager: A contract manager contract_name: The name of the contract event_name: The name of the event contract_address: The address of the contract to be filtered, can be `None` from_block: The block to start search events to_block: The block to stop searching for events Returns: All matching events """ filter_params = { 'fromBlock': from_block, 'toBlock': to_block, } if contract_address is not None: assert is_checksum_address(contract_address) filter_params['contract_address'] = contract_address filter = create_event_filter( web3=web3, event_name=event_name, event_abi=contract_manager.get_event_abi(contract_name, event_name), filter_params=filter_params, ) events = filter.get_all_entries() web3.eth.uninstallFilter(filter.filter_id) return events
def contract_manager_meta(contracts_path): manager = ContractManager(contracts_path) abi = manager.get_contract_abi('TokenNetwork') assert isinstance(abi, list) abi = manager.get_event_abi('TokenNetwork', 'ChannelClosed') assert isinstance(abi, dict)
def create_registry_event_topics(contract_manager: ContractManager) -> List: new_network_abi = contract_manager.get_event_abi( CONTRACT_TOKEN_NETWORK_REGISTRY, EVENT_TOKEN_NETWORK_CREATED) return [encode_hex(event_abi_to_log_topic(new_network_abi))]
def test_deprecation_executor( web3: Web3, contracts_manager: ContractManager, deploy_contract: Callable, secret_registry_contract: Contract, custom_token: Contract, channel_participant_deposit_limit: int, token_network_deposit_limit: int, get_accounts: Callable, ) -> None: """ A creates a TokenNetworkRegistry and B registers a TokenNetwork This test is mainly a happy-path scenario. One Ethereum account creates a TokenNetworkRegistry, registers a TokenNetwork. TokenNetworkRegistry emits events that shows the new TokenNetwork. The new TokenNetwork has the original account as the deprecation executor. During these, this test also tries to register more than one TokenNetworks and see a failure. """ (deprecation_executor, B) = get_accounts(2) json_contract = contracts_manager.get_contract( CONTRACT_TOKEN_NETWORK_REGISTRY) token_network_registry = deploy_contract( web3, deprecation_executor, json_contract["abi"], json_contract["bin"], _secret_registry_address=secret_registry_contract.address, _chain_id=int(web3.version.network), _settlement_timeout_min=TEST_SETTLE_TIMEOUT_MIN, _settlement_timeout_max=TEST_SETTLE_TIMEOUT_MAX, _max_token_networks=1, ) # Make sure deployer is deprecation_executor assert token_network_registry.functions.deprecation_executor().call( ) == deprecation_executor assert token_network_registry.functions.token_network_created().call() == 0 # We can only deploy one TokenNetwork contract # It can be deployed by anyone tx_hash = token_network_registry.functions.createERC20TokenNetwork( custom_token.address, channel_participant_deposit_limit, token_network_deposit_limit).call_and_transact({"from": B}) assert token_network_registry.functions.token_network_created().call() == 1 # No other TokenNetworks can be deployed now with pytest.raises(TransactionFailed): token_network_registry.functions.createERC20TokenNetwork( custom_token.address, channel_participant_deposit_limit, token_network_deposit_limit).call({"from": B}) with pytest.raises(TransactionFailed): token_network_registry.functions.createERC20TokenNetwork( custom_token.address, channel_participant_deposit_limit, token_network_deposit_limit).call({"from": deprecation_executor}) tx_receipt = web3.eth.getTransactionReceipt(tx_hash) event_abi = contracts_manager.get_event_abi( CONTRACT_TOKEN_NETWORK_REGISTRY, EVENT_TOKEN_NETWORK_CREATED) event_data = get_event_data(event_abi, tx_receipt["logs"][0]) token_network_address = event_data["args"]["token_network_address"] token_network = web3.eth.contract( abi=contracts_manager.get_contract_abi(CONTRACT_TOKEN_NETWORK), address=token_network_address, ) assert token_network.functions.deprecation_executor().call( ) == deprecation_executor
class TokenNetworkRegistry: def __init__( self, jsonrpc_client, registry_address, ): if not is_binary_address(registry_address): raise InvalidAddress( 'Expected binary address format for token network registry') check_address_has_code(jsonrpc_client, registry_address, CONTRACT_TOKEN_NETWORK_REGISTRY) self.contract_manager = ContractManager(CONTRACTS_PRECOMPILED_PATH) proxy = jsonrpc_client.new_contract_proxy( self.contract_manager.get_contract_abi( CONTRACT_TOKEN_NETWORK_REGISTRY), to_normalized_address(registry_address), ) try: is_valid_version = compare_versions( proxy.contract.functions.contract_version().call(), EXPECTED_CONTRACTS_VERSION, ) except BadFunctionCallOutput: raise AddressWrongContract('') if not is_valid_version: raise ContractVersionMismatch( 'Incompatible ABI for TokenNetworkRegistry') self.address = registry_address self.proxy = proxy self.client = jsonrpc_client self.node_address = privatekey_to_address(self.client.privkey) def get_token_network( self, token_address: typing.TokenAddress) -> Optional[typing.Address]: """ Return the token network address for the given token or None if there is no correspoding address. """ if not isinstance(token_address, typing.T_TargetAddress): raise ValueError('token_address must be an address') address = self.proxy.contract.functions.token_to_token_networks( to_checksum_address(token_address), ).call() address = to_canonical_address(address) if is_same_address(address, NULL_ADDRESS): return None return address def add_token(self, token_address: typing.TokenAddress): if not is_binary_address(token_address): raise InvalidAddress('Expected binary address format for token') log_details = { 'node': pex(self.node_address), 'token_address': pex(token_address), 'registry_address': pex(self.address), } log.debug('createERC20TokenNetwork called', **log_details) transaction_hash = self.proxy.transact( 'createERC20TokenNetwork', token_address, ) self.client.poll(transaction_hash) receipt_or_none = check_transaction_threw(self.client, transaction_hash) if receipt_or_none: if self.get_token_network(token_address): msg = 'Token already registered' log.info(f'createERC20TokenNetwork failed, {msg}', **log_details) raise RaidenRecoverableError(msg) log.critical(f'createERC20TokenNetwork failed', **log_details) raise TransactionThrew('createERC20TokenNetwork', receipt_or_none) token_network_address = self.get_token_network(token_address) if token_network_address is None: log.critical( 'createERC20TokenNetwork failed and check_transaction_threw didnt detect it', **log_details, ) raise RuntimeError('token_to_token_networks failed') log.info( 'createERC20TokenNetwork successful', token_network_address=pex(token_network_address), **log_details, ) return token_network_address def tokenadded_filter( self, from_block: typing.BlockSpecification = 0, to_block: typing.BlockSpecification = 'latest', ) -> StatelessFilter: event_abi = self.contract_manager.get_event_abi( CONTRACT_TOKEN_NETWORK_REGISTRY, EVENT_TOKEN_NETWORK_CREATED, ) topics = [encode_hex(event_abi_to_log_topic(event_abi))] registry_address_bin = self.proxy.contract_address return self.client.new_filter( registry_address_bin, topics=topics, from_block=from_block, to_block=to_block, ) def filter_token_added_events(self): filter_ = self.proxy.contract.events.TokenNetworkCreated.createFilter( fromBlock=0) events = filter_.get_all_entries() if filter_.filter_id: self.proxy.contract.web3.eth.uninstallFilter(filter_.filter_id) return events def settlement_timeout_min(self) -> int: """ Returns the minimal settlement timeout for the token network registry. """ return self.proxy.contract.functions.settlement_timeout_min().call() def settlement_timeout_max(self) -> int: """ Returns the maximal settlement timeout for the token network registry. """ return self.proxy.contract.functions.settlement_timeout_max().call()
def create_registry_event_topics(contract_manager: ContractManager, contract_name: str, event_name: str) -> List: """Returns network ABI""" new_network_abi = contract_manager.get_event_abi(contract_name, event_name) return [encode_hex(event_abi_to_log_topic(new_network_abi))]
class SecretRegistry: def __init__( self, jsonrpc_client, secret_registry_address, ): if not is_binary_address(secret_registry_address): raise InvalidAddress( 'Expected binary address format for secret registry') self.contract_manager = ContractManager(CONTRACTS_PRECOMPILED_PATH) check_address_has_code(jsonrpc_client, secret_registry_address, CONTRACT_SECRET_REGISTRY) proxy = jsonrpc_client.new_contract_proxy( self.contract_manager.get_contract_abi(CONTRACT_SECRET_REGISTRY), to_normalized_address(secret_registry_address), ) try: if not compare_versions( proxy.contract.functions.contract_version().call(), EXPECTED_CONTRACTS_VERSION, ): raise ContractVersionMismatch( 'Incompatible ABI for SecretRegistry') except BadFunctionCallOutput: raise AddressWrongContract('') self.address = secret_registry_address self.proxy = proxy self.client = jsonrpc_client self.node_address = privatekey_to_address(self.client.privkey) self.open_secret_transactions = dict() def register_secret(self, secret: typing.Secret): self.register_secret_batch([secret]) def register_secret_batch(self, secrets: List[typing.Secret]): secrets_to_register = list() secrethashes_to_register = list() secrethashes_not_sent = list() secret_registry_transaction = AsyncResult() for secret in secrets: secrethash = sha3(secret) secrethash_hex = encode_hex(secrethash) is_register_needed = (not self.check_registered(secrethash) and secret not in self.open_secret_transactions) if is_register_needed: secrets_to_register.append(secret) secrethashes_to_register.append(secrethash_hex) self.open_secret_transactions[ secret] = secret_registry_transaction else: secrethashes_not_sent.append(secrethash_hex) log_details = { 'node': pex(self.node_address), 'contract': pex(self.address), 'secrethashes': secrethashes_to_register, 'secrethashes_not_sent': secrethashes_not_sent, } if not secrets_to_register: log.debug('registerSecretBatch skipped', **log_details) log.debug('registerSecretBatch called', **log_details) try: transaction_hash = self._register_secret_batch(secrets_to_register) except Exception as e: log.critical('registerSecretBatch failed', **log_details) secret_registry_transaction.set_exception(e) raise else: log.info('registerSecretBatch successful', **log_details) secret_registry_transaction.set(transaction_hash) finally: for secret in secrets_to_register: self.open_secret_transactions.pop(secret, None) def _register_secret_batch(self, secrets): transaction_hash = self.proxy.transact('registerSecretBatch', secrets) self.client.poll(transaction_hash) receipt_or_none = check_transaction_threw(self.client, transaction_hash) if receipt_or_none: raise TransactionThrew('registerSecretBatch', receipt_or_none) return transaction_hash def get_register_block_for_secrethash(self, secrethash: typing.Keccak256) -> int: return self.proxy.contract.functions.getSecretRevealBlockHeight( secrethash).call() def check_registered(self, secrethash: typing.Keccak256) -> bool: return self.get_register_block_for_secrethash(secrethash) > 0 def secret_registered_filter( self, from_block: typing.BlockSpecification = 0, to_block: typing.BlockSpecification = 'latest', ) -> StatelessFilter: event_abi = self.contract_manager.get_event_abi( CONTRACT_SECRET_REGISTRY, EVENT_SECRET_REVEALED, ) topics = [encode_hex(event_abi_to_log_topic(event_abi))] return self.client.new_filter( self.address, topics=topics, from_block=from_block, to_block=to_block, )