pallet_commitment/traits.rs
1// SPDX-License-Identifier: MPL-2.0
2//
3// Part of Auguth Labs open-source softwares.
4// Built for the Substrate framework.
5//
6// This Source Code Form is subject to the terms of the Mozilla Public
7// License, v. 2.0. If a copy of the MPL was not distributed with this
8// file, You can obtain one at https://mozilla.org/MPL/2.0/.
9//
10// Copyright (c) 2026 Auguth Labs (OPC) Pvt Ltd, India
11
12// ===============================================================================
13// ```````````````````````````` COMMIT-HELPERS TRAITS ````````````````````````````
14// ===============================================================================
15
16//! Defines helper traits for implementing a concrete [`Commitment`] system.
17//! All operations are **low-level and unchecked** - callers must ensure validity,
18//! equilibrium, and invariants before invoking these functions.
19//!
20//! ## Requirements
21//! This module additionally requires the balance primitive [`LazyBalance`] provided
22//! via the implementing pallet. All balance interactions and accounting are expected
23//! to be handled through this abstraction.
24//!
25//! ## Traits
26//! - [`CommitBalance`] - balance management and reconciliation.
27//! - [`CommitDeposit`] - low-level deposit operations.
28//! - [`CommitWithdraw`] - low-level withdrawal operations.
29//! - [`CommitOps`] - placing, raising, and resolving commitments.
30//! - [`CommitInspect`] - inspection and auditing of committed values.
31//! - [`PoolOps`] - operations for pooled commitments.
32//! - [`IndexOps`] - operations for indexed digest commitments.
33//!
34//! ## Design Principles
35//! - Explicit imbalance handling for auditability and safety.
36//! - Composability to build full commitment systems (direct, index, pool).
37//! - Separation of low-level operations from higher-level safety.
38//! - Equillibrium in Queriable values maintained.
39
40// ===============================================================================
41// ``````````````````````````````````` IMPORTS ```````````````````````````````````
42// ===============================================================================
43
44// --- FRAME Suite ---
45use frame_suite::{assets::LazyBalance, commitment::*};
46
47// --- Substrate primitives ---
48use sp_runtime::{
49 traits::{CheckedAdd, CheckedSub},
50 ArithmeticError, DispatchError, DispatchResult,
51};
52
53// ===============================================================================
54// ```````````````````````````````` COMMIT BALANCE ```````````````````````````````
55// ===============================================================================
56
57/// Provides low-level balance management and reconciliation behavior
58/// for [`Commitment`] systems.
59///
60/// Commitment frameworks often employ *unbalanced fungible traits* rather than
61/// automatically balanced ones. This enables explicit safety enforcement and
62/// auditability by requiring all balance mismatches to be resolved intentionally
63/// rather than implicitly.
64///
65/// This trait defines how those imbalances and balance adjustments should be
66/// handled consistently across the system.
67///
68/// It only defines **low-level, unchecked operations** - callers are
69/// responsible for ensuring validity and equilibrium before invoking this
70/// function.
71///
72/// ### Generics
73/// - **Proprietor** - the entity (e.g. account, vault, or manager) owning
74/// or controlling the underlying asset balance.
75/// - **Pallet** - the pallet public struct which implements [`Commitment`] traits
76/// for consumer pallet usage, and provides the required commitment abstraction.
77/// - The implementing `Pallet` **must provide [`LazyBalance`]** with guarantees
78/// that all balance operations remain consistent with the commitment system's
79/// underlying asset accounting.
80pub trait CommitBalance<Proprietor, Pallet>
81where
82 Pallet: LazyBalance<Asset = <Pallet as InspectAsset<Proprietor>>::Asset>
83 + InspectAsset<Proprietor>
84 + Commitment<Proprietor>,
85{
86 /// The imbalance type representing the difference between deposits and withdrawals.
87 type Imbalance;
88
89 /// Resolves an imbalance in a proprietor's committed balance.
90 ///
91 /// Used when a digest's value adjustment causes a mismatch in
92 /// deposited versus withdrawn amounts.
93 ///
94 /// Ensures the underlying asset accounting remains correct by minting,
95 /// burning, or otherwise reconciling the imbalance.
96 ///
97 /// It only defines **low-level, unchecked operations** - callers are
98 /// responsible for ensuring validity and equilibrium before invoking this
99 /// function.
100 ///
101 /// ## Returns
102 /// - `Ok(Asset)` containing the final balanced value
103 /// - `Err(DispatchError)` if reconciliation fails
104 fn resolve_imbalance(
105 who: &Proprietor,
106 imbalance: Self::Imbalance,
107 ) -> Result<<Pallet as InspectAsset<Proprietor>>::Asset, DispatchError>;
108
109 /// Deducts a specified asset value from the proprietor's available balance.
110 ///
111 /// This function deducts the requested amount according to the given
112 /// qualifier - exactness or best effort along with force rules to
113 /// determine whether and how the deduction should proceed.
114 ///
115 /// It only defines **low-level, unchecked operations** - callers are
116 /// responsible for ensuring validity and equilibrium before invoking this
117 /// function.
118 ///
119 /// ## Returns
120 /// - `Ok(Asset)` containing the actual deducted value
121 /// - `Err(DispatchError)` if the deduction fails
122 fn deduct_balance(
123 who: &Proprietor,
124 value: <Pallet as InspectAsset<Proprietor>>::Asset,
125 qualifier: &Pallet::Intent,
126 ) -> Result<<Pallet as InspectAsset<Proprietor>>::Asset, DispatchError>;
127
128 /// Deducts a specified asset value from a imbalance (effectively mutating it).
129 ///
130 /// This function deducts the exact amount, maintains equillibrium and
131 /// returns another imbalance - to be resolved (typically by [`Self::resolve_imbalance`]).
132 ///
133 /// This provides extracting new-imbalances from existing imbalances safely.
134 ///
135 /// It only defines **low-level, unchecked operations** - callers are
136 /// responsible for ensuring validity and equilibrium before invoking this
137 /// function.
138 ///
139 /// ## Returns
140 /// - `Ok(Imbalance)` containing the new imbalance
141 /// - `Err(DispatchError)` if the deduction fails
142 fn deduct_from_imbalance(
143 imbalance: &mut Self::Imbalance,
144 value: <Pallet as InspectAsset<Proprietor>>::Asset,
145 ) -> Result<Self::Imbalance, DispatchError>;
146}
147
148// ===============================================================================
149// ```````````````````````````````` COMMIT DEPOSIT ```````````````````````````````
150// ===============================================================================
151
152/// Provides low-level deposit operations for commitment systems, enabling assets
153/// to be recorded against digests, indexes, and pools for a given proprietor.
154///
155/// This trait focuses solely on **recording deposits** within the system. It does **not**
156/// handle balance deductions, freezing funds, or higher-level commit management - those
157/// responsibilities are delegated to upper layers of the [`Commitment`] framework.
158///
159/// It only defines **low-level, unchecked operations** - callers are
160/// responsible for ensuring validity and equilibrium before invoking these
161/// functions.
162///
163/// ### Generics
164/// - **Proprietor** - the entity (e.g. account, vault, or manager)
165/// controlling the asset.
166/// - **Pallet** - the public struct implementing [`Commitment`] traits
167/// and [`LazyBalance`], ensuring consistent asset accounting across the
168/// commitment system.
169pub trait CommitDeposit<Proprietor, Pallet>
170where
171 Pallet: LazyBalance<
172 Asset = <Pallet as InspectAsset<Proprietor>>::Asset,
173 Variant = Pallet::Position,
174 Id = Pallet::Digest,
175 > + DigestModel<Proprietor>
176 + CommitVariant<Proprietor>,
177{
178 /// Type representing a "Receipt" of the deposit towards the
179 /// digest (direct) at the time of commitment.
180 ///
181 /// A receipt acts as a claimable bill over the digest's balance,
182 /// capturing the state at the time of commitment. This allows
183 /// commitments to be resolved accurately later, even if the
184 /// underlying balance changes.
185 ///
186 /// Effectively serves as a versioned claim tied to a specific
187 /// commitment.
188 type Receipt;
189
190 /// Deposits a value to a fully resolved/wrapped digest model and it's
191 /// specified balance variant.
192 ///
193 /// This function assumes the digest has already been resolved and wrapped
194 /// appropriately, so it directly handles the act of **only depositing**
195 /// the given value under the specified reason.
196 ///
197 /// This is a **low-level** function that only records the deposit to the
198 /// digest model. It does **not** perform balance deductions or handle
199 /// commit-level operations such as freezing funds or storing commitment
200 /// records. Any such logic must be handled at a higher level.
201 ///
202 /// Some digests such as indexes and pools may not require a `variant`, yet
203 /// direct requires it, so its kept reagrdless and the caller must acknowledge
204 /// that.
205 ///
206 /// ## Returns
207 /// - `Ok((Receipt, Asset))` containing the deposit's state and the
208 /// actual deposit value.
209 /// - `Err(DispatchError)` if the deposit fails
210 fn deposit_to(
211 who: &Proprietor,
212 reason: &Pallet::Reason,
213 digest_model: &Pallet::Model,
214 value: <Pallet as InspectAsset<Proprietor>>::Asset,
215 variant: &Pallet::Position,
216 qualifier: &Pallet::Intent,
217 ) -> Result<(Self::Receipt, <Pallet as InspectAsset<Proprietor>>::Asset), DispatchError>;
218
219 /// Deposits a committed asset into a given digest of variant for
220 /// a specified reason.
221 ///
222 /// This is a **low-level** function that only records the deposit to
223 /// the digest. It does **not** perform balance deductions or handle
224 /// commit-level operations such as freezing funds or storing commitment
225 /// records. Any such logic must be handled at a higher level.
226 ///
227 /// ## Returns
228 /// - `Ok((Receipt, Asset))` containing the deposit's state and the
229 /// actual deposit value.
230 /// - `Err(DispatchError)` if the deposit fails
231 fn deposit_to_digest(
232 who: &Proprietor,
233 reason: &Pallet::Reason,
234 digest: &Pallet::Digest,
235 value: <Pallet as InspectAsset<Proprietor>>::Asset,
236 variant: &Pallet::Position,
237 qualifier: &Pallet::Intent,
238 ) -> Result<(Self::Receipt, <Pallet as InspectAsset<Proprietor>>::Asset), DispatchError>;
239
240 /// Deposits a committed asset into a given index for a specified reason.
241 ///
242 /// This is a **low-level** function that only records the deposit to the index.
243 /// It does **not** perform balance deductions or handle commit-level operations
244 /// such as freezing funds or storing commitment records.
245 /// Any such logic must be handled at a higher level.
246 ///
247 /// ## Returns
248 /// - `Ok((Receipt, Asset))` containing the deposit's state and the
249 /// actual deposit value.
250 /// - `Err(DispatchError)` if the deposit fails
251 fn deposit_to_index(
252 who: &Proprietor,
253 reason: &Pallet::Reason,
254 index_of: &Pallet::Digest,
255 value: <Pallet as InspectAsset<Proprietor>>::Asset,
256 variant: &Pallet::Position,
257 qualifier: &Pallet::Intent,
258 ) -> Result<(Self::Receipt, <Pallet as InspectAsset<Proprietor>>::Asset), DispatchError>;
259
260 /// Deposits a committed asset into a given pool of a variant for a specified reason.
261 ///
262 /// This is a **low-level** function that only records the deposit to the pool.
263 /// It does **not** perform balance deductions or handle commit-level operations
264 /// such as freezing funds or storing commitment records.
265 /// Any such logic must be handled at a higher level.
266 ///
267 /// ## Returns
268 /// - `Ok((Receipt, Asset))` containing the deposit's state and the
269 /// actual deposit value.
270 /// - `Err(DispatchError)` if the deposit fails
271 fn deposit_to_pool(
272 who: &Proprietor,
273 reason: &Pallet::Reason,
274 pool_of: &Pallet::Digest,
275 value: <Pallet as InspectAsset<Proprietor>>::Asset,
276 variant: &Pallet::Position,
277 qualifier: &Pallet::Intent,
278 ) -> Result<(Self::Receipt, <Pallet as InspectAsset<Proprietor>>::Asset), DispatchError>;
279}
280
281// ===============================================================================
282// ```````````````````````````````` COMMIT WITHDRAW ``````````````````````````````
283// ===============================================================================
284
285/// Provides low-level withdrawal operations for commitment systems, enabling proprietors
286/// to extract committed assets from digests, indexes, and pools for a given reason.
287///
288/// This trait focuses solely on **withdrawing committed values**. It does **not**
289/// handle higher-level operations such as unfreezing funds, updating commitment records,
290/// or enforcing variant rules - those responsibilities are delegated to upper layers
291/// of the [`Commitment`] framework.
292///
293/// It only defines **low-level, unchecked operations** - callers are
294/// responsible for ensuring validity and equilibrium before invoking these
295/// functions.
296///
297/// ### Generics
298/// - **Proprietor** - the entity (e.g. account, vault, or manager)
299/// controlling the asset.
300/// - **Pallet** - the public struct implementing [`Commitment`] traits
301/// and [`LazyBalance`], ensuring consistent asset accounting across the
302/// commitment system.
303pub trait CommitWithdraw<Proprietor, Pallet>: CommitBalance<Proprietor, Pallet>
304where
305 Pallet: LazyBalance<
306 Asset = <Pallet as InspectAsset<Proprietor>>::Asset,
307 Variant = Pallet::Position,
308 Id = Pallet::Digest,
309 > + DigestModel<Proprietor>
310 + CommitVariant<Proprietor>,
311{
312 /// Withdraws the proprietor's value of a commitment done to a resolved/wrapped
313 /// digest model for a given reason.
314 ///
315 /// This function assumes the digest has already been resolved and wrapped appropriately,
316 /// so it directly handles the act of **only withdrawing** its total committed value
317 /// under the specified reason.
318 ///
319 /// This is a **low-level** function that only withdraws to the given proprietor.
320 /// It does **not** perform commit-level operations such as unfreezing funds or
321 /// updating commitment records, nor variant validation.
322 /// Any such logic must be handled at a higher level.
323 ///
324 /// ## Returns
325 /// - `Ok(Imbalance)` containing the withdrawal imbalance
326 /// - `Err(DispatchError)` if the withdrawal fails
327 fn withdraw_for(
328 who: &Proprietor,
329 reason: &Pallet::Reason,
330 digest_model: &Pallet::Model,
331 variant: &Pallet::Position,
332 ) -> Result<Self::Imbalance, DispatchError>;
333
334 /// Withdraws the proprietor's value of a commitment to the given digest
335 /// of variant for a specified reason.
336 ///
337 /// This is a **low-level** function that only withdraws to the given proprietor.
338 /// It does **not** perform commit-level operations such as unfreezing funds or
339 /// updating commitment records.
340 /// Any such logic must be handled at a higher level.
341 ///
342 /// ## Returns
343 /// - `Ok(Imbalance)` containing the withdrawal imbalance
344 /// - `Err(DispatchError)` if the withdrawal fails
345 fn withdraw_from_digest(
346 who: &Proprietor,
347 reason: &Pallet::Reason,
348 digest: &Pallet::Digest,
349 variant: &Pallet::Position,
350 ) -> Result<Self::Imbalance, DispatchError>;
351
352 /// Withdraws the proprietor's value of a commitment to the given index
353 /// digest of variant for a specified reason.
354 ///
355 /// This is a **low-level** function that only withdraws to the given proprietor.
356 /// It does **not** perform commit-level operations such as unfreezing funds or
357 /// updating commitment records.
358 /// Any such logic must be handled at a higher level.
359 ///
360 /// ## Returns
361 /// - `Ok(Imbalance)` containing the withdrawal imbalance
362 /// - `Err(DispatchError)` if the withdrawal fails
363 fn withdraw_from_index(
364 who: &Proprietor,
365 reason: &Pallet::Reason,
366 index_of: &Pallet::Digest,
367 variant: &Pallet::Position,
368 ) -> Result<Self::Imbalance, DispatchError>;
369
370 /// Withdraws the proprietor's value of a commitment to the given pool digest of variant
371 /// for a specified reason.
372 ///
373 /// This is a **low-level** function that only withdraws to the given proprietor.
374 /// It does **not** perform commit-level operations such as unfreezing funds or
375 /// updating commitment records.
376 /// Any such logic must be handled at a higher level.
377 ///
378 /// ## Returns
379 /// - `Ok(Imbalance)` containing the withdrawal imbalance
380 /// - `Err(DispatchError)` if the withdrawal fails
381 fn withdraw_from_pool(
382 who: &Proprietor,
383 reason: &Pallet::Reason,
384 pool_of: &Pallet::Digest,
385 variant: &Pallet::Position,
386 ) -> Result<Self::Imbalance, DispatchError>;
387}
388
389// ===============================================================================
390// ``````````````````````````````` COMMIT OPERATIONS `````````````````````````````
391// ===============================================================================
392
393/// Defines the core operations for managing commitments within digest models.
394///
395/// This trait provides a unified interface for placing, raising, and resolving
396/// commitments across all digest variants - direct, index, and pool.
397///
398/// This trait defines **low-level, unchecked operations** - callers are
399/// responsible for ensuring validity and equilibrium before invoking these
400/// functions.
401///
402/// ### Generics
403/// - **Proprietor** - the entity (e.g. account, vault, or manager)
404/// controlling the asset.
405/// - **Pallet** - the public struct implementing [`Commitment`] traits
406/// and [`LazyBalance`], ensuring consistent asset accounting across the
407/// commitment system.
408pub trait CommitOps<Proprietor, Pallet>
409where
410 Pallet: LazyBalance<
411 Asset = <Pallet as InspectAsset<Proprietor>>::Asset,
412 Variant = Pallet::Position,
413 Id = Pallet::Digest,
414 > + DigestModel<Proprietor>
415 + CommitVariant<Proprietor>,
416{
417 /// Places a commitment using a fully resolved/wrapped digest model and
418 /// a specified digest's balance variant.
419 ///
420 /// This function assumes the digest has already been found-valid and wrapped
421 /// appropriately, so it directly handles the act of **only committing** the
422 /// given value under the specified reason.
423 ///
424 /// It only defines **low-level, unchecked operations** - callers are
425 /// responsible for ensuring validity and equilibrium before invoking this
426 /// function.
427 ///
428 /// ## Returns
429 /// - `Ok(Asset)` containing the committed amount
430 /// - `Err(DispatchError)` if the commitment fails
431 fn place_commit_of(
432 who: &Proprietor,
433 reason: &Pallet::Reason,
434 digest_model: &Pallet::Model,
435 value: <Pallet as InspectAsset<Proprietor>>::Asset,
436 variant: &Pallet::Position,
437 qualifier: &Pallet::Intent,
438 ) -> Result<<Pallet as InspectAsset<Proprietor>>::Asset, DispatchError>;
439
440 /// Places a commitment for a **direct digest** under a given reason and variant.
441 ///
442 /// This function handles the placement of a commitment when the digest is a
443 /// valid, single, direct item (not an index or pool). It records the committed
444 /// value associated with the specific reason and digest, respecting the
445 /// commitment rules.
446 ///
447 /// It only defines **low-level, unchecked operations** - callers are
448 /// responsible for ensuring validity and equilibrium before invoking this
449 /// function.
450 ///
451 /// ## Returns
452 /// - `Ok(Asset)` containing the committed amount
453 /// - `Err(DispatchError)` if the commitment fails
454 fn place_digest_commit(
455 who: &Proprietor,
456 reason: &Pallet::Reason,
457 digest: &Pallet::Digest,
458 value: <Pallet as InspectAsset<Proprietor>>::Asset,
459 variant: &Pallet::Position,
460 qualifier: &Pallet::Intent,
461 ) -> Result<<Pallet as InspectAsset<Proprietor>>::Asset, DispatchError>;
462
463 /// Places a commitment for a **index digest** under a given reason
464 /// and variant.
465 ///
466 /// This function handles the placement of a commitment when the digest
467 /// is a index. It records the committed value associated respecting
468 /// the commitment rules - "One Reason, One Digest Commit" and uses high
469 /// level structures to bypass it safely.
470 ///
471 /// It only defines **low-level, unchecked operations** - callers are
472 /// responsible for ensuring validity and equilibrium before invoking this
473 /// function.
474 ///
475 /// ## Returns
476 /// - `Ok(Asset)` containing the committed amount
477 /// - `Err(DispatchError)` if the commitment fails
478 fn place_index_commit(
479 who: &Proprietor,
480 reason: &Pallet::Reason,
481 index_of: &Pallet::Digest,
482 value: <Pallet as InspectAsset<Proprietor>>::Asset,
483 variant: &Pallet::Position,
484 qualifier: &Pallet::Intent,
485 ) -> Result<<Pallet as InspectAsset<Proprietor>>::Asset, DispatchError>;
486
487 /// Places a commitment for a **pool digest** under a given
488 /// reason and variant.
489 ///
490 /// This function handles the placement of a commitment when
491 /// the digest is a pool. It records the committed value associated
492 /// respecting the commitment rules- "One Reason, One Digest Commit"
493 /// and uses high level structures to bypass it safely.
494 ///
495 /// It only defines **low-level, unchecked operations** - callers are
496 /// responsible for ensuring validity and equilibrium before invoking this
497 /// function.
498 ///
499 /// ## Returns
500 /// - `Ok(Asset)` containing the committed amount
501 /// - `Err(DispatchError)` if the commitment fails
502 fn place_pool_commit(
503 who: &Proprietor,
504 reason: &Pallet::Reason,
505 pool_of: &Pallet::Digest,
506 value: <Pallet as InspectAsset<Proprietor>>::Asset,
507 variant: &Pallet::Position,
508 qualifier: &Pallet::Intent,
509 ) -> Result<<Pallet as InspectAsset<Proprietor>>::Asset, DispatchError>;
510
511 /// Raises an existing commitment by adding a new commitment
512 /// instance.
513 ///
514 /// Commitments are immutable; each raise adds a new commit
515 /// instance - by shareing semantics with existing commit of the reason.
516 /// How accumulation is handled depends on the context: direct digest,
517 /// index, or pool.
518 ///
519 /// It only defines **low-level, unchecked operations** - callers are
520 /// responsible for ensuring validity and equilibrium before invoking this
521 /// function.
522 ///
523 /// ## Returns
524 /// - `Ok(Asset)` containing the raised amount
525 /// - `Err(DispatchError)` if the raise operation fails
526 fn raise_commit_of(
527 who: &Proprietor,
528 reason: &Pallet::Reason,
529 digest_model: &Pallet::Model,
530 value: <Pallet as InspectAsset<Proprietor>>::Asset,
531 qualifier: &Pallet::Intent,
532 ) -> Result<<Pallet as InspectAsset<Proprietor>>::Asset, DispatchError>;
533
534 /// Adds a new instance of a commitment for a direct digest.
535 ///
536 /// Commitments are immutable and cannot be changed once created. This
537 /// enforces invariants by adding new commit instances to the same
538 /// digest and reason.
539 ///
540 /// It only defines **low-level, unchecked operations** - callers are
541 /// responsible for ensuring validity and equilibrium before invoking this
542 /// function.
543 ///
544 /// ## Returns
545 /// - `Ok(Asset)` containing the raised amount
546 /// - `Err(DispatchError)` if the raise operation fails
547 fn raise_digest_commit(
548 who: &Proprietor,
549 reason: &Pallet::Reason,
550 digest: &Pallet::Digest,
551 value: <Pallet as InspectAsset<Proprietor>>::Asset,
552 qualifier: &Pallet::Intent,
553 ) -> Result<<Pallet as InspectAsset<Proprietor>>::Asset, DispatchError>;
554
555 /// Adds a new instance of a commitment for an index digest.
556 ///
557 /// Commitments are immutable and cannot be changed once created. This
558 /// enforces invariants by adding new commit instances to the same
559 /// index digest and reason.
560 ///
561 /// It only defines **low-level, unchecked operations** - callers are
562 /// responsible for ensuring validity and equilibrium before invoking this
563 /// function.
564 ///
565 /// ## Returns
566 /// - `Ok(Asset)` containing the raised amount
567 /// - `Err(DispatchError)` if the raise operation fails
568 fn raise_index_commit(
569 who: &Proprietor,
570 reason: &Pallet::Reason,
571 index_of: &Pallet::Digest,
572 value: <Pallet as InspectAsset<Proprietor>>::Asset,
573 qualifier: &Pallet::Intent,
574 ) -> Result<<Pallet as InspectAsset<Proprietor>>::Asset, DispatchError>;
575
576 /// Adds a new instance of a commitment for a pool digest.
577 ///
578 /// The pool should release and recover itself, adding the raised value.
579 /// It may also record instances of commits for the proprietor to the pool rather
580 /// than to its slot digest, since it collectively manages funds for commitments by
581 /// the pool itself acting like a pseudo-proprietor.
582 ///
583 /// It only defines **low-level, unchecked operations** - callers are
584 /// responsible for ensuring validity and equilibrium before invoking this
585 /// function.
586 ///
587 /// ## Returns
588 /// - `Ok(Asset)` containing the raised amount
589 /// - `Err(DispatchError)` if the raise operation fails
590 fn raise_pool_commit(
591 who: &Proprietor,
592 reason: &Pallet::Reason,
593 pool_of: &Pallet::Digest,
594 value: <Pallet as InspectAsset<Proprietor>>::Asset,
595 qualifier: &Pallet::Intent,
596 ) -> Result<<Pallet as InspectAsset<Proprietor>>::Asset, DispatchError>;
597
598 /// Resolves and finalizes a commitment for a fully resolved digest model.
599 ///
600 /// This method closes the commitment and provides the final withdrawn asset value
601 /// from the commitment to the reason.
602 ///
603 /// It only defines **low-level, unchecked operations** - callers are
604 /// responsible for ensuring validity and equilibrium before invoking this
605 /// function.
606 ///
607 /// ## Returns
608 /// - `Ok(Asset)` containing the resolved commitment value
609 /// - `Err(DispatchError)` if resolution fails
610 fn resolve_commit_of(
611 who: &Proprietor,
612 reason: &Pallet::Reason,
613 digest_model: &Pallet::Model,
614 ) -> Result<<Pallet as InspectAsset<Proprietor>>::Asset, DispatchError>;
615
616 /// Resolves and finalizes a commitment for a direct digest.
617 ///
618 /// This method closes the direct digest commitment and provides the
619 /// final withdrawn asset value from the commitment to the reason.
620 ///
621 /// It only defines **low-level, unchecked operations** - callers are
622 /// responsible for ensuring validity and equilibrium before invoking this
623 /// function.
624 ///
625 /// ## Returns
626 /// - `Ok(Asset)` containing the resolved commitment value
627 /// - `Err(DispatchError)` if resolution fails
628 fn resolve_digest_commit(
629 who: &Proprietor,
630 reason: &Pallet::Reason,
631 digest: &Pallet::Digest,
632 ) -> Result<<Pallet as InspectAsset<Proprietor>>::Asset, DispatchError>;
633
634 /// Resolves and finalizes a commitment for an index digest.
635 ///
636 /// This method closes the index digest commitment and provides the
637 /// final withdrawn asset value from the commitment to the reason.
638 ///
639 /// It only defines **low-level, unchecked operations** - callers are
640 /// responsible for ensuring validity and equilibrium before invoking this
641 /// function.
642 ///
643 /// ## Returns
644 /// - `Ok(Asset)` containing the resolved commitment value
645 /// - `Err(DispatchError)` if resolution fails
646 fn resolve_index_commit(
647 who: &Proprietor,
648 reason: &Pallet::Reason,
649 index_of: &Pallet::Digest,
650 ) -> Result<<Pallet as InspectAsset<Proprietor>>::Asset, DispatchError>;
651
652 /// Resolves and finalizes a commitment for a pool digest.
653 ///
654 /// This method closes the pool digest commitment and provides the
655 /// final withdrawn asset value from the commitment to the reason.
656 ///
657 /// It only defines **low-level, unchecked operations** - callers are
658 /// responsible for ensuring validity and equilibrium before invoking this
659 /// function.
660 ///
661 /// ## Returns
662 /// - `Ok(Asset)` containing the resolved commitment value
663 /// - `Err(DispatchError)` if resolution fails
664 fn resolve_pool_commit(
665 who: &Proprietor,
666 reason: &Pallet::Reason,
667 pool_of: &Pallet::Digest,
668 ) -> Result<<Pallet as InspectAsset<Proprietor>>::Asset, DispatchError>;
669
670 /// Sets the total asset value for a given reason.
671 ///
672 /// This is a **low-level function** and should only be used
673 /// when equilibrium is maintained, meaning the value being set must
674 /// correctly reflect the committed state of the system for the reason.
675 fn set_total_value(reason: &Pallet::Reason, value: <Pallet as InspectAsset<Proprietor>>::Asset);
676
677 /// Adds a given asset value to the total value for the specified reason.
678 ///
679 /// It only defines **low-level, unchecked operations** - callers are
680 /// responsible for ensuring validity and equilibrium before invoking this
681 /// function.
682 ///
683 /// ## Returns
684 /// - `Ok(())` if the addition succeeds
685 /// - `Err(DispatchError)` with `Overflow` if adding causes overflow
686 fn add_to_total_value(
687 reason: &Pallet::Reason,
688 value: <Pallet as InspectAsset<Proprietor>>::Asset,
689 ) -> DispatchResult {
690 let current = Pallet::get_total_value(reason);
691 let new_total = current
692 .checked_add(&value)
693 .ok_or(DispatchError::Arithmetic(ArithmeticError::Overflow))?;
694
695 Self::set_total_value(reason, new_total);
696 Ok(())
697 }
698
699 /// Subtracts a given asset value from the total value for the
700 /// specified reason.
701 ///
702 /// It only defines **low-level, unchecked operations** - callers are
703 /// responsible for ensuring validity and equilibrium before invoking
704 /// this function.
705 ///
706 /// ### Returns
707 /// - `Ok(())` if the subtraction succeeds
708 /// - `Err(DispatchError)` with `Underflow` if subtraction would
709 /// underflow
710 fn sub_from_total_value(
711 reason: &Pallet::Reason,
712 value: <Pallet as InspectAsset<Proprietor>>::Asset,
713 ) -> DispatchResult {
714 let current = Pallet::get_total_value(reason);
715 let new_total = current
716 .checked_sub(&value)
717 .ok_or(DispatchError::Arithmetic(ArithmeticError::Underflow))?;
718
719 Self::set_total_value(reason, new_total);
720 Ok(())
721 }
722}
723
724// ===============================================================================
725// ```````````````````````````````` COMMIT INSPECT ```````````````````````````````
726// ===============================================================================
727
728/// Provides inspection and querying capabilities for committed
729/// values across digests, indexes, and pools for a given proprietor.
730///
731/// This trait allows retrieving **real-time committed values** without
732/// altering state, supporting precise accounting and auditability.
733///
734/// This trait defines **low-level, unchecked operations** - callers are
735/// responsible for ensuring validity and equilibrium before invoking these
736/// functions.
737///
738/// ### Generics
739/// - **Proprietor** - the entity (e.g. account, vault, or manager)
740/// controlling the asset.
741/// - **Pallet** - the public struct implementing [`Commitment`] traits
742/// and [`LazyBalance`], ensuring consistent asset accounting across the
743/// commitment system.
744pub trait CommitInspect<Proprietor, Pallet>
745where
746 Pallet: LazyBalance<Asset = <Pallet as InspectAsset<Proprietor>>::Asset, Id = Pallet::Digest>
747 + DigestModel<Proprietor>
748 + Commitment<Proprietor>,
749{
750 /// Retrieves the real-time commitment value for a fully
751 /// resolved digest model.
752 ///
753 /// Aggregates all individual commit instances associated with
754 /// the digest model for the given proprietor and reason,
755 /// returning a single live value.
756 ///
757 /// ## Returns
758 /// - `Ok(Asset)` containing the total committed value for the digest model
759 /// - `Err(DispatchError)` if the value cannot be determined
760 fn commit_value_of(
761 who: &Proprietor,
762 reason: &Pallet::Reason,
763 digest_model: &Pallet::Model,
764 ) -> Result<<Pallet as InspectAsset<Proprietor>>::Asset, DispatchError>;
765
766 /// Retrieves the real-time commitment value for a direct digest.
767 ///
768 /// Returns the total value proprietor commit holds under the given
769 /// reason for the direct digest.
770 ///
771 /// ## Returns
772 /// - `Ok(Asset)` containing the committed value for the digest
773 /// - `Err(DispatchError)` if value cannot be retrieved
774 fn digest_commit_value(
775 who: &Proprietor,
776 reason: &Pallet::Reason,
777 digest: &Pallet::Digest,
778 ) -> Result<<Pallet as InspectAsset<Proprietor>>::Asset, DispatchError>;
779
780 /// Retrieves the real-time commitment value for an index digest.
781 ///
782 /// Computes the aggregate value across all entries contained
783 /// in the index for the specified proprietor and reason.
784 ///
785 /// ## Returns
786 /// - `Ok(Asset)` containing the total committed value across
787 /// all index entries
788 /// - `Err(DispatchError)` if value cannot be calculated
789 fn index_commit_value(
790 who: &Proprietor,
791 reason: &Pallet::Reason,
792 index_of: &Pallet::Digest,
793 ) -> Result<<Pallet as InspectAsset<Proprietor>>::Asset, DispatchError>;
794
795 /// Retrieves the real-time commitment value for a specific
796 /// entry within an index.
797 ///
798 /// Provides the real-time value for a single entry digest within
799 /// the index, reflecting the proprietor's commitment to that
800 /// specific entry.
801 ///
802 /// ## Returns
803 /// - `Ok(Asset)` containing the committed value for the entry
804 /// - `Err(DispatchError)` if value cannot be retrieved
805 fn index_entry_commit_value(
806 who: &Proprietor,
807 reason: &Pallet::Reason,
808 index_of: &Pallet::Digest,
809 entry_of: &Pallet::Digest,
810 ) -> Result<<Pallet as InspectAsset<Proprietor>>::Asset, DispatchError>;
811
812 /// Retrieves the real-time commitment value for
813 /// a **pool digest**.
814 ///
815 /// Aggregates the values of all slots under the pool for
816 /// the proprietor.
817 ///
818 /// ## Returns
819 /// - `Ok(Asset)` containing the total committed value
820 /// across all pool slots
821 /// - `Err(DispatchError)` if value cannot be calculated
822 fn pool_commit_value(
823 who: &Proprietor,
824 reason: &Pallet::Reason,
825 pool_of: &Pallet::Digest,
826 ) -> Result<<Pallet as InspectAsset<Proprietor>>::Asset, DispatchError>;
827
828 /// Retrieves the committed value of a specific slot for a
829 /// particular proprietor.
830 ///
831 /// Aggregates the proprietor's commitment to that slot within the
832 /// pool in real-time, showing their individual exposure to the slot.
833 ///
834 /// ### Returns
835 /// - `Ok(Asset)` containing the proprietor's committed value for the slot
836 /// - `Err(DispatchError)` if the slot does not exist or value cannot be
837 /// retrieved
838 fn pool_slot_commit_value(
839 who: &Proprietor,
840 reason: &Pallet::Reason,
841 pool_of: &Pallet::Digest,
842 slot_of: &Pallet::Digest,
843 ) -> Result<<Pallet as InspectAsset<Proprietor>>::Asset, DispatchError>;
844
845 /// Queries the real-time value of commitments for a given reason.
846 ///
847 /// This function calculates the current committed value based on the
848 /// provided parameters:
849 /// - If `digest_model` is provided, only values associated with that specific
850 /// digest model are included
851 /// - If `digest_model` is `None`, the total value across all relevant digests
852 /// for the reason is returned
853 ///
854 /// ## Returns
855 /// - `Ok(Asset)` containing the calculated total asset value
856 /// - `Err(DispatchError)` if the query fails or the value cannot be determined
857 fn value_of(
858 digest_model: Option<&Pallet::Model>,
859 reason: &Pallet::Reason,
860 ) -> Result<<Pallet as InspectAsset<Proprietor>>::Asset, DispatchError>;
861}
862
863// ===============================================================================
864// ``````````````````````````````` POOL OPERATIONS ```````````````````````````````
865// ===============================================================================
866
867/// Defines operational behavior for managing pooled balances within a commitment system.
868///
869/// A `PoolOps` implementation extends [`PoolVariant`] to provide concrete
870/// management logic for a proprietor's pooled balances, where a pool may act
871/// as a *single committing authority* maintaining aggregate or managed funds.
872///
873/// Unlike indexes (which represent discrete digests committed on behalf of a proprietor),
874/// pools aggregate balances and resolve them collectively, acting as a unified
875/// resource manager.
876///
877/// This trait defines **low-level, unchecked operations** - callers are
878/// responsible for ensuring validity and equilibrium before invoking these
879/// functions.
880///
881/// ### Generics
882/// - **Proprietor** - the entity (e.g. account, vault, or manager)
883/// controlling the asset.
884/// - **Pallet** - the public struct implementing [`Commitment`] traits
885/// and [`LazyBalance`], ensuring consistent asset accounting across the
886/// commitment system.
887pub trait PoolOps<Proprietor, Pallet>
888where
889 Pallet: LazyBalance<
890 Asset = <Pallet as InspectAsset<Proprietor>>::Asset,
891 Variant = Pallet::Position,
892 Id = Pallet::Digest,
893 > + PoolVariant<Proprietor>,
894{
895 /// The balance type associated with the pool.
896 type PoolBalance;
897
898 /// Releases a pool's balance, resetting it to its default state.
899 ///
900 /// Releasing a pool means resolving all active commit digests from this single balance,
901 /// similar in concept to resolving a commit.
902 ///
903 /// - The release-recovery should be **immediate** at the calling site - safety must
904 /// be ensured by the caller.
905 /// - Pools differ from indexes: while indexes resolve multiple digests per proprietor,
906 /// pools resolve from a *single managed balance* representing aggregated commitments.
907 ///
908 /// It only defines **low-level, unchecked operations** - callers are
909 /// responsible for ensuring validity and equilibrium before invoking this
910 /// function.
911 ///
912 /// ## Returns
913 /// - `Ok(PoolBalance)` containing the resolved pool balance
914 /// - `Err(DispatchError)` if the release operation fails
915 fn release_pool(
916 reason: &Pallet::Reason,
917 pool_of: &Pallet::Digest,
918 ) -> Result<Self::PoolBalance, DispatchError>;
919
920 /// Recovers a pool's state after a prior release via [`PoolOps::release_pool`].
921 ///
922 /// This function restores the pool's state following balance mutation or reconciliation.
923 /// Should only be invoked after the pool has been released via [`PoolOps::release_pool`].
924 ///
925 /// It only defines **low-level, unchecked operations** - callers are
926 /// responsible for ensuring validity and equilibrium before invoking this
927 /// function.
928 ///
929 /// ## Returns
930 /// - `Ok(())` if the pool state was successfully recovered
931 /// - `Err(DispatchError)` if recovery fails
932 fn recover_pool(
933 reason: &Pallet::Reason,
934 pool_of: &Pallet::Digest,
935 balance: &Self::PoolBalance,
936 ) -> DispatchResult;
937
938 /// Removes a slot from a pool and updates the pool's state accordingly.
939 ///
940 /// This operation ensures that:
941 /// - The slot represented by `slot_of` is removed from the pool.
942 /// - The pool's collective balance is released and then recovered to reflect
943 /// the updated state after removal.
944 ///
945 /// Automatically updates the pool's internal representation of managed funds.
946 ///
947 /// It only defines **low-level, unchecked operations** - callers are
948 /// responsible for ensuring validity and equilibrium before invoking this
949 /// function.
950 ///
951 /// ### Returns
952 /// - `Ok(())` if the slot was successfully removed and pool state updated
953 /// - `Err(DispatchError)` if the operation fails
954 fn remove_pool_slot(
955 who: &Proprietor,
956 reason: &Pallet::Reason,
957 pool_of: &Pallet::Digest,
958 slot_of: &Pallet::Digest,
959 ) -> DispatchResult;
960
961 /// Sets or updates a slot within a pool and synchronizes the pool's state.
962 ///
963 /// This operation may:
964 /// - Add a new slot to the pool.
965 /// - Update an existing slot's `shares` or `variant`.
966 /// - Trigger a pool release and recovery cycle to ensure
967 /// the pool's balance reflects the new slot configuration.
968 ///
969 /// It only defines **low-level, unchecked operations** - callers are
970 /// responsible for ensuring validity and equilibrium before invoking this
971 /// function.
972 ///
973 /// ## Behavior
974 /// - Ensures slot state consistency within the pool.
975 /// - Used for slot creation, update, or reallocation of pool shares.
976 ///
977 /// ### Returns
978 /// - `Ok(())` if the slot was successfully set and pool state synchronized
979 /// - `Err(DispatchError)` if the operation fails
980 fn set_pool_slot(
981 who: &Proprietor,
982 reason: &Pallet::Reason,
983 pool_of: &Pallet::Digest,
984 slot_of: &Pallet::Digest,
985 shares: Pallet::Shares,
986 variant: &Pallet::Position,
987 ) -> DispatchResult;
988}
989
990// ===============================================================================
991// ``````````````````````````````` INDEX OPERATIONS ``````````````````````````````
992// ===============================================================================
993
994/// Defines operational behavior for managing indexed digests within a commitment system.
995///
996/// An `IndexOps` implementation extends [`IndexVariant`] to provide concrete
997/// management logic for a proprietor's indexed commitments, where an index acts
998/// as a container of discrete digest entries.
999///
1000/// Unlike pools (which aggregate balances collectively), indexes represent
1001/// *structured groupings* of digests that can be individually set or removed,
1002/// allowing for fine-grained commit management.
1003///
1004/// This trait defines **low-level, unchecked operations** - callers are
1005/// responsible for ensuring validity and equilibrium before invoking these
1006/// functions.
1007///
1008/// ### Generics
1009/// - **Proprietor** - the entity (e.g. account, vault, or manager)
1010/// controlling the asset.
1011/// - **Pallet** - the public struct implementing [`Commitment`] traits
1012/// and [`LazyBalance`], ensuring consistent asset accounting across the
1013/// commitment system.
1014pub trait IndexOps<Proprietor, Pallet>
1015where
1016 Pallet: LazyBalance<
1017 Asset = <Pallet as InspectAsset<Proprietor>>::Asset,
1018 Variant = Pallet::Position,
1019 Id = Pallet::Digest,
1020 > + IndexVariant<Proprietor>,
1021{
1022 /// Removes a digest entry from an index for the given proprietor and reason.
1023 ///
1024 /// Since indexes are immutable, this operation creates a new index without
1025 /// the specified entry and generates a new digest for it. The caller is
1026 /// responsible for managing the lifecycle of the old index digest.
1027 ///
1028 /// This is a **low-level, unchecked operation** - callers must ensure
1029 /// equilibrium and invariant safety before calling.
1030 ///
1031 /// ## Returns
1032 /// - `Ok(Digest)` containing the new index digest after entry removal
1033 /// - `Err(DispatchError)` if the operation fails
1034 fn remove_index_entry(
1035 who: &Proprietor,
1036 reason: &Pallet::Reason,
1037 index_of: &Pallet::Digest,
1038 entry_of: &Pallet::Digest,
1039 ) -> Result<Pallet::Digest, DispatchError>;
1040
1041 /// Sets or updates a digest entry within an index and returns the new index digest.
1042 ///
1043 /// Since indexes are immutable, this operation creates a new index with the updated
1044 /// entry configuration (shares and variant) and generates a new digest for it.
1045 /// If the entry exists, it is updated; otherwise, it is added.
1046 ///
1047 /// This is a **low-level, unchecked operation** - callers must ensure
1048 /// equilibrium and invariant safety before calling.
1049 ///
1050 /// ## Returns
1051 /// - `Ok(Digest)` containing the new index digest after entry modification
1052 /// - `Err(DispatchError)` if the operation fails
1053 fn set_index_entry(
1054 who: &Proprietor,
1055 reason: &Pallet::Reason,
1056 index_of: &Pallet::Digest,
1057 entry_of: &Pallet::Digest,
1058 shares: Pallet::Shares,
1059 variant: &Pallet::Position,
1060 ) -> Result<Pallet::Digest, DispatchError>;
1061}