Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: commitment proofs #6463

Open
wants to merge 1 commit into
base: development
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 @@ -110,6 +110,12 @@ pub enum UniIdError {
Nonconvertible,
}

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

impl FromStr for UniNodeId {
type Err = UniIdError;

Expand Down
70 changes: 70 additions & 0 deletions applications/minotari_console_wallet/src/automation/commands.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1816,6 +1816,76 @@ pub async fn command_runner(
println!("Spend key: {}", spend_key_hex);
}
},
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 outputs match this commitment");
continue;
}
if count > 1 {
eprintln!("Multiple unspent outputs match this commitment");
continue;
}

// Try to generate the requested 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 {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this will only allow you to verify your own commitments

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you want to verify any output you probably need a new method that will get that from a base node

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 outputs match this commitment");
continue;
}
if count > 1 {
eprintln!("Multiple unspent outputs match this commitment");
continue;
}

// Try to verify the requested 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!("VerifyProof 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 @@ -149,6 +149,8 @@ pub enum CliCommands {
CreateTlsCerts,
Sync(SyncArgs),
ExportViewKeyAndSpendKey(ExportViewKeyAndSpendKeyArgs),
CreateCommitmentProof(CreateCommitmentProofArgs),
VerifyCommitmentProof(VerifyCommitmentProofArgs),
}

#[derive(Debug, Args, Clone)]
Expand Down Expand Up @@ -380,3 +382,18 @@ pub struct SyncArgs {
#[clap(short, long, default_value = "0")]
pub sync_to_height: u64,
}

#[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,
}
4 changes: 3 additions & 1 deletion applications/minotari_console_wallet/src/wallet_modes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -530,7 +530,7 @@ async fn run_grpc(
mod test {
use std::path::Path;

use crate::{cli::CliCommands, wallet_modes::parse_command_file};
use crate::{cli::CliCommands, wallet_modes::parse_command_file, Cli};

#[test]
#[allow(clippy::too_many_lines)]
Expand Down Expand Up @@ -640,6 +640,8 @@ mod test {
CliCommands::PreMineSpendBackupUtxo(_) => {},
CliCommands::Sync(_) => {},
CliCommands::ExportViewKeyAndSpendKey(_) => {},
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 @@ -55,6 +55,8 @@ prost = "0.11.9"
itertools = "0.10.3"
chacha20poly1305 = "0.10.1"
zeroize = "1"
tari_bulletproofs_plus = "0.4.0"
merlin = "3.0.0"

[build-dependencies]
tari_common = { path = "../../common", features = ["build", "static-application-info"], version = "1.1.0-pre.2" }
Expand Down
68 changes: 68 additions & 0 deletions base_layer/wallet/src/output_manager_service/handle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,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 @@ -247,6 +249,28 @@ impl fmt::Display for OutputManagerRequest {
),

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,
"VerifyCommitmentProof(commitment: {}, message: {}, minimum_value: {}, proof: (not shown))",
commitment.to_hex(),
message,
if let Some(minimum_value) = minimum_value {
*minimum_value
} else {
MicroMinotari::zero()
},
),
}
}
}
Expand Down Expand Up @@ -299,6 +323,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 @@ -911,4 +937,46 @@ impl OutputManagerHandle {
_ => Err(OutputManagerError::UnexpectedApiResponse),
}
}

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),
}
}
}
Loading
Loading