[−][src]Struct merlin::Transcript
A transcript of a public-coin argument.
The prover's messages are added to the transcript using commit_bytes
,
and the verifier's challenges can be computed using challenge_bytes
.
Creating and using a Merlin transcript
To create a Merlin transcript, use Transcript::new()
. This
function takes a domain separation label which should be unique to
the application. To use the transcript with a Merlin-based proof
implementation, the prover's side creates a Merlin transcript with
an application-specific domain separation label, and passes a
&mut
reference to the transcript to the proving function(s). To
verify the resulting proof, the verifier creates their own Merlin
transcript using the same domain separation label, then passes a
&mut
reference to the verifier's transcript to the verification
function.
Implementing proofs using Merlin
Implementations of proof protocols should take a &mut Transcript
as a parameter, not construct one internally. This provides
three benefits:
-
It forces the API client to initialize their own transcript using
Transcript::new()
. Since that function takes a domain separation string, this ensures that all proofs are domain-separated, not just with a proof-specific domain separator, but also with a per-application domain separator. -
It ensures that protocols are sequentially composable, by running them on a common transcript. (Since transcript instances are domain-separated, it should not be possible to extract a sub-protocol's challenges and commitments as a standalone proof).
-
It allows API clients to commit contextual data to the proof transcript prior to running the protocol, allowing them to bind proof statements to arbitrary application data.
Defining protocol behaviour with extension traits
This API is byte-oriented, while an actual protocol likely requires typed data — for instance, a protocol probably wants to receive challenge scalars, not challenge bytes. The recommended way to bridge this abstraction gap is to define a protocol-specific extension trait.
For instance, consider a discrete-log based protocol which commits to Ristretto points and requires challenge scalars for the Ristretto group. This protocol can define a protocol-specific extension trait in its crate as follows:
extern crate curve25519_dalek; use curve25519_dalek::ristretto::RistrettoPoint; use curve25519_dalek::ristretto::CompressedRistretto; use curve25519_dalek::scalar::Scalar; extern crate merlin; use merlin::Transcript; trait TranscriptProtocol { fn domain_sep(&mut self); fn commit_point(&mut self, label: &'static [u8], point: &CompressedRistretto); fn challenge_scalar(&mut self, label: &'static [u8]) -> Scalar; } impl TranscriptProtocol for Transcript { fn domain_sep(&mut self) { self.commit_bytes(b"dom-sep", b"TranscriptProtocol Example"); } fn commit_point(&mut self, label: &'static [u8], point: &CompressedRistretto) { self.commit_bytes(label, point.as_bytes()); } fn challenge_scalar(&mut self, label: &'static [u8]) -> Scalar { let mut buf = [0; 64]; self.challenge_bytes(label, &mut buf); Scalar::from_bytes_mod_order_wide(&buf) } } fn example(transcript: &mut Transcript, A: &RistrettoPoint, B: &RistrettoPoint) { // Since the TranscriptProtocol trait is in scope, the extension // methods are available on the `transcript` object: transcript.domain_sep(); transcript.commit_point(b"A", &A.compress()); transcript.commit_point(b"B", &B.compress()); let c = transcript.challenge_scalar(b"c"); // ... }
Now, the implementation of the protocol can use the domain_sep
to add domain separation to an existing &mut Transcript
, and
then call the commit_point
and challenge_scalar
methods,
rather than calling commit_bytes
and
challenge_bytes
directly.
However, because the protocol-specific behaviour is defined in a
protocol-specific trait, different protocols can use the same
Transcript
instance without imposing any extra type constraints.
Methods
impl Transcript
[src]
pub fn new(label: &'static [u8]) -> Transcript
[src]
Initialize a new transcript with the supplied label
, which
is used as a domain separator.
Note
This function should be called by a protocol's API consumer, and not by the protocol implementation. See above for details.
Implementation
Initializes a STROBE-128 context with a Merlin domain-separator label, then commits the user-supplied label using the STROBE operations
meta-AD( b"dom-sep" || LE32(label.len()) );
AD( label );
pub fn commit_bytes(&mut self, label: &'static [u8], message: &[u8])
[src]
Commit a prover's message
to the transcript.
The label
parameter is metadata about the message, and is
also committed to the transcript.
Implementation
Performs the STROBE operations
meta-AD( label || LE32(message.len()) );
AD( message );
pub fn commit_u64(&mut self, label: &'static [u8], x: u64)
[src]
Convenience method for committing a u64
to the transcript.
The label
parameter is metadata about the message, and is
also committed to the transcript.
Implementation
Calls commit_bytes
with the little-endian encoding of x
.
pub fn challenge_bytes(&mut self, label: &'static [u8], dest: &mut [u8])
[src]
Fill the supplied buffer with the verifier's challenge bytes.
The label
parameter is metadata about the challenge, and is
also committed to the transcript.
Implementation
Performs the STROBE operations
meta-AD( label || LE32(dest.len()) );
dest <- PRF();
pub fn build_rng(&self) -> TranscriptRngBuilder
[src]
Fork the current Transcript
to construct an RNG whose output is bound
to the current transcript state as well as prover's secrets.
See the TranscriptRngBuilder
documentation for more details.
Trait Implementations
impl Clone for Transcript
[src]
fn clone(&self) -> Transcript
[src]
fn clone_from(&mut self, source: &Self)
1.0.0[src]
Performs copy-assignment from source
. Read more
Auto Trait Implementations
impl Send for Transcript
impl Sync for Transcript
Blanket Implementations
impl<T> From for T
[src]
impl<T, U> Into for T where
U: From<T>,
[src]
U: From<T>,
impl<T> ToOwned for T where
T: Clone,
[src]
T: Clone,
impl<T, U> TryFrom for T where
U: Into<T>,
[src]
U: Into<T>,
type Error = !
try_from
)The type returned in the event of a conversion error.
fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>
[src]
impl<T> Borrow for T where
T: ?Sized,
[src]
T: ?Sized,
impl<T> Any for T where
T: 'static + ?Sized,
[src]
T: 'static + ?Sized,
impl<T> BorrowMut for T where
T: ?Sized,
[src]
T: ?Sized,
fn borrow_mut(&mut self) -> &mut T
[src]
impl<T, U> TryInto for T where
U: TryFrom<T>,
[src]
U: TryFrom<T>,