def __post_init__(self) -> None: typecheck(self.address, T_Address) typecheck(self.token_address, T_Address) self.partneraddresses_to_channelidentifiers = defaultdict( list, self.partneraddresses_to_channelidentifiers )
def __post_init__(self) -> None: typecheck(self.lock, HashTimeLockState) typecheck(self.secret, T_Secret) self.amount = self.lock.amount self.expiration = self.lock.expiration self.secrethash = self.lock.secrethash self.encoded = self.lock.encoded
def __post_init__(self) -> None: typecheck(self.address, T_Address) typecheck(self.contract_balance, T_TokenAmount) if self.address == NULL_ADDRESS_BYTES: raise ValueError("address cannot be null.") if self.contract_balance < 0: raise ValueError("contract_balance cannot be negative.")
def state_transition( chain_state: ChainState, state_change: StateChange ) -> TransitionResult[ChainState]: iteration = handle_state_change(chain_state, state_change) update_queues(iteration, state_change) typecheck(iteration.new_state, ChainState) return iteration
def __post_init__(self) -> None: typecheck(self.lock, HashTimeLockState) typecheck(self.balance_proof, BalanceProofSignedState) # At least the lock for this transfer must be in the locksroot, so it # must not be empty # pylint: disable=E1101 if self.balance_proof.locksroot == LOCKSROOT_OF_NO_LOCKS: raise ValueError("balance_proof must not be empty")
def make_receive_expired_lock( channel_state: NettingChannelState, privkey: bytes, nonce: Nonce, transferred_amount: TokenAmount, lock: HashTimeLockState, locked_amount: LockedAmount, pending_locks: PendingLocksState = None, chain_id: ChainID = None, ) -> ReceiveLockExpired: typecheck(lock, HashTimeLockState) signer = LocalSigner(privkey) address = signer.address if address not in (channel_state.our_state.address, channel_state.partner_state.address): raise ValueError("Private key does not match any of the participants.") if pending_locks is None: pending_locks = make_empty_pending_locks_state() else: assert lock.encoded not in pending_locks.locks locksroot = compute_locksroot(pending_locks) chain_id = chain_id or channel_state.chain_id lock_expired_msg = LockExpired( chain_id=chain_id, nonce=nonce, message_identifier=make_message_identifier(), transferred_amount=transferred_amount, locked_amount=TokenAmount(locked_amount), locksroot=locksroot, channel_identifier=channel_state.identifier, token_network_address=channel_state.token_network_address, recipient=channel_state.partner_state.address, secrethash=lock.secrethash, signature=EMPTY_SIGNATURE, ) lock_expired_msg.sign(signer) balance_proof = balanceproof_from_envelope(lock_expired_msg) receive_lockedtransfer = ReceiveLockExpired( balance_proof=balance_proof, secrethash=lock.secrethash, message_identifier=make_message_identifier(), sender=balance_proof.sender, ) return receive_lockedtransfer
def __post_init__(self) -> None: typecheck(self.reveal_timeout, int) typecheck(self.settle_timeout, int) typecheck(self.open_transaction, SuccessfulTransactionState) typecheck(self.canonical_identifier.channel_identifier, T_ChannelID) if self.our_state.address == self.partner_state.address: raise ValueError("it is illegal to open a channel with itself") if self.reveal_timeout <= 0: raise ValueError("reveal_timeout must be a positive integer") if self.settle_timeout <= 0: raise ValueError("settle_timeout must be a positive integer") if (self.canonical_identifier.channel_identifier < 0 or self.canonical_identifier.channel_identifier > UINT256_MAX): raise ValueError("channel identifier should be a uint256") valid_close_transaction = self.close_transaction is None or isinstance( self.close_transaction, TransactionExecutionStatus) if not valid_close_transaction: raise ValueError( "close_transaction must be a TransactionExecutionStatus instance" ) valid_settle_transaction = self.settle_transaction is None or isinstance( self.settle_transaction, TransactionExecutionStatus) if not valid_settle_transaction: raise ValueError( "settle_transaction must be a TransactionExecutionStatus instance or None" )
def __post_init__(self) -> None: typecheck(self.address, T_Address) if not self.tokennetworkaddresses_to_tokennetworks: self.tokennetworkaddresses_to_tokennetworks: Dict[ TokenNetworkAddress, TokenNetworkState ] = {token_network.address: token_network for token_network in self.token_network_list} if not self.tokenaddresses_to_tokennetworkaddresses: self.tokenaddresses_to_tokennetworkaddresses: Dict[ TokenAddress, TokenNetworkAddress ] = { token_network.token_address: token_network.address for token_network in self.token_network_list }
def __post_init__(self) -> None: typecheck(self.nonce, int) typecheck(self.transferred_amount, T_TokenAmount) typecheck(self.locked_amount, T_TokenAmount) typecheck(self.locksroot, T_Locksroot) if self.nonce <= 0: raise ValueError("nonce cannot be zero or negative") if self.nonce > UINT64_MAX: raise ValueError("nonce is too large") if self.transferred_amount < 0: raise ValueError("transferred_amount cannot be negative") if self.transferred_amount > UINT256_MAX: raise ValueError("transferred_amount is too large") if len(self.locksroot) != 32: raise ValueError("locksroot must have length 32") self.canonical_identifier.validate() self.balance_hash = hash_balance_data( transferred_amount=self.transferred_amount, locked_amount=self.locked_amount, locksroot=self.locksroot, )
def events_for_onchain_secretreveal( channel_state: NettingChannelState, secret: Secret, expiration: BlockExpiration, block_hash: BlockHash, ) -> List[Event]: events: List[Event] = list() typecheck(secret, T_Secret) if get_status(channel_state) in CHANNEL_STATES_UP_TO_CLOSED: reveal_event = ContractSendSecretReveal( expiration=expiration, secret=secret, triggered_by_block_hash=block_hash ) events.append(reveal_event) return events
def get_token_network( self, token_address: TokenAddress, block_identifier: BlockIdentifier ) -> Optional[TokenNetworkAddress]: """Return the token network address for the given token or None if there is no correspoding address. """ typecheck(token_address, T_TargetAddress) address = self.proxy.functions.token_to_token_networks( token_address).call(block_identifier=block_identifier) address = to_canonical_address(address) if address == NULL_ADDRESS_BYTES: return None return address
def get_token_network( self, token_address: TokenAddress, block_identifier: BlockSpecification ) -> Optional[TokenNetworkAddress]: """ Return the token network address for the given token or None if there is no correspoding address. """ typecheck(token_address, T_TargetAddress) address = self.proxy.contract.functions.token_to_token_networks( to_checksum_address(token_address)).call( block_identifier=block_identifier) address = to_canonical_address(address) if is_same_address(address, NULL_ADDRESS_HEX): return None return address
def from_balance_proof_signed_state( cls, balance_proof: BalanceProofSignedState ) -> "SignedBlindedBalanceProof": typecheck(balance_proof, BalanceProofSignedState) # pylint: disable=unexpected-keyword-arg return cls( channel_identifier=balance_proof.channel_identifier, token_network_address=balance_proof.token_network_address, nonce=balance_proof.nonce, additional_hash=balance_proof.message_hash, chain_id=balance_proof.chain_id, signature=balance_proof.signature, balance_hash=hash_balance_data( balance_proof.transferred_amount, balance_proof.locked_amount, balance_proof.locksroot, ), )
def from_balance_proof_signed_state( cls, balance_proof: BalanceProofSignedState, non_closing_participant: Address, reward_amount: TokenAmount, monitoring_service_contract_address: Address, ) -> "RequestMonitoring": typecheck(balance_proof, BalanceProofSignedState) onchain_balance_proof = SignedBlindedBalanceProof.from_balance_proof_signed_state( balance_proof=balance_proof ) # pylint: disable=unexpected-keyword-arg return cls( balance_proof=onchain_balance_proof, reward_amount=reward_amount, signature=EMPTY_SIGNATURE, non_closing_participant=non_closing_participant, monitoring_service_contract_address=monitoring_service_contract_address, )
def validate(self) -> None: typecheck(self.chain_identifier, T_ChainID) typecheck(self.token_network_address, T_Address) typecheck(self.channel_identifier, T_ChannelID) if self.channel_identifier < 0 or self.channel_identifier > UINT256_MAX: raise ValueError("channel id is invalid")
def handle_action_change_node_network_state( chain_state: ChainState, state_change: ActionChangeNodeNetworkState ) -> TransitionResult[ChainState]: events: List[Event] = list() node_address = state_change.node_address network_state = state_change.network_state chain_state.nodeaddresses_to_networkstates[node_address] = network_state for secrethash, subtask in list(chain_state.payment_mapping.secrethashes_to_task.items()): # This typecheck would not have been needed if token_network_address, a common attribute # for all TransferTasks was part of the TransferTasks superclass. typecheck(subtask, (InitiatorTask, MediatorTask, TargetTask)) result = subdispatch_mediatortask( chain_state=chain_state, state_change=state_change, token_network_address=subtask.token_network_address, secrethash=secrethash, ) events.extend(result.events) return TransitionResult(chain_state, events)
def payment_channel( self, canonical_identifier: CanonicalIdentifier) -> PaymentChannel: token_network_address = canonical_identifier.token_network_address channel_id = canonical_identifier.channel_identifier if not is_binary_address(token_network_address): raise ValueError("address must be a valid address") typecheck(channel_id, T_ChannelID) with self._payment_channel_creation_lock: dict_key = (token_network_address, channel_id) if dict_key not in self.identifier_to_payment_channel: token_network = self.token_network(token_network_address) self.identifier_to_payment_channel[dict_key] = PaymentChannel( token_network=token_network, channel_identifier=channel_id, contract_manager=self.contract_manager, ) return self.identifier_to_payment_channel[dict_key]
def __post_init__(self) -> None: typecheck(self.amount, T_PaymentWithFeeAmount) typecheck(self.expiration, T_BlockNumber) typecheck(self.secrethash, T_Secret) from raiden.messages.transfers import Lock # put here to avoid cyclic depenendcies lock = Lock(amount=self.amount, expiration=self.expiration, secrethash=self.secrethash) self.encoded = EncodedData(lock.as_bytes)
def dispatch( state: ST, state_transition: Callable[[ST, StateChange], TransitionResult[ST]], state_change: StateChange, ) -> Tuple[ST, List[Event]]: iteration = state_transition(state, state_change) typecheck(iteration, TransitionResult) for e in iteration.events: typecheck(e, Event) typecheck(iteration.new_state, State) assert iteration.new_state is not None, "State transition did not yield new state" return iteration.new_state, iteration.events
def dispatch(self, state_change: StateChange) -> Tuple[ST, List[Event]]: # Update the current state by applying the state changes iteration = self.state_transition(self.current_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 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, iteration.events
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 __post_init__(self) -> None: super().__post_init__() typecheck(self.from_hop, HopState) typecheck(self.transfer, LockedTransferSignedState)
def __post_init__(self) -> None: typecheck(self.transfer, TransferDescriptionWithSecretState)
def __post_init__(self) -> None: typecheck(self.payer_transfer, LockedTransferSignedState) typecheck(self.payee_address, T_Address) typecheck(self.payee_transfer, LockedTransferUnsignedState)
def __post_init__(self) -> None: super().__post_init__() typecheck(self.transfer, LockedTransferUnsignedState)
def __post_init__(self) -> None: typecheck(self.triggered_by_block_hash, T_BlockHash)
def __post_init__(self) -> None: typecheck(self.block_number, T_BlockNumber) typecheck(self.block_hash, T_BlockHash)
def __post_init__(self) -> None: typecheck(self.nonce, int) typecheck(self.transferred_amount, T_TokenAmount) typecheck(self.locked_amount, T_LockedAmount) typecheck(self.locksroot, T_Locksroot) typecheck(self.message_hash, bytes) typecheck(self.signature, T_Signature) typecheck(self.sender, T_Address) if self.nonce <= 0: raise ValueError("nonce cannot be zero or negative") if self.nonce > UINT64_MAX: raise ValueError("nonce is too large") if self.transferred_amount < 0: raise ValueError("transferred_amount cannot be negative") if self.transferred_amount > UINT256_MAX: raise ValueError("transferred_amount is too large") if len(self.locksroot) != 32: raise ValueError("locksroot must have length 32") if len(self.message_hash) != 32: raise ValueError("message_hash is an invalid hash") if len(self.signature) != 65: raise ValueError("signature is an invalid signature") self.canonical_identifier.validate() self.balance_hash = hash_balance_data( transferred_amount=self.transferred_amount, locked_amount=self.locked_amount, locksroot=self.locksroot, )
def __post_init__(self) -> None: super().__post_init__() typecheck(self.transfer, LockedTransferSignedState) object.__setattr__(self, "secrethash", sha256_secrethash(self.secret))
def make_receive_transfer_mediated( channel_state: NettingChannelState, privkey: bytes, nonce: Nonce, transferred_amount: TokenAmount, lock: HashTimeLockState, pending_locks: PendingLocksState = None, locked_amount: Optional[PaymentWithFeeAmount] = None, chain_id: Optional[ChainID] = None, ) -> LockedTransferSignedState: typecheck(lock, HashTimeLockState) signer = LocalSigner(privkey) address = signer.address if address not in (channel_state.our_state.address, channel_state.partner_state.address): raise ValueError("Private key does not match any of the participants.") if pending_locks is None: locks = make_empty_pending_locks_state() locks.locks.append(lock.encoded) else: assert bytes(lock.encoded) in pending_locks.locks locks = pending_locks if locked_amount is None: locked_amount = lock.amount assert locked_amount >= lock.amount locksroot = compute_locksroot(locks) payment_identifier = PaymentID(nonce) transfer_target = make_target_address() transfer_initiator = make_initiator_address() chain_id = chain_id or channel_state.chain_id transfer_metadata = Metadata(routes=[ RouteMetadata( route=[channel_state.our_state.address, Address(transfer_target)]) ]) mediated_transfer_msg = LockedTransfer( chain_id=chain_id, message_identifier=make_message_identifier(), payment_identifier=payment_identifier, nonce=nonce, token_network_address=channel_state.token_network_address, token=channel_state.token_address, channel_identifier=channel_state.identifier, transferred_amount=transferred_amount, locked_amount=TokenAmount(locked_amount), recipient=channel_state.partner_state.address, locksroot=locksroot, lock=Lock(amount=lock.amount, expiration=lock.expiration, secrethash=lock.secrethash), target=transfer_target, initiator=transfer_initiator, signature=EMPTY_SIGNATURE, fee=0, metadata=transfer_metadata, ) mediated_transfer_msg.sign(signer) receive_lockedtransfer = LockedTransferSignedState( payment_identifier=payment_identifier, token=channel_state.token_address, lock=lock, initiator=transfer_initiator, target=transfer_target, message_identifier=make_message_identifier(), balance_proof=balanceproof_from_envelope(mediated_transfer_msg), routes=[ route_metadata.route for route_metadata in transfer_metadata.routes ], ) return receive_lockedtransfer