dao.rs 48 KB

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