16 #include <test/util/logging.h>
17 #include <test/util/setup_common.h>
20 #include <validation.h>
24 #include <boost/test/unit_test.hpp>
43 std::vector<bilingual_str> warnings;
46 wallet->postInitProcess();
50 static void TestUnloadWallet(std::shared_ptr<CWallet>&& wallet)
53 wallet->m_chain_notifications_handler.reset();
64 std::map<COutPoint, Coin> coins;
65 coins[mtx.
vin[0].prevout].out = from.
vout[index];
66 std::map<int, std::string> input_errors;
71 static void AddKey(
CWallet& wallet,
const CKey& key)
75 spk_man->AddKeyPubKey(key, key.GetPubKey());
78 BOOST_FIXTURE_TEST_CASE(scan_for_wallet_transactions, TestChain100Setup)
96 AddKey(wallet, coinbaseKey);
115 AddKey(wallet, coinbaseKey);
141 AddKey(wallet, coinbaseKey);
166 AddKey(wallet, coinbaseKey);
178 BOOST_FIXTURE_TEST_CASE(importmulti_rescan, TestChain100Setup)
209 key.
pushKV(
"timestamp", 0);
215 futureKey.MakeNewKey(
true);
222 request.params.setArray();
223 request.params.push_back(keys);
227 strprintf(
"[{\"success\":false,\"error\":{\"code\":-1,\"message\":\"Rescan failed for key with creation "
228 "timestamp %d. There was an error reading a block from time %d, which is after or within %d "
229 "seconds of key creation, and could contain transactions pertaining to the key. As a result, "
230 "transactions and coins using this key may not appear in the wallet. This error could be caused "
231 "by pruning or data corruption (see bitcoind log for details) and could be dealt with by "
232 "downloading and rescanning the relevant blocks (see -reindex and -rescan "
233 "options).\"}},{\"success\":true}]",
243 BOOST_FIXTURE_TEST_CASE(importwallet_rescan, TestChain100Setup)
249 m_coinbase_txns.emplace_back(CreateAndProcessBlock({},
GetScriptForRawPubKey(coinbaseKey.GetPubKey())).vtx[0]);
250 m_coinbase_txns.emplace_back(CreateAndProcessBlock({},
GetScriptForRawPubKey(coinbaseKey.GetPubKey())).vtx[0]);
256 m_coinbase_txns.emplace_back(CreateAndProcessBlock({},
GetScriptForRawPubKey(coinbaseKey.GetPubKey())).vtx[0]);
261 std::string backup_file = (
GetDataDir() /
"wallet.backup").
string();
267 auto spk_man = wallet->GetOrCreateLegacyScriptPubKeyMan();
268 LOCK2(wallet->cs_wallet, spk_man->cs_KeyStore);
269 spk_man->mapKeyMetadata[coinbaseKey.GetPubKey().GetID()].nCreateTime = KEY_TIME;
270 spk_man->AddKeyPubKey(coinbaseKey, coinbaseKey.GetPubKey());
277 request.params.setArray();
278 request.params.push_back(backup_file);
288 LOCK(wallet->cs_wallet);
289 wallet->SetupLegacyScriptPubKeyMan();
293 request.params.setArray();
294 request.params.push_back(backup_file);
302 for (
size_t i = 0; i < m_coinbase_txns.size(); ++i) {
303 bool found = wallet->GetWalletTx(m_coinbase_txns[i]->GetHash());
304 bool expected = i >= 100;
318 BOOST_FIXTURE_TEST_CASE(coin_mark_dirty_immature_credit, TestChain100Setup)
325 CWalletTx wtx(&wallet, m_coinbase_txns.back());
327 LOCK2(wallet.cs_wallet, spk_man->cs_KeyStore);
331 wtx.m_confirm = confirm;
340 BOOST_CHECK(spk_man->AddKeyPubKey(coinbaseKey, coinbaseKey.GetPubKey()));
354 assert(inserted.second);
355 const uint256& hash = inserted.first->first;
356 block = inserted.first->second;
357 block->
nTime = blockTime;
359 confirm = {CWalletTx::Status::CONFIRMED, block->
nHeight, hash, 0};
403 m_wallet.AddDestData(batch, dest,
"misc",
"val_misc");
404 m_wallet.AddDestData(batch, dest,
"rr0",
"val_rr0");
405 m_wallet.AddDestData(batch, dest,
"rr1",
"val_rr1");
407 auto values =
m_wallet.GetDestValues(
"rr");
420 CKeyID add_address = add_pubkey.GetID();
430 bool is_pubkey_fully_valid = add_pubkey.IsFullyValid();
431 if (is_pubkey_fully_valid) {
442 if (is_pubkey_fully_valid) {
449 static void PollutePubKey(
CPubKey& pubkey)
451 std::vector<unsigned char> pubkey_raw(pubkey.begin(), pubkey.end());
452 std::fill(pubkey_raw.begin()+1, pubkey_raw.end(), 0);
454 assert(!pubkey.IsFullyValid());
455 assert(pubkey.IsValid());
468 key.MakeNewKey(
false);
469 pubkey = key.GetPubKey();
470 assert(!pubkey.IsCompressed());
471 TestWatchOnlyPubKey(spk_man, pubkey);
474 PollutePubKey(pubkey);
475 TestWatchOnlyPubKey(spk_man, pubkey);
478 key.MakeNewKey(
true);
479 pubkey = key.GetPubKey();
480 assert(pubkey.IsCompressed());
481 TestWatchOnlyPubKey(spk_man, pubkey);
484 PollutePubKey(pubkey);
485 TestWatchOnlyPubKey(spk_man, pubkey);
489 TestWatchOnlyPubKey(spk_man, pubkey);
492 class ListCoinsTestingSetup :
public TestChain100Setup
495 ListCoinsTestingSetup()
505 AddKey(*wallet, coinbaseKey);
515 ~ListCoinsTestingSetup()
541 auto it = wallet->mapWallet.find(tx->GetHash());
544 it->second.m_confirm = confirm;
549 std::unique_ptr<CWallet> wallet;
552 BOOST_FIXTURE_TEST_CASE(ListCoins, ListCoinsTestingSetup)
554 std::string coinbaseAddress = coinbaseKey.GetPubKey().GetID().ToString();
558 std::map<CTxDestination, std::vector<COutput>> list;
586 std::vector<COutput> available;
590 for (
const auto& group : list) {
591 for (
const auto& coin : group.second) {
598 std::vector<COutput> available;
613 BOOST_FIXTURE_TEST_CASE(wallet_disableprivkeys, TestChain100Setup)
629 static size_t CalculateNestedKeyhashInputSize(
bool use_max_sig)
633 key.MakeNewKey(
true);
634 CPubKey pubkey = key.GetPubKey();
640 CScript inner_script =
CScript() << OP_0 << std::vector<unsigned char>(key_hash.begin(), key_hash.end());
644 CScript script_pubkey =
CScript() << OP_HASH160 << std::vector<unsigned char>(script_id.begin(), script_id.end()) <<
OP_EQUAL;
649 keystore.AddKeyPubKey(key, pubkey);
664 BOOST_FIXTURE_TEST_CASE(dummy_input_size_test, TestChain100Setup)
670 bool malformed_descriptor(std::ios_base::failure e)
672 std::string s(e.what());
673 return s.find(
"Missing checksum") != std::string::npos;
676 BOOST_FIXTURE_TEST_CASE(wallet_descriptor_test, BasicTestingSetup)
678 std::vector<unsigned char> malformed_record;
680 vw << std::string(
"notadescriptor");
688 BOOST_CHECK_EXCEPTION(vr >> w_desc, std::ios_base::failure, malformed_descriptor);
709 BOOST_FIXTURE_TEST_CASE(
CreateWallet, TestChain100Setup)
713 auto wallet = TestLoadWallet(*chain);
715 key.MakeNewKey(
true);
716 AddKey(*wallet, key);
717 TestUnloadWallet(std::move(wallet));
723 DebugLogHelper addtx_counter(
"[default wallet] AddToWallet", [&](
const std::string* s) {
724 if (s) ++addtx_count;
729 bool rescan_completed =
false;
730 DebugLogHelper rescan_check(
"[default wallet] Rescan completed", [&](
const std::string* s) {
731 if (s) rescan_completed =
true;
739 std::promise<void> promise;
741 promise.get_future().wait();
744 m_coinbase_txns.push_back(CreateAndProcessBlock({},
GetScriptForRawPubKey(coinbaseKey.GetPubKey())).vtx[0]);
745 auto block_tx = TestSimpleSpend(*m_coinbase_txns[0], 0, coinbaseKey,
GetScriptForRawPubKey(key.GetPubKey()));
746 m_coinbase_txns.push_back(CreateAndProcessBlock({block_tx},
GetScriptForRawPubKey(coinbaseKey.GetPubKey())).vtx[0]);
747 auto mempool_tx = TestSimpleSpend(*m_coinbase_txns[1], 0, coinbaseKey,
GetScriptForRawPubKey(key.GetPubKey()));
753 wallet = TestLoadWallet(*chain);
757 LOCK(wallet->cs_wallet);
770 TestUnloadWallet(std::move(wallet));
782 m_coinbase_txns.push_back(CreateAndProcessBlock({},
GetScriptForRawPubKey(coinbaseKey.GetPubKey())).vtx[0]);
783 block_tx = TestSimpleSpend(*m_coinbase_txns[2], 0, coinbaseKey,
GetScriptForRawPubKey(key.GetPubKey()));
784 m_coinbase_txns.push_back(CreateAndProcessBlock({block_tx},
GetScriptForRawPubKey(coinbaseKey.GetPubKey())).vtx[0]);
785 mempool_tx = TestSimpleSpend(*m_coinbase_txns[3], 0, coinbaseKey,
GetScriptForRawPubKey(key.GetPubKey()));
791 wallet = TestLoadWallet(*chain);
794 LOCK(wallet->cs_wallet);
800 TestUnloadWallet(std::move(wallet));
803 BOOST_FIXTURE_TEST_CASE(ZapSelectTx, TestChain100Setup)
806 auto wallet = TestLoadWallet(*chain);
808 key.MakeNewKey(
true);
809 AddKey(*wallet, key);
812 m_coinbase_txns.push_back(CreateAndProcessBlock({},
GetScriptForRawPubKey(coinbaseKey.GetPubKey())).vtx[0]);
813 auto block_tx = TestSimpleSpend(*m_coinbase_txns[0], 0, coinbaseKey,
GetScriptForRawPubKey(key.GetPubKey()));
819 auto block_hash = block_tx.GetHash();
820 auto prev_hash = m_coinbase_txns[0]->GetHash();
822 LOCK(wallet->cs_wallet);
826 std::vector<uint256> vHashIn{ block_hash }, vHashOut;
833 TestUnloadWallet(std::move(wallet));
std::shared_ptr< const CTransaction > CTransactionRef
void SetupLegacyScriptPubKeyMan()
Make a LegacyScriptPubKeyMan and set it for all types, internal, and external.
std::unique_ptr< WalletDatabase > CreateMockWalletDatabase()
Return object for accessing temporary in-memory database.
static void AddTx(const CTransactionRef &tx, const CAmount &nFee, CTxMemPool &pool) EXCLUSIVE_LOCKS_REQUIRED(cs_main
void SyncWithValidationInterfaceQueue()
This is a synonym for the following, which asserts certain locks are not held: std::promise pro...
static const unsigned int MAX_BLOCKFILE_SIZE
The maximum size of a blk?????.dat file (since 0.8)
std::shared_ptr< CWallet > m_wallet
void SignTransaction(CMutableTransaction &mtx, const SigningProvider *keystore, const std::map< COutPoint, Coin > &coins, const UniValue &hashType, UniValue &result)
Sign a transaction with the given keystore and previous transactions.
constexpr CAmount DEFAULT_TRANSACTION_MAXFEE
-maxtxfee default
CAmount GetAvailableBalance(const CCoinControl *coinControl=nullptr) const
void UnloadWallet(std::shared_ptr< CWallet > &&wallet)
Explicitly unload and delete the wallet.
std::map< CTxDestination, std::vector< COutput > > ListCoins() const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Return list of available coins and locked coins grouped by non-change output address.
#define BOOST_AUTO_TEST_CASE(funcName)
CChain & ChainActive()
Please prefer the identical ChainstateManager::ActiveChain.
Provides an interface for creating and interacting with one or two chainstates: an IBD chainstate gen...
bool AddWallet(const std::shared_ptr< CWallet > &wallet)
RecursiveMutex cs_KeyStore
uint256 GetRandHash() noexcept
uint256 last_scanned_block
Hash and height of most recent block that was successfully scanned.
static const CAmount COIN
void AvailableCoins(std::vector< COutput > &vCoins, bool fOnlySafe=true, const CCoinControl *coinControl=nullptr, const CAmount &nMinimumAmount=1, const CAmount &nMaximumAmount=MAX_MONEY, const CAmount &nMinimumSumAmount=MAX_MONEY, const uint64_t nMaximumCount=0) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
populate vCoins with vector of available COutputs.
UniValue HandleRequest(const JSONRPCRequest &request)
virtual bool AddCScript(const CScript &redeemScript)
static CTransactionRef MakeTransactionRef()
const BaseSignatureCreator & DUMMY_SIGNATURE_CREATOR
A signature creator that just produces 71-byte empty signatures.
CScript GetScriptForRawPubKey(const CPubKey &pubKey)
Generate a P2PK script for the given pubkey.
static const unsigned int DEFAULT_INCREMENTAL_RELAY_FEE
Default for -incrementalrelayfee, which sets the minimum feerate increase for mempool limiting or BIP...
std::string write(unsigned int prettyIndent=0, unsigned int indentLevel=0) const
const BaseSignatureCreator & DUMMY_MAXIMUM_SIGNATURE_CREATOR
A signature creator that just produces 72-byte empty signatures.
static auto & nullopt
Substitute for C++17 std::nullopt.
FlatFilePos GetBlockPos() const
bool RemoveWatchOnly(const CScript &dest)
Remove a watch only script from the keystore.
int GetLastBlockHeight() const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Get last block processed height.
static constexpr int64_t TIMESTAMP_WINDOW
Timestamp window used as a grace period by code that compares external timestamps (such as timestamps...
std::unique_ptr< Chain > MakeChain(NodeContext &node)
Return implementation of Chain interface.
Access to the wallet database.
std::shared_ptr< CWallet > CreateWallet(interfaces::Chain &chain, const std::string &name, Optional< bool > load_on_start, DatabaseOptions &options, DatabaseStatus &status, bilingual_str &error, std::vector< bilingual_str > &warnings)
bool HaveWatchOnly(const CScript &dest) const
Returns whether the watch-only script is in the wallet.
int64_t CAmount
Amount in satoshis (Can be negative)
int64_t GetBlockTimeMax() const
void SetMockTime(int64_t nMockTimeIn)
For testing.
std::string ToString(const T &t)
Locale-independent version of std::to_string.
CBlockIndex * Tip() const
Returns the index entry for the tip of this chain, or nullptr if none.
bool error(const char *fmt, const Args &...args)
ChainstateManager * chainman
bool push_back(const UniValue &val)
NodeContext struct containing references to chain state and connection state.
void CommitTransaction(CTransactionRef tx, mapValue_t mapValue, std::vector< std::pair< std::string, std::string >> orderForm)
Submit the transaction to the node's mempool and then relay to peers.
int64_t GetVirtualTransactionInputSize(const CTxIn &txin, int64_t nSigOpCost, unsigned int bytes_per_sigop)
DBErrors LoadWallet(bool &fFirstRunRet)
CAmount m_mine_immature
Immature coinbases in the main chain.
#define LEAVE_CRITICAL_SECTION(cs)
Minimal stream for reading from an existing vector by reference.
An input of a transaction.
An encapsulated public key.
Fillable signing provider that keeps keys in an address->secret map.
const fs::path & GetDataDir(bool fNetSpecific)
static const unsigned int DEFAULT_MIN_RELAY_TX_FEE
Default for -minrelaytxfee, minimum relay fee for transactions.
RecursiveMutex cs_main
Mutex to guard access to validation specific variables, such as reading or changing the chainstate...
const std::vector< CTxOut > vout
void UnlinkPrunedFiles(const std::set< int > &setFilesToPrune)
Actually unlink the specified files.
std::unique_ptr< WalletDatabase > MakeWalletDatabase(const std::string &name, const DatabaseOptions &options, DatabaseStatus &status, bilingual_str &error_string)
std::unique_ptr< interfaces::Handler > HandleLoadWallet(LoadWalletFn load_wallet)
LegacyScriptPubKeyMan * GetOrCreateLegacyScriptPubKeyMan()
bool pushKV(const std::string &key, const UniValue &val)
void SetLastBlockProcessed(int block_height, uint256 block_hash) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
Set last block processed height, currently only use in unit test.
std::unique_ptr< WalletDatabase > CreateDummyWalletDatabase()
Return object for accessing dummy database with no read/write capabilities.
void CallFunctionInValidationInterfaceQueue(std::function< void()> func)
Pushes a function to callback onto the notification queue, guaranteeing any callbacks generated prior...
bool RemoveWallet(const std::shared_ptr< CWallet > &wallet, Optional< bool > load_on_start, std::vector< bilingual_str > &warnings)
CWalletTx * AddToWallet(CTransactionRef tx, const CWalletTx::Confirmation &confirm, const UpdateWalletTxFn &update_wtx=nullptr, bool fFlushOnClose=true)
Descriptor with some wallet metadata.
An outpoint - a combination of a transaction hash and an index n into its vout.
CBlockFileInfo * GetBlockFileInfo(size_t n)
Get block file info entry for one block file.
std::vector< CTxOut > vout
bool LoadWatchOnly(const CScript &dest)
Adds a watch-only address to the store, without saving it to disk (used by LoadWallet) ...
#define WITH_LOCK(cs, code)
Run code while locking a mutex.
RPCHelpMan importwallet()
Type-safe dynamic reference.
std::string HexStr(const Span< const uint8_t > s)
Convert a span of bytes to a lower-case hexadecimal string.
RAII object to check and reserve a wallet rescan.
A transaction with a bunch of additional info that only the owner cares about.
uint160 Hash160(const T1 &in1)
Compute the 160-bit hash an object.
static std::shared_ptr< CWallet > Create(interfaces::Chain &chain, const std::string &name, std::unique_ptr< WalletDatabase > database, uint64_t wallet_creation_flags, bilingual_str &error, std::vector< bilingual_str > &warnings)
#define ENTER_CRITICAL_SECTION(cs)
void LockCoin(const COutPoint &output) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
#define EXCLUSIVE_LOCKS_REQUIRED(...)
static const CAmount DEFAULT_TRANSACTION_MINFEE
-mintxfee default
#define BOOST_FIXTURE_TEST_SUITE(a, b)
bool CreateTransaction(const std::vector< CRecipient > &vecSend, CTransactionRef &tx, CAmount &nFeeRet, int &nChangePosInOut, bilingual_str &error, const CCoinControl &coin_control, FeeCalculation &fee_calc_out, bool sign=true)
Create a new transaction paying the recipients with a set of coins selected by SelectCoins(); Also cr...
Testing setup and teardown for wallet.
#define BOOST_CHECK_EQUAL(v1, v2)
The block chain is a tree shaped structure starting with the genesis block at the root...
Serialized script, used inside transaction inputs and outputs.
bool(* handler)(const util::Ref &context, HTTPRequest *req, const std::string &strReq)
enum CWallet::ScanResult::@15 status
A reference to a CKey: the Hash160 of its serialized public key.
void UpdateInput(CTxIn &input, const SignatureData &data)
#define BOOST_AUTO_TEST_SUITE_END()
A CWallet maintains a set of transactions and balances, and provides the ability to create new transa...
bool ProduceSignature(const SigningProvider &provider, const BaseSignatureCreator &creator, const CScript &fromPubKey, SignatureData &sigdata)
Produce a script signature using a generic signature creator.
bool GetWatchPubKey(const CKeyID &address, CPubKey &pubkey_out) const
Fetches a pubkey from mapWatchKeys if it exists there.
Optional< int > last_scanned_height
A mutable version of CTransaction.
uint256 last_failed_block
Height of the most recent block that could not be scanned due to read errors or pruning.
const uint256 & GetHash() const
static const CAmount WALLET_INCREMENTAL_RELAY_FEE
minimum recommended increment for BIP 125 replacement txs
An encapsulated private key.
The basic transaction that is broadcasted on the network and contained in blocks. ...
int nHeight
height of the entry in the chain. The genesis block has height 0
ScanResult ScanForWalletTransactions(const uint256 &start_block, int start_height, Optional< int > max_height, const WalletRescanReserver &reserver, bool fUpdate)
Scan the block chain (starting in start_block) for transactions from or to us.
boost::variant< CNoDestination, PKHash, ScriptHash, WitnessV0ScriptHash, WitnessV0KeyHash, WitnessUnknown > CTxDestination
A txout script template with a specific destination.
Balance GetBalance(int min_depth=0, bool avoid_reuse=true) const
virtual bool AddKey(const CKey &key)
#define Assert(val)
Identity function.
uint256 GetBlockHash() const
#define BOOST_CHECK(expr)
const uint256 * phashBlock
pointer to the hash of the block, if any. Memory is owned by this CBlockIndex
BlockMap & BlockIndex() EXCLUSIVE_LOCKS_REQUIRED(
static constexpr size_t DUMMY_NESTED_P2WPKH_INPUT_SIZE
Pre-calculated constants for input size estimation in virtual size