Remove dummy confirmations in RPC API and GUI for InstantSend transactions (#2040)

* remove instandsenddepth option

* remove CInstantSend::GetConfirmations

* Explicit IXlocks processing in the code using GetDepthInMainChain

* remove dummy confirmations for IX locks

* remove unused constant

* Track IS status in TransactionStatus

* Highlight IS in tx list

* Customize confirmation icons for IS txes

* Fix issues:

- bring back removed comment;
- simplify 2 complex condition to ose `IsTrusted()` function only;
- rename `IsLockedIX` function to 'IsLockedByInstantSend`;

* Revert condition with IsTrusted()

* code style fix

* remove dummy confirmations from instantsend.md

* fix instantsend.md
This commit is contained in:
gladcow 2018-07-28 19:39:37 +03:00 committed by UdjinM6
parent a83ab55010
commit 0a6f47323b
13 changed files with 111 additions and 148 deletions

View File

@ -25,56 +25,4 @@ When a wallet InstantSend transaction is successfully locked a shell command pro
#### RPC #### RPC
Details pertaining to an observed "Transaction Lock" can also be retrieved through RPC, its important however to understand the underlying mechanism. Details pertaining to an observed "Transaction Lock" can also be retrieved through RPC. There is a boolean field named `instantlock` which indicates whether a given transaction is locked via InstantSend. This field is present in the output of some wallet RPC commands e.g. `listsinceblock`, `gettransaction` etc. as well as in the output of some mempool RPC commands e.g. `getmempoolentry` and a couple of others like `getrawmempool` (for `verbose=true` only).
By default, the Dash Core daemon will launch using the following constant:
```
static const int DEFAULT_INSTANTSEND_DEPTH = 5;
```
This value can be overridden by passing the following argument to the Dash Core daemon:
```
-instantsenddepth=<n>
```
The key thing to understand is that this value indicates the number of "confirmations" a successful Transaction Lock represents. When Wallet RPC commands which support `minconf` and `addlockconf` parameters (such as `listreceivedbyaddress`) are performed and `addlockconf` is `true`, then `instantsenddepth` attribute is taken into account when returning information about the transaction. In this case the value in `confirmations` field you see through RPC is showing the number of `"Blockchain Confirmations" + "InstantSend Depth"` (assuming the funds were sent via InstantSend).
There is also a field named `instantlock` (that is present in commands such as `listsinceblock`). The value in this field indicates whether a given transaction is locked via InstantSend.
**Examples**
1. `listreceivedbyaddress 0 true`
* InstantSend transaction just occurred:
* confirmations: 5
* InstantSend transaction received one confirmation from blockchain:
* confirmations: 6
* non-InstantSend transaction just occurred:
* confirmations: 0
* non-InstantSend transaction received one confirmation from blockchain:
* confirmations: 1
2. `listreceivedbyaddress 0`
* InstantSend transaction just occurred:
* confirmations: 0
* InstantSend transaction received one confirmation from blockchain:
* confirmations: 1
* non-InstantSend transaction just occurred:
* confirmations: 0
* non-InstantSend transaction received one confirmation from blockchain:
* confirmations: 1
3. `listsinceblock`
* InstantSend transaction just occurred:
* confirmations: 0
* instantlock: true
* InstantSend transaction received one confirmation from blockchain:
* confirmations: 1
* instantlock: true
* non-InstantSend transaction just occurred:
* confirmations: 0
* instantlock: false
* non-InstantSend transaction received one confirmation from blockchain:
* confirmations: 1
* instantlock: false

View File

@ -605,7 +605,7 @@ bool CGovernanceObject::IsCollateralValid(std::string& strError, bool& fMissingC
// GET CONFIRMATIONS FOR TRANSACTION // GET CONFIRMATIONS FOR TRANSACTION
AssertLockHeld(cs_main); AssertLockHeld(cs_main);
int nConfirmationsIn = instantsend.GetConfirmations(nCollateralHash); int nConfirmationsIn = 0;
if (nBlockHash != uint256()) { if (nBlockHash != uint256()) {
BlockMap::iterator mi = mapBlockIndex.find(nBlockHash); BlockMap::iterator mi = mapBlockIndex.find(nBlockHash);
if (mi != mapBlockIndex.end() && (*mi).second) { if (mi != mapBlockIndex.end() && (*mi).second) {
@ -616,7 +616,8 @@ bool CGovernanceObject::IsCollateralValid(std::string& strError, bool& fMissingC
} }
} }
if(nConfirmationsIn < GOVERNANCE_FEE_CONFIRMATIONS) { if((nConfirmationsIn < GOVERNANCE_FEE_CONFIRMATIONS) &&
(!instantsend.IsLockedInstantSendTransaction(nCollateralHash))){
strError = strprintf("Collateral requires at least %d confirmations to be relayed throughout the network (it has only %d)", GOVERNANCE_FEE_CONFIRMATIONS, nConfirmationsIn); strError = strprintf("Collateral requires at least %d confirmations to be relayed throughout the network (it has only %d)", GOVERNANCE_FEE_CONFIRMATIONS, nConfirmationsIn);
if (nConfirmationsIn >= GOVERNANCE_MIN_RELAY_FEE_CONFIRMATIONS) { if (nConfirmationsIn >= GOVERNANCE_MIN_RELAY_FEE_CONFIRMATIONS) {
fMissingConfirmations = true; fMissingConfirmations = true;

View File

@ -576,7 +576,6 @@ std::string HelpMessage(HelpMessageMode mode)
strUsage += HelpMessageGroup(_("InstantSend options:")); strUsage += HelpMessageGroup(_("InstantSend options:"));
strUsage += HelpMessageOpt("-enableinstantsend=<n>", strprintf(_("Enable InstantSend, show confirmations for locked transactions (0-1, default: %u)"), 1)); strUsage += HelpMessageOpt("-enableinstantsend=<n>", strprintf(_("Enable InstantSend, show confirmations for locked transactions (0-1, default: %u)"), 1));
strUsage += HelpMessageOpt("-instantsenddepth=<n>", strprintf(_("Show N confirmations for a successfully locked transaction (%u-%u, default: %u)"), MIN_INSTANTSEND_DEPTH, MAX_INSTANTSEND_DEPTH, DEFAULT_INSTANTSEND_DEPTH));
strUsage += HelpMessageOpt("-instantsendnotify=<cmd>", _("Execute command when a wallet InstantSend transaction is successfully locked (%s in cmd is replaced by TxID)")); strUsage += HelpMessageOpt("-instantsendnotify=<cmd>", _("Execute command when a wallet InstantSend transaction is successfully locked (%s in cmd is replaced by TxID)"));
@ -1873,11 +1872,8 @@ bool AppInitMain(boost::thread_group& threadGroup, CScheduler& scheduler)
#endif // ENABLE_WALLET #endif // ENABLE_WALLET
fEnableInstantSend = GetBoolArg("-enableinstantsend", 1); fEnableInstantSend = GetBoolArg("-enableinstantsend", 1);
nInstantSendDepth = GetArg("-instantsenddepth", DEFAULT_INSTANTSEND_DEPTH);
nInstantSendDepth = std::min(std::max(nInstantSendDepth, MIN_INSTANTSEND_DEPTH), MAX_INSTANTSEND_DEPTH);
LogPrintf("fLiteMode %d\n", fLiteMode); LogPrintf("fLiteMode %d\n", fLiteMode);
LogPrintf("nInstantSendDepth %d\n", nInstantSendDepth);
#ifdef ENABLE_WALLET #ifdef ENABLE_WALLET
LogPrintf("PrivateSend liquidityprovider: %d\n", privateSendClient.nLiquidityProvider); LogPrintf("PrivateSend liquidityprovider: %d\n", privateSendClient.nLiquidityProvider);
LogPrintf("PrivateSend rounds: %d\n", privateSendClient.nPrivateSendRounds); LogPrintf("PrivateSend rounds: %d\n", privateSendClient.nPrivateSendRounds);

View File

@ -33,7 +33,6 @@ extern CWallet* pwalletMain;
extern CTxMemPool mempool; extern CTxMemPool mempool;
bool fEnableInstantSend = true; bool fEnableInstantSend = true;
int nInstantSendDepth = DEFAULT_INSTANTSEND_DEPTH;
int nCompleteTXLocks; int nCompleteTXLocks;
CInstantSend instantsend; CInstantSend instantsend;
@ -838,11 +837,6 @@ int CInstantSend::GetTransactionLockSignatures(const uint256& txHash)
return -1; return -1;
} }
int CInstantSend::GetConfirmations(const uint256 &nTXHash)
{
return IsLockedInstantSendTransaction(nTXHash) ? nInstantSendDepth : 0;
}
bool CInstantSend::IsTxLockCandidateTimedOut(const uint256& txHash) bool CInstantSend::IsTxLockCandidateTimedOut(const uint256& txHash)
{ {
if(!fEnableInstantSend) return false; if(!fEnableInstantSend) return false;

View File

@ -26,14 +26,6 @@ extern CInstantSend instantsend;
(1000/2900.0)**5 = 0.004875397277841433 (1000/2900.0)**5 = 0.004875397277841433
*/ */
// The INSTANTSEND_DEPTH is the "pseudo block depth" level assigned to locked
// txs to indicate the degree of confidence in their eventual confirmation and
// inability to be double-spent (adjustable via command line argument)
static const int MIN_INSTANTSEND_DEPTH = 0;
static const int MAX_INSTANTSEND_DEPTH = 60;
/// Default number of "pseudo-confirmations" for an InstantSend tx
static const int DEFAULT_INSTANTSEND_DEPTH = 5;
static const int MIN_INSTANTSEND_PROTO_VERSION = 70208; static const int MIN_INSTANTSEND_PROTO_VERSION = 70208;
/// For how long we are going to accept votes/locks /// For how long we are going to accept votes/locks
@ -145,8 +137,6 @@ public:
bool IsLockedInstantSendTransaction(const uint256& txHash); bool IsLockedInstantSendTransaction(const uint256& txHash);
/// Get the actual number of accepted lock signatures /// Get the actual number of accepted lock signatures
int GetTransactionLockSignatures(const uint256& txHash); int GetTransactionLockSignatures(const uint256& txHash);
/// Get instantsend confirmations (only)
int GetConfirmations(const uint256 &nTXHash);
/// Remove expired entries from maps /// Remove expired entries from maps
void CheckAndRemove(); void CheckAndRemove();

View File

@ -34,6 +34,8 @@ static const bool DEFAULT_SPLASHSCREEN = true;
#define COLOR_TX_STATUS_DANGER QColor(200, 100, 100) #define COLOR_TX_STATUS_DANGER QColor(200, 100, 100)
/* Transaction list -- TX status decoration - default color */ /* Transaction list -- TX status decoration - default color */
#define COLOR_BLACK QColor(0, 0, 0) #define COLOR_BLACK QColor(0, 0, 0)
/* Transaction list -- TX status decoration - LockedByInstantSend color */
#define COLOR_TX_STATUS_LOCKED QColor(0, 128, 255)
/* Tooltips longer than this (in characters) are converted into rich text, /* Tooltips longer than this (in characters) are converted into rich text,
so that they can be word-wrapped. so that they can be word-wrapped.

View File

@ -291,6 +291,7 @@ void TransactionRecord::updateStatus(const CWalletTx &wtx)
} }
else else
{ {
status.lockedByInstantSend = wtx.IsLockedByInstantSend();
if (status.depth < 0) if (status.depth < 0)
{ {
status.status = TransactionStatus::Conflicted; status.status = TransactionStatus::Conflicted;

View File

@ -42,6 +42,8 @@ public:
/// Transaction counts towards available balance /// Transaction counts towards available balance
bool countsForBalance; bool countsForBalance;
/// Transaction was locked via InstantSend
bool lockedByInstantSend;
/// Sorting key based on status /// Sorting key based on status
std::string sortKey; std::string sortKey;

View File

@ -484,6 +484,24 @@ QString TransactionTableModel::formatTxAmount(const TransactionRecord *wtx, bool
return QString(str); return QString(str);
} }
QIcon IconWithShiftedColor(const QString& filename, bool shift)
{
if (!shift)
return QIcon(filename);
QImage img(filename);
img = img.convertToFormat(QImage::Format_ARGB32);
for (int x = img.width(); x--; )
{
for (int y = img.height(); y--; )
{
const QRgb rgb = img.pixel(x, y);
img.setPixel(x, y, qRgba(qRed(rgb), qGreen(rgb), qBlue(rgb)+128, qAlpha(rgb)));
}
}
return QIcon(QPixmap::fromImage(img));
}
QVariant TransactionTableModel::txStatusDecoration(const TransactionRecord *wtx) const QVariant TransactionTableModel::txStatusDecoration(const TransactionRecord *wtx) const
{ {
QString theme = GUIUtil::getThemeName(); QString theme = GUIUtil::getThemeName();
@ -495,17 +513,19 @@ QVariant TransactionTableModel::txStatusDecoration(const TransactionRecord *wtx)
case TransactionStatus::Offline: case TransactionStatus::Offline:
return COLOR_TX_STATUS_OFFLINE; return COLOR_TX_STATUS_OFFLINE;
case TransactionStatus::Unconfirmed: case TransactionStatus::Unconfirmed:
// TODO: use special icon for InstantSend 0-conf
return QIcon(":/icons/" + theme + "/transaction_0"); return QIcon(":/icons/" + theme + "/transaction_0");
case TransactionStatus::Abandoned: case TransactionStatus::Abandoned:
return QIcon(":/icons/" + theme + "/transaction_abandoned"); return QIcon(":/icons/" + theme + "/transaction_abandoned");
case TransactionStatus::Confirming: case TransactionStatus::Confirming:
switch(wtx->status.depth) switch(wtx->status.depth)
{ {
case 1: return QIcon(":/icons/" + theme + "/transaction_1"); // TODO: use special icons for InstantSend instead of color shifting
case 2: return QIcon(":/icons/" + theme + "/transaction_2"); case 1: return IconWithShiftedColor(":/icons/" + theme + "/transaction_1", wtx->status.lockedByInstantSend);
case 3: return QIcon(":/icons/" + theme + "/transaction_3"); case 2: return IconWithShiftedColor(":/icons/" + theme + "/transaction_2", wtx->status.lockedByInstantSend);
case 4: return QIcon(":/icons/" + theme + "/transaction_4"); case 3: return IconWithShiftedColor(":/icons/" + theme + "/transaction_3", wtx->status.lockedByInstantSend);
default: return QIcon(":/icons/" + theme + "/transaction_5"); case 4: return IconWithShiftedColor(":/icons/" + theme + "/transaction_4", wtx->status.lockedByInstantSend);
default: return IconWithShiftedColor(":/icons/" + theme + "/transaction_5", wtx->status.lockedByInstantSend);
}; };
case TransactionStatus::Confirmed: case TransactionStatus::Confirmed:
return QIcon(":/icons/" + theme + "/transaction_confirmed"); return QIcon(":/icons/" + theme + "/transaction_confirmed");
@ -608,6 +628,10 @@ QVariant TransactionTableModel::data(const QModelIndex &index, int role) const
{ {
return COLOR_TX_STATUS_DANGER; return COLOR_TX_STATUS_DANGER;
} }
if(rec->status.lockedByInstantSend)
{
return COLOR_TX_STATUS_LOCKED;
}
// Non-confirmed (but not immature) as transactions are grey // Non-confirmed (but not immature) as transactions are grey
if(!rec->status.countsForBalance && rec->status.status != TransactionStatus::Immature) if(!rec->status.countsForBalance && rec->status.status != TransactionStatus::Immature)
{ {

View File

@ -754,7 +754,7 @@ bool WalletModel::transactionCanBeAbandoned(uint256 hash) const
{ {
LOCK2(cs_main, wallet->cs_wallet); LOCK2(cs_main, wallet->cs_wallet);
const CWalletTx *wtx = wallet->GetWalletTx(hash); const CWalletTx *wtx = wallet->GetWalletTx(hash);
if (!wtx || wtx->isAbandoned() || wtx->GetDepthInMainChain() > 0 || wtx->InMempool()) if (!wtx || wtx->isAbandoned() || wtx->GetDepthInMainChain() > 0 || wtx->IsLockedByInstantSend() || wtx->InMempool())
return false; return false;
return true; return true;
} }

View File

@ -58,7 +58,7 @@ void EnsureWalletIsUnlocked()
void WalletTxToJSON(const CWalletTx& wtx, UniValue& entry) void WalletTxToJSON(const CWalletTx& wtx, UniValue& entry)
{ {
int confirms = wtx.GetDepthInMainChain(false); int confirms = wtx.GetDepthInMainChain();
bool fLocked = instantsend.IsLockedInstantSendTransaction(wtx.GetHash()); bool fLocked = instantsend.IsLockedInstantSendTransaction(wtx.GetHash());
entry.push_back(Pair("confirmations", confirms)); entry.push_back(Pair("confirmations", confirms));
entry.push_back(Pair("instantlock", fLocked)); entry.push_back(Pair("instantlock", fLocked));
@ -657,12 +657,12 @@ UniValue getreceivedbyaddress(const JSONRPCRequest& request)
if (request.fHelp || request.params.size() < 1 || request.params.size() > 3) if (request.fHelp || request.params.size() < 1 || request.params.size() > 3)
throw std::runtime_error( throw std::runtime_error(
"getreceivedbyaddress \"address\" ( minconf addlockconf )\n" "getreceivedbyaddress \"address\" ( minconf addlocked )\n"
"\nReturns the total amount received by the given address in transactions with at least minconf confirmations.\n" "\nReturns the total amount received by the given address in transactions with at least minconf confirmations.\n"
"\nArguments:\n" "\nArguments:\n"
"1. \"address\" (string, required) The dash address for transactions.\n" "1. \"address\" (string, required) The dash address for transactions.\n"
"2. minconf (numeric, optional, default=1) Only include transactions confirmed at least this many times.\n" "2. minconf (numeric, optional, default=1) Only include transactions confirmed at least this many times.\n"
"3. addlockconf (bool, optional, default=false) Whether to add " + std::to_string(nInstantSendDepth) + " confirmations to transactions locked via InstantSend.\n" "3. addlocked (bool, optional, default=false) Whether to include transactions locked via InstantSend.\n"
"\nResult:\n" "\nResult:\n"
"amount (numeric) The total amount in " + CURRENCY_UNIT + " received at this address.\n" "amount (numeric) The total amount in " + CURRENCY_UNIT + " received at this address.\n"
"\nExamples:\n" "\nExamples:\n"
@ -690,7 +690,7 @@ UniValue getreceivedbyaddress(const JSONRPCRequest& request)
int nMinDepth = 1; int nMinDepth = 1;
if (request.params.size() > 1) if (request.params.size() > 1)
nMinDepth = request.params[1].get_int(); nMinDepth = request.params[1].get_int();
bool fAddLockConf = (request.params.size() > 2 && request.params[2].get_bool()); bool fAddLocked = (request.params.size() > 2 && request.params[2].get_bool());
// Tally // Tally
CAmount nAmount = 0; CAmount nAmount = 0;
@ -702,7 +702,7 @@ UniValue getreceivedbyaddress(const JSONRPCRequest& request)
BOOST_FOREACH(const CTxOut& txout, wtx.tx->vout) BOOST_FOREACH(const CTxOut& txout, wtx.tx->vout)
if (txout.scriptPubKey == scriptPubKey) if (txout.scriptPubKey == scriptPubKey)
if (wtx.GetDepthInMainChain(fAddLockConf) >= nMinDepth) if ((wtx.GetDepthInMainChain() >= nMinDepth) || (fAddLocked && wtx.IsLockedByInstantSend()))
nAmount += txout.nValue; nAmount += txout.nValue;
} }
@ -717,12 +717,12 @@ UniValue getreceivedbyaccount(const JSONRPCRequest& request)
if (request.fHelp || request.params.size() < 1 || request.params.size() > 3) if (request.fHelp || request.params.size() < 1 || request.params.size() > 3)
throw std::runtime_error( throw std::runtime_error(
"getreceivedbyaccount \"account\" ( minconf addlockconf )\n" "getreceivedbyaccount \"account\" ( minconf addlocked )\n"
"\nDEPRECATED. Returns the total amount received by addresses with <account> in transactions with specified minimum number of confirmations.\n" "\nDEPRECATED. Returns the total amount received by addresses with <account> in transactions with specified minimum number of confirmations.\n"
"\nArguments:\n" "\nArguments:\n"
"1. \"account\" (string, required) The selected account, may be the default account using \"\".\n" "1. \"account\" (string, required) The selected account, may be the default account using \"\".\n"
"2. minconf (numeric, optional, default=1) Only include transactions confirmed at least this many times.\n" "2. minconf (numeric, optional, default=1) Only include transactions confirmed at least this many times.\n"
"3. addlockconf (bool, optional, default=false) Whether to add " + std::to_string(nInstantSendDepth) + " confirmations to transactions locked via InstantSend.\n" "3. addlocked (bool, optional, default=false) Whether to include transactions locked via InstantSend.\n"
"\nResult:\n" "\nResult:\n"
"amount (numeric) The total amount in " + CURRENCY_UNIT + " received for this account.\n" "amount (numeric) The total amount in " + CURRENCY_UNIT + " received for this account.\n"
"\nExamples:\n" "\nExamples:\n"
@ -742,7 +742,7 @@ UniValue getreceivedbyaccount(const JSONRPCRequest& request)
int nMinDepth = 1; int nMinDepth = 1;
if (request.params.size() > 1) if (request.params.size() > 1)
nMinDepth = request.params[1].get_int(); nMinDepth = request.params[1].get_int();
bool fAddLockConf = (request.params.size() > 2 && request.params[2].get_bool()); bool fAddLocked = (request.params.size() > 2 && request.params[2].get_bool());
// Get the set of pub keys assigned to account // Get the set of pub keys assigned to account
std::string strAccount = AccountFromValue(request.params[0]); std::string strAccount = AccountFromValue(request.params[0]);
@ -760,7 +760,7 @@ UniValue getreceivedbyaccount(const JSONRPCRequest& request)
{ {
CTxDestination address; CTxDestination address;
if (ExtractDestination(txout.scriptPubKey, address) && IsMine(*pwalletMain, address) && setAddress.count(address)) if (ExtractDestination(txout.scriptPubKey, address) && IsMine(*pwalletMain, address) && setAddress.count(address))
if (wtx.GetDepthInMainChain(fAddLockConf) >= nMinDepth) if ((wtx.GetDepthInMainChain() >= nMinDepth) || (fAddLocked && wtx.IsLockedByInstantSend()))
nAmount += txout.nValue; nAmount += txout.nValue;
} }
} }
@ -776,7 +776,7 @@ UniValue getbalance(const JSONRPCRequest& request)
if (request.fHelp || request.params.size() > 4) if (request.fHelp || request.params.size() > 4)
throw std::runtime_error( throw std::runtime_error(
"getbalance ( \"account\" minconf addlockconf include_watchonly )\n" "getbalance ( \"account\" minconf addlocked include_watchonly )\n"
"\nIf account is not specified, returns the server's total available balance.\n" "\nIf account is not specified, returns the server's total available balance.\n"
"If account is specified (DEPRECATED), returns the balance in the account.\n" "If account is specified (DEPRECATED), returns the balance in the account.\n"
"Note that the account \"\" is not the same as leaving the parameter out.\n" "Note that the account \"\" is not the same as leaving the parameter out.\n"
@ -784,7 +784,7 @@ UniValue getbalance(const JSONRPCRequest& request)
"\nArguments:\n" "\nArguments:\n"
"1. \"account\" (string, optional) DEPRECATED. The selected account, or \"*\" for entire wallet. It may be the default account using \"\".\n" "1. \"account\" (string, optional) DEPRECATED. The selected account, or \"*\" for entire wallet. It may be the default account using \"\".\n"
"2. minconf (numeric, optional, default=1) Only include transactions confirmed at least this many times.\n" "2. minconf (numeric, optional, default=1) Only include transactions confirmed at least this many times.\n"
"3. addlockconf (bool, optional, default=false) Whether to add " + std::to_string(nInstantSendDepth) + " confirmations to transactions locked via InstantSend.\n" "3. addlocked (bool, optional, default=false) Whether to add balance from transactions locked via InstantSend.\n"
"4. include_watchonly (bool, optional, default=false) Also include balance in watch-only addresses (see 'importaddress')\n" "4. include_watchonly (bool, optional, default=false) Also include balance in watch-only addresses (see 'importaddress')\n"
"\nResult:\n" "\nResult:\n"
"amount (numeric) The total amount in " + CURRENCY_UNIT + " received for this account.\n" "amount (numeric) The total amount in " + CURRENCY_UNIT + " received for this account.\n"
@ -805,7 +805,7 @@ UniValue getbalance(const JSONRPCRequest& request)
int nMinDepth = 1; int nMinDepth = 1;
if (request.params.size() > 1) if (request.params.size() > 1)
nMinDepth = request.params[1].get_int(); nMinDepth = request.params[1].get_int();
bool fAddLockConf = (request.params.size() > 2 && request.params[2].get_bool()); bool fAddLocked = (request.params.size() > 2 && request.params[2].get_bool());
isminefilter filter = ISMINE_SPENDABLE; isminefilter filter = ISMINE_SPENDABLE;
if(request.params.size() > 3) if(request.params.size() > 3)
if(request.params[3].get_bool()) if(request.params[3].get_bool())
@ -827,7 +827,7 @@ UniValue getbalance(const JSONRPCRequest& request)
std::list<COutputEntry> listReceived; std::list<COutputEntry> listReceived;
std::list<COutputEntry> listSent; std::list<COutputEntry> listSent;
wtx.GetAmounts(listReceived, listSent, allFee, strSentAccount, filter); wtx.GetAmounts(listReceived, listSent, allFee, strSentAccount, filter);
if (wtx.GetDepthInMainChain(fAddLockConf) >= nMinDepth) if ((wtx.GetDepthInMainChain() >= nMinDepth) || (fAddLocked && wtx.IsLockedByInstantSend()))
{ {
BOOST_FOREACH(const COutputEntry& r, listReceived) BOOST_FOREACH(const COutputEntry& r, listReceived)
nBalance += r.amount; nBalance += r.amount;
@ -841,7 +841,7 @@ UniValue getbalance(const JSONRPCRequest& request)
std::string strAccount = AccountFromValue(request.params[0]); std::string strAccount = AccountFromValue(request.params[0]);
CAmount nBalance = pwalletMain->GetAccountBalance(strAccount, nMinDepth, filter, fAddLockConf); CAmount nBalance = pwalletMain->GetAccountBalance(strAccount, nMinDepth, filter, fAddLocked);
return ValueFromAmount(nBalance); return ValueFromAmount(nBalance);
} }
@ -916,7 +916,7 @@ UniValue sendfrom(const JSONRPCRequest& request)
if (request.fHelp || request.params.size() < 3 || request.params.size() > 7) if (request.fHelp || request.params.size() < 3 || request.params.size() > 7)
throw std::runtime_error( throw std::runtime_error(
"sendfrom \"fromaccount\" \"toaddress\" amount ( minconf addlockconf \"comment\" \"comment_to\" )\n" "sendfrom \"fromaccount\" \"toaddress\" amount ( minconf addlocked \"comment\" \"comment_to\" )\n"
"\nDEPRECATED (use sendtoaddress). Sent an amount from an account to a dash address." "\nDEPRECATED (use sendtoaddress). Sent an amount from an account to a dash address."
+ HelpRequiringPassphrase() + "\n" + HelpRequiringPassphrase() + "\n"
"\nArguments:\n" "\nArguments:\n"
@ -927,7 +927,7 @@ UniValue sendfrom(const JSONRPCRequest& request)
"2. \"toaddress\" (string, required) The dash address to send funds to.\n" "2. \"toaddress\" (string, required) The dash address to send funds to.\n"
"3. amount (numeric or string, required) The amount in " + CURRENCY_UNIT + " (transaction fee is added on top).\n" "3. amount (numeric or string, required) The amount in " + CURRENCY_UNIT + " (transaction fee is added on top).\n"
"4. minconf (numeric, optional, default=1) Only use funds with at least this many confirmations.\n" "4. minconf (numeric, optional, default=1) Only use funds with at least this many confirmations.\n"
"5. addlockconf (bool, optional, default=false) Whether to add " + std::to_string(nInstantSendDepth) + " confirmations to transactions locked via InstantSend.\n" "5. addlocked (bool, optional, default=false) Whether to include transactions locked via InstantSend.\n"
"6. \"comment\" (string, optional) A comment used to store what the transaction is for. \n" "6. \"comment\" (string, optional) A comment used to store what the transaction is for. \n"
" This is not part of the transaction, just kept in your wallet.\n" " This is not part of the transaction, just kept in your wallet.\n"
"7. \"comment_to\" (string, optional) An optional comment to store the name of the person or organization \n" "7. \"comment_to\" (string, optional) An optional comment to store the name of the person or organization \n"
@ -956,7 +956,7 @@ UniValue sendfrom(const JSONRPCRequest& request)
int nMinDepth = 1; int nMinDepth = 1;
if (request.params.size() > 3) if (request.params.size() > 3)
nMinDepth = request.params[3].get_int(); nMinDepth = request.params[3].get_int();
bool fAddLockConf = (request.params.size() > 4 && request.params[4].get_bool()); bool fAddLocked = (request.params.size() > 4 && request.params[4].get_bool());
CWalletTx wtx; CWalletTx wtx;
wtx.strFromAccount = strAccount; wtx.strFromAccount = strAccount;
@ -968,7 +968,7 @@ UniValue sendfrom(const JSONRPCRequest& request)
EnsureWalletIsUnlocked(); EnsureWalletIsUnlocked();
// Check funds // Check funds
CAmount nBalance = pwalletMain->GetAccountBalance(strAccount, nMinDepth, ISMINE_SPENDABLE, fAddLockConf); CAmount nBalance = pwalletMain->GetAccountBalance(strAccount, nMinDepth, ISMINE_SPENDABLE, fAddLocked);
if (nAmount > nBalance) if (nAmount > nBalance)
throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, "Account has insufficient funds"); throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, "Account has insufficient funds");
@ -985,7 +985,7 @@ UniValue sendmany(const JSONRPCRequest& request)
if (request.fHelp || request.params.size() < 2 || request.params.size() > 8) if (request.fHelp || request.params.size() < 2 || request.params.size() > 8)
throw std::runtime_error( throw std::runtime_error(
"sendmany \"fromaccount\" {\"address\":amount,...} ( minconf addlockconf \"comment\" [\"address\",...] subtractfeefromamount use_is use_ps )\n" "sendmany \"fromaccount\" {\"address\":amount,...} ( minconf addlocked \"comment\" [\"address\",...] subtractfeefromamount use_is use_ps )\n"
"\nSend multiple times. Amounts are double-precision floating point numbers." "\nSend multiple times. Amounts are double-precision floating point numbers."
+ HelpRequiringPassphrase() + "\n" + HelpRequiringPassphrase() + "\n"
"\nArguments:\n" "\nArguments:\n"
@ -996,7 +996,7 @@ UniValue sendmany(const JSONRPCRequest& request)
" ,...\n" " ,...\n"
" }\n" " }\n"
"3. minconf (numeric, optional, default=1) Only use the balance confirmed at least this many times.\n" "3. minconf (numeric, optional, default=1) Only use the balance confirmed at least this many times.\n"
"4. addlockconf (bool, optional, default=false) Whether to add " + std::to_string(nInstantSendDepth) + " confirmations to transactions locked via InstantSend.\n" "4. addlocked (bool, optional, default=false) Whether to include transactions locked via InstantSend.\n"
"5. \"comment\" (string, optional) A comment\n" "5. \"comment\" (string, optional) A comment\n"
"6. subtractfeefromamount (array, optional) A json array with addresses.\n" "6. subtractfeefromamount (array, optional) A json array with addresses.\n"
" The fee will be equally deducted from the amount of each selected address.\n" " The fee will be equally deducted from the amount of each selected address.\n"
@ -1030,7 +1030,7 @@ UniValue sendmany(const JSONRPCRequest& request)
int nMinDepth = 1; int nMinDepth = 1;
if (request.params.size() > 2) if (request.params.size() > 2)
nMinDepth = request.params[2].get_int(); nMinDepth = request.params[2].get_int();
bool fAddLockConf = (request.params.size() > 3 && request.params[3].get_bool()); bool fAddLocked = (request.params.size() > 3 && request.params[3].get_bool());
CWalletTx wtx; CWalletTx wtx;
wtx.strFromAccount = strAccount; wtx.strFromAccount = strAccount;
@ -1076,7 +1076,7 @@ UniValue sendmany(const JSONRPCRequest& request)
EnsureWalletIsUnlocked(); EnsureWalletIsUnlocked();
// Check funds // Check funds
CAmount nBalance = pwalletMain->GetAccountBalance(strAccount, nMinDepth, ISMINE_SPENDABLE, fAddLockConf); CAmount nBalance = pwalletMain->GetAccountBalance(strAccount, nMinDepth, ISMINE_SPENDABLE, fAddLocked);
if (totalAmount > nBalance) if (totalAmount > nBalance)
throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, "Account has insufficient funds"); throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, "Account has insufficient funds");
@ -1177,7 +1177,7 @@ UniValue ListReceived(const UniValue& params, bool fByAccounts)
int nMinDepth = 1; int nMinDepth = 1;
if (params.size() > 0) if (params.size() > 0)
nMinDepth = params[0].get_int(); nMinDepth = params[0].get_int();
bool fAddLockConf = (params.size() > 1 && params[1].get_bool()); bool fAddLocked = (params.size() > 1 && params[1].get_bool());
// Whether to include empty accounts // Whether to include empty accounts
bool fIncludeEmpty = false; bool fIncludeEmpty = false;
@ -1198,8 +1198,8 @@ UniValue ListReceived(const UniValue& params, bool fByAccounts)
if (wtx.IsCoinBase() || !CheckFinalTx(*wtx.tx)) if (wtx.IsCoinBase() || !CheckFinalTx(*wtx.tx))
continue; continue;
int nDepth = wtx.GetDepthInMainChain(fAddLockConf); int nDepth = wtx.GetDepthInMainChain();
if (nDepth < nMinDepth) if ((nDepth < nMinDepth) && !(fAddLocked && wtx.IsLockedByInstantSend()))
continue; continue;
BOOST_FOREACH(const CTxOut& txout, wtx.tx->vout) BOOST_FOREACH(const CTxOut& txout, wtx.tx->vout)
@ -1303,11 +1303,11 @@ UniValue listreceivedbyaddress(const JSONRPCRequest& request)
if (request.fHelp || request.params.size() > 4) if (request.fHelp || request.params.size() > 4)
throw std::runtime_error( throw std::runtime_error(
"listreceivedbyaddress ( minconf addlockconf include_empty include_watchonly)\n" "listreceivedbyaddress ( minconf addlocked include_empty include_watchonly)\n"
"\nList incoming payments grouped by receiving address.\n" "\nList incoming payments grouped by receiving address.\n"
"\nArguments:\n" "\nArguments:\n"
"1. minconf (numeric, optional, default=1) The minimum number of confirmations before payments are included.\n" "1. minconf (numeric, optional, default=1) The minimum number of confirmations before payments are included.\n"
"2. addlockconf (bool, optional, default=false) Whether to add " + std::to_string(nInstantSendDepth) + " confirmations to transactions locked via InstantSend.\n" "2. addlocked (bool, optional, default=false) Whether to include transactions locked via InstantSend.\n"
"3. include_empty (bool, optional, default=false) Whether to include addresses that haven't received any payments.\n" "3. include_empty (bool, optional, default=false) Whether to include addresses that haven't received any payments.\n"
"4. include_watchonly (bool, optional, default=false) Whether to include watch-only addresses (see 'importaddress').\n" "4. include_watchonly (bool, optional, default=false) Whether to include watch-only addresses (see 'importaddress').\n"
@ -1319,8 +1319,8 @@ UniValue listreceivedbyaddress(const JSONRPCRequest& request)
" \"account\" : \"accountname\", (string) DEPRECATED. The account of the receiving address. The default account is \"\".\n" " \"account\" : \"accountname\", (string) DEPRECATED. The account of the receiving address. The default account is \"\".\n"
" \"amount\" : x.xxx, (numeric) The total amount in " + CURRENCY_UNIT + " received by the address\n" " \"amount\" : x.xxx, (numeric) The total amount in " + CURRENCY_UNIT + " received by the address\n"
" \"confirmations\" : n (numeric) The number of confirmations of the most recent transaction included.\n" " \"confirmations\" : n (numeric) The number of confirmations of the most recent transaction included.\n"
" If 'addlockconf' is true, the minimum number of confirmations is calculated\n" " If 'addlocked' is true, the number of confirmations can be less than\n"
" including additional " + std::to_string(nInstantSendDepth) + " confirmations for transactions locked via InstantSend\n" " configured for transactions locked via InstantSend\n"
" \"label\" : \"label\", (string) A comment for the address/transaction, if any\n" " \"label\" : \"label\", (string) A comment for the address/transaction, if any\n"
" \"txids\": [\n" " \"txids\": [\n"
" n, (numeric) The ids of transactions received with the address \n" " n, (numeric) The ids of transactions received with the address \n"
@ -1348,11 +1348,11 @@ UniValue listreceivedbyaccount(const JSONRPCRequest& request)
if (request.fHelp || request.params.size() > 4) if (request.fHelp || request.params.size() > 4)
throw std::runtime_error( throw std::runtime_error(
"listreceivedbyaccount ( minconf addlockconf include_empty include_watchonly)\n" "listreceivedbyaccount ( minconf addlocked include_empty include_watchonly)\n"
"\nDEPRECATED. List incoming payments grouped by account.\n" "\nDEPRECATED. List incoming payments grouped by account.\n"
"\nArguments:\n" "\nArguments:\n"
"1. minconf (numeric, optional, default=1) The minimum number of confirmations before payments are included.\n" "1. minconf (numeric, optional, default=1) The minimum number of confirmations before payments are included.\n"
"2. addlockconf (bool, optional, default=false) Whether to add " + std::to_string(nInstantSendDepth) + " confirmations to transactions locked via InstantSend.\n" "2. addlocked (bool, optional, default=false) Whether to include transactions locked via InstantSend.\n"
"3. include_empty (bool, optional, default=false) Whether to include accounts that haven't received any payments.\n" "3. include_empty (bool, optional, default=false) Whether to include accounts that haven't received any payments.\n"
"4. include_watchonly (bool, optional, default=false) Whether to include watch-only addresses (see 'importaddress').\n" "4. include_watchonly (bool, optional, default=false) Whether to include watch-only addresses (see 'importaddress').\n"
@ -1423,7 +1423,7 @@ void ListTransactions(const CWalletTx& wtx, const std::string& strAccount, int n
} }
// Received // Received
if (listReceived.size() > 0 && wtx.GetDepthInMainChain() >= nMinDepth) if (listReceived.size() > 0 && ((wtx.GetDepthInMainChain() >= nMinDepth) || wtx.IsLockedByInstantSend()))
{ {
BOOST_FOREACH(const COutputEntry& r, listReceived) BOOST_FOREACH(const COutputEntry& r, listReceived)
{ {
@ -1615,11 +1615,11 @@ UniValue listaccounts(const JSONRPCRequest& request)
if (request.fHelp || request.params.size() > 3) if (request.fHelp || request.params.size() > 3)
throw std::runtime_error( throw std::runtime_error(
"listaccounts ( minconf addlockconf include_watchonly)\n" "listaccounts ( minconf addlocked include_watchonly)\n"
"\nDEPRECATED. Returns Object that has account names as keys, account balances as values.\n" "\nDEPRECATED. Returns Object that has account names as keys, account balances as values.\n"
"\nArguments:\n" "\nArguments:\n"
"1. minconf (numeric, optional, default=1) Only include transactions with at least this many confirmations\n" "1. minconf (numeric, optional, default=1) Only include transactions with at least this many confirmations\n"
"2. addlockconf (bool, optional, default=false) Whether to add " + std::to_string(nInstantSendDepth) + " confirmations to transactions locked via InstantSend.\n" "2. addlocked (bool, optional, default=false) Whether to include transactions locked via InstantSend.\n"
"3. include_watchonly (bool, optional, default=false) Include balances in watch-only addresses (see 'importaddress')\n" "3. include_watchonly (bool, optional, default=false) Include balances in watch-only addresses (see 'importaddress')\n"
"\nResult:\n" "\nResult:\n"
"{ (json object where keys are account names, and values are numeric balances\n" "{ (json object where keys are account names, and values are numeric balances\n"
@ -1642,7 +1642,7 @@ UniValue listaccounts(const JSONRPCRequest& request)
int nMinDepth = 1; int nMinDepth = 1;
if (request.params.size() > 0) if (request.params.size() > 0)
nMinDepth = request.params[0].get_int(); nMinDepth = request.params[0].get_int();
bool fAddLockConf = (request.params.size() > 1 && request.params[1].get_bool()); bool fAddLocked = (request.params.size() > 1 && request.params[1].get_bool());
isminefilter includeWatchonly = ISMINE_SPENDABLE; isminefilter includeWatchonly = ISMINE_SPENDABLE;
if(request.params.size() > 2) if(request.params.size() > 2)
if(request.params[2].get_bool()) if(request.params[2].get_bool())
@ -1661,14 +1661,14 @@ UniValue listaccounts(const JSONRPCRequest& request)
std::string strSentAccount; std::string strSentAccount;
std::list<COutputEntry> listReceived; std::list<COutputEntry> listReceived;
std::list<COutputEntry> listSent; std::list<COutputEntry> listSent;
int nDepth = wtx.GetDepthInMainChain(fAddLockConf); int nDepth = wtx.GetDepthInMainChain();
if (wtx.GetBlocksToMaturity() > 0 || nDepth < 0) if (wtx.GetBlocksToMaturity() > 0 || nDepth < 0)
continue; continue;
wtx.GetAmounts(listReceived, listSent, nFee, strSentAccount, includeWatchonly); wtx.GetAmounts(listReceived, listSent, nFee, strSentAccount, includeWatchonly);
mapAccountBalances[strSentAccount] -= nFee; mapAccountBalances[strSentAccount] -= nFee;
BOOST_FOREACH(const COutputEntry& s, listSent) BOOST_FOREACH(const COutputEntry& s, listSent)
mapAccountBalances[strSentAccount] -= s.amount; mapAccountBalances[strSentAccount] -= s.amount;
if (nDepth >= nMinDepth) if ((nDepth >= nMinDepth) || (fAddLocked && wtx.IsLockedByInstantSend()))
{ {
BOOST_FOREACH(const COutputEntry& r, listReceived) BOOST_FOREACH(const COutputEntry& r, listReceived)
if (pwalletMain->mapAddressBook.count(r.destination)) if (pwalletMain->mapAddressBook.count(r.destination))
@ -1784,7 +1784,7 @@ UniValue listsinceblock(const JSONRPCRequest& request)
{ {
CWalletTx tx = (*it).second; CWalletTx tx = (*it).second;
if (depth == -1 || tx.GetDepthInMainChain(false) < depth) if (depth == -1 || tx.GetDepthInMainChain() < depth)
ListTransactions(tx, "*", 0, true, transactions, filter); ListTransactions(tx, "*", 0, true, transactions, filter);
} }
@ -2856,11 +2856,11 @@ static const CRPCCommand commands[] =
{ "wallet", "getaccountaddress", &getaccountaddress, true, {"account"} }, { "wallet", "getaccountaddress", &getaccountaddress, true, {"account"} },
{ "wallet", "getaccount", &getaccount, true, {"address"} }, { "wallet", "getaccount", &getaccount, true, {"address"} },
{ "wallet", "getaddressesbyaccount", &getaddressesbyaccount, true, {"account"} }, { "wallet", "getaddressesbyaccount", &getaddressesbyaccount, true, {"account"} },
{ "wallet", "getbalance", &getbalance, false, {"account","minconf","addlockconf","include_watchonly"} }, { "wallet", "getbalance", &getbalance, false, {"account","minconf","addlocked","include_watchonly"} },
{ "wallet", "getnewaddress", &getnewaddress, true, {"account"} }, { "wallet", "getnewaddress", &getnewaddress, true, {"account"} },
{ "wallet", "getrawchangeaddress", &getrawchangeaddress, true, {} }, { "wallet", "getrawchangeaddress", &getrawchangeaddress, true, {} },
{ "wallet", "getreceivedbyaccount", &getreceivedbyaccount, false, {"account","minconf","addlockconf"} }, { "wallet", "getreceivedbyaccount", &getreceivedbyaccount, false, {"account","minconf","addlocked"} },
{ "wallet", "getreceivedbyaddress", &getreceivedbyaddress, false, {"address","minconf","addlockconf"} }, { "wallet", "getreceivedbyaddress", &getreceivedbyaddress, false, {"address","minconf","addlocked"} },
{ "wallet", "gettransaction", &gettransaction, false, {"txid","include_watchonly"} }, { "wallet", "gettransaction", &gettransaction, false, {"txid","include_watchonly"} },
{ "wallet", "getunconfirmedbalance", &getunconfirmedbalance, false, {} }, { "wallet", "getunconfirmedbalance", &getunconfirmedbalance, false, {} },
{ "wallet", "getwalletinfo", &getwalletinfo, false, {} }, { "wallet", "getwalletinfo", &getwalletinfo, false, {} },
@ -2871,19 +2871,19 @@ static const CRPCCommand commands[] =
{ "wallet", "importprunedfunds", &importprunedfunds, true, {"rawtransaction","txoutproof"} }, { "wallet", "importprunedfunds", &importprunedfunds, true, {"rawtransaction","txoutproof"} },
{ "wallet", "importpubkey", &importpubkey, true, {"pubkey","label","rescan"} }, { "wallet", "importpubkey", &importpubkey, true, {"pubkey","label","rescan"} },
{ "wallet", "keypoolrefill", &keypoolrefill, true, {"newsize"} }, { "wallet", "keypoolrefill", &keypoolrefill, true, {"newsize"} },
{ "wallet", "listaccounts", &listaccounts, false, {"minconf","addlockconf","include_watchonly"} }, { "wallet", "listaccounts", &listaccounts, false, {"minconf","addlocked","include_watchonly"} },
{ "wallet", "listaddressgroupings", &listaddressgroupings, false, {} }, { "wallet", "listaddressgroupings", &listaddressgroupings, false, {} },
{ "wallet", "listaddressbalances", &listaddressbalances, false, {"minamount"} }, { "wallet", "listaddressbalances", &listaddressbalances, false, {"minamount"} },
{ "wallet", "listlockunspent", &listlockunspent, false, {} }, { "wallet", "listlockunspent", &listlockunspent, false, {} },
{ "wallet", "listreceivedbyaccount", &listreceivedbyaccount, false, {"minconf","addlockconf","include_empty","include_watchonly"} }, { "wallet", "listreceivedbyaccount", &listreceivedbyaccount, false, {"minconf","addlocked","include_empty","include_watchonly"} },
{ "wallet", "listreceivedbyaddress", &listreceivedbyaddress, false, {"minconf","addlockconf","include_empty","include_watchonly"} }, { "wallet", "listreceivedbyaddress", &listreceivedbyaddress, false, {"minconf","addlocked","include_empty","include_watchonly"} },
{ "wallet", "listsinceblock", &listsinceblock, false, {"blockhash","target_confirmations","include_watchonly"} }, { "wallet", "listsinceblock", &listsinceblock, false, {"blockhash","target_confirmations","include_watchonly"} },
{ "wallet", "listtransactions", &listtransactions, false, {"account","count","skip","include_watchonly"} }, { "wallet", "listtransactions", &listtransactions, false, {"account","count","skip","include_watchonly"} },
{ "wallet", "listunspent", &listunspent, false, {"minconf","maxconf","addresses","include_unsafe"} }, { "wallet", "listunspent", &listunspent, false, {"minconf","maxconf","addresses","include_unsafe"} },
{ "wallet", "lockunspent", &lockunspent, true, {"unlock","transactions"} }, { "wallet", "lockunspent", &lockunspent, true, {"unlock","transactions"} },
{ "wallet", "move", &movecmd, false, {"fromaccount","toaccount","amount","minconf","comment"} }, { "wallet", "move", &movecmd, false, {"fromaccount","toaccount","amount","minconf","comment"} },
{ "wallet", "sendfrom", &sendfrom, false, {"fromaccount","toaddress","amount","minconf","addlockconf","comment","comment_to"} }, { "wallet", "sendfrom", &sendfrom, false, {"fromaccount","toaddress","amount","minconf","addlocked","comment","comment_to"} },
{ "wallet", "sendmany", &sendmany, false, {"fromaccount","amounts","minconf","addlockconf","comment","subtractfeefrom"} }, { "wallet", "sendmany", &sendmany, false, {"fromaccount","amounts","minconf","addlocked","comment","subtractfeefrom"} },
{ "wallet", "sendtoaddress", &sendtoaddress, false, {"address","amount","comment","comment_to","subtractfeefromamount"} }, { "wallet", "sendtoaddress", &sendtoaddress, false, {"address","amount","comment","comment_to","subtractfeefromamount"} },
{ "wallet", "setaccount", &setaccount, true, {"address","account"} }, { "wallet", "setaccount", &setaccount, true, {"address","account"} },
{ "wallet", "settxfee", &settxfee, true, {"amount"} }, { "wallet", "settxfee", &settxfee, true, {"amount"} },

View File

@ -1259,7 +1259,7 @@ bool CWallet::AbandonTransaction(const uint256& hashTx)
// Can't mark abandoned if confirmed or in mempool // Can't mark abandoned if confirmed or in mempool
assert(mapWallet.count(hashTx)); assert(mapWallet.count(hashTx));
CWalletTx& origtx = mapWallet[hashTx]; CWalletTx& origtx = mapWallet[hashTx];
if (origtx.GetDepthInMainChain() > 0 || origtx.InMempool()) { if (origtx.GetDepthInMainChain() > 0 || origtx.InMempool() || origtx.IsLockedByInstantSend()) {
return false; return false;
} }
@ -1945,7 +1945,7 @@ void CWallet::ReacceptWalletTransactions()
int nDepth = wtx.GetDepthInMainChain(); int nDepth = wtx.GetDepthInMainChain();
if (!wtx.IsCoinBase() && (nDepth == 0 && !wtx.isAbandoned())) { if (!wtx.IsCoinBase() && (nDepth == 0 && !wtx.IsLockedByInstantSend() && !wtx.isAbandoned())) {
mapSorted.insert(std::make_pair(wtx.nOrderPos, &wtx)); mapSorted.insert(std::make_pair(wtx.nOrderPos, &wtx));
} }
} }
@ -2194,7 +2194,7 @@ CAmount CWalletTx::GetDenominatedCredit(bool unconfirmed, bool fUseCache) const
if (IsCoinBase() && GetBlocksToMaturity() > 0) if (IsCoinBase() && GetBlocksToMaturity() > 0)
return 0; return 0;
int nDepth = GetDepthInMainChain(false); int nDepth = GetDepthInMainChain();
if(nDepth < 0) return 0; if(nDepth < 0) return 0;
bool isUnconfirmed = IsTrusted() && nDepth == 0; bool isUnconfirmed = IsTrusted() && nDepth == 0;
@ -2258,6 +2258,8 @@ bool CWalletTx::IsTrusted() const
return true; return true;
if (nDepth < 0) if (nDepth < 0)
return false; return false;
if (IsLockedByInstantSend())
return true;
if (!bSpendZeroConfChange || !IsFromMe(ISMINE_ALL)) // using wtx's cached debit if (!bSpendZeroConfChange || !IsFromMe(ISMINE_ALL)) // using wtx's cached debit
return false; return false;
@ -2501,7 +2503,7 @@ CAmount CWallet::GetUnconfirmedBalance() const
for (std::map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it) for (std::map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
{ {
const CWalletTx* pcoin = &(*it).second; const CWalletTx* pcoin = &(*it).second;
if (!pcoin->IsTrusted() && pcoin->GetDepthInMainChain() == 0 && pcoin->InMempool()) if (!pcoin->IsTrusted() && pcoin->GetDepthInMainChain() == 0 && !pcoin->IsLockedByInstantSend() && pcoin->InMempool())
nTotal += pcoin->GetAvailableCredit(); nTotal += pcoin->GetAvailableCredit();
} }
} }
@ -2546,7 +2548,7 @@ CAmount CWallet::GetUnconfirmedWatchOnlyBalance() const
for (std::map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it) for (std::map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
{ {
const CWalletTx* pcoin = &(*it).second; const CWalletTx* pcoin = &(*it).second;
if (!pcoin->IsTrusted() && pcoin->GetDepthInMainChain() == 0 && pcoin->InMempool()) if (!pcoin->IsTrusted() && pcoin->GetDepthInMainChain() == 0 && !pcoin->IsLockedByInstantSend() && pcoin->InMempool())
nTotal += pcoin->GetAvailableWatchOnlyCredit(); nTotal += pcoin->GetAvailableWatchOnlyCredit();
} }
} }
@ -2589,7 +2591,7 @@ void CWallet::AvailableCoins(std::vector<COutput>& vCoins, bool fOnlyConfirmed,
if (pcoin->IsCoinBase() && pcoin->GetBlocksToMaturity() > 0) if (pcoin->IsCoinBase() && pcoin->GetBlocksToMaturity() > 0)
continue; continue;
int nDepth = pcoin->GetDepthInMainChain(false); int nDepth = pcoin->GetDepthInMainChain();
// do not use IX for inputs that have less then nInstantSendConfirmationsRequired blockchain confirmations // do not use IX for inputs that have less then nInstantSendConfirmationsRequired blockchain confirmations
if (fUseInstantSend && nDepth < nInstantSendConfirmationsRequired) if (fUseInstantSend && nDepth < nInstantSendConfirmationsRequired)
continue; continue;
@ -3277,7 +3279,7 @@ int CWallet::CountInputsWithAmount(CAmount nInputAmount)
{ {
const CWalletTx* pcoin = &(*it).second; const CWalletTx* pcoin = &(*it).second;
if (pcoin->IsTrusted()){ if (pcoin->IsTrusted()){
int nDepth = pcoin->GetDepthInMainChain(false); int nDepth = pcoin->GetDepthInMainChain();
for (unsigned int i = 0; i < pcoin->tx->vout.size(); i++) { for (unsigned int i = 0; i < pcoin->tx->vout.size(); i++) {
COutput out = COutput(pcoin, i, nDepth, true, true); COutput out = COutput(pcoin, i, nDepth, true, true);
@ -4315,7 +4317,7 @@ std::map<CTxDestination, CAmount> CWallet::GetAddressBalances()
continue; continue;
int nDepth = pcoin->GetDepthInMainChain(); int nDepth = pcoin->GetDepthInMainChain();
if (nDepth < (pcoin->IsFromMe(ISMINE_ALL) ? 0 : 1)) if ((nDepth < (pcoin->IsFromMe(ISMINE_ALL) ? 0 : 1)) && !pcoin->IsLockedByInstantSend())
continue; continue;
for (unsigned int i = 0; i < pcoin->tx->vout.size(); i++) for (unsigned int i = 0; i < pcoin->tx->vout.size(); i++)
@ -4431,13 +4433,13 @@ std::set< std::set<CTxDestination> > CWallet::GetAddressGroupings()
return ret; return ret;
} }
CAmount CWallet::GetAccountBalance(const std::string& strAccount, int nMinDepth, const isminefilter& filter, bool fAddLockConf) CAmount CWallet::GetAccountBalance(const std::string& strAccount, int nMinDepth, const isminefilter& filter, bool fAddLocked)
{ {
CWalletDB walletdb(strWalletFile); CWalletDB walletdb(strWalletFile);
return GetAccountBalance(walletdb, strAccount, nMinDepth, filter, fAddLockConf); return GetAccountBalance(walletdb, strAccount, nMinDepth, filter, fAddLocked);
} }
CAmount CWallet::GetAccountBalance(CWalletDB& walletdb, const std::string& strAccount, int nMinDepth, const isminefilter& filter, bool fAddLockConf) CAmount CWallet::GetAccountBalance(CWalletDB& walletdb, const std::string& strAccount, int nMinDepth, const isminefilter& filter, bool fAddLocked)
{ {
CAmount nBalance = 0; CAmount nBalance = 0;
@ -4445,13 +4447,13 @@ CAmount CWallet::GetAccountBalance(CWalletDB& walletdb, const std::string& strAc
for (std::map<uint256, CWalletTx>::iterator it = mapWallet.begin(); it != mapWallet.end(); ++it) for (std::map<uint256, CWalletTx>::iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
{ {
const CWalletTx& wtx = (*it).second; const CWalletTx& wtx = (*it).second;
if (!CheckFinalTx(wtx) || wtx.GetBlocksToMaturity() > 0 || wtx.GetDepthInMainChain(fAddLockConf) < 0) if (!CheckFinalTx(wtx) || wtx.GetBlocksToMaturity() > 0 || wtx.GetDepthInMainChain() < 0)
continue; continue;
CAmount nReceived, nSent, nFee; CAmount nReceived, nSent, nFee;
wtx.GetAccountAmounts(strAccount, nReceived, nSent, nFee, filter); wtx.GetAccountAmounts(strAccount, nReceived, nSent, nFee, filter);
if (nReceived != 0 && wtx.GetDepthInMainChain(fAddLockConf) >= nMinDepth) if (nReceived != 0 && ((wtx.GetDepthInMainChain() >= nMinDepth) || (fAddLocked && wtx.IsLockedByInstantSend())))
nBalance += nReceived; nBalance += nReceived;
nBalance -= nSent + nFee; nBalance -= nSent + nFee;
} }
@ -5349,7 +5351,7 @@ void CMerkleTx::SetMerkleBranch(const CBlockIndex* pindex, int posInBlock)
nIndex = posInBlock; nIndex = posInBlock;
} }
int CMerkleTx::GetDepthInMainChain(const CBlockIndex* &pindexRet, bool enableIX) const int CMerkleTx::GetDepthInMainChain(const CBlockIndex* &pindexRet) const
{ {
int nResult; int nResult;
@ -5376,12 +5378,14 @@ int CMerkleTx::GetDepthInMainChain(const CBlockIndex* &pindexRet, bool enableIX)
} }
} }
if(enableIX && nResult < 6 && instantsend.IsLockedInstantSendTransaction(GetHash()))
return nInstantSendDepth + nResult;
return nResult; return nResult;
} }
bool CMerkleTx::IsLockedByInstantSend() const
{
return instantsend.IsLockedInstantSendTransaction(GetHash());
}
int CMerkleTx::GetBlocksToMaturity() const int CMerkleTx::GetBlocksToMaturity() const
{ {
if (!IsCoinBase()) if (!IsCoinBase())

View File

@ -271,9 +271,10 @@ public:
* 0 : in memory pool, waiting to be included in a block * 0 : in memory pool, waiting to be included in a block
* >=1 : this many blocks deep in the main chain * >=1 : this many blocks deep in the main chain
*/ */
int GetDepthInMainChain(const CBlockIndex* &pindexRet, bool enableIX = true) const; int GetDepthInMainChain(const CBlockIndex* &pindexRet) const;
int GetDepthInMainChain(bool enableIX = true) const { const CBlockIndex *pindexRet; return GetDepthInMainChain(pindexRet, enableIX); } int GetDepthInMainChain() const { const CBlockIndex *pindexRet; return GetDepthInMainChain(pindexRet); }
bool IsInMainChain() const { const CBlockIndex *pindexRet; return GetDepthInMainChain(pindexRet) > 0; } bool IsInMainChain() const { const CBlockIndex *pindexRet; return GetDepthInMainChain(pindexRet) > 0; }
bool IsLockedByInstantSend() const;
int GetBlocksToMaturity() const; int GetBlocksToMaturity() const;
/** Pass this transaction to the mempool. Fails if absolute fee exceeds absurd fee. */ /** Pass this transaction to the mempool. Fails if absolute fee exceeds absurd fee. */
bool AcceptToMemoryPool(const CAmount& nAbsurdFee, CValidationState& state); bool AcceptToMemoryPool(const CAmount& nAbsurdFee, CValidationState& state);
@ -977,8 +978,8 @@ public:
std::set< std::set<CTxDestination> > GetAddressGroupings(); std::set< std::set<CTxDestination> > GetAddressGroupings();
std::map<CTxDestination, CAmount> GetAddressBalances(); std::map<CTxDestination, CAmount> GetAddressBalances();
CAmount GetAccountBalance(const std::string& strAccount, int nMinDepth, const isminefilter& filter, bool fAddLockConf); CAmount GetAccountBalance(const std::string& strAccount, int nMinDepth, const isminefilter& filter, bool fAddLocked);
CAmount GetAccountBalance(CWalletDB& walletdb, const std::string& strAccount, int nMinDepth, const isminefilter& filter, bool fAddLockConf); CAmount GetAccountBalance(CWalletDB& walletdb, const std::string& strAccount, int nMinDepth, const isminefilter& filter, bool fAddLocked);
std::set<CTxDestination> GetAccountAddresses(const std::string& strAccount) const; std::set<CTxDestination> GetAccountAddresses(const std::string& strAccount) const;
isminetype IsMine(const CTxIn& txin) const; isminetype IsMine(const CTxIn& txin) const;