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,
    )
예제 #5
0
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
예제 #6
0
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
예제 #7
0
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
예제 #8
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
예제 #9
0
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
예제 #10
0
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
예제 #11
0
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,
    )
예제 #12
0
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,
    )
예제 #13
0
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})
예제 #15
0
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
예제 #16
0
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")
예제 #17
0
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,
    )
예제 #18
0
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)
예제 #20
0
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
예제 #22
0
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()
예제 #23
0
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))]
예제 #24
0
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,
        )