Просмотр исходного кода

wallet::money::transfer::Builder::build() creates an object of type MoneyTransferParams

x 3 лет назад
Родитель
Сommit
a6a76ffc4a

+ 1 - 1
example/dao2/contract/dao/src/lib.rs

@@ -50,7 +50,7 @@ define_contract!(
 
 
 fn init_contract(cid: ContractId, _ix: &[u8]) -> ContractResult {
 fn init_contract(cid: ContractId, _ix: &[u8]) -> ContractResult {
     let info_db = db_init(cid, "info")?;
     let info_db = db_init(cid, "info")?;
-    let roots_db = db_init(cid, "dao_roots")?;
+    let _ = db_init(cid, "dao_roots")?;
 
 
     let dao_tree = MerkleTree::new(100);
     let dao_tree = MerkleTree::new(100);
     let mut dao_tree_data = Vec::new();
     let mut dao_tree_data = Vec::new();

+ 88 - 9
example/dao2/contract/money/src/lib.rs

@@ -1,23 +1,81 @@
 use darkfi_sdk::{
 use darkfi_sdk::{
-    crypto::ContractId,
+    crypto::{ContractId, PublicKey},
     db::{db_init, db_lookup, db_set},
     db::{db_init, db_lookup, db_set},
     define_contract,
     define_contract,
+    msg,
     error::ContractResult,
     error::ContractResult,
     pasta::pallas,
     pasta::pallas,
+    tx::ContractCall,
     util::set_return_data,
     util::set_return_data,
 };
 };
-use darkfi_serial::{serialize, Encodable, SerialDecodable, SerialEncodable};
+use darkfi_serial::{serialize, Encodable, SerialDecodable, SerialEncodable, WriteExt, deserialize};
 
 
 #[repr(u8)]
 #[repr(u8)]
 pub enum MoneyFunction {
 pub enum MoneyFunction {
-    Foo = 0x00,
-    Mint = 0x01,
+    Transfer = 0x00,
+}
+
+impl From<u8> for MoneyFunction {
+    fn from(b: u8) -> Self {
+        match b {
+            0x00 => Self::Transfer,
+            _ => panic!("Invalid function ID: {:#04x?}", b),
+        }
+    }
 }
 }
 
 
 #[derive(SerialEncodable, SerialDecodable)]
 #[derive(SerialEncodable, SerialDecodable)]
-pub struct MoneyMintParams {
-    pub a: u32,
-    pub b: u32,
+pub struct MoneyTransferParams {
+    /// Clear inputs
+    pub clear_inputs: Vec<ClearInput>,
+    /// Anonymous inputs
+    pub inputs: Vec<Input>,
+    /// Anonymous outputs
+    pub outputs: Vec<Output>,
+}
+#[derive(SerialEncodable, SerialDecodable)]
+pub struct MoneyTransferUpdate {
+    // nullifiers
+    // coins
+}
+
+/// A transaction's clear input
+#[derive(SerialEncodable, SerialDecodable)]
+pub struct ClearInput {
+    /// Input's value (amount)
+    pub value: u64,
+    /// Input's token ID
+    pub token_id: pallas::Base,
+    /// Blinding factor for `value`
+    pub value_blind: pallas::Scalar,
+    /// Blinding factor for `token_id`
+    pub token_blind: pallas::Scalar,
+    /// Public key for the signature
+    pub signature_public: PublicKey,
+}
+
+/// A transaction's anonymous input
+#[derive(SerialEncodable, SerialDecodable)]
+pub struct Input {
+    // Public inputs for the zero-knowledge proof
+    pub value_commit: pallas::Point,
+    pub token_commit: pallas::Point,
+    pub nullifier: pallas::Base,
+    pub merkle_root: pallas::Base,
+    pub spend_hook: pallas::Base,
+    pub user_data_enc: pallas::Base,
+    pub signature_public: PublicKey,
+}
+
+/// A transaction's anonymous output
+#[derive(SerialEncodable, SerialDecodable)]
+pub struct Output {
+    // Public inputs for the zero-knowledge proof
+    pub value_commit: pallas::Point,
+    pub token_commit: pallas::Point,
+    pub coin: pallas::Base,
+    ///// The encrypted note
+    //pub enc_note: EncryptedNote2,
 }
 }
 
 
 define_contract!(
 define_contract!(
@@ -44,10 +102,31 @@ fn get_metadata(_cid: ContractId, ix: &[u8]) -> ContractResult {
     Ok(())
     Ok(())
 }
 }
 fn process_instruction(cid: ContractId, ix: &[u8]) -> ContractResult {
 fn process_instruction(cid: ContractId, ix: &[u8]) -> ContractResult {
+    let (call_idx, call): (u32, Vec<ContractCall>) = deserialize(ix)?;
+
+    assert!(call_idx < call.len() as u32);
+    let self_ = &call[call_idx as usize];
+
+    match MoneyFunction::from(self_.data[0]) {
+        MoneyFunction::Transfer => {
+            let update = MoneyTransferUpdate {};
+
+            let mut update_data = Vec::new();
+            update_data.write_u8(MoneyFunction::Transfer as u8)?;
+            update.encode(&mut update_data)?;
+            set_return_data(&update_data)?;
+            msg!("update is set!");
+        }
+    }
     Ok(())
     Ok(())
 }
 }
 fn process_update(cid: ContractId, update_data: &[u8]) -> ContractResult {
 fn process_update(cid: ContractId, update_data: &[u8]) -> ContractResult {
-    let db_handle = db_lookup(cid, "wagies")?;
-    db_set(db_handle, &serialize(&"jason_gulag".to_string()), &serialize(&110))?;
+    match MoneyFunction::from(update_data[0]) {
+        MoneyFunction::Transfer => {
+            let db_handle = db_lookup(cid, "wagies")?;
+            db_set(db_handle, &serialize(&"jason_gulag".to_string()), &serialize(&110))?;
+        }
+    }
+
     Ok(())
     Ok(())
 }
 }

+ 24 - 16
example/dao2/src/contract/money/transfer/wallet.rs

@@ -28,17 +28,16 @@ use darkfi::{
         types::{
         types::{
             DrkCoinBlind, DrkSerial, DrkSpendHook, DrkUserData, DrkUserDataBlind, DrkValueBlind,
             DrkCoinBlind, DrkSerial, DrkSpendHook, DrkUserData, DrkUserDataBlind, DrkValueBlind,
         },
         },
+        Proof
     },
     },
     Result,
     Result,
 };
 };
 
 
+use money_contract::{MoneyFunction, MoneyTransferParams, ClearInput, Input, Output};
+
 use crate::{
 use crate::{
-    contract::money::{
-        transfer::validate::{CallData, ClearInput, Input, Output},
-        CONTRACT_ID,
-    },
     note,
     note,
-    util::{FuncCall, ZkContractInfo, ZkContractTable},
+    util::{ZkContractInfo, ZkContractTable},
 };
 };
 
 
 #[derive(Clone, SerialEncodable, SerialDecodable)]
 #[derive(Clone, SerialEncodable, SerialDecodable)]
@@ -108,7 +107,7 @@ impl Builder {
         total
         total
     }
     }
 
 
-    pub fn build(self, zk_bins: &ZkContractTable) -> Result<FuncCall> {
+    pub fn build(self, zk_bins: &ZkContractTable) -> Result<(MoneyTransferParams, Vec<Proof>)> {
         assert!(self.clear_inputs.len() + self.inputs.len() > 0);
         assert!(self.clear_inputs.len() + self.inputs.len() > 0);
 
 
         let mut clear_inputs = vec![];
         let mut clear_inputs = vec![];
@@ -164,7 +163,15 @@ impl Builder {
             )?;
             )?;
             proofs.push(burn_proof);
             proofs.push(burn_proof);
 
 
-            let input = Input { revealed };
+            let input = Input {
+                value_commit: revealed.value_commit,
+                token_commit: revealed.token_commit,
+                nullifier: revealed.nullifier.inner(),
+                merkle_root: revealed.merkle_root.inner(),
+                spend_hook: revealed.spend_hook,
+                user_data_enc: revealed.user_data_enc,
+                signature_public: revealed.signature_public,
+            };
             inputs.push(input);
             inputs.push(input);
         }
         }
 
 
@@ -217,19 +224,20 @@ impl Builder {
                 token_blind,
                 token_blind,
             };
             };
 
 
-            let encrypted_note = note::encrypt(&note, &output.public)?;
+            //let encrypted_note = note::encrypt(&note, &output.public)?;
 
 
-            let output = Output { revealed, enc_note: encrypted_note };
+            let output = Output {
+                value_commit: revealed.value_commit,
+                token_commit: revealed.token_commit,
+                coin: revealed.coin.0,
+            };
             outputs.push(output);
             outputs.push(output);
         }
         }
 
 
-        let call_data = CallData { clear_inputs, inputs, outputs };
+        //let call_data = CallData { clear_inputs, inputs, outputs };
 
 
-        Ok(FuncCall {
-            contract_id: *CONTRACT_ID,
-            func_id: *super::FUNC_ID,
-            call_data: Box::new(call_data),
-            proofs,
-        })
+        Ok((MoneyTransferParams {
+            clear_inputs, inputs, outputs
+        }, proofs))
     }
     }
 }
 }

+ 60 - 56
example/dao2/src/main.rs

@@ -197,7 +197,6 @@ async fn main() -> BoxResult<()> {
     let zk_dao_mint_bin = ZkBinary::decode(zk_dao_mint_bincode)?;
     let zk_dao_mint_bin = ZkBinary::decode(zk_dao_mint_bincode)?;
     zk_bins.add_contract("dao-mint".to_string(), zk_dao_mint_bin, 13);
     zk_bins.add_contract("dao-mint".to_string(), zk_dao_mint_bin, 13);
 
 
-    /*
     debug!(target: "demo", "Loading money-transfer contracts");
     debug!(target: "demo", "Loading money-transfer contracts");
     {
     {
         let start = Instant::now();
         let start = Instant::now();
@@ -216,6 +215,7 @@ async fn main() -> BoxResult<()> {
         zk_bins.add_native("money-transfer-mint".to_string(), mint_pk, mint_vk);
         zk_bins.add_native("money-transfer-mint".to_string(), mint_pk, mint_vk);
         zk_bins.add_native("money-transfer-burn".to_string(), burn_pk, burn_vk);
         zk_bins.add_native("money-transfer-burn".to_string(), burn_pk, burn_vk);
     }
     }
+    /*
     debug!(target: "demo", "Loading dao-propose-main.zk");
     debug!(target: "demo", "Loading dao-propose-main.zk");
     let zk_dao_propose_main_bincode = include_bytes!("../proof/dao-propose-main.zk.bin");
     let zk_dao_propose_main_bincode = include_bytes!("../proof/dao-propose-main.zk.bin");
     let zk_dao_propose_main_bin = ZkBinary::decode(zk_dao_propose_main_bincode)?;
     let zk_dao_propose_main_bin = ZkBinary::decode(zk_dao_propose_main_bincode)?;
@@ -235,13 +235,13 @@ async fn main() -> BoxResult<()> {
     let zk_dao_exec_bincode = include_bytes!("../proof/dao-exec.zk.bin");
     let zk_dao_exec_bincode = include_bytes!("../proof/dao-exec.zk.bin");
     let zk_dao_exec_bin = ZkBinary::decode(zk_dao_exec_bincode)?;
     let zk_dao_exec_bin = ZkBinary::decode(zk_dao_exec_bincode)?;
     zk_bins.add_contract("dao-exec".to_string(), zk_dao_exec_bin, 13);
     zk_bins.add_contract("dao-exec".to_string(), zk_dao_exec_bin, 13);
+    */
 
 
     // State for money contracts
     // State for money contracts
     let cashier_signature_secret = SecretKey::random(&mut OsRng);
     let cashier_signature_secret = SecretKey::random(&mut OsRng);
     let cashier_signature_public = PublicKey::from_secret(cashier_signature_secret);
     let cashier_signature_public = PublicKey::from_secret(cashier_signature_secret);
     let faucet_signature_secret = SecretKey::random(&mut OsRng);
     let faucet_signature_secret = SecretKey::random(&mut OsRng);
     let faucet_signature_public = PublicKey::from_secret(faucet_signature_secret);
     let faucet_signature_public = PublicKey::from_secret(faucet_signature_secret);
-    */
 
 
     // We use this to receive coins
     // We use this to receive coins
     let mut cache = WalletCache::new();
     let mut cache = WalletCache::new();
@@ -372,60 +372,64 @@ async fn main() -> BoxResult<()> {
 
 
     debug!(target: "demo", "Create DAO bulla: {:?}", dao_bulla.0);
     debug!(target: "demo", "Create DAO bulla: {:?}", dao_bulla.0);
 
 
-    /////////////////////////////////////////////////
-    // Old stuff
-    /////////////////////////////////////////////////
-    /*
-    let wasm_bytes = std::fs::read("dao_contract.wasm")?;
-    let dao_contract_id = ContractId::from(pallas::Base::from(1));
-    let mut runtime = Runtime::new(&wasm_bytes, blockchain.clone(), dao_contract_id)?;
-
-    // Deploy function to initialize the smart contract state.
-    // Here we pass an empty payload, but it's possible to feed in arbitrary data.
-    runtime.deploy(&[])?;
-
-    // This is another call so we instantiate a new runtime.
-    let mut runtime = Runtime::new(&wasm_bytes, blockchain.clone(), dao_contract_id)?;
-
-    // =============================================
-    // Build some kind of payload to show an example
-    // =============================================
-    // Write the actual call data
-    let mut calldata = Vec::new();
-    // Selects which path executes in the contract.
-    calldata.write_u8(DaoFunction::Mint as u8)?;
-    let params = DaoMintParams { a: 777, b: 666 };
-    params.encode(&mut calldata)?;
-
-    let func_calls = vec![ContractCall {
-        contract_id: dao_contract_id,
-        calldata
-    }];
-
-    let mut payload = Vec::new();
-    //// Write the actual payload data
-    let call_index = 0;
-    payload.write_u32(call_index)?;
-    func_calls.encode(&mut payload)?;
-
-    // ============================================================
-    // Serialize the payload into the runtime format and execute it
-    // ============================================================
-    let update = runtime.exec(&payload)?;
-
-    // =====================================================
-    // If exec was successful, try to apply the state change
-    // =====================================================
-    runtime.apply(&update)?;
-
-    // =====================================================
-    // Verify ZK proofs and signatures
-    // =====================================================
-    let metadata = runtime.metadata(&payload)?;
-    let mut decoder = Cursor::new(&metadata);
-    let zk_public_values: Vec<(String, Vec<pallas::Base>)> = Decodable::decode(&mut decoder)?;
-    let signature_public_keys: Vec<pallas::Point> = Decodable::decode(decoder)?;
-    */
+    ///////////////////////////////////////////////////
+    //// Mint the initial supply of treasury token
+    //// and send it all to the DAO directly
+    ///////////////////////////////////////////////////
+    debug!(target: "demo", "Stage 2. Minting treasury token");
+
+    cache.track(dao_keypair.secret);
+
+    //// Wallet
+
+    // Address of deployed contract in our example is dao::exec::FUNC_ID
+    // This field is public, you can see it's being sent to a DAO
+    // but nothing else is visible.
+    //
+    // In the python code we wrote:
+    //
+    //   spend_hook = b"0xdao_ruleset"
+    //
+    let spend_hook = *dao::exec::FUNC_ID;
+    let tx = {
+        // The user_data can be a simple hash of the items passed into the ZK proof
+        // up to corresponding linked ZK proof to interpret however they need.
+        // In out case, it's the bulla for the DAO
+        let user_data = dao_bulla.0;
+
+        let builder = money::transfer::wallet::Builder {
+            clear_inputs: vec![money::transfer::wallet::BuilderClearInputInfo {
+                value: xdrk_supply,
+                token_id: xdrk_token_id,
+                signature_secret: cashier_signature_secret,
+            }],
+            inputs: vec![],
+            outputs: vec![money::transfer::wallet::BuilderOutputInfo {
+                value: xdrk_supply,
+                token_id: xdrk_token_id,
+                public: dao_keypair.public,
+                serial: pallas::Base::random(&mut OsRng),
+                coin_blind: pallas::Base::random(&mut OsRng),
+                spend_hook,
+                user_data,
+            }],
+        };
+        let (params, dao_mint_proofs) = builder.build(&zk_bins)?;
+    };
+
+
+    //let func_call = builder.build(&zk_bins)?;
+    //let func_calls = vec![func_call];
+
+    //let mut signatures = vec![];
+    //for func_call in &func_calls {
+    //    let sign = sign([cashier_signature_secret].to_vec(), func_call);
+    //    signatures.push(sign);
+    //}
+
+    //let tx = Transaction { func_calls, signatures };
+
+    ///////////////////////////////////////////////////
 
 
     show_dao_state(&blockchain, &dao_contract_id)?;
     show_dao_state(&blockchain, &dao_contract_id)?;
     show_money_state(&blockchain, &money_contract_id)?;
     show_money_state(&blockchain, &money_contract_id)?;