From 33eeb372e781241cfdb55f9b176866eed202be89 Mon Sep 17 00:00:00 2001 From: Bushstar Date: Wed, 5 Apr 2023 09:46:27 +0100 Subject: [PATCH 1/8] Return error on sub balance failure. --- src/rust/crates/ain-evm-ffi/src/lib.rs | 15 +++++++++------ src/rust/crates/ain-evm-state/src/handler.rs | 18 +++++++++++++++--- 2 files changed, 24 insertions(+), 9 deletions(-) diff --git a/src/rust/crates/ain-evm-ffi/src/lib.rs b/src/rust/crates/ain-evm-ffi/src/lib.rs index a171e53429a..f719076e83e 100644 --- a/src/rust/crates/ain-evm-ffi/src/lib.rs +++ b/src/rust/crates/ain-evm-ffi/src/lib.rs @@ -7,8 +7,8 @@ use std::error::Error; #[cxx::bridge] mod ffi { extern "Rust" { - fn evm_add_balance(address: &str, amount: [u8; 32]) -> Result<()>; - fn evm_sub_balance(address: &str, amount: [u8; 32]) -> Result<()>; + fn evm_add_balance(context: u64, address: &str, amount: [u8; 32]) -> Result<()>; + fn evm_sub_balance(context: u64, address: &str, amount: [u8; 32]) -> Result; fn evm_validate_raw_tx(tx: &str) -> Result; fn evm_get_context() -> u64; @@ -33,12 +33,15 @@ mod ffi { } } -pub fn evm_add_balance(address: &str, amount: [u8; 32]) -> Result<(), Box> { - RUNTIME.evm.add_balance(address, amount.into()) +pub fn evm_add_balance(context: u64, address: &str, amount: [u8; 32]) -> Result<(), Box> { + RUNTIME.evm.add_balance(context, address, amount.into()) } -pub fn evm_sub_balance(address: &str, amount: [u8; 32]) -> Result<(), Box> { - RUNTIME.evm.sub_balance(address, amount.into()) +pub fn evm_sub_balance(context: u64, address: &str, amount: [u8; 32]) -> Result> { + match RUNTIME.evm.sub_balance(context, address, amount.into()) { + Ok(_) => Ok(true), + Err(_) => Ok(false), + } } pub fn evm_validate_raw_tx(tx: &str) -> Result> { diff --git a/src/rust/crates/ain-evm-state/src/handler.rs b/src/rust/crates/ain-evm-state/src/handler.rs index 1a4fbcc5e39..aca4bec24e2 100644 --- a/src/rust/crates/ain-evm-state/src/handler.rs +++ b/src/rust/crates/ain-evm-state/src/handler.rs @@ -13,6 +13,17 @@ use std::sync::{Arc, RwLock}; use crate::tx_queue::TransactionQueueMap; use crate::EVMState; +#[derive(Debug)] +struct ErrorStr(String); + +impl std::fmt::Display for ErrorStr { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + write!(f, "Error: {}", self.0) + } +} + +impl Error for ErrorStr {} + #[derive(Clone, Debug)] pub struct EVMHandler { pub state: Arc>, @@ -47,7 +58,7 @@ impl EVMHandler { } // TODO wrap in EVM transaction and dryrun with evm_call - pub fn add_balance(&self, address: &str, value: U256) -> Result<(), Box> { + pub fn add_balance(&self, context: u64, address: &str, value: U256) -> Result<(), Box> { let to = address.parse()?; let mut state = self.state.write().unwrap(); let mut account = state.entry(to).or_default(); @@ -55,14 +66,15 @@ impl EVMHandler { Ok(()) } - pub fn sub_balance(&self, address: &str, value: U256) -> Result<(), Box> { + pub fn sub_balance(&self, context: u64, address: &str, value: U256) -> Result<(), Box> { let address = address.parse()?; let mut state = self.state.write().unwrap(); let mut account = state.get_mut(&address).unwrap(); if account.balance > value { account.balance = account.balance - value; + return Ok(()); } - Ok(()) + Err(Box::new(ErrorStr("Sub balance failed".into()))) } pub fn validate_raw_tx(&self, tx: &str) -> Result> { From 4971d726a2ebeb95e8df90b2aaeea1f898277f85 Mon Sep 17 00:00:00 2001 From: Bushstar Date: Wed, 5 Apr 2023 09:55:24 +0100 Subject: [PATCH 2/8] Change to expected return type --- src/wallet/wallet.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 67a80432a75..85afc6cbe60 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -167,7 +167,7 @@ std::array GetKeyFromWallets(rust::Vec input) { } } - std::array result{}; + std::array result{}; std::copy(key.begin(), key.end(), result.begin()); return result; From 518ab4dae34f04131879223cb1597b1131462768 Mon Sep 17 00:00:00 2001 From: Bushstar Date: Wed, 5 Apr 2023 09:55:46 +0100 Subject: [PATCH 3/8] Update EVM in/out TX --- src/amount.h | 2 ++ src/masternodes/mn_checks.cpp | 50 ++++++++++++++++++++++++++++------- src/masternodes/rpc_evm.cpp | 3 --- 3 files changed, 42 insertions(+), 13 deletions(-) diff --git a/src/amount.h b/src/amount.h index dd26bdc686b..67db644848f 100644 --- a/src/amount.h +++ b/src/amount.h @@ -77,6 +77,8 @@ struct DCT_ID { static constexpr CAmount COIN = 100000000; static constexpr CAmount CENT = 1000000; +static constexpr int64_t WEI_IN_GWEI = 1000000000; +static constexpr int64_t CAMOUNT_TO_WEI = 10; //Converts the given value to decimal format string with COIN precision. inline std::string GetDecimalString(CAmount nValue) diff --git a/src/masternodes/mn_checks.cpp b/src/masternodes/mn_checks.cpp index 7afd8c7faaa..8f79d2a4aa7 100644 --- a/src/masternodes/mn_checks.cpp +++ b/src/masternodes/mn_checks.cpp @@ -3834,12 +3834,6 @@ class CCustomTxApplyVisitor : public CCustomTxVisitor { const auto sumFrom = SumAllTransfers(obj.from); const auto sumTo = SumAllTransfers(obj.to); - if (obj.type == CTransferBalanceType::EvmIn || obj.type == CTransferBalanceType::EvmOut) { - for (const auto& [id, _] : sumFrom.balances) - if (id != DCT_ID{0}) - return Res::Err("For EVM in/out transfers only DFI token is currently supported"); - } - if (sumFrom != sumTo) return Res::Err("sum of inputs (from) != sum of outputs (to)"); @@ -3851,18 +3845,54 @@ class CCustomTxApplyVisitor : public CCustomTxVisitor { if (!res) return res; } else if (obj.type == CTransferBalanceType::EvmIn) { - for (const auto& [addr, _] : obj.to) { + res = SubBalancesDelShares(obj.from); + if (!res) + return res; + + for (const auto& [addr, balances] : obj.to) { CTxDestination dest; if (ExtractDestination(addr, dest)) { if (dest.index() != WitV16KeyEthHashType) { return Res::Err("To address must be an ETH address in case of \"evmin\" transfertype"); } } + + const auto toAddress = std::get(dest); + + for (const auto& [id, amount] : balances.balances) { + if (id != DCT_ID{0}) { + return Res::Err("For EVM out transfers, only DFI token is currently supported"); + } + + arith_uint256 balanceIn = amount; + balanceIn *= CAMOUNT_TO_WEI * WEI_IN_GWEI; + evm_add_balance(evmContext, HexStr(toAddress.begin(), toAddress.end()), ArithToUint256(balanceIn).ToArrayReversed()); + } } - res = SubBalancesDelShares(obj.from); - if (!res) - return res; } else if (obj.type == CTransferBalanceType::EvmOut) { + for (const auto& [addr, balances] : obj.from) { + CTxDestination dest; + if (ExtractDestination(addr, dest)) { + if (dest.index() != WitV16KeyEthHashType) { + return Res::Err("Invalid destination"); + } + } + + const auto fromAddress = std::get(dest); + + for (const auto& [id, amount] : balances.balances) { + if (id != DCT_ID{0}) { + return Res::Err("For EVM out transfers, only DFI token is currently supported"); + } + + arith_uint256 balanceIn = amount; + balanceIn *= CAMOUNT_TO_WEI * WEI_IN_GWEI; + if (!evm_sub_balance(evmContext, HexStr(fromAddress.begin(), fromAddress.end()), ArithToUint256(balanceIn).ToArrayReversed())) { + return Res::Err("Not enough balance in %s to cover EVM out", EncodeDestination(dest)); + } + } + } + res = AddBalancesSetShares(obj.to); if (!res) return res; diff --git a/src/masternodes/rpc_evm.cpp b/src/masternodes/rpc_evm.cpp index 1bdd020873a..fed5bc3c220 100644 --- a/src/masternodes/rpc_evm.cpp +++ b/src/masternodes/rpc_evm.cpp @@ -3,9 +3,6 @@ #include #include -const int64_t WEI_IN_GWEI = 1000000000; -const int64_t CAMOUNT_TO_WEI = 10; - UniValue evmtx(const JSONRPCRequest& request) { auto pwallet = GetWallet(request); From 51ee3dc80d6d6288f92b68296674d0d67253fc53 Mon Sep 17 00:00:00 2001 From: Bushstar Date: Wed, 5 Apr 2023 10:07:06 +0100 Subject: [PATCH 4/8] Use array instead of rust::Vec --- src/wallet/wallet.cpp | 2 +- src/wallet/wallet.h | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 85afc6cbe60..1bb27f4d52d 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -156,7 +156,7 @@ std::shared_ptr LoadWallet(interfaces::Chain& chain, const WalletLocati return wallet; } -std::array GetKeyFromWallets(rust::Vec input) { +std::array GetKeyFromWallets(std::array input) { CKey key; CKeyID keyID; std::copy(input.begin(), input.end(), keyID.begin()); diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index d976bded457..4a297c7689a 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -9,7 +9,6 @@ #include #include #include -#include #include #include #include