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 OrchardRawAddressPtr* addr,
const OrchardIncomingViewingKeyPtr* ivk); 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 * 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. * 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()) 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] #[no_mangle]
pub extern "C" fn orchard_wallet_get_ivk_for_address( pub extern "C" fn orchard_wallet_get_ivk_for_address(
wallet: *const Wallet, wallet: *const Wallet,

View File

@ -120,7 +120,7 @@ TEST(TransactionBuilder, OrchardToOrchard) {
// Now we can get spend info for the note. // Now we can get spend info for the note.
auto spendInfo = wallet.GetSpendInfo(notes); 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. // Get the root of the commitment tree.
OrchardMerkleFrontier tree; OrchardMerkleFrontier tree;
@ -130,7 +130,7 @@ TEST(TransactionBuilder, OrchardToOrchard) {
// Create an Orchard-only transaction // Create an Orchard-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
auto builder = TransactionBuilder(consensusParams, 2, orchardAnchor); 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); builder.AddOrchardOutput(std::nullopt, recipient, 25000, std::nullopt);
auto maybeTx = builder.Build(); auto maybeTx = builder.Build();
EXPECT_TRUE(maybeTx.IsTx()); EXPECT_TRUE(maybeTx.IsTx());

View File

@ -4,10 +4,18 @@
#include "wallet/orchard.h" #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 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) { for (const auto& note : noteMetadata) {
auto pSpendInfo = orchard_wallet_get_spend_info( auto pSpendInfo = orchard_wallet_get_spend_info(
inner.get(), inner.get(),
@ -21,7 +29,12 @@ std::vector<orchard::SpendInfo> OrchardWallet::GetSpendInfo(
note.GetAddress(), note.GetAddress(),
note.GetNoteValue()); 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; return result;

View File

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

View File

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