Move `Amount` and `NonNegativeAmount` types to the `zcash_protocol` crate.

This commit is contained in:
Kris Nuttycombe 2024-01-27 11:46:06 -07:00
parent bacfe3cb9d
commit 5e4d9abbce
12 changed files with 59 additions and 50 deletions

View File

@ -6,3 +6,25 @@ and this library adheres to Rust's notion of
[Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [Unreleased]
The entries below are relative to the `zcash_primitives` crate as of the tag
`zcash_primitives-0.14.0`.
### Added
- The following modules have been extracted from `zcash_primitives` and
moved to this crate:
- `consensus`
- `constants`
- `zcash_protocol::value` replaces `zcash_primitives::transcation::components::amount`
- `zcash_protocol::value::Amount::into_u64`
- `impl TryFrom<u64> for zcash_protocol::value::NonNegativeAmount`
- Added in `zcash_protocol::value`:
- `NonNegativeAmount::into_u64`
- `TryFrom<u64> for NonNegativeAmount`
### Removed
- The following conversions have been removed from `zcash_protocol::value`, as
`zcash_protocol` does not depend on the `orchard` or `sapling-crypto` crates.
- `From<NonNegativeAmount> for orchard::NoteValue>`
- `TryFrom<orchard::ValueSum> for Amount`
- `From<NonNegativeAmount> for sapling::value::NoteValue>`
- `TryFrom<sapling::value::NoteValue> for NonNegativeAmount`

View File

@ -17,3 +17,4 @@
pub mod consensus;
pub mod constants;
pub mod value;

View File

@ -4,9 +4,6 @@ use std::iter::Sum;
use std::ops::{Add, AddAssign, Mul, Neg, Sub, SubAssign};
use memuse::DynamicUsage;
use orchard::value as orchard;
use crate::sapling;
pub const COIN: i64 = 1_0000_0000;
pub const MAX_MONEY: i64 = 21_000_000 * COIN;
@ -235,14 +232,6 @@ impl Mul<usize> for Amount {
}
}
impl TryFrom<orchard::ValueSum> for Amount {
type Error = ();
fn try_from(v: orchard::ValueSum) -> Result<Amount, Self::Error> {
i64::try_from(v).map_err(|_| ()).and_then(Amount::try_from)
}
}
/// A type-safe representation of some nonnegative amount of Zcash.
///
/// A NonNegativeAmount can only be constructed from an integer that is within the valid monetary
@ -254,6 +243,11 @@ impl NonNegativeAmount {
/// Returns the identity `NonNegativeAmount`
pub const ZERO: Self = NonNegativeAmount(Amount(0));
/// Returns this NonNegativeAmount as a u64.
pub fn into_u64(self) -> u64 {
self.0.try_into().unwrap()
}
/// Creates a NonNegativeAmount from a u64.
///
/// Returns an error if the amount is outside the range `{0..MAX_MONEY}`.
@ -323,35 +317,15 @@ impl From<&NonNegativeAmount> for Amount {
impl From<NonNegativeAmount> for u64 {
fn from(n: NonNegativeAmount) -> Self {
n.0.try_into().unwrap()
n.into_u64()
}
}
impl From<NonNegativeAmount> for sapling::value::NoteValue {
fn from(n: NonNegativeAmount) -> Self {
sapling::value::NoteValue::from_raw(n.into())
}
}
impl TryFrom<sapling::value::NoteValue> for NonNegativeAmount {
impl TryFrom<u64> for NonNegativeAmount {
type Error = ();
fn try_from(value: sapling::value::NoteValue) -> Result<Self, Self::Error> {
Self::from_u64(value.inner())
}
}
impl From<NonNegativeAmount> for orchard::NoteValue {
fn from(n: NonNegativeAmount) -> Self {
orchard::NoteValue::from_raw(n.into())
}
}
impl TryFrom<orchard::NoteValue> for NonNegativeAmount {
type Error = ();
fn try_from(value: orchard::NoteValue) -> Result<Self, Self::Error> {
Self::from_u64(value.inner())
fn try_from(value: u64) -> Result<Self, Self::Error> {
NonNegativeAmount::from_u64(value)
}
}

View File

@ -67,7 +67,7 @@ impl InputView<()> for SpendInfo {
}
fn value(&self) -> NonNegativeAmount {
NonNegativeAmount::try_from(self.value())
NonNegativeAmount::try_from(self.value().inner())
.expect("An existing note to be spent must have a valid amount value.")
}
}
@ -81,7 +81,7 @@ pub trait OutputView {
impl OutputView for OutputInfo {
fn value(&self) -> NonNegativeAmount {
NonNegativeAmount::try_from(self.value())
NonNegativeAmount::try_from(self.value().inner())
.expect("Output values should be checked at construction.")
}
}

View File

@ -1217,7 +1217,7 @@ mod tests {
// Create a fake Note for the account
let mut rng = OsRng;
let rseed = generate_random_rseed(zip212_enforcement, &mut rng);
let note = sapling::Note::from_parts(to, NoteValue::from(value), rseed);
let note = sapling::Note::from_parts(to, NoteValue::from_raw(value.into()), rseed);
let encryptor = sapling_note_encryption(
Some(dfvk.fvk().ovk),
note.clone(),

View File

@ -361,7 +361,7 @@ pub enum Note {
impl Note {
pub fn value(&self) -> NonNegativeAmount {
match self {
Note::Sapling(n) => n.value().try_into().expect(
Note::Sapling(n) => n.value().inner().try_into().expect(
"Sapling notes must have values in the range of valid non-negative ZEC values.",
),
#[cfg(feature = "orchard")]
@ -461,6 +461,7 @@ impl<NoteRef> sapling_fees::InputView<NoteRef> for ReceivedNote<NoteRef, sapling
fn value(&self) -> NonNegativeAmount {
self.note
.value()
.inner()
.try_into()
.expect("Sapling note values are indirectly checked by consensus.")
}
@ -475,6 +476,7 @@ impl<NoteRef> orchard_fees::InputView<NoteRef> for ReceivedNote<NoteRef, orchard
fn value(&self) -> NonNegativeAmount {
self.note
.value()
.inner()
.try_into()
.expect("Orchard note values are indirectly checked by consensus.")
}

View File

@ -785,7 +785,7 @@ pub(crate) fn fake_compact_block<P: consensus::Parameters>(
// Create a fake Note for the account
let mut rng = OsRng;
let rseed = generate_random_rseed(zip212_enforcement(params, height), &mut rng);
let note = Note::from_parts(to, NoteValue::from(value), rseed);
let note = Note::from_parts(to, NoteValue::from_raw(value.into_u64()), rseed);
let encryptor = sapling_note_encryption(
Some(dfvk.fvk().ovk),
note.clone(),
@ -894,7 +894,11 @@ pub(crate) fn fake_compact_block_spending<P: consensus::Parameters>(
// Create a fake Note for the payment
ctx.outputs.push({
let note = Note::from_parts(to, NoteValue::from(value), rseed);
let note = Note::from_parts(
to,
sapling::value::NoteValue::from_raw(value.into_u64()),
rseed,
);
let encryptor = sapling_note_encryption(
Some(dfvk.fvk().ovk),
note.clone(),
@ -918,7 +922,7 @@ pub(crate) fn fake_compact_block_spending<P: consensus::Parameters>(
let rseed = generate_random_rseed(zip212_enforcement, &mut rng);
let note = Note::from_parts(
change_addr,
NoteValue::from((in_value - value).unwrap()),
NoteValue::from_raw((in_value - value).unwrap().into_u64()),
rseed,
);
let encryptor = sapling_note_encryption(

View File

@ -244,7 +244,7 @@ impl<P: consensus::Parameters> RusqliteMigration for Migration<P> {
&mut commitment_tree,
dfvk,
&diversifier,
&note_value.try_into().unwrap(),
&sapling::value::NoteValue::from_raw(note_value.into_u64()),
&rseed,
note_commitment_tree_position,
)?;

View File

@ -9,10 +9,7 @@ use sapling::{self, Diversifier, Nullifier, Rseed};
use zcash_primitives::{
consensus::{self, BlockHeight},
memo::MemoBytes,
transaction::{
components::{amount::NonNegativeAmount, Amount},
TxId,
},
transaction::{components::Amount, TxId},
zip32::{AccountId, Scope},
};
@ -115,7 +112,7 @@ fn to_spendable_note<P: consensus::Parameters>(
Diversifier(tmp)
};
let note_value = NonNegativeAmount::from_nonnegative_i64(row.get(4)?).map_err(|_e| {
let note_value: u64 = row.get::<_, i64>(4)?.try_into().map_err(|_e| {
SqliteClientError::CorruptedData("Note values must be nonnegative".to_string())
})?;
@ -164,7 +161,7 @@ fn to_spendable_note<P: consensus::Parameters>(
output_index,
Note::Sapling(sapling::Note::from_parts(
recipient,
note_value.into(),
sapling::value::NoteValue::from_raw(note_value),
rseed,
)),
spending_key_scope,

View File

@ -15,10 +15,18 @@ and this library adheres to Rust's notion of
`zcash_protocol::consensus` module.
- `zcash_primitives::constants` is now a reexport of the
`zcash_protocol::constants` module.
- `zcash_primitives::transaction::components::amount` is now a reexport of the
`zcash_protocol::value` module.
### Removed
- `zcash_primitives::consensus::sapling_zip212_enforcement` instead use
`zcash_primitives::transaction::components::sapling::zip212_enforcement`.
- From `zcash_primitive::components::transaction`:
- `impl From<Amount> for u64`
- `impl TryFrom<sapling::value::NoteValue> for NonNegativeAmount`
- `impl From<NonNegativeAmount> for sapling::value::NoteValue`
- `impl TryFrom<orchard::ValueSum> for Amount`
- `impl From<NonNegativeAmount> for orchard::NoteValue`
## [0.14.0] - 2024-03-01
### Added

View File

@ -118,6 +118,7 @@ temporary-zcashd = []
## Exposes APIs that are useful for testing, such as `proptest` strategies.
test-dependencies = [
"dep:proptest",
"zcash_protocol/test-dependencies",
"orchard/test-dependencies",
"sapling/test-dependencies",
]

View File

@ -1,6 +1,6 @@
//! Structs representing the components within Zcash transactions.
pub mod amount;
pub use zcash_protocol::value as amount;
pub mod orchard;
pub mod sapling;
pub mod sprout;