Skip to content

Commit

Permalink
feat: dbc reasons in SpentProof
Browse files Browse the repository at this point in the history
BREAKING CHANGE: Changes the SpentProofs
  • Loading branch information
grumbach committed Mar 2, 2023
1 parent 979cb83 commit 6a6eeea
Show file tree
Hide file tree
Showing 11 changed files with 146 additions and 52 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,8 @@ deploy/
cargo-all.sh
bindings
tmp

reissue_merge_100_to_1.svg
reissue_split_1_to_100.svg

# Added by cargo

Expand Down
24 changes: 15 additions & 9 deletions benches/reissue.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
use sn_dbc::{
mock,
rand::{CryptoRng, RngCore},
rng, Dbc, Owner, OwnerOnce, Result, Token, TransactionVerifier,
rng, Dbc, Hash, Owner, OwnerOnce, Result, Token, TransactionVerifier,
};

use criterion::{black_box, criterion_group, criterion_main, Criterion};
Expand Down Expand Up @@ -41,8 +41,10 @@ fn bench_reissue_1_to_100(c: &mut Criterion) {
.build(&mut rng)
.unwrap();

for (key_image, tx) in dbc_builder.inputs() {
let spent_proof_share = spentbook.log_spent(key_image, tx).unwrap();
for (public_key, tx) in dbc_builder.inputs() {
let spent_proof_share = spentbook
.log_spent(public_key, tx, Hash::default())
.unwrap();
dbc_builder = dbc_builder.add_spent_proof_share(spent_proof_share);
}

Expand Down Expand Up @@ -88,8 +90,10 @@ fn bench_reissue_100_to_1(c: &mut Criterion) {
.build(&mut rng)
.unwrap();

for (key_image, tx) in dbc_builder.inputs() {
let spent_proof_share = spentbook_node.log_spent(key_image, tx).unwrap();
for (public_key, tx) in dbc_builder.inputs() {
let spent_proof_share = spentbook_node
.log_spent(public_key, tx, Hash::default())
.unwrap();
dbc_builder = dbc_builder.add_spent_proof_share(spent_proof_share);
}
let dbcs = dbc_builder.build(&spentbook_node.key_manager).unwrap();
Expand All @@ -109,8 +113,10 @@ fn bench_reissue_100_to_1(c: &mut Criterion) {
.build(&mut rng)
.unwrap();

for (key_image, tx) in merge_dbc_builder.inputs() {
let spent_proof_share = spentbook_node.log_spent(key_image, tx).unwrap();
for (public_key, tx) in merge_dbc_builder.inputs() {
let spent_proof_share = spentbook_node
.log_spent(public_key, tx, Hash::default())
.unwrap();
merge_dbc_builder = merge_dbc_builder.add_spent_proof_share(spent_proof_share);
}

Expand Down Expand Up @@ -156,8 +162,8 @@ fn generate_dbc_of_value(
}))
.build(rng)?;

for (key_image, tx) in dbc_builder.inputs() {
let spent_proof_share = spentbook_node.log_spent(key_image, tx)?;
for (public_key, tx) in dbc_builder.inputs() {
let spent_proof_share = spentbook_node.log_spent(public_key, tx, Hash::default())?;
dbc_builder = dbc_builder.add_spent_proof_share(spent_proof_share);
}

Expand Down
14 changes: 9 additions & 5 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, Dbc, DbcBuilder, DbcTransaction, OutputOwnerMap, Owner, OwnerOnce, RevealedCommitment,
RevealedTransaction, Token, TransactionBuilder,
rng, Dbc, DbcBuilder, DbcTransaction, Hash, OutputOwnerMap, Owner, OwnerOnce,
RevealedCommitment, RevealedTransaction, Token, TransactionBuilder,
};

use std::collections::{BTreeMap, HashMap};
Expand Down Expand Up @@ -662,8 +662,11 @@ fn write_to_spentbook(mintinfo: &mut MintInfo, mut dbc_builder: DbcBuilder) -> R
for (public_key, tx) in dbc_builder.inputs() {
for (sp_idx, sb_node) in mintinfo.spentbook_nodes.iter_mut().enumerate() {
println!("logging input {public_key:?}, spentbook {sp_idx}");
dbc_builder =
dbc_builder.add_spent_proof_share(sb_node.log_spent(public_key, tx.clone())?);
dbc_builder = dbc_builder.add_spent_proof_share(sb_node.log_spent(
public_key,
tx.clone(),
Hash::default(),
)?);
}
dbc_builder = dbc_builder.add_spent_transaction(tx);
}
Expand Down Expand Up @@ -753,7 +756,8 @@ fn reissue_auto_cli(mintinfo: &mut MintInfo) -> Result<()> {
for (public_key, tx) in dbc_builder.inputs() {
for spentbook_node in mintinfo.spentbook_nodes.iter_mut() {
let log_spent_start = SystemTime::now();
let spent_proof_share = spentbook_node.log_spent(public_key, tx.clone())?;
let spent_proof_share =
spentbook_node.log_spent(public_key, tx.clone(), Hash::default())?;
log_spent_duration += log_spent_start.elapsed().unwrap();
dbc_builder = dbc_builder
.add_spent_proof_share(spent_proof_share)
Expand Down
4 changes: 2 additions & 2 deletions src/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -357,8 +357,8 @@ impl DbcBuilder {
let spent_proofs: BTreeSet<SpentProof> = self
.spent_proof_shares
.iter()
.map(|(key_image, shares)| {
SpentProof::try_from_proof_shares(*key_image, transaction_hash, shares.iter())
.map(|(public_key, shares)| {
SpentProof::try_from_proof_shares(*public_key, transaction_hash, shares.iter())
})
.chain(self.spent_proofs.iter().cloned().map(Ok))
.collect::<Result<_>>()?;
Expand Down
39 changes: 36 additions & 3 deletions src/dbc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,16 @@ impl Dbc {
self.amount_secrets(&self.owner_base().secret_key()?)
}

/// returns the reason (if any) why this dbc was spent
pub fn reason(&self) -> Option<Hash> {
let reason = self.spent_proofs.iter().next()?.reason();
if reason == Hash::default() {
None
} else {
Some(reason)
}
}

/// returns PublicKey for the owner's derived public key
/// This is useful for checking if a Dbc has been spent.
pub fn public_key(&self, base_sk: &SecretKey) -> Result<PublicKey> {
Expand Down Expand Up @@ -224,6 +234,16 @@ impl Dbc {
return Err(Error::MissingSpentTransaction);
}

// verify that all spent_proofs reasons are equal
let reason = self.reason();
let reasons_are_equal = |s: &SpentProof| match reason {
Some(r) => r == s.reason(),
None => s.reason() == Hash::default(),
};
if !self.spent_proofs.iter().all(reasons_are_equal) {
return Err(Error::SpentProofShareReasonMismatch(owner));
}

self.verify_amount_matches_commitment(base_sk)
}

Expand Down Expand Up @@ -357,7 +377,11 @@ pub(crate) mod tests {

for (public_key, tx) in dbc_builder.inputs() {
dbc_builder = dbc_builder
.add_spent_proof_share(spentbook_node.log_spent(public_key, tx.clone())?)
.add_spent_proof_share(spentbook_node.log_spent(
public_key,
tx.clone(),
Hash::default(),
)?)
.add_spent_transaction(tx);
}

Expand Down Expand Up @@ -580,7 +604,11 @@ pub(crate) mod tests {

for (public_key, tx) in dbc_builder.inputs() {
dbc_builder = dbc_builder
.add_spent_proof_share(spentbook_node.log_spent(public_key, tx.clone())?)
.add_spent_proof_share(spentbook_node.log_spent(
public_key,
tx.clone(),
Hash::default(),
)?)
.add_spent_transaction(tx);
}

Expand Down Expand Up @@ -674,6 +702,7 @@ pub(crate) mod tests {
let content = SpentProofContent {
public_key: secret_key.public_key(),
transaction_hash: spent_proof.transaction_hash(),
reason: Hash::default(),
public_commitment: *spent_proof.public_commitment(),
};

Expand Down Expand Up @@ -824,7 +853,11 @@ pub(crate) mod tests {

for (public_key, tx) in dbc_builder.inputs() {
dbc_builder = dbc_builder
.add_spent_proof_share(spentbook_node.log_spent(public_key, tx.clone())?)
.add_spent_proof_share(spentbook_node.log_spent(
public_key,
tx.clone(),
Hash::default(),
)?)
.add_spent_transaction(tx);
}

Expand Down
3 changes: 3 additions & 0 deletions src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,9 @@ pub enum Error {
#[error("We need at least one spent proof share for {0:?} to build a SpentProof")]
MissingSpentProofShare(PublicKey),

#[error("SpentProofShares for {0:?} have mismatching reasons")]
SpentProofShareReasonMismatch(PublicKey),

#[error("Decryption failed")]
DecryptionBySecretKeyFailed,

Expand Down
2 changes: 1 addition & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ pub use crate::{
use serde::{Deserialize, Serialize};

#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
#[derive(Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, Default)]
pub struct Hash([u8; 32]);

impl Hash {
Expand Down
64 changes: 42 additions & 22 deletions src/mint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,10 @@

#[cfg(test)]
mod tests {

use crate::tests::{TinyInt, TinyVec};
use crate::{
tests::{TinyInt, TinyVec},
Hash,
};
use blsttc::{PublicKey, SecretKey, SecretKeySet};
use quickcheck_macros::quickcheck;
use std::collections::BTreeSet;
Expand Down Expand Up @@ -85,10 +87,11 @@ mod tests {
};

for (public_key, tx) in dbc_builder.inputs() {
let spent_proof_share = match spentbook_node.log_spent(public_key, tx.clone()) {
Ok(s) => s,
Err(e) => return check_error(e),
};
let spent_proof_share =
match spentbook_node.log_spent(public_key, tx.clone(), Hash::default()) {
Ok(s) => s,
Err(e) => return check_error(e),
};
dbc_builder = dbc_builder
.add_spent_proof_share(spent_proof_share)
.add_spent_transaction(tx);
Expand Down Expand Up @@ -187,11 +190,14 @@ mod tests {

for (public_key, tx) in dbc_builder.inputs() {
// normally spentbook verifies the tx, but here we skip it in order check reissue results.
let spent_proof_share =
match spentbook_node.log_spent_and_skip_tx_verification(public_key, tx.clone()) {
Ok(s) => s,
Err(e) => return check_tx_error(e),
};
let spent_proof_share = match spentbook_node.log_spent_and_skip_tx_verification(
public_key,
Hash::default(),
tx.clone(),
) {
Ok(s) => s,
Err(e) => return check_tx_error(e),
};
dbc_builder = dbc_builder
.add_spent_proof_share(spent_proof_share)
.add_spent_transaction(tx);
Expand Down Expand Up @@ -284,14 +290,16 @@ mod tests {
}
1 if is_invalid_spent_proof => {
// spentbook verifies the tx. If an error, we need to check it
let spent_proof_share = match spentbook_node.log_spent(public_key, tx.clone()) {
Ok(s) => s,
Err(e) => return check_error(e),
};
let spent_proof_share =
match spentbook_node.log_spent(public_key, tx.clone(), Hash::default()) {
Ok(s) => s,
Err(e) => return check_error(e),
};
SpentProofShare {
content: SpentProofContent {
public_key: *spent_proof_share.public_key(),
transaction_hash: spent_proof_share.transaction_hash(),
reason: Hash::default(),
public_commitment: *spent_proof_share.public_commitment(),
},
spentbook_pks: spent_proof_share.spentbook_pks,
Expand All @@ -305,7 +313,7 @@ mod tests {
}
_ => {
// spentbook verifies the tx.
match spentbook_node.log_spent(public_key, tx.clone()) {
match spentbook_node.log_spent(public_key, tx.clone(), Hash::default()) {
Ok(s) => s,
Err(e) => return check_error(e),
}
Expand Down Expand Up @@ -458,7 +466,11 @@ mod tests {

for (public_key, tx) in dbc_builder.inputs() {
dbc_builder = dbc_builder
.add_spent_proof_share(spentbook.log_spent(public_key, tx.clone())?)
.add_spent_proof_share(spentbook.log_spent(
public_key,
tx.clone(),
Hash::default(),
)?)
.add_spent_transaction(tx);
}

Expand Down Expand Up @@ -541,7 +553,7 @@ mod tests {
// ----------

for (public_key, tx) in dbc_builder_fudged.inputs() {
match spentbook.log_spent(public_key, tx) {
match spentbook.log_spent(public_key, tx, Hash::default()) {
Err(Error::Transaction(crate::transaction::Error::InvalidCommitment)) => {}
_ => panic!("Expecting Transaction Error::InvalidCommitment"),
}
Expand All @@ -555,8 +567,11 @@ mod tests {
// normally spentbook verifies the tx, but here we skip it in order to obtain
// a spentproof with an invalid tx.
for (public_key, tx) in dbc_builder_fudged.inputs() {
let spent_proof_share =
spentbook.log_spent_and_skip_tx_verification(public_key, tx.clone())?;
let spent_proof_share = spentbook.log_spent_and_skip_tx_verification(
public_key,
Hash::default(),
tx.clone(),
)?;
dbc_builder_fudged = dbc_builder_fudged
.add_spent_proof_share(spent_proof_share)
.add_spent_transaction(tx);
Expand Down Expand Up @@ -595,7 +610,8 @@ mod tests {

let dbc_builder_bad_proof = dbc_builder_true.clone();
for (public_key, tx) in dbc_builder_bad_proof.inputs() {
let result = spentbook.log_spent_and_skip_tx_verification(public_key, tx);
let result =
spentbook.log_spent_and_skip_tx_verification(public_key, Hash::default(), tx);

// The builder should return an error because the spentproof does not match the tx.
match result {
Expand Down Expand Up @@ -625,18 +641,22 @@ mod tests {
let _genesis_spent_proof_share = new_spentbook.log_spent(
genesis_dbc.transaction.inputs[0].public_key,
genesis_dbc.transaction.clone(),
Hash::default(),
)?;
let _starting_spent_proof_share = new_spentbook.log_spent(
starting_dbc.transaction.inputs[0].public_key,
starting_dbc.transaction.clone(),
Hash::default(),
)?;
let _spent_proof_share = new_spentbook.log_spent(
b_dbc.transaction.inputs[0].public_key,
b_dbc.transaction.clone(),
Hash::default(),
)?;

for (public_key, tx) in dbc_builder_true.inputs() {
let spent_proof_share = new_spentbook.log_spent(public_key, tx.clone())?;
let spent_proof_share =
new_spentbook.log_spent(public_key, tx.clone(), Hash::default())?;
dbc_builder_true = dbc_builder_true
.add_spent_proof_share(spent_proof_share)
.add_spent_transaction(tx);
Expand Down
11 changes: 7 additions & 4 deletions src/mock/genesis_builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use super::GenesisMaterial;
use crate::{
mock,
rand::{CryptoRng, RngCore},
AmountSecrets, Dbc, Result, TransactionBuilder,
AmountSecrets, Dbc, Hash, Result, TransactionBuilder,
};
use blsttc::SecretKeySet;

Expand Down Expand Up @@ -87,10 +87,13 @@ impl GenesisBuilder {
)
.build(rng)?;

for (key_image, tx) in dbc_builder.inputs() {
for (public_key, tx) in dbc_builder.inputs() {
for spentbook_node in self.spentbook_nodes.iter_mut() {
dbc_builder = dbc_builder
.add_spent_proof_share(spentbook_node.log_spent(key_image, tx.clone())?);
dbc_builder = dbc_builder.add_spent_proof_share(spentbook_node.log_spent(
public_key,
tx.clone(),
Hash::default(),
)?);
}
dbc_builder = dbc_builder.add_spent_transaction(tx);
}
Expand Down

0 comments on commit 6a6eeea

Please sign in to comment.