Skip to main content

gear_common/gas_provider/
mod.rs

1// Copyright (C) Gear Technologies Inc.
2// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0
3
4use super::*;
5use frame_support::traits::tokens::Balance as BalanceTrait;
6use sp_runtime::{RuntimeDebug, traits::Zero};
7use sp_std::marker::PhantomData;
8
9mod error;
10mod internal;
11mod lockable;
12mod negative_imbalance;
13mod node;
14mod positive_imbalance;
15mod reservable;
16
17#[cfg(feature = "std")]
18pub mod auxiliary;
19
20#[cfg(test)]
21mod property_tests;
22
23pub use error::Error;
24pub use internal::TreeImpl;
25pub use lockable::{LockId, LockableTree};
26pub use negative_imbalance::NegativeImbalance;
27pub use node::{ChildrenRefs, GasNode, GasNodeId, NodeLock};
28pub use positive_imbalance::PositiveImbalance;
29pub use reservable::ReservableTree;
30
31/// Simplified type for result of `GasTree::consume` call.
32pub type ConsumeResultOf<T> = Result<
33    Option<(
34        <T as Tree>::NegativeImbalance,
35        GasMultiplier<<T as Tree>::Funds, <T as Tree>::Balance>,
36        <T as Tree>::ExternalOrigin,
37    )>,
38    <T as Tree>::Error,
39>;
40
41/// Simplified type for `GasTree::get_origin_node` call.
42pub type OriginNodeDataOf<T> = (
43    <T as Tree>::ExternalOrigin,
44    GasMultiplier<<T as Tree>::Funds, <T as Tree>::Balance>,
45    <T as Tree>::NodeId,
46);
47
48/// Abstraction for a chain of value items each piece of which has an attributed
49/// owner and can be traced up to some root origin.
50///
51/// The definition is largely inspired by the `frame_support::traits::Currency`,
52/// however, the intended use is very close to the UTxO based ledger model.
53pub trait Tree {
54    /// Type representing the external owner of a value (gas) item.
55    type ExternalOrigin;
56
57    /// Type that identifies a node of the tree.
58    type NodeId: Clone;
59
60    /// Type representing a quantity of value.
61    type Balance: Clone;
62
63    /// Type representing a quantity of token balance.
64    type Funds: Clone;
65
66    // Types to denote a result of some unbalancing operation - that is
67    // operations that create inequality between the underlying value
68    // supply and some hypothetical "collateral" asset.
69
70    /// `PositiveImbalance` indicates that some value has been added
71    /// to circulation , i.e. total supply has increased.
72    type PositiveImbalance: Imbalance<Balance = Self::Balance>;
73
74    /// `NegativeImbalance` indicates that some value has been removed
75    /// from circulation, i.e. total supply has decreased.
76    type NegativeImbalance: Imbalance<Balance = Self::Balance>;
77
78    type InternalError: Error;
79
80    /// Error type
81    type Error: From<Self::InternalError>;
82
83    /// The total amount of value currently in circulation.
84    fn total_supply() -> Self::Balance;
85
86    /// Increase the total issuance of the underlying value by creating some
87    /// `amount` of it and attributing it to the `origin`.
88    ///
89    /// The `key` identifies the created "bag" of value. In case the `key`
90    /// already identifies some other piece of value an error is returned.
91    fn create(
92        origin: Self::ExternalOrigin,
93        multiplier: GasMultiplier<Self::Funds, Self::Balance>,
94        key: impl Into<Self::NodeId>,
95        amount: Self::Balance,
96    ) -> Result<Self::PositiveImbalance, Self::Error>;
97
98    /// The id of node, external origin and funds multiplier for a key.
99    ///
100    /// Error occurs if the tree is invalidated (has "orphan" nodes), and the
101    /// node identified by the `key` belongs to a subtree originating at
102    /// such "orphan" node, or in case of inexistent key.
103    fn get_origin_node(key: impl Into<Self::NodeId>)
104    -> Result<OriginNodeDataOf<Self>, Self::Error>;
105
106    /// The external origin for a key.
107    ///
108    /// See [`get_origin_node`](Self::get_origin_node) for details.
109    fn get_external(key: impl Into<Self::NodeId>) -> Result<Self::ExternalOrigin, Self::Error> {
110        Self::get_origin_node(key).map(|(external, _multiplier, _key)| external)
111    }
112
113    /// The funds multiplier for a key.
114    ///
115    /// See [`get_origin_node`](Self::get_origin_node) for details.
116    fn get_funds_multiplier(
117        key: impl Into<Self::NodeId>,
118    ) -> Result<GasMultiplier<Self::Funds, Self::Balance>, Self::Error> {
119        Self::get_origin_node(key).map(|(_external, multiplier, _key)| multiplier)
120    }
121
122    /// The id of external node for a key.
123    ///
124    /// See [`get_origin_node`](Self::get_origin_node) for details.
125    fn get_origin_key(key: impl Into<Self::NodeId>) -> Result<Self::NodeId, Self::Error> {
126        Self::get_origin_node(key).map(|(_external, _multiplier, key)| key)
127    }
128
129    /// Get value associated with given id and the key of an ancestor,
130    /// that keeps this value.
131    ///
132    /// Error occurs if the tree is invalidated (has "orphan" nodes), and the
133    /// node identified by the `key` belongs to a subtree originating at
134    /// such "orphan" node, or in case of inexistent key.
135    fn get_limit_node(
136        key: impl Into<Self::NodeId>,
137    ) -> Result<(Self::Balance, Self::NodeId), Self::Error>;
138
139    /// Get value associated with given id and the key of an consumed ancestor,
140    /// that keeps this value.
141    ///
142    /// Error occurs if the tree is invalidated (has "orphan" nodes), and the
143    /// node identified by the `key` belongs to a subtree originating at
144    /// such "orphan" node, or in case of inexistent key.
145    fn get_limit_node_consumed(
146        key: impl Into<Self::NodeId>,
147    ) -> Result<(Self::Balance, Self::NodeId), Self::Error>;
148
149    /// Get value associated with given id.
150    ///
151    /// See [`get_limit_node`](Self::get_limit_node) for details.
152    fn get_limit(key: impl Into<Self::NodeId>) -> Result<Self::Balance, Self::Error> {
153        Self::get_limit_node(key).map(|(balance, _key)| balance)
154    }
155
156    /// Get value associated with given id within consumed node.
157    ///
158    /// See [`get_limit_node_consumed`](Self::get_limit_node_consumed) for details.
159    fn get_limit_consumed(key: impl Into<Self::NodeId>) -> Result<Self::Balance, Self::Error> {
160        Self::get_limit_node_consumed(key).map(|(balance, _key)| balance)
161    }
162
163    /// Consume underlying value.
164    ///
165    /// If `key` does not identify any value or the value can't be fully
166    /// consumed due to being a part of other value or itself having
167    /// unconsumed parts, return `None`, else the corresponding
168    /// piece of value is destroyed and imbalance is created.
169    ///
170    /// Error occurs if the tree is invalidated (has "orphan" nodes), and the
171    /// node identified by the `key` belongs to a subtree originating at
172    /// such "orphan" node, or in case of inexistent key.
173    fn consume(key: impl Into<Self::NodeId>) -> ConsumeResultOf<Self>;
174
175    /// Burn underlying value.
176    ///
177    /// This "spends" the specified amount of value thereby decreasing the
178    /// overall supply of it. In case of a success, this indicates the
179    /// entire value supply becomes over-collateralized,
180    /// hence negative imbalance.
181    fn spend(
182        key: impl Into<Self::NodeId>,
183        amount: Self::Balance,
184    ) -> Result<Self::NegativeImbalance, Self::Error>;
185
186    /// Split underlying value.
187    ///
188    /// If `key` does not identify any value or the `amount` exceeds what's
189    /// locked under that key, an error is returned.
190    ///
191    /// This can't create imbalance as no value is burned or created.
192    fn split_with_value(
193        key: impl Into<Self::NodeId>,
194        new_key: impl Into<Self::NodeId>,
195        amount: Self::Balance,
196    ) -> Result<(), Self::Error>;
197
198    /// Split underlying value.
199    ///
200    /// If `key` does not identify any value an error is returned.
201    ///
202    /// This can't create imbalance as no value is burned or created.
203    fn split(
204        key: impl Into<Self::NodeId>,
205        new_key: impl Into<Self::NodeId>,
206    ) -> Result<(), Self::Error>;
207
208    /// Cut underlying value to a reserved node.
209    ///
210    /// If `key` does not identify any value or the `amount` exceeds what's
211    /// locked under that key, an error is returned.
212    ///
213    /// This can't create imbalance as no value is burned or created.
214    fn cut(
215        key: impl Into<Self::NodeId>,
216        new_key: impl Into<Self::NodeId>,
217        amount: Self::Balance,
218    ) -> Result<(), Self::Error>;
219
220    /// Creates deposit external node to be used as pre-defined gas node.
221    fn create_deposit(
222        key: impl Into<Self::NodeId>,
223        new_key: impl Into<Self::NodeId>,
224        amount: Self::Balance,
225    ) -> Result<(), Self::Error>;
226
227    /// Return bool, defining does node exist.
228    fn exists(key: impl Into<Self::NodeId>) -> bool;
229
230    /// Returns bool, defining does node exist and is external with deposit.
231    fn exists_and_deposit(key: impl Into<Self::NodeId>) -> bool;
232
233    /// Removes all values.
234    fn clear();
235}
236
237/// Represents logic of centralized GasTree-algorithm.
238pub trait Provider {
239    /// Type representing the external owner of a value (gas) item.
240    type ExternalOrigin;
241
242    /// Type that identifies a tree node.
243    type NodeId;
244
245    /// Type representing a quantity of value.
246    type Balance;
247
248    /// Type representing a quantity of token balance.
249    type Funds;
250
251    // Types to denote a result of some unbalancing operation - that is
252    // operations that create inequality between the underlying value
253    // supply and some hypothetical "collateral" asset.
254
255    type InternalError: Error;
256
257    /// Error type.
258    type Error: From<Self::InternalError>;
259
260    /// A ledger to account for gas creation and consumption.
261    type GasTree: LockableTree<
262            ExternalOrigin = Self::ExternalOrigin,
263            NodeId = Self::NodeId,
264            Balance = Self::Balance,
265            Funds = Self::Funds,
266            InternalError = Self::InternalError,
267            Error = Self::Error,
268        > + ReservableTree;
269
270    /// Resets all related to gas provider storages.
271    ///
272    /// It's a temporary production solution to avoid DB migrations
273    /// and would be available for test purposes only in the future.
274    fn reset() {
275        Self::GasTree::clear();
276    }
277}
278
279/// Represents either added or removed value to/from total supply of the currency.
280pub trait Imbalance {
281    type Balance;
282
283    /// Returns imbalance raw value.
284    fn peek(&self) -> Self::Balance;
285
286    /// Applies imbalance to some amount.
287    fn apply_to(&self, amount: &mut Option<Self::Balance>) -> Result<(), ImbalanceError>;
288}
289
290/// Represents errors returned by via the [Imbalance] trait.
291/// Indicates the imbalance value causes amount value overflowing
292/// when applied to the latter.
293#[derive(Debug, PartialEq)]
294pub struct ImbalanceError;