Skip to content
This repository was archived by the owner on Nov 6, 2020. It is now read-only.
Closed
32 changes: 29 additions & 3 deletions rpc/src/v1/impls/eth.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
use std::thread;
use std::time::{Instant, Duration, SystemTime, UNIX_EPOCH};
use std::sync::Arc;
use std::collections::BTreeMap;

use rlp::Rlp;
use ethereum_types::{Address, H64, H160, H256, U64, U256};
Expand Down Expand Up @@ -202,12 +203,17 @@ impl<C, SN: ?Sized, S: ?Sized, M, EM, T: StateInfo + 'static> EthClient<C, SN, S
}
}

fn rich_block(&self, id: BlockNumberOrId, include_txs: bool) -> Result<Option<RichBlock>> {
fn encoded_block(&self, id: BlockNumberOrId) -> (
Option<encoded::Block>, // block
Option<U256>, // difficulty
Option<BTreeMap<String, String>>, // extra
bool // is_pending
) {
let client = &self.client;

let client_query = |id| (client.block(id), client.block_total_difficulty(id), client.block_extra_info(id), false);

let (block, difficulty, extra, is_pending) = match id {
match id {
BlockNumberOrId::Number(BlockNumber::Pending) => {
let info = self.client.chain_info();
match self.miner.pending_block(info.best_block_number) {
Expand Down Expand Up @@ -248,7 +254,11 @@ impl<C, SN: ?Sized, S: ?Sized, M, EM, T: StateInfo + 'static> EthClient<C, SN, S
},

BlockNumberOrId::Id(id) => client_query(id),
};
}
}

fn rich_block(&self, id: BlockNumberOrId, include_txs: bool) -> Result<Option<RichBlock>> {
let (block, difficulty, extra, is_pending) = self.encoded_block(id);

match (block, difficulty) {
(Some(block), Some(total_difficulty)) => {
Expand Down Expand Up @@ -740,6 +750,22 @@ impl<C, SN: ?Sized, S: ?Sized, M, EM, T: StateInfo + 'static> Eth for EthClient<
Box::new(future::done(result))
}

fn raw_block_by_number(&self, num: BlockNumber, _include_txs: bool) -> BoxFuture<Option<Bytes>> {
let result = Ok(self.encoded_block(num.clone().into()).0)
.and_then(
errors::check_block_number_existence(&*self.client, num, self.options.allow_missing_blocks)
)
.map(|try_block| {
if let Some(block) = try_block { // block found
Some(Bytes::from(block.rlp().as_raw().to_vec()))
} else { // block not found
None
}
});

Box::new(future::done(result))
}

fn transaction_by_hash(&self, hash: H256) -> BoxFuture<Option<Transaction>> {
let tx = try_bf!(self.transaction(PendingTransactionId::Hash(hash))).or_else(|| {
self.miner.transaction(&hash)
Expand Down
34 changes: 24 additions & 10 deletions rpc/src/v1/impls/light/eth.rs
Original file line number Diff line number Diff line change
Expand Up @@ -133,14 +133,13 @@ where

// get a "rich" block structure. Fails on unknown block.
fn rich_block(&self, id: BlockId, include_txs: bool) -> BoxFuture<RichBlock> {
let (on_demand, sync) = (self.on_demand.clone(), self.sync.clone());
let (client, engine) = (self.client.clone(), self.client.engine().clone());
let engine = self.client.engine().clone();

// helper for filling out a rich block once we've got a block and a score.
let fill_rich = move |block: encoded::Block, score: Option<U256>| {
// Get the raw block, fill it into a rich block
Box::new(self.encoded_block(id).and_then(move |(block, score)| {
let header = block.decode_header();
let extra_info = engine.extra_info(&header);
RichBlock {
future::ok(RichBlock {
inner: Block {
hash: Some(header.hash()),
size: Some(block.rlp().as_raw().len().into()),
Expand All @@ -167,14 +166,19 @@ where
extra_data: Bytes::new(header.extra_data().clone()),
},
extra_info,
}
};
})
}))
}

fn encoded_block(&self, id: BlockId) -> BoxFuture<(encoded::Block, Option<U256>)> {
let (on_demand, sync) = (self.on_demand.clone(), self.sync.clone());
let client = self.client.clone();

// get the block itself.
Box::new(self.fetcher().block(id).and_then(move |block| {
// then fetch the total difficulty (this is much easier after getting the block).
match client.score(id) {
Some(score) => Either::A(future::ok(fill_rich(block, Some(score)))),
Some(score) => Either::A(future::ok((block, Some(score)))),
None => {
// make a CHT request to fetch the chain score.
let req = cht::block_to_cht_number(block.number())
Expand All @@ -190,7 +194,7 @@ where
.expect("genesis always stored; qed")
.difficulty();

return Either::A(future::ok(fill_rich(block, Some(score))))
return Either::A(future::ok((block, Some(score))))
}
};

Expand All @@ -208,7 +212,7 @@ where
None
};

fill_rich(block, score)
(block, score)
}).map_err(errors::on_demand_error)),
None => Either::A(future::err(errors::network_disabled())),
}
Expand Down Expand Up @@ -305,6 +309,16 @@ where
Box::new(self.rich_block(num.to_block_id(), include_txs).map(Some))
}

fn raw_block_by_number(&self, num: BlockNumber, _include_txs: bool) -> BoxFuture<Option<Bytes>> {
Box::new(self.encoded_block(num.to_block_id()).map(|(block, _)|
Some(Bytes::new(block
.rlp()
.as_raw()
.to_vec()
))
))
}

fn transaction_count(&self, address: H160, num: Option<BlockNumber>) -> BoxFuture<U256> {
Box::new(self.fetcher().account(address, num.unwrap_or_default().to_block_id())
.map(|acc| acc.map_or(0.into(), |a| a.nonce)))
Expand Down
17 changes: 17 additions & 0 deletions rpc/src/v1/tests/eth.rs
Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,23 @@ fn eth_get_block() {
assert_eq!(tester.handler.handle_request_sync(req_block).unwrap(), res_block);
}

#[test]
fn eth_get_raw_block() {
let chain = extract_chain!("BlockchainTests/bcGasPricerTest/RPC_API_Test");
let tester = EthTester::from_chain(&chain);

// In the test data, each block contains a "rlp" field. These tests are run against those field values.
// blocknumber 1
let req_block = r#"{"method":"eth_getRawBlockByNumber","params":["0x1",false],"id":1,"jsonrpc":"2.0"}"#;
let res_block = r#"{"jsonrpc":"2.0","result":"0xf90968f901fba0cded1bc807465a72e2d54697076ab858f28b15d4beaae8faa47339c8eee386a3a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a0ee57559895449b8dbd0a096b2999cf97b517b645ec8db33c7f5934778672263ea03ccbb984a0a736604acae327d9b643f8e75c7931cb2c6ac10dab4226e2e4c5a3a0a2bd925fcbb8b1ec39612553b17c9265ab198f5af25cc564655114bf5a28c75db901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000083020000018401dee56e83078674845bbdf64480a02a0928c245db5c5d50ac3bfa8e36f284e68ce47d136eba0b7e7e1d9b32b6be5d8828609b1e25e1917af90766f907638001832fefd8800ab907155b5b610705806100106000396000f3006000357c010000000000000000000000000000000000000000000000000000000090048063102accc11461012c57806312a7b9141461013a5780631774e6461461014c5780631e26fd331461015d5780631f9030371461016e578063343a875d1461018057806338cc4831146101955780634e7ad367146101bd57806357cb2fc4146101cb57806365538c73146101e057806368895979146101ee57806376bc21d9146102005780639a19a9531461020e5780639dc2c8f51461021f578063a53b1c1e1461022d578063a67808571461023e578063b61c05031461024c578063c2b12a731461025a578063d2282dc51461026b578063e30081a01461027c578063e8beef5b1461028d578063f38b06001461029b578063f5b53e17146102a9578063fd408767146102bb57005b6101346104d6565b60006000f35b61014261039b565b8060005260206000f35b610157600435610326565b60006000f35b6101686004356102c9565b60006000f35b610176610442565b8060005260206000f35b6101886103d3565b8060ff1660005260206000f35b61019d610413565b8073ffffffffffffffffffffffffffffffffffffffff1660005260206000f35b6101c56104c5565b60006000f35b6101d36103b7565b8060000b60005260206000f35b6101e8610454565b60006000f35b6101f6610401565b8060005260206000f35b61020861051f565b60006000f35b6102196004356102e5565b60006000f35b610227610693565b60006000f35b610238600435610342565b60006000f35b610246610484565b60006000f35b610254610493565b60006000f35b61026560043561038d565b60006000f35b610276600435610350565b60006000f35b61028760043561035e565b60006000f35b6102956105b4565b60006000f35b6102a3610547565b60006000f35b6102b16103ef565b8060005260206000f35b6102c3610600565b60006000f35b80600060006101000a81548160ff021916908302179055505b50565b80600060016101000a81548160ff02191690837f01000000000000000000000000000000000000000000000000000000000000009081020402179055505b50565b80600060026101000a81548160ff021916908302179055505b50565b806001600050819055505b50565b806002600050819055505b50565b80600360006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908302179055505b50565b806004600050819055505b50565b6000600060009054906101000a900460ff1690506103b4565b90565b6000600060019054906101000a900460000b90506103d0565b90565b6000600060029054906101000a900460ff1690506103ec565b90565b600060016000505490506103fe565b90565b60006002600050549050610410565b90565b6000600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905061043f565b90565b60006004600050549050610451565b90565b7f65c9ac8011e286e89d02a269890f41d67ca2cc597b2c76c7c69321ff492be5806000602a81526020016000a15b565b6000602a81526020016000a05b565b60017f81933b308056e7e85668661dcd102b1f22795b4431f9cf4625794f381c271c6b6000602a81526020016000a25b565b60016000602a81526020016000a15b565b3373ffffffffffffffffffffffffffffffffffffffff1660017f0e216b62efbb97e751a2ce09f607048751720397ecfb9eef1e48a6644948985b6000602a81526020016000a35b565b3373ffffffffffffffffffffffffffffffffffffffff1660016000602a81526020016000a25b565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6001023373ffffffffffffffffffffffffffffffffffffffff1660017f317b31292193c2a4f561cc40a95ea0d97a2733f14af6d6d59522473e1f3ae65f6000602a81526020016000a45b565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6001023373ffffffffffffffffffffffffffffffffffffffff1660016000602a81526020016000a35b565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6001023373ffffffffffffffffffffffffffffffffffffffff1660017fd5f0a30e4be0c6be577a71eceb7464245a796a7e6a55c0d971837b250de05f4e60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe98152602001602a81526020016000a45b565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6001023373ffffffffffffffffffffffffffffffffffffffff16600160007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe98152602001602a81526020016000a35b561ca0e439aa8812c1c0a751b0931ea20c5a30cd54fe15cae883c59fd8107e04557679a058d025af99b538b778a47da8115c43d5cee564c3cc8d58eb972aaf80ea2c406ec0","id":1}"#;
assert_eq!(tester.handler.handle_request_sync(req_block).unwrap(), res_block);

// blocknumber 2
let req_block = r#"{"method":"eth_getRawBlockByNumber","params":["0x2",false],"id":1,"jsonrpc":"2.0"}"#;
let res_block = r#"{"jsonrpc":"2.0","result":"0xf90266f901faa03afbe9e94654329fa016ead8b86fec531c6dc8805b07b7fa312477153c5327e5a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a052cbd86e23f3cd03140f49302f32ace2583c5e046c91049eb10136266b932caca0f6f36662c7d5cd443067f551d9874f11a9dfc9c3cfd72388beb19e60b585938ca0e9111d31a5282e8d68d1beaf1821405a9716182e2b780a724e1e6b78c609c6f3b901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000083020000028401de6db68253f0845bbdf76480a0245b103751f0c19c2928c59b8f34f0623af1739c7393f499175a107a26bb13bc88e94f58ed82520f45f866f86401018304cb2f946295ee1b4f6dd65047762f924ecd367c17eabf8f0a8412a7b9141ba0ed2e0f715eccaab4362c19c1cf35ad8031ab1cabe71ada3fe8b269fe9d726712a06691074f289f826d23c92808ae363959eb958fb7a91fc721875ece4958114c65c0","id":1}"#;
assert_eq!(tester.handler.handle_request_sync(req_block).unwrap(), res_block);
}

#[test]
fn eth_get_block_by_hash() {
let chain = extract_chain!("BlockchainTests/bcGasPricerTest/RPC_API_Test");
Expand Down
4 changes: 4 additions & 0 deletions rpc/src/v1/traits/eth.rs
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,10 @@ pub trait Eth {
#[rpc(name = "eth_getBlockByNumber")]
fn block_by_number(&self, BlockNumber, bool) -> BoxFuture<Option<RichBlock>>;

/// Returns raw block with given number. No extras included.
#[rpc(name = "eth_getRawBlockByNumber")]
fn raw_block_by_number(&self, BlockNumber, bool) -> BoxFuture<Option<Bytes>>;

/// Returns the number of transactions sent from given address at given time (block number).
#[rpc(name = "eth_getTransactionCount")]
fn transaction_count(&self, H160, Option<BlockNumber>) -> BoxFuture<U256>;
Expand Down