Jelajahi Sumber

daod: change ContractId and FuncId to static pallas::Base

lunar-mining 3 tahun lalu
induk
melakukan
1643902e8b

+ 1 - 1
Cargo.lock

@@ -1160,9 +1160,9 @@ dependencies = [
  "halo2_gadgets",
  "halo2_proofs",
  "incrementalmerkletree",
+ "lazy_static",
  "log",
  "num_cpus",
- "once_cell",
  "pasta_curves",
  "rand",
  "serde_json",

+ 4 - 2
bin/daod/Cargo.toml

@@ -21,9 +21,7 @@ easy-parallel = "3.2.0"
 log = "0.4.17"
 num_cpus = "1.13.1"
 simplelog = "0.12.0"
-url = "2.2.2"
 thiserror = "1.0.32"
-once_cell = "1.13.1"
 
 # Crypto
 incrementalmerkletree = "0.3.0"
@@ -36,3 +34,7 @@ group = "0.12.0"
 
 # Encoding and parsing
 serde_json = "1.0.85"
+
+# Utilities
+lazy_static = "1.4.0"
+url = "2.2.2"

+ 7 - 4
bin/daod/src/dao_contract/exec/mod.rs

@@ -1,7 +1,10 @@
-use once_cell::sync::Lazy;
-use pasta_curves::pallas;
-
-pub static FUNC_ID: Lazy<pallas::Base> = Lazy::new(|| pallas::Base::from(110));
+use lazy_static::lazy_static;
+use pasta_curves::{group::ff::Field, pallas};
+use rand::rngs::OsRng;
 
 pub mod validate;
 pub mod wallet;
+
+lazy_static! {
+    pub static ref FUNC_ID: pallas::Base = pallas::Base::random(&mut OsRng);
+}

+ 5 - 5
bin/daod/src/dao_contract/exec/validate.rs

@@ -14,8 +14,8 @@ use std::any::{Any, TypeId};
 
 use crate::{
     dao_contract,
-    dao_contract::HashableBase,
-    demo::{CallDataBase, StateRegistry, Transaction, UpdateBase},
+    dao_contract::CONTRACT_ID,
+    demo::{CallDataBase, HashableBase, StateRegistry, Transaction, UpdateBase},
     money_contract,
 };
 
@@ -133,7 +133,7 @@ pub fn state_transition(
     }
 
     // 3. First item should be a Money::transfer() calldata
-    if parent_tx.func_calls[0].func_id != "Money::transfer()" {
+    if parent_tx.func_calls[0].func_id != *money_contract::transfer::FUNC_ID {
         return Err(Error::InvalidCallData)
     }
 
@@ -171,7 +171,7 @@ pub fn state_transition(
 
     // 3. get the ProposalVote from DAO::State
     let state = states
-        .lookup::<dao_contract::State>(&"DAO".to_string())
+        .lookup::<dao_contract::State>(*CONTRACT_ID)
         .expect("Return type is not of type State");
     let proposal_votes = state.proposal_votes.get(&HashableBase(call_data.proposal)).unwrap();
 
@@ -195,7 +195,7 @@ pub struct Update {
 impl UpdateBase for Update {
     fn apply(self: Box<Self>, states: &mut StateRegistry) {
         let state = states
-            .lookup_mut::<dao_contract::State>(&"DAO".to_string())
+            .lookup_mut::<dao_contract::State>(*CONTRACT_ID)
             .expect("Return type is not of type State");
         state.proposal_votes.remove(&HashableBase(self.proposal)).unwrap();
     }

+ 5 - 3
bin/daod/src/dao_contract/exec/wallet.rs

@@ -14,7 +14,9 @@ use darkfi::{
 };
 
 use crate::{
-    dao_contract::{exec::validate::CallData, mint::wallet::DaoParams, propose::wallet::Proposal},
+    dao_contract::{
+        exec::validate::CallData, mint::wallet::DaoParams, propose::wallet::Proposal, CONTRACT_ID,
+    },
     demo::{FuncCall, ZkContractInfo, ZkContractTable},
 };
 
@@ -186,8 +188,8 @@ impl Builder {
         };
 
         FuncCall {
-            contract_id: "DAO".to_string(),
-            func_id: "DAO::exec()".to_string(),
+            contract_id: *CONTRACT_ID,
+            func_id: *super::FUNC_ID,
             call_data: Box::new(call_data),
             proofs,
         }

+ 8 - 0
bin/daod/src/dao_contract/mint/mod.rs

@@ -1,3 +1,7 @@
+use lazy_static::lazy_static;
+use pasta_curves::{group::ff::Field, pallas};
+use rand::rngs::OsRng;
+
 pub mod validate;
 /// This is an anonymous contract function that mutates the internal DAO state.
 ///
@@ -34,3 +38,7 @@ pub mod validate;
 /// let tx = builder.build();
 /// ```
 pub mod wallet;
+
+lazy_static! {
+    pub static ref FUNC_ID: pallas::Base = pallas::Base::random(&mut OsRng);
+}

+ 2 - 2
bin/daod/src/dao_contract/mint/validate.rs

@@ -6,7 +6,7 @@ use darkfi::{
 };
 
 use crate::{
-    dao_contract::{DaoBulla, State},
+    dao_contract::{DaoBulla, State, CONTRACT_ID},
     demo::{CallDataBase, StateRegistry, Transaction, UpdateBase},
 };
 
@@ -35,7 +35,7 @@ pub struct Update {
 impl UpdateBase for Update {
     fn apply(self: Box<Self>, states: &mut StateRegistry) {
         // Lookup dao_contract state from registry
-        let state = states.lookup_mut::<State>(&"DAO".to_string()).unwrap();
+        let state = states.lookup_mut::<State>(*CONTRACT_ID).unwrap();
         // Add dao_bulla to state.dao_bullas
         state.add_dao_bulla(self.dao_bulla);
     }

+ 3 - 3
bin/daod/src/dao_contract/mint/wallet.rs

@@ -13,7 +13,7 @@ use pasta_curves::{arithmetic::CurveAffine, group::Curve, pallas};
 use rand::rngs::OsRng;
 
 use crate::{
-    dao_contract::mint::validate::CallData,
+    dao_contract::{mint::validate::CallData, CONTRACT_ID},
     demo::{FuncCall, ZkContractInfo, ZkContractTable},
 };
 
@@ -86,8 +86,8 @@ impl Builder {
 
         let call_data = CallData { dao_bulla };
         FuncCall {
-            contract_id: "DAO".to_string(),
-            func_id: "DAO::mint()".to_string(),
+            contract_id: *CONTRACT_ID,
+            func_id: *super::FUNC_ID,
             call_data: Box::new(call_data),
             proofs: vec![mint_proof],
         }

+ 9 - 1
bin/daod/src/dao_contract/mod.rs

@@ -1,3 +1,7 @@
+use lazy_static::lazy_static;
+use pasta_curves::{group::ff::Field, pallas};
+use rand::rngs::OsRng;
+
 // mint()
 pub mod mint;
 // propose()
@@ -9,4 +13,8 @@ pub mod exec;
 
 pub mod state;
 
-pub use state::{DaoBulla, HashableBase, State};
+pub use state::{DaoBulla, State};
+
+lazy_static! {
+    pub static ref CONTRACT_ID: pallas::Base = pallas::Base::random(&mut OsRng);
+}

+ 8 - 0
bin/daod/src/dao_contract/propose/mod.rs

@@ -1,2 +1,10 @@
+use lazy_static::lazy_static;
+use pasta_curves::{group::ff::Field, pallas};
+use rand::rngs::OsRng;
+
 pub mod validate;
 pub mod wallet;
+
+lazy_static! {
+    pub static ref FUNC_ID: pallas::Base = pallas::Base::random(&mut OsRng);
+}

+ 5 - 3
bin/daod/src/dao_contract/propose/validate.rs

@@ -12,8 +12,10 @@ use pasta_curves::{
 use std::any::{Any, TypeId};
 
 use crate::{
+    dao_contract,
     dao_contract::State as DaoState,
     demo::{CallDataBase, StateRegistry, Transaction, UpdateBase},
+    money_contract,
     money_contract::state::State as MoneyState,
     note::EncryptedNote2,
 };
@@ -137,13 +139,13 @@ pub fn state_transition(
 
     // Check the merkle roots for the input coins are valid
     for input in &call_data.inputs {
-        let money_state = states.lookup::<MoneyState>(&"Money".to_string()).unwrap();
+        let money_state = states.lookup::<MoneyState>(*money_contract::CONTRACT_ID).unwrap();
         if !money_state.is_valid_merkle(&input.merkle_root) {
             return Err(Error::InvalidInputMerkleRoot)
         }
     }
 
-    let state = states.lookup::<DaoState>(&"DAO".to_string()).unwrap();
+    let state = states.lookup::<DaoState>(*dao_contract::CONTRACT_ID).unwrap();
 
     // Is the DAO bulla generated in the ZK proof valid
     if !state.is_valid_dao_merkle(&call_data.header.dao_merkle_root) {
@@ -163,7 +165,7 @@ pub struct Update {
 
 impl UpdateBase for Update {
     fn apply(self: Box<Self>, states: &mut StateRegistry) {
-        let state = states.lookup_mut::<DaoState>(&"DAO".to_string()).unwrap();
+        let state = states.lookup_mut::<DaoState>(*dao_contract::CONTRACT_ID).unwrap();
         state.add_proposal_bulla(self.proposal_bulla);
     }
 }

+ 3 - 2
bin/daod/src/dao_contract/propose/wallet.rs

@@ -22,6 +22,7 @@ use crate::{
     dao_contract::{
         mint::wallet::DaoParams,
         propose::validate::{CallData, Header, Input},
+        CONTRACT_ID,
     },
     demo::{FuncCall, ZkContractInfo, ZkContractTable},
     money_contract, note,
@@ -258,8 +259,8 @@ impl Builder {
         let call_data = CallData { header, inputs };
 
         FuncCall {
-            contract_id: "DAO".to_string(),
-            func_id: "DAO::propose()".to_string(),
+            contract_id: *CONTRACT_ID,
+            func_id: *super::FUNC_ID,
             call_data: Box::new(call_data),
             proofs,
         }

+ 3 - 15
bin/daod/src/dao_contract/state.rs

@@ -1,10 +1,8 @@
 use incrementalmerkletree::{bridgetree::BridgeTree, Tree};
-use pasta_curves::{
-    group::{ff::PrimeField, Group},
-    pallas,
-};
-use std::{any::Any, collections::HashMap, hash::Hasher};
+use pasta_curves::{group::Group, pallas};
+use std::{any::Any, collections::HashMap};
 
+use crate::demo::HashableBase;
 use darkfi::{
     crypto::{constants::MERKLE_DEPTH, merkle_node::MerkleNode, nullifier::Nullifier},
     util::serial::{SerialDecodable, SerialEncodable},
@@ -15,16 +13,6 @@ pub struct DaoBulla(pub pallas::Base);
 
 type MerkleTree = BridgeTree<MerkleNode, MERKLE_DEPTH>;
 
-#[derive(Eq, PartialEq)]
-pub struct HashableBase(pub pallas::Base);
-
-impl std::hash::Hash for HashableBase {
-    fn hash<H: Hasher>(&self, state: &mut H) {
-        let bytes = self.0.to_repr();
-        bytes.hash(state);
-    }
-}
-
 pub struct ProposalVotes {
     // TODO: might be more logical to have 'yes_vote_commits' and 'no_vote_commits'
     /// Weighted vote commits

+ 8 - 0
bin/daod/src/dao_contract/vote/mod.rs

@@ -1,2 +1,10 @@
+use lazy_static::lazy_static;
+use pasta_curves::{group::ff::Field, pallas};
+use rand::rngs::OsRng;
+
 pub mod validate;
 pub mod wallet;
+
+lazy_static! {
+    pub static ref FUNC_ID: pallas::Base = pallas::Base::random(&mut OsRng);
+}

+ 5 - 3
bin/daod/src/dao_contract/vote/validate.rs

@@ -14,8 +14,10 @@ use pasta_curves::{
 use std::any::{Any, TypeId};
 
 use crate::{
+    dao_contract,
     dao_contract::State as DaoState,
     demo::{CallDataBase, StateRegistry, Transaction, UpdateBase},
+    money_contract,
     money_contract::state::State as MoneyState,
     note::EncryptedNote2,
 };
@@ -146,7 +148,7 @@ pub fn state_transition(
     // This will be inside wasm so unwrap is fine.
     let call_data = call_data.unwrap();
 
-    let dao_state = states.lookup::<DaoState>(&"DAO".to_string()).unwrap();
+    let dao_state = states.lookup::<DaoState>(*dao_contract::CONTRACT_ID).unwrap();
 
     // Check proposal_bulla exists
     let votes_info = dao_state.lookup_proposal_votes(call_data.header.proposal_bulla);
@@ -159,7 +161,7 @@ pub fn state_transition(
     let mut vote_nulls = Vec::new();
     let mut total_value_commit = pallas::Point::identity();
     for input in &call_data.inputs {
-        let money_state = states.lookup::<MoneyState>(&"Money".to_string()).unwrap();
+        let money_state = states.lookup::<MoneyState>(*money_contract::CONTRACT_ID).unwrap();
         if !money_state.is_valid_merkle(&input.merkle_root) {
             return Err(Error::InvalidInputMerkleRoot)
         }
@@ -195,7 +197,7 @@ pub struct Update {
 
 impl UpdateBase for Update {
     fn apply(mut self: Box<Self>, states: &mut StateRegistry) {
-        let state = states.lookup_mut::<DaoState>(&"DAO".to_string()).unwrap();
+        let state = states.lookup_mut::<DaoState>(*dao_contract::CONTRACT_ID).unwrap();
         let votes_info = state.lookup_proposal_votes_mut(self.proposal_bulla).unwrap();
         votes_info.vote_commits += self.vote_commit;
         votes_info.value_commits += self.value_commit;

+ 3 - 2
bin/daod/src/dao_contract/vote/wallet.rs

@@ -23,6 +23,7 @@ use crate::{
         mint::wallet::DaoParams,
         propose::wallet::Proposal,
         vote::validate::{CallData, Header, Input},
+        CONTRACT_ID,
     },
     demo::{FuncCall, ZkContractInfo, ZkContractTable},
     money_contract, note,
@@ -288,8 +289,8 @@ impl Builder {
         let call_data = CallData { header, inputs };
 
         FuncCall {
-            contract_id: "DAO".to_string(),
-            func_id: "DAO::vote()".to_string(),
+            contract_id: *CONTRACT_ID,
+            func_id: *super::FUNC_ID,
             call_data: Box::new(call_data),
             proofs,
         }

+ 48 - 34
bin/daod/src/demo.rs

@@ -2,13 +2,17 @@ use incrementalmerkletree::Tree;
 use log::debug;
 use pasta_curves::{
     arithmetic::CurveAffine,
-    group::{ff::Field, Curve, Group},
+    group::{
+        ff::{Field, PrimeField},
+        Curve, Group,
+    },
     pallas,
 };
 use rand::rngs::OsRng;
 use std::{
     any::{Any, TypeId},
     collections::HashMap,
+    hash::Hasher,
     time::Instant,
 };
 
@@ -42,6 +46,16 @@ use crate::{dao_contract, example_contract, money_contract};
 
 type Result<T> = std::result::Result<T, Box<dyn std::error::Error>>;
 
+#[derive(Eq, PartialEq)]
+pub struct HashableBase(pub pallas::Base);
+
+impl std::hash::Hash for HashableBase {
+    fn hash<H: Hasher>(&self, state: &mut H) {
+        let bytes = self.0.to_repr();
+        bytes.hash(state);
+    }
+}
+
 pub struct ZkBinaryContractInfo {
     pub k_param: u32,
     pub bincode: ZkBinary,
@@ -163,9 +177,8 @@ fn sign(signature_secrets: Vec<SecretKey>, func_calls: &Vec<FuncCall>) -> Vec<Si
     signatures
 }
 
-// These would normally be a hash or sth
-type ContractId = String;
-type FuncId = String;
+type ContractId = pallas::Base;
+type FuncId = pallas::Base;
 
 pub struct FuncCall {
     pub contract_id: ContractId,
@@ -205,7 +218,7 @@ pub trait CallDataBase {
 type GenericContractState = Box<dyn Any>;
 
 pub struct StateRegistry {
-    pub states: HashMap<ContractId, GenericContractState>,
+    pub states: HashMap<HashableBase, GenericContractState>,
 }
 
 impl StateRegistry {
@@ -215,15 +228,15 @@ impl StateRegistry {
 
     fn register(&mut self, contract_id: ContractId, state: GenericContractState) {
         debug!(target: "StateRegistry::register()", "contract_id: {:?}", contract_id);
-        self.states.insert(contract_id, state);
+        self.states.insert(HashableBase(contract_id), state);
     }
 
-    pub fn lookup_mut<'a, S: 'static>(&'a mut self, contract_id: &ContractId) -> Option<&'a mut S> {
-        self.states.get_mut(contract_id).and_then(|state| state.downcast_mut())
+    pub fn lookup_mut<'a, S: 'static>(&'a mut self, contract_id: ContractId) -> Option<&'a mut S> {
+        self.states.get_mut(&HashableBase(contract_id)).and_then(|state| state.downcast_mut())
     }
 
-    pub fn lookup<'a, S: 'static>(&'a self, contract_id: &ContractId) -> Option<&'a S> {
-        self.states.get(contract_id).and_then(|state| state.downcast_ref())
+    pub fn lookup<'a, S: 'static>(&'a self, contract_id: ContractId) -> Option<&'a S> {
+        self.states.get(&HashableBase(contract_id)).and_then(|state| state.downcast_ref())
     }
 }
 
@@ -247,7 +260,7 @@ pub async fn example() -> Result<()> {
     zk_bins.add_contract("example-foo".to_string(), zk_example_foo_bin, 13);
 
     let example_state = example_contract::state::State::new();
-    states.register("Example".to_string(), example_state);
+    states.register(*example_contract::CONTRACT_ID, example_state);
 
     //// Wallet
 
@@ -266,7 +279,7 @@ pub async fn example() -> Result<()> {
     let mut updates = vec![];
     // Validate all function calls in the tx
     for (idx, func_call) in tx.func_calls.iter().enumerate() {
-        if func_call.func_id == "Example::foo()" {
+        if func_call.func_id == *example_contract::foo::FUNC_ID {
             debug!("example_contract::foo::state_transition()");
 
             let update = example_contract::foo::validate::state_transition(&states, idx, &tx)
@@ -363,12 +376,12 @@ pub async fn demo() -> Result<()> {
 
     let money_state =
         money_contract::state::State::new(cashier_signature_public, faucet_signature_public);
-    states.register("Money".to_string(), money_state);
+    states.register(*money_contract::CONTRACT_ID, money_state);
 
     /////////////////////////////////////////////////////
 
     let dao_state = dao_contract::State::new();
-    states.register("DAO".to_string(), dao_state);
+    states.register(*dao_contract::CONTRACT_ID, dao_state);
 
     /////////////////////////////////////////////////////
     ////// Create the DAO bulla
@@ -405,7 +418,7 @@ pub async fn demo() -> Result<()> {
     for (idx, func_call) in tx.func_calls.iter().enumerate() {
         // So then the verifier will lookup the corresponding state_transition and apply
         // functions based off the func_id
-        if func_call.func_id == "DAO::mint()" {
+        if func_call.func_id == *dao_contract::mint::FUNC_ID {
             debug!("dao_contract::mint::state_transition()");
 
             let update = dao_contract::mint::validate::state_transition(&states, idx, &tx)
@@ -430,7 +443,7 @@ pub async fn demo() -> Result<()> {
     // We need to witness() the value in our local merkle tree
     // Must be called as soon as this DAO bulla is added to the state
     let dao_leaf_position = {
-        let state = states.lookup_mut::<dao_contract::State>(&"DAO".to_string()).unwrap();
+        let state = states.lookup_mut::<dao_contract::State>(*dao_contract::CONTRACT_ID).unwrap();
         state.dao_tree.witness().unwrap()
     };
 
@@ -451,7 +464,7 @@ pub async fn demo() -> Result<()> {
     ///////////////////////////////////////////////////
     debug!(target: "demo", "Stage 2. Minting treasury token");
 
-    let state = states.lookup_mut::<money_contract::State>(&"Money".to_string()).unwrap();
+    let state = states.lookup_mut::<money_contract::State>(*money_contract::CONTRACT_ID).unwrap();
     state.wallet_cache.track(dao_keypair.secret);
 
     //// Wallet
@@ -501,7 +514,7 @@ pub async fn demo() -> Result<()> {
     for (idx, func_call) in tx.func_calls.iter().enumerate() {
         // So then the verifier will lookup the corresponding state_transition and apply
         // functions based off the func_id
-        if func_call.func_id == "Money::transfer()" {
+        if func_call.func_id == *money_contract::transfer::FUNC_ID {
             debug!("money_contract::transfer::state_transition()");
 
             let update = money_contract::transfer::validate::state_transition(&states, idx, &tx)
@@ -521,7 +534,7 @@ pub async fn demo() -> Result<()> {
     //// Wallet
     // DAO reads the money received from the encrypted note
 
-    let state = states.lookup_mut::<money_contract::State>(&"Money".to_string()).unwrap();
+    let state = states.lookup_mut::<money_contract::State>(*money_contract::CONTRACT_ID).unwrap();
     let mut recv_coins = state.wallet_cache.get_received(&dao_keypair.secret);
     assert_eq!(recv_coins.len(), 1);
     let dao_recv_coin = recv_coins.pop().unwrap();
@@ -562,7 +575,7 @@ pub async fn demo() -> Result<()> {
     // Hodler 3: the tiebreaker
     let gov_keypair_3 = Keypair::random(&mut OsRng);
 
-    let state = states.lookup_mut::<money_contract::State>(&"Money".to_string()).unwrap();
+    let state = states.lookup_mut::<money_contract::State>(*money_contract::CONTRACT_ID).unwrap();
     state.wallet_cache.track(gov_keypair_1.secret);
     state.wallet_cache.track(gov_keypair_2.secret);
     state.wallet_cache.track(gov_keypair_3.secret);
@@ -628,7 +641,7 @@ pub async fn demo() -> Result<()> {
     for (idx, func_call) in tx.func_calls.iter().enumerate() {
         // So then the verifier will lookup the corresponding state_transition and apply
         // functions based off the func_id
-        if func_call.func_id == "Money::transfer()" {
+        if func_call.func_id == *money_contract::transfer::FUNC_ID {
             debug!("money_contract::transfer::state_transition()");
 
             let update = money_contract::transfer::validate::state_transition(&states, idx, &tx)
@@ -651,7 +664,8 @@ pub async fn demo() -> Result<()> {
     // Check that each person received one coin
     for (i, key) in gov_keypairs.iter().enumerate() {
         let gov_recv_coin = {
-            let state = states.lookup_mut::<money_contract::State>(&"Money".to_string()).unwrap();
+            let state =
+                states.lookup_mut::<money_contract::State>(*money_contract::CONTRACT_ID).unwrap();
             let mut recv_coins = state.wallet_cache.get_received(&key.secret);
             assert_eq!(recv_coins.len(), 1);
             let recv_coin = recv_coins.pop().unwrap();
@@ -709,7 +723,7 @@ pub async fn demo() -> Result<()> {
     let user_keypair = Keypair::random(&mut OsRng);
 
     let (money_leaf_position, money_merkle_path) = {
-        let state = states.lookup::<money_contract::State>(&"Money".to_string()).unwrap();
+        let state = states.lookup::<money_contract::State>(*money_contract::CONTRACT_ID).unwrap();
         let tree = &state.tree;
         let leaf_position = gov_recv[0].leaf_position.clone();
         let root = tree.root(0).unwrap();
@@ -729,7 +743,7 @@ pub async fn demo() -> Result<()> {
     };
 
     let (dao_merkle_path, dao_merkle_root) = {
-        let state = states.lookup::<dao_contract::State>(&"DAO".to_string()).unwrap();
+        let state = states.lookup::<dao_contract::State>(*dao_contract::CONTRACT_ID).unwrap();
         let tree = &state.dao_tree;
         let root = tree.root(0).unwrap();
         let merkle_path = tree.authentication_path(dao_leaf_position, &root).unwrap();
@@ -773,7 +787,7 @@ pub async fn demo() -> Result<()> {
     let mut updates = vec![];
     // Validate all function calls in the tx
     for (idx, func_call) in tx.func_calls.iter().enumerate() {
-        if func_call.func_id == "DAO::propose()" {
+        if func_call.func_id == *dao_contract::propose::FUNC_ID {
             debug!(target: "demo", "dao_contract::propose::state_transition()");
 
             let update = dao_contract::propose::validate::state_transition(&states, idx, &tx)
@@ -849,7 +863,7 @@ pub async fn demo() -> Result<()> {
     // User 1: YES
 
     let (money_leaf_position, money_merkle_path) = {
-        let state = states.lookup::<money_contract::State>(&"Money".to_string()).unwrap();
+        let state = states.lookup::<money_contract::State>(*money_contract::CONTRACT_ID).unwrap();
         let tree = &state.tree;
         let leaf_position = gov_recv[0].leaf_position.clone();
         let root = tree.root(0).unwrap();
@@ -895,7 +909,7 @@ pub async fn demo() -> Result<()> {
     let mut updates = vec![];
     // Validate all function calls in the tx
     for (idx, func_call) in tx.func_calls.iter().enumerate() {
-        if func_call.func_id == "DAO::vote()" {
+        if func_call.func_id == *dao_contract::vote::FUNC_ID {
             debug!(target: "demo", "dao_contract::vote::state_transition()");
 
             let update = dao_contract::vote::validate::state_transition(&states, idx, &tx)
@@ -936,7 +950,7 @@ pub async fn demo() -> Result<()> {
     // User 2: NO
 
     let (money_leaf_position, money_merkle_path) = {
-        let state = states.lookup::<money_contract::State>(&"Money".to_string()).unwrap();
+        let state = states.lookup::<money_contract::State>(*money_contract::CONTRACT_ID).unwrap();
         let tree = &state.tree;
         let leaf_position = gov_recv[1].leaf_position.clone();
         let root = tree.root(0).unwrap();
@@ -982,7 +996,7 @@ pub async fn demo() -> Result<()> {
     let mut updates = vec![];
     // Validate all function calls in the tx
     for (idx, func_call) in tx.func_calls.iter().enumerate() {
-        if func_call.func_id == "DAO::vote()" {
+        if func_call.func_id == *dao_contract::vote::FUNC_ID {
             debug!(target: "demo", "dao_contract::vote::state_transition()");
 
             let update = dao_contract::vote::validate::state_transition(&states, idx, &tx)
@@ -1023,7 +1037,7 @@ pub async fn demo() -> Result<()> {
     // User 3: YES
 
     let (money_leaf_position, money_merkle_path) = {
-        let state = states.lookup::<money_contract::State>(&"Money".to_string()).unwrap();
+        let state = states.lookup::<money_contract::State>(*money_contract::CONTRACT_ID).unwrap();
         let tree = &state.tree;
         let leaf_position = gov_recv[2].leaf_position.clone();
         let root = tree.root(0).unwrap();
@@ -1069,7 +1083,7 @@ pub async fn demo() -> Result<()> {
     let mut updates = vec![];
     // Validate all function calls in the tx
     for (idx, func_call) in tx.func_calls.iter().enumerate() {
-        if func_call.func_id == "DAO::vote()" {
+        if func_call.func_id == *dao_contract::vote::FUNC_ID {
             debug!(target: "demo", "dao_contract::vote::state_transition()");
 
             let update = dao_contract::vote::validate::state_transition(&states, idx, &tx)
@@ -1185,7 +1199,7 @@ pub async fn demo() -> Result<()> {
     let exec_signature_secret = SecretKey::random(&mut OsRng);
 
     let (treasury_leaf_position, treasury_merkle_path) = {
-        let state = states.lookup::<money_contract::State>(&"Money".to_string()).unwrap();
+        let state = states.lookup::<money_contract::State>(*money_contract::CONTRACT_ID).unwrap();
         let tree = &state.tree;
         let leaf_position = dao_recv_coin.leaf_position.clone();
         let root = tree.root(0).unwrap();
@@ -1282,13 +1296,13 @@ pub async fn demo() -> Result<()> {
     let mut updates = vec![];
     // Validate all function calls in the tx
     for (idx, func_call) in tx.func_calls.iter().enumerate() {
-        if func_call.func_id == "DAO::exec()" {
+        if func_call.func_id == *dao_contract::exec::FUNC_ID {
             debug!("dao_contract::exec::state_transition()");
 
             let update = dao_contract::exec::validate::state_transition(&states, idx, &tx)
                 .expect("dao_contract::exec::validate::state_transition() failed!");
             updates.push(update);
-        } else if func_call.func_id == "Money::transfer()" {
+        } else if func_call.func_id == *money_contract::transfer::FUNC_ID {
             debug!("money_contract::transfer::state_transition()");
 
             let update = money_contract::transfer::validate::state_transition(&states, idx, &tx)

+ 8 - 0
bin/daod/src/example_contract/foo/mod.rs

@@ -1,2 +1,10 @@
+use lazy_static::lazy_static;
+use pasta_curves::{group::ff::Field, pallas};
+use rand::rngs::OsRng;
+
 pub mod validate;
 pub mod wallet;
+
+lazy_static! {
+    pub static ref FUNC_ID: pallas::Base = pallas::Base::random(&mut OsRng);
+}

+ 3 - 3
bin/daod/src/example_contract/foo/validate.rs

@@ -10,7 +10,7 @@ use std::any::{Any, TypeId};
 
 use crate::{
     demo::{CallDataBase, StateRegistry, Transaction, UpdateBase},
-    example_contract::state::State,
+    example_contract::{state::State, CONTRACT_ID},
 };
 
 type Result<T> = std::result::Result<T, Error>;
@@ -71,7 +71,7 @@ pub fn state_transition(
     // This will be inside wasm so unwrap is fine.
     let call_data = call_data.unwrap();
 
-    let example_state = states.lookup::<State>(&"Example".to_string()).unwrap();
+    let example_state = states.lookup::<State>(*CONTRACT_ID).unwrap();
 
     if example_state.public_exists(&call_data.public_value) {
         return Err(Error::ValueExists)
@@ -87,7 +87,7 @@ pub struct Update {
 
 impl UpdateBase for Update {
     fn apply(self: Box<Self>, states: &mut StateRegistry) {
-        let example_state = states.lookup_mut::<State>(&"Example".to_string()).unwrap();
+        let example_state = states.lookup_mut::<State>(*CONTRACT_ID).unwrap();
         example_state.add_public_value(self.public_value);
     }
 }

+ 3 - 3
bin/daod/src/example_contract/foo/wallet.rs

@@ -14,7 +14,7 @@ use darkfi::{
 
 use crate::{
     demo::{FuncCall, ZkContractInfo, ZkContractTable},
-    example_contract::foo::validate::CallData,
+    example_contract::{foo::validate::CallData, CONTRACT_ID},
 };
 
 pub struct Foo {
@@ -65,8 +65,8 @@ impl Builder {
         let call_data = CallData { public_value: c, signature_public };
 
         FuncCall {
-            contract_id: "Example".to_string(),
-            func_id: "Example::foo()".to_string(),
+            contract_id: *CONTRACT_ID,
+            func_id: *super::FUNC_ID,
             call_data: Box::new(call_data),
             proofs,
         }

+ 9 - 0
bin/daod/src/example_contract/mod.rs

@@ -1,3 +1,12 @@
+use lazy_static::lazy_static;
+use pasta_curves::{group::ff::Field, pallas};
+use rand::rngs::OsRng;
+
 // foo()
 pub mod foo;
+
 pub mod state;
+
+lazy_static! {
+    pub static ref CONTRACT_ID: pallas::Base = pallas::Base::random(&mut OsRng);
+}

+ 10 - 1
bin/daod/src/money_contract/mod.rs

@@ -1,4 +1,13 @@
-pub mod state;
+use lazy_static::lazy_static;
+use pasta_curves::{group::ff::Field, pallas};
+use rand::rngs::OsRng;
+
+// transfer()
 pub mod transfer;
 
+pub mod state;
 pub use state::State;
+
+lazy_static! {
+    pub static ref CONTRACT_ID: pallas::Base = pallas::Base::random(&mut OsRng);
+}

+ 8 - 0
bin/daod/src/money_contract/transfer/mod.rs

@@ -1,3 +1,11 @@
+use lazy_static::lazy_static;
+use pasta_curves::{group::ff::Field, pallas};
+use rand::rngs::OsRng;
+
 pub mod validate;
 pub mod wallet;
 pub use wallet::{Builder, BuilderClearInputInfo, BuilderInputInfo, BuilderOutputInfo, Note};
+
+lazy_static! {
+    pub static ref FUNC_ID: pallas::Base = pallas::Base::random(&mut OsRng);
+}

+ 5 - 5
bin/daod/src/money_contract/transfer/validate.rs

@@ -20,8 +20,9 @@ use darkfi::{
 };
 
 use crate::{
+    dao_contract,
     demo::{CallDataBase, StateRegistry, Transaction, UpdateBase},
-    money_contract::state::State,
+    money_contract::{state::State, CONTRACT_ID},
     note::EncryptedNote2,
 };
 
@@ -41,7 +42,7 @@ pub struct Update {
 
 impl UpdateBase for Update {
     fn apply(mut self: Box<Self>, states: &mut StateRegistry) {
-        let state = states.lookup_mut::<State>(&"Money".to_string()).unwrap();
+        let state = states.lookup_mut::<State>(*CONTRACT_ID).unwrap();
 
         // Extend our list of nullifiers with the ones from the update
         state.nullifiers.append(&mut self.nullifiers);
@@ -77,8 +78,7 @@ pub fn state_transition(
     // This will be inside wasm so unwrap is fine.
     let call_data = call_data.unwrap();
 
-    let state =
-        states.lookup::<State>(&"Money".to_string()).expect("Return type is not of type State");
+    let state = states.lookup::<State>(*CONTRACT_ID).expect("Return type is not of type State");
 
     // Code goes here
     for (i, input) in call_data.clear_inputs.iter().enumerate() {
@@ -121,7 +121,7 @@ pub fn state_transition(
                 // TODO: we need to change these to pallas::Base
                 // temporary workaround for now
                 // if func_call.func_id == spend_hook ...
-                if func_call.func_id == "DAO::exec()" {
+                if func_call.func_id == *dao_contract::exec::FUNC_ID {
                     is_found = true;
                     break
                 }

+ 6 - 3
bin/daod/src/money_contract/transfer/wallet.rs

@@ -18,7 +18,10 @@ use darkfi::{
 
 use crate::{
     demo::{FuncCall, ZkContractInfo, ZkContractTable},
-    money_contract::transfer::validate::{CallData, ClearInput, Input, Output},
+    money_contract::{
+        transfer::validate::{CallData, ClearInput, Input, Output},
+        CONTRACT_ID,
+    },
     note,
 };
 
@@ -207,8 +210,8 @@ impl Builder {
         let call_data = CallData { clear_inputs, inputs, outputs };
 
         Ok(FuncCall {
-            contract_id: "Money".to_string(),
-            func_id: "Money::transfer()".to_string(),
+            contract_id: *CONTRACT_ID,
+            func_id: *super::FUNC_ID,
             call_data: Box::new(call_data),
             proofs,
         })