Skip to content

Commit

Permalink
Porting Batch Validator changes on top of the latest version of zsa1 …
Browse files Browse the repository at this point in the history
…branch (after PR #81 was merged)
  • Loading branch information
dmidem committed Oct 11, 2023
1 parent 7937e5b commit fe51ec9
Show file tree
Hide file tree
Showing 5 changed files with 131 additions and 2 deletions.
18 changes: 16 additions & 2 deletions src/bundle/batch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,10 @@ use pasta_curves::vesta;
use rand::{CryptoRng, RngCore};
use tracing::debug;

use super::{Authorized, Bundle};
use super::{burn_validation::validate_bundle_burn, Authorized, Bundle};
use crate::{
circuit::VerifyingKey,
note::AssetBase,
primitives::redpallas::{self, Binding, SpendAuth},
};

Expand All @@ -23,6 +24,7 @@ struct BundleSignature {
pub struct BatchValidator {
proofs: plonk::BatchVerifier<vesta::Affine>,
signatures: Vec<BundleSignature>,
burns: Vec<(AssetBase, i64)>,
}

impl BatchValidator {
Expand All @@ -31,10 +33,11 @@ impl BatchValidator {
BatchValidator {
proofs: plonk::BatchVerifier::new(),
signatures: vec![],
burns: vec![],
}
}

/// Adds the proof and RedPallas signatures from the given bundle to the validator.
/// Adds the proof, RedPallas signatures and burn mechanism values from the given bundle to the validator.
pub fn add_bundle<V: Copy + Into<i64>>(
&mut self,
bundle: &Bundle<Authorized, V>,
Expand All @@ -58,6 +61,13 @@ impl BatchValidator {
.authorization()
.proof()
.add_to_batch(&mut self.proofs, bundle.to_instances());

self.burns.extend(
bundle
.burn
.iter()
.map(|(asset, amount)| (*asset, (*amount).into())),
);
}

/// Batch-validates the accumulated bundles.
Expand All @@ -67,6 +77,10 @@ impl BatchValidator {
/// figure out which of the accumulated bundles might be invalid; if that information
/// is desired, construct separate [`BatchValidator`]s for sub-batches of the bundles.
pub fn validate<R: RngCore + CryptoRng>(self, vk: &VerifyingKey, rng: R) -> bool {
if validate_bundle_burn(&self.burns).is_err() {
return false;
}

if self.signatures.is_empty() {
// An empty batch is always valid, but is not free to run; skip it.
// Note that a transaction has at least a binding signature, so if
Expand Down
53 changes: 53 additions & 0 deletions src/issuance.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
//! Structs related to issuance bundles and the associated logic.
use blake2b_simd::Hash as Blake2bHash;
use group::Group;
use memuse::DynamicUsage;
use nonempty::NonEmpty;
use rand::{CryptoRng, RngCore};
use std::collections::HashSet;
Expand All @@ -25,6 +26,10 @@ use crate::{

use crate::supply_info::{AssetSupply, SupplyInfo};

mod batch;

pub use batch::BatchValidator;

/// A bundle of actions to be applied to the ledger.
#[derive(Debug, Clone)]
pub struct IssueBundle<T: IssueAuth> {
Expand All @@ -49,6 +54,24 @@ pub struct IssueAction {
finalize: bool,
}

impl DynamicUsage for IssueAction {
#[inline(always)]
fn dynamic_usage(&self) -> usize {
self.asset_desc.dynamic_usage() + self.notes.dynamic_usage()
}

#[inline(always)]
fn dynamic_usage_bounds(&self) -> (usize, Option<usize>) {
let asset_desc_bounds = self.asset_desc.dynamic_usage_bounds();
let note_bounds = self.notes.dynamic_usage_bounds();

(
asset_desc_bounds.0 + note_bounds.0,
asset_desc_bounds.1.zip(note_bounds.1).map(|(a, b)| a + b),
)
}
}

/// The parameters required to add a Note into an IssueAction.
#[derive(Debug)]
pub struct IssueInfo {
Expand Down Expand Up @@ -202,6 +225,15 @@ impl IssueAuth for Unauthorized {}
impl IssueAuth for Prepared {}
impl IssueAuth for Signed {}

impl DynamicUsage for Signed {
fn dynamic_usage(&self) -> usize {
0
}
fn dynamic_usage_bounds(&self) -> (usize, Option<usize>) {
(0, Some(0))
}
}

impl<T: IssueAuth> IssueBundle<T> {
/// Returns the issuer verification key for the bundle.
pub fn ik(&self) -> &IssuanceValidatingKey {
Expand Down Expand Up @@ -460,6 +492,27 @@ impl IssueBundle<Signed> {
}
}

impl DynamicUsage for IssueBundle<Signed> {
fn dynamic_usage(&self) -> usize {
self.actions.dynamic_usage() + self.ik.dynamic_usage() + self.authorization.dynamic_usage()
}

fn dynamic_usage_bounds(&self) -> (usize, Option<usize>) {
let action_bounds = self.actions.dynamic_usage_bounds();
let ik_bounds = self.ik.dynamic_usage_bounds();
let authorization_bounds = self.authorization.dynamic_usage_bounds();

(
action_bounds.0 + ik_bounds.0 + authorization_bounds.0,
action_bounds
.1
.zip(ik_bounds.1)
.zip(authorization_bounds.1)
.map(|((a, b), c)| a + b + c),
)
}
}

/// Validation for Orchard IssueBundles
///
/// A set of previously finalized asset types must be provided in `finalized` argument.
Expand Down
36 changes: 36 additions & 0 deletions src/issuance/batch.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
use std::collections::HashSet;

use super::{verify_issue_bundle, AssetBase, IssueBundle, Signed};

/// Batch validation context for Issuance.
///
#[derive(Debug, Default)]
pub struct BatchValidator {
bundles: Vec<(IssueBundle<Signed>, [u8; 32])>,
}

impl BatchValidator {
/// Constructs a new batch validation context.
pub fn new() -> Self {
BatchValidator { bundles: vec![] }
}

/// Adds bundle to the validator.
pub fn add_bundle(&mut self, bundle: &IssueBundle<Signed>, sighash: [u8; 32]) {
self.bundles.push((bundle.clone(), sighash))
}

/// Batch-validates the accumulated bundles.
///
/// Returns `true` if every bundle added to the batch validator is valid, or `false`
/// if one or more are invalid.
pub fn validate(self) -> bool {
// FIXME: take/save finalization set from/to the global state
let finalized = HashSet::<AssetBase>::new();

// FIXME: process resulting supply_info
self.bundles
.into_iter()
.all(|(bundle, sighash)| verify_issue_bundle(&bundle, sighash, &finalized).is_ok())
}
}
13 changes: 13 additions & 0 deletions src/keys.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ use group::{
prime::PrimeCurveAffine,
Curve, GroupEncoding,
};
use memuse::DynamicUsage;
use pasta_curves::{pallas, pallas::Scalar};
use rand::{CryptoRng, RngCore};
use subtle::{Choice, ConditionallySelectable, ConstantTimeEq, CtOption};
Expand Down Expand Up @@ -349,6 +350,18 @@ impl PartialEq for IssuanceValidatingKey {

impl Eq for IssuanceValidatingKey {}

impl DynamicUsage for IssuanceValidatingKey {
#[inline(always)]
fn dynamic_usage(&self) -> usize {
0
}

#[inline(always)]
fn dynamic_usage_bounds(&self) -> (usize, Option<usize>) {
(0, Some(0))
}
}

impl IssuanceValidatingKey {
/// Converts this spend validating key to its serialized form,
/// I2LEOSP_256(ik).
Expand Down
13 changes: 13 additions & 0 deletions src/note.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
use core::fmt;

use group::GroupEncoding;
use memuse::DynamicUsage;
use pasta_curves::pallas;
use rand::RngCore;
use subtle::{Choice, ConditionallySelectable, CtOption};
Expand Down Expand Up @@ -306,6 +307,18 @@ impl Note {
}
}

impl DynamicUsage for Note {
#[inline(always)]
fn dynamic_usage(&self) -> usize {
0
}

#[inline(always)]
fn dynamic_usage_bounds(&self) -> (usize, Option<usize>) {
(0, Some(0))
}
}

/// An encrypted note.
#[derive(Clone)]
pub struct TransmittedNoteCiphertext {
Expand Down

0 comments on commit fe51ec9

Please sign in to comment.