fix: aura don't add SystemTime::now()
(#10720)
This commit does the following: - Prevent overflow in `verify_timestamp()` by not adding `now` to found faulty timestamp - Use explicit `CheckedSystemTime::checked_add` to prevent potential consensus issues because SystemTime is platform depedent - remove `#[cfg(not(time_checked_add))]` conditional compilation
This commit is contained in:
parent
e1333ea1e9
commit
78d0a8696f
@ -22,7 +22,7 @@ use std::iter::FromIterator;
|
|||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
use std::sync::atomic::{AtomicUsize, AtomicBool, Ordering as AtomicOrdering};
|
use std::sync::atomic::{AtomicUsize, AtomicBool, Ordering as AtomicOrdering};
|
||||||
use std::sync::{Weak, Arc};
|
use std::sync::{Weak, Arc};
|
||||||
use std::time::{UNIX_EPOCH, SystemTime, Duration};
|
use std::time::{UNIX_EPOCH, Duration};
|
||||||
|
|
||||||
use block::*;
|
use block::*;
|
||||||
use client::EngineClient;
|
use client::EngineClient;
|
||||||
@ -42,14 +42,12 @@ use itertools::{self, Itertools};
|
|||||||
use rlp::{encode, Decodable, DecoderError, Encodable, RlpStream, Rlp};
|
use rlp::{encode, Decodable, DecoderError, Encodable, RlpStream, Rlp};
|
||||||
use ethereum_types::{H256, H520, Address, U128, U256};
|
use ethereum_types::{H256, H520, Address, U128, U256};
|
||||||
use parking_lot::{Mutex, RwLock};
|
use parking_lot::{Mutex, RwLock};
|
||||||
|
use time_utils::CheckedSystemTime;
|
||||||
use types::BlockNumber;
|
use types::BlockNumber;
|
||||||
use types::header::{Header, ExtendedHeader};
|
use types::header::{Header, ExtendedHeader};
|
||||||
use types::ancestry_action::AncestryAction;
|
use types::ancestry_action::AncestryAction;
|
||||||
use unexpected::{Mismatch, OutOfBounds};
|
use unexpected::{Mismatch, OutOfBounds};
|
||||||
|
|
||||||
#[cfg(not(time_checked_add))]
|
|
||||||
use time_utils::CheckedSystemTime;
|
|
||||||
|
|
||||||
mod finality;
|
mod finality;
|
||||||
|
|
||||||
/// `AuthorityRound` params.
|
/// `AuthorityRound` params.
|
||||||
@ -584,10 +582,10 @@ fn verify_timestamp(step: &Step, header_step: u64) -> Result<(), BlockError> {
|
|||||||
// Returning it further won't recover the sync process.
|
// Returning it further won't recover the sync process.
|
||||||
trace!(target: "engine", "verify_timestamp: block too early");
|
trace!(target: "engine", "verify_timestamp: block too early");
|
||||||
|
|
||||||
let now = SystemTime::now();
|
let found = CheckedSystemTime::checked_add(UNIX_EPOCH, Duration::from_secs(oob.found))
|
||||||
let found = now.checked_add(Duration::from_secs(oob.found)).ok_or(BlockError::TimestampOverflow)?;
|
.ok_or(BlockError::TimestampOverflow)?;
|
||||||
let max = oob.max.and_then(|m| now.checked_add(Duration::from_secs(m)));
|
let max = oob.max.and_then(|m| CheckedSystemTime::checked_add(UNIX_EPOCH, Duration::from_secs(m)));
|
||||||
let min = oob.min.and_then(|m| now.checked_add(Duration::from_secs(m)));
|
let min = oob.min.and_then(|m| CheckedSystemTime::checked_add(UNIX_EPOCH, Duration::from_secs(m)));
|
||||||
|
|
||||||
let new_oob = OutOfBounds { min, max, found };
|
let new_oob = OutOfBounds { min, max, found };
|
||||||
|
|
||||||
|
@ -24,13 +24,11 @@ use engines::clique::{VoteType, DIFF_INTURN, DIFF_NOTURN, NULL_AUTHOR, SIGNING_D
|
|||||||
use error::{Error, BlockError};
|
use error::{Error, BlockError};
|
||||||
use ethereum_types::{Address, H64};
|
use ethereum_types::{Address, H64};
|
||||||
use rand::Rng;
|
use rand::Rng;
|
||||||
|
use time_utils::CheckedSystemTime;
|
||||||
use types::BlockNumber;
|
use types::BlockNumber;
|
||||||
use types::header::Header;
|
use types::header::Header;
|
||||||
use unexpected::Mismatch;
|
use unexpected::Mismatch;
|
||||||
|
|
||||||
#[cfg(not(feature = "time_checked_add"))]
|
|
||||||
use time_utils::CheckedSystemTime;
|
|
||||||
|
|
||||||
/// Type that keeps track of the state for a given vote
|
/// Type that keeps track of the state for a given vote
|
||||||
// Votes that go against the proposal aren't counted since it's equivalent to not voting
|
// Votes that go against the proposal aren't counted since it's equivalent to not voting
|
||||||
#[derive(Copy, Clone, Debug, PartialEq, PartialOrd)]
|
#[derive(Copy, Clone, Debug, PartialEq, PartialOrd)]
|
||||||
@ -268,7 +266,7 @@ impl CliqueBlockState {
|
|||||||
// This is a quite bad API because we must mutate both variables even when already `inturn` fails
|
// This is a quite bad API because we must mutate both variables even when already `inturn` fails
|
||||||
// That's why we can't return early and must have the `if-else` in the end
|
// That's why we can't return early and must have the `if-else` in the end
|
||||||
pub fn calc_next_timestamp(&mut self, timestamp: u64, period: u64) -> Result<(), Error> {
|
pub fn calc_next_timestamp(&mut self, timestamp: u64, period: u64) -> Result<(), Error> {
|
||||||
let inturn = UNIX_EPOCH.checked_add(Duration::from_secs(timestamp.saturating_add(period)));
|
let inturn = CheckedSystemTime::checked_add(UNIX_EPOCH, Duration::from_secs(timestamp.saturating_add(period)));
|
||||||
|
|
||||||
self.next_timestamp_inturn = inturn;
|
self.next_timestamp_inturn = inturn;
|
||||||
|
|
||||||
|
@ -81,12 +81,10 @@ use parking_lot::RwLock;
|
|||||||
use rand::Rng;
|
use rand::Rng;
|
||||||
use super::signer::EngineSigner;
|
use super::signer::EngineSigner;
|
||||||
use unexpected::{Mismatch, OutOfBounds};
|
use unexpected::{Mismatch, OutOfBounds};
|
||||||
|
use time_utils::CheckedSystemTime;
|
||||||
use types::BlockNumber;
|
use types::BlockNumber;
|
||||||
use types::header::{ExtendedHeader, Header};
|
use types::header::{ExtendedHeader, Header};
|
||||||
|
|
||||||
#[cfg(not(feature = "time_checked_add"))]
|
|
||||||
use time_utils::CheckedSystemTime;
|
|
||||||
|
|
||||||
use self::block_state::CliqueBlockState;
|
use self::block_state::CliqueBlockState;
|
||||||
use self::params::CliqueParams;
|
use self::params::CliqueParams;
|
||||||
|
|
||||||
@ -545,7 +543,7 @@ impl Engine<EthereumMachine> for Clique {
|
|||||||
|
|
||||||
// Don't waste time checking blocks from the future
|
// Don't waste time checking blocks from the future
|
||||||
{
|
{
|
||||||
let limit = SystemTime::now().checked_add(Duration::from_secs(self.period))
|
let limit = CheckedSystemTime::checked_add(SystemTime::now(), Duration::from_secs(self.period))
|
||||||
.ok_or(BlockError::TimestampOverflow)?;
|
.ok_or(BlockError::TimestampOverflow)?;
|
||||||
|
|
||||||
// This should succeed under the contraints that the system clock works
|
// This should succeed under the contraints that the system clock works
|
||||||
@ -555,7 +553,7 @@ impl Engine<EthereumMachine> for Clique {
|
|||||||
|
|
||||||
let hdr = Duration::from_secs(header.timestamp());
|
let hdr = Duration::from_secs(header.timestamp());
|
||||||
if hdr > limit_as_dur {
|
if hdr > limit_as_dur {
|
||||||
let found = UNIX_EPOCH.checked_add(hdr).ok_or(BlockError::TimestampOverflow)?;
|
let found = CheckedSystemTime::checked_add(UNIX_EPOCH, hdr).ok_or(BlockError::TimestampOverflow)?;
|
||||||
|
|
||||||
Err(BlockError::TemporarilyInvalid(OutOfBounds {
|
Err(BlockError::TemporarilyInvalid(OutOfBounds {
|
||||||
min: None,
|
min: None,
|
||||||
@ -666,8 +664,8 @@ impl Engine<EthereumMachine> for Clique {
|
|||||||
// Ensure that the block's timestamp isn't too close to it's parent
|
// Ensure that the block's timestamp isn't too close to it's parent
|
||||||
let limit = parent.timestamp().saturating_add(self.period);
|
let limit = parent.timestamp().saturating_add(self.period);
|
||||||
if limit > header.timestamp() {
|
if limit > header.timestamp() {
|
||||||
let max = UNIX_EPOCH.checked_add(Duration::from_secs(header.timestamp()));
|
let max = CheckedSystemTime::checked_add(UNIX_EPOCH, Duration::from_secs(header.timestamp()));
|
||||||
let found = UNIX_EPOCH.checked_add(Duration::from_secs(limit))
|
let found = CheckedSystemTime::checked_add(UNIX_EPOCH, Duration::from_secs(limit))
|
||||||
.ok_or(BlockError::TimestampOverflow)?;
|
.ok_or(BlockError::TimestampOverflow)?;
|
||||||
|
|
||||||
Err(BlockError::InvalidTimestamp(OutOfBounds {
|
Err(BlockError::InvalidTimestamp(OutOfBounds {
|
||||||
|
@ -15,7 +15,6 @@
|
|||||||
// along with Parity Ethereum. If not, see <http://www.gnu.org/licenses/>.
|
// along with Parity Ethereum. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
#![warn(missing_docs, unused_extern_crates)]
|
#![warn(missing_docs, unused_extern_crates)]
|
||||||
#![cfg_attr(feature = "time_checked_add", feature(time_checked_add))]
|
|
||||||
|
|
||||||
//! Ethcore library
|
//! Ethcore library
|
||||||
//!
|
//!
|
||||||
@ -103,6 +102,7 @@ extern crate parity_util_mem as malloc_size_of;
|
|||||||
extern crate rustc_hex;
|
extern crate rustc_hex;
|
||||||
extern crate serde;
|
extern crate serde;
|
||||||
extern crate stats;
|
extern crate stats;
|
||||||
|
extern crate time_utils;
|
||||||
extern crate triehash_ethereum as triehash;
|
extern crate triehash_ethereum as triehash;
|
||||||
extern crate unexpected;
|
extern crate unexpected;
|
||||||
extern crate using_queue;
|
extern crate using_queue;
|
||||||
@ -153,9 +153,6 @@ extern crate fetch;
|
|||||||
#[cfg(all(test, feature = "price-info"))]
|
#[cfg(all(test, feature = "price-info"))]
|
||||||
extern crate parity_runtime;
|
extern crate parity_runtime;
|
||||||
|
|
||||||
#[cfg(not(time_checked_add))]
|
|
||||||
extern crate time_utils;
|
|
||||||
|
|
||||||
pub mod block;
|
pub mod block;
|
||||||
pub mod builtin;
|
pub mod builtin;
|
||||||
pub mod client;
|
pub mod client;
|
||||||
|
@ -40,7 +40,6 @@ use types::{BlockNumber, header::Header};
|
|||||||
use types::transaction::SignedTransaction;
|
use types::transaction::SignedTransaction;
|
||||||
use verification::queue::kind::blocks::Unverified;
|
use verification::queue::kind::blocks::Unverified;
|
||||||
|
|
||||||
#[cfg(not(time_checked_add))]
|
|
||||||
use time_utils::CheckedSystemTime;
|
use time_utils::CheckedSystemTime;
|
||||||
|
|
||||||
/// Preprocessed block data gathered in `verify_block_unordered` call
|
/// Preprocessed block data gathered in `verify_block_unordered` call
|
||||||
@ -303,7 +302,7 @@ pub fn verify_header_params(header: &Header, engine: &dyn EthEngine, is_full: bo
|
|||||||
// this will resist overflow until `year 2037`
|
// this will resist overflow until `year 2037`
|
||||||
let max_time = SystemTime::now() + ACCEPTABLE_DRIFT;
|
let max_time = SystemTime::now() + ACCEPTABLE_DRIFT;
|
||||||
let invalid_threshold = max_time + ACCEPTABLE_DRIFT * 9;
|
let invalid_threshold = max_time + ACCEPTABLE_DRIFT * 9;
|
||||||
let timestamp = UNIX_EPOCH.checked_add(Duration::from_secs(header.timestamp()))
|
let timestamp = CheckedSystemTime::checked_add(UNIX_EPOCH, Duration::from_secs(header.timestamp()))
|
||||||
.ok_or(BlockError::TimestampOverflow)?;
|
.ok_or(BlockError::TimestampOverflow)?;
|
||||||
|
|
||||||
if timestamp > invalid_threshold {
|
if timestamp > invalid_threshold {
|
||||||
@ -327,9 +326,9 @@ fn verify_parent(header: &Header, parent: &Header, engine: &dyn EthEngine) -> Re
|
|||||||
|
|
||||||
if !engine.is_timestamp_valid(header.timestamp(), parent.timestamp()) {
|
if !engine.is_timestamp_valid(header.timestamp(), parent.timestamp()) {
|
||||||
let now = SystemTime::now();
|
let now = SystemTime::now();
|
||||||
let min = now.checked_add(Duration::from_secs(parent.timestamp().saturating_add(1)))
|
let min = CheckedSystemTime::checked_add(now, Duration::from_secs(parent.timestamp().saturating_add(1)))
|
||||||
.ok_or(BlockError::TimestampOverflow)?;
|
.ok_or(BlockError::TimestampOverflow)?;
|
||||||
let found = now.checked_add(Duration::from_secs(header.timestamp()))
|
let found = CheckedSystemTime::checked_add(now, Duration::from_secs(header.timestamp()))
|
||||||
.ok_or(BlockError::TimestampOverflow)?;
|
.ok_or(BlockError::TimestampOverflow)?;
|
||||||
return Err(From::from(BlockError::InvalidTimestamp(OutOfBounds { max: None, min: Some(min), found }.into())))
|
return Err(From::from(BlockError::InvalidTimestamp(OutOfBounds { max: None, min: Some(min), found }.into())))
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user