mirror of
https://github.com/dashpay/dash.git
synced 2024-12-25 20:12:57 +01:00
merge bitcoin#15638: Pull wallet code out of libbitcoin_server (#4560)
* merge 15638: Move CheckTransaction from lib_server to lib_consensus * merge 15638: Move policy settings to new src/policy/settings unit * merge 15638: Move rpc utility methods to rpc/util * merge 15638: Move rpc rawtransaction util functions to rpc/rawtransaction_util.cpp * merge 15638: Move several units into common libraries * merge 15638: Move wallet load functions to wallet/load unit * merge 15638: Document src subdirectories and different libraries * [build] Add several util units (cleanup) * build: resolve missing declarations by re-specifying headers
This commit is contained in:
parent
a3a8bfee08
commit
d978259654
@ -158,6 +158,7 @@ BITCOIN_CORE_H = \
|
|||||||
compat/sanity.h \
|
compat/sanity.h \
|
||||||
compressor.h \
|
compressor.h \
|
||||||
consensus/consensus.h \
|
consensus/consensus.h \
|
||||||
|
consensus/tx_check.h \
|
||||||
consensus/tx_verify.h \
|
consensus/tx_verify.h \
|
||||||
core_io.h \
|
core_io.h \
|
||||||
core_memusage.h \
|
core_memusage.h \
|
||||||
@ -241,6 +242,7 @@ BITCOIN_CORE_H = \
|
|||||||
policy/feerate.h \
|
policy/feerate.h \
|
||||||
policy/fees.h \
|
policy/fees.h \
|
||||||
policy/policy.h \
|
policy/policy.h \
|
||||||
|
policy/settings.h \
|
||||||
pow.h \
|
pow.h \
|
||||||
protocol.h \
|
protocol.h \
|
||||||
psbt.h \
|
psbt.h \
|
||||||
@ -251,7 +253,7 @@ BITCOIN_CORE_H = \
|
|||||||
rpc/mining.h \
|
rpc/mining.h \
|
||||||
rpc/protocol.h \
|
rpc/protocol.h \
|
||||||
rpc/server.h \
|
rpc/server.h \
|
||||||
rpc/rawtransaction.h \
|
rpc/rawtransaction_util.h \
|
||||||
rpc/register.h \
|
rpc/register.h \
|
||||||
rpc/util.h \
|
rpc/util.h \
|
||||||
saltedhasher.h \
|
saltedhasher.h \
|
||||||
@ -309,6 +311,7 @@ BITCOIN_CORE_H = \
|
|||||||
wallet/crypter.h \
|
wallet/crypter.h \
|
||||||
wallet/db.h \
|
wallet/db.h \
|
||||||
wallet/fees.h \
|
wallet/fees.h \
|
||||||
|
wallet/load.h \
|
||||||
wallet/psbtwallet.h \
|
wallet/psbtwallet.h \
|
||||||
wallet/rpcwallet.h \
|
wallet/rpcwallet.h \
|
||||||
wallet/wallet.h \
|
wallet/wallet.h \
|
||||||
@ -331,6 +334,9 @@ obj/build.h: FORCE
|
|||||||
libdash_util_a-clientversion.$(OBJEXT): obj/build.h
|
libdash_util_a-clientversion.$(OBJEXT): obj/build.h
|
||||||
|
|
||||||
# server: shared between dashd and dash-qt
|
# server: shared between dashd and dash-qt
|
||||||
|
# Contains code accessing mempool and chain state that is meant to be separated
|
||||||
|
# from wallet and gui code (see node/README.md). Shared code should go in
|
||||||
|
# libdash_common or libdash_util libraries, instead.
|
||||||
libdash_server_a_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) $(MINIUPNPC_CPPFLAGS) $(EVENT_CFLAGS) $(EVENT_PTHREADS_CFLAGS)
|
libdash_server_a_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) $(MINIUPNPC_CPPFLAGS) $(EVENT_CFLAGS) $(EVENT_PTHREADS_CFLAGS)
|
||||||
libdash_server_a_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
|
libdash_server_a_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
|
||||||
libdash_server_a_SOURCES = \
|
libdash_server_a_SOURCES = \
|
||||||
@ -338,7 +344,6 @@ libdash_server_a_SOURCES = \
|
|||||||
addrman.cpp \
|
addrman.cpp \
|
||||||
banman.cpp \
|
banman.cpp \
|
||||||
batchedlogger.cpp \
|
batchedlogger.cpp \
|
||||||
bloom.cpp \
|
|
||||||
blockencodings.cpp \
|
blockencodings.cpp \
|
||||||
blockfilter.cpp \
|
blockfilter.cpp \
|
||||||
chain.cpp \
|
chain.cpp \
|
||||||
@ -361,7 +366,6 @@ libdash_server_a_SOURCES = \
|
|||||||
index/blockfilterindex.cpp \
|
index/blockfilterindex.cpp \
|
||||||
index/txindex.cpp \
|
index/txindex.cpp \
|
||||||
interfaces/chain.cpp \
|
interfaces/chain.cpp \
|
||||||
interfaces/handler.cpp \
|
|
||||||
interfaces/node.cpp \
|
interfaces/node.cpp \
|
||||||
init.cpp \
|
init.cpp \
|
||||||
dbwrapper.cpp \
|
dbwrapper.cpp \
|
||||||
@ -389,7 +393,6 @@ libdash_server_a_SOURCES = \
|
|||||||
masternode/payments.cpp \
|
masternode/payments.cpp \
|
||||||
masternode/sync.cpp \
|
masternode/sync.cpp \
|
||||||
masternode/utils.cpp \
|
masternode/utils.cpp \
|
||||||
merkleblock.cpp \
|
|
||||||
messagesigner.cpp \
|
messagesigner.cpp \
|
||||||
miner.cpp \
|
miner.cpp \
|
||||||
net.cpp \
|
net.cpp \
|
||||||
@ -401,6 +404,7 @@ libdash_server_a_SOURCES = \
|
|||||||
noui.cpp \
|
noui.cpp \
|
||||||
policy/fees.cpp \
|
policy/fees.cpp \
|
||||||
policy/policy.cpp \
|
policy/policy.cpp \
|
||||||
|
policy/settings.cpp \
|
||||||
pow.cpp \
|
pow.cpp \
|
||||||
rest.cpp \
|
rest.cpp \
|
||||||
rpc/blockchain.cpp \
|
rpc/blockchain.cpp \
|
||||||
@ -414,7 +418,6 @@ libdash_server_a_SOURCES = \
|
|||||||
rpc/rpcquorums.cpp \
|
rpc/rpcquorums.cpp \
|
||||||
rpc/server.cpp \
|
rpc/server.cpp \
|
||||||
rpc/coinjoin.cpp \
|
rpc/coinjoin.cpp \
|
||||||
rpc/util.cpp \
|
|
||||||
script/sigcache.cpp \
|
script/sigcache.cpp \
|
||||||
shutdown.cpp \
|
shutdown.cpp \
|
||||||
spork.cpp \
|
spork.cpp \
|
||||||
@ -462,7 +465,7 @@ libdash_wallet_a_SOURCES = \
|
|||||||
wallet/crypter.cpp \
|
wallet/crypter.cpp \
|
||||||
wallet/db.cpp \
|
wallet/db.cpp \
|
||||||
wallet/fees.cpp \
|
wallet/fees.cpp \
|
||||||
wallet/init.cpp \
|
wallet/load.cpp \
|
||||||
wallet/psbtwallet.cpp \
|
wallet/psbtwallet.cpp \
|
||||||
wallet/rpcdump.cpp \
|
wallet/rpcdump.cpp \
|
||||||
wallet/rpcwallet.cpp \
|
wallet/rpcwallet.cpp \
|
||||||
@ -571,6 +574,7 @@ libdash_consensus_a_SOURCES = \
|
|||||||
consensus/merkle.cpp \
|
consensus/merkle.cpp \
|
||||||
consensus/merkle.h \
|
consensus/merkle.h \
|
||||||
consensus/params.h \
|
consensus/params.h \
|
||||||
|
consensus/tx_check.cpp \
|
||||||
consensus/validation.h \
|
consensus/validation.h \
|
||||||
hash.cpp \
|
hash.cpp \
|
||||||
hash.h \
|
hash.h \
|
||||||
@ -605,6 +609,7 @@ libdash_common_a_SOURCES = \
|
|||||||
base58.cpp \
|
base58.cpp \
|
||||||
bech32.cpp \
|
bech32.cpp \
|
||||||
bip39.cpp \
|
bip39.cpp \
|
||||||
|
bloom.cpp \
|
||||||
chainparams.cpp \
|
chainparams.cpp \
|
||||||
coins.cpp \
|
coins.cpp \
|
||||||
compressor.cpp \
|
compressor.cpp \
|
||||||
@ -614,12 +619,16 @@ libdash_common_a_SOURCES = \
|
|||||||
key.cpp \
|
key.cpp \
|
||||||
key_io.cpp \
|
key_io.cpp \
|
||||||
keystore.cpp \
|
keystore.cpp \
|
||||||
|
merkleblock.cpp \
|
||||||
netaddress.cpp \
|
netaddress.cpp \
|
||||||
netbase.cpp \
|
netbase.cpp \
|
||||||
net_permissions.cpp \
|
net_permissions.cpp \
|
||||||
policy/feerate.cpp \
|
policy/feerate.cpp \
|
||||||
|
policy/policy.cpp \
|
||||||
psbt.cpp \
|
psbt.cpp \
|
||||||
protocol.cpp \
|
protocol.cpp \
|
||||||
|
rpc/rawtransaction_util.cpp \
|
||||||
|
rpc/util.cpp \
|
||||||
saltedhasher.cpp \
|
saltedhasher.cpp \
|
||||||
scheduler.cpp \
|
scheduler.cpp \
|
||||||
script/descriptor.cpp \
|
script/descriptor.cpp \
|
||||||
@ -648,6 +657,7 @@ libdash_util_a_SOURCES = \
|
|||||||
compat/glibcxx_sanity.cpp \
|
compat/glibcxx_sanity.cpp \
|
||||||
compat/strnlen.cpp \
|
compat/strnlen.cpp \
|
||||||
fs.cpp \
|
fs.cpp \
|
||||||
|
interfaces/handler.cpp \
|
||||||
logging.cpp \
|
logging.cpp \
|
||||||
random.cpp \
|
random.cpp \
|
||||||
rpc/protocol.cpp \
|
rpc/protocol.cpp \
|
||||||
|
65
src/consensus/tx_check.cpp
Normal file
65
src/consensus/tx_check.cpp
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
// Copyright (c) 2017-2018 The Bitcoin Core developers
|
||||||
|
// Distributed under the MIT software license, see the accompanying
|
||||||
|
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||||
|
|
||||||
|
#include <version.h>
|
||||||
|
|
||||||
|
#include <consensus/consensus.h>
|
||||||
|
#include <consensus/tx_check.h>
|
||||||
|
|
||||||
|
#include <primitives/transaction.h>
|
||||||
|
#include <consensus/validation.h>
|
||||||
|
|
||||||
|
bool CheckTransaction(const CTransaction& tx, CValidationState& state)
|
||||||
|
{
|
||||||
|
bool allowEmptyTxInOut = false;
|
||||||
|
if (tx.nType == TRANSACTION_QUORUM_COMMITMENT) {
|
||||||
|
allowEmptyTxInOut = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Basic checks that don't depend on any context
|
||||||
|
if (!allowEmptyTxInOut && tx.vin.empty())
|
||||||
|
return state.DoS(10, false, REJECT_INVALID, "bad-txns-vin-empty");
|
||||||
|
if (!allowEmptyTxInOut && tx.vout.empty())
|
||||||
|
return state.DoS(10, false, REJECT_INVALID, "bad-txns-vout-empty");
|
||||||
|
// Size limits
|
||||||
|
if (::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION) > MAX_LEGACY_BLOCK_SIZE)
|
||||||
|
return state.DoS(100, false, REJECT_INVALID, "bad-txns-oversize");
|
||||||
|
if (tx.vExtraPayload.size() > MAX_TX_EXTRA_PAYLOAD)
|
||||||
|
return state.DoS(100, false, REJECT_INVALID, "bad-txns-payload-oversize");
|
||||||
|
|
||||||
|
// Check for negative or overflow output values
|
||||||
|
CAmount nValueOut = 0;
|
||||||
|
for (const auto& txout : tx.vout) {
|
||||||
|
if (txout.nValue < 0)
|
||||||
|
return state.DoS(100, false, REJECT_INVALID, "bad-txns-vout-negative");
|
||||||
|
if (txout.nValue > MAX_MONEY)
|
||||||
|
return state.DoS(100, false, REJECT_INVALID, "bad-txns-vout-toolarge");
|
||||||
|
nValueOut += txout.nValue;
|
||||||
|
if (!MoneyRange(nValueOut))
|
||||||
|
return state.DoS(100, false, REJECT_INVALID, "bad-txns-txouttotal-toolarge");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for duplicate inputs
|
||||||
|
std::set<COutPoint> vInOutPoints;
|
||||||
|
for (const auto& txin : tx.vin) {
|
||||||
|
if (!vInOutPoints.insert(txin.prevout).second)
|
||||||
|
return state.DoS(100, false, REJECT_INVALID, "bad-txns-inputs-duplicate");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tx.IsCoinBase()) {
|
||||||
|
size_t minCbSize = 2;
|
||||||
|
if (tx.nType == TRANSACTION_COINBASE) {
|
||||||
|
// With the introduction of CbTx, coinbase scripts are not required anymore to hold a valid block height
|
||||||
|
minCbSize = 1;
|
||||||
|
}
|
||||||
|
if (tx.vin[0].scriptSig.size() < minCbSize || tx.vin[0].scriptSig.size() > 100)
|
||||||
|
return state.DoS(100, false, REJECT_INVALID, "bad-cb-length");
|
||||||
|
} else {
|
||||||
|
for (const auto& txin : tx.vin)
|
||||||
|
if (txin.prevout.IsNull())
|
||||||
|
return state.DoS(10, false, REJECT_INVALID, "bad-txns-prevout-null");
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
21
src/consensus/tx_check.h
Normal file
21
src/consensus/tx_check.h
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
// Copyright (c) 2017-2018 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_CONSENSUS_TX_CHECK_H
|
||||||
|
#define BITCOIN_CONSENSUS_TX_CHECK_H
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Context-independent transaction checking code that can be called outside the
|
||||||
|
* bitcoin server and doesn't depend on chain or mempool state. Transaction
|
||||||
|
* verification code that does call server functions or depend on server state
|
||||||
|
* belongs in tx_verify.h/cpp instead.
|
||||||
|
*/
|
||||||
|
|
||||||
|
class CTransaction;
|
||||||
|
class CValidationState;
|
||||||
|
|
||||||
|
/** Context-independent validity checks */
|
||||||
|
bool CheckTransaction(const CTransaction& tx, CValidationState& state);
|
||||||
|
|
||||||
|
#endif // BITCOIN_CONSENSUS_TX_CHECK_H
|
@ -159,65 +159,6 @@ unsigned int GetTransactionSigOpCount(const CTransaction& tx, const CCoinsViewCa
|
|||||||
return nSigOps;
|
return nSigOps;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CheckTransaction(const CTransaction& tx, CValidationState &state)
|
|
||||||
{
|
|
||||||
bool allowEmptyTxInOut = false;
|
|
||||||
if (tx.nType == TRANSACTION_QUORUM_COMMITMENT) {
|
|
||||||
allowEmptyTxInOut = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Basic checks that don't depend on any context
|
|
||||||
if (!allowEmptyTxInOut && tx.vin.empty())
|
|
||||||
return state.DoS(10, false, REJECT_INVALID, "bad-txns-vin-empty");
|
|
||||||
if (!allowEmptyTxInOut && tx.vout.empty())
|
|
||||||
return state.DoS(10, false, REJECT_INVALID, "bad-txns-vout-empty");
|
|
||||||
// Size limits
|
|
||||||
if (::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION) > MAX_LEGACY_BLOCK_SIZE)
|
|
||||||
return state.DoS(100, false, REJECT_INVALID, "bad-txns-oversize");
|
|
||||||
if (tx.vExtraPayload.size() > MAX_TX_EXTRA_PAYLOAD)
|
|
||||||
return state.DoS(100, false, REJECT_INVALID, "bad-txns-payload-oversize");
|
|
||||||
|
|
||||||
// Check for negative or overflow output values
|
|
||||||
CAmount nValueOut = 0;
|
|
||||||
for (const auto& txout : tx.vout)
|
|
||||||
{
|
|
||||||
if (txout.nValue < 0)
|
|
||||||
return state.DoS(100, false, REJECT_INVALID, "bad-txns-vout-negative");
|
|
||||||
if (txout.nValue > MAX_MONEY)
|
|
||||||
return state.DoS(100, false, REJECT_INVALID, "bad-txns-vout-toolarge");
|
|
||||||
nValueOut += txout.nValue;
|
|
||||||
if (!MoneyRange(nValueOut))
|
|
||||||
return state.DoS(100, false, REJECT_INVALID, "bad-txns-txouttotal-toolarge");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check for duplicate inputs
|
|
||||||
std::set<COutPoint> vInOutPoints;
|
|
||||||
for (const auto& txin : tx.vin)
|
|
||||||
{
|
|
||||||
if (!vInOutPoints.insert(txin.prevout).second)
|
|
||||||
return state.DoS(100, false, REJECT_INVALID, "bad-txns-inputs-duplicate");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tx.IsCoinBase())
|
|
||||||
{
|
|
||||||
size_t minCbSize = 2;
|
|
||||||
if (tx.nType == TRANSACTION_COINBASE) {
|
|
||||||
// With the introduction of CbTx, coinbase scripts are not required anymore to hold a valid block height
|
|
||||||
minCbSize = 1;
|
|
||||||
}
|
|
||||||
if (tx.vin[0].scriptSig.size() < minCbSize || tx.vin[0].scriptSig.size() > 100)
|
|
||||||
return state.DoS(100, false, REJECT_INVALID, "bad-cb-length");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
for (const auto& txin : tx.vin)
|
|
||||||
if (txin.prevout.IsNull())
|
|
||||||
return state.DoS(10, false, REJECT_INVALID, "bad-txns-prevout-null");
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Consensus::CheckTxInputs(const CTransaction& tx, CValidationState& state, const CCoinsViewCache& inputs, int nSpendHeight, CAmount& txfee)
|
bool Consensus::CheckTxInputs(const CTransaction& tx, CValidationState& state, const CCoinsViewCache& inputs, int nSpendHeight, CAmount& txfee)
|
||||||
{
|
{
|
||||||
// are the actual inputs available?
|
// are the actual inputs available?
|
||||||
|
@ -17,9 +17,6 @@ class CValidationState;
|
|||||||
|
|
||||||
/** Transaction validation functions */
|
/** Transaction validation functions */
|
||||||
|
|
||||||
/** Context-independent validity checks */
|
|
||||||
bool CheckTransaction(const CTransaction& tx, CValidationState& state);
|
|
||||||
|
|
||||||
namespace Consensus {
|
namespace Consensus {
|
||||||
/**
|
/**
|
||||||
* Check whether all inputs of this transaction are valid (no double spends and amounts)
|
* Check whether all inputs of this transaction are valid (no double spends and amounts)
|
||||||
|
@ -37,6 +37,7 @@
|
|||||||
#include <policy/feerate.h>
|
#include <policy/feerate.h>
|
||||||
#include <policy/fees.h>
|
#include <policy/fees.h>
|
||||||
#include <policy/policy.h>
|
#include <policy/policy.h>
|
||||||
|
#include <policy/settings.h>
|
||||||
#include <rpc/server.h>
|
#include <rpc/server.h>
|
||||||
#include <rpc/register.h>
|
#include <rpc/register.h>
|
||||||
#include <rpc/blockchain.h>
|
#include <rpc/blockchain.h>
|
||||||
|
@ -19,6 +19,7 @@
|
|||||||
#include <rpc/protocol.h>
|
#include <rpc/protocol.h>
|
||||||
#include <rpc/server.h>
|
#include <rpc/server.h>
|
||||||
#include <shutdown.h>
|
#include <shutdown.h>
|
||||||
|
#include <policy/settings.h>
|
||||||
#include <sync.h>
|
#include <sync.h>
|
||||||
#include <threadsafety.h>
|
#include <threadsafety.h>
|
||||||
#include <timedata.h>
|
#include <timedata.h>
|
||||||
|
@ -25,6 +25,7 @@
|
|||||||
#include <policy/feerate.h>
|
#include <policy/feerate.h>
|
||||||
#include <policy/fees.h>
|
#include <policy/fees.h>
|
||||||
#include <policy/policy.h>
|
#include <policy/policy.h>
|
||||||
|
#include <policy/settings.h>
|
||||||
#include <primitives/block.h>
|
#include <primitives/block.h>
|
||||||
#include <rpc/server.h>
|
#include <rpc/server.h>
|
||||||
#include <scheduler.h>
|
#include <scheduler.h>
|
||||||
|
@ -30,6 +30,7 @@
|
|||||||
#include <validation.h>
|
#include <validation.h>
|
||||||
#include <wallet/fees.h>
|
#include <wallet/fees.h>
|
||||||
#include <wallet/rpcwallet.h>
|
#include <wallet/rpcwallet.h>
|
||||||
|
#include <wallet/load.h>
|
||||||
#include <wallet/wallet.h>
|
#include <wallet/wallet.h>
|
||||||
#include <wallet/walletutil.h>
|
#include <wallet/walletutil.h>
|
||||||
|
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
#include <key_io.h>
|
#include <key_io.h>
|
||||||
#include <hash.h>
|
#include <hash.h>
|
||||||
#include <validation.h> // For strMessageMagic
|
#include <util/validation.h> // For strMessageMagic
|
||||||
#include <messagesigner.h>
|
#include <messagesigner.h>
|
||||||
#include <tinyformat.h>
|
#include <tinyformat.h>
|
||||||
#include <util/strencodings.h>
|
#include <util/strencodings.h>
|
||||||
|
22
src/node/README.md
Normal file
22
src/node/README.md
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
# src/node/
|
||||||
|
|
||||||
|
The [`src/node/`](./) directory contains code that needs to access node state
|
||||||
|
(state in `CChain`, `CBlockIndex`, `CCoinsView`, `CTxMemPool`, and similar
|
||||||
|
classes).
|
||||||
|
|
||||||
|
Code in [`src/node/`](./) is meant to be segregated from code in
|
||||||
|
[`src/wallet/`](../wallet/) and [`src/qt/`](../qt/), to ensure wallet and GUI
|
||||||
|
code changes don't interfere with node operation, to allow wallet and GUI code
|
||||||
|
to run in separate processes, and to perhaps eventually allow wallet and GUI
|
||||||
|
code to be maintained in separate source repositories.
|
||||||
|
|
||||||
|
As a rule of thumb, code in one of the [`src/node/`](./),
|
||||||
|
[`src/wallet/`](../wallet/), or [`src/qt/`](../qt/) directories should avoid
|
||||||
|
calling code in the other directories directly, and only invoke it indirectly
|
||||||
|
through the more limited [`src/interfaces/`](../interfaces/) classes.
|
||||||
|
|
||||||
|
The [`src/node/`](./) directory is a new directory introduced in
|
||||||
|
[#14978](https://github.com/bitcoin/bitcoin/pull/14978) and at the moment is
|
||||||
|
sparsely populated. Eventually more substantial files like
|
||||||
|
[`src/validation.cpp`](../validation.cpp) and
|
||||||
|
[`src/txmempool.cpp`](../txmempool.cpp) might be moved there.
|
@ -13,32 +13,6 @@
|
|||||||
|
|
||||||
#include <future>
|
#include <future>
|
||||||
|
|
||||||
std::string TransactionErrorString(const TransactionError err)
|
|
||||||
{
|
|
||||||
switch (err) {
|
|
||||||
case TransactionError::OK:
|
|
||||||
return "No error";
|
|
||||||
case TransactionError::MISSING_INPUTS:
|
|
||||||
return "Missing inputs";
|
|
||||||
case TransactionError::ALREADY_IN_CHAIN:
|
|
||||||
return "Transaction already in block chain";
|
|
||||||
case TransactionError::P2P_DISABLED:
|
|
||||||
return "Peer-to-peer functionality missing or disabled";
|
|
||||||
case TransactionError::MEMPOOL_REJECTED:
|
|
||||||
return "Transaction rejected by AcceptToMemoryPool";
|
|
||||||
case TransactionError::MEMPOOL_ERROR:
|
|
||||||
return "AcceptToMemoryPool failed";
|
|
||||||
case TransactionError::INVALID_PSBT:
|
|
||||||
return "PSBT is not sane";
|
|
||||||
case TransactionError::PSBT_MISMATCH:
|
|
||||||
return "PSBTs not compatible (different transactions)";
|
|
||||||
case TransactionError::SIGHASH_MISMATCH:
|
|
||||||
return "Specified sighash value does not match existing value";
|
|
||||||
// no default case, so the compiler can warn about missing cases
|
|
||||||
}
|
|
||||||
assert(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
TransactionError BroadcastTransaction(const CTransactionRef tx, uint256& hashTx, std::string& err_string, const CAmount& highfee, const bool bypass_limits)
|
TransactionError BroadcastTransaction(const CTransactionRef tx, uint256& hashTx, std::string& err_string, const CAmount& highfee, const bool bypass_limits)
|
||||||
{
|
{
|
||||||
std::promise<void> promise;
|
std::promise<void> promise;
|
||||||
|
@ -8,20 +8,7 @@
|
|||||||
#include <attributes.h>
|
#include <attributes.h>
|
||||||
#include <primitives/transaction.h>
|
#include <primitives/transaction.h>
|
||||||
#include <uint256.h>
|
#include <uint256.h>
|
||||||
|
#include <util/error.h>
|
||||||
enum class TransactionError {
|
|
||||||
OK, //!< No error
|
|
||||||
MISSING_INPUTS,
|
|
||||||
ALREADY_IN_CHAIN,
|
|
||||||
P2P_DISABLED,
|
|
||||||
MEMPOOL_REJECTED,
|
|
||||||
MEMPOOL_ERROR,
|
|
||||||
INVALID_PSBT,
|
|
||||||
PSBT_MISMATCH,
|
|
||||||
SIGHASH_MISMATCH,
|
|
||||||
};
|
|
||||||
|
|
||||||
std::string TransactionErrorString(const TransactionError error);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Broadcast a transaction
|
* Broadcast a transaction
|
||||||
|
@ -26,41 +26,6 @@ std::string StringForFeeEstimateHorizon(FeeEstimateHorizon horizon) {
|
|||||||
|
|
||||||
return horizon_string->second;
|
return horizon_string->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string StringForFeeReason(FeeReason reason) {
|
|
||||||
static const std::map<FeeReason, std::string> fee_reason_strings = {
|
|
||||||
{FeeReason::NONE, "None"},
|
|
||||||
{FeeReason::HALF_ESTIMATE, "Half Target 60% Threshold"},
|
|
||||||
{FeeReason::FULL_ESTIMATE, "Target 85% Threshold"},
|
|
||||||
{FeeReason::DOUBLE_ESTIMATE, "Double Target 95% Threshold"},
|
|
||||||
{FeeReason::CONSERVATIVE, "Conservative Double Target longer horizon"},
|
|
||||||
{FeeReason::MEMPOOL_MIN, "Mempool Min Fee"},
|
|
||||||
{FeeReason::PAYTXFEE, "PayTxFee set"},
|
|
||||||
{FeeReason::FALLBACK, "Fallback fee"},
|
|
||||||
{FeeReason::REQUIRED, "Minimum Required Fee"},
|
|
||||||
{FeeReason::MAXTXFEE, "MaxTxFee limit"}
|
|
||||||
};
|
|
||||||
auto reason_string = fee_reason_strings.find(reason);
|
|
||||||
|
|
||||||
if (reason_string == fee_reason_strings.end()) return "Unknown";
|
|
||||||
|
|
||||||
return reason_string->second;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool FeeModeFromString(const std::string& mode_string, FeeEstimateMode& fee_estimate_mode) {
|
|
||||||
static const std::map<std::string, FeeEstimateMode> fee_modes = {
|
|
||||||
{"UNSET", FeeEstimateMode::UNSET},
|
|
||||||
{"ECONOMICAL", FeeEstimateMode::ECONOMICAL},
|
|
||||||
{"CONSERVATIVE", FeeEstimateMode::CONSERVATIVE},
|
|
||||||
};
|
|
||||||
auto mode = fee_modes.find(mode_string);
|
|
||||||
|
|
||||||
if (mode == fee_modes.end()) return false;
|
|
||||||
|
|
||||||
fee_estimate_mode = mode->second;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* We will instantiate an instance of this class to track transactions that were
|
* We will instantiate an instance of this class to track transactions that were
|
||||||
* included in a block. We will lump transactions into a bucket according to their
|
* included in a block. We will lump transactions into a bucket according to their
|
||||||
|
@ -46,8 +46,6 @@ enum class FeeReason {
|
|||||||
MAXTXFEE,
|
MAXTXFEE,
|
||||||
};
|
};
|
||||||
|
|
||||||
std::string StringForFeeReason(FeeReason reason);
|
|
||||||
|
|
||||||
/* Used to determine type of fee estimation requested */
|
/* Used to determine type of fee estimation requested */
|
||||||
enum class FeeEstimateMode {
|
enum class FeeEstimateMode {
|
||||||
UNSET, //!< Use default settings based on other criteria
|
UNSET, //!< Use default settings based on other criteria
|
||||||
@ -55,8 +53,6 @@ enum class FeeEstimateMode {
|
|||||||
CONSERVATIVE, //!< Force estimateSmartFee to use conservative estimates
|
CONSERVATIVE, //!< Force estimateSmartFee to use conservative estimates
|
||||||
};
|
};
|
||||||
|
|
||||||
bool FeeModeFromString(const std::string& mode_string, FeeEstimateMode& fee_estimate_mode);
|
|
||||||
|
|
||||||
/* Used to return detailed information about a feerate bucket */
|
/* Used to return detailed information about a feerate bucket */
|
||||||
struct EstimatorBucket
|
struct EstimatorBucket
|
||||||
{
|
{
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
|
|
||||||
#include <validation.h>
|
#include <validation.h>
|
||||||
#include <coins.h>
|
#include <coins.h>
|
||||||
|
#include <policy/settings.h>
|
||||||
#include <tinyformat.h>
|
#include <tinyformat.h>
|
||||||
#include <util/system.h>
|
#include <util/system.h>
|
||||||
#include <util/strencodings.h>
|
#include <util/strencodings.h>
|
||||||
@ -170,10 +171,6 @@ bool AreInputsStandard(const CTransaction& tx, const CCoinsViewCache& mapInputs)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int nBytesPerSigOp = DEFAULT_BYTES_PER_SIGOP;
|
|
||||||
CFeeRate incrementalRelayFee = CFeeRate(DEFAULT_INCREMENTAL_RELAY_FEE);
|
|
||||||
CFeeRate dustRelayFee = CFeeRate(DUST_RELAY_TX_FEE);
|
|
||||||
|
|
||||||
int64_t GetVirtualTransactionSize(int64_t nSize, int64_t nSigOp)
|
int64_t GetVirtualTransactionSize(int64_t nSize, int64_t nSigOp)
|
||||||
{
|
{
|
||||||
return std::max(nSize, nSigOp * nBytesPerSigOp);
|
return std::max(nSize, nSigOp * nBytesPerSigOp);
|
||||||
|
@ -34,6 +34,8 @@ static const unsigned int DEFAULT_MAX_MEMPOOL_SIZE = 300;
|
|||||||
static const unsigned int DEFAULT_INCREMENTAL_RELAY_FEE = 1000;
|
static const unsigned int DEFAULT_INCREMENTAL_RELAY_FEE = 1000;
|
||||||
/** Default for -bytespersigop */
|
/** Default for -bytespersigop */
|
||||||
static const unsigned int DEFAULT_BYTES_PER_SIGOP = 20;
|
static const unsigned int DEFAULT_BYTES_PER_SIGOP = 20;
|
||||||
|
/** Default for -permitbaremultisig */
|
||||||
|
static const bool DEFAULT_PERMIT_BAREMULTISIG = true;
|
||||||
/** Min feerate for defining dust. Historically this has been based on the
|
/** Min feerate for defining dust. Historically this has been based on the
|
||||||
* minRelayTxFee, however changing the dust limit changes which transactions are
|
* minRelayTxFee, however changing the dust limit changes which transactions are
|
||||||
* standard and should be done with care and ideally rarely. It makes sense to
|
* standard and should be done with care and ideally rarely. It makes sense to
|
||||||
@ -83,12 +85,8 @@ bool IsStandardTx(const CTransaction& tx, std::string& reason);
|
|||||||
*/
|
*/
|
||||||
bool AreInputsStandard(const CTransaction& tx, const CCoinsViewCache& mapInputs);
|
bool AreInputsStandard(const CTransaction& tx, const CCoinsViewCache& mapInputs);
|
||||||
|
|
||||||
extern unsigned int nBytesPerSigOp;
|
|
||||||
|
|
||||||
/** Compute the virtual transaction size (taking sigops into account). */
|
/** Compute the virtual transaction size (taking sigops into account). */
|
||||||
int64_t GetVirtualTransactionSize(int64_t nSize, int64_t nSigOp);
|
int64_t GetVirtualTransactionSize(int64_t nSize, int64_t nSigOp);
|
||||||
int64_t GetVirtualTransactionSize(const CTransaction& tx, int64_t nSigOp = 0);
|
int64_t GetVirtualTransactionSize(const CTransaction& tx, int64_t nSigOp = 0);
|
||||||
|
|
||||||
extern CFeeRate incrementalRelayFee;
|
|
||||||
extern CFeeRate dustRelayFee;
|
|
||||||
#endif // BITCOIN_POLICY_POLICY_H
|
#endif // BITCOIN_POLICY_POLICY_H
|
||||||
|
14
src/policy/settings.cpp
Normal file
14
src/policy/settings.cpp
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
// Copyright (c) 2009-2010 Satoshi Nakamoto
|
||||||
|
// Copyright (c) 2009-2018 The Bitcoin Core developers
|
||||||
|
// Distributed under the MIT software license, see the accompanying
|
||||||
|
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||||
|
|
||||||
|
#include <policy/settings.h>
|
||||||
|
|
||||||
|
#include <policy/feerate.h>
|
||||||
|
#include <policy/policy.h>
|
||||||
|
|
||||||
|
bool fIsBareMultisigStd = DEFAULT_PERMIT_BAREMULTISIG;
|
||||||
|
CFeeRate incrementalRelayFee = CFeeRate(DEFAULT_INCREMENTAL_RELAY_FEE);
|
||||||
|
CFeeRate dustRelayFee = CFeeRate(DUST_RELAY_TX_FEE);
|
||||||
|
unsigned int nBytesPerSigOp = DEFAULT_BYTES_PER_SIGOP;
|
17
src/policy/settings.h
Normal file
17
src/policy/settings.h
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
// Copyright (c) 2009-2010 Satoshi Nakamoto
|
||||||
|
// Copyright (c) 2009-2018 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_POLICY_SETTINGS_H
|
||||||
|
#define BITCOIN_POLICY_SETTINGS_H
|
||||||
|
|
||||||
|
class CFeeRate;
|
||||||
|
|
||||||
|
// Policy settings which are configurable at runtime.
|
||||||
|
extern CFeeRate incrementalRelayFee;
|
||||||
|
extern CFeeRate dustRelayFee;
|
||||||
|
extern unsigned int nBytesPerSigOp;
|
||||||
|
extern bool fIsBareMultisigStd;
|
||||||
|
|
||||||
|
#endif // BITCOIN_POLICY_SETTINGS_H
|
@ -14,6 +14,7 @@
|
|||||||
#include <net_permissions.h>
|
#include <net_permissions.h>
|
||||||
#include <netbase.h>
|
#include <netbase.h>
|
||||||
#include <policy/policy.h>
|
#include <policy/policy.h>
|
||||||
|
#include <policy/settings.h>
|
||||||
#include <rpc/protocol.h>
|
#include <rpc/protocol.h>
|
||||||
#include <rpc/util.h>
|
#include <rpc/util.h>
|
||||||
#include <sync.h>
|
#include <sync.h>
|
||||||
|
@ -21,7 +21,7 @@
|
|||||||
#include <policy/policy.h>
|
#include <policy/policy.h>
|
||||||
#include <primitives/transaction.h>
|
#include <primitives/transaction.h>
|
||||||
#include <psbt.h>
|
#include <psbt.h>
|
||||||
#include <rpc/rawtransaction.h>
|
#include <rpc/rawtransaction_util.h>
|
||||||
#include <rpc/server.h>
|
#include <rpc/server.h>
|
||||||
#include <rpc/util.h>
|
#include <rpc/util.h>
|
||||||
#include <script/script.h>
|
#include <script/script.h>
|
||||||
@ -397,96 +397,6 @@ static UniValue verifytxoutproof(const JSONRPCRequest& request)
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
CMutableTransaction ConstructTransaction(const UniValue& inputs_in, const UniValue& outputs_in, const UniValue& locktime)
|
|
||||||
{
|
|
||||||
if (inputs_in.isNull() || outputs_in.isNull())
|
|
||||||
throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, arguments 1 and 2 must be non-null");
|
|
||||||
|
|
||||||
UniValue inputs = inputs_in.get_array();
|
|
||||||
const bool outputs_is_obj = outputs_in.isObject();
|
|
||||||
UniValue outputs = outputs_is_obj ? outputs_in.get_obj() : outputs_in.get_array();
|
|
||||||
|
|
||||||
CMutableTransaction rawTx;
|
|
||||||
if (!locktime.isNull()) {
|
|
||||||
int64_t nLockTime = locktime.get_int64();
|
|
||||||
if (nLockTime < 0 || nLockTime > LOCKTIME_MAX)
|
|
||||||
throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, locktime out of range");
|
|
||||||
rawTx.nLockTime = nLockTime;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (unsigned int idx = 0; idx < inputs.size(); idx++) {
|
|
||||||
const UniValue& input = inputs[idx];
|
|
||||||
const UniValue& o = input.get_obj();
|
|
||||||
|
|
||||||
uint256 txid = ParseHashO(o, "txid");
|
|
||||||
|
|
||||||
const UniValue& vout_v = find_value(o, "vout");
|
|
||||||
if (!vout_v.isNum())
|
|
||||||
throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, missing vout key");
|
|
||||||
int nOutput = vout_v.get_int();
|
|
||||||
if (nOutput < 0)
|
|
||||||
throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, vout must be positive");
|
|
||||||
|
|
||||||
uint32_t nSequence = (rawTx.nLockTime ? CTxIn::SEQUENCE_FINAL - 1 : CTxIn::SEQUENCE_FINAL);
|
|
||||||
|
|
||||||
// set the sequence number if passed in the parameters object
|
|
||||||
const UniValue& sequenceObj = find_value(o, "sequence");
|
|
||||||
if (sequenceObj.isNum()) {
|
|
||||||
int64_t seqNr64 = sequenceObj.get_int64();
|
|
||||||
if (seqNr64 < 0 || seqNr64 > CTxIn::SEQUENCE_FINAL)
|
|
||||||
throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, sequence number is out of range");
|
|
||||||
else
|
|
||||||
nSequence = (uint32_t)seqNr64;
|
|
||||||
}
|
|
||||||
|
|
||||||
CTxIn in(COutPoint(txid, nOutput), CScript(), nSequence);
|
|
||||||
|
|
||||||
rawTx.vin.push_back(in);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::set<CTxDestination> destinations;
|
|
||||||
if (!outputs_is_obj) {
|
|
||||||
// Translate array of key-value pairs into dict
|
|
||||||
UniValue outputs_dict = UniValue(UniValue::VOBJ);
|
|
||||||
for (size_t i = 0; i < outputs.size(); ++i) {
|
|
||||||
const UniValue& output = outputs[i];
|
|
||||||
if (!output.isObject()) {
|
|
||||||
throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, key-value pair not an object as expected");
|
|
||||||
}
|
|
||||||
if (output.size() != 1) {
|
|
||||||
throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, key-value pair must contain exactly one key");
|
|
||||||
}
|
|
||||||
outputs_dict.pushKVs(output);
|
|
||||||
}
|
|
||||||
outputs = std::move(outputs_dict);
|
|
||||||
}
|
|
||||||
for (const std::string& name_ : outputs.getKeys()) {
|
|
||||||
if (name_ == "data") {
|
|
||||||
std::vector<unsigned char> data = ParseHexV(outputs[name_].getValStr(), "Data");
|
|
||||||
|
|
||||||
CTxOut out(0, CScript() << OP_RETURN << data);
|
|
||||||
rawTx.vout.push_back(out);
|
|
||||||
} else {
|
|
||||||
CTxDestination destination = DecodeDestination(name_);
|
|
||||||
if (!IsValidDestination(destination)) {
|
|
||||||
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, std::string("Invalid Dash address: ") + name_);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!destinations.insert(destination).second) {
|
|
||||||
throw JSONRPCError(RPC_INVALID_PARAMETER, std::string("Invalid parameter, duplicated address: ") + name_);
|
|
||||||
}
|
|
||||||
|
|
||||||
CScript scriptPubKey = GetScriptForDestination(destination);
|
|
||||||
CAmount nAmount = AmountFromValue(outputs[name_]);
|
|
||||||
|
|
||||||
CTxOut out(nAmount, scriptPubKey);
|
|
||||||
rawTx.vout.push_back(out);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return rawTx;
|
|
||||||
}
|
|
||||||
|
|
||||||
static UniValue createrawtransaction(const JSONRPCRequest& request)
|
static UniValue createrawtransaction(const JSONRPCRequest& request)
|
||||||
{
|
{
|
||||||
if (request.fHelp || request.params.size() < 2 || request.params.size() > 4) {
|
if (request.fHelp || request.params.size() < 2 || request.params.size() > 4) {
|
||||||
@ -673,18 +583,6 @@ static UniValue decodescript(const JSONRPCRequest& request)
|
|||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Pushes a JSON object for script verification or signing errors to vErrorsRet. */
|
|
||||||
static void TxInErrorToJSON(const CTxIn& txin, UniValue& vErrorsRet, const std::string& strMessage)
|
|
||||||
{
|
|
||||||
UniValue entry(UniValue::VOBJ);
|
|
||||||
entry.pushKV("txid", txin.prevout.hash.ToString());
|
|
||||||
entry.pushKV("vout", (uint64_t)txin.prevout.n);
|
|
||||||
entry.pushKV("scriptSig", HexStr(txin.scriptSig));
|
|
||||||
entry.pushKV("sequence", (uint64_t)txin.nSequence);
|
|
||||||
entry.pushKV("error", strMessage);
|
|
||||||
vErrorsRet.push_back(entry);
|
|
||||||
}
|
|
||||||
|
|
||||||
static UniValue combinerawtransaction(const JSONRPCRequest& request)
|
static UniValue combinerawtransaction(const JSONRPCRequest& request)
|
||||||
{
|
{
|
||||||
if (request.fHelp || request.params.size() != 1)
|
if (request.fHelp || request.params.size() != 1)
|
||||||
@ -769,135 +667,6 @@ static UniValue combinerawtransaction(const JSONRPCRequest& request)
|
|||||||
return EncodeHexTx(CTransaction(mergedTx));
|
return EncodeHexTx(CTransaction(mergedTx));
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(https://github.com/bitcoin/bitcoin/pull/10973#discussion_r267084237):
|
|
||||||
// This function is called from both wallet and node rpcs
|
|
||||||
// (signrawtransactionwithwallet and signrawtransactionwithkey). It should be
|
|
||||||
// moved to a util file so wallet code doesn't need to link against node code.
|
|
||||||
// Also the dependency on interfaces::Chain should be removed, so
|
|
||||||
// signrawtransactionwithkey doesn't need access to a Chain instance.
|
|
||||||
UniValue SignTransaction(interfaces::Chain& chain, CMutableTransaction& mtx, const UniValue& prevTxsUnival, CBasicKeyStore *keystore, bool is_temp_keystore, const UniValue& hashType)
|
|
||||||
{
|
|
||||||
// Fetch previous transactions (inputs):
|
|
||||||
std::map<COutPoint, Coin> coins;
|
|
||||||
for (const CTxIn& txin : mtx.vin) {
|
|
||||||
coins[txin.prevout]; // Create empty map entry keyed by prevout.
|
|
||||||
}
|
|
||||||
chain.findCoins(coins);
|
|
||||||
|
|
||||||
// Add previous txouts given in the RPC call:
|
|
||||||
if (!prevTxsUnival.isNull()) {
|
|
||||||
UniValue prevTxs = prevTxsUnival.get_array();
|
|
||||||
for (unsigned int idx = 0; idx < prevTxs.size(); ++idx) {
|
|
||||||
const UniValue& p = prevTxs[idx];
|
|
||||||
if (!p.isObject()) {
|
|
||||||
throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "expected object with {\"txid'\",\"vout\",\"scriptPubKey\"}");
|
|
||||||
}
|
|
||||||
|
|
||||||
UniValue prevOut = p.get_obj();
|
|
||||||
|
|
||||||
RPCTypeCheckObj(prevOut,
|
|
||||||
{
|
|
||||||
{"txid", UniValueType(UniValue::VSTR)},
|
|
||||||
{"vout", UniValueType(UniValue::VNUM)},
|
|
||||||
{"scriptPubKey", UniValueType(UniValue::VSTR)},
|
|
||||||
});
|
|
||||||
|
|
||||||
uint256 txid = ParseHashO(prevOut, "txid");
|
|
||||||
|
|
||||||
int nOut = find_value(prevOut, "vout").get_int();
|
|
||||||
if (nOut < 0) {
|
|
||||||
throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "vout must be positive");
|
|
||||||
}
|
|
||||||
|
|
||||||
COutPoint out(txid, nOut);
|
|
||||||
std::vector<unsigned char> pkData(ParseHexO(prevOut, "scriptPubKey"));
|
|
||||||
CScript scriptPubKey(pkData.begin(), pkData.end());
|
|
||||||
|
|
||||||
{
|
|
||||||
auto coin = coins.find(out);
|
|
||||||
if (coin != coins.end() && !coin->second.IsSpent() && coin->second.out.scriptPubKey != scriptPubKey) {
|
|
||||||
std::string err("Previous output scriptPubKey mismatch:\n");
|
|
||||||
err = err + ScriptToAsmStr(coin->second.out.scriptPubKey) + "\nvs:\n"+
|
|
||||||
ScriptToAsmStr(scriptPubKey);
|
|
||||||
throw JSONRPCError(RPC_DESERIALIZATION_ERROR, err);
|
|
||||||
}
|
|
||||||
Coin newcoin;
|
|
||||||
newcoin.out.scriptPubKey = scriptPubKey;
|
|
||||||
newcoin.out.nValue = 0;
|
|
||||||
if (prevOut.exists("amount")) {
|
|
||||||
newcoin.out.nValue = AmountFromValue(find_value(prevOut, "amount"));
|
|
||||||
}
|
|
||||||
newcoin.nHeight = 1;
|
|
||||||
coins[out] = std::move(newcoin);
|
|
||||||
}
|
|
||||||
|
|
||||||
// if redeemScript and private keys were given, add redeemScript to the keystore so it can be signed
|
|
||||||
if (is_temp_keystore && scriptPubKey.IsPayToScriptHash()) {
|
|
||||||
RPCTypeCheckObj(prevOut,
|
|
||||||
{
|
|
||||||
{"redeemScript", UniValueType(UniValue::VSTR)},
|
|
||||||
});
|
|
||||||
UniValue v = find_value(prevOut, "redeemScript");
|
|
||||||
if (!v.isNull()) {
|
|
||||||
std::vector<unsigned char> rsData(ParseHexV(v, "redeemScript"));
|
|
||||||
CScript redeemScript(rsData.begin(), rsData.end());
|
|
||||||
keystore->AddCScript(redeemScript);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int nHashType = ParseSighashString(hashType);
|
|
||||||
|
|
||||||
bool fHashSingle = ((nHashType & ~SIGHASH_ANYONECANPAY) == SIGHASH_SINGLE);
|
|
||||||
|
|
||||||
// Script verification errors
|
|
||||||
UniValue vErrors(UniValue::VARR);
|
|
||||||
|
|
||||||
// Use CTransaction for the constant parts of the
|
|
||||||
// transaction to avoid rehashing.
|
|
||||||
const CTransaction txConst(mtx);
|
|
||||||
// Sign what we can:
|
|
||||||
for (unsigned int i = 0; i < mtx.vin.size(); i++) {
|
|
||||||
CTxIn& txin = mtx.vin[i];
|
|
||||||
auto coin = coins.find(txin.prevout);
|
|
||||||
if (coin == coins.end() || coin->second.IsSpent()) {
|
|
||||||
TxInErrorToJSON(txin, vErrors, "Input not found or already spent");
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
const CScript& prevPubKey = coin->second.out.scriptPubKey;
|
|
||||||
const CAmount& amount = coin->second.out.nValue;
|
|
||||||
|
|
||||||
SignatureData sigdata = DataFromTransaction(mtx, i, coin->second.out);
|
|
||||||
// Only sign SIGHASH_SINGLE if there's a corresponding output:
|
|
||||||
if (!fHashSingle || (i < mtx.vout.size())) {
|
|
||||||
ProduceSignature(*keystore, MutableTransactionSignatureCreator(&mtx, i, amount, nHashType), prevPubKey, sigdata);
|
|
||||||
}
|
|
||||||
|
|
||||||
UpdateInput(txin, sigdata);
|
|
||||||
|
|
||||||
ScriptError serror = SCRIPT_ERR_OK;
|
|
||||||
if (!VerifyScript(txin.scriptSig, prevPubKey, STANDARD_SCRIPT_VERIFY_FLAGS, TransactionSignatureChecker(&txConst, i, amount), &serror)) {
|
|
||||||
if (serror == SCRIPT_ERR_INVALID_STACK_OPERATION) {
|
|
||||||
// Unable to sign input and verification failed (possible attempt to partially sign).
|
|
||||||
TxInErrorToJSON(txin, vErrors, "Unable to sign input, invalid stack size (possibly missing key)");
|
|
||||||
} else {
|
|
||||||
TxInErrorToJSON(txin, vErrors, ScriptErrorString(serror));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
bool fComplete = vErrors.empty();
|
|
||||||
|
|
||||||
UniValue result(UniValue::VOBJ);
|
|
||||||
result.pushKV("hex", EncodeHexTx(CTransaction(mtx)));
|
|
||||||
result.pushKV("complete", fComplete);
|
|
||||||
if (!vErrors.empty()) {
|
|
||||||
result.pushKV("errors", vErrors);
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
static UniValue signrawtransactionwithkey(const JSONRPCRequest& request)
|
static UniValue signrawtransactionwithkey(const JSONRPCRequest& request)
|
||||||
{
|
{
|
||||||
if (request.fHelp || request.params.size() < 2 || request.params.size() > 4)
|
if (request.fHelp || request.params.size() < 2 || request.params.size() > 4)
|
||||||
|
250
src/rpc/rawtransaction_util.cpp
Normal file
250
src/rpc/rawtransaction_util.cpp
Normal file
@ -0,0 +1,250 @@
|
|||||||
|
// Copyright (c) 2010 Satoshi Nakamoto
|
||||||
|
// Copyright (c) 2009-2019 The Bitcoin Core developers
|
||||||
|
// Distributed under the MIT software license, see the accompanying
|
||||||
|
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||||
|
|
||||||
|
#include <rpc/rawtransaction_util.h>
|
||||||
|
|
||||||
|
#include <coins.h>
|
||||||
|
#include <core_io.h>
|
||||||
|
#include <interfaces/chain.h>
|
||||||
|
#include <key_io.h>
|
||||||
|
#include <keystore.h>
|
||||||
|
#include <policy/policy.h>
|
||||||
|
#include <policy/settings.h>
|
||||||
|
#include <primitives/transaction.h>
|
||||||
|
#include <rpc/protocol.h>
|
||||||
|
#include <rpc/util.h>
|
||||||
|
#include <tinyformat.h>
|
||||||
|
#include <univalue.h>
|
||||||
|
#include <util/strencodings.h>
|
||||||
|
#include <validation.h>
|
||||||
|
#include <txmempool.h>
|
||||||
|
|
||||||
|
CMutableTransaction ConstructTransaction(const UniValue& inputs_in, const UniValue& outputs_in, const UniValue& locktime)
|
||||||
|
{
|
||||||
|
if (inputs_in.isNull() || outputs_in.isNull())
|
||||||
|
throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, arguments 1 and 2 must be non-null");
|
||||||
|
|
||||||
|
UniValue inputs = inputs_in.get_array();
|
||||||
|
const bool outputs_is_obj = outputs_in.isObject();
|
||||||
|
UniValue outputs = outputs_is_obj ? outputs_in.get_obj() : outputs_in.get_array();
|
||||||
|
|
||||||
|
CMutableTransaction rawTx;
|
||||||
|
if (!locktime.isNull()) {
|
||||||
|
int64_t nLockTime = locktime.get_int64();
|
||||||
|
if (nLockTime < 0 || nLockTime > LOCKTIME_MAX)
|
||||||
|
throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, locktime out of range");
|
||||||
|
rawTx.nLockTime = nLockTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (unsigned int idx = 0; idx < inputs.size(); idx++) {
|
||||||
|
const UniValue& input = inputs[idx];
|
||||||
|
const UniValue& o = input.get_obj();
|
||||||
|
|
||||||
|
uint256 txid = ParseHashO(o, "txid");
|
||||||
|
|
||||||
|
const UniValue& vout_v = find_value(o, "vout");
|
||||||
|
if (!vout_v.isNum())
|
||||||
|
throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, missing vout key");
|
||||||
|
int nOutput = vout_v.get_int();
|
||||||
|
if (nOutput < 0)
|
||||||
|
throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, vout must be positive");
|
||||||
|
|
||||||
|
uint32_t nSequence = (rawTx.nLockTime ? CTxIn::SEQUENCE_FINAL - 1 : CTxIn::SEQUENCE_FINAL);
|
||||||
|
|
||||||
|
// set the sequence number if passed in the parameters object
|
||||||
|
const UniValue& sequenceObj = find_value(o, "sequence");
|
||||||
|
if (sequenceObj.isNum()) {
|
||||||
|
int64_t seqNr64 = sequenceObj.get_int64();
|
||||||
|
if (seqNr64 < 0 || seqNr64 > CTxIn::SEQUENCE_FINAL)
|
||||||
|
throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, sequence number is out of range");
|
||||||
|
else
|
||||||
|
nSequence = (uint32_t)seqNr64;
|
||||||
|
}
|
||||||
|
|
||||||
|
CTxIn in(COutPoint(txid, nOutput), CScript(), nSequence);
|
||||||
|
|
||||||
|
rawTx.vin.push_back(in);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::set<CTxDestination> destinations;
|
||||||
|
if (!outputs_is_obj) {
|
||||||
|
// Translate array of key-value pairs into dict
|
||||||
|
UniValue outputs_dict = UniValue(UniValue::VOBJ);
|
||||||
|
for (size_t i = 0; i < outputs.size(); ++i) {
|
||||||
|
const UniValue& output = outputs[i];
|
||||||
|
if (!output.isObject()) {
|
||||||
|
throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, key-value pair not an object as expected");
|
||||||
|
}
|
||||||
|
if (output.size() != 1) {
|
||||||
|
throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, key-value pair must contain exactly one key");
|
||||||
|
}
|
||||||
|
outputs_dict.pushKVs(output);
|
||||||
|
}
|
||||||
|
outputs = std::move(outputs_dict);
|
||||||
|
}
|
||||||
|
for (const std::string& name_ : outputs.getKeys()) {
|
||||||
|
if (name_ == "data") {
|
||||||
|
std::vector<unsigned char> data = ParseHexV(outputs[name_].getValStr(), "Data");
|
||||||
|
|
||||||
|
CTxOut out(0, CScript() << OP_RETURN << data);
|
||||||
|
rawTx.vout.push_back(out);
|
||||||
|
} else {
|
||||||
|
CTxDestination destination = DecodeDestination(name_);
|
||||||
|
if (!IsValidDestination(destination)) {
|
||||||
|
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, std::string("Invalid Dash address: ") + name_);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!destinations.insert(destination).second) {
|
||||||
|
throw JSONRPCError(RPC_INVALID_PARAMETER, std::string("Invalid parameter, duplicated address: ") + name_);
|
||||||
|
}
|
||||||
|
|
||||||
|
CScript scriptPubKey = GetScriptForDestination(destination);
|
||||||
|
CAmount nAmount = AmountFromValue(outputs[name_]);
|
||||||
|
|
||||||
|
CTxOut out(nAmount, scriptPubKey);
|
||||||
|
rawTx.vout.push_back(out);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return rawTx;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Pushes a JSON object for script verification or signing errors to vErrorsRet. */
|
||||||
|
static void TxInErrorToJSON(const CTxIn& txin, UniValue& vErrorsRet, const std::string& strMessage)
|
||||||
|
{
|
||||||
|
UniValue entry(UniValue::VOBJ);
|
||||||
|
entry.pushKV("txid", txin.prevout.hash.ToString());
|
||||||
|
entry.pushKV("vout", (uint64_t)txin.prevout.n);
|
||||||
|
entry.pushKV("scriptSig", HexStr(txin.scriptSig));
|
||||||
|
entry.pushKV("sequence", (uint64_t)txin.nSequence);
|
||||||
|
entry.pushKV("error", strMessage);
|
||||||
|
vErrorsRet.push_back(entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO(https://github.com/bitcoin/bitcoin/pull/10973#discussion_r267084237):
|
||||||
|
// The dependency on interfaces::Chain should be removed, so
|
||||||
|
// signrawtransactionwithkey doesn't need access to a Chain instance.
|
||||||
|
UniValue SignTransaction(interfaces::Chain& chain, CMutableTransaction& mtx, const UniValue& prevTxsUnival, CBasicKeyStore *keystore, bool is_temp_keystore, const UniValue& hashType)
|
||||||
|
{
|
||||||
|
// Fetch previous transactions (inputs):
|
||||||
|
std::map<COutPoint, Coin> coins;
|
||||||
|
for (const CTxIn& txin : mtx.vin) {
|
||||||
|
coins[txin.prevout]; // Create empty map entry keyed by prevout.
|
||||||
|
}
|
||||||
|
chain.findCoins(coins);
|
||||||
|
|
||||||
|
// Add previous txouts given in the RPC call:
|
||||||
|
if (!prevTxsUnival.isNull()) {
|
||||||
|
UniValue prevTxs = prevTxsUnival.get_array();
|
||||||
|
for (unsigned int idx = 0; idx < prevTxs.size(); ++idx) {
|
||||||
|
const UniValue& p = prevTxs[idx];
|
||||||
|
if (!p.isObject()) {
|
||||||
|
throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "expected object with {\"txid'\",\"vout\",\"scriptPubKey\"}");
|
||||||
|
}
|
||||||
|
|
||||||
|
UniValue prevOut = p.get_obj();
|
||||||
|
|
||||||
|
RPCTypeCheckObj(prevOut,
|
||||||
|
{
|
||||||
|
{"txid", UniValueType(UniValue::VSTR)},
|
||||||
|
{"vout", UniValueType(UniValue::VNUM)},
|
||||||
|
{"scriptPubKey", UniValueType(UniValue::VSTR)},
|
||||||
|
});
|
||||||
|
|
||||||
|
uint256 txid = ParseHashO(prevOut, "txid");
|
||||||
|
|
||||||
|
int nOut = find_value(prevOut, "vout").get_int();
|
||||||
|
if (nOut < 0) {
|
||||||
|
throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "vout must be positive");
|
||||||
|
}
|
||||||
|
|
||||||
|
COutPoint out(txid, nOut);
|
||||||
|
std::vector<unsigned char> pkData(ParseHexO(prevOut, "scriptPubKey"));
|
||||||
|
CScript scriptPubKey(pkData.begin(), pkData.end());
|
||||||
|
|
||||||
|
{
|
||||||
|
auto coin = coins.find(out);
|
||||||
|
if (coin != coins.end() && !coin->second.IsSpent() && coin->second.out.scriptPubKey != scriptPubKey) {
|
||||||
|
std::string err("Previous output scriptPubKey mismatch:\n");
|
||||||
|
err = err + ScriptToAsmStr(coin->second.out.scriptPubKey) + "\nvs:\n"+
|
||||||
|
ScriptToAsmStr(scriptPubKey);
|
||||||
|
throw JSONRPCError(RPC_DESERIALIZATION_ERROR, err);
|
||||||
|
}
|
||||||
|
Coin newcoin;
|
||||||
|
newcoin.out.scriptPubKey = scriptPubKey;
|
||||||
|
newcoin.out.nValue = 0;
|
||||||
|
if (prevOut.exists("amount")) {
|
||||||
|
newcoin.out.nValue = AmountFromValue(find_value(prevOut, "amount"));
|
||||||
|
}
|
||||||
|
newcoin.nHeight = 1;
|
||||||
|
coins[out] = std::move(newcoin);
|
||||||
|
}
|
||||||
|
|
||||||
|
// if redeemScript and private keys were given, add redeemScript to the keystore so it can be signed
|
||||||
|
if (is_temp_keystore && scriptPubKey.IsPayToScriptHash()) {
|
||||||
|
RPCTypeCheckObj(prevOut,
|
||||||
|
{
|
||||||
|
{"redeemScript", UniValueType(UniValue::VSTR)},
|
||||||
|
});
|
||||||
|
UniValue v = find_value(prevOut, "redeemScript");
|
||||||
|
if (!v.isNull()) {
|
||||||
|
std::vector<unsigned char> rsData(ParseHexV(v, "redeemScript"));
|
||||||
|
CScript redeemScript(rsData.begin(), rsData.end());
|
||||||
|
keystore->AddCScript(redeemScript);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int nHashType = ParseSighashString(hashType);
|
||||||
|
|
||||||
|
bool fHashSingle = ((nHashType & ~SIGHASH_ANYONECANPAY) == SIGHASH_SINGLE);
|
||||||
|
|
||||||
|
// Script verification errors
|
||||||
|
UniValue vErrors(UniValue::VARR);
|
||||||
|
|
||||||
|
// Use CTransaction for the constant parts of the
|
||||||
|
// transaction to avoid rehashing.
|
||||||
|
const CTransaction txConst(mtx);
|
||||||
|
// Sign what we can:
|
||||||
|
for (unsigned int i = 0; i < mtx.vin.size(); i++) {
|
||||||
|
CTxIn& txin = mtx.vin[i];
|
||||||
|
auto coin = coins.find(txin.prevout);
|
||||||
|
if (coin == coins.end() || coin->second.IsSpent()) {
|
||||||
|
TxInErrorToJSON(txin, vErrors, "Input not found or already spent");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
const CScript& prevPubKey = coin->second.out.scriptPubKey;
|
||||||
|
const CAmount& amount = coin->second.out.nValue;
|
||||||
|
|
||||||
|
SignatureData sigdata = DataFromTransaction(mtx, i, coin->second.out);
|
||||||
|
// Only sign SIGHASH_SINGLE if there's a corresponding output:
|
||||||
|
if (!fHashSingle || (i < mtx.vout.size())) {
|
||||||
|
ProduceSignature(*keystore, MutableTransactionSignatureCreator(&mtx, i, amount, nHashType), prevPubKey, sigdata);
|
||||||
|
}
|
||||||
|
|
||||||
|
UpdateInput(txin, sigdata);
|
||||||
|
|
||||||
|
ScriptError serror = SCRIPT_ERR_OK;
|
||||||
|
if (!VerifyScript(txin.scriptSig, prevPubKey, STANDARD_SCRIPT_VERIFY_FLAGS, TransactionSignatureChecker(&txConst, i, amount), &serror)) {
|
||||||
|
if (serror == SCRIPT_ERR_INVALID_STACK_OPERATION) {
|
||||||
|
// Unable to sign input and verification failed (possible attempt to partially sign).
|
||||||
|
TxInErrorToJSON(txin, vErrors, "Unable to sign input, invalid stack size (possibly missing key)");
|
||||||
|
} else {
|
||||||
|
TxInErrorToJSON(txin, vErrors, ScriptErrorString(serror));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
bool fComplete = vErrors.empty();
|
||||||
|
|
||||||
|
UniValue result(UniValue::VOBJ);
|
||||||
|
result.pushKV("hex", EncodeHexTx(CTransaction(mtx)));
|
||||||
|
result.pushKV("complete", fComplete);
|
||||||
|
if (!vErrors.empty()) {
|
||||||
|
result.pushKV("errors", vErrors);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
@ -2,12 +2,12 @@
|
|||||||
// Distributed under the MIT software license, see the accompanying
|
// Distributed under the MIT software license, see the accompanying
|
||||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||||
|
|
||||||
#ifndef BITCOIN_RPC_RAWTRANSACTION_H
|
#ifndef BITCOIN_RPC_RAWTRANSACTION_UTIL_H
|
||||||
#define BITCOIN_RPC_RAWTRANSACTION_H
|
#define BITCOIN_RPC_RAWTRANSACTION_UTIL_H
|
||||||
|
|
||||||
class CBasicKeyStore;
|
class CBasicKeyStore;
|
||||||
struct CMutableTransaction;
|
|
||||||
class UniValue;
|
class UniValue;
|
||||||
|
struct CMutableTransaction;
|
||||||
|
|
||||||
namespace interfaces {
|
namespace interfaces {
|
||||||
class Chain;
|
class Chain;
|
||||||
@ -19,4 +19,4 @@ UniValue SignTransaction(interfaces::Chain& chain, CMutableTransaction& mtx, con
|
|||||||
/** Create a transaction from univalue parameters */
|
/** Create a transaction from univalue parameters */
|
||||||
CMutableTransaction ConstructTransaction(const UniValue& inputs_in, const UniValue& outputs_in, const UniValue& locktime);
|
CMutableTransaction ConstructTransaction(const UniValue& inputs_in, const UniValue& outputs_in, const UniValue& locktime);
|
||||||
|
|
||||||
#endif // BITCOIN_RPC_RAWTRANSACTION_H
|
#endif // BITCOIN_RPC_RAWTRANSACTION_UTIL_H
|
@ -54,150 +54,6 @@ void RPCServer::OnStopped(std::function<void ()> slot)
|
|||||||
g_rpcSignals.Stopped.connect(slot);
|
g_rpcSignals.Stopped.connect(slot);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RPCTypeCheck(const UniValue& params,
|
|
||||||
const std::list<UniValueType>& typesExpected,
|
|
||||||
bool fAllowNull)
|
|
||||||
{
|
|
||||||
unsigned int i = 0;
|
|
||||||
for (const UniValueType& t : typesExpected) {
|
|
||||||
if (params.size() <= i)
|
|
||||||
break;
|
|
||||||
|
|
||||||
const UniValue& v = params[i];
|
|
||||||
if (!(fAllowNull && v.isNull())) {
|
|
||||||
RPCTypeCheckArgument(v, t);
|
|
||||||
}
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void RPCTypeCheckArgument(const UniValue& value, const UniValueType& typeExpected)
|
|
||||||
{
|
|
||||||
if (!typeExpected.typeAny && value.type() != typeExpected.type) {
|
|
||||||
throw JSONRPCError(RPC_TYPE_ERROR, strprintf("Expected type %s, got %s", uvTypeName(typeExpected.type), uvTypeName(value.type())));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void RPCTypeCheckObj(const UniValue& o,
|
|
||||||
const std::map<std::string, UniValueType>& typesExpected,
|
|
||||||
bool fAllowNull,
|
|
||||||
bool fStrict)
|
|
||||||
{
|
|
||||||
for (const auto& t : typesExpected) {
|
|
||||||
const UniValue& v = find_value(o, t.first);
|
|
||||||
if (!fAllowNull && v.isNull())
|
|
||||||
throw JSONRPCError(RPC_TYPE_ERROR, strprintf("Missing %s", t.first));
|
|
||||||
|
|
||||||
if (!(t.second.typeAny || v.type() == t.second.type || (fAllowNull && v.isNull()))) {
|
|
||||||
std::string err = strprintf("Expected type %s for %s, got %s",
|
|
||||||
uvTypeName(t.second.type), t.first, uvTypeName(v.type()));
|
|
||||||
throw JSONRPCError(RPC_TYPE_ERROR, err);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fStrict)
|
|
||||||
{
|
|
||||||
for (const std::string& k : o.getKeys())
|
|
||||||
{
|
|
||||||
if (typesExpected.count(k) == 0)
|
|
||||||
{
|
|
||||||
std::string err = strprintf("Unexpected key %s", k);
|
|
||||||
throw JSONRPCError(RPC_TYPE_ERROR, err);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
CAmount AmountFromValue(const UniValue& value)
|
|
||||||
{
|
|
||||||
if (!value.isNum() && !value.isStr())
|
|
||||||
throw JSONRPCError(RPC_TYPE_ERROR, "Amount is not a number or string");
|
|
||||||
CAmount amount;
|
|
||||||
if (!ParseFixedPoint(value.getValStr(), 8, &amount))
|
|
||||||
throw JSONRPCError(RPC_TYPE_ERROR, "Invalid amount");
|
|
||||||
if (!MoneyRange(amount))
|
|
||||||
throw JSONRPCError(RPC_TYPE_ERROR, "Amount out of range");
|
|
||||||
return amount;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint256 ParseHashV(const UniValue& v, std::string strName)
|
|
||||||
{
|
|
||||||
std::string strHex;
|
|
||||||
if (v.isStr())
|
|
||||||
strHex = v.get_str();
|
|
||||||
if (!IsHex(strHex)) // Note: IsHex("") is false
|
|
||||||
throw JSONRPCError(RPC_INVALID_PARAMETER, strName+" must be hexadecimal string (not '"+strHex+"')");
|
|
||||||
if (64 != strHex.length())
|
|
||||||
throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("%s must be of length %d (not %d)", strName, 64, strHex.length()));
|
|
||||||
uint256 result;
|
|
||||||
result.SetHex(strHex);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
uint256 ParseHashO(const UniValue& o, std::string strKey)
|
|
||||||
{
|
|
||||||
return ParseHashV(find_value(o, strKey), strKey);
|
|
||||||
}
|
|
||||||
std::vector<unsigned char> ParseHexV(const UniValue& v, std::string strName)
|
|
||||||
{
|
|
||||||
std::string strHex;
|
|
||||||
if (v.isStr())
|
|
||||||
strHex = v.get_str();
|
|
||||||
if (!IsHex(strHex))
|
|
||||||
throw JSONRPCError(RPC_INVALID_PARAMETER, strName+" must be hexadecimal string (not '"+strHex+"')");
|
|
||||||
return ParseHex(strHex);
|
|
||||||
}
|
|
||||||
std::vector<unsigned char> ParseHexO(const UniValue& o, std::string strKey)
|
|
||||||
{
|
|
||||||
return ParseHexV(find_value(o, strKey), strKey);
|
|
||||||
}
|
|
||||||
|
|
||||||
int32_t ParseInt32V(const UniValue& v, const std::string &strName)
|
|
||||||
{
|
|
||||||
std::string strNum = v.getValStr();
|
|
||||||
int32_t num;
|
|
||||||
if (!ParseInt32(strNum, &num))
|
|
||||||
throw JSONRPCError(RPC_INVALID_PARAMETER, strName+" must be a 32bit integer (not '"+strNum+"')");
|
|
||||||
return num;
|
|
||||||
}
|
|
||||||
|
|
||||||
int64_t ParseInt64V(const UniValue& v, const std::string &strName)
|
|
||||||
{
|
|
||||||
std::string strNum = v.getValStr();
|
|
||||||
int64_t num;
|
|
||||||
if (!ParseInt64(strNum, &num))
|
|
||||||
throw JSONRPCError(RPC_INVALID_PARAMETER, strName+" must be a 64bit integer (not '"+strNum+"')");
|
|
||||||
return num;
|
|
||||||
}
|
|
||||||
|
|
||||||
double ParseDoubleV(const UniValue& v, const std::string &strName)
|
|
||||||
{
|
|
||||||
std::string strNum = v.getValStr();
|
|
||||||
double num;
|
|
||||||
if (!ParseDouble(strNum, &num))
|
|
||||||
throw JSONRPCError(RPC_INVALID_PARAMETER, strName+" must be a be number (not '"+strNum+"')");
|
|
||||||
return num;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ParseBoolV(const UniValue& v, const std::string &strName)
|
|
||||||
{
|
|
||||||
std::string strBool;
|
|
||||||
if (v.isBool())
|
|
||||||
return v.get_bool();
|
|
||||||
else if (v.isNum())
|
|
||||||
strBool = itostr(v.get_int());
|
|
||||||
else if (v.isStr())
|
|
||||||
strBool = v.get_str();
|
|
||||||
|
|
||||||
strBool = ToLower(strBool);
|
|
||||||
|
|
||||||
if (strBool == "true" || strBool == "yes" || strBool == "1") {
|
|
||||||
return true;
|
|
||||||
} else if (strBool == "false" || strBool == "no" || strBool == "0") {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
throw JSONRPCError(RPC_INVALID_PARAMETER, strName+" must be true, false, yes, no, 1 or 0 (not '"+strBool+"')");
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string CRPCTable::help(const std::string& strCommand, const std::string& strSubCommand, const JSONRPCRequest& helpreq) const
|
std::string CRPCTable::help(const std::string& strCommand, const std::string& strSubCommand, const JSONRPCRequest& helpreq) const
|
||||||
{
|
{
|
||||||
std::string strRet;
|
std::string strRet;
|
||||||
@ -662,18 +518,6 @@ std::vector<std::string> CRPCTable::listCommands() const
|
|||||||
return commandList;
|
return commandList;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string HelpExampleCli(const std::string& methodname, const std::string& args)
|
|
||||||
{
|
|
||||||
return "> dash-cli " + methodname + " " + args + "\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string HelpExampleRpc(const std::string& methodname, const std::string& args)
|
|
||||||
{
|
|
||||||
return "> curl --user myusername --data-binary '{\"jsonrpc\": \"1.0\", \"id\":\"curltest\", "
|
|
||||||
"\"method\": \"" + methodname + "\", \"params\": [" + args + "] }' -H 'content-type: text/plain;'"
|
|
||||||
" http://127.0.0.1:" + strprintf("%d", gArgs.GetArg("-rpcport", BaseParams().RPCPort())) + "/\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
void RPCSetTimerInterfaceIfUnset(RPCTimerInterface *iface)
|
void RPCSetTimerInterfaceIfUnset(RPCTimerInterface *iface)
|
||||||
{
|
{
|
||||||
if (!timerInterface)
|
if (!timerInterface)
|
||||||
|
@ -25,15 +25,6 @@ namespace RPCServer
|
|||||||
void OnStopped(std::function<void ()> slot);
|
void OnStopped(std::function<void ()> slot);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Wrapper for UniValue::VType, which includes typeAny:
|
|
||||||
* Used to denote don't care type. */
|
|
||||||
struct UniValueType {
|
|
||||||
UniValueType(UniValue::VType _type) : typeAny(false), type(_type) {}
|
|
||||||
UniValueType() : typeAny(true) {}
|
|
||||||
bool typeAny;
|
|
||||||
UniValue::VType type;
|
|
||||||
};
|
|
||||||
|
|
||||||
class JSONRPCRequest
|
class JSONRPCRequest
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -63,26 +54,6 @@ void SetRPCWarmupFinished();
|
|||||||
/* returns the current warmup state. */
|
/* returns the current warmup state. */
|
||||||
bool RPCIsInWarmup(std::string *outStatus);
|
bool RPCIsInWarmup(std::string *outStatus);
|
||||||
|
|
||||||
/**
|
|
||||||
* Type-check arguments; throws JSONRPCError if wrong type given. Does not check that
|
|
||||||
* the right number of arguments are passed, just that any passed are the correct type.
|
|
||||||
*/
|
|
||||||
void RPCTypeCheck(const UniValue& params,
|
|
||||||
const std::list<UniValueType>& typesExpected, bool fAllowNull=false);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Type-check one argument; throws JSONRPCError if wrong type given.
|
|
||||||
*/
|
|
||||||
void RPCTypeCheckArgument(const UniValue& value, const UniValueType& typeExpected);
|
|
||||||
|
|
||||||
/*
|
|
||||||
Check for expected keys/value types in an Object.
|
|
||||||
*/
|
|
||||||
void RPCTypeCheckObj(const UniValue& o,
|
|
||||||
const std::map<std::string, UniValueType>& typesExpected,
|
|
||||||
bool fAllowNull = false,
|
|
||||||
bool fStrict = false);
|
|
||||||
|
|
||||||
/** Opaque base class for timers returned by NewTimerFunc.
|
/** Opaque base class for timers returned by NewTimerFunc.
|
||||||
* This provides no methods at the moment, but makes sure that delete
|
* This provides no methods at the moment, but makes sure that delete
|
||||||
* cleans up the whole state.
|
* cleans up the whole state.
|
||||||
@ -204,24 +175,6 @@ bool IsDeprecatedRPCEnabled(const std::string& method);
|
|||||||
|
|
||||||
extern CRPCTable tableRPC;
|
extern CRPCTable tableRPC;
|
||||||
|
|
||||||
/**
|
|
||||||
* Utilities: convert hex-encoded Values
|
|
||||||
* (throws error if not hex).
|
|
||||||
*/
|
|
||||||
extern uint256 ParseHashV(const UniValue& v, std::string strName);
|
|
||||||
extern uint256 ParseHashO(const UniValue& o, std::string strKey);
|
|
||||||
extern std::vector<unsigned char> ParseHexV(const UniValue& v, std::string strName);
|
|
||||||
extern std::vector<unsigned char> ParseHexO(const UniValue& o, std::string strKey);
|
|
||||||
|
|
||||||
extern int32_t ParseInt32V(const UniValue& v, const std::string &strName);
|
|
||||||
extern int64_t ParseInt64V(const UniValue& v, const std::string &strName);
|
|
||||||
extern double ParseDoubleV(const UniValue& v, const std::string &strName);
|
|
||||||
extern bool ParseBoolV(const UniValue& v, const std::string &strName);
|
|
||||||
|
|
||||||
extern CAmount AmountFromValue(const UniValue& value);
|
|
||||||
extern std::string HelpExampleCli(const std::string& methodname, const std::string& args);
|
|
||||||
extern std::string HelpExampleRpc(const std::string& methodname, const std::string& args);
|
|
||||||
|
|
||||||
void StartRPC();
|
void StartRPC();
|
||||||
void InterruptRPC();
|
void InterruptRPC();
|
||||||
void StopRPC();
|
void StopRPC();
|
||||||
|
158
src/rpc/util.cpp
158
src/rpc/util.cpp
@ -2,15 +2,173 @@
|
|||||||
// Distributed under the MIT software license, see the accompanying
|
// Distributed under the MIT software license, see the accompanying
|
||||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||||
|
|
||||||
|
#include <chainparamsbase.h>
|
||||||
#include <key_io.h>
|
#include <key_io.h>
|
||||||
#include <keystore.h>
|
#include <keystore.h>
|
||||||
#include <pubkey.h>
|
#include <pubkey.h>
|
||||||
#include <rpc/util.h>
|
#include <rpc/util.h>
|
||||||
#include <tinyformat.h>
|
#include <tinyformat.h>
|
||||||
|
#include <util/system.h>
|
||||||
#include <util/strencodings.h>
|
#include <util/strencodings.h>
|
||||||
|
|
||||||
InitInterfaces* g_rpc_interfaces = nullptr;
|
InitInterfaces* g_rpc_interfaces = nullptr;
|
||||||
|
|
||||||
|
void RPCTypeCheck(const UniValue& params,
|
||||||
|
const std::list<UniValueType>& typesExpected,
|
||||||
|
bool fAllowNull)
|
||||||
|
{
|
||||||
|
unsigned int i = 0;
|
||||||
|
for (const UniValueType& t : typesExpected) {
|
||||||
|
if (params.size() <= i)
|
||||||
|
break;
|
||||||
|
|
||||||
|
const UniValue& v = params[i];
|
||||||
|
if (!(fAllowNull && v.isNull())) {
|
||||||
|
RPCTypeCheckArgument(v, t);
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void RPCTypeCheckArgument(const UniValue& value, const UniValueType& typeExpected)
|
||||||
|
{
|
||||||
|
if (!typeExpected.typeAny && value.type() != typeExpected.type) {
|
||||||
|
throw JSONRPCError(RPC_TYPE_ERROR, strprintf("Expected type %s, got %s", uvTypeName(typeExpected.type), uvTypeName(value.type())));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void RPCTypeCheckObj(const UniValue& o,
|
||||||
|
const std::map<std::string, UniValueType>& typesExpected,
|
||||||
|
bool fAllowNull,
|
||||||
|
bool fStrict)
|
||||||
|
{
|
||||||
|
for (const auto& t : typesExpected) {
|
||||||
|
const UniValue& v = find_value(o, t.first);
|
||||||
|
if (!fAllowNull && v.isNull())
|
||||||
|
throw JSONRPCError(RPC_TYPE_ERROR, strprintf("Missing %s", t.first));
|
||||||
|
|
||||||
|
if (!(t.second.typeAny || v.type() == t.second.type || (fAllowNull && v.isNull()))) {
|
||||||
|
std::string err = strprintf("Expected type %s for %s, got %s",
|
||||||
|
uvTypeName(t.second.type), t.first, uvTypeName(v.type()));
|
||||||
|
throw JSONRPCError(RPC_TYPE_ERROR, err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fStrict)
|
||||||
|
{
|
||||||
|
for (const std::string& k : o.getKeys())
|
||||||
|
{
|
||||||
|
if (typesExpected.count(k) == 0)
|
||||||
|
{
|
||||||
|
std::string err = strprintf("Unexpected key %s", k);
|
||||||
|
throw JSONRPCError(RPC_TYPE_ERROR, err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CAmount AmountFromValue(const UniValue& value)
|
||||||
|
{
|
||||||
|
if (!value.isNum() && !value.isStr())
|
||||||
|
throw JSONRPCError(RPC_TYPE_ERROR, "Amount is not a number or string");
|
||||||
|
CAmount amount;
|
||||||
|
if (!ParseFixedPoint(value.getValStr(), 8, &amount))
|
||||||
|
throw JSONRPCError(RPC_TYPE_ERROR, "Invalid amount");
|
||||||
|
if (!MoneyRange(amount))
|
||||||
|
throw JSONRPCError(RPC_TYPE_ERROR, "Amount out of range");
|
||||||
|
return amount;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint256 ParseHashV(const UniValue& v, std::string strName)
|
||||||
|
{
|
||||||
|
std::string strHex;
|
||||||
|
if (v.isStr())
|
||||||
|
strHex = v.get_str();
|
||||||
|
if (!IsHex(strHex)) // Note: IsHex("") is false
|
||||||
|
throw JSONRPCError(RPC_INVALID_PARAMETER, strName+" must be hexadecimal string (not '"+strHex+"')");
|
||||||
|
if (64 != strHex.length())
|
||||||
|
throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("%s must be of length %d (not %d)", strName, 64, strHex.length()));
|
||||||
|
uint256 result;
|
||||||
|
result.SetHex(strHex);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
uint256 ParseHashO(const UniValue& o, std::string strKey)
|
||||||
|
{
|
||||||
|
return ParseHashV(find_value(o, strKey), strKey);
|
||||||
|
}
|
||||||
|
std::vector<unsigned char> ParseHexV(const UniValue& v, std::string strName)
|
||||||
|
{
|
||||||
|
std::string strHex;
|
||||||
|
if (v.isStr())
|
||||||
|
strHex = v.get_str();
|
||||||
|
if (!IsHex(strHex))
|
||||||
|
throw JSONRPCError(RPC_INVALID_PARAMETER, strName+" must be hexadecimal string (not '"+strHex+"')");
|
||||||
|
return ParseHex(strHex);
|
||||||
|
}
|
||||||
|
std::vector<unsigned char> ParseHexO(const UniValue& o, std::string strKey)
|
||||||
|
{
|
||||||
|
return ParseHexV(find_value(o, strKey), strKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t ParseInt32V(const UniValue& v, const std::string &strName)
|
||||||
|
{
|
||||||
|
std::string strNum = v.getValStr();
|
||||||
|
int32_t num;
|
||||||
|
if (!ParseInt32(strNum, &num))
|
||||||
|
throw JSONRPCError(RPC_INVALID_PARAMETER, strName+" must be a 32bit integer (not '"+strNum+"')");
|
||||||
|
return num;
|
||||||
|
}
|
||||||
|
|
||||||
|
int64_t ParseInt64V(const UniValue& v, const std::string &strName)
|
||||||
|
{
|
||||||
|
std::string strNum = v.getValStr();
|
||||||
|
int64_t num;
|
||||||
|
if (!ParseInt64(strNum, &num))
|
||||||
|
throw JSONRPCError(RPC_INVALID_PARAMETER, strName+" must be a 64bit integer (not '"+strNum+"')");
|
||||||
|
return num;
|
||||||
|
}
|
||||||
|
|
||||||
|
double ParseDoubleV(const UniValue& v, const std::string &strName)
|
||||||
|
{
|
||||||
|
std::string strNum = v.getValStr();
|
||||||
|
double num;
|
||||||
|
if (!ParseDouble(strNum, &num))
|
||||||
|
throw JSONRPCError(RPC_INVALID_PARAMETER, strName+" must be a be number (not '"+strNum+"')");
|
||||||
|
return num;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ParseBoolV(const UniValue& v, const std::string &strName)
|
||||||
|
{
|
||||||
|
std::string strBool;
|
||||||
|
if (v.isBool())
|
||||||
|
return v.get_bool();
|
||||||
|
else if (v.isNum())
|
||||||
|
strBool = itostr(v.get_int());
|
||||||
|
else if (v.isStr())
|
||||||
|
strBool = v.get_str();
|
||||||
|
|
||||||
|
strBool = ToLower(strBool);
|
||||||
|
|
||||||
|
if (strBool == "true" || strBool == "yes" || strBool == "1") {
|
||||||
|
return true;
|
||||||
|
} else if (strBool == "false" || strBool == "no" || strBool == "0") {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
throw JSONRPCError(RPC_INVALID_PARAMETER, strName+" must be true, false, yes, no, 1 or 0 (not '"+strBool+"')");
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string HelpExampleCli(const std::string& methodname, const std::string& args)
|
||||||
|
{
|
||||||
|
return "> dash-cli " + methodname + " " + args + "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string HelpExampleRpc(const std::string& methodname, const std::string& args)
|
||||||
|
{
|
||||||
|
return "> curl --user myusername --data-binary '{\"jsonrpc\": \"1.0\", \"id\":\"curltest\", "
|
||||||
|
"\"method\": \"" + methodname + "\", \"params\": [" + args + "] }' -H 'content-type: text/plain;'"
|
||||||
|
" http://127.0.0.1:" + strprintf("%d", gArgs.GetArg("-rpcport", BaseParams().RPCPort())) + "/\n";
|
||||||
|
}
|
||||||
|
|
||||||
// Converts a hex string to a public key if possible
|
// Converts a hex string to a public key if possible
|
||||||
CPubKey HexToPubKey(const std::string& hex_in)
|
CPubKey HexToPubKey(const std::string& hex_in)
|
||||||
{
|
{
|
||||||
|
@ -28,6 +28,53 @@ struct InitInterfaces;
|
|||||||
//! state to RPC method implementations.
|
//! state to RPC method implementations.
|
||||||
extern InitInterfaces* g_rpc_interfaces;
|
extern InitInterfaces* g_rpc_interfaces;
|
||||||
|
|
||||||
|
/** Wrapper for UniValue::VType, which includes typeAny:
|
||||||
|
* Used to denote don't care type. */
|
||||||
|
struct UniValueType {
|
||||||
|
UniValueType(UniValue::VType _type) : typeAny(false), type(_type) {}
|
||||||
|
UniValueType() : typeAny(true) {}
|
||||||
|
bool typeAny;
|
||||||
|
UniValue::VType type;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Type-check arguments; throws JSONRPCError if wrong type given. Does not check that
|
||||||
|
* the right number of arguments are passed, just that any passed are the correct type.
|
||||||
|
*/
|
||||||
|
void RPCTypeCheck(const UniValue& params,
|
||||||
|
const std::list<UniValueType>& typesExpected, bool fAllowNull=false);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Type-check one argument; throws JSONRPCError if wrong type given.
|
||||||
|
*/
|
||||||
|
void RPCTypeCheckArgument(const UniValue& value, const UniValueType& typeExpected);
|
||||||
|
|
||||||
|
/*
|
||||||
|
Check for expected keys/value types in an Object.
|
||||||
|
*/
|
||||||
|
void RPCTypeCheckObj(const UniValue& o,
|
||||||
|
const std::map<std::string, UniValueType>& typesExpected,
|
||||||
|
bool fAllowNull = false,
|
||||||
|
bool fStrict = false);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Utilities: convert hex-encoded Values
|
||||||
|
* (throws error if not hex).
|
||||||
|
*/
|
||||||
|
extern uint256 ParseHashV(const UniValue& v, std::string strName);
|
||||||
|
extern uint256 ParseHashO(const UniValue& o, std::string strKey);
|
||||||
|
extern std::vector<unsigned char> ParseHexV(const UniValue& v, std::string strName);
|
||||||
|
extern std::vector<unsigned char> ParseHexO(const UniValue& o, std::string strKey);
|
||||||
|
|
||||||
|
extern int32_t ParseInt32V(const UniValue& v, const std::string &strName);
|
||||||
|
extern int64_t ParseInt64V(const UniValue& v, const std::string &strName);
|
||||||
|
extern double ParseDoubleV(const UniValue& v, const std::string &strName);
|
||||||
|
extern bool ParseBoolV(const UniValue& v, const std::string &strName);
|
||||||
|
|
||||||
|
extern CAmount AmountFromValue(const UniValue& value);
|
||||||
|
extern std::string HelpExampleCli(const std::string& methodname, const std::string& args);
|
||||||
|
extern std::string HelpExampleRpc(const std::string& methodname, const std::string& args);
|
||||||
|
|
||||||
CPubKey HexToPubKey(const std::string& hex_in);
|
CPubKey HexToPubKey(const std::string& hex_in);
|
||||||
CPubKey AddrToPubKey(CKeyStore* const keystore, const std::string& addr_in);
|
CPubKey AddrToPubKey(CKeyStore* const keystore, const std::string& addr_in);
|
||||||
CScript CreateMultisigRedeemscript(const int required, const std::vector<CPubKey>& pubkeys);
|
CScript CreateMultisigRedeemscript(const int required, const std::vector<CPubKey>& pubkeys);
|
||||||
|
@ -16,7 +16,7 @@
|
|||||||
#include <protocol.h>
|
#include <protocol.h>
|
||||||
#include <script/standard.h>
|
#include <script/standard.h>
|
||||||
#include <timedata.h>
|
#include <timedata.h>
|
||||||
#include <validation.h>
|
#include <util/validation.h> // for strMessageMagic
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
#include <policy/policy.h>
|
#include <policy/policy.h>
|
||||||
#include <script/script.h>
|
#include <script/script.h>
|
||||||
#include <script/script_error.h>
|
#include <script/script_error.h>
|
||||||
|
#include <policy/settings.h>
|
||||||
#include <script/sign.h>
|
#include <script/sign.h>
|
||||||
#include <script/ismine.h>
|
#include <script/ismine.h>
|
||||||
#include <test/setup_common.h>
|
#include <test/setup_common.h>
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
#include <script/sign.h>
|
#include <script/sign.h>
|
||||||
#include <util/system.h>
|
#include <util/system.h>
|
||||||
#include <util/strencodings.h>
|
#include <util/strencodings.h>
|
||||||
|
#include <rpc/util.h>
|
||||||
#include <test/setup_common.h>
|
#include <test/setup_common.h>
|
||||||
|
|
||||||
#if defined(HAVE_CONSENSUS_LIB)
|
#if defined(HAVE_CONSENSUS_LIB)
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
// Distributed under the MIT software license, see the accompanying
|
// Distributed under the MIT software license, see the accompanying
|
||||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||||
|
|
||||||
#include <consensus/tx_verify.h>
|
#include <consensus/tx_check.h>
|
||||||
#include <consensus/validation.h>
|
#include <consensus/validation.h>
|
||||||
#include <test/data/sighash.json.h>
|
#include <test/data/sighash.json.h>
|
||||||
#include <hash.h>
|
#include <hash.h>
|
||||||
|
@ -8,13 +8,14 @@
|
|||||||
|
|
||||||
#include <clientversion.h>
|
#include <clientversion.h>
|
||||||
#include <checkqueue.h>
|
#include <checkqueue.h>
|
||||||
#include <consensus/tx_verify.h>
|
#include <consensus/tx_check.h>
|
||||||
#include <consensus/validation.h>
|
#include <consensus/validation.h>
|
||||||
#include <core_io.h>
|
#include <core_io.h>
|
||||||
#include <key.h>
|
#include <key.h>
|
||||||
#include <keystore.h>
|
#include <keystore.h>
|
||||||
#include <validation.h>
|
#include <validation.h>
|
||||||
#include <policy/policy.h>
|
#include <policy/policy.h>
|
||||||
|
#include <policy/settings.h>
|
||||||
#include <script/script.h>
|
#include <script/script.h>
|
||||||
#include <script/script_error.h>
|
#include <script/script_error.h>
|
||||||
#include <util/strencodings.h>
|
#include <util/strencodings.h>
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
#include <validation.h>
|
#include <validation.h>
|
||||||
#include <policy/policy.h>
|
#include <policy/policy.h>
|
||||||
#include <policy/fees.h>
|
#include <policy/fees.h>
|
||||||
|
#include <policy/settings.h>
|
||||||
#include <reverse_iterator.h>
|
#include <reverse_iterator.h>
|
||||||
#include <streams.h>
|
#include <streams.h>
|
||||||
#include <timedata.h>
|
#include <timedata.h>
|
||||||
|
@ -6,6 +6,32 @@
|
|||||||
|
|
||||||
#include <util/system.h>
|
#include <util/system.h>
|
||||||
|
|
||||||
|
std::string TransactionErrorString(const TransactionError err)
|
||||||
|
{
|
||||||
|
switch (err) {
|
||||||
|
case TransactionError::OK:
|
||||||
|
return "No error";
|
||||||
|
case TransactionError::MISSING_INPUTS:
|
||||||
|
return "Missing inputs";
|
||||||
|
case TransactionError::ALREADY_IN_CHAIN:
|
||||||
|
return "Transaction already in block chain";
|
||||||
|
case TransactionError::P2P_DISABLED:
|
||||||
|
return "Peer-to-peer functionality missing or disabled";
|
||||||
|
case TransactionError::MEMPOOL_REJECTED:
|
||||||
|
return "Transaction rejected by AcceptToMemoryPool";
|
||||||
|
case TransactionError::MEMPOOL_ERROR:
|
||||||
|
return "AcceptToMemoryPool failed";
|
||||||
|
case TransactionError::INVALID_PSBT:
|
||||||
|
return "PSBT is not sane";
|
||||||
|
case TransactionError::PSBT_MISMATCH:
|
||||||
|
return "PSBTs not compatible (different transactions)";
|
||||||
|
case TransactionError::SIGHASH_MISMATCH:
|
||||||
|
return "Specified sighash value does not match existing value";
|
||||||
|
// no default case, so the compiler can warn about missing cases
|
||||||
|
}
|
||||||
|
assert(false);
|
||||||
|
}
|
||||||
|
|
||||||
std::string AmountHighWarn(const std::string& optname)
|
std::string AmountHighWarn(const std::string& optname)
|
||||||
{
|
{
|
||||||
return strprintf(_("%s is set very high!"), optname);
|
return strprintf(_("%s is set very high!"), optname);
|
||||||
|
@ -17,6 +17,20 @@
|
|||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
enum class TransactionError {
|
||||||
|
OK, //!< No error
|
||||||
|
MISSING_INPUTS,
|
||||||
|
ALREADY_IN_CHAIN,
|
||||||
|
P2P_DISABLED,
|
||||||
|
MEMPOOL_REJECTED,
|
||||||
|
MEMPOOL_ERROR,
|
||||||
|
INVALID_PSBT,
|
||||||
|
PSBT_MISMATCH,
|
||||||
|
SIGHASH_MISMATCH,
|
||||||
|
};
|
||||||
|
|
||||||
|
std::string TransactionErrorString(const TransactionError error);
|
||||||
|
|
||||||
std::string AmountHighWarn(const std::string& optname);
|
std::string AmountHighWarn(const std::string& optname);
|
||||||
std::string AmountErrMsg(const char* const optname, const std::string& strValue);
|
std::string AmountErrMsg(const char* const optname, const std::string& strValue);
|
||||||
|
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
#include <checkqueue.h>
|
#include <checkqueue.h>
|
||||||
#include <consensus/consensus.h>
|
#include <consensus/consensus.h>
|
||||||
#include <consensus/merkle.h>
|
#include <consensus/merkle.h>
|
||||||
|
#include <consensus/tx_check.h>
|
||||||
#include <consensus/tx_verify.h>
|
#include <consensus/tx_verify.h>
|
||||||
#include <consensus/validation.h>
|
#include <consensus/validation.h>
|
||||||
#include <cuckoocache.h>
|
#include <cuckoocache.h>
|
||||||
@ -22,6 +23,7 @@
|
|||||||
#include <logging/timer.h>
|
#include <logging/timer.h>
|
||||||
#include <policy/fees.h>
|
#include <policy/fees.h>
|
||||||
#include <policy/policy.h>
|
#include <policy/policy.h>
|
||||||
|
#include <policy/settings.h>
|
||||||
#include <pow.h>
|
#include <pow.h>
|
||||||
#include <primitives/block.h>
|
#include <primitives/block.h>
|
||||||
#include <primitives/transaction.h>
|
#include <primitives/transaction.h>
|
||||||
@ -141,7 +143,6 @@ bool fTimestampIndex = false;
|
|||||||
bool fSpentIndex = false;
|
bool fSpentIndex = false;
|
||||||
bool fHavePruned = false;
|
bool fHavePruned = false;
|
||||||
bool fPruneMode = false;
|
bool fPruneMode = false;
|
||||||
bool fIsBareMultisigStd = DEFAULT_PERMIT_BAREMULTISIG;
|
|
||||||
bool fRequireStandard = true;
|
bool fRequireStandard = true;
|
||||||
bool fCheckBlockIndex = false;
|
bool fCheckBlockIndex = false;
|
||||||
bool fCheckpointsEnabled = DEFAULT_CHECKPOINTS_ENABLED;
|
bool fCheckpointsEnabled = DEFAULT_CHECKPOINTS_ENABLED;
|
||||||
|
@ -83,8 +83,6 @@ static const unsigned int MAX_REJECT_MESSAGE_LENGTH = 111;
|
|||||||
|
|
||||||
static const int64_t DEFAULT_MAX_TIP_AGE = 6 * 60 * 60; // ~144 blocks behind -> 2 x fork detection time, was 24 * 60 * 60 in bitcoin
|
static const int64_t DEFAULT_MAX_TIP_AGE = 6 * 60 * 60; // ~144 blocks behind -> 2 x fork detection time, was 24 * 60 * 60 in bitcoin
|
||||||
|
|
||||||
/** Default for -permitbaremultisig */
|
|
||||||
static const bool DEFAULT_PERMIT_BAREMULTISIG = true;
|
|
||||||
static const bool DEFAULT_CHECKPOINTS_ENABLED = true;
|
static const bool DEFAULT_CHECKPOINTS_ENABLED = true;
|
||||||
static const bool DEFAULT_TXINDEX = true;
|
static const bool DEFAULT_TXINDEX = true;
|
||||||
static const bool DEFAULT_ADDRESSINDEX = false;
|
static const bool DEFAULT_ADDRESSINDEX = false;
|
||||||
@ -130,7 +128,6 @@ typedef std::unordered_map<uint256, CBlockIndex*, BlockHasher> BlockMap;
|
|||||||
typedef std::unordered_multimap<uint256, CBlockIndex*, BlockHasher> PrevBlockMap;
|
typedef std::unordered_multimap<uint256, CBlockIndex*, BlockHasher> PrevBlockMap;
|
||||||
extern uint64_t nLastBlockTx;
|
extern uint64_t nLastBlockTx;
|
||||||
extern uint64_t nLastBlockSize;
|
extern uint64_t nLastBlockSize;
|
||||||
extern const std::string strMessageMagic;
|
|
||||||
extern Mutex g_best_block_mutex;
|
extern Mutex g_best_block_mutex;
|
||||||
extern std::condition_variable g_best_block_cv;
|
extern std::condition_variable g_best_block_cv;
|
||||||
extern uint256 g_best_block;
|
extern uint256 g_best_block;
|
||||||
@ -139,7 +136,6 @@ extern std::atomic_bool fReindex;
|
|||||||
extern bool fAddressIndex;
|
extern bool fAddressIndex;
|
||||||
extern bool fTimestampIndex;
|
extern bool fTimestampIndex;
|
||||||
extern bool fSpentIndex;
|
extern bool fSpentIndex;
|
||||||
extern bool fIsBareMultisigStd;
|
|
||||||
/** Whether there are dedicated script-checking threads running.
|
/** Whether there are dedicated script-checking threads running.
|
||||||
* False indicates all script checking is done on the main threadMessageHandler thread.
|
* False indicates all script checking is done on the main threadMessageHandler thread.
|
||||||
*/
|
*/
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
#include <wallet/fees.h>
|
#include <wallet/fees.h>
|
||||||
|
|
||||||
#include <policy/policy.h>
|
#include <policy/policy.h>
|
||||||
|
#include <policy/settings.h>
|
||||||
#include <util/system.h>
|
#include <util/system.h>
|
||||||
#include <validation.h>
|
#include <validation.h>
|
||||||
#include <wallet/coincontrol.h>
|
#include <wallet/coincontrol.h>
|
||||||
|
@ -256,58 +256,6 @@ bool WalletInit::ParameterInteraction() const
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool VerifyWallets(interfaces::Chain& chain, const std::vector<std::string>& wallet_files)
|
|
||||||
{
|
|
||||||
if (gArgs.IsArgSet("-walletdir")) {
|
|
||||||
fs::path wallet_dir = gArgs.GetArg("-walletdir", "");
|
|
||||||
boost::system::error_code error;
|
|
||||||
// The canonical path cleans the path, preventing >1 Berkeley environment instances for the same directory
|
|
||||||
fs::path canonical_wallet_dir = fs::canonical(wallet_dir, error);
|
|
||||||
if (error || !fs::exists(wallet_dir)) {
|
|
||||||
chain.initError(strprintf(_("Specified -walletdir \"%s\" does not exist"), wallet_dir.string()));
|
|
||||||
return false;
|
|
||||||
} else if (!fs::is_directory(wallet_dir)) {
|
|
||||||
chain.initError(strprintf(_("Specified -walletdir \"%s\" is not a directory"), wallet_dir.string()));
|
|
||||||
return false;
|
|
||||||
// The canonical path transforms relative paths into absolute ones, so we check the non-canonical version
|
|
||||||
} else if (!wallet_dir.is_absolute()) {
|
|
||||||
chain.initError(strprintf(_("Specified -walletdir \"%s\" is a relative path"), wallet_dir.string()));
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
gArgs.ForceSetArg("-walletdir", canonical_wallet_dir.string());
|
|
||||||
}
|
|
||||||
|
|
||||||
LogPrintf("Using wallet directory %s\n", GetWalletDir().string());
|
|
||||||
|
|
||||||
chain.initMessage(_("Verifying wallet(s)..."));
|
|
||||||
|
|
||||||
// Parameter interaction code should have thrown an error if -salvagewallet
|
|
||||||
// was enabled with more than wallet file, so the wallet_files size check
|
|
||||||
// here should have no effect.
|
|
||||||
bool salvage_wallet = gArgs.GetBoolArg("-salvagewallet", false) && wallet_files.size() <= 1;
|
|
||||||
|
|
||||||
// Keep track of each wallet absolute path to detect duplicates.
|
|
||||||
std::set<fs::path> wallet_paths;
|
|
||||||
|
|
||||||
for (const auto& wallet_file : wallet_files) {
|
|
||||||
WalletLocation location(wallet_file);
|
|
||||||
|
|
||||||
if (!wallet_paths.insert(location.GetPath()).second) {
|
|
||||||
chain.initError(strprintf(_("Error loading wallet %s. Duplicate -wallet filename specified."), wallet_file));
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string error_string;
|
|
||||||
std::string warning_string;
|
|
||||||
bool verify_success = CWallet::Verify(chain, location, salvage_wallet, error_string, warning_string);
|
|
||||||
if (!error_string.empty()) chain.initError(error_string);
|
|
||||||
if (!warning_string.empty()) chain.initWarning(warning_string);
|
|
||||||
if (!verify_success) return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void WalletInit::Construct(InitInterfaces& interfaces) const
|
void WalletInit::Construct(InitInterfaces& interfaces) const
|
||||||
{
|
{
|
||||||
if (gArgs.GetBoolArg("-disablewallet", DEFAULT_DISABLE_WALLET)) {
|
if (gArgs.GetBoolArg("-disablewallet", DEFAULT_DISABLE_WALLET)) {
|
||||||
@ -318,62 +266,6 @@ void WalletInit::Construct(InitInterfaces& interfaces) const
|
|||||||
interfaces.chain_clients.emplace_back(interfaces::MakeWalletClient(*interfaces.chain, gArgs.GetArgs("-wallet")));
|
interfaces.chain_clients.emplace_back(interfaces::MakeWalletClient(*interfaces.chain, gArgs.GetArgs("-wallet")));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool LoadWallets(interfaces::Chain& chain, const std::vector<std::string>& wallet_files)
|
|
||||||
{
|
|
||||||
for (const std::string& walletFile : wallet_files) {
|
|
||||||
std::shared_ptr<CWallet> pwallet = CWallet::CreateWalletFromFile(chain, WalletLocation(walletFile));
|
|
||||||
if (!pwallet) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void StartWallets(CScheduler& scheduler)
|
|
||||||
{
|
|
||||||
for (const std::shared_ptr<CWallet>& pwallet : GetWallets()) {
|
|
||||||
pwallet->postInitProcess();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Run a thread to flush wallet periodically
|
|
||||||
scheduler.scheduleEvery(MaybeCompactWalletDB, 500);
|
|
||||||
|
|
||||||
if (!fMasternodeMode && CCoinJoinClientOptions::IsEnabled()) {
|
|
||||||
scheduler.scheduleEvery(std::bind(&DoCoinJoinMaintenance, std::ref(*g_connman)), 1 * 1000);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void FlushWallets()
|
|
||||||
{
|
|
||||||
for (const std::shared_ptr<CWallet>& pwallet : GetWallets()) {
|
|
||||||
if (CCoinJoinClientOptions::IsEnabled()) {
|
|
||||||
// Stop CoinJoin, release keys
|
|
||||||
auto it = coinJoinClientManagers.find(pwallet->GetName());
|
|
||||||
it->second->ResetPool();
|
|
||||||
it->second->StopMixing();
|
|
||||||
}
|
|
||||||
pwallet->Flush(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void StopWallets()
|
|
||||||
{
|
|
||||||
for (const std::shared_ptr<CWallet>& pwallet : GetWallets()) {
|
|
||||||
pwallet->Flush(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void UnloadWallets()
|
|
||||||
{
|
|
||||||
auto wallets = GetWallets();
|
|
||||||
while (!wallets.empty()) {
|
|
||||||
auto wallet = wallets.back();
|
|
||||||
wallets.pop_back();
|
|
||||||
RemoveWallet(wallet);
|
|
||||||
UnloadWallet(std::move(wallet));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void WalletInit::AutoLockMasternodeCollaterals() const
|
void WalletInit::AutoLockMasternodeCollaterals() const
|
||||||
{
|
{
|
||||||
|
123
src/wallet/load.cpp
Normal file
123
src/wallet/load.cpp
Normal file
@ -0,0 +1,123 @@
|
|||||||
|
// Copyright (c) 2009-2010 Satoshi Nakamoto
|
||||||
|
// Copyright (c) 2009-2018 The Bitcoin Core developers
|
||||||
|
// Distributed under the MIT software license, see the accompanying
|
||||||
|
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||||
|
|
||||||
|
#include <wallet/load.h>
|
||||||
|
|
||||||
|
#include <net.h>
|
||||||
|
#include <coinjoin/client.h>
|
||||||
|
#include <coinjoin/options.h>
|
||||||
|
#include <interfaces/chain.h>
|
||||||
|
#include <scheduler.h>
|
||||||
|
#include <util/system.h>
|
||||||
|
#include <wallet/wallet.h>
|
||||||
|
|
||||||
|
bool VerifyWallets(interfaces::Chain& chain, const std::vector<std::string>& wallet_files)
|
||||||
|
{
|
||||||
|
if (gArgs.IsArgSet("-walletdir")) {
|
||||||
|
fs::path wallet_dir = gArgs.GetArg("-walletdir", "");
|
||||||
|
boost::system::error_code error;
|
||||||
|
// The canonical path cleans the path, preventing >1 Berkeley environment instances for the same directory
|
||||||
|
fs::path canonical_wallet_dir = fs::canonical(wallet_dir, error);
|
||||||
|
if (error || !fs::exists(wallet_dir)) {
|
||||||
|
chain.initError(strprintf(_("Specified -walletdir \"%s\" does not exist"), wallet_dir.string()));
|
||||||
|
return false;
|
||||||
|
} else if (!fs::is_directory(wallet_dir)) {
|
||||||
|
chain.initError(strprintf(_("Specified -walletdir \"%s\" is not a directory"), wallet_dir.string()));
|
||||||
|
return false;
|
||||||
|
// The canonical path transforms relative paths into absolute ones, so we check the non-canonical version
|
||||||
|
} else if (!wallet_dir.is_absolute()) {
|
||||||
|
chain.initError(strprintf(_("Specified -walletdir \"%s\" is a relative path"), wallet_dir.string()));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
gArgs.ForceSetArg("-walletdir", canonical_wallet_dir.string());
|
||||||
|
}
|
||||||
|
|
||||||
|
LogPrintf("Using wallet directory %s\n", GetWalletDir().string());
|
||||||
|
|
||||||
|
chain.initMessage(_("Verifying wallet(s)..."));
|
||||||
|
|
||||||
|
// Parameter interaction code should have thrown an error if -salvagewallet
|
||||||
|
// was enabled with more than wallet file, so the wallet_files size check
|
||||||
|
// here should have no effect.
|
||||||
|
bool salvage_wallet = gArgs.GetBoolArg("-salvagewallet", false) && wallet_files.size() <= 1;
|
||||||
|
|
||||||
|
// Keep track of each wallet absolute path to detect duplicates.
|
||||||
|
std::set<fs::path> wallet_paths;
|
||||||
|
|
||||||
|
for (const auto& wallet_file : wallet_files) {
|
||||||
|
WalletLocation location(wallet_file);
|
||||||
|
|
||||||
|
if (!wallet_paths.insert(location.GetPath()).second) {
|
||||||
|
chain.initError(strprintf(_("Error loading wallet %s. Duplicate -wallet filename specified."), wallet_file));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string error_string;
|
||||||
|
std::string warning_string;
|
||||||
|
bool verify_success = CWallet::Verify(chain, location, salvage_wallet, error_string, warning_string);
|
||||||
|
if (!error_string.empty()) chain.initError(error_string);
|
||||||
|
if (!warning_string.empty()) chain.initWarning(warning_string);
|
||||||
|
if (!verify_success) return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool LoadWallets(interfaces::Chain& chain, const std::vector<std::string>& wallet_files)
|
||||||
|
{
|
||||||
|
for (const std::string& walletFile : wallet_files) {
|
||||||
|
std::shared_ptr<CWallet> pwallet = CWallet::CreateWalletFromFile(chain, WalletLocation(walletFile));
|
||||||
|
if (!pwallet) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void StartWallets(CScheduler& scheduler)
|
||||||
|
{
|
||||||
|
for (const std::shared_ptr<CWallet>& pwallet : GetWallets()) {
|
||||||
|
pwallet->postInitProcess();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Run a thread to flush wallet periodically
|
||||||
|
scheduler.scheduleEvery(MaybeCompactWalletDB, 500);
|
||||||
|
|
||||||
|
if (!fMasternodeMode && CCoinJoinClientOptions::IsEnabled()) {
|
||||||
|
scheduler.scheduleEvery(std::bind(&DoCoinJoinMaintenance, std::ref(*g_connman)), 1 * 1000);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void FlushWallets()
|
||||||
|
{
|
||||||
|
for (const std::shared_ptr<CWallet>& pwallet : GetWallets()) {
|
||||||
|
if (CCoinJoinClientOptions::IsEnabled()) {
|
||||||
|
// Stop CoinJoin, release keys
|
||||||
|
auto it = coinJoinClientManagers.find(pwallet->GetName());
|
||||||
|
it->second->ResetPool();
|
||||||
|
it->second->StopMixing();
|
||||||
|
}
|
||||||
|
pwallet->Flush(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void StopWallets()
|
||||||
|
{
|
||||||
|
for (const std::shared_ptr<CWallet>& pwallet : GetWallets()) {
|
||||||
|
pwallet->Flush(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void UnloadWallets()
|
||||||
|
{
|
||||||
|
auto wallets = GetWallets();
|
||||||
|
while (!wallets.empty()) {
|
||||||
|
auto wallet = wallets.back();
|
||||||
|
wallets.pop_back();
|
||||||
|
RemoveWallet(wallet);
|
||||||
|
UnloadWallet(std::move(wallet));
|
||||||
|
}
|
||||||
|
}
|
38
src/wallet/load.h
Normal file
38
src/wallet/load.h
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
// Copyright (c) 2009-2010 Satoshi Nakamoto
|
||||||
|
// Copyright (c) 2009-2018 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_WALLET_LOAD_H
|
||||||
|
#define BITCOIN_WALLET_LOAD_H
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
class CScheduler;
|
||||||
|
|
||||||
|
namespace interfaces {
|
||||||
|
class Chain;
|
||||||
|
} // namespace interfaces
|
||||||
|
|
||||||
|
//! Responsible for reading and validating the -wallet arguments and verifying the wallet database.
|
||||||
|
//! This function will perform salvage on the wallet if requested, as long as only one wallet is
|
||||||
|
//! being loaded (WalletParameterInteraction forbids -salvagewallet, -zapwallettxes or -upgradewallet with multiwallet).
|
||||||
|
bool VerifyWallets(interfaces::Chain& chain, const std::vector<std::string>& wallet_files);
|
||||||
|
|
||||||
|
//! Load wallet databases.
|
||||||
|
bool LoadWallets(interfaces::Chain& chain, const std::vector<std::string>& wallet_files);
|
||||||
|
|
||||||
|
//! Complete startup of wallets.
|
||||||
|
void StartWallets(CScheduler& scheduler);
|
||||||
|
|
||||||
|
//! Flush all wallets in preparation for shutdown.
|
||||||
|
void FlushWallets();
|
||||||
|
|
||||||
|
//! Stop all wallets. Wallets will be flushed first.
|
||||||
|
void StopWallets();
|
||||||
|
|
||||||
|
//! Close all wallets.
|
||||||
|
void UnloadWallets();
|
||||||
|
|
||||||
|
#endif // BITCOIN_WALLET_LOAD_H
|
@ -18,7 +18,7 @@
|
|||||||
#include <policy/feerate.h>
|
#include <policy/feerate.h>
|
||||||
#include <policy/fees.h>
|
#include <policy/fees.h>
|
||||||
#include <rpc/mining.h>
|
#include <rpc/mining.h>
|
||||||
#include <rpc/rawtransaction.h>
|
#include <rpc/rawtransaction_util.h>
|
||||||
#include <rpc/server.h>
|
#include <rpc/server.h>
|
||||||
#include <rpc/util.h>
|
#include <rpc/util.h>
|
||||||
#include <script/descriptor.h>
|
#include <script/descriptor.h>
|
||||||
|
@ -20,6 +20,7 @@
|
|||||||
#include <net.h>
|
#include <net.h>
|
||||||
#include <policy/fees.h>
|
#include <policy/fees.h>
|
||||||
#include <policy/policy.h>
|
#include <policy/policy.h>
|
||||||
|
#include <policy/settings.h>
|
||||||
#include <primitives/block.h>
|
#include <primitives/block.h>
|
||||||
#include <primitives/transaction.h>
|
#include <primitives/transaction.h>
|
||||||
#include <script/script.h>
|
#include <script/script.h>
|
||||||
|
@ -39,26 +39,6 @@
|
|||||||
#include <utility>
|
#include <utility>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
//! Responsible for reading and validating the -wallet arguments and verifying the wallet database.
|
|
||||||
// This function will perform salvage on the wallet if requested, as long as only one wallet is
|
|
||||||
// being loaded (WalletParameterInteraction forbids -salvagewallet, -zapwallettxes or -upgradewallet with multiwallet).
|
|
||||||
bool VerifyWallets(interfaces::Chain& chain, const std::vector<std::string>& wallet_files);
|
|
||||||
|
|
||||||
//! Load wallet databases.
|
|
||||||
bool LoadWallets(interfaces::Chain& chain, const std::vector<std::string>& wallet_files);
|
|
||||||
|
|
||||||
//! Complete startup of wallets.
|
|
||||||
void StartWallets(CScheduler& scheduler);
|
|
||||||
|
|
||||||
//! Flush all wallets in preparation for shutdown.
|
|
||||||
void FlushWallets();
|
|
||||||
|
|
||||||
//! Stop all wallets. Wallets will be flushed first.
|
|
||||||
void StopWallets();
|
|
||||||
|
|
||||||
//! Close all wallets.
|
|
||||||
void UnloadWallets();
|
|
||||||
|
|
||||||
//! Explicitly unload and delete the wallet.
|
//! Explicitly unload and delete the wallet.
|
||||||
// Blocks the current thread after signaling the unload intent so that all
|
// Blocks the current thread after signaling the unload intent so that all
|
||||||
// wallet clients release the wallet.
|
// wallet clients release the wallet.
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
|
|
||||||
#include <wallet/walletdb.h>
|
#include <wallet/walletdb.h>
|
||||||
|
|
||||||
#include <consensus/tx_verify.h>
|
#include <consensus/tx_check.h>
|
||||||
#include <consensus/validation.h>
|
#include <consensus/validation.h>
|
||||||
#include <key_io.h>
|
#include <key_io.h>
|
||||||
#include <fs.h>
|
#include <fs.h>
|
||||||
|
@ -12,7 +12,7 @@ EXPECTED_CIRCULAR_DEPENDENCIES=(
|
|||||||
"chainparamsbase -> util/system -> chainparamsbase"
|
"chainparamsbase -> util/system -> chainparamsbase"
|
||||||
"index/txindex -> validation -> index/txindex"
|
"index/txindex -> validation -> index/txindex"
|
||||||
"policy/fees -> txmempool -> policy/fees"
|
"policy/fees -> txmempool -> policy/fees"
|
||||||
"policy/policy -> validation -> policy/policy"
|
"policy/policy -> policy/settings -> policy/policy"
|
||||||
"qt/addresstablemodel -> qt/walletmodel -> qt/addresstablemodel"
|
"qt/addresstablemodel -> qt/walletmodel -> qt/addresstablemodel"
|
||||||
"qt/bantablemodel -> qt/clientmodel -> qt/bantablemodel"
|
"qt/bantablemodel -> qt/clientmodel -> qt/bantablemodel"
|
||||||
"qt/bitcoingui -> qt/utilitydialog -> qt/bitcoingui"
|
"qt/bitcoingui -> qt/utilitydialog -> qt/bitcoingui"
|
||||||
@ -29,6 +29,7 @@ EXPECTED_CIRCULAR_DEPENDENCIES=(
|
|||||||
"wallet/wallet -> wallet/walletdb -> wallet/wallet"
|
"wallet/wallet -> wallet/walletdb -> wallet/wallet"
|
||||||
"wallet/coincontrol -> wallet/wallet -> wallet/coincontrol"
|
"wallet/coincontrol -> wallet/wallet -> wallet/coincontrol"
|
||||||
"policy/fees -> policy/policy -> validation -> policy/fees"
|
"policy/fees -> policy/policy -> validation -> policy/fees"
|
||||||
|
"policy/policy -> validation -> policy/policy"
|
||||||
"qt/addressbookpage -> qt/bitcoingui -> qt/walletview -> qt/addressbookpage"
|
"qt/addressbookpage -> qt/bitcoingui -> qt/walletview -> qt/addressbookpage"
|
||||||
"txmempool -> validation -> validationinterface -> txmempool"
|
"txmempool -> validation -> validationinterface -> txmempool"
|
||||||
"qt/addressbookpage -> qt/bitcoingui -> qt/walletview -> qt/receivecoinsdialog -> qt/addressbookpage"
|
"qt/addressbookpage -> qt/bitcoingui -> qt/walletview -> qt/receivecoinsdialog -> qt/addressbookpage"
|
||||||
|
Loading…
Reference in New Issue
Block a user