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@169bdabe14)
This commit is contained in:
instagibbs 2016-10-25 14:27:04 -04:00 committed by Jack Grigg
parent 050133358b
commit 52ae7dbb90
4 changed files with 28 additions and 16 deletions

View File

@ -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 {

View File

@ -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();
}

View File

@ -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<const int64_t, CWalletTx*>& item : mapSorted) {
CWalletTx& wtx = *(item.second);
wtx.AcceptToMemoryPool(false);
CValidationState state;
wtx.AcceptToMemoryPool(state, false);
}
}
@ -5586,7 +5590,7 @@ bool CWallet::CreateTransaction(const vector<CRecipient>& vecSend, CWalletTx& wt
/**
* Call after CreateTransaction unless you want to abort
*/
bool CWallet::CommitTransaction(CWalletTx& wtxNew, std::optional<std::reference_wrapper<CReserveKey>> reservekey)
bool CWallet::CommitTransaction(CWalletTx& wtxNew, std::optional<std::reference_wrapper<CReserveKey>> reservekey, CValidationState& state)
{
{
LOCK2(cs_main, cs_wallet);
@ -5625,10 +5629,10 @@ bool CWallet::CommitTransaction(CWalletTx& wtxNew, std::optional<std::reference_
if (fBroadcastTransactions)
{
// Broadcast
if (!wtxNew.AcceptToMemoryPool(false))
if (!wtxNew.AcceptToMemoryPool(state, false))
{
// This must not fail. The transaction has already been signed and recorded.
LogPrintf("CommitTransaction(): Error: Transaction not valid\n");
LogPrintf("CommitTransaction(): Error: Transaction not valid, %s\n", state.GetRejectReason());
return false;
}
wtxNew.RelayWalletTransaction();
@ -6711,9 +6715,8 @@ int CMerkleTx::GetBlocksToMaturity() const
}
bool CMerkleTx::AcceptToMemoryPool(bool fLimitFree, bool fRejectAbsurdFee)
bool CMerkleTx::AcceptToMemoryPool(CValidationState& state, bool fLimitFree, bool fRejectAbsurdFee)
{
CValidationState state;
return ::AcceptToMemoryPool(Params(), mempool, state, *this, fLimitFree, NULL, fRejectAbsurdFee);
}

View File

@ -420,7 +420,7 @@ public:
bool IsInMainChain() const { const CBlockIndex *pindexRet; return GetDepthInMainChainINTERNAL(pindexRet) > 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<std::reference_wrapper<CReserveKey>> reservekey);
bool CommitTransaction(CWalletTx& wtxNew, std::optional<std::reference_wrapper<CReserveKey>> reservekey, CValidationState& state);
static CFeeRate minTxFee;
/**