Skip to content

Commit

Permalink
feat: make GenesisMaterial usable by any node
Browse files Browse the repository at this point in the history
This commit makes GenesisMaterial fully fixed.  It no longer accepts an
amount parameter or any parameter.  This means that every node of every
type (mint, spentbook, wallet, audit) can know the GenesisMaterial
without need to consult any other node, so it greatly simplifies
coordination.

For now, the GENESIS_AMOUNT is set to u64::MAX.  This takes full
advantage of the u64 range.  It also caused some tests to break because
they use the genesis amount as a starting point and then increment.
Such tests were fixed by first reissuing to an intermediate
"starting_dbc" of the desired value.

 * use GenesisMaterial in SpentBookNodeMock
 * remove SpentBookNodeMock::set_genesis()
 * remove MintNode::GenesisDbcShare
 * remove MintNode::issue_genesis_dbc()
 * modify mismatched test to avoid int overflow
 * GenesisMaterial::new --> default()
 * define GENESIS_AMOUNT to u64::MAX
 * derive Default for GenesisBuilderMock
 * modify GenesisBuilderMock to build using GenesisMaterial
 * remove ability to choose genesis amount in mint-repl
 * modify reissue bench to first generate a dbc of value 100.
 * modify prop_dbc_validation() to first generate a dbc of value 100 to
   avoid integer overflow.
  • Loading branch information
dan-da committed Feb 23, 2022
1 parent aad4e7f commit 3b8d2d2
Show file tree
Hide file tree
Showing 8 changed files with 263 additions and 271 deletions.
67 changes: 57 additions & 10 deletions benches/reissue.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@
#![allow(clippy::from_iter_instead_of_collect)]

use sn_dbc::{
Amount, DbcBuilder, GenesisBuilderMock, KeyImage, Owner, OwnerOnce, ReissueRequestBuilder,
SpentProofShare,
Amount, Dbc, DbcBuilder, GenesisBuilderMock, KeyImage, MintNode, Owner, OwnerOnce,
ReissueRequestBuilder, Result, SimpleKeyManager, SpentBookNodeMock, SpentProofShare,
};

use blst_ringct::Output;
Expand All @@ -25,18 +25,18 @@ fn bench_reissue_1_to_100(c: &mut Criterion) {
let mut rng8 = rand8::rngs::StdRng::from_seed([0u8; 32]);
let mut rng = rand::rngs::StdRng::from_seed([0u8; 32]);

let (mintnode, mut spentbook, _genesis_dbc_share, genesis_dbc) =
GenesisBuilderMock::init_genesis_single(N_OUTPUTS as u64, &mut rng, &mut rng8).unwrap();
let (mintnode, mut spentbook, starting_dbc) =
generate_dbc_of_value(N_OUTPUTS as Amount, &mut rng, &mut rng8).unwrap();

let (reissue_tx, _revealed_commitments, _material, _output_owners) =
sn_dbc::TransactionBuilder::default()
.add_input_by_secrets(
genesis_dbc
starting_dbc
.owner_once_bearer()
.unwrap()
.secret_key_blst()
.unwrap(),
genesis_dbc.amount_secrets_bearer().unwrap(),
starting_dbc.amount_secrets_bearer().unwrap(),
vec![], // never any decoys for genesis
&mut rng8,
)
Expand Down Expand Up @@ -76,18 +76,18 @@ fn bench_reissue_100_to_1(c: &mut Criterion) {
let mut rng = rand::rngs::StdRng::from_seed([0u8; 32]);
let num_decoys = 0;

let (mintnode, mut spentbook, _genesis_dbc_share, genesis_dbc) =
GenesisBuilderMock::init_genesis_single(N_OUTPUTS as u64, &mut rng, &mut rng8).unwrap();
let (mintnode, mut spentbook, starting_dbc) =
generate_dbc_of_value(N_OUTPUTS as Amount, &mut rng, &mut rng8).unwrap();

let (reissue_tx, revealed_commitments, _material, output_owners) =
sn_dbc::TransactionBuilder::default()
.add_input_by_secrets(
genesis_dbc
starting_dbc
.owner_once_bearer()
.unwrap()
.secret_key_blst()
.unwrap(),
genesis_dbc.amount_secrets_bearer().unwrap(),
starting_dbc.amount_secrets_bearer().unwrap(),
vec![], // never any decoy inputs for genesis
&mut rng8,
)
Expand Down Expand Up @@ -170,6 +170,53 @@ fn bench_reissue_100_to_1(c: &mut Criterion) {
});
}

fn generate_dbc_of_value(
amount: Amount,
rng: &mut impl rand::RngCore,
rng8: &mut (impl rand8::RngCore + rand_core::CryptoRng),
) -> Result<(MintNode<SimpleKeyManager>, SpentBookNodeMock, Dbc)> {
let (mint_node, mut spentbook_node, genesis_dbc, _genesis_material, _amount_secrets) =
GenesisBuilderMock::init_genesis_single(rng, rng8)?;

let output_amounts = vec![amount, sn_dbc::GenesisMaterial::GENESIS_AMOUNT - amount];

let (tx, revealed_commitments, _material, output_owners) =
sn_dbc::TransactionBuilder::default()
.add_input_by_secrets(
genesis_dbc.owner_once_bearer()?.secret_key_blst()?,
genesis_dbc.amount_secrets_bearer()?,
vec![], // never any decoys for genesis
rng8,
)
.add_outputs(output_amounts.into_iter().map(|amount| {
let owner_once =
OwnerOnce::from_owner_base(Owner::from_random_secret_key(rng), rng8);
(
Output {
amount,
public_key: owner_once.as_owner().public_key_blst(),
},
owner_once,
)
}))
.build(rng8)?;

// Build ReissuRequest
let mut rr_builder = ReissueRequestBuilder::new(tx.clone());
for mlsag in tx.mlsags.iter() {
let spent_proof_share = spentbook_node.log_spent(mlsag.key_image.into(), tx.clone())?;
rr_builder = rr_builder.add_spent_proof_share(spent_proof_share);
}
let rr = rr_builder.build()?;

let reissue_share = mint_node.reissue(rr)?;
let mut dbc_builder = DbcBuilder::new(revealed_commitments, output_owners);
dbc_builder = dbc_builder.add_reissue_share(reissue_share);
let (starting_dbc, ..) = dbc_builder.build()?.into_iter().next().unwrap();

Ok((mint_node, spentbook_node, starting_dbc))
}

criterion_group! {
name = reissue;
config = Criterion::default().sample_size(10);
Expand Down
31 changes: 8 additions & 23 deletions examples/mint-repl/mint-repl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ fn main() -> Result<()> {
println!("Type 'help' to get started.\n");

// Create a default mint with money supply = 1000.
let mut mintinfo: MintInfo = mk_new_random_mint(0, 1000)?;
let mut mintinfo: MintInfo = mk_new_random_mint(0)?;

let mut rl = Editor::<()>::new();
rl.set_auto_add_history(true);
Expand Down Expand Up @@ -161,21 +161,6 @@ fn newmint() -> Result<MintInfo> {
return Err(anyhow!("newmint operation cancelled"));
}

let amount = loop {
let amount: Amount = readline_prompt("\nTotal Money Supply Amount: ")?.parse()?;

if amount == 0 {
let answer = readline_prompt(
"\nA mint with supply == 0 can only reissue Dbc worth 0. Change? [y/n]: ",
)?;
if answer.to_ascii_lowercase() != "n" {
continue;
}
// note: we allow amount to be 0. Let sn_dbc validation deal with it (or not).
}
break amount;
};

// polynomial, from which SecretKeySet is built.
let poly_input = readline_prompt_nl("\nSecretKeySet Poly Hex, or [r]andom: ")?;

Expand All @@ -190,12 +175,12 @@ fn newmint() -> Result<MintInfo> {
println!("\nThere must be at least 1 signer\n");
}
};
mk_new_random_mint(threshold, amount)?
mk_new_random_mint(threshold)?
}
_ => {
let poly: Poly = from_be_hex(&poly_input)?;
let secret_key_set = SecretKeySet::from(poly.clone());
mk_new_mint(secret_key_set, poly, amount)?
mk_new_mint(secret_key_set, poly)?
}
};

Expand All @@ -205,21 +190,21 @@ fn newmint() -> Result<MintInfo> {
}

/// creates a new mint using a random seed.
fn mk_new_random_mint(threshold: usize, amount: Amount) -> Result<MintInfo> {
fn mk_new_random_mint(threshold: usize) -> Result<MintInfo> {
let (poly, secret_key_set) = mk_secret_key_set(threshold)?;
mk_new_mint(secret_key_set, poly, amount)
mk_new_mint(secret_key_set, poly)
}

/// creates a new mint from an existing SecretKeySet that was seeded by poly.
fn mk_new_mint(sks: SecretKeySet, poly: Poly, genesis_amount: Amount) -> Result<MintInfo> {
fn mk_new_mint(sks: SecretKeySet, poly: Poly) -> Result<MintInfo> {
let mut rng8 = rand8::rngs::StdRng::from_seed([0u8; 32]);

// make as many spentbook nodes as mintnodes. (for now)
let num_mint_nodes = sks.threshold() + 1;
let num_spentbook_nodes = num_mint_nodes;

let (mint_nodes, spentbook_nodes, _genesis_dbc_shares, genesis_dbc) =
GenesisBuilderMock::from(genesis_amount)
let (mint_nodes, spentbook_nodes, genesis_dbc, _genesis, _amount_secrets) =
GenesisBuilderMock::default()
.gen_mint_nodes_with_sks(num_mint_nodes, &sks)
.gen_spentbook_nodes_with_sks(num_spentbook_nodes, &sks)
.build(&mut rng8)?;
Expand Down

0 comments on commit 3b8d2d2

Please sign in to comment.