diff --git a/lib/Cargo.lock b/lib/Cargo.lock index eeeacc4c309..e88efe05e93 100644 --- a/lib/Cargo.lock +++ b/lib/Cargo.lock @@ -148,6 +148,7 @@ dependencies = [ "quote", "regex", "rlp", + "rustc-hex", "serde", "serde_json", "syn 2.0.15", diff --git a/lib/ain-evm/src/backend.rs b/lib/ain-evm/src/backend.rs index f25be4297ec..6aae6816a3c 100644 --- a/lib/ain-evm/src/backend.rs +++ b/lib/ain-evm/src/backend.rs @@ -117,10 +117,12 @@ impl EVMBackend { impl Backend for EVMBackend { fn gas_price(&self) -> U256 { + debug!(target: "backend", "[EVMBackend] Getting gas"); unimplemented!() } fn origin(&self) -> H160 { + debug!(target: "backend", "[EVMBackend] Getting origin"); unimplemented!() } @@ -149,7 +151,9 @@ impl Backend for EVMBackend { } fn block_base_fee_per_gas(&self) -> U256 { - unimplemented!("Implement block_base_fee_per_gas function") + debug!(target: "backend", "[EVMBackend] Getting block_base_fee_per_gas"); + U256::default() + // unimplemented!("Implement block_base_fee_per_gas function") } fn chain_id(&self) -> U256 { @@ -161,6 +165,7 @@ impl Backend for EVMBackend { } fn basic(&self, address: H160) -> Basic { + debug!(target: "backend", "[EVMBackend] basic for address {:x?}", address); self.get_account(address) .map(|account| Basic { balance: account.balance, @@ -170,12 +175,14 @@ impl Backend for EVMBackend { } fn code(&self, address: H160) -> Vec { + debug!(target: "backend", "[EVMBackend] code for address {:x?}", address); self.get_account(address) .and_then(|account| self.storage.get_code_by_hash(account.code_hash)) .unwrap_or_default() } fn storage(&self, address: H160, index: H256) -> H256 { + debug!(target: "backend", "[EVMBackend] Getting storage for address {:x?} at index {:x?}", address, index); self.get_account(address) .and_then(|account| { self.trie_store @@ -189,6 +196,7 @@ impl Backend for EVMBackend { } fn original_storage(&self, address: H160, index: H256) -> Option { + debug!(target: "backend", "[EVMBackend] Getting original storage for address {:x?} at index {:x?}", address, index); Some(self.storage(address, index)) } } diff --git a/lib/ain-evm/src/evm.rs b/lib/ain-evm/src/evm.rs index 7585ff79476..6d0751cb2d0 100644 --- a/lib/ain-evm/src/evm.rs +++ b/lib/ain-evm/src/evm.rs @@ -91,6 +91,7 @@ impl EVMHandler { .get_latest_block() .map(|block| block.header.state_root) .unwrap_or_default(); + println!("state_root : {:#?}", state_root); let vicinity = Vicinity {}; let mut backend = EVMBackend::from_root( state_root, diff --git a/lib/ain-evm/src/executor.rs b/lib/ain-evm/src/executor.rs index b4d3772c2bc..d96376a2cba 100644 --- a/lib/ain-evm/src/executor.rs +++ b/lib/ain-evm/src/executor.rs @@ -1,5 +1,3 @@ -use std::collections::BTreeMap; - use crate::{ backend::EVMBackendError, evm::EVMHandler, @@ -14,6 +12,7 @@ use evm::{ Config, ExitReason, }; use primitive_types::H160; +use std::collections::BTreeMap; #[derive(Debug)] pub struct AinExecutor<'backend, B: Backend> { diff --git a/lib/ain-evm/src/storage/mod.rs b/lib/ain-evm/src/storage/mod.rs index d6cae1601c9..2ad54b5f263 100644 --- a/lib/ain-evm/src/storage/mod.rs +++ b/lib/ain-evm/src/storage/mod.rs @@ -164,3 +164,12 @@ impl Storage { self.blockchain_data_handler.put_code(&hash, &code) } } + +impl Storage { + pub fn dump_db(&self) { + println!( + "self.block_data_handler : {:#?}", + self.blockchain_data_handler + ); + } +} diff --git a/lib/ain-evm/src/traits.rs b/lib/ain-evm/src/traits.rs index 2552cc81293..43fde0966aa 100644 --- a/lib/ain-evm/src/traits.rs +++ b/lib/ain-evm/src/traits.rs @@ -3,6 +3,7 @@ use ethereum::AccessList; use evm::Config; use primitive_types::{H160, U256}; +#[derive(Debug)] pub struct ExecutorContext<'a> { pub caller: Option, pub to: Option, diff --git a/lib/ain-grpc/Cargo.toml b/lib/ain-grpc/Cargo.toml index 0fcd28a984a..cea0a181e1d 100644 --- a/lib/ain-grpc/Cargo.toml +++ b/lib/ain-grpc/Cargo.toml @@ -24,6 +24,7 @@ hex = "0.4.3" async-trait = "0.1.68" rlp = "0.5.2" protobuf-src = "1.1.0" +rustc-hex = "2.1.0" [build-dependencies] cxx-gen = "0.7" diff --git a/lib/ain-grpc/src/bytes.rs b/lib/ain-grpc/src/bytes.rs new file mode 100644 index 00000000000..d4b3a0f58b6 --- /dev/null +++ b/lib/ain-grpc/src/bytes.rs @@ -0,0 +1,117 @@ +use rustc_hex::{FromHex, ToHex}; +use serde::{ + de::{Error, Visitor}, + Deserialize, Deserializer, Serialize, Serializer, +}; +use std::fmt; + +/// Wrapper structure around vector of bytes. +#[derive(Clone, Debug, Default, Eq, PartialEq, Hash)] +pub struct Bytes(pub Vec); + +impl Bytes { + /// Simple constructor. + pub fn new(bytes: Vec) -> Bytes { + Bytes(bytes) + } + /// Convert back to vector + pub fn into_vec(self) -> Vec { + self.0 + } +} + +impl From> for Bytes { + fn from(bytes: Vec) -> Bytes { + Bytes(bytes) + } +} + +impl From for Vec { + fn from(bytes: Bytes) -> Vec { + bytes.0 + } +} + +impl Serialize for Bytes { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + let mut serialized = "0x".to_owned(); + serialized.push_str(self.0.to_hex::().as_ref()); + serializer.serialize_str(serialized.as_ref()) + } +} + +impl<'a> Deserialize<'a> for Bytes { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'a>, + { + deserializer.deserialize_any(BytesVisitor) + } +} + +struct BytesVisitor; + +impl<'a> Visitor<'a> for BytesVisitor { + type Value = Bytes; + + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + write!(formatter, "a 0x-prefixed, hex-encoded vector of bytes") + } + + fn visit_str(self, value: &str) -> Result + where + E: Error, + { + if value.len() >= 2 && value.starts_with("0x") && value.len() & 1 == 0 { + Ok(Bytes::new(FromHex::from_hex(&value[2..]).map_err(|e| { + Error::custom(format!("Invalid hex: {}", e)) + })?)) + } else { + Err(Error::custom( + "Invalid bytes format. Expected a 0x-prefixed hex string with even length", + )) + } + } + + fn visit_string(self, value: String) -> Result + where + E: Error, + { + self.visit_str(value.as_ref()) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_bytes_serialize() { + let bytes = Bytes("0123456789abcdef".from_hex().unwrap()); + let serialized = serde_json::to_string(&bytes).unwrap(); + assert_eq!(serialized, r#""0x0123456789abcdef""#); + } + + #[test] + fn test_bytes_deserialize() { + let bytes0: Result = serde_json::from_str(r#""∀∂""#); + let bytes1: Result = serde_json::from_str(r#""""#); + let bytes2: Result = serde_json::from_str(r#""0x123""#); + let bytes3: Result = serde_json::from_str(r#""0xgg""#); + + let bytes4: Bytes = serde_json::from_str(r#""0x""#).unwrap(); + let bytes5: Bytes = serde_json::from_str(r#""0x12""#).unwrap(); + let bytes6: Bytes = serde_json::from_str(r#""0x0123""#).unwrap(); + + assert!(bytes0.is_err()); + assert!(bytes1.is_err()); + assert!(bytes2.is_err()); + assert!(bytes3.is_err()); + assert_eq!(bytes4, Bytes(vec![])); + assert_eq!(bytes5, Bytes(vec![0x12])); + assert_eq!(bytes6, Bytes(vec![0x1, 0x23])); + } +} diff --git a/lib/ain-grpc/src/call_request.rs b/lib/ain-grpc/src/call_request.rs index 662ccee6f1e..85a221d789d 100644 --- a/lib/ain-grpc/src/call_request.rs +++ b/lib/ain-grpc/src/call_request.rs @@ -2,6 +2,8 @@ use ethereum::AccessListItem; use primitive_types::{H160, U256}; use serde::Deserialize; +use crate::bytes::Bytes; + /// Call request #[derive(Clone, Debug, Default, Eq, PartialEq, Deserialize, Serialize)] #[serde(deny_unknown_fields)] @@ -22,7 +24,7 @@ pub struct CallRequest { /// Value pub value: Option, /// Data - pub data: Option>, + pub data: Option, /// Nonce pub nonce: Option, /// AccessList diff --git a/lib/ain-grpc/src/lib.rs b/lib/ain-grpc/src/lib.rs index 5bcd8d549e4..143bacc7761 100644 --- a/lib/ain-grpc/src/lib.rs +++ b/lib/ain-grpc/src/lib.rs @@ -3,6 +3,7 @@ extern crate serde; extern crate serde_json; pub mod block; +mod bytes; pub mod call_request; pub mod codegen; mod impls; diff --git a/lib/ain-grpc/src/rpc.rs b/lib/ain-grpc/src/rpc.rs index 81418de6e76..ef22da7bb13 100644 --- a/lib/ain-grpc/src/rpc.rs +++ b/lib/ain-grpc/src/rpc.rs @@ -1,4 +1,5 @@ use crate::block::{BlockNumber, RpcBlock}; +use crate::bytes::Bytes; use crate::call_request::CallRequest; use crate::codegen::types::EthTransactionInfo; @@ -24,7 +25,7 @@ pub trait MetachainRPC { /// Makes a call to the Ethereum node without creating a transaction on the blockchain. /// Returns the output data as a hexadecimal string. #[method(name = "eth_call")] - fn call(&self, input: CallRequest) -> RpcResult; + fn call(&self, input: CallRequest, block_number: Option) -> RpcResult; /// Retrieves the list of accounts managed by the node. /// Returns a vector of Ethereum addresses as hexadecimal strings. @@ -180,6 +181,10 @@ pub trait MetachainRPC { /// Returns current gas_price. #[method(name = "eth_gasPrice")] fn gas_price(&self) -> RpcResult; + + // Dump full db + #[method(name = "dumpdb")] + fn dump_db(&self) -> RpcResult<()>; } pub struct MetachainRPCModule { @@ -227,7 +232,8 @@ impl MetachainRPCModule { } impl MetachainRPCServer for MetachainRPCModule { - fn call(&self, input: CallRequest) -> RpcResult { + fn call(&self, input: CallRequest, _block_number: Option) -> RpcResult { + debug!(target:"rpc", "[RPC] Call input {:#?}", input); let CallRequest { from, to, @@ -243,13 +249,13 @@ impl MetachainRPCServer for MetachainRPCModule { from, to, value.unwrap_or_default(), - &data.unwrap_or_default(), + &data.map(|d| d.0).unwrap_or_default(), gas.unwrap_or_default().as_u64(), vec![], ) - .map_err(|e| Error::Custom(format!("Error getting address balance : {e:?}")))?; + .map_err(|e| Error::Custom(format!("Error calling EVM : {e:?}")))?; - Ok(hex::encode(data)) + Ok(Bytes(data)) } fn accounts(&self) -> RpcResult> { @@ -261,7 +267,7 @@ impl MetachainRPCServer for MetachainRPCModule { fn get_balance(&self, address: H160, block_number: Option) -> RpcResult { let block_number = self.block_number_to_u256(block_number); - debug!( + debug!(target:"rpc", "Getting balance for address: {:?} at block : {} ", address, block_number ); @@ -271,14 +277,14 @@ impl MetachainRPCServer for MetachainRPCModule { .get_balance(address, block_number) .unwrap_or(U256::zero()); - debug!("Address: {:?} balance : {} ", address, balance); + debug!(target:"rpc","Address: {:?} balance : {} ", address, balance); Ok(balance) } fn get_code(&self, address: H160, block_number: Option) -> RpcResult { let block_number = self.block_number_to_u256(block_number); - debug!( + debug!(target:"rpc", "Getting code for address: {:?} at block : {}", address, block_number ); @@ -302,7 +308,7 @@ impl MetachainRPCServer for MetachainRPCModule { block_number: Option, ) -> RpcResult { let block_number = self.block_number_to_u256(block_number); - debug!( + debug!(target:"rpc", "Getting storage for address: {:?}, at position {:?}, for block {}", address, position, block_number ); @@ -321,6 +327,7 @@ impl MetachainRPCServer for MetachainRPCModule { hash: H256, full_transactions: Option, ) -> RpcResult> { + debug!("Getting block by hash {:#x}", hash); self.handler .storage .get_block_by_hash(&hash) @@ -358,7 +365,7 @@ impl MetachainRPCServer for MetachainRPCModule { .map(|block| block.header.number) .unwrap_or_default(); - debug!("Current block number: {:?}", count); + debug!(target:"rpc","Current block number: {:?}", count); Ok(count) } @@ -368,7 +375,7 @@ impl MetachainRPCServer for MetachainRPCModule { full_transactions: Option, ) -> RpcResult> { let block_number = self.block_number_to_u256(Some(block_number)); - debug!("Getting block by number : {}", block_number); + debug!(target:"rpc","Getting block by number : {}", block_number); self.handler .storage .get_block_by_number(&block_number) @@ -455,7 +462,7 @@ impl MetachainRPCServer for MetachainRPCModule { } fn send_raw_transaction(&self, tx: &str) -> RpcResult { - debug!("[send_raw_transaction] Sending raw transaction: {:?}", tx); + debug!(target:"rpc","[send_raw_transaction] Sending raw transaction: {:?}", tx); let raw_tx = tx.strip_prefix("0x").unwrap_or(tx); let hex = hex::decode(raw_tx).map_err(|e| Error::Custom(format!("Eror decoding TX {e:?}")))?; @@ -465,15 +472,15 @@ impl MetachainRPCServer for MetachainRPCModule { let signed_tx = SignedTx::try_from(raw_tx) .map_err(|e| Error::Custom(format!("TX error {e:?}")))?; - debug!( + debug!(target:"rpc", "[send_raw_transaction] signed_tx sender : {:#x}", signed_tx.sender ); - debug!( + debug!(target:"rpc", "[send_raw_transaction] signed_tx nonce : {:#x}", signed_tx.nonce() ); - debug!( + debug!(target:"rpc", "[send_raw_transaction] transaction hash : {:#x}", signed_tx.transaction.hash() ); @@ -481,13 +488,13 @@ impl MetachainRPCServer for MetachainRPCModule { Ok(format!("{:#x}", signed_tx.transaction.hash())) } Ok(false) => { - debug!("[send_raw_transaction] Could not publish raw transaction: {tx}"); + debug!(target:"rpc","[send_raw_transaction] Could not publish raw transaction: {tx}"); Err(Error::Custom(format!( "Could not publish raw transaction: {tx}" ))) } Err(e) => { - debug!("[send_raw_transaction] Error publishing TX {e:?}"); + debug!(target:"rpc","[send_raw_transaction] Error publishing TX {e:?}"); Err(Error::Custom(format!("Error publishing TX {e:?}"))) } } @@ -498,7 +505,7 @@ impl MetachainRPCServer for MetachainRPCModule { address: H160, block_number: Option, ) -> RpcResult { - debug!("Getting transaction count for address: {:?}", address); + debug!(target:"rpc","Getting transaction count for address: {:?}", address); let block_number = self.block_number_to_u256(block_number); let nonce = self .handler @@ -508,7 +515,7 @@ impl MetachainRPCServer for MetachainRPCModule { Error::Custom(format!("Error getting address transaction count : {e:?}")) })?; - debug!("Count: {:#?}", nonce); + debug!(target:"rpc","Count: {:#?}", nonce); Ok(nonce) } @@ -529,20 +536,20 @@ impl MetachainRPCServer for MetachainRPCModule { from, to, value.unwrap_or_default(), - &data.unwrap_or_default(), + &data.map(|d| d.0).unwrap_or_default(), gas.unwrap_or_default().as_u64(), vec![], ) .map_err(|e| Error::Custom(format!("Error calling EVM : {e:?}")))?; let native_size = ain_cpp_imports::get_native_tx_size(data).unwrap_or(0); - debug!("estimateGas: {:#?} + {:#?}", native_size, used_gas); + debug!(target:"rpc","estimateGas: {:#?} + {:#?}", native_size, used_gas); Ok(U256::from(native_size + std::cmp::max(21000, used_gas))) } fn gas_price(&self) -> RpcResult { let gas_price = ain_cpp_imports::get_min_relay_tx_fee().unwrap_or(10); - debug!("gasPrice: {:#?}", gas_price); + debug!(target:"rpc","gasPrice: {:#?}", gas_price); Ok(U256::from(gas_price)) } @@ -568,4 +575,9 @@ impl MetachainRPCServer for MetachainRPCModule { fn eth_submithashrate(&self, _hashrate: String, _id: String) -> RpcResult { Ok(false) } + + fn dump_db(&self) -> RpcResult<()> { + self.handler.storage.dump_db(); + Ok(()) + } }