Fix "pending" parameter on RPC block requests (#1602)
* Initial commit. * Pending blocks work. * Address grumbles. * Fix up for new API.
This commit is contained in:
parent
2b193f00d4
commit
598833d1ea
@ -39,8 +39,18 @@ impl Block {
|
|||||||
pub fn is_good(b: &[u8]) -> bool {
|
pub fn is_good(b: &[u8]) -> bool {
|
||||||
UntrustedRlp::new(b).as_val::<Block>().is_ok()
|
UntrustedRlp::new(b).as_val::<Block>().is_ok()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get the RLP-encoding of the block without the seal.
|
||||||
|
pub fn rlp_bytes(&self, seal: Seal) -> Bytes {
|
||||||
|
let mut block_rlp = RlpStream::new_list(3);
|
||||||
|
self.header.stream_rlp(&mut block_rlp, seal);
|
||||||
|
block_rlp.append(&self.transactions);
|
||||||
|
block_rlp.append(&self.uncles);
|
||||||
|
block_rlp.out()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
impl Decodable for Block {
|
impl Decodable for Block {
|
||||||
fn decode<D>(decoder: &D) -> Result<Self, DecoderError> where D: Decoder {
|
fn decode<D>(decoder: &D) -> Result<Self, DecoderError> where D: Decoder {
|
||||||
if decoder.as_raw().len() != try!(decoder.as_rlp().payload_info()).total() {
|
if decoder.as_raw().len() != try!(decoder.as_rlp().payload_info()).total() {
|
||||||
@ -140,9 +150,12 @@ impl ExecutedBlock {
|
|||||||
|
|
||||||
/// Trait for a object that is a `ExecutedBlock`.
|
/// Trait for a object that is a `ExecutedBlock`.
|
||||||
pub trait IsBlock {
|
pub trait IsBlock {
|
||||||
/// Get the block associated with this object.
|
/// Get the `ExecutedBlock` associated with this object.
|
||||||
fn block(&self) -> &ExecutedBlock;
|
fn block(&self) -> &ExecutedBlock;
|
||||||
|
|
||||||
|
/// Get the base `Block` object associated with this.
|
||||||
|
fn base(&self) -> &Block { &self.block().base }
|
||||||
|
|
||||||
/// Get the header associated with this object's block.
|
/// Get the header associated with this object's block.
|
||||||
fn header(&self) -> &Header { &self.block().base.header }
|
fn header(&self) -> &Header { &self.block().base.header }
|
||||||
|
|
||||||
|
@ -44,6 +44,7 @@ use error::{ImportError, ExecutionError, BlockError, ImportResult};
|
|||||||
use header::BlockNumber;
|
use header::BlockNumber;
|
||||||
use state::State;
|
use state::State;
|
||||||
use spec::Spec;
|
use spec::Spec;
|
||||||
|
use basic_types::Seal;
|
||||||
use engine::Engine;
|
use engine::Engine;
|
||||||
use views::HeaderView;
|
use views::HeaderView;
|
||||||
use service::ClientIoMessage;
|
use service::ClientIoMessage;
|
||||||
@ -462,8 +463,10 @@ impl Client {
|
|||||||
/// Otherwise, this can fail (but may not) if the DB prunes state.
|
/// Otherwise, this can fail (but may not) if the DB prunes state.
|
||||||
pub fn state_at(&self, id: BlockID) -> Option<State> {
|
pub fn state_at(&self, id: BlockID) -> Option<State> {
|
||||||
// fast path for latest state.
|
// fast path for latest state.
|
||||||
if let BlockID::Latest = id.clone() {
|
match id.clone() {
|
||||||
return Some(self.state())
|
BlockID::Pending => return self.miner.pending_state().or_else(|| Some(self.state())),
|
||||||
|
BlockID::Latest => return Some(self.state()),
|
||||||
|
_ => {},
|
||||||
}
|
}
|
||||||
|
|
||||||
let block_number = match self.block_number(id.clone()) {
|
let block_number = match self.block_number(id.clone()) {
|
||||||
@ -556,7 +559,7 @@ impl Client {
|
|||||||
BlockID::Number(number) => Some(number),
|
BlockID::Number(number) => Some(number),
|
||||||
BlockID::Hash(ref hash) => self.chain.block_number(hash),
|
BlockID::Hash(ref hash) => self.chain.block_number(hash),
|
||||||
BlockID::Earliest => Some(0),
|
BlockID::Earliest => Some(0),
|
||||||
BlockID::Latest => Some(self.chain.best_block_number())
|
BlockID::Latest | BlockID::Pending => Some(self.chain.best_block_number()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -565,7 +568,7 @@ impl Client {
|
|||||||
BlockID::Hash(hash) => Some(hash),
|
BlockID::Hash(hash) => Some(hash),
|
||||||
BlockID::Number(number) => chain.block_hash(number),
|
BlockID::Number(number) => chain.block_hash(number),
|
||||||
BlockID::Earliest => chain.block_hash(0),
|
BlockID::Earliest => chain.block_hash(0),
|
||||||
BlockID::Latest => Some(chain.best_block_hash())
|
BlockID::Latest | BlockID::Pending => Some(chain.best_block_hash()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -683,6 +686,11 @@ impl BlockChainClient for Client {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn block(&self, id: BlockID) -> Option<Bytes> {
|
fn block(&self, id: BlockID) -> Option<Bytes> {
|
||||||
|
if let &BlockID::Pending = &id {
|
||||||
|
if let Some(block) = self.miner.pending_block() {
|
||||||
|
return Some(block.rlp_bytes(Seal::Without));
|
||||||
|
}
|
||||||
|
}
|
||||||
Self::block_hash(&self.chain, id).and_then(|hash| {
|
Self::block_hash(&self.chain, id).and_then(|hash| {
|
||||||
self.chain.block(&hash)
|
self.chain.block(&hash)
|
||||||
})
|
})
|
||||||
@ -697,6 +705,11 @@ impl BlockChainClient for Client {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn block_total_difficulty(&self, id: BlockID) -> Option<U256> {
|
fn block_total_difficulty(&self, id: BlockID) -> Option<U256> {
|
||||||
|
if let &BlockID::Pending = &id {
|
||||||
|
if let Some(block) = self.miner.pending_block() {
|
||||||
|
return Some(*block.header.difficulty() + self.block_total_difficulty(BlockID::Latest).expect("blocks in chain have details; qed"));
|
||||||
|
}
|
||||||
|
}
|
||||||
Self::block_hash(&self.chain, id).and_then(|hash| self.chain.block_details(&hash)).map(|d| d.total_difficulty)
|
Self::block_hash(&self.chain, id).and_then(|hash| self.chain.block_details(&hash)).map(|d| d.total_difficulty)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -241,7 +241,7 @@ impl TestBlockChainClient {
|
|||||||
BlockID::Hash(hash) => Some(hash),
|
BlockID::Hash(hash) => Some(hash),
|
||||||
BlockID::Number(n) => self.numbers.read().get(&(n as usize)).cloned(),
|
BlockID::Number(n) => self.numbers.read().get(&(n as usize)).cloned(),
|
||||||
BlockID::Earliest => self.numbers.read().get(&0).cloned(),
|
BlockID::Earliest => self.numbers.read().get(&0).cloned(),
|
||||||
BlockID::Latest => self.numbers.read().get(&(self.numbers.read().len() - 1)).cloned()
|
BlockID::Latest | BlockID::Pending => self.numbers.read().get(&(self.numbers.read().len() - 1)).cloned()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -22,8 +22,9 @@ use util::*;
|
|||||||
use util::using_queue::{UsingQueue, GetAction};
|
use util::using_queue::{UsingQueue, GetAction};
|
||||||
use account_provider::AccountProvider;
|
use account_provider::AccountProvider;
|
||||||
use views::{BlockView, HeaderView};
|
use views::{BlockView, HeaderView};
|
||||||
|
use state::State;
|
||||||
use client::{MiningBlockChainClient, Executive, Executed, EnvInfo, TransactOptions, BlockID, CallAnalytics};
|
use client::{MiningBlockChainClient, Executive, Executed, EnvInfo, TransactOptions, BlockID, CallAnalytics};
|
||||||
use block::{ClosedBlock, IsBlock};
|
use block::{ClosedBlock, IsBlock, Block};
|
||||||
use error::*;
|
use error::*;
|
||||||
use transaction::SignedTransaction;
|
use transaction::SignedTransaction;
|
||||||
use receipt::Receipt;
|
use receipt::Receipt;
|
||||||
@ -226,6 +227,16 @@ impl Miner {
|
|||||||
self.options.force_sealing || !self.options.new_work_notify.is_empty()
|
self.options.force_sealing || !self.options.new_work_notify.is_empty()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get `Some` `clone()` of the current pending block's state or `None` if we're not sealing.
|
||||||
|
pub fn pending_state(&self) -> Option<State> {
|
||||||
|
self.sealing_work.lock().peek_last_ref().map(|b| b.block().fields().state.clone())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get `Some` `clone()` of the current pending block's state or `None` if we're not sealing.
|
||||||
|
pub fn pending_block(&self) -> Option<Block> {
|
||||||
|
self.sealing_work.lock().peek_last_ref().map(|b| b.base().clone())
|
||||||
|
}
|
||||||
|
|
||||||
/// Prepares new block for sealing including top transactions from queue.
|
/// Prepares new block for sealing including top transactions from queue.
|
||||||
#[cfg_attr(feature="dev", allow(match_same_arms))]
|
#[cfg_attr(feature="dev", allow(match_same_arms))]
|
||||||
#[cfg_attr(feature="dev", allow(cyclomatic_complexity))]
|
#[cfg_attr(feature="dev", allow(cyclomatic_complexity))]
|
||||||
|
@ -33,7 +33,9 @@ pub enum BlockID {
|
|||||||
/// Earliest block (genesis).
|
/// Earliest block (genesis).
|
||||||
Earliest,
|
Earliest,
|
||||||
/// Latest mined block.
|
/// Latest mined block.
|
||||||
Latest
|
Latest,
|
||||||
|
/// Pending block.
|
||||||
|
Pending,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Uniquely identifies transaction.
|
/// Uniquely identifies transaction.
|
||||||
|
@ -28,7 +28,7 @@ pub enum BlockNumber {
|
|||||||
/// Earliest block (genesis)
|
/// Earliest block (genesis)
|
||||||
Earliest,
|
Earliest,
|
||||||
/// Pending block (being mined)
|
/// Pending block (being mined)
|
||||||
Pending
|
Pending,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Deserialize for BlockNumber {
|
impl Deserialize for BlockNumber {
|
||||||
@ -63,8 +63,8 @@ impl Into<BlockID> for BlockNumber {
|
|||||||
match self {
|
match self {
|
||||||
BlockNumber::Num(n) => BlockID::Number(n),
|
BlockNumber::Num(n) => BlockID::Number(n),
|
||||||
BlockNumber::Earliest => BlockID::Earliest,
|
BlockNumber::Earliest => BlockID::Earliest,
|
||||||
// TODO: change this once blockid support pendingst,
|
BlockNumber::Latest => BlockID::Latest,
|
||||||
BlockNumber::Pending | BlockNumber::Latest => BlockID::Latest,
|
BlockNumber::Pending => BlockID::Pending,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -87,7 +87,7 @@ mod tests {
|
|||||||
assert_eq!(BlockID::Number(100), BlockNumber::Num(100).into());
|
assert_eq!(BlockID::Number(100), BlockNumber::Num(100).into());
|
||||||
assert_eq!(BlockID::Earliest, BlockNumber::Earliest.into());
|
assert_eq!(BlockID::Earliest, BlockNumber::Earliest.into());
|
||||||
assert_eq!(BlockID::Latest, BlockNumber::Latest.into());
|
assert_eq!(BlockID::Latest, BlockNumber::Latest.into());
|
||||||
assert_eq!(BlockID::Latest, BlockNumber::Pending.into());
|
assert_eq!(BlockID::Pending, BlockNumber::Pending.into());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user