2019-01-07 11:33:07 +01:00
|
|
|
// Copyright 2015-2019 Parity Technologies (UK) Ltd.
|
|
|
|
// This file is part of Parity Ethereum.
|
2016-07-11 17:02:42 +02:00
|
|
|
|
2019-01-07 11:33:07 +01:00
|
|
|
// Parity Ethereum is free software: you can redistribute it and/or modify
|
2016-07-11 17:02:42 +02: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.
|
|
|
|
|
2019-01-07 11:33:07 +01:00
|
|
|
// Parity Ethereum is distributed in the hope that it will be useful,
|
2016-07-11 17:02:42 +02: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
|
2019-01-07 11:33:07 +01:00
|
|
|
// along with Parity Ethereum. If not, see <http://www.gnu.org/licenses/>.
|
2016-07-11 17:02:42 +02:00
|
|
|
|
2017-09-06 20:47:45 +02:00
|
|
|
use bytes::Bytes;
|
2018-11-28 11:30:05 +01:00
|
|
|
use ethereum_types::{H256, U256};
|
2019-01-04 14:05:46 +01:00
|
|
|
use types::transaction::UnverifiedTransaction;
|
2018-05-07 12:58:25 +02:00
|
|
|
use blockchain::ImportRoute;
|
2018-04-27 15:04:27 +02:00
|
|
|
use std::time::Duration;
|
2018-05-07 12:58:25 +02:00
|
|
|
use std::collections::HashMap;
|
2016-07-11 17:02:42 +02:00
|
|
|
|
2018-04-09 16:14:33 +02:00
|
|
|
/// Messages to broadcast via chain
|
|
|
|
pub enum ChainMessageType {
|
|
|
|
/// Consensus message
|
|
|
|
Consensus(Vec<u8>),
|
|
|
|
/// Message with private transaction
|
2018-08-29 14:31:04 +02:00
|
|
|
PrivateTransaction(H256, Vec<u8>),
|
2018-04-09 16:14:33 +02:00
|
|
|
/// Message with signed private transaction
|
2018-08-29 14:31:04 +02:00
|
|
|
SignedPrivateTransaction(H256, Vec<u8>),
|
2018-04-09 16:14:33 +02:00
|
|
|
}
|
|
|
|
|
2018-05-07 12:58:25 +02:00
|
|
|
/// Route type to indicate whether it is enacted or retracted.
|
|
|
|
#[derive(Clone)]
|
|
|
|
pub enum ChainRouteType {
|
|
|
|
/// Enacted block
|
|
|
|
Enacted,
|
|
|
|
/// Retracted block
|
|
|
|
Retracted
|
|
|
|
}
|
|
|
|
|
|
|
|
/// A complete chain enacted retracted route.
|
|
|
|
#[derive(Default, Clone)]
|
|
|
|
pub struct ChainRoute {
|
|
|
|
route: Vec<(H256, ChainRouteType)>,
|
|
|
|
enacted: Vec<H256>,
|
|
|
|
retracted: Vec<H256>,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<'a> From<&'a [ImportRoute]> for ChainRoute {
|
|
|
|
fn from(import_results: &'a [ImportRoute]) -> ChainRoute {
|
|
|
|
ChainRoute::new(import_results.iter().flat_map(|route| {
|
|
|
|
route.retracted.iter().map(|h| (*h, ChainRouteType::Retracted))
|
|
|
|
.chain(route.enacted.iter().map(|h| (*h, ChainRouteType::Enacted)))
|
|
|
|
}).collect())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl ChainRoute {
|
|
|
|
/// Create a new ChainRoute based on block hash and route type pairs.
|
|
|
|
pub fn new(route: Vec<(H256, ChainRouteType)>) -> Self {
|
|
|
|
let (enacted, retracted) = Self::to_enacted_retracted(&route);
|
|
|
|
|
|
|
|
Self { route, enacted, retracted }
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Gather all non-duplicate enacted and retracted blocks.
|
|
|
|
fn to_enacted_retracted(route: &[(H256, ChainRouteType)]) -> (Vec<H256>, Vec<H256>) {
|
|
|
|
fn map_to_vec(map: Vec<(H256, bool)>) -> Vec<H256> {
|
|
|
|
map.into_iter().map(|(k, _v)| k).collect()
|
|
|
|
}
|
|
|
|
|
|
|
|
// Because we are doing multiple inserts some of the blocks that were enacted in import `k`
|
|
|
|
// could be retracted in import `k+1`. This is why to understand if after all inserts
|
|
|
|
// the block is enacted or retracted we iterate over all routes and at the end final state
|
|
|
|
// will be in the hashmap
|
|
|
|
let map = route.iter().fold(HashMap::new(), |mut map, route| {
|
|
|
|
match &route.1 {
|
|
|
|
&ChainRouteType::Enacted => {
|
|
|
|
map.insert(route.0, true);
|
|
|
|
},
|
|
|
|
&ChainRouteType::Retracted => {
|
|
|
|
map.insert(route.0, false);
|
|
|
|
},
|
|
|
|
}
|
|
|
|
map
|
|
|
|
});
|
|
|
|
|
|
|
|
// Split to enacted retracted (using hashmap value)
|
|
|
|
let (enacted, retracted) = map.into_iter().partition(|&(_k, v)| v);
|
|
|
|
// And convert tuples to keys
|
|
|
|
(map_to_vec(enacted), map_to_vec(retracted))
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Consume route and return the enacted retracted form.
|
|
|
|
pub fn into_enacted_retracted(self) -> (Vec<H256>, Vec<H256>) {
|
|
|
|
(self.enacted, self.retracted)
|
|
|
|
}
|
|
|
|
|
|
|
|
/// All non-duplicate enacted blocks.
|
|
|
|
pub fn enacted(&self) -> &[H256] {
|
|
|
|
&self.enacted
|
|
|
|
}
|
|
|
|
|
|
|
|
/// All non-duplicate retracted blocks.
|
|
|
|
pub fn retracted(&self) -> &[H256] {
|
|
|
|
&self.retracted
|
|
|
|
}
|
|
|
|
|
|
|
|
/// All blocks in the route.
|
|
|
|
pub fn route(&self) -> &[(H256, ChainRouteType)] {
|
|
|
|
&self.route
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-12-19 10:24:14 +01:00
|
|
|
/// Used by `ChainNotify` `new_blocks()`
|
|
|
|
pub struct NewBlocks {
|
|
|
|
/// Imported blocks
|
|
|
|
pub imported: Vec<H256>,
|
|
|
|
/// Invalid blocks
|
|
|
|
pub invalid: Vec<H256>,
|
|
|
|
/// Route
|
|
|
|
pub route: ChainRoute,
|
|
|
|
/// Sealed
|
|
|
|
pub sealed: Vec<H256>,
|
|
|
|
/// Block bytes.
|
|
|
|
pub proposed: Vec<Bytes>,
|
|
|
|
/// Duration
|
|
|
|
pub duration: Duration,
|
|
|
|
/// Has more blocks to import
|
|
|
|
pub has_more_blocks_to_import: bool,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl NewBlocks {
|
|
|
|
/// Constructor
|
2018-12-20 14:28:32 +01:00
|
|
|
pub fn new(
|
2018-12-19 10:24:14 +01:00
|
|
|
imported: Vec<H256>,
|
|
|
|
invalid: Vec<H256>,
|
|
|
|
route: ChainRoute,
|
|
|
|
sealed: Vec<H256>,
|
|
|
|
proposed: Vec<Bytes>,
|
|
|
|
duration: Duration,
|
|
|
|
has_more_blocks_to_import: bool,
|
|
|
|
) -> NewBlocks {
|
|
|
|
NewBlocks {
|
|
|
|
imported,
|
|
|
|
invalid,
|
|
|
|
route,
|
|
|
|
sealed,
|
|
|
|
proposed,
|
|
|
|
duration,
|
|
|
|
has_more_blocks_to_import,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-07-11 17:02:42 +02:00
|
|
|
/// Represents what has to be handled by actor listening to chain events
|
|
|
|
pub trait ChainNotify : Send + Sync {
|
2016-09-05 12:17:21 +02:00
|
|
|
/// fires when chain has new blocks.
|
2018-12-20 14:28:32 +01:00
|
|
|
fn new_blocks(&self, _new_blocks: NewBlocks) {
|
2016-07-11 17:02:42 +02:00
|
|
|
// does nothing by default
|
|
|
|
}
|
|
|
|
|
|
|
|
/// fires when chain achieves active mode
|
|
|
|
fn start(&self) {
|
|
|
|
// does nothing by default
|
|
|
|
}
|
|
|
|
|
|
|
|
/// fires when chain achieves passive mode
|
|
|
|
fn stop(&self) {
|
|
|
|
// does nothing by default
|
|
|
|
}
|
2016-08-15 14:25:57 +02:00
|
|
|
|
|
|
|
/// fires when chain broadcasts a message
|
2018-11-28 11:30:05 +01:00
|
|
|
fn broadcast(&self, _message_type: ChainMessageType) {
|
|
|
|
// does nothing by default
|
|
|
|
}
|
|
|
|
|
|
|
|
/// fires when new block is about to be imported
|
|
|
|
/// implementations should be light
|
|
|
|
fn block_pre_import(&self, _bytes: &Bytes, _hash: &H256, _difficulty: &U256) {
|
|
|
|
// does nothing by default
|
|
|
|
}
|
2016-12-12 21:28:46 +01:00
|
|
|
|
2016-12-10 21:22:19 +01:00
|
|
|
/// fires when new transactions are received from a peer
|
|
|
|
fn transactions_received(&self,
|
2018-04-13 17:34:27 +02:00
|
|
|
_txs: &[UnverifiedTransaction],
|
2016-12-10 21:22:19 +01:00
|
|
|
_peer_id: usize,
|
2016-12-10 14:56:41 +01:00
|
|
|
) {
|
|
|
|
// does nothing by default
|
2016-08-15 14:25:57 +02:00
|
|
|
}
|
2016-07-11 17:02:42 +02:00
|
|
|
}
|