11use crate :: {
2- CURRENT_VERSION , NormalizedSpell , V0 , V0_SPELL_VK , V1 , V1_SPELL_VK , V2 , V2_SPELL_VK , V3 ,
3- V3_SPELL_VK , V4 , V4_SPELL_VK , V5 , V5_SPELL_VK , bitcoin_tx:: BitcoinTx , cardano_tx:: CardanoTx ,
2+ CURRENT_VERSION , MOCK_SPELL_VK , NormalizedSpell , V0 , V0_SPELL_VK , V1 , V1_SPELL_VK , V2 ,
3+ V2_SPELL_VK , V3 , V3_SPELL_VK , V4 , V4_SPELL_VK , V5 , V5_SPELL_VK , ark, bitcoin_tx:: BitcoinTx ,
4+ cardano_tx:: CardanoTx ,
45} ;
5- use anyhow:: bail;
6+ use anyhow:: { anyhow , bail} ;
67use charms_data:: { TxId , util} ;
78use enum_dispatch:: enum_dispatch;
89use serde:: { Deserialize , Serialize } ;
910use serde_with:: { IfIsHumanReadable , serde_as} ;
1011use sp1_primitives:: io:: SP1PublicValues ;
12+ use sp1_verifier:: Groth16Verifier ;
1113
1214#[ enum_dispatch]
1315pub trait EnchantedTx {
14- fn extract_and_verify_spell ( & self , spell_vk : & str ) -> anyhow:: Result < NormalizedSpell > ;
16+ fn extract_and_verify_spell (
17+ & self ,
18+ spell_vk : & str ,
19+ mock : bool ,
20+ ) -> anyhow:: Result < NormalizedSpell > ;
1521 fn tx_outs_len ( & self ) -> usize ;
1622 fn tx_id ( & self ) -> TxId ;
1723 fn hex ( & self ) -> String ;
@@ -65,23 +71,48 @@ impl Tx {
6571/// Extract a [`NormalizedSpell`] from a transaction and verify it.
6672/// Incorrect spells are rejected.
6773#[ tracing:: instrument( level = "debug" , skip_all) ]
68- pub fn extract_and_verify_spell ( spell_vk : & str , tx : & Tx ) -> anyhow:: Result < NormalizedSpell > {
69- tx. extract_and_verify_spell ( spell_vk)
74+ pub fn extract_and_verify_spell (
75+ spell_vk : & str ,
76+ tx : & Tx ,
77+ mock : bool ,
78+ ) -> anyhow:: Result < NormalizedSpell > {
79+ tx. extract_and_verify_spell ( spell_vk, mock)
7080}
7181
72- pub fn vks ( spell_version : u32 , spell_vk : & str ) -> anyhow:: Result < ( & str , & [ u8 ] ) > {
82+ pub fn spell_vk ( spell_version : u32 , spell_vk : & str , mock : bool ) -> anyhow:: Result < & str > {
83+ if mock {
84+ return Ok ( MOCK_SPELL_VK ) ;
85+ }
7386 match spell_version {
74- CURRENT_VERSION => Ok ( ( spell_vk, CURRENT_GROTH16_VK_BYTES ) ) ,
75- V5 => Ok ( ( V5_SPELL_VK , V5_GROTH16_VK_BYTES ) ) ,
76- V4 => Ok ( ( V4_SPELL_VK , V4_GROTH16_VK_BYTES ) ) ,
77- V3 => Ok ( ( V3_SPELL_VK , V3_GROTH16_VK_BYTES ) ) ,
78- V2 => Ok ( ( V2_SPELL_VK , V2_GROTH16_VK_BYTES ) ) ,
79- V1 => Ok ( ( V1_SPELL_VK , V1_GROTH16_VK_BYTES ) ) ,
80- V0 => Ok ( ( V0_SPELL_VK , V0_GROTH16_VK_BYTES ) ) ,
87+ CURRENT_VERSION => Ok ( spell_vk) ,
88+ V5 => Ok ( V5_SPELL_VK ) ,
89+ V4 => Ok ( V4_SPELL_VK ) ,
90+ V3 => Ok ( V3_SPELL_VK ) ,
91+ V2 => Ok ( V2_SPELL_VK ) ,
92+ V1 => Ok ( V1_SPELL_VK ) ,
93+ V0 => Ok ( V0_SPELL_VK ) ,
8194 _ => bail ! ( "unsupported spell version: {}" , spell_version) ,
8295 }
8396}
8497
98+ pub fn groth16_vk ( spell_version : u32 , mock : bool ) -> anyhow:: Result < & ' static [ u8 ] > {
99+ if mock {
100+ return Ok ( MOCK_GROTH16_VK_BYTES ) ;
101+ }
102+ match spell_version {
103+ CURRENT_VERSION => Ok ( CURRENT_GROTH16_VK_BYTES ) ,
104+ V5 => Ok ( V5_GROTH16_VK_BYTES ) ,
105+ V4 => Ok ( V4_GROTH16_VK_BYTES ) ,
106+ V3 => Ok ( V3_GROTH16_VK_BYTES ) ,
107+ V2 => Ok ( V2_GROTH16_VK_BYTES ) ,
108+ V1 => Ok ( V1_GROTH16_VK_BYTES ) ,
109+ V0 => Ok ( V0_GROTH16_VK_BYTES ) ,
110+ _ => bail ! ( "unsupported spell version: {}" , spell_version) ,
111+ }
112+ }
113+
114+ pub const MOCK_GROTH16_VK_BYTES : & ' static [ u8 ] = include_bytes ! ( "../vk/mock/mock-groth16-vk.bin" ) ;
115+
85116pub const V0_GROTH16_VK_BYTES : & ' static [ u8 ] = include_bytes ! ( "../vk/v0/groth16_vk.bin" ) ;
86117pub const V1_GROTH16_VK_BYTES : & ' static [ u8 ] = include_bytes ! ( "../vk/v1/groth16_vk.bin" ) ;
87118pub const V2_GROTH16_VK_BYTES : & ' static [ u8 ] = V1_GROTH16_VK_BYTES ;
@@ -91,21 +122,36 @@ pub const V5_GROTH16_VK_BYTES: &'static [u8] = V4_GROTH16_VK_BYTES;
91122pub const V6_GROTH16_VK_BYTES : & ' static [ u8 ] = V5_GROTH16_VK_BYTES ;
92123pub const CURRENT_GROTH16_VK_BYTES : & ' static [ u8 ] = V6_GROTH16_VK_BYTES ;
93124
94- pub fn to_sp1_pv < T : Serialize > ( spell_version : u32 , t : & T ) -> SP1PublicValues {
95- let mut pv = SP1PublicValues :: new ( ) ;
125+ pub fn to_serialized_pv < T : Serialize > ( spell_version : u32 , t : & T ) -> Vec < u8 > {
96126 match spell_version {
97127 CURRENT_VERSION | V5 | V4 | V3 | V2 | V1 => {
98128 // we commit to CBOR-encoded tuple `(spell_vk, n_spell)`
99- pv . write_slice ( util:: write ( t) . unwrap ( ) . as_slice ( ) ) ;
129+ util:: write ( t) . unwrap ( )
100130 }
101131 V0 => {
102132 // we used to commit to the tuple `(spell_vk, n_spell)`, which was serialized internally
103133 // by SP1
134+ let mut pv = SP1PublicValues :: new ( ) ;
104135 pv. write ( t) ;
136+ pv. to_vec ( )
105137 }
106138 _ => unreachable ! ( ) ,
107139 }
108- pv
140+ }
141+
142+ pub fn verify_snark_proof (
143+ proof : & [ u8 ] ,
144+ public_inputs : & [ u8 ] ,
145+ vk_hash : & str ,
146+ spell_version : u32 ,
147+ mock : bool ,
148+ ) -> anyhow:: Result < ( ) > {
149+ let groth16_vk = groth16_vk ( spell_version, mock) ?;
150+ match mock {
151+ false => Groth16Verifier :: verify ( proof, public_inputs, vk_hash, groth16_vk)
152+ . map_err ( |e| anyhow ! ( "could not verify spell proof: {}" , e) ) ,
153+ true => ark:: verify_groth16_proof ( proof, public_inputs, groth16_vk) ,
154+ }
109155}
110156
111157#[ cfg( test) ]
0 commit comments