Module mithril_stm::stm

source ·
Expand description

Top-level API for Mithril Stake-based Threshold Multisignature scheme. See figure 6 of the paper for most of the protocol.

What follows is a simple example showing the usage of STM.

use blake2::{Blake2b, digest::consts::U32};
use mithril_stm::key_reg::KeyReg; // Import key registration functionality
use mithril_stm::stm::{StmClerk, StmInitializer, StmParameters, StmSig, StmSigner};
use mithril_stm::AggregationError;
use rayon::prelude::*; // We use par_iter to speed things up

use rand_chacha::ChaCha20Rng;
use rand_core::{RngCore, SeedableRng};

let nparties = 4; // Use a small number of parties for this example
type D = Blake2b<U32>; // Setting the hash function for convenience

let mut rng = ChaCha20Rng::from_seed([0u8; 32]); // create and initialize rng
let mut msg = [0u8; 16]; // setting an arbitrary message
rng.fill_bytes(&mut msg);

// In the following, we will have 4 parties try to sign `msg`, then aggregate and
// verify those signatures.

//////////////////////////
// initialization phase //
//////////////////////////

// Set low parameters for testing
// XXX: not for production
let params = StmParameters {
    m: 100, // Security parameter XXX: not for production
    k: 2, // Quorum parameter XXX: not for production
    phi_f: 0.2, // Lottery parameter XXX: not for production
};

// Generate some arbitrary stake for each party
// Stake is an integer.
// Total stake of all parties is total stake in the system.
let stakes = (0..nparties)
    .into_iter()
    .map(|_| 1 + (rng.next_u64() % 9999))
    .collect::<Vec<_>>();

// Create a new key registry from the parties and their stake
let mut key_reg = KeyReg::init();

// For each party, crate a StmInitializer.
// This struct can create keys for the party.
let mut ps: Vec<StmInitializer> = Vec::with_capacity(nparties);
for stake in stakes {
    // Create keys for this party
    let p = StmInitializer::setup(params, stake, &mut rng);
    // Register keys with the KeyReg service
    key_reg
        .register(p.stake, p.verification_key())
        .unwrap();
    ps.push(p);
}

// Close the key registration.
let closed_reg = key_reg.close();

// Finalize the StmInitializer and turn it into a StmSigner, which can execute the
// rest of the protocol.
let ps = ps
    .into_par_iter()
    .map(|p| p.new_signer(closed_reg.clone()).unwrap())
    .collect::<Vec<StmSigner<D>>>();

/////////////////////
// operation phase //
/////////////////////

// Next, each party tries to sign the message for each index available.
// We collect the successful signatures into a vec.
let sigs = ps
    .par_iter()
    .filter_map(|p| {
        return p.sign(&msg);
    })
    .collect::<Vec<StmSig>>();

// StmClerk can aggregate and verify signatures.
let clerk = StmClerk::from_signer(&ps[0]);

// Aggregate and verify the signatures
let msig = clerk.aggregate(&sigs, &msg);
match msig {
    Ok(aggr) => {
        println!("Aggregate ok");
        assert!(aggr
            .verify(&msg, &clerk.compute_avk(), &params)
            .is_ok());
    }
    Err(AggregationError::NotEnoughSignatures(n, k)) => {
        println!("Not enough signatures");
        assert!(n < params.k && k == params.k)
    }
    Err(_) => unreachable!(),
}

Structs§

  • Full node verifier including the list of eligible signers and the total stake of the system.
  • StmMultiSig uses the “concatenation” proving system (as described in Section 4.3 of the original paper.) This means that the aggregated signature contains a vector with all individual signatures. BatchPath is also a part of the aggregate signature which covers path for all signatures.
  • Stm aggregate key (batch compatible), which contains the merkle tree commitment and the total stake of the system. Batch Compat Merkle tree commitment includes the number of leaves in the tree in order to obtain batch path.
  • StmClerk can verify and aggregate StmSigs and verify StmMultiSigs. Clerks can only be generated with the registration closed. This avoids that a Merkle Tree is computed before all parties have registered.
  • Initializer for StmSigner. This is the data that is used during the key registration procedure. Once the latter is finished, this instance is consumed into an StmSigner.
  • Used to set protocol parameters.
  • Signature created by a single party who has won the lottery.
  • Signature with its registered party.
  • Participant in the protocol can sign messages.

Type Aliases§

  • Quorum index for signatures. An aggregate signature (StmMultiSig) must have at least k unique indices.
  • The quantity of stake held by a party, represented as a u64.
  • Wrapper of the MultiSignature Verification key
  • Wrapper of the MultiSignature Verification key with proof of possession