-
Notifications
You must be signed in to change notification settings - Fork 22
Description
It annoyed me that I can't append a transcript to a transcript, nor can I fork a transcript which I can then append (or... not append).
Either way, here's how to forking append a transcript, seems like an oversight that something like this isn't part of the library.
TL;DR the current .clone semantics don't capture tree structures, which are very useful. Forking a transcript is transcribed in both transcripts, as is appending a transcript to another one.
Really, the challenge should be bi-directional, the code below doesn't acknowledge which transcript the fork is joining when it's appended. So don't use it...
use merlin::Transcript;
pub trait TranscriptExt {
// Proposed method to fork a transcript
fn fork_transcript(&mut self) -> Transcript;
// Proposed method to append another transcript
fn append_transcript(&mut self, other: &mut Transcript);
}
impl TranscriptExt for Transcript {
fn fork_transcript(&mut self) -> Transcript {
// Generate a challenge to use as a label for the fork
let mut fork_label = [0u8; 32];
self.challenge_bytes(b"fork_label", &mut fork_label);
// Create a new transcript with the fork label
let mut forked_transcript = self.clone();
forked_transcript.append_message(b"forked_from", &fork_label);
forked_transcript
}
fn append_transcript(&mut self, other: &mut Transcript) {
// Use the challenge from the previous fork as a label
let mut append_label = [0u8; 32];
other.challenge_bytes(b"fork_challenge", &mut append_label);
// Append the entire transcript with this label
self.append_message(b"appended_transcript", &append_label);
}
}
fn main() {
// Example usage
let mut original_transcript = Transcript::new(b"protocol_context");
original_transcript.append_message(b"initial_message", b"data");
// Fork the transcript
let mut forked_transcript = original_transcript.fork_transcript();
forked_transcript.append_message(b"fork_specific_message", b"fork_data");
// Append another transcript
original_transcript.append_transcript(&mut forked_transcript);
}So you could use something like
fn append_transcript(&mut self, other: &mut Transcript) {
// Generate a challenge from the receiving transcript
let mut receiver_challenge = [0u8; 32];
self.challenge_bytes(b"append_receiver_challenge", &mut receiver_challenge);
// Generate a challenge from the appended transcript
let mut appended_challenge = [0u8; 32];
other.challenge_bytes(b"append_sender_challenge", &mut appended_challenge);
// Append both challenges to both transcripts
self.append_message(b"appended_transcript_receiver_challenge", &receiver_challenge);
other.append_message(b"appended_transcript_sender_challenge", &appended_challenge);
}Additionally, it would be good if the challenge size was defined somewhere as a constant usize instead of hard-coding 32 everywhere