darkfi_contract_test_harness/
vks.rs
1use std::{
20 fs::File,
21 io::{Read, Write},
22 path::PathBuf,
23 process::Command,
24};
25
26use darkfi::{
27 blockchain::contract_store::SMART_CONTRACT_ZKAS_DB_NAME,
28 zk::{empty_witnesses, ProvingKey, VerifyingKey, ZkCircuit},
29 zkas::ZkBinary,
30 Result,
31};
32use darkfi_dao_contract::{
33 DAO_CONTRACT_ZKAS_DAO_AUTH_MONEY_TRANSFER_ENC_COIN_NS,
34 DAO_CONTRACT_ZKAS_DAO_AUTH_MONEY_TRANSFER_NS, DAO_CONTRACT_ZKAS_DAO_EARLY_EXEC_NS,
35 DAO_CONTRACT_ZKAS_DAO_EXEC_NS, DAO_CONTRACT_ZKAS_DAO_MINT_NS,
36 DAO_CONTRACT_ZKAS_DAO_PROPOSE_INPUT_NS, DAO_CONTRACT_ZKAS_DAO_PROPOSE_MAIN_NS,
37 DAO_CONTRACT_ZKAS_DAO_VOTE_INPUT_NS, DAO_CONTRACT_ZKAS_DAO_VOTE_MAIN_NS,
38};
39use darkfi_money_contract::{
40 MONEY_CONTRACT_ZKAS_AUTH_TOKEN_MINT_NS_V1, MONEY_CONTRACT_ZKAS_BURN_NS_V1,
41 MONEY_CONTRACT_ZKAS_FEE_NS_V1, MONEY_CONTRACT_ZKAS_MINT_NS_V1,
42 MONEY_CONTRACT_ZKAS_TOKEN_MINT_NS_V1,
43};
44use darkfi_sdk::crypto::{DAO_CONTRACT_ID, MONEY_CONTRACT_ID};
45use darkfi_serial::{deserialize, serialize};
46
47use log::debug;
48use sled_overlay::sled;
49
50const PKS_HASH: &str = "46a30a57bd14b6bc5851bbde8b011ba2e12765bba7901c5e42f511bdb68b3255";
53const VKS_HASH: &str = "4e6f5326b3acc7fd4f6525914be8076276b16c5601940d034de0617c94b1170f";
54
55fn cache_path(typ: &str) -> Result<PathBuf> {
57 let output = Command::new("git").arg("rev-parse").arg("--show-toplevel").output()?.stdout;
58 let mut path = PathBuf::from(String::from_utf8(output[..output.len() - 1].to_vec())?);
59 path.push("src");
60 path.push("contract");
61 path.push("test-harness");
62 path.push(typ);
63 Ok(path)
64}
65
66pub type Vks = Vec<(Vec<u8>, String, Vec<u8>)>;
68pub type Pks = Vec<(Vec<u8>, String, Vec<u8>)>;
70
71pub fn get_cached_pks_and_vks() -> Result<(Pks, Vks)> {
73 let pks_path = cache_path("pks.bin")?;
74 let vks_path = cache_path("vks.bin")?;
75
76 let mut pks = None;
77 let mut vks = None;
78
79 if pks_path.exists() {
80 debug!("Found {:?}", pks_path);
81 let mut f = File::open(pks_path.clone())?;
82 let mut data = vec![];
83 f.read_to_end(&mut data)?;
84
85 let known_hash = blake3::Hash::from_hex(PKS_HASH)?;
86 let found_hash = blake3::hash(&data);
87
88 debug!("Known PKS hash: {}", known_hash);
89 debug!("Found PKS hash: {}", found_hash);
90
91 if known_hash == found_hash {
92 pks = Some(deserialize(&data)?)
93 }
94
95 drop(f);
96 }
97
98 if vks_path.exists() {
99 debug!("Found {:?}", vks_path);
100 let mut f = File::open(vks_path.clone())?;
101 let mut data = vec![];
102 f.read_to_end(&mut data)?;
103
104 let known_hash = blake3::Hash::from_hex(VKS_HASH)?;
105 let found_hash = blake3::hash(&data);
106
107 debug!("Known VKS hash: {}", known_hash);
108 debug!("Found VKS hash: {}", found_hash);
109
110 if known_hash == found_hash {
111 vks = Some(deserialize(&data)?)
112 }
113
114 drop(f);
115 }
116
117 if let (Some(pks), Some(vks)) = (pks, vks) {
119 return Ok((pks, vks))
120 }
121
122 let bins = vec![
124 &include_bytes!("../../money/proof/fee_v1.zk.bin")[..],
126 &include_bytes!("../../money/proof/mint_v1.zk.bin")[..],
127 &include_bytes!("../../money/proof/burn_v1.zk.bin")[..],
128 &include_bytes!("../../money/proof/token_mint_v1.zk.bin")[..],
129 &include_bytes!("../../money/proof/auth_token_mint_v1.zk.bin")[..],
130 &include_bytes!("../../dao/proof/mint.zk.bin")[..],
132 &include_bytes!("../../dao/proof/propose-input.zk.bin")[..],
133 &include_bytes!("../../dao/proof/propose-main.zk.bin")[..],
134 &include_bytes!("../../dao/proof/vote-input.zk.bin")[..],
135 &include_bytes!("../../dao/proof/vote-main.zk.bin")[..],
136 &include_bytes!("../../dao/proof/exec.zk.bin")[..],
137 &include_bytes!("../../dao/proof/early-exec.zk.bin")[..],
138 &include_bytes!("../../dao/proof/auth-money-transfer.zk.bin")[..],
139 &include_bytes!("../../dao/proof/auth-money-transfer-enc-coin.zk.bin")[..],
140 ];
141
142 let mut pks = vec![];
143 let mut vks = vec![];
144
145 for bincode in bins.iter() {
146 let zkbin = ZkBinary::decode(bincode)?;
147 debug!("Building PK for {}", zkbin.namespace);
148 let witnesses = empty_witnesses(&zkbin)?;
149 let circuit = ZkCircuit::new(witnesses, &zkbin);
150
151 let pk = ProvingKey::build(zkbin.k, &circuit);
152 let mut pk_buf = vec![];
153 pk.write(&mut pk_buf)?;
154 pks.push((bincode.to_vec(), zkbin.namespace.clone(), pk_buf));
155
156 debug!("Building VK for {}", zkbin.namespace);
157 let vk = VerifyingKey::build(zkbin.k, &circuit);
158 let mut vk_buf = vec![];
159 vk.write(&mut vk_buf)?;
160 vks.push((bincode.to_vec(), zkbin.namespace.clone(), vk_buf));
161 }
162
163 debug!("Writing PKs to {:?}", pks_path);
164 let mut f = File::create(&pks_path)?;
165 let ser = serialize(&pks);
166 let hash = blake3::hash(&ser);
167 debug!("{:?} {}", pks_path, hash);
168 f.write_all(&ser)?;
169
170 debug!("Writing VKs to {:?}", vks_path);
171 let mut f = File::create(&vks_path)?;
172 let ser = serialize(&vks);
173 let hash = blake3::hash(&ser);
174 debug!("{:?} {}", vks_path, hash);
175 f.write_all(&ser)?;
176
177 Ok((pks, vks))
178}
179
180pub fn inject(sled_db: &sled::Db, vks: &Vks) -> Result<()> {
182 let money_db_name = MONEY_CONTRACT_ID.hash_state_id(SMART_CONTRACT_ZKAS_DB_NAME);
184 let dao_db_name = DAO_CONTRACT_ID.hash_state_id(SMART_CONTRACT_ZKAS_DB_NAME);
185
186 let money_tree = sled_db.open_tree(money_db_name)?;
188 let dao_tree = sled_db.open_tree(dao_db_name)?;
189
190 for (bincode, namespace, vk) in vks.iter() {
191 match namespace.as_str() {
192 MONEY_CONTRACT_ZKAS_FEE_NS_V1 |
194 MONEY_CONTRACT_ZKAS_MINT_NS_V1 |
195 MONEY_CONTRACT_ZKAS_BURN_NS_V1 |
196 MONEY_CONTRACT_ZKAS_TOKEN_MINT_NS_V1 |
197 MONEY_CONTRACT_ZKAS_AUTH_TOKEN_MINT_NS_V1 => {
198 let key = serialize(&namespace.as_str());
199 let value = serialize(&(bincode.clone(), vk.clone()));
200 money_tree.insert(key, value)?;
201 }
202
203 DAO_CONTRACT_ZKAS_DAO_MINT_NS |
205 DAO_CONTRACT_ZKAS_DAO_VOTE_INPUT_NS |
206 DAO_CONTRACT_ZKAS_DAO_VOTE_MAIN_NS |
207 DAO_CONTRACT_ZKAS_DAO_PROPOSE_INPUT_NS |
208 DAO_CONTRACT_ZKAS_DAO_PROPOSE_MAIN_NS |
209 DAO_CONTRACT_ZKAS_DAO_EXEC_NS |
210 DAO_CONTRACT_ZKAS_DAO_EARLY_EXEC_NS |
211 DAO_CONTRACT_ZKAS_DAO_AUTH_MONEY_TRANSFER_NS |
212 DAO_CONTRACT_ZKAS_DAO_AUTH_MONEY_TRANSFER_ENC_COIN_NS => {
213 let key = serialize(&namespace.as_str());
214 let value = serialize(&(bincode.clone(), vk.clone()));
215 dao_tree.insert(key, value)?;
216 }
217
218 x => panic!("Found unhandled zkas namespace {}", x),
219 }
220 }
221
222 Ok(())
223}