Add test for Orchard wallet note detection.
This tests the following operations: * add a spending key to the wallet * add notes from the Orchard bundle component of a transaction to the wallet * detect notes in the wallet that correspond to the spending key * verify that notes that are not ours are not mistakenly labeled as ours
This commit is contained in:
parent
4c53499f11
commit
dcf7f46260
|
@ -59,6 +59,7 @@ zcash_gtest_SOURCES += \
|
|||
gtest/test_zip32.cpp
|
||||
if ENABLE_WALLET
|
||||
zcash_gtest_SOURCES += \
|
||||
wallet/gtest/test_orchard_wallet.cpp \
|
||||
wallet/gtest/test_paymentdisclosure.cpp \
|
||||
wallet/gtest/test_wallet.cpp
|
||||
endif
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#include "pubkey.h"
|
||||
#include "rpc/protocol.h"
|
||||
#include "transaction_builder.h"
|
||||
#include "gtest/test_transaction_builder.h"
|
||||
#include "utiltest.h"
|
||||
#include "zcash/Address.hpp"
|
||||
#include "zcash/address/mnemonic.h"
|
||||
|
@ -16,69 +17,6 @@
|
|||
#include <gmock/gmock.h>
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
// Fake an empty view
|
||||
class TransactionBuilderCoinsViewDB : public CCoinsView {
|
||||
public:
|
||||
std::map<uint256, SproutMerkleTree> sproutTrees;
|
||||
|
||||
TransactionBuilderCoinsViewDB() {}
|
||||
|
||||
bool GetSproutAnchorAt(const uint256 &rt, SproutMerkleTree &tree) const {
|
||||
auto it = sproutTrees.find(rt);
|
||||
if (it != sproutTrees.end()) {
|
||||
tree = it->second;
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool GetSaplingAnchorAt(const uint256 &rt, SaplingMerkleTree &tree) const {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool GetOrchardAnchorAt(const uint256 &rt, OrchardMerkleFrontier &tree) const {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool GetNullifier(const uint256 &nf, ShieldedType type) const {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool GetCoins(const uint256 &txid, CCoins &coins) const {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool HaveCoins(const uint256 &txid) const {
|
||||
return false;
|
||||
}
|
||||
|
||||
uint256 GetBestBlock() const {
|
||||
uint256 a;
|
||||
return a;
|
||||
}
|
||||
|
||||
uint256 GetBestAnchor(ShieldedType type) const {
|
||||
uint256 a;
|
||||
return a;
|
||||
}
|
||||
|
||||
bool BatchWrite(CCoinsMap &mapCoins,
|
||||
const uint256 &hashBlock,
|
||||
const uint256 &hashSproutAnchor,
|
||||
const uint256 &hashSaplingAnchor,
|
||||
CAnchorsSproutMap &mapSproutAnchors,
|
||||
CAnchorsSaplingMap &mapSaplingAnchors,
|
||||
CNullifiersMap &mapSproutNullifiers,
|
||||
CNullifiersMap saplingNullifiersMap) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool GetStats(CCoinsStats &stats) const {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
TEST(TransactionBuilder, TransparentToSapling)
|
||||
{
|
||||
auto consensusParams = RegtestActivateSapling();
|
||||
|
|
|
@ -0,0 +1,73 @@
|
|||
// Copyright (c) 2022 The Zcash developers
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or https://www.opensource.org/licenses/mit-license.php .
|
||||
|
||||
#ifndef ZCASH_GTEST_TEST_TRANSACTION_BUILDER_H
|
||||
#define ZCASH_GTEST_TEST_TRANSACTION_BUILDER_H
|
||||
|
||||
#include "coins.h"
|
||||
|
||||
// Fake an empty view
|
||||
class TransactionBuilderCoinsViewDB : public CCoinsView {
|
||||
public:
|
||||
std::map<uint256, SproutMerkleTree> sproutTrees;
|
||||
|
||||
TransactionBuilderCoinsViewDB() {}
|
||||
|
||||
bool GetSproutAnchorAt(const uint256 &rt, SproutMerkleTree &tree) const {
|
||||
auto it = sproutTrees.find(rt);
|
||||
if (it != sproutTrees.end()) {
|
||||
tree = it->second;
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool GetSaplingAnchorAt(const uint256 &rt, SaplingMerkleTree &tree) const {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool GetOrchardAnchorAt(const uint256 &rt, OrchardMerkleFrontier &tree) const {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool GetNullifier(const uint256 &nf, ShieldedType type) const {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool GetCoins(const uint256 &txid, CCoins &coins) const {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool HaveCoins(const uint256 &txid) const {
|
||||
return false;
|
||||
}
|
||||
|
||||
uint256 GetBestBlock() const {
|
||||
uint256 a;
|
||||
return a;
|
||||
}
|
||||
|
||||
uint256 GetBestAnchor(ShieldedType type) const {
|
||||
uint256 a;
|
||||
return a;
|
||||
}
|
||||
|
||||
bool BatchWrite(CCoinsMap &mapCoins,
|
||||
const uint256 &hashBlock,
|
||||
const uint256 &hashSproutAnchor,
|
||||
const uint256 &hashSaplingAnchor,
|
||||
CAnchorsSproutMap &mapSproutAnchors,
|
||||
CAnchorsSaplingMap &mapSaplingAnchors,
|
||||
CNullifiersMap &mapSproutNullifiers,
|
||||
CNullifiersMap saplingNullifiersMap) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool GetStats(CCoinsStats &stats) const {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
|
@ -82,7 +82,8 @@ bool orchard_wallet_tx_contains_my_notes(
|
|||
|
||||
/**
|
||||
* Add the specified spending key to the wallet's key store.
|
||||
* This will also compute and add the associated incoming viewing key.
|
||||
* This will also compute and add the associated full and
|
||||
* incoming viewing keys.
|
||||
*/
|
||||
void orchard_wallet_add_spending_key(
|
||||
OrchardWalletPtr* wallet,
|
||||
|
|
|
@ -0,0 +1,75 @@
|
|||
#include <gmock/gmock.h>
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include "random.h"
|
||||
#include "transaction_builder.h"
|
||||
#include "utiltest.h"
|
||||
#include "wallet/orchard.h"
|
||||
#include "zcash/Address.hpp"
|
||||
|
||||
#include "gtest/test_transaction_builder.h"
|
||||
|
||||
#include <optional>
|
||||
|
||||
using namespace libzcash;
|
||||
|
||||
OrchardSpendingKey RandomOrchardSpendingKey() {
|
||||
auto coinType = Params().BIP44CoinType() ;
|
||||
|
||||
auto seed = MnemonicSeed::Random(coinType);
|
||||
return OrchardSpendingKey::ForAccount(seed, coinType, 0);
|
||||
}
|
||||
|
||||
CTransaction FakeOrchardTx(const OrchardSpendingKey& sk, libzcash::diversifier_index_t j) {
|
||||
CBasicKeyStore keystore;
|
||||
CKey tsk = AddTestCKeyToKeyStore(keystore);
|
||||
auto scriptPubKey = GetScriptForDestination(tsk.GetPubKey().GetID());
|
||||
|
||||
auto fvk = sk.ToFullViewingKey();
|
||||
auto ivk = fvk.ToIncomingViewingKey();
|
||||
auto recipient = ivk.Address(j);
|
||||
|
||||
TransactionBuilderCoinsViewDB fakeDB;
|
||||
auto orchardAnchor = fakeDB.GetBestAnchor(ShieldedType::ORCHARD);
|
||||
|
||||
// Create a shielding transaction from transparent to Orchard
|
||||
// 0.0005 t-ZEC in, 0.0004 z-ZEC out, default fee
|
||||
auto builder = TransactionBuilder(Params().GetConsensus(), 1, orchardAnchor, &keystore);
|
||||
builder.AddTransparentInput(COutPoint(uint256S("1234"), 0), scriptPubKey, 50000);
|
||||
builder.AddOrchardOutput(std::nullopt, recipient, 40000, std::nullopt);
|
||||
|
||||
auto maybeTx = builder.Build();
|
||||
EXPECT_TRUE(maybeTx.IsTx());
|
||||
return maybeTx.GetTxOrThrow();
|
||||
}
|
||||
|
||||
TEST(OrchardWalletTests, TxContainsMyNotes) {
|
||||
auto consensusParams = RegtestActivateNU5();
|
||||
OrchardWallet wallet;
|
||||
|
||||
// Add a new spending key to the wallet
|
||||
auto sk = RandomOrchardSpendingKey();
|
||||
wallet.AddSpendingKey(sk);
|
||||
|
||||
// Create a transaction sending to the default address for that
|
||||
// spending key and add it to the wallet.
|
||||
auto tx = FakeOrchardTx(sk, libzcash::diversifier_index_t(0));
|
||||
wallet.AddNotesIfInvolvingMe(tx);
|
||||
|
||||
// Check that we detect the transaction as ours
|
||||
EXPECT_TRUE(wallet.TxContainsMyNotes(tx.GetHash()));
|
||||
|
||||
// Create a transaction sending to a different diversified address
|
||||
auto tx1 = FakeOrchardTx(sk, libzcash::diversifier_index_t(0xffffffffffffffff));
|
||||
wallet.AddNotesIfInvolvingMe(tx1);
|
||||
|
||||
// Check that we also detect this transaction as ours
|
||||
EXPECT_TRUE(wallet.TxContainsMyNotes(tx1.GetHash()));
|
||||
|
||||
// Now generate a new key, and send a transaction to it without adding
|
||||
// the key to the wallet; it should not be detected as ours.
|
||||
auto skNotOurs = RandomOrchardSpendingKey();
|
||||
auto tx2 = FakeOrchardTx(skNotOurs, libzcash::diversifier_index_t(0));
|
||||
wallet.AddNotesIfInvolvingMe(tx2);
|
||||
EXPECT_FALSE(wallet.TxContainsMyNotes(tx2.GetHash()));
|
||||
}
|
Loading…
Reference in New Issue