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
Details pertaining to an observed "Transaction Lock" can also be retrieved through RPC, its important however to understand the underlying mechanism.
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
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).

View File

@ -605,7 +605,7 @@ bool CGovernanceObject::IsCollateralValid(std::string& strError, bool& fMissingC
// GET CONFIRMATIONS FOR TRANSACTION
AssertLockHeld(cs_main);
int nConfirmationsIn = instantsend.GetConfirmations(nCollateralHash);
int nConfirmationsIn = 0;
if (nBlockHash != uint256()) {
BlockMap::iterator mi = mapBlockIndex.find(nBlockHash);
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);
if (nConfirmationsIn >= GOVERNANCE_MIN_RELAY_FEE_CONFIRMATIONS) {
fMissingConfirmations = true;

View File

@ -576,7 +576,6 @@ std::string HelpMessage(HelpMessageMode mode)
strUsage += HelpMessageGroup(_("InstantSend options:"));
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)"));
@ -1873,11 +1872,8 @@ bool AppInitMain(boost::thread_group& threadGroup, CScheduler& scheduler)
#endif // ENABLE_WALLET
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("nInstantSendDepth %d\n", nInstantSendDepth);
#ifdef ENABLE_WALLET
LogPrintf("PrivateSend liquidityprovider: %d\n", privateSendClient.nLiquidityProvider);
LogPrintf("PrivateSend rounds: %d\n", privateSendClient.nPrivateSendRounds);

View File

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

View File

@ -26,14 +26,6 @@ extern CInstantSend instantsend;
(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;
/// For how long we are going to accept votes/locks
@ -145,8 +137,6 @@ public:
bool IsLockedInstantSendTransaction(const uint256& txHash);
/// Get the actual number of accepted lock signatures
int GetTransactionLockSignatures(const uint256& txHash);
/// Get instantsend confirmations (only)
int GetConfirmations(const uint256 &nTXHash);
/// Remove expired entries from maps
void CheckAndRemove();

View File

@ -34,6 +34,8 @@ static const bool DEFAULT_SPLASHSCREEN = true;
#define COLOR_TX_STATUS_DANGER QColor(200, 100, 100)
/* Transaction list -- TX status decoration - default color */
#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,
so that they can be word-wrapped.

View File

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

View File

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

View File

@ -484,6 +484,24 @@ QString TransactionTableModel::formatTxAmount(const TransactionRecord *wtx, bool
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
{
QString theme = GUIUtil::getThemeName();
@ -495,17 +513,19 @@ QVariant TransactionTableModel::txStatusDecoration(const TransactionRecord *wtx)
case TransactionStatus::Offline:
return COLOR_TX_STATUS_OFFLINE;
case TransactionStatus::Unconfirmed:
// TODO: use special icon for InstantSend 0-conf
return QIcon(":/icons/" + theme + "/transaction_0");
case TransactionStatus::Abandoned:
return QIcon(":/icons/" + theme + "/transaction_abandoned");
case TransactionStatus::Confirming:
switch(wtx->status.depth)
{
case 1: return QIcon(":/icons/" + theme + "/transaction_1");
case 2: return QIcon(":/icons/" + theme + "/transaction_2");
case 3: return QIcon(":/icons/" + theme + "/transaction_3");
case 4: return QIcon(":/icons/" + theme + "/transaction_4");
default: return QIcon(":/icons/" + theme + "/transaction_5");
// TODO: use special icons for InstantSend instead of color shifting
case 1: return IconWithShiftedColor(":/icons/" + theme + "/transaction_1", wtx->status.lockedByInstantSend);
case 2: return IconWithShiftedColor(":/icons/" + theme + "/transaction_2", wtx->status.lockedByInstantSend);
case 3: return IconWithShiftedColor(":/icons/" + theme + "/transaction_3", wtx->status.lockedByInstantSend);
case 4: return IconWithShiftedColor(":/icons/" + theme + "/transaction_4", wtx->status.lockedByInstantSend);
default: return IconWithShiftedColor(":/icons/" + theme + "/transaction_5", wtx->status.lockedByInstantSend);
};
case TransactionStatus::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;
}
if(rec->status.lockedByInstantSend)
{
return COLOR_TX_STATUS_LOCKED;
}
// Non-confirmed (but not immature) as transactions are grey
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);
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 true;
}

View File

@ -58,7 +58,7 @@ void EnsureWalletIsUnlocked()
void WalletTxToJSON(const CWalletTx& wtx, UniValue& entry)
{
int confirms = wtx.GetDepthInMainChain(false);
int confirms = wtx.GetDepthInMainChain();
bool fLocked = instantsend.IsLockedInstantSendTransaction(wtx.GetHash());
entry.push_back(Pair("confirmations", confirms));
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)
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"
"\nArguments:\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"
"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"
"amount (numeric) The total amount in " + CURRENCY_UNIT + " received at this address.\n"
"\nExamples:\n"
@ -690,7 +690,7 @@ UniValue getreceivedbyaddress(const JSONRPCRequest& request)
int nMinDepth = 1;
if (request.params.size() > 1)
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
CAmount nAmount = 0;
@ -702,7 +702,7 @@ UniValue getreceivedbyaddress(const JSONRPCRequest& request)
BOOST_FOREACH(const CTxOut& txout, wtx.tx->vout)
if (txout.scriptPubKey == scriptPubKey)
if (wtx.GetDepthInMainChain(fAddLockConf) >= nMinDepth)
if ((wtx.GetDepthInMainChain() >= nMinDepth) || (fAddLocked && wtx.IsLockedByInstantSend()))
nAmount += txout.nValue;
}
@ -717,12 +717,12 @@ UniValue getreceivedbyaccount(const JSONRPCRequest& request)
if (request.fHelp || request.params.size() < 1 || request.params.size() > 3)
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"
"\nArguments:\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"
"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"
"amount (numeric) The total amount in " + CURRENCY_UNIT + " received for this account.\n"
"\nExamples:\n"
@ -742,7 +742,7 @@ UniValue getreceivedbyaccount(const JSONRPCRequest& request)
int nMinDepth = 1;
if (request.params.size() > 1)
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
std::string strAccount = AccountFromValue(request.params[0]);
@ -760,7 +760,7 @@ UniValue getreceivedbyaccount(const JSONRPCRequest& request)
{
CTxDestination 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;
}
}
@ -776,7 +776,7 @@ UniValue getbalance(const JSONRPCRequest& request)
if (request.fHelp || request.params.size() > 4)
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"
"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"
@ -784,7 +784,7 @@ UniValue getbalance(const JSONRPCRequest& request)
"\nArguments:\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"
"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"
"\nResult:\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;
if (request.params.size() > 1)
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;
if(request.params.size() > 3)
if(request.params[3].get_bool())
@ -827,7 +827,7 @@ UniValue getbalance(const JSONRPCRequest& request)
std::list<COutputEntry> listReceived;
std::list<COutputEntry> listSent;
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)
nBalance += r.amount;
@ -841,7 +841,7 @@ UniValue getbalance(const JSONRPCRequest& request)
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);
}
@ -916,7 +916,7 @@ UniValue sendfrom(const JSONRPCRequest& request)
if (request.fHelp || request.params.size() < 3 || request.params.size() > 7)
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."
+ HelpRequiringPassphrase() + "\n"
"\nArguments:\n"
@ -927,7 +927,7 @@ UniValue sendfrom(const JSONRPCRequest& request)
"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"
"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"
" 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"
@ -956,7 +956,7 @@ UniValue sendfrom(const JSONRPCRequest& request)
int nMinDepth = 1;
if (request.params.size() > 3)
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;
wtx.strFromAccount = strAccount;
@ -968,7 +968,7 @@ UniValue sendfrom(const JSONRPCRequest& request)
EnsureWalletIsUnlocked();
// Check funds
CAmount nBalance = pwalletMain->GetAccountBalance(strAccount, nMinDepth, ISMINE_SPENDABLE, fAddLockConf);
CAmount nBalance = pwalletMain->GetAccountBalance(strAccount, nMinDepth, ISMINE_SPENDABLE, fAddLocked);
if (nAmount > nBalance)
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)
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."
+ HelpRequiringPassphrase() + "\n"
"\nArguments:\n"
@ -996,7 +996,7 @@ UniValue sendmany(const JSONRPCRequest& request)
" ,...\n"
" }\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"
"6. subtractfeefromamount (array, optional) A json array with addresses.\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;
if (request.params.size() > 2)
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;
wtx.strFromAccount = strAccount;
@ -1076,7 +1076,7 @@ UniValue sendmany(const JSONRPCRequest& request)
EnsureWalletIsUnlocked();
// Check funds
CAmount nBalance = pwalletMain->GetAccountBalance(strAccount, nMinDepth, ISMINE_SPENDABLE, fAddLockConf);
CAmount nBalance = pwalletMain->GetAccountBalance(strAccount, nMinDepth, ISMINE_SPENDABLE, fAddLocked);
if (totalAmount > nBalance)
throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, "Account has insufficient funds");
@ -1177,7 +1177,7 @@ UniValue ListReceived(const UniValue& params, bool fByAccounts)
int nMinDepth = 1;
if (params.size() > 0)
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
bool fIncludeEmpty = false;
@ -1198,8 +1198,8 @@ UniValue ListReceived(const UniValue& params, bool fByAccounts)
if (wtx.IsCoinBase() || !CheckFinalTx(*wtx.tx))
continue;
int nDepth = wtx.GetDepthInMainChain(fAddLockConf);
if (nDepth < nMinDepth)
int nDepth = wtx.GetDepthInMainChain();
if ((nDepth < nMinDepth) && !(fAddLocked && wtx.IsLockedByInstantSend()))
continue;
BOOST_FOREACH(const CTxOut& txout, wtx.tx->vout)
@ -1303,11 +1303,11 @@ UniValue listreceivedbyaddress(const JSONRPCRequest& request)
if (request.fHelp || request.params.size() > 4)
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"
"\nArguments:\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"
"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"
" \"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"
" If 'addlockconf' is true, the minimum number of confirmations is calculated\n"
" including additional " + std::to_string(nInstantSendDepth) + " confirmations for transactions locked via InstantSend\n"
" If 'addlocked' is true, the number of confirmations can be less than\n"
" configured for transactions locked via InstantSend\n"
" \"label\" : \"label\", (string) A comment for the address/transaction, if any\n"
" \"txids\": [\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)
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"
"\nArguments:\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"
"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
if (listReceived.size() > 0 && wtx.GetDepthInMainChain() >= nMinDepth)
if (listReceived.size() > 0 && ((wtx.GetDepthInMainChain() >= nMinDepth) || wtx.IsLockedByInstantSend()))
{
BOOST_FOREACH(const COutputEntry& r, listReceived)
{
@ -1615,11 +1615,11 @@ UniValue listaccounts(const JSONRPCRequest& request)
if (request.fHelp || request.params.size() > 3)
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"
"\nArguments:\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"
"\nResult:\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;
if (request.params.size() > 0)
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;
if(request.params.size() > 2)
if(request.params[2].get_bool())
@ -1661,14 +1661,14 @@ UniValue listaccounts(const JSONRPCRequest& request)
std::string strSentAccount;
std::list<COutputEntry> listReceived;
std::list<COutputEntry> listSent;
int nDepth = wtx.GetDepthInMainChain(fAddLockConf);
int nDepth = wtx.GetDepthInMainChain();
if (wtx.GetBlocksToMaturity() > 0 || nDepth < 0)
continue;
wtx.GetAmounts(listReceived, listSent, nFee, strSentAccount, includeWatchonly);
mapAccountBalances[strSentAccount] -= nFee;
BOOST_FOREACH(const COutputEntry& s, listSent)
mapAccountBalances[strSentAccount] -= s.amount;
if (nDepth >= nMinDepth)
if ((nDepth >= nMinDepth) || (fAddLocked && wtx.IsLockedByInstantSend()))
{
BOOST_FOREACH(const COutputEntry& r, listReceived)
if (pwalletMain->mapAddressBook.count(r.destination))
@ -1784,7 +1784,7 @@ UniValue listsinceblock(const JSONRPCRequest& request)
{
CWalletTx tx = (*it).second;
if (depth == -1 || tx.GetDepthInMainChain(false) < depth)
if (depth == -1 || tx.GetDepthInMainChain() < depth)
ListTransactions(tx, "*", 0, true, transactions, filter);
}
@ -2856,11 +2856,11 @@ static const CRPCCommand commands[] =
{ "wallet", "getaccountaddress", &getaccountaddress, true, {"account"} },
{ "wallet", "getaccount", &getaccount, true, {"address"} },
{ "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", "getrawchangeaddress", &getrawchangeaddress, true, {} },
{ "wallet", "getreceivedbyaccount", &getreceivedbyaccount, false, {"account","minconf","addlockconf"} },
{ "wallet", "getreceivedbyaddress", &getreceivedbyaddress, false, {"address","minconf","addlockconf"} },
{ "wallet", "getreceivedbyaccount", &getreceivedbyaccount, false, {"account","minconf","addlocked"} },
{ "wallet", "getreceivedbyaddress", &getreceivedbyaddress, false, {"address","minconf","addlocked"} },
{ "wallet", "gettransaction", &gettransaction, false, {"txid","include_watchonly"} },
{ "wallet", "getunconfirmedbalance", &getunconfirmedbalance, false, {} },
{ "wallet", "getwalletinfo", &getwalletinfo, false, {} },
@ -2871,19 +2871,19 @@ static const CRPCCommand commands[] =
{ "wallet", "importprunedfunds", &importprunedfunds, true, {"rawtransaction","txoutproof"} },
{ "wallet", "importpubkey", &importpubkey, true, {"pubkey","label","rescan"} },
{ "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", "listaddressbalances", &listaddressbalances, false, {"minamount"} },
{ "wallet", "listlockunspent", &listlockunspent, false, {} },
{ "wallet", "listreceivedbyaccount", &listreceivedbyaccount, false, {"minconf","addlockconf","include_empty","include_watchonly"} },
{ "wallet", "listreceivedbyaddress", &listreceivedbyaddress, false, {"minconf","addlockconf","include_empty","include_watchonly"} },
{ "wallet", "listreceivedbyaccount", &listreceivedbyaccount, false, {"minconf","addlocked","include_empty","include_watchonly"} },
{ "wallet", "listreceivedbyaddress", &listreceivedbyaddress, false, {"minconf","addlocked","include_empty","include_watchonly"} },
{ "wallet", "listsinceblock", &listsinceblock, false, {"blockhash","target_confirmations","include_watchonly"} },
{ "wallet", "listtransactions", &listtransactions, false, {"account","count","skip","include_watchonly"} },
{ "wallet", "listunspent", &listunspent, false, {"minconf","maxconf","addresses","include_unsafe"} },
{ "wallet", "lockunspent", &lockunspent, true, {"unlock","transactions"} },
{ "wallet", "move", &movecmd, false, {"fromaccount","toaccount","amount","minconf","comment"} },
{ "wallet", "sendfrom", &sendfrom, false, {"fromaccount","toaddress","amount","minconf","addlockconf","comment","comment_to"} },
{ "wallet", "sendmany", &sendmany, false, {"fromaccount","amounts","minconf","addlockconf","comment","subtractfeefrom"} },
{ "wallet", "sendfrom", &sendfrom, false, {"fromaccount","toaddress","amount","minconf","addlocked","comment","comment_to"} },
{ "wallet", "sendmany", &sendmany, false, {"fromaccount","amounts","minconf","addlocked","comment","subtractfeefrom"} },
{ "wallet", "sendtoaddress", &sendtoaddress, false, {"address","amount","comment","comment_to","subtractfeefromamount"} },
{ "wallet", "setaccount", &setaccount, true, {"address","account"} },
{ "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
assert(mapWallet.count(hashTx));
CWalletTx& origtx = mapWallet[hashTx];
if (origtx.GetDepthInMainChain() > 0 || origtx.InMempool()) {
if (origtx.GetDepthInMainChain() > 0 || origtx.InMempool() || origtx.IsLockedByInstantSend()) {
return false;
}
@ -1945,7 +1945,7 @@ void CWallet::ReacceptWalletTransactions()
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));
}
}
@ -2194,7 +2194,7 @@ CAmount CWalletTx::GetDenominatedCredit(bool unconfirmed, bool fUseCache) const
if (IsCoinBase() && GetBlocksToMaturity() > 0)
return 0;
int nDepth = GetDepthInMainChain(false);
int nDepth = GetDepthInMainChain();
if(nDepth < 0) return 0;
bool isUnconfirmed = IsTrusted() && nDepth == 0;
@ -2258,6 +2258,8 @@ bool CWalletTx::IsTrusted() const
return true;
if (nDepth < 0)
return false;
if (IsLockedByInstantSend())
return true;
if (!bSpendZeroConfChange || !IsFromMe(ISMINE_ALL)) // using wtx's cached debit
return false;
@ -2501,7 +2503,7 @@ CAmount CWallet::GetUnconfirmedBalance() const
for (std::map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
{
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();
}
}
@ -2546,7 +2548,7 @@ CAmount CWallet::GetUnconfirmedWatchOnlyBalance() const
for (std::map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
{
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();
}
}
@ -2589,7 +2591,7 @@ void CWallet::AvailableCoins(std::vector<COutput>& vCoins, bool fOnlyConfirmed,
if (pcoin->IsCoinBase() && pcoin->GetBlocksToMaturity() > 0)
continue;
int nDepth = pcoin->GetDepthInMainChain(false);
int nDepth = pcoin->GetDepthInMainChain();
// do not use IX for inputs that have less then nInstantSendConfirmationsRequired blockchain confirmations
if (fUseInstantSend && nDepth < nInstantSendConfirmationsRequired)
continue;
@ -3277,7 +3279,7 @@ int CWallet::CountInputsWithAmount(CAmount nInputAmount)
{
const CWalletTx* pcoin = &(*it).second;
if (pcoin->IsTrusted()){
int nDepth = pcoin->GetDepthInMainChain(false);
int nDepth = pcoin->GetDepthInMainChain();
for (unsigned int i = 0; i < pcoin->tx->vout.size(); i++) {
COutput out = COutput(pcoin, i, nDepth, true, true);
@ -4315,7 +4317,7 @@ std::map<CTxDestination, CAmount> CWallet::GetAddressBalances()
continue;
int nDepth = pcoin->GetDepthInMainChain();
if (nDepth < (pcoin->IsFromMe(ISMINE_ALL) ? 0 : 1))
if ((nDepth < (pcoin->IsFromMe(ISMINE_ALL) ? 0 : 1)) && !pcoin->IsLockedByInstantSend())
continue;
for (unsigned int i = 0; i < pcoin->tx->vout.size(); i++)
@ -4431,13 +4433,13 @@ std::set< std::set<CTxDestination> > CWallet::GetAddressGroupings()
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);
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;
@ -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)
{
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;
CAmount nReceived, nSent, nFee;
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 -= nSent + nFee;
}
@ -5349,7 +5351,7 @@ void CMerkleTx::SetMerkleBranch(const CBlockIndex* pindex, int posInBlock)
nIndex = posInBlock;
}
int CMerkleTx::GetDepthInMainChain(const CBlockIndex* &pindexRet, bool enableIX) const
int CMerkleTx::GetDepthInMainChain(const CBlockIndex* &pindexRet) const
{
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;
}
bool CMerkleTx::IsLockedByInstantSend() const
{
return instantsend.IsLockedInstantSendTransaction(GetHash());
}
int CMerkleTx::GetBlocksToMaturity() const
{
if (!IsCoinBase())

View File

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