darkfi_money_contract/client/
pow_reward_v1.rs1use darkfi::{
20 zk::{Proof, ProvingKey},
21 zkas::ZkBinary,
22 Result,
23};
24use darkfi_sdk::{
25 blockchain::expected_reward,
26 crypto::{note::AeadEncryptedNote, pasta_prelude::*, Blind, FuncId, PublicKey},
27 pasta::pallas,
28};
29use log::debug;
30use rand::rngs::OsRng;
31
32use crate::{
33 client::{
34 transfer_v1::{proof::create_transfer_mint_proof, TransferCallOutput},
35 MoneyNote,
36 },
37 model::{ClearInput, Coin, MoneyPoWRewardParamsV1, Output, DARK_TOKEN_ID},
38};
39
40pub struct PoWRewardCallDebris {
41 pub params: MoneyPoWRewardParamsV1,
42 pub proofs: Vec<Proof>,
43}
44
45pub struct PoWRewardRevealed {
46 pub coin: Coin,
47 pub value_commit: pallas::Point,
48 pub token_commit: pallas::Base,
49}
50
51impl PoWRewardRevealed {
52 pub fn to_vec(&self) -> Vec<pallas::Base> {
53 let valcom_coords = self.value_commit.to_affine().coordinates().unwrap();
54
55 vec![self.coin.inner(), *valcom_coords.x(), *valcom_coords.y(), self.token_commit]
58 }
59}
60
61pub struct PoWRewardCallBuilder {
63 pub signature_public: PublicKey,
65 pub block_height: u32,
67 pub fees: u64,
69 pub recipient: Option<PublicKey>,
71 pub spend_hook: Option<FuncId>,
73 pub user_data: Option<pallas::Base>,
75 pub mint_zkbin: ZkBinary,
77 pub mint_pk: ProvingKey,
79}
80
81impl PoWRewardCallBuilder {
82 fn _build(&self, value: u64) -> Result<PoWRewardCallDebris> {
83 debug!(target: "contract::money::client::pow_reward", "Building Money::PoWRewardV1 contract call");
84
85 let token_id = *DARK_TOKEN_ID;
88
89 let value_blind = Blind::random(&mut OsRng);
91 let token_blind = Blind::random(&mut OsRng);
92 let coin_blind = Blind::random(&mut OsRng);
93 let c_input = ClearInput {
94 value,
95 token_id,
96 value_blind,
97 token_blind,
98 signature_public: self.signature_public,
99 };
100
101 let spend_hook = self.spend_hook.unwrap_or(FuncId::none());
103 let user_data = self.user_data.unwrap_or(pallas::Base::ZERO);
104
105 let output = TransferCallOutput {
107 public_key: self.recipient.unwrap_or(self.signature_public),
108 value,
109 token_id,
110 spend_hook,
111 user_data,
112 blind: Blind::random(&mut OsRng),
113 };
114
115 debug!(target: "contract::money::client::pow_reward", "Creating token mint proof for output");
116 let (proof, public_inputs) = create_transfer_mint_proof(
117 &self.mint_zkbin,
118 &self.mint_pk,
119 &output,
120 value_blind,
121 token_blind,
122 spend_hook,
123 user_data,
124 coin_blind,
125 )?;
126
127 let note = MoneyNote {
128 value: output.value,
129 token_id: output.token_id,
130 spend_hook,
131 user_data,
132 coin_blind,
133 value_blind,
134 token_blind,
135 memo: vec![],
136 };
137
138 let encrypted_note = AeadEncryptedNote::encrypt(¬e, &output.public_key, &mut OsRng)?;
139
140 let c_output = Output {
141 value_commit: public_inputs.value_commit,
142 token_commit: public_inputs.token_commit,
143 coin: public_inputs.coin,
144 note: encrypted_note,
145 };
146
147 let params = MoneyPoWRewardParamsV1 { input: c_input, output: c_output };
148 let debris = PoWRewardCallDebris { params, proofs: vec![proof] };
149 Ok(debris)
150 }
151
152 pub fn build(&self) -> Result<PoWRewardCallDebris> {
153 let reward = expected_reward(self.block_height) + self.fees;
154 self._build(reward)
155 }
156
157 pub fn build_with_custom_reward(&self, reward: u64) -> Result<PoWRewardCallDebris> {
159 self._build(reward + self.fees)
160 }
161}