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