diff options
author | MeshCollider <dobsonsa68@gmail.com> | 2018-12-14 14:21:06 +1300 |
---|---|---|
committer | MeshCollider <dobsonsa68@gmail.com> | 2018-12-14 14:21:29 +1300 |
commit | 7a30e0f6c54443616fdc28b7080dcbc9b630ac77 (patch) | |
tree | 19564b3460c196e5b481f7ba358903da4fc40a97 /src/wallet | |
parent | a5aea9654f3661254a90815a85067487647fbce9 (diff) | |
parent | 0e75f44a09ed07ff5eeeb142a4cefc4aba0ddf32 (diff) | |
download | bitcoin-7a30e0f6c54443616fdc28b7080dcbc9b630ac77.tar.xz |
Merge #14821: Replace CAffectedKeysVisitor with descriptor based logic
0e75f44a0 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
Diffstat (limited to 'src/wallet')
-rw-r--r-- | src/wallet/wallet.cpp | 80 |
1 files changed, 13 insertions, 67 deletions
diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index cea6564b4e..fea0378839 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -22,6 +22,7 @@ #include <policy/rbf.h> #include <primitives/block.h> #include <primitives/transaction.h> +#include <script/descriptor.h> #include <script/script.h> #include <shutdown.h> #include <timedata.h> @@ -104,67 +105,17 @@ std::string COutput::ToString() const return strprintf("COutput(%s, %d, %d) [%s]", tx->GetHash().ToString(), i, nDepth, FormatMoney(tx->tx->vout[i].nValue)); } -/** A class to identify which pubkeys a script and a keystore have in common. */ -class CAffectedKeysVisitor : public boost::static_visitor<void> { -private: - const CKeyStore &keystore; - std::vector<CKeyID> &vKeys; - -public: - /** - * @param[in] keystoreIn The CKeyStore that is queried for the presence of a pubkey. - * @param[out] vKeysIn A vector to which a script's pubkey identifiers are appended if they are in the keystore. - */ - CAffectedKeysVisitor(const CKeyStore &keystoreIn, std::vector<CKeyID> &vKeysIn) : keystore(keystoreIn), vKeys(vKeysIn) {} - - /** - * Apply the visitor to each destination in a script, recursively to the redeemscript - * in the case of p2sh destinations. - * @param[in] script The CScript from which destinations are extracted. - * @post Any CKeyIDs that script and keystore have in common are appended to the visitor's vKeys. - */ - void Process(const CScript &script) { - txnouttype type; - std::vector<CTxDestination> vDest; - int nRequired; - if (ExtractDestinations(script, type, vDest, nRequired)) { - for (const CTxDestination &dest : vDest) - boost::apply_visitor(*this, dest); - } - } - - void operator()(const CKeyID &keyId) { - if (keystore.HaveKey(keyId)) - vKeys.push_back(keyId); - } - - void operator()(const CScriptID &scriptId) { - CScript script; - if (keystore.GetCScript(scriptId, script)) - Process(script); - } - - void operator()(const WitnessV0ScriptHash& scriptID) - { - CScriptID id; - CRIPEMD160().Write(scriptID.begin(), 32).Finalize(id.begin()); - CScript script; - if (keystore.GetCScript(id, script)) { - Process(script); - } - } - - void operator()(const WitnessV0KeyHash& keyid) - { - CKeyID id(keyid); - if (keystore.HaveKey(id)) { - vKeys.push_back(id); - } +std::vector<CKeyID> GetAffectedKeys(const CScript& spk, const SigningProvider& provider) +{ + std::vector<CScript> dummy; + FlatSigningProvider out; + InferDescriptor(spk, provider)->Expand(0, DUMMY_SIGNING_PROVIDER, dummy, out); + std::vector<CKeyID> ret; + for (const auto& entry : out.pubkeys) { + ret.push_back(entry.first); } - - template<typename X> - void operator()(const X &none) {} -}; + return ret; +} const CWalletTx* CWallet::GetWalletTx(const uint256& hash) const { @@ -977,9 +928,7 @@ bool CWallet::AddToWalletIfInvolvingMe(const CTransactionRef& ptx, const CBlockI // loop though all outputs for (const CTxOut& txout: tx.vout) { // extract addresses and check if they match with an unused keypool key - std::vector<CKeyID> vAffected; - CAffectedKeysVisitor(*this, vAffected).Process(txout.scriptPubKey); - for (const CKeyID &keyid : vAffected) { + for (const auto& keyid : GetAffectedKeys(txout.scriptPubKey, *this)) { std::map<CKeyID, int64_t>::const_iterator mi = m_pool_key_to_index.find(keyid); if (mi != m_pool_key_to_index.end()) { 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 return; // find first block that affects those keys, if there are any left - std::vector<CKeyID> vAffected; for (const auto& entry : mapWallet) { // iterate over all wallet transactions... const CWalletTx &wtx = entry.second; @@ -3721,14 +3669,12 @@ void CWallet::GetKeyBirthTimes(interfaces::Chain::Lock& locked_chain, std::map<C int nHeight = pindex->nHeight; for (const CTxOut &txout : wtx.tx->vout) { // iterate over all their outputs - CAffectedKeysVisitor(*this, vAffected).Process(txout.scriptPubKey); - for (const CKeyID &keyid : vAffected) { + for (const auto &keyid : GetAffectedKeys(txout.scriptPubKey, *this)) { // ... and all their affected keys std::map<CKeyID, CBlockIndex*>::iterator rit = mapKeyFirstBlock.find(keyid); if (rit != mapKeyFirstBlock.end() && nHeight < rit->second->nHeight) rit->second = pindex; } - vAffected.clear(); } } } |