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 #6348

Closed
Closed
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 @@ -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
Loading