|
|
@ -626,35 +626,6 @@ CAmount CCoinsViewCache::GetValueIn(int32_t nHeight,int64_t *interestp,const CTr |
|
|
|
|
|
|
|
bool CCoinsViewCache::HaveJoinSplitRequirements(const CTransaction& tx) const |
|
|
|
{ |
|
|
|
boost::unordered_map<uint256, SproutMerkleTree, CCoinsKeyHasher> intermediates; |
|
|
|
|
|
|
|
BOOST_FOREACH(const JSDescription &joinsplit, tx.vjoinsplit) |
|
|
|
{ |
|
|
|
BOOST_FOREACH(const uint256& nullifier, joinsplit.nullifiers) |
|
|
|
{ |
|
|
|
if (GetNullifier(nullifier, SPROUT)) { |
|
|
|
// If the nullifier is set, this transaction
|
|
|
|
// double-spends!
|
|
|
|
return false; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
SproutMerkleTree tree; |
|
|
|
auto it = intermediates.find(joinsplit.anchor); |
|
|
|
if (it != intermediates.end()) { |
|
|
|
tree = it->second; |
|
|
|
} else if (!GetSproutAnchorAt(joinsplit.anchor, tree)) { |
|
|
|
return false; |
|
|
|
} |
|
|
|
|
|
|
|
BOOST_FOREACH(const uint256& commitment, joinsplit.commitments) |
|
|
|
{ |
|
|
|
tree.append(commitment); |
|
|
|
} |
|
|
|
|
|
|
|
intermediates.insert(std::make_pair(tree.root(), tree)); |
|
|
|
} |
|
|
|
|
|
|
|
for (const SpendDescription &spendDescription : tx.vShieldedSpend) { |
|
|
|
if (GetNullifier(spendDescription.nullifier, SAPLING)) { // Prevent double spends
|
|
|
|
LogPrintf("%s: sapling nullifier %s exists, preventing double spend\n", __FUNCTION__, spendDescription.nullifier.GetHex().c_str()); |
|
|
|