Skip to content

Commit 7a30e0f

Browse files
committed
Merge #14821: Replace CAffectedKeysVisitor with descriptor based logic
0e75f44 Replace CAffectedKeysVisitor with descriptor based logic (Pieter Wuille) Pull request description: It seems we don't need a custom visitor pattern anymore to find what keys are affected by a script. Instead, infer the descriptor, and see which keys it expands to. Tree-SHA512: 8a52f61fb74e8ebfd8d02e759629e423ced6bd7d9a9ee7c4bdd2cca8465bc27b951cc69c8d835244a611ba55c6d22f83b81acef05487cb988c88c0951b797699
2 parents a5aea96 + 0e75f44 commit 7a30e0f

File tree

1 file changed

+13
-67
lines changed

1 file changed

+13
-67
lines changed

src/wallet/wallet.cpp

Lines changed: 13 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include <policy/rbf.h>
2323
#include <primitives/block.h>
2424
#include <primitives/transaction.h>
25+
#include <script/descriptor.h>
2526
#include <script/script.h>
2627
#include <shutdown.h>
2728
#include <timedata.h>
@@ -104,67 +105,17 @@ std::string COutput::ToString() const
104105
return strprintf("COutput(%s, %d, %d) [%s]", tx->GetHash().ToString(), i, nDepth, FormatMoney(tx->tx->vout[i].nValue));
105106
}
106107

107-
/** A class to identify which pubkeys a script and a keystore have in common. */
108-
class CAffectedKeysVisitor : public boost::static_visitor<void> {
109-
private:
110-
const CKeyStore &keystore;
111-
std::vector<CKeyID> &vKeys;
112-
113-
public:
114-
/**
115-
* @param[in] keystoreIn The CKeyStore that is queried for the presence of a pubkey.
116-
* @param[out] vKeysIn A vector to which a script's pubkey identifiers are appended if they are in the keystore.
117-
*/
118-
CAffectedKeysVisitor(const CKeyStore &keystoreIn, std::vector<CKeyID> &vKeysIn) : keystore(keystoreIn), vKeys(vKeysIn) {}
119-
120-
/**
121-
* Apply the visitor to each destination in a script, recursively to the redeemscript
122-
* in the case of p2sh destinations.
123-
* @param[in] script The CScript from which destinations are extracted.
124-
* @post Any CKeyIDs that script and keystore have in common are appended to the visitor's vKeys.
125-
*/
126-
void Process(const CScript &script) {
127-
txnouttype type;
128-
std::vector<CTxDestination> vDest;
129-
int nRequired;
130-
if (ExtractDestinations(script, type, vDest, nRequired)) {
131-
for (const CTxDestination &dest : vDest)
132-
boost::apply_visitor(*this, dest);
133-
}
134-
}
135-
136-
void operator()(const CKeyID &keyId) {
137-
if (keystore.HaveKey(keyId))
138-
vKeys.push_back(keyId);
139-
}
140-
141-
void operator()(const CScriptID &scriptId) {
142-
CScript script;
143-
if (keystore.GetCScript(scriptId, script))
144-
Process(script);
145-
}
146-
147-
void operator()(const WitnessV0ScriptHash& scriptID)
148-
{
149-
CScriptID id;
150-
CRIPEMD160().Write(scriptID.begin(), 32).Finalize(id.begin());
151-
CScript script;
152-
if (keystore.GetCScript(id, script)) {
153-
Process(script);
154-
}
155-
}
156-
157-
void operator()(const WitnessV0KeyHash& keyid)
158-
{
159-
CKeyID id(keyid);
160-
if (keystore.HaveKey(id)) {
161-
vKeys.push_back(id);
162-
}
108+
std::vector<CKeyID> GetAffectedKeys(const CScript& spk, const SigningProvider& provider)
109+
{
110+
std::vector<CScript> dummy;
111+
FlatSigningProvider out;
112+
InferDescriptor(spk, provider)->Expand(0, DUMMY_SIGNING_PROVIDER, dummy, out);
113+
std::vector<CKeyID> ret;
114+
for (const auto& entry : out.pubkeys) {
115+
ret.push_back(entry.first);
163116
}
164-
165-
template<typename X>
166-
void operator()(const X &none) {}
167-
};
117+
return ret;
118+
}
168119

169120
const CWalletTx* CWallet::GetWalletTx(const uint256& hash) const
170121
{
@@ -977,9 +928,7 @@ bool CWallet::AddToWalletIfInvolvingMe(const CTransactionRef& ptx, const CBlockI
977928
// loop though all outputs
978929
for (const CTxOut& txout: tx.vout) {
979930
// extract addresses and check if they match with an unused keypool key
980-
std::vector<CKeyID> vAffected;
981-
CAffectedKeysVisitor(*this, vAffected).Process(txout.scriptPubKey);
982-
for (const CKeyID &keyid : vAffected) {
931+
for (const auto& keyid : GetAffectedKeys(txout.scriptPubKey, *this)) {
983932
std::map<CKeyID, int64_t>::const_iterator mi = m_pool_key_to_index.find(keyid);
984933
if (mi != m_pool_key_to_index.end()) {
985934
WalletLogPrintf("%s: Detected a used keypool key, mark all keypool key up to this key as used\n", __func__);
@@ -3711,7 +3660,6 @@ void CWallet::GetKeyBirthTimes(interfaces::Chain::Lock& locked_chain, std::map<C
37113660
return;
37123661

37133662
// find first block that affects those keys, if there are any left
3714-
std::vector<CKeyID> vAffected;
37153663
for (const auto& entry : mapWallet) {
37163664
// iterate over all wallet transactions...
37173665
const CWalletTx &wtx = entry.second;
@@ -3721,14 +3669,12 @@ void CWallet::GetKeyBirthTimes(interfaces::Chain::Lock& locked_chain, std::map<C
37213669
int nHeight = pindex->nHeight;
37223670
for (const CTxOut &txout : wtx.tx->vout) {
37233671
// iterate over all their outputs
3724-
CAffectedKeysVisitor(*this, vAffected).Process(txout.scriptPubKey);
3725-
for (const CKeyID &keyid : vAffected) {
3672+
for (const auto &keyid : GetAffectedKeys(txout.scriptPubKey, *this)) {
37263673
// ... and all their affected keys
37273674
std::map<CKeyID, CBlockIndex*>::iterator rit = mapKeyFirstBlock.find(keyid);
37283675
if (rit != mapKeyFirstBlock.end() && nHeight < rit->second->nHeight)
37293676
rit->second = pindex;
37303677
}
3731-
vAffected.clear();
37323678
}
37333679
}
37343680
}

0 commit comments

Comments
 (0)