Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
143 changes: 136 additions & 7 deletions rust-src/concordium_base/src/random_oracle/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,7 @@

use crate::{common::*, curve_arithmetic::Curve};
use sha3::{Digest, Sha3_256};

use std::convert::Infallible;
use std::fmt::Arguments;
use std::io::{IoSlice, Write};
Expand All @@ -220,7 +221,7 @@ pub struct RandomOracle(Sha3_256);
/// [Transcript protocol](TranscriptProtocol) implementation V1. See [`random_oracle`](self)
/// and [`TranscriptProtocol`] for how to use it.
#[repr(transparent)]
#[derive(Debug)]
#[derive(Debug, Clone)]
pub struct TranscriptProtocolV1(Sha3_256);

/// Type of challenges computed from the random oracle.
Expand Down Expand Up @@ -557,11 +558,139 @@ impl TranscriptProtocolV1 {
transcript.append_label(domain);
transcript
}
}

/// Duplicate the transcript, creating a new copy of it.
/// Further updates are independent.
pub fn split(&self) -> Self {
TranscriptProtocolV1(self.0.clone())

#[cfg(test)]
const LABEL_WIDTH: usize = 35;
const MSG_SIZE_WIDTH: usize = 5;
#[cfg(test)]
#[derive(Debug, Clone)]
pub struct TranscriptProtocolTracer<P> {
pub inner: P,
pub lines: std::cell::RefCell<Vec<String>>,
}

#[cfg(test)]
impl<P> TranscriptProtocolTracer<P> {
pub fn new(inner: P) -> Self {
let lines = std::cell::RefCell::new(vec![]);
//lines.borrow_mut().push(format!("=== {:^LABEL_WIDTH$} ===", "Proof Transcript"));
Self {
inner,
lines,
}
}
}

#[cfg(test)]
impl<P> Drop for TranscriptProtocolTracer<P> {
fn drop(&mut self) {
for line in self.lines.borrow().iter() {
println!("{}", line);
}
}
}

#[cfg(test)]
impl<P: TranscriptProtocol> TranscriptProtocol for TranscriptProtocolTracer<P> {

fn append_label(&mut self, label: impl AsRef<[u8]>) {
self.inner.append_label(label.as_ref());
self.lines
.borrow_mut()
.push(format!(
"-l-> {:<LABEL_WIDTH$}",
String::from_utf8_lossy(label.as_ref()).into_owned()
));
}

fn append_message(&mut self, label: impl AsRef<[u8]>, message: &impl Serial) {
self.inner.append_message(label.as_ref(), message);
self.lines.borrow_mut().push(format!(
"-m-> {:<LABEL_WIDTH$} {:>MSG_SIZE_WIDTH$} bytes",
String::from_utf8_lossy(label.as_ref()).into_owned(),
to_bytes(message).len()
));
}

fn append_messages<'a, T: Serial + 'a, B: IntoIterator<Item = &'a T>>(
&mut self,
label: impl AsRef<[u8]>,
messages: B,
) where
B::IntoIter: ExactSizeIterator,
{
let messages: Vec<_> = messages.into_iter().collect();
self.inner.append_messages(label.as_ref(), &messages);
self.lines.borrow_mut().push(format!(
"-m-> {:<LABEL_WIDTH$} {:>MSG_SIZE_WIDTH$} items {:>MSG_SIZE_WIDTH$} bytes total (append messages)",
String::from_utf8_lossy(label.as_ref()).into_owned(),
messages.len(),
messages
.iter()
.map(|msg| to_bytes(msg).len())
.sum::<usize>()
));
}

fn append_final_prover_message(&mut self, label: impl AsRef<[u8]>, message: &impl Serial) {
self.inner
.append_final_prover_message(label.as_ref(), message);
self.lines.borrow_mut().push(format!(
"-m-> {:<LABEL_WIDTH$} {:>MSG_SIZE_WIDTH$} bytes (final prover message)",
String::from_utf8_lossy(label.as_ref()).into_owned(),
to_bytes(message).len()
));
}

fn append_each_message<T, B: IntoIterator<Item = T>>(
&mut self,
label: impl AsRef<[u8]>,
messages: B,
mut append_item: impl FnMut(&mut Self, T),
) where
B::IntoIter: ExactSizeIterator,
{
let messages: Vec<_> = messages.into_iter().collect();
self.lines.borrow_mut().push(format!(" {:<LABEL_WIDTH$}","--- start append each message ---"));
self.lines.borrow_mut().push(format!(
"-m-> {:<LABEL_WIDTH$} {:>MSG_SIZE_WIDTH$} items",
String::from_utf8_lossy(label.as_ref()).into_owned(),
messages.len(),
));
let mut lines = Vec::new();
self.inner
.append_each_message(label, messages, |inner, item| unsafe {
lines.push(format!(" {:<LABEL_WIDTH$}","- start message -"));
let mut tracer =
TranscriptProtocolTracer::new(std::mem::MaybeUninit::uninit().assume_init());
std::mem::swap(inner, &mut tracer.inner);
append_item(&mut tracer, item);
std::mem::swap(inner, &mut tracer.inner);
lines.extend(tracer.lines.take());
lines.push(format!(" {:<LABEL_WIDTH$}","- end message -"));
});
self.lines.borrow_mut().extend(lines);
self.lines.borrow_mut().push(format!(" {:<LABEL_WIDTH$}","--- end append each message ---"));
}

fn extract_challenge_scalar<C: Curve>(&mut self, label: impl AsRef<[u8]>) -> C::Scalar {
let val = self.inner.extract_challenge_scalar::<C>(label.as_ref());
self.lines.borrow_mut().push(format!(
"<-c- {:<LABEL_WIDTH$} {:>MSG_SIZE_WIDTH$} (extract scalar challenge)",
String::from_utf8_lossy(label.as_ref()).into_owned(),
""
));
val
}

fn extract_raw_challenge(&self) -> Challenge {
let val = self.inner.extract_raw_challenge();
self.lines
.borrow_mut()
.push(format!("<-c- {:<LABEL_WIDTH$} {:>MSG_SIZE_WIDTH$} (extract raw challenge)","",""));
val
}
}

Expand Down Expand Up @@ -821,10 +950,10 @@ mod tests {
/// by [`<TranscriptProtocolV1 as TranscriptProtocol>::extract_challenge_scalar`]
#[test]
pub fn test_v1_extract_challenge_scalar_stable() {
let ro = TranscriptProtocolV1::with_domain("Domain1");
let mut ro = TranscriptProtocolV1::with_domain("Domain1");

let scalar_hex = hex::encode(common::to_bytes(
&ro.split().extract_challenge_scalar::<ArCurve>("Scalar1"),
&ro.extract_challenge_scalar::<ArCurve>("Scalar1"),
));
assert_eq!(
scalar_hex,
Expand Down
73 changes: 69 additions & 4 deletions rust-src/concordium_base/src/web3id/v1/proofs.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use crate::random_oracle::{TranscriptProtocol, TranscriptProtocolV1};
use crate::{
curve_arithmetic::Curve,
id::types::{Attribute, GlobalContext},
Expand All @@ -16,7 +17,6 @@ use crate::id::types::{
IdentityAttributesCredentialsInfo, IdentityAttributesCredentialsValues, IpContextOnly,
};
use crate::pedersen_commitment::Commitment;
use crate::random_oracle::{TranscriptProtocol, TranscriptProtocolV1};
use crate::web3id::v1::{
AccountBasedCredentialV1, AccountBasedSubjectClaims, AccountCredentialProofPrivateInputs,
AccountCredentialProofs, AccountCredentialSubject, AccountCredentialVerificationMaterial,
Expand Down Expand Up @@ -72,12 +72,13 @@ impl<P: Pairing, C: Curve<Scalar = P::ScalarField>, AttributeType: Attribute<C::
.enumerate()
{
// The proof for each credential is independent, so make a copy of the transcript so far
let mut transcript = transcript.split();
let mut transcript = transcript.clone();

transcript.append_message("ProofVersion", &credential.proof_version());
transcript.append_message("CreationTime", &credential.created());

let claims = credential.claims();

request.subject_claims.push(claims);

if !credential.verify(global_context, &mut transcript, verification_material) {
Expand Down Expand Up @@ -524,11 +525,27 @@ impl<C: Curve, AttributeType: Attribute<C::Scalar>> RequestV1<C, AttributeType>
csprng: &mut (impl Rng + CryptoRng),
now: chrono::DateTime<chrono::Utc>,
) -> Result<PresentationV1<P, C, AttributeType>, ProveError>
where
AttributeType: 'a,
{
let transcript = TranscriptProtocolV1::with_domain("ConcordiumVerifiableCredentialV1");
self.prove_with_transcript(global_context, private_inputs, csprng, now, transcript)
}

pub fn prove_with_transcript<'a, P: Pairing<ScalarField = C::Scalar>>(
self,
global_context: &GlobalContext<C>,
private_inputs: impl ExactSizeIterator<
Item = CredentialProofPrivateInputs<'a, P, C, AttributeType>,
>,
csprng: &mut (impl Rng + CryptoRng),
now: chrono::DateTime<chrono::Utc>,
mut transcript: impl TranscriptProtocol + Clone,
) -> Result<PresentationV1<P, C, AttributeType>, ProveError>
where
AttributeType: 'a,
{
let mut verifiable_credentials = Vec::with_capacity(private_inputs.len());
let mut transcript = TranscriptProtocolV1::with_domain("ConcordiumVerifiableCredentialV1");
append_context(&mut transcript, &self.context);
transcript.append_message("GlobalContext", &global_context);

Expand All @@ -538,7 +555,7 @@ impl<C: Curve, AttributeType: Attribute<C::Scalar>> RequestV1<C, AttributeType>
for (subject_claims, private_inputs) in self.subject_claims.into_iter().zip(private_inputs)
{
// The proof for each credential is independent, so make a copy of the transcript so far
let mut transcript = transcript.split();
let mut transcript = transcript.clone();

transcript.append_message(
"ProofVersion",
Expand Down Expand Up @@ -702,6 +719,7 @@ pub mod tests {
use crate::id::constants::{ArCurve, AttributeKind, IpPairing};
use crate::id::id_proof_types::{AttributeInRangeStatement, AttributeValueStatement};
use crate::id::types::{AttributeTag, IpIdentity};
use crate::random_oracle::TranscriptProtocolTracer;
use crate::web3id::did::Network;
use crate::web3id::v1::{fixtures, ContextProperty};
use crate::web3id::Web3IdAttribute;
Expand Down Expand Up @@ -1794,4 +1812,51 @@ pub mod tests {
.verify(&global_context, public.iter())
.expect("verify");
}

/// Test prove and verify presentation for identity credentials.
#[test]
fn test_transcript_trace_identity() {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Trace:

ConcordiumContextInformationV1
given, 33 bytes
requested, 33 bytes
GlobalContext, 24684 bytes
ProofVersion, 1 bytes
CreationTime, 8 bytes
ConcordiumIdBasedCredential
Issuer, 4 bytes
Statements, 105 bytes
Network, 1 bytes
IdentityAttributesCredentials
IdentityAttributeValues, 730 bytes
GlobalContext, 24684 bytes
PsSigKnown
blinded_sig, 96 bytes
messages, 388 bytes
ps_pub_key, 3128 bytes
comm_key, 96 bytes
, 5 messages
cipher, 96 bytes
commitment, 48 bytes
pub_key, 96 bytes
cmm_key, 96 bytes
cipher, 96 bytes
commitment, 48 bytes
pub_key, 96 bytes
cmm_key, 96 bytes
cipher, 96 bytes
commitment, 48 bytes
pub_key, 96 bytes
cmm_key, 96 bytes
cipher, 96 bytes
commitment, 48 bytes
pub_key, 96 bytes
cmm_key, 96 bytes
cipher, 96 bytes
commitment, 48 bytes
pub_key, 96 bytes
cmm_key, 96 bytes
point, 1548 bytes
<extract raw challenge>
response, final prover message, 948 bytes
ValidFrom, 3 bytes
ValidTo, 3 bytes
EncryptedIdentityCredentialId, 511 bytes
SetMembershipProof
G, 200 bytes
H, 200 bytes
v_keys, 96 bytes
V, 48 bytes
theSet, 136 bytes
A, 48 bytes
S, 48 bytes
y, extract scalar challenge
z, extract scalar challenge
T1, 48 bytes
T2, 48 bytes
x, extract scalar challenge
tx, 32 bytes
tx_tilde, 32 bytes
e_tilde, 32 bytes
w, extract scalar challenge
Lj, 48 bytes
Rj, 48 bytes
uj, extract scalar challenge
Lj, 48 bytes
Rj, 48 bytes
uj, extract scalar challenge
a, final prover message, 32 bytes
b, final prover message, 32 bytes
SetNonMembershipProof
G, 200 bytes
H, 200 bytes
v_keys, 96 bytes
V, 48 bytes
theSet, 136 bytes
A, 48 bytes
S, 48 bytes
y, extract scalar challenge
z, extract scalar challenge
T1, 48 bytes
T2, 48 bytes
x, extract scalar challenge
tx, 32 bytes
tx_tilde, 32 bytes
e_tilde, 32 bytes
w, extract scalar challenge
Lj, 48 bytes
Rj, 48 bytes
uj, extract scalar challenge
Lj, 48 bytes
Rj, 48 bytes
uj, extract scalar challenge
a, final prover message, 32 bytes
b, final prover message, 32 bytes
AttributeRangeProof
a, 32 bytes
b, 32 bytes
G, 6152 bytes
H, 6152 bytes
v_keys, 96 bytes
n, 1 bytes
Vj, 48 bytes
Vj, 48 bytes
A, 48 bytes
S, 48 bytes
y, extract scalar challenge
z, extract scalar challenge
T1, 48 bytes
T2, 48 bytes
x, extract scalar challenge
tx, 32 bytes
tx_tilde, 32 bytes
e_tilde, 32 bytes
w, extract scalar challenge
Lj, 48 bytes
Rj, 48 bytes
uj, extract scalar challenge
Lj, 48 bytes
Rj, 48 bytes
uj, extract scalar challenge
Lj, 48 bytes
Rj, 48 bytes
uj, extract scalar challenge
Lj, 48 bytes
Rj, 48 bytes
uj, extract scalar challenge
Lj, 48 bytes
Rj, 48 bytes
uj, extract scalar challenge
Lj, 48 bytes
Rj, 48 bytes
uj, extract scalar challenge
Lj, 48 bytes
Rj, 48 bytes
uj, extract scalar challenge
a, final prover message, 32 bytes
b, final prover message, 32 bytes
AttributeRangeProof
a, 32 bytes
b, 32 bytes
G, 6152 bytes
H, 6152 bytes
v_keys, 96 bytes
n, 1 bytes
Vj, 48 bytes
Vj, 48 bytes
A, 48 bytes
S, 48 bytes
y, extract scalar challenge
z, extract scalar challenge
T1, 48 bytes
T2, 48 bytes
x, extract scalar challenge
tx, 32 bytes
tx_tilde, 32 bytes
e_tilde, 32 bytes
w, extract scalar challenge
Lj, 48 bytes
Rj, 48 bytes
uj, extract scalar challenge
Lj, 48 bytes
Rj, 48 bytes
uj, extract scalar challenge
Lj, 48 bytes
Rj, 48 bytes
uj, extract scalar challenge
Lj, 48 bytes
Rj, 48 bytes
uj, extract scalar challenge
Lj, 48 bytes
Rj, 48 bytes
uj, extract scalar challenge
Lj, 48 bytes
Rj, 48 bytes
uj, extract scalar challenge
Lj, 48 bytes
Rj, 48 bytes
uj, extract scalar challenge
a, final prover message, 32 bytes
b, final prover message, 32 bytes
RevealedAttribute, 11 bytes

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated by @tschudid :

-l-> ConcordiumContextInformationV1     
-m-> given                                  33 bytes
-m-> requested                              33 bytes
-m-> GlobalContext                       24684 bytes
-m-> ProofVersion                            1 bytes
-m-> CreationTime                            8 bytes
-l-> ConcordiumIdBasedCredential        
-m-> Issuer                                  4 bytes
-m-> Statements                            105 bytes
-m-> Network                                 1 bytes
-l-> IdentityAttributesCredentials      
-m-> IdentityAttributeValues               730 bytes
-m-> GlobalContext                       24684 bytes
-l-> PsSigKnown                         
-m-> blinded_sig                            96 bytes
-m-> messages                              388 bytes
-m-> ps_pub_key                           3128 bytes
-m-> comm_key                               96 bytes
     --- start append each message ---  
-m->                                         5 items
     - start message -                  
-m-> cipher                                 96 bytes
-m-> commitment                             48 bytes
-m-> pub_key                                96 bytes
-m-> cmm_key                                96 bytes
     - end message -                    
     - start message -                  
-m-> cipher                                 96 bytes
-m-> commitment                             48 bytes
-m-> pub_key                                96 bytes
-m-> cmm_key                                96 bytes
     - end message -                    
     - start message -                  
-m-> cipher                                 96 bytes
-m-> commitment                             48 bytes
-m-> pub_key                                96 bytes
-m-> cmm_key                                96 bytes
     - end message -                    
     - start message -                  
-m-> cipher                                 96 bytes
-m-> commitment                             48 bytes
-m-> pub_key                                96 bytes
-m-> cmm_key                                96 bytes
     - end message -                    
     - start message -                  
-m-> cipher                                 96 bytes
-m-> commitment                             48 bytes
-m-> pub_key                                96 bytes
-m-> cmm_key                                96 bytes
     - end message -                    
     --- end append each message ---    
-m-> point                                1548 bytes
<-c-                                                 (extract raw challenge)
-m-> response                              948 bytes (final prover message)
-m-> ValidFrom                               3 bytes
-m-> ValidTo                                 3 bytes
-m-> EncryptedIdentityCredentialId         511 bytes
-l-> SetMembershipProof                 
-m-> G                                     200 bytes
-m-> H                                     200 bytes
-m-> v_keys                                 96 bytes
-m-> V                                      48 bytes
-m-> theSet                                136 bytes
-m-> A                                      48 bytes
-m-> S                                      48 bytes
<-c- y                                               (extract scalar challenge)
<-c- z                                               (extract scalar challenge)
-m-> T1                                     48 bytes
-m-> T2                                     48 bytes
<-c- x                                               (extract scalar challenge)
-m-> tx                                     32 bytes
-m-> tx_tilde                               32 bytes
-m-> e_tilde                                32 bytes
<-c- w                                               (extract scalar challenge)
-m-> Lj                                     48 bytes
-m-> Rj                                     48 bytes
<-c- uj                                              (extract scalar challenge)
-m-> Lj                                     48 bytes
-m-> Rj                                     48 bytes
<-c- uj                                              (extract scalar challenge)
-m-> a                                      32 bytes (final prover message)
-m-> b                                      32 bytes (final prover message)
-l-> SetNonMembershipProof              
-m-> G                                     200 bytes
-m-> H                                     200 bytes
-m-> v_keys                                 96 bytes
-m-> V                                      48 bytes
-m-> theSet                                136 bytes
-m-> A                                      48 bytes
-m-> S                                      48 bytes
<-c- y                                               (extract scalar challenge)
<-c- z                                               (extract scalar challenge)
-m-> T1                                     48 bytes
-m-> T2                                     48 bytes
<-c- x                                               (extract scalar challenge)
-m-> tx                                     32 bytes
-m-> tx_tilde                               32 bytes
-m-> e_tilde                                32 bytes
<-c- w                                               (extract scalar challenge)
-m-> Lj                                     48 bytes
-m-> Rj                                     48 bytes
<-c- uj                                              (extract scalar challenge)
-m-> Lj                                     48 bytes
-m-> Rj                                     48 bytes
<-c- uj                                              (extract scalar challenge)
-m-> a                                      32 bytes (final prover message)
-m-> b                                      32 bytes (final prover message)
-l-> AttributeRangeProof                
-m-> a                                      32 bytes
-m-> b                                      32 bytes
-m-> G                                    6152 bytes
-m-> H                                    6152 bytes
-m-> v_keys                                 96 bytes
-m-> n                                       1 bytes
-m-> Vj                                     48 bytes
-m-> Vj                                     48 bytes
-m-> A                                      48 bytes
-m-> S                                      48 bytes
<-c- y                                               (extract scalar challenge)
<-c- z                                               (extract scalar challenge)
-m-> T1                                     48 bytes
-m-> T2                                     48 bytes
<-c- x                                               (extract scalar challenge)
-m-> tx                                     32 bytes
-m-> tx_tilde                               32 bytes
-m-> e_tilde                                32 bytes
<-c- w                                               (extract scalar challenge)
-m-> Lj                                     48 bytes
-m-> Rj                                     48 bytes
<-c- uj                                              (extract scalar challenge)
-m-> Lj                                     48 bytes
-m-> Rj                                     48 bytes
<-c- uj                                              (extract scalar challenge)
-m-> Lj                                     48 bytes
-m-> Rj                                     48 bytes
<-c- uj                                              (extract scalar challenge)
-m-> Lj                                     48 bytes
-m-> Rj                                     48 bytes
<-c- uj                                              (extract scalar challenge)
-m-> Lj                                     48 bytes
-m-> Rj                                     48 bytes
<-c- uj                                              (extract scalar challenge)
-m-> Lj                                     48 bytes
-m-> Rj                                     48 bytes
<-c- uj                                              (extract scalar challenge)
-m-> Lj                                     48 bytes
-m-> Rj                                     48 bytes
<-c- uj                                              (extract scalar challenge)
-m-> a                                      32 bytes (final prover message)
-m-> b                                      32 bytes (final prover message)
-l-> AttributeRangeProof                
-m-> a                                      32 bytes
-m-> b                                      32 bytes
-m-> G                                    6152 bytes
-m-> H                                    6152 bytes
-m-> v_keys                                 96 bytes
-m-> n                                       1 bytes
-m-> Vj                                     48 bytes
-m-> Vj                                     48 bytes
-m-> A                                      48 bytes
-m-> S                                      48 bytes
<-c- y                                               (extract scalar challenge)
<-c- z                                               (extract scalar challenge)
-m-> T1                                     48 bytes
-m-> T2                                     48 bytes
<-c- x                                               (extract scalar challenge)
-m-> tx                                     32 bytes
-m-> tx_tilde                               32 bytes
-m-> e_tilde                                32 bytes
<-c- w                                               (extract scalar challenge)
-m-> Lj                                     48 bytes
-m-> Rj                                     48 bytes
<-c- uj                                              (extract scalar challenge)
-m-> Lj                                     48 bytes
-m-> Rj                                     48 bytes
<-c- uj                                              (extract scalar challenge)
-m-> Lj                                     48 bytes
-m-> Rj                                     48 bytes
<-c- uj                                              (extract scalar challenge)
-m-> Lj                                     48 bytes
-m-> Rj                                     48 bytes
<-c- uj                                              (extract scalar challenge)
-m-> Lj                                     48 bytes
-m-> Rj                                     48 bytes
<-c- uj                                              (extract scalar challenge)
-m-> Lj                                     48 bytes
-m-> Rj                                     48 bytes
<-c- uj                                              (extract scalar challenge)
-m-> Lj                                     48 bytes
-m-> Rj                                     48 bytes
<-c- uj                                              (extract scalar challenge)
-m-> a                                      32 bytes (final prover message)
-m-> b                                      32 bytes (final prover message)
-m-> RevealedAttribute                      11 bytes

let challenge = challenge_fixture();

let global_context = GlobalContext::generate("Test".into());

let (statements, attributes) = fixtures::statements_and_attributes();

let id_cred_fixture = fixtures::identity_credentials_fixture(attributes, &global_context);

let subject_claims = vec![SubjectClaims::Identity(IdentityBasedSubjectClaims {
network: Network::Testnet,
issuer: id_cred_fixture.issuer,
statements,
})];

let request = RequestV1::<ArCurve, Web3IdAttribute> {
context: challenge,
subject_claims,
};

let transcript = TranscriptProtocolTracer::new(TranscriptProtocolV1::with_domain(
"ConcordiumVerifiableCredentialV1",
));

let proof = request
.clone()
.prove_with_transcript(
&global_context,
[id_cred_fixture.private_inputs()].into_iter(),
&mut rand::thread_rng(),
chrono::Utc::now(),
transcript,
)
.expect("prove");

let public = vec![id_cred_fixture.verification_material];
assert_eq!(
proof
.verify(&global_context, public.iter())
.expect("verify"),
request,
"verify request"
);
}
}