def test_get_networks(chain_state, token_network_address): orig_chain_state = deepcopy(chain_state) token_address = factories.make_address() token_network_registry_empty = TokenNetworkRegistryState( address=factories.make_address(), token_network_list=[]) chain_state.identifiers_to_tokennetworkregistries[ token_network_registry_empty.address] = token_network_registry_empty assert get_networks( chain_state=chain_state, token_network_registry_address=token_network_registry_empty.address, token_address=token_address, ) == (token_network_registry_empty, None) chain_state = orig_chain_state token_network = TokenNetworkState( address=token_network_address, token_address=token_address, network_graph=TokenNetworkGraphState( token_network_address=token_network_address), ) token_network_registry = TokenNetworkRegistryState( address=factories.make_address(), token_network_list=[token_network]) assert get_networks( chain_state=chain_state, token_network_registry_address=token_network_registry.address, token_address=token_address, ) == (None, None) chain_state.identifiers_to_tokennetworkregistries[ token_network_registry.address] = token_network_registry assert get_networks( chain_state=chain_state, token_network_registry_address=token_network_registry.address, token_address=token_address, ) == (token_network_registry, token_network)
def wrong_amount_secret_request(self, previous_action, amount): assume(amount != previous_action.transfer.amount) self._assume_channel_opened(previous_action) transfer = deepcopy(previous_action.transfer) transfer.amount = amount action = self._receive_secret_request(transfer) self._invalid_authentic_secret_request(previous_action, action)
def copy(self) -> "StateManager[ST]": # The state objects must be treated as immutable, so make a copy of the # current state and pass the copy to the state machine to be modified. before_copy = time.time() copy_state = deepcopy(self.current_state) log.debug("Copied state before applying state changes", duration=time.time() - before_copy) return StateManager(self.state_transition, copy_state)
def clone_state(state: T) -> T: # The state objects must be treated as immutable, so make a copy of the # current state and pass the copy to the state machine to be modified. before_copy = time.time() copy_state = deepcopy(state) log.debug("Copied state before applying state changes", duration=time.time() - before_copy) return copy_state
def test_contract_receive_channelnew_must_be_idempotent(channel_properties): block_number = 10 block_hash = factories.make_block_hash() token_network_address = factories.make_address() token_id = factories.make_address() token_network_state = TokenNetworkState( address=token_network_address, token_address=token_id, network_graph=TokenNetworkGraphState(token_network_address), ) pseudo_random_generator = random.Random() properties, _ = channel_properties channel_state1 = factories.create(properties) channel_state2 = deepcopy(channel_state1) state_change1 = ContractReceiveChannelNew( transaction_hash=factories.make_transaction_hash(), channel_state=channel_state1, block_number=block_number, block_hash=block_hash, ) token_network.state_transition( token_network_state=token_network_state, state_change=state_change1, block_number=block_number, block_hash=block_hash, pseudo_random_generator=pseudo_random_generator, ) state_change2 = ContractReceiveChannelNew( transaction_hash=factories.make_transaction_hash(), channel_state=channel_state2, block_number=block_number + 1, block_hash=factories.make_block_hash(), ) # replay the ContractReceiveChannelNew state change iteration = token_network.state_transition( token_network_state=token_network_state, state_change=state_change2, block_number=block_number, block_hash=block_hash, pseudo_random_generator=pseudo_random_generator, ) msg = "the channel must not have been overwritten" channelmap_by_id = iteration.new_state.channelidentifiers_to_channels assert channelmap_by_id[channel_state1.identifier] == channel_state1, msg channelmap_by_address = iteration.new_state.partneraddresses_to_channelidentifiers partner_channels_ids = channelmap_by_address[ channel_state1.partner_state.address] assert channel_state1.identifier in partner_channels_ids, msg
def secret_request_with_wrong_payment_id(self, previous_action, payment_identifier): assume( payment_identifier != previous_action.transfer.payment_identifier) self._assume_channel_opened(previous_action) transfer = deepcopy(previous_action.transfer) transfer.payment_identifier = payment_identifier action = self._receive_secret_request(transfer) client = self._get_initiator_client(transfer) self._unauthentic_secret_request(action, client)
def secret_request_with_wrong_secrethash(self, previous_action, secret): assume( sha256_secrethash(secret) != sha256_secrethash( previous_action.transfer.secret)) self._assume_channel_opened(previous_action) transfer = deepcopy(previous_action.transfer) transfer.secret = secret action = self._receive_secret_request(transfer) client = self._get_initiator_client(transfer) return self._unauthentic_secret_request(action, client)
def handle_action_transfer_reroute( chain_state: ChainState, state_change: ActionTransferReroute ) -> TransitionResult[ChainState]: new_secrethash = state_change.secrethash current_payment_task = chain_state.payment_mapping.secrethashes_to_task[ state_change.transfer.lock.secrethash ] chain_state.payment_mapping.secrethashes_to_task.update( {new_secrethash: deepcopy(current_payment_task)} ) return subdispatch_to_paymenttask(chain_state, state_change, new_secrethash)
def deserialize(data: Dict) -> Any: """ Deserialize a dict-like object. If the key ``_type`` is present, import the target and deserialize via Marshmallow. Raises ``SerializationError`` for invalid inputs. """ if not isinstance(data, Mapping): raise SerializationError( f"Can't deserialize non dict-like objects: {data}") if "_type" in data: try: klass = _import_type(data["_type"]) schema = SchemaCache.get_or_create_schema(klass) return schema.load(deepcopy(data)) except (ValueError, TypeError, ValidationError) as ex: raise SerializationError(f"Can't deserialize: {data}") from ex return data
def dispatch( self, state_changes: List[StateChange]) -> Tuple[ST, List[List[Event]]]: """ Apply the `state_change` in the current machine and return the resulting events. Args: state_change: An object representation of a state change. Return: A list of events produced by the state transition. It's the upper layer's responsibility to decided how to handle these events. """ if not state_changes: raise ValueError( "dispatch called with an empty state_changes list") # The state objects must be treated as immutable, so make a copy of the # current state and pass the copy to the state machine to be modified. before_copy = time.time() next_state = deepcopy(self.current_state) log.debug("Copied state before applying state changes", duration=time.time() - before_copy) # Update the current state by applying the state changes events: List[List[Event]] = list() for state_change in state_changes: iteration = self.state_transition(next_state, state_change) typecheck(iteration, TransitionResult) for e in iteration.events: typecheck(e, Event) typecheck(iteration.new_state, State) # Skipping the copy because this value is internal events.append(iteration.events) next_state = iteration.new_state assert next_state is not None, "State transition did not yield new state" self.current_state = next_state return iteration.new_state, events
def _channel_and_transfer(num_pending_locks): our_model, _ = create_model(700) partner_model, privkey = create_model(700, num_pending_locks) reverse_channel_state = create_channel_from_models(partner_model, our_model, privkey) lock_secret = keccak(b"some secret seed") lock = HashTimeLockState(30, 10, sha256(lock_secret).digest()) mediated_transfer = make_receive_transfer_mediated( reverse_channel_state, privkey, nonce=partner_model.next_nonce, transferred_amount=0, lock=lock, pending_locks=PendingLocksState(partner_model.pending_locks + [bytes(lock.encoded)]), locked_amount=lock.amount, ) channel_state = deepcopy(reverse_channel_state) channel_state.our_state = reverse_channel_state.partner_state channel_state.partner_state = reverse_channel_state.our_state return channel_state, mediated_transfer
def test_subdispatch_by_canonical_id(chain_state): our_model, _ = create_model(balance=10, num_pending_locks=1) partner_model, _ = create_model(balance=0, num_pending_locks=0) channel_state = create_channel_from_models( our_model, partner_model, factories.make_privatekey_bin() ) canonical_identifier = channel_state.canonical_identifier token_network = TokenNetworkState( address=canonical_identifier.token_network_address, token_address=factories.make_address(), network_graph=TokenNetworkGraphState( token_network_address=channel_state.token_network_address ), ) token_network.partneraddresses_to_channelidentifiers[ partner_model.participant_address ] = canonical_identifier.channel_identifier token_network.channelidentifiers_to_channels[ canonical_identifier.channel_identifier ] = channel_state token_network_registry = TokenNetworkRegistryState( address=factories.make_address(), token_network_list=[token_network] ) chain_state.identifiers_to_tokennetworkregistries[ token_network_registry.address ] = token_network_registry chain_state.tokennetworkaddresses_to_tokennetworkregistryaddresses[ canonical_identifier.token_network_address ] = token_network_registry.address # dispatching a Block will be ignored previous_state = deepcopy(chain_state) state_change = Block( block_number=chain_state.block_number, gas_limit=GAS_LIMIT, block_hash=chain_state.block_hash, ) transition_result = subdispatch_by_canonical_id( chain_state=chain_state, canonical_identifier=canonical_identifier, state_change=state_change, ) assert transition_result.new_state == previous_state assert transition_result.events == [] state_change = ActionChannelClose(canonical_identifier=canonical_identifier) # dispatching for an unknown canonical_identifier will not emit events transition_result = subdispatch_by_canonical_id( chain_state=chain_state, canonical_identifier=CanonicalIdentifier( chain_identifier=chain_state.chain_id, token_network_address=factories.make_address(), channel_identifier=factories.make_channel_identifier(), ), state_change=state_change, ) assert not transition_result.events, transition_result assert get_status(channel_state) == ChannelState.STATE_OPENED transition_result = subdispatch_by_canonical_id( chain_state=chain_state, canonical_identifier=canonical_identifier, state_change=state_change, ) assert get_status(channel_state) == ChannelState.STATE_CLOSING assert transition_result.new_state == chain_state, transition_result
def test_fees_are_updated_during_startup(raiden_network, restart_node, token_addresses, deposit, retry_timeout) -> None: """ Test that the supplied fee settings are correctly forwarded to all channels during node startup. """ app0, app1 = raiden_network token_address = token_addresses[0] def get_channel_state(app) -> NettingChannelState: chain_state = views.state_from_app(app) token_network_registry_address = app.raiden.default_registry.address token_network_address = views.get_token_network_address_by_token_address( chain_state, token_network_registry_address, token_address) assert token_network_address channel_state = views.get_channelstate_by_token_network_and_partner( chain_state, token_network_address, app1.raiden.address) assert channel_state return channel_state waiting.wait_both_channel_deposit(app0, app1, app0.raiden.default_registry.address, token_address, deposit, retry_timeout) # This is the imbalance penalty generated for the deposit # with DEFAULT_MEDIATION_PROPORTIONAL_IMBALANCE_FEE # once both channels have deposited the default (200) deposit default_imbalance_penalty = [ (0, 1), (20, 0), (40, 0), (60, 0), (80, 0), (100, 0), (120, 0), (140, 0), (160, 0), (180, 0), (200, 0), (220, 0), (240, 0), (260, 0), (280, 0), (300, 0), (320, 0), (340, 0), (360, 0), (380, 0), (400, 1), ] # Check that the defaults are used channel_state = get_channel_state(app0) assert channel_state.fee_schedule.flat == DEFAULT_MEDIATION_FLAT_FEE assert channel_state.fee_schedule.proportional == DEFAULT_MEDIATION_PROPORTIONAL_FEE assert channel_state.fee_schedule.imbalance_penalty == default_imbalance_penalty original_config = deepcopy(app0.raiden.config) # Now restart app0, and set new flat fee for that token network flat_fee = FeeAmount(100) app0.stop() app0.raiden.config = deepcopy(original_config) app0.raiden.config.mediation_fees.token_to_flat_fee[ token_address] = flat_fee restart_node(app0) channel_state = get_channel_state(app0) assert channel_state.fee_schedule.flat == flat_fee assert channel_state.fee_schedule.proportional == DEFAULT_MEDIATION_PROPORTIONAL_FEE assert channel_state.fee_schedule.imbalance_penalty == default_imbalance_penalty # Now restart app0, and set new proportional fee prop_fee = ProportionalFeeAmount(123) app0.stop() app0.raiden.config = deepcopy(original_config) app0.raiden.config.mediation_fees.token_to_proportional_fee[ token_address] = prop_fee restart_node(app0) channel_state = get_channel_state(app0) assert channel_state.fee_schedule.flat == DEFAULT_MEDIATION_FLAT_FEE assert channel_state.fee_schedule.proportional == prop_fee assert channel_state.fee_schedule.imbalance_penalty == default_imbalance_penalty # Now restart app0, and set new proportional imbalance fee app0.stop() app0.raiden.config = deepcopy(original_config) app0.raiden.config.mediation_fees.token_to_proportional_imbalance_fee[ token_address] = 0.05e6 restart_node(app0) channel_state = get_channel_state(app0) assert channel_state.fee_schedule.flat == DEFAULT_MEDIATION_FLAT_FEE assert channel_state.fee_schedule.proportional == DEFAULT_MEDIATION_PROPORTIONAL_FEE # with 5% imbalance fee full_imbalance_penalty = [ (0, 20), (20, 18), (40, 16), (60, 14), (80, 12), (100, 10), (120, 8), (140, 6), (160, 4), (180, 2), (200, 0), (220, 2), (240, 4), (260, 6), (280, 8), (300, 10), (320, 12), (340, 14), (360, 16), (380, 18), (400, 20), ] assert channel_state.fee_schedule.imbalance_penalty == full_imbalance_penalty