Skip to content

Commit

Permalink
feat: expose Token type in public API
Browse files Browse the repository at this point in the history
  • Loading branch information
bochaco committed Aug 4, 2022
1 parent 290b09d commit 5333138
Show file tree
Hide file tree
Showing 12 changed files with 296 additions and 92 deletions.
21 changes: 12 additions & 9 deletions benches/reissue.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,18 +11,18 @@
use sn_dbc::{
mock,
rand::{CryptoRng, RngCore},
rng, Amount, Dbc, Owner, OwnerOnce, Result, TransactionVerifier,
rng, Dbc, Owner, OwnerOnce, Result, Token, TransactionVerifier,
};

use criterion::{black_box, criterion_group, criterion_main, Criterion};

const N_OUTPUTS: u32 = 100;
const N_OUTPUTS: u64 = 100;

fn bench_reissue_1_to_100(c: &mut Criterion) {
let mut rng = rng::from_seed([0u8; 32]);

let (mut spentbook, starting_dbc) =
generate_dbc_of_value(N_OUTPUTS as Amount, &mut rng).unwrap();
generate_dbc_of_value(Token::from_nano(N_OUTPUTS), &mut rng).unwrap();

let mut dbc_builder = sn_dbc::TransactionBuilder::default()
.set_require_all_decoys(false) // no decoys!
Expand All @@ -37,7 +37,7 @@ fn bench_reissue_1_to_100(c: &mut Criterion) {
.add_outputs_by_amount((0..N_OUTPUTS).into_iter().map(|_| {
let owner_once =
OwnerOnce::from_owner_base(Owner::from_random_secret_key(&mut rng), &mut rng);
(1, owner_once)
(Token::from_nano(1), owner_once)
}))
.build(&mut rng)
.unwrap();
Expand Down Expand Up @@ -70,7 +70,7 @@ fn bench_reissue_100_to_1(c: &mut Criterion) {
let mut rng = rng::from_seed([0u8; 32]);

let (mut spentbook_node, starting_dbc) =
generate_dbc_of_value(N_OUTPUTS as Amount, &mut rng).unwrap();
generate_dbc_of_value(Token::from_nano(N_OUTPUTS), &mut rng).unwrap();

let mut dbc_builder = sn_dbc::TransactionBuilder::default()
.set_require_all_decoys(false) // no decoys!
Expand All @@ -85,7 +85,7 @@ fn bench_reissue_100_to_1(c: &mut Criterion) {
.add_outputs_by_amount((0..N_OUTPUTS).into_iter().map(|_| {
let owner_once =
OwnerOnce::from_owner_base(Owner::from_random_secret_key(&mut rng), &mut rng);
(1, owner_once)
(Token::from_nano(1), owner_once)
}))
.build(&mut rng)
.unwrap();
Expand All @@ -108,7 +108,7 @@ fn bench_reissue_100_to_1(c: &mut Criterion) {
})
.collect(),
)
.add_output_by_amount(N_OUTPUTS as Amount, output_owner_once)
.add_output_by_amount(Token::from_nano(N_OUTPUTS), output_owner_once)
.build(&mut rng)
.unwrap();

Expand Down Expand Up @@ -137,13 +137,16 @@ fn bench_reissue_100_to_1(c: &mut Criterion) {
}

fn generate_dbc_of_value(
amount: Amount,
amount: Token,
rng: &mut (impl RngCore + CryptoRng),
) -> Result<(mock::SpentBookNode, Dbc)> {
let (mut spentbook_node, genesis_dbc, _genesis_material, _amount_secrets) =
mock::GenesisBuilder::init_genesis_single(rng)?;

let output_amounts = vec![amount, mock::GenesisMaterial::GENESIS_AMOUNT - amount];
let output_amounts = vec![
amount,
Token::from_nano(mock::GenesisMaterial::GENESIS_AMOUNT - amount.as_nano()),
];

let mut dbc_builder = sn_dbc::TransactionBuilder::default()
.set_require_all_decoys(false) // no decoys!
Expand Down
22 changes: 10 additions & 12 deletions examples/mint-repl/mint-repl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ use sn_dbc::{
},
mock,
rand::{seq::IteratorRandom, Rng},
rng, Amount, Dbc, DbcBuilder, OutputOwnerMap, Owner, OwnerOnce, RevealedCommitment,
RingCtMaterial, RingCtTransaction, TransactionBuilder,
rng, Dbc, DbcBuilder, OutputOwnerMap, Owner, OwnerOnce, RevealedCommitment, RingCtMaterial,
RingCtTransaction, Token, TransactionBuilder,
};

use std::collections::{BTreeMap, HashMap};
Expand Down Expand Up @@ -604,26 +604,24 @@ fn prepare_tx(mintinfo: &MintInfo) -> Result<DbcBuilder> {
// note, we upcast to i128 to allow negative value.
// This permits unbalanced inputs/outputs to reach sn_dbc layer for verification.
let inputs_amount_sum = tx_builder.inputs_amount_sum();
while inputs_amount_sum as i128 - tx_builder.outputs_amount_sum() as i128 > 0 {
while let Some(remaining) = inputs_amount_sum.checked_sub(tx_builder.outputs_amount_sum()) {
println!();
println!("------------");
println!("Output #{}", i);
println!("------------\n");

let remaining = inputs_amount_sum - tx_builder.outputs_amount_sum();

println!(
"Inputs total: {}. Remaining: {}",
inputs_amount_sum, remaining
);
let line = readline_prompt("Amount, or '[c]ancel': ")?;
let amount: Amount = if line == "c" {
let line = readline_prompt("Token, or '[c]ancel': ")?;
let amount: Token = if line == "c" {
println!("\nprepare_tx cancelled\n");
break;
} else {
line.parse()?
};
if amount > remaining || amount == 0 {
if amount > remaining || amount == Token::zero() {
let answer = readline_prompt(&format!(
"\nThe amount should normally be in the range 1..{}. Change it? [y/n]: ",
remaining
Expand Down Expand Up @@ -759,24 +757,24 @@ fn reissue_auto_cli(mintinfo: &mut MintInfo) -> Result<()> {

while tx_builder.outputs_amount_sum() < inputs_sum || tx_builder.outputs().is_empty() {
let amount = if tx_builder.outputs().len() >= max_outputs - 1 {
inputs_sum - tx_builder.outputs_amount_sum()
inputs_sum.as_nano() - tx_builder.outputs_amount_sum().as_nano()
} else {
// randomize output amount
let diff = inputs_sum - tx_builder.outputs_amount_sum();
let diff = inputs_sum.as_nano() - tx_builder.outputs_amount_sum().as_nano();

let is_last = rng.gen_range(0..max_outputs + 1) == max_outputs;
if is_last {
diff
} else {
let range_max = if diff == Amount::MAX { diff } else { diff + 1 };
let range_max = if diff == u64::MAX { diff } else { diff + 1 };
rng.gen_range(0..range_max)
}
};

let owner_once =
OwnerOnce::from_owner_base(Owner::from_random_secret_key(&mut rng), &mut rng);

tx_builder = tx_builder.add_output_by_amount(amount, owner_once);
tx_builder = tx_builder.add_output_by_amount(Token::from_nano(amount), owner_once);
}

let mut dbc_builder = tx_builder.build(&mut rng)?;
Expand Down
16 changes: 6 additions & 10 deletions src/amount_secrets.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,22 +6,18 @@
// KIND, either express or implied. Please review the Licences for the specific language governing
// permissions and limitations relating to use of the SAFE Network Software.

use crate::rand::RngCore;
use crate::{BlindingFactor, Error};
use bls_ringct::RevealedCommitment;
use crate::{rand::RngCore, BlindingFactor, Error, Token};
use bls_ringct::{ringct::Amount, RevealedCommitment};
use blsttc::{
Ciphertext, DecryptionShare, IntoFr, PublicKey, PublicKeySet, SecretKey, SecretKeySet,
SecretKeyShare,
};
use std::collections::BTreeMap;
use std::convert::TryFrom;

pub use bls_ringct::ringct::Amount;
use std::{collections::BTreeMap, convert::TryFrom};

#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};

const AMT_SIZE: usize = std::mem::size_of::<Amount>(); // Amount size: 8 bytes (u64)
const AMT_SIZE: usize = std::mem::size_of::<Token>(); // Amount size: 8 bytes (u64)
const BF_SIZE: usize = std::mem::size_of::<BlindingFactor>(); // Blinding factor size: 32 bytes (BlindingFactor)

/// AmountSecrets wraps bls_ringct::RevealedCommitment to provide some methods
Expand All @@ -39,8 +35,8 @@ pub struct AmountSecrets(RevealedCommitment);

impl AmountSecrets {
/// amount getter
pub fn amount(&self) -> Amount {
self.0.value
pub fn amount(&self) -> Token {
Token::from_nano(self.0.value)
}

/// blinding factor getter
Expand Down
28 changes: 16 additions & 12 deletions src/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
// KIND, either express or implied. Please review the Licences for the specific language governing
// permissions and limitations relating to use of the SAFE Network Software.

use bls_ringct::{bls_bulletproofs::PedersenGens, group::Curve, ringct::Amount};
use bls_ringct::{bls_bulletproofs::PedersenGens, group::Curve};
pub use bls_ringct::{
ringct::RingCtTransaction, DecoyInput, MlsagMaterial, Output, RevealedCommitment,
RingCtMaterial, TrueInput,
Expand All @@ -20,7 +20,7 @@ use std::{
use crate::{
rand::{CryptoRng, RngCore},
AmountSecrets, Commitment, Dbc, DbcContent, Error, Hash, KeyImage, OwnerOnce, Result,
SpentProof, SpentProofKeyVerifier, SpentProofShare, TransactionVerifier,
SpentProof, SpentProofKeyVerifier, SpentProofShare, Token, TransactionVerifier,
};

#[cfg(feature = "serde")]
Expand Down Expand Up @@ -201,19 +201,19 @@ impl TransactionBuilder {
self
}

/// add an output by providing Amount and OwnerOnce
pub fn add_output_by_amount(mut self, amount: Amount, owner: OwnerOnce) -> Self {
/// add an output by providing Token and OwnerOnce
pub fn add_output_by_amount(mut self, amount: Token, owner: OwnerOnce) -> Self {
let pk = owner.as_owner().public_key();
let output = Output::new(pk, amount);
let output = Output::new(pk, amount.as_nano());
self.output_owner_map.insert(pk, owner);
self.ringct_material.outputs.push(output);
self
}

/// add an output by providing iter of (Amount, OwnerOnce)
/// add an output by providing iter of (Token, OwnerOnce)
pub fn add_outputs_by_amount(
mut self,
outputs: impl IntoIterator<Item = (Amount, OwnerOnce)>,
outputs: impl IntoIterator<Item = (Token, OwnerOnce)>,
) -> Self {
for (amount, owner) in outputs.into_iter() {
self = self.add_output_by_amount(amount, owner);
Expand All @@ -230,16 +230,20 @@ impl TransactionBuilder {
}

/// get sum of input amounts
pub fn inputs_amount_sum(&self) -> Amount {
self.true_inputs
pub fn inputs_amount_sum(&self) -> Token {
let amount = self
.true_inputs
.iter()
.map(|t| t.revealed_commitment.value)
.sum()
.sum();

Token::from_nano(amount)
}

/// get sum of output amounts
pub fn outputs_amount_sum(&self) -> Amount {
self.ringct_material.outputs.iter().map(|o| o.amount).sum()
pub fn outputs_amount_sum(&self) -> Token {
let amount = self.ringct_material.outputs.iter().map(|o| o.amount).sum();
Token::from_nano(amount)
}

/// get true inputs
Expand Down
33 changes: 18 additions & 15 deletions src/dbc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -325,19 +325,19 @@ pub(crate) mod tests {
use crate::{
mock,
rand::{CryptoRng, RngCore},
Amount, AmountSecrets, DbcBuilder, Hash, Owner, OwnerOnce, SpentProofContent,
AmountSecrets, DbcBuilder, Hash, Owner, OwnerOnce, SpentProofContent, Token,
};
use bls_ringct::{bls_bulletproofs::PedersenGens, ringct::RingCtMaterial, Output};
use blsttc::PublicKey;
use std::convert::TryInto;

fn divide(amount: Amount, n_ways: u8) -> impl Iterator<Item = Amount> {
fn divide(amount: Token, n_ways: u8) -> impl Iterator<Item = Token> {
(0..n_ways).into_iter().map(move |i| {
let equal_parts = amount / (n_ways as Amount);
let leftover = amount % (n_ways as Amount);
let equal_parts = amount.as_nano() / n_ways as u64;
let leftover = amount.as_nano() % n_ways as u64;

let odd_compensation = if (i as Amount) < leftover { 1 } else { 0 };
equal_parts + odd_compensation
let odd_compensation = if (i as u64) < leftover { 1 } else { 0 };
Token::from_nano(equal_parts + odd_compensation)
})
}

Expand Down Expand Up @@ -376,7 +376,7 @@ pub(crate) mod tests {
fn from_hex_should_deserialize_a_hex_encoded_string_to_a_dbc() -> Result<(), Error> {
let dbc = Dbc::from_hex(DBC_WITH_1_530_000_000)?;
let amount = dbc.amount_secrets_bearer()?.amount();
assert_eq!(amount, 1_530_000_000);
assert_eq!(amount, Token::from_nano(1_530_000_000));
Ok(())
}

Expand Down Expand Up @@ -586,7 +586,7 @@ pub(crate) mod tests {
.set_require_all_decoys(false)
.add_decoy_inputs(decoy_inputs)
.add_inputs_dbc(inputs)?
.add_output_by_amount(amount, owner_once.clone())
.add_output_by_amount(Token::from_nano(amount), owner_once.clone())
.build(&mut rng)?;

for (key_image, tx) in dbc_builder.inputs() {
Expand All @@ -611,7 +611,7 @@ pub(crate) mod tests {
.collect();

let fuzzed_amt_secrets = AmountSecrets::from((
amount + extra_output_amount.coerce::<Amount>(),
amount + extra_output_amount.coerce::<u64>(),
amount_secrets_list[0].blinding_factor(),
));
let dbc_amount = fuzzed_amt_secrets.amount();
Expand Down Expand Up @@ -736,7 +736,7 @@ pub(crate) mod tests {
assert_eq!(n_wrong_signer_sigs.coerce::<u8>(), 0);
assert_eq!(n_wrong_msg_sigs.coerce::<u8>(), 0);

assert_eq!(dbc_amount, amount);
assert_eq!(dbc_amount, Token::from_nano(amount));
assert_eq!(extra_output_amount.coerce::<u8>(), 0);
}
Err(Error::SpentProofInputLenMismatch { current, expected }) => {
Expand All @@ -758,7 +758,7 @@ pub(crate) mod tests {
assert_eq!(n_inputs.coerce::<u8>(), 0);
}
Err(Error::AmountCommitmentsDoNotMatch) => {
assert_ne!(amount, dbc_amount);
assert_ne!(Token::from_nano(amount), dbc_amount);
assert_ne!(extra_output_amount, TinyInt(0));
}
Err(Error::InvalidSpentProofSignature(_pk, _msg)) => {
Expand All @@ -784,14 +784,14 @@ pub(crate) mod tests {
}

pub(crate) fn generate_bearer_dbc_of_value(
amount: Amount,
amount: u64,
rng: &mut (impl RngCore + CryptoRng),
) -> Result<(mock::SpentBookNode, Dbc, Dbc, Dbc)> {
generate_dbc_of_value(amount, Owner::from_random_secret_key(rng), rng)
}

pub(crate) fn generate_owned_dbc_of_value(
amount: Amount,
amount: u64,
pk_hex: &str,
rng: &mut (impl RngCore + CryptoRng),
) -> Result<(mock::SpentBookNode, Dbc, Dbc, Dbc)> {
Expand All @@ -810,14 +810,17 @@ pub(crate) mod tests {
}

fn generate_dbc_of_value(
amount: Amount,
amount: u64,
owner: Owner,
rng: &mut (impl RngCore + CryptoRng),
) -> Result<(mock::SpentBookNode, Dbc, Dbc, Dbc)> {
let (mut spentbook_node, genesis_dbc, _genesis_material, _amount_secrets) =
mock::GenesisBuilder::init_genesis_single(rng)?;

let output_amounts = vec![amount, mock::GenesisMaterial::GENESIS_AMOUNT - amount];
let output_amounts = vec![
Token::from_nano(amount),
Token::from_nano(mock::GenesisMaterial::GENESIS_AMOUNT - amount),
];

let mut dbc_builder = crate::TransactionBuilder::default()
.set_require_all_decoys(false)
Expand Down
12 changes: 11 additions & 1 deletion src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,20 @@ use crate::KeyImage;
pub type Result<T, E = Error> = std::result::Result<T, E>;

#[allow(clippy::large_enum_variant)]
#[derive(Error, Debug, Clone)]
#[derive(Error, Debug, Clone, PartialEq)]
#[non_exhaustive]
/// Node error variants.
pub enum Error {
/// While parsing a `Token`, precision would be lost.
#[error("Lost precision on the number of coins during parsing")]
LossOfTokenPrecision,
/// The amount would exceed the maximum value for `Token` (u64::MAX).
#[error("The token amount would exceed the maximum value (u64::MAX)")]
ExcessiveTokenValue,
/// Failed to parse a `Token` from a string.
#[error("Failed to parse: {0}")]
FailedToParseToken(String),

#[error("Failed signature check.")]
FailedSignature,

Expand Down

0 comments on commit 5333138

Please sign in to comment.