فهرست منبع

darkfid/tests: properly test sync logic by generating next blocks using fixed mining difficulty

skoupidi 2 سال پیش
والد
کامیت
3547539c3f
3فایلهای تغییر یافته به همراه91 افزوده شده و 15 حذف شده
  1. 2 3
      bin/darkfid/src/task/miner.rs
  2. 77 2
      bin/darkfid/src/tests/harness.rs
  3. 12 10
      bin/darkfid/src/tests/mod.rs

+ 2 - 3
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,
     )?;

+ 77 - 2
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<BlockInfo> {
+        // 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

+ 12 - 10
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<Executor<'static>>) -> 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<Executor<'static>>) -> 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 =