mirror of https://github.com/zcash/orchard.git
updated issuance
This commit is contained in:
parent
95079aa8b7
commit
c7a87831db
181
src/issuance.rs
181
src/issuance.rs
|
@ -1,23 +1,27 @@
|
|||
use core::fmt;
|
||||
//! Structs related to issuance bundles and the associated logic.
|
||||
|
||||
use memuse::DynamicUsage;
|
||||
use nonempty::NonEmpty;
|
||||
|
||||
use crate::{note::{ExtractedNoteCommitment, TransmittedNoteCiphertext}, Note, primitives::redpallas::{self, SpendAuth}};
|
||||
use crate::bundle::Authorization;
|
||||
use crate::note::NoteType;
|
||||
use crate::{primitives::redpallas::{self, SpendAuth},
|
||||
Note,
|
||||
};
|
||||
|
||||
impl<T> IssueAction<T> {
|
||||
/// Constructs an `IssueAction` from its constituent parts.
|
||||
pub fn from_parts(
|
||||
ik: redpallas::VerificationKey<SpendAuth>,
|
||||
cmx: ExtractedNoteCommitment,
|
||||
note: Note,
|
||||
asset_desc: Vec<u8>,
|
||||
notes: NonEmpty<Note>,
|
||||
finalize: bool,
|
||||
authorization: T,
|
||||
) -> Self {
|
||||
IssueAction {
|
||||
ik,
|
||||
cmx,
|
||||
note,
|
||||
asset_desc,
|
||||
notes,
|
||||
finalize,
|
||||
authorization,
|
||||
}
|
||||
}
|
||||
|
@ -27,14 +31,14 @@ impl<T> IssueAction<T> {
|
|||
&self.ik
|
||||
}
|
||||
|
||||
/// Returns the commitment to the new note being created.
|
||||
pub fn cmx(&self) -> &ExtractedNoteCommitment {
|
||||
&self.cmx
|
||||
/// Returns the asset description for the note being created.
|
||||
pub fn asset_desc(&self) -> &[u8] {
|
||||
&self.asset_desc
|
||||
}
|
||||
|
||||
/// Returns the issued note. ciphertext.
|
||||
pub fn note(&self) -> &Note {
|
||||
&self.note
|
||||
/// Returns the issued notes.
|
||||
pub fn notes(&self) -> &NonEmpty<Note> {
|
||||
&self.notes
|
||||
}
|
||||
|
||||
/// Returns the authorization for this action.
|
||||
|
@ -42,12 +46,18 @@ impl<T> IssueAction<T> {
|
|||
&self.authorization
|
||||
}
|
||||
|
||||
/// Returns whether the asset type was finalized in this action.
|
||||
pub fn is_finalized(&self) -> bool {
|
||||
self.finalize
|
||||
}
|
||||
|
||||
/// Transitions this issue action from one authorization state to another.
|
||||
pub fn map<U>(self, step: impl FnOnce(T) -> U) -> IssueAction<U> {
|
||||
IssueAction {
|
||||
ik: self.ik,
|
||||
cmx: self.cmx,
|
||||
note: self.note,
|
||||
asset_desc: self.asset_desc,
|
||||
notes: self.notes,
|
||||
finalize: self.finalize,
|
||||
authorization: step(self.authorization),
|
||||
}
|
||||
}
|
||||
|
@ -56,8 +66,9 @@ impl<T> IssueAction<T> {
|
|||
pub fn try_map<U, E>(self, step: impl FnOnce(T) -> Result<U, E>) -> Result<IssueAction<U>, E> {
|
||||
Ok(IssueAction {
|
||||
ik: self.ik,
|
||||
cmx: self.cmx,
|
||||
note: self.note,
|
||||
asset_desc: self.asset_desc,
|
||||
notes: self.notes,
|
||||
finalize: self.finalize,
|
||||
authorization: step(self.authorization)?,
|
||||
})
|
||||
}
|
||||
|
@ -79,44 +90,35 @@ impl DynamicUsage for IssueAction<redpallas::Signature<SpendAuth>> {
|
|||
#[cfg(any(test, feature = "test-dependencies"))]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "test-dependencies")))]
|
||||
pub(crate) mod testing {
|
||||
use nonempty::NonEmpty;
|
||||
use proptest::prelude::*;
|
||||
use rand::{rngs::StdRng, SeedableRng};
|
||||
use reddsa::orchard::SpendAuth;
|
||||
|
||||
use proptest::prelude::*;
|
||||
|
||||
use crate::{
|
||||
note::{
|
||||
commitment::ExtractedNoteCommitment,
|
||||
testing::arb_note, TransmittedNoteCiphertext,
|
||||
},
|
||||
note::testing::arb_note,
|
||||
primitives::redpallas::{
|
||||
self,
|
||||
testing::{arb_spendauth_signing_key, arb_spendauth_verification_key},
|
||||
},
|
||||
value::{NoteValue},
|
||||
value::NoteValue,
|
||||
};
|
||||
|
||||
use super::IssueAction;
|
||||
|
||||
prop_compose! {
|
||||
/// Generate an issue action without authorization data.
|
||||
/// Generate an issue action with a single note and without authorization data.
|
||||
pub fn arb_unauthorized_issue_action(output_value: NoteValue)(
|
||||
ik in arb_spendauth_verification_key(),
|
||||
asset_desc in prop::collection::vec(any::<u8>(), 0..=255),
|
||||
note in arb_note(output_value),
|
||||
) -> IssueAction<()> {
|
||||
let cmx = ExtractedNoteCommitment::from(note.commitment());
|
||||
|
||||
// FIXME: make a real one from the note.
|
||||
let encrypted_note = TransmittedNoteCiphertext {
|
||||
epk_bytes: [0u8; 32],
|
||||
enc_ciphertext: [0u8; 580],
|
||||
out_ciphertext: [0u8; 80]
|
||||
};
|
||||
IssueAction {
|
||||
ik,
|
||||
cmx,
|
||||
encrypted_note,
|
||||
authorization: ()
|
||||
asset_desc,
|
||||
notes:NonEmpty::new(note), //todo: replace note type
|
||||
finalize: false,
|
||||
authorization: (),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -125,78 +127,103 @@ pub(crate) mod testing {
|
|||
/// Generate an issue action with invalid (random) authorization data.
|
||||
pub fn arb_issue_action(output_value: NoteValue)(
|
||||
sk in arb_spendauth_signing_key(),
|
||||
asset_desc in prop::collection::vec(any::<u8>(), 0..=255),
|
||||
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),
|
||||
) -> IssueAction<redpallas::Signature<SpendAuth>> {
|
||||
let cmx = ExtractedNoteCommitment::from(note.commitment());
|
||||
|
||||
// FIXME: make a real one from the note.
|
||||
let encrypted_note = TransmittedNoteCiphertext {
|
||||
epk_bytes: [0u8; 32],
|
||||
enc_ciphertext: [0u8; 580],
|
||||
out_ciphertext: [0u8; 80]
|
||||
};
|
||||
|
||||
let rng = StdRng::from_seed(rng_seed);
|
||||
|
||||
IssueAction {
|
||||
ik: redpallas::VerificationKey::from(&sk),
|
||||
cmx,
|
||||
encrypted_note,
|
||||
asset_desc,
|
||||
notes:NonEmpty::new(note), //todo: replace note type
|
||||
finalize: false,
|
||||
authorization: sk.sign(rng, &fake_sighash),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// An issue action applied to the global ledger.
|
||||
///
|
||||
/// Externally, this creates a zsa note (adding a commitment to the global ledger).
|
||||
/// Externally, this creates new zsa notes (adding a commitment to the global ledger).
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct IssueAction<A> {
|
||||
/// The issuer key for the note being created.
|
||||
ik: redpallas::VerificationKey<SpendAuth>,
|
||||
// Asset description for verification.
|
||||
/// Asset description for verification.
|
||||
asset_desc: Vec<u8>,
|
||||
/// A commitment to the new note being created.
|
||||
cmx: ExtractedNoteCommitment,
|
||||
/// the newly issued note.
|
||||
note: Note, //TODO: serialize using note_encryption::note_plaintext_bytes()
|
||||
|
||||
/// The newly issued notes.
|
||||
notes: NonEmpty<Note>,
|
||||
/// Finalize will prevent further issuance of the same asset.
|
||||
finalize: bool,
|
||||
/// The authorization for this action.
|
||||
authorization: A,
|
||||
}
|
||||
|
||||
/// An issue action applied to the global ledger.
|
||||
///
|
||||
/// Externally, this creates a zsa note (adding a commitment to the global ledger).
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct FinalizeIssueAction<A> {
|
||||
/// The issuer key for the note being created.
|
||||
ik: redpallas::VerificationKey<SpendAuth>,
|
||||
/// The type of this note.
|
||||
note_type: NoteType,
|
||||
/// The authorization for this action.
|
||||
authorization: A,
|
||||
}
|
||||
|
||||
// /// Defines the authorization type of an Orchard bundle.
|
||||
// pub trait Authorization: fmt::Debug {
|
||||
// /// The authorization type of an Orchard action.
|
||||
// type SpendAuth: fmt::Debug;
|
||||
// }
|
||||
|
||||
/// A bundle of actions to be applied to the ledger.
|
||||
#[derive(Clone)]
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct IssueBundle<T: Authorization> {
|
||||
/// The list of issue actions that make up this bundle.
|
||||
actions: NonEmpty<IssueAction<T::SpendAuth>>,
|
||||
/// The list of finalization actions that make up this bundle.
|
||||
finalizations: NonEmpty<FinalizeIssueAction<T::SpendAuth>>,
|
||||
/// The authorization for this bundle.
|
||||
authorization: T,
|
||||
}
|
||||
|
||||
|
||||
// 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)
|
||||
// }
|
||||
// }
|
||||
|
|
Loading…
Reference in New Issue