@ -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 ( ) ;
}
}
}