Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Organize STM code - Merkle Tree Module #2374

Open
wants to merge 18 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 8 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions mithril-stm/src/eligibility_check.rs
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,10 @@ mod tests {
q < phi
}

// ---------------------------------------------------------------------
// Property test: `test_precision_approximation`
// Property test: `early_break_taylor`
// ---------------------------------------------------------------------
proptest! {
#![proptest_config(ProptestConfig::with_cases(50))]

Expand Down
211 changes: 106 additions & 105 deletions mithril-stm/src/error.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
//! Crate specific errors

use crate::merkle_tree::{BatchPath, Path};
use crate::merkle_tree::basic::Path;
use crate::merkle_tree::batch_compatible::BatchPath;
use blake2::digest::{Digest, FixedOutput};
use {
crate::multi_sig::{Signature, VerificationKey, VerificationKeyPoP},
Expand Down Expand Up @@ -39,6 +40,22 @@ pub enum MultiSignatureError {
VerificationKeyInfinity(Box<VerificationKey>),
}

/// Error types related to merkle trees.
#[derive(Debug, Clone, thiserror::Error)]
pub enum MerkleTreeError<D: Digest + FixedOutput> {
/// Serialization error
#[error("Serialization of a merkle tree failed")]
SerializationError,

/// Invalid merkle path
#[error("Path does not verify against root")]
PathInvalid(Path<D>),

/// Invalid merkle batch path
#[error("Batch path does not verify against root")]
BatchPathInvalid(BatchPath<D>),
}

/// Errors which can be output by Mithril single signature verification.
#[derive(Debug, Clone, thiserror::Error)]
pub enum StmSignatureError {
Expand Down Expand Up @@ -67,28 +84,39 @@ pub enum StmSignatureError {
SerializationError,
}

/// Errors which can be output by Mithril aggregate verification.
#[derive(Debug, Clone, thiserror::Error)]
pub enum StmAggregateSignatureError<D: Digest + FixedOutput> {
/// The IVK is invalid after aggregating the keys
#[error("Aggregated key does not correspond to the expected key.")]
IvkInvalid(Box<VerificationKey>),

/// This error occurs when the the serialization of the raw bytes failed
#[error("Invalid bytes")]
SerializationError,
impl From<MultiSignatureError> for StmSignatureError {
fn from(e: MultiSignatureError) -> Self {
match e {
MultiSignatureError::SerializationError => Self::SerializationError,
MultiSignatureError::SignatureInvalid(e) => Self::SignatureInvalid(e),
MultiSignatureError::BatchInvalid => unreachable!(),
MultiSignatureError::KeyInvalid(_) => unreachable!(),
MultiSignatureError::AggregateSignatureInvalid => unreachable!(),
MultiSignatureError::SignatureInfinity(_) => unreachable!(),
MultiSignatureError::VerificationKeyInfinity(_) => unreachable!(),
}
}
}

/// Invalid merkle batch path
#[error("Batch path does not verify against root")]
PathInvalid(BatchPath<D>),
impl<D: Digest + FixedOutput> From<MerkleTreeError<D>> for StmSignatureError {
fn from(e: MerkleTreeError<D>) -> Self {
match e {
MerkleTreeError::SerializationError => Self::SerializationError,
_ => unreachable!(),
}
}
}

/// Batch verification of STM aggregate signatures failed
#[error("Batch verification of STM aggregate signatures failed")]
BatchInvalid,
/// Error types for aggregation.
#[derive(Debug, Clone, thiserror::Error)]
pub enum AggregationError {
/// Not enough signatures were collected, got this many instead.
#[error("Not enough signatures. Got only {0} out of {1}.")]
NotEnoughSignatures(u64, u64),

/// `CoreVerifier` check failed
#[error("Core verification error: {0}")]
CoreVerificationError(#[source] CoreVerifierError),
/// This error happens when we try to convert a u64 to a usize and it does not fit
#[error("Invalid usize conversion")]
UsizeConversionInvalid,
}

/// Errors which can be output by `CoreVerifier`.
Expand All @@ -111,81 +139,59 @@ pub enum CoreVerifierError {
IndividualSignatureInvalid(#[source] StmSignatureError),
}

/// Error types for aggregation.
#[derive(Debug, Clone, thiserror::Error)]
pub enum AggregationError {
/// Not enough signatures were collected, got this many instead.
#[error("Not enough signatures. Got only {0} out of {1}.")]
NotEnoughSignatures(u64, u64),

/// This error happens when we try to convert a u64 to a usize and it does not fit
#[error("Invalid usize conversion")]
UsizeConversionInvalid,
}

/// Error types related to merkle trees.
#[derive(Debug, Clone, thiserror::Error)]
pub enum MerkleTreeError<D: Digest + FixedOutput> {
/// Serialization error
#[error("Serialization of a merkle tree failed")]
SerializationError,

/// Invalid merkle path
#[error("Path does not verify against root")]
PathInvalid(Path<D>),

/// Invalid merkle batch path
#[error("Batch path does not verify against root")]
BatchPathInvalid(BatchPath<D>),
}

/// Errors which can be outputted by key registration.
#[derive(Debug, Clone, thiserror::Error, PartialEq, Eq)]
pub enum RegisterError {
/// This key has already been registered by a participant
#[error("This key has already been registered.")]
KeyRegistered(Box<VerificationKey>),

/// Verification key is the infinity
#[error("Verification key is the infinity")]
VerificationKeyInfinity(Box<VerificationKey>),

/// The supplied key is not valid
#[error("The verification of correctness of the supplied key is invalid.")]
KeyInvalid(Box<VerificationKeyPoP>),

/// Serialization error
#[error("Serialization error")]
SerializationError,

/// UnregisteredInitializer error
#[error("Initializer not registered. Cannot participate as a signer.")]
UnregisteredInitializer,
impl From<AggregationError> for CoreVerifierError {
fn from(e: AggregationError) -> Self {
match e {
AggregationError::NotEnoughSignatures(e, _e) => Self::NoQuorum(e, e),
AggregationError::UsizeConversionInvalid => unreachable!(),
}
}
}

impl From<MultiSignatureError> for StmSignatureError {
impl From<MultiSignatureError> for CoreVerifierError {
fn from(e: MultiSignatureError) -> Self {
match e {
MultiSignatureError::SerializationError => Self::SerializationError,
MultiSignatureError::SignatureInvalid(e) => Self::SignatureInvalid(e),
MultiSignatureError::AggregateSignatureInvalid => Self::AggregateSignatureInvalid,
MultiSignatureError::BatchInvalid => unreachable!(),
MultiSignatureError::SerializationError => unreachable!(),
MultiSignatureError::KeyInvalid(_) => unreachable!(),
MultiSignatureError::AggregateSignatureInvalid => unreachable!(),
MultiSignatureError::SignatureInvalid(_e) => unreachable!(),
MultiSignatureError::SignatureInfinity(_) => unreachable!(),
MultiSignatureError::VerificationKeyInfinity(_) => unreachable!(),
}
}
}

impl<D: Digest + FixedOutput> From<MerkleTreeError<D>> for StmSignatureError {
fn from(e: MerkleTreeError<D>) -> Self {
match e {
MerkleTreeError::SerializationError => Self::SerializationError,
_ => unreachable!(),
}
impl From<StmSignatureError> for CoreVerifierError {
fn from(e: StmSignatureError) -> Self {
CoreVerifierError::IndividualSignatureInvalid(e)
}
}

/// Errors which can be output by Mithril aggregate verification.
#[derive(Debug, Clone, thiserror::Error)]
pub enum StmAggregateSignatureError<D: Digest + FixedOutput> {
/// The IVK is invalid after aggregating the keys
#[error("Aggregated key does not correspond to the expected key.")]
IvkInvalid(Box<VerificationKey>),

/// This error occurs when the the serialization of the raw bytes failed
#[error("Invalid bytes")]
SerializationError,

/// Invalid merkle batch path
#[error("Batch path does not verify against root")]
PathInvalid(BatchPath<D>),

/// Batch verification of STM aggregate signatures failed
#[error("Batch verification of STM aggregate signatures failed")]
BatchInvalid,

/// `CoreVerifier` check failed
#[error("Core verification error: {0}")]
CoreVerificationError(#[source] CoreVerifierError),
}

impl<D: Digest + FixedOutput> From<MerkleTreeError<D>> for StmAggregateSignatureError<D> {
fn from(e: MerkleTreeError<D>) -> Self {
match e {
Expand Down Expand Up @@ -233,33 +239,28 @@ impl<D: Digest + FixedOutput> From<StmSignatureError> for StmAggregateSignatureE
}
}

impl From<AggregationError> for CoreVerifierError {
fn from(e: AggregationError) -> Self {
match e {
AggregationError::NotEnoughSignatures(e, _e) => Self::NoQuorum(e, e),
AggregationError::UsizeConversionInvalid => unreachable!(),
}
}
}
/// Errors which can be outputted by key registration.
#[derive(Debug, Clone, thiserror::Error, PartialEq, Eq)]
pub enum RegisterError {
/// This key has already been registered by a participant
#[error("This key has already been registered.")]
KeyRegistered(Box<VerificationKey>),

impl From<MultiSignatureError> for CoreVerifierError {
fn from(e: MultiSignatureError) -> Self {
match e {
MultiSignatureError::AggregateSignatureInvalid => Self::AggregateSignatureInvalid,
MultiSignatureError::BatchInvalid => unreachable!(),
MultiSignatureError::SerializationError => unreachable!(),
MultiSignatureError::KeyInvalid(_) => unreachable!(),
MultiSignatureError::SignatureInvalid(_e) => unreachable!(),
MultiSignatureError::SignatureInfinity(_) => unreachable!(),
MultiSignatureError::VerificationKeyInfinity(_) => unreachable!(),
}
}
}
/// Verification key is the infinity
#[error("Verification key is the infinity")]
VerificationKeyInfinity(Box<VerificationKey>),

impl From<StmSignatureError> for CoreVerifierError {
fn from(e: StmSignatureError) -> Self {
CoreVerifierError::IndividualSignatureInvalid(e)
}
/// The supplied key is not valid
#[error("The verification of correctness of the supplied key is invalid.")]
KeyInvalid(Box<VerificationKeyPoP>),

/// Serialization error
#[error("Serialization error")]
SerializationError,

/// UnregisteredInitializer error
#[error("Initializer not registered. Cannot participate as a signer.")]
UnregisteredInitializer,
}

impl From<MultiSignatureError> for RegisterError {
Expand Down
30 changes: 17 additions & 13 deletions mithril-stm/src/key_reg.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
//! Key registration functionality.
use super::stm::Stake;
use crate::error::RegisterError;
use crate::merkle_tree::{MTLeaf, MerkleTree};
use crate::merkle_tree::leaf::MTLeaf;
use crate::merkle_tree::tree::MerkleTree;
use crate::multi_sig::{VerificationKey, VerificationKeyPoP};
use blake2::digest::{Digest, FixedOutput};
use std::collections::hash_map::Entry;
Expand All @@ -19,18 +20,6 @@ pub struct KeyReg {
keys: HashMap<VerificationKey, Stake>,
}

/// Structure generated out of a closed registration containing the registered parties, total stake, and the merkle tree.
/// One can only get a global `avk` out of a closed key registration.
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct ClosedKeyReg<D: Digest> {
/// Ordered list of registered parties.
pub reg_parties: Vec<RegParty>,
/// Total stake of the registered parties.
pub total_stake: Stake,
/// Unique public key out of the key registration instance.
pub merkle_tree: Arc<MerkleTree<D>>,
}

impl KeyReg {
/// Initialize an empty `KeyReg`.
pub fn init() -> Self {
Expand Down Expand Up @@ -78,6 +67,18 @@ impl KeyReg {
}
}

/// Structure generated out of a closed registration containing the registered parties, total stake, and the merkle tree.
/// One can only get a global `avk` out of a closed key registration.
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct ClosedKeyReg<D: Digest> {
/// Ordered list of registered parties.
pub reg_parties: Vec<RegParty>,
/// Total stake of the registered parties.
pub total_stake: Stake,
/// Unique public key out of the key registration instance.
pub merkle_tree: Arc<MerkleTree<D>>,
}

#[cfg(test)]
mod tests {
use super::*;
Expand All @@ -88,6 +89,9 @@ mod tests {
use rand_chacha::ChaCha20Rng;
use rand_core::SeedableRng;

// ---------------------------------------------------------------------
// Property test: `test_keyreg`
// ---------------------------------------------------------------------
proptest! {
#[test]
fn test_keyreg(stake in vec(1..1u64 << 60, 2..=10),
Expand Down
Loading
Loading