Extract blockchain from ethcore (#10114)

* Split blockchain & db from ethcore.

* Clean up blockchain deps.

* Missing docs.

* Fix blockchain tests.

* Make other crates compile.

* Remove some re-exports.

* Remove types re-export from ethcore.

* Remove EVM dependency from transaction.

* Merge ethcore-transaction with common-types.

* Clean-up ethcore deps a bit.

* remove ethcore from cargo.toml

* Update ethcore/blockchain/src/lib.rs

Co-Authored-By: tomusdrw <tomusdrw@users.noreply.github.com>

* Address review comments.

* Update DB comment.

* Add tracking issue to the TODO and fix typo.

* Common naming for common types.

* Update ethcore/db/src/keys.rs

Co-Authored-By: tomusdrw <tomusdrw@users.noreply.github.com>

* Update ethcore/blockchain/src/generator.rs

Co-Authored-By: tomusdrw <tomusdrw@users.noreply.github.com>

* Try to fix beta tests.
This commit is contained in:
Tomasz Drwięga
2019-01-04 14:05:46 +01:00
committed by Afri Schoedon
parent 3090324366
commit 3650f2d51c
223 changed files with 1428 additions and 1058 deletions

View File

@@ -0,0 +1,44 @@
// Copyright 2015-2018 Parity Technologies (UK) Ltd.
// This file is part of Parity.
// Parity is free software: you can redistribute it and/or modify
// 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.
// Parity is distributed in the hope that it will be useful,
// 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
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
use ethereum_types::{H256, U256};
use common_types::{encoded, BlockNumber};
use common_types::header::Header;
/// Contains information on a best block that is specific to the consensus engine.
///
/// For GHOST fork-choice rule it would typically describe the block with highest
/// combined difficulty (usually the block with the highest block number).
///
/// Sometimes refered as 'latest block'.
pub struct BestBlock {
/// Best block decoded header.
pub header: Header,
/// Best block uncompressed bytes.
pub block: encoded::Block,
/// Best block total difficulty.
pub total_difficulty: U256,
}
/// Best ancient block info. If the blockchain has a gap this keeps track of where it starts.
#[derive(Default)]
pub struct BestAncientBlock {
/// Best block hash.
pub hash: H256,
/// Best block number.
pub number: BlockNumber,
}

View File

@@ -0,0 +1,54 @@
// Copyright 2015-2018 Parity Technologies (UK) Ltd.
// This file is part of Parity.
// Parity is free software: you can redistribute it and/or modify
// 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.
// Parity is distributed in the hope that it will be useful,
// 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
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
use ethereum_types::{H256, U256};
use common_types::BlockNumber;
/// Brief info about inserted block.
#[derive(Clone)]
pub struct BlockInfo {
/// Block hash.
pub hash: H256,
/// Block number.
pub number: BlockNumber,
/// Total block difficulty.
pub total_difficulty: U256,
/// Block location in blockchain.
pub location: BlockLocation
}
/// Describes location of newly inserted block.
#[derive(Debug, Clone, PartialEq)]
pub enum BlockLocation {
/// It's part of the canon chain.
CanonChain,
/// It's not a part of the canon chain.
Branch,
/// It's part of the fork which should become canon chain,
/// because its total difficulty is higher than current
/// canon chain difficulty.
BranchBecomingCanonChain(BranchBecomingCanonChainData),
}
#[derive(Debug, Clone, PartialEq)]
pub struct BranchBecomingCanonChainData {
/// Hash of the newest common ancestor with old canon chain.
pub ancestor: H256,
/// Hashes of the blocks between ancestor and this block.
pub enacted: Vec<H256>,
/// Hashes of the blocks which were invalidated.
pub retracted: Vec<H256>,
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,35 @@
// Copyright 2015-2018 Parity Technologies (UK) Ltd.
// This file is part of Parity.
// Parity is free software: you can redistribute it and/or modify
// 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.
// Parity is distributed in the hope that it will be useful,
// 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
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
/// Represents blockchain's in-memory cache size in bytes.
#[derive(Debug)]
pub struct CacheSize {
/// Blocks cache size.
pub blocks: usize,
/// BlockDetails cache size.
pub block_details: usize,
/// Transaction addresses cache size.
pub transaction_addresses: usize,
/// Block receipts size.
pub block_receipts: usize,
}
impl CacheSize {
/// Total amount used by the cache.
pub fn total(&self) -> usize {
self.blocks + self.block_details + self.transaction_addresses + self.block_receipts
}
}

View File

@@ -0,0 +1,35 @@
// Copyright 2015-2018 Parity Technologies (UK) Ltd.
// This file is part of Parity.
// Parity is free software: you can redistribute it and/or modify
// 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.
// Parity is distributed in the hope that it will be useful,
// 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
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
//! Blockchain configuration.
/// Blockchain configuration.
#[derive(Debug, PartialEq, Clone)]
pub struct Config {
/// Preferred cache size in bytes.
pub pref_cache_size: usize,
/// Maximum cache size in bytes.
pub max_cache_size: usize,
}
impl Default for Config {
fn default() -> Self {
Config {
pref_cache_size: 1 << 14,
max_cache_size: 1 << 20,
}
}
}

View File

@@ -0,0 +1,249 @@
// Copyright 2015-2018 Parity Technologies (UK) Ltd.
// This file is part of Parity.
// Parity is free software: you can redistribute it and/or modify
// 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.
// Parity is distributed in the hope that it will be useful,
// 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
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
//! Blockchain generator for tests.
use std::collections::VecDeque;
use ethereum_types::{U256, H256, Bloom};
use common_types::encoded;
use common_types::header::Header;
use common_types::transaction::SignedTransaction;
use common_types::view;
use common_types::views::BlockView;
use rlp::encode;
use rlp_derive::RlpEncodable;
/// Helper structure, used for encoding blocks.
#[derive(Default, Clone, RlpEncodable)]
pub struct Block {
/// Block header
pub header: Header,
/// Block transactions
pub transactions: Vec<SignedTransaction>,
/// Block uncles
pub uncles: Vec<Header>
}
impl Block {
/// Get a copy of the header
#[inline]
pub fn header(&self) -> Header {
self.header.clone()
}
/// Get block hash
#[inline]
pub fn hash(&self) -> H256 {
view!(BlockView, &self.encoded().raw()).header_view().hash()
}
/// Get block number
#[inline]
pub fn number(&self) -> u64 {
self.header.number()
}
/// Get RLP encoding of this block
#[inline]
pub fn encoded(&self) -> encoded::Block {
encoded::Block::new(encode(self))
}
/// Get block difficulty
#[inline]
pub fn difficulty(&self) -> U256 {
*self.header.difficulty()
}
}
/// Specify block options for generator
#[derive(Debug)]
pub struct BlockOptions {
/// Difficulty
pub difficulty: U256,
/// Set bloom filter
pub bloom: Bloom,
/// Transactions included in blocks
pub transactions: Vec<SignedTransaction>,
}
impl Default for BlockOptions {
fn default() -> Self {
BlockOptions {
difficulty: 10.into(),
bloom: Bloom::default(),
transactions: Vec::new(),
}
}
}
/// Utility to create blocks
#[derive(Clone)]
pub struct BlockBuilder {
blocks: VecDeque<Block>,
}
impl BlockBuilder {
/// Create new BlockBuilder starting at genesis.
pub fn genesis() -> Self {
let mut blocks = VecDeque::with_capacity(1);
blocks.push_back(Block::default());
BlockBuilder {
blocks,
}
}
/// Add new block with default options.
#[inline]
pub fn add_block(&self) -> Self {
self.add_block_with(|| BlockOptions::default())
}
/// Add `count` number of blocks with default options.
#[inline]
pub fn add_blocks(&self, count: usize) -> Self {
self.add_blocks_with(count, || BlockOptions::default())
}
/// Add block with specified options.
#[inline]
pub fn add_block_with<T>(&self, get_metadata: T) -> Self where T: Fn() -> BlockOptions {
self.add_blocks_with(1, get_metadata)
}
/// Add a block with given difficulty
#[inline]
pub fn add_block_with_difficulty<T>(&self, difficulty: T) -> Self where T: Into<U256> {
let difficulty = difficulty.into();
self.add_blocks_with(1, move || BlockOptions {
difficulty,
..Default::default()
})
}
/// Add a block with given transactions.
#[inline]
pub fn add_block_with_transactions<T>(&self, transactions: T) -> Self
where T: IntoIterator<Item = SignedTransaction> {
let transactions = transactions.into_iter().collect::<Vec<_>>();
self.add_blocks_with(1, || BlockOptions {
transactions: transactions.clone(),
..Default::default()
})
}
/// Add a block with given bloom filter.
#[inline]
pub fn add_block_with_bloom(&self, bloom: Bloom) -> Self {
self.add_blocks_with(1, move || BlockOptions {
bloom,
..Default::default()
})
}
/// Add a bunch of blocks with given metadata.
pub fn add_blocks_with<T>(&self, count: usize, get_metadata: T) -> Self where T: Fn() -> BlockOptions {
assert!(count > 0, "There must be at least 1 block");
let mut parent_hash = self.last().hash();
let mut parent_number = self.last().number();
let mut blocks = VecDeque::with_capacity(count);
for _ in 0..count {
let mut block = Block::default();
let metadata = get_metadata();
let block_number = parent_number + 1;
block.header.set_parent_hash(parent_hash);
block.header.set_number(block_number);
block.header.set_log_bloom(metadata.bloom);
block.header.set_difficulty(metadata.difficulty);
block.transactions = metadata.transactions;
parent_hash = block.hash();
parent_number = block_number;
blocks.push_back(block);
}
BlockBuilder {
blocks,
}
}
/// Get a reference to the last generated block.
#[inline]
pub fn last(&self) -> &Block {
self.blocks.back().expect("There is always at least 1 block")
}
}
/// Generates a blockchain from given block builders (blocks will be concatenated).
#[derive(Clone)]
pub struct BlockGenerator {
builders: VecDeque<BlockBuilder>,
}
impl BlockGenerator {
/// Create new block generator.
pub fn new<T>(builders: T) -> Self where T: IntoIterator<Item = BlockBuilder> {
BlockGenerator {
builders: builders.into_iter().collect(),
}
}
}
impl Iterator for BlockGenerator {
type Item = Block;
fn next(&mut self) -> Option<Self::Item> {
loop {
match self.builders.front_mut() {
Some(ref mut builder) => {
if let Some(block) = builder.blocks.pop_front() {
return Some(block);
}
},
None => return None,
}
self.builders.pop_front();
}
}
}
#[cfg(test)]
mod tests {
use super::{BlockBuilder, BlockOptions, BlockGenerator};
#[test]
fn test_block_builder() {
let genesis = BlockBuilder::genesis();
let block_1 = genesis.add_block();
let block_1001 = block_1.add_blocks(1000);
let block_1002 = block_1001.add_block_with(|| BlockOptions::default());
let generator = BlockGenerator::new(vec![genesis, block_1, block_1001, block_1002]);
assert_eq!(generator.count(), 1003);
}
#[test]
fn test_block_builder_fork() {
let genesis = BlockBuilder::genesis();
let block_10a = genesis.add_blocks(10);
let block_11b = genesis.add_blocks(11);
assert_eq!(block_10a.last().number(), 10);
assert_eq!(block_11b.last().number(), 11);
}
}

View File

@@ -0,0 +1,135 @@
// Copyright 2015-2018 Parity Technologies (UK) Ltd.
// This file is part of Parity.
// Parity is free software: you can redistribute it and/or modify
// 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.
// Parity is distributed in the hope that it will be useful,
// 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
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
//! Import route.
use ethereum_types::H256;
use crate::block_info::{BlockInfo, BlockLocation};
/// Import route for newly inserted block.
#[derive(Debug, PartialEq, Clone)]
pub struct ImportRoute {
/// Blocks that were invalidated by new block.
pub retracted: Vec<H256>,
/// Blocks that were validated by new block.
pub enacted: Vec<H256>,
/// Blocks which are neither retracted nor enacted.
pub omitted: Vec<H256>,
}
impl ImportRoute {
/// Empty import route.
pub fn none() -> Self {
ImportRoute {
retracted: vec![],
enacted: vec![],
omitted: vec![],
}
}
}
impl From<BlockInfo> for ImportRoute {
fn from(info: BlockInfo) -> ImportRoute {
match info.location {
BlockLocation::CanonChain => ImportRoute {
retracted: vec![],
enacted: vec![info.hash],
omitted: vec![],
},
BlockLocation::Branch => ImportRoute {
retracted: vec![],
enacted: vec![],
omitted: vec![info.hash],
},
BlockLocation::BranchBecomingCanonChain(mut data) => {
data.enacted.push(info.hash);
ImportRoute {
retracted: data.retracted,
enacted: data.enacted,
omitted: vec![],
}
}
}
}
}
#[cfg(test)]
mod tests {
use ethereum_types::{H256, U256};
use crate::block_info::{BlockInfo, BlockLocation, BranchBecomingCanonChainData};
use super::ImportRoute;
#[test]
fn import_route_none() {
assert_eq!(ImportRoute::none(), ImportRoute {
enacted: vec![],
retracted: vec![],
omitted: vec![],
});
}
#[test]
fn import_route_branch() {
let info = BlockInfo {
hash: H256::from(U256::from(1)),
number: 0,
total_difficulty: U256::from(0),
location: BlockLocation::Branch,
};
assert_eq!(ImportRoute::from(info), ImportRoute {
retracted: vec![],
enacted: vec![],
omitted: vec![H256::from(U256::from(1))],
});
}
#[test]
fn import_route_canon_chain() {
let info = BlockInfo {
hash: H256::from(U256::from(1)),
number: 0,
total_difficulty: U256::from(0),
location: BlockLocation::CanonChain,
};
assert_eq!(ImportRoute::from(info), ImportRoute {
retracted: vec![],
enacted: vec![H256::from(U256::from(1))],
omitted: vec![],
});
}
#[test]
fn import_route_branch_becoming_canon_chain() {
let info = BlockInfo {
hash: H256::from(U256::from(2)),
number: 0,
total_difficulty: U256::from(0),
location: BlockLocation::BranchBecomingCanonChain(BranchBecomingCanonChainData {
ancestor: H256::from(U256::from(0)),
enacted: vec![H256::from(U256::from(1))],
retracted: vec![H256::from(U256::from(3)), H256::from(U256::from(4))],
})
};
assert_eq!(ImportRoute::from(info), ImportRoute {
retracted: vec![H256::from(U256::from(3)), H256::from(U256::from(4))],
enacted: vec![H256::from(U256::from(1)), H256::from(U256::from(2))],
omitted: vec![],
});
}
}

View File

@@ -0,0 +1,37 @@
// Copyright 2015-2018 Parity Technologies (UK) Ltd.
// This file is part of Parity.
// Parity is free software: you can redistribute it and/or modify
// 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.
// Parity is distributed in the hope that it will be useful,
// 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
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
//! Blockchain database.
#![warn(missing_docs)]
mod best_block;
mod block_info;
mod blockchain;
mod cache;
mod config;
mod import_route;
mod update;
pub mod generator;
pub use self::blockchain::{BlockProvider, BlockChain, BlockChainDB, BlockChainDBHandler};
pub use self::cache::CacheSize;
pub use self::config::Config;
pub use self::import_route::ImportRoute;
pub use self::update::ExtrasInsert;
pub use ethcore_db::keys::{BlockReceipts, BlockDetails, TransactionAddress};
pub use common_types::tree_route::TreeRoute;

View File

@@ -0,0 +1,51 @@
// Copyright 2015-2018 Parity Technologies (UK) Ltd.
// This file is part of Parity.
// Parity is free software: you can redistribute it and/or modify
// 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.
// Parity is distributed in the hope that it will be useful,
// 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
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
use std::collections::HashMap;
use common_types::BlockNumber;
use common_types::encoded::Block;
use common_types::engines::ForkChoice;
use ethcore_db::keys::{BlockDetails, BlockReceipts, TransactionAddress};
use ethereum_types::{H256, Bloom};
use crate::block_info::BlockInfo;
/// Block extras update info.
pub struct ExtrasUpdate {
/// Block info.
pub info: BlockInfo,
/// Current block uncompressed rlp bytes
pub block: Block,
/// Modified block hashes.
pub block_hashes: HashMap<BlockNumber, H256>,
/// Modified block details.
pub block_details: HashMap<H256, BlockDetails>,
/// Modified block receipts.
pub block_receipts: HashMap<H256, BlockReceipts>,
/// Modified blocks blooms.
pub blocks_blooms: Option<(u64, Vec<Bloom>)>,
/// Modified transaction addresses (None signifies removed transactions).
pub transactions_addresses: HashMap<H256, Option<TransactionAddress>>,
}
/// Extra information in block insertion.
pub struct ExtrasInsert {
/// The primitive fork choice before applying finalization rules.
pub fork_choice: ForkChoice,
/// Is the inserted block considered finalized.
pub is_finalized: bool,
}