Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Changes required for keystone support that require dependency updates beyond what we can currently do. #1666

Draft
wants to merge 13 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 9 additions & 11 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 6 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -65,18 +65,18 @@ redjubjub = "0.7"
sapling = { package = "sapling-crypto", version = "0.4", default-features = false }

# - Orchard
nonempty = "0.7"
orchard = { version = "0.10.1", default-features = false }
pasta_curves = "0.5"

# - Transparent
bip32 = { version = "0.5", default-features = false }
ripemd = { version = "0.1", default-features = false }
secp256k1 = { version = "0.27", default-features = false, features = ["alloc"] }
secp256k1 = { version = "0.29", default-features = false, features = ["alloc"] }
transparent = { package = "zcash_transparent", version = "0.1", path = "zcash_transparent", default-features = false }

# Boilerplate & missing stdlib
getset = "0.1"
nonempty = { version = "0.11", default-features = false }

# CSPRNG
rand = { version = "0.8", default-features = false }
Expand Down Expand Up @@ -193,3 +193,7 @@ debug = true

[workspace.lints.rust]
unexpected_cfgs = { level = "warn", check-cfg = ['cfg(zcash_unstable, values("zfuture"))'] }

[patch.crates-io]
bip32 = { git = "https://github.com/KeystoneHQ/crates.git", rev = "9873e8fd56007d792fa60d6e844fdb75d527c858" }
orchard = { git = "https://github.com/zcash/orchard.git", rev = "cd3e0901ccac2c630dd7fd03eb496d5030c1bbfe" }
4 changes: 4 additions & 0 deletions components/zcash_encoding/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ and this library adheres to Rust's notion of
[Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [Unreleased]

### Changed
- Migrated to `nonempty 0.11`

## [0.2.2] - 2024-12-13
### Added
- `no-std` support, via a default-enabled `std` feature flag.
Expand Down
2 changes: 1 addition & 1 deletion devtools/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ zcash_protocol = {workspace = true, features = ["local-consensus"] }

# Transparent
secp256k1.workspace = true
transparent.workspace = true
transparent = { workspace = true, features = ["test-dependencies"] }

# Sprout
ed25519-zebra = "4"
Expand Down
5 changes: 3 additions & 2 deletions devtools/src/bin/inspect/transaction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -325,8 +325,9 @@
),
txid_parts,
);
let msg = secp256k1::Message::from_slice(sighash.as_ref())
.expect("signature_hash() returns correct length");
let msg =
secp256k1::Message::from_digest_slice(sighash.as_ref())

Check warning on line 329 in devtools/src/bin/inspect/transaction.rs

View check run for this annotation

Codecov / codecov/patch

devtools/src/bin/inspect/transaction.rs#L328-L329

Added lines #L328 - L329 were not covered by tests
.expect("signature_hash() returns correct length");

if let Err(e) = ctx.verify_ecdsa(&msg, &sig, &pubkey) {
eprintln!(" ⚠️ Spend {} is invalid: {}", i, e);
Expand Down
3 changes: 3 additions & 0 deletions pczt/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,8 @@ and this library adheres to Rust's notion of

## [Unreleased]

### Changed
- Migrated to `nonempty 0.11`

## [0.1.0] - 2024-12-16
Initial release supporting the PCZT v1 format.
92 changes: 91 additions & 1 deletion pczt/src/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,16 @@
// These are required fields that are part of the final transaction, and are filled in
// by the Creator when initializing the PCZT.
//
#[getset(get = "pub")]
pub(crate) tx_version: u32,
#[getset(get = "pub")]
pub(crate) version_group_id: u32,

/// The consensus branch ID for the chain in which this transaction will be mined.
///
/// Non-optional because this commits to the set of consensus rules that will apply to
/// the transaction; differences therein can affect every role.
#[getset(get = "pub")]
pub(crate) consensus_branch_id: u32,

/// The transaction locktime to use if no inputs specify a required locktime.
Expand All @@ -36,6 +39,7 @@
/// - If omitted, the fallback locktime is assumed to be 0.
pub(crate) fallback_lock_time: Option<u32>,

#[getset(get = "pub")]
pub(crate) expiry_height: u32,

/// The [SLIP 44] coin type, indicating the network for which this transaction is
Expand Down Expand Up @@ -181,9 +185,10 @@
}
}

#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, Getters)]
pub(crate) struct Zip32Derivation {
/// The [ZIP 32 seed fingerprint](https://zips.z.cash/zip-0032#seed-fingerprints).
#[getset(get = "pub")]
pub(crate) seed_fingerprint: [u8; 32],

/// The sequence of indices corresponding to the shielded HD path.
Expand All @@ -196,9 +201,94 @@
///
/// [BIP 44]: https://github.com/bitcoin/bips/blob/master/bip-0044.mediawiki
/// [ZIP 320]: https://zips.z.cash/zip-0320
#[getset(get = "pub")]
pub(crate) derivation_path: Vec<u32>,
}

/// Determines the lock time for the transaction.
///
/// Implemented following the specification in [BIP 370], with the rationale that this
/// makes integration of PCZTs simpler for codebases that already support PSBTs.
///
/// [BIP 370]: https://github.com/bitcoin/bips/blob/master/bip-0370.mediawiki#determining-lock-time
pub fn determine_lock_time<L: LockTimeInput>(

Check warning on line 214 in pczt/src/common.rs

View check run for this annotation

Codecov / codecov/patch

pczt/src/common.rs#L214

Added line #L214 was not covered by tests
global: &crate::common::Global,
inputs: &[L],
) -> Result<u32, ()> {

Check failure on line 217 in pczt/src/common.rs

View workflow job for this annotation

GitHub Actions / Clippy (MSRV)

this returns a `Result<_, ()>`

error: this returns a `Result<_, ()>` --> pczt/src/common.rs:214:1 | 214 | / pub fn determine_lock_time<L: LockTimeInput>( 215 | | global: &crate::common::Global, 216 | | inputs: &[L], 217 | | ) -> Result<u32, ()> { | |____________________^ | = help: use a custom `Error` type instead = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#result_unit_err = note: `-D clippy::result-unit-err` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::result_unit_err)]`
// The nLockTime field of a transaction is determined by inspecting the
// `Global.fallback_lock_time` and each input's `required_time_lock_time` and
// `required_height_lock_time` fields.

// If one or more inputs have a `required_time_lock_time` or `required_height_lock_time`,
let have_required_lock_time = inputs.iter().any(|input| {
input.required_time_lock_time().is_some() || input.required_height_lock_time().is_some()

Check warning on line 224 in pczt/src/common.rs

View check run for this annotation

Codecov / codecov/patch

pczt/src/common.rs#L223-L224

Added lines #L223 - L224 were not covered by tests
});
// then the field chosen is the one which is supported by all of the inputs. This can
// be determined by looking at all of the inputs which specify a locktime in either of
// those fields, and choosing the field which is present in all of those inputs.
// Inputs not specifying a lock time field can take both types of lock times, as can
// those that specify both.
let time_lock_time_unsupported = inputs

Check warning on line 231 in pczt/src/common.rs

View check run for this annotation

Codecov / codecov/patch

pczt/src/common.rs#L231

Added line #L231 was not covered by tests
.iter()
.any(|input| input.required_height_lock_time().is_some());
let height_lock_time_unsupported = inputs

Check warning on line 234 in pczt/src/common.rs

View check run for this annotation

Codecov / codecov/patch

pczt/src/common.rs#L233-L234

Added lines #L233 - L234 were not covered by tests
.iter()
.any(|input| input.required_time_lock_time().is_some());

Check warning on line 236 in pczt/src/common.rs

View check run for this annotation

Codecov / codecov/patch

pczt/src/common.rs#L236

Added line #L236 was not covered by tests

// The lock time chosen is then the maximum value of the chosen type of lock time.
match (
have_required_lock_time,
time_lock_time_unsupported,
height_lock_time_unsupported,

Check warning on line 242 in pczt/src/common.rs

View check run for this annotation

Codecov / codecov/patch

pczt/src/common.rs#L239-L242

Added lines #L239 - L242 were not covered by tests
) {
(true, true, true) => Err(()),
(true, false, true) => Ok(inputs
.iter()
.filter_map(|input| input.required_time_lock_time())
.max()
.expect("iterator is non-empty because have_required_lock_time is true")),

Check warning on line 249 in pczt/src/common.rs

View check run for this annotation

Codecov / codecov/patch

pczt/src/common.rs#L244-L249

Added lines #L244 - L249 were not covered by tests
// If a PSBT has both types of locktimes possible because one or more inputs
// specify both `required_time_lock_time` and `required_height_lock_time`, then a
// locktime determined by looking at the `required_height_lock_time` fields of the
// inputs must be chosen.
(true, _, false) => Ok(inputs
.iter()
.filter_map(|input| input.required_height_lock_time())
.max()
.expect("iterator is non-empty because have_required_lock_time is true")),

Check warning on line 258 in pczt/src/common.rs

View check run for this annotation

Codecov / codecov/patch

pczt/src/common.rs#L254-L258

Added lines #L254 - L258 were not covered by tests
// If none of the inputs have a `required_time_lock_time` and
// `required_height_lock_time`, then `Global.fallback_lock_time` must be used. If
// `Global.fallback_lock_time` is not provided, then it is assumed to be 0.
(false, _, _) => Ok(global.fallback_lock_time.unwrap_or(0)),

Check warning on line 262 in pczt/src/common.rs

View check run for this annotation

Codecov / codecov/patch

pczt/src/common.rs#L262

Added line #L262 was not covered by tests
}
}

pub trait LockTimeInput {
fn required_time_lock_time(&self) -> Option<u32>;
fn required_height_lock_time(&self) -> Option<u32>;
}

impl LockTimeInput for crate::transparent::Input {
fn required_time_lock_time(&self) -> Option<u32> {
self.required_time_lock_time

Check warning on line 273 in pczt/src/common.rs

View check run for this annotation

Codecov / codecov/patch

pczt/src/common.rs#L272-L273

Added lines #L272 - L273 were not covered by tests
}

fn required_height_lock_time(&self) -> Option<u32> {
self.required_height_lock_time

Check warning on line 277 in pczt/src/common.rs

View check run for this annotation

Codecov / codecov/patch

pczt/src/common.rs#L276-L277

Added lines #L276 - L277 were not covered by tests
}
}

#[cfg(feature = "transparent")]
impl LockTimeInput for ::transparent::pczt::Input {
fn required_time_lock_time(&self) -> Option<u32> {
*self.required_time_lock_time()
}

fn required_height_lock_time(&self) -> Option<u32> {
*self.required_height_lock_time()
}
}

#[cfg(test)]
mod tests {
use alloc::collections::BTreeMap;
Expand Down
9 changes: 9 additions & 0 deletions pczt/src/orchard.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,18 +33,21 @@ pub struct Bundle {
///
/// This is set by the Creator. The Constructor MUST only add spends and outputs that
/// are consistent with these flags (i.e. are dummies as appropriate).
#[getset(get = "pub")]
pub(crate) flags: u8,

/// The net value of Orchard spends minus outputs.
///
/// This is initialized by the Creator, and updated by the Constructor as spends or
/// outputs are added to the PCZT. It enables per-spend and per-output values to be
/// redacted from the PCZT after they are no longer necessary.
#[getset(get = "pub")]
pub(crate) value_sum: (u64, bool),

/// The Orchard anchor for this transaction.
///
/// Set by the Creator.
#[getset(get = "pub")]
pub(crate) anchor: [u8; 32],

/// The Orchard bundle proof.
Expand All @@ -67,6 +70,7 @@ pub struct Action {
// These are required fields that are part of the final transaction, and are filled in
// by the Constructor when adding an output.
//
#[getset(get = "pub")]
pub(crate) cv_net: [u8; 32],
#[getset(get = "pub")]
pub(crate) spend: Spend,
Expand Down Expand Up @@ -97,6 +101,7 @@ pub struct Spend {
//
#[getset(get = "pub")]
pub(crate) nullifier: [u8; 32],
#[getset(get = "pub")]
pub(crate) rk: [u8; 32],

/// The spend authorization signature.
Expand Down Expand Up @@ -183,18 +188,22 @@ pub struct Output {
// These are required fields that are part of the final transaction, and are filled in
// by the Constructor when adding an output.
//
#[getset(get = "pub")]
pub(crate) cmx: [u8; 32],
#[getset(get = "pub")]
pub(crate) ephemeral_key: [u8; 32],
/// The encrypted note plaintext for the output.
///
/// Encoded as a `Vec<u8>` because its length depends on the transaction version.
///
/// Once we have memo bundles, we will be able to set memos independently of Outputs.
/// For now, the Constructor sets both at the same time.
#[getset(get = "pub")]
pub(crate) enc_ciphertext: Vec<u8>,
/// The encrypted note plaintext for the output.
///
/// Encoded as a `Vec<u8>` because its length depends on the transaction version.
#[getset(get = "pub")]
pub(crate) out_ciphertext: Vec<u8>,

/// The [raw encoding] of the Orchard payment address that will receive the output.
Expand Down
2 changes: 2 additions & 0 deletions pczt/src/roles.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ pub mod prover;
#[cfg(feature = "signer")]
pub mod signer;

pub mod low_level_signer;

pub mod combiner;

#[cfg(feature = "spend-finalizer")]
Expand Down
Loading
Loading