schema.rs 48 KB

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