Skip to content

Commit

Permalink
Add eth_getBlockByHash rpc implementation (#3992)
Browse files Browse the repository at this point in the history
* cleanup code

* get block from the blockchain

* update Block::build(), Header::build() functions

* update to the latest lib

* update Transaction::build

* provide gas_price argument

* fix clippy

* update transaction test

* cleanup
  • Loading branch information
Mr-Leshiy authored May 18, 2022
1 parent 4b38bc5 commit 04e2143
Show file tree
Hide file tree
Showing 12 changed files with 212 additions and 93 deletions.
2 changes: 1 addition & 1 deletion jcli/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ rpassword = "5.0"
clap = { version = "3.1", default-features = false, features = ["suggestions", "color", "wrap_help", "std"] }

[features]
evm = ["chain-evm","jormungandr-lib/evm"]
evm = ["jormungandr-lib/evm", "chain-evm"]

[dependencies.reqwest]
version = "0.11"
Expand Down
4 changes: 2 additions & 2 deletions jcli/src/jcli_lib/certificate/new_evm_mapping.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use crate::jcli_lib::{
utils::key_parser::parse_pub_key,
};
use chain_crypto::{Ed25519, PublicKey};
use chain_evm::Address;
use chain_evm::ethereum_types::H160;
use chain_impl_mockchain::certificate::{Certificate, EvmMapping};
use jormungandr_lib::interfaces::Certificate as CertificateType;
use std::path::PathBuf;
Expand All @@ -16,7 +16,7 @@ pub struct EvmMapCmd {
#[structopt(name = "ACCOUNT_KEY", parse(try_from_str = parse_pub_key))]
account_id: PublicKey<Ed25519>,
/// hex encoded H160 address
evm_address: Address,
evm_address: H160,
/// write the output to the given file or print it to the standard output if not defined
#[structopt(short = "o", long = "output")]
output: Option<PathBuf>,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -175,9 +175,6 @@ pub enum FromConfigParamsError {
KesUpdateSpeed(#[from] super::kes_update_speed::TryFromKesUpdateSpeedError),
#[error("Invalid FeesGoTo setting")]
FeesGoTo(#[from] super::fees_go_to::TryFromFeesGoToError),
#[cfg(feature = "evm")]
#[error("Invalid EvmEnvSettings setting")]
EvmEnvSettings(#[from] crate::interfaces::evm_params::TryFromEvmEnvSettingsError),
}

impl TryFrom<ConfigParams> for BlockchainConfiguration {
Expand Down Expand Up @@ -344,7 +341,7 @@ impl BlockchainConfiguration {
}
#[cfg(feature = "evm")]
ConfigParam::EvmEnvironment(params) => evm_env_settings
.replace(params.try_into()?)
.replace(params.into())
.map(|_| "evm_evn_settings"),
}
.map(|name| Err(FromConfigParamsError::InitConfigParamDuplicate { name }))
Expand Down
5 changes: 1 addition & 4 deletions jormungandr-lib/src/interfaces/config_params.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,9 +77,6 @@ pub enum FromConfigParamError {
ActiveSlotCoefficient(#[from] super::block0_configuration::TryFromActiveSlotCoefficientError),
#[error("Invalid KES Update speed value")]
KesUpdateSpeed(#[from] super::block0_configuration::TryFromKesUpdateSpeedError),
#[cfg(feature = "evm")]
#[error("Invalid EvmEnvSettings value")]
EvmEnvSettings(#[from] super::evm_params::TryFromEvmEnvSettingsError),
}

impl From<ConfigParams> for ConfigParamsLib {
Expand Down Expand Up @@ -174,7 +171,7 @@ impl TryFrom<ConfigParamLib> for ConfigParam {
#[cfg(feature = "evm")]
ConfigParamLib::EvmConfiguration(val) => Self::EvmConfiguration(val.into()),
#[cfg(feature = "evm")]
ConfigParamLib::EvmEnvironment(val) => Self::EvmEnvironment(val.try_into()?),
ConfigParamLib::EvmEnvironment(val) => Self::EvmEnvironment(val.into()),
})
}
}
Expand Down
17 changes: 4 additions & 13 deletions jormungandr-lib/src/interfaces/evm_params.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
use chain_impl_mockchain::{config, evm};
use serde::{Deserialize, Serialize};
use std::convert::TryFrom;
use thiserror::Error;

#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)]
pub enum EvmConfig {
Expand Down Expand Up @@ -39,19 +37,12 @@ pub struct EvmEnvSettings {
block_gas_limit: u64,
}

#[derive(Debug, Error)]
pub enum TryFromEvmEnvSettingsError {
#[error("Incompatible Config param, expected EvmEnvSettings")]
Incompatible,
}

impl TryFrom<config::EvmEnvSettings> for EvmEnvSettings {
type Error = TryFromEvmEnvSettingsError;
fn try_from(val: config::EvmEnvSettings) -> Result<Self, Self::Error> {
Ok(Self {
impl From<config::EvmEnvSettings> for EvmEnvSettings {
fn from(val: config::EvmEnvSettings) -> Self {
Self {
gas_price: val.gas_price,
block_gas_limit: val.block_gas_limit,
})
}
}
}

Expand Down
23 changes: 15 additions & 8 deletions jormungandr/src/jrpc/eth_block_info/logic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,22 +5,29 @@ use crate::{
};
use chain_evm::ethereum_types::H256;

pub fn get_block_by_hash(
_hash: H256,
pub async fn get_block_by_hash(
hash: H256,
full: bool,
_context: &Context,
context: &Context,
) -> Result<Option<Block>, Error> {
// TODO implement
Ok(Some(Block::build(full)))
let blockchain_tip = context.blockchain_tip()?.get_ref().await;
let gas_limit = blockchain_tip.ledger().evm_block_gas_limit();
let gas_price = blockchain_tip.ledger().evm_gas_price();
let block = context.blockchain()?.storage().get(hash.0.into())?;
Ok(block.map(|block| Block::build(block, full, gas_limit, gas_price)))
}

pub fn get_block_by_number(
pub async fn get_block_by_number(
_number: BlockNumber,
full: bool,
_context: &Context,
context: &Context,
) -> Result<Option<Block>, Error> {
// TODO implement
Ok(Some(Block::build(full)))
let block = context.blockchain()?.storage().get([0; 32].into())?;
let blockchain_tip = context.blockchain_tip()?.get_ref().await;
let gas_limit = blockchain_tip.ledger().evm_block_gas_limit();
let gas_price = blockchain_tip.ledger().evm_gas_price();
Ok(block.map(|block| Block::build(block, full, gas_limit, gas_price)))
}

pub fn get_transaction_count_by_hash(
Expand Down
9 changes: 8 additions & 1 deletion jormungandr/src/jrpc/eth_block_info/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,12 @@ use jsonrpsee_http_server::RpcModule;
mod logic;

#[derive(Debug, thiserror::Error)]
pub enum Error {}
pub enum Error {
#[error(transparent)]
ContextError(#[from] crate::context::Error),
#[error(transparent)]
Storage(#[from] crate::blockchain::StorageError),
}

pub fn eth_block_info_module(context: ContextLock) -> RpcModule<ContextLock> {
let mut module = RpcModule::new(context);
Expand All @@ -14,6 +19,7 @@ pub fn eth_block_info_module(context: ContextLock) -> RpcModule<ContextLock> {
let context = context.read().await;
let (block_hash, full) = params.parse()?;
logic::get_block_by_hash(block_hash, full, &context)
.await
.map_err(|err| jsonrpsee_core::Error::Custom(err.to_string()))
})
.unwrap();
Expand All @@ -23,6 +29,7 @@ pub fn eth_block_info_module(context: ContextLock) -> RpcModule<ContextLock> {
let context = context.read().await;
let (block_number, full) = params.parse()?;
logic::get_block_by_number(block_number, full, &context)
.await
.map_err(|err| jsonrpsee_core::Error::Custom(err.to_string()))
})
.unwrap();
Expand Down
6 changes: 3 additions & 3 deletions jormungandr/src/jrpc/eth_transaction/logic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ pub fn get_transaction_by_hash(
_context: &Context,
) -> Result<Option<Transaction>, Error> {
// TODO implement
Ok(Some(Transaction::build()))
Ok(None)
}

pub fn get_transaction_by_block_hash_and_index(
Expand All @@ -32,7 +32,7 @@ pub fn get_transaction_by_block_hash_and_index(
_context: &Context,
) -> Result<Option<Transaction>, Error> {
// TODO implement
Ok(Some(Transaction::build()))
Ok(None)
}

pub fn get_transaction_by_block_number_and_index(
Expand All @@ -41,7 +41,7 @@ pub fn get_transaction_by_block_number_and_index(
_context: &Context,
) -> Result<Option<Transaction>, Error> {
// TODO implement
Ok(Some(Transaction::build()))
Ok(None)
}

pub fn get_transaction_receipt(_hash: H256, _context: &Context) -> Result<Option<Receipt>, Error> {
Expand Down
124 changes: 87 additions & 37 deletions jormungandr/src/jrpc/eth_types/block.rs
Original file line number Diff line number Diff line change
@@ -1,34 +1,21 @@
use super::{bytes::Bytes, number::Number, transaction::Transaction};
use chain_core::property::Serialize;
use chain_evm::ethereum_types::{Bloom, H160, H256};
use serde::{Serialize, Serializer};
use chain_impl_mockchain::{
block::{Block as JorBlock, Header as JorHeader},
fragment::Fragment,
};

/// Block Transactions
#[derive(Debug)]
#[derive(Debug, Serialize)]
#[serde(untagged)]
pub enum BlockTransactions {
/// Only hashes
Hashes(Vec<H256>),
/// Full transactions
Full(Vec<Transaction>),
}

impl Default for BlockTransactions {
fn default() -> Self {
Self::Hashes(Vec::new())
}
}

impl Serialize for BlockTransactions {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
match *self {
BlockTransactions::Hashes(ref hashes) => hashes.serialize(serializer),
BlockTransactions::Full(ref ts) => ts.serialize(serializer),
}
}
}

/// Block header representation.
#[derive(Debug, Serialize, PartialEq, Eq)]
#[serde(rename_all = "camelCase")]
Expand Down Expand Up @@ -69,24 +56,27 @@ pub struct Header {
}

impl Header {
pub fn build() -> Self {
pub fn build(header: JorHeader, gas_limit: u64) -> Self {
Self {
hash: H256::zero(),
hash: H256::from_slice(header.hash().as_ref()),
mix_hash: H256::zero(),
nonce: 1.into(),
parent_hash: H256::zero(),
nonce: 0.into(),
parent_hash: H256::from_slice(header.block_parent_hash().as_ref()),
uncles_hash: H256::zero(),
miner: H160::zero(),
miner: header
.get_bft_leader_id()
.map(|id| H160::from_slice(id.as_ref()))
.unwrap_or_else(H160::zero),
state_root: H256::zero(),
transactions_root: H256::zero(),
transactions_root: H256::from_slice(header.block_content_hash().as_ref()),
receipts_root: H256::zero(),
number: 1.into(),
gas_used: 1.into(),
gas_limit: 1.into(),
number: Into::<u64>::into(Into::<u32>::into(header.chain_length())).into(),
gas_used: 0.into(),
gas_limit: gas_limit.into(),
extra_data: Bytes::default(),
logs_bloom: Bloom::zero(),
timestamp: 1.into(),
difficulty: Some(1.into()),
timestamp: 0.into(),
difficulty: Some(0.into()),
}
}
}
Expand All @@ -111,21 +101,81 @@ pub struct Block {
}

impl Block {
pub fn build(full: bool) -> Self {
let header = Header::build();
pub fn build(block: JorBlock, full: bool, gas_limit: u64, gas_price: u64) -> Self {
let header = Header::build(block.header().clone(), gas_limit);
let transactions = if full {
BlockTransactions::Full(vec![Transaction::build()])
let mut res = Vec::new();
for (i, fragment) in block.fragments().enumerate() {
if let Fragment::Evm(evm_tx) = fragment {
let evm_tx = evm_tx.as_slice().payload().into_payload();
res.push(Transaction::build(
evm_tx,
Some(header.hash),
Some(header.number.clone()),
Some((i as u64).into()),
gas_price,
));
}
}
BlockTransactions::Full(res)
} else {
BlockTransactions::Hashes(vec![H256::zero()])
let mut res = Vec::new();
for fragment in block.fragments() {
if let Fragment::Evm(evm_tx) = fragment {
res.push(H256::from_slice(evm_tx.hash().as_ref()));
}
}
BlockTransactions::Hashes(res)
};

Self {
header,
total_difficulty: 1.into(),
total_difficulty: 0.into(),
uncles: Default::default(),
transactions,
size: 1.into(),
size: (block.serialized_size() as u64).into(),
base_fee_per_gas: Some(1.into()),
}
}
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn block_serialize() {
let header = Header {
hash: H256::zero(),
mix_hash: H256::zero(),
nonce: 0.into(),
parent_hash: H256::zero(),
uncles_hash: H256::zero(),
miner: H160::zero(),
state_root: H256::zero(),
transactions_root: H256::zero(),
receipts_root: H256::zero(),
number: 0.into(),
gas_used: 0.into(),
gas_limit: 0.into(),
extra_data: Bytes::default(),
logs_bloom: Bloom::zero(),
timestamp: 0.into(),
difficulty: Some(0.into()),
};

let block = Block {
header,
total_difficulty: 0.into(),
uncles: Default::default(),
transactions: BlockTransactions::Hashes(vec![H256::zero()]),
size: 0.into(),
base_fee_per_gas: Some(0.into()),
};

assert_eq!(
serde_json::to_string(&block).unwrap(),
r#"{"hash":"0x0000000000000000000000000000000000000000000000000000000000000000","mixHash":"0x0000000000000000000000000000000000000000000000000000000000000000","nonce":"0x0","parentHash":"0x0000000000000000000000000000000000000000000000000000000000000000","sha3Uncles":"0x0000000000000000000000000000000000000000000000000000000000000000","miner":"0x0000000000000000000000000000000000000000","stateRoot":"0x0000000000000000000000000000000000000000000000000000000000000000","transactionsRoot":"0x0000000000000000000000000000000000000000000000000000000000000000","receiptsRoot":"0x0000000000000000000000000000000000000000000000000000000000000000","number":"0x0","gasUsed":"0x0","gasLimit":"0x0","extraData":"0x","logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","timestamp":"0x0","difficulty":"0x0","totalDifficulty":"0x0","uncles":[],"transactions":["0x0000000000000000000000000000000000000000000000000000000000000000"],"size":"0x0","baseFeePerGas":"0x0"}"#
);
}
}
6 changes: 6 additions & 0 deletions jormungandr/src/jrpc/eth_types/bytes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,12 @@ use std::fmt;
#[derive(Debug, Clone, PartialEq, Eq, Default)]
pub struct Bytes(Box<[u8]>);

impl From<Box<[u8]>> for Bytes {
fn from(val: Box<[u8]>) -> Self {
Self(val)
}
}

impl Serialize for Bytes {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
Expand Down
2 changes: 1 addition & 1 deletion jormungandr/src/jrpc/eth_types/number.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use serde::{
use std::fmt;

/// Represents usize.
#[derive(Debug, PartialEq, Eq)]
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Number(u64);

impl From<u64> for Number {
Expand Down
Loading

0 comments on commit 04e2143

Please sign in to comment.