gear_common/gas_provider/
auxiliary.rs

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