pub(crate) fn compute_challenge(&mut self, challenge_id: &str) -> Result<Vec<u8>, PlonkError> {
        let challenge =
            self.challenges.get_mut(challenge_id).ok_or(PlonkError::ChallengeNotFound)?;

        if challenge.is_computed {
            return Ok(challenge.value.clone());
        }

        // Reset the hash function before and after computing the challenge
        self.h.reset();

        self.h.update(challenge_id.as_bytes());

        if challenge.position != 0 {
            if let Some(previous_challenge) = &self.previous_challenge {
                if previous_challenge.position != challenge.position - 1 {
                    return Err(PlonkError::PreviousChallengeNotComputed);
                }
                self.h.update(&previous_challenge.value)
            } else {
                return Err(PlonkError::PreviousChallengeNotComputed);
            }
        }

        for binding in challenge.bindings.iter() {
            self.h.update(binding)
        }

        let res = self.h.finalize_reset();

        challenge.value = res.to_vec();
        challenge.is_computed = true;

        // Update the previous challenge reference
        self.previous_challenge = Some(challenge.clone());

        Ok(res.to_vec())
    }
Computes a challenge and returns its value.

Challenges must be computed in order. The previous challenge is automatically fed into the
challenge currently being computed.
crates/verifier/src/plonk/transcript.rs