-
Notifications
You must be signed in to change notification settings - Fork 111
Transcript API #1501
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
Transcript API #1501
Conversation
3acebd9
to
e9a54b0
Compare
e9a54b0
to
ea49ed3
Compare
cryptography/src/transcript.rs
Outdated
} | ||
|
||
fn flush(&mut self) { | ||
let (n, bytes) = encode_u64(self.pending); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Recommend just using U64
: https://github.com/commonwarexyz/monorepo/blob/main/utils/src/sequence/u64.rs
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I intentionally wanted to avoid encoding the length as a full 8 bytes, because that's a lot of overhead for small messages.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm pretty sure the code as-written is the same as self.hasher.update(UInt(self.pending).encode).as_ref()); However, it seems you are doing this to avoid a heap allocation (?) Related to #1507
I would probably just stick with what's clearer for now (possible heap allocation)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I intentionally wanted to avoid encoding the length as a full 8 bytes, because that's a lot of overhead for small messages.
Curious how much overhead this actually ends up being? When running on a 64-bit machine, seems like this would get padded up anyways (not to mention you avoid the extra work of encoding a varint)?
If you were ok with u64, it would just look like this (avoids the heap as well):
fn flush(&mut self) {
self.hasher.update(&self.pending.encode_fixed::<8>());
self.pending = 0;
}
I would probably just stick with what's clearer for now (possible heap allocation)
If you do want to keep UInt, I echo Brendan's point that we should try to use codec
directly for this (or put up a preliminary PR that allows you to take it to a level of efficiency you are happy with).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well, we are using codec
by virtue of using Write
, which Encode
requires as a super trait.
cryptography/src/transcript.rs
Outdated
} | ||
|
||
fn flush(&mut self) { | ||
let (n, bytes) = encode_u64(self.pending); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm pretty sure the code as-written is the same as self.hasher.update(UInt(self.pending).encode).as_ref()); However, it seems you are doing this to avoid a heap allocation (?) Related to #1507
I would probably just stick with what's clearer for now (possible heap allocation)
cryptography/src/transcript.rs
Outdated
self | ||
} | ||
|
||
/// Like [Self::commit], except that subsequent calls are considered part of the same message. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
clarity:
- subsequent calls to what? Maybe: "...
append
andcommit
are considered part of the same message until the end of the nextcommit
call." (?0 - Mention that no other functions (besides append) can be called until
commit
is called, otherwise it will panic
pub fn noise(&self, label: &'static [u8]) -> impl CryptoRngCore { | ||
let mut out = Self::start(StartTag::Noise, Some(self.summarize().hash.as_bytes())); | ||
out.commit(label); | ||
Rng::new(out.hasher.finalize_xof()) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
finalizing twice (once in summarize
and once in finalize_xof
) seems a bit inefficient, so I considered recommending doing self.hasher.clone()
and doing something with that, but I realize that creates kind of a minefield for possible collisions. So maybe the way your doing it is safest
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Another possibility is adding in an EndTag
which would get appended right before calling hasher.finalize (or finalize_xof). Then you could distinguish between summarize
and noise
without an additional compression function call.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
On a second look, this seems unavoidable if you want to keep &self
, because you can't write in the label without modifying the state, and what you want to do instead is initialize a new hash object. I've pushed a commit which makes initialization take an optional Summary instead, to be used as the key, but you still need to commit the data to this new keyed hash function.
This allows us to use the `rand_core::CryptoRngCore` trait alias, which is very convenient.
Closes #1483 This creates a minimal API for cryptographic Transcripts. This is useful for hashing, particularly in cases where we want some kind of hash, but don't need to conform to a particular specification, and want to avoid footguns around message sequencing, length extension, etc.
ea49ed3
to
c336372
Compare
This makes it so that the inner method for initializating a transcript will always take an Option key, either creating a normal hash, or a keyed hash.
@BrendanChou did a pass on your review comments! |
28cbe0e
to
cb142c9
Compare
cb142c9
to
ba7d32e
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Small nit on mod
comment?
/// The namespace serves to disamiguate two transcripts, so that even if they record | ||
/// the same information, the results will be different: | ||
/// ``` | ||
/// # use commonware_cryptography::transcript::Transcript; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
TIL
Codecov Report❌ Patch coverage is
@@ Coverage Diff @@
## main #1501 +/- ##
========================================
Coverage 92.06% 92.07%
========================================
Files 283 284 +1
Lines 73182 73354 +172
========================================
+ Hits 67377 67540 +163
- Misses 5805 5814 +9
... and 2 files with indirect coverage changes Continue to review full report in Codecov by Sentry.
🚀 New features to boost your workflow:
|
c.f. #1483