contract/money/client/pow_reward: decoupled signer and recipient keys

This commit is contained in:
aggstam
2023-10-17 12:40:09 +03:00
parent ab10b5145c
commit 7e40dd3633
3 changed files with 48 additions and 16 deletions

View File

@@ -24,7 +24,7 @@ use darkfi::{
use darkfi_sdk::{
blockchain::expected_reward,
crypto::{
ecvrf::VrfProof, note::AeadEncryptedNote, pasta_prelude::*, Keypair, PublicKey,
ecvrf::VrfProof, note::AeadEncryptedNote, pasta_prelude::*, PublicKey, SecretKey,
DARK_TOKEN_ID,
},
pasta::pallas,
@@ -66,8 +66,10 @@ impl PoWRewardRevealed {
/// Struct holding necessary information to build a `Money::PoWRewardV1` contract call.
pub struct PoWRewardCallBuilder {
/// Caller's keypair
pub keypair: Keypair,
/// Caller's secret key, used for signing and VRF proof generation
pub secret: SecretKey,
/// Reward recipient's public key
pub recipient: PublicKey,
/// Rewarded block height(slot)
pub block_height: u64,
/// Extending fork last proposal/block nonce
@@ -95,14 +97,10 @@ impl PoWRewardCallBuilder {
// Only DARK_TOKEN_ID can be minted as PoW reward.
let token_id = *DARK_TOKEN_ID;
let input = TransactionBuilderClearInputInfo {
value,
token_id,
signature_secret: self.keypair.secret,
};
let input =
TransactionBuilderClearInputInfo { value, token_id, signature_secret: self.secret };
let output =
TransactionBuilderOutputInfo { value, token_id, public_key: self.keypair.public };
let output = TransactionBuilderOutputInfo { value, token_id, public_key: self.recipient };
// We just create the commitment blinds here. We simply encofce
// that the clear input and the anon output have the same commitments.
@@ -157,7 +155,7 @@ impl PoWRewardCallBuilder {
vrf_input.extend_from_slice(&self.last_nonce.to_repr());
vrf_input.extend_from_slice(self.fork_previous_hash.as_bytes());
vrf_input.extend_from_slice(&pallas::Base::from(self.block_height).to_repr());
let vrf_proof = VrfProof::prove(self.keypair.secret, &vrf_input, &mut OsRng);
let vrf_proof = VrfProof::prove(self.secret, &vrf_input, &mut OsRng);
let params = MoneyPoWRewardParamsV1 {
input: c_input,

View File

@@ -51,7 +51,7 @@ fn pow_reward() -> Result<()> {
info!(target: "money", "[Malicious] =======================================");
info!(target: "money", "[Malicious] Building PoW reward tx for genesis slot");
info!(target: "money", "[Malicious] =======================================");
let (pow_reward_tx, _) = th.pow_reward(&Holder::Alice, current_height, Some(0))?;
let (pow_reward_tx, _) = th.pow_reward(&Holder::Alice, None, current_height, Some(0))?;
info!(target: "money", "[Malicious] =======================================");
info!(target: "money", "[Malicious] Checking PoW reward tx for genesis slot");
@@ -67,7 +67,7 @@ fn pow_reward() -> Result<()> {
info!(target: "money", "[Malicious] Building erroneous PoW reward tx");
info!(target: "money", "[Malicious] ================================");
let (pow_reward_tx, _) =
th.pow_reward(&Holder::Alice, current_height, Some(alice_reward + 1))?;
th.pow_reward(&Holder::Alice, None, current_height, Some(alice_reward + 1))?;
info!(target: "money", "[Malicious] =======================================");
info!(target: "money", "[Malicious] Checking erroneous amount PoW reward tx");
@@ -79,7 +79,7 @@ fn pow_reward() -> Result<()> {
info!(target: "money", "[Alice] Building PoW reward tx");
info!(target: "money", "[Alice] ======================");
let (pow_reward_tx, pow_reward_params) =
th.pow_reward(&Holder::Alice, current_height, None)?;
th.pow_reward(&Holder::Alice, None, current_height, None)?;
for holder in &HOLDERS {
info!(target: "money", "[{holder:?}] =============================");
@@ -128,11 +128,36 @@ fn pow_reward() -> Result<()> {
let bob_oc = th.gather_owncoin(&Holder::Bob, &transfer_params.outputs[1], None)?;
bob_owncoins.push(bob_oc);
// Alice can also send her PoW reward directly to bob
current_height += 1;
th.generate_slot(current_height).await?;
info!(target: "money", "[Alice] ==============================");
info!(target: "money", "[Alice] Building PoW reward tx for Bob");
info!(target: "money", "[Alice] ==============================");
let (pow_reward_tx, pow_reward_params) =
th.pow_reward(&Holder::Alice, Some(&Holder::Bob), current_height, None)?;
for holder in &HOLDERS {
info!(target: "money", "[{holder:?}] =====================================");
info!(target: "money", "[{holder:?}] Executing Alice PoW reward tx for Bob");
info!(target: "money", "[{holder:?}] =====================================");
th.execute_pow_reward_tx(holder, &pow_reward_tx, &pow_reward_params, current_height)
.await?;
}
th.assert_trees(&HOLDERS);
// Bob gathers his new owncoin
let bob_oc = th.gather_owncoin(&Holder::Bob, &pow_reward_params.output, None)?;
bob_owncoins.push(bob_oc);
// Validating transaction outcomes
assert!(alice_owncoins.len() == 1);
assert!(bob_owncoins.len() == 1);
assert!(bob_owncoins.len() == 2);
assert!(alice_owncoins[0].note.value == alice_reward - alice_send);
assert!(bob_owncoins[0].note.value == alice_send);
assert!(bob_owncoins[1].note.value == alice_reward);
// Statistics
th.statistics();

View File

@@ -37,6 +37,7 @@ impl TestHarness {
pub fn pow_reward(
&mut self,
holder: &Holder,
recipient: Option<&Holder>,
block_height: u64,
reward: Option<u64>,
) -> Result<(Transaction, MoneyPoWRewardParamsV1)> {
@@ -58,8 +59,16 @@ impl TestHarness {
let spend_hook = pallas::Base::zero();
let user_data = pallas::Base::zero();
let recipient = if let Some(holder) = recipient {
let holder = self.holders.get(holder).unwrap();
holder.keypair.public
} else {
wallet.keypair.public
};
let builder = PoWRewardCallBuilder {
keypair: wallet.keypair,
secret: wallet.keypair.secret,
recipient,
block_height,
last_nonce,
fork_hash,