Skip to content

Commit

Permalink
feat!: simplifying spent proofs and TX verification public APIs
Browse files Browse the repository at this point in the history
  • Loading branch information
bochaco committed Jul 7, 2022
1 parent 97a7ff2 commit e4ec6ce
Show file tree
Hide file tree
Showing 10 changed files with 85 additions and 89 deletions.
2 changes: 1 addition & 1 deletion examples/mint-repl/mint-repl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ fn main() -> Result<()> {
loop {
match rl.readline(">> ") {
Ok(line) => {
let mut args = line.trim().split_whitespace();
let mut args = line.split_whitespace();
let cmd = if let Some(cmd) = args.next() {
cmd
} else {
Expand Down
6 changes: 3 additions & 3 deletions src/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ use std::{
use crate::{
rand::{CryptoRng, RngCore},
AmountSecrets, Commitment, Dbc, DbcContent, Error, Hash, IndexedSignatureShare, KeyImage,
KeyManager, OwnerOnce, Result, SpentProof, SpentProofContent, SpentProofShare,
OwnerOnce, Result, SpentProof, SpentProofContent, SpentProofKeyVerifier, SpentProofShare,
TransactionVerifier,
};

Expand Down Expand Up @@ -400,7 +400,7 @@ impl DbcBuilder {
///
/// see TransactionVerifier::verify() for a description of
/// verifier requirements.
pub fn build<K: KeyManager>(
pub fn build<K: SpentProofKeyVerifier>(
self,
verifier: &K,
) -> Result<Vec<(Dbc, OwnerOnce, AmountSecrets)>> {
Expand All @@ -410,7 +410,7 @@ impl DbcBuilder {
// note that we do this just once for entire Tx, not once per output Dbc.
TransactionVerifier::verify(verifier, &self.transaction, &spent_proofs)?;

// verify there is a maching spent transaction for each spent_proof
// verify there is a matching spent transaction for each spent_proof
if !spent_proofs.iter().all(|proof| {
self.spent_transactions
.contains_key(&proof.transaction_hash())
Expand Down
12 changes: 8 additions & 4 deletions src/dbc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@
// permissions and limitations relating to use of the SAFE Network Software.

use crate::{
AmountSecrets, DbcContent, DerivationIndex, Error, Hash, KeyImage, KeyManager, Owner, Result,
SpentProof, TransactionVerifier,
AmountSecrets, DbcContent, DerivationIndex, Error, Hash, KeyImage, Owner, Result, SpentProof,
SpentProofKeyVerifier, TransactionVerifier,
};
use bls_ringct::{
group::Curve,
Expand Down Expand Up @@ -200,7 +200,11 @@ impl Dbc {
///
/// see comments for Dbc::verify_amount_matches_commitment() for a
/// description of how to handle Error::AmountCommitmentsDoNotMatch
pub fn verify<K: KeyManager>(&self, base_sk: &SecretKey, verifier: &K) -> Result<(), Error> {
pub fn verify<K: SpentProofKeyVerifier>(
&self,
base_sk: &SecretKey,
verifier: &K,
) -> Result<(), Error> {
TransactionVerifier::verify(verifier, &self.transaction, &self.spent_proofs)?;

let owner = self.owner_once(base_sk)?.public_key();
Expand Down Expand Up @@ -228,7 +232,7 @@ impl Dbc {

/// bearer version of verify()
/// will return an error if the SecretKey is not available. (not bearer)
pub fn verify_bearer<K: KeyManager>(&self, verifier: &K) -> Result<(), Error> {
pub fn verify_bearer<K: SpentProofKeyVerifier>(&self, verifier: &K) -> Result<(), Error> {
self.verify(&self.owner_base().secret_key()?, verifier)
}

Expand Down
59 changes: 0 additions & 59 deletions src/key_manager.rs

This file was deleted.

9 changes: 6 additions & 3 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ mod builder;
mod dbc;
mod dbc_content;
mod error;
mod key_manager;
mod mint;
mod owner;
mod spent_proof;
Expand All @@ -34,6 +33,8 @@ pub use blsttc;
// this knowingly and pledge to uphold that promise.
pub use bls_ringct::rand;

pub use blsttc::{PublicKey, PublicKeySet, Signature, SignatureShare};

pub use crate::{
amount_secrets::{Amount, AmountSecrets},
blst::{BlindingFactor, Commitment, KeyImage},
Expand All @@ -44,9 +45,11 @@ pub use crate::{
dbc::Dbc,
dbc_content::DbcContent,
error::{Error, Result},
key_manager::{IndexedSignatureShare, KeyManager, PublicKey, PublicKeySet, Signature},
owner::{DerivationIndex, Owner, OwnerOnce},
spent_proof::{SpentProof, SpentProofContent, SpentProofShare},
spent_proof::{
IndexedSignatureShare, SpentProof, SpentProofContent, SpentProofKeyVerifier,
SpentProofShare,
},
verification::TransactionVerifier,
};

Expand Down
2 changes: 1 addition & 1 deletion 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},
Amount, AmountSecrets, Dbc, KeyManager, Result, TransactionBuilder,
Amount, AmountSecrets, Dbc, Result, TransactionBuilder,
};
use blsttc::SecretKeySet;

Expand Down
26 changes: 16 additions & 10 deletions src/mock/key_manager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,38 +74,44 @@ impl From<Signer> for KeyManager {
}
}

impl crate::KeyManager for KeyManager {
impl crate::SpentProofKeyVerifier for KeyManager {
type Error = crate::Error;

fn add_known_key(&mut self, key: PublicKey) -> Result<()> {
fn verify(&self, msg_hash: &Hash, key: &PublicKey, signature: &Signature) -> Result<()> {
self.cache.verify(msg_hash, key, signature)
}
}

impl KeyManager {
pub fn add_known_key(&mut self, key: PublicKey) -> Result<()> {
self.cache.add_known_key(key);
Ok(())
}

fn public_key_set(&self) -> Result<PublicKeySet> {
pub fn public_key_set(&self) -> Result<PublicKeySet> {
Ok(self.signer.public_key_set())
}

fn sign_with_child_key(&self, index: &[u8], tx_hash: &Hash) -> Result<IndexedSignatureShare> {
pub fn sign_with_child_key(
&self,
index: &[u8],
tx_hash: &Hash,
) -> Result<IndexedSignatureShare> {
let child_signer = self.signer.derive_child(index);
Ok(IndexedSignatureShare::new(
child_signer.index(),
child_signer.sign(tx_hash),
))
}

fn sign(&self, msg_hash: &Hash) -> Result<IndexedSignatureShare> {
pub fn sign(&self, msg_hash: &Hash) -> Result<IndexedSignatureShare> {
Ok(IndexedSignatureShare::new(
self.signer.index(),
self.signer.sign(msg_hash),
))
}

fn verify(&self, msg_hash: &Hash, key: &PublicKey, signature: &Signature) -> Result<()> {
self.cache.verify(msg_hash, key, signature)
}

fn verify_known_key(&self, key: &PublicKey) -> Result<()> {
pub fn verify_known_key(&self, key: &PublicKey) -> Result<()> {
self.cache.verify_known_key(key)
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/mock/spentbook.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ use super::GenesisMaterial;
use crate::{
mock,
rand::{prelude::IteratorRandom, RngCore},
Commitment, Hash, KeyImage, KeyManager, Result, SpentProofContent, SpentProofShare,
Commitment, Hash, KeyImage, Result, SpentProofContent, SpentProofShare,
};

/// This is a mock SpentBook used for our test cases. A proper implementation
Expand Down
50 changes: 46 additions & 4 deletions src/spent_proof.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,7 @@
// permissions and limitations relating to use of the SAFE Network Software.

use crate::{
Commitment, Error, Hash, IndexedSignatureShare, KeyImage, KeyManager, PublicKey, PublicKeySet,
Result, Signature,
Commitment, Error, Hash, KeyImage, PublicKey, PublicKeySet, Result, Signature, SignatureShare,
};

use std::cmp::Ordering;
Expand Down Expand Up @@ -61,6 +60,32 @@ impl Ord for SpentProofContent {
}
}

#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, Clone, Hash, PartialEq, Eq)]
pub struct IndexedSignatureShare {
index: u64,
signature_share: SignatureShare,
}

impl IndexedSignatureShare {
pub fn new(index: u64, signature_share: SignatureShare) -> Self {
Self {
index,
signature_share,
}
}

pub fn threshold_crypto(&self) -> (u64, &SignatureShare) {
(self.index, &self.signature_share)
}

pub fn to_bytes(&self) -> Vec<u8> {
let mut bytes = self.index.to_le_bytes().to_vec();
bytes.extend(&self.signature_share.to_bytes());
bytes
}
}

/// A share of a SpentProof, combine enough of these to form a
/// SpentProof.
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
Expand Down Expand Up @@ -128,6 +153,19 @@ impl SpentProofShare {
}
}

/// For the spent proofs to verify, the caller must provide
/// an implementation of this trait which must have/know
/// the pubkey of the spentbook section that signed each of the proofs.
pub trait SpentProofKeyVerifier {
type Error: std::error::Error;
fn verify(
&self,
msg_hash: &Hash,
key: &PublicKey,
signature: &Signature,
) -> Result<(), Self::Error>;
}

/// SpentProof's are constructed when a DBC is logged to the spentbook.
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
Expand Down Expand Up @@ -177,13 +215,17 @@ impl SpentProof {
/// valid for this SpentProof.
///
/// note that the verifier must already hold (trust) the spentbook's public key.
pub fn verify<K: KeyManager>(&self, tx_hash: Hash, verifier: &K) -> Result<()> {
pub fn verify<K: SpentProofKeyVerifier>(
&self,
tx_hash: Hash,
proof_key_verifier: &K,
) -> Result<()> {
// verify input tx_hash matches our tx_hash which was signed by spentbook.
if tx_hash != self.content.transaction_hash {
return Err(Error::InvalidTransactionHash);
}

verifier
proof_key_verifier
.verify(
&self.content.hash(),
&self.spentbook_pub_key,
Expand Down
6 changes: 3 additions & 3 deletions src/verification.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 crate::{Commitment, Error, Hash, KeyImage, KeyManager, Result, SpentProof};
use crate::{Commitment, Error, Hash, KeyImage, Result, SpentProof, SpentProofKeyVerifier};
use bls_ringct::ringct::RingCtTransaction;
use std::collections::BTreeSet;

Expand All @@ -22,14 +22,14 @@ impl TransactionVerifier {
/// Verifies a transaction including spent proofs.
///
/// This function relies/assumes that the caller (wallet/client) obtains
/// the spentbook's public keys (held by KeyManager) in a
/// the spentbook's public keys (held by SpentProofKeyVerifier) in a
/// trustless/verified way. ie, the caller should not simply obtain keys
/// from a SpentBookNode directly, but must somehow verify that the node is
/// a valid authority.
///
/// note: for spent_proofs to verify, the verifier must have/know the
/// public key of each spentbook section that recorded a tx input as spent.
pub fn verify<K: KeyManager>(
pub fn verify<K: SpentProofKeyVerifier>(
verifier: &K,
transaction: &RingCtTransaction,
spent_proofs: &BTreeSet<SpentProof>,
Expand Down

0 comments on commit e4ec6ce

Please sign in to comment.