Last active
December 23, 2024 01:46
-
-
Save HarryR/a1217d3a2d929bde1aeace052500d670 to your computer and use it in GitHub Desktop.
Forking Merlin transcripts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
use merlin::Transcript; | |
use std::cell::RefCell; | |
use std::rc::Rc; | |
#[derive(Debug)] | |
enum TranscriptState { | |
Original, | |
Forked { parent_label: Vec<u8> }, | |
} | |
#[derive(Debug)] | |
struct RestrictedTranscript { | |
transcript: Transcript, | |
state: TranscriptState, | |
forks: RefCell<Vec<Rc<RestrictedTranscript>>>, | |
} | |
impl RestrictedTranscript { | |
// Create a new original transcript | |
pub fn new(context: &'static [u8]) -> Self { | |
Self { | |
transcript: Transcript::new(context), | |
state: TranscriptState::Original, | |
forks: RefCell::new(Vec::new()), | |
} | |
} | |
// Controlled forking method | |
pub fn fork(&mut self) -> Rc<RestrictedTranscript> { | |
// Generate a fork label | |
let mut fork_label = [0u8; 32]; | |
self.transcript.clone_mut().challenge_bytes(b"fork_label", &mut fork_label); | |
// Create forked transcript | |
let forked = Rc::new(RestrictedTranscript { | |
transcript: self.transcript.clone(), | |
state: TranscriptState::Forked { | |
parent_label: fork_label.to_vec() | |
}, | |
forks: RefCell::new(Vec::new()), | |
}); | |
// Track the fork | |
self.forks.borrow_mut().push(Rc::clone(&forked)); | |
forked | |
} | |
// Append another transcript (only if it's a fork) | |
pub fn append_transcript(&mut self, other: &mut RestrictedTranscript) { | |
// Validate that this is a genuine fork | |
match &other.state { | |
TranscriptState::Forked { parent_label } => { | |
// Append using the fork label | |
let mut append_label = [0u8; 32]; | |
other.transcript.clone_mut().challenge_bytes(b"fork_challenge", &mut append_label); | |
// Append to this transcript | |
self.transcript.append_message(b"appended_transcript", &append_label); | |
}, | |
_ => panic!("Can only append forked transcripts"), | |
} | |
} | |
// Delegate other Transcript methods | |
pub fn append_message(&mut self, label: &'static [u8], message: &[u8]) { | |
self.transcript.append_message(label, message); | |
} | |
pub fn challenge_bytes(&mut self, label: &'static [u8], dest: &mut [u8]) { | |
self.transcript.challenge_bytes(label, dest); | |
} | |
} | |
fn main() { | |
// Example usage | |
let mut original = RestrictedTranscript::new(b"protocol"); | |
// Controlled fork | |
let mut fork1 = original.fork(); | |
// This would fail to compile/panic | |
// let illegal_clone = fork1.clone(); | |
// Demonstrating append | |
original.append_transcript(&mut fork1); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment