diff --git a/wallet-core/src/ffi.rs b/wallet-core/src/ffi.rs index 86f64775fb..0e4a528f57 100644 --- a/wallet-core/src/ffi.rs +++ b/wallet-core/src/ffi.rs @@ -33,12 +33,20 @@ use core::{ptr, slice}; use dusk_bytes::Serializable; use execution_core::{ signatures::bls::PublicKey as BlsPublicKey, - transfer::phoenix::{NoteLeaf, PublicKey as PhoenixPublicKey}, + transfer::phoenix::{ + ArchivedNoteLeaf, NoteLeaf, PublicKey as PhoenixPublicKey, + }, + BlsScalar, }; use zeroize::Zeroize; use rkyv::to_bytes; +#[no_mangle] +static KEY_SIZE: usize = BlsScalar::SIZE; +#[no_mangle] +static ITEM_SIZE: usize = core::mem::size_of::(); + /// The size of the scratch buffer used for parsing the notes. const NOTES_BUFFER_SIZE: usize = 96 * 1024; @@ -89,10 +97,23 @@ pub unsafe fn map_owned( indexes: *const u8, notes_ptr: *const u8, owned_ptr: *mut *mut u8, + last_info_ptr: *mut [u8; 16], ) -> ErrorCode { + use core::cmp::max; + let keys = indexes_into_keys(seed, indexes, derive_phoenix_sk); let notes: Vec = mem::from_buffer(notes_ptr)?; + let (block_height, pos) = + notes + .iter() + .fold((0u64, 0u64), |(block_height, pos), leaf| { + ( + max(block_height, leaf.block_height), + max(pos, *leaf.note.pos()), + ) + }); + let owned = notes::owned::map(&keys, notes); keys.into_iter().for_each(|mut sk| sk.zeroize()); @@ -110,6 +131,16 @@ pub unsafe fn map_owned( ptr::copy_nonoverlapping(len.as_ptr(), ptr, 4); ptr::copy_nonoverlapping(bytes.as_ptr(), ptr.add(4), bytes.len()); + ptr::copy_nonoverlapping( + block_height.to_le_bytes().as_ptr(), + &mut (*last_info_ptr)[0], + 8, + ); + ptr::copy_nonoverlapping( + pos.to_le_bytes().as_ptr(), + &mut (*last_info_ptr)[8], + 8, + ); ErrorCode::Ok } diff --git a/wallet-core/src/notes/balance.rs b/wallet-core/src/notes/balance.rs index 2e05111004..5a4f345b16 100644 --- a/wallet-core/src/notes/balance.rs +++ b/wallet-core/src/notes/balance.rs @@ -19,6 +19,33 @@ pub fn calculate( vk: &PhoenixViewKey, notes: impl Iterator, ) -> TotalAmount +where + T: AsRef, +{ + let mut values: Vec = notes + .filter_map(|note| { + vk.owns(note.as_ref().stealth_address()) + .then_some(true) + .and(note.as_ref().value(Some(vk)).ok()) + }) + .collect(); + + values.sort_by(|a, b| b.cmp(a)); + + let spendable = values.iter().take(MAX_INPUT_NOTES).sum(); + let value = spendable + values.iter().skip(MAX_INPUT_NOTES).sum::(); + + TotalAmount { value, spendable } +} + +/// Calculate the sum for all the given [`Note`]s without +/// performing any ownership checks. The [`PhoenixViewKey`] +/// is used solely for decrypting the values of obfuscated +/// notes. +pub fn calculate_unchecked( + vk: &PhoenixViewKey, + notes: impl Iterator, +) -> TotalAmount where T: AsRef, {