def secret_registry_batch_happy_path( web3: Web3, secret_registry_proxy: SecretRegistry) -> None: secrets = [make_secret() for i in range(4)] secrethashes = [sha256_secrethash(secret) for secret in secrets] secret_registered_filter = secret_registry_proxy.secret_registered_filter( GENESIS_BLOCK_NUMBER) secret_registry_proxy.register_secret_batch(secrets=secrets) logs = [ secret_registry_proxy.proxy.decode_event(log) for log in secret_registered_filter.get_new_entries(web3.eth.blockNumber) ] for secrethash in secrethashes: secret_registered = must_have_event(logs, { "event": "SecretRevealed", "args": { "secrethash": secrethash } }) assert secret_registered, "All secrets from the batch must be registered" block = secret_registry_proxy.get_secret_registration_block_by_secrethash( secrethash=secrethash, block_identifier="latest") msg = "Block number reported by the proxy and the event must match" assert block == secret_registered["blockNumber"], msg
def secret_registry_batch_happy_path( proxy_manager: ProxyManager, secret_registry_proxy: SecretRegistry) -> None: secrets = [make_secret() for i in range(4)] secrethashes = [sha256_secrethash(secret) for secret in secrets] secret_registry_proxy.register_secret_batch(secrets=secrets) logs = get_secret_registry_events( proxy_manager=proxy_manager, secret_registry_address=secret_registry_proxy.address, contract_manager=secret_registry_proxy.contract_manager, ) for secrethash in secrethashes: secret_registered = must_have_event(logs, { "event": "SecretRevealed", "args": { "secrethash": secrethash } }) assert secret_registered, "All secrets from the batch must be registered" block = secret_registry_proxy.get_secret_registration_block_by_secrethash( secrethash=secrethash, block_identifier="latest") msg = "Block number reported by the proxy and the event must match" assert block == secret_registered["block_number"], msg
def secret_registry_batch_happy_path( proxy_manager: ProxyManager, secret_registry_proxy: SecretRegistry ) -> None: secrets = [make_secret() for i in range(4)] secrethashes = [sha256_secrethash(secret) for secret in secrets] transaction_hashes = secret_registry_proxy.register_secret_batch(secrets=secrets) for tx_hash in transaction_hashes: assert is_tx_hash_bytes(tx_hash) 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), ) for secrethash in secrethashes: secret_registered = must_have_event( logs, {"event": "SecretRevealed", "args": {"secrethash": secrethash}} ) assert secret_registered, "All secrets from the batch must be registered" block = secret_registry_proxy.get_secret_registration_block_by_secrethash( secrethash=secrethash, block_identifier=BLOCK_ID_LATEST ) msg = "Block number reported by the proxy and the event must match" assert block == secret_registered["block_number"], msg
def test_register_secret_happy_path(secret_registry_proxy: SecretRegistry, contract_manager): """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 = keccak(secret) secret_unregistered = make_secret() secrethash_unregistered = keccak(secret_unregistered) secret_registered_filter = secret_registry_proxy.secret_registered_filter() 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" chain = BlockChainService(jsonrpc_client=secret_registry_proxy.client, contract_manager=contract_manager) chain.wait_until_block(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_all_entries() ] 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 check_ethereum_confirmed_block_is_not_pruned( jsonrpc_client: JSONRPCClient, secret_registry: SecretRegistry, confirmation_blocks: int ) -> None: """Checks the Ethereum client is not pruning data too aggressively, because in some circunstances it is necessary for a node to fetch additional data from the smart contract. """ unconfirmed_block_number = jsonrpc_client.block_number() # This is a small error margin. It is possible during normal operation for: # # - AlarmTask sees a new block and calls RaidenService._callback_new_block # - The service gets the current latest block number and computes the # confirmed block number. # - The service fetches every filter, this can take a while. # - While the above is happening, it is possible for a `few_blocks` to be # mined. # - The decode function is called, and tries to access what it thinks is # the latest_confirmed_block, but it is in reality `few_blocks` older. # # This value bellow is the expected drift, that allows the decode function # mentioned above to work properly. maximum_delay_to_process_a_block = 2 minimum_available_history = confirmation_blocks + maximum_delay_to_process_a_block target_confirmed_block = unconfirmed_block_number - minimum_available_history try: # Using the secret registry is arbitrary, any proxy with an `eth_call` # would work here. secret_registry.get_secret_registration_block_by_secrethash( EMPTY_SECRETHASH, block_identifier=target_confirmed_block ) except ValueError: # If this exception is raised the Ethereum node is too aggressive with # the block pruning. click.secho( f"The ethereum client does not have the necessary data available. " f"The client can not operate because the prunning strategy is too " f"agressive. Please make sure that at very minimum " f"{minimum_available_history} blocks of history are available.", fg="red", ) sys.exit(1)
def secret_registry(self, address: Address) -> SecretRegistry: if not is_binary_address(address): raise ValueError("address must be a valid address") with self._secret_registry_creation_lock: if address not in self.address_to_secret_registry: self.address_to_secret_registry[address] = SecretRegistry( jsonrpc_client=self.client, secret_registry_address=address, contract_manager=self.contract_manager, ) return self.address_to_secret_registry[address]
def add_secret_registry_listener( self, secret_registry_proxy: SecretRegistry, contract_manager: ContractManager, from_block: typing.BlockSpecification = 'latest', ): secret_registry_filter = secret_registry_proxy.secret_registered_filter( from_block=from_block, ) secret_registry_address = secret_registry_proxy.address self.add_event_listener( 'SecretRegistry {}'.format(pex(secret_registry_address)), secret_registry_filter, contract_manager.get_contract_abi(CONTRACT_SECRET_REGISTRY), )
def secret_registry_proxy(deploy_client, secret_registry_address, contract_manager): """This uses the available SecretRegistry JSONRPCClient proxy to instantiate a Raiden proxy. The JSONRPCClient proxy just exposes the functions from the smart contract as methods in a generate python object, the Raiden proxy uses it to provider alternative interfaces *and* most importantly to do additional error checking (reason for transaction failure, gas usage, etc.). """ return SecretRegistry( jsonrpc_client=deploy_client, secret_registry_address=to_canonical_address(secret_registry_address), contract_manager=contract_manager, )
def add_secret_registry_listener( self, secret_registry_proxy: SecretRegistry, contract_manager: ContractManager, from_block: BlockNumber, ) -> None: secret_registry_filter = secret_registry_proxy.secret_registered_filter( from_block=from_block ) secret_registry_address = secret_registry_proxy.address self.add_event_listener( "SecretRegistry {}".format(to_checksum_address(secret_registry_address)), secret_registry_filter, contract_manager.get_contract_abi(CONTRACT_SECRET_REGISTRY), )
def secret_registry_proxy_fixture( deploy_client: JSONRPCClient, secret_registry_address: SecretRegistryAddress, contract_manager: ContractManager, ) -> SecretRegistry: """This uses the available SecretRegistry JSONRPCClient proxy to instantiate a Raiden proxy. The JSONRPCClient proxy just exposes the functions from the smart contract as methods in a generate python object, the Raiden proxy uses it to provider alternative interfaces *and* most importantly to do additional error checking (reason for transaction failure, gas usage, etc.). """ return SecretRegistry( jsonrpc_client=deploy_client, secret_registry_address=secret_registry_address, contract_manager=contract_manager, block_identifier=BLOCK_ID_LATEST, )
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_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!"