-
Notifications
You must be signed in to change notification settings - Fork 240
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(Notes): Split get_note
into get_note
and get_note_unsafe
#4346
Comments
@LHerskind suggested that we could also extend the interface in other ways, for example by adding |
Permutations of scenarios are a mix and match of the following:
Hmm... I'm not sure if that's actually a helpful list. But having thought more, here is a hopefully-comprehensive list of methods that I think we should support:
In all cases, we should track in the context whether a note has been nullified already within the same function, and throw an error if it gets re-nullified. Barretenberg would allow us to do this without adding constraints, through non-circuit types. Maybe noir might have features to enable this? Footnote: |
get_note
into get_note
and get_note_unsafe
get_note
into get_note
and get_note_unsafe
Superceded by #7834. |
The discussion in #3123 and conversations with @LHerskind made me realize that our two big state variables,
Singleton
andSet
, behave very differently with reading notes despite having similar APIs.Set.get_notes()
simply reads a bunch of notes and returns them. The expectation is that these notes will be immediately consumed and nullified by callingremove()
. Indeed, this is how things likeBalanceSet
work. Failing to callremove()
introduces a security issue since nullifier non-inclusion will never be proved, and the burden of this call falls on the user ofSet
.Singleton.get_note()
reads a note, immediately nullifies it and creates a new one with the same value. This guarantees that the value read is not nullified andget_note()
is therefore always safe to use. However, this is often suboptimal: if the value was mean to be replaced with a different one then the nullification and re-creation insideget_note()
was redundant and unnecessary. (the kernels actually squash note creation followed by nullification, but we're still doing a lot of useless hashing)I think this behavior mismatch on such basic types can be extremely confusing to new users and easily lead to costly mistakes. But there's also good reasons why things are the way they are, and both current implementations are good things that should exist. I propose we take the learnings from each of these, more explicitly lay out potential pit falls, and address naming inconsistencies.
The plan is to have for both state variables a
get_note
variant that does what it says and is always safe (but might be suboptimal), and aget_note_unsafe
variant which, if you know what you're doing, can be used to produce better results while still remaining safe.For
Singleton
:get_note
would be the same as the current implementation. Example use case: some configuration value is read.get_note_unsafe
would not destroy the current note nor create a new one. Example use case: some value is read and then modified (as was being discussed in refactor: singleton redesign #3753).For
Set
:get_note
would remove all read notes from the set and then reinsert them. Example use case: some configuration values are proven to exist (e.g. a set of permissions).get_note_unsafe
would be the same as the current implementation. Example use case: a token balance in which read notes are consumed.The text was updated successfully, but these errors were encountered: