diff options
Diffstat (limited to 'src')
36 files changed, 374 insertions, 288 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index 6ad7aabae0..1e54512cbd 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -130,6 +130,7 @@ BITCOIN_CORE_H = \ rpc/client.h \ rpc/protocol.h \ rpc/server.h \ + rpc/register.h \ scheduler.h \ script/sigcache.h \ script/sign.h \ diff --git a/src/Makefile.qt.include b/src/Makefile.qt.include index 247ca3f1d4..8443fe697b 100644 --- a/src/Makefile.qt.include +++ b/src/Makefile.qt.include @@ -392,7 +392,7 @@ SECONDARY: $(QT_QM) qt/bitcoinstrings.cpp: $(libbitcoin_server_a_SOURCES) $(libbitcoin_wallet_a_SOURCES) @test -n $(XGETTEXT) || echo "xgettext is required for updating translations" - $(AM_V_GEN) cd $(srcdir); XGETTEXT=$(XGETTEXT) PACKAGE_NAME="$(PACKAGE_NAME)" COPYRIGHT_HOLDERS="$(COPYRIGHT_HOLDERS)" COPYRIGHT_HOLDERS_SUBSTITUTION="$(COPYRIGHT_HOLDERS_SUBSTITUTION)" ../share/qt/extract_strings_qt.py $^ + $(AM_V_GEN) cd $(srcdir); XGETTEXT=$(XGETTEXT) PACKAGE_NAME="$(PACKAGE_NAME)" COPYRIGHT_HOLDERS="$(COPYRIGHT_HOLDERS)" COPYRIGHT_HOLDERS_SUBSTITUTION="$(COPYRIGHT_HOLDERS_SUBSTITUTION)" $(PYTHON) ../share/qt/extract_strings_qt.py $^ translate: qt/bitcoinstrings.cpp $(QT_FORMS_UI) $(QT_FORMS_UI) $(BITCOIN_QT_CPP) $(BITCOIN_QT_H) $(BITCOIN_MM) @test -n $(LUPDATE) || echo "lupdate is required for updating translations" diff --git a/src/Makefile.test.include b/src/Makefile.test.include index 4481349e50..d806fb219e 100644 --- a/src/Makefile.test.include +++ b/src/Makefile.test.include @@ -130,7 +130,7 @@ bitcoin_test_clean : FORCE check-local: @echo "Running test/bitcoin-util-test.py..." - $(AM_V_at)srcdir=$(srcdir) PYTHONPATH=$(builddir)/test $(srcdir)/test/bitcoin-util-test.py + $(AM_V_at)srcdir=$(srcdir) PYTHONPATH=$(builddir)/test $(PYTHON) $(srcdir)/test/bitcoin-util-test.py $(AM_V_at)$(MAKE) $(AM_MAKEFLAGS) -C secp256k1 check if EMBEDDED_UNIVALUE $(AM_V_at)$(MAKE) $(AM_MAKEFLAGS) -C univalue check diff --git a/src/chainparams.cpp b/src/chainparams.cpp index 508c4de167..965d131695 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -86,7 +86,13 @@ public: consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].bit = 28; consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].nStartTime = 1199145601; // January 1, 2008 consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].nTimeout = 1230767999; // December 31, 2008 - /** + + // Deployment of BIP68, BIP112, and BIP113. + consensus.vDeployments[Consensus::DEPLOYMENT_CSV].bit = 0; + consensus.vDeployments[Consensus::DEPLOYMENT_CSV].nStartTime = 1462060800; // May 1st, 2016 + consensus.vDeployments[Consensus::DEPLOYMENT_CSV].nTimeout = 1493596800; // May 1st, 2017 + + /** * The message start string is designed to be unlikely to occur in normal data. * The characters are rarely used upper ASCII, not valid as UTF-8, and produce * a large 32-bit integer with any alignment. @@ -171,6 +177,12 @@ public: consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].bit = 28; consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].nStartTime = 1199145601; // January 1, 2008 consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].nTimeout = 1230767999; // December 31, 2008 + + // Deployment of BIP68, BIP112, and BIP113. + consensus.vDeployments[Consensus::DEPLOYMENT_CSV].bit = 0; + consensus.vDeployments[Consensus::DEPLOYMENT_CSV].nStartTime = 1456790400; // March 1st, 2016 + consensus.vDeployments[Consensus::DEPLOYMENT_CSV].nTimeout = 1493596800; // May 1st, 2017 + pchMessageStart[0] = 0x0b; pchMessageStart[1] = 0x11; pchMessageStart[2] = 0x09; @@ -238,6 +250,9 @@ public: consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].bit = 28; consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].nStartTime = 0; consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].nTimeout = 999999999999ULL; + consensus.vDeployments[Consensus::DEPLOYMENT_CSV].bit = 0; + consensus.vDeployments[Consensus::DEPLOYMENT_CSV].nStartTime = 0; + consensus.vDeployments[Consensus::DEPLOYMENT_CSV].nTimeout = 999999999999ULL; pchMessageStart[0] = 0xfa; pchMessageStart[1] = 0xbf; diff --git a/src/consensus/params.h b/src/consensus/params.h index 7c3a8e84c3..4f3480b89b 100644 --- a/src/consensus/params.h +++ b/src/consensus/params.h @@ -15,6 +15,7 @@ namespace Consensus { enum DeploymentPos { DEPLOYMENT_TESTDUMMY, + DEPLOYMENT_CSV, // Deployment of BIP68, BIP112, and BIP113. MAX_VERSION_BITS_DEPLOYMENTS }; diff --git a/src/init.cpp b/src/init.cpp index 38ac91b2af..3667820a21 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -24,9 +24,11 @@ #include "net.h" #include "policy/policy.h" #include "rpc/server.h" +#include "rpc/register.h" #include "script/standard.h" #include "script/sigcache.h" #include "scheduler.h" +#include "timedata.h" #include "txdb.h" #include "txmempool.h" #include "torcontrol.h" @@ -63,9 +65,6 @@ using namespace std; -#ifdef ENABLE_WALLET -CWallet* pwalletMain = NULL; -#endif bool fFeeEstimatesInitialized = false; static const bool DEFAULT_PROXYRANDOMIZE = true; static const bool DEFAULT_REST_ENABLE = false; @@ -365,6 +364,7 @@ std::string HelpMessage(HelpMessageMode mode) strUsage += HelpMessageOpt("-maxconnections=<n>", strprintf(_("Maintain at most <n> connections to peers (default: %u)"), DEFAULT_MAX_PEER_CONNECTIONS)); strUsage += HelpMessageOpt("-maxreceivebuffer=<n>", strprintf(_("Maximum per-connection receive buffer, <n>*1000 bytes (default: %u)"), DEFAULT_MAXRECEIVEBUFFER)); strUsage += HelpMessageOpt("-maxsendbuffer=<n>", strprintf(_("Maximum per-connection send buffer, <n>*1000 bytes (default: %u)"), DEFAULT_MAXSENDBUFFER)); + strUsage += HelpMessageOpt("-maxtimeadjustment", strprintf(_("Maximum allowed median peer time offset adjustment. Local perspective of time may be influenced by peers forward or backward by this amount. (default: %u seconds)"), DEFAULT_MAX_TIME_ADJUSTMENT)); strUsage += HelpMessageOpt("-onion=<ip:port>", strprintf(_("Use separate SOCKS5 proxy to reach peers via Tor hidden services (default: %s)"), "-proxy")); strUsage += HelpMessageOpt("-onlynet=<net>", _("Only connect to nodes in network <net> (ipv4, ipv6 or onion)")); strUsage += HelpMessageOpt("-permitbaremultisig", strprintf(_("Relay non-P2SH multisig (default: %u)"), DEFAULT_PERMIT_BAREMULTISIG)); @@ -913,10 +913,11 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) fPruneMode = true; } + RegisterAllCoreRPCCommands(tableRPC); #ifdef ENABLE_WALLET bool fDisableWallet = GetBoolArg("-disablewallet", false); if (!fDisableWallet) - walletRegisterRPCCommands(); + RegisterWalletRPCCommands(tableRPC); #endif nConnectTimeout = GetArg("-timeout", DEFAULT_CONNECT_TIMEOUT); @@ -944,56 +945,8 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) nBytesPerSigOp = GetArg("-bytespersigop", nBytesPerSigOp); #ifdef ENABLE_WALLET - if (mapArgs.count("-mintxfee")) - { - CAmount n = 0; - if (ParseMoney(mapArgs["-mintxfee"], n) && n > 0) - CWallet::minTxFee = CFeeRate(n); - 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 > HIGH_TX_FEE_PER_KB) - 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; - if (!ParseMoney(mapArgs["-paytxfee"], nFeePerK)) - return InitError(AmountErrMsg("paytxfee", mapArgs["-paytxfee"])); - if (nFeePerK > HIGH_TX_FEE_PER_KB) - InitWarning(_("-paytxfee is set very high! This is the transaction fee you will pay if you send a transaction.")); - payTxFee = CFeeRate(nFeePerK, 1000); - if (payTxFee < ::minRelayTxFee) - { - return InitError(strprintf(_("Invalid amount for -paytxfee=<amount>: '%s' (must be at least %s)"), - mapArgs["-paytxfee"], ::minRelayTxFee.ToString())); - } - } - if (mapArgs.count("-maxtxfee")) - { - CAmount nMaxFee = 0; - if (!ParseMoney(mapArgs["-maxtxfee"], nMaxFee)) - return InitError(AmountErrMsg("maxtxfee", mapArgs["-maxtxfee"])); - if (nMaxFee > HIGH_MAX_TX_FEE) - InitWarning(_("-maxtxfee is set very high! Fees this large could be paid on a single transaction.")); - maxTxFee = nMaxFee; - if (CFeeRate(maxTxFee, 1000) < ::minRelayTxFee) - { - return InitError(strprintf(_("Invalid amount for -maxtxfee=<amount>: '%s' (must be at least the minrelay fee of %s to prevent stuck transactions)"), - mapArgs["-maxtxfee"], ::minRelayTxFee.ToString())); - } - } - nTxConfirmTarget = GetArg("-txconfirmtarget", DEFAULT_TX_CONFIRM_TARGET); - bSpendZeroConfChange = GetBoolArg("-spendzeroconfchange", DEFAULT_SPEND_ZEROCONF_CHANGE); - fSendFreeTransactions = GetBoolArg("-sendfreetransactions", DEFAULT_SEND_FREE_TRANSACTIONS); - - std::string strWalletFile = GetArg("-wallet", DEFAULT_WALLET_DAT); + if (!CWallet::ParameterInteraction()) + return false; #endif // ENABLE_WALLET fIsBareMultisigStd = GetBoolArg("-permitbaremultisig", DEFAULT_PERMIT_BAREMULTISIG); @@ -1028,11 +981,7 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) return InitError(strprintf(_("Initialization sanity check failed. %s is shutting down."), _(PACKAGE_NAME))); std::string strDataDir = GetDataDir().string(); -#ifdef ENABLE_WALLET - // Wallet file must be a plain filename without a directory - if (strWalletFile != boost::filesystem::basename(strWalletFile) + boost::filesystem::extension(strWalletFile)) - return InitError(strprintf(_("Wallet %s resides outside data directory %s"), strWalletFile, strDataDir)); -#endif + // Make sure only a single Bitcoin process is using the data directory. boost::filesystem::path pathLockFile = GetDataDir() / ".lock"; FILE* file = fopen(pathLockFile.string().c_str(), "a"); // empty lock file; created if it doesn't exist. @@ -1093,20 +1042,8 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) // ********************************************************* Step 5: verify wallet database integrity #ifdef ENABLE_WALLET if (!fDisableWallet) { - LogPrintf("Using wallet %s\n", strWalletFile); - uiInterface.InitMessage(_("Verifying wallet...")); - - std::string warningString; - std::string errorString; - - if (!CWallet::Verify(strWalletFile, warningString, errorString)) + if (!CWallet::Verify()) return false; - - if (!warningString.empty()) - InitWarning(warningString); - if (!errorString.empty()) - return InitError(errorString); - } // (!fDisableWallet) #endif // ENABLE_WALLET // ********************************************************* Step 6: network initialization @@ -1417,16 +1354,7 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) pwalletMain = NULL; LogPrintf("Wallet disabled!\n"); } else { - std::string warningString; - std::string errorString; - pwalletMain = CWallet::InitLoadWallet(fDisableWallet, strWalletFile, warningString, errorString); - if (!warningString.empty()) - InitWarning(warningString); - if (!errorString.empty()) - { - LogPrintf("%s", errorString); - return InitError(errorString); - } + CWallet::InitLoadWallet(); if (!pwalletMain) return false; } diff --git a/src/init.h b/src/init.h index af1b94b72a..63e07ccb3c 100644 --- a/src/init.h +++ b/src/init.h @@ -16,8 +16,6 @@ namespace boost class thread_group; } // namespace boost -extern CWallet* pwalletMain; - void StartShutdown(); bool ShutdownRequested(); /** Interrupt threads */ diff --git a/src/main.cpp b/src/main.cpp index 36189f4ffc..2c0b3bfee7 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -2286,6 +2286,13 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin flags |= SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY; } + // Start enforcing BIP68 (sequence locks) and BIP112 (CHECKSEQUENCEVERIFY) using versionbits logic. + int nLockTimeFlags = 0; + if (VersionBitsState(pindex->pprev, chainparams.GetConsensus(), Consensus::DEPLOYMENT_CSV, versionbitscache) == THRESHOLD_ACTIVE) { + flags |= SCRIPT_VERIFY_CHECKSEQUENCEVERIFY; + nLockTimeFlags |= LOCKTIME_VERIFY_SEQUENCE; + } + int64_t nTime2 = GetTimeMicros(); nTimeForks += nTime2 - nTime1; LogPrint("bench", " - Fork checks: %.2fms [%.2fs]\n", 0.001 * (nTime2 - nTime1), nTimeForks * 0.000001); @@ -2294,7 +2301,6 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin CCheckQueueControl<CScriptCheck> control(fScriptChecks && nScriptCheckThreads ? &scriptcheckqueue : NULL); std::vector<int> prevheights; - int nLockTimeFlags = 0; CAmount nFees = 0; int nInputs = 0; unsigned int nSigOps = 0; @@ -2549,8 +2555,8 @@ void static UpdateTip(CBlockIndex *pindexNew) { nTimeBestReceived = GetTime(); mempool.AddTransactionsUpdated(1); - LogPrintf("%s: new best=%s height=%d bits=%d log2_work=%.8g tx=%lu date=%s progress=%f cache=%.1fMiB(%utx)\n", __func__, - chainActive.Tip()->GetBlockHash().ToString(), chainActive.Height(), chainActive.Tip()->nBits, + LogPrintf("%s: new best=%s height=%d version=0x%08x log2_work=%.8g tx=%lu date='%s' progress=%f cache=%.1fMiB(%utx)\n", __func__, + chainActive.Tip()->GetBlockHash().ToString(), chainActive.Height(), chainActive.Tip()->nVersion, log(chainActive.Tip()->nChainWork.getdouble())/log(2.0), (unsigned long)chainActive.Tip()->nChainTx, DateTimeStrFormat("%Y-%m-%d %H:%M:%S", chainActive.Tip()->GetBlockTime()), Checkpoints::GuessVerificationProgress(chainParams.Checkpoints(), chainActive.Tip()), pcoinsTip->DynamicMemoryUsage() * (1.0 / (1<<20)), pcoinsTip->GetCacheSize()); @@ -3284,8 +3290,8 @@ bool ContextualCheckBlockHeader(const CBlockHeader& block, CValidationState& sta // Reject outdated version blocks when 95% (75% on testnet) of the network has upgraded: for (int32_t version = 2; version < 5; ++version) // check for version 2, 3 and 4 upgrades if (block.nVersion < version && IsSuperMajority(version, pindexPrev, consensusParams.nMajorityRejectBlockOutdated, consensusParams)) - return state.Invalid(false, REJECT_OBSOLETE, strprintf("bad-version(v%d)", version - 1), - strprintf("rejected nVersion=%d block", version - 1)); + return state.Invalid(false, REJECT_OBSOLETE, strprintf("bad-version(0x%08x)", version - 1), + strprintf("rejected nVersion=0x%08x block", version - 1)); return true; } @@ -3295,12 +3301,18 @@ bool ContextualCheckBlock(const CBlock& block, CValidationState& state, CBlockIn const int nHeight = pindexPrev == NULL ? 0 : pindexPrev->nHeight + 1; const Consensus::Params& consensusParams = Params().GetConsensus(); + // Start enforcing BIP113 (Median Time Past) using versionbits logic. + int nLockTimeFlags = 0; + if (VersionBitsState(pindexPrev, consensusParams, Consensus::DEPLOYMENT_CSV, versionbitscache) == THRESHOLD_ACTIVE) { + nLockTimeFlags |= LOCKTIME_MEDIAN_TIME_PAST; + } + + int64_t nLockTimeCutoff = (nLockTimeFlags & LOCKTIME_MEDIAN_TIME_PAST) + ? pindexPrev->GetMedianTimePast() + : block.GetBlockTime(); + // Check that all transactions are finalized BOOST_FOREACH(const CTransaction& tx, block.vtx) { - int nLockTimeFlags = 0; - int64_t nLockTimeCutoff = (nLockTimeFlags & LOCKTIME_MEDIAN_TIME_PAST) - ? pindexPrev->GetMedianTimePast() - : block.GetBlockTime(); if (!IsFinalTx(tx, nHeight, nLockTimeCutoff)) { return state.DoS(10, false, REJECT_INVALID, "bad-txns-nonfinal", false, "non-final transaction"); } diff --git a/src/policy/policy.cpp b/src/policy/policy.cpp index 332abc430e..e3ed7be000 100644 --- a/src/policy/policy.cpp +++ b/src/policy/policy.cpp @@ -55,7 +55,7 @@ bool IsStandard(const CScript& scriptPubKey, txnouttype& whichType) bool IsStandardTx(const CTransaction& tx, std::string& reason) { - if (tx.nVersion > CTransaction::CURRENT_VERSION || tx.nVersion < 1) { + if (tx.nVersion > CTransaction::MAX_STANDARD_VERSION || tx.nVersion < 1) { reason = "version"; return false; } diff --git a/src/primitives/block.cpp b/src/primitives/block.cpp index 59e949d71a..6fb33230a5 100644 --- a/src/primitives/block.cpp +++ b/src/primitives/block.cpp @@ -18,7 +18,7 @@ uint256 CBlockHeader::GetHash() const std::string CBlock::ToString() const { std::stringstream s; - s << strprintf("CBlock(hash=%s, ver=%d, hashPrevBlock=%s, hashMerkleRoot=%s, nTime=%u, nBits=%08x, nNonce=%u, vtx=%u)\n", + s << strprintf("CBlock(hash=%s, ver=0x%08x, hashPrevBlock=%s, hashMerkleRoot=%s, nTime=%u, nBits=%08x, nNonce=%u, vtx=%u)\n", GetHash().ToString(), nVersion, hashPrevBlock.ToString(), diff --git a/src/primitives/transaction.h b/src/primitives/transaction.h index e124dca365..149816406a 100644 --- a/src/primitives/transaction.h +++ b/src/primitives/transaction.h @@ -207,8 +207,15 @@ private: void UpdateHash() const; public: + // Default transaction version. static const int32_t CURRENT_VERSION=1; + // Changing the default transaction version requires a two step process: first + // adapting relay policy by bumping MAX_STANDARD_VERSION, and then later date + // bumping the default CURRENT_VERSION at which point both CURRENT_VERSION and + // MAX_STANDARD_VERSION will be equal. + static const int32_t MAX_STANDARD_VERSION=2; + // The local variables are made const to prevent unintended modification // without updating the cached hash value. However, CTransaction is not // actually immutable; deserialization and assignment are implemented, diff --git a/src/qt/rpcconsole.cpp b/src/qt/rpcconsole.cpp index 42112c42f1..d8647d902a 100644 --- a/src/qt/rpcconsole.cpp +++ b/src/qt/rpcconsole.cpp @@ -459,6 +459,8 @@ void RPCConsole::setClientModel(ClientModel *model) autoCompleter = new QCompleter(wordList, this); ui->lineEdit->setCompleter(autoCompleter); + // clear the lineEdit after activating from QCompleter + connect(autoCompleter, SIGNAL(activated(const QString&)), ui->lineEdit, SLOT(clear()), Qt::QueuedConnection); } } diff --git a/src/qt/transactiondesc.cpp b/src/qt/transactiondesc.cpp index 1b8bf978ad..bae0cbd1c8 100644 --- a/src/qt/transactiondesc.cpp +++ b/src/qt/transactiondesc.cpp @@ -240,7 +240,8 @@ QString TransactionDesc::toHTML(CWallet *wallet, CWalletTx &wtx, TransactionReco if (wtx.mapValue.count("comment") && !wtx.mapValue["comment"].empty()) strHTML += "<br><b>" + tr("Comment") + ":</b><br>" + GUIUtil::HtmlEscape(wtx.mapValue["comment"], true) + "<br>"; - strHTML += "<b>" + tr("Transaction ID") + ":</b> " + TransactionRecord::formatSubTxId(wtx.GetHash(), rec->idx) + "<br>"; + strHTML += "<b>" + tr("Transaction ID") + ":</b> " + rec->getTxID() + "<br>"; + strHTML += "<b>" + tr("Output index") + ":</b> " + QString::number(rec->getOutputIndex()) + "<br>"; // Message from normal bitcoin:URI (bitcoin:123...?message=example) Q_FOREACH (const PAIRTYPE(std::string, std::string)& r, wtx.vOrderForm) diff --git a/src/qt/transactionrecord.cpp b/src/qt/transactionrecord.cpp index 1efeda93ec..4fe47181f6 100644 --- a/src/qt/transactionrecord.cpp +++ b/src/qt/transactionrecord.cpp @@ -262,11 +262,10 @@ bool TransactionRecord::statusUpdateNeeded() QString TransactionRecord::getTxID() const { - return formatSubTxId(hash, idx); + return QString::fromStdString(hash.ToString()); } -QString TransactionRecord::formatSubTxId(const uint256 &hash, int vout) +int TransactionRecord::getOutputIndex() const { - return QString::fromStdString(hash.ToString() + strprintf("-%03d", vout)); + return idx; } - diff --git a/src/qt/transactionrecord.h b/src/qt/transactionrecord.h index 330cd48cfa..8c754c3aad 100644 --- a/src/qt/transactionrecord.h +++ b/src/qt/transactionrecord.h @@ -129,8 +129,8 @@ public: /** Return the unique identifier for this transaction (part) */ QString getTxID() const; - /** Format subtransaction id */ - static QString formatSubTxId(const uint256 &hash, int vout); + /** Return the output index of the subtransaction */ + int getOutputIndex() const; /** Update status from core wallet tx. */ diff --git a/src/rest.cpp b/src/rest.cpp index ebdccc9402..2dff8d7dad 100644 --- a/src/rest.cpp +++ b/src/rest.cpp @@ -273,6 +273,9 @@ static bool rest_block_notxdetails(HTTPRequest* req, const std::string& strURIPa return rest_block(req, strURIPart, false); } +// A bit of a hack - dependency on a function defined in rpc/blockchain.cpp +UniValue getblockchaininfo(const UniValue& params, bool fHelp); + static bool rest_chaininfo(HTTPRequest* req, const std::string& strURIPart) { if (!CheckWarmup(req)) diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp index a110dff0d1..f1c9d9f7ab 100644 --- a/src/rpc/blockchain.cpp +++ b/src/rpc/blockchain.cpp @@ -681,6 +681,7 @@ UniValue getblockchaininfo(const UniValue& params, bool fHelp) softforks.push_back(SoftForkDesc("bip34", 2, tip, consensusParams)); softforks.push_back(SoftForkDesc("bip66", 3, tip, consensusParams)); softforks.push_back(SoftForkDesc("bip65", 4, tip, consensusParams)); + bip9_softforks.push_back(BIP9SoftForkDesc("csv", consensusParams, Consensus::DEPLOYMENT_CSV)); obj.push_back(Pair("softforks", softforks)); obj.push_back(Pair("bip9_softforks", bip9_softforks)); @@ -911,3 +912,31 @@ UniValue reconsiderblock(const UniValue& params, bool fHelp) return NullUniValue; } + +static const CRPCCommand commands[] = +{ // category name actor (function) okSafeMode + // --------------------- ------------------------ ----------------------- ---------- + { "blockchain", "getblockchaininfo", &getblockchaininfo, true }, + { "blockchain", "getbestblockhash", &getbestblockhash, true }, + { "blockchain", "getblockcount", &getblockcount, true }, + { "blockchain", "getblock", &getblock, true }, + { "blockchain", "getblockhash", &getblockhash, true }, + { "blockchain", "getblockheader", &getblockheader, true }, + { "blockchain", "getchaintips", &getchaintips, true }, + { "blockchain", "getdifficulty", &getdifficulty, true }, + { "blockchain", "getmempoolinfo", &getmempoolinfo, true }, + { "blockchain", "getrawmempool", &getrawmempool, true }, + { "blockchain", "gettxout", &gettxout, true }, + { "blockchain", "gettxoutsetinfo", &gettxoutsetinfo, true }, + { "blockchain", "verifychain", &verifychain, true }, + + /* Not shown in help */ + { "hidden", "invalidateblock", &invalidateblock, true }, + { "hidden", "reconsiderblock", &reconsiderblock, true }, +}; + +void RegisterBlockchainRPCCommands(CRPCTable &tableRPC) +{ + for (unsigned int vcidx = 0; vcidx < ARRAYLEN(commands); vcidx++) + tableRPC.appendCommand(commands[vcidx].name, &commands[vcidx]); +} diff --git a/src/rpc/client.cpp b/src/rpc/client.cpp index 89420b93d7..b040d2bc80 100644 --- a/src/rpc/client.cpp +++ b/src/rpc/client.cpp @@ -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/rpc/mining.cpp b/src/rpc/mining.cpp index a2abbb323d..b63ee22889 100644 --- a/src/rpc/mining.cpp +++ b/src/rpc/mining.cpp @@ -781,3 +781,27 @@ UniValue estimatesmartpriority(const UniValue& params, bool fHelp) result.push_back(Pair("blocks", answerFound)); return result; } + +static const CRPCCommand commands[] = +{ // category name actor (function) okSafeMode + // --------------------- ------------------------ ----------------------- ---------- + { "mining", "getnetworkhashps", &getnetworkhashps, true }, + { "mining", "getmininginfo", &getmininginfo, true }, + { "mining", "prioritisetransaction", &prioritisetransaction, true }, + { "mining", "getblocktemplate", &getblocktemplate, true }, + { "mining", "submitblock", &submitblock, true }, + + { "generating", "generate", &generate, true }, + { "generating", "generatetoaddress", &generatetoaddress, true }, + + { "util", "estimatefee", &estimatefee, true }, + { "util", "estimatepriority", &estimatepriority, true }, + { "util", "estimatesmartfee", &estimatesmartfee, true }, + { "util", "estimatesmartpriority", &estimatesmartpriority, true }, +}; + +void RegisterMiningRPCCommands(CRPCTable &tableRPC) +{ + for (unsigned int vcidx = 0; vcidx < ARRAYLEN(commands); vcidx++) + tableRPC.appendCommand(commands[vcidx].name, &commands[vcidx]); +} diff --git a/src/rpc/misc.cpp b/src/rpc/misc.cpp index 0aab9c3043..e8a099b445 100644 --- a/src/rpc/misc.cpp +++ b/src/rpc/misc.cpp @@ -396,3 +396,21 @@ UniValue setmocktime(const UniValue& params, bool fHelp) return NullUniValue; } + +static const CRPCCommand commands[] = +{ // category name actor (function) okSafeMode + // --------------------- ------------------------ ----------------------- ---------- + { "control", "getinfo", &getinfo, true }, /* uses wallet if enabled */ + { "util", "validateaddress", &validateaddress, true }, /* uses wallet if enabled */ + { "util", "createmultisig", &createmultisig, true }, + { "util", "verifymessage", &verifymessage, true }, + + /* Not shown in help */ + { "hidden", "setmocktime", &setmocktime, true }, +}; + +void RegisterMiscRPCCommands(CRPCTable &tableRPC) +{ + for (unsigned int vcidx = 0; vcidx < ARRAYLEN(commands); vcidx++) + tableRPC.appendCommand(commands[vcidx].name, &commands[vcidx]); +} diff --git a/src/rpc/net.cpp b/src/rpc/net.cpp index 065214a98a..017cd6ca32 100644 --- a/src/rpc/net.cpp +++ b/src/rpc/net.cpp @@ -626,3 +626,25 @@ UniValue clearbanned(const UniValue& params, bool fHelp) return NullUniValue; } + +static const CRPCCommand commands[] = +{ // category name actor (function) okSafeMode + // --------------------- ------------------------ ----------------------- ---------- + { "network", "getconnectioncount", &getconnectioncount, true }, + { "network", "ping", &ping, true }, + { "network", "getpeerinfo", &getpeerinfo, true }, + { "network", "addnode", &addnode, true }, + { "network", "disconnectnode", &disconnectnode, true }, + { "network", "getaddednodeinfo", &getaddednodeinfo, true }, + { "network", "getnettotals", &getnettotals, true }, + { "network", "getnetworkinfo", &getnetworkinfo, true }, + { "network", "setban", &setban, true }, + { "network", "listbanned", &listbanned, true }, + { "network", "clearbanned", &clearbanned, true }, +}; + +void RegisterNetRPCCommands(CRPCTable &tableRPC) +{ + for (unsigned int vcidx = 0; vcidx < ARRAYLEN(commands); vcidx++) + tableRPC.appendCommand(commands[vcidx].name, &commands[vcidx]); +} diff --git a/src/rpc/rawtransaction.cpp b/src/rpc/rawtransaction.cpp index 34dd3b30f5..de8cd68f66 100644 --- a/src/rpc/rawtransaction.cpp +++ b/src/rpc/rawtransaction.cpp @@ -841,3 +841,23 @@ UniValue sendrawtransaction(const UniValue& params, bool fHelp) return hashTx.GetHex(); } + +static const CRPCCommand commands[] = +{ // category name actor (function) okSafeMode + // --------------------- ------------------------ ----------------------- ---------- + { "rawtransactions", "getrawtransaction", &getrawtransaction, true }, + { "rawtransactions", "createrawtransaction", &createrawtransaction, true }, + { "rawtransactions", "decoderawtransaction", &decoderawtransaction, true }, + { "rawtransactions", "decodescript", &decodescript, true }, + { "rawtransactions", "sendrawtransaction", &sendrawtransaction, false }, + { "rawtransactions", "signrawtransaction", &signrawtransaction, false }, /* uses wallet if enabled */ + + { "blockchain", "gettxoutproof", &gettxoutproof, true }, + { "blockchain", "verifytxoutproof", &verifytxoutproof, true }, +}; + +void RegisterRawTransactionRPCCommands(CRPCTable &tableRPC) +{ + for (unsigned int vcidx = 0; vcidx < ARRAYLEN(commands); vcidx++) + tableRPC.appendCommand(commands[vcidx].name, &commands[vcidx]); +} diff --git a/src/rpc/register.h b/src/rpc/register.h new file mode 100644 index 0000000000..01aa58a25d --- /dev/null +++ b/src/rpc/register.h @@ -0,0 +1,32 @@ +// Copyright (c) 2009-2016 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#ifndef BITCOIN_RPCREGISTER_H +#define BITCOIN_RPCREGISTER_H + +/** These are in one header file to avoid creating tons of single-function + * headers for everything under src/rpc/ */ +class CRPCTable; + +/** Register block chain RPC commands */ +void RegisterBlockchainRPCCommands(CRPCTable &tableRPC); +/** Register P2P networking RPC commands */ +void RegisterNetRPCCommands(CRPCTable &tableRPC); +/** Register miscellaneous RPC commands */ +void RegisterMiscRPCCommands(CRPCTable &tableRPC); +/** Register mining RPC commands */ +void RegisterMiningRPCCommands(CRPCTable &tableRPC); +/** Register raw transaction RPC commands */ +void RegisterRawTransactionRPCCommands(CRPCTable &tableRPC); + +static inline void RegisterAllCoreRPCCommands(CRPCTable &tableRPC) +{ + RegisterBlockchainRPCCommands(tableRPC); + RegisterNetRPCCommands(tableRPC); + RegisterMiscRPCCommands(tableRPC); + RegisterMiningRPCCommands(tableRPC); + RegisterRawTransactionRPCCommands(tableRPC); +} + +#endif diff --git a/src/rpc/server.cpp b/src/rpc/server.cpp index 1303a3bb13..8326fe14d2 100644 --- a/src/rpc/server.cpp +++ b/src/rpc/server.cpp @@ -256,72 +256,8 @@ static const CRPCCommand vRPCCommands[] = { // category name actor (function) okSafeMode // --------------------- ------------------------ ----------------------- ---------- /* Overall control/query calls */ - { "control", "getinfo", &getinfo, true }, /* uses wallet if enabled */ { "control", "help", &help, true }, { "control", "stop", &stop, true }, - - /* P2P networking */ - { "network", "getnetworkinfo", &getnetworkinfo, true }, - { "network", "addnode", &addnode, true }, - { "network", "disconnectnode", &disconnectnode, true }, - { "network", "getaddednodeinfo", &getaddednodeinfo, true }, - { "network", "getconnectioncount", &getconnectioncount, true }, - { "network", "getnettotals", &getnettotals, true }, - { "network", "getpeerinfo", &getpeerinfo, true }, - { "network", "ping", &ping, true }, - { "network", "setban", &setban, true }, - { "network", "listbanned", &listbanned, true }, - { "network", "clearbanned", &clearbanned, true }, - - /* Block chain and UTXO */ - { "blockchain", "getblockchaininfo", &getblockchaininfo, true }, - { "blockchain", "getbestblockhash", &getbestblockhash, true }, - { "blockchain", "getblockcount", &getblockcount, true }, - { "blockchain", "getblock", &getblock, true }, - { "blockchain", "getblockhash", &getblockhash, true }, - { "blockchain", "getblockheader", &getblockheader, true }, - { "blockchain", "getchaintips", &getchaintips, true }, - { "blockchain", "getdifficulty", &getdifficulty, true }, - { "blockchain", "getmempoolinfo", &getmempoolinfo, true }, - { "blockchain", "getrawmempool", &getrawmempool, true }, - { "blockchain", "gettxout", &gettxout, true }, - { "blockchain", "gettxoutproof", &gettxoutproof, true }, - { "blockchain", "verifytxoutproof", &verifytxoutproof, true }, - { "blockchain", "gettxoutsetinfo", &gettxoutsetinfo, true }, - { "blockchain", "verifychain", &verifychain, true }, - - /* Mining */ - { "mining", "getblocktemplate", &getblocktemplate, true }, - { "mining", "getmininginfo", &getmininginfo, true }, - { "mining", "getnetworkhashps", &getnetworkhashps, true }, - { "mining", "prioritisetransaction", &prioritisetransaction, true }, - { "mining", "submitblock", &submitblock, true }, - - /* Coin generation */ - { "generating", "generate", &generate, true }, - { "generating", "generatetoaddress", &generatetoaddress, true }, - - /* Raw transactions */ - { "rawtransactions", "createrawtransaction", &createrawtransaction, true }, - { "rawtransactions", "decoderawtransaction", &decoderawtransaction, true }, - { "rawtransactions", "decodescript", &decodescript, true }, - { "rawtransactions", "getrawtransaction", &getrawtransaction, true }, - { "rawtransactions", "sendrawtransaction", &sendrawtransaction, false }, - { "rawtransactions", "signrawtransaction", &signrawtransaction, false }, /* uses wallet if enabled */ - - /* Utility functions */ - { "util", "createmultisig", &createmultisig, true }, - { "util", "validateaddress", &validateaddress, true }, /* uses wallet if enabled */ - { "util", "verifymessage", &verifymessage, true }, - { "util", "estimatefee", &estimatefee, true }, - { "util", "estimatepriority", &estimatepriority, true }, - { "util", "estimatesmartfee", &estimatesmartfee, true }, - { "util", "estimatesmartpriority", &estimatesmartpriority, true }, - - /* Not shown in help */ - { "hidden", "invalidateblock", &invalidateblock, true }, - { "hidden", "reconsiderblock", &reconsiderblock, true }, - { "hidden", "setmocktime", &setmocktime, true }, }; CRPCTable::CRPCTable() diff --git a/src/rpc/server.h b/src/rpc/server.h index 35e114feef..a7ed710ce6 100644 --- a/src/rpc/server.h +++ b/src/rpc/server.h @@ -181,65 +181,6 @@ extern std::string HelpExampleRpc(const std::string& methodname, const std::stri extern void EnsureWalletIsUnlocked(); -extern UniValue getconnectioncount(const UniValue& params, bool fHelp); // in rpc/net.cpp -extern UniValue getpeerinfo(const UniValue& params, bool fHelp); -extern UniValue ping(const UniValue& params, bool fHelp); -extern UniValue addnode(const UniValue& params, bool fHelp); -extern UniValue disconnectnode(const UniValue& params, bool fHelp); -extern UniValue getaddednodeinfo(const UniValue& params, bool fHelp); -extern UniValue getnettotals(const UniValue& params, bool fHelp); -extern UniValue setban(const UniValue& params, bool fHelp); -extern UniValue listbanned(const UniValue& params, bool fHelp); -extern UniValue clearbanned(const UniValue& params, bool fHelp); - -extern UniValue generate(const UniValue& params, bool fHelp); -extern UniValue generatetoaddress(const UniValue& params, bool fHelp); -extern UniValue getnetworkhashps(const UniValue& params, bool fHelp); -extern UniValue getmininginfo(const UniValue& params, bool fHelp); -extern UniValue prioritisetransaction(const UniValue& params, bool fHelp); -extern UniValue getblocktemplate(const UniValue& params, bool fHelp); -extern UniValue submitblock(const UniValue& params, bool fHelp); -extern UniValue estimatefee(const UniValue& params, bool fHelp); -extern UniValue estimatepriority(const UniValue& params, bool fHelp); -extern UniValue estimatesmartfee(const UniValue& params, bool fHelp); -extern UniValue estimatesmartpriority(const UniValue& params, bool fHelp); - -extern UniValue verifymessage(const UniValue& params, bool fHelp); -extern UniValue createmultisig(const UniValue& params, bool fHelp); -extern UniValue validateaddress(const UniValue& params, bool fHelp); -extern UniValue getinfo(const UniValue& params, bool fHelp); -extern UniValue getblockchaininfo(const UniValue& params, bool fHelp); -extern UniValue getnetworkinfo(const UniValue& params, bool fHelp); -extern UniValue setmocktime(const UniValue& params, bool fHelp); - -extern UniValue getrawtransaction(const UniValue& params, bool fHelp); // in rpc/rawtransaction.cpp -extern UniValue listunspent(const UniValue& params, bool fHelp); -extern UniValue lockunspent(const UniValue& params, bool fHelp); -extern UniValue listlockunspent(const UniValue& params, bool fHelp); -extern UniValue createrawtransaction(const UniValue& params, bool fHelp); -extern UniValue decoderawtransaction(const UniValue& params, bool fHelp); -extern UniValue decodescript(const UniValue& params, bool fHelp); -extern UniValue signrawtransaction(const UniValue& params, bool fHelp); -extern UniValue sendrawtransaction(const UniValue& params, bool fHelp); -extern UniValue gettxoutproof(const UniValue& params, bool fHelp); -extern UniValue verifytxoutproof(const UniValue& params, bool fHelp); - -extern UniValue getblockcount(const UniValue& params, bool fHelp); // in rpc/blockchain.cpp -extern UniValue getbestblockhash(const UniValue& params, bool fHelp); -extern UniValue getdifficulty(const UniValue& params, bool fHelp); -extern UniValue settxfee(const UniValue& params, bool fHelp); -extern UniValue getmempoolinfo(const UniValue& params, bool fHelp); -extern UniValue getrawmempool(const UniValue& params, bool fHelp); -extern UniValue getblockhash(const UniValue& params, bool fHelp); -extern UniValue getblockheader(const UniValue& params, bool fHelp); -extern UniValue getblock(const UniValue& params, bool fHelp); -extern UniValue gettxoutsetinfo(const UniValue& params, bool fHelp); -extern UniValue gettxout(const UniValue& params, bool fHelp); -extern UniValue verifychain(const UniValue& params, bool fHelp); -extern UniValue getchaintips(const UniValue& params, bool fHelp); -extern UniValue invalidateblock(const UniValue& params, bool fHelp); -extern UniValue reconsiderblock(const UniValue& params, bool fHelp); - bool StartRPC(); void InterruptRPC(); void StopRPC(); diff --git a/src/test/bctest.py b/src/test/bctest.py index 3a8d0ea51b..8105b87ffa 100644 --- a/src/test/bctest.py +++ b/src/test/bctest.py @@ -1,7 +1,7 @@ # Copyright 2014 BitPay, Inc. # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. - +from __future__ import division,print_function,unicode_literals import subprocess import os import json diff --git a/src/test/bitcoin-util-test.py b/src/test/bitcoin-util-test.py index 20afb16a9e..95dd3e81b4 100755 --- a/src/test/bitcoin-util-test.py +++ b/src/test/bitcoin-util-test.py @@ -2,7 +2,7 @@ # Copyright 2014 BitPay, Inc. # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. - +from __future__ import division,print_function,unicode_literals import os import bctest import buildenv diff --git a/src/test/rpc_tests.cpp b/src/test/rpc_tests.cpp index d6309ca384..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> @@ -36,7 +37,7 @@ UniValue CallRPC(string args) string strMethod = vArgs[0]; vArgs.erase(vArgs.begin()); UniValue params = RPCConvertValues(strMethod, vArgs); - + BOOST_CHECK(tableRPC[strMethod]); rpcfn_type method = tableRPC[strMethod]->actor; try { UniValue result = (*method)(params, false); @@ -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/test/test_bitcoin.cpp b/src/test/test_bitcoin.cpp index dadc8b948f..97b9996252 100644 --- a/src/test/test_bitcoin.cpp +++ b/src/test/test_bitcoin.cpp @@ -17,6 +17,8 @@ #include "txdb.h" #include "txmempool.h" #include "ui_interface.h" +#include "rpc/server.h" +#include "rpc/register.h" #ifdef ENABLE_WALLET #include "wallet/db.h" #include "wallet/wallet.h" @@ -29,7 +31,6 @@ #include <boost/thread.hpp> CClientUIInterface uiInterface; // Declared but not defined in ui_interface.h -CWallet* pwalletMain; extern bool fPrintToConsole; extern void noui_connect(); @@ -53,9 +54,12 @@ BasicTestingSetup::~BasicTestingSetup() TestingSetup::TestingSetup(const std::string& chainName) : BasicTestingSetup(chainName) { const CChainParams& chainparams = Params(); + // Ideally we'd move all the RPC tests to the functional testing framework + // instead of unit tests, but for now we need these here. + RegisterAllCoreRPCCommands(tableRPC); #ifdef ENABLE_WALLET bitdb.MakeMock(); - walletRegisterRPCCommands(); + RegisterWalletRPCCommands(tableRPC); #endif ClearDatadirCache(); pathTemp = GetTempPath() / strprintf("test_bitcoin_%lu_%i", (unsigned long)GetTime(), (int)(GetRand(100000))); diff --git a/src/timedata.cpp b/src/timedata.cpp index 4d2f8d1e3b..b6bcf86fbf 100644 --- a/src/timedata.cpp +++ b/src/timedata.cpp @@ -83,7 +83,7 @@ void AddTimeData(const CNetAddr& ip, int64_t nOffsetSample) int64_t nMedian = vTimeOffsets.median(); std::vector<int64_t> vSorted = vTimeOffsets.sorted(); // Only let other nodes change our time by so much - if (abs64(nMedian) < 70 * 60) + if (abs64(nMedian) <= std::max<int64_t>(0, GetArg("-maxtimeadjustment", DEFAULT_MAX_TIME_ADJUSTMENT))) { nTimeOffset = nMedian; } diff --git a/src/timedata.h b/src/timedata.h index 2296baf11b..9f2499c85c 100644 --- a/src/timedata.h +++ b/src/timedata.h @@ -10,6 +10,8 @@ #include <stdint.h> #include <vector> +static const int64_t DEFAULT_MAX_TIME_ADJUSTMENT = 70 * 60; + class CNetAddr; /** diff --git a/src/versionbits.cpp b/src/versionbits.cpp index fbb60c0fc5..78feb8ab0c 100644 --- a/src/versionbits.cpp +++ b/src/versionbits.cpp @@ -25,7 +25,7 @@ ThresholdState AbstractThresholdConditionChecker::GetStateFor(const CBlockIndex* break; } if (pindexPrev->GetMedianTimePast() < nTimeStart) { - // Optimizaton: don't recompute down further, as we know every earlier block will be before the start time + // Optimization: don't recompute down further, as we know every earlier block will be before the start time cache[pindexPrev] = THRESHOLD_DEFINED; break; } diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index a1733bae77..61c9846e11 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -2509,7 +2509,7 @@ extern UniValue importwallet(const UniValue& params, bool fHelp); extern UniValue importprunedfunds(const UniValue& params, bool fHelp); extern UniValue removeprunedfunds(const UniValue& params, bool fHelp); -const CRPCCommand vWalletRPCCommands[] = +static const CRPCCommand commands[] = { // category name actor (function) okSafeMode // --------------------- ------------------------ ----------------------- ---------- { "rawtransactions", "fundrawtransaction", &fundrawtransaction, false }, @@ -2559,14 +2559,8 @@ const CRPCCommand vWalletRPCCommands[] = { "wallet", "removeprunedfunds", &removeprunedfunds, true }, }; -void walletRegisterRPCCommands() +void RegisterWalletRPCCommands(CRPCTable &tableRPC) { - unsigned int vcidx; - for (vcidx = 0; vcidx < ARRAYLEN(vWalletRPCCommands); vcidx++) - { - const CRPCCommand *pcmd; - - pcmd = &vWalletRPCCommands[vcidx]; - tableRPC.appendCommand(pcmd->name, pcmd); - } + for (unsigned int vcidx = 0; vcidx < ARRAYLEN(commands); vcidx++) + tableRPC.appendCommand(commands[vcidx].name, &commands[vcidx]); } diff --git a/src/wallet/rpcwallet.h b/src/wallet/rpcwallet.h index 42e8021afa..a5de7e2de1 100644 --- a/src/wallet/rpcwallet.h +++ b/src/wallet/rpcwallet.h @@ -5,6 +5,8 @@ #ifndef BITCOIN_WALLET_RPCWALLET_H #define BITCOIN_WALLET_RPCWALLET_H -void walletRegisterRPCCommands(); +class CRPCTable; + +void RegisterWalletRPCCommands(CRPCTable &tableRPC); #endif //BITCOIN_WALLET_RPCWALLET_H diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 1ea8d2ffe7..e8c9466710 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -33,6 +33,7 @@ using namespace std; +CWallet* pwalletMain = NULL; /** Transaction fee set by the user */ CFeeRate payTxFee(DEFAULT_TRANSACTION_FEE); unsigned int nTxConfirmTarget = DEFAULT_TX_CONFIRM_TARGET; @@ -364,8 +365,33 @@ void CWallet::Flush(bool shutdown) bitdb.Flush(shutdown); } -bool CWallet::Verify(const string& walletFile, string& warningString, string& errorString) +bool static UIError(const std::string &str) { + uiInterface.ThreadSafeMessageBox(str, "", CClientUIInterface::MSG_ERROR); + return false; +} + +void static UIWarning(const std::string &str) +{ + uiInterface.ThreadSafeMessageBox(str, "", CClientUIInterface::MSG_WARNING); +} + +static std::string AmountErrMsg(const char * const optname, const std::string& strValue) +{ + return strprintf(_("Invalid amount for -%s=<amount>: '%s'"), optname, strValue); +} + +bool CWallet::Verify() +{ + std::string walletFile = GetArg("-wallet", DEFAULT_WALLET_DAT); + + LogPrintf("Using wallet %s\n", walletFile); + uiInterface.InitMessage(_("Verifying wallet...")); + + // Wallet file must be a plain filename without a directory + if (walletFile != boost::filesystem::basename(walletFile) + boost::filesystem::extension(walletFile)) + return UIError(strprintf(_("Wallet %s resides outside data directory %s"), walletFile, GetDataDir().string())); + if (!bitdb.Open(GetDataDir())) { // try moving the database env out of the way @@ -381,9 +407,7 @@ bool CWallet::Verify(const string& walletFile, string& warningString, string& er // try again if (!bitdb.Open(GetDataDir())) { // if it still fails, it probably means we can't even create the database env - string msg = strprintf(_("Error initializing wallet database environment %s!"), GetDataDir()); - errorString += msg; - return true; + return UIError(strprintf(_("Error initializing wallet database environment %s!"), GetDataDir())); } } @@ -399,14 +423,14 @@ bool CWallet::Verify(const string& walletFile, string& warningString, string& er CDBEnv::VerifyResult r = bitdb.Verify(walletFile, CWalletDB::Recover); if (r == CDBEnv::RECOVER_OK) { - warningString += strprintf(_("Warning: Wallet file corrupt, data salvaged!" + UIWarning(strprintf(_("Warning: Wallet file corrupt, data salvaged!" " Original %s saved as %s in %s; if" " your balance or transactions are incorrect you should" " restore from a backup."), - walletFile, "wallet.{timestamp}.bak", GetDataDir()); + walletFile, "wallet.{timestamp}.bak", GetDataDir())); } if (r == CDBEnv::RECOVER_FAIL) - errorString += strprintf(_("%s corrupt, salvage failed"), walletFile); + return UIError(strprintf(_("%s corrupt, salvage failed"), walletFile)); } return true; @@ -3018,20 +3042,20 @@ std::string CWallet::GetWalletHelpString(bool showDebug) return strUsage; } -CWallet* CWallet::InitLoadWallet(bool fDisableWallet, const std::string& strWalletFile, std::string& warningString, std::string& errorString) +bool CWallet::InitLoadWallet() { + std::string walletFile = GetArg("-wallet", DEFAULT_WALLET_DAT); + // needed to restore wallet transaction meta data after -zapwallettxes std::vector<CWalletTx> vWtx; if (GetBoolArg("-zapwallettxes", false)) { uiInterface.InitMessage(_("Zapping all transactions from wallet...")); - CWallet *tempWallet = new CWallet(strWalletFile); + CWallet *tempWallet = new CWallet(walletFile); DBErrors nZapWalletRet = tempWallet->ZapWalletTx(vWtx); if (nZapWalletRet != DB_LOAD_OK) { - errorString = strprintf(_("Error loading %s: Wallet corrupted"), strWalletFile); - uiInterface.InitMessage(strprintf(_("Error loading %s: Wallet corrupted"), strWalletFile)); - return NULL; + return UIError(strprintf(_("Error loading %s: Wallet corrupted"), walletFile)); } delete tempWallet; @@ -3042,32 +3066,27 @@ CWallet* CWallet::InitLoadWallet(bool fDisableWallet, const std::string& strWall int64_t nStart = GetTimeMillis(); bool fFirstRun = true; - CWallet *walletInstance = new CWallet(strWalletFile); + CWallet *walletInstance = new CWallet(walletFile); DBErrors nLoadWalletRet = walletInstance->LoadWallet(fFirstRun); if (nLoadWalletRet != DB_LOAD_OK) { if (nLoadWalletRet == DB_CORRUPT) - errorString += strprintf(_("Error loading %s: Wallet corrupted"), strWalletFile) + "\n"; + return UIError(strprintf(_("Error loading %s: Wallet corrupted"), walletFile)); else if (nLoadWalletRet == DB_NONCRITICAL_ERROR) { - warningString += strprintf(_("Error reading %s! All keys read correctly, but transaction data" + UIWarning(strprintf(_("Error reading %s! All keys read correctly, but transaction data" " or address book entries might be missing or incorrect."), - strWalletFile); + walletFile)); } else if (nLoadWalletRet == DB_TOO_NEW) - errorString += strprintf(_("Error loading %s: Wallet requires newer version of %s"), - strWalletFile, _(PACKAGE_NAME)) + - "\n"; + return UIError(strprintf(_("Error loading %s: Wallet requires newer version of %s"), + walletFile, _(PACKAGE_NAME))); else if (nLoadWalletRet == DB_NEED_REWRITE) { - errorString += strprintf(_("Wallet needed to be rewritten: restart %s to complete"), _(PACKAGE_NAME)) + "\n"; - LogPrintf("%s", errorString); + return UIError(strprintf(_("Wallet needed to be rewritten: restart %s to complete"), _(PACKAGE_NAME))); } else - errorString += strprintf(_("Error loading %s"), strWalletFile) + "\n"; - - if (!errorString.empty()) - return NULL; + return UIError(strprintf(_("Error loading %s"), walletFile)); } if (GetBoolArg("-upgradewallet", fFirstRun)) @@ -3083,8 +3102,7 @@ CWallet* CWallet::InitLoadWallet(bool fDisableWallet, const std::string& strWall LogPrintf("Allowing wallet upgrade up to %i\n", nMaxVersion); if (nMaxVersion < walletInstance->GetVersion()) { - errorString += _("Cannot downgrade wallet") + "\n"; - return NULL; + return UIError(_("Cannot downgrade wallet")); } walletInstance->SetMaxVersion(nMaxVersion); } @@ -3098,10 +3116,7 @@ CWallet* CWallet::InitLoadWallet(bool fDisableWallet, const std::string& strWall if (walletInstance->GetKeyFromPool(newDefaultKey)) { walletInstance->SetDefaultKey(newDefaultKey); if (!walletInstance->SetAddressBook(walletInstance->vchDefaultKey.GetID(), "", "receive")) - { - errorString += _("Cannot write default address") += "\n"; - return NULL; - } + return UIError(_("Cannot write default address") += "\n"); } walletInstance->SetBestChain(chainActive.GetLocator()); @@ -3116,7 +3131,7 @@ CWallet* CWallet::InitLoadWallet(bool fDisableWallet, const std::string& strWall pindexRescan = chainActive.Genesis(); else { - CWalletDB walletdb(strWalletFile); + CWalletDB walletdb(walletFile); CBlockLocator locator; if (walletdb.ReadBestBlock(locator)) pindexRescan = FindForkInGlobalIndex(chainActive, locator); @@ -3135,10 +3150,7 @@ CWallet* CWallet::InitLoadWallet(bool fDisableWallet, const std::string& strWall block = block->pprev; if (pindexRescan != block) - { - errorString = _("Prune: last wallet synchronisation goes beyond pruned data. You need to -reindex (download the whole blockchain again in case of pruned node)"); - return NULL; - } + return UIError(_("Prune: last wallet synchronisation goes beyond pruned data. You need to -reindex (download the whole blockchain again in case of pruned node)")); } uiInterface.InitMessage(_("Rescanning...")); @@ -3152,7 +3164,7 @@ CWallet* CWallet::InitLoadWallet(bool fDisableWallet, const std::string& strWall // Restore wallet transaction metadata after -zapwallettxes=1 if (GetBoolArg("-zapwallettxes", false) && GetArg("-zapwallettxes", "1") != "2") { - CWalletDB walletdb(strWalletFile); + CWalletDB walletdb(walletFile); BOOST_FOREACH(const CWalletTx& wtxOld, vWtx) { @@ -3176,7 +3188,62 @@ CWallet* CWallet::InitLoadWallet(bool fDisableWallet, const std::string& strWall } walletInstance->SetBroadcastTransactions(GetBoolArg("-walletbroadcast", DEFAULT_WALLETBROADCAST)); - return walletInstance; + pwalletMain = walletInstance; + return true; +} + +bool CWallet::ParameterInteraction() +{ + if (mapArgs.count("-mintxfee")) + { + CAmount n = 0; + if (ParseMoney(mapArgs["-mintxfee"], n) && n > 0) + CWallet::minTxFee = CFeeRate(n); + else + return UIError(AmountErrMsg("mintxfee", mapArgs["-mintxfee"])); + } + if (mapArgs.count("-fallbackfee")) + { + CAmount nFeePerK = 0; + if (!ParseMoney(mapArgs["-fallbackfee"], nFeePerK)) + return UIError(strprintf(_("Invalid amount for -fallbackfee=<amount>: '%s'"), mapArgs["-fallbackfee"])); + if (nFeePerK > HIGH_TX_FEE_PER_KB) + UIWarning(_("-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; + if (!ParseMoney(mapArgs["-paytxfee"], nFeePerK)) + return UIError(AmountErrMsg("paytxfee", mapArgs["-paytxfee"])); + if (nFeePerK > HIGH_TX_FEE_PER_KB) + UIWarning(_("-paytxfee is set very high! This is the transaction fee you will pay if you send a transaction.")); + payTxFee = CFeeRate(nFeePerK, 1000); + if (payTxFee < ::minRelayTxFee) + { + return UIError(strprintf(_("Invalid amount for -paytxfee=<amount>: '%s' (must be at least %s)"), + mapArgs["-paytxfee"], ::minRelayTxFee.ToString())); + } + } + if (mapArgs.count("-maxtxfee")) + { + CAmount nMaxFee = 0; + if (!ParseMoney(mapArgs["-maxtxfee"], nMaxFee)) + return UIError(AmountErrMsg("maxtxfee", mapArgs["-maxtxfee"])); + if (nMaxFee > HIGH_MAX_TX_FEE) + UIWarning(_("-maxtxfee is set very high! Fees this large could be paid on a single transaction.")); + maxTxFee = nMaxFee; + if (CFeeRate(maxTxFee, 1000) < ::minRelayTxFee) + { + return UIError(strprintf(_("Invalid amount for -maxtxfee=<amount>: '%s' (must be at least the minrelay fee of %s to prevent stuck transactions)"), + mapArgs["-maxtxfee"], ::minRelayTxFee.ToString())); + } + } + nTxConfirmTarget = GetArg("-txconfirmtarget", DEFAULT_TX_CONFIRM_TARGET); + bSpendZeroConfChange = GetBoolArg("-spendzeroconfchange", DEFAULT_SPEND_ZEROCONF_CHANGE); + fSendFreeTransactions = GetBoolArg("-sendfreetransactions", DEFAULT_SEND_FREE_TRANSACTIONS); + + return true; } CKeyPool::CKeyPool() diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index 5db36f52d1..867f33a7b5 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -28,6 +28,8 @@ #include <boost/shared_ptr.hpp> +extern CWallet* pwalletMain; + /** * Settings */ @@ -841,7 +843,7 @@ public: void Flush(bool shutdown=false); //! Verify the wallet database and perform salvage if required - static bool Verify(const std::string& walletFile, std::string& warningString, std::string& errorString); + static bool Verify(); /** * Address book entry changed. @@ -876,8 +878,11 @@ public: /* Returns the wallets help message */ static std::string GetWalletHelpString(bool showDebug); - /* initializes the wallet, returns a new CWallet instance or a null pointer in case of an error */ - static CWallet* InitLoadWallet(bool fDisableWallet, const std::string& strWalletFile, std::string& warningString, std::string& errorString); + /* Initializes the wallet, returns a new CWallet instance or a null pointer in case of an error */ + static bool InitLoadWallet(); + + /* Wallets parameter interaction */ + static bool ParameterInteraction(); }; /** A key allocated from the key pool. */ |