def handle_message_crosssecretrequest(raiden, message): secret_request_message = SecretRequest(message.message_identifier, message.payment_identifier, message.secrethash, message.amount) secret_request_message.signature = message.secret_request_signature state_change = ReceiveSecretRequest( secret_request_message.payment_identifier, secret_request_message.amount, secret_request_message.secrethash, secret_request_message.sender, ) row = raiden.wal.get_crosstransaction_by_identifier(message.cross_id) if row[7] == 6: raiden.handle_state_change(state_change) raiden.wal.change_crosstransaction_status(message.cross_id, 8) #sync acceptcross = AcceptCross(random.randint(0, UINT64_MAX), row[1], row[2], message.cross_id, 7) raiden.sign(acceptcross) raiden.transport.send_async( row[2], bytes("123", 'utf-8'), acceptcross, ) log.info('##sync sended') else: raiden.wal.change_crosstransaction_status(message.cross_id, 5) state_change_id = raiden.wal.storage.write_state_change(state_change) raiden.wal.storage.change_crosstransaction_statechangeid( message.cross_id, state_change_id)
def test_secret_request_5(): dict_data = { "type": "SecretRequest", "message_identifier": 9443946215632930647, "payment_identifier": 1322351847924173620, "amount": 100000000000000000, "expiration": 12000000, "secrethash": "0xaf1ca2932cb5c3e3045eedb17ce760419d2b3e5234eeefe6fd82475adeb4da10" } message = SecretRequest(message_identifier=dict_data["message_identifier"], payment_identifier=dict_data["payment_identifier"], secrethash=decode_hex(dict_data["secrethash"]), amount=dict_data["amount"], expiration=dict_data["expiration"]) message.sign(signer) data_was_signed = message._data_to_sign() print("SR signature: " + message.signature.hex()) assert recover(data_was_signed, message.signature) == to_canonical_address( "0x7ca28d3d760b4aa2b79e8d42cbdc187c7df9af40")
def test_secret_request(iterations=ITERATIONS): identifier = 1 hashlock = HASH msg = SecretRequest( identifier, hashlock ) msg.sign(PRIVKEY, ADDRESS) run_timeit('SecretRequest', msg, iterations=iterations)
def test_udp_decode_invalid_size_message(mock_udp): message = SecretRequest( message_identifier=random.randint(0, UINT64_MAX), payment_identifier=1, secrethash=UNIT_SECRETHASH, amount=1, expiration=10, ) data = message.encode() wrong_command_id_data = data[:-1] assert not mock_udp.receive(wrong_command_id_data)
def test_secret_request(iterations=ITERATIONS): identifier = 1 hashlock = HASH amount = 1 msg = SecretRequest( identifier, hashlock, amount, ) msg.sign(PRIVKEY, ADDRESS) run_timeit('SecretRequest', msg, iterations=iterations)
def test_udp_decode_invalid_size_message(mock_udp): message = SecretRequest( message_identifier=random.randint(0, UINT64_MAX), payment_identifier=1, secrethash=UNIT_SECRETHASH, amount=1, expiration=10, ) data = message.encode() wrong_command_id_data = data[:-1] host_port = None assert not mock_udp.receive(wrong_command_id_data, host_port)
def on_mediatedtransfer(self, transfer): assert isinstance(transfer, MediatedTransfer) log.debug('ON MEDIATED TRANSFER', address=pex(self.raiden.address)) channel = self.assetmanager.channels[transfer.sender] channel.register_transfer( transfer) # this raises if the transfer is invalid # either we are the target of the transfer, so we need to send a # SecretRequest if transfer.target == self.raiden.address: secret_request = SecretRequest(transfer.lock.hashlock) self.raiden.sign(secret_request) self.raiden.send(transfer.initiator, secret_request) secret_request_task = ForwardSecretTask( self, transfer.lock.hashlock, recipient=transfer.sender, ) secret_request_task.start() # or we are a participating node in the network and need to keep # forwarding the MediatedTransfer else: transfer_task = MediatedTransferTask( self, transfer.lock.amount, transfer.target, transfer.lock.hashlock, originating_transfer=transfer, ) transfer_task.start()
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)
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)
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)
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)
def _run(self): # pylint: disable=method-hidden transfer = self.originating_transfer assetmanager = self.transfermanager.assetmanager raiden = assetmanager.raiden transfer_details = '{} -> {} hash:{}'.format( pex(transfer.target), pex(transfer.initiator), pex(transfer.hash), ) log.debug('END MEDIATED TRANSFER {}'.format(transfer_details)) secret_request = SecretRequest(transfer.lock.hashlock) raiden.sign(secret_request) raiden.send(transfer.initiator, secret_request) self.event = AsyncResult() response = self.event.wait(raiden.config['msg_timeout']) if response is None: log.error('SECRETREQUEST TIMED OUT!') self.transfermanager.on_hashlock_result(transfer.hashlock, False) return if not isinstance(response, Secret): raise Exception('Invalid message received.') if sha3(response.secret) != transfer.lock.hashlock: raise Exception('Invalid secret received.') # update all channels and propagate the secret assetmanager.register_secret(response.secret) self.transfermanager.on_hashlock_result(transfer.lock.hashlock, True)
def run_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_signer = LocalSigner(other_key) 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_signer, app0) unlock = Unlock( 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(unlock, other_signer, 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_signer, app0) reveal_secret_message = RevealSecret( message_identifier=random.randint(0, UINT64_MAX), secret=UNIT_SECRET, ) sign_and_inject(reveal_secret_message, other_signer, app0)
def on_event(self, event): if isinstance(event, SendMediatedTransfer): receiver = event.receiver fee = 0 graph = self.raiden.channelgraphs[event.token] channel = graph.partneraddress_channel[receiver] mediated_transfer = channel.create_mediatedtransfer( event.initiator, event.target, fee, event.amount, event.identifier, event.expiration, event.hashlock, ) self.raiden.sign(mediated_transfer) channel.register_transfer(mediated_transfer) self.raiden.send_async(receiver, mediated_transfer) elif isinstance(event, SendRevealSecret): reveal_message = RevealSecret(event.secret) self.raiden.sign(reveal_message) self.raiden.send_async(event.receiver, reveal_message) elif isinstance(event, SendBalanceProof): # TODO: issue #189 # unlock and update remotely (send the Secret message) self.raiden.handle_secret( event.identifier, event.token, event.secret, None, sha3(event.secret), ) elif isinstance(event, SendSecretRequest): secret_request = SecretRequest( event.identifier, event.hashlock, event.amount, ) self.raiden.sign(secret_request) self.raiden.send_async(event.receiver, secret_request) elif isinstance(event, SendRefundTransfer): pass elif isinstance(event, EventTransferCompleted): for result in self.raiden.identifier_result[event.identifier]: result.set(True) elif isinstance(event, EventTransferFailed): for result in self.raiden.identifier_result[event.identifier]: result.set(True)
def handle_send_secretrequest( raiden: 'RaidenService', secret_request_event: SendSecretRequest): secret_request_message = SecretRequest.from_event(secret_request_event) raiden.sign(secret_request_message) raiden.send_async( secret_request_event.receiver, secret_request_message, )
def handle_send_secretrequest( raiden: 'RaidenService', secret_request_event: SendSecretRequest, ): secret_request_message = SecretRequest.from_event(secret_request_event) raiden.sign(secret_request_message) raiden.protocol.send_async( secret_request_event.queue_name, secret_request_event.recipient, secret_request_message, )
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 amount = 10 refund_transfer_message = make_refund_transfer( payment_identifier=1, nonce=1, token_network_address=token_network_identifier, 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(), 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, ) 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)
def make_message(convert_to_hex: bool = False, overwrite_data=None): room = Room(None, "!roomID:server") if not overwrite_data: message = SecretRequest( message_identifier=random.randint(0, UINT64_MAX), payment_identifier=1, secrethash=factories.UNIT_SECRETHASH, amount=1, expiration=10, ) message.sign(LocalSigner(factories.HOP1_KEY)) data = message.encode() if convert_to_hex: data = "0x" + data.hex() else: data = json.dumps(message.to_dict()) else: data = overwrite_data event = dict(type="m.room.message", sender=USERID1, content={ "msgtype": "m.text", "body": data }) return room, event
def make_message(convert_to_hex: bool = False, overwrite_data=None): from matrix_client.room import Room room = Room(None, '!roomID:server') if not overwrite_data: message = SecretRequest( message_identifier=random.randint(0, UINT64_MAX), payment_identifier=1, secrethash=UNIT_SECRETHASH, amount=1, expiration=10, ) message.sign(HOP1_KEY) data = message.encode() if convert_to_hex: data = '0x' + data.hex() else: data = json.dumps(message.to_dict()) else: data = overwrite_data event = dict( type='m.room.message', sender=USERID1, content={ 'msgtype': 'm.text', 'body': data, }, ) return room, event
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
def on_mediatedtransfer(self, transfer): assert isinstance(transfer, MediatedTransfer) log.debug('ON MEDIATED TRANSFER', address=pex(self.raiden.address)) channel = self.assetmanager.channels[transfer.sender] channel.register_transfer( transfer) # this raises if the transfer is invalid config = self.raiden.config # either we are the target of the transfer, so we need to send a # SecretRequest if transfer.target == self.raiden.address: secret_request = SecretRequest(transfer.lock.hashlock) self.raiden.sign(secret_request) self.raiden.send(transfer.initiator, secret_request) secret_request_task = ForwardSecretTask( self, transfer.lock.hashlock, recipient=transfer.sender, msg_timeout=config[ 'msg_timeout'] # FIXME additional config['secret_request_timeout'] ? ) secret_request_task.start() # or we are a participating node in the network and need to keep # forwarding the MediatedTransfer else: # subtract reveal_timeout from the lock expiration of the incoming transfer expiration = transfer.lock.expiration - config['reveal_timeout'] transfer_task = MediatedTransferTask( self, transfer.lock.amount, transfer.target, transfer.lock.hashlock, expiration, originating_transfer=transfer, ) transfer_task.start()
def message_from_sendevent(send_event: SendMessageEvent) -> Message: if type(send_event) == SendLockedTransfer: assert isinstance(send_event, SendLockedTransfer), MYPY_ANNOTATION message = LockedTransfer.from_event(send_event) elif type(send_event) == SendLockedTransferLight: assert isinstance(send_event, SendLockedTransferLight), MYPY_ANNOTATION message = send_event.signed_locked_transfer elif type(send_event) == SendSecretReveal: assert isinstance(send_event, SendSecretReveal), MYPY_ANNOTATION message = RevealSecret.from_event(send_event) elif type(send_event) == SendSecretRevealLight: assert isinstance(send_event, SendSecretRevealLight), MYPY_ANNOTATION message = send_event.signed_secret_reveal elif type(send_event) == SendBalanceProof: assert isinstance(send_event, SendBalanceProof), MYPY_ANNOTATION message = Unlock.from_event(send_event) elif type(send_event) == SendBalanceProofLight: assert isinstance(send_event, SendBalanceProofLight), MYPY_ANNOTATION message = send_event.signed_balance_proof elif type(send_event) == SendSecretRequest: assert isinstance(send_event, SendSecretRequest), MYPY_ANNOTATION message = SecretRequest.from_event(send_event) elif type(send_event) == SendSecretRequestLight: assert isinstance(send_event, SendSecretRequestLight), MYPY_ANNOTATION message = send_event.signed_secret_request elif type(send_event) == SendRefundTransfer: assert isinstance(send_event, SendRefundTransfer), MYPY_ANNOTATION message = RefundTransfer.from_event(send_event) elif type(send_event) == SendLockExpired: assert isinstance(send_event, SendLockExpired), MYPY_ANNOTATION message = LockExpired.from_event(send_event) elif type(send_event) == SendProcessed: assert isinstance(send_event, SendProcessed), MYPY_ANNOTATION message = Processed.from_event(send_event) else: raise ValueError(f"Unknown event type {send_event}") return message
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)
def test_secret_request(iterations=ITERATIONS): hashlock = HASH msg = SecretRequest(hashlock) msg.sign(PRIVKEY) run_timeit('SecretRequest', msg, iterations=iterations)
def _run(self): # pylint: disable=method-hidden,too-many-locals fee = 0 raiden = self.raiden from_mediated_transfer = self.from_mediated_transfer hashlock = from_mediated_transfer.lock.hashlock from_token = from_mediated_transfer.token to_token = self.to_token to_amount = self.to_amount to_graph = raiden.channelgraphs[to_token] from_graph = raiden.channelgraphs[from_token] from_channel = from_graph.partneraddress_channel[from_mediated_transfer.sender] raiden.register_task_for_hashlock(from_token, self, hashlock) raiden.register_channel_for_hashlock(from_token, from_channel, hashlock) lock_expiration = from_mediated_transfer.lock.expiration - raiden.config['reveal_timeout'] lock_timeout = lock_expiration - raiden.get_block_number() to_routes = to_graph.get_best_routes( raiden.addres, from_mediated_transfer.initiator, # route back to the initiator from_mediated_transfer.lock.amount, lock_timeout, ) if log.isEnabledFor(logging.DEBUG): log.debug( 'EXCHANGE TRANSFER %s -> %s msghash:%s hashlock:%s', pex(from_mediated_transfer.target), pex(from_mediated_transfer.initiator), pex(from_mediated_transfer.hash), pex(hashlock), ) secret_request = SecretRequest( from_mediated_transfer.identifier, from_mediated_transfer.lock.hashlock, from_mediated_transfer.lock.amount, ) raiden.sign(secret_request) raiden.send_async(from_mediated_transfer.initiator, secret_request) for path, to_channel in to_routes: to_next_hop = path[1] to_mediated_transfer = to_channel.create_mediatedtransfer( raiden.address, # this node is the new initiator from_mediated_transfer.initiator, # the initiator is the target for the to_token fee, to_amount, lock_expiration, hashlock, # use the original hashlock ) raiden.sign(to_mediated_transfer) if log.isEnabledFor(logging.DEBUG): log.debug( 'MEDIATED TRANSFER NEW PATH path:%s hashlock:%s', lpex(path), pex(from_mediated_transfer.lock.hashlock), ) # The interest on the hashlock outlives this task, the secret # handling will happen only _once_ raiden.register_channel_for_hashlock(to_token, to_channel, hashlock) to_channel.register_transfer(to_mediated_transfer) response = self.send_and_wait_valid(raiden, to_mediated_transfer) if log.isEnabledFor(logging.DEBUG): log.debug( 'EXCHANGE TRANSFER NEW PATH path:%s hashlock:%s', lpex(path), pex(hashlock), ) # only refunds for `from_token` must be considered (check send_and_wait_valid) if isinstance(response, RefundTransfer): if response.lock.amount != to_mediated_transfer.amount: log.info( 'Partner %s sent an invalid refund message with an invalid amount', pex(to_next_hop), ) raiden.on_hashlock_result(from_token, hashlock, False) return else: to_channel.register_transfer(response) elif isinstance(response, Secret): # claim the from_token raiden.handle_secret( response.identifier, from_token, response.secret, response, hashlock, ) # unlock the to_token raiden.handle_secret( response.identifier, to_token, response.secret, response, hashlock, ) self._wait_for_unlock_or_close( raiden, from_graph, from_channel, from_mediated_transfer, )
def from_dict(cls, data: Dict[str, Any]) -> "ActionSendSecretRequestLight": instance = cls(secret_request=SecretRequest.from_dict( data["secret_request"]), sender=to_canonical_address(data["sender"]), receiver=to_canonical_address(data["receiver"])) return instance
def on_event(self, event): if isinstance(event, SendMediatedTransfer): receiver = event.receiver fee = 0 graph = self.raiden.token_to_channelgraph[event.token] channel = graph.partneraddress_to_channel[receiver] mediated_transfer = channel.create_mediatedtransfer( event.initiator, event.target, fee, event.amount, event.identifier, event.expiration, event.hashlock, ) self.raiden.sign(mediated_transfer) channel.register_transfer( self.raiden.get_block_number(), mediated_transfer, ) self.raiden.send_async(receiver, mediated_transfer) elif isinstance(event, SendRevealSecret): reveal_message = RevealSecret(event.secret) self.raiden.sign(reveal_message) self.raiden.send_async(event.receiver, reveal_message) elif isinstance(event, SendBalanceProof): # TODO: issue #189 # unlock and update remotely (send the Secret message) self.raiden.handle_secret( event.identifier, event.token, event.secret, None, sha3(event.secret), ) elif isinstance(event, SendSecretRequest): secret_request = SecretRequest( event.identifier, event.hashlock, event.amount, ) self.raiden.sign(secret_request) self.raiden.send_async(event.receiver, secret_request) elif isinstance(event, SendRefundTransfer): receiver = event.receiver fee = 0 graph = self.raiden.token_to_channelgraph[event.token] channel = graph.partneraddress_to_channel[receiver] refund_transfer = channel.create_refundtransfer( event.initiator, event.target, fee, event.amount, event.identifier, event.expiration, event.hashlock, ) self.raiden.sign(refund_transfer) channel.register_transfer( self.raiden.get_block_number(), refund_transfer, ) self.raiden.send_async(receiver, refund_transfer) elif isinstance(event, EventTransferSentSuccess): for result in self.raiden.identifier_to_results[event.identifier]: result.set(True) elif isinstance(event, EventTransferSentFailed): for result in self.raiden.identifier_to_results[event.identifier]: result.set(False) elif isinstance(event, UNEVENTEFUL_EVENTS): pass elif isinstance(event, EventUnlockFailed): log.error('UnlockFailed!', initiator=event.initiator, expiration=event.expiration) elif isinstance(event, ContractSendChannelClose): graph = self.raiden.token_to_channelgraph[event.token] channel = graph.address_to_channel[event.channel_address] balance_proof = channel.our_state.balance_proof.balance_proof channel.external_state.close(balance_proof) else: log.error('Unknown event {}'.format(type(event)))
def _run(self): # pylint: disable=method-hidden,too-many-locals fee = 0 raiden = self.raiden tokenswap = self.tokenswap # this is the MediatedTransfer that wil pay the maker's half of the # swap, not necessarily from him maker_paying_transfer = self.from_mediated_transfer # this is the address of the node that the taker actually has a channel # with (might or might not be the maker) maker_payer_hop = maker_paying_transfer.sender assert tokenswap.identifier == maker_paying_transfer.identifier assert tokenswap.from_token == maker_paying_transfer.token assert tokenswap.from_amount == maker_paying_transfer.lock.amount assert tokenswap.from_nodeaddress == maker_paying_transfer.initiator maker_receiving_token = tokenswap.to_token to_amount = tokenswap.to_amount identifier = maker_paying_transfer.identifier hashlock = maker_paying_transfer.lock.hashlock maker_address = maker_paying_transfer.initiator taker_receiving_token = maker_paying_transfer.token taker_paying_token = maker_receiving_token from_graph = raiden.token_to_channelgraph[taker_receiving_token] from_channel = from_graph.partneraddress_to_channel[maker_payer_hop] to_graph = raiden.token_to_channelgraph[maker_receiving_token] # update the channel's distributable and merkle tree from_channel.register_transfer( raiden.get_block_number(), maker_paying_transfer, ) # register the task to receive Refund/Secrect/RevealSecret messages raiden.greenlet_task_dispatcher.register_task(self, hashlock) raiden.register_channel_for_hashlock(taker_receiving_token, from_channel, hashlock) # send to the maker a secret request informing how much the taker will # be _paid_, this is used to inform the maker that his part of the # mediated transfer is okay secret_request = SecretRequest( identifier, maker_paying_transfer.lock.hashlock, maker_paying_transfer.lock.amount, ) raiden.sign(secret_request) raiden.send_async(maker_address, secret_request) lock_expiration = maker_paying_transfer.lock.expiration - raiden.config['reveal_timeout'] # Note: taker may only try different routes if a RefundTransfer is # received, because the maker is the node controlling the secret available_routes = get_best_routes( to_graph, raiden.protocol.nodeaddresses_networkstatuses, raiden.address, maker_address, maker_paying_transfer.lock.amount, previous_address=None, ) if not available_routes: if log.isEnabledFor(logging.DEBUG): node_address = raiden.address log.debug( 'TAKER TOKEN SWAP FAILED, NO ROUTES', from_=pex(node_address), to=pex(maker_address), ) return first_transfer = None for route in available_routes: taker_paying_channel = to_graph.get_channel_by_contract_address( route.channel_address, ) taker_paying_hop = route.node_address if log.isEnabledFor(logging.DEBUG): log.debug( 'TAKER TOKEN SWAP', from_=pex(maker_paying_transfer.target), to=pex(maker_address), msghash=pex(maker_paying_transfer.hash), hashlock=pex(hashlock), ) # make a paying MediatedTransfer with same hashlock/identifier and the # taker's paying token/amount taker_paying_transfer = taker_paying_channel.create_mediatedtransfer( raiden.address, maker_address, fee, to_amount, identifier, lock_expiration, hashlock, ) raiden.sign(taker_paying_transfer) taker_paying_channel.register_transfer( raiden.get_block_number(), taker_paying_transfer, ) if not first_transfer: first_transfer = taker_paying_transfer if log.isEnabledFor(logging.DEBUG): log.debug( 'EXCHANGE TRANSFER NEW PATH', path=lpex(taker_paying_hop), hashlock=pex(hashlock), ) # register the task to receive Refund/Secrect/RevealSecret messages raiden.register_channel_for_hashlock( maker_receiving_token, taker_paying_channel, hashlock, ) response, secret = self.send_and_wait_valid( raiden, taker_paying_transfer, maker_payer_hop, ) # only refunds for `maker_receiving_token` must be considered # (check send_and_wait_valid) if isinstance(response, RefundTransfer): if response.lock.amount != taker_paying_transfer.amount: log.info( 'Partner %s sent an invalid refund message with an invalid amount', pex(taker_paying_hop), ) raiden.greenlet_task_dispatcher.unregister_task(self, hashlock, False) return else: taker_paying_channel.register_transfer( raiden.get_block_number(), response, ) elif isinstance(response, RevealSecret): # the secret was registered by the message handler # wait for the taker_paying_hop to reveal the secret prior to # unlocking locally if response.sender != taker_paying_hop: response = self.wait_reveal_secret( raiden, taker_paying_hop, taker_paying_transfer.lock.expiration, ) # unlock and send the Secret message raiden.handle_secret( identifier, taker_paying_token, response.secret, None, hashlock, ) # if the secret arrived early, withdraw it, otherwise send the # RevealSecret forward in the maker-path if secret: raiden.handle_secret( identifier, taker_receiving_token, response.secret, secret, hashlock, ) # wait for the withdraw in case it did not happen yet self._wait_for_unlock_or_close( raiden, from_graph, from_channel, maker_paying_transfer, ) return # the lock expired else: if log.isEnabledFor(logging.DEBUG): node_address = raiden.address log.debug( 'TAKER TOKEN SWAP FAILED', from_=pex(node_address), to=pex(maker_address), ) self.async_result.set(False) return # no route is available, wait for the sent mediated transfer to expire self._wait_expiration(raiden, first_transfer) if log.isEnabledFor(logging.DEBUG): node_address = raiden.address log.debug( 'TAKER TOKEN SWAP FAILED', from_=pex(node_address), to=pex(maker_address), ) self.async_result.set(False)
def handle_inittarget_light( state_change: ActionInitTargetLight, channel_state: NettingChannelState, pseudo_random_generator: random.Random, block_number: BlockNumber, storage ) -> TransitionResult[TargetTransferState]: """ Handles an ActionInitTarget state change. """ transfer = state_change.transfer route = state_change.route assert channel_state.identifier == transfer.balance_proof.channel_identifier is_valid, channel_events, errormsg, handle_invoice_result = channel.handle_receive_lockedtransfer_light( channel_state, transfer, storage ) if is_valid: # A valid balance proof does not mean the payment itself is still valid. # e.g. the lock may be near expiration or have expired. This is fine. The # message with an unusable lock must be handled to properly synchronize the # local view of the partner's channel state, allowing the next balance # proofs to be handled. This however, must only be done once, which is # enforced by the nonce increasing sequentially, which is verified by # the handler handle_receive_lockedtransfer. target_state = TargetTransferState(route, transfer) safe_to_wait, _ = is_safe_to_wait( transfer.lock.expiration, channel_state.reveal_timeout, block_number ) # If there is not enough time to safely unlock the lock on-chain # silently let the transfer expire. The target task must be created to # handle the ReceiveLockExpired state change, which will clear the # expired lock. # # We add a new validation. # It is verified that if there was an invoice it was paid successfully, # if it was not, the payment is interrupted # by not generating an event send secret request if safe_to_wait and handle_invoice_result['is_valid']: payment = LightClientPayment( state_change.transfer.target, state_change.transfer.initiator, False, channel_state.token_network_identifier, transfer.lock.amount, str(date.today()), LightClientPaymentStatus.Pending, transfer.payment_identifier ) payment_exists = LightClientService.get_light_client_payment(payment.payment_id, storage) if not payment_exists: LightClientMessageHandler.store_light_client_payment(payment, storage) message_identifier = message_identifier_from_prng(pseudo_random_generator) recipient = transfer.initiator secret_request = SendSecretRequest( recipient=Address(recipient), channel_identifier=CHANNEL_IDENTIFIER_GLOBAL_QUEUE, message_identifier=message_identifier, payment_identifier=transfer.payment_identifier, amount=transfer.lock.amount, expiration=transfer.lock.expiration, secrethash=transfer.lock.secrethash, ) store_locked_transfer_event = StoreMessageEvent(transfer.message_identifier, transfer.payment_identifier, 1, state_change.signed_lockedtransfer, True) secret_request_message = SecretRequest.from_event(secret_request) store_secret_request_event = StoreMessageEvent(message_identifier, transfer.payment_identifier, 5, secret_request_message, False) channel_events.append(store_secret_request_event) channel_events.append(store_locked_transfer_event) iteration = TransitionResult(target_state, channel_events) else: # If the balance proof is not valid, do *not* create a task. Otherwise it's # possible for an attacker to send multiple invalid transfers, and increase # the memory usage of this Node. assert errormsg, "handle_receive_lockedtransfer should return error msg if not valid" unlock_failed = EventUnlockClaimFailed( identifier=transfer.payment_identifier, secrethash=transfer.lock.secrethash, reason=errormsg, ) channel_events.append(unlock_failed) iteration = TransitionResult(None, channel_events) return iteration
def _run(self): # pylint: disable=method-hidden raiden = self.raiden originating_transfer = self.originating_transfer hashlock = originating_transfer.lock.hashlock assetmanager = raiden.get_manager_by_asset_address(self.asset_address) transfermanager = assetmanager.transfermanager originating_channel = assetmanager.get_channel_by_partner_address( originating_transfer.sender, ) transfermanager.register_task_for_hashlock(self, hashlock) assetmanager.register_channel_for_hashlock(originating_channel, hashlock) if log.isEnabledFor(logging.DEBUG): log.debug( 'END MEDIATED TRANSFER %s -> %s msghash:%s hashlock:%s', pex(originating_transfer.target), pex(originating_transfer.initiator), pex(originating_transfer.hash), pex(originating_transfer.lock.hashlock), ) secret_request = SecretRequest( originating_transfer.identifier, originating_transfer.lock.hashlock, originating_transfer.lock.amount, ) raiden.sign(secret_request) # If the transfer timed out in the initiator a new hashlock will be # created and this task will not receive a secret, this is fine because # the task will eventually exit once a blocktimeout happens and a new # task will be created for the new hashlock valid_messages_iterator = self.send_secretrequest_and_iter_valid( raiden, originating_transfer, secret_request, ) for response in valid_messages_iterator: # at this point a Secret message is not valid if isinstance(response, RevealSecret): assetmanager.handle_secret( originating_transfer.identifier, response.secret, ) self._wait_for_unlock_or_close( raiden, assetmanager, originating_channel, originating_transfer, ) transfermanager.on_hashlock_result(hashlock, True) return elif response is TIMEOUT: # this task timeouts on a blocknumber, at this point all the other # nodes have timedout transfermanager.on_hashlock_result( originating_transfer.lock.hashlock, False) break
def _run(self): # pylint: disable=method-hidden,too-many-locals fee = 0 raiden = self.raiden from_mediated_transfer = self.from_mediated_transfer hashlock = from_mediated_transfer.lock.hashlock from_asset = from_mediated_transfer.asset to_asset = self.to_asset to_amount = self.to_amount to_assetmanager = raiden.get_manager_by_asset_address(to_asset) from_assetmanager = raiden.get_manager_by_asset_address(from_asset) from_transfermanager = from_assetmanager.transfermanager from_channel = from_assetmanager.get_channel_by_partner_address( from_mediated_transfer.sender, ) from_transfermanager.register_task_for_hashlock(self, hashlock) from_assetmanager.register_channel_for_hashlock(from_channel, hashlock) lock_expiration = from_mediated_transfer.lock.expiration - raiden.config[ 'reveal_timeout'] lock_timeout = lock_expiration - raiden.chain.block_number() to_routes = to_assetmanager.get_best_routes( from_mediated_transfer.lock.amount, from_mediated_transfer.initiator, # route back to the initiator lock_timeout, ) if log.isEnabledFor(logging.DEBUG): log.debug( 'EXCHANGE TRANSFER %s -> %s msghash:%s hashlock:%s', pex(from_mediated_transfer.target), pex(from_mediated_transfer.initiator), pex(from_mediated_transfer.hash), pex(hashlock), ) secret_request = SecretRequest( from_mediated_transfer.identifier, from_mediated_transfer.lock.hashlock, from_mediated_transfer.lock.amount, ) raiden.sign(secret_request) raiden.send_async(from_mediated_transfer.initiator, secret_request) for path, to_channel in to_routes: to_next_hop = path[1] to_mediated_transfer = to_channel.create_mediatedtransfer( raiden.address, # this node is the new initiator from_mediated_transfer. initiator, # the initiator is the target for the to_asset fee, to_amount, lock_expiration, hashlock, # use the original hashlock ) raiden.sign(to_mediated_transfer) if log.isEnabledFor(logging.DEBUG): log.debug( 'MEDIATED TRANSFER NEW PATH path:%s hashlock:%s', lpex(path), pex(from_mediated_transfer.lock.hashlock), ) # Using assetmanager to register the interest because it outlives # this task, the secret handling will happen only _once_ to_assetmanager.register_channel_for_hashlock( to_channel, hashlock, ) to_channel.register_transfer(to_mediated_transfer) response = self.send_and_wait_valid(raiden, to_mediated_transfer) if log.isEnabledFor(logging.DEBUG): log.debug( 'EXCHANGE TRANSFER NEW PATH path:%s hashlock:%s', lpex(path), pex(hashlock), ) # only refunds for `from_asset` must be considered (check send_and_wait_valid) if isinstance(response, RefundTransfer): if response.lock.amount != to_mediated_transfer.amount: log.info( 'Partner %s sent an invalid refund message with an invalid amount', pex(to_next_hop), ) timeout_message = from_channel.create_timeouttransfer_for( from_mediated_transfer) raiden.send_async(from_mediated_transfer.sender, timeout_message) self.transfermanager.on_hashlock_result(hashlock, False) return else: to_channel.register_transfer(response) elif isinstance(response, Secret): # this node is receiving the from_asset and sending the # to_asset, meaning that it can claim the to_asset but it needs # a Secret message to claim the from_asset to_assetmanager.handle_secretmessage(response) from_assetmanager.handle_secretmessage(response) self._wait_for_unlock_or_close( raiden, from_assetmanager, from_channel, from_mediated_transfer, )