def handle_secretrequest( initiator_state: InitiatorTransferState, state_change: ReceiveSecretRequest, channel_state: NettingChannelState, pseudo_random_generator: random.Random, ) -> TransitionResult[InitiatorTransferState]: is_message_from_target = ( state_change.sender == initiator_state.transfer_description.target and state_change.secrethash == initiator_state.transfer_description.secrethash and state_change.payment_identifier == initiator_state.transfer_description.payment_identifier) lock = channel.get_lock( channel_state.our_state, initiator_state.transfer_description.secrethash, ) already_received_secret_request = initiator_state.received_secret_request is_valid_secretrequest = (state_change.amount == initiator_state.transfer_description.amount and state_change.expiration == lock.expiration) if already_received_secret_request and is_message_from_target: # A secret request was received earlier, all subsequent are ignored # as it might be an attack iteration = TransitionResult(initiator_state, list()) elif is_valid_secretrequest and is_message_from_target: # Reveal the secret to the target node and wait for its confirmation. # At this point the transfer is not cancellable anymore as either the lock # timeouts or a secret reveal is received. # # Note: The target might be the first hop # message_identifier = message_identifier_from_prng( pseudo_random_generator) transfer_description = initiator_state.transfer_description recipient = transfer_description.target revealsecret = SendSecretReveal( recipient=Address(recipient), channel_identifier=CHANNEL_IDENTIFIER_GLOBAL_QUEUE, message_identifier=message_identifier, secret=transfer_description.secret, ) initiator_state.revealsecret = revealsecret initiator_state.received_secret_request = True iteration = TransitionResult(initiator_state, [revealsecret]) elif not is_valid_secretrequest and is_message_from_target: initiator_state.received_secret_request = True iteration = TransitionResult(initiator_state, list()) else: iteration = TransitionResult(initiator_state, list()) return iteration
def handle_secretrequest_light( initiator_state: InitiatorTransferState, state_change: ReceiveSecretRequestLight, channel_state: NettingChannelState ) -> TransitionResult[InitiatorTransferState]: is_message_from_target = ( state_change.sender == initiator_state.transfer_description.target and state_change.secrethash == initiator_state.transfer_description.secrethash and state_change.payment_identifier == initiator_state.transfer_description.payment_identifier ) lock = channel.get_lock( channel_state.our_state, initiator_state.transfer_description.secrethash ) # This should not ever happen. This task clears itself when the lock is # removed. assert lock is not None, "channel is does not have the transfer's lock" already_received_secret_request = initiator_state.received_secret_request # lock.amount includes the fees, transfer_description.amount is the actual # payment amount, for the transfer to be valid and the unlock allowed the # target must receive an amount between these values. is_valid_secretrequest = ( state_change.amount <= lock.amount and state_change.amount >= initiator_state.transfer_description.amount and state_change.expiration == lock.expiration ## and initiator_state.transfer_description.secret != EMPTY_SECRET ) if already_received_secret_request and is_message_from_target: # A secret request was received earlier, all subsequent are ignored # as it might be an attack iteration = TransitionResult(initiator_state, list()) elif is_valid_secretrequest and is_message_from_target: store_event = StoreMessageEvent(state_change.secret_request_message.message_identifier, state_change.payment_identifier, 5, state_change.secret_request_message, True) initiator_state.received_secret_request = True iteration = TransitionResult(initiator_state, [store_event]) elif not is_valid_secretrequest and is_message_from_target: initiator_state.received_secret_request = True iteration = TransitionResult(initiator_state, list()) else: iteration = TransitionResult(initiator_state, list()) return iteration
def handle_send_secret_reveal_light( initiator_state: InitiatorTransferState, state_change: ActionSendSecretRevealLight ) -> TransitionResult[InitiatorTransferState]: # Reveal the secret to the target node and wait for its confirmation. # At this point the transfer is not cancellable anymore as either the lock # timeouts or a secret reveal is received. # # Note: The target might be the first hop # message_identifier = state_change.reveal_secret.message_identifier transfer_description = initiator_state.transfer_description recipient = transfer_description.target revealsecret = SendSecretRevealLight( sender= Address(state_change.sender), recipient=Address(recipient), channel_identifier=CHANNEL_IDENTIFIER_GLOBAL_QUEUE, message_identifier=message_identifier, secret=state_change.reveal_secret.secret, signed_secret_reveal=state_change.reveal_secret ) initiator_state.revealsecret = revealsecret initiator_state.received_secret_request = True store_message_event = StoreMessageEvent(message_identifier, transfer_description.payment_identifier, 7, state_change.reveal_secret, True) iteration = TransitionResult(initiator_state, [revealsecret, store_message_event]) return iteration
def handle_secretrequest( initiator_state: InitiatorTransferState, state_change: ReceiveSecretRequest, channel_state: NettingChannelState, pseudo_random_generator: random.Random, ) -> TransitionResult[InitiatorTransferState]: is_message_from_target = ( state_change.sender == initiator_state.transfer_description.target and state_change.secrethash == initiator_state.transfer_description.secrethash and state_change.payment_identifier == initiator_state.transfer_description.payment_identifier) lock = channel.get_lock(channel_state.our_state, initiator_state.transfer_description.secrethash) # This should not ever happen. This task clears itself when the lock is # removed. assert lock is not None, "channel is does not have the transfer's lock" already_received_secret_request = initiator_state.received_secret_request # transfer_description.amount is the actual payment amount without fees. # For the transfer to be valid and the unlock allowed the target must # receive at least that amount. is_valid_secretrequest = ( state_change.amount >= initiator_state.transfer_description.amount and state_change.expiration == lock.expiration and initiator_state.transfer_description.secret != ABSENT_SECRET) if already_received_secret_request and is_message_from_target: # A secret request was received earlier, all subsequent are ignored # as it might be an attack iteration = TransitionResult(initiator_state, list()) elif is_valid_secretrequest and is_message_from_target: # Reveal the secret to the target node and wait for its confirmation. # At this point the transfer is not cancellable anymore as either the lock # timeouts or a secret reveal is received. # # Note: The target might be the first hop # message_identifier = message_identifier_from_prng( pseudo_random_generator) transfer_description = initiator_state.transfer_description recipient = transfer_description.target revealsecret = SendSecretReveal( recipient=Address(recipient), message_identifier=message_identifier, secret=transfer_description.secret, canonical_identifier=CANONICAL_IDENTIFIER_GLOBAL_QUEUE, ) initiator_state.transfer_state = "transfer_secret_revealed" initiator_state.received_secret_request = True iteration = TransitionResult(initiator_state, [revealsecret]) elif not is_valid_secretrequest and is_message_from_target: initiator_state.received_secret_request = True invalid_request = EventInvalidSecretRequest( payment_identifier=state_change.payment_identifier, intended_amount=initiator_state.transfer_description.amount, actual_amount=state_change.amount, ) iteration = TransitionResult(initiator_state, [invalid_request]) else: iteration = TransitionResult(initiator_state, list()) return iteration