소스 검색

finish dao rewrite

x 2 년 전
부모
커밋
7e9bd2946e

+ 30 - 0
src/contract/dao/proof/dao-auth-money-transfer.zk

@@ -21,6 +21,17 @@ witness "DaoAuthMoneyTransfer" {
 	Base dao_public_x,
 	Base dao_public_y,
 	Base dao_bulla_blind,
+
+    # Dao input(s) user data blind
+    Base input_user_data_blind,
+
+	# Dao output coin attrs
+	Base dao_value,
+	Base dao_token,
+	Base dao_serial,
+
+    # Should be set to DAO_CONTRACT_ID
+    Base dao_contract_id,
 }
 
 circuit "DaoAuthMoneyTransfer" {
@@ -47,9 +58,28 @@ circuit "DaoAuthMoneyTransfer" {
 	constrain_instance(proposal_bulla);
 
     # Check inputs are spending from the correct DAO
+    input_user_data_enc = poseidon_hash(dao_bulla, input_user_data_blind);
+	constrain_instance(input_user_data_enc);
+
     # Change output should be sending back to the DAO
+	dao_change_coin = poseidon_hash(
+		dao_public_x,
+		dao_public_y,
+        # We don't need to check this value.
+        # money::transfer() checks that sum(input values) = sum(output values)
+        # which ensures it will be correct.
+		dao_value,
+        # Likewise the token_id must match the other output coins.
+		dao_token,
+		dao_serial,
+		dao_contract_id,
+		dao_bulla,
+	);
+	constrain_instance(dao_change_coin);
+	constrain_instance(dao_contract_id);
 
     # Reveal content commit. This should contain the set of coins.
     # We check these are set in the runtime.
+	constrain_instance(proposal_auth_calls_commit);
 }
 

+ 25 - 4
src/contract/dao/src/client/auth_xfer.rs

@@ -16,8 +16,11 @@
  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
  */
 
+use darkfi_money_contract::model::CoinAttributes;
 use darkfi_sdk::{
-    crypto::{pasta_prelude::*, pedersen_commitment_u64, SecretKey},
+    crypto::{
+        pasta_prelude::*, pedersen_commitment_u64, poseidon_hash, SecretKey, DAO_CONTRACT_ID,
+    },
     pasta::pallas,
 };
 
@@ -37,6 +40,8 @@ use crate::model::{
 pub struct DaoAuthMoneyTransferCall {
     pub proposal: DaoProposal,
     pub dao: Dao,
+    pub input_user_data_blind: pallas::Base,
+    pub dao_coin_attrs: CoinAttributes,
 }
 
 impl DaoAuthMoneyTransferCall {
@@ -46,7 +51,7 @@ impl DaoAuthMoneyTransferCall {
         auth_xfer_pk: &ProvingKey,
     ) -> Result<(DaoAuthMoneyTransferParams, Vec<Proof>)> {
         let mut proofs = vec![];
-        let params = DaoAuthMoneyTransferParams { proposal_bulla: self.proposal.to_bulla() };
+        let params = DaoAuthMoneyTransferParams {};
 
         let dao_proposer_limit = pallas::Base::from(self.dao.proposer_limit);
         let dao_quorum = pallas::Base::from(self.dao.quorum);
@@ -55,6 +60,9 @@ impl DaoAuthMoneyTransferCall {
 
         let (dao_pub_x, dao_pub_y) = self.dao.public_key.xy();
 
+        let input_user_data_enc =
+            poseidon_hash([self.dao.to_bulla().inner(), self.input_user_data_blind]);
+
         let prover_witnesses = vec![
             // proposal params
             Witness::Base(Value::known(self.proposal.auth_calls.commit())),
@@ -69,10 +77,23 @@ impl DaoAuthMoneyTransferCall {
             Witness::Base(Value::known(dao_pub_x)),
             Witness::Base(Value::known(dao_pub_y)),
             Witness::Base(Value::known(self.dao.bulla_blind)),
+            // Dao input user data blind
+            Witness::Base(Value::known(self.input_user_data_blind)),
+            // Dao output coin attrs
+            Witness::Base(Value::known(pallas::Base::from(self.dao_coin_attrs.value))),
+            Witness::Base(Value::known(self.dao_coin_attrs.token_id.inner())),
+            Witness::Base(Value::known(self.dao_coin_attrs.serial)),
+            // DAO_CONTRACT_ID
+            Witness::Base(Value::known(DAO_CONTRACT_ID.inner())),
         ];
 
-        let public_inputs = vec![params.proposal_bulla.inner()];
-        //export_witness_json("witness.json", &prover_witnesses, &public_inputs);
+        let public_inputs = vec![
+            self.proposal.to_bulla().inner(),
+            input_user_data_enc,
+            self.dao_coin_attrs.to_coin().inner(),
+            DAO_CONTRACT_ID.inner(),
+            self.proposal.auth_calls.commit(),
+        ];
 
         let circuit = ZkCircuit::new(prover_witnesses, auth_xfer_zkbin);
         let proof = Proof::create(auth_xfer_pk, &[circuit], &public_inputs, &mut OsRng)

+ 1 - 1
src/contract/dao/src/client/exec.rs

@@ -114,7 +114,7 @@ impl DaoExecCall {
         proofs.push(input_proof);
 
         let params = DaoExecParams {
-            proposal: proposal_bulla,
+            proposal_bulla,
             proposal_auth_calls: self.proposal.auth_calls,
             blind_total_vote: DaoBlindAggregateVote { yes_vote_commit, all_vote_commit },
         };

+ 25 - 6
src/contract/dao/src/entrypoint/auth_xfer.rs

@@ -21,7 +21,7 @@ use darkfi_money_contract::{
     MoneyFunction,
 };
 use darkfi_sdk::{
-    crypto::{contract_id::MONEY_CONTRACT_ID, pasta_prelude::*, ContractId, PublicKey},
+    crypto::{pasta_prelude::*, ContractId, PublicKey, DAO_CONTRACT_ID, MONEY_CONTRACT_ID},
     dark_tree::DarkLeaf,
     db::{db_del, db_get, db_lookup},
     error::{ContractError, ContractResult},
@@ -33,7 +33,7 @@ use darkfi_serial::{deserialize, serialize, Encodable, WriteExt};
 
 use crate::{
     error::DaoError,
-    model::{DaoAuthCall, DaoAuthMoneyTransferParams, DaoExecParams},
+    model::{DaoAuthCall, DaoAuthMoneyTransferParams, DaoExecParams, VecAuthCallCommit},
     DaoFunction, DAO_CONTRACT_DB_PROPOSAL_BULLAS, DAO_CONTRACT_ZKAS_DAO_AUTH_MONEY_TRANSFER_NS,
 };
 
@@ -43,15 +43,34 @@ pub(crate) fn dao_authxfer_get_metadata(
     call_idx: u32,
     calls: Vec<DarkLeaf<ContractCall>>,
 ) -> Result<Vec<u8>, ContractError> {
-    let self_ = &calls[call_idx as usize];
-    let params: DaoAuthMoneyTransferParams = deserialize(&self_.data.data[1..])?;
+    let sibling_idx = call_idx + 1;
+    let xfer_call = &calls[sibling_idx as usize].data;
+    let xfer_params: MoneyTransferParamsV1 = deserialize(&xfer_call.data[1..])?;
+
+    let parent_idx = calls[call_idx as usize].parent_index.unwrap();
+    let exec_callnode = &calls[parent_idx];
+    let exec_params: DaoExecParams = deserialize(&exec_callnode.data.data[1..])?;
+
+    assert!(xfer_params.inputs.len() > 0);
+    // This value should be the same for all inputs, as enforced in process_instruction() below.
+    let input_user_data_enc = xfer_params.inputs[0].user_data_enc;
+
+    assert!(xfer_params.outputs.len() > 0);
+    // Also check the coin in the change output
+    let last_coin = xfer_params.outputs.last().unwrap().coin;
 
     let mut zk_public_inputs: Vec<(String, Vec<pallas::Base>)> = vec![];
     let signature_pubkeys: Vec<PublicKey> = vec![];
 
     zk_public_inputs.push((
         DAO_CONTRACT_ZKAS_DAO_AUTH_MONEY_TRANSFER_NS.to_string(),
-        vec![params.proposal_bulla.inner()],
+        vec![
+            exec_params.proposal_bulla.inner(),
+            input_user_data_enc,
+            last_coin.inner(),
+            DAO_CONTRACT_ID.inner(),
+            exec_params.proposal_auth_calls.commit(),
+        ],
     ));
 
     let mut metadata = vec![];
@@ -155,7 +174,7 @@ pub(crate) fn dao_authxfer_process_instruction(
     // Also the public_key should match.
 
     // We do not need to check the amounts, since sum(input values) == sum(output values)
-    // otherwise the tx is invalid.
+    // otherwise the money::transfer() call is invalid.
 
     let mut update_data = vec![];
     update_data.write_u8(DaoFunction::AuthMoneyTransfer as u8)?;

+ 5 - 17
src/contract/dao/src/entrypoint/exec.rs

@@ -52,22 +52,10 @@ pub(crate) fn dao_exec_get_metadata(
     let yes_vote_coords = blind_vote.yes_vote_commit.to_affine().coordinates().unwrap();
     let all_vote_coords = blind_vote.all_vote_commit.to_affine().coordinates().unwrap();
 
-    /*
-    let mut input_valcoms = pallas::Point::identity();
-    for input in &money_xfer_params.inputs {
-        input_valcoms += input.value_commit;
-    }
-    let input_value_coords = input_valcoms.to_affine().coordinates().unwrap();
-
-    assert!(money_xfer_params.inputs.len() > 0);
-    // This value should be the same for all inputs, as enforced in process_instruction() below.
-    let input_user_data_enc = money_xfer_params.inputs[0].user_data_enc;
-    */
-
     zk_public_inputs.push((
         DAO_CONTRACT_ZKAS_DAO_EXEC_NS.to_string(),
         vec![
-            params.proposal.inner(),
+            params.proposal_bulla.inner(),
             params.proposal_auth_calls.commit(),
             *yes_vote_coords.x(),
             *yes_vote_coords.y(),
@@ -127,8 +115,8 @@ pub(crate) fn dao_exec_process_instruction(
 
     // Get the ProposalVote from DAO state
     let proposal_db = db_lookup(cid, DAO_CONTRACT_DB_PROPOSAL_BULLAS)?;
-    let Some(data) = db_get(proposal_db, &serialize(&params.proposal))? else {
-        msg!("[Dao::Exec] Error: Proposal {:?} not found", params.proposal);
+    let Some(data) = db_get(proposal_db, &serialize(&params.proposal_bulla))? else {
+        msg!("[Dao::Exec] Error: Proposal {:?} not found", params.proposal_bulla);
         return Err(DaoError::ProposalNonexistent.into())
     };
     let proposal: DaoProposalMetadata = deserialize(&data)?;
@@ -141,7 +129,7 @@ pub(crate) fn dao_exec_process_instruction(
     }
 
     // Create state update
-    let update = DaoExecUpdate { proposal: params.proposal };
+    let update = DaoExecUpdate { proposal_bulla: params.proposal_bulla };
     let mut update_data = vec![];
     update_data.write_u8(DaoFunction::Exec as u8)?;
     update.encode(&mut update_data)?;
@@ -152,7 +140,7 @@ pub(crate) fn dao_exec_process_instruction(
 pub(crate) fn dao_exec_process_update(cid: ContractId, update: DaoExecUpdate) -> ContractResult {
     // Remove proposal from db
     let proposal_vote_db = db_lookup(cid, DAO_CONTRACT_DB_PROPOSAL_BULLAS)?;
-    db_del(proposal_vote_db, &serialize(&update.proposal))?;
+    db_del(proposal_vote_db, &serialize(&update.proposal_bulla))?;
 
     Ok(())
 }

+ 3 - 6
src/contract/dao/src/model.rs

@@ -325,7 +325,7 @@ impl Default for DaoBlindAggregateVote {
 #[derive(Debug, Clone, SerialEncodable, SerialDecodable)]
 pub struct DaoExecParams {
     /// The proposal bulla
-    pub proposal: DaoProposalBulla,
+    pub proposal_bulla: DaoProposalBulla,
     pub proposal_auth_calls: Vec<DaoAuthCall>,
     /// Aggregated blinds for the vote commitments
     pub blind_total_vote: DaoBlindAggregateVote,
@@ -335,12 +335,9 @@ pub struct DaoExecParams {
 #[derive(Debug, Clone, SerialEncodable, SerialDecodable)]
 pub struct DaoExecUpdate {
     /// The proposal bulla
-    pub proposal: DaoProposalBulla,
+    pub proposal_bulla: DaoProposalBulla,
 }
 
 /// Parameters for `Dao::AuthMoneyTransfer`
 #[derive(Debug, Clone, SerialEncodable, SerialDecodable)]
-pub struct DaoAuthMoneyTransferParams {
-    /// The proposal bulla
-    pub proposal_bulla: DaoProposalBulla,
-}
+pub struct DaoAuthMoneyTransferParams {}

+ 1 - 1
src/contract/dao/tests/integration.rs

@@ -318,7 +318,7 @@ fn integration_test() -> Result<()> {
             &dao,
             &dao_mint_params.dao_bulla,
             &propose_info,
-            &proposal_coinattrs,
+            proposal_coinattrs,
             total_yes_vote_value,
             total_all_vote_value,
             total_yes_vote_blind,

+ 14 - 15
src/contract/test-harness/src/dao_exec.rs

@@ -53,7 +53,7 @@ impl TestHarness {
         dao: &Dao,
         dao_bulla: &DaoBulla,
         proposal: &DaoProposal,
-        proposal_coinattrs: &Vec<CoinAttributes>,
+        proposal_coinattrs: Vec<CoinAttributes>,
         yes_vote_value: u64,
         all_vote_value: u64,
         yes_vote_blind: pallas::Scalar,
@@ -108,25 +108,20 @@ impl TestHarness {
         }
 
         let mut outputs = vec![];
-        for coin in proposal_coinattrs {
-            assert_eq!(proposal_token_id, coin.token_id);
-            outputs.push(xfer::TransferCallOutput {
-                public_key: coin.public_key,
-                value: coin.value,
-                token_id: proposal_token_id,
-                serial: coin.serial,
-                spend_hook: coin.spend_hook,
-                user_data: coin.user_data,
-            });
+        for coin_attr in proposal_coinattrs {
+            assert_eq!(proposal_token_id, coin_attr.token_id);
+            outputs.push(coin_attr);
         }
-        outputs.push(xfer::TransferCallOutput {
+
+        let dao_coin_attrs = CoinAttributes {
             public_key: dao_wallet.keypair.public,
             value: change_value,
             token_id: proposal_token_id,
             serial: pallas::Base::random(&mut OsRng),
             spend_hook: DAO_CONTRACT_ID.inner(),
             user_data: dao_bulla.inner(),
-        });
+        };
+        outputs.push(dao_coin_attrs.clone());
 
         let xfer_builder = xfer::TransferCallBuilder {
             clear_inputs: vec![],
@@ -183,8 +178,12 @@ impl TestHarness {
         let exec_call = ContractCall { contract_id: *DAO_CONTRACT_ID, data };
 
         // Auth module
-        let auth_xfer_builder =
-            DaoAuthMoneyTransferCall { proposal: proposal.clone(), dao: dao.clone() };
+        let auth_xfer_builder = DaoAuthMoneyTransferCall {
+            proposal: proposal.clone(),
+            dao: dao.clone(),
+            input_user_data_blind,
+            dao_coin_attrs,
+        };
         let (auth_xfer_params, auth_xfer_proofs) =
             auth_xfer_builder.make(dao_auth_xfer_zkbin, dao_auth_xfer_pk)?;
         let mut data = vec![DaoFunction::AuthMoneyTransfer as u8];