From 3547539c3f274689a2709c6736acc3583063cd2d Mon Sep 17 00:00:00 2001 From: skoupidi Date: Wed, 7 Feb 2024 14:40:50 +0200 Subject: [PATCH] darkfid/tests: properly test sync logic by generating next blocks using fixed mining difficulty --- bin/darkfid/src/task/miner.rs | 5 +- bin/darkfid/src/tests/harness.rs | 79 +++++++++++++++++++++++++++++++- bin/darkfid/src/tests/mod.rs | 22 +++++---- 3 files changed, 91 insertions(+), 15 deletions(-) diff --git a/bin/darkfid/src/task/miner.rs b/bin/darkfid/src/task/miner.rs index ef8933705..c69408374 100644 --- a/bin/darkfid/src/task/miner.rs +++ b/bin/darkfid/src/task/miner.rs @@ -77,9 +77,8 @@ pub async fn miner_task(node: &Darkfid, recipient: &PublicKey) -> Result<()> { async fn miner_loop(node: &Darkfid, recipient: &PublicKey) -> Result<()> { // Grab zkas proving keys and bin for PoWReward transaction info!(target: "darkfid::task::miner_task", "Generating zkas bin and proving keys..."); - let blockchain = node.validator.blockchain.clone(); - let (zkbin, _) = blockchain.contracts.get_zkas( - &blockchain.sled_db, + let (zkbin, _) = node.validator.blockchain.contracts.get_zkas( + &node.validator.blockchain.sled_db, &MONEY_CONTRACT_ID, MONEY_CONTRACT_ZKAS_MINT_NS_V1, )?; diff --git a/bin/darkfid/src/tests/harness.rs b/bin/darkfid/src/tests/harness.rs index d2b0da5b8..4a84373a7 100644 --- a/bin/darkfid/src/tests/harness.rs +++ b/bin/darkfid/src/tests/harness.rs @@ -19,14 +19,26 @@ use std::{collections::HashMap, sync::Arc}; use darkfi::{ - blockchain::BlockInfo, + blockchain::{BlockInfo, Header}, net::Settings, rpc::jsonrpc::JsonSubscriber, + tx::{ContractCallLeaf, TransactionBuilder}, validator::{Validator, ValidatorConfig}, + zk::{empty_witnesses, ProvingKey, ZkCircuit}, Result, }; use darkfi_contract_test_harness::{vks, Holder, TestHarness}; +use darkfi_money_contract::{ + client::pow_reward_v1::PoWRewardCallBuilder, MoneyFunction, MONEY_CONTRACT_ZKAS_MINT_NS_V1, +}; +use darkfi_sdk::{ + crypto::{Keypair, MONEY_CONTRACT_ID}, + pasta::pallas, + ContractCall, +}; +use darkfi_serial::Encodable; use num_bigint::BigUint; +use rand::rngs::OsRng; use url::Url; use crate::{ @@ -146,7 +158,7 @@ impl Harness { Ok(()) } - pub async fn _add_blocks(&self, blocks: &[BlockInfo]) -> Result<()> { + pub async fn add_blocks(&self, blocks: &[BlockInfo]) -> Result<()> { // We simply broadcast the block using Alice's sync P2P for block in blocks { self.alice.sync_p2p.broadcast(&BlockInfoMessage::from(block)).await; @@ -157,6 +169,69 @@ impl Harness { Ok(()) } + + pub async fn generate_next_block(&self, previous: &BlockInfo) -> Result { + // Next block info + let block_height = previous.header.height + 1; + let last_nonce = previous.header.nonce; + let fork_previous_hash = previous.header.previous; + + // Generate a producer transaction + let keypair = Keypair::default(); + let (zkbin, _) = self.alice.validator.blockchain.contracts.get_zkas( + &self.alice.validator.blockchain.sled_db, + &MONEY_CONTRACT_ID, + MONEY_CONTRACT_ZKAS_MINT_NS_V1, + )?; + let circuit = ZkCircuit::new(empty_witnesses(&zkbin)?, &zkbin); + let pk = ProvingKey::build(zkbin.k, &circuit); + + // We're just going to be using a zero spend-hook and user-data + let spend_hook = pallas::Base::zero().into(); + let user_data = pallas::Base::zero(); + + // Build the transaction debris + let debris = PoWRewardCallBuilder { + secret: keypair.secret, + recipient: keypair.public, + block_height, + last_nonce, + fork_previous_hash, + spend_hook, + user_data, + mint_zkbin: zkbin.clone(), + mint_pk: pk.clone(), + } + .build()?; + + // Generate and sign the actual transaction + let mut data = vec![MoneyFunction::PoWRewardV1 as u8]; + debris.params.encode(&mut data)?; + let call = ContractCall { contract_id: *MONEY_CONTRACT_ID, data }; + let mut tx_builder = + TransactionBuilder::new(ContractCallLeaf { call, proofs: debris.proofs }, vec![])?; + let mut tx = tx_builder.build()?; + let sigs = tx.create_sigs(&mut OsRng, &[keypair.secret])?; + tx.signatures = vec![sigs]; + + // We increment timestamp so we don't have to use sleep + let mut timestamp = previous.header.timestamp; + timestamp.add(1); + + // Generate header + let header = Header::new(previous.hash()?, block_height, timestamp, last_nonce); + + // Generate the block + let mut block = BlockInfo::new_empty(header); + + // Add producer transaction to the block + block.append_txs(vec![tx])?; + + // Attach signature + block.sign(&keypair.secret)?; + + Ok(block) + } } // Note: This function should mirror darkfid::main diff --git a/bin/darkfid/src/tests/mod.rs b/bin/darkfid/src/tests/mod.rs index aa8548f5e..e439733bd 100644 --- a/bin/darkfid/src/tests/mod.rs +++ b/bin/darkfid/src/tests/mod.rs @@ -20,6 +20,8 @@ use std::sync::Arc; use darkfi::{net::Settings, Result}; use darkfi_contract_test_harness::init_logger; +use darkfi_sdk::num_traits::One; +use num_bigint::BigUint; use smol::Executor; use url::Url; @@ -33,7 +35,7 @@ async fn sync_blocks_real(ex: Arc>) -> Result<()> { // Initialize harness in testing mode let pow_target = 90; - let pow_fixed_difficulty = None; + let pow_fixed_difficulty = Some(BigUint::one()); let config = HarnessConfig { pow_target, pow_fixed_difficulty: pow_fixed_difficulty.clone(), @@ -43,19 +45,19 @@ async fn sync_blocks_real(ex: Arc>) -> Result<()> { let th = Harness::new(config, false, &ex).await?; // Retrieve genesis block - let _previous = th.alice.validator.blockchain.last_block()?; + let previous = th.alice.validator.blockchain.last_block()?; - // Generate next block - //let block1 = th.generate_next_block(&previous).await?; + // Generate next blocks + let block1 = th.generate_next_block(&previous).await?; + let block2 = th.generate_next_block(&block1).await?; + let block3 = th.generate_next_block(&block2).await?; + let block4 = th.generate_next_block(&block3).await?; - // Generate next block - //let block2 = th.generate_next_block(&block1).await?; - - // Add it to nodes - //th.add_blocks(&vec![block1, block2]).await?; + // Add them to nodes + th.add_blocks(&vec![block1, block2, block3, block4]).await?; // Validate chains - th.validate_chains(1).await?; + th.validate_chains(5).await?; // We are going to create a third node and try to sync from the previous two let mut sync_settings =