dusk_wallet_core/notes/
owned.rs

1// This Source Code Form is subject to the terms of the Mozilla Public
2// License, v. 2.0. If a copy of the MPL was not distributed with this
3// file, You can obtain one at http://mozilla.org/MPL/2.0/.
4//
5// Copyright (c) DUSK NETWORK. All rights reserved.
6
7//! Provides functions and types to handle notes' ownership.
8
9use alloc::vec;
10use alloc::vec::Vec;
11use core::ops::Index;
12use core::slice::Iter;
13
14use bytecheck::CheckBytes;
15use dusk_core::transfer::phoenix::{NoteLeaf, SecretKey as PhoenixSecretKey};
16use dusk_core::BlsScalar;
17use rkyv::{Archive, Deserialize, Serialize};
18
19/// A collection of notes stored as key-value pairs.
20/// The key is a `BlsScalar` and the value is a `NoteLeaf`.
21/// Duplicates are allowed.
22#[derive(Default, Archive, Serialize, Deserialize, Debug, PartialEq, Clone)]
23#[archive_attr(derive(CheckBytes))]
24pub struct NoteList {
25    /// The underlying storage of key-value pairs where
26    /// `BlsScalar` is the key and `NoteLeaf` is the value.
27    entries: Vec<(BlsScalar, NoteLeaf)>,
28}
29
30impl NoteList {
31    /// Inserts a new key-value pair into the collection.
32    pub fn insert(&mut self, key: BlsScalar, value: NoteLeaf) {
33        self.entries.push((key, value));
34    }
35
36    /// Returns the number of entries (key-value pairs) in the collection.
37    #[must_use]
38    pub fn len(&self) -> usize {
39        self.entries.len()
40    }
41
42    /// Checks if the collection is empty.
43    #[must_use]
44    pub fn is_empty(&self) -> bool {
45        self.entries.is_empty()
46    }
47
48    /// Retrieves the value (`NoteLeaf`) associated with a given key
49    #[must_use]
50    pub fn get(&self, key: &BlsScalar) -> Option<&NoteLeaf> {
51        self.entries.iter().find(|(k, _)| k == key).map(|(_, v)| v)
52    }
53
54    /// Retrieves all keys in the collection.
55    #[must_use]
56    pub fn keys(&self) -> Vec<BlsScalar> {
57        self.entries.iter().map(|(k, _)| *k).collect()
58    }
59
60    /// Returns an iterator over the key-value pairs.
61    pub fn iter(&self) -> Iter<'_, (BlsScalar, NoteLeaf)> {
62        self.entries.iter()
63    }
64}
65
66impl Index<&BlsScalar> for NoteList {
67    type Output = NoteLeaf;
68
69    /// Retrieves the value (`NoteLeaf`) associated with a given key
70    /// (`BlsScalar`).
71    ///
72    /// Panics if the key is not found in the collection.
73    fn index(&self, index: &BlsScalar) -> &Self::Output {
74        self.get(index).expect("key not found")
75    }
76}
77
78impl<'a> IntoIterator for &'a NoteList {
79    type IntoIter = core::slice::Iter<'a, (BlsScalar, NoteLeaf)>;
80    type Item = &'a (BlsScalar, NoteLeaf);
81    fn into_iter(self) -> Self::IntoIter {
82        self.iter()
83    }
84}
85
86impl From<Vec<(BlsScalar, NoteLeaf)>> for NoteList {
87    fn from(entries: Vec<(BlsScalar, NoteLeaf)>) -> Self {
88        NoteList { entries }
89    }
90}
91
92/// Filter all notes and their block height that are owned by the given keys,
93/// mapped to their nullifiers.
94pub fn map(
95    keys: impl AsRef<[PhoenixSecretKey]>,
96    notes: impl AsRef<[NoteLeaf]>,
97) -> Vec<NoteList> {
98    notes.as_ref().iter().fold(
99        vec![NoteList::default(); keys.as_ref().len()],
100        |mut notes_maps, note_leaf| {
101            for (i, sk) in keys.as_ref().iter().enumerate() {
102                if sk.owns(note_leaf.note.stealth_address()) {
103                    let nullifier = note_leaf.note.gen_nullifier(sk);
104                    notes_maps[i].insert(nullifier, note_leaf.clone());
105                    break;
106                }
107            }
108            notes_maps
109        },
110    )
111}