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, )
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, )
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
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
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, )
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)
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)
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, )