Address documentation & naming requests from code review.
This commit is contained in:
parent
2053d7f57b
commit
db89569b90
|
@ -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,
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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,
|
||||
|
|
Loading…
Reference in New Issue