From ef23c9ada8794a9d1649092bd61b23fb1fbfb6c2 Mon Sep 17 00:00:00 2001 From: Niven Date: Thu, 30 Nov 2023 14:17:55 +0800 Subject: [PATCH 01/16] Switch lib from string to byte array --- lib/ain-evm/src/core.rs | 2 +- lib/ain-grpc/src/lib.rs | 10 ++--- lib/ain-rs-exports/src/core.rs | 6 +-- lib/ain-rs-exports/src/lib.rs | 74 +++++++++++++++++----------------- src/init.cpp | 22 ++++++++-- src/key.h | 3 +- 6 files changed, 66 insertions(+), 51 deletions(-) diff --git a/lib/ain-evm/src/core.rs b/lib/ain-evm/src/core.rs index d26d4fed65..7ea344e2e5 100644 --- a/lib/ain-evm/src/core.rs +++ b/lib/ain-evm/src/core.rs @@ -43,7 +43,7 @@ use crate::{ EVMError, Result, }; -pub type XHash = String; +pub type XHash = [u8; 32]; pub struct SignedTxCache { inner: spin::Mutex>, diff --git a/lib/ain-grpc/src/lib.rs b/lib/ain-grpc/src/lib.rs index f414a01d9a..ec225b15c3 100644 --- a/lib/ain-grpc/src/lib.rs +++ b/lib/ain-grpc/src/lib.rs @@ -72,9 +72,9 @@ pub fn init_services() { let _ = &*SERVICES; } -pub fn init_network_json_rpc_service(addr: &str) -> Result<()> { +pub fn init_network_json_rpc_service(addr: String) -> Result<()> { info!("Starting JSON RPC server at {}", addr); - let addr = addr.parse::()?; + let addr = addr.as_str().parse::()?; let max_connections = ain_cpp_imports::get_max_connections(); let max_response_size = ain_cpp_imports::get_max_response_byte_size(); let runtime = &SERVICES; @@ -112,7 +112,7 @@ pub fn init_network_json_rpc_service(addr: &str) -> Result<()> { Ok(()) } -pub fn init_network_grpc_service(_addr: &str) -> Result<()> { +pub fn init_network_grpc_service(_addr: String) -> Result<()> { // log::info!("Starting gRPC server at {}", addr); // Commented out for now as nothing to serve // let runtime = &SERVICES; @@ -122,9 +122,9 @@ pub fn init_network_grpc_service(_addr: &str) -> Result<()> { Ok(()) } -pub fn init_network_subscriptions_service(addr: &str) -> Result<()> { +pub fn init_network_subscriptions_service(addr: String) -> Result<()> { info!("Starting WebSockets server at {}", addr); - let addr = addr.parse::()?; + let addr = addr.as_str().parse::()?; let max_connections = ain_cpp_imports::get_max_connections(); let max_response_size = ain_cpp_imports::get_max_response_byte_size(); let runtime = &SERVICES; diff --git a/lib/ain-rs-exports/src/core.rs b/lib/ain-rs-exports/src/core.rs index 35e0aa176b..9b8ebf8ac9 100644 --- a/lib/ain-rs-exports/src/core.rs +++ b/lib/ain-rs-exports/src/core.rs @@ -20,21 +20,21 @@ pub fn ain_rs_stop_core_services(result: &mut CrossBoundaryResult) { cross_boundary_success(result); } -pub fn ain_rs_init_network_json_rpc_service(result: &mut CrossBoundaryResult, addr: &str) { +pub fn ain_rs_init_network_json_rpc_service(result: &mut CrossBoundaryResult, addr: String) { match ain_grpc::init_network_json_rpc_service(addr) { Ok(()) => cross_boundary_success(result), Err(e) => cross_boundary_error_return(result, e.to_string()), } } -pub fn ain_rs_init_network_grpc_service(result: &mut CrossBoundaryResult, addr: &str) { +pub fn ain_rs_init_network_grpc_service(result: &mut CrossBoundaryResult, addr: String) { match ain_grpc::init_network_grpc_service(addr) { Ok(()) => cross_boundary_success(result), Err(e) => cross_boundary_error_return(result, e.to_string()), } } -pub fn ain_rs_init_network_subscriptions_service(result: &mut CrossBoundaryResult, addr: &str) { +pub fn ain_rs_init_network_subscriptions_service(result: &mut CrossBoundaryResult, addr: String) { match ain_grpc::init_network_subscriptions_service(addr) { Ok(()) => cross_boundary_success(result), Err(e) => cross_boundary_error_return(result, e.to_string()), diff --git a/lib/ain-rs-exports/src/lib.rs b/lib/ain-rs-exports/src/lib.rs index 2dc6f8138b..008c2b2f45 100644 --- a/lib/ain-rs-exports/src/lib.rs +++ b/lib/ain-rs-exports/src/lib.rs @@ -44,25 +44,25 @@ pub mod ffi { fn ain_rs_stop_core_services(result: &mut CrossBoundaryResult); // Networking - fn ain_rs_init_network_json_rpc_service(result: &mut CrossBoundaryResult, addr: &str); - fn ain_rs_init_network_grpc_service(result: &mut CrossBoundaryResult, addr: &str); - fn ain_rs_init_network_subscriptions_service(result: &mut CrossBoundaryResult, addr: &str); + fn ain_rs_init_network_json_rpc_service(result: &mut CrossBoundaryResult, addr: String); + fn ain_rs_init_network_grpc_service(result: &mut CrossBoundaryResult, addr: String); + fn ain_rs_init_network_subscriptions_service(result: &mut CrossBoundaryResult, addr: String); fn ain_rs_stop_network_services(result: &mut CrossBoundaryResult); } // ========== Block ========== #[derive(Default)] pub struct EVMBlockHeader { - pub parent_hash: String, - pub beneficiary: String, - pub state_root: String, - pub receipts_root: String, + pub parent_hash: [u8; 32], + pub beneficiary: [u8; 20], + pub state_root: [u8; 32], + pub receipts_root: [u8; 32], pub number: u64, pub gas_limit: u64, pub gas_used: u64, pub timestamp: u64, pub extra_data: Vec, - pub mix_hash: String, + pub mix_hash: [u8; 32], pub nonce: u64, pub base_fee: u64, } @@ -72,22 +72,22 @@ pub mod ffi { pub struct EVMTransaction { // EIP-2718 transaction type: legacy - 0x0, EIP2930 - 0x1, EIP1559 - 0x2 pub tx_type: u8, - pub hash: String, - pub sender: String, + pub hash: [u8; 32], + pub sender: [u8; 20], pub nonce: u64, pub gas_price: u64, pub gas_limit: u64, pub max_fee_per_gas: u64, pub max_priority_fee_per_gas: u64, pub create_tx: bool, - pub to: String, + pub to: [u8; 20], pub value: u64, pub data: Vec, } #[derive(Default)] pub struct TxMinerInfo { - pub address: String, + pub address: [u8; 20], pub nonce: u64, pub tip_fee: u64, pub min_rbf_tip_fee: u64, @@ -109,15 +109,15 @@ pub mod ffi { pub nonce: u64, pub gas_price: u64, pub gas_limit: u64, - pub to: &'a str, + pub to: [u8; 20], pub value: u64, pub input: Vec, pub priv_key: [u8; 32], } pub struct CreateTransferDomainContext { - pub from: String, - pub to: String, + pub from: [u8; 20], + pub to: [u8; 20], pub native_address: String, pub direction: bool, pub value: u64, @@ -129,9 +129,9 @@ pub mod ffi { } pub struct TransferDomainInfo { - pub from: String, - pub to: String, - pub native_address: String, + pub from: [u8; 20], + pub to: [u8; 20], + pub native_address: [u8; 20], pub direction: bool, pub value: u64, pub token_id: u32, @@ -151,7 +151,7 @@ pub mod ffi { #[derive(Default)] pub struct FinalizeBlockCompletion { - pub block_hash: String, + pub block_hash: [u8; 32], pub total_burnt_fees: u64, pub total_priority_fees: u64, pub block_number: u64, @@ -159,7 +159,7 @@ pub mod ffi { #[derive(Default)] pub struct ValidateTxCompletion { - pub tx_hash: String, + pub tx_hash: [u8; 32], } extern "Rust" { @@ -168,12 +168,12 @@ pub mod ffi { // // If they are fallible, it's a TODO to changed and move later // so errors are propogated up properly. - fn evm_try_get_balance(result: &mut CrossBoundaryResult, address: &str) -> u64; + fn evm_try_get_balance(result: &mut CrossBoundaryResult, address: [u8; 20]) -> u64; fn evm_try_unsafe_create_template( result: &mut CrossBoundaryResult, dvm_block: u64, - miner_address: &str, + miner_address: [u8; 20], difficulty: u32, timestamp: u64, mnview_ptr: usize, @@ -197,27 +197,27 @@ pub mod ffi { fn evm_try_unsafe_get_next_valid_nonce_in_template( result: &mut CrossBoundaryResult, block_template: &BlockTemplateWrapper, - address: &str, + address: [u8; 20], ) -> u64; fn evm_try_unsafe_remove_txs_above_hash_in_template( result: &mut CrossBoundaryResult, block_template: &mut BlockTemplateWrapper, - target_hash: String, - ) -> Vec; + target_hash: [u8; 32], + ) -> Vec<[u8; 32]>; fn evm_try_unsafe_add_balance_in_template( result: &mut CrossBoundaryResult, block_template: &mut BlockTemplateWrapper, raw_tx: &str, - native_hash: &str, + native_hash: [u8; 32], ); fn evm_try_unsafe_sub_balance_in_template( result: &mut CrossBoundaryResult, block_template: &mut BlockTemplateWrapper, raw_tx: &str, - native_hash: &str, + native_hash: [u8; 32], ) -> bool; fn evm_try_unsafe_validate_raw_tx_in_template( @@ -237,7 +237,7 @@ pub mod ffi { result: &mut CrossBoundaryResult, block_template: &mut BlockTemplateWrapper, raw_tx: &str, - native_hash: &str, + native_hash: [u8; 32], ) -> ValidateTxCompletion; fn evm_try_unsafe_construct_block_in_template( @@ -270,28 +270,28 @@ pub mod ffi { fn evm_try_store_account_nonce( result: &mut CrossBoundaryResult, - from_address: &str, + from_address: [u8; 20], nonce: u64, ); fn evm_try_get_block_hash_by_number( result: &mut CrossBoundaryResult, height: u64, - ) -> String; + ) -> [u8; 32]; - fn evm_try_get_block_number_by_hash(result: &mut CrossBoundaryResult, hash: &str) -> u64; + fn evm_try_get_block_number_by_hash(result: &mut CrossBoundaryResult, hash: [u8; 32]) -> u64; fn evm_try_get_block_header_by_hash( result: &mut CrossBoundaryResult, - hash: &str, + hash: [u8; 32], ) -> EVMBlockHeader; fn evm_try_get_tx_by_hash( result: &mut CrossBoundaryResult, - tx_hash: &str, + tx_hash: [u8; 32], ) -> EVMTransaction; - fn evm_try_get_tx_hash(result: &mut CrossBoundaryResult, raw_tx: &str) -> String; + fn evm_try_get_tx_hash(result: &mut CrossBoundaryResult, raw_tx: &str) -> [u8; 32]; fn evm_try_unsafe_make_signed_tx(result: &mut CrossBoundaryResult, raw_tx: &str) -> usize; @@ -304,7 +304,7 @@ pub mod ffi { fn evm_try_unsafe_create_dst20( result: &mut CrossBoundaryResult, block_template: &mut BlockTemplateWrapper, - native_hash: &str, + native_hash: [u8; 32], token: DST20TokenInfo, ); @@ -312,14 +312,14 @@ pub mod ffi { result: &mut CrossBoundaryResult, block_template: &mut BlockTemplateWrapper, raw_tx: &str, - native_hash: &str, + native_hash: [u8; 32], token_id: u64, out: bool, ); fn evm_try_unsafe_is_smart_contract_in_template( result: &mut CrossBoundaryResult, - address: &str, + address: [u8; 20], block_template: &BlockTemplateWrapper, ) -> bool; diff --git a/src/init.cpp b/src/init.cpp index 4fb992c024..6a24036cc5 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -2314,11 +2314,17 @@ bool AppInitMain(InitInterfaces& interfaces) { std::vector eth_endpoints, g_endpoints, ws_endpoints; SetupRPCPorts(eth_endpoints, g_endpoints, ws_endpoints); + CrossBoundaryResult result; // Bind ETH RPC addresses for (auto it = eth_endpoints.begin(); it != eth_endpoints.end(); ++it) { LogPrint(BCLog::HTTP, "Binding ETH RPC server on endpoint %s\n", *it); - auto res = XResultStatusLogged(ain_rs_init_network_json_rpc_service(result, *it)) + const auto addr = rs_try_from_utf8(result, ffi_from_string_to_slice(*it)); + if (!result.ok) { + LogPrint(BCLog::HTTP, "Invalid ETH RPC address, not UTF-8 valid"); + return false; + } + auto res = XResultStatusLogged(ain_rs_init_network_json_rpc_service(result, addr)) if (!res) { LogPrintf("Binding ETH RPC server on endpoint %s failed.\n", *it); return false; @@ -2328,7 +2334,12 @@ bool AppInitMain(InitInterfaces& interfaces) // Bind gRPC addresses for (auto it = g_endpoints.begin(); it != g_endpoints.end(); ++it) { LogPrint(BCLog::HTTP, "Binding gRPC server on endpoint %s\n", *it); - auto res = XResultStatusLogged(ain_rs_init_network_grpc_service(result, *it)) + const auto addr = rs_try_from_utf8(result, ffi_from_string_to_slice(*it)); + if (!result.ok) { + LogPrint(BCLog::HTTP, "Invalid gRPC address, not UTF-8 valid"); + return false; + } + auto res = XResultStatusLogged(ain_rs_init_network_grpc_service(result, addr)) if (!res) { LogPrintf("Binding gRPC server on endpoint %s failed.\n", *it); return false; @@ -2338,7 +2349,12 @@ bool AppInitMain(InitInterfaces& interfaces) // bind websocket addresses for (auto it = ws_endpoints.begin(); it != ws_endpoints.end(); ++it) { LogPrint(BCLog::HTTP, "Binding websocket server on endpoint %s\n", *it); - auto res = XResultStatusLogged(ain_rs_init_network_subscriptions_service(result, *it)) + const auto addr = rs_try_from_utf8(result, ffi_from_string_to_slice(*it)); + if (!result.ok) { + LogPrint(BCLog::HTTP, "Invalid websocket address, not UTF-8 valid"); + return false; + } + auto res = XResultStatusLogged(ain_rs_init_network_subscriptions_service(result, addr)) if (!res) { LogPrintf("Binding websocket server on endpoint %s failed.\n", *it); return false; diff --git a/src/key.h b/src/key.h index 0857fa6639..26699ab05e 100644 --- a/src/key.h +++ b/src/key.h @@ -15,8 +15,7 @@ #include #include -// typedef std::array EvmAddressData; -typedef std::string EvmAddressData; +typedef std::array EvmAddressData; /** * secure_allocator is defined in allocators.h From 045500db10e5694eaac044a9a412600cea048c86 Mon Sep 17 00:00:00 2001 From: Niven Date: Thu, 30 Nov 2023 23:31:51 +0800 Subject: [PATCH 02/16] Shift all exposed ffi and ffi calls to use byte arrays directly --- lib/ain-cpp-imports/src/bridge.rs | 2 +- lib/ain-cpp-imports/src/lib.rs | 4 +- lib/ain-evm/src/core.rs | 27 +++----- lib/ain-evm/src/evm.rs | 2 +- lib/ain-grpc/src/rpc/eth.rs | 3 +- lib/ain-rs-exports/src/evm.rs | 101 +++++++++++++----------------- lib/ain-rs-exports/src/lib.rs | 18 ++++-- src/dfi/consensus/xvm.cpp | 46 ++++++++------ src/dfi/evm.h | 1 + src/dfi/mn_checks.cpp | 2 +- src/dfi/mn_checks.h | 2 +- src/dfi/rpc_accounts.cpp | 40 ++++++------ src/dfi/rpc_customtx.cpp | 14 +++-- src/dfi/rpc_evm.cpp | 22 ++++--- src/dfi/tokens.cpp | 2 +- src/dfi/validation.cpp | 10 +-- src/ffi/ffiexports.cpp | 11 +--- src/ffi/ffiexports.h | 2 +- src/ffi/ffihelpers.h | 16 +++++ src/miner.cpp | 5 +- src/rpc/blockchain.cpp | 18 ++++-- src/test/transaction_tests.cpp | 7 ++- src/validation.cpp | 2 +- 23 files changed, 193 insertions(+), 164 deletions(-) diff --git a/lib/ain-cpp-imports/src/bridge.rs b/lib/ain-cpp-imports/src/bridge.rs index 53d3662157..049aaefda6 100644 --- a/lib/ain-cpp-imports/src/bridge.rs +++ b/lib/ain-cpp-imports/src/bridge.rs @@ -41,7 +41,7 @@ pub mod ffi { fn getPoolTransactions() -> Vec; fn getNativeTxSize(data: Vec) -> u64; fn getMinRelayTxFee() -> u64; - fn getEthPrivKey(key: String) -> [u8; 32]; + fn getEthPrivKey(key: [u8; 20]) -> [u8; 32]; fn getStateInputJSON() -> String; fn getEthSyncStatus() -> [i64; 2]; fn getAttributeValues(mnview_ptr: usize) -> Attributes; diff --git a/lib/ain-cpp-imports/src/lib.rs b/lib/ain-cpp-imports/src/lib.rs index fd008bd4bc..9f2f5a0daf 100644 --- a/lib/ain-cpp-imports/src/lib.rs +++ b/lib/ain-cpp-imports/src/lib.rs @@ -68,7 +68,7 @@ mod ffi { pub fn getMinRelayTxFee() -> u64 { unimplemented!("{}", UNIMPL_MSG) } - pub fn getEthPrivKey(_key: String) -> [u8; 32] { + pub fn getEthPrivKey(_key: [u8; 20]) -> [u8; 32] { unimplemented!("{}", UNIMPL_MSG) } pub fn getStateInputJSON() -> String { @@ -207,7 +207,7 @@ pub fn get_min_relay_tx_fee() -> Result> { } /// Gets the private key for the given pubkey string. -pub fn get_eth_priv_key(key: String) -> Result<[u8; 32], Box> { +pub fn get_eth_priv_key(key: [u8; 20]) -> Result<[u8; 32], Box> { let eth_key = ffi::getEthPrivKey(key); Ok(eth_key) } diff --git a/lib/ain-evm/src/core.rs b/lib/ain-evm/src/core.rs index 7ea344e2e5..a7c29c1460 100644 --- a/lib/ain-evm/src/core.rs +++ b/lib/ain-evm/src/core.rs @@ -159,9 +159,9 @@ pub struct ValidateTxInfo { } pub struct TransferDomainTxInfo { - pub from: String, - pub to: String, - pub native_address: String, + pub from: [u8; 20], + pub to: [u8; 20], + pub native_address: [u8; 20], pub direction: bool, pub value: u64, pub token_id: u32, @@ -484,10 +484,7 @@ impl EVMCoreService { } // Validate tx sender with transferdomain sender - let sender = context - .from - .parse::() - .map_err(|_| "Invalid address")?; + let sender = H160::from(context.from); if signed_tx.sender != sender { return Err(format_err!( "[validate_raw_transferdomain_tx] invalid sender, signed_tx.sender : {:#?}, transferdomain sender : {:#?}", @@ -535,19 +532,15 @@ impl EVMCoreService { } } + let native_address = H160::from(context.native_address); + let native_address = format!("{native_address:?}"); let (from_address, to_address) = if context.direction { // EvmIn - let to_address = context - .to - .parse::() - .map_err(|_| "failed to parse to address")?; + let to_address = H160::from(context.to); (fixed_address, to_address) } else { // EvmOut - let from_address = context - .from - .parse::() - .map_err(|_| "failed to parse from address")?; + let from_address = H160::from(context.from); (from_address, fixed_address) }; let value = try_from_satoshi(U256::from(context.value))?.0; @@ -591,7 +584,7 @@ impl EVMCoreService { let ethabi::Token::String(ref input_native_address) = token_inputs[3] else { return Err(format_err!("invalid native address input in evm tx").into()); }; - if context.native_address != *input_native_address { + if native_address != *input_native_address { return Err(format_err!("invalid native address input in evm tx").into()); } } else { @@ -642,7 +635,7 @@ impl EVMCoreService { let ethabi::Token::String(ref input_native_address) = token_inputs[4] else { return Err(format_err!("invalid native address input in evm tx").into()); }; - if context.native_address != *input_native_address { + if native_address != *input_native_address { return Err(format_err!("invalid native address input in evm tx").into()); } } diff --git a/lib/ain-evm/src/evm.rs b/lib/ain-evm/src/evm.rs index e1568d7810..ea7a7f4f1d 100644 --- a/lib/ain-evm/src/evm.rs +++ b/lib/ain-evm/src/evm.rs @@ -221,7 +221,7 @@ impl EVMServices { .collect(), Vec::new(), ); - let block_hash = format!("{:?}", block.header.hash()); + let block_hash = block.header.hash().to_fixed_bytes(); let receipts = self.receipt.generate_receipts( &all_transactions, receipts_v3.clone(), diff --git a/lib/ain-grpc/src/rpc/eth.rs b/lib/ain-grpc/src/rpc/eth.rs index 78c4502b82..29b281d6d2 100644 --- a/lib/ain-grpc/src/rpc/eth.rs +++ b/lib/ain-grpc/src/rpc/eth.rs @@ -1146,8 +1146,7 @@ fn sign( message: TransactionMessage, ) -> Result> { debug!(target:"rpc", "sign address {:#x}", address); - let key = format!("{address:?}"); - let priv_key = get_eth_priv_key(key).unwrap(); + let priv_key = get_eth_priv_key(address.to_fixed_bytes()).unwrap(); let secret_key = SecretKey::parse(&priv_key).unwrap(); match message { diff --git a/lib/ain-rs-exports/src/evm.rs b/lib/ain-rs-exports/src/evm.rs index cf44382ffa..dff826c0f2 100644 --- a/lib/ain-rs-exports/src/evm.rs +++ b/lib/ain-rs-exports/src/evm.rs @@ -49,8 +49,7 @@ fn evm_try_create_and_sign_tx(ctx: ffi::CreateTransactionContext) -> Result().map_err(|_| "Invalid address")?; - TransactionAction::Call(to_address) + TransactionAction::Call(H160::from(ctx.to)) }; let nonce = U256::from(ctx.nonce); let gas_price = try_from_gwei(U256::from(ctx.gas_price))?; @@ -98,14 +97,15 @@ fn evm_try_create_and_sign_transfer_domain_tx( let FixedContract { fixed_address, .. } = get_transfer_domain_contract(); let action = TransactionAction::Call(fixed_address); - let sender = ctx.from.parse::().map_err(|_| "Invalid address")?; - + let sender = H160::from(ctx.from); + let native_address = H160::from(ctx.native_address); + let native_address = format!("{native_address:?}"); let (from_address, to_address) = if ctx.direction { - let to_address = ctx.to.parse::().map_err(|_| "Invalid address")?; + let to_address = H160::from(ctx.to); // Send EvmIn from contract address (fixed_address, to_address) } else { - let from_address = ctx.from.parse::().map_err(|_| "Invalid address")?; + let from_address = H160::from(ctx.from); // Send EvmOut to contract address (from_address, fixed_address) }; @@ -116,7 +116,7 @@ fn evm_try_create_and_sign_transfer_domain_tx( let from_address = ethabi::Token::Address(from_address); let to_address = ethabi::Token::Address(to_address); let value = ethabi::Token::Uint(value.0); - let native_address = ethabi::Token::String(ctx.native_address); + let native_address = ethabi::Token::String(native_address); let is_native_token_transfer = ctx.token_id == 0; if is_native_token_transfer { @@ -167,10 +167,8 @@ fn evm_try_create_and_sign_transfer_domain_tx( } #[ffi_fallible] -fn evm_try_store_account_nonce(from_address: &str, nonce: u64) -> Result<()> { - let from_address = from_address - .parse::() - .map_err(|_| "Invalid address")?; +fn evm_try_store_account_nonce(from_address: [u8; 20], nonce: u64) -> Result<()> { + let from_address = H160::from(from_address); let _ = SERVICES .evm .core @@ -192,10 +190,9 @@ fn evm_try_store_account_nonce(from_address: &str, nonce: u64) -> Result<()> { /// /// Returns the balance of the account as a `u64` on success. #[ffi_fallible] -fn evm_try_get_balance(address: &str) -> Result { - let address = address.parse::().map_err(|_| "Invalid address")?; +fn evm_try_get_balance(address: [u8; 20]) -> Result { + let address = H160::from(address); let state_root = SERVICES.evm.block.get_latest_state_root()?; - let balance = SERVICES.evm.core.get_balance(address, state_root)?; let amount = WeiAmount(balance).to_satoshi()?.try_into()?; @@ -234,10 +231,9 @@ fn evm_try_unsafe_update_state_in_template(template: &mut BlockTemplateWrapper) #[ffi_fallible] fn evm_try_unsafe_get_next_valid_nonce_in_template( template: &BlockTemplateWrapper, - address: &str, + address: [u8; 20], ) -> Result { - let address = address.parse::().map_err(|_| "Invalid address")?; - + let address = H160::from(address); unsafe { let next_nonce = SERVICES .evm @@ -258,13 +254,14 @@ fn evm_try_unsafe_get_next_valid_nonce_in_template( #[ffi_fallible] fn evm_try_unsafe_remove_txs_above_hash_in_template( template: &mut BlockTemplateWrapper, - target_hash: String, -) -> Result> { + target_hash: XHash, +) -> Result<()> { unsafe { SERVICES .evm .core - .remove_txs_above_hash_in_block_template(template.get_inner_mut()?, target_hash) + .remove_txs_above_hash_in_block_template(template.get_inner_mut()?, target_hash)?; + Ok(()) } } @@ -279,14 +276,13 @@ fn evm_try_unsafe_remove_txs_above_hash_in_template( fn evm_try_unsafe_add_balance_in_template( template: &mut BlockTemplateWrapper, raw_tx: &str, - native_hash: &str, + native_hash: XHash, ) -> Result<()> { let signed_tx = SERVICES .evm .core .signed_tx_cache .try_get_or_create(raw_tx)?; - let native_hash = XHash::from(native_hash); let exec_tx = ExecuteTx::SystemTx(SystemTx::TransferDomain(TransferDomainData { signed_tx: Box::new(signed_tx), @@ -310,14 +306,13 @@ fn evm_try_unsafe_add_balance_in_template( fn evm_try_unsafe_sub_balance_in_template( template: &mut BlockTemplateWrapper, raw_tx: &str, - native_hash: &str, + native_hash: XHash, ) -> Result { let signed_tx = SERVICES .evm .core .signed_tx_cache .try_get_or_create(raw_tx)?; - let native_hash = XHash::from(native_hash); let exec_tx = ExecuteTx::SystemTx(SystemTx::TransferDomain(TransferDomainData { signed_tx: Box::new(signed_tx), @@ -506,10 +501,8 @@ fn evm_try_unsafe_remove_template(template: &mut BlockTemplateWrapper) -> Result fn evm_try_unsafe_push_tx_in_template( template: &mut BlockTemplateWrapper, raw_tx: &str, - native_hash: &str, + native_hash: XHash, ) -> Result { - let native_hash = native_hash.to_string(); - unsafe { let signed_tx = SERVICES .evm @@ -525,7 +518,7 @@ fn evm_try_unsafe_push_tx_in_template( )?; Ok(ffi::ValidateTxCompletion { - tx_hash: format!("{:?}", tx_hash), + tx_hash: tx_hash.to_fixed_bytes(), }) } } @@ -604,7 +597,7 @@ fn evm_try_get_block_hash_by_number(height: u64) -> Result { .storage .get_block_by_number(&U256::from(height))? .ok_or("Invalid block number")?; - Ok(format!("{:?}", block.header.hash())) + Ok(block.header.hash().to_fixed_bytes()) } /// Return the block number for a given blockhash. @@ -617,9 +610,8 @@ fn evm_try_get_block_hash_by_number(height: u64) -> Result { /// /// Returns the block number associated with the given blockhash. #[ffi_fallible] -fn evm_try_get_block_number_by_hash(hash: &str) -> Result { - let hash = hash.parse::().map_err(|_| "Invalid hash")?; - +fn evm_try_get_block_number_by_hash(hash: XHash) -> Result { + let hash = H256::from(hash); let block = SERVICES .evm .storage @@ -630,9 +622,8 @@ fn evm_try_get_block_number_by_hash(hash: &str) -> Result { } #[ffi_fallible] -fn evm_try_get_block_header_by_hash(hash: &str) -> Result { - let hash = hash.parse::().map_err(|_| "Invalid hash")?; - +fn evm_try_get_block_header_by_hash(hash: XHash) -> Result { + let hash = H256::from(hash); let block = SERVICES .evm .storage @@ -645,16 +636,16 @@ fn evm_try_get_block_header_by_hash(hash: &str) -> Result { let base_fee = u64::try_from(WeiAmount(block.header.base_fee).to_satoshi()?)?; let out = ffi::EVMBlockHeader { - parent_hash: format!("{:?}", block.header.parent_hash), - beneficiary: format!("{:?}", block.header.beneficiary), - state_root: format!("{:?}", block.header.state_root), - receipts_root: format!("{:?}", block.header.receipts_root), + parent_hash: block.header.parent_hash.to_fixed_bytes(), + beneficiary: block.header.beneficiary.to_fixed_bytes(), + state_root: block.header.state_root.to_fixed_bytes(), + receipts_root: block.header.receipts_root.to_fixed_bytes(), number, gas_limit, gas_used, timestamp: block.header.timestamp, extra_data: block.header.extra_data.clone(), - mix_hash: format!("{:?}", block.header.mix_hash), + mix_hash: block.header.mix_hash.to_fixed_bytes(), nonce: block.header.nonce.to_low_u64_be(), base_fee, }; @@ -662,9 +653,8 @@ fn evm_try_get_block_header_by_hash(hash: &str) -> Result { } #[ffi_fallible] -fn evm_try_get_tx_by_hash(tx_hash: &str) -> Result { - let tx_hash = tx_hash.parse::().map_err(|_| "Invalid hash")?; - +fn evm_try_get_tx_by_hash(tx_hash: XHash) -> Result { + let tx_hash = H256::from(tx_hash); let tx = SERVICES .evm .storage @@ -701,8 +691,8 @@ fn evm_try_get_tx_by_hash(tx_hash: &str) -> Result { let out = ffi::EVMTransaction { tx_type, - hash: format!("{:?}", tx.hash()), - sender: format!("{:?}", tx.sender), + hash: tx.hash().to_fixed_bytes(), + sender: tx.sender.to_fixed_bytes(), nonce, gas_price, gas_limit, @@ -713,8 +703,8 @@ fn evm_try_get_tx_by_hash(tx_hash: &str) -> Result { TransactionAction::Create => true, }, to: match tx.to() { - Some(to) => format!("{to:?}"), - None => XHash::new(), + Some(to) => to.to_fixed_bytes(), + None => H160::zero().to_fixed_bytes(), }, value, data: tx.data().to_vec(), @@ -725,10 +715,9 @@ fn evm_try_get_tx_by_hash(tx_hash: &str) -> Result { #[ffi_fallible] fn evm_try_unsafe_create_dst20( template: &mut BlockTemplateWrapper, - native_hash: &str, + native_hash: XHash, token: ffi::DST20TokenInfo, ) -> Result<()> { - let native_hash = XHash::from(native_hash); let address = ain_contracts::dst20_address_from_token_id(token.id)?; debug!("Deploying to address {:#?}", address); @@ -750,11 +739,10 @@ fn evm_try_unsafe_create_dst20( fn evm_try_unsafe_bridge_dst20( template: &mut BlockTemplateWrapper, raw_tx: &str, - native_hash: &str, + native_hash: XHash, token_id: u64, out: bool, ) -> Result<()> { - let native_hash = XHash::from(native_hash); let contract_address = ain_contracts::dst20_address_from_token_id(token_id)?; let signed_tx = SERVICES .evm @@ -783,13 +771,13 @@ fn evm_try_unsafe_bridge_dst20( /// /// Returns the transaction's hash #[ffi_fallible] -fn evm_try_get_tx_hash(raw_tx: &str) -> Result { +fn evm_try_get_tx_hash(raw_tx: &str) -> Result<[u8; 32]> { let signed_tx = SERVICES .evm .core .signed_tx_cache .try_get_or_create(raw_tx)?; - Ok(format!("{:?}", signed_tx.hash())) + Ok(signed_tx.hash().to_fixed_bytes()) } #[ffi_fallible] @@ -820,11 +808,10 @@ fn evm_try_unsafe_cache_signed_tx(raw_tx: &str, instance: usize) -> Result<()> { /// Returns `true` if the address is a contract, `false` otherwise #[ffi_fallible] fn evm_try_unsafe_is_smart_contract_in_template( - address: &str, + address: [u8; 20], template: &BlockTemplateWrapper, ) -> Result { - let address = address.parse::().map_err(|_| "Invalid address")?; - + let address = H160::from(address); unsafe { SERVICES .evm @@ -856,7 +843,7 @@ fn evm_try_get_tx_miner_info_from_raw_tx(raw_tx: &str, mnview_ptr: usize) -> Res Ok(TxMinerInfo { nonce, - address: format!("{:?}", signed_tx.sender), + address: signed_tx.sender.to_fixed_bytes(), tip_fee, min_rbf_tip_fee, }) diff --git a/lib/ain-rs-exports/src/lib.rs b/lib/ain-rs-exports/src/lib.rs index 008c2b2f45..2276c6450c 100644 --- a/lib/ain-rs-exports/src/lib.rs +++ b/lib/ain-rs-exports/src/lib.rs @@ -46,7 +46,10 @@ pub mod ffi { // Networking fn ain_rs_init_network_json_rpc_service(result: &mut CrossBoundaryResult, addr: String); fn ain_rs_init_network_grpc_service(result: &mut CrossBoundaryResult, addr: String); - fn ain_rs_init_network_subscriptions_service(result: &mut CrossBoundaryResult, addr: String); + fn ain_rs_init_network_subscriptions_service( + result: &mut CrossBoundaryResult, + addr: String, + ); fn ain_rs_stop_network_services(result: &mut CrossBoundaryResult); } @@ -104,7 +107,7 @@ pub mod ffi { // ========== EVM ========== - pub struct CreateTransactionContext<'a> { + pub struct CreateTransactionContext { pub chain_id: u64, pub nonce: u64, pub gas_price: u64, @@ -118,7 +121,7 @@ pub mod ffi { pub struct CreateTransferDomainContext { pub from: [u8; 20], pub to: [u8; 20], - pub native_address: String, + pub native_address: [u8; 20], pub direction: bool, pub value: u64, pub token_id: u32, @@ -173,7 +176,7 @@ pub mod ffi { fn evm_try_unsafe_create_template( result: &mut CrossBoundaryResult, dvm_block: u64, - miner_address: [u8; 20], + miner_address: &str, difficulty: u32, timestamp: u64, mnview_ptr: usize, @@ -204,7 +207,7 @@ pub mod ffi { result: &mut CrossBoundaryResult, block_template: &mut BlockTemplateWrapper, target_hash: [u8; 32], - ) -> Vec<[u8; 32]>; + ); fn evm_try_unsafe_add_balance_in_template( result: &mut CrossBoundaryResult, @@ -279,7 +282,10 @@ pub mod ffi { height: u64, ) -> [u8; 32]; - fn evm_try_get_block_number_by_hash(result: &mut CrossBoundaryResult, hash: [u8; 32]) -> u64; + fn evm_try_get_block_number_by_hash( + result: &mut CrossBoundaryResult, + hash: [u8; 32], + ) -> u64; fn evm_try_get_block_header_by_hash( result: &mut CrossBoundaryResult, diff --git a/src/dfi/consensus/xvm.cpp b/src/dfi/consensus/xvm.cpp index 9524d69fc6..1e035a44a9 100644 --- a/src/dfi/consensus/xvm.cpp +++ b/src/dfi/consensus/xvm.cpp @@ -12,6 +12,7 @@ #include #include #include +#include constexpr uint32_t MAX_TRANSFERDOMAIN_EVM_DATA_LEN = 1024; @@ -56,6 +57,8 @@ static Res ValidateTransferDomainScripts(const CScript &srcScript, const auto srcType = FromTxDestType(src.index()); const auto destType = FromTxDestType(dest.index()); + const auto srcKey = CKeyID::FromOrDefaultDestination(src); + const auto destKey = CKeyID::FromOrDefaultDestination(dest); if (edge == VMDomainEdge::DVMToEVM) { if (!config.dvmToEvmSrcAddresses.count(srcType)) { @@ -64,8 +67,8 @@ static Res ValidateTransferDomainScripts(const CScript &srcScript, if (!config.dvmToEvmDestAddresses.count(destType)) { return DeFiErrors::TransferDomainETHDestAddress(); } - context.to = EncodeDestination(dest); - context.native_address = EncodeDestination(src); + context.to = destKey.GetByteArray(); + context.native_address = srcKey.GetByteArray(); return Res::Ok(); } else if (edge == VMDomainEdge::EVMToDVM) { @@ -75,8 +78,8 @@ static Res ValidateTransferDomainScripts(const CScript &srcScript, if (!config.evmToDvmDestAddresses.count(destType)) { return DeFiErrors::TransferDomainDVMDestAddress(); } - context.from = EncodeDestination(src); - context.native_address = EncodeDestination(dest); + context.from = srcKey.GetByteArray(); + context.native_address = destKey.GetByteArray(); return Res::Ok(); } @@ -149,7 +152,8 @@ static Res ValidateTransferDomainEdge(const CTransaction &tx, if (!ExtractDestination(from, dest)) { return DeFiErrors::ScriptUnexpected(from); } - context.from = EncodeDestination(dest); + const auto destKey = CKeyID::FromOrDefaultDestination(dest); + context.from = destKey.GetByteArray(); return HasAuth(tx, coins, src.address); @@ -261,7 +265,7 @@ Res CXVMConsensus::operator()(const CTransferDomainMessage &obj) const { // Check if destination address is a contract auto isSmartContract = - evm_try_unsafe_is_smart_contract_in_template(result, toAddress->GetHex(), evmTemplate->GetTemplate()); + evm_try_unsafe_is_smart_contract_in_template(result, toAddress->GetByteArray(), evmTemplate->GetTemplate()); if (!result.ok) { return Res::Err("Error checking contract address: %s", result.reason); } @@ -298,22 +302,24 @@ Res CXVMConsensus::operator()(const CTransferDomainMessage &obj) const { return Res::Ok(); } - auto hash = evm_try_get_tx_hash(result, evmTx); + auto bytes = evm_try_get_tx_hash(result, evmTx); if (!result.ok) { return Res::Err("Error getting tx hash: %s", result.reason); } - evmTxHash = std::string(hash.data(), hash.length()).substr(2); + auto hash = ffi_from_byte_vector_to_uint256(bytes); + evmTxHash = hash.GetHex(); + // Add balance to ERC55 address auto tokenId = dst.amount.nTokenId; if (tokenId == DCT_ID{0}) { evm_try_unsafe_add_balance_in_template( - result, evmTemplate->GetTemplate(), evmTx, tx.GetHash().GetHex()); + result, evmTemplate->GetTemplate(), evmTx, tx.GetHash().GetByteArray()); if (!result.ok) { return Res::Err("Error bridging DFI: %s", result.reason); } } else { evm_try_unsafe_bridge_dst20( - result, evmTemplate->GetTemplate(), evmTx, tx.GetHash().GetHex(), tokenId.v, true); + result, evmTemplate->GetTemplate(), evmTx, tx.GetHash().GetByteArray(), tokenId.v, true); if (!result.ok) { return Res::Err("Error bridging DST20: %s", result.reason); } @@ -334,7 +340,7 @@ Res CXVMConsensus::operator()(const CTransferDomainMessage &obj) const { // Check if source address is a contract auto isSmartContract = - evm_try_unsafe_is_smart_contract_in_template(result, fromAddress->GetHex(), evmTemplate->GetTemplate()); + evm_try_unsafe_is_smart_contract_in_template(result, fromAddress->GetByteArray(), evmTemplate->GetTemplate()); if (!result.ok) { return Res::Err("Error checking contract address: %s", result.reason); } @@ -355,17 +361,18 @@ Res CXVMConsensus::operator()(const CTransferDomainMessage &obj) const { return Res::Ok(); } - auto hash = evm_try_get_tx_hash(result, evmTx); + auto bytes = evm_try_get_tx_hash(result, evmTx); if (!result.ok) { return Res::Err("Error getting tx hash: %s", result.reason); } - evmTxHash = std::string(hash.data(), hash.length()).substr(2); + auto hash = ffi_from_byte_vector_to_uint256(bytes); + evmTxHash = hash.GetHex(); // Subtract balance from ERC55 address auto tokenId = dst.amount.nTokenId; if (tokenId == DCT_ID{0}) { if (!evm_try_unsafe_sub_balance_in_template( - result, evmTemplate->GetTemplate(), evmTx, tx.GetHash().GetHex())) { + result, evmTemplate->GetTemplate(), evmTx, tx.GetHash().GetByteArray())) { return DeFiErrors::TransferDomainNotEnoughBalance(EncodeDestination(dest)); } if (!result.ok) { @@ -373,7 +380,7 @@ Res CXVMConsensus::operator()(const CTransferDomainMessage &obj) const { } } else { evm_try_unsafe_bridge_dst20( - result, evmTemplate->GetTemplate(), evmTx, tx.GetHash().GetHex(), tokenId.v, false); + result, evmTemplate->GetTemplate(), evmTx, tx.GetHash().GetByteArray(), tokenId.v, false); if (!result.ok) { return Res::Err("Error bridging DST20: %s", result.reason); } @@ -386,7 +393,7 @@ Res CXVMConsensus::operator()(const CTransferDomainMessage &obj) const { res = mnview.AddBalance(dst.address, dst.amount); if (!res) { evm_try_unsafe_remove_txs_above_hash_in_template( - result, evmTemplate->GetTemplate(), tx.GetHash().GetHex()); + result, evmTemplate->GetTemplate(), tx.GetHash().GetByteArray()); return res; } stats.evmDvmTotal.Add(dst.amount); @@ -412,7 +419,7 @@ Res CXVMConsensus::operator()(const CTransferDomainMessage &obj) const { attributes->SetValue(CTransferDomainStatsLive::Key, stats); res = mnview.SetVariable(*attributes); if (!res) { - evm_try_unsafe_remove_txs_above_hash_in_template(result, evmTemplate->GetTemplate(), tx.GetHash().GetHex()); + evm_try_unsafe_remove_txs_above_hash_in_template(result, evmTemplate->GetTemplate(), tx.GetHash().GetByteArray()); return res; } return Res::Ok(); @@ -439,14 +446,15 @@ Res CXVMConsensus::operator()(const CEvmTxMessage &obj) const { } const auto validateResults = evm_try_unsafe_push_tx_in_template( - result, evmTemplate->GetTemplate(), HexStr(obj.evmTx), tx.GetHash().GetHex()); + result, evmTemplate->GetTemplate(), HexStr(obj.evmTx), tx.GetHash().GetByteArray()); if (!result.ok) { LogPrintf("[evm_try_push_tx_in_template] failed, reason : %s\n", result.reason); return Res::Err("evm tx failed to queue %s\n", result.reason); } auto txHash = tx.GetHash().GetHex(); - auto evmTxHash = std::string(validateResults.tx_hash.data(), validateResults.tx_hash.length()).substr(2); + auto hash = ffi_from_byte_vector_to_uint256(validateResults.tx_hash); + auto evmTxHash = hash.GetHex(); auto res = mnview.SetVMDomainTxEdge(VMDomainEdge::DVMToEVM, txHash, evmTxHash); if (!res) { LogPrintf("Failed to store DVMtoEVM TX hash for DFI TX %s\n", txHash); diff --git a/src/dfi/evm.h b/src/dfi/evm.h index c045a60f93..1a085367a8 100644 --- a/src/dfi/evm.h +++ b/src/dfi/evm.h @@ -6,6 +6,7 @@ #include #include #include +#include #include