Sfoglia il codice sorgente

migrate builder over

x 3 anni fa
parent
commit
0dfe9243eb

+ 1 - 1
src/contract/dao/Cargo.toml

@@ -25,7 +25,7 @@ rand = { version = "0.8.5", optional = true }
 [dev-dependencies]
 async-std = {version = "1.12.0", features = ["attributes"]}
 darkfi = {path = "../../../", features = ["tx", "blockchain"]}
-darkfi-money-contract = { path = "../money", features = ["client"] }
+darkfi-money-contract = { path = "../money", features = ["client", "no-entrypoint"] }
 simplelog = "0.12.0"
 sled = "0.34.7"
 sqlx = {version = "0.6.2", features = ["runtime-async-std-native-tls", "sqlite"]}

+ 0 - 0
src/contract/dao/src/client.rs → src/contract/dao/src/dao_client.rs


+ 6 - 2
src/contract/dao/src/lib.rs

@@ -27,8 +27,12 @@ pub mod state;
 pub mod note;
 
 #[cfg(feature = "client")]
-/// Transaction building API for clients interacting with this contract
-pub mod client;
+/// Transaction building API for clients interacting with DAO contract
+pub mod dao_client;
+
+#[cfg(feature = "client")]
+/// Transaction building API for clients interacting with money contract
+pub mod money_client;
 
 // These are the zkas circuit namespaces
 pub const DAO_CONTRACT_ZKAS_DAO_MINT_NS: &str = "DaoMint";

+ 272 - 0
src/contract/dao/src/money_client.rs

@@ -0,0 +1,272 @@
+/* This file is part of DarkFi (https://dark.fi)
+ *
+ * Copyright (C) 2020-2022 Dyne.org foundation
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ */
+
+use chacha20poly1305::{AeadInPlace, ChaCha20Poly1305, KeyInit};
+use darkfi::{
+    consensus::leadcoin::LeadCoin,
+    zk::{
+        proof::{Proof, ProvingKey},
+        vm::ZkCircuit,
+        vm_stack::Witness,
+    },
+    zkas::ZkBinary,
+    ClientFailed, Error, Result,
+};
+use darkfi_sdk::{
+    crypto::{
+        constants::MERKLE_DEPTH,
+        diffie_hellman::{kdf_sapling, sapling_ka_agree},
+        pedersen::{pedersen_commitment_base, pedersen_commitment_u64, ValueBlind, ValueCommit},
+        poseidon_hash, Keypair, MerkleNode, Nullifier, PublicKey, SecretKey, TokenId,
+    },
+    incrementalmerkletree,
+    incrementalmerkletree::{bridgetree::BridgeTree, Hashable, Tree},
+    pasta::{
+        arithmetic::CurveAffine,
+        group::{
+            ff::{Field, PrimeField},
+            Curve,
+        },
+        pallas,
+    },
+};
+use darkfi_serial::{serialize, Decodable, Encodable, SerialDecodable, SerialEncodable};
+use halo2_proofs::circuit::Value;
+use log::{debug, error, info};
+use rand::rngs::OsRng;
+
+use darkfi_money_contract::{
+    client::{create_transfer_burn_proof, create_transfer_mint_proof, Note},
+    state::{ClearInput, Input, MoneyTransferParams, Output},
+};
+
+/*
+use darkfi::{
+    crypto::{
+        burn_proof::create_burn_proof,
+        mint_proof::create_mint_proof,
+        types::{
+            DrkCoinBlind, DrkSerial, DrkSpendHook, DrkUserData, DrkUserDataBlind, DrkValueBlind,
+        },
+    },
+    Result,
+};
+
+use crate::{
+    contract::money::{
+        transfer::validate::{CallData, ClearInput, Input, Output},
+        CONTRACT_ID,
+    },
+    note,
+    util::{FuncCall, ZkContractInfo, ZkContractTable},
+};
+*/
+
+/*
+#[derive(Clone, SerialEncodable, SerialDecodable)]
+pub struct Note {
+    pub serial: DrkSerial,
+    pub value: u64,
+    pub token_id: TokenId,
+    pub spend_hook: DrkSpendHook,
+    pub user_data: DrkUserData,
+    pub coin_blind: DrkCoinBlind,
+    pub value_blind: DrkValueBlind,
+    pub token_blind: DrkValueBlind,
+}
+*/
+
+pub struct Builder {
+    pub clear_inputs: Vec<BuilderClearInputInfo>,
+    pub inputs: Vec<BuilderInputInfo>,
+    pub outputs: Vec<BuilderOutputInfo>,
+}
+
+pub struct BuilderClearInputInfo {
+    pub value: u64,
+    pub token_id: TokenId,
+    pub signature_secret: SecretKey,
+}
+
+pub struct BuilderInputInfo {
+    pub leaf_position: incrementalmerkletree::Position,
+    pub merkle_path: Vec<MerkleNode>,
+    pub secret: SecretKey,
+    pub note: Note,
+    pub user_data_blind: pallas::Base,
+    pub value_blind: ValueBlind,
+    pub signature_secret: SecretKey,
+}
+
+pub struct BuilderOutputInfo {
+    pub value: u64,
+    pub token_id: TokenId,
+    pub public: PublicKey,
+    pub serial: pallas::Base,
+    pub coin_blind: pallas::Base,
+    pub spend_hook: pallas::Base,
+    pub user_data: pallas::Base,
+}
+
+impl Builder {
+    fn compute_remainder_blind(
+        clear_inputs: &[ClearInput],
+        input_blinds: &[ValueBlind],
+        output_blinds: &[ValueBlind],
+    ) -> ValueBlind {
+        let mut total = ValueBlind::zero();
+
+        for input in clear_inputs {
+            total += input.value_blind;
+        }
+
+        for input_blind in input_blinds {
+            total += input_blind;
+        }
+
+        for output_blind in output_blinds {
+            total -= output_blind;
+        }
+
+        total
+    }
+
+    pub fn build(
+        self,
+        mint_zkbin: &ZkBinary,
+        mint_pk: &ProvingKey,
+        burn_zkbin: &ZkBinary,
+        burn_pk: &ProvingKey,
+    ) -> Result<(MoneyTransferParams, Vec<Proof>)> {
+        assert!(self.clear_inputs.len() + self.inputs.len() > 0);
+
+        let mut clear_inputs = vec![];
+        let token_blind = ValueBlind::random(&mut OsRng);
+        for input in &self.clear_inputs {
+            let signature_public = PublicKey::from_secret(input.signature_secret);
+            let value_blind = ValueBlind::random(&mut OsRng);
+
+            let clear_input = ClearInput {
+                value: input.value,
+                token_id: input.token_id,
+                value_blind,
+                token_blind,
+                signature_public,
+            };
+            clear_inputs.push(clear_input);
+        }
+
+        let mut proofs = vec![];
+        let mut inputs = vec![];
+        let mut input_blinds = vec![];
+
+        for input in self.inputs {
+            let value_blind = input.value_blind;
+            input_blinds.push(value_blind);
+
+            // Note from the previous output
+            let note = input.note.clone();
+
+            let (proof, revealed) = create_transfer_burn_proof(
+                burn_zkbin,
+                burn_pk,
+                note.value,
+                note.token_id,
+                value_blind,
+                token_blind,
+                note.serial,
+                note.spend_hook,
+                note.user_data,
+                input.user_data_blind,
+                note.coin_blind,
+                input.secret,
+                input.leaf_position,
+                input.merkle_path.clone(),
+                input.signature_secret,
+            )?;
+
+            proofs.push(proof);
+
+            let input = Input {
+                value_commit: revealed.value_commit,
+                token_commit: revealed.token_commit,
+                nullifier: revealed.nullifier,
+                merkle_root: revealed.merkle_root,
+                spend_hook: revealed.spend_hook,
+                user_data_enc: revealed.user_data_enc,
+                signature_public: revealed.signature_public,
+            };
+            inputs.push(input);
+        }
+
+        let mut outputs = vec![];
+        let mut output_blinds = vec![];
+        // This value_blind calc assumes there will always be at least a single output
+        assert!(!self.outputs.is_empty());
+
+        for (i, output) in self.outputs.iter().enumerate() {
+            let value_blind = if i == self.outputs.len() - 1 {
+                Self::compute_remainder_blind(&clear_inputs, &input_blinds, &output_blinds)
+            } else {
+                ValueBlind::random(&mut OsRng)
+            };
+            output_blinds.push(value_blind);
+
+            let serial = output.serial;
+            let coin_blind = output.coin_blind;
+
+            let (proof, revealed) = create_transfer_mint_proof(
+                mint_zkbin,
+                mint_pk,
+                output.value,
+                output.token_id,
+                value_blind,
+                token_blind,
+                serial,
+                output.spend_hook,
+                output.user_data,
+                coin_blind,
+                output.public,
+            )?;
+
+            proofs.push(proof);
+
+            let note = Note {
+                serial,
+                value: output.value,
+                token_id: output.token_id,
+                spend_hook: output.spend_hook,
+                user_data: output.user_data,
+                coin_blind,
+                value_blind,
+                token_blind,
+                memo: Vec::new(),
+            };
+
+            //let encrypted_note = note.encrypt(&output.public)?;
+            /*
+            let encrypted_note = note::encrypt(&note, &output.public)?;
+
+            let output = Output { revealed, enc_note: encrypted_note };
+            outputs.push(output);
+            */
+        }
+
+        Ok((MoneyTransferParams { clear_inputs, inputs, outputs }, proofs))
+    }
+}

+ 8 - 4
src/contract/dao/tests/integration.rs

@@ -28,7 +28,7 @@ use log::{debug, info};
 use rand::rngs::OsRng;
 
 use darkfi_dao_contract::{
-    client::{build_dao_mint_tx, MerkleTree},
+    dao_client::{build_dao_mint_tx, MerkleTree},
     DaoFunction,
 };
 
@@ -60,11 +60,11 @@ async fn integration_test() -> Result<()> {
     let mut th = DaoTestHarness::new().await?;
 
     // Money parameters
-    //let xdrk_supply = 1_000_000;
-    //let xrdk_token_id = TokenId::from(pallas::Base::random(&mut OsRng));
+    let xdrk_supply = 1_000_000;
+    let xrdk_token_id = TokenId::from(pallas::Base::random(&mut OsRng));
 
     // Governance token parameters
-    //let gdrk_supply = 1_000_000;
+    let gdrk_supply = 1_000_000;
     let gdrk_token_id = TokenId::from(pallas::Base::random(&mut OsRng));
 
     // DAO parameters
@@ -131,7 +131,11 @@ async fn integration_test() -> Result<()> {
     // =======================================================
     debug!(target: "demo", "Stage 2. Minting treasury token");
 
+    // We use this to receive coins
+    //let mut cache = WalletCache::new();
+
     let mut th = MoneyTestHarness::new().await?;
+    //let (params, proofs) = builder.build(&zk_bins)?;
 
     Ok(())
 }

+ 25 - 6
src/contract/money/src/client.rs

@@ -47,12 +47,15 @@ use darkfi_sdk::{
     incrementalmerkletree::{bridgetree::BridgeTree, Hashable, Tree},
     pasta::{
         arithmetic::CurveAffine,
-        group::{ff::PrimeField, Curve},
+        group::{
+            ff::{Field, PrimeField},
+            Curve,
+        },
         pallas,
     },
 };
 use darkfi_serial::{serialize, Decodable, Encodable, SerialDecodable, SerialEncodable};
-use halo2_proofs::{arithmetic::Field, circuit::Value};
+use halo2_proofs::circuit::Value;
 use log::{debug, error, info};
 use rand::rngs::OsRng;
 
@@ -143,6 +146,11 @@ pub struct Note {
     pub value: u64,
     /// Token ID of the coin
     pub token_id: TokenId,
+    /// Spend hook used for protocol owned liquidity.
+    /// Specifies which contract owns this coin.
+    pub spend_hook: pallas::Base,
+    /// User data used by protocol when spend hook is enabled.
+    pub user_data: pallas::Base,
     /// Blinding factor for the coin bulla
     pub coin_blind: pallas::Base,
     /// Blinding factor for the value pedersen commitment
@@ -207,6 +215,9 @@ impl EncryptedNote {
     }
 }
 
+// TODO: we can put all these in an internal module like:
+// money_transfer::builder::ClearInputInfo
+
 struct TransactionBuilderClearInputInfo {
     pub value: u64,
     pub token_id: TokenId,
@@ -226,7 +237,7 @@ struct TransactionBuilderOutputInfo {
     pub public_key: PublicKey,
 }
 
-struct TransferBurnRevealed {
+pub struct TransferBurnRevealed {
     pub value_commit: ValueCommit,
     pub token_commit: ValueCommit,
     pub nullifier: Nullifier,
@@ -321,7 +332,7 @@ impl TransferBurnRevealed {
     }
 }
 
-struct TransferMintRevealed {
+pub struct TransferMintRevealed {
     pub coin: Coin,
     pub value_commit: ValueCommit,
     pub token_commit: ValueCommit,
@@ -376,7 +387,7 @@ impl TransferMintRevealed {
 }
 
 #[allow(clippy::too_many_arguments)]
-fn create_transfer_mint_proof(
+pub fn create_transfer_mint_proof(
     zkbin: &ZkBinary,
     pk: &ProvingKey,
     value: u64,
@@ -424,7 +435,7 @@ fn create_transfer_mint_proof(
 }
 
 #[allow(clippy::too_many_arguments)]
-fn create_transfer_burn_proof(
+pub fn create_transfer_burn_proof(
     zkbin: &ZkBinary,
     pk: &ProvingKey,
     value: u64,
@@ -799,6 +810,8 @@ pub fn build_half_swap_tx(
         serial,
         value: output.value,
         token_id: output.token_id,
+        spend_hook: pallas::Base::zero(),
+        user_data: pallas::Base::zero(),
         coin_blind,
         value_blind: value_recv_blind,
         token_blind: token_recv_blind,
@@ -1025,6 +1038,8 @@ pub fn build_transfer_tx(
             serial,
             value: output.value,
             token_id: output.token_id,
+            spend_hook: pallas::Base::zero(),
+            user_data: pallas::Base::zero(),
             coin_blind,
             value_blind,
             token_blind,
@@ -1236,6 +1251,8 @@ pub fn build_unstake_tx(
             serial,
             value: coin.value,
             token_id: token_id_recv,
+            spend_hook: pallas::Base::zero(),
+            user_data: pallas::Base::zero(),
             coin_blind,
             value_blind,
             token_blind: token_recv_blind,
@@ -1290,6 +1307,8 @@ mod tests {
             serial: pallas::Base::random(&mut OsRng),
             value: 100,
             token_id: TokenId::from(pallas::Base::random(&mut OsRng)),
+            spend_hook: pallas::Base::zero(),
+            user_data: pallas::Base::zero(),
             coin_blind: pallas::Base::random(&mut OsRng),
             value_blind: pallas::Scalar::random(&mut OsRng),
             token_blind: pallas::Scalar::random(&mut OsRng),