Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 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
5 changes: 3 additions & 2 deletions applications/minotari_app_grpc/proto/wallet.proto
Original file line number Diff line number Diff line change
Expand Up @@ -1066,7 +1066,7 @@ message PaymentRecipient {
// The type of payment to perform.
PaymentType payment_type = 5;
// Optional encrypted payment ID for reference (max 256 bytes).
bytes payment_id = 6;
UserPaymentId user_payment_id = 7;
}

message TransferResponse {
Expand Down Expand Up @@ -1136,8 +1136,9 @@ message TransactionInfo {
bool is_cancelled = 8;
bytes excess_sig = 9;
uint64 timestamp = 10;
bytes payment_id = 12;
bytes raw_payment_id = 12;
uint64 mined_in_block_height = 13;
bytes user_payment_id = 14;
}

enum TransactionDirection {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -489,15 +489,36 @@ impl wallet_server::Wallet for WalletGrpcServer {
.ok_or_else(|| Status::internal("Request is malformed".to_string()))?;
let address = TariAddress::from_str(&message.address)
.map_err(|_| Status::internal("Destination address is malformed".to_string()))?;

let payment_id = if let Some(user_pay_id) = message.user_payment_id {
let bytes = match (
user_pay_id.u256.is_empty(),
user_pay_id.utf8_string.is_empty(),
user_pay_id.user_bytes.is_empty(),
) {
(false, true, true) => user_pay_id.u256,
(true, false, true) => user_pay_id.utf8_string.as_bytes().to_vec(),
(true, true, false) => user_pay_id.user_bytes,
_ => {
return Err(Status::invalid_argument(
"user_payment_id must be one of u256, utf8_string or user_bytes".to_string(),
));
},
};
PaymentId::Open {
user_data: bytes,
tx_type: TxType::ClaimAtomicSwap,
}
} else {
PaymentId::Empty
};
let mut transaction_service = self.get_transaction_service();
let response = match transaction_service
.send_sha_atomic_swap_transaction(
address.clone(),
message.amount.into(),
UtxoSelectionCriteria::default(),
message.fee_per_gram.into(),
PaymentId::from_bytes(&message.payment_id),
payment_id,
)
.await
{
Expand Down Expand Up @@ -664,15 +685,36 @@ impl wallet_server::Wallet for WalletGrpcServer {
dest.amount,
dest.fee_per_gram,
dest.payment_type,
dest.payment_id,
dest.user_payment_id,
))
})
.collect::<Result<Vec<_>, _>>()
.map_err(Status::invalid_argument)?;

let mut transfers = Vec::new();
for (hex_address, address, amount, fee_per_gram, payment_type, payment_id) in recipients {
let payment_id = PaymentId::from_bytes(&payment_id);
for (hex_address, address, amount, fee_per_gram, payment_type, user_payment_id) in recipients {
let payment_id = if let Some(user_pay_id) = user_payment_id {
let bytes = match (
user_pay_id.u256.is_empty(),
user_pay_id.utf8_string.is_empty(),
user_pay_id.user_bytes.is_empty(),
) {
(false, true, true) => user_pay_id.u256,
(true, false, true) => user_pay_id.utf8_string.as_bytes().to_vec(),
(true, true, false) => user_pay_id.user_bytes,
_ => {
return Err(Status::invalid_argument(
"user_payment_id must be one of u256, utf8_string or user_bytes".to_string(),
));
},
};
PaymentId::Open {
user_data: bytes,
tx_type: TxType::ClaimAtomicSwap,
}
} else {
PaymentId::Empty
};
let mut transaction_service = self.get_transaction_service();
transfers.push(async move {
(
Expand Down Expand Up @@ -971,7 +1013,8 @@ impl wallet_server::Wallet for WalletGrpcServer {
.unwrap_or(&Signature::default())
.get_signature()
.to_vec(),
payment_id: txn.payment_id.to_bytes(),
raw_payment_id: txn.payment_id.to_bytes(),
user_payment_id: txn.payment_id.user_data_as_bytes(),
mined_in_block_height: txn.mined_height.unwrap_or(0),
}),
};
Expand Down Expand Up @@ -1321,7 +1364,8 @@ fn convert_wallet_transaction_into_transaction_info(
fee: 0,
excess_sig: Default::default(),
timestamp: tx.timestamp.timestamp() as u64,
payment_id: tx.payment_id.to_bytes(),
raw_payment_id: tx.payment_id.to_bytes(),
user_payment_id: tx.payment_id.user_data_as_bytes(),
mined_in_block_height: 0,
},
PendingOutbound(tx) => TransactionInfo {
Expand All @@ -1335,7 +1379,8 @@ fn convert_wallet_transaction_into_transaction_info(
fee: tx.fee.into(),
excess_sig: Default::default(),
timestamp: tx.timestamp.timestamp() as u64,
payment_id: tx.payment_id.to_bytes(),
raw_payment_id: tx.payment_id.to_bytes(),
user_payment_id: tx.payment_id.user_data_as_bytes(),
mined_in_block_height: 0,
},
Completed(tx) => TransactionInfo {
Expand All @@ -1353,7 +1398,8 @@ fn convert_wallet_transaction_into_transaction_info(
.first_kernel_excess_sig()
.map(|s| s.get_signature().to_vec())
.unwrap_or_default(),
payment_id: tx.payment_id.to_bytes(),
raw_payment_id: tx.payment_id.to_bytes(),
user_payment_id: tx.payment_id.user_data_as_bytes(),
mined_in_block_height: tx.mined_height.unwrap_or(0),
},
}
Expand Down
2 changes: 1 addition & 1 deletion base_layer/wallet/src/base_node_service/service.rs
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ where T: WalletBackend + 'static
&mut self,
request: BaseNodeServiceRequest,
) -> Result<BaseNodeServiceResponse, BaseNodeServiceError> {
debug!(
trace!(
target: LOG_TARGET,
"Handling Wallet Base Node Service Request: {:?}", request
);
Expand Down
4 changes: 2 additions & 2 deletions base_layer/wallet/src/connectivity_service/service.rs
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,7 @@ impl WalletConnectivityService {
match self.pools.get(&node_id) {
Some(pools) => match pools.base_node_wallet_rpc_client.get().await {
Ok(client) => {
debug!(target: LOG_TARGET, "Obtained pool RPC 'wallet' connection to base node '{}'", node_id);
trace!(target: LOG_TARGET, "Obtained pool RPC 'wallet' connection to base node '{}'", node_id);
let _result = reply.send(client);
},
Err(e) => {
Expand Down Expand Up @@ -247,7 +247,7 @@ impl WalletConnectivityService {
match self.pools.get(&node_id) {
Some(pools) => match pools.base_node_sync_rpc_client.get().await {
Ok(client) => {
debug!(target: LOG_TARGET, "Obtained pool RPC 'sync' connection to base node '{}'", node_id);
trace!(target: LOG_TARGET, "Obtained pool RPC 'sync' connection to base node '{}'", node_id);
let _result = reply.send(client);
},
Err(e) => {
Expand Down
12 changes: 8 additions & 4 deletions base_layer/wallet/src/transaction_service/service.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1142,6 +1142,7 @@ where
>,
reply_channel: oneshot::Sender<Result<TransactionServiceResponse, TransactionServiceError>>,
) -> Result<(), TransactionServiceError> {
debug!(target: LOG_TARGET, "Sending transaction to {} with {}", destination, amount);
let tx_id = TxId::new_random();
if let Err(e) = self.verify_send(&destination, TariAddressFeatures::create_interactive_only()) {
let err = match e {
Expand All @@ -1159,6 +1160,11 @@ where
});
return Err(e);
}
// let override the payment_id if the address says we should
if destination.features().contains(TariAddressFeatures::PAYMENT_ID) {
debug!(target: LOG_TARGET, "Address contains memo, overriding memo {} with {:?}", payment_id, destination.get_payment_id_user_data_bytes());
payment_id = PaymentId::open(destination.get_payment_id_user_data_bytes(), TxType::PaymentToOther);
}
// If we're paying ourselves, let's complete and submit the transaction immediately
if &self
.resources
Expand Down Expand Up @@ -1219,10 +1225,6 @@ where

return Ok(());
}
// let override the payment_id if the address says we should
if destination.features().contains(TariAddressFeatures::PAYMENT_ID) {
payment_id = PaymentId::open(destination.get_payment_id_user_data_bytes(), TxType::PaymentToOther);
}
let (tx_reply_sender, tx_reply_receiver) = mpsc::channel(100);
let (cancellation_sender, cancellation_receiver) = oneshot::channel();
self.pending_transaction_reply_senders.insert(tx_id, tx_reply_sender);
Expand Down Expand Up @@ -1773,9 +1775,11 @@ where
recipient_script: Option<TariScript>,
mut payment_id: PaymentId,
) -> Result<TxId, TransactionServiceError> {
debug!(target: LOG_TARGET, "Sending one sided transaction to {} with {}", dest_address, amount);
let tx_id = TxId::new_random();
// let override the payment_id if the address says we should
if dest_address.features().contains(TariAddressFeatures::PAYMENT_ID) {
debug!(target: LOG_TARGET, "Address contains memo, overriding memo {} with {:?}", payment_id, dest_address.get_payment_id_user_data_bytes());
payment_id = PaymentId::open(dest_address.get_payment_id_user_data_bytes(), TxType::PaymentToOther);
}
let payment_id = match payment_id.clone() {
Expand Down
51 changes: 46 additions & 5 deletions base_layer/wallet_ffi/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -318,7 +318,8 @@ pub struct TariUtxo {
pub lock_height: u64,
pub status: u8,
pub coinbase_extra: *const c_char,
pub payment_id: *const c_char,
pub raw_payment_id: *const c_char,
pub user_payment_id: *const c_char,
pub mined_in_block: *const c_char,
}

Expand Down Expand Up @@ -351,7 +352,10 @@ impl From<DbWalletOutput> for TariUtxo {
coinbase_extra: CString::new(x.wallet_output.features.coinbase_extra.to_hex())
.expect("failed to obtain hex from a commitment")
.into_raw(),
payment_id: CString::new(format!("{}", x.payment_id))
raw_payment_id: CString::new(format!("{}", x.payment_id))
.expect("failed to obtain string from a payment id")
.into_raw(),
user_payment_id: CString::new(format!("{}", x.payment_id.user_data_as_string()))
.expect("failed to obtain string from a payment id")
.into_raw(),
mined_in_block: CString::new(x.mined_in_block.unwrap_or_default().to_hex())
Expand Down Expand Up @@ -868,7 +872,44 @@ pub unsafe extern "C" fn tari_utxo_get_coinbase_extra(utxo: *const TariUtxo, err
CString::into_raw(result)
}

/// Get the payment id from a TariUtxo
/// Get the raw payment id from a TariUtxo
///
/// ## Arguments
/// `utxo` - The pointer to a TariUtxo.
/// `error_out` - Pointer to an int which will be modified to an error code should one occur, may not be null. Functions
/// as an out parameter. Returns a null pointer if any pointer argument is null.
///
/// ## Returns
/// `*mut c_char` - Returns a pointer to a char array (that contains the payment id). Note that it returns empty if
/// there was an error
///
/// # Safety
/// The ```string_destroy``` method must be called when finished with a string from rust to prevent a memory leak
#[no_mangle]
pub unsafe extern "C" fn tari_utxo_get_raw_payment_id(utxo: *const TariUtxo, error_out: *mut c_int) -> *mut c_char {
if error_out.is_null() {
return ptr::null_mut();
}
*error_out = 0;

let result = CString::new("").expect("Blank CString will not fail.");
if utxo.is_null() {
*error_out = LibWalletError::from(InterfaceError::NullError("utxo".to_string())).code;
return ptr::null_mut();
}

let payment_id_str = match CStr::from_ptr((*utxo).raw_payment_id).to_str() {
Ok(s) => s,
Err(_) => {
*error_out = LibWalletError::from(InterfaceError::PointerError("payment_id".to_string())).code;
return CString::into_raw(result);
},
};
let result = CString::new(payment_id_str).expect("Commitment will not fail.");
CString::into_raw(result)
}

/// Get the user payment id from a TariUtxo
///
/// ## Arguments
/// `utxo` - The pointer to a TariUtxo.
Expand All @@ -882,7 +923,7 @@ pub unsafe extern "C" fn tari_utxo_get_coinbase_extra(utxo: *const TariUtxo, err
/// # Safety
/// The ```string_destroy``` method must be called when finished with a string from rust to prevent a memory leak
#[no_mangle]
pub unsafe extern "C" fn tari_utxo_get_payment_id(utxo: *const TariUtxo, error_out: *mut c_int) -> *mut c_char {
pub unsafe extern "C" fn tari_utxo_get_user_payment_id(utxo: *const TariUtxo, error_out: *mut c_int) -> *mut c_char {
if error_out.is_null() {
return ptr::null_mut();
}
Expand All @@ -894,7 +935,7 @@ pub unsafe extern "C" fn tari_utxo_get_payment_id(utxo: *const TariUtxo, error_o
return ptr::null_mut();
}

let payment_id_str = match CStr::from_ptr((*utxo).payment_id).to_str() {
let payment_id_str = match CStr::from_ptr((*utxo).user_payment_id).to_str() {
Ok(s) => s,
Err(_) => {
*error_out = LibWalletError::from(InterfaceError::PointerError("payment_id".to_string())).code;
Expand Down
Loading