Trait CommitIndex

Source
pub trait CommitIndex<Proprietor>: Commitment<Proprietor> {
    type Index: Elastic + Storable;
    type Shares: Countable;

Show 18 methods // Required methods fn index_exists( reason: &Self::Reason, index_of: &Self::Digest, ) -> DispatchResult; fn entry_exists( reason: &Self::Reason, index_of: &Self::Digest, entry_of: &Self::Digest, ) -> DispatchResult; fn has_index(reason: &Self::Reason) -> DispatchResult; fn get_index( reason: &Self::Reason, index_of: &Self::Digest, ) -> Result<Self::Index, DispatchError>; fn get_entries_shares( reason: &Self::Reason, index_of: &Self::Digest, ) -> Result<Vec<(Self::Digest, Self::Shares)>, DispatchError>; fn get_entry_value( reason: &Self::Reason, index_of: &Self::Digest, entry_of: &Self::Digest, ) -> Result<Self::Asset, DispatchError>; fn get_entry_value_for( who: &Proprietor, reason: &Self::Reason, index_of: &Self::Digest, entry_of: &Self::Digest, ) -> Result<Self::Asset, DispatchError>; fn gen_index_digest( from: &Proprietor, reason: &Self::Reason, index: &Self::Index, ) -> Result<Self::Digest, DispatchError>; fn prepare_index( who: &Proprietor, reason: &Self::Reason, entries: &[(Self::Digest, Self::Shares)], ) -> Result<Self::Index, DispatchError>; fn set_index( who: &Proprietor, reason: &Self::Reason, index: &Self::Index, digest: &Self::Digest, ) -> DispatchResult; fn set_entry_shares( who: &Proprietor, reason: &Self::Reason, index_of: &Self::Digest, entry_of: &Self::Digest, shares: Self::Shares, ) -> Result<Self::Digest, DispatchError>; fn reap_index( reason: &Self::Reason, index_of: &Self::Digest, ) -> DispatchResult; // Provided methods fn get_index_value( reason: &Self::Reason, index_of: &Self::Digest, ) -> Result<Self::Asset, DispatchError> { ... } fn get_entries_value( reason: &Self::Reason, index_of: &Self::Digest, ) -> Result<Vec<(Self::Digest, Self::Asset)>, DispatchError> { ... } fn get_entries_value_for( who: &Proprietor, reason: &Self::Reason, index_of: &Self::Digest, ) -> Result<Vec<(Self::Digest, Self::Asset)>, DispatchError> { ... } fn get_index_value_for( who: &Proprietor, reason: &Self::Reason, index_of: &Self::Digest, ) -> Result<Self::Asset, DispatchError> { ... } fn on_set_index( _who: &Proprietor, _index_of: &Self::Digest, _reason: &Self::Reason, _index: &Self::Index, ) { ... } fn on_reap_index( _index_of: &Self::Digest, _reason: &Self::Reason, _dust: Self::Asset, ) { ... }
}
Expand description

CommitIndex extends Commitment by providing a higher-level financial abstraction that groups multiple commitments under a single “index”.

This enables proprietors to manage related commitments collectively, while preserving the atomicity and immutability guarantees of Commitment.

§Use Cases

  • Portfolio management: Aggregate commitments.
  • Betting pools: Collective tracking and settlement.
  • Multi-asset contracts: Manage grouped assets with shares.
  • Escrow pools: Efficient tracking of grouped escrows.
  • Market positions: Aggregate for easier tracking.

§Why CommitIndex?

The base Commitment trait enforces:

“One reason -> one digest”.

This is restrictive when:

  • A proprietor needs to manage multiple related commitments under one reason.
  • Aggregation of commitments is required.
  • Ownership of grouped commitments must be tracked proportionally.
  • Trustless, composable structures are desired.

CommitIndex solves this by introducing indexes:

  • An index digest references multiple committed digests (entries).
  • Each entry remains an independent Commitment.
  • The index enables aggregation, share-tracking, and collective management without breaking core commitment rules.

§Core Principles

  1. Wrapper over commitments

    • Index digest groups multiple committed digests.
    • Entries retain individual commitment properties.
  2. Management layer

    • Tracks shares and values for each entry.
    • Aggregates entry values into a single index value.
  3. Integrity

    • Entries remain independent commitments.
    • Index creation does not alter entry commitments.
  4. Trustless design

    • Anyone can interact with indexes without requiring creator consent, provided the share structure allows it.

§Examples

§Example 1: Portfolio Staking

Alice stakes multiple digests under a single reason to manage risk:

ReasonDigestValue
“staking”“digest_a123”100
“staking”“digest_b456”200
“staking”“digest_c789”300

Each row is an independent commitment. Alice creates a CommitIndex:

  • Reason = "staking"
  • Digest = "index_digest_xyz"
  • Entries = [digest_a123, digest_b456, digest_c789]
  • Shares = [1, 2, 3]

Total value = 600, with proportional share tracking.

§Example 2: Betting Pool

Bettors commit value for different bets under the same reason:

ReasonDigestValue
“betting_pool”“digest_bet101”50
“betting_pool”“digest_bet102”80

CommitIndex:

  • Reason = "betting_pool"
  • Digest = "index_digest_betting"
  • Entries = [digest_bet101, digest_bet102]
  • Shares = [2, 3]

Total value = 130, with proportional share tracking.

§Example 3: Market Position Index

Dave aggregates multiple market positions:

ReasonDigestValue
“market_positions”“digest_order1”500
“market_positions”“digest_order2”300

CommitIndex:

  • Reason = "market_positions"
  • Digest = "index_digest_market"
  • Entries = [digest_order1, digest_order2]
  • Shares = [5, 3]

Aggregates positions without altering atomic commitments.

§Example 4: Escrow Pool

Multiple escrows under one reason:

ReasonDigestValue
“escrow_pool”“digest_escrow1”1000
“escrow_pool”“digest_escrow2”1500

CommitIndex:

  • Reason = "escrow_pool"
  • Digest = "index_digest_escrow"
  • Entries = [digest_escrow1, digest_escrow2]
  • Shares = [1, 1.5]

Tracks total escrow commitments (2500) and proportional ownership.

§Invariants

  • An index digest is a managed wrapper over multiple committed digests.
  • Each entry is an independent Commitment.
  • Index creation preserves atomicity, immutability, and reason-digest invariants.
  • Shares define proportional ownership of aggregated commitments.
  • Must maintain the base-invariant “One Reason -> One Digest”

Generics:

  • Proprietor - the entity that owns the asset and can make commitments.

Required Associated Types§

Source

type Index: Elastic + Storable

The type representing an index. This could be a struct containing entries and shares.

Source

type Shares: Countable

The type representing shares for an entry.

Should be a simple unsigned numeric type.

Required Methods§

Source

fn index_exists( reason: &Self::Reason, index_of: &Self::Digest, ) -> DispatchResult

Checks whether an index exists for the given reason and index digest.

§Returns
  • Ok(()) if the index exists
  • Err(DispatchError) if the index is not found
Source

fn entry_exists( reason: &Self::Reason, index_of: &Self::Digest, entry_of: &Self::Digest, ) -> DispatchResult

Checks whether a specific entry exists within the given index.

Verifies that the specified entry digest is part of the index’s entry list under the given reason.

§Returns
  • Ok(()) if the entry exists within the index
  • Err(DispatchError) if the entry is not found in the index
Source

fn has_index(reason: &Self::Reason) -> DispatchResult

Checks whether any index exists for the given reason.

Verifies that at least one index has been created under the specified reason across all proprietors.

§Returns
  • Ok(()) if at least one index exists for the reason
  • Err(DispatchError) if no indexes are found for the reason
Source

fn get_index( reason: &Self::Reason, index_of: &Self::Digest, ) -> Result<Self::Index, DispatchError>

Retrieves the complete index structure for the given reason and index digest.

Returns the full index object containing all entries, shares, and associated metadata for inspection or processing.

§Returns
  • Ok(Index) containing the complete index structure i.e., CommitIndex::Index
  • Err(DispatchError) if the index does not exist
Source

fn get_entries_shares( reason: &Self::Reason, index_of: &Self::Digest, ) -> Result<Vec<(Self::Digest, Self::Shares)>, DispatchError>

Retrieves the shares of each entry in the given index.

Returns a list of entry digests paired with their corresponding shares, representing each entry’s proportional weight within the index.

§Returns
  • Ok(Vec<(Self::Digest, Self::Shares)>) containing entry-share pairs
  • Err(DispatchError) if the index does not exist or retrieval fails
Source

fn get_entry_value( reason: &Self::Reason, index_of: &Self::Digest, entry_of: &Self::Digest, ) -> Result<Self::Asset, DispatchError>

Retrieves the real-time committed value of a specific entry within an index.

Returns the current value for the given entry digest under the specified reason and index. Since the supertrait Commitment allows digest values to be updated via Commitment::set_digest_value, this reflects the live state rather than the original deposit.

§Returns
  • Ok(Asset) containing the entry’s current committed value
  • Err(DispatchError) if the index or entry does not exist
Source

fn get_entry_value_for( who: &Proprietor, reason: &Self::Reason, index_of: &Self::Digest, entry_of: &Self::Digest, ) -> Result<Self::Asset, DispatchError>

Retrieves the real-time value of a proprietor’s commitment to a specific entry within an index.

Returns the live committed value for the given proprietor and entry digest. Since the supertrait Commitment allows digest values to be updated via Commitment::set_digest_value, this reflects the current state rather than the deposited total.

§Returns
  • Ok(Asset) containing the proprietor’s current commitment to the entry
  • Err(DispatchError) if the index or entry does not exist
Source

fn gen_index_digest( from: &Proprietor, reason: &Self::Reason, index: &Self::Index, ) -> Result<Self::Digest, DispatchError>

Generates a unique digest for the given index object.

Creates a distinct identifier derived from the proprietor, reason, and index structure (including entries and shares). The generated digest must be collision-resistant and unique across all indexes of reason.

§Returns
  • Ok(Digest) containing the generated unique index digest
  • Err(DispatchError) if digest generation fails due to invalid inputs
Source

fn prepare_index( who: &Proprietor, reason: &Self::Reason, entries: &[(Self::Digest, Self::Shares)], ) -> Result<Self::Index, DispatchError>

Prepares an index object from the provided entry data.

Constructs a valid index structure from a list of (Digest, Shares) pairs, where each pair represents:

  • Digest: The unique identifier of an entry within the index
  • Shares: The proportional weight or ownership of that entry

This method:

  • Validates entry data for consistency and integrity
  • Ensures no duplicate digests exist
  • Rejects entries with nil/empty digests or zero shares
  • Creates an immutable, atomic index object
§Returns
  • Ok(Index) containing the prepared index structure
  • Err(DispatchError) if preparation fails due to invalid data or validation errors
Source

fn set_index( who: &Proprietor, reason: &Self::Reason, index: &Self::Index, digest: &Self::Digest, ) -> DispatchResult

Binds the prepared index to the specified digest under the given reason.

Associates the provided digest with the index structure, making it queryable and usable within the commitment system. The index object should be safely prepared via CommitIndex::prepare_index before calling this method.

This operation ensures:

  • The digest uniquely identifies the index
  • All entries and shares are preserved with integrity
  • The index conforms to CommitIndex invariants
§Returns
  • Ok(()) if the index is successfully set
  • Err(DispatchError) if the operation fails due to invalid data or conflicts
Source

fn set_entry_shares( who: &Proprietor, reason: &Self::Reason, index_of: &Self::Digest, entry_of: &Self::Digest, shares: Self::Shares, ) -> Result<Self::Digest, DispatchError>

Updates the shares of a single entry within an existing index.

Since indexes are immutable once created, this method internally:

  1. Prepares a new index with the updated share for the specified entry
  2. Generates a new digest for the modified index
  3. Returns the new index digest

Since no explicit entry-removal methods are provided, this method may be used to remove an entry when its share is set to zero.

By invariant, commitment indexes must not contain entries with zero shares.

For updating multiple entries, use CommitIndex::prepare_index and CommitIndex::set_index to create a completely new index structure.

§Returns
  • Ok(Digest) containing the new index digest after share update
  • Err(DispatchError) if the index or entry does not exist, or update fails
Source

fn reap_index(reason: &Self::Reason, index_of: &Self::Digest) -> DispatchResult

Removes an index if it contains no active commitments.

Permanently deletes the specified index digest under the given reason, freeing associated resources. Indexes can only be reaped when they have no committed entries or remaining balances.

§Returns
  • Ok(()) if the index is successfully removed
  • Err(DispatchError) if the index does not exist or contains active commitments

Provided Methods§

Source

fn get_index_value( reason: &Self::Reason, index_of: &Self::Digest, ) -> Result<Self::Asset, DispatchError>

Retrieves the real-time aggregated value of the specified index.

Computes the total value by summing the current values of all entry digests under the index. Since the supertrait Commitment allows digest values to be updated via Commitment::set_digest_value, this reflects the live state rather than historical deposits.

Ensures each entry’s digest value is current before aggregation.

§Returns
  • Ok(Asset) containing the total aggregated value of the index
  • Err(DispatchError) if the index does not exist or value computation fails
Source

fn get_entries_value( reason: &Self::Reason, index_of: &Self::Digest, ) -> Result<Vec<(Self::Digest, Self::Asset)>, DispatchError>

Retrieves the real-time values of all entries within the specified index.

Each entry’s value is fetched individually and reflects any changes since the commitment was created, as the supertrait Commitment allows digest values to be updated via Commitment::set_digest_value.

Returns a list of entry digests paired with their current committed values.

§Returns
  • Ok(Vec<(Self::Digest, Self::Asset)>) containing entry-value pairs
  • Err(DispatchError) if the index does not exist or value retrieval fails
Source

fn get_entries_value_for( who: &Proprietor, reason: &Self::Reason, index_of: &Self::Digest, ) -> Result<Vec<(Self::Digest, Self::Asset)>, DispatchError>

Retrieves the real-time values of a proprietor’s commitments to all entries within the specified index.

Each entry’s value is computed individually for the given proprietor and reflects any changes since commitment, as the supertrait Commitment allows digest values to be updated via Commitment::set_digest_value.

Returns a list of entry digests paired with their current committed values for the specified proprietor.

§Returns
  • Ok(Vec<(Self::Digest, Self::Asset)>) containing entry-value pairs for the proprietor
  • Err(DispatchError) if the index does not exist or value retrieval fails
Source

fn get_index_value_for( who: &Proprietor, reason: &Self::Reason, index_of: &Self::Digest, ) -> Result<Self::Asset, DispatchError>

Retrieves the real-time total value of a proprietor’s commitment to an index.

Aggregates the live committed values of all entry digests within the index for the given proprietor. Since the supertrait Commitment allows digest values to be updated via Commitment::set_digest_value, this reflects the current total rather than historical deposits.

§Returns
  • Ok(Asset) containing the proprietor’s total commitment to the index
  • Err(DispatchError) if the index does not exist or computation fails
Source

fn on_set_index( _who: &Proprietor, _index_of: &Self::Digest, _reason: &Self::Reason, _index: &Self::Index, )

Hook called after an index is created and its digest is set by a proprietor.

Provides an extension point for triggering side-effects such as events, logging, recalculations, or external state updates when a new index is established.

Default implementation is a no-op.

Source

fn on_reap_index( _index_of: &Self::Digest, _reason: &Self::Reason, _dust: Self::Asset, )

Hook called after an index is reaped (removed).

Provides an extension point for cleanup tasks, logging, freeing related resources, or triggering external notifications when an index is permanently removed from the system.

dust represents any residual value that was unclaimable and effectively considered dead.

Default implementation is a no-op.

Dyn Compatibility§

This trait is not dyn compatible.

In older versions of Rust, dyn compatibility was called "object safety", so this trait is not object safe.

Implementors§