Refactor ChainTip to take a struct of Merkle trees instead of a pair.
This makes addition of the Orchard Merkle frontier easier in the future.
This commit is contained in:
parent
d9de6b64fc
commit
4afc6a37c9
|
@ -70,12 +70,12 @@ void SyncWithWallets(const CTransaction &tx, const CBlock *pblock, const int nHe
|
||||||
|
|
||||||
struct CachedBlockData {
|
struct CachedBlockData {
|
||||||
CBlockIndex *pindex;
|
CBlockIndex *pindex;
|
||||||
std::pair<SproutMerkleTree, SaplingMerkleTree> oldTrees;
|
MerkleFrontiers oldTrees;
|
||||||
std::list<CTransaction> txConflicted;
|
std::list<CTransaction> txConflicted;
|
||||||
|
|
||||||
CachedBlockData(
|
CachedBlockData(
|
||||||
CBlockIndex *pindex,
|
CBlockIndex *pindex,
|
||||||
std::pair<SproutMerkleTree, SaplingMerkleTree> oldTrees,
|
MerkleFrontiers oldTrees,
|
||||||
std::list<CTransaction> txConflicted):
|
std::list<CTransaction> txConflicted):
|
||||||
pindex(pindex), oldTrees(oldTrees), txConflicted(txConflicted) {}
|
pindex(pindex), oldTrees(oldTrees), txConflicted(txConflicted) {}
|
||||||
};
|
};
|
||||||
|
@ -135,27 +135,28 @@ void ThreadNotifyWallets(CBlockIndex *pindexLastTip)
|
||||||
|
|
||||||
// Iterate backwards over the connected blocks we need to notify.
|
// Iterate backwards over the connected blocks we need to notify.
|
||||||
while (pindex && pindex != pindexFork) {
|
while (pindex && pindex != pindexFork) {
|
||||||
|
MerkleFrontiers oldFrontiers;
|
||||||
// Get the Sprout commitment tree as of the start of this block.
|
// Get the Sprout commitment tree as of the start of this block.
|
||||||
SproutMerkleTree oldSproutTree;
|
assert(pcoinsTip->GetSproutAnchorAt(pindex->hashSproutAnchor, oldFrontiers.sprout));
|
||||||
assert(pcoinsTip->GetSproutAnchorAt(pindex->hashSproutAnchor, oldSproutTree));
|
|
||||||
|
|
||||||
// Get the Sapling commitment tree as of the start of this block.
|
// Get the Sapling commitment tree as of the start of this block.
|
||||||
// We can get this from the `hashFinalSaplingRoot` of the last block
|
// We can get this from the `hashFinalSaplingRoot` of the last block
|
||||||
// However, this is only reliable if the last block was on or after
|
// However, this is only reliable if the last block was on or after
|
||||||
// the Sapling activation height. Otherwise, the last anchor was the
|
// the Sapling activation height. Otherwise, the last anchor was the
|
||||||
// empty root.
|
// empty root.
|
||||||
SaplingMerkleTree oldSaplingTree;
|
|
||||||
if (chainParams.GetConsensus().NetworkUpgradeActive(
|
if (chainParams.GetConsensus().NetworkUpgradeActive(
|
||||||
pindex->pprev->nHeight, Consensus::UPGRADE_SAPLING)) {
|
pindex->pprev->nHeight, Consensus::UPGRADE_SAPLING)) {
|
||||||
assert(pcoinsTip->GetSaplingAnchorAt(
|
assert(pcoinsTip->GetSaplingAnchorAt(
|
||||||
pindex->pprev->hashFinalSaplingRoot, oldSaplingTree));
|
pindex->pprev->hashFinalSaplingRoot, oldFrontiers.sapling));
|
||||||
} else {
|
} else {
|
||||||
assert(pcoinsTip->GetSaplingAnchorAt(SaplingMerkleTree::empty_root(), oldSaplingTree));
|
assert(pcoinsTip->GetSaplingAnchorAt(SaplingMerkleTree::empty_root(), oldFrontiers.sapling));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: Add the Orchard frontier to oldFrontiers
|
||||||
|
|
||||||
blockStack.emplace_back(
|
blockStack.emplace_back(
|
||||||
pindex,
|
pindex,
|
||||||
std::make_pair(oldSproutTree, oldSaplingTree),
|
oldFrontiers,
|
||||||
recentlyConflicted.first.at(pindex));
|
recentlyConflicted.first.at(pindex));
|
||||||
|
|
||||||
pindex = pindex->pprev;
|
pindex = pindex->pprev;
|
||||||
|
|
|
@ -23,6 +23,11 @@ class CValidationInterface;
|
||||||
class CValidationState;
|
class CValidationState;
|
||||||
class uint256;
|
class uint256;
|
||||||
|
|
||||||
|
struct MerkleFrontiers {
|
||||||
|
SproutMerkleTree sprout;
|
||||||
|
SaplingMerkleTree sapling;
|
||||||
|
};
|
||||||
|
|
||||||
// These functions dispatch to one or all registered wallets
|
// These functions dispatch to one or all registered wallets
|
||||||
|
|
||||||
/** Register a wallet to receive updates from core */
|
/** Register a wallet to receive updates from core */
|
||||||
|
@ -37,7 +42,7 @@ protected:
|
||||||
virtual void UpdatedBlockTip(const CBlockIndex *pindex) {}
|
virtual void UpdatedBlockTip(const CBlockIndex *pindex) {}
|
||||||
virtual void SyncTransaction(const CTransaction &tx, const CBlock *pblock, const int nHeight) {}
|
virtual void SyncTransaction(const CTransaction &tx, const CBlock *pblock, const int nHeight) {}
|
||||||
virtual void EraseFromWallet(const uint256 &hash) {}
|
virtual void EraseFromWallet(const uint256 &hash) {}
|
||||||
virtual void ChainTip(const CBlockIndex *pindex, const CBlock *pblock, std::optional<std::pair<SproutMerkleTree, SaplingMerkleTree>> added) {}
|
virtual void ChainTip(const CBlockIndex *pindex, const CBlock *pblock, std::optional<MerkleFrontiers> added) {}
|
||||||
virtual void UpdatedTransaction(const uint256 &hash) {}
|
virtual void UpdatedTransaction(const uint256 &hash) {}
|
||||||
virtual void Inventory(const uint256 &hash) {}
|
virtual void Inventory(const uint256 &hash) {}
|
||||||
virtual void ResendWalletTransactions(int64_t nBestBlockTime) {}
|
virtual void ResendWalletTransactions(int64_t nBestBlockTime) {}
|
||||||
|
@ -59,7 +64,7 @@ struct CMainSignals {
|
||||||
/** Notifies listeners of an updated transaction without new data (for now: a coinbase potentially becoming visible). */
|
/** Notifies listeners of an updated transaction without new data (for now: a coinbase potentially becoming visible). */
|
||||||
boost::signals2::signal<void (const uint256 &)> UpdatedTransaction;
|
boost::signals2::signal<void (const uint256 &)> UpdatedTransaction;
|
||||||
/** Notifies listeners of a change to the tip of the active block chain. */
|
/** Notifies listeners of a change to the tip of the active block chain. */
|
||||||
boost::signals2::signal<void (const CBlockIndex *, const CBlock *, std::optional<std::pair<SproutMerkleTree, SaplingMerkleTree>>)> ChainTip;
|
boost::signals2::signal<void (const CBlockIndex *, const CBlock *, std::optional<MerkleFrontiers>)> ChainTip;
|
||||||
/** Notifies listeners about an inventory item being seen on the network. */
|
/** Notifies listeners about an inventory item being seen on the network. */
|
||||||
boost::signals2::signal<void (const uint256 &)> Inventory;
|
boost::signals2::signal<void (const uint256 &)> Inventory;
|
||||||
/** Tells listeners to broadcast their data. */
|
/** Tells listeners to broadcast their data. */
|
||||||
|
|
|
@ -60,11 +60,10 @@ public:
|
||||||
void IncrementNoteWitnesses(const Consensus::Params& consensus,
|
void IncrementNoteWitnesses(const Consensus::Params& consensus,
|
||||||
const CBlockIndex* pindex,
|
const CBlockIndex* pindex,
|
||||||
const CBlock* pblock,
|
const CBlock* pblock,
|
||||||
SproutMerkleTree& sproutTree,
|
MerkleFrontiers& frontiers,
|
||||||
SaplingMerkleTree& saplingTree,
|
|
||||||
bool performOrchardWalletUpdates) {
|
bool performOrchardWalletUpdates) {
|
||||||
CWallet::IncrementNoteWitnesses(
|
CWallet::IncrementNoteWitnesses(
|
||||||
consensus, pindex, pblock, sproutTree, saplingTree, performOrchardWalletUpdates);
|
consensus, pindex, pblock, frontiers, performOrchardWalletUpdates);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -96,8 +95,7 @@ std::pair<JSOutPoint, SaplingOutPoint> CreateValidBlock(TestWallet& wallet,
|
||||||
const libzcash::SproutSpendingKey& sk,
|
const libzcash::SproutSpendingKey& sk,
|
||||||
const CBlockIndex& index,
|
const CBlockIndex& index,
|
||||||
CBlock& block,
|
CBlock& block,
|
||||||
SproutMerkleTree& sproutTree,
|
MerkleFrontiers& frontiers) {
|
||||||
SaplingMerkleTree& saplingTree) {
|
|
||||||
auto wtx = GetValidSproutReceive(sk, 50, true);
|
auto wtx = GetValidSproutReceive(sk, 50, true);
|
||||||
auto note = GetSproutNote(sk, wtx, 0, 1);
|
auto note = GetSproutNote(sk, wtx, 0, 1);
|
||||||
auto nullifier = note.nullifier(sk);
|
auto nullifier = note.nullifier(sk);
|
||||||
|
@ -111,7 +109,7 @@ std::pair<JSOutPoint, SaplingOutPoint> CreateValidBlock(TestWallet& wallet,
|
||||||
wallet.LoadWalletTx(wtx);
|
wallet.LoadWalletTx(wtx);
|
||||||
|
|
||||||
block.vtx.push_back(wtx);
|
block.vtx.push_back(wtx);
|
||||||
wallet.IncrementNoteWitnesses(Params().GetConsensus(), &index, &block, sproutTree, saplingTree, true);
|
wallet.IncrementNoteWitnesses(Params().GetConsensus(), &index, &block, frontiers, true);
|
||||||
|
|
||||||
return std::make_pair(jsoutpt, saplingNotes[0]);
|
return std::make_pair(jsoutpt, saplingNotes[0]);
|
||||||
}
|
}
|
||||||
|
@ -705,10 +703,11 @@ TEST(WalletTests, GetConflictedSaplingNotes) {
|
||||||
// Generate note A
|
// Generate note A
|
||||||
libzcash::SaplingNote note(pk, 50000, zip_212_enabled[ver]);
|
libzcash::SaplingNote note(pk, 50000, zip_212_enabled[ver]);
|
||||||
auto cm = note.cmu().value();
|
auto cm = note.cmu().value();
|
||||||
SaplingMerkleTree saplingTree;
|
|
||||||
saplingTree.append(cm);
|
MerkleFrontiers frontiers;
|
||||||
auto anchor = saplingTree.root();
|
frontiers.sapling.append(cm);
|
||||||
auto witness = saplingTree.witness();
|
auto anchor = frontiers.sapling.root();
|
||||||
|
auto witness = frontiers.sapling.witness();
|
||||||
|
|
||||||
// Generate tx to create output note B
|
// Generate tx to create output note B
|
||||||
auto builder = TransactionBuilder(consensusParams, 1, std::nullopt);
|
auto builder = TransactionBuilder(consensusParams, 1, std::nullopt);
|
||||||
|
@ -719,7 +718,6 @@ TEST(WalletTests, GetConflictedSaplingNotes) {
|
||||||
|
|
||||||
// Fake-mine the transaction
|
// Fake-mine the transaction
|
||||||
EXPECT_EQ(-1, chainActive.Height());
|
EXPECT_EQ(-1, chainActive.Height());
|
||||||
SproutMerkleTree sproutTree;
|
|
||||||
CBlock block;
|
CBlock block;
|
||||||
block.vtx.push_back(wtx);
|
block.vtx.push_back(wtx);
|
||||||
block.hashMerkleRoot = block.BuildMerkleTree();
|
block.hashMerkleRoot = block.BuildMerkleTree();
|
||||||
|
@ -738,7 +736,7 @@ TEST(WalletTests, GetConflictedSaplingNotes) {
|
||||||
wallet.LoadWalletTx(wtx);
|
wallet.LoadWalletTx(wtx);
|
||||||
|
|
||||||
// Simulate receiving new block and ChainTip signal
|
// Simulate receiving new block and ChainTip signal
|
||||||
wallet.IncrementNoteWitnesses(Params().GetConsensus(),&fakeIndex, &block, sproutTree, saplingTree, true);
|
wallet.IncrementNoteWitnesses(Params().GetConsensus(),&fakeIndex, &block, frontiers, true);
|
||||||
wallet.UpdateSaplingNullifierNoteMapForBlock(&block);
|
wallet.UpdateSaplingNullifierNoteMapForBlock(&block);
|
||||||
|
|
||||||
// Retrieve the updated wtx from wallet
|
// Retrieve the updated wtx from wallet
|
||||||
|
@ -764,7 +762,7 @@ TEST(WalletTests, GetConflictedSaplingNotes) {
|
||||||
ASSERT_EQ(static_cast<bool>(maybe_nf), true);
|
ASSERT_EQ(static_cast<bool>(maybe_nf), true);
|
||||||
auto nullifier2 = maybe_nf.value();
|
auto nullifier2 = maybe_nf.value();
|
||||||
|
|
||||||
anchor = saplingTree.root();
|
anchor = frontiers.sapling.root();
|
||||||
|
|
||||||
// Create transaction to spend note B
|
// Create transaction to spend note B
|
||||||
auto builder2 = TransactionBuilder(consensusParams, 2, std::nullopt);
|
auto builder2 = TransactionBuilder(consensusParams, 2, std::nullopt);
|
||||||
|
@ -844,8 +842,7 @@ TEST(WalletTests, GetConflictedOrchardNotes) {
|
||||||
CWalletTx wtx {&wallet, tx};
|
CWalletTx wtx {&wallet, tx};
|
||||||
|
|
||||||
// Fake-mine the transaction
|
// Fake-mine the transaction
|
||||||
SproutMerkleTree sproutTree;
|
MerkleFrontiers frontiers;
|
||||||
SaplingMerkleTree saplingTree;
|
|
||||||
OrchardMerkleFrontier orchardTree;
|
OrchardMerkleFrontier orchardTree;
|
||||||
orchardTree.AppendBundle(wtx.GetOrchardBundle());
|
orchardTree.AppendBundle(wtx.GetOrchardBundle());
|
||||||
|
|
||||||
|
@ -870,7 +867,7 @@ TEST(WalletTests, GetConflictedOrchardNotes) {
|
||||||
wallet.LoadWalletTx(wtx);
|
wallet.LoadWalletTx(wtx);
|
||||||
|
|
||||||
// Simulate receiving new block and ChainTip signal
|
// Simulate receiving new block and ChainTip signal
|
||||||
wallet.IncrementNoteWitnesses(Params().GetConsensus(),&fakeIndex, &block, sproutTree, saplingTree, true);
|
wallet.IncrementNoteWitnesses(Params().GetConsensus(),&fakeIndex, &block, frontiers, true);
|
||||||
|
|
||||||
// Fetch the Orchard note so we can spend it.
|
// Fetch the Orchard note so we can spend it.
|
||||||
std::vector<SproutNoteEntry> sproutEntries;
|
std::vector<SproutNoteEntry> sproutEntries;
|
||||||
|
@ -1103,12 +1100,13 @@ TEST(WalletTests, NavigateFromSaplingNullifierToNote) {
|
||||||
ASSERT_TRUE(nf);
|
ASSERT_TRUE(nf);
|
||||||
uint256 nullifier = nf.value();
|
uint256 nullifier = nf.value();
|
||||||
|
|
||||||
|
MerkleFrontiers frontiers = { .sapling = testNote.tree };
|
||||||
|
|
||||||
// Verify dummy note is unspent
|
// Verify dummy note is unspent
|
||||||
EXPECT_FALSE(wallet.IsSaplingSpent(nullifier));
|
EXPECT_FALSE(wallet.IsSaplingSpent(nullifier));
|
||||||
|
|
||||||
// Fake-mine the transaction
|
// Fake-mine the transaction
|
||||||
EXPECT_EQ(-1, chainActive.Height());
|
EXPECT_EQ(-1, chainActive.Height());
|
||||||
SproutMerkleTree sproutTree;
|
|
||||||
CBlock block;
|
CBlock block;
|
||||||
block.vtx.push_back(wtx);
|
block.vtx.push_back(wtx);
|
||||||
block.hashMerkleRoot = block.BuildMerkleTree();
|
block.hashMerkleRoot = block.BuildMerkleTree();
|
||||||
|
@ -1138,7 +1136,7 @@ TEST(WalletTests, NavigateFromSaplingNullifierToNote) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Simulate receiving new block and ChainTip signal
|
// Simulate receiving new block and ChainTip signal
|
||||||
wallet.IncrementNoteWitnesses(Params().GetConsensus(), &fakeIndex, &block, sproutTree, testNote.tree, true);
|
wallet.IncrementNoteWitnesses(Params().GetConsensus(), &fakeIndex, &block, frontiers, true);
|
||||||
wallet.UpdateSaplingNullifierNoteMapForBlock(&block);
|
wallet.UpdateSaplingNullifierNoteMapForBlock(&block);
|
||||||
|
|
||||||
// Retrieve the updated wtx from wallet
|
// Retrieve the updated wtx from wallet
|
||||||
|
@ -1221,10 +1219,10 @@ TEST(WalletTests, SpentSaplingNoteIsFromMe) {
|
||||||
// Generate Sapling note A
|
// Generate Sapling note A
|
||||||
libzcash::SaplingNote note(pk, 50000, zip_212_enabled[ver]);
|
libzcash::SaplingNote note(pk, 50000, zip_212_enabled[ver]);
|
||||||
auto cm = note.cmu().value();
|
auto cm = note.cmu().value();
|
||||||
SaplingMerkleTree saplingTree;
|
MerkleFrontiers frontiers;
|
||||||
saplingTree.append(cm);
|
frontiers.sapling.append(cm);
|
||||||
auto anchor = saplingTree.root();
|
auto anchor = frontiers.sapling.root();
|
||||||
auto witness = saplingTree.witness();
|
auto witness = frontiers.sapling.witness();
|
||||||
|
|
||||||
// Generate transaction, which sends funds to note B
|
// Generate transaction, which sends funds to note B
|
||||||
auto builder = TransactionBuilder(consensusParams, 1, std::nullopt);
|
auto builder = TransactionBuilder(consensusParams, 1, std::nullopt);
|
||||||
|
@ -1238,7 +1236,6 @@ TEST(WalletTests, SpentSaplingNoteIsFromMe) {
|
||||||
|
|
||||||
// Fake-mine the transaction
|
// Fake-mine the transaction
|
||||||
EXPECT_EQ(-1, chainActive.Height());
|
EXPECT_EQ(-1, chainActive.Height());
|
||||||
SproutMerkleTree sproutTree;
|
|
||||||
CBlock block;
|
CBlock block;
|
||||||
block.vtx.push_back(wtx);
|
block.vtx.push_back(wtx);
|
||||||
block.hashMerkleRoot = block.BuildMerkleTree();
|
block.hashMerkleRoot = block.BuildMerkleTree();
|
||||||
|
@ -1258,7 +1255,7 @@ TEST(WalletTests, SpentSaplingNoteIsFromMe) {
|
||||||
// Simulate receiving new block and ChainTip signal.
|
// Simulate receiving new block and ChainTip signal.
|
||||||
// This triggers calculation of nullifiers for notes belonging to this wallet
|
// This triggers calculation of nullifiers for notes belonging to this wallet
|
||||||
// in the output descriptions of wtx.
|
// in the output descriptions of wtx.
|
||||||
wallet.IncrementNoteWitnesses(Params().GetConsensus(), &fakeIndex, &block, sproutTree, saplingTree, true);
|
wallet.IncrementNoteWitnesses(Params().GetConsensus(), &fakeIndex, &block, frontiers, true);
|
||||||
wallet.UpdateSaplingNullifierNoteMapForBlock(&block);
|
wallet.UpdateSaplingNullifierNoteMapForBlock(&block);
|
||||||
|
|
||||||
// Retrieve the updated wtx from wallet
|
// Retrieve the updated wtx from wallet
|
||||||
|
@ -1296,7 +1293,7 @@ TEST(WalletTests, SpentSaplingNoteIsFromMe) {
|
||||||
|
|
||||||
// NOTE: Not updating the anchor results in a core dump. Shouldn't builder just return error?
|
// NOTE: Not updating the anchor results in a core dump. Shouldn't builder just return error?
|
||||||
// *** Error in `./zcash-gtest': double free or corruption (out): 0x00007ffd8755d990 ***
|
// *** Error in `./zcash-gtest': double free or corruption (out): 0x00007ffd8755d990 ***
|
||||||
anchor = saplingTree.root();
|
anchor = frontiers.sapling.root();
|
||||||
|
|
||||||
// Create transaction to spend note B
|
// Create transaction to spend note B
|
||||||
auto builder2 = TransactionBuilder(consensusParams, 2, std::nullopt);
|
auto builder2 = TransactionBuilder(consensusParams, 2, std::nullopt);
|
||||||
|
@ -1393,9 +1390,8 @@ TEST(WalletTests, CachedWitnessesEmptyChain) {
|
||||||
CBlock block;
|
CBlock block;
|
||||||
block.vtx.push_back(wtx);
|
block.vtx.push_back(wtx);
|
||||||
CBlockIndex index(block);
|
CBlockIndex index(block);
|
||||||
SproutMerkleTree sproutTree;
|
MerkleFrontiers frontiers;
|
||||||
SaplingMerkleTree saplingTree;
|
wallet.IncrementNoteWitnesses(Params().GetConsensus(), &index, &block, frontiers, true);
|
||||||
wallet.IncrementNoteWitnesses(Params().GetConsensus(), &index, &block, sproutTree, saplingTree, true);
|
|
||||||
|
|
||||||
::GetWitnessesAndAnchors(wallet, sproutNotes, saplingNotes, sproutWitnesses, saplingWitnesses);
|
::GetWitnessesAndAnchors(wallet, sproutNotes, saplingNotes, sproutWitnesses, saplingWitnesses);
|
||||||
|
|
||||||
|
@ -1415,8 +1411,7 @@ TEST(WalletTests, CachedWitnessesChainTip) {
|
||||||
|
|
||||||
std::pair<uint256, uint256> anchors1;
|
std::pair<uint256, uint256> anchors1;
|
||||||
CBlock block1;
|
CBlock block1;
|
||||||
SproutMerkleTree sproutTree;
|
MerkleFrontiers frontiers;
|
||||||
SaplingMerkleTree saplingTree;
|
|
||||||
|
|
||||||
auto sk = libzcash::SproutSpendingKey::random();
|
auto sk = libzcash::SproutSpendingKey::random();
|
||||||
wallet.AddSproutSpendingKey(sk);
|
wallet.AddSproutSpendingKey(sk);
|
||||||
|
@ -1425,7 +1420,7 @@ TEST(WalletTests, CachedWitnessesChainTip) {
|
||||||
// First block (case tested in _empty_chain)
|
// First block (case tested in _empty_chain)
|
||||||
CBlockIndex index1(block1);
|
CBlockIndex index1(block1);
|
||||||
index1.nHeight = 1;
|
index1.nHeight = 1;
|
||||||
auto outpts = CreateValidBlock(wallet, sk, index1, block1, sproutTree, saplingTree);
|
auto outpts = CreateValidBlock(wallet, sk, index1, block1, frontiers);
|
||||||
|
|
||||||
// Called to fetch anchor
|
// Called to fetch anchor
|
||||||
std::vector<JSOutPoint> sproutNotes {outpts.first};
|
std::vector<JSOutPoint> sproutNotes {outpts.first};
|
||||||
|
@ -1466,9 +1461,8 @@ TEST(WalletTests, CachedWitnessesChainTip) {
|
||||||
block2.vtx.push_back(wtx);
|
block2.vtx.push_back(wtx);
|
||||||
CBlockIndex index2(block2);
|
CBlockIndex index2(block2);
|
||||||
index2.nHeight = 2;
|
index2.nHeight = 2;
|
||||||
SproutMerkleTree sproutTree2 {sproutTree};
|
MerkleFrontiers frontiers2 = { .sprout = frontiers.sprout, .sapling = frontiers.sapling };
|
||||||
SaplingMerkleTree saplingTree2 {saplingTree};
|
wallet.IncrementNoteWitnesses(Params().GetConsensus(), &index2, &block2, frontiers2, true);
|
||||||
wallet.IncrementNoteWitnesses(Params().GetConsensus(), &index2, &block2, sproutTree2, saplingTree2, true);
|
|
||||||
|
|
||||||
auto anchors2 = GetWitnessesAndAnchors(wallet, sproutNotes, saplingNotes, sproutWitnesses, saplingWitnesses);
|
auto anchors2 = GetWitnessesAndAnchors(wallet, sproutNotes, saplingNotes, sproutWitnesses, saplingWitnesses);
|
||||||
EXPECT_NE(anchors2.first, anchors2.second);
|
EXPECT_NE(anchors2.first, anchors2.second);
|
||||||
|
@ -1489,7 +1483,7 @@ TEST(WalletTests, CachedWitnessesChainTip) {
|
||||||
EXPECT_NE(anchors1.second, anchors3.second);
|
EXPECT_NE(anchors1.second, anchors3.second);
|
||||||
|
|
||||||
// Re-incrementing with the same block should give the same result
|
// Re-incrementing with the same block should give the same result
|
||||||
wallet.IncrementNoteWitnesses(Params().GetConsensus(), &index2, &block2, sproutTree, saplingTree, true);
|
wallet.IncrementNoteWitnesses(Params().GetConsensus(), &index2, &block2, frontiers, true);
|
||||||
auto anchors4 = GetWitnessesAndAnchors(wallet, sproutNotes, saplingNotes, sproutWitnesses, saplingWitnesses);
|
auto anchors4 = GetWitnessesAndAnchors(wallet, sproutNotes, saplingNotes, sproutWitnesses, saplingWitnesses);
|
||||||
EXPECT_NE(anchors4.first, anchors4.second);
|
EXPECT_NE(anchors4.first, anchors4.second);
|
||||||
|
|
||||||
|
@ -1499,7 +1493,7 @@ TEST(WalletTests, CachedWitnessesChainTip) {
|
||||||
EXPECT_EQ(anchors2.second, anchors4.second);
|
EXPECT_EQ(anchors2.second, anchors4.second);
|
||||||
|
|
||||||
// Incrementing with the same block again should not change the cache
|
// Incrementing with the same block again should not change the cache
|
||||||
wallet.IncrementNoteWitnesses(Params().GetConsensus(), &index2, &block2, sproutTree, saplingTree, true);
|
wallet.IncrementNoteWitnesses(Params().GetConsensus(), &index2, &block2, frontiers, true);
|
||||||
std::vector<std::optional<SproutWitness>> sproutWitnesses5;
|
std::vector<std::optional<SproutWitness>> sproutWitnesses5;
|
||||||
std::vector<std::optional<SaplingWitness>> saplingWitnesses5;
|
std::vector<std::optional<SaplingWitness>> saplingWitnesses5;
|
||||||
|
|
||||||
|
@ -1518,8 +1512,7 @@ TEST(WalletTests, CachedWitnessesDecrementFirst) {
|
||||||
TestWallet wallet(Params());
|
TestWallet wallet(Params());
|
||||||
LOCK(wallet.cs_wallet);
|
LOCK(wallet.cs_wallet);
|
||||||
|
|
||||||
SproutMerkleTree sproutTree;
|
MerkleFrontiers frontiers;
|
||||||
SaplingMerkleTree saplingTree;
|
|
||||||
|
|
||||||
auto sk = libzcash::SproutSpendingKey::random();
|
auto sk = libzcash::SproutSpendingKey::random();
|
||||||
wallet.AddSproutSpendingKey(sk);
|
wallet.AddSproutSpendingKey(sk);
|
||||||
|
@ -1529,7 +1522,7 @@ TEST(WalletTests, CachedWitnessesDecrementFirst) {
|
||||||
CBlock block1;
|
CBlock block1;
|
||||||
CBlockIndex index1(block1);
|
CBlockIndex index1(block1);
|
||||||
index1.nHeight = 1;
|
index1.nHeight = 1;
|
||||||
CreateValidBlock(wallet, sk, index1, block1, sproutTree, saplingTree);
|
CreateValidBlock(wallet, sk, index1, block1, frontiers);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::pair<uint256, uint256> anchors2;
|
std::pair<uint256, uint256> anchors2;
|
||||||
|
@ -1539,7 +1532,7 @@ TEST(WalletTests, CachedWitnessesDecrementFirst) {
|
||||||
{
|
{
|
||||||
// Second block (case tested in _chain_tip)
|
// Second block (case tested in _chain_tip)
|
||||||
index2.nHeight = 2;
|
index2.nHeight = 2;
|
||||||
auto outpts = CreateValidBlock(wallet, sk, index2, block2, sproutTree, saplingTree);
|
auto outpts = CreateValidBlock(wallet, sk, index2, block2, frontiers);
|
||||||
|
|
||||||
// Called to fetch anchor
|
// Called to fetch anchor
|
||||||
std::vector<JSOutPoint> sproutNotes {outpts.first};
|
std::vector<JSOutPoint> sproutNotes {outpts.first};
|
||||||
|
@ -1585,7 +1578,7 @@ TEST(WalletTests, CachedWitnessesDecrementFirst) {
|
||||||
EXPECT_NE(anchors2.second, anchors4.second);
|
EXPECT_NE(anchors2.second, anchors4.second);
|
||||||
|
|
||||||
// Re-incrementing with the same block should give the same result
|
// Re-incrementing with the same block should give the same result
|
||||||
wallet.IncrementNoteWitnesses(Params().GetConsensus(), &index2, &block2, sproutTree, saplingTree, true);
|
wallet.IncrementNoteWitnesses(Params().GetConsensus(), &index2, &block2, frontiers, true);
|
||||||
|
|
||||||
auto anchors5 = GetWitnessesAndAnchors(wallet, sproutNotes, saplingNotes, sproutWitnesses, saplingWitnesses);
|
auto anchors5 = GetWitnessesAndAnchors(wallet, sproutNotes, saplingNotes, sproutWitnesses, saplingWitnesses);
|
||||||
|
|
||||||
|
@ -1607,10 +1600,8 @@ TEST(WalletTests, CachedWitnessesCleanIndex) {
|
||||||
std::vector<SaplingOutPoint> saplingNotes;
|
std::vector<SaplingOutPoint> saplingNotes;
|
||||||
std::vector<uint256> sproutAnchors;
|
std::vector<uint256> sproutAnchors;
|
||||||
std::vector<uint256> saplingAnchors;
|
std::vector<uint256> saplingAnchors;
|
||||||
SproutMerkleTree sproutTree;
|
MerkleFrontiers frontiers;
|
||||||
SproutMerkleTree sproutRiTree = sproutTree;
|
MerkleFrontiers riFrontiers = { .sprout = frontiers.sprout, .sapling = frontiers.sapling };
|
||||||
SaplingMerkleTree saplingTree;
|
|
||||||
SaplingMerkleTree saplingRiTree = saplingTree;
|
|
||||||
std::vector<std::optional<SproutWitness>> sproutWitnesses;
|
std::vector<std::optional<SproutWitness>> sproutWitnesses;
|
||||||
std::vector<std::optional<SaplingWitness>> saplingWitnesses;
|
std::vector<std::optional<SaplingWitness>> saplingWitnesses;
|
||||||
|
|
||||||
|
@ -1623,11 +1614,11 @@ TEST(WalletTests, CachedWitnessesCleanIndex) {
|
||||||
indices.resize(numBlocks);
|
indices.resize(numBlocks);
|
||||||
for (size_t i = 0; i < numBlocks; i++) {
|
for (size_t i = 0; i < numBlocks; i++) {
|
||||||
indices[i].nHeight = i;
|
indices[i].nHeight = i;
|
||||||
auto oldSproutRoot = sproutTree.root();
|
auto oldSproutRoot = frontiers.sprout.root();
|
||||||
auto oldSaplingRoot = saplingTree.root();
|
auto oldSaplingRoot = frontiers.sapling.root();
|
||||||
auto outpts = CreateValidBlock(wallet, sk, indices[i], blocks[i], sproutTree, saplingTree);
|
auto outpts = CreateValidBlock(wallet, sk, indices[i], blocks[i], frontiers);
|
||||||
EXPECT_NE(oldSproutRoot, sproutTree.root());
|
EXPECT_NE(oldSproutRoot, frontiers.sprout.root());
|
||||||
EXPECT_NE(oldSaplingRoot, saplingTree.root());
|
EXPECT_NE(oldSaplingRoot, frontiers.sapling.root());
|
||||||
sproutNotes.push_back(outpts.first);
|
sproutNotes.push_back(outpts.first);
|
||||||
saplingNotes.push_back(outpts.second);
|
saplingNotes.push_back(outpts.second);
|
||||||
|
|
||||||
|
@ -1643,9 +1634,8 @@ TEST(WalletTests, CachedWitnessesCleanIndex) {
|
||||||
// Now pretend we are reindexing: the chain is cleared, and each block is
|
// Now pretend we are reindexing: the chain is cleared, and each block is
|
||||||
// used to increment witnesses again.
|
// used to increment witnesses again.
|
||||||
for (size_t i = 0; i < numBlocks; i++) {
|
for (size_t i = 0; i < numBlocks; i++) {
|
||||||
SproutMerkleTree sproutRiPrevTree {sproutRiTree};
|
MerkleFrontiers riPrevFrontiers{riFrontiers};
|
||||||
SaplingMerkleTree saplingRiPrevTree {saplingRiTree};
|
wallet.IncrementNoteWitnesses(Params().GetConsensus(), &(indices[i]), &(blocks[i]), riFrontiers, true);
|
||||||
wallet.IncrementNoteWitnesses(Params().GetConsensus(), &(indices[i]), &(blocks[i]), sproutRiTree, saplingRiTree, true);
|
|
||||||
|
|
||||||
auto anchors = GetWitnessesAndAnchors(wallet, sproutNotes, saplingNotes, sproutWitnesses, saplingWitnesses);
|
auto anchors = GetWitnessesAndAnchors(wallet, sproutNotes, saplingNotes, sproutWitnesses, saplingWitnesses);
|
||||||
for (size_t j = 0; j < numBlocks; j++) {
|
for (size_t j = 0; j < numBlocks; j++) {
|
||||||
|
@ -1672,7 +1662,7 @@ TEST(WalletTests, CachedWitnessesCleanIndex) {
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
wallet.IncrementNoteWitnesses(Params().GetConsensus(), &(indices[i]), &(blocks[i]), sproutRiPrevTree, saplingRiPrevTree, true);
|
wallet.IncrementNoteWitnesses(Params().GetConsensus(), &(indices[i]), &(blocks[i]), riPrevFrontiers, true);
|
||||||
auto anchors = GetWitnessesAndAnchors(wallet, sproutNotes, saplingNotes, sproutWitnesses, saplingWitnesses);
|
auto anchors = GetWitnessesAndAnchors(wallet, sproutNotes, saplingNotes, sproutWitnesses, saplingWitnesses);
|
||||||
for (size_t j = 0; j < numBlocks; j++) {
|
for (size_t j = 0; j < numBlocks; j++) {
|
||||||
EXPECT_TRUE((bool) sproutWitnesses[j]);
|
EXPECT_TRUE((bool) sproutWitnesses[j]);
|
||||||
|
@ -2059,6 +2049,8 @@ TEST(WalletTests, UpdatedSaplingNoteData) {
|
||||||
builder.AddSaplingOutput(extfvk.fvk.ovk, pa2, 25000, {});
|
builder.AddSaplingOutput(extfvk.fvk.ovk, pa2, 25000, {});
|
||||||
auto tx = builder.Build().GetTxOrThrow();
|
auto tx = builder.Build().GetTxOrThrow();
|
||||||
|
|
||||||
|
MerkleFrontiers frontiers = { .sapling = testNote.tree };
|
||||||
|
|
||||||
// Wallet contains extfvk1 but not extfvk2
|
// Wallet contains extfvk1 but not extfvk2
|
||||||
CWalletTx wtx {&wallet, tx};
|
CWalletTx wtx {&wallet, tx};
|
||||||
ASSERT_TRUE(wallet.AddSaplingZKey(sk));
|
ASSERT_TRUE(wallet.AddSaplingZKey(sk));
|
||||||
|
@ -2067,7 +2059,6 @@ TEST(WalletTests, UpdatedSaplingNoteData) {
|
||||||
|
|
||||||
// Fake-mine the transaction
|
// Fake-mine the transaction
|
||||||
EXPECT_EQ(-1, chainActive.Height());
|
EXPECT_EQ(-1, chainActive.Height());
|
||||||
SproutMerkleTree sproutTree;
|
|
||||||
CBlock block;
|
CBlock block;
|
||||||
block.vtx.push_back(wtx);
|
block.vtx.push_back(wtx);
|
||||||
block.hashMerkleRoot = block.BuildMerkleTree();
|
block.hashMerkleRoot = block.BuildMerkleTree();
|
||||||
|
@ -2086,7 +2077,7 @@ TEST(WalletTests, UpdatedSaplingNoteData) {
|
||||||
wallet.LoadWalletTx(wtx);
|
wallet.LoadWalletTx(wtx);
|
||||||
|
|
||||||
// Simulate receiving new block and ChainTip signal
|
// Simulate receiving new block and ChainTip signal
|
||||||
wallet.IncrementNoteWitnesses(Params().GetConsensus(), &fakeIndex, &block, sproutTree, testNote.tree, true);
|
wallet.IncrementNoteWitnesses(Params().GetConsensus(), &fakeIndex, &block, frontiers, true);
|
||||||
wallet.UpdateSaplingNullifierNoteMapForBlock(&block);
|
wallet.UpdateSaplingNullifierNoteMapForBlock(&block);
|
||||||
|
|
||||||
// Retrieve the updated wtx from wallet
|
// Retrieve the updated wtx from wallet
|
||||||
|
@ -2104,7 +2095,7 @@ TEST(WalletTests, UpdatedSaplingNoteData) {
|
||||||
// The payment note has not been witnessed yet, so let's fake the witness.
|
// The payment note has not been witnessed yet, so let's fake the witness.
|
||||||
SaplingOutPoint sop0(wtx2.GetHash(), 0);
|
SaplingOutPoint sop0(wtx2.GetHash(), 0);
|
||||||
SaplingOutPoint sop1(wtx2.GetHash(), 1);
|
SaplingOutPoint sop1(wtx2.GetHash(), 1);
|
||||||
wtx2.mapSaplingNoteData[sop0].witnesses.push_front(testNote.tree.witness());
|
wtx2.mapSaplingNoteData[sop0].witnesses.push_front(frontiers.sapling.witness());
|
||||||
wtx2.mapSaplingNoteData[sop0].witnessHeight = 0;
|
wtx2.mapSaplingNoteData[sop0].witnessHeight = 0;
|
||||||
|
|
||||||
// The txs are different as wtx is aware of just the change output,
|
// The txs are different as wtx is aware of just the change output,
|
||||||
|
@ -2132,7 +2123,7 @@ TEST(WalletTests, UpdatedSaplingNoteData) {
|
||||||
EXPECT_EQ(wtx.mapSaplingNoteData[sop0].witnesses.front(), wtx2.mapSaplingNoteData[sop0].witnesses.front());
|
EXPECT_EQ(wtx.mapSaplingNoteData[sop0].witnesses.front(), wtx2.mapSaplingNoteData[sop0].witnesses.front());
|
||||||
// wtx2 never had its change output witnessed even though it has been in wtx
|
// wtx2 never had its change output witnessed even though it has been in wtx
|
||||||
EXPECT_EQ(0, wtx2.mapSaplingNoteData[sop1].witnesses.size());
|
EXPECT_EQ(0, wtx2.mapSaplingNoteData[sop1].witnesses.size());
|
||||||
EXPECT_EQ(wtx.mapSaplingNoteData[sop1].witnesses.front(), testNote.tree.witness());
|
EXPECT_EQ(wtx.mapSaplingNoteData[sop1].witnesses.front(), frontiers.sapling.witness());
|
||||||
|
|
||||||
// Tear down
|
// Tear down
|
||||||
chainActive.SetTip(NULL);
|
chainActive.SetTip(NULL);
|
||||||
|
@ -2215,7 +2206,7 @@ TEST(WalletTests, MarkAffectedSaplingTransactionsDirty) {
|
||||||
|
|
||||||
// Fake-mine the transaction
|
// Fake-mine the transaction
|
||||||
EXPECT_EQ(-1, chainActive.Height());
|
EXPECT_EQ(-1, chainActive.Height());
|
||||||
SaplingMerkleTree saplingTree;
|
MerkleFrontiers frontiers;
|
||||||
SproutMerkleTree sproutTree;
|
SproutMerkleTree sproutTree;
|
||||||
CBlock block;
|
CBlock block;
|
||||||
block.vtx.push_back(wtx);
|
block.vtx.push_back(wtx);
|
||||||
|
@ -2235,7 +2226,7 @@ TEST(WalletTests, MarkAffectedSaplingTransactionsDirty) {
|
||||||
wallet.LoadWalletTx(wtx);
|
wallet.LoadWalletTx(wtx);
|
||||||
|
|
||||||
// Simulate receiving new block and ChainTip signal
|
// Simulate receiving new block and ChainTip signal
|
||||||
wallet.IncrementNoteWitnesses(Params().GetConsensus(), &fakeIndex, &block, sproutTree, saplingTree, true);
|
wallet.IncrementNoteWitnesses(Params().GetConsensus(), &fakeIndex, &block, frontiers, true);
|
||||||
wallet.UpdateSaplingNullifierNoteMapForBlock(&block);
|
wallet.UpdateSaplingNullifierNoteMapForBlock(&block);
|
||||||
|
|
||||||
// Retrieve the updated wtx from wallet
|
// Retrieve the updated wtx from wallet
|
||||||
|
@ -2248,8 +2239,8 @@ TEST(WalletTests, MarkAffectedSaplingTransactionsDirty) {
|
||||||
auto maybe_note = maybe_pt.value().note(ivk);
|
auto maybe_note = maybe_pt.value().note(ivk);
|
||||||
ASSERT_EQ(static_cast<bool>(maybe_note), true);
|
ASSERT_EQ(static_cast<bool>(maybe_note), true);
|
||||||
auto note = maybe_note.value();
|
auto note = maybe_note.value();
|
||||||
auto anchor = saplingTree.root();
|
auto anchor = frontiers.sapling.root();
|
||||||
auto witness = saplingTree.witness();
|
auto witness = frontiers.sapling.witness();
|
||||||
|
|
||||||
// Create a Sapling-only transaction
|
// Create a Sapling-only transaction
|
||||||
// 0.0004 z-ZEC in, 0.00025 z-ZEC out, default fee, 0.00005 z-ZEC change
|
// 0.0004 z-ZEC in, 0.00025 z-ZEC out, default fee, 0.00005 z-ZEC change
|
||||||
|
|
|
@ -1392,15 +1392,14 @@ bool CWallet::ChangeWalletPassphrase(const SecureString& strOldWalletPassphrase,
|
||||||
|
|
||||||
void CWallet::ChainTipAdded(const CBlockIndex *pindex,
|
void CWallet::ChainTipAdded(const CBlockIndex *pindex,
|
||||||
const CBlock *pblock,
|
const CBlock *pblock,
|
||||||
SproutMerkleTree sproutTree,
|
MerkleFrontiers frontiers,
|
||||||
SaplingMerkleTree saplingTree,
|
|
||||||
bool performOrchardWalletUpdates)
|
bool performOrchardWalletUpdates)
|
||||||
{
|
{
|
||||||
const auto chainParams = Params();
|
const auto chainParams = Params();
|
||||||
IncrementNoteWitnesses(
|
IncrementNoteWitnesses(
|
||||||
chainParams.GetConsensus(),
|
chainParams.GetConsensus(),
|
||||||
pindex, pblock,
|
pindex, pblock,
|
||||||
sproutTree, saplingTree, performOrchardWalletUpdates);
|
frontiers, performOrchardWalletUpdates);
|
||||||
UpdateSaplingNullifierNoteMapForBlock(pblock);
|
UpdateSaplingNullifierNoteMapForBlock(pblock);
|
||||||
|
|
||||||
// SetBestChain() can be expensive for large wallets, so do only
|
// SetBestChain() can be expensive for large wallets, so do only
|
||||||
|
@ -1432,11 +1431,11 @@ void CWallet::ChainTip(const CBlockIndex *pindex,
|
||||||
const CBlock *pblock,
|
const CBlock *pblock,
|
||||||
// If this is None, it indicates a rollback and we will decrement the
|
// If this is None, it indicates a rollback and we will decrement the
|
||||||
// witnesses / rewind the tree
|
// witnesses / rewind the tree
|
||||||
std::optional<std::pair<SproutMerkleTree, SaplingMerkleTree>> added)
|
std::optional<MerkleFrontiers> added)
|
||||||
{
|
{
|
||||||
const auto& consensus = Params().GetConsensus();
|
const auto& consensus = Params().GetConsensus();
|
||||||
if (added.has_value()) {
|
if (added.has_value()) {
|
||||||
ChainTipAdded(pindex, pblock, added->first, added->second, true);
|
ChainTipAdded(pindex, pblock, added.value(), true);
|
||||||
// Prevent migration transactions from being created when node is syncing after launch,
|
// Prevent migration transactions from being created when node is syncing after launch,
|
||||||
// and also when node wakes up from suspension/hibernation and incoming blocks are old.
|
// and also when node wakes up from suspension/hibernation and incoming blocks are old.
|
||||||
if (!IsInitialBlockDownload(consensus) &&
|
if (!IsInitialBlockDownload(consensus) &&
|
||||||
|
@ -2600,8 +2599,7 @@ void CWallet::IncrementNoteWitnesses(
|
||||||
const Consensus::Params& consensus,
|
const Consensus::Params& consensus,
|
||||||
const CBlockIndex* pindex,
|
const CBlockIndex* pindex,
|
||||||
const CBlock* pblockIn,
|
const CBlock* pblockIn,
|
||||||
SproutMerkleTree& sproutTree,
|
MerkleFrontiers& frontiers,
|
||||||
SaplingMerkleTree& saplingTree,
|
|
||||||
bool performOrchardWalletUpdates)
|
bool performOrchardWalletUpdates)
|
||||||
{
|
{
|
||||||
LOCK(cs_wallet);
|
LOCK(cs_wallet);
|
||||||
|
@ -2633,7 +2631,7 @@ void CWallet::IncrementNoteWitnesses(
|
||||||
const JSDescription& jsdesc = tx.vJoinSplit[i];
|
const JSDescription& jsdesc = tx.vJoinSplit[i];
|
||||||
for (uint8_t j = 0; j < jsdesc.commitments.size(); j++) {
|
for (uint8_t j = 0; j < jsdesc.commitments.size(); j++) {
|
||||||
const uint256& note_commitment = jsdesc.commitments[j];
|
const uint256& note_commitment = jsdesc.commitments[j];
|
||||||
sproutTree.append(note_commitment);
|
frontiers.sprout.append(note_commitment);
|
||||||
|
|
||||||
// Increment existing witnesses
|
// Increment existing witnesses
|
||||||
for (std::pair<const uint256, CWalletTx>& wtxItem : mapWallet) {
|
for (std::pair<const uint256, CWalletTx>& wtxItem : mapWallet) {
|
||||||
|
@ -2643,14 +2641,14 @@ void CWallet::IncrementNoteWitnesses(
|
||||||
// If this is our note, witness it
|
// If this is our note, witness it
|
||||||
if (txIsOurs) {
|
if (txIsOurs) {
|
||||||
JSOutPoint jsoutpt {hash, i, j};
|
JSOutPoint jsoutpt {hash, i, j};
|
||||||
::WitnessNoteIfMine(mapWallet[hash].mapSproutNoteData, pindex->nHeight, nWitnessCacheSize, jsoutpt, sproutTree.witness());
|
::WitnessNoteIfMine(mapWallet[hash].mapSproutNoteData, pindex->nHeight, nWitnessCacheSize, jsoutpt, frontiers.sprout.witness());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Sapling
|
// Sapling
|
||||||
for (uint32_t i = 0; i < tx.vShieldedOutput.size(); i++) {
|
for (uint32_t i = 0; i < tx.vShieldedOutput.size(); i++) {
|
||||||
const uint256& note_commitment = tx.vShieldedOutput[i].cmu;
|
const uint256& note_commitment = tx.vShieldedOutput[i].cmu;
|
||||||
saplingTree.append(note_commitment);
|
frontiers.sapling.append(note_commitment);
|
||||||
|
|
||||||
// Increment existing witnesses
|
// Increment existing witnesses
|
||||||
for (std::pair<const uint256, CWalletTx>& wtxItem : mapWallet) {
|
for (std::pair<const uint256, CWalletTx>& wtxItem : mapWallet) {
|
||||||
|
@ -2660,13 +2658,14 @@ void CWallet::IncrementNoteWitnesses(
|
||||||
// If this is our note, witness it
|
// If this is our note, witness it
|
||||||
if (txIsOurs) {
|
if (txIsOurs) {
|
||||||
SaplingOutPoint outPoint {hash, i};
|
SaplingOutPoint outPoint {hash, i};
|
||||||
::WitnessNoteIfMine(mapWallet[hash].mapSaplingNoteData, pindex->nHeight, nWitnessCacheSize, outPoint, saplingTree.witness());
|
::WitnessNoteIfMine(mapWallet[hash].mapSaplingNoteData, pindex->nHeight, nWitnessCacheSize, outPoint, frontiers.sapling.witness());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we're at or beyond NU5 activation, update the Orchard note commitment tree.
|
// If we're at or beyond NU5 activation, update the Orchard note commitment tree.
|
||||||
if (performOrchardWalletUpdates && consensus.NetworkUpgradeActive(pindex->nHeight, Consensus::UPGRADE_NU5)) {
|
if (performOrchardWalletUpdates && consensus.NetworkUpgradeActive(pindex->nHeight, Consensus::UPGRADE_NU5)) {
|
||||||
|
|
||||||
assert(orchardWallet.AppendNoteCommitments(pindex->nHeight, *pblock));
|
assert(orchardWallet.AppendNoteCommitments(pindex->nHeight, *pblock));
|
||||||
assert(pindex->hashFinalOrchardRoot == orchardWallet.GetLatestAnchor());
|
assert(pindex->hashFinalOrchardRoot == orchardWallet.GetLatestAnchor());
|
||||||
}
|
}
|
||||||
|
@ -4389,18 +4388,17 @@ int CWallet::ScanForWalletTransactions(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SproutMerkleTree sproutTree;
|
MerkleFrontiers frontiers;
|
||||||
SaplingMerkleTree saplingTree;
|
|
||||||
// This should never fail: we should always be able to get the tree
|
// This should never fail: we should always be able to get the tree
|
||||||
// state on the path to the tip of our chain
|
// state on the path to the tip of our chain
|
||||||
assert(pcoinsTip->GetSproutAnchorAt(pindex->hashSproutAnchor, sproutTree));
|
assert(pcoinsTip->GetSproutAnchorAt(pindex->hashSproutAnchor, frontiers.sprout));
|
||||||
if (pindex->pprev) {
|
if (pindex->pprev) {
|
||||||
if (consensus.NetworkUpgradeActive(pindex->pprev->nHeight, Consensus::UPGRADE_SAPLING)) {
|
if (consensus.NetworkUpgradeActive(pindex->pprev->nHeight, Consensus::UPGRADE_SAPLING)) {
|
||||||
assert(pcoinsTip->GetSaplingAnchorAt(pindex->pprev->hashFinalSaplingRoot, saplingTree));
|
assert(pcoinsTip->GetSaplingAnchorAt(pindex->pprev->hashFinalSaplingRoot, frontiers.sapling));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Increment note witness caches
|
// Increment note witness caches
|
||||||
ChainTipAdded(pindex, &block, sproutTree, saplingTree, performOrchardWalletUpdates);
|
ChainTipAdded(pindex, &block, frontiers, performOrchardWalletUpdates);
|
||||||
|
|
||||||
pindex = chainActive.Next(pindex);
|
pindex = chainActive.Next(pindex);
|
||||||
if (GetTime() >= nNow + 60) {
|
if (GetTime() >= nNow + 60) {
|
||||||
|
|
|
@ -1086,8 +1086,7 @@ protected:
|
||||||
const Consensus::Params& consensus,
|
const Consensus::Params& consensus,
|
||||||
const CBlockIndex* pindex,
|
const CBlockIndex* pindex,
|
||||||
const CBlock* pblock,
|
const CBlock* pblock,
|
||||||
SproutMerkleTree& sproutTree,
|
MerkleFrontiers& frontiers,
|
||||||
SaplingMerkleTree& saplingTree,
|
|
||||||
bool performOrchardWalletUpdates
|
bool performOrchardWalletUpdates
|
||||||
);
|
);
|
||||||
/**
|
/**
|
||||||
|
@ -1158,8 +1157,7 @@ private:
|
||||||
void ChainTipAdded(
|
void ChainTipAdded(
|
||||||
const CBlockIndex *pindex,
|
const CBlockIndex *pindex,
|
||||||
const CBlock *pblock,
|
const CBlock *pblock,
|
||||||
SproutMerkleTree sproutTree,
|
MerkleFrontiers frontiers,
|
||||||
SaplingMerkleTree saplingTree,
|
|
||||||
bool performOrchardWalletUpdates);
|
bool performOrchardWalletUpdates);
|
||||||
|
|
||||||
/* Add a transparent secret key to the wallet. Internal use only. */
|
/* Add a transparent secret key to the wallet. Internal use only. */
|
||||||
|
@ -1806,7 +1804,7 @@ public:
|
||||||
void ChainTip(
|
void ChainTip(
|
||||||
const CBlockIndex *pindex,
|
const CBlockIndex *pindex,
|
||||||
const CBlock *pblock,
|
const CBlock *pblock,
|
||||||
std::optional<std::pair<SproutMerkleTree, SaplingMerkleTree>> added);
|
std::optional<MerkleFrontiers> added);
|
||||||
void RunSaplingMigration(int blockHeight);
|
void RunSaplingMigration(int blockHeight);
|
||||||
void AddPendingSaplingMigrationTx(const CTransaction& tx);
|
void AddPendingSaplingMigrationTx(const CTransaction& tx);
|
||||||
/** Saves witness caches and best block locator to disk. */
|
/** Saves witness caches and best block locator to disk. */
|
||||||
|
|
|
@ -335,8 +335,7 @@ double benchmark_increment_sprout_note_witnesses(size_t nTxs)
|
||||||
const Consensus::Params& consensusParams = Params().GetConsensus();
|
const Consensus::Params& consensusParams = Params().GetConsensus();
|
||||||
|
|
||||||
CWallet wallet(Params());
|
CWallet wallet(Params());
|
||||||
SproutMerkleTree sproutTree;
|
MerkleFrontiers frontiers;
|
||||||
SaplingMerkleTree saplingTree;
|
|
||||||
|
|
||||||
auto sproutSpendingKey = libzcash::SproutSpendingKey::random();
|
auto sproutSpendingKey = libzcash::SproutSpendingKey::random();
|
||||||
wallet.AddSproutSpendingKey(sproutSpendingKey);
|
wallet.AddSproutSpendingKey(sproutSpendingKey);
|
||||||
|
@ -353,7 +352,7 @@ double benchmark_increment_sprout_note_witnesses(size_t nTxs)
|
||||||
index1.nHeight = 1;
|
index1.nHeight = 1;
|
||||||
|
|
||||||
// Increment to get transactions witnessed
|
// Increment to get transactions witnessed
|
||||||
wallet.ChainTip(&index1, &block1, std::make_pair(sproutTree, saplingTree));
|
wallet.ChainTip(&index1, &block1, frontiers);
|
||||||
|
|
||||||
// Second block
|
// Second block
|
||||||
CBlock block2;
|
CBlock block2;
|
||||||
|
@ -369,7 +368,7 @@ double benchmark_increment_sprout_note_witnesses(size_t nTxs)
|
||||||
|
|
||||||
struct timeval tv_start;
|
struct timeval tv_start;
|
||||||
timer_start(tv_start);
|
timer_start(tv_start);
|
||||||
wallet.ChainTip(&index2, &block2, std::make_pair(sproutTree, saplingTree));
|
wallet.ChainTip(&index2, &block2, frontiers);
|
||||||
return timer_stop(tv_start);
|
return timer_stop(tv_start);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -397,8 +396,7 @@ double benchmark_increment_sapling_note_witnesses(size_t nTxs)
|
||||||
const Consensus::Params& consensusParams = Params().GetConsensus();
|
const Consensus::Params& consensusParams = Params().GetConsensus();
|
||||||
|
|
||||||
CWallet wallet(Params());
|
CWallet wallet(Params());
|
||||||
SproutMerkleTree sproutTree;
|
MerkleFrontiers frontiers;
|
||||||
SaplingMerkleTree saplingTree;
|
|
||||||
|
|
||||||
auto saplingSpendingKey = GetTestMasterSaplingSpendingKey();
|
auto saplingSpendingKey = GetTestMasterSaplingSpendingKey();
|
||||||
wallet.AddSaplingSpendingKey(saplingSpendingKey);
|
wallet.AddSaplingSpendingKey(saplingSpendingKey);
|
||||||
|
@ -415,7 +413,7 @@ double benchmark_increment_sapling_note_witnesses(size_t nTxs)
|
||||||
index1.nHeight = 1;
|
index1.nHeight = 1;
|
||||||
|
|
||||||
// Increment to get transactions witnessed
|
// Increment to get transactions witnessed
|
||||||
wallet.ChainTip(&index1, &block1, std::make_pair(sproutTree, saplingTree));
|
wallet.ChainTip(&index1, &block1, frontiers);
|
||||||
|
|
||||||
// Second block
|
// Second block
|
||||||
CBlock block2;
|
CBlock block2;
|
||||||
|
@ -431,7 +429,7 @@ double benchmark_increment_sapling_note_witnesses(size_t nTxs)
|
||||||
|
|
||||||
struct timeval tv_start;
|
struct timeval tv_start;
|
||||||
timer_start(tv_start);
|
timer_start(tv_start);
|
||||||
wallet.ChainTip(&index2, &block2, std::make_pair(sproutTree, saplingTree));
|
wallet.ChainTip(&index2, &block2, frontiers);
|
||||||
return timer_stop(tv_start);
|
return timer_stop(tv_start);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue