diff --git a/.circleci/config.yml b/.circleci/config.yml index 495b0cd298..648e49ede2 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -128,11 +128,7 @@ commands: name: Generate report command: cd integration_tests && node ./generate_report.js when: always - #- run: - # name: Set the correct Node version for wallet FFI tests - # shell: bash -l {0} - # command: nvm install v12.22.6 && nvm use v12.22.6 && cd integration_tests && npm install - # when: always + # Below step requires NodeJS v12 to run correctly, see explanation in WalletFFI.feature - run: name: Run FFI wallet library cucumber scenarios command: cd integration_tests && mkdir -p cucumber_output && node_modules/.bin/cucumber-js --tags "not @long-running and not @broken and not @flaky and @wallet-ffi" --format json:cucumber_output/tests_ffi.cucumber --exit diff --git a/Cargo.lock b/Cargo.lock index ce89dfad41..5d6526d9ec 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4853,7 +4853,7 @@ dependencies = [ [[package]] name = "tari_wallet_ffi" -version = "0.17.5" +version = "0.17.6" dependencies = [ "chrono", "env_logger 0.7.1", diff --git a/base_layer/wallet_ffi/Cargo.toml b/base_layer/wallet_ffi/Cargo.toml index ee284c158f..a49a3e923c 100644 --- a/base_layer/wallet_ffi/Cargo.toml +++ b/base_layer/wallet_ffi/Cargo.toml @@ -3,7 +3,7 @@ name = "tari_wallet_ffi" authors = ["The Tari Development Community"] description = "Tari cryptocurrency wallet C FFI bindings" license = "BSD-3-Clause" -version = "0.17.5" +version = "0.17.6" edition = "2018" [dependencies] diff --git a/base_layer/wallet_ffi/src/lib.rs b/base_layer/wallet_ffi/src/lib.rs index 21306353f6..a727412d3d 100644 --- a/base_layer/wallet_ffi/src/lib.rs +++ b/base_layer/wallet_ffi/src/lib.rs @@ -211,9 +211,7 @@ pub type TariTransportType = tari_p2p::transport::TransportType; pub type TariPublicKey = tari_comms::types::CommsPublicKey; pub type TariPrivateKey = tari_comms::types::CommsSecretKey; pub type TariCommsConfig = tari_p2p::initialization::CommsConfig; -pub type TariExcess = tari_common_types::types::Commitment; -pub type TariExcessPublicNonce = tari_crypto::ristretto::RistrettoPublicKey; -pub type TariExcessSignature = tari_crypto::ristretto::RistrettoSecretKey; +pub type TariTransactionKernel = tari_core::transactions::transaction::TransactionKernel; pub struct TariContacts(Vec); @@ -265,6 +263,114 @@ pub unsafe extern "C" fn string_destroy(ptr: *mut c_char) { /// -------------------------------------------------------------------------------------------- /// +/// ----------------------------------- Transaction Kernel ------------------------------------- /// + +/// Gets the excess for a TariTransactionKernel +/// +/// ## Arguments +/// `x` - The pointer to a TariTransactionKernel +/// +/// ## Returns +/// `*mut c_char` - Returns a pointer to a char array. 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 transaction_kernel_get_excess_hex( + kernel: *mut TariTransactionKernel, + error_out: *mut c_int, +) -> *mut c_char { + let mut error = 0; + let mut result = CString::new("").unwrap(); + ptr::swap(error_out, &mut error as *mut c_int); + if kernel.is_null() { + error = LibWalletError::from(InterfaceError::NullError("kernel".to_string())).code; + ptr::swap(error_out, &mut error as *mut c_int); + return CString::into_raw(result); + } + let excess = (*kernel).excess.clone().to_hex(); + result = CString::new(excess).unwrap(); + result.into_raw() +} + +/// Gets the public nonce for a TariTransactionKernel +/// +/// ## Arguments +/// `x` - The pointer to a TariTransactionKernel +/// +/// ## Returns +/// `*mut c_char` - Returns a pointer to a char array. 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 transaction_kernel_get_excess_public_nonce_hex( + kernel: *mut TariTransactionKernel, + error_out: *mut c_int, +) -> *mut c_char { + let mut error = 0; + let mut result = CString::new("").unwrap(); + ptr::swap(error_out, &mut error as *mut c_int); + if kernel.is_null() { + error = LibWalletError::from(InterfaceError::NullError("kernel".to_string())).code; + ptr::swap(error_out, &mut error as *mut c_int); + return CString::into_raw(result); + } + let nonce = (*kernel).excess_sig.get_public_nonce().to_hex(); + result = CString::new(nonce).unwrap(); + result.into_raw() +} + +/// Gets the signature for a TariTransactionKernel +/// +/// ## Arguments +/// `x` - The pointer to a TariTransactionKernel +/// +/// ## Returns +/// `*mut c_char` - Returns a pointer to a char array. 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 transaction_kernel_get_excess_signature_hex( + kernel: *mut TariTransactionKernel, + error_out: *mut c_int, +) -> *mut c_char { + let mut error = 0; + let mut result = CString::new("").unwrap(); + ptr::swap(error_out, &mut error as *mut c_int); + if kernel.is_null() { + error = LibWalletError::from(InterfaceError::NullError("kernel".to_string())).code; + ptr::swap(error_out, &mut error as *mut c_int); + return CString::into_raw(result); + } + let signature = (*kernel).excess_sig.get_signature().to_hex(); + result = CString::new(signature).unwrap(); + result.into_raw() +} + +/// Frees memory for a TariTransactionKernel +/// +/// ## Arguments +/// `x` - The pointer to a TariTransactionKernel +/// +/// ## Returns +/// `()` - Does not return a value, equivalent to void in C +/// +/// # Safety +/// None +#[no_mangle] +pub unsafe extern "C" fn transaction_kernel_destroy(x: *mut TariTransactionKernel) { + if !x.is_null() { + Box::from_raw(x); + } +} + +/// -------------------------------------------------------------------------------------------- /// + /// -------------------------------- ByteVector ------------------------------------------------ /// /// Creates a ByteVector @@ -438,57 +544,6 @@ pub unsafe extern "C" fn public_key_destroy(pk: *mut TariPublicKey) { } } -/// Frees memory for a TariExcess -/// -/// ## Arguments -/// `x` - The pointer to a TariExcess -/// -/// ## Returns -/// `()` - Does not return a value, equivalent to void in C -/// -/// # Safety -/// None -#[no_mangle] -pub unsafe extern "C" fn excess_destroy(x: *mut TariExcess) { - if !x.is_null() { - Box::from_raw(x); - } -} - -/// Frees memory for a TariExcessPublicNonce -/// -/// ## Arguments -/// `r` - The pointer to a TariExcessPublicNonce -/// -/// ## Returns -/// `()` - Does not return a value, equivalent to void in C -/// -/// # Safety -/// None -#[no_mangle] -pub unsafe extern "C" fn nonce_destroy(r: *mut TariExcessPublicNonce) { - if !r.is_null() { - Box::from_raw(r); - } -} - -/// Frees memory for a TariExcessSignature -/// -/// ## Arguments -/// `s` - The pointer to a TariExcessSignature -/// -/// ## Returns -/// `()` - Does not return a value, equivalent to void in C -/// -/// # Safety -/// None -#[no_mangle] -pub unsafe extern "C" fn signature_destroy(s: *mut TariExcessSignature) { - if !s.is_null() { - Box::from_raw(s); - } -} - /// Gets a ByteVector from a TariPublicKey /// /// ## Arguments @@ -1473,7 +1528,7 @@ pub unsafe extern "C" fn completed_transaction_get_destination_public_key( Box::into_raw(Box::new(m)) } -/// Gets the TariExcess of a TariCompletedTransaction +/// Gets the TariTransactionKernel of a TariCompletedTransaction /// /// ## Arguments /// `transaction` - The pointer to a TariCompletedTransaction @@ -1481,17 +1536,18 @@ pub unsafe extern "C" fn completed_transaction_get_destination_public_key( /// as an out parameter. /// /// ## Returns -/// `*mut TariExcess` - Returns the transaction excess, note that it will be +/// `*mut TariTransactionKernel` - Returns the transaction kernel, note that it will be /// ptr::null_mut() if transaction is null, if the transaction status is Pending, or if the number of kernels is not /// exactly one. /// /// # Safety -/// The ```excess_destroy``` method must be called when finished with a TariExcess to prevent a memory leak +/// The ```transaction_kernel_destroy``` method must be called when finished with a TariTransactionKernel to prevent a +/// memory leak #[no_mangle] -pub unsafe extern "C" fn completed_transaction_get_excess( +pub unsafe extern "C" fn completed_transaction_get_transaction_kernel( transaction: *mut TariCompletedTransaction, error_out: *mut c_int, -) -> *mut TariExcess { +) -> *mut TariTransactionKernel { let mut error = 0; ptr::swap(error_out, &mut error as *mut c_int); if transaction.is_null() { @@ -1522,116 +1578,10 @@ pub unsafe extern "C" fn completed_transaction_get_excess( return ptr::null_mut(); } - let x = kernels[0].excess.clone(); + let x = kernels[0].clone(); Box::into_raw(Box::new(x)) } -/// Gets the TariExcessPublicNonce of a TariCompletedTransaction -/// -/// ## Arguments -/// `transaction` - The pointer to a TariCompletedTransaction -/// `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 -/// `*mut TariExcessPublicNonce` - Returns the transaction excess public nonce, note that it will be -/// ptr::null_mut() if transaction is null, if the transaction status is Pending, or if the number of kernels is not -/// exactly one. -/// -/// # Safety -/// The ```nonce_destroy``` method must be called when finished with a TariExcessPublicNonce to prevent a memory leak -#[no_mangle] -pub unsafe extern "C" fn completed_transaction_get_public_nonce( - transaction: *mut TariCompletedTransaction, - error_out: *mut c_int, -) -> *mut TariExcessPublicNonce { - let mut error = 0; - ptr::swap(error_out, &mut error as *mut c_int); - if transaction.is_null() { - error = LibWalletError::from(InterfaceError::NullError("transaction".to_string())).code; - ptr::swap(error_out, &mut error as *mut c_int); - return ptr::null_mut(); - } - - // check the tx is not in pending state - if matches!( - (*transaction).status, - TransactionStatus::Pending | TransactionStatus::Imported - ) { - let msg = format!("Incorrect transaction status: {}", (*transaction).status); - error = LibWalletError::from(TransactionError::StatusError(msg)).code; - ptr::swap(error_out, &mut error as *mut c_int); - return ptr::null_mut(); - } - - let kernels = (*transaction).transaction.get_body().kernels(); - - // currently we presume that each CompletedTransaction only has 1 kernel - // if that changes this will need to be accounted for - if kernels.len() != 1 { - let msg = format!("Expected 1 kernel, got {}", kernels.len()); - error = LibWalletError::from(TransactionError::KernelError(msg)).code; - ptr::swap(error_out, &mut error as *mut c_int); - return ptr::null_mut(); - } - - let r = kernels[0].excess_sig.get_public_nonce().clone(); - Box::into_raw(Box::new(r)) -} - -/// Gets the TariExcessSignature of a TariCompletedTransaction -/// -/// ## Arguments -/// `transaction` - The pointer to a TariCompletedTransaction -/// `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 -/// `*mut TariExcessSignature` - Returns the transaction excess signature, note that it will be -/// ptr::null_mut() if transaction is null, if the transaction status is Pending, or if the number of kernels is not -/// exactly one. -/// -/// # Safety -/// The ```signature_destroy``` method must be called when finished with a TariExcessSignature to prevent a memory leak -#[no_mangle] -pub unsafe extern "C" fn completed_transaction_get_signature( - transaction: *mut TariCompletedTransaction, - error_out: *mut c_int, -) -> *mut TariExcessSignature { - let mut error = 0; - ptr::swap(error_out, &mut error as *mut c_int); - if transaction.is_null() { - error = LibWalletError::from(InterfaceError::NullError("transaction".to_string())).code; - ptr::swap(error_out, &mut error as *mut c_int); - return ptr::null_mut(); - } - - // check the tx is not in pending state - if matches!( - (*transaction).status, - TransactionStatus::Pending | TransactionStatus::Imported - ) { - let msg = format!("Incorrect transaction status: {}", (*transaction).status); - error = LibWalletError::from(TransactionError::StatusError(msg)).code; - ptr::swap(error_out, &mut error as *mut c_int); - return ptr::null_mut(); - } - - let kernels = (*transaction).transaction.get_body().kernels(); - - // currently we presume that each CompletedTransaction only has 1 kernel - // if that changes this will need to be accounted for - if kernels.len() != 1 { - let msg = format!("Expected 1 kernel, got {}", kernels.len()); - error = LibWalletError::from(TransactionError::KernelError(msg)).code; - ptr::swap(error_out, &mut error as *mut c_int); - return ptr::null_mut(); - } - - let s = kernels[0].excess_sig.get_signature().clone(); - Box::into_raw(Box::new(s)) -} - /// Gets the source TariPublicKey of a TariCompletedTransaction /// /// ## Arguments @@ -5445,6 +5395,22 @@ mod test { assert_eq!((*tx).status, TransactionStatus::MinedUnconfirmed); let mut lock = CALLBACK_STATE_FFI.lock().unwrap(); lock.mined_tx_unconfirmed_callback_called = true; + let mut error = 0; + let error_ptr = &mut error as *mut c_int; + let kernel = completed_transaction_get_transaction_kernel(tx, error_ptr); + let excess_hex_ptr = transaction_kernel_get_excess_hex(kernel, error_ptr); + let excess_hex = CString::from_raw(excess_hex_ptr).to_str().unwrap().to_owned(); + assert!(!excess_hex.is_empty()); + let nonce_hex_ptr = transaction_kernel_get_excess_public_nonce_hex(kernel, error_ptr); + let nonce_hex = CString::from_raw(nonce_hex_ptr).to_str().unwrap().to_owned(); + assert!(!nonce_hex.is_empty()); + let sig_hex_ptr = transaction_kernel_get_excess_signature_hex(kernel, error_ptr); + let sig_hex = CString::from_raw(sig_hex_ptr).to_str().unwrap().to_owned(); + assert!(!sig_hex.is_empty()); + string_destroy(excess_hex_ptr as *mut c_char); + string_destroy(sig_hex_ptr as *mut c_char); + string_destroy(nonce_hex_ptr); + transaction_kernel_destroy(kernel); drop(lock); completed_transaction_destroy(tx); } diff --git a/base_layer/wallet_ffi/wallet.h b/base_layer/wallet_ffi/wallet.h index bd17dd613e..0dfd400482 100644 --- a/base_layer/wallet_ffi/wallet.h +++ b/base_layer/wallet_ffi/wallet.h @@ -73,11 +73,7 @@ struct TariSeedWords; struct EmojiSet; -struct TariExcess; - -struct TariExcessPublicNonce; - -struct TariExcessSignature; +struct TariTransactionKernel; /// -------------------------------- Transport Types ----------------------------------------------- /// @@ -262,26 +258,25 @@ bool completed_transaction_is_outbound(struct TariCompletedTransaction *tx, int /// Gets the number of confirmations of a TariCompletedTransaction unsigned long long completed_transaction_get_confirmations(struct TariCompletedTransaction *transaction, int *error_out); +// Gets the TariTransactionKernel of a TariCompletedTransaction +struct TariTransactionKernel *completed_transaction_get_transaction_kernel(struct TariCompletedTransaction *transaction, int *error_out); + // Frees memory for a TariCompletedTransaction void completed_transaction_destroy(struct TariCompletedTransaction *transaction); -// Gets the TariExcess of a TariCompletedTransaction -struct TariExcess *completed_transaction_get_excess(struct TariCompletedTransaction *transaction, int *error_out); - -// Gets the TariExcessPublicNonce of a TariCompletedTransaction -struct TariExcessPublicNonce *completed_transaction_get_public_nonce(struct TariCompletedTransaction *transaction, int *error_out); +/// --------------------------------------- TransactionKernel ------------------------------------------------------ /// -// Gets the TariExcessSignature of a TariCompletedTransaction -struct TariExcessSignature *completed_transaction_get_signature(struct TariCompletedTransaction *transaction, int *error_out); +// Gets the excess for a TariTransactionKernel +const char *transaction_kernel_get_excess_hex(struct TariTransactionKernel *kernel, int *error_out); -// Frees memory for a TariExcess -void excess_destroy(struct TariExcess *excess); +// Gets the public nonce for a TariTransactionKernel +const char *transaction_kernel_get_excess_public_nonce_hex(struct TariTransactionKernel *kernel, int *error_out); -// Frees memory for a TariExcessPublicNonce -void nonce_destroy(struct TariExcessPublicNonce *nonce); +// Gets the signature for a TariTransactionKernel +const char *transaction_kernel_get_excess_signature_hex(struct TariTransactionKernel *kernel, int *error_out); -// Frees memory for a TariExcessSignature -void signature_destroy(struct TariExcessSignature *signature); +// Frees memory for a TariTransactionKernel +void transaction_kernel_destroy(struct TariTransactionKernel *kernel); /// -------------------------------- CompletedTransactions ------------------------------------------------------ /// diff --git a/integration_tests/features/WalletFFI.feature b/integration_tests/features/WalletFFI.feature index 729c7480c5..524789a87b 100644 --- a/integration_tests/features/WalletFFI.feature +++ b/integration_tests/features/WalletFFI.feature @@ -6,10 +6,10 @@ Feature: Wallet FFI # https://github.com/nodejs/node/issues/32463 # https://github.com/node-ffi-napi/node-ffi-napi/issues/97 - # It's just calling the encrypt function, we don't test if it's actually encrypted Scenario: As a client I want to be able to protect my wallet with a passphrase Given I have a base node BASE And I have a ffi wallet FFI_WALLET connected to base node BASE + # It's just calling the encrypt function, we don't test if it's actually encrypted And I set passphrase PASSPHRASE of ffi wallet FFI_WALLET And I stop ffi wallet FFI_WALLET @@ -90,6 +90,7 @@ Feature: Wallet FFI And mining node MINER mines 10 blocks Then I wait for wallet RECEIVER to have at least 1000000 uT And I have 1 received and 1 send transaction in ffi wallet FFI_WALLET + Then I want to view the transaction kernels for completed transactions in ffi wallet FFI_WALLET And I start STXO validation on ffi wallet FFI_WALLET And I start UTXO validation on ffi wallet FFI_WALLET And I stop ffi wallet FFI_WALLET diff --git a/integration_tests/features/support/steps.js b/integration_tests/features/support/steps.js index f67aa45f08..d5f05d8c5e 100644 --- a/integration_tests/features/support/steps.js +++ b/integration_tests/features/support/steps.js @@ -4069,7 +4069,31 @@ Then( } ); -When(/I stop ffi wallet (.*)/, function (walletName) { +Then( + "I want to view the transaction kernels for completed transactions in ffi wallet {word}", + { timeout: 20 * 1000 }, + function (name) { + let ffi_wallet = this.getWallet(name); + let transactions = ffi_wallet.getCompletedTxs(); + let length = transactions.getLength(); + expect(length > 0).to.equal(true); + for (let i = 0; i < length; i++) { + let tx = transactions.getAt(i); + let kernel = tx.getKernel(); + let data = kernel.asObject(); + console.log("Transaction kernel info:"); + console.log(data); + expect(data.excess.length > 0).to.equal(true); + expect(data.nonce.length > 0).to.equal(true); + expect(data.sig.length > 0).to.equal(true); + kernel.destroy(); + tx.destroy(); + } + transactions.destroy(); + } +); + +When("I stop ffi wallet {word}", function (walletName) { let wallet = this.getWallet(walletName); wallet.stop(); wallet.resetCounters(); diff --git a/integration_tests/features/support/world.js b/integration_tests/features/support/world.js index aa2233cf20..b14fa6c982 100644 --- a/integration_tests/features/support/world.js +++ b/integration_tests/features/support/world.js @@ -384,8 +384,12 @@ BeforeAll({ timeout: 1200000 }, async function () { console.log("Compiling wallet FFI..."); await InterfaceFFI.compile(); - await InterfaceFFI.init(); console.log("Finished compilation."); + console.log("Loading FFI interface.."); + await InterfaceFFI.init(); + console.log("FFI interface loaded."); + + console.log("World ready, now lets run some tests! :)"); }); After(async function (testCase) { diff --git a/integration_tests/helpers/ffi/completedTransaction.js b/integration_tests/helpers/ffi/completedTransaction.js index 6e0605bcbe..8d0defdeb3 100644 --- a/integration_tests/helpers/ffi/completedTransaction.js +++ b/integration_tests/helpers/ffi/completedTransaction.js @@ -1,5 +1,6 @@ const InterfaceFFI = require("./ffiInterface"); const PublicKey = require("./publicKey"); +const TransactionKernel = require("./transactionKernel"); class CompletedTransaction { ptr; @@ -69,6 +70,12 @@ class CompletedTransaction { return InterfaceFFI.completedTransactionGetConfirmations(this.ptr); } + getKernel() { + let result = new TransactionKernel(); + result.pointerAssign(InterfaceFFI.completedTransactionGetKernel(this.ptr)); + return result; + } + destroy() { if (this.ptr) { InterfaceFFI.completedTransactionDestroy(this.ptr); diff --git a/integration_tests/helpers/ffi/ffiInterface.js b/integration_tests/helpers/ffi/ffiInterface.js index fd724cb55d..e2f19f69ee 100644 --- a/integration_tests/helpers/ffi/ffiInterface.js +++ b/integration_tests/helpers/ffi/ffiInterface.js @@ -155,27 +155,29 @@ class InterfaceFFI { [this.ptr, this.intPtr], ], completed_transaction_destroy: [this.void, [this.ptr]], - //completed_transaction_get_excess: [ - //this.tari_excess_ptr, - // [this.tari_completed_transaction_ptr, this.intPtr], - //], - //completed_transaction_get_public_nonce: [ - // this.tari_excess_public_nonce_ptr, - // [this.tari_completed_transaction_ptr, this.intPtr], - //], - //completed_transaction_get_signature: [ - // this.tari_excess_signature_ptr, - // [this.tari_completed_transaction_ptr, this.intPtr], - //], - // excess_destroy: [this.void, [this.tari_excess_ptr]], - // nonce_destroy: [this.void, [this.tari_excess_public_nonce_ptr]], - // signature_destroy: [this.void, [this.tari_excess_signature_ptr]], + completed_transaction_get_transaction_kernel: [ + this.ptr, + [this.ptr, this.intPtr], + ], completed_transactions_get_length: [this.uint, [this.ptr, this.intPtr]], completed_transactions_get_at: [ this.ptr, [this.ptr, this.uint, this.intPtr], ], completed_transactions_destroy: [this.void, [this.ptr]], + transaction_kernel_get_excess_hex: [ + this.stringPtr, + [this.ptr, this.intPtr], + ], + transaction_kernel_get_excess_public_nonce_hex: [ + this.stringPtr, + [this.ptr, this.intPtr], + ], + transaction_kernel_get_excess_signature_hex: [ + this.stringPtr, + [this.ptr, this.intPtr], + ], + transaction_kernel_destroy: [this.void, [this.ptr]], pending_outbound_transaction_get_transaction_id: [ this.ulonglong, [this.ptr, this.intPtr], @@ -847,76 +849,54 @@ class InterfaceFFI { return result; } + static completedTransactionGetKernel(ptr) { + let error = this.initError(); + let result = this.fn.completed_transaction_get_transaction_kernel( + ptr, + error + ); + this.checkErrorResult(error, `completedTransactionGetConfirmations`); + return result; + } + static completedTransactionDestroy(ptr) { this.fn.completed_transaction_destroy(ptr); } //endregion - /* - //Flagged as design flaw in the FFI lib - - static completedTransactionGetExcess(transaction) { - return new Promise((resolve, reject) => - this.fn.completed_transaction_get_excess.async( - transaction, - this.error, - this.checkAsyncRes(resolve, reject, "completedTransactionGetExcess") - ) - ); - } - - static completedTransactionGetPublicNonce(transaction) { - return new Promise((resolve, reject) => - this.fn.completed_transaction_get_public_nonce.async( - transaction, - this.error, - this.checkAsyncRes( - resolve, - reject, - "completedTransactionGetPublicNonce" - ) - ) - ); - } - - static completedTransactionGetSignature(transaction) { - return new Promise((resolve, reject) => - this.fn.completed_transaction_get_signature.async( - transaction, - this.error, - this.checkAsyncRes(resolve, reject, "completedTransactionGetSignature") - ) - ); + //region TransactionKernel + static transactionKernelGetExcess(ptr) { + let error = this.initError(); + let result = this.fn.transaction_kernel_get_excess_hex(ptr, error); + this.checkErrorResult(error, `completedTransactionGetConfirmations`); + return result; } - static excessDestroy(excess) { - return new Promise((resolve, reject) => - this.fn.excess_destroy.async( - excess, - this.checkAsyncRes(resolve, reject, "excessDestroy") - ) + static transactionKernelGetExcessPublicNonce(ptr) { + let error = this.initError(); + let result = this.fn.transaction_kernel_get_excess_public_nonce_hex( + ptr, + error ); + this.checkErrorResult(error, `completedTransactionGetConfirmations`); + return result; } - static nonceDestroy(nonce) { - return new Promise((resolve, reject) => - this.fn.nonce_destroy.async( - nonce, - this.checkAsyncRes(resolve, reject, "nonceDestroy") - ) + static transactionKernelGetExcessSigntature(ptr) { + let error = this.initError(); + let result = this.fn.transaction_kernel_get_excess_signature_hex( + ptr, + error ); + this.checkErrorResult(error, `completedTransactionGetConfirmations`); + return result; } - static signatureDestroy(signature) { - return new Promise((resolve, reject) => - this.fn.signature_destroy.async( - signature, - this.checkAsyncRes(resolve, reject, "signatureDestroy") - ) - ); + static transactionKernelDestroy(ptr) { + this.fn.transaction_kernel_destroy(ptr); } - */ + //endRegion //region CompletedTransactions (List) static completedTransactionsGetLength(ptr) { diff --git a/integration_tests/helpers/ffi/transactionKernel.js b/integration_tests/helpers/ffi/transactionKernel.js new file mode 100644 index 0000000000..47c68f42e4 --- /dev/null +++ b/integration_tests/helpers/ffi/transactionKernel.js @@ -0,0 +1,57 @@ +const InterfaceFFI = require("./ffiInterface"); + +class CompletedTransactionKernel { + ptr; + + pointerAssign(ptr) { + // Prevent pointer from being leaked in case of re-assignment + if (this.ptr) { + this.destroy(); + this.ptr = ptr; + } else { + this.ptr = ptr; + } + } + + getPtr() { + return this.ptr; + } + + getExcess() { + let strPtr = InterfaceFFI.transactionKernelGetExcess(this.ptr); + let result = strPtr.readCString(); + InterfaceFFI.stringDestroy(strPtr); + return result; + } + + getNonce() { + let strPtr = InterfaceFFI.transactionKernelGetExcessPublicNonce(this.ptr); + let result = strPtr.readCString(); + InterfaceFFI.stringDestroy(strPtr); + return result; + } + + getSignature() { + let strPtr = InterfaceFFI.transactionKernelGetExcessSigntature(this.ptr); + let result = strPtr.readCString(); + InterfaceFFI.stringDestroy(strPtr); + return result; + } + + asObject() { + return { + excess: this.getExcess(), + nonce: this.getNonce(), + sig: this.getSignature(), + }; + } + + destroy() { + if (this.ptr) { + InterfaceFFI.transactionKernelDestroy(this.ptr); + this.ptr = undefined; //prevent double free segfault + } + } +} + +module.exports = CompletedTransactionKernel;