demo.rs 48 KB

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