demo.rs 48 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333
  1. use std::{
  2. any::{Any, TypeId},
  3. collections::HashMap,
  4. hash::Hasher,
  5. io,
  6. time::Instant,
  7. };
  8. use incrementalmerkletree::Tree;
  9. use log::debug;
  10. use pasta_curves::{
  11. arithmetic::CurveAffine,
  12. group::{
  13. ff::{Field, PrimeField},
  14. Curve, Group,
  15. },
  16. pallas,
  17. };
  18. use rand::rngs::OsRng;
  19. use darkfi::{
  20. crypto::{
  21. keypair::{Keypair, PublicKey, SecretKey},
  22. proof::{ProvingKey, VerifyingKey},
  23. schnorr::{SchnorrPublic, SchnorrSecret, Signature},
  24. types::{DrkCircuitField, DrkSpendHook, DrkUserData, DrkValue},
  25. util::{pedersen_commitment_u64, poseidon_hash},
  26. Proof,
  27. },
  28. serial::Encodable,
  29. zk::{
  30. circuit::{BurnContract, MintContract},
  31. vm::ZkCircuit,
  32. vm_stack::empty_witnesses,
  33. },
  34. zkas::decoder::ZkBinary,
  35. };
  36. use crate::{dao_contract, example_contract, money_contract};
  37. // TODO: Anonymity leaks in this proof of concept:
  38. //
  39. // * Vote updates are linked to the proposal_bulla
  40. // * Nullifier of vote will link vote with the coin when it's spent
  41. // TODO: strategize and cleanup Result/Error usage
  42. // TODO: fix up code doc
  43. type Result<T> = std::result::Result<T, Box<dyn std::error::Error>>;
  44. #[derive(Eq, PartialEq)]
  45. pub struct HashableBase(pub pallas::Base);
  46. // FIXME: TODO: This should need Hash, use something else like a b58 string.
  47. impl std::hash::Hash for HashableBase {
  48. fn hash<H: Hasher>(&self, state: &mut H) {
  49. let bytes = self.0.to_repr();
  50. bytes.hash(state);
  51. }
  52. }
  53. pub struct ZkBinaryContractInfo {
  54. pub k_param: u32,
  55. pub bincode: ZkBinary,
  56. pub proving_key: ProvingKey,
  57. pub verifying_key: VerifyingKey,
  58. }
  59. pub struct ZkNativeContractInfo {
  60. pub proving_key: ProvingKey,
  61. pub verifying_key: VerifyingKey,
  62. }
  63. pub enum ZkContractInfo {
  64. Binary(ZkBinaryContractInfo),
  65. Native(ZkNativeContractInfo),
  66. }
  67. pub struct ZkContractTable {
  68. // Key will be a hash of zk binary contract on chain
  69. table: HashMap<String, ZkContractInfo>,
  70. }
  71. impl ZkContractTable {
  72. fn new() -> Self {
  73. Self { table: HashMap::new() }
  74. }
  75. fn add_contract(&mut self, key: String, bincode: ZkBinary, k_param: u32) {
  76. let witnesses = empty_witnesses(&bincode);
  77. let circuit = ZkCircuit::new(witnesses, bincode.clone());
  78. let proving_key = ProvingKey::build(k_param, &circuit);
  79. let verifying_key = VerifyingKey::build(k_param, &circuit);
  80. let info = ZkContractInfo::Binary(ZkBinaryContractInfo {
  81. k_param,
  82. bincode,
  83. proving_key,
  84. verifying_key,
  85. });
  86. self.table.insert(key, info);
  87. }
  88. fn add_native(&mut self, key: String, proving_key: ProvingKey, verifying_key: VerifyingKey) {
  89. self.table.insert(
  90. key,
  91. ZkContractInfo::Native(ZkNativeContractInfo { proving_key, verifying_key }),
  92. );
  93. }
  94. pub fn lookup(&self, key: &String) -> Option<&ZkContractInfo> {
  95. self.table.get(key)
  96. }
  97. }
  98. pub struct Transaction {
  99. pub func_calls: Vec<FuncCall>,
  100. pub signatures: Vec<Signature>,
  101. }
  102. impl Transaction {
  103. /// Verify ZK contracts for the entire tx
  104. /// In real code, we could parallelize this for loop
  105. /// TODO: fix use of unwrap with Result type stuff
  106. fn zk_verify(&self, zk_bins: &ZkContractTable) {
  107. for func_call in &self.func_calls {
  108. let proofs_public_vals = &func_call.call_data.zk_public_values();
  109. assert_eq!(
  110. proofs_public_vals.len(),
  111. func_call.proofs.len(),
  112. "proof_public_vals.len()={} and func_call.proofs.len()={} do not match",
  113. proofs_public_vals.len(),
  114. func_call.proofs.len()
  115. );
  116. for (i, (proof, (key, public_vals))) in
  117. func_call.proofs.iter().zip(proofs_public_vals.iter()).enumerate()
  118. {
  119. match zk_bins.lookup(key).unwrap() {
  120. ZkContractInfo::Binary(info) => {
  121. let verifying_key = &info.verifying_key;
  122. let verify_result = proof.verify(verifying_key, public_vals);
  123. assert!(verify_result.is_ok(), "verify proof[{}]='{}' failed", i, key);
  124. }
  125. ZkContractInfo::Native(info) => {
  126. let verifying_key = &info.verifying_key;
  127. let verify_result = proof.verify(verifying_key, public_vals);
  128. assert!(verify_result.is_ok(), "verify proof[{}]='{}' failed", i, key);
  129. }
  130. };
  131. debug!(target: "demo", "zk_verify({}) passed [i={}]", key, i);
  132. }
  133. }
  134. }
  135. fn verify_sigs(&self) {
  136. let mut unsigned_tx_data = vec![];
  137. for (i, (func_call, signature)) in
  138. self.func_calls.iter().zip(self.signatures.clone()).enumerate()
  139. {
  140. func_call.encode(&mut unsigned_tx_data).expect("failed to encode data");
  141. let signature_pub_keys = func_call.call_data.signature_public_keys();
  142. for signature_pub_key in signature_pub_keys {
  143. let verify_result = signature_pub_key.verify(&unsigned_tx_data[..], &signature);
  144. assert!(verify_result, "verify sigs[{}] failed", i);
  145. }
  146. debug!(target: "demo", "verify_sigs({}) passed", i);
  147. }
  148. }
  149. }
  150. fn sign(signature_secrets: &[SecretKey], func_calls: &[FuncCall]) -> Vec<Signature> {
  151. let mut signatures = vec![];
  152. let mut unsigned_tx_data = vec![];
  153. for (_i, (signature_secret, func_call)) in
  154. signature_secrets.iter().zip(func_calls.iter()).enumerate()
  155. {
  156. func_call.encode(&mut unsigned_tx_data).expect("failed to encode data");
  157. let signature = signature_secret.sign(&unsigned_tx_data[..]);
  158. signatures.push(signature);
  159. }
  160. signatures
  161. }
  162. type ContractId = pallas::Base;
  163. type FuncId = pallas::Base;
  164. pub struct FuncCall {
  165. pub contract_id: ContractId,
  166. pub func_id: FuncId,
  167. pub call_data: Box<dyn CallDataBase>,
  168. pub proofs: Vec<Proof>,
  169. }
  170. impl Encodable for FuncCall {
  171. fn encode<W: io::Write>(&self, mut w: W) -> core::result::Result<usize, io::Error> {
  172. let mut len = 0;
  173. len += self.contract_id.encode(&mut w)?;
  174. len += self.func_id.encode(&mut w)?;
  175. len += self.proofs.encode(&mut w)?;
  176. len += self.call_data.encode_bytes(&mut w)?;
  177. Ok(len)
  178. }
  179. }
  180. pub trait CallDataBase {
  181. // Public values for verifying the proofs
  182. // Needed so we can convert internal types so they can be used in Proof::verify()
  183. fn zk_public_values(&self) -> Vec<(String, Vec<DrkCircuitField>)>;
  184. // For upcasting to CallData itself so it can be read in state_transition()
  185. fn as_any(&self) -> &dyn Any;
  186. // Public keys we will use to verify transaction signatures.
  187. fn signature_public_keys(&self) -> Vec<PublicKey>;
  188. fn encode_bytes(
  189. &self,
  190. writer: &mut dyn std::io::Write,
  191. ) -> core::result::Result<usize, std::io::Error>;
  192. }
  193. type GenericContractState = Box<dyn Any>;
  194. pub struct StateRegistry {
  195. pub states: HashMap<HashableBase, GenericContractState>,
  196. }
  197. impl StateRegistry {
  198. fn new() -> Self {
  199. Self { states: HashMap::new() }
  200. }
  201. fn register(&mut self, contract_id: ContractId, state: GenericContractState) {
  202. debug!(target: "StateRegistry::register()", "contract_id: {:?}", contract_id);
  203. self.states.insert(HashableBase(contract_id), state);
  204. }
  205. //pub fn lookup_mut<'a, S: 'static>(&'a mut self, contract_id: ContractId) -> Option<&'a mut S> {
  206. pub fn lookup_mut<S: 'static>(&mut self, contract_id: ContractId) -> Option<&mut S> {
  207. self.states.get_mut(&HashableBase(contract_id)).and_then(|state| state.downcast_mut())
  208. }
  209. //pub fn lookup<'a, S: 'static>(&'a self, contract_id: ContractId) -> Option<&'a S> {
  210. pub fn lookup<S: 'static>(&self, contract_id: ContractId) -> Option<&S> {
  211. self.states.get(&HashableBase(contract_id)).and_then(|state| state.downcast_ref())
  212. }
  213. }
  214. pub trait UpdateBase {
  215. fn apply(self: Box<Self>, states: &mut StateRegistry);
  216. }
  217. ///////////////////////////////////////////////////
  218. ///// Example contract
  219. ///////////////////////////////////////////////////
  220. pub async fn example() -> Result<()> {
  221. debug!(target: "demo", "Stage 0. Example contract");
  222. // Lookup table for smart contract states
  223. let mut states = StateRegistry::new();
  224. // Initialize ZK binary table
  225. let mut zk_bins = ZkContractTable::new();
  226. let zk_example_foo_bincode = include_bytes!("../proof/foo.zk.bin");
  227. let zk_example_foo_bin = ZkBinary::decode(zk_example_foo_bincode)?;
  228. zk_bins.add_contract("example-foo".to_string(), zk_example_foo_bin, 13);
  229. let example_state = example_contract::state::State::new();
  230. states.register(*example_contract::CONTRACT_ID, example_state);
  231. //// Wallet
  232. let foo_w = example_contract::foo::wallet::Foo { a: 5, b: 10 };
  233. let signature_secret = SecretKey::random(&mut OsRng);
  234. let builder = example_contract::foo::wallet::Builder { foo: foo_w, signature_secret };
  235. let func_call = builder.build(&zk_bins);
  236. let func_calls = vec![func_call];
  237. let signatures = sign(&[signature_secret], &func_calls);
  238. let tx = Transaction { func_calls, signatures };
  239. //// Validator
  240. let mut updates = vec![];
  241. // Validate all function calls in the tx
  242. for (idx, func_call) in tx.func_calls.iter().enumerate() {
  243. if func_call.func_id == *example_contract::foo::FUNC_ID {
  244. debug!("example_contract::foo::state_transition()");
  245. let update = example_contract::foo::validate::state_transition(&states, idx, &tx)
  246. .expect("example_contract::foo::validate::state_transition() failed!");
  247. updates.push(update);
  248. }
  249. }
  250. // Atomically apply all changes
  251. for update in updates {
  252. update.apply(&mut states);
  253. }
  254. tx.zk_verify(&zk_bins);
  255. tx.verify_sigs();
  256. Ok(())
  257. }
  258. pub async fn demo() -> Result<()> {
  259. // Example smart contract
  260. //// TODO: this will be moved to a different file
  261. example().await?;
  262. // Money parameters
  263. let xdrk_supply = 1_000_000;
  264. let xdrk_token_id = pallas::Base::random(&mut OsRng);
  265. // Governance token parameters
  266. let gdrk_supply = 1_000_000;
  267. let gdrk_token_id = pallas::Base::random(&mut OsRng);
  268. // DAO parameters
  269. let dao_proposer_limit = 110;
  270. let dao_quorum = 110;
  271. let dao_approval_ratio_quot = 1;
  272. let dao_approval_ratio_base = 2;
  273. // Lookup table for smart contract states
  274. let mut states = StateRegistry::new();
  275. // Initialize ZK binary table
  276. let mut zk_bins = ZkContractTable::new();
  277. debug!(target: "demo", "Loading dao-mint.zk");
  278. let zk_dao_mint_bincode = include_bytes!("../proof/dao-mint.zk.bin");
  279. let zk_dao_mint_bin = ZkBinary::decode(zk_dao_mint_bincode)?;
  280. zk_bins.add_contract("dao-mint".to_string(), zk_dao_mint_bin, 13);
  281. debug!(target: "demo", "Loading money-transfer contracts");
  282. {
  283. let start = Instant::now();
  284. let mint_pk = ProvingKey::build(11, &MintContract::default());
  285. debug!("Mint PK: [{:?}]", start.elapsed());
  286. let start = Instant::now();
  287. let burn_pk = ProvingKey::build(11, &BurnContract::default());
  288. debug!("Burn PK: [{:?}]", start.elapsed());
  289. let start = Instant::now();
  290. let mint_vk = VerifyingKey::build(11, &MintContract::default());
  291. debug!("Mint VK: [{:?}]", start.elapsed());
  292. let start = Instant::now();
  293. let burn_vk = VerifyingKey::build(11, &BurnContract::default());
  294. debug!("Burn VK: [{:?}]", start.elapsed());
  295. zk_bins.add_native("money-transfer-mint".to_string(), mint_pk, mint_vk);
  296. zk_bins.add_native("money-transfer-burn".to_string(), burn_pk, burn_vk);
  297. }
  298. debug!(target: "demo", "Loading dao-propose-main.zk");
  299. let zk_dao_propose_main_bincode = include_bytes!("../proof/dao-propose-main.zk.bin");
  300. let zk_dao_propose_main_bin = ZkBinary::decode(zk_dao_propose_main_bincode)?;
  301. zk_bins.add_contract("dao-propose-main".to_string(), zk_dao_propose_main_bin, 13);
  302. debug!(target: "demo", "Loading dao-propose-burn.zk");
  303. let zk_dao_propose_burn_bincode = include_bytes!("../proof/dao-propose-burn.zk.bin");
  304. let zk_dao_propose_burn_bin = ZkBinary::decode(zk_dao_propose_burn_bincode)?;
  305. zk_bins.add_contract("dao-propose-burn".to_string(), zk_dao_propose_burn_bin, 13);
  306. debug!(target: "demo", "Loading dao-vote-main.zk");
  307. let zk_dao_vote_main_bincode = include_bytes!("../proof/dao-vote-main.zk.bin");
  308. let zk_dao_vote_main_bin = ZkBinary::decode(zk_dao_vote_main_bincode)?;
  309. zk_bins.add_contract("dao-vote-main".to_string(), zk_dao_vote_main_bin, 13);
  310. debug!(target: "demo", "Loading dao-vote-burn.zk");
  311. let zk_dao_vote_burn_bincode = include_bytes!("../proof/dao-vote-burn.zk.bin");
  312. let zk_dao_vote_burn_bin = ZkBinary::decode(zk_dao_vote_burn_bincode)?;
  313. zk_bins.add_contract("dao-vote-burn".to_string(), zk_dao_vote_burn_bin, 13);
  314. let zk_dao_exec_bincode = include_bytes!("../proof/dao-exec.zk.bin");
  315. let zk_dao_exec_bin = ZkBinary::decode(zk_dao_exec_bincode)?;
  316. zk_bins.add_contract("dao-exec".to_string(), zk_dao_exec_bin, 13);
  317. // State for money contracts
  318. let cashier_signature_secret = SecretKey::random(&mut OsRng);
  319. let cashier_signature_public = PublicKey::from_secret(cashier_signature_secret);
  320. let faucet_signature_secret = SecretKey::random(&mut OsRng);
  321. let faucet_signature_public = PublicKey::from_secret(faucet_signature_secret);
  322. ///////////////////////////////////////////////////
  323. let money_state =
  324. money_contract::state::State::new(cashier_signature_public, faucet_signature_public);
  325. states.register(*money_contract::CONTRACT_ID, money_state);
  326. /////////////////////////////////////////////////////
  327. let dao_state = dao_contract::State::new();
  328. states.register(*dao_contract::CONTRACT_ID, dao_state);
  329. /////////////////////////////////////////////////////
  330. ////// Create the DAO bulla
  331. /////////////////////////////////////////////////////
  332. debug!(target: "demo", "Stage 1. Creating DAO bulla");
  333. //// Wallet
  334. //// Setup the DAO
  335. let dao_keypair = Keypair::random(&mut OsRng);
  336. let dao_bulla_blind = pallas::Base::random(&mut OsRng);
  337. let signature_secret = SecretKey::random(&mut OsRng);
  338. // Create DAO mint tx
  339. let builder = dao_contract::mint::wallet::Builder {
  340. dao_proposer_limit,
  341. dao_quorum,
  342. dao_approval_ratio_quot,
  343. dao_approval_ratio_base,
  344. gov_token_id: gdrk_token_id,
  345. dao_pubkey: dao_keypair.public,
  346. dao_bulla_blind,
  347. _signature_secret: signature_secret,
  348. };
  349. let func_call = builder.build(&zk_bins);
  350. let func_calls = vec![func_call];
  351. let signatures = sign(&[signature_secret], &func_calls);
  352. let tx = Transaction { func_calls, signatures };
  353. //// Validator
  354. let mut updates = vec![];
  355. // Validate all function calls in the tx
  356. for (idx, func_call) in tx.func_calls.iter().enumerate() {
  357. // So then the verifier will lookup the corresponding state_transition and apply
  358. // functions based off the func_id
  359. if func_call.func_id == *dao_contract::mint::FUNC_ID {
  360. debug!("dao_contract::mint::state_transition()");
  361. let update = dao_contract::mint::validate::state_transition(&states, idx, &tx)
  362. .expect("dao_contract::mint::validate::state_transition() failed!");
  363. updates.push(update);
  364. }
  365. }
  366. // Atomically apply all changes
  367. for update in updates {
  368. update.apply(&mut states);
  369. }
  370. tx.zk_verify(&zk_bins);
  371. tx.verify_sigs();
  372. // Wallet stuff
  373. // In your wallet, wait until you see the tx confirmed before doing anything below
  374. // So for example keep track of tx hash
  375. //assert_eq!(tx.hash(), tx_hash);
  376. // We need to witness() the value in our local merkle tree
  377. // Must be called as soon as this DAO bulla is added to the state
  378. let dao_leaf_position = {
  379. let state = states.lookup_mut::<dao_contract::State>(*dao_contract::CONTRACT_ID).unwrap();
  380. state.dao_tree.witness().unwrap()
  381. };
  382. // It might just be easier to hash it ourselves from keypair and blind...
  383. let dao_bulla = {
  384. assert_eq!(tx.func_calls.len(), 1);
  385. let func_call = &tx.func_calls[0];
  386. let call_data = func_call.call_data.as_any();
  387. assert_eq!((*call_data).type_id(), TypeId::of::<dao_contract::mint::validate::CallData>());
  388. let call_data = call_data.downcast_ref::<dao_contract::mint::validate::CallData>().unwrap();
  389. call_data.dao_bulla.clone()
  390. };
  391. debug!(target: "demo", "Create DAO bulla: {:?}", dao_bulla.0);
  392. ///////////////////////////////////////////////////
  393. //// Mint the initial supply of treasury token
  394. //// and send it all to the DAO directly
  395. ///////////////////////////////////////////////////
  396. debug!(target: "demo", "Stage 2. Minting treasury token");
  397. let state = states.lookup_mut::<money_contract::State>(*money_contract::CONTRACT_ID).unwrap();
  398. state.wallet_cache.track(dao_keypair.secret);
  399. //// Wallet
  400. // Address of deployed contract in our example is dao_contract::exec::FUNC_ID
  401. // This field is public, you can see it's being sent to a DAO
  402. // but nothing else is visible.
  403. //
  404. // In the python code we wrote:
  405. //
  406. // spend_hook = b"0xdao_ruleset"
  407. //
  408. let spend_hook = *dao_contract::exec::FUNC_ID;
  409. // The user_data can be a simple hash of the items passed into the ZK proof
  410. // up to corresponding linked ZK proof to interpret however they need.
  411. // In out case, it's the bulla for the DAO
  412. let user_data = dao_bulla.0;
  413. let builder = money_contract::transfer::wallet::Builder {
  414. clear_inputs: vec![money_contract::transfer::wallet::BuilderClearInputInfo {
  415. value: xdrk_supply,
  416. token_id: xdrk_token_id,
  417. signature_secret: cashier_signature_secret,
  418. }],
  419. inputs: vec![],
  420. outputs: vec![money_contract::transfer::wallet::BuilderOutputInfo {
  421. value: xdrk_supply,
  422. token_id: xdrk_token_id,
  423. public: dao_keypair.public,
  424. serial: pallas::Base::random(&mut OsRng),
  425. coin_blind: pallas::Base::random(&mut OsRng),
  426. spend_hook,
  427. user_data,
  428. }],
  429. };
  430. let func_call = builder.build(&zk_bins)?;
  431. let func_calls = vec![func_call];
  432. let signatures = sign(&[cashier_signature_secret], &func_calls);
  433. let tx = Transaction { func_calls, signatures };
  434. //// Validator
  435. let mut updates = vec![];
  436. // Validate all function calls in the tx
  437. for (idx, func_call) in tx.func_calls.iter().enumerate() {
  438. // So then the verifier will lookup the corresponding state_transition and apply
  439. // functions based off the func_id
  440. if func_call.func_id == *money_contract::transfer::FUNC_ID {
  441. debug!("money_contract::transfer::state_transition()");
  442. let update = money_contract::transfer::validate::state_transition(&states, idx, &tx)
  443. .expect("money_contract::transfer::validate::state_transition() failed!");
  444. updates.push(update);
  445. }
  446. }
  447. // Atomically apply all changes
  448. for update in updates {
  449. update.apply(&mut states);
  450. }
  451. tx.zk_verify(&zk_bins);
  452. tx.verify_sigs();
  453. //// Wallet
  454. // DAO reads the money received from the encrypted note
  455. let state = states.lookup_mut::<money_contract::State>(*money_contract::CONTRACT_ID).unwrap();
  456. let mut recv_coins = state.wallet_cache.get_received(&dao_keypair.secret);
  457. assert_eq!(recv_coins.len(), 1);
  458. let dao_recv_coin = recv_coins.pop().unwrap();
  459. let treasury_note = dao_recv_coin.note;
  460. // Check the actual coin received is valid before accepting it
  461. let coords = dao_keypair.public.0.to_affine().coordinates().unwrap();
  462. let coin = poseidon_hash::<8>([
  463. *coords.x(),
  464. *coords.y(),
  465. DrkValue::from(treasury_note.value),
  466. treasury_note.token_id,
  467. treasury_note.serial,
  468. treasury_note.spend_hook,
  469. treasury_note.user_data,
  470. treasury_note.coin_blind,
  471. ]);
  472. assert_eq!(coin, dao_recv_coin.coin.0);
  473. assert_eq!(treasury_note.spend_hook, *dao_contract::exec::FUNC_ID);
  474. assert_eq!(treasury_note.user_data, dao_bulla.0);
  475. debug!("DAO received a coin worth {} xDRK", treasury_note.value);
  476. ///////////////////////////////////////////////////
  477. //// Mint the governance token
  478. //// Send it to three hodlers
  479. ///////////////////////////////////////////////////
  480. debug!(target: "demo", "Stage 3. Minting governance token");
  481. //// Wallet
  482. // Hodler 1
  483. let gov_keypair_1 = Keypair::random(&mut OsRng);
  484. // Hodler 2
  485. let gov_keypair_2 = Keypair::random(&mut OsRng);
  486. // Hodler 3: the tiebreaker
  487. let gov_keypair_3 = Keypair::random(&mut OsRng);
  488. let state = states.lookup_mut::<money_contract::State>(*money_contract::CONTRACT_ID).unwrap();
  489. state.wallet_cache.track(gov_keypair_1.secret);
  490. state.wallet_cache.track(gov_keypair_2.secret);
  491. state.wallet_cache.track(gov_keypair_3.secret);
  492. let gov_keypairs = vec![gov_keypair_1, gov_keypair_2, gov_keypair_3];
  493. // Spend hook and user data disabled
  494. let spend_hook = DrkSpendHook::from(0);
  495. let user_data = DrkUserData::from(0);
  496. let output1 = money_contract::transfer::wallet::BuilderOutputInfo {
  497. value: 400000,
  498. token_id: gdrk_token_id,
  499. public: gov_keypair_1.public,
  500. serial: pallas::Base::random(&mut OsRng),
  501. coin_blind: pallas::Base::random(&mut OsRng),
  502. spend_hook,
  503. user_data,
  504. };
  505. let output2 = money_contract::transfer::wallet::BuilderOutputInfo {
  506. value: 400000,
  507. token_id: gdrk_token_id,
  508. public: gov_keypair_2.public,
  509. serial: pallas::Base::random(&mut OsRng),
  510. coin_blind: pallas::Base::random(&mut OsRng),
  511. spend_hook,
  512. user_data,
  513. };
  514. let output3 = money_contract::transfer::wallet::BuilderOutputInfo {
  515. value: 200000,
  516. token_id: gdrk_token_id,
  517. public: gov_keypair_3.public,
  518. serial: pallas::Base::random(&mut OsRng),
  519. coin_blind: pallas::Base::random(&mut OsRng),
  520. spend_hook,
  521. user_data,
  522. };
  523. assert!(2 * 400000 + 200000 == gdrk_supply);
  524. let builder = money_contract::transfer::wallet::Builder {
  525. clear_inputs: vec![money_contract::transfer::wallet::BuilderClearInputInfo {
  526. value: gdrk_supply,
  527. token_id: gdrk_token_id,
  528. signature_secret: cashier_signature_secret,
  529. }],
  530. inputs: vec![],
  531. outputs: vec![output1, output2, output3],
  532. };
  533. let func_call = builder.build(&zk_bins)?;
  534. let func_calls = vec![func_call];
  535. let signatures = sign(&[cashier_signature_secret], &func_calls);
  536. let tx = Transaction { func_calls, signatures };
  537. //// Validator
  538. let mut updates = vec![];
  539. // Validate all function calls in the tx
  540. for (idx, func_call) in tx.func_calls.iter().enumerate() {
  541. // So then the verifier will lookup the corresponding state_transition and apply
  542. // functions based off the func_id
  543. if func_call.func_id == *money_contract::transfer::FUNC_ID {
  544. debug!("money_contract::transfer::state_transition()");
  545. let update = money_contract::transfer::validate::state_transition(&states, idx, &tx)
  546. .expect("money_contract::transfer::validate::state_transition() failed!");
  547. updates.push(update);
  548. }
  549. }
  550. // Atomically apply all changes
  551. for update in updates {
  552. update.apply(&mut states);
  553. }
  554. tx.zk_verify(&zk_bins);
  555. tx.verify_sigs();
  556. //// Wallet
  557. let mut gov_recv = vec![None, None, None];
  558. // Check that each person received one coin
  559. for (i, key) in gov_keypairs.iter().enumerate() {
  560. let gov_recv_coin = {
  561. let state =
  562. states.lookup_mut::<money_contract::State>(*money_contract::CONTRACT_ID).unwrap();
  563. let mut recv_coins = state.wallet_cache.get_received(&key.secret);
  564. assert_eq!(recv_coins.len(), 1);
  565. let recv_coin = recv_coins.pop().unwrap();
  566. let note = &recv_coin.note;
  567. assert_eq!(note.token_id, gdrk_token_id);
  568. // Normal payment
  569. assert_eq!(note.spend_hook, pallas::Base::from(0));
  570. assert_eq!(note.user_data, pallas::Base::from(0));
  571. let coords = key.public.0.to_affine().coordinates().unwrap();
  572. let coin = poseidon_hash::<8>([
  573. *coords.x(),
  574. *coords.y(),
  575. DrkValue::from(note.value),
  576. note.token_id,
  577. note.serial,
  578. note.spend_hook,
  579. note.user_data,
  580. note.coin_blind,
  581. ]);
  582. assert_eq!(coin, recv_coin.coin.0);
  583. debug!("Holder{} received a coin worth {} gDRK", i, note.value);
  584. recv_coin
  585. };
  586. gov_recv[i] = Some(gov_recv_coin);
  587. }
  588. // unwrap them for this demo
  589. let gov_recv: Vec<_> = gov_recv.into_iter().map(|r| r.unwrap()).collect();
  590. ///////////////////////////////////////////////////
  591. // DAO rules:
  592. // 1. gov token IDs must match on all inputs
  593. // 2. proposals must be submitted by minimum amount
  594. // 3. all votes >= quorum
  595. // 4. outcome > approval_ratio
  596. // 5. structure of outputs
  597. // output 0: value and address
  598. // output 1: change address
  599. ///////////////////////////////////////////////////
  600. ///////////////////////////////////////////////////
  601. // Propose the vote
  602. // In order to make a valid vote, first the proposer must
  603. // meet a criteria for a minimum number of gov tokens
  604. ///////////////////////////////////////////////////
  605. debug!(target: "demo", "Stage 4. Propose the vote");
  606. //// Wallet
  607. // TODO: look into proposal expiry once time for voting has finished
  608. let user_keypair = Keypair::random(&mut OsRng);
  609. let (money_leaf_position, money_merkle_path) = {
  610. let state = states.lookup::<money_contract::State>(*money_contract::CONTRACT_ID).unwrap();
  611. let tree = &state.tree;
  612. let leaf_position = gov_recv[0].leaf_position;
  613. let root = tree.root(0).unwrap();
  614. let merkle_path = tree.authentication_path(leaf_position, &root).unwrap();
  615. (leaf_position, merkle_path)
  616. };
  617. // TODO: is it possible for an invalid transfer() to be constructed on exec()?
  618. // need to look into this
  619. let signature_secret = SecretKey::random(&mut OsRng);
  620. let input = dao_contract::propose::wallet::BuilderInput {
  621. secret: gov_keypair_1.secret,
  622. note: gov_recv[0].note.clone(),
  623. leaf_position: money_leaf_position,
  624. merkle_path: money_merkle_path,
  625. signature_secret,
  626. };
  627. let (dao_merkle_path, dao_merkle_root) = {
  628. let state = states.lookup::<dao_contract::State>(*dao_contract::CONTRACT_ID).unwrap();
  629. let tree = &state.dao_tree;
  630. let root = tree.root(0).unwrap();
  631. let merkle_path = tree.authentication_path(dao_leaf_position, &root).unwrap();
  632. (merkle_path, root)
  633. };
  634. let dao_params = dao_contract::mint::wallet::DaoParams {
  635. proposer_limit: dao_proposer_limit,
  636. quorum: dao_quorum,
  637. approval_ratio_base: dao_approval_ratio_base,
  638. approval_ratio_quot: dao_approval_ratio_quot,
  639. gov_token_id: gdrk_token_id,
  640. public_key: dao_keypair.public,
  641. bulla_blind: dao_bulla_blind,
  642. };
  643. let proposal = dao_contract::propose::wallet::Proposal {
  644. dest: user_keypair.public,
  645. amount: 1000,
  646. serial: pallas::Base::random(&mut OsRng),
  647. token_id: xdrk_token_id,
  648. blind: pallas::Base::random(&mut OsRng),
  649. };
  650. let builder = dao_contract::propose::wallet::Builder {
  651. inputs: vec![input],
  652. proposal,
  653. dao: dao_params.clone(),
  654. dao_leaf_position,
  655. dao_merkle_path,
  656. dao_merkle_root,
  657. };
  658. let func_call = builder.build(&zk_bins);
  659. let func_calls = vec![func_call];
  660. let signatures = sign(&[signature_secret], &func_calls);
  661. let tx = Transaction { func_calls, signatures };
  662. //// Validator
  663. let mut updates = vec![];
  664. // Validate all function calls in the tx
  665. for (idx, func_call) in tx.func_calls.iter().enumerate() {
  666. if func_call.func_id == *dao_contract::propose::FUNC_ID {
  667. debug!(target: "demo", "dao_contract::propose::state_transition()");
  668. let update = dao_contract::propose::validate::state_transition(&states, idx, &tx)
  669. .expect("dao_contract::propose::validate::state_transition() failed!");
  670. updates.push(update);
  671. }
  672. }
  673. // Atomically apply all changes
  674. for update in updates {
  675. update.apply(&mut states);
  676. }
  677. tx.zk_verify(&zk_bins);
  678. tx.verify_sigs();
  679. //// Wallet
  680. // Read received proposal
  681. let (proposal, proposal_bulla) = {
  682. assert_eq!(tx.func_calls.len(), 1);
  683. let func_call = &tx.func_calls[0];
  684. let call_data = func_call.call_data.as_any();
  685. assert_eq!(
  686. (*call_data).type_id(),
  687. TypeId::of::<dao_contract::propose::validate::CallData>()
  688. );
  689. let call_data =
  690. call_data.downcast_ref::<dao_contract::propose::validate::CallData>().unwrap();
  691. let header = &call_data.header;
  692. let note: dao_contract::propose::wallet::Note =
  693. header.enc_note.decrypt(&dao_keypair.secret).unwrap();
  694. // TODO: check it belongs to DAO bulla
  695. // Return the proposal info
  696. (note.proposal, call_data.header.proposal_bulla)
  697. };
  698. debug!(target: "demo", "Proposal now active!");
  699. debug!(target: "demo", " destination: {:?}", proposal.dest);
  700. debug!(target: "demo", " amount: {}", proposal.amount);
  701. debug!(target: "demo", " token_id: {:?}", proposal.token_id);
  702. debug!(target: "demo", " dao_bulla: {:?}", dao_bulla.0);
  703. debug!(target: "demo", "Proposal bulla: {:?}", proposal_bulla);
  704. ///////////////////////////////////////////////////
  705. // Proposal is accepted!
  706. // Start the voting
  707. ///////////////////////////////////////////////////
  708. // Copying these schizo comments from python code:
  709. // Lets the voting begin
  710. // Voters have access to the proposal and dao data
  711. // vote_state = VoteState()
  712. // We don't need to copy nullifier set because it is checked from gov_state
  713. // in vote_state_transition() anyway
  714. //
  715. // TODO: what happens if voters don't unblind their vote
  716. // Answer:
  717. // 1. there is a time limit
  718. // 2. both the MPC or users can unblind
  719. //
  720. // TODO: bug if I vote then send money, then we can double vote
  721. // TODO: all timestamps missing
  722. // - timelock (future voting starts in 2 days)
  723. // Fix: use nullifiers from money gov state only from
  724. // beginning of gov period
  725. // Cannot use nullifiers from before voting period
  726. debug!(target: "demo", "Stage 5. Start voting");
  727. // We were previously saving updates here for testing
  728. // let mut updates = vec![];
  729. // User 1: YES
  730. let (money_leaf_position, money_merkle_path) = {
  731. let state = states.lookup::<money_contract::State>(*money_contract::CONTRACT_ID).unwrap();
  732. let tree = &state.tree;
  733. let leaf_position = gov_recv[0].leaf_position;
  734. let root = tree.root(0).unwrap();
  735. let merkle_path = tree.authentication_path(leaf_position, &root).unwrap();
  736. (leaf_position, merkle_path)
  737. };
  738. let signature_secret = SecretKey::random(&mut OsRng);
  739. let input = dao_contract::vote::wallet::BuilderInput {
  740. secret: gov_keypair_1.secret,
  741. note: gov_recv[0].note.clone(),
  742. leaf_position: money_leaf_position,
  743. merkle_path: money_merkle_path,
  744. signature_secret,
  745. };
  746. let vote_option: bool = true;
  747. // assert!(vote_option || !vote_option); // wtf
  748. // We create a new keypair to encrypt the vote.
  749. // For the demo MVP, you can just use the dao_keypair secret
  750. let vote_keypair_1 = Keypair::random(&mut OsRng);
  751. let builder = dao_contract::vote::wallet::Builder {
  752. inputs: vec![input],
  753. vote: dao_contract::vote::wallet::Vote {
  754. vote_option,
  755. vote_option_blind: pallas::Scalar::random(&mut OsRng),
  756. },
  757. vote_keypair: vote_keypair_1,
  758. proposal: proposal.clone(),
  759. dao: dao_params.clone(),
  760. };
  761. debug!(target: "demo", "build()...");
  762. let func_call = builder.build(&zk_bins);
  763. let func_calls = vec![func_call];
  764. let signatures = sign(&[signature_secret], &func_calls);
  765. let tx = Transaction { func_calls, signatures };
  766. //// Validator
  767. let mut updates = vec![];
  768. // Validate all function calls in the tx
  769. for (idx, func_call) in tx.func_calls.iter().enumerate() {
  770. if func_call.func_id == *dao_contract::vote::FUNC_ID {
  771. debug!(target: "demo", "dao_contract::vote::state_transition()");
  772. let update = dao_contract::vote::validate::state_transition(&states, idx, &tx)
  773. .expect("dao_contract::vote::validate::state_transition() failed!");
  774. updates.push(update);
  775. }
  776. }
  777. // Atomically apply all changes
  778. for update in updates {
  779. update.apply(&mut states);
  780. }
  781. tx.zk_verify(&zk_bins);
  782. tx.verify_sigs();
  783. //// Wallet
  784. // Secret vote info. Needs to be revealed at some point.
  785. // TODO: look into verifiable encryption for notes
  786. // TODO: look into timelock puzzle as a possibility
  787. let vote_note_1 = {
  788. assert_eq!(tx.func_calls.len(), 1);
  789. let func_call = &tx.func_calls[0];
  790. let call_data = func_call.call_data.as_any();
  791. assert_eq!((*call_data).type_id(), TypeId::of::<dao_contract::vote::validate::CallData>());
  792. let call_data = call_data.downcast_ref::<dao_contract::vote::validate::CallData>().unwrap();
  793. let header = &call_data.header;
  794. let note: dao_contract::vote::wallet::Note =
  795. header.enc_note.decrypt(&vote_keypair_1.secret).unwrap();
  796. note
  797. };
  798. debug!(target: "demo", "User 1 voted!");
  799. debug!(target: "demo", " vote_option: {}", vote_note_1.vote.vote_option);
  800. debug!(target: "demo", " value: {}", vote_note_1.vote_value);
  801. // User 2: NO
  802. let (money_leaf_position, money_merkle_path) = {
  803. let state = states.lookup::<money_contract::State>(*money_contract::CONTRACT_ID).unwrap();
  804. let tree = &state.tree;
  805. let leaf_position = gov_recv[1].leaf_position;
  806. let root = tree.root(0).unwrap();
  807. let merkle_path = tree.authentication_path(leaf_position, &root).unwrap();
  808. (leaf_position, merkle_path)
  809. };
  810. let signature_secret = SecretKey::random(&mut OsRng);
  811. let input = dao_contract::vote::wallet::BuilderInput {
  812. secret: gov_keypair_2.secret,
  813. note: gov_recv[1].note.clone(),
  814. leaf_position: money_leaf_position,
  815. merkle_path: money_merkle_path,
  816. signature_secret,
  817. };
  818. let vote_option: bool = false;
  819. // assert!(vote_option || !vote_option); // wtf
  820. // We create a new keypair to encrypt the vote.
  821. let vote_keypair_2 = Keypair::random(&mut OsRng);
  822. let builder = dao_contract::vote::wallet::Builder {
  823. inputs: vec![input],
  824. vote: dao_contract::vote::wallet::Vote {
  825. vote_option,
  826. vote_option_blind: pallas::Scalar::random(&mut OsRng),
  827. },
  828. vote_keypair: vote_keypair_2,
  829. proposal: proposal.clone(),
  830. dao: dao_params.clone(),
  831. };
  832. debug!(target: "demo", "build()...");
  833. let func_call = builder.build(&zk_bins);
  834. let func_calls = vec![func_call];
  835. let signatures = sign(&[signature_secret], &func_calls);
  836. let tx = Transaction { func_calls, signatures };
  837. //// Validator
  838. let mut updates = vec![];
  839. // Validate all function calls in the tx
  840. for (idx, func_call) in tx.func_calls.iter().enumerate() {
  841. if func_call.func_id == *dao_contract::vote::FUNC_ID {
  842. debug!(target: "demo", "dao_contract::vote::state_transition()");
  843. let update = dao_contract::vote::validate::state_transition(&states, idx, &tx)
  844. .expect("dao_contract::vote::validate::state_transition() failed!");
  845. updates.push(update);
  846. }
  847. }
  848. // Atomically apply all changes
  849. for update in updates {
  850. update.apply(&mut states);
  851. }
  852. tx.zk_verify(&zk_bins);
  853. tx.verify_sigs();
  854. //// Wallet
  855. // Secret vote info. Needs to be revealed at some point.
  856. // TODO: look into verifiable encryption for notes
  857. // TODO: look into timelock puzzle as a possibility
  858. let vote_note_2 = {
  859. assert_eq!(tx.func_calls.len(), 1);
  860. let func_call = &tx.func_calls[0];
  861. let call_data = func_call.call_data.as_any();
  862. assert_eq!((*call_data).type_id(), TypeId::of::<dao_contract::vote::validate::CallData>());
  863. let call_data = call_data.downcast_ref::<dao_contract::vote::validate::CallData>().unwrap();
  864. let header = &call_data.header;
  865. let note: dao_contract::vote::wallet::Note =
  866. header.enc_note.decrypt(&vote_keypair_2.secret).unwrap();
  867. note
  868. };
  869. debug!(target: "demo", "User 2 voted!");
  870. debug!(target: "demo", " vote_option: {}", vote_note_2.vote.vote_option);
  871. debug!(target: "demo", " value: {}", vote_note_2.vote_value);
  872. // User 3: YES
  873. let (money_leaf_position, money_merkle_path) = {
  874. let state = states.lookup::<money_contract::State>(*money_contract::CONTRACT_ID).unwrap();
  875. let tree = &state.tree;
  876. let leaf_position = gov_recv[2].leaf_position;
  877. let root = tree.root(0).unwrap();
  878. let merkle_path = tree.authentication_path(leaf_position, &root).unwrap();
  879. (leaf_position, merkle_path)
  880. };
  881. let signature_secret = SecretKey::random(&mut OsRng);
  882. let input = dao_contract::vote::wallet::BuilderInput {
  883. secret: gov_keypair_3.secret,
  884. note: gov_recv[2].note.clone(),
  885. leaf_position: money_leaf_position,
  886. merkle_path: money_merkle_path,
  887. signature_secret,
  888. };
  889. let vote_option: bool = true;
  890. // assert!(vote_option || !vote_option); // wtf
  891. // We create a new keypair to encrypt the vote.
  892. let vote_keypair_3 = Keypair::random(&mut OsRng);
  893. let builder = dao_contract::vote::wallet::Builder {
  894. inputs: vec![input],
  895. vote: dao_contract::vote::wallet::Vote {
  896. vote_option,
  897. vote_option_blind: pallas::Scalar::random(&mut OsRng),
  898. },
  899. vote_keypair: vote_keypair_3,
  900. proposal: proposal.clone(),
  901. dao: dao_params.clone(),
  902. };
  903. debug!(target: "demo", "build()...");
  904. let func_call = builder.build(&zk_bins);
  905. let func_calls = vec![func_call];
  906. let signatures = sign(&[signature_secret], &func_calls);
  907. let tx = Transaction { func_calls, signatures };
  908. //// Validator
  909. let mut updates = vec![];
  910. // Validate all function calls in the tx
  911. for (idx, func_call) in tx.func_calls.iter().enumerate() {
  912. if func_call.func_id == *dao_contract::vote::FUNC_ID {
  913. debug!(target: "demo", "dao_contract::vote::state_transition()");
  914. let update = dao_contract::vote::validate::state_transition(&states, idx, &tx)
  915. .expect("dao_contract::vote::validate::state_transition() failed!");
  916. updates.push(update);
  917. }
  918. }
  919. // Atomically apply all changes
  920. for update in updates {
  921. update.apply(&mut states);
  922. }
  923. tx.zk_verify(&zk_bins);
  924. tx.verify_sigs();
  925. //// Wallet
  926. // Secret vote info. Needs to be revealed at some point.
  927. // TODO: look into verifiable encryption for notes
  928. // TODO: look into timelock puzzle as a possibility
  929. let vote_note_3 = {
  930. assert_eq!(tx.func_calls.len(), 1);
  931. let func_call = &tx.func_calls[0];
  932. let call_data = func_call.call_data.as_any();
  933. assert_eq!((*call_data).type_id(), TypeId::of::<dao_contract::vote::validate::CallData>());
  934. let call_data = call_data.downcast_ref::<dao_contract::vote::validate::CallData>().unwrap();
  935. let header = &call_data.header;
  936. let note: dao_contract::vote::wallet::Note =
  937. header.enc_note.decrypt(&vote_keypair_3.secret).unwrap();
  938. note
  939. };
  940. debug!(target: "demo", "User 3 voted!");
  941. debug!(target: "demo", " vote_option: {}", vote_note_3.vote.vote_option);
  942. debug!(target: "demo", " value: {}", vote_note_3.vote_value);
  943. // Every votes produces a semi-homomorphic encryption of their vote.
  944. // Which is either yes or no
  945. // We copy the state tree for the governance token so coins can be used
  946. // to vote on other proposals at the same time.
  947. // With their vote, they produce a ZK proof + nullifier
  948. // The votes are unblinded by MPC to a selected party at the end of the
  949. // voting period.
  950. // (that's if we want votes to be hidden during voting)
  951. let mut yes_votes_value = 0;
  952. let mut yes_votes_blind = pallas::Scalar::from(0);
  953. let mut yes_votes_commit = pallas::Point::identity();
  954. let mut all_votes_value = 0;
  955. let mut all_votes_blind = pallas::Scalar::from(0);
  956. let mut all_votes_commit = pallas::Point::identity();
  957. // We were previously saving votes to a Vec<Update> for testing.
  958. // However since Update is now UpdateBase it gets moved into update.apply().
  959. // So we need to think of another way to run these tests.
  960. //assert!(updates.len() == 3);
  961. for (i, note /* update*/) in [vote_note_1, vote_note_2, vote_note_3]
  962. .iter() /*.zip(updates)*/
  963. .enumerate()
  964. {
  965. let vote_commit = pedersen_commitment_u64(note.vote_value, note.vote_value_blind);
  966. //assert!(update.value_commit == all_vote_value_commit);
  967. all_votes_commit += vote_commit;
  968. all_votes_blind += note.vote_value_blind;
  969. let yes_vote_commit = pedersen_commitment_u64(
  970. note.vote.vote_option as u64 * note.vote_value,
  971. note.vote.vote_option_blind,
  972. );
  973. //assert!(update.yes_vote_commit == yes_vote_commit);
  974. yes_votes_commit += yes_vote_commit;
  975. yes_votes_blind += note.vote.vote_option_blind;
  976. let vote_option = note.vote.vote_option;
  977. if vote_option {
  978. yes_votes_value += note.vote_value;
  979. }
  980. all_votes_value += note.vote_value;
  981. let vote_result: String = if vote_option { "yes".to_string() } else { "no".to_string() };
  982. debug!("Voter {} voted {}", i, vote_result);
  983. }
  984. debug!("Outcome = {} / {}", yes_votes_value, all_votes_value);
  985. assert!(all_votes_commit == pedersen_commitment_u64(all_votes_value, all_votes_blind));
  986. assert!(yes_votes_commit == pedersen_commitment_u64(yes_votes_value, yes_votes_blind));
  987. ///////////////////////////////////////////////////
  988. // Execute the vote
  989. ///////////////////////////////////////////////////
  990. //// Wallet
  991. // Used to export user_data from this coin so it can be accessed by DAO::exec()
  992. let user_data_blind = pallas::Base::random(&mut OsRng);
  993. let user_serial = pallas::Base::random(&mut OsRng);
  994. let user_coin_blind = pallas::Base::random(&mut OsRng);
  995. let dao_serial = pallas::Base::random(&mut OsRng);
  996. let dao_coin_blind = pallas::Base::random(&mut OsRng);
  997. let input_value = treasury_note.value;
  998. let input_value_blind = pallas::Scalar::random(&mut OsRng);
  999. let tx_signature_secret = SecretKey::random(&mut OsRng);
  1000. let exec_signature_secret = SecretKey::random(&mut OsRng);
  1001. let (treasury_leaf_position, treasury_merkle_path) = {
  1002. let state = states.lookup::<money_contract::State>(*money_contract::CONTRACT_ID).unwrap();
  1003. let tree = &state.tree;
  1004. let leaf_position = dao_recv_coin.leaf_position;
  1005. let root = tree.root(0).unwrap();
  1006. let merkle_path = tree.authentication_path(leaf_position, &root).unwrap();
  1007. (leaf_position, merkle_path)
  1008. };
  1009. let input = money_contract::transfer::wallet::BuilderInputInfo {
  1010. leaf_position: treasury_leaf_position,
  1011. merkle_path: treasury_merkle_path,
  1012. secret: dao_keypair.secret,
  1013. note: treasury_note,
  1014. user_data_blind,
  1015. value_blind: input_value_blind,
  1016. signature_secret: tx_signature_secret,
  1017. };
  1018. let builder = money_contract::transfer::wallet::Builder {
  1019. clear_inputs: vec![],
  1020. inputs: vec![input],
  1021. outputs: vec![
  1022. // Sending money
  1023. money_contract::transfer::wallet::BuilderOutputInfo {
  1024. value: 1000,
  1025. token_id: xdrk_token_id,
  1026. public: user_keypair.public,
  1027. serial: proposal.serial,
  1028. coin_blind: proposal.blind,
  1029. spend_hook: pallas::Base::from(0),
  1030. user_data: pallas::Base::from(0),
  1031. },
  1032. // Change back to DAO
  1033. money_contract::transfer::wallet::BuilderOutputInfo {
  1034. value: xdrk_supply - 1000,
  1035. token_id: xdrk_token_id,
  1036. public: dao_keypair.public,
  1037. serial: dao_serial,
  1038. coin_blind: dao_coin_blind,
  1039. spend_hook: *dao_contract::exec::FUNC_ID,
  1040. user_data: proposal_bulla,
  1041. },
  1042. ],
  1043. };
  1044. let transfer_func_call = builder.build(&zk_bins)?;
  1045. let builder = dao_contract::exec::wallet::Builder {
  1046. proposal,
  1047. dao: dao_params,
  1048. yes_votes_value,
  1049. all_votes_value,
  1050. yes_votes_blind,
  1051. all_votes_blind,
  1052. user_serial,
  1053. user_coin_blind,
  1054. dao_serial,
  1055. dao_coin_blind,
  1056. input_value,
  1057. input_value_blind,
  1058. hook_dao_exec: *dao_contract::exec::FUNC_ID,
  1059. signature_secret: exec_signature_secret,
  1060. };
  1061. let exec_func_call = builder.build(&zk_bins);
  1062. let func_calls = vec![transfer_func_call, exec_func_call];
  1063. let signatures = sign(&[tx_signature_secret, exec_signature_secret], &func_calls);
  1064. let tx = Transaction { func_calls, signatures };
  1065. {
  1066. // Now the spend_hook field specifies the function DAO::exec()
  1067. // so Money::transfer() must also be combined with DAO::exec()
  1068. assert_eq!(tx.func_calls.len(), 2);
  1069. let transfer_func_call = &tx.func_calls[0];
  1070. let transfer_call_data = transfer_func_call.call_data.as_any();
  1071. assert_eq!(
  1072. (*transfer_call_data).type_id(),
  1073. TypeId::of::<money_contract::transfer::validate::CallData>()
  1074. );
  1075. let transfer_call_data =
  1076. transfer_call_data.downcast_ref::<money_contract::transfer::validate::CallData>();
  1077. let transfer_call_data = transfer_call_data.unwrap();
  1078. // At least one input has this field value which means DAO::exec() is invoked.
  1079. assert_eq!(transfer_call_data.inputs.len(), 1);
  1080. let input = &transfer_call_data.inputs[0];
  1081. assert_eq!(input.revealed.spend_hook, *dao_contract::exec::FUNC_ID);
  1082. let user_data_enc = poseidon_hash::<2>([dao_bulla.0, user_data_blind]);
  1083. assert_eq!(input.revealed.user_data_enc, user_data_enc);
  1084. }
  1085. //// Validator
  1086. let mut updates = vec![];
  1087. // Validate all function calls in the tx
  1088. for (idx, func_call) in tx.func_calls.iter().enumerate() {
  1089. if func_call.func_id == *dao_contract::exec::FUNC_ID {
  1090. debug!("dao_contract::exec::state_transition()");
  1091. let update = dao_contract::exec::validate::state_transition(&states, idx, &tx)
  1092. .expect("dao_contract::exec::validate::state_transition() failed!");
  1093. updates.push(update);
  1094. } else if func_call.func_id == *money_contract::transfer::FUNC_ID {
  1095. debug!("money_contract::transfer::state_transition()");
  1096. let update = money_contract::transfer::validate::state_transition(&states, idx, &tx)
  1097. .expect("money_contract::transfer::validate::state_transition() failed!");
  1098. updates.push(update);
  1099. }
  1100. }
  1101. // Atomically apply all changes
  1102. for update in updates {
  1103. update.apply(&mut states);
  1104. }
  1105. // Other stuff
  1106. tx.zk_verify(&zk_bins);
  1107. tx.verify_sigs();
  1108. //// Wallet
  1109. Ok(())
  1110. }