Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
15 changes: 15 additions & 0 deletions dash-spv-ffi/src/callbacks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -731,6 +731,13 @@ impl FFIWalletEventCallbacks {
.map(|d| FFIOutputDetail {
index: d.index,
role: FFIOutputRole::from(d.role),
value: d.value,
address: match &d.address {
Some(addr) => {
CString::new(addr.to_string()).unwrap_or_default().into_raw()
}
None => std::ptr::null_mut(),
},
})
.collect();

Expand Down Expand Up @@ -784,6 +791,14 @@ impl FFIWalletEventCallbacks {
}
}
}
// Free the CString addresses from output details
for detail in output_details {
if !detail.address.is_null() {
unsafe {
drop(CString::from_raw(detail.address));
}
}
}
// SAFETY: Free the heap-allocated IS lock bytes produced by
// `From<TransactionContext>` after the callback returns.
if !islock_data.is_null() && islock_len > 0 {
Expand Down
25 changes: 19 additions & 6 deletions key-wallet-ffi/src/managed_account.rs
Original file line number Diff line number Diff line change
Expand Up @@ -791,6 +791,13 @@ pub unsafe extern "C" fn managed_core_account_get_transactions(
.map(|d| FFIOutputDetail {
index: d.index,
role: FFIOutputRole::from(d.role),
value: d.value,
address: match &d.address {
Some(addr) => {
std::ffi::CString::new(addr.to_string()).unwrap_or_default().into_raw()
}
None => std::ptr::null_mut(),
},
})
.collect::<Vec<_>>()
.into_boxed_slice();
Expand Down Expand Up @@ -841,12 +848,16 @@ pub unsafe extern "C" fn managed_core_account_free_transactions(
drop(Box::from_raw(slice as *mut [FFIInputDetail]));
}

// Free output details
// Free output detail addresses first, then the array
if !record.output_details.is_null() && record.output_details_count > 0 {
drop(Box::from_raw(std::ptr::slice_from_raw_parts_mut(
record.output_details,
record.output_details_count,
)));
let slice =
std::slice::from_raw_parts_mut(record.output_details, record.output_details_count);
for detail in slice.iter() {
if !detail.address.is_null() {
drop(std::ffi::CString::from_raw(detail.address));
}
}
drop(Box::from_raw(slice as *mut [FFIOutputDetail]));
}

// Free tx data
Expand Down Expand Up @@ -2027,7 +2038,7 @@ mod tests {
let addr = std::ffi::CString::new("XtestAddress123").unwrap();
let input_slice = vec![FFIInputDetail {
index: 0,
value: 100000,
value: 0,
address: addr.into_raw(),
}]
.into_boxed_slice();
Expand All @@ -2038,6 +2049,8 @@ mod tests {
let output_slice = vec![FFIOutputDetail {
index: 0,
role: FFIOutputRole::Received,
value: 0,
address: std::ptr::null_mut(),
}]
.into_boxed_slice();
r0.output_details_count = output_slice.len();
Expand Down
2 changes: 2 additions & 0 deletions key-wallet-ffi/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -930,6 +930,8 @@ pub struct FFIInputDetail {
pub struct FFIOutputDetail {
pub index: u32,
pub role: FFIOutputRole,
pub value: u64,
pub address: *mut c_char,
}

#[cfg(test)]
Expand Down
2 changes: 2 additions & 0 deletions key-wallet/src/managed_account/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -504,6 +504,8 @@ impl ManagedCoreAccount {
output_details.push(OutputDetail {
index: idx as u32,
role,
address: resolved_outputs[idx].clone(),
value: output.value,
});
}

Expand Down
4 changes: 4 additions & 0 deletions key-wallet/src/managed_account/transaction_record.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,10 @@ pub struct OutputDetail {
pub index: u32,
/// Role of this output from the wallet's perspective
pub role: OutputRole,
/// Decoded address (None for non-standard scripts)
pub address: Option<Address>,
/// Value in satoshis
pub value: u64,
}

/// Role of a transaction output from the wallet's perspective
Expand Down
Loading