@@ -94,6 +94,7 @@ pub enum VerificationError {
94
94
UtxoInputLenMismatch ,
95
95
/// Balance Check failed
96
96
BalanceCheckFailed ,
97
+ IndexOutOfBounds ,
97
98
}
98
99
99
100
impl fmt:: Display for VerificationError {
@@ -129,6 +130,7 @@ impl fmt::Display for VerificationError {
129
130
VerificationError :: SurjectionProofMissing ( i) => {
130
131
write ! ( f, "Missing Surjection Proof for output index {}" , i)
131
132
}
133
+ VerificationError :: IndexOutOfBounds => todo ! ( ) ,
132
134
}
133
135
}
134
136
}
@@ -825,6 +827,65 @@ pub enum TxInType{
825
827
}
826
828
827
829
impl Transaction {
830
+
831
+ /// Verify surjection proof for output at index i. Returns Ok(()) if there is
832
+ /// an explicit asset and no surjection proof
833
+ pub fn verify_surjection_proof (
834
+ & self ,
835
+ secp : & Secp256k1 < secp256k1_zkp:: All > ,
836
+ spent_utxos : & [ TxOut ] ,
837
+ i : usize ,
838
+ ) -> Result < ( ) , VerificationError >
839
+ {
840
+ if spent_utxos. len ( ) != self . input . len ( ) {
841
+ return Err ( VerificationError :: UtxoInputLenMismatch ) ;
842
+ }
843
+ // Issuances and reissuances not supported yet
844
+ let mut in_commits = vec ! [ ] ;
845
+ let mut domain = vec ! [ ] ;
846
+ for ( i, inp) in self . input . iter ( ) . enumerate ( ) {
847
+ let gen = spent_utxos[ i] . get_asset_gen ( secp)
848
+ . map_err ( |e| VerificationError :: SpentTxOutError ( i, e) ) ?;
849
+ domain. push ( gen) ;
850
+ in_commits. push (
851
+ spent_utxos[ i] . get_value_commit ( secp)
852
+ . map_err ( |e| VerificationError :: SpentTxOutError ( i, e) ) ?
853
+ ) ;
854
+ if inp. has_issuance ( ) {
855
+ let ( asset_id, token_id) = inp. issuance_ids ( ) ;
856
+ let arr = [
857
+ ( inp. asset_issuance . amount , asset_id) ,
858
+ ( inp. asset_issuance . inflation_keys , token_id) ,
859
+ ] ;
860
+ for ( amt, asset) in arr. iter ( ) {
861
+ match amt {
862
+ Value :: Null => continue ,
863
+ Value :: Explicit ( v) => {
864
+ let gen = Generator :: new_unblinded ( secp, asset. into_tag ( ) ) ;
865
+ domain. push ( gen) ;
866
+ let comm = PedersenCommitment :: new_unblinded ( secp, * v, gen) ;
867
+ in_commits. push ( comm)
868
+ } ,
869
+ Value :: Confidential ( comm) => in_commits. push ( * comm) ,
870
+ }
871
+ }
872
+ }
873
+ }
874
+
875
+ let out = self . output . get ( i) . ok_or ( VerificationError :: IndexOutOfBounds ) ?;
876
+
877
+ // Surjection proof checks
878
+ if let Some ( gen) = out. asset . commitment ( ) {
879
+ let surjectionproof = out. witness . surjection_proof . as_ref ( ) . ok_or (
880
+ VerificationError :: SurjectionProofMissing ( i) ) ?;
881
+ if !surjectionproof. verify ( secp, gen, & domain) {
882
+ return Err ( VerificationError :: SurjectionProofVerificationError ( i) )
883
+ }
884
+ } else {
885
+ // No surjection proof checks for explicit assets
886
+ }
887
+ Ok ( ( ) )
888
+ }
828
889
/// Verify that the transaction has correctly calculated blinding
829
890
/// factors and they CT verification equation holds.
830
891
/// This is *NOT* a complete Transaction verification check
@@ -913,36 +974,36 @@ impl Transaction {
913
974
}
914
975
}
915
976
916
- for ( i, out) in self . output . iter ( ) . enumerate ( ) {
917
-
918
- // Compute the value commitments and asset generator
919
- let out_commit = out. get_value_commit ( secp)
920
- . map_err ( |e| VerificationError :: SpentTxOutError ( i, e) ) ?;
921
- out_commits. push ( out_commit) ;
922
-
923
- // rangeproof checks
924
- if let Some ( comm) = out. value . commitment ( ) {
925
- let gen = out. get_asset_gen ( secp)
926
- . map_err ( |e| VerificationError :: TxOutError ( i, e) ) ?;
927
- let rangeproof = out. witness . rangeproof . as_ref ( ) . ok_or (
928
- VerificationError :: RangeProofMissing ( i) ) ?;
929
- rangeproof. verify ( secp, comm, out. script_pubkey . as_bytes ( ) , gen)
930
- . map_err ( |e| VerificationError :: RangeProofError ( i, e) ) ?;
931
- } else {
932
- // No rangeproof checks for explicit values
933
- }
934
-
935
- // Surjection proof checks
936
- if let Some ( gen) = out. asset . commitment ( ) {
937
- let surjectionproof = out. witness . surjection_proof . as_ref ( ) . ok_or (
938
- VerificationError :: SurjectionProofMissing ( i) ) ?;
939
- if !surjectionproof. verify ( secp, gen, & domain) {
940
- return Err ( VerificationError :: SurjectionProofVerificationError ( i) )
941
- }
942
- } else {
943
- // No surjection proof checks for explicit assets
944
- }
945
- }
977
+ // for (i, out) in self.output.iter().enumerate() {
978
+
979
+ // // Compute the value commitments and asset generator
980
+ // let out_commit = out.get_value_commit(secp)
981
+ // .map_err(|e| VerificationError::SpentTxOutError(i, e))?;
982
+ // out_commits.push(out_commit);
983
+
984
+ // // rangeproof checks
985
+ // if let Some(comm) = out.value.commitment() {
986
+ // let gen = out.get_asset_gen(secp)
987
+ // .map_err(|e| VerificationError::TxOutError(i, e))?;
988
+ // let rangeproof = out.witness.rangeproof.as_ref().ok_or(
989
+ // VerificationError::RangeProofMissing(i))?;
990
+ // rangeproof.verify(secp, comm, out.script_pubkey.as_bytes(), gen)
991
+ // .map_err(|e| VerificationError::RangeProofError(i, e))?;
992
+ // } else {
993
+ // // No rangeproof checks for explicit values
994
+ // }
995
+
996
+ // // Surjection proof checks
997
+ // if let Some(gen) = out.asset.commitment() {
998
+ // let surjectionproof = out.witness.surjection_proof.as_ref().ok_or(
999
+ // VerificationError::SurjectionProofMissing(i))?;
1000
+ // if !surjectionproof.verify(secp, gen, &domain) {
1001
+ // return Err(VerificationError::SurjectionProofVerificationError(i))
1002
+ // }
1003
+ // } else {
1004
+ // // No surjection proof checks for explicit assets
1005
+ // }
1006
+ // }
946
1007
// Final Balance check
947
1008
if !secp256k1_zkp:: verify_commitments_sum_to_equal ( secp, & in_commits, & out_commits) {
948
1009
return Err ( VerificationError :: BalanceCheckFailed )
0 commit comments