From 8222cc2b28bd982d0946259976163225831c3a86 Mon Sep 17 00:00:00 2001 From: Mihailo Milenkovic Date: Wed, 3 May 2023 07:20:28 +0200 Subject: [PATCH] estimateGas and gasPrice RPC implementations (#1940) * estimateGas and gasPrice rpc and ffi * Remove protoc lib includes * Resolve depends build issues * Consolidate persistent state to BlockchainDataHandler struct (#1944) * Consolidate persistent state to BlockchainDataHandler struct * Update cache after cache miss * Get receipts root before creating block * Update deps, add protobuf-src into runtime deps * Fix protobuf-src compilation * Use self contained rust toolchain * CI workflow for EVM RPC testing (#1821) * Add workflow for testing evm rpc * Add test workflow for EVM RPCs * Rename EVM RPC Test * Rename tests * Rename workflow job * Fix typo on environment var on CI * Rename tag 'test/rpc_evm' to 'evm' * Set NODE_URL to point devnet --------- Co-authored-by: Prasanna Loganathar Co-authored-by: Jouzo <15011228+Jouzo@users.noreply.github.com> Co-authored-by: dCorral <55594560+dcorral@users.noreply.github.com> Co-authored-by: canonbrother --- lib/ain-cpp-imports/src/bridge.rs | 2 ++ lib/ain-cpp-imports/src/lib.rs | 16 +++++++++++++++ lib/ain-evm/src/evm.rs | 12 +++++++---- lib/ain-grpc/src/rpc.rs | 34 ++++++++++++++++++++++++++----- src/ffi/ffiexports.cpp | 34 +++++++++++++++++++++++++++++++ src/ffi/ffiexports.h | 2 ++ 6 files changed, 91 insertions(+), 9 deletions(-) diff --git a/lib/ain-cpp-imports/src/bridge.rs b/lib/ain-cpp-imports/src/bridge.rs index 3238354d7a6..771722f7db4 100644 --- a/lib/ain-cpp-imports/src/bridge.rs +++ b/lib/ain-cpp-imports/src/bridge.rs @@ -11,5 +11,7 @@ pub mod ffi { fn getDifficulty(_block_hash: [u8; 32]) -> u32; fn getChainWork(_block_hash: [u8; 32]) -> [u8; 32]; fn getPoolTransactions() -> Vec; + fn getNativeTxSize(data: Vec) -> u64; + fn getMinRelayTxFee() -> u64; } } diff --git a/lib/ain-cpp-imports/src/lib.rs b/lib/ain-cpp-imports/src/lib.rs index ee63f49513e..0f9fa87033a 100644 --- a/lib/ain-cpp-imports/src/lib.rs +++ b/lib/ain-cpp-imports/src/lib.rs @@ -34,6 +34,12 @@ mod ffi { pub fn getPoolTransactions() -> Vec { unimplemented!("{}", UNIMPL_MSG) } + pub fn getNativeTxSize(_data: Vec) -> u64 { + unimplemented!("{}", UNIMPL_MSG) + } + pub fn getMinRelayTxFee() -> u64 { + unimplemented!("{}", UNIMPL_MSG) + } } pub fn get_chain_id() -> Result> { @@ -76,5 +82,15 @@ pub fn get_pool_transactions() -> Result, Box> { Ok(transactions) } +pub fn get_native_tx_size(data: Vec) -> Result> { + let tx_size = ffi::getNativeTxSize(data); + Ok(tx_size) +} + +pub fn get_min_relay_tx_fee() -> Result> { + let tx_fee = ffi::getMinRelayTxFee(); + Ok(tx_fee) +} + #[cfg(test)] mod tests {} diff --git a/lib/ain-evm/src/evm.rs b/lib/ain-evm/src/evm.rs index c5187919d3e..24bb27bf452 100644 --- a/lib/ain-evm/src/evm.rs +++ b/lib/ain-evm/src/evm.rs @@ -59,7 +59,7 @@ impl EVMHandler { data: &[u8], gas_limit: u64, access_list: AccessList, - ) -> (ExitReason, Vec) { + ) -> (ExitReason, Vec, u64) { // TODO Add actual gas, chain_id, block_number from header let vicinity = get_vicinity(caller, None); @@ -76,7 +76,11 @@ impl EVMHandler { }, false, ); - (tx_response.exit_reason, tx_response.data) + ( + tx_response.exit_reason, + tx_response.data, + tx_response.used_gas, + ) } // TODO wrap in EVM transaction and dryrun with evm_call @@ -120,8 +124,8 @@ impl EVMHandler { signed_tx.gas_limit().as_u64(), signed_tx.access_list(), ) { - (exit_reason, _) if exit_reason.is_succeed() => Ok(signed_tx), - (exit_reason, _) => Err(anyhow!("Error calling EVM {:?}", exit_reason).into()), + (exit_reason, _, _) if exit_reason.is_succeed() => Ok(signed_tx), + (exit_reason, _, _) => Err(anyhow!("Error calling EVM {:?}", exit_reason).into()), } } diff --git a/lib/ain-grpc/src/rpc.rs b/lib/ain-grpc/src/rpc.rs index 162c5486886..a0153bf63d7 100644 --- a/lib/ain-grpc/src/rpc.rs +++ b/lib/ain-grpc/src/rpc.rs @@ -90,7 +90,7 @@ pub trait MetachainRPC { fn get_transaction_count(&self, address: H160) -> RpcResult; #[method(name = "eth_estimateGas")] - fn estimate_gas(&self) -> RpcResult; + fn estimate_gas(&self, input: CallRequest) -> RpcResult; #[method(name = "mc_getState")] fn get_state(&self) -> RpcResult; @@ -131,7 +131,7 @@ impl MetachainRPCServer for MetachainRPCModule { data, .. } = input; - let (_, data) = self.handler.evm.call( + let (_, data, ..) = self.handler.evm.call( from, to, value.unwrap_or_default(), @@ -357,8 +357,30 @@ impl MetachainRPCServer for MetachainRPCModule { Ok(format!("{:#x}", nonce)) } - fn estimate_gas(&self) -> RpcResult { - Ok(format!("{:#x}", 21000)) + fn estimate_gas(&self, input: CallRequest) -> RpcResult { + let CallRequest { + from, + to, + gas, + value, + data, + .. + } = input; + + let (_, data, used_gas) = self.handler.evm.call( + from, + to, + value.unwrap_or_default(), + &data.unwrap_or_default(), + gas.unwrap_or_default().as_u64(), + vec![], + ); + let native_size = ain_cpp_imports::get_native_tx_size(data).unwrap_or(0); + debug!("estimateGas: {:#?} + {:#?}", native_size, used_gas); + Ok(format!( + "{:#x}", + native_size + std::cmp::max(21000, used_gas) + )) } fn get_state(&self) -> RpcResult { @@ -366,7 +388,9 @@ impl MetachainRPCServer for MetachainRPCModule { } fn gas_price(&self) -> RpcResult { - Ok(format!("{:#x}", 0)) + let gas_price = ain_cpp_imports::get_min_relay_tx_fee().unwrap_or(10); + debug!("gasPrice: {:#?}", gas_price); + Ok(format!("{:#x}", gas_price)) } fn get_receipt(&self, hash: H256) -> RpcResult> { diff --git a/src/ffi/ffiexports.cpp b/src/ffi/ffiexports.cpp index ffeba0dbea6..8849c698ae2 100644 --- a/src/ffi/ffiexports.cpp +++ b/src/ffi/ffiexports.cpp @@ -135,3 +135,37 @@ rust::vec getPoolTransactions() { return poolTransactions; } + +uint64_t getNativeTxSize(rust::Vec rawTransaction) { + std::vector evmTx(rawTransaction.size()); + std::copy(rawTransaction.begin(), rawTransaction.end(), evmTx.begin()); + CDataStream metadata(DfTxMarker, SER_NETWORK, PROTOCOL_VERSION); + metadata << static_cast(CustomTxType::EvmTx) + << CEvmTxMessage{evmTx}; + + CScript scriptMeta; + scriptMeta << OP_RETURN << ToByteVector(metadata); + + int targetHeight; + { + LOCK(cs_main); + targetHeight = ::ChainActive().Height() + 1; + } + + const auto txVersion = GetTransactionVersion(targetHeight); + CMutableTransaction rawTx(txVersion); + + rawTx.vin.resize(2); + rawTx.vin[0].scriptSig = CScript() << OP_0; + rawTx.vin[1].scriptSig = CScript() << OP_0; + + rawTx.vout.emplace_back(0, scriptMeta); + + CTransaction tx(rawTx); + + return tx.GetTotalSize(); +} + +uint64_t getMinRelayTxFee() { + return ::minRelayTxFee.GetFeePerK() * 10000000; +} diff --git a/src/ffi/ffiexports.h b/src/ffi/ffiexports.h index e20f563a98a..54edaf83f61 100644 --- a/src/ffi/ffiexports.h +++ b/src/ffi/ffiexports.h @@ -12,5 +12,7 @@ rust::string getDatadir(); uint32_t getDifficulty(std::array blockHash); std::array getChainWork(std::array blockHash); rust::vec getPoolTransactions(); +uint64_t getNativeTxSize(rust::Vec rawTransaction); +uint64_t getMinRelayTxFee(); #endif // DEFI_EVM_FFI_H