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: TransparentNote cleanup #5904

Merged
merged 1 commit into from
Apr 22, 2024
Merged
Show file tree
Hide file tree
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
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,14 @@ use dep::aztec::{

global TRANSPARENT_NOTE_LEN: Field = 2;

// Transparent note represents a note that is created in the clear (public execution),
// but can only be spent by those that know the preimage of the "secret_hash"
// Transparent note represents a note that is created in the clear (public execution), but can only be spent by those
// that know the preimage of the "secret_hash" (the secret). This is typically used when shielding a token balance.
// Owner of the tokens provides a "secret_hash" as an argument to the public "shield" function and then the tokens
// can be redeemed in private by presenting the preimage of the "secret_hash" (the secret).
#[aztec(note)]
struct TransparentNote {
amount: Field,
secret_hash: Field,
// the secret is just here for ease of use and won't be (de)serialized
secret: Field,
}

struct TransparentNoteProperties {
Expand All @@ -34,19 +34,27 @@ impl NoteInterface<TRANSPARENT_NOTE_LEN> for TransparentNote {
TransparentNote {
amount: serialized_note[0],
secret_hash: serialized_note[1],
secret: 0,
header: NoteHeader::empty(),
}
}

// TODO(https://github.com/AztecProtocol/aztec-packages/issues/1386): Ensure nullifier collisions are prevented
fn compute_nullifier(self, _context: &mut PrivateContext) -> Field {
self.compute_nullifier_without_context()
}

// Computing a nullifier in a transparent note is not guarded by making secret a part of the nullifier preimage (as
// is common in other cases) and instead is guarded by the functionality of "redeem_shield" function. There we do
// the following:
// 1) We pass the secret as an argument to the function and use it to compute a secret hash,
// 2) we fetch a note via the "get_notes" oracle which accepts the secret hash as an argument,
// 3) the "get_notes" oracle constrains that the secret hash in the returned note matches the one computed in
// circuit.
// This achieves that the note can only be spent by the party that knows the secret.
fn compute_nullifier_without_context(self) -> Field {
let siloed_note_hash = compute_note_hash_for_consumption(self);
// TODO(#1205) Should use a non-zero generator index.
pedersen_hash([self.secret, siloed_note_hash],0)
pedersen_hash([siloed_note_hash], 0)
}

fn broadcast(self, context: &mut PrivateContext, slot: Field) {
Expand All @@ -55,26 +63,12 @@ impl NoteInterface<TRANSPARENT_NOTE_LEN> for TransparentNote {
}

impl TransparentNote {

// CONSTRUCTORS

pub fn new(amount: Field, secret_hash: Field) -> Self {
TransparentNote { amount, secret_hash, secret: 0, header: NoteHeader::empty() }
}

// new oracle call primitive
// get me the secret corresponding to this hash
pub fn new_from_secret(amount: Field, secret: Field) -> Self {
TransparentNote { amount, secret_hash: compute_secret_hash(secret), secret, header: NoteHeader::empty() }
TransparentNote { amount, secret_hash, header: NoteHeader::empty() }
}

// CUSTOM FUNCTIONS FOR THIS NOTE TYPE

pub fn knows_secret(self, secret: Field) {
let hash = compute_secret_hash(secret);
assert(self.secret_hash == hash);
}

// Custom serialization forces us to manually create the metadata struct and its getter
pub fn properties() -> TransparentNoteProperties {
TransparentNoteProperties {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,14 @@ use dep::aztec::{

global TRANSPARENT_NOTE_LEN: Field = 2;

// Transparent note represents a note that is created in the clear (public execution),
// but can only be spent by those that know the preimage of the "secret_hash"
// Transparent note represents a note that is created in the clear (public execution), but can only be spent by those
// that know the preimage of the "secret_hash" (the secret). This is typically used when shielding a token balance.
// Owner of the tokens provides a "secret_hash" as an argument to the public "shield" function and then the tokens
// can be redeemed in private by presenting the preimage of the "secret_hash" (the secret).
#[aztec(note)]
struct TransparentNote {
amount: Field,
secret_hash: Field,
// the secret is just here for ease of use and won't be (de)serialized
secret: Field
}

struct TransparentNoteProperties {
Expand All @@ -34,19 +34,27 @@ impl NoteInterface<TRANSPARENT_NOTE_LEN> for TransparentNote {
TransparentNote {
amount: serialized_note[0],
secret_hash: serialized_note[1],
secret: 0,
header: NoteHeader::empty(),
}
}

// TODO(https://github.com/AztecProtocol/aztec-packages/issues/1386): Ensure nullifier collisions are prevented
fn compute_nullifier(self, _context: &mut PrivateContext) -> Field {
self.compute_nullifier_without_context()
}

// Computing a nullifier in a transparent note is not guarded by making secret a part of the nullifier preimage (as
// is common in other cases) and instead is guarded by the functionality of "redeem_shield" function. There we do
// the following:
// 1) We pass the secret as an argument to the function and use it to compute a secret hash,
// 2) we fetch a note via the "get_notes" oracle which accepts the secret hash as an argument,
// 3) the "get_notes" oracle constrains that the secret hash in the returned note matches the one computed in
// circuit.
// This achieves that the note can only be spent by the party that knows the secret.
fn compute_nullifier_without_context(self) -> Field {
let siloed_note_hash = compute_note_hash_for_consumption(self);
// TODO(#1205) Should use a non-zero generator index.
pedersen_hash([self.secret, siloed_note_hash],0)
pedersen_hash([siloed_note_hash], 0)
}

fn broadcast(self, context: &mut PrivateContext, slot: Field) {
Expand All @@ -55,26 +63,12 @@ impl NoteInterface<TRANSPARENT_NOTE_LEN> for TransparentNote {
}

impl TransparentNote {

// CONSTRUCTORS

pub fn new(amount: Field, secret_hash: Field) -> Self {
TransparentNote { amount, secret_hash, secret: 0, header: NoteHeader::empty() }
}

// new oracle call primitive
// get me the secret corresponding to this hash
pub fn new_from_secret(amount: Field, secret: Field) -> Self {
TransparentNote { amount, secret_hash: compute_secret_hash(secret), secret, header: NoteHeader::empty() }
TransparentNote { amount, secret_hash, header: NoteHeader::empty() }
}

// CUSTOM FUNCTIONS FOR THIS NOTE TYPE

pub fn knows_secret(self, secret: Field) {
let hash = compute_secret_hash(secret);
assert(self.secret_hash == hash);
}

// Custom serialization forces us to manually create the metadata struct and its getter
pub fn properties() -> TransparentNoteProperties {
TransparentNoteProperties {
Expand Down
Loading