openethereum/crates/ethcore/types/src/header.rs

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

458 lines
16 KiB
Rust
Raw Normal View History

2020-09-22 14:53:52 +02:00
// Copyright 2015-2020 Parity Technologies (UK) Ltd.
// This file is part of OpenEthereum.
2016-02-05 13:40:41 +01:00
2020-09-22 14:53:52 +02:00
// OpenEthereum is free software: you can redistribute it and/or modify
2016-02-05 13:40:41 +01:00
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
2020-09-22 14:53:52 +02:00
// OpenEthereum is distributed in the hope that it will be useful,
2016-02-05 13:40:41 +01:00
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
2020-09-22 14:53:52 +02:00
// along with OpenEthereum. If not, see <http://www.gnu.org/licenses/>.
2016-02-05 13:40:41 +01:00
2016-02-02 15:29:53 +01:00
//! Block header.
use crate::{
bytes::Bytes,
hash::{keccak, KECCAK_EMPTY_LIST_RLP, KECCAK_NULL_RLP},
BlockNumber,
};
use ethereum_types::{Address, Bloom, H256, U256};
use parity_util_mem::MallocSizeOf;
use rlp::{Decodable, DecoderError, Encodable, Rlp, RlpStream};
/// Semantic boolean for when a seal/signature is included.
#[derive(Debug, Clone, Copy)]
enum Seal {
/// The seal/signature is included.
With,
/// The seal/signature is not included.
Without,
}
Fork choice and metadata framework for Engine (#8401) * Add light client TODO item * Move existing total-difficulty-based fork choice check to Engine * Abstract total difficulty and block provider as Machine::BlockMetadata and Machine::BlockProvider * Decouple "generate_metadata" logic to Engine * Use fixed BlockMetadata and BlockProvider type for null and instantseal In this way they can use total difficulty fork choice check * Extend blockdetails with metadatas and finalized info * Extra data update: mark_finalized and update_metadatas * Check finalized block in Blockchain * Fix a test constructor in verification mod * Add total difficulty trait * Fix type import * Db migration to V13 with metadata column * Address grumbles * metadatas -> metadata * Use generic type for update_metadata to avoid passing HashMap all around * Remove metadata in blockdetails * [WIP] Implement a generic metadata architecture * [WIP] Metadata insertion logic in BlockChain * typo: Value -> Self::Value * [WIP] Temporarily remove Engine::is_new_best interface So that we don't have too many type errors. * [WIP] Fix more type errors * [WIP] ExtendedHeader::PartialEq * [WIP] Change metadata type Option<Vec<u8>> to Vec<u8> * [WIP] Remove Metadata Error * [WIP] Clean up error conversion * [WIP] finalized -> is_finalized * [WIP] Mark all fields in ExtrasInsert as pub * [WIP] Remove unused import * [WIP] Keep only local metadata info * Mark metadata as optional * [WIP] Revert metadata db change in BlockChain * [WIP] Put finalization in unclosed state * Use metadata interface in BlockDetail * [WIP] Fix current build failures * [WIP] Remove unused blockmetadata struct * Remove DB migration info * [WIP] Typo * Use ExtendedHeader to implement fork choice check * Implement is_new_best using Ancestry iterator * Use expect instead of panic * [WIP] Add ancestry Engine support via on_new_block * Fix tests * Emission of ancestry actions * use_short_version should take account of metadata * Engine::is_new_best -> Engine::fork_choice * Use proper expect format as defined in #1026 * panic -> expect * ancestry_header -> ancestry_with_metadata * Boxed iterator -> &mut iterator * Fix tests * is_new_best -> primitive_fork_choice * Document how fork_choice works * Engine::fork_choice -> Engine::primitive_fork_choice * comment: clarify types of finalization where Engine::primitive_fork_choice works * Expose FinalizationInfo to Engine * Fix tests due to merging * Remove TotalDifficulty trait * Do not pass FinalizationInfo to Engine If there's finalized blocks in from route, choose the old branch without calling `Engine::fork_choice`. * Fix compile * Fix unused import * Remove is_to_route_finalized When no block reorg passes a finalized block, this variable is always false. * Address format grumbles * Fix docs: mark_finalized returns None if block hash is not found `blockchain` mod does not yet have an Error type, so we still temporarily use None here. * Fix inaccurate tree_route None expect description
2018-05-16 08:58:01 +02:00
/// Extended block header, wrapping `Header` with finalized and total difficulty information.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ExtendedHeader {
/// The actual header.
pub header: Header,
/// Whether the block underlying this header is considered finalized.
pub is_finalized: bool,
/// The parent block difficulty.
pub parent_total_difficulty: U256,
}
/// A block header.
///
/// Reflects the specific RLP fields of a block in the chain with additional room for the seal
/// which is non-specific.
///
/// Doesn't do all that much on its own.
#[derive(Debug, Clone, Eq, MallocSizeOf)]
pub struct Header {
2016-02-02 18:21:31 +01:00
/// Parent hash.
parent_hash: H256,
2016-02-02 18:21:31 +01:00
/// Block timestamp.
timestamp: u64,
2016-02-02 18:21:31 +01:00
/// Block number.
number: BlockNumber,
2016-02-02 18:21:31 +01:00
/// Block author.
author: Address,
2020-08-05 06:08:03 +02:00
2016-02-02 18:21:31 +01:00
/// Transactions root.
transactions_root: H256,
2016-02-02 18:21:31 +01:00
/// Block uncles hash.
uncles_hash: H256,
2016-02-02 18:21:31 +01:00
/// Block extra data.
extra_data: Bytes,
2020-08-05 06:08:03 +02:00
2016-02-02 18:21:31 +01:00
/// State root.
state_root: H256,
2016-02-02 18:21:31 +01:00
/// Block receipts root.
receipts_root: H256,
2016-02-02 18:21:31 +01:00
/// Block bloom.
log_bloom: Bloom,
2016-02-02 18:21:31 +01:00
/// Gas used for contracts execution.
gas_used: U256,
2016-02-02 18:21:31 +01:00
/// Block gas limit.
gas_limit: U256,
2020-08-05 06:08:03 +02:00
2016-02-02 18:21:31 +01:00
/// Block difficulty.
difficulty: U256,
/// Vector of post-RLP-encoded fields.
seal: Vec<Bytes>,
2020-08-05 06:08:03 +02:00
/// Memoized hash of that header and the seal.
hash: Option<H256>,
}
2016-03-02 23:41:15 +01:00
impl PartialEq for Header {
fn eq(&self, c: &Header) -> bool {
if let (&Some(ref h1), &Some(ref h2)) = (&self.hash, &c.hash) {
if h1 == h2 {
return true;
}
}
2020-08-05 06:08:03 +02:00
2016-03-02 23:41:15 +01:00
self.parent_hash == c.parent_hash
&& self.timestamp == c.timestamp
&& self.number == c.number
&& self.author == c.author
&& self.transactions_root == c.transactions_root
&& self.uncles_hash == c.uncles_hash
&& self.extra_data == c.extra_data
&& self.state_root == c.state_root
&& self.receipts_root == c.receipts_root
&& self.log_bloom == c.log_bloom
&& self.gas_used == c.gas_used
&& self.gas_limit == c.gas_limit
&& self.difficulty == c.difficulty
&& self.seal == c.seal
}
}
2016-02-02 18:21:31 +01:00
impl Default for Header {
fn default() -> Self {
Header {
parent_hash: H256::default(),
timestamp: 0,
number: 0,
author: Address::default(),
2020-08-05 06:08:03 +02:00
transactions_root: KECCAK_NULL_RLP,
uncles_hash: KECCAK_EMPTY_LIST_RLP,
extra_data: vec![],
2020-08-05 06:08:03 +02:00
state_root: KECCAK_NULL_RLP,
receipts_root: KECCAK_NULL_RLP,
log_bloom: Bloom::default(),
gas_used: U256::default(),
gas_limit: U256::default(),
2020-08-05 06:08:03 +02:00
difficulty: U256::default(),
seal: vec![],
hash: None,
}
}
2016-02-02 18:21:31 +01:00
}
impl Header {
/// Create a new, default-valued, header.
pub fn new() -> Self {
Self::default()
}
2020-08-05 06:08:03 +02:00
/// Get the parent_hash field of the header.
pub fn parent_hash(&self) -> &H256 {
&self.parent_hash
}
2020-08-05 06:08:03 +02:00
2016-02-03 13:20:32 +01:00
/// Get the timestamp field of the header.
pub fn timestamp(&self) -> u64 {
self.timestamp
}
2020-08-05 06:08:03 +02:00
/// Get the number field of the header.
pub fn number(&self) -> BlockNumber {
self.number
}
2020-08-05 06:08:03 +02:00
2016-02-03 13:20:32 +01:00
/// Get the author field of the header.
2016-01-10 14:05:39 +01:00
pub fn author(&self) -> &Address {
&self.author
}
2020-08-05 06:08:03 +02:00
2016-02-03 13:20:32 +01:00
/// Get the extra data field of the header.
2016-01-10 14:05:39 +01:00
pub fn extra_data(&self) -> &Bytes {
&self.extra_data
}
2020-08-05 06:08:03 +02:00
2016-02-03 13:20:32 +01:00
/// Get the state root field of the header.
pub fn state_root(&self) -> &H256 {
&self.state_root
}
2020-08-05 06:08:03 +02:00
2016-02-03 13:20:32 +01:00
/// Get the receipts root field of the header.
pub fn receipts_root(&self) -> &H256 {
&self.receipts_root
2020-08-05 06:08:03 +02:00
}
/// Get the log bloom field of the header.
pub fn log_bloom(&self) -> &Bloom {
&self.log_bloom
}
2020-08-05 06:08:03 +02:00
/// Get the transactions root field of the header.
pub fn transactions_root(&self) -> &H256 {
&self.transactions_root
}
2020-08-05 06:08:03 +02:00
/// Get the uncles hash field of the header.
2016-01-15 23:32:17 +01:00
pub fn uncles_hash(&self) -> &H256 {
&self.uncles_hash
}
2020-08-05 06:08:03 +02:00
2016-02-03 13:20:32 +01:00
/// Get the gas used field of the header.
2016-01-15 23:32:17 +01:00
pub fn gas_used(&self) -> &U256 {
&self.gas_used
}
2020-08-05 06:08:03 +02:00
2016-02-03 13:20:32 +01:00
/// Get the gas limit field of the header.
2017-11-01 11:29:03 +01:00
pub fn gas_limit(&self) -> &U256 {
&self.gas_limit
2020-08-05 06:08:03 +02:00
}
2017-11-01 11:29:03 +01:00
/// Get the difficulty field of the header.
pub fn difficulty(&self) -> &U256 {
&self.difficulty
2017-11-01 11:29:03 +01:00
}
2020-08-05 06:08:03 +02:00
2016-02-03 13:20:32 +01:00
/// Get the seal field of the header.
pub fn seal(&self) -> &[Bytes] {
&self.seal
}
2020-08-05 06:08:03 +02:00
2016-06-14 18:12:05 +02:00
/// Get the seal field with RLP-decoded values as bytes.
pub fn decode_seal<'a, T: ::std::iter::FromIterator<&'a [u8]>>(
&'a self,
) -> Result<T, DecoderError> {
self.seal.iter().map(|rlp| Rlp::new(rlp).data()).collect()
}
2020-08-05 06:08:03 +02:00
2016-06-14 18:12:05 +02:00
/// Set the number field of the header.
pub fn set_parent_hash(&mut self, a: H256) {
change_field(&mut self.hash, &mut self.parent_hash, a);
}
2020-08-05 06:08:03 +02:00
2016-06-14 18:12:05 +02:00
/// Set the uncles hash field of the header.
pub fn set_uncles_hash(&mut self, a: H256) {
change_field(&mut self.hash, &mut self.uncles_hash, a);
}
2016-06-14 18:12:05 +02:00
/// Set the state root field of the header.
pub fn set_state_root(&mut self, a: H256) {
change_field(&mut self.hash, &mut self.state_root, a);
2020-08-05 06:08:03 +02:00
}
/// Set the transactions root field of the header.
pub fn set_transactions_root(&mut self, a: H256) {
change_field(&mut self.hash, &mut self.transactions_root, a);
}
2020-08-05 06:08:03 +02:00
2016-06-14 18:12:05 +02:00
/// Set the receipts root field of the header.
pub fn set_receipts_root(&mut self, a: H256) {
change_field(&mut self.hash, &mut self.receipts_root, a);
}
2020-08-05 06:08:03 +02:00
2016-02-03 13:20:32 +01:00
/// Set the log bloom field of the header.
pub fn set_log_bloom(&mut self, a: Bloom) {
change_field(&mut self.hash, &mut self.log_bloom, a);
}
2020-08-05 06:08:03 +02:00
/// Set the timestamp field of the header.
pub fn set_timestamp(&mut self, a: u64) {
change_field(&mut self.hash, &mut self.timestamp, a);
}
2020-08-05 06:08:03 +02:00
2016-02-03 13:20:32 +01:00
/// Set the number field of the header.
pub fn set_number(&mut self, a: BlockNumber) {
change_field(&mut self.hash, &mut self.number, a);
}
2020-08-05 06:08:03 +02:00
2016-02-03 13:20:32 +01:00
/// Set the author field of the header.
pub fn set_author(&mut self, a: Address) {
change_field(&mut self.hash, &mut self.author, a);
}
2020-08-05 06:08:03 +02:00
2016-02-03 13:20:32 +01:00
/// Set the extra data field of the header.
pub fn set_extra_data(&mut self, a: Bytes) {
change_field(&mut self.hash, &mut self.extra_data, a);
2020-08-05 06:08:03 +02:00
}
/// Set the gas used field of the header.
pub fn set_gas_used(&mut self, a: U256) {
change_field(&mut self.hash, &mut self.gas_used, a);
}
2020-08-05 06:08:03 +02:00
2016-02-03 13:20:32 +01:00
/// Set the gas limit field of the header.
pub fn set_gas_limit(&mut self, a: U256) {
change_field(&mut self.hash, &mut self.gas_limit, a);
}
2020-08-05 06:08:03 +02:00
2016-02-03 13:20:32 +01:00
/// Set the difficulty field of the header.
pub fn set_difficulty(&mut self, a: U256) {
change_field(&mut self.hash, &mut self.difficulty, a);
}
2020-08-05 06:08:03 +02:00
2016-02-03 13:20:32 +01:00
/// Set the seal field of the header.
pub fn set_seal(&mut self, a: Vec<Bytes>) {
change_field(&mut self.hash, &mut self.seal, a)
}
2020-08-05 06:08:03 +02:00
/// Get & memoize the hash of this header (keccak of the RLP with seal).
pub fn compute_hash(&mut self) -> H256 {
let hash = self.hash();
self.hash = Some(hash);
hash
}
2020-08-05 06:08:03 +02:00
/// Get the hash of this header (keccak of the RLP with seal).
2015-12-24 17:18:47 +01:00
pub fn hash(&self) -> H256 {
self.hash.unwrap_or_else(|| keccak(self.rlp(Seal::With)))
2015-12-24 17:18:47 +01:00
}
2020-08-05 06:08:03 +02:00
2016-01-17 12:00:34 +01:00
/// Get the hash of the header excluding the seal
pub fn bare_hash(&self) -> H256 {
keccak(self.rlp(Seal::Without))
2016-01-17 12:00:34 +01:00
}
2020-08-05 06:08:03 +02:00
/// Encode the header, getting a type-safe wrapper around the RLP.
pub fn encoded(&self) -> crate::encoded::Header {
crate::encoded::Header::new(self.rlp(Seal::With))
}
2020-08-05 06:08:03 +02:00
/// Get the RLP representation of this Header.
fn rlp(&self, with_seal: Seal) -> Bytes {
let mut s = RlpStream::new();
self.stream_rlp(&mut s, with_seal);
s.out()
}
2020-08-05 06:08:03 +02:00
2016-02-03 13:20:32 +01:00
/// Place this header into an RLP stream `s`, optionally `with_seal`.
fn stream_rlp(&self, s: &mut RlpStream, with_seal: Seal) {
if let Seal::With = with_seal {
s.begin_list(13 + self.seal.len());
} else {
s.begin_list(13);
}
2020-08-05 06:08:03 +02:00
s.append(&self.parent_hash);
s.append(&self.uncles_hash);
s.append(&self.author);
s.append(&self.state_root);
s.append(&self.transactions_root);
s.append(&self.receipts_root);
s.append(&self.log_bloom);
s.append(&self.difficulty);
s.append(&self.number);
s.append(&self.gas_limit);
s.append(&self.gas_used);
s.append(&self.timestamp);
s.append(&self.extra_data);
2020-08-05 06:08:03 +02:00
2016-01-17 15:56:09 +01:00
if let Seal::With = with_seal {
for b in &self.seal {
s.append_raw(b, 1);
2016-01-17 15:56:09 +01:00
}
}
}
}
/// Alter value of given field, reset memoised hash if changed.
fn change_field<T>(hash: &mut Option<H256>, field: &mut T, value: T)
where
T: PartialEq<T>,
{
if field != &value {
*field = value;
*hash = None;
}
2015-12-08 16:31:36 +01:00
}
impl Decodable for Header {
fn decode(r: &Rlp) -> Result<Self, DecoderError> {
2015-12-14 15:22:41 +01:00
let mut blockheader = Header {
parent_hash: r.val_at(0)?,
uncles_hash: r.val_at(1)?,
author: r.val_at(2)?,
state_root: r.val_at(3)?,
transactions_root: r.val_at(4)?,
receipts_root: r.val_at(5)?,
log_bloom: r.val_at(6)?,
difficulty: r.val_at(7)?,
number: r.val_at(8)?,
gas_limit: r.val_at(9)?,
gas_used: r.val_at(10)?,
timestamp: r.val_at(11)?,
extra_data: r.val_at(12)?,
2015-12-14 12:09:32 +01:00
seal: vec![],
hash: keccak(r.as_raw()).into(),
2015-12-14 12:09:32 +01:00
};
2020-08-05 06:08:03 +02:00
for i in 13..r.item_count()? {
blockheader.seal.push(r.at(i)?.as_raw().to_vec())
2015-12-14 15:22:41 +01:00
}
2020-08-05 06:08:03 +02:00
2015-12-14 12:09:32 +01:00
Ok(blockheader)
2015-12-08 16:31:36 +01:00
}
}
impl Encodable for Header {
2016-01-27 17:22:01 +01:00
fn rlp_append(&self, s: &mut RlpStream) {
self.stream_rlp(s, Seal::With);
2015-12-08 16:31:36 +01:00
}
}
impl ExtendedHeader {
/// Returns combined difficulty of all ancestors together with the difficulty of this header.
pub fn total_score(&self) -> U256 {
self.parent_total_difficulty + *self.header.difficulty()
}
Fork choice and metadata framework for Engine (#8401) * Add light client TODO item * Move existing total-difficulty-based fork choice check to Engine * Abstract total difficulty and block provider as Machine::BlockMetadata and Machine::BlockProvider * Decouple "generate_metadata" logic to Engine * Use fixed BlockMetadata and BlockProvider type for null and instantseal In this way they can use total difficulty fork choice check * Extend blockdetails with metadatas and finalized info * Extra data update: mark_finalized and update_metadatas * Check finalized block in Blockchain * Fix a test constructor in verification mod * Add total difficulty trait * Fix type import * Db migration to V13 with metadata column * Address grumbles * metadatas -> metadata * Use generic type for update_metadata to avoid passing HashMap all around * Remove metadata in blockdetails * [WIP] Implement a generic metadata architecture * [WIP] Metadata insertion logic in BlockChain * typo: Value -> Self::Value * [WIP] Temporarily remove Engine::is_new_best interface So that we don't have too many type errors. * [WIP] Fix more type errors * [WIP] ExtendedHeader::PartialEq * [WIP] Change metadata type Option<Vec<u8>> to Vec<u8> * [WIP] Remove Metadata Error * [WIP] Clean up error conversion * [WIP] finalized -> is_finalized * [WIP] Mark all fields in ExtrasInsert as pub * [WIP] Remove unused import * [WIP] Keep only local metadata info * Mark metadata as optional * [WIP] Revert metadata db change in BlockChain * [WIP] Put finalization in unclosed state * Use metadata interface in BlockDetail * [WIP] Fix current build failures * [WIP] Remove unused blockmetadata struct * Remove DB migration info * [WIP] Typo * Use ExtendedHeader to implement fork choice check * Implement is_new_best using Ancestry iterator * Use expect instead of panic * [WIP] Add ancestry Engine support via on_new_block * Fix tests * Emission of ancestry actions * use_short_version should take account of metadata * Engine::is_new_best -> Engine::fork_choice * Use proper expect format as defined in #1026 * panic -> expect * ancestry_header -> ancestry_with_metadata * Boxed iterator -> &mut iterator * Fix tests * is_new_best -> primitive_fork_choice * Document how fork_choice works * Engine::fork_choice -> Engine::primitive_fork_choice * comment: clarify types of finalization where Engine::primitive_fork_choice works * Expose FinalizationInfo to Engine * Fix tests due to merging * Remove TotalDifficulty trait * Do not pass FinalizationInfo to Engine If there's finalized blocks in from route, choose the old branch without calling `Engine::fork_choice`. * Fix compile * Fix unused import * Remove is_to_route_finalized When no block reorg passes a finalized block, this variable is always false. * Address format grumbles * Fix docs: mark_finalized returns None if block hash is not found `blockchain` mod does not yet have an Error type, so we still temporarily use None here. * Fix inaccurate tree_route None expect description
2018-05-16 08:58:01 +02:00
}
2015-12-09 00:45:33 +01:00
#[cfg(test)]
mod tests {
use super::Header;
2020-08-05 06:08:03 +02:00
use rlp;
use rustc_hex::FromHex;
2020-08-05 06:08:03 +02:00
#[test]
fn test_header_seal_fields() {
// that's rlp of block header created with ethash engine.
let header_rlp = "f901f9a0d405da4e66f1445d455195229624e133f5baafe72b5cf7b3c36c12c8146e98b7a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a05fb2b4bfdef7b314451cb138a534d225c922fc0e5fbe25e451142732c3e25c25a088d2ec6b9860aae1a2c3b299f72b6a5d70d7f7ba4722c78f2c49ba96273c2158a007c6fdfa8eea7e86b81f5b0fc0f78f90cc19f4aa60d323151e0cac660199e9a1b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008302008003832fefba82524d84568e932a80a0a0349d8c3df71f1a48a9df7d03fd5f14aeee7d91332c009ecaff0a71ead405bd88ab4e252a7e8c2a23".from_hex().unwrap();
let mix_hash = "a0a0349d8c3df71f1a48a9df7d03fd5f14aeee7d91332c009ecaff0a71ead405bd"
.from_hex()
2017-11-01 11:29:03 +01:00
.unwrap();
let mix_hash_decoded = "a0349d8c3df71f1a48a9df7d03fd5f14aeee7d91332c009ecaff0a71ead405bd"
.from_hex()
.unwrap();
let nonce = "88ab4e252a7e8c2a23".from_hex().unwrap();
2017-11-01 11:29:03 +01:00
let nonce_decoded = "ab4e252a7e8c2a23".from_hex().unwrap();
2020-08-05 06:08:03 +02:00
let header: Header = rlp::decode(&header_rlp).expect("error decoding header");
2017-11-01 11:29:03 +01:00
let seal_fields = header.seal.clone();
assert_eq!(seal_fields.len(), 2);
assert_eq!(seal_fields[0], mix_hash);
assert_eq!(seal_fields[1], nonce);
2020-08-05 06:08:03 +02:00
2017-11-01 11:29:03 +01:00
let decoded_seal = header.decode_seal::<Vec<_>>().unwrap();
assert_eq!(decoded_seal.len(), 2);
assert_eq!(decoded_seal[0], &*mix_hash_decoded);
assert_eq!(decoded_seal[1], &*nonce_decoded);
}
2020-08-05 06:08:03 +02:00
#[test]
fn decode_and_encode_header() {
// that's rlp of block header created with ethash engine.
let header_rlp = "f901f9a0d405da4e66f1445d455195229624e133f5baafe72b5cf7b3c36c12c8146e98b7a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a05fb2b4bfdef7b314451cb138a534d225c922fc0e5fbe25e451142732c3e25c25a088d2ec6b9860aae1a2c3b299f72b6a5d70d7f7ba4722c78f2c49ba96273c2158a007c6fdfa8eea7e86b81f5b0fc0f78f90cc19f4aa60d323151e0cac660199e9a1b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008302008003832fefba82524d84568e932a80a0a0349d8c3df71f1a48a9df7d03fd5f14aeee7d91332c009ecaff0a71ead405bd88ab4e252a7e8c2a23".from_hex().unwrap();
2020-08-05 06:08:03 +02:00
let header: Header = rlp::decode(&header_rlp).expect("error decoding header");
let encoded_header = rlp::encode(&header);
2020-08-05 06:08:03 +02:00
assert_eq!(header_rlp, encoded_header);
}
2020-08-05 06:08:03 +02:00
#[test]
fn reject_header_with_large_timestamp() {
// that's rlp of block header created with ethash engine.
// The encoding contains a large timestamp (295147905179352825856)
let header_rlp = "f901f9a0d405da4e66f1445d455195229624e133f5baafe72b5cf7b3c36c12c8146e98b7a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a05fb2b4bfdef7b314451cb138a534d225c922fc0e5fbe25e451142732c3e25c25a088d2ec6b9860aae1a2c3b299f72b6a5d70d7f7ba4722c78f2c49ba96273c2158a007c6fdfa8eea7e86b81f5b0fc0f78f90cc19f4aa60d323151e0cac660199e9a1b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008302008003832fefba82524d891000000000000000000080a0a0349d8c3df71f1a48a9df7d03fd5f14aeee7d91332c009ecaff0a71ead405bd88ab4e252a7e8c2a23".from_hex().unwrap();
2020-08-05 06:08:03 +02:00
// This should fail decoding timestamp
let header: Result<Header, _> = rlp::decode(&header_rlp);
assert_eq!(header.unwrap_err(), rlp::DecoderError::RlpIsTooBig);
}
2015-12-09 00:45:33 +01:00
}