def maybe_add_tokennetwork(node_state, payment_network_identifier, token_network_state): token_network_identifier = token_network_state.address token_address = token_network_state.token_address payment_network_state, token_network_state_previous = get_networks( node_state, payment_network_identifier, token_address, ) if payment_network_state is None: payment_network_state = PaymentNetworkState( payment_network_identifier, [token_network_state], ) ids_to_payments = node_state.identifiers_to_paymentnetworks ids_to_payments[payment_network_identifier] = payment_network_state elif token_network_state_previous is None: ids_to_tokens = payment_network_state.tokenidentifiers_to_tokennetworks addrs_to_tokens = payment_network_state.tokenaddresses_to_tokennetworks ids_to_tokens[token_network_identifier] = token_network_state addrs_to_tokens[token_address] = token_network_state
def maybe_add_tokennetwork( chain_state: ChainState, payment_network_identifier: typing.PaymentNetworkID, token_network_state: TokenNetworkState, ): token_network_identifier = token_network_state.address token_address = token_network_state.token_address payment_network_state, token_network_state_previous = get_networks( chain_state, payment_network_identifier, token_address, ) if payment_network_state is None: payment_network_state = PaymentNetworkState( payment_network_identifier, [token_network_state], ) ids_to_payments = chain_state.identifiers_to_paymentnetworks ids_to_payments[payment_network_identifier] = payment_network_state if token_network_state_previous is None: ids_to_tokens = payment_network_state.tokenidentifiers_to_tokennetworks addresses_to_ids = payment_network_state.tokenaddresses_to_tokenidentifiers ids_to_tokens[token_network_identifier] = token_network_state addresses_to_ids[token_address] = token_network_identifier
def register_payment_network(self, registry_address, from_block=None): proxies = get_relevant_proxies( self.chain, self.address, registry_address, ) # Install the filters first to avoid missing changes, as a consequence # some events might be applied twice. self.blockchain_events.add_proxies_listeners(proxies, from_block) token_network_list = list() for manager in proxies.channel_managers: manager_address = manager.address netting_channel_proxies = proxies.channelmanager_nettingchannels[manager_address] network = get_token_network_state_from_proxies(self, manager, netting_channel_proxies) token_network_list.append(network) payment_network = PaymentNetworkState( registry_address, token_network_list, ) state_change = ContractReceiveNewPaymentNetwork(payment_network) self.handle_state_change(state_change)
def payment_network_state(chain_state, payment_network_id): payment_network = PaymentNetworkState( payment_network_id, [], ) chain_state.identifiers_to_paymentnetworks[payment_network_id] = payment_network return payment_network
def initialize(self, block_number, random, random_seed): self.random_seed = random_seed self.block_number = block_number self.random = random self.private_key, self.address = factories.make_privkey_address() self.chain_state = ChainState( self.random, self.block_number, self.address, factories.UNIT_CHAIN_ID, ) self.token_network_id = factories.make_address() self.token_id = factories.make_address() self.token_network_state = TokenNetworkState(self.token_network_id, self.token_id) self.payment_network_id = factories.make_payment_network_identifier() self.payment_network_state = PaymentNetworkState( self.payment_network_id, [self.token_network_state], ) self.chain_state.identifiers_to_paymentnetworks[ self.payment_network_id] = self.payment_network_state return self.new_channel_with_transaction()
def initialize(self, block_number, random, random_seed): self.random_seed = random_seed self.block_number = block_number self.block_hash = factories.make_block_hash() self.random = random self.private_key, self.address = factories.make_privkey_address() self.chain_state = ChainState( pseudo_random_generator=self.random, block_number=self.block_number, block_hash=self.block_hash, our_address=self.address, chain_id=factories.UNIT_CHAIN_ID, ) self.token_network_id = factories.UNIT_TOKEN_NETWORK_ADDRESS self.token_id = factories.UNIT_TOKEN_ADDRESS self.token_network_state = TokenNetworkState(self.token_network_id, self.token_id) self.payment_network_id = factories.make_payment_network_identifier() self.payment_network_state = PaymentNetworkState( self.payment_network_id, [self.token_network_state]) self.chain_state.identifiers_to_paymentnetworks[ self.payment_network_id] = self.payment_network_state self.chain_state.tokennetworkaddresses_to_paymentnetworkaddresses[ self.token_network_id] = self.payment_network_id channels = [ self.new_channel_with_transaction() for _ in range(self.initial_number_of_channels) ] return multiple(*channels)
def maybe_add_tokennetwork( chain_state: ChainState, payment_network_identifier: PaymentNetworkID, token_network_state: TokenNetworkState, ): token_network_identifier = token_network_state.address token_address = token_network_state.token_address payment_network_state, token_network_state_previous = get_networks( chain_state, payment_network_identifier, token_address, ) if payment_network_state is None: payment_network_state = PaymentNetworkState( payment_network_identifier, [token_network_state], ) ids_to_payments = chain_state.identifiers_to_paymentnetworks ids_to_payments[payment_network_identifier] = payment_network_state if token_network_state_previous is None: ids_to_tokens = payment_network_state.tokenidentifiers_to_tokennetworks addresses_to_ids = payment_network_state.tokenaddresses_to_tokenidentifiers ids_to_tokens[token_network_identifier] = token_network_state addresses_to_ids[token_address] = token_network_identifier mapping = chain_state.tokennetworkaddresses_to_paymentnetworkaddresses # FIXME: Remove cast once TokenNetworkAddress or TokenNetworkID are removed mapping[TokenNetworkAddress( token_network_identifier)] = payment_network_identifier
def initialize(self, block_number, random, random_seed): self.random_seed = random_seed self.block_number = block_number self.random = random self.private_key, self.address = factories.make_privkey_address() self.chain_state = ChainState( self.random, self.block_number, self.address, factories.UNIT_CHAIN_ID, ) self.token_network_id = factories.make_address() self.token_id = factories.make_address() self.token_network_state = TokenNetworkState(self.token_network_id, self.token_id) self.payment_network_id = factories.make_payment_network_identifier() self.payment_network_state = PaymentNetworkState( self.payment_network_id, [self.token_network_state], ) self.chain_state.identifiers_to_paymentnetworks[ self.payment_network_id] = self.payment_network_state self.channels = list() for partner_address in self.channels_with: channel = factories.make_channel( our_balance=1000, partner_balance=1000, token_network_identifier=self.token_network_id, our_address=self.address, partner_address=partner_address, ) channel_new_state_change = ContractReceiveChannelNew( factories.make_transaction_hash(), self.token_network_id, channel, self.block_number, ) node.state_transition(self.chain_state, channel_new_state_change) self.channels.append(channel)
def test_detect_balance_proof_change(): prng = random.Random() block_hash = factories.make_block_hash() old = ChainState( pseudo_random_generator=prng, block_number=1, block_hash=block_hash, our_address=2, chain_id=3, ) new = ChainState( pseudo_random_generator=prng, block_number=1, block_hash=block_hash, our_address=2, chain_id=3, ) def diff(): return list(detect_balance_proof_change(old, new)) assert len(diff()) == 0 payment_network = PaymentNetworkState(b'x', []) payment_network_copy = deepcopy(payment_network) new.identifiers_to_paymentnetworks['a'] = payment_network assert len(diff()) == 0 token_network = TokenNetworkState(b'a', b'a') token_network_copy = deepcopy(token_network) payment_network.tokenidentifiers_to_tokennetworks['a'] = token_network assert len(diff()) == 0 channel = NettingChannelState( canonical_identifier=factories.make_canonical_identifier(), token_address=b'a', payment_network_identifier=1, reveal_timeout=1, settle_timeout=2, mediation_fee=0, our_state=None, partner_state=None, open_transaction=TransactionExecutionStatus(result='success'), settle_transaction=None, update_transaction=None, close_transaction=None, ) channel_copy = deepcopy(channel) token_network.channelidentifiers_to_channels['a'] = channel our_state = NettingChannelEndState(address=b'b', balance=1) our_state_copy = deepcopy(our_state) partner_state = NettingChannelEndState(address=b'a', balance=0) partner_state_copy = deepcopy(partner_state) channel.our_state = our_state channel.partner_state = partner_state assert len(diff()) == 0 balance_proof = object() partner_state.balance_proof = balance_proof assert len(diff()) == 1 old.identifiers_to_paymentnetworks['a'] = payment_network_copy assert len(diff()) == 1 payment_network_copy.tokenidentifiers_to_tokennetworks[ 'a'] = token_network_copy assert len(diff()) == 1 token_network_copy.channelidentifiers_to_channels['a'] = channel_copy channel_copy.partner_state = partner_state_copy assert len(diff()) == 1 channel_copy.partner_state.balance_proof = balance_proof assert len(diff()) == 0 channel_copy.partner_state.balance_proof = object() assert len(diff()) == 1 assert diff() == [balance_proof] # check our_state BP changes channel_copy.partner_state.balance_proof = balance_proof assert len(diff()) == 0 channel.our_state.balance_proof = object() channel_copy.our_state = our_state_copy assert len(diff()) == 1 assert diff() == [channel.our_state.balance_proof] channel_copy.our_state.balance_proof = channel.our_state.balance_proof assert len(diff()) == 0
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()
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'], ) self.maybe_upgrade_db() storage = sqlite.SerializedSQLiteStorage( database_path=self.database_path, serializer=serialize.JSONSerializer(), ) storage.log_run() 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), ) # 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 = self.query_start_block state_change = ActionInitChain( random.Random(), last_log_block_number, self.chain.node_address, self.chain.network_id, ) self.handle_state_change(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, last_log_block_number, ) self.handle_state_change(state_change) 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}', ) # 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 reject messages for closed/settled channels. self.alarm.register_callback(self._callback_new_block) with self.dispatch_events_lock: self.alarm.first_run(last_log_block_number) chain_state = views.state_from_raiden(self) self._initialize_transactions_queues(chain_state) self._initialize_whitelists(chain_state) self._initialize_payment_statuses(chain_state) # send messages in queue before starting transport, # this is necessary to avoid a race where, if the transport is started # before the messages are queued, actions triggered by it can cause new # messages to be enqueued before these older ones self._initialize_messages_queues(chain_state) # The transport must not ever be started before the alarm task's # `first_run()` has been, because it's this method which synchronizes the # node with the blockchain, including the channel's state (if the channel # is closed on-chain new messages must be rejected, which will not be the # case if the node is not synchronized) self.transport.start( raiden_service=self, message_handler=self.message_handler, prev_auth_data=chain_state.last_transport_authdata, ) # First run has been called above! self.alarm.start() # 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(chain_state) if self.config['transport_type'] == 'udp': endpoint_registration_greenlet.get() # re-raise if exception occurred log.debug('Raiden Service started', node=pex(self.address)) super().start()
def start(self): """ Start the node. """ if self.stop_event and self.stop_event.is_set(): self.stop_event.clear() if self.database_dir is not None: self.db_lock.acquire(timeout=0) assert self.db_lock.is_locked # The database may be :memory: storage = sqlite.SQLiteStorage(self.database_path, serialize.PickleSerializer()) self.wal, unapplied_events = wal.restore_from_latest_snapshot( node.state_transition, storage, ) if self.wal.state_manager.current_state is None: block_number = self.chain.block_number() state_change = ActionInitChain( random.Random(), block_number, self.chain.network_id, ) self.wal.log_and_dispatch(state_change, block_number) payment_network = PaymentNetworkState( self.default_registry.address, [], # empty list of token network states as it's the node's startup ) state_change = ContractReceiveNewPaymentNetwork(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) # 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) self.alarm.first_run() self.alarm.start() queueids_to_queues = views.get_all_messagequeues( views.state_from_raiden(self)) self.transport.start(self, queueids_to_queues) # Health check needs the transport layer self.start_neighbours_healthcheck() for event in unapplied_events: on_raiden_event(self, event) self.start_event.set()
def start_async(self) -> RaidenGreenletEvent: """ Start the node asynchronously. """ self.start_event.clear() 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'], ) # The database may be :memory: storage = sqlite.SQLiteStorage(self.database_path, serialize.PickleSerializer()) self.wal = wal.restore_from_latest_snapshot( node.state_transition, storage, ) if self.wal.state_manager.current_state is None: log.debug('No recoverable state available, created inital state') 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, block_number) payment_network = PaymentNetworkState( self.default_registry.address, [], # empty list of token network states as it's the node's startup ) state_change = ContractReceiveNewPaymentNetwork( constants.NULL_ADDRESS, 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) # Restore the current snapshot group self.snapshot_group = last_log_block_number // SNAPSHOT_BLOCK_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) 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), ) with self.dispatch_events_lock: for transaction in pending_transactions: on_raiden_event(self, transaction) self.alarm.start() queueids_to_queues = views.get_all_messagequeues(chain_state) self.transport.start(self, queueids_to_queues) # Health check needs the transport layer self.start_neighbours_healthcheck() if self.config['transport_type'] == 'udp': def set_start_on_registration(_): self.start_event.set() endpoint_registration_greenlet.link_safe(set_start_on_registration) else: self.start_event.set() return self.start_event
def test_detect_balance_proof_change(): prng = random.Random() block_hash = factories.make_block_hash() old = ChainState( pseudo_random_generator=prng, block_number=1, block_hash=block_hash, our_address=2, chain_id=3, ) new = ChainState( pseudo_random_generator=prng, block_number=1, block_hash=block_hash, our_address=2, chain_id=3, ) def diff(): return list(detect_balance_proof_change(old, new)) assert len(diff()) == 0 payment_network = PaymentNetworkState(b'x', []) payment_network_copy = deepcopy(payment_network) new.identifiers_to_paymentnetworks['a'] = payment_network assert len(diff()) == 0 token_network = TokenNetworkState(b'a', b'a') token_network_copy = deepcopy(token_network) payment_network.tokenidentifiers_to_tokennetworks['a'] = token_network assert len(diff()) == 0 channel = NettingChannelState( 1, 0, b'a', 1, 1, 1, 2, None, None, TransactionExecutionStatus(result='success'), ) channel_copy = deepcopy(channel) token_network.channelidentifiers_to_channels['a'] = channel partner_state = NettingChannelEndState(b'a', 0) partner_state_copy = deepcopy(partner_state) channel.partner_state = partner_state assert len(diff()) == 0 balance_proof = object() partner_state.balance_proof = balance_proof assert len(diff()) == 1 old.identifiers_to_paymentnetworks['a'] = payment_network_copy assert len(diff()) == 1 payment_network_copy.tokenidentifiers_to_tokennetworks[ 'a'] = token_network_copy assert len(diff()) == 1 token_network_copy.channelidentifiers_to_channels['a'] = channel_copy channel_copy.partner_state = partner_state_copy assert len(diff()) == 1 channel_copy.partner_state.balance_proof = balance_proof assert len(diff()) == 0 channel_copy.partner_state.balance_proof = object() assert len(diff()) == 1 assert diff() == [balance_proof]
def start(self): """ Start the node synchronously. Raises directly if anything went wrong on startup """ assert self.stop_event.ready(), f"Node already started. node:{self!r}" self.stop_event.clear() self.greenlets = list() self.ready_to_process_events = False # set to False because of restarts if self.database_dir is not None: self.db_lock.acquire(timeout=0) assert self.db_lock.is_locked, f"Database not locked. node:{self!r}" # 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"], ) self.maybe_upgrade_db() storage = sqlite.SerializedSQLiteStorage( database_path=self.database_path, serializer=serialize.JSONSerializer()) storage.update_version() storage.log_run() 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, creating inital state.", node=pex(self.address)) # 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 = self.query_start_block last_log_block_hash = self.chain.client.blockhash_from_blocknumber( last_log_block_number) state_change = ActionInitChain( pseudo_random_generator=random.Random(), block_number=last_log_block_number, block_hash=last_log_block_hash, our_address=self.chain.node_address, chain_id=self.chain.network_id, ) self.handle_and_track_state_change(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( transaction_hash=constants.EMPTY_HASH, payment_network=payment_network, block_number=last_log_block_number, block_hash=last_log_block_hash, ) self.handle_and_track_state_change(state_change) 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}") # 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 latest confirmed 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 reject messages for closed/settled channels. self.alarm.register_callback(self._callback_new_block) self.alarm.first_run(last_log_block_number) chain_state = views.state_from_raiden(self) self._initialize_payment_statuses(chain_state) self._initialize_transactions_queues(chain_state) self._initialize_messages_queues(chain_state) self._initialize_whitelists(chain_state) self._initialize_monitoring_services_queue(chain_state) self._initialize_ready_to_processed_events() if self.config["transport_type"] == "udp": endpoint_registration_greenlet.get( ) # re-raise if exception occurred # Start the side-effects: # - React to blockchain events # - React to incoming messages # - Send pending transactions # - Send pending message self.alarm.link_exception(self.on_error) self.transport.link_exception(self.on_error) self._start_transport(chain_state) self._start_alarm_task() log.debug("Raiden Service started", node=pex(self.address)) super().start()