darkfi_contract_test_harness/
money_pow_reward.rs1use darkfi::{
20 blockchain::{BlockInfo, BlockchainOverlay, Header},
21 tx::{ContractCallLeaf, Transaction, TransactionBuilder},
22 validator::verification::apply_producer_transaction,
23 Result,
24};
25use darkfi_money_contract::{
26 client::{pow_reward_v1::PoWRewardCallBuilder, MoneyNote, OwnCoin},
27 model::MoneyPoWRewardParamsV1,
28 MoneyFunction, MONEY_CONTRACT_ZKAS_MINT_NS_V1,
29};
30use darkfi_sdk::{
31 crypto::{contract_id::MONEY_CONTRACT_ID, MerkleNode, MerkleTree},
32 ContractCall,
33};
34use darkfi_serial::AsyncEncodable;
35use log::info;
36
37use super::{Holder, TestHarness};
38
39impl TestHarness {
40 async fn pow_reward(
45 &mut self,
46 holder: &Holder,
47 recipient: Option<&Holder>,
48 reward: Option<u64>,
49 fees: Option<u64>,
50 ) -> Result<(Transaction, MoneyPoWRewardParamsV1)> {
51 let wallet = self.holders.get(holder).unwrap();
52
53 let (mint_pk, mint_zkbin) = self.proving_keys.get(MONEY_CONTRACT_ZKAS_MINT_NS_V1).unwrap();
54
55 let last_block = wallet.validator.blockchain.last_block()?;
57
58 let recipient = if let Some(holder) = recipient {
60 Some(self.holders.get(holder).unwrap().keypair.public)
61 } else {
62 None
63 };
64
65 let fees = fees.unwrap_or_default();
67
68 let builder = PoWRewardCallBuilder {
70 signature_public: wallet.keypair.public,
71 block_height: last_block.header.height + 1,
72 fees,
73 recipient,
74 spend_hook: None,
75 user_data: None,
76 mint_zkbin: mint_zkbin.clone(),
77 mint_pk: mint_pk.clone(),
78 };
79
80 let debris = match reward {
81 Some(value) => builder.build_with_custom_reward(value)?,
82 None => builder.build()?,
83 };
84
85 let mut data = vec![MoneyFunction::PoWRewardV1 as u8];
87 debris.params.encode_async(&mut data).await?;
88 let call = ContractCall { contract_id: *MONEY_CONTRACT_ID, data };
89 let mut tx_builder =
90 TransactionBuilder::new(ContractCallLeaf { call, proofs: debris.proofs }, vec![])?;
91 let mut tx = tx_builder.build()?;
92 let sigs = tx.create_sigs(&[wallet.keypair.secret])?;
93 tx.signatures = vec![sigs];
94
95 Ok((tx, debris.params))
96 }
97
98 pub async fn generate_block(
103 &mut self,
104 miner: &Holder,
105 holders: &[Holder],
106 ) -> Result<Vec<OwnCoin>> {
107 info!("Building PoWReward transaction for {miner:?}");
109 let (tx, params) = self.pow_reward(miner, None, None, None).await?;
110
111 let wallet = self.holders.get(miner).unwrap();
113 let previous = wallet.validator.blockchain.last_block()?;
114
115 let timestamp = previous.header.timestamp.checked_add(1.into())?;
117
118 let header = Header::new(
120 previous.hash(),
121 previous.header.height + 1,
122 timestamp,
123 previous.header.nonce,
124 );
125
126 let mut block = BlockInfo::new_empty(header);
128
129 block.append_txs(vec![tx]);
131
132 let overlay = BlockchainOverlay::new(&wallet.validator.blockchain)?;
134 let _ = apply_producer_transaction(
135 &overlay,
136 block.header.height,
137 wallet.validator.consensus.module.read().await.target,
138 block.txs.last().unwrap(),
139 &mut MerkleTree::new(1),
140 )
141 .await?;
142 block.header.state_root =
143 overlay.lock().unwrap().contracts.get_state_monotree()?.get_headroot()?.unwrap();
144
145 block.sign(&wallet.keypair.secret);
147
148 let mut found_owncoins = vec![];
150 for holder in holders {
151 let wallet = self.holders.get_mut(holder).unwrap();
152 wallet.validator.add_test_blocks(&[block.clone()]).await?;
153 wallet.money_merkle_tree.append(MerkleNode::from(params.output.coin.inner()));
154
155 let Ok(note) = params.output.note.decrypt::<MoneyNote>(&wallet.keypair.secret) else {
157 continue
158 };
159
160 let owncoin = OwnCoin {
161 coin: params.output.coin,
162 note: note.clone(),
163 secret: wallet.keypair.secret,
164 leaf_position: wallet.money_merkle_tree.mark().unwrap(),
165 };
166
167 wallet.unspent_money_coins.push(owncoin.clone());
168 found_owncoins.push(owncoin);
169 }
170
171 Ok(found_owncoins)
172 }
173}