Skip to content

Commit

Permalink
feat(wallet_ffi): new ffi method to create covenant (#4115)
Browse files Browse the repository at this point in the history
Description
---
* Created a new FFI method to create a covenant object from bytes.
* Updated the C header with the definition of the new method

Motivation and Context
---
Currently the mobile apps cannot properly import faucet UTXOs, as they are passing null values for output features and covenants to the `wallet_import_external_utxo_as_non_rewindable` method, which is not allowed. So the mobile apps needs new FFI methods to create both output features and covenants. This pull request deals with covenants only.

How Has This Been Tested?
---
Created two new unit tests for the new FFI method
  • Loading branch information
mrnaveira authored and stringhandler committed May 20, 2022
1 parent cf3a1e6 commit 121149a
Show file tree
Hide file tree
Showing 2 changed files with 107 additions and 1 deletion.
97 changes: 96 additions & 1 deletion base_layer/wallet_ffi/src/lib.rs
Expand Up @@ -990,7 +990,63 @@ pub unsafe extern "C" fn commitment_signature_destroy(com_sig: *mut TariCommitme
}

/// -------------------------------------------------------------------------------------------- ///
/// --------------------------------------- Covenant --------------------------------------------///

/// Creates a TariCovenant from a ByteVector containing the covenant bytes
///
/// ## Arguments
/// `covenant_bytes` - The covenant bytes as a ByteVector
///
/// ## Returns
/// `TariCovenant` - Returns a commitment signature. Note that it will be ptr::null_mut() if any argument is
/// null or if there was an error with the contents of bytes
///
/// # Safety
/// The ```covenant_destroy``` function must be called when finished with a TariCovenant to prevent a memory leak
#[no_mangle]
pub unsafe extern "C" fn covenant_create_from_bytes(
covenant_bytes: *const ByteVector,
error_out: *mut c_int,
) -> *mut TariCovenant {
let mut error = 0;
ptr::swap(error_out, &mut error as *mut c_int);

if covenant_bytes.is_null() {
error = LibWalletError::from(InterfaceError::NullError("covenant_bytes".to_string())).code;
ptr::swap(error_out, &mut error as *mut c_int);
return ptr::null_mut();
}
let decoded_covenant_bytes = (*covenant_bytes).0.clone();

match TariCovenant::from_bytes(&decoded_covenant_bytes) {
Ok(covenant) => Box::into_raw(Box::new(covenant)),
Err(e) => {
error!(target: LOG_TARGET, "Error creating a Covenant: {:?}", e);
error = LibWalletError::from(InterfaceError::InvalidArgument("covenant_bytes".to_string())).code;
ptr::swap(error_out, &mut error as *mut c_int);
ptr::null_mut()
},
}
}

/// Frees memory for a TariCovenant
///
/// ## Arguments
/// `covenant` - The pointer to a TariCovenant
///
/// ## Returns
/// `()` - Does not return a value, equivalent to void in C
///
/// # Safety
/// None
#[no_mangle]
pub unsafe extern "C" fn covenant_destroy(covenant: *mut TariCovenant) {
if !covenant.is_null() {
Box::from_raw(covenant);
}
}

/// -------------------------------------------------------------------------------------------- ///
/// ---------------------------------- Output Features ------------------------------------------///

/// Creates a TariOutputFeatures from byte values
Expand Down Expand Up @@ -6585,7 +6641,10 @@ mod test {

use libc::{c_char, c_uchar, c_uint};
use tari_common_types::{emoji, transaction::TransactionStatus};
use tari_core::transactions::test_helpers::{create_unblinded_output, TestParams};
use tari_core::{
covenant,
transactions::test_helpers::{create_unblinded_output, TestParams},
};
use tari_key_manager::{mnemonic::MnemonicLanguage, mnemonic_wordlists};
use tari_test_utils::random;
use tari_wallet::{
Expand Down Expand Up @@ -7094,6 +7153,42 @@ mod test {
}
}

#[test]
fn test_covenant_create_empty() {
unsafe {
let mut error = 0;
let error_ptr = &mut error as *mut c_int;

let covenant_bytes = Box::into_raw(Box::new(ByteVector(Vec::new())));
let covenant = covenant_create_from_bytes(covenant_bytes, error_ptr);

assert_eq!(error, 0);
let empty_covenant = covenant!();
assert_eq!(*covenant, empty_covenant);

covenant_destroy(covenant);
byte_vector_destroy(covenant_bytes);
}
}

#[test]
fn test_covenant_create_filled() {
unsafe {
let mut error = 0;
let error_ptr = &mut error as *mut c_int;

let expected_covenant = covenant!(identity());
let covenant_bytes = Box::into_raw(Box::new(ByteVector(expected_covenant.to_bytes())));
let covenant = covenant_create_from_bytes(covenant_bytes, error_ptr);

assert_eq!(error, 0);
assert_eq!(*covenant, expected_covenant);

covenant_destroy(covenant);
byte_vector_destroy(covenant_bytes);
}
}

#[test]
fn test_output_features_create_empty() {
unsafe {
Expand Down
11 changes: 11 additions & 0 deletions base_layer/wallet_ffi/wallet.h
Expand Up @@ -189,6 +189,17 @@ struct TariCommitmentSignature *commitment_signature_create_from_bytes(
// Frees memory for a TariCommitmentSignature
void commitment_signature_destroy(struct TariCommitmentSignature *com_sig);

/// -------------------------------- Covenant --------------------------------------------- ///

// Creates a TariCovenant from a ByteVector containing the covenant bytes
struct TariCovenant *covenant_create_from_bytes(
struct ByteVector *covenant_bytes,
int *error_out
);

// Frees memory for a TariCovenant
void covenant_destroy(struct TariCovenant *covenant);

/// -------------------------------- Output Features --------------------------------------------- ///

// Creates a TariOutputFeatures from byte values
Expand Down

0 comments on commit 121149a

Please sign in to comment.