Beispiel #1
0
def handle_action_transfer_direct(
        token_network_state,
        state_change,
        pseudo_random_generator,
        block_number,
):
    receiver_address = state_change.receiver_address
    channel_state = token_network_state.partneraddresses_to_channels.get(receiver_address)

    if channel_state:
        iteration = channel.state_transition(
            channel_state,
            state_change,
            pseudo_random_generator,
            block_number,
        )
        events = iteration.events
    else:
        failure = EventTransferSentFailed(
            state_change.identifier,
            'Unknown partner channel',
        )
        events = [failure]

    return TransitionResult(token_network_state, events)
Beispiel #2
0
def subdispatch_to_channel_by_id(
        token_network_state,
        state_change,
        pseudo_random_generator,
        block_number,
):
    events = list()

    ids_to_channels = token_network_state.channelidentifiers_to_channels
    channel_state = ids_to_channels.get(state_change.channel_identifier)

    if channel_state:
        result = channel.state_transition(
            channel_state,
            state_change,
            pseudo_random_generator,
            block_number,
        )

        if result.new_state is None:
            del ids_to_channels[state_change.channel_identifier]
        else:
            ids_to_channels[state_change.channel_identifier] = result.new_state

        events.extend(result.events)

    return TransitionResult(token_network_state, events)
def test_initiator_handle_contract_receive_after_channel_closed():
    """ Initiator must accept on-chain secret reveal if the channel is closed.
    However, the off-chain unlock must not be done!

    This will happen because secrets are registered after a channel is closed,
    during the settlement window.
    """
    block_number = 10
    setup = setup_initiator_tests(amount=UNIT_TRANSFER_AMOUNT * 2, block_number=block_number)

    transfer = setup.current_state.initiator.transfer
    assert transfer.lock.secrethash in setup.channel.our_state.secrethashes_to_lockedlocks

    channel_closed = ContractReceiveChannelClosed(
        transaction_hash=factories.make_transaction_hash(),
        transaction_from=factories.make_address(),
        token_network_identifier=setup.channel.token_network_identifier,
        channel_identifier=setup.channel.identifier,
        block_number=block_number,
    )

    channel_close_transition = channel.state_transition(
        channel_state=setup.channel,
        state_change=channel_closed,
        pseudo_random_generator=setup.prng,
        block_number=block_number,
    )
    channel_state = channel_close_transition.new_state

    state_change = ContractReceiveSecretReveal(
        transaction_hash=factories.make_transaction_hash(),
        secret_registry_address=factories.make_address(),
        secrethash=transfer.lock.secrethash,
        secret=UNIT_SECRET,
        block_number=transfer.lock.expiration,
    )

    channel_map = {
        channel_state.identifier: channel_state,
    }
    iteration = initiator_manager.handle_onchain_secretreveal(
        payment_state=setup.current_state,
        state_change=state_change,
        channelidentifiers_to_channels=channel_map,
        pseudo_random_generator=setup.prng,
    )
    secrethash = setup.current_state.initiator.transfer_description.secrethash
    assert secrethash in channel_state.our_state.secrethashes_to_onchain_unlockedlocks

    msg = 'The channel is closed already, the balance proof must not be sent off-chain'
    assert not events.must_contain_entry(iteration.events, SendBalanceProof, {}), msg
Beispiel #4
0
def handle_batch_unlock(
        token_network_state,
        state_change,
        pseudo_random_generator,
        block_number,
):
    participant1 = state_change.participant
    participant2 = state_change.partner

    events = list()
    for channel_state in list(token_network_state.channelidentifiers_to_channels.values()):
        are_addresses_valid1 = (
            channel_state.our_state.address == participant1 and
            channel_state.partner_state.address == participant2
        )
        are_addresses_valid2 = (
            channel_state.our_state.address == participant2 and
            channel_state.partner_state.address == participant1
        )
        is_valid_locksroot = True
        is_valid_channel = (
            (are_addresses_valid1 or are_addresses_valid2) and
            is_valid_locksroot
        )

        if is_valid_channel:
            sub_iteration = channel.state_transition(
                channel_state,
                state_change,
                pseudo_random_generator,
                block_number,
            )
            events.extend(sub_iteration.events)

            if sub_iteration.new_state is None:

                token_network_state.partneraddresses_to_channelidentifiers[
                    channel_state.partner_state.address
                ].remove(channel_state.identifier)

                del token_network_state.channelidentifiers_to_channels[
                    channel_state.identifier
                ]

    return TransitionResult(token_network_state, events)
Beispiel #5
0
def test_channelstate_repeated_contract_balance():
    """Handling the same blockchain event multiple times must change the
    balance only once.
    """
    deposit_block_number = 10
    block_number = deposit_block_number + DEFAULT_NUMBER_OF_CONFIRMATIONS_BLOCK + 1

    our_model1, _ = create_model(70)
    partner_model1, _ = create_model(100)
    channel_state = create_channel_from_models(our_model1, partner_model1)

    deposit_amount = 10
    balance1_new = our_model1.balance + deposit_amount

    deposit_transaction = TransactionChannelNewBalance(
        our_model1.participant_address,
        balance1_new,
        deposit_block_number,
    )
    state_change = ContractReceiveChannelNewBalance(
        channel_state.token_network_identifier,
        channel_state.identifier,
        deposit_transaction,
    )

    our_model2 = our_model1._replace(
        balance=balance1_new,
        distributable=balance1_new,
        contract_balance=balance1_new,
    )
    partner_model2 = partner_model1
    pseudo_random_generator = random.Random()

    for _ in range(10):
        iteration = channel.state_transition(
            deepcopy(channel_state),
            state_change,
            pseudo_random_generator,
            block_number,
        )
        new_state = iteration.new_state

        assert_partner_state(new_state.our_state, new_state.partner_state, our_model2)
        assert_partner_state(new_state.partner_state, new_state.our_state, partner_model2)
Beispiel #6
0
def subdispatch_to_all_channels(
        chain_state: ChainState,
        state_change: StateChange,
        block_number: typing.BlockNumber,
) -> TransitionResult:
    events = list()

    for payment_network in chain_state.identifiers_to_paymentnetworks.values():
        for token_network_state in payment_network.tokenidentifiers_to_tokennetworks.values():
            for channel_state in token_network_state.channelidentifiers_to_channels.values():
                result = channel.state_transition(
                    channel_state,
                    state_change,
                    chain_state.pseudo_random_generator,
                    block_number,
                )
                events.extend(result.events)

    return TransitionResult(chain_state, events)
Beispiel #7
0
def subdispatch_to_all_channels(
        chain_state: ChainState,
        state_change: StateChange,
        block_number: BlockNumber,
) -> TransitionResult:
    events = list()

    for payment_network in chain_state.identifiers_to_paymentnetworks.values():
        for token_network_state in payment_network.tokenidentifiers_to_tokennetworks.values():
            for channel_state in token_network_state.channelidentifiers_to_channels.values():
                result = channel.state_transition(
                    channel_state,
                    state_change,
                    chain_state.pseudo_random_generator,
                    block_number,
                )
                events.extend(result.events)

    return TransitionResult(chain_state, events)
Beispiel #8
0
def test_channelstate_update_contract_balance():
    """A blockchain event for a new balance must increase the respective
    participants balance.
    """
    deposit_block_number = 10
    block_number = deposit_block_number + DEFAULT_NUMBER_OF_CONFIRMATIONS_BLOCK + 1

    our_model1, _ = create_model(70)
    partner_model1, _ = create_model(100)
    channel_state = create_channel_from_models(our_model1, partner_model1)

    deposit_amount = 10
    balance1_new = our_model1.balance + deposit_amount

    deposit_transaction = TransactionChannelNewBalance(
        our_model1.participant_address,
        balance1_new,
        deposit_block_number,
    )
    state_change = ContractReceiveChannelNewBalance(
        channel_state.token_network_identifier,
        channel_state.identifier,
        deposit_transaction,
    )

    pseudo_random_generator = random.Random()
    iteration = channel.state_transition(
        deepcopy(channel_state),
        state_change,
        pseudo_random_generator,
        block_number,
    )
    new_state = iteration.new_state

    our_model2 = our_model1._replace(
        balance=balance1_new,
        distributable=balance1_new,
        contract_balance=balance1_new,
    )
    partner_model2 = partner_model1

    assert_partner_state(new_state.our_state, new_state.partner_state, our_model2)
    assert_partner_state(new_state.partner_state, new_state.our_state, partner_model2)
Beispiel #9
0
def handle_batch_unlock(
    token_network_state: TokenNetworkState,
    state_change: ContractReceiveChannelBatchUnlock,
    pseudo_random_generator: random.Random,
    block_number: BlockNumber,
    block_hash: BlockHash,
):
    participant1 = state_change.participant
    participant2 = state_change.partner

    events = list()
    for channel_state in list(
            token_network_state.channelidentifiers_to_channels.values()):
        are_addresses_valid1 = (channel_state.our_state.address == participant1
                                and channel_state.partner_state.address
                                == participant2)
        are_addresses_valid2 = (channel_state.our_state.address == participant2
                                and channel_state.partner_state.address
                                == participant1)
        is_valid_locksroot = True
        is_valid_channel = ((are_addresses_valid1 or are_addresses_valid2)
                            and is_valid_locksroot)

        if is_valid_channel:
            sub_iteration = channel.state_transition(
                channel_state=channel_state,
                state_change=state_change,
                block_number=block_number,
                block_hash=block_hash,
            )
            events.extend(sub_iteration.events)

            if sub_iteration.new_state is None:

                token_network_state.partneraddresses_to_channelidentifiers[
                    channel_state.partner_state.address].remove(
                        channel_state.identifier)

                del token_network_state.channelidentifiers_to_channels[
                    channel_state.identifier]

    return TransitionResult(token_network_state, events)
Beispiel #10
0
def test_channelstate_decreasing_contract_balance():
    """A blockchain event for a new balance that decrease the balance must be
    ignored.
    """
    deposit_block_number = 10
    block_number = deposit_block_number + DEFAULT_NUMBER_OF_CONFIRMATIONS_BLOCK + 1

    our_model1, _ = create_model(70)
    partner_model1, _ = create_model(100)
    channel_state = create_channel_from_models(our_model1, partner_model1)
    payment_network_identifier = factories.make_address()
    token_address = factories.make_address()

    amount = 10
    balance1_new = our_model1.balance - amount

    deposit_transaction = TransactionChannelNewBalance(
        our_model1.participant_address,
        balance1_new,
        deposit_block_number,
    )
    state_change = ContractReceiveChannelNewBalance(
        payment_network_identifier,
        token_address,
        channel_state.identifier,
        deposit_transaction,
    )

    pseudo_random_generator = random.Random()
    iteration = channel.state_transition(
        deepcopy(channel_state),
        state_change,
        pseudo_random_generator,
        block_number,
    )
    new_state = iteration.new_state

    assert_partner_state(new_state.our_state, new_state.partner_state,
                         our_model1)
    assert_partner_state(new_state.partner_state, new_state.our_state,
                         partner_model1)
Beispiel #11
0
def handle_batch_unlock(
    token_network_state,
    state_change,
    pseudo_random_generator,
    block_number,
):
    participant1 = state_change.participant
    participant2 = state_change.partner

    events = list()
    for channel_state in list(
            token_network_state.channelidentifiers_to_channels.values()):
        are_addresses_valid1 = (channel_state.our_state.address == participant1
                                and channel_state.partner_state.address
                                == participant2)
        are_addresses_valid2 = (channel_state.our_state.address == participant2
                                and channel_state.partner_state.address
                                == participant1)
        is_valid_locksroot = True
        is_valid_channel = ((are_addresses_valid1 or are_addresses_valid2)
                            and is_valid_locksroot)

        if is_valid_channel:
            sub_iteration = channel.state_transition(
                channel_state,
                state_change,
                pseudo_random_generator,
                block_number,
            )
            events.extend(sub_iteration.events)

            if sub_iteration.new_state is None:

                del token_network_state.partneraddresses_to_channels[
                    channel_state.partner_state.address][
                        channel_state.identifier]

                del token_network_state.channelidentifiers_to_channels[
                    channel_state.identifier]

    return TransitionResult(token_network_state, events)
Beispiel #12
0
def handle_receive_transfer_refund(
        token_network_state,
        state_change,
        pseudo_random_generator,
        block_number,
):
    events = list()

    channel_id = state_change.balance_proof.channel_identifier
    channel_state = token_network_state.channelidentifiers_to_channels.get(channel_id)

    if channel_state:
        result = channel.state_transition(
            channel_state,
            state_change,
            pseudo_random_generator,
            block_number,
        )
        events.extend(result.events)

    return TransitionResult(token_network_state, events)
Beispiel #13
0
def subdispatch_to_channel_by_id(
    token_network_state,
    state_change,
    pseudo_random_generator,
    block_number,
):
    events = list()

    ids_to_channels = token_network_state.channelidentifiers_to_channels
    channel_state = ids_to_channels.get(state_change.channel_identifier)

    if channel_state:
        result = channel.state_transition(
            channel_state,
            state_change,
            pseudo_random_generator,
            block_number,
        )
        events.extend(result.events)

    return TransitionResult(token_network_state, events)
Beispiel #14
0
def handle_receive_transfer_refund(
        token_network_state,
        state_change,
        pseudo_random_generator,
        block_number,
):
    events = list()

    channel_id = state_change.balance_proof.channel_address
    channel_state = token_network_state.channelidentifiers_to_channels.get(channel_id)

    if channel_state:
        result = channel.state_transition(
            channel_state,
            state_change,
            pseudo_random_generator,
            block_number,
        )
        events.extend(result.events)

    return TransitionResult(token_network_state, events)
Beispiel #15
0
def test_initiator_lock_expired_must_not_be_sent_if_channel_is_closed():
    """ If the channel is closed there is no rason to send balance proofs
    off-chain, so a remove expired lock must not be sent when the channel is
    closed.
    """
    block_number = 10
    setup = setup_initiator_tests(amount=UNIT_TRANSFER_AMOUNT * 2,
                                  block_number=block_number)

    channel_closed = ContractReceiveChannelClosed(
        transaction_hash=factories.make_transaction_hash(),
        transaction_from=factories.make_address(),
        token_network_identifier=setup.channel.token_network_identifier,
        channel_identifier=setup.channel.identifier,
        block_number=block_number,
    )
    channel_close_transition = channel.state_transition(
        channel_state=setup.channel,
        state_change=channel_closed,
        pseudo_random_generator=setup.prng,
        block_number=block_number,
    )
    channel_state = channel_close_transition.new_state

    expiration_block_number = setup.lock.expiration + DEFAULT_NUMBER_OF_BLOCK_CONFIRMATIONS * 2
    block = Block(
        block_number=expiration_block_number,
        gas_limit=1,
        block_hash=factories.make_transaction_hash(),
    )
    channel_map = {channel_state.identifier: channel_state}
    iteration = initiator_manager.state_transition(
        setup.current_state,
        block,
        channel_map,
        setup.prng,
        expiration_block_number,
    )
    assert events.must_contain_entry(iteration.events, SendLockExpired,
                                     {}) is None
Beispiel #16
0
def subdispatch_to_all_channels(
    chain_state: ChainState,
    state_change: StateChange,
    block_number: BlockNumber,
    block_hash: BlockHash,
) -> TransitionResult[ChainState]:
    events = list()

    for payment_network in chain_state.identifiers_to_paymentnetworks.values():
        for token_network_state in payment_network.tokenidentifiers_to_tokennetworks.values(
        ):
            for channel_state in token_network_state.channelidentifiers_to_channels.values(
            ):
                result = channel.state_transition(
                    channel_state=channel_state,
                    state_change=state_change,
                    block_number=block_number,
                    block_hash=block_hash,
                )
                events.extend(result.events)

    return TransitionResult(chain_state, events)
def test_initiator_lock_expired_must_not_be_sent_if_channel_is_closed():
    """ If the channel is closed there is no rason to send balance proofs
    off-chain, so a remove expired lock must not be sent when the channel is
    closed.
    """
    block_number = 10
    setup = setup_initiator_tests(amount=UNIT_TRANSFER_AMOUNT * 2, block_number=block_number)

    channel_closed = ContractReceiveChannelClosed(
        transaction_hash=factories.make_transaction_hash(),
        transaction_from=factories.make_address(),
        token_network_identifier=setup.channel.token_network_identifier,
        channel_identifier=setup.channel.identifier,
        block_number=block_number,
    )
    channel_close_transition = channel.state_transition(
        channel_state=setup.channel,
        state_change=channel_closed,
        pseudo_random_generator=setup.prng,
        block_number=block_number,
    )
    channel_state = channel_close_transition.new_state

    expiration_block_number = channel.get_sender_expiration_threshold(setup.lock)
    block = Block(
        block_number=expiration_block_number,
        gas_limit=1,
        block_hash=factories.make_transaction_hash(),
    )
    channel_map = {channel_state.identifier: channel_state}
    iteration = initiator_manager.state_transition(
        setup.current_state,
        block,
        channel_map,
        setup.prng,
        expiration_block_number,
    )
    assert events.must_contain_entry(iteration.events, SendLockExpired, {}) is None
Beispiel #18
0
def subdispatch_to_all_channels(
    chain_state: ChainState,
    state_change: StateChange,
    block_number: BlockNumber,
    block_hash: BlockHash,
) -> TransitionResult[ChainState]:
    events = list()

    for token_network_registry in chain_state.identifiers_to_tokennetworkregistries.values():
        for (
            token_network_state
        ) in token_network_registry.tokennetworkaddresses_to_tokennetworks.values():
            for channel_state in token_network_state.channelidentifiers_to_channels.values():
                result = channel.state_transition(
                    channel_state=channel_state,
                    state_change=state_change,
                    block_number=block_number,
                    block_hash=block_hash,
                    pseudo_random_generator=chain_state.pseudo_random_generator,
                )
                events.extend(result.events)

    return TransitionResult(chain_state, events)
Beispiel #19
0
def test_channelstate_repeated_contract_balance():
    """Handling the same blockchain event multiple times must change the
    balance only once.
    """
    block_number = 10

    our_model1, _ = create_model(70)
    partner_model1, _ = create_model(100)
    channel_state = create_channel_from_models(our_model1, partner_model1)

    deposit_amount = 10
    balance1_new = our_model1.balance + deposit_amount
    state_change = ContractReceiveChannelNewBalance(
        channel_state.identifier,
        our_model1.participant_address,
        balance1_new,
    )

    our_model2 = our_model1._replace(
        balance=balance1_new,
        distributable=balance1_new,
        contract_balance=balance1_new,
    )
    partner_model2 = partner_model1

    for _ in range(10):
        iteration = channel.state_transition(
            deepcopy(channel_state),
            state_change,
            block_number,
        )
        new_state = iteration.new_state

        assert_partner_state(new_state.our_state, new_state.partner_state,
                             our_model2)
        assert_partner_state(new_state.partner_state, new_state.our_state,
                             partner_model2)
Beispiel #20
0
def handle_action_transfer_direct(
    payment_network_identifier,
    token_network_state,
    state_change,
    pseudo_random_generator,
    block_number,
):
    receiver_address = state_change.receiver_address
    channels = [
        token_network_state.channelidentifiers_to_channels[channel_id]
        for channel_id in token_network_state.
        partneraddresses_to_channelidentifiers[receiver_address]
    ]
    channel_states = views.filter_channels_by_status(
        channels,
        [CHANNEL_STATE_UNUSABLE],
    )
    if channel_states:
        iteration = channel.state_transition(
            channel_states[-1],
            state_change,
            pseudo_random_generator,
            block_number,
        )
        events = iteration.events
    else:
        failure = EventPaymentSentFailed(
            payment_network_identifier,
            state_change.token_network_identifier,
            state_change.identifier,
            receiver_address,
            'Unknown partner channel',
        )
        events = [failure]

    return TransitionResult(token_network_state, events)
Beispiel #21
0
def test_channelstate_update_contract_balance():
    """A blockchain event for a new balance must increase the respective
    participants balance.
    """
    block_number = 10

    our_model1, _ = create_model(70)
    partner_model1, _ = create_model(100)
    channel_state = create_channel_from_models(our_model1, partner_model1)

    deposit_amount = 10
    balance1_new = our_model1.balance + deposit_amount
    state_change = ContractReceiveChannelNewBalance(
        channel_state.identifier,
        our_model1.participant_address,
        balance1_new,
    )

    iteration = channel.state_transition(
        deepcopy(channel_state),
        state_change,
        block_number,
    )
    new_state = iteration.new_state

    our_model2 = our_model1._replace(
        balance=balance1_new,
        distributable=balance1_new,
        contract_balance=balance1_new,
    )
    partner_model2 = partner_model1

    assert_partner_state(new_state.our_state, new_state.partner_state,
                         our_model2)
    assert_partner_state(new_state.partner_state, new_state.our_state,
                         partner_model2)
Beispiel #22
0
def test_deposit_must_wait_for_confirmation():
    block_number = 10
    confirmed_deposit_block_number = block_number + DEFAULT_NUMBER_OF_CONFIRMATIONS_BLOCK + 1

    our_model1, _ = create_model(0)
    partner_model1, _ = create_model(0)
    channel_state = create_channel_from_models(our_model1, partner_model1)
    payment_network_identifier = factories.make_address()
    token_address = factories.make_address()

    deposit_amount = 10
    balance1_new = our_model1.balance + deposit_amount
    our_model2 = our_model1._replace(
        balance=balance1_new,
        distributable=balance1_new,
        contract_balance=balance1_new,
    )
    partner_model2 = partner_model1

    assert channel_state.our_state.contract_balance == 0
    assert channel_state.partner_state.contract_balance == 0

    deposit_transaction = TransactionChannelNewBalance(
        channel_state.our_state.address,
        deposit_amount,
        block_number,
    )
    new_balance = ContractReceiveChannelNewBalance(
        payment_network_identifier,
        token_address,
        channel_state.identifier,
        deposit_transaction,
    )
    pseudo_random_generator = random.Random()
    iteration = channel.state_transition(
        deepcopy(channel_state),
        new_balance,
        pseudo_random_generator,
        block_number,
    )
    unconfirmed_state = iteration.new_state

    for block_number in range(block_number, confirmed_deposit_block_number):
        unconfirmed_block = Block(block_number)
        iteration = channel.state_transition(
            deepcopy(unconfirmed_state),
            unconfirmed_block,
            pseudo_random_generator,
            block_number,
        )
        unconfirmed_state = iteration.new_state

        assert_partner_state(
            unconfirmed_state.our_state,
            unconfirmed_state.partner_state,
            our_model1,
        )
        assert_partner_state(
            unconfirmed_state.partner_state,
            unconfirmed_state.our_state,
            partner_model1,
        )

    confirmed_block = Block(confirmed_deposit_block_number)
    iteration = channel.state_transition(
        deepcopy(unconfirmed_state),
        confirmed_block,
        pseudo_random_generator,
        confirmed_deposit_block_number,
    )
    confirmed_state = iteration.new_state

    assert_partner_state(confirmed_state.our_state, confirmed_state.partner_state, our_model2)
    assert_partner_state(confirmed_state.partner_state, confirmed_state.our_state, partner_model2)
Beispiel #23
0
def test_channel_cleared_after_two_unlocks():
    our_model, _ = create_model(balance=700, merkletree_width=1)
    partner_model, partner_key1 = create_model(balance=700, merkletree_width=1)
    channel_state = create_channel_from_models(our_model, partner_model, partner_key1)
    block_number = 1
    block_hash = make_block_hash()

    def make_unlock(unlock_end, partner_end):
        batch_unlock = ContractReceiveChannelBatchUnlock(
            transaction_hash=make_transaction_hash(),
            canonical_identifier=channel_state.canonical_identifier,
            participant=partner_end.address,
            partner=unlock_end.address,
            locksroot=unlock_end.balance_proof.locksroot,
            unlocked_amount=10,
            returned_tokens=0,
            block_number=block_number,
            block_hash=block_hash,
        )
        return batch_unlock

    settle_channel = ContractReceiveChannelSettled(
        transaction_hash=make_transaction_hash(),
        canonical_identifier=channel_state.canonical_identifier,
        our_onchain_locksroot=merkleroot(channel_state.our_state.merkletree),
        partner_onchain_locksroot=merkleroot(channel_state.partner_state.merkletree),
        block_number=1,
        block_hash=make_block_hash(),
    )
    iteration = channel.state_transition(channel_state, settle_channel, block_number, block_hash)

    msg = "both participants have pending locks, merkleroot must not be empty"
    assert iteration.new_state.our_state.onchain_locksroot is not EMPTY_MERKLE_ROOT, msg
    assert iteration.new_state.partner_state.onchain_locksroot is not EMPTY_MERKLE_ROOT, msg

    batch_unlock = make_unlock(channel_state.our_state, channel_state.partner_state)
    iteration = channel.state_transition(
        iteration.new_state, batch_unlock, block_number, block_hash
    )
    msg = "all of our locks has been unlocked, onchain state must be updated"
    assert iteration.new_state.our_state.onchain_locksroot is EMPTY_MERKLE_ROOT, msg
    msg = "partner has pending locks, the merkleroot must not be cleared"
    assert iteration.new_state.partner_state.onchain_locksroot is not EMPTY_MERKLE_ROOT, msg
    msg = "partner locksroot is not unlocked, channel should not have been cleaned"
    assert iteration.new_state is not None, msg

    # processing the same unlock twice must not count
    iteration = channel.state_transition(
        iteration.new_state, batch_unlock, block_number, block_hash
    )
    msg = "partner has pending locks, the merkleroot must not be cleared"
    assert iteration.new_state.partner_state.onchain_locksroot is not EMPTY_MERKLE_ROOT, msg
    msg = "partner locksroot is not unlocked, channel should not have been cleaned"
    assert iteration.new_state is not None, msg

    iteration = channel.state_transition(
        iteration.new_state,
        make_unlock(channel_state.partner_state, channel_state.our_state),
        block_number,
        block_hash,
    )
    msg = "all unlocks have been done, channel must be cleared"
    assert iteration.new_state is None, msg
Beispiel #24
0
def test_withdraw_lock_with_a_large_expiration(
        tester_registry_address,
        deposit,
        tester_channels,
        tester_chain,
        tester_token,
        settle_timeout,
):

    """ Withdraw must accept a lock that expires after the settlement period. """
    pkey0, pkey1, nettingchannel, channel0, channel1 = tester_channels[0]
    address0 = privatekey_to_address(pkey0)
    address1 = privatekey_to_address(pkey1)
    pseudo_random_generator = random.Random()

    initial_balance0 = tester_token.balanceOf(address0, sender=pkey0)
    initial_balance1 = tester_token.balanceOf(address1, sender=pkey0)

    # use a really large expiration
    lock_expiration = tester_chain.block.number + settle_timeout * 5

    # work around for the python expiration validation
    bad_block_number = lock_expiration - 10
    channel.state_transition(
        channel0,
        Block(bad_block_number),
        pseudo_random_generator,
        bad_block_number,
    )

    lock_amount = 29
    secret = sha3(b'test_withdraw_lock_with_a_large_expiration')
    lock_secrethash = sha3(secret)
    lock = Lock(
        amount=lock_amount,
        expiration=lock_expiration,
        secrethash=lock_secrethash,
    )
    mediated0 = make_mediated_transfer(
        tester_registry_address,
        channel0,
        channel1,
        address0,
        address1,
        lock,
        pkey0,
        secret,
    )

    nettingchannel.close(sender=pkey0)

    mediated0_hash = sha3(mediated0.packed().data[:-65])
    nettingchannel.updateTransfer(
        mediated0.nonce,
        mediated0.transferred_amount,
        mediated0.locksroot,
        mediated0_hash,
        mediated0.signature,
        sender=pkey1,
    )

    unlock_proofs = channel.get_known_unlocks(channel1.partner_state)
    proof = unlock_proofs[0]

    nettingchannel.withdraw(
        proof.lock_encoded,
        b''.join(proof.merkle_proof),
        proof.secret,
        sender=pkey1,
    )

    tester_chain.mine(number_of_blocks=settle_timeout + 1)
    nettingchannel.settle(sender=pkey0)

    balance0 = initial_balance0 + deposit - lock_amount
    balance1 = initial_balance1 + deposit + lock_amount
    assert tester_token.balanceOf(address0, sender=pkey0) == balance0
    assert tester_token.balanceOf(address1, sender=pkey0) == balance1
    assert tester_token.balanceOf(nettingchannel.address, sender=pkey0) == 0
Beispiel #25
0
def test_withdraw(
        tester_registry_address,
        deposit,
        settle_timeout,
        reveal_timeout,
        tester_channels,
        tester_chain,
        tester_token,
):

    pkey0, pkey1, nettingchannel, channel0, channel1 = tester_channels[0]
    pseudo_random_generator = random.Random()

    address0 = privatekey_to_address(pkey0)
    address1 = privatekey_to_address(pkey1)

    initial_balance0 = tester_token.balanceOf(address0, sender=pkey0)
    initial_balance1 = tester_token.balanceOf(address1, sender=pkey0)

    lock_amount = 31
    lock_expiration = tester_chain.block.number + reveal_timeout + 5
    secret = b'secretsecretsecretsecretsecretse'
    secrethash = sha3(secret)
    new_block = Block(tester_chain.block.number)
    channel.state_transition(
        channel0,
        new_block,
        pseudo_random_generator,
        new_block.block_number,
    )
    channel.state_transition(
        channel1,
        new_block,
        pseudo_random_generator,
        new_block.block_number,
    )
    lock0 = Lock(lock_amount, lock_expiration, secrethash)

    mediated0 = make_mediated_transfer(
        tester_registry_address,
        channel0,
        channel1,
        address0,
        address1,
        lock0,
        pkey0,
        secret,
    )

    # withdraw the pending transfer sent to us by our partner
    lock_state = lockstate_from_lock(mediated0.lock)
    proof = channel.compute_proof_for_lock(
        channel1.partner_state,
        secret,
        lock_state,
    )

    mediated0_hash = sha3(mediated0.packed().data[:-65])
    nettingchannel.close(
        mediated0.nonce,
        mediated0.transferred_amount,
        mediated0.locksroot,
        mediated0_hash,
        mediated0.signature,
        sender=pkey1,
    )

    tester_chain.mine(number_of_blocks=1)

    nettingchannel.withdraw(
        proof.lock_encoded,
        b''.join(proof.merkle_proof),
        proof.secret,
        sender=pkey1,
    )

    tester_chain.mine(number_of_blocks=settle_timeout + 1)
    nettingchannel.settle(sender=pkey0)

    balance0 = initial_balance0 + deposit - lock0.amount
    balance1 = initial_balance1 + deposit + lock0.amount
    assert tester_token.balanceOf(address0, sender=pkey0) == balance0
    assert tester_token.balanceOf(address1, sender=pkey0) == balance1
    assert tester_token.balanceOf(nettingchannel.address, sender=pkey0) == 0
Beispiel #26
0
def test_withdraw_both_participants(
        tester_registry_address,
        deposit,
        settle_timeout,
        reveal_timeout,
        tester_channels,
        tester_chain,
        tester_token,
):

    pkey0, pkey1, nettingchannel, channel0, channel1 = tester_channels[0]
    pseudo_random_generator = random.Random()

    address0 = privatekey_to_address(pkey0)
    address1 = privatekey_to_address(pkey1)

    initial_balance0 = tester_token.balanceOf(address0, sender=pkey0)
    initial_balance1 = tester_token.balanceOf(address1, sender=pkey0)

    secret = b'secretsecretsecretsecretsecretse'
    secrethash = sha3(secret)

    lock_amount = 31
    lock01_expiration = tester_chain.block.number + settle_timeout - 1 * reveal_timeout
    lock10_expiration = tester_chain.block.number + settle_timeout - 2 * reveal_timeout

    new_block = Block(tester_chain.block.number)
    channel.state_transition(
        channel0,
        new_block,
        pseudo_random_generator,
        new_block.block_number,
    )
    channel.state_transition(
        channel1,
        new_block,
        pseudo_random_generator,
        new_block.block_number,
    )

    # using the same secrethash and amount is intentional
    lock01 = Lock(lock_amount, lock01_expiration, secrethash)
    lock10 = Lock(lock_amount, lock10_expiration, secrethash)

    mediated01 = make_mediated_transfer(
        tester_registry_address,
        channel0,
        channel1,
        address0,
        address1,
        lock01,
        pkey0,
        secret,
    )

    mediated10 = make_mediated_transfer(
        tester_registry_address,
        channel1,
        channel0,
        address1,
        address0,
        lock10,
        pkey1,
        secret,
    )

    mediated01_hash = sha3(mediated01.packed().data[:-65])
    nettingchannel.close(
        mediated01.nonce,
        mediated01.transferred_amount,
        mediated01.locksroot,
        mediated01_hash,
        mediated01.signature,
        sender=pkey1,
    )
    tester_chain.mine(number_of_blocks=1)

    mediated10_hash = sha3(mediated10.packed().data[:-65])
    nettingchannel.updateTransfer(
        mediated10.nonce,
        mediated10.transferred_amount,
        mediated10.locksroot,
        mediated10_hash,
        mediated10.signature,
        sender=pkey0,
    )
    tester_chain.mine(number_of_blocks=1)

    lock_state01 = lockstate_from_lock(mediated01.lock)
    proof01 = channel.compute_proof_for_lock(
        channel1.partner_state,
        secret,
        lock_state01,
    )
    nettingchannel.withdraw(
        proof01.lock_encoded,
        b''.join(proof01.merkle_proof),
        proof01.secret,
        sender=pkey1,
    )

    lock_state10 = lockstate_from_lock(mediated10.lock)
    proof10 = channel.compute_proof_for_lock(
        channel0.partner_state,
        secret,
        lock_state10,
    )
    nettingchannel.withdraw(
        proof10.lock_encoded,
        b''.join(proof10.merkle_proof),
        proof10.secret,
        sender=pkey0,
    )

    tester_chain.mine(number_of_blocks=settle_timeout + 1)
    nettingchannel.settle(sender=pkey0)

    balance0 = initial_balance0 + deposit - lock01.amount + lock10.amount
    balance1 = initial_balance1 + deposit + lock01.amount - lock10.amount
    assert tester_token.balanceOf(address0, sender=pkey0) == balance0
    assert tester_token.balanceOf(address1, sender=pkey0) == balance1
    assert tester_token.balanceOf(nettingchannel.address, sender=pkey0) == 0
Beispiel #27
0
def test_withdraw_expired_lock(
        tester_registry_address,
        reveal_timeout,
        tester_channels,
        tester_chain,
):

    pkey0, pkey1, nettingchannel, channel0, channel1 = tester_channels[0]
    pseudo_random_generator = random.Random()

    lock_timeout = reveal_timeout + 5
    lock_expiration = tester_chain.block.number + lock_timeout
    secret = b'expiredlockexpiredlockexpiredloc'
    secrethash = sha3(secret)
    new_block = Block(tester_chain.block.number)
    channel.state_transition(
        channel0,
        new_block,
        pseudo_random_generator,
        new_block.block_number,
    )
    channel.state_transition(
        channel1,
        new_block,
        pseudo_random_generator,
        new_block.block_number,
    )
    lock1 = Lock(amount=31, expiration=lock_expiration, secrethash=secrethash)

    mediated0 = make_mediated_transfer(
        tester_registry_address,
        channel1,
        channel0,
        privatekey_to_address(pkey0),
        privatekey_to_address(pkey1),
        lock1,
        pkey1,
        secret,
    )

    mediated0_hash = sha3(mediated0.packed().data[:-65])
    nettingchannel.close(
        mediated0.nonce,
        mediated0.transferred_amount,
        mediated0.locksroot,
        mediated0_hash,
        mediated0.signature,
        sender=pkey0,
    )

    # expire the lock
    tester_chain.mine(number_of_blocks=lock_timeout + 1)

    unlock_proofs = channel.get_known_unlocks(channel0.partner_state)
    proof = unlock_proofs[0]

    with pytest.raises(TransactionFailed):
        nettingchannel.withdraw(
            proof.lock_encoded,
            b''.join(proof.merkle_proof),
            proof.secret,
            sender=pkey0,
        )
Beispiel #28
0
def test_settle_with_locked_mediated_transfer_for_closing_party(
        deposit, settle_timeout, reveal_timeout, tester_chain, tester_channels,
        tester_token):
    """ Test settle with a locked mediated transfer for the closing address. """

    pkey0, pkey1, nettingchannel, channel0, channel1 = tester_channels[0]
    payment_network_identifier = factories.make_address()
    pseudo_random_generator = random.Random()

    address0 = privatekey_to_address(pkey0)
    address1 = privatekey_to_address(pkey1)

    initial0 = tester_token.balanceOf(address0, sender=pkey0)
    initial1 = tester_token.balanceOf(address1, sender=pkey0)

    transferred_amount0 = 30
    increase_transferred_amount(
        payment_network_identifier,
        channel0,
        channel1,
        transferred_amount0,
        pkey0,
    )

    expiration0 = tester_chain.block.number + reveal_timeout + 5
    new_block = Block(tester_chain.block.number)
    channel.state_transition(
        channel0,
        new_block,
        pseudo_random_generator,
        new_block.block_number,
    )
    channel.state_transition(
        channel1,
        new_block,
        pseudo_random_generator,
        new_block.block_number,
    )
    lock0 = Lock(amount=29, expiration=expiration0, secrethash=sha3(b'lock1'))
    mediated0 = make_mediated_transfer(
        channel0,
        channel1,
        address0,
        address1,
        lock0,
        pkey0,
    )

    mediated0_hash = sha3(mediated0.packed().data[:-65])
    nettingchannel.close(
        mediated0.nonce,
        mediated0.transferred_amount,
        mediated0.locksroot,
        mediated0_hash,
        mediated0.signature,
        sender=pkey1,
    )

    tester_chain.mine(number_of_blocks=settle_timeout + 1)
    nettingchannel.settle(sender=pkey1)

    # the balances only change by transferred_amount because the lock was /not/ unlocked
    balance0 = initial0 + deposit - transferred_amount0
    balance1 = initial1 + transferred_amount0

    assert tester_token.balanceOf(nettingchannel.address, sender=pkey0) == 0
    assert tester_token.balanceOf(address0, sender=pkey0) == balance0
    assert tester_token.balanceOf(address1, sender=pkey0) == balance1
Beispiel #29
0
def test_channel_cleared_after_two_unlocks():
    our_model, _ = create_model(balance=700, num_pending_locks=1)
    partner_model, partner_key1 = create_model(balance=700,
                                               num_pending_locks=1)
    channel_state = create_channel_from_models(our_model, partner_model,
                                               partner_key1)
    block_number = 1
    block_hash = make_block_hash()
    pseudo_random_generator = random.Random()

    def make_unlock(unlock_end, partner_end):
        batch_unlock = ContractReceiveChannelBatchUnlock(
            transaction_hash=make_transaction_hash(),
            canonical_identifier=channel_state.canonical_identifier,
            receiver=partner_end.address,
            sender=unlock_end.address,
            locksroot=unlock_end.balance_proof.locksroot,
            unlocked_amount=10,
            returned_tokens=0,
            block_number=block_number,
            block_hash=block_hash,
        )
        return batch_unlock

    settle_channel = ContractReceiveChannelSettled(
        transaction_hash=make_transaction_hash(),
        canonical_identifier=channel_state.canonical_identifier,
        our_onchain_locksroot=compute_locksroot(
            channel_state.our_state.pending_locks),
        partner_onchain_locksroot=compute_locksroot(
            channel_state.partner_state.pending_locks),
        block_number=1,
        block_hash=make_block_hash(),
    )
    iteration = channel.state_transition(
        channel_state=channel_state,
        state_change=settle_channel,
        block_number=block_number,
        block_hash=block_hash,
        pseudo_random_generator=pseudo_random_generator,
    )

    msg = "both participants have pending locks, locksroot must not represent the empty list"
    assert iteration.new_state.our_state.onchain_locksroot != LOCKSROOT_OF_NO_LOCKS, msg
    assert iteration.new_state.partner_state.onchain_locksroot != LOCKSROOT_OF_NO_LOCKS, msg

    batch_unlock = make_unlock(channel_state.our_state,
                               channel_state.partner_state)
    iteration = channel.state_transition(
        channel_state=iteration.new_state,
        state_change=batch_unlock,
        block_number=block_number,
        block_hash=block_hash,
        pseudo_random_generator=pseudo_random_generator,
    )
    msg = "all of our locks has been unlocked, onchain state must be updated"
    assert iteration.new_state.our_state.onchain_locksroot is LOCKSROOT_OF_NO_LOCKS, msg
    msg = "partner has pending locks, the locksroot must not represent the empty list"
    assert iteration.new_state.partner_state.onchain_locksroot is not LOCKSROOT_OF_NO_LOCKS, msg
    msg = "partner locksroot is not unlocked, channel should not have been cleaned"
    assert iteration.new_state is not None, msg

    # processing the same unlock twice must not count
    iteration = channel.state_transition(
        channel_state=iteration.new_state,
        state_change=batch_unlock,
        block_number=block_number,
        block_hash=block_hash,
        pseudo_random_generator=pseudo_random_generator,
    )
    msg = "partner has pending locks, the locksroot must not represent the empty list"
    assert iteration.new_state.partner_state.onchain_locksroot is not LOCKSROOT_OF_NO_LOCKS, msg
    msg = "partner locksroot is not unlocked, channel should not have been cleaned"
    assert iteration.new_state is not None, msg

    iteration = channel.state_transition(
        channel_state=iteration.new_state,
        state_change=make_unlock(channel_state.partner_state,
                                 channel_state.our_state),
        block_number=block_number,
        block_hash=block_hash,
        pseudo_random_generator=pseudo_random_generator,
    )
    msg = "all unlocks have been done, channel must be cleared"
    assert iteration.new_state is None, msg
Beispiel #30
0
def test_mediated_after_direct_transfer(
    reveal_timeout,
    settle_timeout,
    deposit,
    tester_chain,
    tester_channels,
    tester_token,
):
    """ The transfer types must not change the behavior of the dispute. """

    pkey0, pkey1, nettingchannel, channel0, channel1 = tester_channels[0]
    payment_network_identifier = factories.make_address()
    pseudo_random_generator = random.Random()

    address0 = privatekey_to_address(pkey0)
    address1 = privatekey_to_address(pkey1)

    initial_balance0 = tester_token.balanceOf(address0, sender=pkey0)
    initial_balance1 = tester_token.balanceOf(address1, sender=pkey0)

    first_amount0 = 90
    make_direct_transfer_from_channel(
        payment_network_identifier,
        channel0,
        channel1,
        first_amount0,
        pkey0,
    )

    lock_expiration = tester_chain.block.number + reveal_timeout + 5
    new_block = Block(tester_chain.block.number)
    channel.state_transition(
        channel0,
        new_block,
        pseudo_random_generator,
        new_block.block_number,
    )
    channel.state_transition(
        channel1,
        new_block,
        pseudo_random_generator,
        new_block.block_number,
    )
    lock1 = Lock(amount=31,
                 expiration=lock_expiration,
                 secrethash=sha3(b'lock2'))
    second_mediated0 = make_mediated_transfer(
        payment_network_identifier,
        channel0,
        channel1,
        address0,
        address1,
        lock1,
        pkey0,
    )

    nettingchannel.close(sender=pkey0)

    second_mediated0_hash = sha3(second_mediated0.packed().data[:-65])
    nettingchannel.updateTransfer(
        second_mediated0.nonce,
        second_mediated0.transferred_amount,
        second_mediated0.locksroot,
        second_mediated0_hash,
        second_mediated0.signature,
        sender=pkey1,
    )

    tester_chain.mine(number_of_blocks=settle_timeout + 1)
    nettingchannel.settle(sender=pkey0)

    # the balances only change by transferred_amount because the lock was /not/ unlocked
    balance0 = initial_balance0 + deposit - first_amount0
    balance1 = initial_balance1 + deposit + first_amount0

    assert tester_token.balanceOf(nettingchannel.address, sender=pkey1) == 0
    assert tester_token.balanceOf(address0, sender=pkey0) == balance0
    assert tester_token.balanceOf(address1, sender=pkey1) == balance1
Beispiel #31
0
def test_settle_two_locked_mediated_transfer_messages(
    deposit,
    settle_timeout,
    reveal_timeout,
    tester_chain,
    tester_channels,
    tester_token,
):

    pkey0, pkey1, nettingchannel, channel0, channel1 = tester_channels[0]
    payment_network_identifier = factories.make_address()
    pseudo_random_generator = random.Random()

    address0 = privatekey_to_address(pkey0)
    address1 = privatekey_to_address(pkey1)

    initial_balance0 = tester_token.balanceOf(address0, sender=pkey0)
    initial_balance1 = tester_token.balanceOf(address1, sender=pkey1)

    transferred_amount0 = 30
    increase_transferred_amount(
        payment_network_identifier,
        channel0,
        channel1,
        transferred_amount0,
        pkey0,
    )

    transferred_amount1 = 70
    increase_transferred_amount(
        payment_network_identifier,
        channel1,
        channel0,
        transferred_amount1,
        pkey1,
    )

    expiration0 = tester_chain.block.number + reveal_timeout + 5
    new_block = Block(tester_chain.block.number)
    channel.state_transition(
        channel0,
        new_block,
        pseudo_random_generator,
        new_block.block_number,
    )
    channel.state_transition(
        channel1,
        new_block,
        pseudo_random_generator,
        new_block.block_number,
    )
    lock0 = Lock(amount=29, expiration=expiration0, secrethash=sha3(b'lock1'))
    mediated0 = make_mediated_transfer(
        payment_network_identifier,
        channel0,
        channel1,
        address0,
        address1,
        lock0,
        pkey0,
    )

    lock_expiration1 = tester_chain.block.number + reveal_timeout + 5
    lock1 = Lock(amount=31,
                 expiration=lock_expiration1,
                 secrethash=sha3(b'lock2'))
    mediated1 = make_mediated_transfer(
        payment_network_identifier,
        channel1,
        channel0,
        address1,
        address0,
        lock1,
        pkey1,
    )

    mediated0_hash = sha3(mediated0.packed().data[:-65])
    nettingchannel.close(
        mediated0.nonce,
        mediated0.transferred_amount,
        mediated0.locksroot,
        mediated0_hash,
        mediated0.signature,
        sender=pkey1,
    )

    mediated1_hash = sha3(mediated1.packed().data[:-65])
    nettingchannel.updateTransfer(
        mediated1.nonce,
        mediated1.transferred_amount,
        mediated1.locksroot,
        mediated1_hash,
        mediated1.signature,
        sender=pkey0,
    )

    tester_chain.mine(number_of_blocks=settle_timeout + 1)
    nettingchannel.settle(sender=pkey0)

    # the balances only change by transferred_amount because the lock was /not/ unlocked
    balance0 = initial_balance0 + deposit - transferred_amount0 + transferred_amount1
    balance1 = initial_balance1 + deposit + transferred_amount0 - transferred_amount1

    assert tester_token.balanceOf(nettingchannel.address, sender=pkey1) == 0
    assert tester_token.balanceOf(address0, sender=pkey0) == balance0
    assert tester_token.balanceOf(address1, sender=pkey1) == balance1