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: add more burn details to burn command #5169

Merged
4 changes: 4 additions & 0 deletions applications/tari_app_grpc/proto/wallet.proto
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ message CreateBurnTransactionRequest{
uint64 amount = 1;
uint64 fee_per_gram = 2;
string message = 3;
bytes claim_public_key = 4;
}


Expand Down Expand Up @@ -137,6 +138,9 @@ message CreateBurnTransactionResponse{
uint64 transaction_id = 1;
bool is_success = 2;
string failure_message = 3;
bytes commitment = 4;
bytes ownership_proof = 5;
bytes rangeproof = 6;
}

message TransferResult {
Expand Down
9 changes: 8 additions & 1 deletion applications/tari_console_wallet/src/automation/commands.rs
Original file line number Diff line number Diff line change
Expand Up @@ -136,9 +136,16 @@ pub async fn burn_tari(
message: String,
) -> Result<TxId, CommandError> {
wallet_transaction_service
.burn_tari(amount, UtxoSelectionCriteria::default(), fee_per_gram * uT, message)
.burn_tari(
amount,
UtxoSelectionCriteria::default(),
fee_per_gram * uT,
message,
None,
)
.await
.map_err(CommandError::TransactionServiceError)
.map(|res| res.0)
}

/// publishes a tari-SHA atomic swap HTLC transaction
Expand Down
15 changes: 13 additions & 2 deletions applications/tari_console_wallet/src/grpc/wallet_grpc_server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -595,23 +595,34 @@ impl wallet_server::Wallet for WalletGrpcServer {
UtxoSelectionCriteria::default(),
message.fee_per_gram.into(),
message.message,
if message.claim_public_key.is_empty() {
None
} else {
Some(
PublicKey::from_bytes(&message.claim_public_key)
.map_err(|e| Status::invalid_argument(e.to_string()))?,
)
},
)
.await
{
Ok(tx_id) => {
Ok((tx_id, commitment, ownership_proof, rangeproof)) => {
debug!(target: LOG_TARGET, "Transaction broadcast: {}", tx_id,);
CreateBurnTransactionResponse {
transaction_id: tx_id.as_u64(),
is_success: true,
failure_message: Default::default(),
commitment: commitment.to_vec(),
ownership_proof: ownership_proof.map(|o| o.to_vec()).unwrap_or(vec![]),
rangeproof: rangeproof.to_vec(),
}
},
Err(e) => {
warn!(target: LOG_TARGET, "Failed to burn Tarid: {}", e);
CreateBurnTransactionResponse {
transaction_id: Default::default(),
is_success: false,
failure_message: e.to_string(),
..Default::default()
}
},
};
Expand Down
3 changes: 3 additions & 0 deletions base_layer/wallet/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,9 @@ pub type WalletSqlite = Wallet<
KeyManagerSqliteDatabase,
>;

hash_domain!(BurntOutputDomain, "burnt_output", 1);
type BurntOutputDomainHasher = DomainSeparatedHasher<Blake256, BurntOutputDomain>;

hash_domain!(
WalletOutputRewindKeysDomain,
"com.tari.tari_project.base_layer.wallet.output_rewind_keys",
Expand Down
3 changes: 3 additions & 0 deletions base_layer/wallet/src/transaction_service/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ use tari_core::transactions::{
transaction_components::{EncryptionError, TransactionError},
transaction_protocol::TransactionProtocolError,
};
use tari_crypto::signatures::CommitmentSignatureError;
use tari_p2p::services::liveness::error::LivenessError;
use tari_service_framework::reply_channel::TransportChannelError;
use tari_utilities::ByteArrayError;
Expand Down Expand Up @@ -178,6 +179,8 @@ pub enum TransactionServiceError {
EncryptionError(#[from] EncryptionError),
#[error("FixedHash size error: `{0}`")]
FixedHashSizeError(#[from] FixedHashSizeError),
#[error("Commitment signature error: {0}")]
CommitmentSignatureError(#[from] CommitmentSignatureError),
}

#[derive(Debug, Error)]
Expand Down
21 changes: 18 additions & 3 deletions base_layer/wallet/src/transaction_service/handle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ use chrono::NaiveDateTime;
use tari_common_types::{
tari_address::TariAddress,
transaction::{ImportStatus, TxId},
types::{PublicKey, Signature},
types::{BulletRangeProof, Commitment, PublicKey, Signature},
};
use tari_comms::types::CommsPublicKey;
use tari_core::{
Expand All @@ -42,6 +42,7 @@ use tari_core::{
transaction_components::{OutputFeatures, Transaction, TransactionOutput},
},
};
use tari_crypto::ristretto::RistrettoComSig;
use tari_service_framework::reply_channel::SenderService;
use tokio::sync::broadcast;
use tower::Service;
Expand Down Expand Up @@ -86,6 +87,7 @@ pub enum TransactionServiceRequest {
selection_criteria: UtxoSelectionCriteria,
fee_per_gram: MicroTari,
message: String,
claim_public_key: Option<PublicKey>,
},
RegisterValidatorNode {
amount: MicroTari,
Expand Down Expand Up @@ -235,6 +237,12 @@ impl fmt::Display for TransactionServiceRequest {
#[derive(Debug)]
pub enum TransactionServiceResponse {
TransactionSent(TxId),
BurntTransactionSent {
tx_id: TxId,
commitment: Commitment,
ownership_proof: Option<RistrettoComSig>,
rangeproof: BulletRangeProof,
},
TransactionCancelled,
PendingInboundTransactions(HashMap<TxId, InboundTransaction>),
PendingOutboundTransactions(HashMap<TxId, OutboundTransaction>),
Expand Down Expand Up @@ -519,18 +527,25 @@ impl TransactionServiceHandle {
selection_criteria: UtxoSelectionCriteria,
fee_per_gram: MicroTari,
message: String,
) -> Result<TxId, TransactionServiceError> {
claim_public_key: Option<PublicKey>,
) -> Result<(TxId, Commitment, Option<RistrettoComSig>, BulletRangeProof), TransactionServiceError> {
match self
.handle
.call(TransactionServiceRequest::BurnTari {
amount,
selection_criteria,
fee_per_gram,
message,
claim_public_key,
})
.await??
{
TransactionServiceResponse::TransactionSent(tx_id) => Ok(tx_id),
TransactionServiceResponse::BurntTransactionSent {
tx_id,
commitment,
ownership_proof,
rangeproof,
} => Ok((tx_id, commitment, ownership_proof, rangeproof)),
_ => Err(TransactionServiceError::UnexpectedApiResponse),
}
}
Expand Down
71 changes: 61 additions & 10 deletions base_layer/wallet/src/transaction_service/service.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ use sha2::Sha256;
use tari_common_types::{
tari_address::TariAddress,
transaction::{ImportStatus, TransactionDirection, TransactionStatus, TxId},
types::{PrivateKey, PublicKey, Signature},
types::{Commitment, FixedHash, PrivateKey, PublicKey, RangeProof, Signature},
};
use tari_comms::types::{CommsDHKE, CommsPublicKey};
use tari_comms_dht::outbound::OutboundMessageRequester;
Expand Down Expand Up @@ -69,12 +69,14 @@ use tari_core::{
use tari_crypto::{
commitment::HomomorphicCommitmentFactory,
keys::{PublicKey as PKtrait, SecretKey},
ristretto::RistrettoComSig,
tari_utilities::{ByteArray, ByteArrayError},
};
use tari_p2p::domain_message::DomainMessage;
use tari_script::{inputs, script, TariScript};
use tari_service_framework::{reply_channel, reply_channel::Receiver};
use tari_shutdown::ShutdownSignal;
use tari_utilities::hex::Hex;
use tokio::{
sync::{mpsc, mpsc::Sender, oneshot, Mutex},
task::JoinHandle,
Expand Down Expand Up @@ -120,6 +122,7 @@ use crate::{
types::WalletHasher,
util::{wallet_identity::WalletIdentity, watch::Watch},
utxo_scanner_service::RECOVERY_KEY,
BurntOutputDomainHasher,
OperationId,
WalletOutputEncryptionKeysDomainHasher,
WalletOutputRewindKeysDomainHasher,
Expand Down Expand Up @@ -642,16 +645,25 @@ where
selection_criteria,
fee_per_gram,
message,
claim_public_key,
} => self
.burn_tari(
amount,
selection_criteria,
fee_per_gram,
message,
claim_public_key,
transaction_broadcast_join_handles,
)
.await
.map(TransactionServiceResponse::TransactionSent),
.map(|(tx_id, commitment, ownership_proof, rangeproof)| {
TransactionServiceResponse::BurntTransactionSent {
tx_id,
commitment,
ownership_proof,
rangeproof,
}
}),
TransactionServiceRequest::RegisterValidatorNode {
amount,
validator_node_public_key,
Expand Down Expand Up @@ -1356,20 +1368,23 @@ where
.await
}

/// Creates a transaction to burn some Tari
/// # Arguments
/// 'amount': The amount of Tari to send to the recipient
/// 'fee_per_gram': The amount of fee per transaction gram to be included in transaction
/// Creates a transaction to burn some Tari. The optional _claim public key_ parameter is used in the challenge of
/// the
// corresponding optional _ownership proof_ return value. Burn commitments and ownership proofs will exclusively be
// used in the 2nd layer (DAN layer). When such an _ownership proof_ is presented later on as part of some
// transaction metadata, the _claim public key_ can be revealed to enable verification of the _ownership proof_
// and the transaction can be signed with the private key corresponding to the claim public key.
pub async fn burn_tari(
&mut self,
amount: MicroTari,
selection_criteria: UtxoSelectionCriteria,
fee_per_gram: MicroTari,
message: String,
claim_public_key: Option<PublicKey>,
transaction_broadcast_join_handles: &mut FuturesUnordered<
JoinHandle<Result<TxId, TransactionServiceProtocolError<TxId>>>,
>,
) -> Result<TxId, TransactionServiceError> {
) -> Result<(TxId, Commitment, Option<RistrettoComSig>, RangeProof), TransactionServiceError> {
let tx_id = TxId::new_random();
let output_features = OutputFeatures::create_burn_output();
// Prepare sender part of the transaction
Expand Down Expand Up @@ -1401,16 +1416,52 @@ where
.await
.map_err(|e| TransactionServiceProtocolError::new(tx_id, e.into()))?;
let sender_message = TransactionSenderMessage::new_single_round_message(stp.get_single_round_message()?);
// TODO: Save spending key in key manager
let spend_key = PrivateKey::random(&mut OsRng);
let rtp = ReceiverTransactionProtocol::new(
sender_message,
PrivateKey::random(&mut OsRng),
spend_key,
spend_key.clone(),
&self.resources.factories,
);

let recipient_reply = rtp.get_signed_data()?.clone();

let commitment = recipient_reply.output.commitment.clone();
let range_proof = recipient_reply.output.proof.clone();
let (nonce_a, _pub_nonce_a) = PublicKey::random_keypair(&mut OsRng);
sdbondi marked this conversation as resolved.
Show resolved Hide resolved
let (nonce_x, _pub_nonce_x) = PublicKey::random_keypair(&mut OsRng);
let pub_nonce = self.resources.factories.commitment.commit(&nonce_x, &nonce_a);
let mut ownership_proof = None;

if let Some(claim_public_key) = claim_public_key {
let hasher = BurntOutputDomainHasher::new_with_label("commitment_signature")
.chain(pub_nonce.as_bytes())
.chain(commitment.as_bytes())
.chain(claim_public_key.as_bytes());

let challenge: FixedHash = digest::Digest::finalize(hasher).into();

warn!(target: LOG_TARGET, "Pub nonce: {}", pub_nonce.to_vec().to_hex());
warn!(
target: LOG_TARGET,
"claim_public_key: {}",
claim_public_key.to_vec().to_hex()
);
warn!(target: LOG_TARGET, "Challenge: {}", challenge.to_vec().to_hex());
ownership_proof = Some(RistrettoComSig::sign(
&PrivateKey::from(amount),
&spend_key,
&nonce_a,
&nonce_x,
challenge.as_bytes(),
&*self.resources.factories.commitment,
)?);
warn!(
target: LOG_TARGET,
"Ownership proof: {}",
ownership_proof.clone().unwrap().to_vec().to_hex()
);
}
// Start finalizing

stp.add_single_recipient_info(recipient_reply)
Expand Down Expand Up @@ -1460,7 +1511,7 @@ where
),
)?;

Ok(tx_id)
Ok((tx_id, commitment, ownership_proof, range_proof))
}

pub async fn register_validator_node(
Expand Down
2 changes: 1 addition & 1 deletion comms/dht/src/store_forward/store.rs
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,7 @@ where S: Service<DecryptedDhtMessage, Response = (), Error = PipelineError> + Se
);

let service = self.next_service.ready_oneshot().await?;
return service.oneshot(message).await;
service.oneshot(message).await
}

async fn get_storage_priority(&self, message: &DecryptedDhtMessage) -> SafResult<Option<StoredMessagePriority>> {
Expand Down