Skip to main content

Version

Enum Version 

Source
#[non_exhaustive]
pub enum Version { V0, V1, }
Expand description

The packet framing used by a Transcript.

The version is an immutable part of a protocol’s definition. Version::V0 uses schema-dependent framing and requires the protocol’s complete packet-history language to be uniquely decodable. Version::V1 provides injective framing for arbitrary byte packets.

Variants (Non-exhaustive)§

This enum is marked as non-exhaustive
Non-exhaustive enums could have additional variants added in future. Therefore, when matching against variants of non-exhaustive enums, an extra wildcard arm must be added to account for any future variants.
§

V0

Use schema-dependent suffix-length framing.

V0 commits data || varint(length(data)). This suffix is ambiguous for unrestricted packet histories because packet data can imitate an earlier packet’s length.

§Safety

A protocol may use V0 only when its complete set of accepted histories is uniquely decodable. One sufficient condition is:

  • the namespace is one fixed value;
  • every history has a fixed packet count and order; and
  • the payload language accepted at each position is prefix-free, such as one fixed-size value or a canonical self-delimiting encoding.

A history containing only one arbitrary packet is also unambiguous because n + varint_size(n) is strictly increasing. This is why a one-packet namespace may be summarized before a fixed-schema protocol continues from the resulting summary.

The proof applies to the complete packet schema, not to each payload in isolation. Fixed-size encodings alone do not make optional, repeated, or reordered packets safe. Changing a packet’s encoding, when it may appear, or how often it may repeat requires checking unique decodability for the full set of accepted histories again.

This fixed schema is safe: every accepted history contains the same namespace, one 8-byte round, and one 32-byte public key.

fn summarize(round: u64, public_key: [u8; 32]) -> Summary {
    let round = round.to_be_bytes();
    Transcript::new(b"_COMMONWARE_CRYPTOGRAPHY_TRANSCRIPT_V0_FIXED", Version::V0)
        .commit(round.as_slice())
        .commit(public_key.as_slice())
        .summarize()
}
assert_ne!(summarize(7, [1; 32]), summarize(8, [1; 32]));

By contrast, unrestricted packet boundaries are unsafe. These distinct V0 histories commit the same bytes.

let zeros = [0u8; 127];
let split = Transcript::new(b"", Version::V0)
    .commit(zeros.as_slice())
    .commit([0x80].as_slice())
    .summarize();

let mut merged = zeros.to_vec();
merged.push(0x7f);
let merged = Transcript::new(b"", Version::V0)
    .commit(merged.as_slice())
    .summarize();

assert_eq!(split, merged);
§

V1

Use injective packet framing for arbitrary packet contents.

V1 commits data || reverse(varint(length(data))). Canonical varints are prefix-free, so their reversals are suffix-free. Starting at the end of a history, the final length and then its exact payload can be recovered repeatedly. Packet data cannot alter those boundaries. Empty packets remain distinct from no packet, and Transcript::append retains constant framing memory because only the pending length is stored.

§Safety

V1 is safe for arbitrary byte packets, variable packet lengths, optional or repeated packets, and schemas that evolve to include them. It binds byte packets and their boundaries; it cannot repair a non-injective application encoding where two semantic values already produce the same packet bytes.

The V0 collision above is separated under V1:

let zeros = [0u8; 127];
let split = Transcript::new(b"", Version::V1)
    .commit(zeros.as_slice())
    .commit([0x80].as_slice())
    .summarize();

let mut merged = zeros.to_vec();
merged.push(0x7f);
let merged = Transcript::new(b"", Version::V1)
    .commit(merged.as_slice())
    .summarize();

assert_ne!(split, merged);

Trait Implementations§

Source§

impl Clone for Version

Source§

fn clone(&self) -> Version

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Copy for Version

Source§

impl Debug for Version

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Eq for Version

Source§

impl Hash for Version

Source§

fn hash<__H: Hasher>(&self, state: &mut __H)

Feeds this value into the given Hasher. Read more
1.3.0 · Source§

fn hash_slice<H>(data: &[Self], state: &mut H)
where H: Hasher, Self: Sized,

Feeds a slice of this type into the given Hasher. Read more
Source§

impl PartialEq for Version

Source§

fn eq(&self, other: &Version) -> bool

Equality operator ==. Read more
1.0.0 (const: unstable) · Source§

fn ne(&self, other: &Rhs) -> bool

Inequality operator !=. Read more
Source§

impl StructuralPartialEq for Version

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<Q, K> Equivalent<K> for Q
where Q: Eq + ?Sized, K: Borrow<Q> + ?Sized,

Source§

fn equivalent(&self, key: &K) -> bool

Checks if this value is equivalent to the given key. Read more
Source§

impl<Q, K> Equivalent<K> for Q
where Q: Eq + ?Sized, K: Borrow<Q> + ?Sized,

Source§

fn equivalent(&self, key: &K) -> bool

Checks if this value is equivalent to the given key. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

impl<T> Pointable for T

Source§

const ALIGN: usize

The alignment of pointer.
Source§

type Init = T

The type for initializers.
Source§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
Source§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
Source§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
Source§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
Source§

impl<T> Read<Exclusive, BecauseExclusive> for T
where T: ?Sized,

Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T> Threaded<T> for T

Source§

type Rest = ()

The outputs beyond the threaded value.
Source§

fn split(self) -> (T, ())

Splits into the threaded value and the extra outputs.
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V

Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more