From 00995adb13bb6f6b9b0162e96ecc9c9fbd215b2b Mon Sep 17 00:00:00 2001 From: Peter John Bushnell Date: Thu, 6 Jul 2023 09:41:07 +0100 Subject: [PATCH] Remove Result from FFI interface (#2157) * Remove result from FFI interface * Restore previous import * Additional cleanups * Restore missing comment --------- Co-authored-by: Prasanna Loganathar --- lib/ain-grpc/src/lib.rs | 2 +- lib/ain-rs-exports/src/lib.rs | 237 +++++++++++++-------------------- src/init.cpp | 9 +- src/masternodes/rpc_evm.cpp | 8 +- src/test/transaction_tests.cpp | 3 +- 5 files changed, 112 insertions(+), 147 deletions(-) diff --git a/lib/ain-grpc/src/lib.rs b/lib/ain-grpc/src/lib.rs index 2f2e95b4b5..b32fcad9f4 100644 --- a/lib/ain-grpc/src/lib.rs +++ b/lib/ain-grpc/src/lib.rs @@ -81,7 +81,7 @@ pub fn init_evm_runtime() { let _ = &*RUNTIME; } -pub fn start_servers(json_addr: &str, grpc_addr: &str) -> Result<(), Box> { +pub fn start_evm_servers(json_addr: &str, grpc_addr: &str) -> Result<(), Box> { add_json_rpc_server(&RUNTIME, json_addr)?; add_grpc_server(&RUNTIME, grpc_addr)?; Ok(()) diff --git a/lib/ain-rs-exports/src/lib.rs b/lib/ain-rs-exports/src/lib.rs index 57a4fc3048..28eb639d7e 100644 --- a/lib/ain-rs-exports/src/lib.rs +++ b/lib/ain-rs-exports/src/lib.rs @@ -2,11 +2,10 @@ use ain_evm::{ storage::traits::Rollback, transaction::{self, SignedTx}, }; -use ain_grpc::{init_evm_runtime, start_servers, stop_evm_runtime}; +use ain_grpc::{init_evm_runtime, start_evm_servers, stop_evm_runtime}; use ain_evm::runtime::RUNTIME; use log::debug; -use std::error::Error; use ethereum::{EnvelopedEncodable, TransactionAction, TransactionSignature}; use primitive_types::{H160, H256, U256}; @@ -20,25 +19,25 @@ pub const GWEI_TO_SATS: u64 = 10; #[cxx::bridge] pub mod ffi { pub struct CreateTransactionContext { - chain_id: u64, - nonce: [u8; 32], - gas_price: [u8; 32], - gas_limit: [u8; 32], - to: [u8; 20], - value: [u8; 32], - input: Vec, - priv_key: [u8; 32], + pub chain_id: u64, + pub nonce: [u8; 32], + pub gas_price: [u8; 32], + pub gas_limit: [u8; 32], + pub to: [u8; 20], + pub value: [u8; 32], + pub input: Vec, + pub priv_key: [u8; 32], } #[derive(Default)] - pub struct FinalizeBlockResult { - block_hash: [u8; 32], - failed_transactions: Vec, - miner_fee: u64, + pub struct FinalizeBlockCompletion { + pub block_hash: [u8; 32], + pub failed_transactions: Vec, + pub miner_fee: u64, } #[derive(Default)] - pub struct ValidateTxResult { + pub struct ValidateTxCompletion { pub nonce: u64, pub sender: [u8; 20], pub used_gas: u64, @@ -50,30 +49,25 @@ pub mod ffi { } extern "Rust" { - fn evm_get_balance(address: [u8; 20]) -> Result; - fn evm_get_nonce(address: [u8; 20]) -> Result; + fn evm_get_balance(address: [u8; 20]) -> u64; + fn evm_get_next_valid_nonce_in_context(context: u64, address: [u8; 20]) -> u64; - fn evm_remove_txs_by_sender(context: u64, address: [u8; 20]) -> Result<()>; + fn evm_remove_txs_by_sender(context: u64, address: [u8; 20]); - fn evm_add_balance( - context: u64, - address: &str, - amount: [u8; 32], - native_tx_hash: [u8; 32], - ) -> Result<()>; + fn evm_add_balance(context: u64, address: &str, amount: [u8; 32], native_tx_hash: [u8; 32]); fn evm_sub_balance( context: u64, address: &str, amount: [u8; 32], native_tx_hash: [u8; 32], - ) -> Result; + ) -> bool; fn evm_try_prevalidate_raw_tx( result: &mut CrossBoundaryResult, tx: &str, with_gas_usage: bool, - ) -> ValidateTxResult; + ) -> ValidateTxCompletion; fn evm_get_context() -> u64; fn evm_discard_context(context: u64); @@ -82,7 +76,7 @@ pub mod ffi { context: u64, raw_tx: &str, native_tx_hash: [u8; 32], - ) -> Result; + ); fn evm_try_finalize( result: &mut CrossBoundaryResult, @@ -91,16 +85,19 @@ pub mod ffi { difficulty: u32, miner_address: [u8; 20], timestamp: u64, - ) -> Result; + ) -> FinalizeBlockCompletion; fn preinit(); fn init_evm_runtime(); - fn start_servers(json_addr: &str, grpc_addr: &str) -> Result<()>; + fn start_servers(result: &mut CrossBoundaryResult, json_addr: &str, grpc_addr: &str); fn stop_evm_runtime(); - fn create_and_sign_tx(ctx: CreateTransactionContext) -> Result>; + fn create_and_sign_tx( + result: &mut CrossBoundaryResult, + ctx: CreateTransactionContext, + ) -> Vec; - fn evm_disconnect_latest_block() -> Result<()>; + fn evm_disconnect_latest_block(); } } @@ -117,7 +114,10 @@ pub mod ffi { /// # Returns /// /// Returns the signed transaction encoded as a byte vector on success. -pub fn create_and_sign_tx(ctx: ffi::CreateTransactionContext) -> Result, TransactionError> { +pub fn create_and_sign_tx( + result: &mut CrossBoundaryResult, + ctx: ffi::CreateTransactionContext, +) -> Vec { let to_action = if ctx.to.is_empty() { TransactionAction::Create } else { @@ -143,9 +143,17 @@ pub fn create_and_sign_tx(ctx: ffi::CreateTransactionContext) -> Result, // Sign let priv_key_h256 = H256::from(ctx.priv_key); - let signed = t.sign(&priv_key_h256, ctx.chain_id)?; - - Ok(signed.encode().into()) + match t.sign(&priv_key_h256, ctx.chain_id) { + Ok(signed) => { + result.ok = true; + signed.encode().into() + } + Err(e) => { + result.ok = false; + result.reason = e.to_string(); + Vec::new() + } + } } /// Retrieves the balance of an EVM account at latest block height. @@ -161,7 +169,7 @@ pub fn create_and_sign_tx(ctx: ffi::CreateTransactionContext) -> Result, /// # Returns /// /// Returns the balance of the account as a `u64` on success. -pub fn evm_get_balance(address: [u8; 20]) -> Result> { +pub fn evm_get_balance(address: [u8; 20]) -> u64 { let account = H160::from(address); let (_, latest_block_number) = RUNTIME .handlers @@ -175,35 +183,7 @@ pub fn evm_get_balance(address: [u8; 20]) -> Result> { .unwrap_or_default(); // convert to try_evm_get_balance - Default to 0 for now balance /= WEI_TO_GWEI; balance /= GWEI_TO_SATS; - Ok(balance.as_u64()) -} - -/// Retrieves the nonce of an EVM account at latest block height. -/// -/// # Arguments -/// -/// * `address` - The EVM address of the account. -/// -/// # Errors -/// -/// Throws an Error if the address is not a valid EVM address. -/// -/// # Returns -/// -/// Returns the nonce of the account as a `u64` on success. -pub fn evm_get_nonce(address: [u8; 20]) -> Result> { - let account = H160::from(address); - let (_, latest_block_number) = RUNTIME - .handlers - .block - .get_latest_block_hash_and_number() - .unwrap_or_default(); - let nonce = RUNTIME - .handlers - .evm - .get_nonce(account, latest_block_number) - .unwrap_or_default(); - Ok(nonce.as_u64()) + balance.as_u64() } /// Retrieves the next valid nonce of an EVM account in a specific context @@ -232,17 +212,9 @@ pub fn evm_get_next_valid_nonce_in_context(context: u64, address: [u8; 20]) -> u /// * `context` - The context queue number. /// * `address` - The EVM address of the account. /// -/// /// # Errors -/// -/// Returns an Error if the context does not match any existing queue -/// -pub fn evm_remove_txs_by_sender(context: u64, address: [u8; 20]) -> Result<(), Box> { +pub fn evm_remove_txs_by_sender(context: u64, address: [u8; 20]) { let address = H160::from(address); - RUNTIME - .handlers - .evm - .remove_txs_by_sender(context, address)?; - Ok(()) + let _ = RUNTIME.handlers.evm.remove_txs_by_sender(context, address); } /// EvmIn. Send DFI to an EVM account. @@ -254,28 +226,13 @@ pub fn evm_remove_txs_by_sender(context: u64, address: [u8; 20]) -> Result<(), B /// * `amount` - The amount to add as a byte array. /// * `hash` - The hash value as a byte array. /// -/// # Errors -/// -/// Returns an Error if: -/// - the context does not match any existing queue -/// - the address is not a valid EVM address -/// -/// # Returns -/// -/// Returns `Ok(())` on success. -pub fn evm_add_balance( - context: u64, - address: &str, - amount: [u8; 32], - hash: [u8; 32], -) -> Result<(), Box> { - let address = address.parse()?; - - RUNTIME - .handlers - .evm - .add_balance(context, address, amount.into(), hash)?; - Ok(()) +pub fn evm_add_balance(context: u64, address: &str, amount: [u8; 32], hash: [u8; 32]) { + if let Ok(address) = address.parse() { + let _ = RUNTIME + .handlers + .evm + .add_balance(context, address, amount.into(), hash); + } } /// EvmOut. Send DFI from an EVM account. @@ -297,21 +254,17 @@ pub fn evm_add_balance( /// # Returns /// /// Returns `true` if the balance subtraction is successful, `false` otherwise. -pub fn evm_sub_balance( - context: u64, - address: &str, - amount: [u8; 32], - hash: [u8; 32], -) -> Result> { - let address = address.parse()?; - match RUNTIME - .handlers - .evm - .sub_balance(context, address, amount.into(), hash) - { - Ok(_) => Ok(true), - Err(_) => Ok(false), +pub fn evm_sub_balance(context: u64, address: &str, amount: [u8; 32], hash: [u8; 32]) -> bool { + if let Ok(address) = address.parse() { + if let Ok(()) = RUNTIME + .handlers + .evm + .sub_balance(context, address, amount.into(), hash) + { + return true; + } } + false } /// Validates a raw EVM transaction. @@ -338,12 +291,12 @@ pub fn evm_try_prevalidate_raw_tx( result: &mut CrossBoundaryResult, tx: &str, with_gas_usage: bool, -) -> ffi::ValidateTxResult { +) -> ffi::ValidateTxCompletion { match RUNTIME.handlers.evm.validate_raw_tx(tx, with_gas_usage) { Ok((signed_tx, used_gas)) => { result.ok = true; - ffi::ValidateTxResult { + ffi::ValidateTxCompletion { nonce: signed_tx.nonce().as_u64(), sender: signed_tx.sender.to_fixed_bytes(), used_gas, @@ -354,7 +307,7 @@ pub fn evm_try_prevalidate_raw_tx( result.ok = false; result.reason = e.to_string(); - ffi::ValidateTxResult::default() + ffi::ValidateTxCompletion::default() } } } @@ -393,25 +346,21 @@ fn evm_discard_context(context: u64) { /// - The `raw_tx` is in invalid format /// - The queue does not exists. /// -/// # Returns -/// -/// Returns `true` if the transaction is successfully queued, `false` otherwise. -fn evm_try_queue_tx( - result: &mut CrossBoundaryResult, - context: u64, - raw_tx: &str, - hash: [u8; 32], -) -> Result> { - let signed_tx: SignedTx = raw_tx.try_into()?; - match RUNTIME.handlers.queue_tx(context, signed_tx.into(), hash) { - Ok(_) => { - result.ok = true; - Ok(true) - } +fn evm_try_queue_tx(result: &mut CrossBoundaryResult, context: u64, raw_tx: &str, hash: [u8; 32]) { + let signed_tx: Result = raw_tx.try_into(); + match signed_tx { + Ok(signed_tx) => match RUNTIME.handlers.queue_tx(context, signed_tx.into(), hash) { + Ok(_) => { + result.ok = true; + } + Err(e) => { + result.ok = false; + result.reason = e.to_string(); + } + }, Err(e) => { result.ok = false; result.reason = e.to_string(); - Ok(false) } } } @@ -426,11 +375,6 @@ fn evm_try_queue_tx( /// * `miner_address` - The miner's EVM address as a byte array. /// * `timestamp` - The block's timestamp. /// -/// # Errors -/// -/// Returns an Error if there is an error restoring the state trie. -/// Returns an Error if the block has invalid TXs, viz. out of order nonces -/// /// # Returns /// /// Returns a `FinalizeBlockResult` containing the block hash, failed transactions, and miner fee on success. @@ -441,7 +385,7 @@ fn evm_try_finalize( difficulty: u32, miner_address: [u8; 20], timestamp: u64, -) -> Result> { +) -> ffi::FinalizeBlockCompletion { let eth_address = H160::from(miner_address); match RUNTIME .handlers @@ -449,16 +393,16 @@ fn evm_try_finalize( { Ok((block_hash, failed_txs, gas_used)) => { result.ok = true; - Ok(ffi::FinalizeBlockResult { + ffi::FinalizeBlockCompletion { block_hash, failed_transactions: failed_txs, miner_fee: gas_used, - }) + } } Err(e) => { result.ok = false; result.reason = e.to_string(); - Ok(ffi::FinalizeBlockResult::default()) + ffi::FinalizeBlockCompletion::default() } } } @@ -467,7 +411,18 @@ pub fn preinit() { ain_grpc::preinit(); } -fn evm_disconnect_latest_block() -> Result<(), Box> { +fn evm_disconnect_latest_block() { RUNTIME.handlers.storage.disconnect_latest_block(); - Ok(()) +} + +fn start_servers(result: &mut CrossBoundaryResult, json_addr: &str, grpc_addr: &str) { + match start_evm_servers(json_addr, grpc_addr) { + Ok(()) => { + result.ok = true; + } + Err(e) => { + result.ok = false; + result.reason = e.to_string(); + } + } } diff --git a/src/init.cpp b/src/init.cpp index c8c6001b02..7c01fc2390 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -1972,8 +1972,13 @@ bool AppInitMain(InitInterfaces& interfaces) std::vector> g_endpoints; SetupRPCPorts(eth_endpoints, g_endpoints); - // Start the ETH RPC and gRPC servers - start_servers(eth_endpoints[0].first + ":" + std::to_string(eth_endpoints[0].second), g_endpoints[0].first + "." + std::to_string(g_endpoints[0].second)); + // Start the GRPC and ETH RPC servers + // Default to using the first address passed to bind + CrossBoundaryResult result; + start_servers(result, eth_endpoints[0].first + ":" + std::to_string(eth_endpoints[0].second), g_endpoints[0].first + "." + std::to_string(g_endpoints[0].second)); + if (!result.ok) { + LogPrintf("EVM servers failed to start: %s\n", result.reason.c_str()); + } try { LOCK(cs_main); diff --git a/src/masternodes/rpc_evm.cpp b/src/masternodes/rpc_evm.cpp index 531c121595..b7ac28bb7d 100644 --- a/src/masternodes/rpc_evm.cpp +++ b/src/masternodes/rpc_evm.cpp @@ -112,7 +112,11 @@ UniValue evmtx(const JSONRPCRequest& request) { std::array privKey{}; std::copy(key.begin(), key.end(), privKey.begin()); - const auto signedTx = create_and_sign_tx(CreateTransactionContext{chainID, nonce.ToArrayReversed(), gasPrice.ToArrayReversed(), gasLimit.ToArrayReversed(), to, value.ToArrayReversed(), input, privKey}); + CrossBoundaryResult result; + const auto signedTx = create_and_sign_tx(result, CreateTransactionContext{chainID, nonce.ToArrayReversed(), gasPrice.ToArrayReversed(), gasLimit.ToArrayReversed(), to, value.ToArrayReversed(), input, privKey}); + if (!result.ok) { + throw JSONRPCError(RPC_MISC_ERROR, strprintf("Failed to create and sign TX: %s", result.reason.c_str())); + } std::vector evmTx(signedTx.size()); std::copy(signedTx.begin(), signedTx.end(), evmTx.begin()); @@ -236,7 +240,7 @@ UniValue logvmmaps(const JSONRPCRequest& request) { UniValue result{UniValue::VOBJ}; UniValue indexesJson{UniValue::VOBJ}; const auto type = static_cast(request.params[0].get_int()); - // TODO: For now, we iterate through the whole list. But this is just a debugging RPC. + // TODO: For now, we iterate through the whole list. But this is just a debugging RPC. // But there's no need to iterate the whole list, we can start at where we need to and // return false, once we hit the limit and stop the iter. switch (type) { diff --git a/src/test/transaction_tests.cpp b/src/test/transaction_tests.cpp index a4e53ea09d..afa4d107c3 100644 --- a/src/test/transaction_tests.cpp +++ b/src/test/transaction_tests.cpp @@ -797,7 +797,8 @@ BOOST_AUTO_TEST_CASE(test_CreateEthTx) { rust::Vec input{}; - const auto reply = create_and_sign_tx(CreateTransactionContext{chainID, nonce, gasPrice.ToArrayReversed(), gasLimit.ToArrayReversed(), to, value, input, privKey}); + CrossBoundaryResult result; + const auto reply = create_and_sign_tx(result, CreateTransactionContext{chainID, nonce, gasPrice.ToArrayReversed(), gasLimit.ToArrayReversed(), to, value, input, privKey}); std::vector replyVector(reply.size()); std::copy(reply.begin(), reply.end(), replyVector.begin()); std::string transaction(HexStr(replyVector.begin(), replyVector.end()));