Skip to content

Commit

Permalink
Commitment proofs
Browse files Browse the repository at this point in the history
  • Loading branch information
AaronFeickert committed May 20, 2024
1 parent 1d6e0d8 commit 1530f1a
Show file tree
Hide file tree
Showing 9 changed files with 289 additions and 7 deletions.
2 changes: 2 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions applications/minotari_app_utilities/src/utilities.rs
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,12 @@ impl From<UniPublicKey> for PublicKey {
}
}

impl UniPublicKey {
pub fn as_public_key(&self) -> &PublicKey {
&self.0
}
}

#[derive(Debug)]
pub enum UniNodeId {
PublicKey(PublicKey),
Expand Down
68 changes: 68 additions & 0 deletions applications/minotari_console_wallet/src/automation/commands.rs
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,8 @@ pub enum WalletCommand {
MintTokens,
CreateInitialCheckpoint,
RevalidateWalletDb,
CreateCommitmentProof,
VerifyCommitmentProof,
}

#[derive(Debug)]
Expand Down Expand Up @@ -1049,6 +1051,72 @@ pub async fn command_runner(
},
Err(err) => eprintln!("Error generating certificates: {}", err),
},
CreateCommitmentProof(args) => match output_service.get_unspent_outputs().await {
Ok(utxos) => {
// Parse into outputs and commitments
let utxos: Vec<(WalletOutput, Commitment)> = utxos
.into_iter()
.map(|v| (v.wallet_output, v.commitment))
.filter(|(_, c)| c.as_public_key() == args.commitment.as_public_key())
.collect();

// Make sure we have a single unspent output corresponding to the requested commitment
let count = utxos.len();
if count == 0 {
eprintln!("No unspent UTXOs match this commitment");
continue;
}
if count > 1 {
eprintln!("Multiple unspent UTXOs match this commitment");
continue;
}

// Try to generate the commitment proof
match output_service
.create_commitment_proof(utxos[0].1.clone(), args.message, args.minimum_value)
.await
{
Ok(proof) => {
println!("Commitment proof: {}", proof.to_hex());
},
Err(e) => eprintln!("CreateCommitmentProof error! {}", e),
}
},
Err(e) => eprintln!("CreateCommitmentProof error! {}", e),
},
VerifyCommitmentProof(args) => match output_service.get_unspent_outputs().await {
Ok(utxos) => {
// Parse into outputs and commitments
let utxos: Vec<(WalletOutput, Commitment)> = utxos
.into_iter()
.map(|v| (v.wallet_output, v.commitment))
.filter(|(_, c)| c.as_public_key() == args.commitment.as_public_key())
.collect();

// Make sure we have a single unspent output corresponding to the requested commitment
let count = utxos.len();
if count == 0 {
eprintln!("No unspent UTXOs match this commitment");
continue;
}
if count > 1 {
eprintln!("Multiple unspent UTXOs match this commitment");
continue;
}

// Try to verify the commitment proof
match output_service
.verify_commitment_proof(utxos[0].1.clone(), args.message, args.minimum_value, args.proof)
.await
{
Ok(()) => {
println!("Commitment proof verified!");
},
Err(e) => eprintln!("VerifyCommitmentProof error! {}", e),
}
},
Err(e) => eprintln!("VerifyCommitmentProof error! {}", e),
},
}
}

Expand Down
17 changes: 17 additions & 0 deletions applications/minotari_console_wallet/src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,8 @@ pub enum CliCommands {
RevalidateWalletDb,
RegisterValidatorNode(RegisterValidatorNodeArgs),
CreateTlsCerts,
CreateCommitmentProof(CreateCommitmentProofArgs),
VerifyCommitmentProof(VerifyCommitmentProofArgs),
}

#[derive(Debug, Args, Clone)]
Expand Down Expand Up @@ -305,3 +307,18 @@ pub struct RegisterValidatorNodeArgs {
#[clap(short, long, default_value = "Registering VN")]
pub message: String,
}

#[derive(Debug, Args, Clone)]
pub struct CreateCommitmentProofArgs {
pub commitment: UniPublicKey,
pub message: String,
pub minimum_value: Option<MicroMinotari>,
}

#[derive(Debug, Args, Clone)]
pub struct VerifyCommitmentProofArgs {
pub commitment: UniPublicKey,
pub message: String,
pub minimum_value: Option<MicroMinotari>,
pub proof: String,
}
2 changes: 2 additions & 0 deletions applications/minotari_console_wallet/src/wallet_modes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -552,6 +552,8 @@ mod test {
CliCommands::RevalidateWalletDb => {},
CliCommands::RegisterValidatorNode(_) => {},
CliCommands::CreateTlsCerts => {},
CliCommands::CreateCommitmentProof(_) => {},
CliCommands::VerifyCommitmentProof(_) => {},
}
}
assert!(
Expand Down
2 changes: 2 additions & 0 deletions base_layer/wallet/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ argon2 = "0.4.1"
bincode = "1.3.1"
blake2 = "0.10"
borsh = "1.2"
tari_bulletproofs_plus = "0.4"
sha2 = "0.10"
chrono = { version = "0.4.19", default-features = false, features = ["serde"] }
derivative = "2.2.0"
Expand All @@ -43,6 +44,7 @@ fs2 = "0.4.0"
futures = { version = "^0.3.1", features = ["compat", "std"] }
libsqlite3-sys = { version = "0.25.1", features = ["bundled"], optional = true }
log = "0.4.6"
merlin = "3"
rand = "0.8"
serde = { version = "1.0.89", features = ["derive"] }
serde_json = "1.0.39"
Expand Down
69 changes: 68 additions & 1 deletion base_layer/wallet/src/output_manager_service/handle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,8 @@ pub enum OutputManagerRequest {
CreateClaimShaAtomicSwapTransaction(HashOutput, PublicKey, MicroMinotari),
CreateHtlcRefundTransaction(HashOutput, MicroMinotari),
GetOutputInfoByTxId(TxId),
CreateCommitmentProof(Commitment, String, Option<MicroMinotari>),
VerifyCommitmentProof(Commitment, String, Option<MicroMinotari>, String),
}

impl fmt::Display for OutputManagerRequest {
Expand Down Expand Up @@ -200,8 +202,29 @@ impl fmt::Display for OutputManagerRequest {
"CreateHtlcRefundTransaction(output hash: {}, , fee_per_gram: {} )",
output, fee_per_gram,
),

GetOutputInfoByTxId(t) => write!(f, "GetOutputInfoByTxId: {}", t),
CreateCommitmentProof(commitment, message, minimum_value) => write!(
f,
"CreateCommitmentProof(commitment: {}, message: {}, minimum_value: {})",
commitment.to_hex(),
message,
if let Some(minimum_value) = minimum_value {
*minimum_value
} else {
MicroMinotari::zero()
},
),
VerifyCommitmentProof(commitment, message, minimum_value, _) => write!(
f,
"CreateCommitmentProof(commitment: {}, message: {}, minimum_value: {})",
commitment.to_hex(),
message,
if let Some(minimum_value) = minimum_value {
*minimum_value
} else {
MicroMinotari::zero()
},
),
}
}
}
Expand Down Expand Up @@ -238,6 +261,8 @@ pub enum OutputManagerResponse {
ClaimHtlcTransaction((TxId, MicroMinotari, MicroMinotari, Transaction)),
OutputInfoByTxId(OutputInfoByTxId),
CoinPreview((Vec<MicroMinotari>, MicroMinotari)),
CommitmentProofCreated(Vec<u8>),
CommitmentProofVerified,
}

pub type OutputManagerEventSender = broadcast::Sender<Arc<OutputManagerEvent>>;
Expand Down Expand Up @@ -391,6 +416,48 @@ impl OutputManagerHandle {
}
}

pub async fn create_commitment_proof(
&mut self,
commitment: Commitment,
message: String,
minimum_value: Option<MicroMinotari>,
) -> Result<Vec<u8>, OutputManagerError> {
match self
.handle
.call(OutputManagerRequest::CreateCommitmentProof(
commitment,
message,
minimum_value,
))
.await??
{
OutputManagerResponse::CommitmentProofCreated(bytes) => Ok(bytes),
_ => Err(OutputManagerError::UnexpectedApiResponse),
}
}

pub async fn verify_commitment_proof(
&mut self,
commitment: Commitment,
message: String,
minimum_value: Option<MicroMinotari>,
proof: String,
) -> Result<(), OutputManagerError> {
match self
.handle
.call(OutputManagerRequest::VerifyCommitmentProof(
commitment,
message,
minimum_value,
proof,
))
.await??
{
OutputManagerResponse::CommitmentProofVerified => Ok(()),
_ => Err(OutputManagerError::UnexpectedApiResponse),
}
}

pub async fn get_balance(&mut self) -> Result<Balance, OutputManagerError> {
match self.handle.call(OutputManagerRequest::GetBalance).await?? {
OutputManagerResponse::Balance(b) => Ok(b),
Expand Down
4 changes: 2 additions & 2 deletions base_layer/wallet/src/output_manager_service/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ use futures::future;
use log::*;
use tari_core::{
consensus::NetworkConsensus,
transactions::{key_manager::TransactionKeyManagerInterface, CryptoFactories},
transactions::{key_manager::SecretTransactionKeyManagerInterface, CryptoFactories},
};
use tari_service_framework::{
async_trait,
Expand Down Expand Up @@ -103,7 +103,7 @@ where T: OutputManagerBackend + 'static
impl<T, TKeyManagerInterface> ServiceInitializer for OutputManagerServiceInitializer<T, TKeyManagerInterface>
where
T: OutputManagerBackend + 'static,
TKeyManagerInterface: TransactionKeyManagerInterface,
TKeyManagerInterface: SecretTransactionKeyManagerInterface,
{
async fn initialize(&mut self, context: ServiceInitializerContext) -> Result<(), ServiceInitializationError> {
let (sender, receiver) = reply_channel::unbounded();
Expand Down
Loading

0 comments on commit 1530f1a

Please sign in to comment.