More verbose and stricter transcripts.#60
Conversation
|
|
||
| /// Errors when validating a transcript. | ||
| #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash, Error)] | ||
| pub enum TranscriptError { |
There was a problem hiding this comment.
I like this, this was clearly missing and the previous way of doing things made identifying and generalizing errors difficult because if I'm not mistaken, before that, errors in the domain separator were just strings
| // #[cfg(feature = "serde-postcard")] | ||
| // /// Use [`zerocopy`] to convert types to/from bytes. | ||
| // pub mod zerocopy; | ||
|
|
spongefish/src/transcript/mod.rs
Outdated
| } | ||
|
|
||
| /// Extension trait for [`Transcript`]. | ||
| pub trait TranscriptExt { |
There was a problem hiding this comment.
If this is an extension trait, shouldn't it look like this?
| pub trait TranscriptExt { | |
| pub trait TranscriptExt: Transcript { |
spongefish/src/transcript/mod.rs
Outdated
| /// Begin of a hint interaction. | ||
| fn begin_hint<T>(&mut self, label: &'static str) -> Result<(), Self::Error>; | ||
|
|
||
| /// End of a hint interaction.. |
There was a problem hiding this comment.
| /// End of a hint interaction.. | |
| /// End of a hint interaction. |
spongefish/src/transcript/mod.rs
Outdated
| /// End of a hint interaction.. | ||
| fn end_hint<T>(&mut self, label: &'static str) -> Result<(), Self::Error>; | ||
|
|
||
| /// Begin of a challenge interaction.. |
There was a problem hiding this comment.
| /// Begin of a challenge interaction.. | |
| /// Begin of a challenge interaction. |
spongefish/src/transcript/mod.rs
Outdated
| /// Begin of a challenge interaction.. | ||
| fn begin_challenge<T>(&mut self, label: &'static str) -> Result<(), Self::Error>; | ||
|
|
||
| /// End of a challenge interaction.. |
There was a problem hiding this comment.
| /// End of a challenge interaction.. | |
| /// End of a challenge interaction. |
spongefish/src/codecs/zerocopy.rs
Outdated
| pub trait ZeroCopyPattern<T>: Transcript { | ||
| fn message(&mut self, label: &'static str) -> Result<(), Self::Error>; | ||
| fn hint(&mut self, label: &'static str) -> Result<(), Self::Error>; | ||
| fn challenge(&mut self, label: &'static str) -> Result<(), Self::Error>; | ||
| } | ||
|
|
||
| pub trait ZeroCopyMessageProver<T: Immutable + IntoBytes>: Transcript { | ||
| fn message(&mut self, label: &'static str, value: &T) -> Result<(), Self::Error>; | ||
| } | ||
|
|
||
| pub trait ZeroCopyMessageVerifier<T: IntoBytes + FromBytes>: Transcript { | ||
| fn message(&mut self, label: &'static str) -> Result<T, Self::Error>; | ||
| } | ||
|
|
||
| pub trait ZeroCopyHintProver<T: Immutable + IntoBytes>: Transcript { | ||
| fn hint(&mut self, label: &'static str, value: &T) -> Result<(), Self::Error>; | ||
| } | ||
|
|
||
| pub trait ZeroCopyHintVerifier<T: IntoBytes + FromBytes>: Transcript { | ||
| fn hint(&mut self, label: &'static str) -> Result<T, Self::Error>; | ||
| } | ||
|
|
||
| pub trait ZeroCopyChallenge<T: IntoBytes + FromBytes>: Transcript { | ||
| fn challenge(&mut self, label: &'static str) -> Result<T, Self::Error>; | ||
| } |
There was a problem hiding this comment.
Maybe can we have a very small one line header doc for each to explain the principle for the reader to better understand
| pub trait BytesPattern { | ||
| fn add_bytes(&mut self, count: usize, label: &str); | ||
| fn hint(&mut self, label: &str); | ||
| fn challenge_bytes(&mut self, count: usize, label: &str); | ||
| } | ||
|
|
||
| pub trait BytesMessageProver { | ||
| fn message(&mut self, input: &[u8]) -> Result<(), DomainSeparatorMismatch>; | ||
| } | ||
|
|
||
| pub trait BytesMessageVerifier { | ||
| fn message(&mut self, output: &mut [u8]) -> Result<(), DomainSeparatorMismatch>; | ||
| } | ||
| pub trait BytesHintProver { | ||
| fn hint(&mut self, input: &[u8]) -> Result<(), DomainSeparatorMismatch>; | ||
| } | ||
|
|
||
| pub trait BytesHintVerifier { | ||
| fn hint(&mut self, output: &mut [u8]) -> Result<(), DomainSeparatorMismatch>; | ||
| } | ||
|
|
||
| pub trait BytesChallenge { | ||
| fn challenge(&mut self, output: &mut [u8]) -> Result<(), DomainSeparatorMismatch>; | ||
| } |
There was a problem hiding this comment.
Maybe a short header doc for each?
| pub enum InteractionKind { | ||
| /// A protocol containing mixed interactions. | ||
| Protocol, | ||
| /// A message send in-band from prover to verifier. |
There was a problem hiding this comment.
| /// A message send in-band from prover to verifier. | |
| /// A message sent in-band from prover to verifier. |
| Protocol, | ||
| /// A message send in-band from prover to verifier. | ||
| Message, | ||
| /// A hint send out-of-band from prover to verifier. |
There was a problem hiding this comment.
| /// A hint send out-of-band from prover to verifier. | |
| /// A hint sent out-of-band from prover to verifier. |
| Challenge, | ||
| } | ||
|
|
||
| /// Kinds of prover-verifier interactions |
There was a problem hiding this comment.
Here the header comment should be different that the one for InteractionKind no?
| Challenge, | ||
| } | ||
|
|
||
| /// Kinds of prover-verifier interactions |
There was a problem hiding this comment.
| /// Kinds of prover-verifier interactions | |
| /// Where in the transcript the interaction sits relative to other actions. |
| pattern: Arc<TranscriptPattern>, | ||
| /// Current position in the interaction pattern. | ||
| position: usize, | ||
| /// Wheter the transcript playback has been finalized. |
There was a problem hiding this comment.
| /// Wheter the transcript playback has been finalized. | |
| /// Whether the transcript playback has been finalized. |
| default = [] | ||
| default = ["arkworks-algebra", "arkworks-rand", "zerocopy"] | ||
| arkworks-rand = [ | ||
| # Workaround to also implement arkworks version of rand as exported by ark_std |
There was a problem hiding this comment.
This one should solve this no? arkworks-rs/std#60
spongefish/src/prover/mod.rs
Outdated
| /// [`ProverState`] does not implement [`Clone`] or [`Copy`] to prevent accidental leaks. | ||
| #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] |
There was a problem hiding this comment.
Here the fact that we derive Clone seems contradictory with the comment just above no?
There was a problem hiding this comment.
Yes, Cloneing the prover state is a footgun, why is this needed?
There was a problem hiding this comment.
I'm following the Rust API Guideline C-COMMON-TRAITS here.
Is the concern here that the user may forget to Zeroize the clones causing them to potentially live longer in memory than necessary?
There was a problem hiding this comment.
it's because if the prover is erroneously copied by the user down the line, and the proof system satisfies special soundness, an adversary can extract the witness. See e.g. https://media.ccc.de/v/27c3-4087-en-console_hacking_2010 around minute 37
|
|
||
| impl<R: RngCore + CryptoRng> CryptoRng for ProverRng<R> {} | ||
|
|
||
| /// Implements the version of `rand` arkworks usses |
There was a problem hiding this comment.
| /// Implements the version of `rand` arkworks usses | |
| /// Implements the version of `rand` arkworks uses |
| #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)] | ||
| pub enum Hierarchy { | ||
| /// A single interaction. | ||
| Atomic, | ||
| /// Start of a sub-protocol. | ||
| Begin, | ||
| /// End of a sub-protocol. | ||
| End, | ||
| } |
There was a problem hiding this comment.
Here maybe this could be useful to have an implementation like
impl Hierarchy {
/// Returns true if this is an atomic (single) interaction.
pub fn is_atomic(&self) -> bool {
matches!(self, Hierarchy::Atomic)
}
/// Returns true if this marks the beginning of a sub-protocol.
pub fn is_begin(&self) -> bool {
matches!(self, Hierarchy::Begin)
}
/// Returns true if this marks the end of a sub-protocol.
pub fn is_end(&self) -> bool {
matches!(self, Hierarchy::End)
}
}| length: Length, | ||
| ) -> Result<(), Self::Error>; | ||
|
|
||
| /// Begin of a subprotocol. |
There was a problem hiding this comment.
| /// Begin of a subprotocol. | |
| /// Beginning of a subprotocol. |
| self.end::<T>(label, Kind::Protocol, Length::None) | ||
| } | ||
|
|
||
| /// Begin of a message interaction. |
There was a problem hiding this comment.
| /// Begin of a message interaction. | |
| /// Beginning of a message interaction. |
| self.end::<T>(label, Kind::Message, length) | ||
| } | ||
|
|
||
| /// Begin of a hint interaction. |
There was a problem hiding this comment.
| /// Begin of a hint interaction. | |
| /// Beginning of a hint interaction. |
| self.end::<T>(label, Kind::Hint, length) | ||
| } | ||
|
|
||
| /// Begin of a challenge interaction.. |
There was a problem hiding this comment.
| /// Begin of a challenge interaction.. | |
| /// Beginning of a challenge interaction. |
| self.begin::<T>(label, Kind::Challenge, length) | ||
| } | ||
|
|
||
| /// End of a challenge interaction.. |
There was a problem hiding this comment.
| /// End of a challenge interaction.. | |
| /// End of a challenge interaction. |
spongefish/src/prover/mod.rs
Outdated
| assert_ne!(buf, [0; 8]); | ||
| } | ||
|
|
||
| // #[test] |
There was a problem hiding this comment.
Please either add these tests or remove them
There was a problem hiding this comment.
Of course! Once the approach and traits are stabilized I'll make the tests work again. Right now everything is still in flux.
|
Hi @recmo, thank you so so much for this incredible work! For me this is starting to become really too big to review. Is there any chance you can split it into multiple PR's? Here's some examples that would make sense:
If that helps, we could schedule a call (potentially with @WizardOfMenlo) for speeding things up and not slow you down? |
Make transcripts stricter by:
TypeIdtype_name.This addresses #6.
It's still a work in progress.