def _initialize_messages_queues(self, chain_state: ChainState): """ Push the queues to the transport and populate targets_to_identifiers_to_statuses. """ events_queues = views.get_all_messagequeues(chain_state) for queue_identifier, event_queue in events_queues.items(): self.start_health_check_for(queue_identifier.recipient) for event in event_queue: is_initiator = ( type(event) == SendLockedTransfer and event.transfer.initiator == self.address ) if is_initiator: self._register_payment_status( target=event.transfer.target, identifier=event.transfer.payment_identifier, balance_proof=event.transfer.balance_proof, ) message = message_from_sendevent(event, self.address) self.sign(message) self.transport.send_async(queue_identifier, message)
def _initialize_messages_queues(self, chain_state): """ Push the queues to the transport and populate targets_to_identifiers_to_statuses. """ events_queues = views.get_all_messagequeues(chain_state) for queue_identifier, event_queue in events_queues.items(): self.start_health_check_for(queue_identifier.recipient) for event in event_queue: is_initiator = ( type(event) == SendLockedTransfer and event.transfer.initiator == self.address ) if type(event) == SendDirectTransfer: self._register_payment_status( target=event.recipient, identifier=event.payment_identifier, payment_type=PaymentType.DIRECT, balance_proof=event.balance_proof, ) elif is_initiator: self._register_payment_status( target=event.transfer.target, identifier=event.transfer.payment_identifier, payment_type=PaymentType.MEDIATED, balance_proof=event.transfer.balance_proof, ) message = message_from_sendevent(event, self.address) self.sign(message) self.transport.send_async(queue_identifier, message)
def start( self, raiden: RaidenService, queueids_to_queues: typing.List[SendMessageEvent], ): self.raiden = raiden self.queueids_to_queues = dict() # server.stop() clears the handle. Since this may be a restart the # handle must always be set self.server.set_handle(self._receive) for (recipient, queue_name), queue in queueids_to_queues.items(): encoded_queue = list() for sendevent in queue: message = message_from_sendevent(sendevent, raiden.address) raiden.sign(message) encoded = message.encode() encoded_queue.append((encoded, sendevent.message_identifier)) self.init_queue_for(recipient, queue_name, encoded_queue) self.server.start()
def cross_handle_recieved_locked_transfer(self, transfer, cross_id): self.start_health_check_for(transfer.initiator) state_change = target_init(transfer) block_number = self.get_block_number() event_list = self.wal.log_and_dispatch(state_change, block_number) for event in event_list: log.debug('RAIDEN EVENT', node=pex(self.address), raiden_event=event) if type(event) == SendSecretRequest: secret_request_message = message_from_sendevent( event, self.address) self.sign(secret_request_message) cross_secret_request_message = CrossSecretRequest( secret_request_message, cross_id) self.sign(cross_secret_request_message) self.transport.send_async( event.recipient, event.queue_name, cross_secret_request_message, ) continue on_raiden_event(self, event) return event_list
def _initialize_messages_queues(self, chain_state: ChainState): """Initialize all the message queues with the transport. Note: All messages from the state queues must be pushed to the transport before it's started. This is necessary to avoid a race where the transport processes network messages too quickly, queueing new messages before any of the previous messages, resulting in new messages being out-of-order. The Alarm task must be started before this method is called, otherwise queues for channel closed while the node was offline won't be properly cleared. It is not bad but it is suboptimal. """ assert not self.transport, f"Transport is running. node:{self!r}" assert self.alarm.is_primed(), f"AlarmTask not primed. node:{self!r}" events_queues = views.get_all_messagequeues(chain_state) for queue_identifier, event_queue in events_queues.items(): self.start_health_check_for(queue_identifier.recipient) for event in event_queue: message = message_from_sendevent(event) self.sign(message) self.transport.send_async(queue_identifier, message)
def handle_send_lockedtransfer(raiden: "RaidenService", send_locked_transfer: SendLockedTransfer): mediated_transfer_message = message_from_sendevent( send_locked_transfer) raiden.sign(mediated_transfer_message) raiden.transport.send_async(send_locked_transfer.queue_identifier, mediated_transfer_message)
def handle_cross_state_change(self, state_change, cross_id, secret, btc_amount, block_number=None): if block_number is None: block_number = self.get_block_number() event_list = self.wal.log_and_dispatch(state_change, block_number) row = self.wal.storage.get_lnd(1) macaroon = row[4] lnd_url = "https://{}/v1/invoices".format(self.config['lnd_address']) lnd_headers = {'Grpc-Metadata-macaroon': macaroon} lnd_r = base64.b64encode(secret) lnd_data = { 'value': btc_amount, 'r_preimage': lnd_r.decode('utf-8'), 'type': "CROSS_CHAIN_INVOICE" } res = requests.post(lnd_url, headers=lnd_headers, data=json.dumps(lnd_data), verify=False) res_json = res.json() lnd_r_hash = res_json['r_hash'] lnd_payment_request = res_json['payment_request'] print('send invoice succ, lnd_r_hash:', lnd_r_hash) for event in event_list: log.debug('RAIDEN EVENT', node=pex(self.address), raiden_event=event) if type(event) == SendLockedTransfer: locked_transfer_message = message_from_sendevent( event, self.address) self.sign(locked_transfer_message) self.wal.storage.change_crosstransaction_r( cross_id, encode_hex(locked_transfer_message.lock.secrethash), lnd_r_hash) tmp_r_hash = base64.b64decode(lnd_r_hash) raiden_r_hash = locked_transfer_message.lock.secrethash hex_r_hash = encode_hex(tmp_r_hash) lnd_string = bytes(lnd_payment_request, "utf-8") cross_transfer_message = CrossLockedTransfer( locked_transfer_message, cross_id, lnd_string) self.sign(cross_transfer_message) self.transport.send_async(cross_transfer_message.recipient, bytes("456", 'utf-8'), cross_transfer_message) print('corss_message send ok') continue on_raiden_event(self, event)
def handle_send_refundtransfer( raiden: "RaidenService", refund_transfer_event: SendRefundTransfer ): refund_transfer_message = message_from_sendevent(refund_transfer_event) raiden.sign(refund_transfer_message) raiden.transport.send_async( refund_transfer_event.queue_identifier, refund_transfer_message )
def handle_send_secretrequest( raiden: "RaidenService", secret_request_event: SendSecretRequest ): if reveal_secret_with_resolver(raiden, secret_request_event): return secret_request_message = message_from_sendevent(secret_request_event) raiden.sign(secret_request_message) raiden.transport.send_async(secret_request_event.queue_identifier, secret_request_message)
def handle_send_crosstransaction( raiden: RaidenService, send_crosstransaction_event: SendCrosstransaction): crosstransaction_message = message_from_sendevent( send_crosstransaction_event, raiden.address) raiden.sign(crosstransaction_message) raiden.transport.send_async(send_crosstransaction_event.recipient, send_crosstransaction_event.queue_name, crosstransaction_message)
def handle_send_balanceproof( raiden: 'RaidenService', balance_proof_event: SendBalanceProof, ): unlock_message = message_from_sendevent(balance_proof_event) raiden.sign(unlock_message) raiden.transport.send_async( balance_proof_event.queue_identifier, unlock_message, )
def handle_send_secretreveal( raiden: 'RaidenService', reveal_secret_event: SendSecretReveal, ): reveal_secret_message = message_from_sendevent(reveal_secret_event) raiden.sign(reveal_secret_message) raiden.transport.send_async( reveal_secret_event.queue_identifier, reveal_secret_message, )
def handle_send_lockexpired( raiden: 'RaidenService', send_lock_expired: SendLockExpired, ): lock_expired_message = message_from_sendevent(send_lock_expired) raiden.sign(lock_expired_message) raiden.transport.send_async( send_lock_expired.queue_identifier, lock_expired_message, )
def handle_send_balanceproof( raiden: RaidenService, balance_proof_event: SendBalanceProof, ): secret_message = message_from_sendevent(balance_proof_event, raiden.address) raiden.sign(secret_message) raiden.transport.send_async( balance_proof_event.queue_identifier, secret_message, )
def handle_send_secretrequest( raiden: RaidenService, secret_request_event: SendSecretRequest, ): secret_request_message = message_from_sendevent(secret_request_event, raiden.address) raiden.sign(secret_request_message) raiden.transport.send_async( secret_request_event.queue_identifier, secret_request_message, )
def handle_send_processed( raiden: RaidenService, processed_event: SendProcessed, ): processed_message = message_from_sendevent(processed_event, raiden.address) raiden.sign(processed_message) raiden.transport.send_async( processed_event.queue_identifier, processed_message, )
def handle_send_revealsecret( raiden: RaidenService, reveal_secret_event: SendRevealSecret, ): reveal_secret_message = message_from_sendevent(reveal_secret_event, raiden.address) raiden.sign(reveal_secret_message) raiden.transport.send_async( reveal_secret_event.queue_identifier, reveal_secret_message, )
def handle_send_directtransfer( raiden: RaidenService, send_direct_transfer: SendDirectTransfer, ): direct_transfer_message = message_from_sendevent(send_direct_transfer, raiden.address) raiden.sign(direct_transfer_message) raiden.transport.send_async( send_direct_transfer.queue_identifier, direct_transfer_message, )
def handle_send_refundtransfer( self, raiden: RaidenService, refund_transfer_event: SendRefundTransfer, ): refund_transfer_message = message_from_sendevent(refund_transfer_event, raiden.address) raiden.sign(refund_transfer_message) raiden.transport.send_async( refund_transfer_event.queue_identifier, refund_transfer_message, )
def handle_send_balanceproof( self, raiden: RaidenService, balance_proof_event: SendBalanceProof, ): secret_message = message_from_sendevent(balance_proof_event, raiden.address) raiden.sign(secret_message) raiden.transport.send_async( balance_proof_event.queue_identifier, secret_message, )
def handle_send_secretrequest( self, raiden: RaidenService, secret_request_event: SendSecretRequest, ): secret_request_message = message_from_sendevent(secret_request_event, raiden.address) raiden.sign(secret_request_message) raiden.transport.send_async( secret_request_event.queue_identifier, secret_request_message, )
def handle_send_processed( raiden: 'RaidenService', processed_event: SendProcessed, ): processed_message = message_from_sendevent(processed_event, raiden.address) raiden.sign(processed_message) raiden.protocol.send_async( processed_event.recipient, processed_event.queue_name, processed_message, )
def handle_send_directtransfer( raiden: RaidenService, send_direct_transfer: SendDirectTransfer, ): direct_transfer_message = message_from_sendevent(send_direct_transfer, raiden.address) raiden.sign(direct_transfer_message) raiden.transport.send_async( send_direct_transfer.recipient, send_direct_transfer.queue_name, direct_transfer_message, )
def handle_send_lockedtransfer( self, raiden: RaidenService, send_locked_transfer: SendLockedTransfer, ): mediated_transfer_message = message_from_sendevent(send_locked_transfer, raiden.address) raiden.sign(mediated_transfer_message) raiden.transport.send_async( send_locked_transfer.queue_identifier, mediated_transfer_message, )
def handle_send_revealsecret( raiden: RaidenService, reveal_secret_event: SendRevealSecret, ): reveal_secret_message = message_from_sendevent(reveal_secret_event, raiden.address) raiden.sign(reveal_secret_message) raiden.transport.send_async( reveal_secret_event.recipient, reveal_secret_event.queue_name, reveal_secret_message, )
def handle_send_lockexpired( self, raiden: RaidenService, send_lock_expired: SendLockExpired, ): lock_expired_message = message_from_sendevent(send_lock_expired, raiden.address) raiden.sign(lock_expired_message) raiden.transport.send_async( send_lock_expired.queue_identifier, lock_expired_message, )
def _initialize_messages_queues(self, chain_state: ChainState): """ Push the message queues to the transport. """ events_queues = views.get_all_messagequeues(chain_state) for queue_identifier, event_queue in events_queues.items(): self.start_health_check_for(queue_identifier.recipient) for event in event_queue: message = message_from_sendevent(event, self.address) self.sign(message) self.transport.send_async(queue_identifier, message)
def handle_send_secretreveal( self, raiden: RaidenService, reveal_secret_event: SendSecretReveal, ): reveal_secret_message = message_from_sendevent(reveal_secret_event, raiden.address) raiden.sign(reveal_secret_message) raiden.transport.send_async( reveal_secret_event.queue_identifier, reveal_secret_message, )
def handle_send_processed( self, raiden: RaidenService, processed_event: SendProcessed, ): processed_message = message_from_sendevent(processed_event, raiden.address) raiden.sign(processed_message) raiden.transport.send_async( processed_event.queue_identifier, processed_message, )
def handle_send_directtransfer( raiden: 'RaidenService', send_direct_transfer: SendDirectTransfer, ): direct_transfer_message = message_from_sendevent(send_direct_transfer, raiden.address) raiden.sign(direct_transfer_message) raiden.protocol.send_async( send_direct_transfer.recipient, send_direct_transfer.queue_name, direct_transfer_message, )
def handle_send_balanceproof( raiden: 'RaidenService', balance_proof_event: SendBalanceProof, ): secret_message = message_from_sendevent(balance_proof_event, raiden.address) raiden.sign(secret_message) raiden.protocol.send_async( balance_proof_event.recipient, balance_proof_event.queue_name, secret_message, )
def handle_send_revealsecret( raiden: 'RaidenService', reveal_secret_event: SendRevealSecret, ): reveal_secret_message = message_from_sendevent(reveal_secret_event, raiden.address) raiden.sign(reveal_secret_message) raiden.protocol.send_async( reveal_secret_event.recipient, reveal_secret_event.queue_name, reveal_secret_message, )
def handle_send_refundtransfer( raiden: 'RaidenService', refund_transfer_event: SendRefundTransfer, ): refund_transfer_message = message_from_sendevent(refund_transfer_event, raiden.address) raiden.sign(refund_transfer_message) raiden.protocol.send_async( refund_transfer_event.recipient, refund_transfer_event.queue_name, refund_transfer_message, )
def handle_send_lockedtransfer( raiden: 'RaidenService', send_locked_transfer: SendLockedTransfer, ): mediated_transfer_message = message_from_sendevent(send_locked_transfer, raiden.address) raiden.sign(mediated_transfer_message) raiden.protocol.send_async( mediated_transfer_message.recipient, send_locked_transfer.queue_name, mediated_transfer_message, )
def handle_send_secretrequest( raiden: 'RaidenService', secret_request_event: SendSecretRequest, ): secret_request_message = message_from_sendevent(secret_request_event, raiden.address) raiden.sign(secret_request_message) raiden.protocol.send_async( secret_request_event.recipient, secret_request_event.queue_name, secret_request_message, )
def test_regression_onchain_secret_reveal_must_update_channel_state(): """ If a secret is learned off-chain and then on-chain, the state of the lock must be updated in the channel. """ pseudo_random_generator = random.Random() setup = factories.make_transfers_pair(2, block_number=10) mediator_state = MediatorTransferState( secrethash=UNIT_SECRETHASH, routes=setup.channels.get_routes(), ) mediator_state.transfers_pair = setup.transfers_pair secret = UNIT_SECRET secrethash = UNIT_SECRETHASH payer_channel = mediator.get_payer_channel(setup.channel_map, setup.transfers_pair[0]) payee_channel = mediator.get_payee_channel(setup.channel_map, setup.transfers_pair[0]) lock = payer_channel.partner_state.secrethashes_to_lockedlocks[secrethash] mediator.state_transition( mediator_state=mediator_state, state_change=ReceiveSecretReveal(secret, payee_channel.partner_state.address), channelidentifiers_to_channels=setup.channel_map, nodeaddresses_to_networkstates=setup.channels. nodeaddresses_to_networkstates, pseudo_random_generator=pseudo_random_generator, block_number=setup.block_number, block_hash=setup.block_hash, ) assert secrethash in payer_channel.partner_state.secrethashes_to_unlockedlocks secret_registry_address = factories.make_address() transaction_hash = factories.make_address() mediator.state_transition( mediator_state=mediator_state, state_change=ContractReceiveSecretReveal( transaction_hash=transaction_hash, secret_registry_address=secret_registry_address, secrethash=secrethash, secret=secret, block_number=setup.block_number, block_hash=setup.block_hash, ), channelidentifiers_to_channels=setup.channel_map, nodeaddresses_to_networkstates=setup.channels. nodeaddresses_to_networkstates, pseudo_random_generator=pseudo_random_generator, block_number=setup.block_number, block_hash=setup.block_hash, ) assert secrethash in payer_channel.partner_state.secrethashes_to_onchain_unlockedlocks # Creates a transfer as it was from the *partner* send_lock_expired, _ = channel.create_sendexpiredlock( sender_end_state=payer_channel.partner_state, locked_lock=lock, pseudo_random_generator=pseudo_random_generator, chain_id=payer_channel.chain_id, token_network_identifier=payer_channel.token_network_identifier, channel_identifier=payer_channel.identifier, recipient=payer_channel.our_state.address, ) assert send_lock_expired expired_message = message_from_sendevent(send_lock_expired, setup.channels.our_address(0)) expired_message.sign(LocalSigner(setup.channels.partner_privatekeys[0])) balance_proof = balanceproof_from_envelope(expired_message) message_identifier = message_identifier_from_prng(pseudo_random_generator) expired_block_number = channel.get_sender_expiration_threshold(lock) mediator.state_transition( mediator_state=mediator_state, state_change=ReceiveLockExpired( balance_proof=balance_proof, secrethash=secrethash, message_identifier=message_identifier, ), channelidentifiers_to_channels=setup.channel_map, nodeaddresses_to_networkstates=setup.channels. nodeaddresses_to_networkstates, pseudo_random_generator=pseudo_random_generator, block_number=expired_block_number, block_hash=factories.make_block_hash(), ) assert secrethash in payer_channel.partner_state.secrethashes_to_onchain_unlockedlocks
def test_regression_mediator_task_no_routes(): """ The mediator must only be cleared after the waiting transfer's lock has been handled. If a node receives a transfer to mediate, but there is no route available (because there is no sufficient capacity or the partner nodes are offline), and a refund is not possible, the mediator task must not be cleared, otherwise followup remove expired lock messages wont be processed and the nodes will get out of sync. """ pseudo_random_generator = random.Random() channels = make_channel_set([ NettingChannelStateProperties( our_state=NettingChannelEndStateProperties(balance=0), partner_state=NettingChannelEndStateProperties( balance=10, address=HOP2, privatekey=HOP2_KEY, ), ), ]) payer_transfer = factories.make_signed_transfer_for( channels[0], factories.LockedTransferSignedStateProperties( sender=HOP2, pkey=HOP2_KEY, transfer=factories.LockedTransferProperties(expiration=30), )) init_state_change = ActionInitMediator( channels.get_routes(), channels.get_route(0), payer_transfer, ) init_iteration = mediator.state_transition( mediator_state=None, state_change=init_state_change, channelidentifiers_to_channels=channels.channel_map, nodeaddresses_to_networkstates=channels.nodeaddresses_to_networkstates, pseudo_random_generator=pseudo_random_generator, block_number=5, block_hash=factories.make_block_hash(), ) msg = 'The task must not be cleared, even if there is no route to forward the transfer' assert init_iteration.new_state is not None, msg assert init_iteration.new_state.waiting_transfer.transfer == payer_transfer assert search_for_item(init_iteration.events, SendLockedTransfer, {}) is None assert search_for_item(init_iteration.events, SendRefundTransfer, {}) is None secrethash = UNIT_SECRETHASH lock = channels[0].partner_state.secrethashes_to_lockedlocks[secrethash] # Creates a transfer as it was from the *partner* send_lock_expired, _ = channel.create_sendexpiredlock( sender_end_state=channels[0].partner_state, locked_lock=lock, pseudo_random_generator=pseudo_random_generator, chain_id=channels[0].chain_id, token_network_identifier=channels[0].token_network_identifier, channel_identifier=channels[0].identifier, recipient=channels[0].our_state.address, ) assert send_lock_expired lock_expired_message = message_from_sendevent(send_lock_expired, HOP1) lock_expired_message.sign(LocalSigner(channels.partner_privatekeys[0])) balance_proof = balanceproof_from_envelope(lock_expired_message) message_identifier = message_identifier_from_prng(pseudo_random_generator) # Regression: The mediator must still be able to process the block which # expires the lock expired_block_number = channel.get_sender_expiration_threshold(lock) block_hash = factories.make_block_hash() expire_block_iteration = mediator.state_transition( mediator_state=init_iteration.new_state, state_change=Block( block_number=expired_block_number, gas_limit=0, block_hash=block_hash, ), channelidentifiers_to_channels=channels.channel_map, nodeaddresses_to_networkstates=channels.nodeaddresses_to_networkstates, pseudo_random_generator=pseudo_random_generator, block_number=expired_block_number, block_hash=block_hash, ) assert expire_block_iteration.new_state is not None receive_expired_iteration = mediator.state_transition( mediator_state=expire_block_iteration.new_state, state_change=ReceiveLockExpired( balance_proof=balance_proof, secrethash=secrethash, message_identifier=message_identifier, ), channelidentifiers_to_channels=channels.channel_map, nodeaddresses_to_networkstates=channels.nodeaddresses_to_networkstates, pseudo_random_generator=pseudo_random_generator, block_number=expired_block_number, block_hash=block_hash, ) msg = 'The only used channel had the lock cleared, the task must be cleared' assert receive_expired_iteration.new_state is None, msg assert secrethash not in channels[ 0].partner_state.secrethashes_to_lockedlocks
def test_regression_mediator_task_no_routes(): """ The mediator must only be cleared after the waiting transfer's lock has been handled. If a node receives a transfer to mediate, but there is no route available (because there is no sufficient capacity or the partner nodes are offline), and a refund is not possible, the mediator task must not be cleared, otherwise followup remove expired lock messages wont be processed and the nodes will get out of sync. """ pseudo_random_generator = random.Random() channels = make_channel_set([ NettingChannelStateProperties( our_state=NettingChannelEndStateProperties(balance=0), partner_state=NettingChannelEndStateProperties( balance=10, address=HOP2, privatekey=HOP2_KEY, ), ), ]) payer_transfer = factories.make_signed_transfer_for( channels[0], factories.LockedTransferSignedStateProperties( sender=HOP2, pkey=HOP2_KEY, transfer=factories.LockedTransferProperties(expiration=30), )) init_state_change = ActionInitMediator( channels.get_routes(), channels.get_route(0), payer_transfer, ) init_iteration = mediator.state_transition( mediator_state=None, state_change=init_state_change, channelidentifiers_to_channels=channels.channel_map, pseudo_random_generator=pseudo_random_generator, block_number=5, ) msg = 'The task must not be cleared, even if there is no route to forward the transfer' assert init_iteration.new_state is not None, msg assert init_iteration.new_state.waiting_transfer.transfer == payer_transfer assert must_contain_entry(init_iteration.events, SendLockedTransfer, {}) is None assert must_contain_entry(init_iteration.events, SendRefundTransfer, {}) is None secrethash = UNIT_SECRETHASH lock = channels[0].partner_state.secrethashes_to_lockedlocks[secrethash] # Creates a transfer as it was from the *partner* send_lock_expired, _ = channel.create_sendexpiredlock( sender_end_state=channels[0].partner_state, locked_lock=lock, pseudo_random_generator=pseudo_random_generator, chain_id=channels[0].chain_id, token_network_identifier=channels[0].token_network_identifier, channel_identifier=channels[0].identifier, recipient=channels[0].our_state.address, ) assert send_lock_expired lock_expired_message = message_from_sendevent(send_lock_expired, HOP1) lock_expired_message.sign(channels.partner_privatekeys[0]) balance_proof = balanceproof_from_envelope(lock_expired_message) message_identifier = message_identifier_from_prng(pseudo_random_generator) # Regression: The mediator must still be able to process the block which # expires the lock expired_block_number = channel.get_sender_expiration_threshold(lock) expire_block_iteration = mediator.state_transition( mediator_state=init_iteration.new_state, state_change=Block( block_number=expired_block_number, gas_limit=0, block_hash=None, ), channelidentifiers_to_channels=channels.channel_map, pseudo_random_generator=pseudo_random_generator, block_number=expired_block_number, ) assert expire_block_iteration.new_state is not None receive_expired_iteration = mediator.state_transition( mediator_state=expire_block_iteration.new_state, state_change=ReceiveLockExpired( balance_proof=balance_proof, secrethash=secrethash, message_identifier=message_identifier, ), channelidentifiers_to_channels=channels.channel_map, pseudo_random_generator=pseudo_random_generator, block_number=expired_block_number, ) msg = 'The only used channel had the lock cleared, the task must be cleared' assert receive_expired_iteration.new_state is None, msg assert secrethash not in channels[0].partner_state.secrethashes_to_lockedlocks
def test_regression_onchain_secret_reveal_must_update_channel_state(): """ If a secret is learned off-chain and then on-chain, the state of the lock must be updated in the channel. """ pseudo_random_generator = random.Random() setup = factories.make_transfers_pair(2, block_number=10) mediator_state = MediatorTransferState(UNIT_SECRETHASH) mediator_state.transfers_pair = setup.transfers_pair secret = UNIT_SECRET secrethash = UNIT_SECRETHASH payer_channel = mediator.get_payer_channel(setup.channel_map, setup.transfers_pair[0]) payee_channel = mediator.get_payee_channel(setup.channel_map, setup.transfers_pair[0]) lock = payer_channel.partner_state.secrethashes_to_lockedlocks[secrethash] mediator.state_transition( mediator_state=mediator_state, state_change=ReceiveSecretReveal(secret, payee_channel.partner_state.address), channelidentifiers_to_channels=setup.channel_map, pseudo_random_generator=pseudo_random_generator, block_number=setup.block_number, ) assert secrethash in payer_channel.partner_state.secrethashes_to_unlockedlocks secret_registry_address = factories.make_address() transaction_hash = factories.make_address() mediator.state_transition( mediator_state=mediator_state, state_change=ContractReceiveSecretReveal( transaction_hash, secret_registry_address, secrethash, secret, setup.block_number, ), channelidentifiers_to_channels=setup.channel_map, pseudo_random_generator=pseudo_random_generator, block_number=setup.block_number, ) assert secrethash in payer_channel.partner_state.secrethashes_to_onchain_unlockedlocks # Creates a transfer as it was from the *partner* send_lock_expired, _ = channel.create_sendexpiredlock( sender_end_state=payer_channel.partner_state, locked_lock=lock, pseudo_random_generator=pseudo_random_generator, chain_id=payer_channel.chain_id, token_network_identifier=payer_channel.token_network_identifier, channel_identifier=payer_channel.identifier, recipient=payer_channel.our_state.address, ) assert send_lock_expired expired_message = message_from_sendevent(send_lock_expired, setup.channels.our_address(0)) expired_message.sign(setup.channels.partner_privatekeys[0]) balance_proof = balanceproof_from_envelope(expired_message) message_identifier = message_identifier_from_prng(pseudo_random_generator) expired_block_number = channel.get_sender_expiration_threshold(lock) mediator.state_transition( mediator_state=mediator_state, state_change=ReceiveLockExpired( balance_proof=balance_proof, secrethash=secrethash, message_identifier=message_identifier, ), channelidentifiers_to_channels=setup.channel_map, pseudo_random_generator=pseudo_random_generator, block_number=expired_block_number, ) assert secrethash in payer_channel.partner_state.secrethashes_to_onchain_unlockedlocks
def start(self): """ Start the node synchronously. Raises directly if anything went wrong on startup """ if not self.stop_event.ready(): raise RuntimeError(f'{self!r} already started') self.stop_event.clear() if self.database_dir is not None: self.db_lock.acquire(timeout=0) assert self.db_lock.is_locked # start the registration early to speed up the start if self.config['transport_type'] == 'udp': endpoint_registration_greenlet = gevent.spawn( self.discovery.register, self.address, self.config['transport']['udp']['external_ip'], self.config['transport']['udp']['external_port'], ) storage = sqlite.SQLiteStorage(self.database_path, serialize.JSONSerializer()) self.wal = wal.restore_to_state_change( transition_function=node.state_transition, storage=storage, state_change_identifier='latest', ) if self.wal.state_manager.current_state is None: log.debug( 'No recoverable state available, created inital state', node=pex(self.address), ) block_number = self.chain.block_number() state_change = ActionInitChain( random.Random(), block_number, self.chain.node_address, self.chain.network_id, ) self.wal.log_and_dispatch(state_change) payment_network = PaymentNetworkState( self.default_registry.address, [], # empty list of token network states as it's the node's startup ) state_change = ContractReceiveNewPaymentNetwork( constants.EMPTY_HASH, payment_network, ) self.handle_state_change(state_change) # On first run Raiden needs to fetch all events for the payment # network, to reconstruct all token network graphs and find opened # channels last_log_block_number = 0 else: # The `Block` state change is dispatched only after all the events # for that given block have been processed, filters can be safely # installed starting from this position without losing events. last_log_block_number = views.block_number( self.wal.state_manager.current_state) log.debug( 'Restored state from WAL', last_restored_block=last_log_block_number, node=pex(self.address), ) known_networks = views.get_payment_network_identifiers( views.state_from_raiden(self)) if known_networks and self.default_registry.address not in known_networks: configured_registry = pex(self.default_registry.address) known_registries = lpex(known_networks) raise RuntimeError( f'Token network address mismatch.\n' f'Raiden is configured to use the smart contract ' f'{configured_registry}, which conflicts with the current known ' f'smart contracts {known_registries}', ) # Clear ref cache & disable caching serialize.RaidenJSONDecoder.ref_cache.clear() serialize.RaidenJSONDecoder.cache_object_references = False # Restore the current snapshot group state_change_qty = self.wal.storage.count_state_changes() self.snapshot_group = state_change_qty // SNAPSHOT_STATE_CHANGES_COUNT # Install the filters using the correct from_block value, otherwise # blockchain logs can be lost. self.install_all_blockchain_filters( self.default_registry, self.default_secret_registry, last_log_block_number, ) # Complete the first_run of the alarm task and synchronize with the # blockchain since the last run. # # Notes about setup order: # - The filters must be polled after the node state has been primed, # otherwise the state changes won't have effect. # - The alarm must complete its first run before the transport is started, # to avoid rejecting messages for unknown channels. self.alarm.register_callback(self._callback_new_block) # alarm.first_run may process some new channel, which would start_health_check_for # a partner, that's why transport needs to be already started at this point self.transport.start(self) self.alarm.first_run() chain_state = views.state_from_raiden(self) # Dispatch pending transactions pending_transactions = views.get_pending_transactions(chain_state, ) log.debug( 'Processing pending transactions', num_pending_transactions=len(pending_transactions), node=pex(self.address), ) with self.dispatch_events_lock: for transaction in pending_transactions: try: self.raiden_event_handler.on_raiden_event( self, transaction) except RaidenRecoverableError as e: log.error(str(e)) except RaidenUnrecoverableError as e: if self.config['network_type'] == NetworkType.MAIN: if isinstance(e, InvalidDBData): raise log.error(str(e)) else: raise self.alarm.start() # after transport and alarm is started, send queued messages events_queues = views.get_all_messagequeues(chain_state) for queue_identifier, event_queue in events_queues.items(): self.start_health_check_for(queue_identifier.recipient) # repopulate identifier_to_results for pending transfers for event in event_queue: if type(event) == SendDirectTransfer: self.identifier_to_results[ event.payment_identifier] = AsyncResult() message = message_from_sendevent(event, self.address) self.sign(message) self.transport.send_async(queue_identifier, message) # exceptions on these subtasks should crash the app and bubble up self.alarm.link_exception(self.on_error) self.transport.link_exception(self.on_error) # Health check needs the transport layer self.start_neighbours_healthcheck() if self.config['transport_type'] == 'udp': endpoint_registration_greenlet.get( ) # re-raise if exception occurred super().start()