Ejemplo n.º 1
0
def test_secret(iterations=ITERATIONS):
    identifier = 1
    secret = HASH
    msg = Secret(
        identifier,
        secret
    )
    msg.sign(PRIVKEY, ADDRESS)
    run_timeit('Secret', msg, iterations=iterations)
Ejemplo n.º 2
0
def test_secret(iterations=ITERATIONS):
    identifier = 1
    secret = HASH
    amount = 1
    msg = Secret(
        identifier,
        secret,
        amount,
    )
    msg.sign(PRIVKEY, ADDRESS)
    run_timeit('Secret', msg, iterations=iterations)
Ejemplo n.º 3
0
    def create_secret(self, identifier, secret):
        hashlock = sha3(secret)

        from_ = self.our_state

        lock = from_.balance_proof.get_lock_by_hashlock(hashlock)
        lockhashed = sha3(lock.as_bytes)
        leafs = from_.balance_proof.unclaimed_merkletree()
        leafs.remove(lockhashed)

        locksroot_with_pending_lock_removed = Merkletree(
            leafs).merkleroot or EMPTY_MERKLE_ROOT
        transferred_amount = from_.transferred_amount + lock.amount

        nonce = self.get_next_nonce()

        secret = Secret(
            identifier,
            nonce,
            self.channel_address,
            transferred_amount,
            locksroot_with_pending_lock_removed,
            secret,
        )
        return secret
Ejemplo n.º 4
0
def test_receive_hashlocktransfer_unknown(raiden_network, token_addresses):
    app0 = raiden_network[0]
    token_address = token_addresses[0]

    other_key = HOP1_KEY
    other_address = HOP1
    amount = 10
    refund_transfer_message = make_refund_transfer(
        identifier=1,
        nonce=1,
        token=token_address,
        channel=other_address,
        transferred_amount=amount,
        recipient=app0.raiden.address,
        locksroot=UNIT_HASHLOCK,
        amount=amount,
        hashlock=UNIT_HASHLOCK,
    )
    sign_and_inject(refund_transfer_message, other_key, other_address, app0)

    secret = Secret(
        identifier=1,
        nonce=1,
        channel=make_address(),
        transferred_amount=amount,
        locksroot=UNIT_HASHLOCK,
        secret=UNIT_SECRET,
    )
    sign_and_inject(secret, other_key, other_address, app0)

    secret_request_message = SecretRequest(1, UNIT_HASHLOCK, 1)
    sign_and_inject(secret_request_message, other_key, other_address, app0)

    reveal_secret_message = RevealSecret(UNIT_SECRET)
    sign_and_inject(reveal_secret_message, other_key, other_address, app0)
Ejemplo n.º 5
0
def claim_lock(app_chain, identifier, token, secret):
    """ Unlock a pending transfer. """
    secrethash = sha3(secret)
    for from_, to_ in zip(app_chain[:-1], app_chain[1:]):
        from_channel = get_channelstate(from_, to_, token)
        partner_channel = get_channelstate(to_, from_, token)

        unlock_lock = channel.send_unlock(
            from_channel,
            identifier,
            secret,
            secrethash,
        )

        secret_message = Secret(
            unlock_lock.identifier,
            unlock_lock.balance_proof.nonce,
            unlock_lock.balance_proof.channel_address,
            unlock_lock.balance_proof.transferred_amount,
            unlock_lock.balance_proof.locksroot,
            unlock_lock.secret,
        )
        from_.raiden.sign(secret_message)

        balance_proof = balanceproof_from_envelope(secret_message)
        receive_unlock = ReceiveUnlock(
            unlock_lock.secret,
            balance_proof,
        )

        is_valid, msg = channel.handle_unlock(
            partner_channel,
            receive_unlock,
        )
        assert is_valid, msg
Ejemplo n.º 6
0
def test_receive_hashlocktransfer_unknown(raiden_network):
    app0 = raiden_network[0]  # pylint: disable=unbalanced-tuple-unpacking

    token_manager0 = app0.raiden.managers_by_token_address.values()[0]

    other_key = PrivateKey(HASH2, ctx=GLOBAL_CTX, raw=True)
    other_address = privatekey_to_address(other_key.private_key)
    amount = 10
    lock = Lock(amount, 1, HASH)
    refund_transfer = RefundTransfer(identifier=1,
                                     nonce=1,
                                     token=token_manager0.token_address,
                                     transferred_amount=amount,
                                     recipient=app0.raiden.address,
                                     locksroot=HASH,
                                     lock=lock)
    sign_and_send(refund_transfer, other_key, other_address, app0)

    transfer_timeout = TransferTimeout(HASH, HASH)
    sign_and_send(transfer_timeout, other_key, other_address, app0)

    secret = Secret(1, HASH, token_manager0.token_address)
    sign_and_send(secret, other_key, other_address, app0)

    secret_request = SecretRequest(1, HASH, 1)
    sign_and_send(secret_request, other_key, other_address, app0)

    reveal_secret = RevealSecret(HASH)
    sign_and_send(reveal_secret, other_key, other_address, app0)

    # Whenever processing of ConfirmTransfer is implemented test it here
    # too by removing the expectation of an exception
    with pytest.raises(KeyError):
        confirm_transfer = ConfirmTransfer(HASH)
        sign_and_send(confirm_transfer, other_key, other_address, app0)
Ejemplo n.º 7
0
def test_receive_hashlocktransfer_unknown(raiden_network):
    app0 = raiden_network[0]  # pylint: disable=unbalanced-tuple-unpacking

    token_manager0 = app0.raiden.managers_by_token_address.values()[0]

    other_key = PrivateKey(HASH2, ctx=GLOBAL_CTX, raw=True)
    other_address = privatekey_to_address(other_key.private_key)
    amount = 10
    lock = Lock(amount, 1, HASH)
    refund_transfer = RefundTransfer(identifier=1,
                                     nonce=1,
                                     token=token_manager0.token_address,
                                     transferred_amount=amount,
                                     recipient=app0.raiden.address,
                                     locksroot=HASH,
                                     lock=lock)
    sign_and_send(refund_transfer, other_key, other_address, app0)

    secret = Secret(1, HASH, token_manager0.token_address)
    sign_and_send(secret, other_key, other_address, app0)

    secret_request = SecretRequest(1, HASH, 1)
    sign_and_send(secret_request, other_key, other_address, app0)

    reveal_secret = RevealSecret(HASH)
    sign_and_send(reveal_secret, other_key, other_address, app0)
Ejemplo n.º 8
0
def test_receive_hashlocktransfer_unknown(raiden_network):
    app0 = raiden_network[0]  # pylint: disable=unbalanced-tuple-unpacking

    graph0 = app0.raiden.channelgraphs.values()[0]

    other_key = PrivateKey(HASH2)
    other_address = privatekey_to_address(HASH2)
    amount = 10
    lock = Lock(amount, 1, HASH)
    refund_transfer = RefundTransfer(
        identifier=1,
        nonce=1,
        token=graph0.token_address,
        transferred_amount=amount,
        recipient=app0.raiden.address,
        locksroot=HASH,
        lock=lock
    )
    sign_and_send(refund_transfer, other_key, other_address, app0)

    secret = Secret(1, HASH, graph0.token_address)
    sign_and_send(secret, other_key, other_address, app0)

    secret_request = SecretRequest(1, HASH, 1)
    sign_and_send(secret_request, other_key, other_address, app0)

    reveal_secret = RevealSecret(HASH)
    sign_and_send(reveal_secret, other_key, other_address, app0)
Ejemplo n.º 9
0
    def register_secret(self, secret):
        """ Handle a secret that could be received from a Secret message or a
        ChannelSecretRevealed event.
        """
        hashlock = sha3(secret)
        channels_reveal = self.hashlock_channel[hashlock]

        secret_message = Secret(secret)
        self.raiden.sign(secret_message)

        while channels_reveal:
            reveal_to = channels_reveal.pop()

            # send the secret to all channels registered, including the next
            # hop that might be the node that informed us about the secret
            self.raiden.send(reveal_to.partner_state.address, secret_message)

            # update the channel by claiming the locked transfers
            try:
                reveal_to.claim_locked(secret)
            except InvalidSecret:
                log.error('claiming lock failed')

        assert len(self.hashlock_channel[hashlock]) == 0
        del self.hashlock_channel[hashlock]
Ejemplo n.º 10
0
def test_secret(iterations=ITERATIONS):
    identifier = 1
    nonce = 1
    channel = HASH
    transferred_amount = 1
    secret = HASH
    locksroot = ''
    msg = Secret(
        identifier,
        nonce,
        channel,
        transferred_amount,
        locksroot,
        secret,
    )
    msg.sign(PRIVKEY, ADDRESS)
    run_timeit('Secret', msg, iterations=iterations)
def test_secret(iterations=ITERATIONS):
    identifier = 1
    nonce = 1
    channel = HASH
    transferred_amount = 1
    secret = HASH
    locksroot = ''
    msg = Secret(
        identifier,
        nonce,
        channel,
        transferred_amount,
        locksroot,
        secret,
    )
    msg.sign(PRIVKEY, ADDRESS)
    run_timeit('Secret', msg, iterations=iterations)
Ejemplo n.º 12
0
def handle_send_balanceproof(
        raiden: 'RaidenService',
        balance_proof_event: SendBalanceProof):
    secret_message = Secret.from_event(balance_proof_event)
    raiden.sign(secret_message)
    raiden.send_async(
        balance_proof_event.receiver,
        secret_message,
    )
Ejemplo n.º 13
0
def test_receive_secrethashtransfer_unknown(raiden_network, token_addresses):
    app0 = raiden_network[0]
    token_address = token_addresses[0]

    token_network_identifier = views.get_token_network_identifier_by_token_address(
        views.state_from_app(app0),
        app0.raiden.default_registry.address,
        token_address,
    )

    other_key = HOP1_KEY
    other_address = HOP1
    channel_identifier = make_channel_identifier()

    amount = 10
    refund_transfer_message = make_refund_transfer(
        payment_identifier=1,
        nonce=1,
        token_network_address=token_network_identifier,
        token=token_address,
        channel_identifier=channel_identifier,
        transferred_amount=amount,
        recipient=app0.raiden.address,
        locksroot=UNIT_SECRETHASH,
        amount=amount,
        secrethash=UNIT_SECRETHASH,
    )
    sign_and_inject(refund_transfer_message, other_key, other_address, app0)

    secret = Secret(
        chain_id=UNIT_CHAIN_ID,
        message_identifier=random.randint(0, UINT64_MAX),
        payment_identifier=1,
        nonce=1,
        channel_identifier=channel_identifier,
        token_network_address=token_network_identifier,
        transferred_amount=amount,
        locked_amount=0,
        locksroot=UNIT_SECRETHASH,
        secret=UNIT_SECRET,
    )
    sign_and_inject(secret, other_key, other_address, app0)

    secret_request_message = SecretRequest(
        message_identifier=random.randint(0, UINT64_MAX),
        payment_identifier=1,
        secrethash=UNIT_SECRETHASH,
        amount=1,
        expiration=refund_transfer_message.lock.expiration,
    )
    sign_and_inject(secret_request_message, other_key, other_address, app0)

    reveal_secret_message = RevealSecret(
        message_identifier=random.randint(0, UINT64_MAX),
        secret=UNIT_SECRET,
    )
    sign_and_inject(reveal_secret_message, other_key, other_address, app0)
Ejemplo n.º 14
0
    def handle_secret(self, secret):
        """ Handle a secret that could be received from a Secret message or a
        ChannelSecretRevealed event.
        """
        hashlock = sha3(secret)
        channels_reveal = self.hashlock_channel[hashlock]

        secret_message = Secret(secret)
        self.raiden.sign(secret_message)

        while channels_reveal:
            reveal_to = channels_reveal.pop()

            # When a secret is revealed a message could be in-transit
            # containing the older lockroot, for this reason the recipient
            # cannot update it's locksroot at the moment a secret was revealed.
            #
            # The protocol is to register the secret so that it can compute a
            # proof of balance, if necessary, forward the secret to the sender
            # and wait for the update from it. It's the sender duty to order
            # the current in-transit (and possible the transfers in queue)
            # transfers and the secret/locksroot update.
            #
            # The channel and it's queue must be changed in sync, a transfer
            # must not be created and while we update the balance_proof.

            # critical read/write section
            # (relying on the GIL and non-blocking apis instead of an explicit
            # lock).

            # we are the sender, so we can claim the lock/update the locksroot
            # and add the update message into the end of the message queue, all
            # the messages will remain consistent (including the messages
            # in-transit and the ones that are already in the queue)
            if reveal_to.partner_state.balance_proof.is_pending(hashlock):
                reveal_to.claim_lock(secret)
                self.raiden.send_async(reveal_to.partner_state.address,
                                       secret_message)

            # we are the recipient, register the secret so that a balance proof
            # can be generate and reveal the secret to the sender. the asset
            # will be claimed once the secret is received from the sender in
            # the MediatedTransferTask
            elif reveal_to.our_state.balance_proof.is_pending(hashlock):
                reveal_to.register_secret(secret)
                self.raiden.send_async(reveal_to.partner_state.address,
                                       secret_message)

            else:
                log.error('No corresponding hashlock for the given secret.')
            # /critical read/write section

        # delete the list it wont ever be used again (unless we have a sha3
        # collision)
        del self.hashlock_channel[hashlock]
Ejemplo n.º 15
0
def handle_send_balanceproof(
        raiden: 'RaidenService',
        balance_proof_event: SendBalanceProof,
):
    secret_message = Secret.from_event(balance_proof_event)
    raiden.sign(secret_message)
    raiden.protocol.send_async(
        balance_proof_event.queue_name,
        balance_proof_event.recipient,
        secret_message,
    )
Ejemplo n.º 16
0
    def _run(self):  # pylint: disable=method-hidden
        mediated_transfer = self.originating_transfer
        assetmanager = self.transfermanager.assetmanager
        originating_channel = assetmanager.get_channel_by_partner_address(
            mediated_transfer.sender)
        raiden = assetmanager.raiden

        log.debug(
            'END MEDIATED TRANSFER %s -> %s msghash:%s hashlock:%s',
            pex(mediated_transfer.target),
            pex(mediated_transfer.initiator),
            pex(mediated_transfer.hash),
            pex(mediated_transfer.lock.hashlock),
        )

        secret_request = SecretRequest(mediated_transfer.lock.hashlock)
        raiden.sign(secret_request)

        response = self.send_and_wait_valid(raiden, mediated_transfer,
                                            secret_request)

        if response is None:
            timeout_message = originating_channel.create_timeouttransfer_for(
                mediated_transfer)
            raiden.send_async(mediated_transfer.sender, timeout_message)
            self.transfermanager.on_hashlock_result(
                mediated_transfer.lock.hashlock, False)
            return

        # register the secret so that a balance proof can be created but don't
        # claim until our partner has informed us that it's internal state is
        # updated
        originating_channel.register_secret(response.secret)

        secret_message = Secret(response.secret)
        raiden.sign(secret_message)
        raiden.send_async(mediated_transfer.sender, secret_message)

        # wait for the secret from `sender` to claim the lock
        while True:
            response = self.response_message.wait()
            # critical write section
            self.response_message = AsyncResult()
            # /critical write section

            if isinstance(
                    response,
                    Secret) and response.sender == mediated_transfer.sender:
                originating_channel.claim_lock(response.secret)
                self.transfermanager.on_hashlock_result(
                    mediated_transfer.lock.hashlock, True)
                return
Ejemplo n.º 17
0
    def check_path(self, msg, channel):
        if isinstance(msg, CancelTransfer):
            return None  # try with next path
        elif isinstance(msg, TransferTimeout):
            # stale hashlock
            if not self.isinitiator:
                self.raiden.send(self.originating_transfer.sender, msg)
            return False
        elif isinstance(msg, Secret):
            assert self.originating_transfer
            assert msg.hashlock == self.hashlock
            if self.originating_transfer.sender != self.originating_transfer.initiator:
                fwd = Secret(msg.secret)
                self.raiden.sign(fwd)
                self.raiden.send(self.originating_transfer.sender, fwd)
            else:
                log.warning('NOT FORWARDING SECRET TO ININTIATOR')
            return True
        elif isinstance(msg, SecretRequest):
            assert self.isinitiator

            # lock.target can easilly be tampered, ensure that we are receiving
            # the SecretRequest from the correct node
            if msg.sender != self.target:
                log.error('Tampered SecretRequest', secret_request=msg)
                return None  # try the next available path

            # TODO: the lock.amount can easily be tampered, check the `target`
            # locked transfer has the correct `amount`
            msg = Secret(self.secret)
            self.raiden.sign(msg)
            self.raiden.send(self.target, msg)

            # TODO: Guarantee that `target` received the secret, otherwise we
            # updated the channel and the first hop will receive the asset, but
            # none of the other channels will make the transfer
            channel.claim_locked(self.secret)
            return True
        return None
Ejemplo n.º 18
0
 def _run(self):  # pylint: disable=method-hidden
     self.event = AsyncResult()  # http://www.gevent.org/gevent.event.html
     timeout = self.timeout
     msg = self.event.wait(timeout)
     if not msg:
         log.error('TIMEOUT! ' * 5)
         # TransferTimeout is of no use, SecretRequest was for sender
         return self.on_completion(False)
     assert isinstance(msg, Secret)
     assert msg.hashlock == self.hashlock
     fwd = Secret(msg.secret)
     self.raiden.sign(fwd)
     self.raiden.send(self.recipient, fwd)
     return self.on_completion(True)
Ejemplo n.º 19
0
    def create_secret(self, identifier, secret):
        from_ = self.our_state
        to_ = self.partner_state

        self.release_lock(secret)
        locksroot_with_pending_lock_removed = to_.balance_proof.merkleroot_for_unclaimed(
        )

        secret = Secret(
            identifier,
            from_.nonce,
            self.channel_address,
            from_.transferred_amount,
            locksroot_with_pending_lock_removed,
            secret,
        )
        return secret
Ejemplo n.º 20
0
def test_receive_secrethashtransfer_unknown(raiden_network, token_addresses):
    app0 = raiden_network[0]
    token_address = token_addresses[0]

    other_key = HOP1_KEY
    other_address = HOP1
    amount = 10
    refund_transfer_message = make_refund_transfer(
        payment_identifier=1,
        nonce=1,
        registry_address=app0.raiden.default_registry.address,
        token=token_address,
        channel=other_address,
        transferred_amount=amount,
        recipient=app0.raiden.address,
        locksroot=UNIT_SECRETHASH,
        amount=amount,
        secrethash=UNIT_SECRETHASH,
    )
    sign_and_inject(refund_transfer_message, other_key, other_address, app0)

    secret = Secret(
        message_identifier=random.randint(0, UINT64_MAX),
        payment_identifier=1,
        nonce=1,
        channel=make_address(),
        transferred_amount=amount,
        locked_amount=0,
        locksroot=UNIT_SECRETHASH,
        secret=UNIT_SECRET,
    )
    sign_and_inject(secret, other_key, other_address, app0)

    secret_request_message = SecretRequest(
        message_identifier=random.randint(0, UINT64_MAX),
        payment_identifier=1,
        secrethash=UNIT_SECRETHASH,
        amount=1,
    )
    sign_and_inject(secret_request_message, other_key, other_address, app0)

    reveal_secret_message = RevealSecret(
        message_identifier=random.randint(0, UINT64_MAX),
        secret=UNIT_SECRET,
    )
    sign_and_inject(reveal_secret_message, other_key, other_address, app0)
Ejemplo n.º 21
0
def claim_lock(app_chain, payment_identifier, token_network_identifier,
               secret):
    """ Unlock a pending transfer. """
    secrethash = sha3(secret)
    for from_, to_ in zip(app_chain[:-1], app_chain[1:]):
        from_channel = get_channelstate(from_, to_, token_network_identifier)
        partner_channel = get_channelstate(to_, from_,
                                           token_network_identifier)

        unlock_lock = channel.send_unlock(
            from_channel,
            random.randint(0, UINT64_MAX),
            payment_identifier,
            secret,
            secrethash,
        )

        secret_message = Secret(
            chain_id=unlock_lock.balance_proof.chain_id,
            message_identifier=unlock_lock.message_identifier,
            payment_identifier=unlock_lock.payment_identifier,
            nonce=unlock_lock.balance_proof.nonce,
            token_network_address=partner_channel.token_network_identifier,
            channel_identifier=unlock_lock.balance_proof.channel_identifier,
            transferred_amount=unlock_lock.balance_proof.transferred_amount,
            locked_amount=unlock_lock.balance_proof.locked_amount,
            locksroot=unlock_lock.balance_proof.locksroot,
            secret=unlock_lock.secret,
        )
        from_.raiden.sign(secret_message)

        balance_proof = balanceproof_from_envelope(secret_message)
        receive_unlock = ReceiveUnlock(
            message_identifier=random.randint(0, UINT64_MAX),
            secret=unlock_lock.secret,
            balance_proof=balance_proof,
        )

        is_valid, _, msg = channel.handle_unlock(
            partner_channel,
            receive_unlock,
        )
        assert is_valid, msg
Ejemplo n.º 22
0
    def handle_secret(self, secret):
        """ Handle a secret that could be received from a Secret message or a
        ChannelSecretRevealed event.
        """
        hashlock = sha3(secret)
        channels_reveal = self.hashlock_channel[hashlock]

        secret_message = Secret(secret)
        self.raiden.sign(secret_message)

        while channels_reveal:
            reveal_to = channels_reveal.pop()

            # critical read/write section
            # The channel and it's queue must be changed in sync, a transfer
            # must not be created and the balance_proof must not be changed
            # while we update the state (relaying on the GIL and non-blocing
            # apis instead of an explicit lock).

            # If we created the mediated transfer update our local state and
            # notify our partner to do the same, this operation needs to be
            # synchronized with the merkletree of locks to inhibit locksroot
            # conflicts.
            if reveal_to.partner_state.balance_proof.is_pending(hashlock):
                reveal_to.claim_lock(secret)
                self.raiden.send_async(reveal_to.partner_state.address,
                                       secret_message)

            # Otherwise we received the transfer, reveal it to the
            # originating_channel so that it can update it's internal state and
            # allow us to update too.
            elif reveal_to.our_state.balance_proof.is_pending(hashlock):
                # register the secret so that a balance proof can be generated
                reveal_to.register_secret(secret)
                self.raiden.send_async(reveal_to.partner_state.address,
                                       secret_message)

            else:
                log.error('No corresponding hashlock for the given secret.')

        # delete the list it wont ever be used again (unless we have a sha3
        # colision)
        del self.hashlock_channel[hashlock]
Ejemplo n.º 23
0
    def create_secret(self, identifier, secret):
        hashlock = sha3(secret)

        from_ = self.our_state

        lock = from_.get_lock_by_hashlock(hashlock)
        locksroot_with_pending_lock_removed = from_.compute_merkleroot_without(
            lock)
        transferred_amount = from_.transferred_amount + lock.amount

        nonce = self.get_next_nonce()

        secret = Secret(
            identifier,
            nonce,
            self.channel_address,
            transferred_amount,
            locksroot_with_pending_lock_removed,
            secret,
        )
        return secret
def test_receive_hashlocktransfer_unknown(raiden_network):
    app0 = raiden_network[0]  # pylint: disable=unbalanced-tuple-unpacking

    graph0 = app0.raiden.token_to_channelgraph.values()[0]

    other_key = PrivateKey(HASH2)
    other_address = privatekey_to_address(HASH2)
    amount = 10
    refund_transfer = make_refund_transfer(
        identifier=1,
        nonce=1,
        token=graph0.token_address,
        channel=other_address,
        transferred_amount=amount,
        recipient=app0.raiden.address,
        locksroot=UNIT_HASHLOCK,
        amount=amount,
        hashlock=UNIT_HASHLOCK,
    )
    sign_and_send(refund_transfer, other_key, other_address, app0)

    secret = Secret(
        identifier=1,
        nonce=1,
        channel=make_address(),
        transferred_amount=amount,
        locksroot=UNIT_HASHLOCK,
        secret=UNIT_SECRET,
    )
    sign_and_send(secret, other_key, other_address, app0)

    secret_request = SecretRequest(1, UNIT_HASHLOCK, 1)
    sign_and_send(secret_request, other_key, other_address, app0)

    reveal_secret = RevealSecret(UNIT_SECRET)
    sign_and_send(reveal_secret, other_key, other_address, app0)
Ejemplo n.º 25
0
    def _secret(self, identifier, secret, partner_secret_message, hashlock):
        channels_list = self.hashlock_channel[hashlock]
        channels_to_remove = list()

        # Dont use the partner_secret_message.token since it might not match with the
        # current token manager
        our_secret_message = Secret(identifier, secret, self.token_address)
        self.raiden.sign(our_secret_message)

        revealsecret_message = RevealSecret(secret)
        self.raiden.sign(revealsecret_message)

        for channel in channels_list:
            # critical read/write section
            # - the `release_lock` might raise if the `balance_proof` changes
            #   after the check
            # - a message created before the lock is release must be added in
            #   the message queue before `our_secret_message`
            # We are relying on the GIL and non-blocking apis instead of an
            # explicit lock.

            if channel.partner_state.balance_proof.is_unclaimed(hashlock):
                # we are the sender, so we can release the lock once the secret
                # is known and add the update message into the end of the
                # message queue, all the messages will remain consistent
                # (including the messages in-transit and the ones that are
                # already in the queue)
                channel.release_lock(secret)

                # notify our partner that our state is updated and it can
                # withdraw the token
                self.raiden.send_async(channel.partner_state.address,
                                       our_secret_message)

                channels_to_remove.append(channel)

            # we are the recipient, we can only withdraw the token if a secret
            # message is received from the correct sender and token address, so
            # withdraw if a valid message is received otherwise register the
            # secret and reveal the secret to channel patner.
            if channel.our_state.balance_proof.is_unclaimed(hashlock):
                # partner_secret_message might be None
                if partner_secret_message:
                    valid_sender = partner_secret_message.sender == channel.partner_state.address
                    valid_token = partner_secret_message.token == channel.token_address

                    if valid_sender and valid_token:
                        channel.withdraw_lock(secret)
                        channels_to_remove.append(channel)
                    else:
                        # assume our partner does not know the secret and reveal it
                        channel.register_secret(secret)
                        self.raiden.send_async(channel.partner_state.address,
                                               revealsecret_message)
                else:
                    channel.register_secret(secret)
                    self.raiden.send_async(channel.partner_state.address,
                                           revealsecret_message)
            # /critical read/write section

        for channel in channels_to_remove:
            channels_list.remove(channel)

        # delete the list from defaultdict, it wont be used again
        if len(channels_list) == 0:
            del self.hashlock_channel[hashlock]
Ejemplo n.º 26
0
def test_interwoven_transfers():
    """Can keep doing transactions even if not all secrets have been released."""
    number_of_transfers = 100
    balance_for_all_transfers = 11 * number_of_transfers

    lock_amounts = cycle([1, 3, 5, 7, 11])
    lock_secrets = [
        format(i, '>032').encode()
        for i in range(number_of_transfers)
    ]

    our_model, _ = create_model(70)
    partner_model, privkey2 = create_model(balance_for_all_transfers)
    channel_state = create_channel_from_models(our_model, partner_model)

    block_number = 1000
    nonce = 0
    transferred_amount = 0
    our_model_current = our_model
    partner_model_current = partner_model

    for i, (lock_amount, lock_secret) in enumerate(zip(lock_amounts, lock_secrets)):
        nonce += 1
        block_number += 1

        lock_expiration = block_number + channel_state.settle_timeout - 1
        lock_secrethash = sha3(lock_secret)
        lock = HashTimeLockState(
            lock_amount,
            lock_expiration,
            lock_secrethash,
        )

        merkletree_leaves = list(partner_model_current.merkletree_leaves)
        merkletree_leaves.append(lock.lockhash)

        partner_model_current = partner_model_current._replace(
            distributable=partner_model_current.distributable - lock_amount,
            amount_locked=partner_model_current.amount_locked + lock_amount,
            next_nonce=partner_model_current.next_nonce + 1,
            merkletree_leaves=merkletree_leaves,
        )

        receive_lockedtransfer = make_receive_transfer_mediated(
            channel_state,
            privkey2,
            nonce,
            transferred_amount,
            lock,
            merkletree_leaves=merkletree_leaves,
        )

        is_valid, msg = channel.handle_receive_lockedtransfer(
            channel_state,
            receive_lockedtransfer,
        )
        assert is_valid, msg

        assert_partner_state(
            channel_state.our_state,
            channel_state.partner_state,
            our_model_current,
        )
        assert_partner_state(
            channel_state.partner_state,
            channel_state.our_state,
            partner_model_current,
        )

        # claim a transaction at every other iteration, leaving the current one
        # in place
        if i % 2:
            # Update our model:
            # - Increase nonce because the secret is a new balance proof
            # - The lock is removed from the merkle tree, the balance proof must be updated
            #   - The locksroot must have unlocked lock removed
            #   - The transferred amount must be increased by the lock amount
            # - This changes the balance for both participants:
            #   - the sender balance and locked amount is decremented by the lock amount
            #   - the receiver balance and distributable is incremented by the lock amount
            nonce += 1
            transferred_amount += lock_amount

            merkletree_leaves = list(partner_model_current.merkletree_leaves)
            merkletree_leaves.remove(lock.lockhash)
            tree = compute_layers(merkletree_leaves)
            locksroot = tree[MERKLEROOT][0]

            partner_model_current = partner_model_current._replace(
                amount_locked=partner_model_current.amount_locked - lock_amount,
                balance=partner_model_current.balance - lock_amount,
                next_nonce=partner_model_current.next_nonce + 1,
                merkletree_leaves=merkletree_leaves,
            )

            our_model_current = our_model_current._replace(
                balance=our_model_current.balance + lock_amount,
                distributable=our_model_current.distributable + lock_amount,
            )

            message_identifier = random.randint(0, UINT64_MAX)
            secret_message = Secret(
                message_identifier=message_identifier,
                payment_identifier=nonce,
                nonce=nonce,
                channel=channel_state.identifier,
                transferred_amount=transferred_amount,
                locksroot=locksroot,
                secret=lock_secret,
            )
            secret_message.sign(privkey2, channel_state.partner_state.address)

            balance_proof = balanceproof_from_envelope(secret_message)
            unlock_state_change = ReceiveUnlock(
                lock_secret,
                balance_proof,
            )

            is_valid, msg = channel.handle_unlock(channel_state, unlock_state_change)
            assert is_valid, msg

            assert_partner_state(
                channel_state.our_state,
                channel_state.partner_state,
                our_model_current,
            )
            assert_partner_state(
                channel_state.partner_state,
                channel_state.our_state,
                partner_model_current,
            )
Ejemplo n.º 27
0
def test_channelstate_receive_lockedtransfer():
    """Tests receiving a mediated transfer.

    The transfer is done in three steps:
        - a mediated transfer including a lock in its balance proof is sent
        - the secret is revealed
        - the unlocked balance proof is sent updating the transferred_amount
    """
    our_model1, _ = create_model(70)
    partner_model1, privkey2 = create_model(100)
    channel_state = create_channel_from_models(our_model1, partner_model1)

    # Step 1: Simulate receiving a transfer
    # - The receiver end state doesnt change
    # - The lock must be registered with the sender end
    lock_amount = 30
    lock_expiration = 10
    lock_secret = sha3(b'test_end_state')
    lock_secrethash = sha3(lock_secret)
    lock = HashTimeLockState(
        lock_amount,
        lock_expiration,
        lock_secrethash,
    )

    nonce = 1
    transferred_amount = 0
    receive_lockedtransfer = make_receive_transfer_mediated(
        channel_state,
        privkey2,
        nonce,
        transferred_amount,
        lock,
    )

    is_valid, msg = channel.handle_receive_lockedtransfer(
        channel_state,
        receive_lockedtransfer,
    )
    assert is_valid, msg

    our_model2 = our_model1
    partner_model2 = partner_model1._replace(
        distributable=partner_model1.distributable - lock_amount,
        amount_locked=lock_amount,
        next_nonce=2,
        merkletree_leaves=[lock.lockhash],
    )
    assert_partner_state(channel_state.our_state, channel_state.partner_state, our_model2)
    assert_partner_state(channel_state.partner_state, channel_state.our_state, partner_model2)

    # Step 2: Simulate learning the secret
    # - Registers the secret, this must not change the balance/locked amount
    channel.register_secret(channel_state, lock_secret, lock_secrethash)

    assert_partner_state(channel_state.our_state, channel_state.partner_state, our_model2)
    assert_partner_state(channel_state.partner_state, channel_state.our_state, partner_model2)

    # Step 3: Simulate unlocking the lock
    # - Update the balances
    transferred_amount = 0
    message_identifier = random.randint(0, UINT64_MAX)
    secret_message = Secret(
        message_identifier=message_identifier,
        payment_identifier=1,
        nonce=2,
        channel=channel_state.identifier,
        transferred_amount=transferred_amount + lock_amount,
        locksroot=EMPTY_MERKLE_ROOT,
        secret=lock_secret,
    )
    secret_message.sign(privkey2, channel_state.partner_state.address)

    balance_proof = balanceproof_from_envelope(secret_message)
    unlock_state_change = ReceiveUnlock(
        lock_secret,
        balance_proof,
    )

    is_valid, msg = channel.handle_unlock(channel_state, unlock_state_change)
    assert is_valid, msg

    our_model3 = our_model2._replace(
        balance=our_model2.balance + lock_amount,
        distributable=our_model2.balance + lock_amount,
    )
    partner_model3 = partner_model2._replace(
        balance=partner_model2.balance - lock_amount,
        amount_locked=0,
        next_nonce=3,
        merkletree_leaves=[],
    )

    assert_partner_state(channel_state.our_state, channel_state.partner_state, our_model3)
    assert_partner_state(channel_state.partner_state, channel_state.our_state, partner_model3)
def test_regression_multiple_revealsecret(raiden_network, token_addresses):
    """ Multiple RevealSecret messages arriving at the same time must be
    handled properly.

    Secret handling followed these steps:

        The Secret message arrives
        The secret is registered
        The channel is updated and the correspoding lock is removed
        * A balance proof for the new channel state is created and sent to the
          payer
        The channel is unregistered for the given hashlock

    The step marked with an asterisk above introduced a context-switch, this
    allowed a second Reveal Secret message to be handled before the channel was
    unregistered, because the channel was already updated an exception was raised
    for an unknown secret.
    """
    app0, app1 = raiden_network
    token = token_addresses[0]

    identifier = 1
    secret = sha3(b'test_regression_multiple_revealsecret')
    hashlock = sha3(secret)
    expiration = app0.raiden.get_block_number() + 100
    amount = 10

    mediated_transfer = channel(app0, app1, token).create_mediatedtransfer(
        transfer_initiator=app0.raiden.address,
        transfer_target=app1.raiden.address,
        fee=0,
        amount=amount,
        identifier=identifier,
        expiration=expiration,
        hashlock=hashlock,
    )
    app0.raiden.sign(mediated_transfer)

    message_data = mediated_transfer.encode()
    app1.raiden.protocol.receive(message_data)

    reveal_secret = RevealSecret(secret)
    app0.raiden.sign(reveal_secret)
    reveal_secret_data = reveal_secret.encode()

    secret = Secret(
        identifier=identifier,
        nonce=mediated_transfer.nonce + 1,
        channel=channel(app0, app1, token).channel_address,
        transferred_amount=amount,
        locksroot=EMPTY_MERKLE_ROOT,
        secret=secret,
    )
    app0.raiden.sign(secret)
    secret_data = secret.encode()

    messages = [
        secret_data,
        reveal_secret_data,
    ]

    wait = [
        gevent.spawn_later(
            .1,
            app1.raiden.protocol.receive,
            data,
        )
        for data in messages
    ]

    gevent.joinall(wait)
Ejemplo n.º 29
0
    def _run(self):  # pylint: disable=method-hidden,too-many-locals
        amount = self.amount
        target = self.target
        raiden = self.transfermanager.assetmanager.raiden

        fee = 0
        # there are no guarantees that the next_hop will follow the same route
        routes = self.transfermanager.assetmanager.get_best_routes(
            amount,
            target,
            lock_timeout=None,
        )

        if log.isEnabledFor(logging.DEBUG):
            log.debug(
                'START MEDIATED TRANSFER initiator:%s target:%s',
                pex(self.address),
                pex(self.target),
            )

        for path, forward_channel in routes:
            # try a new secret
            secret = sha3(hex(random.getrandbits(256)))
            hashlock = sha3(secret)

            next_hop = path[1]

            if log.isEnabledFor(logging.DEBUG):
                log.debug(
                    'START MEDIATED TRANSFER NEW PATH path:%s hashlock:%s',
                    lpex(path),
                    pex(hashlock),
                )

            self.transfermanager.register_task_for_hashlock(self, hashlock)

            lock_expiration = (raiden.chain.block_number() +
                               forward_channel.settle_timeout -
                               raiden.config['reveal_timeout'])

            mediated_transfer = forward_channel.create_mediatedtransfer(
                raiden.address,
                target,
                fee,
                amount,
                lock_expiration,
                hashlock,
            )
            raiden.sign(mediated_transfer)
            forward_channel.register_transfer(mediated_transfer)

            response = self.send_and_wait_valid(raiden, path,
                                                mediated_transfer)

            # `next_hop` timedout
            if response is None:
                self.transfermanager.on_hashlock_result(hashlock, False)

            # someone down the line timedout / couldn't proceed
            elif isinstance(response, (RefundTransfer, TransferTimeout)):
                self.transfermanager.on_hashlock_result(hashlock, False)

            # `target` received the MediatedTransfer
            elif response.sender == target and isinstance(
                    response, SecretRequest):
                secret_message = Secret(secret)
                raiden.sign(secret_message)
                raiden.send_async(target, secret_message)

                # register the secret now and just incur with the additional
                # overhead of retrying until the `next_hop` receives the secret
                # forward_channel.register_secret(secret)

                # wait until `next_hop` received the secret to syncronize our
                # state (otherwise we can send a new transfer with an invalid
                # locksroot while the secret is in transit that will incur into
                # additional retry/timeout latency)
                next_hop = path[1]
                while True:
                    response = self.response_message.wait()
                    # critical write section
                    self.response_message = AsyncResult()
                    # /critical write section
                    if isinstance(response,
                                  Secret) and response.sender == next_hop:
                        # critical read/write section
                        # The channel and it's queue must be locked, a transfer
                        # must not be created while we update the balance_proof.
                        forward_channel.claim_lock(secret)
                        raiden.send_async(next_hop, secret_message)
                        # /critical write section

                        self.transfermanager.on_hashlock_result(hashlock, True)
                        self.done_result.set(True)

                        return

                    log.error(
                        'Invalid message ignoring. %s',
                        repr(response),
                    )
            else:
                log.error(
                    'Unexpected response %s',
                    repr(response),
                )
                self.transfermanager.on_hashlock_result(hashlock, False)

        if log.isEnabledFor(logging.DEBUG):
            log.debug(
                'START MEDIATED TRANSFER FAILED initiator:%s target:%s',
                pex(self.address),
                pex(self.target),
            )

        self.done_result.set(False)  # all paths failed
Ejemplo n.º 30
0
def test_regression_multiple_revealsecret(raiden_network, token_addresses, transport_protocol):
    """ Multiple RevealSecret messages arriving at the same time must be
    handled properly.

    Secret handling followed these steps:

        The Secret message arrives
        The secret is registered
        The channel is updated and the correspoding lock is removed
        * A balance proof for the new channel state is created and sent to the
          payer
        The channel is unregistered for the given secrethash

    The step marked with an asterisk above introduced a context-switch. This
    allowed a second Reveal Secret message to be handled before the channel was
    unregistered. And because the channel was already updated an exception was raised
    for an unknown secret.
    """
    app0, app1 = raiden_network
    token = token_addresses[0]
    token_network_identifier = views.get_token_network_identifier_by_token_address(
        views.state_from_app(app0),
        app0.raiden.default_registry.address,
        token,
    )
    channelstate_0_1 = get_channelstate(app0, app1, token_network_identifier)

    payment_identifier = 1
    secret = sha3(b'test_regression_multiple_revealsecret')
    secrethash = sha3(secret)
    expiration = app0.raiden.get_block_number() + 100
    lock_amount = 10
    lock = Lock(
        lock_amount,
        expiration,
        secrethash,
    )

    nonce = 1
    transferred_amount = 0
    mediated_transfer = LockedTransfer(
        chain_id=UNIT_CHAIN_ID,
        message_identifier=random.randint(0, UINT64_MAX),
        payment_identifier=payment_identifier,
        nonce=nonce,
        token_network_address=app0.raiden.default_registry.address,
        token=token,
        channel_identifier=channelstate_0_1.identifier,
        transferred_amount=transferred_amount,
        locked_amount=lock_amount,
        recipient=app1.raiden.address,
        locksroot=lock.secrethash,
        lock=lock,
        target=app1.raiden.address,
        initiator=app0.raiden.address,
    )
    app0.raiden.sign(mediated_transfer)

    if transport_protocol is TransportProtocol.UDP:
        message_data = mediated_transfer.encode()
        host_port = None
        app1.raiden.transport.receive(message_data, host_port)
    elif transport_protocol is TransportProtocol.MATRIX:
        app1.raiden.transport._receive_message(mediated_transfer)
    else:
        raise TypeError('Unknown TransportProtocol')

    reveal_secret = RevealSecret(
        random.randint(0, UINT64_MAX),
        secret,
    )
    app0.raiden.sign(reveal_secret)

    token_network_identifier = channelstate_0_1.token_network_identifier
    secret = Secret(
        chain_id=UNIT_CHAIN_ID,
        message_identifier=random.randint(0, UINT64_MAX),
        payment_identifier=payment_identifier,
        nonce=mediated_transfer.nonce + 1,
        token_network_address=token_network_identifier,
        channel_identifier=channelstate_0_1.identifier,
        transferred_amount=lock_amount,
        locked_amount=0,
        locksroot=EMPTY_MERKLE_ROOT,
        secret=secret,
    )
    app0.raiden.sign(secret)

    if transport_protocol is TransportProtocol.UDP:
        messages = [
            secret.encode(),
            reveal_secret.encode(),
        ]
        host_port = None
        receive_method = app1.raiden.transport.receive
        wait = [
            gevent.spawn_later(
                .1,
                receive_method,
                data,
                host_port,
            )
            for data in messages
        ]
    elif transport_protocol is TransportProtocol.MATRIX:
        messages = [
            secret,
            reveal_secret,
        ]
        receive_method = app1.raiden.transport._receive_message
        wait = [
            gevent.spawn_later(
                .1,
                receive_method,
                data,
            )
            for data in messages
        ]
    else:
        raise TypeError('Unknown TransportProtocol')

    gevent.joinall(wait)
Ejemplo n.º 31
0
def test_secret(iterations=ITERATIONS):
    secret = HASH
    msg = Secret(secret)
    msg.sign(PRIVKEY)
    run_timeit('Secret', msg, iterations=iterations)
Ejemplo n.º 32
0
def test_regression_multiple_revealsecret(raiden_network, token_addresses, transport_config):
    """ Multiple RevealSecret messages arriving at the same time must be
    handled properly.

    Secret handling followed these steps:

        The Secret message arrives
        The secret is registered
        The channel is updated and the correspoding lock is removed
        * A balance proof for the new channel state is created and sent to the
          payer
        The channel is unregistered for the given secrethash

    The step marked with an asterisk above introduced a context-switch. This
    allowed a second Reveal Secret message to be handled before the channel was
    unregistered. And because the channel was already updated an exception was raised
    for an unknown secret.
    """
    app0, app1 = raiden_network
    token = token_addresses[0]
    token_network_identifier = views.get_token_network_identifier_by_token_address(
        views.state_from_app(app0),
        app0.raiden.default_registry.address,
        token,
    )
    channelstate_0_1 = get_channelstate(app0, app1, token_network_identifier)

    payment_identifier = 1
    secret = sha3(b'test_regression_multiple_revealsecret')
    secrethash = sha3(secret)
    expiration = app0.raiden.get_block_number() + 100
    lock_amount = 10
    lock = Lock(
        lock_amount,
        expiration,
        secrethash,
    )

    nonce = 1
    transferred_amount = 0
    mediated_transfer = LockedTransfer(
        chain_id=UNIT_CHAIN_ID,
        message_identifier=random.randint(0, UINT64_MAX),
        payment_identifier=payment_identifier,
        nonce=nonce,
        token_network_address=app0.raiden.default_registry.address,
        token=token,
        channel_identifier=channelstate_0_1.identifier,
        transferred_amount=transferred_amount,
        locked_amount=lock_amount,
        recipient=app1.raiden.address,
        locksroot=lock.secrethash,
        lock=lock,
        target=app1.raiden.address,
        initiator=app0.raiden.address,
    )
    app0.raiden.sign(mediated_transfer)

    if transport_config.protocol is TransportProtocol.UDP:
        message_data = mediated_transfer.encode()
        host_port = None
        app1.raiden.transport.receive(message_data, host_port)
    elif transport_config.protocol is TransportProtocol.MATRIX:
        app1.raiden.transport._receive_message(mediated_transfer)
    else:
        raise TypeError('Unknown TransportProtocol')

    reveal_secret = RevealSecret(
        random.randint(0, UINT64_MAX),
        secret,
    )
    app0.raiden.sign(reveal_secret)

    token_network_identifier = channelstate_0_1.token_network_identifier
    secret = Secret(
        chain_id=UNIT_CHAIN_ID,
        message_identifier=random.randint(0, UINT64_MAX),
        payment_identifier=payment_identifier,
        nonce=mediated_transfer.nonce + 1,
        token_network_address=token_network_identifier,
        channel_identifier=channelstate_0_1.identifier,
        transferred_amount=lock_amount,
        locked_amount=0,
        locksroot=EMPTY_MERKLE_ROOT,
        secret=secret,
    )
    app0.raiden.sign(secret)

    if transport_config.protocol is TransportProtocol.UDP:
        messages = [
            secret.encode(),
            reveal_secret.encode(),
        ]
        host_port = None
        receive_method = app1.raiden.transport.receive
        wait = [
            gevent.spawn_later(
                .1,
                receive_method,
                data,
                host_port,
            )
            for data in messages
        ]
    elif transport_config.protocol is TransportProtocol.MATRIX:
        messages = [
            secret,
            reveal_secret,
        ]
        receive_method = app1.raiden.transport._receive_message
        wait = [
            gevent.spawn_later(
                .1,
                receive_method,
                data,
            )
            for data in messages
        ]
    else:
        raise TypeError('Unknown TransportProtocol')

    gevent.joinall(wait)
Ejemplo n.º 33
0
    def handle_secret(  # pylint: disable=too-many-arguments
            self,
            identifier,
            token_address,
            secret,
            partner_secret_message,
            hashlock):
        """ Unlock/Witdraws locks, register the secret, and send Secret
        messages as necessary.

        This function will:
            - Unlock the locks created by this node and send a Secret message to
            the corresponding partner so that she can withdraw the token.
            - Withdraw the lock from sender.
            - Register the secret for the locks received and reveal the secret
            to the senders

        Note:
            The channel needs to be registered with
            `raiden.register_channel_for_hashlock`.
        """
        # handling the secret needs to:
        # - unlock the token for all `forward_channel` (the current one
        #   and the ones that failed with a refund)
        # - send a message to each of the forward nodes allowing them
        #   to withdraw the token
        # - register the secret for the `originating_channel` so that a
        #   proof can be made, if necessary
        # - reveal the secret to the `sender` node (otherwise we
        #   cannot withdraw the token)
        channels_list = self.tokens_hashlocks_channels[token_address][hashlock]
        channels_to_remove = list()

        # Dont use the partner_secret_message.token since it might not match
        # the current token manager
        our_secret_message = Secret(
            identifier,
            secret,
            token_address,
        )
        self.sign(our_secret_message)

        revealsecret_message = RevealSecret(secret)
        self.sign(revealsecret_message)

        for channel in channels_list:
            # unlock a sent lock
            if channel.partner_state.balance_proof.is_unclaimed(hashlock):
                channel.release_lock(secret)
                self.send_async(
                    channel.partner_state.address,
                    our_secret_message,
                )
                channels_to_remove.append(channel)

            # withdraw a pending lock
            if channel.our_state.balance_proof.is_unclaimed(hashlock):
                if partner_secret_message:
                    matching_sender = (
                        partner_secret_message.sender == channel.partner_state.address
                    )
                    matching_token = partner_secret_message.token == channel.token_address

                    if matching_sender and matching_token:
                        channel.withdraw_lock(secret)
                        channels_to_remove.append(channel)
                    else:
                        channel.register_secret(secret)
                        self.send_async(
                            channel.partner_state.address,
                            revealsecret_message,
                        )
                else:
                    channel.register_secret(secret)
                    self.send_async(
                        channel.partner_state.address,
                        revealsecret_message,
                    )

        for channel in channels_to_remove:
            channels_list.remove(channel)

        if len(channels_list) == 0:
            del self.tokens_hashlocks_channels[token_address][hashlock]
def test_end_state():
    token_address = make_address()
    privkey1, address1 = make_privkey_address()
    address2 = make_address()
    channel_address = make_address()

    balance1 = 70
    balance2 = 110

    lock_secret = sha3(b'test_end_state')
    lock_amount = 30
    lock_expiration = 10
    lock_hashlock = sha3(lock_secret)

    state1 = ChannelEndState(address1, balance1, None, EMPTY_MERKLE_TREE)
    state2 = ChannelEndState(address2, balance2, None, EMPTY_MERKLE_TREE)

    assert state1.contract_balance == balance1
    assert state2.contract_balance == balance2
    assert state1.balance(state2) == balance1
    assert state2.balance(state1) == balance2

    assert state1.is_locked(lock_hashlock) is False
    assert state2.is_locked(lock_hashlock) is False

    assert merkleroot(state1.merkletree) == EMPTY_MERKLE_ROOT
    assert merkleroot(state2.merkletree) == EMPTY_MERKLE_ROOT

    assert state1.nonce is None
    assert state2.nonce is None

    lock = Lock(
        lock_amount,
        lock_expiration,
        lock_hashlock,
    )
    lock_hash = sha3(lock.as_bytes)

    transferred_amount = 0
    locksroot = state2.compute_merkleroot_with(lock)

    locked_transfer = LockedTransfer(
        1,
        nonce=1,
        token=token_address,
        channel=channel_address,
        transferred_amount=transferred_amount,
        recipient=state2.address,
        locksroot=locksroot,
        lock=lock,
    )

    transfer_target = make_address()
    transfer_initiator = make_address()
    fee = 0
    mediated_transfer = locked_transfer.to_mediatedtransfer(
        transfer_target,
        transfer_initiator,
        fee,
    )
    mediated_transfer.sign(privkey1, address1)

    state1.register_locked_transfer(mediated_transfer)

    assert state1.contract_balance == balance1
    assert state2.contract_balance == balance2
    assert state1.balance(state2) == balance1
    assert state2.balance(state1) == balance2

    assert state1.distributable(state2) == balance1 - lock_amount
    assert state2.distributable(state1) == balance2

    assert state1.amount_locked == lock_amount
    assert state2.amount_locked == 0

    assert state1.is_locked(lock_hashlock) is True
    assert state2.is_locked(lock_hashlock) is False

    assert merkleroot(state1.merkletree) == lock_hash
    assert merkleroot(state2.merkletree) == EMPTY_MERKLE_ROOT

    assert state1.nonce is 1
    assert state2.nonce is None

    with pytest.raises(ValueError):
        state1.update_contract_balance(balance1 - 10)

    state1.update_contract_balance(balance1 + 10)

    assert state1.contract_balance == balance1 + 10
    assert state2.contract_balance == balance2
    assert state1.balance(state2) == balance1 + 10
    assert state2.balance(state1) == balance2

    assert state1.distributable(state2) == balance1 - lock_amount + 10
    assert state2.distributable(state1) == balance2

    assert state1.amount_locked == lock_amount
    assert state2.amount_locked == 0

    assert state1.is_locked(lock_hashlock) is True
    assert state2.is_locked(lock_hashlock) is False

    assert merkleroot(state1.merkletree) == lock_hash
    assert merkleroot(state2.merkletree) == EMPTY_MERKLE_ROOT

    assert state1.nonce is 1
    assert state2.nonce is None

    # registering the secret should not change the locked amount
    state1.register_secret(lock_secret)

    assert state1.contract_balance == balance1 + 10
    assert state2.contract_balance == balance2
    assert state1.balance(state2) == balance1 + 10
    assert state2.balance(state1) == balance2

    assert state1.is_locked(lock_hashlock) is False
    assert state2.is_locked(lock_hashlock) is False

    assert merkleroot(state1.merkletree) == lock_hash
    assert merkleroot(state2.merkletree) == EMPTY_MERKLE_ROOT

    assert state1.nonce is 1
    assert state2.nonce is None

    secret_message = Secret(
        identifier=1,
        nonce=2,
        channel=channel_address,
        transferred_amount=transferred_amount + lock_amount,
        locksroot=EMPTY_MERKLE_ROOT,
        secret=lock_secret,
    )
    secret_message.sign(privkey1, address1)
    state1.register_secretmessage(secret_message)

    assert state1.contract_balance == balance1 + 10
    assert state2.contract_balance == balance2
    assert state1.balance(state2) == balance1 + 10 - lock_amount
    assert state2.balance(state1) == balance2 + lock_amount

    assert state1.distributable(state2) == balance1 + 10 - lock_amount
    assert state2.distributable(state1) == balance2 + lock_amount

    assert state1.amount_locked == 0
    assert state2.amount_locked == 0

    assert state1.is_locked(lock_hashlock) is False
    assert state2.is_locked(lock_hashlock) is False

    assert merkleroot(state1.merkletree) == EMPTY_MERKLE_ROOT
    assert merkleroot(state2.merkletree) == EMPTY_MERKLE_ROOT

    assert state1.nonce is 2
    assert state2.nonce is None
Ejemplo n.º 35
0
def test_end_state():
    token_address = make_address()
    privkey1, address1 = make_privkey_address()
    address2 = make_address()
    channel_address = make_address()

    balance1 = 70
    balance2 = 110

    lock_secret = sha3('test_end_state')
    lock_amount = 30
    lock_expiration = 10
    lock_hashlock = sha3(lock_secret)

    state1 = ChannelEndState(address1, balance1, None, EMPTY_MERKLE_TREE)
    state2 = ChannelEndState(address2, balance2, None, EMPTY_MERKLE_TREE)

    assert state1.contract_balance == balance1
    assert state2.contract_balance == balance2
    assert state1.balance(state2) == balance1
    assert state2.balance(state1) == balance2


    assert state1.is_locked(lock_hashlock) is False
    assert state2.is_locked(lock_hashlock) is False

    assert merkleroot(state1.merkletree) == EMPTY_MERKLE_ROOT
    assert merkleroot(state2.merkletree) == EMPTY_MERKLE_ROOT

    assert state1.nonce is None
    assert state2.nonce is None

    lock = Lock(
        lock_amount,
        lock_expiration,
        lock_hashlock,
    )
    lock_hash = sha3(lock.as_bytes)

    transferred_amount = 0
    locksroot = state2.compute_merkleroot_with(lock)

    locked_transfer = LockedTransfer(
        1,
        nonce=1,
        token=token_address,
        channel=channel_address,
        transferred_amount=transferred_amount,
        recipient=state2.address,
        locksroot=locksroot,
        lock=lock,
    )

    transfer_target = make_address()
    transfer_initiator = make_address()
    fee = 0
    mediated_transfer = locked_transfer.to_mediatedtransfer(
        transfer_target,
        transfer_initiator,
        fee,
    )
    mediated_transfer.sign(privkey1, address1)

    state1.register_locked_transfer(mediated_transfer)

    assert state1.contract_balance == balance1
    assert state2.contract_balance == balance2
    assert state1.balance(state2) == balance1
    assert state2.balance(state1) == balance2

    assert state1.distributable(state2) == balance1 - lock_amount
    assert state2.distributable(state1) == balance2

    assert state1.amount_locked == lock_amount
    assert state2.amount_locked == 0

    assert state1.is_locked(lock_hashlock) is True
    assert state2.is_locked(lock_hashlock) is False

    assert merkleroot(state1.merkletree) == lock_hash
    assert merkleroot(state2.merkletree) == EMPTY_MERKLE_ROOT

    assert state1.nonce is 1
    assert state2.nonce is None

    with pytest.raises(ValueError):
        state1.update_contract_balance(balance1 - 10)

    state1.update_contract_balance(balance1 + 10)

    assert state1.contract_balance == balance1 + 10
    assert state2.contract_balance == balance2
    assert state1.balance(state2) == balance1 + 10
    assert state2.balance(state1) == balance2

    assert state1.distributable(state2) == balance1 - lock_amount + 10
    assert state2.distributable(state1) == balance2

    assert state1.amount_locked == lock_amount
    assert state2.amount_locked == 0

    assert state1.is_locked(lock_hashlock) is True
    assert state2.is_locked(lock_hashlock) is False

    assert merkleroot(state1.merkletree) == lock_hash
    assert merkleroot(state2.merkletree) == EMPTY_MERKLE_ROOT

    assert state1.nonce is 1
    assert state2.nonce is None

    # registering the secret should not change the locked amount
    state1.register_secret(lock_secret)

    assert state1.contract_balance == balance1 + 10
    assert state2.contract_balance == balance2
    assert state1.balance(state2) == balance1 + 10
    assert state2.balance(state1) == balance2


    assert state1.is_locked(lock_hashlock) is False
    assert state2.is_locked(lock_hashlock) is False

    assert merkleroot(state1.merkletree) == lock_hash
    assert merkleroot(state2.merkletree) == EMPTY_MERKLE_ROOT

    assert state1.nonce is 1
    assert state2.nonce is None

    secret_message = Secret(
        identifier=1,
        nonce=2,
        channel=channel_address,
        transferred_amount=transferred_amount + lock_amount,
        locksroot=EMPTY_MERKLE_ROOT,
        secret=lock_secret,
    )
    secret_message.sign(privkey1, address1)
    state1.register_secretmessage(secret_message)

    assert state1.contract_balance == balance1 + 10
    assert state2.contract_balance == balance2
    assert state1.balance(state2) == balance1 + 10 - lock_amount
    assert state2.balance(state1) == balance2 + lock_amount

    assert state1.distributable(state2) == balance1 + 10 - lock_amount
    assert state2.distributable(state1) == balance2 + lock_amount

    assert state1.amount_locked == 0
    assert state2.amount_locked == 0

    assert state1.is_locked(lock_hashlock) is False
    assert state2.is_locked(lock_hashlock) is False

    assert merkleroot(state1.merkletree) == EMPTY_MERKLE_ROOT
    assert merkleroot(state2.merkletree) == EMPTY_MERKLE_ROOT

    assert state1.nonce is 2
    assert state2.nonce is None
Ejemplo n.º 36
0
def test_secret(iterations=ITERATIONS):
    secret = HASH
    msg = Secret(secret)
    msg.sign(PRIVKEY)
    run_timeit('Secret', msg, iterations=iterations)