mirror of
https://github.com/bitcoin/bitcoin.git
synced 2026-01-19 23:03:45 +01:00
Implicitly know about P2WPKH redeemscripts
Make CKeyStore automatically known about the redeemscripts necessary for P2SH-P2WPKH (and due to the extra checks in IsMine, also P2WPKH) spending.
This commit is contained in:
@@ -11,6 +11,31 @@ bool CKeyStore::AddKey(const CKey &key) {
|
||||
return AddKeyPubKey(key, key.GetPubKey());
|
||||
}
|
||||
|
||||
void CBasicKeyStore::ImplicitlyLearnRelatedKeyScripts(const CPubKey& pubkey)
|
||||
{
|
||||
AssertLockHeld(cs_KeyStore);
|
||||
CKeyID key_id = pubkey.GetID();
|
||||
// We must actually know about this key already.
|
||||
assert(HaveKey(key_id) || mapWatchKeys.count(key_id));
|
||||
// This adds the redeemscripts necessary to detect P2WPKH and P2SH-P2WPKH
|
||||
// outputs. Technically P2WPKH outputs don't have a redeemscript to be
|
||||
// spent. However, our current IsMine logic requires the corresponding
|
||||
// P2SH-P2WPKH redeemscript to be present in the wallet in order to accept
|
||||
// payment even to P2WPKH outputs.
|
||||
// Also note that having superfluous scripts in the keystore never hurts.
|
||||
// They're only used to guide recursion in signing and IsMine logic - if
|
||||
// a script is present but we can't do anything with it, it has no effect.
|
||||
// "Implicitly" refers to fact that scripts are derived automatically from
|
||||
// existing keys, and are present in memory, even without being explicitly
|
||||
// loaded (e.g. from a file).
|
||||
if (pubkey.IsCompressed()) {
|
||||
CScript script = GetScriptForDestination(WitnessV0KeyHash(key_id));
|
||||
// This does not use AddCScript, as it may be overridden.
|
||||
CScriptID id(script);
|
||||
mapScripts[id] = std::move(script);
|
||||
}
|
||||
}
|
||||
|
||||
bool CBasicKeyStore::GetPubKey(const CKeyID &address, CPubKey &vchPubKeyOut) const
|
||||
{
|
||||
CKey key;
|
||||
@@ -31,6 +56,7 @@ bool CBasicKeyStore::AddKeyPubKey(const CKey& key, const CPubKey &pubkey)
|
||||
{
|
||||
LOCK(cs_KeyStore);
|
||||
mapKeys[pubkey.GetID()] = key;
|
||||
ImplicitlyLearnRelatedKeyScripts(pubkey);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -110,8 +136,10 @@ bool CBasicKeyStore::AddWatchOnly(const CScript &dest)
|
||||
LOCK(cs_KeyStore);
|
||||
setWatchOnly.insert(dest);
|
||||
CPubKey pubKey;
|
||||
if (ExtractPubKey(dest, pubKey))
|
||||
if (ExtractPubKey(dest, pubKey)) {
|
||||
mapWatchKeys[pubKey.GetID()] = pubKey;
|
||||
ImplicitlyLearnRelatedKeyScripts(pubKey);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -120,8 +148,11 @@ bool CBasicKeyStore::RemoveWatchOnly(const CScript &dest)
|
||||
LOCK(cs_KeyStore);
|
||||
setWatchOnly.erase(dest);
|
||||
CPubKey pubKey;
|
||||
if (ExtractPubKey(dest, pubKey))
|
||||
if (ExtractPubKey(dest, pubKey)) {
|
||||
mapWatchKeys.erase(pubKey.GetID());
|
||||
}
|
||||
// Related CScripts are not removed; having superfluous scripts around is
|
||||
// harmless (see comment in ImplicitlyLearnRelatedKeyScripts).
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user