@ -1619,7 +1619,8 @@ bool CWallet::AddToWalletIfInvolvingMe(const CTransaction& tx, const CBlock* pbl
return false ;
bool fExisted = mapWallet . count ( tx . GetHash ( ) ) ! = 0 ;
if ( fExisted & & ! fUpdate ) return false ;
auto saplingNoteDataAndAddressesToAdd = FindMySaplingNotes ( tx ) ;
std : : pair < mapSaplingNoteData_t , SaplingIncomingViewingKeyMap > saplingNoteDataAndAddressesToAdd ;
saplingNoteDataAndAddressesToAdd = fAsyncNoteDecryption ? FindMySaplingNotesAsync ( tx , nHeight ) : FindMySaplingNotes ( tx , nHeight ) ;
auto saplingNoteData = saplingNoteDataAndAddressesToAdd . first ;
auto addressesToAdd = saplingNoteDataAndAddressesToAdd . second ;
for ( const auto & addressToAdd : addressesToAdd ) {
@ -1814,6 +1815,103 @@ std::pair<mapSaplingNoteData_t, SaplingIncomingViewingKeyMap> CWallet::FindMySap
return std : : make_pair ( noteData , viewingKeysToAdd ) ;
}
static std : : pair < mapSaplingNoteData_t , SaplingIncomingViewingKeyMap > DecryptSaplingNoteWorker ( const Consensus : : Params & consensus_params , const SaplingIncomingViewingKey & ivk , const OutputDescription & outdesc , const int & height , const uint256 & hash , const uint32_t & i )
{
mapSaplingNoteData_t noteData ;
SaplingIncomingViewingKeyMap viewingKeysToAdd ;
auto result = SaplingNotePlaintext : : decrypt ( consensus_params , height , outdesc . encCiphertext , ivk , outdesc . ephemeralKey , outdesc . cmu ) ;
if ( result )
{
// We don't cache the nullifier here as computing it requires knowledge of the note position
// in the commitment tree, which can only be determined when the transaction has been mined.
SaplingOutPoint op { hash , i } ;
SaplingNoteData nd ;
nd . ivk = ivk ;
noteData . insert ( std : : make_pair ( op , nd ) ) ;
auto address = ivk . address ( result . value ( ) . d ) ;
if ( address )
{
viewingKeysToAdd . insert ( make_pair ( address . value ( ) , ivk ) ) ;
}
}
return std : : make_pair ( noteData , viewingKeysToAdd ) ;
}
/**
* Finds all output notes in the given transaction that have been sent to
* SaplingPaymentAddresses in this wallet .
*
* It should never be necessary to call this method with a CWalletTx , because
* the result of FindMySaplingNotes ( for the addresses available at the time ) will
* already have been cached in CWalletTx . mapSaplingNoteData .
*/
std : : pair < mapSaplingNoteData_t , SaplingIncomingViewingKeyMap > CWallet : : FindMySaplingNotesAsync ( const CTransaction & tx , int height ) const
{
mapSaplingNoteData_t noteData ;
SaplingIncomingViewingKeyMap viewingKeysToAdd ;
if ( tx . vShieldedOutput . empty ( ) )
{
return std : : make_pair ( noteData , viewingKeysToAdd ) ;
}
LOCK ( cs_KeyStore ) ;
std : : set < SaplingIncomingViewingKey > setSaplingIvkToTest ;
for ( const auto & [ ivk , fvk ] : mapSaplingFullViewingKeys )
{
setSaplingIvkToTest . insert ( ivk ) ;
}
for ( const auto & [ address , ivk ] : mapSaplingIncomingViewingKeys )
{
setSaplingIvkToTest . insert ( ivk ) ;
}
if ( setSaplingIvkToTest . empty ( ) )
{
return std : : make_pair ( noteData , viewingKeysToAdd ) ;
}
std : : vector < std : : future < std : : pair < mapSaplingNoteData_t , SaplingIncomingViewingKeyMap > > > vDecryptFutures ;
const Consensus : : Params consensus_params = Params ( ) . GetConsensus ( ) ;
uint256 hash = tx . GetHash ( ) ;
// Protocol Spec: 4.19 Block Chain Scanning (Sapling)
for ( uint32_t i = 0 ; i < tx . vShieldedOutput . size ( ) ; + + i )
{
const OutputDescription output = tx . vShieldedOutput [ i ] ;
for ( SaplingIncomingViewingKey ivk : setSaplingIvkToTest )
{
vDecryptFutures . emplace_back ( std : : async ( std : : launch : : async , DecryptSaplingNoteWorker , consensus_params , ivk , output , height , hash , i ) ) ;
}
}
for ( auto & fut : vDecryptFutures )
{
auto result_pair = fut . get ( ) ;
if ( ! result_pair . first . empty ( ) )
{
noteData . insert ( result_pair . first . begin ( ) , result_pair . first . end ( ) ) ;
for ( auto [ address , ivk ] : result_pair . second )
{
if ( mapSaplingIncomingViewingKeys . count ( address ) = = 0 )
{
viewingKeysToAdd [ address ] = ivk ;
}
}
}
}
return std : : make_pair ( noteData , viewingKeysToAdd ) ;
}
bool CWallet : : IsSaplingNullifierFromMe ( const uint256 & nullifier ) const
{
{