From d15600caee247e4e49eb97042865052e3ab71e64 Mon Sep 17 00:00:00 2001 From: Paul Date: Thu, 14 Jul 2022 10:32:30 +0300 Subject: [PATCH] added IssueAction --- src/issuance.rs | 165 ++++++++++++++++++++++++++++++++++++++++++++++++ src/lib.rs | 1 + 2 files changed, 166 insertions(+) create mode 100644 src/issuance.rs diff --git a/src/issuance.rs b/src/issuance.rs new file mode 100644 index 00000000..3ae22737 --- /dev/null +++ b/src/issuance.rs @@ -0,0 +1,165 @@ +use memuse::DynamicUsage; + +use crate::{ + note::{ExtractedNoteCommitment, TransmittedNoteCiphertext}, + primitives::redpallas::{self, SpendAuth}, +}; + +/// 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 IssueAction { + /// The issuer key for the note being created. + ik: redpallas::VerificationKey, + /// A commitment to the new note being created. + cmx: ExtractedNoteCommitment, + /// The transmitted note ciphertext. + encrypted_note: TransmittedNoteCiphertext, + /// The authorization for this action. + authorization: A, +} + +impl IssueAction { + /// Constructs an `IssueAction` from its constituent parts. + pub fn from_parts( + ik: redpallas::VerificationKey, + cmx: ExtractedNoteCommitment, + encrypted_note: TransmittedNoteCiphertext, + authorization: T, + ) -> Self { + IssueAction { + ik, + cmx, + encrypted_note, + authorization, + } + } + + /// Returns the issuer verification key for the note being created. + pub fn ik(&self) -> &redpallas::VerificationKey { + &self.ik + } + + /// Returns the commitment to the new note being created. + pub fn cmx(&self) -> &ExtractedNoteCommitment { + &self.cmx + } + + /// Returns the encrypted note ciphertext. + pub fn encrypted_note(&self) -> &TransmittedNoteCiphertext { + &self.encrypted_note + } + + /// Returns the authorization for this action. + pub fn authorization(&self) -> &T { + &self.authorization + } + + /// Transitions this issue action from one authorization state to another. + pub fn map(self, step: impl FnOnce(T) -> U) -> IssueAction { + IssueAction { + ik: self.ik, + cmx: self.cmx, + encrypted_note: self.encrypted_note, + authorization: step(self.authorization), + } + } + + /// Transitions this issue action from one authorization state to another. + pub fn try_map(self, step: impl FnOnce(T) -> Result) -> Result, E> { + Ok(IssueAction { + ik: self.ik, + cmx: self.cmx, + encrypted_note: self.encrypted_note, + authorization: step(self.authorization)?, + }) + } +} + +impl DynamicUsage for IssueAction> { + #[inline(always)] + fn dynamic_usage(&self) -> usize { + 0 + } + + #[inline(always)] + fn dynamic_usage_bounds(&self) -> (usize, Option) { + (0, Some(0)) + } +} + +/// Generators for property testing. +#[cfg(any(test, feature = "test-dependencies"))] +#[cfg_attr(docsrs, doc(cfg(feature = "test-dependencies")))] +pub(crate) mod testing { + use rand::{rngs::StdRng, SeedableRng}; + use reddsa::orchard::SpendAuth; + + use proptest::prelude::*; + + use crate::{ + note::{ + commitment::ExtractedNoteCommitment, + testing::arb_note, TransmittedNoteCiphertext, + }, + primitives::redpallas::{ + self, + testing::{arb_spendauth_signing_key, arb_spendauth_verification_key}, + }, + value::{NoteValue}, + }; + + use super::IssueAction; + + prop_compose! { + /// Generate an issue action without authorization data. + pub fn arb_unauthorized_issue_action(output_value: NoteValue)( + ik in arb_spendauth_verification_key(), + 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: () + } + } + } + + prop_compose! { + /// Generate an issue action with invalid (random) authorization data. + pub fn arb_issue_action(output_value: NoteValue)( + sk in arb_spendauth_signing_key(), + 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> { + 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, + authorization: sk.sign(rng, &fake_sighash), + } + } + } +} diff --git a/src/lib.rs b/src/lib.rs index d30e9c83..4bea532b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -30,6 +30,7 @@ mod spec; pub mod tree; pub mod value; pub mod zip32; +pub mod issuance; #[cfg(test)] mod test_vectors;