@@ -3914,6 +3914,8 @@ fn get_rng() -> rand::rngs::OsRng {
3914
3914
pub enum ProofError {
3915
3915
#[ error( "kimchi error: {0:?}" ) ]
3916
3916
ProvingError ( #[ from] kimchi:: error:: ProverError ) ,
3917
+ #[ error( "kimchi error with context: {0:?}" ) ]
3918
+ ProvingErrorWithContext ( #[ from] debug:: KimchiProofError ) ,
3917
3919
#[ error( "constraint not satisfield: {0}" ) ]
3918
3920
ConstraintsNotSatisfied ( String ) ,
3919
3921
#[ error( "invalid bigint" ) ]
@@ -3959,12 +3961,11 @@ pub(super) fn create_proof<C: ProofConstants, F: FieldWitness>(
3959
3961
let prover_index: & ProverIndex < F > = & prover. index ;
3960
3962
3961
3963
// 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 ( ) ;
3963
3965
3964
3966
if only_verify_constraints {
3965
- let public = & computed_witness[ 0 ] [ 0 ..prover_index. cs . public ] ;
3966
3967
prover_index
3967
- . verify ( & computed_witness, public )
3968
+ . verify ( & computed_witness, & public_input )
3968
3969
. map_err ( |e| {
3969
3970
ProofError :: ConstraintsNotSatisfied ( format ! ( "incorrect witness: {:?}" , e) )
3970
3971
} ) ?;
@@ -3984,10 +3985,38 @@ pub(super) fn create_proof<C: ProofConstants, F: FieldWitness>(
3984
3985
computed_witness,
3985
3986
& [ ] ,
3986
3987
prover_index,
3987
- prev_challenges,
3988
+ prev_challenges. clone ( ) ,
3988
3989
None ,
3989
3990
& mut rng,
3990
3991
)
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
+ } )
3991
4020
. context ( "create_recursive" ) ?;
3992
4021
3993
4022
eprintln ! ( "proof_elapsed={:?}" , now. elapsed( ) ) ;
@@ -3998,6 +4027,157 @@ pub(super) fn create_proof<C: ProofConstants, F: FieldWitness>(
3998
4027
} )
3999
4028
}
4000
4029
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
+
4001
4181
#[ derive( Clone ) ]
4002
4182
pub struct Prover < F : FieldWitness > {
4003
4183
/// Constants to each kind of proof
0 commit comments