Address documentation & naming requests from code review.

This commit is contained in:
Kris Nuttycombe 2021-09-03 17:32:40 -06:00
parent 2053d7f57b
commit db89569b90
5 changed files with 104 additions and 44 deletions

View File

@ -33,10 +33,9 @@ pub mod wallet;
/// Read-only operations required for light wallet functions.
///
/// This trait defines the read-only portion of the storage
/// interface atop which higher-level wallet operations are
/// implemented. It serves to allow wallet functions to be
/// abstracted away from any particular data storage substrate.
/// This trait defines the read-only portion of the storage interface atop which
/// higher-level wallet operations are implemented. It serves to allow wallet functions to
/// be abstracted away from any particular data storage substrate.
pub trait WalletRead {
/// The type of errors produced by a wallet backend.
type Error;
@ -143,6 +142,9 @@ pub trait WalletRead {
) -> Result<Amount, Self::Error>;
/// Returns the memo for a note.
///
/// Implementations of this method must return an error if the note identifier
/// does not appear in the backing data store.
fn get_memo(&self, id_note: Self::NoteRef) -> Result<Memo, Self::Error>;
/// Returns a transaction.
@ -165,18 +167,20 @@ pub trait WalletRead {
/// with which they are associated.
fn get_nullifiers(&self) -> Result<Vec<(AccountId, Nullifier)>, Self::Error>;
/// Returns all nullifiers (including those for notes that have been previously spent), along
/// with the account identifiers with which they are associated.
fn get_all_nullifiers(&self) -> Result<Vec<(AccountId, Nullifier)>, Self::Error>;
/// Return all unspent notes.
fn get_unspent_sapling_notes(
/// Return all unspent Sapling notes.
fn get_spendable_sapling_notes(
&self,
account: AccountId,
anchor_height: BlockHeight,
) -> Result<Vec<SpendableNote>, Self::Error>;
/// Returns a list of unspent notes sufficient to cover the specified
/// Returns a list of spendable Sapling notes sufficient to cover the specified
/// target value, if possible.
fn select_unspent_sapling_notes(
fn select_spendable_sapling_notes(
&self,
account: AccountId,
target_value: Amount,
@ -184,10 +188,12 @@ pub trait WalletRead {
) -> Result<Vec<SpendableNote>, Self::Error>;
#[cfg(feature = "transparent-inputs")]
fn get_unspent_transparent_utxos(
/// Returns a list of unspent transparent UTXOs that appear in the chain at heights up to and
/// including `max_height`.
fn get_unspent_transparent_outputs(
&self,
address: &TransparentAddress,
anchor_height: BlockHeight,
max_height: BlockHeight,
) -> Result<Vec<WalletTransparentOutput>, Self::Error>;
}
@ -410,7 +416,7 @@ pub mod testing {
Ok(Vec::new())
}
fn get_unspent_sapling_notes(
fn get_spendable_sapling_notes(
&self,
_account: AccountId,
_anchor_height: BlockHeight,
@ -418,7 +424,7 @@ pub mod testing {
Ok(Vec::new())
}
fn select_unspent_sapling_notes(
fn select_spendable_sapling_notes(
&self,
_account: AccountId,
_target_value: Amount,
@ -428,7 +434,7 @@ pub mod testing {
}
#[cfg(feature = "transparent-inputs")]
fn get_unspent_transparent_utxos(
fn get_unspent_transparent_outputs(
&self,
_address: &TransparentAddress,
_anchor_height: BlockHeight,

View File

@ -190,20 +190,44 @@ where
wallet_db,
params,
prover,
account,
extsk,
account,
&req,
ovk_policy,
min_confirmations,
)
}
/// Constructs a transaction that sends funds as specified by the `request` argument
/// and stores it to the wallet's "sent transactions" data store, and returns the
/// identifier for the transaction.
///
/// This procedure uses the wallet's underlying note selection algorithm to choose
/// inputs of sufficient value to satisfy the request, if possible.
///
/// Parameters:
/// * `wallet_db`: A read/write reference to the wallet database
/// * `params`: Consensus parameters
/// * `prover`: The TxProver to use in constructing the shielded transaction.
/// * `extsk`: The extended spending key that controls the funds that will be spent
/// in the resulting transaction.
/// * `account`: The ZIP32 account identifier associated with the extended spending
/// key that controls the funds to be used in creating this transaction. This ]
/// procedure will return an error if this does not correctly correspond to `extsk`.
/// * `request`: The ZIP-321 payment request specifying the recipients and amounts
/// for the transaction.
/// * `ovk_policy`: The policy to use for constructing outgoing viewing keys that
/// can allow the sender to view the resulting notes on the blockchain.
/// * `min_confirmations`: The minimum number of confirmations that a previously
/// received note must have in the blockchain in order to be considered for being
/// spent.
#[allow(clippy::too_many_arguments)]
pub fn spend<E, N, P, D, R>(
wallet_db: &mut D,
params: &P,
prover: impl TxProver,
account: AccountId,
extsk: &ExtendedSpendingKey,
account: AccountId,
request: &TransactionRequest,
ovk_policy: OvkPolicy,
min_confirmations: u32,
@ -241,7 +265,7 @@ where
.ok_or_else(|| E::from(Error::InvalidAmount))?;
let target_value = (value + DEFAULT_FEE).ok_or_else(|| E::from(Error::InvalidAmount))?;
let spendable_notes =
wallet_db.select_unspent_sapling_notes(account, target_value, anchor_height)?;
wallet_db.select_spendable_sapling_notes(account, target_value, anchor_height)?;
// Confirm we were able to select sufficient value
let selected_value = spendable_notes
@ -336,15 +360,37 @@ where
})
}
/// Constructs a transaction that consumes available transparent UTXOs belonging to
/// the specified secret key, and sends them to the default address for the provided Sapling
/// extended full viewing key.
///
/// This procedure will not attempt to shield transparent funds if the total amount being shielded
/// is less than the default fee to send the transaction. Fees will be paid only from the transparent
/// UTXOs being consumed.
///
/// Parameters:
/// * `wallet_db`: A read/write reference to the wallet database
/// * `params`: Consensus parameters
/// * `prover`: The TxProver to use in constructing the shielded transaction.
/// * `sk`: The secp256k1 secret key that will be used to detect and spend transparent
/// UTXOs.
/// * `extfvk`: The extended full viewing key that will be used to produce the
/// Sapling address to which funds will be sent.
/// * `account`: The ZIP32 account identifier associated with the the extended
/// full viewing key. This procedure will return an error if this does not correctly
/// correspond to `extfvk`.
/// * `min_confirmations`: The minimum number of confirmations that a previously
/// received UTXO must have in the blockchain in order to be considered for being
/// spent.
#[cfg(feature = "transparent-inputs")]
#[allow(clippy::too_many_arguments)]
pub fn shield_funds<E, N, P, D, R>(
pub fn shield_transparent_funds<E, N, P, D, R>(
wallet_db: &mut D,
params: &P,
prover: impl TxProver,
account: AccountId,
sk: &secp256k1::SecretKey,
extsk: &ExtendedSpendingKey,
extfvk: &ExtendedFullViewingKey,
account: AccountId,
memo: &MemoBytes,
min_confirmations: u32,
) -> Result<D::TxRef, E>
@ -354,6 +400,12 @@ where
R: Copy + Debug,
D: WalletWrite<Error = E, TxRef = R>,
{
// Check that the ExtendedSpendingKey we have been given corresponds to the
// ExtendedFullViewingKey for the account we are spending from.
if !wallet_db.is_valid_account_extfvk(account, &extfvk)? {
return Err(E::from(Error::InvalidExtSk(account)));
}
let (latest_scanned_height, latest_anchor) = wallet_db
.get_target_and_anchor_heights(min_confirmations)
.and_then(|x| x.ok_or_else(|| Error::ScanRequired.into()))?;
@ -362,14 +414,11 @@ where
let taddr = derive_transparent_address_from_secret_key(sk);
// derive own shielded address from the provided extended spending key
let z_address = extsk.default_address().unwrap().1;
let exfvk = ExtendedFullViewingKey::from(extsk);
let ovk = exfvk.fvk.ovk;
let z_address = extfvk.default_address().unwrap().1;
let ovk = extfvk.fvk.ovk;
// get UTXOs from DB
let utxos = wallet_db.get_unspent_transparent_utxos(&taddr, latest_anchor)?;
let utxos = wallet_db.get_unspent_transparent_outputs(&taddr, latest_anchor)?;
let total_amount = utxos
.iter()
.map(|utxo| utxo.value)

View File

@ -274,29 +274,34 @@ impl<P: consensus::Parameters> WalletRead for WalletDb<P> {
wallet::get_all_nullifiers(&self)
}
fn get_unspent_sapling_notes(
fn get_spendable_sapling_notes(
&self,
account: AccountId,
anchor_height: BlockHeight,
) -> Result<Vec<SpendableNote>, Self::Error> {
wallet::transact::get_unspent_sapling_notes(&self, account, anchor_height)
wallet::transact::get_spendable_sapling_notes(&self, account, anchor_height)
}
fn select_unspent_sapling_notes(
fn select_spendable_sapling_notes(
&self,
account: AccountId,
target_value: Amount,
anchor_height: BlockHeight,
) -> Result<Vec<SpendableNote>, Self::Error> {
wallet::transact::select_unspent_sapling_notes(&self, account, target_value, anchor_height)
wallet::transact::select_spendable_sapling_notes(
&self,
account,
target_value,
anchor_height,
)
}
fn get_unspent_transparent_utxos(
fn get_unspent_transparent_outputs(
&self,
address: &TransparentAddress,
anchor_height: BlockHeight,
max_height: BlockHeight,
) -> Result<Vec<WalletTransparentOutput>, Self::Error> {
wallet::get_unspent_transparent_utxos(&self, address, anchor_height)
wallet::get_unspent_transparent_outputs(&self, address, max_height)
}
}
@ -409,32 +414,32 @@ impl<'a, P: consensus::Parameters> WalletRead for DataConnStmtCache<'a, P> {
self.wallet_db.get_all_nullifiers()
}
fn get_unspent_sapling_notes(
fn get_spendable_sapling_notes(
&self,
account: AccountId,
anchor_height: BlockHeight,
) -> Result<Vec<SpendableNote>, Self::Error> {
self.wallet_db
.get_unspent_sapling_notes(account, anchor_height)
.get_spendable_sapling_notes(account, anchor_height)
}
fn select_unspent_sapling_notes(
fn select_spendable_sapling_notes(
&self,
account: AccountId,
target_value: Amount,
anchor_height: BlockHeight,
) -> Result<Vec<SpendableNote>, Self::Error> {
self.wallet_db
.select_unspent_sapling_notes(account, target_value, anchor_height)
.select_spendable_sapling_notes(account, target_value, anchor_height)
}
fn get_unspent_transparent_utxos(
fn get_unspent_transparent_outputs(
&self,
address: &TransparentAddress,
anchor_height: BlockHeight,
max_height: BlockHeight,
) -> Result<Vec<WalletTransparentOutput>, Self::Error> {
self.wallet_db
.get_unspent_transparent_utxos(address, anchor_height)
.get_unspent_transparent_outputs(address, max_height)
}
}

View File

@ -701,10 +701,10 @@ pub fn get_all_nullifiers<P>(
Ok(res)
}
pub fn get_unspent_transparent_utxos<P: consensus::Parameters>(
pub fn get_unspent_transparent_outputs<P: consensus::Parameters>(
wdb: &WalletDb<P>,
address: &TransparentAddress,
anchor_height: BlockHeight,
max_height: BlockHeight,
) -> Result<Vec<WalletTransparentOutput>, SqliteClientError> {
let mut stmt_blocks = wdb.conn.prepare(
"SELECT u.address, u.prevout_txid, u.prevout_idx, u.script, u.value_zat, u.height, tx.block as block
@ -718,7 +718,7 @@ pub fn get_unspent_transparent_utxos<P: consensus::Parameters>(
let addr_str = address.encode(&wdb.params);
let rows = stmt_blocks.query_map(params![addr_str, u32::from(anchor_height)], |row| {
let rows = stmt_blocks.query_map(params![addr_str, u32::from(max_height)], |row| {
let addr: String = row.get(0)?;
let address = TransparentAddress::decode(&wdb.params, &addr).map_err(|e| {
rusqlite::Error::FromSqlConversionFailure(

View File

@ -59,7 +59,7 @@ fn to_spendable_note(row: &Row) -> Result<SpendableNote, SqliteClientError> {
})
}
pub fn get_unspent_sapling_notes<P>(
pub fn get_spendable_sapling_notes<P>(
wdb: &WalletDb<P>,
account: AccountId,
anchor_height: BlockHeight,
@ -87,7 +87,7 @@ pub fn get_unspent_sapling_notes<P>(
notes.collect::<Result<_, _>>()
}
pub fn select_unspent_sapling_notes<P>(
pub fn select_spendable_sapling_notes<P>(
wdb: &WalletDb<P>,
account: AccountId,
target_value: Amount,