darkfid: optional mining reward spend hook and user data added

This commit is contained in:
skoupidi
2024-06-20 14:18:16 +03:00
parent 3f31e393e1
commit 109b902b01
14 changed files with 158 additions and 48 deletions

1
Cargo.lock generated
View File

@@ -2206,6 +2206,7 @@ version = "0.4.1"
dependencies = [
"async-trait",
"blake3 1.5.1",
"bs58",
"darkfi",
"darkfi-contract-test-harness",
"darkfi-sdk",

View File

@@ -10,7 +10,7 @@ edition = "2021"
[dependencies]
# Darkfi
darkfi = {path = "../../", features = ["async-daemonize"]}
darkfi = {path = "../../", features = ["async-daemonize", "bs58"]}
darkfi_money_contract = {path = "../../src/contract/money"}
darkfi-contract-test-harness = {path = "../../src/contract/test-harness"}
darkfi-sdk = {path = "../../src/sdk"}
@@ -18,6 +18,7 @@ darkfi-serial = {path = "../../src/serial"}
# Misc
blake3 = "1.5.1"
bs58 = "0.5.1"
log = "0.4.21"
num-bigint = "0.4.5"
rand = "0.8.5"

View File

@@ -40,6 +40,12 @@ miner = true
# replace with your own one.
recipient = "5ZHfYpt4mpJcwBNxfEyxLzeFJUEeoePs5NQ5jVEgHrMf"
# Optional contract spend hook to use in the mining reward
#spend_hook = "YOUR_SPEND_HOOK_HERE"
# Optional user data to use in the mining reward
#user_data = "YOUR_USER_DATA_HERE"
# Skip syncing process and start node right away
skip_sync = true
@@ -132,6 +138,12 @@ miner = false
# Wallet address to receive mining rewards.
#recipient = "YOUR_WALLET_ADDRESS_HERE"
# Optional contract spend hook to use in the mining reward
#spend_hook = "YOUR_SPEND_HOOK_HERE"
# Optional user data to use in the mining reward
#user_data = "YOUR_USER_DATA_HERE"
# Skip syncing process and start node right away
skip_sync = false
@@ -228,6 +240,12 @@ miner = false
# Wallet address to receive mining rewards.
#recipient = "YOUR_WALLET_ADDRESS_HERE"
# Optional contract spend hook to use in the mining reward
#spend_hook = "YOUR_SPEND_HOOK_HERE"
# Optional user data to use in the mining reward
#user_data = "YOUR_USER_DATA_HERE"
# Skip syncing process and start node right away
skip_sync = false

View File

@@ -136,6 +136,14 @@ pub struct BlockchainNetwork {
/// Wallet address to receive mining rewards
pub recipient: Option<String>,
#[structopt(long)]
/// Optional contract spend hook to use in the mining reward
pub spend_hook: Option<String>,
#[structopt(long)]
/// Optional user data to use in the mining reward
pub user_data: Option<String>,
#[structopt(long)]
/// Skip syncing process and start node right away
pub skip_sync: bool,
@@ -341,13 +349,16 @@ async fn realmain(args: Args, ex: Arc<smol::Executor<'static>>) -> Result<()> {
consensus_task.clone().start(
consensus_init_task(
darkfid.clone(),
ConsensusInitTaskConfig::new(
blockchain_config.skip_sync,
blockchain_config.checkpoint_height,
blockchain_config.checkpoint, blockchain_config.miner,
blockchain_config.recipient,
ConsensusInitTaskConfig {
skip_sync: blockchain_config.skip_sync,
checkpoint_height: blockchain_config.checkpoint_height,
checkpoint: blockchain_config.checkpoint,
miner: blockchain_config.miner,
recipient: blockchain_config.recipient,
spend_hook: blockchain_config.spend_hook,
user_data: blockchain_config.user_data,
bootstrap,
),
},
ex.clone(),
),
|res| async move {

View File

@@ -25,36 +25,28 @@ use darkfi::{
util::{encoding::base64, time::Timestamp},
Error, Result,
};
use darkfi_sdk::crypto::PublicKey;
use darkfi_sdk::{
crypto::{FuncId, PublicKey},
pasta::{group::ff::PrimeField, pallas},
};
use darkfi_serial::serialize_async;
use log::{error, info};
use crate::{
task::{garbage_collect_task, miner_task, sync_task},
task::{garbage_collect_task, miner::MinerRewardsRecipientConfig, miner_task, sync_task},
Darkfid,
};
/// Auxiliary structure representing node consesus init task configuration
/// Auxiliary structure representing node consensus init task configuration
pub struct ConsensusInitTaskConfig {
skip_sync: bool,
checkpoint_height: Option<u32>,
checkpoint: Option<String>,
miner: bool,
recipient: Option<String>,
bootstrap: u64,
}
impl ConsensusInitTaskConfig {
pub fn new(
skip_sync: bool,
checkpoint_height: Option<u32>,
checkpoint: Option<String>,
miner: bool,
recipient: Option<String>,
bootstrap: u64,
) -> Self {
Self { skip_sync, checkpoint_height, checkpoint, miner, recipient, bootstrap }
}
pub skip_sync: bool,
pub checkpoint_height: Option<u32>,
pub checkpoint: Option<String>,
pub miner: bool,
pub recipient: Option<String>,
pub spend_hook: Option<String>,
pub user_data: Option<String>,
pub bootstrap: u64,
}
/// Sync the node consensus state and start the corresponding task, based on node type.
@@ -97,15 +89,41 @@ pub async fn consensus_init_task(
None
};
// Grab rewards recipient public key(address) if node is a miner
let recipient = if config.miner {
// Grab rewards recipient public key(address) if node is a miner,
// along with configured spend hook and user data.
let recipient_config = if config.miner {
if config.recipient.is_none() {
return Err(Error::ParseFailed("Recipient address missing"))
}
match PublicKey::from_str(config.recipient.as_ref().unwrap()) {
Ok(address) => Some(address),
let recipient = match PublicKey::from_str(config.recipient.as_ref().unwrap()) {
Ok(address) => address,
Err(_) => return Err(Error::InvalidAddress),
}
};
let spend_hook = match config.spend_hook {
Some(s) => match FuncId::from_str(&s) {
Ok(s) => Some(s),
Err(_) => return Err(Error::ParseFailed("Invalid spend hook")),
},
None => None,
};
let user_data = match config.user_data {
Some(u) => {
let bytes: [u8; 32] = match bs58::decode(&u).into_vec()?.try_into() {
Ok(b) => b,
Err(_) => return Err(Error::ParseFailed("Invalid user data")),
};
match pallas::Base::from_repr(bytes).into() {
Some(v) => Some(v),
None => return Err(Error::ParseFailed("Invalid user data")),
}
}
None => None,
};
Some(MinerRewardsRecipientConfig { recipient, spend_hook, user_data })
} else {
None
};
@@ -113,7 +131,13 @@ pub async fn consensus_init_task(
// Gracefully handle network disconnections
loop {
let result = if config.miner {
miner_task(node.clone(), recipient.unwrap(), config.skip_sync, ex.clone()).await
miner_task(
node.clone(),
recipient_config.as_ref().unwrap(),
config.skip_sync,
ex.clone(),
)
.await
} else {
replicator_task(node.clone(), ex.clone()).await
};

View File

@@ -36,7 +36,7 @@ use darkfi_money_contract::{
client::pow_reward_v1::PoWRewardCallBuilder, MoneyFunction, MONEY_CONTRACT_ZKAS_MINT_NS_V1,
};
use darkfi_sdk::{
crypto::{poseidon_hash, PublicKey, SecretKey, MONEY_CONTRACT_ID},
crypto::{poseidon_hash, FuncId, PublicKey, SecretKey, MONEY_CONTRACT_ID},
pasta::pallas,
ContractCall,
};
@@ -48,6 +48,13 @@ use smol::channel::{Receiver, Sender};
use crate::{proto::ProposalMessage, task::garbage_collect_task, Darkfid};
/// Auxiliary structure representing node miner rewards recipient configuration
pub struct MinerRewardsRecipientConfig {
pub recipient: PublicKey,
pub spend_hook: Option<FuncId>,
pub user_data: Option<pallas::Base>,
}
/// Async task used for participating in the PoW block production.
/// Miner initializes their setup and waits for next finalization,
/// by listenning for new proposals from the network, for optimal
@@ -60,7 +67,7 @@ use crate::{proto::ProposalMessage, task::garbage_collect_task, Darkfid};
/// finishes, node triggers finallization check.
pub async fn miner_task(
node: Arc<Darkfid>,
recipient: PublicKey,
recipient_config: &MinerRewardsRecipientConfig,
skip_sync: bool,
ex: Arc<smol::Executor<'static>>,
) -> Result<()> {
@@ -158,7 +165,7 @@ pub async fn miner_task(
&node,
&extended_fork,
&mut secret,
&recipient,
recipient_config,
&zkbin,
&pk,
&stop_signal,
@@ -262,7 +269,7 @@ async fn mine(
node: &Darkfid,
extended_fork: &Fork,
secret: &mut SecretKey,
recipient: &PublicKey,
recipient_config: &MinerRewardsRecipientConfig,
zkbin: &ZkBinary,
pk: &ProvingKey,
stop_signal: &Receiver<()>,
@@ -270,7 +277,7 @@ async fn mine(
) -> Result<()> {
smol::future::or(
wait_stop_signal(stop_signal),
mine_next_block(node, extended_fork, secret, recipient, zkbin, pk, skip_sync),
mine_next_block(node, extended_fork, secret, recipient_config, zkbin, pk, skip_sync),
)
.await
}
@@ -293,7 +300,7 @@ async fn mine_next_block(
node: &Darkfid,
extended_fork: &Fork,
secret: &mut SecretKey,
recipient: &PublicKey,
recipient_config: &MinerRewardsRecipientConfig,
zkbin: &ZkBinary,
pk: &ProvingKey,
skip_sync: bool,
@@ -302,7 +309,7 @@ async fn mine_next_block(
let (next_target, mut next_block) = generate_next_block(
extended_fork,
secret,
recipient,
recipient_config,
zkbin,
pk,
node.validator.consensus.module.read().await.target,
@@ -343,7 +350,7 @@ async fn mine_next_block(
async fn generate_next_block(
extended_fork: &Fork,
secret: &mut SecretKey,
recipient: &PublicKey,
recipient_config: &MinerRewardsRecipientConfig,
zkbin: &ZkBinary,
pk: &ProvingKey,
block_target: u32,
@@ -368,7 +375,7 @@ async fn generate_next_block(
*secret = SecretKey::from(next_secret);
// Generate reward transaction
let tx = generate_transaction(next_block_height, fees, secret, recipient, zkbin, pk)?;
let tx = generate_transaction(next_block_height, fees, secret, recipient_config, zkbin, pk)?;
txs.push(tx);
// Generate the new header
@@ -391,7 +398,7 @@ fn generate_transaction(
block_height: u32,
fees: u64,
secret: &SecretKey,
recipient: &PublicKey,
recipient_config: &MinerRewardsRecipientConfig,
zkbin: &ZkBinary,
pk: &ProvingKey,
) -> Result<Transaction> {
@@ -400,9 +407,9 @@ fn generate_transaction(
signature_public: PublicKey::from_secret(*secret),
block_height,
fees,
recipient: Some(*recipient),
spend_hook: None,
user_data: None,
recipient: Some(recipient_config.recipient),
spend_hook: recipient_config.spend_hook,
user_data: recipient_config.user_data,
mint_zkbin: zkbin.clone(),
mint_pk: pk.clone(),
}

View File

@@ -34,6 +34,12 @@ miner = true
# replace with your own one.
recipient = "9vw6WznKk7xEFQwwXhJWMMdjUPi3cXL8NrFKQpKifG1U"
# Optional contract spend hook to use in the mining reward
#spend_hook = "YOUR_SPEND_HOOK_HERE"
# Optional user data to use in the mining reward
#user_data = "YOUR_USER_DATA_HERE"
# Skip syncing process and start node right away
skip_sync = true

View File

@@ -34,6 +34,12 @@ miner = true
# replace with your own one.
recipient = "9vw6WznKk7xEFQwwXhJWMMdjUPi3cXL8NrFKQpKifG1U"
# Optional contract spend hook to use in the mining reward
#spend_hook = "YOUR_SPEND_HOOK_HERE"
# Optional user data to use in the mining reward
#user_data = "YOUR_USER_DATA_HERE"
# Skip syncing process and start node right away
skip_sync = false

View File

@@ -34,6 +34,12 @@ miner = true
# replace with your own one.
recipient = "9vw6WznKk7xEFQwwXhJWMMdjUPi3cXL8NrFKQpKifG1U"
# Optional contract spend hook to use in the mining reward
#spend_hook = "YOUR_SPEND_HOOK_HERE"
# Optional user data to use in the mining reward
#user_data = "YOUR_USER_DATA_HERE"
# Skip syncing process and start node right away
skip_sync = false

View File

@@ -34,6 +34,12 @@ miner = true
# replace with your own one.
recipient = "9vw6WznKk7xEFQwwXhJWMMdjUPi3cXL8NrFKQpKifG1U"
# Optional contract spend hook to use in the mining reward
#spend_hook = "YOUR_SPEND_HOOK_HERE"
# Optional user data to use in the mining reward
#user_data = "YOUR_USER_DATA_HERE"
# Skip syncing process and start node right away
skip_sync = false

View File

@@ -34,6 +34,12 @@ miner = true
# replace with your own one.
recipient = "9vw6WznKk7xEFQwwXhJWMMdjUPi3cXL8NrFKQpKifG1U"
# Optional contract spend hook to use in the mining reward
#spend_hook = "YOUR_SPEND_HOOK_HERE"
# Optional user data to use in the mining reward
#user_data = "YOUR_USER_DATA_HERE"
# Skip syncing process and start node right away
skip_sync = false

View File

@@ -37,6 +37,12 @@ miner = true
# replace with your own one.
recipient = "9vw6WznKk7xEFQwwXhJWMMdjUPi3cXL8NrFKQpKifG1U"
# Optional contract spend hook to use in the mining reward
#spend_hook = "6iW9nywZYvyhcM7P1iLwYkh92rvYtREDsC8hgqf2GLuT"
# Optional user data to use in the mining reward
#user_data = "YOUR_USER_DATA_HERE"
# Skip syncing process and start node right away
skip_sync = true

View File

@@ -34,6 +34,12 @@ miner = true
# replace with your own one.
recipient = "9vw6WznKk7xEFQwwXhJWMMdjUPi3cXL8NrFKQpKifG1U"
# Optional contract spend hook to use in the mining reward
#spend_hook = "YOUR_SPEND_HOOK_HERE"
# Optional user data to use in the mining reward
#user_data = "YOUR_USER_DATA_HERE"
# Skip syncing process and start node right away
skip_sync = true

View File

@@ -42,6 +42,12 @@ miner = true
# replace with your own one.
recipient = "9vw6WznKk7xEFQwwXhJWMMdjUPi3cXL8NrFKQpKifG1U"
# Optional contract spend hook to use in the mining reward
#spend_hook = "YOUR_SPEND_HOOK_HERE"
# Optional user data to use in the mining reward
#user_data = "YOUR_USER_DATA_HERE"
# Skip syncing process and start node right away
skip_sync = false