validator: check block timestamp is after genesis

This commit is contained in:
skoupidi
2024-06-19 16:23:24 +03:00
parent db2eeafd08
commit 934d8f1a42
6 changed files with 35 additions and 13 deletions

View File

@@ -29,15 +29,17 @@ fn forks() -> Result<()> {
let record1 = HeaderHash::new(blake3::hash(b"Let there be dark!").into());
let record2 = HeaderHash::new(blake3::hash(b"Never skip brain day.").into());
// Create a temporary blockchain and a PoW module
// Create a temporary blockchain
let blockchain = Blockchain::new(&sled::Config::new().temporary(true).open()?)?;
let module = PoWModule::new(blockchain.clone(), 90, None)?;
// Generate and insert default genesis block
let genesis_block = BlockInfo::default();
blockchain.add_block(&genesis_block)?;
let genesis_block_hash = genesis_block.hash();
// Generate the PoW module
let module = PoWModule::new(blockchain.clone(), 90, None)?;
// Create a fork
let fork = Fork::new(blockchain.clone(), module).await?;

View File

@@ -155,7 +155,7 @@ impl Harness {
// Sleep a bit so blocks can be propagated and then
// trigger finalization check to Alice and Bob
sleep(5).await;
sleep(10).await;
self.alice.validator.finalization().await?;
self.bob.validator.finalization().await?;

View File

@@ -105,7 +105,6 @@ async fn sync_blocks_real(ex: Arc<Executor<'static>>) -> Result<()> {
// Verify node synced
let alice = &th.alice.validator;
let charlie = &charlie.validator;
charlie.validate_blockchain(pow_target, pow_fixed_difficulty.clone()).await?;
assert_eq!(alice.blockchain.len(), charlie.blockchain.len());
assert!(charlie.blockchain.headers.is_empty_sync());
// Node must have just the best fork

View File

@@ -112,7 +112,6 @@ async fn sync_forks_real(ex: Arc<Executor<'static>>) -> Result<()> {
}
#[test]
#[ignore]
fn sync_forks() -> Result<()> {
let ex = Arc::new(Executor::new());
let (signal, shutdown) = smol::channel::unbounded::<()>();

View File

@@ -699,15 +699,18 @@ impl Validator {
// Set previous
let mut previous = &blocks[0];
// Create a time keeper and a PoW module to validate each block
let mut module = PoWModule::new(blockchain.clone(), pow_target, pow_fixed_difficulty)?;
// Deploy native wasm contracts
deploy_native_contracts(&overlay, pow_target).await?;
// Validate genesis block
verify_genesis_block(&overlay, previous, pow_target).await?;
// Write the changes to the in memory db
overlay.lock().unwrap().overlay.lock().unwrap().apply()?;
// Create a PoW module to validate each block
let mut module = PoWModule::new(blockchain, pow_target, pow_fixed_difficulty)?;
// Validate and insert each block
for block in &blocks[1..] {
// Verify block
@@ -718,9 +721,7 @@ impl Validator {
};
// Update PoW module
if block.header.version == 1 {
module.append(block.header.timestamp, &module.next_difficulty()?);
}
module.append(block.header.timestamp, &module.next_difficulty()?);
// Use last inserted block as next iteration previous
previous = block;

View File

@@ -74,6 +74,8 @@ const BLOCK_FUTURE_TIME_LIMIT: Timestamp = Timestamp::from_u64(60 * 60 * 2);
/// This struct represents the information required by the PoW algorithm
#[derive(Clone)]
pub struct PoWModule {
/// Genesis block timestamp
pub genesis: Timestamp,
/// Target block time, in seconds
pub target: u32,
/// Optional fixed difficulty
@@ -95,6 +97,9 @@ impl PoWModule {
target: u32,
fixed_difficulty: Option<BigUint>,
) -> Result<Self> {
// Retrieve genesis block timestamp
let genesis = blockchain.genesis_block()?.header.timestamp;
// Retrieving last BUF_SIZE difficulties from blockchain to build the buffers
let mut timestamps = RingBuffer::<Timestamp, BUF_SIZE>::new();
let mut difficulties = RingBuffer::<BigUint, BUF_SIZE>::new();
@@ -111,7 +116,14 @@ impl PoWModule {
assert!(diff > &BigUint::zero());
}
Ok(Self { target, fixed_difficulty, timestamps, difficulties, cummulative_difficulty })
Ok(Self {
genesis,
target,
fixed_difficulty,
timestamps,
difficulties,
cummulative_difficulty,
})
}
/// Compute the next mining difficulty, based on current ring buffers.
@@ -214,6 +226,11 @@ impl PoWModule {
/// Verify provided block timestamp is valid and matches certain criteria
pub fn verify_timestamp_by_median(&self, timestamp: Timestamp) -> bool {
// Check timestamp is after genesis one
if timestamp <= self.genesis {
return false
}
// If not enough blocks, no proper median yet, return true
if self.timestamps.len() < BLOCKCHAIN_TIMESTAMP_CHECK_WINDOW {
return true
@@ -421,6 +438,8 @@ mod tests {
fn test_wide_difficulty() -> Result<()> {
let sled_db = sled::Config::new().temporary(true).open()?;
let blockchain = Blockchain::new(&sled_db)?;
let genesis_block = BlockInfo::default();
blockchain.add_block(&genesis_block)?;
let mut module = PoWModule::new(blockchain, DEFAULT_TEST_DIFFICULTY_TARGET, None)?;
let output = Command::new("./script/research/pow/gen_wide_data.py").output().unwrap();
@@ -454,9 +473,11 @@ mod tests {
// Default setup
let sled_db = sled::Config::new().temporary(true).open()?;
let blockchain = Blockchain::new(&sled_db)?;
let mut genesis_block = BlockInfo::default();
genesis_block.header.timestamp = 0.into();
blockchain.add_block(&genesis_block)?;
let module = PoWModule::new(blockchain, DEFAULT_TEST_DIFFICULTY_TARGET, None)?;
let (_, recvr) = smol::channel::bounded(1);
let genesis_block = BlockInfo::default();
// Mine next block
let mut next_block = BlockInfo::default();