Decouple timestamp open-block-assignment/verification to Engine (#8305)
This commit is contained in:
parent
811d165458
commit
ff0ce70169
@ -267,7 +267,7 @@ impl<'x> OpenBlock<'x> {
|
|||||||
r.block.header.set_parent_hash(parent.hash());
|
r.block.header.set_parent_hash(parent.hash());
|
||||||
r.block.header.set_number(number);
|
r.block.header.set_number(number);
|
||||||
r.block.header.set_author(author);
|
r.block.header.set_author(author);
|
||||||
r.block.header.set_timestamp_now(parent.timestamp());
|
r.block.header.set_timestamp(engine.open_block_header_timestamp(parent.timestamp()));
|
||||||
r.block.header.set_extra_data(extra_data);
|
r.block.header.set_extra_data(extra_data);
|
||||||
|
|
||||||
let gas_floor_target = cmp::max(gas_range_target.0, engine.params().min_gas_limit);
|
let gas_floor_target = cmp::max(gas_range_target.0, engine.params().min_gas_limit);
|
||||||
|
@ -397,7 +397,7 @@ impl PrepareOpenBlock for TestBlockChainClient {
|
|||||||
extra_data,
|
extra_data,
|
||||||
false,
|
false,
|
||||||
).expect("Opening block for tests will not fail.");
|
).expect("Opening block for tests will not fail.");
|
||||||
// TODO [todr] Override timestamp for predictability (set_timestamp_now kind of sucks)
|
// TODO [todr] Override timestamp for predictability
|
||||||
open_block.set_timestamp(*self.latest_block_timestamp.read());
|
open_block.set_timestamp(*self.latest_block_timestamp.read());
|
||||||
open_block
|
open_block
|
||||||
}
|
}
|
||||||
|
@ -50,6 +50,17 @@ impl<M: Machine> Engine<M> for InstantSeal<M>
|
|||||||
fn verify_local_seal(&self, _header: &M::Header) -> Result<(), M::Error> {
|
fn verify_local_seal(&self, _header: &M::Header) -> Result<(), M::Error> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn open_block_header_timestamp(&self, parent_timestamp: u64) -> u64 {
|
||||||
|
use std::{time, cmp};
|
||||||
|
|
||||||
|
let now = time::SystemTime::now().duration_since(time::UNIX_EPOCH).unwrap_or_default();
|
||||||
|
cmp::max(now.as_secs(), parent_timestamp)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_timestamp_valid(&self, header_timestamp: u64, parent_timestamp: u64) -> bool {
|
||||||
|
header_timestamp >= parent_timestamp
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
@ -325,6 +325,19 @@ pub trait Engine<M: Machine>: Sync + Send {
|
|||||||
fn supports_warp(&self) -> bool {
|
fn supports_warp(&self) -> bool {
|
||||||
self.snapshot_components().is_some()
|
self.snapshot_components().is_some()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Return a new open block header timestamp based on the parent timestamp.
|
||||||
|
fn open_block_header_timestamp(&self, parent_timestamp: u64) -> u64 {
|
||||||
|
use std::{time, cmp};
|
||||||
|
|
||||||
|
let now = time::SystemTime::now().duration_since(time::UNIX_EPOCH).unwrap_or_default();
|
||||||
|
cmp::max(now.as_secs() as u64, parent_timestamp + 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Check whether the parent timestamp is valid.
|
||||||
|
fn is_timestamp_valid(&self, header_timestamp: u64, parent_timestamp: u64) -> bool {
|
||||||
|
header_timestamp > parent_timestamp
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Common type alias for an engine coupled with an Ethereum-like state machine.
|
/// Common type alias for an engine coupled with an Ethereum-like state machine.
|
||||||
|
@ -17,7 +17,6 @@
|
|||||||
//! Block header.
|
//! Block header.
|
||||||
|
|
||||||
use std::cmp;
|
use std::cmp;
|
||||||
use std::time::{SystemTime, UNIX_EPOCH};
|
|
||||||
use hash::{KECCAK_NULL_RLP, KECCAK_EMPTY_LIST_RLP, keccak};
|
use hash::{KECCAK_NULL_RLP, KECCAK_EMPTY_LIST_RLP, keccak};
|
||||||
use heapsize::HeapSizeOf;
|
use heapsize::HeapSizeOf;
|
||||||
use ethereum_types::{H256, U256, Address, Bloom};
|
use ethereum_types::{H256, U256, Address, Bloom};
|
||||||
@ -224,12 +223,6 @@ impl Header {
|
|||||||
change_field(&mut self.hash, &mut self.timestamp, a);
|
change_field(&mut self.hash, &mut self.timestamp, a);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set the timestamp field of the header to the current time.
|
|
||||||
pub fn set_timestamp_now(&mut self, but_later_than: u64) {
|
|
||||||
let now = SystemTime::now().duration_since(UNIX_EPOCH).unwrap_or_default();
|
|
||||||
self.set_timestamp(cmp::max(now.as_secs() as u64, but_later_than + 1));
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Set the number field of the header.
|
/// Set the number field of the header.
|
||||||
pub fn set_number(&mut self, a: BlockNumber) {
|
pub fn set_number(&mut self, a: BlockNumber) {
|
||||||
change_field(&mut self.hash, &mut self.number, a);
|
change_field(&mut self.hash, &mut self.number, a);
|
||||||
@ -428,4 +421,3 @@ mod tests {
|
|||||||
assert_eq!(header_rlp, encoded_header);
|
assert_eq!(header_rlp, encoded_header);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -25,7 +25,7 @@ use std::collections::HashSet;
|
|||||||
use std::time::{SystemTime, UNIX_EPOCH};
|
use std::time::{SystemTime, UNIX_EPOCH};
|
||||||
|
|
||||||
use bytes::Bytes;
|
use bytes::Bytes;
|
||||||
use ethereum_types::{H256, U256};
|
use ethereum_types::H256;
|
||||||
use hash::keccak;
|
use hash::keccak;
|
||||||
use heapsize::HeapSizeOf;
|
use heapsize::HeapSizeOf;
|
||||||
use rlp::UntrustedRlp;
|
use rlp::UntrustedRlp;
|
||||||
@ -127,7 +127,7 @@ pub struct FullFamilyParams<'a, C: BlockInfo + CallContract + 'a> {
|
|||||||
/// Phase 3 verification. Check block information against parent and uncles.
|
/// Phase 3 verification. Check block information against parent and uncles.
|
||||||
pub fn verify_block_family<C: BlockInfo + CallContract>(header: &Header, parent: &Header, engine: &EthEngine, do_full: Option<FullFamilyParams<C>>) -> Result<(), Error> {
|
pub fn verify_block_family<C: BlockInfo + CallContract>(header: &Header, parent: &Header, engine: &EthEngine, do_full: Option<FullFamilyParams<C>>) -> Result<(), Error> {
|
||||||
// TODO: verify timestamp
|
// TODO: verify timestamp
|
||||||
verify_parent(&header, &parent, engine.params().gas_limit_bound_divisor)?;
|
verify_parent(&header, &parent, engine)?;
|
||||||
engine.verify_block_family(&header, &parent)?;
|
engine.verify_block_family(&header, &parent)?;
|
||||||
|
|
||||||
let params = match do_full {
|
let params = match do_full {
|
||||||
@ -225,7 +225,7 @@ fn verify_uncles(header: &Header, bytes: &[u8], bc: &BlockProvider, engine: &Eth
|
|||||||
}
|
}
|
||||||
|
|
||||||
let uncle_parent = uncle_parent.decode();
|
let uncle_parent = uncle_parent.decode();
|
||||||
verify_parent(&uncle, &uncle_parent, engine.params().gas_limit_bound_divisor)?;
|
verify_parent(&uncle, &uncle_parent, engine)?;
|
||||||
engine.verify_block_family(&uncle, &uncle_parent)?;
|
engine.verify_block_family(&uncle, &uncle_parent)?;
|
||||||
verified.insert(uncle.hash());
|
verified.insert(uncle.hash());
|
||||||
}
|
}
|
||||||
@ -303,11 +303,13 @@ pub fn verify_header_params(header: &Header, engine: &EthEngine, is_full: bool)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Check header parameters agains parent header.
|
/// Check header parameters agains parent header.
|
||||||
fn verify_parent(header: &Header, parent: &Header, gas_limit_divisor: U256) -> Result<(), Error> {
|
fn verify_parent(header: &Header, parent: &Header, engine: &EthEngine) -> Result<(), Error> {
|
||||||
|
let gas_limit_divisor = engine.params().gas_limit_bound_divisor;
|
||||||
|
|
||||||
if !header.parent_hash().is_zero() && &parent.hash() != header.parent_hash() {
|
if !header.parent_hash().is_zero() && &parent.hash() != header.parent_hash() {
|
||||||
return Err(From::from(BlockError::InvalidParentHash(Mismatch { expected: parent.hash(), found: header.parent_hash().clone() })))
|
return Err(From::from(BlockError::InvalidParentHash(Mismatch { expected: parent.hash(), found: header.parent_hash().clone() })))
|
||||||
}
|
}
|
||||||
if header.timestamp() <= parent.timestamp() {
|
if !engine.is_timestamp_valid(header.timestamp(), parent.timestamp()) {
|
||||||
return Err(From::from(BlockError::InvalidTimestamp(OutOfBounds { max: None, min: Some(parent.timestamp() + 1), found: header.timestamp() })))
|
return Err(From::from(BlockError::InvalidTimestamp(OutOfBounds { max: None, min: Some(parent.timestamp() + 1), found: header.timestamp() })))
|
||||||
}
|
}
|
||||||
if header.number() != parent.number() + 1 {
|
if header.number() != parent.number() + 1 {
|
||||||
|
Loading…
Reference in New Issue
Block a user