aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.am2
-rw-r--r--src/Makefile.qt.include3
-rw-r--r--src/chainparams.cpp4
-rw-r--r--src/main.cpp86
-rw-r--r--src/main.h18
-rw-r--r--src/netbase.cpp10
-rw-r--r--src/netbase.h3
-rw-r--r--src/policy/fees.h4
-rw-r--r--src/policy/policy.cpp4
-rw-r--r--src/qt/bitcoin.qrc1
-rw-r--r--src/qt/guiconstants.h2
-rw-r--r--src/qt/res/icons/transaction_abandoned.pngbin0 -> 1473 bytes
-rw-r--r--src/qt/transactiondesc.cpp2
-rw-r--r--src/qt/transactionrecord.cpp2
-rw-r--r--src/qt/transactionrecord.h1
-rw-r--r--src/qt/transactiontablemodel.cpp10
-rw-r--r--src/qt/transactionview.cpp33
-rw-r--r--src/qt/transactionview.h2
-rw-r--r--src/qt/walletmodel.cpp15
-rw-r--r--src/qt/walletmodel.h3
-rw-r--r--src/rpc/blockchain.cpp16
-rw-r--r--src/rpc/client.cpp5
-rw-r--r--src/script/interpreter.cpp12
-rw-r--r--src/script/standard.h2
-rw-r--r--src/test/rpc_tests.cpp24
-rw-r--r--src/txmempool.h40
-rw-r--r--src/utiltime.cpp2
-rw-r--r--src/wallet/wallet.h8
28 files changed, 220 insertions, 94 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index 1e54512cbd..d91e959cff 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -479,7 +479,7 @@ endif
%.pb.cc %.pb.h: %.proto
@test -f $(PROTOC)
- $(AM_V_GEN) $(PROTOC) --cpp_out=$(@D) --proto_path=$(abspath $(<D) $<)
+ $(AM_V_GEN) $(PROTOC) --cpp_out=$(@D) --proto_path=$(<D) $<
if ENABLE_TESTS
include Makefile.test.include
diff --git a/src/Makefile.qt.include b/src/Makefile.qt.include
index 357e4c47ff..8443fe697b 100644
--- a/src/Makefile.qt.include
+++ b/src/Makefile.qt.include
@@ -268,7 +268,8 @@ RES_ICONS = \
qt/res/icons/tx_output.png \
qt/res/icons/tx_mined.png \
qt/res/icons/warning.png \
- qt/res/icons/verify.png
+ qt/res/icons/verify.png \
+ qt/res/icons/transaction_abandoned.png
BITCOIN_QT_CPP = \
qt/bantablemodel.cpp \
diff --git a/src/chainparams.cpp b/src/chainparams.cpp
index 965d131695..5c7d190125 100644
--- a/src/chainparams.cpp
+++ b/src/chainparams.cpp
@@ -266,8 +266,8 @@ public:
assert(consensus.hashGenesisBlock == uint256S("0x0f9188f13cb7b2c71f2a335e3a4fc328bf5beb436012afca590b1a11466e2206"));
assert(genesis.hashMerkleRoot == uint256S("0x4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b"));
- vFixedSeeds.clear(); //! Regtest mode doesn't have any fixed seeds.
- vSeeds.clear(); //! Regtest mode doesn't have any DNS seeds.
+ vFixedSeeds.clear(); //!< Regtest mode doesn't have any fixed seeds.
+ vSeeds.clear(); //!< Regtest mode doesn't have any DNS seeds.
fMiningRequiresPeers = false;
fDefaultConsistencyChecks = true;
diff --git a/src/main.cpp b/src/main.cpp
index 2c0b3bfee7..9b164c7999 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -194,16 +194,11 @@ namespace {
/** Blocks that are in flight, and that are in the queue to be downloaded. Protected by cs_main. */
struct QueuedBlock {
uint256 hash;
- CBlockIndex *pindex; //! Optional.
- int64_t nTime; //! Time of "getdata" request in microseconds.
- bool fValidatedHeaders; //! Whether this block has validated headers at the time of request.
- int64_t nTimeDisconnect; //! The timeout for this block request (for disconnecting a slow peer)
+ CBlockIndex* pindex; //!< Optional.
+ bool fValidatedHeaders; //!< Whether this block has validated headers at the time of request.
};
map<uint256, pair<NodeId, list<QueuedBlock>::iterator> > mapBlocksInFlight;
- /** Number of blocks in flight with validated headers. */
- int nQueuedValidatedHeaders = 0;
-
/** Number of preferable block download peers. */
int nPreferredDownload = 0;
@@ -212,6 +207,9 @@ namespace {
/** Dirty block file entries. */
set<int> setDirtyFileInfo;
+
+ /** Number of peers from which we're downloading blocks. */
+ int nPeersWithValidatedDownloads = 0;
} // anon namespace
//////////////////////////////////////////////////////////////////////////////
@@ -259,6 +257,8 @@ struct CNodeState {
//! Since when we're stalling block download progress (in microseconds), or 0.
int64_t nStallingSince;
list<QueuedBlock> vBlocksInFlight;
+ //! When the first entry in vBlocksInFlight started downloading. Don't care when vBlocksInFlight is empty.
+ int64_t nDownloadingSince;
int nBlocksInFlight;
int nBlocksInFlightValidHeaders;
//! Whether we consider this a preferred download peer.
@@ -276,6 +276,7 @@ struct CNodeState {
pindexBestHeaderSent = NULL;
fSyncStarted = false;
nStallingSince = 0;
+ nDownloadingSince = 0;
nBlocksInFlight = 0;
nBlocksInFlightValidHeaders = 0;
fPreferredDownload = false;
@@ -310,12 +311,6 @@ void UpdatePreferredDownload(CNode* node, CNodeState* state)
nPreferredDownload += state->fPreferredDownload;
}
-// Returns time at which to timeout block request (nTime in microseconds)
-int64_t GetBlockTimeout(int64_t nTime, int nValidatedQueuedBefore, const Consensus::Params &consensusParams)
-{
- return nTime + 500000 * consensusParams.nPowTargetSpacing * (4 + nValidatedQueuedBefore);
-}
-
void InitializeNode(NodeId nodeid, const CNode *pnode) {
LOCK(cs_main);
CNodeState &state = mapNodeState.insert(std::make_pair(nodeid, CNodeState())).first->second;
@@ -335,13 +330,21 @@ void FinalizeNode(NodeId nodeid) {
}
BOOST_FOREACH(const QueuedBlock& entry, state->vBlocksInFlight) {
- nQueuedValidatedHeaders -= entry.fValidatedHeaders;
mapBlocksInFlight.erase(entry.hash);
}
EraseOrphansFor(nodeid);
nPreferredDownload -= state->fPreferredDownload;
+ nPeersWithValidatedDownloads -= (state->nBlocksInFlightValidHeaders != 0);
+ assert(nPeersWithValidatedDownloads >= 0);
mapNodeState.erase(nodeid);
+
+ if (mapNodeState.empty()) {
+ // Do a consistency check after the last peer is removed.
+ assert(mapBlocksInFlight.empty());
+ assert(nPreferredDownload == 0);
+ assert(nPeersWithValidatedDownloads == 0);
+ }
}
// Requires cs_main.
@@ -350,8 +353,15 @@ bool MarkBlockAsReceived(const uint256& hash) {
map<uint256, pair<NodeId, list<QueuedBlock>::iterator> >::iterator itInFlight = mapBlocksInFlight.find(hash);
if (itInFlight != mapBlocksInFlight.end()) {
CNodeState *state = State(itInFlight->second.first);
- nQueuedValidatedHeaders -= itInFlight->second.second->fValidatedHeaders;
state->nBlocksInFlightValidHeaders -= itInFlight->second.second->fValidatedHeaders;
+ if (state->nBlocksInFlightValidHeaders == 0 && itInFlight->second.second->fValidatedHeaders) {
+ // Last validated block on the queue was received.
+ nPeersWithValidatedDownloads--;
+ }
+ if (state->vBlocksInFlight.begin() == itInFlight->second.second) {
+ // First block on the queue was received, update the start download time for the next one
+ state->nDownloadingSince = std::max(state->nDownloadingSince, GetTimeMicros());
+ }
state->vBlocksInFlight.erase(itInFlight->second.second);
state->nBlocksInFlight--;
state->nStallingSince = 0;
@@ -369,12 +379,17 @@ void MarkBlockAsInFlight(NodeId nodeid, const uint256& hash, const Consensus::Pa
// Make sure it's not listed somewhere already.
MarkBlockAsReceived(hash);
- int64_t nNow = GetTimeMicros();
- QueuedBlock newentry = {hash, pindex, nNow, pindex != NULL, GetBlockTimeout(nNow, nQueuedValidatedHeaders, consensusParams)};
- nQueuedValidatedHeaders += newentry.fValidatedHeaders;
+ QueuedBlock newentry = {hash, pindex, pindex != NULL};
list<QueuedBlock>::iterator it = state->vBlocksInFlight.insert(state->vBlocksInFlight.end(), newentry);
state->nBlocksInFlight++;
state->nBlocksInFlightValidHeaders += newentry.fValidatedHeaders;
+ if (state->nBlocksInFlight == 1) {
+ // We're starting a block download (batch) from this peer.
+ state->nDownloadingSince = GetTimeMicros();
+ }
+ if (state->nBlocksInFlightValidHeaders == 1 && pindex != NULL) {
+ nPeersWithValidatedDownloads++;
+ }
mapBlocksInFlight[hash] = std::make_pair(nodeid, it);
}
@@ -1010,6 +1025,14 @@ bool AcceptToMemoryPoolWorker(CTxMemPool& pool, CValidationState& state, const C
if (fRequireStandard && !IsStandardTx(tx, reason))
return state.DoS(0, false, REJECT_NONSTANDARD, reason);
+ // Don't relay version 2 transactions until CSV is active, and we can be
+ // sure that such transactions will be mined (unless we're on
+ // -testnet/-regtest).
+ const CChainParams& chainparams = Params();
+ if (fRequireStandard && tx.nVersion >= 2 && VersionBitsTipState(chainparams.GetConsensus(), Consensus::DEPLOYMENT_CSV) != THRESHOLD_ACTIVE) {
+ return state.DoS(0, false, REJECT_NONSTANDARD, "premature-version2-tx");
+ }
+
// Only accept nLockTime-using transactions that can be mined in the next
// block; we don't want our mempool filled up with transactions that can't
// be mined yet.
@@ -2877,6 +2900,8 @@ bool ActivateBestChain(CValidationState &state, const CChainParams& chainparams,
CBlockIndex *pindexMostWork = NULL;
do {
boost::this_thread::interruption_point();
+ if (ShutdownRequested())
+ break;
CBlockIndex *pindexNewTip = NULL;
const CBlockIndex *pindexFork;
@@ -3894,7 +3919,6 @@ void UnloadBlockIndex()
nBlockSequenceId = 1;
mapBlockSource.clear();
mapBlocksInFlight.clear();
- nQueuedValidatedHeaders = 0;
nPreferredDownload = 0;
setDirtyBlockIndex.clear();
setDirtyFileInfo.clear();
@@ -4475,9 +4499,8 @@ void static ProcessGetData(CNode* pfrom, const Consensus::Params& consensusParam
}
}
-bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, int64_t nTimeReceived)
+bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, int64_t nTimeReceived, const CChainParams& chainparams)
{
- const CChainParams& chainparams = Params();
RandAddSeedPerfmon();
LogPrint("net", "received: %s (%u bytes) peer=%d\n", SanitizeString(strCommand), vRecv.size(), pfrom->id);
if (mapArgs.count("-dropmessagestest") && GetRand(atoi(mapArgs["-dropmessagestest"])) == 0)
@@ -5487,7 +5510,7 @@ bool ProcessMessages(CNode* pfrom)
bool fRet = false;
try
{
- fRet = ProcessMessage(pfrom, strCommand, vRecv, msg.nTime);
+ fRet = ProcessMessage(pfrom, strCommand, vRecv, msg.nTime, chainparams);
boost::this_thread::interruption_point();
}
catch (const std::ios_base::failure& e)
@@ -5811,24 +5834,15 @@ bool SendMessages(CNode* pto)
LogPrintf("Peer=%d is stalling block download, disconnecting\n", pto->id);
pto->fDisconnect = true;
}
- // In case there is a block that has been in flight from this peer for (2 + 0.5 * N) times the block interval
- // (with N the number of validated blocks that were in flight at the time it was requested), disconnect due to
- // timeout. We compensate for in-flight blocks to prevent killing off peers due to our own downstream link
+ // In case there is a block that has been in flight from this peer for 2 + 0.5 * N times the block interval
+ // (with N the number of peers from which we're downloading validated blocks), disconnect due to timeout.
+ // We compensate for other peers to prevent killing off peers due to our own downstream link
// being saturated. We only count validated in-flight blocks so peers can't advertise non-existing block hashes
// to unreasonably increase our timeout.
- // We also compare the block download timeout originally calculated against the time at which we'd disconnect
- // if we assumed the block were being requested now (ignoring blocks we've requested from this peer, since we're
- // only looking at this peer's oldest request). This way a large queue in the past doesn't result in a
- // permanently large window for this block to be delivered (ie if the number of blocks in flight is decreasing
- // more quickly than once every 5 minutes, then we'll shorten the download window for this block).
if (!pto->fDisconnect && state.vBlocksInFlight.size() > 0) {
QueuedBlock &queuedBlock = state.vBlocksInFlight.front();
- int64_t nTimeoutIfRequestedNow = GetBlockTimeout(nNow, nQueuedValidatedHeaders - state.nBlocksInFlightValidHeaders, consensusParams);
- if (queuedBlock.nTimeDisconnect > nTimeoutIfRequestedNow) {
- LogPrint("net", "Reducing block download timeout for peer=%d block=%s, orig=%d new=%d\n", pto->id, queuedBlock.hash.ToString(), queuedBlock.nTimeDisconnect, nTimeoutIfRequestedNow);
- queuedBlock.nTimeDisconnect = nTimeoutIfRequestedNow;
- }
- if (queuedBlock.nTimeDisconnect < nNow) {
+ int nOtherPeersWithValidatedDownloads = nPeersWithValidatedDownloads - (state.nBlocksInFlightValidHeaders > 0);
+ if (nNow > state.nDownloadingSince + consensusParams.nPowTargetSpacing * (BLOCK_DOWNLOAD_TIMEOUT_BASE + BLOCK_DOWNLOAD_TIMEOUT_PER_PEER * nOtherPeersWithValidatedDownloads)) {
LogPrintf("Timeout downloading block %s from peer=%d, disconnecting\n", queuedBlock.hash.ToString(), pto->id);
pto->fDisconnect = true;
}
diff --git a/src/main.h b/src/main.h
index 0bfcfab213..0962f44e94 100644
--- a/src/main.h
+++ b/src/main.h
@@ -106,6 +106,10 @@ static const unsigned int AVG_INVENTORY_BROADCAST_INTERVAL = 5;
static const unsigned int AVG_FEEFILTER_BROADCAST_INTERVAL = 10 * 60;
/** Maximum feefilter broadcast delay after significant change. */
static const unsigned int MAX_FEEFILTER_CHANGE_DELAY = 5 * 60;
+/** Block download timeout base, expressed in millionths of the block interval (i.e. 10 min) */
+static const int64_t BLOCK_DOWNLOAD_TIMEOUT_BASE = 1000000;
+/** Additional block download timeout per parallel downloading peer (i.e. 5 min) */
+static const int64_t BLOCK_DOWNLOAD_TIMEOUT_PER_PEER = 500000;
static const unsigned int DEFAULT_LIMITFREERELAY = 15;
static const bool DEFAULT_RELAYPRIORITY = true;
@@ -469,13 +473,13 @@ bool TestBlockValidity(CValidationState& state, const CChainParams& chainparams,
class CBlockFileInfo
{
public:
- unsigned int nBlocks; //! number of blocks stored in file
- unsigned int nSize; //! number of used bytes of block file
- unsigned int nUndoSize; //! number of used bytes in the undo file
- unsigned int nHeightFirst; //! lowest height of block in file
- unsigned int nHeightLast; //! highest height of block in file
- uint64_t nTimeFirst; //! earliest time of block in file
- uint64_t nTimeLast; //! latest time of block in file
+ unsigned int nBlocks; //!< number of blocks stored in file
+ unsigned int nSize; //!< number of used bytes of block file
+ unsigned int nUndoSize; //!< number of used bytes in the undo file
+ unsigned int nHeightFirst; //!< lowest height of block in file
+ unsigned int nHeightLast; //!< highest height of block in file
+ uint64_t nTimeFirst; //!< earliest time of block in file
+ uint64_t nTimeLast; //!< latest time of block in file
ADD_SERIALIZE_METHODS;
diff --git a/src/netbase.cpp b/src/netbase.cpp
index 7f79dd02c6..281c6bcb7f 100644
--- a/src/netbase.cpp
+++ b/src/netbase.cpp
@@ -170,7 +170,8 @@ bool static LookupIntern(const char *pszName, std::vector<CNetAddr>& vIP, unsign
if (aiTrav->ai_family == AF_INET6)
{
assert(aiTrav->ai_addrlen >= sizeof(sockaddr_in6));
- vIP.push_back(CNetAddr(((struct sockaddr_in6*)(aiTrav->ai_addr))->sin6_addr));
+ struct sockaddr_in6* s6 = (struct sockaddr_in6*) aiTrav->ai_addr;
+ vIP.push_back(CNetAddr(s6->sin6_addr, s6->sin6_scope_id));
}
aiTrav = aiTrav->ai_next;
@@ -629,6 +630,7 @@ bool ConnectSocketByName(CService &addr, SOCKET& hSocketRet, const char *pszDest
void CNetAddr::Init()
{
memset(ip, 0, sizeof(ip));
+ scopeId = 0;
}
void CNetAddr::SetIP(const CNetAddr& ipIn)
@@ -678,9 +680,10 @@ CNetAddr::CNetAddr(const struct in_addr& ipv4Addr)
SetRaw(NET_IPV4, (const uint8_t*)&ipv4Addr);
}
-CNetAddr::CNetAddr(const struct in6_addr& ipv6Addr)
+CNetAddr::CNetAddr(const struct in6_addr& ipv6Addr, const uint32_t scope)
{
SetRaw(NET_IPV6, (const uint8_t*)&ipv6Addr);
+ scopeId = scope;
}
CNetAddr::CNetAddr(const char *pszIp, bool fAllowLookup)
@@ -1099,7 +1102,7 @@ CService::CService(const struct sockaddr_in& addr) : CNetAddr(addr.sin_addr), po
assert(addr.sin_family == AF_INET);
}
-CService::CService(const struct sockaddr_in6 &addr) : CNetAddr(addr.sin6_addr), port(ntohs(addr.sin6_port))
+CService::CService(const struct sockaddr_in6 &addr) : CNetAddr(addr.sin6_addr, addr.sin6_scope_id), port(ntohs(addr.sin6_port))
{
assert(addr.sin6_family == AF_INET6);
}
@@ -1192,6 +1195,7 @@ bool CService::GetSockAddr(struct sockaddr* paddr, socklen_t *addrlen) const
memset(paddrin6, 0, *addrlen);
if (!GetIn6Addr(&paddrin6->sin6_addr))
return false;
+ paddrin6->sin6_scope_id = scopeId;
paddrin6->sin6_family = AF_INET6;
paddrin6->sin6_port = htons(port);
return true;
diff --git a/src/netbase.h b/src/netbase.h
index 1db66ac27f..db736154fa 100644
--- a/src/netbase.h
+++ b/src/netbase.h
@@ -44,6 +44,7 @@ class CNetAddr
{
protected:
unsigned char ip[16]; // in network byte order
+ uint32_t scopeId; // for scoped/link-local ipv6 addresses
public:
CNetAddr();
@@ -89,7 +90,7 @@ class CNetAddr
std::vector<unsigned char> GetGroup() const;
int GetReachabilityFrom(const CNetAddr *paddrPartner = NULL) const;
- CNetAddr(const struct in6_addr& pipv6Addr);
+ CNetAddr(const struct in6_addr& pipv6Addr, const uint32_t scope = 0);
bool GetIn6Addr(struct in6_addr* pipv6Addr) const;
friend bool operator==(const CNetAddr& a, const CNetAddr& b);
diff --git a/src/policy/fees.h b/src/policy/fees.h
index cdd984de7d..463f62f710 100644
--- a/src/policy/fees.h
+++ b/src/policy/fees.h
@@ -265,8 +265,8 @@ public:
void Read(CAutoFile& filein);
private:
- CFeeRate minTrackedFee; //! Passed to constructor to avoid dependency on main
- double minTrackedPriority; //! Set to AllowFreeThreshold
+ CFeeRate minTrackedFee; //!< Passed to constructor to avoid dependency on main
+ double minTrackedPriority; //!< Set to AllowFreeThreshold
unsigned int nBestSeenHeight;
struct TxStatsInfo
{
diff --git a/src/policy/policy.cpp b/src/policy/policy.cpp
index e3ed7be000..d1a15451dc 100644
--- a/src/policy/policy.cpp
+++ b/src/policy/policy.cpp
@@ -73,12 +73,12 @@ bool IsStandardTx(const CTransaction& tx, std::string& reason)
BOOST_FOREACH(const CTxIn& txin, tx.vin)
{
// Biggest 'standard' txin is a 15-of-15 P2SH multisig with compressed
- // keys. (remember the 520 byte limit on redeemScript size) That works
+ // keys (remember the 520 byte limit on redeemScript size). That works
// out to a (15*(33+1))+3=513 byte redeemScript, 513+1+15*(73+1)+3=1627
// bytes of scriptSig, which we round off to 1650 bytes for some minor
// future-proofing. That's also enough to spend a 20-of-20
// CHECKMULTISIG scriptPubKey, though such a scriptPubKey is not
- // considered standard)
+ // considered standard.
if (txin.scriptSig.size() > 1650) {
reason = "scriptsig-size";
return false;
diff --git a/src/qt/bitcoin.qrc b/src/qt/bitcoin.qrc
index dcd3b4ae2c..24b0bae3ec 100644
--- a/src/qt/bitcoin.qrc
+++ b/src/qt/bitcoin.qrc
@@ -49,6 +49,7 @@
<file alias="fontbigger">res/icons/fontbigger.png</file>
<file alias="fontsmaller">res/icons/fontsmaller.png</file>
<file alias="prompticon">res/icons/chevron.png</file>
+ <file alias="transaction_abandoned">res/icons/transaction_abandoned.png</file>
</qresource>
<qresource prefix="/movies">
<file alias="spinner-000">res/movies/spinner-000.png</file>
diff --git a/src/qt/guiconstants.h b/src/qt/guiconstants.h
index 5ceffcd70a..4b2c10dd48 100644
--- a/src/qt/guiconstants.h
+++ b/src/qt/guiconstants.h
@@ -29,6 +29,8 @@ static const bool DEFAULT_SPLASHSCREEN = true;
#define COLOR_TX_STATUS_OPENUNTILDATE QColor(64, 64, 255)
/* Transaction list -- TX status decoration - offline */
#define COLOR_TX_STATUS_OFFLINE QColor(192, 192, 192)
+/* Transaction list -- TX status decoration - danger, tx needs attention */
+#define COLOR_TX_STATUS_DANGER QColor(200, 100, 100)
/* Transaction list -- TX status decoration - default color */
#define COLOR_BLACK QColor(0, 0, 0)
diff --git a/src/qt/res/icons/transaction_abandoned.png b/src/qt/res/icons/transaction_abandoned.png
new file mode 100644
index 0000000000..8ca6445c20
--- /dev/null
+++ b/src/qt/res/icons/transaction_abandoned.png
Binary files differ
diff --git a/src/qt/transactiondesc.cpp b/src/qt/transactiondesc.cpp
index 5abefc144e..bae0cbd1c8 100644
--- a/src/qt/transactiondesc.cpp
+++ b/src/qt/transactiondesc.cpp
@@ -39,7 +39,7 @@ QString TransactionDesc::FormatTxStatus(const CWalletTx& wtx)
else if (GetAdjustedTime() - wtx.nTimeReceived > 2 * 60 && wtx.GetRequestCount() == 0)
return tr("%1/offline").arg(nDepth);
else if (nDepth == 0)
- return tr("0/unconfirmed, %1").arg((wtx.InMempool() ? tr("in memory pool") : tr("not in memory pool")));
+ return tr("0/unconfirmed, %1").arg((wtx.InMempool() ? tr("in memory pool") : tr("not in memory pool"))) + (wtx.isAbandoned() ? ", "+tr("abandoned") : "");
else if (nDepth < 6)
return tr("%1/unconfirmed").arg(nDepth);
else
diff --git a/src/qt/transactionrecord.cpp b/src/qt/transactionrecord.cpp
index 97b77cc93d..4fe47181f6 100644
--- a/src/qt/transactionrecord.cpp
+++ b/src/qt/transactionrecord.cpp
@@ -239,6 +239,8 @@ void TransactionRecord::updateStatus(const CWalletTx &wtx)
else if (status.depth == 0)
{
status.status = TransactionStatus::Unconfirmed;
+ if (wtx.isAbandoned())
+ status.status = TransactionStatus::Abandoned;
}
else if (status.depth < RecommendedNumConfirmations)
{
diff --git a/src/qt/transactionrecord.h b/src/qt/transactionrecord.h
index 95ab98c10d..8c754c3aad 100644
--- a/src/qt/transactionrecord.h
+++ b/src/qt/transactionrecord.h
@@ -33,6 +33,7 @@ public:
Unconfirmed, /**< Not yet mined into a block **/
Confirming, /**< Confirmed, but waiting for the recommended number of confirmations **/
Conflicted, /**< Conflicts with other transaction or mempool **/
+ Abandoned, /**< Abandoned from the wallet **/
/// Generated (mined) transactions
Immature, /**< Mined but waiting for maturity */
MaturesWarning, /**< Transaction will likely not mature because no nodes have confirmed */
diff --git a/src/qt/transactiontablemodel.cpp b/src/qt/transactiontablemodel.cpp
index d2a52b3022..b29ecf8348 100644
--- a/src/qt/transactiontablemodel.cpp
+++ b/src/qt/transactiontablemodel.cpp
@@ -312,6 +312,9 @@ QString TransactionTableModel::formatTxStatus(const TransactionRecord *wtx) cons
case TransactionStatus::Unconfirmed:
status = tr("Unconfirmed");
break;
+ case TransactionStatus::Abandoned:
+ status = tr("Abandoned");
+ break;
case TransactionStatus::Confirming:
status = tr("Confirming (%1 of %2 recommended confirmations)").arg(wtx->status.depth).arg(TransactionRecord::RecommendedNumConfirmations);
break;
@@ -468,6 +471,8 @@ QVariant TransactionTableModel::txStatusDecoration(const TransactionRecord *wtx)
return COLOR_TX_STATUS_OFFLINE;
case TransactionStatus::Unconfirmed:
return QIcon(":/icons/transaction_0");
+ case TransactionStatus::Abandoned:
+ return QIcon(":/icons/transaction_abandoned");
case TransactionStatus::Confirming:
switch(wtx->status.depth)
{
@@ -573,6 +578,11 @@ QVariant TransactionTableModel::data(const QModelIndex &index, int role) const
case Qt::TextAlignmentRole:
return column_alignments[index.column()];
case Qt::ForegroundRole:
+ // Use the "danger" color for abandoned transactions
+ if(rec->status.status == TransactionStatus::Abandoned)
+ {
+ return COLOR_TX_STATUS_DANGER;
+ }
// Non-confirmed (but not immature) as transactions are grey
if(!rec->status.countsForBalance && rec->status.status != TransactionStatus::Immature)
{
diff --git a/src/qt/transactionview.cpp b/src/qt/transactionview.cpp
index a4d4c7a35f..a352228c36 100644
--- a/src/qt/transactionview.cpp
+++ b/src/qt/transactionview.cpp
@@ -37,7 +37,7 @@
TransactionView::TransactionView(const PlatformStyle *platformStyle, QWidget *parent) :
QWidget(parent), model(0), transactionProxyModel(0),
- transactionView(0)
+ transactionView(0), abandonAction(0)
{
// Build filter row
setContentsMargins(0,0,0,0);
@@ -137,6 +137,7 @@ TransactionView::TransactionView(const PlatformStyle *platformStyle, QWidget *pa
transactionView = view;
// Actions
+ abandonAction = new QAction(tr("Abandon transaction"), this);
QAction *copyAddressAction = new QAction(tr("Copy address"), this);
QAction *copyLabelAction = new QAction(tr("Copy label"), this);
QAction *copyAmountAction = new QAction(tr("Copy amount"), this);
@@ -153,8 +154,10 @@ TransactionView::TransactionView(const PlatformStyle *platformStyle, QWidget *pa
contextMenu->addAction(copyTxIDAction);
contextMenu->addAction(copyTxHexAction);
contextMenu->addAction(copyTxPlainText);
- contextMenu->addAction(editLabelAction);
contextMenu->addAction(showDetailsAction);
+ contextMenu->addSeparator();
+ contextMenu->addAction(abandonAction);
+ contextMenu->addAction(editLabelAction);
mapperThirdPartyTxUrls = new QSignalMapper(this);
@@ -170,6 +173,7 @@ TransactionView::TransactionView(const PlatformStyle *platformStyle, QWidget *pa
connect(view, SIGNAL(doubleClicked(QModelIndex)), this, SIGNAL(doubleClicked(QModelIndex)));
connect(view, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(contextualMenu(QPoint)));
+ connect(abandonAction, SIGNAL(triggered()), this, SLOT(abandonTx()));
connect(copyAddressAction, SIGNAL(triggered()), this, SLOT(copyAddress()));
connect(copyLabelAction, SIGNAL(triggered()), this, SLOT(copyLabel()));
connect(copyAmountAction, SIGNAL(triggered()), this, SLOT(copyAmount()));
@@ -360,12 +364,37 @@ void TransactionView::exportClicked()
void TransactionView::contextualMenu(const QPoint &point)
{
QModelIndex index = transactionView->indexAt(point);
+ QModelIndexList selection = transactionView->selectionModel()->selectedRows(0);
+
+ // check if transaction can be abandoned, disable context menu action in case it doesn't
+ uint256 hash;
+ hash.SetHex(selection.at(0).data(TransactionTableModel::TxHashRole).toString().toStdString());
+ abandonAction->setEnabled(model->transactionCanBeAbandoned(hash));
+
if(index.isValid())
{
contextMenu->exec(QCursor::pos());
}
}
+void TransactionView::abandonTx()
+{
+ if(!transactionView || !transactionView->selectionModel())
+ return;
+ QModelIndexList selection = transactionView->selectionModel()->selectedRows(0);
+
+ // get the hash from the TxHashRole (QVariant / QString)
+ uint256 hash;
+ QString hashQStr = selection.at(0).data(TransactionTableModel::TxHashRole).toString();
+ hash.SetHex(hashQStr.toStdString());
+
+ // Abandon the wallet transaction over the walletModel
+ model->abandonTransaction(hash);
+
+ // Update the table
+ model->getTransactionTableModel()->updateTransaction(hashQStr, CT_UPDATED, false);
+}
+
void TransactionView::copyAddress()
{
GUIUtil::copyEntryData(transactionView, 0, TransactionTableModel::AddressRole);
diff --git a/src/qt/transactionview.h b/src/qt/transactionview.h
index 2cfbd471b0..e9b9d5b6bc 100644
--- a/src/qt/transactionview.h
+++ b/src/qt/transactionview.h
@@ -75,6 +75,7 @@ private:
QFrame *dateRangeWidget;
QDateTimeEdit *dateFrom;
QDateTimeEdit *dateTo;
+ QAction *abandonAction;
QWidget *createDateRangeWidget();
@@ -97,6 +98,7 @@ private Q_SLOTS:
void copyTxPlainText();
void openThirdPartyTxUrl(QString url);
void updateWatchOnlyColumn(bool fHaveWatchOnly);
+ void abandonTx();
Q_SIGNALS:
void doubleClicked(const QModelIndex&);
diff --git a/src/qt/walletmodel.cpp b/src/qt/walletmodel.cpp
index cf38c64eb0..ce230d6aed 100644
--- a/src/qt/walletmodel.cpp
+++ b/src/qt/walletmodel.cpp
@@ -668,3 +668,18 @@ bool WalletModel::saveReceiveRequest(const std::string &sAddress, const int64_t
else
return wallet->AddDestData(dest, key, sRequest);
}
+
+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())
+ return false;
+ return true;
+}
+
+bool WalletModel::abandonTransaction(uint256 hash) const
+{
+ LOCK2(cs_main, wallet->cs_wallet);
+ return wallet->AbandonTransaction(hash);
+}
diff --git a/src/qt/walletmodel.h b/src/qt/walletmodel.h
index 7a47eda86f..e5470bf618 100644
--- a/src/qt/walletmodel.h
+++ b/src/qt/walletmodel.h
@@ -200,6 +200,9 @@ public:
void loadReceiveRequests(std::vector<std::string>& vReceiveRequests);
bool saveReceiveRequest(const std::string &sAddress, const int64_t nId, const std::string &sRequest);
+ bool transactionCanBeAbandoned(uint256 hash) const;
+ bool abandonTransaction(uint256 hash) const;
+
private:
CWallet *wallet;
bool fHaveWatchOnly;
diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp
index f1c9d9f7ab..34637b9f7e 100644
--- a/src/rpc/blockchain.cpp
+++ b/src/rpc/blockchain.cpp
@@ -70,6 +70,7 @@ UniValue blockheaderToJSON(const CBlockIndex* blockindex)
result.push_back(Pair("confirmations", confirmations));
result.push_back(Pair("height", blockindex->nHeight));
result.push_back(Pair("version", blockindex->nVersion));
+ result.push_back(Pair("versionHex", strprintf("%08x", blockindex->nVersion)));
result.push_back(Pair("merkleroot", blockindex->hashMerkleRoot.GetHex()));
result.push_back(Pair("time", (int64_t)blockindex->nTime));
result.push_back(Pair("mediantime", (int64_t)blockindex->GetMedianTimePast()));
@@ -98,6 +99,7 @@ UniValue blockToJSON(const CBlock& block, const CBlockIndex* blockindex, bool tx
result.push_back(Pair("size", (int)::GetSerializeSize(block, SER_NETWORK, PROTOCOL_VERSION)));
result.push_back(Pair("height", blockindex->nHeight));
result.push_back(Pair("version", block.nVersion));
+ result.push_back(Pair("versionHex", strprintf("%08x", block.nVersion)));
result.push_back(Pair("merkleroot", block.hashMerkleRoot.GetHex()));
UniValue txs(UniValue::VARR);
BOOST_FOREACH(const CTransaction&tx, block.vtx)
@@ -316,6 +318,7 @@ UniValue getblockheader(const UniValue& params, bool fHelp)
" \"confirmations\" : n, (numeric) The number of confirmations, or -1 if the block is not on the main chain\n"
" \"height\" : n, (numeric) The block height or index\n"
" \"version\" : n, (numeric) The block version\n"
+ " \"versionHex\" : \"00000000\", (string) The block version formatted in hexadecimal\n"
" \"merkleroot\" : \"xxxx\", (string) The merkle root\n"
" \"time\" : ttt, (numeric) The block time in seconds since epoch (Jan 1 1970 GMT)\n"
" \"mediantime\" : ttt, (numeric) The median block time in seconds since epoch (Jan 1 1970 GMT)\n"
@@ -375,6 +378,7 @@ UniValue getblock(const UniValue& params, bool fHelp)
" \"size\" : n, (numeric) The block size\n"
" \"height\" : n, (numeric) The block height or index\n"
" \"version\" : n, (numeric) The block version\n"
+ " \"versionHex\" : \"00000000\", (string) The block version formatted in hexadecimal\n"
" \"merkleroot\" : \"xxxx\", (string) The merkle root\n"
" \"tx\" : [ (array of string) The transaction ids\n"
" \"transactionid\" (string) The transaction id\n"
@@ -608,13 +612,20 @@ static UniValue BIP9SoftForkDesc(const std::string& name, const Consensus::Param
{
UniValue rv(UniValue::VOBJ);
rv.push_back(Pair("id", name));
- switch (VersionBitsTipState(consensusParams, id)) {
+ const ThresholdState thresholdState = VersionBitsTipState(consensusParams, id);
+ switch (thresholdState) {
case THRESHOLD_DEFINED: rv.push_back(Pair("status", "defined")); break;
case THRESHOLD_STARTED: rv.push_back(Pair("status", "started")); break;
case THRESHOLD_LOCKED_IN: rv.push_back(Pair("status", "locked_in")); break;
case THRESHOLD_ACTIVE: rv.push_back(Pair("status", "active")); break;
case THRESHOLD_FAILED: rv.push_back(Pair("status", "failed")); break;
}
+ if (THRESHOLD_STARTED == thresholdState)
+ {
+ rv.push_back(Pair("bit", consensusParams.vDeployments[id].bit));
+ }
+ rv.push_back(Pair("startTime", consensusParams.vDeployments[id].nStartTime));
+ rv.push_back(Pair("timeout", consensusParams.vDeployments[id].nTimeout));
return rv;
}
@@ -653,6 +664,9 @@ UniValue getblockchaininfo(const UniValue& params, bool fHelp)
" {\n"
" \"id\": \"xxxx\", (string) name of the softfork\n"
" \"status\": \"xxxx\", (string) one of \"defined\", \"started\", \"lockedin\", \"active\", \"failed\"\n"
+ " \"bit\": xx, (numeric) the bit, 0-28, in the block version field used to signal this soft fork\n"
+ " \"startTime\": xx, (numeric) the minimum median time past of a block at which the bit gains its meaning\n"
+ " \"timeout\": xx (numeric) the median time past of a block at which the deployment is considered failed if not yet locked in\n"
" }\n"
" ]\n"
"}\n"
diff --git a/src/rpc/client.cpp b/src/rpc/client.cpp
index 89420b93d7..c89af6bfa7 100644
--- a/src/rpc/client.cpp
+++ b/src/rpc/client.cpp
@@ -18,8 +18,8 @@ using namespace std;
class CRPCConvertParam
{
public:
- std::string methodName; //! method whose params want conversion
- int paramIdx; //! 0-based idx of param to convert
+ std::string methodName; //!< method whose params want conversion
+ int paramIdx; //!< 0-based idx of param to convert
};
static const CRPCConvertParam vRPCConvertParams[] =
@@ -30,7 +30,6 @@ static const CRPCConvertParam vRPCConvertParams[] =
{ "generate", 0 },
{ "generate", 1 },
{ "generatetoaddress", 0 },
- { "generatetoaddress", 1 },
{ "generatetoaddress", 2 },
{ "getnetworkhashps", 0 },
{ "getnetworkhashps", 1 },
diff --git a/src/script/interpreter.cpp b/src/script/interpreter.cpp
index 149a4f0156..9c47f7c6c9 100644
--- a/src/script/interpreter.cpp
+++ b/src/script/interpreter.cpp
@@ -1015,12 +1015,12 @@ namespace {
*/
class CTransactionSignatureSerializer {
private:
- const CTransaction &txTo; //! reference to the spending transaction (the one being serialized)
- const CScript &scriptCode; //! output script being consumed
- const unsigned int nIn; //! input index of txTo being signed
- const bool fAnyoneCanPay; //! whether the hashtype has the SIGHASH_ANYONECANPAY flag set
- const bool fHashSingle; //! whether the hashtype is SIGHASH_SINGLE
- const bool fHashNone; //! whether the hashtype is SIGHASH_NONE
+ const CTransaction& txTo; //!< reference to the spending transaction (the one being serialized)
+ const CScript& scriptCode; //!< output script being consumed
+ const unsigned int nIn; //!< input index of txTo being signed
+ const bool fAnyoneCanPay; //!< whether the hashtype has the SIGHASH_ANYONECANPAY flag set
+ const bool fHashSingle; //!< whether the hashtype is SIGHASH_SINGLE
+ const bool fHashNone; //!< whether the hashtype is SIGHASH_NONE
public:
CTransactionSignatureSerializer(const CTransaction &txToIn, const CScript &scriptCodeIn, unsigned int nInIn, int nHashTypeIn) :
diff --git a/src/script/standard.h b/src/script/standard.h
index 64bf010ec1..f348da8e19 100644
--- a/src/script/standard.h
+++ b/src/script/standard.h
@@ -27,7 +27,7 @@ public:
CScriptID(const uint160& in) : uint160(in) {}
};
-static const unsigned int MAX_OP_RETURN_RELAY = 83; //! bytes (+1 for OP_RETURN, +2 for the pushdata opcodes)
+static const unsigned int MAX_OP_RETURN_RELAY = 83; //!< bytes (+1 for OP_RETURN, +2 for the pushdata opcodes)
extern bool fAcceptDatacarrier;
extern unsigned nMaxDatacarrierBytes;
diff --git a/src/test/rpc_tests.cpp b/src/test/rpc_tests.cpp
index 1976ee2cb6..bbda6a48f4 100644
--- a/src/test/rpc_tests.cpp
+++ b/src/test/rpc_tests.cpp
@@ -11,6 +11,7 @@
#include "test/test_bitcoin.h"
#include <boost/algorithm/string.hpp>
+#include <boost/assign/list_of.hpp>
#include <boost/test/unit_test.hpp>
#include <univalue.h>
@@ -308,4 +309,27 @@ BOOST_AUTO_TEST_CASE(rpc_ban)
BOOST_CHECK_EQUAL(adr.get_str(), "2001:4d48:ac57:400:cacf:e9ff:fe1d:9c63/128");
}
+BOOST_AUTO_TEST_CASE(rpc_convert_values_generatetoaddress)
+{
+ UniValue result;
+
+ BOOST_CHECK_NO_THROW(result = RPCConvertValues("generatetoaddress", boost::assign::list_of("101")("mkESjLZW66TmHhiFX8MCaBjrhZ543PPh9a")));
+ BOOST_CHECK_EQUAL(result[0].get_int(), 101);
+ BOOST_CHECK_EQUAL(result[1].get_str(), "mkESjLZW66TmHhiFX8MCaBjrhZ543PPh9a");
+
+ BOOST_CHECK_NO_THROW(result = RPCConvertValues("generatetoaddress", boost::assign::list_of("101")("mhMbmE2tE9xzJYCV9aNC8jKWN31vtGrguU")));
+ BOOST_CHECK_EQUAL(result[0].get_int(), 101);
+ BOOST_CHECK_EQUAL(result[1].get_str(), "mhMbmE2tE9xzJYCV9aNC8jKWN31vtGrguU");
+
+ BOOST_CHECK_NO_THROW(result = RPCConvertValues("generatetoaddress", boost::assign::list_of("1")("mkESjLZW66TmHhiFX8MCaBjrhZ543PPh9a")("9")));
+ BOOST_CHECK_EQUAL(result[0].get_int(), 1);
+ BOOST_CHECK_EQUAL(result[1].get_str(), "mkESjLZW66TmHhiFX8MCaBjrhZ543PPh9a");
+ BOOST_CHECK_EQUAL(result[2].get_int(), 9);
+
+ BOOST_CHECK_NO_THROW(result = RPCConvertValues("generatetoaddress", boost::assign::list_of("1")("mhMbmE2tE9xzJYCV9aNC8jKWN31vtGrguU")("9")));
+ BOOST_CHECK_EQUAL(result[0].get_int(), 1);
+ BOOST_CHECK_EQUAL(result[1].get_str(), "mhMbmE2tE9xzJYCV9aNC8jKWN31vtGrguU");
+ BOOST_CHECK_EQUAL(result[2].get_int(), 9);
+}
+
BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/txmempool.h b/src/txmempool.h
index 9dbb37dad0..de4ba0b371 100644
--- a/src/txmempool.h
+++ b/src/txmempool.h
@@ -74,28 +74,28 @@ class CTxMemPoolEntry
{
private:
CTransaction tx;
- CAmount nFee; //! Cached to avoid expensive parent-transaction lookups
- size_t nTxSize; //! ... and avoid recomputing tx size
- size_t nModSize; //! ... and modified size for priority
- size_t nUsageSize; //! ... and total memory usage
- int64_t nTime; //! Local time when entering the mempool
- double entryPriority; //! Priority when entering the mempool
- unsigned int entryHeight; //! Chain height when entering the mempool
- bool hadNoDependencies; //! Not dependent on any other txs when it entered the mempool
- CAmount inChainInputValue; //! Sum of all txin values that are already in blockchain
- bool spendsCoinbase; //! keep track of transactions that spend a coinbase
- unsigned int sigOpCount; //! Legacy sig ops plus P2SH sig op count
- int64_t feeDelta; //! Used for determining the priority of the transaction for mining in a block
- LockPoints lockPoints; //! Track the height and time at which tx was final
+ CAmount nFee; //!< Cached to avoid expensive parent-transaction lookups
+ size_t nTxSize; //!< ... and avoid recomputing tx size
+ size_t nModSize; //!< ... and modified size for priority
+ size_t nUsageSize; //!< ... and total memory usage
+ int64_t nTime; //!< Local time when entering the mempool
+ double entryPriority; //!< Priority when entering the mempool
+ unsigned int entryHeight; //!< Chain height when entering the mempool
+ bool hadNoDependencies; //!< Not dependent on any other txs when it entered the mempool
+ CAmount inChainInputValue; //!< Sum of all txin values that are already in blockchain
+ bool spendsCoinbase; //!< keep track of transactions that spend a coinbase
+ unsigned int sigOpCount; //!< Legacy sig ops plus P2SH sig op count
+ int64_t feeDelta; //!< Used for determining the priority of the transaction for mining in a block
+ LockPoints lockPoints; //!< Track the height and time at which tx was final
// Information about descendants of this transaction that are in the
// mempool; if we remove this transaction we must remove all of these
// descendants as well. if nCountWithDescendants is 0, treat this entry as
// dirty, and nSizeWithDescendants and nModFeesWithDescendants will not be
// correct.
- uint64_t nCountWithDescendants; //! number of descendant transactions
- uint64_t nSizeWithDescendants; //! ... and size
- CAmount nModFeesWithDescendants; //! ... and total fees (all including us)
+ uint64_t nCountWithDescendants; //!< number of descendant transactions
+ uint64_t nSizeWithDescendants; //!< ... and size
+ CAmount nModFeesWithDescendants; //!< ... and total fees (all including us)
// Analogous statistics for ancestor transactions
uint64_t nCountWithAncestors;
@@ -399,18 +399,18 @@ public:
class CTxMemPool
{
private:
- uint32_t nCheckFrequency; //! Value n means that n times in 2^32 we check.
+ uint32_t nCheckFrequency; //!< Value n means that n times in 2^32 we check.
unsigned int nTransactionsUpdated;
CBlockPolicyEstimator* minerPolicyEstimator;
- uint64_t totalTxSize; //! sum of all mempool tx' byte sizes
- uint64_t cachedInnerUsage; //! sum of dynamic memory usage of all the map elements (NOT the maps themselves)
+ uint64_t totalTxSize; //!< sum of all mempool tx' byte sizes
+ uint64_t cachedInnerUsage; //!< sum of dynamic memory usage of all the map elements (NOT the maps themselves)
CFeeRate minReasonableRelayFee;
mutable int64_t lastRollingFeeUpdate;
mutable bool blockSinceLastRollingFeeBump;
- mutable double rollingMinimumFeeRate; //! minimum fee to get into the pool, decreases exponentially
+ mutable double rollingMinimumFeeRate; //!< minimum fee to get into the pool, decreases exponentially
void trackPackageRemoved(const CFeeRate& rate);
diff --git a/src/utiltime.cpp b/src/utiltime.cpp
index 91b40d9991..da590f8889 100644
--- a/src/utiltime.cpp
+++ b/src/utiltime.cpp
@@ -14,7 +14,7 @@
using namespace std;
-static int64_t nMockTime = 0; //! For unit testing
+static int64_t nMockTime = 0; //!< For unit testing
int64_t GetTime()
{
diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h
index 867f33a7b5..96d5d4e1e0 100644
--- a/src/wallet/wallet.h
+++ b/src/wallet/wallet.h
@@ -228,11 +228,11 @@ public:
mapValue_t mapValue;
std::vector<std::pair<std::string, std::string> > vOrderForm;
unsigned int fTimeReceivedIsTxTime;
- unsigned int nTimeReceived; //! time received by this node
+ unsigned int nTimeReceived; //!< time received by this node
unsigned int nTimeSmart;
char fFromMe;
std::string strFromAccount;
- int64_t nOrderPos; //! position in ordered transaction list
+ int64_t nOrderPos; //!< position in ordered transaction list
// memory only
mutable bool fDebitCached;
@@ -324,7 +324,7 @@ public:
}
READWRITE(*(CMerkleTx*)this);
- std::vector<CMerkleTx> vUnused; //! Used to be vtxPrev
+ std::vector<CMerkleTx> vUnused; //!< Used to be vtxPrev
READWRITE(vUnused);
READWRITE(mapValue);
READWRITE(vOrderForm);
@@ -465,7 +465,7 @@ public:
std::string strOtherAccount;
std::string strComment;
mapValue_t mapValue;
- int64_t nOrderPos; //! position in ordered transaction list
+ int64_t nOrderPos; //!< position in ordered transaction list
uint64_t nEntryNo;
CAccountingEntry()