Struct merlin::Transcript[][src]

pub struct Transcript { /* fields omitted */ }

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.

Usage

Implementations of proof protocols should take a &mut Transcript as a parameter, not construct one internally. This provides three benefits:

  1. 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.

  2. 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).

  3. 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 seperation 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]

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 );

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 );

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();

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]

Returns a copy of the value. Read more

Performs copy-assignment from source. Read more

Auto Trait Implementations

impl Send for Transcript

impl Sync for Transcript