diff --git a/jcli/Cargo.toml b/jcli/Cargo.toml index 2b23e682b5..1f4ea86a0c 100644 --- a/jcli/Cargo.toml +++ b/jcli/Cargo.toml @@ -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" diff --git a/jcli/src/jcli_lib/certificate/new_evm_mapping.rs b/jcli/src/jcli_lib/certificate/new_evm_mapping.rs index 0d2e34f16e..3a67da8b8e 100644 --- a/jcli/src/jcli_lib/certificate/new_evm_mapping.rs +++ b/jcli/src/jcli_lib/certificate/new_evm_mapping.rs @@ -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; @@ -16,7 +16,7 @@ pub struct EvmMapCmd { #[structopt(name = "ACCOUNT_KEY", parse(try_from_str = parse_pub_key))] account_id: PublicKey, /// 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, diff --git a/jormungandr-lib/src/interfaces/block0_configuration/initial_config.rs b/jormungandr-lib/src/interfaces/block0_configuration/initial_config.rs index 3066ef052e..eb2de2c413 100644 --- a/jormungandr-lib/src/interfaces/block0_configuration/initial_config.rs +++ b/jormungandr-lib/src/interfaces/block0_configuration/initial_config.rs @@ -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 for BlockchainConfiguration { @@ -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 })) diff --git a/jormungandr-lib/src/interfaces/config_params.rs b/jormungandr-lib/src/interfaces/config_params.rs index 0227f4ddc7..79515b513f 100644 --- a/jormungandr-lib/src/interfaces/config_params.rs +++ b/jormungandr-lib/src/interfaces/config_params.rs @@ -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 for ConfigParamsLib { @@ -174,7 +171,7 @@ impl TryFrom 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()), }) } } diff --git a/jormungandr-lib/src/interfaces/evm_params.rs b/jormungandr-lib/src/interfaces/evm_params.rs index b4c9a69bf9..6b6b4cde10 100644 --- a/jormungandr-lib/src/interfaces/evm_params.rs +++ b/jormungandr-lib/src/interfaces/evm_params.rs @@ -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 { @@ -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 for EvmEnvSettings { - type Error = TryFromEvmEnvSettingsError; - fn try_from(val: config::EvmEnvSettings) -> Result { - Ok(Self { +impl From for EvmEnvSettings { + fn from(val: config::EvmEnvSettings) -> Self { + Self { gas_price: val.gas_price, block_gas_limit: val.block_gas_limit, - }) + } } } diff --git a/jormungandr/src/jrpc/eth_block_info/logic.rs b/jormungandr/src/jrpc/eth_block_info/logic.rs index 32692c7157..eda30b1bb6 100644 --- a/jormungandr/src/jrpc/eth_block_info/logic.rs +++ b/jormungandr/src/jrpc/eth_block_info/logic.rs @@ -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, 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, 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( diff --git a/jormungandr/src/jrpc/eth_block_info/mod.rs b/jormungandr/src/jrpc/eth_block_info/mod.rs index 4a1cbfb765..67a0c29be4 100644 --- a/jormungandr/src/jrpc/eth_block_info/mod.rs +++ b/jormungandr/src/jrpc/eth_block_info/mod.rs @@ -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 { let mut module = RpcModule::new(context); @@ -14,6 +19,7 @@ pub fn eth_block_info_module(context: ContextLock) -> RpcModule { 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(); @@ -23,6 +29,7 @@ pub fn eth_block_info_module(context: ContextLock) -> RpcModule { 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(); diff --git a/jormungandr/src/jrpc/eth_transaction/logic.rs b/jormungandr/src/jrpc/eth_transaction/logic.rs index 7f479999be..1267d522fe 100644 --- a/jormungandr/src/jrpc/eth_transaction/logic.rs +++ b/jormungandr/src/jrpc/eth_transaction/logic.rs @@ -23,7 +23,7 @@ pub fn get_transaction_by_hash( _context: &Context, ) -> Result, Error> { // TODO implement - Ok(Some(Transaction::build())) + Ok(None) } pub fn get_transaction_by_block_hash_and_index( @@ -32,7 +32,7 @@ pub fn get_transaction_by_block_hash_and_index( _context: &Context, ) -> Result, Error> { // TODO implement - Ok(Some(Transaction::build())) + Ok(None) } pub fn get_transaction_by_block_number_and_index( @@ -41,7 +41,7 @@ pub fn get_transaction_by_block_number_and_index( _context: &Context, ) -> Result, Error> { // TODO implement - Ok(Some(Transaction::build())) + Ok(None) } pub fn get_transaction_receipt(_hash: H256, _context: &Context) -> Result, Error> { diff --git a/jormungandr/src/jrpc/eth_types/block.rs b/jormungandr/src/jrpc/eth_types/block.rs index a5ab82552d..8503883e96 100644 --- a/jormungandr/src/jrpc/eth_types/block.rs +++ b/jormungandr/src/jrpc/eth_types/block.rs @@ -1,9 +1,14 @@ 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), @@ -11,24 +16,6 @@ pub enum BlockTransactions { Full(Vec), } -impl Default for BlockTransactions { - fn default() -> Self { - Self::Hashes(Vec::new()) - } -} - -impl Serialize for BlockTransactions { - fn serialize(&self, serializer: S) -> Result - 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")] @@ -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::::into(Into::::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()), } } } @@ -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"}"# + ); + } +} diff --git a/jormungandr/src/jrpc/eth_types/bytes.rs b/jormungandr/src/jrpc/eth_types/bytes.rs index 4d570b4a7e..bab469ee02 100644 --- a/jormungandr/src/jrpc/eth_types/bytes.rs +++ b/jormungandr/src/jrpc/eth_types/bytes.rs @@ -4,6 +4,12 @@ use std::fmt; #[derive(Debug, Clone, PartialEq, Eq, Default)] pub struct Bytes(Box<[u8]>); +impl From> for Bytes { + fn from(val: Box<[u8]>) -> Self { + Self(val) + } +} + impl Serialize for Bytes { fn serialize(&self, serializer: S) -> Result where diff --git a/jormungandr/src/jrpc/eth_types/number.rs b/jormungandr/src/jrpc/eth_types/number.rs index cea6bbad77..33284dbdc6 100644 --- a/jormungandr/src/jrpc/eth_types/number.rs +++ b/jormungandr/src/jrpc/eth_types/number.rs @@ -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 for Number { diff --git a/jormungandr/src/jrpc/eth_types/transaction.rs b/jormungandr/src/jrpc/eth_types/transaction.rs index fab608dff0..c96c24e303 100644 --- a/jormungandr/src/jrpc/eth_types/transaction.rs +++ b/jormungandr/src/jrpc/eth_types/transaction.rs @@ -1,5 +1,6 @@ use super::{bytes::Bytes, number::Number}; use chain_evm::ethereum_types::{H160, H256, U256}; +use chain_impl_mockchain::evm::EvmTransaction; use serde::{Deserialize, Serialize}; #[derive(Debug, PartialEq, Eq, Serialize, Deserialize)] @@ -39,23 +40,85 @@ pub struct Transaction { } impl Transaction { - pub fn build() -> Self { - Self { - block_hash: None, - block_number: None, - nonce: 1.into(), - from: H160::zero(), - to: Some(H160::zero()), - value: 1.into(), - gas: 1.into(), - input: Default::default(), - gas_price: 1.into(), - chain_id: Some(1.into()), - transaction_index: None, - v: 1.into(), - r: U256::one(), - s: U256::one(), - transaction_type: 1.into(), + pub fn build( + tx: EvmTransaction, + block_hash: Option, + block_number: Option, + transaction_index: Option, + gas_price: u64, + ) -> Self { + match tx { + EvmTransaction::Call { + caller, + address, + value, + data, + gas_limit, + access_list: _, + } => Self { + block_hash, + block_number, + nonce: 1.into(), + from: caller, + to: Some(address), + value: value.into(), + gas: gas_limit.into(), + input: data.into(), + gas_price: gas_price.into(), + chain_id: Some(1.into()), + transaction_index, + v: 1.into(), + r: U256::one(), + s: U256::one(), + transaction_type: 1.into(), + }, + EvmTransaction::Create { + caller, + value, + init_code, + gas_limit, + access_list: _, + } => Self { + block_hash, + block_number, + nonce: 1.into(), + from: caller, + to: None, + value: value.into(), + gas: gas_limit.into(), + input: init_code.into(), + gas_price: gas_price.into(), + chain_id: Some(1.into()), + transaction_index, + v: 1.into(), + r: U256::one(), + s: U256::one(), + transaction_type: 1.into(), + }, + EvmTransaction::Create2 { + caller, + value, + init_code, + salt: _, + gas_limit, + access_list: _, + } => Self { + block_hash, + block_number, + nonce: 1.into(), + from: caller, + to: None, + value: value.into(), + gas: gas_limit.into(), + input: init_code.into(), + gas_price: gas_price.into(), + chain_id: Some(1.into()), + transaction_index, + v: 1.into(), + r: U256::one(), + s: U256::one(), + transaction_type: 1.into(), + }, } } } @@ -87,8 +150,9 @@ mod tests { serde_json::to_string(&transaction).unwrap(), r#"{"blockHash":null,"blockNumber":null,"nonce":"0x0","from":"0x0000000000000000000000000000000000000000","to":"0x0000000000000000000000000000000000000000","value":"0x0","gas":"0x0","input":"0x","gasPrice":"0x0","chainId":"0x0","transactionIndex":null,"v":"0x0","r":"0x0","s":"0x0","type":"0x0"}"# ); - let decoded: Transaction = serde_json::from_str(r#"{"blockHash":null,"blockNumber":null,"nonce":"0x0","from":"0x0000000000000000000000000000000000000000","to":"0x0000000000000000000000000000000000000000","value":"0x0","gas":"0x0","input":"0x","gasPrice":"0x0","chainId":"0x0","transactionIndex":null,"v":"0x0","r":"0x0","s":"0x0","type":"0x0"}"# - ).unwrap(); + let decoded: Transaction = serde_json::from_str(r#"{"blockHash":null,"blockNumber":null,"nonce":"0x0","from":"0x0000000000000000000000000000000000000000","to":"0x0000000000000000000000000000000000000000","value":"0x0","gas":"0x0","input":"0x","gasPrice":"0x0","chainId":"0x0","transactionIndex":null,"v":"0x0","r":"0x0","s":"0x0","type":"0x0"}"#).unwrap(); assert_eq!(decoded, transaction); + let decoded_without_nulls: Transaction = serde_json::from_str(r#"{"nonce":"0x0","from":"0x0000000000000000000000000000000000000000","to":"0x0000000000000000000000000000000000000000","value":"0x0","gas":"0x0","input":"0x","gasPrice":"0x0","chainId":"0x0","v":"0x0","r":"0x0","s":"0x0","type":"0x0"}"#).unwrap(); + assert_eq!(decoded_without_nulls, transaction); } }