Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: add partial note support for value note #8141

Merged
Merged
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
82 changes: 81 additions & 1 deletion noir-projects/aztec-nr/value-note/src/value_note.nr
Original file line number Diff line number Diff line change
@@ -1,16 +1,23 @@
use dep::aztec::{
generators::{Ga1 as G_amt, Ga2 as G_npk, Ga3 as G_rnd, G_slot},
protocol_types::{
address::AztecAddress, traits::{Deserialize, Serialize}, constants::GENERATOR_INDEX__NOTE_NULLIFIER,
hash::poseidon2_hash_with_separator
hash::poseidon2_hash_with_separator, point::{Point, POINT_LENGTH}
},
note::{note_header::NoteHeader, note_interface::NoteInterface, utils::compute_note_hash_for_nullify},
oracle::unsafe_rand::unsafe_rand, keys::getters::get_nsk_app, context::PrivateContext
};
use dep::std::{embedded_curve_ops::multi_scalar_mul, hash::from_field_unsafe};

global VALUE_NOTE_LEN: Field = 3; // 3 plus a header.
// VALUE_NOTE_LEN * 32 + 32(storage_slot as bytes) + 32(note_type_id as bytes)
global VALUE_NOTE_BYTES_LEN: Field = 3 * 32 + 64;

trait OwnedNote {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I implement this to keep parity with tokennote.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's fine to have this as a temporary standin as the thing gets replaced, but ultimately this trait is unecessary and we should remove it eventually.

fn new(amount: U128, owner_npk_m_hash: Field) -> Self;
fn get_amount(self) -> U128;
}

// docs:start:value-note-def
#[aztec(note)]
struct ValueNote {
Expand Down Expand Up @@ -46,6 +53,22 @@ impl NoteInterface<VALUE_NOTE_LEN, VALUE_NOTE_BYTES_LEN> for ValueNote {
GENERATOR_INDEX__NOTE_NULLIFIER as Field,
)
}

fn compute_note_hiding_point(self) -> Point {
// We use the unsafe version because the multi_scalar_mul will constrain the scalars.
let amount_scalar = from_field_unsafe(self.value);
let npk_m_hash_scalar = from_field_unsafe(self.npk_m_hash);
let randomness_scalar = from_field_unsafe(self.randomness);
let slot_scalar = from_field_unsafe(self.header.storage_slot);
// We compute the note hiding point as:
// `G_amt * amount + G_npk * npk_m_hash + G_rnd * randomness + G_slot * slot`
// instead of using pedersen or poseidon2 because it allows us to privately add and subtract from amount
// in public by leveraging homomorphism.
multi_scalar_mul(
[G_amt, G_npk, G_rnd, G_slot],
[amount_scalar, npk_m_hash_scalar, randomness_scalar, slot_scalar]
)
}
}

impl ValueNote {
Expand All @@ -54,6 +77,12 @@ impl ValueNote {
let header = NoteHeader::empty();
ValueNote { value, npk_m_hash, randomness, header }
}

// TODO: Merge this func with `compute_note_hiding_point`. I (benesjan) didn't do it in the initial PR to not have
// to modify macros and all the related funcs in it.
fn to_note_hiding_point(self) -> ValueNoteHidingPoint {
ValueNoteHidingPoint::new(self.compute_note_hiding_point())
}
}

impl Serialize<7> for ValueNote {
Expand All @@ -75,3 +104,54 @@ impl Eq for ValueNote {
(self.randomness == other.randomness)
}
}

impl OwnedNote for ValueNote {
fn new(value: U128, owner_npk_m_hash: Field) -> Self {
Self {
value: value.to_field(),
npk_m_hash: owner_npk_m_hash,
randomness: unsafe_rand(),
header: NoteHeader::empty(),
}
}

fn get_amount(self) -> U128 {
U128::from_field(self.value)
}
}

struct ValueNoteHidingPoint {
inner: Point
}

impl ValueNoteHidingPoint {
fn new(point: Point) -> Self {
Self { inner: point }
}

fn add_value(&mut self, value: U128) {
self.inner = multi_scalar_mul([G_amt], [from_field_unsafe(value.to_integer())]) + self.inner;
}

fn add_npk_m_hash(&mut self, npk_m_hash: Field) {
self.inner = multi_scalar_mul([G_npk], [from_field_unsafe(npk_m_hash)]) + self.inner;
}

fn add_randomness(&mut self, randomness: Field) {
self.inner = multi_scalar_mul([G_rnd], [from_field_unsafe(randomness)]) + self.inner;
}

fn add_slot(&mut self, slot: Field) {
self.inner = multi_scalar_mul([G_slot], [from_field_unsafe(slot)]) + self.inner;
}

fn finalize(self) -> Field {
self.inner.x
}
}

impl Serialize<POINT_LENGTH> for ValueNoteHidingPoint {
fn serialize(self) -> [Field; POINT_LENGTH] {
self.inner.serialize()
}
}
Loading