Changing the Issuance Authorization Signature to the BIP 340 Schnorr scheme (#93)

This changes the issuance authorization signature from the redpallas signature scheme to the BIP 340 Schnorr signature scheme, as detailed in ZIP 227.
This commit is contained in:
Vivek Arte 2024-01-31 22:38:24 +05:30 committed by GitHub
parent 344b647d54
commit 1a1f3e7cae
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
19 changed files with 2006 additions and 1724 deletions

View File

@ -32,6 +32,7 @@ group = { version = "0.13", features = ["wnaf-memuse"] }
halo2_gadgets = { git = "https://github.com/QED-it/halo2", branch = "zsa1" }
halo2_proofs = { git = "https://github.com/QED-it/halo2", branch = "zsa1", default-features = false, features = ["batch", "floor-planner-v1-legacy-pdqsort"] }
hex = "0.4"
k256 = { version = "0.13.0", features = ["arithmetic", "schnorr"] }
lazy_static = "1"
memuse = { version = "0.2.1", features = ["nonempty"] }
pasta_curves = "0.5"
@ -53,16 +54,18 @@ plotters = { version = "0.3.0", optional = true }
[dev-dependencies]
bridgetree = "0.4"
criterion = "0.4" # 0.5 depends on clap 4 which has MSRV 1.70
criterion = "0.4" #Pinned: 0.5 depends on clap 4 which has MSRV 1.70
halo2_gadgets = { git = "https://github.com/QED-it/halo2", branch = "zsa1", features = ["test-dependencies"] }
hex = "0.4"
proptest = "1.0.0"
zcash_note_encryption_zsa = { package = "zcash_note_encryption", version = "0.4", git = "https://github.com/QED-it/zcash_note_encryption", branch = "zsa1", features = ["pre-zip-212"] }
incrementalmerkletree = { version = "0.5", features = ["test-dependencies"] }
ahash = "=0.8.6" #Pinned: 0.8.7 depends on Rust 1.72
half = "=2.2.1" #Pinned: 2.3.1 requires Rust 1.70
[target.'cfg(unix)'.dev-dependencies]
inferno = "0.11"
clap = "=4.2.0" # Used by inferno. Last version required rust 1.70
inferno = "0.11" #Pinned
clap = "=4.2.0" #Pinned: Used by inferno. Later version requires Rust 1.70
pprof = { version = "0.11", features = ["criterion", "flamegraph"] }
[lib]

View File

@ -126,7 +126,7 @@ pub(crate) mod testing {
use proptest::prelude::*;
use crate::note::asset_base::testing::arb_asset_id;
use crate::note::asset_base::testing::arb_asset_base;
use crate::{
note::{
commitment::ExtractedNoteCommitment, nullifier::testing::arb_nullifier,
@ -147,7 +147,7 @@ pub(crate) mod testing {
nf in arb_nullifier(),
rk in arb_spendauth_verification_key(),
note in arb_note(output_value),
asset in arb_asset_id()
asset in arb_asset_base()
) -> Action<()> {
let cmx = ExtractedNoteCommitment::from(note.commitment());
let cv_net = ValueCommitment::derive(
@ -180,7 +180,7 @@ pub(crate) mod testing {
note in arb_note(output_value),
rng_seed in prop::array::uniform32(prop::num::u8::ANY),
fake_sighash in prop::array::uniform32(prop::num::u8::ANY),
asset in arb_asset_id()
asset in arb_asset_base()
) -> Action<redpallas::Signature<SpendAuth>> {
let cmx = ExtractedNoteCommitment::from(note.commitment());
let cv_net = ValueCommitment::derive(

View File

@ -553,7 +553,7 @@ pub mod testing {
use super::{Action, Authorization, Authorized, Bundle, Flags};
pub use crate::action::testing::{arb_action, arb_unauthorized_action};
use crate::note::asset_base::testing::arb_zsa_asset_id;
use crate::note::asset_base::testing::arb_zsa_asset_base;
use crate::note::AssetBase;
use crate::value::testing::arb_value_sum;
@ -619,10 +619,10 @@ pub mod testing {
/// Create an arbitrary vector of assets to burn.
pub fn arb_asset_to_burn()
(
asset_id in arb_zsa_asset_id(),
asset_base in arb_zsa_asset_base(),
value in arb_value_sum()
) -> (AssetBase, ValueSum) {
(asset_id, value)
(asset_base, value)
}
}

View File

@ -83,7 +83,7 @@ mod tests {
pub fn get_burn_tuple(asset_desc: &str, value: i64) -> (AssetBase, i64) {
use crate::keys::{IssuanceAuthorizingKey, IssuanceValidatingKey};
let isk = IssuanceAuthorizingKey::from_bytes([0u8; 32]).unwrap();
let isk = IssuanceAuthorizingKey::from_bytes([1u8; 32]).unwrap();
(
AssetBase::derive(&IssuanceValidatingKey::from(&isk), asset_desc),

View File

@ -1486,7 +1486,7 @@ mod tests {
let asset_base = if is_native_asset {
AssetBase::native()
} else {
AssetBase::random(&mut rng)
AssetBase::random()
};
// Create spent_note
@ -1578,7 +1578,7 @@ mod tests {
pallas::Point::random(&mut rng).to_affine().to_bytes(),
pallas::Point::random(&mut rng).to_affine().to_bytes(),
NoteValue::from_raw(rng.next_u64()),
AssetBase::random(&mut rng),
AssetBase::random(),
pallas::Base::random(&mut rng),
pallas::Base::random(&mut rng),
NoteCommitTrapdoor(pallas::Scalar::random(&mut rng)),

View File

@ -2596,7 +2596,7 @@ mod tests {
let two_pow_254 = pallas::Base::from_u128(1 << 127).square();
let mut rng = OsRng;
let random_asset = AssetBase::random(&mut rng);
let random_asset = AssetBase::random();
// Test different values of `ak`, `nk`
let mut circuits = vec![];

View File

@ -305,7 +305,7 @@ mod tests {
let mut circuits = vec![];
let mut instances = vec![];
let native_asset = AssetBase::native();
let random_asset = AssetBase::random(&mut rng);
let random_asset = AssetBase::random();
for split_flag in [false, true] {
for asset in [native_asset, random_asset] {
let v_old = NoteValue::from_raw(rng.next_u64());

View File

@ -1,8 +1,9 @@
//! Structs related to issuance bundles and the associated logic.
use blake2b_simd::Hash as Blake2bHash;
use group::Group;
use k256::schnorr;
use nonempty::NonEmpty;
use rand::{CryptoRng, RngCore};
use rand::RngCore;
use std::collections::HashSet;
use std::fmt;
@ -15,13 +16,9 @@ use crate::issuance::Error::{
use crate::keys::{IssuanceAuthorizingKey, IssuanceValidatingKey};
use crate::note::asset_base::is_asset_desc_of_valid_size;
use crate::note::{AssetBase, Nullifier};
use crate::primitives::redpallas::Signature;
use crate::value::{NoteValue, ValueSum};
use crate::{
primitives::redpallas::{self, SpendAuth},
Address, Note,
};
use crate::{Address, Note};
use crate::supply_info::{AssetSupply, SupplyInfo};
@ -183,19 +180,14 @@ pub struct Prepared {
/// Marker for an authorized bundle.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Signed {
signature: redpallas::Signature<SpendAuth>,
signature: schnorr::Signature,
}
impl Signed {
/// Returns the signature for this authorization.
pub fn signature(&self) -> &redpallas::Signature<SpendAuth> {
pub fn signature(&self) -> &schnorr::Signature {
&self.signature
}
/// Constructs an `Signed` from its constituent parts.
pub fn from_parts(signature: Signature<SpendAuth>) -> Self {
Signed { signature }
}
}
impl IssueAuth for Unauthorized {}
@ -408,12 +400,8 @@ impl IssueBundle<Unauthorized> {
impl IssueBundle<Prepared> {
/// Sign the `IssueBundle`.
/// The call makes sure that the provided `isk` matches the `ik` and the driven `asset` for each note in the bundle.
pub fn sign<R: RngCore + CryptoRng>(
self,
mut rng: R,
isk: &IssuanceAuthorizingKey,
) -> Result<IssueBundle<Signed>, Error> {
/// The call makes sure that the provided `isk` matches the `ik` and the derived `asset` for each note in the bundle.
pub fn sign(self, isk: &IssuanceAuthorizingKey) -> Result<IssueBundle<Signed>, Error> {
let expected_ik: IssuanceValidatingKey = (isk).into();
// Make sure the `expected_ik` matches the `asset` for all notes.
@ -422,12 +410,15 @@ impl IssueBundle<Prepared> {
Ok(())
})?;
// Make sure the signature can be generated.
let signature = isk
.try_sign(&self.authorization.sighash)
.map_err(|_| IssueBundleInvalidSignature)?;
Ok(IssueBundle {
ik: self.ik,
actions: self.actions,
authorization: Signed {
signature: isk.sign(&mut rng, &self.authorization.sighash),
},
authorization: Signed { signature },
})
}
}
@ -501,7 +492,7 @@ pub fn verify_issue_bundle(
bundle
.ik
.verify(&sighash, &bundle.authorization.signature)
.map_err(IssueBundleInvalidSignature)?;
.map_err(|_| IssueBundleInvalidSignature)?;
let supply_info =
bundle
@ -543,7 +534,7 @@ pub enum Error {
/// Verification errors:
/// Invalid signature.
IssueBundleInvalidSignature(reddsa::Error),
IssueBundleInvalidSignature,
/// The provided `AssetBase` has been previously finalized.
IssueActionPreviouslyFinalizedAssetBase(AssetBase),
@ -551,8 +542,6 @@ pub enum Error {
ValueSumOverflow,
}
impl std::error::Error for Error {}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
@ -580,7 +569,7 @@ impl fmt::Display for Error {
"the AssetBase is the identity point of the Pallas curve, which is invalid."
)
}
IssueBundleInvalidSignature(_) => {
IssueBundleInvalidSignature => {
write!(f, "invalid signature")
}
IssueActionPreviouslyFinalizedAssetBase(_) => {
@ -616,7 +605,6 @@ mod tests {
use pasta_curves::pallas::{Point, Scalar};
use rand::rngs::OsRng;
use rand::RngCore;
use reddsa::Error::InvalidSignature;
use std::collections::HashSet;
fn setup_params() -> (
@ -628,7 +616,7 @@ mod tests {
) {
let mut rng = OsRng;
let isk = IssuanceAuthorizingKey::random(&mut rng);
let isk = IssuanceAuthorizingKey::random();
let ik: IssuanceValidatingKey = (&isk).into();
let fvk = FullViewingKey::from(&SpendingKey::random(&mut rng));
@ -684,12 +672,7 @@ mod tests {
fn identity_point_test_params(
note1_value: u64,
note2_value: u64,
) -> (
OsRng,
IssuanceAuthorizingKey,
IssueBundle<Unauthorized>,
[u8; 32],
) {
) -> (IssuanceAuthorizingKey, IssueBundle<Unauthorized>, [u8; 32]) {
let (mut rng, isk, ik, recipient, sighash) = setup_params();
let note1 = Note::new(
@ -713,7 +696,7 @@ mod tests {
let bundle = IssueBundle::from_parts(ik, NonEmpty::new(action), Unauthorized);
(rng, isk, bundle, sighash)
(isk, bundle, sighash)
}
#[test]
@ -734,7 +717,7 @@ mod tests {
#[test]
fn verify_supply_invalid_for_asset_base_as_identity() {
let (_, _, bundle, _) = identity_point_test_params(10, 20);
let (_, bundle, _) = identity_point_test_params(10, 20);
assert_eq!(
bundle.actions.head.verify_supply(&bundle.ik),
@ -928,7 +911,7 @@ mod tests {
)
.unwrap();
let signed = bundle.prepare(sighash).sign(rng, &isk).unwrap();
let signed = bundle.prepare(sighash).sign(&isk).unwrap();
ik.verify(&sighash, &signed.authorization.signature)
.expect("signature should be valid");
@ -949,11 +932,11 @@ mod tests {
)
.unwrap();
let wrong_isk: IssuanceAuthorizingKey = IssuanceAuthorizingKey::random(&mut OsRng);
let wrong_isk: IssuanceAuthorizingKey = IssuanceAuthorizingKey::random();
let err = bundle
.prepare([0; 32])
.sign(rng, &wrong_isk)
.sign(&wrong_isk)
.expect_err("should not be able to sign");
assert_eq!(err, IssueBundleIkMismatchAssetBase);
@ -987,7 +970,7 @@ mod tests {
let err = bundle
.prepare([0; 32])
.sign(rng, &isk)
.sign(&isk)
.expect_err("should not be able to sign");
assert_eq!(err, IssueBundleIkMismatchAssetBase);
@ -1008,7 +991,7 @@ mod tests {
)
.unwrap();
let signed = bundle.prepare(sighash).sign(rng, &isk).unwrap();
let signed = bundle.prepare(sighash).sign(&isk).unwrap();
let prev_finalized = &mut HashSet::new();
let supply_info = verify_issue_bundle(&signed, sighash, prev_finalized).unwrap();
@ -1037,7 +1020,7 @@ mod tests {
.finalize_action(String::from("Verify with finalize"))
.unwrap();
let signed = bundle.prepare(sighash).sign(rng, &isk).unwrap();
let signed = bundle.prepare(sighash).sign(&isk).unwrap();
let prev_finalized = &mut HashSet::new();
let supply_info = verify_issue_bundle(&signed, sighash, prev_finalized).unwrap();
@ -1102,7 +1085,7 @@ mod tests {
)
.unwrap();
let signed = bundle.prepare(sighash).sign(rng, &isk).unwrap();
let signed = bundle.prepare(sighash).sign(&isk).unwrap();
let prev_finalized = &mut HashSet::new();
let supply_info = verify_issue_bundle(&signed, sighash, prev_finalized).unwrap();
@ -1146,7 +1129,7 @@ mod tests {
)
.unwrap();
let signed = bundle.prepare(sighash).sign(rng, &isk).unwrap();
let signed = bundle.prepare(sighash).sign(&isk).unwrap();
let prev_finalized = &mut HashSet::new();
let final_type = AssetBase::derive(&ik, &String::from("already final"));
@ -1168,7 +1151,7 @@ mod tests {
}
}
let (mut rng, isk, ik, recipient, sighash) = setup_params();
let (rng, isk, ik, recipient, sighash) = setup_params();
let (bundle, _) = IssueBundle::new(
ik,
@ -1181,19 +1164,19 @@ mod tests {
)
.unwrap();
let wrong_isk: IssuanceAuthorizingKey = IssuanceAuthorizingKey::random(&mut rng);
let wrong_isk: IssuanceAuthorizingKey = IssuanceAuthorizingKey::random();
let mut signed = bundle.prepare(sighash).sign(rng, &isk).unwrap();
let mut signed = bundle.prepare(sighash).sign(&isk).unwrap();
signed.set_authorization(Signed {
signature: wrong_isk.sign(&mut rng, &sighash),
signature: wrong_isk.try_sign(&sighash).unwrap(),
});
let prev_finalized = &HashSet::new();
assert_eq!(
verify_issue_bundle(&signed, sighash, prev_finalized).unwrap_err(),
IssueBundleInvalidSignature(InvalidSignature)
IssueBundleInvalidSignature
);
}
@ -1212,12 +1195,12 @@ mod tests {
.unwrap();
let sighash: [u8; 32] = bundle.commitment().into();
let signed = bundle.prepare(sighash).sign(rng, &isk).unwrap();
let signed = bundle.prepare(sighash).sign(&isk).unwrap();
let prev_finalized = &HashSet::new();
assert_eq!(
verify_issue_bundle(&signed, random_sighash, prev_finalized).unwrap_err(),
IssueBundleInvalidSignature(InvalidSignature)
IssueBundleInvalidSignature
);
}
@ -1236,7 +1219,7 @@ mod tests {
)
.unwrap();
let mut signed = bundle.prepare(sighash).sign(rng, &isk).unwrap();
let mut signed = bundle.prepare(sighash).sign(&isk).unwrap();
// Add "bad" note
let note = Note::new(
@ -1274,9 +1257,9 @@ mod tests {
)
.unwrap();
let mut signed = bundle.prepare(sighash).sign(rng, &isk).unwrap();
let mut signed = bundle.prepare(sighash).sign(&isk).unwrap();
let incorrect_isk = IssuanceAuthorizingKey::random(&mut rng);
let incorrect_isk = IssuanceAuthorizingKey::random();
let incorrect_ik: IssuanceValidatingKey = (&incorrect_isk).into();
// Add "bad" note
@ -1320,7 +1303,7 @@ mod tests {
)
.unwrap();
let mut signed = bundle.prepare(sighash).sign(rng, &isk).unwrap();
let mut signed = bundle.prepare(sighash).sign(&isk).unwrap();
let prev_finalized = HashSet::new();
// 1. Try too long description
@ -1345,23 +1328,23 @@ mod tests {
#[test]
fn issue_bundle_cannot_be_signed_with_asset_base_identity_point() {
let (rng, isk, bundle, sighash) = identity_point_test_params(10, 20);
let (isk, bundle, sighash) = identity_point_test_params(10, 20);
assert_eq!(
bundle.prepare(sighash).sign(rng, &isk).unwrap_err(),
bundle.prepare(sighash).sign(&isk).unwrap_err(),
AssetBaseCannotBeIdentityPoint
);
}
#[test]
fn issue_bundle_verify_fail_asset_base_identity_point() {
let (mut rng, isk, bundle, sighash) = identity_point_test_params(10, 20);
let (isk, bundle, sighash) = identity_point_test_params(10, 20);
let signed = IssueBundle {
ik: bundle.ik,
actions: bundle.actions,
authorization: Signed {
signature: isk.sign(&mut rng, &sighash),
signature: isk.try_sign(&sighash).unwrap(),
},
};
@ -1398,24 +1381,20 @@ mod tests {
pub mod testing {
use crate::issuance::{IssueAction, IssueBundle, Prepared, Signed, Unauthorized};
use crate::keys::testing::arb_issuance_validating_key;
use crate::note::asset_base::testing::zsa_asset_id;
use crate::note::asset_base::testing::zsa_asset_base;
use crate::note::testing::arb_zsa_note;
use crate::primitives::redpallas::Signature;
use k256::schnorr;
use nonempty::NonEmpty;
use proptest::collection::vec;
use proptest::prelude::*;
use proptest::prop_compose;
use reddsa::orchard::SpendAuth;
prop_compose! {
/// Generate a uniformly distributed signature
pub(crate) fn arb_signature()(
half_bytes in prop::array::uniform32(prop::num::u8::ANY)
) -> Signature<SpendAuth> {
// prop::array can only generate 32 elements max, so we duplicate it
let sig_bytes: [u8; 64] = [half_bytes, half_bytes].concat().try_into().unwrap();
let sig: Signature<SpendAuth> = Signature::from(sig_bytes);
sig
sig_bytes in vec(prop::num::u8::ANY, 64)
) -> schnorr::Signature {
schnorr::Signature::try_from(sig_bytes.as_slice()).unwrap()
}
}
@ -1423,7 +1402,7 @@ pub mod testing {
/// Generate an issue action
pub fn arb_issue_action(asset_desc: String)
(
asset in zsa_asset_id(asset_desc.clone()),
asset in zsa_asset_base(asset_desc.clone()),
)
(
note in arb_zsa_note(asset),

View File

@ -1,7 +1,10 @@
//! Key structures for Orchard.
use core::mem;
use std::io::{self, Read, Write};
use std::{
fmt::{Debug, Formatter},
io::{self, Read, Write},
};
use aes::Aes256;
use blake2b_simd::{Hash as Blake2bHash, Params};
@ -11,8 +14,16 @@ use group::{
prime::PrimeCurveAffine,
Curve, GroupEncoding,
};
use k256::{
schnorr,
schnorr::{
signature::hazmat::{PrehashSigner, PrehashVerifier},
Signature, VerifyingKey,
},
NonZeroScalar,
};
use pasta_curves::{pallas, pallas::Scalar};
use rand::{CryptoRng, RngCore};
use rand::{rngs::OsRng, RngCore};
use subtle::{Choice, ConditionallySelectable, ConstantTimeEq, CtOption};
use zcash_note_encryption_zsa::EphemeralKeyBytes;
@ -218,28 +229,13 @@ fn check_structural_validity(
}
}
/// We currently use `SpendAuth` as the `IssuanceAuth`.
type IssuanceAuth = SpendAuth;
/// An issuance key, from which all key material is derived.
///
/// $\mathsf{isk}$ as defined in [ZIP 227][issuancekeycomponents].
///
/// [issuancekeycomponents]: https://qed-it.github.io/zips/zip-0227#issuance-key-derivation
#[derive(Debug, Copy, Clone)]
pub struct IssuanceAuthorizingKey([u8; 32]);
impl From<SpendingKey> for IssuanceAuthorizingKey {
fn from(sk: SpendingKey) -> Self {
IssuanceAuthorizingKey(*sk.to_bytes())
}
}
impl ConstantTimeEq for IssuanceAuthorizingKey {
fn ct_eq(&self, other: &Self) -> Choice {
self.to_bytes().ct_eq(other.to_bytes())
}
}
#[derive(Copy, Clone)]
pub struct IssuanceAuthorizingKey(NonZeroScalar);
impl IssuanceAuthorizingKey {
/// Generates a random issuance key.
@ -248,21 +244,23 @@ impl IssuanceAuthorizingKey {
/// Real issuance keys should be derived according to [ZIP 32].
///
/// [ZIP 32]: https://zips.z.cash/zip-0032
pub(crate) fn random(rng: &mut impl RngCore) -> Self {
SpendingKey::random(rng).into()
pub(crate) fn random() -> Self {
IssuanceAuthorizingKey(NonZeroScalar::random(&mut OsRng))
}
/// Constructs an Orchard issuance key from uniformly-random bytes.
///
/// Returns `None` if the bytes do not correspond to a valid Orchard issuance key.
pub fn from_bytes(isk_bytes: [u8; 32]) -> CtOption<Self> {
let isk = IssuanceAuthorizingKey(isk_bytes);
CtOption::new(isk, 1u8.into())
pub fn from_bytes(isk_bytes: [u8; 32]) -> Option<Self> {
NonZeroScalar::try_from(&isk_bytes as &[u8])
.ok()
.map(IssuanceAuthorizingKey)
}
/// Returns the raw bytes of the issuance key.
pub fn to_bytes(&self) -> &[u8; 32] {
&self.0
/// Unwrap call never fails since the issuance authorizing key is exactly 32 bytes.
pub fn to_bytes(&self) -> [u8; 32] {
self.0.to_bytes().try_into().unwrap()
}
/// Derives the Orchard-ZSA issuance key for the given seed, coin type, and account.
@ -277,81 +275,74 @@ impl IssuanceAuthorizingKey {
ChildIndex::try_from(coin_type)?,
ChildIndex::try_from(account)?,
];
ExtendedSpendingKey::from_path(seed, path, ZIP32_ORCHARD_PERSONALIZATION_FOR_ISSUANCE)
.map(|esk| esk.sk().into())
}
/// Derives the RedPallas signing key from isk. Internal use only, does not enforce all constraints.
fn derive_inner(&self) -> pallas::Scalar {
to_scalar(PrfExpand::ZsaIsk.expand(&self.0))
// we are reusing zip32 logic for deriving the key, zip32 should be updated as discussed
let &isk_bytes =
ExtendedSpendingKey::from_path(seed, path, ZIP32_ORCHARD_PERSONALIZATION_FOR_ISSUANCE)?
.sk()
.to_bytes();
IssuanceAuthorizingKey::from_bytes(isk_bytes).ok_or(zip32::Error::InvalidSpendingKey)
}
/// Sign the provided message using the `IssuanceAuthorizingKey`.
pub fn sign(
&self,
rng: &mut (impl RngCore + CryptoRng),
msg: &[u8],
) -> redpallas::Signature<IssuanceAuth> {
conditionally_negate(self.derive_inner()).sign(rng, msg)
/// Only supports signing of messages of length 32 bytes, since we will only be using it to sign 32 byte SIGHASH values.
pub fn try_sign(&self, msg: &[u8; 32]) -> Result<Signature, schnorr::Error> {
schnorr::SigningKey::from(self.0).sign_prehash(msg)
}
}
impl Debug for IssuanceAuthorizingKey {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
f.debug_tuple("IssuanceAuthorizingKey")
.field(&self.0.to_bytes())
.finish()
}
}
/// A key used to validate issuance authorization signatures.
///
/// Defined in [ZIP 227: Issuance of Zcash Shielded Assets § Issuance Key Generation][IssuanceZSA].
/// Note that this is $\mathsf{ik}^\mathbb{P}$, which by construction is equivalent to
/// $\mathsf{ik}$ but stored here as a RedPallas verification key.
///
/// [IssuanceZSA]: https://qed-it.github.io/zips/zip-0227#issuance-key-derivation
#[derive(Debug, Clone, PartialOrd, Ord)]
pub struct IssuanceValidatingKey(VerificationKey<IssuanceAuth>);
#[derive(Debug, Clone)]
pub struct IssuanceValidatingKey(schnorr::VerifyingKey);
impl From<&IssuanceAuthorizingKey> for IssuanceValidatingKey {
fn from(isk: &IssuanceAuthorizingKey) -> Self {
IssuanceValidatingKey((&(conditionally_negate(isk.derive_inner()))).into())
}
}
impl From<&IssuanceValidatingKey> for pallas::Point {
fn from(issuance_validating_key: &IssuanceValidatingKey) -> pallas::Point {
pallas::Point::from_bytes(&(&issuance_validating_key.0).into()).unwrap()
IssuanceValidatingKey(*schnorr::SigningKey::from(isk.0).verifying_key())
}
}
impl PartialEq for IssuanceValidatingKey {
fn eq(&self, other: &Self) -> bool {
<[u8; 32]>::from(&self.0).eq(&<[u8; 32]>::from(&other.0))
self.to_bytes().eq(&other.to_bytes())
}
}
impl Eq for IssuanceValidatingKey {}
impl IssuanceValidatingKey {
/// Converts this spend validating key to its serialized form,
/// I2LEOSP_256(ik).
/// Converts this issuance validating key to its serialized form,
/// in big-endian order as defined in BIP 340.
/// Unwrap call never fails since the issuance validating key is exactly 32 bytes.
pub fn to_bytes(&self) -> [u8; 32] {
// This is correct because the wrapped point must have ỹ = 0, and
// so the point repr is the same as I2LEOSP of its x-coordinate.
<[u8; 32]>::from(&self.0)
self.0.to_bytes().try_into().unwrap()
}
/// Constructs an Orchard issuance validating key from uniformly-random bytes.
/// Constructs an Orchard issuance validating key from the provided bytes.
/// The bytes are assumed to be encoded in big-endian order.
///
/// Returns `None` if the bytes do not correspond to a valid key.
pub fn from_bytes(bytes: &[u8]) -> Option<Self> {
<[u8; 32]>::try_from(bytes)
VerifyingKey::from_bytes(bytes)
.ok()
.and_then(check_structural_validity)
.map(IssuanceValidatingKey)
}
/// Verifies a purported `signature` over `msg` made by this verification key.
pub fn verify(
&self,
msg: &[u8],
signature: &redpallas::Signature<IssuanceAuth>,
) -> Result<(), reddsa::Error> {
self.0.verify(msg, signature)
pub fn verify(&self, msg: &[u8], signature: &Signature) -> Result<(), schnorr::Error> {
self.0.verify_prehash(msg, signature)
}
}
@ -1118,8 +1109,8 @@ pub mod testing {
key in prop::array::uniform32(prop::num::u8::ANY)
.prop_map(IssuanceAuthorizingKey::from_bytes)
.prop_filter(
"Values must correspond to valid Orchard issuance keys.",
|opt| bool::from(opt.is_some())
"Values must correspond to valid Orchard-ZSA issuance keys.",
|opt| opt.is_some()
)
) -> IssuanceAuthorizingKey {
key.unwrap()
@ -1198,6 +1189,21 @@ mod tests {
));
}
#[test]
fn issuance_authorizing_key_from_bytes_fail_on_zero() {
// isk must not be the zero scalar.
let isk = IssuanceAuthorizingKey::from_bytes([0; 32]);
assert!(isk.is_none());
}
#[test]
fn issuance_authorizing_key_from_bytes_to_bytes_roundtrip() {
let isk = IssuanceAuthorizingKey::random();
let isk_bytes = isk.to_bytes();
let isk_roundtrip = IssuanceAuthorizingKey::from_bytes(isk_bytes).unwrap();
assert_eq!(isk_bytes, isk_roundtrip.to_bytes());
}
proptest! {
#[test]
fn key_agreement(
@ -1235,13 +1241,13 @@ mod tests {
let ask: SpendAuthorizingKey = (&sk).into();
assert_eq!(<[u8; 32]>::from(&ask.0), tv.ask);
let isk = IssuanceAuthorizingKey::from_bytes(tv.sk).unwrap();
let isk = IssuanceAuthorizingKey::from_bytes(tv.isk).unwrap();
let ak: SpendValidatingKey = (&ask).into();
assert_eq!(<[u8; 32]>::from(ak.0), tv.ak);
let ik: IssuanceValidatingKey = (&isk).into();
assert_eq!(<[u8; 32]>::from(ik.0), tv.ik);
assert_eq!(ik.to_bytes(), tv.ik);
let nk: NullifierDerivingKey = (&sk).into();
assert_eq!(nk.0.to_repr(), tv.nk);
@ -1288,4 +1294,22 @@ mod tests {
assert_eq!(internal_ovk.0, tv.internal_ovk);
}
}
#[test]
fn issuance_auth_sig_test_vectors() {
for tv in crate::test_vectors::issuance_auth_sig::test_vectors() {
let isk = IssuanceAuthorizingKey::from_bytes(tv.isk).unwrap();
let ik = IssuanceValidatingKey::from(&isk);
assert_eq!(ik.to_bytes(), tv.ik);
let message = tv.msg;
let signature = isk.try_sign(&message).unwrap();
let sig_bytes: [u8; 64] = signature.to_bytes();
assert_eq!(sig_bytes, tv.sig);
assert!(ik.verify(&message, &signature).is_ok());
}
}
}

View File

@ -334,7 +334,7 @@ impl fmt::Debug for TransmittedNoteCiphertext {
pub mod testing {
use proptest::prelude::*;
use crate::note::asset_base::testing::arb_asset_id;
use crate::note::asset_base::testing::arb_asset_base;
use crate::note::AssetBase;
use crate::value::testing::arb_note_value;
use crate::{
@ -358,7 +358,7 @@ pub mod testing {
recipient in arb_address(),
rho in arb_nullifier(),
rseed in arb_rseed(),
asset in arb_asset_id(),
asset in arb_asset_base(),
) -> Note {
Note {
recipient,

View File

@ -2,7 +2,6 @@ use blake2b_simd::{Hash as Blake2bHash, Params};
use group::{Group, GroupEncoding};
use halo2_proofs::arithmetic::CurveExt;
use pasta_curves::pallas;
use rand::RngCore;
use std::hash::{Hash, Hasher};
use subtle::{Choice, ConstantTimeEq, CtOption};
@ -101,8 +100,8 @@ impl AssetBase {
/// Generates a ZSA random asset.
///
/// This is only used in tests.
pub(crate) fn random(rng: &mut impl RngCore) -> Self {
let isk = IssuanceAuthorizingKey::random(rng);
pub(crate) fn random() -> Self {
let isk = IssuanceAuthorizingKey::random();
let ik = IssuanceValidatingKey::from(&isk);
let asset_descr = "zsa_asset";
AssetBase::derive(&ik, asset_descr)
@ -139,7 +138,7 @@ pub mod testing {
prop_compose! {
/// Generate a uniformly distributed note type
pub fn arb_asset_id()(
pub fn arb_asset_base()(
is_native in prop::bool::ANY,
isk in arb_issuance_authorizing_key(),
str in "[A-Za-z]{255}",
@ -154,7 +153,7 @@ pub mod testing {
prop_compose! {
/// Generate the native note type
pub fn native_asset_id()(_i in 0..10) -> AssetBase {
pub fn native_asset_base()(_i in 0..10) -> AssetBase {
// TODO: remove _i
AssetBase::native()
}
@ -162,7 +161,7 @@ pub mod testing {
prop_compose! {
/// Generate an asset ID
pub fn arb_zsa_asset_id()(
pub fn arb_zsa_asset_base()(
isk in arb_issuance_authorizing_key(),
str in "[A-Za-z]{255}"
) -> AssetBase {
@ -172,7 +171,7 @@ pub mod testing {
prop_compose! {
/// Generate an asset ID using a specific description
pub fn zsa_asset_id(asset_desc: String)(
pub fn zsa_asset_base(asset_desc: String)(
isk in arb_issuance_authorizing_key(),
) -> AssetBase {
assert!(super::is_asset_desc_of_valid_size(&asset_desc));
@ -182,7 +181,7 @@ pub mod testing {
#[test]
fn test_vectors() {
let test_vectors = crate::test_vectors::asset_id::test_vectors();
let test_vectors = crate::test_vectors::asset_base::test_vectors();
for tv in test_vectors {
let description = std::str::from_utf8(&tv.description).unwrap();

View File

@ -82,7 +82,7 @@ mod tests {
fn create_test_asset(asset_desc: &str) -> AssetBase {
use crate::keys::{IssuanceAuthorizingKey, IssuanceValidatingKey};
let isk = IssuanceAuthorizingKey::from_bytes([0u8; 32]).unwrap();
let isk = IssuanceAuthorizingKey::from_bytes([1u8; 32]).unwrap();
AssetBase::derive(&IssuanceValidatingKey::from(&isk), asset_desc)
}

View File

@ -1,5 +1,6 @@
pub(crate) mod asset_id;
pub(crate) mod asset_base;
pub(crate) mod commitment_tree;
pub(crate) mod issuance_auth_sig;
pub(crate) mod keys;
pub(crate) mod merkle_path;
pub(crate) mod note_encryption;

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,277 @@
// From https://github.com/zcash-hackworks/zcash-test-vectors/ (issuance_auth_sig)
pub(crate) struct TestVector {
pub(crate) isk: [u8; 32],
pub(crate) ik: [u8; 32],
pub(crate) msg: [u8; 32],
pub(crate) sig: [u8; 64],
}
pub(crate) fn test_vectors() -> Vec<TestVector> {
vec![
TestVector {
isk: [
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x03,
],
ik: [
0xf9, 0x30, 0x8a, 0x01, 0x92, 0x58, 0xc3, 0x10, 0x49, 0x34, 0x4f, 0x85, 0xf8, 0x9d,
0x52, 0x29, 0xb5, 0x31, 0xc8, 0x45, 0x83, 0x6f, 0x99, 0xb0, 0x86, 0x01, 0xf1, 0x13,
0xbc, 0xe0, 0x36, 0xf9,
],
msg: [
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
],
sig: [
0xe9, 0x07, 0x83, 0x1f, 0x80, 0x84, 0x8d, 0x10, 0x69, 0xa5, 0x37, 0x1b, 0x40, 0x24,
0x10, 0x36, 0x4b, 0xdf, 0x1c, 0x5f, 0x83, 0x07, 0xb0, 0x08, 0x4c, 0x55, 0xf1, 0xce,
0x2d, 0xca, 0x82, 0x15, 0x25, 0xf6, 0x6a, 0x4a, 0x85, 0xea, 0x8b, 0x71, 0xe4, 0x82,
0xa7, 0x4f, 0x38, 0x2d, 0x2c, 0xe5, 0xeb, 0xee, 0xe8, 0xfd, 0xb2, 0x17, 0x2f, 0x47,
0x7d, 0xf4, 0x90, 0x0d, 0x31, 0x05, 0x36, 0xc0,
],
},
TestVector {
isk: [
0x5d, 0x7a, 0x8f, 0x73, 0x9a, 0x2d, 0x9e, 0x94, 0x5b, 0x0c, 0xe1, 0x52, 0xa8, 0x04,
0x9e, 0x29, 0x4c, 0x4d, 0x6e, 0x66, 0xb1, 0x64, 0x93, 0x9d, 0xaf, 0xfa, 0x2e, 0xf6,
0xee, 0x69, 0x21, 0x48,
],
ik: [
0x4b, 0xec, 0xe1, 0xff, 0x00, 0xe2, 0xed, 0x77, 0x64, 0xae, 0x6b, 0xe2, 0x0d, 0x2f,
0x67, 0x22, 0x04, 0xfc, 0x86, 0xcc, 0xed, 0xd6, 0xfc, 0x1f, 0x71, 0xdf, 0x02, 0xc7,
0x51, 0x6d, 0x9f, 0x31,
],
msg: [
0x1c, 0xdd, 0x86, 0xb3, 0xcc, 0x43, 0x18, 0xd9, 0x61, 0x4f, 0xc8, 0x20, 0x90, 0x5d,
0x04, 0x2b, 0xb1, 0xef, 0x9c, 0xa3, 0xf2, 0x49, 0x88, 0xc7, 0xb3, 0x53, 0x42, 0x01,
0xcf, 0xb1, 0xcd, 0x8d,
],
sig: [
0xa5, 0xb5, 0x92, 0x78, 0x1b, 0xeb, 0x55, 0xee, 0xbf, 0x8b, 0xc2, 0xbf, 0xd7, 0x9d,
0xa9, 0x45, 0x2d, 0xc9, 0x22, 0x39, 0x87, 0x7e, 0xb7, 0xe1, 0xf5, 0x64, 0x65, 0xff,
0x11, 0x1e, 0x59, 0x08, 0xde, 0xac, 0x15, 0xd5, 0x69, 0x99, 0x9a, 0x2b, 0xd2, 0x2b,
0x2e, 0xf6, 0x01, 0xc5, 0x81, 0x3b, 0xdb, 0xba, 0x99, 0x3c, 0x08, 0xd4, 0xe8, 0x56,
0xc9, 0x26, 0xd9, 0xe2, 0xc0, 0x63, 0x93, 0x67,
],
},
TestVector {
isk: [
0xbf, 0x69, 0xb8, 0x25, 0x0c, 0x18, 0xef, 0x41, 0x29, 0x4c, 0xa9, 0x79, 0x93, 0xdb,
0x54, 0x6c, 0x1f, 0xe0, 0x1f, 0x7e, 0x9c, 0x8e, 0x36, 0xd6, 0xa5, 0xe2, 0x9d, 0x4e,
0x30, 0xa7, 0x35, 0x94,
],
ik: [
0xd4, 0x22, 0x9e, 0x19, 0x5e, 0x25, 0xf6, 0x02, 0xa2, 0x18, 0x61, 0x22, 0xcb, 0x4e,
0x78, 0x76, 0x7b, 0x3c, 0x66, 0xac, 0x39, 0x08, 0x08, 0xd2, 0xd1, 0xb4, 0x04, 0x42,
0xda, 0x7f, 0x00, 0x66,
],
msg: [
0xbf, 0x50, 0x98, 0x42, 0x1c, 0x69, 0x37, 0x8a, 0xf1, 0xe4, 0x0f, 0x64, 0xe1, 0x25,
0x94, 0x6f, 0x62, 0xc2, 0xfa, 0x7b, 0x2f, 0xec, 0xbc, 0xb6, 0x4b, 0x69, 0x68, 0x91,
0x2a, 0x63, 0x81, 0xce,
],
sig: [
0x18, 0x8b, 0x15, 0x57, 0x42, 0x87, 0x83, 0x55, 0x6b, 0x66, 0x80, 0x3b, 0xf9, 0x06,
0x63, 0xb7, 0xa1, 0x6d, 0x43, 0x76, 0x92, 0x7c, 0x58, 0x35, 0xe0, 0xb7, 0x26, 0x52,
0x0e, 0xb2, 0x6d, 0x53, 0x24, 0x99, 0x10, 0xc3, 0x9c, 0x5f, 0x05, 0x90, 0xb6, 0xd6,
0xaa, 0xb3, 0x51, 0xff, 0x8c, 0xd8, 0xe0, 0x63, 0xfa, 0x74, 0x20, 0x42, 0x55, 0xda,
0xdc, 0x00, 0xd9, 0xe0, 0xdf, 0xf7, 0x7b, 0x09,
],
},
TestVector {
isk: [
0x3d, 0xc1, 0x66, 0xd5, 0x6a, 0x1d, 0x62, 0xf5, 0xa8, 0xd7, 0x55, 0x1d, 0xb5, 0xfd,
0x93, 0x13, 0xe8, 0xc7, 0x20, 0x3d, 0x99, 0x6a, 0xf7, 0xd4, 0x77, 0x08, 0x37, 0x56,
0xd5, 0x9a, 0xf8, 0x0d,
],
ik: [
0xce, 0xb7, 0x5a, 0x43, 0x9f, 0xf0, 0x16, 0x15, 0x80, 0xbf, 0x29, 0x57, 0x24, 0xc6,
0xd9, 0x2d, 0x31, 0xb7, 0xaa, 0x02, 0x84, 0x03, 0x39, 0x44, 0x49, 0x64, 0x48, 0x6f,
0xae, 0xa8, 0x90, 0xe5,
],
msg: [
0x06, 0xa7, 0x45, 0xf4, 0x4a, 0xb0, 0x23, 0x75, 0x2c, 0xb5, 0xb4, 0x06, 0xed, 0x89,
0x85, 0xe1, 0x81, 0x30, 0xab, 0x33, 0x36, 0x26, 0x97, 0xb0, 0xe4, 0xe4, 0xc7, 0x63,
0xcc, 0xb8, 0xf6, 0x76,
],
sig: [
0x6e, 0x5e, 0xd6, 0x65, 0x6c, 0x32, 0x71, 0x32, 0xb1, 0x65, 0x81, 0x06, 0x2f, 0x1b,
0x13, 0x8a, 0xcc, 0x6f, 0x1f, 0x83, 0x43, 0xed, 0x9d, 0x89, 0xab, 0x5f, 0xd9, 0x38,
0xe4, 0xe6, 0xce, 0xf7, 0x99, 0xa2, 0x25, 0x1c, 0xa5, 0x2d, 0x60, 0x82, 0x0e, 0x51,
0x00, 0x25, 0x06, 0x7d, 0xcd, 0x1b, 0xf7, 0x54, 0xc5, 0xbf, 0xf1, 0x39, 0xb4, 0xcc,
0x44, 0xb3, 0x7d, 0x27, 0xd1, 0x7c, 0x4a, 0xee,
],
},
TestVector {
isk: [
0x49, 0x5c, 0x22, 0x2f, 0x7f, 0xba, 0x1e, 0x31, 0xde, 0xfa, 0x3d, 0x5a, 0x57, 0xef,
0xc2, 0xe1, 0xe9, 0xb0, 0x1a, 0x03, 0x55, 0x87, 0xd5, 0xfb, 0x1a, 0x38, 0xe0, 0x1d,
0x94, 0x90, 0x3d, 0x3c,
],
ik: [
0xb0, 0xfa, 0x9d, 0x77, 0xfc, 0xbd, 0x96, 0x45, 0x91, 0x32, 0xe3, 0x05, 0xe3, 0x24,
0xe7, 0x93, 0x6a, 0xe1, 0x3b, 0x15, 0x14, 0x7e, 0x20, 0x5d, 0x7b, 0xae, 0x42, 0xfa,
0x7f, 0xaf, 0x5d, 0x1e,
],
msg: [
0x3e, 0x0a, 0xd3, 0x36, 0x0c, 0x1d, 0x37, 0x10, 0xac, 0xd2, 0x0b, 0x18, 0x3e, 0x31,
0xd4, 0x9f, 0x25, 0xc9, 0xa1, 0x38, 0xf4, 0x9b, 0x1a, 0x53, 0x7e, 0xdc, 0xf0, 0x4b,
0xe3, 0x4a, 0x98, 0x51,
],
sig: [
0x17, 0xc2, 0xe5, 0xdf, 0x2e, 0xa6, 0xa1, 0x2e, 0x8a, 0xb2, 0xb0, 0xd5, 0x04, 0x89,
0x8f, 0x3f, 0x23, 0x43, 0xe0, 0x98, 0x90, 0x7f, 0x7a, 0xfe, 0x43, 0xac, 0x8a, 0x01,
0x14, 0x42, 0x35, 0x80, 0x97, 0x53, 0x67, 0xba, 0x4b, 0x6d, 0x16, 0x6c, 0x44, 0x28,
0x48, 0x57, 0xb7, 0xcd, 0x29, 0xa8, 0x38, 0xb4, 0x9c, 0xc3, 0x41, 0xd2, 0x89, 0x51,
0xaa, 0x0b, 0x5d, 0x55, 0x6a, 0x20, 0x9e, 0xb6,
],
},
TestVector {
isk: [
0xa7, 0xaf, 0x9d, 0xb6, 0x99, 0x0e, 0xd8, 0x3d, 0xd6, 0x4a, 0xf3, 0x59, 0x7c, 0x04,
0x32, 0x3e, 0xa5, 0x1b, 0x00, 0x52, 0xad, 0x80, 0x84, 0xa8, 0xb9, 0xda, 0x94, 0x8d,
0x32, 0x0d, 0xad, 0xd6,
],
ik: [
0x0b, 0xb4, 0x91, 0x3d, 0xba, 0xf1, 0x4e, 0xf6, 0xd0, 0xad, 0xeb, 0x8b, 0x70, 0x27,
0xbf, 0x0b, 0x9a, 0x8f, 0x59, 0x0d, 0x3e, 0x2d, 0x95, 0xa1, 0x2d, 0xba, 0xaf, 0x0b,
0x95, 0x33, 0xdc, 0xa4,
],
msg: [
0x4f, 0x54, 0x31, 0xe6, 0x1d, 0xdf, 0x65, 0x8d, 0x24, 0xae, 0x67, 0xc2, 0x2c, 0x8d,
0x13, 0x09, 0x13, 0x1f, 0xc0, 0x0f, 0xe7, 0xf2, 0x35, 0x73, 0x42, 0x76, 0xd3, 0x8d,
0x47, 0xf1, 0xe1, 0x91,
],
sig: [
0x42, 0x1f, 0x5b, 0x07, 0x57, 0x2e, 0x6b, 0x05, 0xe8, 0x0b, 0xa5, 0x85, 0xff, 0x63,
0x21, 0x42, 0x26, 0x75, 0xcd, 0x19, 0xea, 0x59, 0x15, 0xd6, 0x32, 0xeb, 0x47, 0x64,
0x6c, 0xe2, 0x20, 0x27, 0x6b, 0xb7, 0x82, 0x42, 0xcc, 0x75, 0x48, 0xd9, 0xa0, 0x57,
0x2b, 0x89, 0x69, 0x2e, 0x5b, 0x95, 0xdb, 0x14, 0x14, 0xe4, 0xeb, 0xd2, 0x20, 0xcc,
0xf8, 0x3a, 0xf2, 0x98, 0x2f, 0xdd, 0x3a, 0xec,
],
},
TestVector {
isk: [
0xe0, 0x0c, 0x7a, 0x1d, 0x48, 0xaf, 0x04, 0x68, 0x27, 0x59, 0x1e, 0x97, 0x33, 0xa9,
0x7f, 0xa6, 0xb6, 0x79, 0xf3, 0xdc, 0x60, 0x1d, 0x00, 0x82, 0x85, 0xed, 0xcb, 0xda,
0xe6, 0x9c, 0xe8, 0xfc,
],
ik: [
0x61, 0xbb, 0x33, 0x91, 0x59, 0xdf, 0x98, 0x20, 0xef, 0xae, 0xb6, 0x1d, 0x9a, 0x10,
0xcd, 0xc1, 0x3b, 0x4c, 0x99, 0xfd, 0xc8, 0x6d, 0x94, 0x85, 0x11, 0x5d, 0xfd, 0x83,
0x62, 0x36, 0xac, 0xf8,
],
msg: [
0x1b, 0xe4, 0xaa, 0xc0, 0x0f, 0xf2, 0x71, 0x1e, 0xbd, 0x93, 0x1d, 0xe5, 0x18, 0x85,
0x68, 0x78, 0xf7, 0x34, 0x76, 0xf2, 0x1a, 0x48, 0x2e, 0xc9, 0x37, 0x83, 0x65, 0xc8,
0xf7, 0x39, 0x3c, 0x94,
],
sig: [
0x5a, 0x11, 0x48, 0xa8, 0x92, 0x8f, 0xbf, 0x43, 0xbb, 0x33, 0xa5, 0x70, 0xf0, 0xdf,
0xa3, 0x53, 0x32, 0xb7, 0x01, 0x80, 0x21, 0xa0, 0xcb, 0x75, 0xe9, 0x55, 0x4e, 0x86,
0xec, 0xb2, 0x1d, 0xa3, 0x2e, 0xb5, 0xa2, 0xd8, 0xc5, 0x9e, 0xa3, 0x90, 0x43, 0xb9,
0x74, 0x78, 0x75, 0x0c, 0x6b, 0xf8, 0x66, 0xeb, 0x3b, 0x01, 0x5e, 0xbb, 0x31, 0x68,
0xf7, 0x53, 0x76, 0x6a, 0xd1, 0x71, 0xd2, 0x1e,
],
},
TestVector {
isk: [
0xe2, 0x88, 0x53, 0x15, 0xeb, 0x46, 0x71, 0x09, 0x8b, 0x79, 0x53, 0x5e, 0x79, 0x0f,
0xe5, 0x3e, 0x29, 0xfe, 0xf2, 0xb3, 0x76, 0x66, 0x97, 0xac, 0x32, 0xb4, 0xf4, 0x73,
0xf4, 0x68, 0xa0, 0x08,
],
ik: [
0x19, 0x58, 0x53, 0x8b, 0x12, 0x17, 0xa0, 0x3d, 0x89, 0xcd, 0x83, 0xb8, 0x3d, 0x0b,
0xdd, 0x40, 0xa6, 0x9a, 0xbe, 0x3a, 0xc2, 0x5d, 0x00, 0xc6, 0xd2, 0x69, 0x97, 0xf9,
0xf2, 0x57, 0x4d, 0x4f,
],
msg: [
0xe7, 0x23, 0x89, 0xfc, 0x03, 0x88, 0x0d, 0x78, 0x0c, 0xb0, 0x7f, 0xcf, 0xaa, 0xbe,
0x3f, 0x1a, 0x84, 0xb2, 0x7d, 0xb5, 0x9a, 0x4a, 0x15, 0x3d, 0x88, 0x2d, 0x2b, 0x21,
0x03, 0x59, 0x65, 0x55,
],
sig: [
0x16, 0x90, 0xf5, 0x43, 0xee, 0x67, 0xbb, 0x1c, 0xe0, 0xe4, 0x25, 0x4e, 0xa5, 0xdf,
0xd0, 0x42, 0xfe, 0x86, 0x3a, 0xb4, 0x6c, 0xd9, 0xa8, 0x90, 0x55, 0x19, 0xff, 0xb1,
0xb8, 0x40, 0x6b, 0xec, 0xbd, 0x90, 0xda, 0x66, 0xe5, 0xb5, 0x44, 0xbc, 0xd4, 0x3b,
0xdb, 0x29, 0xbc, 0x5d, 0x2c, 0x02, 0x4d, 0xd2, 0x85, 0xab, 0xcd, 0x77, 0xe4, 0xac,
0x1f, 0x9d, 0x60, 0x35, 0x22, 0xe4, 0xf1, 0x5b,
],
},
TestVector {
isk: [
0xed, 0x94, 0x94, 0xc6, 0xac, 0x89, 0x3c, 0x49, 0x72, 0x38, 0x33, 0xec, 0x89, 0x26,
0xc1, 0x03, 0x95, 0x86, 0xa7, 0xaf, 0xcf, 0x4a, 0x0d, 0x9c, 0x73, 0x1e, 0x98, 0x5d,
0x99, 0x58, 0x9c, 0x8b,
],
ik: [
0x7d, 0xd6, 0xd7, 0x61, 0xe1, 0x02, 0x01, 0x37, 0xfa, 0x01, 0xb4, 0xdd, 0xd3, 0xb0,
0xf3, 0x48, 0x04, 0xcc, 0x10, 0xcc, 0x4e, 0x9f, 0x6e, 0x9d, 0xf5, 0xb6, 0x04, 0x69,
0xf5, 0x79, 0x36, 0x67,
],
msg: [
0xb8, 0x38, 0xe8, 0xaa, 0xf7, 0x45, 0x53, 0x3e, 0xd9, 0xe8, 0xae, 0x3a, 0x1c, 0xd0,
0x74, 0xa5, 0x1a, 0x20, 0xda, 0x8a, 0xba, 0x18, 0xd1, 0xdb, 0xeb, 0xbc, 0x86, 0x2d,
0xed, 0x42, 0x43, 0x5e,
],
sig: [
0x59, 0x34, 0x5d, 0x6b, 0x89, 0x4e, 0xd6, 0xd0, 0x3a, 0x56, 0x73, 0xa0, 0x14, 0x63,
0x07, 0x51, 0x04, 0x3d, 0x11, 0xfa, 0x63, 0x18, 0x7c, 0x92, 0x9c, 0xae, 0x3f, 0xa1,
0xb0, 0x29, 0x22, 0xf2, 0x7d, 0xc0, 0x16, 0x40, 0x33, 0x95, 0x2c, 0x84, 0x16, 0xe6,
0xd0, 0x43, 0x81, 0x77, 0xb3, 0xbc, 0xe8, 0x78, 0xfd, 0xec, 0x75, 0x0a, 0x16, 0x64,
0xd4, 0x89, 0xdf, 0x0a, 0x4e, 0xae, 0xb1, 0x35,
],
},
TestVector {
isk: [
0x92, 0x47, 0x69, 0x30, 0xd0, 0x69, 0x89, 0x6c, 0xff, 0x30, 0xeb, 0x41, 0x4f, 0x72,
0x7b, 0x89, 0xe0, 0x01, 0xaf, 0xa2, 0xfb, 0x8d, 0xc3, 0x43, 0x6d, 0x75, 0xa4, 0xa6,
0xf2, 0x65, 0x72, 0x50,
],
ik: [
0xb5, 0x9c, 0x5f, 0x32, 0x34, 0xd6, 0xca, 0x36, 0xcc, 0x48, 0x3d, 0x67, 0xa8, 0x4f,
0x37, 0xd6, 0xb2, 0x4b, 0x24, 0x45, 0x48, 0x25, 0xd2, 0xb7, 0xbf, 0xdc, 0x80, 0x2b,
0x2e, 0x32, 0x8c, 0x43,
],
msg: [
0x4b, 0x19, 0x22, 0x32, 0xec, 0xb9, 0xf0, 0xc0, 0x24, 0x11, 0xe5, 0x25, 0x96, 0xbc,
0x5e, 0x90, 0x45, 0x7e, 0x74, 0x59, 0x39, 0xff, 0xed, 0xbd, 0x12, 0x86, 0x3c, 0xe7,
0x1a, 0x02, 0xaf, 0x11,
],
sig: [
0xa4, 0x58, 0x79, 0x33, 0x26, 0x98, 0x37, 0x74, 0x09, 0x6d, 0x36, 0x59, 0xeb, 0x9a,
0x21, 0xd1, 0x2c, 0x8e, 0xb8, 0x77, 0x56, 0x6b, 0x66, 0xbf, 0x60, 0x33, 0xdb, 0x8f,
0xde, 0x20, 0xc4, 0x66, 0xa2, 0xe9, 0x54, 0x30, 0xa0, 0x1e, 0xb9, 0xad, 0x28, 0xe0,
0x76, 0x5b, 0xed, 0x21, 0xdc, 0xd3, 0x03, 0x86, 0xfc, 0xe7, 0xaa, 0xba, 0xde, 0xa6,
0xda, 0x72, 0x8c, 0x16, 0xbb, 0x80, 0xf1, 0xc2,
],
},
TestVector {
isk: [
0x7d, 0x41, 0x7a, 0xdb, 0x3d, 0x15, 0xcc, 0x54, 0xdc, 0xb1, 0xfc, 0xe4, 0x67, 0x50,
0x0c, 0x6b, 0x8f, 0xb8, 0x6b, 0x12, 0xb5, 0x6d, 0xa9, 0xc3, 0x82, 0x85, 0x7d, 0xee,
0xcc, 0x40, 0xa9, 0x8d,
],
ik: [
0x45, 0x61, 0x9f, 0x20, 0x6c, 0x3b, 0xfc, 0x84, 0xfd, 0x42, 0x4f, 0xfb, 0x5c, 0x81,
0x6f, 0x65, 0x4b, 0x27, 0xaa, 0x7f, 0x7b, 0x4b, 0xd6, 0x7e, 0xc5, 0xf9, 0xac, 0x6d,
0x0f, 0x38, 0xdb, 0xb1,
],
msg: [
0x5f, 0x29, 0x35, 0x39, 0x5e, 0xe4, 0x76, 0x2d, 0xd2, 0x1a, 0xfd, 0xbb, 0x5d, 0x47,
0xfa, 0x9a, 0x6d, 0xd9, 0x84, 0xd5, 0x67, 0xdb, 0x28, 0x57, 0xb9, 0x27, 0xb7, 0xfa,
0xe2, 0xdb, 0x58, 0x71,
],
sig: [
0xe6, 0x92, 0x4d, 0x53, 0xec, 0x97, 0x80, 0x79, 0xd6, 0x6a, 0x28, 0x4c, 0x00, 0xa8,
0x68, 0xf9, 0xeb, 0x75, 0x1a, 0xe3, 0xb1, 0x69, 0x0d, 0x15, 0xee, 0x1b, 0x39, 0x68,
0x0b, 0x83, 0xc4, 0x38, 0xe4, 0x5f, 0x02, 0xa2, 0x3c, 0x65, 0x6e, 0x4e, 0x53, 0xd3,
0xc7, 0x3e, 0xfa, 0x0d, 0xc5, 0xf7, 0xad, 0x63, 0x28, 0x21, 0x7f, 0xd5, 0x9b, 0x23,
0xaa, 0xe4, 0xf9, 0x0c, 0x68, 0xbe, 0x76, 0xbc,
],
},
]
}

File diff suppressed because it is too large Load Diff

View File

@ -462,7 +462,7 @@ pub mod testing {
#[cfg(test)]
mod tests {
use crate::note::asset_base::testing::{arb_asset_id, native_asset_id};
use crate::note::asset_base::testing::{arb_asset_base, native_asset_base};
use crate::note::AssetBase;
use proptest::prelude::*;
@ -532,17 +532,17 @@ mod tests {
fn bsk_consistent_with_bvk_native_with_zsa_transfer_and_burning(
native_values in (1usize..10).prop_flat_map(|n_values|
arb_note_value_bounded(MAX_NOTE_VALUE / n_values as u64).prop_flat_map(move |bound|
prop::collection::vec((arb_value_sum_bounded(bound), arb_trapdoor(), native_asset_id()), n_values)
prop::collection::vec((arb_value_sum_bounded(bound), arb_trapdoor(), native_asset_base()), n_values)
)
),
(asset_values, neg_trapdoors) in (1usize..10).prop_flat_map(|n_values|
(arb_note_value_bounded(MAX_NOTE_VALUE / n_values as u64).prop_flat_map(move |bound|
prop::collection::vec((arb_value_sum_bounded(bound), arb_trapdoor(), arb_asset_id()), n_values)
prop::collection::vec((arb_value_sum_bounded(bound), arb_trapdoor(), arb_asset_base()), n_values)
), prop::collection::vec(arb_trapdoor(), n_values))
),
burn_values in (1usize..10).prop_flat_map(|n_values|
arb_note_value_bounded(MAX_NOTE_VALUE / n_values as u64)
.prop_flat_map(move |bound| prop::collection::vec((arb_value_sum_bounded(bound), arb_trapdoor(), arb_asset_id()), n_values))
.prop_flat_map(move |bound| prop::collection::vec((arb_value_sum_bounded(bound), arb_trapdoor(), arb_asset_base()), n_values))
)
) {
check_binding_signature(&native_values, &[], &[], &[]);

View File

@ -58,7 +58,7 @@ fn prepare_keys() -> Keychain {
let fvk = FullViewingKey::from(&sk);
let recipient = fvk.address_at(0u32, Scope::External);
let isk = IssuanceAuthorizingKey::from_bytes([0; 32]).unwrap();
let isk = IssuanceAuthorizingKey::from_bytes([1u8; 32]).unwrap();
let ik = IssuanceValidatingKey::from(&isk);
Keychain {
pk,
@ -73,12 +73,11 @@ fn prepare_keys() -> Keychain {
fn sign_issue_bundle(
unauthorized: IssueBundle<Unauthorized>,
rng: OsRng,
isk: &IssuanceAuthorizingKey,
) -> IssueBundle<Signed> {
let sighash = unauthorized.commitment().into();
let proven = unauthorized.prepare(sighash);
proven.sign(rng, isk).unwrap()
proven.sign(isk).unwrap()
}
fn build_and_sign_bundle(
@ -161,7 +160,7 @@ fn issue_zsa_notes(asset_descr: &str, keys: &Keychain) -> (Note, Note) {
)
.is_ok());
let issue_bundle = sign_issue_bundle(unauthorized, rng, keys.isk());
let issue_bundle = sign_issue_bundle(unauthorized, keys.isk());
// Take notes from first action
let notes = issue_bundle.get_all_notes();