Merge pull request #4638 from Munkybooty/backports-0.18-pr18

Backports 0.18 pr18
This commit is contained in:
PastaPastaPasta 2022-03-05 12:43:14 -06:00 committed by GitHub
commit c67867582d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
29 changed files with 348 additions and 165 deletions

View File

@ -644,7 +644,7 @@ case $host in
AC_MSG_ERROR("windres not found")
fi
CPPFLAGS="$CPPFLAGS -D_MT -DWIN32 -D_WINDOWS -DBOOST_THREAD_USE_LIB"
CPPFLAGS="$CPPFLAGS -D_MT -DWIN32 -D_WINDOWS -DBOOST_THREAD_USE_LIB -D_WIN32_WINNT=0x0601"
if test "x$CXXFLAGS_overridden" = "xno"; then
CXXFLAGS="$CXXFLAGS -w"
fi

View File

@ -10,6 +10,7 @@ MANDIR=${MANDIR:-$TOPDIR/doc/man}
BITCOIND=${BITCOIND:-$BINDIR/dashd}
BITCOINCLI=${BITCOINCLI:-$BINDIR/dash-cli}
BITCOINTX=${BITCOINTX:-$BINDIR/dash-tx}
WALLET_TOOL=${WALLET_TOOL:-$BINDIR/dash-wallet}
BITCOINQT=${BITCOINQT:-$BINDIR/qt/dash-qt}
[ ! -x $BITCOIND ] && echo "$BITCOIND not found or not executable." && exit 1
@ -23,7 +24,7 @@ read -r -a BTCVER <<< "$($BITCOINCLI --version | head -n1 | awk -F'[ -]' '{ prin
echo "[COPYRIGHT]" > footer.h2m
$BITCOIND --version | sed -n '1!p' >> footer.h2m
for cmd in $BITCOIND $BITCOINCLI $BITCOINTX $BITCOINQT; do
for cmd in $BITCOIND $BITCOINCLI $BITCOINTX $WALLET_TOOL $BITCOINQT; do
cmdname="${cmd##*/}"
help2man -N --version-string=${BTCVER[0]} --include=footer.h2m -o ${MANDIR}/${cmdname}.1 ${cmd}
sed -i "s/\\\-${BTCVER[1]}//g" ${MANDIR}/${cmdname}.1

View File

@ -89,7 +89,7 @@ sign=SIGHASH\-FLAGS
.IP
Add zero or more signatures to transaction. This command requires JSON
registers:prevtxs=JSON object, privatekeys=JSON object. See
signrawtransaction docs for format of sighash flags, JSON
signrawtransactionwithkey docs for format of sighash flags, JSON
objects.
.PP
Register Commands:

68
doc/man/dash-wallet.1 Normal file
View File

@ -0,0 +1,68 @@
.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.47.6.
.TH DASH-WALLET "1" "February 2019" "dash-wallet v0.17.99.0" "User Commands"
.SH NAME
dash-wallet \- manual page for dash-wallet v0.17.99.0
.SH DESCRIPTION
DASH Core dash\-wallet version v0.17.99.0
.PP
wallet\-tool is an offline tool for creating and interacting with Dash Core wallet files.
By default wallet\-tool will act on wallets in the default mainnet wallet directory in the datadir.
To change the target wallet, use the \fB\-datadir\fR, \fB\-wallet\fR and \fB\-testnet\fR/\-regtest arguments.
.SS "Usage:"
.IP
dash\-wallet [options] <command>
.SH OPTIONS
.HP
\-?
.IP
This help message
.HP
\fB\-datadir=\fR<dir>
.IP
Specify data directory
.HP
\fB\-wallet=\fR<wallet\-name>
.IP
Specify wallet name
.PP
Debugging/Testing options:
.HP
\fB\-debug=\fR<category>
.IP
Output debugging information (default: 0).
.HP
\fB\-printtoconsole\fR
.IP
Send trace/debug info to console (default: 1 when no \fB\-debug\fR is true, 0
otherwise.
.PP
Chain selection options:
.HP
\fB\-testnet\fR
.IP
Use the test chain
.PP
Commands:
.IP
create
.IP
Create new wallet file
.IP
info
.IP
Get wallet info
.SH COPYRIGHT
Copyright (C) 2014-2021 The Dash Core developers
Copyright (C) 2009-2019 The Bitcoin Core developers
Please contribute if you find Bitcoin Core useful. Visit
<https://bitcoincore.org> for further information about the software.
The source code is available from <https://github.com/bitcoin/bitcoin>.
This is experimental software.
Distributed under the MIT software license, see the accompanying file COPYING
or <https://opensource.org/licenses/MIT>
This product includes software developed by the OpenSSL Project for use in the
OpenSSL Toolkit <https://www.openssl.org> and cryptographic software written by
Eric Young and UPnP software written by Thomas Bernard.

View File

@ -57,7 +57,7 @@ Specify data directory
.HP
\fB\-dbcache=\fR<n>
.IP
Set database cache size in megabytes (4 to 16384, default: 300)
Set database cache size in MiB (4 to 16384, default: 300)
.HP
\fB\-debuglogfile=\fR<file>
.IP
@ -741,7 +741,7 @@ relaying, mining and transaction creation (default: 0.00001)
\fB\-whitelistforcerelay\fR
.IP
Force relay of transactions from whitelisted peers even if they violate
local relay policy (default: 1)
local relay policy (default: 0)
.HP
\fB\-whitelistrelay\fR
.IP

View File

@ -11,10 +11,6 @@
#endif
#ifdef WIN32
#ifdef _WIN32_WINNT
#undef _WIN32_WINNT
#endif
#define _WIN32_WINNT 0x0501
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN 1
#endif

View File

@ -1231,16 +1231,7 @@ bool AppInitBasicSetup()
#endif
#ifdef WIN32
// Enable Data Execution Prevention (DEP)
// Minimum supported OS versions: WinXP SP3, WinVista >= SP1, Win Server 2008
// A failure is non-critical and needs no further attention!
#ifndef PROCESS_DEP_ENABLE
// We define this here, because GCCs winbase.h limits this to _WIN32_WINNT >= 0x0601 (Windows 7),
// which is not correct. Can be removed, when GCCs winbase.h is fixed!
#define PROCESS_DEP_ENABLE 0x00000001
#endif
typedef BOOL (WINAPI *PSETPROCDEPPOL)(DWORD);
PSETPROCDEPPOL setProcDEPPol = (PSETPROCDEPPOL)GetProcAddress(GetModuleHandleA("Kernel32.dll"), "SetProcessDEPPolicy");
if (setProcDEPPol != nullptr) setProcDEPPol(PROCESS_DEP_ENABLE);
SetProcessDEPPolicy(PROCESS_DEP_ENABLE);
#endif
if (!SetupNetworking())

View File

@ -10,16 +10,16 @@
#include <chain.h>
#include <chainparams.h>
#include <consensus/consensus.h>
#include <consensus/tx_verify.h>
#include <consensus/merkle.h>
#include <consensus/tx_verify.h>
#include <consensus/validation.h>
#include <policy/feerate.h>
#include <policy/policy.h>
#include <pow.h>
#include <primitives/transaction.h>
#include <timedata.h>
#include <util/system.h>
#include <util/moneystr.h>
#include <util/system.h>
#include <util/validation.h>
#include <evo/specialtx.h>
@ -33,14 +33,6 @@
#include <algorithm>
#include <utility>
// Unconfirmed transactions in the memory pool often depend on other
// transactions in the memory pool. When we select transactions from the
// pool, we select by highest fee rate of a transaction combined with all
// its ancestors.
uint64_t nLastBlockTx = 0;
uint64_t nLastBlockSize = 0;
int64_t UpdateTime(CBlockHeader* pblock, const Consensus::Params& consensusParams, const CBlockIndex* pindexPrev)
{
int64_t nOldTime = pblock->nTime;
@ -100,6 +92,9 @@ void BlockAssembler::resetBlock()
nFees = 0;
}
Optional<int64_t> BlockAssembler::m_last_block_num_txs{nullopt};
Optional<int64_t> BlockAssembler::m_last_block_size{nullopt};
std::unique_ptr<CBlockTemplate> BlockAssembler::CreateNewBlock(const CScript& scriptPubKeyIn)
{
int64_t nTimeStart = GetTimeMicros();
@ -160,8 +155,8 @@ std::unique_ptr<CBlockTemplate> BlockAssembler::CreateNewBlock(const CScript& sc
int64_t nTime1 = GetTimeMicros();
nLastBlockTx = nBlockTx;
nLastBlockSize = nBlockSize;
m_last_block_num_txs = nBlockTx;
m_last_block_size = nBlockSize;
LogPrintf("CreateNewBlock(): total size %u txs: %u fees: %ld sigops %d\n", nBlockSize, nBlockTx, nFees, nBlockSigOps);
// Create coinbase transaction.

View File

@ -1,17 +1,19 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2015 The Bitcoin Core developers
// 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_MINER_H
#define BITCOIN_MINER_H
#include <optional.h>
#include <primitives/block.h>
#include <txmempool.h>
#include <validation.h>
#include <stdint.h>
#include <memory>
#include <stdint.h>
#include <boost/multi_index_container.hpp>
#include <boost/multi_index/ordered_index.hpp>
@ -159,6 +161,9 @@ public:
/** Construct a new block template with coinbase to scriptPubKeyIn */
std::unique_ptr<CBlockTemplate> CreateNewBlock(const CScript& scriptPubKeyIn);
static Optional<int64_t> m_last_block_num_txs;
static Optional<int64_t> m_last_block_size;
private:
// utility functions
/** Clear the block's state and prepare for assembling a new block */

View File

@ -71,17 +71,6 @@ static constexpr int DNSSEEDS_TO_QUERY_AT_ONCE = 3;
#define MSG_DONTWAIT 0
#endif
// Fix for ancient MinGW versions, that don't have defined these in ws2tcpip.h.
// Todo: Can be removed when our pull-tester is upgraded to a modern MinGW version.
#ifdef WIN32
#ifndef PROTECTION_LEVEL_UNRESTRICTED
#define PROTECTION_LEVEL_UNRESTRICTED 10
#endif
#ifndef IPV6_PROTECTION_LEVEL
#define IPV6_PROTECTION_LEVEL 23
#endif
#endif
/** Used to pass flags to the Bind() function */
enum BindFlags {
BF_NONE = 0,

View File

@ -86,9 +86,6 @@ bool static LookupIntern(const char *pszName, std::vector<CNetAddr>& vIP, unsign
aiHint.ai_protocol = IPPROTO_TCP;
// We don't care which address family (IPv4 or IPv6) is returned
aiHint.ai_family = AF_UNSPEC;
#ifdef WIN32
aiHint.ai_flags = fAllowLookup ? 0 : AI_NUMERICHOST;
#else
// If we allow lookups of hostnames, use the AI_ADDRCONFIG flag to only
// return addresses whose family we have an address configured for.
//
@ -96,7 +93,6 @@ bool static LookupIntern(const char *pszName, std::vector<CNetAddr>& vIP, unsign
// getaddrinfo to only decode numerical network addresses and suppress
// hostname lookups.
aiHint.ai_flags = fAllowLookup ? AI_ADDRCONFIG : AI_NUMERICHOST;
#endif
struct addrinfo *aiRes = nullptr;
int nErr = getaddrinfo(pszName, nullptr, &aiHint, &aiRes);
if (nErr)

View File

@ -26,10 +26,6 @@
#include <util/system.h>
#ifdef WIN32
#ifdef _WIN32_WINNT
#undef _WIN32_WINNT
#endif
#define _WIN32_WINNT 0x0501
#ifdef _WIN32_IE
#undef _WIN32_IE
#endif

View File

@ -199,36 +199,36 @@ static UniValue generatetoaddress(const JSONRPCRequest& request)
static UniValue getmininginfo(const JSONRPCRequest& request)
{
if (request.fHelp || request.params.size() != 0)
if (request.fHelp || request.params.size() != 0) {
throw std::runtime_error(
RPCHelpMan{"getmininginfo",
"\nReturns a json object containing mining-related information.",
{},
RPCResult{
"{\n"
" \"blocks\": nnn, (numeric) The current block\n"
" \"currentblocksize\": nnn, (numeric) The last block size\n"
" \"currentblocktx\": nnn, (numeric) The last block transaction\n"
" \"difficulty\": xxx.xxxxx (numeric) The current difficulty\n"
" \"networkhashps\": nnn, (numeric) The network hashes per second\n"
" \"pooledtx\": n (numeric) The size of the mempool\n"
" \"chain\": \"xxxx\", (string) current network name as defined in BIP70 (main, test, regtest)\n"
" \"warnings\": \"...\" (string) any network and blockchain warnings\n"
"}\n"
"{\n"
" \"blocks\": nnn, (numeric) The current block\n"
" \"currentblocksize\": nnn, (numeric, optional) The block size of the last assembled block (only present if a block was ever assembled)\n"
" \"currentblocktx\": nnn, (numeric, optional) The number of block transactions of the last assembled block (only present if a block was ever assembled)\n"
" \"difficulty\": xxx.xxxxx (numeric) The current difficulty\n"
" \"networkhashps\": nnn, (numeric) The network hashes per second\n"
" \"pooledtx\": n (numeric) The size of the mempool\n"
" \"chain\": \"xxxx\", (string) current network name as defined in BIP70 (main, test, regtest)\n"
" \"warnings\": \"...\" (string) any network and blockchain warnings\n"
"}\n"
},
RPCExamples{
HelpExampleCli("getmininginfo", "")
+ HelpExampleRpc("getmininginfo", "")
},
}.ToString());
}
LOCK(cs_main);
UniValue obj(UniValue::VOBJ);
obj.pushKV("blocks", (int)::ChainActive().Height());
obj.pushKV("currentblocksize", (uint64_t)nLastBlockSize);
obj.pushKV("currentblocktx", (uint64_t)nLastBlockTx);
if (BlockAssembler::m_last_block_size) obj.pushKV("currentblocksize", *BlockAssembler::m_last_block_size);
if (BlockAssembler::m_last_block_num_txs) obj.pushKV("currentblocktx", *BlockAssembler::m_last_block_num_txs);
obj.pushKV("difficulty", (double)GetDifficulty(::ChainActive().Tip()));
obj.pushKV("networkhashps", getnetworkhashps(request));
obj.pushKV("pooledtx", (uint64_t)mempool.size());

View File

@ -113,13 +113,17 @@ static UniValue getrawtransaction(const JSONRPCRequest& request)
{
if (request.fHelp || request.params.size() < 1 || request.params.size() > 3)
throw std::runtime_error(
RPCHelpMan{"getrawtransaction",
RPCHelpMan{
"getrawtransaction",
"\nReturn the raw transaction data.\n"
"\nBy default this function only works for mempool transactions. When called with a blockhash\n"
"argument, getrawtransaction will return the transaction if the specified block is available and\n"
"the transaction is found in that block. When called without a blockhash argument, getrawtransaction\n"
"will return the transaction if it is in the mempool, or if -txindex is enabled and the transaction\n"
"is in a block in the blockchain.\n"
"\nReturn the raw transaction data.\n"
"\nHint: use getmempoolentry to fetch a specific transaction from the mempool.\n"
"Or use gettransaction for wallet transactions.\n"
"\nIf verbose is 'true', returns an Object with information about 'txid'.\n"
"If verbose is 'false' or omitted, returns a string that is serialized, hex-encoded data for 'txid'.\n",
{

View File

@ -10,10 +10,6 @@
#endif
#ifdef WIN32
#ifdef _WIN32_WINNT
#undef _WIN32_WINNT
#endif
#define _WIN32_WINNT 0x0501
#define WIN32_LEAN_AND_MEAN 1
#ifndef NOMINMAX
#define NOMINMAX

View File

@ -46,11 +46,6 @@
#pragma warning(disable:4717)
#endif
#ifdef _WIN32_WINNT
#undef _WIN32_WINNT
#endif
#define _WIN32_WINNT 0x0501
#ifdef _WIN32_IE
#undef _WIN32_IE
#endif

View File

@ -15,8 +15,8 @@
#include <coins.h>
#include <crypto/common.h> // for ReadLE64
#include <fs.h>
#include <protocol.h> // For CMessageHeader::MessageStartChars
#include <policy/feerate.h>
#include <protocol.h> // For CMessageHeader::MessageStartChars
#include <script/script_error.h>
#include <sync.h>
#include <txdb.h>
@ -123,8 +123,6 @@ extern CBlockPolicyEstimator feeEstimator;
extern CTxMemPool mempool;
typedef std::unordered_map<uint256, CBlockIndex*, BlockHasher> BlockMap;
typedef std::unordered_multimap<uint256, CBlockIndex*, BlockHasher> PrevBlockMap;
extern uint64_t nLastBlockTx;
extern uint64_t nLastBlockSize;
extern Mutex g_best_block_mutex;
extern std::condition_variable g_best_block_cv;
extern uint256 g_best_block;

View File

@ -1173,7 +1173,7 @@ static std::string RecurseImportData(const CScript& script, ImportData& import_d
}
}
static UniValue ProcessImportLegacy(ImportData& import_data, std::map<CKeyID, CPubKey>& pubkey_map, std::map<CKeyID, CKey>& privkey_map, std::set<CScript>& script_pub_keys, bool& have_solving_data, const UniValue& data)
static UniValue ProcessImportLegacy(ImportData& import_data, std::map<CKeyID, CPubKey>& pubkey_map, std::map<CKeyID, CKey>& privkey_map, std::set<CScript>& script_pub_keys, bool& have_solving_data, const UniValue& data, std::vector<CKeyID>& ordered_pubkeys)
{
UniValue warnings(UniValue::VARR);
@ -1236,6 +1236,7 @@ static UniValue ProcessImportLegacy(ImportData& import_data, std::map<CKeyID, CP
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Pubkey \"" + str + "\" is not a valid public key");
}
pubkey_map.emplace(pubkey.GetID(), pubkey);
ordered_pubkeys.push_back(pubkey.GetID());
}
for (size_t i = 0; i < keys.size(); ++i) {
const auto& str = keys[i].get_str();
@ -1307,7 +1308,7 @@ static UniValue ProcessImportLegacy(ImportData& import_data, std::map<CKeyID, CP
return warnings;
}
static UniValue ProcessImportDescriptor(ImportData& import_data, std::map<CKeyID, CPubKey>& pubkey_map, std::map<CKeyID, CKey>& privkey_map, std::set<CScript>& script_pub_keys, bool& have_solving_data, const UniValue& data)
static UniValue ProcessImportDescriptor(ImportData& import_data, std::map<CKeyID, CPubKey>& pubkey_map, std::map<CKeyID, CKey>& privkey_map, std::set<CScript>& script_pub_keys, bool& have_solving_data, const UniValue& data, std::vector<CKeyID>& ordered_pubkeys)
{
UniValue warnings(UniValue::VARR);
@ -1334,22 +1335,25 @@ static UniValue ProcessImportDescriptor(ImportData& import_data, std::map<CKeyID
const UniValue& priv_keys = data.exists("keys") ? data["keys"].get_array() : UniValue();
FlatSigningProvider out_keys;
// Expand all descriptors to get public keys and scripts.
// TODO: get private keys from descriptors too
for (int i = range_start; i <= range_end; ++i) {
FlatSigningProvider out_keys;
std::vector<CScript> scripts_temp;
parsed_desc->Expand(i, keys, scripts_temp, out_keys);
std::copy(scripts_temp.begin(), scripts_temp.end(), std::inserter(script_pub_keys, script_pub_keys.end()));
for (const auto& key_pair: out_keys.pubkeys) {
ordered_pubkeys.push_back(key_pair.first);
}
for (const auto& x: out_keys.scripts) {
import_data.import_scripts.emplace(x.second);
}
std::copy(out_keys.pubkeys.begin(), out_keys.pubkeys.end(), std::inserter(pubkey_map, pubkey_map.end()));
import_data.key_origins.insert(out_keys.origins.begin(), out_keys.origins.end());
}
for (const auto& x : out_keys.scripts) {
import_data.import_scripts.emplace(x.second);
}
std::copy(out_keys.pubkeys.begin(), out_keys.pubkeys.end(), std::inserter(pubkey_map, pubkey_map.end()));
import_data.key_origins.insert(out_keys.origins.begin(), out_keys.origins.end());
for (size_t i = 0; i < priv_keys.size(); ++i) {
const auto& str = priv_keys[i].get_str();
CKey key = DecodeSecret(str);
@ -1400,19 +1404,26 @@ static UniValue ProcessImport(CWallet * const pwallet, const UniValue& data, con
throw JSONRPCError(RPC_INVALID_PARAMETER, "Internal addresses should not have a label");
}
const std::string& label = data.exists("label") ? data["label"].get_str() : "";
const bool add_keypool = data.exists("keypool") ? data["keypool"].get_bool() : false;
// Add to keypool only works with privkeys disabled
if (add_keypool && !pwallet->IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS)) {
throw JSONRPCError(RPC_INVALID_PARAMETER, "Keys can only be imported to the keypool when private keys are disabled");
}
ImportData import_data;
std::map<CKeyID, CPubKey> pubkey_map;
std::map<CKeyID, CKey> privkey_map;
std::set<CScript> script_pub_keys;
std::vector<CKeyID> ordered_pubkeys;
bool have_solving_data;
if (data.exists("scriptPubKey") && data.exists("desc")) {
throw JSONRPCError(RPC_INVALID_PARAMETER, "Both a descriptor and a scriptPubKey should not be provided.");
} else if (data.exists("scriptPubKey")) {
warnings = ProcessImportLegacy(import_data, pubkey_map, privkey_map, script_pub_keys, have_solving_data, data);
warnings = ProcessImportLegacy(import_data, pubkey_map, privkey_map, script_pub_keys, have_solving_data, data, ordered_pubkeys);
} else if (data.exists("desc")) {
warnings = ProcessImportDescriptor(import_data, pubkey_map, privkey_map, script_pub_keys, have_solving_data, data);
warnings = ProcessImportDescriptor(import_data, pubkey_map, privkey_map, script_pub_keys, have_solving_data, data, ordered_pubkeys);
} else {
throw JSONRPCError(RPC_INVALID_PARAMETER, "Either a descriptor or scriptPubKey must be provided.");
}
@ -1437,7 +1448,7 @@ static UniValue ProcessImport(CWallet * const pwallet, const UniValue& data, con
if (!pwallet->ImportPrivKeys(privkey_map, timestamp)) {
throw JSONRPCError(RPC_WALLET_ERROR, "Error adding key to wallet");
}
if (!pwallet->ImportPubKeys(pubkey_map, timestamp, import_data.key_origins)) {
if (!pwallet->ImportPubKeys(ordered_pubkeys, pubkey_map, import_data.key_origins, add_keypool, internal, timestamp)) {
throw JSONRPCError(RPC_WALLET_ERROR, "Error adding address to wallet");
}
if (!pwallet->ImportScriptPubKeys(label, script_pub_keys, have_solving_data, internal, timestamp)) {

View File

@ -168,11 +168,6 @@ UniValue getnewaddress(const JSONRPCRequest& request)
},
}.ToString());
// Belt and suspenders check for disabled private keys
if (pwallet->IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS)) {
throw JSONRPCError(RPC_WALLET_ERROR, "Error: Private keys are disabled for this wallet");
}
LOCK(pwallet->cs_wallet);
if (!pwallet->CanGetAddresses()) {
@ -224,11 +219,6 @@ static UniValue getrawchangeaddress(const JSONRPCRequest& request)
},
}.ToString());
// Belt and suspenders check for disabled private keys
if (pwallet->IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS)) {
throw JSONRPCError(RPC_WALLET_ERROR, "Error: Private keys are disabled for this wallet");
}
LOCK(pwallet->cs_wallet);
if (!pwallet->CanGetAddresses(true)) {
@ -2591,9 +2581,7 @@ static UniValue getwalletinfo(const JSONRPCRequest& request)
obj.pushKV("timefirstkey", pwallet->GetTimeFirstKey());
obj.pushKV("keypoololdest", pwallet->GetOldestKeyPoolTime());
obj.pushKV("keypoolsize", (int64_t)pwallet->KeypoolCountExternalKeys());
if (fHDEnabled) {
obj.pushKV("keypoolsize_hd_internal", (int64_t)(pwallet->KeypoolCountInternalKeys()));
}
obj.pushKV("keypoolsize_hd_internal", (int64_t)(pwallet->KeypoolCountInternalKeys()));
obj.pushKV("keys_left", pwallet->nKeysLeftSinceAutoBackup);
if (pwallet->IsCrypted())
obj.pushKV("unlocked_until", pwallet->nRelockTime);

View File

@ -2121,17 +2121,25 @@ bool CWallet::ImportPrivKeys(const std::map<CKeyID, CKey>& privkey_map, const in
return true;
}
bool CWallet::ImportPubKeys(const std::map<CKeyID, CPubKey>& pubkey_map, const int64_t timestamp, const std::map<CKeyID, std::pair<CPubKey, KeyOriginInfo>>& key_origins)
bool CWallet::ImportPubKeys(const std::vector<CKeyID>& ordered_pubkeys, const std::map<CKeyID, CPubKey>& pubkey_map, const std::map<CKeyID, std::pair<CPubKey, KeyOriginInfo>>& key_origins, const bool add_keypool, const bool internal, const int64_t timestamp)
{
WalletBatch batch(*database);
for (const auto& entry : pubkey_map) {
const CKeyID& id = entry.first;
const CPubKey& pubkey = entry.second;
for (const CKeyID& id : ordered_pubkeys) {
auto entry = pubkey_map.find(id);
if (entry == pubkey_map.end()) {
continue;
}
const CPubKey& pubkey = entry->second;
CPubKey temp;
if (!GetPubKey(id, temp) && !AddWatchOnlyWithDB(batch, GetScriptForRawPubKey(pubkey), timestamp)) {
return false;
}
mapKeyMetadata[id].nCreateTime = timestamp;
// Add to keypool only works with pubkeys
if (add_keypool) {
AddKeypoolPubkeyWithDB(pubkey, internal, batch);
NotifyCanGetAddressesChanged();
}
}
for (const auto& entry : key_origins) {
AddKeyOrigin(entry.second.first, entry.second.second);
@ -3659,8 +3667,8 @@ bool CWallet::CreateTransaction(interfaces::Chain::Lock& locked_chain, const std
// post-backup change.
// Reserve a new key pair from key pool
if (IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS)) {
strFailReason = _("Can't generate a change-address key. Private keys are disabled for this wallet.");
if (!CanGetAddresses(true)) {
strFailReason = _("Can't generate a change-address key. No keys in the internal keypool and can't generate any keys.");
return false;
}
CPubKey vchPubKey;
@ -4314,29 +4322,17 @@ bool CWallet::TopUpKeyPool(unsigned int kpSize)
fInternal = true;
}
assert(m_max_keypool_index < std::numeric_limits<int64_t>::max()); // How in the hell did you use so many keys?
int64_t index = ++m_max_keypool_index;
// TODO: implement keypools for all accounts?
CPubKey pubkey(GenerateNewKey(batch, 0, fInternal));
if (!batch.WritePool(index, CKeyPool(pubkey, fInternal))) {
throw std::runtime_error(std::string(__func__) + ": writing generated key failed");
}
AddKeypoolPubkeyWithDB(pubkey, fInternal, batch);
if (fInternal) {
setInternalKeyPool.insert(index);
} else {
setExternalKeyPool.insert(index);
}
m_pool_key_to_index[pubkey.GetID()] = index;
if (missingInternal + missingExternal > 0) {
WalletLogPrintf("keypool added %d keys (%d internal), size=%u (%u internal)\n",
missingInternal + missingExternal, missingInternal,
setInternalKeyPool.size() + setExternalKeyPool.size(), setInternalKeyPool.size());
}
double dProgress = 100.f * index / (nTargetSize + 1);
double dProgress = 100.f * m_max_keypool_index / (nTargetSize + 1);
std::string strMsg = strprintf(_("Loading wallet... (%3.2f %%)"), dProgress);
uiInterface.InitMessage(strMsg);
}
@ -4345,6 +4341,29 @@ bool CWallet::TopUpKeyPool(unsigned int kpSize)
return true;
}
void CWallet::AddKeypoolPubkey(const CPubKey& pubkey, const bool internal)
{
WalletBatch batch(*database);
AddKeypoolPubkeyWithDB(pubkey, internal, batch);
NotifyCanGetAddressesChanged();
}
void CWallet::AddKeypoolPubkeyWithDB(const CPubKey& pubkey, const bool internal, WalletBatch& batch)
{
LOCK(cs_wallet);
assert(m_max_keypool_index < std::numeric_limits<int64_t>::max()); // How in the hell did you use so many keys?
int64_t index = ++m_max_keypool_index;
if (!batch.WritePool(index, CKeyPool(pubkey, internal))) {
throw std::runtime_error(std::string(__func__) + ": writing imported pubkey failed");
}
if (internal) {
setInternalKeyPool.insert(index);
} else {
setExternalKeyPool.insert(index);
}
m_pool_key_to_index[pubkey.GetID()] = index;
}
bool CWallet::ReserveKeyFromKeyPool(int64_t& nIndex, CKeyPool& keypool, bool fRequestedInternal)
{
nIndex = -1;
@ -4354,7 +4373,8 @@ bool CWallet::ReserveKeyFromKeyPool(int64_t& nIndex, CKeyPool& keypool, bool fRe
TopUpKeyPool();
bool fReturningInternal = IsHDEnabled() && fRequestedInternal;
bool fReturningInternal = fRequestedInternal;
fReturningInternal &= IsHDEnabled() || IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS);
std::set<int64_t>& setKeyPool = fReturningInternal ? setInternalKeyPool : setExternalKeyPool;
// Get the oldest key
@ -4369,7 +4389,8 @@ bool CWallet::ReserveKeyFromKeyPool(int64_t& nIndex, CKeyPool& keypool, bool fRe
if (!batch.ReadPool(nIndex, keypool)) {
throw std::runtime_error(std::string(__func__) + ": read failed");
}
if (!HaveKey(keypool.vchPubKey.GetID())) {
CPubKey pk;
if (!GetPubKey(keypool.vchPubKey.GetID(), pk)) {
throw std::runtime_error(std::string(__func__) + ": unknown key in key pool");
}
if (keypool.fInternal != fReturningInternal) {
@ -4426,10 +4447,9 @@ bool CWallet::GetKeyFromPool(CPubKey& result, bool internal)
{
LOCK(cs_wallet);
int64_t nIndex;
if (!ReserveKeyFromKeyPool(nIndex, keypool, internal)) {
if (!ReserveKeyFromKeyPool(nIndex, keypool, internal) && !IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS)) {
if (IsLocked(true)) return false;
// TODO: implement keypool for all accouts?
WalletBatch batch(*database);
result = GenerateNewKey(batch, 0, internal);
return true;

View File

@ -1007,7 +1007,7 @@ public:
bool ImportScripts(const std::set<CScript> scripts) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
bool ImportPrivKeys(const std::map<CKeyID, CKey>& privkey_map, const int64_t timestamp) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
bool ImportPubKeys(const std::map<CKeyID, CPubKey>& pubkey_map, const int64_t timestamp, const std::map<CKeyID, std::pair<CPubKey, KeyOriginInfo>>& key_origins) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
bool ImportPubKeys(const std::vector<CKeyID>& ordered_pubkeys, const std::map<CKeyID, CPubKey>& pubkey_map, const std::map<CKeyID, std::pair<CPubKey, KeyOriginInfo>>& key_origins, const bool add_keypool, const bool internal, const int64_t timestamp) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
bool ImportScriptPubKeys(const std::string& label, const std::set<CScript>& script_pub_keys, const bool have_solving_data, const bool internal, const int64_t timestamp) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
CFeeRate m_pay_tx_fee{DEFAULT_PAY_TX_FEE};
@ -1029,6 +1029,8 @@ public:
size_t KeypoolCountExternalKeys() EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
size_t KeypoolCountInternalKeys() EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
bool TopUpKeyPool(unsigned int kpSize = 0);
void AddKeypoolPubkey(const CPubKey& pubkey, const bool internal);
void AddKeypoolPubkeyWithDB(const CPubKey& pubkey, const bool internal, WalletBatch& batch);
/**
* Reserves a key from the keypool and sets nIndex to its index

View File

@ -46,7 +46,7 @@ from decimal import Decimal
from itertools import product
from io import BytesIO
from test_framework.blocktools import create_coinbase, create_block, create_transaction
from test_framework.blocktools import create_coinbase, create_block, create_transaction, TIME_GENESIS_BLOCK
from test_framework.messages import ToHex, CTransaction
from test_framework.mininode import P2PDataStore
from test_framework.script import (
@ -54,7 +54,7 @@ from test_framework.script import (
OP_CHECKSEQUENCEVERIFY,
OP_DROP,
)
from test_framework.test_framework import (BitcoinTestFramework, GENESISTIME)
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import (
assert_equal,
get_bip9_status,
@ -186,9 +186,9 @@ class BIP68_112_113Test(BitcoinTestFramework):
self.coinbase_blocks = self.nodes[0].generate(1 + 16 + 2 * 32 + 1) # 82 blocks generated for inputs
# set time so that there was enough time to build up to 1000 blocks 10 minutes apart on top of the last one
# without worrying about getting into the future
self.nodes[0].setmocktime(GENESISTIME + 600 * 1000 + 100)
self.nodes[0].setmocktime(TIME_GENESIS_BLOCK + 600 * 1000 + 100)
self.tipheight = 82 # height of the next block to build
self.last_block_time = GENESISTIME
self.last_block_time = TIME_GENESIS_BLOCK
self.tip = int(self.nodes[0].getbestblockhash(), 16)
self.nodeaddress = self.nodes[0].getnewaddress()
@ -261,7 +261,7 @@ class BIP68_112_113Test(BitcoinTestFramework):
self.nodes[0].setmocktime(self.last_block_time + 600)
inputblockhash = self.nodes[0].generate(1)[0] # 1 block generated for inputs to be in chain at height 572
self.nodes[0].setmocktime(GENESISTIME + 600 * 1000 + 100)
self.nodes[0].setmocktime(TIME_GENESIS_BLOCK + 600 * 1000 + 100)
self.tip = int(inputblockhash, 16)
self.tipheight += 1
self.last_block_time += 600

View File

@ -1,5 +1,5 @@
#!/usr/bin/env python3
# Copyright (c) 2014-2016 The Bitcoin Core developers
# Copyright (c) 2014-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.
"""Test mining RPCs
@ -11,7 +11,9 @@
import copy
from decimal import Decimal
from test_framework.blocktools import create_coinbase
from test_framework.blocktools import (
create_coinbase,
)
from test_framework.messages import (
CBlock,
CBlockHeader,
@ -23,6 +25,7 @@ from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import (
assert_equal,
assert_raises_rpc_error,
connect_nodes,
)
from test_framework.script import CScriptNum
@ -37,9 +40,23 @@ def assert_template(node, block, expect, rehash=True):
class MiningTest(BitcoinTestFramework):
def set_test_params(self):
self.num_nodes = 2
self.setup_clean_chain = False
self.setup_clean_chain = True
def mine_chain(self):
self.log.info('Create some old blocks')
for _ in range(0, 200):
self.bump_mocktime(156)
self.nodes[0].generate(1)
mining_info = self.nodes[0].getmininginfo()
assert_equal(mining_info['blocks'], 200)
assert_equal(mining_info['currentblocktx'], 0)
assert_equal(mining_info['currentblocksize'], 1000)
self.restart_node(0)
connect_nodes(self.nodes[0], 1)
connect_nodes(self.nodes[1], 0)
def run_test(self):
self.mine_chain()
node = self.nodes[0]
def assert_submitblock(block, result_str_1, result_str_2=None):
@ -52,8 +69,8 @@ class MiningTest(BitcoinTestFramework):
mining_info = node.getmininginfo()
assert_equal(mining_info['blocks'], 200)
assert_equal(mining_info['chain'], self.chain)
assert_equal(mining_info['currentblocksize'], 0)
assert_equal(mining_info['currentblocktx'], 0)
assert 'currentblocksize' not in mining_info
assert 'currentblocktx' not in mining_info
assert_equal(mining_info['difficulty'], Decimal('4.656542373906925E-10'))
assert_equal(mining_info['networkhashps'], Decimal('0.01282051282051282'))
assert_equal(mining_info['pooledtx'], 0)

View File

@ -1,5 +1,5 @@
#!/usr/bin/env python3
# Copyright (c) 2015-2016 The Bitcoin Core developers
# Copyright (c) 2015-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.
"""Utilities for manipulating blocks and transactions."""
@ -19,6 +19,9 @@ from io import BytesIO
MAX_BLOCK_SIGOPS = 20000
# Genesis block time (regtest)
TIME_GENESIS_BLOCK = 1417713337
def create_block(hashprev, coinbase, ntime=None):
"""Create a block (with regtest difficulty)."""
block = CBlock()

View File

@ -20,6 +20,7 @@ import time
from concurrent.futures import ThreadPoolExecutor
from .authproxy import JSONRPCException
from test_framework.blocktools import TIME_GENESIS_BLOCK
from . import coverage
from .messages import (
CTransaction,
@ -63,7 +64,6 @@ TEST_EXIT_PASSED = 0
TEST_EXIT_FAILED = 1
TEST_EXIT_SKIPPED = 77
GENESISTIME = 1417713337
TMPDIR_PREFIX = "dash_func_test_"
class SkipTest(Exception):
@ -400,6 +400,7 @@ class BitcoinTestFramework(metaclass=BitcoinTestMetaClass):
bitcoin_cli=self.options.bitcoincli,
mocktime=self.mocktime,
coverage_dir=self.options.coveragedir,
cwd=self.options.tmpdir,
extra_conf=extra_confs[i],
extra_args=extra_args[i],
use_cli=self.options.usecli,
@ -506,12 +507,12 @@ class BitcoinTestFramework(metaclass=BitcoinTestMetaClass):
# For backwared compatibility of the python scripts
# with previous versions of the cache, set MOCKTIME
# to regtest genesis time + (201 * 156)
self.mocktime = GENESISTIME + (201 * 156)
self.mocktime = TIME_GENESIS_BLOCK + (201 * 156)
for node in self.nodes:
node.mocktime = self.mocktime
def set_genesis_mocktime(self):
self.mocktime = GENESISTIME
self.mocktime = TIME_GENESIS_BLOCK
for node in self.nodes:
node.mocktime = self.mocktime
@ -570,7 +571,7 @@ class BitcoinTestFramework(metaclass=BitcoinTestMetaClass):
self.set_genesis_mocktime()
for i in range(MAX_NODES):
datadir = initialize_datadir(self.options.cachedir, i, self.chain)
args = [self.options.bitcoind, "-datadir=" + datadir, "-mocktime="+str(GENESISTIME), '-disablewallet']
args = [self.options.bitcoind, "-datadir=" + datadir, "-mocktime="+str(TIME_GENESIS_BLOCK), '-disablewallet']
if i > 0:
args.append("-connect=127.0.0.1:" + str(p2p_port(0)))
if extra_args is not None:
@ -581,6 +582,7 @@ class BitcoinTestFramework(metaclass=BitcoinTestMetaClass):
bitcoin_cli=self.options.bitcoincli,
mocktime=self.mocktime,
coverage_dir=None,
cwd=self.options.tmpdir,
))
self.nodes[i].args = args
self.start_node(i)
@ -596,7 +598,7 @@ class BitcoinTestFramework(metaclass=BitcoinTestMetaClass):
#
# blocks are created with timestamps 10 minutes apart
# starting from 2010 minutes in the past
block_time = GENESISTIME
block_time = TIME_GENESIS_BLOCK
for i in range(2):
for peer in range(4):
for j in range(25):

View File

@ -60,7 +60,7 @@ class TestNode():
To make things easier for the test writer, any unrecognised messages will
be dispatched to the RPC connection."""
def __init__(self, i, datadir, extra_args_from_options, *, chain, rpchost, timewait, bitcoind, bitcoin_cli, mocktime, coverage_dir, extra_conf=None, extra_args=None, use_cli=False, start_perf=False):
def __init__(self, i, datadir, extra_args_from_options, *, chain, rpchost, timewait, bitcoind, bitcoin_cli, mocktime, coverage_dir, cwd, extra_conf=None, extra_args=None, use_cli=False, start_perf=False):
"""
Kwargs:
start_perf (bool): If True, begin profiling the node with `perf` as soon as
@ -78,6 +78,7 @@ class TestNode():
self.rpc_timeout *= Options.timeout_scale
self.binary = bitcoind
self.coverage_dir = coverage_dir
self.cwd = cwd
self.mocktime = mocktime
if extra_conf is not None:
append_config(datadir, extra_conf)
@ -185,7 +186,7 @@ class TestNode():
assert self.rpc_connected and self.rpc is not None, self._node_msg("Error: no RPC connection")
return getattr(self.rpc, name)
def start(self, extra_args=None, *, stdout=None, stderr=None, **kwargs):
def start(self, extra_args=None, *, cwd=None, stdout=None, stderr=None, **kwargs):
"""Start the node."""
if extra_args is None:
extra_args = self.extra_args
@ -198,6 +199,9 @@ class TestNode():
self.stderr = stderr
self.stdout = stdout
if cwd is None:
cwd = self.cwd
all_args = self.args + self.extra_args_from_options + extra_args
if self.mocktime != 0:
all_args = all_args + ["-mocktime=%d" % self.mocktime]
@ -210,7 +214,7 @@ class TestNode():
# add environment variable LIBC_FATAL_STDERR_=1 so that libc errors are written to stderr and not the terminal
subp_env = dict(os.environ, LIBC_FATAL_STDERR_="1")
self.process = subprocess.Popen(all_args, env=subp_env, stdout=stdout, stderr=stderr, **kwargs)
self.process = subprocess.Popen(all_args, env=subp_env, stdout=stdout, stderr=stderr, cwd=cwd, **kwargs)
self.running = True
self.log.debug("dashd started, waiting for RPC to come up")

View File

@ -31,8 +31,8 @@ class CreateWalletTest(BitcoinTestFramework):
self.log.info("Test disableprivatekeys creation.")
self.nodes[0].createwallet(wallet_name='w1', disable_private_keys=True)
w1 = node.get_wallet_rpc('w1')
assert_raises_rpc_error(-4, "Error: Private keys are disabled for this wallet", w1.getnewaddress)
assert_raises_rpc_error(-4, "Error: Private keys are disabled for this wallet", w1.getrawchangeaddress)
assert_raises_rpc_error(-4, "Error: This wallet has no available keys", w1.getnewaddress)
assert_raises_rpc_error(-4, "Error: This wallet has no available keys", w1.getrawchangeaddress)
w1.importpubkey(w0.getaddressinfo(address1)['pubkey'])
self.log.info('Test that private keys cannot be imported')
@ -48,8 +48,8 @@ class CreateWalletTest(BitcoinTestFramework):
self.log.info("Test blank creation with private keys disabled.")
self.nodes[0].createwallet(wallet_name='w2', disable_private_keys=True, blank=True)
w2 = node.get_wallet_rpc('w2')
assert_raises_rpc_error(-4, "Error: Private keys are disabled for this wallet", w2.getnewaddress)
assert_raises_rpc_error(-4, "Error: Private keys are disabled for this wallet", w2.getrawchangeaddress)
assert_raises_rpc_error(-4, "Error: This wallet has no available keys", w2.getnewaddress)
assert_raises_rpc_error(-4, "Error: This wallet has no available keys", w2.getrawchangeaddress)
w2.importpubkey(w0.getaddressinfo(address1)['pubkey'])
self.log.info("Test blank creation with private keys enabled.")
@ -89,12 +89,12 @@ class CreateWalletTest(BitcoinTestFramework):
self.nodes[0].createwallet(wallet_name='w5', disable_private_keys=True, blank=True)
w5 = node.get_wallet_rpc('w5')
assert_equal(w5.getwalletinfo()['keypoolsize'], 0)
assert_raises_rpc_error(-4, "Error: Private keys are disabled for this wallet", w5.getnewaddress)
assert_raises_rpc_error(-4, "Error: Private keys are disabled for this wallet", w5.getrawchangeaddress)
assert_raises_rpc_error(-4, "Error: This wallet has no available keys", w5.getnewaddress)
assert_raises_rpc_error(-4, "Error: This wallet has no available keys", w5.getrawchangeaddress)
# Encrypt the wallet
assert_raises_rpc_error(-16, "Error: wallet does not contain private keys, nothing to encrypt.", w5.encryptwallet, 'pass')
assert_raises_rpc_error(-4, "Error: Private keys are disabled for this wallet", w5.getnewaddress)
assert_raises_rpc_error(-4, "Error: Private keys are disabled for this wallet", w5.getrawchangeaddress)
assert_raises_rpc_error(-4, "Error: This wallet has no available keys", w5.getnewaddress)
assert_raises_rpc_error(-4, "Error: This wallet has no available keys", w5.getrawchangeaddress)
self.log.info('New blank and encrypted wallets can be created')
self.nodes[0].createwallet(wallet_name='wblank', disable_private_keys=False, blank=True, passphrase='thisisapassphrase')

View File

@ -78,7 +78,6 @@ def read_dump(file_name, addrs, script_addrs, hd_master_addr_old):
class WalletDumpTest(BitcoinTestFramework):
def set_test_params(self):
self.setup_clean_chain = True
self.num_nodes = 1
self.extra_args = [["-keypool=90", "-usehd=1"]]
self.rpc_timeout = 120
@ -87,12 +86,6 @@ class WalletDumpTest(BitcoinTestFramework):
self.skip_if_no_wallet()
def setup_network(self):
# TODO remove this when usehd=1 becomes the default
# use our own cache and -usehd=1 as extra arg as the default cache is run with -usehd=0
self.options.tmpdir = os.path.join(self.options.tmpdir, 'hd')
self.options.cachedir = os.path.join(self.options.cachedir, 'hd')
self._initialize_chain(extra_args=self.extra_args[0])
self.set_cache_mocktime()
self.add_nodes(self.num_nodes, extra_args=self.extra_args)
self.start_nodes()

View File

@ -633,5 +633,118 @@ class ImportMultiTest(BitcoinTestFramework):
assert 'hdmasterfingerprint' not in pub_import_info
assert 'hdkeypath' not in pub_import_info
# Import some public keys to the keypool of a no privkey wallet
self.log.info("Adding pubkey to keypool of disableprivkey wallet")
self.nodes[1].createwallet(wallet_name="noprivkeys", disable_private_keys=True)
wrpc = self.nodes[1].get_wallet_rpc("noprivkeys")
addr1 = self.nodes[0].getnewaddress()
addr2 = self.nodes[0].getnewaddress()
pub1 = self.nodes[0].getaddressinfo(addr1)['pubkey']
pub2 = self.nodes[0].getaddressinfo(addr2)['pubkey']
result = wrpc.importmulti(
[{
'desc': descsum_create('pkh(' + pub1 + ')'),
'keypool': True,
"timestamp": "now",
},
{
'desc': descsum_create('pkh(' + pub2 + ')'),
'keypool': True,
"timestamp": "now",
}]
)
assert result[0]['success']
assert result[1]['success']
assert_equal(wrpc.getwalletinfo()["keypoolsize"], 2)
newaddr1 = wrpc.getnewaddress()
assert_equal(addr1, newaddr1)
newaddr2 = wrpc.getnewaddress()
assert_equal(addr2, newaddr2)
# Import some public keys to the internal keypool of a no privkey wallet
self.log.info("Adding pubkey to internal keypool of disableprivkey wallet")
addr1 = self.nodes[0].getnewaddress()
addr2 = self.nodes[0].getnewaddress()
pub1 = self.nodes[0].getaddressinfo(addr1)['pubkey']
pub2 = self.nodes[0].getaddressinfo(addr2)['pubkey']
result = wrpc.importmulti(
[{
'desc': descsum_create('pkh(' + pub1 + ')'),
'keypool': True,
'internal': True,
"timestamp": "now",
},
{
'desc': descsum_create('pkh(' + pub2 + ')'),
'keypool': True,
'internal': True,
"timestamp": "now",
}]
)
assert result[0]['success']
assert result[1]['success']
assert_equal(wrpc.getwalletinfo()["keypoolsize_hd_internal"], 2)
newaddr1 = wrpc.getrawchangeaddress()
assert_equal(addr1, newaddr1)
newaddr2 = wrpc.getrawchangeaddress()
assert_equal(addr2, newaddr2)
# Import a multisig and make sure the keys don't go into the keypool
self.log.info('Imported scripts with pubkeys shoud not have their pubkeys go into the keypool')
addr1 = self.nodes[0].getnewaddress()
addr2 = self.nodes[0].getnewaddress()
pub1 = self.nodes[0].getaddressinfo(addr1)['pubkey']
pub2 = self.nodes[0].getaddressinfo(addr2)['pubkey']
result = wrpc.importmulti(
[{
'desc': descsum_create('sh(multi(2,' + pub1 + ',' + pub2 + '))'),
'keypool': True,
"timestamp": "now",
}]
)
assert result[0]['success']
assert_equal(wrpc.getwalletinfo()["keypoolsize"], 0)
# Cannot import those pubkeys to keypool of wallet with privkeys
self.log.info("Pubkeys cannot be added to the keypool of a wallet with private keys")
wrpc = self.nodes[1].get_wallet_rpc("")
assert wrpc.getwalletinfo()['private_keys_enabled']
result = wrpc.importmulti(
[{
'desc': descsum_create('pkh(' + pub1 + ')'),
'keypool': True,
"timestamp": "now",
}]
)
assert_equal(result[0]['error']['code'], -8)
assert_equal(result[0]['error']['message'], "Keys can only be imported to the keypool when private keys are disabled")
# Make sure ranged imports import keys in order
self.log.info('Key ranges should be imported in order')
wrpc = self.nodes[1].get_wallet_rpc("noprivkeys")
assert_equal(wrpc.getwalletinfo()["keypoolsize"], 0)
assert_equal(wrpc.getwalletinfo()["private_keys_enabled"], False)
xpub = "tpubDAXcJ7s7ZwicqjprRaEWdPoHKrCS215qxGYxpusRLLmJuT69ZSicuGdSfyvyKpvUNYBW1s2U3NSrT6vrCYB9e6nZUEvrqnwXPF8ArTCRXMY"
addresses = [
'yUxX4qnzWntXhEGrYB92v7ez4EZBnUjB1y', # m/0'/0'/0
'yRhTPsPd2qYgYbFFCqY2nuPHJQBjTnMQxg', # m/0'/0'/1
'yUyn3UV9rBdWfw6yJJ6eAoKuzDJ8RVLP1o', # m/0'/0'/2
'yi8GEkfLBgK85wGmBFsMFdSbEvPPNCSnVx', # m/0'/0'/3
'yYB4whdY8APWoCez6ryNdMBrrDjwzFbqMi', # m/0'/0'/4
]
result = wrpc.importmulti(
[{
'desc': descsum_create('pkh([80002067/0h/0h]' + xpub + '/*)'),
'keypool': True,
'timestamp': 'now',
'range' : [0, 4],
}]
)
for i in range(0, 5):
addr = wrpc.getnewaddress('')
assert_equal(addr, addresses[i])
if __name__ == '__main__':
ImportMultiTest().main()