Skip to content

Commit

Permalink
Merge branch 'wallet/spendable_value' into sqlite_wallet/orchard_support
Browse files Browse the repository at this point in the history
  • Loading branch information
nuttycom committed Mar 8, 2024
2 parents 35a3214 + 9de4f1f commit 89d99f5
Show file tree
Hide file tree
Showing 13 changed files with 434 additions and 211 deletions.
4 changes: 4 additions & 0 deletions components/zcash_protocol/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ and this library adheres to Rust's notion of

## [Unreleased]

### Added
- `zcash_protocol::memo`:
- `impl TryFrom<&MemoBytes> for Memo`

## [0.1.0] - 2024-03-06
The entries below are relative to the `zcash_primitives` crate as of the tag
`zcash_primitives-0.14.0`.
Expand Down
14 changes: 13 additions & 1 deletion components/zcash_protocol/src/memo.rs
Original file line number Diff line number Diff line change
Expand Up @@ -197,13 +197,25 @@ impl TryFrom<MemoBytes> for Memo {
/// Returns an error if the provided slice does not represent a valid `Memo` (for
/// example, if the slice is not 512 bytes, or the encoded `Memo` is non-canonical).
fn try_from(bytes: MemoBytes) -> Result<Self, Self::Error> {
Self::try_from(&bytes)
}
}

impl TryFrom<&MemoBytes> for Memo {
type Error = Error;

/// Parses a `Memo` from its ZIP 302 serialization.
///
/// Returns an error if the provided slice does not represent a valid `Memo` (for
/// example, if the slice is not 512 bytes, or the encoded `Memo` is non-canonical).
fn try_from(bytes: &MemoBytes) -> Result<Self, Self::Error> {
match bytes.0[0] {
0xF6 if bytes.0.iter().skip(1).all(|&b| b == 0) => Ok(Memo::Empty),
0xFF => Ok(Memo::Arbitrary(Box::new(bytes.0[1..].try_into().unwrap()))),
b if b <= 0xF4 => str::from_utf8(bytes.as_slice())
.map(|r| Memo::Text(TextMemo(r.to_owned())))
.map_err(Error::InvalidUtf8),
_ => Ok(Memo::Future(bytes)),
_ => Ok(Memo::Future(bytes.clone())),
}
}
}
Expand Down
19 changes: 19 additions & 0 deletions zcash_client_backend/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,10 @@ and this library adheres to Rust's notion of
- `AccountBalance::with_orchard_balance_mut`
- `AccountBirthday::orchard_frontier`
- `BlockMetadata::orchard_tree_size`
- `DecryptedTransaction::{new, tx(), outputs()}`
- `ScannedBlock::orchard`
- `ScannedBlockCommitments::orchard`
- `SentTransaction::new`
- `ORCHARD_SHARD_HEIGHT`
- `BlockMetadata::orchard_tree_size`
- `chain::ScanSummary::{spent_orchard_note_count, received_orchard_note_count}`
Expand Down Expand Up @@ -51,13 +53,28 @@ and this library adheres to Rust's notion of
- Changes to the `WalletRead` trait:
- Added `get_account`
- Added `get_orchard_nullifiers`
- Changes to the `InputSource` trait:
- `select_spendable_notes` now takes its `target_value` argument as a
`NonNegativeAmount`. Also, the values of the returned map are also
`NonNegativeAmount`s instead of `Amount`s.
- Fields of `DecryptedTransaction` are now private. Use `DecryptedTransaction::new`
and the newly provided accessors instead.
- Fields of `SentTransaction` are now private. Use `SentTransaction::new`
and the newly provided accessors instead.
- `ShieldedProtocol` has a new `Orchard` variant.
- `WalletCommitmentTrees`
- `type OrchardShardStore`
- `fn with_orchard_tree_mut`
- `fn put_orchard_subtree_roots`
- Added method `WalletRead::validate_seed`
- Removed `Error::AccountNotFound` variant.
- `zcash_client_backend::decrypt`:
- Fields of `DecryptedOutput` are now private. Use `DecryptedOutput::new`
and the newly provided accessors instead.
- `decrypt_transaction` now returns a `DecryptedOutput<crate::wallet::Note>`
instead of a `DecryptedOutput<sapling::Note>` and will decrypt Orchard
outputs when the `orchard` feature is enabled. In addition, the type
constraint on its `<A>` parameter has been strengthened to `Copy`.
- `zcash_client_backend::fees`:
- Arguments to `ChangeStrategy::compute_balance` have changed.
- `zcash_client_backend::zip321::render::amount_str` now takes a
Expand All @@ -70,6 +87,8 @@ and this library adheres to Rust's notion of
### Removed
- `zcash_client_backend::PoolType::is_receiver`: use
`zcash_keys::Address::has_receiver` instead.
- `zcash_client_backend::DecryptedTransaction::sapling_outputs` use
the `DecryptedTransaction::outputs` method instead.

### Fixed
- This release fixes an error in amount parsing in `zip321` that previously
Expand Down
94 changes: 79 additions & 15 deletions zcash_client_backend/src/data_api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ use zcash_primitives::{
consensus::BlockHeight,
memo::{Memo, MemoBytes},
transaction::{
components::amount::{Amount, BalanceError, NonNegativeAmount},
components::amount::{BalanceError, NonNegativeAmount},
Transaction, TxId,
},
};
Expand Down Expand Up @@ -445,7 +445,7 @@ pub trait InputSource {
fn select_spendable_notes(
&self,
account: Self::AccountId,
target_value: Amount,
target_value: NonNegativeAmount,
sources: &[ShieldedProtocol],
anchor_height: BlockHeight,
exclude: &[Self::NoteRef],
Expand Down Expand Up @@ -666,7 +666,7 @@ pub trait WalletRead {
&self,
_account: Self::AccountId,
_max_height: BlockHeight,
) -> Result<HashMap<TransparentAddress, Amount>, Self::Error> {
) -> Result<HashMap<TransparentAddress, NonNegativeAmount>, Self::Error> {
Ok(HashMap::new())
}

Expand Down Expand Up @@ -876,13 +876,29 @@ impl<A> ScannedBlock<A> {
}

/// A transaction that was detected during scanning of the blockchain,
/// including its decrypted Sapling outputs.
/// including its decrypted Sapling and/or Orchard outputs.
///
/// The purpose of this struct is to permit atomic updates of the
/// wallet database when transactions are successfully decrypted.
pub struct DecryptedTransaction<'a, AccountId> {
pub tx: &'a Transaction,
pub sapling_outputs: &'a Vec<DecryptedOutput<sapling::Note, AccountId>>,
tx: &'a Transaction,
outputs: &'a Vec<DecryptedOutput<Note, AccountId>>,
}

impl<'a, AccountId> DecryptedTransaction<'a, AccountId> {
/// Constructs a new [`DecryptedTransaction`] from its constituent parts.
pub fn new(tx: &'a Transaction, outputs: &'a Vec<DecryptedOutput<Note, AccountId>>) -> Self {
Self { tx, outputs }
}

/// Returns the raw transaction data.
pub fn tx(&self) -> &Transaction {
self.tx
}
/// Returns the Sapling outputs that were decrypted from the transaction.
pub fn outputs(&self) -> &Vec<DecryptedOutput<Note, AccountId>> {
self.outputs
}
}

/// A transaction that was constructed and sent by the wallet.
Expand All @@ -891,13 +907,61 @@ pub struct DecryptedTransaction<'a, AccountId> {
/// wallet database when transactions are created and submitted
/// to the network.
pub struct SentTransaction<'a, AccountId> {
pub tx: &'a Transaction,
pub created: time::OffsetDateTime,
pub account: AccountId,
pub outputs: Vec<SentTransactionOutput<AccountId>>,
pub fee_amount: Amount,
tx: &'a Transaction,
created: time::OffsetDateTime,
account: AccountId,
outputs: Vec<SentTransactionOutput<AccountId>>,
fee_amount: NonNegativeAmount,
#[cfg(feature = "transparent-inputs")]
pub utxos_spent: Vec<OutPoint>,
utxos_spent: Vec<OutPoint>,
}

impl<'a, AccountId> SentTransaction<'a, AccountId> {
/// Constructs a new [`SentTransaction`] from its constituent parts.
pub fn new(
tx: &'a Transaction,
created: time::OffsetDateTime,
account: AccountId,
outputs: Vec<SentTransactionOutput<AccountId>>,
fee_amount: NonNegativeAmount,
#[cfg(feature = "transparent-inputs")] utxos_spent: Vec<OutPoint>,
) -> Self {
Self {
tx,
created,
account,
outputs,
fee_amount,
#[cfg(feature = "transparent-inputs")]
utxos_spent,
}
}

/// Returns the transaction that was sent.
pub fn tx(&self) -> &Transaction {
self.tx
}
/// Returns the timestamp of the transaction's creation.
pub fn created(&self) -> time::OffsetDateTime {
self.created
}
/// Returns the id for the account that created the outputs.
pub fn account_id(&self) -> &AccountId {
&self.account
}
/// Returns the outputs of the transaction.
pub fn outputs(&self) -> &[SentTransactionOutput<AccountId>] {
self.outputs.as_ref()
}
/// Returns the fee paid by the transaction.
pub fn fee_amount(&self) -> NonNegativeAmount {
self.fee_amount
}
/// Returns the list of UTXOs spent in the created transaction.
#[cfg(feature = "transparent-inputs")]
pub fn utxos_spent(&self) -> &[OutPoint] {
self.utxos_spent.as_ref()
}
}

/// An output of a transaction generated by the wallet.
Expand Down Expand Up @@ -1281,7 +1345,7 @@ pub mod testing {
block::BlockHash,
consensus::{BlockHeight, Network},
memo::Memo,
transaction::{components::Amount, Transaction, TxId},
transaction::{components::amount::NonNegativeAmount, Transaction, TxId},
};

use crate::{
Expand Down Expand Up @@ -1346,7 +1410,7 @@ pub mod testing {
fn select_spendable_notes(
&self,
_account: Self::AccountId,
_target_value: Amount,
_target_value: NonNegativeAmount,
_sources: &[ShieldedProtocol],
_anchor_height: BlockHeight,
_exclude: &[Self::NoteRef],
Expand Down Expand Up @@ -1498,7 +1562,7 @@ pub mod testing {
&self,
_account: Self::AccountId,
_max_height: BlockHeight,
) -> Result<HashMap<TransparentAddress, Amount>, Self::Error> {
) -> Result<HashMap<TransparentAddress, NonNegativeAmount>, Self::Error> {
Ok(HashMap::new())
}

Expand Down
13 changes: 5 additions & 8 deletions zcash_client_backend/src/data_api/wallet.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,10 +47,7 @@ use zcash_primitives::{
memo::MemoBytes,
transaction::{
builder::{BuildConfig, BuildResult, Builder},
components::{
amount::{Amount, NonNegativeAmount},
sapling::zip212_enforcement,
},
components::{amount::NonNegativeAmount, sapling::zip212_enforcement},
fees::{zip317::FeeError as Zip317FeeError, FeeRule, StandardFeeRule},
Transaction, TxId,
},
Expand Down Expand Up @@ -166,10 +163,10 @@ where
.or_else(|| params.activation_height(NetworkUpgrade::Sapling))
.expect("Sapling activation height must be known.");

data.store_decrypted_tx(DecryptedTransaction {
data.store_decrypted_tx(DecryptedTransaction::new(
tx,
sapling_outputs: &decrypt_transaction(params, height, tx, &ufvks),
})?;
&decrypt_transaction(params, height, tx, &ufvks),
))?;

Ok(())
}
Expand Down Expand Up @@ -1244,7 +1241,7 @@ where
created: time::OffsetDateTime::now_utc(),
account,
outputs,
fee_amount: Amount::from(proposal_step.balance().fee_required()),
fee_amount: proposal_step.balance().fee_required(),
#[cfg(feature = "transparent-inputs")]
utxos_spent,
})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -462,7 +462,7 @@ where
shielded_inputs = wallet_db
.select_spendable_notes(
account,
amount_required.into(),
amount_required,
selectable_pools,
anchor_height,
&exclude,
Expand Down
Loading

0 comments on commit 89d99f5

Please sign in to comment.