def handle_onchain_secretreveal(
        initiator_state: InitiatorTransferState,
        state_change: ContractReceiveSecretReveal,
        channel_state: NettingChannelState,
        pseudo_random_generator: random.Random,
) -> TransitionResult[InitiatorTransferState]:
    """ When a secret is revealed on-chain all nodes learn the secret.

    This check the on-chain secret corresponds to the one used by the
    initiator, and if valid a new balance proof is sent to the next hop with
    the current lock removed from the merkle tree and the transferred amount
    updated.
    """
    iteration: TransitionResult[InitiatorTransferState]
    secret = state_change.secret
    secrethash = initiator_state.transfer_description.secrethash
    is_valid_secret = is_valid_secret_reveal(
        state_change=state_change,
        transfer_secrethash=secrethash,
        secret=secret,
    )
    is_channel_open = channel.get_status(channel_state) == CHANNEL_STATE_OPENED
    is_lock_expired = state_change.block_number > initiator_state.transfer.lock.expiration

    is_lock_unlocked = (
        is_valid_secret and
        not is_lock_expired
    )

    if is_lock_unlocked:
        channel.register_onchain_secret(
            channel_state=channel_state,
            secret=secret,
            secrethash=secrethash,
            secret_reveal_block_number=state_change.block_number,
        )

    if is_lock_unlocked and is_channel_open:
        events = events_for_unlock_lock(
            initiator_state,
            channel_state,
            state_change.secret,
            state_change.secrethash,
            pseudo_random_generator,
        )
        iteration = TransitionResult(None, events)
    else:
        events = list()
        iteration = TransitionResult(initiator_state, events)

    return iteration