Coverage Report

Created: 2026-04-29 19:21

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/tmp/bitcoin/src/wallet/test/util.cpp
Line
Count
Source
1
// Copyright (c) 2021-present The Bitcoin Core developers
2
// Distributed under the MIT software license, see the accompanying
3
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
4
5
#include <wallet/test/util.h>
6
7
#include <chain.h>
8
#include <key.h>
9
#include <key_io.h>
10
#include <streams.h>
11
#include <test/util/setup_common.h>
12
#include <validationinterface.h>
13
#include <wallet/context.h>
14
#include <wallet/wallet.h>
15
#include <wallet/walletdb.h>
16
17
#include <sqlite3.h>
18
19
#include <memory>
20
21
namespace wallet {
22
std::unique_ptr<CWallet> CreateSyncedWallet(interfaces::Chain& chain, CChain& cchain, const CKey& key)
23
4
{
24
4
    auto wallet = std::make_unique<CWallet>(&chain, "", CreateMockableWalletDatabase());
25
4
    {
26
4
        LOCK2(wallet->cs_wallet, ::cs_main);
27
4
        wallet->SetLastBlockProcessed(cchain.Height(), cchain.Tip()->GetBlockHash());
28
4
    }
29
4
    {
30
4
        LOCK(wallet->cs_wallet);
31
4
        wallet->SetWalletFlag(WALLET_FLAG_DESCRIPTORS);
32
4
        wallet->SetupDescriptorScriptPubKeyMans();
33
34
4
        FlatSigningProvider provider;
35
4
        std::string error;
36
4
        auto descs = Parse("combo(" + EncodeSecret(key) + ")", provider, error, /* require_checksum=*/ false);
37
4
        assert(descs.size() == 1);
38
4
        auto& desc = descs.at(0);
39
4
        WalletDescriptor w_desc(std::move(desc), 0, 0, 1, 1);
40
4
        Assert(wallet->AddWalletDescriptor(w_desc, provider, "", false));
41
4
    }
42
0
    WalletRescanReserver reserver(*wallet);
43
4
    reserver.reserve();
44
4
    CWallet::ScanResult result = wallet->ScanForWalletTransactions(cchain.Genesis()->GetBlockHash(), /*start_height=*/0, /*max_height=*/{}, reserver, /*fUpdate=*/false, /*save_progress=*/false);
45
4
    assert(result.status == CWallet::ScanResult::SUCCESS);
46
4
    assert(result.last_scanned_block == cchain.Tip()->GetBlockHash());
47
4
    assert(*result.last_scanned_height == cchain.Height());
48
4
    assert(result.last_failed_block.IsNull());
49
4
    return wallet;
50
4
}
51
52
std::shared_ptr<CWallet> TestCreateWallet(std::unique_ptr<WalletDatabase> database, WalletContext& context, uint64_t create_flags)
53
3
{
54
3
    bilingual_str _error;
55
3
    std::vector<bilingual_str> _warnings;
56
3
    auto wallet = CWallet::CreateNew(context, "", std::move(database), create_flags, _error, _warnings);
57
3
    NotifyWalletLoaded(context, wallet);
58
3
    if (context.chain) {
59
2
        wallet->postInitProcess();
60
2
    }
61
3
    return wallet;
62
3
}
63
64
std::shared_ptr<CWallet> TestCreateWallet(WalletContext& context)
65
3
{
66
3
    DatabaseOptions options;
67
3
    options.require_create = true;
68
3
    options.create_flags = WALLET_FLAG_DESCRIPTORS;
69
3
    DatabaseStatus status;
70
3
    bilingual_str error;
71
3
    std::vector<bilingual_str> warnings;
72
3
    auto database = MakeWalletDatabase("", options, status, error);
73
3
    return TestCreateWallet(std::move(database), context, options.create_flags);
74
3
}
75
76
77
std::shared_ptr<CWallet> TestLoadWallet(std::unique_ptr<WalletDatabase> database, WalletContext& context)
78
2
{
79
2
    bilingual_str error;
80
2
    std::vector<bilingual_str> warnings;
81
2
    auto wallet = CWallet::LoadExisting(context, "", std::move(database), error, warnings);
82
2
    NotifyWalletLoaded(context, wallet);
83
2
    if (context.chain) {
84
2
        wallet->postInitProcess();
85
2
    }
86
2
    return wallet;
87
2
}
88
89
std::shared_ptr<CWallet> TestLoadWallet(WalletContext& context)
90
2
{
91
2
    DatabaseOptions options;
92
2
    options.require_existing = true;
93
2
    DatabaseStatus status;
94
2
    bilingual_str error;
95
2
    std::vector<bilingual_str> warnings;
96
2
    auto database = MakeWalletDatabase("", options, status, error);
97
2
    return TestLoadWallet(std::move(database), context);
98
2
}
99
100
void TestUnloadWallet(std::shared_ptr<CWallet>&& wallet)
101
4
{
102
    // Calls SyncWithValidationInterfaceQueue
103
4
    wallet->chain().waitForNotificationsIfTipChanged({});
104
4
    wallet->m_chain_notifications_handler.reset();
105
4
    WaitForDeleteWallet(std::move(wallet));
106
4
}
107
108
std::unique_ptr<WalletDatabase> DuplicateMockDatabase(WalletDatabase& database)
109
0
{
110
0
    std::unique_ptr<DatabaseBatch> batch_orig = database.MakeBatch();
111
0
    std::unique_ptr<DatabaseCursor> cursor_orig = batch_orig->GetNewCursor();
112
113
0
    std::unique_ptr<WalletDatabase> new_db = CreateMockableWalletDatabase();
114
0
    std::unique_ptr<DatabaseBatch> new_db_batch = new_db->MakeBatch();
115
0
    MockableSQLiteBatch* batch_new = dynamic_cast<MockableSQLiteBatch*>(new_db_batch.get());
116
0
    Assert(batch_new);
117
118
0
    while (true) {
119
0
        DataStream key, value;
120
0
        DatabaseCursor::Status status = cursor_orig->Next(key, value);
121
0
        Assert(status != DatabaseCursor::Status::FAIL);
122
0
        if (status != DatabaseCursor::Status::MORE) break;
123
0
        batch_new->WriteKey(std::move(key), std::move(value));
124
0
    }
125
126
0
    return new_db;
127
0
}
128
129
std::string getnewaddress(CWallet& w)
130
0
{
131
0
    constexpr auto output_type = OutputType::BECH32;
132
0
    return EncodeDestination(getNewDestination(w, output_type));
133
0
}
134
135
CTxDestination getNewDestination(CWallet& w, OutputType output_type)
136
0
{
137
0
    return *Assert(w.GetNewDestination(output_type, ""));
138
0
}
139
140
MockableSQLiteDatabase::MockableSQLiteDatabase()
141
75
    : SQLiteDatabase(fs::PathFromString("mock/"), fs::PathFromString("mock/wallet.dat"), DatabaseOptions(), SQLITE_OPEN_MEMORY)
142
75
{}
143
144
std::unique_ptr<WalletDatabase> CreateMockableWalletDatabase()
145
75
{
146
75
    return std::make_unique<MockableSQLiteDatabase>();
147
75
}
148
149
wallet::DescriptorScriptPubKeyMan* CreateDescriptor(CWallet& keystore, const std::string& desc_str, const bool success)
150
20
{
151
20
    keystore.SetWalletFlag(WALLET_FLAG_DESCRIPTORS);
152
153
20
    FlatSigningProvider keys;
154
20
    std::string error;
155
20
    auto parsed_descs = Parse(desc_str, keys, error, false);
156
20
    Assert(success == (!parsed_descs.empty()));
157
20
    if (!success) return nullptr;
158
14
    auto& desc = parsed_descs.at(0);
159
160
14
    const int64_t range_start = 0, range_end = 1, next_index = 0, timestamp = 1;
161
162
14
    WalletDescriptor w_desc(std::move(desc), timestamp, range_start, range_end, next_index);
163
164
14
    LOCK(keystore.cs_wallet);
165
14
    auto spkm = Assert(keystore.AddWalletDescriptor(w_desc, keys,/*label=*/"", /*internal=*/false));
166
14
    return &spkm.value().get();
167
20
};
168
} // namespace wallet