muta_protocol/traits/
binding.rs

1use std::iter::Iterator;
2
3use derive_more::{Display, From};
4
5use crate::fixed_codec::FixedCodec;
6use crate::types::{Address, Epoch, Hash, MerkleRoot, Receipt, ServiceContext, SignedTransaction};
7use crate::{ProtocolError, ProtocolErrorKind, ProtocolResult};
8
9#[derive(Debug, Display, From)]
10pub enum BindingMacroError {
11    #[display(fmt = "service {:?} method {:?} was not found", service, method)]
12    NotFoundMethod { service: String, method: String },
13
14    #[display(fmt = "Parsing payload to json failed {:?}", _0)]
15    JsonParse(serde_json::Error),
16}
17impl std::error::Error for BindingMacroError {}
18
19impl From<BindingMacroError> for ProtocolError {
20    fn from(err: BindingMacroError) -> ProtocolError {
21        ProtocolError::new(ProtocolErrorKind::BindingMacro, Box::new(err))
22    }
23}
24
25pub trait ServiceMapping: Send + Sync {
26    fn get_service<SDK: 'static + ServiceSDK>(
27        &self,
28        name: &str,
29        sdk: SDK,
30    ) -> ProtocolResult<Box<dyn Service>>;
31
32    fn list_service_name(&self) -> Vec<String>;
33}
34
35// `ServiceState` provides access to` world state` and `account` for` service`.
36// The bottom layer is an MPT tree.
37//
38// Each `service` will have a separate` ServiceState`, so their states are
39// isolated from each other.
40pub trait ServiceState {
41    fn get<Key: FixedCodec, Ret: FixedCodec>(&self, key: &Key) -> ProtocolResult<Option<Ret>>;
42
43    fn contains<Key: FixedCodec>(&self, key: &Key) -> ProtocolResult<bool>;
44
45    // Insert a pair of key / value
46    // Note: This key/value pair will go into the cache first
47    // and will not be persisted to MPT until `commit` is called.
48    fn insert<Key: FixedCodec, Value: FixedCodec>(
49        &mut self,
50        key: Key,
51        value: Value,
52    ) -> ProtocolResult<()>;
53
54    fn get_account_value<Key: FixedCodec, Ret: FixedCodec>(
55        &self,
56        address: &Address,
57        key: &Key,
58    ) -> ProtocolResult<Option<Ret>>;
59
60    fn set_account_value<Key: FixedCodec, Val: FixedCodec>(
61        &mut self,
62        address: &Address,
63        key: Key,
64        val: Val,
65    ) -> ProtocolResult<()>;
66
67    // Roll back all data in the cache
68    fn revert_cache(&mut self) -> ProtocolResult<()>;
69
70    // Move data from cache to stash
71    fn stash(&mut self) -> ProtocolResult<()>;
72
73    // Persist data from stash into MPT
74    fn commit(&mut self) -> ProtocolResult<MerkleRoot>;
75}
76
77pub trait ChainQuerier {
78    fn get_transaction_by_hash(&self, tx_hash: &Hash) -> ProtocolResult<Option<SignedTransaction>>;
79
80    // To get the latest `Epoch` of finality, set `epoch_id` to `None`
81    fn get_epoch_by_epoch_id(&self, epoch_id: Option<u64>) -> ProtocolResult<Option<Epoch>>;
82
83    fn get_receipt_by_hash(&self, tx_hash: &Hash) -> ProtocolResult<Option<Receipt>>;
84}
85
86// Admission control will be called before entering service
87pub trait AdmissionControl {
88    fn next<SDK: ServiceSDK>(&self, ctx: ServiceContext, sdk: SDK) -> ProtocolResult<()>;
89}
90
91// Developers can use service to customize blockchain business
92//
93// It contains:
94// - init: Initialize the service.
95// - hooks: A pair of hooks that allow inserting a piece of logic before and
96//   after the epoch is executed.
97// - read: Provide some read-only functions for users or other services to call
98// - write: provide some writable functions for users or other services to call
99pub trait Service {
100    // Executed to create genesis states when starting chain
101    fn genesis_(&mut self, _payload: String) -> ProtocolResult<()> {
102        Ok(())
103    }
104
105    // Executed before the epoch is executed.
106    fn hook_before_(&mut self) -> ProtocolResult<()> {
107        Ok(())
108    }
109
110    // Executed after epoch execution.
111    fn hook_after_(&mut self) -> ProtocolResult<()> {
112        Ok(())
113    }
114
115    fn write_(&mut self, ctx: ServiceContext) -> ProtocolResult<String>;
116
117    fn read_(&self, ctx: ServiceContext) -> ProtocolResult<String>;
118}
119
120// `ServiceSDK` provides multiple rich interfaces for `service` developers
121//
122// It contains:
123//
124// - Various data structures that store data to `world state`(call
125//   `alloc_or_recover_*`)
126// - Access and modify `account`
127// - Access service state
128// - Event triggered
129// - Access to data on the chain (epoch, transaction, receipt)
130// - Read / write other `service`
131//
132// In fact, these functions depend on:
133//
134// - ChainDB
135// - ServiceState
136pub trait ServiceSDK {
137    // Alloc or recover a `Map` by` var_name`
138    fn alloc_or_recover_map<Key: 'static + FixedCodec + PartialEq, Val: 'static + FixedCodec>(
139        &mut self,
140        var_name: &str,
141    ) -> ProtocolResult<Box<dyn StoreMap<Key, Val>>>;
142
143    // Alloc or recover a `Array` by` var_name`
144    fn alloc_or_recover_array<Elm: 'static + FixedCodec>(
145        &mut self,
146        var_name: &str,
147    ) -> ProtocolResult<Box<dyn StoreArray<Elm>>>;
148
149    // Alloc or recover a `Uint64` by` var_name`
150    fn alloc_or_recover_uint64(&mut self, var_name: &str) -> ProtocolResult<Box<dyn StoreUint64>>;
151
152    // Alloc or recover a `String` by` var_name`
153    fn alloc_or_recover_string(&mut self, var_name: &str) -> ProtocolResult<Box<dyn StoreString>>;
154
155    // Alloc or recover a `Bool` by` var_name`
156    fn alloc_or_recover_bool(&mut self, var_name: &str) -> ProtocolResult<Box<dyn StoreBool>>;
157
158    // Get a value from the service state by key
159    fn get_value<Key: FixedCodec, Ret: FixedCodec>(&self, key: &Key)
160        -> ProtocolResult<Option<Ret>>;
161
162    // Set a value to the service state by key
163    fn set_value<Key: FixedCodec, Val: FixedCodec>(
164        &mut self,
165        key: Key,
166        val: Val,
167    ) -> ProtocolResult<()>;
168
169    // Get a value from the specified address by key
170    fn get_account_value<Key: FixedCodec, Ret: FixedCodec>(
171        &self,
172        address: &Address,
173        key: &Key,
174    ) -> ProtocolResult<Option<Ret>>;
175
176    // Insert a pair of key / value to the specified address
177    fn set_account_value<Key: FixedCodec, Val: FixedCodec>(
178        &mut self,
179        address: &Address,
180        key: Key,
181        val: Val,
182    ) -> ProtocolResult<()>;
183
184    // Get a signed transaction by `tx_hash`
185    // if not found on the chain, return None
186    fn get_transaction_by_hash(&self, tx_hash: &Hash) -> ProtocolResult<Option<SignedTransaction>>;
187
188    // Get a epoch by `epoch_id`
189    // if not found on the chain, return None
190    // When the parameter `epoch_id` is None, get the latest (executing)` epoch`
191    fn get_epoch_by_epoch_id(&self, epoch_id: Option<u64>) -> ProtocolResult<Option<Epoch>>;
192
193    // Get a receipt by `tx_hash`
194    // if not found on the chain, return None
195    fn get_receipt_by_hash(&self, tx_hash: &Hash) -> ProtocolResult<Option<Receipt>>;
196
197    // Call other read-only methods of `service` and return the results
198    // synchronously NOTE: You can use recursive calls, but the maximum call
199    // stack is 1024
200    fn read(
201        &self,
202        ctx: &ServiceContext,
203        service: &str,
204        method: &str,
205        payload: &str,
206    ) -> ProtocolResult<String>;
207
208    // Call other writable methods of `service` and return the results synchronously
209    // NOTE: You can use recursive calls, but the maximum call stack is 1024
210    fn write(
211        &mut self,
212        ctx: &ServiceContext,
213        service: &str,
214        method: &str,
215        payload: &str,
216    ) -> ProtocolResult<String>;
217}
218
219pub trait StoreMap<Key: FixedCodec + PartialEq, Value: FixedCodec> {
220    fn get(&self, key: &Key) -> ProtocolResult<Value>;
221
222    fn contains(&self, key: &Key) -> ProtocolResult<bool>;
223
224    fn insert(&mut self, key: Key, value: Value) -> ProtocolResult<()>;
225
226    fn remove(&mut self, key: &Key) -> ProtocolResult<()>;
227
228    fn len(&self) -> ProtocolResult<u32>;
229
230    fn is_empty(&self) -> ProtocolResult<bool>;
231
232    fn iter<'a>(&'a self) -> Box<dyn Iterator<Item = (&Key, Value)> + 'a>;
233}
234
235pub trait StoreArray<Elm: FixedCodec> {
236    fn get(&self, index: u32) -> ProtocolResult<Elm>;
237
238    fn push(&mut self, element: Elm) -> ProtocolResult<()>;
239
240    fn remove(&mut self, index: u32) -> ProtocolResult<()>;
241
242    fn len(&self) -> ProtocolResult<u32>;
243
244    fn is_empty(&self) -> ProtocolResult<bool>;
245
246    fn iter<'a>(&'a self) -> Box<dyn Iterator<Item = (u32, Elm)> + 'a>;
247}
248
249pub trait StoreUint64 {
250    fn get(&self) -> ProtocolResult<u64>;
251
252    fn set(&mut self, val: u64) -> ProtocolResult<()>;
253
254    // Add val with self
255    // And set the result back to self
256    fn add(&mut self, val: u64) -> ProtocolResult<()>;
257
258    // Self minus val
259    // And set the result back to self
260    fn sub(&mut self, val: u64) -> ProtocolResult<()>;
261
262    // Multiply val with self
263    // And set the result back to self
264    fn mul(&mut self, val: u64) -> ProtocolResult<()>;
265
266    // Power of self
267    // And set the result back to self
268    fn pow(&mut self, val: u32) -> ProtocolResult<()>;
269
270    // Self divided by val
271    // And set the result back to self
272    fn div(&mut self, val: u64) -> ProtocolResult<()>;
273
274    // Remainder of self
275    // And set the result back to self
276    fn rem(&mut self, val: u64) -> ProtocolResult<()>;
277}
278
279pub trait StoreString {
280    fn get(&self) -> ProtocolResult<String>;
281
282    fn set(&mut self, val: &str) -> ProtocolResult<()>;
283
284    fn len(&self) -> ProtocolResult<u32>;
285
286    fn is_empty(&self) -> ProtocolResult<bool>;
287}
288
289pub trait StoreBool {
290    fn get(&self) -> ProtocolResult<bool>;
291
292    fn set(&mut self, b: bool) -> ProtocolResult<()>;
293}