RPC: parity_getBlockReceipts (#9527)
* Block receipts RPC. * Use lazy evaluation of block receipts (ecrecover). * Optimize transaction_receipt to prevent performance regression. * Fix RPC grumbles. * Add block & transaction receipt tests. * Fix conversion to block id.
This commit is contained in:
committed by
Marek Kotewicz
parent
3f95a62e4f
commit
cc963d42a0
@@ -46,7 +46,7 @@ use v1::helpers::{SyncPollFilter, PollManager};
|
||||
use v1::helpers::light_fetch::{self, LightFetch};
|
||||
use v1::traits::Eth;
|
||||
use v1::types::{
|
||||
RichBlock, Block, BlockTransactions, BlockNumber, Bytes, SyncStatus, SyncInfo,
|
||||
RichBlock, Block, BlockTransactions, BlockNumber, LightBlockNumber, Bytes, SyncStatus, SyncInfo,
|
||||
Transaction, CallRequest, Index, Filter, Log, Receipt, Work,
|
||||
H64 as RpcH64, H256 as RpcH256, H160 as RpcH160, U256 as RpcU256,
|
||||
};
|
||||
@@ -67,23 +67,6 @@ pub struct EthClient<T> {
|
||||
gas_price_percentile: usize,
|
||||
}
|
||||
|
||||
impl<T> EthClient<T> {
|
||||
fn num_to_id(num: BlockNumber) -> BlockId {
|
||||
// Note: Here we treat `Pending` as `Latest`.
|
||||
// Since light clients don't produce pending blocks
|
||||
// (they don't have state) we can safely fallback to `Latest`.
|
||||
match num {
|
||||
BlockNumber::Num(n) => BlockId::Number(n),
|
||||
BlockNumber::Earliest => BlockId::Earliest,
|
||||
BlockNumber::Latest => BlockId::Latest,
|
||||
BlockNumber::Pending => {
|
||||
warn!("`Pending` is deprecated and may be removed in future versions. Falling back to `Latest`");
|
||||
BlockId::Latest
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Clone for EthClient<T> {
|
||||
fn clone(&self) -> Self {
|
||||
// each instance should have its own poll manager.
|
||||
@@ -285,7 +268,7 @@ impl<T: LightChainClient + 'static> Eth for EthClient<T> {
|
||||
}
|
||||
|
||||
fn balance(&self, address: RpcH160, num: Trailing<BlockNumber>) -> BoxFuture<RpcU256> {
|
||||
Box::new(self.fetcher().account(address.into(), Self::num_to_id(num.unwrap_or_default()))
|
||||
Box::new(self.fetcher().account(address.into(), num.unwrap_or_default().to_block_id())
|
||||
.map(|acc| acc.map_or(0.into(), |a| a.balance).into()))
|
||||
}
|
||||
|
||||
@@ -298,11 +281,11 @@ impl<T: LightChainClient + 'static> Eth for EthClient<T> {
|
||||
}
|
||||
|
||||
fn block_by_number(&self, num: BlockNumber, include_txs: bool) -> BoxFuture<Option<RichBlock>> {
|
||||
Box::new(self.rich_block(Self::num_to_id(num), include_txs).map(Some))
|
||||
Box::new(self.rich_block(num.to_block_id(), include_txs).map(Some))
|
||||
}
|
||||
|
||||
fn transaction_count(&self, address: RpcH160, num: Trailing<BlockNumber>) -> BoxFuture<RpcU256> {
|
||||
Box::new(self.fetcher().account(address.into(), Self::num_to_id(num.unwrap_or_default()))
|
||||
Box::new(self.fetcher().account(address.into(), num.unwrap_or_default().to_block_id())
|
||||
.map(|acc| acc.map_or(0.into(), |a| a.nonce).into()))
|
||||
}
|
||||
|
||||
@@ -325,7 +308,7 @@ impl<T: LightChainClient + 'static> Eth for EthClient<T> {
|
||||
fn block_transaction_count_by_number(&self, num: BlockNumber) -> BoxFuture<Option<RpcU256>> {
|
||||
let (sync, on_demand) = (self.sync.clone(), self.on_demand.clone());
|
||||
|
||||
Box::new(self.fetcher().header(Self::num_to_id(num)).and_then(move |hdr| {
|
||||
Box::new(self.fetcher().header(num.to_block_id()).and_then(move |hdr| {
|
||||
if hdr.transactions_root() == KECCAK_NULL_RLP {
|
||||
Either::A(future::ok(Some(U256::from(0).into())))
|
||||
} else {
|
||||
@@ -357,7 +340,7 @@ impl<T: LightChainClient + 'static> Eth for EthClient<T> {
|
||||
fn block_uncles_count_by_number(&self, num: BlockNumber) -> BoxFuture<Option<RpcU256>> {
|
||||
let (sync, on_demand) = (self.sync.clone(), self.on_demand.clone());
|
||||
|
||||
Box::new(self.fetcher().header(Self::num_to_id(num)).and_then(move |hdr| {
|
||||
Box::new(self.fetcher().header(num.to_block_id()).and_then(move |hdr| {
|
||||
if hdr.uncles_hash() == KECCAK_EMPTY_LIST_RLP {
|
||||
Either::B(future::ok(Some(U256::from(0).into())))
|
||||
} else {
|
||||
@@ -371,7 +354,7 @@ impl<T: LightChainClient + 'static> Eth for EthClient<T> {
|
||||
}
|
||||
|
||||
fn code_at(&self, address: RpcH160, num: Trailing<BlockNumber>) -> BoxFuture<Bytes> {
|
||||
Box::new(self.fetcher().code(address.into(), Self::num_to_id(num.unwrap_or_default())).map(Into::into))
|
||||
Box::new(self.fetcher().code(address.into(), num.unwrap_or_default().to_block_id()).map(Into::into))
|
||||
}
|
||||
|
||||
fn send_raw_transaction(&self, raw: Bytes) -> Result<RpcH256> {
|
||||
@@ -438,7 +421,7 @@ impl<T: LightChainClient + 'static> Eth for EthClient<T> {
|
||||
}
|
||||
|
||||
fn transaction_by_block_number_and_index(&self, num: BlockNumber, idx: Index) -> BoxFuture<Option<Transaction>> {
|
||||
Box::new(self.fetcher().block(Self::num_to_id(num)).map(move |block| {
|
||||
Box::new(self.fetcher().block(num.to_block_id()).map(move |block| {
|
||||
light_fetch::extract_transaction_at_index(block, idx.value())
|
||||
}))
|
||||
}
|
||||
@@ -482,7 +465,7 @@ impl<T: LightChainClient + 'static> Eth for EthClient<T> {
|
||||
|
||||
fn uncle_by_block_number_and_index(&self, num: BlockNumber, idx: Index) -> BoxFuture<Option<RichBlock>> {
|
||||
let client = self.client.clone();
|
||||
Box::new(self.fetcher().block(Self::num_to_id(num)).map(move |block| {
|
||||
Box::new(self.fetcher().block(num.to_block_id()).map(move |block| {
|
||||
extract_uncle_at_index(block, idx, client)
|
||||
}))
|
||||
}
|
||||
|
||||
@@ -26,7 +26,6 @@ use ethstore::random_phrase;
|
||||
use sync::LightSyncProvider;
|
||||
use ethcore::account_provider::AccountProvider;
|
||||
use ethcore_logger::RotatingLogger;
|
||||
use ethcore::ids::BlockId;
|
||||
|
||||
use light::client::LightChainClient;
|
||||
|
||||
@@ -42,9 +41,9 @@ use v1::types::{
|
||||
Bytes, U256, U64, H160, H256, H512, CallRequest,
|
||||
Peers, Transaction, RpcSettings, Histogram,
|
||||
TransactionStats, LocalTransactionStatus,
|
||||
BlockNumber, ConsensusCapability, VersionInfo,
|
||||
BlockNumber, LightBlockNumber, ConsensusCapability, VersionInfo,
|
||||
OperationsInfo, ChainStatus,
|
||||
AccountInfo, HwAccountInfo, Header, RichHeader,
|
||||
AccountInfo, HwAccountInfo, Header, RichHeader, Receipt,
|
||||
};
|
||||
use Host;
|
||||
|
||||
@@ -403,18 +402,15 @@ impl Parity for ParityClient {
|
||||
extra_info: extra_info,
|
||||
})
|
||||
};
|
||||
// Note: Here we treat `Pending` as `Latest`.
|
||||
// Since light clients don't produce pending blocks
|
||||
// (they don't have state) we can safely fallback to `Latest`.
|
||||
let id = match number.unwrap_or_default() {
|
||||
BlockNumber::Num(n) => BlockId::Number(n),
|
||||
BlockNumber::Earliest => BlockId::Earliest,
|
||||
BlockNumber::Latest | BlockNumber::Pending => BlockId::Latest,
|
||||
};
|
||||
|
||||
let id = number.unwrap_or_default().to_block_id();
|
||||
Box::new(self.fetcher().header(id).and_then(from_encoded))
|
||||
}
|
||||
|
||||
fn block_receipts(&self, number: Trailing<BlockNumber>) -> BoxFuture<Vec<Receipt>> {
|
||||
let id = number.unwrap_or_default().to_block_id();
|
||||
Box::new(self.fetcher().receipts(id).and_then(|receipts| Ok(receipts.into_iter().map(Into::into).collect())))
|
||||
}
|
||||
|
||||
fn ipfs_cid(&self, content: Bytes) -> Result<String> {
|
||||
ipfs::cid(content)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user