diff --git a/src/bip47/account.cpp b/src/bip47/account.cpp index 74a56fd582..09ef4ce7b2 100644 --- a/src/bip47/account.cpp +++ b/src/bip47/account.cpp @@ -251,7 +251,12 @@ bool CAccountReceiver::acceptMaskedPayload(std::vector const & ma bool CAccountReceiver::acceptMaskedPayload(std::vector const & maskedPayload, CTransaction const & tx) { - std::unique_ptr jsplit = lelantus::ParseLelantusJoinSplit(tx); + std::unique_ptr jsplit; + try { + jsplit = lelantus::ParseLelantusJoinSplit(tx); + }catch (...) { + return false; + } if (!jsplit) return false; std::unique_ptr pcode; diff --git a/src/hdmint/tracker.cpp b/src/hdmint/tracker.cpp index 1df6b1e081..c394e721d5 100644 --- a/src/hdmint/tracker.cpp +++ b/src/hdmint/tracker.cpp @@ -546,9 +546,7 @@ bool CHDMintTracker::IsMempoolSpendOurs(const std::set& setMempool, con uint32_t pubcoinId; try { std::tie(spend, pubcoinId) = sigma::ParseSigmaSpend(txin); - } catch (CBadTxIn &) { - return false; - } catch (std::ios_base::failure &) { + } catch (...) { return false; } @@ -562,9 +560,7 @@ bool CHDMintTracker::IsMempoolSpendOurs(const std::set& setMempool, con std::unique_ptr joinsplit; try { joinsplit = lelantus::ParseLelantusJoinSplit(tx); - } catch (CBadTxIn &) { - return false; - } catch (std::ios_base::failure &) { + } catch (...) { return false; } diff --git a/src/lelantus.cpp b/src/lelantus.cpp index 31f81b093d..7a973a7929 100644 --- a/src/lelantus.cpp +++ b/src/lelantus.cpp @@ -384,6 +384,12 @@ bool CheckLelantusJoinSplitTransaction( REJECT_MALFORMED, "CheckLelantusJoinSplitTransaction: invalid joinsplit transaction"); } + catch (...) { + return state.DoS(100, + false, + REJECT_MALFORMED, + "CheckLelantusJoinSplitTransaction: failed to deserialize joinsplit"); + } int jSplitVersion = joinsplit->getVersion(); @@ -698,18 +704,6 @@ bool CheckLelantusTransaction( { Consensus::Params const & consensus = ::Params().GetConsensus(); - - if(tx.IsLelantusJoinSplit()) { - CAmount nFees; - try { - nFees = lelantus::ParseLelantusJoinSplit(tx)->getFee(); - } - catch (CBadTxIn&) { - return state.DoS(0, false, REJECT_INVALID, "unable to parse joinsplit"); - } - - } - int realHeight = nHeight; if (realHeight == INT_MAX) { @@ -779,7 +773,7 @@ void RemoveLelantusJoinSplitReferencingBlock(CTxMemPool& pool, CBlockIndex* bloc try { joinsplit = ParseLelantusJoinSplit(tx); } - catch (const std::ios_base::failure &) { + catch (...) { txn_to_remove.push_back(tx); break; } @@ -818,7 +812,7 @@ std::vector GetLelantusJoinSplitSerialNumbers(const CTransaction &tx, co try { return ParseLelantusJoinSplit(tx)->getCoinSerialNumbers(); } - catch (const std::ios_base::failure &) { + catch (...) { return std::vector(); } } @@ -830,7 +824,7 @@ std::vector GetLelantusJoinSplitIds(const CTransaction &tx, const CTxI try { return ParseLelantusJoinSplit(tx)->getCoinGroupIds(); } - catch (const std::ios_base::failure &) { + catch (...) { return std::vector(); } } @@ -961,7 +955,12 @@ bool GetOutPointFromBlock(COutPoint& outPoint, const GroupElement &pubCoinValue, uint32_t nIndex = 0; for (const CTxOut &txout: tx->vout) { if (txout.scriptPubKey.IsLelantusMint() || txout.scriptPubKey.IsLelantusJMint()) { - ParseLelantusMintScript(txout.scriptPubKey, txPubCoinValue); + try { + ParseLelantusMintScript(txout.scriptPubKey, txPubCoinValue); + } + catch (...) { + continue; + } if(pubCoinValue==txPubCoinValue){ outPoint = COutPoint(tx->GetHash(), nIndex); return true; diff --git a/src/llmq/quorums_instantsend.cpp b/src/llmq/quorums_instantsend.cpp index 8795fdaa33..a9e9310f38 100644 --- a/src/llmq/quorums_instantsend.cpp +++ b/src/llmq/quorums_instantsend.cpp @@ -1547,7 +1547,13 @@ CTransaction AdaptJsplitTx(CTransaction const & tx) static size_t const jsplitSerialSize = 32; CTransaction result{tx}; - std::unique_ptr jsplit = lelantus::ParseLelantusJoinSplit(tx); + std::unique_ptr jsplit; + try { + jsplit = lelantus::ParseLelantusJoinSplit(tx); + } + catch (...) { + return result; + } const_cast*>(&result.vin)->clear(); //This const_cast was done intentionally as the current design allows for this way only for (Scalar const & serial : jsplit->getCoinSerialNumbers()) { CTxIn newin; diff --git a/src/qt/transactiondesc.cpp b/src/qt/transactiondesc.cpp index a4101ce501..5cef9772f6 100644 --- a/src/qt/transactiondesc.cpp +++ b/src/qt/transactiondesc.cpp @@ -241,7 +241,12 @@ QString TransactionDesc::toHTML(CWallet *wallet, CWalletTx &wtx, TransactionReco CAmount nTxFee = nDebit - wtx.tx->GetValueOut(); if (wtx.tx->IsLelantusJoinSplit() && wtx.tx->vin.size() > 0) { - nTxFee = lelantus::ParseLelantusJoinSplit(*wtx.tx)->getFee(); + try { + nTxFee = lelantus::ParseLelantusJoinSplit(*wtx.tx)->getFee(); + } + catch (...) { + //do nothing + } } if (nTxFee > 0) strHTML += "" + tr("Transaction fee") + ": " + BitcoinUnits::formatHtmlWithUnit(unit, -nTxFee) + "
"; diff --git a/src/qt/transactionrecord.cpp b/src/qt/transactionrecord.cpp index 9a7d7f2230..b5a0bffcf7 100644 --- a/src/qt/transactionrecord.cpp +++ b/src/qt/transactionrecord.cpp @@ -63,7 +63,11 @@ QList TransactionRecord::decomposeTransaction(const CWallet * if (wtx.tx->IsZerocoinSpend() || isAllSigmaSpendFromMe || isAllJoinSplitFromMe) { CAmount nTxFee = nDebit - wtx.tx->GetValueOut(); if (isAllJoinSplitFromMe && wtx.tx->vin.size() > 0) { - nTxFee = lelantus::ParseLelantusJoinSplit(*wtx.tx)->getFee(); + try { + nTxFee = lelantus::ParseLelantusJoinSplit(*wtx.tx)->getFee(); + } catch (...) { + // do nothing + } } bool first = true; diff --git a/src/rpc/rawtransaction.cpp b/src/rpc/rawtransaction.cpp index 0be544842d..c21827c6aa 100644 --- a/src/rpc/rawtransaction.cpp +++ b/src/rpc/rawtransaction.cpp @@ -123,7 +123,13 @@ void TxToJSON(const CTransaction& tx, const uint256 hashBlock, UniValue& entry) } else if (txin.IsLelantusJoinSplit()) { in.push_back("joinsplit"); fillStdFields(in, txin); - std::unique_ptr jsplit = lelantus::ParseLelantusJoinSplit(tx); + std::unique_ptr jsplit; + try { + jsplit = lelantus::ParseLelantusJoinSplit(tx); + } + catch (...) { + continue; + } in.push_back(Pair("nFees", ValueFromAmount(jsplit->getFee()))); UniValue serials(UniValue::VARR); for (Scalar const & serial : jsplit->getCoinSerialNumbers()) { diff --git a/src/secp256k1/src/cpp/GroupElement.cpp b/src/secp256k1/src/cpp/GroupElement.cpp index 3793f18c5b..b94499cd8f 100644 --- a/src/secp256k1/src/cpp/GroupElement.cpp +++ b/src/secp256k1/src/cpp/GroupElement.cpp @@ -531,7 +531,7 @@ const unsigned char* GroupElement::deserialize(const unsigned char* buffer) { secp256k1_gej_set_ge(reinterpret_cast(g_), &result); if (!secp256k1_ge_is_valid_var(&result) && !result.infinity) { - throw std::runtime_error("GroupElement: deserialize failed"); + throw std::invalid_argument("GroupElement: deserialize failed"); } return buffer + memoryRequired(); } diff --git a/src/validation.cpp b/src/validation.cpp index d61fc26377..08c85b67fb 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -831,6 +831,9 @@ bool AcceptToMemoryPoolWorker(CTxMemPool& pool, CValidationState& state, const C catch (CBadTxIn&) { return state.Invalid(false, REJECT_CONFLICT, "txn-invalid-lelantus-joinsplit"); } + catch (...) { + return state.Invalid(false, REJECT_CONFLICT, "failed to deserialize joinsplit"); + } const std::vector &ids = joinsplit->getCoinGroupIds(); const std::vector& serials = joinsplit->getCoinSerialNumbers(); @@ -1080,6 +1083,9 @@ bool AcceptToMemoryPoolWorker(CTxMemPool& pool, CValidationState& state, const C catch (CBadTxIn&) { return state.DoS(0, false, REJECT_INVALID, "unable to parse joinsplit"); } + catch (...) { + return state.DoS(0, false, REJECT_INVALID, "failed to deserialize joinsplit"); + } } // nModifiedFees includes any fee deltas from PrioritiseTransaction CAmount nModifiedFees = nFees; @@ -1965,6 +1971,9 @@ bool CheckTxInputs(const CTransaction& tx, CValidationState& state, const CCoins catch (CBadTxIn&) { return state.DoS(0, false, REJECT_INVALID, "unable to parse joinsplit"); } + catch (...) { + return state.DoS(0, false, REJECT_INVALID, "failed to deserialize joinsplit"); + } } if (nTxFee < 0) return state.DoS(100, false, REJECT_INVALID, "bad-txns-fee-negative"); @@ -2389,7 +2398,12 @@ static DisconnectResult DisconnectBlock(const CBlock& block, CValidationState& s if(tx.IsSigmaSpend()) nFees += sigma::GetSigmaSpendInput(tx) - tx.GetValueOut(); else if (tx.IsLelantusJoinSplit()) { - nFees += lelantus::ParseLelantusJoinSplit(tx)->getFee(); + try { + nFees += lelantus::ParseLelantusJoinSplit(tx)->getFee(); + } + catch (...) { + // do nothing + } } dbIndexHelper.DisconnectTransactionInputs(tx, pindex->nHeight, i, view); @@ -2777,6 +2791,9 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin catch (CBadTxIn&) { return state.DoS(0, false, REJECT_INVALID, "unable to parse joinsplit"); } + catch (...) { + return state.DoS(0, false, REJECT_INVALID, "failed to deserialize joinsplit"); + } } // Check transaction against signa/lelantus state @@ -3290,7 +3307,7 @@ bool static DisconnectTip(CValidationState& state, const CChainParams& chainpara try { joinsplit = lelantus::ParseLelantusJoinSplit(*tx); } - catch (CBadTxIn &) { + catch (...) { continue; } diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 55b2102bef..529c50d8f5 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -2069,8 +2069,14 @@ UniValue gettransaction(const JSONRPCRequest& request) CAmount nDebit = wtx.GetDebit(filter); CAmount nNet = nCredit - nDebit; CAmount nFee = (wtx.IsFromMe(filter) ? wtx.tx->GetValueOut() - nDebit : 0); - if (wtx.tx->vin[0].IsLelantusJoinSplit()) - nFee = (0 - lelantus::ParseLelantusJoinSplit(*wtx.tx)->getFee()); + if (wtx.tx->vin[0].IsLelantusJoinSplit()) { + try { + nFee = (0 - lelantus::ParseLelantusJoinSplit(*wtx.tx)->getFee()); + } + catch (...) { + // do nothing + } + } entry.push_back(Pair("amount", ValueFromAmount(nNet - nFee))); @@ -4099,7 +4105,7 @@ UniValue listlelantusjoinsplits(const JSONRPCRequest& request) { std::unique_ptr joinsplit; try { joinsplit = lelantus::ParseLelantusJoinSplit(*pwtx->tx); - } catch (std::invalid_argument&) { + } catch (...) { continue; } diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 6dee64d9cb..c787d90757 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -745,7 +745,11 @@ bool CWallet::IsSpent(const uint256 &hash, unsigned int n) const return meta.isUsed; } else if (zwallet && (script.IsLelantusMint() || script.IsLelantusJMint())) { secp_primitives::GroupElement pubcoin; - lelantus::ParseLelantusMintScript(script, pubcoin); + try { + lelantus::ParseLelantusMintScript(script, pubcoin); + } catch (std::invalid_argument &) { + return false; + } uint256 hashPubcoin = primitives::GetPubCoinValueHash(pubcoin); CLelantusMintMeta meta; if(!zwallet->GetTracker().GetLelantusMetaFromPubcoin(hashPubcoin, meta)){ @@ -1425,7 +1429,7 @@ bool CWallet::AbandonTransaction(const uint256& hashTx) try { joinsplit = lelantus::ParseLelantusJoinSplit(*wtx.tx); } - catch (CBadTxIn&) { + catch (...) { continue; } @@ -1590,7 +1594,7 @@ isminetype CWallet::IsMine(const CTxIn &txin, const CTransaction& tx) const try { joinsplit = lelantus::ParseLelantusJoinSplit(tx); } - catch (CBadTxIn&) { + catch (...) { return ISMINE_NO; } @@ -1651,7 +1655,7 @@ CAmount CWallet::GetDebit(const CTxIn &txin, const CTransaction& tx, const ismin try { joinsplit = lelantus::ParseLelantusJoinSplit(tx); } - catch (CBadTxIn&) { + catch (...) { goto end; } @@ -2079,7 +2083,12 @@ void CWalletTx::GetAmounts(std::list& listReceived, nFee = nDebit - nValueOut; } else - nFee = lelantus::ParseLelantusJoinSplit(*tx)->getFee(); + try { + nFee = lelantus::ParseLelantusJoinSplit(*tx)->getFee(); + } + catch (...) { + // do nothing + } } // Sent/received. @@ -3690,7 +3699,11 @@ void CWallet::ListAvailableLelantusMintCoins(std::vector &vCoins, bool if (pcoin->tx->vout[i].scriptPubKey.IsLelantusMint() || pcoin->tx->vout[i].scriptPubKey.IsLelantusJMint()) { CTxOut txout = pcoin->tx->vout[i]; secp_primitives::GroupElement pubCoin; - lelantus::ParseLelantusMintScript(txout.scriptPubKey, pubCoin); + try { + lelantus::ParseLelantusMintScript(txout.scriptPubKey, pubCoin); + } catch (std::invalid_argument &) { + continue; + } LogPrintf("Pubcoin=%s\n", pubCoin.tostring()); // CHECKING PROCESS BOOST_FOREACH(const CLelantusEntry& ownCoinItem, listOwnCoins) {