@@ -3914,6 +3914,8 @@ fn get_rng() -> rand::rngs::OsRng {
39143914pub enum ProofError {
39153915 #[ error( "kimchi error: {0:?}" ) ]
39163916 ProvingError ( #[ from] kimchi:: error:: ProverError ) ,
3917+ #[ error( "kimchi error with context: {0:?}" ) ]
3918+ ProvingErrorWithContext ( #[ from] debug:: KimchiProofError ) ,
39173919 #[ error( "constraint not satisfield: {0}" ) ]
39183920 ConstraintsNotSatisfied ( String ) ,
39193921 #[ error( "invalid bigint" ) ]
@@ -3959,12 +3961,11 @@ pub(super) fn create_proof<C: ProofConstants, F: FieldWitness>(
39593961 let prover_index: & ProverIndex < F > = & prover. index ;
39603962
39613963 // public input
3962- let public_input = computed_witness[ 0 ] [ 0 ..prover_index. cs . public ] . to_vec ( ) ;
3964+ let public_input = computed_witness[ 0 ] [ ..prover_index. cs . public ] . to_vec ( ) ;
39633965
39643966 if only_verify_constraints {
3965- let public = & computed_witness[ 0 ] [ 0 ..prover_index. cs . public ] ;
39663967 prover_index
3967- . verify ( & computed_witness, public )
3968+ . verify ( & computed_witness, & public_input )
39683969 . map_err ( |e| {
39693970 ProofError :: ConstraintsNotSatisfied ( format ! ( "incorrect witness: {:?}" , e) )
39703971 } ) ?;
@@ -3984,10 +3985,38 @@ pub(super) fn create_proof<C: ProofConstants, F: FieldWitness>(
39843985 computed_witness,
39853986 & [ ] ,
39863987 prover_index,
3987- prev_challenges,
3988+ prev_challenges. clone ( ) ,
39883989 None ,
39893990 & mut rng,
39903991 )
3992+ . map_err ( |e| {
3993+ use kimchi:: groupmap:: GroupMap ;
3994+
3995+ let prev_challenges_hash = debug:: hash_prev_challenge :: < F > ( & prev_challenges) ;
3996+ let witness_primary_hash = debug:: hash_slice ( & w. primary ) ;
3997+ let witness_aux_hash = debug:: hash_slice ( w. aux ( ) ) ;
3998+ let group_map_hash = debug:: hash_slice ( & group_map. composition ( ) ) ;
3999+
4000+ dbg ! (
4001+ & prev_challenges_hash,
4002+ & witness_primary_hash,
4003+ & witness_aux_hash,
4004+ & group_map_hash
4005+ ) ;
4006+
4007+ let context = debug:: KimchiProofError {
4008+ inner_error : e. to_string ( ) ,
4009+ witness_primary : w. primary . iter ( ) . map ( |f| ( * f) . into ( ) ) . collect ( ) ,
4010+ witness_aux : w. aux ( ) . iter ( ) . map ( |f| ( * f) . into ( ) ) . collect ( ) ,
4011+ // prev_challenges,
4012+ witness_primary_hash,
4013+ witness_aux_hash,
4014+ prev_challenges_hash,
4015+ group_map_hash,
4016+ } ;
4017+
4018+ ProofError :: ProvingErrorWithContext ( context)
4019+ } )
39914020 . context ( "create_recursive" ) ?;
39924021
39934022 eprintln ! ( "proof_elapsed={:?}" , now. elapsed( ) ) ;
@@ -3998,6 +4027,157 @@ pub(super) fn create_proof<C: ProofConstants, F: FieldWitness>(
39984027 } )
39994028}
40004029
4030+ pub mod debug {
4031+ use super :: * ;
4032+
4033+ use mina_p2p_messages:: bigint:: BigInt ;
4034+ use mina_p2p_messages:: binprot;
4035+ use sha2:: Digest ;
4036+
4037+ fn hash_field < F : FieldWitness > ( state : & mut sha2:: Sha256 , f : & F ) {
4038+ for limb in f. montgomery_form_ref ( ) {
4039+ state. update ( limb. to_le_bytes ( ) ) ;
4040+ }
4041+ }
4042+
4043+ fn hash_field_slice < F : FieldWitness > ( state : & mut sha2:: Sha256 , slice : & [ F ] ) {
4044+ state. update ( slice. len ( ) . to_le_bytes ( ) ) ;
4045+ for f in slice. iter ( ) . flat_map ( |f| f. montgomery_form_ref ( ) ) {
4046+ state. update ( f. to_le_bytes ( ) ) ;
4047+ }
4048+ }
4049+
4050+ pub ( super ) fn hash_slice < F : FieldWitness > ( slice : & [ F ] ) -> String {
4051+ let mut hasher = sha2:: Sha256 :: new ( ) ;
4052+ hash_field_slice ( & mut hasher, slice) ;
4053+ hex:: encode ( hasher. finalize ( ) )
4054+ }
4055+
4056+ pub ( super ) fn hash_prev_challenge < F : FieldWitness > (
4057+ prevs : & [ RecursionChallenge < F :: OtherCurve > ] ,
4058+ ) -> String {
4059+ use poly_commitment:: commitment:: CommitmentCurve ;
4060+ use sha2:: Digest ;
4061+ let mut hasher = sha2:: Sha256 :: new ( ) ;
4062+ for RecursionChallenge { chals, comm } in prevs {
4063+ hash_field_slice ( & mut hasher, chals) ;
4064+ let poly_commitment:: PolyComm { elems } = comm;
4065+ for elem in elems {
4066+ match elem. to_coordinates ( ) {
4067+ None => {
4068+ hasher. update ( [ 0 ] ) ;
4069+ }
4070+ Some ( ( c1, c2) ) => {
4071+ hasher. update ( [ 1 ] ) ;
4072+ hash_field ( & mut hasher, & c1) ;
4073+ hash_field ( & mut hasher, & c2) ;
4074+ }
4075+ }
4076+ }
4077+ }
4078+ hex:: encode ( hasher. finalize ( ) )
4079+ }
4080+
4081+ #[ derive( Clone ) ]
4082+ pub struct KimchiProofError {
4083+ pub inner_error : String ,
4084+ pub witness_primary : Vec < BigInt > ,
4085+ pub witness_aux : Vec < BigInt > ,
4086+ // pub prev_challenges: Vec<RecursionChallenge<F::OtherCurve>>,
4087+ // Store hashes in case there is a de/serialization bug
4088+ pub witness_primary_hash : String ,
4089+ pub witness_aux_hash : String ,
4090+ pub prev_challenges_hash : String ,
4091+ pub group_map_hash : String ,
4092+ }
4093+
4094+ // Manual implementation because String does not implement binprot traits (because unbounded)
4095+ impl binprot:: BinProtWrite for KimchiProofError {
4096+ fn binprot_write < W : std:: io:: Write > ( & self , w : & mut W ) -> std:: io:: Result < ( ) > {
4097+ let Self {
4098+ inner_error,
4099+ witness_primary,
4100+ witness_aux,
4101+ witness_primary_hash,
4102+ witness_aux_hash,
4103+ prev_challenges_hash,
4104+ group_map_hash,
4105+ } = self ;
4106+ let inner_error: & [ u8 ] = inner_error. as_bytes ( ) ;
4107+ let witness_primary_hash: & [ u8 ] = witness_primary_hash. as_bytes ( ) ;
4108+ let witness_aux_hash: & [ u8 ] = witness_aux_hash. as_bytes ( ) ;
4109+ let prev_challenges_hash: & [ u8 ] = prev_challenges_hash. as_bytes ( ) ;
4110+ let group_map_hash: & [ u8 ] = group_map_hash. as_bytes ( ) ;
4111+ binprot:: BinProtWrite :: binprot_write ( & inner_error, w) ?;
4112+ binprot:: BinProtWrite :: binprot_write ( witness_primary, w) ?;
4113+ binprot:: BinProtWrite :: binprot_write ( witness_aux, w) ?;
4114+ binprot:: BinProtWrite :: binprot_write ( & witness_primary_hash, w) ?;
4115+ binprot:: BinProtWrite :: binprot_write ( & witness_aux_hash, w) ?;
4116+ binprot:: BinProtWrite :: binprot_write ( & prev_challenges_hash, w) ?;
4117+ binprot:: BinProtWrite :: binprot_write ( & group_map_hash, w) ?;
4118+ Ok ( ( ) )
4119+ }
4120+ }
4121+ // Manual implementation because String does not implement binprot traits (because unbounded)
4122+ impl binprot:: BinProtRead for KimchiProofError {
4123+ fn binprot_read < R : std:: io:: Read + ?Sized > ( r : & mut R ) -> Result < Self , binprot:: Error >
4124+ where
4125+ Self : Sized ,
4126+ {
4127+ let to_string = |bytes : Vec < u8 > | -> String { String :: from_utf8 ( bytes) . unwrap ( ) } ;
4128+ let inner_error: Vec < u8 > = binprot:: BinProtRead :: binprot_read ( r) ?;
4129+ let witness_primary: Vec < BigInt > = binprot:: BinProtRead :: binprot_read ( r) ?;
4130+ let witness_aux: Vec < BigInt > = binprot:: BinProtRead :: binprot_read ( r) ?;
4131+ let witness_primary_hash: Vec < u8 > = binprot:: BinProtRead :: binprot_read ( r) ?;
4132+ let witness_aux_hash: Vec < u8 > = binprot:: BinProtRead :: binprot_read ( r) ?;
4133+ let prev_challenges_hash: Vec < u8 > = binprot:: BinProtRead :: binprot_read ( r) ?;
4134+ let group_map_hash: Vec < u8 > = binprot:: BinProtRead :: binprot_read ( r) ?;
4135+ Ok ( Self {
4136+ inner_error : to_string ( inner_error) ,
4137+ witness_primary,
4138+ witness_aux,
4139+ witness_primary_hash : to_string ( witness_primary_hash) ,
4140+ witness_aux_hash : to_string ( witness_aux_hash) ,
4141+ prev_challenges_hash : to_string ( prev_challenges_hash) ,
4142+ group_map_hash : to_string ( group_map_hash) ,
4143+ } )
4144+ }
4145+ }
4146+
4147+ impl core:: fmt:: Display for KimchiProofError {
4148+ fn fmt ( & self , f : & mut std:: fmt:: Formatter < ' _ > ) -> std:: fmt:: Result {
4149+ f. write_fmt ( format_args ! ( "{:?}" , self ) )
4150+ }
4151+ }
4152+
4153+ impl std:: error:: Error for KimchiProofError { }
4154+
4155+ impl core:: fmt:: Debug for KimchiProofError {
4156+ fn fmt ( & self , f : & mut std:: fmt:: Formatter < ' _ > ) -> std:: fmt:: Result {
4157+ let Self {
4158+ inner_error,
4159+ witness_primary,
4160+ witness_aux,
4161+ witness_primary_hash,
4162+ witness_aux_hash,
4163+ prev_challenges_hash,
4164+ group_map_hash,
4165+ } = self ;
4166+
4167+ // Print witness lengths, not the whole vectors
4168+ f. debug_struct ( "KimchiProofError" )
4169+ . field ( "inner_error" , inner_error)
4170+ . field ( "witness_primary" , & witness_primary. len ( ) )
4171+ . field ( "witness_aux" , & witness_aux. len ( ) )
4172+ . field ( "witness_primary_hash" , & witness_primary_hash)
4173+ . field ( "witness_aux_hash" , & witness_aux_hash)
4174+ . field ( "prev_challenges_hash" , & prev_challenges_hash)
4175+ . field ( "group_map_hash" , & group_map_hash)
4176+ . finish ( )
4177+ }
4178+ }
4179+ }
4180+
40014181#[ derive( Clone ) ]
40024182pub struct Prover < F : FieldWitness > {
40034183 /// Constants to each kind of proof
0 commit comments