aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/chainparams.cpp3
-rw-r--r--src/chainparams.h2
-rw-r--r--src/clientversion.h2
-rw-r--r--src/init.cpp26
-rw-r--r--src/main.cpp16
-rw-r--r--src/main.h2
-rw-r--r--src/net.cpp2
-rw-r--r--src/netbase.cpp2
-rw-r--r--src/policy/fees.cpp2
-rw-r--r--src/policy/fees.h6
-rw-r--r--src/qt/clientmodel.cpp2
-rw-r--r--src/qt/coincontroldialog.cpp6
-rw-r--r--src/qt/sendcoinsdialog.cpp8
-rw-r--r--src/qt/transactionview.cpp2
-rw-r--r--src/rpcblockchain.cpp8
-rw-r--r--src/rpcrawtransaction.cpp2
-rw-r--r--src/rpcserver.cpp1
-rw-r--r--src/rpcserver.h1
-rw-r--r--src/test/merkle_tests.cpp2
-rw-r--r--src/torcontrol.cpp14
-rw-r--r--src/wallet/db.cpp2
-rw-r--r--src/wallet/rpcwallet.cpp49
-rw-r--r--src/wallet/wallet.cpp121
-rw-r--r--src/wallet/wallet.h14
-rw-r--r--src/wallet/wallet_ismine.h2
-rw-r--r--src/wallet/walletdb.cpp5
26 files changed, 222 insertions, 80 deletions
diff --git a/src/chainparams.cpp b/src/chainparams.cpp
index 9cf99492c..b962f6ac0 100644
--- a/src/chainparams.cpp
+++ b/src/chainparams.cpp
@@ -92,7 +92,6 @@ public:
pchMessageStart[3] = 0xd9;
vAlertPubKey = ParseHex("04fc9702847840aaf195de8442ebecedf5b095cdbb9bc716bda9110971b28a49e0ead8564ff0db22209e0374782c093bb899692d524e9d6a6956e7c5ecbcd68284");
nDefaultPort = 8333;
- nMaxTipAge = 24 * 60 * 60;
nPruneAfterHeight = 100000;
genesis = CreateGenesisBlock(1231006505, 2083236893, 0x1d00ffff, 1, 50 * COIN);
@@ -169,7 +168,6 @@ public:
pchMessageStart[3] = 0x07;
vAlertPubKey = ParseHex("04302390343f91cc401d56d68b123028bf52e5fca1939df127f63c6467cdf9c8e2c14b61104cf817d0b780da337893ecc4aaff1309e536162dabbdb45200ca2b0a");
nDefaultPort = 18333;
- nMaxTipAge = 0x7fffffff;
nPruneAfterHeight = 1000;
genesis = CreateGenesisBlock(1296688602, 414098458, 0x1d00ffff, 1, 50 * COIN);
@@ -232,7 +230,6 @@ public:
pchMessageStart[1] = 0xbf;
pchMessageStart[2] = 0xb5;
pchMessageStart[3] = 0xda;
- nMaxTipAge = 24 * 60 * 60;
nDefaultPort = 18444;
nPruneAfterHeight = 1000;
diff --git a/src/chainparams.h b/src/chainparams.h
index fdf5c17a0..88bc66676 100644
--- a/src/chainparams.h
+++ b/src/chainparams.h
@@ -64,7 +64,6 @@ public:
bool DefaultConsistencyChecks() const { return fDefaultConsistencyChecks; }
/** Policy: Filter transactions that do not match well-defined patterns */
bool RequireStandard() const { return fRequireStandard; }
- int64_t MaxTipAge() const { return nMaxTipAge; }
uint64_t PruneAfterHeight() const { return nPruneAfterHeight; }
/** Make miner stop after a block is found. In RPC, don't return until nGenProcLimit blocks are generated */
bool MineBlocksOnDemand() const { return fMineBlocksOnDemand; }
@@ -84,7 +83,6 @@ protected:
//! Raw pub key bytes for the broadcast alert signing key.
std::vector<unsigned char> vAlertPubKey;
int nDefaultPort;
- long nMaxTipAge;
uint64_t nPruneAfterHeight;
std::vector<CDNSSeedData> vSeeds;
std::vector<unsigned char> base58Prefixes[MAX_BASE58_TYPES];
diff --git a/src/clientversion.h b/src/clientversion.h
index c832663a7..40361660e 100644
--- a/src/clientversion.h
+++ b/src/clientversion.h
@@ -26,7 +26,7 @@
* Copyright year (2009-this)
* Todo: update this when changing our copyright comments in the source
*/
-#define COPYRIGHT_YEAR 2015
+#define COPYRIGHT_YEAR 2016
#endif //HAVE_CONFIG_H
diff --git a/src/init.cpp b/src/init.cpp
index 220df5ebf..0a0e58776 100644
--- a/src/init.cpp
+++ b/src/init.cpp
@@ -312,7 +312,8 @@ std::string HelpMessage(HelpMessageMode mode)
// When adding new options to the categories, please keep and ensure alphabetical ordering.
// Do not translate _(...) -help-debug options, Many technical terms, and only a very small audience, so is unnecessary stress to translators.
string strUsage = HelpMessageGroup(_("Options:"));
- strUsage += HelpMessageOpt("-?", _("This help message"));
+ strUsage += HelpMessageOpt("-?", _("Print this help message and exit"));
+ strUsage += HelpMessageOpt("-version", _("Print version and exit"));
strUsage += HelpMessageOpt("-alerts", strprintf(_("Receive and display P2P network alerts (default: %u)"), DEFAULT_ALERTS));
strUsage += HelpMessageOpt("-alertnotify=<cmd>", _("Execute command when a relevant alert is received or we see a really long fork (%s in cmd is replaced by message)"));
strUsage += HelpMessageOpt("-blocknotify=<cmd>", _("Execute command when the best block changes (%s in cmd is replaced by block hash)"));
@@ -393,6 +394,8 @@ std::string HelpMessage(HelpMessageMode mode)
strUsage += HelpMessageGroup(_("Wallet options:"));
strUsage += HelpMessageOpt("-disablewallet", _("Do not load the wallet and disable wallet RPC calls"));
strUsage += HelpMessageOpt("-keypool=<n>", strprintf(_("Set key pool size to <n> (default: %u)"), DEFAULT_KEYPOOL_SIZE));
+ strUsage += HelpMessageOpt("-fallbackfee=<amt>", strprintf(_("A fee rate (in %s/kB) that will be used when fee estimation has insufficient data (default: %s)"),
+ CURRENCY_UNIT, FormatMoney(DEFAULT_FALLBACK_FEE)));
strUsage += HelpMessageOpt("-mintxfee=<amt>", strprintf(_("Fees (in %s/kB) smaller than this are considered zero fee for transaction creation (default: %s)"),
CURRENCY_UNIT, FormatMoney(DEFAULT_TRANSACTION_MINFEE)));
strUsage += HelpMessageOpt("-paytxfee=<amt>", strprintf(_("Fee (in %s/kB) to add to transactions you send (default: %s)"),
@@ -421,8 +424,11 @@ std::string HelpMessage(HelpMessageMode mode)
#endif
strUsage += HelpMessageGroup(_("Debugging/Testing options:"));
+ strUsage += HelpMessageOpt("-uacomment=<cmt>", _("Append comment to the user agent string"));
if (showDebug)
{
+ strUsage += HelpMessageOpt("-checkblockindex", strprintf("Do a full consistency check for mapBlockIndex, setBlockIndexCandidates, chainActive and mapBlocksUnlinked occasionally. Also sets -checkmempool (default: %u)", Params(CBaseChainParams::MAIN).DefaultConsistencyChecks()));
+ strUsage += HelpMessageOpt("-checkmempool=<n>", strprintf("Run checks every <n> transactions (default: %u)", Params(CBaseChainParams::MAIN).DefaultConsistencyChecks()));
strUsage += HelpMessageOpt("-checkpoints", strprintf("Disable expensive verification for known chain history (default: %u)", DEFAULT_CHECKPOINTS_ENABLED));
#ifdef ENABLE_WALLET
strUsage += HelpMessageOpt("-dblogsize=<n>", strprintf("Flush wallet database activity from memory to disk log every <n> megabytes (default: %u)", DEFAULT_WALLET_DBLOGSIZE));
@@ -445,6 +451,8 @@ std::string HelpMessage(HelpMessageMode mode)
debugCategories += ", qt";
strUsage += HelpMessageOpt("-debug=<category>", strprintf(_("Output debugging information (default: %u, supplying <category> is optional)"), 0) + ". " +
_("If <category> is not supplied or if <category> = 1, output all debugging information.") + _("<category> can be:") + " " + debugCategories + ".");
+ if (showDebug)
+ strUsage += HelpMessageOpt("-nodebug", "Turn off debugging messages, same as -debug=0");
strUsage += HelpMessageOpt("-gen", strprintf(_("Generate coins (default: %u)"), DEFAULT_GENERATE));
strUsage += HelpMessageOpt("-genproclimit=<n>", strprintf(_("Set the number of threads for coin generation if enabled (-1 = all cores, default: %d)"), DEFAULT_GENERATE_THREADS));
strUsage += HelpMessageOpt("-help-debug", _("Show all debugging options (usage: --help -help-debug)"));
@@ -453,9 +461,11 @@ std::string HelpMessage(HelpMessageMode mode)
if (showDebug)
{
strUsage += HelpMessageOpt("-logtimemicros", strprintf("Add microsecond precision to debug timestamps (default: %u)", DEFAULT_LOGTIMEMICROS));
+ strUsage += HelpMessageOpt("-mocktime=<n>", "Replace actual time with <n> seconds since epoch (default: 0)");
strUsage += HelpMessageOpt("-limitfreerelay=<n>", strprintf("Continuously rate-limit free transactions to <n>*1000 bytes per minute (default: %u)", DEFAULT_LIMITFREERELAY));
strUsage += HelpMessageOpt("-relaypriority", strprintf("Require high priority for relaying free or low-fee transactions (default: %u)", DEFAULT_RELAYPRIORITY));
strUsage += HelpMessageOpt("-maxsigcachesize=<n>", strprintf("Limit size of signature cache to <n> MiB (default: %u)", DEFAULT_MAX_SIG_CACHE_SIZE));
+ strUsage += HelpMessageOpt("-maxtipage=<n>", strprintf("Maximum tip age in seconds to consider node in initial block download (default: %u)", DEFAULT_MAX_TIP_AGE));
}
strUsage += HelpMessageOpt("-minrelaytxfee=<amt>", strprintf(_("Fees (in %s/kB) smaller than this are considered zero fee for relaying, mining and transaction creation (default: %s)"),
CURRENCY_UNIT, FormatMoney(DEFAULT_MIN_RELAY_TX_FEE)));
@@ -489,6 +499,7 @@ std::string HelpMessage(HelpMessageMode mode)
strUsage += HelpMessageOpt("-server", _("Accept command line and JSON-RPC commands"));
strUsage += HelpMessageOpt("-rest", strprintf(_("Accept public REST requests (default: %u)"), DEFAULT_REST_ENABLE));
strUsage += HelpMessageOpt("-rpcbind=<addr>", _("Bind to given address to listen for JSON-RPC connections. Use [host]:port notation for IPv6. This option can be specified multiple times (default: bind to all interfaces)"));
+ strUsage += HelpMessageOpt("-rpccookiefile=<loc>", _("Location of the auth cookie (default: data dir)"));
strUsage += HelpMessageOpt("-rpcuser=<user>", _("Username for JSON-RPC connections"));
strUsage += HelpMessageOpt("-rpcpassword=<pw>", _("Password for JSON-RPC connections"));
strUsage += HelpMessageOpt("-rpcauth=<userpw>", _("Username and hashed password for JSON-RPC connections. The field <userpw> comes in the format: <USERNAME>:<SALT>$<HASH>. A canonical python script is included in share/rpcuser. This option can be specified multiple times"));
@@ -959,6 +970,15 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
else
return InitError(AmountErrMsg("mintxfee", mapArgs["-mintxfee"]));
}
+ if (mapArgs.count("-fallbackfee"))
+ {
+ CAmount nFeePerK = 0;
+ if (!ParseMoney(mapArgs["-fallbackfee"], nFeePerK))
+ return InitError(strprintf(_("Invalid amount for -fallbackfee=<amount>: '%s'"), mapArgs["-fallbackfee"]));
+ if (nFeePerK > nHighTransactionFeeWarning)
+ InitWarning(_("-fallbackfee is set very high! This is the transaction fee you may pay when fee estimates are not available."));
+ CWallet::fallbackFee = CFeeRate(nFeePerK);
+ }
if (mapArgs.count("-paytxfee"))
{
CAmount nFeePerK = 0;
@@ -977,7 +997,7 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
{
CAmount nMaxFee = 0;
if (!ParseMoney(mapArgs["-maxtxfee"], nMaxFee))
- return InitError(AmountErrMsg("maxtxfee", mapArgs["-maptxfee"]));
+ return InitError(AmountErrMsg("maxtxfee", mapArgs["-maxtxfee"]));
if (nMaxFee > nHighTransactionMaxFeeWarning)
InitWarning(_("-maxtxfee is set very high! Fees this large could be paid on a single transaction."));
maxTxFee = nMaxFee;
@@ -1006,6 +1026,8 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
if (GetBoolArg("-peerbloomfilters", true))
nLocalServices |= NODE_BLOOM;
+ nMaxTipAge = GetArg("-maxtipage", DEFAULT_MAX_TIP_AGE);
+
// ********************************************************* Step 4: application initialization: dir lock, daemonize, pidfile, debug log
// Initialize elliptic curve code
diff --git a/src/main.cpp b/src/main.cpp
index 06374cc1b..9870beecc 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -75,6 +75,9 @@ bool fCheckpointsEnabled = DEFAULT_CHECKPOINTS_ENABLED;
size_t nCoinCacheUsage = 5000 * 300;
uint64_t nPruneTarget = 0;
bool fAlerts = DEFAULT_ALERTS;
+/* If the tip is older than this (in seconds), the node is considered to be in initial block download.
+ */
+int64_t nMaxTipAge = DEFAULT_MAX_TIP_AGE;
/** Fees smaller than this (in satoshi) are considered zero fee (for relaying, mining and transaction creation) */
CFeeRate minRelayTxFee = CFeeRate(DEFAULT_MIN_RELAY_TX_FEE);
@@ -1377,7 +1380,7 @@ bool IsInitialBlockDownload()
if (lockIBDState)
return false;
bool state = (chainActive.Height() < pindexBestHeader->nHeight - 24 * 6 ||
- pindexBestHeader->GetBlockTime() < GetTime() - chainParams.MaxTipAge());
+ pindexBestHeader->GetBlockTime() < GetTime() - nMaxTipAge);
if (!state)
lockIBDState = true;
return state;
@@ -1633,9 +1636,12 @@ bool CheckInputs(const CTransaction& tx, CValidationState &state, const CCoinsVi
// Only if ALL inputs pass do we perform expensive ECDSA signature checks.
// Helps prevent CPU exhaustion attacks.
- // Skip ECDSA signature verification when connecting blocks
- // before the last block chain checkpoint. This is safe because block merkle hashes are
- // still computed and checked, and any change will be caught at the next checkpoint.
+ // Skip ECDSA signature verification when connecting blocks before the
+ // last block chain checkpoint. Assuming the checkpoints are valid this
+ // is safe because block merkle hashes are still computed and checked,
+ // and any change will be caught at the next checkpoint. Of course, if
+ // the checkpoint is for a chain that's invalid due to false scriptSigs
+ // this optimisation would allow an invalid chain to be accepted.
if (fScriptChecks) {
for (unsigned int i = 0; i < tx.vin.size(); i++) {
const COutPoint &prevout = tx.vin[i].prevout;
@@ -4538,7 +4544,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
{
if (fBlocksOnly)
LogPrint("net", "transaction (%s) inv sent in violation of protocol peer=%d\n", inv.hash.ToString(), pfrom->id);
- else if (!fAlreadyHave && !fImporting && !fReindex)
+ else if (!fAlreadyHave && !fImporting && !fReindex && !IsInitialBlockDownload())
pfrom->AskFor(inv);
}
diff --git a/src/main.h b/src/main.h
index cefaedabf..228877641 100644
--- a/src/main.h
+++ b/src/main.h
@@ -97,6 +97,7 @@ static const unsigned int AVG_INVENTORY_BROADCAST_INTERVAL = 5;
static const unsigned int DEFAULT_LIMITFREERELAY = 15;
static const bool DEFAULT_RELAYPRIORITY = true;
+static const int64_t DEFAULT_MAX_TIP_AGE = 24 * 60 * 60;
/** Default for -permitbaremultisig */
static const bool DEFAULT_PERMIT_BAREMULTISIG = true;
@@ -137,6 +138,7 @@ extern bool fCheckpointsEnabled;
extern size_t nCoinCacheUsage;
extern CFeeRate minRelayTxFee;
extern bool fAlerts;
+extern int64_t nMaxTipAge;
/** Best header we've seen so far (used for getheaders queries' starting points). */
extern CBlockIndex *pindexBestHeader;
diff --git a/src/net.cpp b/src/net.cpp
index 84582484e..db8f97abc 100644
--- a/src/net.cpp
+++ b/src/net.cpp
@@ -2177,7 +2177,7 @@ bool CNode::OutboundTargetReached(bool historicalBlockServingLimit)
if (historicalBlockServingLimit)
{
- // keep a large enought buffer to at least relay each block once
+ // keep a large enough buffer to at least relay each block once
uint64_t timeLeftInCycle = GetMaxOutboundTimeLeftInCycle();
uint64_t buffer = timeLeftInCycle / 600 * MAX_BLOCK_SIZE;
if (buffer >= nMaxOutboundLimit || nMaxOutboundTotalBytesSentInCycle >= nMaxOutboundLimit - buffer)
diff --git a/src/netbase.cpp b/src/netbase.cpp
index 4e1f26760..7f79dd02c 100644
--- a/src/netbase.cpp
+++ b/src/netbase.cpp
@@ -140,7 +140,7 @@ bool static LookupIntern(const char *pszName, std::vector<CNetAddr>& vIP, unsign
return false;
do {
- // Should set the timeout limit to a resonable value to avoid
+ // Should set the timeout limit to a reasonable value to avoid
// generating unnecessary checking call during the polling loop,
// while it can still response to stop request quick enough.
// 2 seconds looks fine in our situation.
diff --git a/src/policy/fees.cpp b/src/policy/fees.cpp
index 980ecf10d..de3c060d6 100644
--- a/src/policy/fees.cpp
+++ b/src/policy/fees.cpp
@@ -87,7 +87,7 @@ double TxConfirmStats::EstimateMedianVal(int confTarget, double sufficientTxVal,
int maxbucketindex = buckets.size() - 1;
// requireGreater means we are looking for the lowest fee/priority such that all higher
- // values pass, so we start at maxbucketindex (highest fee) and look at succesively
+ // values pass, so we start at maxbucketindex (highest fee) and look at successively
// smaller buckets until we reach failure. Otherwise, we are looking for the highest
// fee/priority such that all lower values fail, and we go in the opposite direction.
unsigned int startbucket = requireGreater ? maxbucketindex : 0;
diff --git a/src/policy/fees.h b/src/policy/fees.h
index 7a293267d..3fa31c39e 100644
--- a/src/policy/fees.h
+++ b/src/policy/fees.h
@@ -29,7 +29,7 @@ class CTxMemPool;
* included in blocks before transactions of lower fee/priority. So for
* example if you wanted to know what fee you should put on a transaction to
* be included in a block within the next 5 blocks, you would start by looking
- * at the bucket with with the highest fee transactions and verifying that a
+ * at the bucket with the highest fee transactions and verifying that a
* sufficiently high percentage of them were confirmed within 5 blocks and
* then you would look at the next highest fee bucket, and so on, stopping at
* the last bucket to pass the test. The average fee of transactions in this
@@ -87,13 +87,13 @@ private:
// Count the total # of txs in each bucket
// Track the historical moving average of this total over blocks
std::vector<double> txCtAvg;
- // and calcuate the total for the current block to update the moving average
+ // and calculate the total for the current block to update the moving average
std::vector<int> curBlockTxCt;
// Count the total # of txs confirmed within Y blocks in each bucket
// Track the historical moving average of theses totals over blocks
std::vector<std::vector<double> > confAvg; // confAvg[Y][X]
- // and calcuate the totals for the current block to update the moving averages
+ // and calculate the totals for the current block to update the moving averages
std::vector<std::vector<int> > curBlockConf; // curBlockConf[Y][X]
// Sum the total priority/fee of all tx's in each bucket
diff --git a/src/qt/clientmodel.cpp b/src/qt/clientmodel.cpp
index b4ac69639..fb502b3c8 100644
--- a/src/qt/clientmodel.cpp
+++ b/src/qt/clientmodel.cpp
@@ -112,7 +112,7 @@ double ClientModel::getVerificationProgress(const CBlockIndex *tipIn) const
void ClientModel::updateTimer()
{
// no locking required at this point
- // the following calls will aquire the required lock
+ // the following calls will acquire the required lock
Q_EMIT mempoolSizeChanged(getMempoolSize(), getMempoolDynamicUsage());
Q_EMIT bytesChanged(getTotalBytesRecv(), getTotalBytesSent());
}
diff --git a/src/qt/coincontroldialog.cpp b/src/qt/coincontroldialog.cpp
index a5c2b6d42..7393c83c7 100644
--- a/src/qt/coincontroldialog.cpp
+++ b/src/qt/coincontroldialog.cpp
@@ -408,10 +408,8 @@ void CoinControlDialog::viewItemChanged(QTreeWidgetItem* item, int column)
CoinControlDialog::updateLabels(model, this);
}
- // todo: this is a temporary qt5 fix: when clicking a parent node in tree mode, the parent node
- // including all children are partially selected. But the parent node should be fully selected
- // as well as the children. Children should never be partially selected in the first place.
- // Should be fixed in Qt5.4 and above. https://bugreports.qt.io/browse/QTBUG-43473
+ // TODO: Remove this temporary qt5 fix after Qt5.3 and Qt5.4 are no longer used.
+ // Fixed in Qt5.5 and above: https://bugreports.qt.io/browse/QTBUG-43473
#if QT_VERSION >= 0x050000
else if (column == COLUMN_CHECKBOX && item->childCount() > 0)
{
diff --git a/src/qt/sendcoinsdialog.cpp b/src/qt/sendcoinsdialog.cpp
index 31c9028c4..5fc7b57a4 100644
--- a/src/qt/sendcoinsdialog.cpp
+++ b/src/qt/sendcoinsdialog.cpp
@@ -640,13 +640,15 @@ void SendCoinsDialog::updateSmartFeeLabel()
CFeeRate feeRate = mempool.estimateSmartFee(nBlocksToConfirm, &estimateFoundAtBlocks);
if (feeRate <= CFeeRate(0)) // not enough data => minfee
{
- ui->labelSmartFee->setText(BitcoinUnits::formatWithUnit(model->getOptionsModel()->getDisplayUnit(), CWallet::GetRequiredFee(1000)) + "/kB");
+ ui->labelSmartFee->setText(BitcoinUnits::formatWithUnit(model->getOptionsModel()->getDisplayUnit(),
+ std::max(CWallet::fallbackFee.GetFeePerK(), CWallet::GetRequiredFee(1000))) + "/kB");
ui->labelSmartFee2->show(); // (Smart fee not initialized yet. This usually takes a few blocks...)
ui->labelFeeEstimation->setText("");
}
else
{
- ui->labelSmartFee->setText(BitcoinUnits::formatWithUnit(model->getOptionsModel()->getDisplayUnit(), feeRate.GetFeePerK()) + "/kB");
+ ui->labelSmartFee->setText(BitcoinUnits::formatWithUnit(model->getOptionsModel()->getDisplayUnit(),
+ std::max(feeRate.GetFeePerK(), CWallet::GetRequiredFee(1000))) + "/kB");
ui->labelSmartFee2->hide();
ui->labelFeeEstimation->setText(tr("Estimated to begin confirmation within %n block(s).", "", estimateFoundAtBlocks));
}
@@ -789,7 +791,7 @@ void SendCoinsDialog::coinControlUpdateLabels()
if (model->getOptionsModel()->getCoinControlFeatures())
{
- // enable minium absolute fee UI controls
+ // enable minimum absolute fee UI controls
ui->radioCustomAtLeast->setVisible(true);
// only enable the feature if inputs are selected
diff --git a/src/qt/transactionview.cpp b/src/qt/transactionview.cpp
index 28928d821..4a9a19821 100644
--- a/src/qt/transactionview.cpp
+++ b/src/qt/transactionview.cpp
@@ -267,7 +267,7 @@ void TransactionView::chooseDate(int idx)
break;
case LastMonth:
transactionProxyModel->setDateRange(
- QDateTime(QDate(current.year(), current.month()-1, 1)),
+ QDateTime(QDate(current.year(), current.month(), 1).addMonths(-1)),
QDateTime(QDate(current.year(), current.month(), 1)));
break;
case ThisYear:
diff --git a/src/rpcblockchain.cpp b/src/rpcblockchain.cpp
index edaa71e79..954441d15 100644
--- a/src/rpcblockchain.cpp
+++ b/src/rpcblockchain.cpp
@@ -323,7 +323,8 @@ UniValue getblockheader(const UniValue& params, bool fHelp)
" \"bits\" : \"1d00ffff\", (string) The bits\n"
" \"difficulty\" : x.xxx, (numeric) The difficulty\n"
" \"previousblockhash\" : \"hash\", (string) The hash of the previous block\n"
- " \"nextblockhash\" : \"hash\" (string) The hash of the next block\n"
+ " \"nextblockhash\" : \"hash\", (string) The hash of the next block\n"
+ " \"chainwork\" : \"0000...1f3\" (string) Expected number of hashes required to produce the current chain (in hex)\n"
"}\n"
"\nResult (for verbose=false):\n"
"\"data\" (string) A string that is serialized, hex-encoded data for block 'hash'.\n"
@@ -384,6 +385,7 @@ UniValue getblock(const UniValue& params, bool fHelp)
" \"nonce\" : n, (numeric) The nonce\n"
" \"bits\" : \"1d00ffff\", (string) The bits\n"
" \"difficulty\" : x.xxx, (numeric) The difficulty\n"
+ " \"chainwork\" : \"xxxx\", (string) Expected number of hashes required to produce the chain up to this block (in hex)\n"
" \"previousblockhash\" : \"hash\", (string) The hash of the previous block\n"
" \"nextblockhash\" : \"hash\" (string) The hash of the next block\n"
"}\n"
@@ -472,8 +474,8 @@ UniValue gettxout(const UniValue& params, bool fHelp)
"\nReturns details about an unspent transaction output.\n"
"\nArguments:\n"
"1. \"txid\" (string, required) The transaction id\n"
- "2. n (numeric, required) vout value\n"
- "3. includemempool (boolean, optional) Whether to included the mem pool\n"
+ "2. n (numeric, required) vout number\n"
+ "3. includemempool (boolean, optional) Whether to include the mem pool\n"
"\nResult:\n"
"{\n"
" \"bestblock\" : \"hash\", (string) the block hash\n"
diff --git a/src/rpcrawtransaction.cpp b/src/rpcrawtransaction.cpp
index 4947ad1f7..64bf569ba 100644
--- a/src/rpcrawtransaction.cpp
+++ b/src/rpcrawtransaction.cpp
@@ -338,7 +338,7 @@ UniValue createrawtransaction(const UniValue& params, bool fHelp)
" ]\n"
"2. \"outputs\" (string, required) a json object with outputs\n"
" {\n"
- " \"address\": x.xxx (numeric, required) The key is the bitcoin address, the value is the " + CURRENCY_UNIT + " amount\n"
+ " \"address\": x.xxx (numeric or string, required) The key is the bitcoin address, the numeric value (can be string) is the " + CURRENCY_UNIT + " amount\n"
" \"data\": \"hex\", (string, required) The key is \"data\", the value is hex encoded data\n"
" ...\n"
" }\n"
diff --git a/src/rpcserver.cpp b/src/rpcserver.cpp
index 78d6898bc..53c368b27 100644
--- a/src/rpcserver.cpp
+++ b/src/rpcserver.cpp
@@ -346,6 +346,7 @@ static const CRPCCommand vRPCCommands[] =
{ "wallet", "getreceivedbyaccount", &getreceivedbyaccount, false },
{ "wallet", "getreceivedbyaddress", &getreceivedbyaddress, false },
{ "wallet", "gettransaction", &gettransaction, false },
+ { "wallet", "abandontransaction", &abandontransaction, false },
{ "wallet", "getunconfirmedbalance", &getunconfirmedbalance, false },
{ "wallet", "getwalletinfo", &getwalletinfo, false },
{ "wallet", "importprivkey", &importprivkey, true },
diff --git a/src/rpcserver.h b/src/rpcserver.h
index 9dce31887..29f503658 100644
--- a/src/rpcserver.h
+++ b/src/rpcserver.h
@@ -223,6 +223,7 @@ extern UniValue listaddressgroupings(const UniValue& params, bool fHelp);
extern UniValue listaccounts(const UniValue& params, bool fHelp);
extern UniValue listsinceblock(const UniValue& params, bool fHelp);
extern UniValue gettransaction(const UniValue& params, bool fHelp);
+extern UniValue abandontransaction(const UniValue& params, bool fHelp);
extern UniValue backupwallet(const UniValue& params, bool fHelp);
extern UniValue keypoolrefill(const UniValue& params, bool fHelp);
extern UniValue walletpassphrase(const UniValue& params, bool fHelp);
diff --git a/src/test/merkle_tests.cpp b/src/test/merkle_tests.cpp
index 1e31f2e67..b40ab848d 100644
--- a/src/test/merkle_tests.cpp
+++ b/src/test/merkle_tests.cpp
@@ -77,7 +77,7 @@ BOOST_AUTO_TEST_CASE(merkle_test)
int duplicate2 = mutate >= 2 ? 1 << ctz(ntx1) : 0; // Likewise for the second mutation.
if (duplicate2 >= ntx1) break;
int ntx2 = ntx1 + duplicate2;
- int duplicate3 = mutate >= 3 ? 1 << ctz(ntx2) : 0; // And for the the third mutation.
+ int duplicate3 = mutate >= 3 ? 1 << ctz(ntx2) : 0; // And for the third mutation.
if (duplicate3 >= ntx2) break;
int ntx3 = ntx2 + duplicate3;
// Build a block with ntx different transactions.
diff --git a/src/torcontrol.cpp b/src/torcontrol.cpp
index 4ebcb9b66..8b7702481 100644
--- a/src/torcontrol.cpp
+++ b/src/torcontrol.cpp
@@ -79,7 +79,7 @@ public:
/**
* Connect to a Tor control port.
* target is address of the form host:port.
- * connected is the handler that is called when connection is succesfully established.
+ * connected is the handler that is called when connection is successfully established.
* disconnected is a handler that is called when the connection is broken.
* Return true on success.
*/
@@ -177,7 +177,7 @@ void TorControlConnection::eventcb(struct bufferevent *bev, short what, void *ct
{
TorControlConnection *self = (TorControlConnection*)ctx;
if (what & BEV_EVENT_CONNECTED) {
- LogPrint("tor", "tor: Succesfully connected!\n");
+ LogPrint("tor", "tor: Successfully connected!\n");
self->connected(*self);
} else if (what & (BEV_EVENT_EOF|BEV_EVENT_ERROR)) {
if (what & BEV_EVENT_ERROR)
@@ -303,7 +303,7 @@ static std::map<std::string,std::string> ParseTorReplyMapping(const std::string
/** Read full contents of a file and return them in a std::string.
* Returns a pair <status, string>.
- * If an error occured, status will be false, otherwise status will be true and the data will be returned in string.
+ * If an error occurred, status will be false, otherwise status will be true and the data will be returned in string.
*
* @param maxsize Puts a maximum size limit on the file that is read. If the file is larger than this, truncated data
* (with len > maxsize) will be returned.
@@ -380,7 +380,7 @@ private:
void authchallenge_cb(TorControlConnection& conn, const TorControlReply& reply);
/** Callback for PROTOCOLINFO result */
void protocolinfo_cb(TorControlConnection& conn, const TorControlReply& reply);
- /** Callback after succesful connection */
+ /** Callback after successful connection */
void connected_cb(TorControlConnection& conn);
/** Callback after connection lost or failed connection attempt */
void disconnected_cb(TorControlConnection& conn);
@@ -419,7 +419,7 @@ TorController::~TorController()
void TorController::add_onion_cb(TorControlConnection& conn, const TorControlReply& reply)
{
if (reply.code == 250) {
- LogPrint("tor", "tor: ADD_ONION succesful\n");
+ LogPrint("tor", "tor: ADD_ONION successful\n");
BOOST_FOREACH(const std::string &s, reply.lines) {
std::map<std::string,std::string> m = ParseTorReplyMapping(s);
std::map<std::string,std::string>::iterator i;
@@ -448,7 +448,7 @@ void TorController::add_onion_cb(TorControlConnection& conn, const TorControlRep
void TorController::auth_cb(TorControlConnection& conn, const TorControlReply& reply)
{
if (reply.code == 250) {
- LogPrint("tor", "tor: Authentication succesful\n");
+ LogPrint("tor", "tor: Authentication successful\n");
// Now that we know Tor is running setup the proxy for onion addresses
// if -onion isn't set to something else.
@@ -501,7 +501,7 @@ static std::vector<uint8_t> ComputeResponse(const std::string &key, const std::v
void TorController::authchallenge_cb(TorControlConnection& conn, const TorControlReply& reply)
{
if (reply.code == 250) {
- LogPrint("tor", "tor: SAFECOOKIE authentication challenge succesful\n");
+ LogPrint("tor", "tor: SAFECOOKIE authentication challenge successful\n");
std::pair<std::string,std::string> l = SplitTorReplyLine(reply.lines[0]);
if (l.first == "AUTHCHALLENGE") {
std::map<std::string,std::string> m = ParseTorReplyMapping(l.second);
diff --git a/src/wallet/db.cpp b/src/wallet/db.cpp
index d18250b76..50b0f40a6 100644
--- a/src/wallet/db.cpp
+++ b/src/wallet/db.cpp
@@ -205,7 +205,7 @@ bool CDBEnv::Salvage(const std::string& strFile, bool fAggressive, std::vector<C
std::string keyHex, valueHex;
while (!strDump.eof() && keyHex != "DATA=END") {
getline(strDump, keyHex);
- if (keyHex != "DATA_END") {
+ if (keyHex != "DATA=END") {
getline(strDump, valueHex);
vResult.push_back(make_pair(ParseHex(keyHex), ParseHex(valueHex)));
}
diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp
index 374f2fd40..a977b5abd 100644
--- a/src/wallet/rpcwallet.cpp
+++ b/src/wallet/rpcwallet.cpp
@@ -388,11 +388,11 @@ UniValue sendtoaddress(const UniValue& params, bool fHelp)
if (fHelp || params.size() < 2 || params.size() > 5)
throw runtime_error(
"sendtoaddress \"bitcoinaddress\" amount ( \"comment\" \"comment-to\" subtractfeefromamount )\n"
- "\nSend an amount to a given address. The amount is a real and is rounded to the nearest 0.00000001\n"
+ "\nSend an amount to a given address.\n"
+ HelpRequiringPassphrase() +
"\nArguments:\n"
"1. \"bitcoinaddress\" (string, required) The bitcoin address to send to.\n"
- "2. \"amount\" (numeric, required) The amount in " + CURRENCY_UNIT + " to send. eg 0.1\n"
+ "2. \"amount\" (numeric or string, required) The amount in " + CURRENCY_UNIT + " to send. eg 0.1\n"
"3. \"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"
"4. \"comment-to\" (string, optional) A comment to store the name of the person or organization \n"
@@ -864,13 +864,12 @@ UniValue sendfrom(const UniValue& params, bool fHelp)
if (fHelp || params.size() < 3 || params.size() > 6)
throw runtime_error(
"sendfrom \"fromaccount\" \"tobitcoinaddress\" amount ( minconf \"comment\" \"comment-to\" )\n"
- "\nDEPRECATED (use sendtoaddress). Sent an amount from an account to a bitcoin address.\n"
- "The amount is a real and is rounded to the nearest 0.00000001."
+ "\nDEPRECATED (use sendtoaddress). Sent an amount from an account to a bitcoin address."
+ HelpRequiringPassphrase() + "\n"
"\nArguments:\n"
"1. \"fromaccount\" (string, required) The name of the account to send funds from. May be the default account using \"\".\n"
"2. \"tobitcoinaddress\" (string, required) The bitcoin address to send funds to.\n"
- "3. amount (numeric, 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"
"5. \"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"
@@ -935,7 +934,7 @@ UniValue sendmany(const UniValue& params, bool fHelp)
"1. \"fromaccount\" (string, required) DEPRECATED. The account to send the funds from. Should be \"\" for the default account\n"
"2. \"amounts\" (string, required) A json object with addresses and amounts\n"
" {\n"
- " \"address\":amount (numeric) The bitcoin address is the key, the numeric amount in " + CURRENCY_UNIT + " is the value\n"
+ " \"address\":amount (numeric or string) The bitcoin address is the key, the numeric amount (can be string) in " + CURRENCY_UNIT + " is the value\n"
" ,...\n"
" }\n"
"3. minconf (numeric, optional, default=1) Only use the balance confirmed at least this many times.\n"
@@ -1424,7 +1423,7 @@ UniValue listtransactions(const UniValue& params, bool fHelp)
" 'send' category of transactions.\n"
" \"confirmations\": n, (numeric) The number of confirmations for the transaction. Available for 'send' and \n"
" 'receive' category of transactions. Negative confirmations indicate the\n"
- " transation conflicts with the block chain\n"
+ " transaction conflicts with the block chain\n"
" \"trusted\": xxx (bool) Whether we consider the outputs of this unconfirmed transaction safe to spend.\n"
" \"blockhash\": \"hashvalue\", (string) The block hash containing the transaction. Available for 'send' and 'receive'\n"
" category of transactions.\n"
@@ -1764,6 +1763,40 @@ UniValue gettransaction(const UniValue& params, bool fHelp)
return entry;
}
+UniValue abandontransaction(const UniValue& params, bool fHelp)
+{
+ if (!EnsureWalletIsAvailable(fHelp))
+ return NullUniValue;
+
+ if (fHelp || params.size() != 1)
+ throw runtime_error(
+ "abandontransaction \"txid\"\n"
+ "\nMark in-wallet transaction <txid> as abandoned\n"
+ "This will mark this transaction and all its in-wallet descendants as abandoned which will allow\n"
+ "for their inputs to be respent. It can be used to replace \"stuck\" or evicted transactions.\n"
+ "It only works on transactions which are not included in a block and are not currently in the mempool.\n"
+ "It has no effect on transactions which are already conflicted or abandoned.\n"
+ "\nArguments:\n"
+ "1. \"txid\" (string, required) The transaction id\n"
+ "\nResult:\n"
+ "\nExamples:\n"
+ + HelpExampleCli("abandontransaction", "\"1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d\"")
+ + HelpExampleRpc("abandontransaction", "\"1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d\"")
+ );
+
+ LOCK2(cs_main, pwalletMain->cs_wallet);
+
+ uint256 hash;
+ hash.SetHex(params[0].get_str());
+
+ if (!pwalletMain->mapWallet.count(hash))
+ throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid or non-wallet transaction id");
+ if (!pwalletMain->AbandonTransaction(hash))
+ throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Transaction not eligible for abandonment");
+
+ return NullUniValue;
+}
+
UniValue backupwallet(const UniValue& params, bool fHelp)
{
@@ -2180,7 +2213,7 @@ UniValue settxfee(const UniValue& params, bool fHelp)
"settxfee amount\n"
"\nSet the transaction fee per kB. Overwrites the paytxfee parameter.\n"
"\nArguments:\n"
- "1. amount (numeric, required) The transaction fee in " + CURRENCY_UNIT + "/kB rounded to the nearest 0.00000001\n"
+ "1. amount (numeric or sting, required) The transaction fee in " + CURRENCY_UNIT + "/kB\n"
"\nResult\n"
"true|false (boolean) Returns true if successful\n"
"\nExamples:\n"
diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp
index 1904361ba..cbc71aa16 100644
--- a/src/wallet/wallet.cpp
+++ b/src/wallet/wallet.cpp
@@ -47,6 +47,14 @@ bool fSendFreeTransactions = DEFAULT_SEND_FREE_TRANSACTIONS;
* Override with -mintxfee
*/
CFeeRate CWallet::minTxFee = CFeeRate(DEFAULT_TRANSACTION_MINFEE);
+/**
+ * If fee estimation does not have enough data to provide estimates, use this fee instead.
+ * Has no effect if not using fee estimation
+ * Override with -fallbackfee
+ */
+CFeeRate CWallet::fallbackFee = CFeeRate(DEFAULT_FALLBACK_FEE);
+
+const uint256 CMerkleTx::ABANDON_HASH(uint256S("0000000000000000000000000000000000000000000000000000000000000001"));
/** @defgroup mapWallet
*
@@ -455,8 +463,11 @@ bool CWallet::IsSpent(const uint256& hash, unsigned int n) const
{
const uint256& wtxid = it->second;
std::map<uint256, CWalletTx>::const_iterator mit = mapWallet.find(wtxid);
- if (mit != mapWallet.end() && mit->second.GetDepthInMainChain() >= 0)
- return true; // Spent
+ if (mit != mapWallet.end()) {
+ int depth = mit->second.GetDepthInMainChain();
+ if (depth > 0 || (depth == 0 && !mit->second.isAbandoned()))
+ return true; // Spent
+ }
}
return false;
}
@@ -610,7 +621,7 @@ bool CWallet::AddToWallet(const CWalletTx& wtxIn, bool fFromLoadWallet, CWalletD
BOOST_FOREACH(const CTxIn& txin, wtx.vin) {
if (mapWallet.count(txin.prevout.hash)) {
CWalletTx& prevtx = mapWallet[txin.prevout.hash];
- if (prevtx.nIndex == -1 && !prevtx.hashBlock.IsNull()) {
+ if (prevtx.nIndex == -1 && !prevtx.hashUnset()) {
MarkConflicted(prevtx.hashBlock, wtx.GetHash());
}
}
@@ -631,7 +642,7 @@ bool CWallet::AddToWallet(const CWalletTx& wtxIn, bool fFromLoadWallet, CWalletD
wtxOrdered.insert(make_pair(wtx.nOrderPos, TxPair(&wtx, (CAccountingEntry*)0)));
wtx.nTimeSmart = wtx.nTimeReceived;
- if (!wtxIn.hashBlock.IsNull())
+ if (!wtxIn.hashUnset())
{
if (mapBlockIndex.count(wtxIn.hashBlock))
{
@@ -681,7 +692,13 @@ bool CWallet::AddToWallet(const CWalletTx& wtxIn, bool fFromLoadWallet, CWalletD
if (!fInsertedNew)
{
// Merge
- if (!wtxIn.hashBlock.IsNull() && wtxIn.hashBlock != wtx.hashBlock)
+ if (!wtxIn.hashUnset() && wtxIn.hashBlock != wtx.hashBlock)
+ {
+ wtx.hashBlock = wtxIn.hashBlock;
+ fUpdated = true;
+ }
+ // If no longer abandoned, update
+ if (wtxIn.hashBlock.IsNull() && wtx.isAbandoned())
{
wtx.hashBlock = wtxIn.hashBlock;
fUpdated = true;
@@ -768,6 +785,64 @@ bool CWallet::AddToWalletIfInvolvingMe(const CTransaction& tx, const CBlock* pbl
return false;
}
+bool CWallet::AbandonTransaction(const uint256& hashTx)
+{
+ LOCK2(cs_main, cs_wallet);
+
+ // Do not flush the wallet here for performance reasons
+ CWalletDB walletdb(strWalletFile, "r+", false);
+
+ std::set<uint256> todo;
+ std::set<uint256> done;
+
+ // Can't mark abandoned if confirmed or in mempool
+ assert(mapWallet.count(hashTx));
+ CWalletTx& origtx = mapWallet[hashTx];
+ if (origtx.GetDepthInMainChain() > 0 || origtx.InMempool()) {
+ return false;
+ }
+
+ todo.insert(hashTx);
+
+ while (!todo.empty()) {
+ uint256 now = *todo.begin();
+ todo.erase(now);
+ done.insert(now);
+ assert(mapWallet.count(now));
+ CWalletTx& wtx = mapWallet[now];
+ int currentconfirm = wtx.GetDepthInMainChain();
+ // If the orig tx was not in block, none of its spends can be
+ assert(currentconfirm <= 0);
+ // if (currentconfirm < 0) {Tx and spends are already conflicted, no need to abandon}
+ if (currentconfirm == 0 && !wtx.isAbandoned()) {
+ // If the orig tx was not in block/mempool, none of its spends can be in mempool
+ assert(!wtx.InMempool());
+ wtx.nIndex = -1;
+ wtx.setAbandoned();
+ wtx.MarkDirty();
+ wtx.WriteToDisk(&walletdb);
+ NotifyTransactionChanged(this, wtx.GetHash(), CT_UPDATED);
+ // Iterate over all its outputs, and mark transactions in the wallet that spend them abandoned too
+ TxSpends::const_iterator iter = mapTxSpends.lower_bound(COutPoint(hashTx, 0));
+ while (iter != mapTxSpends.end() && iter->first.hash == now) {
+ if (!done.count(iter->second)) {
+ todo.insert(iter->second);
+ }
+ iter++;
+ }
+ // If a transaction changes 'conflicted' state, that changes the balance
+ // available of the outputs it spends. So force those to be recomputed
+ BOOST_FOREACH(const CTxIn& txin, wtx.vin)
+ {
+ if (mapWallet.count(txin.prevout.hash))
+ mapWallet[txin.prevout.hash].MarkDirty();
+ }
+ }
+ }
+
+ return true;
+}
+
void CWallet::MarkConflicted(const uint256& hashBlock, const uint256& hashTx)
{
LOCK2(cs_main, cs_wallet);
@@ -784,14 +859,14 @@ void CWallet::MarkConflicted(const uint256& hashBlock, const uint256& hashTx)
// Do not flush the wallet here for performance reasons
CWalletDB walletdb(strWalletFile, "r+", false);
- std::deque<uint256> todo;
+ std::set<uint256> todo;
std::set<uint256> done;
- todo.push_back(hashTx);
+ todo.insert(hashTx);
while (!todo.empty()) {
- uint256 now = todo.front();
- todo.pop_front();
+ uint256 now = *todo.begin();
+ todo.erase(now);
done.insert(now);
assert(mapWallet.count(now));
CWalletTx& wtx = mapWallet[now];
@@ -807,7 +882,7 @@ void CWallet::MarkConflicted(const uint256& hashBlock, const uint256& hashTx)
TxSpends::const_iterator iter = mapTxSpends.lower_bound(COutPoint(now, 0));
while (iter != mapTxSpends.end() && iter->first.hash == now) {
if (!done.count(iter->second)) {
- todo.push_back(iter->second);
+ todo.insert(iter->second);
}
iter++;
}
@@ -976,7 +1051,7 @@ int CWalletTx::GetRequestCount() const
if (IsCoinBase())
{
// Generated block
- if (!hashBlock.IsNull())
+ if (!hashUnset())
{
map<uint256, int>::const_iterator mi = pwallet->mapRequestCount.find(hashBlock);
if (mi != pwallet->mapRequestCount.end())
@@ -992,7 +1067,7 @@ int CWalletTx::GetRequestCount() const
nRequests = (*mi).second;
// How about the block it's in?
- if (nRequests == 0 && !hashBlock.IsNull())
+ if (nRequests == 0 && !hashUnset())
{
map<uint256, int>::const_iterator mi = pwallet->mapRequestCount.find(hashBlock);
if (mi != pwallet->mapRequestCount.end())
@@ -1166,7 +1241,7 @@ void CWallet::ReacceptWalletTransactions()
int nDepth = wtx.GetDepthInMainChain();
- if (!wtx.IsCoinBase() && nDepth == 0) {
+ if (!wtx.IsCoinBase() && (nDepth == 0 && !wtx.isAbandoned())) {
mapSorted.insert(std::make_pair(wtx.nOrderPos, &wtx));
}
}
@@ -1186,7 +1261,7 @@ bool CWalletTx::RelayWalletTransaction()
assert(pwallet->GetBroadcastTransactions());
if (!IsCoinBase())
{
- if (GetDepthInMainChain() == 0) {
+ if (GetDepthInMainChain() == 0 && !isAbandoned()) {
LogPrintf("Relaying wtx %s\n", GetHash().ToString());
RelayTransaction((CTransaction)*this);
return true;
@@ -2230,14 +2305,12 @@ CAmount CWallet::GetMinimumFee(unsigned int nTxBytes, unsigned int nConfirmTarge
if (nFeeNeeded == 0) {
int estimateFoundTarget = nConfirmTarget;
nFeeNeeded = pool.estimateSmartFee(nConfirmTarget, &estimateFoundTarget).GetFee(nTxBytes);
- // ... unless we don't have enough mempool data for our desired target
- // so we make sure we're paying at least minTxFee
- if (nFeeNeeded == 0 || (unsigned int)estimateFoundTarget > nConfirmTarget)
- nFeeNeeded = std::max(nFeeNeeded, GetRequiredFee(nTxBytes));
- }
- // prevent user from paying a non-sense fee (like 1 satoshi): 0 < fee < minRelayFee
- if (nFeeNeeded < ::minRelayTxFee.GetFee(nTxBytes))
- nFeeNeeded = ::minRelayTxFee.GetFee(nTxBytes);
+ // ... unless we don't have enough mempool data for estimatefee, then use fallbackFee
+ if (nFeeNeeded == 0)
+ nFeeNeeded = fallbackFee.GetFee(nTxBytes);
+ }
+ // prevent user from paying a fee below minRelayTxFee or minTxFee
+ nFeeNeeded = std::max(nFeeNeeded, GetRequiredFee(nTxBytes));
// But always obey the maximum
if (nFeeNeeded > maxTxFee)
nFeeNeeded = maxTxFee;
@@ -2927,8 +3000,9 @@ int CMerkleTx::SetMerkleBranch(const CBlock& block)
int CMerkleTx::GetDepthInMainChain(const CBlockIndex* &pindexRet) const
{
- if (hashBlock.IsNull())
+ if (hashUnset())
return 0;
+
AssertLockHeld(cs_main);
// Find the block it claims to be in
@@ -2956,4 +3030,3 @@ bool CMerkleTx::AcceptToMemoryPool(bool fLimitFree, bool fRejectAbsurdFee)
CValidationState state;
return ::AcceptToMemoryPool(mempool, state, *this, fLimitFree, NULL, false, fRejectAbsurdFee);
}
-
diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h
index a9d0c3f60..2176a5ff6 100644
--- a/src/wallet/wallet.h
+++ b/src/wallet/wallet.h
@@ -41,6 +41,8 @@ static const unsigned int DEFAULT_KEYPOOL_SIZE = 100;
static const CAmount DEFAULT_TRANSACTION_FEE = 0;
//! -paytxfee will warn if called with a higher fee than this amount (in satoshis) per KB
static const CAmount nHighTransactionFeeWarning = 0.01 * COIN;
+//! -fallbackfee default
+static const CAmount DEFAULT_FALLBACK_FEE = 20000;
//! -mintxfee default
static const CAmount DEFAULT_TRANSACTION_MINFEE = 1000;
//! -maxtxfee default
@@ -154,6 +156,10 @@ struct COutputEntry
/** A transaction with a merkle branch linking it to the block chain. */
class CMerkleTx : public CTransaction
{
+private:
+ /** Constant used in hashBlock to indicate tx has been abandoned */
+ static const uint256 ABANDON_HASH;
+
public:
uint256 hashBlock;
@@ -205,6 +211,9 @@ public:
bool IsInMainChain() const { const CBlockIndex *pindexRet; return GetDepthInMainChain(pindexRet) > 0; }
int GetBlocksToMaturity() const;
bool AcceptToMemoryPool(bool fLimitFree=true, bool fRejectAbsurdFee=true);
+ bool hashUnset() const { return (hashBlock.IsNull() || hashBlock == ABANDON_HASH); }
+ bool isAbandoned() const { return (hashBlock == ABANDON_HASH); }
+ void setAbandoned() { hashBlock = ABANDON_HASH; }
};
/**
@@ -565,7 +574,6 @@ private:
/* Mark a transaction (and its in-wallet descendants) as conflicting with a particular block. */
void MarkConflicted(const uint256& hashBlock, const uint256& hashTx);
-
void SyncMetaData(std::pair<TxSpends::iterator, TxSpends::iterator>);
public:
@@ -745,6 +753,7 @@ public:
bool AddAccountingEntry(const CAccountingEntry&, CWalletDB & pwalletdb);
static CFeeRate minTxFee;
+ static CFeeRate fallbackFee;
/**
* Estimate the minimum fee considering user set parameters
* and the required fee
@@ -862,6 +871,9 @@ public:
bool GetBroadcastTransactions() const { return fBroadcastTransactions; }
/** Set whether this wallet broadcasts transactions. */
void SetBroadcastTransactions(bool broadcast) { fBroadcastTransactions = broadcast; }
+
+ /* Mark a transaction (and it in-wallet descendants) as abandoned so its inputs may be respent. */
+ bool AbandonTransaction(const uint256& hashTx);
};
/** A key allocated from the key pool. */
diff --git a/src/wallet/wallet_ismine.h b/src/wallet/wallet_ismine.h
index 93cdf6ab8..51afd1b14 100644
--- a/src/wallet/wallet_ismine.h
+++ b/src/wallet/wallet_ismine.h
@@ -17,7 +17,7 @@ class CScript;
enum isminetype
{
ISMINE_NO = 0,
- //! Indicates that we dont know how to create a scriptSig that would solve this if we were given the appropriate private keys
+ //! Indicates that we don't know how to create a scriptSig that would solve this if we were given the appropriate private keys
ISMINE_WATCH_UNSOLVABLE = 1,
//! Indicates that we know how to create a scriptSig that would solve this if we were given the appropriate private keys
ISMINE_WATCH_SOLVABLE = 2,
diff --git a/src/wallet/walletdb.cpp b/src/wallet/walletdb.cpp
index 5266946ca..67511976d 100644
--- a/src/wallet/walletdb.cpp
+++ b/src/wallet/walletdb.cpp
@@ -15,11 +15,6 @@
#include "utiltime.h"
#include "wallet/wallet.h"
-#if defined(FORCE_BOOST_EMULATED_SCOPED_ENUMS)
-#define BOOST_NO_SCOPED_ENUMS
-#define BOOST_NO_CXX11_SCOPED_ENUMS
-#endif
-
#include <boost/version.hpp>
#include <boost/filesystem.hpp>
#include <boost/foreach.hpp>