tapir/primitives/transcript.go

52 lines
1.7 KiB
Go

package primitives
import (
"fmt"
"golang.org/x/crypto/sha3"
"hash"
)
// Transcript implements a transcript of a public coin argument.
//
// We have the following goals:
// - Provide a consisted transcript API for our zero knowledge protocols
// - Allow sequential proofs over a common transcript (ensuring a single proof cannot be extracted standalone)
// - produce an auditable human-readable transcript.
//
// The design of this API was inspired by Merlin: https://docs.rs/crate/merlin/
//
// At some point we might want to extend this to be compatible with Merlin transcripts, built on STROBE
type Transcript struct {
hash hash.Hash
transcript string
}
// NewTranscript creates a new Transcript with the given Label, the label should be unique to the application
func NewTranscript(label string) *Transcript {
transcript := new(Transcript)
transcript.hash = sha3.New256()
transcript.AddToTranscript("protocol", []byte(label))
return transcript
}
// AddToTranscript appends a value to the transcript with the given label
// This binds the given data to the label.
func (t *Transcript) AddToTranscript(label string, b []byte) {
op := fmt.Sprintf("%s (%d) %x;", label, len(b), b)
t.transcript = fmt.Sprintf("%v\n%v", t.transcript, op)
t.hash.Write([]byte(op))
}
// OutputTranscriptToAudit outputs a human-readable copy of the transcript so far.
func (t Transcript) OutputTranscriptToAudit() string {
return t.transcript
}
// CommitToTranscript generates a challenge based on the current transcript, it also commits the challenge to the transcript.
func (t *Transcript) CommitToTranscript(label string) []byte {
t.AddToTranscript("commit", []byte(label))
b := t.hash.Sum([]byte{})
t.AddToTranscript(label, b)
return b
}