예제 #1
0
    def handle_contract_send_channelupdate(
            raiden: "RaidenService",
            channel_update_event: ContractSendChannelUpdateTransfer) -> None:
        balance_proof = channel_update_event.balance_proof

        if balance_proof:
            canonical_identifier = balance_proof.canonical_identifier
            channel = raiden.proxy_manager.payment_channel(
                canonical_identifier=canonical_identifier)

            non_closing_data = pack_signed_balance_proof(
                msg_type=MessageTypeId.BALANCE_PROOF_UPDATE,
                nonce=balance_proof.nonce,
                balance_hash=balance_proof.balance_hash,
                additional_hash=balance_proof.message_hash,
                canonical_identifier=canonical_identifier,
                partner_signature=balance_proof.signature,
            )
            our_signature = raiden.signer.sign(data=non_closing_data)

            channel.update_transfer(
                nonce=balance_proof.nonce,
                balance_hash=balance_proof.balance_hash,
                additional_hash=balance_proof.message_hash,
                partner_signature=balance_proof.signature,
                signature=our_signature,
                block_identifier=channel_update_event.triggered_by_block_hash,
            )
예제 #2
0
    def handle_contract_send_channelclose(
        raiden: "RaidenService",
        chain_state: ChainState,
        channel_close_event: ContractSendChannelClose,
    ) -> None:
        balance_proof = channel_close_event.balance_proof

        if balance_proof:
            nonce = balance_proof.nonce
            balance_hash = balance_proof.balance_hash
            signature_in_proof = balance_proof.signature
            message_hash = balance_proof.message_hash
            canonical_identifier = balance_proof.canonical_identifier

        else:
            nonce = Nonce(0)
            balance_hash = EMPTY_BALANCE_HASH
            signature_in_proof = EMPTY_SIGNATURE
            message_hash = EMPTY_MESSAGE_HASH
            canonical_identifier = channel_close_event.canonical_identifier

        closing_data = pack_signed_balance_proof(
            msg_type=MessageTypeId.BALANCE_PROOF,
            nonce=nonce,
            balance_hash=balance_hash,
            additional_hash=message_hash,
            canonical_identifier=canonical_identifier,
            partner_signature=signature_in_proof,
        )

        our_signature = raiden.signer.sign(data=closing_data)

        confirmed_block_identifier = state_from_raiden(raiden).block_hash
        channel_state = get_channelstate_by_canonical_identifier(
            chain_state=chain_state,
            canonical_identifier=channel_close_event.canonical_identifier)

        if channel_state is None:
            raise RaidenUnrecoverableError(
                "ContractSendChannelClose for inexesting channel.")

        channel_proxy = raiden.proxy_manager.payment_channel(
            channel_state=channel_state,
            block_identifier=confirmed_block_identifier)

        channel_proxy.close(
            nonce=nonce,
            balance_hash=balance_hash,
            additional_hash=message_hash,
            non_closing_signature=signature_in_proof,
            closing_signature=our_signature,
            block_identifier=channel_close_event.triggered_by_block_hash,
        )
예제 #3
0
 def _data_to_sign(self) -> bytes:
     packed = pack_signed_balance_proof(
         msg_type=MessageTypeId.BALANCE_PROOF_UPDATE,
         nonce=self.nonce,
         balance_hash=self.balance_hash,
         additional_hash=self.additional_hash,
         canonical_identifier=CanonicalIdentifier(
             chain_identifier=self.chain_id,
             token_network_address=self.token_network_address,
             channel_identifier=self.channel_identifier,
         ),
         partner_signature=self.signature,
     )
     return packed
예제 #4
0
    def handle_contract_send_channelupdate(
            raiden: "RaidenService",
            channel_update_event: ContractSendChannelUpdateTransfer) -> None:
        balance_proof = channel_update_event.balance_proof

        if balance_proof:
            canonical_identifier = balance_proof.canonical_identifier
            chain_state = state_from_raiden(raiden)
            confirmed_block_identifier = chain_state.block_hash

            channel_state = get_channelstate_by_canonical_identifier(
                chain_state=chain_state,
                canonical_identifier=canonical_identifier)

            if channel_state is None:
                raise RaidenUnrecoverableError(
                    "ContractSendChannelUpdateTransfer for inexesting channel."
                )

            channel = raiden.proxy_manager.payment_channel(
                channel_state=channel_state,
                block_identifier=confirmed_block_identifier)

            non_closing_data = pack_signed_balance_proof(
                msg_type=MessageTypeId.BALANCE_PROOF_UPDATE,
                nonce=balance_proof.nonce,
                balance_hash=balance_proof.balance_hash,
                additional_hash=balance_proof.message_hash,
                canonical_identifier=canonical_identifier,
                partner_signature=balance_proof.signature,
            )
            our_signature = raiden.signer.sign(data=non_closing_data)

            try:
                channel.update_transfer(
                    nonce=balance_proof.nonce,
                    balance_hash=balance_proof.balance_hash,
                    additional_hash=balance_proof.message_hash,
                    partner_signature=balance_proof.signature,
                    signature=our_signature,
                    block_identifier=channel_update_event.
                    triggered_by_block_hash,
                )
            except InsufficientEth as e:
                raise RaidenUnrecoverableError(
                    f"{str(e)}\n"
                    "CAUTION: This happened when updating our side of the channel "
                    "during a channel settlement. You are in immediate danger of "
                    "losing funds in this channel.") from e
예제 #5
0
    def handle_contract_send_channelclose(
        raiden: "RaidenService",
        chain_state: ChainState,
        channel_close_event: ContractSendChannelClose,
    ) -> None:
        balance_proof = channel_close_event.balance_proof

        if balance_proof:
            nonce = balance_proof.nonce
            balance_hash = balance_proof.balance_hash
            signature_in_proof = balance_proof.signature
            message_hash = balance_proof.message_hash
            canonical_identifier = balance_proof.canonical_identifier

        else:
            nonce = Nonce(0)
            balance_hash = EMPTY_BALANCE_HASH
            signature_in_proof = EMPTY_SIGNATURE
            message_hash = EMPTY_MESSAGE_HASH
            canonical_identifier = channel_close_event.canonical_identifier

        closing_data = pack_signed_balance_proof(
            msg_type=MessageTypeId.BALANCE_PROOF,
            nonce=nonce,
            balance_hash=balance_hash,
            additional_hash=message_hash,
            canonical_identifier=canonical_identifier,
            partner_signature=signature_in_proof,
        )

        our_signature = raiden.signer.sign(data=closing_data)

        channel_proxy = raiden.proxy_manager.payment_channel(
            canonical_identifier=CanonicalIdentifier(
                chain_identifier=chain_state.chain_id,
                token_network_address=channel_close_event.token_network_address,
                channel_identifier=channel_close_event.channel_identifier,
            )
        )

        channel_proxy.close(
            nonce=nonce,
            balance_hash=balance_hash,
            additional_hash=message_hash,
            non_closing_signature=signature_in_proof,
            closing_signature=our_signature,
            block_identifier=channel_close_event.triggered_by_block_hash,
        )
예제 #6
0
    def verify_request_monitoring(self, partner_address: Address,
                                  requesting_address: Address) -> bool:
        """ One should only use this method to verify integrity and signatures of a
        RequestMonitoring message. """
        if not self.non_closing_signature:
            return False

        balance_proof_data = pack_balance_proof(
            nonce=self.balance_proof.nonce,
            balance_hash=self.balance_proof.balance_hash,
            additional_hash=self.balance_proof.additional_hash,
            canonical_identifier=CanonicalIdentifier(
                chain_identifier=self.balance_proof.chain_id,
                token_network_address=self.balance_proof.token_network_address,
                channel_identifier=self.balance_proof.channel_identifier,
            ),
        )
        blinded_data = pack_signed_balance_proof(
            msg_type=MessageTypeId.BALANCE_PROOF_UPDATE,
            nonce=self.balance_proof.nonce,
            balance_hash=self.balance_proof.balance_hash,
            additional_hash=self.balance_proof.additional_hash,
            canonical_identifier=CanonicalIdentifier(
                chain_identifier=self.balance_proof.chain_id,
                token_network_address=self.balance_proof.token_network_address,
                channel_identifier=self.balance_proof.channel_identifier,
            ),
            partner_signature=self.balance_proof.signature,
        )
        reward_proof_data = pack_reward_proof(
            chain_id=self.balance_proof.chain_id,
            token_network_address=self.balance_proof.token_network_address,
            reward_amount=self.reward_amount,
            monitoring_service_contract_address=self.
            monitoring_service_contract_address,
            non_closing_participant=requesting_address,
            non_closing_signature=self.non_closing_signature,
        )
        reward_proof_signature = self.reward_proof_signature or EMPTY_SIGNATURE
        return (recover(balance_proof_data,
                        self.balance_proof.signature) == partner_address
                and recover(blinded_data,
                            self.non_closing_signature) == requesting_address
                and recover(reward_proof_data,
                            reward_proof_signature) == requesting_address)
예제 #7
0
def test_request_monitoring() -> None:
    properties = factories.BalanceProofSignedStateProperties(
        pkey=PARTNER_PRIVKEY)
    balance_proof = factories.create(properties)
    partner_signed_balance_proof = SignedBlindedBalanceProof.from_balance_proof_signed_state(
        balance_proof)
    request_monitoring = RequestMonitoring(
        balance_proof=partner_signed_balance_proof,
        non_closing_participant=ADDRESS,
        reward_amount=TokenAmount(55),
        signature=EMPTY_SIGNATURE,
        monitoring_service_contract_address=MSC_ADDRESS,
    )
    assert request_monitoring
    request_monitoring.sign(signer)
    as_dict = DictSerializer.serialize(request_monitoring)
    assert DictSerializer.deserialize(as_dict) == request_monitoring
    # RequestMonitoring can be created directly from BalanceProofSignedState
    direct_created = RequestMonitoring.from_balance_proof_signed_state(
        balance_proof=balance_proof,
        non_closing_participant=ADDRESS,
        reward_amount=TokenAmount(55),
        monitoring_service_contract_address=MSC_ADDRESS,
    )
    # `direct_created` is not signed while request_monitoring is
    assert DictSerializer().serialize(
        direct_created) != DictSerializer().serialize(request_monitoring)

    direct_created.sign(signer)
    # Instances created from same balance proof are equal
    assert direct_created == request_monitoring
    other_balance_proof = factories.create(
        factories.replace(properties, message_hash=keccak(b"2")))
    other_instance = RequestMonitoring.from_balance_proof_signed_state(
        balance_proof=other_balance_proof,
        non_closing_participant=ADDRESS,
        reward_amount=TokenAmount(55),
        monitoring_service_contract_address=MSC_ADDRESS,
    )
    other_instance.sign(signer)
    # different balance proof ==> non-equality
    assert other_instance != request_monitoring

    # test signature verification
    assert request_monitoring.non_closing_signature
    reward_proof_data = pack_reward_proof(
        token_network_address=request_monitoring.balance_proof.
        token_network_address,
        chain_id=request_monitoring.balance_proof.chain_id,
        reward_amount=request_monitoring.reward_amount,
        monitoring_service_contract_address=MSC_ADDRESS,
        non_closing_participant=ADDRESS,
        non_closing_signature=request_monitoring.non_closing_signature,
    )

    assert request_monitoring.reward_proof_signature
    assert recover(reward_proof_data,
                   request_monitoring.reward_proof_signature) == ADDRESS

    blinded_data = pack_signed_balance_proof(
        msg_type=MessageTypeId.BALANCE_PROOF_UPDATE,
        nonce=request_monitoring.balance_proof.nonce,
        balance_hash=request_monitoring.balance_proof.balance_hash,
        additional_hash=request_monitoring.balance_proof.additional_hash,
        canonical_identifier=factories.make_canonical_identifier(
            chain_identifier=request_monitoring.balance_proof.chain_id,
            token_network_address=request_monitoring.balance_proof.
            token_network_address,
            channel_identifier=request_monitoring.balance_proof.
            channel_identifier,
        ),
        partner_signature=request_monitoring.balance_proof.signature,
    )
    assert recover(blinded_data,
                   request_monitoring.non_closing_signature) == ADDRESS

    balance_proof_data = pack_balance_proof(
        nonce=request_monitoring.balance_proof.nonce,
        balance_hash=request_monitoring.balance_proof.balance_hash,
        additional_hash=request_monitoring.balance_proof.additional_hash,
        canonical_identifier=factories.make_canonical_identifier(
            chain_identifier=request_monitoring.balance_proof.chain_id,
            token_network_address=request_monitoring.balance_proof.
            token_network_address,
            channel_identifier=request_monitoring.balance_proof.
            channel_identifier,
        ),
    )
    assert (recover(
        balance_proof_data,
        request_monitoring.balance_proof.signature) == PARTNER_ADDRESS)

    assert request_monitoring.verify_request_monitoring(
        PARTNER_ADDRESS, ADDRESS)
예제 #8
0
def test_locksroot_loading_during_channel_settle_handling(
    raiden_chain, deploy_client, token_addresses
):
    app0, app1 = raiden_chain
    token_network_registry_address = app0.raiden.default_registry.address
    token_address = token_addresses[0]

    transfer(
        initiator_app=app0,
        target_app=app1,
        token_address=token_address,
        amount=PaymentAmount(10),
        identifier=PaymentID(1),
        transfer_state=TransferState.SECRET_NOT_REQUESTED,
    )
    transfer(
        initiator_app=app1,
        target_app=app0,
        token_address=token_address,
        amount=PaymentAmount(7),
        identifier=PaymentID(2),
        transfer_state=TransferState.SECRET_NOT_REQUESTED,
    )

    token_network_address = views.get_token_network_address_by_token_address(
        chain_state=views.state_from_raiden(app0.raiden),
        token_network_registry_address=token_network_registry_address,
        token_address=token_address,
    )
    assert token_network_address
    channel_state = get_channelstate(
        app0=app0, app1=app1, token_network_address=token_network_address
    )

    channel = app0.raiden.proxy_manager.payment_channel(channel_state.canonical_identifier)
    balance_proof = channel_state.partner_state.balance_proof
    assert balance_proof
    balance_proof = cast(BalanceProofSignedState, balance_proof)
    block_number = app0.raiden.rpc_client.block_number()

    closing_data = pack_signed_balance_proof(
        msg_type=MessageTypeId.BALANCE_PROOF,
        nonce=balance_proof.nonce,
        balance_hash=balance_proof.balance_hash,
        additional_hash=balance_proof.message_hash,
        canonical_identifier=balance_proof.canonical_identifier,
        partner_signature=balance_proof.signature,
    )
    closing_signature = app0.raiden.signer.sign(data=closing_data)

    channel.close(
        nonce=balance_proof.nonce,
        balance_hash=balance_proof.balance_hash,
        additional_hash=balance_proof.message_hash,
        non_closing_signature=balance_proof.signature,
        closing_signature=closing_signature,
        block_identifier=block_number,
    )

    close_block = app0.raiden.rpc_client.block_number()

    app0.stop()

    waiting.wait_for_settle(
        raiden=app1.raiden,
        token_network_registry_address=token_network_registry_address,
        token_address=token_address,
        channel_ids=[channel_state.canonical_identifier.channel_identifier],
        retry_timeout=1,
    )

    contract_proxy, _ = deploy_rpc_test_contract(deploy_client, "RpcWithStorageTest")
    iterations = 1000

    def send_transaction():
        check_block = deploy_client.get_checking_block()
        startgas = contract_proxy.estimate_gas(check_block, "waste_storage", iterations)
        startgas = safe_gas_limit(startgas)
        transaction = contract_proxy.transact("waste_storage", startgas, iterations)
        return deploy_client.poll(transaction)

    for _ in range(10):
        send_transaction()

    # Wait until the target block has be prunned, it has to be larger than
    # pruning_history
    pruned_after_blocks = pruning_history * 1.5

    waiting.wait_for_block(
        raiden=app1.raiden, block_number=close_block + pruned_after_blocks, retry_timeout=1
    )

    channel = app0.raiden.proxy_manager.payment_channel(channel_state.canonical_identifier)

    # make sure the block was pruned
    with pytest.raises(ValueError):
        channel.detail(block_identifier=close_block)

    # This must not raise when the settle event is being raised and the
    # locksroot is being recover (#3856)
    app0.start()

    assert wait_for_state_change(
        raiden=app0.raiden,
        item_type=ContractReceiveChannelSettled,
        attributes={"canonical_identifier": channel_state.canonical_identifier},
        retry_timeout=1,
    )