Skip to content

Commit

Permalink
Support for additional RichBlock fields (#57)
Browse files Browse the repository at this point in the history
* Add optional block hash parameter in rich_block_build

* Add extra_data field value in rich_block_build

* Add seal_fields value in rich_block_build

* Add transactions support and conversion in rich_block_build

* Update block_by_number to support transactions conversion

* Move block transactions statuses logic to pallet_ethereum

* Style fixing

Co-authored-by: Wei Tang <accounts@that.world>

* Style fixing

Co-authored-by: Wei Tang <accounts@that.world>

Co-authored-by: Wei Tang <accounts@that.world>
  • Loading branch information
tgmichel and sorpaas committed Jul 1, 2020
1 parent dd7a211 commit b7214d1
Show file tree
Hide file tree
Showing 4 changed files with 80 additions and 14 deletions.
11 changes: 11 additions & 0 deletions frame/ethereum/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -311,6 +311,17 @@ impl<T: Trait> Module<T> {
None
}

pub fn block_transaction_statuses(
block: &Block
) -> Vec<Option<TransactionStatus>> {
block.transactions.iter().map(|transaction|{
let transaction_hash = H256::from_slice(
Keccak256::digest(&rlp::encode(transaction)).as_slice()
);
<Module<T>>::transaction_status(transaction_hash)
}).collect()
}

/// Execute an Ethereum transaction, ignoring transaction signatures.
pub fn execute(source: H160, transaction: ethereum::Transaction) {
let transaction_hash = H256::from_slice(
Expand Down
17 changes: 16 additions & 1 deletion rpc/primitives/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,20 @@ pub struct TransactionStatus {
pub logs_bloom: Bloom,
}

impl Default for TransactionStatus {
fn default() -> Self {
TransactionStatus {
transaction_hash: H256::default(),
transaction_index: 0 as u32,
from: H160::default(),
to: None,
contract_address: None,
logs: Vec::new(),
logs_bloom: Bloom::default(),
}
}
}

sp_api::decl_runtime_apis! {
/// API necessary for Ethereum-compatibility layer.
pub trait EthereumRuntimeApi {
Expand All @@ -52,9 +66,10 @@ sp_api::decl_runtime_apis! {
gas_price: U256,
nonce: Option<U256>,
) -> Option<(Vec<u8>, U256)>;
fn block_by_number(number: u32) -> Option<EthereumBlock>;
fn block_by_number(number: u32) -> (Option<EthereumBlock>, Vec<Option<TransactionStatus>>);
fn block_transaction_count_by_number(number: u32) -> Option<U256>;
fn block_by_hash(hash: H256) -> Option<EthereumBlock>;
fn block_by_hash_with_statuses(hash: H256) -> (Option<EthereumBlock>, Vec<Option<TransactionStatus>>);
fn block_transaction_count_by_hash(hash: H256) -> Option<U256>;
fn transaction_by_hash(hash: H256) -> Option<(
EthereumTransaction,
Expand Down
40 changes: 29 additions & 11 deletions rpc/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,10 +66,18 @@ impl<B: BlockT, C, SC, P, CT, BE> EthApi<B, C, SC, P, CT, BE> {
}
}

fn rich_block_build(block: ethereum::Block) -> RichBlock {
fn rich_block_build(
block: ethereum::Block,
statuses: Vec<Option<TransactionStatus>>,
hash: Option<H256>
) -> RichBlock {
Rich {
inner: Block {
hash: None, // TODO
hash: Some(hash.unwrap_or_else(|| {
H256::from_slice(
Keccak256::digest(&rlp::encode(&block.header)).as_slice()
)
})),
parent_hash: block.header.parent_hash,
uncles_hash: H256::zero(), // TODO
author: H160::default(), // TODO
Expand All @@ -80,16 +88,26 @@ fn rich_block_build(block: ethereum::Block) -> RichBlock {
number: Some(block.header.number),
gas_used: block.header.gas_used,
gas_limit: block.header.gas_limit,
extra_data: Bytes(vec![]), // TODO H256 to Vec<u8>
extra_data: Bytes(block.header.extra_data.as_bytes().to_vec()),
logs_bloom: Some(block.header.logs_bloom),
timestamp: U256::from(block.header.timestamp),
difficulty: block.header.difficulty,
total_difficulty: None, // TODO
seal_fields: vec![], // TODO
seal_fields: vec![
Bytes(block.header.mix_hash.as_bytes().to_vec()),
Bytes(block.header.nonce.as_bytes().to_vec())
],
uncles: vec![], // TODO
// TODO expected struct `frontier_rpc_core::types::transaction::Transaction`,
// found struct `ethereum::transaction::Transaction`
transactions: BlockTransactions::Full(vec![]),
transactions: BlockTransactions::Full(
block.transactions.iter().enumerate().map(|(index, transaction)|{
let mut status = statuses[index].clone();
// A fallback to default check
if status.is_none() {
status = Some(TransactionStatus::default());
}
transaction_build(transaction.clone(), block.clone(), status.unwrap())
}).collect()
),
size: None // TODO
},
extra_info: BTreeMap::new()
Expand Down Expand Up @@ -296,11 +314,11 @@ impl<B, C, SC, P, CT, BE> EthApiT for EthApi<B, C, SC, P, CT, BE> where
let header = self.select_chain.best_chain()
.map_err(|_| internal_err("fetch header failed"))?;

if let Ok(Some(block)) = self.client.runtime_api().block_by_hash(
if let Ok((Some(block), statuses)) = self.client.runtime_api().block_by_hash_with_statuses(
&BlockId::Hash(header.hash()),
hash
) {
Ok(Some(rich_block_build(block)))
Ok(Some(rich_block_build(block, statuses, Some(hash))))
} else {
Ok(None)
}
Expand All @@ -310,11 +328,11 @@ impl<B, C, SC, P, CT, BE> EthApiT for EthApi<B, C, SC, P, CT, BE> where
let header = self.select_chain.best_chain()
.map_err(|_| internal_err("fetch header failed"))?;
if let Ok(Some(native_number)) = self.native_block_number(Some(number)) {
if let Ok(Some(block)) = self.client.runtime_api().block_by_number(
if let Ok((Some(block), statuses)) = self.client.runtime_api().block_by_number(
&BlockId::Hash(header.hash()),
native_number
) {
return Ok(Some(rich_block_build(block)));
return Ok(Some(rich_block_build(block, statuses, None)));
}
}
Ok(None)
Expand Down
26 changes: 24 additions & 2 deletions template/runtime/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -505,8 +505,17 @@ impl_runtime_apis! {
).ok().map(|(_, ret, gas)| (ret, gas))
}

fn block_by_number(number: u32) -> Option<EthereumBlock> {
<ethereum::Module<Runtime>>::block_by_number(number)
fn block_by_number(number: u32) -> (
Option<EthereumBlock>, Vec<Option<ethereum::TransactionStatus>>
) {
if let Some(block) = <ethereum::Module<Runtime>>::block_by_number(number) {
let statuses = <ethereum::Module<Runtime>>::block_transaction_statuses(&block);
return (
Some(block),
statuses
);
}
(None,vec![])
}

fn block_transaction_count_by_number(number: u32) -> Option<U256> {
Expand All @@ -527,6 +536,19 @@ impl_runtime_apis! {
<ethereum::Module<Runtime>>::block_by_hash(hash)
}

fn block_by_hash_with_statuses(hash: H256) -> (
Option<EthereumBlock>, Vec<Option<ethereum::TransactionStatus>>
) {
if let Some(block) = <ethereum::Module<Runtime>>::block_by_hash(hash) {
let statuses = <ethereum::Module<Runtime>>::block_transaction_statuses(&block);
return (
Some(block),
statuses
);
}
(None, vec![])
}

fn transaction_by_hash(hash: H256) -> Option<(
EthereumTransaction,
EthereumBlock,
Expand Down

0 comments on commit b7214d1

Please sign in to comment.