use alloc::vec;
use alloc::vec::Vec;
use core::ops::Index;
use core::slice::Iter;
use bytecheck::CheckBytes;
use dusk_core::BlsScalar;
use dusk_core::transfer::phoenix::{NoteLeaf, SecretKey as PhoenixSecretKey};
use rkyv::{Archive, Deserialize, Serialize};
#[derive(Default, Archive, Serialize, Deserialize, Debug, PartialEq, Clone)]
#[archive_attr(derive(CheckBytes))]
pub struct NoteList {
entries: Vec<(BlsScalar, NoteLeaf)>,
}
impl NoteList {
pub fn insert(&mut self, key: BlsScalar, value: NoteLeaf) {
self.entries.push((key, value));
}
#[must_use]
pub fn len(&self) -> usize {
self.entries.len()
}
#[must_use]
pub fn is_empty(&self) -> bool {
self.entries.is_empty()
}
#[must_use]
pub fn get(&self, key: &BlsScalar) -> Option<&NoteLeaf> {
self.entries.iter().find(|(k, _)| k == key).map(|(_, v)| v)
}
#[must_use]
pub fn keys(&self) -> Vec<BlsScalar> {
self.entries.iter().map(|(k, _)| *k).collect()
}
pub fn iter(&self) -> Iter<'_, (BlsScalar, NoteLeaf)> {
self.entries.iter()
}
}
impl Index<&BlsScalar> for NoteList {
type Output = NoteLeaf;
fn index(&self, index: &BlsScalar) -> &Self::Output {
self.get(index).expect("key not found")
}
}
impl<'a> IntoIterator for &'a NoteList {
type IntoIter = core::slice::Iter<'a, (BlsScalar, NoteLeaf)>;
type Item = &'a (BlsScalar, NoteLeaf);
fn into_iter(self) -> Self::IntoIter {
self.iter()
}
}
impl From<Vec<(BlsScalar, NoteLeaf)>> for NoteList {
fn from(entries: Vec<(BlsScalar, NoteLeaf)>) -> Self {
NoteList { entries }
}
}
pub fn map(
keys: impl AsRef<[PhoenixSecretKey]>,
notes: impl AsRef<[NoteLeaf]>,
) -> Vec<NoteList> {
notes.as_ref().iter().fold(
vec![NoteList::default(); keys.as_ref().len()],
|mut notes_maps, note_leaf| {
for (i, sk) in keys.as_ref().iter().enumerate() {
if sk.owns(note_leaf.note.stealth_address()) {
let nullifier = note_leaf.note.gen_nullifier(sk);
notes_maps[i].insert(nullifier, note_leaf.clone());
break;
}
}
notes_maps
},
)
}