2016-03-10 11:32:10 +01:00
// Copyright 2015, 2016 Ethcore (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 client.
mod client ;
mod config ;
2016-05-18 11:34:15 +02:00
mod error ;
2016-03-10 20:27:50 +01:00
mod test_client ;
2016-04-30 17:41:24 +02:00
mod trace ;
2016-03-10 11:32:10 +01:00
pub use self ::client ::* ;
2016-05-19 00:44:49 +02:00
pub use self ::config ::{ ClientConfig , BlockQueueConfig , BlockChainConfig , Switch , VMType } ;
2016-05-18 11:34:15 +02:00
pub use self ::error ::Error ;
2016-05-16 18:33:32 +02:00
pub use types ::ids ::* ;
2016-03-10 20:27:50 +01:00
pub use self ::test_client ::{ TestBlockChainClient , EachBlockWith } ;
2016-05-02 12:17:30 +02:00
pub use self ::trace ::Filter as TraceFilter ;
2016-04-28 21:47:44 +02:00
pub use executive ::{ Executed , Executive , TransactOptions } ;
pub use env_info ::{ LastHashes , EnvInfo } ;
2016-03-10 11:32:10 +01:00
use util ::bytes ::Bytes ;
use util ::hash ::{ Address , H256 , H2048 } ;
use util ::numbers ::U256 ;
2016-06-16 12:44:08 +02:00
use util ::Itertools ;
2016-03-10 11:32:10 +01:00
use blockchain ::TreeRoute ;
use block_queue ::BlockQueueInfo ;
2016-06-13 18:51:14 +02:00
use block ::OpenBlock ;
2016-03-22 16:07:42 +01:00
use header ::{ BlockNumber , Header } ;
2016-03-11 14:26:23 +01:00
use transaction ::{ LocalizedTransaction , SignedTransaction } ;
2016-03-10 11:32:10 +01:00
use log_entry ::LocalizedLogEntry ;
use filter ::Filter ;
2016-06-18 20:26:44 +02:00
use views ::{ HeaderView , BlockView } ;
2016-05-14 14:28:44 +02:00
use error ::{ ImportResult , ExecutionError } ;
2016-03-20 18:44:57 +01:00
use receipt ::LocalizedReceipt ;
2016-05-02 12:17:30 +02:00
use trace ::LocalizedTrace ;
2016-05-19 00:44:49 +02:00
use evm ::Factory as EvmFactory ;
2016-06-01 14:50:06 +02:00
use miner ::{ TransactionImportResult } ;
2016-05-31 19:52:53 +02:00
use error ::Error as EthError ;
2016-03-10 11:32:10 +01:00
2016-05-31 21:03:44 +02:00
/// Options concerning what analytics we run on the call.
#[ derive(Eq, PartialEq, Default, Clone, Copy, Debug) ]
pub struct CallAnalytics {
2016-06-02 13:50:50 +02:00
/// Make a transaction trace.
pub transaction_tracing : bool ,
2016-05-31 21:03:44 +02:00
/// Make a VM trace.
pub vm_tracing : bool ,
/// Make a diff.
2016-06-02 12:39:25 +02:00
pub state_diffing : bool ,
2016-05-31 21:03:44 +02:00
}
2016-03-10 11:32:10 +01:00
/// Blockchain database client. Owns and manages a blockchain and a block queue.
pub trait BlockChainClient : Sync + Send {
/// Get raw block header data by block id.
2016-05-19 11:00:32 +02:00
fn block_header ( & self , id : BlockID ) -> Option < Bytes > ;
2016-03-10 11:32:10 +01:00
/// Get raw block body data by block id.
/// Block body is an RLP list of two items: uncles and transactions.
2016-05-19 11:00:32 +02:00
fn block_body ( & self , id : BlockID ) -> Option < Bytes > ;
2016-03-10 11:32:10 +01:00
/// Get raw block data by block header hash.
2016-05-19 11:00:32 +02:00
fn block ( & self , id : BlockID ) -> Option < Bytes > ;
2016-03-10 11:32:10 +01:00
/// Get block status by block header hash.
2016-05-19 11:00:32 +02:00
fn block_status ( & self , id : BlockID ) -> BlockStatus ;
2016-03-10 11:32:10 +01:00
/// Get block total difficulty.
2016-05-19 11:00:32 +02:00
fn block_total_difficulty ( & self , id : BlockID ) -> Option < U256 > ;
2016-03-10 11:32:10 +01:00
2016-05-26 12:40:29 +02:00
/// Attempt to get address nonce at given block.
/// May not fail on BlockID::Latest.
fn nonce ( & self , address : & Address , id : BlockID ) -> Option < U256 > ;
2016-05-26 12:52:33 +02:00
/// Get address nonce at the latest block's state.
2016-05-26 22:17:55 +02:00
fn latest_nonce ( & self , address : & Address ) -> U256 {
2016-05-26 12:40:29 +02:00
self . nonce ( address , BlockID ::Latest )
. expect ( " nonce will return Some when given BlockID::Latest. nonce was given BlockID::Latest. \
Therefore nonce has returned Some ; qed " )
}
2016-03-10 11:32:10 +01:00
/// Get block hash.
2016-05-19 11:00:32 +02:00
fn block_hash ( & self , id : BlockID ) -> Option < H256 > ;
2016-03-10 11:32:10 +01:00
/// Get address code.
fn code ( & self , address : & Address ) -> Option < Bytes > ;
2016-05-26 11:46:45 +02:00
/// Get address balance at the given block's state.
///
2016-05-26 12:45:43 +02:00
/// May not return None if given BlockID::Latest.
2016-05-26 11:46:45 +02:00
/// Returns None if and only if the block's root hash has been pruned from the DB.
fn balance ( & self , address : & Address , id : BlockID ) -> Option < U256 > ;
2016-03-12 19:51:24 +01:00
2016-05-26 12:45:43 +02:00
/// Get address balance at the latest block's state.
2016-05-26 22:17:55 +02:00
fn latest_balance ( & self , address : & Address ) -> U256 {
2016-05-26 12:45:43 +02:00
self . balance ( address , BlockID ::Latest )
. expect ( " balance will return Some if given BlockID::Latest. balance was given BlockID::Latest \
Therefore balance has returned Some ; qed " )
}
/// Get value of the storage at given position at the given block's state.
2016-05-25 17:35:15 +02:00
///
2016-05-26 12:45:43 +02:00
/// May not return None if given BlockID::Latest.
2016-05-26 11:46:45 +02:00
/// Returns None if and only if the block's root hash has been pruned from the DB.
fn storage_at ( & self , address : & Address , position : & H256 , id : BlockID ) -> Option < H256 > ;
2016-05-25 17:54:20 +02:00
2016-05-26 12:45:43 +02:00
/// Get value of the storage at given position at the latest block's state.
2016-05-26 22:17:55 +02:00
fn latest_storage_at ( & self , address : & Address , position : & H256 ) -> H256 {
2016-05-26 12:45:43 +02:00
self . storage_at ( address , position , BlockID ::Latest )
. expect ( " storage_at will return Some if given BlockID::Latest. storage_at was given BlockID::Latest. \
Therefore storage_at has returned Some ; qed " )
}
2016-03-10 11:32:10 +01:00
/// Get transaction with given hash.
2016-05-19 11:00:32 +02:00
fn transaction ( & self , id : TransactionID ) -> Option < LocalizedTransaction > ;
2016-03-10 11:32:10 +01:00
2016-03-22 16:07:42 +01:00
/// Get uncle with given id.
2016-05-19 11:00:32 +02:00
fn uncle ( & self , id : UncleID ) -> Option < Header > ;
2016-03-22 16:07:42 +01:00
2016-03-20 17:29:39 +01:00
/// Get transaction receipt with given hash.
2016-05-19 11:00:32 +02:00
fn transaction_receipt ( & self , id : TransactionID ) -> Option < LocalizedReceipt > ;
2016-03-20 17:29:39 +01:00
2016-03-10 11:32:10 +01:00
/// Get a tree route between `from` and `to`.
/// See `BlockChain::tree_route`.
fn tree_route ( & self , from : & H256 , to : & H256 ) -> Option < TreeRoute > ;
2016-05-24 21:56:17 +02:00
/// Get all possible uncle hashes for a block.
fn find_uncles ( & self , hash : & H256 ) -> Option < Vec < H256 > > ;
2016-03-10 11:32:10 +01:00
/// Get latest state node
fn state_data ( & self , hash : & H256 ) -> Option < Bytes > ;
/// Get raw block receipts data by block header hash.
fn block_receipts ( & self , hash : & H256 ) -> Option < Bytes > ;
/// Import a block into the blockchain.
fn import_block ( & self , bytes : Bytes ) -> ImportResult ;
/// Get block queue information.
fn queue_info ( & self ) -> BlockQueueInfo ;
/// Clear block queue and abort all import activity.
fn clear_queue ( & self ) ;
/// Get blockchain information.
fn chain_info ( & self ) -> BlockChainInfo ;
/// Get the best block header.
fn best_block_header ( & self ) -> Bytes {
// TODO: lock blockchain only once
2016-05-19 11:00:32 +02:00
self . block_header ( BlockID ::Hash ( self . chain_info ( ) . best_block_hash ) ) . unwrap ( )
2016-03-10 11:32:10 +01:00
}
/// Returns numbers of blocks containing given bloom.
2016-05-19 11:00:32 +02:00
fn blocks_with_bloom ( & self , bloom : & H2048 , from_block : BlockID , to_block : BlockID ) -> Option < Vec < BlockNumber > > ;
2016-03-10 11:32:10 +01:00
/// Returns logs matching given filter.
fn logs ( & self , filter : Filter ) -> Vec < LocalizedLogEntry > ;
2016-03-10 21:17:58 +01:00
2016-03-19 21:37:11 +01:00
/// Makes a non-persistent transaction call.
2016-05-28 16:52:33 +02:00
// TODO: should be able to accept blockchain location for call.
2016-05-31 21:03:44 +02:00
fn call ( & self , t : & SignedTransaction , analytics : CallAnalytics ) -> Result < Executed , ExecutionError > ;
2016-03-23 17:28:02 +01:00
2016-05-19 00:44:49 +02:00
/// Returns EvmFactory.
fn vm_factory ( & self ) -> & EvmFactory ;
2016-05-02 12:17:30 +02:00
/// Returns traces matching given filter.
fn filter_traces ( & self , filter : TraceFilter ) -> Option < Vec < LocalizedTrace > > ;
/// Returns trace with given id.
fn trace ( & self , trace : TraceId ) -> Option < LocalizedTrace > ;
/// Returns traces created by transaction.
2016-05-19 11:00:32 +02:00
fn transaction_traces ( & self , trace : TransactionID ) -> Option < Vec < LocalizedTrace > > ;
2016-05-02 12:17:30 +02:00
/// Returns traces created by transaction from block.
2016-05-19 11:00:32 +02:00
fn block_traces ( & self , trace : BlockID ) -> Option < Vec < LocalizedTrace > > ;
2016-05-02 12:17:30 +02:00
2016-04-28 21:47:44 +02:00
/// Get last hashes starting from best block.
fn last_hashes ( & self ) -> LastHashes ;
2016-05-31 19:52:53 +02:00
/// import transactions from network/other 3rd party
fn import_transactions ( & self , transactions : Vec < SignedTransaction > ) -> Vec < Result < TransactionImportResult , EthError > > ;
2016-06-19 14:35:42 +02:00
/// Queue transactions for importing.
fn queue_transactions ( & self , transactions : Vec < Bytes > ) ;
2016-05-31 19:52:53 +02:00
/// list all transactions
2016-06-27 19:06:54 +02:00
fn pending_transactions ( & self ) -> Vec < SignedTransaction > ;
2016-06-16 12:44:08 +02:00
/// Get the gas price distribution.
fn gas_price_statistics ( & self , sample_size : usize , distribution_size : usize ) -> Result < Vec < U256 > , ( ) > {
let mut h = self . chain_info ( ) . best_block_hash ;
let mut corpus = Vec ::new ( ) ;
for _ in 0 .. sample_size {
let block_bytes = self . block ( BlockID ::Hash ( h ) ) . expect ( " h is either the best_block_hash or an ancestor; qed " ) ;
let block = BlockView ::new ( & block_bytes ) ;
let header = block . header_view ( ) ;
if header . number ( ) = = 0 {
break ;
}
block . transaction_views ( ) . iter ( ) . foreach ( | t | corpus . push ( t . gas_price ( ) ) ) ;
h = header . parent_hash ( ) . clone ( ) ;
}
corpus . sort ( ) ;
let n = corpus . len ( ) ;
if n > 0 {
Ok ( ( 0 .. ( distribution_size + 1 ) )
. map ( | i | corpus [ i * ( n - 1 ) / distribution_size ] )
. collect ::< Vec < _ > > ( )
)
} else {
Err ( ( ) )
}
}
2016-06-18 20:26:44 +02:00
2016-06-23 11:30:48 +02:00
/// Get `Some` gas limit of SOFT_FORK_BLOCK, or `None` if chain is not yet that long.
2016-06-22 19:49:07 +02:00
fn dao_rescue_block_gas_limit ( & self , chain_hash : H256 ) -> Option < U256 > {
2016-06-24 14:20:50 +02:00
const SOFT_FORK_BLOCK : u64 = 1800000 ;
2016-06-22 21:37:29 +02:00
// shortcut if the canon chain is already known.
2016-06-23 11:30:48 +02:00
if self . chain_info ( ) . best_block_number > SOFT_FORK_BLOCK + 1000 {
return self . block_header ( BlockID ::Number ( SOFT_FORK_BLOCK ) ) . map ( | header | HeaderView ::new ( & header ) . gas_limit ( ) ) ;
2016-06-22 21:37:29 +02:00
}
// otherwise check according to `chain_hash`.
2016-06-22 19:49:07 +02:00
if let Some ( mut header ) = self . block_header ( BlockID ::Hash ( chain_hash ) ) {
2016-06-23 11:30:48 +02:00
if HeaderView ::new ( & header ) . number ( ) < SOFT_FORK_BLOCK {
2016-06-22 19:49:07 +02:00
None
} else {
2016-06-23 11:30:48 +02:00
while HeaderView ::new ( & header ) . number ( ) ! = SOFT_FORK_BLOCK {
2016-06-22 19:49:07 +02:00
header = self . block_header ( BlockID ::Hash ( HeaderView ::new ( & header ) . parent_hash ( ) ) ) . expect ( " chain is complete; parent of chain entry must be in chain; qed " ) ;
}
Some ( HeaderView ::new ( & header ) . gas_limit ( ) )
}
} else {
None
}
2016-06-18 20:26:44 +02:00
}
2016-03-10 11:32:10 +01:00
}
2016-05-31 16:41:15 +02:00
/// Extended client interface used for mining
2016-05-31 20:33:26 +02:00
pub trait MiningBlockChainClient : BlockChainClient {
2016-06-06 14:33:12 +02:00
/// Returns OpenBlock prepared for closing.
2016-06-23 14:29:16 +02:00
fn prepare_open_block ( & self , author : Address , gas_range_target : ( U256 , U256 ) , extra_data : Bytes )
2016-06-06 14:33:12 +02:00
-> OpenBlock ;
2016-05-31 16:41:15 +02:00
}