{
{
AssertLockHeld(cs_wallet);
+ AssertLockHeld(cs_main);
uint256 txHash = tx.GetHash();
bool fExisted = mapWallet.count(txHash) != 0;
if (fExisted && !fUpdate) return false;
}
}
- bool canSign = false;
- bool isMine = false;
-
for (auto output : tx.vout)
{
bool canSpend = false;
if (output.scriptPubKey.IsPayToCryptoCondition(p) && p.IsValid() && p.version >= p.VERSION_V3)
{
- // assert and fix if we find any spot where this wouldn't be held, rather than
- // creating a deadlock by attempting to take the cs out of order
- AssertLockHeld(cs_main);
-
uint32_t nHeight = 0;
if (pblock)
{
}
else
{
- // doesn't seem like this should ever happen
+ // this should never happen
assert(false);
}
}
if (p.evalCode == EVAL_IDENTITY_PRIMARY && p.vData.size() && (*(CIdentity *)&identity = CIdentity(p.vData[0])).IsValid())
{
- identity.txid = tx.GetHash();
+ identity.txid = txHash;
CIdentityMapKey idMapKey = CIdentityMapKey(identity.GetID(),
nHeight,
1,
std::pair<CIdentityMapKey, CIdentityMapValue> idHistory;
- // if we are deleting, current identity is what it was, idHistory is what it will be, if adding, current is what it will be, idHistory is what it was
+ // if adding, current is what it will be, idHistory is what it was
+ // if we are deleting, current identity is what it was, idHistory is what it will be
std::pair<bool, bool> wasCanSignCanSpend({false, false});
std::pair<bool, bool> canSignCanSpend(CheckAuthority(identity));
- // if it is revoked, consider the recovery authority in the can sign/can spend decision
+ // if the new identity is revoked, the recovery identity holds can sign/can spend authority
if (identity.IsRevoked())
{
- // if it's revoked, default will be no authority, and we will only have authority if
- // we have recovery identity in this wallet
+ // if it's revoked, default is no authority for primary addresses, but we will have authority if
+ // we have control over the recovery identity
std::pair<CIdentityMapKey, CIdentityMapValue> recoveryAuthority;
if (GetIdentity(identity.recoveryAuthority, recoveryAuthority, nHeight ? nHeight : INT_MAX))
{
{
wasCanSignCanSpend = CheckAuthority(idHistory.second);
- if (idHistory.second.IsRevoked() && !(wasCanSignCanSpend.first && wasCanSignCanSpend.second))
+ if (idHistory.second.IsRevoked())
{
std::pair<CIdentityMapKey, CIdentityMapValue> oldRecoveryAuthority;
std::pair<bool, bool> auxCSCS;
}
}
- // if this is the initial registration, delete all other instances of the ID
+ // if this is an add of the initial registration, delete all other instances of the ID
if (CNameReservation(tx).IsValid())
{
while (GetIdentity(idID, idHistory))
{
+ // any definition of this identity in this wallet must be
+ // invalid now
RemoveIdentity(idHistory.first, idHistory.second.txid);
+ if (idHistory.second.txid != txHash)
+ {
+ // any definition of this ID in this wallet that is not this definition
+ // must also be on an invalid transaction
+ EraseFromWallet(idHistory.second.txid);
+ }
// set wasCanSignCanSpend to true, true to delete any dependent transactions
wasCanSignCanSpend = {true, true};
}
idHistory = std::pair<CIdentityMapKey, CIdentityMapValue>();
+ wasCanSignCanSpend = std::pair<bool, bool>({false, false});
}
+
else if (nHeight && idHistory.first.blockHeight == nHeight && idHistory.second.txid != identity.txid)
{
// this is one of more than one identity records in the same block
{
if (canSignCanSpend.first)
{
- // add all UTXOs that are sent to this address to this wallet
+ // add all UTXOs sent to this address to this wallet
std::vector<std::pair<CAddressUnspentKey, CAddressUnspentValue>> unspentOutputs;
if (GetAddressUnspent(idID, CScript::P2ID, unspentOutputs))
{
CTransaction newTx;
if (myGetTransaction(newOut.first.txhash, newTx, blkHash))
{
- auto sprNoteData = FindMySproutNotes(newTx);
- auto sapNoteDataAndAddressesToAdd = FindMySaplingNotes(newTx);
- auto sapNoteData = sapNoteDataAndAddressesToAdd.first;
- auto addrsToAdd = sapNoteDataAndAddressesToAdd.second;
- for (const auto &addressToAdd : addrsToAdd)
- {
- AddSaplingIncomingViewingKey(addressToAdd.second, addressToAdd.first);
- }
-
CWalletTx wtx(this, newTx);
- if (sprNoteData.size() > 0) {
- wtx.SetSproutNoteData(sprNoteData);
- }
-
- if (sapNoteData.size() > 0) {
- wtx.SetSaplingNoteData(sapNoteData);
- }
-
// Get merkle branch if transaction was found in a block
CBlock block;
auto blkIndexIt = mapBlockIndex.find(blkHash);
continue;
}
- // if the tx is from this wallet, we will not erase it
- if (IsFromMe(txidAndWtx.second))
- {
- continue;
- }
-
txnouttype txType;
std::vector<CTxDestination> addresses;
int minSigs;
bool eraseTx = true;
- std::vector<CIdentityID> oneTxIDs;
int i = 0;
uint256 hashTx = txidAndWtx.second.GetHash();
+ // if we still have z-address notes on the transaction, don't delete
+ auto sprNoteData = FindMySproutNotes(txidAndWtx.second);
+ auto sapNoteDataAndAddressesToAdd = FindMySaplingNotes(txidAndWtx.second);
+ if (sprNoteData.size() || sapNoteDataAndAddressesToAdd.first.size())
+ {
+ // don't erase the tx, but check to erase IDs
+ eraseTx = false;
+ }
+
+ // if the tx is from this wallet, we will not erase it
+ if (IsFromMe(txidAndWtx.second))
+ {
+ eraseTx = false;
+ }
+
// look for a reason not to delete this tx
for (auto txout : txidAndWtx.second.vout)
{
if (IsMine(txout))
{
eraseTx = false;
- break;
}
continue;
}
{
// we should keep this transaction anyhow, check next
eraseTx = false;
- break;
+ continue;
}
for (auto &dest : addresses)
{
if (dest.which() == COptCCParams::ADDRTYPE_ID)
{
- oneTxIDs.push_back(GetDestinationID(dest));
+ idsToCheck.insert(GetDestinationID(dest));
}
}
}
if (eraseTx)
{
txesToErase.push_back(txidAndWtx.first);
-
- for (auto &checkID : oneTxIDs)
- {
- idsToCheck.insert(checkID);
- }
}
}
}
}
- isMine = IsMine(tx);
-
- if (fExisted || isMine || IsFromMe(tx) || sproutNoteData.size() > 0 || saplingNoteData.size() > 0)
+ if (fExisted || IsMine(tx) || IsFromMe(tx) || sproutNoteData.size() > 0 || saplingNoteData.size() > 0)
{
CWalletTx wtx(this, tx);