mirror of https://github.com/zcash/orchard.git
added sign and verify
This commit is contained in:
parent
d3ad5e14b8
commit
3ebec5f349
157
src/issuance.rs
157
src/issuance.rs
|
@ -5,7 +5,7 @@ use nonempty::NonEmpty;
|
||||||
use rand::{CryptoRng, RngCore};
|
use rand::{CryptoRng, RngCore};
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
|
||||||
use crate::keys::IssuerValidatingKey;
|
use crate::keys::{IssuerAuthorizingKey, IssuerValidatingKey};
|
||||||
use crate::note::note_type::MAX_ASSET_DESCRIPTION_SIZE;
|
use crate::note::note_type::MAX_ASSET_DESCRIPTION_SIZE;
|
||||||
use crate::note::{NoteType, Nullifier};
|
use crate::note::{NoteType, Nullifier};
|
||||||
use crate::value::NoteValue;
|
use crate::value::NoteValue;
|
||||||
|
@ -31,13 +31,39 @@ impl IssueAction<Unauthorized> {
|
||||||
|
|
||||||
/// inject the `sighash` for signature into the bundle.
|
/// inject the `sighash` for signature into the bundle.
|
||||||
pub fn prepare(self, sighash: [u8; 32]) -> IssueAction<Prepared> {
|
pub fn prepare(self, sighash: [u8; 32]) -> IssueAction<Prepared> {
|
||||||
return IssueAction {
|
IssueAction {
|
||||||
ik: self.ik,
|
ik: self.ik,
|
||||||
asset_desc: self.asset_desc,
|
asset_desc: self.asset_desc,
|
||||||
notes: self.notes,
|
notes: self.notes,
|
||||||
finalize: self.finalize,
|
finalize: self.finalize,
|
||||||
authorization: Prepared { sighash },
|
authorization: Prepared { sighash },
|
||||||
};
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl IssueAction<Prepared> {
|
||||||
|
/// Sign the sighash using the provided `IssuerValidatingKey`.
|
||||||
|
///
|
||||||
|
/// # Panics
|
||||||
|
///
|
||||||
|
/// Panics if the provided `IssuerAuthorizingKey` does not match the action's `IssuerValidatingKey`.
|
||||||
|
pub fn sign<R: RngCore + CryptoRng>(
|
||||||
|
self,
|
||||||
|
mut rng: R,
|
||||||
|
isk: &IssuerAuthorizingKey,
|
||||||
|
) -> IssueAction<Signed> {
|
||||||
|
let expected_ik: IssuerValidatingKey = (isk).into();
|
||||||
|
assert_eq!(expected_ik, self.ik);
|
||||||
|
|
||||||
|
IssueAction {
|
||||||
|
ik: self.ik,
|
||||||
|
asset_desc: self.asset_desc,
|
||||||
|
notes: self.notes,
|
||||||
|
finalize: self.finalize,
|
||||||
|
authorization: Signed {
|
||||||
|
signature: isk.sign(&mut rng, &self.authorization.sighash),
|
||||||
|
},
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -353,12 +379,7 @@ impl IssueBundle<Unauthorized> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Loads the sighash into this bundle, preparing it for signing.
|
/// Loads the sighash into each action in the bundle, as preparation for signing.
|
||||||
///
|
|
||||||
/// This API ensures that all signatures are created over the same sighash.
|
|
||||||
/// pub fn prepare<R: RngCore + CryptoRng>(
|
|
||||||
// self,
|
|
||||||
// mut rng: R,
|
|
||||||
pub fn prepare(self, sighash: [u8; 32]) -> IssueBundle<Prepared> {
|
pub fn prepare(self, sighash: [u8; 32]) -> IssueBundle<Prepared> {
|
||||||
IssueBundle {
|
IssueBundle {
|
||||||
actions: self
|
actions: self
|
||||||
|
@ -370,6 +391,24 @@ impl IssueBundle<Unauthorized> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl IssueBundle<Prepared> {
|
||||||
|
/// Sign all the relevant actions
|
||||||
|
pub fn sign<R: RngCore + CryptoRng>(
|
||||||
|
self,
|
||||||
|
mut rng: R,
|
||||||
|
isk: &IssuerAuthorizingKey,
|
||||||
|
) -> IssueBundle<Signed> {
|
||||||
|
// todo: check ik fits isk
|
||||||
|
IssueBundle {
|
||||||
|
actions: self
|
||||||
|
.actions
|
||||||
|
.into_iter()
|
||||||
|
.map(|a| a.sign(&mut rng, isk))
|
||||||
|
.collect(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Errors produced during the issuance process
|
/// Errors produced during the issuance process
|
||||||
#[derive(Debug, PartialEq, Eq)]
|
#[derive(Debug, PartialEq, Eq)]
|
||||||
pub enum Error {
|
pub enum Error {
|
||||||
|
@ -388,6 +427,7 @@ mod tests {
|
||||||
};
|
};
|
||||||
use crate::value::NoteValue;
|
use crate::value::NoteValue;
|
||||||
use rand::rngs::OsRng;
|
use rand::rngs::OsRng;
|
||||||
|
use rand::RngCore;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn issue_bundle_basic() {
|
fn issue_bundle_basic() {
|
||||||
|
@ -555,69 +595,48 @@ mod tests {
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
let fake_sighash = [1; 32];
|
let mut fake_sighash = [0; 32];
|
||||||
|
rng.fill_bytes(&mut fake_sighash);
|
||||||
|
|
||||||
let prepared = bundle.prepare(fake_sighash);
|
let prepared = bundle.prepare(fake_sighash);
|
||||||
|
|
||||||
let action = prepared
|
let action = prepared.get_action(ik, String::from("Frost")).unwrap();
|
||||||
|
assert_eq!(action.authorization().sighash, fake_sighash);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn issue_bundle_sign() {
|
||||||
|
let mut rng = OsRng;
|
||||||
|
let sk = SpendingKey::random(&mut rng);
|
||||||
|
let isk: IssuerAuthorizingKey = (&sk).into();
|
||||||
|
let ik: IssuerValidatingKey = (&isk).into();
|
||||||
|
|
||||||
|
let fvk = FullViewingKey::from(&sk);
|
||||||
|
let recipient = fvk.address_at(0u32, Scope::External);
|
||||||
|
|
||||||
|
let mut bundle = IssueBundle::new();
|
||||||
|
|
||||||
|
bundle
|
||||||
|
.add_recipient(
|
||||||
|
ik.clone(),
|
||||||
|
String::from("Frost"),
|
||||||
|
recipient,
|
||||||
|
NoteValue::from_raw(5),
|
||||||
|
false,
|
||||||
|
rng,
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let mut rnd_sighash = [0; 32];
|
||||||
|
rng.fill_bytes(&mut rnd_sighash);
|
||||||
|
|
||||||
|
let signed = bundle.prepare(rnd_sighash).sign(rng, &isk);
|
||||||
|
|
||||||
|
let action = signed
|
||||||
.get_action(ik.clone(), String::from("Frost"))
|
.get_action(ik.clone(), String::from("Frost"))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let auth = action.authorization();
|
|
||||||
assert_eq!(auth.sighash, fake_sighash);
|
ik.verify(&rnd_sighash, &action.authorization.signature)
|
||||||
|
.expect("signature should be valid");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// mod tests {
|
|
||||||
// use rand::rngs::OsRng;
|
|
||||||
//
|
|
||||||
// use super::Builder;
|
|
||||||
// // use crate::keys::{IssuerAuthorizingKey, IssuerValidatingKey};
|
|
||||||
// use crate::note::NoteType;
|
|
||||||
// use crate::{
|
|
||||||
// bundle::{Authorized, Bundle, Flags},
|
|
||||||
// circuit::ProvingKey,
|
|
||||||
// constants::MERKLE_DEPTH_ORCHARD,
|
|
||||||
// keys::{FullViewingKey, Scope, SpendingKey},
|
|
||||||
// tree::EMPTY_ROOTS,
|
|
||||||
// value::NoteValue,
|
|
||||||
// };
|
|
||||||
// use crate::builder::Builder;
|
|
||||||
//
|
|
||||||
// #[test]
|
|
||||||
// fn shielding_bundle() {
|
|
||||||
// let pk = ProvingKey::build();
|
|
||||||
// let mut rng = OsRng;
|
|
||||||
//
|
|
||||||
// let sk = SpendingKey::random(&mut rng);
|
|
||||||
// let fvk = FullViewingKey::from(&sk);
|
|
||||||
// let recipient = fvk.address_at(0u32, Scope::External);
|
|
||||||
//
|
|
||||||
// let mut builder = Builder::new(
|
|
||||||
// Flags::from_parts(true, true),
|
|
||||||
// EMPTY_ROOTS[MERKLE_DEPTH_ORCHARD].into(),
|
|
||||||
// );
|
|
||||||
//
|
|
||||||
// builder
|
|
||||||
// .add_recipient(
|
|
||||||
// None,
|
|
||||||
// recipient,
|
|
||||||
// NoteValue::from_raw(5000),
|
|
||||||
// NoteType::native(),
|
|
||||||
// None,
|
|
||||||
// )
|
|
||||||
// .unwrap();
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// let bundle: Bundle<Authorized, i64> = builder
|
|
||||||
// .build(&mut rng)
|
|
||||||
// .unwrap()
|
|
||||||
// .create_proof(&pk, &mut rng)
|
|
||||||
// .unwrap()
|
|
||||||
// .prepare(&mut rng, [0; 32])
|
|
||||||
// .sign()
|
|
||||||
// .finalize()
|
|
||||||
// .unwrap();
|
|
||||||
// assert_eq!(bundle.value_balance(), &(-5000));
|
|
||||||
//
|
|
||||||
// verify_bundle(&bundle, &vk)
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
13
src/keys.rs
13
src/keys.rs
|
@ -209,9 +209,7 @@ impl IssuerAuthorizingKey {
|
||||||
to_scalar(PrfExpand::ZsaIsk.expand(&sk.0))
|
to_scalar(PrfExpand::ZsaIsk.expand(&sk.0))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// RXXXX
|
/// Sign the provided message using the `IssuerAuthorizingKey`.
|
||||||
///
|
|
||||||
/// XXXXX
|
|
||||||
pub fn sign(
|
pub fn sign(
|
||||||
&self,
|
&self,
|
||||||
rng: &mut (impl RngCore + CryptoRng),
|
rng: &mut (impl RngCore + CryptoRng),
|
||||||
|
@ -280,6 +278,15 @@ impl IssuerValidatingKey {
|
||||||
.and_then(check_structural_validity)
|
.and_then(check_structural_validity)
|
||||||
.map(IssuerValidatingKey)
|
.map(IssuerValidatingKey)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Verifies a purported `signature` over `msg` made by this verification key.
|
||||||
|
pub fn verify(
|
||||||
|
&self,
|
||||||
|
msg: &[u8],
|
||||||
|
signature: &redpallas::Signature<SpendAuth>,
|
||||||
|
) -> Result<(), reddsa::Error> {
|
||||||
|
self.0.verify(msg, signature)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A function to check structural validity of the validating keys for authorizing transfers and
|
/// A function to check structural validity of the validating keys for authorizing transfers and
|
||||||
|
|
Loading…
Reference in New Issue