23 #include <validation.h> 32 #include <boost/test/unit_test.hpp> 53 mtx.
vin.push_back({
CTxIn{from.GetHash(), index}});
56 std::map<COutPoint, Coin> coins;
57 coins[mtx.
vin[0].prevout].out = from.vout[index];
58 std::map<int, bilingual_str> input_errors;
70 auto& desc = descs.at(0);
72 if (!
wallet.AddWalletDescriptor(w_desc, provider,
"",
false))
assert(
false);
115 std::chrono::steady_clock::time_point fake_time;
116 reserver.
setNow([&] { fake_time += 60
s;
return fake_time; });
220 wallet->SetupLegacyScriptPubKeyMan();
223 context.
args = &m_args;
230 key.
pushKV(
"timestamp", 0);
247 strprintf(
"[{\"success\":false,\"error\":{\"code\":-1,\"message\":\"Rescan failed for key with creation " 248 "timestamp %d. There was an error reading a block from time %d, which is after or within %d " 249 "seconds of key creation, and could contain transactions pertaining to the key. As a result, " 250 "transactions and coins using this key may not appear in the wallet. This error could be caused " 251 "by pruning or data corruption (see bitcoind log for details) and could be dealt with by " 252 "downloading and rescanning the relevant blocks (see -reindex option and rescanblockchain " 253 "RPC).\"}},{\"success\":true}]",
269 m_coinbase_txns.emplace_back(CreateAndProcessBlock({},
GetScriptForRawPubKey(coinbaseKey.GetPubKey())).vtx[0]);
270 m_coinbase_txns.emplace_back(CreateAndProcessBlock({},
GetScriptForRawPubKey(coinbaseKey.GetPubKey())).vtx[0]);
276 m_coinbase_txns.emplace_back(CreateAndProcessBlock({},
GetScriptForRawPubKey(coinbaseKey.GetPubKey())).vtx[0]);
278 std::string backup_file =
fs::PathToString(m_args.GetDataDirNet() /
"wallet.backup");
283 context.
args = &m_args;
286 auto spk_man =
wallet->GetOrCreateLegacyScriptPubKeyMan();
288 spk_man->mapKeyMetadata[coinbaseKey.GetPubKey().GetID()].nCreateTime = KEY_TIME;
289 spk_man->AddKeyPubKey(coinbaseKey, coinbaseKey.GetPubKey());
309 wallet->SetupLegacyScriptPubKeyMan();
312 context.
args = &m_args;
325 for (
size_t i = 0; i < m_coinbase_txns.size(); ++i) {
326 bool found =
wallet->GetWalletTx(m_coinbase_txns[i]->GetHash());
327 bool expected = i >= 100;
338 const auto NUM_WALLETS{5};
341 BOOST_REQUIRE(chain->getRwSetting(
"wallet").isNull());
343 const auto& check_concurrent_wallet = [&](
const auto& settings_function,
int num_expected_wallets) {
344 std::vector<std::thread> threads;
345 threads.reserve(NUM_WALLETS);
346 for (
auto i{0}; i < NUM_WALLETS; ++i) threads.emplace_back(settings_function, i);
347 for (
auto&
t : threads)
t.join();
349 auto wallets = chain->getRwSetting(
"wallet");
354 check_concurrent_wallet([&chain](
int i) {
360 check_concurrent_wallet([&chain](
int i) {
380 wallet.SetupDescriptorScriptPubKeyMans();
404 auto inserted = chainman.
BlockIndex().emplace(std::piecewise_construct, std::make_tuple(
GetRandHash()), std::make_tuple());
406 const uint256& hash = inserted.first->first;
407 block = &inserted.first->second;
408 block->
nTime = blockTime;
454 std::vector<bilingual_str> warnings;
456 auto wallet{std::make_shared<CWallet>(chain.get(),
"", std::move(database))};
466 BOOST_CHECK(!wallet->IsAddressPreviouslySpent(PKHash()));
467 WalletBatch batch{wallet->GetDatabase()};
477 BOOST_CHECK(wallet->IsAddressPreviouslySpent(PKHash()));
478 BOOST_CHECK(wallet->IsAddressPreviouslySpent(ScriptHash()));
479 auto requests = wallet->GetAddressReceiveRequests();
480 auto erequests = {
"val_rr11",
"val_rr20"};
481 BOOST_CHECK_EQUAL_COLLECTIONS(requests.begin(), requests.end(), std::begin(erequests), std::end(erequests));
489 BOOST_CHECK(!wallet->IsAddressPreviouslySpent(PKHash()));
490 BOOST_CHECK(!wallet->IsAddressPreviouslySpent(ScriptHash()));
491 auto requests = wallet->GetAddressReceiveRequests();
492 auto erequests = {
"val_rr11"};
493 BOOST_CHECK_EQUAL_COLLECTIONS(requests.begin(), requests.end(), std::begin(erequests), std::end(erequests));
516 if (is_pubkey_fully_valid) {
527 if (is_pubkey_fully_valid) {
537 std::vector<unsigned char> pubkey_raw;
538 pubkey_raw.push_back(pubkey[0]);
539 pubkey_raw.insert(pubkey_raw.end(), pubkey.
size() - 1, 0);
602 wallet->CommitTransaction(tx, {}, {});
613 auto it =
wallet->mapWallet.find(tx->GetHash());
624 std::string coinbaseAddress = coinbaseKey.GetPubKey().GetID().ToString();
628 std::map<CTxDestination, std::vector<COutput>> list;
658 for (
const auto&
group : list) {
659 for (
const auto& coin :
group.second) {
661 wallet->LockCoin(coin.outpoint);
680 std::map<OutputType, size_t>& expected_coins_sizes)
682 LOCK(context.wallet->cs_wallet);
689 for (uint32_t i = 0; i < wtx.tx->vout.size(); i++) context.wallet->LockCoin({wtx.GetHash(), i});
690 for (
const auto& [type, size] : expected_coins_sizes)
BOOST_CHECK_EQUAL(size, available_coins.
coins[type].size());
695 std::map<OutputType, size_t> expected_coins_sizes;
696 for (
const auto& out_type :
OUTPUT_TYPES) { expected_coins_sizes[out_type] = 0U; }
714 expected_coins_sizes[out_type] = 2U;
723 wallet->SetupLegacyScriptPubKeyMan();
755 CScript script_pubkey =
CScript() << OP_HASH160 << std::vector<unsigned char>(script_id.begin(), script_id.end()) <<
OP_EQUAL;
760 keystore.AddKeyPubKey(key, pubkey);
783 std::string
s(e.what());
784 return s.find(
"Missing checksum") != std::string::npos;
789 std::vector<unsigned char> malformed_record;
791 vw << std::string(
"notadescriptor");
822 m_args.ForceSetArg(
"-unsafesqlitesync",
"1");
825 context.
args = &m_args;
836 DebugLogHelper addtx_counter(
"[default wallet] AddToWallet", [&](
const std::string*
s) {
837 if (
s) ++addtx_count;
842 bool rescan_completed =
false;
843 DebugLogHelper rescan_check(
"[default wallet] Rescan completed", [&](
const std::string*
s) {
844 if (
s) rescan_completed =
true;
852 std::promise<void> promise;
854 promise.get_future().wait();
857 m_coinbase_txns.push_back(CreateAndProcessBlock({},
GetScriptForRawPubKey(coinbaseKey.GetPubKey())).vtx[0]);
859 m_coinbase_txns.push_back(CreateAndProcessBlock({block_tx},
GetScriptForRawPubKey(coinbaseKey.GetPubKey())).vtx[0]);
899 m_coinbase_txns.push_back(CreateAndProcessBlock({},
GetScriptForRawPubKey(coinbaseKey.GetPubKey())).vtx[0]);
901 m_coinbase_txns.push_back(CreateAndProcessBlock({block_tx},
GetScriptForRawPubKey(coinbaseKey.GetPubKey())).vtx[0]);
923 context.
args = &m_args;
931 m_args.ForceSetArg(
"-unsafesqlitesync",
"1");
933 context.
args = &m_args;
940 m_coinbase_txns.push_back(CreateAndProcessBlock({},
GetScriptForRawPubKey(coinbaseKey.GetPubKey())).vtx[0]);
947 auto block_hash = block_tx.GetHash();
948 auto prev_tx = m_coinbase_txns[0];
954 std::vector<uint256> vHashIn{ block_hash };
974 wallet.SetupDescriptorScriptPubKeyMans();
997 mtx.
vin.emplace_back(tx_id_to_spend, 0);
999 const auto good_tx_id{mtx.
GetHash()};
1004 const CWalletTx* new_wtx =
wallet.GetWalletTx(good_tx_id.ToUint256());
1018 mtx.
vin.emplace_back(good_tx_id, 0);
1021 HasReason(
"DB error adding transaction to wallet, write failed"));
std::shared_ptr< const CTransaction > CTransactionRef
RPCHelpMan importwallet()
std::unique_ptr< interfaces::Chain > chain
std::optional< DatabaseFormat > require_format
static UniValue Parse(std::string_view raw)
Parse string to UniValue or throw runtime_error if string contains invalid JSON.
bool HaveWatchOnly(const CScript &dest) const
Returns whether the watch-only script is in the wallet.
void push_back(UniValue val)
bool RemoveWatchOnly(const CScript &dest)
Remove a watch only script from the keystore.
State of transaction added to mempool.
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.
static const CAmount DEFAULT_TRANSACTION_MINFEE
-mintxfee default
static constexpr unsigned int DEFAULT_INCREMENTAL_RELAY_FEE
Default for -incrementalrelayfee, which sets the minimum feerate increase for mempool limiting or rep...
static constexpr size_t DUMMY_NESTED_P2WPKH_INPUT_SIZE
Pre-calculated constants for input size estimation in virtual size
static void AddKey(CWallet &wallet, const CKey &key)
static size_t CalculateNestedKeyhashInputSize(bool use_max_sig)
Describes a place in the block chain to another node such that if the other node doesn't have the sam...
size_t Size() const
The following methods are provided so that CoinsResult can mimic a vector, i.e., methods can work wit...
void TestLoadWallet(const std::string &name, DatabaseFormat format, std::function< void(std::shared_ptr< CWallet >)> f)
Provides an interface for creating and interacting with one or two chainstates: an IBD chainstate gen...
RecursiveMutex cs_KeyStore
static const DatabaseFormat DATABASE_FORMATS[]
CPubKey GetPubKey() const
Compute the public key from a private key.
virtual bool AddCScript(const CScript &redeemScript)
std::shared_ptr< CWallet > m_wallet
std::unique_ptr< ValidationSignals > validation_signals
Issues calls about blocks and transactions.
CoinsResult AvailableCoinsListUnspent(const CWallet &wallet, const CCoinControl *coinControl, CoinFilterParams params)
Wrapper function for AvailableCoins which skips the feerate and CoinFilterParams::only_spendable para...
const BaseSignatureCreator & DUMMY_SIGNATURE_CREATOR
A signature creator that just produces 71-byte empty signatures.
static constexpr unsigned int DEFAULT_MIN_RELAY_TX_FEE
Default for -minrelaytxfee, minimum relay fee for transactions.
const BaseSignatureCreator & DUMMY_MAXIMUM_SIGNATURE_CREATOR
A signature creator that just produces 72-byte empty signatures.
State of transaction not confirmed or conflicting with a known block and not in the mempool...
bool RemoveWalletSetting(interfaces::Chain &chain, const std::string &wallet_name)
Remove wallet name from persistent configuration so it will not be loaded on startup.
RAII object to check and reserve a wallet rescan.
Balance GetBalance(const CWallet &wallet, const int min_depth, bool avoid_reuse)
bool reserve(bool with_passphrase=false)
Access to the wallet database.
State of transaction confirmed in a block.
bool(* handler)(const std::any &context, HTTPRequest *req, const std::string &strReq)
std::shared_ptr< CWallet > TestLoadWallet(std::unique_ptr< WalletDatabase > database, WalletContext &context, uint64_t create_flags)
static constexpr int64_t TIMESTAMP_WINDOW
Timestamp window used as a grace period by code that compares external timestamps (such as timestamps...
BOOST_AUTO_TEST_CASE(WatchOnlyPubKeys)
CKeyID GetID() const
Get the KeyID of this public key (hash of its serialization)
bool GetWatchPubKey(const CKeyID &address, CPubKey &pubkey_out) const
Fetches a pubkey from mapWatchKeys if it exists there.
static constexpr auto OUTPUT_TYPES
std::unique_ptr< CWallet > wallet
static void AvailableCoins(benchmark::Bench &bench, const std::vector< OutputType > &output_type)
constexpr unsigned char * begin()
bool LoadWatchOnly(const CScript &dest)
Adds a watch-only address to the store, without saving it to disk (used by LoadWallet) ...
Minimal stream for reading from an existing byte array by Span.
CKey GenerateRandomKey(bool compressed) noexcept
std::map< OutputType, std::vector< COutput > > coins
int64_t CAmount
Amount in satoshis (Can be negative)
static int64_t AddTx(ChainstateManager &chainman, CWallet &wallet, uint32_t lockTime, int64_t mockTime, int64_t blockTime)
COutputs available for spending, stored by OutputType.
uint256 GetBlockHash() const
void SetMockTime(int64_t nMockTimeIn)
DEPRECATED Use SetMockTime with chrono type.
A transaction with a bunch of additional info that only the owner cares about.
NodeContext struct containing references to chain state and connection state.
void WaitForDeleteWallet(std::shared_ptr< CWallet > &&wallet)
Explicitly delete the wallet.
int64_t GetVirtualTransactionInputSize(const CTxIn &txin, int64_t nSigOpCost, unsigned int bytes_per_sigop)
static std::string PathToString(const path &path)
Convert path object to a byte string.
bool IsFullyValid() const
fully validate whether this is a valid public key (more expensive than IsValid()) ...
static const CAmount WALLET_INCREMENTAL_RELAY_FEE
minimum recommended increment for replacement txs
BOOST_FIXTURE_TEST_SUITE(cuckoocache_tests, BasicTestingSetup)
Test Suite for CuckooCache.
An input of a transaction.
util::Result< CreatedTransactionResult > CreateTransaction(CWallet &wallet, const std::vector< CRecipient > &vecSend, std::optional< unsigned 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...
static void PollutePubKey(CPubKey &pubkey)
BOOST_AUTO_TEST_SUITE_END()
static void TestWatchOnlyPubKey(LegacyScriptPubKeyMan *spk_man, const CPubKey &add_pubkey)
An encapsulated public key.
Fillable signing provider that keeps keys in an address->secret map.
std::variant< TxStateConfirmed, TxStateInMempool, TxStateBlockConflicted, TxStateInactive, TxStateUnrecognized > TxState
All possible CWalletTx states.
static CMutableTransaction TestSimpleSpend(const CTransaction &from, uint32_t index, const CKey &key, const CScript &pubkey)
void MakeNewKey(bool fCompressed)
Generate a new private key using a cryptographic PRNG.
static void AddTx(CWallet &wallet)
CAmount CachedTxGetImmatureCredit(const CWallet &wallet, const CWalletTx &wtx, const isminefilter &filter)
int64_t GetBlockTimeMax() const
Indicate that this wallet supports DescriptorScriptPubKeyMan.
BOOST_CHECK_EXCEPTION predicates to check the specific validation error.
std::string write(unsigned int prettyIndent=0, unsigned int indentLevel=0) const
A CWallet maintains a set of transactions and balances, and provides the ability to create new transa...
bool malformed_descriptor(std::ios_base::failure e)
unsigned int size() const
Simple read-only vector-like interface to the pubkey data.
Txid GetHash() const
Compute the hash of this CMutableTransaction.
Testing fixture that pre-creates a 100-block REGTEST-mode block chain.
MockableDatabase & GetMockableDatabase(CWallet &wallet)
std::vector< CTxOut > vout
bool AddWalletSetting(interfaces::Chain &chain, const std::string &wallet_name)
Add wallet name to persistent configuration so it will be loaded on startup.
#define WITH_LOCK(cs, code)
Run code while locking a mutex.
Descriptor with some wallet metadata.
node::BlockMap & BlockIndex() EXCLUSIVE_LOCKS_REQUIRED(
CScript GetScriptForDestination(const CTxDestination &dest)
Generate a Bitcoin scriptPubKey for the given CTxDestination.
static CTransactionRef MakeTransactionRef(Tx &&txIn)
bool RemoveWallet(WalletContext &context, const std::shared_ptr< CWallet > &wallet, std::optional< bool > load_on_start, std::vector< bilingual_str > &warnings)
CWalletTx & AddTx(CRecipient recipient)
uint160 Hash160(const T1 &in1)
Compute the 160-bit hash an object.
CAmount CachedTxGetAvailableCredit(const CWallet &wallet, const CWalletTx &wtx, const isminefilter &filter)
BOOST_FIXTURE_TEST_CASE(wallet_coinsresult_test, BasicTestingSetup)
std::unique_ptr< CWallet > CreateSyncedWallet(interfaces::Chain &chain, CChain &cchain, const CKey &key)
std::unique_ptr< WalletDatabase > CreateMockableWalletDatabase(MockableData records)
#define EXCLUSIVE_LOCKS_REQUIRED(...)
std::unique_ptr< Chain > MakeChain(node::NodeContext &node)
Return implementation of Chain interface.
BOOST_FIXTURE_TEST_CASE(wallet_sync_tx_invalid_state_test, TestingSetup)
Checks a wallet invalid state where the inputs (prev-txs) of a new arriving transaction are not marke...
#define BOOST_CHECK_EQUAL(v1, v2)
The block chain is a tree shaped structure starting with the genesis block at the root...
void pushKV(std::string key, UniValue val)
Serialized script, used inside transaction inputs and outputs.
static transaction_identifier FromUint256(const uint256 &id)
void TestUnloadWallet(std::shared_ptr< CWallet > &&wallet)
constexpr unsigned char * end()
static const unsigned int MAX_BLOCKFILE_SIZE
The maximum size of a blk?????.dat file (since 0.8)
uint256 GetRandHash() noexcept
Generate a random uint256.
A reference to a CKey: the Hash160 of its serialized public key.
void UpdateInput(CTxIn &input, const SignatureData &data)
void TestCoinsResult(ListCoinsTest &context, OutputType out_type, CAmount amount, std::map< OutputType, size_t > &expected_coins_sizes)
std::string HexStr(const Span< const uint8_t > s)
Convert a span of bytes to a lower-case hexadecimal string.
std::unique_ptr< interfaces::Handler > HandleLoadWallet(WalletContext &context, LoadWalletFn load_wallet)
constexpr CAmount DEFAULT_TRANSACTION_MAXFEE
-maxtxfee default
WalletContext struct containing references to state shared between CWallet instances, like the reference to the chain interface, and the list of opened wallets.
bool ProduceSignature(const SigningProvider &provider, const BaseSignatureCreator &creator, const CScript &fromPubKey, SignatureData &sigdata)
Produce a script signature using a generic signature creator.
interfaces::Chain * chain
A mutable version of CTransaction.
CScript GetScriptForRawPubKey(const CPubKey &pubKey)
Generate a P2PK script for the given pubkey.
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
FlatFilePos GetBlockPos() const EXCLUSIVE_LOCKS_REQUIRED(
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)
BOOST_AUTO_TEST_CASE(bnb_search_test)
UniValue HandleRequest(const JSONRPCRequest &request) const
std::string EncodeSecret(const CKey &key)
static bool RunWithinTxn(WalletBatch &batch, std::string_view process_desc, const std::function< bool(WalletBatch &)> &func)
RecursiveMutex cs_main
Mutex to guard access to validation specific variables, such as reading or changing the chainstate...
bool AddWallet(WalletContext &context, const std::shared_ptr< CWallet > &wallet)
Testing setup that configures a complete environment.
std::unique_ptr< ChainstateManager > chainman
std::string ToString(const T &t)
Locale-independent version of std::to_string.
virtual bool AddKey(const CKey &key)
std::unique_ptr< WalletDatabase > MakeWalletDatabase(const std::string &name, const DatabaseOptions &options, DatabaseStatus &status, bilingual_str &error_string)
std::map< CTxDestination, std::vector< COutput > > ListCoins(const CWallet &wallet)
Return list of available coins and locked coins grouped by non-change output address.
#define Assert(val)
Identity function.
#define BOOST_CHECK(expr)
static constexpr CAmount COIN
The amount of satoshis in one BTC.
bool IsCompressed() const
Check whether this is a compressed public key.
const uint256 * phashBlock
pointer to the hash of the block, if any. Memory is owned by this CBlockIndex