diff options
-rw-r--r-- | src/chainparams.h | 7 | ||||
-rw-r--r-- | src/init.cpp | 12 | ||||
-rw-r--r-- | src/main.cpp | 23 | ||||
-rw-r--r-- | src/miner.cpp | 22 | ||||
-rw-r--r-- | src/miner.h | 3 | ||||
-rw-r--r-- | src/qt/paymentrequestplus.cpp | 13 | ||||
-rw-r--r-- | src/qt/paymentrequestplus.h | 1 | ||||
-rw-r--r-- | src/qt/paymentserver.cpp | 36 | ||||
-rw-r--r-- | src/qt/paymentserver.h | 2 | ||||
-rw-r--r-- | src/qt/sendcoinsdialog.cpp | 2 | ||||
-rw-r--r-- | src/rpcmining.cpp | 4 | ||||
-rw-r--r-- | src/rpcrawtransaction.cpp | 111 | ||||
-rw-r--r-- | src/rpcserver.cpp | 177 | ||||
-rw-r--r-- | src/rpcserver.h | 1 | ||||
-rw-r--r-- | src/wallet/rpcdump.cpp | 16 | ||||
-rw-r--r-- | src/wallet/rpcwallet.cpp | 226 |
16 files changed, 391 insertions, 265 deletions
diff --git a/src/chainparams.h b/src/chainparams.h index e5e691cc53..0692094478 100644 --- a/src/chainparams.h +++ b/src/chainparams.h @@ -40,11 +40,9 @@ public: }; const Consensus::Params& GetConsensus() const { return consensus; } - const uint256& HashGenesisBlock() const { return consensus.hashGenesisBlock; } const CMessageHeader::MessageStartChars& MessageStart() const { return pchMessageStart; } const std::vector<unsigned char>& AlertKey() const { return vAlertPubKey; } int GetDefaultPort() const { return nDefaultPort; } - const uint256& ProofOfWorkLimit() const { return consensus.powLimit; } int SubsidyHalvingInterval() const { return consensus.nSubsidyHalvingInterval; } int EnforceBlockUpgradeMajority() const { return consensus.nMajorityEnforceBlockUpgrade; } int RejectBlockOutdatedMajority() const { return consensus.nMajorityRejectBlockOutdated; } @@ -58,13 +56,8 @@ public: bool MiningRequiresPeers() const { return fMiningRequiresPeers; } /** Default value for -checkmempool and -checkblockindex argument */ bool DefaultConsistencyChecks() const { return fDefaultConsistencyChecks; } - /** Allow mining of a min-difficulty block */ - bool AllowMinDifficultyBlocks() const { return consensus.fPowAllowMinDifficultyBlocks; } /** Make standard checks */ bool RequireStandard() const { return fRequireStandard; } - int64_t TargetTimespan() const { return consensus.nPowTargetTimespan; } - int64_t TargetSpacing() const { return consensus.nPowTargetSpacing; } - int64_t DifficultyAdjustmentInterval() const { return consensus.nPowTargetTimespan / consensus.nPowTargetSpacing; } /** Make miner stop after a block is found. In RPC, don't return until nGenProcLimit blocks are generated */ bool MineBlocksOnDemand() const { return fMineBlocksOnDemand; } /** In the future use NetworkIDString() for RPC fields */ diff --git a/src/init.cpp b/src/init.cpp index 53e521983f..4d9c233c8c 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -242,11 +242,6 @@ void OnRPCStopped() void OnRPCPreCommand(const CRPCCommand& cmd) { -#ifdef ENABLE_WALLET - if (cmd.reqWallet && !pwalletMain) - throw JSONRPCError(RPC_METHOD_NOT_FOUND, "Method not found (disabled)"); -#endif - // Observe safe mode string strWarning = GetWarnings("rpc"); if (strWarning != "" && !GetBoolArg("-disablesafemode", false) && @@ -607,6 +602,7 @@ bool AppInit2(boost::thread_group& threadGroup) #endif // ********************************************************* Step 2: parameter interactions + const CChainParams& chainparams = Params(); // Set this early so that parameter interactions go to console fPrintToConsole = GetBoolArg("-printtoconsole", false); @@ -699,8 +695,8 @@ bool AppInit2(boost::thread_group& threadGroup) InitWarning(_("Warning: Unsupported argument -benchmark ignored, use -debug=bench.")); // Checkmempool and checkblockindex default to true in regtest mode - mempool.setSanityCheck(GetBoolArg("-checkmempool", Params().DefaultConsistencyChecks())); - fCheckBlockIndex = GetBoolArg("-checkblockindex", Params().DefaultConsistencyChecks()); + mempool.setSanityCheck(GetBoolArg("-checkmempool", chainparams.DefaultConsistencyChecks())); + fCheckBlockIndex = GetBoolArg("-checkblockindex", chainparams.DefaultConsistencyChecks()); Checkpoints::fEnabled = GetBoolArg("-checkpoints", true); // -par=0 means autodetect, but nScriptCheckThreads==0 means no concurrency @@ -1043,7 +1039,7 @@ bool AppInit2(boost::thread_group& threadGroup) // If the loaded chain has a wrong genesis, bail out immediately // (we're likely using a testnet datadir, or the other way around). - if (!mapBlockIndex.empty() && mapBlockIndex.count(Params().HashGenesisBlock()) == 0) + if (!mapBlockIndex.empty() && mapBlockIndex.count(chainparams.GetConsensus().hashGenesisBlock) == 0) return InitError(_("Incorrect or no genesis block found. Wrong datadir for network?")); // Initialize the block index (no-op if non-empty database was already loaded) diff --git a/src/main.cpp b/src/main.cpp index a9051118a8..8dd61a3720 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1680,6 +1680,7 @@ static int64_t nTimeTotal = 0; bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pindex, CCoinsViewCache& view, bool fJustCheck) { + const CChainParams& chainparams = Params(); AssertLockHeld(cs_main); // Check it again in case a previous version let a bad block in if (!CheckBlock(block, state, !fJustCheck, !fJustCheck)) @@ -1691,7 +1692,7 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin // Special case for the genesis block, skipping connection of its transactions // (its coinbase is unspendable) - if (block.GetHash() == Params().HashGenesisBlock()) { + if (block.GetHash() == chainparams.GetConsensus().hashGenesisBlock) { if (!fJustCheck) view.SetBestBlock(pindex->GetBlockHash()); return true; @@ -2541,8 +2542,9 @@ bool CheckBlock(const CBlock& block, CValidationState& state, bool fCheckPOW, bo bool ContextualCheckBlockHeader(const CBlockHeader& block, CValidationState& state, CBlockIndex * const pindexPrev) { + const Consensus::Params& consensusParams = Params().GetConsensus(); uint256 hash = block.GetHash(); - if (hash == Params().HashGenesisBlock()) + if (hash == consensusParams.hashGenesisBlock) return true; assert(pindexPrev); @@ -2612,6 +2614,7 @@ bool ContextualCheckBlock(const CBlock& block, CValidationState& state, CBlockIn bool AcceptBlockHeader(const CBlockHeader& block, CValidationState& state, CBlockIndex** ppindex) { + const CChainParams& chainparams = Params(); AssertLockHeld(cs_main); // Check for duplicate uint256 hash = block.GetHash(); @@ -2632,7 +2635,7 @@ bool AcceptBlockHeader(const CBlockHeader& block, CValidationState& state, CBloc // Get prev block index CBlockIndex* pindexPrev = NULL; - if (hash != Params().HashGenesisBlock()) { + if (hash != chainparams.GetConsensus().hashGenesisBlock) { BlockMap::iterator mi = mapBlockIndex.find(block.hashPrevBlock); if (mi == mapBlockIndex.end()) return state.DoS(10, error("%s: prev block not found", __func__), 0, "bad-prevblk"); @@ -3119,6 +3122,7 @@ bool InitBlockIndex() { bool LoadExternalBlockFile(FILE* fileIn, CDiskBlockPos *dbp) { + const CChainParams& chainparams = Params(); // Map of disk positions for blocks with unknown parent (only used for reindex) static std::multimap<uint256, CDiskBlockPos> mapBlocksUnknownParent; int64_t nStart = GetTimeMillis(); @@ -3164,7 +3168,7 @@ bool LoadExternalBlockFile(FILE* fileIn, CDiskBlockPos *dbp) // detect out of order blocks, and store them for later uint256 hash = block.GetHash(); - if (hash != Params().HashGenesisBlock() && mapBlockIndex.find(block.hashPrevBlock) == mapBlockIndex.end()) { + if (hash != chainparams.GetConsensus().hashGenesisBlock && mapBlockIndex.find(block.hashPrevBlock) == mapBlockIndex.end()) { LogPrint("reindex", "%s: Out of order block %s, parent %s not known\n", __func__, hash.ToString(), block.hashPrevBlock.ToString()); if (dbp) @@ -3179,7 +3183,7 @@ bool LoadExternalBlockFile(FILE* fileIn, CDiskBlockPos *dbp) nLoaded++; if (state.IsError()) break; - } else if (hash != Params().HashGenesisBlock() && mapBlockIndex[hash]->nHeight % 1000 == 0) { + } else if (hash != chainparams.GetConsensus().hashGenesisBlock && mapBlockIndex[hash]->nHeight % 1000 == 0) { LogPrintf("Block Import: already had block %s at height %d\n", hash.ToString(), mapBlockIndex[hash]->nHeight); } @@ -3221,6 +3225,7 @@ bool LoadExternalBlockFile(FILE* fileIn, CDiskBlockPos *dbp) void static CheckBlockIndex() { + const Consensus::Params& consensusParams = Params().GetConsensus(); if (!fCheckBlockIndex) { return; } @@ -3271,7 +3276,7 @@ void static CheckBlockIndex() // Begin: actual consistency checks. if (pindex->pprev == NULL) { // Genesis block checks. - assert(pindex->GetBlockHash() == Params().HashGenesisBlock()); // Genesis block's hash must match. + assert(pindex->GetBlockHash() == consensusParams.hashGenesisBlock); // Genesis block's hash must match. assert(pindex == chainActive.Genesis()); // The current active chain's genesis block must be this block. } // HAVE_DATA is equivalent to VALID_TRANSACTIONS and equivalent to nTx > 0 (we stored the number of transactions in the block) @@ -3585,6 +3590,7 @@ void static ProcessGetData(CNode* pfrom) bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, int64_t nTimeReceived) { + const CChainParams& chainparams = Params(); RandAddSeedPerfmon(); LogPrint("net", "received: %s (%u bytes) peer=%d\n", SanitizeString(strCommand), vRecv.size(), pfrom->id); if (mapArgs.count("-dropmessagestest") && GetRand(atoi(mapArgs["-dropmessagestest"])) == 0) @@ -3844,7 +3850,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, // not a direct successor. pfrom->PushMessage("getheaders", chainActive.GetLocator(pindexBestHeader), inv.hash); CNodeState *nodestate = State(pfrom->GetId()); - if (chainActive.Tip()->GetBlockTime() > GetAdjustedTime() - Params().TargetSpacing() * 20 && + if (chainActive.Tip()->GetBlockTime() > GetAdjustedTime() - chainparams.GetConsensus().nPowTargetSpacing * 20 && nodestate->nBlocksInFlight < MAX_BLOCKS_IN_TRANSIT_PER_PEER) { vToFetch.push_back(inv); // Mark block as in flight already, even though the actual "getdata" message only goes out @@ -4507,6 +4513,7 @@ bool ProcessMessages(CNode* pfrom) bool SendMessages(CNode* pto, bool fSendTrickle) { + const Consensus::Params& consensusParams = Params().GetConsensus(); { // Don't send anything until we get their version message if (pto->nVersion == 0) @@ -4694,7 +4701,7 @@ bool SendMessages(CNode* pto, bool fSendTrickle) // timeout. We compensate for in-flight blocks to prevent killing off peers due to our own downstream link // being saturated. We only count validated in-flight blocks so peers can't advertize nonexisting block hashes // to unreasonably increase our timeout. - if (!pto->fDisconnect && state.vBlocksInFlight.size() > 0 && state.vBlocksInFlight.front().nTime < nNow - 500000 * Params().TargetSpacing() * (4 + state.vBlocksInFlight.front().nValidatedQueuedBefore)) { + if (!pto->fDisconnect && state.vBlocksInFlight.size() > 0 && state.vBlocksInFlight.front().nTime < nNow - 500000 * consensusParams.nPowTargetSpacing * (4 + state.vBlocksInFlight.front().nValidatedQueuedBefore)) { LogPrintf("Timeout downloading block %s from peer=%d, disconnecting\n", state.vBlocksInFlight.front().hash.ToString(), pto->id); pto->fDisconnect = true; } diff --git a/src/miner.cpp b/src/miner.cpp index cf08b78229..3abd2d68e4 100644 --- a/src/miner.cpp +++ b/src/miner.cpp @@ -6,11 +6,12 @@ #include "miner.h" #include "amount.h" -#include "primitives/transaction.h" +#include "chainparams.h" #include "hash.h" #include "main.h" #include "net.h" #include "pow.h" +#include "primitives/transaction.h" #include "timedata.h" #include "util.h" #include "utilmoneystr.h" @@ -78,13 +79,13 @@ public: } }; -void UpdateTime(CBlockHeader* pblock, const CBlockIndex* pindexPrev) +void UpdateTime(CBlockHeader* pblock, const Consensus::Params& consensusParams, const CBlockIndex* pindexPrev) { pblock->nTime = std::max(pindexPrev->GetMedianTimePast()+1, GetAdjustedTime()); // Updating time can change work required on testnet: - if (Params().AllowMinDifficultyBlocks()) - pblock->nBits = GetNextWorkRequired(pindexPrev, pblock, Params().GetConsensus()); + if (consensusParams.fPowAllowMinDifficultyBlocks) + pblock->nBits = GetNextWorkRequired(pindexPrev, pblock, consensusParams); } CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn) @@ -325,7 +326,7 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn) // Fill in header pblock->hashPrevBlock = pindexPrev->GetBlockHash(); - UpdateTime(pblock, pindexPrev); + UpdateTime(pblock, Params().GetConsensus(), pindexPrev); pblock->nBits = GetNextWorkRequired(pindexPrev, pblock, Params().GetConsensus()); pblock->nNonce = 0; pblocktemplate->vTxSigOps[0] = GetLegacySigOpCount(pblock->vtx[0]); @@ -440,6 +441,7 @@ void static BitcoinMiner(CWallet *pwallet) LogPrintf("BitcoinMiner started\n"); SetThreadPriority(THREAD_PRIORITY_LOWEST); RenameThread("bitcoin-miner"); + const CChainParams& chainparams = Params(); // Each thread has its own key and counter CReserveKey reservekey(pwallet); @@ -447,7 +449,7 @@ void static BitcoinMiner(CWallet *pwallet) try { while (true) { - if (Params().MiningRequiresPeers()) { + if (chainparams.MiningRequiresPeers()) { // Busy-wait for the network to come online so we don't waste time mining // on an obsolete chain. In regtest mode we expect to fly solo. while (vNodes.empty()) @@ -496,7 +498,7 @@ void static BitcoinMiner(CWallet *pwallet) SetThreadPriority(THREAD_PRIORITY_LOWEST); // In regression test mode, stop mining after a block is found. - if (Params().MineBlocksOnDemand()) + if (chainparams.MineBlocksOnDemand()) throw boost::thread_interrupted(); break; @@ -506,7 +508,7 @@ void static BitcoinMiner(CWallet *pwallet) // Check for stop or if block needs to be rebuilt boost::this_thread::interruption_point(); // Regtest mode doesn't require peers - if (vNodes.empty() && Params().MiningRequiresPeers()) + if (vNodes.empty() && chainparams.MiningRequiresPeers()) break; if (nNonce >= 0xffff0000) break; @@ -516,8 +518,8 @@ void static BitcoinMiner(CWallet *pwallet) break; // Update nTime every few seconds - UpdateTime(pblock, pindexPrev); - if (Params().AllowMinDifficultyBlocks()) + UpdateTime(pblock, chainparams.GetConsensus(), pindexPrev); + if (chainparams.GetConsensus().fPowAllowMinDifficultyBlocks) { // Changing pblock->nTime can change work required on testnet: hashTarget.SetCompact(pblock->nBits); diff --git a/src/miner.h b/src/miner.h index 5d5c9c86c7..0be3152d97 100644 --- a/src/miner.h +++ b/src/miner.h @@ -14,6 +14,7 @@ class CBlockIndex; class CReserveKey; class CScript; class CWallet; +namespace Consensus { class Params; }; struct CBlockTemplate { @@ -29,6 +30,6 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn); CBlockTemplate* CreateNewBlockWithKey(CReserveKey& reservekey); /** Modify the extranonce in a block */ void IncrementExtraNonce(CBlock* pblock, CBlockIndex* pindexPrev, unsigned int& nExtraNonce); -void UpdateTime(CBlockHeader* block, const CBlockIndex* pindexPrev); +void UpdateTime(CBlockHeader* pblock, const Consensus::Params& consensusParams, const CBlockIndex* pindexPrev); #endif // BITCOIN_MINER_H diff --git a/src/qt/paymentrequestplus.cpp b/src/qt/paymentrequestplus.cpp index b69461ad9e..7e9729eeb9 100644 --- a/src/qt/paymentrequestplus.cpp +++ b/src/qt/paymentrequestplus.cpp @@ -59,12 +59,6 @@ bool PaymentRequestPlus::IsInitialized() const return paymentRequest.IsInitialized(); } -QString PaymentRequestPlus::getPKIType() const -{ - if (!IsInitialized()) return QString("none"); - return QString::fromStdString(paymentRequest.pki_type()); -} - bool PaymentRequestPlus::getMerchant(X509_STORE* certStore, QString& merchant) const { merchant.clear(); @@ -124,7 +118,7 @@ bool PaymentRequestPlus::getMerchant(X509_STORE* certStore, QString& merchant) c // The first cert is the signing cert, the rest are untrusted certs that chain // to a valid root authority. OpenSSL needs them separately. STACK_OF(X509) *chain = sk_X509_new_null(); - for (int i = certs.size()-1; i > 0; i--) { + for (int i = certs.size() - 1; i > 0; i--) { sk_X509_push(chain, certs[i]); } X509 *signing_cert = certs[0]; @@ -172,9 +166,8 @@ bool PaymentRequestPlus::getMerchant(X509_STORE* certStore, QString& merchant) c EVP_MD_CTX_init(&ctx); if (!EVP_VerifyInit_ex(&ctx, digestAlgorithm, NULL) || !EVP_VerifyUpdate(&ctx, data_to_verify.data(), data_to_verify.size()) || - !EVP_VerifyFinal(&ctx, (const unsigned char*)paymentRequest.signature().data(), paymentRequest.signature().size(), pubkey)) { - - throw SSLVerifyError("Bad signature, invalid PaymentRequest."); + !EVP_VerifyFinal(&ctx, (const unsigned char*)paymentRequest.signature().data(), (unsigned int)paymentRequest.signature().size(), pubkey)) { + throw SSLVerifyError("Bad signature, invalid payment request."); } // OpenSSL API for getting human printable strings from certs is baroque. diff --git a/src/qt/paymentrequestplus.h b/src/qt/paymentrequestplus.h index 61f8a3415d..99a7186b85 100644 --- a/src/qt/paymentrequestplus.h +++ b/src/qt/paymentrequestplus.h @@ -29,7 +29,6 @@ public: bool SerializeToString(std::string* output) const; bool IsInitialized() const; - QString getPKIType() const; // Returns true if merchant's identity is authenticated, and // returns human-readable merchant identity in merchant bool getMerchant(X509_STORE* certStore, QString& merchant) const; diff --git a/src/qt/paymentserver.cpp b/src/qt/paymentserver.cpp index ad489de343..09e9949b10 100644 --- a/src/qt/paymentserver.cpp +++ b/src/qt/paymentserver.cpp @@ -97,7 +97,11 @@ static QList<QString> savedPaymentRequests; static void ReportInvalidCertificate(const QSslCertificate& cert) { - qDebug() << "ReportInvalidCertificate: Payment server found an invalid certificate: " << cert.subjectInfo(QSslCertificate::CommonName); +#if QT_VERSION < 0x050000 + qDebug() << QString("%1: Payment server found an invalid certificate: ").arg(__func__) << cert.serialNumber() << cert.subjectInfo(QSslCertificate::CommonName) << cert.subjectInfo(QSslCertificate::OrganizationalUnitName); +#else + qDebug() << QString("%1: Payment server found an invalid certificate: ").arg(__func__) << cert.serialNumber() << cert.subjectInfo(QSslCertificate::CommonName) << cert.subjectInfo(QSslCertificate::DistinguishedNameQualifier) << cert.subjectInfo(QSslCertificate::OrganizationalUnitName); +#endif } // @@ -143,13 +147,20 @@ void PaymentServer::LoadRootCAs(X509_STORE* _store) int nRootCerts = 0; const QDateTime currentTime = QDateTime::currentDateTime(); - foreach (const QSslCertificate& cert, certList) - { + + foreach (const QSslCertificate& cert, certList) { + // Don't log NULL certificates + if (cert.isNull()) + continue; + + // Not yet active/valid, or expired certificate if (currentTime < cert.effectiveDate() || currentTime > cert.expiryDate()) { ReportInvalidCertificate(cert); continue; } + #if QT_VERSION >= 0x050000 + // Blacklisted certificate if (cert.isBlacklisted()) { ReportInvalidCertificate(cert); continue; @@ -301,7 +312,7 @@ PaymentServer::PaymentServer(QObject* parent, bool startLocalServer) : // Install global event filter to catch QFileOpenEvents // on Mac: sent when you click bitcoin: links - // other OSes: helpful when dealing with payment request files (in the future) + // other OSes: helpful when dealing with payment request files if (parent) parent->installEventFilter(this); @@ -332,14 +343,13 @@ PaymentServer::~PaymentServer() } // -// OSX-specific way of handling bitcoin: URIs and -// PaymentRequest mime types +// OSX-specific way of handling bitcoin: URIs and PaymentRequest mime types. +// Also used by paymentservertests.cpp and when opening a payment request file +// via "Open URI..." menu entry. // bool PaymentServer::eventFilter(QObject *object, QEvent *event) { - // clicking on bitcoin: URIs creates FileOpen events on the Mac - if (event->type() == QEvent::FileOpen) - { + if (event->type() == QEvent::FileOpen) { QFileOpenEvent *fileEvent = static_cast<QFileOpenEvent*>(event); if (!fileEvent->file().isEmpty()) handleURIOrFile(fileEvent->file()); @@ -515,7 +525,7 @@ bool PaymentServer::readPaymentRequestFromFile(const QString& filename, PaymentR return request.parse(data); } -bool PaymentServer::processPaymentRequest(PaymentRequestPlus& request, SendCoinsRecipient& recipient) +bool PaymentServer::processPaymentRequest(const PaymentRequestPlus& request, SendCoinsRecipient& recipient) { if (!optionsModel) return false; @@ -560,9 +570,9 @@ bool PaymentServer::processPaymentRequest(PaymentRequestPlus& request, SendCoins addresses.append(QString::fromStdString(CBitcoinAddress(dest).ToString())); } else if (!recipient.authenticatedMerchant.isEmpty()) { - // Insecure payments to custom bitcoin addresses are not supported - // (there is no good way to tell the user where they are paying in a way - // they'd have a chance of understanding). + // Unauthenticated payment requests to custom bitcoin addresses are not supported + // (there is no good way to tell the user where they are paying in a way they'd + // have a chance of understanding). emit message(tr("Payment request rejected"), tr("Unverified payment requests to custom payment scripts are unsupported."), CClientUIInterface::MSG_ERROR); diff --git a/src/qt/paymentserver.h b/src/qt/paymentserver.h index 6bf5ac2eea..32ed27983e 100644 --- a/src/qt/paymentserver.h +++ b/src/qt/paymentserver.h @@ -131,7 +131,7 @@ protected: bool eventFilter(QObject *object, QEvent *event); private: - bool processPaymentRequest(PaymentRequestPlus& request, SendCoinsRecipient& recipient); + bool processPaymentRequest(const PaymentRequestPlus& request, SendCoinsRecipient& recipient); void fetchRequest(const QUrl& url); // Setup networking diff --git a/src/qt/sendcoinsdialog.cpp b/src/qt/sendcoinsdialog.cpp index 774667d4ac..59939fa871 100644 --- a/src/qt/sendcoinsdialog.cpp +++ b/src/qt/sendcoinsdialog.cpp @@ -531,7 +531,7 @@ void SendCoinsDialog::processSendCoinsReturn(const WalletModel::SendCoinsReturn msgParams.first = tr("A fee higher than %1 is considered an absurdly high fee.").arg(BitcoinUnits::formatWithUnit(model->getOptionsModel()->getDisplayUnit(), 10000000)); break; case WalletModel::PaymentRequestExpired: - msgParams.first = tr("Payment request expired!"); + msgParams.first = tr("Payment request expired."); msgParams.second = CClientUIInterface::MSG_ERROR; break; // included to prevent a compiler warning. diff --git a/src/rpcmining.cpp b/src/rpcmining.cpp index 949fe3ed52..851d113f3b 100644 --- a/src/rpcmining.cpp +++ b/src/rpcmining.cpp @@ -45,7 +45,7 @@ Value GetNetworkHashPS(int lookup, int height) { // If lookup is -1, then use blocks since last difficulty change. if (lookup <= 0) - lookup = pb->nHeight % Params().DifficultyAdjustmentInterval() + 1; + lookup = pb->nHeight % Params().GetConsensus().DifficultyAdjustmentInterval() + 1; // If lookup is larger than chain, then set it to chain length. if (lookup > pb->nHeight) @@ -514,7 +514,7 @@ Value getblocktemplate(const Array& params, bool fHelp) CBlock* pblock = &pblocktemplate->block; // pointer for convenience // Update nTime - UpdateTime(pblock, pindexPrev); + UpdateTime(pblock, Params().GetConsensus(), pindexPrev); pblock->nNonce = 0; static const Array aCaps = boost::assign::list_of("proposal"); diff --git a/src/rpcrawtransaction.cpp b/src/rpcrawtransaction.cpp index a79b4e3394..c979217a13 100644 --- a/src/rpcrawtransaction.cpp +++ b/src/rpcrawtransaction.cpp @@ -193,117 +193,6 @@ Value getrawtransaction(const Array& params, bool fHelp) return result; } -#ifdef ENABLE_WALLET -Value listunspent(const Array& params, bool fHelp) -{ - if (fHelp || params.size() > 3) - throw runtime_error( - "listunspent ( minconf maxconf [\"address\",...] )\n" - "\nReturns array of unspent transaction outputs\n" - "with between minconf and maxconf (inclusive) confirmations.\n" - "Optionally filter to only include txouts paid to specified addresses.\n" - "Results are an array of Objects, each of which has:\n" - "{txid, vout, scriptPubKey, amount, confirmations}\n" - "\nArguments:\n" - "1. minconf (numeric, optional, default=1) The minimum confirmations to filter\n" - "2. maxconf (numeric, optional, default=9999999) The maximum confirmations to filter\n" - "3. \"addresses\" (string) A json array of bitcoin addresses to filter\n" - " [\n" - " \"address\" (string) bitcoin address\n" - " ,...\n" - " ]\n" - "\nResult\n" - "[ (array of json object)\n" - " {\n" - " \"txid\" : \"txid\", (string) the transaction id \n" - " \"vout\" : n, (numeric) the vout value\n" - " \"address\" : \"address\", (string) the bitcoin address\n" - " \"account\" : \"account\", (string) DEPRECATED. The associated account, or \"\" for the default account\n" - " \"scriptPubKey\" : \"key\", (string) the script key\n" - " \"amount\" : x.xxx, (numeric) the transaction amount in btc\n" - " \"confirmations\" : n (numeric) The number of confirmations\n" - " }\n" - " ,...\n" - "]\n" - - "\nExamples\n" - + HelpExampleCli("listunspent", "") - + HelpExampleCli("listunspent", "6 9999999 \"[\\\"1PGFqEzfmQch1gKD3ra4k18PNj3tTUUSqg\\\",\\\"1LtvqCaApEdUGFkpKMM4MstjcaL4dKg8SP\\\"]\"") - + HelpExampleRpc("listunspent", "6, 9999999 \"[\\\"1PGFqEzfmQch1gKD3ra4k18PNj3tTUUSqg\\\",\\\"1LtvqCaApEdUGFkpKMM4MstjcaL4dKg8SP\\\"]\"") - ); - - RPCTypeCheck(params, boost::assign::list_of(int_type)(int_type)(array_type)); - - int nMinDepth = 1; - if (params.size() > 0) - nMinDepth = params[0].get_int(); - - int nMaxDepth = 9999999; - if (params.size() > 1) - nMaxDepth = params[1].get_int(); - - set<CBitcoinAddress> setAddress; - if (params.size() > 2) { - Array inputs = params[2].get_array(); - BOOST_FOREACH(Value& input, inputs) { - CBitcoinAddress address(input.get_str()); - if (!address.IsValid()) - throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, string("Invalid Bitcoin address: ")+input.get_str()); - if (setAddress.count(address)) - throw JSONRPCError(RPC_INVALID_PARAMETER, string("Invalid parameter, duplicated address: ")+input.get_str()); - setAddress.insert(address); - } - } - - Array results; - vector<COutput> vecOutputs; - assert(pwalletMain != NULL); - LOCK2(cs_main, pwalletMain->cs_wallet); - pwalletMain->AvailableCoins(vecOutputs, false); - BOOST_FOREACH(const COutput& out, vecOutputs) { - if (out.nDepth < nMinDepth || out.nDepth > nMaxDepth) - continue; - - if (setAddress.size()) { - CTxDestination address; - if (!ExtractDestination(out.tx->vout[out.i].scriptPubKey, address)) - continue; - - if (!setAddress.count(address)) - continue; - } - - CAmount nValue = out.tx->vout[out.i].nValue; - const CScript& pk = out.tx->vout[out.i].scriptPubKey; - Object entry; - entry.push_back(Pair("txid", out.tx->GetHash().GetHex())); - entry.push_back(Pair("vout", out.i)); - CTxDestination address; - if (ExtractDestination(out.tx->vout[out.i].scriptPubKey, address)) { - entry.push_back(Pair("address", CBitcoinAddress(address).ToString())); - if (pwalletMain->mapAddressBook.count(address)) - entry.push_back(Pair("account", pwalletMain->mapAddressBook[address].name)); - } - entry.push_back(Pair("scriptPubKey", HexStr(pk.begin(), pk.end()))); - if (pk.IsPayToScriptHash()) { - CTxDestination address; - if (ExtractDestination(pk, address)) { - const CScriptID& hash = boost::get<const CScriptID&>(address); - CScript redeemScript; - if (pwalletMain->GetCScript(hash, redeemScript)) - entry.push_back(Pair("redeemScript", HexStr(redeemScript.begin(), redeemScript.end()))); - } - } - entry.push_back(Pair("amount",ValueFromAmount(nValue))); - entry.push_back(Pair("confirmations",out.nDepth)); - entry.push_back(Pair("spendable", out.fSpendable)); - results.push_back(entry); - } - - return results; -} -#endif - Value createrawtransaction(const Array& params, bool fHelp) { if (fHelp || params.size() != 2) diff --git a/src/rpcserver.cpp b/src/rpcserver.cpp index 0fd7769a19..e2df41fe21 100644 --- a/src/rpcserver.cpp +++ b/src/rpcserver.cpp @@ -193,11 +193,6 @@ string CRPCTable::help(string strCommand) const continue; if ((strCommand != "" || pcmd->category == "hidden") && strMethod != strCommand) continue; -#ifdef ENABLE_WALLET - if (pcmd->reqWallet && !pwalletMain) - continue; -#endif - try { Array params; @@ -271,114 +266,114 @@ Value stop(const Array& params, bool fHelp) * Call Table */ static const CRPCCommand vRPCCommands[] = -{ // category name actor (function) okSafeMode reqWallet - // --------------------- ------------------------ ----------------------- ---------- --------- +{ // category name actor (function) okSafeMode + // --------------------- ------------------------ ----------------------- ---------- /* Overall control/query calls */ - { "control", "getinfo", &getinfo, true, false }, /* uses wallet if enabled */ - { "control", "help", &help, true, false }, - { "control", "stop", &stop, true, false }, + { "control", "getinfo", &getinfo, true }, /* uses wallet if enabled */ + { "control", "help", &help, true }, + { "control", "stop", &stop, true }, /* P2P networking */ - { "network", "getnetworkinfo", &getnetworkinfo, true, false }, - { "network", "addnode", &addnode, true, false }, - { "network", "getaddednodeinfo", &getaddednodeinfo, true, false }, - { "network", "getconnectioncount", &getconnectioncount, true, false }, - { "network", "getnettotals", &getnettotals, true, false }, - { "network", "getpeerinfo", &getpeerinfo, true, false }, - { "network", "ping", &ping, true, false }, + { "network", "getnetworkinfo", &getnetworkinfo, true }, + { "network", "addnode", &addnode, true }, + { "network", "getaddednodeinfo", &getaddednodeinfo, true }, + { "network", "getconnectioncount", &getconnectioncount, true }, + { "network", "getnettotals", &getnettotals, true }, + { "network", "getpeerinfo", &getpeerinfo, true }, + { "network", "ping", &ping, true }, /* Block chain and UTXO */ - { "blockchain", "getblockchaininfo", &getblockchaininfo, true, false }, - { "blockchain", "getbestblockhash", &getbestblockhash, true, false }, - { "blockchain", "getblockcount", &getblockcount, true, false }, - { "blockchain", "getblock", &getblock, true, false }, - { "blockchain", "getblockhash", &getblockhash, true, false }, - { "blockchain", "getchaintips", &getchaintips, true, false }, - { "blockchain", "getdifficulty", &getdifficulty, true, false }, - { "blockchain", "getmempoolinfo", &getmempoolinfo, true, false }, - { "blockchain", "getrawmempool", &getrawmempool, true, false }, - { "blockchain", "gettxout", &gettxout, true, false }, - { "blockchain", "gettxoutsetinfo", &gettxoutsetinfo, true, false }, - { "blockchain", "verifychain", &verifychain, true, false }, + { "blockchain", "getblockchaininfo", &getblockchaininfo, true }, + { "blockchain", "getbestblockhash", &getbestblockhash, true }, + { "blockchain", "getblockcount", &getblockcount, true }, + { "blockchain", "getblock", &getblock, true }, + { "blockchain", "getblockhash", &getblockhash, 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 }, /* Mining */ - { "mining", "getblocktemplate", &getblocktemplate, true, false }, - { "mining", "getmininginfo", &getmininginfo, true, false }, - { "mining", "getnetworkhashps", &getnetworkhashps, true, false }, - { "mining", "prioritisetransaction", &prioritisetransaction, true, false }, - { "mining", "submitblock", &submitblock, true, false }, + { "mining", "getblocktemplate", &getblocktemplate, true }, + { "mining", "getmininginfo", &getmininginfo, true }, + { "mining", "getnetworkhashps", &getnetworkhashps, true }, + { "mining", "prioritisetransaction", &prioritisetransaction, true }, + { "mining", "submitblock", &submitblock, true }, #ifdef ENABLE_WALLET /* Coin generation */ - { "generating", "getgenerate", &getgenerate, true, false }, - { "generating", "setgenerate", &setgenerate, true, false }, - { "generating", "generate", &generate, true, false }, + { "generating", "getgenerate", &getgenerate, true }, + { "generating", "setgenerate", &setgenerate, true }, + { "generating", "generate", &generate, true }, #endif /* Raw transactions */ - { "rawtransactions", "createrawtransaction", &createrawtransaction, true, false }, - { "rawtransactions", "decoderawtransaction", &decoderawtransaction, true, false }, - { "rawtransactions", "decodescript", &decodescript, true, false }, - { "rawtransactions", "getrawtransaction", &getrawtransaction, true, false }, - { "rawtransactions", "sendrawtransaction", &sendrawtransaction, false, false }, - { "rawtransactions", "signrawtransaction", &signrawtransaction, false, false }, /* uses wallet if enabled */ + { "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, false }, - { "util", "validateaddress", &validateaddress, true, false }, /* uses wallet if enabled */ - { "util", "verifymessage", &verifymessage, true, false }, - { "util", "estimatefee", &estimatefee, true, false }, - { "util", "estimatepriority", &estimatepriority, true, false }, + { "util", "createmultisig", &createmultisig, true }, + { "util", "validateaddress", &validateaddress, true }, /* uses wallet if enabled */ + { "util", "verifymessage", &verifymessage, true }, + { "util", "estimatefee", &estimatefee, true }, + { "util", "estimatepriority", &estimatepriority, true }, /* Not shown in help */ - { "hidden", "invalidateblock", &invalidateblock, true, false }, - { "hidden", "reconsiderblock", &reconsiderblock, true, false }, - { "hidden", "setmocktime", &setmocktime, true, false }, + { "hidden", "invalidateblock", &invalidateblock, true }, + { "hidden", "reconsiderblock", &reconsiderblock, true }, + { "hidden", "setmocktime", &setmocktime, true }, #ifdef ENABLE_WALLET - { "hidden", "resendwallettransactions", &resendwallettransactions, true, true }, + { "hidden", "resendwallettransactions", &resendwallettransactions, true}, #endif #ifdef ENABLE_WALLET /* Wallet */ - { "wallet", "addmultisigaddress", &addmultisigaddress, true, true }, - { "wallet", "backupwallet", &backupwallet, true, true }, - { "wallet", "dumpprivkey", &dumpprivkey, true, true }, - { "wallet", "dumpwallet", &dumpwallet, true, true }, - { "wallet", "encryptwallet", &encryptwallet, true, true }, - { "wallet", "getaccountaddress", &getaccountaddress, true, true }, - { "wallet", "getaccount", &getaccount, true, true }, - { "wallet", "getaddressesbyaccount", &getaddressesbyaccount, true, true }, - { "wallet", "getbalance", &getbalance, false, true }, - { "wallet", "getnewaddress", &getnewaddress, true, true }, - { "wallet", "getrawchangeaddress", &getrawchangeaddress, true, true }, - { "wallet", "getreceivedbyaccount", &getreceivedbyaccount, false, true }, - { "wallet", "getreceivedbyaddress", &getreceivedbyaddress, false, true }, - { "wallet", "gettransaction", &gettransaction, false, true }, - { "wallet", "getunconfirmedbalance", &getunconfirmedbalance, false, true }, - { "wallet", "getwalletinfo", &getwalletinfo, false, true }, - { "wallet", "importprivkey", &importprivkey, true, true }, - { "wallet", "importwallet", &importwallet, true, true }, - { "wallet", "importaddress", &importaddress, true, true }, - { "wallet", "keypoolrefill", &keypoolrefill, true, true }, - { "wallet", "listaccounts", &listaccounts, false, true }, - { "wallet", "listaddressgroupings", &listaddressgroupings, false, true }, - { "wallet", "listlockunspent", &listlockunspent, false, true }, - { "wallet", "listreceivedbyaccount", &listreceivedbyaccount, false, true }, - { "wallet", "listreceivedbyaddress", &listreceivedbyaddress, false, true }, - { "wallet", "listsinceblock", &listsinceblock, false, true }, - { "wallet", "listtransactions", &listtransactions, false, true }, - { "wallet", "listunspent", &listunspent, false, true }, - { "wallet", "lockunspent", &lockunspent, true, true }, - { "wallet", "move", &movecmd, false, true }, - { "wallet", "sendfrom", &sendfrom, false, true }, - { "wallet", "sendmany", &sendmany, false, true }, - { "wallet", "sendtoaddress", &sendtoaddress, false, true }, - { "wallet", "setaccount", &setaccount, true, true }, - { "wallet", "settxfee", &settxfee, true, true }, - { "wallet", "signmessage", &signmessage, true, true }, - { "wallet", "walletlock", &walletlock, true, true }, - { "wallet", "walletpassphrasechange", &walletpassphrasechange, true, true }, - { "wallet", "walletpassphrase", &walletpassphrase, true, true }, + { "wallet", "addmultisigaddress", &addmultisigaddress, true }, + { "wallet", "backupwallet", &backupwallet, true }, + { "wallet", "dumpprivkey", &dumpprivkey, true }, + { "wallet", "dumpwallet", &dumpwallet, true }, + { "wallet", "encryptwallet", &encryptwallet, true }, + { "wallet", "getaccountaddress", &getaccountaddress, true }, + { "wallet", "getaccount", &getaccount, true }, + { "wallet", "getaddressesbyaccount", &getaddressesbyaccount, true }, + { "wallet", "getbalance", &getbalance, false }, + { "wallet", "getnewaddress", &getnewaddress, true }, + { "wallet", "getrawchangeaddress", &getrawchangeaddress, true }, + { "wallet", "getreceivedbyaccount", &getreceivedbyaccount, false }, + { "wallet", "getreceivedbyaddress", &getreceivedbyaddress, false }, + { "wallet", "gettransaction", &gettransaction, false }, + { "wallet", "getunconfirmedbalance", &getunconfirmedbalance, false }, + { "wallet", "getwalletinfo", &getwalletinfo, false }, + { "wallet", "importprivkey", &importprivkey, true }, + { "wallet", "importwallet", &importwallet, true }, + { "wallet", "importaddress", &importaddress, true }, + { "wallet", "keypoolrefill", &keypoolrefill, true }, + { "wallet", "listaccounts", &listaccounts, false }, + { "wallet", "listaddressgroupings", &listaddressgroupings, false }, + { "wallet", "listlockunspent", &listlockunspent, false }, + { "wallet", "listreceivedbyaccount", &listreceivedbyaccount, false }, + { "wallet", "listreceivedbyaddress", &listreceivedbyaddress, false }, + { "wallet", "listsinceblock", &listsinceblock, false }, + { "wallet", "listtransactions", &listtransactions, false }, + { "wallet", "listunspent", &listunspent, false }, + { "wallet", "lockunspent", &lockunspent, true }, + { "wallet", "move", &movecmd, false }, + { "wallet", "sendfrom", &sendfrom, false }, + { "wallet", "sendmany", &sendmany, false }, + { "wallet", "sendtoaddress", &sendtoaddress, false }, + { "wallet", "setaccount", &setaccount, true }, + { "wallet", "settxfee", &settxfee, true }, + { "wallet", "signmessage", &signmessage, true }, + { "wallet", "walletlock", &walletlock, true }, + { "wallet", "walletpassphrasechange", &walletpassphrasechange, true }, + { "wallet", "walletpassphrase", &walletpassphrase, true }, #endif // ENABLE_WALLET }; diff --git a/src/rpcserver.h b/src/rpcserver.h index e7aaed8bdf..c3200d8c35 100644 --- a/src/rpcserver.h +++ b/src/rpcserver.h @@ -98,7 +98,6 @@ public: std::string name; rpcfn_type actor; bool okSafeMode; - bool reqWallet; }; /** diff --git a/src/wallet/rpcdump.cpp b/src/wallet/rpcdump.cpp index b9c92a06c5..ab951d1d7d 100644 --- a/src/wallet/rpcdump.cpp +++ b/src/wallet/rpcdump.cpp @@ -25,6 +25,7 @@ using namespace json_spirit; using namespace std; void EnsureWalletIsUnlocked(); +bool EnsureWalletIsAvailable(bool avoidException); std::string static EncodeDumpTime(int64_t nTime) { return DateTimeStrFormat("%Y-%m-%dT%H:%M:%SZ", nTime); @@ -71,6 +72,9 @@ std::string DecodeDumpString(const std::string &str) { Value importprivkey(const Array& params, bool fHelp) { + if (!EnsureWalletIsAvailable(fHelp)) + return Value::null; + if (fHelp || params.size() < 1 || params.size() > 3) throw runtime_error( "importprivkey \"bitcoinprivkey\" ( \"label\" rescan )\n" @@ -142,6 +146,9 @@ Value importprivkey(const Array& params, bool fHelp) Value importaddress(const Array& params, bool fHelp) { + if (!EnsureWalletIsAvailable(fHelp)) + return Value::null; + if (fHelp || params.size() < 1 || params.size() > 3) throw runtime_error( "importaddress \"address\" ( \"label\" rescan )\n" @@ -212,6 +219,9 @@ Value importaddress(const Array& params, bool fHelp) Value importwallet(const Array& params, bool fHelp) { + if (!EnsureWalletIsAvailable(fHelp)) + return Value::null; + if (fHelp || params.size() != 1) throw runtime_error( "importwallet \"filename\"\n" @@ -313,6 +323,9 @@ Value importwallet(const Array& params, bool fHelp) Value dumpprivkey(const Array& params, bool fHelp) { + if (!EnsureWalletIsAvailable(fHelp)) + return Value::null; + if (fHelp || params.size() != 1) throw runtime_error( "dumpprivkey \"bitcoinaddress\"\n" @@ -348,6 +361,9 @@ Value dumpprivkey(const Array& params, bool fHelp) Value dumpwallet(const Array& params, bool fHelp) { + if (!EnsureWalletIsAvailable(fHelp)) + return Value::null; + if (fHelp || params.size() != 1) throw runtime_error( "dumpwallet \"filename\"\n" diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 29f3eda15d..e03cd5b84e 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -37,6 +37,18 @@ std::string HelpRequiringPassphrase() : ""; } +bool EnsureWalletIsAvailable(bool avoidException) +{ + if (!pwalletMain) + { + if (!avoidException) + throw JSONRPCError(RPC_METHOD_NOT_FOUND, "Method not found (disabled)"); + else + return false; + } + return true; +} + void EnsureWalletIsUnlocked() { if (pwalletMain->IsLocked()) @@ -77,6 +89,9 @@ string AccountFromValue(const Value& value) Value getnewaddress(const Array& params, bool fHelp) { + if (!EnsureWalletIsAvailable(fHelp)) + return Value::null; + if (fHelp || params.size() > 1) throw runtime_error( "getnewaddress ( \"account\" )\n" @@ -153,6 +168,9 @@ CBitcoinAddress GetAccountAddress(string strAccount, bool bForceNew=false) Value getaccountaddress(const Array& params, bool fHelp) { + if (!EnsureWalletIsAvailable(fHelp)) + return Value::null; + if (fHelp || params.size() != 1) throw runtime_error( "getaccountaddress \"account\"\n" @@ -182,6 +200,9 @@ Value getaccountaddress(const Array& params, bool fHelp) Value getrawchangeaddress(const Array& params, bool fHelp) { + if (!EnsureWalletIsAvailable(fHelp)) + return Value::null; + if (fHelp || params.size() > 1) throw runtime_error( "getrawchangeaddress\n" @@ -214,6 +235,9 @@ Value getrawchangeaddress(const Array& params, bool fHelp) Value setaccount(const Array& params, bool fHelp) { + if (!EnsureWalletIsAvailable(fHelp)) + return Value::null; + if (fHelp || params.size() < 1 || params.size() > 2) throw runtime_error( "setaccount \"bitcoinaddress\" \"account\"\n" @@ -257,6 +281,9 @@ Value setaccount(const Array& params, bool fHelp) Value getaccount(const Array& params, bool fHelp) { + if (!EnsureWalletIsAvailable(fHelp)) + return Value::null; + if (fHelp || params.size() != 1) throw runtime_error( "getaccount \"bitcoinaddress\"\n" @@ -286,6 +313,9 @@ Value getaccount(const Array& params, bool fHelp) Value getaddressesbyaccount(const Array& params, bool fHelp) { + if (!EnsureWalletIsAvailable(fHelp)) + return Value::null; + if (fHelp || params.size() != 1) throw runtime_error( "getaddressesbyaccount \"account\"\n" @@ -351,6 +381,9 @@ static void SendMoney(const CTxDestination &address, CAmount nValue, bool fSubtr Value sendtoaddress(const Array& params, bool fHelp) { + if (!EnsureWalletIsAvailable(fHelp)) + return Value::null; + if (fHelp || params.size() < 2 || params.size() > 5) throw runtime_error( "sendtoaddress \"bitcoinaddress\" amount ( \"comment\" \"comment-to\" subtractfeefromamount )\n" @@ -404,6 +437,9 @@ Value sendtoaddress(const Array& params, bool fHelp) Value listaddressgroupings(const Array& params, bool fHelp) { + if (!EnsureWalletIsAvailable(fHelp)) + return Value::null; + if (fHelp) throw runtime_error( "listaddressgroupings\n" @@ -453,6 +489,9 @@ Value listaddressgroupings(const Array& params, bool fHelp) Value signmessage(const Array& params, bool fHelp) { + if (!EnsureWalletIsAvailable(fHelp)) + return Value::null; + if (fHelp || params.size() != 2) throw runtime_error( "signmessage \"bitcoinaddress\" \"message\"\n" @@ -506,6 +545,9 @@ Value signmessage(const Array& params, bool fHelp) Value getreceivedbyaddress(const Array& params, bool fHelp) { + if (!EnsureWalletIsAvailable(fHelp)) + return Value::null; + if (fHelp || params.size() < 1 || params.size() > 2) throw runtime_error( "getreceivedbyaddress \"bitcoinaddress\" ( minconf )\n" @@ -561,6 +603,9 @@ Value getreceivedbyaddress(const Array& params, bool fHelp) Value getreceivedbyaccount(const Array& params, bool fHelp) { + if (!EnsureWalletIsAvailable(fHelp)) + return Value::null; + if (fHelp || params.size() < 1 || params.size() > 2) throw runtime_error( "getreceivedbyaccount \"account\" ( minconf )\n" @@ -647,6 +692,9 @@ CAmount GetAccountBalance(const string& strAccount, int nMinDepth, const isminef Value getbalance(const Array& params, bool fHelp) { + if (!EnsureWalletIsAvailable(fHelp)) + return Value::null; + if (fHelp || params.size() > 3) throw runtime_error( "getbalance ( \"account\" minconf includeWatchonly )\n" @@ -719,6 +767,9 @@ Value getbalance(const Array& params, bool fHelp) Value getunconfirmedbalance(const Array ¶ms, bool fHelp) { + if (!EnsureWalletIsAvailable(fHelp)) + return Value::null; + if (fHelp || params.size() > 0) throw runtime_error( "getunconfirmedbalance\n" @@ -732,6 +783,9 @@ Value getunconfirmedbalance(const Array ¶ms, bool fHelp) Value movecmd(const Array& params, bool fHelp) { + if (!EnsureWalletIsAvailable(fHelp)) + return Value::null; + if (fHelp || params.size() < 3 || params.size() > 5) throw runtime_error( "move \"fromaccount\" \"toaccount\" amount ( minconf \"comment\" )\n" @@ -799,6 +853,9 @@ Value movecmd(const Array& params, bool fHelp) Value sendfrom(const Array& params, bool fHelp) { + if (!EnsureWalletIsAvailable(fHelp)) + return Value::null; + if (fHelp || params.size() < 3 || params.size() > 6) throw runtime_error( "sendfrom \"fromaccount\" \"tobitcoinaddress\" amount ( minconf \"comment\" \"comment-to\" )\n" @@ -859,6 +916,9 @@ Value sendfrom(const Array& params, bool fHelp) Value sendmany(const Array& params, bool fHelp) { + if (!EnsureWalletIsAvailable(fHelp)) + return Value::null; + if (fHelp || params.size() < 2 || params.size() > 5) throw runtime_error( "sendmany \"fromaccount\" {\"address\":amount,...} ( minconf \"comment\" [\"address\",...] )\n" @@ -965,6 +1025,9 @@ extern CScript _createmultisig_redeemScript(const Array& params); Value addmultisigaddress(const Array& params, bool fHelp) { + if (!EnsureWalletIsAvailable(fHelp)) + return Value::null; + if (fHelp || params.size() < 2 || params.size() > 3) { string msg = "addmultisigaddress nrequired [\"key\",...] ( \"account\" )\n" @@ -1143,6 +1206,9 @@ Value ListReceived(const Array& params, bool fByAccounts) Value listreceivedbyaddress(const Array& params, bool fHelp) { + if (!EnsureWalletIsAvailable(fHelp)) + return Value::null; + if (fHelp || params.size() > 3) throw runtime_error( "listreceivedbyaddress ( minconf includeempty includeWatchonly)\n" @@ -1177,6 +1243,9 @@ Value listreceivedbyaddress(const Array& params, bool fHelp) Value listreceivedbyaccount(const Array& params, bool fHelp) { + if (!EnsureWalletIsAvailable(fHelp)) + return Value::null; + if (fHelp || params.size() > 3) throw runtime_error( "listreceivedbyaccount ( minconf includeempty includeWatchonly)\n" @@ -1304,6 +1373,9 @@ void AcentryToJSON(const CAccountingEntry& acentry, const string& strAccount, Ar Value listtransactions(const Array& params, bool fHelp) { + if (!EnsureWalletIsAvailable(fHelp)) + return Value::null; + if (fHelp || params.size() > 4) throw runtime_error( "listtransactions ( \"account\" count from includeWatchonly)\n" @@ -1415,6 +1487,9 @@ Value listtransactions(const Array& params, bool fHelp) Value listaccounts(const Array& params, bool fHelp) { + if (!EnsureWalletIsAvailable(fHelp)) + return Value::null; + if (fHelp || params.size() > 2) throw runtime_error( "listaccounts ( minconf includeWatchonly)\n" @@ -1492,6 +1567,9 @@ Value listaccounts(const Array& params, bool fHelp) Value listsinceblock(const Array& params, bool fHelp) { + if (!EnsureWalletIsAvailable(fHelp)) + return Value::null; + if (fHelp) throw runtime_error( "listsinceblock ( \"blockhash\" target-confirmations includeWatchonly)\n" @@ -1580,6 +1658,9 @@ Value listsinceblock(const Array& params, bool fHelp) Value gettransaction(const Array& params, bool fHelp) { + if (!EnsureWalletIsAvailable(fHelp)) + return Value::null; + if (fHelp || params.size() < 1 || params.size() > 2) throw runtime_error( "gettransaction \"txid\" ( includeWatchonly )\n" @@ -1655,6 +1736,9 @@ Value gettransaction(const Array& params, bool fHelp) Value backupwallet(const Array& params, bool fHelp) { + if (!EnsureWalletIsAvailable(fHelp)) + return Value::null; + if (fHelp || params.size() != 1) throw runtime_error( "backupwallet \"destination\"\n" @@ -1678,6 +1762,9 @@ Value backupwallet(const Array& params, bool fHelp) Value keypoolrefill(const Array& params, bool fHelp) { + if (!EnsureWalletIsAvailable(fHelp)) + return Value::null; + if (fHelp || params.size() > 1) throw runtime_error( "keypoolrefill ( newsize )\n" @@ -1719,6 +1806,9 @@ static void LockWallet(CWallet* pWallet) Value walletpassphrase(const Array& params, bool fHelp) { + if (!EnsureWalletIsAvailable(fHelp)) + return Value::null; + if (pwalletMain->IsCrypted() && (fHelp || params.size() != 2)) throw runtime_error( "walletpassphrase \"passphrase\" timeout\n" @@ -1776,6 +1866,9 @@ Value walletpassphrase(const Array& params, bool fHelp) Value walletpassphrasechange(const Array& params, bool fHelp) { + if (!EnsureWalletIsAvailable(fHelp)) + return Value::null; + if (pwalletMain->IsCrypted() && (fHelp || params.size() != 2)) throw runtime_error( "walletpassphrasechange \"oldpassphrase\" \"newpassphrase\"\n" @@ -1819,6 +1912,9 @@ Value walletpassphrasechange(const Array& params, bool fHelp) Value walletlock(const Array& params, bool fHelp) { + if (!EnsureWalletIsAvailable(fHelp)) + return Value::null; + if (pwalletMain->IsCrypted() && (fHelp || params.size() != 0)) throw runtime_error( "walletlock\n" @@ -1855,6 +1951,9 @@ Value walletlock(const Array& params, bool fHelp) Value encryptwallet(const Array& params, bool fHelp) { + if (!EnsureWalletIsAvailable(fHelp)) + return Value::null; + if (!pwalletMain->IsCrypted() && (fHelp || params.size() != 1)) throw runtime_error( "encryptwallet \"passphrase\"\n" @@ -1909,6 +2008,9 @@ Value encryptwallet(const Array& params, bool fHelp) Value lockunspent(const Array& params, bool fHelp) { + if (!EnsureWalletIsAvailable(fHelp)) + return Value::null; + if (fHelp || params.size() < 1 || params.size() > 2) throw runtime_error( "lockunspent unlock [{\"txid\":\"txid\",\"vout\":n},...]\n" @@ -1990,6 +2092,9 @@ Value lockunspent(const Array& params, bool fHelp) Value listlockunspent(const Array& params, bool fHelp) { + if (!EnsureWalletIsAvailable(fHelp)) + return Value::null; + if (fHelp || params.size() > 0) throw runtime_error( "listlockunspent\n" @@ -2036,6 +2141,9 @@ Value listlockunspent(const Array& params, bool fHelp) Value settxfee(const Array& params, bool fHelp) { + if (!EnsureWalletIsAvailable(fHelp)) + return Value::null; + if (fHelp || params.size() < 1 || params.size() > 1) throw runtime_error( "settxfee amount\n" @@ -2062,6 +2170,9 @@ Value settxfee(const Array& params, bool fHelp) Value getwalletinfo(const Array& params, bool fHelp) { + if (!EnsureWalletIsAvailable(fHelp)) + return Value::null; + if (fHelp || params.size() != 0) throw runtime_error( "getwalletinfo\n" @@ -2099,6 +2210,9 @@ Value getwalletinfo(const Array& params, bool fHelp) Value resendwallettransactions(const Array& params, bool fHelp) { + if (!EnsureWalletIsAvailable(fHelp)) + return Value::null; + if (fHelp || params.size() != 0) throw runtime_error( "resendwallettransactions\n" @@ -2118,3 +2232,115 @@ Value resendwallettransactions(const Array& params, bool fHelp) } return result; } + +Value listunspent(const Array& params, bool fHelp) +{ + if (!EnsureWalletIsAvailable(fHelp)) + return Value::null; + + if (fHelp || params.size() > 3) + throw runtime_error( + "listunspent ( minconf maxconf [\"address\",...] )\n" + "\nReturns array of unspent transaction outputs\n" + "with between minconf and maxconf (inclusive) confirmations.\n" + "Optionally filter to only include txouts paid to specified addresses.\n" + "Results are an array of Objects, each of which has:\n" + "{txid, vout, scriptPubKey, amount, confirmations}\n" + "\nArguments:\n" + "1. minconf (numeric, optional, default=1) The minimum confirmations to filter\n" + "2. maxconf (numeric, optional, default=9999999) The maximum confirmations to filter\n" + "3. \"addresses\" (string) A json array of bitcoin addresses to filter\n" + " [\n" + " \"address\" (string) bitcoin address\n" + " ,...\n" + " ]\n" + "\nResult\n" + "[ (array of json object)\n" + " {\n" + " \"txid\" : \"txid\", (string) the transaction id \n" + " \"vout\" : n, (numeric) the vout value\n" + " \"address\" : \"address\", (string) the bitcoin address\n" + " \"account\" : \"account\", (string) DEPRECATED. The associated account, or \"\" for the default account\n" + " \"scriptPubKey\" : \"key\", (string) the script key\n" + " \"amount\" : x.xxx, (numeric) the transaction amount in btc\n" + " \"confirmations\" : n (numeric) The number of confirmations\n" + " }\n" + " ,...\n" + "]\n" + + "\nExamples\n" + + HelpExampleCli("listunspent", "") + + HelpExampleCli("listunspent", "6 9999999 \"[\\\"1PGFqEzfmQch1gKD3ra4k18PNj3tTUUSqg\\\",\\\"1LtvqCaApEdUGFkpKMM4MstjcaL4dKg8SP\\\"]\"") + + HelpExampleRpc("listunspent", "6, 9999999 \"[\\\"1PGFqEzfmQch1gKD3ra4k18PNj3tTUUSqg\\\",\\\"1LtvqCaApEdUGFkpKMM4MstjcaL4dKg8SP\\\"]\"") + ); + + RPCTypeCheck(params, boost::assign::list_of(int_type)(int_type)(array_type)); + + int nMinDepth = 1; + if (params.size() > 0) + nMinDepth = params[0].get_int(); + + int nMaxDepth = 9999999; + if (params.size() > 1) + nMaxDepth = params[1].get_int(); + + set<CBitcoinAddress> setAddress; + if (params.size() > 2) { + Array inputs = params[2].get_array(); + BOOST_FOREACH(Value& input, inputs) { + CBitcoinAddress address(input.get_str()); + if (!address.IsValid()) + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, string("Invalid Bitcoin address: ")+input.get_str()); + if (setAddress.count(address)) + throw JSONRPCError(RPC_INVALID_PARAMETER, string("Invalid parameter, duplicated address: ")+input.get_str()); + setAddress.insert(address); + } + } + + Array results; + vector<COutput> vecOutputs; + assert(pwalletMain != NULL); + LOCK2(cs_main, pwalletMain->cs_wallet); + pwalletMain->AvailableCoins(vecOutputs, false); + BOOST_FOREACH(const COutput& out, vecOutputs) { + if (out.nDepth < nMinDepth || out.nDepth > nMaxDepth) + continue; + + if (setAddress.size()) { + CTxDestination address; + if (!ExtractDestination(out.tx->vout[out.i].scriptPubKey, address)) + continue; + + if (!setAddress.count(address)) + continue; + } + + CAmount nValue = out.tx->vout[out.i].nValue; + const CScript& pk = out.tx->vout[out.i].scriptPubKey; + Object entry; + entry.push_back(Pair("txid", out.tx->GetHash().GetHex())); + entry.push_back(Pair("vout", out.i)); + CTxDestination address; + if (ExtractDestination(out.tx->vout[out.i].scriptPubKey, address)) { + entry.push_back(Pair("address", CBitcoinAddress(address).ToString())); + if (pwalletMain->mapAddressBook.count(address)) + entry.push_back(Pair("account", pwalletMain->mapAddressBook[address].name)); + } + entry.push_back(Pair("scriptPubKey", HexStr(pk.begin(), pk.end()))); + if (pk.IsPayToScriptHash()) { + CTxDestination address; + if (ExtractDestination(pk, address)) { + const CScriptID& hash = boost::get<const CScriptID&>(address); + CScript redeemScript; + if (pwalletMain->GetCScript(hash, redeemScript)) + entry.push_back(Pair("redeemScript", HexStr(redeemScript.begin(), redeemScript.end()))); + } + } + entry.push_back(Pair("amount",ValueFromAmount(nValue))); + entry.push_back(Pair("confirmations",out.nDepth)); + entry.push_back(Pair("spendable", out.fSpendable)); + results.push_back(entry); + } + + return results; +}
\ No newline at end of file |