瀏覽代碼

runtime: get_block_target() fn added, to retrieve current block time target(seconds)

skoupidi 2 年之前
父節點
當前提交
43f9fc8aa1

+ 1 - 1
bin/darkfid/src/main.rs

@@ -120,7 +120,7 @@ pub struct BlockchainNetwork {
 
     #[structopt(long, default_value = "10")]
     /// PoW block production target, in seconds
-    pub pow_target: usize,
+    pub pow_target: u32,
 
     #[structopt(long)]
     /// Optional fixed PoW difficulty, used for testing

+ 1 - 0
bin/darkfid/src/task/garbage_collect.rs

@@ -104,6 +104,7 @@ pub async fn garbage_collect_task(node: Arc<Darkfid>) -> Result<()> {
                 match verify_transactions(
                     &overlay,
                     next_block_height,
+                    node.validator.consensus.module.read().await.target,
                     &tx_vec,
                     &mut MerkleTree::new(1),
                     false,

+ 3 - 1
bin/darkfid/src/task/miner.rs

@@ -291,6 +291,7 @@ async fn mine_next_block(
         recipient,
         zkbin,
         pk,
+        node.validator.consensus.module.read().await.target,
         node.validator.verify_fees,
     )
     .await?;
@@ -326,6 +327,7 @@ async fn generate_next_block(
     recipient: &PublicKey,
     zkbin: &ZkBinary,
     pk: &ProvingKey,
+    block_target: u32,
     verify_fees: bool,
 ) -> Result<(BigUint, BlockInfo)> {
     // Grab forks' last block proposal(previous)
@@ -336,7 +338,7 @@ async fn generate_next_block(
 
     // Grab forks' unproposed transactions
     let (mut txs, fees) = extended_fork
-        .unproposed_txs(&extended_fork.blockchain, next_block_height, verify_fees)
+        .unproposed_txs(&extended_fork.blockchain, next_block_height, block_target, verify_fees)
         .await?;
 
     // We are deriving the next secret key for optimization.

+ 1 - 1
bin/darkfid/src/tests/harness.rs

@@ -44,7 +44,7 @@ use url::Url;
 use crate::{proto::ProposalMessage, task::sync::sync_task, utils::spawn_p2p, Darkfid};
 
 pub struct HarnessConfig {
-    pub pow_target: usize,
+    pub pow_target: u32,
     pub pow_fixed_difficulty: Option<BigUint>,
     pub finalization_threshold: usize,
 }

+ 7 - 1
src/contract/money/tests/delayed_tx.rs

@@ -138,7 +138,13 @@ fn delayed_tx() -> Result<()> {
         let mut gas_used = FEE_CALL_GAS;
         gas_used += wallet
             .validator
-            .add_test_transactions(&[tx], current_block_height, false, false)
+            .add_test_transactions(
+                &[tx],
+                current_block_height,
+                wallet.validator.consensus.module.read().await.target,
+                false,
+                false,
+            )
             .await?;
 
         let coin = &output_coins[0];

+ 10 - 3
src/contract/test-harness/src/lib.rs

@@ -206,11 +206,17 @@ impl Wallet {
         block_height: u32,
     ) -> Result<()> {
         if self.bench_wasm {
-            benchmark_wasm_calls(callname, &self.validator, &tx, block_height);
+            benchmark_wasm_calls(callname, &self.validator, &tx, block_height).await;
         }
 
         self.validator
-            .add_test_transactions(&[tx.clone()], block_height, true, self.validator.verify_fees)
+            .add_test_transactions(
+                &[tx.clone()],
+                block_height,
+                self.validator.consensus.module.read().await.target,
+                true,
+                self.validator.verify_fees,
+            )
             .await?;
 
         // Write the data
@@ -301,7 +307,7 @@ impl TestHarness {
     }
 }
 
-fn benchmark_wasm_calls(
+async fn benchmark_wasm_calls(
     callname: &str,
     validator: &Validator,
     tx: &Transaction,
@@ -317,6 +323,7 @@ fn benchmark_wasm_calls(
             overlay.clone(),
             call.data.contract_id,
             block_height,
+            validator.consensus.module.read().await.target,
             tx.hash(),
             idx as u8,
         )

+ 10 - 2
src/contract/test-harness/src/money_fee.rs

@@ -218,8 +218,16 @@ impl TestHarness {
         // and verification.
         let wallet = self.holders.get(holder).unwrap();
         let mut gas_used = FEE_CALL_GAS;
-        gas_used +=
-            wallet.validator.add_test_transactions(&[tx], block_height, false, false).await?;
+        gas_used += wallet
+            .validator
+            .add_test_transactions(
+                &[tx],
+                block_height,
+                wallet.validator.consensus.module.read().await.target,
+                false,
+                false,
+            )
+            .await?;
 
         // Knowing the total gas, we can now find an OwnCoin of enough value
         // so that we can create a valid Money::Fee call.

+ 24 - 0
src/runtime/import/util.rs

@@ -218,6 +218,30 @@ pub(crate) fn get_verifying_block_height(mut ctx: FunctionEnvMut<Env>) -> i64 {
     env.verifying_block_height as i64
 }
 
+/// Will return currently configured block time target, in seconds
+///
+/// Permissions: deploy, metadata, exec
+pub(crate) fn get_block_target(mut ctx: FunctionEnvMut<Env>) -> i64 {
+    let (env, mut store) = ctx.data_and_store_mut();
+    let cid = env.contract_id;
+
+    if let Err(e) =
+        acl_allow(env, &[ContractSection::Deploy, ContractSection::Metadata, ContractSection::Exec])
+    {
+        error!(
+            target: "runtime::util::get_block_target",
+            "[WASM] [{}] get_block_target(): Called in unauthorized section: {}", cid, e,
+        );
+        return darkfi_sdk::error::CALLER_ACCESS_DENIED
+    }
+
+    // Subtract used gas. Here we count the size of the object.
+    // u32 is 4 bytes.
+    env.subtract_gas(&mut store, 4);
+
+    env.block_target as i64
+}
+
 /// Will return current runtime configured transaction hash
 ///
 /// Permissions: deploy, metadata, exec

+ 10 - 0
src/runtime/vm_runtime.rs

@@ -97,6 +97,8 @@ pub struct Env {
     /// Block height number runtime verifies against.
     /// For unconfirmed txs, this will be the current max height in the chain.
     pub verifying_block_height: u32,
+    /// Currently configured block time target, in seconds
+    pub block_target: u32,
     /// The hash for this transaction the runtime is being run against.
     pub tx_hash: TransactionHash,
     /// The index for this call in the transaction
@@ -156,6 +158,7 @@ impl Runtime {
         blockchain: BlockchainOverlayPtr,
         contract_id: ContractId,
         verifying_block_height: u32,
+        block_target: u32,
         tx_hash: TransactionHash,
         call_idx: u8,
     ) -> Result<Self> {
@@ -199,6 +202,7 @@ impl Runtime {
                 memory: None,
                 objects: RefCell::new(vec![]),
                 verifying_block_height,
+                block_target,
                 tx_hash,
                 call_idx,
                 instance: None,
@@ -291,6 +295,12 @@ impl Runtime {
                     import::util::get_verifying_block_height,
                 ),
 
+                "get_block_target_" => Function::new_typed_with_env(
+                    &mut store,
+                    &ctx,
+                    import::util::get_block_target,
+                ),
+
                 "get_tx_hash_" => Function::new_typed_with_env(
                     &mut store,
                     &ctx,

+ 12 - 0
src/sdk/src/wasm/util.rs

@@ -98,6 +98,17 @@ pub fn get_verifying_block_height() -> GenericResult<u32> {
     parse_retval_u32(ret)
 }
 
+/// Everyone can call this. Will return runtime configured
+/// block target.
+///
+/// ```
+/// block_target = get_block_target();
+/// ```
+pub fn get_block_target() -> GenericResult<u32> {
+    let ret = unsafe { get_block_target_() };
+    parse_retval_u32(ret)
+}
+
 /// Only deploy(), metadata() and exec() can call this. Will return runtime configured
 /// transaction hash.
 ///
@@ -187,6 +198,7 @@ extern "C" {
     fn get_object_size_(len: u32) -> i64;
 
     fn get_verifying_block_height_() -> i64;
+    fn get_block_target_() -> i64;
     fn get_tx_hash_() -> i64;
     fn get_call_index_() -> i64;
     fn get_blockchain_time_() -> i64;

+ 3 - 1
src/validator/consensus.rs

@@ -63,7 +63,7 @@ impl Consensus {
     pub fn new(
         blockchain: Blockchain,
         finalization_threshold: usize,
-        pow_target: usize,
+        pow_target: u32,
         pow_fixed_difficulty: Option<BigUint>,
     ) -> Result<Self> {
         let forks = RwLock::new(vec![]);
@@ -616,6 +616,7 @@ impl Fork {
         &self,
         blockchain: &Blockchain,
         verifying_block_height: u32,
+        block_target: u32,
         verify_fees: bool,
     ) -> Result<(Vec<Transaction>, u64)> {
         // Check if our mempool is not empty
@@ -660,6 +661,7 @@ impl Fork {
             match verify_transaction(
                 &overlay,
                 verifying_block_height,
+                block_target,
                 &unproposed_tx,
                 &mut tree,
                 &mut vks,

+ 14 - 7
src/validator/mod.rs

@@ -62,7 +62,7 @@ pub struct ValidatorConfig {
     /// Currently configured finalization security threshold
     pub finalization_threshold: usize,
     /// Currently configured PoW target
-    pub pow_target: usize,
+    pub pow_target: u32,
     /// Optional fixed difficulty, for testing purposes
     pub pow_fixed_difficulty: Option<BigUint>,
     /// Genesis block
@@ -97,12 +97,12 @@ impl Validator {
         let overlay = BlockchainOverlay::new(&blockchain)?;
 
         // Deploy native wasm contracts
-        deploy_native_contracts(&overlay).await?;
+        deploy_native_contracts(&overlay, config.pow_target).await?;
 
         // Add genesis block if blockchain is empty
         if blockchain.genesis().is_err() {
             info!(target: "validator::new", "Appending genesis block");
-            verify_genesis_block(&overlay, &config.genesis_block).await?;
+            verify_genesis_block(&overlay, &config.genesis_block, config.pow_target).await?;
         };
 
         // Write the changes to the actual chain db
@@ -151,6 +151,7 @@ impl Validator {
         let verify_result = verify_transaction(
             &fork.overlay,
             next_block_height,
+            self.consensus.module.read().await.target,
             tx,
             &mut MerkleTree::new(1),
             &mut vks,
@@ -198,6 +199,7 @@ impl Validator {
             let verify_result = verify_transactions(
                 &fork_clone.overlay,
                 next_block_height,
+                self.consensus.module.read().await.target,
                 &tx_vec,
                 &mut MerkleTree::new(1),
                 self.verify_fees,
@@ -271,6 +273,7 @@ impl Validator {
                 let verify_result = verify_transactions(
                     &fork_clone.overlay,
                     next_block_height,
+                    self.consensus.module.read().await.target,
                     &tx_vec,
                     &mut MerkleTree::new(1),
                     self.verify_fees,
@@ -428,7 +431,7 @@ impl Validator {
         // Validate and insert each block
         for (index, block) in blocks.iter().enumerate() {
             // Verify block
-            match verify_checkpoint_block(&overlay, block, &headers[index]).await {
+            match verify_checkpoint_block(&overlay, block, &headers[index], module.target).await {
                 Ok(()) => { /* Do nothing */ }
                 // Skip already existing block
                 Err(Error::BlockAlreadyExists(_)) => continue,
@@ -585,6 +588,7 @@ impl Validator {
         &self,
         txs: &[Transaction],
         verifying_block_height: u32,
+        block_target: u32,
         write: bool,
         verify_fees: bool,
     ) -> Result<u64> {
@@ -595,6 +599,7 @@ impl Validator {
         let verify_result = verify_transactions(
             &overlay,
             verifying_block_height,
+            block_target,
             txs,
             &mut MerkleTree::new(1),
             verify_fees,
@@ -631,6 +636,7 @@ impl Validator {
         &self,
         tx: &Transaction,
         verifying_block_height: u32,
+        block_target: u32,
         write: bool,
     ) -> Result<()> {
         debug!(target: "validator::add_test_producer_transaction", "Instantiating BlockchainOverlay");
@@ -641,6 +647,7 @@ impl Validator {
         if let Err(e) = verify_producer_transaction(
             &overlay,
             verifying_block_height,
+            block_target,
             tx,
             &mut MerkleTree::new(1),
         )
@@ -674,7 +681,7 @@ impl Validator {
     /// Be careful as this will try to load everything in memory.
     pub async fn validate_blockchain(
         &self,
-        pow_target: usize,
+        pow_target: u32,
         pow_fixed_difficulty: Option<BigUint>,
     ) -> Result<()> {
         let blocks = self.blockchain.get_all()?;
@@ -696,10 +703,10 @@ impl Validator {
         let mut module = PoWModule::new(blockchain.clone(), pow_target, pow_fixed_difficulty)?;
 
         // Deploy native wasm contracts
-        deploy_native_contracts(&overlay).await?;
+        deploy_native_contracts(&overlay, pow_target).await?;
 
         // Validate genesis block
-        verify_genesis_block(&overlay, previous).await?;
+        verify_genesis_block(&overlay, previous, pow_target).await?;
 
         // Validate and insert each block
         for block in &blocks[1..] {

+ 3 - 3
src/validator/pow.rs

@@ -75,7 +75,7 @@ const BLOCK_FUTURE_TIME_LIMIT: Timestamp = Timestamp::from_u64(60 * 60 * 2);
 #[derive(Clone)]
 pub struct PoWModule {
     /// Target block time, in seconds
-    pub target: usize,
+    pub target: u32,
     /// Optional fixed difficulty
     pub fixed_difficulty: Option<BigUint>,
     /// Latest block timestamps ringbuffer
@@ -92,7 +92,7 @@ pub struct PoWModule {
 impl PoWModule {
     pub fn new(
         blockchain: Blockchain,
-        target: usize,
+        target: u32,
         fixed_difficulty: Option<BigUint>,
     ) -> Result<Self> {
         // Retrieving last BUF_SIZE difficulties from blockchain to build the buffers
@@ -415,7 +415,7 @@ mod tests {
     use super::PoWModule;
 
     const DEFAULT_TEST_THREADS: usize = 2;
-    const DEFAULT_TEST_DIFFICULTY_TARGET: usize = 120;
+    const DEFAULT_TEST_DIFFICULTY_TARGET: u32 = 120;
 
     #[test]
     fn test_wide_difficulty() -> Result<()> {

+ 5 - 1
src/validator/utils.rs

@@ -41,7 +41,10 @@ use crate::{
 /// touch anything, or just potentially update the db schemas or whatever
 /// is necessary. This logic should be handled in the init function of
 /// the actual contract, so make sure the native contracts handle this well.
-pub async fn deploy_native_contracts(overlay: &BlockchainOverlayPtr) -> Result<()> {
+pub async fn deploy_native_contracts(
+    overlay: &BlockchainOverlayPtr,
+    block_target: u32,
+) -> Result<()> {
     info!(target: "validator::utils::deploy_native_contracts", "Deploying native WASM contracts");
 
     // The Money contract uses an empty payload to deploy itself.
@@ -89,6 +92,7 @@ pub async fn deploy_native_contracts(overlay: &BlockchainOverlayPtr) -> Result<(
             overlay.clone(),
             nc.1,
             verifying_block_height,
+            block_target,
             TransactionHash::none(),
             call_idx as u8,
         )?;

+ 40 - 8
src/validator/verification.rs

@@ -51,7 +51,11 @@ use crate::{
 };
 
 /// Verify given genesis [`BlockInfo`], and apply it to the provided overlay.
-pub async fn verify_genesis_block(overlay: &BlockchainOverlayPtr, block: &BlockInfo) -> Result<()> {
+pub async fn verify_genesis_block(
+    overlay: &BlockchainOverlayPtr,
+    block: &BlockInfo,
+    block_target: u32,
+) -> Result<()> {
     let block_hash = block.hash().as_string();
     debug!(target: "validator::verification::verify_genesis_block", "Validating genesis block {}", block_hash);
 
@@ -85,7 +89,9 @@ pub async fn verify_genesis_block(overlay: &BlockchainOverlayPtr, block: &BlockI
     // Verify transactions, exluding producer(last) one
     let mut tree = MerkleTree::new(1);
     let txs = &block.txs[..block.txs.len() - 1];
-    if let Err(e) = verify_transactions(overlay, block.header.height, txs, &mut tree, false).await {
+    if let Err(e) =
+        verify_transactions(overlay, block.header.height, block_target, txs, &mut tree, false).await
+    {
         warn!(
             target: "validator::verification::verify_genesis_block",
             "[VALIDATOR] Erroneous transactions found in set",
@@ -147,7 +153,7 @@ pub fn validate_block(block: &BlockInfo, previous: &BlockInfo, module: &PoWModul
 /// Be careful as this will try to load everything in memory.
 pub fn validate_blockchain(
     blockchain: &Blockchain,
-    pow_target: usize,
+    pow_target: u32,
     pow_fixed_difficulty: Option<BigUint>,
 ) -> Result<()> {
     // Generate a PoW module
@@ -191,7 +197,8 @@ pub async fn verify_block(
     // Verify transactions, exluding producer(last) one
     let mut tree = MerkleTree::new(1);
     let txs = &block.txs[..block.txs.len() - 1];
-    let e = verify_transactions(overlay, block.header.height, txs, &mut tree, false).await;
+    let e = verify_transactions(overlay, block.header.height, module.target, txs, &mut tree, false)
+        .await;
     if let Err(e) = e {
         warn!(
             target: "validator::verification::verify_block",
@@ -205,6 +212,7 @@ pub async fn verify_block(
     let public_key = verify_producer_transaction(
         overlay,
         block.header.height,
+        module.target,
         block.txs.last().unwrap(),
         &mut tree,
     )
@@ -231,6 +239,7 @@ pub async fn verify_checkpoint_block(
     overlay: &BlockchainOverlayPtr,
     block: &BlockInfo,
     header: &HeaderHash,
+    block_target: u32,
 ) -> Result<()> {
     let block_hash = block.hash();
     debug!(target: "validator::verification::verify_checkpoint_block", "Validating block {}", block_hash);
@@ -254,7 +263,7 @@ pub async fn verify_checkpoint_block(
     // Apply transactions, exluding producer(last) one
     let mut tree = MerkleTree::new(1);
     let txs = &block.txs[..block.txs.len() - 1];
-    let e = apply_transactions(overlay, block.header.height, txs, &mut tree).await;
+    let e = apply_transactions(overlay, block.header.height, block_target, txs, &mut tree).await;
     if let Err(e) = e {
         warn!(
             target: "validator::verification::verify_checkpoint_block",
@@ -268,6 +277,7 @@ pub async fn verify_checkpoint_block(
     let public_key = apply_producer_transaction(
         overlay,
         block.header.height,
+        block_target,
         block.txs.last().unwrap(),
         &mut tree,
     )
@@ -306,6 +316,7 @@ pub fn verify_producer_signature(block: &BlockInfo, public_key: &PublicKey) -> R
 pub async fn verify_producer_transaction(
     overlay: &BlockchainOverlayPtr,
     verifying_block_height: u32,
+    block_target: u32,
     tx: &Transaction,
     tree: &mut MerkleTree,
 ) -> Result<PublicKey> {
@@ -349,6 +360,7 @@ pub async fn verify_producer_transaction(
         overlay.clone(),
         call.data.contract_id,
         verifying_block_height,
+        block_target,
         tx_hash,
         // Call index in producer tx is 0
         0,
@@ -441,6 +453,7 @@ pub async fn verify_producer_transaction(
 async fn apply_producer_transaction(
     overlay: &BlockchainOverlayPtr,
     verifying_block_height: u32,
+    block_target: u32,
     tx: &Transaction,
     tree: &mut MerkleTree,
 ) -> Result<PublicKey> {
@@ -467,6 +480,7 @@ async fn apply_producer_transaction(
         overlay.clone(),
         call.data.contract_id,
         verifying_block_height,
+        block_target,
         tx_hash,
         // Call index in producer tx is 0
         0,
@@ -515,6 +529,7 @@ async fn apply_producer_transaction(
 pub async fn verify_transaction(
     overlay: &BlockchainOverlayPtr,
     verifying_block_height: u32,
+    block_target: u32,
     tx: &Transaction,
     tree: &mut MerkleTree,
     verifying_keys: &mut HashMap<[u8; 32], HashMap<String, VerifyingKey>>,
@@ -591,6 +606,7 @@ pub async fn verify_transaction(
             overlay.clone(),
             call.data.contract_id,
             verifying_block_height,
+            block_target,
             tx_hash,
             idx as u8,
         )?;
@@ -666,6 +682,7 @@ pub async fn verify_transaction(
                 overlay.clone(),
                 deploy_cid,
                 verifying_block_height,
+                block_target,
                 tx_hash,
                 idx as u8,
             )?;
@@ -760,6 +777,7 @@ pub async fn verify_transaction(
 async fn apply_transaction(
     overlay: &BlockchainOverlayPtr,
     verifying_block_height: u32,
+    block_target: u32,
     tx: &Transaction,
     tree: &mut MerkleTree,
 ) -> Result<()> {
@@ -781,6 +799,7 @@ async fn apply_transaction(
             overlay.clone(),
             call.data.contract_id,
             verifying_block_height,
+            block_target,
             tx_hash,
             idx as u8,
         )?;
@@ -811,6 +830,7 @@ async fn apply_transaction(
                 overlay.clone(),
                 deploy_cid,
                 verifying_block_height,
+                block_target,
                 tx_hash,
                 idx as u8,
             )?;
@@ -833,6 +853,7 @@ async fn apply_transaction(
 pub async fn verify_transactions(
     overlay: &BlockchainOverlayPtr,
     verifying_block_height: u32,
+    block_target: u32,
     txs: &[Transaction],
     tree: &mut MerkleTree,
     verify_fees: bool,
@@ -861,8 +882,16 @@ pub async fn verify_transactions(
     // Iterate over transactions and attempt to verify them
     for tx in txs {
         overlay.lock().unwrap().checkpoint();
-        match verify_transaction(overlay, verifying_block_height, tx, tree, &mut vks, verify_fees)
-            .await
+        match verify_transaction(
+            overlay,
+            verifying_block_height,
+            block_target,
+            tx,
+            tree,
+            &mut vks,
+            verify_fees,
+        )
+        .await
         {
             Ok((gas, _)) => gas_used += gas,
             Err(e) => {
@@ -886,6 +915,7 @@ pub async fn verify_transactions(
 async fn apply_transactions(
     overlay: &BlockchainOverlayPtr,
     verifying_block_height: u32,
+    block_target: u32,
     txs: &[Transaction],
     tree: &mut MerkleTree,
 ) -> Result<()> {
@@ -900,7 +930,9 @@ async fn apply_transactions(
     // Iterate over transactions and attempt to apply them
     for tx in txs {
         overlay.lock().unwrap().checkpoint();
-        if let Err(e) = apply_transaction(overlay, verifying_block_height, tx, tree).await {
+        if let Err(e) =
+            apply_transaction(overlay, verifying_block_height, block_target, tx, tree).await
+        {
             warn!(target: "validator::verification::apply_transactions", "Transaction apply failed: {}", e);
             erroneous_txs.push(tx.clone());
             overlay.lock().unwrap().revert_to_checkpoint()?;