main.rs 45 KB

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