From 88a3e63f4ea3ed36a46b46dcf3b2e2b149c76700 Mon Sep 17 00:00:00 2001 From: Allan Rasmussen Date: Tue, 25 Nov 2025 10:24:24 +0100 Subject: [PATCH 01/20] transcript protocol --- rust-src/concordium_base/src/base.rs | 2 +- .../src/bulletproofs/inner_product_proof.rs | 26 +- .../src/bulletproofs/range_proof.rs | 45 +- .../src/bulletproofs/set_membership_proof.rs | 28 +- .../bulletproofs/set_non_membership_proof.rs | 28 +- .../src/eddsa_ed25519/dlog_ed25519.rs | 2 +- .../concordium_base/src/id/account_holder.rs | 2 +- rust-src/concordium_base/src/id/chain.rs | 2 +- rust-src/concordium_base/src/id/id_prover.rs | 23 +- .../concordium_base/src/id/id_verifier.rs | 23 +- .../src/id/identity_attributes_credentials.rs | 22 +- .../src/id/identity_provider.rs | 2 +- .../concordium_base/src/random_oracle/mod.rs | 539 +++++++++++++++--- .../src/sigma_protocols/aggregate_dlog.rs | 10 +- .../src/sigma_protocols/com_enc_eq.rs | 6 +- .../src/sigma_protocols/com_eq.rs | 6 +- .../com_eq_different_groups.rs | 6 +- .../src/sigma_protocols/com_eq_sig.rs | 9 +- .../src/sigma_protocols/com_ineq.rs | 2 +- .../src/sigma_protocols/com_lin.rs | 13 +- .../src/sigma_protocols/com_mult.rs | 10 +- .../src/sigma_protocols/common.rs | 18 +- .../src/sigma_protocols/dlog.rs | 7 +- .../src/sigma_protocols/dlogaggequal.rs | 8 +- .../src/sigma_protocols/dlogeq.rs | 6 +- .../src/sigma_protocols/enc_trans.rs | 16 +- .../src/sigma_protocols/ps_sig_known.rs | 8 +- .../src/sigma_protocols/vcom_eq.rs | 10 +- rust-src/concordium_base/src/web3id/proofs.rs | 2 +- .../concordium_base/src/web3id/v1/proofs.rs | 6 +- 30 files changed, 627 insertions(+), 260 deletions(-) diff --git a/rust-src/concordium_base/src/base.rs b/rust-src/concordium_base/src/base.rs index a8700f09c..b81641ce3 100644 --- a/rust-src/concordium_base/src/base.rs +++ b/rust-src/concordium_base/src/base.rs @@ -1,5 +1,6 @@ //! Basis type definitions that are used throughout the crate. +use crate::random_oracle::RandomOracle; use crate::{ common::{ base16_decode_string, deserial_string, types::Signature, Buffer, Deserial, Get, @@ -12,7 +13,6 @@ use crate::{ types::{GlobalContext, VerifyKey}, }, pedersen_commitment::{Randomness, Value}, - random_oracle::RandomOracle, }; use concordium_contracts_common::AccountAddress; pub use concordium_contracts_common::{ diff --git a/rust-src/concordium_base/src/bulletproofs/inner_product_proof.rs b/rust-src/concordium_base/src/bulletproofs/inner_product_proof.rs index 14e4eafd6..28d6e21c1 100644 --- a/rust-src/concordium_base/src/bulletproofs/inner_product_proof.rs +++ b/rust-src/concordium_base/src/bulletproofs/inner_product_proof.rs @@ -1,10 +1,9 @@ //! Logarithmic sized inner product proof used as base for the other proofs in //! this crate -use crate::random_oracle::StructuredDigest; +use crate::random_oracle::TranscriptProtocol; use crate::{ common::*, curve_arithmetic::{multiexp, Curve, Field}, - random_oracle::RandomOracle, }; /// Inner product proof @@ -35,7 +34,7 @@ pub struct InnerProductProof { /// this length must be a power of 2. #[allow(non_snake_case)] pub fn prove_inner_product( - transcript: &mut RandomOracle, + transcript: &mut impl TranscriptProtocol, G_slice: &[C], H_slice: &[C], Q: &C, @@ -68,7 +67,7 @@ pub fn prove_inner_product( /// this length must be a power of 2. #[allow(non_snake_case)] pub fn prove_inner_product_with_scalars( - transcript: &mut RandomOracle, + transcript: &mut impl TranscriptProtocol, G_slice: &[C], H_slice: &[C], H_prime_scalars: &[C::Scalar], @@ -137,7 +136,7 @@ pub fn prove_inner_product_with_scalars( transcript.append_message(b"Lj", &Lj); transcript.append_message(b"Rj", &Rj); L_R.push((Lj, Rj)); - let u_j: C::Scalar = transcript.challenge_scalar::(b"uj"); + let u_j: C::Scalar = transcript.extract_challenge_scalar::(b"uj"); // println!("Prover's u_{:?} = {:?}", j, u_j); let u_j_inv = match u_j.inverse() { Some(inv) => inv, @@ -202,6 +201,9 @@ pub fn prove_inner_product_with_scalars( let a = a_vec[0]; let b = b_vec[0]; + transcript.append_final_prover_message(b"a", &a); + transcript.append_final_prover_message(b"b", &b); + Some(InnerProductProof { lr_vec: L_R, a, b }) } @@ -224,7 +226,7 @@ pub struct VerificationScalars { #[allow(non_snake_case)] #[allow(clippy::many_single_char_names)] pub fn verify_scalars( - transcript: &mut RandomOracle, + transcript: &mut impl TranscriptProtocol, n: usize, proof: &InnerProductProof, ) -> Option> { @@ -242,7 +244,7 @@ pub fn verify_scalars( for (Lj, Rj) in L_R { transcript.append_message(b"Lj", Lj); transcript.append_message(b"Rj", Rj); - let u_j: C::Scalar = transcript.challenge_scalar::(b"uj"); + let u_j: C::Scalar = transcript.extract_challenge_scalar::(b"uj"); let u_j_inv = match u_j.inverse() { Some(inv) => inv, _ => return None, @@ -274,6 +276,10 @@ pub fn verify_scalars( s_i.mul_assign(&u_sq[L_R.len() - 1 - lg_i]); s.push(s_i); } + + transcript.append_final_prover_message(b"a", &a); + transcript.append_final_prover_message(b"b", &b); + Some(VerificationScalars { u_sq, u_inv_sq, s }) } @@ -293,7 +299,7 @@ pub fn verify_scalars( /// of 2. #[allow(non_snake_case)] pub fn verify_inner_product( - transcript: &mut RandomOracle, + transcript: &mut impl TranscriptProtocol, G_vec: &[C], H_vec: &[C], P_prime: &C, @@ -347,7 +353,7 @@ pub fn verify_inner_product( /// `P_prime_bases` #[allow(non_snake_case)] pub(crate) fn verify_inner_product_with_scalars( - transcript: &mut RandomOracle, + transcript: &mut impl TranscriptProtocol, H_exponents: &[C::Scalar], P_prime_bases: &[C], P_prime_exponents: &[C::Scalar], @@ -464,8 +470,10 @@ mod tests { use crate::curve_arithmetic::arkworks_instances::ArkGroup; use super::*; + use crate::random_oracle::RandomOracle; use ark_bls12_381::G1Projective; use rand::thread_rng; + type SomeCurve = ArkGroup; #[test] diff --git a/rust-src/concordium_base/src/bulletproofs/range_proof.rs b/rust-src/concordium_base/src/bulletproofs/range_proof.rs index b7ff68fd7..7a45f5470 100644 --- a/rust-src/concordium_base/src/bulletproofs/range_proof.rs +++ b/rust-src/concordium_base/src/bulletproofs/range_proof.rs @@ -1,13 +1,12 @@ //! Implementation of range proofs along the lines of bulletproofs pub use super::utils::Generators; use super::{inner_product_proof::*, utils::*}; -use crate::random_oracle::StructuredDigest; +use crate::random_oracle::TranscriptProtocol; use crate::{ common::*, curve_arithmetic::{multiexp, Curve, Field, MultiExp, PrimeField, Value}, id::id_proof_types::ProofVersion, pedersen_commitment::*, - random_oracle::RandomOracle, }; use rand::*; use std::iter::once; @@ -81,7 +80,7 @@ fn two_n_vec(n: u8) -> Vec { #[allow(clippy::too_many_arguments)] pub fn prove_given_scalars( version: ProofVersion, - transcript: &mut RandomOracle, + transcript: &mut impl TranscriptProtocol, csprng: &mut T, n: u8, m: u8, @@ -125,7 +124,7 @@ pub fn prove_given_scalars( #[allow(clippy::too_many_arguments)] pub fn prove( version: ProofVersion, - transcript: &mut RandomOracle, + transcript: &mut impl TranscriptProtocol, csprng: &mut T, n: u8, m: u8, @@ -236,8 +235,8 @@ pub fn prove( // Part 2: Computation of vector polynomials l(x),r(x) // get challenges y,z from transcript - let y: C::Scalar = transcript.challenge_scalar::(b"y"); - let z: C::Scalar = transcript.challenge_scalar::(b"z"); + let y: C::Scalar = transcript.extract_challenge_scalar::(b"y"); + let z: C::Scalar = transcript.extract_challenge_scalar::(b"z"); // y_nm = (1,y,..,y^(nm-1)) let y_nm = z_vec(y, 0, nm); @@ -353,7 +352,7 @@ pub fn prove( // Part 4: Evaluate l(x), r(x), and t(x) at challenge point x // get challenge x from transcript - let x: C::Scalar = transcript.challenge_scalar::(b"x"); + let x: C::Scalar = transcript.extract_challenge_scalar::(b"x"); // println!("prover's x = {:?}", x); let mut x2 = x; x2.mul_assign(&x); @@ -418,7 +417,7 @@ pub fn prove( // Part 5: Inner product proof for t(x) = // get challenge w from transcript - let w: C::Scalar = transcript.challenge_scalar::(b"w"); + let w: C::Scalar = transcript.extract_challenge_scalar::(b"w"); // get generator q let Q = B.mul_by_scalar(&w); @@ -490,7 +489,7 @@ pub enum VerificationError { #[allow(clippy::many_single_char_names)] pub fn verify_efficient( version: ProofVersion, - transcript: &mut RandomOracle, + transcript: &mut impl TranscriptProtocol, n: u8, commitments: &[Commitment], proof: &RangeProof, @@ -533,8 +532,8 @@ pub fn verify_efficient( transcript.append_message(b"A", &A); transcript.append_message(b"S", &S); // get challenges y,z from transcript - let y: C::Scalar = transcript.challenge_scalar::(b"y"); - let z: C::Scalar = transcript.challenge_scalar::(b"z"); + let y: C::Scalar = transcript.extract_challenge_scalar::(b"y"); + let z: C::Scalar = transcript.extract_challenge_scalar::(b"z"); let mut z2 = z; z2.mul_assign(&z); let mut z3 = z2; @@ -543,7 +542,7 @@ pub fn verify_efficient( transcript.append_message(b"T1", &T_1); transcript.append_message(b"T2", &T_2); // get challenge x (evaluation point) from transcript - let x: C::Scalar = transcript.challenge_scalar::(b"x"); + let x: C::Scalar = transcript.extract_challenge_scalar::(b"x"); let mut x2 = x; x2.mul_assign(&x); // println!("verifier's x = {:?}", x); @@ -552,7 +551,7 @@ pub fn verify_efficient( transcript.append_message(b"tx_tilde", &tx_tilde); transcript.append_message(b"e_tilde", &e_tilde); // get challenge w from transcript - let w: C::Scalar = transcript.challenge_scalar::(b"w"); + let w: C::Scalar = transcript.extract_challenge_scalar::(b"w"); // Part 2: Check verification equation 1 // Calculate delta(x,y) <- (z-z^2)*<1,y_nm> - <1,2_nm> * sum_j=0^m-1 z^(j+3) @@ -677,7 +676,7 @@ pub fn verify_efficient( /// It is assumed that a,b \in [0, 2^n) #[allow(clippy::too_many_arguments)] pub fn prove_less_than_or_equal( - transcript: &mut RandomOracle, + transcript: &mut impl TranscriptProtocol, csprng: &mut T, n: u8, a: u64, @@ -707,7 +706,7 @@ pub fn prove_less_than_or_equal( /// but it should follow that a \in [0, 2^n) if the /// proof verifies. pub fn verify_less_than_or_equal( - transcript: &mut RandomOracle, + transcript: &mut impl TranscriptProtocol, n: u8, commitment_a: &Commitment, commitment_b: &Commitment, @@ -734,7 +733,7 @@ pub fn verify_less_than_or_equal( #[allow(clippy::too_many_arguments)] pub fn prove_in_range( version: ProofVersion, - transcript: &mut RandomOracle, + transcript: &mut impl TranscriptProtocol, csprng: &mut impl rand::Rng, gens: &Generators, keys: &CommitmentKey, @@ -769,7 +768,7 @@ pub fn prove_in_range( #[allow(clippy::too_many_arguments)] pub fn verify_in_range( version: ProofVersion, - transcript: &mut RandomOracle, + transcript: &mut impl TranscriptProtocol, keys: &CommitmentKey, gens: &Generators, a: C::Scalar, @@ -799,9 +798,9 @@ pub fn verify_in_range( #[cfg(test)] mod tests { - use crate::curve_arithmetic::arkworks_instances::ArkGroup; - use super::*; + use crate::curve_arithmetic::arkworks_instances::ArkGroup; + use crate::random_oracle::RandomOracle; /// This function produces a proof that will satisfy the verifier's first /// check, even if the values are not in the interval. @@ -823,7 +822,7 @@ mod tests { B: C, B_tilde: C, csprng: &mut T, - transcript: &mut RandomOracle, + transcript: &mut impl TranscriptProtocol, ) -> (Vec>, Option>) { let nm = (usize::from(n)) * (usize::from(m)); let v_copy = v_vec.clone(); @@ -843,8 +842,8 @@ mod tests { let S = C::zero_point(); transcript.append_message(b"A", &A); transcript.append_message(b"S", &S); - let y: C::Scalar = transcript.challenge_scalar::(b"y"); - let z: C::Scalar = transcript.challenge_scalar::(b"z"); + let y: C::Scalar = transcript.extract_challenge_scalar::(b"y"); + let z: C::Scalar = transcript.extract_challenge_scalar::(b"z"); let z_m = z_vec(z, 0, usize::from(m)); // z squared @@ -864,7 +863,7 @@ mod tests { let e_tilde: C::Scalar = C::Scalar::zero(); transcript.append_message(b"T1", &T_1); transcript.append_message(b"T2", &T_2); - let _x: C::Scalar = transcript.challenge_scalar::(b"x"); + let _x: C::Scalar = transcript.extract_challenge_scalar::(b"x"); // println!("Cheating prover's x = {}", x); for j in 0..usize::from(m) { // tx: diff --git a/rust-src/concordium_base/src/bulletproofs/set_membership_proof.rs b/rust-src/concordium_base/src/bulletproofs/set_membership_proof.rs index 8c3fb6464..b05fca7e3 100644 --- a/rust-src/concordium_base/src/bulletproofs/set_membership_proof.rs +++ b/rust-src/concordium_base/src/bulletproofs/set_membership_proof.rs @@ -1,12 +1,11 @@ //! Implementation of set membership proof along the lines of bulletproofs use super::{inner_product_proof::*, utils::*}; -use crate::random_oracle::StructuredDigest; +use crate::random_oracle::TranscriptProtocol; use crate::{ common::*, curve_arithmetic::{multiexp, Curve, Field, MultiExp}, id::id_proof_types::ProofVersion, pedersen_commitment::*, - random_oracle::RandomOracle, }; use rand::*; use std::{convert::TryInto, iter::once}; @@ -90,7 +89,7 @@ fn a_L_a_R(v: &F, set_slice: &[F]) -> Option<(Vec, Vec)> { #[allow(non_snake_case, clippy::too_many_arguments)] pub fn prove( version: ProofVersion, - transcript: &mut RandomOracle, + transcript: &mut impl TranscriptProtocol, csprng: &mut R, the_set: &[C::Scalar], v: C::Scalar, @@ -100,7 +99,7 @@ pub fn prove( ) -> Result, ProverError> { // Part 0: Add public inputs to transcript // Domain separation - transcript.add_bytes(b"SetMembershipProof"); + transcript.append_label(b"SetMembershipProof"); // Pad set if not power of two let mut set_vec = the_set.to_vec(); @@ -178,8 +177,8 @@ pub fn prove( // Part 2: Computation of vector polynomials l(x),r(x) // get challenges y,z from transcript - let y: C::Scalar = transcript.challenge_scalar::(b"y"); - let z: C::Scalar = transcript.challenge_scalar::(b"z"); + let y: C::Scalar = transcript.extract_challenge_scalar::(b"y"); + let z: C::Scalar = transcript.extract_challenge_scalar::(b"z"); // y_n = (1,y,..,y^(n-1)) let y_n = z_vec(y, 0, n); @@ -262,7 +261,7 @@ pub fn prove( // Part 4: Evaluate l(.), r(.), and t(.) at challenge point x // get challenge x from transcript - let x: C::Scalar = transcript.challenge_scalar::(b"x"); + let x: C::Scalar = transcript.extract_challenge_scalar::(b"x"); let mut x_sq = x; x_sq.mul_assign(&x); // Compute l(x) and r(x) @@ -311,7 +310,7 @@ pub fn prove( // Part 5: Inner product proof for tx = // get challenge w from transcript - let w: C::Scalar = transcript.challenge_scalar::(b"w"); + let w: C::Scalar = transcript.extract_challenge_scalar::(b"w"); // get generator q let Q = B.mul_by_scalar(&w); // compute scalars c such that c*H = H', that is H_prime_scalars = (1, y^-1,.., @@ -372,7 +371,7 @@ pub enum VerificationError { #[allow(non_snake_case)] pub fn verify( version: ProofVersion, - transcript: &mut RandomOracle, + transcript: &mut impl TranscriptProtocol, the_set: &[C::Scalar], V: &Commitment, proof: &SetMembershipProof, @@ -391,7 +390,7 @@ pub fn verify( let (G, H): (Vec<_>, Vec<_>) = gens.G_H.iter().take(n).cloned().unzip(); // Domain separation - transcript.add_bytes(b"SetMembershipProof"); + transcript.append_label(b"SetMembershipProof"); if version >= ProofVersion::Version2 { // Explicitly add generators and commitment keys to the transcript transcript.append_message(b"G", &G); @@ -410,8 +409,8 @@ pub fn verify( transcript.append_message(b"S", &S); // get challenges y,z from transcript - let y: C::Scalar = transcript.challenge_scalar::(b"y"); - let z: C::Scalar = transcript.challenge_scalar::(b"z"); + let y: C::Scalar = transcript.extract_challenge_scalar::(b"y"); + let z: C::Scalar = transcript.extract_challenge_scalar::(b"z"); // define the commitments T1, T2 let T_1 = proof.T_1; @@ -421,7 +420,7 @@ pub fn verify( transcript.append_message(b"T2", &T_2); // get challenge x (evaluation point) from transcript - let x: C::Scalar = transcript.challenge_scalar::(b"x"); + let x: C::Scalar = transcript.extract_challenge_scalar::(b"x"); // define polynomial evaluation value let tx = proof.tx; @@ -434,7 +433,7 @@ pub fn verify( transcript.append_message(b"e_tilde", &e_tilde); // get challenge w from transcript - let w: C::Scalar = transcript.challenge_scalar::(b"w"); + let w: C::Scalar = transcript.extract_challenge_scalar::(b"w"); // compute delta(y,z) = z^3 (1 - zn - <1,s>) + (z - z^2) (<1,y^n>) // first compute helper values @@ -567,6 +566,7 @@ mod tests { use crate::curve_arithmetic::arkworks_instances::ArkGroup; use super::*; + use crate::random_oracle::RandomOracle; use ark_bls12_381::G1Projective; type SomeCurve = ArkGroup; diff --git a/rust-src/concordium_base/src/bulletproofs/set_non_membership_proof.rs b/rust-src/concordium_base/src/bulletproofs/set_non_membership_proof.rs index 5ffabaffb..1396b8605 100644 --- a/rust-src/concordium_base/src/bulletproofs/set_non_membership_proof.rs +++ b/rust-src/concordium_base/src/bulletproofs/set_non_membership_proof.rs @@ -1,12 +1,11 @@ //! Implementation of set-non-membership proof along the lines of bulletproofs use super::{inner_product_proof::*, utils::*}; -use crate::random_oracle::StructuredDigest; +use crate::random_oracle::TranscriptProtocol; use crate::{ common::*, curve_arithmetic::{multiexp, Curve, Field, MultiExp}, id::id_proof_types::ProofVersion, pedersen_commitment::*, - random_oracle::RandomOracle, }; use rand::*; use std::iter::once; @@ -62,7 +61,7 @@ pub enum ProverError { #[allow(non_snake_case, clippy::too_many_arguments)] pub fn prove( version: ProofVersion, - transcript: &mut RandomOracle, + transcript: &mut impl TranscriptProtocol, csprng: &mut R, the_set: &[C::Scalar], v: C::Scalar, @@ -72,7 +71,7 @@ pub fn prove( ) -> Result, ProverError> { // Part 0: Add public inputs to transcript // Domain separation - transcript.add_bytes(b"SetNonMembershipProof"); + transcript.append_label(b"SetNonMembershipProof"); // Pad set if not power of two let mut set_vec = the_set.to_vec(); pad_vector_to_power_of_two(&mut set_vec); @@ -160,8 +159,8 @@ pub fn prove( // Part 2: Computation of vector polynomials l(x),r(x) // get challenges y,z from transcript - let y: C::Scalar = transcript.challenge_scalar::(b"y"); - let z: C::Scalar = transcript.challenge_scalar::(b"z"); + let y: C::Scalar = transcript.extract_challenge_scalar::(b"y"); + let z: C::Scalar = transcript.extract_challenge_scalar::(b"z"); // y_n = (1,y,..,y^(n-1)) let y_n = z_vec(y, 0, n); // ip_y_n = <1,y_n> @@ -233,7 +232,7 @@ pub fn prove( // Part 4: Evaluate l(.), r(.), and t(.) at challenge point x // get challenge x from transcript - let x: C::Scalar = transcript.challenge_scalar::(b"x"); + let x: C::Scalar = transcript.extract_challenge_scalar::(b"x"); let mut x_sq = x; x_sq.mul_assign(&x); // Compute l(x) and r(x) @@ -283,7 +282,7 @@ pub fn prove( // Part 5: Inner product proof for tx = // get challenge w from transcript - let w: C::Scalar = transcript.challenge_scalar::(b"w"); + let w: C::Scalar = transcript.extract_challenge_scalar::(b"w"); // get generator Q = B^w let Q = B.mul_by_scalar(&w); // compute scalars c such that H' = H^c, that is H_prime_scalars = (1, y^-1,.., @@ -341,7 +340,7 @@ pub enum VerificationError { #[allow(non_snake_case)] pub fn verify( version: ProofVersion, - transcript: &mut RandomOracle, + transcript: &mut impl TranscriptProtocol, the_set: &[C::Scalar], V: &Commitment, proof: &SetNonMembershipProof, @@ -360,7 +359,7 @@ pub fn verify( let (G, H): (Vec<_>, Vec<_>) = gens.G_H.iter().take(n).cloned().unzip(); // Domain separation - transcript.add_bytes(b"SetNonMembershipProof"); + transcript.append_label(b"SetNonMembershipProof"); if version >= ProofVersion::Version2 { // Explicitly add generators and commitment keys to the transcript transcript.append_message(b"G", &G); @@ -379,8 +378,8 @@ pub fn verify( transcript.append_message(b"S", &S); // get challenges y,z from transcript - let y: C::Scalar = transcript.challenge_scalar::(b"y"); - let z: C::Scalar = transcript.challenge_scalar::(b"z"); + let y: C::Scalar = transcript.extract_challenge_scalar::(b"y"); + let z: C::Scalar = transcript.extract_challenge_scalar::(b"z"); // define the commitments T1, T2 let T_1 = proof.T_1; @@ -390,7 +389,7 @@ pub fn verify( transcript.append_message(b"T2", &T_2); // get challenge x (evaluation point) from transcript - let x: C::Scalar = transcript.challenge_scalar::(b"x"); + let x: C::Scalar = transcript.extract_challenge_scalar::(b"x"); // define polynomial evaluation value let tx = proof.tx; @@ -403,7 +402,7 @@ pub fn verify( transcript.append_message(b"e_tilde", &e_tilde); // get challenge w from transcript - let w: C::Scalar = transcript.challenge_scalar::(b"w"); + let w: C::Scalar = transcript.extract_challenge_scalar::(b"w"); // compute delta(y,z) = <1, y^n> - z let yn = z_vec(y, 0, n); @@ -497,6 +496,7 @@ mod tests { use crate::curve_arithmetic::arkworks_instances::ArkGroup; use super::*; + use crate::random_oracle::RandomOracle; use ark_bls12_381::G1Projective; type SomeCurve = ArkGroup; diff --git a/rust-src/concordium_base/src/eddsa_ed25519/dlog_ed25519.rs b/rust-src/concordium_base/src/eddsa_ed25519/dlog_ed25519.rs index 7286b3a7c..3f090fc2a 100644 --- a/rust-src/concordium_base/src/eddsa_ed25519/dlog_ed25519.rs +++ b/rust-src/concordium_base/src/eddsa_ed25519/dlog_ed25519.rs @@ -2,7 +2,7 @@ //! curve25519 (cf. "Proof of Knowledge of Discrete Logarithm" Section 9.2.1, //! Bluepaper v1.2.5) which enables one to prove knowledge of the discrete //! logarithm without revealing it. -use crate::random_oracle::StructuredDigest; +use crate::random_oracle::TranscriptProtocol; use crate::{common::*, random_oracle::RandomOracle}; use anyhow::bail; use curve25519_dalek::{ diff --git a/rust-src/concordium_base/src/id/account_holder.rs b/rust-src/concordium_base/src/id/account_holder.rs index 04a528310..c8f20ab5c 100644 --- a/rust-src/concordium_base/src/id/account_holder.rs +++ b/rust-src/concordium_base/src/id/account_holder.rs @@ -1,7 +1,7 @@ //! Functionality needed by the account holder, either when interacting with the //! identity provider, or when interacting with the chain. use super::{id_proof_types::ProofVersion, secret_sharing::*, types::*, utils}; -use crate::random_oracle::StructuredDigest; +use crate::random_oracle::TranscriptProtocol; use crate::{ bulletproofs::{ inner_product_proof::inner_product, diff --git a/rust-src/concordium_base/src/id/chain.rs b/rust-src/concordium_base/src/id/chain.rs index 29d741731..a327659e6 100644 --- a/rust-src/concordium_base/src/id/chain.rs +++ b/rust-src/concordium_base/src/id/chain.rs @@ -1,6 +1,6 @@ //! Functionality needed by the chain to verify credential deployments. use super::{secret_sharing::Threshold, types::*, utils}; -use crate::random_oracle::StructuredDigest; +use crate::random_oracle::TranscriptProtocol; use crate::{ bulletproofs::range_proof::verify_less_than_or_equal, common::{to_bytes, types::TransactionTime}, diff --git a/rust-src/concordium_base/src/id/id_prover.rs b/rust-src/concordium_base/src/id/id_prover.rs index 07c72c91c..1c518f42f 100644 --- a/rust-src/concordium_base/src/id/id_prover.rs +++ b/rust-src/concordium_base/src/id/id_prover.rs @@ -5,7 +5,7 @@ use super::{id_proof_types::*, types::*}; use crate::bulletproofs::set_membership_proof::SetMembershipProof; use crate::bulletproofs::set_non_membership_proof::SetNonMembershipProof; use crate::pedersen_commitment::Randomness; -use crate::random_oracle::StructuredDigest; +use crate::random_oracle::{RandomOracle, TranscriptProtocol}; use crate::sigma_protocols::common::SigmaProof; use crate::sigma_protocols::dlog; use crate::{ @@ -17,7 +17,6 @@ use crate::{ }, curve_arithmetic::{Curve, Value}, pedersen_commitment::{CommitmentKey as PedersenKey, Randomness as PedersenRandomness}, - random_oracle::RandomOracle, sigma_protocols::{ common::prove as sigma_prove, dlog::{Dlog, DlogSecret}, @@ -71,7 +70,7 @@ impl, - transcript: &mut RandomOracle, + transcript: &mut impl TranscriptProtocol, csprng: &mut impl rand::Rng, attribute_values: &impl HasAttributeValues, attribute_randomness: &impl HasAttributeRandomness, @@ -137,7 +136,7 @@ impl, - transcript: &mut RandomOracle, + transcript: &mut impl TranscriptProtocol, csprng: &mut impl rand::Rng, attribute_values: &impl HasAttributeValues, attribute_randomness: &impl HasAttributeRandomness, @@ -170,7 +169,7 @@ impl, - transcript: &mut RandomOracle, + transcript: &mut impl TranscriptProtocol, csprng: &mut impl rand::Rng, attribute_values: &impl HasAttributeValues, attribute_randomness: &impl HasAttributeRandomness, @@ -203,7 +202,7 @@ impl, - transcript: &mut RandomOracle, + transcript: &mut impl TranscriptProtocol, csprng: &mut impl rand::Rng, attribute_values: &impl HasAttributeValues, attribute_randomness: &impl HasAttributeRandomness, @@ -232,11 +231,11 @@ pub(crate) fn prove_value_equal_to_commitment, version: ProofVersion, global: &GlobalContext, - transcript: &mut RandomOracle, + transcript: &mut impl TranscriptProtocol, csprng: &mut impl rand::Rng, ) -> Option>> { let x = attribute_value.to_field_element(); // This is public in the sense that the verifier should learn it - transcript.add_bytes(b"RevealAttributeDlogProof"); + transcript.append_label(b"RevealAttributeDlogProof"); transcript.append_message(b"x", &x); if version >= ProofVersion::Version2 { transcript.append_message(b"keys", &global.on_chain_commitment_key); @@ -267,7 +266,7 @@ impl, - transcript: &mut RandomOracle, + transcript: &mut impl TranscriptProtocol, csprng: &mut impl rand::Rng, attribute_randomness: &impl HasAttributeRandomness, ) -> Option> { @@ -286,7 +285,7 @@ impl>( version: ProofVersion, - transcript: &mut RandomOracle, + transcript: &mut impl TranscriptProtocol, csprng: &mut impl rand::Rng, gens: &Generators, keys: &PedersenKey, @@ -368,7 +367,7 @@ pub fn prove_attribute_in_range>( ) } ProofVersion::Version2 => { - transcript.add_bytes(b"AttributeRangeProof"); + transcript.append_label(b"AttributeRangeProof"); transcript.append_message(b"a", &a); transcript.append_message(b"b", &b); prove_in_range( diff --git a/rust-src/concordium_base/src/id/id_verifier.rs b/rust-src/concordium_base/src/id/id_verifier.rs index 4a834d0c9..80f85db41 100644 --- a/rust-src/concordium_base/src/id/id_verifier.rs +++ b/rust-src/concordium_base/src/id/id_verifier.rs @@ -14,7 +14,7 @@ use crate::bulletproofs::{ use super::id_proof_types::*; use crate::bulletproofs::set_membership_proof::SetMembershipProof; use crate::bulletproofs::set_non_membership_proof::SetNonMembershipProof; -use crate::random_oracle::StructuredDigest; +use crate::random_oracle::{RandomOracle, TranscriptProtocol}; use crate::sigma_protocols::common::SigmaProof; use crate::sigma_protocols::dlog; use crate::{ @@ -22,7 +22,6 @@ use crate::{ pedersen_commitment::{ Commitment, CommitmentKey as PedersenKey, Randomness as PedersenRandomness, Value, }, - random_oracle::RandomOracle, sigma_protocols::{common::verify as sigma_verify, dlog::Dlog}, }; use sha2::{Digest, Sha256}; @@ -59,7 +58,7 @@ pub fn verify_attribute>( #[allow(clippy::too_many_arguments)] pub fn verify_attribute_range>( version: ProofVersion, - transcript: &mut RandomOracle, + transcript: &mut impl TranscriptProtocol, keys: &PedersenKey, gens: &Generators, lower: &AttributeType, @@ -84,7 +83,7 @@ pub fn verify_attribute_range>( ) } ProofVersion::Version2 => { - transcript.add_bytes(b"AttributeRangeProof"); + transcript.append_label(b"AttributeRangeProof"); transcript.append_message(b"a", &a); transcript.append_message(b"b", &b); verify_in_range( @@ -166,7 +165,7 @@ impl< &self, version: ProofVersion, global: &GlobalContext, - transcript: &mut RandomOracle, + transcript: &mut impl TranscriptProtocol, cmm_attributes: &BTreeMap>, proof: &AtomicProof, ) -> bool { @@ -213,7 +212,7 @@ impl< &self, version: ProofVersion, global: &GlobalContext, - transcript: &mut RandomOracle, + transcript: &mut impl TranscriptProtocol, cmm_attributes: &BTreeMap>, proof: &RangeProof, ) -> bool { @@ -248,7 +247,7 @@ impl< &self, version: ProofVersion, global: &GlobalContext, - transcript: &mut RandomOracle, + transcript: &mut impl TranscriptProtocol, cmm_attributes: &BTreeMap>, proof: &SetMembershipProof, ) -> bool { @@ -281,7 +280,7 @@ impl< &self, version: ProofVersion, global: &GlobalContext, - transcript: &mut RandomOracle, + transcript: &mut impl TranscriptProtocol, cmm_attributes: &BTreeMap>, proof: &SetNonMembershipProof, ) -> bool { @@ -309,13 +308,13 @@ fn verify_value_equal_to_commitment, version: ProofVersion, global: &GlobalContext, - transcript: &mut RandomOracle, + transcript: &mut impl TranscriptProtocol, proof: &SigmaProof>, ) -> bool { // There is a commitment to the relevant attribute. We can then check the // proof. let x = attribute_value.to_field_element(); - transcript.add_bytes(b"RevealAttributeDlogProof"); + transcript.append_label(b"RevealAttributeDlogProof"); // x is known to the verifier and should go into the transcript transcript.append_message(b"x", &x); if version >= ProofVersion::Version2 { @@ -343,7 +342,7 @@ impl< &self, version: ProofVersion, global: &GlobalContext, - transcript: &mut RandomOracle, + transcript: &mut impl TranscriptProtocol, cmm_attributes: &BTreeMap>, proof: &AttributeValueProof, ) -> bool { @@ -364,7 +363,7 @@ impl< /// Verify attribute value based on that attribute is already revealed pub(crate) fn verify_for_already_revealed( &self, - transcript: &mut RandomOracle, + transcript: &mut impl TranscriptProtocol, revealed_attributes: &BTreeMap, ) -> bool { let Some(revealed_attribute) = revealed_attributes.get(&self.attribute_tag) else { diff --git a/rust-src/concordium_base/src/id/identity_attributes_credentials.rs b/rust-src/concordium_base/src/id/identity_attributes_credentials.rs index cb08de0c5..ebc1c38fe 100644 --- a/rust-src/concordium_base/src/id/identity_attributes_credentials.rs +++ b/rust-src/concordium_base/src/id/identity_attributes_credentials.rs @@ -9,7 +9,7 @@ use super::{account_holder, types::*, utils}; use crate::pedersen_commitment::{CommitmentKey, Randomness}; -use crate::random_oracle::StructuredDigest; +use crate::random_oracle::TranscriptProtocol; use crate::sigma_protocols::common::{ AndAdapter, AndResponse, ReplicateAdapter, ReplicateResponse, SigmaProof, }; @@ -19,9 +19,7 @@ use crate::{ pedersen_commitment::{ Commitment, CommitmentKey as PedersenKey, Randomness as PedersenRandomness, Value, }, - ps_sig, - random_oracle::RandomOracle, - sigma_protocols, + ps_sig, sigma_protocols, sigma_protocols::com_enc_eq, }; use anyhow::Context; @@ -53,7 +51,7 @@ pub fn prove_identity_attributes< id_object_use_data: &IdObjectUseData, attributes_handling: &BTreeMap, csprng: &mut (impl Rng + CryptoRng), - transcript: &mut RandomOracle, + transcript: &mut impl TranscriptProtocol, ) -> anyhow::Result<( IdentityAttributesCredentialsInfo, IdentityAttributesCredentialsRandomness, @@ -183,9 +181,9 @@ pub fn prove_identity_attributes< // IdentityAttributesCommitmentValues struct. // This should make the proof non-reusable. // We should add the genesis hash also at some point - transcript.add_bytes(b"IdentityAttributesCredentials"); - transcript.append_message(b"identity_attribute_values", &id_attribute_values); - transcript.append_message(b"global_context", &global_context); + transcript.append_label("IdentityAttributesCredentials"); + transcript.append_message("IdentityAttributeValues", &id_attribute_values); + transcript.append_message("GlobalContext", &global_context); let proof = sigma_protocols::common::prove(transcript, &prover, witness, csprng) .context("cannot produce zero knowledge proof")?; @@ -401,7 +399,7 @@ pub fn verify_identity_attributes< global_context: &GlobalContext, ip_context: IpContextOnly<'_, P, C>, id_attr_info: &IdentityAttributesCredentialsInfo, - transcript: &mut RandomOracle, + transcript: &mut impl TranscriptProtocol, ) -> Result<(), AttributeCommitmentVerificationError> { if ip_context.ip_info.ip_identity != id_attr_info.values.ip_identity { return Err(AttributeCommitmentVerificationError::Signature); @@ -415,9 +413,9 @@ pub fn verify_identity_attributes< } // Compute the challenge prefix by hashing the values. - transcript.add_bytes(b"IdentityAttributesCredentials"); - transcript.append_message(b"identity_attribute_values", &id_attr_info.values); - transcript.append_message(b"global_context", &global_context); + transcript.append_label("IdentityAttributesCredentials"); + transcript.append_message("IdentityAttributeValues", &id_attr_info.values); + transcript.append_message("GlobalContext", &global_context); let verifier_sig = signature_knowledge_verifier( &global_context.on_chain_commitment_key, diff --git a/rust-src/concordium_base/src/id/identity_provider.rs b/rust-src/concordium_base/src/id/identity_provider.rs index d2114a8fc..bc1376799 100644 --- a/rust-src/concordium_base/src/id/identity_provider.rs +++ b/rust-src/concordium_base/src/id/identity_provider.rs @@ -1,7 +1,7 @@ //! Functionality needed by the identity provider. This gathers together the //! primitives from the rest of the library into a convenient package. use super::{id_proof_types::ProofVersion, secret_sharing::Threshold, types::*, utils}; -use crate::random_oracle::StructuredDigest; +use crate::random_oracle::TranscriptProtocol; use crate::{ bulletproofs::range_proof::verify_efficient, common::{to_bytes, types::TransactionTime}, diff --git a/rust-src/concordium_base/src/random_oracle/mod.rs b/rust-src/concordium_base/src/random_oracle/mod.rs index d863531ae..c64b1efe6 100644 --- a/rust-src/concordium_base/src/random_oracle/mod.rs +++ b/rust-src/concordium_base/src/random_oracle/mod.rs @@ -1,24 +1,50 @@ -//! This module provides the random oracle replacement function needed in the -//! sigma protocols, bulletproofs, and any other constructions. It is based on -//! SHA3. It is used in non-interactive proofs and plays the same role as a random -//! oracle would play in the corresponding interactive protocol (via -//! Fiat–Shamir transformation). -//! -//! # Using the random oracle replacement -//! [`RandomOracle`] instances should be initialized with at domain-separation -//! string and passed to protocols by mutable borrow. Protocols should update -//! the state of the [`RandomOracle`], allowing them to be sequentially -//! composed. -//! -//! The [`RandomOracle`] instance used to verify a proof needs to be initialised -//! with the context used to produce the proof. Any verification of sub-proofs +//! This module implements the transcript used in sigma protocols, bulletproofs, and other +//! public-coin multi-round proof systems, that has undergone the Fiat-Shamir transformation. +//! It plays the same role as a random oracle would play in the corresponding interactive protocol, +//! hence the name of the present module and some of the types in the module. +//! +//! For background, see "9.3 Non-interactive Proofs using the Fiat-Shamir Transformation" in tbe blue paper. +//! For understanding the general concepts and the considerations put into a transcript implementation, +//! the Merlin transcript can be studied here: (implemented at ). +//! +//! # Using the transcript +//! Transcript instances should be initialized with at domain-separation +//! string that defines the particular protocol. See . +//! +//! For each proof, protocols should update the state of the transcript with public input +//! and implicit public values, and each message send by prover, including the final message +//! send by the prover. Proofs can be be sequentially composed, see . +//! It is specifically because of sequential composition, that it is important that also the final message send by the prover is added to the transcript. +//! +//! Verifier messages (the challenges) in the proof should be extracted from the transcript instance. +//! It is in this extraction, that the transcript plays the role of a random oracle. +//! +//! The transcript instance used to verify a proof needs to be initialised and updated +//! with the same input used to produce the proof. Any verification of sub-proofs //! needs to be performed in the same order as when producing the proof. +//! See +//! +//! Part of a transcript protocol (see ) is defining +//! how messages of types defined by the protocol (often mathematical objects) are encoded to message bytes and how +//! challenge bytes are decoded to challenges of types defined in the protocol (again mathematical objects). The latter must +//! preserve uniform distribution in the challenge space. +//! This is handled via [`TranscriptProtocol`] and largely uses the [`Serial`] +//! and [`Deserial`] implementations on the message and challenge types. //! -//! The [`RandomOracle`] instance should be used to append bytes to its internal state. -//! After adding data, call [`RandomOracle::get_challenge`] to consume/hash the bytes -//! and produce a random challenge. +//! # Example: Ensuring proper domain separation //! -//! For background, the Merlin transcript can also be studied here: (implemented at ). +//! The transcript should be initialized with a domain separating string. Further branches in the code +//! or nested proofs should also be labelled for domain separation. +//! +//! ``` +//! # use concordium_base::random_oracle::{TranscriptProtocol, TranscriptV1}; +//! let mut transcript = TranscriptV1::with_domain("Proof of something"); +//! // ... +//! transcript.append_label("Subproof1"); +//! // ... +//! transcript.append_label("Branch1"); +//! // ... +//!``` //! //! # Caution: Type ambiguity without domain separation //! Special care is required when adding bytes to domain separate them with labels. @@ -47,9 +73,9 @@ //! }; //! ``` //! -//! Appending the [`RandomOracle`] with either of above types by just adding each type's field values naively +//! Appending the transcript with either of above types by just adding each type's field values naively //! (meaning `hash([1u8, 2u8]`) would produce the same hashing result for both examples. To avoid this, the -//! recommendation is to add the type name and its field names as labels for domain separation. +//! recommendation is to add the type name as labels for domain separation. //! //! # Example: Adding struct data //! @@ -98,7 +124,7 @@ //! }; //! ``` //! -//! Appending the [`RandomOracle`] with each field label and value naively +//! Appending the transcript with each field label and value naively //! (meaning `hash("field_1" + "field_2" + "field_2")`) would produce //! the same hashing result for both examples. To avoid this, //! prepend the length of the variable-length data. @@ -111,44 +137,42 @@ //! //! Serialization of variable-length primitives like `String` will prepend the length. //! -//! ``` -//! # use concordium_base::random_oracle::{StructuredDigest, RandomOracle}; -//! -//! let mut transcript = RandomOracle::empty(); +//!``` +//! # use concordium_base::random_oracle::{TranscriptProtocol, TranscriptV1}; +//! let mut transcript = TranscriptV1::with_domain("Proof of something"); //! let string = "abc".to_string(); //! // The serialization implementation of the `String` type prepends the length of the field values. -//! transcript.append_message(b"String1", &string); +//! transcript.append_message("String1", &string); //! ``` //! //! # Example: Adding collections of data using `Serial` //! //! Serialization of collections like `Vec` will prepend the size of the collection. //! -//! ``` -//! # use concordium_base::random_oracle::{StructuredDigest, RandomOracle}; -//! -//! let mut transcript = RandomOracle::empty(); +//!``` +//! # use concordium_base::random_oracle::{TranscriptProtocol, TranscriptV1}; +//! let mut transcript = TranscriptV1::with_domain("Proof of something"); //! let collection = vec![2,3,4]; -//! transcript.append_message(b"Collection1", &collection); +//! transcript.append_message("Collection1", &collection); //! ``` //! //! # Example: Adding variable number of items //! //! Digesting a variable number of items without relying on `Serial` implementation on the items: //! -//! ``` -//! # use concordium_base::random_oracle::{StructuredDigest, RandomOracle}; +//!``` +//! # use concordium_base::random_oracle::{TranscriptProtocol, TranscriptV1}; //! //! struct Type1; //! -//! fn append_type1(transcript: &mut impl StructuredDigest, val: &Type1) { +//! fn append_type1(transcript: &mut impl TranscriptProtocol, val: &Type1) { //! // digest Type1 //! } //! //! let vec = vec![Type1, Type1]; //! -//! let mut transcript = RandomOracle::empty(); -//! transcript.append_each("Collection", &vec, |transcript, item| { +//! let mut transcript = TranscriptV1::with_domain("Proof of something"); +//! transcript.append_each_message("Collection", &vec, |transcript, item| { //! append_type1(transcript, item); //! }); //! ``` @@ -158,32 +182,49 @@ //! If you add an enum manually to the transcript add the variant name //! to the transcript followed by the variant data. //! -//! ``` -//! # use concordium_base::random_oracle::{StructuredDigest, RandomOracle}; +//!``` +//! # use concordium_base::random_oracle::{TranscriptProtocol, TranscriptV1}; //! //! enum Enum1 { //! Variant_0, //! Variant_1 //! } //! -//! let mut transcript = RandomOracle::empty(); +//! let mut transcript = TranscriptV1::with_domain("Proof of something"); //! -//! transcript.add_bytes(b"Enum1"); -//! transcript.add_bytes(b"Variant_0"); +//! transcript.append_label("Enum1"); +//! transcript.append_label("Variant_0"); //! // add data from Variant_0 //! ``` //! //! Notice that if you serialize an enum that implements [`Serial`], //! the variant discriminator will be serialized (check the [`Serial`] of the enum) + use crate::{common::*, curve_arithmetic::Curve}; use sha3::{Digest, Sha3_256}; -use std::io::Write; +use std::convert::Infallible; +use std::fmt::Arguments; +use std::io::{IoSlice, Write}; -/// State of the random oracle, used to incrementally build up the output. See [`random_oracle`](self). +/// Transcript implementation V0. Implements [`TranscriptProtocol`]. See [`random_oracle`](self) +/// and [`TranscriptProtocol`] for how to use it. #[repr(transparent)] #[derive(Debug)] +// todo ar deprecate? +// #[cfg_attr( +// not(test), +// deprecated( +// note = "Use TranscriptV1 which does proper length prefixing of labels and includes last prover message in transcript for proper sequential composition. Do not change existing protocols without changing their proof version since it will break compatability with existing proofs." +// ) +// )] pub struct RandomOracle(Sha3_256); +/// Transcript implementation V1. Implements [`TranscriptProtocol`]. See [`random_oracle`](self) +/// and [`TranscriptProtocol`] for how to use it. +#[repr(transparent)] +#[derive(Debug)] +pub struct TranscriptV1(Sha3_256); + /// Type of challenges computed from the random oracle. /// We use 32 byte output of SHA3-256 #[derive(Debug, Serialize, PartialEq, Eq, Clone, Copy)] @@ -242,8 +283,18 @@ impl PartialEq for RandomOracle { } } -/// Trait for digesting messages that encourages encoding the structure of the data into -/// the message bytes. This is done e.g. by applying length prefixes for variable-length data and +// todo ar finish doc +/// Transcript protocol that defines how messages and challenges are encoded to and +/// decoded from bytes. +/// The transcript protocol also encourages doing domain separation and labelling data, +/// and helps handling structured data in the right way +/// +/// This is largely done using the [`Serial`] +/// and [`Deserial`] implementations on the message and challenge types. +/// +/// See for a description of the concept of a transcript protocol. +/// +/// This is done e.g. by applying length prefixes for variable-length data and /// prefixing variants with a discriminator. /// And by labelling types and fields for domain separation. Both are done to prevent malleability /// in the proofs where the oracle is used. @@ -252,54 +303,91 @@ impl PartialEq for RandomOracle { /// bytes for variable-length types (including enums), since the corresponding [`Deserial`] /// implementation guarantees the message bytes are unique for the data. Notice that using [`Serial`] /// does not label types or fields in the nested data. -pub trait StructuredDigest: Buffer { - /// Add raw message bytes to the state of the oracle. Should primarily be used to - /// append labels. - fn add_bytes(&mut self, data: impl AsRef<[u8]>); +pub trait TranscriptProtocol { + /// Add domain separating label to the digest. The label bytes will be prepended with the bytes length. + fn append_label(&mut self, label: impl AsRef<[u8]>); - /// Append the given data as the message bytes produced by its [`Serial`] implementation to the state of the oracle. + /// Append the given data as the message bytes produced by its [`Serial`] implementation to the transcript. /// The given label is appended first as domain separation. Notice that a slice, `Vec` and several other collections of /// items implementing [`Serial`] itself implements [`Serial`]. When serializing variable-length /// types or collection types, the length or size will be prepended in the serialization. - fn append_message(&mut self, label: impl AsRef<[u8]>, data: &impl Serial) { - self.add_bytes(label); - self.put(data) - } + fn append_message(&mut self, label: impl AsRef<[u8]>, message: &impl Serial); + + // todo ar finish doc + fn append_messages<'a, T: Serial + 'a, B: IntoIterator>( + &mut self, + label: impl AsRef<[u8]>, + messages: B, + ) where + B::IntoIter: ExactSizeIterator; + + // todo ar finish doc + fn append_final_prover_message(&mut self, label: impl AsRef<[u8]>, message: &impl Serial); /// Append the items in the given iterator using the `append_item` closure to the state of the oracle. /// The given label is appended first as domain separation followed by the length of the iterator. - fn append_each>( + fn append_each_message>( &mut self, - label: &str, - items: B, - mut append_item: impl FnMut(&mut Self, T), + label: impl AsRef<[u8]>, + messages: B, + append_item: impl FnMut(&mut Self, T), + ) where + B::IntoIter: ExactSizeIterator; + + // todo ar finish doc + fn extract_challenge_scalar(&mut self, label: impl AsRef<[u8]>) -> C::Scalar; + + // todo ar finish doc + fn extract_raw_challenge(&self) -> Challenge; +} + +impl TranscriptProtocol for RandomOracle { + fn append_label(&mut self, label: impl AsRef<[u8]>) { + self.0.update(label) + } + + fn append_message(&mut self, label: impl AsRef<[u8]>, message: &impl Serial) { + self.append_label(label); + self.put(message) + } + + fn append_messages<'a, T: Serial + 'a, B: IntoIterator>( + &mut self, + label: impl AsRef<[u8]>, + messages: B, ) where B::IntoIter: ExactSizeIterator, { - let items = items.into_iter(); - self.add_bytes(label); - self.put(&(items.len() as u64)); - for item in items { - append_item(self, item); + self.append_label(label); + for message in messages { + self.put(message); } } -} -impl StructuredDigest for RandomOracle { - fn add_bytes(&mut self, data: impl AsRef<[u8]>) { - self.0.update(data) + fn append_final_prover_message(&mut self, _label: impl AsRef<[u8]>, _message: &impl Serial) { + // not added in V0 + } + + fn append_each_message>( + &mut self, + label: impl AsRef<[u8]>, + messages: B, + mut append_item: impl FnMut(&mut Self, T), + ) where + B::IntoIter: ExactSizeIterator, + { + self.append_label(label); + for message in messages { + append_item(self, message); + } } -} -impl StructuredDigest for sha2::Sha256 { - fn add_bytes(&mut self, data: impl AsRef<[u8]>) { - self.update(data) + fn extract_challenge_scalar(&mut self, label: impl AsRef<[u8]>) -> C::Scalar { + self.challenge_scalar::(label) } -} -impl StructuredDigest for sha2::Sha512 { - fn add_bytes(&mut self, data: impl AsRef<[u8]>) { - self.update(data) + fn extract_raw_challenge(&self) -> Challenge { + self.split().get_challenge() } } @@ -320,12 +408,13 @@ impl RandomOracle { RandomOracle(self.0.clone()) } + pub fn add_bytes>(&mut self, data: B) { + self.0.update(data) + } + /// Append all items from an iterator to the random oracle. Equivalent to /// repeatedly calling append in sequence. /// Returns the new state of the random oracle, consuming the initial state. - #[deprecated( - note = "Use RandomOracle::append_message (with a collection type) instead such that the number of elements is prepended. Do not change existing provers/verifiers since it will break compatability with existing proofs." - )] pub fn extend_from<'a, I, S, B: AsRef<[u8]>>(&mut self, label: B, iter: I) where S: Serial + 'a, @@ -359,6 +448,116 @@ impl RandomOracle { } } +struct BufferAdapter(T); + +impl Write for BufferAdapter { + fn write(&mut self, buf: &[u8]) -> std::io::Result { + self.0.write(buf) + } + + fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> std::io::Result { + self.0.write_vectored(bufs) + } + + fn flush(&mut self) -> std::io::Result<()> { + self.0.flush() + } + + fn write_all(&mut self, buf: &[u8]) -> std::io::Result<()> { + self.0.write_all(buf) + } + + fn write_fmt(&mut self, args: Arguments<'_>) -> std::io::Result<()> { + self.0.write_fmt(args) + } +} + +impl Buffer for BufferAdapter { + type Result = Infallible; + + fn start() -> Self { + unimplemented!() + } + + fn result(self) -> Self::Result { + unimplemented!() + } +} + +impl TranscriptProtocol for TranscriptV1 { + fn append_label(&mut self, label: impl AsRef<[u8]>) { + let label = label.as_ref(); + BufferAdapter(&mut self.0).put(&(label.len() as u64)); + self.0.update(label) + } + + fn append_message(&mut self, label: impl AsRef<[u8]>, message: &impl Serial) { + self.append_label(label); + BufferAdapter(&mut self.0).put(message) + } + + fn append_messages<'a, T: Serial + 'a, B: IntoIterator>( + &mut self, + label: impl AsRef<[u8]>, + messages: B, + ) where + B::IntoIter: ExactSizeIterator, + { + let messages = messages.into_iter(); + self.append_label(label); + BufferAdapter(&mut self.0).put(&(messages.len() as u64)); + for message in messages { + BufferAdapter(&mut self.0).put(message); + } + } + + fn append_final_prover_message(&mut self, label: impl AsRef<[u8]>, message: &impl Serial) { + self.append_message(label, message); + } + + fn append_each_message>( + &mut self, + label: impl AsRef<[u8]>, + messages: B, + mut append_item: impl FnMut(&mut Self, T), + ) where + B::IntoIter: ExactSizeIterator, + { + let messages = messages.into_iter(); + self.append_label(label); + BufferAdapter(&mut self.0).put(&(messages.len() as u64)); + for message in messages { + append_item(self, message); + } + } + + fn extract_challenge_scalar(&mut self, label: impl AsRef<[u8]>) -> C::Scalar { + self.append_label(label); + C::scalar_from_bytes(self.extract_raw_challenge().challenge) + } + + fn extract_raw_challenge(&self) -> Challenge { + Challenge { + challenge: self.0.clone().finalize().into(), + } + } +} + +impl TranscriptV1 { + /// Start with the initial domain string. + pub fn with_domain(domain: impl AsRef<[u8]>) -> Self { + let mut transcript = TranscriptV1(Sha3_256::new()); + transcript.append_label(domain); + transcript + } + + /// Duplicate the transcript, creating a fresh copy of it. + /// Further updates are independent. + pub fn split(&self) -> Self { + TranscriptV1(self.0.clone()) + } +} + #[cfg(test)] mod tests { use super::*; @@ -414,7 +613,7 @@ mod tests { /// Test that we don't accidentally change the digest produced /// by [`RandomOracle::domain`] #[test] - pub fn test_domain_stable() { + pub fn test_v0_domain_stable() { let ro = RandomOracle::domain("Domain1"); let challenge_hex = hex::encode(ro.get_challenge()); @@ -427,7 +626,7 @@ mod tests { /// Test that we don't accidentally change the digest produced /// by [`RandomOracle::add_bytes`] #[test] - pub fn test_add_bytes_stable() { + pub fn test_v0_add_bytes_stable() { let mut ro = RandomOracle::empty(); ro.add_bytes([1u8, 2, 3]); @@ -439,9 +638,23 @@ mod tests { } /// Test that we don't accidentally change the digest produced - /// by [`StructuredDigest::append_message`] + /// by [`TranscriptProtocol::append_label`] + #[test] + pub fn test_v0_append_label_stable() { + let mut ro = RandomOracle::empty(); + ro.append_label([1u8, 2, 3]); + + let challenge_hex = hex::encode(ro.get_challenge()); + assert_eq!( + challenge_hex, + "fd1780a6fc9ee0dab26ceb4b3941ab03e66ccd970d1db91612c66df4515b0a0a" + ); + } + + /// Test that we don't accidentally change the digest produced + /// by [`TranscriptProtocol::append_message`] #[test] - pub fn test_append_message_stable() { + pub fn test_v0_append_message_stable() { let mut ro = RandomOracle::empty(); ro.append_message("Label1", &vec![1u8, 2, 3]); @@ -452,14 +665,60 @@ mod tests { ); } - /// Test that we don't accidentally change the scalar produced - /// by [`RandomOracle::challenge_scalar`] + /// Test that we don't accidentally change the digest produced + /// by [`TranscriptProtocol::append_messages`] and [`RandomOracle::extend_from`] #[test] - pub fn test_challenge_scalar_stable() { + pub fn test_v0_append_messages_stable() { + // todo ar copy to main let mut ro = RandomOracle::empty(); + ro.append_messages("Label1", &vec![1u8, 2, 3]); + + let challenge_hex = hex::encode(ro.get_challenge()); + assert_eq!( + challenge_hex, + "6b1addb1c08e887242f5e78127c31c17851f29349c45aa415adce255f95fd292" + ); + + let mut ro = RandomOracle::empty(); + ro.extend_from("Label1", &vec![1u8, 2, 3]); + + let challenge_hex = hex::encode(ro.get_challenge()); + assert_eq!( + challenge_hex, + "6b1addb1c08e887242f5e78127c31c17851f29349c45aa415adce255f95fd292" + ); + } + + /// Test that we don't accidentally change the digest produced + /// by [`TranscriptProtocol::append_final_prover_message`] + #[test] + pub fn test_v0_append_final_prover_message_stable() { + let mut ro = RandomOracle::empty(); + ro.append_final_prover_message("Label1", &vec![1u8, 2, 3]); + + let challenge_hex = hex::encode(ro.get_challenge()); + assert_eq!( + challenge_hex, + "a7ffc6f8bf1ed76651c14756a061d662f580ff4de43b49fa82d80a4b80f8434a" + ); + } + + /// Test that we don't accidentally change the scalar produced + /// by [`TranscriptProtocol::extract_challenge_scalar`] + #[test] + pub fn test_v0_extract_challenge_scalar_stable() { + let ro = RandomOracle::empty(); + + let scalar_hex = hex::encode(common::to_bytes( + &ro.split().extract_challenge_scalar::("Scalar1"), + )); + assert_eq!( + scalar_hex, + "08646777f9c47efc863115861aa18d95653212c3bdf36899c7db46fbdae095cd" + ); let scalar_hex = hex::encode(common::to_bytes( - &ro.challenge_scalar::("Scalar1"), + &ro.split().challenge_scalar::("Scalar1"), )); assert_eq!( scalar_hex, @@ -483,18 +742,118 @@ mod tests { } /// Test that we don't accidentally change the digest produced - /// by [`StructuredDigest::append_message`] + /// by [`TranscriptProtocol::append_message`] #[test] - pub fn test_append_each_stable() { + pub fn test_v0_append_each_message_stable() { let mut ro = RandomOracle::empty(); - ro.append_each("Label1", &vec![1u8, 2, 3], |ro, item| { + ro.append_each_message("Label1", &vec![1u8, 2, 3], |ro, item| { ro.append_message("Item", item) }); let challenge_hex = hex::encode(ro.get_challenge()); assert_eq!( challenge_hex, - "891fd1754242e364a9eca7a15133403f3293ad330ce295cca0dd8347b94df7a8" + "90da7b2dc7bc9091be9201598ef0d8b43f8b00c53454822a2f8ce41c6a3f3d85" + ); + } + + /// Test that we don't accidentally change the digest produced + /// by [`TranscriptV1::with_domain`] + #[test] + pub fn test_v1_with_domain_stable() { + let ro = TranscriptV1::with_domain("Domain1"); + + let challenge_hex = hex::encode(ro.extract_raw_challenge()); + assert_eq!( + challenge_hex, + "5691f0658460c461ffe14baa70071545df78725892d0decfe6f6642233a0d8e2" + ); + } + + /// Test that we don't accidentally change the digest produced + /// by [`TranscriptProtocol::append_label`] + #[test] + pub fn test_v1_append_label_stable() { + let mut ro = TranscriptV1::with_domain("Domain1"); + ro.append_label([1u8, 2, 3]); + + let challenge_hex = hex::encode(ro.extract_raw_challenge()); + assert_eq!( + challenge_hex, + "683a300a44b3f9165f78dd9fd90efc9a632c11131ef5e805ff3505b5bf0cc7d2" + ); + } + + /// Test that we don't accidentally change the digest produced + /// by [`TranscriptProtocol::append_message`] + #[test] + pub fn test_v1_append_message_stable() { + let mut ro = TranscriptV1::with_domain("Domain1"); + ro.append_message("Label1", &vec![1u8, 2, 3]); + + let challenge_hex = hex::encode(ro.extract_raw_challenge()); + assert_eq!( + challenge_hex, + "5fb23e3d1cfb33d1b2e2da1c070c7a79056b00d13d642ee47fba542d4863a911" + ); + } + + /// Test that we don't accidentally change the digest produced + /// by [`TranscriptProtocol::append_messages`] + #[test] + pub fn test_v1_append_messages_stable() { + let mut ro = TranscriptV1::with_domain("Domain1"); + ro.append_messages("Label1", &vec![1u8, 2, 3]); + + let challenge_hex = hex::encode(ro.extract_raw_challenge()); + assert_eq!( + challenge_hex, + "5fb23e3d1cfb33d1b2e2da1c070c7a79056b00d13d642ee47fba542d4863a911" + ); + } + + /// Test that we don't accidentally change the digest produced + /// by [`TranscriptProtocol::append_final_prover_message`] + #[test] + pub fn test_v1_append_final_prover_message_stable() { + let mut ro = TranscriptV1::with_domain("Domain1"); + ro.append_final_prover_message("Label1", &vec![1u8, 2, 3]); + + let challenge_hex = hex::encode(ro.extract_raw_challenge()); + assert_eq!( + challenge_hex, + "5fb23e3d1cfb33d1b2e2da1c070c7a79056b00d13d642ee47fba542d4863a911" + ); + } + + /// Test that we don't accidentally change the scalar produced + /// by [`TranscriptProtocol::extract_challenge_scalar`] + #[test] + pub fn test_v1_extract_challenge_scalar_stable() { + let ro = TranscriptV1::with_domain("Domain1"); + + let scalar_hex = hex::encode(common::to_bytes( + &ro.split().extract_challenge_scalar::("Scalar1"), + )); + assert_eq!( + scalar_hex, + "3efcc0fdddcc90a71a022212338ae1c6c7b102fdb9af6befd460d68561856ad9" + ); + } + + /// Test that we don't accidentally change the digest produced + /// by [`TranscriptProtocol::append_message`] + #[test] + pub fn test_v1_append_each_message_stable() { + let mut ro = TranscriptV1::with_domain("Domain1"); + ro.append_each_message("Label1", &vec![1u8, 2, 3], |ro, item| { + ro.append_message("Item", item) + }); + + let challenge_hex = hex::encode(ro.extract_raw_challenge()); + assert_eq!( + challenge_hex, + "ffd0694d68003afd3751f33bbadd38ae26db78aa4e62ce4d53814b9676d6c7dd" ); } } diff --git a/rust-src/concordium_base/src/sigma_protocols/aggregate_dlog.rs b/rust-src/concordium_base/src/sigma_protocols/aggregate_dlog.rs index 85fef3d77..5a31f02ff 100644 --- a/rust-src/concordium_base/src/sigma_protocols/aggregate_dlog.rs +++ b/rust-src/concordium_base/src/sigma_protocols/aggregate_dlog.rs @@ -5,11 +5,11 @@ //! $. This is a specialization of `com_eq` protocol where we do not require //! commitments. use super::common::*; -use crate::random_oracle::StructuredDigest; +use crate::random_oracle::TranscriptProtocol; use crate::{ common::*, curve_arithmetic::{multiexp, Curve, Field}, - random_oracle::{Challenge, RandomOracle}, + random_oracle::Challenge, }; use itertools::izip; use std::rc::Rc; @@ -38,10 +38,9 @@ impl SigmaProtocol for AggregateDlog { type Response = Response; type SecretData = Vec>; - fn public(&self, ro: &mut RandomOracle) { + fn public(&self, ro: &mut impl TranscriptProtocol) { ro.append_message(b"public", &self.public); - #[allow(deprecated)] - ro.extend_from(b"coeff", &self.coeff) + ro.append_messages(b"coeff", &self.coeff) } fn compute_commit_message( @@ -124,6 +123,7 @@ mod tests { use crate::curve_arithmetic::arkworks_instances::ArkGroup; use super::*; + use crate::random_oracle::RandomOracle; use ark_bls12_381::G1Projective; use rand::{thread_rng, Rng}; diff --git a/rust-src/concordium_base/src/sigma_protocols/com_enc_eq.rs b/rust-src/concordium_base/src/sigma_protocols/com_enc_eq.rs index 696bf9957..8df8c711f 100644 --- a/rust-src/concordium_base/src/sigma_protocols/com_enc_eq.rs +++ b/rust-src/concordium_base/src/sigma_protocols/com_enc_eq.rs @@ -5,7 +5,7 @@ //! Pedersen commitment. use super::common::*; -use crate::random_oracle::StructuredDigest; +use crate::random_oracle::TranscriptProtocol; use crate::{ common::*, curve_arithmetic::{multiexp, Curve, Field}, @@ -13,7 +13,6 @@ use crate::{ Cipher as ElGamalCipher, PublicKey as ElGamalPublicKey, Randomness as ElgamalRandomness, }, pedersen_commitment::{Commitment, CommitmentKey, Randomness as PedersenRandomness, Value}, - random_oracle::RandomOracle, }; use rand::*; @@ -62,7 +61,7 @@ impl SigmaProtocol for ComEncEq { type SecretData = ComEncEqSecret; #[inline] - fn public(&self, ro: &mut RandomOracle) { + fn public(&self, ro: &mut impl TranscriptProtocol) { ro.append_message("cipher", &self.cipher); ro.append_message("commitment", &self.commitment); ro.append_message("pub_key", &self.pub_key); @@ -206,6 +205,7 @@ mod tests { use super::*; use crate::elgamal::{Message, SecretKey as ElgamalSecretKey}; + use crate::random_oracle::RandomOracle; use ark_bls12_381::G1Projective; type G1 = ArkGroup; diff --git a/rust-src/concordium_base/src/sigma_protocols/com_eq.rs b/rust-src/concordium_base/src/sigma_protocols/com_eq.rs index af72c8592..fa05c0e2b 100644 --- a/rust-src/concordium_base/src/sigma_protocols/com_eq.rs +++ b/rust-src/concordium_base/src/sigma_protocols/com_eq.rs @@ -9,12 +9,11 @@ //! same type for both groups. use super::common::*; -use crate::random_oracle::StructuredDigest; +use crate::random_oracle::TranscriptProtocol; use crate::{ common::*, curve_arithmetic::{multiexp, Curve, Field}, pedersen_commitment::{Commitment, CommitmentKey, Randomness, Value}, - random_oracle::RandomOracle, }; #[derive(Clone, Debug, Eq, PartialEq, Serialize, SerdeBase16Serialize)] @@ -60,7 +59,7 @@ impl> SigmaProtocol for ComEq { type Response = Response; type SecretData = ComEqSecret; - fn public(&self, ro: &mut RandomOracle) { + fn public(&self, ro: &mut impl TranscriptProtocol) { ro.append_message("commitment", &self.commitment); ro.append_message("y", &self.y); ro.append_message("cmm_key", &self.cmm_key); @@ -158,6 +157,7 @@ mod test { use crate::curve_arithmetic::arkworks_instances::ArkGroup; use super::*; + use crate::random_oracle::RandomOracle; use ark_bls12_381::{G1Projective, G2Projective}; type G1 = ArkGroup; diff --git a/rust-src/concordium_base/src/sigma_protocols/com_eq_different_groups.rs b/rust-src/concordium_base/src/sigma_protocols/com_eq_different_groups.rs index b22247f0d..cb9f994b3 100644 --- a/rust-src/concordium_base/src/sigma_protocols/com_eq_different_groups.rs +++ b/rust-src/concordium_base/src/sigma_protocols/com_eq_different_groups.rs @@ -4,12 +4,11 @@ //! the value committed to in two commitments $C_1$ and $C_2$ in (potentially) //! two different groups (of the same order) is the same. use super::common::*; -use crate::random_oracle::StructuredDigest; +use crate::random_oracle::TranscriptProtocol; use crate::{ common::*, curve_arithmetic::{multiexp, Curve, Field}, pedersen_commitment::{Commitment, CommitmentKey, Randomness, Value}, - random_oracle::RandomOracle, }; use rand::*; @@ -46,7 +45,7 @@ impl> SigmaProtocol for ComEqDiffGroup type SecretData = ComEqDiffGroupsSecret; #[inline] - fn public(&self, ro: &mut RandomOracle) { + fn public(&self, ro: &mut impl TranscriptProtocol) { ro.append_message("commitment_1", &self.commitment_1); ro.append_message("commitment_2", &self.commitment_2); ro.append_message("cmm_key_1", &self.cmm_key_1); @@ -167,6 +166,7 @@ mod tests { use crate::curve_arithmetic::arkworks_instances::ArkGroup; use super::*; + use crate::random_oracle::RandomOracle; use ark_bls12_381::{G1Projective, G2Projective}; type G1 = ArkGroup; diff --git a/rust-src/concordium_base/src/sigma_protocols/com_eq_sig.rs b/rust-src/concordium_base/src/sigma_protocols/com_eq_sig.rs index f08741adf..5f30b8d7a 100644 --- a/rust-src/concordium_base/src/sigma_protocols/com_eq_sig.rs +++ b/rust-src/concordium_base/src/sigma_protocols/com_eq_sig.rs @@ -8,13 +8,12 @@ //! "Proof of Knowledge of a Signature" Section 5.3.5, Bluepaper v1.2.5") use super::common::*; -use crate::random_oracle::StructuredDigest; +use crate::random_oracle::TranscriptProtocol; use crate::{ common::*, curve_arithmetic::*, pedersen_commitment::{Commitment, CommitmentKey, Randomness, Value}, ps_sig::{BlindedSignature, BlindingRandomness, PublicKey as PsSigPublicKey}, - random_oracle::RandomOracle, }; use itertools::izip; use rand::*; @@ -64,10 +63,9 @@ impl> SigmaProtocol for ComEqSig

; #[inline] - fn public(&self, ro: &mut RandomOracle) { + fn public(&self, ro: &mut impl TranscriptProtocol) { ro.append_message(b"blinded_sig", &self.blinded_sig); - #[allow(deprecated)] - ro.extend_from(b"commitments", self.commitments.iter()); + ro.append_messages(b"commitments", self.commitments.iter()); ro.append_message(b"ps_pub_key", &self.ps_pub_key); ro.append_message(b"comm_key", &self.comm_key) } @@ -301,6 +299,7 @@ mod tests { use ark_bls12_381::G1Projective; use super::*; + use crate::random_oracle::RandomOracle; use crate::{ curve_arithmetic::arkworks_instances::ArkGroup, ps_sig::{SecretKey as PsSigSecretKey, Signature}, diff --git a/rust-src/concordium_base/src/sigma_protocols/com_ineq.rs b/rust-src/concordium_base/src/sigma_protocols/com_ineq.rs index 8c56bafe2..a0c074f4f 100644 --- a/rust-src/concordium_base/src/sigma_protocols/com_ineq.rs +++ b/rust-src/concordium_base/src/sigma_protocols/com_ineq.rs @@ -14,7 +14,7 @@ use super::{ com_mult::{ComMult, ComMultSecret, Response as ComMultResponse}, common::{prove as sigma_prove, verify as sigma_verify, SigmaProof}, }; -use crate::random_oracle::StructuredDigest; +use crate::random_oracle::TranscriptProtocol; use crate::{ common::*, curve_arithmetic::{Curve, Field}, diff --git a/rust-src/concordium_base/src/sigma_protocols/com_lin.rs b/rust-src/concordium_base/src/sigma_protocols/com_lin.rs index bfead357f..84048ed53 100644 --- a/rust-src/concordium_base/src/sigma_protocols/com_lin.rs +++ b/rust-src/concordium_base/src/sigma_protocols/com_lin.rs @@ -5,12 +5,12 @@ //! The r's are randomness in commitments to s_i's and s'. use super::common::*; -use crate::random_oracle::StructuredDigest; +use crate::random_oracle::TranscriptProtocol; use crate::{ common::*, curve_arithmetic::{multiexp, Curve, Field}, pedersen_commitment::{Commitment, CommitmentKey, Randomness, Value}, - random_oracle::{Challenge, RandomOracle}, + random_oracle::Challenge, }; use itertools::izip; @@ -56,11 +56,9 @@ impl SigmaProtocol for ComLin { type Response = Response; type SecretData = ComLinSecret; - fn public(&self, ro: &mut RandomOracle) { - #[allow(deprecated)] - ro.extend_from(b"us", self.us.iter()); - #[allow(deprecated)] - ro.extend_from(b"cmms", self.cmms.iter()); + fn public(&self, ro: &mut impl TranscriptProtocol) { + ro.append_messages(b"us", self.us.iter()); + ro.append_messages(b"cmms", self.cmms.iter()); ro.append_message(b"cmm", &self.cmm); ro.append_message(b"cmm_key", &self.cmm_key) } @@ -224,6 +222,7 @@ mod tests { use super::*; use crate::curve_arithmetic::PrimeField; + use crate::random_oracle::RandomOracle; use rand::thread_rng; use std::str::FromStr; diff --git a/rust-src/concordium_base/src/sigma_protocols/com_mult.rs b/rust-src/concordium_base/src/sigma_protocols/com_mult.rs index dd477de60..34809ef01 100644 --- a/rust-src/concordium_base/src/sigma_protocols/com_mult.rs +++ b/rust-src/concordium_base/src/sigma_protocols/com_mult.rs @@ -4,12 +4,12 @@ //! committed values is equal to the third committed value, without revealing //! the values themselves. use super::common::*; -use crate::random_oracle::StructuredDigest; +use crate::random_oracle::TranscriptProtocol; use crate::{ common::*, curve_arithmetic::{multiexp, Curve, Field}, pedersen_commitment::{Commitment, CommitmentKey, Randomness, Value}, - random_oracle::{Challenge, RandomOracle}, + random_oracle::Challenge, }; use itertools::izip; @@ -46,9 +46,8 @@ impl SigmaProtocol for ComMult { type SecretData = ComMultSecret; #[inline] - fn public(&self, ro: &mut RandomOracle) { - #[allow(deprecated)] - ro.extend_from(b"cmms", self.cmms.iter()); + fn public(&self, ro: &mut impl TranscriptProtocol) { + ro.append_messages(b"cmms", self.cmms.iter()); ro.append_message(b"cmm_key", &self.cmm_key) } @@ -177,6 +176,7 @@ mod tests { use crate::curve_arithmetic::arkworks_instances::ArkGroup; use super::*; + use crate::random_oracle::RandomOracle; use ark_bls12_381::G1Projective; use rand::thread_rng; diff --git a/rust-src/concordium_base/src/sigma_protocols/common.rs b/rust-src/concordium_base/src/sigma_protocols/common.rs index 02d432df1..6d8b20609 100644 --- a/rust-src/concordium_base/src/sigma_protocols/common.rs +++ b/rust-src/concordium_base/src/sigma_protocols/common.rs @@ -20,7 +20,7 @@ pub trait SigmaProtocol: Sized { type SecretData; /// Given a random oracle, feed it all of the public input of this instance. - fn public(&self, ro: &mut RandomOracle); + fn public(&self, ro: &mut impl TranscriptProtocol); /// Compute the first message of the prover. We allow this function /// to return 'None' if the inputs are inconsistent. @@ -107,7 +107,7 @@ impl SigmaProtocol for AndAdapter type Response = AndResponse; type SecretData = (P1::SecretData, P2::SecretData); - fn public(&self, ro: &mut RandomOracle) { + fn public(&self, ro: &mut impl TranscriptProtocol) { self.first.public(ro); self.second.public(ro) } @@ -214,9 +214,9 @@ impl SigmaProtocol for ReplicateAdapter

{ type Response = ReplicateResponse; type SecretData = Vec; - fn public(&self, ro: &mut RandomOracle) { + fn public(&self, ro: &mut impl TranscriptProtocol) { // add all public data in sequence from left to right - self.protocols.iter().for_each(|p| p.public(ro)) + ro.append_each_message(&[], &self.protocols, |ro, p| p.public(ro)); } fn compute_commit_message( @@ -299,7 +299,7 @@ impl ReplicateAdapter

{ /// oracle), produce a sigma proof and update the context. This function can /// return 'None' if the input data is inconsistent. pub fn prove( - ro: &mut RandomOracle, + ro: &mut impl TranscriptProtocol, prover: &D, secret: D::SecretData, csprng: &mut R, @@ -309,9 +309,10 @@ pub fn prove( // For legacy reasons the label `point` is used when adding the commit message // to the RO ro.append_message("point", &commit_message); - let challenge_bytes = ro.split().get_challenge(); + let challenge_bytes = ro.extract_raw_challenge(); let challenge = prover.get_challenge(&challenge_bytes); let response = prover.compute_response(secret, state, &challenge)?; + ro.append_final_prover_message("response", &response); // todo ar try trigger stability tests Some(SigmaProof { challenge: challenge_bytes, response, @@ -321,7 +322,7 @@ pub fn prove( /// Given a single sigma proof and a context in the form of an instantiated /// random oracle, verify the sigma proof and update the state of the context. pub fn verify( - ro: &mut RandomOracle, + ro: &mut impl TranscriptProtocol, verifier: &D, proof: &SigmaProof, ) -> bool { @@ -331,7 +332,8 @@ pub fn verify( Some(ref point) => { verifier.public(ro); ro.append_message("point", &point); - let computed_challenge = ro.split().get_challenge(); + let computed_challenge = ro.extract_raw_challenge(); + ro.append_final_prover_message("response", &proof.response); // todo ar try trigger stability tests computed_challenge == proof.challenge } } diff --git a/rust-src/concordium_base/src/sigma_protocols/dlog.rs b/rust-src/concordium_base/src/sigma_protocols/dlog.rs index e1d7321b4..48f599330 100644 --- a/rust-src/concordium_base/src/sigma_protocols/dlog.rs +++ b/rust-src/concordium_base/src/sigma_protocols/dlog.rs @@ -3,11 +3,11 @@ //! v1.2.5) which enables one to prove knowledge of the discrete logarithm //! without revealing it. use super::common::*; -use crate::random_oracle::StructuredDigest; +use crate::random_oracle::TranscriptProtocol; use crate::{ common::*, curve_arithmetic::{Curve, Field, Value}, - random_oracle::{Challenge, RandomOracle}, + random_oracle::Challenge, }; pub struct Dlog { @@ -38,7 +38,7 @@ impl SigmaProtocol for Dlog { type Response = Response; type SecretData = DlogSecret; - fn public(&self, ro: &mut RandomOracle) { + fn public(&self, ro: &mut impl TranscriptProtocol) { ro.append_message("public", &self.public); ro.append_message("coeff", &self.coeff) } @@ -104,6 +104,7 @@ mod tests { use crate::curve_arithmetic::arkworks_instances::ArkGroup; use super::*; + use crate::random_oracle::RandomOracle; use ark_bls12_381::G1Projective; type G1 = ArkGroup; diff --git a/rust-src/concordium_base/src/sigma_protocols/dlogaggequal.rs b/rust-src/concordium_base/src/sigma_protocols/dlogaggequal.rs index f7346b6dc..d5fc3727f 100644 --- a/rust-src/concordium_base/src/sigma_protocols/dlogaggequal.rs +++ b/rust-src/concordium_base/src/sigma_protocols/dlogaggequal.rs @@ -6,10 +6,11 @@ //! This module is currently not used, and is only here as a reference. //! When using the code needs to be thoroughly reviewed. +use crate::random_oracle::TranscriptProtocol; use crate::{ common::*, curve_arithmetic::{multiexp, Curve, Field}, - random_oracle::{Challenge, RandomOracle}, + random_oracle::Challenge, sigma_protocols::{aggregate_dlog::*, common::*, dlog::*}, }; use itertools::izip; @@ -35,8 +36,8 @@ impl SigmaProtocol for DlogAndAggregateDlogsEqual { type Response = Response; type SecretData = (Rc, Vec>>); - fn public(&self, ro: &mut RandomOracle) { - self.aggregate_dlogs.iter().for_each(|p| p.public(ro)); + fn public(&self, ro: &mut impl TranscriptProtocol) { + ro.append_each_message(&[], &self.aggregate_dlogs, |ro, p| p.public(ro)); self.dlog.public(ro) } @@ -147,6 +148,7 @@ impl SigmaProtocol for DlogAndAggregateDlogsEqual { #[cfg(test)] mod test { use super::*; + use crate::random_oracle::RandomOracle; use crate::{ curve_arithmetic::multiexp, id::constants::{ArCurve, BaseField}, diff --git a/rust-src/concordium_base/src/sigma_protocols/dlogeq.rs b/rust-src/concordium_base/src/sigma_protocols/dlogeq.rs index 573a57763..be0a7c6e3 100644 --- a/rust-src/concordium_base/src/sigma_protocols/dlogeq.rs +++ b/rust-src/concordium_base/src/sigma_protocols/dlogeq.rs @@ -4,9 +4,10 @@ //! NB: This module is not used by the rest of the project and is only here for //! demonstration purposes. //! If it becomes necessary to use it, the code needs to be thoroughly reviewed. +use crate::random_oracle::TranscriptProtocol; use crate::{ curve_arithmetic::Curve, - random_oracle::{Challenge, RandomOracle}, + random_oracle::Challenge, sigma_protocols::{ common::*, dlog::{Response as DlogResponse, *}, @@ -25,7 +26,7 @@ impl SigmaProtocol for DlogEqual { type Response = DlogResponse; type SecretData = DlogSecret; - fn public(&self, ro: &mut RandomOracle) { + fn public(&self, ro: &mut impl TranscriptProtocol) { self.dlog1.public(ro); self.dlog2.public(ro) } @@ -84,6 +85,7 @@ mod test { }; use rand::*; + use crate::random_oracle::RandomOracle; use std::str::FromStr; type G1 = ArCurve; diff --git a/rust-src/concordium_base/src/sigma_protocols/enc_trans.rs b/rust-src/concordium_base/src/sigma_protocols/enc_trans.rs index 22bb75199..3fbc8791b 100644 --- a/rust-src/concordium_base/src/sigma_protocols/enc_trans.rs +++ b/rust-src/concordium_base/src/sigma_protocols/enc_trans.rs @@ -52,14 +52,14 @@ use super::{ common::*, dlog::*, }; -use crate::random_oracle::StructuredDigest; +use crate::random_oracle::TranscriptProtocol; use crate::{ common::*, curve_arithmetic::{multiexp, Curve, Field}, elgamal::ChunkSize, encrypted_transfers::types::CHUNK_SIZE, pedersen_commitment::{Randomness as PedersenRandomness, Value}, - random_oracle::{Challenge, RandomOracle}, + random_oracle::Challenge, }; use itertools::izip; use std::rc::Rc; @@ -76,10 +76,9 @@ pub struct ElgDec { } impl ElgDec { - fn public(&self, ro: &mut RandomOracle) { + fn public(&self, ro: &mut impl TranscriptProtocol) { ro.append_message(b"public", &self.public); - #[allow(deprecated)] - ro.extend_from(b"coeff", &self.coeff) + ro.append_messages(b"coeff", &self.coeff) } } @@ -182,10 +181,10 @@ impl SigmaProtocol for EncTrans { type Response = EncTransResponse; type SecretData = EncTransSecret; - fn public(&self, ro: &mut RandomOracle) { + fn public(&self, ro: &mut impl TranscriptProtocol) { self.elg_dec.public(ro); - self.encexp1.iter().for_each(|p| p.public(ro)); - self.encexp2.iter().for_each(|p| p.public(ro)); + ro.append_each_message(&[], &self.encexp1, |ro, p| p.public(ro)); + ro.append_each_message(&[], &self.encexp2, |ro, p| p.public(ro)); self.dlog.public(ro) } @@ -365,6 +364,7 @@ impl SigmaProtocol for EncTrans { #[cfg(test)] mod tests { use super::*; + use crate::random_oracle::RandomOracle; use crate::{ curve_arithmetic::arkworks_instances::ArkGroup, elgamal::{PublicKey, Randomness, SecretKey}, diff --git a/rust-src/concordium_base/src/sigma_protocols/ps_sig_known.rs b/rust-src/concordium_base/src/sigma_protocols/ps_sig_known.rs index 73fb37bf3..4609f91a5 100644 --- a/rust-src/concordium_base/src/sigma_protocols/ps_sig_known.rs +++ b/rust-src/concordium_base/src/sigma_protocols/ps_sig_known.rs @@ -22,14 +22,13 @@ use crate::common::{Buffer, Deserial, Get, ParseResult, Put, Serial}; use crate::curve_arithmetic::{Curve, Field, Pairing, Secret}; -use crate::random_oracle::StructuredDigest; +use crate::random_oracle::TranscriptProtocol; use crate::sigma_protocols::common::SigmaProtocol; use crate::{ curve_arithmetic, pedersen_commitment::{Commitment, CommitmentKey, Randomness, Value}, ps_sig, ps_sig::BlindedSignature, - random_oracle::RandomOracle, }; use byteorder::ReadBytesExt; use concordium_base_derive::Serialize; @@ -169,8 +168,8 @@ impl> SigmaProtocol for PsSigKnown type SecretData = PsSigWitness; #[inline] - fn public(&self, ro: &mut RandomOracle) { - ro.add_bytes("PsSigKnown"); + fn public(&self, ro: &mut impl TranscriptProtocol) { + ro.append_label("PsSigKnown"); // public input to statement: ro.append_message("blinded_sig", &self.blinded_sig); ro.append_message("messages", &self.msgs); @@ -441,6 +440,7 @@ mod tests { type G1 = ArkGroup; type Bls12 = ark_ec::models::bls12::Bls12; use crate::ps_sig::{SigRetrievalRandomness, UnknownMessage}; + use crate::random_oracle::RandomOracle; use crate::sigma_protocols::common::SigmaProof; #[derive(Debug, Clone, Copy)] diff --git a/rust-src/concordium_base/src/sigma_protocols/vcom_eq.rs b/rust-src/concordium_base/src/sigma_protocols/vcom_eq.rs index 4d05f1583..c81a50b4c 100644 --- a/rust-src/concordium_base/src/sigma_protocols/vcom_eq.rs +++ b/rust-src/concordium_base/src/sigma_protocols/vcom_eq.rs @@ -4,12 +4,12 @@ //! \prod_{i=1}^n g_i^{x_i}$ and $C_i = \bar{g}^{x_i} \bar{h}^{r_i}$ for $i\in //! I$. use super::common::*; -use crate::random_oracle::StructuredDigest; +use crate::random_oracle::TranscriptProtocol; use crate::{ common::*, curve_arithmetic::{multiexp, Curve, Field}, pedersen_commitment::{Commitment, Value}, - random_oracle::{Challenge, RandomOracle}, + random_oracle::Challenge, }; use itertools::izip; use std::collections::BTreeMap; @@ -57,11 +57,10 @@ impl SigmaProtocol for VecComEq { type Response = Response; type SecretData = (Vec, Value, BTreeMap>); - fn public(&self, ro: &mut RandomOracle) { + fn public(&self, ro: &mut impl TranscriptProtocol) { ro.append_message(b"C", &self.comm); ro.append_message(b"Cis", &self.comms); - #[allow(deprecated)] - ro.extend_from(b"gis", &self.gis); + ro.append_messages(b"gis", &self.gis); ro.append_message(b"h", &self.h); ro.append_message("h_bar", &self.h_bar); ro.append_message("g_bar", &self.g_bar) @@ -225,6 +224,7 @@ mod tests { use crate::curve_arithmetic::arkworks_instances::ArkGroup; use super::*; + use crate::random_oracle::RandomOracle; use ark_bls12_381::G1Projective; use rand::{thread_rng, Rng}; diff --git a/rust-src/concordium_base/src/web3id/proofs.rs b/rust-src/concordium_base/src/web3id/proofs.rs index 9faefdb4a..514c6ea95 100644 --- a/rust-src/concordium_base/src/web3id/proofs.rs +++ b/rust-src/concordium_base/src/web3id/proofs.rs @@ -1,4 +1,4 @@ -use crate::random_oracle::StructuredDigest; +use crate::random_oracle::TranscriptProtocol; use crate::{ curve_arithmetic::Curve, id::types::{Attribute, GlobalContext}, diff --git a/rust-src/concordium_base/src/web3id/v1/proofs.rs b/rust-src/concordium_base/src/web3id/v1/proofs.rs index 56743860d..ac7ab0bbd 100644 --- a/rust-src/concordium_base/src/web3id/v1/proofs.rs +++ b/rust-src/concordium_base/src/web3id/v1/proofs.rs @@ -1,4 +1,3 @@ -use crate::random_oracle::StructuredDigest; use crate::{ curve_arithmetic::Curve, id::types::{Attribute, GlobalContext}, @@ -18,6 +17,7 @@ use crate::id::types::{ IdentityAttributesCredentialsInfo, IdentityAttributesCredentialsValues, IpContextOnly, }; use crate::pedersen_commitment::Commitment; +use crate::random_oracle::TranscriptProtocol; use crate::web3id::v1::{ AccountBasedCredentialV1, AccountBasedSubjectClaims, AccountCredentialProofPrivateInputs, AccountCredentialProofs, AccountCredentialSubject, AccountCredentialVerificationMaterial, @@ -515,8 +515,8 @@ impl> RequestV1 } } -fn append_context(digest: &mut impl StructuredDigest, context: &ContextInformation) { - digest.add_bytes("ConcordiumContextInformationV1"); +fn append_context(digest: &mut impl TranscriptProtocol, context: &ContextInformation) { + digest.append_label("ConcordiumContextInformationV1"); digest.append_message("given", &context.given); digest.append_message("requested", &context.requested); } From 4fb017ef8e6425f0e5cb9ffccf531b3fe5e12200 Mon Sep 17 00:00:00 2001 From: Allan Rasmussen Date: Tue, 25 Nov 2025 11:12:37 +0100 Subject: [PATCH 02/20] doc --- .../concordium_base/src/random_oracle/mod.rs | 121 ++++++++---------- 1 file changed, 52 insertions(+), 69 deletions(-) diff --git a/rust-src/concordium_base/src/random_oracle/mod.rs b/rust-src/concordium_base/src/random_oracle/mod.rs index c64b1efe6..25978c1ea 100644 --- a/rust-src/concordium_base/src/random_oracle/mod.rs +++ b/rust-src/concordium_base/src/random_oracle/mod.rs @@ -3,7 +3,7 @@ //! It plays the same role as a random oracle would play in the corresponding interactive protocol, //! hence the name of the present module and some of the types in the module. //! -//! For background, see "9.3 Non-interactive Proofs using the Fiat-Shamir Transformation" in tbe blue paper. +//! For background, see "9.3 Non-interactive Proofs using the Fiat-Shamir Transformation" in the blue paper. //! For understanding the general concepts and the considerations put into a transcript implementation, //! the Merlin transcript can be studied here: (implemented at ). //! @@ -13,8 +13,10 @@ //! //! For each proof, protocols should update the state of the transcript with public input //! and implicit public values, and each message send by prover, including the final message -//! send by the prover. Proofs can be be sequentially composed, see . -//! It is specifically because of sequential composition, that it is important that also the final message send by the prover is added to the transcript. +//! send by the prover. This is part of ensuring soundness and non-malleability of the proof systems +//! that has undergone the Fiat-Shamir transformation. +//! Proofs can be sequentially composed, see . +//! It is specifically because of sequential composition, that we also add the final message send by the prover in each sub-proof to the transcript. //! //! Verifier messages (the challenges) in the proof should be extracted from the transcript instance. //! It is in this extraction, that the transcript plays the role of a random oracle. @@ -22,7 +24,6 @@ //! The transcript instance used to verify a proof needs to be initialised and updated //! with the same input used to produce the proof. Any verification of sub-proofs //! needs to be performed in the same order as when producing the proof. -//! See //! //! Part of a transcript protocol (see ) is defining //! how messages of types defined by the protocol (often mathematical objects) are encoded to message bytes and how @@ -38,7 +39,7 @@ //! //! ``` //! # use concordium_base::random_oracle::{TranscriptProtocol, TranscriptV1}; -//! let mut transcript = TranscriptV1::with_domain("Proof of something"); +//! let mut transcript = TranscriptV1::with_domain("ProofOfSomething"); //! // ... //! transcript.append_label("Subproof1"); //! // ... @@ -83,7 +84,7 @@ //! to define the data message bytes. //! //! ```rust,ignore -//! # use concordium_base::random_oracle::{StructuredDigest, RandomOracle}; +//! # use concordium_base::random_oracle::{TranscriptProtocol, TranscriptV1}; //! # use concordium_base::common::{Serialize}; //! //! #[derive(Serialize)] @@ -97,8 +98,8 @@ //! field_2: 2u8, //! }; //! -//! let mut transcript = RandomOracle::empty(); -//! transcript.append_message(b"Type1", &example); +//! let mut transcript = TranscriptV1::with_domain("ProofOfSomething"); +//! transcript.append_message("Type1", &example); //!``` //! //! # Caution: Ambiguous variable-length data @@ -139,7 +140,7 @@ //! //!``` //! # use concordium_base::random_oracle::{TranscriptProtocol, TranscriptV1}; -//! let mut transcript = TranscriptV1::with_domain("Proof of something"); +//! let mut transcript = TranscriptV1::with_domain("ProofOfSomething"); //! let string = "abc".to_string(); //! // The serialization implementation of the `String` type prepends the length of the field values. //! transcript.append_message("String1", &string); @@ -151,7 +152,7 @@ //! //!``` //! # use concordium_base::random_oracle::{TranscriptProtocol, TranscriptV1}; -//! let mut transcript = TranscriptV1::with_domain("Proof of something"); +//! let mut transcript = TranscriptV1::with_domain("ProofOfSomething"); //! let collection = vec![2,3,4]; //! transcript.append_message("Collection1", &collection); //! ``` @@ -171,7 +172,7 @@ //! //! let vec = vec![Type1, Type1]; //! -//! let mut transcript = TranscriptV1::with_domain("Proof of something"); +//! let mut transcript = TranscriptV1::with_domain("ProofOfSomething"); //! transcript.append_each_message("Collection", &vec, |transcript, item| { //! append_type1(transcript, item); //! }); @@ -190,7 +191,7 @@ //! Variant_1 //! } //! -//! let mut transcript = TranscriptV1::with_domain("Proof of something"); +//! let mut transcript = TranscriptV1::with_domain("ProofOfSomething"); //! //! transcript.append_label("Enum1"); //! transcript.append_label("Variant_0"); @@ -283,37 +284,31 @@ impl PartialEq for RandomOracle { } } -// todo ar finish doc -/// Transcript protocol that defines how messages and challenges are encoded to and -/// decoded from bytes. -/// The transcript protocol also encourages doing domain separation and labelling data, -/// and helps handling structured data in the right way -/// -/// This is largely done using the [`Serial`] +/// The transcript protocol defines how messages and challenges are encoded to bytes and +/// decoded from bytes. This is largely done using the [`Serial`] /// and [`Deserial`] implementations on the message and challenge types. +/// The transcript protocol also encourages doing domain separation and labeling data. +/// See for a description of the concept of a transcript protocol +/// and the [module documentation](self) for further description. /// -/// See for a description of the concept of a transcript protocol. -/// -/// This is done e.g. by applying length prefixes for variable-length data and -/// prefixing variants with a discriminator. -/// And by labelling types and fields for domain separation. Both are done to prevent malleability -/// in the proofs where the oracle is used. -/// -/// Using [`Serial`] is one of the approaches to correctly produce the message -/// bytes for variable-length types (including enums), since the corresponding [`Deserial`] -/// implementation guarantees the message bytes are unique for the data. Notice that using [`Serial`] -/// does not label types or fields in the nested data. +/// Part of the responsibility of the transcript protocol is to apply length prefixes for variable-length data and +/// prefixing data variants with a variant discriminator. Using [`Serial`] is one of the approaches to achieve this, +/// since the corresponding [`Deserial`] implementation guarantees the message bytes are unique for the data, +/// and hence naturally length and discriminator prefixed. Notice that the "legacy" implementation +/// [`RandomOracle`] does not properly length prefix all variable length data, hence the implementation [`TranscriptV1`] should +/// be used in new proofs systems and new proof versions. pub trait TranscriptProtocol { - /// Add domain separating label to the digest. The label bytes will be prepended with the bytes length. + /// Add domain separating label to the digest. fn append_label(&mut self, label: impl AsRef<[u8]>); /// Append the given data as the message bytes produced by its [`Serial`] implementation to the transcript. /// The given label is appended first as domain separation. Notice that a slice, `Vec` and several other collections of - /// items implementing [`Serial`] itself implements [`Serial`]. When serializing variable-length - /// types or collection types, the length or size will be prepended in the serialization. + /// items implementing [`Serial`] itself implements [`Serial`], to those collection types can be used as messages. fn append_message(&mut self, label: impl AsRef<[u8]>, message: &impl Serial); - // todo ar finish doc + /// Append the given items as the message bytes produced by its [`Serial`] implementation to the transcript. + /// The given label is appended first as domain separation. Notice that a slice, `Vec` and several other collections of + /// items implementing [`Serial`] itself implements [`Serial`], so for those types [`Self::append_message`] can be used. fn append_messages<'a, T: Serial + 'a, B: IntoIterator>( &mut self, label: impl AsRef<[u8]>, @@ -321,11 +316,13 @@ pub trait TranscriptProtocol { ) where B::IntoIter: ExactSizeIterator; - // todo ar finish doc + /// Append the final prover message in sub-proofs like sigma protocols and bullet proofs. The method + /// is equivalent to [`Self::append_message`] but is here to distinguish the final prover message. + /// This is needed since the "legacy" implementation [`RandomOracle`] does not include this final message in transcripts. fn append_final_prover_message(&mut self, label: impl AsRef<[u8]>, message: &impl Serial); - /// Append the items in the given iterator using the `append_item` closure to the state of the oracle. - /// The given label is appended first as domain separation followed by the length of the iterator. + /// Append the items in the given iterator using the `append_item` closure to the transcript. + /// The given label is appended first as domain separation. fn append_each_message>( &mut self, label: impl AsRef<[u8]>, @@ -334,10 +331,11 @@ pub trait TranscriptProtocol { ) where B::IntoIter: ExactSizeIterator; - // todo ar finish doc + // Extract curve scalar from the transcript. Additionally, the given label is appended + // to the transcript before extracting the scalar. fn extract_challenge_scalar(&mut self, label: impl AsRef<[u8]>) -> C::Scalar; - // todo ar finish doc + /// Extract raw challenge bytes from the transcript. fn extract_raw_challenge(&self) -> Challenge; } @@ -365,7 +363,7 @@ impl TranscriptProtocol for RandomOracle { } fn append_final_prover_message(&mut self, _label: impl AsRef<[u8]>, _message: &impl Serial) { - // not added in V0 + // not added in RandomOracle } fn append_each_message>( @@ -448,6 +446,7 @@ impl RandomOracle { } } +/// Implements [`Buffer`] by wrapping a type implementing [`Write`] struct BufferAdapter(T); impl Write for BufferAdapter { @@ -551,7 +550,7 @@ impl TranscriptV1 { transcript } - /// Duplicate the transcript, creating a fresh copy of it. + /// Duplicate the transcript, creating a new copy of it. /// Further updates are independent. pub fn split(&self) -> Self { TranscriptV1(self.0.clone()) @@ -638,7 +637,7 @@ mod tests { } /// Test that we don't accidentally change the digest produced - /// by [`TranscriptProtocol::append_label`] + /// by [`::append_label`] #[test] pub fn test_v0_append_label_stable() { let mut ro = RandomOracle::empty(); @@ -652,7 +651,7 @@ mod tests { } /// Test that we don't accidentally change the digest produced - /// by [`TranscriptProtocol::append_message`] + /// by [`::append_message`] #[test] pub fn test_v0_append_message_stable() { let mut ro = RandomOracle::empty(); @@ -666,10 +665,9 @@ mod tests { } /// Test that we don't accidentally change the digest produced - /// by [`TranscriptProtocol::append_messages`] and [`RandomOracle::extend_from`] + /// by [`::append_messages`] and [`RandomOracle::extend_from`] #[test] pub fn test_v0_append_messages_stable() { - // todo ar copy to main let mut ro = RandomOracle::empty(); ro.append_messages("Label1", &vec![1u8, 2, 3]); @@ -690,7 +688,7 @@ mod tests { } /// Test that we don't accidentally change the digest produced - /// by [`TranscriptProtocol::append_final_prover_message`] + /// by [`::append_final_prover_message`] #[test] pub fn test_v0_append_final_prover_message_stable() { let mut ro = RandomOracle::empty(); @@ -704,7 +702,7 @@ mod tests { } /// Test that we don't accidentally change the scalar produced - /// by [`TranscriptProtocol::extract_challenge_scalar`] + /// by [`::extract_challenge_scalar`] #[test] pub fn test_v0_extract_challenge_scalar_stable() { let ro = RandomOracle::empty(); @@ -727,22 +725,7 @@ mod tests { } /// Test that we don't accidentally change the digest produced - /// by [`RandomOracle::extend_from`] - #[test] - pub fn test_extend_from_stable() { - let mut ro = RandomOracle::empty(); - #[allow(deprecated)] - ro.extend_from("Label1", &vec![1u8, 2, 3]); - - let challenge_hex = hex::encode(ro.get_challenge()); - assert_eq!( - challenge_hex, - "6b1addb1c08e887242f5e78127c31c17851f29349c45aa415adce255f95fd292" - ); - } - - /// Test that we don't accidentally change the digest produced - /// by [`TranscriptProtocol::append_message`] + /// by [`::append_each_message`] #[test] pub fn test_v0_append_each_message_stable() { let mut ro = RandomOracle::empty(); @@ -771,7 +754,7 @@ mod tests { } /// Test that we don't accidentally change the digest produced - /// by [`TranscriptProtocol::append_label`] + /// by [`::append_label`] #[test] pub fn test_v1_append_label_stable() { let mut ro = TranscriptV1::with_domain("Domain1"); @@ -785,7 +768,7 @@ mod tests { } /// Test that we don't accidentally change the digest produced - /// by [`TranscriptProtocol::append_message`] + /// by [`::append_message`] #[test] pub fn test_v1_append_message_stable() { let mut ro = TranscriptV1::with_domain("Domain1"); @@ -799,7 +782,7 @@ mod tests { } /// Test that we don't accidentally change the digest produced - /// by [`TranscriptProtocol::append_messages`] + /// by [`::append_messages`] #[test] pub fn test_v1_append_messages_stable() { let mut ro = TranscriptV1::with_domain("Domain1"); @@ -813,7 +796,7 @@ mod tests { } /// Test that we don't accidentally change the digest produced - /// by [`TranscriptProtocol::append_final_prover_message`] + /// by [`::append_final_prover_message`] #[test] pub fn test_v1_append_final_prover_message_stable() { let mut ro = TranscriptV1::with_domain("Domain1"); @@ -827,7 +810,7 @@ mod tests { } /// Test that we don't accidentally change the scalar produced - /// by [`TranscriptProtocol::extract_challenge_scalar`] + /// by [`::extract_challenge_scalar`] #[test] pub fn test_v1_extract_challenge_scalar_stable() { let ro = TranscriptV1::with_domain("Domain1"); @@ -842,7 +825,7 @@ mod tests { } /// Test that we don't accidentally change the digest produced - /// by [`TranscriptProtocol::append_message`] + /// by [`::append_each_message`] #[test] pub fn test_v1_append_each_message_stable() { let mut ro = TranscriptV1::with_domain("Domain1"); From e62be07dbfa21e5b644aa871fcd503e717ee8ba2 Mon Sep 17 00:00:00 2001 From: Allan Rasmussen Date: Tue, 25 Nov 2025 11:25:00 +0100 Subject: [PATCH 03/20] fix --- .../src/id/identity_attributes_credentials.rs | 12 ++-- .../concordium_base/src/random_oracle/mod.rs | 66 +++++++++---------- 2 files changed, 39 insertions(+), 39 deletions(-) diff --git a/rust-src/concordium_base/src/id/identity_attributes_credentials.rs b/rust-src/concordium_base/src/id/identity_attributes_credentials.rs index ebc1c38fe..737f6f2d6 100644 --- a/rust-src/concordium_base/src/id/identity_attributes_credentials.rs +++ b/rust-src/concordium_base/src/id/identity_attributes_credentials.rs @@ -181,9 +181,9 @@ pub fn prove_identity_attributes< // IdentityAttributesCommitmentValues struct. // This should make the proof non-reusable. // We should add the genesis hash also at some point - transcript.append_label("IdentityAttributesCredentials"); - transcript.append_message("IdentityAttributeValues", &id_attribute_values); - transcript.append_message("GlobalContext", &global_context); + transcript.append_label(b"IdentityAttributesCredentials"); + transcript.append_message(b"identity_attribute_values", &id_attribute_values); + transcript.append_message(b"global_context", &global_context); let proof = sigma_protocols::common::prove(transcript, &prover, witness, csprng) .context("cannot produce zero knowledge proof")?; @@ -413,9 +413,9 @@ pub fn verify_identity_attributes< } // Compute the challenge prefix by hashing the values. - transcript.append_label("IdentityAttributesCredentials"); - transcript.append_message("IdentityAttributeValues", &id_attr_info.values); - transcript.append_message("GlobalContext", &global_context); + transcript.append_label(b"IdentityAttributesCredentials"); + transcript.append_message(b"identity_attribute_values", &id_attr_info.values); + transcript.append_message(b"global_context", &global_context); let verifier_sig = signature_knowledge_verifier( &global_context.on_chain_commitment_key, diff --git a/rust-src/concordium_base/src/random_oracle/mod.rs b/rust-src/concordium_base/src/random_oracle/mod.rs index 25978c1ea..d75d2edec 100644 --- a/rust-src/concordium_base/src/random_oracle/mod.rs +++ b/rust-src/concordium_base/src/random_oracle/mod.rs @@ -38,8 +38,8 @@ //! or nested proofs should also be labelled for domain separation. //! //! ``` -//! # use concordium_base::random_oracle::{TranscriptProtocol, TranscriptV1}; -//! let mut transcript = TranscriptV1::with_domain("ProofOfSomething"); +//! # use concordium_base::random_oracle::{TranscriptProtocol, TranscriptProtocolV1}; +//! let mut transcript = TranscriptProtocolV1::with_domain("ProofOfSomething"); //! // ... //! transcript.append_label("Subproof1"); //! // ... @@ -84,7 +84,7 @@ //! to define the data message bytes. //! //! ```rust,ignore -//! # use concordium_base::random_oracle::{TranscriptProtocol, TranscriptV1}; +//! # use concordium_base::random_oracle::{TranscriptProtocol, TranscriptProtocolV1}; //! # use concordium_base::common::{Serialize}; //! //! #[derive(Serialize)] @@ -98,7 +98,7 @@ //! field_2: 2u8, //! }; //! -//! let mut transcript = TranscriptV1::with_domain("ProofOfSomething"); +//! let mut transcript = TranscriptProtocolV1::with_domain("ProofOfSomething"); //! transcript.append_message("Type1", &example); //!``` //! @@ -139,8 +139,8 @@ //! Serialization of variable-length primitives like `String` will prepend the length. //! //!``` -//! # use concordium_base::random_oracle::{TranscriptProtocol, TranscriptV1}; -//! let mut transcript = TranscriptV1::with_domain("ProofOfSomething"); +//! # use concordium_base::random_oracle::{TranscriptProtocol, TranscriptProtocolV1}; +//! let mut transcript = TranscriptProtocolV1::with_domain("ProofOfSomething"); //! let string = "abc".to_string(); //! // The serialization implementation of the `String` type prepends the length of the field values. //! transcript.append_message("String1", &string); @@ -151,8 +151,8 @@ //! Serialization of collections like `Vec` will prepend the size of the collection. //! //!``` -//! # use concordium_base::random_oracle::{TranscriptProtocol, TranscriptV1}; -//! let mut transcript = TranscriptV1::with_domain("ProofOfSomething"); +//! # use concordium_base::random_oracle::{TranscriptProtocol, TranscriptProtocolV1}; +//! let mut transcript = TranscriptProtocolV1::with_domain("ProofOfSomething"); //! let collection = vec![2,3,4]; //! transcript.append_message("Collection1", &collection); //! ``` @@ -162,7 +162,7 @@ //! Digesting a variable number of items without relying on `Serial` implementation on the items: //! //!``` -//! # use concordium_base::random_oracle::{TranscriptProtocol, TranscriptV1}; +//! # use concordium_base::random_oracle::{TranscriptProtocol, TranscriptProtocolV1}; //! //! struct Type1; //! @@ -172,7 +172,7 @@ //! //! let vec = vec![Type1, Type1]; //! -//! let mut transcript = TranscriptV1::with_domain("ProofOfSomething"); +//! let mut transcript = TranscriptProtocolV1::with_domain("ProofOfSomething"); //! transcript.append_each_message("Collection", &vec, |transcript, item| { //! append_type1(transcript, item); //! }); @@ -184,14 +184,14 @@ //! to the transcript followed by the variant data. //! //!``` -//! # use concordium_base::random_oracle::{TranscriptProtocol, TranscriptV1}; +//! # use concordium_base::random_oracle::{TranscriptProtocol, TranscriptProtocolV1}; //! //! enum Enum1 { //! Variant_0, //! Variant_1 //! } //! -//! let mut transcript = TranscriptV1::with_domain("ProofOfSomething"); +//! let mut transcript = TranscriptProtocolV1::with_domain("ProofOfSomething"); //! //! transcript.append_label("Enum1"); //! transcript.append_label("Variant_0"); @@ -215,7 +215,7 @@ use std::io::{IoSlice, Write}; // #[cfg_attr( // not(test), // deprecated( -// note = "Use TranscriptV1 which does proper length prefixing of labels and includes last prover message in transcript for proper sequential composition. Do not change existing protocols without changing their proof version since it will break compatability with existing proofs." +// note = "Use TranscriptProtocolV1 which does proper length prefixing of labels and includes last prover message in transcript for proper sequential composition. Do not change existing protocols without changing their proof version since it will break compatability with existing proofs." // ) // )] pub struct RandomOracle(Sha3_256); @@ -224,7 +224,7 @@ pub struct RandomOracle(Sha3_256); /// and [`TranscriptProtocol`] for how to use it. #[repr(transparent)] #[derive(Debug)] -pub struct TranscriptV1(Sha3_256); +pub struct TranscriptProtocolV1(Sha3_256); /// Type of challenges computed from the random oracle. /// We use 32 byte output of SHA3-256 @@ -295,7 +295,7 @@ impl PartialEq for RandomOracle { /// prefixing data variants with a variant discriminator. Using [`Serial`] is one of the approaches to achieve this, /// since the corresponding [`Deserial`] implementation guarantees the message bytes are unique for the data, /// and hence naturally length and discriminator prefixed. Notice that the "legacy" implementation -/// [`RandomOracle`] does not properly length prefix all variable length data, hence the implementation [`TranscriptV1`] should +/// [`RandomOracle`] does not properly length prefix all variable length data, hence the implementation [`TranscriptProtocolV1`] should /// be used in new proofs systems and new proof versions. pub trait TranscriptProtocol { /// Add domain separating label to the digest. @@ -483,7 +483,7 @@ impl Buffer for BufferAdapter { } } -impl TranscriptProtocol for TranscriptV1 { +impl TranscriptProtocol for TranscriptProtocolV1 { fn append_label(&mut self, label: impl AsRef<[u8]>) { let label = label.as_ref(); BufferAdapter(&mut self.0).put(&(label.len() as u64)); @@ -542,10 +542,10 @@ impl TranscriptProtocol for TranscriptV1 { } } -impl TranscriptV1 { +impl TranscriptProtocolV1 { /// Start with the initial domain string. pub fn with_domain(domain: impl AsRef<[u8]>) -> Self { - let mut transcript = TranscriptV1(Sha3_256::new()); + let mut transcript = TranscriptProtocolV1(Sha3_256::new()); transcript.append_label(domain); transcript } @@ -553,7 +553,7 @@ impl TranscriptV1 { /// Duplicate the transcript, creating a new copy of it. /// Further updates are independent. pub fn split(&self) -> Self { - TranscriptV1(self.0.clone()) + TranscriptProtocolV1(self.0.clone()) } } @@ -741,10 +741,10 @@ mod tests { } /// Test that we don't accidentally change the digest produced - /// by [`TranscriptV1::with_domain`] + /// by [`TranscriptProtocolV1::with_domain`] #[test] pub fn test_v1_with_domain_stable() { - let ro = TranscriptV1::with_domain("Domain1"); + let ro = TranscriptProtocolV1::with_domain("Domain1"); let challenge_hex = hex::encode(ro.extract_raw_challenge()); assert_eq!( @@ -754,10 +754,10 @@ mod tests { } /// Test that we don't accidentally change the digest produced - /// by [`::append_label`] + /// by [`::append_label`] #[test] pub fn test_v1_append_label_stable() { - let mut ro = TranscriptV1::with_domain("Domain1"); + let mut ro = TranscriptProtocolV1::with_domain("Domain1"); ro.append_label([1u8, 2, 3]); let challenge_hex = hex::encode(ro.extract_raw_challenge()); @@ -768,10 +768,10 @@ mod tests { } /// Test that we don't accidentally change the digest produced - /// by [`::append_message`] + /// by [`::append_message`] #[test] pub fn test_v1_append_message_stable() { - let mut ro = TranscriptV1::with_domain("Domain1"); + let mut ro = TranscriptProtocolV1::with_domain("Domain1"); ro.append_message("Label1", &vec![1u8, 2, 3]); let challenge_hex = hex::encode(ro.extract_raw_challenge()); @@ -782,10 +782,10 @@ mod tests { } /// Test that we don't accidentally change the digest produced - /// by [`::append_messages`] + /// by [`::append_messages`] #[test] pub fn test_v1_append_messages_stable() { - let mut ro = TranscriptV1::with_domain("Domain1"); + let mut ro = TranscriptProtocolV1::with_domain("Domain1"); ro.append_messages("Label1", &vec![1u8, 2, 3]); let challenge_hex = hex::encode(ro.extract_raw_challenge()); @@ -796,10 +796,10 @@ mod tests { } /// Test that we don't accidentally change the digest produced - /// by [`::append_final_prover_message`] + /// by [`::append_final_prover_message`] #[test] pub fn test_v1_append_final_prover_message_stable() { - let mut ro = TranscriptV1::with_domain("Domain1"); + let mut ro = TranscriptProtocolV1::with_domain("Domain1"); ro.append_final_prover_message("Label1", &vec![1u8, 2, 3]); let challenge_hex = hex::encode(ro.extract_raw_challenge()); @@ -810,10 +810,10 @@ mod tests { } /// Test that we don't accidentally change the scalar produced - /// by [`::extract_challenge_scalar`] + /// by [`::extract_challenge_scalar`] #[test] pub fn test_v1_extract_challenge_scalar_stable() { - let ro = TranscriptV1::with_domain("Domain1"); + let ro = TranscriptProtocolV1::with_domain("Domain1"); let scalar_hex = hex::encode(common::to_bytes( &ro.split().extract_challenge_scalar::("Scalar1"), @@ -825,10 +825,10 @@ mod tests { } /// Test that we don't accidentally change the digest produced - /// by [`::append_each_message`] + /// by [`::append_each_message`] #[test] pub fn test_v1_append_each_message_stable() { - let mut ro = TranscriptV1::with_domain("Domain1"); + let mut ro = TranscriptProtocolV1::with_domain("Domain1"); ro.append_each_message("Label1", &vec![1u8, 2, 3], |ro, item| { ro.append_message("Item", item) }); From 8c5282c47152bdfb253eaeb0c3b3f860c4fc9a7d Mon Sep 17 00:00:00 2001 From: Allan Rasmussen Date: Tue, 25 Nov 2025 11:29:42 +0100 Subject: [PATCH 04/20] ddoc --- rust-src/concordium_base/src/random_oracle/mod.rs | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/rust-src/concordium_base/src/random_oracle/mod.rs b/rust-src/concordium_base/src/random_oracle/mod.rs index d75d2edec..60045016c 100644 --- a/rust-src/concordium_base/src/random_oracle/mod.rs +++ b/rust-src/concordium_base/src/random_oracle/mod.rs @@ -207,8 +207,12 @@ use std::convert::Infallible; use std::fmt::Arguments; use std::io::{IoSlice, Write}; -/// Transcript implementation V0. Implements [`TranscriptProtocol`]. See [`random_oracle`](self) +/// "Legacy" [transcript protocol](TranscriptProtocol) implementation. See [`random_oracle`](self) /// and [`TranscriptProtocol`] for how to use it. +/// Notice that this "legacy" implementation +/// does not properly length prefix all variable length data, and also does not add +/// the final prover message in sub-proofs, hence the implementation [`TranscriptProtocolV1`] should +/// be used in new proofs systems and new proof versions. #[repr(transparent)] #[derive(Debug)] // todo ar deprecate? @@ -220,7 +224,7 @@ use std::io::{IoSlice, Write}; // )] pub struct RandomOracle(Sha3_256); -/// Transcript implementation V1. Implements [`TranscriptProtocol`]. See [`random_oracle`](self) +/// [Transcript protocol](TranscriptProtocol) implementation V1. See [`random_oracle`](self) /// and [`TranscriptProtocol`] for how to use it. #[repr(transparent)] #[derive(Debug)] @@ -294,9 +298,7 @@ impl PartialEq for RandomOracle { /// Part of the responsibility of the transcript protocol is to apply length prefixes for variable-length data and /// prefixing data variants with a variant discriminator. Using [`Serial`] is one of the approaches to achieve this, /// since the corresponding [`Deserial`] implementation guarantees the message bytes are unique for the data, -/// and hence naturally length and discriminator prefixed. Notice that the "legacy" implementation -/// [`RandomOracle`] does not properly length prefix all variable length data, hence the implementation [`TranscriptProtocolV1`] should -/// be used in new proofs systems and new proof versions. +/// and hence naturally length and discriminator prefixed. pub trait TranscriptProtocol { /// Add domain separating label to the digest. fn append_label(&mut self, label: impl AsRef<[u8]>); From d05b3f61c6c800e4ce5a1bd91a2a110fba3e2869 Mon Sep 17 00:00:00 2001 From: Allan Rasmussen Date: Tue, 25 Nov 2025 11:46:39 +0100 Subject: [PATCH 05/20] todo --- rust-src/concordium_base/src/sigma_protocols/common.rs | 2 +- rust-src/concordium_base/src/sigma_protocols/dlogaggequal.rs | 2 +- rust-src/concordium_base/src/sigma_protocols/enc_trans.rs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/rust-src/concordium_base/src/sigma_protocols/common.rs b/rust-src/concordium_base/src/sigma_protocols/common.rs index 6d8b20609..44277de64 100644 --- a/rust-src/concordium_base/src/sigma_protocols/common.rs +++ b/rust-src/concordium_base/src/sigma_protocols/common.rs @@ -216,7 +216,7 @@ impl SigmaProtocol for ReplicateAdapter

{ fn public(&self, ro: &mut impl TranscriptProtocol) { // add all public data in sequence from left to right - ro.append_each_message(&[], &self.protocols, |ro, p| p.public(ro)); + ro.append_each_message(&[], &self.protocols, |ro, p| p.public(ro)); // todo ar trigger tripwire } fn compute_commit_message( diff --git a/rust-src/concordium_base/src/sigma_protocols/dlogaggequal.rs b/rust-src/concordium_base/src/sigma_protocols/dlogaggequal.rs index d5fc3727f..af39d7cb0 100644 --- a/rust-src/concordium_base/src/sigma_protocols/dlogaggequal.rs +++ b/rust-src/concordium_base/src/sigma_protocols/dlogaggequal.rs @@ -37,7 +37,7 @@ impl SigmaProtocol for DlogAndAggregateDlogsEqual { type SecretData = (Rc, Vec>>); fn public(&self, ro: &mut impl TranscriptProtocol) { - ro.append_each_message(&[], &self.aggregate_dlogs, |ro, p| p.public(ro)); + ro.append_each_message(&[], &self.aggregate_dlogs, |ro, p| p.public(ro));// todo ar try trigger wiretrip self.dlog.public(ro) } diff --git a/rust-src/concordium_base/src/sigma_protocols/enc_trans.rs b/rust-src/concordium_base/src/sigma_protocols/enc_trans.rs index 3fbc8791b..43ecbf1c8 100644 --- a/rust-src/concordium_base/src/sigma_protocols/enc_trans.rs +++ b/rust-src/concordium_base/src/sigma_protocols/enc_trans.rs @@ -183,7 +183,7 @@ impl SigmaProtocol for EncTrans { fn public(&self, ro: &mut impl TranscriptProtocol) { self.elg_dec.public(ro); - ro.append_each_message(&[], &self.encexp1, |ro, p| p.public(ro)); + ro.append_each_message(&[], &self.encexp1, |ro, p| p.public(ro)); // todo ar try trigger writetrip ro.append_each_message(&[], &self.encexp2, |ro, p| p.public(ro)); self.dlog.public(ro) } From 0733806cf27ad7a762ee21c85a439f6b6500267f Mon Sep 17 00:00:00 2001 From: Allan Rasmussen Date: Tue, 25 Nov 2025 11:54:33 +0100 Subject: [PATCH 06/20] fix --- .../concordium_base/benches/bulletproofs.rs | 5 ++++ .../benches/encrypted_transfers_benchmarks.rs | 6 ++++ .../benches/set_proof_bench.rs | 6 ++++ .../src/encrypted_transfers/mod.rs | 4 +++ .../concordium_base/src/id/account_holder.rs | 4 +++ rust-src/concordium_base/src/id/chain.rs | 1 + rust-src/concordium_base/src/id/id_prover.rs | 2 ++ .../concordium_base/src/id/id_verifier.rs | 2 ++ .../src/id/identity_provider.rs | 3 ++ .../concordium_base/src/random_oracle/mod.rs | 20 ++++++++----- .../src/sigma_protocols/com_ineq.rs | 2 ++ .../src/sigma_protocols/dlogaggequal.rs | 2 +- rust-src/concordium_base/src/web3id/proofs.rs | 2 ++ .../concordium_base/src/web3id/v1/proofs.rs | 30 ++++++++++--------- 14 files changed, 67 insertions(+), 22 deletions(-) diff --git a/rust-src/concordium_base/benches/bulletproofs.rs b/rust-src/concordium_base/benches/bulletproofs.rs index b6687089a..15ff9381d 100644 --- a/rust-src/concordium_base/benches/bulletproofs.rs +++ b/rust-src/concordium_base/benches/bulletproofs.rs @@ -68,6 +68,7 @@ pub fn prove_verify_benchmarks(c: &mut Criterion) { let v_vec_p = v_vec.clone(); let gens_p = gens.clone(); let randomness_p = randomness.clone(); + #[allow(deprecated)] let mut transcript = RandomOracle::empty(); group.bench_function("Prove", move |b| { b.iter(|| { @@ -86,6 +87,7 @@ pub fn prove_verify_benchmarks(c: &mut Criterion) { }); let rng = &mut thread_rng(); + #[allow(deprecated)] let mut transcript = RandomOracle::empty(); let proof = prove( ProofVersion::Version1, @@ -102,6 +104,7 @@ pub fn prove_verify_benchmarks(c: &mut Criterion) { group.bench_function("Verify Efficient", move |b| { b.iter(|| { + #[allow(deprecated)] let mut transcript = RandomOracle::empty(); assert!(verify_efficient( ProofVersion::Version1, @@ -150,6 +153,7 @@ fn compare_inner_product_proof(c: &mut Criterion) { let mut H_prime: Vec = Vec::with_capacity(n); let y_inv = y.inverse().unwrap(); let mut H_prime_scalars: Vec<::Scalar> = Vec::with_capacity(n); + #[allow(deprecated)] let mut transcript = RandomOracle::empty(); let G_vec_p = G_vec.clone(); let H_vec_p = H_vec.clone(); @@ -165,6 +169,7 @@ fn compare_inner_product_proof(c: &mut Criterion) { prove_inner_product(&mut transcript, &G_vec, &H_prime, &Q, &a_vec, &b_vec); }) }); + #[allow(deprecated)] let mut transcript = RandomOracle::empty(); group.bench_function("Better inner product proof with scalars", move |b| { b.iter(|| { diff --git a/rust-src/concordium_base/benches/encrypted_transfers_benchmarks.rs b/rust-src/concordium_base/benches/encrypted_transfers_benchmarks.rs index 3702f5686..2de329122 100644 --- a/rust-src/concordium_base/benches/encrypted_transfers_benchmarks.rs +++ b/rust-src/concordium_base/benches/encrypted_transfers_benchmarks.rs @@ -49,6 +49,7 @@ pub fn enc_trans_bench(c: &mut Criterion) { let S = pk_sender.encrypt_exponent_given_generator(&s_value, generator, &mut csprng); let challenge_prefix = generate_challenge_prefix(&mut csprng); + #[allow(deprecated)] let ro = RandomOracle::domain(challenge_prefix); let index = csprng.gen::().into(); @@ -78,6 +79,7 @@ pub fn enc_trans_bench(c: &mut Criterion) { ); let challenge_prefix = generate_challenge_prefix(&mut csprng); + #[allow(deprecated)] let ro = RandomOracle::domain(&challenge_prefix); let mut ro_copy = ro.split(); @@ -99,6 +101,7 @@ pub fn enc_trans_bench(c: &mut Criterion) { &format!("{}: Verify transaction and proofs", module_path!()), move |b| { b.iter(|| { + #[allow(deprecated)] let mut ro = RandomOracle::domain(&challenge_prefix); assert_eq!( verify_enc_trans( @@ -136,6 +139,7 @@ pub fn sec_to_pub_bench(c: &mut Criterion) { let S = pk.encrypt_exponent_given_generator(&s_value, generator, &mut csprng); let challenge_prefix = generate_challenge_prefix(&mut csprng); + #[allow(deprecated)] let ro = RandomOracle::domain(challenge_prefix); let index = csprng.gen::().into(); @@ -167,6 +171,7 @@ pub fn sec_to_pub_bench(c: &mut Criterion) { ); let challenge_prefix = generate_challenge_prefix(&mut csprng); + #[allow(deprecated)] let ro = RandomOracle::domain(&challenge_prefix); let mut ro_copy = ro.split(); @@ -190,6 +195,7 @@ pub fn sec_to_pub_bench(c: &mut Criterion) { ), move |b| { b.iter(|| { + #[allow(deprecated)] let mut ro = RandomOracle::domain(&challenge_prefix); assert_eq!( verify_sec_to_pub_trans(&context, &mut ro, &transaction, &pk, &S,), diff --git a/rust-src/concordium_base/benches/set_proof_bench.rs b/rust-src/concordium_base/benches/set_proof_bench.rs index 3dd9e5d3f..da55723ff 100644 --- a/rust-src/concordium_base/benches/set_proof_bench.rs +++ b/rust-src/concordium_base/benches/set_proof_bench.rs @@ -69,6 +69,7 @@ pub fn bench_set_proofs(c: &mut Criterion) { group.bench_function(BenchmarkId::new("SM Prove", n), move |b| { b.iter(|| { let rng = &mut thread_rng(); + #[allow(deprecated)] let mut transcript = RandomOracle::empty(); set_membership_proof::prove( ProofVersion::Version1, @@ -92,6 +93,7 @@ pub fn bench_set_proofs(c: &mut Criterion) { group.bench_function(BenchmarkId::new("SNM Prove", n), move |b| { b.iter(|| { let rng = &mut thread_rng(); + #[allow(deprecated)] let mut transcript = RandomOracle::empty(); set_non_membership_proof::prove( ProofVersion::Version1, @@ -108,6 +110,7 @@ pub fn bench_set_proofs(c: &mut Criterion) { }); // Generate valid proofs for verification + #[allow(deprecated)] let mut transcript = RandomOracle::empty(); let snm_proof = set_non_membership_proof::prove( ProofVersion::Version1, @@ -121,6 +124,7 @@ pub fn bench_set_proofs(c: &mut Criterion) { ); assert!(snm_proof.is_ok()); let snm_proof = snm_proof.unwrap(); + #[allow(deprecated)] let mut transcript = RandomOracle::empty(); let sm_proof = set_membership_proof::prove( ProofVersion::Version1, @@ -143,6 +147,7 @@ pub fn bench_set_proofs(c: &mut Criterion) { let sm_proof_p = sm_proof.clone(); group.bench_function(BenchmarkId::new("SM Verify", n), move |b| { b.iter(|| { + #[allow(deprecated)] let mut transcript = RandomOracle::empty(); set_membership_proof::verify( ProofVersion::Version1, @@ -165,6 +170,7 @@ pub fn bench_set_proofs(c: &mut Criterion) { let snm_proof_p = snm_proof.clone(); group.bench_function(BenchmarkId::new("SNM Verify", n), move |b| { b.iter(|| { + #[allow(deprecated)] let mut transcript = RandomOracle::empty(); set_non_membership_proof::verify( ProofVersion::Version1, diff --git a/rust-src/concordium_base/src/encrypted_transfers/mod.rs b/rust-src/concordium_base/src/encrypted_transfers/mod.rs index 5c8704f9b..ac92c15bd 100644 --- a/rust-src/concordium_base/src/encrypted_transfers/mod.rs +++ b/rust-src/concordium_base/src/encrypted_transfers/mod.rs @@ -164,6 +164,7 @@ pub fn make_transfer_data( csprng: &mut R, ) -> Option> { let sender_pk = &PublicKey::from(sender_sk); + #[allow(deprecated)] let mut ro = RandomOracle::domain("EncryptedTransfer"); ro.append_message(b"ctx", &ctx); ro.append_message(b"receiver_pk", &receiver_pk); @@ -204,6 +205,7 @@ pub fn verify_transfer_data( transfer_data: &EncryptedAmountTransferData, ) -> bool { // Fixme: Put context into the random oracle. + #[allow(deprecated)] let mut ro = RandomOracle::domain("EncryptedTransfer"); ro.append_message(b"ctx", &ctx); ro.append_message(b"receiver_pk", &receiver_pk); @@ -244,6 +246,7 @@ pub fn make_sec_to_pub_transfer_data( ) -> Option> { let pk = &PublicKey::from(sk); // FIXME: Put context into random oracle + #[allow(deprecated)] let mut ro = RandomOracle::domain("SecToPubTransfer"); ro.append_message(b"ctx", &ctx); ro.append_message(b"pk", &pk); @@ -284,6 +287,7 @@ pub fn verify_sec_to_pub_transfer_data( transfer_data: &SecToPubAmountTransferData, ) -> bool { // Fixme: Put context into the random oracle. + #[allow(deprecated)] let mut ro = RandomOracle::domain("SecToPubTransfer"); ro.append_message(b"ctx", &ctx); ro.append_message(b"pk", &pk); diff --git a/rust-src/concordium_base/src/id/account_holder.rs b/rust-src/concordium_base/src/id/account_holder.rs index c8f20ab5c..e0842bf04 100644 --- a/rust-src/concordium_base/src/id/account_holder.rs +++ b/rust-src/concordium_base/src/id/account_holder.rs @@ -92,6 +92,7 @@ pub fn generate_pio>( crate::ps_sig::SigRetrievalRandomness

, )> { let mut csprng = thread_rng(); + #[allow(deprecated)] let mut transcript = RandomOracle::domain("PreIdentityProof"); // Prove ownership of the initial account let pub_info_for_ip = build_pub_info_for_ip( @@ -211,6 +212,7 @@ pub fn generate_pio_v1_with_rng>( PreIdentityObjectV1, crate::ps_sig::SigRetrievalRandomness

, )> { + #[allow(deprecated)] let mut transcript = RandomOracle::domain("PreIdentityProof"); let CommonPioGenerationOutput { prover, @@ -856,6 +858,7 @@ pub fn create_unsigned_credential< // Compute the challenge prefix by hashing the values. // FIXME: We should do something different here. // Eventually we'll have to include the genesis hash. + #[allow(deprecated)] let mut ro = RandomOracle::domain("credential"); ro.append_message(b"cred_values", &cred_values); ro.append_message(b"address", &addr); @@ -1270,6 +1273,7 @@ pub fn generate_id_recovery_request> StatementWithContext> = Vec::with_capacity(self.statement.statements.len()); + #[allow(deprecated)] let mut transcript = RandomOracle::domain("Concordium ID2.0 proof"); transcript.append_message(b"ctx", &global); transcript.add_bytes(challenge); @@ -353,6 +354,7 @@ pub fn prove_attribute_in_range>( let b = upper.to_field_element(); match version { ProofVersion::Version1 => { + #[allow(deprecated)] let mut transcript_v1 = RandomOracle::domain("attribute_range_proof"); prove_in_range( ProofVersion::Version1, diff --git a/rust-src/concordium_base/src/id/id_verifier.rs b/rust-src/concordium_base/src/id/id_verifier.rs index 80f85db41..74252d2db 100644 --- a/rust-src/concordium_base/src/id/id_verifier.rs +++ b/rust-src/concordium_base/src/id/id_verifier.rs @@ -70,6 +70,7 @@ pub fn verify_attribute_range>( let b = upper.to_field_element(); match version { ProofVersion::Version1 => { + #[allow(deprecated)] let mut transcript_v1 = RandomOracle::domain("attribute_range_proof"); verify_in_range( ProofVersion::Version1, @@ -396,6 +397,7 @@ impl> Statement commitments: &CredentialDeploymentCommitments, proofs: &Proof, ) -> bool { + #[allow(deprecated)] let mut transcript = RandomOracle::domain("Concordium ID2.0 proof"); transcript.append_message(b"ctx", &global); transcript.add_bytes(challenge); diff --git a/rust-src/concordium_base/src/id/identity_provider.rs b/rust-src/concordium_base/src/id/identity_provider.rs index bc1376799..e2c3a3131 100644 --- a/rust-src/concordium_base/src/id/identity_provider.rs +++ b/rust-src/concordium_base/src/id/identity_provider.rs @@ -82,6 +82,7 @@ pub fn validate_request>( return Err(Reason::IncorrectProof); } + #[allow(deprecated)] let mut transcript = RandomOracle::domain("PreIdentityProof"); // Construct the common verifier and verify the range proof let (verifier, response) = validate_request_common( @@ -131,6 +132,7 @@ pub fn validate_request_v1>( let common_fields = pre_id_obj.get_common_pio_fields(); let poks_common = &pre_id_obj.poks; + #[allow(deprecated)] let mut transcript = RandomOracle::domain("PreIdentityProof"); // Construct the common verifier and verify the range proof let (verifier, response) = validate_request_common( @@ -691,6 +693,7 @@ pub fn validate_id_recovery_request Self { + #[allow(deprecated)] RandomOracle::empty() } @@ -393,11 +387,23 @@ impl TranscriptProtocol for RandomOracle { impl RandomOracle { /// Start with the initial empty state of the oracle. + #[cfg_attr( + not(test), + deprecated( + note = "Use TranscriptProtocolV1 instead, see documentation on RandomOracle. Do not change existing protocols without changing their proof version since it will break compatability with existing proofs." + ) + )] pub fn empty() -> Self { RandomOracle(Sha3_256::new()) } /// Start with the initial domain string. + #[cfg_attr( + not(test), + deprecated( + note = "Use TranscriptProtocolV1 instead, see documentation on RandomOracle. Do not change existing protocols without changing their proof version since it will break compatability with existing proofs." + ) + )] pub fn domain>(data: B) -> Self { RandomOracle(Sha3_256::new().chain_update(data)) } diff --git a/rust-src/concordium_base/src/sigma_protocols/com_ineq.rs b/rust-src/concordium_base/src/sigma_protocols/com_ineq.rs index a0c074f4f..923ce10cd 100644 --- a/rust-src/concordium_base/src/sigma_protocols/com_ineq.rs +++ b/rust-src/concordium_base/src/sigma_protocols/com_ineq.rs @@ -44,6 +44,7 @@ pub fn prove_com_ineq( pub_value: C::Scalar, csprng: &mut R, ) -> Option> { + #[allow(deprecated)] let mut transcript = RandomOracle::domain(b"InequalityProof"); let c = com_key.hide(&value, value_tilde); @@ -110,6 +111,7 @@ pub fn verify_com_ineq( com_mult_response, aux_com, } = proof; + #[allow(deprecated)] let mut transcript = RandomOracle::domain(b"InequalityProof"); transcript.append_message(b"commitmentKey", &com_key); transcript.append_message(b"public commitment", &c); diff --git a/rust-src/concordium_base/src/sigma_protocols/dlogaggequal.rs b/rust-src/concordium_base/src/sigma_protocols/dlogaggequal.rs index af39d7cb0..f8555f746 100644 --- a/rust-src/concordium_base/src/sigma_protocols/dlogaggequal.rs +++ b/rust-src/concordium_base/src/sigma_protocols/dlogaggequal.rs @@ -37,7 +37,7 @@ impl SigmaProtocol for DlogAndAggregateDlogsEqual { type SecretData = (Rc, Vec>>); fn public(&self, ro: &mut impl TranscriptProtocol) { - ro.append_each_message(&[], &self.aggregate_dlogs, |ro, p| p.public(ro));// todo ar try trigger wiretrip + ro.append_each_message(&[], &self.aggregate_dlogs, |ro, p| p.public(ro)); // todo ar try trigger wiretrip self.dlog.public(ro) } diff --git a/rust-src/concordium_base/src/web3id/proofs.rs b/rust-src/concordium_base/src/web3id/proofs.rs index 514c6ea95..ab7e4bab4 100644 --- a/rust-src/concordium_base/src/web3id/proofs.rs +++ b/rust-src/concordium_base/src/web3id/proofs.rs @@ -59,6 +59,7 @@ impl> Presentation, public: impl ExactSizeIterator>, ) -> Result, PresentationVerificationError> { + #[allow(deprecated)] let mut transcript = RandomOracle::domain("ConcordiumWeb3ID"); transcript.add_bytes(self.presentation_context); transcript.append_message(b"ctx", ¶ms); @@ -329,6 +330,7 @@ impl> Request { AttributeType: 'a, { let mut proofs = Vec::with_capacity(attrs.len()); + #[allow(deprecated)] let mut transcript = RandomOracle::domain("ConcordiumWeb3ID"); transcript.add_bytes(self.challenge); transcript.append_message(b"ctx", ¶ms); diff --git a/rust-src/concordium_base/src/web3id/v1/proofs.rs b/rust-src/concordium_base/src/web3id/v1/proofs.rs index ac7ab0bbd..a090a9e88 100644 --- a/rust-src/concordium_base/src/web3id/v1/proofs.rs +++ b/rust-src/concordium_base/src/web3id/v1/proofs.rs @@ -1,7 +1,6 @@ use crate::{ curve_arithmetic::Curve, id::types::{Attribute, GlobalContext}, - random_oracle::RandomOracle, }; use itertools::Itertools; use std::collections::BTreeMap; @@ -17,7 +16,7 @@ use crate::id::types::{ IdentityAttributesCredentialsInfo, IdentityAttributesCredentialsValues, IpContextOnly, }; use crate::pedersen_commitment::Commitment; -use crate::random_oracle::TranscriptProtocol; +use crate::random_oracle::{TranscriptProtocol, TranscriptProtocolV1}; use crate::web3id::v1::{ AccountBasedCredentialV1, AccountBasedSubjectClaims, AccountCredentialProofPrivateInputs, AccountCredentialProofs, AccountCredentialSubject, AccountCredentialVerificationMaterial, @@ -55,7 +54,9 @@ impl, AttributeType: Attribute, verification_material: impl ExactSizeIterator>, ) -> Result, VerifyError> { - let mut transcript = RandomOracle::domain("ConcordiumVerifiablePresentationV1"); + #[allow(deprecated)] + let mut transcript = + TranscriptProtocolV1::with_domain("ConcordiumVerifiablePresentationV1"); append_context(&mut transcript, &self.presentation_context); transcript.append_message(b"ctx", &global_context); @@ -91,7 +92,7 @@ impl, AttributeType: Attribute, - transcript: &mut RandomOracle, + transcript: &mut impl TranscriptProtocol, verification_material: &CredentialVerificationMaterial, ) -> bool { match self { @@ -110,7 +111,7 @@ impl> AccountBasedCredentialV1>( &self, global_context: &GlobalContext, - transcript: &mut RandomOracle, + transcript: &mut impl TranscriptProtocol, verification_material: &CredentialVerificationMaterial, ) -> bool { let CredentialVerificationMaterial::Account(AccountCredentialVerificationMaterial { @@ -144,7 +145,7 @@ impl, AttributeType: Attribute, - transcript: &mut RandomOracle, + transcript: &mut impl TranscriptProtocol, verification_material: &CredentialVerificationMaterial, ) -> bool { let CredentialVerificationMaterial::Identity(IdentityCredentialVerificationMaterial { @@ -229,7 +230,7 @@ fn verify_statements< cmm_attributes: &BTreeMap>, revealed_attributes: &BTreeMap, global_context: &GlobalContext, - transcript: &mut RandomOracle, + transcript: &mut impl TranscriptProtocol, ) -> bool { statements.into_iter().zip_longest(proofs).all(|elm| { elm.both().map_or(false, |(statement, proof)| { @@ -250,7 +251,7 @@ impl> AccountBasedSubjectClaims>( self, global_context: &GlobalContext, - transcript: &mut RandomOracle, + transcript: &mut impl TranscriptProtocol, csprng: &mut (impl Rng + CryptoRng), now: chrono::DateTime, private_input: CredentialProofPrivateInputs, @@ -295,7 +296,7 @@ impl> IdentityBasedSubjectClaims>( self, global_context: &GlobalContext, - transcript: &mut RandomOracle, + transcript: &mut impl TranscriptProtocol, csprng: &mut (impl Rng + CryptoRng), now: chrono::DateTime, private_input: CredentialProofPrivateInputs, @@ -403,7 +404,7 @@ fn prove_statements< attribute_randomness: &impl HasAttributeRandomness, revealed_attributes: &BTreeMap, global_context: &GlobalContext, - transcript: &mut RandomOracle, + transcript: &mut impl TranscriptProtocol, csprng: &mut (impl Rng + CryptoRng), ) -> Result>, ProveError> { statements @@ -428,7 +429,7 @@ impl> SubjectClaims>( self, global_context: &GlobalContext, - transcript: &mut RandomOracle, + transcript: &mut impl TranscriptProtocol, csprng: &mut (impl Rng + CryptoRng), now: chrono::DateTime, private_input: CredentialProofPrivateInputs, @@ -482,7 +483,8 @@ impl> RequestV1 AttributeType: 'a, { let mut verifiable_credentials = Vec::with_capacity(private_inputs.len()); - let mut transcript = RandomOracle::domain("ConcordiumVerifiablePresentationV1"); + let mut transcript = + TranscriptProtocolV1::with_domain("ConcordiumVerifiablePresentationV1"); append_context(&mut transcript, &self.context); transcript.append_message(b"ctx", &global_context); @@ -532,7 +534,7 @@ impl< &self, version: ProofVersion, global: &GlobalContext, - transcript: &mut RandomOracle, + transcript: &mut impl TranscriptProtocol, csprng: &mut impl rand::Rng, attribute_values: &impl HasAttributeValues, attribute_randomness: &impl HasAttributeRandomness, @@ -608,7 +610,7 @@ impl< &self, version: ProofVersion, global: &GlobalContext, - transcript: &mut RandomOracle, + transcript: &mut impl TranscriptProtocol, cmm_attributes: &BTreeMap>, revealed_attributes: &BTreeMap, proof: &AtomicProofV1, From 251a0acc07ef5c22de606bfc116d061e5822de69 Mon Sep 17 00:00:00 2001 From: Allan Rasmussen Date: Tue, 25 Nov 2025 12:24:59 +0100 Subject: [PATCH 07/20] fix --- rust-src/concordium_base/src/web3id/v1.rs | 4 ++-- rust-src/concordium_base/src/web3id/v1/anchor.rs | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/rust-src/concordium_base/src/web3id/v1.rs b/rust-src/concordium_base/src/web3id/v1.rs index 4047682ef..0d18c8f8b 100644 --- a/rust-src/concordium_base/src/web3id/v1.rs +++ b/rust-src/concordium_base/src/web3id/v1.rs @@ -1844,7 +1844,7 @@ mod tests { "issuer": "did:ccd:testnet:idp:17", "proof": { "created": "2023-08-28T23:12:15Z", - "proofValue": "000000000000000502b12365d42dbcdda54216b524d94eda74809018b8179d90c747829da5d24df4b2d835d7f77879cf52d5b1809564c5ec49990998db469e5c04553de3f787a3998d660204fe2dd1033a310bfc06ab8a9e5426ff90fdaf554ac11e96bbf18b1e1da898425e0f42bb5b91f650cffc83890c5c3634217e1ca6df0150d100aedc6c49b36b548e9e853f9180b3b994f2b9e6e302840ce0d443ca529eba7fb3b15cd10987be5a40a2e5cf825467588a00584b228bea646482954922ae2bffad62c65eebb71a4ca5367d4ac3e3b4cb0e56190e95f6af1c47d0b45991d39e58ee3a25c32de75c9d91cabd2cc5bc4325a4699b8a1c2e486059d472917ba1c5e4a2b66f77dbcf08a2aa21cbd0ec8f78061aa92cc1b126e06e1fc0da0d03c30e444721fbe07a1100000007ae9f2dffa4e4102b834e7930e7bb9476b00b8f0077e5fb48bc953f44571a9f9f8bcf46ea1cc3e93ca6e635d85ee5a63fa2a1c92e0bf7fba3e61a37f858f8fa52f40644f59e1fb65b6fb34eaaa75a907e85e2c8efd664a0c6a9d40cbe3e96fd7ab0ff06a4a1e66fd3950cf1af6c8a7d30197ae6aec4ecf463c368f3b587b5b65b93a6b77167e112e724a5fe6e7b3ce16b8402d736cb9b207e0e3833bb47d0e3ddc581790c9539ecd3190bdee690120c9b8e322e3fb2799ada40f5e7d9b66a8774aa662ab85c9e330410a19d0c1311c13cf59c798fa021d24afd85fabfe151802cbde37dafc0046920345961db062e5fb9b2fe0334debe1670ef88142a625e6acd1b7ded9f63b68d7b938b108dbf4cca60257bdf32fed399b2d0f11a10c59a4089937a28cbeefc28a93e533722d6060856baf26ccd9470a9c50229acc54753534888e1c8f8c612b5e6af0705dceeac85a5ac3d641b3033c5d3af066f33147256b86b1fffaaceea3bf9e4fd98f7a5371e4a882dd3c7cbe5d9b34e933d6ac224d7198cc4c8d3e5f0cef03fad810ca36499dc3a5e157d435843d60eb6a3fc3c3624d9fef8b5f2f2335af0a8ecca5cf71a9ffab6651d7c899d560264a6c9e361ee10a17dcb18522acdc0a19ab004f15ba1e23fa2aa3bb75f3767678d12c6dc35b2a04bb5239ce2cf35649a42525f42f91d6b80266af0fbd86645611332203ac555250fc29f6bb1b50932c7e48418bbadf57db4931789a0dd44e9b70d437af1ae686ede83e6965108a655caf34bd7b0b587eef0a29350020abae08bd2d979752316f749ab4686da684dcae5b571213c7bfb914cb70965e9b643862f71bab5d22b7dbf7d3f84636ba514ef2cf0c87ecf225e3bdc99e15368b3d814fb1e257ac1fc0b9114cbb8ed594ce50688c88d8ea9d0e97f55e89fbddd282e13d7303d3604e969bc0e699388c2f6fbb310aa82f18af896019d79f26f72fbe3a5dfc6fd30c34ac8d57d499e49664ecfa76094c6fba2372dba87a2b55dd9dc30877af0d6fdd2b2ea54be03b39554bf77b9ad30ef725df82bdb6c5456adf9ac3187ffbeaab1b4ce68782829850f10182deb13eaa94edd3640768224a178b8bac224d12711c7d3bec925db4da9bd1424db872757a1f2e10c9dac40483a69972504e5d69163a9f13c5dc8fc60a1634554a5009d948704f92e701eeb0a5b2cbfdcf62fd7b8cc0db65b2ba52dd1bbe2e46eddeff70f5fb3686917587b82a9cf1e1c8a7b6cf44dbe57bbf83d541bfbfccac677a377ef4e1a5ced1e7e5147bde759150f531780bcfc5658b099787d68277d3d41d992022be434194d8307d2a90a518705017affec5796354ff2432f57f525cf014bdcf0b9fd84b9501d3938259c433b4e6181e2630b56826c4a0c7d03cc0a8768ce7226703cf97ee83d6bc1c0c044a2e0d4439780d1c7351ea8ece10000000298ff27cb9f1c4afb38c535cee5dbde71599f727976298c540cdb7ff0b10a439f1599c9bf879e35746e2fd04dda05368d966efc49f07a5c48baaca5853de36dd2f0c7fab8106f1158f34ece1d0fd8576eb727d834cb0c380c150086e2222ba38283d8c26a9af828584cbd90801cc0c3e1855b9a26f81efd3931000b8a2109ac9cd5070b98963d700560fd6c6de1df8202ac21dfbdf141bdf58ee96d7a72cb2dfba962159a2c9d0fe1d312aca7a56ce97716d7d16e47b7c59e651ee8fe8dbbf56c3048a31df649d9da46f669b80d5cb31c3ee70c5e6a05de8be814833934befaef06757e390f83ce84b4fd84fb9d86eb30a897faa4718d7b5a12c086255a0a21cc048b69df7282cd3234e4423e85d15c09d49fc2005e869a4876fec01369c3b0ec0ae6f710797b4e5294a7fdf72c05341b6887da98066400436af27e739c140e3a481df2845cd78df942a2c0fb01429d5b04cd96b18c0b2bbf764b533a6f095edbea844cbc0d196b4e423c7fd409c1ceb6572812707c9048ec5a373c29e3cefbbd128e1ebe72b84be67ae22e3dfee5b47f57b289755b558624daeb22ce521c432fbf2cab96826ec670f18a194b151ec0f49c31237f35caae1296715571520e22caff2912531b1ee43d555dee29e7105161dfe86f133b3fb7c194e72c12b1eaac010160a3e8a44cad0b1c1ef89d492014997603a37b26e9461572edcf93a011d639550e0505ad8932c2a205c688d70d6414717c7a31868b5d01c37993085cf28d1c670000000295c326f59171824b2fc3e09816b73c6f75a03fb50f611559855d295e0a565ff6d2505f970464ca12e81031d286866dd5b73c285de994b592f8d8c2e64227bcc5ae2058339d11af025cfcb126c2b3c9a7839b87c8d218f93b0f30a0876076eb9598e1ec92a57f4ce785b1a05c01e8db34b4cefe8e518a859aa6d9530bbe72a033af7e87a95433de67b86f389e178b1aaaa53eddcdf1be990d96ba7e7f18ffa83d60385e1a1130dbf245e1b4bac2e8bceb2c1184380e6e0f7876157d7ae074d1fb013266272083b5420b3fc654141046e5bee9e3ffe50497f372d55b3f0aec05873c7409c8a1507c38f6c87b726e9355d5d326658e1e7e67b349ef1a65185ec51802b2a44460fcbf28d7ce0fce6c677113a88b88ec272d3cfac24d33afc47b6fa15259af84fa6543ef673cbd18a44d47420c8c53d7eaf9272dfa62fadd8d118c2055480b6494a67b0346c9fa0b2ba2cba9c0591224a2ed7b399ea35b89111a53059cb410c51ffb45d0aab4b642087698fcb67d55d33a711db3f84a125f970705b68c5ae5b8ea2394c891911d7f1032ec08ec8df792bcbcb1a953214317be0085b4b7b23a45d52a83f77cade01752c7ae6fe1d81bb5dc3b6a74e3d2f4130178263b9e633914559cf75d5902b5fc696198bff1d25812b05ade020d0aadcae022336b3c49639dd8dd90381bb59828ca9a82d87610d1e01b4ee4827f30d11ac72fa911f4439ca4fbfe164dc370e5c96dcc329bbf9972d71e811d17f5dd2ffb760ac0e31400000007b9e19ad95babc1c31bf657ae20a5420cf05bbf024ae2ffe13b363d5404c5a0ef360c54d49e8725210a5bba290d29cb58a2607e5134fdb367631e10d8e159396e39bbc09bd7084038f6b5cebd5386da5cd18cfe3ce9dbf75b51f4d7de00e00c5993a3b4d05fb3f4edb2a8d05cece2da96d7d87081c1610eb949caed95520479c662d623ad1464fee46bc3486521d44427ad8d76db0cc6ab51cb69d1dfd59c1938b68b80a8813c9dad15f9466941e377836693dfdcfc96e12a296699ef77ab274293a917b64e48f413ee2908b574ad8875951ce40dceadaf104145a2a937bce6707a962355a61efbf9379a1da606f98915a21a9255eaf105b04651d789fc90ddab8a402d11fd8e5befece4956d1d0c9c47987c7d282cb045c053fc860e8c07365b9937aae7fa435190992a02a24e388bd0b0836775d0e01c7faba3e92c5d3e8975fcad16cce9e9b01f378a572ab4039e0b8582d4d3a47c3b3fb587483cd1a760e628d0f3d63ac9e8b10cefa8b94d02cade0ab47005ad368f4f9e5b766a5c353a6eb1a7fd5bed46fbd1554c4ec47d8b6d3b38dcc66db969c646a34928eeb40147adc94878a1b237fcbe21f779e723e8a4f6a6cec0cb57205789e8d781bf465a833608b5181ad27d420e0e1f7383c0222df32259ace41dc092dfc745bbfc4bd371cd99e5a1c73baeb8ad15c34e060af529a8babad63c3a131ca089053f498170afb30b26e0f2794b0d1f417d870af7daf37694430db13f00b7af5101723d656d334c72b5e0bbe13478722e954935e6701ecf3cc725d61e42edbb896b6d4dff5b51f48e194337fb086908d50edcb61a295dcf57f54b6b41d5a760f5ff8992a6e45acfec08157dc3640fa1878cdb5ce41cb27ab9096beb3ded0b7cd57c1c4a850abc08ac822a3be26b4deb5a3cd11914ae5ac2c29430fe91be97fea012981dbb389da64d4a794017f91fb40e3188bd7190025a5b39c323a90f5a8496d5f64e200093072f1379728f1f0e741b51db5e4967d1e5437ca1d531ed742fe9ad2708ba06b3f8006d9f6e451166c885818931efbf878b5d041b211441fa707013ebe73e41ca25da68cebf07b67ef99e5fef798d5bdff3378d766b8116e710384d1530280b79e945", + "proofValue": "000000000000000502b12365d42dbcdda54216b524d94eda74809018b8179d90c747829da5d24df4b2d835d7f77879cf52d5b1809564c5ec49990998db469e5c04553de3f787a3998d660204fe2dd1033a310bfc06ab8a9e5426ff90fdaf554ac11e96bbf18b1e1da8b0fc5ec7fa6079816d44c3e4bae9e0fc7f8c6d144231dbb6f60e987231a7332b82eb2127258de3018344c859084a1252b3979160ae63a916e77839343a3d8a03e91c3a92dca0ab9571afd4f218e5a1846c41dad133716212562d776ca9fcee0e0d886b1551b178ade515ba130fec09000841521485f4f0c002cfec26109021992aaffbe5174216d6f47d11f1e91c99f60309d92479b6558d3716a469c574607355165148beb2b48492c9d37af7aa72e71799cad806fb127ecb39207734ed184c000000078c913a915e5570288ec73a2b154758bcdc84669bf1bfd4c9e57a0bc20884bfbf0a345025a3825b04e00edefcf1618346b32c40e8f13b54f1276240f2a9886ed56811fc9c62618cd072a8100f88f9e794c5a2af1d677a379471a49a640adc1b18b9067637e893331d8771830df7eeb274ed1a8f3a0ca96bfdd5ed2b188bf51176063b8c18a17bc4c1322de31c4e3de5ddab070b0503d634685d34070f4c868f6102998be1991562d2343103c37de7016d6640088d78b6f5ca580098e5057a3594b5821c92de6f8ef470040dd63c8159a0e4f84502a7f6f3e12d56258d042b1b84b3907ec3c22cdb81711ee568a654e65e91d87ec6bd255feb2f97a9342ee83080c7961583e85690f810b22bcd412eda6d24b484691b3496953b0480a6c6dd531dad1f856c67d195594c0a8fca609ea0c998ab919f062b27d8a063e80ffad73bbc4ab13fa7b5def2360a4787ade72e16d093216303a04c029429d149d4018229c700432974d5063fb68cb2d76f46cee01f668c6466dff521916cdd4f62e60a602c98b768df7237913a5a797e4e868458ae937e806b594427a6832f1aa027d9f826efe2eb63651ef18711c909c75d1ac2df96d8c679d91cd586f8a9b5f83d7154675dbd7c134ddf7564948d5abb24a0b1479de9ff7419ffa947d1352b88b57cee9aa34313bfa3831bbd01a30f311565e88a1ba8588227d8e63c70da6bd1c43654e6c008cd61887e4432e45dbd22e8d01c34a36d6693aa811303a765653bb3590cfb42256d1d844de27480764d53a8be644e89155e77980cea4083d0d6bbc2478920b4190d1e67dc96625b7cabf6662b4f9a8798f08965ef49ddaffb94a3cdc0225b4ccf9f9caa32a7c1035915e77d51e1dfb6041b541e4bc956f389784b6fdabca45f5e150a543bb7aa722b3abb36971c25523d44e3184f2c21c1a3060f92101969710a210dda0964c5edb6efa7d58ed52b5f176810768ede3914706bbf98af412159ef99ccd429c3d79db03862bb6e5a9de77930388bcb710731e339c08ac4768603b39554bf77b9ad30ef725df82bdb6c5456adf9ac3187ffbeaab1b4ce68782829850f10182deb13eaa94edd3640768224a178b8bac224d12711c7d3bec925db4da9bd1424db872757a1f2e10c9dac40483a69972504e5d69163a9f13c5dc8fc609075a46217da3a040397b503f56b7c97e0d84a4b22e71eb2ada61e3039f91f55771b65d72e87237cfc88781b3491c9fdb5680962f2303d20323dfeb546fbb228cbe877418de69055ff10b0023f45e07bb24db1b9dd6011527a32a4735db2c427481f9b654370561008d4c1c0f3145cfa7a6756ea20a6aecf68cf729b2ccfbc68276fa53570be8a4f74ac11433fd0048fbe0bde0772978620b83325c38a2650d6681bf45d62fa3afe9817de06fd122b2183c370f177546dc274412d41d20afe09000000029508e5c7ec749516dd2c45cd31cae72f44c830da8a5ca026b028cab53cd07107323e8206a9b30c4f6676ab4ce1cef5ddaa2726200d144a1e380428dcfcc7a44c8ac6940d8243007a1229674107b62973d2b9ced71aee4964e8bcd42bb6b64b08a44385e22ac94e0e7eea9ee5d4bc468e09937de43640bc4f52930b6f697ee186bef99b54e30d82b3b8002ab0804ca4ec9695a7d4721498073132bc442aab9ac50a5746b70ac7f5131fb90534218bfcb68925a22a5d95f639d7af612c10d6e8d05d738613f73d4cfbd83bc345544b62e545e62476947a07926d1f72c0da1a9d5c06ce6132a47c7e56b89ff3434e5dabadd24a093755c95498841c63a537124d66048b69df7282cd3234e4423e85d15c09d49fc2005e869a4876fec01369c3b0ec0ae6f710797b4e5294a7fdf72c05341b6887da98066400436af27e739c140e3a481df2845cd78df942a2c0fb01429d5b04cd96b18c0b2bbf764b533a6f095edbea9945362b3fa5826bd37435ec9ffeb4f397d5aecd487ad89ecf7575bba18122f1dc31c8c2b9b462850ba06373f9356054a051539f5b619ed5baa08e70b9b947655d03493dde34f1ee866233184b16ed5701a6aabb59bf6e317ba195a3cc9cdbb63591f4f2c52effb2048adbb7fcdb91dfda0ddf5456f477d5d1a680f08eeec7fc5da043585288c3ffd87c899cccd69737163c2afe01be71aa61dbd66e814988c4177301a76f697b70cc80c4512f54a597b4c7abc8a309f98d33fd8cf8511b5e5e00000002b9739d0f50892d470a92652deadea1887169927489e17fce741e76f14311e9645d250af920fcbf8ac52ee20adaaf6731802849e9c774b415ad8cf940c5fa3b379697dd96d5f41fd480fcd8d7dfea3359318effd4d67b2e0a562f219040e1cb7982dfeb2b4774dbf601c28b89c407de10eabc3168d05011200e068a186a402bbb2c4d5e34072f196cd62615688b24f005a2e6206a277a97feba2e94f6502e0ba14e76759cc8a1c8a30d4c5d102dd8278daf01e922efeca6bb45dfffc9d0c74ea2058d51f9c727e4aeb0c13e2d5ca6718ec81e5c3dc35a106b4de2bf997bc8c242570d2a9cc5dcc95975fa831893e7e52326a555b5036c184a710c774f3e6f212602b2a44460fcbf28d7ce0fce6c677113a88b88ec272d3cfac24d33afc47b6fa15259af84fa6543ef673cbd18a44d47420c8c53d7eaf9272dfa62fadd8d118c2055480b6494a67b0346c9fa0b2ba2cba9c0591224a2ed7b399ea35b89111a53059c8161f481a8ed0b5f3427fae64ab47361d2544fd02054152d9075f77baa67d147cf583928f1a43539f06400c41c1ec05991c1cdaa03d0cf3e169011f771fa78bca3a72903f95f0ccbeec0dd2a89d8c0dd874c5c4602862046818a3f94fd7447ec32cf89573e38094b321b3a0d1f7a5b55942db1cc3a16afb6124f5986bdc22ba72f28af268c7e0bded3d112634f8b14fa3ad5bbad0615d750b1c93b360a4eea1947823e0cd33989897bd9278af0a5bcd037fc606d663dddf39010e7092756c6cc00000007a49afb2c255ed717102cbf0e636108889dedc10885d73349f3ebb38ac45df089106b9c8d62848cdc47300cbe9ee8185293b0a9cb5db305d174d66f3e91c02c92ca64d8042882feb760605fcb8cd92772d693c4ec3e2cde07315e23c53c57a0afa360c46b252c691d7bd993a0e8ff3e33dd3fb69b6887f63928d9c3675c4df282b778e448d524696dd415a032b4900d468c1455a287769b34c0f0df24d32475dd085fdddde705b5f7e21fb1b749f5be5a5c2e7ede4c5a9c8b49291056eebc3e4b812d4e8a8a68d90940fe2029c95bdbc10d510bb70b7598e2fa9a81ece6bde9afcbacb8e0e5eada08e066cc7372e7ebc485a333e01e24743ee8b0770001726d59e488207ba34fc30780f25455275261ed0b2a4842c9fb726c44b17dabc68da96d8144a33fcf8aa4f574a6d5b9a27bc76a9c21cf95c399c592e75d70f238e937fe2869c7f89c187baf50e98aee796972a1ab579fb8604edcebe90ba8ac564aef7f8132db3e1b7af54918eadfd9dc5cb22b1968dd68ff8c8ce8b6cba5e1cd5b696ca1b13edb7397fb5bd908fffdbdccb5fcf7b088ebf1c5f8f6f1b0788e87f7e37cfedb5b085c4a36d7e1a5d93a8cf9ff2ba65bed6262538454d97966bd314c49f1dfaa1cbb5566b47f76a0be3c68e9087ad7b6bbe7d534dacfb8c154275a409d178805cf0970476bc10f72cc4524b42b0baddee30a774e605cd972ef7f4e987be3f44cb11f09fea8757ae28063f0552f7eb6740461c52327055fc112a06e55699c96459246c54c7ab94890e23e6b21f0f1624a3c6c41049dc3209f0c1364d71c7583b049ce241e70f992b5d87140e831d0b330b2150e4d2be222a281cbcbf7777fca472b9089b7a6ebccc80d6431debbe19391436d0fef79164266a00e8ea2554021e351acea9651f9b11f2e07821ee3e308221f66b166b158ff3cfa7fb8f48ed410a3779d94aaa1650b11485f15703527cc26a9631a4142a0bd444f8d5b0c5a2b4f38dffb9f80ef4b5ec3d9e54634f92e2ecd34a895d58f73ac36109d6293d15a00c46914fe7eb5d1ef01c942f70569ae0831659325fa2d773d1a62bc2c6c95bc6e1a15020f303f2965c124891101274712d27c19589e465656e13db3a33b415df5", "type": "ConcordiumZKProofV4" } } @@ -2339,7 +2339,7 @@ mod tests { "issuer": "did:ccd:testnet:idp:0", "proof": { "created": "2023-08-28T23:12:15Z", - "proofValue": "0000000000000006010098ad4f48bcd0cf5440853e520858603f16058ee0fc1afdc3efe98abe98771e23c000d19119c28d704a5916929f66f2a30200abb05a0ff79b3b06f912f0ec642268d3a1ad1cdf4f050ab7d55c795aa1ab771f4be29f29134e0d7709566f9b2468805f03009158599821c271588f24e92db7ca30197ec5b0c901efaadd34cca707e56b9aab1a7f14e329816e2acf4d07a7edf1bd6b0400af07a1ba7a22bcb1602114921a48fa966a821354cd0dd63a87ce018caccc50b56f2c9f55a062cdc423657aa5cec8a4c9050100097465737476616c75650602aef4be258f8baca0ee44affd36bc9ca6299cc811ac6cb77d10792ff546153d6a84c0c0e030b131ed29111911794174859966f6ba8cafaf228cb921351c2cbc84358c0fa946ca862f8e30d920e46397bf96b56f50b66ae9c93953dc24de2904640000000000000004a547c8619f3ff2670efbefb21281e459b7cc9766c4f377f78e9f97e2c50569a8dcb155f2a502e936d2cb6ef1a73e92af9916e6353b7127d55bb525cb18074b5ec130463e03a4eda583b05c2d63db40a08ab8bf05f930ec234cc2f788d5f5bfbeab3e4881918ce964ffd55483219edd435ac865286bfd313cd834aabfa8061d2ae173cbe4b59ab2bda78faa4c2c937afba80d7fba0822579ac0ef6915f4820f968a74f00ff5ab74e90b0a7bcb2b92093a5e94a54aea1d48ffd1e5bb3fb48069bce0d38776200db38b2aa170f8b27c74ea497c638ec1b8462c490544c1ebe22a5e00000005000000012404b1242ad971ff6e57bfecd2e3068c0ed7a4be33c0558b042de299df63b9145b8d3ddb4ecbba76d96ff8288092d908ab184c8411753dcd5dc9c6d8897a15313597cc5db38f68c4c935053142d3c2da4eb167cdee40e5e4c2878d53342ded4c0000000246959ce33bb25348f64d0e585567b52253b24ce6229bd83b3fae46c03af515c83a652cd7e8fa07c78db0b70a1b7c35af6ee9f0d83521acf7569d285684ff7fc56f22277da5ab40b30a75cb1bcc60cb7a5762919a415740cc09ba27c5bb9fdaf7000000031ed1953514eda42ba220a54d745ec4b454f1f380716279ff43f0bca3cb111c732d09e8eb6edc8c23d8095a14006684127c48353d55c02d7a69d3b6f5451c0d853c6c09e1a4d07097f16ca2a3324081a7301d1810a7844d331ce3f6012eff6700000000040dd23dd94272e26b45418aea3d3cf75690cf88e17f7eb881ff95fe1f1ef61fd63778bb771eea088f2717e964ae8d3ca1b9d7814a57c0c0482b9a65103f616f9b6a4e943c333d4a6cd894f4802e57db6e9a5270c42f39ae770f4472eccea797da000000052ca1395e3dedb1e0842cd4481627aa55b2a592d64ca7f5bf6845baa3e22647d73ef788e3576f6467206a7c57b1a6b63e9ed774aad4ecb7eaa8fa6b440a7a76a665733b664b5ab5038897f85ab2cbcae9a5a58b6e1e0a442dae026c2b74174b4658e84db7c2c90b21acf4b39f23b83db7f98baf1c6c5153c0123932d329d73eee0000000c003349aa2906906b01ab75f6b6897787dcfc7ccf96212d74d02558468c8b5856405cff39ee6e21fd7db4a2b6b02ab8a6b770c6f2604b2b8db00b38706fb31efb3a025993bed7d839a22f09f5ddafa524032766f3d175cceb640c9a58a9308b3d7a980101010262c5c9fc27e61854fa91c43236139ba5d944e9e628cd1b57b9c045fa114c490000655c0c404889511e939c8c0bee6e4f8199363ca505203e3c4bc5fe45cb5664db6b82bf5f16c7aa92ca5988914f5db5202e23be8939f5225dc0aa2f3386f57cfe0044835f8e5a723bde4dad0488037806e4e094abac57d201a0d1c825023027c1aa1d057b2f767acce630ef8cffa0806f5c0a6a71b1bc3e4c4f011b267830644eb70054164b289d57391c9c6dc767624d83a6384af2ab164fc80a41a6c1fd88dc6dba69c64fa9892188c32340ca6807e9b382759453c52d4ddb7ea65bb1e76be70eab003845506b51d820542c77bc063d112d53ae60687e00b6d7d8b845ff69443167795062cbeb5af4316238d72efcf11237689c4fa7c78d31033f5f26baa14640aec901023f799320ea06418335530b3370f2a3ad555bc335f847e167a177ed5e7320384d000000000000000502803596b4ba5ea05b1fea2b78e292f935d621453cffcd207e10f3072b2813ca3e963cebf05b19cd82da4bd5aad1dcc7fda1492d7ffc8f532bc4b37e9bf4753b7ae6b8f08e05a851052fc6ac7617ce68293678747d11f9a508bab6f7a60edde9c4a27fecaacee7cac6eb0072b08de2040391f5aff1d39c1eca45e9e1ceef6a680dfdccb7c8ac5cff24ce02454dc58ca329b1413f5c39f6a27d2341d7d30041f5b52e38fa03b8888556cd7a2fd6a8012a233d7ed79910a46e4090e6e6bfffea9f0e0ade8a970e7b6480833d376652ae0c9777209a785c5a254fad593a7975d4ddeb5dd25dd7d83d97bdb2ce1cc891220eb3a4bed2913c5be128668a5a88973ef7a314fb5a6df50796cef77dec15ba05b11eb627ccc3db214a61a4017bc3120f09f8000000078a266d8f2078084649b2ed641128818654f98dc78097cf82fb9ce0c6991b18539fc1fcd9dfed877dd2deecf666001ad7b7423143d3fc06e26ceb0caa7fc4bfb01e93e4f9a526ea814ac0e62ea52c5c53822b0dd82eba58a098ab4f453b17fde6820cc74e023722080be7eaa211162d5b83c54a149d0e533efef9487747d1413d918ef00eb7fe7ace6a56b8ae115ee2f3b37c6638b3a0432be164f4a470a4242ca12f166a59d153f703cbb2642c303d2956292419c97b3f9ae170b24182789692b759e754eeb963745d43f97392774f02b6751fb299b4dfff4a56de20f26fa97da30dd49f48f282e177450959047edb1a8e44cfc98d5b2f5961aef7ba75aa7884977cb3fa85d994e532b9a1a8e9c858f7c5c2d6fb386f1d33d796006c868c6faea2d60fbb0d81cf2198f996553684c7b18d7d1bed0f264aedc6a7fcdf7f1650f39c049bdf5123299c02249c947826faa1826a28e100a24f229775f61490a8829edeea2ea86649e258875d4be63e98bd45143cb9681a1b2a3892b61f68c2b58cd793aa738350605769568745244a7a9c7d0514525745a2850f05eecfa3dd378b90b59678564617db5f7549bff21e5fa72f8229e28245371a7339831a004d8e2a2ebd935b1c7747514458f6bd6620f60ae168c5f27ae8cbf6fc43b2d4201e0ead6992978537653ffdb3b05b32aa8234a3ddf4e3cc2ea898e95b8b1be35976d65cd7f44509cd2ef2717e8fc362bedee81c0fa87f0cfaead1202669041d5f1f7d2ed362c7d1b6f1664081833912f0ea2965a332482e08fa46e1de20b0ce239a8797ddb19144d980add3e9e1fe8109868a83472cd5a495cf9674b6ec0a0a5ef5f8cb6991c40c6e96f625389cb56de87eca9526b6efd349f0bd44f1c232337c9176efa03e5ca6b78a80064793ea605a23d6e7d8ad865360d2e29e18647accbac4c5ae984b649fb9e5062f5a16f58324782bab8d4008f5eb944137a43bb031072d9127fa382cbb5eb07c7143f70e405edc38fd0d6bea2fba80388bf8a5aa0cf5e3ad9cec039035240c33b7dec4981aa53e914f67ac932328b31f3fc4d0aac1c19a4da4dab1b525a63008d0e40b86076a1b7e9f0f219955c76798ae8d5131eee35e9900c5cdc8b58badd7022044521d7ad239a91bb2ae1a02fc61472f7d3629d14070641a1eae899e6e379b568caab0141ab86ad93488e61340d917ae4f2871782b64bd070e7dc49c57ed667b35d3f84db8fc09847fb3693e84649dd1c57c317340cac5c6ef962b44e37e9bb84fc222677f00d1ec332e25e81531a84c524e23800e4ef69431345966a6ecf5aec3ce00979684c2861be62231ab74b97953a8197a39251d157a1304a673724ef8687b27beaa474a7056543dfe5cb70502ffc62af63e6ad983b75f4be55185c2b5bfafc698219dfb5079fbed6f7a21f480bae1111ad333f72f8f00000002843454765b3b8b53bb33880bad2ec21d3704ea9c04ec2a0ee82219519349767c74b93c03f3d6b35a7deba79a16051427930281f7b6e4477be5aee7cf3e365bacfa95c28a10afcf8627bae2eb4091d7270f05c56d39517bfc9fbe8c291bea271ba8490429e3a7dc4c30758f8a4c1481ae6e1b5e54187bc0476797d9a9ad2dc2035c58ba233a1faaa72f3c2503000eab59b4e01708ac8f549e4098cb764510681ddc21d86976771ace658329dacfc3232f921f7630948ae70af7c9093a42c596cb6710353288322c0a66f3e62935d8284ff9894a86fae2ee1ba619b96547e0056a192121dc406ecea4bd342d300124bd20d415606fc3c8a37fa0056cb3b4f64f9a0487cbd29bfc97194ed8868ed4e458c7b2bf8ab6f04efee532502cf588c4f26b9b2830baa635c56857be5fd6803fd35d508881bd7cf3b5872ff84640384e2576bd93d4d86fdafcba2df3f29036491573031ede2ddb09dd092ad890a68f07876aeea856a0eb127ca4c08896db9bdc0211918711eddb3175615dec61a6b00ac88ab5ece1be74a55d69d3b2d94815c542fc9da317b86f78570d167c356b0032e10cde818eeec642cc5e4a85aac3dc4ff60d6d747059218c3f3d0c918b5fdb5e0e7559404f25bd8f7ca73432e44261f4fe0c1e1a7bd944e21771168a80ca5529fb6d195bd1a150c3e8c6e8677102aba4b3bb0831c4c645bd6b0f7ed3db492b204e348738fa7a61a2f959ccb7747e3ae7471eca3f8fc2c66bf734b15f700acb82ed23c400000002a04cae736db5790f72295d165d68e0d9bda882cd9e46a4c724b4aec31b98ef396064f56d9e4884cd84aa415de23ca479b89e0735074fc47e66fb75f55308b2bf5ccdb176784ddb550f769586c9a9c154671b6f347a1f4419b1ebfe96e59142e68233bcff4b5be7957cc0bb8c436fd8617f1591c73687194346e8dce9fad3cb3decd80f4e742309707fc5a8927518611099e471bae562f9fe68af039631e6f5177fb5f7faae75f2c426ee6817b6f03a1fb104aea55f29069e3ae442f24f389e7f10399e22ff0c8438bd8475dd309b90cbeae55ef9724bd22ef44553c07eaecde90901fdd15084ee4e3f9b5b6cdacc1042e3277ba5127cdca7c66061b9503287be02b387e119ec10c4a8963ee52710d75c21710881bae7fb5a8595fd43a9156419f8080891e50139bd4af14f1ba25ebe0152b5e83d115be493372e147742d8bfe3a8269e8ecd27ec055a11055d5405192cda8c8db528f06b120fc2e3f47089897411b3cc9ed940ae6645bbc674a01a9babd2c8ed3909640ae91ef01a3039103e818c70ee3be85aa3f3804adca265c3fd97cd8d94f4f16aeaac2f6bbd06c218a421dbc1176d53c8192bca54a39ec1a4ade163b9b0c4f60b07980b7373a7e61a64dd7e28c3882ee5511a8bd20186e63bdb37713478816106bc23241851486d10ac03bb45c9df3032ffb14ce3e0d6870e6c9c8024dfebe9396a56aa408d73c719ee34052dcb8f90f3f327891ea1e6e67096e0cb22407f2d772cab457af6810288f6a867000000079348680adeaa4311e21fc4f31c2f50ffb0e427bd011455f0b3151b36b3f52c94ddf8d9079a9b485745bf99c6e5220a3ca6c115c208bc42493413fe641bb8326d37c1ba622785d04a8f7e104f591c0fafedb770c1363e67aa0d130fc434c8bf7f8ecdf1effd86e1f53c80ae9564e67ad747c84fb31c129d551ee311fbdf30c46a9cc5e7b9b8997bd91aad8de5589ffabf8a776bdbe60b2e463b90041b2247db219e6b4a5bf2ffa23c5af0bdbdedcdc8c080040061280a8394b27cb253951f8464b10f257f944db3d1545dad0cccd866d7da659256a0f104580190aad200cbb614ebf17552e8dd851b769fd19b49b0fa34b9e6a679e83101bc2f5b8a1d102aed0544d12d78bdb9a39e455da446d102d9ad21096ea853fe444923dc57c31d11ce2b8a5d882e831edc6cd2e9ad229a0c34263131854d77fdd15bd11d9820d617bd5ccacbc7c9407149fd92b46dab47e60afeb09001f49d837d5f09c0ac9da6697a5224d2808296855826429fe519a859a17158c21d38f7cf9c222602c320a2b5931a840237bc5674e3dfe9a217425a0660b349a9524c529a7b978f81488b45b9e93f7b8436e9c7d9ff19d85c2214a4fdcaab9261cd2add29201c3b9d6ce4ce657219400ae109ede3507f5057aeb85849cbb8f55593d43c18737c27b86fb33c1617fba13965a846407748fd33ae7352bb119ab71b8e09487842ce37569c13f212ad925041188a19a0bf71468ae290c5d5561bafd547949c4e5da973992729a849bf5fa4fd04eb55b3a8db7cccdc3a0ebdaa3cfdc7a7396ecca820682b40d078bdef188b609045d76fccafb6f8def22071b9eb1afed2082feeedd741b7cb89d073bbc63f773ae935249a3c50566ad71b42de17b8c7f24b153785c863be33115391516003c1d9989b78130bd7e74c0f9dcce55da0201a1eaacdb37549d84da95ee20ca70ae13e95a97a7b18b67e75b8ec1b41ad55049ada043a39a8f8282878c92ca3ba266d23195041e1198f125d0695f843b597aef1edace684e90b09abebaa85f6a101", + "proofValue": "0000000000000006010098ad4f48bcd0cf5440853e520858603f16058ee0fc1afdc3efe98abe98771e23c000d19119c28d704a5916929f66f2a30200abb05a0ff79b3b06f912f0ec642268d3a1ad1cdf4f050ab7d55c795aa1ab771f4be29f29134e0d7709566f9b2468805f03009158599821c271588f24e92db7ca30197ec5b0c901efaadd34cca707e56b9aab1a7f14e329816e2acf4d07a7edf1bd6b0400af07a1ba7a22bcb1602114921a48fa966a821354cd0dd63a87ce018caccc50b56f2c9f55a062cdc423657aa5cec8a4c9050100097465737476616c75650602aef4be258f8baca0ee44affd36bc9ca6299cc811ac6cb77d10792ff546153d6a84c0c0e030b131ed29111911794174859966f6ba8cafaf228cb921351c2cbc84358c0fa946ca862f8e30d920e46397bf96b56f50b66ae9c93953dc24de2904640000000000000004a547c8619f3ff2670efbefb21281e459b7cc9766c4f377f78e9f97e2c50569a8dcb155f2a502e936d2cb6ef1a73e92af9916e6353b7127d55bb525cb18074b5ec130463e03a4eda583b05c2d63db40a08ab8bf05f930ec234cc2f788d5f5bfbeab3e4881918ce964ffd55483219edd435ac865286bfd313cd834aabfa8061d2ae173cbe4b59ab2bda78faa4c2c937afba80d7fba0822579ac0ef6915f4820f968a74f00ff5ab74e90b0a7bcb2b92093a5e94a54aea1d48ffd1e5bb3fb48069bc75feccbac69acb1e8820f76f2e4d01c71e89676b7427c3e9c32bfec40ab015250000000500000001245ac32acac9af918c50bc82ca3e73ffadaae30bd326a69d5f3eebdcb96827c35f4e37798564bc39592753c95e193a981fd740dacdc6230db544d633d1cd40595f845915a2168a7424a91b2e4694fcaef8a73022cec58427e746748a9e97cc6f0000000234a314e4c14923566a22e6c0bb137572c2f2f19a1ef4f4fdcc99636ec64c517d129a59b3fa9592fec05f4bd46aa458af7ddce49fad6f0c50a7d6a30ac5844bab1093452de134fb06918f438772997262d9efd10c7c198cdbc24cb2fc426cce98000000032f275d292c75644f5cf792e9d0052a5a052dda1e6537d198d2ce6394c74fd0485e3c3611c91777e2972f9515f94d8821a107f33bc0724a3fa6ea862877866ea86f90f3def72307aece11d0234179ac41577d4043081ec0bebffad01436e5c78a0000000447b010eeee3659f16947d2772bc7e7ba317820df93bc917218804af2d09b242a0b75711ac5dc55d9a97ee0ce434f65658880427822c391c57db564edb16c59d957a5c75cf83bb5007881e96a846387eb43c3d4add3f5c2d6c2589ab0794c613a00000005186e076d537df6fae24790e8dd8212d33e3ba6c7a8d7b66f6e8f5e61a36af86808748efdb5bfb09bfa4527a2be88a37e66bd1441a5a7b56070486af75de7dd416f4a09489453096103f36eed8831c7320998db6f77d4f65b65553463a00e1cf25ba3106151234f6a0589785074d694f554fd5b68c61482c156eac0db5026b70e0000000c005224652292d29b5027867cfa4cf2c37deb269104206cff553e2be0b38126d5c607ec4d94d0c6b083fd7964ebe4920a530bb30fcb4a6cbc36240c0a97a8ed7abf02046e59587f9824b5e6200189d49984ae5c64a42c47b289c10dcc9efea6ee00cc0101010252650ad1fb2d52a65b89190c202d8ae03f46dfc2813239a88c0522fedd43dd1d000f779d999e44e189ada898c57238598c807264842e04fa17bb8cbc4dc6ed76a33a5a60f732a830e5f06d534fe0659746075b7cec27bd7e23bd6028299f8af060001fd4fe6978c981c680bfc23daf482e6befd3bd21ef409d3e0fb851181e65a5df0cff347c383acbefd6707828362cda9cb1309d01e3040aa94344fcafab693c57003fdbc028eba48baecea549ef683165e6cedc80b01f487eee8982f3faffd8a4055ac72f3d353d2f412be417dec4be5ea8a827301db88cd2f03dceebe30941a930004f1e3046c74895ad8d1fb2c0dadeeb1e2668470bc21f72f6a4f10bf3a0c668cd2be7296f5aa0655ff2fbdfd969f9012ab8bc0f517021ed7a1d091bbcdb2cff95010267edbb0be454bab6621827d9d5cf69d83717c8e89196600433c1e579d7ee5cfd000000000000000502803596b4ba5ea05b1fea2b78e292f935d621453cffcd207e10f3072b2813ca3e963cebf05b19cd82da4bd5aad1dcc7fda1492d7ffc8f532bc4b37e9bf4753b7ae6b8f08e05a851052fc6ac7617ce68293678747d11f9a508bab6f7a60edde9c48c13d67bdec6bbf4761217631a71322079090795f777629ffeedcacf8facb69e1230239148dc52550d185cd271d4f7aba50823b4e01de91b91f02c40d89dda2062f17ca7983c9f49cdccef3f8dc5d71cc024c9dab0ea12637928f6190c7de9bf61c3a1f41d41562ad100571b1a3bd89b5b1c27c65ab7cc5d3afc363814fffca5627dcf15591b3aceb699f1223f29ee9f5e2809e94bdf44eb9c423c891c852d9336626f55e570796260131a6162f833e83a911fd2e41fd3bbaea4c7d63c184e9500000007866f9af1ca9c20f8cf300ac0818a020dbe42e48b99173a831fb067e721ef724f2d16ac44a6f014169ba94d0d234ec00fb20c38021c8acc0b14908881998f575c3d009f3cd36f4c3b8d7e644479f5c132eec36f6fe5087bcd18eab86df82f57768b532d0b4d9e8034417fb14024caab31a63d7518d6cd7f554173aa073ff62e22b2d3b97dd4c5f0a4edb258d89f59872687bad25d48ea6577d0d6571d34cb7d990f4c146fd7c905edf8e222d62e1fc2917d98b2f93d902f210944a70d63b92edab3d64ef612683f0cc574da0c46f815839f7235e258e4c16b8bfff5997b897279fbeeb617d175082b3683ed179b8c0f2f91f98325897aec404b1fcb0d78a03901cc8635276a78046b55003995a37bfb51ff0cfe622f6973bef94925289580e0388c092f5e42b7c11c65b013b6bd811de318e1cc837b4d83b375eb6ec38b44e33c0e4bfeb0c8be70147e0b2f2cba8ae03d82db1293f7d5cb408913d37dbf19e116a0e555ec4bd7fb215fda8947963b49148353e36f60a7ff9b13e6afbc0d893bc0a74d3002089abd1617df186aca13a3a4d2f27c4194db6be720c88c493f8018fb8580307243afd9de4e7b79e7fda88124b6df014dcf20b4918e6240fa55253b1f9bf584b609692d33bb01f0752a1bea6481d66a4c838712c78383be77fa8a31c9b283340424bde4540a642b78c9d90f068475e3be84cad3843413aef74bfcc321d99b80949a0823c76a41714b4f84d5f099530fe0c7823725c0f20c545dd127fb36ca89003287f3c413ebf9646bc40305a62144a42e572bfca0ffb9db450f861fa6a2845034c429f03fe4e3e944c001802da438e8be287aa6348f108ae11ff51f64d9bb40b650542ed87955687faf7a428805e8df21e364ac06cc08b3b508ee88a8a573b304ba54501d9cb8cca7e826768ca00ac75d553790104f05334cafde3719dceeef81e22f650626780aa55b751c6f4cbf3414f2073f8968682e4b5dfea500fcfcf896118abddfa72756f4a6e3cc3716a153159c4e114d89ebc1ee6b1671039035240c33b7dec4981aa53e914f67ac932328b31f3fc4d0aac1c19a4da4dab1b525a63008d0e40b86076a1b7e9f0f219955c76798ae8d5131eee35e9900c5cdc8b58badd7022044521d7ad239a91bb2ae1a02fc61472f7d3629d14070641a1eb7ba210e608b184475719fee24a957470b5893d2114e7112dde2d1371febd0615dbfe1a4b501addb6e21ad9ac7c405a7932e83a504e1d5ef067744ae2a27fcb0ad451437fd210041890659b91b5ad0f297679a2ee45c93468c711626231c44522515da8c38162144aa7e79fa4d4667b2618c4821d732e7ee040dfec90605814405cc52d50e838c0794986543ad9a4cb4dec47f85616cc88c1206b88ab7b969a93847acc76bc835b565cc681e7503559f966beb9df30a80f56e90d8df2ea8da9b0000000281e5e75e2a3ccf9b49f9692a0cbcb188f0e6da132a43bf048176a17681ce0341a7a4a15135ac1bcb5ecc390a011bd65a91144f8e5d34fec58023e3d020e5e35d9b0821d73a7f40c43c4173a092b5d9589e6a816e48f3ac477fe134d8b960a2c1a9f4e276b23f7fc33a6eecb64d848f4034b1510c02af80b81eb8a117c135880add259efbe719125be613652c3b2e7c1c8a1860df0e5a590c7c79e10fdbe646f630a56c9d750f8b08ec211f694026a94e4149687161a59f43e60b4a16ed60e1e66cc6d61b33bcde6935e679caed06268d858ed12fb7ea10ab8eeefb7179be8dbe65147246faddac341f6d56aea39af3a6b0eb936bdfe10c288d1874704535f9780487cbd29bfc97194ed8868ed4e458c7b2bf8ab6f04efee532502cf588c4f26b9b2830baa635c56857be5fd6803fd35d508881bd7cf3b5872ff84640384e2576bd93d4d86fdafcba2df3f29036491573031ede2ddb09dd092ad890a68f07876aee99d3e4719e313761d5be72d94590caeaf4f636540e8b89ca6bc1574d379749645e678224a35fe91336759cb8f4a2f92e827ed5fc52c93c9ea435f63423d110722a24c0c9be53ec6e5fbdc7fb702742a666175a579a83e717e3e7bdf390d1d41519ab6c5b414368e72aa4fca69ceb823138922d47acf1cae011a8812d780701761f3ff411e4462e7f0e5a249ba6dfacc8e7e124484e1049c7ad53f85ce8f72fb20bba7688d57b2dbb3b18011cd66a22f6b767b4e76aa319f829357dfcbd5d085b000000028c72593db9ab1e1effda6b3951a2e1dbda1e28be9b95edce268873d203f45458edb7063d53c06315813e4af5b0c7327ba9cf5d374b28362537a171dde4ccd88437cd33bd25792b563a5cafbc76ab295981168d42bdcc54c2e9bf37cbfb804e2e82727d8a382a4b999be576a36a3379c2290965257328b782c71ac9dbd0d906af7f5d594dea34447325fd0bd3a86dc1a6a536e08347ef37dd281e2e4d7409afb857852fc758f7911beffba8d77d9d0045865489154824b9dbc2c88a9b9c23d510701e9cc60ece9890faa12e90bfc99c782440f8d12c6c9efcc7728ab702208b5d33985fb6f8785b91a09a72fa3679cf06a67e475f6e0cfd22fc266d5cabe9d2d702b387e119ec10c4a8963ee52710d75c21710881bae7fb5a8595fd43a9156419f8080891e50139bd4af14f1ba25ebe0152b5e83d115be493372e147742d8bfe3a8269e8ecd27ec055a11055d5405192cda8c8db528f06b120fc2e3f4708989741194b44ee21034f97bffe9e44029aefc1f69205cb5be7af39085acadbd69d783703b0604b8af0d315804159554a04ad296b6ba0ff6627e6959a45c25f63ed3648d4295edb0fff4657eb20396c18d2f18dde479655f4a42308e1564ca362b25b2a25530755010e93c197da18baf1770f3596fe118c2328419a00821c8575c2f159f146315d4aa83fcccdab86d1e79d9112beaaf1d650bb59b294eea76587b540b71418388ca21f5c790744aa1c0fa4b2f6e882eeb9c3ed5e127fd6fac7441f70a4000000007a3d7c92ad23197b21a7c184d632344809fe6826e5251fe5fe2cfa78a9b42a5f494717e23b4a9c1da2e36765f0795bc928121d69c63fe13c619ef8ec52b16b167b8d1af417385745cb79366a7bb0ed598feded8b6758fbeb71bf6b68016e6890c9095f002664dfeb053d9fb448f87af254c6f4734766f5485306b78a8bcfa0ed7a7cdcc7390b35dc4326828923a14c28a977a916552883a5d91392a71ada76fcd2578fc257e246322cc24469bb34c36e5b9b38d2eea2d40fe97b6903fc521855e83893d07fd884a9418f00daf07b7354d77ba2b384d4754f4759c5e68c8dc9e28fde3af8e46149685434569ee3fb1d08e8c50028857fdfa97d24e351f7aed684fe61bc19ed1aaf03f52c38d7c94364f8422564347029ce11cb9762da235a20bfa89d562b17630db743ad169496835df51e9ed40af684e83bfa24325863c29b7318857c35d6acca3812c03d415e66439198436e4769c067a147f8343584458d87e51c99532befce9e556a715759ceb5ce1b28f4a0dad2db2030b921296269df133ab4c8af9244f3b26653944d621b3ca182882ad03adb6c05614a57275dc94910b1e1b0cfea1ca92e53817350e2e50dcd78d20a45b4b3d5c442644233bac6ce757f01a93d925279de07cac72477ca340eb9ac91441e54ae383823fb1d4813f93b78a94ecb22e516ec96d56b79e60bf81f998d67f20c912572d88f2b9f259c9b7c858d63cf4345af7be530fdff8eff071fba82fcff337cc8716712d16c2c4c25e08f4b6b1eca1de73071eb698decad384c02208b717494b05c1451edeab3a18dd3d932e7dd6b0e4b6a696c912ff53a3d1845d4a0d7580ad68692a60210e4cd62504939c25261da64ac80e1c4b5b64ad554a90fadc1caf6126cf5981b6750e508badf0c89694975b042bfe976032e00ae7b7cc00aea104a68e82ce1a8c41dee412e7698ebdc2e1f3c2a87dfec9515ffebc006f024e282c42a9acd02b77025023d6956cb754919c0983c4c28b1e123c75ef631e601f378c4e5750a51949a85e7dcb7d01", "type": "ConcordiumZKProofV4" } } diff --git a/rust-src/concordium_base/src/web3id/v1/anchor.rs b/rust-src/concordium_base/src/web3id/v1/anchor.rs index f88779acf..deaeeb63f 100644 --- a/rust-src/concordium_base/src/web3id/v1/anchor.rs +++ b/rust-src/concordium_base/src/web3id/v1/anchor.rs @@ -1260,7 +1260,7 @@ mod tests { "issuer": "did:ccd:testnet:idp:0", "proof": { "created": "2023-08-28T23:12:15Z", - "proofValue": "0000000000000006010098ad4f48bcd0cf5440853e520858603f16058ee0fc1afdc3efe98abe98771e23c000d19119c28d704a5916929f66f2a30200abb05a0ff79b3b06f912f0ec642268d3a1ad1cdf4f050ab7d55c795aa1ab771f4be29f29134e0d7709566f9b2468805f03009158599821c271588f24e92db7ca30197ec5b0c901efaadd34cca707e56b9aab1a7f14e329816e2acf4d07a7edf1bd6b0400af07a1ba7a22bcb1602114921a48fa966a821354cd0dd63a87ce018caccc50b56f2c9f55a062cdc423657aa5cec8a4c9050100097465737476616c75650602aef4be258f8baca0ee44affd36bc9ca6299cc811ac6cb77d10792ff546153d6a84c0c0e030b131ed29111911794174859966f6ba8cafaf228cb921351c2cbc84358c0fa946ca862f8e30d920e46397bf96b56f50b66ae9c93953dc24de2904640000000000000004a547c8619f3ff2670efbefb21281e459b7cc9766c4f377f78e9f97e2c50569a8dcb155f2a502e936d2cb6ef1a73e92af9916e6353b7127d55bb525cb18074b5ec130463e03a4eda583b05c2d63db40a08ab8bf05f930ec234cc2f788d5f5bfbeab3e4881918ce964ffd55483219edd435ac865286bfd313cd834aabfa8061d2ae173cbe4b59ab2bda78faa4c2c937afba80d7fba0822579ac0ef6915f4820f968a74f00ff5ab74e90b0a7bcb2b92093a5e94a54aea1d48ffd1e5bb3fb48069bcadf8b1e6664e83c2e12f47291bdb470b47df740c2623fc0d7a0ad34fb9d64fb900000005000000015cc1f983b2a7a7debded95108cb89f65381917f8120e4deea665b9e3ca0a70212ffd481839d094662c2db50136796152e41cbbba6bf87bf02e78abee35933a9e67285f7d35a7d9bf24a37fe49620f6255f1ac78cb4aef1151e29944ecb702643000000024bce7d3ca07538e9aff9772b4cf9c2b24a67b91397f5994226a093d298b4a23633e46e7ade5ef65956edf9de27d9a975ce949f97d73a0d5258cf8e8f87adaa570463fd2f9559ef5f7dd364dc4abce05550d0e53475c9918b1e23c7b34d89d8e1000000036440ecd3c6c671a0c40ed70f884a9f5212c3d1e05af61e4d6da7c58dde7fb1ba05f41f668da5d1440ab95f5ba3691046c0b1ff3478c731785cefa5a4dda8cee6665ce1ac8c8040c932a44ed2bf077cdcca394d7eb8e3c3e91f40cc6512db24c5000000043912fd3c9a5e2167423188eebbbda54c616ded7580a3eb34500916687f11d4f00ce689c028a28370fdba1edaaf3b7a29881cf8c2602f961b2137779d7a6fa18356936262155f6b04dbda6b1d35c67248e9396ef932abed13006651b2882f155f000000056ebac799466813bd7f9ed65a9bb5c91ec3710d88aa4c1f6390e475170231bce41cd0d020868b143ce9d0a8f1543dd1ee2f5b3e85525dde8d04e1d12ac2063ada69d7bc2ac5b50cece6fc9e386d6c4b576417ae6ccee6321e5a61599eb3748d74206742d6126667ee04141b72104aacb32e580b5db3f549777b7f035a2a16a0860000000c002224a394b6edcf83998ee8d9b58095b38d6b6c5c42521d5c31b81dbc52ccc0264bda335a1e7f61ffa2bba8d356c1b48e01b58f266c50363c1798479f7a9365200266f9eb50ef10d0dc63ef4ddb238831148e01e0e38d8e0b94c373597dfb5d295501010102299f078d1e543497070baee391c060737354c015f1d0bf82faf3d78d3a48376e0005c7dc83b81accdb0954f6ad51d0ce35ad66b3201f5336ac20c3c1c08ff856272ce6116990d8266acd40309cf895f52e62e1bb357cff558e53e18d37e544ee7b006c88ea28f1502893beaac7e6d9c1905fc58c051cf077e1093c89c81cd7a671800f2b98037e637fe747200f9288272de1c67170fa3f2d3e29911784a49bcefd78004b04bc8c867d1afa3992d8a11f3a8ada1ee1ed48f348e7ddec33d32b824ebc25457b8151147ba053e00c478f95e6cd752578973ad575e09919fd6caf59d11f600024d5e6122667191464557a4e758cce911968ad9813e181522f6c2e2703576aeb69aaf0412219e752b222329904b4c29949a6d9b18c91604704dc071897bf05760102531993dd2439551210bfa191f9b66e49e693c6c189260aa605280886804ff692000000000000000502803596b4ba5ea05b1fea2b78e292f935d621453cffcd207e10f3072b2813ca3e963cebf05b19cd82da4bd5aad1dcc7fda1492d7ffc8f532bc4b37e9bf4753b7ae6b8f08e05a851052fc6ac7617ce68293678747d11f9a508bab6f7a60edde9c4a41e80bca9bbd4fad0a8dc8db2b4264dc25e35599bab793956d61dbc0c012f01b393c8cf7254a24c18b6b05f1180a555b712be45be9a9be20eed26c68683c81afb0de03c61af110d25cf10e364996a30b29fb0d4543f9bc2ed0dd1a6def19cdb09ef7c0f24f29ae9dcd5aaf809bd67d86b9cf8e639ebd28385a2ad954db1851f59737318d78ad8a990cfdc208f2229fe33ceba14c7b34dd9f0687454384206f36bbc7762e015510952538f10e502b1be9cab7e8f6637964aa58a100eb72eed7d00000007aa3d9d70c9a1112cd8bbf2f23f5d436bb038970c1cd718b65865369ac172f3edee2e353d68ca75a309e1299d03f7a50083914b99232b25f106f4cb9fea1f5ec988aa749975a9f0cd1ba56682bb2b90d2f9cb33be146d6fc81584707dedf3d660ab47522d8bb4d47e832121c792e5278040eca2900b7a8ce4c073554602a1feaa82c210550bb95f35bd4aceb1b0bf08bd8fc4e5b6c0432fcddc18e086d915bf7a5076df3be63b3ce6087abbf7e0a3f8f530407803f8fac559437c881a99c1282fa5856086c95f71ebb957d9db6514796dead2b87375f97c24bbab00d666c024872a84c8b8e26097352d10eeaed535055a85ad5c6827309fc69583c5a6e7533572222c9b38c509feb71eaec826ff703b9c9442a9c807e4a530b07912360708f441b742162d2708308e50a6a213efcccaa755288a0b8008bb7310f7cabc4a6ef02f4257ba0f91ffa237c88a3d4640c61870acfe90ce01f8112a6e4ed0e38b717c2895e438068b952e78b58461d83764d0b6e375398a5f5ebd492365b16fca7f96648f85a67c865334e72a44f5753a74fb20a49778648a6832c5eabfd6c75eea8b72235b1d4493149fbdf9cd61ca31b97d9d851188135e28dce14b0911a42c014fce1040a46d53e226011a686c216476c1775cc05b7388b72444d3c0be400c543b8588ffc4bcc9fe12a56824164b7f46c69bff954199f0df17ef4de3da2849f94e503c1d5ecee6303f58d70c61df996c383c8673869287b27a490f120a8c881087df070f3592d60322efe69da5cd4493a9c373faabfe517942a1c4d04157f18052dd87803dc0fcdf15f61f938f80ba8c44010d0950a7f8d6a5e500d74e10252a2024c5474a7a03479f929811c0ba0b6d5befb5ec49396f1c578880d587e4b949a80bf50eacff5f3180963723fcc2fb53b386547e87ce814b34d7721e8bd65fe49d594d21ae53cbf8207c14e5afc034542804febe2dcfd61dc28b7d73d3eeeeb87d5c64a83e378487375585888dc7bef240bf88f8c43782c49d7964dd3b5f0ab7f219039035240c33b7dec4981aa53e914f67ac932328b31f3fc4d0aac1c19a4da4dab1b525a63008d0e40b86076a1b7e9f0f219955c76798ae8d5131eee35e9900c5cdc8b58badd7022044521d7ad239a91bb2ae1a02fc61472f7d3629d14070641a1eb279dda86a693d9bd31eb38e677c5f85070e2cc05cb574ffc4340fe23bd4682a7faa8b4c2b7c86486dc9a3f6977442028f9adf7b0e8211df3770f580eb6f0ee86a7cea689a6888c31bb81a72fd82d7138f3cb5fbea85460d59faae9ec97e7ee914fecabac546163a683af1858ba5dd471653021a0c170b9ffdf2f63b00c225a3545ee75f4b4d1fae8e5ae3ab2a82616cfd1d28a7194606eec6a7820a4330771c0a652d08e02a418cdfa8f77915e1598b1c9c3ee01f6f2c84da643c23182c0bfc00000002934c0abe8b38512e0a8f2cdda0f7a4ccfdb8892ac0c47577b1736ff0a8760da7ab80078380f9a3f76c29c450f01e7846b7c265e81c7820c1069a01ec112e4c9f5ef2224beea1b6726f9d571a817e7878dc0081e58a2e2d6d8897590ca8bbfad592c86a5dfa048c11a1d5256168e1abbec3294fff524270dcb4e2ccf4ad1c01b2f50617bdea7cde01dfd40abceb826b72907e4627a972d0d94ac18d90b070e5138542620c162fee11e35b615c1332af593d165ad2124ee700c905eafb47bb8c1c3efa9dee61560288af752e95391e6ba8931ee2a555706893f47e4e1db4cb6ef8495975561f3d7ab3cf72a254d2d09143ab8b72a20fc808b0007d465bf25359ec0487cbd29bfc97194ed8868ed4e458c7b2bf8ab6f04efee532502cf588c4f26b9b2830baa635c56857be5fd6803fd35d508881bd7cf3b5872ff84640384e2576bd93d4d86fdafcba2df3f29036491573031ede2ddb09dd092ad890a68f07876aeeb1670ef988687963f3e3481e448df81c3887471be037c05e55b9ffa04295049a53a7bf2dc6f8f444bcdb55aa860b68c59860c8918ec080cf9da5e53ef614446784f1a59370c718c3f22b1951bf719e97e5af289407f6162ca5c790f93ca249db4999d4f766193d965457595fd708fdd1d5e45929132988a250cbb6d49047ceea5a7d229ba568f9022cdfbe5e6cd7c201ba74ac1ba1a90679a02797e3661300ea1a0cfd5b1b5f013992653794a219d4ecdaae19e0598582f48ad7496557fa709200000002b52319c25eabb5fddbf0f1329721ff50aaf0ebd5adafe2886f458f0c7f2b004d206168484605a5a9b504465ba59d254f8cadc1bd5a2ab181ddfdfafbf205f0b40ba5593e87176e42872e5e3e46e42f28eb15d389bc08e95a05bd6fe04dddd7ddb240dbca64d7b462884689308b73495a273780a25c953d32d5c298c888972df69d450581a07e6465d284b56b4eeacdd2811b655cbb86a9c7c19649bbe5df94d24b840d895c372374af8e8692e9bf66b142b3214f70c3da25c0258bc8c2eab1555f1fa270c6d9fec15b2bffdb1905f86ed286cf41ee3fb30bf7cf3e51bdf05e943fc018f613b86e8ff48aa3d9ebe0cdf6bf8a6d35626ec7b0934b6094160c087202b387e119ec10c4a8963ee52710d75c21710881bae7fb5a8595fd43a9156419f8080891e50139bd4af14f1ba25ebe0152b5e83d115be493372e147742d8bfe3a8269e8ecd27ec055a11055d5405192cda8c8db528f06b120fc2e3f470898974118e681c1b99e40a986ff74b97d61f5c4e88e52c7aef82fabd2f44256ffdbf980635cdf40bdda88c767ddbe643aae7ac4ab61f5b500bc405db39d6d0ff790878a76c5d09f8a5a21010b71ea9bccf811db26d23f437bf196fc0e42ef701068d51d33e4afcecc6ee66ed2addf6ebd1480dfdc2f9e25462d573493bd645e8a7a1336118677a442c14009d33e4bfc1756b09039789a7e806d5050c2fc70e33842b904042dce8c4121c2e82db496052715bca21c7706daf66b0990c88c2c628c1d4f23500000007a23a41c1b755d06289d7546233e2ae891c82f7f17ed0422d1f8754a20e0c7bce8b7159ea6d0680246f5542f662195263a45c271dd1a930a5791e9a2fe7d8a64cf235b20f07eb1e5af8664c15686c45e5e2811b570e27a8dfab1f71936f038320aa43184c3d0ef0bf81fc71b55d7130275eda4f851c02843c47bf5632bcddfa1797116ece6d63df159b63a22215a1f28988f6d990c1ab70d364d886e322f3147783665325302327ba4ead49d6bb759b6f45e95e391081185357516860fbf607b0932cb683faf83fbb9f31d8530facc9f9fdf04fdcbd2d83ca60f8f7f73852cb0410eaf3868c2e0d42dd2cc3cb96ecb7498dc3c337260451ee86b551c8bbac56ba350a2767f4afc4c891c00030c60629f6bbe0df10804206ed13fbe92971eb40868a9758765fa6499efeb9d1b3f924be03dae0815318a70a42a9bc836139cca5cae5239482d6a65affa6fedcc9776e77c9b65eb66297aed36094dc65d7d9f13302bb6d2b6a079cb6285e96bfb14809a8fff7fa35b63a68f295b6b977f73a4055e682ab6564c3a56bd9b63cc39c6fbdd01646b75c9d35974c4dd5cc4ad44113cd0635f903d48339fdf5276585b1ed66a991ad291af87e3b5c4f2a9247272977fdc8b74fb9dd5eba894f6e78184602e73e2045fcd3cdf8192fc038e3778599338cd9a4920be187e5b212a010a6351e865722a5ea0f55cecc492ec52b11679f8e3d2e9ce2e9bbd37683c44fef05e8c5c84dd0b8920b14c2aa9dd0e47ef96f2442a2969938fa8235eb06b166ee46115c3be5ad83cc73a0175564b6080401ca5ebe79ad8b383b94b8d167eef0459deea932a3200ee323c1542543b71b15bcf84a0d6bfdca76d30e1c5e593602a6d119e488db1b91fa39572973fc2e47ab7eaac489df7379fb9b4c2b5939f5a84b21d13545673640bc9750d94ea0aebd5fbddbc811692004e66eae5c8461c1d31a812bae721d8c76c44939b499779660f27b6bcc89168941199c1edfd9175ee71cf46036c9b362ac72922e504c42731eecfe146629257d01", + "proofValue": "0000000000000006010098ad4f48bcd0cf5440853e520858603f16058ee0fc1afdc3efe98abe98771e23c000d19119c28d704a5916929f66f2a30200abb05a0ff79b3b06f912f0ec642268d3a1ad1cdf4f050ab7d55c795aa1ab771f4be29f29134e0d7709566f9b2468805f03009158599821c271588f24e92db7ca30197ec5b0c901efaadd34cca707e56b9aab1a7f14e329816e2acf4d07a7edf1bd6b0400af07a1ba7a22bcb1602114921a48fa966a821354cd0dd63a87ce018caccc50b56f2c9f55a062cdc423657aa5cec8a4c9050100097465737476616c75650602aef4be258f8baca0ee44affd36bc9ca6299cc811ac6cb77d10792ff546153d6a84c0c0e030b131ed29111911794174859966f6ba8cafaf228cb921351c2cbc84358c0fa946ca862f8e30d920e46397bf96b56f50b66ae9c93953dc24de2904640000000000000004a547c8619f3ff2670efbefb21281e459b7cc9766c4f377f78e9f97e2c50569a8dcb155f2a502e936d2cb6ef1a73e92af9916e6353b7127d55bb525cb18074b5ec130463e03a4eda583b05c2d63db40a08ab8bf05f930ec234cc2f788d5f5bfbeab3e4881918ce964ffd55483219edd435ac865286bfd313cd834aabfa8061d2ae173cbe4b59ab2bda78faa4c2c937afba80d7fba0822579ac0ef6915f4820f968a74f00ff5ab74e90b0a7bcb2b92093a5e94a54aea1d48ffd1e5bb3fb48069bc8686fc39256b42d9078c37efbea87c1fd885cc40b86c6b6842aeaad30238698800000005000000013c26f1e7570b8e3ad601d332bbb9c35831adb9df15067d5f237d446a2e8153b70ba3653e0fafbc842cd1e99db48a2e28bfe28a735da15c3689cfab8996b88e3d19def84044ea3ac4f735857236767a1d0ee12b4de9015534ef867bce670cc1f20000000233507984f62b349c5ce61a9bf04d3cf7b379773c6177817bbc625a3bf6b86a59589ce33c6f93efd633a9dc041b05cbf8af3572c63a2b50daa60e0dfc866087b5023f96284d7217fb62b277166a19e2adaee7c82f9d0dd42aeaded693720be7e5000000033583e65be2844c92f97eb3b7ea0a0b30e6b2c6e03ecfebb2f0f742115ab16c7931380522321ed887458603ed2dd6b3f4895e0f86b58688ebd1f57b53067cad3a32cfbaba3e4368b4eb662f6159b492e0799577f999dbdc0a3490c0b5649b0fd1000000042bb84fe8775902b247a49a581a92ece9486f4ea11d95812faf9df8b40bf4628f2a6d155cf7426f0e83a8a68e255b1fddbc68b6a4eb78eb28c608fecf4770f66e26201f17689c9cb9d6f5b62080152ee5befed2d8bf8911ae018c9648ffe2938800000005510ca234128a8adfd4321be100d1694ffde3492638da333347572d91f3f357b9468f520e552954f5130a40513cca4fe1f33f5222ad2353e9b3a7e9f59aba7a673a36152765fa2b13d9551a38c0738f13c01e1f2f254c222540aa06199e2ea42f48ca21e75e7218e80d73cfa9ebe7201df9290a453f08def04a62c605417635030000000c002bceb59abdabc30e3b70290ac19593074e9d7f961efeca01fee2ef20b57f02d555844560253d558a449ce90462d6b1e1c2e7a26048fce2e1e4c31903dd45a7cf026d703a25aa6c7d7fa7c01dafacbe8dfa2eb1687ea31f871065ce0b2d2415fd5701010102264a9a01ce2ca3e74b6c2f655962ca0f085e4e4bb2ef80a3ec063bbe1e42e525000d49e88a1dc318b16f4d9d5bcd14bd4bf2c42ddefcf76ba82bab7dbedc18b0fd194ff722105fe1becfe4d00fe4393a095bb16488eed6ac63d4e819b30c8f8c61005e46e26cd70fa7e980478bb030e670c4dfeef74d4432032ca2f84c38f7f3f46536dd55990d58db28c331391288bf92d66fd313b52837eec7046349d513e5ede0003297c35d8a68126638e98790eda7760155a8b7f60606bfb5bfed718aef68d2ca546f29035ccaa4844b807cba88f75692604fdbab294ee34230acecb332d0630200639f8ee330a373814e58ccc9dfbd6be0da6b8ba48c682c3a9ac0203f7180dd1e131351d06fdb63543b10163d1bbe98c059aa3af441741b96a8504c55a052daee0102002ca2eaf66f108739028e28aaf41cc51035724127467ef995bab1fe02c51231000000000000000502803596b4ba5ea05b1fea2b78e292f935d621453cffcd207e10f3072b2813ca3e963cebf05b19cd82da4bd5aad1dcc7fda1492d7ffc8f532bc4b37e9bf4753b7ae6b8f08e05a851052fc6ac7617ce68293678747d11f9a508bab6f7a60edde9c4b2b0c42b0f664e4bcf343ec942ad3a3f4a5ecb36839f56bff87c2426c4f0555555c8cfdfd332fb47efe94beea2bb1fc1a6d1d3a913881f6e526249330bf9a475a1e284544d68d2479cd5c225ee735aef5e5ace0d6b3b34c94c35352ae850d8d46ac2f9c6e79ce6649675df832606b5950f8fce0e2885b9d5803ad04192d29a290cabcb0e335535226b00486425d3be8c6e99a9bc3943179b26bcf1cbfd0cfb5629c4275cf8be413c044780587151c2e8b47d01c30caed3080fe25dd211f1ac8400000007a9ee8e6929639d7c7334458021546461c7074d514d4d233c3cb0a390c4ce8a6929865e02aa9e75cfc06330c369b999b3a0092e894284e919e928018bf6f9fc59e2efa0723e178f0554b2cfd03f7b84b41bc1f7fde0eb14bb0b64aeb2aaba5365aa90f01c2b87050e47cecc06e03c630d70c4b77afbde8684b2625f36db1aa4b32d55790329b8b071867e3243f05ecc1d951b6b46f48dde51e330c8c53aeed4d3a8b0e1efe15549160104a266c0ec380719c341c179b6c84ab729a870e47b4a2a85d3d1f7b65b0674eb5ea8e2031aca456f0c486978edc6303cf99712f0441aecaaebf0af4224afeb8b00daf9086c9438a0496a2022412308d90382360e62b136202da01b49fe8fe8f06184ec135ec74780ed1390515b1670a056679a6aa14e5e82076f1d1dfdd7eb4b15b05e61de916094e0b03d904ff4d278e1196d63fa3ff41b859bdff9812c2c8fa5d471337e5637b5e3d951973bdb84ebc34c77008a9a07834144ef2f1f43b6cf21a5ca2caf2a2d6e2a626a5232297878e063994943e55786137afa8b9ed43cb0193b2da7de8494310d179a29c214533285fb7f4626570e9154733292075ce80efa787df24eb3158dc4f9f2062cdd21b8bf602d7796b3efc85e49aba74d1b12b3e3d81ac9546c4644b136eb7c9284461dcfd64e86b817a89993e8380b1caa6705b873f874ec55e44734d03857715016a28d0fcdb4ae859b5e9459ff54f27c22a007e150eb951bdd87973e67517a5b3e858019d99c070cf15bd98394277aa86632769bb1f06f520777a5c3cf93fc3e9ed0aea1a25ee7b23f9991c99d0de14bf926378685662fb7d69f99d38954b433b45a09d500862369bdc4843ba94e0571f5c0fd4b1a45d7cdfc94bc4974626a3d306c0a0d0fe432f61e1735b8cd381ff71ae284ef761d80e151962a600fa1685e773cf2ef362d2844d73ceece02844bf20baa65aa79308e5d9b0ded37e246e1ace76438b1292ac7d78550729d68fd04a3bf974264785cf0fa2cf5e0f8bcca94a3771c466d0763e410b1039035240c33b7dec4981aa53e914f67ac932328b31f3fc4d0aac1c19a4da4dab1b525a63008d0e40b86076a1b7e9f0f219955c76798ae8d5131eee35e9900c5cdc8b58badd7022044521d7ad239a91bb2ae1a02fc61472f7d3629d14070641a1eb12db115593e2e2b5fc167962dfafe209fc006a112a42237794cfa2e915a90991364919ab89b3fd7b523fda624bf0b3da77b1964ab8c7f32ff2d305348bbec302152932228963226b197703be314b4fccd2c8c9e4384038e5bb7028e449e37cc3939b5302187fc21fd2918392f549f852c573f32b4fc55d84a27acbb8f910f6e660439b07f061a86c4197e4b70631edb869f5b4050767a8625ce1dbfd6127d04289a671b1bf343f5cba72d154bcd3c5c35cf06f92bccbd940c4651e344406a5b0000000288522a84e55bc513f4ca48849428ef9f956a26ce1f0eb739e49d1b57c97d57cf15af9116cfe49ee5196a533d487fcc5c98230612cb382cd1e49ae60d012d0f6c6985e77c0bfcd1687cd89ba2e66932768a628da4afe63c1378b490ef2551d0a187a1e01dce092b0c8acff2b1df84f75cd09539c5abd90642bfda99a648fb9551248131a0eb457743af0d58b958423836ad5dd1615920f8acf1f2c688c9316e7cdf6440cc41385cc0d862b83ffe0af503ab694152fb829871b31bebaac20bb0a1715d28c811c0a9769d5edf16f7d5a306dc18a006e5e6de36d5a65d575b975e69100cb92dc287cc9f96392dc333a2a835cf15898127da44ff241b278d16f190f20487cbd29bfc97194ed8868ed4e458c7b2bf8ab6f04efee532502cf588c4f26b9b2830baa635c56857be5fd6803fd35d508881bd7cf3b5872ff84640384e2576bd93d4d86fdafcba2df3f29036491573031ede2ddb09dd092ad890a68f07876aee8b7d4f3cd01356db57bfc20fb2fc248b8aa5b5c272947abb3848a0ff0b8c0a7ea9ca608c88abf84cec05736f29dac8f494c68c9ac9d2729b99558481db1844b8c59a0ae1b2c3c03ad9091867841fb547a648b03a29fc981d3b776836e55e96301ba62e26162eedbade649030ac2a9159dd34111ddae649f5f7de192a5fe647d138bcdecf6c3c8ed141f8de4456b6417e7d61ada423df9979eb379192788acabd2abda66af33ad18d39e14fcf9178421c9d96adefaf25c7767d812c2b5cd8e69400000002b1afe618ab0194e831229483914d84b7e3dafd2e23eb661ada31a871212ff99ed369bd418720f213725334ee0cd84f95b8335d2d2d436d54c1320bc90ccf9924607fc27f19704fa7818673da4bd0813c773b9e1edaee40ecce0958925b3f6b8b967e6072b376a6d3ce64d8fb95338304b46b914e474b7a4cfd59ee7706a9357a76ce92c2d00e711bbc524cee09c534ce814460d87b7470d03e25dd08bb0bbc825adcd9f66cf1b2138e741c1a022314a28cdc6ed9f4ad02658003e23c04fb42ac66ac5ad6470723b5a67e3e1926f45eb14b9af215b3bb28a190f665cd1fcb6fa64c3d631299695d9534be64cde4ae46d70a17bbb8b2aaa9c71b48025131ad3b3902b387e119ec10c4a8963ee52710d75c21710881bae7fb5a8595fd43a9156419f8080891e50139bd4af14f1ba25ebe0152b5e83d115be493372e147742d8bfe3a8269e8ecd27ec055a11055d5405192cda8c8db528f06b120fc2e3f47089897411a97c0d726fbfa85f94141abd5ba2077e7056928ced031005efda3b6ac53b75163fe6474e558d4248967488941dec796d8e02cccd22a907a34219254b2febe0e6a7e1b9ca1ceb47515a3c827020b682562a6360c9270243244b9805c00ef24464072e5d636ed9eb2e4c020256425b4860cd2bc0cb48ed3ba171bc0b3bcf2739f42b8999615ecbabcc61abd860fde30f279f88dcec4aeac2a3fbdb95d75f3f124c0195245ad176aad3ff0d6bb4d6357bd34c772c11a3b70e23bb74c18062a2144500000007977f36ad0224878709df8ab94ec4bb86e738816e72f29aab307be192de4351f2f8de29757395bcade5d5497dc8ebe18981bbe8c651d926007cd1df483e3e70e60706b092b091616f5624e6c0b44593c471e2ebebd239a814fcb3fbd16293241ea586fa3ec47029be2698a45c652dbc190a9bf1eb4b06b51dbea0755a0f8a6cb9c622ad9e03dc83e887694e87cccefa23ab070673cfa7b9ad54a4f7fa4343565da7e9575467283b9a8c82381418d2d4e426161b11f4714924f86916618b7b8251a1bf436578791d3beab78fe969a0b2504cb046dd9513bd23ee40797f49fad186964572c4fff0164783c40725667791d09376e2dc0ccb83954c8f16147f68350a2393dcbe707e87f740e5301171c152824cdab75110d13c29063caaaf4a155e41833f1be03275f2e677322861094eb5acb281e6af8665df37fa359e4a1d84ab5d5fff7e71d8f1d77f45b0f9412c117b3bae6d238024bf89ab60da2e7e7a467be2a7611d53dabb3c00e095d1732c787e05b861d10169c2828026023f35568b14fb9843b4b2bc40ee2dd0764b83d8107d3a9f35c93ec6e2f76293821d447e9e6486128eeb886f60b3ee3cec7c5bd5857540a3de5ba73d8cf08683efa9810b5ce5039de30155d3479cf475c0e6ab6e92dafa254e7c213ee15e214bcdf0408664c89986fa429f0647c71aed6c3bad7deaaa888503ad57d87d96e76a35442aab90dc396667e8cc66560a92f6084fbf9fb86ada861f13fbd25b5b3640698d7bd77d0128ab0cd675f396259761fe588c09d8819d7b2a72ef2225c20cbf9955f4840cafaa87e3e8a241e3b61e2e2d709a372f9ce749e29c591f8a42e29afc9e0ee7bdbb4319d452cdc62b349b7c3d776119c0de54837e43987a3645162e3d61aa5cae315e3e51407f4665ae2b0989ee607fb02c1a8425e955b4c9ed3315689a3750630fbc5aa63a24c5c3b1610276bd1eb2f4a99f53ee6fc354cb14a3a10a1d2dd307d7800be3f64977023e8b5cdd9d7a7588ffea391f4370b56032062f1d33c90f89a15d01", "type": "ConcordiumZKProofV4" } } @@ -1328,7 +1328,7 @@ mod tests { let verification_audit_anchor_on_chain = fixtures::verification_audit_anchor_fixture(); let cbor = cbor::cbor_encode(&verification_audit_anchor_on_chain).unwrap(); - assert_eq!(hex::encode(&cbor), "a4646861736858209eb4aa6091914e2c5a5e64a6c5d2e23f5172b40ad8bc4d53088acf7bf43d1766647479706566434344564141667075626c6963a1636b6579046776657273696f6e01"); + assert_eq!(hex::encode(&cbor), "a46468617368582081bd9a90e378357169599e5a70af14e1fd004383ea326738daf808c505600509647479706566434344564141667075626c6963a1636b6579046776657273696f6e01"); let decoded: VerificationAuditAnchor = cbor::cbor_decode(&cbor).unwrap(); assert_eq!(decoded, verification_audit_anchor_on_chain); } @@ -1358,7 +1358,7 @@ mod tests { let verification_audit_anchor_hash = fixtures::verification_audit_anchor_fixture().hash; let expected_verification_audit_anchor_hash = Hash::new( <[u8; 32]>::from_hex( - "9eb4aa6091914e2c5a5e64a6c5d2e23f5172b40ad8bc4d53088acf7bf43d1766", + "81bd9a90e378357169599e5a70af14e1fd004383ea326738daf808c505600509", ) .expect("Invalid hex"), ); From 387000ca07110458f1531fcdc5112172553311a1 Mon Sep 17 00:00:00 2001 From: Allan Rasmussen Date: Tue, 25 Nov 2025 12:27:09 +0100 Subject: [PATCH 08/20] fix --- rust-src/concordium_base/src/sigma_protocols/common.rs | 6 +++--- .../concordium_base/src/sigma_protocols/dlogaggequal.rs | 2 +- rust-src/concordium_base/src/sigma_protocols/enc_trans.rs | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/rust-src/concordium_base/src/sigma_protocols/common.rs b/rust-src/concordium_base/src/sigma_protocols/common.rs index 44277de64..04769975e 100644 --- a/rust-src/concordium_base/src/sigma_protocols/common.rs +++ b/rust-src/concordium_base/src/sigma_protocols/common.rs @@ -216,7 +216,7 @@ impl SigmaProtocol for ReplicateAdapter

{ fn public(&self, ro: &mut impl TranscriptProtocol) { // add all public data in sequence from left to right - ro.append_each_message(&[], &self.protocols, |ro, p| p.public(ro)); // todo ar trigger tripwire + ro.append_each_message(&[], &self.protocols, |ro, p| p.public(ro)); } fn compute_commit_message( @@ -312,7 +312,7 @@ pub fn prove( let challenge_bytes = ro.extract_raw_challenge(); let challenge = prover.get_challenge(&challenge_bytes); let response = prover.compute_response(secret, state, &challenge)?; - ro.append_final_prover_message("response", &response); // todo ar try trigger stability tests + ro.append_final_prover_message("response", &response); Some(SigmaProof { challenge: challenge_bytes, response, @@ -333,7 +333,7 @@ pub fn verify( verifier.public(ro); ro.append_message("point", &point); let computed_challenge = ro.extract_raw_challenge(); - ro.append_final_prover_message("response", &proof.response); // todo ar try trigger stability tests + ro.append_final_prover_message("response", &proof.response); computed_challenge == proof.challenge } } diff --git a/rust-src/concordium_base/src/sigma_protocols/dlogaggequal.rs b/rust-src/concordium_base/src/sigma_protocols/dlogaggequal.rs index f8555f746..d5fc3727f 100644 --- a/rust-src/concordium_base/src/sigma_protocols/dlogaggequal.rs +++ b/rust-src/concordium_base/src/sigma_protocols/dlogaggequal.rs @@ -37,7 +37,7 @@ impl SigmaProtocol for DlogAndAggregateDlogsEqual { type SecretData = (Rc, Vec>>); fn public(&self, ro: &mut impl TranscriptProtocol) { - ro.append_each_message(&[], &self.aggregate_dlogs, |ro, p| p.public(ro)); // todo ar try trigger wiretrip + ro.append_each_message(&[], &self.aggregate_dlogs, |ro, p| p.public(ro)); self.dlog.public(ro) } diff --git a/rust-src/concordium_base/src/sigma_protocols/enc_trans.rs b/rust-src/concordium_base/src/sigma_protocols/enc_trans.rs index 43ecbf1c8..3fbc8791b 100644 --- a/rust-src/concordium_base/src/sigma_protocols/enc_trans.rs +++ b/rust-src/concordium_base/src/sigma_protocols/enc_trans.rs @@ -183,7 +183,7 @@ impl SigmaProtocol for EncTrans { fn public(&self, ro: &mut impl TranscriptProtocol) { self.elg_dec.public(ro); - ro.append_each_message(&[], &self.encexp1, |ro, p| p.public(ro)); // todo ar try trigger writetrip + ro.append_each_message(&[], &self.encexp1, |ro, p| p.public(ro)); ro.append_each_message(&[], &self.encexp2, |ro, p| p.public(ro)); self.dlog.public(ro) } From 6079f60d25f82dcb285bcf76cadd60bd119726ca Mon Sep 17 00:00:00 2001 From: Allan Rasmussen Date: Tue, 25 Nov 2025 13:14:49 +0100 Subject: [PATCH 09/20] fix --- rust-src/concordium_base/src/aggregate_sig/ffi.rs | 2 ++ rust-src/concordium_base/src/eddsa_ed25519/ffi.rs | 2 ++ 2 files changed, 4 insertions(+) diff --git a/rust-src/concordium_base/src/aggregate_sig/ffi.rs b/rust-src/concordium_base/src/aggregate_sig/ffi.rs index 0665379df..acbe7d253 100644 --- a/rust-src/concordium_base/src/aggregate_sig/ffi.rs +++ b/rust-src/concordium_base/src/aggregate_sig/ffi.rs @@ -234,6 +234,7 @@ pub extern "C" fn bls_prove( let ro_bytes = slice_from_c_bytes!(ro_ptr, ro_len); let sk = from_ptr!(sk_ptr); + #[allow(deprecated)] let mut ro = RandomOracle::domain(ro_bytes); let mut csprng = thread_rng(); let prf = sk.prove(&mut csprng, &mut ro); @@ -252,6 +253,7 @@ pub extern "C" fn bls_check_proof( let proof = from_ptr!(proof_ptr); let pk = from_ptr!(pk_ptr); + #[allow(deprecated)] let mut ro = RandomOracle::domain(ro_bytes); let check = pk.check_proof(&mut ro, proof); u8::from(check) diff --git a/rust-src/concordium_base/src/eddsa_ed25519/ffi.rs b/rust-src/concordium_base/src/eddsa_ed25519/ffi.rs index d1483addd..edb81cffc 100644 --- a/rust-src/concordium_base/src/eddsa_ed25519/ffi.rs +++ b/rust-src/concordium_base/src/eddsa_ed25519/ffi.rs @@ -152,6 +152,7 @@ extern "C" fn eddsa_verify_dlog_ed25519( Ok(proof) => proof, } }; + #[allow(deprecated)] if verify_dlog_ed25519(&mut RandomOracle::domain(challenge), &public_key, &proof) { 1 } else { @@ -194,6 +195,7 @@ extern "C" fn eddsa_prove_dlog_ed25519( let mut csprng = thread_rng(); let proof = prove_dlog_ed25519( &mut csprng, + #[allow(deprecated)] &mut RandomOracle::domain(challenge), &public_key, &secret_key, From 5f8ae65a116eea91caf820df70c6f31c247ad431 Mon Sep 17 00:00:00 2001 From: Allan Rasmussen Date: Tue, 25 Nov 2025 13:48:39 +0100 Subject: [PATCH 10/20] presentation transcript --- rust-src/concordium_base/src/web3id/v1.rs | 66 +++++++++++-- .../concordium_base/src/web3id/v1/anchor.rs | 6 +- .../concordium_base/src/web3id/v1/proofs.rs | 92 +++++++++++++++---- 3 files changed, 133 insertions(+), 31 deletions(-) diff --git a/rust-src/concordium_base/src/web3id/v1.rs b/rust-src/concordium_base/src/web3id/v1.rs index 0d18c8f8b..f349d6f56 100644 --- a/rust-src/concordium_base/src/web3id/v1.rs +++ b/rust-src/concordium_base/src/web3id/v1.rs @@ -125,8 +125,11 @@ pub struct ContextProperty { /// Claims about a single account based subject. Accounts are on-chain credentials /// deployed from identity credentials. -#[derive(Debug, Clone, PartialEq, Eq)] -pub struct AccountBasedSubjectClaims> { +#[derive(Debug, Clone, PartialEq, Eq, common::Serialize)] +pub struct AccountBasedSubjectClaims< + C: Curve, + AttributeType: Attribute + common::Serialize, +> { /// Network on which the account exists pub network: Network, /// Identity provider which issued the credentials @@ -142,8 +145,11 @@ pub struct AccountBasedSubjectClaims> { +#[derive(Debug, Clone, PartialEq, Eq, common::Serialize)] +pub struct IdentityBasedSubjectClaims< + C: Curve, + AttributeType: Attribute + common::Serialize, +> { /// Network to which the identity credentials are issued pub network: Network, /// Identity provider which issued the credentials @@ -163,6 +169,42 @@ pub enum SubjectClaims> { Identity(IdentityBasedSubjectClaims), } +impl + common::Serial> common::Serial + for SubjectClaims +{ + fn serial(&self, out: &mut B) { + match self { + Self::Account(claims) => { + out.put(&0u8); + out.put(claims); + } + Self::Identity(claims) => { + out.put(&1u8); + out.put(claims); + } + } + } +} + +impl + common::Deserial> common::Deserial + for SubjectClaims +{ + fn deserial(source: &mut R) -> ParseResult { + let tag: u8 = source.get()?; + Ok(match tag { + 0 => { + let claims = source.get()?; + Self::Account(claims) + } + 1 => { + let claims = source.get()?; + Self::Identity(claims) + } + _ => bail!("unsupported SubjectClaims: {}", tag), + }) + } +} + impl + serde::Serialize> serde::Serialize for SubjectClaims { @@ -637,7 +679,7 @@ impl, AttributeType: Attribute, AttributeType: Attribute ConcordiumZKProofVersion { + match self { + CredentialV1::Account(acc) => acc.proof.proof_version, + CredentialV1::Identity(id) => id.proof.proof_version, + } + } + /// Metadata about the credential. This contains data that must be externally verified /// and also data needed to look up [`CredentialVerificationMaterial`]. pub fn metadata(&self) -> CredentialMetadataV1 { @@ -934,7 +984,7 @@ impl, AttributeType: Attribute::from_hex( - "81bd9a90e378357169599e5a70af14e1fd004383ea326738daf808c505600509", + "9eb4aa6091914e2c5a5e64a6c5d2e23f5172b40ad8bc4d53088acf7bf43d1766", ) .expect("Invalid hex"), ); diff --git a/rust-src/concordium_base/src/web3id/v1/proofs.rs b/rust-src/concordium_base/src/web3id/v1/proofs.rs index a090a9e88..a6e3d8b1d 100644 --- a/rust-src/concordium_base/src/web3id/v1/proofs.rs +++ b/rust-src/concordium_base/src/web3id/v1/proofs.rs @@ -1,3 +1,4 @@ +use crate::random_oracle::{TranscriptProtocol, TranscriptProtocolV1}; use crate::{ curve_arithmetic::Curve, id::types::{Attribute, GlobalContext}, @@ -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, @@ -54,11 +54,9 @@ impl, AttributeType: Attribute, verification_material: impl ExactSizeIterator>, ) -> Result, VerifyError> { - #[allow(deprecated)] - let mut transcript = - TranscriptProtocolV1::with_domain("ConcordiumVerifiablePresentationV1"); + let mut transcript = TranscriptProtocolV1::with_domain("ConcordiumVerifiableCredentialV1"); append_context(&mut transcript, &self.presentation_context); - transcript.append_message(b"ctx", &global_context); + transcript.append_message("GlobalContext", &global_context); let mut request = RequestV1 { context: self.presentation_context.clone(), @@ -73,7 +71,14 @@ impl, AttributeType: Attribute> AccountBasedCredentialV1, AttributeType: Attribute, AttributeType: Attribute = self .proof .proof_value @@ -225,14 +246,18 @@ fn verify_statements< AttributeType: Attribute + 'a, TagType: Ord + crate::common::Serialize + 'a, >( - statements: impl IntoIterator>, - proofs: impl IntoIterator>, + statements: &[AtomicStatementV1], + proofs: &[AtomicProofV1], cmm_attributes: &BTreeMap>, revealed_attributes: &BTreeMap, global_context: &GlobalContext, transcript: &mut impl TranscriptProtocol, ) -> bool { - statements.into_iter().zip_longest(proofs).all(|elm| { + // Notice that we already added the number of statements to the transcript + // by adding statements to the transcript. This acts as a variable length + // prefix of the loop over statements. + + statements.iter().zip_longest(proofs).all(|elm| { elm.both().map_or(false, |(statement, proof)| { statement.verify( ProofVersion::Version2, @@ -265,6 +290,12 @@ impl> AccountBasedSubjectClaims> IdentityBasedSubjectClaims = self .statements .iter() @@ -344,6 +380,17 @@ impl> IdentityBasedSubjectClaims = id_attr_cred_info .values .attributes @@ -370,12 +417,6 @@ impl> IdentityBasedSubjectClaims + 'a, TagType: Ord + crate::common::Serialize + 'a, >( - statements: impl IntoIterator>, + statements: &[AtomicStatementV1], attribute_values: &impl HasAttributeValues, attribute_randomness: &impl HasAttributeRandomness, revealed_attributes: &BTreeMap, @@ -407,8 +448,12 @@ fn prove_statements< transcript: &mut impl TranscriptProtocol, csprng: &mut (impl Rng + CryptoRng), ) -> Result>, ProveError> { + // Notice that we already added the number of statements to the transcript + // by adding statements to the transcript. This acts as a variable length + // prefix of the loop over statements. + statements - .into_iter() + .iter() .map(|statement| { statement .prove( @@ -483,16 +528,23 @@ impl> RequestV1 AttributeType: 'a, { let mut verifiable_credentials = Vec::with_capacity(private_inputs.len()); - let mut transcript = - TranscriptProtocolV1::with_domain("ConcordiumVerifiablePresentationV1"); + let mut transcript = TranscriptProtocolV1::with_domain("ConcordiumVerifiableCredentialV1"); append_context(&mut transcript, &self.context); - transcript.append_message(b"ctx", &global_context); + transcript.append_message("GlobalContext", &global_context); if self.subject_claims.len() != private_inputs.len() { return Err(ProveError::PrivateInputsMismatch); } for (subject_claims, private_inputs) in self.subject_claims.into_iter().zip(private_inputs) { + let mut transcript = transcript.split(); + + transcript.append_message( + "ProofVersion", + &ConcordiumZKProofVersion::ConcordiumZKProofV4, + ); + transcript.append_message("CreationTime", &now); + let credential = subject_claims.prove( global_context, &mut transcript, From 62ed4283f3ea99b74a5ba0db0e43b1fb517e0804 Mon Sep 17 00:00:00 2001 From: Allan Rasmussen Date: Tue, 25 Nov 2025 13:52:45 +0100 Subject: [PATCH 11/20] fix --- rust-src/concordium_base/src/web3id/v1.rs | 4 ++-- rust-src/concordium_base/src/web3id/v1/anchor.rs | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/rust-src/concordium_base/src/web3id/v1.rs b/rust-src/concordium_base/src/web3id/v1.rs index f349d6f56..c57fe80c3 100644 --- a/rust-src/concordium_base/src/web3id/v1.rs +++ b/rust-src/concordium_base/src/web3id/v1.rs @@ -1894,7 +1894,7 @@ mod tests { "issuer": "did:ccd:testnet:idp:17", "proof": { "created": "2023-08-28T23:12:15Z", - "proofValue": "000000000000000502b12365d42dbcdda54216b524d94eda74809018b8179d90c747829da5d24df4b2d835d7f77879cf52d5b1809564c5ec49990998db469e5c04553de3f787a3998d660204fe2dd1033a310bfc06ab8a9e5426ff90fdaf554ac11e96bbf18b1e1da898425e0f42bb5b91f650cffc83890c5c3634217e1ca6df0150d100aedc6c49b36b548e9e853f9180b3b994f2b9e6e302840ce0d443ca529eba7fb3b15cd10987be5a40a2e5cf825467588a00584b228bea646482954922ae2bffad62c65eebb71a4ca5367d4ac3e3b4cb0e56190e95f6af1c47d0b45991d39e58ee3a25c32de75c9d91cabd2cc5bc4325a4699b8a1c2e486059d472917ba1c5e4a2b66f77dbcf08a2aa21cbd0ec8f78061aa92cc1b126e06e1fc0da0d03c30e444721fbe07a1100000007ae9f2dffa4e4102b834e7930e7bb9476b00b8f0077e5fb48bc953f44571a9f9f8bcf46ea1cc3e93ca6e635d85ee5a63fa2a1c92e0bf7fba3e61a37f858f8fa52f40644f59e1fb65b6fb34eaaa75a907e85e2c8efd664a0c6a9d40cbe3e96fd7ab0ff06a4a1e66fd3950cf1af6c8a7d30197ae6aec4ecf463c368f3b587b5b65b93a6b77167e112e724a5fe6e7b3ce16b8402d736cb9b207e0e3833bb47d0e3ddc581790c9539ecd3190bdee690120c9b8e322e3fb2799ada40f5e7d9b66a8774aa662ab85c9e330410a19d0c1311c13cf59c798fa021d24afd85fabfe151802cbde37dafc0046920345961db062e5fb9b2fe0334debe1670ef88142a625e6acd1b7ded9f63b68d7b938b108dbf4cca60257bdf32fed399b2d0f11a10c59a4089937a28cbeefc28a93e533722d6060856baf26ccd9470a9c50229acc54753534888e1c8f8c612b5e6af0705dceeac85a5ac3d641b3033c5d3af066f33147256b86b1fffaaceea3bf9e4fd98f7a5371e4a882dd3c7cbe5d9b34e933d6ac224d7198cc4c8d3e5f0cef03fad810ca36499dc3a5e157d435843d60eb6a3fc3c3624d9fef8b5f2f2335af0a8ecca5cf71a9ffab6651d7c899d560264a6c9e361ee10a17dcb18522acdc0a19ab004f15ba1e23fa2aa3bb75f3767678d12c6dc35b2a04bb5239ce2cf35649a42525f42f91d6b80266af0fbd86645611332203ac555250fc29f6bb1b50932c7e48418bbadf57db4931789a0dd44e9b70d437af1ae686ede83e6965108a655caf34bd7b0b587eef0a29350020abae08bd2d979752316f749ab4686da684dcae5b571213c7bfb914cb70965e9b643862f71bab5d22b7dbf7d3f84636ba514ef2cf0c87ecf225e3bdc99e15368b3d814fb1e257ac1fc0b9114cbb8ed594ce50688c88d8ea9d0e97f55e89fbddd282e13d7303d3604e969bc0e699388c2f6fbb310aa82f18af896019d79f26f72fbe3a5dfc6fd30c34ac8d57d499e49664ecfa76094c6fba2372dba87a2b55dd9dc30877af0d6fdd2b2ea54be03b39554bf77b9ad30ef725df82bdb6c5456adf9ac3187ffbeaab1b4ce68782829850f10182deb13eaa94edd3640768224a178b8bac224d12711c7d3bec925db4da9bd1424db872757a1f2e10c9dac40483a69972504e5d69163a9f13c5dc8fc60a1634554a5009d948704f92e701eeb0a5b2cbfdcf62fd7b8cc0db65b2ba52dd1bbe2e46eddeff70f5fb3686917587b82a9cf1e1c8a7b6cf44dbe57bbf83d541bfbfccac677a377ef4e1a5ced1e7e5147bde759150f531780bcfc5658b099787d68277d3d41d992022be434194d8307d2a90a518705017affec5796354ff2432f57f525cf014bdcf0b9fd84b9501d3938259c433b4e6181e2630b56826c4a0c7d03cc0a8768ce7226703cf97ee83d6bc1c0c044a2e0d4439780d1c7351ea8ece10000000298ff27cb9f1c4afb38c535cee5dbde71599f727976298c540cdb7ff0b10a439f1599c9bf879e35746e2fd04dda05368d966efc49f07a5c48baaca5853de36dd2f0c7fab8106f1158f34ece1d0fd8576eb727d834cb0c380c150086e2222ba38283d8c26a9af828584cbd90801cc0c3e1855b9a26f81efd3931000b8a2109ac9cd5070b98963d700560fd6c6de1df8202ac21dfbdf141bdf58ee96d7a72cb2dfba962159a2c9d0fe1d312aca7a56ce97716d7d16e47b7c59e651ee8fe8dbbf56c3048a31df649d9da46f669b80d5cb31c3ee70c5e6a05de8be814833934befaef06757e390f83ce84b4fd84fb9d86eb30a897faa4718d7b5a12c086255a0a21cc048b69df7282cd3234e4423e85d15c09d49fc2005e869a4876fec01369c3b0ec0ae6f710797b4e5294a7fdf72c05341b6887da98066400436af27e739c140e3a481df2845cd78df942a2c0fb01429d5b04cd96b18c0b2bbf764b533a6f095edbea844cbc0d196b4e423c7fd409c1ceb6572812707c9048ec5a373c29e3cefbbd128e1ebe72b84be67ae22e3dfee5b47f57b289755b558624daeb22ce521c432fbf2cab96826ec670f18a194b151ec0f49c31237f35caae1296715571520e22caff2912531b1ee43d555dee29e7105161dfe86f133b3fb7c194e72c12b1eaac010160a3e8a44cad0b1c1ef89d492014997603a37b26e9461572edcf93a011d639550e0505ad8932c2a205c688d70d6414717c7a31868b5d01c37993085cf28d1c670000000295c326f59171824b2fc3e09816b73c6f75a03fb50f611559855d295e0a565ff6d2505f970464ca12e81031d286866dd5b73c285de994b592f8d8c2e64227bcc5ae2058339d11af025cfcb126c2b3c9a7839b87c8d218f93b0f30a0876076eb9598e1ec92a57f4ce785b1a05c01e8db34b4cefe8e518a859aa6d9530bbe72a033af7e87a95433de67b86f389e178b1aaaa53eddcdf1be990d96ba7e7f18ffa83d60385e1a1130dbf245e1b4bac2e8bceb2c1184380e6e0f7876157d7ae074d1fb013266272083b5420b3fc654141046e5bee9e3ffe50497f372d55b3f0aec05873c7409c8a1507c38f6c87b726e9355d5d326658e1e7e67b349ef1a65185ec51802b2a44460fcbf28d7ce0fce6c677113a88b88ec272d3cfac24d33afc47b6fa15259af84fa6543ef673cbd18a44d47420c8c53d7eaf9272dfa62fadd8d118c2055480b6494a67b0346c9fa0b2ba2cba9c0591224a2ed7b399ea35b89111a53059cb410c51ffb45d0aab4b642087698fcb67d55d33a711db3f84a125f970705b68c5ae5b8ea2394c891911d7f1032ec08ec8df792bcbcb1a953214317be0085b4b7b23a45d52a83f77cade01752c7ae6fe1d81bb5dc3b6a74e3d2f4130178263b9e633914559cf75d5902b5fc696198bff1d25812b05ade020d0aadcae022336b3c49639dd8dd90381bb59828ca9a82d87610d1e01b4ee4827f30d11ac72fa911f4439ca4fbfe164dc370e5c96dcc329bbf9972d71e811d17f5dd2ffb760ac0e31400000007b9e19ad95babc1c31bf657ae20a5420cf05bbf024ae2ffe13b363d5404c5a0ef360c54d49e8725210a5bba290d29cb58a2607e5134fdb367631e10d8e159396e39bbc09bd7084038f6b5cebd5386da5cd18cfe3ce9dbf75b51f4d7de00e00c5993a3b4d05fb3f4edb2a8d05cece2da96d7d87081c1610eb949caed95520479c662d623ad1464fee46bc3486521d44427ad8d76db0cc6ab51cb69d1dfd59c1938b68b80a8813c9dad15f9466941e377836693dfdcfc96e12a296699ef77ab274293a917b64e48f413ee2908b574ad8875951ce40dceadaf104145a2a937bce6707a962355a61efbf9379a1da606f98915a21a9255eaf105b04651d789fc90ddab8a402d11fd8e5befece4956d1d0c9c47987c7d282cb045c053fc860e8c07365b9937aae7fa435190992a02a24e388bd0b0836775d0e01c7faba3e92c5d3e8975fcad16cce9e9b01f378a572ab4039e0b8582d4d3a47c3b3fb587483cd1a760e628d0f3d63ac9e8b10cefa8b94d02cade0ab47005ad368f4f9e5b766a5c353a6eb1a7fd5bed46fbd1554c4ec47d8b6d3b38dcc66db969c646a34928eeb40147adc94878a1b237fcbe21f779e723e8a4f6a6cec0cb57205789e8d781bf465a833608b5181ad27d420e0e1f7383c0222df32259ace41dc092dfc745bbfc4bd371cd99e5a1c73baeb8ad15c34e060af529a8babad63c3a131ca089053f498170afb30b26e0f2794b0d1f417d870af7daf37694430db13f00b7af5101723d656d334c72b5e0bbe13478722e954935e6701ecf3cc725d61e42edbb896b6d4dff5b51f48e194337fb086908d50edcb61a295dcf57f54b6b41d5a760f5ff8992a6e45acfec08157dc3640fa1878cdb5ce41cb27ab9096beb3ded0b7cd57c1c4a850abc08ac822a3be26b4deb5a3cd11914ae5ac2c29430fe91be97fea012981dbb389da64d4a794017f91fb40e3188bd7190025a5b39c323a90f5a8496d5f64e200093072f1379728f1f0e741b51db5e4967d1e5437ca1d531ed742fe9ad2708ba06b3f8006d9f6e451166c885818931efbf878b5d041b211441fa707013ebe73e41ca25da68cebf07b67ef99e5fef798d5bdff3378d766b8116e710384d1530280b79e945", + "proofValue": "000000000000000502b12365d42dbcdda54216b524d94eda74809018b8179d90c747829da5d24df4b2d835d7f77879cf52d5b1809564c5ec49990998db469e5c04553de3f787a3998d660204fe2dd1033a310bfc06ab8a9e5426ff90fdaf554ac11e96bbf18b1e1da8a5ec51caa2b6fd6fc32ee131f7ef87126c610792f050563ac76138401936acd2a28d2d5bdd050994b2384584c9c748bea6ecfe85facb2920dbf349194bac86c4d8c60697b51d298d906699f7b1b239852f5b784eefcceef3a9fbc157d4c957711b21591d8bd3f6ee889c55043ac6cf4cba325b25aacee116aaa4544090c6f6505715b9602db53eb3d65f38b545a0fece7af159acffb5816089bed5f6a5b7640f6d16a140ca7abafded72cdbe4f8804655d560865ec5cdcd7fade5ec00a1abcb400000007af0c150c10fca79fe5d585c034b97bd832af43996af6dd501103f83cad750774023b40207c95a4e308d77bb9b84afff2b1affde5b520372b5232f2f736368ca5af4eec6c276a6ff47b8b52d0efe59705b8a2e4c5fcd8fd03ff126cb279088561818d42980c3ab3f1d6554247bd4c5f0576c6eac703e15b37f50febef3a0b9cb9cd8a08d97e8c4663ec74d75b9e0af057820097daf36eb3a608b8fdc794cfc464b07dcf168ad8c53489580e024b56aaa7be41733a27f055f4daffb5fd7efc1b7aa56ab6745221d87503add6d41fec8b5c47735d771990b1ce7cb0c00fb05511434b4ffa3e57b48a65b4afd5d20ac6f1daa14e71dfc41eb61ce6f097f93f586ca43a7d29dd846ccdb00718dd7d74031600bfc04568587ca2b6a3df2b889d9d21ae80f162354f38a8eeb84637af702bc69ecffc1ce9d1a936e141cc9e0b46e39b3421784f7772945f9393e2731e97ad659ba8579c62762fc287fab66e172cd5a0ace34acaf203d02f9576abc95f496ea7e3095a6c9ee4a6f2194d13716caf9851d0b3a66ed3bff369446904ba26bf6e938d73be1f6b697e9eddc531a4037dd45cbeac31195215d2ac022acc7cd0db211f52a3a719aa289aaa83ddb285c69d6d9a48988bcae28451f673a53ccbe4f9464e4a70a05360a92c38547ed9f17c9f901e98836779ef4b7af3215f007aba61e272a6c649f5370a766a5397cddad16ce07a7b4eabefcd63a3dbdbc8101f90e43a1e0d8f2329a1b498617860ef3b37a08cc4445223b5e62cacf38ff22fa24298ada17299ce932a4c935929fc05f8a1b78559af803fd13f7faba91902d3ce16c9c0bf463d2111e7a0e5dc43e43daf88f13e1079e966cce2768fc1a9f890e0e95446b4aeb2f1541991efdac2d80122e8c266f81fc661fe698dac1161ec7528d6e27e98894e48e6de647af1dfa0f33fbbb8fb6dc90f75c2b6cf5a22bb350d6ebddcc0d3ba6d532076a46dce8de18471fd63c7702e2f54ebb6041b5f629647e7ba313fee83171d208cf1f53652c2b6af1c5b378fcd03b39554bf77b9ad30ef725df82bdb6c5456adf9ac3187ffbeaab1b4ce68782829850f10182deb13eaa94edd3640768224a178b8bac224d12711c7d3bec925db4da9bd1424db872757a1f2e10c9dac40483a69972504e5d69163a9f13c5dc8fc608479e5a7b885ed5300b746e24729f07c75a94215ec7a2e6bc01b52f714de7dfc63693afd5d10d3b04edcfb4704a99c64983dc5b1665379da2e164918917e25eb3cacd93a250da5790b3499c4c6c6b0b327b4b38609f94fdebda725d9840fd1704baddeb3ce42b6cf77c9a5a9e7cf79d9fcad623f797f334bde7c1f1b72b0238f522e5d35488db09f13f60ba2f86a883994e5c81b6c937c92ba44b8f9eb78144023bec3a769f8fe532b5a5f523662e23dbfc91e9d3392f1fd0a821d85903ae4d8000000028bd4214b4ce7aab1c510f757c7d862ad137db2a40002bd9b828150d950c6525dc5c54f1d8f144b70c62cbb6baa740ed298733424ad4dc42d9fea5bb89c05b59eb9b4fb1edc063971b7046dd4caa65097c05ac9c8d60d9ac014d75c58d55d64a5b9fa6e69d9a5373cf686b1ae9b138111e2fcaa4398ecffb159ab1166a6c09605a95d364228e82099ec09d47a5ca33493b394cef3a33b32404627b3df2fea323e48ca3437761d906b44648486ee2e00e69a007fdbb4352e905f59f4540a7d22d43c5d6ec39bfa7f969975e5130fe87aba477186d1f486b50f26840ba9e676a46c1ac54737ab10f3d36e50b67901363c30a23ab1aadd8f7c3d4b9f050bed425381048b69df7282cd3234e4423e85d15c09d49fc2005e869a4876fec01369c3b0ec0ae6f710797b4e5294a7fdf72c05341b6887da98066400436af27e739c140e3a481df2845cd78df942a2c0fb01429d5b04cd96b18c0b2bbf764b533a6f095edbeaa93b55f721ac7fd624c1163bd7507799c725d5438282dc0391d1d404d3b3bc61eaf150c5433f8f009e0881922a24e6308302a4b44dac57a9d70e8acef97595401632b5bb7816025493181fedd24679cf28562fd5dde2f761e3c68dac283df0ab6905142ae1694de00d4b9aacdf26e911671b32bc5436bd02e1325cef59ab9eac432752a04d9cc94d597812e8d88d30dae0af5ce15afe35982152837296d2f3800eee823a89bfc817aadd9611e44224cdc8e5dbeb5dddc979265c5d5c5efdb44700000002a24f5463ca685e8a41d7466050daae2fe1e985f423b63fd564e9586819d9f78558c2615e19acb8823594b87212ba353cadd258c6bb1781fedb9cb27fe8fea9498f6fea4b0702ea8b278fafcb46491d620f224447db7b4b7323cf3dcc8b92d556953a1f1132db33ccfd0886809900a5a77956dff23108e05f99697ce1a7b8b1596a48e545ff904d43a1fc255e5fbc4ef383d7c66b6b6ae7a54b7cb461334ee30afd3a72b4b4617521d029f41a5f00bc8c1cde8df2c4c4803076217272ad37a8d0149465dc4f3c273edd845790ceb0e9b4dbc059d3f49180b7c83e6bc07e7d72234c41f36e7c5249be8b6097a9e0d4ac4c9304c63f9b21c17ffd1faf41dfdbf60602b2a44460fcbf28d7ce0fce6c677113a88b88ec272d3cfac24d33afc47b6fa15259af84fa6543ef673cbd18a44d47420c8c53d7eaf9272dfa62fadd8d118c2055480b6494a67b0346c9fa0b2ba2cba9c0591224a2ed7b399ea35b89111a53059ca20a4730876439f653e04a98c88bde58e6d10f4ed5ca46233cb6054480a89806a7992cf6597b6822b140face0bc4de77a54fbd8b74c8b786c101f40bf45f6f59abb820108c5d1a51aa59210bf202f430f8b964b30e3258f6cad0ca8a8b88bb043d28f792f84570024c0a4fb28a1749972686488dd026b629489e3b8e60c99647159e9e3473ddd55ed3d9e56a17174509be24e80d9ae7bb558130bb3bb024cd6117245b472a3ece0eac70f73a68e64d092ece19c328632cbe998c1908c615537800000007966878c8fe3ae5c656fb13d1f07ad16689293c1747063a0c460a3d201c35b9524eb1966883f1f797c1d3025b879b755c8cfb7e0419df4760264ad7cbf17ed76bf12f579a8c1cbc4cf984003295912b123b0a4281df422814702d4e62259530b896bb5c6ccda5ec63219e895729e941e1c1716a4ef57863eb9de953bea60e625765939a89d9bd48f4b5d2caba03aa569889c8c0f04fa75c369b5a4e4d1ffbfff3bf586897d91041d562e42cd8d82ecb4befeb67cf8990458853d1763308841a74af0955364d0aecaa0a26e6649d46372710b080c4ab5037b6808276653a87971374d899de4e33ff946083f12db74464cca51694ad92c0e2d35e5dd4cdfa7cf3794b91bae217d36bc0aa6675ac53b8b230a4565d039059658a2c002d6520428d63a8015fab9c9a49215949fd76c740b61b6d0d9ab62661a3293eca495bbc7ecf3fd2b8c88d9e47e7e7a583e3e8bda2c548b4f8a12e64ba60a069b1683919af24477af10ef3fd8122c1c2011762fee8c5bf0bfcff3e7db2017a12074354b14a8e33a3713e51c622c88a38ee08ae14faae7629a03b494bfb062462305389fcf3b3ef03d52e2a89f8d08b3b2003ace3288ed3824a1fb3e4f5a1df7a56bf5e4f183a695cb05fae2002c3eb779c2df5c7f0467ffe75ebb0a1de856100a1384e36521ba2b14ba461a6405e1ef888978cff9d8d16a2afab190a06cfa8bef6fd5fe8b8453857fb479a85465d3487be0071f7f8a02b9712fb4073243e504bc2078b6cd00223582744730d14487b03c7f9db0b7fbb5c7a12e2b744d5804c28dfeea7ffb8cf11ab8185f04798a3fa52f49ff7f0d141b502e3d547e88865690ff3e5b80d951e287514d5741933209761d4173fa6ede87093c51c33750c5a12794091a1fafd9bcffcb27cb37cce184c1d07ed9272ff2f4cffd2944c946e25ccfb2f5ed017c0b4b04e45e75664b76562618774b3912150a65c9c4e99222226819d6b37431c6353ca662cb7dedb250677ffb5d9e2ee47edfc64da1f96404e307cb9fe181923a9c8c400a0155deaa4f088f5061a91148f29f43574245cf47a80f0205ed62d704f31d6ff1c0a381161223d1b0e04d63c5bf4b66d0870c60963319b59ca50cdb23a28e7fb", "type": "ConcordiumZKProofV4" } } @@ -2389,7 +2389,7 @@ mod tests { "issuer": "did:ccd:testnet:idp:0", "proof": { "created": "2023-08-28T23:12:15Z", - "proofValue": "0000000000000006010098ad4f48bcd0cf5440853e520858603f16058ee0fc1afdc3efe98abe98771e23c000d19119c28d704a5916929f66f2a30200abb05a0ff79b3b06f912f0ec642268d3a1ad1cdf4f050ab7d55c795aa1ab771f4be29f29134e0d7709566f9b2468805f03009158599821c271588f24e92db7ca30197ec5b0c901efaadd34cca707e56b9aab1a7f14e329816e2acf4d07a7edf1bd6b0400af07a1ba7a22bcb1602114921a48fa966a821354cd0dd63a87ce018caccc50b56f2c9f55a062cdc423657aa5cec8a4c9050100097465737476616c75650602aef4be258f8baca0ee44affd36bc9ca6299cc811ac6cb77d10792ff546153d6a84c0c0e030b131ed29111911794174859966f6ba8cafaf228cb921351c2cbc84358c0fa946ca862f8e30d920e46397bf96b56f50b66ae9c93953dc24de2904640000000000000004a547c8619f3ff2670efbefb21281e459b7cc9766c4f377f78e9f97e2c50569a8dcb155f2a502e936d2cb6ef1a73e92af9916e6353b7127d55bb525cb18074b5ec130463e03a4eda583b05c2d63db40a08ab8bf05f930ec234cc2f788d5f5bfbeab3e4881918ce964ffd55483219edd435ac865286bfd313cd834aabfa8061d2ae173cbe4b59ab2bda78faa4c2c937afba80d7fba0822579ac0ef6915f4820f968a74f00ff5ab74e90b0a7bcb2b92093a5e94a54aea1d48ffd1e5bb3fb48069bce0d38776200db38b2aa170f8b27c74ea497c638ec1b8462c490544c1ebe22a5e00000005000000012404b1242ad971ff6e57bfecd2e3068c0ed7a4be33c0558b042de299df63b9145b8d3ddb4ecbba76d96ff8288092d908ab184c8411753dcd5dc9c6d8897a15313597cc5db38f68c4c935053142d3c2da4eb167cdee40e5e4c2878d53342ded4c0000000246959ce33bb25348f64d0e585567b52253b24ce6229bd83b3fae46c03af515c83a652cd7e8fa07c78db0b70a1b7c35af6ee9f0d83521acf7569d285684ff7fc56f22277da5ab40b30a75cb1bcc60cb7a5762919a415740cc09ba27c5bb9fdaf7000000031ed1953514eda42ba220a54d745ec4b454f1f380716279ff43f0bca3cb111c732d09e8eb6edc8c23d8095a14006684127c48353d55c02d7a69d3b6f5451c0d853c6c09e1a4d07097f16ca2a3324081a7301d1810a7844d331ce3f6012eff6700000000040dd23dd94272e26b45418aea3d3cf75690cf88e17f7eb881ff95fe1f1ef61fd63778bb771eea088f2717e964ae8d3ca1b9d7814a57c0c0482b9a65103f616f9b6a4e943c333d4a6cd894f4802e57db6e9a5270c42f39ae770f4472eccea797da000000052ca1395e3dedb1e0842cd4481627aa55b2a592d64ca7f5bf6845baa3e22647d73ef788e3576f6467206a7c57b1a6b63e9ed774aad4ecb7eaa8fa6b440a7a76a665733b664b5ab5038897f85ab2cbcae9a5a58b6e1e0a442dae026c2b74174b4658e84db7c2c90b21acf4b39f23b83db7f98baf1c6c5153c0123932d329d73eee0000000c003349aa2906906b01ab75f6b6897787dcfc7ccf96212d74d02558468c8b5856405cff39ee6e21fd7db4a2b6b02ab8a6b770c6f2604b2b8db00b38706fb31efb3a025993bed7d839a22f09f5ddafa524032766f3d175cceb640c9a58a9308b3d7a980101010262c5c9fc27e61854fa91c43236139ba5d944e9e628cd1b57b9c045fa114c490000655c0c404889511e939c8c0bee6e4f8199363ca505203e3c4bc5fe45cb5664db6b82bf5f16c7aa92ca5988914f5db5202e23be8939f5225dc0aa2f3386f57cfe0044835f8e5a723bde4dad0488037806e4e094abac57d201a0d1c825023027c1aa1d057b2f767acce630ef8cffa0806f5c0a6a71b1bc3e4c4f011b267830644eb70054164b289d57391c9c6dc767624d83a6384af2ab164fc80a41a6c1fd88dc6dba69c64fa9892188c32340ca6807e9b382759453c52d4ddb7ea65bb1e76be70eab003845506b51d820542c77bc063d112d53ae60687e00b6d7d8b845ff69443167795062cbeb5af4316238d72efcf11237689c4fa7c78d31033f5f26baa14640aec901023f799320ea06418335530b3370f2a3ad555bc335f847e167a177ed5e7320384d000000000000000502803596b4ba5ea05b1fea2b78e292f935d621453cffcd207e10f3072b2813ca3e963cebf05b19cd82da4bd5aad1dcc7fda1492d7ffc8f532bc4b37e9bf4753b7ae6b8f08e05a851052fc6ac7617ce68293678747d11f9a508bab6f7a60edde9c4a27fecaacee7cac6eb0072b08de2040391f5aff1d39c1eca45e9e1ceef6a680dfdccb7c8ac5cff24ce02454dc58ca329b1413f5c39f6a27d2341d7d30041f5b52e38fa03b8888556cd7a2fd6a8012a233d7ed79910a46e4090e6e6bfffea9f0e0ade8a970e7b6480833d376652ae0c9777209a785c5a254fad593a7975d4ddeb5dd25dd7d83d97bdb2ce1cc891220eb3a4bed2913c5be128668a5a88973ef7a314fb5a6df50796cef77dec15ba05b11eb627ccc3db214a61a4017bc3120f09f8000000078a266d8f2078084649b2ed641128818654f98dc78097cf82fb9ce0c6991b18539fc1fcd9dfed877dd2deecf666001ad7b7423143d3fc06e26ceb0caa7fc4bfb01e93e4f9a526ea814ac0e62ea52c5c53822b0dd82eba58a098ab4f453b17fde6820cc74e023722080be7eaa211162d5b83c54a149d0e533efef9487747d1413d918ef00eb7fe7ace6a56b8ae115ee2f3b37c6638b3a0432be164f4a470a4242ca12f166a59d153f703cbb2642c303d2956292419c97b3f9ae170b24182789692b759e754eeb963745d43f97392774f02b6751fb299b4dfff4a56de20f26fa97da30dd49f48f282e177450959047edb1a8e44cfc98d5b2f5961aef7ba75aa7884977cb3fa85d994e532b9a1a8e9c858f7c5c2d6fb386f1d33d796006c868c6faea2d60fbb0d81cf2198f996553684c7b18d7d1bed0f264aedc6a7fcdf7f1650f39c049bdf5123299c02249c947826faa1826a28e100a24f229775f61490a8829edeea2ea86649e258875d4be63e98bd45143cb9681a1b2a3892b61f68c2b58cd793aa738350605769568745244a7a9c7d0514525745a2850f05eecfa3dd378b90b59678564617db5f7549bff21e5fa72f8229e28245371a7339831a004d8e2a2ebd935b1c7747514458f6bd6620f60ae168c5f27ae8cbf6fc43b2d4201e0ead6992978537653ffdb3b05b32aa8234a3ddf4e3cc2ea898e95b8b1be35976d65cd7f44509cd2ef2717e8fc362bedee81c0fa87f0cfaead1202669041d5f1f7d2ed362c7d1b6f1664081833912f0ea2965a332482e08fa46e1de20b0ce239a8797ddb19144d980add3e9e1fe8109868a83472cd5a495cf9674b6ec0a0a5ef5f8cb6991c40c6e96f625389cb56de87eca9526b6efd349f0bd44f1c232337c9176efa03e5ca6b78a80064793ea605a23d6e7d8ad865360d2e29e18647accbac4c5ae984b649fb9e5062f5a16f58324782bab8d4008f5eb944137a43bb031072d9127fa382cbb5eb07c7143f70e405edc38fd0d6bea2fba80388bf8a5aa0cf5e3ad9cec039035240c33b7dec4981aa53e914f67ac932328b31f3fc4d0aac1c19a4da4dab1b525a63008d0e40b86076a1b7e9f0f219955c76798ae8d5131eee35e9900c5cdc8b58badd7022044521d7ad239a91bb2ae1a02fc61472f7d3629d14070641a1eae899e6e379b568caab0141ab86ad93488e61340d917ae4f2871782b64bd070e7dc49c57ed667b35d3f84db8fc09847fb3693e84649dd1c57c317340cac5c6ef962b44e37e9bb84fc222677f00d1ec332e25e81531a84c524e23800e4ef69431345966a6ecf5aec3ce00979684c2861be62231ab74b97953a8197a39251d157a1304a673724ef8687b27beaa474a7056543dfe5cb70502ffc62af63e6ad983b75f4be55185c2b5bfafc698219dfb5079fbed6f7a21f480bae1111ad333f72f8f00000002843454765b3b8b53bb33880bad2ec21d3704ea9c04ec2a0ee82219519349767c74b93c03f3d6b35a7deba79a16051427930281f7b6e4477be5aee7cf3e365bacfa95c28a10afcf8627bae2eb4091d7270f05c56d39517bfc9fbe8c291bea271ba8490429e3a7dc4c30758f8a4c1481ae6e1b5e54187bc0476797d9a9ad2dc2035c58ba233a1faaa72f3c2503000eab59b4e01708ac8f549e4098cb764510681ddc21d86976771ace658329dacfc3232f921f7630948ae70af7c9093a42c596cb6710353288322c0a66f3e62935d8284ff9894a86fae2ee1ba619b96547e0056a192121dc406ecea4bd342d300124bd20d415606fc3c8a37fa0056cb3b4f64f9a0487cbd29bfc97194ed8868ed4e458c7b2bf8ab6f04efee532502cf588c4f26b9b2830baa635c56857be5fd6803fd35d508881bd7cf3b5872ff84640384e2576bd93d4d86fdafcba2df3f29036491573031ede2ddb09dd092ad890a68f07876aeea856a0eb127ca4c08896db9bdc0211918711eddb3175615dec61a6b00ac88ab5ece1be74a55d69d3b2d94815c542fc9da317b86f78570d167c356b0032e10cde818eeec642cc5e4a85aac3dc4ff60d6d747059218c3f3d0c918b5fdb5e0e7559404f25bd8f7ca73432e44261f4fe0c1e1a7bd944e21771168a80ca5529fb6d195bd1a150c3e8c6e8677102aba4b3bb0831c4c645bd6b0f7ed3db492b204e348738fa7a61a2f959ccb7747e3ae7471eca3f8fc2c66bf734b15f700acb82ed23c400000002a04cae736db5790f72295d165d68e0d9bda882cd9e46a4c724b4aec31b98ef396064f56d9e4884cd84aa415de23ca479b89e0735074fc47e66fb75f55308b2bf5ccdb176784ddb550f769586c9a9c154671b6f347a1f4419b1ebfe96e59142e68233bcff4b5be7957cc0bb8c436fd8617f1591c73687194346e8dce9fad3cb3decd80f4e742309707fc5a8927518611099e471bae562f9fe68af039631e6f5177fb5f7faae75f2c426ee6817b6f03a1fb104aea55f29069e3ae442f24f389e7f10399e22ff0c8438bd8475dd309b90cbeae55ef9724bd22ef44553c07eaecde90901fdd15084ee4e3f9b5b6cdacc1042e3277ba5127cdca7c66061b9503287be02b387e119ec10c4a8963ee52710d75c21710881bae7fb5a8595fd43a9156419f8080891e50139bd4af14f1ba25ebe0152b5e83d115be493372e147742d8bfe3a8269e8ecd27ec055a11055d5405192cda8c8db528f06b120fc2e3f47089897411b3cc9ed940ae6645bbc674a01a9babd2c8ed3909640ae91ef01a3039103e818c70ee3be85aa3f3804adca265c3fd97cd8d94f4f16aeaac2f6bbd06c218a421dbc1176d53c8192bca54a39ec1a4ade163b9b0c4f60b07980b7373a7e61a64dd7e28c3882ee5511a8bd20186e63bdb37713478816106bc23241851486d10ac03bb45c9df3032ffb14ce3e0d6870e6c9c8024dfebe9396a56aa408d73c719ee34052dcb8f90f3f327891ea1e6e67096e0cb22407f2d772cab457af6810288f6a867000000079348680adeaa4311e21fc4f31c2f50ffb0e427bd011455f0b3151b36b3f52c94ddf8d9079a9b485745bf99c6e5220a3ca6c115c208bc42493413fe641bb8326d37c1ba622785d04a8f7e104f591c0fafedb770c1363e67aa0d130fc434c8bf7f8ecdf1effd86e1f53c80ae9564e67ad747c84fb31c129d551ee311fbdf30c46a9cc5e7b9b8997bd91aad8de5589ffabf8a776bdbe60b2e463b90041b2247db219e6b4a5bf2ffa23c5af0bdbdedcdc8c080040061280a8394b27cb253951f8464b10f257f944db3d1545dad0cccd866d7da659256a0f104580190aad200cbb614ebf17552e8dd851b769fd19b49b0fa34b9e6a679e83101bc2f5b8a1d102aed0544d12d78bdb9a39e455da446d102d9ad21096ea853fe444923dc57c31d11ce2b8a5d882e831edc6cd2e9ad229a0c34263131854d77fdd15bd11d9820d617bd5ccacbc7c9407149fd92b46dab47e60afeb09001f49d837d5f09c0ac9da6697a5224d2808296855826429fe519a859a17158c21d38f7cf9c222602c320a2b5931a840237bc5674e3dfe9a217425a0660b349a9524c529a7b978f81488b45b9e93f7b8436e9c7d9ff19d85c2214a4fdcaab9261cd2add29201c3b9d6ce4ce657219400ae109ede3507f5057aeb85849cbb8f55593d43c18737c27b86fb33c1617fba13965a846407748fd33ae7352bb119ab71b8e09487842ce37569c13f212ad925041188a19a0bf71468ae290c5d5561bafd547949c4e5da973992729a849bf5fa4fd04eb55b3a8db7cccdc3a0ebdaa3cfdc7a7396ecca820682b40d078bdef188b609045d76fccafb6f8def22071b9eb1afed2082feeedd741b7cb89d073bbc63f773ae935249a3c50566ad71b42de17b8c7f24b153785c863be33115391516003c1d9989b78130bd7e74c0f9dcce55da0201a1eaacdb37549d84da95ee20ca70ae13e95a97a7b18b67e75b8ec1b41ad55049ada043a39a8f8282878c92ca3ba266d23195041e1198f125d0695f843b597aef1edace684e90b09abebaa85f6a101", + "proofValue": "0000000000000006010098ad4f48bcd0cf5440853e520858603f16058ee0fc1afdc3efe98abe98771e23c000d19119c28d704a5916929f66f2a30200abb05a0ff79b3b06f912f0ec642268d3a1ad1cdf4f050ab7d55c795aa1ab771f4be29f29134e0d7709566f9b2468805f03009158599821c271588f24e92db7ca30197ec5b0c901efaadd34cca707e56b9aab1a7f14e329816e2acf4d07a7edf1bd6b0400af07a1ba7a22bcb1602114921a48fa966a821354cd0dd63a87ce018caccc50b56f2c9f55a062cdc423657aa5cec8a4c9050100097465737476616c75650602aef4be258f8baca0ee44affd36bc9ca6299cc811ac6cb77d10792ff546153d6a84c0c0e030b131ed29111911794174859966f6ba8cafaf228cb921351c2cbc84358c0fa946ca862f8e30d920e46397bf96b56f50b66ae9c93953dc24de2904640000000000000004a547c8619f3ff2670efbefb21281e459b7cc9766c4f377f78e9f97e2c50569a8dcb155f2a502e936d2cb6ef1a73e92af9916e6353b7127d55bb525cb18074b5ec130463e03a4eda583b05c2d63db40a08ab8bf05f930ec234cc2f788d5f5bfbeab3e4881918ce964ffd55483219edd435ac865286bfd313cd834aabfa8061d2ae173cbe4b59ab2bda78faa4c2c937afba80d7fba0822579ac0ef6915f4820f968a74f00ff5ab74e90b0a7bcb2b92093a5e94a54aea1d48ffd1e5bb3fb48069bcbdff2e71c59cd60b45bd8490e66cb4812a03f0b5c04c157f1b1d2910adc10d4d00000005000000015b0526600d3ef05cb20f585ad0704f190dcbf4fd7cd096495cc4bd0770091fdd35a2d0763cf75826373239d3791636cca8990f52ab40f099b90b80345d70f8bd5db5d7f642e9edf556f39834c99ba0cc816c0515394a8e020c924d9370ccc92a0000000244fa95e305f8c2842cb28dda35bf1bc12ca280b0ae336d7245f3192eac9a897019a23bd1f262c3d9517f4ee76fa7e13d8a1ad3e1d2835124024a8d295f4810e6266ee2d5b31de85158f6c29c3c24ef53e94608365b848cb9f79bcdf24f8a445c000000034a2b6fdb6ece754989596832571c773ccbad8d7c01987af251ad783c901e709041c2900d1d5087a900e3f8ebc002cb094a9f73c3ee2d3c3bca798cf0d05f2844645af63e601b79752a739f62a8a9c6722acb5a7fde42bb3a0e22740d8acd12020000000408328d26a6b82a3b7c226a12d58a7354a10d86b2fd9ede1a7fdf17d4aefeb65c0ce4f2eb50a007bb1ce7017a5c5b6dcdadcbd0ef9ed7b17d525bceef6e92945970b375bf34bc25498eb7539c1aaffac4a9a69070c7d03783a653108b88d7cd4f0000000520a66daebce66a35d57230c28aab64096fe095eaed8db9e984cc0e43c47b1df616fc1b30bbdf46684dacc9826046a9aa0318f1793a70161a5390e8c818d7ca1f1438b65a3a79f9b08424336bfc84bd0966aa48ba5592cbccd041c6ca4910e8c8124643f962e3521f721ae2a595cea65a2df35190cb6050d2cd5d6af7c54817520000000c0069ba5877e546eaf50608f973b9800c4241058f08f2b154c6e824bd1abb5bc3e71f8240ea233b0028dbfbe165511f531761920dd01cb111a7ce04e6fee32268e00230002a54b56a47ae42fbf1845732ed66d18cc9db36424c7f105a2c00961ab61901010102613fb0a76d46e9bf506a37e147da34ff60261db95e6882f218d44a610488ad44005088bb3d81c5f47f46c395398967ffa0fca31da15bf5705f2499ddb19b2d357c4c7e1562935fcfa493d78164fe2594b29c144d65abb98594a117f577d39e4b4c006893ec35761361b10a0e2581141186a9b8758c95606336afc559c9ac0e517a5f610a060077c7a2fe19795f6fb34edb97d93aa14b2a620c288bcbdc9fd25658a8006e1c0336246fafea4b5bb33a7774750abc4296d2b3ad8defae9ee2c76565f4612b6687786aea7bf7c80179a50a726164084e260ba16101e68704032539ed9c86005c1c31878348f40a7bfd8da75ac0e607cbda5c0711985187d74b63304c3d4162179aa2b16fe107a07d9e9df4e97b60cac2618a162d326ffb7cc38f8f01f5a83901025c81a95fa449e47935bb87d45f72ab2fe7e627e154e73801f1565d8eaf76e7ff000000000000000502803596b4ba5ea05b1fea2b78e292f935d621453cffcd207e10f3072b2813ca3e963cebf05b19cd82da4bd5aad1dcc7fda1492d7ffc8f532bc4b37e9bf4753b7ae6b8f08e05a851052fc6ac7617ce68293678747d11f9a508bab6f7a60edde9c480cbbd8128425b47a4de48c892bbe3319a14a3fcb236ce94813473be81134d913d5365f0c78f68c52c639ca277e7d1cda1fedf1eb5d8c2427061dcb8c2581d6dcb294f8ce3e6dc889d85d3d0c8f31e8da26ae5585f20b3ed2f5827f4566c25e51e870a5fe08c30f131b85eb16c8b36ea5e58f7fadb23525194dfe6fabe1280b227ce5a63fc5f9eab33595c98c59e168cb5a0b43696623dc0fb765092afd7c3da2ebe184b46725ab0672ade4759aede6b6ff6b34db950453b8ceae02ea13b099b000000078b214e88a466ef56e32c833f9fb6d88e664506dacb77119cecebbe035c754a2e74f6eb0050a37ca86e426934f7e3834aa3d8469f618565940f0b4f41b2d6fcbb2e8ed1154533c82db51a7a9d6d9131e1c868b26c41c631550634418cd5f73b858760a3b10eeabccf1c158d504e597076819d79db87ff5829923edd71b9d86b4651913f9988502c8c2865108e2c8e4f65b03d518ee8bf7a876cb752fed3c54f71dd60962238a3c6065752e836243d672af69dad66dc2d5cae200c784813a1cd8d84731e0cc03090d0e99cc1d459f0a54951294f6604f1cadc5de861117878d9cf5e9eace25278736e4d150caffd38b9808fb58bced5e2f82313397af5d05b2bc0620b75ef984dbc6c120bdeb10b0646057934cf31bd4fb0dfc2a70ad24f4ce98b83c44eb9a1d1cb227f959e4d9aea5518aa9f67e883de83cb5b24065c9965748293066f36c023a73d3c7add09431b66e7951bc4fc055deb70ff246f15dc47f2f489347131987cca0a6fecedb170221f131bccfb2ed6b0b142fb314de84ff7b6508dfda3d662023ab275dac5a8e3f7455b9b3c3253959e02379249247c24b1bf6dcd61e242fc5cd0d229f954430d3aecfcae7d880082065efdc281d70db9f89e3236b8f956e50bd610c60f9fed98c3ceb3b206a286ac96d4ba8370d89a9de5142a831412c735fe0f54f3aed07ba419258ea03b86908307b6228d412afb2ef6c40f36619d0c8ec016deda34854c1bb36635ac8bd30589999cf93fcce2a057d980524d5ef9df6e7f50a497217d5e51a12b2f00094590d65e6150a1da0f8b36ef07c2ac1366d9a0d747f2e933e16a0a0c016146bf7f38dc07fdf868b2af9f9ed2a246654fe277405e8b6776e40a76237b7ce0a9a977825c565665d38b1d103f2f361531ae7601f5bbfcd6fc3324836096ed68fb37e8fffeeb25b141f9494ab8267754336e2ec226ca345d85c4f3eb95f3197a7fddcfc85087643cde45ca57794559956f3721a944880d44906f3f536cba39c3306634373c6e6cbc6d7ff91900de574d039035240c33b7dec4981aa53e914f67ac932328b31f3fc4d0aac1c19a4da4dab1b525a63008d0e40b86076a1b7e9f0f219955c76798ae8d5131eee35e9900c5cdc8b58badd7022044521d7ad239a91bb2ae1a02fc61472f7d3629d14070641a1e8952efa8c2c39e20be0df9fc47d5a6dd528132b0de03e82da2fbe2f47a8c277432d9d8c75be4129403904a144649a337963aca119b891a595ac454c529f94ac141c949858b200b61a42bb1466cc2d23340ac74e7a0ff27fd251cbeef326a572023da64f6131f1597d27983d3d14176c6cf2b22180d33da711cbfc43b2c983bfb1377635189ec44f3123bed01f622806af289c753650366101c6330817ea5c4815c8e3b6e1f091dbcbf4cef656c12ee5201913d86109110a134297322ab07d27300000002966689b03475dd11aff6774b268ac01ca27789f03185ccf24831213a5ae0ce0ac402fcf814a5165ab7cfe6e8d92aece6b715b6db2b1ec0578f50f25520f4deacb631aca326d717870b1accfb269891030e9d5c0bf493770fce64445c539c1c4cb053bee911f86c6e496af8d9693a41c1bc7b7c2a6338756d5dc5a75f20de41011297640d00b3f22900f511450108e4488f10f9ba29c945e4094ef33c80f33cac5b1d049744666f9333d93e551d287e21274238d06a1c35daeb69c1209fb70ca336c48c6acedd2a86a6b59358299b0a1eef60fdc3d9f24f52a37eaf5d5c3cb15c3013f943314dcbe3f5ffa80831865f46c28200c40fa6388373957b7f838cb2640487cbd29bfc97194ed8868ed4e458c7b2bf8ab6f04efee532502cf588c4f26b9b2830baa635c56857be5fd6803fd35d508881bd7cf3b5872ff84640384e2576bd93d4d86fdafcba2df3f29036491573031ede2ddb09dd092ad890a68f07876aee8f5dde25485be4382e448af473971dcc86ed35f2384d3054de8bf1cce7aa2abca2fc0a4b609b4848490ce7870f9caa44b789b56781191ed012c94953c08118b5c4be0d245ba8f6bf25e2de1d7a2bddb21ed70c34397b79ee49dfb02a7490dfef563f5cfc60cd9c4f060157fbd7ae4986bdc5235189866d73905e9748342e1fdd1fa9904c0c35eeb0771763f5d3b23f4f79eb8fa0435d8f96c4d85f0b4bbddc6355f6a2e44b95987e27250d29c85246d39ada545a7c249d82ad5017b279c9298d00000002a9aaf2f58d798219673b2b2825ca124cbcb936fae0956731905817f60f4ceb913cadf2f8739a7fd2e26cd8d284db4285b42630cd4950c189c434dbb42e11494e35be0a7abe9e64d3ab3b33281891f45f9fce3821d3db2eb784c45d7093ed2a988bf215e0ecd1941e52bbfb2e3b9164107a90d8f82eda64f5510c818e308cb03899115c0a57043090a00021ce38b2876b838b2510b0340508ecefe68a43a088398ba6861afc85ef3f4515bf177b8e62528c5e32334fc385db2b63145295f3e2186a3c03537e76313c00dbcf0f388b7d705ce8f9acec6827f7ca044322845e5f92561f33fc0fbbeacf8542f9716651ad2bede85f92e26701976426be110a2201fa02b387e119ec10c4a8963ee52710d75c21710881bae7fb5a8595fd43a9156419f8080891e50139bd4af14f1ba25ebe0152b5e83d115be493372e147742d8bfe3a8269e8ecd27ec055a11055d5405192cda8c8db528f06b120fc2e3f47089897411b7af706c4e85f57bd44166eb136a5baab2020e0e206516a7fe23bb76578bf51a5368ec22bccef7579d1243ba67d3560ea45179a519b9619f80c338379a6c73424aaf830cc9e883897db42fbcbdc02b486b5df87409bb5ac4d233578338e5b05769377a5f40d222e6992e685232f4eb9da8c3b3637e54907717157dacdaa0f0943c94d974c385098ee4933b54ead871f3ae8485d0130f14fdfe5209f50c667a6f23ce2cfdf7fd125c60e82c27e8a32ea281ad9438eb9212b2dd79a50cf5d18740000000079216f0e66e5f1918d0c0c76ea3a2d93e07675c26d52d1606b7c3a611534081e55e4363dc556915362431d6d617fbd2d2b312a345d2c53700066d3bdeb8e8330e9d2fff8c45553a24a712f21e4ba04ba13f3800377b2a47a945d9b192d00759cc9807f98b77a843d8987c9d3429ea17c5925cb92195f40fbbf55728f260b85d0ca3e0ce0dbc7850f064078a00cdb062bd885061ac95cdb89876b237451f2b54c75f895c73c9c4e55f24dd097fda90b97a0ebdd251e6f07c618a9cde161b46096ab5f033f9e22031db2a5ce3bf6ece3b0fb74128fb51a711a75da3d082dae5a978594710eb3b104789de0e11a05ca3d1018abf1dfea312143e48df89f8f00605e81b71aeb4140be08451ad2c33fe97b1a52e387fbdf57885cf6c2b59f25ae796aeb6929b26c9342cc54c621043e2a7ae2c023447e43c8bd2bf11f528defc4a13612ff3edee2900d970ae86a9b0f33feb1586cb687318c0a8b756703523edb10035207f781f36409d046d9a63cf917f4a43553b4d5b94eb8d9e1109aad16b574dcaa1912b868ef222dd50174a0f28fb5d90647e1fe438bfbeefc04f8267be621d57acb2c0ea7415efff0318c04bba32cd0b85cc6c8c5681e47f1bb4e512738e5e11bed711e089053bddbed5effc4b0de0e894878154f16dce626a8c532803f5a6fcb6e549428a2f2b5fd9d7b73afa98a3a1bdd5962502345ff5763b4990aa8bea4c05f1a818dd58c018787c4bd9facafa0686f9f0596721f50a2cc9681d7644aef13e32115d9e4fe86fc595f92e417c536c6b650cf4f7659b82d2649e52fc8134179065c0b808cf0e54b7e15f31b84c246cada5cb176e076231d38f6ee31332bcd1ac7c3933aa3ed59ce388058e1b42ab7588bff6a28518171a728e2ce69569347f5993a32241040c2b8c0b20ae2670929462bed4b599a5330e0f958647ca694b9515ae569d132fbef38dc03489bf9932153a9e324fd2312d5aa3cc2b2564597a68085c3135a3cb9cf5a3962b75dfefe7027bf0f19a8b7864c79d537a29e98459bc01", "type": "ConcordiumZKProofV4" } } diff --git a/rust-src/concordium_base/src/web3id/v1/anchor.rs b/rust-src/concordium_base/src/web3id/v1/anchor.rs index f88779acf..850e00191 100644 --- a/rust-src/concordium_base/src/web3id/v1/anchor.rs +++ b/rust-src/concordium_base/src/web3id/v1/anchor.rs @@ -1260,7 +1260,7 @@ mod tests { "issuer": "did:ccd:testnet:idp:0", "proof": { "created": "2023-08-28T23:12:15Z", - "proofValue": "0000000000000006010098ad4f48bcd0cf5440853e520858603f16058ee0fc1afdc3efe98abe98771e23c000d19119c28d704a5916929f66f2a30200abb05a0ff79b3b06f912f0ec642268d3a1ad1cdf4f050ab7d55c795aa1ab771f4be29f29134e0d7709566f9b2468805f03009158599821c271588f24e92db7ca30197ec5b0c901efaadd34cca707e56b9aab1a7f14e329816e2acf4d07a7edf1bd6b0400af07a1ba7a22bcb1602114921a48fa966a821354cd0dd63a87ce018caccc50b56f2c9f55a062cdc423657aa5cec8a4c9050100097465737476616c75650602aef4be258f8baca0ee44affd36bc9ca6299cc811ac6cb77d10792ff546153d6a84c0c0e030b131ed29111911794174859966f6ba8cafaf228cb921351c2cbc84358c0fa946ca862f8e30d920e46397bf96b56f50b66ae9c93953dc24de2904640000000000000004a547c8619f3ff2670efbefb21281e459b7cc9766c4f377f78e9f97e2c50569a8dcb155f2a502e936d2cb6ef1a73e92af9916e6353b7127d55bb525cb18074b5ec130463e03a4eda583b05c2d63db40a08ab8bf05f930ec234cc2f788d5f5bfbeab3e4881918ce964ffd55483219edd435ac865286bfd313cd834aabfa8061d2ae173cbe4b59ab2bda78faa4c2c937afba80d7fba0822579ac0ef6915f4820f968a74f00ff5ab74e90b0a7bcb2b92093a5e94a54aea1d48ffd1e5bb3fb48069bcadf8b1e6664e83c2e12f47291bdb470b47df740c2623fc0d7a0ad34fb9d64fb900000005000000015cc1f983b2a7a7debded95108cb89f65381917f8120e4deea665b9e3ca0a70212ffd481839d094662c2db50136796152e41cbbba6bf87bf02e78abee35933a9e67285f7d35a7d9bf24a37fe49620f6255f1ac78cb4aef1151e29944ecb702643000000024bce7d3ca07538e9aff9772b4cf9c2b24a67b91397f5994226a093d298b4a23633e46e7ade5ef65956edf9de27d9a975ce949f97d73a0d5258cf8e8f87adaa570463fd2f9559ef5f7dd364dc4abce05550d0e53475c9918b1e23c7b34d89d8e1000000036440ecd3c6c671a0c40ed70f884a9f5212c3d1e05af61e4d6da7c58dde7fb1ba05f41f668da5d1440ab95f5ba3691046c0b1ff3478c731785cefa5a4dda8cee6665ce1ac8c8040c932a44ed2bf077cdcca394d7eb8e3c3e91f40cc6512db24c5000000043912fd3c9a5e2167423188eebbbda54c616ded7580a3eb34500916687f11d4f00ce689c028a28370fdba1edaaf3b7a29881cf8c2602f961b2137779d7a6fa18356936262155f6b04dbda6b1d35c67248e9396ef932abed13006651b2882f155f000000056ebac799466813bd7f9ed65a9bb5c91ec3710d88aa4c1f6390e475170231bce41cd0d020868b143ce9d0a8f1543dd1ee2f5b3e85525dde8d04e1d12ac2063ada69d7bc2ac5b50cece6fc9e386d6c4b576417ae6ccee6321e5a61599eb3748d74206742d6126667ee04141b72104aacb32e580b5db3f549777b7f035a2a16a0860000000c002224a394b6edcf83998ee8d9b58095b38d6b6c5c42521d5c31b81dbc52ccc0264bda335a1e7f61ffa2bba8d356c1b48e01b58f266c50363c1798479f7a9365200266f9eb50ef10d0dc63ef4ddb238831148e01e0e38d8e0b94c373597dfb5d295501010102299f078d1e543497070baee391c060737354c015f1d0bf82faf3d78d3a48376e0005c7dc83b81accdb0954f6ad51d0ce35ad66b3201f5336ac20c3c1c08ff856272ce6116990d8266acd40309cf895f52e62e1bb357cff558e53e18d37e544ee7b006c88ea28f1502893beaac7e6d9c1905fc58c051cf077e1093c89c81cd7a671800f2b98037e637fe747200f9288272de1c67170fa3f2d3e29911784a49bcefd78004b04bc8c867d1afa3992d8a11f3a8ada1ee1ed48f348e7ddec33d32b824ebc25457b8151147ba053e00c478f95e6cd752578973ad575e09919fd6caf59d11f600024d5e6122667191464557a4e758cce911968ad9813e181522f6c2e2703576aeb69aaf0412219e752b222329904b4c29949a6d9b18c91604704dc071897bf05760102531993dd2439551210bfa191f9b66e49e693c6c189260aa605280886804ff692000000000000000502803596b4ba5ea05b1fea2b78e292f935d621453cffcd207e10f3072b2813ca3e963cebf05b19cd82da4bd5aad1dcc7fda1492d7ffc8f532bc4b37e9bf4753b7ae6b8f08e05a851052fc6ac7617ce68293678747d11f9a508bab6f7a60edde9c4a41e80bca9bbd4fad0a8dc8db2b4264dc25e35599bab793956d61dbc0c012f01b393c8cf7254a24c18b6b05f1180a555b712be45be9a9be20eed26c68683c81afb0de03c61af110d25cf10e364996a30b29fb0d4543f9bc2ed0dd1a6def19cdb09ef7c0f24f29ae9dcd5aaf809bd67d86b9cf8e639ebd28385a2ad954db1851f59737318d78ad8a990cfdc208f2229fe33ceba14c7b34dd9f0687454384206f36bbc7762e015510952538f10e502b1be9cab7e8f6637964aa58a100eb72eed7d00000007aa3d9d70c9a1112cd8bbf2f23f5d436bb038970c1cd718b65865369ac172f3edee2e353d68ca75a309e1299d03f7a50083914b99232b25f106f4cb9fea1f5ec988aa749975a9f0cd1ba56682bb2b90d2f9cb33be146d6fc81584707dedf3d660ab47522d8bb4d47e832121c792e5278040eca2900b7a8ce4c073554602a1feaa82c210550bb95f35bd4aceb1b0bf08bd8fc4e5b6c0432fcddc18e086d915bf7a5076df3be63b3ce6087abbf7e0a3f8f530407803f8fac559437c881a99c1282fa5856086c95f71ebb957d9db6514796dead2b87375f97c24bbab00d666c024872a84c8b8e26097352d10eeaed535055a85ad5c6827309fc69583c5a6e7533572222c9b38c509feb71eaec826ff703b9c9442a9c807e4a530b07912360708f441b742162d2708308e50a6a213efcccaa755288a0b8008bb7310f7cabc4a6ef02f4257ba0f91ffa237c88a3d4640c61870acfe90ce01f8112a6e4ed0e38b717c2895e438068b952e78b58461d83764d0b6e375398a5f5ebd492365b16fca7f96648f85a67c865334e72a44f5753a74fb20a49778648a6832c5eabfd6c75eea8b72235b1d4493149fbdf9cd61ca31b97d9d851188135e28dce14b0911a42c014fce1040a46d53e226011a686c216476c1775cc05b7388b72444d3c0be400c543b8588ffc4bcc9fe12a56824164b7f46c69bff954199f0df17ef4de3da2849f94e503c1d5ecee6303f58d70c61df996c383c8673869287b27a490f120a8c881087df070f3592d60322efe69da5cd4493a9c373faabfe517942a1c4d04157f18052dd87803dc0fcdf15f61f938f80ba8c44010d0950a7f8d6a5e500d74e10252a2024c5474a7a03479f929811c0ba0b6d5befb5ec49396f1c578880d587e4b949a80bf50eacff5f3180963723fcc2fb53b386547e87ce814b34d7721e8bd65fe49d594d21ae53cbf8207c14e5afc034542804febe2dcfd61dc28b7d73d3eeeeb87d5c64a83e378487375585888dc7bef240bf88f8c43782c49d7964dd3b5f0ab7f219039035240c33b7dec4981aa53e914f67ac932328b31f3fc4d0aac1c19a4da4dab1b525a63008d0e40b86076a1b7e9f0f219955c76798ae8d5131eee35e9900c5cdc8b58badd7022044521d7ad239a91bb2ae1a02fc61472f7d3629d14070641a1eb279dda86a693d9bd31eb38e677c5f85070e2cc05cb574ffc4340fe23bd4682a7faa8b4c2b7c86486dc9a3f6977442028f9adf7b0e8211df3770f580eb6f0ee86a7cea689a6888c31bb81a72fd82d7138f3cb5fbea85460d59faae9ec97e7ee914fecabac546163a683af1858ba5dd471653021a0c170b9ffdf2f63b00c225a3545ee75f4b4d1fae8e5ae3ab2a82616cfd1d28a7194606eec6a7820a4330771c0a652d08e02a418cdfa8f77915e1598b1c9c3ee01f6f2c84da643c23182c0bfc00000002934c0abe8b38512e0a8f2cdda0f7a4ccfdb8892ac0c47577b1736ff0a8760da7ab80078380f9a3f76c29c450f01e7846b7c265e81c7820c1069a01ec112e4c9f5ef2224beea1b6726f9d571a817e7878dc0081e58a2e2d6d8897590ca8bbfad592c86a5dfa048c11a1d5256168e1abbec3294fff524270dcb4e2ccf4ad1c01b2f50617bdea7cde01dfd40abceb826b72907e4627a972d0d94ac18d90b070e5138542620c162fee11e35b615c1332af593d165ad2124ee700c905eafb47bb8c1c3efa9dee61560288af752e95391e6ba8931ee2a555706893f47e4e1db4cb6ef8495975561f3d7ab3cf72a254d2d09143ab8b72a20fc808b0007d465bf25359ec0487cbd29bfc97194ed8868ed4e458c7b2bf8ab6f04efee532502cf588c4f26b9b2830baa635c56857be5fd6803fd35d508881bd7cf3b5872ff84640384e2576bd93d4d86fdafcba2df3f29036491573031ede2ddb09dd092ad890a68f07876aeeb1670ef988687963f3e3481e448df81c3887471be037c05e55b9ffa04295049a53a7bf2dc6f8f444bcdb55aa860b68c59860c8918ec080cf9da5e53ef614446784f1a59370c718c3f22b1951bf719e97e5af289407f6162ca5c790f93ca249db4999d4f766193d965457595fd708fdd1d5e45929132988a250cbb6d49047ceea5a7d229ba568f9022cdfbe5e6cd7c201ba74ac1ba1a90679a02797e3661300ea1a0cfd5b1b5f013992653794a219d4ecdaae19e0598582f48ad7496557fa709200000002b52319c25eabb5fddbf0f1329721ff50aaf0ebd5adafe2886f458f0c7f2b004d206168484605a5a9b504465ba59d254f8cadc1bd5a2ab181ddfdfafbf205f0b40ba5593e87176e42872e5e3e46e42f28eb15d389bc08e95a05bd6fe04dddd7ddb240dbca64d7b462884689308b73495a273780a25c953d32d5c298c888972df69d450581a07e6465d284b56b4eeacdd2811b655cbb86a9c7c19649bbe5df94d24b840d895c372374af8e8692e9bf66b142b3214f70c3da25c0258bc8c2eab1555f1fa270c6d9fec15b2bffdb1905f86ed286cf41ee3fb30bf7cf3e51bdf05e943fc018f613b86e8ff48aa3d9ebe0cdf6bf8a6d35626ec7b0934b6094160c087202b387e119ec10c4a8963ee52710d75c21710881bae7fb5a8595fd43a9156419f8080891e50139bd4af14f1ba25ebe0152b5e83d115be493372e147742d8bfe3a8269e8ecd27ec055a11055d5405192cda8c8db528f06b120fc2e3f470898974118e681c1b99e40a986ff74b97d61f5c4e88e52c7aef82fabd2f44256ffdbf980635cdf40bdda88c767ddbe643aae7ac4ab61f5b500bc405db39d6d0ff790878a76c5d09f8a5a21010b71ea9bccf811db26d23f437bf196fc0e42ef701068d51d33e4afcecc6ee66ed2addf6ebd1480dfdc2f9e25462d573493bd645e8a7a1336118677a442c14009d33e4bfc1756b09039789a7e806d5050c2fc70e33842b904042dce8c4121c2e82db496052715bca21c7706daf66b0990c88c2c628c1d4f23500000007a23a41c1b755d06289d7546233e2ae891c82f7f17ed0422d1f8754a20e0c7bce8b7159ea6d0680246f5542f662195263a45c271dd1a930a5791e9a2fe7d8a64cf235b20f07eb1e5af8664c15686c45e5e2811b570e27a8dfab1f71936f038320aa43184c3d0ef0bf81fc71b55d7130275eda4f851c02843c47bf5632bcddfa1797116ece6d63df159b63a22215a1f28988f6d990c1ab70d364d886e322f3147783665325302327ba4ead49d6bb759b6f45e95e391081185357516860fbf607b0932cb683faf83fbb9f31d8530facc9f9fdf04fdcbd2d83ca60f8f7f73852cb0410eaf3868c2e0d42dd2cc3cb96ecb7498dc3c337260451ee86b551c8bbac56ba350a2767f4afc4c891c00030c60629f6bbe0df10804206ed13fbe92971eb40868a9758765fa6499efeb9d1b3f924be03dae0815318a70a42a9bc836139cca5cae5239482d6a65affa6fedcc9776e77c9b65eb66297aed36094dc65d7d9f13302bb6d2b6a079cb6285e96bfb14809a8fff7fa35b63a68f295b6b977f73a4055e682ab6564c3a56bd9b63cc39c6fbdd01646b75c9d35974c4dd5cc4ad44113cd0635f903d48339fdf5276585b1ed66a991ad291af87e3b5c4f2a9247272977fdc8b74fb9dd5eba894f6e78184602e73e2045fcd3cdf8192fc038e3778599338cd9a4920be187e5b212a010a6351e865722a5ea0f55cecc492ec52b11679f8e3d2e9ce2e9bbd37683c44fef05e8c5c84dd0b8920b14c2aa9dd0e47ef96f2442a2969938fa8235eb06b166ee46115c3be5ad83cc73a0175564b6080401ca5ebe79ad8b383b94b8d167eef0459deea932a3200ee323c1542543b71b15bcf84a0d6bfdca76d30e1c5e593602a6d119e488db1b91fa39572973fc2e47ab7eaac489df7379fb9b4c2b5939f5a84b21d13545673640bc9750d94ea0aebd5fbddbc811692004e66eae5c8461c1d31a812bae721d8c76c44939b499779660f27b6bcc89168941199c1edfd9175ee71cf46036c9b362ac72922e504c42731eecfe146629257d01", + "proofValue": "0000000000000006010098ad4f48bcd0cf5440853e520858603f16058ee0fc1afdc3efe98abe98771e23c000d19119c28d704a5916929f66f2a30200abb05a0ff79b3b06f912f0ec642268d3a1ad1cdf4f050ab7d55c795aa1ab771f4be29f29134e0d7709566f9b2468805f03009158599821c271588f24e92db7ca30197ec5b0c901efaadd34cca707e56b9aab1a7f14e329816e2acf4d07a7edf1bd6b0400af07a1ba7a22bcb1602114921a48fa966a821354cd0dd63a87ce018caccc50b56f2c9f55a062cdc423657aa5cec8a4c9050100097465737476616c75650602aef4be258f8baca0ee44affd36bc9ca6299cc811ac6cb77d10792ff546153d6a84c0c0e030b131ed29111911794174859966f6ba8cafaf228cb921351c2cbc84358c0fa946ca862f8e30d920e46397bf96b56f50b66ae9c93953dc24de2904640000000000000004a547c8619f3ff2670efbefb21281e459b7cc9766c4f377f78e9f97e2c50569a8dcb155f2a502e936d2cb6ef1a73e92af9916e6353b7127d55bb525cb18074b5ec130463e03a4eda583b05c2d63db40a08ab8bf05f930ec234cc2f788d5f5bfbeab3e4881918ce964ffd55483219edd435ac865286bfd313cd834aabfa8061d2ae173cbe4b59ab2bda78faa4c2c937afba80d7fba0822579ac0ef6915f4820f968a74f00ff5ab74e90b0a7bcb2b92093a5e94a54aea1d48ffd1e5bb3fb48069bc8a3c5994b768eec8fe6aea7422b208e8167d1baac746a147148d64214f29909c00000005000000013611d8317f5d7e7fe664dfb14bd4a96e7937ed67de385acacb15ffff3a99cc892df76dd074efecad1e6515831e4b1ec778cd8d2da5aebc15fb5c7bccb3821169132da1660bec909f4ac6e09f3c0f6240fe6e01fde4d6ee52a70f4d8e49a40bcf000000021ab19f671563117ad0fcb561cf74382eb4af7ca968ba235cc651504ba4dd494b319215d7739191f254ee4948a7b011539fdfb99af441f7bcb593dcae25d564db670c7e6b7717950abd02db9ceee5b7d53737618ec4e09da403c2c509d126caee000000033e6c099e09eb27f21d93e1bd089c893e315a3c67265b885436b9679e102e2a55140b5127ed5c437b7e2767c45b7ffd50e34609235b6166bd3b9b7f7f24f056e75c8758c979c197f0049b7b3fd2e0eb76b1a450449b74d9dc0b6ce86a7694870c000000046f2801039ba3be90a43ebea75250e647f4cf059e8f31a6a110cb1588365556e9170b69418fd565551d60d3e98c6a25d345d5f11d8d8be4e368a013e662de5c296eab8ec4ca9a86278b435d63f733d93157de64b80d4124d238b780d382ba26f40000000547a3e190d199824f5ac60691d5a8891d2927b7d4c0a822ee7bfcbaeb7c8e08d15d8342ab285881e5ecdaffe89998ac605b001ef4f2999f9390aa8fcbb2c408b22c447a1bc21a5eaa5c14c6dcacf33121b5fe53aaf6129895c033aa22d78868c033b5e05df1cb5fa44901ec217a94c7c839abb17fafba113a745dd37e6d424fd40000000c00563335ce3be272031c7bfaf658ee24d1c5034576d80825c06bf4539eca4921980bfb1e4079d68736f26ee2e7f08d6ba6e58fc43e0207e2a151d47d82f20fc6910209a63b45c21f41c9c95c59da2cfa9646e2694e2cc835441b29188f1519f73b4a010101020f4d02af83526c2bdad4e86a66337dc9c818e1a3ec13d1df09cc7b17766e639a00423ce5c7937023ee8da438f9c54e087be280494edb4d104c527b63868b27a8f22dc0271521a65a32dc88989947f5b92f9df35bc024f6a9e0fd2048c424dee66600637632095291f1069b034ce85d2ffb8e378c0ed6c3718288a1fafc7b740ef1ab6af8ac0efb4d57b305e580ebca489307927a3cc6e4103c2fc690143c6b49e32e0048085153d8b392da92841612799165e7dc7f11fb79260d777ce2be2093cb6abe2d0fee3c51fe931ece33231e64fd157a9075e46b390c6034e9d1092fb7f54010000f4f82dc331afe2bec7dae2224c5dc2f48672aa702d1393feb8506cb053e6de849d151a88a252bba3c61375ae3115b976e9766e6eec2ed58ecb58cd6090d860601022b0a1e8bbb07aea43fd95f51d06a6a76cb92f1686daa5441f913d226c7cd55a0000000000000000502803596b4ba5ea05b1fea2b78e292f935d621453cffcd207e10f3072b2813ca3e963cebf05b19cd82da4bd5aad1dcc7fda1492d7ffc8f532bc4b37e9bf4753b7ae6b8f08e05a851052fc6ac7617ce68293678747d11f9a508bab6f7a60edde9c4b3637248644343e17b1925ae5b646201871d5bf9284509687fc88d5b8b637d75f601c12010f145d8a63f505d7e82e2d992c005cf70a37d099d6b077d4daa89786630eafe881f4179ca6f691a02d9a0b252b51a0f720d56527dee9e2eb76c64bc2afd13518eb9a4a9da74583aea387f165dbd0de9bf5cfc7f0ded32823a3bd1262968d7b7c187847720aa8283d75c3b6889cf377551123f951f0421ef1e23d8da17f9435c24a6d7f80f0473d6c6f0962bb26b02ae06318c6793e5d7d88ed6a83f00000007906d504f1c33cc09e1b23357e439cb1530aa2f3a84acbdb13cedf9c9c4a8248b1d139719566508a427cece0c11cd4ea9a9ede51badf9a23af022cf949adbea2425a7c8a2b1a330992fb51f42251c183dd9ea7620ecd22f1a5de743385cf981308f38c286d8fef790b59dd56a9b9fc0daf85bd7156f5526dd76e185362bb8eb77e3873c7d8d9d8ec02ddb0b6635bed14ea639d1b450b82f2151497f4dd5ff4fa5147d2189a7d76083f037fd2b188f1a7e64be188f1108441f9c734a30869ee6f994f7b58cedd6ffc267333a228ece5af5efebea335272e07ba2639da4b1db916807ccb56e614618a6d6a80e4b1bb90614a5575ccf209ff423668b169e5c6c339ac9b9806d1f1aee2712643f1c2e8d4d3ab142f3d544a5a420fd95fab2a7f9485ba06b6e7183332c307b764bc3efb1328993c11e731f00bc5fa52f331b9beda38420ce031b496aa9c0601cac5ce88ad96fa7182f4bc37f3c55b5d0335f0bbae7f790a90d5a1dd9223fba087f30b2fd559436f34bfdc2fde7bf4114f3f1176bcf86ac987a4f67f72450465149a47614a2ac5cd896368ae130a69609368b3c51cb9ec2c6c93fe38b8b30b1f640cbd3f5fa12876a30cd7ae255c714317ded74e4560db84a83ac48b667dc2d2ab822e2e1ffdda2fef0c3224f8796c73b01c11868fe97a3164f7f6273c7a8ae7b896c233073886b8201557aebdd6eb9c185d1840376b79d986682269702a27532aaa7908f73cda14f76d41dd0c28fe2bb1e24783900290e41ba730adeff83eecfe8017cbc68b5dd0a28dff847ff9553537401b14f5ef8acfefb4d9f508ff996668ee48719bf01837149a2486c8664df6c3dceea0cb70670d5a6912419343577db2fa0350318b4ab6d687dc8f9cb2953b8ea16f0a47cd05ef5109b3e1df46272023e8e4c4afec00f6c13dae62dbd723615a391ccd4717a1296a6c81d1d81f63a8a51efc3707b824286bbe306e317cf2b41bc35660fed74698782d282d2f69ac1c1f31fb89e1ab76e7317de765e001b2db373e1f055c5a0039035240c33b7dec4981aa53e914f67ac932328b31f3fc4d0aac1c19a4da4dab1b525a63008d0e40b86076a1b7e9f0f219955c76798ae8d5131eee35e9900c5cdc8b58badd7022044521d7ad239a91bb2ae1a02fc61472f7d3629d14070641a1eaaa06cfe8c01b96f2254b36a1e7a445f0805b302bab4a1ecda6016acd72efe6ecf261bad14a2431c531e993b3d4edec087cb5b0309f7319144d4b02cfe57a68949b0727de4dea9d1af3e6dbe8ed19bac11a8550e09cd8fe7423606bbcd111d930a6b695031be96c52eed85183e8526e48b9767739fbe92537742461e74076e3d5d70057b84f7963edb32772d5a981acc48fbf1dfa5806489194d6e22691bc11744ffb8266dfd7b409491df1a49c45faf85142788f22862f4584e4f49f381b3a800000002895eb0d679eba6b7539e8a2b0b1593c83b27eac57a909c956c70edc6194cdc5f1ffc68f199a3827fd6d51a6f92a7867c8db5d07f65e3670f828988a749df72aa80ef3823fff83cbab6b522fc1afc3a93d8d2803e6001f19d3704b2cddb98e9f1b9365f7588bb1ddbfc1340e80b170bb11617ad54880298559b2ac1daf12fc471ea99eb1b56a8de4872f833e978453a8788fbb260bf39c041ffa245b63cd346e5c81e4fa28faf45a06d1b9c52466965bb06656084cb352f77a2daa642658b3b20551173ad0ad5875a56c8fac0b4ba34c299c8eed82801262003b39ba5175627274148b7ceb112d4a60595ece65ec79a344640182ccf47f460c0abde90a395c8d30487cbd29bfc97194ed8868ed4e458c7b2bf8ab6f04efee532502cf588c4f26b9b2830baa635c56857be5fd6803fd35d508881bd7cf3b5872ff84640384e2576bd93d4d86fdafcba2df3f29036491573031ede2ddb09dd092ad890a68f07876aeeae64ac01d87cfd5b294df3604878d69c638415a713c448ea07c33ce8ee8def76defce22f36b1938c065375a4ff3dc3f3a287286ba2af7313c1ee8458a4a1d37b8c047b348321dd2fc7686161fa590066053cb19a074c9ebdb3dc901c419dba9c1eb54e1848c57956d524ed9988ec72c9dc3b6e2dae09ba5d5bb6def93cc94d01385855e2d07c2ca376bebe2e8d985866408bf6aa8e5f09e083e0e955d18a4c0a2f815ef41d55b3a5542059475e7ae32c006874827c4714abe9bf685acea9c8d200000002889d435b67a7d22a5e89dcde9e74854edbfd4b8906484b9f8838ce87ecc08e0f85c1df44034803872580e6cc59588fa98d3ddf938916ef2a168e61a2a02cbd4d719cb604a8d63faa6eca2e0c140d9a5e198c62eafa21848a9f977e92e9588a06b496235e3809417f4ac918e86211454b646eb8be272f48b503b40e58bf3c71919e30838fe4ebd5e6bdb74d51b772a8c582781302207fedc6fb0cf6e16cbc268fafb14539d567e7d1d75745888631a7eb4a9960df79a76d6224b2b8ecfffcfb351059e7e9e5151c41ee44f0fd8d2f9dbc6015e8f635078a0e9956d96a3116829d73e40244ae0bdf2e3f29a0518651c4c5b7c1e28f58bf427c41817d6474b8898102b387e119ec10c4a8963ee52710d75c21710881bae7fb5a8595fd43a9156419f8080891e50139bd4af14f1ba25ebe0152b5e83d115be493372e147742d8bfe3a8269e8ecd27ec055a11055d5405192cda8c8db528f06b120fc2e3f4708989741199065975bd9bffa642c317a3579783739fe66d2f738d43d39a25b5a33e06dc7879a5cc876541b617a913d50245f764b6b4b4a2fb1203c1174d39433137bb356f715cd5c8825d00e6192a3cbc78695374a2e8a7819dd1467bcec221251212a3782fd9d837f48b30b1de67becb0138eef162bbf1dc9641a8ccaaed97da8e253c501ae725c2e8b57e431e73e4b0f78a527a731f3663fa401cc7ab36aaadb095ed1255b51a600ffed9e5062b10905648089a4de17ccfaa8ecd73007a58516b3e758600000007ad7f37adf760c84b9675bb6e973fcb08cb08027049ac8d3ff522e5401ef7c83530def9308baf50fabd8c15360bddf704ac0b749c36c320eeb495cbc8daf41bf295c25a1646fe4b78f2c2eb3356877aeb57840f486b6192fd08397a72c3c94c7491ced14d277013dd038254f32a5c9b73ace5d919f7431d32c80c08658da8d002d10dcfb9d7c8fb742795df16e91e35fc832e498220be36f84ed8f89736d4d766a43477700e12904118db7992a814a6c9000c4ea11d93bbd41a64a77190131d9c86fba98f9f650002ff6bd1d2a82754ea85d30fd1002fd7da18dbcdd3323a18c88468750dbf5dec7e0904e7535ab48570a3e7a9f665c3b2dfb72b5da2adf39da4747ee3020b520add6925aa1a5c440e0a57954e43773240991a1f34e971fa70c5991e30f96c8ba34d075d47b3c0162f6068f5eb3df5802a05ce5fc9461a51edbda829ef8607eca819c13ca9e4459de90682e07af1b1c338d2359663a14e01b91c8495d97d3081c1badea61e58fb7c62c116203ecc7f26c04c9deb9cabdf7bb0cdaf2b8d6885d74b5d76e9fe07d3034d7b887cb7cd3603c58451d35542a2a72e65fe01e52511d0c607dedc3a6053ce655ea136af1a8b1daede59882b89e1c29ccba301e876d2e958ce6089a689bfb11a5592d00ff33d4a3bab6d883f522260c313b59b87e42ce6d5679c8b67178154d99a4a03cf36ebaebb1171403ac37ab45e166ffcab0624b2b69600617ca8be26764881e4f6c6eb0237b48148cd8e5aae3c09d22a6e4e527e13667a803f38aeae50bb8d973634048885a02190af2914add80ab4cf36ec411934987bfb2ec3da1e3619f249a6c694e88ae070ce0935340a6d8a67bd21db8dba4cbf04af35b15404d37f8479acd122d2bffa17e890c0b2448f3bee34cd46eaa0b5d7132dbaa2f8b25cad41f7a8184fbcd306f422fa9f0bf1b37f3789633d68b97ad4527bf36d5a2fac68c4316b74c098be94b6743a3dfc0e00a713a8e7b9dcd50c002a87b4207705c6f70dae2a0730613cd834f882c43f721d6401", "type": "ConcordiumZKProofV4" } } @@ -1328,7 +1328,7 @@ mod tests { let verification_audit_anchor_on_chain = fixtures::verification_audit_anchor_fixture(); let cbor = cbor::cbor_encode(&verification_audit_anchor_on_chain).unwrap(); - assert_eq!(hex::encode(&cbor), "a4646861736858209eb4aa6091914e2c5a5e64a6c5d2e23f5172b40ad8bc4d53088acf7bf43d1766647479706566434344564141667075626c6963a1636b6579046776657273696f6e01"); + assert_eq!(hex::encode(&cbor), "a464686173685820b3793f06e85809ae98f422cdcb5f508b4d5cd78f5a1732cd95d82a54f2b32037647479706566434344564141667075626c6963a1636b6579046776657273696f6e01"); let decoded: VerificationAuditAnchor = cbor::cbor_decode(&cbor).unwrap(); assert_eq!(decoded, verification_audit_anchor_on_chain); } @@ -1358,7 +1358,7 @@ mod tests { let verification_audit_anchor_hash = fixtures::verification_audit_anchor_fixture().hash; let expected_verification_audit_anchor_hash = Hash::new( <[u8; 32]>::from_hex( - "9eb4aa6091914e2c5a5e64a6c5d2e23f5172b40ad8bc4d53088acf7bf43d1766", + "b3793f06e85809ae98f422cdcb5f508b4d5cd78f5a1732cd95d82a54f2b32037", ) .expect("Invalid hex"), ); From 8f8361976013f80e2bfe79d64f8c767902d2f4d2 Mon Sep 17 00:00:00 2001 From: Allan Rasmussen Date: Tue, 25 Nov 2025 14:02:55 +0100 Subject: [PATCH 12/20] fix --- rust-src/concordium_base/src/web3id/v1/proofs.rs | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/rust-src/concordium_base/src/web3id/v1/proofs.rs b/rust-src/concordium_base/src/web3id/v1/proofs.rs index a6e3d8b1d..0e750c2e2 100644 --- a/rust-src/concordium_base/src/web3id/v1/proofs.rs +++ b/rust-src/concordium_base/src/web3id/v1/proofs.rs @@ -71,6 +71,7 @@ impl, AttributeType: Attribute> AccountBasedCredentialV1, AttributeType: Attribute> AccountBasedSubjectClaims> IdentityBasedSubjectClaims> RequestV1 } 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(); transcript.append_message( From d9ec71a0ddb985963803aaff4e58ecb553839b6b Mon Sep 17 00:00:00 2001 From: Allan Rasmussen Date: Tue, 25 Nov 2025 15:27:03 +0100 Subject: [PATCH 13/20] test --- rust-src/concordium_base/src/web3id/v1.rs | 4 +- .../concordium_base/src/web3id/v1/anchor.rs | 6 +- .../concordium_base/src/web3id/v1/proofs.rs | 280 +++++++++++++++++- 3 files changed, 284 insertions(+), 6 deletions(-) diff --git a/rust-src/concordium_base/src/web3id/v1.rs b/rust-src/concordium_base/src/web3id/v1.rs index c57fe80c3..e15a97ab2 100644 --- a/rust-src/concordium_base/src/web3id/v1.rs +++ b/rust-src/concordium_base/src/web3id/v1.rs @@ -1894,7 +1894,7 @@ mod tests { "issuer": "did:ccd:testnet:idp:17", "proof": { "created": "2023-08-28T23:12:15Z", - "proofValue": "000000000000000502b12365d42dbcdda54216b524d94eda74809018b8179d90c747829da5d24df4b2d835d7f77879cf52d5b1809564c5ec49990998db469e5c04553de3f787a3998d660204fe2dd1033a310bfc06ab8a9e5426ff90fdaf554ac11e96bbf18b1e1da8a5ec51caa2b6fd6fc32ee131f7ef87126c610792f050563ac76138401936acd2a28d2d5bdd050994b2384584c9c748bea6ecfe85facb2920dbf349194bac86c4d8c60697b51d298d906699f7b1b239852f5b784eefcceef3a9fbc157d4c957711b21591d8bd3f6ee889c55043ac6cf4cba325b25aacee116aaa4544090c6f6505715b9602db53eb3d65f38b545a0fece7af159acffb5816089bed5f6a5b7640f6d16a140ca7abafded72cdbe4f8804655d560865ec5cdcd7fade5ec00a1abcb400000007af0c150c10fca79fe5d585c034b97bd832af43996af6dd501103f83cad750774023b40207c95a4e308d77bb9b84afff2b1affde5b520372b5232f2f736368ca5af4eec6c276a6ff47b8b52d0efe59705b8a2e4c5fcd8fd03ff126cb279088561818d42980c3ab3f1d6554247bd4c5f0576c6eac703e15b37f50febef3a0b9cb9cd8a08d97e8c4663ec74d75b9e0af057820097daf36eb3a608b8fdc794cfc464b07dcf168ad8c53489580e024b56aaa7be41733a27f055f4daffb5fd7efc1b7aa56ab6745221d87503add6d41fec8b5c47735d771990b1ce7cb0c00fb05511434b4ffa3e57b48a65b4afd5d20ac6f1daa14e71dfc41eb61ce6f097f93f586ca43a7d29dd846ccdb00718dd7d74031600bfc04568587ca2b6a3df2b889d9d21ae80f162354f38a8eeb84637af702bc69ecffc1ce9d1a936e141cc9e0b46e39b3421784f7772945f9393e2731e97ad659ba8579c62762fc287fab66e172cd5a0ace34acaf203d02f9576abc95f496ea7e3095a6c9ee4a6f2194d13716caf9851d0b3a66ed3bff369446904ba26bf6e938d73be1f6b697e9eddc531a4037dd45cbeac31195215d2ac022acc7cd0db211f52a3a719aa289aaa83ddb285c69d6d9a48988bcae28451f673a53ccbe4f9464e4a70a05360a92c38547ed9f17c9f901e98836779ef4b7af3215f007aba61e272a6c649f5370a766a5397cddad16ce07a7b4eabefcd63a3dbdbc8101f90e43a1e0d8f2329a1b498617860ef3b37a08cc4445223b5e62cacf38ff22fa24298ada17299ce932a4c935929fc05f8a1b78559af803fd13f7faba91902d3ce16c9c0bf463d2111e7a0e5dc43e43daf88f13e1079e966cce2768fc1a9f890e0e95446b4aeb2f1541991efdac2d80122e8c266f81fc661fe698dac1161ec7528d6e27e98894e48e6de647af1dfa0f33fbbb8fb6dc90f75c2b6cf5a22bb350d6ebddcc0d3ba6d532076a46dce8de18471fd63c7702e2f54ebb6041b5f629647e7ba313fee83171d208cf1f53652c2b6af1c5b378fcd03b39554bf77b9ad30ef725df82bdb6c5456adf9ac3187ffbeaab1b4ce68782829850f10182deb13eaa94edd3640768224a178b8bac224d12711c7d3bec925db4da9bd1424db872757a1f2e10c9dac40483a69972504e5d69163a9f13c5dc8fc608479e5a7b885ed5300b746e24729f07c75a94215ec7a2e6bc01b52f714de7dfc63693afd5d10d3b04edcfb4704a99c64983dc5b1665379da2e164918917e25eb3cacd93a250da5790b3499c4c6c6b0b327b4b38609f94fdebda725d9840fd1704baddeb3ce42b6cf77c9a5a9e7cf79d9fcad623f797f334bde7c1f1b72b0238f522e5d35488db09f13f60ba2f86a883994e5c81b6c937c92ba44b8f9eb78144023bec3a769f8fe532b5a5f523662e23dbfc91e9d3392f1fd0a821d85903ae4d8000000028bd4214b4ce7aab1c510f757c7d862ad137db2a40002bd9b828150d950c6525dc5c54f1d8f144b70c62cbb6baa740ed298733424ad4dc42d9fea5bb89c05b59eb9b4fb1edc063971b7046dd4caa65097c05ac9c8d60d9ac014d75c58d55d64a5b9fa6e69d9a5373cf686b1ae9b138111e2fcaa4398ecffb159ab1166a6c09605a95d364228e82099ec09d47a5ca33493b394cef3a33b32404627b3df2fea323e48ca3437761d906b44648486ee2e00e69a007fdbb4352e905f59f4540a7d22d43c5d6ec39bfa7f969975e5130fe87aba477186d1f486b50f26840ba9e676a46c1ac54737ab10f3d36e50b67901363c30a23ab1aadd8f7c3d4b9f050bed425381048b69df7282cd3234e4423e85d15c09d49fc2005e869a4876fec01369c3b0ec0ae6f710797b4e5294a7fdf72c05341b6887da98066400436af27e739c140e3a481df2845cd78df942a2c0fb01429d5b04cd96b18c0b2bbf764b533a6f095edbeaa93b55f721ac7fd624c1163bd7507799c725d5438282dc0391d1d404d3b3bc61eaf150c5433f8f009e0881922a24e6308302a4b44dac57a9d70e8acef97595401632b5bb7816025493181fedd24679cf28562fd5dde2f761e3c68dac283df0ab6905142ae1694de00d4b9aacdf26e911671b32bc5436bd02e1325cef59ab9eac432752a04d9cc94d597812e8d88d30dae0af5ce15afe35982152837296d2f3800eee823a89bfc817aadd9611e44224cdc8e5dbeb5dddc979265c5d5c5efdb44700000002a24f5463ca685e8a41d7466050daae2fe1e985f423b63fd564e9586819d9f78558c2615e19acb8823594b87212ba353cadd258c6bb1781fedb9cb27fe8fea9498f6fea4b0702ea8b278fafcb46491d620f224447db7b4b7323cf3dcc8b92d556953a1f1132db33ccfd0886809900a5a77956dff23108e05f99697ce1a7b8b1596a48e545ff904d43a1fc255e5fbc4ef383d7c66b6b6ae7a54b7cb461334ee30afd3a72b4b4617521d029f41a5f00bc8c1cde8df2c4c4803076217272ad37a8d0149465dc4f3c273edd845790ceb0e9b4dbc059d3f49180b7c83e6bc07e7d72234c41f36e7c5249be8b6097a9e0d4ac4c9304c63f9b21c17ffd1faf41dfdbf60602b2a44460fcbf28d7ce0fce6c677113a88b88ec272d3cfac24d33afc47b6fa15259af84fa6543ef673cbd18a44d47420c8c53d7eaf9272dfa62fadd8d118c2055480b6494a67b0346c9fa0b2ba2cba9c0591224a2ed7b399ea35b89111a53059ca20a4730876439f653e04a98c88bde58e6d10f4ed5ca46233cb6054480a89806a7992cf6597b6822b140face0bc4de77a54fbd8b74c8b786c101f40bf45f6f59abb820108c5d1a51aa59210bf202f430f8b964b30e3258f6cad0ca8a8b88bb043d28f792f84570024c0a4fb28a1749972686488dd026b629489e3b8e60c99647159e9e3473ddd55ed3d9e56a17174509be24e80d9ae7bb558130bb3bb024cd6117245b472a3ece0eac70f73a68e64d092ece19c328632cbe998c1908c615537800000007966878c8fe3ae5c656fb13d1f07ad16689293c1747063a0c460a3d201c35b9524eb1966883f1f797c1d3025b879b755c8cfb7e0419df4760264ad7cbf17ed76bf12f579a8c1cbc4cf984003295912b123b0a4281df422814702d4e62259530b896bb5c6ccda5ec63219e895729e941e1c1716a4ef57863eb9de953bea60e625765939a89d9bd48f4b5d2caba03aa569889c8c0f04fa75c369b5a4e4d1ffbfff3bf586897d91041d562e42cd8d82ecb4befeb67cf8990458853d1763308841a74af0955364d0aecaa0a26e6649d46372710b080c4ab5037b6808276653a87971374d899de4e33ff946083f12db74464cca51694ad92c0e2d35e5dd4cdfa7cf3794b91bae217d36bc0aa6675ac53b8b230a4565d039059658a2c002d6520428d63a8015fab9c9a49215949fd76c740b61b6d0d9ab62661a3293eca495bbc7ecf3fd2b8c88d9e47e7e7a583e3e8bda2c548b4f8a12e64ba60a069b1683919af24477af10ef3fd8122c1c2011762fee8c5bf0bfcff3e7db2017a12074354b14a8e33a3713e51c622c88a38ee08ae14faae7629a03b494bfb062462305389fcf3b3ef03d52e2a89f8d08b3b2003ace3288ed3824a1fb3e4f5a1df7a56bf5e4f183a695cb05fae2002c3eb779c2df5c7f0467ffe75ebb0a1de856100a1384e36521ba2b14ba461a6405e1ef888978cff9d8d16a2afab190a06cfa8bef6fd5fe8b8453857fb479a85465d3487be0071f7f8a02b9712fb4073243e504bc2078b6cd00223582744730d14487b03c7f9db0b7fbb5c7a12e2b744d5804c28dfeea7ffb8cf11ab8185f04798a3fa52f49ff7f0d141b502e3d547e88865690ff3e5b80d951e287514d5741933209761d4173fa6ede87093c51c33750c5a12794091a1fafd9bcffcb27cb37cce184c1d07ed9272ff2f4cffd2944c946e25ccfb2f5ed017c0b4b04e45e75664b76562618774b3912150a65c9c4e99222226819d6b37431c6353ca662cb7dedb250677ffb5d9e2ee47edfc64da1f96404e307cb9fe181923a9c8c400a0155deaa4f088f5061a91148f29f43574245cf47a80f0205ed62d704f31d6ff1c0a381161223d1b0e04d63c5bf4b66d0870c60963319b59ca50cdb23a28e7fb", + "proofValue": "000000000000000502b12365d42dbcdda54216b524d94eda74809018b8179d90c747829da5d24df4b2d835d7f77879cf52d5b1809564c5ec49990998db469e5c04553de3f787a3998d660204fe2dd1033a310bfc06ab8a9e5426ff90fdaf554ac11e96bbf18b1e1da88db85b1fecf20f66e9a4cca89ca261430d9a775de164636011003d72d1d522dae8488fb5ff2b348e8f4f4f68d7bc33e38a29abf47db4d15f9d1b703efff0ed234a668d779cad8e592041828446206bb98c48e23e06684405903c6cd14e06f4c4389c1954fd8c8be55052680025ff77e060416cea8d8a9cd512da8d6a4d3651092557b7ec885d994d32e775174bebb4f61630fdd1192dfa1cd0fe0b76cbdbc167571a3b82445887427d46f406f2e8139e93bd8950368cb74d9219fcf3cc195b7400000007a6bbc0b7dedae5d3c9b4096410d050e926f6aaa65b63d6e903bdf533762b3f0eab62286575e4261a5adcaf800aef0a3394b567034287af3f6fa990315e29ab084ccefeca9ef5a185a64170b169fd3c90d3f70ce1f0df4b1f2a8a88efefcf2ac9831d560dd6c8328b470d21163a8fc3174a2456e76bb0672b85fd8d14ee08b257e6b54df0c9bd2142ce9a176af53c3b6794aeacbdb1b40f22c4ae645b10b218a5cc6d50dbf7b374e706de7b6ec9faf72d89e6e91b3383b1ab3b6d2d5be95af2d192eddb29452b78545944d23b578dc4a364cd626e57fffc2e4e284e67c4c58d4a58029ad2fe82a74c4f79ef643e3d417493b5a25ffc04b8968cf6ad43a6ff2e0bdad32cd83fc26f958177add5a5dc61dfda8e3c95f17ebef3d0d364c2ba4f55eeb7e5f7beff294a7df714d83a5cbbf665b711877e4497941d5eb99b4ee4ddbcb0b22d04df8a2290d1c29a4d2b559f28308ff961fad1c524478e5fce35f2b05b64e3d36ddf55af7b269436ae1e06cb2b106af4d3465e171f8b2f8d5c7de50cb9068b186360d490384d75fedb0bdc6e7349ff43f86b6ac6a3578281aca11c1c15ee191da64f61e9a28cad750167ad86b781b7d204a1f241d65006c6ba2de1bbbe35d00d55893780c487e5e772c5a12f20b61ec355d75fedb5969096200f7d1afc5b805db4b2b001629af1cb3f6aaa3abef758c282261264b36525e7d16a76ecc09070e9a0ec300b679bd773137b81335fb792609ae55831fb97c96449e29a438ec9f60e9c6ffdebe8f3b168e33b51e3cec726067ddd143537f21713968f8dbb04c796b66f80e11f416c7db00b43d7272f824ea5e5059579e746c032310cbe801ecb5f04b23346926141ee8b79e2e4d522bd93d263844569fdb5a5f29e522c31868408a82b29d6b0392c1ff173431155190c630145f1c9ad989060c456e7979b32b46ea6e831a80f9d4bdd4b3bb5dfa32cac82415a5258a1d3528eddf116378d51c449b7071b1902c289f468d5212aabb6fea40a3d4e9cddd9444e00b1b36369bb6c03b39554bf77b9ad30ef725df82bdb6c5456adf9ac3187ffbeaab1b4ce68782829850f10182deb13eaa94edd3640768224a178b8bac224d12711c7d3bec925db4da9bd1424db872757a1f2e10c9dac40483a69972504e5d69163a9f13c5dc8fc60b1ae7e6d38e19aa6374b3db2d0ed6918fac19a79981df368bb842f5b3e88ed9f88af521c771e336233d35dab81a3ef02b12475047f017ddc597aa597f49dadc9cbb0c72cb50b08c7e3a155f35b7879d64ea48923d6a550399e33a167dc783c7f6ced1b69d4180cca76304febb32c320703294b174da590c3607aa1651f0a88573997ddc59deb816d401a5130517c7a81f1e92cd4e5511bbdc15dd8762a9d285616c3a0b58c0ed867cc74128f52006aeb802f1a07237c66d8c4feef00fd2b1ae400000002a83a469f8f002dc2bf11e8c1b65e2a17b1f398c6806744425e444bffeafc34128320d8a061e226b6d7541ee0e0466327b14b41d7d8142aa18f5b3e734ca8b07cbe0d024a0f648e4db512ee56f4e7ef71d08b1fe3985db75d0beb6e1cc9b8c428971e9c0858baed4e935768dd2201aa82cfbf1692770dc92c7558f23fd46f5d050cd11a1cb476380011fca121f1ce23b9b43e16948af3b3fe4c8a15d4ff935476b23a67f14b0d2ee19a9c48ab89228be2772d63a50fe87fb9ce56dbf43f261b8a0de90b8f7cf375db6016b9b3fa0af14594312df176ea4070eae321a8b22f573c7183f0d3655b15dda99339fd9caa66e9134861e6504c7cc8188c19d1756383ec048b69df7282cd3234e4423e85d15c09d49fc2005e869a4876fec01369c3b0ec0ae6f710797b4e5294a7fdf72c05341b6887da98066400436af27e739c140e3a481df2845cd78df942a2c0fb01429d5b04cd96b18c0b2bbf764b533a6f095edbeaa506a369ea1e6bf58a89075f51344b7db1e4899a12383642a04091aaaef9fcf49281d22d23faca75c7de65be46fb3ae787822af473431d3b611a1aa63051cf37c2a5cae78b26e6e66e8994d62a5b1098bf61306a3418422199a614e4b09269953ec7d6cd85b83e0d4bb6d5370506f505e0e255e3fc86321938647e5638d47a3f711431d0e050a141c2d7a9ff7473515d24fcf7d49df7c62c7a311de1ba74e1eb017f29dec74a0c4b6c1033754c4cec0c45c85e99c62e654d0b6ed8087e811b560000000286384013b18b78f466a96c266b36cd1b3ae84b6746e1cddb521d5248c62eac29c1f7faddfe5094ce8fd5b457d65f0fc18c018bcac96884e2907c390ee2ecbe057336d4c1bd0c6edeba8340910f5ed88b1169283ff98cfecb016af2476595f835806f969e3a7b594d41af1abf47619d929ca35323890888d58febdb488ce9a2a170dcdc0222a6b33d1ce367702a5e6f6e84bb20150993878b7e5023bf51c427b7bf8cfb7b504e5e0258b25c7fe094a79dd4051c2807f480a36bf6d38795526a4f02ee00fa5456eac9e78022d1593bba9d6f4b09c064558cc5d433b81346c7b4f60c731be525a641825de736e0ea4776de5cbbe0c4d8c5b9c080b8160a39f868e702b2a44460fcbf28d7ce0fce6c677113a88b88ec272d3cfac24d33afc47b6fa15259af84fa6543ef673cbd18a44d47420c8c53d7eaf9272dfa62fadd8d118c2055480b6494a67b0346c9fa0b2ba2cba9c0591224a2ed7b399ea35b89111a53059c862afeedd50d8b65c822e69a213b0fc8f2e4188289ebbc5828ff043f0365453989208210c97536a7e9ee865af8872688935b3a9616c8802e3482a4074d0b759e11d052195453ef95945cd0557916d80a9eda70f61ffc653ce99d66caf1cdf7f0688f3bd5adc04f23552b0ef780e6c804f2738b60c3e812cc36c9c02484a47b831c0ff050e1513f54ba97372b1b8b48a278a56d5088ef09d2f24a6c9b95697c1406e4718f3bc71070191eaff6f89ce06c9aa5fedaeb0dabbbd4da46eb22a74ae200000007a5df6c977b2cceed7dc03296768edbe510f0674341d6732cd366a56b13469408ca9a94c1bd50f77074e351ebd8ec6a9485fa5193e1d6574ed673a8ea871fcf9621b0a67f370f56f882c062360c0f4038c1afb1d25dfb554f03b7757a71e61f21ab3baa7c7ac3d30ef2d5328fff37fb6658052001b90bf00000d1b553d8fe988342bee11e6cd1423131c019a9766272069248846381908bbefcf3129f8dbc3cf848ce7fa2e8e7d90c51e03634cf23574ecf51b9efb3b5c244bbbaf8f136c2e917874397a528529aa95cd3076f0ad4fe1751d25e5351dc4fbe28efabae297827a47f902d822b561304db940dfec34db5778e00039f96cb100e76c29cd3b71733f139054e8a39df0d5644285ac93486a2374ecea315f961f59a9c9f6d18fce437e286e11cc988e03ba537773e37fee3bd4a222bcc4361743621916bfd8e982b5957ce2f1dedc3e5fdedea8ae8574ef10e2ab24f53383813f54832fc7b3e79bc7a82c46b4b66ff5aa24086a59041ca4d9db7bff59c37820129d9f3df31007c17d1e48e63b20c1b9ca5106b3baac41a29318810fa8fed1e954c2cd4793db870fed9b17350aeea535ed51ff96fff8c1d7b67518a913efebe3dc3eaac543787be142064eb2fa0559b9f4e570d297ecf1d09bb704595217a5643016e52df4e1c20c0be398ef9832c8343626967d7f81eadd5d81d27a208ed586ef24d69ce7101e4a8384fc5a3cd25716c550c73a4b079d297b507a4ca1d6099346c31b4ade498589f40a04d072e6e9a664e07c9165eb8bb2d1f7568c00c09e4421cf5da5a466684df2e3987f692dff494949916f3bde458fd16f3ef4ddf09563b93b239ea442430d449c27a21215b5dba2930237640088c5d176cb3e5941d5f0a56982b2b05f35503cfc007b730475f28f4241ac28c5f955723f9d92124ab4aab89d198444db0de63fc100df9dab06a3e0591a5096877b581e7304278af7fe8778c13df4f0bc72e0801e663f075db89c119b8639b836a3d6026ec7610ed05fc405228c03e2bec4d60d61b00fee62d95135d4f7f9b06628d14597d9045d70e3d27d9ab7847b71e968b3639f70b5faf58f07543f340c7b5a6a12542209795ae19544a3e32bd966df630815b60", "type": "ConcordiumZKProofV4" } } @@ -2389,7 +2389,7 @@ mod tests { "issuer": "did:ccd:testnet:idp:0", "proof": { "created": "2023-08-28T23:12:15Z", - "proofValue": "0000000000000006010098ad4f48bcd0cf5440853e520858603f16058ee0fc1afdc3efe98abe98771e23c000d19119c28d704a5916929f66f2a30200abb05a0ff79b3b06f912f0ec642268d3a1ad1cdf4f050ab7d55c795aa1ab771f4be29f29134e0d7709566f9b2468805f03009158599821c271588f24e92db7ca30197ec5b0c901efaadd34cca707e56b9aab1a7f14e329816e2acf4d07a7edf1bd6b0400af07a1ba7a22bcb1602114921a48fa966a821354cd0dd63a87ce018caccc50b56f2c9f55a062cdc423657aa5cec8a4c9050100097465737476616c75650602aef4be258f8baca0ee44affd36bc9ca6299cc811ac6cb77d10792ff546153d6a84c0c0e030b131ed29111911794174859966f6ba8cafaf228cb921351c2cbc84358c0fa946ca862f8e30d920e46397bf96b56f50b66ae9c93953dc24de2904640000000000000004a547c8619f3ff2670efbefb21281e459b7cc9766c4f377f78e9f97e2c50569a8dcb155f2a502e936d2cb6ef1a73e92af9916e6353b7127d55bb525cb18074b5ec130463e03a4eda583b05c2d63db40a08ab8bf05f930ec234cc2f788d5f5bfbeab3e4881918ce964ffd55483219edd435ac865286bfd313cd834aabfa8061d2ae173cbe4b59ab2bda78faa4c2c937afba80d7fba0822579ac0ef6915f4820f968a74f00ff5ab74e90b0a7bcb2b92093a5e94a54aea1d48ffd1e5bb3fb48069bcbdff2e71c59cd60b45bd8490e66cb4812a03f0b5c04c157f1b1d2910adc10d4d00000005000000015b0526600d3ef05cb20f585ad0704f190dcbf4fd7cd096495cc4bd0770091fdd35a2d0763cf75826373239d3791636cca8990f52ab40f099b90b80345d70f8bd5db5d7f642e9edf556f39834c99ba0cc816c0515394a8e020c924d9370ccc92a0000000244fa95e305f8c2842cb28dda35bf1bc12ca280b0ae336d7245f3192eac9a897019a23bd1f262c3d9517f4ee76fa7e13d8a1ad3e1d2835124024a8d295f4810e6266ee2d5b31de85158f6c29c3c24ef53e94608365b848cb9f79bcdf24f8a445c000000034a2b6fdb6ece754989596832571c773ccbad8d7c01987af251ad783c901e709041c2900d1d5087a900e3f8ebc002cb094a9f73c3ee2d3c3bca798cf0d05f2844645af63e601b79752a739f62a8a9c6722acb5a7fde42bb3a0e22740d8acd12020000000408328d26a6b82a3b7c226a12d58a7354a10d86b2fd9ede1a7fdf17d4aefeb65c0ce4f2eb50a007bb1ce7017a5c5b6dcdadcbd0ef9ed7b17d525bceef6e92945970b375bf34bc25498eb7539c1aaffac4a9a69070c7d03783a653108b88d7cd4f0000000520a66daebce66a35d57230c28aab64096fe095eaed8db9e984cc0e43c47b1df616fc1b30bbdf46684dacc9826046a9aa0318f1793a70161a5390e8c818d7ca1f1438b65a3a79f9b08424336bfc84bd0966aa48ba5592cbccd041c6ca4910e8c8124643f962e3521f721ae2a595cea65a2df35190cb6050d2cd5d6af7c54817520000000c0069ba5877e546eaf50608f973b9800c4241058f08f2b154c6e824bd1abb5bc3e71f8240ea233b0028dbfbe165511f531761920dd01cb111a7ce04e6fee32268e00230002a54b56a47ae42fbf1845732ed66d18cc9db36424c7f105a2c00961ab61901010102613fb0a76d46e9bf506a37e147da34ff60261db95e6882f218d44a610488ad44005088bb3d81c5f47f46c395398967ffa0fca31da15bf5705f2499ddb19b2d357c4c7e1562935fcfa493d78164fe2594b29c144d65abb98594a117f577d39e4b4c006893ec35761361b10a0e2581141186a9b8758c95606336afc559c9ac0e517a5f610a060077c7a2fe19795f6fb34edb97d93aa14b2a620c288bcbdc9fd25658a8006e1c0336246fafea4b5bb33a7774750abc4296d2b3ad8defae9ee2c76565f4612b6687786aea7bf7c80179a50a726164084e260ba16101e68704032539ed9c86005c1c31878348f40a7bfd8da75ac0e607cbda5c0711985187d74b63304c3d4162179aa2b16fe107a07d9e9df4e97b60cac2618a162d326ffb7cc38f8f01f5a83901025c81a95fa449e47935bb87d45f72ab2fe7e627e154e73801f1565d8eaf76e7ff000000000000000502803596b4ba5ea05b1fea2b78e292f935d621453cffcd207e10f3072b2813ca3e963cebf05b19cd82da4bd5aad1dcc7fda1492d7ffc8f532bc4b37e9bf4753b7ae6b8f08e05a851052fc6ac7617ce68293678747d11f9a508bab6f7a60edde9c480cbbd8128425b47a4de48c892bbe3319a14a3fcb236ce94813473be81134d913d5365f0c78f68c52c639ca277e7d1cda1fedf1eb5d8c2427061dcb8c2581d6dcb294f8ce3e6dc889d85d3d0c8f31e8da26ae5585f20b3ed2f5827f4566c25e51e870a5fe08c30f131b85eb16c8b36ea5e58f7fadb23525194dfe6fabe1280b227ce5a63fc5f9eab33595c98c59e168cb5a0b43696623dc0fb765092afd7c3da2ebe184b46725ab0672ade4759aede6b6ff6b34db950453b8ceae02ea13b099b000000078b214e88a466ef56e32c833f9fb6d88e664506dacb77119cecebbe035c754a2e74f6eb0050a37ca86e426934f7e3834aa3d8469f618565940f0b4f41b2d6fcbb2e8ed1154533c82db51a7a9d6d9131e1c868b26c41c631550634418cd5f73b858760a3b10eeabccf1c158d504e597076819d79db87ff5829923edd71b9d86b4651913f9988502c8c2865108e2c8e4f65b03d518ee8bf7a876cb752fed3c54f71dd60962238a3c6065752e836243d672af69dad66dc2d5cae200c784813a1cd8d84731e0cc03090d0e99cc1d459f0a54951294f6604f1cadc5de861117878d9cf5e9eace25278736e4d150caffd38b9808fb58bced5e2f82313397af5d05b2bc0620b75ef984dbc6c120bdeb10b0646057934cf31bd4fb0dfc2a70ad24f4ce98b83c44eb9a1d1cb227f959e4d9aea5518aa9f67e883de83cb5b24065c9965748293066f36c023a73d3c7add09431b66e7951bc4fc055deb70ff246f15dc47f2f489347131987cca0a6fecedb170221f131bccfb2ed6b0b142fb314de84ff7b6508dfda3d662023ab275dac5a8e3f7455b9b3c3253959e02379249247c24b1bf6dcd61e242fc5cd0d229f954430d3aecfcae7d880082065efdc281d70db9f89e3236b8f956e50bd610c60f9fed98c3ceb3b206a286ac96d4ba8370d89a9de5142a831412c735fe0f54f3aed07ba419258ea03b86908307b6228d412afb2ef6c40f36619d0c8ec016deda34854c1bb36635ac8bd30589999cf93fcce2a057d980524d5ef9df6e7f50a497217d5e51a12b2f00094590d65e6150a1da0f8b36ef07c2ac1366d9a0d747f2e933e16a0a0c016146bf7f38dc07fdf868b2af9f9ed2a246654fe277405e8b6776e40a76237b7ce0a9a977825c565665d38b1d103f2f361531ae7601f5bbfcd6fc3324836096ed68fb37e8fffeeb25b141f9494ab8267754336e2ec226ca345d85c4f3eb95f3197a7fddcfc85087643cde45ca57794559956f3721a944880d44906f3f536cba39c3306634373c6e6cbc6d7ff91900de574d039035240c33b7dec4981aa53e914f67ac932328b31f3fc4d0aac1c19a4da4dab1b525a63008d0e40b86076a1b7e9f0f219955c76798ae8d5131eee35e9900c5cdc8b58badd7022044521d7ad239a91bb2ae1a02fc61472f7d3629d14070641a1e8952efa8c2c39e20be0df9fc47d5a6dd528132b0de03e82da2fbe2f47a8c277432d9d8c75be4129403904a144649a337963aca119b891a595ac454c529f94ac141c949858b200b61a42bb1466cc2d23340ac74e7a0ff27fd251cbeef326a572023da64f6131f1597d27983d3d14176c6cf2b22180d33da711cbfc43b2c983bfb1377635189ec44f3123bed01f622806af289c753650366101c6330817ea5c4815c8e3b6e1f091dbcbf4cef656c12ee5201913d86109110a134297322ab07d27300000002966689b03475dd11aff6774b268ac01ca27789f03185ccf24831213a5ae0ce0ac402fcf814a5165ab7cfe6e8d92aece6b715b6db2b1ec0578f50f25520f4deacb631aca326d717870b1accfb269891030e9d5c0bf493770fce64445c539c1c4cb053bee911f86c6e496af8d9693a41c1bc7b7c2a6338756d5dc5a75f20de41011297640d00b3f22900f511450108e4488f10f9ba29c945e4094ef33c80f33cac5b1d049744666f9333d93e551d287e21274238d06a1c35daeb69c1209fb70ca336c48c6acedd2a86a6b59358299b0a1eef60fdc3d9f24f52a37eaf5d5c3cb15c3013f943314dcbe3f5ffa80831865f46c28200c40fa6388373957b7f838cb2640487cbd29bfc97194ed8868ed4e458c7b2bf8ab6f04efee532502cf588c4f26b9b2830baa635c56857be5fd6803fd35d508881bd7cf3b5872ff84640384e2576bd93d4d86fdafcba2df3f29036491573031ede2ddb09dd092ad890a68f07876aee8f5dde25485be4382e448af473971dcc86ed35f2384d3054de8bf1cce7aa2abca2fc0a4b609b4848490ce7870f9caa44b789b56781191ed012c94953c08118b5c4be0d245ba8f6bf25e2de1d7a2bddb21ed70c34397b79ee49dfb02a7490dfef563f5cfc60cd9c4f060157fbd7ae4986bdc5235189866d73905e9748342e1fdd1fa9904c0c35eeb0771763f5d3b23f4f79eb8fa0435d8f96c4d85f0b4bbddc6355f6a2e44b95987e27250d29c85246d39ada545a7c249d82ad5017b279c9298d00000002a9aaf2f58d798219673b2b2825ca124cbcb936fae0956731905817f60f4ceb913cadf2f8739a7fd2e26cd8d284db4285b42630cd4950c189c434dbb42e11494e35be0a7abe9e64d3ab3b33281891f45f9fce3821d3db2eb784c45d7093ed2a988bf215e0ecd1941e52bbfb2e3b9164107a90d8f82eda64f5510c818e308cb03899115c0a57043090a00021ce38b2876b838b2510b0340508ecefe68a43a088398ba6861afc85ef3f4515bf177b8e62528c5e32334fc385db2b63145295f3e2186a3c03537e76313c00dbcf0f388b7d705ce8f9acec6827f7ca044322845e5f92561f33fc0fbbeacf8542f9716651ad2bede85f92e26701976426be110a2201fa02b387e119ec10c4a8963ee52710d75c21710881bae7fb5a8595fd43a9156419f8080891e50139bd4af14f1ba25ebe0152b5e83d115be493372e147742d8bfe3a8269e8ecd27ec055a11055d5405192cda8c8db528f06b120fc2e3f47089897411b7af706c4e85f57bd44166eb136a5baab2020e0e206516a7fe23bb76578bf51a5368ec22bccef7579d1243ba67d3560ea45179a519b9619f80c338379a6c73424aaf830cc9e883897db42fbcbdc02b486b5df87409bb5ac4d233578338e5b05769377a5f40d222e6992e685232f4eb9da8c3b3637e54907717157dacdaa0f0943c94d974c385098ee4933b54ead871f3ae8485d0130f14fdfe5209f50c667a6f23ce2cfdf7fd125c60e82c27e8a32ea281ad9438eb9212b2dd79a50cf5d18740000000079216f0e66e5f1918d0c0c76ea3a2d93e07675c26d52d1606b7c3a611534081e55e4363dc556915362431d6d617fbd2d2b312a345d2c53700066d3bdeb8e8330e9d2fff8c45553a24a712f21e4ba04ba13f3800377b2a47a945d9b192d00759cc9807f98b77a843d8987c9d3429ea17c5925cb92195f40fbbf55728f260b85d0ca3e0ce0dbc7850f064078a00cdb062bd885061ac95cdb89876b237451f2b54c75f895c73c9c4e55f24dd097fda90b97a0ebdd251e6f07c618a9cde161b46096ab5f033f9e22031db2a5ce3bf6ece3b0fb74128fb51a711a75da3d082dae5a978594710eb3b104789de0e11a05ca3d1018abf1dfea312143e48df89f8f00605e81b71aeb4140be08451ad2c33fe97b1a52e387fbdf57885cf6c2b59f25ae796aeb6929b26c9342cc54c621043e2a7ae2c023447e43c8bd2bf11f528defc4a13612ff3edee2900d970ae86a9b0f33feb1586cb687318c0a8b756703523edb10035207f781f36409d046d9a63cf917f4a43553b4d5b94eb8d9e1109aad16b574dcaa1912b868ef222dd50174a0f28fb5d90647e1fe438bfbeefc04f8267be621d57acb2c0ea7415efff0318c04bba32cd0b85cc6c8c5681e47f1bb4e512738e5e11bed711e089053bddbed5effc4b0de0e894878154f16dce626a8c532803f5a6fcb6e549428a2f2b5fd9d7b73afa98a3a1bdd5962502345ff5763b4990aa8bea4c05f1a818dd58c018787c4bd9facafa0686f9f0596721f50a2cc9681d7644aef13e32115d9e4fe86fc595f92e417c536c6b650cf4f7659b82d2649e52fc8134179065c0b808cf0e54b7e15f31b84c246cada5cb176e076231d38f6ee31332bcd1ac7c3933aa3ed59ce388058e1b42ab7588bff6a28518171a728e2ce69569347f5993a32241040c2b8c0b20ae2670929462bed4b599a5330e0f958647ca694b9515ae569d132fbef38dc03489bf9932153a9e324fd2312d5aa3cc2b2564597a68085c3135a3cb9cf5a3962b75dfefe7027bf0f19a8b7864c79d537a29e98459bc01", + "proofValue": "0000000000000006010098ad4f48bcd0cf5440853e520858603f16058ee0fc1afdc3efe98abe98771e23c000d19119c28d704a5916929f66f2a30200abb05a0ff79b3b06f912f0ec642268d3a1ad1cdf4f050ab7d55c795aa1ab771f4be29f29134e0d7709566f9b2468805f03009158599821c271588f24e92db7ca30197ec5b0c901efaadd34cca707e56b9aab1a7f14e329816e2acf4d07a7edf1bd6b0400af07a1ba7a22bcb1602114921a48fa966a821354cd0dd63a87ce018caccc50b56f2c9f55a062cdc423657aa5cec8a4c9050100097465737476616c75650602aef4be258f8baca0ee44affd36bc9ca6299cc811ac6cb77d10792ff546153d6a84c0c0e030b131ed29111911794174859966f6ba8cafaf228cb921351c2cbc84358c0fa946ca862f8e30d920e46397bf96b56f50b66ae9c93953dc24de2904640000000000000004a547c8619f3ff2670efbefb21281e459b7cc9766c4f377f78e9f97e2c50569a8dcb155f2a502e936d2cb6ef1a73e92af9916e6353b7127d55bb525cb18074b5ec130463e03a4eda583b05c2d63db40a08ab8bf05f930ec234cc2f788d5f5bfbeab3e4881918ce964ffd55483219edd435ac865286bfd313cd834aabfa8061d2ae173cbe4b59ab2bda78faa4c2c937afba80d7fba0822579ac0ef6915f4820f968a74f00ff5ab74e90b0a7bcb2b92093a5e94a54aea1d48ffd1e5bb3fb48069bc9dda27a50094cba9bfcf801e64dbe683c0b71926a7185436e942f8c8077566b3000000050000000115726915418468b26d6e74190b76915057b8a4241cce9c45ce7fb9eebadb10380d3c58996247f9589b75d980c22cb52bba4474635acdd36ca9608b03a4fa17071d2475f082a64d60185b4e66be4c25d82abc0da2539127a03835c23c92cbae27000000023c9d71ca25a598cb0ea22848c766906ff6ae52cd30b32e0aea57905edf89c7a06c424eb85df08da398507bf2a2d60873a927d42479a08e902c247555b5a54c266c4447fa40a7a8c1f693e71a628fe46d844ce6a79b9a76ddf5a3c682db641dd900000003687dde67f4bf5a0a89cf32468d344b296f8f243d6fa5946f96c04c2e9aa506b14330a6083226b65b55c3cea3985ab39b60b8d0db1bd812fb2ada6e14288da2fd07db10ace62993c934944bd63b11a0b1c098059905a6777970d04365c085d1da0000000409dcbd1240c0fc6eaa35254ccc5cb724442bbf38c7c1d37912b1fcccad403f2e2a68dc38582ba48dadae94def9b6bcca09cc8a76d1fe7d6a76e6891dfba34ba55e5cd0bb1bc71976f9f85768b82bdfe47664c6e2f6e87c4bc836c898b4fcfe780000000538f72551c6300c32bd3401901113c1a0de21b6c411f7b23dcb0978021c06043e27a762ac3f79325a7da5c92520bf30930a15b4f8e1f8e0345a8920944def95ab2244e704856d61cc42dc2b7765939b408f73150f0bba0069d43a388dc4b9af4c5adb834750b09315c12cc625f1813f9417f72f6d367f47585584c45d6471aa6d0000000c000438badd11174560b10965889ef2a5e06c7e10a049b1ca950b5641a7a6fa0d2c2dee4aa278a8d7dcba3625824033c4bae0c8336a73afe374f1366b8acec0b22602560a5a195d54241d9307176e66834046001a5d73649e7fc557829d89d897855701010102338aa101037d164c46e745fe608dd7bedb3dcc66eb8b6f1fdd0b6843e7260c3200198b0abade3d91b3a0dd7e23cad15f1e671037ef0a600b882f6b832defe318db20dcf6376d42d73fc9db0bfd4fc2c63110951792167ddddc89500980551f9bb70049f2851c9793009b5eb009d32a102358596a79fa951176c475e1cce3ab454c4064269569c392c56309f2ca90b77af6254209dab87841ed35042a44270ae946cf00496a71478e437a843beb8e522295c9b3479b4a28b77dd624268693eb9538d2ae5105514841b593230dfb8c64936082a79c76e0df7392049895001ccc0f81739d002e3175e30fe6f0eb0ef6ebcba037b75dcace321379a487be6db7ea03de3fa5a057cd6a8a6c24a45847ad6941fc7e3c347a39260427c7f413b95821064aff6e1a01023cbcc2d00f1f28d79687747b0e4fb70b22319e39fefb76a90ef22e021f96ff55000000000000000502803596b4ba5ea05b1fea2b78e292f935d621453cffcd207e10f3072b2813ca3e963cebf05b19cd82da4bd5aad1dcc7fda1492d7ffc8f532bc4b37e9bf4753b7ae6b8f08e05a851052fc6ac7617ce68293678747d11f9a508bab6f7a60edde9c4b092dd34e11fd7dd65823bd9a28f6169fba00b9b82cb9a8e149f43421c17a98aa5d382d05056a988c0956d330ff55f9caf87e8f23f45b9c3fd46fd17de35b9288ed1fde6fa48135fd76e331da22d2ebeaaa90098c9fb5744358a77cbf3a3043f51203db2a0423969266759114978722c077c55d02bffa1f76c8fcb85395cab013c3ba44446b18d561753335da9236fac7cb618432492eb7d992d699cc240456120da4c2712b9a44b640af2033485fd918ae817e81cf0e26057c66371f1b2b7b0000000079580daa7ed6bfd9662c47231c3094a8f96c2c25e5c0eba5336343eca68747f7e9918ac172c2211a43438fd47b136bd628ff969687ca71147490780b44914c168c007ed619431b041287d549fb96d51e6b41e7c28eadcfe553d53b870acac4594a6010d523918c8862810fc6c8cde78e3e5965735c1d00f0ef9b5cc4902ae52ec62010d0f98b9d07c78a3ae3eb1676f56b07a0ab8716ebea736ceffd92045eed660158cc24864a23b5b3e0cac55c68051dffaefcdaca795ff97e093d901173faeadc00b2053ae59cbb36864862c30bbcfa5032e1516590e380c2b5073cd1bc3e76ae8f8dc4edc892ebbe15805271f98c0ac22ef9e0daecde89e16bbf0f5e0206c32a54ed875a3de1e86d560f615c8c6cca5fe74d2c096003486caddbd6185b859b2502a5d05bd9ac863faa0a2ca54eabe1fab68df7086d78a486f688d4419bac0ca6b29288d9ee95df17e27d269bcff0fa521802f55a178e6189c4fc4e0c9aacc7641935f9750f7af0aac001a0efb0e2436afe8d40637b5f1b40858878bfa5ae8a017b3217a716ebdf27a1723a93865fe088c834cff4c2e27ebcac37e3d23b7bfc4a96f4d0d3e1ebf1f13ad4a81f7c73482802590d0c0dea55147cc163fbd143db10aeb8505a2d9ee098a6c47bc41fe032d729becf1b7131249773a9efd811e9caebd1d72658785b32470eab5708287532a4a4a4a91073b5b77e693c393ede85f4d23c77d4e7accf7460976f7ed911d9090748eb9498c76bb8ba173367a5963a938d8c2173d20db10bcc7c452f1f19f93b31a02b6f24794413dc183ea2bf157388d22397beb12e6e4a626ab32e6740a0c3d9bcb49579c27a479d5cf6f2d98b1227c690d734161166bbf9caff311f2c504a4dda5e53b70b8738b18dfa4fbb5ecd0b074885db065516a7a19b78c63dc1f5a72a8b843b5ea3c1b49feaccfa55216a81dd028a44797f262a0b42d1e617490f16f575f44991cd02f1a679d6695a0137b02423d96ee162d768f0ef1c74980e5728bfcda5fa69d451e3a64dea119b16aab039035240c33b7dec4981aa53e914f67ac932328b31f3fc4d0aac1c19a4da4dab1b525a63008d0e40b86076a1b7e9f0f219955c76798ae8d5131eee35e9900c5cdc8b58badd7022044521d7ad239a91bb2ae1a02fc61472f7d3629d14070641a1e8106424aff358bd337af5576ce1a48243e21c3b73051a87b7a914ef68645f82f5c2b1a8af8def5d639feea0fa02f625f9397619ff9538ec5ca1238e7f26451a7036e9319fbe3baadcefe0f09d32a37cbc7644b92ab9e984304fe7ee22886d8e7331b923ccea38b31cd4c5b6e21ea7b13f93a74d2e4e5c5abe8f48efdc901055541e152730c07ed5c80c97a3538602df6b37cbc864618781c1728ca3d13af97b33e922b8722a17d7b3397dbd604ea26446aee03488924d55a8dca65731db96bbd00000002a753709610f96d22afb715d26c8586d8971f9201ba327d6eb4a0ff5ee0943f81f7eef7901d85fdd59b18d825b64accae87447036ee703852251d2b9d0d9add516ea1c1ac8f68168e881c4a6ebfb1f9c1c7e7098b7aabf9e0a2efa2423186f7f4898dfca0ef6f07fdbd180a2a164d21b18b0424d7f7e9c93d326e3ab308062bf644184b0e76e3782b27de5b4b971b127a904946ecd4b94a21158d8ffc0f040b6dde6f044dc084ce27a016a1677099f3b335237a19623edc4940193bf706197b2832e1f8a77215de4dc73fab8cf1e1e090f57e5db737174759e3434b4da5feeefa41be4bf511821326cb664dcb6705c926e135c0de63e86b3c0fb1db02a47ecda00487cbd29bfc97194ed8868ed4e458c7b2bf8ab6f04efee532502cf588c4f26b9b2830baa635c56857be5fd6803fd35d508881bd7cf3b5872ff84640384e2576bd93d4d86fdafcba2df3f29036491573031ede2ddb09dd092ad890a68f07876aeea30b4541acc1c039323dfeb5a8bb81396cee8e41a591c6c559f24181b3f1d9a1cf386dbbc74e601480099930464fff2f820ffefe9c1754ea7220ab4fb95a73bd217f7440d26d803077031d039a09f366221c1d60f761f70bcfe592e099e41b4a5bd088cd1ece3af477e1d13f03c1459ad22b42f3479f12d7229de52d7f4ef95c689a33ade597a8902964e244e6cca0d1f94de905f9fccf95b774ed2b8c2a36f061f3a8da53b11d71d9855c79face7dac770caf93e5e9d7fbd6b2907f994bf8e6000000028c27c3a9d06054e718d61e0c97597c3e2aa2fa7b372b61e37fd02004a58cd9a9db0e4aa75995de479dc528369aae7850971c7a68b793ac91d3f8e31fe12200a63cd651d0fef437981c041f1417c0a7b35ffc2725f19ea6f47b2db483ad3c28b1ac997b445bb2fb55c276fb800e331cd8a406efc9074101a3b477df4d1fa187a27a07e58e3d0a5fff80d9c33f5b0d9f0685a41e8378e99fe37e7376290d971afcd3548fd6e7ab783c338558a58c7f4b17b3f2f19892b8fab86f297ad4fc25ba8107bdfd243161d90f6439adafe37e70edf6d318489571acc3761f12ca134dd42713dcd3d4e4bf11bdbabb6771a1d11f406969ed4f1b3dea7d32c292ffa07a302a02b387e119ec10c4a8963ee52710d75c21710881bae7fb5a8595fd43a9156419f8080891e50139bd4af14f1ba25ebe0152b5e83d115be493372e147742d8bfe3a8269e8ecd27ec055a11055d5405192cda8c8db528f06b120fc2e3f470898974118b864ba4ea9442144f894abfdc952071f586c663ee9c7daaa100295213bf22a96b9c2562d7f4bdbc878e59a5dff96d1793ff7a7819b528ee718513bcd5d6f44cb1ff1433d4a6a72d95a3e9c2f9bdf179fc0d999a689ba5f10717dd812bef9cab61b118dfc80d1f16fed604130e256bc3cbbd4a3f9e7aa656e685d9f801845f043178b7aad99f9214e790c31939f6b85e3d876351377a3d57b3c85d84876a93fd039a4ff13d73c3564d8cd9c4310b4e7bbc27f907b10b6f95c09c853e6edbb84300000007ac2df00a78778a0e2e4ab221df2686305b7c4f369c9393d83d2398442fd650d3d49a9171e64b20c4b341e8c5f0153bab845202926b803c5eef4d10937696d1f2917a5c1ddfa86860b780c7e9cdca49bc0c07973d1a2a77fa6688176e3c88c933afc37a04d49778bb6c3eac0ef42a67cde86dbee2825f12f848ed2383af2da472dde4fc29b9ed9267480363f587f5babcb86c0965845495f3b5cda6f3cd5d5784a3123b89a74b7732b51dfbbfb28cd9ea0f635c4920711cc8bc9512154ef679ddac1730212ea8cc4718c1085583c5c40b964f1aa0689595a8b6d1869f23a8d857c68251863f5c3e57c62f73d40090b437a337db8b01b5b258f5217fb81b634edea1f942224a7d6bb9124272a99f038980976a8df52094c62fe7dc6a07cbe2e67aa413ddead30ad92e54c0cdc1b915d2bedfef9660fa69b513736ca221fa4bd6ce054c90ebd9ddae7cce9f0c02630cfe7f88f8fec518d60cd79fd9f9acd653b8cb8707dc463eb942faf56308d8afd89a5d1f690a43203cb72049183431d0e291888a344544ea7d38ae1db3ee49d6d9790e1baa80abbe54db280593b9a7f632a0bd9298cc93f298b8b0a7b91eaddc1856e2ad00c721bb2099d944fa0a847513fa51bfca7822fb8163794fa28e8bc9712dc2f2cd5b6f53c66dd8a536f869447dbf39b4accb28dcec7de58ad83819bcc4ab0b966b165bb8e0bfcb30a6280e588cac873e9b3919a8bb8c3418f4cecfc2e14e60b47259143898aeb7380ef76d93c8e5102ffdedb793e49f23cba70e9ec04475394fffea2d0c6273730a101314589fc9c7ab713604443a0e8c7816d10d6581fa30fdb1552c61025ae3e85d46e7dd38e90d1a6d8d4921c806d9dfc84a7a0497335c8b9e4be2db89512fd2ca332ebb66ec302da2ab68f2a40cf3b957720348b7ac5414b9c7c3bf05c88fe606a31b69b5d6e606a0d8dce4c0952d047fec38e28ef722bfae923ca9104f1742f1df96ef9650543e19d25a3b6e8f93e0ac26841120c46cd416e9fa4a111b1ad3b8a171033d26a901", "type": "ConcordiumZKProofV4" } } diff --git a/rust-src/concordium_base/src/web3id/v1/anchor.rs b/rust-src/concordium_base/src/web3id/v1/anchor.rs index 850e00191..039346225 100644 --- a/rust-src/concordium_base/src/web3id/v1/anchor.rs +++ b/rust-src/concordium_base/src/web3id/v1/anchor.rs @@ -1260,7 +1260,7 @@ mod tests { "issuer": "did:ccd:testnet:idp:0", "proof": { "created": "2023-08-28T23:12:15Z", - "proofValue": "0000000000000006010098ad4f48bcd0cf5440853e520858603f16058ee0fc1afdc3efe98abe98771e23c000d19119c28d704a5916929f66f2a30200abb05a0ff79b3b06f912f0ec642268d3a1ad1cdf4f050ab7d55c795aa1ab771f4be29f29134e0d7709566f9b2468805f03009158599821c271588f24e92db7ca30197ec5b0c901efaadd34cca707e56b9aab1a7f14e329816e2acf4d07a7edf1bd6b0400af07a1ba7a22bcb1602114921a48fa966a821354cd0dd63a87ce018caccc50b56f2c9f55a062cdc423657aa5cec8a4c9050100097465737476616c75650602aef4be258f8baca0ee44affd36bc9ca6299cc811ac6cb77d10792ff546153d6a84c0c0e030b131ed29111911794174859966f6ba8cafaf228cb921351c2cbc84358c0fa946ca862f8e30d920e46397bf96b56f50b66ae9c93953dc24de2904640000000000000004a547c8619f3ff2670efbefb21281e459b7cc9766c4f377f78e9f97e2c50569a8dcb155f2a502e936d2cb6ef1a73e92af9916e6353b7127d55bb525cb18074b5ec130463e03a4eda583b05c2d63db40a08ab8bf05f930ec234cc2f788d5f5bfbeab3e4881918ce964ffd55483219edd435ac865286bfd313cd834aabfa8061d2ae173cbe4b59ab2bda78faa4c2c937afba80d7fba0822579ac0ef6915f4820f968a74f00ff5ab74e90b0a7bcb2b92093a5e94a54aea1d48ffd1e5bb3fb48069bc8a3c5994b768eec8fe6aea7422b208e8167d1baac746a147148d64214f29909c00000005000000013611d8317f5d7e7fe664dfb14bd4a96e7937ed67de385acacb15ffff3a99cc892df76dd074efecad1e6515831e4b1ec778cd8d2da5aebc15fb5c7bccb3821169132da1660bec909f4ac6e09f3c0f6240fe6e01fde4d6ee52a70f4d8e49a40bcf000000021ab19f671563117ad0fcb561cf74382eb4af7ca968ba235cc651504ba4dd494b319215d7739191f254ee4948a7b011539fdfb99af441f7bcb593dcae25d564db670c7e6b7717950abd02db9ceee5b7d53737618ec4e09da403c2c509d126caee000000033e6c099e09eb27f21d93e1bd089c893e315a3c67265b885436b9679e102e2a55140b5127ed5c437b7e2767c45b7ffd50e34609235b6166bd3b9b7f7f24f056e75c8758c979c197f0049b7b3fd2e0eb76b1a450449b74d9dc0b6ce86a7694870c000000046f2801039ba3be90a43ebea75250e647f4cf059e8f31a6a110cb1588365556e9170b69418fd565551d60d3e98c6a25d345d5f11d8d8be4e368a013e662de5c296eab8ec4ca9a86278b435d63f733d93157de64b80d4124d238b780d382ba26f40000000547a3e190d199824f5ac60691d5a8891d2927b7d4c0a822ee7bfcbaeb7c8e08d15d8342ab285881e5ecdaffe89998ac605b001ef4f2999f9390aa8fcbb2c408b22c447a1bc21a5eaa5c14c6dcacf33121b5fe53aaf6129895c033aa22d78868c033b5e05df1cb5fa44901ec217a94c7c839abb17fafba113a745dd37e6d424fd40000000c00563335ce3be272031c7bfaf658ee24d1c5034576d80825c06bf4539eca4921980bfb1e4079d68736f26ee2e7f08d6ba6e58fc43e0207e2a151d47d82f20fc6910209a63b45c21f41c9c95c59da2cfa9646e2694e2cc835441b29188f1519f73b4a010101020f4d02af83526c2bdad4e86a66337dc9c818e1a3ec13d1df09cc7b17766e639a00423ce5c7937023ee8da438f9c54e087be280494edb4d104c527b63868b27a8f22dc0271521a65a32dc88989947f5b92f9df35bc024f6a9e0fd2048c424dee66600637632095291f1069b034ce85d2ffb8e378c0ed6c3718288a1fafc7b740ef1ab6af8ac0efb4d57b305e580ebca489307927a3cc6e4103c2fc690143c6b49e32e0048085153d8b392da92841612799165e7dc7f11fb79260d777ce2be2093cb6abe2d0fee3c51fe931ece33231e64fd157a9075e46b390c6034e9d1092fb7f54010000f4f82dc331afe2bec7dae2224c5dc2f48672aa702d1393feb8506cb053e6de849d151a88a252bba3c61375ae3115b976e9766e6eec2ed58ecb58cd6090d860601022b0a1e8bbb07aea43fd95f51d06a6a76cb92f1686daa5441f913d226c7cd55a0000000000000000502803596b4ba5ea05b1fea2b78e292f935d621453cffcd207e10f3072b2813ca3e963cebf05b19cd82da4bd5aad1dcc7fda1492d7ffc8f532bc4b37e9bf4753b7ae6b8f08e05a851052fc6ac7617ce68293678747d11f9a508bab6f7a60edde9c4b3637248644343e17b1925ae5b646201871d5bf9284509687fc88d5b8b637d75f601c12010f145d8a63f505d7e82e2d992c005cf70a37d099d6b077d4daa89786630eafe881f4179ca6f691a02d9a0b252b51a0f720d56527dee9e2eb76c64bc2afd13518eb9a4a9da74583aea387f165dbd0de9bf5cfc7f0ded32823a3bd1262968d7b7c187847720aa8283d75c3b6889cf377551123f951f0421ef1e23d8da17f9435c24a6d7f80f0473d6c6f0962bb26b02ae06318c6793e5d7d88ed6a83f00000007906d504f1c33cc09e1b23357e439cb1530aa2f3a84acbdb13cedf9c9c4a8248b1d139719566508a427cece0c11cd4ea9a9ede51badf9a23af022cf949adbea2425a7c8a2b1a330992fb51f42251c183dd9ea7620ecd22f1a5de743385cf981308f38c286d8fef790b59dd56a9b9fc0daf85bd7156f5526dd76e185362bb8eb77e3873c7d8d9d8ec02ddb0b6635bed14ea639d1b450b82f2151497f4dd5ff4fa5147d2189a7d76083f037fd2b188f1a7e64be188f1108441f9c734a30869ee6f994f7b58cedd6ffc267333a228ece5af5efebea335272e07ba2639da4b1db916807ccb56e614618a6d6a80e4b1bb90614a5575ccf209ff423668b169e5c6c339ac9b9806d1f1aee2712643f1c2e8d4d3ab142f3d544a5a420fd95fab2a7f9485ba06b6e7183332c307b764bc3efb1328993c11e731f00bc5fa52f331b9beda38420ce031b496aa9c0601cac5ce88ad96fa7182f4bc37f3c55b5d0335f0bbae7f790a90d5a1dd9223fba087f30b2fd559436f34bfdc2fde7bf4114f3f1176bcf86ac987a4f67f72450465149a47614a2ac5cd896368ae130a69609368b3c51cb9ec2c6c93fe38b8b30b1f640cbd3f5fa12876a30cd7ae255c714317ded74e4560db84a83ac48b667dc2d2ab822e2e1ffdda2fef0c3224f8796c73b01c11868fe97a3164f7f6273c7a8ae7b896c233073886b8201557aebdd6eb9c185d1840376b79d986682269702a27532aaa7908f73cda14f76d41dd0c28fe2bb1e24783900290e41ba730adeff83eecfe8017cbc68b5dd0a28dff847ff9553537401b14f5ef8acfefb4d9f508ff996668ee48719bf01837149a2486c8664df6c3dceea0cb70670d5a6912419343577db2fa0350318b4ab6d687dc8f9cb2953b8ea16f0a47cd05ef5109b3e1df46272023e8e4c4afec00f6c13dae62dbd723615a391ccd4717a1296a6c81d1d81f63a8a51efc3707b824286bbe306e317cf2b41bc35660fed74698782d282d2f69ac1c1f31fb89e1ab76e7317de765e001b2db373e1f055c5a0039035240c33b7dec4981aa53e914f67ac932328b31f3fc4d0aac1c19a4da4dab1b525a63008d0e40b86076a1b7e9f0f219955c76798ae8d5131eee35e9900c5cdc8b58badd7022044521d7ad239a91bb2ae1a02fc61472f7d3629d14070641a1eaaa06cfe8c01b96f2254b36a1e7a445f0805b302bab4a1ecda6016acd72efe6ecf261bad14a2431c531e993b3d4edec087cb5b0309f7319144d4b02cfe57a68949b0727de4dea9d1af3e6dbe8ed19bac11a8550e09cd8fe7423606bbcd111d930a6b695031be96c52eed85183e8526e48b9767739fbe92537742461e74076e3d5d70057b84f7963edb32772d5a981acc48fbf1dfa5806489194d6e22691bc11744ffb8266dfd7b409491df1a49c45faf85142788f22862f4584e4f49f381b3a800000002895eb0d679eba6b7539e8a2b0b1593c83b27eac57a909c956c70edc6194cdc5f1ffc68f199a3827fd6d51a6f92a7867c8db5d07f65e3670f828988a749df72aa80ef3823fff83cbab6b522fc1afc3a93d8d2803e6001f19d3704b2cddb98e9f1b9365f7588bb1ddbfc1340e80b170bb11617ad54880298559b2ac1daf12fc471ea99eb1b56a8de4872f833e978453a8788fbb260bf39c041ffa245b63cd346e5c81e4fa28faf45a06d1b9c52466965bb06656084cb352f77a2daa642658b3b20551173ad0ad5875a56c8fac0b4ba34c299c8eed82801262003b39ba5175627274148b7ceb112d4a60595ece65ec79a344640182ccf47f460c0abde90a395c8d30487cbd29bfc97194ed8868ed4e458c7b2bf8ab6f04efee532502cf588c4f26b9b2830baa635c56857be5fd6803fd35d508881bd7cf3b5872ff84640384e2576bd93d4d86fdafcba2df3f29036491573031ede2ddb09dd092ad890a68f07876aeeae64ac01d87cfd5b294df3604878d69c638415a713c448ea07c33ce8ee8def76defce22f36b1938c065375a4ff3dc3f3a287286ba2af7313c1ee8458a4a1d37b8c047b348321dd2fc7686161fa590066053cb19a074c9ebdb3dc901c419dba9c1eb54e1848c57956d524ed9988ec72c9dc3b6e2dae09ba5d5bb6def93cc94d01385855e2d07c2ca376bebe2e8d985866408bf6aa8e5f09e083e0e955d18a4c0a2f815ef41d55b3a5542059475e7ae32c006874827c4714abe9bf685acea9c8d200000002889d435b67a7d22a5e89dcde9e74854edbfd4b8906484b9f8838ce87ecc08e0f85c1df44034803872580e6cc59588fa98d3ddf938916ef2a168e61a2a02cbd4d719cb604a8d63faa6eca2e0c140d9a5e198c62eafa21848a9f977e92e9588a06b496235e3809417f4ac918e86211454b646eb8be272f48b503b40e58bf3c71919e30838fe4ebd5e6bdb74d51b772a8c582781302207fedc6fb0cf6e16cbc268fafb14539d567e7d1d75745888631a7eb4a9960df79a76d6224b2b8ecfffcfb351059e7e9e5151c41ee44f0fd8d2f9dbc6015e8f635078a0e9956d96a3116829d73e40244ae0bdf2e3f29a0518651c4c5b7c1e28f58bf427c41817d6474b8898102b387e119ec10c4a8963ee52710d75c21710881bae7fb5a8595fd43a9156419f8080891e50139bd4af14f1ba25ebe0152b5e83d115be493372e147742d8bfe3a8269e8ecd27ec055a11055d5405192cda8c8db528f06b120fc2e3f4708989741199065975bd9bffa642c317a3579783739fe66d2f738d43d39a25b5a33e06dc7879a5cc876541b617a913d50245f764b6b4b4a2fb1203c1174d39433137bb356f715cd5c8825d00e6192a3cbc78695374a2e8a7819dd1467bcec221251212a3782fd9d837f48b30b1de67becb0138eef162bbf1dc9641a8ccaaed97da8e253c501ae725c2e8b57e431e73e4b0f78a527a731f3663fa401cc7ab36aaadb095ed1255b51a600ffed9e5062b10905648089a4de17ccfaa8ecd73007a58516b3e758600000007ad7f37adf760c84b9675bb6e973fcb08cb08027049ac8d3ff522e5401ef7c83530def9308baf50fabd8c15360bddf704ac0b749c36c320eeb495cbc8daf41bf295c25a1646fe4b78f2c2eb3356877aeb57840f486b6192fd08397a72c3c94c7491ced14d277013dd038254f32a5c9b73ace5d919f7431d32c80c08658da8d002d10dcfb9d7c8fb742795df16e91e35fc832e498220be36f84ed8f89736d4d766a43477700e12904118db7992a814a6c9000c4ea11d93bbd41a64a77190131d9c86fba98f9f650002ff6bd1d2a82754ea85d30fd1002fd7da18dbcdd3323a18c88468750dbf5dec7e0904e7535ab48570a3e7a9f665c3b2dfb72b5da2adf39da4747ee3020b520add6925aa1a5c440e0a57954e43773240991a1f34e971fa70c5991e30f96c8ba34d075d47b3c0162f6068f5eb3df5802a05ce5fc9461a51edbda829ef8607eca819c13ca9e4459de90682e07af1b1c338d2359663a14e01b91c8495d97d3081c1badea61e58fb7c62c116203ecc7f26c04c9deb9cabdf7bb0cdaf2b8d6885d74b5d76e9fe07d3034d7b887cb7cd3603c58451d35542a2a72e65fe01e52511d0c607dedc3a6053ce655ea136af1a8b1daede59882b89e1c29ccba301e876d2e958ce6089a689bfb11a5592d00ff33d4a3bab6d883f522260c313b59b87e42ce6d5679c8b67178154d99a4a03cf36ebaebb1171403ac37ab45e166ffcab0624b2b69600617ca8be26764881e4f6c6eb0237b48148cd8e5aae3c09d22a6e4e527e13667a803f38aeae50bb8d973634048885a02190af2914add80ab4cf36ec411934987bfb2ec3da1e3619f249a6c694e88ae070ce0935340a6d8a67bd21db8dba4cbf04af35b15404d37f8479acd122d2bffa17e890c0b2448f3bee34cd46eaa0b5d7132dbaa2f8b25cad41f7a8184fbcd306f422fa9f0bf1b37f3789633d68b97ad4527bf36d5a2fac68c4316b74c098be94b6743a3dfc0e00a713a8e7b9dcd50c002a87b4207705c6f70dae2a0730613cd834f882c43f721d6401", + "proofValue": "0000000000000006010098ad4f48bcd0cf5440853e520858603f16058ee0fc1afdc3efe98abe98771e23c000d19119c28d704a5916929f66f2a30200abb05a0ff79b3b06f912f0ec642268d3a1ad1cdf4f050ab7d55c795aa1ab771f4be29f29134e0d7709566f9b2468805f03009158599821c271588f24e92db7ca30197ec5b0c901efaadd34cca707e56b9aab1a7f14e329816e2acf4d07a7edf1bd6b0400af07a1ba7a22bcb1602114921a48fa966a821354cd0dd63a87ce018caccc50b56f2c9f55a062cdc423657aa5cec8a4c9050100097465737476616c75650602aef4be258f8baca0ee44affd36bc9ca6299cc811ac6cb77d10792ff546153d6a84c0c0e030b131ed29111911794174859966f6ba8cafaf228cb921351c2cbc84358c0fa946ca862f8e30d920e46397bf96b56f50b66ae9c93953dc24de2904640000000000000004a547c8619f3ff2670efbefb21281e459b7cc9766c4f377f78e9f97e2c50569a8dcb155f2a502e936d2cb6ef1a73e92af9916e6353b7127d55bb525cb18074b5ec130463e03a4eda583b05c2d63db40a08ab8bf05f930ec234cc2f788d5f5bfbeab3e4881918ce964ffd55483219edd435ac865286bfd313cd834aabfa8061d2ae173cbe4b59ab2bda78faa4c2c937afba80d7fba0822579ac0ef6915f4820f968a74f00ff5ab74e90b0a7bcb2b92093a5e94a54aea1d48ffd1e5bb3fb48069bce918947b0401f828565db1e1e51aa857ef93e03fa5ababc60cd4786d7a09634900000005000000012ce448b95daa378716adf0848b6ea854a371f8a640a27aae907a65e1d165b4df09aa5ed12957cf03b1d3e63d08f678e42d4741932fb8a68be3de3dc42052c332352bea7c1bc835e9610dd6ecd8df1fb78c5c175cd2a88a5ad4b4731993c2755400000002630a1133b728c97b192006c497ecaa7b547069790aab33afdfc83f83ba195fb53f964ea79dab2d0045d6ed96ed44e37d36092cff72896093383b0be9ca5b4d4205888ac87fd63f140e6af46eaff4d6f7b97df993db959ddfea2da9de2c614eeb000000033f555cc9e29211d7b6e0157dc9012fef3d0d7d741832ae5b5a871cdf86a16d6b19bad51c715218a9fd1cbccfd36ffd31954b70b61f224223554884554e94fb2e020c07103d39461b8d0f72b260869977dae7258753cc39aae01f668abd2030cc000000044edf6719f081fb79fcf6ad84c8345eda80969194af7eaca4b93469edd70590f85f18123730e9c397d0ae12a21236af34e6fd1422f50ccfd43858df85b8048b9734d96018a5f60a96f993f0c27dbfca86bcac0e8d43b33354b27d7e5c7877a5ac000000050d792f44183c862b920029f6676493d2826142a0efc12909fb25cf9bf65c5a395c2dcb0d0c0d0de256d634ecefed391c5c6f6abd6930cbd9579a9c3e32c7dc902fbf3973d776db8645328ca8e64f7989208dea27eacf54ad1723194a2a040f905696c2bfe78b0ec413d57aa4d0553e77ded504b4fe62cc36c47d6d4a86b5cfa60000000c0027725a72d2e64a1173bf298dcf55c676e05b25fdb2029536950b87cdf3d4d8025127ea383a77dc8d7cebe9877096e55154a548c7dc00ae167aebb1b11b9b7cfc023ff02d4e04a94e3f4f52a5dcb0e0f4ff42ec4dd82fdbafae5bdcdabcab5731b60101010226defceebd8ea21e70659e0d47156e9aafa0e8433825732220ea7c0c64f05f80006ee634d79329135d6e7ba852ed6f11bd8346ddbebb96e0024681aae104e161516c9104b5e1f3f4ce09805d9a6ac56165fc6e06b64b1009842a54fc268d88efeb004f7ce2fffb38f7b85cbff4d83175b7192ef53e497ac21e7a02c76c55ad09cf2a481dc049ec4b6c844984801d62ab5d0c48b59ca891124a42762b91b47c3be4e90020d451af64b35661fbc1b2c4758dc3999a26452142d418cc17c03d0fd54b7bd070b3729b387669e5ba643cc52237f94ccd83513cdf360533c95c0e9ec95d3321006ef4b2f6ea5557fec7a9e2add74baeb3e4eee4033df5f5fe36e5ad141bf06d596f834f74b7285f35675046152d9ed31e55bff88704790c15d1376b9d367eae490102526050662f7ce80610a9537cb546c5d9f6d70c2cf1868ea5f03e5cf6deb0f796000000000000000502803596b4ba5ea05b1fea2b78e292f935d621453cffcd207e10f3072b2813ca3e963cebf05b19cd82da4bd5aad1dcc7fda1492d7ffc8f532bc4b37e9bf4753b7ae6b8f08e05a851052fc6ac7617ce68293678747d11f9a508bab6f7a60edde9c4832a0fe5be28e50fb11eeb45ada1c695c32f32ca6770c0cbde453d35f27aeccb42c859a479428fa37977e6495dba22d2a26bcebabbc8d4608efdfcababdc2e4023775a5b4a036bbdc54c700947eb10a13dc6638380093a2ae32fbcd187759ae57210fdb66984ff3cbf005e211ff658d558e48520db37620ea4ff00300af4204b62f4cd1fadff410104c96f90db4d00d04d33eea519333697ac76ba0b8f58cc4f40080ae28bc9f6f6a2bab31997b3d6eb369410dea819480d625751f8e410acfc00000007b8fa84c66b844c262f4d87c05e6953ecd8eb1c2dbcb39e29785806b6e724444cec1c4631fafe2d443608e9d80d47268483b5d81b6a029b9c9649fd1b1c2ae2a3952ffe0d742a871f0d1c616d01a25739ea46932297339cbe4ead8fb80dc568fc83a7d525f6142e7bc8103573ed78d254eba1ef2efa52b702e97e77167d0be1cef32561ce45c7c39312ff9e4e4b1d22dfb93d00ec817a88fe25810bdd6f4e8c01c70b71176106a6a6dd462136bc3a864428a49e679341707c593efae6cd7c4dabb22af142f11717364291ac39418bbae54a1cbf388bd64f906ed1406a822bd9c7db49462c04efe016e51a74745c64bc0185782f409611c2dd92f08e0d7dc1eb0dea1e9435b739085462454d18e738bdde1fe076a0ca39256fc1327f479257093585f5affff4e6025362e02017164f1637144310ead68ce9c3ac0314508f564e2940f6c0844d0dad7fbfa5656d3cedb122b6ebd8e7382d1650e1858b089efcb881b5dd1cb90b0a70d5dada079298bed1c4656ca730b8aae399b6fdcfbd48e1ca34a5ac1a6aa26707161e1f93f0e441dd1fae1043eed5cbb0c57f4b387ffa8cbce7b7c970c9ac42e8e2c65174b10f2ba1b484c9ea785cfe0ee8ddd39519c35e9743c38e53b484e7ac0484b7762e7bf6b1aaf4d8a3b6f018bc67b62480bd404eee1eb4343460d1aa1847d16786e2b7f514b1086e7ab2af51290b7c02baf61761ed5c74e78287bd57c703dd28be90692f3c6f8d5680406f7a937798a144131519d71f61ce807b2b08b57e0086f49509a0c138e838cb8f43c05992c87e4a63c8b0cc8d98de91d2fdb7136c1ae9f1aa20a38c2e26453407caacd5ea8bf948f927c4b440a71dd3573add57d748f701a4d2d49472b57b1b9ab5947833e7848a1fe600367f4517a2a897bd31f12cfa9740d2bc2d49d84b2bd244dd818658b2a20822308b071e35161216b4cb110a40d250d8d0a1a3c468081db7d7405f3ec73760fc1c50c16c9fae68090727f52ca4d7ed19d7571e91309fa71cda8e88471d61177b55f4e5039035240c33b7dec4981aa53e914f67ac932328b31f3fc4d0aac1c19a4da4dab1b525a63008d0e40b86076a1b7e9f0f219955c76798ae8d5131eee35e9900c5cdc8b58badd7022044521d7ad239a91bb2ae1a02fc61472f7d3629d14070641a1eb0ae78b9d434a8d58901dafdb10f2a64139185d098d2fcc635495c59746302c665f5cd233c7a2af83135dc4c9d68c4dc907a48ea71e14e5940a31afad31331273c0b9b1a5f9135f7c3ac7da281227ec16ef4a44d3ea368d80efe22709a378ed90959f6cab2611b7fb357a5b97645ea72b798e9f1e191f4090e72b41ae1aa6feb33bfe631a37c4aed94bda117d3efae9f2112a2e01f36e1a9247b5ea2f13735440ba3b4471d203585873a2632fcc12617398d6ed2e0dc3f131a810c4c074c2fb700000002ab6c28f1723d6169913f2fee10bdd5ca0c0beb23e2f8df58bb2c66ebe3b6376a84748885a152584c39f7d043f7bd95428578a6d20213df102ba313d04144aec52c4b99e33e79371b78bb19912359dbfbf99f0b4bb1b41c3f46f62ecf461cdd909643a10b66b79d6a682b02c6dc0f4562a200008884830ae274b3808d1c5eb7c5821686098723f9d9c08b7bab607d91bea7ba82eaf6fde9323d88abec3b81b9b2208f014d7b044b019ecdb735538fccaaa3c1aa0a9b412feea2d7b454c62592920833c9b9f8f222e59082492a73f5ff331a55b0f7abb7690db49e685570ab256830f006753b41f3c24b192e079ba9dd9bbbca82beea28ca13bd7f64ada89264390487cbd29bfc97194ed8868ed4e458c7b2bf8ab6f04efee532502cf588c4f26b9b2830baa635c56857be5fd6803fd35d508881bd7cf3b5872ff84640384e2576bd93d4d86fdafcba2df3f29036491573031ede2ddb09dd092ad890a68f07876aee853d3fec93bbfc61b872b43b5e0ccac5ecf166b0770708e8d7ca8078b19dfcf4d3feebf4f962e0c69833338255e2dc2b8a2fb5b617875c72f21c30c492945f922375140d0a03c9bdd7329fa8b6d2666ff7b9a6effc7d6659aba3f27f92b8bf6f0950bb10453a522bc6062133552608efecdc132037309e88a155f72665dc6c0b48bf27b3cd3d215470d14c6579d7dd32a85f75b2c5687d0d349061924d01af5c550fa76e21935a60acfcf31ef1b8c6a4180833b89bcdb11728cce06c3c19078600000002b67cac0bc5add116b86ac8cca6abbfd80c07582e86e90d76ba6c6aa41d01d11a4ca907a634ee339cb5ee830719379885a774cbf76d65d324ae890313a1688b0cc161f6e0b47dbd0db2157a92739a20d028c30b6da5ec4ebb76e00c8a69fae0d4a8fe97431f898f3e65b4c43c619f36818c5de5db53b358d65002b96880a1de467f812a8b841a758315b0cfac32b9cea2912a04dd0a87ec3c2fa8d7ba2d739eb5945d79366faea8f118df235e57a83a144a507a8d74e39e1479cd320332aa88a5518f62e781c524e28f40c701dee87e94e8c8315b003c71e1976ab072e0178a91196c01b9e0c00da3b620a28b0f1b498989e6ec966c7718c62efea0b25cc2665202b387e119ec10c4a8963ee52710d75c21710881bae7fb5a8595fd43a9156419f8080891e50139bd4af14f1ba25ebe0152b5e83d115be493372e147742d8bfe3a8269e8ecd27ec055a11055d5405192cda8c8db528f06b120fc2e3f47089897411b92d9655a6d0766ec82ea392c7b6d1c05b00ccacf5e0ce8ac3418db4ff5b7f2def38ca2480f2dc03dc3defdb5c2eddcbb7abb0385359202fab02ff010884811e5f513504c482f30a6a41cf1a5e1eae4ea5fd7e83c6006dfd1859ebcf7ef69b5f3102f68b98b020431c735540f0faa51d05e380ba8be244af5d9208b0a659b6c23b42da958e514c545107c454f1f82e18e4f718be1ad9254fc4ba1d87de6d625b684497e14c6654b2d547d58e152800deb8a1d1ca39287461bb183c0b8cc529bc00000007970c4e8eedd5fcb380f4bdaaac76bfa3fc52b9fd9a8a40f3782355bd7bdab4999a32ee6fccf1ebc6dd7e54b21dad79bf981f13d11a242716793cc47ec6f0e19296135609cfcaaf472afcc4870df46c9b6f9f69cf1bc234757fba97a74c1cee84912a32caf9b90d7787d46b1c675be9dc0fe10f078835f36fece20295c1c890df280293fb1b7a9b2825f90b235dec576c90a953eb9f0aad4255e399ab2a4d179f6a7f8884679078de8a8a352af00ceb3a104a9b2222cf26cf3c889455adb606d0b34c7723950f6e26ad096b74b1f62a52b3bb1b0c8c770495e57a760f3e69c69501f898df1dcff10d726adfb09a26c821a268a7531e43a52ba39c1e3ac1d83a0a539308e37237e6b9d11ed659da956e2e49e4b9e73579fca7fb446777c8f52f49863620612e3de9d270364451c2f775dcd678d4ad2c0cebb4eeda7b41d5418b0d347087e168386a8a883b4d9a72a06e5daebdd392b3a306e5813c3e00b4af12d83154ece98ce449f2f479d6b2446b61c45dac93262381a68e276f8b6bfbb1fcf3aa50b209fca5d003daf725b635ea24c45e624ee2e0a83399ec513edbf66fb41f6cab206e68c4e5f30519ba581c65d2b7873b10a486c96fcb3824dd94d7448e747f27443ac395271aa177c2ddd9b16d24d29a4b4c7c9eff295741919aa4ccc9bf8437f3cad8668726f9b012dda2b87d5a61ecbbad868115389bd20fa945a604fc7bc28feb58f7dc49ec36293a80494f3eb8964a49c534346040cd47fd6e498fb3c2153ea6f059b751f9d5548ecb3bf3e1e33ec52bc52acd2298bd7141a6fe3e199036c7fa3377a20a9688e2731d98e402c6334892c0d3c2ab82ff1c2bbd928ce3ef57afa80568c69e005949b384d48c189539e2278acbc4580aa93e1dacc72daf67b709bc0384d54f8c7399b318a584100031954e79999c51f37d9541d0602e116953f7fcbffec6c850499751f9767f1c4be6238566565390e7c5a3732c65b35a149fddd3c10d6231e342c1771c9e35688f18874cb25ecda9299ed9763237c51701", "type": "ConcordiumZKProofV4" } } @@ -1328,7 +1328,7 @@ mod tests { let verification_audit_anchor_on_chain = fixtures::verification_audit_anchor_fixture(); let cbor = cbor::cbor_encode(&verification_audit_anchor_on_chain).unwrap(); - assert_eq!(hex::encode(&cbor), "a464686173685820b3793f06e85809ae98f422cdcb5f508b4d5cd78f5a1732cd95d82a54f2b32037647479706566434344564141667075626c6963a1636b6579046776657273696f6e01"); + assert_eq!(hex::encode(&cbor), "a4646861736858202b89c72a01903e99004e7968cfea1ba5a00980c04e09f2f6d60590a3b49839ac647479706566434344564141667075626c6963a1636b6579046776657273696f6e01"); let decoded: VerificationAuditAnchor = cbor::cbor_decode(&cbor).unwrap(); assert_eq!(decoded, verification_audit_anchor_on_chain); } @@ -1358,7 +1358,7 @@ mod tests { let verification_audit_anchor_hash = fixtures::verification_audit_anchor_fixture().hash; let expected_verification_audit_anchor_hash = Hash::new( <[u8; 32]>::from_hex( - "b3793f06e85809ae98f422cdcb5f508b4d5cd78f5a1732cd95d82a54f2b32037", + "2b89c72a01903e99004e7968cfea1ba5a00980c04e09f2f6d60590a3b49839ac", ) .expect("Invalid hex"), ); diff --git a/rust-src/concordium_base/src/web3id/v1/proofs.rs b/rust-src/concordium_base/src/web3id/v1/proofs.rs index 0e750c2e2..3bc4a89c2 100644 --- a/rust-src/concordium_base/src/web3id/v1/proofs.rs +++ b/rust-src/concordium_base/src/web3id/v1/proofs.rs @@ -700,7 +700,7 @@ pub mod tests { use super::*; use std::collections::BTreeMap; - use crate::id::constants::{ArCurve, AttributeKind}; + use crate::id::constants::{ArCurve, AttributeKind, IpPairing}; use crate::id::id_proof_types::{AttributeInRangeStatement, AttributeValueStatement}; use crate::id::types::{AttributeTag, IpIdentity}; use crate::web3id::did::Network; @@ -1517,4 +1517,282 @@ pub mod tests { .expect_err("verify"); assert_eq!(err, VerifyError::InvalidCredential(0)); } + + /// Test that the verifier can verify previously generated proofs. + #[test] + fn test_stability_account() { + let global_context = GlobalContext::generate("Test".into()); + + let acc_cred_fixture = fixtures::account_credentials_fixture( + [ + (3.into(), Web3IdAttribute::Numeric(137)), + ( + 1.into(), + Web3IdAttribute::String(AttributeKind::try_new("xkcd".into()).unwrap()), + ), + ( + 2.into(), + Web3IdAttribute::String(AttributeKind::try_new("aa".into()).unwrap()), + ), + ( + 5.into(), + Web3IdAttribute::String(AttributeKind::try_new("testvalue".into()).unwrap()), + ), + ( + 6.into(), + Web3IdAttribute::String(AttributeKind::try_new("bb".into()).unwrap()), + ), + ( + AttributeTag(4).to_string().parse().unwrap(), + Web3IdAttribute::try_from( + chrono::DateTime::parse_from_rfc3339("2023-08-28T23:12:15Z") + .unwrap() + .to_utc(), + ) + .unwrap(), + ), + ] + .into_iter() + .collect(), + &global_context, + ); + + let proof_json = r#" +{ + "type": [ + "VerifiablePresentation", + "ConcordiumVerifiablePresentationV1" + ], + "presentationContext": { + "type": "ConcordiumContextInformationV1", + "given": [ + { + "label": "prop1", + "context": "val1" + } + ], + "requested": [ + { + "label": "prop2", + "context": "val2" + } + ] + }, + "verifiableCredential": [ + { + "type": [ + "VerifiableCredential", + "ConcordiumVerifiableCredentialV1", + "ConcordiumAccountBasedCredential" + ], + "credentialSubject": { + "id": "did:ccd:testnet:cred:856793e4ba5d058cea0b5c3a1c8affb272efcf53bbab77ee28d3e2270d5041d220c1e1a9c6c8619c84e40ebd70fb583e", + "statement": [ + { + "type": "AttributeInRange", + "attributeTag": "dob", + "lower": 80, + "upper": 1237 + }, + { + "type": "AttributeInSet", + "attributeTag": "sex", + "set": [ + "aa", + "ff", + "zz" + ] + }, + { + "type": "AttributeNotInSet", + "attributeTag": "lastName", + "set": [ + "aa", + "ff", + "zz" + ] + }, + { + "type": "AttributeInRange", + "attributeTag": "countryOfResidence", + "lower": { + "type": "date-time", + "timestamp": "2023-08-27T23:12:15Z" + }, + "upper": { + "type": "date-time", + "timestamp": "2023-08-29T23:12:15Z" + } + }, + { + "type": "AttributeValue", + "attributeTag": "nationality", + "attributeValue": "testvalue" + } + ] + }, + "issuer": "did:ccd:testnet:idp:17", + "proof": { + "created": "2023-08-28T23:12:15Z", + "proofValue": "000000000000000502b12365d42dbcdda54216b524d94eda74809018b8179d90c747829da5d24df4b2d835d7f77879cf52d5b1809564c5ec49990998db469e5c04553de3f787a3998d660204fe2dd1033a310bfc06ab8a9e5426ff90fdaf554ac11e96bbf18b1e1da88db85b1fecf20f66e9a4cca89ca261430d9a775de164636011003d72d1d522dae8488fb5ff2b348e8f4f4f68d7bc33e38a29abf47db4d15f9d1b703efff0ed234a668d779cad8e592041828446206bb98c48e23e06684405903c6cd14e06f4c4389c1954fd8c8be55052680025ff77e060416cea8d8a9cd512da8d6a4d3651092557b7ec885d994d32e775174bebb4f61630fdd1192dfa1cd0fe0b76cbdbc167571a3b82445887427d46f406f2e8139e93bd8950368cb74d9219fcf3cc195b7400000007a6bbc0b7dedae5d3c9b4096410d050e926f6aaa65b63d6e903bdf533762b3f0eab62286575e4261a5adcaf800aef0a3394b567034287af3f6fa990315e29ab084ccefeca9ef5a185a64170b169fd3c90d3f70ce1f0df4b1f2a8a88efefcf2ac9831d560dd6c8328b470d21163a8fc3174a2456e76bb0672b85fd8d14ee08b257e6b54df0c9bd2142ce9a176af53c3b6794aeacbdb1b40f22c4ae645b10b218a5cc6d50dbf7b374e706de7b6ec9faf72d89e6e91b3383b1ab3b6d2d5be95af2d192eddb29452b78545944d23b578dc4a364cd626e57fffc2e4e284e67c4c58d4a58029ad2fe82a74c4f79ef643e3d417493b5a25ffc04b8968cf6ad43a6ff2e0bdad32cd83fc26f958177add5a5dc61dfda8e3c95f17ebef3d0d364c2ba4f55eeb7e5f7beff294a7df714d83a5cbbf665b711877e4497941d5eb99b4ee4ddbcb0b22d04df8a2290d1c29a4d2b559f28308ff961fad1c524478e5fce35f2b05b64e3d36ddf55af7b269436ae1e06cb2b106af4d3465e171f8b2f8d5c7de50cb9068b186360d490384d75fedb0bdc6e7349ff43f86b6ac6a3578281aca11c1c15ee191da64f61e9a28cad750167ad86b781b7d204a1f241d65006c6ba2de1bbbe35d00d55893780c487e5e772c5a12f20b61ec355d75fedb5969096200f7d1afc5b805db4b2b001629af1cb3f6aaa3abef758c282261264b36525e7d16a76ecc09070e9a0ec300b679bd773137b81335fb792609ae55831fb97c96449e29a438ec9f60e9c6ffdebe8f3b168e33b51e3cec726067ddd143537f21713968f8dbb04c796b66f80e11f416c7db00b43d7272f824ea5e5059579e746c032310cbe801ecb5f04b23346926141ee8b79e2e4d522bd93d263844569fdb5a5f29e522c31868408a82b29d6b0392c1ff173431155190c630145f1c9ad989060c456e7979b32b46ea6e831a80f9d4bdd4b3bb5dfa32cac82415a5258a1d3528eddf116378d51c449b7071b1902c289f468d5212aabb6fea40a3d4e9cddd9444e00b1b36369bb6c03b39554bf77b9ad30ef725df82bdb6c5456adf9ac3187ffbeaab1b4ce68782829850f10182deb13eaa94edd3640768224a178b8bac224d12711c7d3bec925db4da9bd1424db872757a1f2e10c9dac40483a69972504e5d69163a9f13c5dc8fc60b1ae7e6d38e19aa6374b3db2d0ed6918fac19a79981df368bb842f5b3e88ed9f88af521c771e336233d35dab81a3ef02b12475047f017ddc597aa597f49dadc9cbb0c72cb50b08c7e3a155f35b7879d64ea48923d6a550399e33a167dc783c7f6ced1b69d4180cca76304febb32c320703294b174da590c3607aa1651f0a88573997ddc59deb816d401a5130517c7a81f1e92cd4e5511bbdc15dd8762a9d285616c3a0b58c0ed867cc74128f52006aeb802f1a07237c66d8c4feef00fd2b1ae400000002a83a469f8f002dc2bf11e8c1b65e2a17b1f398c6806744425e444bffeafc34128320d8a061e226b6d7541ee0e0466327b14b41d7d8142aa18f5b3e734ca8b07cbe0d024a0f648e4db512ee56f4e7ef71d08b1fe3985db75d0beb6e1cc9b8c428971e9c0858baed4e935768dd2201aa82cfbf1692770dc92c7558f23fd46f5d050cd11a1cb476380011fca121f1ce23b9b43e16948af3b3fe4c8a15d4ff935476b23a67f14b0d2ee19a9c48ab89228be2772d63a50fe87fb9ce56dbf43f261b8a0de90b8f7cf375db6016b9b3fa0af14594312df176ea4070eae321a8b22f573c7183f0d3655b15dda99339fd9caa66e9134861e6504c7cc8188c19d1756383ec048b69df7282cd3234e4423e85d15c09d49fc2005e869a4876fec01369c3b0ec0ae6f710797b4e5294a7fdf72c05341b6887da98066400436af27e739c140e3a481df2845cd78df942a2c0fb01429d5b04cd96b18c0b2bbf764b533a6f095edbeaa506a369ea1e6bf58a89075f51344b7db1e4899a12383642a04091aaaef9fcf49281d22d23faca75c7de65be46fb3ae787822af473431d3b611a1aa63051cf37c2a5cae78b26e6e66e8994d62a5b1098bf61306a3418422199a614e4b09269953ec7d6cd85b83e0d4bb6d5370506f505e0e255e3fc86321938647e5638d47a3f711431d0e050a141c2d7a9ff7473515d24fcf7d49df7c62c7a311de1ba74e1eb017f29dec74a0c4b6c1033754c4cec0c45c85e99c62e654d0b6ed8087e811b560000000286384013b18b78f466a96c266b36cd1b3ae84b6746e1cddb521d5248c62eac29c1f7faddfe5094ce8fd5b457d65f0fc18c018bcac96884e2907c390ee2ecbe057336d4c1bd0c6edeba8340910f5ed88b1169283ff98cfecb016af2476595f835806f969e3a7b594d41af1abf47619d929ca35323890888d58febdb488ce9a2a170dcdc0222a6b33d1ce367702a5e6f6e84bb20150993878b7e5023bf51c427b7bf8cfb7b504e5e0258b25c7fe094a79dd4051c2807f480a36bf6d38795526a4f02ee00fa5456eac9e78022d1593bba9d6f4b09c064558cc5d433b81346c7b4f60c731be525a641825de736e0ea4776de5cbbe0c4d8c5b9c080b8160a39f868e702b2a44460fcbf28d7ce0fce6c677113a88b88ec272d3cfac24d33afc47b6fa15259af84fa6543ef673cbd18a44d47420c8c53d7eaf9272dfa62fadd8d118c2055480b6494a67b0346c9fa0b2ba2cba9c0591224a2ed7b399ea35b89111a53059c862afeedd50d8b65c822e69a213b0fc8f2e4188289ebbc5828ff043f0365453989208210c97536a7e9ee865af8872688935b3a9616c8802e3482a4074d0b759e11d052195453ef95945cd0557916d80a9eda70f61ffc653ce99d66caf1cdf7f0688f3bd5adc04f23552b0ef780e6c804f2738b60c3e812cc36c9c02484a47b831c0ff050e1513f54ba97372b1b8b48a278a56d5088ef09d2f24a6c9b95697c1406e4718f3bc71070191eaff6f89ce06c9aa5fedaeb0dabbbd4da46eb22a74ae200000007a5df6c977b2cceed7dc03296768edbe510f0674341d6732cd366a56b13469408ca9a94c1bd50f77074e351ebd8ec6a9485fa5193e1d6574ed673a8ea871fcf9621b0a67f370f56f882c062360c0f4038c1afb1d25dfb554f03b7757a71e61f21ab3baa7c7ac3d30ef2d5328fff37fb6658052001b90bf00000d1b553d8fe988342bee11e6cd1423131c019a9766272069248846381908bbefcf3129f8dbc3cf848ce7fa2e8e7d90c51e03634cf23574ecf51b9efb3b5c244bbbaf8f136c2e917874397a528529aa95cd3076f0ad4fe1751d25e5351dc4fbe28efabae297827a47f902d822b561304db940dfec34db5778e00039f96cb100e76c29cd3b71733f139054e8a39df0d5644285ac93486a2374ecea315f961f59a9c9f6d18fce437e286e11cc988e03ba537773e37fee3bd4a222bcc4361743621916bfd8e982b5957ce2f1dedc3e5fdedea8ae8574ef10e2ab24f53383813f54832fc7b3e79bc7a82c46b4b66ff5aa24086a59041ca4d9db7bff59c37820129d9f3df31007c17d1e48e63b20c1b9ca5106b3baac41a29318810fa8fed1e954c2cd4793db870fed9b17350aeea535ed51ff96fff8c1d7b67518a913efebe3dc3eaac543787be142064eb2fa0559b9f4e570d297ecf1d09bb704595217a5643016e52df4e1c20c0be398ef9832c8343626967d7f81eadd5d81d27a208ed586ef24d69ce7101e4a8384fc5a3cd25716c550c73a4b079d297b507a4ca1d6099346c31b4ade498589f40a04d072e6e9a664e07c9165eb8bb2d1f7568c00c09e4421cf5da5a466684df2e3987f692dff494949916f3bde458fd16f3ef4ddf09563b93b239ea442430d449c27a21215b5dba2930237640088c5d176cb3e5941d5f0a56982b2b05f35503cfc007b730475f28f4241ac28c5f955723f9d92124ab4aab89d198444db0de63fc100df9dab06a3e0591a5096877b581e7304278af7fe8778c13df4f0bc72e0801e663f075db89c119b8639b836a3d6026ec7610ed05fc405228c03e2bec4d60d61b00fee62d95135d4f7f9b06628d14597d9045d70e3d27d9ab7847b71e968b3639f70b5faf58f07543f340c7b5a6a12542209795ae19544a3e32bd966df630815b60", + "type": "ConcordiumZKProofV4" + } + } + ], + "proof": { + "created": "2023-08-28T23:12:15Z", + "proofValue": "", + "type": "ConcordiumWeakLinkingProofV1" + } +} +"#; + let proof: PresentationV1 = + serde_json::from_str(proof_json).unwrap(); + + let public = vec![acc_cred_fixture.verification_material]; + + proof + .verify(&global_context, public.iter()) + .expect("verify"); + } + + /// Test that the verifier can verify previously generated proofs. + #[test] + fn test_stability_identity() { + let global_context = GlobalContext::generate("Test".into()); + + let id_cred_fixture = fixtures::identity_credentials_fixture( + [ + (3.into(), Web3IdAttribute::Numeric(137)), + ( + 1.into(), + Web3IdAttribute::String(AttributeKind::try_new("xkcd".into()).unwrap()), + ), + ( + 2.into(), + Web3IdAttribute::String(AttributeKind::try_new("aa".into()).unwrap()), + ), + ( + 5.into(), + Web3IdAttribute::String(AttributeKind::try_new("testvalue".into()).unwrap()), + ), + ( + 6.into(), + Web3IdAttribute::String(AttributeKind::try_new("bb".into()).unwrap()), + ), + ( + AttributeTag(4).to_string().parse().unwrap(), + Web3IdAttribute::try_from( + chrono::DateTime::parse_from_rfc3339("2023-08-28T23:12:15Z") + .unwrap() + .to_utc(), + ) + .unwrap(), + ), + ] + .into_iter() + .collect(), + &global_context, + ); + + let proof_json = r#" +{ + "type": [ + "VerifiablePresentation", + "ConcordiumVerifiablePresentationV1" + ], + "presentationContext": { + "type": "ConcordiumContextInformationV1", + "given": [ + { + "label": "prop1", + "context": "val1" + } + ], + "requested": [ + { + "label": "prop2", + "context": "val2" + } + ] + }, + "verifiableCredential": [ + { + "type": [ + "VerifiableCredential", + "ConcordiumVerifiableCredentialV1", + "ConcordiumIdBasedCredential" + ], + "credentialSubject": { + "id": "did:ccd:testnet:encidcred:04000500000001a45064854acb7969f49e221ca4e57aaf5d3a7af2a012e667d9f123a96e7fab6f3c0458e59149062a37615fbaff4d412f959d6060a0b98ae6c2d1f08ab3e173f02ceb959c69c30eb55017c74af4179470adb3b3b7b5e382bc8fd3dc173d7bc6b400000002acb968eac3f7f940d80e2cc4dee7ef9256cb1d19fd61a8c2b6d8bf61cdbfb105975b4132cd73f9679567ad8501e698c280e2dc5cac96c5e428adcc4cd9de19b7704df058a5c938c894bf03a94298fc5f741930c575f8f0dd1af64052dcaf4f00000000038b3287ab16051907adab6558c887faae7d41384462d58b569b45ff4549c23325e763ebf98bb7b68090c9c23d11ae057787793917a120aaf73f3caeec5adfc74d43f7ab4d920d89940a8e1cf5e73df89ff49cf95ac38dbc127587259fcdd8baec00000004b5754b446925b3861025a250ab232c5a53da735d5cfb13250db74b37b28ef522242228ab0a3735825be48a37e18bbf7c962776f4a4698f6e30c4ed4d4aca5583296fd05ca86234abe88d347b506073c32d8b87b88f03e9e888aa8a6d76050b2200000005b0e9cd5f084c79d1d7beb52f58182962aebe2fad91740537faa2d409d31dec9af504b7ac8dc15eae6738698d2dc10410930a5f6bc26b8b3b65c82748119af60f17f1e114c62afa62f7783b20a455cd4747d6cda058f381e40185bb9e6618f4e4", + "statement": [ + { + "type": "AttributeInRange", + "attributeTag": "dob", + "lower": 80, + "upper": 1237 + }, + { + "type": "AttributeInSet", + "attributeTag": "sex", + "set": [ + "aa", + "ff", + "zz" + ] + }, + { + "type": "AttributeNotInSet", + "attributeTag": "lastName", + "set": [ + "aa", + "ff", + "zz" + ] + }, + { + "type": "AttributeInRange", + "attributeTag": "countryOfResidence", + "lower": { + "type": "date-time", + "timestamp": "2023-08-27T23:12:15Z" + }, + "upper": { + "type": "date-time", + "timestamp": "2023-08-29T23:12:15Z" + } + }, + { + "type": "AttributeValue", + "attributeTag": "nationality", + "attributeValue": "testvalue" + } + ] + }, + "validFrom": "2020-05-01T00:00:00Z", + "validUntil": "2022-05-31T23:59:59Z", + "issuer": "did:ccd:testnet:idp:0", + "proof": { + "created": "2023-08-28T23:12:15Z", + "proofValue": "0000000000000006010098ad4f48bcd0cf5440853e520858603f16058ee0fc1afdc3efe98abe98771e23c000d19119c28d704a5916929f66f2a30200abb05a0ff79b3b06f912f0ec642268d3a1ad1cdf4f050ab7d55c795aa1ab771f4be29f29134e0d7709566f9b2468805f03009158599821c271588f24e92db7ca30197ec5b0c901efaadd34cca707e56b9aab1a7f14e329816e2acf4d07a7edf1bd6b0400af07a1ba7a22bcb1602114921a48fa966a821354cd0dd63a87ce018caccc50b56f2c9f55a062cdc423657aa5cec8a4c9050100097465737476616c75650602aef4be258f8baca0ee44affd36bc9ca6299cc811ac6cb77d10792ff546153d6a84c0c0e030b131ed29111911794174859966f6ba8cafaf228cb921351c2cbc84358c0fa946ca862f8e30d920e46397bf96b56f50b66ae9c93953dc24de2904640000000000000004a547c8619f3ff2670efbefb21281e459b7cc9766c4f377f78e9f97e2c50569a8dcb155f2a502e936d2cb6ef1a73e92af9916e6353b7127d55bb525cb18074b5ec130463e03a4eda583b05c2d63db40a08ab8bf05f930ec234cc2f788d5f5bfbeab3e4881918ce964ffd55483219edd435ac865286bfd313cd834aabfa8061d2ae173cbe4b59ab2bda78faa4c2c937afba80d7fba0822579ac0ef6915f4820f968a74f00ff5ab74e90b0a7bcb2b92093a5e94a54aea1d48ffd1e5bb3fb48069bc9dda27a50094cba9bfcf801e64dbe683c0b71926a7185436e942f8c8077566b3000000050000000115726915418468b26d6e74190b76915057b8a4241cce9c45ce7fb9eebadb10380d3c58996247f9589b75d980c22cb52bba4474635acdd36ca9608b03a4fa17071d2475f082a64d60185b4e66be4c25d82abc0da2539127a03835c23c92cbae27000000023c9d71ca25a598cb0ea22848c766906ff6ae52cd30b32e0aea57905edf89c7a06c424eb85df08da398507bf2a2d60873a927d42479a08e902c247555b5a54c266c4447fa40a7a8c1f693e71a628fe46d844ce6a79b9a76ddf5a3c682db641dd900000003687dde67f4bf5a0a89cf32468d344b296f8f243d6fa5946f96c04c2e9aa506b14330a6083226b65b55c3cea3985ab39b60b8d0db1bd812fb2ada6e14288da2fd07db10ace62993c934944bd63b11a0b1c098059905a6777970d04365c085d1da0000000409dcbd1240c0fc6eaa35254ccc5cb724442bbf38c7c1d37912b1fcccad403f2e2a68dc38582ba48dadae94def9b6bcca09cc8a76d1fe7d6a76e6891dfba34ba55e5cd0bb1bc71976f9f85768b82bdfe47664c6e2f6e87c4bc836c898b4fcfe780000000538f72551c6300c32bd3401901113c1a0de21b6c411f7b23dcb0978021c06043e27a762ac3f79325a7da5c92520bf30930a15b4f8e1f8e0345a8920944def95ab2244e704856d61cc42dc2b7765939b408f73150f0bba0069d43a388dc4b9af4c5adb834750b09315c12cc625f1813f9417f72f6d367f47585584c45d6471aa6d0000000c000438badd11174560b10965889ef2a5e06c7e10a049b1ca950b5641a7a6fa0d2c2dee4aa278a8d7dcba3625824033c4bae0c8336a73afe374f1366b8acec0b22602560a5a195d54241d9307176e66834046001a5d73649e7fc557829d89d897855701010102338aa101037d164c46e745fe608dd7bedb3dcc66eb8b6f1fdd0b6843e7260c3200198b0abade3d91b3a0dd7e23cad15f1e671037ef0a600b882f6b832defe318db20dcf6376d42d73fc9db0bfd4fc2c63110951792167ddddc89500980551f9bb70049f2851c9793009b5eb009d32a102358596a79fa951176c475e1cce3ab454c4064269569c392c56309f2ca90b77af6254209dab87841ed35042a44270ae946cf00496a71478e437a843beb8e522295c9b3479b4a28b77dd624268693eb9538d2ae5105514841b593230dfb8c64936082a79c76e0df7392049895001ccc0f81739d002e3175e30fe6f0eb0ef6ebcba037b75dcace321379a487be6db7ea03de3fa5a057cd6a8a6c24a45847ad6941fc7e3c347a39260427c7f413b95821064aff6e1a01023cbcc2d00f1f28d79687747b0e4fb70b22319e39fefb76a90ef22e021f96ff55000000000000000502803596b4ba5ea05b1fea2b78e292f935d621453cffcd207e10f3072b2813ca3e963cebf05b19cd82da4bd5aad1dcc7fda1492d7ffc8f532bc4b37e9bf4753b7ae6b8f08e05a851052fc6ac7617ce68293678747d11f9a508bab6f7a60edde9c4b092dd34e11fd7dd65823bd9a28f6169fba00b9b82cb9a8e149f43421c17a98aa5d382d05056a988c0956d330ff55f9caf87e8f23f45b9c3fd46fd17de35b9288ed1fde6fa48135fd76e331da22d2ebeaaa90098c9fb5744358a77cbf3a3043f51203db2a0423969266759114978722c077c55d02bffa1f76c8fcb85395cab013c3ba44446b18d561753335da9236fac7cb618432492eb7d992d699cc240456120da4c2712b9a44b640af2033485fd918ae817e81cf0e26057c66371f1b2b7b0000000079580daa7ed6bfd9662c47231c3094a8f96c2c25e5c0eba5336343eca68747f7e9918ac172c2211a43438fd47b136bd628ff969687ca71147490780b44914c168c007ed619431b041287d549fb96d51e6b41e7c28eadcfe553d53b870acac4594a6010d523918c8862810fc6c8cde78e3e5965735c1d00f0ef9b5cc4902ae52ec62010d0f98b9d07c78a3ae3eb1676f56b07a0ab8716ebea736ceffd92045eed660158cc24864a23b5b3e0cac55c68051dffaefcdaca795ff97e093d901173faeadc00b2053ae59cbb36864862c30bbcfa5032e1516590e380c2b5073cd1bc3e76ae8f8dc4edc892ebbe15805271f98c0ac22ef9e0daecde89e16bbf0f5e0206c32a54ed875a3de1e86d560f615c8c6cca5fe74d2c096003486caddbd6185b859b2502a5d05bd9ac863faa0a2ca54eabe1fab68df7086d78a486f688d4419bac0ca6b29288d9ee95df17e27d269bcff0fa521802f55a178e6189c4fc4e0c9aacc7641935f9750f7af0aac001a0efb0e2436afe8d40637b5f1b40858878bfa5ae8a017b3217a716ebdf27a1723a93865fe088c834cff4c2e27ebcac37e3d23b7bfc4a96f4d0d3e1ebf1f13ad4a81f7c73482802590d0c0dea55147cc163fbd143db10aeb8505a2d9ee098a6c47bc41fe032d729becf1b7131249773a9efd811e9caebd1d72658785b32470eab5708287532a4a4a4a91073b5b77e693c393ede85f4d23c77d4e7accf7460976f7ed911d9090748eb9498c76bb8ba173367a5963a938d8c2173d20db10bcc7c452f1f19f93b31a02b6f24794413dc183ea2bf157388d22397beb12e6e4a626ab32e6740a0c3d9bcb49579c27a479d5cf6f2d98b1227c690d734161166bbf9caff311f2c504a4dda5e53b70b8738b18dfa4fbb5ecd0b074885db065516a7a19b78c63dc1f5a72a8b843b5ea3c1b49feaccfa55216a81dd028a44797f262a0b42d1e617490f16f575f44991cd02f1a679d6695a0137b02423d96ee162d768f0ef1c74980e5728bfcda5fa69d451e3a64dea119b16aab039035240c33b7dec4981aa53e914f67ac932328b31f3fc4d0aac1c19a4da4dab1b525a63008d0e40b86076a1b7e9f0f219955c76798ae8d5131eee35e9900c5cdc8b58badd7022044521d7ad239a91bb2ae1a02fc61472f7d3629d14070641a1e8106424aff358bd337af5576ce1a48243e21c3b73051a87b7a914ef68645f82f5c2b1a8af8def5d639feea0fa02f625f9397619ff9538ec5ca1238e7f26451a7036e9319fbe3baadcefe0f09d32a37cbc7644b92ab9e984304fe7ee22886d8e7331b923ccea38b31cd4c5b6e21ea7b13f93a74d2e4e5c5abe8f48efdc901055541e152730c07ed5c80c97a3538602df6b37cbc864618781c1728ca3d13af97b33e922b8722a17d7b3397dbd604ea26446aee03488924d55a8dca65731db96bbd00000002a753709610f96d22afb715d26c8586d8971f9201ba327d6eb4a0ff5ee0943f81f7eef7901d85fdd59b18d825b64accae87447036ee703852251d2b9d0d9add516ea1c1ac8f68168e881c4a6ebfb1f9c1c7e7098b7aabf9e0a2efa2423186f7f4898dfca0ef6f07fdbd180a2a164d21b18b0424d7f7e9c93d326e3ab308062bf644184b0e76e3782b27de5b4b971b127a904946ecd4b94a21158d8ffc0f040b6dde6f044dc084ce27a016a1677099f3b335237a19623edc4940193bf706197b2832e1f8a77215de4dc73fab8cf1e1e090f57e5db737174759e3434b4da5feeefa41be4bf511821326cb664dcb6705c926e135c0de63e86b3c0fb1db02a47ecda00487cbd29bfc97194ed8868ed4e458c7b2bf8ab6f04efee532502cf588c4f26b9b2830baa635c56857be5fd6803fd35d508881bd7cf3b5872ff84640384e2576bd93d4d86fdafcba2df3f29036491573031ede2ddb09dd092ad890a68f07876aeea30b4541acc1c039323dfeb5a8bb81396cee8e41a591c6c559f24181b3f1d9a1cf386dbbc74e601480099930464fff2f820ffefe9c1754ea7220ab4fb95a73bd217f7440d26d803077031d039a09f366221c1d60f761f70bcfe592e099e41b4a5bd088cd1ece3af477e1d13f03c1459ad22b42f3479f12d7229de52d7f4ef95c689a33ade597a8902964e244e6cca0d1f94de905f9fccf95b774ed2b8c2a36f061f3a8da53b11d71d9855c79face7dac770caf93e5e9d7fbd6b2907f994bf8e6000000028c27c3a9d06054e718d61e0c97597c3e2aa2fa7b372b61e37fd02004a58cd9a9db0e4aa75995de479dc528369aae7850971c7a68b793ac91d3f8e31fe12200a63cd651d0fef437981c041f1417c0a7b35ffc2725f19ea6f47b2db483ad3c28b1ac997b445bb2fb55c276fb800e331cd8a406efc9074101a3b477df4d1fa187a27a07e58e3d0a5fff80d9c33f5b0d9f0685a41e8378e99fe37e7376290d971afcd3548fd6e7ab783c338558a58c7f4b17b3f2f19892b8fab86f297ad4fc25ba8107bdfd243161d90f6439adafe37e70edf6d318489571acc3761f12ca134dd42713dcd3d4e4bf11bdbabb6771a1d11f406969ed4f1b3dea7d32c292ffa07a302a02b387e119ec10c4a8963ee52710d75c21710881bae7fb5a8595fd43a9156419f8080891e50139bd4af14f1ba25ebe0152b5e83d115be493372e147742d8bfe3a8269e8ecd27ec055a11055d5405192cda8c8db528f06b120fc2e3f470898974118b864ba4ea9442144f894abfdc952071f586c663ee9c7daaa100295213bf22a96b9c2562d7f4bdbc878e59a5dff96d1793ff7a7819b528ee718513bcd5d6f44cb1ff1433d4a6a72d95a3e9c2f9bdf179fc0d999a689ba5f10717dd812bef9cab61b118dfc80d1f16fed604130e256bc3cbbd4a3f9e7aa656e685d9f801845f043178b7aad99f9214e790c31939f6b85e3d876351377a3d57b3c85d84876a93fd039a4ff13d73c3564d8cd9c4310b4e7bbc27f907b10b6f95c09c853e6edbb84300000007ac2df00a78778a0e2e4ab221df2686305b7c4f369c9393d83d2398442fd650d3d49a9171e64b20c4b341e8c5f0153bab845202926b803c5eef4d10937696d1f2917a5c1ddfa86860b780c7e9cdca49bc0c07973d1a2a77fa6688176e3c88c933afc37a04d49778bb6c3eac0ef42a67cde86dbee2825f12f848ed2383af2da472dde4fc29b9ed9267480363f587f5babcb86c0965845495f3b5cda6f3cd5d5784a3123b89a74b7732b51dfbbfb28cd9ea0f635c4920711cc8bc9512154ef679ddac1730212ea8cc4718c1085583c5c40b964f1aa0689595a8b6d1869f23a8d857c68251863f5c3e57c62f73d40090b437a337db8b01b5b258f5217fb81b634edea1f942224a7d6bb9124272a99f038980976a8df52094c62fe7dc6a07cbe2e67aa413ddead30ad92e54c0cdc1b915d2bedfef9660fa69b513736ca221fa4bd6ce054c90ebd9ddae7cce9f0c02630cfe7f88f8fec518d60cd79fd9f9acd653b8cb8707dc463eb942faf56308d8afd89a5d1f690a43203cb72049183431d0e291888a344544ea7d38ae1db3ee49d6d9790e1baa80abbe54db280593b9a7f632a0bd9298cc93f298b8b0a7b91eaddc1856e2ad00c721bb2099d944fa0a847513fa51bfca7822fb8163794fa28e8bc9712dc2f2cd5b6f53c66dd8a536f869447dbf39b4accb28dcec7de58ad83819bcc4ab0b966b165bb8e0bfcb30a6280e588cac873e9b3919a8bb8c3418f4cecfc2e14e60b47259143898aeb7380ef76d93c8e5102ffdedb793e49f23cba70e9ec04475394fffea2d0c6273730a101314589fc9c7ab713604443a0e8c7816d10d6581fa30fdb1552c61025ae3e85d46e7dd38e90d1a6d8d4921c806d9dfc84a7a0497335c8b9e4be2db89512fd2ca332ebb66ec302da2ab68f2a40cf3b957720348b7ac5414b9c7c3bf05c88fe606a31b69b5d6e606a0d8dce4c0952d047fec38e28ef722bfae923ca9104f1742f1df96ef9650543e19d25a3b6e8f93e0ac26841120c46cd416e9fa4a111b1ad3b8a171033d26a901", + "type": "ConcordiumZKProofV4" + } + } + ], + "proof": { + "created": "2023-08-28T23:12:15Z", + "proofValue": "", + "type": "ConcordiumWeakLinkingProofV1" + } +} +"#; + let proof: PresentationV1 = + serde_json::from_str(proof_json).unwrap(); + + let public = vec![id_cred_fixture.verification_material]; + + proof + .verify(&global_context, public.iter()) + .expect("verify"); + } } From 783e2c5fc75321a066d3cc49ce2ab2edf7c096ff Mon Sep 17 00:00:00 2001 From: Allan Rasmussen Date: Tue, 25 Nov 2025 17:01:21 +0100 Subject: [PATCH 14/20] fix --- .../concordium_base/src/random_oracle/mod.rs | 115 ++++++++++++++++-- .../concordium_base/src/web3id/v1/proofs.rs | 76 +++++++++++- 2 files changed, 180 insertions(+), 11 deletions(-) diff --git a/rust-src/concordium_base/src/random_oracle/mod.rs b/rust-src/concordium_base/src/random_oracle/mod.rs index c4e44d6ac..5064af924 100644 --- a/rust-src/concordium_base/src/random_oracle/mod.rs +++ b/rust-src/concordium_base/src/random_oracle/mod.rs @@ -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}; @@ -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, Default)] // todo ar remove default pub struct TranscriptProtocolV1(Sha3_256); /// Type of challenges computed from the random oracle. @@ -557,11 +558,111 @@ 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)] +#[derive(Debug, Clone)] +pub struct TranscriptProtocolTracer

{ + pub inner: P, + pub lines: std::cell::RefCell>, +} + +#[cfg(test)] +impl

TranscriptProtocolTracer

{ + pub fn new(inner: P) -> Self { + Self { + inner, + lines: std::cell::RefCell::new(vec![]), + } + } +} + +#[cfg(test)] +impl TranscriptProtocol for TranscriptProtocolTracer

{ + fn append_label(&mut self, label: impl AsRef<[u8]>) { + self.inner.append_label(label.as_ref()); + self.lines + .borrow_mut() + .push(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, message); + self.lines + .borrow_mut() + .last_mut() + .expect("last line") + .extend(format!(", {} bytes", to_bytes(message).len()).chars()); + } + + fn append_messages<'a, T: Serial + 'a, B: IntoIterator>( + &mut self, + label: impl AsRef<[u8]>, + messages: B, + ) where + B::IntoIter: ExactSizeIterator, + { + let messages: Vec<_> = messages.into_iter().collect(); + self.inner.append_messages(label, &messages); + self.lines + .borrow_mut() + .last_mut() + .expect("last line") + .extend( + format!( + ", {} items, {} bytes total", + messages.len(), + messages + .iter() + .map(|msg| to_bytes(msg).len()) + .sum::() + ) + .chars(), + ); + } + + fn append_final_prover_message(&mut self, label: impl AsRef<[u8]>, message: &impl Serial) { + self.inner.append_final_prover_message(label, message); + self.lines + .borrow_mut() + .last_mut() + .expect("last line") + .extend(format!(", final prover message, {} bytes", to_bytes(message).len()).chars()); + } + + fn append_each_message>( + &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.inner + .append_each_message(label, messages, |inner, item| { + let mut tracer = TranscriptProtocolTracer::new(std::mem::take(inner)); + append_item(&mut tracer, item); + *inner = std::mem::take(&mut tracer.inner); + }); + } + + fn extract_challenge_scalar(&mut self, label: impl AsRef<[u8]>) -> C::Scalar { + let val = self.inner.extract_challenge_scalar::(label); + self.lines + .borrow_mut() + .last_mut() + .expect("last line") + .extend(", extract scalar challenge".chars()); + val + } + + fn extract_raw_challenge(&self) -> Challenge { + let val = self.inner.extract_raw_challenge(); + self.lines + .borrow_mut() + .push("".to_string()); + val } } @@ -821,10 +922,10 @@ mod tests { /// by [`::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::("Scalar1"), + &ro.extract_challenge_scalar::("Scalar1"), )); assert_eq!( scalar_hex, diff --git a/rust-src/concordium_base/src/web3id/v1/proofs.rs b/rust-src/concordium_base/src/web3id/v1/proofs.rs index 3bc4a89c2..6c35efefc 100644 --- a/rust-src/concordium_base/src/web3id/v1/proofs.rs +++ b/rust-src/concordium_base/src/web3id/v1/proofs.rs @@ -72,7 +72,7 @@ impl, AttributeType: Attribute> RequestV1 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); + self.prove_with_transcript(global_context, private_inputs, csprng, &mut transcript, now) + } + + fn prove_with_transcript<'a, P: Pairing>( + self, + global_context: &GlobalContext, + private_inputs: impl ExactSizeIterator< + Item = CredentialProofPrivateInputs<'a, P, C, AttributeType>, + >, + csprng: &mut (impl Rng + CryptoRng), + transcript: &mut (impl TranscriptProtocol + Clone), + now: chrono::DateTime, + ) -> Result, ProveError> + where + AttributeType: 'a, + { + let mut verifiable_credentials = Vec::with_capacity(private_inputs.len()); + append_context(transcript, &self.context); transcript.append_message("GlobalContext", &global_context); if self.subject_claims.len() != private_inputs.len() { @@ -539,7 +555,7 @@ impl> RequestV1 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", @@ -703,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; @@ -1795,4 +1812,55 @@ pub mod tests { .verify(&global_context, public.iter()) .expect("verify"); } + + /// Test prove and verify presentation for identity credentials. + #[test] + fn test_transcript_trace_identity() { + 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:: { + context: challenge, + subject_claims, + }; + + let mut transcript = TranscriptProtocolTracer::new(TranscriptProtocolV1::with_domain( + "ConcordiumVerifiableCredentialV1", + )); + let mut csprng = rand::thread_rng(); + let proof = request + .clone() + .prove_with_transcript( + &global_context, + [id_cred_fixture.private_inputs()].into_iter(), + &mut csprng, + &mut transcript, + chrono::Utc::now(), + ) + .expect("prove"); + + let public = vec![id_cred_fixture.verification_material]; + assert_eq!( + proof + .verify(&global_context, public.iter()) + .expect("verify"), + request, + "verify request" + ); + + for line in transcript.lines.borrow().iter() { + println!("{}", line); + } + } } From 69e201ecc2d6b2bbacb9591f52333be82e455e37 Mon Sep 17 00:00:00 2001 From: Allan Rasmussen Date: Tue, 25 Nov 2025 17:08:23 +0100 Subject: [PATCH 15/20] change label --- .../src/id/identity_attributes_credentials.rs | 18 ++++++++++-------- ...ity_attributes_credentials_stable_proof.hex | 2 +- rust-src/concordium_base/src/web3id/v1.rs | 2 +- .../concordium_base/src/web3id/v1/anchor.rs | 6 +++--- .../concordium_base/src/web3id/v1/proofs.rs | 2 +- 5 files changed, 16 insertions(+), 14 deletions(-) diff --git a/rust-src/concordium_base/src/id/identity_attributes_credentials.rs b/rust-src/concordium_base/src/id/identity_attributes_credentials.rs index 737f6f2d6..bdbd7ab0a 100644 --- a/rust-src/concordium_base/src/id/identity_attributes_credentials.rs +++ b/rust-src/concordium_base/src/id/identity_attributes_credentials.rs @@ -181,9 +181,9 @@ pub fn prove_identity_attributes< // IdentityAttributesCommitmentValues struct. // This should make the proof non-reusable. // We should add the genesis hash also at some point - transcript.append_label(b"IdentityAttributesCredentials"); - transcript.append_message(b"identity_attribute_values", &id_attribute_values); - transcript.append_message(b"global_context", &global_context); + transcript.append_label("IdentityAttributesCredentials"); + transcript.append_message("IdentityAttributeValues", &id_attribute_values); + transcript.append_message("GlobalContext", &global_context); let proof = sigma_protocols::common::prove(transcript, &prover, witness, csprng) .context("cannot produce zero knowledge proof")?; @@ -413,9 +413,9 @@ pub fn verify_identity_attributes< } // Compute the challenge prefix by hashing the values. - transcript.append_label(b"IdentityAttributesCredentials"); - transcript.append_message(b"identity_attribute_values", &id_attr_info.values); - transcript.append_message(b"global_context", &global_context); + transcript.append_label("IdentityAttributesCredentials"); + transcript.append_message("IdentityAttributeValues", &id_attr_info.values); + transcript.append_message("GlobalContext", &global_context); let verifier_sig = signature_knowledge_verifier( &global_context.on_chain_commitment_key, @@ -1208,19 +1208,21 @@ mod test { pub fn test_identity_attributes_stable() { let id_object_fixture = identity_object_fixture(); - // Comment out to regenerate proof. We can do that as long as we have not released yet - + // // Comment out to regenerate proof. We can do that as long as we have not released yet + // // let mut attributes_handling = BTreeMap::new(); // attributes_handling.insert(TAG_0, IdentityAttributeHandling::Commit); // attributes_handling.insert(TAG_1, IdentityAttributeHandling::Reveal); // // let mut transcript = RandomOracle::empty(); + // let mut csprng = rand::thread_rng(); // let (id_attr_info, rand) = prove_identity_attributes( // &id_object_fixture.global_ctx, // ip_context(&id_object_fixture), // &id_object_fixture.id_object, // &id_object_fixture.id_use_data, // &attributes_handling, + // &mut csprng, // &mut transcript, // ) // .expect("prove"); diff --git a/rust-src/concordium_base/src/id/identity_attributes_credentials_stable_proof.hex b/rust-src/concordium_base/src/id/identity_attributes_credentials_stable_proof.hex index 6aa7533e7..164e707ee 100644 --- a/rust-src/concordium_base/src/id/identity_attributes_credentials_stable_proof.hex +++ b/rust-src/concordium_base/src/id/identity_attributes_credentials_stable_proof.hex @@ -1 +1 @@ -0000000004000500000001b01ae8c302f8fe2253715b937992048f253b6a9eb0390b2e5d192e233f44eb0a8a5c62dc6205ce90c390eefcdd8505878df958fcc143ef627d5621cf1b17e74b32696d5b13fa2db5b82238549a631ad3809c0e36bc6d99ab4f149ec89cd28523000000028b0895877e21125c4a9e261a0783e63354f45db56d1846c03151ec1620eb3f2a1648805e5bdf39a2d50f6556399a0dabb47521eb0c79e4e940eac749e8bcbd662c054b04555a3b6d0ab53c7c455ffd292342260a4616b70f2d3651082fb4e97400000003b0f6bb28319f6ec761a93cb824953d26b87b8240c79fd0de229788f2662010e8aef7e9656c0cd968b207625d304b527ba324f4b42b4927ae4081ae3968956dc29c40c18b77b85c07ebc665855a28a95bdf0cfa04056958f95eb5a528fc32e3e6000000048691182c3dc558f192d919f919926634f7bf8bed92b777913d1b7221842026cc0eb7b3e38ab4bf22549a451590544492b8ceabe77805865e3c73453f37b9cb0198bbbcb8dee81f81dec089bd7f31f178d194a892144e690958ae7cb44ccbf06800000005a84b6e4b90bdc5db3f05650e1092baa668842e890c151ddb70e3375246d205607eeb1f13d4378532f0ede701fc92388f8929bab30624f233435ad05c964ea26d85abe1e3181fca0bf3435bf45e0da740754182cc41d075af33bf5c5c5826972200030000a5b463b000c4d0353f403b653842839e681d3710080bca981e5b0b5569705fcf09071dd08eb306996cf2aa1d96004ebd0201057465737431050207e60507e4058182e48f77712c0c5847d615b1b7efffeb427a271054f0455a39607feb3f11d99411cb85d728e6b5244fe7278cdc045c8919e085134427588965c9d558ce2492ffcb9fca8c90ef5b30f92f988d44fbae1129070de64e6c1febc4aeae51bdc43b0000000000000004ae75a616c313063b54c6c684569b060dddf6e1c2177a01f45dd287424ca048f657e56bd059bfcc1d6b20be7e5a1d0372a32de2bd1507249ba5cb556f71963f91df3232ea597a7325017b50e3a7d043829e6c0e4779d48f2f669368b09e341ac48eaa41605b57ca2f88be9629b303f9ed447ae64c51a5f0a16d248f127a94b319714939e2b61b11bbb53509385a308163a177c94454d219d8ccd516bca62e2f7ab9bdb0e22cfb0367731c16ed5df46221767c1fa9c60b14208d779f2233ab55b9ca04f3184229dc467669c248c4a79b906571285748d69d5c9f486923e6f0d9d5000000050000000166952f27b344256ba6b07976495fef937dd664d3d745c9cd5a7f8ea7798c3eb9640036afab91548bcd4d55df77778b24d710e9b3e3036d94a231b87bd790a4296d48f736e2f7d7a9ae6f00cc6eb32a5bca4594db95b976449f6b7a12e7158d54000000020d30191155cff3ea43ae656f51fc86f41b530cf1461a81377f04077844646a1651f08afe97dfff786a90879741d7f47fbb40bbfc1d5ed14546c57d735f6a03485a9c7a741fa34a42666a69cf5059e8f2a4a24783b411a5df9c9bf549cbe5b9cc00000003248cca96b7cfd290afdff3c4b7328726e8ba2434b380bb0314a7e9caba93b0e56c2340afd81a175b73fffc8191cc1f7039ad74ce7383e359d60833de915557ab0c3f423cc174cf6e1564679275738b6d68bd3999b5dcdc5b8c15675e5b2fd2d900000004722e3f3522fbae1f41f5e6ada345d974e97765b70d5ec08584008212a5df40eb20c730d6859e54217a406a194a5493e1d875e3ae0d5e8143d30ab3460a889ae657ecc6bee2e72b22a70013121e393656a1a551337da0e12191abcf07522ae86700000005416346b607529a98396a392ceae1ab7c82657d27e544109ee6797bfa419934a5601889fd8ea3845fbfddc9bb0d3df9abfe3d13cbadb5c3f50e2c9432722258fd64477163d86305fb341248019749839872fba4059a7f929e5acc10da9b28ab3121104776ffdaede7a83811e794a2354ccfb2fd2303994615983c1f5e07295e3f00000009004ce19f4e7306e88a13fd74a6aebb8153e67e5a788d15583fdb42a3b087186bc930007fcbdc34ad3afd58b9a211bebf952cf7e12fb04f2fcd2f1ed97b38d22267027165c3ccb796fb403a4530dfadbe613008c539fb0a9dd7ace18f239fb46c35de01010102085c112a64617c2153dc651e42a53abdd08dc18d14aa5164cfef144499040c96005d61a86a3209a4bed5b274687a02d0c7e1e657c64f2ed2be411fc58078220e3f076d2f3464c2ff45555e36f179e21937d4eba7e94cb4bb2c7a4739855ad73ab90102112f8b8e76fa5d4ad3e7e2f22f8e15a85ae9b53cecf809e565c690600f34ddce \ No newline at end of file +0000000004000500000001a9b52b38e71f495c570ab67f0c62c0a6e6b9c75a0cc94c39ffe1beaaec7a13381d40521a2fa22332f0808defffb38bc0aca6699c7b03859f26271112cb141942165bd2d2dcf0754ade475ece031ce47799f9d04ea1d82af780bd94583eef047500000002af2dac80b1c94d5b6b069e10c90bef45f33aabbe9ba69d06676a25d71f10813e3610ce816d4eac46a0540d7ca0dc6eb7b41f8aeb74f605232708b8d41f8bd47a960de95945d37728efbd6fe6d4ae3907890727944a9a322fd00907c8b8957068000000038eef6229c3f6bae1c448142f39f1f6ff94cf68941c4f8bbdcf0f4ecb77f17632a2f29476f38abd98a4820b83afe3c755ad8759b52bb50daa5296a203fb8e3225967fe648dac8ebd8e3115f1487cc8d9d5478c1f6421c62e865d1416eda8b4b480000000493f8bb6032f7a323890d079e3c43e29544c3a61302a82622201e4f142efba13f5686726c393a125a3c4b8d4530df57a088262b5a71bad237bb15289f240bba32b5bcb1d329cc438fe4132d3df53d6ba94effcf3fe07201995a984f77e07be33100000005a42734679a9c66e765e3128880394c3ecb6b5332c1389d81948d9252b34f26a73770f30b604db44f854fc64d24e5c50786efa20b470ac35b2580b39cf41e9c95ad45ab094edc0f1de036c39888c012afc577c2dda40f5fac368cc9a83dc9ea4b00030000a58fb0b79d280833eaa62fb0d5bb2cd84c185533037957278a84e064961c7f956405a28704c34192d7691ad0dbffd9310201057465737431050207e60507e405b0a13099ab416f2caf5e0565cd2591a849dfa06afd6c0758b5e26eeb84b1980f25a1510715cfb6644ad8604f884d7200982daf1592b340bc4787bcc29e5dadd757aa68c39412822b5870b8762cd2d537d9b7632823d0923f8c07494ae2f3962e0000000000000004a0f0b132121d78ac5be2c5e569750ce71f38b8b9259455ab8a15bf091508fcae134bfb7201eede64308d1285f416462982b6d011542e6c5fe6725e8dd1c9b2f86b38f169f541da777b41e7197cf6a3030b5a73da58ffaaab4ccc6e384201aa75b28f44fd98bc9cb1991d0c64bad261898c5fa8f9a0030ab7b7d69db962902dd1e7233da7760e41a33cc086898ae95a8cb6111c6eef83db3e720ccf5484c145ac3e55b79f8b01d2505bac5a9e38975ca52cf094f1bb3ec0762c4b2507c9b63c4f0991db7e83b84db1607fb58893df77d3785b3318cb49a62b07439cd2740f22d800000005000000010e1a76a2b97bba5760adc8416c8a4c09891a1750e8d12210279669d55345085910a8caa872c4a0ce309a6fb2f1dce92b7cb8a8f0951b748ad725f7793feddcd95f444f7078959ad3e52bad9c0feecfca4a3c5298586d8f6d508f0e7f4efc7d450000000234a2d50855aa5c3af4b58ce8d2cd7d66023565dd57b4ed0f9a1103d979959be3721755ef0cae8d37919e194f14a202e4c984b42e45c5153b3aa3bc80ae47710671e8441d0c36f2ba80435a6660aac9730123bde7918afb8e4f55cd452f63480e00000003169e99ba93584555dace2bf37df0d2c962cbc28658c85d72773a9c6edad45fb76ccb506e3af5b739aa49a301d7917d35a772f2277461a22e9ca6b4cce0627798582c15b201964f5634590452a9c90398f9b91a3cb7d7d60a9a832b69e209cb0f000000045a1c800795ded51088d5d9742dd8d28f14d875ed5722e010e98aef9c236d4fca24492453abda5885a47679fcd0db48037732f488e64d9e457115dbcc9a7392ef645b377dfbee2475af60d3dffa361e76885c92f278eff2bede0a2d5d1799384a0000000520cd03f963b61005ab753f6c59ec309c1fb4d2be3fba95176120f0528643faea05694c6b5d22d3b923d27526fd6a5bdb9165a97ac9a754430f62c4105fe280fa294d78558a1856d6cf1683c190755b16c05f210dcff42480dfc4fbd68c1864d40bd138749cb9811e841321a7d15f3227a3232e631afa1e9c648122ab4afea990000000090007414977cfbdf5e5e7e617e1b85b45988d27f43f621211e2469b80df5c7ee58060c5080b03e30ab25a1f7e28f02e168137bff0a262e72ca23babd88b080446840202a3c0f484cb24096aafb529305f9d68410c39b651bc95e03a88debf71f56ace0101010254f1b724ebdf88f730f10b1c98124b8b63215e5ebebfd357f803d7c28024e4870073d4a67d3e6142713742764f63169bf517b90f9f23511e65b3d736b8650013bd45ab07abf4ff8584b6c0a4b52eb834c828352a36db18b7bba0759f3a41fdcb25010231a865f4998698b8c25278af53b1d20f09df01a0951fb0e8b796a232f2c8cc3d \ No newline at end of file diff --git a/rust-src/concordium_base/src/web3id/v1.rs b/rust-src/concordium_base/src/web3id/v1.rs index e15a97ab2..169571556 100644 --- a/rust-src/concordium_base/src/web3id/v1.rs +++ b/rust-src/concordium_base/src/web3id/v1.rs @@ -2389,7 +2389,7 @@ mod tests { "issuer": "did:ccd:testnet:idp:0", "proof": { "created": "2023-08-28T23:12:15Z", - "proofValue": "0000000000000006010098ad4f48bcd0cf5440853e520858603f16058ee0fc1afdc3efe98abe98771e23c000d19119c28d704a5916929f66f2a30200abb05a0ff79b3b06f912f0ec642268d3a1ad1cdf4f050ab7d55c795aa1ab771f4be29f29134e0d7709566f9b2468805f03009158599821c271588f24e92db7ca30197ec5b0c901efaadd34cca707e56b9aab1a7f14e329816e2acf4d07a7edf1bd6b0400af07a1ba7a22bcb1602114921a48fa966a821354cd0dd63a87ce018caccc50b56f2c9f55a062cdc423657aa5cec8a4c9050100097465737476616c75650602aef4be258f8baca0ee44affd36bc9ca6299cc811ac6cb77d10792ff546153d6a84c0c0e030b131ed29111911794174859966f6ba8cafaf228cb921351c2cbc84358c0fa946ca862f8e30d920e46397bf96b56f50b66ae9c93953dc24de2904640000000000000004a547c8619f3ff2670efbefb21281e459b7cc9766c4f377f78e9f97e2c50569a8dcb155f2a502e936d2cb6ef1a73e92af9916e6353b7127d55bb525cb18074b5ec130463e03a4eda583b05c2d63db40a08ab8bf05f930ec234cc2f788d5f5bfbeab3e4881918ce964ffd55483219edd435ac865286bfd313cd834aabfa8061d2ae173cbe4b59ab2bda78faa4c2c937afba80d7fba0822579ac0ef6915f4820f968a74f00ff5ab74e90b0a7bcb2b92093a5e94a54aea1d48ffd1e5bb3fb48069bc9dda27a50094cba9bfcf801e64dbe683c0b71926a7185436e942f8c8077566b3000000050000000115726915418468b26d6e74190b76915057b8a4241cce9c45ce7fb9eebadb10380d3c58996247f9589b75d980c22cb52bba4474635acdd36ca9608b03a4fa17071d2475f082a64d60185b4e66be4c25d82abc0da2539127a03835c23c92cbae27000000023c9d71ca25a598cb0ea22848c766906ff6ae52cd30b32e0aea57905edf89c7a06c424eb85df08da398507bf2a2d60873a927d42479a08e902c247555b5a54c266c4447fa40a7a8c1f693e71a628fe46d844ce6a79b9a76ddf5a3c682db641dd900000003687dde67f4bf5a0a89cf32468d344b296f8f243d6fa5946f96c04c2e9aa506b14330a6083226b65b55c3cea3985ab39b60b8d0db1bd812fb2ada6e14288da2fd07db10ace62993c934944bd63b11a0b1c098059905a6777970d04365c085d1da0000000409dcbd1240c0fc6eaa35254ccc5cb724442bbf38c7c1d37912b1fcccad403f2e2a68dc38582ba48dadae94def9b6bcca09cc8a76d1fe7d6a76e6891dfba34ba55e5cd0bb1bc71976f9f85768b82bdfe47664c6e2f6e87c4bc836c898b4fcfe780000000538f72551c6300c32bd3401901113c1a0de21b6c411f7b23dcb0978021c06043e27a762ac3f79325a7da5c92520bf30930a15b4f8e1f8e0345a8920944def95ab2244e704856d61cc42dc2b7765939b408f73150f0bba0069d43a388dc4b9af4c5adb834750b09315c12cc625f1813f9417f72f6d367f47585584c45d6471aa6d0000000c000438badd11174560b10965889ef2a5e06c7e10a049b1ca950b5641a7a6fa0d2c2dee4aa278a8d7dcba3625824033c4bae0c8336a73afe374f1366b8acec0b22602560a5a195d54241d9307176e66834046001a5d73649e7fc557829d89d897855701010102338aa101037d164c46e745fe608dd7bedb3dcc66eb8b6f1fdd0b6843e7260c3200198b0abade3d91b3a0dd7e23cad15f1e671037ef0a600b882f6b832defe318db20dcf6376d42d73fc9db0bfd4fc2c63110951792167ddddc89500980551f9bb70049f2851c9793009b5eb009d32a102358596a79fa951176c475e1cce3ab454c4064269569c392c56309f2ca90b77af6254209dab87841ed35042a44270ae946cf00496a71478e437a843beb8e522295c9b3479b4a28b77dd624268693eb9538d2ae5105514841b593230dfb8c64936082a79c76e0df7392049895001ccc0f81739d002e3175e30fe6f0eb0ef6ebcba037b75dcace321379a487be6db7ea03de3fa5a057cd6a8a6c24a45847ad6941fc7e3c347a39260427c7f413b95821064aff6e1a01023cbcc2d00f1f28d79687747b0e4fb70b22319e39fefb76a90ef22e021f96ff55000000000000000502803596b4ba5ea05b1fea2b78e292f935d621453cffcd207e10f3072b2813ca3e963cebf05b19cd82da4bd5aad1dcc7fda1492d7ffc8f532bc4b37e9bf4753b7ae6b8f08e05a851052fc6ac7617ce68293678747d11f9a508bab6f7a60edde9c4b092dd34e11fd7dd65823bd9a28f6169fba00b9b82cb9a8e149f43421c17a98aa5d382d05056a988c0956d330ff55f9caf87e8f23f45b9c3fd46fd17de35b9288ed1fde6fa48135fd76e331da22d2ebeaaa90098c9fb5744358a77cbf3a3043f51203db2a0423969266759114978722c077c55d02bffa1f76c8fcb85395cab013c3ba44446b18d561753335da9236fac7cb618432492eb7d992d699cc240456120da4c2712b9a44b640af2033485fd918ae817e81cf0e26057c66371f1b2b7b0000000079580daa7ed6bfd9662c47231c3094a8f96c2c25e5c0eba5336343eca68747f7e9918ac172c2211a43438fd47b136bd628ff969687ca71147490780b44914c168c007ed619431b041287d549fb96d51e6b41e7c28eadcfe553d53b870acac4594a6010d523918c8862810fc6c8cde78e3e5965735c1d00f0ef9b5cc4902ae52ec62010d0f98b9d07c78a3ae3eb1676f56b07a0ab8716ebea736ceffd92045eed660158cc24864a23b5b3e0cac55c68051dffaefcdaca795ff97e093d901173faeadc00b2053ae59cbb36864862c30bbcfa5032e1516590e380c2b5073cd1bc3e76ae8f8dc4edc892ebbe15805271f98c0ac22ef9e0daecde89e16bbf0f5e0206c32a54ed875a3de1e86d560f615c8c6cca5fe74d2c096003486caddbd6185b859b2502a5d05bd9ac863faa0a2ca54eabe1fab68df7086d78a486f688d4419bac0ca6b29288d9ee95df17e27d269bcff0fa521802f55a178e6189c4fc4e0c9aacc7641935f9750f7af0aac001a0efb0e2436afe8d40637b5f1b40858878bfa5ae8a017b3217a716ebdf27a1723a93865fe088c834cff4c2e27ebcac37e3d23b7bfc4a96f4d0d3e1ebf1f13ad4a81f7c73482802590d0c0dea55147cc163fbd143db10aeb8505a2d9ee098a6c47bc41fe032d729becf1b7131249773a9efd811e9caebd1d72658785b32470eab5708287532a4a4a4a91073b5b77e693c393ede85f4d23c77d4e7accf7460976f7ed911d9090748eb9498c76bb8ba173367a5963a938d8c2173d20db10bcc7c452f1f19f93b31a02b6f24794413dc183ea2bf157388d22397beb12e6e4a626ab32e6740a0c3d9bcb49579c27a479d5cf6f2d98b1227c690d734161166bbf9caff311f2c504a4dda5e53b70b8738b18dfa4fbb5ecd0b074885db065516a7a19b78c63dc1f5a72a8b843b5ea3c1b49feaccfa55216a81dd028a44797f262a0b42d1e617490f16f575f44991cd02f1a679d6695a0137b02423d96ee162d768f0ef1c74980e5728bfcda5fa69d451e3a64dea119b16aab039035240c33b7dec4981aa53e914f67ac932328b31f3fc4d0aac1c19a4da4dab1b525a63008d0e40b86076a1b7e9f0f219955c76798ae8d5131eee35e9900c5cdc8b58badd7022044521d7ad239a91bb2ae1a02fc61472f7d3629d14070641a1e8106424aff358bd337af5576ce1a48243e21c3b73051a87b7a914ef68645f82f5c2b1a8af8def5d639feea0fa02f625f9397619ff9538ec5ca1238e7f26451a7036e9319fbe3baadcefe0f09d32a37cbc7644b92ab9e984304fe7ee22886d8e7331b923ccea38b31cd4c5b6e21ea7b13f93a74d2e4e5c5abe8f48efdc901055541e152730c07ed5c80c97a3538602df6b37cbc864618781c1728ca3d13af97b33e922b8722a17d7b3397dbd604ea26446aee03488924d55a8dca65731db96bbd00000002a753709610f96d22afb715d26c8586d8971f9201ba327d6eb4a0ff5ee0943f81f7eef7901d85fdd59b18d825b64accae87447036ee703852251d2b9d0d9add516ea1c1ac8f68168e881c4a6ebfb1f9c1c7e7098b7aabf9e0a2efa2423186f7f4898dfca0ef6f07fdbd180a2a164d21b18b0424d7f7e9c93d326e3ab308062bf644184b0e76e3782b27de5b4b971b127a904946ecd4b94a21158d8ffc0f040b6dde6f044dc084ce27a016a1677099f3b335237a19623edc4940193bf706197b2832e1f8a77215de4dc73fab8cf1e1e090f57e5db737174759e3434b4da5feeefa41be4bf511821326cb664dcb6705c926e135c0de63e86b3c0fb1db02a47ecda00487cbd29bfc97194ed8868ed4e458c7b2bf8ab6f04efee532502cf588c4f26b9b2830baa635c56857be5fd6803fd35d508881bd7cf3b5872ff84640384e2576bd93d4d86fdafcba2df3f29036491573031ede2ddb09dd092ad890a68f07876aeea30b4541acc1c039323dfeb5a8bb81396cee8e41a591c6c559f24181b3f1d9a1cf386dbbc74e601480099930464fff2f820ffefe9c1754ea7220ab4fb95a73bd217f7440d26d803077031d039a09f366221c1d60f761f70bcfe592e099e41b4a5bd088cd1ece3af477e1d13f03c1459ad22b42f3479f12d7229de52d7f4ef95c689a33ade597a8902964e244e6cca0d1f94de905f9fccf95b774ed2b8c2a36f061f3a8da53b11d71d9855c79face7dac770caf93e5e9d7fbd6b2907f994bf8e6000000028c27c3a9d06054e718d61e0c97597c3e2aa2fa7b372b61e37fd02004a58cd9a9db0e4aa75995de479dc528369aae7850971c7a68b793ac91d3f8e31fe12200a63cd651d0fef437981c041f1417c0a7b35ffc2725f19ea6f47b2db483ad3c28b1ac997b445bb2fb55c276fb800e331cd8a406efc9074101a3b477df4d1fa187a27a07e58e3d0a5fff80d9c33f5b0d9f0685a41e8378e99fe37e7376290d971afcd3548fd6e7ab783c338558a58c7f4b17b3f2f19892b8fab86f297ad4fc25ba8107bdfd243161d90f6439adafe37e70edf6d318489571acc3761f12ca134dd42713dcd3d4e4bf11bdbabb6771a1d11f406969ed4f1b3dea7d32c292ffa07a302a02b387e119ec10c4a8963ee52710d75c21710881bae7fb5a8595fd43a9156419f8080891e50139bd4af14f1ba25ebe0152b5e83d115be493372e147742d8bfe3a8269e8ecd27ec055a11055d5405192cda8c8db528f06b120fc2e3f470898974118b864ba4ea9442144f894abfdc952071f586c663ee9c7daaa100295213bf22a96b9c2562d7f4bdbc878e59a5dff96d1793ff7a7819b528ee718513bcd5d6f44cb1ff1433d4a6a72d95a3e9c2f9bdf179fc0d999a689ba5f10717dd812bef9cab61b118dfc80d1f16fed604130e256bc3cbbd4a3f9e7aa656e685d9f801845f043178b7aad99f9214e790c31939f6b85e3d876351377a3d57b3c85d84876a93fd039a4ff13d73c3564d8cd9c4310b4e7bbc27f907b10b6f95c09c853e6edbb84300000007ac2df00a78778a0e2e4ab221df2686305b7c4f369c9393d83d2398442fd650d3d49a9171e64b20c4b341e8c5f0153bab845202926b803c5eef4d10937696d1f2917a5c1ddfa86860b780c7e9cdca49bc0c07973d1a2a77fa6688176e3c88c933afc37a04d49778bb6c3eac0ef42a67cde86dbee2825f12f848ed2383af2da472dde4fc29b9ed9267480363f587f5babcb86c0965845495f3b5cda6f3cd5d5784a3123b89a74b7732b51dfbbfb28cd9ea0f635c4920711cc8bc9512154ef679ddac1730212ea8cc4718c1085583c5c40b964f1aa0689595a8b6d1869f23a8d857c68251863f5c3e57c62f73d40090b437a337db8b01b5b258f5217fb81b634edea1f942224a7d6bb9124272a99f038980976a8df52094c62fe7dc6a07cbe2e67aa413ddead30ad92e54c0cdc1b915d2bedfef9660fa69b513736ca221fa4bd6ce054c90ebd9ddae7cce9f0c02630cfe7f88f8fec518d60cd79fd9f9acd653b8cb8707dc463eb942faf56308d8afd89a5d1f690a43203cb72049183431d0e291888a344544ea7d38ae1db3ee49d6d9790e1baa80abbe54db280593b9a7f632a0bd9298cc93f298b8b0a7b91eaddc1856e2ad00c721bb2099d944fa0a847513fa51bfca7822fb8163794fa28e8bc9712dc2f2cd5b6f53c66dd8a536f869447dbf39b4accb28dcec7de58ad83819bcc4ab0b966b165bb8e0bfcb30a6280e588cac873e9b3919a8bb8c3418f4cecfc2e14e60b47259143898aeb7380ef76d93c8e5102ffdedb793e49f23cba70e9ec04475394fffea2d0c6273730a101314589fc9c7ab713604443a0e8c7816d10d6581fa30fdb1552c61025ae3e85d46e7dd38e90d1a6d8d4921c806d9dfc84a7a0497335c8b9e4be2db89512fd2ca332ebb66ec302da2ab68f2a40cf3b957720348b7ac5414b9c7c3bf05c88fe606a31b69b5d6e606a0d8dce4c0952d047fec38e28ef722bfae923ca9104f1742f1df96ef9650543e19d25a3b6e8f93e0ac26841120c46cd416e9fa4a111b1ad3b8a171033d26a901", + "proofValue": "0000000000000006010098ad4f48bcd0cf5440853e520858603f16058ee0fc1afdc3efe98abe98771e23c000d19119c28d704a5916929f66f2a30200abb05a0ff79b3b06f912f0ec642268d3a1ad1cdf4f050ab7d55c795aa1ab771f4be29f29134e0d7709566f9b2468805f03009158599821c271588f24e92db7ca30197ec5b0c901efaadd34cca707e56b9aab1a7f14e329816e2acf4d07a7edf1bd6b0400af07a1ba7a22bcb1602114921a48fa966a821354cd0dd63a87ce018caccc50b56f2c9f55a062cdc423657aa5cec8a4c9050100097465737476616c75650602aef4be258f8baca0ee44affd36bc9ca6299cc811ac6cb77d10792ff546153d6a84c0c0e030b131ed29111911794174859966f6ba8cafaf228cb921351c2cbc84358c0fa946ca862f8e30d920e46397bf96b56f50b66ae9c93953dc24de2904640000000000000004a547c8619f3ff2670efbefb21281e459b7cc9766c4f377f78e9f97e2c50569a8dcb155f2a502e936d2cb6ef1a73e92af9916e6353b7127d55bb525cb18074b5ec130463e03a4eda583b05c2d63db40a08ab8bf05f930ec234cc2f788d5f5bfbeab3e4881918ce964ffd55483219edd435ac865286bfd313cd834aabfa8061d2ae173cbe4b59ab2bda78faa4c2c937afba80d7fba0822579ac0ef6915f4820f968a74f00ff5ab74e90b0a7bcb2b92093a5e94a54aea1d48ffd1e5bb3fb48069bc022d40f10bd9f0db027ee76e5d78722b22605a1f420c0d8923f384fd2e9df4d500000005000000014996e6a8d95d738baf684228c059ffda43b6a801240c467ff648b24c1e32a8fa25e6348ea46cfe7a6134f6754367715ab1fa97f963720164fd4af47882ea5f5c68917936ca63783c8e7252b3add6d60427580f639caec877eaf62af847e260b0000000022edfd6a9b5f6cb325c2ddafc2f37328768062360b94ff89b795eefc2bdd8b8c7566f982f3189e2158c9932e6c2236beae9c4a1767de64235066fc668c43590a466a5e08b9552ff74c7850795edfb41de40a8183b3ae27e25e14a851192492649000000035477e4693d1f65ba2c6d911de408be4b4164ae853b9d944859a7125c7f80c8b6737b58adf891170ac056de0907671899121fede2fd7cbcd6c266fef9d011baf65e6529fb326268ad4394ac4bdcd594901d2d649c9633ed273d47472550a6ed1d00000004636f324e0c8d9958f960f621ba0bdb0a12c2fdac465fab6f3d6b0219edf20bda34bcc475e9e940e5f2c166aab81bb46a24fe84a7c150f60f19b25a9aa26b02960fb8204657da982ecc80099255157f127037fc1d01bae5e751dfd1b568d5d3b2000000055252326e4bd286ff449e1e4191ad5bfd3834498357850252b2efdf71e5a195801b0b139f690a241db78ffae798e90adf5468ed485dd47c396dafdbf95846ab3f1dfc26f4044279839a74ef3d99d3e683ddfd948707a841052beed7fa59d3cfe10a85e4f590f94aeec5694aa34ce7809e6409635c3dcc06c48e2b6eb7c88e805b0000000c0044de5e492f26cdc8d9dd7353c8f4561776db5cf1e9e56765f8a27325bea23c7c6e93ee0e96b86044e30a334d6a3574f1eb257fbc13e38045de829d08e668e1760233b357f18e2fb13b681affb3100a76389289b0a672fb4c018b496086e907a8d9010101024a3c3d379c549361b01f1da35dc354171e8b08e37cde8b26708a7d0a74a1c475001607576a587bc3724829d37a211c4e7ac685f5d2ff8d183878c47761fa207a2772c92a29d9723c60fcf02a5f3ee44f16c8d719ef0ff7306017e8abcca0ac43da002c1306c3df6c321d1827b482e5bdd43d9ae0ebda13ee87f8ffce45b9280974d30da67ed93028333a98441ec283b84ef993ba16ee3f63abeb6913cb84c6087e520031d913edbe710a6ef608a7496ddb24b62af6dc53b0c400515094a102dc34ba7e5101b14654477c70600fc619c536a55689a34483d87a607c616b8e4a7f588b1c0020de9f2cbea7cb077e1dc06c4f2f3286792ff9ab865d04a264699b063387d3565a810470a1a3f0b94ed0a313bf2558035cb562112fe9d4ce3db05035da60dfb401023ecf78fe04bea07742a2b68c1dfc848ced58d50cc72e3aa9417456c137f07042000000000000000502803596b4ba5ea05b1fea2b78e292f935d621453cffcd207e10f3072b2813ca3e963cebf05b19cd82da4bd5aad1dcc7fda1492d7ffc8f532bc4b37e9bf4753b7ae6b8f08e05a851052fc6ac7617ce68293678747d11f9a508bab6f7a60edde9c4975a76ced40574074001091721440b1d62252454c2b26494f5014ef4b5f0adaab23eea032dabcf7fc274915ed26a38ea985468e8f27f81f378870fdf0c9fa880b75d301d54dead22ebe69d98305b8bcb1825f77084a3fe794ef69ae07ca2f40c327c3b8055a8dc2823524df825d4748e84c743856120bf5bc77826884412154e26cf2b601c2b869084806c5e670919b8cb8d6ea8f7a8fd14096f7dc9765bcd0d5a04e5770764de9318b0f4f5fd1343b30f0954656423cbb994da605956acc5e30000000792698ceb941b32e6ff12451a75d1eb465ca0710879a4d67ecf75ff5e614605b7284f07109a658007dd94b499322649a68af4e7b7ad848fbc3e2dfe248fe846d0836279a0a8045909516fa2de9ce9d456e68278372af302a891a3c138596bb369abb626f0e5ccd6ceb9d6f7f0bd979a37afdeff02c294ad7db9ad1335f0d532027bf7fc78c7fe3d1025bbd9b754e8ce068ef1e251727d48cb25040091f05b327ac2ec733c1cb349f6aa20c00f644a3f9c84df72112b4f4b247126df77eb27933db078a098bc904d01ce5de1be0fdb9d8796b3d427c7a89d7ace44209339c5577416dff5094858771314c6dcb8562f7d17a30c84630530510bff914ff0398b4616171386c23145d4cff3e4a0f698715bd68dbe2233b851ee49c17c0b7dc9b6f5f4ae461de98c4d582c8be6f490e75a0c2b1a61dfca366e86ca6ed131b93d43c93292f6182cf3d86e98d0baf613630e7a34a54dcba10f680b641579909c138223182443f71f110d7eb97d0bc99c795d95f28611ddf484208c3aa9763b517024d32faaea07a4343e4fa9b72ffb951fddd5e811def887a8d92e89c574d7820ed46df10da13e63ec1223d2bf1ee4b8f6cd353eae032fd8b3f6f886d5feb3032ac2c6cef1f03513e04646ffdbd0be6597f674bfcbce9f16127b43aa49f4e6853c56e2cd96c75aab089f07d04515e52a097c1b08c75ddb30315af1d65aebd00585c3818e7587baa5b11b80a0fd5fd2e0b7b473c9ad112a3168aadaf83ba4d94ad7e6b47c639684d634fe5ae59fc1f9e6741e924bdc8ed49c2a72bf1e7869fff80d17a7a0adacbf2123fbed51683d0897fd76310f3896381f47c675764b6475a027f92a0b89d863218dce9b3ac48524b3d1def4f0877aeab34415a27e33d305e9ae39dc8c918125498ab16932378e9f739bd2e0c4866265ff9f98c7b562000c762254336c3ac576cdfd96936c3f32ded9523594401d0ad2f2232a01b9c8443395180f1ec80a119e63e0bf631cb93a9db4ee6a2a29e06f520835f7af238e1c8cd873bef1e4039035240c33b7dec4981aa53e914f67ac932328b31f3fc4d0aac1c19a4da4dab1b525a63008d0e40b86076a1b7e9f0f219955c76798ae8d5131eee35e9900c5cdc8b58badd7022044521d7ad239a91bb2ae1a02fc61472f7d3629d14070641a1e86c2ef60ae3a42de23a15550c75b135a7be766fc38a2554377afc4892fef23e54ad59b72bfa590493d3a0e6d0c3692f9b12c28a4c2fcbfc8331381867935bdbdbe83220fe2330b5024ffdaeb37eb9a4f8dc8505ff846ce16a24ad0f36b8145591838c8cd056b4fa56d76e3f0d3c04cd58a13fc953ac12f292817ad4c1b46d62e372b5a5f8c7f3a4dcb29beb03b75d7b9d0a4a463e37f00da224c7fde6d34c3d53f34ac41a47b698e9b381d0debc448c465c594d9cf9c42e8cbce7e0e03091000000000028f08b690d86821cdcd517648214e22b5b0b73e2c7f82a3ccae933d61bc0e28fc69b047aba5cc6b8e9e6f4578e02924db920fdd2cbc3f1171c98169f4fd5676b77f210f9ae5e949afab54b2e52137538906ea05c5fc5e0ca989eb081a3ba9285ea611a9d69bbefb08d3142a7523a3ca91961b4f6deaa87286a4fe776607572b5db7e6ea488c5b9007731663b4537b584983937bfa8ec12bc8f6b1ec8185cb2863f7dc15f82f50978301f7441901d2921799af71fbf5f3a83162ddaed844b5647970b4bf4cb7d8bae88457f65c2e5f09b71b6585303e4783642c20949423fba406002407e6a58cd57836650e76df878926d0b6315f4c4329385566667701fe7f820487cbd29bfc97194ed8868ed4e458c7b2bf8ab6f04efee532502cf588c4f26b9b2830baa635c56857be5fd6803fd35d508881bd7cf3b5872ff84640384e2576bd93d4d86fdafcba2df3f29036491573031ede2ddb09dd092ad890a68f07876aeeb5ed24f1e21e96aa8f81d1b57f7963fdb0d617a6c302365781dcbe1628103ba3e9fb7c05ec5064aa5f518a2dd54deb3bb6547660749326b8e7c23931f938d1f94b2b199330c7cf4e21caaf3586b5ce3f56d5a1a06a78729f9e8b7838eef1f95828f2e1f46ccd7642fae51f13d2b0d6c55b328e0d6bae6355d412db989f82a3fa47b167da18c385588da0d8b2715d09c06cb2e03a1bccf8e112893d054c79b8d850d3c90fc8866865a2f85a8b3f64d9dfad1381b1bc0653335ac741925dccaac600000002895dca7ed412bae0cb70d758773dcfbb2254c95be80f230ceb3a73883bd6b6220cff45b7e9d058da58071acb8a32767b99a869379b6095f4e2b7ddecbd8a4d17a094f9681a4345c35c87dd86cba4074e56dae9e1ddadb7edfa248058f12f8f0c965d922130d696027a12fdfd06b1c39c7fba1875b39f751be361ccf330dfcdfa68623eb78747bc06f9ac45b812d5d313abfbfabdb4411220d1e78b5384749bb890b3f220139e0200315d516b3fb2e156b2a5c1c2a081a3e67eb6e8fc97be9bb4439a9eaadaab8e29db023baa98322d0d0e7f06efd708b5c7f8846e799e8607a20242d81c399a6571f8ea9c203a534ebfc6bf416540b8ad6a2c82e66dd9d2c0c502b387e119ec10c4a8963ee52710d75c21710881bae7fb5a8595fd43a9156419f8080891e50139bd4af14f1ba25ebe0152b5e83d115be493372e147742d8bfe3a8269e8ecd27ec055a11055d5405192cda8c8db528f06b120fc2e3f47089897411aaae9e0b0179b2e09afee8e5d56ea05b85694d71186f6d6dba1465c19cfc41f55751c1c7e3e071f0a97733f2ad4a8d7eb5038bb97411c01f77d451d483611c939f1910f388110198c69a2efdce02ad2334a1c39958bd66abb940ef1f42143a65010e383128f291e962c579ec7cb9f24f373554e84ce1a21f459d5ea4ab1a41ec733322f9b95611de75450bf415e60dc15f8d33fdb61f14d9c73c92cd6ace0943403768e8947e8122b2cbbc663a5373940daf22b914730c980c66e87e444db56f000000078c1751517b7f76514a5ea7af097099c03cc64d9416494d5a9f448c2615903650ab7c8c2358619073d84f04034ba7f768b62b4825d8a12f4c0378b2b271eb05f8b3cff514ebdae3b6de637539305437c2bc0bc6c2649961a1d22295035d07f460863a3d0467f01e79c4199bf3dd73a57a58315be6b4e465e43fe66e82dc933ee622598672fbd0c5bae12d8e187c7a6dc8a2c4b3dc57040a759e23594760d76c8d6655c0860e4a1187e89d7451b1507bc5e0ff3eeb28577af943a44afb61d96eca898cb8417551edffc189fe2d24e83f554206c397b80153044e45be32aef5b46deff4625d1d316338bf3521ee32ef50388a067b5c0972ca68797b98b337c09589c307d5adfac00a524ccca6d8d5450a0eea765673fbea3956aa0edf0dc0a2c7318dd61540865a408715c148e406489f7e56d953af3df90585b2dd12e99a4a6878009001b62f9fa0a023041fd77f41be2da2ed746a07bb3fa3864ab5e76be4f98d480fd97280735eb9f44c6bb0b1b02e2ee8c9d1c71c68de3325e6d14f44ef98b68b50ddef96b312c9a17296ecf837591659252f25670d9744c7334abca978eab4d7c40276b876ca682c2c06ba2809082d842c021fadb934bff19025c4dc1d80f6a9fac3cf59a7209c1d73113b87b8d34a8d618a5534db6fbc4492cfb6439a2c088cbbd44febb15f56e1d119bbf1e2bd108325711d56938eeffce12ecc900059822448666fd380701afb94887ff3a73d5ab6e3a9614ec319bb579d02de414db8a02d54f80928255dafc2b7833159aab87daffd5e143e7e939ec2c05496573f7de1aa46492cc29053e0ab0d7a2b524b3cade5e2ee0fbb0aa8f0b340cf139321230da9d50df0e36794ff03927ebdfaeb5b4c88612f9a7cb6660d8a088433ec92cd24ad06e4bb75885b0b7103d524f4f6b080be40484b9138278d95feb40af1c52cbb29f7623675d081c0930866586fee0476a9f21bffe406e3265413f792e0d464e9476becd32bb6af4856aaf4dfdbd6f1a2fea4cbe6df332e324f091fa74e7d9cdf01", "type": "ConcordiumZKProofV4" } } diff --git a/rust-src/concordium_base/src/web3id/v1/anchor.rs b/rust-src/concordium_base/src/web3id/v1/anchor.rs index 039346225..767e7dc75 100644 --- a/rust-src/concordium_base/src/web3id/v1/anchor.rs +++ b/rust-src/concordium_base/src/web3id/v1/anchor.rs @@ -1260,7 +1260,7 @@ mod tests { "issuer": "did:ccd:testnet:idp:0", "proof": { "created": "2023-08-28T23:12:15Z", - "proofValue": "0000000000000006010098ad4f48bcd0cf5440853e520858603f16058ee0fc1afdc3efe98abe98771e23c000d19119c28d704a5916929f66f2a30200abb05a0ff79b3b06f912f0ec642268d3a1ad1cdf4f050ab7d55c795aa1ab771f4be29f29134e0d7709566f9b2468805f03009158599821c271588f24e92db7ca30197ec5b0c901efaadd34cca707e56b9aab1a7f14e329816e2acf4d07a7edf1bd6b0400af07a1ba7a22bcb1602114921a48fa966a821354cd0dd63a87ce018caccc50b56f2c9f55a062cdc423657aa5cec8a4c9050100097465737476616c75650602aef4be258f8baca0ee44affd36bc9ca6299cc811ac6cb77d10792ff546153d6a84c0c0e030b131ed29111911794174859966f6ba8cafaf228cb921351c2cbc84358c0fa946ca862f8e30d920e46397bf96b56f50b66ae9c93953dc24de2904640000000000000004a547c8619f3ff2670efbefb21281e459b7cc9766c4f377f78e9f97e2c50569a8dcb155f2a502e936d2cb6ef1a73e92af9916e6353b7127d55bb525cb18074b5ec130463e03a4eda583b05c2d63db40a08ab8bf05f930ec234cc2f788d5f5bfbeab3e4881918ce964ffd55483219edd435ac865286bfd313cd834aabfa8061d2ae173cbe4b59ab2bda78faa4c2c937afba80d7fba0822579ac0ef6915f4820f968a74f00ff5ab74e90b0a7bcb2b92093a5e94a54aea1d48ffd1e5bb3fb48069bce918947b0401f828565db1e1e51aa857ef93e03fa5ababc60cd4786d7a09634900000005000000012ce448b95daa378716adf0848b6ea854a371f8a640a27aae907a65e1d165b4df09aa5ed12957cf03b1d3e63d08f678e42d4741932fb8a68be3de3dc42052c332352bea7c1bc835e9610dd6ecd8df1fb78c5c175cd2a88a5ad4b4731993c2755400000002630a1133b728c97b192006c497ecaa7b547069790aab33afdfc83f83ba195fb53f964ea79dab2d0045d6ed96ed44e37d36092cff72896093383b0be9ca5b4d4205888ac87fd63f140e6af46eaff4d6f7b97df993db959ddfea2da9de2c614eeb000000033f555cc9e29211d7b6e0157dc9012fef3d0d7d741832ae5b5a871cdf86a16d6b19bad51c715218a9fd1cbccfd36ffd31954b70b61f224223554884554e94fb2e020c07103d39461b8d0f72b260869977dae7258753cc39aae01f668abd2030cc000000044edf6719f081fb79fcf6ad84c8345eda80969194af7eaca4b93469edd70590f85f18123730e9c397d0ae12a21236af34e6fd1422f50ccfd43858df85b8048b9734d96018a5f60a96f993f0c27dbfca86bcac0e8d43b33354b27d7e5c7877a5ac000000050d792f44183c862b920029f6676493d2826142a0efc12909fb25cf9bf65c5a395c2dcb0d0c0d0de256d634ecefed391c5c6f6abd6930cbd9579a9c3e32c7dc902fbf3973d776db8645328ca8e64f7989208dea27eacf54ad1723194a2a040f905696c2bfe78b0ec413d57aa4d0553e77ded504b4fe62cc36c47d6d4a86b5cfa60000000c0027725a72d2e64a1173bf298dcf55c676e05b25fdb2029536950b87cdf3d4d8025127ea383a77dc8d7cebe9877096e55154a548c7dc00ae167aebb1b11b9b7cfc023ff02d4e04a94e3f4f52a5dcb0e0f4ff42ec4dd82fdbafae5bdcdabcab5731b60101010226defceebd8ea21e70659e0d47156e9aafa0e8433825732220ea7c0c64f05f80006ee634d79329135d6e7ba852ed6f11bd8346ddbebb96e0024681aae104e161516c9104b5e1f3f4ce09805d9a6ac56165fc6e06b64b1009842a54fc268d88efeb004f7ce2fffb38f7b85cbff4d83175b7192ef53e497ac21e7a02c76c55ad09cf2a481dc049ec4b6c844984801d62ab5d0c48b59ca891124a42762b91b47c3be4e90020d451af64b35661fbc1b2c4758dc3999a26452142d418cc17c03d0fd54b7bd070b3729b387669e5ba643cc52237f94ccd83513cdf360533c95c0e9ec95d3321006ef4b2f6ea5557fec7a9e2add74baeb3e4eee4033df5f5fe36e5ad141bf06d596f834f74b7285f35675046152d9ed31e55bff88704790c15d1376b9d367eae490102526050662f7ce80610a9537cb546c5d9f6d70c2cf1868ea5f03e5cf6deb0f796000000000000000502803596b4ba5ea05b1fea2b78e292f935d621453cffcd207e10f3072b2813ca3e963cebf05b19cd82da4bd5aad1dcc7fda1492d7ffc8f532bc4b37e9bf4753b7ae6b8f08e05a851052fc6ac7617ce68293678747d11f9a508bab6f7a60edde9c4832a0fe5be28e50fb11eeb45ada1c695c32f32ca6770c0cbde453d35f27aeccb42c859a479428fa37977e6495dba22d2a26bcebabbc8d4608efdfcababdc2e4023775a5b4a036bbdc54c700947eb10a13dc6638380093a2ae32fbcd187759ae57210fdb66984ff3cbf005e211ff658d558e48520db37620ea4ff00300af4204b62f4cd1fadff410104c96f90db4d00d04d33eea519333697ac76ba0b8f58cc4f40080ae28bc9f6f6a2bab31997b3d6eb369410dea819480d625751f8e410acfc00000007b8fa84c66b844c262f4d87c05e6953ecd8eb1c2dbcb39e29785806b6e724444cec1c4631fafe2d443608e9d80d47268483b5d81b6a029b9c9649fd1b1c2ae2a3952ffe0d742a871f0d1c616d01a25739ea46932297339cbe4ead8fb80dc568fc83a7d525f6142e7bc8103573ed78d254eba1ef2efa52b702e97e77167d0be1cef32561ce45c7c39312ff9e4e4b1d22dfb93d00ec817a88fe25810bdd6f4e8c01c70b71176106a6a6dd462136bc3a864428a49e679341707c593efae6cd7c4dabb22af142f11717364291ac39418bbae54a1cbf388bd64f906ed1406a822bd9c7db49462c04efe016e51a74745c64bc0185782f409611c2dd92f08e0d7dc1eb0dea1e9435b739085462454d18e738bdde1fe076a0ca39256fc1327f479257093585f5affff4e6025362e02017164f1637144310ead68ce9c3ac0314508f564e2940f6c0844d0dad7fbfa5656d3cedb122b6ebd8e7382d1650e1858b089efcb881b5dd1cb90b0a70d5dada079298bed1c4656ca730b8aae399b6fdcfbd48e1ca34a5ac1a6aa26707161e1f93f0e441dd1fae1043eed5cbb0c57f4b387ffa8cbce7b7c970c9ac42e8e2c65174b10f2ba1b484c9ea785cfe0ee8ddd39519c35e9743c38e53b484e7ac0484b7762e7bf6b1aaf4d8a3b6f018bc67b62480bd404eee1eb4343460d1aa1847d16786e2b7f514b1086e7ab2af51290b7c02baf61761ed5c74e78287bd57c703dd28be90692f3c6f8d5680406f7a937798a144131519d71f61ce807b2b08b57e0086f49509a0c138e838cb8f43c05992c87e4a63c8b0cc8d98de91d2fdb7136c1ae9f1aa20a38c2e26453407caacd5ea8bf948f927c4b440a71dd3573add57d748f701a4d2d49472b57b1b9ab5947833e7848a1fe600367f4517a2a897bd31f12cfa9740d2bc2d49d84b2bd244dd818658b2a20822308b071e35161216b4cb110a40d250d8d0a1a3c468081db7d7405f3ec73760fc1c50c16c9fae68090727f52ca4d7ed19d7571e91309fa71cda8e88471d61177b55f4e5039035240c33b7dec4981aa53e914f67ac932328b31f3fc4d0aac1c19a4da4dab1b525a63008d0e40b86076a1b7e9f0f219955c76798ae8d5131eee35e9900c5cdc8b58badd7022044521d7ad239a91bb2ae1a02fc61472f7d3629d14070641a1eb0ae78b9d434a8d58901dafdb10f2a64139185d098d2fcc635495c59746302c665f5cd233c7a2af83135dc4c9d68c4dc907a48ea71e14e5940a31afad31331273c0b9b1a5f9135f7c3ac7da281227ec16ef4a44d3ea368d80efe22709a378ed90959f6cab2611b7fb357a5b97645ea72b798e9f1e191f4090e72b41ae1aa6feb33bfe631a37c4aed94bda117d3efae9f2112a2e01f36e1a9247b5ea2f13735440ba3b4471d203585873a2632fcc12617398d6ed2e0dc3f131a810c4c074c2fb700000002ab6c28f1723d6169913f2fee10bdd5ca0c0beb23e2f8df58bb2c66ebe3b6376a84748885a152584c39f7d043f7bd95428578a6d20213df102ba313d04144aec52c4b99e33e79371b78bb19912359dbfbf99f0b4bb1b41c3f46f62ecf461cdd909643a10b66b79d6a682b02c6dc0f4562a200008884830ae274b3808d1c5eb7c5821686098723f9d9c08b7bab607d91bea7ba82eaf6fde9323d88abec3b81b9b2208f014d7b044b019ecdb735538fccaaa3c1aa0a9b412feea2d7b454c62592920833c9b9f8f222e59082492a73f5ff331a55b0f7abb7690db49e685570ab256830f006753b41f3c24b192e079ba9dd9bbbca82beea28ca13bd7f64ada89264390487cbd29bfc97194ed8868ed4e458c7b2bf8ab6f04efee532502cf588c4f26b9b2830baa635c56857be5fd6803fd35d508881bd7cf3b5872ff84640384e2576bd93d4d86fdafcba2df3f29036491573031ede2ddb09dd092ad890a68f07876aee853d3fec93bbfc61b872b43b5e0ccac5ecf166b0770708e8d7ca8078b19dfcf4d3feebf4f962e0c69833338255e2dc2b8a2fb5b617875c72f21c30c492945f922375140d0a03c9bdd7329fa8b6d2666ff7b9a6effc7d6659aba3f27f92b8bf6f0950bb10453a522bc6062133552608efecdc132037309e88a155f72665dc6c0b48bf27b3cd3d215470d14c6579d7dd32a85f75b2c5687d0d349061924d01af5c550fa76e21935a60acfcf31ef1b8c6a4180833b89bcdb11728cce06c3c19078600000002b67cac0bc5add116b86ac8cca6abbfd80c07582e86e90d76ba6c6aa41d01d11a4ca907a634ee339cb5ee830719379885a774cbf76d65d324ae890313a1688b0cc161f6e0b47dbd0db2157a92739a20d028c30b6da5ec4ebb76e00c8a69fae0d4a8fe97431f898f3e65b4c43c619f36818c5de5db53b358d65002b96880a1de467f812a8b841a758315b0cfac32b9cea2912a04dd0a87ec3c2fa8d7ba2d739eb5945d79366faea8f118df235e57a83a144a507a8d74e39e1479cd320332aa88a5518f62e781c524e28f40c701dee87e94e8c8315b003c71e1976ab072e0178a91196c01b9e0c00da3b620a28b0f1b498989e6ec966c7718c62efea0b25cc2665202b387e119ec10c4a8963ee52710d75c21710881bae7fb5a8595fd43a9156419f8080891e50139bd4af14f1ba25ebe0152b5e83d115be493372e147742d8bfe3a8269e8ecd27ec055a11055d5405192cda8c8db528f06b120fc2e3f47089897411b92d9655a6d0766ec82ea392c7b6d1c05b00ccacf5e0ce8ac3418db4ff5b7f2def38ca2480f2dc03dc3defdb5c2eddcbb7abb0385359202fab02ff010884811e5f513504c482f30a6a41cf1a5e1eae4ea5fd7e83c6006dfd1859ebcf7ef69b5f3102f68b98b020431c735540f0faa51d05e380ba8be244af5d9208b0a659b6c23b42da958e514c545107c454f1f82e18e4f718be1ad9254fc4ba1d87de6d625b684497e14c6654b2d547d58e152800deb8a1d1ca39287461bb183c0b8cc529bc00000007970c4e8eedd5fcb380f4bdaaac76bfa3fc52b9fd9a8a40f3782355bd7bdab4999a32ee6fccf1ebc6dd7e54b21dad79bf981f13d11a242716793cc47ec6f0e19296135609cfcaaf472afcc4870df46c9b6f9f69cf1bc234757fba97a74c1cee84912a32caf9b90d7787d46b1c675be9dc0fe10f078835f36fece20295c1c890df280293fb1b7a9b2825f90b235dec576c90a953eb9f0aad4255e399ab2a4d179f6a7f8884679078de8a8a352af00ceb3a104a9b2222cf26cf3c889455adb606d0b34c7723950f6e26ad096b74b1f62a52b3bb1b0c8c770495e57a760f3e69c69501f898df1dcff10d726adfb09a26c821a268a7531e43a52ba39c1e3ac1d83a0a539308e37237e6b9d11ed659da956e2e49e4b9e73579fca7fb446777c8f52f49863620612e3de9d270364451c2f775dcd678d4ad2c0cebb4eeda7b41d5418b0d347087e168386a8a883b4d9a72a06e5daebdd392b3a306e5813c3e00b4af12d83154ece98ce449f2f479d6b2446b61c45dac93262381a68e276f8b6bfbb1fcf3aa50b209fca5d003daf725b635ea24c45e624ee2e0a83399ec513edbf66fb41f6cab206e68c4e5f30519ba581c65d2b7873b10a486c96fcb3824dd94d7448e747f27443ac395271aa177c2ddd9b16d24d29a4b4c7c9eff295741919aa4ccc9bf8437f3cad8668726f9b012dda2b87d5a61ecbbad868115389bd20fa945a604fc7bc28feb58f7dc49ec36293a80494f3eb8964a49c534346040cd47fd6e498fb3c2153ea6f059b751f9d5548ecb3bf3e1e33ec52bc52acd2298bd7141a6fe3e199036c7fa3377a20a9688e2731d98e402c6334892c0d3c2ab82ff1c2bbd928ce3ef57afa80568c69e005949b384d48c189539e2278acbc4580aa93e1dacc72daf67b709bc0384d54f8c7399b318a584100031954e79999c51f37d9541d0602e116953f7fcbffec6c850499751f9767f1c4be6238566565390e7c5a3732c65b35a149fddd3c10d6231e342c1771c9e35688f18874cb25ecda9299ed9763237c51701", + "proofValue": "0000000000000006010098ad4f48bcd0cf5440853e520858603f16058ee0fc1afdc3efe98abe98771e23c000d19119c28d704a5916929f66f2a30200abb05a0ff79b3b06f912f0ec642268d3a1ad1cdf4f050ab7d55c795aa1ab771f4be29f29134e0d7709566f9b2468805f03009158599821c271588f24e92db7ca30197ec5b0c901efaadd34cca707e56b9aab1a7f14e329816e2acf4d07a7edf1bd6b0400af07a1ba7a22bcb1602114921a48fa966a821354cd0dd63a87ce018caccc50b56f2c9f55a062cdc423657aa5cec8a4c9050100097465737476616c75650602aef4be258f8baca0ee44affd36bc9ca6299cc811ac6cb77d10792ff546153d6a84c0c0e030b131ed29111911794174859966f6ba8cafaf228cb921351c2cbc84358c0fa946ca862f8e30d920e46397bf96b56f50b66ae9c93953dc24de2904640000000000000004a547c8619f3ff2670efbefb21281e459b7cc9766c4f377f78e9f97e2c50569a8dcb155f2a502e936d2cb6ef1a73e92af9916e6353b7127d55bb525cb18074b5ec130463e03a4eda583b05c2d63db40a08ab8bf05f930ec234cc2f788d5f5bfbeab3e4881918ce964ffd55483219edd435ac865286bfd313cd834aabfa8061d2ae173cbe4b59ab2bda78faa4c2c937afba80d7fba0822579ac0ef6915f4820f968a74f00ff5ab74e90b0a7bcb2b92093a5e94a54aea1d48ffd1e5bb3fb48069bcc387a76b72ec0200cd68ff21006f7dc003c73f6a084d53232ab71af550ba5c9b000000050000000158820688e6d5cab5289178bdd2d589e9e07a855c510b1270e0a421acd153746827d4a9acb3bd37c9639a238978589c86bd50da86dfbff13db87b244338f446c06a6a6decefddf6de525baef19db126a1035c9d295389b6b0df59ecbd31a202c6000000026d562ce2d10361662f4108d936a5ab0eaf5081440db3b3a580460a4c022f0f0e642f8114705603deffce7cd50082e89d79f26281ae06b849a5ec31bc32d5d0614f5b7a8fad273d13e78769c9760805b48ebd895a5fe6a4021d81b333c5bb389b0000000336e858c07cf4c4d6a24fee98faf8436fdc1128aae533303fc8c4d216d8923d3537ead2a2f963205c6d3918dda48a4cdab84da3e951630051380c819972725c946fc99fee37d3b9dbbaf1917fd56d3d746b770689bf1026a57f94fab32f50187d000000042d1e99dc215c7744940d0987b485eeff5d25d23e82a8e904ea3f384e042de7e91dd3885c31fa44019c677bd89a5548fc41f7003eb4648ee3ded91b2b6b40b7b23ad40e7f4e6b33e5cc6b9324b02e7106adf4a3ac758ac1a282150d1354b9ab1c000000054f2cf54e84f7f094b55d4e8757159fc66d463ec1d80adef3d59cdee8fe62761971ff274b1d074be8b4d7393824453b31711e111776f47b29832b4c03b1d0cd89030e8f7ff7b379238a15e2df630277b75b879decbef400345b6a86e2b574d07b5339cf4b61b01290e9fe751ce1679950e76dd61661cb8897fd3d8bcc9bc55e0b0000000c000a9b2ff602110507a088f243cc130317665b856d16dc8f6039e7f847bfb52cfc3450bfbb69a29783a9b5b23d6d5421f1daa5a83740daa8401fc8222ae77bd1f60241ddae89c6b809a8f644019525d14f99880d4c8793e789a0a7d706614407d1b301010102440f755830727b5f10916e6871575d7abc8ac064afa821f80bce872022f2bfd300644ec9d8fc4ca2ce6674c14f21a5e74c29e6044828f4b4684e2eee1891c99e2a6095c63ec879d75681f19ce07aa16f4c167470bb0f55e7a243b61543cdd195c90037193559761a9bef8efbba56320c60a844996d56a8abe72d86021503fe14344e35477a0e0a1beb6e16aef290190e0d55cf75142287f75e4fdd977d4dbe787bde0004b368b338fc129799cb0d5b92e2261d5e8ab753d8ed821e02e83f255ae5293b10e279d60f3922bc49569c7a5f22587839b3bbe4b367a14d686f3bab04acb65a00643213767a4693c6c7fe1ae8bb879309cde0dbb11688d51889a31739e2c5b11f5192c1329c82abfea0ed9a58dfb11d089fbf0ace6cde29af97c7068ccdeb34ec01024b74406001751f0b3fa5d5aead94e8c0e3f36d5790d534e39182ac1f2c391408000000000000000502803596b4ba5ea05b1fea2b78e292f935d621453cffcd207e10f3072b2813ca3e963cebf05b19cd82da4bd5aad1dcc7fda1492d7ffc8f532bc4b37e9bf4753b7ae6b8f08e05a851052fc6ac7617ce68293678747d11f9a508bab6f7a60edde9c484c87f1fabd67d07f4fc5da977b9fefcf7ead0942977ac09b6b597500a0c95bdc942e913f4de29b93e6ecb26c3f76e18a2a57c2378b49bcc5e14d2e89a5c618ed7ffe1238da17a10648581e8ecb73ee76f0c36211f54f05f465de35b42e27ac6209ac19a5a3bf652748f20545c06a1aeed6a4c45504edbdf2b818210d9103e68007444633e08947c99193fbae9696b268a1fcf6ce58bcbfdc295a515c9966bf66386539a896c0babee669031dd831a4d487913c3a73b429faf2d74c046a5d65400000007a46aaad346d2fca20d6777883005e9dbc9085d56bd6e8dfcf0fe5432f1a8eb7fc1b9383dc0facb77ae0139ceb1b9d045974283c26d21a1a3c6d00f133e5844be6aeda03aa94692ff5506ab9de83aebae8d3b218556a0a3720f16dd79379cd8948db151d746a369770a7899e35deae87f78975f832cc4acafee3d3cbd6538b75936c8dd254d3785ccc7757cd209bc153a8903296b22c4be6546fe7ae191c277ad01d1216c52e4a0d88e28d2b4b90b59926f1e78e4434a4027e0eaf569ed37303c89977caad292916356530c0b4fe2e275c5bb76b8424bbc4604370037d0da71b7bc6731ae1ab70e1551604f4fa3071bfa96fac3809da2e4594467e434b51d05f4b8ff822d2ef3e53136b113209286be86f7f901f1dc9823c9f55b5343d3c4d582b2b4d272c7c2d851a52934f583a364749d409ae3e75025cb0948b985459a898c82fcc25d8849a84be0c5d92c8e64f695adeab0f72c539ceb0f4179fe442785e80795bf0cc3c11f09cae5e10a902c6eceea039bf8e1f20bcf74f4081dd0cdf380ae0e5a50a9a99ce41d16e90abbb8fc60c1c3195bc7534f8f48b417c45df1770a5304b097ff1c53b72f326b662b4b0df0b7d1ec307e06ad0aaa47732408c7b88246ad90ba2a4e218173c69057668b5a850874d5cf56f346cffbe9fd3030f3785f9044e6c21c58c5b066af155f57b8392797bfb1c0c5d0b9151212ae02b7ea2e106ac97d458ee865327cd55340c94b2c5aaa6a95650f28c77d0a2174fb36301fd1a50fffc2a08c98ea9b6cb52be7f689f744326bf93ce18720ae8d3c5c3d9c1b50b4b4851a74659ef6690be8703aef33d8da261de1b00c2691a8fe9a0f731e075079b93bb855e8a8f87591efaa4c429e8a8ec10707196315bae3d3d2aa0153845ecb656c77e0144518da59d127066725f0c6ceee6dcee06c06cf71f1abd752fab80963ca8891ad08f6450ac459a0206075c69751fbfd66f37e06707bfb7b90e2a221596abecab0bd5238c789e6d8b6078c9f035cd07fd680de847dea7ac9a7b4bc039035240c33b7dec4981aa53e914f67ac932328b31f3fc4d0aac1c19a4da4dab1b525a63008d0e40b86076a1b7e9f0f219955c76798ae8d5131eee35e9900c5cdc8b58badd7022044521d7ad239a91bb2ae1a02fc61472f7d3629d14070641a1ea65286fe1a99d5fe875576809cfdb038de2e3a10b367570d19259b0004a51fe2177807f49f3b0f6e76188cd622ec66f7a6b461000a7554a1da879ea55eaa6c3bfecda6e767fe6d2db7b81fa3587c75af85c800529ce6061764ea55fd23f42d5d168f5e5103a7413482d8f7ea7f4d581cf6cf9704a61843d5ce67ac36ea80cb831119dc51a72f9426be9a940ebcdab7c5ff1ef24337f47ac07aeff6411e92381b05c16d7e1162f2fca42646a3e23d9db8eaf7d3fc76d7e1f80682a4872b98b68600000002b1e81e9a5bf198a5b586123b8671f4e254562fd9bbc95d92673db997d63ee1e477d994c3609726106f884c462c5688228206e3a114395351a02875a4dac9b97f7cad6d3341b181f83a1cbdce5b786abf3eecb76e35346adb38b881bdfc6208c9ab85cdee9abb7e72cca871f997e9919ff2386b11d5a6f6d07fb12a920cefd29951308c2648acac42002f2cf2fbc7030bb75264f3f8b65f9bbe7ca51a65104507587bb5fff50a32735075cf2c0af2823d2138ed084e997d7b5eb24daa37a0107c19a3c62773815b0761bbeb602678ce99372036d50a0ce9aafb60ca53ddf79abd670629f85b03aeeac9ac0c1fe3ec6fe5a740480e6967d14f3c724a37fe7eccf60487cbd29bfc97194ed8868ed4e458c7b2bf8ab6f04efee532502cf588c4f26b9b2830baa635c56857be5fd6803fd35d508881bd7cf3b5872ff84640384e2576bd93d4d86fdafcba2df3f29036491573031ede2ddb09dd092ad890a68f07876aee927ea64763b555e66f9fb8bac9736c980cc0212e4297568cbbd9f176b87a2bd896be85b0cf5b9f93f3ae357dc98628ec97872b8121d292c9a7604b5a1847158b6516cbc6a981db892c3e393f10017fbb0f25f5d19a552b0ab491c72bc31e02f65d33e813b5bd34ca687b1445f093e49de295bfeb88ab8b18bdde68fa2f303e15576f09623f3f777f1d893d8ebf6f70319166ec0d9b6dd9b03a4d3b17e442e50c0e999d85d12858aec3e4c4f064f361106354da178ed23306a9d2df809b7a24d9000000028d5f9bf753813e60dd51f1d3b1e8235e02a3255261cfbf943cbe742258aa53a95391aa3f1647cc57b0b08669aa68aa16b32058a6acabc078c869739b15926a4082052beef36699c7ad836052b5e8c650cd6397630e040ab780461f0fdf2fa0c3a92a85c891d20678c7d3ab33fa7cc1fc46b3fe867032c45571ff9b362ddb435473c67f3705b4183e084d146aaac142a9af3d2132b388b43b787a5a1dda09f26aea25751f35f9e126955d1e2e891216bb619793884888a2dfe01404c5c351b11624c040a922a5afb725d54f53e37e22e38915e0bd259765b2f4042fa21d729254547affa87481d84acde598335ae95b808090e2eb312f3ce226c6c769abb356b002b387e119ec10c4a8963ee52710d75c21710881bae7fb5a8595fd43a9156419f8080891e50139bd4af14f1ba25ebe0152b5e83d115be493372e147742d8bfe3a8269e8ecd27ec055a11055d5405192cda8c8db528f06b120fc2e3f4708989741190ead61047bf5b56b148c774b623cae87a946c9ce873182459ca761806d5a410554b7476fb858de0c44f278517ba6375b4a8a1d03caf2b01227f62ff59564f2e5bab22c94915b00054d5719e435b12a0a9016c2eec51d955ec1d3c69090dd5565455a25fa58660bd48504c20a1f4d3335c594cf183b7746853ca6e23694eca1123f6e1df454df40795885059bac7f0bcf048867e236a7061f75d9dfe829f1e0c12fa79c29596bd533287778fb3496abe63c085588dbc57a551cebbb95043c243000000078fde866cf6617af4f383a63d44154c9f6189c992ffda30a27163e652b699a63f0b89f93a9f932509186d4fa3a6ded4f7b3fb0b926d3369ebab5bae7df9b7a1b4933197461756d80adb3695ab32dea2b72e91e7bd7e2fbb4aa5786871f70878489971107a7c6a9482fe798abceffc48eb9c47a078daf3c856c82253c33e5b3bae5faa903941d017af9ad6d48763528562b02b5b964e3428fd73605dbc53c190974622195952500837b0fc50ad7610d1de20e7e34eb4e52663ddda4e33a141102885b35f88b5859c7c3ffc460f8726b20dfae6942cf4c521ea5c4017ba01df60ef390f463eb436e69acd26c5cec0dd9591873f6e812ea57886b066f41c5d9c610a9f4ccac74e6ebcdb4889a53e504cb81531588bf2e31bdd7c4701cc57a548190db37c7b39c84741a294484ba2dbead64631e23f2e5c9bb5298118bce737198418d2d71d33973c0380e1f25622eb87b1d5a7ddeb91f5eaaa39b789deb952c81a61c90ae6c5f75d49755afe65b843fde1eb5c0ad15c5f41bf648787422dd91ae1438b88f40e94d2db5989634ae525c8b1ca063b507a4a645f0e6181614fb2b5097913e354c22d12b4283285ae113698d1fd849f270448420847c6aafcc1e4d79a063eacc2a175763d4542ec7b13e6be21cc04323bef585e2f09906fa12866a729809663e47f9803001ee881c979276d6eb17b55b455c353f47de2537cf3e97ffa1c466a83d4a2fdd6d65fee369f3247108cafdbd549cc37799719ae438f4d4313f5a259c68c771e6fc3c55def92cb54d932f12a82dd6d08fe88947ef604fda8863d89ed5df9ed6026e3cd0cc63f3cf1192a6b504f9a918956c466a487974ae1b9dd59956fc7a7572c0e6a6af53b00e094e1b33fea24e10fc3ce2c0be6f9cb0297bab67ea4b0a2578d75a0c6b167d61d179c8002de4370ce420a3e2c4d0445f3782957b1eb8c19c797c9106035ab0193e840dc0f2c5817c66788593c1c9232c3b9a02ad195945ddb7fd2efadf555a255726c2f224b7288958b6a6bbb8fd51d98435701", "type": "ConcordiumZKProofV4" } } @@ -1328,7 +1328,7 @@ mod tests { let verification_audit_anchor_on_chain = fixtures::verification_audit_anchor_fixture(); let cbor = cbor::cbor_encode(&verification_audit_anchor_on_chain).unwrap(); - assert_eq!(hex::encode(&cbor), "a4646861736858202b89c72a01903e99004e7968cfea1ba5a00980c04e09f2f6d60590a3b49839ac647479706566434344564141667075626c6963a1636b6579046776657273696f6e01"); + assert_eq!(hex::encode(&cbor), "a46468617368582040a6771bea78e282222f643165b24f9b46a6a8a6648baf862356e4246e9e8d35647479706566434344564141667075626c6963a1636b6579046776657273696f6e01"); let decoded: VerificationAuditAnchor = cbor::cbor_decode(&cbor).unwrap(); assert_eq!(decoded, verification_audit_anchor_on_chain); } @@ -1358,7 +1358,7 @@ mod tests { let verification_audit_anchor_hash = fixtures::verification_audit_anchor_fixture().hash; let expected_verification_audit_anchor_hash = Hash::new( <[u8; 32]>::from_hex( - "2b89c72a01903e99004e7968cfea1ba5a00980c04e09f2f6d60590a3b49839ac", + "40a6771bea78e282222f643165b24f9b46a6a8a6648baf862356e4246e9e8d35", ) .expect("Invalid hex"), ); diff --git a/rust-src/concordium_base/src/web3id/v1/proofs.rs b/rust-src/concordium_base/src/web3id/v1/proofs.rs index 3bc4a89c2..edd0c0e8f 100644 --- a/rust-src/concordium_base/src/web3id/v1/proofs.rs +++ b/rust-src/concordium_base/src/web3id/v1/proofs.rs @@ -1774,7 +1774,7 @@ pub mod tests { "issuer": "did:ccd:testnet:idp:0", "proof": { "created": "2023-08-28T23:12:15Z", - "proofValue": "0000000000000006010098ad4f48bcd0cf5440853e520858603f16058ee0fc1afdc3efe98abe98771e23c000d19119c28d704a5916929f66f2a30200abb05a0ff79b3b06f912f0ec642268d3a1ad1cdf4f050ab7d55c795aa1ab771f4be29f29134e0d7709566f9b2468805f03009158599821c271588f24e92db7ca30197ec5b0c901efaadd34cca707e56b9aab1a7f14e329816e2acf4d07a7edf1bd6b0400af07a1ba7a22bcb1602114921a48fa966a821354cd0dd63a87ce018caccc50b56f2c9f55a062cdc423657aa5cec8a4c9050100097465737476616c75650602aef4be258f8baca0ee44affd36bc9ca6299cc811ac6cb77d10792ff546153d6a84c0c0e030b131ed29111911794174859966f6ba8cafaf228cb921351c2cbc84358c0fa946ca862f8e30d920e46397bf96b56f50b66ae9c93953dc24de2904640000000000000004a547c8619f3ff2670efbefb21281e459b7cc9766c4f377f78e9f97e2c50569a8dcb155f2a502e936d2cb6ef1a73e92af9916e6353b7127d55bb525cb18074b5ec130463e03a4eda583b05c2d63db40a08ab8bf05f930ec234cc2f788d5f5bfbeab3e4881918ce964ffd55483219edd435ac865286bfd313cd834aabfa8061d2ae173cbe4b59ab2bda78faa4c2c937afba80d7fba0822579ac0ef6915f4820f968a74f00ff5ab74e90b0a7bcb2b92093a5e94a54aea1d48ffd1e5bb3fb48069bc9dda27a50094cba9bfcf801e64dbe683c0b71926a7185436e942f8c8077566b3000000050000000115726915418468b26d6e74190b76915057b8a4241cce9c45ce7fb9eebadb10380d3c58996247f9589b75d980c22cb52bba4474635acdd36ca9608b03a4fa17071d2475f082a64d60185b4e66be4c25d82abc0da2539127a03835c23c92cbae27000000023c9d71ca25a598cb0ea22848c766906ff6ae52cd30b32e0aea57905edf89c7a06c424eb85df08da398507bf2a2d60873a927d42479a08e902c247555b5a54c266c4447fa40a7a8c1f693e71a628fe46d844ce6a79b9a76ddf5a3c682db641dd900000003687dde67f4bf5a0a89cf32468d344b296f8f243d6fa5946f96c04c2e9aa506b14330a6083226b65b55c3cea3985ab39b60b8d0db1bd812fb2ada6e14288da2fd07db10ace62993c934944bd63b11a0b1c098059905a6777970d04365c085d1da0000000409dcbd1240c0fc6eaa35254ccc5cb724442bbf38c7c1d37912b1fcccad403f2e2a68dc38582ba48dadae94def9b6bcca09cc8a76d1fe7d6a76e6891dfba34ba55e5cd0bb1bc71976f9f85768b82bdfe47664c6e2f6e87c4bc836c898b4fcfe780000000538f72551c6300c32bd3401901113c1a0de21b6c411f7b23dcb0978021c06043e27a762ac3f79325a7da5c92520bf30930a15b4f8e1f8e0345a8920944def95ab2244e704856d61cc42dc2b7765939b408f73150f0bba0069d43a388dc4b9af4c5adb834750b09315c12cc625f1813f9417f72f6d367f47585584c45d6471aa6d0000000c000438badd11174560b10965889ef2a5e06c7e10a049b1ca950b5641a7a6fa0d2c2dee4aa278a8d7dcba3625824033c4bae0c8336a73afe374f1366b8acec0b22602560a5a195d54241d9307176e66834046001a5d73649e7fc557829d89d897855701010102338aa101037d164c46e745fe608dd7bedb3dcc66eb8b6f1fdd0b6843e7260c3200198b0abade3d91b3a0dd7e23cad15f1e671037ef0a600b882f6b832defe318db20dcf6376d42d73fc9db0bfd4fc2c63110951792167ddddc89500980551f9bb70049f2851c9793009b5eb009d32a102358596a79fa951176c475e1cce3ab454c4064269569c392c56309f2ca90b77af6254209dab87841ed35042a44270ae946cf00496a71478e437a843beb8e522295c9b3479b4a28b77dd624268693eb9538d2ae5105514841b593230dfb8c64936082a79c76e0df7392049895001ccc0f81739d002e3175e30fe6f0eb0ef6ebcba037b75dcace321379a487be6db7ea03de3fa5a057cd6a8a6c24a45847ad6941fc7e3c347a39260427c7f413b95821064aff6e1a01023cbcc2d00f1f28d79687747b0e4fb70b22319e39fefb76a90ef22e021f96ff55000000000000000502803596b4ba5ea05b1fea2b78e292f935d621453cffcd207e10f3072b2813ca3e963cebf05b19cd82da4bd5aad1dcc7fda1492d7ffc8f532bc4b37e9bf4753b7ae6b8f08e05a851052fc6ac7617ce68293678747d11f9a508bab6f7a60edde9c4b092dd34e11fd7dd65823bd9a28f6169fba00b9b82cb9a8e149f43421c17a98aa5d382d05056a988c0956d330ff55f9caf87e8f23f45b9c3fd46fd17de35b9288ed1fde6fa48135fd76e331da22d2ebeaaa90098c9fb5744358a77cbf3a3043f51203db2a0423969266759114978722c077c55d02bffa1f76c8fcb85395cab013c3ba44446b18d561753335da9236fac7cb618432492eb7d992d699cc240456120da4c2712b9a44b640af2033485fd918ae817e81cf0e26057c66371f1b2b7b0000000079580daa7ed6bfd9662c47231c3094a8f96c2c25e5c0eba5336343eca68747f7e9918ac172c2211a43438fd47b136bd628ff969687ca71147490780b44914c168c007ed619431b041287d549fb96d51e6b41e7c28eadcfe553d53b870acac4594a6010d523918c8862810fc6c8cde78e3e5965735c1d00f0ef9b5cc4902ae52ec62010d0f98b9d07c78a3ae3eb1676f56b07a0ab8716ebea736ceffd92045eed660158cc24864a23b5b3e0cac55c68051dffaefcdaca795ff97e093d901173faeadc00b2053ae59cbb36864862c30bbcfa5032e1516590e380c2b5073cd1bc3e76ae8f8dc4edc892ebbe15805271f98c0ac22ef9e0daecde89e16bbf0f5e0206c32a54ed875a3de1e86d560f615c8c6cca5fe74d2c096003486caddbd6185b859b2502a5d05bd9ac863faa0a2ca54eabe1fab68df7086d78a486f688d4419bac0ca6b29288d9ee95df17e27d269bcff0fa521802f55a178e6189c4fc4e0c9aacc7641935f9750f7af0aac001a0efb0e2436afe8d40637b5f1b40858878bfa5ae8a017b3217a716ebdf27a1723a93865fe088c834cff4c2e27ebcac37e3d23b7bfc4a96f4d0d3e1ebf1f13ad4a81f7c73482802590d0c0dea55147cc163fbd143db10aeb8505a2d9ee098a6c47bc41fe032d729becf1b7131249773a9efd811e9caebd1d72658785b32470eab5708287532a4a4a4a91073b5b77e693c393ede85f4d23c77d4e7accf7460976f7ed911d9090748eb9498c76bb8ba173367a5963a938d8c2173d20db10bcc7c452f1f19f93b31a02b6f24794413dc183ea2bf157388d22397beb12e6e4a626ab32e6740a0c3d9bcb49579c27a479d5cf6f2d98b1227c690d734161166bbf9caff311f2c504a4dda5e53b70b8738b18dfa4fbb5ecd0b074885db065516a7a19b78c63dc1f5a72a8b843b5ea3c1b49feaccfa55216a81dd028a44797f262a0b42d1e617490f16f575f44991cd02f1a679d6695a0137b02423d96ee162d768f0ef1c74980e5728bfcda5fa69d451e3a64dea119b16aab039035240c33b7dec4981aa53e914f67ac932328b31f3fc4d0aac1c19a4da4dab1b525a63008d0e40b86076a1b7e9f0f219955c76798ae8d5131eee35e9900c5cdc8b58badd7022044521d7ad239a91bb2ae1a02fc61472f7d3629d14070641a1e8106424aff358bd337af5576ce1a48243e21c3b73051a87b7a914ef68645f82f5c2b1a8af8def5d639feea0fa02f625f9397619ff9538ec5ca1238e7f26451a7036e9319fbe3baadcefe0f09d32a37cbc7644b92ab9e984304fe7ee22886d8e7331b923ccea38b31cd4c5b6e21ea7b13f93a74d2e4e5c5abe8f48efdc901055541e152730c07ed5c80c97a3538602df6b37cbc864618781c1728ca3d13af97b33e922b8722a17d7b3397dbd604ea26446aee03488924d55a8dca65731db96bbd00000002a753709610f96d22afb715d26c8586d8971f9201ba327d6eb4a0ff5ee0943f81f7eef7901d85fdd59b18d825b64accae87447036ee703852251d2b9d0d9add516ea1c1ac8f68168e881c4a6ebfb1f9c1c7e7098b7aabf9e0a2efa2423186f7f4898dfca0ef6f07fdbd180a2a164d21b18b0424d7f7e9c93d326e3ab308062bf644184b0e76e3782b27de5b4b971b127a904946ecd4b94a21158d8ffc0f040b6dde6f044dc084ce27a016a1677099f3b335237a19623edc4940193bf706197b2832e1f8a77215de4dc73fab8cf1e1e090f57e5db737174759e3434b4da5feeefa41be4bf511821326cb664dcb6705c926e135c0de63e86b3c0fb1db02a47ecda00487cbd29bfc97194ed8868ed4e458c7b2bf8ab6f04efee532502cf588c4f26b9b2830baa635c56857be5fd6803fd35d508881bd7cf3b5872ff84640384e2576bd93d4d86fdafcba2df3f29036491573031ede2ddb09dd092ad890a68f07876aeea30b4541acc1c039323dfeb5a8bb81396cee8e41a591c6c559f24181b3f1d9a1cf386dbbc74e601480099930464fff2f820ffefe9c1754ea7220ab4fb95a73bd217f7440d26d803077031d039a09f366221c1d60f761f70bcfe592e099e41b4a5bd088cd1ece3af477e1d13f03c1459ad22b42f3479f12d7229de52d7f4ef95c689a33ade597a8902964e244e6cca0d1f94de905f9fccf95b774ed2b8c2a36f061f3a8da53b11d71d9855c79face7dac770caf93e5e9d7fbd6b2907f994bf8e6000000028c27c3a9d06054e718d61e0c97597c3e2aa2fa7b372b61e37fd02004a58cd9a9db0e4aa75995de479dc528369aae7850971c7a68b793ac91d3f8e31fe12200a63cd651d0fef437981c041f1417c0a7b35ffc2725f19ea6f47b2db483ad3c28b1ac997b445bb2fb55c276fb800e331cd8a406efc9074101a3b477df4d1fa187a27a07e58e3d0a5fff80d9c33f5b0d9f0685a41e8378e99fe37e7376290d971afcd3548fd6e7ab783c338558a58c7f4b17b3f2f19892b8fab86f297ad4fc25ba8107bdfd243161d90f6439adafe37e70edf6d318489571acc3761f12ca134dd42713dcd3d4e4bf11bdbabb6771a1d11f406969ed4f1b3dea7d32c292ffa07a302a02b387e119ec10c4a8963ee52710d75c21710881bae7fb5a8595fd43a9156419f8080891e50139bd4af14f1ba25ebe0152b5e83d115be493372e147742d8bfe3a8269e8ecd27ec055a11055d5405192cda8c8db528f06b120fc2e3f470898974118b864ba4ea9442144f894abfdc952071f586c663ee9c7daaa100295213bf22a96b9c2562d7f4bdbc878e59a5dff96d1793ff7a7819b528ee718513bcd5d6f44cb1ff1433d4a6a72d95a3e9c2f9bdf179fc0d999a689ba5f10717dd812bef9cab61b118dfc80d1f16fed604130e256bc3cbbd4a3f9e7aa656e685d9f801845f043178b7aad99f9214e790c31939f6b85e3d876351377a3d57b3c85d84876a93fd039a4ff13d73c3564d8cd9c4310b4e7bbc27f907b10b6f95c09c853e6edbb84300000007ac2df00a78778a0e2e4ab221df2686305b7c4f369c9393d83d2398442fd650d3d49a9171e64b20c4b341e8c5f0153bab845202926b803c5eef4d10937696d1f2917a5c1ddfa86860b780c7e9cdca49bc0c07973d1a2a77fa6688176e3c88c933afc37a04d49778bb6c3eac0ef42a67cde86dbee2825f12f848ed2383af2da472dde4fc29b9ed9267480363f587f5babcb86c0965845495f3b5cda6f3cd5d5784a3123b89a74b7732b51dfbbfb28cd9ea0f635c4920711cc8bc9512154ef679ddac1730212ea8cc4718c1085583c5c40b964f1aa0689595a8b6d1869f23a8d857c68251863f5c3e57c62f73d40090b437a337db8b01b5b258f5217fb81b634edea1f942224a7d6bb9124272a99f038980976a8df52094c62fe7dc6a07cbe2e67aa413ddead30ad92e54c0cdc1b915d2bedfef9660fa69b513736ca221fa4bd6ce054c90ebd9ddae7cce9f0c02630cfe7f88f8fec518d60cd79fd9f9acd653b8cb8707dc463eb942faf56308d8afd89a5d1f690a43203cb72049183431d0e291888a344544ea7d38ae1db3ee49d6d9790e1baa80abbe54db280593b9a7f632a0bd9298cc93f298b8b0a7b91eaddc1856e2ad00c721bb2099d944fa0a847513fa51bfca7822fb8163794fa28e8bc9712dc2f2cd5b6f53c66dd8a536f869447dbf39b4accb28dcec7de58ad83819bcc4ab0b966b165bb8e0bfcb30a6280e588cac873e9b3919a8bb8c3418f4cecfc2e14e60b47259143898aeb7380ef76d93c8e5102ffdedb793e49f23cba70e9ec04475394fffea2d0c6273730a101314589fc9c7ab713604443a0e8c7816d10d6581fa30fdb1552c61025ae3e85d46e7dd38e90d1a6d8d4921c806d9dfc84a7a0497335c8b9e4be2db89512fd2ca332ebb66ec302da2ab68f2a40cf3b957720348b7ac5414b9c7c3bf05c88fe606a31b69b5d6e606a0d8dce4c0952d047fec38e28ef722bfae923ca9104f1742f1df96ef9650543e19d25a3b6e8f93e0ac26841120c46cd416e9fa4a111b1ad3b8a171033d26a901", + "proofValue": "0000000000000006010098ad4f48bcd0cf5440853e520858603f16058ee0fc1afdc3efe98abe98771e23c000d19119c28d704a5916929f66f2a30200abb05a0ff79b3b06f912f0ec642268d3a1ad1cdf4f050ab7d55c795aa1ab771f4be29f29134e0d7709566f9b2468805f03009158599821c271588f24e92db7ca30197ec5b0c901efaadd34cca707e56b9aab1a7f14e329816e2acf4d07a7edf1bd6b0400af07a1ba7a22bcb1602114921a48fa966a821354cd0dd63a87ce018caccc50b56f2c9f55a062cdc423657aa5cec8a4c9050100097465737476616c75650602aef4be258f8baca0ee44affd36bc9ca6299cc811ac6cb77d10792ff546153d6a84c0c0e030b131ed29111911794174859966f6ba8cafaf228cb921351c2cbc84358c0fa946ca862f8e30d920e46397bf96b56f50b66ae9c93953dc24de2904640000000000000004a547c8619f3ff2670efbefb21281e459b7cc9766c4f377f78e9f97e2c50569a8dcb155f2a502e936d2cb6ef1a73e92af9916e6353b7127d55bb525cb18074b5ec130463e03a4eda583b05c2d63db40a08ab8bf05f930ec234cc2f788d5f5bfbeab3e4881918ce964ffd55483219edd435ac865286bfd313cd834aabfa8061d2ae173cbe4b59ab2bda78faa4c2c937afba80d7fba0822579ac0ef6915f4820f968a74f00ff5ab74e90b0a7bcb2b92093a5e94a54aea1d48ffd1e5bb3fb48069bc022d40f10bd9f0db027ee76e5d78722b22605a1f420c0d8923f384fd2e9df4d500000005000000014996e6a8d95d738baf684228c059ffda43b6a801240c467ff648b24c1e32a8fa25e6348ea46cfe7a6134f6754367715ab1fa97f963720164fd4af47882ea5f5c68917936ca63783c8e7252b3add6d60427580f639caec877eaf62af847e260b0000000022edfd6a9b5f6cb325c2ddafc2f37328768062360b94ff89b795eefc2bdd8b8c7566f982f3189e2158c9932e6c2236beae9c4a1767de64235066fc668c43590a466a5e08b9552ff74c7850795edfb41de40a8183b3ae27e25e14a851192492649000000035477e4693d1f65ba2c6d911de408be4b4164ae853b9d944859a7125c7f80c8b6737b58adf891170ac056de0907671899121fede2fd7cbcd6c266fef9d011baf65e6529fb326268ad4394ac4bdcd594901d2d649c9633ed273d47472550a6ed1d00000004636f324e0c8d9958f960f621ba0bdb0a12c2fdac465fab6f3d6b0219edf20bda34bcc475e9e940e5f2c166aab81bb46a24fe84a7c150f60f19b25a9aa26b02960fb8204657da982ecc80099255157f127037fc1d01bae5e751dfd1b568d5d3b2000000055252326e4bd286ff449e1e4191ad5bfd3834498357850252b2efdf71e5a195801b0b139f690a241db78ffae798e90adf5468ed485dd47c396dafdbf95846ab3f1dfc26f4044279839a74ef3d99d3e683ddfd948707a841052beed7fa59d3cfe10a85e4f590f94aeec5694aa34ce7809e6409635c3dcc06c48e2b6eb7c88e805b0000000c0044de5e492f26cdc8d9dd7353c8f4561776db5cf1e9e56765f8a27325bea23c7c6e93ee0e96b86044e30a334d6a3574f1eb257fbc13e38045de829d08e668e1760233b357f18e2fb13b681affb3100a76389289b0a672fb4c018b496086e907a8d9010101024a3c3d379c549361b01f1da35dc354171e8b08e37cde8b26708a7d0a74a1c475001607576a587bc3724829d37a211c4e7ac685f5d2ff8d183878c47761fa207a2772c92a29d9723c60fcf02a5f3ee44f16c8d719ef0ff7306017e8abcca0ac43da002c1306c3df6c321d1827b482e5bdd43d9ae0ebda13ee87f8ffce45b9280974d30da67ed93028333a98441ec283b84ef993ba16ee3f63abeb6913cb84c6087e520031d913edbe710a6ef608a7496ddb24b62af6dc53b0c400515094a102dc34ba7e5101b14654477c70600fc619c536a55689a34483d87a607c616b8e4a7f588b1c0020de9f2cbea7cb077e1dc06c4f2f3286792ff9ab865d04a264699b063387d3565a810470a1a3f0b94ed0a313bf2558035cb562112fe9d4ce3db05035da60dfb401023ecf78fe04bea07742a2b68c1dfc848ced58d50cc72e3aa9417456c137f07042000000000000000502803596b4ba5ea05b1fea2b78e292f935d621453cffcd207e10f3072b2813ca3e963cebf05b19cd82da4bd5aad1dcc7fda1492d7ffc8f532bc4b37e9bf4753b7ae6b8f08e05a851052fc6ac7617ce68293678747d11f9a508bab6f7a60edde9c4975a76ced40574074001091721440b1d62252454c2b26494f5014ef4b5f0adaab23eea032dabcf7fc274915ed26a38ea985468e8f27f81f378870fdf0c9fa880b75d301d54dead22ebe69d98305b8bcb1825f77084a3fe794ef69ae07ca2f40c327c3b8055a8dc2823524df825d4748e84c743856120bf5bc77826884412154e26cf2b601c2b869084806c5e670919b8cb8d6ea8f7a8fd14096f7dc9765bcd0d5a04e5770764de9318b0f4f5fd1343b30f0954656423cbb994da605956acc5e30000000792698ceb941b32e6ff12451a75d1eb465ca0710879a4d67ecf75ff5e614605b7284f07109a658007dd94b499322649a68af4e7b7ad848fbc3e2dfe248fe846d0836279a0a8045909516fa2de9ce9d456e68278372af302a891a3c138596bb369abb626f0e5ccd6ceb9d6f7f0bd979a37afdeff02c294ad7db9ad1335f0d532027bf7fc78c7fe3d1025bbd9b754e8ce068ef1e251727d48cb25040091f05b327ac2ec733c1cb349f6aa20c00f644a3f9c84df72112b4f4b247126df77eb27933db078a098bc904d01ce5de1be0fdb9d8796b3d427c7a89d7ace44209339c5577416dff5094858771314c6dcb8562f7d17a30c84630530510bff914ff0398b4616171386c23145d4cff3e4a0f698715bd68dbe2233b851ee49c17c0b7dc9b6f5f4ae461de98c4d582c8be6f490e75a0c2b1a61dfca366e86ca6ed131b93d43c93292f6182cf3d86e98d0baf613630e7a34a54dcba10f680b641579909c138223182443f71f110d7eb97d0bc99c795d95f28611ddf484208c3aa9763b517024d32faaea07a4343e4fa9b72ffb951fddd5e811def887a8d92e89c574d7820ed46df10da13e63ec1223d2bf1ee4b8f6cd353eae032fd8b3f6f886d5feb3032ac2c6cef1f03513e04646ffdbd0be6597f674bfcbce9f16127b43aa49f4e6853c56e2cd96c75aab089f07d04515e52a097c1b08c75ddb30315af1d65aebd00585c3818e7587baa5b11b80a0fd5fd2e0b7b473c9ad112a3168aadaf83ba4d94ad7e6b47c639684d634fe5ae59fc1f9e6741e924bdc8ed49c2a72bf1e7869fff80d17a7a0adacbf2123fbed51683d0897fd76310f3896381f47c675764b6475a027f92a0b89d863218dce9b3ac48524b3d1def4f0877aeab34415a27e33d305e9ae39dc8c918125498ab16932378e9f739bd2e0c4866265ff9f98c7b562000c762254336c3ac576cdfd96936c3f32ded9523594401d0ad2f2232a01b9c8443395180f1ec80a119e63e0bf631cb93a9db4ee6a2a29e06f520835f7af238e1c8cd873bef1e4039035240c33b7dec4981aa53e914f67ac932328b31f3fc4d0aac1c19a4da4dab1b525a63008d0e40b86076a1b7e9f0f219955c76798ae8d5131eee35e9900c5cdc8b58badd7022044521d7ad239a91bb2ae1a02fc61472f7d3629d14070641a1e86c2ef60ae3a42de23a15550c75b135a7be766fc38a2554377afc4892fef23e54ad59b72bfa590493d3a0e6d0c3692f9b12c28a4c2fcbfc8331381867935bdbdbe83220fe2330b5024ffdaeb37eb9a4f8dc8505ff846ce16a24ad0f36b8145591838c8cd056b4fa56d76e3f0d3c04cd58a13fc953ac12f292817ad4c1b46d62e372b5a5f8c7f3a4dcb29beb03b75d7b9d0a4a463e37f00da224c7fde6d34c3d53f34ac41a47b698e9b381d0debc448c465c594d9cf9c42e8cbce7e0e03091000000000028f08b690d86821cdcd517648214e22b5b0b73e2c7f82a3ccae933d61bc0e28fc69b047aba5cc6b8e9e6f4578e02924db920fdd2cbc3f1171c98169f4fd5676b77f210f9ae5e949afab54b2e52137538906ea05c5fc5e0ca989eb081a3ba9285ea611a9d69bbefb08d3142a7523a3ca91961b4f6deaa87286a4fe776607572b5db7e6ea488c5b9007731663b4537b584983937bfa8ec12bc8f6b1ec8185cb2863f7dc15f82f50978301f7441901d2921799af71fbf5f3a83162ddaed844b5647970b4bf4cb7d8bae88457f65c2e5f09b71b6585303e4783642c20949423fba406002407e6a58cd57836650e76df878926d0b6315f4c4329385566667701fe7f820487cbd29bfc97194ed8868ed4e458c7b2bf8ab6f04efee532502cf588c4f26b9b2830baa635c56857be5fd6803fd35d508881bd7cf3b5872ff84640384e2576bd93d4d86fdafcba2df3f29036491573031ede2ddb09dd092ad890a68f07876aeeb5ed24f1e21e96aa8f81d1b57f7963fdb0d617a6c302365781dcbe1628103ba3e9fb7c05ec5064aa5f518a2dd54deb3bb6547660749326b8e7c23931f938d1f94b2b199330c7cf4e21caaf3586b5ce3f56d5a1a06a78729f9e8b7838eef1f95828f2e1f46ccd7642fae51f13d2b0d6c55b328e0d6bae6355d412db989f82a3fa47b167da18c385588da0d8b2715d09c06cb2e03a1bccf8e112893d054c79b8d850d3c90fc8866865a2f85a8b3f64d9dfad1381b1bc0653335ac741925dccaac600000002895dca7ed412bae0cb70d758773dcfbb2254c95be80f230ceb3a73883bd6b6220cff45b7e9d058da58071acb8a32767b99a869379b6095f4e2b7ddecbd8a4d17a094f9681a4345c35c87dd86cba4074e56dae9e1ddadb7edfa248058f12f8f0c965d922130d696027a12fdfd06b1c39c7fba1875b39f751be361ccf330dfcdfa68623eb78747bc06f9ac45b812d5d313abfbfabdb4411220d1e78b5384749bb890b3f220139e0200315d516b3fb2e156b2a5c1c2a081a3e67eb6e8fc97be9bb4439a9eaadaab8e29db023baa98322d0d0e7f06efd708b5c7f8846e799e8607a20242d81c399a6571f8ea9c203a534ebfc6bf416540b8ad6a2c82e66dd9d2c0c502b387e119ec10c4a8963ee52710d75c21710881bae7fb5a8595fd43a9156419f8080891e50139bd4af14f1ba25ebe0152b5e83d115be493372e147742d8bfe3a8269e8ecd27ec055a11055d5405192cda8c8db528f06b120fc2e3f47089897411aaae9e0b0179b2e09afee8e5d56ea05b85694d71186f6d6dba1465c19cfc41f55751c1c7e3e071f0a97733f2ad4a8d7eb5038bb97411c01f77d451d483611c939f1910f388110198c69a2efdce02ad2334a1c39958bd66abb940ef1f42143a65010e383128f291e962c579ec7cb9f24f373554e84ce1a21f459d5ea4ab1a41ec733322f9b95611de75450bf415e60dc15f8d33fdb61f14d9c73c92cd6ace0943403768e8947e8122b2cbbc663a5373940daf22b914730c980c66e87e444db56f000000078c1751517b7f76514a5ea7af097099c03cc64d9416494d5a9f448c2615903650ab7c8c2358619073d84f04034ba7f768b62b4825d8a12f4c0378b2b271eb05f8b3cff514ebdae3b6de637539305437c2bc0bc6c2649961a1d22295035d07f460863a3d0467f01e79c4199bf3dd73a57a58315be6b4e465e43fe66e82dc933ee622598672fbd0c5bae12d8e187c7a6dc8a2c4b3dc57040a759e23594760d76c8d6655c0860e4a1187e89d7451b1507bc5e0ff3eeb28577af943a44afb61d96eca898cb8417551edffc189fe2d24e83f554206c397b80153044e45be32aef5b46deff4625d1d316338bf3521ee32ef50388a067b5c0972ca68797b98b337c09589c307d5adfac00a524ccca6d8d5450a0eea765673fbea3956aa0edf0dc0a2c7318dd61540865a408715c148e406489f7e56d953af3df90585b2dd12e99a4a6878009001b62f9fa0a023041fd77f41be2da2ed746a07bb3fa3864ab5e76be4f98d480fd97280735eb9f44c6bb0b1b02e2ee8c9d1c71c68de3325e6d14f44ef98b68b50ddef96b312c9a17296ecf837591659252f25670d9744c7334abca978eab4d7c40276b876ca682c2c06ba2809082d842c021fadb934bff19025c4dc1d80f6a9fac3cf59a7209c1d73113b87b8d34a8d618a5534db6fbc4492cfb6439a2c088cbbd44febb15f56e1d119bbf1e2bd108325711d56938eeffce12ecc900059822448666fd380701afb94887ff3a73d5ab6e3a9614ec319bb579d02de414db8a02d54f80928255dafc2b7833159aab87daffd5e143e7e939ec2c05496573f7de1aa46492cc29053e0ab0d7a2b524b3cade5e2ee0fbb0aa8f0b340cf139321230da9d50df0e36794ff03927ebdfaeb5b4c88612f9a7cb6660d8a088433ec92cd24ad06e4bb75885b0b7103d524f4f6b080be40484b9138278d95feb40af1c52cbb29f7623675d081c0930866586fee0476a9f21bffe406e3265413f792e0d464e9476becd32bb6af4856aaf4dfdbd6f1a2fea4cbe6df332e324f091fa74e7d9cdf01", "type": "ConcordiumZKProofV4" } } From 8dca9f7abf8a0670a32001fcf7ac95b2637ef517 Mon Sep 17 00:00:00 2001 From: Allan Rasmussen Date: Wed, 26 Nov 2025 14:46:38 +0100 Subject: [PATCH 16/20] fix --- .../concordium_base/src/random_oracle/mod.rs | 20 +++++++++++++++---- .../concordium_base/src/web3id/v1/proofs.rs | 4 +--- 2 files changed, 17 insertions(+), 7 deletions(-) diff --git a/rust-src/concordium_base/src/random_oracle/mod.rs b/rust-src/concordium_base/src/random_oracle/mod.rs index 5064af924..e4c6bab2a 100644 --- a/rust-src/concordium_base/src/random_oracle/mod.rs +++ b/rust-src/concordium_base/src/random_oracle/mod.rs @@ -207,6 +207,7 @@ use sha3::{Digest, Sha3_256}; use std::convert::Infallible; use std::fmt::Arguments; use std::io::{IoSlice, Write}; +use std::mem::MaybeUninit; /// "Legacy" [transcript protocol](TranscriptProtocol) implementation. See [`random_oracle`](self) /// and [`TranscriptProtocol`] for how to use it. @@ -577,8 +578,16 @@ impl

TranscriptProtocolTracer

{ } } +impl

Drop for TranscriptProtocolTracer

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

{ +impl TranscriptProtocol for TranscriptProtocolTracer

{ fn append_label(&mut self, label: impl AsRef<[u8]>) { self.inner.append_label(label.as_ref()); self.lines @@ -641,9 +650,12 @@ impl TranscriptProtocol for TranscriptProtocolT let messages: Vec<_> = messages.into_iter().collect(); self.inner .append_each_message(label, messages, |inner, item| { - let mut tracer = TranscriptProtocolTracer::new(std::mem::take(inner)); - append_item(&mut tracer, item); - *inner = std::mem::take(&mut tracer.inner); + unsafe { + let mut tracer = TranscriptProtocolTracer::new(MaybeUninit::uninit().assume_init()); + std::mem::swap(inner, &mut tracer.inner); + append_item(&mut tracer, item); + std::mem::swap(inner, &mut tracer.inner); + } }); } diff --git a/rust-src/concordium_base/src/web3id/v1/proofs.rs b/rust-src/concordium_base/src/web3id/v1/proofs.rs index 6c35efefc..6a9f937c3 100644 --- a/rust-src/concordium_base/src/web3id/v1/proofs.rs +++ b/rust-src/concordium_base/src/web3id/v1/proofs.rs @@ -1859,8 +1859,6 @@ pub mod tests { "verify request" ); - for line in transcript.lines.borrow().iter() { - println!("{}", line); - } + } } From 995ffb82b6bba5207878419792a0c40ffd1b0520 Mon Sep 17 00:00:00 2001 From: Allan Rasmussen Date: Thu, 27 Nov 2025 10:10:50 +0100 Subject: [PATCH 17/20] test --- .../concordium_base/src/random_oracle/mod.rs | 78 ++++++++++--------- .../concordium_base/src/web3id/v1/proofs.rs | 39 ++++------ 2 files changed, 54 insertions(+), 63 deletions(-) diff --git a/rust-src/concordium_base/src/random_oracle/mod.rs b/rust-src/concordium_base/src/random_oracle/mod.rs index 5064af924..2741f60c9 100644 --- a/rust-src/concordium_base/src/random_oracle/mod.rs +++ b/rust-src/concordium_base/src/random_oracle/mod.rs @@ -560,14 +560,14 @@ impl TranscriptProtocolV1 { } } -#[cfg(test)] +// #[cfg(test)] #[derive(Debug, Clone)] pub struct TranscriptProtocolTracer

{ pub inner: P, pub lines: std::cell::RefCell>, } -#[cfg(test)] +// #[cfg(test)] impl

TranscriptProtocolTracer

{ pub fn new(inner: P) -> Self { Self { @@ -577,7 +577,9 @@ impl

TranscriptProtocolTracer

{ } } -#[cfg(test)] +// todo ar also support with_domain + +// #[cfg(test)] impl TranscriptProtocol for TranscriptProtocolTracer

{ fn append_label(&mut self, label: impl AsRef<[u8]>) { self.inner.append_label(label.as_ref()); @@ -587,12 +589,12 @@ impl TranscriptProtocol for TranscriptProtocolT } fn append_message(&mut self, label: impl AsRef<[u8]>, message: &impl Serial) { - self.inner.append_message(label, message); - self.lines - .borrow_mut() - .last_mut() - .expect("last line") - .extend(format!(", {} bytes", to_bytes(message).len()).chars()); + self.inner.append_message(label.as_ref(), message); + self.lines.borrow_mut().push(format!( + "{}, {} bytes", + String::from_utf8_lossy(label.as_ref()).into_owned(), + to_bytes(message).len() + )); } fn append_messages<'a, T: Serial + 'a, B: IntoIterator>( @@ -603,31 +605,26 @@ impl TranscriptProtocol for TranscriptProtocolT B::IntoIter: ExactSizeIterator, { let messages: Vec<_> = messages.into_iter().collect(); - self.inner.append_messages(label, &messages); - self.lines - .borrow_mut() - .last_mut() - .expect("last line") - .extend( - format!( - ", {} items, {} bytes total", - messages.len(), - messages - .iter() - .map(|msg| to_bytes(msg).len()) - .sum::() - ) - .chars(), - ); + self.inner.append_messages(label.as_ref(), &messages); + self.lines.borrow_mut().push(format!( + "{}, {} items, {} bytes total", + String::from_utf8_lossy(label.as_ref()).into_owned(), + messages.len(), + messages + .iter() + .map(|msg| to_bytes(msg).len()) + .sum::() + )); } fn append_final_prover_message(&mut self, label: impl AsRef<[u8]>, message: &impl Serial) { - self.inner.append_final_prover_message(label, message); - self.lines - .borrow_mut() - .last_mut() - .expect("last line") - .extend(format!(", final prover message, {} bytes", to_bytes(message).len()).chars()); + self.inner + .append_final_prover_message(label.as_ref(), message); + self.lines.borrow_mut().push(format!( + "{}, final prover message, {} bytes", + String::from_utf8_lossy(label.as_ref()).into_owned(), + to_bytes(message).len() + )); } fn append_each_message>( @@ -639,21 +636,28 @@ impl TranscriptProtocol for TranscriptProtocolT B::IntoIter: ExactSizeIterator, { let messages: Vec<_> = messages.into_iter().collect(); + self.lines.borrow_mut().push(format!( + "{}, {} messages", + 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| { let mut tracer = TranscriptProtocolTracer::new(std::mem::take(inner)); append_item(&mut tracer, item); *inner = std::mem::take(&mut tracer.inner); + lines.extend(tracer.lines.into_inner()); }); + self.lines.borrow_mut().extend(lines); } fn extract_challenge_scalar(&mut self, label: impl AsRef<[u8]>) -> C::Scalar { - let val = self.inner.extract_challenge_scalar::(label); - self.lines - .borrow_mut() - .last_mut() - .expect("last line") - .extend(", extract scalar challenge".chars()); + let val = self.inner.extract_challenge_scalar::(label.as_ref()); + self.lines.borrow_mut().push(format!( + "{}, extract scalar challenge", + String::from_utf8_lossy(label.as_ref()).into_owned(), + )); val } diff --git a/rust-src/concordium_base/src/web3id/v1/proofs.rs b/rust-src/concordium_base/src/web3id/v1/proofs.rs index 19741e643..c7a24ee1a 100644 --- a/rust-src/concordium_base/src/web3id/v1/proofs.rs +++ b/rust-src/concordium_base/src/web3id/v1/proofs.rs @@ -1,4 +1,4 @@ -use crate::random_oracle::{TranscriptProtocol, TranscriptProtocolV1}; +use crate::random_oracle::{TranscriptProtocol, TranscriptProtocolTracer, TranscriptProtocolV1}; use crate::{ curve_arithmetic::Curve, id::types::{Attribute, GlobalContext}, @@ -528,25 +528,11 @@ impl> RequestV1 where AttributeType: 'a, { - let mut transcript = TranscriptProtocolV1::with_domain("ConcordiumVerifiableCredentialV1"); - self.prove_with_transcript(global_context, private_inputs, csprng, &mut transcript, now) - } - fn prove_with_transcript<'a, P: Pairing>( - self, - global_context: &GlobalContext, - private_inputs: impl ExactSizeIterator< - Item = CredentialProofPrivateInputs<'a, P, C, AttributeType>, - >, - csprng: &mut (impl Rng + CryptoRng), - transcript: &mut (impl TranscriptProtocol + Clone), - now: chrono::DateTime, - ) -> Result, ProveError> - where - AttributeType: 'a, - { let mut verifiable_credentials = Vec::with_capacity(private_inputs.len()); - append_context(transcript, &self.context); + // todo ar revert + let mut transcript = TranscriptProtocolTracer::new(TranscriptProtocolV1::with_domain("ConcordiumVerifiableCredentialV1")); + append_context(&mut transcript, &self.context); transcript.append_message("GlobalContext", &global_context); if self.subject_claims.len() != private_inputs.len() { @@ -571,6 +557,11 @@ impl> RequestV1 private_inputs, )?; verifiable_credentials.push(credential); + + // todo ar revert + for line in transcript.lines.borrow().iter() { + println!("{}", line); + } } let linking_proof = LinkingProofV1 { @@ -1838,15 +1829,11 @@ pub mod tests { let mut transcript = TranscriptProtocolTracer::new(TranscriptProtocolV1::with_domain( "ConcordiumVerifiableCredentialV1", )); - let mut csprng = rand::thread_rng(); let proof = request .clone() - .prove_with_transcript( + .prove( &global_context, [id_cred_fixture.private_inputs()].into_iter(), - &mut csprng, - &mut transcript, - chrono::Utc::now(), ) .expect("prove"); @@ -1859,8 +1846,8 @@ pub mod tests { "verify request" ); - for line in transcript.lines.borrow().iter() { - println!("{}", line); - } + // for line in transcript.lines.borrow().iter() { + // println!("{}", line); + // } } } From 572a61e88e0b8e6a49d33942a66321aa463b2de6 Mon Sep 17 00:00:00 2001 From: Allan Rasmussen Date: Thu, 27 Nov 2025 10:51:08 +0100 Subject: [PATCH 18/20] trace --- rust-src/concordium_base/src/random_oracle/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust-src/concordium_base/src/random_oracle/mod.rs b/rust-src/concordium_base/src/random_oracle/mod.rs index f7ce914bd..eedea38a5 100644 --- a/rust-src/concordium_base/src/random_oracle/mod.rs +++ b/rust-src/concordium_base/src/random_oracle/mod.rs @@ -221,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, Clone, Default)] // todo ar remove default +#[derive(Debug, Clone)] pub struct TranscriptProtocolV1(Sha3_256); /// Type of challenges computed from the random oracle. From cc2dd86c03fbadf1340b856efa8623a3ef1f33c8 Mon Sep 17 00:00:00 2001 From: tschudid <14889202+tschudid@users.noreply.github.com> Date: Tue, 9 Dec 2025 09:28:49 +0100 Subject: [PATCH 19/20] add some formatting to trace --- .../concordium_base/src/random_oracle/mod.rs | 29 ++++++++++++++----- 1 file changed, 21 insertions(+), 8 deletions(-) diff --git a/rust-src/concordium_base/src/random_oracle/mod.rs b/rust-src/concordium_base/src/random_oracle/mod.rs index eedea38a5..f333a56ec 100644 --- a/rust-src/concordium_base/src/random_oracle/mod.rs +++ b/rust-src/concordium_base/src/random_oracle/mod.rs @@ -560,6 +560,10 @@ impl TranscriptProtocolV1 { } } + +#[cfg(test)] +const LABEL_WIDTH: usize = 35; +const MSG_SIZE_WIDTH: usize = 5; #[cfg(test)] #[derive(Debug, Clone)] pub struct TranscriptProtocolTracer

{ @@ -570,9 +574,11 @@ pub struct TranscriptProtocolTracer

{ #[cfg(test)] impl

TranscriptProtocolTracer

{ 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: std::cell::RefCell::new(vec![]), + lines, } } } @@ -588,17 +594,21 @@ impl

Drop for TranscriptProtocolTracer

{ #[cfg(test)] impl TranscriptProtocol for TranscriptProtocolTracer

{ + fn append_label(&mut self, label: impl AsRef<[u8]>) { self.inner.append_label(label.as_ref()); self.lines .borrow_mut() - .push(String::from_utf8_lossy(label.as_ref()).into_owned()); + .push(format!( + "-l-> {:, message: &impl Serial) { self.inner.append_message(label.as_ref(), message); self.lines.borrow_mut().push(format!( - "{}, {} bytes", + "-m-> {:MSG_SIZE_WIDTH$} bytes", String::from_utf8_lossy(label.as_ref()).into_owned(), to_bytes(message).len() )); @@ -614,7 +624,7 @@ impl TranscriptProtocol for TranscriptProtocolTracer

{ let messages: Vec<_> = messages.into_iter().collect(); self.inner.append_messages(label.as_ref(), &messages); self.lines.borrow_mut().push(format!( - "{}, {} items, {} bytes total", + "-m-> {:MSG_SIZE_WIDTH$} items {:>MSG_SIZE_WIDTH$} bytes total (append messages)", String::from_utf8_lossy(label.as_ref()).into_owned(), messages.len(), messages @@ -628,7 +638,7 @@ impl TranscriptProtocol for TranscriptProtocolTracer

{ self.inner .append_final_prover_message(label.as_ref(), message); self.lines.borrow_mut().push(format!( - "{}, final prover message, {} bytes", + "-m-> {:MSG_SIZE_WIDTH$} bytes (final prover message)", String::from_utf8_lossy(label.as_ref()).into_owned(), to_bytes(message).len() )); @@ -643,8 +653,9 @@ impl TranscriptProtocol for TranscriptProtocolTracer

{ 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!( - "{}, {} messages", + "-m-> {:MSG_SIZE_WIDTH$} items", String::from_utf8_lossy(label.as_ref()).into_owned(), messages.len(), )); @@ -659,13 +670,15 @@ impl TranscriptProtocol for TranscriptProtocolTracer

{ lines.extend(tracer.lines.take()); }); self.lines.borrow_mut().extend(lines); + self.lines.borrow_mut().push(format!(" {:^LABEL_WIDTH$}","--- end append each message ---")); } fn extract_challenge_scalar(&mut self, label: impl AsRef<[u8]>) -> C::Scalar { let val = self.inner.extract_challenge_scalar::(label.as_ref()); self.lines.borrow_mut().push(format!( - "{}, extract scalar challenge", + "<-c- {:MSG_SIZE_WIDTH$} (extract scalar challenge)", String::from_utf8_lossy(label.as_ref()).into_owned(), + "" )); val } @@ -674,7 +687,7 @@ impl TranscriptProtocol for TranscriptProtocolTracer

{ let val = self.inner.extract_raw_challenge(); self.lines .borrow_mut() - .push("".to_string()); + .push(format!("<-c- {:MSG_SIZE_WIDTH$} (extract raw challenge)","","")); val } } From b3bcb6df8215314ac3f6688cfa26e10b86365139 Mon Sep 17 00:00:00 2001 From: tschudid <14889202+tschudid@users.noreply.github.com> Date: Tue, 9 Dec 2025 12:23:35 +0100 Subject: [PATCH 20/20] more formatting --- rust-src/concordium_base/src/random_oracle/mod.rs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/rust-src/concordium_base/src/random_oracle/mod.rs b/rust-src/concordium_base/src/random_oracle/mod.rs index f333a56ec..d50906f52 100644 --- a/rust-src/concordium_base/src/random_oracle/mod.rs +++ b/rust-src/concordium_base/src/random_oracle/mod.rs @@ -653,7 +653,7 @@ impl TranscriptProtocol for TranscriptProtocolTracer

{ 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!(" {: {:MSG_SIZE_WIDTH$} items", String::from_utf8_lossy(label.as_ref()).into_owned(), @@ -662,15 +662,17 @@ impl TranscriptProtocol for TranscriptProtocolTracer

{ let mut lines = Vec::new(); self.inner .append_each_message(label, messages, |inner, item| unsafe { + lines.push(format!(" {:(&mut self, label: impl AsRef<[u8]>) -> C::Scalar {