Skip to content

Commit

Permalink
fix: refactor to validate spent_proofs in Dbc::confirm_valid
Browse files Browse the repository at this point in the history
  • Loading branch information
dan-da authored and dirvine committed Feb 17, 2022
1 parent 6670818 commit 0059b3e
Show file tree
Hide file tree
Showing 6 changed files with 187 additions and 129 deletions.
4 changes: 4 additions & 0 deletions src/amount_secrets.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,10 @@ impl AmountSecrets {
self.0.value
}

pub fn blinding_factor(&self) -> Scalar {
self.0.blinding
}

/// Convert to bytes
pub fn to_bytes(&self) -> Vec<u8> {
self.0.to_bytes()
Expand Down
89 changes: 45 additions & 44 deletions src/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ pub use blstrs::{G1Affine, Scalar};
use blsttc::{PublicKeySet, SignatureShare};
use bulletproofs::PedersenGens;
use rand_core::RngCore;
use std::collections::{BTreeMap, HashSet};
use std::collections::{BTreeMap, BTreeSet, HashSet};

use crate::{
Amount, AmountSecrets, Dbc, DbcContent, Error, KeyImage, NodeSignature, ReissueRequest,
Expand All @@ -26,6 +26,29 @@ impl TransactionBuilder {
self
}

pub fn add_input_by_true_input(
mut self,
true_input: TrueInput,
decoy_inputs: Vec<DecoyInput>,
mut rng: impl RngCore,
) -> Self {
self.0
.inputs
.push(MlsagMaterial::new(true_input, decoy_inputs, &mut rng));
self
}

pub fn add_inputs_by_true_inputs(
mut self,
inputs: Vec<(TrueInput, Vec<DecoyInput>)>,
mut rng: impl RngCore,
) -> Self {
for (true_input, decoy_inputs) in inputs.into_iter() {
self = self.add_input_by_true_input(true_input, decoy_inputs, &mut rng);
}
self
}

pub fn add_input_by_secrets(
mut self,
secret_key: Scalar,
Expand Down Expand Up @@ -110,15 +133,15 @@ impl ReissueRequestBuilder {
}

/// Add a SpentProofShare for the given key_image
pub fn add_spent_proof_share(mut self, key_image: KeyImage, share: SpentProofShare) -> Self {
let shares = self.spent_proof_shares.entry(key_image).or_default();
pub fn add_spent_proof_share(mut self, share: SpentProofShare) -> Self {
let shares = self.spent_proof_shares.entry(share.key_image).or_default();
shares.insert(share);

self
}

pub fn build(&self) -> Result<ReissueRequest> {
let spent_proofs: BTreeMap<KeyImage, SpentProof> = self
let spent_proofs: BTreeSet<SpentProof> = self
.spent_proof_shares
.iter()
.map(|(key_image, shares)| {
Expand Down Expand Up @@ -153,24 +176,14 @@ impl ReissueRequestBuilder {

let public_commitments: Vec<G1Affine> = any_share.public_commitments.clone();

let index = match self
.transaction
.mlsags
.iter()
.position(|m| m.key_image.to_compressed() == *key_image)
{
Some(idx) => idx,
None => return Err(Error::SpentProofKeyImageMismatch),
};

let spent_proof = SpentProof {
index,
key_image: *key_image,
spentbook_pub_key,
spentbook_sig,
public_commitments,
};

Ok((*key_image, spent_proof))
Ok(spent_proof)
})
.collect::<Result<_>>()?;

Expand All @@ -189,19 +202,14 @@ impl ReissueRequestBuilder {
/// generate the final Dbc outputs.
#[derive(Debug)]
pub struct DbcBuilder {
pub transaction: RingCtTransaction,
pub revealed_commitments: Vec<RevealedCommitment>,
pub reissue_shares: Vec<ReissueShare>,
}

impl DbcBuilder {
/// Create a new DbcBuilder from a ReissueTransaction
pub fn new(
transaction: RingCtTransaction,
revealed_commitments: Vec<RevealedCommitment>,
) -> Self {
pub fn new(revealed_commitments: Vec<RevealedCommitment>) -> Self {
Self {
transaction,
revealed_commitments,
reissue_shares: Default::default(),
}
Expand Down Expand Up @@ -246,28 +254,21 @@ impl DbcBuilder {
// add pubkeyset to HashSet, so we can verify there is only one distinct PubKeySet
pk_set = &pk_set | &pub_key_sets; // union the sets together.

// Verify transaction returned to us by the Mint matches our request

// fixme: binary operation `!=` cannot be applied to type `RingCtTransaction`

// if self.transaction != rs.transaction {
// return Err(Error::ReissueShareDbcTransactionMismatch);
// }

// Verify that mint sig count matches input count.
if rs.mint_node_signatures.len() != self.transaction.mlsags.len() {
if rs.mint_node_signatures.len() != rs.transaction.mlsags.len() {
return Err(Error::ReissueShareMintNodeSignaturesLenMismatch);
}

// Verify that each input has a NodeSignature

// todo: what to replace this with?

// for input in self.reissue_transaction.inputs.iter() {
// if rs.mint_node_signatures.get(&input.spend_key()).is_none() {
// return Err(Error::ReissueShareMintNodeSignatureNotFoundForInput);
// }
// }
for mlsag in rs.transaction.mlsags.iter() {
if rs
.mint_node_signatures
.get(&mlsag.key_image.to_compressed())
.is_none()
{
return Err(Error::ReissueShareMintNodeSignatureNotFoundForInput);
}
}
}

// verify that PublicKeySet for all Dbc in all ReissueShare match.
Expand All @@ -286,8 +287,9 @@ impl DbcBuilder {
.collect();

// Note: we can just use the first item because we already verified that
// all the ReissueShare match for dbc_transaction
// all the ReissueShare match
let transaction = &self.reissue_shares[0].transaction;
let spent_proofs = &self.reissue_shares[0].spent_proofs;

// Combine signatures from all the mint nodes to obtain Mint's Signature.
let mint_sig = mint_public_key_set.combine_signatures(mint_sig_shares_ref)?;
Expand All @@ -300,8 +302,7 @@ impl DbcBuilder {
.collect();

// Form the final output DBCs, with Mint's Signature for each.
let output_dbcs: Vec<Dbc> = self
.transaction
let output_dbcs: Vec<Dbc> = transaction
.outputs
.iter()
.map(|proof| {
Expand All @@ -318,8 +319,7 @@ impl DbcBuilder {
amount_secrets_list[0].clone(),
)),
transaction: transaction.clone(),
transaction_sigs: self
.transaction
transaction_sigs: transaction
.mlsags
.iter()
.map(|mlsag| {
Expand All @@ -329,6 +329,7 @@ impl DbcBuilder {
)
})
.collect(),
spent_proofs: spent_proofs.clone(),
}
})
.collect();
Expand Down
29 changes: 15 additions & 14 deletions src/dbc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,10 @@

use crate::{dbc_content::OwnerPublicKey, DbcContent, Error, KeyManager, Result};

use crate::{Hash, SpentProof};
use blst_ringct::ringct::RingCtTransaction;
use blsttc::{PublicKey, Signature};
use std::collections::BTreeMap;
use std::collections::{BTreeMap, BTreeSet};
use tiny_keccak::{Hasher, Sha3};

// note: typedef should be moved into blst_ringct crate
Expand All @@ -22,6 +23,7 @@ pub struct Dbc {
pub content: DbcContent,
pub transaction: RingCtTransaction,
pub transaction_sigs: BTreeMap<KeyImage, (PublicKey, Signature)>,
pub spent_proofs: BTreeSet<SpentProof>,
}

impl Dbc {
Expand Down Expand Up @@ -52,21 +54,20 @@ impl Dbc {
hash
}

// todo: Do we even need this fn anymore? not called by MintNode::reissue()...
// To be correct, it would need to call RingCtTransaction::verify()...

// Check there exists a DbcTransaction with the output containing this Dbc
// Check there DOES NOT exist a DbcTransaction with this Dbc as parent (already minted)
pub fn confirm_valid<K: KeyManager>(&self, _verifier: &K) -> Result<(), Error> {
// for (input, (mint_key, mint_sig)) in self.transaction_sigs.iter() {
// if !self.transaction.inputs.contains(input) {
// return Err(Error::UnknownInput);
// }

// verifier
// .verify(&self.transaction.hash(), mint_key, mint_sig)
// .map_err(|e| Error::Signing(e.to_string()))?;
// }
pub fn confirm_valid<K: KeyManager>(&self, verifier: &K) -> Result<(), Error> {
for spent_proof in self.spent_proofs.iter() {
if !self
.transaction
.mlsags
.iter()
.any(|m| m.key_image.to_compressed() == spent_proof.key_image)
{
return Err(Error::UnknownInput);
}
spent_proof.validate(Hash::from(self.transaction.hash()), verifier)?;
}

if self.transaction.mlsags.is_empty() {
Err(Error::TransactionMustHaveAnInput)
Expand Down
9 changes: 5 additions & 4 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -135,22 +135,23 @@ impl DbcHelper {
}
}

pub(crate) struct BlsHelper {}
// temporary: should go away once blsttc is integrated with with blstrs
pub struct BlsHelper {}

impl BlsHelper {
#[allow(dead_code)]
pub(crate) fn blsttc_to_blstrs_sk(sk: SecretKey) -> Scalar {
pub fn blsttc_to_blstrs_sk(sk: SecretKey) -> Scalar {
let bytes = sk.to_bytes();
println!("sk bytes: {:?}", bytes);
Scalar::from_bytes_be(&bytes).unwrap()
}

pub(crate) fn blsttc_to_blstrs_pubkey(pk: &PublicKey) -> G1Affine {
pub fn blsttc_to_blstrs_pubkey(pk: &PublicKey) -> G1Affine {
let bytes = pk.to_bytes();
G1Affine::from_compressed(&bytes).unwrap()
}

pub(crate) fn blstrs_to_blsttc_pubkey(pk: &G1Affine) -> PublicKey {
pub fn blstrs_to_blsttc_pubkey(pk: &G1Affine) -> PublicKey {
let bytes = pk.to_compressed();
PublicKey::from_bytes(bytes).unwrap()
}
Expand Down
Loading

0 comments on commit 0059b3e

Please sign in to comment.