openethereum/ethcore/light/src/provider.rs

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

479 lines
15 KiB
Rust
Raw Normal View History

// Copyright 2015-2019 Parity Technologies (UK) Ltd.
// This file is part of Parity Ethereum.
2016-12-05 16:55:33 +01:00
// Parity Ethereum is free software: you can redistribute it and/or modify
2016-12-05 16:55:33 +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.
// Parity Ethereum is distributed in the hope that it will be useful,
2016-12-05 16:55:33 +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
// along with Parity Ethereum. If not, see <http://www.gnu.org/licenses/>.
2016-12-05 16:55:33 +01:00
//! A provider for the PIP protocol. This is typically a full node, who can
2016-12-05 16:55:33 +01:00
//! give as much data as necessary to its peers.
use std::sync::Arc;
use common_types::{
blockchain_info::BlockChainInfo, encoded, ids::BlockId, transaction::PendingTransaction,
`Client` refactoring (#7038) * Improves `BestBlock` comment * Improves `TraceDB` comment * Improves `journaldb::Algorithm` comment. Probably the whole enum should be renamed to `Strategy` or something alike. * Comments some of the `Client`'s fields * Deglobs client imports * Fixes comments * Extracts `import_lock` to `Importer` struct * Extracts `verifier` to `Importer` struct * Extracts `block_queue` to `Importer` struct * Extracts `miner` to `Importer` struct * Extracts `ancient_verifier` to `Importer` struct * Extracts `rng` to `Importer` struct * Extracts `import_old_block` to `Importer` struct * Adds `Nonce` trait * Adds `Balance` trait * Adds `ChainInfo` trait * Fixes imports for tests using `chain_info` method * Adds `BlockInfo` trait * Adds more `ChainInfo` imports * Adds `BlockInfo` imports * Adds `ReopenBlock` trait * Adds `PrepareOpenBlock` trait * Fixes import in tests * Adds `CallContract` trait * Fixes imports in tests using `call_contract` method * Adds `TransactionInfo` trait * Adds `RegistryInfo` trait * Fixes imports in tests using `registry_address` method * Adds `ScheduleInfo` trait * Adds `ImportSealedBlock` trait * Fixes imports in test using `import_sealed_block` method * Adds `BroadcastProposalBlock` trait * Migrates `Miner` to static dispatch * Fixes tests * Moves `calculate_enacted_retracted` to `Importer` * Moves import-related methods to `Importer` * Removes redundant `import_old_block` wrapper * Extracts `import_block*` into separate trait * Fixes tests * Handles `Pending` in `LightFetch` * Handles `Pending` in filters * Handles `Pending` in `ParityClient` * Handles `Pending` in `EthClient` * Removes `BlockId::Pending`, partly refactors dependent code * Adds `StateInfo` trait * Exports `StateOrBlock` and `BlockChain` types from `client` module * Refactors `balance` RPC using generic API * Refactors `storage_at` RPC using generic API * Makes `MinerService::pending_state`'s return type dynamic * Adds `StateOrBlock` and `BlockChain` types * Adds impl of `client::BlockChain` for `Client` * Exports `StateInfo` trait from `client` module * Missing `self` use To be fixed up to "Adds impl of `client::BlockChain` for `Client`" * Adds `number_to_id` and refactors dependent RPC methods * Refactors `code_at` using generic API * Adds `StateClient` trait * Refactors RPC to use `StateClient` trait * Reverts `client::BlockChain` trait stuff, refactors methods to accept `StateOrBlock` * Refactors TestClient * Adds helper function `block_number_to_id` * Uses `block_number_to_id` instead of local function * Handles `Pending` in `list_accounts` and `list_storage_keys` * Attempt to use associated types for state instead of trait objects * Simplifies `state_at_beginning` * Extracts `call` and `call_many` into separate trait * Refactors `build_last_hashes` to accept reference * Exports `Call` type from the module * Refactors `call` and `call_many` to accept state and header * Exports `state_at` in `StateClient` * Exports `pending_block_header` from `MinerService` * Refactors RPC `call` method using new API * Adds missing parentheses * Refactors `parity::call` to use new call API * Update .gitlab-ci.yml fix gitlab lint * Fixes error handling * Refactors `traces::call` and `call_many` to use new call API * Refactors `call_contract` * Refactors `block_header` * Refactors internal RPC method `block` * Moves `estimate_gas` to `Call` trait, refactors parameters * Refactors `estimate_gas` in RPC * Refactors `uncle` * Refactors RPC `transaction` * Covers missing branches * Makes it all compile, fixes compiler grumbles * Adds casts in `blockchain` module * Fixes `PendingBlock` tests, work on `MinerService` * Adds test stubs for StateClient and EngineInfo * Makes `state_db` public * Adds missing impls for `TestBlockChainClient` * Adds trait documentation * Adds missing docs to the `state_db` module * Fixes trivial compilation errors * Moves `code_hash` method to a `BlockInfo` trait * Refactors `Verifier` to be generic over client * Refactors `TransactionFilter` to be generic over client * Refactors `Miner` and `Client` to reflect changes in verifier and txfilter API * Moves `ServiceTransactionChecker` back to `ethcore` * Fixes trait bounds in `Miner` API * Fixes `Client` * Fixes lifetime bound in `FullFamilyParams` * Adds comments to `FullFamilyParams` * Fixes imports in `ethcore` * Fixes BlockNumber handling in `code_at` and `replay_block_transactions` * fix compile issues * First step to redundant trait merge * Fixes compilation error in RPC tests * Adds mock `State` as a stub for `TestClient` * Handles `StateOrBlock::State` in `TestBlockChainClient::balance` * Fixes `transaction_count` RPC * Fixes `transaction_count` * Moves `service_transaction.json` to the `contracts` subfolder * Fixes compilation errors in tests * Refactors client to use `AccountData` * Refactors client to use `BlockChain` * Refactors miner to use aggregate traits * Adds `SealedBlockImporter` trait * Refactors miner to use `SealedBlockImporter` trait * Removes unused imports * Simplifies `RegistryInfo::registry_address` * Fixes indentation * Removes commented out trait bound
2018-03-03 18:42:13 +01:00
};
use ethcore::client::{
BlockChainClient, BlockInfo as ClientBlockInfo, ChainInfo, ProvingBlockChainClient,
2020-08-05 06:08:03 +02:00
};
use ethereum_types::H256;
use parking_lot::RwLock;
2016-12-05 16:55:33 +01:00
2017-02-03 18:47:03 +01:00
use cht::{self, BlockInfo};
use client::{AsLightClient, LightChainClient};
use transaction_queue::TransactionQueue;
2017-02-03 18:47:03 +01:00
2016-12-05 17:09:05 +01:00
use request;
2016-12-05 16:55:33 +01:00
/// Maximum allowed size of a headers request.
pub const MAX_HEADERS_PER_REQUEST: u64 = 512;
/// Defines the operations that a provider for the light subprotocol must fulfill.
2016-12-05 16:55:33 +01:00
pub trait Provider: Send + Sync {
/// Provide current blockchain info.
fn chain_info(&self) -> BlockChainInfo;
2020-08-05 06:08:03 +02:00
2016-12-05 16:55:33 +01:00
/// Find the depth of a common ancestor between two blocks.
/// If either block is unknown or an ancestor can't be found
/// then return `None`.
fn reorg_depth(&self, a: &H256, b: &H256) -> Option<u64>;
2020-08-05 06:08:03 +02:00
2016-12-05 16:55:33 +01:00
/// Earliest block where state queries are available.
/// If `None`, no state queries are servable.
fn earliest_state(&self) -> Option<u64>;
2020-08-05 06:08:03 +02:00
2016-12-05 16:55:33 +01:00
/// Provide a list of headers starting at the requested block,
/// possibly in reverse and skipping `skip` at a time.
///
/// The returned vector may have any length in the range [0, `max`], but the
/// results within must adhere to the `skip` and `reverse` parameters.
fn block_headers(
&self,
req: request::CompleteHeadersRequest,
) -> Option<request::HeadersResponse> {
use request::HashOrNumber;
2020-08-05 06:08:03 +02:00
if req.max == 0 {
return None;
}
2020-08-05 06:08:03 +02:00
let best_num = self.chain_info().best_block_number;
let start_num = match req.start {
HashOrNumber::Number(start_num) => start_num,
HashOrNumber::Hash(hash) => match self.block_header(BlockId::Hash(hash)) {
None => {
trace!(target: "pip_provider", "Unknown block hash {} requested", hash);
return None;
}
Some(header) => {
let num = header.number();
let canon_hash = self.block_header(BlockId::Number(num)).map(|h| h.hash());
2020-08-05 06:08:03 +02:00
if req.max == 1 || canon_hash != Some(hash) {
// Non-canonical header or single header requested.
return Some(::request::HeadersResponse {
headers: vec![header],
});
}
2020-08-05 06:08:03 +02:00
num
}
2016-12-05 16:55:33 +01:00
},
};
2020-08-05 06:08:03 +02:00
let max = ::std::cmp::min(MAX_HEADERS_PER_REQUEST, req.max);
2020-08-05 06:08:03 +02:00
let headers: Vec<_> = (0_u64..max)
.map(|x: u64| x.saturating_mul(req.skip.saturating_add(1)))
.take_while(|&x| {
if req.reverse {
x < start_num
} else {
best_num.saturating_sub(start_num) >= x
2020-08-05 06:08:03 +02:00
}
})
.map(|x| {
if req.reverse {
start_num.saturating_sub(x)
} else {
start_num.saturating_add(x)
2020-08-05 06:08:03 +02:00
}
})
.map(|x| self.block_header(BlockId::Number(x)))
2016-12-05 16:55:33 +01:00
.take_while(|x| x.is_some())
.flat_map(|x| x)
.collect();
2020-08-05 06:08:03 +02:00
if headers.is_empty() {
None
} else {
Some(::request::HeadersResponse { headers })
}
2016-12-05 16:55:33 +01:00
}
2020-08-05 06:08:03 +02:00
/// Get a block header by id.
fn block_header(&self, id: BlockId) -> Option<encoded::Header>;
2020-08-05 06:08:03 +02:00
/// Get a transaction index by hash.
fn transaction_index(
&self,
req: request::CompleteTransactionIndexRequest,
) -> Option<request::TransactionIndexResponse>;
2020-08-05 06:08:03 +02:00
/// Fulfill a block body request.
fn block_body(&self, req: request::CompleteBodyRequest) -> Option<request::BodyResponse>;
2020-08-05 06:08:03 +02:00
/// Fulfill a request for block receipts.
fn block_receipts(
&self,
req: request::CompleteReceiptsRequest,
) -> Option<request::ReceiptsResponse>;
2020-08-05 06:08:03 +02:00
/// Get an account proof.
fn account_proof(
&self,
req: request::CompleteAccountRequest,
) -> Option<request::AccountResponse>;
2020-08-05 06:08:03 +02:00
/// Get a storage proof.
fn storage_proof(
&self,
req: request::CompleteStorageRequest,
) -> Option<request::StorageResponse>;
2020-08-05 06:08:03 +02:00
/// Provide contract code for the specified (block_hash, code_hash) pair.
fn contract_code(&self, req: request::CompleteCodeRequest) -> Option<request::CodeResponse>;
2020-08-05 06:08:03 +02:00
/// Provide a header proof from a given Canonical Hash Trie as well as the
/// corresponding header.
fn header_proof(
&self,
req: request::CompleteHeaderProofRequest,
) -> Option<request::HeaderProofResponse>;
2020-08-05 06:08:03 +02:00
/// Provide pending transactions.
fn transactions_to_propagate(&self) -> Vec<PendingTransaction>;
2020-08-05 06:08:03 +02:00
/// Provide a proof-of-execution for the given transaction proof request.
/// Returns a vector of all state items necessary to execute the transaction.
fn transaction_proof(
&self,
req: request::CompleteExecutionRequest,
) -> Option<request::ExecutionResponse>;
2020-08-05 06:08:03 +02:00
/// Provide epoch signal data at given block hash. This should be just the
fn epoch_signal(&self, req: request::CompleteSignalRequest) -> Option<request::SignalResponse>;
}
// Implementation of a light client data provider for a client.
impl<T: ProvingBlockChainClient + ?Sized> Provider for T {
fn chain_info(&self) -> BlockChainInfo {
`Client` refactoring (#7038) * Improves `BestBlock` comment * Improves `TraceDB` comment * Improves `journaldb::Algorithm` comment. Probably the whole enum should be renamed to `Strategy` or something alike. * Comments some of the `Client`'s fields * Deglobs client imports * Fixes comments * Extracts `import_lock` to `Importer` struct * Extracts `verifier` to `Importer` struct * Extracts `block_queue` to `Importer` struct * Extracts `miner` to `Importer` struct * Extracts `ancient_verifier` to `Importer` struct * Extracts `rng` to `Importer` struct * Extracts `import_old_block` to `Importer` struct * Adds `Nonce` trait * Adds `Balance` trait * Adds `ChainInfo` trait * Fixes imports for tests using `chain_info` method * Adds `BlockInfo` trait * Adds more `ChainInfo` imports * Adds `BlockInfo` imports * Adds `ReopenBlock` trait * Adds `PrepareOpenBlock` trait * Fixes import in tests * Adds `CallContract` trait * Fixes imports in tests using `call_contract` method * Adds `TransactionInfo` trait * Adds `RegistryInfo` trait * Fixes imports in tests using `registry_address` method * Adds `ScheduleInfo` trait * Adds `ImportSealedBlock` trait * Fixes imports in test using `import_sealed_block` method * Adds `BroadcastProposalBlock` trait * Migrates `Miner` to static dispatch * Fixes tests * Moves `calculate_enacted_retracted` to `Importer` * Moves import-related methods to `Importer` * Removes redundant `import_old_block` wrapper * Extracts `import_block*` into separate trait * Fixes tests * Handles `Pending` in `LightFetch` * Handles `Pending` in filters * Handles `Pending` in `ParityClient` * Handles `Pending` in `EthClient` * Removes `BlockId::Pending`, partly refactors dependent code * Adds `StateInfo` trait * Exports `StateOrBlock` and `BlockChain` types from `client` module * Refactors `balance` RPC using generic API * Refactors `storage_at` RPC using generic API * Makes `MinerService::pending_state`'s return type dynamic * Adds `StateOrBlock` and `BlockChain` types * Adds impl of `client::BlockChain` for `Client` * Exports `StateInfo` trait from `client` module * Missing `self` use To be fixed up to "Adds impl of `client::BlockChain` for `Client`" * Adds `number_to_id` and refactors dependent RPC methods * Refactors `code_at` using generic API * Adds `StateClient` trait * Refactors RPC to use `StateClient` trait * Reverts `client::BlockChain` trait stuff, refactors methods to accept `StateOrBlock` * Refactors TestClient * Adds helper function `block_number_to_id` * Uses `block_number_to_id` instead of local function * Handles `Pending` in `list_accounts` and `list_storage_keys` * Attempt to use associated types for state instead of trait objects * Simplifies `state_at_beginning` * Extracts `call` and `call_many` into separate trait * Refactors `build_last_hashes` to accept reference * Exports `Call` type from the module * Refactors `call` and `call_many` to accept state and header * Exports `state_at` in `StateClient` * Exports `pending_block_header` from `MinerService` * Refactors RPC `call` method using new API * Adds missing parentheses * Refactors `parity::call` to use new call API * Update .gitlab-ci.yml fix gitlab lint * Fixes error handling * Refactors `traces::call` and `call_many` to use new call API * Refactors `call_contract` * Refactors `block_header` * Refactors internal RPC method `block` * Moves `estimate_gas` to `Call` trait, refactors parameters * Refactors `estimate_gas` in RPC * Refactors `uncle` * Refactors RPC `transaction` * Covers missing branches * Makes it all compile, fixes compiler grumbles * Adds casts in `blockchain` module * Fixes `PendingBlock` tests, work on `MinerService` * Adds test stubs for StateClient and EngineInfo * Makes `state_db` public * Adds missing impls for `TestBlockChainClient` * Adds trait documentation * Adds missing docs to the `state_db` module * Fixes trivial compilation errors * Moves `code_hash` method to a `BlockInfo` trait * Refactors `Verifier` to be generic over client * Refactors `TransactionFilter` to be generic over client * Refactors `Miner` and `Client` to reflect changes in verifier and txfilter API * Moves `ServiceTransactionChecker` back to `ethcore` * Fixes trait bounds in `Miner` API * Fixes `Client` * Fixes lifetime bound in `FullFamilyParams` * Adds comments to `FullFamilyParams` * Fixes imports in `ethcore` * Fixes BlockNumber handling in `code_at` and `replay_block_transactions` * fix compile issues * First step to redundant trait merge * Fixes compilation error in RPC tests * Adds mock `State` as a stub for `TestClient` * Handles `StateOrBlock::State` in `TestBlockChainClient::balance` * Fixes `transaction_count` RPC * Fixes `transaction_count` * Moves `service_transaction.json` to the `contracts` subfolder * Fixes compilation errors in tests * Refactors client to use `AccountData` * Refactors client to use `BlockChain` * Refactors miner to use aggregate traits * Adds `SealedBlockImporter` trait * Refactors miner to use `SealedBlockImporter` trait * Removes unused imports * Simplifies `RegistryInfo::registry_address` * Fixes indentation * Removes commented out trait bound
2018-03-03 18:42:13 +01:00
ChainInfo::chain_info(self)
}
2020-08-05 06:08:03 +02:00
fn reorg_depth(&self, a: &H256, b: &H256) -> Option<u64> {
self.tree_route(a, b).map(|route| route.index as u64)
}
2020-08-05 06:08:03 +02:00
fn earliest_state(&self) -> Option<u64> {
Some(self.pruning_info().earliest_state)
}
2020-08-05 06:08:03 +02:00
fn block_header(&self, id: BlockId) -> Option<encoded::Header> {
`Client` refactoring (#7038) * Improves `BestBlock` comment * Improves `TraceDB` comment * Improves `journaldb::Algorithm` comment. Probably the whole enum should be renamed to `Strategy` or something alike. * Comments some of the `Client`'s fields * Deglobs client imports * Fixes comments * Extracts `import_lock` to `Importer` struct * Extracts `verifier` to `Importer` struct * Extracts `block_queue` to `Importer` struct * Extracts `miner` to `Importer` struct * Extracts `ancient_verifier` to `Importer` struct * Extracts `rng` to `Importer` struct * Extracts `import_old_block` to `Importer` struct * Adds `Nonce` trait * Adds `Balance` trait * Adds `ChainInfo` trait * Fixes imports for tests using `chain_info` method * Adds `BlockInfo` trait * Adds more `ChainInfo` imports * Adds `BlockInfo` imports * Adds `ReopenBlock` trait * Adds `PrepareOpenBlock` trait * Fixes import in tests * Adds `CallContract` trait * Fixes imports in tests using `call_contract` method * Adds `TransactionInfo` trait * Adds `RegistryInfo` trait * Fixes imports in tests using `registry_address` method * Adds `ScheduleInfo` trait * Adds `ImportSealedBlock` trait * Fixes imports in test using `import_sealed_block` method * Adds `BroadcastProposalBlock` trait * Migrates `Miner` to static dispatch * Fixes tests * Moves `calculate_enacted_retracted` to `Importer` * Moves import-related methods to `Importer` * Removes redundant `import_old_block` wrapper * Extracts `import_block*` into separate trait * Fixes tests * Handles `Pending` in `LightFetch` * Handles `Pending` in filters * Handles `Pending` in `ParityClient` * Handles `Pending` in `EthClient` * Removes `BlockId::Pending`, partly refactors dependent code * Adds `StateInfo` trait * Exports `StateOrBlock` and `BlockChain` types from `client` module * Refactors `balance` RPC using generic API * Refactors `storage_at` RPC using generic API * Makes `MinerService::pending_state`'s return type dynamic * Adds `StateOrBlock` and `BlockChain` types * Adds impl of `client::BlockChain` for `Client` * Exports `StateInfo` trait from `client` module * Missing `self` use To be fixed up to "Adds impl of `client::BlockChain` for `Client`" * Adds `number_to_id` and refactors dependent RPC methods * Refactors `code_at` using generic API * Adds `StateClient` trait * Refactors RPC to use `StateClient` trait * Reverts `client::BlockChain` trait stuff, refactors methods to accept `StateOrBlock` * Refactors TestClient * Adds helper function `block_number_to_id` * Uses `block_number_to_id` instead of local function * Handles `Pending` in `list_accounts` and `list_storage_keys` * Attempt to use associated types for state instead of trait objects * Simplifies `state_at_beginning` * Extracts `call` and `call_many` into separate trait * Refactors `build_last_hashes` to accept reference * Exports `Call` type from the module * Refactors `call` and `call_many` to accept state and header * Exports `state_at` in `StateClient` * Exports `pending_block_header` from `MinerService` * Refactors RPC `call` method using new API * Adds missing parentheses * Refactors `parity::call` to use new call API * Update .gitlab-ci.yml fix gitlab lint * Fixes error handling * Refactors `traces::call` and `call_many` to use new call API * Refactors `call_contract` * Refactors `block_header` * Refactors internal RPC method `block` * Moves `estimate_gas` to `Call` trait, refactors parameters * Refactors `estimate_gas` in RPC * Refactors `uncle` * Refactors RPC `transaction` * Covers missing branches * Makes it all compile, fixes compiler grumbles * Adds casts in `blockchain` module * Fixes `PendingBlock` tests, work on `MinerService` * Adds test stubs for StateClient and EngineInfo * Makes `state_db` public * Adds missing impls for `TestBlockChainClient` * Adds trait documentation * Adds missing docs to the `state_db` module * Fixes trivial compilation errors * Moves `code_hash` method to a `BlockInfo` trait * Refactors `Verifier` to be generic over client * Refactors `TransactionFilter` to be generic over client * Refactors `Miner` and `Client` to reflect changes in verifier and txfilter API * Moves `ServiceTransactionChecker` back to `ethcore` * Fixes trait bounds in `Miner` API * Fixes `Client` * Fixes lifetime bound in `FullFamilyParams` * Adds comments to `FullFamilyParams` * Fixes imports in `ethcore` * Fixes BlockNumber handling in `code_at` and `replay_block_transactions` * fix compile issues * First step to redundant trait merge * Fixes compilation error in RPC tests * Adds mock `State` as a stub for `TestClient` * Handles `StateOrBlock::State` in `TestBlockChainClient::balance` * Fixes `transaction_count` RPC * Fixes `transaction_count` * Moves `service_transaction.json` to the `contracts` subfolder * Fixes compilation errors in tests * Refactors client to use `AccountData` * Refactors client to use `BlockChain` * Refactors miner to use aggregate traits * Adds `SealedBlockImporter` trait * Refactors miner to use `SealedBlockImporter` trait * Removes unused imports * Simplifies `RegistryInfo::registry_address` * Fixes indentation * Removes commented out trait bound
2018-03-03 18:42:13 +01:00
ClientBlockInfo::block_header(self, id)
}
2020-08-05 06:08:03 +02:00
fn transaction_index(
&self,
req: request::CompleteTransactionIndexRequest,
) -> Option<request::TransactionIndexResponse> {
use common_types::ids::TransactionId;
2020-08-05 06:08:03 +02:00
self.transaction_receipt(TransactionId::Hash(req.hash))
.map(|receipt| request::TransactionIndexResponse {
num: receipt.block_number,
hash: receipt.block_hash,
index: receipt.transaction_index as u64,
})
}
2020-08-05 06:08:03 +02:00
fn block_body(&self, req: request::CompleteBodyRequest) -> Option<request::BodyResponse> {
BlockChainClient::block_body(self, BlockId::Hash(req.hash))
.map(|body| ::request::BodyResponse { body })
}
2020-08-05 06:08:03 +02:00
fn block_receipts(
&self,
req: request::CompleteReceiptsRequest,
) -> Option<request::ReceiptsResponse> {
BlockChainClient::block_receipts(self, &req.hash).map(|x| ::request::ReceiptsResponse {
receipts: x.receipts,
})
}
2020-08-05 06:08:03 +02:00
fn account_proof(
&self,
req: request::CompleteAccountRequest,
) -> Option<request::AccountResponse> {
self.prove_account(req.address_hash, BlockId::Hash(req.block_hash))
.map(|(proof, acc)| ::request::AccountResponse {
proof,
nonce: acc.nonce,
balance: acc.balance,
code_hash: acc.code_hash,
storage_root: acc.storage_root,
})
}
2020-08-05 06:08:03 +02:00
fn storage_proof(
&self,
req: request::CompleteStorageRequest,
) -> Option<request::StorageResponse> {
self.prove_storage(
req.address_hash,
req.key_hash,
BlockId::Hash(req.block_hash),
)
.map(|(proof, item)| ::request::StorageResponse { proof, value: item })
}
2020-08-05 06:08:03 +02:00
fn contract_code(&self, req: request::CompleteCodeRequest) -> Option<request::CodeResponse> {
self.state_data(&req.code_hash)
.map(|code| ::request::CodeResponse { code })
}
2020-08-05 06:08:03 +02:00
fn header_proof(
&self,
req: request::CompleteHeaderProofRequest,
) -> Option<request::HeaderProofResponse> {
let cht_number = match cht::block_to_cht_number(req.num) {
Some(cht_num) => cht_num,
None => {
debug!(target: "pip_provider", "Requested CHT proof with invalid block number");
return None;
}
};
2020-08-05 06:08:03 +02:00
let mut needed = None;
2020-08-05 06:08:03 +02:00
2017-02-03 18:47:03 +01:00
// build the CHT, caching the requested header as we pass through it.
let cht = {
let block_info = |id| {
let hdr = self.block_header(id);
let td = self.block_total_difficulty(id);
2020-08-05 06:08:03 +02:00
2017-02-03 18:47:03 +01:00
match (hdr, td) {
(Some(hdr), Some(td)) => {
let info = BlockInfo {
hash: hdr.hash(),
parent_hash: hdr.parent_hash(),
total_difficulty: td,
};
2020-08-05 06:08:03 +02:00
if hdr.number() == req.num {
needed = Some((hdr, td));
2017-02-03 18:47:03 +01:00
}
2020-08-05 06:08:03 +02:00
2017-02-03 18:47:03 +01:00
Some(info)
2017-01-16 17:10:30 +01:00
}
2017-02-03 18:47:03 +01:00
_ => None,
2017-01-16 17:10:30 +01:00
}
2017-02-03 18:47:03 +01:00
};
2020-08-05 06:08:03 +02:00
match cht::build(cht_number, block_info) {
2017-02-03 18:47:03 +01:00
Some(cht) => cht,
None => return None, // incomplete CHT.
2017-01-16 17:10:30 +01:00
}
2017-02-03 18:47:03 +01:00
};
2020-08-05 06:08:03 +02:00
let (needed_hdr, needed_td) =
needed.expect("`needed` always set in loop, number checked before; qed");
2020-08-05 06:08:03 +02:00
2017-02-03 18:47:03 +01:00
// prove our result.
match cht.prove(req.num, 0) {
Ok(Some(proof)) => Some(::request::HeaderProofResponse {
proof,
hash: needed_hdr.hash(),
td: needed_td,
}),
2017-02-03 18:47:03 +01:00
Ok(None) => None,
Err(e) => {
debug!(target: "pip_provider", "Error looking up number in freshly-created CHT: {}", e);
2017-02-03 18:47:03 +01:00
None
2017-01-16 17:10:30 +01:00
}
2016-12-05 16:55:33 +01:00
}
2020-08-05 06:08:03 +02:00
}
fn transaction_proof(
&self,
req: request::CompleteExecutionRequest,
) -> Option<request::ExecutionResponse> {
use common_types::transaction::Transaction;
2020-08-05 06:08:03 +02:00
let id = BlockId::Hash(req.block_hash);
let nonce = match self.nonce(&req.from, id) {
Some(nonce) => nonce,
None => return None,
};
let transaction = Transaction {
nonce,
gas: req.gas,
gas_price: req.gas_price,
action: req.action,
value: req.value,
data: req.data,
}
.fake_sign(req.from);
2020-08-05 06:08:03 +02:00
self.prove_transaction(transaction, id)
2017-04-19 14:58:19 +02:00
.map(|(_, proof)| ::request::ExecutionResponse { items: proof })
}
2020-08-05 06:08:03 +02:00
fn transactions_to_propagate(&self) -> Vec<PendingTransaction> {
BlockChainClient::transactions_to_propagate(self)
New Transaction Queue implementation (#8074) * Implementation of Verifier, Scoring and Ready. * Queue in progress. * TransactionPool. * Prepare for txpool release. * Miner refactor [WiP] * WiP reworking miner. * Make it compile. * Add some docs. * Split blockchain access to a separate file. * Work on miner API. * Fix ethcore tests. * Refactor miner interface for sealing/work packages. * Implement next nonce. * RPC compiles. * Implement couple of missing methdods for RPC. * Add transaction queue listeners. * Compiles! * Clean-up and parallelize. * Get rid of RefCell in header. * Revert "Get rid of RefCell in header." This reverts commit 0f2424c9b7319a786e1565ea2a8a6d801a21b4fb. * Override Sync requirement. * Fix status display. * Unify logging. * Extract some cheap checks. * Measurements and optimizations. * Fix scoring bug, heap size of bug and add cache * Disable tx queueing and parallel verification. * Make ethcore and ethcore-miner compile again. * Make RPC compile again. * Bunch of txpool tests. * Migrate transaction queue tests. * Nonce Cap * Nonce cap cache and tests. * Remove stale future transactions from the queue. * Optimize scoring and write some tests. * Simple penalization. * Clean up and support for different scoring algorithms. * Add CLI parameters for the new queue. * Remove banning queue. * Disable debug build. * Change per_sender limit to be 1% instead of 5% * Avoid cloning when propagating transactions. * Remove old todo. * Post-review fixes. * Fix miner options default. * Implement back ready transactions for light client. * Get rid of from_pending_block * Pass rejection reason. * Add more details to drop. * Rollback heap size of. * Avoid cloning hashes when propagating and include more details on rejection. * Fix tests. * Introduce nonces cache. * Remove uneccessary hashes allocation. * Lower the mem limit. * Re-enable parallel verification. * Add miner log. Don't check the type if not below min_gas_price. * Add more traces, fix disabling miner. * Fix creating pending blocks twice on AuRa authorities. * Fix tests. * re-use pending blocks in AuRa * Use reseal_min_period to prevent too frequent update_sealing. * Fix log to contain hash not sender. * Optimize local transactions. * Fix aura tests. * Update locks comments. * Get rid of unsafe Sync impl. * Review fixes. * Remove excessive matches. * Fix compilation errors. * Use new pool in private transactions. * Fix private-tx test. * Fix secret store tests. * Actually use gas_floor_target * Fix config tests. * Fix pool tests. * Address grumbles.
2018-04-13 17:34:27 +02:00
.into_iter()
.map(|tx| tx.pending().clone())
.collect()
2016-12-05 16:55:33 +01:00
}
2020-08-05 06:08:03 +02:00
fn epoch_signal(&self, req: request::CompleteSignalRequest) -> Option<request::SignalResponse> {
self.epoch_signal(req.block_hash)
.map(|signal| request::SignalResponse { signal })
}
2016-12-15 18:19:19 +01:00
}
2017-01-16 17:42:39 +01:00
/// The light client "provider" implementation. This wraps a `LightClient` and
/// a light transaction queue.
pub struct LightProvider<L> {
client: Arc<L>,
txqueue: Arc<RwLock<TransactionQueue>>,
}
impl<L> LightProvider<L> {
/// Create a new `LightProvider` from the given client and transaction queue.
pub fn new(client: Arc<L>, txqueue: Arc<RwLock<TransactionQueue>>) -> Self {
LightProvider { client, txqueue }
}
}
// TODO: draw from cache (shared between this and the RPC layer)
impl<L: AsLightClient + Send + Sync> Provider for LightProvider<L> {
fn chain_info(&self) -> BlockChainInfo {
self.client.as_light_client().chain_info()
}
2020-08-05 06:08:03 +02:00
fn reorg_depth(&self, _a: &H256, _b: &H256) -> Option<u64> {
None
}
2020-08-05 06:08:03 +02:00
fn earliest_state(&self) -> Option<u64> {
None
}
2020-08-05 06:08:03 +02:00
fn block_header(&self, id: BlockId) -> Option<encoded::Header> {
self.client.as_light_client().block_header(id)
}
2020-08-05 06:08:03 +02:00
fn transaction_index(
&self,
_req: request::CompleteTransactionIndexRequest,
2017-10-16 18:18:43 +02:00
) -> Option<request::TransactionIndexResponse> {
None
}
2020-08-05 06:08:03 +02:00
fn block_body(&self, _req: request::CompleteBodyRequest) -> Option<request::BodyResponse> {
None
}
2020-08-05 06:08:03 +02:00
fn block_receipts(
&self,
_req: request::CompleteReceiptsRequest,
) -> Option<request::ReceiptsResponse> {
None
}
2020-08-05 06:08:03 +02:00
fn account_proof(
&self,
_req: request::CompleteAccountRequest,
) -> Option<request::AccountResponse> {
None
}
2020-08-05 06:08:03 +02:00
fn storage_proof(
&self,
_req: request::CompleteStorageRequest,
) -> Option<request::StorageResponse> {
None
}
2020-08-05 06:08:03 +02:00
fn contract_code(&self, _req: request::CompleteCodeRequest) -> Option<request::CodeResponse> {
None
}
2020-08-05 06:08:03 +02:00
fn header_proof(
&self,
_req: request::CompleteHeaderProofRequest,
) -> Option<request::HeaderProofResponse> {
None
}
2020-08-05 06:08:03 +02:00
fn transaction_proof(
&self,
_req: request::CompleteExecutionRequest,
) -> Option<request::ExecutionResponse> {
None
}
2020-08-05 06:08:03 +02:00
fn epoch_signal(
&self,
_req: request::CompleteSignalRequest,
) -> Option<request::SignalResponse> {
None
}
2020-08-05 06:08:03 +02:00
fn transactions_to_propagate(&self) -> Vec<PendingTransaction> {
let chain_info = self.chain_info();
self.txqueue.read().ready_transactions(
chain_info.best_block_number,
chain_info.best_block_timestamp,
)
}
}
impl<L: AsLightClient> AsLightClient for LightProvider<L> {
type Client = L::Client;
fn as_light_client(&self) -> &L::Client {
self.client.as_light_client()
}
}
2017-01-16 17:42:39 +01:00
#[cfg(test)]
mod tests {
use super::Provider;
use ethcore::client::{EachBlockWith, TestBlockChainClient};
#[test]
fn cht_proof() {
let client = TestBlockChainClient::new();
client.add_blocks(2000, EachBlockWith::Nothing);
let req = ::request::CompleteHeaderProofRequest { num: 1500 };
2017-01-16 17:42:39 +01:00
assert!(client.header_proof(req.clone()).is_none());
client.add_blocks(48, EachBlockWith::Nothing);
assert!(client.header_proof(req.clone()).is_some());
}
}