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;