schema.rs 45 KB

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