Skip to main content

Commitment

Struct Commitment 

Source
pub struct Commitment {
    pub version: u8,
    pub protocol_id: [u8; 32],
    pub mpc_root: Hash,
    pub contract_id: Hash,
    pub previous_commitment: Hash,
    pub transition_payload_hash: Hash,
    pub seal_id: Hash,
    pub domain_separator: [u8; 32],
}
Expand description

A V2 commitment binding state to an anchor.

A commitment is the core data structure in CSV. It captures everything needed to verify a state transition:

  • Which protocol it belongs to (protocol_id)
  • What state it represents (mpc_root, contract_id)
  • Where it came from (previous_commitment)
  • What changed (transition_payload_hash)
  • What seal was consumed (seal_id)
  • Which chain context it’s valid in (domain_separator)

§Commitment Chain

Commitments form a linked chain: each commitment references the hash of the previous one via previous_commitment. Clients validate the entire chain from genesis to the current state without querying the blockchain for each step.

§Collision Resistance

Each field is hashed with a unique domain tag (e.g., "commitment-version", "commitment-protocol-id") using csv_tagged_hash. This prevents cross-field and cross-protocol collision attacks where an attacker could rearrange field bytes to forge a valid-looking commitment.

Fields§

§version: u8

Format version. Currently always COMMITMENT_VERSION.

§protocol_id: [u8; 32]

Protocol identifier this commitment belongs to.

This is a 32-byte namespace that isolates commitments from different protocols sharing the same anchoring layer. For example:

  • Bitcoin adapter: b"CSV-BTC-\x00\x00..." (magic bytes padded)
  • Ethereum adapter: b"CSV-ETH-\x00\x00..."
§mpc_root: Hash

Merkle root of the MPC tree for multi-protocol witnessing.

When multiple protocols share a single witness (e.g., a threshold signature spanning Bitcoin and Ethereum), this root commits to all participating protocols’ individual roots.

For single-protocol use (the common case), this is set to a deterministic empty root: SHA256("csv-empty-mpc-root").

§contract_id: Hash

Unique contract/right identifier.

For NFTs, this is the token ID. For credentials, this is the credential hash. For assets, this is the asset identifier.

Must be unique within the protocol namespace.

§previous_commitment: Hash

Hash of the previous commitment in the chain.

For the first commitment (genesis), this is typically Hash::zero(). For subsequent commitments, this is previous_commitment.hash().

This forms the commitment chain that clients validate independently.

§transition_payload_hash: Hash

SHA-256 hash of the state transition payload.

This commits to the actual data being transitioned (e.g., new owner, metadata update, transfer details). Clients must verify this hash matches the payload they expect.

§seal_id: Hash

SHA-256 hash of the consumed seal reference.

This binds the commitment to the specific seal that was consumed to authorize this transition. The seal reference includes the chain-specific identifier (UTXO txid, object ID, etc.) and the seal’s nonce/value.

§domain_separator: [u8; 32]

Domain separator for chain-specific commitment isolation.

Prevents cross-chain replay attacks by ensuring a commitment created on one chain cannot be used on another. Typically constructed as H(chain_id || network || protocol_version).

Implementations§

Source§

impl Commitment

Source

pub fn new( protocol_id: [u8; 32], mpc_tree: &MpcTree, contract_id: Hash, previous_commitment: Hash, transition_payload_hash: Hash, seal_ref: &SealRef, domain_separator: [u8; 32], ) -> Self

Create a commitment

This creates a V2 (MPC-aware) commitment. All adapters should use this constructor. The protocol_id should uniquely identify the protocol (e.g., “CSV-BTC-” for Bitcoin, “CSV-ETH-” for Ethereum).

Source

pub fn simple( contract_id: Hash, previous_commitment: Hash, transition_payload_hash: Hash, seal_ref: &SealRef, domain_separator: [u8; 32], ) -> Self

Create a commitment without MPC tree (for simple single-protocol use)

This is a convenience constructor that uses a default empty MPC root. For multi-protocol use cases, use Commitment::new instead.

Source

pub fn v1( contract_id: Hash, previous_commitment: Hash, transition_payload_hash: Hash, seal_ref: &SealRef, domain_separator: [u8; 32], ) -> Self

👎Deprecated since 0.2.0:

Use Commitment::simple instead

Backwards-compatible alias for Commitment::simple.

Source

pub fn hash(&self) -> Hash

Compute the commitment hash

Source

pub fn version(&self) -> u8

Get the version

Source

pub fn contract_id(&self) -> Hash

Get the contract ID

Source

pub fn seal_id(&self) -> Hash

Get the seal ID hash

Source

pub fn domain_separator(&self) -> [u8; 32]

Get the domain separator

Source

pub fn to_canonical_bytes(&self) -> Vec<u8>

Serialize commitment using canonical encoding

Source

pub fn from_canonical_bytes(bytes: &[u8]) -> Result<Self, &'static str>

Deserialize commitment from canonical bytes

Only V2 format is supported. Legacy V1 format was removed.

Trait Implementations§

Source§

impl Clone for Commitment

Source§

fn clone(&self) -> Commitment

Returns a duplicate of the value. Read more
1.0.0 · Source§

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

Performs copy-assignment from source. Read more
Source§

impl Debug for Commitment

Source§

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

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

impl<'de> Deserialize<'de> for Commitment

Source§

fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>
where __D: Deserializer<'de>,

Deserialize this value from the given Serde deserializer. Read more
Source§

impl PartialEq for Commitment

Source§

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

Tests for self and other values to be equal, and is used by ==.
1.0.0 · Source§

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

Tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
Source§

impl Serialize for Commitment

Source§

fn serialize<__S>(&self, __serializer: __S) -> Result<__S::Ok, __S::Error>
where __S: Serializer,

Serialize this value into the given Serde serializer. Read more
Source§

impl Eq for Commitment

Source§

impl StructuralPartialEq for Commitment

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<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<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

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> Same for T

Source§

type Output = T

Should always be Self
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 = Infallible

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

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

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> DeserializeOwned for T
where T: for<'de> Deserialize<'de>,