diff --git a/lib/ain-rs-exports/src/evm.rs b/lib/ain-rs-exports/src/evm.rs index 0f8fe61769..4a680dfa4a 100644 --- a/lib/ain-rs-exports/src/evm.rs +++ b/lib/ain-rs-exports/src/evm.rs @@ -722,11 +722,6 @@ pub fn evm_try_get_dst20_total_supply( }, }; - debug!( - "[evm_try_get_dst20_total_supply] State root {:#?}", - state_root - ); - match SERVICES.evm.get_dst20_total_supply(token_id, state_root) { Ok(total_supply) => { let Ok(total_supply) = u64::try_from(WeiAmount(total_supply).to_satoshi()) else { diff --git a/src/masternodes/errors.h b/src/masternodes/errors.h index d999c976ed..9d3b576e10 100644 --- a/src/masternodes/errors.h +++ b/src/masternodes/errors.h @@ -538,6 +538,10 @@ class DeFiErrors { return Res::Err("Accounting mistmatch on EVM side for DST20 token #%s: Old: %lld New: %lld Current: %lld", token, oldBalance, newBalance, currentBalance); } + static Res InvalidEVMAddressBalance() { + return Res::Err("Unable to read EVM address balance"); + } + static Res SettingEVMAttributeFailure() { return Res::Err("Failed to set EVM attribute"); } diff --git a/src/masternodes/validation.cpp b/src/masternodes/validation.cpp index 584752fe0f..386f301818 100644 --- a/src/masternodes/validation.cpp +++ b/src/masternodes/validation.cpp @@ -2413,29 +2413,44 @@ CTransferDomainMessage DecodeTransferDomainMessage(const CTransactionRef& tx, co return CTransferDomainMessage{}; } -CAmount GetEvmDST20TotalSupply(const DCT_ID& id, const std::string &stateRoot = std::string()) { +ResVal GetEVMBlockCount() { + auto result = XResultValue(evm_try_get_block_count(result)); + if (!result) { + return result; + } + + return {static_cast(*result), Res::Ok()}; +} + +ResVal GetEvmDST20TotalSupply(const DCT_ID& id, const std::string &stateRoot = std::string()) { auto result = XResultValue(evm_try_get_dst20_total_supply(result, id.v, stateRoot)); - if (result) - if (auto balance = *result) - return static_cast(balance); + if (!result) { + return result; + } - return -1; + return {static_cast(*result), Res::Ok()}; } -CAmount GetEvmDFIBalance(const CScript& address, const std::string &stateRoot = std::string()) { +ResVal GetEvmDFIBalance(const CScript& address, const std::string &stateRoot = std::string()) { CTxDestination dest; if (ExtractDestination(address, dest) && dest.index() == WitV16KeyEthHashType) { const auto keyID = std::get(dest); auto result = XResultValue(stateRoot.empty() ? evm_try_get_balance(result, keyID.ToHexString()) : evm_try_get_balance_at_state_root(result, keyID.ToHexString(), stateRoot)); - if (result) - if (auto balance = *result) - return static_cast(balance); + if (!result) { + return result; + } + + return {static_cast(*result), Res::Ok()}; } - return -1; + return DeFiErrors::InvalidEVMAddressBalance(); } -void ProcessAccountingStateBeforeBlock(const CBlock &block, const CBlockIndex* pindex, CCustomCSView &mnview, const CChainParams& chainparams, CEVMInitialState& evmInitialState) { +Res ProcessAccountingStateBeforeBlock(const CBlock &block, const CBlockIndex* pindex, CCustomCSView &mnview, const CChainParams& chainparams, CEVMInitialState& evmInitialState) { + auto evmBlockCount = GetEVMBlockCount(); + if (!evmBlockCount || !*evmBlockCount) + return Res::Ok(); + std::map &evmBalances = evmInitialState.evmBalances; CStatsTokenBalances& dst20EvmTotalSupply = evmInitialState.dst20EvmTotalSupply; @@ -2444,33 +2459,40 @@ void ProcessAccountingStateBeforeBlock(const CBlock &block, const CBlockIndex* p auto txMessage = DecodeTransferDomainMessage(tx, pindex, chainparams); for (auto const &[src, dst]: txMessage.transfers){ if (src.amount.nTokenId == DCT_ID{0}) { - std::vector> balanceList{ - { src.domain, VMDomain::EVM, src.address, src.amount, evmBalances.find(src.address) == evmBalances.end() }, - { dst.domain, VMDomain::EVM, dst.address, src.amount, evmBalances.find(dst.address) == evmBalances.end() }, - }; - for (auto [domain, domainTarget, address, amount, condition]: balanceList) { - if (domain == static_cast(domainTarget) && condition) { - if (amount.nTokenId == DCT_ID{0}) { - auto balance = GetEvmDFIBalance(address); - if (balance > -1) evmBalances[address].Add({amount.nTokenId, balance}); - } - } + auto condition = evmBalances.find(src.address) == evmBalances.end(); + if ((src.domain == static_cast(VMDomain::EVM) || dst.domain == static_cast(VMDomain::EVM)) && condition) { + auto address = src.domain == static_cast(VMDomain::EVM) ? src.address : dst.address; + auto balance = GetEvmDFIBalance(address); + if (!balance) + return balance; + + evmBalances[address].Add({DCT_ID{0}, *balance}); } } } } + auto res = Res::Ok(); // Storing inital EVM DST20 total supply mnview.ForEachToken([&](DCT_ID const& id, CTokenImplementation token) { auto supply = GetEvmDST20TotalSupply(id); - if (supply != -1) - dst20EvmTotalSupply.Add({id, supply}); + if (!supply) { + res = supply; + return false; + } + dst20EvmTotalSupply.Add({id, *supply}); return true; }); + + return res; } static Res ProcessAccountingConsensusChecks(const CBlock &block, const CBlockIndex* pindex, CCustomCSView& cache, const CChainParams& chainparams, CEVMInitialState& evmInitialState, const CEvmBlockStatsLive& evmStats, const std::string &stateRoot) { + auto evmBlockCount = GetEVMBlockCount(); + if (!evmBlockCount || !*evmBlockCount) + return Res::Ok(); + auto attributes = cache.GetAttributes(); assert(attributes); @@ -2554,10 +2576,12 @@ static Res ProcessAccountingConsensusChecks(const CBlock &block, const CBlockInd auto oldBalance = (evmInitialState.evmBalances.find(address) != evmInitialState.evmBalances.end()) ? evmInitialState.evmBalances[address] : CStatsTokenBalances{}; auto newBalance = oldBalance; auto balance = GetEvmDFIBalance(address,stateRoot); + if (!balance) + return balance; newBalance.AddBalances(delta.balances); - if (balance > -1 && newBalance.balances[DFIToken] != balance) - return DeFiErrors::AccountingMissmatchEVM(ScriptToString(address), oldBalance.balances[DFIToken], newBalance.balances[DFIToken], balance); + if (newBalance.balances[DFIToken] != *balance) + return DeFiErrors::AccountingMissmatchEVM(ScriptToString(address), oldBalance.balances[DFIToken], newBalance.balances[DFIToken], *balance); } // DST20 token EVM totaly supply tally @@ -2565,11 +2589,15 @@ static Res ProcessAccountingConsensusChecks(const CBlock &block, const CBlockInd auto res = Res::Ok(); cache.ForEachToken([&](DCT_ID const& id, CTokenImplementation token) { auto supply = GetEvmDST20TotalSupply(id, stateRoot); - if (supply != -1) - if (deltaDST20EvmTotalSupply.balances[id] != supply || deltaDST20EvmTotalSupply.balances[id] < 0) { - res = DeFiErrors::AccountingMissmatchEVMDST20(id.ToString(), evmInitialState.dst20EvmTotalSupply.balances[id], deltaDST20EvmTotalSupply.balances[id], supply); - return false; - } + if (!supply) { + res = supply; + return false; + } + + if (deltaDST20EvmTotalSupply.balances[id] != *supply || deltaDST20EvmTotalSupply.balances[id] < 0) { + res = DeFiErrors::AccountingMissmatchEVMDST20(id.ToString(), evmInitialState.dst20EvmTotalSupply.balances[id], deltaDST20EvmTotalSupply.balances[id], *supply); + return false; + } return true; }); diff --git a/src/masternodes/validation.h b/src/masternodes/validation.h index 7563afda39..775f63be11 100644 --- a/src/masternodes/validation.h +++ b/src/masternodes/validation.h @@ -19,7 +19,7 @@ using CreationTxs = std::mapGetValue(CTransferDomainStatsLive::Key, CTransferDomainStatsLive{}); - ProcessAccountingStateBeforeBlock(block, pindex, mnview, chainparams, evmInitialState); + auto res = ProcessAccountingStateBeforeBlock(block, pindex, mnview, chainparams, evmInitialState); + if (!res.ok) + return state.Invalid(ValidationInvalidReason::CONSENSUS, error("%s: %s", __func__, res.msg), REJECT_INVALID, res.dbgMsg); } // Execute TXs