Skip to content
This repository has been archived by the owner on Sep 13, 2022. It is now read-only.

Commit

Permalink
fix(consensus): Add timestamp checking (#377)
Browse files Browse the repository at this point in the history
* fix(consensus): Add timestamp checking

* add test

* fix lint

* fix unit

* check previous block

* fix lint

* fix sync

* lint

* fix sync

* Update logic
  • Loading branch information
yejiayu authored Aug 4, 2020
1 parent 19859b3 commit 382ede9
Show file tree
Hide file tree
Showing 3 changed files with 58 additions and 9 deletions.
55 changes: 46 additions & 9 deletions core/consensus/src/engine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use std::collections::{HashMap, HashSet};
use std::convert::TryFrom;
use std::error::Error;
use std::sync::Arc;
use std::time::{Duration, Instant, SystemTime, UNIX_EPOCH};
use std::time::{Duration, Instant};

use async_trait::async_trait;
use futures::lock::Mutex;
Expand Down Expand Up @@ -32,7 +32,7 @@ use crate::message::{
END_GOSSIP_SIGNED_VOTE,
};
use crate::status::StatusAgent;
use crate::util::{check_list_roots, digest_signed_transactions, OverlordCrypto};
use crate::util::{check_list_roots, digest_signed_transactions, time_now, OverlordCrypto};
use crate::wal::SignedTxsWAL;
use crate::ConsensusError;

Expand Down Expand Up @@ -175,6 +175,8 @@ impl<Adapter: ConsensusAdapter + 'static> Engine<FixedPill> for ConsensusEngine<
// If the block is proposed by self, it does not need to check. Get full signed
// transactions directly.
if !exemption {
let current_timestamp = time_now();

self.adapter
.verify_block_header(ctx.clone(), block.inner.block.clone())
.await
Expand All @@ -194,6 +196,15 @@ impl<Adapter: ConsensusAdapter + 'static> Engine<FixedPill> for ConsensusEngine<
.get_block_by_height(ctx.clone(), block.inner.block.header.height - 1)
.await?;

// verify block timestamp.
if !validate_timestamp(
current_timestamp,
block.inner.block.header.timestamp,
previous_block.header.timestamp,
) {
return Err(ProtocolError::from(ConsensusError::InvalidTimestamp).into());
}

self.adapter
.verify_proof(
ctx.clone(),
Expand Down Expand Up @@ -800,17 +811,43 @@ fn covert_to_overlord_authority(validators: &[Validator]) -> Vec<Node> {
authority
}

fn time_now() -> u64 {
SystemTime::now()
.duration_since(UNIX_EPOCH)
.unwrap()
.as_millis() as u64
}

async fn sync_txs<CA: ConsensusAdapter>(
ctx: Context,
adapter: Arc<CA>,
propose_hashes: Vec<Hash>,
) -> ProtocolResult<()> {
adapter.sync_txs(ctx, propose_hashes).await
}

fn validate_timestamp(
current_timestamp: u64,
proposal_timestamp: u64,
previous_timestamp: u64,
) -> bool {
if proposal_timestamp < previous_timestamp {
return false;
}

if proposal_timestamp > current_timestamp {
return false;
}

true
}

#[cfg(test)]
mod tests {
use super::validate_timestamp;

#[test]
fn test_validate_timestamp() {
// current 10, proposal 9, previous 8. true
assert_eq!(validate_timestamp(10, 9, 8), true);

// current 10, proposal 11, previous 8. true
assert_eq!(validate_timestamp(10, 11, 8), false);

// current 10, proposal 9, previous 11. true
assert_eq!(validate_timestamp(10, 9, 11), false);
}
}
4 changes: 4 additions & 0 deletions core/consensus/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,10 @@ pub enum ConsensusError {
#[display(fmt = "Consensus missed pill cooresponding {:?}", _0)]
MissingPill(Hash),

/// Invalid timestamp
#[display(fmt = "Consensus invalid timestamp")]
InvalidTimestamp,

/// Consensus missed the block header.
#[display(fmt = "Consensus missed block header of {} block", _0)]
MissingBlockHeader(u64),
Expand Down
8 changes: 8 additions & 0 deletions core/consensus/src/util.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use std::collections::HashMap;
use std::convert::TryFrom;
use std::error::Error;
use std::time::{SystemTime, UNIX_EPOCH};

use bytes::buf::BufMut;
use bytes::BytesMut;
Expand All @@ -17,6 +18,13 @@ use protocol::traits::Context;
use protocol::types::{Address, Hash, Hex, MerkleRoot, SignedTransaction};
use protocol::{Bytes, ProtocolError, ProtocolResult};

pub fn time_now() -> u64 {
SystemTime::now()
.duration_since(UNIX_EPOCH)
.unwrap()
.as_millis() as u64
}

pub struct OverlordCrypto {
private_key: BlsPrivateKey,
addr_pubkey: RwLock<HashMap<Bytes, BlsPublicKey>>,
Expand Down

0 comments on commit 382ede9

Please sign in to comment.