Skip to main content

gear_common/gas_provider/
auxiliary.rs

1// Copyright (C) Gear Technologies Inc.
2// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0
3
4//! Auxiliary implementation of the gas provider.
5
6use crate::{
7    Origin,
8    gas_provider::{Error, GasNode, GasNodeId, Provider, TreeImpl},
9    storage::{MapStorage, ValueStorage},
10};
11use alloc::collections::BTreeMap;
12use core::{
13    cell::{Ref, RefMut},
14    marker::PhantomData,
15};
16use sp_core::H256;
17use std::thread::LocalKey;
18
19/// Balance type used in the gas tree.
20pub(crate) type Balance = u64;
21/// Type represents token value equivalent of gas.
22pub(crate) type Funds = u128;
23/// Type represents gas tree node id, which is a key for gas nodes map storage.
24pub type NodeId = GasNodeId<PlainNodeId, ReservationNodeId>;
25/// Type represents gas tree node, which is a value for gas nodes map storage.
26pub type Node = GasNode<ExternalOrigin, NodeId, Balance, Funds>;
27
28/// Gas provider implementor used in native, non-wasm runtimes.
29pub struct AuxiliaryGasProvider<TIStorage, TIProvider, GNStorage, GNProvider>(
30    PhantomData<(TIStorage, TIProvider, GNStorage, GNProvider)>,
31);
32
33impl<TIStorage, TIProvider, GNStorage, GNProvider> Provider
34    for AuxiliaryGasProvider<TIStorage, TIProvider, GNStorage, GNProvider>
35where
36    TIStorage: TotalIssuanceStorage<TIProvider> + 'static,
37    TIProvider: TotalIssuanceProvider + 'static,
38    GNStorage: GasNodesStorage<GNProvider> + 'static,
39    GNProvider: GasNodesProvider + 'static,
40{
41    type ExternalOrigin = ExternalOrigin;
42    type NodeId = NodeId;
43    type Balance = Balance;
44    type Funds = Funds;
45    type InternalError = GasTreeError;
46    type Error = GasTreeError;
47
48    type GasTree = TreeImpl<
49        TotalIssuanceWrap<TIStorage, TIProvider>,
50        Self::InternalError,
51        Self::Error,
52        ExternalOrigin,
53        Self::NodeId,
54        GasNodesWrap<GNStorage, GNProvider>,
55    >;
56}
57
58#[derive(Debug, Copy, Hash, Clone, Eq, PartialEq, Ord, PartialOrd)]
59pub struct ExternalOrigin(pub H256);
60
61impl Origin for ExternalOrigin {
62    fn into_origin(self) -> H256 {
63        self.0
64    }
65
66    fn from_origin(val: H256) -> Self {
67        Self(val)
68    }
69}
70
71#[derive(Debug, Copy, Hash, Clone, Eq, PartialEq, Ord, PartialOrd)]
72pub struct PlainNodeId(pub H256);
73
74impl Origin for PlainNodeId {
75    fn into_origin(self) -> H256 {
76        self.0
77    }
78
79    fn from_origin(val: H256) -> Self {
80        Self(val)
81    }
82}
83
84impl<U> From<PlainNodeId> for GasNodeId<PlainNodeId, U> {
85    fn from(plain_node_id: PlainNodeId) -> Self {
86        Self::Node(plain_node_id)
87    }
88}
89
90#[derive(Debug, Copy, Hash, Clone, Eq, PartialEq, Ord, PartialOrd)]
91pub struct ReservationNodeId(pub H256);
92
93impl Origin for ReservationNodeId {
94    fn into_origin(self) -> H256 {
95        self.0
96    }
97
98    fn from_origin(val: H256) -> Self {
99        Self(val)
100    }
101}
102
103impl<T> From<ReservationNodeId> for GasNodeId<T, ReservationNodeId> {
104    fn from(node_id: ReservationNodeId) -> Self {
105        Self::Reservation(node_id)
106    }
107}
108
109/// Error type serving error variants returned from gas tree methods.
110#[derive(Clone, Copy, Debug, Eq, PartialEq)]
111pub enum GasTreeError {
112    NodeAlreadyExists,
113    ParentIsLost,
114    ParentHasNoChildren,
115    NodeNotFound,
116    NodeWasConsumed,
117    InsufficientBalance,
118    Forbidden,
119    UnexpectedConsumeOutput,
120    UnexpectedNodeType,
121    ValueIsNotCaught,
122    ValueIsBlocked,
123    ValueIsNotBlocked,
124    ConsumedWithLock,
125    ConsumedWithSystemReservation,
126    TotalValueIsOverflowed,
127    TotalValueIsUnderflowed,
128}
129
130impl Error for GasTreeError {
131    fn node_already_exists() -> Self {
132        Self::NodeAlreadyExists
133    }
134
135    fn parent_is_lost() -> Self {
136        Self::ParentIsLost
137    }
138
139    fn parent_has_no_children() -> Self {
140        Self::ParentHasNoChildren
141    }
142
143    fn node_not_found() -> Self {
144        Self::NodeNotFound
145    }
146
147    fn node_was_consumed() -> Self {
148        Self::NodeWasConsumed
149    }
150
151    fn insufficient_balance() -> Self {
152        Self::InsufficientBalance
153    }
154
155    fn forbidden() -> Self {
156        Self::Forbidden
157    }
158
159    fn unexpected_consume_output() -> Self {
160        Self::UnexpectedConsumeOutput
161    }
162
163    fn unexpected_node_type() -> Self {
164        Self::UnexpectedNodeType
165    }
166
167    fn value_is_not_caught() -> Self {
168        Self::ValueIsNotCaught
169    }
170
171    fn value_is_blocked() -> Self {
172        Self::ValueIsBlocked
173    }
174
175    fn value_is_not_blocked() -> Self {
176        Self::ValueIsNotBlocked
177    }
178
179    fn consumed_with_lock() -> Self {
180        Self::ConsumedWithLock
181    }
182
183    fn consumed_with_system_reservation() -> Self {
184        Self::ConsumedWithSystemReservation
185    }
186
187    fn total_value_is_overflowed() -> Self {
188        Self::TotalValueIsOverflowed
189    }
190
191    fn total_value_is_underflowed() -> Self {
192        Self::TotalValueIsUnderflowed
193    }
194}
195
196pub trait TotalIssuanceStorage<T: TotalIssuanceProvider> {
197    fn storage() -> &'static LocalKey<T>;
198}
199
200pub trait TotalIssuanceProvider {
201    fn data(&self) -> Ref<'_, Option<Balance>>;
202    fn data_mut(&self) -> RefMut<'_, Option<Balance>>;
203}
204
205/// Global `TotalIssuance` storage manager.
206#[derive(Debug, PartialEq, Eq)]
207pub struct TotalIssuanceWrap<TIStorage, TIProvider>(PhantomData<(TIStorage, TIProvider)>);
208
209impl<TIStorage, TIProvider> ValueStorage for TotalIssuanceWrap<TIStorage, TIProvider>
210where
211    TIStorage: TotalIssuanceStorage<TIProvider> + 'static,
212    TIProvider: TotalIssuanceProvider + 'static,
213{
214    type Value = Balance;
215
216    fn exists() -> bool {
217        TIStorage::storage().with(|i| i.data().is_some())
218    }
219
220    fn get() -> Option<Self::Value> {
221        TIStorage::storage().with(|i| *i.data())
222    }
223
224    fn kill() {
225        TIStorage::storage().with(|i| {
226            let mut data = i.data_mut();
227            *data = None;
228        });
229    }
230
231    fn mutate<R, F: FnOnce(&mut Option<Self::Value>) -> R>(f: F) -> R {
232        TIStorage::storage().with(|i| f(&mut i.data_mut()))
233    }
234
235    fn put(value: Self::Value) {
236        TIStorage::storage().with(|i| {
237            i.data_mut().replace(value);
238        });
239    }
240
241    fn set(value: Self::Value) -> Option<Self::Value> {
242        Self::mutate(|opt| {
243            let prev = opt.take();
244            *opt = Some(value);
245            prev
246        })
247    }
248
249    fn take() -> Option<Self::Value> {
250        TIStorage::storage().with(|i| i.data_mut().take())
251    }
252}
253
254pub trait GasNodesStorage<T: GasNodesProvider> {
255    fn storage() -> &'static LocalKey<T>;
256}
257
258pub trait GasNodesProvider {
259    fn data(&self) -> Ref<'_, BTreeMap<NodeId, Node>>;
260    fn data_mut(&self) -> RefMut<'_, BTreeMap<NodeId, Node>>;
261}
262
263/// Global `GasNodes` storage manager.
264pub struct GasNodesWrap<GNStorage, GNProvider>(PhantomData<(GNStorage, GNProvider)>);
265
266impl<GNStorage, GNProvider> MapStorage for GasNodesWrap<GNStorage, GNProvider>
267where
268    GNStorage: GasNodesStorage<GNProvider> + 'static,
269    GNProvider: GasNodesProvider + 'static,
270{
271    type Key = NodeId;
272    type Value = Node;
273
274    fn contains_key(key: &Self::Key) -> bool {
275        GNStorage::storage().with(|tree| tree.data().contains_key(key))
276    }
277
278    fn get(key: &Self::Key) -> Option<Self::Value> {
279        GNStorage::storage().with(|tree| tree.data().get(key).cloned())
280    }
281
282    fn insert(key: Self::Key, value: Self::Value) {
283        GNStorage::storage().with(|tree| {
284            tree.data_mut().insert(key, value);
285        });
286    }
287
288    fn mutate<R, F: FnOnce(&mut Option<Self::Value>) -> R>(_key: Self::Key, _f: F) -> R {
289        unimplemented!()
290    }
291
292    fn mutate_values<F: FnMut(Self::Value) -> Self::Value>(mut _f: F) {
293        unimplemented!()
294    }
295
296    fn remove(key: Self::Key) {
297        GNStorage::storage().with(|tree| {
298            tree.data_mut().remove(&key);
299        });
300    }
301
302    fn clear() {
303        GNStorage::storage().with(|tree| {
304            tree.data_mut().clear();
305        });
306    }
307
308    fn take(key: Self::Key) -> Option<Self::Value> {
309        GNStorage::storage().with(|tree| tree.data_mut().remove(&key))
310    }
311}