diff --git a/android-bindings/src/bindings.rs b/android-bindings/src/bindings.rs index 98a54b9368..b393a50224 100644 --- a/android-bindings/src/bindings.rs +++ b/android-bindings/src/bindings.rs @@ -54,7 +54,7 @@ use mc_transaction_core::{ use mc_transaction_std::{ AuthenticatedSenderMemo, AuthenticatedSenderWithPaymentRequestIdMemo, ChangeDestination, DestinationMemo, InputCredentials, MemoBuilder, MemoPayload, RTHMemoBuilder, - SenderMemoCredential, TransactionBuilder, + SenderMemoCredential, TransactionBuilder, TxOutContext, }; use mc_util_from_random::FromRandom; @@ -1478,6 +1478,65 @@ pub unsafe extern "C" fn Java_com_mobilecoin_lib_TxOut_decrypt_1memo_1payload( ) } +/******************************************************************** + * TxOutContext + */ +#[no_mangle] +pub unsafe extern "C" fn Java_com_mobilecoin_lib_TxOutContext_get_1tx_1out( + env: JNIEnv, + obj: JObject, +) -> jlong { + jni_ffi_call_or( + || Ok(0), + &env, + |env| { + let tx_out_context: MutexGuard = + env.get_rust_field(obj, RUST_OBJ_FIELD)?; + let tx_out = tx_out_context.tx_out.to_owned(); + let mbox = Box::new(Mutex::new(tx_out)); + let ptr: *mut Mutex = Box::into_raw(mbox); + Ok(ptr as jlong) + }, + ) +} + +#[no_mangle] +pub unsafe extern "C" fn Java_com_mobilecoin_lib_TxOutContext_get_1confirmation_1number( + env: JNIEnv, + obj: JObject, +) -> jbyteArray { + jni_ffi_call_or( + || Ok(JObject::null().into_inner()), + &env, + |env| { + let tx_out_context: MutexGuard = + env.get_rust_field(obj, RUST_OBJ_FIELD)?; + let confirmation_number = &tx_out_context.confirmation; + let bytes = mc_util_serial::encode(confirmation_number); + Ok(env.byte_array_from_slice(&bytes)?) + }, + ) +} + +#[no_mangle] +pub unsafe extern "C" fn Java_com_mobilecoin_lib_TxOutContext_get_1shared_1secret( + env: JNIEnv, + obj: JObject, +) -> jlong { + jni_ffi_call_or( + || Ok(0), + &env, + |env| { + let tx_out_context: MutexGuard = + env.get_rust_field(obj, RUST_OBJ_FIELD)?; + let shared_secret = tx_out_context.shared_secret.to_owned(); + let mbox = Box::new(Mutex::new(shared_secret)); + let ptr: *mut Mutex = Box::into_raw(mbox); + Ok(ptr as jlong) + }, + ) +} + /******************************************************************** * TxOutMembershipProof */ @@ -1713,8 +1772,8 @@ pub unsafe extern "C" fn Java_com_mobilecoin_lib_TransactionBuilder_add_1output( env.get_rust_field(recipient, RUST_OBJ_FIELD)?; let mut rng = McRng::default(); - let (tx_out, confirmation_number) = - tx_builder.add_output(value as u64, &recipient, &mut rng)?; + let tx_out_context = tx_builder.add_output(value as u64, &recipient, &mut rng)?; + let confirmation_number = &tx_out_context.confirmation; if !confirmation_number_out.is_null() { let len = env.get_array_length(confirmation_number_out)?; if len as usize >= confirmation_number.to_vec().len() { @@ -1731,8 +1790,8 @@ pub unsafe extern "C" fn Java_com_mobilecoin_lib_TransactionBuilder_add_1output( } } - let mbox = Box::new(Mutex::new(tx_out)); - let ptr: *mut Mutex = Box::into_raw(mbox); + let mbox = Box::new(Mutex::new(tx_out_context)); + let ptr: *mut Mutex = Box::into_raw(mbox); Ok(ptr as jlong) }, ) @@ -1760,8 +1819,9 @@ pub unsafe extern "C" fn Java_com_mobilecoin_lib_TransactionBuilder_add_1change_ ChangeDestination::from(&*source_account_key); let mut rng = McRng::default(); - let (tx_out, confirmation_number) = + let tx_out_context = tx_builder.add_change_output(value, &change_destination, &mut rng)?; + let confirmation_number = &tx_out_context.confirmation; if !confirmation_number_out.is_null() { let len = env.get_array_length(confirmation_number_out)?; if len as usize >= confirmation_number.to_vec().len() { @@ -1778,8 +1838,8 @@ pub unsafe extern "C" fn Java_com_mobilecoin_lib_TransactionBuilder_add_1change_ } } - let mbox = Box::new(Mutex::new(tx_out)); - let ptr: *mut Mutex = Box::into_raw(mbox); + let mbox = Box::new(Mutex::new(tx_out_context)); + let ptr: *mut Mutex = Box::into_raw(mbox); Ok(ptr as jlong) }, ) diff --git a/libmobilecoin/include/transaction.h b/libmobilecoin/include/transaction.h index 37b748466e..0c5f2a2810 100644 --- a/libmobilecoin/include/transaction.h +++ b/libmobilecoin/include/transaction.h @@ -216,9 +216,10 @@ McData* MC_NULLABLE mc_transaction_builder_add_output( const McPublicAddress* MC_NONNULL recipient_address, McRngCallback* MC_NULLABLE rng_callback, McMutableBuffer* MC_NONNULL out_tx_out_confirmation_number, + McMutableBuffer* MC_NONNULL out_tx_out_shared_secret, McError* MC_NULLABLE * MC_NULLABLE out_error ) -MC_ATTRIBUTE_NONNULL(1, 3, 6); +MC_ATTRIBUTE_NONNULL(1, 3, 5, 6); /// # Preconditions /// @@ -237,9 +238,10 @@ McData* MC_NULLABLE mc_transaction_builder_add_change_output( uint64_t amount, McRngCallback* MC_NULLABLE rng_callback, McMutableBuffer* MC_NONNULL out_tx_out_confirmation_number, + McMutableBuffer* MC_NONNULL out_tx_out_shared_secret, McError* MC_NULLABLE * MC_NULLABLE out_error ) -MC_ATTRIBUTE_NONNULL(1, 2, 4, 6); +MC_ATTRIBUTE_NONNULL(1, 2, 4, 5, 6); /// # Preconditions /// diff --git a/libmobilecoin/libmobilecoin_cbindgen.h b/libmobilecoin/libmobilecoin_cbindgen.h index a1deb37e5e..67cea067d3 100644 --- a/libmobilecoin/libmobilecoin_cbindgen.h +++ b/libmobilecoin/libmobilecoin_cbindgen.h @@ -785,6 +785,7 @@ FfiOptOwnedPtr mc_transaction_builder_add_output(FfiMutPtr recipient_address, FfiOptMutPtr rng_callback, FfiMutPtr out_tx_out_confirmation_number, + FfiMutPtr out_tx_out_shared_secret, FfiOptMutPtr> out_error); /** @@ -806,6 +807,7 @@ FfiOptOwnedPtr mc_transaction_builder_add_change_output(FfiRefPtr rng_callback, FfiMutPtr out_tx_out_confirmation_number, + FfiMutPtr out_tx_out_shared_secret, FfiOptMutPtr> out_error); /** diff --git a/libmobilecoin/src/transaction.rs b/libmobilecoin/src/transaction.rs index 747aaf4a7d..d6c3779120 100644 --- a/libmobilecoin/src/transaction.rs +++ b/libmobilecoin/src/transaction.rs @@ -481,6 +481,7 @@ pub extern "C" fn mc_transaction_builder_add_output( recipient_address: FfiRefPtr, rng_callback: FfiOptMutPtr, out_tx_out_confirmation_number: FfiMutPtr, + out_tx_out_shared_secret: FfiMutPtr, out_error: FfiOptMutPtr>, ) -> FfiOptOwnedPtr { ffi_boundary_with_error(out_error, || { @@ -496,11 +497,18 @@ pub extern "C" fn mc_transaction_builder_add_output( .as_slice_mut_of_len(TxOutConfirmationNumber::size()) .expect("out_tx_out_confirmation_number length is insufficient"); - let (tx_out, confirmation) = + let tx_out_context = transaction_builder.add_output(amount, &recipient_address, &mut rng)?; - out_tx_out_confirmation_number.copy_from_slice(confirmation.as_ref()); - Ok(mc_util_serial::encode(&tx_out)) + out_tx_out_confirmation_number.copy_from_slice(tx_out_context.confirmation.as_ref()); + + let out_tx_out_shared_secret = out_tx_out_shared_secret + .into_mut() + .as_slice_mut_of_len(RistrettoPublic::size()) + .expect("out_tx_out_shared_secret length is insufficient"); + + out_tx_out_shared_secret.copy_from_slice(&tx_out_context.shared_secret.to_bytes()); + Ok(mc_util_serial::encode(&tx_out_context.tx_out)) }) } @@ -523,6 +531,7 @@ pub extern "C" fn mc_transaction_builder_add_change_output( amount: u64, rng_callback: FfiOptMutPtr, out_tx_out_confirmation_number: FfiMutPtr, + out_tx_out_shared_secret: FfiMutPtr, out_error: FfiOptMutPtr>, ) -> FfiOptOwnedPtr { ffi_boundary_with_error(out_error, || { @@ -539,11 +548,18 @@ pub extern "C" fn mc_transaction_builder_add_change_output( .as_slice_mut_of_len(TxOutConfirmationNumber::size()) .expect("out_tx_out_confirmation_number length is insufficient"); - let (tx_out, confirmation) = + let tx_out_context = transaction_builder.add_change_output(amount, &change_destination, &mut rng)?; - out_tx_out_confirmation_number.copy_from_slice(confirmation.as_ref()); - Ok(mc_util_serial::encode(&tx_out)) + out_tx_out_confirmation_number.copy_from_slice(tx_out_context.confirmation.as_ref()); + + let out_tx_out_shared_secret = out_tx_out_shared_secret + .into_mut() + .as_slice_mut_of_len(RistrettoPublic::size()) + .expect("out_tx_out_shared_secret length is insufficient"); + + out_tx_out_shared_secret.copy_from_slice(&tx_out_context.shared_secret.to_bytes()); + Ok(mc_util_serial::encode(&tx_out_context.tx_out)) }) } diff --git a/mobilecoind/src/payments.rs b/mobilecoind/src/payments.rs index cee5b5681d..f94b4fab8d 100644 --- a/mobilecoind/src/payments.rs +++ b/mobilecoind/src/payments.rs @@ -25,6 +25,7 @@ use mc_transaction_core::{ }; use mc_transaction_std::{ ChangeDestination, EmptyMemoBuilder, InputCredentials, MemoBuilder, TransactionBuilder, + TxOutContext, }; use mc_util_uri::FogUri; use rand::Rng; @@ -970,12 +971,16 @@ impl TransactionBuilder { value: u64, recipient: &PublicAddress, rng: &mut RNG, - ) -> Result<(TxOut, TxOutConfirmationNumber), TxBuilderError> { + ) -> Result { // Taking self.memo_builder here means that we can call functions on &mut self, // and pass them something that has captured the memo builder. // Calling take() on Option is just moving a pointer. @@ -207,7 +222,7 @@ impl TransactionBuilder { value: u64, change_destination: &ChangeDestination, rng: &mut RNG, - ) -> Result<(TxOut, TxOutConfirmationNumber), TxBuilderError> { + ) -> Result { // Taking self.memo_builder here means that we can call functions on &mut self, // and pass them something that has captured the memo builder. // Calling take() on Option is just moving a pointer. @@ -265,7 +280,7 @@ impl TransactionBuilder { fog_hint_address: &PublicAddress, memo_fn: impl FnOnce(MemoContext) -> Result, NewMemoError>, rng: &mut RNG, - ) -> Result<(TxOut, TxOutConfirmationNumber), TxBuilderError> { + ) -> Result { let (hint, pubkey_expiry) = create_fog_hint(fog_hint_address, &self.fog_resolver, rng)?; let amount = Amount { value, @@ -281,7 +296,11 @@ impl TransactionBuilder { let confirmation = TxOutConfirmationNumber::from(&shared_secret); - Ok((tx_out, confirmation)) + Ok(TxOutContext { + tx_out, + confirmation, + shared_secret, + }) } /// Sets the tombstone block, clamping to smallest pubkey expiry value. @@ -792,7 +811,7 @@ pub mod transaction_builder_tests { .unwrap(); transaction_builder.add_input(input_credentials); - let (_txout, confirmation) = transaction_builder + let TxOutContext { confirmation, .. } = transaction_builder .add_output( value - Mob::MINIMUM_FEE, &recipient.default_subaddress(), @@ -875,7 +894,7 @@ pub mod transaction_builder_tests { .unwrap(); transaction_builder.add_input(input_credentials); - let (_txout, confirmation) = transaction_builder + let TxOutContext { confirmation, .. } = transaction_builder .add_output( value - Mob::MINIMUM_FEE, &recipient.default_subaddress(), @@ -970,7 +989,7 @@ pub mod transaction_builder_tests { get_input_credentials(block_version, amount, &sender, &fog_resolver, &mut rng); transaction_builder.add_input(input_credentials); - let (_txout, _confirmation) = transaction_builder + let _tx_out_context = transaction_builder .add_output_with_fog_hint_address( value - Mob::MINIMUM_FEE, &recipient.default_subaddress(), @@ -1049,7 +1068,7 @@ pub mod transaction_builder_tests { get_input_credentials(block_version, amount, &sender, &fog_resolver, &mut rng); transaction_builder.add_input(input_credentials); - let (_txout, _confirmation) = transaction_builder + transaction_builder .add_output(value - Mob::MINIMUM_FEE, &recipient_address, &mut rng) .unwrap(); @@ -1081,7 +1100,7 @@ pub mod transaction_builder_tests { get_input_credentials(block_version, amount, &sender, &fog_resolver, &mut rng); transaction_builder.add_input(input_credentials); - let (_txout, _confirmation) = transaction_builder + transaction_builder .add_output(value - Mob::MINIMUM_FEE, &recipient_address, &mut rng) .unwrap(); @@ -1147,7 +1166,7 @@ pub mod transaction_builder_tests { ); transaction_builder.add_input(input_credentials); - let (_txout, _confirmation) = transaction_builder + transaction_builder .add_output( value - change_value - Mob::MINIMUM_FEE, &recipient_address, @@ -1325,7 +1344,7 @@ pub mod transaction_builder_tests { ); transaction_builder.add_input(input_credentials); - let (_txout, _confirmation) = transaction_builder + transaction_builder .add_output( value - change_value - Mob::MINIMUM_FEE, &recipient_address, @@ -1484,7 +1503,7 @@ pub mod transaction_builder_tests { ); transaction_builder.add_input(input_credentials); - let (_txout, _confirmation) = transaction_builder + transaction_builder .add_output( value - change_value - Mob::MINIMUM_FEE * 4, &recipient_address, @@ -1643,7 +1662,7 @@ pub mod transaction_builder_tests { ); transaction_builder.add_input(input_credentials); - let (_txout, _confirmation) = transaction_builder + transaction_builder .add_output( value - change_value - Mob::MINIMUM_FEE, &recipient_address, @@ -1802,7 +1821,7 @@ pub mod transaction_builder_tests { ); transaction_builder.add_input(input_credentials); - let (_txout, _confirmation) = transaction_builder + transaction_builder .add_output( value - change_value - Mob::MINIMUM_FEE, &recipient_address, @@ -1949,7 +1968,7 @@ pub mod transaction_builder_tests { ); transaction_builder.add_input(input_credentials); - let (_txout, _confirmation) = transaction_builder + transaction_builder .add_output( value - change_value - Mob::MINIMUM_FEE, &recipient_address, @@ -2121,7 +2140,7 @@ pub mod transaction_builder_tests { ); transaction_builder.add_input(input_credentials); - let (_txout, _confirmation) = transaction_builder + transaction_builder .add_output( value - change_value - Mob::MINIMUM_FEE, &bob_address, @@ -2310,7 +2329,7 @@ pub mod transaction_builder_tests { ); transaction_builder.add_input(input_credentials); - let (_txout, _confirmation) = transaction_builder + transaction_builder .add_output( value - change_value - Mob::MINIMUM_FEE, &recipient_address, @@ -2578,7 +2597,10 @@ pub mod transaction_builder_tests { ); transaction_builder.add_input(input_credentials); - let (burn_tx_out, _confirmation) = transaction_builder + let TxOutContext { + tx_out: burn_tx_out, + .. + } = transaction_builder .add_output( value - change_value - Mob::MINIMUM_FEE, &recipient, @@ -2740,7 +2762,7 @@ pub mod transaction_builder_tests { ); transaction_builder.add_input(input_credentials); - let (_burn_tx_out, _confirmation) = transaction_builder + transaction_builder .add_output(100, &burn_address(), &mut rng) .unwrap(); @@ -2783,7 +2805,10 @@ pub mod transaction_builder_tests { ); transaction_builder.add_input(input_credentials); - let (burn_output, _confirmation) = transaction_builder + let TxOutContext { + tx_out: burn_output, + .. + } = transaction_builder .add_output(110, &burn_address(), &mut rng) .unwrap(); @@ -2839,7 +2864,10 @@ pub mod transaction_builder_tests { ); transaction_builder.add_input(input_credentials); - let (burn_tx_out, _confirmation) = transaction_builder + let TxOutContext { + tx_out: burn_tx_out, + .. + } = transaction_builder .add_output(100, &burn_address(), &mut rng) .unwrap();