示例#1
0
def wait_for_sync_etherscan(
    rpc_client: JSONRPCClient, url: str, tolerance: int, sleep: float
) -> None:
    local_block = rpc_client.block_number()
    etherscan_block = etherscan_query_with_retries(url, sleep)
    syncing_str = "\rSyncing ... Current: {} / Target: ~{}"

    if local_block >= etherscan_block - tolerance:
        return

    print("Waiting for the ethereum node to synchronize. [Use ^C to exit]")
    print(syncing_str.format(local_block, etherscan_block), end="")

    for i in count():
        sys.stdout.flush()
        gevent.sleep(sleep)
        local_block = rpc_client.block_number()

        # update the oracle block number sparsely to not spam the server
        if local_block >= etherscan_block or i % 50 == 0:
            etherscan_block = etherscan_query_with_retries(url, sleep)

            if local_block >= etherscan_block - tolerance:
                return

        print(syncing_str.format(local_block, etherscan_block), end="")

    # add a newline so that the next print will start have it's own line
    print("")
示例#2
0
def blocks_to_sync(rpc_client: JSONRPCClient) -> BlockTimeout:
    sync_status = rpc_client.web3.eth.syncing

    if sync_status is False:
        return BlockTimeout(0)

    assert isinstance(sync_status, Mapping), MYPY_ANNOTATION
    highest_block = sync_status["highestBlock"]

    current_block = rpc_client.block_number()
    return BlockTimeout(highest_block - current_block)
示例#3
0
def wait_for_sync_blockcypher(
    rpc_client: JSONRPCClient, tolerance: BlockTimeout, sleep: float
) -> None:
    syncing_str = "\rSyncing ... Current: {} / Target: ~{}"
    error_str = "Could not get blockchain information from blockcypher. Ignoring."

    local_block = rpc_client.block_number()
    blockcypher_block = blockcypher_query_with_retries(sleep)

    if blockcypher_block is None:
        print(error_str)
        return

    if local_block >= blockcypher_block - tolerance:
        return

    print("Waiting for the ethereum node to synchronize. [Use ^C to exit]")
    print(syncing_str.format(local_block, blockcypher_block), end="")

    for i in count():
        sys.stdout.flush()
        gevent.sleep(sleep)
        local_block = rpc_client.block_number()

        # update the oracle block number sparsely to not spam the server
        if local_block >= blockcypher_block or i % 50 == 0:
            blockcypher_block = blockcypher_query_with_retries(sleep)

            if blockcypher_block is None:
                print(error_str)
                return

            if local_block >= blockcypher_block - tolerance:
                return

        print(syncing_str.format(local_block, blockcypher_block), end="")

    # add a newline so that the next print will start have it's own line
    print("")
示例#4
0
    def is_synced(rpc_client: JSONRPCClient) -> bool:
        sync_status = rpc_client.web3.eth.syncing

        # the node is synchronized
        if sync_status is False:
            return True

        assert isinstance(sync_status, Mapping), MYPY_ANNOTATION
        highest_block = sync_status["highestBlock"]

        current_block = rpc_client.block_number()
        if highest_block - current_block > tolerance:
            return False

        return True
示例#5
0
def test_register_secret_batch_with_pruned_block(
    proxy_manager: ProxyManager,
    secret_registry_proxy: SecretRegistry,
    web3: Web3,
    private_keys: List[PrivateKey],
) -> None:
    """Test secret registration with a pruned given block."""
    rpc_client = JSONRPCClient(web3, private_keys[1])

    # Now wait until this block becomes pruned
    pruned_number = rpc_client.block_number()
    rpc_client.wait_until_block(
        target_block_number=BlockNumber(pruned_number + STATE_PRUNING_AFTER_BLOCKS)
    )
    secret_registry_batch_happy_path(proxy_manager, secret_registry_proxy)
示例#6
0
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 estimate_blocktime(rpc_client: JSONRPCClient, oldest: int = 256) -> float:
    """Calculate a blocktime estimate based on some past blocks.
    Args:
        oldest: delta in block numbers to go back.
    Return:
        average block time in seconds
    """
    last_block_number = rpc_client.block_number()
    # around genesis block there is nothing to estimate
    if last_block_number < 1:
        return 15
    # if there are less than `oldest` blocks available, start at block 1
    if last_block_number < oldest:
        interval = (last_block_number - 1) or 1
    else:
        interval = last_block_number - oldest
    assert interval > 0
    last_timestamp = rpc_client.get_block(last_block_number)["timestamp"]
    first_timestamp = rpc_client.get_block(last_block_number -
                                           interval)["timestamp"]
    delta = last_timestamp - first_timestamp
    return delta / interval
示例#8
0
def main(output_directory, network_id, eth_rpc_endpoint, contracts_version):
    web3 = Web3(HTTPProvider(rpc_normalized_endpoint(eth_rpc_endpoint)))

    try:
        check_ethereum_client_is_supported(web3)
    except ConnectionError:
        click.secho(
            f"Couldn't connect to the ethereum node, double check it is running "
            f"on {eth_rpc_endpoint}, this option can be changed with "
            f"{ETH_RPC_CONFIG_OPTION}",
            fg="red",
        )
        return

    check_ethereum_network_id(network_id, web3)

    # This script does not send any transactions, the privatekey is generate
    # just because it is a dependency for JSONRPCClient.
    unecessary_privatekey = factories.make_privatekey_bin()
    rpc_client = JSONRPCClient(web3=web3, privkey=unecessary_privatekey)
    check_synced(rpc_client)

    deployment_data = get_contracts_deployment_info(chain_id=network_id, version=contracts_version)

    if not deployment_data:
        raise RuntimeError(
            f"There is no deployment data available for contracts-version {contracts_version}."
        )

    network_name = ID_TO_CHAINNAME.get(network_id)
    if network_name is None:
        raise RuntimeError(f"Network with id {network_id} is not known.")

    contracts = deployment_data["contracts"]
    token_network_registry_deployed_at = BlockNumber(
        contracts[CONTRACT_TOKEN_NETWORK_REGISTRY]["block_number"]
    )
    token_network_registry_address = TokenNetworkRegistryAddress(
        to_canonical_address(contracts[CONTRACT_TOKEN_NETWORK_REGISTRY]["address"])
    )
    secret_registry_address = SecretRegistryAddress(
        to_canonical_address(contracts[CONTRACT_SECRET_REGISTRY]["address"])
    )

    contracts_path = contracts_precompiled_path(contracts_version)
    contract_manager = ContractManager(contracts_path)

    current_block_number = rpc_client.block_number()
    confirmed_block = rpc_client.get_block(
        BlockNumber(current_block_number - DEFAULT_NUMBER_OF_BLOCK_CONFIRMATIONS)
    )

    all_events_for_a_deployment = fetch_all_events_for_a_deployment(
        contract_manager=contract_manager,
        web3=web3,
        token_network_registry_address=token_network_registry_address,
        secret_registry_address=secret_registry_address,
        start_block=token_network_registry_deployed_at,
        target_block=confirmed_block["number"],
    )

    target_block_formatted = to_hex(confirmed_block["hash"])
    file_path = os.path.join(
        output_directory,
        (
            f"{network_name}-"
            f"{to_checksum_address(token_network_registry_address)}-"
            f"{target_block_formatted}.json.gz"
        ),
    )

    block_data = {
        "gasLimit": confirmed_block["gasLimit"],
        "gasUsed": confirmed_block["gasUsed"],
        "hash": to_hex(confirmed_block["hash"]),
        "number": confirmed_block["number"],
    }
    block_data_formatted = simplejson.dumps(block_data).encode("utf8")

    with gzip.open(file_path, mode="wb") as handler:
        # Format is `jsonlines` (http://jsonlines.org/), this is used because we
        # don't have to keep all the events in memory to start encoding the data.
        for event in all_events_for_a_deployment:
            format_event_for_serialization(event)
            data = simplejson.dumps(event).encode("utf8")
            handler.write(data + b"\n")

        # Write the block details at the end
        handler.write(block_data_formatted + b"\n")
示例#9
0
def test_payment_channel_proxy_basics(
    token_network_registry_address: TokenNetworkRegistryAddress,
    token_network_proxy: TokenNetwork,
    token_proxy: Token,
    chain_id: ChainID,
    private_keys: List[PrivateKey],
    web3: Web3,
    contract_manager: ContractManager,
    reveal_timeout: BlockTimeout,
) -> None:
    token_network_address = token_network_proxy.address
    partner = privatekey_to_address(private_keys[0])

    rpc_client = JSONRPCClient(web3, private_keys[1])
    proxy_manager = ProxyManager(
        rpc_client=rpc_client,
        contract_manager=contract_manager,
        metadata=ProxyManagerMetadata(
            token_network_registry_deployed_at=GENESIS_BLOCK_NUMBER,
            filters_start_at=GENESIS_BLOCK_NUMBER,
        ),
    )
    token_network_proxy = proxy_manager.token_network(
        address=token_network_address, block_identifier=BLOCK_ID_LATEST
    )
    start_block = web3.eth.blockNumber

    channel_details = token_network_proxy.new_netting_channel(
        partner=partner,
        settle_timeout=TEST_SETTLE_TIMEOUT_MIN,
        given_block_identifier=BLOCK_ID_LATEST,
    )
    channel_identifier = channel_details.channel_identifier
    assert channel_identifier is not None

    channel_state = NettingChannelState(
        canonical_identifier=CanonicalIdentifier(
            chain_identifier=chain_id,
            token_network_address=token_network_address,
            channel_identifier=channel_identifier,
        ),
        token_address=token_network_proxy.token_address(),
        token_network_registry_address=token_network_registry_address,
        reveal_timeout=reveal_timeout,
        settle_timeout=BlockTimeout(TEST_SETTLE_TIMEOUT_MIN),
        fee_schedule=FeeScheduleState(),
        our_state=NettingChannelEndState(
            address=token_network_proxy.client.address, contract_balance=Balance(0)
        ),
        partner_state=NettingChannelEndState(address=partner, contract_balance=Balance(0)),
        open_transaction=SuccessfulTransactionState(finished_block_number=BlockNumber(0)),
    )
    channel_proxy_1 = proxy_manager.payment_channel(
        channel_state=channel_state, block_identifier=BLOCK_ID_LATEST
    )

    assert channel_proxy_1.channel_identifier == channel_identifier
    assert channel_proxy_1.opened(BLOCK_ID_LATEST) is True

    # Test deposit
    initial_token_balance = 100
    token_proxy.transfer(rpc_client.address, TokenAmount(initial_token_balance))
    assert token_proxy.balance_of(rpc_client.address) == initial_token_balance
    assert token_proxy.balance_of(partner) == 0
    channel_proxy_1.approve_and_set_total_deposit(
        total_deposit=TokenAmount(10), block_identifier=BLOCK_ID_LATEST
    )

    # ChannelOpened, ChannelNewDeposit
    channel_events = get_all_netting_channel_events(
        proxy_manager=proxy_manager,
        token_network_address=token_network_address,
        netting_channel_identifier=channel_proxy_1.channel_identifier,
        contract_manager=contract_manager,
        from_block=start_block,
        to_block=web3.eth.blockNumber,
    )

    assert len(channel_events) == 2

    block_before_close = web3.eth.blockNumber
    empty_balance_proof = BalanceProof(
        channel_identifier=channel_proxy_1.channel_identifier,
        token_network_address=token_network_address,
        balance_hash=EMPTY_BALANCE_HASH,
        nonce=0,
        chain_id=chain_id,
        transferred_amount=TokenAmount(0),
    )
    closing_data = (
        empty_balance_proof.serialize_bin(msg_type=MessageTypeId.BALANCE_PROOF) + EMPTY_SIGNATURE
    )
    channel_proxy_1.close(
        nonce=Nonce(0),
        balance_hash=EMPTY_BALANCE_HASH,
        additional_hash=EMPTY_MESSAGE_HASH,
        non_closing_signature=EMPTY_SIGNATURE,
        closing_signature=LocalSigner(private_keys[1]).sign(data=closing_data),
        block_identifier=BLOCK_ID_LATEST,
    )
    assert channel_proxy_1.closed(BLOCK_ID_LATEST) is True
    # ChannelOpened, ChannelNewDeposit, ChannelClosed
    channel_events = get_all_netting_channel_events(
        proxy_manager=proxy_manager,
        token_network_address=token_network_address,
        netting_channel_identifier=channel_proxy_1.channel_identifier,
        contract_manager=contract_manager,
        from_block=start_block,
        to_block=web3.eth.blockNumber,
    )
    assert len(channel_events) == 3

    # check the settlement timeouts again
    assert channel_proxy_1.settle_timeout() == TEST_SETTLE_TIMEOUT_MIN

    # update transfer -- we need to wait on +1 since we use the latest block on parity for
    # estimate gas and at the time the latest block is the settle timeout block.
    # More info: https://github.com/raiden-network/raiden/pull/3699#discussion_r270477227
    rpc_client.wait_until_block(
        target_block_number=BlockNumber(rpc_client.block_number() + TEST_SETTLE_TIMEOUT_MIN + 1)
    )

    transaction_hash = channel_proxy_1.settle(
        transferred_amount=TokenAmount(0),
        locked_amount=LockedAmount(0),
        locksroot=LOCKSROOT_OF_NO_LOCKS,
        partner_transferred_amount=TokenAmount(0),
        partner_locked_amount=LockedAmount(0),
        partner_locksroot=LOCKSROOT_OF_NO_LOCKS,
        block_identifier=BLOCK_ID_LATEST,
    )
    assert is_tx_hash_bytes(transaction_hash)
    assert channel_proxy_1.settled(BLOCK_ID_LATEST) is True
    # ChannelOpened, ChannelNewDeposit, ChannelClosed, ChannelSettled
    channel_events = get_all_netting_channel_events(
        proxy_manager=proxy_manager,
        token_network_address=token_network_address,
        netting_channel_identifier=channel_proxy_1.channel_identifier,
        contract_manager=contract_manager,
        from_block=start_block,
        to_block=web3.eth.blockNumber,
    )
    assert len(channel_events) == 4

    channel_details = token_network_proxy.new_netting_channel(
        partner=partner,
        settle_timeout=TEST_SETTLE_TIMEOUT_MIN,
        given_block_identifier=BLOCK_ID_LATEST,
    )
    new_channel_identifier = channel_details.channel_identifier
    assert new_channel_identifier is not None

    channel_state = NettingChannelState(
        canonical_identifier=CanonicalIdentifier(
            chain_identifier=chain_id,
            token_network_address=token_network_address,
            channel_identifier=new_channel_identifier,
        ),
        token_address=token_network_proxy.token_address(),
        token_network_registry_address=token_network_registry_address,
        reveal_timeout=reveal_timeout,
        settle_timeout=BlockTimeout(TEST_SETTLE_TIMEOUT_MIN),
        fee_schedule=FeeScheduleState(),
        our_state=NettingChannelEndState(
            address=token_network_proxy.client.address, contract_balance=Balance(0)
        ),
        partner_state=NettingChannelEndState(address=partner, contract_balance=Balance(0)),
        open_transaction=SuccessfulTransactionState(finished_block_number=BlockNumber(0)),
    )
    channel_proxy_2 = proxy_manager.payment_channel(
        channel_state=channel_state, block_identifier=BLOCK_ID_LATEST
    )

    assert channel_proxy_2.channel_identifier == new_channel_identifier
    assert channel_proxy_2.opened(BLOCK_ID_LATEST) is True

    msg = "The channel was already closed, the second call must fail"
    with pytest.raises(RaidenRecoverableError):
        channel_proxy_1.close(
            nonce=Nonce(0),
            balance_hash=EMPTY_BALANCE_HASH,
            additional_hash=EMPTY_MESSAGE_HASH,
            non_closing_signature=EMPTY_SIGNATURE,
            closing_signature=LocalSigner(private_keys[1]).sign(data=closing_data),
            block_identifier=block_before_close,
        )
        pytest.fail(msg)

    msg = "The channel is not open at latest, this must raise"
    with pytest.raises(RaidenUnrecoverableError):
        channel_proxy_1.close(
            nonce=Nonce(0),
            balance_hash=EMPTY_BALANCE_HASH,
            additional_hash=EMPTY_MESSAGE_HASH,
            non_closing_signature=EMPTY_SIGNATURE,
            closing_signature=LocalSigner(private_keys[1]).sign(data=closing_data),
            block_identifier=BLOCK_ID_LATEST,
        )
        pytest.fail(msg)

    msg = (
        "The channel was not opened at the provided block (latest). "
        "This call should never have been attempted."
    )
    with pytest.raises(BrokenPreconditionError):
        channel_proxy_1.approve_and_set_total_deposit(
            total_deposit=TokenAmount(20), block_identifier=BLOCK_ID_LATEST
        )
        pytest.fail(msg)
示例#10
0
def test_payment_channel_proxy_basics(
    token_network_proxy, token_proxy, chain_id, private_keys, web3, contract_manager
):
    token_network_address = token_network_proxy.address
    partner = privatekey_to_address(private_keys[0])

    client = JSONRPCClient(web3, private_keys[1])
    chain = BlockChainService(jsonrpc_client=client, contract_manager=contract_manager)
    token_network_proxy = chain.token_network(address=token_network_address)
    start_block = web3.eth.blockNumber

    channel_identifier = token_network_proxy.new_netting_channel(
        partner=partner, settle_timeout=TEST_SETTLE_TIMEOUT_MIN, given_block_identifier="latest"
    )
    assert channel_identifier is not None

    channel_proxy_1 = chain.payment_channel(
        canonical_identifier=CanonicalIdentifier(
            chain_identifier=chain_id,
            token_network_address=token_network_address,
            channel_identifier=channel_identifier,
        )
    )

    channel_filter = channel_proxy_1.all_events_filter(from_block=start_block, to_block="latest")

    assert channel_proxy_1.channel_identifier == channel_identifier
    assert channel_proxy_1.opened("latest") is True

    # Test deposit
    initial_token_balance = 100
    token_proxy.transfer(client.address, initial_token_balance)
    assert token_proxy.balance_of(client.address) == initial_token_balance
    assert token_proxy.balance_of(partner) == 0
    channel_proxy_1.set_total_deposit(total_deposit=10, block_identifier="latest")

    assert len(channel_filter.get_all_entries()) == 2  # ChannelOpened, ChannelNewDeposit
    block_before_close = web3.eth.blockNumber

    channel_proxy_1.close(
        nonce=0,
        balance_hash=EMPTY_HASH,
        additional_hash=EMPTY_HASH,
        signature=EMPTY_SIGNATURE,
        block_identifier="latest",
    )
    assert channel_proxy_1.closed("latest") is True
    # ChannelOpened, ChannelNewDeposit, ChannelClosed
    assert len(channel_filter.get_all_entries()) == 3

    # check the settlement timeouts again
    assert channel_proxy_1.settle_timeout() == TEST_SETTLE_TIMEOUT_MIN

    # update transfer -- we need to wait on +1 since we use the latest block on parity for
    # estimate gas and at the time the latest block is the settle timeout block.
    # More info: https://github.com/raiden-network/raiden/pull/3699#discussion_r270477227
    chain.wait_until_block(target_block_number=client.block_number() + TEST_SETTLE_TIMEOUT_MIN + 1)

    channel_proxy_1.settle(
        transferred_amount=0,
        locked_amount=0,
        locksroot=EMPTY_HASH,
        partner_transferred_amount=0,
        partner_locked_amount=0,
        partner_locksroot=EMPTY_HASH,
        block_identifier="latest",
    )
    assert channel_proxy_1.settled("latest") is True
    # ChannelOpened, ChannelNewDeposit, ChannelClosed, ChannelSettled
    assert len(channel_filter.get_all_entries()) == 4

    new_channel_identifier = token_network_proxy.new_netting_channel(
        partner=partner, settle_timeout=TEST_SETTLE_TIMEOUT_MIN, given_block_identifier="latest"
    )
    assert new_channel_identifier is not None

    channel_proxy_2 = chain.payment_channel(
        canonical_identifier=CanonicalIdentifier(
            chain_identifier=chain_id,
            token_network_address=token_network_address,
            channel_identifier=new_channel_identifier,
        )
    )

    assert channel_proxy_2.channel_identifier == new_channel_identifier
    assert channel_proxy_2.opened("latest") is True

    msg = "The channel was already closed, the second call must fail"
    with pytest.raises(RaidenRecoverableError, message=msg):
        channel_proxy_1.close(
            nonce=0,
            balance_hash=EMPTY_HASH,
            additional_hash=EMPTY_HASH,
            signature=EMPTY_SIGNATURE,
            block_identifier=block_before_close,
        )

    msg = "The channel is not open at latest, this must raise"
    with pytest.raises(RaidenUnrecoverableError, message=msg):
        channel_proxy_1.close(
            nonce=0,
            balance_hash=EMPTY_HASH,
            additional_hash=EMPTY_HASH,
            signature=EMPTY_SIGNATURE,
            block_identifier="latest",
        )

    msg = "The channel is closed, set total deposit must fail"
    with pytest.raises(ChannelOutdatedError, message=msg):
        channel_proxy_1.set_total_deposit(total_deposit=20, block_identifier="latest")
示例#11
0
def test_token_network_proxy(token_network_proxy, private_keys, token_proxy,
                             chain_id, web3, contract_manager):
    assert token_network_proxy.settlement_timeout_min(
    ) == TEST_SETTLE_TIMEOUT_MIN
    assert token_network_proxy.settlement_timeout_max(
    ) == TEST_SETTLE_TIMEOUT_MAX

    token_network_address = to_canonical_address(
        token_network_proxy.proxy.contract.address)

    c1_signer = LocalSigner(private_keys[1])
    c1_client = JSONRPCClient(web3, private_keys[1])
    c1_proxy_manager = ProxyManager(
        rpc_client=c1_client,
        contract_manager=contract_manager,
        metadata=ProxyManagerMetadata(
            token_network_registry_deployed_at=GENESIS_BLOCK_NUMBER,
            filters_start_at=GENESIS_BLOCK_NUMBER,
        ),
    )
    c2_client = JSONRPCClient(web3, private_keys[2])
    c2_proxy_manager = ProxyManager(
        rpc_client=c2_client,
        contract_manager=contract_manager,
        metadata=ProxyManagerMetadata(
            token_network_registry_deployed_at=GENESIS_BLOCK_NUMBER,
            filters_start_at=GENESIS_BLOCK_NUMBER,
        ),
    )
    c2_signer = LocalSigner(private_keys[2])
    c1_token_network_proxy = c1_proxy_manager.token_network(
        token_network_address)
    c2_token_network_proxy = c2_proxy_manager.token_network(
        token_network_address)

    initial_token_balance = 100
    token_proxy.transfer(c1_client.address, initial_token_balance)
    token_proxy.transfer(c2_client.address, initial_token_balance)

    initial_balance_c1 = token_proxy.balance_of(c1_client.address)
    assert initial_balance_c1 == initial_token_balance
    initial_balance_c2 = token_proxy.balance_of(c2_client.address)
    assert initial_balance_c2 == initial_token_balance

    # instantiating a new channel - test basic assumptions
    assert (c1_token_network_proxy.get_channel_identifier_or_none(
        participant1=c1_client.address,
        participant2=c2_client.address,
        block_identifier="latest",
    ) is None)

    msg = "Hex encoded addresses are not supported, an assertion must be raised"
    with pytest.raises(AssertionError):
        c1_token_network_proxy.get_channel_identifier(
            participant1=to_checksum_address(c1_client.address),
            participant2=to_checksum_address(c2_client.address),
            block_identifier="latest",
        )
        pytest.fail(msg)

    msg = "Zero is not a valid channel_identifier identifier, an exception must be raised."
    with pytest.raises(InvalidChannelID):
        assert c1_token_network_proxy.channel_is_opened(
            participant1=c1_client.address,
            participant2=c2_client.address,
            block_identifier="latest",
            channel_identifier=0,
        )
        pytest.fail(msg)

    msg = "Zero is not a valid channel_identifier identifier. an exception must be raised."
    with pytest.raises(InvalidChannelID):
        assert c1_token_network_proxy.channel_is_closed(
            participant1=c1_client.address,
            participant2=c2_client.address,
            block_identifier="latest",
            channel_identifier=0,
        )
        pytest.fail(msg)

    msg = ("Opening a channel with a settle_timeout lower then token "
           "network's minimum will fail. This must be validated and the "
           "transaction must not be sent.")
    with pytest.raises(InvalidSettleTimeout):
        c1_token_network_proxy.new_netting_channel(
            partner=c2_client.address,
            settle_timeout=TEST_SETTLE_TIMEOUT_MIN - 1,
            given_block_identifier="latest",
        )
        pytest.fail(msg)

    # Using exactly the minimal timeout must succeed
    c1_token_network_proxy.new_netting_channel(
        partner=make_address(),
        settle_timeout=TEST_SETTLE_TIMEOUT_MIN,
        given_block_identifier="latest",
    )

    msg = ("Opening a channel with a settle_timeout larger then token "
           "network's maximum will fail. This must be validated and the "
           "transaction must not be sent.")
    with pytest.raises(InvalidSettleTimeout):
        c1_token_network_proxy.new_netting_channel(
            partner=c2_client.address,
            settle_timeout=TEST_SETTLE_TIMEOUT_MAX + 1,
            given_block_identifier="latest",
        )
        pytest.fail(msg)

    # Using exactly the maximal timeout must succeed
    c1_token_network_proxy.new_netting_channel(
        partner=make_address(),
        settle_timeout=TEST_SETTLE_TIMEOUT_MAX,
        given_block_identifier="latest",
    )

    msg = (
        "Opening a channel with itself is not allow. This must be validated and "
        "the transaction must not be sent.")
    with pytest.raises(SamePeerAddress):
        c1_token_network_proxy.new_netting_channel(
            partner=c1_client.address,
            settle_timeout=TEST_SETTLE_TIMEOUT_MIN,
            given_block_identifier="latest",
        )
        pytest.fail(msg)

    msg = "Trying a deposit to an inexisting channel must fail."
    with pytest.raises(BrokenPreconditionError):
        c1_token_network_proxy.set_total_deposit(
            given_block_identifier="latest",
            channel_identifier=100,
            total_deposit=1,
            partner=c2_client.address,
        )
        pytest.fail(msg)

    empty_balance_proof = BalanceProof(
        channel_identifier=100,
        token_network_address=c1_token_network_proxy.address,
        balance_hash=encode_hex(EMPTY_BALANCE_HASH),
        nonce=0,
        chain_id=chain_id,
        transferred_amount=0,
    )
    closing_data = (empty_balance_proof.serialize_bin(
        msg_type=MessageTypeId.BALANCE_PROOF) + EMPTY_SIGNATURE)

    msg = "Trying to close an inexisting channel must fail."
    match = "The channel was not open at the provided block"
    with pytest.raises(RaidenUnrecoverableError, match=match):
        c1_token_network_proxy.close(
            channel_identifier=100,
            partner=c2_client.address,
            balance_hash=EMPTY_HASH,
            nonce=0,
            additional_hash=EMPTY_HASH,
            non_closing_signature=EMPTY_SIGNATURE,
            closing_signature=c1_signer.sign(data=closing_data),
            given_block_identifier="latest",
        )
        pytest.fail(msg)

    channel_identifier = c1_token_network_proxy.new_netting_channel(
        partner=c2_client.address,
        settle_timeout=TEST_SETTLE_TIMEOUT_MIN,
        given_block_identifier="latest",
    )
    msg = "new_netting_channel did not return a valid channel id"
    assert isinstance(channel_identifier, T_ChannelID), msg

    msg = "multiple channels with the same peer are not allowed"
    with pytest.raises(BrokenPreconditionError):
        c1_token_network_proxy.new_netting_channel(
            partner=c2_client.address,
            settle_timeout=TEST_SETTLE_TIMEOUT_MIN,
            given_block_identifier="latest",
        )
        pytest.fail(msg)

    assert (c1_token_network_proxy.get_channel_identifier_or_none(
        participant1=c1_client.address,
        participant2=c2_client.address,
        block_identifier="latest",
    ) is not None)

    assert (c1_token_network_proxy.channel_is_opened(
        participant1=c1_client.address,
        participant2=c2_client.address,
        block_identifier="latest",
        channel_identifier=channel_identifier,
    ) is True)

    msg = "set_total_deposit must fail if the amount exceed the account's balance"
    with pytest.raises(BrokenPreconditionError):
        c1_token_network_proxy.set_total_deposit(
            given_block_identifier="latest",
            channel_identifier=channel_identifier,
            total_deposit=initial_token_balance + 1,
            partner=c2_client.address,
        )
        pytest.fail(msg)

    msg = "set_total_deposit must fail with a negative amount"
    with pytest.raises(BrokenPreconditionError):
        c1_token_network_proxy.set_total_deposit(
            given_block_identifier="latest",
            channel_identifier=channel_identifier,
            total_deposit=-1,
            partner=c2_client.address,
        )
        pytest.fail(msg)

    msg = "set_total_deposit must fail with a zero amount"
    with pytest.raises(BrokenPreconditionError):
        c1_token_network_proxy.set_total_deposit(
            given_block_identifier="latest",
            channel_identifier=channel_identifier,
            total_deposit=0,
            partner=c2_client.address,
        )
        pytest.fail(msg)

    c1_token_network_proxy.set_total_deposit(
        given_block_identifier="latest",
        channel_identifier=channel_identifier,
        total_deposit=10,
        partner=c2_client.address,
    )

    transferred_amount = 3
    balance_proof = BalanceProof(
        channel_identifier=channel_identifier,
        token_network_address=to_checksum_address(token_network_address),
        nonce=1,
        chain_id=chain_id,
        transferred_amount=transferred_amount,
    )
    signature = c1_signer.sign(data=balance_proof.serialize_bin())
    balance_proof.signature = encode_hex(signature)

    signature_number = int.from_bytes(signature, "big")
    bit_to_change = random.randint(0, SIGNATURE_SIZE_IN_BITS - 1)
    signature_number_bit_flipped = signature_number ^ (2**bit_to_change)

    invalid_signatures = [
        EMPTY_SIGNATURE,
        b"\x11" * 65,
        signature_number_bit_flipped.to_bytes(len(signature), "big"),
    ]

    msg = "close must fail if the closing_signature is invalid"
    for invalid_signature in invalid_signatures:
        closing_data = (
            balance_proof.serialize_bin(msg_type=MessageTypeId.BALANCE_PROOF) +
            invalid_signature)
        with pytest.raises(RaidenUnrecoverableError):
            c2_token_network_proxy.close(
                channel_identifier=channel_identifier,
                partner=c1_client.address,
                balance_hash=decode_hex(balance_proof.balance_hash),
                nonce=balance_proof.nonce,
                additional_hash=decode_hex(balance_proof.additional_hash),
                non_closing_signature=invalid_signature,
                closing_signature=c2_signer.sign(data=closing_data),
                given_block_identifier="latest",
            )
            pytest.fail(msg)

    blocknumber_prior_to_close = c2_client.block_number()

    closing_data = balance_proof.serialize_bin(
        msg_type=MessageTypeId.BALANCE_PROOF) + decode_hex(
            balance_proof.signature)
    c2_token_network_proxy.close(
        channel_identifier=channel_identifier,
        partner=c1_client.address,
        balance_hash=decode_hex(balance_proof.balance_hash),
        nonce=balance_proof.nonce,
        additional_hash=decode_hex(balance_proof.additional_hash),
        non_closing_signature=decode_hex(balance_proof.signature),
        closing_signature=c2_signer.sign(data=closing_data),
        given_block_identifier="latest",
    )
    assert (c1_token_network_proxy.channel_is_closed(
        participant1=c1_client.address,
        participant2=c2_client.address,
        block_identifier="latest",
        channel_identifier=channel_identifier,
    ) is True)
    assert (c1_token_network_proxy.get_channel_identifier_or_none(
        participant1=c1_client.address,
        participant2=c2_client.address,
        block_identifier="latest",
    ) is not None)

    msg = (
        "given_block_identifier is the block at which the transaction is being  "
        "sent. If the channel is already closed at that block the client code  "
        "has a programming error. An exception is raised for that.")
    with pytest.raises(RaidenUnrecoverableError):
        c2_token_network_proxy.close(
            channel_identifier=channel_identifier,
            partner=c1_client.address,
            balance_hash=decode_hex(balance_proof.balance_hash),
            nonce=balance_proof.nonce,
            additional_hash=decode_hex(balance_proof.additional_hash),
            non_closing_signature=decode_hex(balance_proof.signature),
            closing_signature=c2_signer.sign(data=closing_data),
            given_block_identifier="latest",
        )
        pytest.fail(msg)

    msg = ("The channel cannot be closed two times. If it was not closed at "
           "given_block_identifier but it is closed at the time the proxy is "
           "called an exception must be raised.")
    with pytest.raises(RaidenRecoverableError):
        c2_token_network_proxy.close(
            channel_identifier=channel_identifier,
            partner=c1_client.address,
            balance_hash=decode_hex(balance_proof.balance_hash),
            nonce=balance_proof.nonce,
            additional_hash=decode_hex(balance_proof.additional_hash),
            non_closing_signature=decode_hex(balance_proof.signature),
            closing_signature=c2_signer.sign(data=closing_data),
            given_block_identifier=blocknumber_prior_to_close,
        )
        pytest.fail(msg)

    msg = "depositing to a closed channel must fail"
    match = "closed"
    with pytest.raises(RaidenRecoverableError, match=match):
        c2_token_network_proxy.set_total_deposit(
            given_block_identifier=blocknumber_prior_to_close,
            channel_identifier=channel_identifier,
            total_deposit=20,
            partner=c1_client.address,
        )
        pytest.fail(msg)

    c1_proxy_manager.wait_until_block(
        target_block_number=c1_proxy_manager.client.block_number() +
        TEST_SETTLE_TIMEOUT_MIN)

    invalid_transferred_amount = 1
    msg = "settle with invalid transferred_amount data must fail"
    with pytest.raises(BrokenPreconditionError):
        c2_token_network_proxy.settle(
            channel_identifier=channel_identifier,
            transferred_amount=invalid_transferred_amount,
            locked_amount=0,
            locksroot=LOCKSROOT_OF_NO_LOCKS,
            partner=c1_client.address,
            partner_transferred_amount=transferred_amount,
            partner_locked_amount=0,
            partner_locksroot=LOCKSROOT_OF_NO_LOCKS,
            given_block_identifier="latest",
        )
        pytest.fail(msg)

    c2_token_network_proxy.settle(
        channel_identifier=channel_identifier,
        transferred_amount=0,
        locked_amount=0,
        locksroot=LOCKSROOT_OF_NO_LOCKS,
        partner=c1_client.address,
        partner_transferred_amount=transferred_amount,
        partner_locked_amount=0,
        partner_locksroot=LOCKSROOT_OF_NO_LOCKS,
        given_block_identifier="latest",
    )
    assert (c1_token_network_proxy.get_channel_identifier_or_none(
        participant1=c1_client.address,
        participant2=c2_client.address,
        block_identifier="latest",
    ) is None)
    assert token_proxy.balance_of(c1_client.address) == (initial_balance_c1 -
                                                         transferred_amount)
    assert token_proxy.balance_of(c2_client.address) == (initial_balance_c2 +
                                                         transferred_amount)

    msg = "depositing to a settled channel must fail"
    with pytest.raises(BrokenPreconditionError):
        c1_token_network_proxy.set_total_deposit(
            given_block_identifier="latest",
            channel_identifier=channel_identifier,
            total_deposit=10,
            partner=c2_client.address,
        )
        pytest.fail(msg)
def test_token_network_proxy_update_transfer(token_network_proxy, private_keys,
                                             token_proxy, chain_id, web3,
                                             contract_manager):
    """Tests channel lifecycle, with `update_transfer` before settling"""
    token_network_address = to_canonical_address(
        token_network_proxy.proxy.address)

    c1_client = JSONRPCClient(web3, private_keys[1])
    c1_proxy_manager = ProxyManager(
        rpc_client=c1_client,
        contract_manager=contract_manager,
        metadata=ProxyManagerMetadata(
            token_network_registry_deployed_at=GENESIS_BLOCK_NUMBER,
            filters_start_at=GENESIS_BLOCK_NUMBER,
        ),
    )
    c1_signer = LocalSigner(private_keys[1])
    c2_client = JSONRPCClient(web3, private_keys[2])
    c2_proxy_manager = ProxyManager(
        rpc_client=c2_client,
        contract_manager=contract_manager,
        metadata=ProxyManagerMetadata(
            token_network_registry_deployed_at=GENESIS_BLOCK_NUMBER,
            filters_start_at=GENESIS_BLOCK_NUMBER,
        ),
    )
    c1_token_network_proxy = c1_proxy_manager.token_network(
        address=token_network_address, block_identifier=BLOCK_ID_LATEST)
    c2_token_network_proxy = c2_proxy_manager.token_network(
        address=token_network_address, block_identifier=BLOCK_ID_LATEST)
    # create a channel
    channel_identifier, _, _ = c1_token_network_proxy.new_netting_channel(
        partner=c2_client.address,
        settle_timeout=10,
        given_block_identifier=BLOCK_ID_LATEST)
    # deposit to the channel
    initial_balance = 100
    token_proxy.transfer(c1_client.address, initial_balance)
    token_proxy.transfer(c2_client.address, initial_balance)
    initial_balance_c1 = token_proxy.balance_of(c1_client.address)
    assert initial_balance_c1 == initial_balance
    initial_balance_c2 = token_proxy.balance_of(c2_client.address)
    assert initial_balance_c2 == initial_balance
    c1_token_network_proxy.approve_and_set_total_deposit(
        given_block_identifier=BLOCK_ID_LATEST,
        channel_identifier=channel_identifier,
        total_deposit=10,
        partner=c2_client.address,
    )
    c2_token_network_proxy.approve_and_set_total_deposit(
        given_block_identifier=BLOCK_ID_LATEST,
        channel_identifier=channel_identifier,
        total_deposit=10,
        partner=c1_client.address,
    )
    # balance proof signed by c1
    transferred_amount_c1 = 1
    transferred_amount_c2 = 3
    balance_proof_c1 = BalanceProof(
        channel_identifier=channel_identifier,
        token_network_address=token_network_address,
        nonce=1,
        chain_id=chain_id,
        transferred_amount=transferred_amount_c1,
    )
    balance_proof_c1.signature = encode_hex(
        LocalSigner(
            private_keys[1]).sign(data=balance_proof_c1.serialize_bin()))
    # balance proof signed by c2
    balance_proof_c2 = BalanceProof(
        channel_identifier=channel_identifier,
        token_network_address=token_network_address,
        nonce=2,
        chain_id=chain_id,
        transferred_amount=transferred_amount_c2,
    )
    balance_proof_c2.signature = encode_hex(
        LocalSigner(
            private_keys[2]).sign(data=balance_proof_c2.serialize_bin()))

    non_closing_data = balance_proof_c1.serialize_bin(
        msg_type=MessageTypeId.BALANCE_PROOF_UPDATE) + decode_hex(
            balance_proof_c1.signature)
    non_closing_signature = LocalSigner(
        c2_client.privkey).sign(data=non_closing_data)

    with pytest.raises(RaidenUnrecoverableError) as exc:
        c2_token_network_proxy.update_transfer(
            channel_identifier=channel_identifier,
            partner=c1_client.address,
            balance_hash=balance_proof_c1.balance_hash,
            nonce=balance_proof_c1.nonce,
            additional_hash=decode_hex(balance_proof_c1.additional_hash),
            closing_signature=decode_hex(balance_proof_c1.signature),
            non_closing_signature=non_closing_signature,
            given_block_identifier=BLOCK_ID_LATEST,
        )

        assert "not in a closed state" in str(exc)

    # close by c1
    closing_data = balance_proof_c2.serialize_bin(
        msg_type=MessageTypeId.BALANCE_PROOF) + decode_hex(
            balance_proof_c2.signature)
    c1_token_network_proxy.close(
        channel_identifier=channel_identifier,
        partner=c2_client.address,
        balance_hash=balance_proof_c2.balance_hash,
        nonce=balance_proof_c2.nonce,
        additional_hash=decode_hex(balance_proof_c2.additional_hash),
        non_closing_signature=decode_hex(balance_proof_c2.signature),
        closing_signature=c1_signer.sign(data=closing_data),
        given_block_identifier=BLOCK_ID_LATEST,
    )

    # update transfer with completely invalid closing signature
    with pytest.raises(RaidenUnrecoverableError) as excinfo:
        c2_token_network_proxy.update_transfer(
            channel_identifier=channel_identifier,
            partner=c1_client.address,
            balance_hash=balance_proof_c1.balance_hash,
            nonce=balance_proof_c1.nonce,
            additional_hash=decode_hex(balance_proof_c1.additional_hash),
            closing_signature=b"",
            non_closing_signature=b"",
            given_block_identifier=BLOCK_ID_LATEST,
        )
    assert str(excinfo.value) == "Couldn't verify the balance proof signature"

    # using invalid non-closing signature
    # Usual mistake when calling update Transfer - balance proof signature is missing in the data
    non_closing_data = balance_proof_c1.serialize_bin(
        msg_type=MessageTypeId.BALANCE_PROOF_UPDATE)
    non_closing_signature = LocalSigner(
        c2_client.privkey).sign(data=non_closing_data)
    with pytest.raises(RaidenUnrecoverableError):
        c2_token_network_proxy.update_transfer(
            channel_identifier=channel_identifier,
            partner=c1_client.address,
            balance_hash=balance_proof_c1.balance_hash,
            nonce=balance_proof_c1.nonce,
            additional_hash=decode_hex(balance_proof_c1.additional_hash),
            closing_signature=decode_hex(balance_proof_c1.signature),
            non_closing_signature=non_closing_signature,
            given_block_identifier=BLOCK_ID_LATEST,
        )

    non_closing_data = balance_proof_c1.serialize_bin(
        msg_type=MessageTypeId.BALANCE_PROOF_UPDATE) + decode_hex(
            balance_proof_c1.signature)
    non_closing_signature = LocalSigner(
        c2_client.privkey).sign(data=non_closing_data)
    c2_token_network_proxy.update_transfer(
        channel_identifier=channel_identifier,
        partner=c1_client.address,
        balance_hash=balance_proof_c1.balance_hash,
        nonce=balance_proof_c1.nonce,
        additional_hash=decode_hex(balance_proof_c1.additional_hash),
        closing_signature=decode_hex(balance_proof_c1.signature),
        non_closing_signature=non_closing_signature,
        given_block_identifier=BLOCK_ID_LATEST,
    )

    with pytest.raises(BrokenPreconditionError) as exc:
        c1_token_network_proxy.settle(
            channel_identifier=channel_identifier,
            transferred_amount=transferred_amount_c1,
            locked_amount=0,
            locksroot=LOCKSROOT_OF_NO_LOCKS,
            partner=c2_client.address,
            partner_transferred_amount=transferred_amount_c2,
            partner_locked_amount=0,
            partner_locksroot=LOCKSROOT_OF_NO_LOCKS,
            given_block_identifier=BLOCK_ID_LATEST,
        )

        assert "cannot be settled before settlement window is over" in str(exc)

    c1_client.wait_until_block(target_block_number=c1_client.block_number() +
                               10)

    # settling with an invalid amount
    with pytest.raises(BrokenPreconditionError):
        c1_token_network_proxy.settle(
            channel_identifier=channel_identifier,
            transferred_amount=2,
            locked_amount=0,
            locksroot=LOCKSROOT_OF_NO_LOCKS,
            partner=c2_client.address,
            partner_transferred_amount=2,
            partner_locked_amount=0,
            partner_locksroot=LOCKSROOT_OF_NO_LOCKS,
            given_block_identifier=BLOCK_ID_LATEST,
        )

    # proper settle
    c1_token_network_proxy.settle(
        channel_identifier=channel_identifier,
        transferred_amount=transferred_amount_c1,
        locked_amount=0,
        locksroot=LOCKSROOT_OF_NO_LOCKS,
        partner=c2_client.address,
        partner_transferred_amount=transferred_amount_c2,
        partner_locked_amount=0,
        partner_locksroot=LOCKSROOT_OF_NO_LOCKS,
        given_block_identifier=BLOCK_ID_LATEST,
    )
    assert token_proxy.balance_of(
        c2_client.address) == (initial_balance_c2 + transferred_amount_c1 -
                               transferred_amount_c2)
    assert token_proxy.balance_of(
        c1_client.address) == (initial_balance_c1 + transferred_amount_c2 -
                               transferred_amount_c1)

    # Already settled
    with pytest.raises(BrokenPreconditionError) as exc:
        c2_token_network_proxy.approve_and_set_total_deposit(
            given_block_identifier=BLOCK_ID_LATEST,
            channel_identifier=channel_identifier,
            total_deposit=20,
            partner=c1_client.address,
        )

        assert "getChannelIdentifier returned 0" in str(exc)
示例#13
0
class ScenarioRunner:
    def __init__(
        self,
        account: Account,
        auth: str,
        data_path: Path,
        scenario_file: Path,
        environment: EnvironmentConfig,
        success: Event,
        raiden_client: Optional[str],
        task_state_callback: Optional[
            Callable[["ScenarioRunner", "Task", "TaskState"], None]
        ] = None,
        smoketest_deployment_data: DeployedContracts = None,
        delete_snapshots: bool = False,
    ) -> None:
        self.success = success

        self.smoketest_deployment_data = smoketest_deployment_data
        self.delete_snapshots = delete_snapshots

        self.data_path = data_path
        self.environment = environment

        # Set the client executable to use
        if raiden_client is not None:
            self.environment.raiden_client = raiden_client

        self.task_count = 0
        self.running_task_count = 0
        self.task_cache: Dict[str, Task] = {}
        self.task_state_callback = task_state_callback
        # Storage for arbitrary data tasks might need to persist
        self.task_storage: Dict[str, dict] = defaultdict(dict)

        self.definition = ScenarioDefinition(scenario_file, data_path, self.environment)

        log.debug("Local seed", seed=self.local_seed)

        self.run_number = determine_run_number(self.definition.scenario_dir)

        log.info("Run number", run_number=self.run_number)

        self.protocol = "http"
        self.session = make_session(auth, self.definition.settings, self.definition.nodes)

        web3 = Web3(HTTPProvider(environment.eth_rpc_endpoints[0], session=self.session))
        self.chain_id = ChainID(web3.eth.chainId)
        self.definition.settings.eth_rpc_endpoint_iterator = environment.eth_rpc_endpoint_iterator
        self.definition.settings.chain_id = self.chain_id

        assert account.privkey, "Account not unlockable"
        self.client = JSONRPCClient(
            web3=web3,
            privkey=account.privkey,
            gas_price_strategy=faster_gas_price_strategy,
            block_num_confirmations=DEFAULT_NUMBER_OF_BLOCK_CONFIRMATIONS,
        )

        assert account.address, "Account not loaded"
        balance = self.client.balance(account.address)
        if balance < OWN_ACCOUNT_BALANCE_MIN:
            raise ScenarioError(
                f"Insufficient balance ({balance / 10 ** 18} Eth) "
                f"in account {to_checksum_address(account.address)} "
                f'on chain "{self.definition.settings.chain_id}"'
                f" - it needs additional {(OWN_ACCOUNT_BALANCE_MIN - balance) / 10 ** 18} Eth ("
                f"that is {OWN_ACCOUNT_BALANCE_MIN - balance} Wei)."
            )

        self.node_controller = NodeController(
            runner=self,
            config=self.definition.nodes,
            raiden_client=self.environment.raiden_client,
            delete_snapshots=self.delete_snapshots,
        )
        task_config = self.definition.scenario.root_config
        task_class = self.definition.scenario.root_class
        self.root_task = task_class(runner=self, config=task_config)

    @property
    def local_seed(self) -> str:
        """Return a persistent random seed value.

        We need a unique seed per scenario player 'installation'.
        This is used in the node private key generation to prevent re-use of node keys between
        multiple users of the scenario player.

        The seed is stored in a file inside the ``.definition.settings.sp_root_dir``.
        """
        assert self.definition.settings.sp_root_dir
        seed_file = self.definition.settings.sp_root_dir.joinpath("seed.txt")
        if not seed_file.exists():
            seed = str(encode_hex(bytes(random.randint(0, 255) for _ in range(20))))
            seed_file.write_text(seed)
        else:
            seed = seed_file.read_text().strip()
        return seed

    def ensure_token_network_discovery(
        self, token: CustomToken, token_network_addresses: TokenNetworkAddress
    ) -> None:
        """Ensure that all our nodes have discovered the same token network."""
        for node in self.node_controller:  # type: ignore
            node_endpoint = API_URL_TOKEN_NETWORK_ADDRESS.format(
                protocol=self.protocol,
                target_host=node.base_url,
                token_address=to_checksum_address(token.address),
            )
            address = wait_for_token_network_discovery(
                node_endpoint, self.definition.settings, self.session
            )
            if to_canonical_address(address) != Address(token_network_addresses):
                raise RuntimeError(
                    f"Nodes diverged on the token network address, there should be "
                    f"exactly one token network available for all nodes. Current "
                    f"values : {to_hex(token_network_addresses)}"
                )

    def run_scenario(self) -> None:
        with Janitor() as nursery:
            self.node_controller.set_nursery(nursery)
            self.node_controller.initialize_nodes()

            try:
                for node_runner in self.node_controller._node_runners:
                    node_runner.start()
            except Exception:
                log.error("failed to start", exc_info=True)
                raise

            node_addresses = self.node_controller.addresses

            scenario = nursery.spawn_under_watch(
                self.setup_environment_and_run_main_task, node_addresses
            )
            scenario.name = "orchestration"

            # Wait for either a crash in one of the Raiden nodes or for the
            # scenario to exit (successfully or not).
            greenlets = {scenario}
            gevent.joinall(greenlets, raise_error=True, count=1)
        self.success.set()

    def setup_environment_and_run_main_task(self, node_addresses: Set[ChecksumAddress]) -> None:
        """This will first make sure the on-chain state is setup properly, and
        then execute the scenario.

        The on-chain state consists of:

        - Deployment of the test CustomToken
        - For each of the Raiden nodes, make sure they have enough:

            - Ether to pay for the transactions.
            - Utility token balances in the user deposit smart contract.
            - Tokens to be used with the test token network.
        """
        block_execution_started = self.client.block_number()

        settings = self.definition.settings
        udc_settings = settings.services.udc

        smoketesting = False
        if self.chain_id != CHAINNAME_TO_ID["smoketest"]:
            deploy = get_contracts_deployment_info(
                self.chain_id,
                RAIDEN_CONTRACT_VERSION,
                development_environment=self.environment.development_environment,
            )
        else:
            smoketesting = True
            deploy = self.smoketest_deployment_data

        msg = "There is no deployment details for the given chain_id and contracts version pair"
        assert deploy, msg

        proxy_manager = get_proxy_manager(self.client, deploy)

        # Tracking pool to synchronize on all concurrent transactions
        pool = Pool()

        log.debug("Funding Raiden node's accounts with ether")
        self.setup_raiden_nodes_ether_balances(pool, node_addresses)

        if is_udc_enabled(udc_settings):
            (
                userdeposit_proxy,
                user_token_proxy,
            ) = get_udc_and_corresponding_token_from_dependencies(
                udc_address=udc_settings.address,
                chain_id=settings.chain_id,
                proxy_manager=proxy_manager,
                development_environment=self.environment.development_environment,
            )

            log.debug("Minting utility tokens and /scheduling/ transfers to the nodes")
            mint_greenlets = self.setup_mint_user_deposit_tokens_for_distribution(
                pool, userdeposit_proxy, user_token_proxy, node_addresses
            )
            self.setup_raiden_nodes_with_sufficient_user_deposit_balances(
                pool, userdeposit_proxy, node_addresses, mint_greenlets
            )

        # This is a blocking call. If the token has to be deployed it will
        # block until mined and confirmed, since that is a requirement for the
        # following setup calls.
        token_proxy = self.setup_token_contract_for_token_network(proxy_manager)
        if smoketesting:
            token_network_registry_proxy = get_token_network_registry_from_dependencies(
                settings=settings,
                proxy_manager=proxy_manager,
                smoketest_deployment_data=deploy,
                development_environment=self.environment.development_environment,
            )
        else:
            token_network_registry_proxy = get_token_network_registry_from_dependencies(
                settings=settings,
                proxy_manager=proxy_manager,
                development_environment=self.environment.development_environment,
            )

        self.setup_raiden_token_balances(pool, token_proxy, node_addresses)

        # Wait for all the transactions
        # - Move ether from the orcheastration account (the scenario player),
        # to the raiden nodes.
        # - Mint enough utility tokens (user deposit tokens) for the
        # orchestration account to transfer for the nodes.
        # - Mint network tokens for the nodes to use in the scenarion.
        # - Deposit utility tokens for the raiden nodes in the user deposit
        # contract.
        log.debug("Waiting for funding transactions to be mined")
        pool.join(raise_error=True)

        log.debug("Registering token to create the network")
        token_network_address = maybe_create_token_network(
            token_network_registry_proxy, token_proxy
        )

        log.debug("Waiting for the REST APIs")
        wait_for_nodes_to_be_ready(self.node_controller._node_runners, self.session)

        log.info("Making sure all nodes have the same token network")
        self.ensure_token_network_discovery(token_proxy, token_network_address)

        log.info(
            "Setup done, running scenario",
            token_network_address=to_checksum_address(token_network_address),
        )

        # Expose attributes used by the tasks
        self.token = token_proxy
        self.contract_manager = proxy_manager.contract_manager
        self.token_network_address = to_checksum_address(token_network_address)
        self.block_execution_started = block_execution_started

        self.root_task()

    def setup_raiden_nodes_ether_balances(
        self, pool: Pool, node_addresses: Set[ChecksumAddress]
    ) -> Set[Greenlet]:
        """ Makes sure every Raiden node has at least `NODE_ACCOUNT_BALANCE_MIN`. """

        greenlets: Set[Greenlet] = set()
        for address in node_addresses:
            g = pool.spawn(
                eth_maybe_transfer,
                orchestration_client=self.client,
                target=to_canonical_address(address),
                minimum_balance=NODE_ACCOUNT_BALANCE_MIN,
                maximum_balance=NODE_ACCOUNT_BALANCE_FUND,
            )
            greenlets.add(g)

        return greenlets

    def setup_mint_user_deposit_tokens_for_distribution(
        self,
        pool: Pool,
        userdeposit_proxy: UserDeposit,
        token_proxy: CustomToken,
        node_addresses: Set[ChecksumAddress],
    ) -> Set[Greenlet]:
        """Ensures the scenario player account has enough tokens and allowance
        to fund the Raiden nodes.
        """
        settings = self.definition.settings
        udc_settings = settings.services.udc
        balance_per_node = settings.services.udc.token.balance_per_node

        msg = "udc is not enabled, this function should not be called"
        assert is_udc_enabled(udc_settings), msg

        node_count = len(node_addresses)
        required_allowance = balance_per_node * node_count

        allowance_greenlet = pool.spawn(
            userdeposit_maybe_increase_allowance,
            token_proxy=token_proxy,
            userdeposit_proxy=userdeposit_proxy,
            orchestrator_address=self.client.address,
            minimum_allowance=required_allowance,
            maximum_allowance=UINT256_MAX,
        )

        mint_greenlet = pool.spawn(
            token_maybe_mint,
            token_proxy=token_proxy,
            target_address=to_checksum_address(self.client.address),
            minimum_balance=required_allowance,
            maximum_balance=ORCHESTRATION_MAXIMUM_BALANCE,
        )

        return {allowance_greenlet, mint_greenlet}

    def setup_raiden_token_balances(
        self, pool: Pool, token_proxy: CustomToken, node_addresses: Set[ChecksumAddress]
    ) -> Set[Greenlet]:
        """Mint the necessary amount of tokens from `token_proxy` for every `node_addresses`.

        This will use the scenario player's account, therefore it doesn't have
        to wait for the ether transfers to finish.
        """
        token_min_amount = self.definition.token.min_balance
        token_max_amount = self.definition.token.max_funding

        greenlets: Set[Greenlet] = set()
        for address in node_addresses:
            g = pool.spawn(
                token_maybe_mint,
                token_proxy=token_proxy,
                target_address=address,
                minimum_balance=token_min_amount,
                maximum_balance=token_max_amount,
            )
            greenlets.add(g)

        return greenlets

    def setup_raiden_nodes_with_sufficient_user_deposit_balances(
        self,
        pool: Pool,
        userdeposit_proxy: UserDeposit,
        node_addresses: Set[ChecksumAddress],
        mint_greenlets: Set[Greenlet],
    ) -> Set[Greenlet]:
        """Makes sure every Raiden node's account has enough tokens in the
        user deposit contract.

        For these transfers to work, the approve and mint transacations have to
        be mined and confirmed. This is necessary because otherwise the gas
        estimation of the deposits fail.
        """
        msg = "udc is not enabled, this function should not be called"
        assert is_udc_enabled(self.definition.settings.services.udc), msg

        minimum_effective_deposit = self.definition.settings.services.udc.token.balance_per_node
        maximum_funding = self.definition.settings.services.udc.token.max_funding

        log.debug("Depositing utility tokens for the nodes")
        greenlets: Set[Greenlet] = set()
        for address in node_addresses:
            g = pool.spawn(
                userdeposit_maybe_deposit,
                userdeposit_proxy=userdeposit_proxy,
                mint_greenlets=mint_greenlets,
                target_address=to_canonical_address(address),
                minimum_effective_deposit=minimum_effective_deposit,
                maximum_funding=maximum_funding,
            )
            greenlets.add(g)

        return greenlets

    def setup_token_contract_for_token_network(self, proxy_manager: ProxyManager) -> CustomToken:
        """Ensure there is a deployed token contract and return a `CustomToken`
        proxy to it. This token will be used for the scenario's token network.

        This will either:

        - Use the token from the address provided in the scenario
          configuration.
        - Use a previously deployed token, with the details loaded from the
          disk.
        - Deploy a new token if neither of the above options is used.
        """
        token_definition = self.definition.token
        reuse_token_from_file = token_definition.can_reuse_token

        if token_definition.address:
            token_address = to_canonical_address(token_definition.address)
        elif reuse_token_from_file:
            token_details = load_token_configuration_from_file(token_definition.token_file)
            token_address = to_canonical_address(token_details["address"])
        else:
            contract_data = proxy_manager.contract_manager.get_contract(CONTRACT_CUSTOM_TOKEN)
            contract, receipt = self.client.deploy_single_contract(
                contract_name=CONTRACT_CUSTOM_TOKEN,
                contract=contract_data,
                constructor_parameters=(
                    ORCHESTRATION_MAXIMUM_BALANCE,
                    token_definition.decimals,
                    token_definition.name,
                    token_definition.symbol,
                ),
            )
            token_address = to_canonical_address(contract.address)

            if token_definition.should_reuse_token:
                details = TokenDetails(
                    {
                        "name": token_definition.name,
                        "address": to_checksum_address(token_address),
                        "block": receipt["blockNumber"],
                    }
                )
                save_token_configuration_to_file(token_definition.token_file, details)

        return proxy_manager.custom_token(TokenAddress(token_address), "latest")

    def task_state_changed(self, task: "Task", state: "TaskState"):
        if self.task_state_callback:
            self.task_state_callback(self, task, state)

    def get_node_address(self, index):
        return self.node_controller[index].address

    def get_node_baseurl(self, index):
        return self.node_controller[index].base_url
示例#14
0
def test_remote_transaction_with_zero_gasprice_is_not_mined(
        web3: Web3, deploy_key: PrivateKey,
        eth_nodes_configuration: List[EthNodeDescription]) -> None:
    """ If the non-local transaction is sent with a gas price set to zero it is
    not mined.
    """
    host = "127.0.0.1"

    assert eth_nodes_configuration[0].miner
    miner_rpc_port = eth_nodes_configuration[0].rpc_port

    assert not eth_nodes_configuration[1].miner
    rpc_port = eth_nodes_configuration[1].rpc_port

    miner_web3 = Web3(HTTPProvider(f"http://{host}:{miner_rpc_port}"))
    miner_client = JSONRPCClient(miner_web3, deploy_key)

    web3 = Web3(HTTPProvider(f"http://{host}:{rpc_port}"))
    client = JSONRPCClient(web3, deploy_key)

    before_deploy_block = client.block_number()
    normal_gas_proxy, _ = deploy_rpc_test_contract(client, "RpcTest")
    num_blocks_to_wait = client.block_number() - before_deploy_block

    gas_price = GasPrice(0)
    gas_price_strategy = make_fixed_gas_price_strategy(gas_price)
    client.web3.eth.setGasPriceStrategy(gas_price_strategy)
    zero_gas_proxy = client.new_contract_proxy(
        abi=normal_gas_proxy.abi, contract_address=normal_gas_proxy.address)

    address = normal_gas_proxy.address
    assert len(client.web3.eth.getCode(address)) > 0

    estimated_transaction = client.estimate_gas(zero_gas_proxy, "ret", {})
    assert estimated_transaction, "Gas estimation should not fail here"

    zerogas_transaction_sent = client.transact(estimated_transaction)

    # wait for how many blocks it took to mine the deployment, since this is a
    # private chain, if the new transaction will be mined it should be roughly
    # in the same time frame (adding two blocks to cover race conditions)
    target_block_number = client.block_number() + num_blocks_to_wait + 2
    while client.block_number() < target_block_number:
        gevent.sleep(0.5)

    try:
        miner_zerogas_tx = miner_client.web3.eth.getTransaction(
            zerogas_transaction_sent.transaction_hash)
        miner_zerogas_receipt = miner_client.web3.eth.getTransactionReceipt(
            zerogas_transaction_sent.transaction_hash)
    except TransactionNotFound:
        miner_zerogas_tx = None
        miner_zerogas_receipt = None

    msg = "The transaction was discarded by the miner, there is no transaction and no receipt"
    assert miner_zerogas_tx is None, msg
    assert miner_zerogas_receipt is None, msg

    zerogas_tx = client.web3.eth.getTransaction(
        zerogas_transaction_sent.transaction_hash)
    msg = (
        "The transaction was NOT discarded by the original node, because it is a local transaction"
    )
    assert zerogas_tx is not None, msg

    try:
        zerogas_receipt = client.web3.eth.getTransactionReceipt(
            zerogas_transaction_sent.transaction_hash)
    except TransactionNotFound:
        zerogas_receipt = None

    msg = "The transaction does NOT have a receipt because the miner rejected it"
    assert zerogas_receipt is None, msg
def test_payment_channel_outdated_channel_close(
    token_network_proxy,
    private_keys,
    chain_id,
    web3,
    contract_manager,
):
    token_network_address = to_canonical_address(
        token_network_proxy.proxy.contract.address)

    partner = privatekey_to_address(private_keys[0])

    client = JSONRPCClient(web3, private_keys[1])
    chain = BlockChainService(client)
    token_network_proxy = TokenNetwork(
        jsonrpc_client=client,
        token_network_address=token_network_address,
        contract_manager=contract_manager,
    )
    start_block = web3.eth.blockNumber

    # create a channel
    channel_identifier = token_network_proxy.new_netting_channel(
        partner,
        TEST_SETTLE_TIMEOUT_MIN,
    )
    assert channel_identifier is not None

    # create channel proxies
    channel_proxy_1 = PaymentChannel(
        token_network=token_network_proxy,
        channel_identifier=channel_identifier,
        contract_manager=contract_manager,
    )

    channel_filter = channel_proxy_1.all_events_filter(
        from_block=start_block,
        to_block='latest',
    )

    assert channel_proxy_1.channel_identifier == channel_identifier

    assert channel_proxy_1.opened() is True

    # balance proof by c1
    balance_proof = BalanceProof(
        channel_identifier=channel_identifier,
        token_network_address=to_checksum_address(token_network_address),
        nonce=0,
        chain_id=chain_id,
        transferred_amount=0,
    )
    balance_proof.signature = encode_hex(
        LocalSigner(private_keys[0]).sign(
            data=balance_proof.serialize_bin(), ), )
    # correct close
    token_network_proxy.close(
        channel_identifier=channel_identifier,
        partner=partner,
        balance_hash=bytes(32),
        nonce=balance_proof.nonce,
        additional_hash=bytes(32),
        signature=decode_hex(balance_proof.signature),
    )
    assert channel_proxy_1.closed() is True

    events = channel_filter.get_all_entries()
    assert len(events) == 2  # ChannelOpened, ChannelClosed

    # check the settlement timeouts again
    assert channel_proxy_1.settle_timeout() == TEST_SETTLE_TIMEOUT_MIN

    # update transfer
    chain.wait_until_block(target_block_number=client.block_number() +
                           TEST_SETTLE_TIMEOUT_MIN)

    token_network_proxy.settle(
        channel_identifier=channel_identifier,
        transferred_amount=0,
        locked_amount=0,
        locksroot=EMPTY_HASH,
        partner=partner,
        partner_transferred_amount=0,
        partner_locked_amount=0,
        partner_locksroot=EMPTY_HASH,
    )
    assert channel_proxy_1.settled() is True

    events = channel_filter.get_all_entries()

    assert len(events) == 3  # ChannelOpened, ChannelClosed, ChannelSettled

    # Create a new channel with a different identifier
    # create a channel
    new_channel_identifier = token_network_proxy.new_netting_channel(
        partner,
        TEST_SETTLE_TIMEOUT_MIN,
    )
    assert new_channel_identifier is not None
    # create channel proxies
    channel_proxy_2 = PaymentChannel(
        token_network=token_network_proxy,
        channel_identifier=new_channel_identifier,
        contract_manager=contract_manager,
    )

    assert channel_proxy_2.channel_identifier == new_channel_identifier
    assert channel_proxy_2.opened() is True

    with pytest.raises(ChannelOutdatedError):
        token_network_proxy.close(
            channel_identifier=channel_identifier,
            partner=partner,
            balance_hash=bytes(32),
            nonce=balance_proof.nonce,
            additional_hash=bytes(32),
            signature=decode_hex(balance_proof.signature),
        )
def test_payment_channel_proxy_basics(
    token_network_proxy,
    private_keys,
    token_proxy,
    chain_id,
    web3,
    contract_manager,
):
    token_network_address = to_canonical_address(
        token_network_proxy.proxy.contract.address)

    c1_client = JSONRPCClient(web3, private_keys[1])
    c1_chain = BlockChainService(c1_client)
    c2_client = JSONRPCClient(web3, private_keys[2])
    c1_token_network_proxy = TokenNetwork(
        jsonrpc_client=c1_client,
        token_network_address=token_network_address,
        contract_manager=contract_manager,
    )
    c2_token_network_proxy = TokenNetwork(
        jsonrpc_client=c2_client,
        token_network_address=token_network_address,
        contract_manager=contract_manager,
    )

    start_block = web3.eth.blockNumber

    # create a channel
    channel_identifier = c1_token_network_proxy.new_netting_channel(
        c2_client.address,
        TEST_SETTLE_TIMEOUT_MIN,
    )
    assert channel_identifier is not None

    # create channel proxies
    channel_proxy_1 = PaymentChannel(
        token_network=c1_token_network_proxy,
        channel_identifier=channel_identifier,
        contract_manager=contract_manager,
    )
    channel_proxy_2 = PaymentChannel(
        token_network=c2_token_network_proxy,
        channel_identifier=channel_identifier,
        contract_manager=contract_manager,
    )

    channel_filter = channel_proxy_1.all_events_filter(
        from_block=start_block,
        to_block='latest',
    )

    assert channel_proxy_1.channel_identifier == channel_identifier
    assert channel_proxy_2.channel_identifier == channel_identifier

    assert channel_proxy_1.opened() is True
    assert channel_proxy_2.opened() is True

    # check the settlement timeouts
    assert channel_proxy_1.settle_timeout() == channel_proxy_2.settle_timeout()
    assert channel_proxy_1.settle_timeout() == TEST_SETTLE_TIMEOUT_MIN

    events = channel_filter.get_all_entries()
    assert len(events) == 1  # ChannelOpened

    # test deposits
    initial_token_balance = 100
    token_proxy.transfer(c1_client.address, initial_token_balance)
    initial_balance_c1 = token_proxy.balance_of(c1_client.address)
    assert initial_balance_c1 == initial_token_balance
    initial_balance_c2 = token_proxy.balance_of(c2_client.address)
    assert initial_balance_c2 == 0

    # actual deposit
    channel_proxy_1.set_total_deposit(10)

    events = channel_filter.get_all_entries()
    assert len(events) == 2  # ChannelOpened, ChannelNewDeposit

    # balance proof by c2
    transferred_amount = 3
    balance_proof = BalanceProof(
        channel_identifier=channel_identifier,
        token_network_address=to_checksum_address(token_network_address),
        nonce=1,
        chain_id=chain_id,
        transferred_amount=transferred_amount,
    )
    balance_proof.signature = encode_hex(
        LocalSigner(private_keys[1]).sign(
            data=balance_proof.serialize_bin(), ), )
    # correct close
    c2_token_network_proxy.close(
        channel_identifier=channel_identifier,
        partner=c1_client.address,
        balance_hash=decode_hex(balance_proof.balance_hash),
        nonce=balance_proof.nonce,
        additional_hash=decode_hex(balance_proof.additional_hash),
        signature=decode_hex(balance_proof.signature),
    )
    assert channel_proxy_1.closed() is True
    assert channel_proxy_2.closed() is True

    events = channel_filter.get_all_entries()
    assert len(events) == 3  # ChannelOpened, ChannelNewDeposit, ChannelClosed

    # check the settlement timeouts again
    assert channel_proxy_1.settle_timeout() == channel_proxy_2.settle_timeout()
    assert channel_proxy_1.settle_timeout() == TEST_SETTLE_TIMEOUT_MIN

    # update transfer
    c1_chain.wait_until_block(target_block_number=c1_client.block_number() +
                              TEST_SETTLE_TIMEOUT_MIN, )

    c2_token_network_proxy.settle(
        channel_identifier=channel_identifier,
        transferred_amount=0,
        locked_amount=0,
        locksroot=EMPTY_HASH,
        partner=c1_client.address,
        partner_transferred_amount=transferred_amount,
        partner_locked_amount=0,
        partner_locksroot=EMPTY_HASH,
    )
    assert channel_proxy_1.settled() is True
    assert channel_proxy_2.settled() is True

    events = channel_filter.get_all_entries()

    assert len(
        events
    ) == 4  # ChannelOpened, ChannelNewDeposit, ChannelClosed, ChannelSettled
示例#17
0
def test_payment_channel_proxy_basics(
        token_network_proxy,
        private_keys,
        token_proxy,
        chain_id,
        web3,
        contract_manager,
):
    token_network_address = to_canonical_address(token_network_proxy.proxy.contract.address)

    c1_client = JSONRPCClient(web3, private_keys[1])
    c1_chain = BlockChainService(private_keys[1], c1_client)
    c2_client = JSONRPCClient(web3, private_keys[2])
    c1_token_network_proxy = TokenNetwork(
        jsonrpc_client=c1_client,
        token_network_address=token_network_address,
        contract_manager=contract_manager,
    )
    c2_token_network_proxy = TokenNetwork(
        jsonrpc_client=c2_client,
        token_network_address=token_network_address,
        contract_manager=contract_manager,
    )

    start_block = web3.eth.blockNumber

    # create a channel
    channel_identifier = c1_token_network_proxy.new_netting_channel(
        c2_client.address,
        TEST_SETTLE_TIMEOUT_MIN,
    )
    assert channel_identifier is not None

    # create channel proxies
    channel_proxy_1 = PaymentChannel(
        token_network=c1_token_network_proxy,
        channel_identifier=channel_identifier,
        contract_manager=contract_manager,
    )
    channel_proxy_2 = PaymentChannel(
        token_network=c2_token_network_proxy,
        channel_identifier=channel_identifier,
        contract_manager=contract_manager,
    )

    channel_filter = channel_proxy_1.all_events_filter(
        from_block=start_block,
        to_block='latest',
    )

    assert channel_proxy_1.channel_identifier == channel_identifier
    assert channel_proxy_2.channel_identifier == channel_identifier

    assert channel_proxy_1.opened() is True
    assert channel_proxy_2.opened() is True

    # check the settlement timeouts
    assert channel_proxy_1.settle_timeout() == channel_proxy_2.settle_timeout()
    assert channel_proxy_1.settle_timeout() == TEST_SETTLE_TIMEOUT_MIN

    events = channel_filter.get_all_entries()
    assert len(events) == 1  # ChannelOpened

    # test deposits
    initial_token_balance = 100
    token_proxy.transfer(c1_client.address, initial_token_balance)
    initial_balance_c1 = token_proxy.balance_of(c1_client.address)
    assert initial_balance_c1 == initial_token_balance
    initial_balance_c2 = token_proxy.balance_of(c2_client.address)
    assert initial_balance_c2 == 0

    # actual deposit
    channel_proxy_1.set_total_deposit(10)

    events = channel_filter.get_all_entries()
    assert len(events) == 2  # ChannelOpened, ChannelNewDeposit

    # balance proof by c2
    transferred_amount = 3
    balance_proof = BalanceProof(
        channel_identifier=channel_identifier,
        token_network_address=to_checksum_address(token_network_address),
        nonce=1,
        chain_id=chain_id,
        transferred_amount=transferred_amount,
    )
    balance_proof.signature = encode_hex(eth_sign(
        privkey=encode_hex(private_keys[1]),
        data=balance_proof.serialize_bin(),
    ))
    # correct close
    c2_token_network_proxy.close(
        channel_identifier=channel_identifier,
        partner=c1_client.address,
        balance_hash=decode_hex(balance_proof.balance_hash),
        nonce=balance_proof.nonce,
        additional_hash=decode_hex(balance_proof.additional_hash),
        signature=decode_hex(balance_proof.signature),
    )
    assert channel_proxy_1.closed() is True
    assert channel_proxy_2.closed() is True

    events = channel_filter.get_all_entries()
    assert len(events) == 3  # ChannelOpened, ChannelNewDeposit, ChannelClosed

    # check the settlement timeouts again
    assert channel_proxy_1.settle_timeout() == channel_proxy_2.settle_timeout()
    assert channel_proxy_1.settle_timeout() == TEST_SETTLE_TIMEOUT_MIN

    # update transfer
    wait_until_block(c1_chain, c1_client.block_number() + TEST_SETTLE_TIMEOUT_MIN)

    c2_token_network_proxy.settle(
        channel_identifier=channel_identifier,
        transferred_amount=0,
        locked_amount=0,
        locksroot=EMPTY_HASH,
        partner=c1_client.address,
        partner_transferred_amount=transferred_amount,
        partner_locked_amount=0,
        partner_locksroot=EMPTY_HASH,
    )
    assert channel_proxy_1.settled() is True
    assert channel_proxy_2.settled() is True

    events = channel_filter.get_all_entries()

    assert len(events) == 4  # ChannelOpened, ChannelNewDeposit, ChannelClosed, ChannelSettled
示例#18
0
def test_payment_channel_outdated_channel_close(
        token_network_proxy,
        private_keys,
        chain_id,
        web3,
        contract_manager,
):
    token_network_address = to_canonical_address(token_network_proxy.proxy.contract.address)

    partner = privatekey_to_address(private_keys[0])

    client = JSONRPCClient(web3, private_keys[1])
    chain = BlockChainService(private_keys[1], client)
    token_network_proxy = TokenNetwork(
        jsonrpc_client=client,
        token_network_address=token_network_address,
        contract_manager=contract_manager,
    )
    start_block = web3.eth.blockNumber

    # create a channel
    channel_identifier = token_network_proxy.new_netting_channel(
        partner,
        TEST_SETTLE_TIMEOUT_MIN,
    )
    assert channel_identifier is not None

    # create channel proxies
    channel_proxy_1 = PaymentChannel(
        token_network=token_network_proxy,
        channel_identifier=channel_identifier,
        contract_manager=contract_manager,
    )

    channel_filter = channel_proxy_1.all_events_filter(
        from_block=start_block,
        to_block='latest',
    )

    assert channel_proxy_1.channel_identifier == channel_identifier

    assert channel_proxy_1.opened() is True

    # balance proof by c1
    balance_proof = BalanceProof(
        channel_identifier=channel_identifier,
        token_network_address=to_checksum_address(token_network_address),
        nonce=0,
        chain_id=chain_id,
        transferred_amount=0,
    )
    balance_proof.signature = encode_hex(eth_sign(
        privkey=encode_hex(private_keys[0]),
        data=balance_proof.serialize_bin(),
    ))
    # correct close
    token_network_proxy.close(
        channel_identifier=channel_identifier,
        partner=partner,
        balance_hash=bytes(32),
        nonce=balance_proof.nonce,
        additional_hash=bytes(32),
        signature=decode_hex(balance_proof.signature),
    )
    assert channel_proxy_1.closed() is True

    events = channel_filter.get_all_entries()
    assert len(events) == 2  # ChannelOpened, ChannelClosed

    # check the settlement timeouts again
    assert channel_proxy_1.settle_timeout() == TEST_SETTLE_TIMEOUT_MIN

    # update transfer
    wait_until_block(chain, client.block_number() + TEST_SETTLE_TIMEOUT_MIN)

    token_network_proxy.settle(
        channel_identifier=channel_identifier,
        transferred_amount=0,
        locked_amount=0,
        locksroot=EMPTY_HASH,
        partner=partner,
        partner_transferred_amount=0,
        partner_locked_amount=0,
        partner_locksroot=EMPTY_HASH,
    )
    assert channel_proxy_1.settled() is True

    events = channel_filter.get_all_entries()

    assert len(events) == 3  # ChannelOpened, ChannelClosed, ChannelSettled

    # Create a new channel with a different identifier
    # create a channel
    new_channel_identifier = token_network_proxy.new_netting_channel(
        partner,
        TEST_SETTLE_TIMEOUT_MIN,
    )
    assert new_channel_identifier is not None
    # create channel proxies
    channel_proxy_2 = PaymentChannel(
        token_network=token_network_proxy,
        channel_identifier=new_channel_identifier,
        contract_manager=contract_manager,
    )

    assert channel_proxy_2.channel_identifier == new_channel_identifier
    assert channel_proxy_2.opened() is True

    with pytest.raises(ChannelOutdatedError):
        token_network_proxy.close(
            channel_identifier=channel_identifier,
            partner=partner,
            balance_hash=bytes(32),
            nonce=balance_proof.nonce,
            additional_hash=bytes(32),
            signature=decode_hex(balance_proof.signature),
        )
示例#19
0
def test_token_network_proxy(token_network_proxy, private_keys, token_proxy,
                             chain_id, web3, contract_manager):
    assert token_network_proxy.settlement_timeout_min(
    ) == TEST_SETTLE_TIMEOUT_MIN
    assert token_network_proxy.settlement_timeout_max(
    ) == TEST_SETTLE_TIMEOUT_MAX

    token_network_address = to_canonical_address(
        token_network_proxy.proxy.contract.address)

    c1_signer = LocalSigner(private_keys[1])
    c1_client = JSONRPCClient(web3, private_keys[1])
    c1_chain = BlockChainService(jsonrpc_client=c1_client,
                                 contract_manager=contract_manager)
    c2_client = JSONRPCClient(web3, private_keys[2])
    c1_token_network_proxy = TokenNetwork(
        jsonrpc_client=c1_client,
        token_network_address=token_network_address,
        contract_manager=contract_manager,
    )
    c2_token_network_proxy = TokenNetwork(
        jsonrpc_client=c2_client,
        token_network_address=token_network_address,
        contract_manager=contract_manager,
    )

    initial_token_balance = 100
    token_proxy.transfer(c1_client.address, initial_token_balance)
    token_proxy.transfer(c2_client.address, initial_token_balance)

    initial_balance_c1 = token_proxy.balance_of(c1_client.address)
    assert initial_balance_c1 == initial_token_balance
    initial_balance_c2 = token_proxy.balance_of(c2_client.address)
    assert initial_balance_c2 == initial_token_balance

    # instantiating a new channel - test basic assumptions
    assert (c1_token_network_proxy._channel_exists_and_not_settled(
        participant1=c1_client.address,
        participant2=c2_client.address,
        block_identifier="latest",
    ) is False)

    channel_identifier = c1_token_network_proxy._call_and_check_result(
        "latest",
        "getChannelIdentifier",
        to_checksum_address(c1_client.address),
        to_checksum_address(c2_client.address),
    )
    assert channel_identifier == 0

    msg = "Zero is not a valid channel_identifier identifier, ValueError must be " "raised."
    with pytest.raises(ValueError, message=msg):
        assert c1_token_network_proxy.channel_is_opened(
            participant1=c1_client.address,
            participant2=c2_client.address,
            block_identifier="latest",
            channel_identifier=0,
        )

    msg = "Zero is not a valid channel_identifier identifier. ValueError must be " "raised."
    with pytest.raises(ValueError, message=msg):
        assert c1_token_network_proxy.channel_is_closed(
            participant1=c1_client.address,
            participant2=c2_client.address,
            block_identifier="latest",
            channel_identifier=0,
        )

    msg = ("Opening a channel with a settle_timeout lower then token "
           "network's minimum will fail. This must be validated and the "
           "transaction must not be sent.")
    with pytest.raises(InvalidSettleTimeout, message=msg):
        c1_token_network_proxy.new_netting_channel(
            partner=c2_client.address,
            settle_timeout=TEST_SETTLE_TIMEOUT_MIN - 1,
            given_block_identifier="latest",
        )

    msg = ("Opening a channel with a settle_timeout larger then token "
           "network's maximum will fail. This must be validated and the "
           "transaction must not be sent.")
    with pytest.raises(InvalidSettleTimeout, message=msg):
        c1_token_network_proxy.new_netting_channel(
            partner=c2_client.address,
            settle_timeout=TEST_SETTLE_TIMEOUT_MAX + 1,
            given_block_identifier="latest",
        )

    msg = (
        "Opening a channel with itself is not allow. This must be validated and "
        "the transaction must not be sent.")
    with pytest.raises(SamePeerAddress, message=msg):
        c1_token_network_proxy.new_netting_channel(
            partner=c1_client.address,
            settle_timeout=TEST_SETTLE_TIMEOUT_MIN,
            given_block_identifier="latest",
        )

    msg = "Trying a deposit to an inexisting channel must fail."
    with pytest.raises(RaidenUnrecoverableError,
                       message=msg,
                       match="does not exist"):
        c1_token_network_proxy.set_total_deposit(
            given_block_identifier="latest",
            channel_identifier=1,
            total_deposit=1,
            partner=c2_client.address,
        )

    msg = "Trying to close an inexisting channel must fail."
    match = "The channel was not open at the provided block"
    with pytest.raises(RaidenUnrecoverableError, message=msg, match=match):
        c1_token_network_proxy.close(
            channel_identifier=1,
            partner=c2_client.address,
            balance_hash=EMPTY_HASH,
            nonce=0,
            additional_hash=EMPTY_HASH,
            signature=EMPTY_SIGNATURE,
            given_block_identifier="latest",
        )

    channel_identifier = c1_token_network_proxy.new_netting_channel(
        partner=c2_client.address,
        settle_timeout=TEST_SETTLE_TIMEOUT_MIN,
        given_block_identifier="latest",
    )
    msg = "new_netting_channel did not return a valid channel id"
    assert isinstance(channel_identifier, T_ChannelID), msg

    msg = "multiple channels with the same peer are not allowed"
    with pytest.raises(DuplicatedChannelError, message=msg):
        c1_token_network_proxy.new_netting_channel(
            partner=c2_client.address,
            settle_timeout=TEST_SETTLE_TIMEOUT_MIN,
            given_block_identifier="latest",
        )

    assert (c1_token_network_proxy._channel_exists_and_not_settled(
        participant1=c1_client.address,
        participant2=c2_client.address,
        channel_identifier=channel_identifier,
        block_identifier="latest",
    ) is True)

    assert (c1_token_network_proxy.channel_is_opened(
        participant1=c1_client.address,
        participant2=c2_client.address,
        block_identifier="latest",
        channel_identifier=channel_identifier,
    ) is True)

    msg = "set_total_deposit must fail if the amount exceed the account's balance"
    with pytest.raises(DepositMismatch, message=msg):
        c1_token_network_proxy.set_total_deposit(
            given_block_identifier="latest",
            channel_identifier=channel_identifier,
            total_deposit=initial_token_balance + 1,
            partner=c2_client.address,
        )

    msg = "set_total_deposit must fail with a negative amount"
    with pytest.raises(DepositMismatch):
        c1_token_network_proxy.set_total_deposit(
            given_block_identifier="latest",
            channel_identifier=channel_identifier,
            total_deposit=-1,
            partner=c2_client.address,
        )

    msg = "set_total_deposit must fail with a zero amount"
    with pytest.raises(DepositMismatch):
        c1_token_network_proxy.set_total_deposit(
            given_block_identifier="latest",
            channel_identifier=channel_identifier,
            total_deposit=0,
            partner=c2_client.address,
        )

    c1_token_network_proxy.set_total_deposit(
        given_block_identifier="latest",
        channel_identifier=channel_identifier,
        total_deposit=10,
        partner=c2_client.address,
    )

    transferred_amount = 3
    balance_proof = BalanceProof(
        channel_identifier=channel_identifier,
        token_network_address=to_checksum_address(token_network_address),
        nonce=1,
        chain_id=chain_id,
        transferred_amount=transferred_amount,
    )
    signature = c1_signer.sign(data=balance_proof.serialize_bin())
    balance_proof.signature = encode_hex(signature)

    signature_number = int.from_bytes(signature, "big")
    bit_to_change = random.randint(0, SIGNATURE_SIZE_IN_BITS - 1)
    signature_number_bit_flipped = signature_number ^ (2**bit_to_change)

    invalid_signatures = [
        EMPTY_SIGNATURE,
        b"\x11" * 65,
        signature_number_bit_flipped.to_bytes(len(signature), "big"),
    ]

    msg = "close must fail if the signature is invalid"
    for invalid_signature in invalid_signatures:
        with pytest.raises(RaidenUnrecoverableError, message=msg):
            c2_token_network_proxy.close(
                channel_identifier=channel_identifier,
                partner=c1_client.address,
                balance_hash=decode_hex(balance_proof.balance_hash),
                nonce=balance_proof.nonce,
                additional_hash=decode_hex(balance_proof.additional_hash),
                signature=invalid_signature,
                given_block_identifier="latest",
            )

    blocknumber_prior_to_close = c2_client.block_number()

    c2_token_network_proxy.close(
        channel_identifier=channel_identifier,
        partner=c1_client.address,
        balance_hash=decode_hex(balance_proof.balance_hash),
        nonce=balance_proof.nonce,
        additional_hash=decode_hex(balance_proof.additional_hash),
        signature=decode_hex(balance_proof.signature),
        given_block_identifier="latest",
    )
    assert (c1_token_network_proxy.channel_is_closed(
        participant1=c1_client.address,
        participant2=c2_client.address,
        block_identifier="latest",
        channel_identifier=channel_identifier,
    ) is True)
    assert (c1_token_network_proxy._channel_exists_and_not_settled(
        participant1=c1_client.address,
        participant2=c2_client.address,
        channel_identifier=channel_identifier,
        block_identifier="latest",
    ) is True)

    msg = (
        "given_block_identifier is the block at which the transaction is being  "
        "sent. If the channel is already closed at that block the client code  "
        "has a programming error. An exception is raised for that.")
    with pytest.raises(RaidenUnrecoverableError, message=msg):
        c2_token_network_proxy.close(
            channel_identifier=channel_identifier,
            partner=c1_client.address,
            balance_hash=decode_hex(balance_proof.balance_hash),
            nonce=balance_proof.nonce,
            additional_hash=decode_hex(balance_proof.additional_hash),
            signature=decode_hex(balance_proof.signature),
            given_block_identifier="latest",
        )

    msg = ("The channel cannot be closed two times. If it was not closed at "
           "given_block_identifier but it is closed at the time the proxy is "
           "called an exception must be raised.")
    with pytest.raises(RaidenRecoverableError, message=msg):
        c2_token_network_proxy.close(
            channel_identifier=channel_identifier,
            partner=c1_client.address,
            balance_hash=decode_hex(balance_proof.balance_hash),
            nonce=balance_proof.nonce,
            additional_hash=decode_hex(balance_proof.additional_hash),
            signature=decode_hex(balance_proof.signature),
            given_block_identifier=blocknumber_prior_to_close,
        )

    msg = "depositing to a closed channel must fail"
    match = "setTotalDeposit call will fail. Channel is already closed"
    with pytest.raises(RaidenRecoverableError, message=msg, match=match):
        c2_token_network_proxy.set_total_deposit(
            given_block_identifier=blocknumber_prior_to_close,
            channel_identifier=channel_identifier,
            total_deposit=20,
            partner=c1_client.address,
        )

    c1_chain.wait_until_block(target_block_number=c1_chain.block_number() +
                              TEST_SETTLE_TIMEOUT_MIN)

    invalid_transferred_amount = 1
    msg = "settle with invalid transferred_amount data must fail"
    with pytest.raises(RaidenUnrecoverableError, message=msg):
        c2_token_network_proxy.settle(
            channel_identifier=channel_identifier,
            transferred_amount=invalid_transferred_amount,
            locked_amount=0,
            locksroot=EMPTY_HASH,
            partner=c1_client.address,
            partner_transferred_amount=transferred_amount,
            partner_locked_amount=0,
            partner_locksroot=EMPTY_HASH,
            given_block_identifier="latest",
        )

    c2_token_network_proxy.settle(
        channel_identifier=channel_identifier,
        transferred_amount=0,
        locked_amount=0,
        locksroot=EMPTY_HASH,
        partner=c1_client.address,
        partner_transferred_amount=transferred_amount,
        partner_locked_amount=0,
        partner_locksroot=EMPTY_HASH,
        given_block_identifier="latest",
    )
    assert (c1_token_network_proxy._channel_exists_and_not_settled(
        participant1=c1_client.address,
        participant2=c2_client.address,
        channel_identifier=channel_identifier,
        block_identifier="latest",
    ) is False)
    assert token_proxy.balance_of(c1_client.address) == (initial_balance_c1 -
                                                         transferred_amount)
    assert token_proxy.balance_of(c2_client.address) == (initial_balance_c2 +
                                                         transferred_amount)

    msg = "depositing to a settled channel must fail"
    match = "setTotalDeposit call will fail."
    with pytest.raises(RaidenUnrecoverableError, message=msg, match=match):
        c1_token_network_proxy.set_total_deposit(
            given_block_identifier="latest",
            channel_identifier=channel_identifier,
            total_deposit=10,
            partner=c2_client.address,
        )
示例#20
0
def test_remote_transaction_with_zero_gasprice_is_not_mined(
        web3: Web3, deploy_key: PrivateKey, blockchain_rpc_ports: List[Port],
        blockchain_type: str) -> None:
    """ If the non-local transaction is sent with a gas price set to zero it is
    not mined.
    """
    host = "127.0.0.1"
    miner_rpc_port, rpc_port = blockchain_rpc_ports

    miner_web3 = Web3(HTTPProvider(f"http://{host}:{miner_rpc_port}"))
    miner_client = JSONRPCClient(miner_web3, deploy_key)

    web3 = Web3(HTTPProvider(f"http://{host}:{rpc_port}"))
    client = JSONRPCClient(web3, deploy_key)

    before_deploy_block = client.block_number()
    normal_gas_proxy, _ = deploy_rpc_test_contract(client, "RpcTest")
    num_blocks_to_wait = client.block_number() - before_deploy_block

    gas_price = GasPrice(0)
    gas_price_strategy = make_fixed_gas_price_strategy(gas_price)
    client.web3.eth.setGasPriceStrategy(gas_price_strategy)
    zero_gas_proxy = client.new_contract_proxy(
        abi=normal_gas_proxy.contract.abi,
        contract_address=normal_gas_proxy.contract_address)

    address = normal_gas_proxy.contract_address
    assert len(client.web3.eth.getCode(to_checksum_address(address))) > 0

    check_block = client.get_checking_block()
    gas_estimate = zero_gas_proxy.estimate_gas(check_block, "ret")
    assert gas_estimate, "Gas estimation should not fail here"

    zerogas_txhash = zero_gas_proxy.transact("ret", gas_estimate)

    # wait for how many blocks it took to mine the deployment, since this is a
    # private chain, if the new transaction will be mined it should be roughly
    # in the same time frame (adding two blocks to cover race conditions)
    target_block_number = client.block_number() + num_blocks_to_wait + 2
    while client.block_number() < target_block_number:
        gevent.sleep(0.5)

    miner_zerogas_tx = miner_client.web3.eth.getTransaction(zerogas_txhash)
    miner_zerogas_receipt = miner_client.web3.eth.getTransactionReceipt(
        zerogas_txhash)

    msg = "The transaction was discarded by the miner, there is no transaction and no receipt"
    assert miner_zerogas_tx is None, msg
    assert miner_zerogas_receipt is None, msg

    zerogas_tx = client.web3.eth.getTransaction(zerogas_txhash)
    zerogas_receipt = client.web3.eth.getTransactionReceipt(zerogas_txhash)

    msg = (
        "The transaction was NOT discarded by the original node, because it is a local transaction"
    )
    assert zerogas_tx is not None, msg

    zerogas_receipt = client.web3.eth.getTransactionReceipt(zerogas_txhash)
    msg = "The transaction does NOT have a receipt because the miner rejected it"

    if blockchain_type == "geth":
        assert zerogas_receipt is None, msg
    elif blockchain_type == "parity":
        assert zerogas_receipt["blockNumber"] is None, msg
    else:
        raise RuntimeError(f"Unknown blockchain_type {blockchain_type}")
示例#21
0
def test_payment_channel_proxy_basics(token_network_proxy, token_proxy,
                                      chain_id, private_keys, web3,
                                      contract_manager):
    token_network_address = token_network_proxy.address
    partner = privatekey_to_address(private_keys[0])

    client = JSONRPCClient(web3, private_keys[1])
    proxy_manager = ProxyManager(
        rpc_client=client,
        contract_manager=contract_manager,
        metadata=ProxyManagerMetadata(
            token_network_registry_deployed_at=GENESIS_BLOCK_NUMBER,
            filters_start_at=GENESIS_BLOCK_NUMBER,
        ),
    )
    token_network_proxy = proxy_manager.token_network(
        address=token_network_address)
    start_block = web3.eth.blockNumber

    channel_identifier = token_network_proxy.new_netting_channel(
        partner=partner,
        settle_timeout=TEST_SETTLE_TIMEOUT_MIN,
        given_block_identifier="latest")
    assert channel_identifier is not None

    channel_proxy_1 = proxy_manager.payment_channel(
        canonical_identifier=CanonicalIdentifier(
            chain_identifier=chain_id,
            token_network_address=token_network_address,
            channel_identifier=channel_identifier,
        ))

    channel_filter = channel_proxy_1.all_events_filter(from_block=start_block,
                                                       to_block="latest")

    assert channel_proxy_1.channel_identifier == channel_identifier
    assert channel_proxy_1.opened("latest") is True

    # Test deposit
    initial_token_balance = 100
    token_proxy.transfer(client.address, initial_token_balance)
    assert token_proxy.balance_of(client.address) == initial_token_balance
    assert token_proxy.balance_of(partner) == 0
    channel_proxy_1.set_total_deposit(total_deposit=10,
                                      block_identifier="latest")

    assert len(channel_filter.get_all_entries()
               ) == 2  # ChannelOpened, ChannelNewDeposit
    block_before_close = web3.eth.blockNumber

    empty_balance_proof = BalanceProof(
        channel_identifier=channel_proxy_1.channel_identifier,
        token_network_address=token_network_address,
        balance_hash=encode_hex(EMPTY_BALANCE_HASH),
        nonce=0,
        chain_id=chain_id,
        transferred_amount=0,
    )
    closing_data = (empty_balance_proof.serialize_bin(
        msg_type=MessageTypeId.BALANCE_PROOF) + EMPTY_SIGNATURE)
    channel_proxy_1.close(
        nonce=0,
        balance_hash=EMPTY_HASH,
        additional_hash=EMPTY_HASH,
        non_closing_signature=EMPTY_SIGNATURE,
        closing_signature=LocalSigner(private_keys[1]).sign(data=closing_data),
        block_identifier="latest",
    )
    assert channel_proxy_1.closed("latest") is True
    # ChannelOpened, ChannelNewDeposit, ChannelClosed
    assert len(channel_filter.get_all_entries()) == 3

    # check the settlement timeouts again
    assert channel_proxy_1.settle_timeout() == TEST_SETTLE_TIMEOUT_MIN

    # update transfer -- we need to wait on +1 since we use the latest block on parity for
    # estimate gas and at the time the latest block is the settle timeout block.
    # More info: https://github.com/raiden-network/raiden/pull/3699#discussion_r270477227
    proxy_manager.wait_until_block(target_block_number=client.block_number() +
                                   TEST_SETTLE_TIMEOUT_MIN + 1)

    channel_proxy_1.settle(
        transferred_amount=0,
        locked_amount=0,
        locksroot=LOCKSROOT_OF_NO_LOCKS,
        partner_transferred_amount=0,
        partner_locked_amount=0,
        partner_locksroot=LOCKSROOT_OF_NO_LOCKS,
        block_identifier="latest",
    )
    assert channel_proxy_1.settled("latest") is True
    # ChannelOpened, ChannelNewDeposit, ChannelClosed, ChannelSettled
    assert len(channel_filter.get_all_entries()) == 4

    new_channel_identifier = token_network_proxy.new_netting_channel(
        partner=partner,
        settle_timeout=TEST_SETTLE_TIMEOUT_MIN,
        given_block_identifier="latest")
    assert new_channel_identifier is not None

    channel_proxy_2 = proxy_manager.payment_channel(
        canonical_identifier=CanonicalIdentifier(
            chain_identifier=chain_id,
            token_network_address=token_network_address,
            channel_identifier=new_channel_identifier,
        ))

    assert channel_proxy_2.channel_identifier == new_channel_identifier
    assert channel_proxy_2.opened("latest") is True

    msg = "The channel was already closed, the second call must fail"
    with pytest.raises(RaidenRecoverableError):
        channel_proxy_1.close(
            nonce=0,
            balance_hash=EMPTY_HASH,
            additional_hash=EMPTY_HASH,
            non_closing_signature=EMPTY_SIGNATURE,
            closing_signature=LocalSigner(
                private_keys[1]).sign(data=closing_data),
            block_identifier=block_before_close,
        )
        pytest.fail(msg)

    msg = "The channel is not open at latest, this must raise"
    with pytest.raises(RaidenUnrecoverableError):
        channel_proxy_1.close(
            nonce=0,
            balance_hash=EMPTY_HASH,
            additional_hash=EMPTY_HASH,
            non_closing_signature=EMPTY_SIGNATURE,
            closing_signature=LocalSigner(
                private_keys[1]).sign(data=closing_data),
            block_identifier="latest",
        )
        pytest.fail(msg)

    msg = ("The channel was not opened at the provided block (latest). "
           "This call should never have been attempted.")
    with pytest.raises(BrokenPreconditionError):
        channel_proxy_1.set_total_deposit(total_deposit=20,
                                          block_identifier="latest")
        pytest.fail(msg)
示例#22
0
def setup_raiden(
    matrix_server: str,
    print_step: StepPrinter,
    contracts_version,
    eth_rpc_endpoint: str,
    web3: Web3,
    base_datadir: Path,
    keystore: Path,
) -> RaidenTestSetup:
    print_step("Deploying Raiden contracts")

    client = JSONRPCClient(web3, get_private_key(keystore))
    contract_manager = ContractManager(
        contracts_precompiled_path(contracts_version))

    proxy_manager = ProxyManager(
        rpc_client=client,
        contract_manager=contract_manager,
        metadata=ProxyManagerMetadata(
            token_network_registry_deployed_at=GENESIS_BLOCK_NUMBER,
            filters_start_at=GENESIS_BLOCK_NUMBER,
        ),
    )

    token = deploy_token(
        deploy_client=client,
        contract_manager=contract_manager,
        initial_amount=TokenAmount(1000),
        decimals=0,
        token_name="TKN",
        token_symbol="TKN",
        token_contract_name=CONTRACT_CUSTOM_TOKEN,
    )
    contract_addresses = deploy_smoketest_contracts(
        client=client,
        chain_id=CHAINNAME_TO_ID["smoketest"],
        contract_manager=contract_manager,
        token_address=token.address,
    )
    confirmed_block_identifier = client.get_confirmed_blockhash()
    registry = proxy_manager.token_network_registry(
        TokenNetworkRegistryAddress(
            contract_addresses[CONTRACT_TOKEN_NETWORK_REGISTRY]),
        block_identifier=confirmed_block_identifier,
    )

    registry.add_token(
        token_address=TokenAddress(to_canonical_address(token.address)),
        channel_participant_deposit_limit=TokenAmount(UINT256_MAX),
        token_network_deposit_limit=TokenAmount(UINT256_MAX),
        given_block_identifier=confirmed_block_identifier,
    )

    print_step("Setting up Raiden")
    user_deposit_contract_address = to_checksum_address(
        contract_addresses[CONTRACT_USER_DEPOSIT])

    args = {
        "address": to_checksum_address(TEST_ACCOUNT_ADDRESS),
        "datadir": keystore,
        "eth_rpc_endpoint": eth_rpc_endpoint,
        "gas_price": "fast",
        "keystore_path": keystore,
        "matrix_server": matrix_server,
        "chain_id": str(CHAINNAME_TO_ID["smoketest"]),
        "password_file": click.File()(os.path.join(base_datadir, "pw")),
        "user_deposit_contract_address": user_deposit_contract_address,
        "sync_check": False,
        "environment_type": Environment.DEVELOPMENT,
    }

    # Wait until the secret registry is confirmed, otherwise the RaidenService
    # inialization will fail, needed for the check
    # `check_ethereum_confirmed_block_is_not_pruned`.
    current_block = client.block_number()
    target_block_number = current_block + DEFAULT_NUMBER_OF_BLOCK_CONFIRMATIONS
    while current_block < target_block_number:
        current_block = client.block_number()
        sleep(0.5)

    return RaidenTestSetup(args=args,
                           token=token,
                           contract_addresses=contract_addresses)
示例#23
0
def setup_raiden(
    transport,
    matrix_server,
    print_step,
    contracts_version,
    eth_client,
    eth_rpc_endpoint,
    web3,
    base_datadir,
    keystore,
):
    print_step("Deploying Raiden contracts")

    if eth_client is EthClient.PARITY:
        client = JSONRPCClient(web3,
                               get_private_key(keystore),
                               gas_estimate_correction=lambda gas: gas * 2)
    else:
        client = JSONRPCClient(web3, get_private_key(keystore))
    contract_manager = ContractManager(
        contracts_precompiled_path(contracts_version))

    proxy_manager = ProxyManager(
        rpc_client=client,
        contract_manager=contract_manager,
        metadata=ProxyManagerMetadata(
            token_network_registry_deployed_at=GENESIS_BLOCK_NUMBER,
            filters_start_at=GENESIS_BLOCK_NUMBER,
        ),
    )

    token = deploy_token(
        deploy_client=client,
        contract_manager=contract_manager,
        initial_amount=1000,
        decimals=0,
        token_name="TKN",
        token_symbol="TKN",
        token_contract_name=CONTRACT_HUMAN_STANDARD_TOKEN,
    )
    contract_addresses = deploy_smoketest_contracts(
        client=client,
        chain_id=NETWORKNAME_TO_ID["smoketest"],
        contract_manager=contract_manager,
        token_address=to_canonical_address(token.contract.address),
    )
    registry = proxy_manager.token_network_registry(
        contract_addresses[CONTRACT_TOKEN_NETWORK_REGISTRY])

    registry.add_token(
        token_address=to_canonical_address(token.contract.address),
        channel_participant_deposit_limit=UINT256_MAX,
        token_network_deposit_limit=UINT256_MAX,
        block_identifier=client.get_confirmed_blockhash(),
    )

    print_step("Setting up Raiden")
    tokennetwork_registry_contract_address = to_checksum_address(
        contract_addresses[CONTRACT_TOKEN_NETWORK_REGISTRY])
    secret_registry_contract_address = to_checksum_address(
        contract_addresses[CONTRACT_SECRET_REGISTRY])

    args = {
        "address": to_checksum_address(TEST_ACCOUNT_ADDRESS),
        "datadir": keystore,
        "eth_rpc_endpoint": eth_rpc_endpoint,
        "gas_price": "fast",
        "keystore_path": keystore,
        "matrix_server": matrix_server,
        "network_id": str(NETWORKNAME_TO_ID["smoketest"]),
        "password_file": click.File()(os.path.join(base_datadir, "pw")),
        "tokennetwork_registry_contract_address":
        tokennetwork_registry_contract_address,
        "secret_registry_contract_address": secret_registry_contract_address,
        "sync_check": False,
        "transport": transport,
    }

    service_registry_contract_address = to_checksum_address(
        contract_addresses[CONTRACT_SERVICE_REGISTRY])
    args[
        "service_registry_contract_address"] = service_registry_contract_address

    monitoring_service_contract_address = to_checksum_address(
        contract_addresses[CONTRACT_MONITORING_SERVICE])
    args[
        "monitoring_service_contract_address"] = monitoring_service_contract_address

    one_to_n_contract_address = to_checksum_address(
        contract_addresses[CONTRACT_ONE_TO_N])
    args["one_to_n_contract_address"] = one_to_n_contract_address

    # Wait until the secret registry is confirmed, otherwise the App
    # inialization will fail, needed for the check
    # `check_ethereum_confirmed_block_is_not_pruned`.
    current_block = client.block_number()
    target_block_number = current_block + DEFAULT_NUMBER_OF_BLOCK_CONFIRMATIONS
    while current_block < target_block_number:
        current_block = client.block_number()
        sleep(0.5)

    return {
        "args": args,
        "contract_addresses": contract_addresses,
        "token": token
    }