From 52ae7dbb9014108e2241bf3b70f6bd2d13cd80bb Mon Sep 17 00:00:00 2001 From: instagibbs Date: Tue, 25 Oct 2016 14:27:04 -0400 Subject: [PATCH] Return useful error message on ATMP failure Zcash: Excludes changes to QT wallet, includes our own uses of CommitTransaction. (cherry picked from commit bitcoin/bitcoin@169bdabe14ef5988ff92a7370114edc85b070b27) --- src/wallet/asyncrpcoperation_common.h | 8 +++++--- src/wallet/rpcwallet.cpp | 15 +++++++++++---- src/wallet/wallet.cpp | 17 ++++++++++------- src/wallet/wallet.h | 4 ++-- 4 files changed, 28 insertions(+), 16 deletions(-) diff --git a/src/wallet/asyncrpcoperation_common.h b/src/wallet/asyncrpcoperation_common.h index 0e924e600..5b50e89e1 100644 --- a/src/wallet/asyncrpcoperation_common.h +++ b/src/wallet/asyncrpcoperation_common.h @@ -5,6 +5,7 @@ #ifndef ZCASH_WALLET_ASYNCRPCOPERATION_COMMON_H #define ZCASH_WALLET_ASYNCRPCOPERATION_COMMON_H +#include "consensus/validation.h" #include "core_io.h" #include "primitives/transaction.h" #include "rpc/protocol.h" @@ -38,9 +39,10 @@ UniValue SendTransaction( // More details in debug.log throw JSONRPCError(RPC_WALLET_ERROR, "SendTransaction: SaveRecipientMappings failed"); } - if (!pwalletMain->CommitTransaction(wtx, reservekey)) { - // More details in debug.log - throw JSONRPCError(RPC_WALLET_ERROR, "SendTransaction: CommitTransaction failed"); + CValidationState state; + if (!pwalletMain->CommitTransaction(wtx, reservekey, state)) { + std::string strError = strprintf("SendTransaction: Transaction commit failed:: %s", state.GetRejectReason()); + throw JSONRPCError(RPC_WALLET_ERROR, strError); } o.pushKV("txid", tx.GetHash().ToString()); } else { diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index bf1194561..05a0b753d 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -7,6 +7,7 @@ #include "amount.h" #include "consensus/upgrades.h" #include "consensus/params.h" +#include "consensus/validation.h" #include "core_io.h" #include "deprecation.h" #include "experimental_features.h" @@ -288,8 +289,11 @@ static void SendMoney(const CTxDestination &address, CAmount nValue, bool fSubtr strError = strprintf("Error: This transaction requires a transaction fee of at least %s because of its amount, complexity, or use of recently received funds!", FormatMoney(nFeeRequired)); throw JSONRPCError(RPC_WALLET_ERROR, strError); } - if (!pwalletMain->CommitTransaction(wtxNew, reservekey)) - throw JSONRPCError(RPC_WALLET_ERROR, "Error: The transaction was rejected! This might happen if some of the coins in your wallet were already spent, such as if you used a copy of the wallet and coins were spent in the copy but not marked as spent here."); + CValidationState state; + if (!pwalletMain->CommitTransaction(wtxNew, reservekey, state)) { + strError = strprintf("Error: The transaction was rejected! Reason given: %s", state.GetRejectReason()); + throw JSONRPCError(RPC_WALLET_ERROR, strError); + } } UniValue sendtoaddress(const UniValue& params, bool fHelp) @@ -1191,8 +1195,11 @@ UniValue sendmany(const UniValue& params, bool fHelp) bool fCreated = pwalletMain->CreateTransaction(vecSend, wtx, keyChange, nFeeRequired, nChangePosRet, strFailReason); if (!fCreated) throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, strFailReason); - if (!pwalletMain->CommitTransaction(wtx, keyChange)) - throw JSONRPCError(RPC_WALLET_ERROR, "Transaction commit failed"); + CValidationState state; + if (!pwalletMain->CommitTransaction(wtx, keyChange, state)) { + strFailReason = strprintf("Transaction commit failed:: %s", state.GetRejectReason()); + throw JSONRPCError(RPC_WALLET_ERROR, strFailReason); + } return wtx.GetHash().GetHex(); } diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 679cdd6b0..90355b0cc 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -1488,7 +1488,10 @@ void CWallet::RunSaplingMigration(int blockHeight) { for (const CTransaction& transaction : pendingSaplingMigrationTxs) { // Send the transaction CWalletTx wtx(this, transaction); - CommitTransaction(wtx, std::nullopt); + CValidationState state; + if (!CommitTransaction(wtx, std::nullopt, state)) { + LogPrintf("Error: The Sapling migration transaction was rejected! Reason given: %s", state.GetRejectReason()); + } } pendingSaplingMigrationTxs.clear(); } @@ -4524,7 +4527,8 @@ void CWallet::ReacceptWalletTransactions() // Try to add wallet transactions to memory pool for (std::pair& item : mapSorted) { CWalletTx& wtx = *(item.second); - wtx.AcceptToMemoryPool(false); + CValidationState state; + wtx.AcceptToMemoryPool(state, false); } } @@ -5586,7 +5590,7 @@ bool CWallet::CreateTransaction(const vector& vecSend, CWalletTx& wt /** * Call after CreateTransaction unless you want to abort */ -bool CWallet::CommitTransaction(CWalletTx& wtxNew, std::optional> reservekey) +bool CWallet::CommitTransaction(CWalletTx& wtxNew, std::optional> reservekey, CValidationState& state) { { LOCK2(cs_main, cs_wallet); @@ -5625,10 +5629,10 @@ bool CWallet::CommitTransaction(CWalletTx& wtxNew, std::optional 0; } int GetBlocksToMaturity() const; /** Pass this transaction to the mempool. Fails if absolute fee exceeds maxTxFee. */ - bool AcceptToMemoryPool(bool fLimitFree=true, bool fRejectAbsurdFee=true); + bool AcceptToMemoryPool(CValidationState& state, bool fLimitFree=true, bool fRejectAbsurdFee=true); }; enum class WalletUAGenerationError { @@ -1742,7 +1742,7 @@ public: return true; } - bool CommitTransaction(CWalletTx& wtxNew, std::optional> reservekey); + bool CommitTransaction(CWalletTx& wtxNew, std::optional> reservekey, CValidationState& state); static CFeeRate minTxFee; /**