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

feat!: re-do partial notes #12391

Draft
wants to merge 8 commits into
base: master
Choose a base branch
from
Draft

feat!: re-do partial notes #12391

wants to merge 8 commits into from

Conversation

nventuro
Copy link
Contributor

Closes #9375.

This re-implements partial notes leveraging the work from #12122. We now emit a private log with all of the fields plus a 'public log completion tag', which is the tag of the public log that will contain the public fields. These two logs are merged when doing discovery, resulting in the note's packed representation.

All in all this means we need to store much less information in public storage (just one field), and we don't need to deal with publishing public logs with encrypted public content. It also removes a lot of PXE code that dealt with the destructuring of these logs, slicing off the public fields, etc. Once this is merged, moving decryption to NR should be trivial.

I iterated a bit on how the note structs are laid out and thing the current version is a reasonably good starting point. Eventually we'll autogenerate it via macros, but given we may want to introduce further changes I chose to not worry about that for now.

We're currently sort of hackily relying on the fact that note type ids are 7 bits long, and set the 8th bit to indicate the log is that of a partial note. Fixing this requires properly supporting events during log discovery (which would become message discovery), but that's out of scope for this PR.

@@ -1,25 +1,320 @@
use aztec::{macros::notes::partial_note, oracle::random::random, prelude::AztecAddress};
use dep::aztec::{
Copy link
Contributor Author

@nventuro nventuro Feb 28, 2025

Choose a reason for hiding this comment

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

This file is a copy-paste of uint_note.nr except using field instead of u128. Read that one instead.

Comment on lines +150 to +157
let encrypted_log = default_aes128::note::compute_log(
*context,
private_log_content,
storage_slot,
recipient,
sender,
);
context.emit_private_log(encrypted_log);

Choose a reason for hiding this comment

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

is there a way of not-choosing to use default_aes128 encryption strategy here?
can the fn partial have as input an encryption method?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

As of today, encryption is hardcoded in PXE to be AES. We'll soon move it into aztec-nr, at which point it'd be possible to somehow configure which encryption algorithm the contracts wishes to use. But this is just a first step, so it'll take a while to get there. Keep in mind this is the very first attempt to do this this alternative way. We'd similarly want to allow for unconstrained encryption etc.

Choose a reason for hiding this comment

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

this file imports encrypted_logs::log_assembly_strategies::default_aes128::note::encode_and_encrypt_note but could be using other encryption strategy, are both partial notes and full notes processed independently? (could they work with different setups?)

quote {
impl aztec::event::event_interface::EventInterface<$content_len> for $name {
fn get_event_type_id() -> aztec::protocol_types::abis::event_selector::EventSelector {
aztec::protocol_types::abis::event_selector::EventSelector::from_field($event_type_id)
$from_field($event_type_id)
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This was creating warnings and bothering me, so I fixed it in true @benesjan style

Copy link
Contributor

Choose a reason for hiding this comment

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

I feel attacked

Copy link
Contributor

@benesjan benesjan left a comment

Choose a reason for hiding this comment

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

Cute! LGTM

typ.get_trait_impl(trait_constraint).unwrap().methods().filter(|m| m.name() == target_method)[0]
typ.get_trait_impl(trait_constraint).expect(f"Type does not implement trait").methods().filter(
|m| m.name() == target_method,
)[0]
Copy link
Contributor

Choose a reason for hiding this comment

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

There is another copy of get_trait_impl_method in protocol-circuits-types. Makes sense to copy this change over there as well.

impl NoteHash for UintNote {
fn compute_note_hash(self, storage_slot: Field) -> Field {
// Partial notes can be implemented by having the note hash be either the result of multiscalar multiplication
// (MSM), or two rounds of poseidon. MSM results in more constraints and is only required when multiple variants
Copy link
Contributor

Choose a reason for hiding this comment

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

Interesting. Do you know the resulting constraint difference here?

It's cool that this is so much simpler than fiddling with generators and MSM.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

iirc msm is ~3k, and poseidon should be ~500.


NFT::at(context.this_address())._store_nft_set_partial_note(partial_note).enqueue(context);

partial_note
}
Copy link
Contributor

@benesjan benesjan Mar 3, 2025

Choose a reason for hiding this comment

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

Fanstastic how concise ^ this has become.

) {
context.storage_write(slot, point);
context.storage_write(slot + aztec::protocol_types::point::POINT_LENGTH as Field, setup_log);
fn _store_nft_set_partial_note(partial_note: PartialNFTNote) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Do we still have some plan down the pipeline to somehow get rid of this public call?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

No, best thing we could do is have the library automatically inject it.

@benesjan benesjan force-pushed the nv/redo-partial branch 2 times, most recently from c6fc6cb to 106ce57 Compare March 3, 2025 15:40
Copy link
Contributor

benesjan commented Mar 3, 2025

This stack of pull requests is managed by Graphite. Learn more about stacking.

@benesjan benesjan force-pushed the nv/redo-partial branch 2 times, most recently from fedae6d to 2a9675f Compare March 3, 2025 17:41
@benesjan benesjan marked this pull request as draft March 3, 2025 19:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Avoid the need for defining setup log length manually
3 participants