Skip to main content

CollateralBufferResult

Enum CollateralBufferResult 

Source
pub enum CollateralBufferResult {
    Known {
        epoch: u64,
        protocol_version: u16,
        funding_state: CollateralFundingState,
        recommended_buffer_dig_base_units: u64,
        spendable_dig_base_units: u64,
        pairs_served_by_this_node: u64,
        required_per_store_dig_base_units: u64,
        margin_bp: u64,
        overlap_dig_base_units: u64,
        escalation_headroom_dig_base_units: u64,
        horizon_epochs: u32,
        escalation_ceiling_micros: u64,
    },
    Unknown {
        reason: CollateralBufferUnknownReason,
    },
}
Expand description

control.collateral.buffer — the $DIG this node recommends holding, and where it stands against that figure.

Every amount here is in DIG BASE UNITS. $DIG carries 3 decimals, so one base unit is 0.001 DIG. It is NOT a mojo: a mojo is XCH’s base unit at 1e-12 XCH, nine orders of magnitude away. margin_bp is the one field that is not an amount and is in BASIS POINTS (100 is +1%), the unit the collateral crate’s own presets and rounding use, never converted.

UNKNOWN is a first-class answer, and a zero here is the money lie in its purest form. On control.collateral.requirement a fabricated zero reads as a free requirement; here it reads as no buffer needed, which is worse, because an operator acting on it would post nothing and lose the epoch. A node that cannot enumerate the pairs it serves, cannot read its reclaim state, or cannot see its balance says so WITH the reason — the tagged variant means there is no representable state in which a client holds a figure it was never given.

The horizon travels with the buffer, because a buffer without one is a magic number. The escalation of the per-store requirement is bounded at +12.5% per epoch and COMPOUNDS: about x1.12 at one epoch, x1.60 at four, x4.62 at thirteen. Two nodes quoting a buffer over different horizons are answering different questions, and neither figure can be checked without knowing which. escalation_ceiling_micros states the multiplier this node assumed, and it is a WORST CASE, not a forecast: inside the controller’s dead band the multiplier does not move at all.

The total is authoritative; the terms are the working. recommended_buffer_dig_base_units is the figure to hold and the figure funding_state was decided against. The other fields exist so a client can show WHY that number is what it is — which is the difference between a figure an operator can weigh and one they can only accept — and a client MUST NOT re-add them and prefer its own sum, because rounding lives in the node’s arithmetic, not the client’s.

Why this is not part of CollateralRequirementResult. The requirement is consensus-derived and every node derives it identically; the buffer is LOCAL — it depends on the pairs this particular node serves, on an operator preference (the margin), and on a horizon this node chose. 0.23.0 kept the margin out of the requirement on exactly that grounds, and the same reasoning binds harder here, because a buffer folded into the requirement’s result would make one node’s preferences look like the network’s price.

Variants§

§

Known

The node can state its buffer and its position against it.

Fields

§epoch: u64

The epoch the underlying requirement governs, one-based.

§protocol_version: u16

The collateral protocol version that COMPUTED that epoch, carried for the same reason CollateralRequirementResult::Known carries it: a client holding only numbers cannot tell a disagreement from a rule change.

§funding_state: CollateralFundingState

Where this node stands against recommended_buffer_dig_base_units.

§recommended_buffer_dig_base_units: u64

The $DIG this node recommends holding, in DIG base units. The authoritative figure.

§spendable_dig_base_units: u64

The spendable $DIG the node compared against the buffer, in DIG base units.

Carried so funding_state is checkable rather than merely assertive: a client can show the two numbers the verdict came from. It is what is SPENDABLE — collateral already locked is not in it.

§pairs_served_by_this_node: u64

Qualifying (owner, store, root) pairs THIS NODE serves.

This node’s own set, never the census stores count, which is a network-wide advertisement count. Multiplying the census figure by the requirement is the confident, badly wrong number this field exists to prevent.

§required_per_store_dig_base_units: u64

The epoch’s per-store requirement, in DIG base units, BEFORE any local safety margin — the same value control.collateral.requirement returns.

§margin_bp: u64

The local safety margin in force, in BASIS POINTS (100 is +1%).

§overlap_dig_base_units: u64

Collateral still locked against positions this node has not yet reclaimed, in DIG base units.

A transition overlap: during the changeover the node must be able to cover the new epoch while the previous epoch’s posting is not yet back. It is NOT derivable from any other field here, which is why a node that cannot read its reclaim state answers ReclaimStateUnknown rather than omitting the term.

§escalation_headroom_dig_base_units: u64

The headroom included for the requirement escalating over horizon_epochs, in DIG base units. Also not derivable client-side, because it depends on the horizon and ceiling this node chose.

§horizon_epochs: u32

How many future epochs the headroom covers. Never implied, never defaulted by a reader: the same buffer over a different horizon is a different claim.

§escalation_ceiling_micros: u64

The compounded WORST-CASE escalation multiplier assumed over horizon_epochs, in millionths (1_000_000 is x1.0).

A ceiling, not a forecast. Escalation is capped at +12.5% per epoch, so four epochs bound at roughly 1_601_806 (x1.60); in the dead band the multiplier does not move at all and the realised figure is 1_000_000. A surface presenting this as an expectation would tell an operator to hold money for a rise the controller may never make.

§

Unknown

The node cannot state the buffer, and names which fact is missing.

Fields

§reason: CollateralBufferUnknownReason

Which fact the node is missing.

Trait Implementations§

Source§

impl Clone for CollateralBufferResult

Source§

fn clone(&self) -> CollateralBufferResult

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 CollateralBufferResult

Source§

impl Debug for CollateralBufferResult

Source§

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

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

impl<'de> Deserialize<'de> for CollateralBufferResult

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 Eq for CollateralBufferResult

Source§

impl PartialEq for CollateralBufferResult

Source§

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

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

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

Inequality operator !=. Read more
Source§

impl Serialize for CollateralBufferResult

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 StructuralPartialEq for CollateralBufferResult

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

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> 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.