diff --git a/src/blockchain/block_store.rs b/src/blockchain/block_store.rs
index 2e0907f94..b21f4957a 100644
--- a/src/blockchain/block_store.rs
+++ b/src/blockchain/block_store.rs
@@ -16,19 +16,15 @@
* along with this program. If not, see .
*/
-use std::io::Cursor;
-
use darkfi_sdk::{
blockchain::Slot,
- crypto::{ecvrf::VrfProof, pasta_prelude::PrimeField, schnorr::Signature},
+ crypto::schnorr::Signature,
pasta::{group::ff::FromUniformBytes, pallas},
};
#[cfg(feature = "async-serial")]
use darkfi_serial::async_trait;
-use darkfi_serial::{
- deserialize, serialize, Decodable, Encodable, SerialDecodable, SerialEncodable,
-};
+use darkfi_serial::{deserialize, serialize, Encodable, SerialDecodable, SerialEncodable};
use crate::{tx::Transaction, Error, Result};
@@ -147,46 +143,6 @@ impl BlockInfo {
Ok(())
}
-
- /// Compute block's rank, assuming the block is valid.
- pub fn rank(&self) -> Result {
- // Genesis block has rank 0
- if self.header.height == 0 {
- return Ok(0)
- }
-
- // Extract VRF proof from the producer transaction
- let tx = self.txs.last().unwrap();
- let data = &tx.calls[0].data;
- let position = match self.header.version {
- // PoW uses MoneyPoWRewardParamsV1
- 1 => 563,
- // PoS uses ConsensusProposalParamsV1
- 2 => 490,
- _ => return Err(Error::BlockVersionIsInvalid(self.header.version)),
- };
- let mut decoder = Cursor::new(&data);
- decoder.set_position(position);
- let vrf_proof: VrfProof = Decodable::decode(&mut decoder)?;
-
- // Compute nonce u64
- let mut nonce = [0u8; 8];
- nonce.copy_from_slice(&self.header.nonce.to_repr()[..8]);
- let nonce = u64::from_be_bytes(nonce);
-
- // Compute VRF u64
- let mut vrf = [0u8; 64];
- vrf[..blake3::OUT_LEN].copy_from_slice(vrf_proof.hash_output().as_bytes());
- let vrf_pallas = pallas::Base::from_uniform_bytes(&vrf);
- let mut vrf = [0u8; 8];
- vrf.copy_from_slice(&vrf_pallas.to_repr()[..8]);
- let vrf = u64::from_be_bytes(vrf);
-
- // Finally, compute the rank
- let rank = nonce % vrf;
-
- Ok(rank)
- }
}
/// [`Block`] sled tree
diff --git a/src/validator/consensus.rs b/src/validator/consensus.rs
index cd4cbf9b2..21180b6fe 100644
--- a/src/validator/consensus.rs
+++ b/src/validator/consensus.rs
@@ -29,7 +29,9 @@ use crate::{
blockchain::{BlockInfo, Blockchain, BlockchainOverlay, BlockchainOverlayPtr, Header},
tx::Transaction,
util::time::{TimeKeeper, Timestamp},
- validator::{pid::slot_pid_output, pow::PoWModule, verify_block, verify_transactions},
+ validator::{
+ pid::slot_pid_output, pow::PoWModule, utils::block_rank, verify_block, verify_transactions,
+ },
Error, Result,
};
@@ -632,7 +634,19 @@ impl Fork {
let mut sum = 0;
let proposals = self.overlay.lock().unwrap().get_blocks_by_hash(&self.proposals)?;
for proposal in &proposals {
- sum += proposal.rank()?;
+ // For block height > 3, retrieve their previous previous block
+ let previous_previous = if proposal.header.height > 3 {
+ let previous = &self
+ .overlay
+ .lock()
+ .unwrap()
+ .get_blocks_by_hash(&[proposal.header.previous])?[0];
+ self.overlay.lock().unwrap().get_blocks_by_hash(&[previous.header.previous])?[0]
+ .clone()
+ } else {
+ proposal.clone()
+ };
+ sum += block_rank(proposal, &previous_previous)?;
}
// Use fork(proposals) length as a multiplier to compute the actual fork rank
diff --git a/src/validator/utils.rs b/src/validator/utils.rs
index a7360c0fb..6478c3226 100644
--- a/src/validator/utils.rs
+++ b/src/validator/utils.rs
@@ -16,12 +16,23 @@
* along with this program. If not, see .
*/
-use darkfi_sdk::crypto::{PublicKey, CONSENSUS_CONTRACT_ID, DAO_CONTRACT_ID, MONEY_CONTRACT_ID};
-use darkfi_serial::serialize;
+use std::io::Cursor;
+
+use darkfi_sdk::{
+ crypto::{
+ ecvrf::VrfProof, pasta_prelude::PrimeField, PublicKey, CONSENSUS_CONTRACT_ID,
+ DAO_CONTRACT_ID, MONEY_CONTRACT_ID,
+ },
+ pasta::{group::ff::FromUniformBytes, pallas},
+};
+use darkfi_serial::{serialize, Decodable};
use log::info;
use crate::{
- blockchain::BlockchainOverlayPtr, runtime::vm_runtime::Runtime, util::time::TimeKeeper, Result,
+ blockchain::{BlockInfo, BlockchainOverlayPtr},
+ runtime::vm_runtime::Runtime,
+ util::time::TimeKeeper,
+ Error, Result,
};
/// Deploy DarkFi native wasm contracts to provided blockchain overlay.
@@ -86,3 +97,51 @@ pub fn deploy_native_contracts(
Ok(())
}
+
+/// Compute a block's rank, assuming the its valid.
+/// Genesis block has rank 0.
+/// First 2 blocks rank is equal to their nonce, since their previous
+/// previous block producer doesn't exist or have a VRF.
+pub fn block_rank(block: &BlockInfo, previous_previous: &BlockInfo) -> Result {
+ // Genesis block has rank 0
+ if block.header.height == 0 {
+ return Ok(0)
+ }
+
+ // Compute nonce u64
+ let mut nonce = [0u8; 8];
+ nonce.copy_from_slice(&block.header.nonce.to_repr()[..8]);
+ let nonce = u64::from_be_bytes(nonce);
+
+ // First 2 block have rank equal to their nonce
+ if block.header.height < 3 {
+ return Ok(nonce)
+ }
+
+ // Extract VRF proof from the previous previous producer transaction
+ let tx = previous_previous.txs.last().unwrap();
+ let data = &tx.calls[0].data;
+ let position = match previous_previous.header.version {
+ // PoW uses MoneyPoWRewardParamsV1
+ 1 => 563,
+ // PoS uses ConsensusProposalParamsV1
+ 2 => 490,
+ _ => return Err(Error::BlockVersionIsInvalid(previous_previous.header.version)),
+ };
+ let mut decoder = Cursor::new(&data);
+ decoder.set_position(position);
+ let vrf_proof: VrfProof = Decodable::decode(&mut decoder)?;
+
+ // Compute VRF u64
+ let mut vrf = [0u8; 64];
+ vrf[..blake3::OUT_LEN].copy_from_slice(vrf_proof.hash_output().as_bytes());
+ let vrf_pallas = pallas::Base::from_uniform_bytes(&vrf);
+ let mut vrf = [0u8; 8];
+ vrf.copy_from_slice(&vrf_pallas.to_repr()[..8]);
+ let vrf = u64::from_be_bytes(vrf);
+
+ // Finally, compute the rank
+ let rank = nonce % vrf;
+
+ Ok(rank)
+}