Пример #1
0
def get_channel_state(
        token_address,
        token_network_address,
        reveal_timeout,
        payment_channel_proxy,
        opened_block_number,
):
    channel_details = payment_channel_proxy.detail()

    our_state = NettingChannelEndState(
        channel_details['our_address'],
        channel_details['our_deposit'],
    )
    partner_state = NettingChannelEndState(
        channel_details['partner_address'],
        channel_details['partner_deposit'],
    )

    identifier = payment_channel_proxy.channel_identifier
    settle_timeout = payment_channel_proxy.settle_timeout()

    closed_block_number = None

    # ignore bad open block numbers
    if opened_block_number <= 0:
        return None

    open_transaction = TransactionExecutionStatus(
        None,
        opened_block_number,
        TransactionExecutionStatus.SUCCESS,
    )

    if closed_block_number:
        close_transaction = TransactionExecutionStatus(
            None,
            closed_block_number,
            TransactionExecutionStatus.SUCCESS,
        )
    else:
        close_transaction = None

    # For the current implementation the channel is a smart contract that
    # will be killed on settle.
    settle_transaction = None

    channel = NettingChannelState(
        identifier,
        token_address,
        token_network_address,
        reveal_timeout,
        settle_timeout,
        our_state,
        partner_state,
        open_transaction,
        close_transaction,
        settle_transaction,
    )

    return channel
Пример #2
0
def get_channel_state(token_address, reveal_timeout, netting_channel_proxy):
    channel_details = netting_channel_proxy.detail()

    our_state = NettingChannelEndState(
        channel_details['our_address'],
        channel_details['our_balance'],
    )
    partner_state = NettingChannelEndState(
        channel_details['partner_address'],
        channel_details['partner_balance'],
    )

    identifier = netting_channel_proxy.address
    reveal_timeout = reveal_timeout
    settle_timeout = channel_details['settle_timeout']

    opened_block_number = netting_channel_proxy.opened()
    closed_block_number = netting_channel_proxy.closed()

    # ignore bad open block numbers
    if opened_block_number <= 0:
        return None

    # ignore negative closed block numbers
    if closed_block_number < 0:
        return None

    open_transaction = TransactionExecutionStatus(
        None,
        opened_block_number,
        TransactionExecutionStatus.SUCCESS,
    )

    if closed_block_number:
        close_transaction = TransactionExecutionStatus(
            None,
            closed_block_number,
            TransactionExecutionStatus.SUCCESS,
        )
    else:
        close_transaction = None

    # For the current implementation the channel is a smart contract that
    # will be killed on settle.
    settle_transaction = None

    channel = NettingChannelState(
        identifier,
        token_address,
        reveal_timeout,
        settle_timeout,
        our_state,
        partner_state,
        open_transaction,
        close_transaction,
        settle_transaction,
    )

    return channel
Пример #3
0
    def create(self) -> NettingChannelEndState:
        state = NettingChannelEndState(self.address or make_address(),
                                       self.balance)

        merkletree_leaves = (self.merkletree_leaves
                             or make_merkletree_leaves(self.merkletree_width)
                             or None)
        if merkletree_leaves:
            state.merkletree = MerkleTreeState(
                compute_layers(merkletree_leaves))

        return state
Пример #4
0
def _(properties, defaults=None) -> NettingChannelEndState:
    args = _properties_to_kwargs(
        properties, defaults or NettingChannelEndStateProperties.DEFAULTS)
    state = NettingChannelEndState(args["address"] or make_address(),
                                   args["balance"])

    merkletree_leaves = (args["merkletree_leaves"]
                         or make_merkletree_leaves(args["merkletree_width"])
                         or None)
    if merkletree_leaves:
        state.merkletree = MerkleTreeState(compute_layers(merkletree_leaves))

    return state
Пример #5
0
def _(properties, defaults=None) -> NettingChannelEndState:
    args = _properties_to_kwargs(properties, defaults or NETTING_CHANNEL_END_STATE_DEFAULTS)
    state = NettingChannelEndState(args['address'] or make_address(), args['balance'])

    merkletree_leaves = (
        args['merkletree_leaves'] or
        make_merkletree_leaves(args['merkletree_width']) or
        None
    )
    if merkletree_leaves:
        state.merkletree = MerkleTreeState(compute_layers(merkletree_leaves))

    return state
Пример #6
0
def _(properties, defaults=None) -> NettingChannelEndState:
    args = _properties_to_kwargs(
        properties, defaults or NETTING_CHANNEL_END_STATE_DEFAULTS)
    state = NettingChannelEndState(args['address'] or make_address(),
                                   args['balance'])

    merkletree_leaves = (args['merkletree_leaves']
                         or make_merkletree_leaves(args['merkletree_width'])
                         or None)
    if merkletree_leaves:
        state.merkletree = MerkleTreeState(compute_layers(merkletree_leaves))

    return state
Пример #7
0
def create_channel_from_models(our_model, partner_model):
    """Utility to instantiate state objects used throughout the tests."""
    our_state = NettingChannelEndState(
        our_model.participant_address,
        our_model.balance,
    )
    partner_state = NettingChannelEndState(
        partner_model.participant_address,
        partner_model.balance,
    )

    identifier = factories.make_channel_identifier()
    token_address = factories.make_address()
    token_network_identifier = factories.make_address()
    reveal_timeout = 10
    settle_timeout = 100
    opened_transaction = TransactionExecutionStatus(
        None,
        1,
        TransactionExecutionStatus.SUCCESS,
    )
    closed_transaction = None
    settled_transaction = None

    channel_state = NettingChannelState(
        identifier=identifier,
        chain_id=UNIT_CHAIN_ID,
        token_address=token_address,
        token_network_identifier=token_network_identifier,
        reveal_timeout=reveal_timeout,
        settle_timeout=settle_timeout,
        our_state=our_state,
        partner_state=partner_state,
        open_transaction=opened_transaction,
        close_transaction=closed_transaction,
        settle_transaction=settled_transaction,
    )

    assert_partner_state(
        channel_state.our_state,
        channel_state.partner_state,
        our_model,
    )

    assert_partner_state(
        channel_state.partner_state,
        channel_state.our_state,
        partner_model,
    )

    return channel_state
Пример #8
0
def contractreceivechannelnew_from_event(
        new_channel_details: NewChannelDetails, channel_config: ChannelConfig,
        event: DecodedEvent) -> ContractReceiveChannelNew:
    data = event.event_data
    args = data["args"]
    settle_timeout = args["settle_timeout"]

    block_number = event.block_number
    identifier = args["channel_identifier"]
    token_network_address = TokenNetworkAddress(event.originating_contract)

    our_state = NettingChannelEndState(new_channel_details.our_address,
                                       Balance(0))
    partner_state = NettingChannelEndState(new_channel_details.partner_address,
                                           Balance(0))

    open_transaction = TransactionExecutionStatus(
        None, block_number, TransactionExecutionStatus.SUCCESS)

    # If the node was offline for a long period, the channel may have been
    # closed already, if that is the case during initialization the node will
    # process the other events and update the channel's state
    close_transaction: Optional[TransactionExecutionStatus] = None
    settle_transaction: Optional[TransactionExecutionStatus] = None

    channel_state = NettingChannelState(
        canonical_identifier=CanonicalIdentifier(
            chain_identifier=new_channel_details.chain_id,
            token_network_address=token_network_address,
            channel_identifier=identifier,
        ),
        token_address=new_channel_details.token_address,
        token_network_registry_address=new_channel_details.
        token_network_registry_address,
        reveal_timeout=channel_config.reveal_timeout,
        settle_timeout=settle_timeout,
        fee_schedule=channel_config.fee_schedule,
        our_state=our_state,
        partner_state=partner_state,
        open_transaction=open_transaction,
        close_transaction=close_transaction,
        settle_transaction=settle_transaction,
    )

    return ContractReceiveChannelNew(
        channel_state=channel_state,
        transaction_hash=event.transaction_hash,
        block_number=block_number,
        block_hash=event.block_hash,
    )
Пример #9
0
def test_channelstate_get_unlock_proof():
    number_of_transfers = 100
    lock_amounts = cycle([1, 3, 5, 7, 11])
    lock_secrets = [
        make_secret(i)
        for i in range(number_of_transfers)
    ]

    block_number = 1000
    locked_amount = 0
    settle_timeout = 8
    merkletree_leaves = []
    locked_locks = {}
    unlocked_locks = {}

    for lock_amount, lock_secret in zip(lock_amounts, lock_secrets):
        block_number += 1
        locked_amount += lock_amount

        lock_expiration = block_number + settle_timeout
        lock_secrethash = sha3(lock_secret)
        lock = HashTimeLockState(
            lock_amount,
            lock_expiration,
            lock_secrethash,
        )

        merkletree_leaves.append(lock.lockhash)
        if random.randint(0, 1) == 0:
            locked_locks[lock_secrethash] = lock
        else:
            unlocked_locks[lock_secrethash] = UnlockPartialProofState(lock, lock_secret)

    end_state = NettingChannelEndState(HOP1, 300)
    end_state.secrethashes_to_lockedlocks = locked_locks
    end_state.secrethashes_to_unlockedlocks = unlocked_locks
    end_state.merkletree = MerkleTreeState(compute_layers(merkletree_leaves))

    unlock_proof = channel.get_batch_unlock(end_state)
    assert len(unlock_proof) == len(end_state.merkletree.layers[LEAVES])
    leaves_packed = b''.join(lock.encoded for lock in unlock_proof)

    recomputed_merkle_tree = MerkleTreeState(compute_layers(
        merkle_leaves_from_packed_data(leaves_packed),
    ))
    assert len(recomputed_merkle_tree.layers[LEAVES]) == len(end_state.merkletree.layers[LEAVES])

    computed_merkleroot = merkleroot(recomputed_merkle_tree)
    assert merkleroot(end_state.merkletree) == computed_merkleroot
Пример #10
0
def make_channel_endstate(
    address: typing.Address = EMPTY,
    balance: typing.Balance = EMPTY,
) -> NettingChannelEndState:
    address = if_empty(address, make_address())
    balance = if_empty(balance, 0)
    return NettingChannelEndState(address, balance)
Пример #11
0
def make_endstate(address, balance):
    end_state = NettingChannelEndState(
        address,
        balance,
    )

    return end_state
Пример #12
0
def test_endstate_update_contract_balance():
    """The balance must be monotonic."""
    balance1 = 101
    node_address = factories.make_address()

    end_state = NettingChannelEndState(node_address, balance1)
    assert end_state.contract_balance == balance1

    channel.update_contract_balance(end_state, balance1 - 10)
    assert end_state.contract_balance == balance1

    channel.update_contract_balance(end_state, balance1 + 10)
    assert end_state.contract_balance == balance1 + 10
Пример #13
0
def register_secret_endstate(
    end_state: NettingChannelEndState,
    secret: typing.Secret,
    secrethash: typing.SecretHash,
) -> None:
    if is_lock_locked(end_state, secrethash):
        pendinglock = end_state.secrethashes_to_lockedlocks[secrethash]
        del end_state.secrethashes_to_lockedlocks[secrethash]

        end_state.secrethashes_to_unlockedlocks[
            secrethash] = UnlockPartialProofState(
                pendinglock,
                secret,
            )
Пример #14
0
def test_new_end_state():
    """Test the defaults for an end state object."""
    balance1 = 101
    node_address = factories.make_address()
    end_state = NettingChannelEndState(node_address, balance1)

    lock_secret = sha3(b'test_end_state')
    lock_secrethash = sha3(lock_secret)

    assert channel.is_lock_pending(end_state, lock_secrethash) is False
    assert channel.is_lock_locked(end_state, lock_secrethash) is False
    assert channel.get_next_nonce(end_state) == 1
    assert channel.get_amount_locked(end_state) == 0
    assert not channel.get_known_unlocks(end_state)
    assert merkleroot(end_state.merkletree) == EMPTY_MERKLE_ROOT

    assert not end_state.secrethashes_to_lockedlocks
    assert not end_state.secrethashes_to_unlockedlocks
Пример #15
0
def test_detect_balance_proof_change():
    prng = random.Random()
    block_hash = factories.make_block_hash()
    old = ChainState(
        pseudo_random_generator=prng,
        block_number=1,
        block_hash=block_hash,
        our_address=2,
        chain_id=3,
    )
    new = ChainState(
        pseudo_random_generator=prng,
        block_number=1,
        block_hash=block_hash,
        our_address=2,
        chain_id=3,
    )

    def diff():
        return list(detect_balance_proof_change(old, new))

    assert len(diff()) == 0

    payment_network = PaymentNetworkState(b'x', [])
    payment_network_copy = deepcopy(payment_network)
    new.identifiers_to_paymentnetworks['a'] = payment_network
    assert len(diff()) == 0

    token_network = TokenNetworkState(b'a', b'a')
    token_network_copy = deepcopy(token_network)
    payment_network.tokenidentifiers_to_tokennetworks['a'] = token_network
    assert len(diff()) == 0

    channel = NettingChannelState(
        1,
        0,
        b'a',
        1,
        1,
        1,
        2,
        None,
        None,
        TransactionExecutionStatus(result='success'),
    )
    channel_copy = deepcopy(channel)
    token_network.channelidentifiers_to_channels['a'] = channel
    partner_state = NettingChannelEndState(b'a', 0)
    partner_state_copy = deepcopy(partner_state)
    channel.partner_state = partner_state
    assert len(diff()) == 0

    balance_proof = object()
    partner_state.balance_proof = balance_proof
    assert len(diff()) == 1

    old.identifiers_to_paymentnetworks['a'] = payment_network_copy
    assert len(diff()) == 1

    payment_network_copy.tokenidentifiers_to_tokennetworks[
        'a'] = token_network_copy
    assert len(diff()) == 1

    token_network_copy.channelidentifiers_to_channels['a'] = channel_copy
    channel_copy.partner_state = partner_state_copy
    assert len(diff()) == 1

    channel_copy.partner_state.balance_proof = balance_proof
    assert len(diff()) == 0

    channel_copy.partner_state.balance_proof = object()
    assert len(diff()) == 1

    assert diff() == [balance_proof]
Пример #16
0
def channel_from_nettingcontract(our_key, netting_contract, reveal_timeout):
    """ Create a `channel.Channel` for the `netting_contract`.

    Use this to make sure that both implementations (the smart contract and the
    python code) work in tandem."""
    our_address = privatekey_to_address(our_key)

    token_address_hex = netting_contract.tokenAddress(sender=our_key)
    settle_timeout = netting_contract.settleTimeout(sender=our_key)

    address_balance = netting_contract.addressAndBalance(sender=our_key)
    address1_hex, balance1, address2_hex, balance2 = address_balance

    opened_block_number = netting_contract.opened(sender=our_key)
    closed_block_number = netting_contract.closed(sender=our_key)
    settled_block_number = None

    identifier = address_decoder(netting_contract.address)
    token_address = normalize_address(token_address_hex)
    address1 = normalize_address(address1_hex)
    address2 = normalize_address(address2_hex)

    if our_address == address1:
        our_balance = balance1
        partner_address = address2
        partner_balance = balance2
    else:
        our_balance = balance2
        partner_address = address1
        partner_balance = balance1

    our_state = NettingChannelEndState(
        our_address,
        our_balance,
    )
    partner_state = NettingChannelEndState(
        partner_address,
        partner_balance,
    )

    open_transaction = TransactionExecutionStatus(
        None,
        opened_block_number,
        TransactionExecutionStatus.SUCCESS,
    )

    close_transaction = None
    if closed_block_number:
        close_transaction = TransactionExecutionStatus(
            None,
            closed_block_number,
            TransactionExecutionStatus.SUCCESS,
        )

    settle_transaction = None
    if settled_block_number:
        settle_transaction = TransactionExecutionStatus(
            None,
            settled_block_number,
            TransactionExecutionStatus.SUCCESS,
        )

    channel = NettingChannelState(
        identifier,
        token_address,
        reveal_timeout,
        settle_timeout,
        our_state,
        partner_state,
        open_transaction,
        close_transaction,
        settle_transaction,
    )

    return channel
Пример #17
0
def test_invalid_timeouts():
    token_address = factories.make_address()
    reveal_timeout = 5
    settle_timeout = 10
    identifier = factories.make_address()

    address1 = factories.make_address()
    address2 = factories.make_address()
    balance1 = 10
    balance2 = 10

    opened_transaction = TransactionExecutionStatus(
        None,
        1,
        TransactionExecutionStatus.SUCCESS,
    )
    closed_transaction = None
    settled_transaction = None

    our_state = NettingChannelEndState(address1, balance1)
    partner_state = NettingChannelEndState(address2, balance2)

    # do not allow a reveal timeout larger than the settle timeout
    with pytest.raises(ValueError):
        large_reveal_timeout = 50
        small_settle_timeout = 49

        NettingChannelState(
            identifier,
            token_address,
            large_reveal_timeout,
            small_settle_timeout,
            our_state,
            partner_state,
            opened_transaction,
            closed_transaction,
            settled_transaction,
        )

    # TypeError: 'a', [], {}
    for invalid_value in (-1, 0, 1.1, 1.0):
        with pytest.raises(ValueError):
            NettingChannelState(
                identifier,
                token_address,
                invalid_value,
                settle_timeout,
                our_state,
                partner_state,
                opened_transaction,
                closed_transaction,
                settled_transaction,
            )

        with pytest.raises(ValueError):
            NettingChannelState(
                identifier,
                token_address,
                reveal_timeout,
                invalid_value,
                our_state,
                partner_state,
                opened_transaction,
                closed_transaction,
                settled_transaction,
            )
Пример #18
0
def test_detect_balance_proof_change():
    prng = random.Random()

    block_hash = make_block_hash()
    our_address = make_address()
    empty_chain = ChainState(
        pseudo_random_generator=prng,
        block_number=1,
        block_hash=block_hash,
        our_address=our_address,
        chain_id=3,
    )

    assert empty(detect_balance_proof_change(empty_chain,
                                             empty_chain)), MSG_NO_CHANGE
    assert empty(
        detect_balance_proof_change(empty_chain,
                                    deepcopy(empty_chain))), MSG_NO_CHANGE

    token_network_registry_address = make_address()
    chain_with_registry_no_bp = deepcopy(empty_chain)
    chain_with_registry_no_bp.identifiers_to_tokennetworkregistries[
        token_network_registry_address] = TokenNetworkRegistryState(
            token_network_registry_address, [])

    assert empty(
        detect_balance_proof_change(empty_chain,
                                    chain_with_registry_no_bp)), MSG_NO_CHANGE
    assert empty(
        detect_balance_proof_change(
            chain_with_registry_no_bp,
            deepcopy(chain_with_registry_no_bp))), MSG_NO_CHANGE

    token_network_address = make_address()
    token_address = make_address()

    chain_with_token_network_no_bp = deepcopy(chain_with_registry_no_bp)
    chain_with_token_network_no_bp.identifiers_to_tokennetworkregistries[
        token_network_registry_address].tokennetworkaddresses_to_tokennetworks[
            token_network_address] = TokenNetworkState(
                address=token_network_address,
                token_address=token_address,
                network_graph=TokenNetworkGraphState(token_network_address),
            )
    assert empty(
        detect_balance_proof_change(
            empty_chain, chain_with_token_network_no_bp)), MSG_NO_CHANGE
    assert empty(
        detect_balance_proof_change(
            chain_with_registry_no_bp,
            chain_with_token_network_no_bp)), MSG_NO_CHANGE
    assert empty(
        detect_balance_proof_change(
            chain_with_token_network_no_bp,
            deepcopy(chain_with_token_network_no_bp))), MSG_NO_CHANGE

    partner_address = make_address()
    canonical_identifier = make_canonical_identifier()
    channel_no_bp = NettingChannelState(
        canonical_identifier=canonical_identifier,
        token_address=token_address,
        token_network_registry_address=token_network_registry_address,
        reveal_timeout=1,
        settle_timeout=2,
        our_state=NettingChannelEndState(address=our_address,
                                         contract_balance=1),
        partner_state=NettingChannelEndState(address=partner_address,
                                             contract_balance=0),
        open_transaction=TransactionExecutionStatus(result="success"),
        settle_transaction=None,
        update_transaction=None,
        close_transaction=None,
        fee_schedule=FeeScheduleState(),
    )

    chain_with_channel_no_bp = deepcopy(chain_with_token_network_no_bp)
    chain_with_token_network_no_bp.identifiers_to_tokennetworkregistries[
        token_network_registry_address].tokennetworkaddresses_to_tokennetworks[
            token_network_address].channelidentifiers_to_channels[
                canonical_identifier.channel_identifier] = channel_no_bp

    assert empty(
        detect_balance_proof_change(empty_chain,
                                    chain_with_channel_no_bp)), MSG_NO_CHANGE
    assert empty(
        detect_balance_proof_change(chain_with_registry_no_bp,
                                    chain_with_channel_no_bp)), MSG_NO_CHANGE
    assert empty(
        detect_balance_proof_change(chain_with_token_network_no_bp,
                                    chain_with_channel_no_bp)), MSG_NO_CHANGE
    assert empty(
        detect_balance_proof_change(
            chain_with_channel_no_bp,
            deepcopy(chain_with_channel_no_bp))), MSG_NO_CHANGE

    channel_with_sent_bp = deepcopy(channel_no_bp)
    channel_with_sent_bp.our_state.balance_proof = create(
        BalanceProofUnsignedState)

    chain_with_sent_bp = deepcopy(chain_with_token_network_no_bp)
    chain_with_sent_bp.identifiers_to_tokennetworkregistries[
        token_network_registry_address].tokennetworkaddresses_to_tokennetworks[
            token_network_address].channelidentifiers_to_channels[
                canonical_identifier.channel_identifier] = channel_with_sent_bp

    assert not empty(
        detect_balance_proof_change(
            empty_chain,
            chain_with_sent_bp)), MSG_BALANCE_PROOF_SHOULD_BE_DETECTED
    assert not empty(
        detect_balance_proof_change(
            chain_with_registry_no_bp,
            chain_with_sent_bp)), MSG_BALANCE_PROOF_SHOULD_BE_DETECTED
    assert not empty(
        detect_balance_proof_change(
            chain_with_token_network_no_bp,
            chain_with_sent_bp)), MSG_BALANCE_PROOF_SHOULD_BE_DETECTED
    assert not empty(
        detect_balance_proof_change(
            chain_with_channel_no_bp,
            chain_with_sent_bp)), MSG_BALANCE_PROOF_SHOULD_BE_DETECTED
    assert empty(
        detect_balance_proof_change(
            chain_with_sent_bp, deepcopy(chain_with_sent_bp))), MSG_NO_CHANGE

    channel_with_received_bp = deepcopy(channel_no_bp)
    channel_with_received_bp.partner_state.balance_proof = create(
        BalanceProofUnsignedState)

    chain_with_received_bp = deepcopy(chain_with_token_network_no_bp)
    chain_with_received_bp.identifiers_to_tokennetworkregistries[
        token_network_registry_address].tokennetworkaddresses_to_tokennetworks[
            token_network_address].channelidentifiers_to_channels[
                canonical_identifier.channel_identifier] = channel_with_sent_bp

    # asserting with `channel_with_received_bp` and `channel_with_sent_bp`
    # doesn't make sense, because one of the balance proofs would have to
    # disappear (which is a bug)
    assert not empty(
        detect_balance_proof_change(
            empty_chain,
            chain_with_received_bp)), MSG_BALANCE_PROOF_SHOULD_BE_DETECTED
    assert not empty(
        detect_balance_proof_change(
            chain_with_registry_no_bp,
            chain_with_received_bp)), MSG_BALANCE_PROOF_SHOULD_BE_DETECTED
    assert not empty(
        detect_balance_proof_change(
            chain_with_token_network_no_bp,
            chain_with_received_bp)), MSG_BALANCE_PROOF_SHOULD_BE_DETECTED
    assert not empty(
        detect_balance_proof_change(
            chain_with_channel_no_bp,
            chain_with_received_bp)), MSG_BALANCE_PROOF_SHOULD_BE_DETECTED
    assert empty(
        detect_balance_proof_change(
            chain_with_received_bp,
            deepcopy(chain_with_received_bp))), MSG_NO_CHANGE

    chain_with_sent_and_received_bp = deepcopy(chain_with_token_network_no_bp)
    ta_to_tn = chain_with_sent_and_received_bp.identifiers_to_tokennetworkregistries
    channel_with_sent_and_recived_bp = (
        ta_to_tn[token_network_registry_address].
        tokennetworkaddresses_to_tokennetworks[token_network_address].
        channelidentifiers_to_channels[canonical_identifier.channel_identifier]
    )
    channel_with_sent_and_recived_bp.partner_state.balance_proof = deepcopy(
        channel_with_received_bp.partner_state.balance_proof)
    channel_with_sent_and_recived_bp.our_state.balance_proof = deepcopy(
        channel_with_received_bp.our_state.balance_proof)

    assert not empty(
        detect_balance_proof_change(empty_chain,
                                    chain_with_sent_and_received_bp)
    ), MSG_BALANCE_PROOF_SHOULD_BE_DETECTED
    assert not empty(
        detect_balance_proof_change(chain_with_registry_no_bp,
                                    chain_with_sent_and_received_bp)
    ), MSG_BALANCE_PROOF_SHOULD_BE_DETECTED
    assert not empty(
        detect_balance_proof_change(chain_with_token_network_no_bp,
                                    chain_with_sent_and_received_bp)
    ), MSG_BALANCE_PROOF_SHOULD_BE_DETECTED
    assert not empty(
        detect_balance_proof_change(chain_with_channel_no_bp,
                                    chain_with_sent_and_received_bp)
    ), MSG_BALANCE_PROOF_SHOULD_BE_DETECTED
    assert not empty(
        detect_balance_proof_change(chain_with_received_bp,
                                    chain_with_sent_and_received_bp)
    ), MSG_BALANCE_PROOF_SHOULD_BE_DETECTED
    assert not empty(
        detect_balance_proof_change(chain_with_sent_bp,
                                    chain_with_sent_and_received_bp)
    ), MSG_BALANCE_PROOF_SHOULD_BE_DETECTED
    assert empty(
        detect_balance_proof_change(
            chain_with_sent_and_received_bp,
            deepcopy(chain_with_sent_and_received_bp))), MSG_NO_CHANGE
Пример #19
0
def get_channel_state(
    token_address: TokenAddress,
    payment_network_identifier: PaymentNetworkID,
    token_network_address: TokenNetworkAddress,
    reveal_timeout: BlockTimeout,
    payment_channel_proxy,
    opened_block_number: BlockNumber,
):
    # Here we have to query the latest state because if we query with an older block
    # state (e.g. opened_block_number) the state may have been pruned which will
    # lead to an error.
    latest_block_hash = payment_channel_proxy.client.blockhash_from_blocknumber(
        "latest")
    channel_details = payment_channel_proxy.detail(latest_block_hash)

    our_state = NettingChannelEndState(
        channel_details.participants_data.our_details.address,
        channel_details.participants_data.our_details.deposit,
    )
    partner_state = NettingChannelEndState(
        channel_details.participants_data.partner_details.address,
        channel_details.participants_data.partner_details.deposit,
    )

    identifier = payment_channel_proxy.channel_identifier
    settle_timeout = payment_channel_proxy.settle_timeout()
    closed_block_number = payment_channel_proxy.close_block_number()

    # ignore bad open block numbers
    if opened_block_number <= 0:
        return None

    open_transaction = TransactionExecutionStatus(
        None, opened_block_number, TransactionExecutionStatus.SUCCESS)

    close_transaction: Optional[TransactionExecutionStatus] = None
    if closed_block_number:
        close_transaction = TransactionExecutionStatus(
            None, closed_block_number, TransactionExecutionStatus.SUCCESS)

    # For the current implementation the channel is a smart contract that
    # will be killed on settle.
    settle_transaction = None

    channel = NettingChannelState(
        canonical_identifier=CanonicalIdentifier(
            chain_identifier=channel_details.chain_id,
            token_network_address=token_network_address,
            channel_identifier=identifier,
        ),
        token_address=token_address,
        payment_network_identifier=payment_network_identifier,
        reveal_timeout=reveal_timeout,
        settle_timeout=settle_timeout,
        mediation_fee=MEDIATION_FEE,
        our_state=our_state,
        partner_state=partner_state,
        open_transaction=open_transaction,
        close_transaction=close_transaction,
        settle_transaction=settle_transaction,
    )

    return channel
Пример #20
0
def test_detect_balance_proof_change():
    prng = random.Random()
    block_hash = factories.make_block_hash()
    old = ChainState(
        pseudo_random_generator=prng,
        block_number=1,
        block_hash=block_hash,
        our_address=2,
        chain_id=3,
    )
    new = ChainState(
        pseudo_random_generator=prng,
        block_number=1,
        block_hash=block_hash,
        our_address=2,
        chain_id=3,
    )

    def diff():
        return list(detect_balance_proof_change(old, new))

    assert len(diff()) == 0

    payment_network = PaymentNetworkState(b'x', [])
    payment_network_copy = deepcopy(payment_network)
    new.identifiers_to_paymentnetworks['a'] = payment_network
    assert len(diff()) == 0

    token_network = TokenNetworkState(b'a', b'a')
    token_network_copy = deepcopy(token_network)
    payment_network.tokenidentifiers_to_tokennetworks['a'] = token_network
    assert len(diff()) == 0

    channel = NettingChannelState(
        canonical_identifier=factories.make_canonical_identifier(),
        token_address=b'a',
        payment_network_identifier=1,
        reveal_timeout=1,
        settle_timeout=2,
        mediation_fee=0,
        our_state=None,
        partner_state=None,
        open_transaction=TransactionExecutionStatus(result='success'),
        settle_transaction=None,
        update_transaction=None,
        close_transaction=None,
    )
    channel_copy = deepcopy(channel)
    token_network.channelidentifiers_to_channels['a'] = channel
    our_state = NettingChannelEndState(address=b'b', balance=1)
    our_state_copy = deepcopy(our_state)
    partner_state = NettingChannelEndState(address=b'a', balance=0)
    partner_state_copy = deepcopy(partner_state)

    channel.our_state = our_state
    channel.partner_state = partner_state
    assert len(diff()) == 0

    balance_proof = object()
    partner_state.balance_proof = balance_proof
    assert len(diff()) == 1

    old.identifiers_to_paymentnetworks['a'] = payment_network_copy
    assert len(diff()) == 1

    payment_network_copy.tokenidentifiers_to_tokennetworks[
        'a'] = token_network_copy
    assert len(diff()) == 1

    token_network_copy.channelidentifiers_to_channels['a'] = channel_copy
    channel_copy.partner_state = partner_state_copy
    assert len(diff()) == 1

    channel_copy.partner_state.balance_proof = balance_proof
    assert len(diff()) == 0

    channel_copy.partner_state.balance_proof = object()
    assert len(diff()) == 1
    assert diff() == [balance_proof]

    # check our_state BP changes
    channel_copy.partner_state.balance_proof = balance_proof
    assert len(diff()) == 0

    channel.our_state.balance_proof = object()
    channel_copy.our_state = our_state_copy
    assert len(diff()) == 1
    assert diff() == [channel.our_state.balance_proof]

    channel_copy.our_state.balance_proof = channel.our_state.balance_proof
    assert len(diff()) == 0
Пример #21
0
def get_channel_state(
    token_address,
    payment_network_identifier,
    token_network_address,
    reveal_timeout,
    payment_channel_proxy,
    opened_block_number,
):
    # LEFTODO: Supply a proper block id
    channel_details = payment_channel_proxy.detail('latest')

    our_state = NettingChannelEndState(
        channel_details.participants_data.our_details.address,
        channel_details.participants_data.our_details.deposit,
    )
    partner_state = NettingChannelEndState(
        channel_details.participants_data.partner_details.address,
        channel_details.participants_data.partner_details.deposit,
    )

    identifier = payment_channel_proxy.channel_identifier
    settle_timeout = payment_channel_proxy.settle_timeout()
    closed_block_number = payment_channel_proxy.close_block_number()

    # ignore bad open block numbers
    if opened_block_number <= 0:
        return None

    open_transaction = TransactionExecutionStatus(
        None,
        opened_block_number,
        TransactionExecutionStatus.SUCCESS,
    )

    if closed_block_number:
        close_transaction = TransactionExecutionStatus(
            None,
            closed_block_number,
            TransactionExecutionStatus.SUCCESS,
        )
    else:
        close_transaction = None

    # For the current implementation the channel is a smart contract that
    # will be killed on settle.
    settle_transaction = None

    channel = NettingChannelState(
        identifier=identifier,
        chain_id=channel_details.chain_id,
        token_address=token_address,
        payment_network_identifier=payment_network_identifier,
        token_network_identifier=token_network_address,
        reveal_timeout=reveal_timeout,
        settle_timeout=settle_timeout,
        our_state=our_state,
        partner_state=partner_state,
        open_transaction=open_transaction,
        close_transaction=close_transaction,
        settle_transaction=settle_transaction,
    )

    return channel
Пример #22
0
def update_contract_balance(
    end_state: NettingChannelEndState,
    contract_balance: typing.Balance,
) -> None:
    if contract_balance > end_state.contract_balance:
        end_state.contract_balance = contract_balance
Пример #23
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)