From e078ae78bb5682ef8d123d4fbe5ff22c63cd7033 Mon Sep 17 00:00:00 2001 From: Shoham Chakraborty Date: Mon, 10 Apr 2023 16:49:20 +0800 Subject: [PATCH 01/13] Store ethereum blocks in BlockManager --- src/rust/Cargo.lock | 11 +++ src/rust/crates/ain-evm-state/src/evm.rs | 50 ------------- src/rust/crates/ain-evm-state/src/handler.rs | 74 ++++++++++++++++++++ 3 files changed, 85 insertions(+), 50 deletions(-) diff --git a/src/rust/Cargo.lock b/src/rust/Cargo.lock index 6ea80466da9..54138578421 100644 --- a/src/rust/Cargo.lock +++ b/src/rust/Cargo.lock @@ -83,6 +83,7 @@ dependencies = [ "cxx-gen", "env_logger", "ethereum", + "fake", "heck", "jsonrpsee-core", "jsonrpsee-http-client", @@ -96,6 +97,7 @@ dependencies = [ "prost", "prost-build", "quote", + "rand", "regex", "serde", "serde_json", @@ -597,6 +599,15 @@ dependencies = [ "sha3", ] +[[package]] +name = "fake" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d68f517805463f3a896a9d29c1d6ff09d3579ded64a7201b4069f8f9c0d52fd" +dependencies = [ + "rand", +] + [[package]] name = "fastrand" version = "1.9.0" diff --git a/src/rust/crates/ain-evm-state/src/evm.rs b/src/rust/crates/ain-evm-state/src/evm.rs index d39aeb22c1c..b18be07c7f2 100644 --- a/src/rust/crates/ain-evm-state/src/evm.rs +++ b/src/rust/crates/ain-evm-state/src/evm.rs @@ -140,56 +140,6 @@ impl EVMHandler { self.tx_queues.add_signed_tx(context, signed_tx); Ok(()) } - - pub fn finalize_block( - &self, - context: u64, - update_state: bool, - ) -> Result<(Block, Vec), Box> { - let mut tx_hashes = Vec::with_capacity(self.tx_queues.len(context)); - let mut failed_tx_hashes = Vec::with_capacity(self.tx_queues.len(context)); - let vicinity = get_vicinity(None, None); - let state = self.tx_queues.state(context).expect("Wrong context"); - let backend = MemoryBackend::new(&vicinity, state); - let mut executor = AinExecutor::new(backend); - - for signed_tx in self.tx_queues.drain_all(context) { - let tx_response = executor.exec(&signed_tx); - if tx_response.exit_reason.is_succeed() { - tx_hashes.push(signed_tx.transaction); - } else { - failed_tx_hashes.push(signed_tx.transaction) - } - } - - self.tx_queues.remove(context); - - if update_state { - let mut state = self.state.write().unwrap(); - *state = executor.backend().state().clone(); - } - - let block = Block::new( - PartialHeader { - parent_hash: Default::default(), - beneficiary: Default::default(), - state_root: Default::default(), - receipts_root: Default::default(), - logs_bloom: Default::default(), - difficulty: Default::default(), - number: Default::default(), - gas_limit: Default::default(), - gas_used: Default::default(), - timestamp: Default::default(), - extra_data: Default::default(), - mix_hash: Default::default(), - nonce: Default::default(), - }, - tx_hashes, - Vec::new(), - ); - Ok((block, failed_tx_hashes)) - } } impl EVMHandler { diff --git a/src/rust/crates/ain-evm-state/src/handler.rs b/src/rust/crates/ain-evm-state/src/handler.rs index 14d18e501ef..8a660dccbd2 100644 --- a/src/rust/crates/ain-evm-state/src/handler.rs +++ b/src/rust/crates/ain-evm-state/src/handler.rs @@ -1,3 +1,9 @@ +use std::error::Error; +use ethereum::{Block, PartialHeader, TransactionV2}; +use evm::backend::{MemoryBackend, MemoryVicinity}; +use primitive_types::{H160, U256}; +use ain_evm::executor::AinExecutor; +use ain_evm::traits::Executor; use crate::block::BlockHandler; use crate::evm::EVMHandler; @@ -13,4 +19,72 @@ impl Handlers { block: BlockHandler::new(), } } + + pub fn finalize_block( + &self, + context: u64, + update_state: bool, + ) -> Result<(Block, Vec), Box> { + let mut tx_hashes = Vec::with_capacity(self.evm.tx_queues.len(context)); + let mut failed_tx_hashes = Vec::with_capacity(self.evm.tx_queues.len(context)); + let vicinity = get_vicinity(None, None); + let state = self.evm.tx_queues.state(context).expect("Wrong context"); + let backend = MemoryBackend::new(&vicinity, state); + let mut executor = AinExecutor::new(backend); + + for signed_tx in self.evm.tx_queues.drain_all(context) { + let tx_response = executor.exec(&signed_tx); + if tx_response.exit_reason.is_succeed() { + tx_hashes.push(signed_tx.transaction); + } else { + failed_tx_hashes.push(signed_tx.transaction) + } + } + + self.evm.tx_queues.remove(context); + + if update_state { + let mut state = self.evm.state.write().unwrap(); + *state = executor.backend().state().clone(); + } + + let block = Block::new( + PartialHeader { + parent_hash: Default::default(), + beneficiary: Default::default(), + state_root: Default::default(), + receipts_root: Default::default(), + logs_bloom: Default::default(), + difficulty: Default::default(), + number: Default::default(), + gas_limit: Default::default(), + gas_used: Default::default(), + timestamp: Default::default(), + extra_data: Default::default(), + mix_hash: Default::default(), + nonce: Default::default(), + }, + tx_hashes, + Vec::new(), + ); + + self.block.connect_block(block.clone()); + + Ok((block, failed_tx_hashes)) + } +} + +fn get_vicinity(origin: Option, gas_price: Option) -> MemoryVicinity { + MemoryVicinity { + gas_price: gas_price.unwrap_or(U256::MAX), + origin: origin.unwrap_or_default(), + block_hashes: Vec::new(), + block_number: Default::default(), + block_coinbase: Default::default(), + block_timestamp: Default::default(), + block_difficulty: Default::default(), + block_gas_limit: U256::MAX, + chain_id: U256::one(), + block_base_fee_per_gas: U256::MAX, + } } From a6a2ae1d5ea3a64c78c1d5af4db2d1d72589ccbd Mon Sep 17 00:00:00 2001 From: Shoham Chakraborty Date: Mon, 10 Apr 2023 16:50:32 +0800 Subject: [PATCH 02/13] Update ffi call --- src/rust/crates/ain-evm-ffi/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/rust/crates/ain-evm-ffi/src/lib.rs b/src/rust/crates/ain-evm-ffi/src/lib.rs index 280132c3705..ca4b136521f 100644 --- a/src/rust/crates/ain-evm-ffi/src/lib.rs +++ b/src/rust/crates/ain-evm-ffi/src/lib.rs @@ -87,6 +87,6 @@ fn evm_queue_tx(context: u64, raw_tx: &str) -> Result> { use rlp::Encodable; fn evm_finalise(context: u64, update_state: bool) -> Result, Box> { - let (block, _failed_tx) = RUNTIME.handlers.evm.finalize_block(context, update_state)?; + let (block, _failed_tx) = RUNTIME.handlers.finalize_block(context, update_state)?; Ok(block.header.rlp_bytes().into()) } From c8547e5e55c952144c1a23e0459981f94d5f13a1 Mon Sep 17 00:00:00 2001 From: Shoham Chakraborty Date: Tue, 11 Apr 2023 13:02:15 +0800 Subject: [PATCH 03/13] eth_blockNumber and eth_getBlockByCount implementations --- src/rust/Cargo.lock | 11 ---- src/rust/crates/ain-evm-state/src/block.rs | 20 ++++-- src/rust/crates/ain-evm-state/src/handler.rs | 11 +++- src/rust/crates/ain-grpc/build.rs | 2 +- src/rust/crates/ain-grpc/src/rpc.rs | 68 +++++++++++++++++++- src/rust/protobuf/rpc/eth.proto | 4 ++ 6 files changed, 93 insertions(+), 23 deletions(-) diff --git a/src/rust/Cargo.lock b/src/rust/Cargo.lock index 54138578421..6ea80466da9 100644 --- a/src/rust/Cargo.lock +++ b/src/rust/Cargo.lock @@ -83,7 +83,6 @@ dependencies = [ "cxx-gen", "env_logger", "ethereum", - "fake", "heck", "jsonrpsee-core", "jsonrpsee-http-client", @@ -97,7 +96,6 @@ dependencies = [ "prost", "prost-build", "quote", - "rand", "regex", "serde", "serde_json", @@ -599,15 +597,6 @@ dependencies = [ "sha3", ] -[[package]] -name = "fake" -version = "2.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d68f517805463f3a896a9d29c1d6ff09d3579ded64a7201b4069f8f9c0d52fd" -dependencies = [ - "rand", -] - [[package]] name = "fastrand" version = "1.9.0" diff --git a/src/rust/crates/ain-evm-state/src/block.rs b/src/rust/crates/ain-evm-state/src/block.rs index 89d1a49b939..0ad92caab26 100644 --- a/src/rust/crates/ain-evm-state/src/block.rs +++ b/src/rust/crates/ain-evm-state/src/block.rs @@ -12,7 +12,7 @@ use std::sync::{Arc, RwLock}; pub static BLOCK_MAP_PATH: &str = "block_map.bin"; pub static BLOCK_DATA_PATH: &str = "block_data.bin"; -type BlockHashtoBlock = HashMap; +type BlockHashtoBlock = HashMap; type Blocks = Vec; pub struct BlockHandler { @@ -33,7 +33,7 @@ impl PersistentState for BlockHashtoBlock { let mut file = File::open(path)?; let mut data = Vec::new(); file.read_to_end(&mut data)?; - let new_state: HashMap = bincode::deserialize(&data)?; + let new_state: HashMap = bincode::deserialize(&data)?; Ok(new_state) } else { Ok(Self::new()) @@ -79,7 +79,7 @@ impl BlockHandler { blocks.push(block.clone()); let mut blockhash = self.block_map.write().unwrap(); - blockhash.insert(block.header.hash(), block.header.number); + blockhash.insert(block.header.hash(), blocks.len() + 1); } pub fn flush(&self) -> Result<(), PersistentStateError> { @@ -90,7 +90,7 @@ impl BlockHandler { self.blocks.write().unwrap().save_to_disk(BLOCK_DATA_PATH) } - pub fn get_block_hash(&self, hash: H256) -> Result { + pub fn get_block_by_hash(&self, hash: H256) -> Result { let block_map = self.block_map.read().unwrap(); let block_number = *block_map .get(&hash) @@ -98,7 +98,17 @@ impl BlockHandler { let blocks = self.blocks.read().unwrap(); let block = blocks - .get(block_number.as_usize()) + .get(block_number) + .ok_or(BlockHandlerError::BlockNotFound)? + .clone(); + + Ok(block) + } + + pub fn get_block_by_number(&self, count: usize) -> Result { + let blocks = self.blocks.read().unwrap(); + let block = blocks + .get(count) .ok_or(BlockHandlerError::BlockNotFound)? .clone(); diff --git a/src/rust/crates/ain-evm-state/src/handler.rs b/src/rust/crates/ain-evm-state/src/handler.rs index 8a660dccbd2..1a41c640d28 100644 --- a/src/rust/crates/ain-evm-state/src/handler.rs +++ b/src/rust/crates/ain-evm-state/src/handler.rs @@ -1,4 +1,5 @@ use std::error::Error; +use std::time::{SystemTime, UNIX_EPOCH}; use ethereum::{Block, PartialHeader, TransactionV2}; use evm::backend::{MemoryBackend, MemoryVicinity}; use primitive_types::{H160, U256}; @@ -48,18 +49,22 @@ impl Handlers { *state = executor.backend().state().clone(); } + let blocks = self.block.blocks.read().unwrap(); + let parent_block = blocks.first().unwrap(); + let number = blocks.len() + 1; + let block = Block::new( PartialHeader { - parent_hash: Default::default(), + parent_hash: parent_block.header.hash(), beneficiary: Default::default(), state_root: Default::default(), receipts_root: Default::default(), logs_bloom: Default::default(), difficulty: Default::default(), - number: Default::default(), + number: U256::from(number), gas_limit: Default::default(), gas_used: Default::default(), - timestamp: Default::default(), + timestamp: SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_millis() as u64, extra_data: Default::default(), mix_hash: Default::default(), nonce: Default::default(), diff --git a/src/rust/crates/ain-grpc/build.rs b/src/rust/crates/ain-grpc/build.rs index fa6a8f46ae6..13f4e2e27ab 100644 --- a/src/rust/crates/ain-grpc/build.rs +++ b/src/rust/crates/ain-grpc/build.rs @@ -642,7 +642,7 @@ fn apply_substitutions( .url .as_ref() .map(String::from) - .unwrap_or_else(|| method.name.to_lower_camel_case()); + .unwrap_or_else(|| method.name.to_lowercase()); if method.client { funcs.extend(quote! { #[allow(non_snake_case)] diff --git a/src/rust/crates/ain-grpc/src/rpc.rs b/src/rust/crates/ain-grpc/src/rpc.rs index 1fe582ab6b5..2002fc08f8e 100644 --- a/src/rust/crates/ain-grpc/src/rpc.rs +++ b/src/rust/crates/ain-grpc/src/rpc.rs @@ -1,7 +1,8 @@ use crate::codegen::rpc::{ ffi::{ - EthAccountsResult, EthBlockInfo, EthCallInput, EthCallResult, EthGetBalanceInput, - EthGetBalanceResult, EthGetBlockByHashInput, EthGetBlockByHashResult, EthTransactionInfo, + EthAccountsResult, EthBlockInfo, EthBlockNumberResult, EthCallInput, EthCallResult, + EthGetBalanceInput, EthGetBalanceResult, EthGetBlockByHashInput, EthGetBlockByHashResult, + EthGetBlockByNumberInput, EthGetBlockByNumberResult, EthTransactionInfo, }, EthService, }; @@ -27,6 +28,15 @@ pub trait EthServiceApi { handler: Arc, input: EthGetBlockByHashInput, ) -> Result; + + fn Eth_BlockNumber( + handler: Arc, + ) -> Result; + + fn Eth_GetBlockByCount( + handler: Arc, + input: EthGetBlockByNumberInput, + ) -> Result; } impl EthServiceApi for EthService { @@ -88,7 +98,7 @@ impl EthServiceApi for EthService { let EthGetBlockByHashInput { hash, .. } = input; let hash = hash.parse().expect("Invalid hash"); - let block = handler.block.get_block_hash(hash).unwrap(); + let block = handler.block.get_block_by_hash(hash).unwrap(); Ok(EthGetBlockByHashResult { block_info: EthBlockInfo { @@ -122,4 +132,56 @@ impl EthServiceApi for EthService { }, }) } + + fn Eth_BlockNumber( + handler: Arc, + ) -> Result { + let count = handler.block.blocks.read().unwrap().len(); + + Ok(EthBlockNumberResult { + block_number: format!("0x{:x}", count), + }) + } + + fn Eth_GetBlockByCount( + handler: Arc, + input: EthGetBlockByNumberInput, + ) -> Result { + let EthGetBlockByNumberInput { number, .. } = input; + + let number: usize = number.parse().ok().unwrap(); + let block = handler.block.get_block_by_number(number).unwrap(); + + Ok(EthGetBlockByNumberResult { + block_info: EthBlockInfo { + block_number: block.header.number.to_string(), + hash: block.header.hash().to_string(), + parent_hash: block.header.parent_hash.to_string(), + nonce: block.header.nonce.to_string(), + sha3_uncles: block.header.ommers_hash.to_string(), + logs_bloom: block.header.logs_bloom.to_string(), + transactions_root: block.header.transactions_root.to_string(), + state_root: block.header.state_root.to_string(), + receipt_root: block.header.receipts_root.to_string(), + miner: block.header.beneficiary.to_string(), + difficulty: block.header.difficulty.to_string(), + total_difficulty: block.header.difficulty.to_string(), + extra_data: String::from_utf8(block.header.extra_data.clone()).unwrap(), + size: size_of_val(&block).to_string(), + gas_limit: block.header.gas_limit.to_string(), + gas_used: block.header.gas_used.to_string(), + timestamps: block.header.timestamp.to_string(), + transactions: block + .transactions + .iter() + .map(|x| x.hash().to_string()) + .collect::>(), + uncles: block + .ommers + .iter() + .map(|x| x.hash().to_string()) + .collect::>(), + }, + }) + } } diff --git a/src/rust/protobuf/rpc/eth.proto b/src/rust/protobuf/rpc/eth.proto index 5e7b4f60d77..2fed7706f35 100644 --- a/src/rust/protobuf/rpc/eth.proto +++ b/src/rust/protobuf/rpc/eth.proto @@ -19,4 +19,8 @@ service eth { /// [ignore] /// Returns the balance for the given address. rpc Eth_SendTransaction(types.EthSendTransactionInput) returns (types.EthSendTransactionResult); + + rpc Eth_BlockNumber(google.protobuf.Empty) returns (types.EthBlockNumberResult); + + rpc Eth_GetBlockByCount(types.EthGetBlockByNumberInput) returns (types.EthGetBlockByNumberResult); } From efe37591018335983a90b2b4ceb4336057b13cb3 Mon Sep 17 00:00:00 2001 From: Shoham Chakraborty Date: Tue, 11 Apr 2023 13:04:47 +0800 Subject: [PATCH 04/13] formatting --- src/rust/crates/ain-evm-state/src/handler.rs | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/src/rust/crates/ain-evm-state/src/handler.rs b/src/rust/crates/ain-evm-state/src/handler.rs index 1a41c640d28..35484203e9b 100644 --- a/src/rust/crates/ain-evm-state/src/handler.rs +++ b/src/rust/crates/ain-evm-state/src/handler.rs @@ -1,12 +1,12 @@ -use std::error::Error; -use std::time::{SystemTime, UNIX_EPOCH}; +use crate::block::BlockHandler; +use crate::evm::EVMHandler; +use ain_evm::executor::AinExecutor; +use ain_evm::traits::Executor; use ethereum::{Block, PartialHeader, TransactionV2}; use evm::backend::{MemoryBackend, MemoryVicinity}; use primitive_types::{H160, U256}; -use ain_evm::executor::AinExecutor; -use ain_evm::traits::Executor; -use crate::block::BlockHandler; -use crate::evm::EVMHandler; +use std::error::Error; +use std::time::{SystemTime, UNIX_EPOCH}; pub struct Handlers { pub evm: EVMHandler, @@ -64,7 +64,10 @@ impl Handlers { number: U256::from(number), gas_limit: Default::default(), gas_used: Default::default(), - timestamp: SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_millis() as u64, + timestamp: SystemTime::now() + .duration_since(UNIX_EPOCH) + .unwrap() + .as_millis() as u64, extra_data: Default::default(), mix_hash: Default::default(), nonce: Default::default(), From b7571a8037452e04a3783e64fbc0758609c65437 Mon Sep 17 00:00:00 2001 From: Shoham Chakraborty Date: Tue, 11 Apr 2023 13:59:02 +0800 Subject: [PATCH 05/13] Fix hanging --- src/rust/crates/ain-evm-state/src/handler.rs | 14 ++++++++++---- src/rust/crates/ain-grpc/src/rpc.rs | 4 ++-- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/src/rust/crates/ain-evm-state/src/handler.rs b/src/rust/crates/ain-evm-state/src/handler.rs index 35484203e9b..7240edd7104 100644 --- a/src/rust/crates/ain-evm-state/src/handler.rs +++ b/src/rust/crates/ain-evm-state/src/handler.rs @@ -4,7 +4,7 @@ use ain_evm::executor::AinExecutor; use ain_evm::traits::Executor; use ethereum::{Block, PartialHeader, TransactionV2}; use evm::backend::{MemoryBackend, MemoryVicinity}; -use primitive_types::{H160, U256}; +use primitive_types::{H160, H256, U256}; use std::error::Error; use std::time::{SystemTime, UNIX_EPOCH}; @@ -49,13 +49,19 @@ impl Handlers { *state = executor.backend().state().clone(); } + let mut parent_hash: H256 = Default::default(); + let mut number: usize = 0; + let blocks = self.block.blocks.read().unwrap(); - let parent_block = blocks.first().unwrap(); - let number = blocks.len() + 1; + if !blocks.is_empty() { + parent_hash = blocks.first().unwrap().header.hash(); + number = blocks.len() + 1; + } + drop(blocks); let block = Block::new( PartialHeader { - parent_hash: parent_block.header.hash(), + parent_hash, beneficiary: Default::default(), state_root: Default::default(), receipts_root: Default::default(), diff --git a/src/rust/crates/ain-grpc/src/rpc.rs b/src/rust/crates/ain-grpc/src/rpc.rs index 2002fc08f8e..682c156c7d1 100644 --- a/src/rust/crates/ain-grpc/src/rpc.rs +++ b/src/rust/crates/ain-grpc/src/rpc.rs @@ -118,7 +118,7 @@ impl EthServiceApi for EthService { size: size_of_val(&block).to_string(), gas_limit: block.header.gas_limit.to_string(), gas_used: block.header.gas_used.to_string(), - timestamps: block.header.timestamp.to_string(), + timestamps: format!("0x{:x}", block.header.timestamp), transactions: block .transactions .iter() @@ -170,7 +170,7 @@ impl EthServiceApi for EthService { size: size_of_val(&block).to_string(), gas_limit: block.header.gas_limit.to_string(), gas_used: block.header.gas_used.to_string(), - timestamps: block.header.timestamp.to_string(), + timestamps: format!("0x{:x}", block.header.timestamp), transactions: block .transactions .iter() From accba50e8c167f75922e3518f8a91dde593f33d7 Mon Sep 17 00:00:00 2001 From: Shoham Chakraborty Date: Tue, 11 Apr 2023 14:50:59 +0800 Subject: [PATCH 06/13] Fix RPC names and output --- src/rust/crates/ain-grpc/src/rpc.rs | 134 ++++++++++++++-------------- src/rust/protobuf/rpc/eth.proto | 4 +- 2 files changed, 67 insertions(+), 71 deletions(-) diff --git a/src/rust/crates/ain-grpc/src/rpc.rs b/src/rust/crates/ain-grpc/src/rpc.rs index 682c156c7d1..c5815dcbfc0 100644 --- a/src/rust/crates/ain-grpc/src/rpc.rs +++ b/src/rust/crates/ain-grpc/src/rpc.rs @@ -1,8 +1,8 @@ use crate::codegen::rpc::{ ffi::{ - EthAccountsResult, EthBlockInfo, EthBlockNumberResult, EthCallInput, EthCallResult, - EthGetBalanceInput, EthGetBalanceResult, EthGetBlockByHashInput, EthGetBlockByHashResult, - EthGetBlockByNumberInput, EthGetBlockByNumberResult, EthTransactionInfo, + EthAccountsResult, EthBlockInfo, EthBlockNumberResult, + EthCallInput, EthCallResult, EthGetBalanceInput, EthGetBalanceResult, + EthGetBlockByHashInput, EthGetBlockByNumberInput, EthTransactionInfo, }, EthService, }; @@ -27,16 +27,16 @@ pub trait EthServiceApi { fn Eth_GetBlockByHash( handler: Arc, input: EthGetBlockByHashInput, - ) -> Result; + ) -> Result; fn Eth_BlockNumber( handler: Arc, ) -> Result; - fn Eth_GetBlockByCount( + fn Eth_GetBlockByNumber( handler: Arc, input: EthGetBlockByNumberInput, - ) -> Result; + ) -> Result; } impl EthServiceApi for EthService { @@ -94,42 +94,40 @@ impl EthServiceApi for EthService { fn Eth_GetBlockByHash( handler: Arc, input: EthGetBlockByHashInput, - ) -> Result { + ) -> Result { let EthGetBlockByHashInput { hash, .. } = input; let hash = hash.parse().expect("Invalid hash"); let block = handler.block.get_block_by_hash(hash).unwrap(); - Ok(EthGetBlockByHashResult { - block_info: EthBlockInfo { - block_number: block.header.number.to_string(), - hash: block.header.hash().to_string(), - parent_hash: block.header.parent_hash.to_string(), - nonce: block.header.nonce.to_string(), - sha3_uncles: block.header.ommers_hash.to_string(), - logs_bloom: block.header.logs_bloom.to_string(), - transactions_root: block.header.transactions_root.to_string(), - state_root: block.header.state_root.to_string(), - receipt_root: block.header.receipts_root.to_string(), - miner: block.header.beneficiary.to_string(), - difficulty: block.header.difficulty.to_string(), - total_difficulty: block.header.difficulty.to_string(), - extra_data: String::from_utf8(block.header.extra_data.clone()).unwrap(), - size: size_of_val(&block).to_string(), - gas_limit: block.header.gas_limit.to_string(), - gas_used: block.header.gas_used.to_string(), - timestamps: format!("0x{:x}", block.header.timestamp), - transactions: block - .transactions - .iter() - .map(|x| x.hash().to_string()) - .collect::>(), - uncles: block - .ommers - .iter() - .map(|x| x.hash().to_string()) - .collect::>(), - }, + Ok(EthBlockInfo { + block_number: block.header.number.to_string(), + hash: block.header.hash().to_string(), + parent_hash: block.header.parent_hash.to_string(), + nonce: block.header.nonce.to_string(), + sha3_uncles: block.header.ommers_hash.to_string(), + logs_bloom: block.header.logs_bloom.to_string(), + transactions_root: block.header.transactions_root.to_string(), + state_root: block.header.state_root.to_string(), + receipt_root: block.header.receipts_root.to_string(), + miner: block.header.beneficiary.to_string(), + difficulty: block.header.difficulty.to_string(), + total_difficulty: block.header.difficulty.to_string(), + extra_data: String::from_utf8(block.header.extra_data.clone()).unwrap(), + size: size_of_val(&block).to_string(), + gas_limit: block.header.gas_limit.to_string(), + gas_used: block.header.gas_used.to_string(), + timestamps: format!("0x{:x}", block.header.timestamp), + transactions: block + .transactions + .iter() + .map(|x| x.hash().to_string()) + .collect::>(), + uncles: block + .ommers + .iter() + .map(|x| x.hash().to_string()) + .collect::>(), }) } @@ -143,45 +141,43 @@ impl EthServiceApi for EthService { }) } - fn Eth_GetBlockByCount( + fn Eth_GetBlockByNumber( handler: Arc, input: EthGetBlockByNumberInput, - ) -> Result { + ) -> Result { let EthGetBlockByNumberInput { number, .. } = input; let number: usize = number.parse().ok().unwrap(); let block = handler.block.get_block_by_number(number).unwrap(); - Ok(EthGetBlockByNumberResult { - block_info: EthBlockInfo { - block_number: block.header.number.to_string(), - hash: block.header.hash().to_string(), - parent_hash: block.header.parent_hash.to_string(), - nonce: block.header.nonce.to_string(), - sha3_uncles: block.header.ommers_hash.to_string(), - logs_bloom: block.header.logs_bloom.to_string(), - transactions_root: block.header.transactions_root.to_string(), - state_root: block.header.state_root.to_string(), - receipt_root: block.header.receipts_root.to_string(), - miner: block.header.beneficiary.to_string(), - difficulty: block.header.difficulty.to_string(), - total_difficulty: block.header.difficulty.to_string(), - extra_data: String::from_utf8(block.header.extra_data.clone()).unwrap(), - size: size_of_val(&block).to_string(), - gas_limit: block.header.gas_limit.to_string(), - gas_used: block.header.gas_used.to_string(), - timestamps: format!("0x{:x}", block.header.timestamp), - transactions: block - .transactions - .iter() - .map(|x| x.hash().to_string()) - .collect::>(), - uncles: block - .ommers - .iter() - .map(|x| x.hash().to_string()) - .collect::>(), - }, + Ok(EthBlockInfo { + block_number: block.header.number.to_string(), + hash: block.header.hash().to_string(), + parent_hash: block.header.parent_hash.to_string(), + nonce: block.header.nonce.to_string(), + sha3_uncles: block.header.ommers_hash.to_string(), + logs_bloom: block.header.logs_bloom.to_string(), + transactions_root: block.header.transactions_root.to_string(), + state_root: block.header.state_root.to_string(), + receipt_root: block.header.receipts_root.to_string(), + miner: block.header.beneficiary.to_string(), + difficulty: block.header.difficulty.to_string(), + total_difficulty: block.header.difficulty.to_string(), + extra_data: String::from_utf8(block.header.extra_data.clone()).unwrap(), + size: size_of_val(&block).to_string(), + gas_limit: block.header.gas_limit.to_string(), + gas_used: block.header.gas_used.to_string(), + timestamps: format!("0x{:x}", block.header.timestamp), + transactions: block + .transactions + .iter() + .map(|x| x.hash().to_string()) + .collect::>(), + uncles: block + .ommers + .iter() + .map(|x| x.hash().to_string()) + .collect::>(), }) } } diff --git a/src/rust/protobuf/rpc/eth.proto b/src/rust/protobuf/rpc/eth.proto index 2fed7706f35..25ac6b37033 100644 --- a/src/rust/protobuf/rpc/eth.proto +++ b/src/rust/protobuf/rpc/eth.proto @@ -14,7 +14,7 @@ service eth { /// Returns the balance for the given address. rpc Eth_GetBalance(types.EthGetBalanceInput) returns (types.EthGetBalanceResult); - rpc Eth_GetBlockByHash(types.EthGetBlockByHashInput) returns (types.EthGetBlockByHashResult); + rpc Eth_GetBlockByHash(types.EthGetBlockByHashInput) returns (types.EthBlockInfo); /// [ignore] /// Returns the balance for the given address. @@ -22,5 +22,5 @@ service eth { rpc Eth_BlockNumber(google.protobuf.Empty) returns (types.EthBlockNumberResult); - rpc Eth_GetBlockByCount(types.EthGetBlockByNumberInput) returns (types.EthGetBlockByNumberResult); + rpc Eth_GetBlockByNumber(types.EthGetBlockByNumberInput) returns (types.EthBlockInfo); } From 9e45b59e810e6f24c57f2b7d03c781f0587427de Mon Sep 17 00:00:00 2001 From: Shoham Chakraborty Date: Tue, 11 Apr 2023 16:23:25 +0800 Subject: [PATCH 07/13] Format --- src/rust/crates/ain-grpc/src/rpc.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/rust/crates/ain-grpc/src/rpc.rs b/src/rust/crates/ain-grpc/src/rpc.rs index 8bc3827829c..61f31c6583a 100644 --- a/src/rust/crates/ain-grpc/src/rpc.rs +++ b/src/rust/crates/ain-grpc/src/rpc.rs @@ -1,8 +1,8 @@ use crate::codegen::rpc::{ ffi::{ - EthAccountsResult, EthBlockInfo, EthBlockNumberResult, - EthCallInput, EthCallResult, EthGetBalanceInput, EthGetBalanceResult, - EthGetBlockByHashInput, EthGetBlockByNumberInput, EthTransactionInfo, + EthAccountsResult, EthBlockInfo, EthBlockNumberResult, EthCallInput, EthCallResult, + EthGetBalanceInput, EthGetBalanceResult, EthGetBlockByHashInput, EthGetBlockByNumberInput, + EthTransactionInfo, }, EthService, }; From aa557a1b4f59c35053e8e83e5b903c573c0e205c Mon Sep 17 00:00:00 2001 From: Shoham Chakraborty Date: Tue, 11 Apr 2023 16:24:53 +0800 Subject: [PATCH 08/13] Fix test --- src/rust/crates/ain-evm/tests/block.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/rust/crates/ain-evm/tests/block.rs b/src/rust/crates/ain-evm/tests/block.rs index e05f09e60fd..dbf2cbce552 100644 --- a/src/rust/crates/ain-evm/tests/block.rs +++ b/src/rust/crates/ain-evm/tests/block.rs @@ -21,7 +21,7 @@ fn test_finalize_block_and_do_not_update_state() { handler.evm.tx_queues.add_signed_tx(context, tx1); let old_state = handler.evm.state.read().unwrap(); - let _ = handler.evm.finalize_block(context, false).unwrap(); + let _ = handler.finalize_block(context, false).unwrap(); let new_state = handler.evm.state.read().unwrap(); assert_eq!(*new_state, *old_state); @@ -58,7 +58,7 @@ fn test_finalize_block_and_update_state() { assert_eq!(handler.evm.tx_queues.len(context), 3); assert_eq!(handler.evm.tx_queues.len(handler.evm.get_context()), 0); - let (block, failed_txs) = handler.evm.finalize_block(context, true).unwrap(); + let (block, failed_txs) = handler.finalize_block(context, true).unwrap(); assert_eq!( block.transactions, vec![tx1, tx2] @@ -131,7 +131,7 @@ fn test_deploy_and_call_smart_contract() { .tx_queues .add_signed_tx(context, create_smart_contract_tx); - handler.evm.finalize_block(context, true).unwrap(); + handler.finalize_block(context, true).unwrap(); // Fund caller address handler.evm.add_balance( @@ -150,7 +150,7 @@ fn test_deploy_and_call_smart_contract() { .tx_queues .add_signed_tx(context, call_smart_contract_tx); - handler.evm.finalize_block(context, true).unwrap(); + handler.finalize_block(context, true).unwrap(); let smart_contract_storage = handler.evm.get_storage(smart_contract_address); assert_eq!( From 469fcf95b91fa5077177b556a002dd59cf7a2076 Mon Sep 17 00:00:00 2001 From: Shoham Chakraborty Date: Tue, 11 Apr 2023 16:33:28 +0800 Subject: [PATCH 09/13] Fix tests --- src/rust/crates/ain-grpc/src/tests.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/rust/crates/ain-grpc/src/tests.rs b/src/rust/crates/ain-grpc/src/tests.rs index cc39028ee5c..19b7d2d3482 100644 --- a/src/rust/crates/ain-grpc/src/tests.rs +++ b/src/rust/crates/ain-grpc/src/tests.rs @@ -55,7 +55,7 @@ fn should_get_balance() { .evm .add_balance(ctx, H160::from_str(ALICE).unwrap(), U256::from(1337)); - let _ = handler.evm.finalize_block(ctx, true); + let _ = handler.finalize_block(ctx, true); let res2 = EthService::Eth_GetBalance(handler, input.into()); assert_eq!(res2.unwrap().balance, "1337"); From a17212215f6b645e37c07a3567b367fb0688c523 Mon Sep 17 00:00:00 2001 From: Shoham Chakraborty Date: Tue, 11 Apr 2023 16:42:33 +0800 Subject: [PATCH 10/13] Fix logic --- src/rust/crates/ain-evm/src/block.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/rust/crates/ain-evm/src/block.rs b/src/rust/crates/ain-evm/src/block.rs index 0ad92caab26..5088439256c 100644 --- a/src/rust/crates/ain-evm/src/block.rs +++ b/src/rust/crates/ain-evm/src/block.rs @@ -79,7 +79,7 @@ impl BlockHandler { blocks.push(block.clone()); let mut blockhash = self.block_map.write().unwrap(); - blockhash.insert(block.header.hash(), blocks.len() + 1); + blockhash.insert(block.header.hash(), blocks.len()); } pub fn flush(&self) -> Result<(), PersistentStateError> { From 922dca0ccda9a4d6a384bda1f0ccc07fea88d777 Mon Sep 17 00:00:00 2001 From: Shoham Chakraborty Date: Tue, 11 Apr 2023 17:14:27 +0800 Subject: [PATCH 11/13] Remove explicit drop --- src/rust/crates/ain-evm/src/handler.rs | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/src/rust/crates/ain-evm/src/handler.rs b/src/rust/crates/ain-evm/src/handler.rs index 02a0697716d..4dce31336af 100644 --- a/src/rust/crates/ain-evm/src/handler.rs +++ b/src/rust/crates/ain-evm/src/handler.rs @@ -49,15 +49,13 @@ impl Handlers { *state = executor.backend().state().clone(); } - let mut parent_hash: H256 = Default::default(); - let mut number: usize = 0; - - let blocks = self.block.blocks.read().unwrap(); - if !blocks.is_empty() { - parent_hash = blocks.first().unwrap().header.hash(); - number = blocks.len() + 1; - } - drop(blocks); + let (parent_hash, number) = { + let blocks = self.block.blocks.read().unwrap(); + blocks + .first() + .and_then(|first_block| Some((first_block.header.hash(), blocks.len() + 1))) + .unwrap_or((H256::default(), 0)) + }; let block = Block::new( PartialHeader { From dcb51618b61738902f6ad1836f7c227c3e448899 Mon Sep 17 00:00:00 2001 From: Shoham Chakraborty Date: Tue, 11 Apr 2023 22:31:55 +0800 Subject: [PATCH 12/13] Fix hash outputs, add test --- src/rust/crates/ain-evm/src/block.rs | 2 +- src/rust/crates/ain-grpc/build.rs | 2 +- src/rust/crates/ain-grpc/src/rpc.rs | 76 ++++++++++++++++----------- src/rust/crates/ain-grpc/src/tests.rs | 41 ++++++++++++++- 4 files changed, 86 insertions(+), 35 deletions(-) diff --git a/src/rust/crates/ain-evm/src/block.rs b/src/rust/crates/ain-evm/src/block.rs index 5088439256c..566b53d5a13 100644 --- a/src/rust/crates/ain-evm/src/block.rs +++ b/src/rust/crates/ain-evm/src/block.rs @@ -79,7 +79,7 @@ impl BlockHandler { blocks.push(block.clone()); let mut blockhash = self.block_map.write().unwrap(); - blockhash.insert(block.header.hash(), blocks.len()); + blockhash.insert(block.header.hash(), blocks.len() - 1); } pub fn flush(&self) -> Result<(), PersistentStateError> { diff --git a/src/rust/crates/ain-grpc/build.rs b/src/rust/crates/ain-grpc/build.rs index eb368ea5fa7..8eb18efebb2 100644 --- a/src/rust/crates/ain-grpc/build.rs +++ b/src/rust/crates/ain-grpc/build.rs @@ -406,7 +406,7 @@ fn change_types(file: syn::File) -> (HashMap, TokenStream, T modified.extend(quote!(#s)); map.insert(s.ident.to_string(), s.clone()); - s.attrs = Attr::parse("#[derive(Debug, Default, Serialize , Deserialize)]"); + s.attrs = Attr::parse("#[derive(Debug, Default, Serialize , Deserialize, PartialEq)]"); let fields = match &mut s.fields { Fields::Named(ref mut f) => f, _ => unreachable!(), diff --git a/src/rust/crates/ain-grpc/src/rpc.rs b/src/rust/crates/ain-grpc/src/rpc.rs index 61f31c6583a..29ef38a51e0 100644 --- a/src/rust/crates/ain-grpc/src/rpc.rs +++ b/src/rust/crates/ain-grpc/src/rpc.rs @@ -7,7 +7,11 @@ use crate::codegen::rpc::{ EthService, }; use ain_evm::handler::Handlers; +use primitive_types::{H256, U256}; +use prost::Message; +use std::hash::Hash; use std::mem::size_of_val; +use std::str::FromStr; use std::sync::Arc; pub trait EthServiceApi { @@ -102,22 +106,22 @@ impl EthServiceApi for EthService { let block = handler.block.get_block_by_hash(hash).unwrap(); Ok(EthBlockInfo { - block_number: block.header.number.to_string(), - hash: block.header.hash().to_string(), - parent_hash: block.header.parent_hash.to_string(), - nonce: block.header.nonce.to_string(), - sha3_uncles: block.header.ommers_hash.to_string(), - logs_bloom: block.header.logs_bloom.to_string(), - transactions_root: block.header.transactions_root.to_string(), - state_root: block.header.state_root.to_string(), - receipt_root: block.header.receipts_root.to_string(), - miner: block.header.beneficiary.to_string(), - difficulty: block.header.difficulty.to_string(), - total_difficulty: block.header.difficulty.to_string(), - extra_data: String::from_utf8(block.header.extra_data.clone()).unwrap(), - size: size_of_val(&block).to_string(), - gas_limit: block.header.gas_limit.to_string(), - gas_used: block.header.gas_used.to_string(), + block_number: format!("0x{:x}", block.header.number), + hash: format_hash(block.header.hash()), + parent_hash: format_hash(block.header.parent_hash), + nonce: format!("0x{:x}", block.header.nonce), + sha3_uncles: format_hash(block.header.ommers_hash), + logs_bloom: format!("0x{:x}", block.header.logs_bloom), + transactions_root: format_hash(block.header.transactions_root), + state_root: format_hash(block.header.state_root), + receipt_root: format_hash(block.header.receipts_root), + miner: format!("0x{:x}", block.header.beneficiary), + difficulty: format!("0x{:x}", block.header.difficulty), + total_difficulty: format_number(block.header.difficulty), + extra_data: format!("0x{:x?}", block.header.extra_data.to_ascii_lowercase()), + size: format!("0x{:x}", size_of_val(&block)), + gas_limit: format_number(block.header.gas_limit), + gas_used: format_number(block.header.gas_used), timestamps: format!("0x{:x}", block.header.timestamp), transactions: block .transactions @@ -152,22 +156,22 @@ impl EthServiceApi for EthService { let block = handler.block.get_block_by_number(number).unwrap(); Ok(EthBlockInfo { - block_number: block.header.number.to_string(), - hash: block.header.hash().to_string(), - parent_hash: block.header.parent_hash.to_string(), - nonce: block.header.nonce.to_string(), - sha3_uncles: block.header.ommers_hash.to_string(), - logs_bloom: block.header.logs_bloom.to_string(), - transactions_root: block.header.transactions_root.to_string(), - state_root: block.header.state_root.to_string(), - receipt_root: block.header.receipts_root.to_string(), - miner: block.header.beneficiary.to_string(), - difficulty: block.header.difficulty.to_string(), - total_difficulty: block.header.difficulty.to_string(), - extra_data: String::from_utf8(block.header.extra_data.clone()).unwrap(), - size: size_of_val(&block).to_string(), - gas_limit: block.header.gas_limit.to_string(), - gas_used: block.header.gas_used.to_string(), + block_number: format!("0x{:x}", block.header.number), + hash: format_hash(block.header.hash()), + parent_hash: format_hash(block.header.parent_hash), + nonce: format!("0x{:x}", block.header.nonce), + sha3_uncles: format_hash(block.header.ommers_hash), + logs_bloom: format!("0x{:x}", block.header.logs_bloom), + transactions_root: format_hash(block.header.transactions_root), + state_root: format_hash(block.header.state_root), + receipt_root: format_hash(block.header.receipts_root), + miner: format!("0x{:x}", block.header.beneficiary), + difficulty: format!("0x{:x}", block.header.difficulty), + total_difficulty: format_number(block.header.difficulty), + extra_data: format!("0x{:x?}", block.header.extra_data.to_ascii_lowercase()), + size: format!("0x{:x}", size_of_val(&block)), + gas_limit: format_number(block.header.gas_limit), + gas_used: format_number(block.header.gas_used), timestamps: format!("0x{:x}", block.header.timestamp), transactions: block .transactions @@ -182,3 +186,11 @@ impl EthServiceApi for EthService { }) } } + +fn format_hash(hash: H256) -> String { + return format!("0x{:x}", hash); +} + +fn format_number(number: U256) -> String { + return format!("0x{:x}", number); +} diff --git a/src/rust/crates/ain-grpc/src/tests.rs b/src/rust/crates/ain-grpc/src/tests.rs index 19b7d2d3482..7d368f926b0 100644 --- a/src/rust/crates/ain-grpc/src/tests.rs +++ b/src/rust/crates/ain-grpc/src/tests.rs @@ -1,5 +1,6 @@ #![cfg(test)] +use ethereum::{BlockV2, PartialHeader}; use std::str::FromStr; use std::sync::Arc; @@ -10,7 +11,7 @@ use ain_evm::handler::Handlers; use crate::{ codegen::{ rpc::EthService, - types::{EthCallInput, EthGetBalanceInput, EthTransactionInfo}, + types::{EthCallInput, EthGetBalanceInput, EthGetBlockByHashInput, EthTransactionInfo}, }, rpc::EthServiceApi, }; @@ -60,3 +61,41 @@ fn should_get_balance() { let res2 = EthService::Eth_GetBalance(handler, input.into()); assert_eq!(res2.unwrap().balance, "1337"); } + +#[test] +fn should_get_block_by_hash() { + let handler = Arc::new(Handlers::new()); + let block = BlockV2::new( + PartialHeader { + parent_hash: Default::default(), + beneficiary: Default::default(), + state_root: Default::default(), + receipts_root: Default::default(), + logs_bloom: Default::default(), + difficulty: Default::default(), + number: Default::default(), + gas_limit: Default::default(), + gas_used: Default::default(), + timestamp: 0, + extra_data: vec![], + mix_hash: Default::default(), + nonce: Default::default(), + }, + Vec::new(), + Vec::new(), + ); + handler.block.connect_block(block.clone()); + + let binding = handler.block.block_map.read().unwrap(); + let bno = binding.get(&block.header.hash()).unwrap(); + + let input = EthGetBlockByHashInput { + hash: format!("{:x}", block.header.hash()), + full_transaction: false, + }; + let res = EthService::Eth_GetBlockByHash(handler.clone(), input.clone().into()); + assert_eq!( + format!("{}", res.unwrap().hash), + format!("0x{:x}", block.header.hash()) + ); +} From 7cda916df686b19d30823d1c8b1a752b52f27d65 Mon Sep 17 00:00:00 2001 From: Shoham Chakraborty Date: Tue, 11 Apr 2023 22:41:08 +0800 Subject: [PATCH 13/13] Syntax improvements --- src/rust/crates/ain-grpc/src/rpc.rs | 34 ++++++++++++++--------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/src/rust/crates/ain-grpc/src/rpc.rs b/src/rust/crates/ain-grpc/src/rpc.rs index 29ef38a51e0..6ef55911cce 100644 --- a/src/rust/crates/ain-grpc/src/rpc.rs +++ b/src/rust/crates/ain-grpc/src/rpc.rs @@ -106,20 +106,20 @@ impl EthServiceApi for EthService { let block = handler.block.get_block_by_hash(hash).unwrap(); Ok(EthBlockInfo { - block_number: format!("0x{:x}", block.header.number), + block_number: format!("{:#x}", block.header.number), hash: format_hash(block.header.hash()), parent_hash: format_hash(block.header.parent_hash), - nonce: format!("0x{:x}", block.header.nonce), + nonce: format!("{:#x}", block.header.nonce), sha3_uncles: format_hash(block.header.ommers_hash), - logs_bloom: format!("0x{:x}", block.header.logs_bloom), + logs_bloom: format!("{:#x}", block.header.logs_bloom), transactions_root: format_hash(block.header.transactions_root), state_root: format_hash(block.header.state_root), receipt_root: format_hash(block.header.receipts_root), - miner: format!("0x{:x}", block.header.beneficiary), - difficulty: format!("0x{:x}", block.header.difficulty), + miner: format!("{:#x}", block.header.beneficiary), + difficulty: format!("{:#x}", block.header.difficulty), total_difficulty: format_number(block.header.difficulty), - extra_data: format!("0x{:x?}", block.header.extra_data.to_ascii_lowercase()), - size: format!("0x{:x}", size_of_val(&block)), + extra_data: format!("{:#x?}", block.header.extra_data.to_ascii_lowercase()), + size: format!("{:#x}", size_of_val(&block)), gas_limit: format_number(block.header.gas_limit), gas_used: format_number(block.header.gas_used), timestamps: format!("0x{:x}", block.header.timestamp), @@ -156,23 +156,23 @@ impl EthServiceApi for EthService { let block = handler.block.get_block_by_number(number).unwrap(); Ok(EthBlockInfo { - block_number: format!("0x{:x}", block.header.number), + block_number: format!("{:#x}", block.header.number), hash: format_hash(block.header.hash()), parent_hash: format_hash(block.header.parent_hash), - nonce: format!("0x{:x}", block.header.nonce), + nonce: format!("{:#x}", block.header.nonce), sha3_uncles: format_hash(block.header.ommers_hash), - logs_bloom: format!("0x{:x}", block.header.logs_bloom), + logs_bloom: format!("{:#x}", block.header.logs_bloom), transactions_root: format_hash(block.header.transactions_root), state_root: format_hash(block.header.state_root), receipt_root: format_hash(block.header.receipts_root), - miner: format!("0x{:x}", block.header.beneficiary), - difficulty: format!("0x{:x}", block.header.difficulty), + miner: format!("{:#x}", block.header.beneficiary), + difficulty: format!("{:#x}", block.header.difficulty), total_difficulty: format_number(block.header.difficulty), - extra_data: format!("0x{:x?}", block.header.extra_data.to_ascii_lowercase()), - size: format!("0x{:x}", size_of_val(&block)), + extra_data: format!("{:#x?}", block.header.extra_data.to_ascii_lowercase()), + size: format!("{:#x}", size_of_val(&block)), gas_limit: format_number(block.header.gas_limit), gas_used: format_number(block.header.gas_used), - timestamps: format!("0x{:x}", block.header.timestamp), + timestamps: format!("{:#x}", block.header.timestamp), transactions: block .transactions .iter() @@ -188,9 +188,9 @@ impl EthServiceApi for EthService { } fn format_hash(hash: H256) -> String { - return format!("0x{:x}", hash); + return format!("{:#x}", hash); } fn format_number(number: U256) -> String { - return format!("0x{:x}", number); + return format!("{:#x}", number); }