wallet: Alter `OrchardWallet::GetSpendInfo` to return the spending key

In the context of `z_sendmany`, we will need both the spending key and
note spendInfo as a pair, so it makes sense to fetch those together.
This commit is contained in:
Jack Grigg 2022-03-11 02:56:42 +00:00
parent 6a7213b5d5
commit 7921ef1c55
7 changed files with 51 additions and 8 deletions

View File

@ -189,6 +189,17 @@ bool orchard_wallet_add_raw_address(
const OrchardRawAddressPtr* addr,
const OrchardIncomingViewingKeyPtr* ivk);
/**
* Returns a pointer to the Orchard spending key corresponding to the specified raw
* address, if it is known to the wallet, or `nullptr` otherwise.
*
* Memory is allocated by Rust and must be manually freed using
* `orchard_spending_key_free`.
*/
OrchardSpendingKeyPtr* orchard_wallet_get_spending_key_for_address(
const OrchardWalletPtr* wallet,
const OrchardRawAddressPtr* addr);
/**
* Returns a pointer to the Orchard incoming viewing key corresponding to the specified
* raw address, if it is known to the wallet, or `nullptr` otherwise.

View File

@ -805,6 +805,22 @@ pub extern "C" fn orchard_wallet_add_raw_address(
wallet.key_store.add_raw_address(*addr, ivk.clone())
}
#[no_mangle]
pub extern "C" fn orchard_wallet_get_spending_key_for_address(
wallet: *const Wallet,
addr: *const Address,
) -> *mut SpendingKey {
let wallet = unsafe { wallet.as_ref() }.expect("Wallet pointer may not be null.");
let addr = unsafe { addr.as_ref() }.expect("Address may not be null.");
wallet
.key_store
.ivk_for_address(addr)
.and_then(|ivk| wallet.key_store.spending_key_for_ivk(ivk))
.map(|sk| Box::into_raw(Box::new(*sk)))
.unwrap_or(std::ptr::null_mut())
}
#[no_mangle]
pub extern "C" fn orchard_wallet_get_ivk_for_address(
wallet: *const Wallet,

View File

@ -120,7 +120,7 @@ TEST(TransactionBuilder, OrchardToOrchard) {
// Now we can get spend info for the note.
auto spendInfo = wallet.GetSpendInfo(notes);
EXPECT_EQ(spendInfo[0].Value(), 40000);
EXPECT_EQ(spendInfo[0].second.Value(), 40000);
// Get the root of the commitment tree.
OrchardMerkleFrontier tree;
@ -130,7 +130,7 @@ TEST(TransactionBuilder, OrchardToOrchard) {
// Create an Orchard-only transaction
// 0.0004 z-ZEC in, 0.00025 z-ZEC out, default fee, 0.00005 z-ZEC change
auto builder = TransactionBuilder(consensusParams, 2, orchardAnchor);
EXPECT_TRUE(builder.AddOrchardSpend(sk, std::move(spendInfo[0])));
EXPECT_TRUE(builder.AddOrchardSpend(sk, std::move(spendInfo[0].second)));
builder.AddOrchardOutput(std::nullopt, recipient, 25000, std::nullopt);
auto maybeTx = builder.Build();
EXPECT_TRUE(maybeTx.IsTx());

View File

@ -4,10 +4,18 @@
#include "wallet/orchard.h"
std::vector<orchard::SpendInfo> OrchardWallet::GetSpendInfo(
std::optional<libzcash::OrchardSpendingKey> OrchardWallet::GetSpendingKeyForAddress(
const libzcash::OrchardRawAddress& addr) const
{
auto skPtr = orchard_wallet_get_spending_key_for_address(inner.get(), addr.inner.get());
if (skPtr == nullptr) return std::nullopt;
return libzcash::OrchardSpendingKey(skPtr);
}
std::vector<std::pair<libzcash::OrchardSpendingKey, orchard::SpendInfo>> OrchardWallet::GetSpendInfo(
const std::vector<OrchardNoteMetadata>& noteMetadata) const
{
std::vector<orchard::SpendInfo> result;
std::vector<std::pair<libzcash::OrchardSpendingKey, orchard::SpendInfo>> result;
for (const auto& note : noteMetadata) {
auto pSpendInfo = orchard_wallet_get_spend_info(
inner.get(),
@ -21,7 +29,12 @@ std::vector<orchard::SpendInfo> OrchardWallet::GetSpendInfo(
note.GetAddress(),
note.GetNoteValue());
result.push_back(std::move(spendInfo));
auto sk = GetSpendingKeyForAddress(note.GetAddress());
if (sk.has_value()) {
result.push_back(std::pair(std::move(sk.value()), std::move(spendInfo)));
} else {
throw std::logic_error("Unknown spending key for given outpoint");
}
}
}
return result;

View File

@ -204,6 +204,9 @@ public:
orchard_wallet_add_full_viewing_key(inner.get(), fvk.inner.get());
}
std::optional<libzcash::OrchardSpendingKey> GetSpendingKeyForAddress(
const libzcash::OrchardRawAddress& addr) const;
std::optional<libzcash::OrchardIncomingViewingKey> GetIncomingViewingKeyForAddress(
const libzcash::OrchardRawAddress& addr) const {
auto ivkPtr = orchard_wallet_get_ivk_for_address(inner.get(), addr.inner.get());
@ -271,7 +274,7 @@ public:
return result;
}
std::vector<orchard::SpendInfo> GetSpendInfo(
std::vector<std::pair<libzcash::OrchardSpendingKey, orchard::SpendInfo>> GetSpendInfo(
const std::vector<OrchardNoteMetadata>& noteMetadata) const;
};

View File

@ -3237,7 +3237,7 @@ void CWallet::GetSaplingNoteWitnesses(const std::vector<SaplingOutPoint>& notes,
}
}
std::vector<orchard::SpendInfo> CWallet::GetOrchardSpendInfo(
std::vector<std::pair<libzcash::OrchardSpendingKey, orchard::SpendInfo>> CWallet::GetOrchardSpendInfo(
const std::vector<OrchardNoteMetadata>& orchardNoteMetadata) const
{
AssertLockHeld(cs_wallet);

View File

@ -1690,7 +1690,7 @@ public:
const std::vector<SaplingOutPoint>& notes,
std::vector<std::optional<SaplingWitness>>& witnesses,
uint256 &final_anchor);
std::vector<orchard::SpendInfo> GetOrchardSpendInfo(
std::vector<std::pair<libzcash::OrchardSpendingKey, orchard::SpendInfo>> GetOrchardSpendInfo(
const std::vector<OrchardNoteMetadata>& orchardNoteMetadata) const;
isminetype IsMine(const CTxIn& txin) const;