-
Notifications
You must be signed in to change notification settings - Fork 151
/
utils.nr
72 lines (62 loc) · 3.23 KB
/
utils.nr
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
use dep::aztec::prelude::{AztecAddress, PrivateContext, PrivateSet, NoteGetterOptions};
use dep::aztec::note::note_getter_options::SortOrder;
use crate::{filter::filter_notes_min_sum, value_note::{ValueNote, VALUE_NOTE_LEN}};
// Sort the note values (0th field) in descending order.
// Pick the fewest notes whose sum is equal to or greater than `amount`.
pub fn create_note_getter_options_for_decreasing_balance(amount: Field) -> NoteGetterOptions<ValueNote, VALUE_NOTE_LEN, Field> {
NoteGetterOptions::with_filter(filter_notes_min_sum, amount).sort(ValueNote::properties().value, SortOrder.DESC)
}
// Creates a new note for the recipient.
// Inserts it to the recipient's set of notes.
pub fn increment(balance: PrivateSet<ValueNote>, amount: Field, recipient: AztecAddress) {
let mut note = ValueNote::new(amount, recipient);
// Insert the new note to the owner's set of notes and emit the log if value is non-zero.
balance.insert(&mut note, amount != 0);
}
// Find some of the `owner`'s notes whose values add up to the `amount`.
// Remove those notes.
// If the value of the removed notes exceeds the requested `amount`, create a new note containing the excess value, so that exactly `amount` is removed.
// Fail if the sum of the selected notes is less than the amount.
pub fn decrement(balance: PrivateSet<ValueNote>, amount: Field, owner: AztecAddress) {
let sum = decrement_by_at_most(balance, amount, owner);
assert(sum == amount, "Balance too low");
}
// Similar to `decrement`, except that it doesn't fail if the decremented amount is less than max_amount.
// The motivation behind this function is that there is an upper-bound on the number of notes a function may
// read and nullify. The requested decrementation `amount` might be spread across too many of the `owner`'s
// notes to 'fit' within this upper-bound, so we might have to remove an amount less than `amount`. A common
// pattern is to repeatedly call this function across many function calls, until enough notes have been nullified to
// equal `amount`.
//
// It returns the decremented amount, which should be less than or equal to max_amount.
pub fn decrement_by_at_most(
balance: PrivateSet<ValueNote>,
max_amount: Field,
owner: AztecAddress
) -> Field {
let options = create_note_getter_options_for_decreasing_balance(max_amount);
let opt_notes = balance.get_notes(options);
let mut decremented = 0;
for i in 0..opt_notes.len() {
if opt_notes[i].is_some() {
decremented += destroy_note(balance, owner, opt_notes[i].unwrap_unchecked());
}
}
// Add the change value back to the owner's balance.
let mut change_value = 0;
if max_amount.lt(decremented) {
change_value = decremented - max_amount;
decremented -= change_value;
}
increment(balance, change_value, owner);
decremented
}
// Removes the note from the owner's set of notes.
// Returns the value of the destroyed note.
pub fn destroy_note(balance: PrivateSet<ValueNote>, owner: AztecAddress, note: ValueNote) -> Field {
// Ensure the note is actually owned by the owner (to prevent user from generating a valid proof while
// spending someone else's notes).
assert(note.owner.eq(owner));
balance.remove(note);
note.value
}