20 #include <validation.h>
28 #include <boost/test/unit_test.hpp>
44 BOOST_FIXTURE_TEST_SUITE(wallet_tests, WalletTestingSetup)
52 std::vector<bilingual_str> warnings;
62 wallet->m_chain_notifications_handler.reset();
73 std::map<COutPoint, Coin> coins;
74 coins[mtx.
vin[0].prevout].out = from.
vout[index];
75 std::map<int, bilingual_str> input_errors;
88 if (!
wallet.AddWalletDescriptor(w_desc, provider,
"",
false))
assert(
false);
131 std::chrono::steady_clock::time_point fake_time;
132 reserver.
setNow([&] { fake_time += 60s;
return fake_time; });
188 file_number = newTip->GetBlockPos().nFile;
236 wallet->SetupLegacyScriptPubKeyMan();
237 WITH_LOCK(
wallet->cs_wallet,
wallet->SetLastBlockProcessed(newTip->nHeight, newTip->GetBlockHash()));
246 key.
pushKV(
"timestamp", 0);
264 strprintf(
"[{\"success\":false,\"error\":{\"code\":-1,\"message\":\"Rescan failed for key with creation "
265 "timestamp %d. There was an error reading a block from time %d, which is after or within %d "
266 "seconds of key creation, and could contain transactions pertaining to the key. As a result, "
267 "transactions and coins using this key may not appear in the wallet. This error could be caused "
268 "by pruning or data corruption (see bitcoind log for details) and could be dealt with by "
269 "downloading and rescanning the relevant blocks (see -reindex option and rescanblockchain "
270 "RPC).\"}},{\"success\":true}]",
286 m_coinbase_txns.emplace_back(CreateAndProcessBlock({},
GetScriptForRawPubKey(coinbaseKey.GetPubKey())).vtx[0]);
287 m_coinbase_txns.emplace_back(CreateAndProcessBlock({},
GetScriptForRawPubKey(coinbaseKey.GetPubKey())).vtx[0]);
293 m_coinbase_txns.emplace_back(CreateAndProcessBlock({},
GetScriptForRawPubKey(coinbaseKey.GetPubKey())).vtx[0]);
295 std::string backup_file =
fs::PathToString(m_args.GetDataDirNet() /
"wallet.backup");
303 auto spk_man =
wallet->GetOrCreateLegacyScriptPubKeyMan();
305 spk_man->mapKeyMetadata[coinbaseKey.GetPubKey().GetID()].nCreateTime = KEY_TIME;
306 spk_man->AddKeyPubKey(coinbaseKey, coinbaseKey.GetPubKey());
326 wallet->SetupLegacyScriptPubKeyMan();
342 for (
size_t i = 0; i < m_coinbase_txns.size(); ++i) {
343 bool found =
wallet->GetWalletTx(m_coinbase_txns[i]->GetHash());
344 bool expected = i >= 100;
364 wallet.SetupDescriptorScriptPubKeyMans();
388 auto inserted = chainman.
BlockIndex().emplace(std::piecewise_construct, std::make_tuple(
GetRandHash()), std::make_tuple());
390 const uint256& hash = inserted.first->first;
391 block = &inserted.first->second;
392 block->
nTime = blockTime;
435 m_wallet.SetAddressUsed(batch, dest,
true);
436 m_wallet.SetAddressReceiveRequest(batch, dest,
"0",
"val_rr0");
437 m_wallet.SetAddressReceiveRequest(batch, dest,
"1",
"val_rr1");
463 if (is_pubkey_fully_valid) {
474 if (is_pubkey_fully_valid) {
483 std::vector<unsigned char> pubkey_raw(pubkey.
begin(), pubkey.
end());
484 std::fill(pubkey_raw.begin()+1, pubkey_raw.end(), 0);
543 constexpr
int RANDOM_CHANGE_POSITION = -1;
548 wallet->CommitTransaction(tx, {}, {});
559 auto it =
wallet->mapWallet.find(tx->GetHash());
570 std::string coinbaseAddress = coinbaseKey.GetPubKey().GetID().ToString();
574 std::map<CTxDestination, std::vector<COutput>> list;
580 BOOST_CHECK_EQUAL(std::get<PKHash>(list.begin()->first).ToString(), coinbaseAddress);
596 BOOST_CHECK_EQUAL(std::get<PKHash>(list.begin()->first).ToString(), coinbaseAddress);
604 for (
const auto& group : list) {
605 for (
const auto& coin : group.second) {
607 wallet->LockCoin(coin.outpoint);
621 BOOST_CHECK_EQUAL(std::get<PKHash>(list.begin()->first).ToString(), coinbaseAddress);
626 std::map<OutputType, size_t>& expected_coins_sizes)
635 for (uint32_t i = 0; i < wtx.
tx->vout.size(); i++)
context.wallet->LockCoin({wtx.GetHash(), i});
636 for (
const auto& [type, size] : expected_coins_sizes)
BOOST_CHECK_EQUAL(size, available_coins.
coins[type].size());
641 std::map<OutputType, size_t> expected_coins_sizes;
642 for (
const auto& out_type :
OUTPUT_TYPES) { expected_coins_sizes[out_type] = 0U; }
660 expected_coins_sizes[out_type] = 2U;
669 wallet->SetupLegacyScriptPubKeyMan();
730 std::string s(e.what());
731 return s.find(
"Missing checksum") != std::string::npos;
736 std::vector<unsigned char> malformed_record;
738 vw << std::string(
"notadescriptor");
769 m_args.ForceSetArg(
"-unsafesqlitesync",
"1");
784 DebugLogHelper addtx_counter(
"[default wallet] AddToWallet", [&](
const std::string* s) {
785 if (s) ++addtx_count;
790 bool rescan_completed =
false;
791 DebugLogHelper rescan_check(
"[default wallet] Rescan completed", [&](
const std::string* s) {
792 if (s) rescan_completed =
true;
800 std::promise<void> promise;
802 promise.get_future().wait();
805 m_coinbase_txns.push_back(CreateAndProcessBlock({},
GetScriptForRawPubKey(coinbaseKey.GetPubKey())).vtx[0]);
807 m_coinbase_txns.push_back(CreateAndProcessBlock({block_tx},
GetScriptForRawPubKey(coinbaseKey.GetPubKey())).vtx[0]);
846 m_coinbase_txns.push_back(CreateAndProcessBlock({},
GetScriptForRawPubKey(coinbaseKey.GetPubKey())).vtx[0]);
848 m_coinbase_txns.push_back(CreateAndProcessBlock({block_tx},
GetScriptForRawPubKey(coinbaseKey.GetPubKey())).vtx[0]);
876 m_args.ForceSetArg(
"-unsafesqlitesync",
"1");
886 m_coinbase_txns.push_back(CreateAndProcessBlock({},
GetScriptForRawPubKey(coinbaseKey.GetPubKey())).vtx[0]);
893 auto block_hash = block_tx.GetHash();
894 auto prev_tx = m_coinbase_txns[0];
900 std::vector<uint256> vHashIn{ block_hash }, vHashOut;
931 std::unique_ptr<DatabaseCursor>
GetNewCursor()
override {
return std::make_unique<FailCursor>(); }
946 bool Rewrite(
const char* pszSkip=
nullptr)
override {
return true; }
947 bool Backup(
const std::string& strDest)
const override {
return true; }
953 std::string
Filename()
override {
return "faildb"; }
954 std::string
Format()
override {
return "faildb"; }
955 std::unique_ptr<DatabaseBatch>
MakeBatch(
bool flush_on_close =
true)
override {
return std::make_unique<FailBatch>(
m_pass); }
968 wallet.SetupDescriptorScriptPubKeyMans();
973 BOOST_ASSERT(op_dest);
992 mtx.
vin.push_back(
CTxIn(tx_id_to_spend, 0));
1013 mtx.
vin.push_back(
CTxIn(good_tx_id, 0));
1016 HasReason(
"DB error adding transaction to wallet, write failed"));
int64_t CAmount
Amount in satoshis (Can be negative)
static constexpr CAmount COIN
The amount of satoshis in one BTC.
static constexpr int64_t TIMESTAMP_WINDOW
Timestamp window used as a grace period by code that compares external timestamps (such as timestamps...
#define Assert(val)
Identity function.
The block chain is a tree shaped structure starting with the genesis block at the root,...
uint256 GetBlockHash() const
int64_t GetBlockTimeMax() const
int nHeight
height of the entry in the chain. The genesis block has height 0
FlatFilePos GetBlockPos() const EXCLUSIVE_LOCKS_REQUIRED(
const uint256 * phashBlock
pointer to the hash of the block, if any. Memory is owned by this CBlockIndex
An encapsulated private key.
void MakeNewKey(bool fCompressed)
Generate a new private key using a cryptographic PRNG.
CPubKey GetPubKey() const
Compute the public key from a private key.
A reference to a CKey: the Hash160 of its serialized public key.
An encapsulated public key.
const unsigned char * end() const
bool IsCompressed() const
Check whether this is a compressed public key.
CKeyID GetID() const
Get the KeyID of this public key (hash of its serialization)
bool IsFullyValid() const
fully validate whether this is a valid public key (more expensive than IsValid())
const unsigned char * begin() const
Serialized script, used inside transaction inputs and outputs.
The basic transaction that is broadcasted on the network and contained in blocks.
const std::vector< CTxOut > vout
const uint256 & GetHash() const
An input of a transaction.
Provides an interface for creating and interacting with one or two chainstates: an IBD chainstate gen...
node::BlockMap & BlockIndex() EXCLUSIVE_LOCKS_REQUIRED(
Double ended buffer combining vector and stream-like interfaces.
uint256 rand256() noexcept
generate a random uint256.
Fillable signing provider that keeps keys in an address->secret map.
virtual bool AddKeyPubKey(const CKey &key, const CPubKey &pubkey)
virtual bool AddCScript(const CScript &redeemScript)
virtual bool AddKey(const CKey &key)
RecursiveMutex cs_KeyStore
BOOST_CHECK_EXCEPTION predicates to check the specific validation error.
UniValue HandleRequest(const JSONRPCRequest &request) const
Minimal stream for reading from an existing byte array by Span.
void push_back(UniValue val)
std::string write(unsigned int prettyIndent=0, unsigned int indentLevel=0) const
void pushKV(std::string key, UniValue val)
constexpr bool IsNull() const
constexpr unsigned char * end()
constexpr unsigned char * begin()
A CWallet maintains a set of transactions and balances, and provides the ability to create new transa...
static std::shared_ptr< CWallet > Create(WalletContext &context, const std::string &name, std::unique_ptr< WalletDatabase > database, uint64_t wallet_creation_flags, bilingual_str &error, std::vector< bilingual_str > &warnings)
A transaction with a bunch of additional info that only the owner cares about.
RAII class that provides access to a WalletDatabase.
RAII class that provides access to a FailDatabase.
std::unique_ptr< DatabaseCursor > GetNewCursor() override
bool WriteKey(DataStream &&key, DataStream &&value, bool overwrite=true) override
bool ReadKey(DataStream &&key, DataStream &value) override
bool TxnCommit() override
bool HasKey(DataStream &&key) override
bool EraseKey(DataStream &&key) override
Status Next(DataStream &key, DataStream &value) override
A dummy WalletDatabase that does nothing, only fails if needed.
void ReloadDbEnv() override
std::string Filename() override
Return path to main database file for logs and error messages.
std::unique_ptr< DatabaseBatch > MakeBatch(bool flush_on_close=true) override
Make a DatabaseBatch connected to this database.
void Open() override
Open the database if it is not already opened.
void RemoveRef() override
Indicate that database user has stopped using the database and that it could be flushed or closed.
std::string Format() override
void IncrementUpdateCounter() override
bool Rewrite(const char *pszSkip=nullptr) override
Rewrite the entire database on disk, with the exception of key pszSkip if non-zero.
void AddRef() override
Indicate the a new database user has began using the database.
void Flush() override
Make sure all changes are flushed to database file.
void Close() override
Flush to the database file and close the database.
bool PeriodicFlush() override
bool Backup(const std::string &strDest) const override
Back up the entire database to a file.
bool HaveWatchOnly(const CScript &dest) const
Returns whether the watch-only script is in the wallet.
bool LoadWatchOnly(const CScript &dest)
Adds a watch-only address to the store, without saving it to disk (used by LoadWallet)
bool GetWatchPubKey(const CKeyID &address, CPubKey &pubkey_out) const
Fetches a pubkey from mapWatchKeys if it exists there.
bool RemoveWatchOnly(const CScript &dest)
Remove a watch only script from the keystore.
std::unique_ptr< CWallet > wallet
CWalletTx & AddTx(CRecipient recipient)
Access to the wallet database.
An instance of this class represents one database.
std::atomic< unsigned int > nUpdateCounter
Descriptor with some wallet metadata.
RAII object to check and reserve a wallet rescan.
bool reserve(bool with_passphrase=false)
RecursiveMutex cs_main
Mutex to guard access to validation specific variables, such as reading or changing the chainstate.
BOOST_AUTO_TEST_SUITE_END()
std::unique_ptr< Descriptor > Parse(const std::string &descriptor, FlatSigningProvider &out, std::string &error, bool require_checksum)
Parse a descriptor string.
uint160 Hash160(const T1 &in1)
Compute the 160-bit hash an object.
std::string EncodeSecret(const CKey &key)
bool error(const char *fmt, const Args &... args)
static std::string PathToString(const path &path)
Convert path object to a byte string.
void UnlinkPrunedFiles(const std::set< int > &setFilesToPrune)
Actually unlink the specified files.
static const unsigned int MAX_BLOCKFILE_SIZE
The maximum size of a blk?????.dat file (since 0.8)
static constexpr size_t DUMMY_NESTED_P2WPKH_INPUT_SIZE
Pre-calculated constants for input size estimation in virtual size
void UnloadWallet(std::shared_ptr< CWallet > &&wallet)
Explicitly unload and delete the wallet.
static CMutableTransaction TestSimpleSpend(const CTransaction &from, uint32_t index, const CKey &key, const CScript &pubkey)
CAmount CachedTxGetAvailableCredit(const CWallet &wallet, const CWalletTx &wtx, const isminefilter &filter)
Balance GetBalance(const CWallet &wallet, const int min_depth, bool avoid_reuse)
CAmount GetAvailableBalance(const CWallet &wallet, const CCoinControl *coinControl)
static void PollutePubKey(CPubKey &pubkey)
std::unique_ptr< WalletDatabase > CreateMockWalletDatabase(DatabaseOptions &options)
Return object for accessing temporary in-memory database.
constexpr CAmount DEFAULT_TRANSACTION_MAXFEE
-maxtxfee default
RPCHelpMan importwallet()
BOOST_FIXTURE_TEST_CASE(wallet_coinsresult_test, BasicTestingSetup)
std::unique_ptr< interfaces::Handler > HandleLoadWallet(WalletContext &context, LoadWalletFn load_wallet)
std::unique_ptr< CWallet > CreateSyncedWallet(interfaces::Chain &chain, CChain &cchain, const CKey &key)
static const CAmount DEFAULT_TRANSACTION_MINFEE
-mintxfee default
util::Result< CreatedTransactionResult > CreateTransaction(CWallet &wallet, const std::vector< CRecipient > &vecSend, int change_pos, const CCoinControl &coin_control, bool sign)
Create a new transaction paying the recipients with a set of coins selected by SelectCoins(); Also cr...
std::unique_ptr< WalletDatabase > MakeWalletDatabase(const std::string &name, const DatabaseOptions &options, DatabaseStatus &status, bilingual_str &error_string)
static std::shared_ptr< CWallet > TestLoadWallet(WalletContext &context)
void NotifyWalletLoaded(WalletContext &context, const std::shared_ptr< CWallet > &wallet)
static int64_t AddTx(ChainstateManager &chainman, CWallet &wallet, uint32_t lockTime, int64_t mockTime, int64_t blockTime)
std::map< CTxDestination, std::vector< COutput > > ListCoins(const CWallet &wallet)
Return list of available coins and locked coins grouped by non-change output address.
static void TestWatchOnlyPubKey(LegacyScriptPubKeyMan *spk_man, const CPubKey &add_pubkey)
CoinsResult AvailableCoinsListUnspent(const CWallet &wallet, const CCoinControl *coinControl, CoinFilterParams params)
Wrapper function for AvailableCoins which skips the feerate and CoinFilterParams::only_spendable para...
std::unique_ptr< WalletDatabase > CreateDummyWalletDatabase()
Return object for accessing dummy database with no read/write capabilities.
static void AddKey(CWallet &wallet, const CKey &key)
bool AddWallet(WalletContext &context, const std::shared_ptr< CWallet > &wallet)
static const CAmount WALLET_INCREMENTAL_RELAY_FEE
minimum recommended increment for replacement txs
static void TestUnloadWallet(std::shared_ptr< CWallet > &&wallet)
CAmount CachedTxGetImmatureCredit(const CWallet &wallet, const CWalletTx &wtx, const isminefilter &filter)
bool malformed_descriptor(std::ios_base::failure e)
std::shared_ptr< CWallet > CreateWallet(WalletContext &context, const std::string &name, std::optional< bool > load_on_start, DatabaseOptions &options, DatabaseStatus &status, bilingual_str &error, std::vector< bilingual_str > &warnings)
void TestCoinsResult(ListCoinsTest &context, OutputType out_type, CAmount amount, std::map< OutputType, size_t > &expected_coins_sizes)
BOOST_AUTO_TEST_CASE(bnb_search_test)
@ WALLET_FLAG_DESCRIPTORS
Indicate that this wallet supports DescriptorScriptPubKeyMan.
@ WALLET_FLAG_DISABLE_PRIVATE_KEYS
static size_t CalculateNestedKeyhashInputSize(bool use_max_sig)
std::variant< TxStateConfirmed, TxStateInMempool, TxStateConflicted, TxStateInactive, TxStateUnrecognized > TxState
All possible CWalletTx states.
bool RemoveWallet(WalletContext &context, const std::shared_ptr< CWallet > &wallet, std::optional< bool > load_on_start, std::vector< bilingual_str > &warnings)
CoinsResult AvailableCoins(const CWallet &wallet, const CCoinControl *coinControl, std::optional< CFeeRate > feerate, const CoinFilterParams ¶ms)
Populate the CoinsResult struct with vectors of available COutputs, organized by OutputType.
std::shared_ptr< CWallet > wallet
#define BOOST_CHECK_EQUAL(v1, v2)
#define BOOST_CHECK(expr)
static constexpr auto OUTPUT_TYPES
int64_t GetVirtualTransactionInputSize(const CTxIn &txin, int64_t nSigOpCost, unsigned int bytes_per_sigop)
static constexpr unsigned int DEFAULT_INCREMENTAL_RELAY_FEE
Default for -incrementalrelayfee, which sets the minimum feerate increase for mempool limiting or rep...
static constexpr unsigned int DEFAULT_MIN_RELAY_TX_FEE
Default for -minrelaytxfee, minimum relay fee for transactions.
static CTransactionRef MakeTransactionRef(Tx &&txIn)
std::shared_ptr< const CTransaction > CTransactionRef
uint256 GetRandHash() noexcept
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.
bool(* handler)(const std::any &context, HTTPRequest *req, const std::string &strReq)
static const int64_t values[]
A selection of numbers that do not trigger int64_t overflow when added/subtracted.
FastRandomContext g_insecure_rand_ctx
This global and the helpers that use it are not thread-safe.
bool ProduceSignature(const SigningProvider &provider, const BaseSignatureCreator &creator, const CScript &fromPubKey, SignatureData &sigdata)
Produce a script signature using a generic signature creator.
void UpdateInput(CTxIn &input, const SignatureData &data)
const BaseSignatureCreator & DUMMY_MAXIMUM_SIGNATURE_CREATOR
A signature creator that just produces 72-byte empty signatures.
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.
CScript GetScriptForDestination(const CTxDestination &dest)
Generate a Bitcoin scriptPubKey for the given CTxDestination.
std::variant< CNoDestination, PKHash, ScriptHash, WitnessV0ScriptHash, WitnessV0KeyHash, WitnessV1Taproot, WitnessUnknown > CTxDestination
A txout script template with a specific destination.
Describes a place in the block chain to another node such that if the other node doesn't have the sam...
A mutable version of CTransaction.
uint256 GetHash() const
Compute the hash of this CMutableTransaction.
std::vector< CTxOut > vout
Testing fixture that pre-creates a 100-block REGTEST-mode block chain.
CBlock CreateAndProcessBlock(const std::vector< CMutableTransaction > &txns, const CScript &scriptPubKey, Chainstate *chainstate=nullptr)
Create a new block with just given transactions, coinbase paying to scriptPubKey, and try to add it t...
Testing setup that configures a complete environment.
std::unique_ptr< ChainstateManager > chainman
std::unique_ptr< interfaces::Chain > chain
std::optional< int > last_scanned_height
uint256 last_scanned_block
Hash and height of most recent block that was successfully scanned.
uint256 last_failed_block
Height of the most recent block that could not be scanned due to read errors or pruning.
enum wallet::CWallet::ScanResult::@17 status
COutputs available for spending, stored by OutputType.
size_t Size() const
The following methods are provided so that CoinsResult can mimic a vector, i.e., methods can work wit...
std::map< OutputType, std::vector< COutput > > coins
State of transaction confirmed in a block.
State of transaction added to mempool.
State of transaction not confirmed or conflicting with a known block and not in the mempool.
WalletContext struct containing references to state shared between CWallet instances,...
interfaces::Chain * chain
#define WITH_LOCK(cs, code)
Run code while locking a mutex.
void SetMockTime(int64_t nMockTimeIn)
DEPRECATED Use SetMockTime with chrono type.
std::string HexStr(const Span< const uint8_t > s)
Convert a span of bytes to a lower-case hexadecimal string.
void CallFunctionInValidationInterfaceQueue(std::function< void()> func)
Pushes a function to callback onto the notification queue, guaranteeing any callbacks generated prior...
void SyncWithValidationInterfaceQueue()
This is a synonym for the following, which asserts certain locks are not held: std::promise<void> pro...
std::shared_ptr< CWallet > m_wallet