def test_get_secret(): secret1 = factories.make_secret() secret2 = factories.make_secret() secrethash3 = factories.make_keccak_hash() secrethash4 = factories.make_keccak_hash() lock_state = HashTimeLockState(amount=10, expiration=10, secrethash=factories.UNIT_SECRETHASH) end_state = factories.create(factories.NettingChannelEndStateProperties()) end_state = factories.replace( end_state, secrethashes_to_lockedlocks={secrethash3: lock_state}, secrethashes_to_unlockedlocks={ sha3(secret1): UnlockPartialProofState(lock=lock_state, secret=secret1) }, secrethashes_to_onchain_unlockedlocks={ sha3(secret2): UnlockPartialProofState(lock=lock_state, secret=secret2) }, ) assert get_secret( end_state, sha3(secret1)) == secret1 # known secret from offchain unlock assert get_secret( end_state, sha3(secret2)) == secret2 # known secret from offchain unlock assert get_secret(end_state, secrethash3) is None # known lock but not unlocked yet assert get_secret(end_state, secrethash4) is None # unknown secrethash
def events_for_onchain_secretreveal( target_state: TargetTransferState, channel_state: NettingChannelState, block_number: typing.BlockNumber, ): """ Emits the event for revealing the secret on-chain if the transfer can not be settled off-chain. """ transfer = target_state.transfer expiration = transfer.lock.expiration safe_to_wait, _ = is_safe_to_wait( expiration, channel_state.reveal_timeout, block_number, ) secret_known_offchain = channel.is_secret_known_offchain( channel_state.partner_state, transfer.lock.secrethash, ) if not safe_to_wait and secret_known_offchain: secret = channel.get_secret( channel_state.partner_state, transfer.lock.secrethash, ) return secret_registry.events_for_onchain_secretreveal( channel_state, secret, expiration, ) return list()
def events_for_onchain_secretreveal( target_state: TargetTransferState, channel_state: NettingChannelState, block_number: BlockNumber, block_hash: BlockHash, ) -> List[Event]: """ Emits the event for revealing the secret on-chain if the transfer can not be settled off-chain. """ transfer = target_state.transfer expiration = transfer.lock.expiration safe_to_wait = is_safe_to_wait(expiration, channel_state.reveal_timeout, block_number) secret_known_offchain = channel.is_secret_known_offchain( channel_state.partner_state, transfer.lock.secrethash ) has_onchain_reveal_started = target_state.state == TargetTransferState.ONCHAIN_SECRET_REVEAL if not safe_to_wait and secret_known_offchain and not has_onchain_reveal_started: target_state.state = TargetTransferState.ONCHAIN_SECRET_REVEAL secret = channel.get_secret(channel_state.partner_state, transfer.lock.secrethash) assert secret, "secret should be known at this point" return secret_registry.events_for_onchain_secretreveal( channel_state=channel_state, secret=secret, expiration=expiration, block_hash=block_hash, ) return list()
def events_for_onchain_secretreveal(target_state, channel_state, block_number): """ Emits the event for revealing the secret on-chain if the transfer cannot to be settled off-chain. """ transfer = target_state.transfer safe_to_wait = is_safe_to_wait( transfer.lock.expiration, channel_state.reveal_timeout, block_number, ) secret_known = channel.is_secret_known( channel_state.partner_state, transfer.lock.secrethash, ) if not safe_to_wait and secret_known: secret = channel.get_secret( channel_state.partner_state, transfer.lock.secrethash, ) return secret_registry.events_for_onchain_secretreveal( channel_state, block_number, secret, ) return list()
def events_for_onchain_secretreveal(target_state, channel_state, block_number): """ Emits the event for revealing the secret on-chain if the transfer cannot to be settled off-chain. """ transfer = target_state.transfer safe_to_wait = is_safe_to_wait( transfer.lock.expiration, channel_state.reveal_timeout, block_number, ) secret_known = channel.is_secret_known( channel_state.partner_state, transfer.lock.secrethash, ) if not safe_to_wait and secret_known: secret = channel.get_secret( channel_state.partner_state, transfer.lock.secrethash, ) return secret_registry.events_for_onchain_secretreveal( channel_state, block_number, secret, ) return list()
def events_for_onchain_secretreveal( channelidentifiers_to_channels, transfers_pair, block_number, ): """ Reveal the secret if a locks is in the unsafe region. """ events = list() pending_transfers_pairs = get_pending_transfer_pairs(transfers_pair) for pair in reversed(pending_transfers_pairs): payer_channel = get_payer_channel(channelidentifiers_to_channels, pair) expiration = pair.payer_transfer.lock.expiration safe_to_wait, _ = is_safe_to_wait( expiration, payer_channel.reveal_timeout, block_number, ) # We check if the secret is already known by receiving a ReceiveSecretReveal state change secret_known = channel.is_secret_known( payer_channel.partner_state, pair.payer_transfer.lock.secrethash, ) if not safe_to_wait and secret_known: secret = channel.get_secret( payer_channel.partner_state, pair.payer_transfer.lock.secrethash, ) reveal_events = secret_registry.events_for_onchain_secretreveal( payer_channel, secret, expiration, ) # short circuit because the secret needs to be revealed on-chain # only once return reveal_events return events
def events_for_onchain_secretreveal( channelidentifiers_to_channels, transfers_pair, block_number, ): """ Reveal secrets for transfer locks that are in the unsafe region. """ events = list() pending_transfers_pairs = get_pending_transfer_pairs(transfers_pair) for pair in reversed(pending_transfers_pairs): payer_channel = get_payer_channel(channelidentifiers_to_channels, pair) safe_to_wait = is_safe_to_wait( pair.payer_transfer.lock.expiration, payer_channel.reveal_timeout, block_number, ) # We check if the secret is already known by receiving a ReceiveSecretReveal state change secret_known = channel.is_secret_known( payer_channel.partner_state, pair.payer_transfer.lock.secrethash, ) if not safe_to_wait and secret_known: secret = channel.get_secret( payer_channel.partner_state, pair.payer_transfer.lock.secrethash, ) reveal_events = secret_registry.events_for_onchain_secretreveal( payer_channel, block_number, secret, ) events.extend(reveal_events) return events
def events_for_onchain_secretreveal( channelidentifiers_to_channels, transfers_pair, block_number, ): """ Reveal secrets for transfer locks that are in the unsafe region. """ events = list() pending_transfers_pairs = get_pending_transfer_pairs(transfers_pair) for pair in reversed(pending_transfers_pairs): payer_channel = get_payer_channel(channelidentifiers_to_channels, pair) safe_to_wait = is_safe_to_wait( pair.payer_transfer.lock.expiration, payer_channel.reveal_timeout, block_number, ) # We check if the secret is already known by receiving a ReceiveSecretReveal state change secret_known = channel.is_secret_known( payer_channel.partner_state, pair.payer_transfer.lock.secrethash, ) if not safe_to_wait and secret_known: secret = channel.get_secret( payer_channel.partner_state, pair.payer_transfer.lock.secrethash, ) reveal_events = secret_registry.events_for_onchain_secretreveal( payer_channel, block_number, secret, ) events.extend(reveal_events) return events
def events_for_onchain_secretreveal( target_state: TargetTransferState, channel_state: NettingChannelState, block_number: BlockNumber, ): """ Emits the event for revealing the secret on-chain if the transfer can not be settled off-chain. """ transfer = target_state.transfer expiration = transfer.lock.expiration safe_to_wait, _ = is_safe_to_wait( expiration, channel_state.reveal_timeout, block_number, ) secret_known_offchain = channel.is_secret_known_offchain( channel_state.partner_state, transfer.lock.secrethash, ) has_onchain_reveal_started = ( target_state.state == TargetTransferState.ONCHAIN_SECRET_REVEAL ) if not safe_to_wait and secret_known_offchain and not has_onchain_reveal_started: target_state.state = TargetTransferState.ONCHAIN_SECRET_REVEAL secret = channel.get_secret( channel_state.partner_state, transfer.lock.secrethash, ) return secret_registry.events_for_onchain_secretreveal( channel_state, secret, expiration, ) return list()
def events_for_onchain_secretreveal_if_dangerzone( channelmap: typing.ChannelMap, secrethash: typing.SecretHash, transfers_pair: typing.List[MediationPairState], block_number: typing.BlockNumber, ) -> typing.List[Event]: """ Reveal the secret on-chain if the lock enters the unsafe region and the secret is not yet on-chain. """ events = list() all_payer_channels = [ get_payer_channel(channelmap, pair) for pair in transfers_pair ] transaction_sent = has_secret_registration_started( all_payer_channels, transfers_pair, secrethash, ) # Only consider the transfers which have a pair. This means if we have a # waiting transfer and for some reason the node knows the secret, it will # not try to register it. Otherwise it would be possible for an attacker to # reveal the secret late, just to force the node to send an unecessary # transaction. for pair in get_pending_transfer_pairs(transfers_pair): payer_channel = get_payer_channel(channelmap, pair) lock = pair.payer_transfer.lock safe_to_wait, _ = is_safe_to_wait( lock.expiration, payer_channel.reveal_timeout, block_number, ) secret_known = channel.is_secret_known( payer_channel.partner_state, pair.payer_transfer.lock.secrethash, ) if not safe_to_wait and secret_known: pair.payer_state = 'payer_waiting_secret_reveal' if not transaction_sent: secret = channel.get_secret( payer_channel.partner_state, lock.secrethash, ) reveal_events = secret_registry.events_for_onchain_secretreveal( payer_channel, secret, lock.expiration, ) events.extend(reveal_events) transaction_sent = True return events