schema.rs 45 KB

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