Skip to content

Commit e98d1d6

Browse files
author
MarcoFalke
committed
Merge #19425: refactor: Get rid of more redundant chain methods
5baa88f test: Remove no longer needed MakeChain calls (Russell Yanofsky) 6965f13 refactor: Replace uses ChainActive() in interfaces/chain.cpp (Russell Yanofsky) 3fbbb9a refactor: Get rid of more redundant chain methods (Russell Yanofsky) Pull request description: This just drops three interfaces::Chain methods replacing them with other calls. Motivation for removing these chain methods: - Need to get rid of findFirstBlockWithTimeAndHeight for #10102, which doesn't support overloaded methods - Followup from bitcoin/bitcoin#16426 (comment) - phantomcircuit comments about findNextBlock test http://www.erisian.com.au/bitcoin-core-dev/log-2020-06-06.html#l-214 Behavior is not changing in any way here. A TODO comment in ScanForWalletTransactions was removed, but just because it was invalid (see bitcoin/bitcoin#19195 (comment)), not because it was implemented. ACKs for top commit: MarcoFalke: re-ACK 5baa88f 🕶 dongcarl: ACK 5baa88f Tree-SHA512: d20a2a8cf8742e6100c6d3a4871ed67f184925712cf9e55d301abee60353bf3f74cd0d46a13be1715d1c2faef72102bb321654d08a128c2ef6880f72b72a6687
2 parents 16b31cc + 5baa88f commit e98d1d6

13 files changed

+101
-150
lines changed

src/bench/wallet_balance.cpp

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,15 +24,13 @@ static void WalletBalance(benchmark::Bench& bench, const bool set_dirty, const b
2424

2525
const auto& ADDRESS_WATCHONLY = ADDRESS_BCRT1_UNSPENDABLE;
2626

27-
NodeContext node;
28-
std::unique_ptr<interfaces::Chain> chain = interfaces::MakeChain(node);
29-
CWallet wallet{chain.get(), "", CreateMockWalletDatabase()};
27+
CWallet wallet{test_setup.m_node.chain.get(), "", CreateMockWalletDatabase()};
3028
{
3129
wallet.SetupLegacyScriptPubKeyMan();
3230
bool first_run;
3331
if (wallet.LoadWallet(first_run) != DBErrors::LOAD_OK) assert(false);
3432
}
35-
auto handler = chain->handleNotifications({&wallet, [](CWallet*) {}});
33+
auto handler = test_setup.m_node.chain->handleNotifications({&wallet, [](CWallet*) {}});
3634

3735
const Optional<std::string> address_mine{add_mine ? Optional<std::string>{getnewaddress(wallet)} : nullopt};
3836
if (add_watchonly) importaddress(wallet, ADDRESS_WATCHONLY);

src/interfaces/chain.h

Lines changed: 9 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,10 @@ class FoundBlock
4444
FoundBlock& time(int64_t& time) { m_time = &time; return *this; }
4545
FoundBlock& maxTime(int64_t& max_time) { m_max_time = &max_time; return *this; }
4646
FoundBlock& mtpTime(int64_t& mtp_time) { m_mtp_time = &mtp_time; return *this; }
47+
//! Return whether block is in the active (most-work) chain.
48+
FoundBlock& inActiveChain(bool& in_active_chain) { m_in_active_chain = &in_active_chain; return *this; }
49+
//! Return next block in the active chain if current block is in the active chain.
50+
FoundBlock& nextBlock(const FoundBlock& next_block) { m_next_block = &next_block; return *this; }
4751
//! Read block data from disk. If the block exists but doesn't have data
4852
//! (for example due to pruning), the CBlock variable will be set to null.
4953
FoundBlock& data(CBlock& data) { m_data = &data; return *this; }
@@ -53,6 +57,8 @@ class FoundBlock
5357
int64_t* m_time = nullptr;
5458
int64_t* m_max_time = nullptr;
5559
int64_t* m_mtp_time = nullptr;
60+
bool* m_in_active_chain = nullptr;
61+
const FoundBlock* m_next_block = nullptr;
5662
CBlock* m_data = nullptr;
5763
};
5864

@@ -77,9 +83,9 @@ class FoundBlock
7783
//! wallet cache it, fee estimation being driven by node mempool, wallet
7884
//! should be the consumer.
7985
//!
80-
//! * The `guessVerificationProgress`, `getBlockHeight`, `getBlockHash`, etc
81-
//! methods can go away if rescan logic is moved on the node side, and wallet
82-
//! only register rescan request.
86+
//! * `guessVerificationProgress` and similar methods can go away if rescan
87+
//! logic moves out of the wallet, and the wallet just requests scans from the
88+
//! node (https://github.com/bitcoin/bitcoin/issues/11756)
8389
class Chain
8490
{
8591
public:
@@ -90,25 +96,13 @@ class Chain
9096
//! any blocks)
9197
virtual Optional<int> getHeight() = 0;
9298

93-
//! Get block height above genesis block. Returns 0 for genesis block,
94-
//! 1 for following block, and so on. Returns nullopt for a block not
95-
//! included in the current chain.
96-
virtual Optional<int> getBlockHeight(const uint256& hash) = 0;
97-
9899
//! Get block hash. Height must be valid or this function will abort.
99100
virtual uint256 getBlockHash(int height) = 0;
100101

101102
//! Check that the block is available on disk (i.e. has not been
102103
//! pruned), and contains transactions.
103104
virtual bool haveBlockOnDisk(int height) = 0;
104105

105-
//! Return height of the first block in the chain with timestamp equal
106-
//! or greater than the given time and height equal or greater than the
107-
//! given height, or nullopt if there is no block with a high enough
108-
//! timestamp and height. Also return the block hash as an optional output parameter
109-
//! (to avoid the cost of a second lookup in case this information is needed.)
110-
virtual Optional<int> findFirstBlockWithTimeAndHeight(int64_t time, int height, uint256* hash) = 0;
111-
112106
//! Get locator for the current chain tip.
113107
virtual CBlockLocator getTipLocator() = 0;
114108

@@ -130,11 +124,6 @@ class Chain
130124
//! information.
131125
virtual bool findFirstBlockWithTimeAndHeight(int64_t min_time, int min_height, const FoundBlock& block={}) = 0;
132126

133-
//! Find next block if block is part of current chain. Also flag if
134-
//! there was a reorg and the specified block hash is no longer in the
135-
//! current chain, and optionally return block information.
136-
virtual bool findNextBlock(const uint256& block_hash, int block_height, const FoundBlock& next={}, bool* reorg=nullptr) = 0;
137-
138127
//! Find ancestor of block at specified height and optionally return
139128
//! ancestor information.
140129
virtual bool findAncestorByHeight(const uint256& block_hash, int ancestor_height, const FoundBlock& ancestor_out={}) = 0;

src/node/interfaces.cpp

Lines changed: 26 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -303,14 +303,16 @@ class NodeImpl : public Node
303303
util::Ref m_context_ref;
304304
};
305305

306-
bool FillBlock(const CBlockIndex* index, const FoundBlock& block, UniqueLock<RecursiveMutex>& lock)
306+
bool FillBlock(const CBlockIndex* index, const FoundBlock& block, UniqueLock<RecursiveMutex>& lock, const CChain& active)
307307
{
308308
if (!index) return false;
309309
if (block.m_hash) *block.m_hash = index->GetBlockHash();
310310
if (block.m_height) *block.m_height = index->nHeight;
311311
if (block.m_time) *block.m_time = index->GetBlockTime();
312312
if (block.m_max_time) *block.m_max_time = index->GetBlockTimeMax();
313313
if (block.m_mtp_time) *block.m_mtp_time = index->GetMedianTimePast();
314+
if (block.m_in_active_chain) *block.m_in_active_chain = active[index->nHeight] == index;
315+
if (block.m_next_block) FillBlock(active[index->nHeight] == index ? active[index->nHeight + 1] : nullptr, *block.m_next_block, lock, active);
314316
if (block.m_data) {
315317
REVERSE_LOCK(lock);
316318
if (!ReadBlockFromDisk(*block.m_data, index, Params().GetConsensus())) block.m_data->SetNull();
@@ -413,48 +415,33 @@ class ChainImpl : public Chain
413415
Optional<int> getHeight() override
414416
{
415417
LOCK(::cs_main);
416-
int height = ::ChainActive().Height();
418+
const CChain& active = Assert(m_node.chainman)->ActiveChain();
419+
int height = active.Height();
417420
if (height >= 0) {
418421
return height;
419422
}
420423
return nullopt;
421424
}
422-
Optional<int> getBlockHeight(const uint256& hash) override
423-
{
424-
LOCK(::cs_main);
425-
CBlockIndex* block = LookupBlockIndex(hash);
426-
if (block && ::ChainActive().Contains(block)) {
427-
return block->nHeight;
428-
}
429-
return nullopt;
430-
}
431425
uint256 getBlockHash(int height) override
432426
{
433427
LOCK(::cs_main);
434-
CBlockIndex* block = ::ChainActive()[height];
428+
const CChain& active = Assert(m_node.chainman)->ActiveChain();
429+
CBlockIndex* block = active[height];
435430
assert(block);
436431
return block->GetBlockHash();
437432
}
438433
bool haveBlockOnDisk(int height) override
439434
{
440435
LOCK(cs_main);
441-
CBlockIndex* block = ::ChainActive()[height];
436+
const CChain& active = Assert(m_node.chainman)->ActiveChain();
437+
CBlockIndex* block = active[height];
442438
return block && ((block->nStatus & BLOCK_HAVE_DATA) != 0) && block->nTx > 0;
443439
}
444-
Optional<int> findFirstBlockWithTimeAndHeight(int64_t time, int height, uint256* hash) override
445-
{
446-
LOCK(cs_main);
447-
CBlockIndex* block = ::ChainActive().FindEarliestAtLeast(time, height);
448-
if (block) {
449-
if (hash) *hash = block->GetBlockHash();
450-
return block->nHeight;
451-
}
452-
return nullopt;
453-
}
454440
CBlockLocator getTipLocator() override
455441
{
456442
LOCK(cs_main);
457-
return ::ChainActive().GetLocator();
443+
const CChain& active = Assert(m_node.chainman)->ActiveChain();
444+
return active.GetLocator();
458445
}
459446
bool checkFinalTx(const CTransaction& tx) override
460447
{
@@ -464,55 +451,54 @@ class ChainImpl : public Chain
464451
Optional<int> findLocatorFork(const CBlockLocator& locator) override
465452
{
466453
LOCK(cs_main);
467-
if (CBlockIndex* fork = FindForkInGlobalIndex(::ChainActive(), locator)) {
454+
const CChain& active = Assert(m_node.chainman)->ActiveChain();
455+
if (CBlockIndex* fork = FindForkInGlobalIndex(active, locator)) {
468456
return fork->nHeight;
469457
}
470458
return nullopt;
471459
}
472460
bool findBlock(const uint256& hash, const FoundBlock& block) override
473461
{
474462
WAIT_LOCK(cs_main, lock);
475-
return FillBlock(LookupBlockIndex(hash), block, lock);
463+
const CChain& active = Assert(m_node.chainman)->ActiveChain();
464+
return FillBlock(LookupBlockIndex(hash), block, lock, active);
476465
}
477466
bool findFirstBlockWithTimeAndHeight(int64_t min_time, int min_height, const FoundBlock& block) override
478467
{
479468
WAIT_LOCK(cs_main, lock);
480-
return FillBlock(ChainActive().FindEarliestAtLeast(min_time, min_height), block, lock);
481-
}
482-
bool findNextBlock(const uint256& block_hash, int block_height, const FoundBlock& next, bool* reorg) override {
483-
WAIT_LOCK(cs_main, lock);
484-
CBlockIndex* block = ChainActive()[block_height];
485-
if (block && block->GetBlockHash() != block_hash) block = nullptr;
486-
if (reorg) *reorg = !block;
487-
return FillBlock(block ? ChainActive()[block_height + 1] : nullptr, next, lock);
469+
const CChain& active = Assert(m_node.chainman)->ActiveChain();
470+
return FillBlock(active.FindEarliestAtLeast(min_time, min_height), block, lock, active);
488471
}
489472
bool findAncestorByHeight(const uint256& block_hash, int ancestor_height, const FoundBlock& ancestor_out) override
490473
{
491474
WAIT_LOCK(cs_main, lock);
475+
const CChain& active = Assert(m_node.chainman)->ActiveChain();
492476
if (const CBlockIndex* block = LookupBlockIndex(block_hash)) {
493477
if (const CBlockIndex* ancestor = block->GetAncestor(ancestor_height)) {
494-
return FillBlock(ancestor, ancestor_out, lock);
478+
return FillBlock(ancestor, ancestor_out, lock, active);
495479
}
496480
}
497-
return FillBlock(nullptr, ancestor_out, lock);
481+
return FillBlock(nullptr, ancestor_out, lock, active);
498482
}
499483
bool findAncestorByHash(const uint256& block_hash, const uint256& ancestor_hash, const FoundBlock& ancestor_out) override
500484
{
501485
WAIT_LOCK(cs_main, lock);
486+
const CChain& active = Assert(m_node.chainman)->ActiveChain();
502487
const CBlockIndex* block = LookupBlockIndex(block_hash);
503488
const CBlockIndex* ancestor = LookupBlockIndex(ancestor_hash);
504489
if (block && ancestor && block->GetAncestor(ancestor->nHeight) != ancestor) ancestor = nullptr;
505-
return FillBlock(ancestor, ancestor_out, lock);
490+
return FillBlock(ancestor, ancestor_out, lock, active);
506491
}
507492
bool findCommonAncestor(const uint256& block_hash1, const uint256& block_hash2, const FoundBlock& ancestor_out, const FoundBlock& block1_out, const FoundBlock& block2_out) override
508493
{
509494
WAIT_LOCK(cs_main, lock);
495+
const CChain& active = Assert(m_node.chainman)->ActiveChain();
510496
const CBlockIndex* block1 = LookupBlockIndex(block_hash1);
511497
const CBlockIndex* block2 = LookupBlockIndex(block_hash2);
512498
const CBlockIndex* ancestor = block1 && block2 ? LastCommonAncestor(block1, block2) : nullptr;
513499
// Using & instead of && below to avoid short circuiting and leaving
514500
// output uninitialized.
515-
return FillBlock(ancestor, ancestor_out, lock) & FillBlock(block1, block1_out, lock) & FillBlock(block2, block2_out, lock);
501+
return FillBlock(ancestor, ancestor_out, lock, active) & FillBlock(block1, block1_out, lock, active) & FillBlock(block2, block2_out, lock, active);
516502
}
517503
void findCoins(std::map<COutPoint, Coin>& coins) override { return FindCoins(m_node, coins); }
518504
double guessVerificationProgress(const uint256& block_hash) override
@@ -632,7 +618,8 @@ class ChainImpl : public Chain
632618
{
633619
if (!old_tip.IsNull()) {
634620
LOCK(::cs_main);
635-
if (old_tip == ::ChainActive().Tip()->GetBlockHash()) return;
621+
const CChain& active = Assert(m_node.chainman)->ActiveChain();
622+
if (old_tip == active.Tip()->GetBlockHash()) return;
636623
}
637624
SyncWithValidationInterfaceQueue();
638625
}

src/test/interfaces_tests.cpp

Lines changed: 24 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,8 @@ BOOST_FIXTURE_TEST_SUITE(interfaces_tests, TestChain100Setup)
1717

1818
BOOST_AUTO_TEST_CASE(findBlock)
1919
{
20-
auto chain = interfaces::MakeChain(m_node);
21-
auto& active = ChainActive();
20+
auto& chain = m_node.chain;
21+
const CChain& active = Assert(m_node.chainman)->ActiveChain();
2222

2323
uint256 hash;
2424
BOOST_CHECK(chain->findBlock(active[10]->GetBlockHash(), FoundBlock().hash(hash)));
@@ -44,13 +44,25 @@ BOOST_AUTO_TEST_CASE(findBlock)
4444
BOOST_CHECK(chain->findBlock(active[60]->GetBlockHash(), FoundBlock().mtpTime(mtp_time)));
4545
BOOST_CHECK_EQUAL(mtp_time, active[60]->GetMedianTimePast());
4646

47+
bool cur_active{false}, next_active{false};
48+
uint256 next_hash;
49+
BOOST_CHECK_EQUAL(active.Height(), 100);
50+
BOOST_CHECK(chain->findBlock(active[99]->GetBlockHash(), FoundBlock().inActiveChain(cur_active).nextBlock(FoundBlock().inActiveChain(next_active).hash(next_hash))));
51+
BOOST_CHECK(cur_active);
52+
BOOST_CHECK(next_active);
53+
BOOST_CHECK_EQUAL(next_hash, active[100]->GetBlockHash());
54+
cur_active = next_active = false;
55+
BOOST_CHECK(chain->findBlock(active[100]->GetBlockHash(), FoundBlock().inActiveChain(cur_active).nextBlock(FoundBlock().inActiveChain(next_active))));
56+
BOOST_CHECK(cur_active);
57+
BOOST_CHECK(!next_active);
58+
4759
BOOST_CHECK(!chain->findBlock({}, FoundBlock()));
4860
}
4961

5062
BOOST_AUTO_TEST_CASE(findFirstBlockWithTimeAndHeight)
5163
{
52-
auto chain = interfaces::MakeChain(m_node);
53-
auto& active = ChainActive();
64+
auto& chain = m_node.chain;
65+
const CChain& active = Assert(m_node.chainman)->ActiveChain();
5466
uint256 hash;
5567
int height;
5668
BOOST_CHECK(chain->findFirstBlockWithTimeAndHeight(/* min_time= */ 0, /* min_height= */ 5, FoundBlock().hash(hash).height(height)));
@@ -59,25 +71,10 @@ BOOST_AUTO_TEST_CASE(findFirstBlockWithTimeAndHeight)
5971
BOOST_CHECK(!chain->findFirstBlockWithTimeAndHeight(/* min_time= */ active.Tip()->GetBlockTimeMax() + 1, /* min_height= */ 0));
6072
}
6173

62-
BOOST_AUTO_TEST_CASE(findNextBlock)
63-
{
64-
auto chain = interfaces::MakeChain(m_node);
65-
auto& active = ChainActive();
66-
bool reorg;
67-
uint256 hash;
68-
BOOST_CHECK(chain->findNextBlock(active[20]->GetBlockHash(), 20, FoundBlock().hash(hash), &reorg));
69-
BOOST_CHECK_EQUAL(hash, active[21]->GetBlockHash());
70-
BOOST_CHECK_EQUAL(reorg, false);
71-
BOOST_CHECK(!chain->findNextBlock(uint256(), 20, {}, &reorg));
72-
BOOST_CHECK_EQUAL(reorg, true);
73-
BOOST_CHECK(!chain->findNextBlock(active.Tip()->GetBlockHash(), active.Height(), {}, &reorg));
74-
BOOST_CHECK_EQUAL(reorg, false);
75-
}
76-
7774
BOOST_AUTO_TEST_CASE(findAncestorByHeight)
7875
{
79-
auto chain = interfaces::MakeChain(m_node);
80-
auto& active = ChainActive();
76+
auto& chain = m_node.chain;
77+
const CChain& active = Assert(m_node.chainman)->ActiveChain();
8178
uint256 hash;
8279
BOOST_CHECK(chain->findAncestorByHeight(active[20]->GetBlockHash(), 10, FoundBlock().hash(hash)));
8380
BOOST_CHECK_EQUAL(hash, active[10]->GetBlockHash());
@@ -86,8 +83,8 @@ BOOST_AUTO_TEST_CASE(findAncestorByHeight)
8683

8784
BOOST_AUTO_TEST_CASE(findAncestorByHash)
8885
{
89-
auto chain = interfaces::MakeChain(m_node);
90-
auto& active = ChainActive();
86+
auto& chain = m_node.chain;
87+
const CChain& active = Assert(m_node.chainman)->ActiveChain();
9188
int height = -1;
9289
BOOST_CHECK(chain->findAncestorByHash(active[20]->GetBlockHash(), active[10]->GetBlockHash(), FoundBlock().height(height)));
9390
BOOST_CHECK_EQUAL(height, 10);
@@ -96,8 +93,8 @@ BOOST_AUTO_TEST_CASE(findAncestorByHash)
9693

9794
BOOST_AUTO_TEST_CASE(findCommonAncestor)
9895
{
99-
auto chain = interfaces::MakeChain(m_node);
100-
auto& active = ChainActive();
96+
auto& chain = m_node.chain;
97+
const CChain& active = Assert(m_node.chainman)->ActiveChain();
10198
auto* orig_tip = active.Tip();
10299
for (int i = 0; i < 10; ++i) {
103100
BlockValidationState state;
@@ -126,8 +123,8 @@ BOOST_AUTO_TEST_CASE(findCommonAncestor)
126123

127124
BOOST_AUTO_TEST_CASE(hasBlocks)
128125
{
129-
auto chain = interfaces::MakeChain(m_node);
130-
auto& active = ChainActive();
126+
auto& chain = m_node.chain;
127+
const CChain& active = Assert(m_node.chainman)->ActiveChain();
131128

132129
// Test ranges
133130
BOOST_CHECK(chain->hasBlocks(active.Tip()->GetBlockHash(), 10, 90));

src/wallet/test/coinselector_tests.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -283,7 +283,7 @@ BOOST_AUTO_TEST_CASE(bnb_search_test)
283283
// Make sure that can use BnB when there are preset inputs
284284
empty_wallet();
285285
{
286-
std::unique_ptr<CWallet> wallet = MakeUnique<CWallet>(m_chain.get(), "", CreateMockWalletDatabase());
286+
std::unique_ptr<CWallet> wallet = MakeUnique<CWallet>(m_node.chain.get(), "", CreateMockWalletDatabase());
287287
bool firstRun;
288288
wallet->LoadWallet(firstRun);
289289
wallet->SetupLegacyScriptPubKeyMan();

src/wallet/test/init_test_fixture.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010

1111
InitWalletDirTestingSetup::InitWalletDirTestingSetup(const std::string& chainName) : BasicTestingSetup(chainName)
1212
{
13-
m_wallet_client = MakeWalletClient(*m_chain, *Assert(m_node.args));
13+
m_wallet_client = MakeWalletClient(*m_node.chain, *Assert(m_node.args));
1414

1515
std::string sep;
1616
sep += fs::path::preferred_separator;

src/wallet/test/init_test_fixture.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@ struct InitWalletDirTestingSetup: public BasicTestingSetup {
1919
fs::path m_datadir;
2020
fs::path m_cwd;
2121
std::map<std::string, fs::path> m_walletdir_path_cases;
22-
std::unique_ptr<interfaces::Chain> m_chain = interfaces::MakeChain(m_node);
2322
std::unique_ptr<interfaces::WalletClient> m_wallet_client;
2423
};
2524

src/wallet/test/ismine_tests.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,7 @@ BOOST_AUTO_TEST_CASE(ismine_standard)
2727
CKey uncompressedKey;
2828
uncompressedKey.MakeNewKey(false);
2929
CPubKey uncompressedPubkey = uncompressedKey.GetPubKey();
30-
NodeContext node;
31-
std::unique_ptr<interfaces::Chain> chain = interfaces::MakeChain(node);
30+
std::unique_ptr<interfaces::Chain>& chain = m_node.chain;
3231

3332
CScript scriptPubKey;
3433
isminetype result;

src/wallet/test/scriptpubkeyman_tests.cpp

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,7 @@ BOOST_FIXTURE_TEST_SUITE(scriptpubkeyman_tests, BasicTestingSetup)
1717
BOOST_AUTO_TEST_CASE(CanProvide)
1818
{
1919
// Set up wallet and keyman variables.
20-
NodeContext node;
21-
std::unique_ptr<interfaces::Chain> chain = interfaces::MakeChain(node);
22-
CWallet wallet(chain.get(), "", CreateDummyWalletDatabase());
20+
CWallet wallet(m_node.chain.get(), "", CreateDummyWalletDatabase());
2321
LegacyScriptPubKeyMan& keyman = *wallet.GetOrCreateLegacyScriptPubKeyMan();
2422

2523
// Make a 1 of 2 multisig script

0 commit comments

Comments
 (0)