def test_no_valid_routes(): from_route, from_transfer = make_from( amount=factories.UNIT_TRANSFER_AMOUNT, target=factories.HOP2, from_expiration=factories.HOP1_TIMEOUT, ) routes = [ factories.make_route(factories.HOP2, available_balance=factories.UNIT_TRANSFER_AMOUNT - 1), factories.make_route(factories.HOP3, available_balance=1), ] init_state_change = make_init_statechange( from_transfer, from_route, routes, ) mediator_state_machine = StateManager( mediator.state_transition, None, ) assert mediator_state_machine.current_state is None events = mediator_state_machine.dispatch( init_state_change, ) assert mediator_state_machine.current_state is None assert len(events) == 1 assert isinstance(events[0], SendRefundTransfer)
def test_no_valid_routes(): from_route, from_transfer = factories.make_from( amount=factories.UNIT_TRANSFER_AMOUNT, target=factories.HOP2, from_expiration=factories.HOP1_TIMEOUT, ) routes = [ factories.make_route(factories.HOP2, available_balance=factories.UNIT_TRANSFER_AMOUNT - 1), factories.make_route(factories.HOP3, available_balance=1), ] init_state_change = make_init_statechange( from_transfer, from_route, routes, ) mediator_state_machine = StateManager( mediator.state_transition, None, ) assert mediator_state_machine.current_state is None events = mediator_state_machine.dispatch( init_state_change, ) assert mediator_state_machine.current_state is None assert len(events) == 1 assert isinstance(events[0], SendRefundTransfer)
def test_cancel_transfer(): identifier = 1 amount = factories.UNIT_TRANSFER_AMOUNT block_number = 1 mediator_address = factories.HOP1 target_address = factories.HOP2 our_address = factories.ADDR routes = [ factories.make_route(mediator_address, available_balance=amount), ] current_state = make_initiator_state( routes, target_address, block_number=block_number, our_address=our_address, secret_generator=SequenceGenerator(), identifier=identifier, ) state_change = ActionCancelTransfer(identifier=identifier) initiator_state_machine = StateManager( initiator.state_transition, current_state, ) assert initiator_state_machine.current_state is not None events = initiator_state_machine.dispatch(state_change) assert len(events) == 1 assert isinstance(events[0], EventTransferSentFailed) assert initiator_state_machine.current_state is None
def test_state_wait_secretrequest_valid(): identifier = 1 amount = factories.UNIT_TRANSFER_AMOUNT block_number = 1 mediator_address = factories.HOP1 target_address = factories.HOP2 our_address = factories.ADDR routes = [factories.make_route(mediator_address, available_balance=amount)] current_state = make_initiator_state( routes, target_address, block_number=block_number, our_address=our_address, secret_generator=SequenceGenerator(), identifier=identifier, ) hashlock = current_state.transfer.hashlock state_change = ReceiveSecretRequest( identifier=identifier, amount=amount, hashlock=hashlock, sender=target_address, ) initiator_state_machine = StateManager( initiator.state_transition, current_state, ) events = initiator_state_machine.dispatch(state_change) assert all(isinstance(event, SendRevealSecret) for event in events) assert len(events) == 1
def test_init_without_routes(): amount = factories.UNIT_TRANSFER_AMOUNT block_number = 1 our_address, target_address = factories.HOP1, factories.HOP3 routes = [] transfer = factories.make_transfer( amount, initiator=our_address, target=target_address, secret=None, hashlock=None, expiration=None, ) init_state_change = ActionInitInitiator( our_address, transfer, RoutesState(routes), SequenceGenerator(), block_number, ) initiator_state_machine = StateManager( initiator.state_transition, None, ) assert initiator_state_machine.current_state is None events = initiator_state_machine.dispatch(init_state_change, ) assert len(events) == 1 assert any(isinstance(e, EventTransferSentFailed) for e in events) assert initiator_state_machine.current_state is None
def test_cancel_transfer(): identifier = 1 amount = factories.UNIT_TRANSFER_AMOUNT block_number = 1 mediator_address = factories.HOP1 target_address = factories.HOP2 our_address = factories.ADDR routes = [ factories.make_route(mediator_address, available_balance=amount), ] current_state = make_initiator_state( routes, target_address, block_number=block_number, our_address=our_address, secret_generator=SequenceGenerator(), identifier=identifier, ) state_change = ActionCancelTransfer( identifier=identifier ) initiator_state_machine = StateManager( initiator.state_transition, current_state, ) assert initiator_state_machine.current_state is not None events = initiator_state_machine.dispatch(state_change) assert len(events) == 1 assert isinstance(events[0], EventTransferSentFailed) assert initiator_state_machine.current_state is None
def restore_from_latest_snapshot(transition_function, storage): snapshot = storage.get_latest_state_snapshot() if snapshot: log.debug('Restoring from snapshot') last_applied_state_change_id, state = snapshot unapplied_state_changes = storage.get_statechanges_by_identifier( from_identifier=last_applied_state_change_id, to_identifier='latest', ) else: log.debug('No snapshot found, replaying all state changes') state = None unapplied_state_changes = storage.get_statechanges_by_identifier( from_identifier=0, to_identifier='latest', ) state_manager = StateManager(transition_function, state) wal = WriteAheadLog(state_manager, storage) log.debug('Replaying state changes', num_state_changes=len(unapplied_state_changes)) for state_change in unapplied_state_changes: state_manager.dispatch(state_change) return wal
def test_state_wait_unlock_valid(): identifier = 1 amount = factories.UNIT_TRANSFER_AMOUNT block_number = 1 mediator_address = factories.HOP1 target_address = factories.HOP2 our_address = factories.ADDR secret_generator = SequenceGenerator() token = factories.UNIT_TOKEN_ADDRESS routes = [factories.make_route(mediator_address, available_balance=amount)] current_state = make_initiator_state( routes, target_address, block_number=block_number, our_address=our_address, secret_generator=secret_generator, identifier=identifier, token=token, ) secret = secret_generator.secrets[0] assert secret is not None # setup the state for the wait unlock current_state.revealsecret = SendRevealSecret( identifier, secret, token, target_address, our_address, ) initiator_state_machine = StateManager( initiator.state_transition, current_state, ) state_change = ReceiveSecretReveal( secret=secret, sender=mediator_address, ) events = initiator_state_machine.dispatch(state_change) assert len(events) == 3 assert any(isinstance(e, SendBalanceProof) for e in events) assert any(isinstance(e, EventTransferSentSuccess) for e in events) assert any(isinstance(e, EventUnlockSuccess) for e in events) balance_proof = next(e for e in events if isinstance(e, SendBalanceProof)) complete = next(e for e in events if isinstance(e, EventTransferSentSuccess)) assert balance_proof.receiver == mediator_address assert complete.identifier == identifier assert initiator_state_machine.current_state is None, 'state must be cleaned'
def test_refund_transfer_next_route(): identifier = 1 amount = factories.UNIT_TRANSFER_AMOUNT block_number = 1 mediator_address = factories.HOP1 target_address = factories.HOP2 our_address = factories.ADDR routes = [ factories.make_route(mediator_address, available_balance=amount), factories.make_route(factories.HOP2, available_balance=amount), ] current_state = make_initiator_state( routes, target_address, block_number=block_number, our_address=our_address, secret_generator=SequenceGenerator(), identifier=identifier, ) transfer = factories.make_transfer( amount, our_address, target_address, block_number + factories.UNIT_SETTLE_TIMEOUT, ) state_change = ReceiveTransferRefund( sender=mediator_address, transfer=transfer, ) prior_state = deepcopy(current_state) initiator_state_machine = StateManager( initiator.state_transition, current_state, ) assert initiator_state_machine.current_state is not None events = initiator_state_machine.dispatch(state_change) assert len(events) == 1 assert any( isinstance(e, SendMediatedTransfer) for e in events ), 'No mediated transfer event emitted, should have tried a new route' assert initiator_state_machine.current_state is not None assert initiator_state_machine.current_state.routes.canceled_routes[ 0] == prior_state.route
def test_init_mediator(): from_route, from_transfer = factories.make_from( amount=factories.UNIT_TRANSFER_AMOUNT, target=factories.HOP2, from_expiration=factories.HOP1_TIMEOUT, ) routes = [ factories.make_route(factories.HOP2, available_balance=factories.UNIT_TRANSFER_AMOUNT), ] init_state_change = make_init_statechange( from_transfer, from_route, routes, ) mediator_state_machine = StateManager( mediator.state_transition, None, ) assert mediator_state_machine.current_state is None events = mediator_state_machine.dispatch(init_state_change, ) mediator_state = mediator_state_machine.current_state assert isinstance(mediator_state, MediatorState) assert mediator_state.our_address == factories.ADDR assert mediator_state.block_number == init_state_change.block_number assert mediator_state.transfers_pair[0].payer_transfer == from_transfer assert mediator_state.transfers_pair[0].payer_route == from_route assert len( events ), 'we have a valid route, the mediated transfer event must be emited' mediated_transfers = [ e for e in events if isinstance(e, SendMediatedTransfer) ] assert len(mediated_transfers ) == 1, 'mediated_transfer should /not/ split the transfer' mediated_transfer = mediated_transfers[0] assert mediated_transfer.token == from_transfer.token, 'transfer token address mismatch' assert mediated_transfer.amount == from_transfer.amount, 'transfer amount mismatch' assert mediated_transfer.expiration < from_transfer.expiration, 'transfer expiration mismatch' assert mediated_transfer.hashlock == from_transfer.hashlock, 'wrong hashlock'
def test_refund_transfer_next_route(): identifier = 1 amount = factories.UNIT_TRANSFER_AMOUNT block_number = 1 mediator_address = factories.HOP1 target_address = factories.HOP2 our_address = factories.ADDR routes = [ factories.make_route(mediator_address, available_balance=amount), factories.make_route(factories.HOP2, available_balance=amount), ] current_state = make_initiator_state( routes, target_address, block_number=block_number, our_address=our_address, secret_generator=SequenceGenerator(), identifier=identifier, ) transfer = factories.make_transfer( amount, our_address, target_address, block_number + factories.UNIT_SETTLE_TIMEOUT, ) state_change = ReceiveTransferRefund( sender=mediator_address, transfer=transfer, ) prior_state = deepcopy(current_state) initiator_state_machine = StateManager( initiator.state_transition, current_state, ) assert initiator_state_machine.current_state is not None events = initiator_state_machine.dispatch(state_change) assert len(events) == 1 assert any( isinstance(e, SendMediatedTransfer) for e in events ), 'No mediated transfer event emitted, should have tried a new route' assert initiator_state_machine.current_state is not None assert initiator_state_machine.current_state.routes.canceled_routes[0] == prior_state.route
def test_init_mediator(): from_route, from_transfer = factories.make_from( amount=factories.UNIT_TRANSFER_AMOUNT, target=factories.HOP2, from_expiration=factories.HOP1_TIMEOUT, ) routes = [ factories.make_route(factories.HOP2, available_balance=factories.UNIT_TRANSFER_AMOUNT), ] init_state_change = make_init_statechange( from_transfer, from_route, routes, ) mediator_state_machine = StateManager( mediator.state_transition, None, ) assert mediator_state_machine.current_state is None events = mediator_state_machine.dispatch( init_state_change, ) mediator_state = mediator_state_machine.current_state assert isinstance(mediator_state, MediatorState) assert mediator_state.our_address == factories.ADDR assert mediator_state.block_number == init_state_change.block_number assert mediator_state.transfers_pair[0].payer_transfer == from_transfer assert mediator_state.transfers_pair[0].payer_route == from_route assert len(events), 'we have a valid route, the mediated transfer event must be emited' mediated_transfers = [ e for e in events if isinstance(e, SendMediatedTransfer) ] assert len(mediated_transfers) == 1, 'mediated_transfer should /not/ split the transfer' mediated_transfer = mediated_transfers[0] assert mediated_transfer.token == from_transfer.token, 'transfer token address mismatch' assert mediated_transfer.amount == from_transfer.amount, 'transfer amount mismatch' assert mediated_transfer.expiration < from_transfer.expiration, 'transfer expiration mismatch' assert mediated_transfer.hashlock == from_transfer.hashlock, 'wrong hashlock'
def new_wal(state_transition: Callable, state: State = None) -> WriteAheadLog: serializer = JSONSerializer() state_manager = StateManager(state_transition, state) storage = SerializedSQLiteStorage(":memory:", serializer) wal = WriteAheadLog(state_manager, storage) return wal
def restore_to_state_change(transition_function, storage, state_change_identifier): snapshot = storage.get_snapshot_closest_to_state_change( state_change_identifier) from_state_change_id = 0 chain_state = None if snapshot: log.debug('Restoring from snapshot') from_state_change_id, chain_state = snapshot else: log.debug('No snapshot found, replaying all state changes') unapplied_state_changes = storage.get_statechanges_by_identifier( from_identifier=from_state_change_id, to_identifier=state_change_identifier, ) state_manager = StateManager(transition_function, chain_state) wal = WriteAheadLog(state_manager, storage) log.debug('Replaying state changes', num_state_changes=len(unapplied_state_changes)) for state_change in unapplied_state_changes: wal.state_manager.dispatch(state_change) return wal
def __init__(self, message_handler=None, state_transition=None, private_key=None): if private_key is None: self.private_key, self.address = factories.make_privkey_address() else: self.private_key = private_key self.address = privatekey_to_address(private_key) self.chain = MockChain(network_id=17, node_address=self.address) self.signer = LocalSigner(self.private_key) self.message_handler = message_handler self.user_deposit = Mock() if state_transition is None: state_transition = node.state_transition serializer = JSONSerializer state_manager = StateManager(state_transition, None) storage = SerializedSQLiteStorage(":memory:", serializer) self.wal = WriteAheadLog(state_manager, storage) state_change = ActionInitChain( pseudo_random_generator=random.Random(), block_number=0, block_hash=factories.make_block_hash(), our_address=self.chain.node_address, chain_id=self.chain.network_id, ) self.wal.log_and_dispatch(state_change)
def replay_wal(storage, token_network_identifier, partner_address): all_state_changes = storage.get_statechanges_by_identifier( from_identifier=0, to_identifier='latest', ) state_manager = StateManager(state_transition=node.state_transition, current_state=None) wal = WriteAheadLog(state_manager, storage) for _, state_change in enumerate(all_state_changes): events = wal.state_manager.dispatch(state_change) chain_state = wal.state_manager.current_state channel_state = views.get_channelstate_by_token_network_and_partner( chain_state, to_canonical_address(token_network_identifier), to_canonical_address(partner_address), ) if not channel_state: continue ### # Customize this to filter things further somewhere around here. # An example would be to add `import pdb; pdb.set_trace()` # and inspect the state. ### print_state_change(state_change) print_events(events)
def restore_to_state_change(transition_function: Callable, storage: SerializedSQLiteStorage, state_change_identifier: int) -> "WriteAheadLog": msg = "state change identifier 'latest' or an integer greater than zero" assert state_change_identifier == "latest" or state_change_identifier > 0, msg from_state_change_id, chain_state = storage.get_snapshot_closest_to_state_change( state_change_identifier=state_change_identifier) if chain_state is not None: log.debug( "Restoring from snapshot", from_state_change_id=from_state_change_id, to_state_change_id=state_change_identifier, ) else: log.debug( "No snapshot found, replaying all state changes", to_state_change_id=state_change_identifier, ) unapplied_state_changes = storage.get_statechanges_by_identifier( from_identifier=from_state_change_id, to_identifier=state_change_identifier) state_manager = StateManager(transition_function, chain_state) wal = WriteAheadLog(state_manager, storage) log.debug("Replaying state changes", num_state_changes=len(unapplied_state_changes)) for state_change in unapplied_state_changes: wal.state_manager.dispatch(state_change, storage) return wal
def test_state_wait_unlock_invalid(): identifier = identifier = 1 amount = factories.UNIT_TRANSFER_AMOUNT block_number = 1 mediator_address = factories.HOP1 target_address = factories.HOP2 our_address = factories.ADDR secret_generator = SequenceGenerator() token = factories.UNIT_TOKEN_ADDRESS routes = [factories.make_route(mediator_address, available_balance=amount)] current_state = make_initiator_state( routes, target_address, block_number=block_number, our_address=our_address, secret_generator=secret_generator, token=token, ) secret = secret_generator.secrets[0] assert secret is not None current_state.revealsecret = SendRevealSecret( identifier, secret, token, target_address, our_address, ) before_state = deepcopy(current_state) initiator_state_machine = StateManager( initiator.state_transition, current_state, ) state_change = ReceiveSecretReveal( secret=secret, sender=factories.ADDR, ) events = initiator_state_machine.dispatch(state_change) assert len(events) == 0 assert initiator_state_machine.current_state.revealsecret is not None assert_state_equal(initiator_state_machine.current_state, current_state) assert_state_equal(current_state, before_state)
def new_wal(): state = None serializer = JSONSerializer state_manager = StateManager(state_transition_noop, state) storage = SQLiteStorage(':memory:', serializer) wal = WriteAheadLog(state_manager, storage) return wal
def test_state_wait_unlock_valid(): identifier = identifier = 1 amount = factories.UNIT_TRANSFER_AMOUNT block_number = 1 mediator_address = factories.HOP1 target_address = factories.HOP2 our_address = factories.ADDR secret_generator = SequenceGenerator() routes = [factories.make_route(mediator_address, available_balance=amount)] current_state = make_initiator_state( routes, target_address, block_number=block_number, our_address=our_address, secret_generator=secret_generator, ) secret = secret_generator.secrets[0] assert secret is not None # setup the state for the wait unlock current_state.revealsecret = SendRevealSecret( identifier, secret, target_address, our_address, ) initiator_state_machine = StateManager( initiator.state_transition, current_state, ) state_change = ReceiveSecretReveal( identifier=identifier, secret=secret, target=our_address, sender=mediator_address, ) events = initiator_state_machine.dispatch(state_change) assert len(events) == 1 assert isinstance(events[0], SendRevealSecret) assert events[0].target == mediator_address assert initiator_state_machine.current_state is None, 'state must be cleaned'
def test_wal(): state = None serializer = PickleSerializer state_manager = StateManager(state_transition_noop, state) ###storage = SQLiteStorage('/home/wk/work/Raiden/test.txt', serializer) storage = SQLiteStorage('/Users/vincent/Downloads/test.txt', serializer) wal = WriteAheadLog(state_manager, storage) return wal
def test_refund_transfer_invalid_sender(): identifier = 1 amount = factories.UNIT_TRANSFER_AMOUNT block_number = 1 mediator_address = factories.HOP1 target_address = factories.HOP2 our_address = factories.ADDR routes = [ factories.make_route(mediator_address, available_balance=amount), ] current_state = make_initiator_state( routes, target_address, block_number=block_number, our_address=our_address, secret_generator=SequenceGenerator(), identifier=identifier, ) transfer = factories.make_transfer( amount, our_address, target_address, block_number + factories.UNIT_SETTLE_TIMEOUT, ) state_change = ReceiveTransferRefund( sender=our_address, transfer=transfer, ) prior_state = deepcopy(current_state) initiator_state_machine = StateManager( initiator.state_transition, current_state, ) assert initiator_state_machine.current_state is not None events = initiator_state_machine.dispatch(state_change) assert len(events) == 0 assert initiator_state_machine.current_state is not None assert_state_equal(initiator_state_machine.current_state, prior_state)
def __init__(self, transition_function, storage): # TODO: # - reapply missing state changes # - clear existing events for the unapplied state changes snapshot = storage.get_state_snapshot() state_manager = StateManager(transition_function, snapshot) self.state_manager = state_manager self.state_change_id = None self.storage = storage
def mediate_mediated_transfer(self, message): # pylint: disable=too-many-locals identifier = message.identifier amount = message.lock.amount target = message.target token = message.token graph = self.channelgraphs[token] routes = graph.get_best_routes( self.address, target, amount, lock_timeout=None, ) available_routes = [ route for route in map(route_to_routestate, routes) if route.state == CHANNEL_STATE_OPENED ] from_channel = graph.partneraddress_channel[message.sender] from_route = channel_to_routestate(from_channel, message.sender) our_address = self.address from_transfer = lockedtransfer_from_message(message) route_state = RoutesState(available_routes) block_number = self.get_block_number() init_mediator = ActionInitMediator( our_address, from_transfer, route_state, from_route, block_number, ) state_manager = StateManager(mediator.state_transition, None) all_events = state_manager.dispatch(init_mediator) for event in all_events: self.state_machine_event_handler.on_event(event) self.identifier_statemanager[identifier].append(state_manager)
def restore_from_latest_snapshot(transition_function, storage): events = list() snapshot = storage.get_state_snapshot() if snapshot: last_applied_state_change_id, state = snapshot unapplied_state_changes = storage.get_statechanges_by_identifier( from_identifier=last_applied_state_change_id, to_identifier='latest', ) else: state = None unapplied_state_changes = list() state_manager = StateManager(transition_function, state) wal = WriteAheadLog(state_manager, storage) for state_change in unapplied_state_changes: events.extend(state_manager.dispatch(state_change)) return wal, events
def restore_to_state_change( transition_function: Callable, storage: SerializedSQLiteStorage, state_change_identifier: StateChangeID, node_address: Address, ) -> Tuple[int, int, "WriteAheadLog"]: chain_state: Optional[State] from_identifier: StateChangeID snapshot = storage.get_snapshot_before_state_change( state_change_identifier=state_change_identifier) if snapshot is not None: log.debug( "Restoring from snapshot", from_state_change_id=snapshot.state_change_identifier, to_state_change_id=state_change_identifier, node=to_checksum_address(node_address), ) from_identifier = snapshot.state_change_identifier chain_state = snapshot.data state_change_qty = snapshot.state_change_qty else: log.debug( "No snapshot found, replaying all state changes", to_state_change_id=state_change_identifier, node=to_checksum_address(node_address), ) from_identifier = LOW_STATECHANGE_ULID chain_state = None state_change_qty = 0 state_manager = StateManager(transition_function, chain_state) wal = WriteAheadLog(state_manager, storage) unapplied_state_changes = storage.get_statechanges_by_range( Range(from_identifier, state_change_identifier)) if unapplied_state_changes: log.debug( "Replaying state changes", replayed_state_changes=[ redact_secret(DictSerializer.serialize(state_change)) for state_change in unapplied_state_changes ], node=to_checksum_address(node_address), ) for state_change in unapplied_state_changes: wal.state_manager.dispatch(state_change) return state_change_qty, len(unapplied_state_changes), wal
def test_init_without_routes(): amount = factories.UNIT_TRANSFER_AMOUNT block_number = 1 our_address, target_address = factories.HOP1, factories.HOP3 routes = [] transfer = factories.make_transfer( amount, initiator=our_address, target=target_address, secret=None, hashlock=None, expiration=None, ) init_state_change = ActionInitInitiator( our_address, transfer, RoutesState(routes), SequenceGenerator(), block_number, ) initiator_state_machine = StateManager( initiator.state_transition, None, ) assert initiator_state_machine.current_state is None events = initiator_state_machine.dispatch( init_state_change, ) assert len(events) == 1 assert any(isinstance(e, EventTransferSentFailed) for e in events) assert initiator_state_machine.current_state is None
def target_mediated_transfer(self, message): graph = self.channelgraphs[message.token] from_channel = graph.partneraddress_channel[message.sender] from_route = channel_to_routestate(from_channel, message.sender) from_transfer = lockedtransfer_from_message(message) our_address = self.address block_number = self.get_block_number() init_target = ActionInitTarget( our_address, from_route, from_transfer, block_number, ) state_manager = StateManager(target_task.state_transition, None) all_events = state_manager.dispatch(init_target) for event in all_events: self.state_machine_event_handler.on_event(event) identifier = message.identifier self.identifier_statemanager[identifier].append(state_manager)
def __init__(self, message_handler=None, state_transition=None, private_key=None): if private_key is None: self.privkey, self.address = factories.make_privkey_address() else: self.privkey = private_key self.address = privatekey_to_address(private_key) self.rpc_client = MockJSONRPCClient(self.address) self.proxy_manager = MockProxyManager(node_address=self.address) self.signer = LocalSigner(self.privkey) self.message_handler = message_handler self.routing_mode = RoutingMode.PRIVATE self.config = RaidenConfig(chain_id=self.rpc_client.chain_id, environment_type=Environment.DEVELOPMENT) self.default_user_deposit = Mock() self.default_registry = Mock() self.default_registry.address = factories.make_address() self.default_one_to_n_address = factories.make_address() self.default_msc_address = factories.make_address() self.targets_to_identifiers_to_statuses: Dict[Address, dict] = defaultdict(dict) self.route_to_feedback_token: dict = {} if state_transition is None: state_transition = node.state_transition serializer = JSONSerializer() state_manager = StateManager(state_transition, None) storage = SerializedSQLiteStorage(":memory:", serializer) self.wal = WriteAheadLog(state_manager, storage) state_change = ActionInitChain( pseudo_random_generator=random.Random(), block_number=BlockNumber(0), block_hash=factories.make_block_hash(), our_address=self.rpc_client.address, chain_id=self.rpc_client.chain_id, ) with self.wal.process_state_change_atomically() as dispatcher: dispatcher.dispatch(state_change) self.transport = Mock()
def replay_wal( storage: SerializedSQLiteStorage, token_network_address: TokenNetworkAddress, partner_address: Address, translator: Optional[Translator] = None, ) -> None: all_state_changes = storage.get_statechanges_by_range( RANGE_ALL_STATE_CHANGES) state_manager = StateManager(state_transition=node.state_transition, current_state=None) wal = WriteAheadLog(state_manager, storage) for _, state_change in enumerate(all_state_changes): # Dispatching the state changes one-by-one to easy debugging _, events = wal.state_manager.dispatch([state_change]) chain_state = wal.state_manager.current_state msg = "Chain state must never be cleared up." assert chain_state, msg channel_state = views.get_channelstate_by_token_network_and_partner( chain_state, to_canonical_address(token_network_address), to_canonical_address(partner_address), ) if channel_state is None: continue ### # Customize this to filter things further somewhere around here. # An example would be to add `breakpoint()` # and inspect the state. ### print_state_change(state_change, translator=translator) print_events(chain.from_iterable(events), translator=translator) # Enable to print color coded presence state of channel partners # print_presence_view(chain_state, translator) # Enable to print balances & balance sum with all channel partners # print_node_balances(chain_state, token_network_address, translator) print_nl()
def __init__(self, message_handler=None, state_transition=None, private_key=None, config=None): if private_key is None: self.privkey, self.address = factories.make_privkey_address() else: self.privkey = private_key self.address = privatekey_to_address(private_key) self.rpc_client = MockJSONRPCClient(self.address) self.proxy_manager = MockProxyManager(node_address=self.address) self.signer = LocalSigner(self.privkey) self.message_handler = message_handler self.routing_mode = RoutingMode.PRIVATE self.config = config self.user_deposit = Mock() self.default_registry = Mock() self.default_registry.address = factories.make_address() self.default_one_to_n_address = factories.make_address() self.default_msc_address = factories.make_address() self.targets_to_identifiers_to_statuses = defaultdict(dict) self.route_to_feedback_token = {} if state_transition is None: state_transition = node.state_transition serializer = JSONSerializer state_manager = StateManager(state_transition, None) storage = SerializedSQLiteStorage(":memory:", serializer) self.wal = WriteAheadLog(state_manager, storage) state_change = ActionInitChain( pseudo_random_generator=random.Random(), block_number=0, block_hash=factories.make_block_hash(), our_address=self.rpc_client.address, chain_id=self.rpc_client.chain_id, ) self.wal.log_and_dispatch([state_change])
def mediate_mediated_transfer(self, message): # pylint: disable=too-many-locals identifier = message.identifier amount = message.lock.amount target = message.target token = message.token graph = self.token_to_channelgraph[token] available_routes = get_best_routes( graph, self.protocol.nodeaddresses_networkstatuses, self.address, target, amount, message.sender, ) from_channel = graph.partneraddress_to_channel[message.sender] from_route = channel_to_routestate(from_channel, message.sender) our_address = self.address from_transfer = lockedtransfer_from_message(message) route_state = RoutesState(available_routes) block_number = self.get_block_number() init_mediator = ActionInitMediator( our_address, from_transfer, route_state, from_route, block_number, ) state_manager = StateManager(mediator.state_transition, None) self.state_machine_event_handler.log_and_dispatch( state_manager, init_mediator) self.identifier_to_statemanagers[identifier].append(state_manager)
def __init__(self, message_handler=None, state_transition=None): self.chain = MockChain() self.private_key, self.address = factories.make_privatekey_address() self.chain.node_address = self.address self.message_handler = message_handler if state_transition is None: state_transition = node.state_transition serializer = JSONSerializer state_manager = StateManager(state_transition, None) storage = SQLiteStorage(':memory:', serializer) self.wal = WriteAheadLog(state_manager, storage) state_change = ActionInitChain( random.Random(), 0, self.chain.node_address, self.chain.network_id, ) self.wal.log_and_dispatch(state_change)
def start_mediated_transfer(self, token_address, amount, identifier, target): # pylint: disable=too-many-locals async_result = AsyncResult() graph = self.token_to_channelgraph[token_address] available_routes = get_best_routes( graph, self.protocol.nodeaddresses_networkstatuses, self.address, target, amount, None, ) if not available_routes: async_result.set(False) return async_result self.protocol.start_health_check(target) if identifier is None: identifier = create_default_identifier() route_state = RoutesState(available_routes) our_address = self.address block_number = self.get_block_number() transfer_state = LockedTransferState( identifier=identifier, amount=amount, token=token_address, initiator=self.address, target=target, expiration=None, hashlock=None, secret=None, ) # Issue #489 # # Raiden may fail after a state change using the random generator is # handled but right before the snapshot is taken. If that happens on # the next initialization when raiden is recovering and applying the # pending state changes a new secret will be generated and the # resulting events won't match, this breaks the architecture model, # since it's assumed the re-execution of a state change will always # produce the same events. # # TODO: Removed the secret generator from the InitiatorState and add # the secret into all state changes that require one, this way the # secret will be serialized with the state change and the recovery will # use the same /random/ secret. random_generator = RandomSecretGenerator() init_initiator = ActionInitInitiator( our_address=our_address, transfer=transfer_state, routes=route_state, random_generator=random_generator, block_number=block_number, ) state_manager = StateManager(initiator.state_transition, None) self.state_machine_event_handler.log_and_dispatch( state_manager, init_initiator) # TODO: implement the network timeout raiden.config['msg_timeout'] and # cancel the current transfer if it hapens (issue #374) self.identifier_to_statemanagers[identifier].append(state_manager) self.identifier_to_results[identifier].append(async_result) return async_result
def test_init_with_usable_routes(): amount = factories.UNIT_TRANSFER_AMOUNT block_number = 1 mediator_address = factories.HOP1 target_address = factories.HOP2 our_address = factories.ADDR secret_generator = SequenceGenerator() routes = [factories.make_route(mediator_address, available_balance=amount)] init_state_change = make_init_statechange( routes, target_address, block_number=block_number, our_address=our_address, secret_generator=secret_generator, ) expiration = block_number + factories.HOP1_TIMEOUT initiator_state_machine = StateManager( initiator.state_transition, None, ) assert initiator_state_machine.current_state is None events = initiator_state_machine.dispatch( init_state_change, ) initiator_state = initiator_state_machine.current_state assert isinstance(initiator_state, InitiatorState) assert initiator_state.our_address == our_address transfer = initiator_state.transfer assert isinstance(transfer, LockedTransferState) assert transfer.amount == amount assert transfer.target == target_address assert transfer.secret == secret_generator.secrets[0] assert transfer.hashlock == sha3(transfer.secret) assert len(events), 'we have a valid route, the mediated transfer event must be emited' mediated_transfers = [ e for e in events if isinstance(e, SendMediatedTransfer) ] assert len(mediated_transfers) == 1, 'mediated_transfer should /not/ split the transfer' mediated_transfer = mediated_transfers[0] assert mediated_transfer.token == factories.UNIT_TOKEN_ADDRESS assert mediated_transfer.amount == amount, 'transfer amount mismatch' assert mediated_transfer.expiration == expiration, 'transfer expiration mismatch' secret_hash = sha3(secret_generator.secrets[0]) assert mediated_transfer.hashlock == secret_hash, 'wrong hashlock' assert mediated_transfer.receiver == mediator_address, 'wrong mediator address' assert initiator_state.route == routes[0] assert len(initiator_state.routes.available_routes) == 0 assert len(initiator_state.routes.ignored_routes) == 0 assert len(initiator_state.routes.refunded_routes) == 0 assert len(initiator_state.routes.canceled_routes) == 0
def test_init_with_usable_routes(): amount = factories.UNIT_TRANSFER_AMOUNT block_number = 1 mediator_address = factories.HOP1 target_address = factories.HOP2 our_address = factories.ADDR secret_generator = SequenceGenerator() routes = [factories.make_route(mediator_address, available_balance=amount)] init_state_change = make_init_statechange( routes, target_address, block_number=block_number, our_address=our_address, secret_generator=secret_generator, ) expiration = block_number + factories.HOP1_TIMEOUT initiator_state_machine = StateManager( initiator.state_transition, None, ) assert initiator_state_machine.current_state is None events = initiator_state_machine.dispatch(init_state_change, ) initiator_state = initiator_state_machine.current_state assert isinstance(initiator_state, InitiatorState) assert initiator_state.our_address == our_address transfer = initiator_state.transfer assert isinstance(transfer, LockedTransferState) assert transfer.amount == amount assert transfer.target == target_address assert transfer.secret == secret_generator.secrets[0] assert transfer.hashlock == sha3(transfer.secret) assert len( events ), 'we have a valid route, the mediated transfer event must be emited' mediated_transfers = [ e for e in events if isinstance(e, SendMediatedTransfer) ] assert len(mediated_transfers ) == 1, 'mediated_transfer should /not/ split the transfer' mediated_transfer = mediated_transfers[0] assert mediated_transfer.token == factories.UNIT_TOKEN_ADDRESS assert mediated_transfer.amount == amount, 'transfer amount mismatch' assert mediated_transfer.expiration == expiration, 'transfer expiration mismatch' assert mediated_transfer.hashlock == sha3( secret_generator.secrets[0]), 'wrong hashlock' assert mediated_transfer.receiver == mediator_address, 'wrong mediator address' assert initiator_state.route == routes[0] assert len(initiator_state.routes.available_routes) == 0 assert len(initiator_state.routes.ignored_routes) == 0 assert len(initiator_state.routes.refunded_routes) == 0 assert len(initiator_state.routes.canceled_routes) == 0