|
@@ -26,12 +26,13 @@ use darkfi_dao_contract::{
|
|
|
client as dao_client,
|
|
client as dao_client,
|
|
|
client::{DaoInfo, DaoProposalInfo, DaoVoteCall, DaoVoteInput},
|
|
client::{DaoInfo, DaoProposalInfo, DaoVoteCall, DaoVoteInput},
|
|
|
model::DaoBlindAggregateVote,
|
|
model::DaoBlindAggregateVote,
|
|
|
- money_client, DaoFunction, DAO_CONTRACT_ZKAS_DAO_EXEC_NS, DAO_CONTRACT_ZKAS_DAO_MINT_NS,
|
|
|
|
|
|
|
+ DaoFunction, DAO_CONTRACT_ZKAS_DAO_EXEC_NS, DAO_CONTRACT_ZKAS_DAO_MINT_NS,
|
|
|
DAO_CONTRACT_ZKAS_DAO_PROPOSE_BURN_NS, DAO_CONTRACT_ZKAS_DAO_PROPOSE_MAIN_NS,
|
|
DAO_CONTRACT_ZKAS_DAO_PROPOSE_BURN_NS, DAO_CONTRACT_ZKAS_DAO_PROPOSE_MAIN_NS,
|
|
|
DAO_CONTRACT_ZKAS_DAO_VOTE_BURN_NS, DAO_CONTRACT_ZKAS_DAO_VOTE_MAIN_NS,
|
|
DAO_CONTRACT_ZKAS_DAO_VOTE_BURN_NS, DAO_CONTRACT_ZKAS_DAO_VOTE_MAIN_NS,
|
|
|
};
|
|
};
|
|
|
use darkfi_money_contract::{
|
|
use darkfi_money_contract::{
|
|
|
- client::OwnCoin, MoneyFunction, MONEY_CONTRACT_ZKAS_BURN_NS_V1, MONEY_CONTRACT_ZKAS_MINT_NS_V1,
|
|
|
|
|
|
|
+ client::{transfer_v1::TransferCallBuilder, OwnCoin},
|
|
|
|
|
+ MoneyFunction, MONEY_CONTRACT_ZKAS_BURN_NS_V1, MONEY_CONTRACT_ZKAS_MINT_NS_V1,
|
|
|
};
|
|
};
|
|
|
use darkfi_sdk::{
|
|
use darkfi_sdk::{
|
|
|
crypto::{
|
|
crypto::{
|
|
@@ -395,77 +396,17 @@ impl Drk {
|
|
|
return Err(anyhow!("Not enough balance in DAO treasury to execute proposal"))
|
|
return Err(anyhow!("Not enough balance in DAO treasury to execute proposal"))
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- // Used to export user_data from this coin so it can be accessed by DAO::exec()
|
|
|
|
|
- let user_data_blind = pallas::Base::random(&mut OsRng);
|
|
|
|
|
|
|
+ // FIXME: This assumes we aren't sending to a protocol.
|
|
|
|
|
+ let rcpt_spend_hook = pallas::Base::ZERO;
|
|
|
|
|
+ let rcpt_user_data = pallas::Base::ZERO;
|
|
|
|
|
+ let rcpt_user_data_blind = pallas::Base::random(&mut OsRng);
|
|
|
|
|
|
|
|
- let user_serial = pallas::Base::random(&mut OsRng);
|
|
|
|
|
- let dao_serial = pallas::Base::random(&mut OsRng);
|
|
|
|
|
-
|
|
|
|
|
- // TODO: FIXME: Clean this up and create an API
|
|
|
|
|
- let exec_signature_secret = SecretKey::random(&mut OsRng);
|
|
|
|
|
- let mut xfer_signature_secrets = vec![];
|
|
|
|
|
- let mut xfer_inputs = vec![];
|
|
|
|
|
-
|
|
|
|
|
- let mut input_coins = vec![];
|
|
|
|
|
- let mut input_amount = 0;
|
|
|
|
|
- for coin in coins {
|
|
|
|
|
- input_amount += coin.note.value;
|
|
|
|
|
- input_coins.push(coin);
|
|
|
|
|
- if input_amount >= proposal.amount {
|
|
|
|
|
- break
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ let change_spend_hook = DAO_CONTRACT_ID.inner();
|
|
|
|
|
+ let change_user_data = dao_bulla.inner();
|
|
|
|
|
+ let change_user_data_blind = pallas::Base::random(&mut OsRng);
|
|
|
|
|
|
|
|
let money_merkle_tree = self.get_money_tree().await?;
|
|
let money_merkle_tree = self.get_money_tree().await?;
|
|
|
|
|
|
|
|
- let mut input_value_blind = pallas::Scalar::from(0);
|
|
|
|
|
- for coin in &input_coins {
|
|
|
|
|
- let value_blind = pallas::Scalar::random(&mut OsRng);
|
|
|
|
|
- let sig_secret = SecretKey::random(&mut OsRng);
|
|
|
|
|
- xfer_signature_secrets.push(sig_secret);
|
|
|
|
|
-
|
|
|
|
|
- xfer_inputs.push(money_client::TransferInput {
|
|
|
|
|
- leaf_position: coin.leaf_position,
|
|
|
|
|
- merkle_path: money_merkle_tree.witness(coin.leaf_position, 0).unwrap(),
|
|
|
|
|
- secret: dao.secret_key,
|
|
|
|
|
- note: coin.note.clone(),
|
|
|
|
|
- user_data_blind,
|
|
|
|
|
- value_blind,
|
|
|
|
|
- signature_secret: sig_secret,
|
|
|
|
|
- });
|
|
|
|
|
-
|
|
|
|
|
- input_value_blind += value_blind;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- let input_sum = input_coins.iter().map(|x| x.note.value).sum::<u64>();
|
|
|
|
|
-
|
|
|
|
|
- let xfer_outputs = vec![
|
|
|
|
|
- // Proposal send
|
|
|
|
|
- money_client::TransferOutput {
|
|
|
|
|
- value: proposal.amount,
|
|
|
|
|
- token_id: proposal.token_id,
|
|
|
|
|
- public: proposal.recipient,
|
|
|
|
|
- serial: user_serial,
|
|
|
|
|
- spend_hook: pallas::Base::zero(),
|
|
|
|
|
- user_data: pallas::Base::zero(),
|
|
|
|
|
- },
|
|
|
|
|
- // Change
|
|
|
|
|
- money_client::TransferOutput {
|
|
|
|
|
- value: input_sum - proposal.amount,
|
|
|
|
|
- token_id: proposal.token_id,
|
|
|
|
|
- public: PublicKey::from_secret(dao.secret_key),
|
|
|
|
|
- serial: dao_serial,
|
|
|
|
|
- spend_hook: DAO_CONTRACT_ID.inner(),
|
|
|
|
|
- user_data: dao_bulla.inner(),
|
|
|
|
|
- },
|
|
|
|
|
- ];
|
|
|
|
|
-
|
|
|
|
|
- let xfer_call = money_client::TransferCall {
|
|
|
|
|
- clear_inputs: vec![],
|
|
|
|
|
- inputs: xfer_inputs,
|
|
|
|
|
- outputs: xfer_outputs,
|
|
|
|
|
- };
|
|
|
|
|
-
|
|
|
|
|
let zkas_bins = self.lookup_zkas(&MONEY_CONTRACT_ID).await?;
|
|
let zkas_bins = self.lookup_zkas(&MONEY_CONTRACT_ID).await?;
|
|
|
let Some(mint_zkbin) = zkas_bins.iter().find(|x| x.0 == MONEY_CONTRACT_ZKAS_MINT_NS_V1)
|
|
let Some(mint_zkbin) = zkas_bins.iter().find(|x| x.0 == MONEY_CONTRACT_ZKAS_MINT_NS_V1)
|
|
|
else {
|
|
else {
|
|
@@ -485,11 +426,30 @@ impl Drk {
|
|
|
eprintln!("Creating Money Burn circuit proving key");
|
|
eprintln!("Creating Money Burn circuit proving key");
|
|
|
let burn_pk = ProvingKey::build(k, &burn_circuit);
|
|
let burn_pk = ProvingKey::build(k, &burn_circuit);
|
|
|
|
|
|
|
|
- let (xfer_params, xfer_proofs) =
|
|
|
|
|
- xfer_call.make(&mint_zkbin, &mint_pk, &burn_zkbin, &burn_pk)?;
|
|
|
|
|
|
|
+ let xfer_builder = TransferCallBuilder {
|
|
|
|
|
+ keypair: dao.keypair(),
|
|
|
|
|
+ recipient: proposal.recipient,
|
|
|
|
|
+ value: proposal.amount,
|
|
|
|
|
+ token_id: proposal.token_id,
|
|
|
|
|
+ rcpt_spend_hook,
|
|
|
|
|
+ rcpt_user_data,
|
|
|
|
|
+ rcpt_user_data_blind,
|
|
|
|
|
+ change_spend_hook,
|
|
|
|
|
+ change_user_data,
|
|
|
|
|
+ change_user_data_blind,
|
|
|
|
|
+ coins,
|
|
|
|
|
+ tree: money_merkle_tree,
|
|
|
|
|
+ mint_zkbin: mint_zkbin.clone(),
|
|
|
|
|
+ mint_pk: mint_pk.clone(),
|
|
|
|
|
+ burn_zkbin: burn_zkbin.clone(),
|
|
|
|
|
+ burn_pk: burn_pk.clone(),
|
|
|
|
|
+ clear_input: false,
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
|
|
+ let xfer_debris = xfer_builder.build()?;
|
|
|
|
|
|
|
|
let mut data = vec![MoneyFunction::TransferV1 as u8];
|
|
let mut data = vec![MoneyFunction::TransferV1 as u8];
|
|
|
- xfer_params.encode(&mut data)?;
|
|
|
|
|
|
|
+ xfer_debris.params.encode(&mut data)?;
|
|
|
let xfer_call = ContractCall { contract_id: *MONEY_CONTRACT_ID, data };
|
|
let xfer_call = ContractCall { contract_id: *MONEY_CONTRACT_ID, data };
|
|
|
|
|
|
|
|
let zkas_bins = self.lookup_zkas(&DAO_CONTRACT_ID).await?;
|
|
let zkas_bins = self.lookup_zkas(&DAO_CONTRACT_ID).await?;
|
|
@@ -546,6 +506,22 @@ impl Drk {
|
|
|
bulla_blind: dao.bulla_blind,
|
|
bulla_blind: dao.bulla_blind,
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
|
|
+ // We need to extract stuff from the inputs and outputs that we'll also
|
|
|
|
|
+ // use in the DAO::Exec call. This DAO API needs to be better.
|
|
|
|
|
+ let mut input_value = 0;
|
|
|
|
|
+ let mut input_value_blind = pallas::Scalar::ZERO;
|
|
|
|
|
+ for (input, blind) in xfer_debris.spent_coins.iter().zip(xfer_debris.input_value_blinds) {
|
|
|
|
|
+ input_value += input.note.value;
|
|
|
|
|
+ input_value_blind += blind;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // First output is change, second output is recipient.
|
|
|
|
|
+ let dao_serial = xfer_debris.minted_coins[0].note.serial;
|
|
|
|
|
+ let user_serial = xfer_debris.minted_coins[1].note.serial;
|
|
|
|
|
+
|
|
|
|
|
+ // TODO: FIXME: This is not checked anywhere!
|
|
|
|
|
+ let exec_signature_secret = SecretKey::random(&mut OsRng);
|
|
|
|
|
+
|
|
|
let dao_exec_call = dao_client::DaoExecCall {
|
|
let dao_exec_call = dao_client::DaoExecCall {
|
|
|
proposal: prop_t,
|
|
proposal: prop_t,
|
|
|
dao: dao_t,
|
|
dao: dao_t,
|
|
@@ -555,8 +531,8 @@ impl Drk {
|
|
|
all_vote_blind: total_all_vote_blind,
|
|
all_vote_blind: total_all_vote_blind,
|
|
|
user_serial,
|
|
user_serial,
|
|
|
dao_serial,
|
|
dao_serial,
|
|
|
- input_value: input_sum, // <-- FIXME
|
|
|
|
|
- input_value_blind, // <-- FIXME
|
|
|
|
|
|
|
+ input_value,
|
|
|
|
|
+ input_value_blind,
|
|
|
hook_dao_exec: DAO_CONTRACT_ID.inner(),
|
|
hook_dao_exec: DAO_CONTRACT_ID.inner(),
|
|
|
signature_secret: exec_signature_secret,
|
|
signature_secret: exec_signature_secret,
|
|
|
};
|
|
};
|
|
@@ -569,11 +545,11 @@ impl Drk {
|
|
|
|
|
|
|
|
let mut tx = Transaction {
|
|
let mut tx = Transaction {
|
|
|
calls: vec![xfer_call, exec_call],
|
|
calls: vec![xfer_call, exec_call],
|
|
|
- proofs: vec![xfer_proofs, exec_proofs],
|
|
|
|
|
|
|
+ proofs: vec![xfer_debris.proofs, exec_proofs],
|
|
|
signatures: vec![],
|
|
signatures: vec![],
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
- let xfer_sigs = tx.create_sigs(&mut OsRng, &xfer_signature_secrets)?;
|
|
|
|
|
|
|
+ let xfer_sigs = tx.create_sigs(&mut OsRng, &xfer_debris.signature_secrets)?;
|
|
|
let exec_sigs = tx.create_sigs(&mut OsRng, &[exec_signature_secret])?;
|
|
let exec_sigs = tx.create_sigs(&mut OsRng, &[exec_signature_secret])?;
|
|
|
tx.signatures = vec![xfer_sigs, exec_sigs];
|
|
tx.signatures = vec![xfer_sigs, exec_sigs];
|
|
|
|
|
|