oasis_runtime_sdk_contracts/
types.rs

1//! Contracts module types.
2pub use oasis_contract_sdk_types::{CodeId, InstanceId};
3use oasis_runtime_sdk::{
4    core::common::crypto::hash::Hash,
5    types::{address::Address, token},
6};
7
8use super::{Error, MODULE_NAME};
9
10/// A generic policy that specifies who is allowed to perform an action.
11#[derive(Clone, Copy, Debug, cbor::Encode, cbor::Decode)]
12pub enum Policy {
13    #[cbor(rename = "nobody", as_struct)]
14    Nobody,
15
16    #[cbor(rename = "address")]
17    Address(Address),
18
19    #[cbor(rename = "everyone", as_struct)]
20    Everyone,
21}
22
23impl Policy {
24    /// Enforce the given policy by returning an error if the policy is not satisfied.
25    pub fn enforce(&self, caller: &Address) -> Result<(), Error> {
26        match self {
27            // Nobody is allowed to perform the action.
28            Policy::Nobody => Err(Error::Forbidden),
29            // Only the given caller is allowed to perform the action.
30            Policy::Address(address) if address == caller => Ok(()),
31            Policy::Address(_) => Err(Error::Forbidden),
32            // Anyone is allowed to perform the action.
33            Policy::Everyone => Ok(()),
34        }
35    }
36}
37
38/// ABI that the given contract should conform to.
39#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, cbor::Encode, cbor::Decode)]
40#[repr(u8)]
41pub enum ABI {
42    /// Custom Oasis SDK-specific ABI (v1).
43    OasisV1 = 1,
44}
45
46/// Stored code information.
47#[derive(Clone, Debug, cbor::Encode, cbor::Decode)]
48#[cbor(no_default)]
49pub struct Code {
50    /// Unique code identifier.
51    pub id: CodeId,
52
53    /// Code hash.
54    pub hash: Hash,
55
56    /// ABI.
57    pub abi: ABI,
58
59    /// ABI sub-version.
60    #[cbor(optional)]
61    pub abi_sv: u32,
62
63    /// Code uploader address.
64    pub uploader: Address,
65
66    /// Who is allowed to instantiate this code.
67    pub instantiate_policy: Policy,
68}
69
70/// Deployed code instance information.
71#[derive(Clone, Debug, cbor::Encode, cbor::Decode)]
72#[cbor(no_default)]
73pub struct Instance {
74    /// Unique instance identifier.
75    pub id: InstanceId,
76
77    /// Identifier of code used by the instance.
78    pub code_id: CodeId,
79
80    /// Instance creator address.
81    pub creator: Address,
82
83    /// Who is allowed to upgrade this instance.
84    pub upgrades_policy: Policy,
85}
86
87impl Instance {
88    /// Address associated with a specific contract instance.
89    pub fn address_for(id: InstanceId) -> Address {
90        Address::from_module_raw(MODULE_NAME, &id.as_u64().to_be_bytes())
91    }
92
93    /// Address associated with the contract.
94    pub fn address(&self) -> Address {
95        Self::address_for(self.id)
96    }
97}
98
99/// Upload call.
100#[derive(Clone, Debug, cbor::Encode, cbor::Decode)]
101#[cbor(no_default)]
102pub struct Upload {
103    /// ABI.
104    pub abi: ABI,
105
106    /// Who is allowed to instantiate this code.
107    pub instantiate_policy: Policy,
108
109    /// Compiled contract code.
110    pub code: Vec<u8>,
111}
112
113/// Upload call result.
114#[derive(Clone, Debug, Default, cbor::Encode, cbor::Decode)]
115pub struct UploadResult {
116    /// Assigned code identifier.
117    pub id: CodeId,
118}
119
120/// Instantiate call.
121#[derive(Clone, Debug, cbor::Encode, cbor::Decode)]
122#[cbor(no_default)]
123pub struct Instantiate {
124    /// Identifier of code used by the instance.
125    pub code_id: CodeId,
126
127    /// Who is allowed to upgrade this instance.
128    pub upgrades_policy: Policy,
129
130    /// Arguments to contract's instantiation function.
131    pub data: Vec<u8>,
132
133    /// Tokens that should be sent to the contract as part of the instantiate call.
134    pub tokens: Vec<token::BaseUnits>,
135}
136
137/// Instantiate call result.
138#[derive(Clone, Debug, Default, cbor::Encode, cbor::Decode)]
139pub struct InstantiateResult {
140    /// Assigned instance identifier.
141    pub id: InstanceId,
142}
143
144/// Contract call.
145#[derive(Clone, Debug, cbor::Encode, cbor::Decode)]
146#[cbor(no_default)]
147pub struct Call {
148    /// Instance identifier.
149    pub id: InstanceId,
150
151    /// Call arguments.
152    pub data: Vec<u8>,
153
154    /// Tokens that should be sent to the contract as part of the call.
155    pub tokens: Vec<token::BaseUnits>,
156}
157
158/// Contract call result.
159#[derive(Clone, Debug, Default, cbor::Encode, cbor::Decode)]
160#[cbor(transparent)]
161pub struct CallResult(pub Vec<u8>);
162
163/// Upgrade call.
164#[derive(Clone, Debug, cbor::Encode, cbor::Decode)]
165#[cbor(no_default)]
166pub struct Upgrade {
167    /// Instance identifier.
168    pub id: InstanceId,
169
170    /// Updated code identifier.
171    pub code_id: CodeId,
172
173    /// Arguments to contract's upgrade function.
174    pub data: Vec<u8>,
175
176    /// Tokens that should be sent to the contract as part of the call.
177    pub tokens: Vec<token::BaseUnits>,
178}
179
180/// Change upgrade policy call.
181#[derive(Clone, Debug, cbor::Encode, cbor::Decode)]
182#[cbor(no_default)]
183pub struct ChangeUpgradePolicy {
184    /// Instance identifier.
185    pub id: InstanceId,
186
187    /// Updated upgrade policy.
188    pub upgrades_policy: Policy,
189}
190
191/// Code information query.
192#[derive(Clone, Debug, cbor::Encode, cbor::Decode)]
193#[cbor(no_default)]
194pub struct CodeQuery {
195    /// Code identifier.
196    pub id: CodeId,
197}
198
199/// Code storage information query.
200#[derive(Clone, Debug, Default, cbor::Encode, cbor::Decode)]
201pub struct CodeStorageQuery {
202    /// Code identifier.
203    pub id: CodeId,
204}
205
206/// Code storage query result.
207#[derive(Clone, Debug, Default, cbor::Encode, cbor::Decode)]
208pub struct CodeStorageQueryResult {
209    /// Stored contract code.
210    pub code: Vec<u8>,
211}
212
213/// Instance information query.
214#[derive(Clone, Debug, Default, cbor::Encode, cbor::Decode)]
215pub struct InstanceQuery {
216    /// Instance identifier.
217    pub id: InstanceId,
218}
219
220/// Instance storage query.
221#[derive(Clone, Debug, Default, cbor::Encode, cbor::Decode)]
222pub struct InstanceStorageQuery {
223    /// Instance identifier.
224    pub id: InstanceId,
225
226    /// Storage key.
227    pub key: Vec<u8>,
228}
229
230#[derive(Clone, Debug, Default, cbor::Encode, cbor::Decode)]
231pub struct InstanceStorageQueryResult {
232    /// Storage value or `None` if key doesn't exist.
233    pub value: Option<Vec<u8>>,
234}
235
236/// Exposed wrapper for oasis-contract-sdk-types::StoreKind.
237#[derive(Clone, Debug, cbor::Encode, cbor::Decode)]
238#[repr(u32)]
239pub enum StoreKind {
240    Public = 0,
241    Confidential = 1,
242}
243
244/// Instance raw storage query.
245#[derive(Clone, Debug, cbor::Encode, cbor::Decode)]
246#[cbor(no_default)]
247pub struct InstanceRawStorageQuery {
248    /// Instance identifier.
249    pub id: InstanceId,
250
251    /// Kind of the store to query.
252    pub store_kind: StoreKind,
253
254    /// Maximum number of items per page.
255    #[cbor(optional)]
256    pub limit: Option<u64>,
257
258    /// Number of skipped items.
259    #[cbor(optional)]
260    pub offset: Option<u64>,
261}
262
263/// Instance raw storage query result.
264#[derive(Clone, Debug, Default, cbor::Encode, cbor::Decode)]
265pub struct InstanceRawStorageQueryResult {
266    /// List of key-value pairs in contract's public store.
267    pub items: Vec<(Vec<u8>, Vec<u8>)>,
268}
269
270/// Public key kind.
271#[derive(Clone, Debug, cbor::Encode, cbor::Decode)]
272#[repr(u8)]
273pub enum PublicKeyKind {
274    Transaction = 1,
275}
276
277/// Public key query.
278#[derive(Clone, Debug, cbor::Encode, cbor::Decode)]
279#[cbor(no_default)]
280pub struct PublicKeyQuery {
281    /// Instance identifier.
282    pub id: InstanceId,
283
284    /// Kind of public key.
285    pub kind: PublicKeyKind,
286}
287
288/// Public key query result.
289#[derive(Clone, Debug, Default, cbor::Encode, cbor::Decode)]
290pub struct PublicKeyQueryResult {
291    /// Public key.
292    pub key: Vec<u8>,
293
294    /// Checksum of the key manager state.
295    pub checksum: Vec<u8>,
296
297    /// Sign(sk, (key || checksum)) from the key manager.
298    pub signature: Vec<u8>,
299}
300
301/// Custom contract query.
302#[derive(Clone, Debug, Default, cbor::Encode, cbor::Decode)]
303pub struct CustomQuery {
304    /// Instance identifier.
305    pub id: InstanceId,
306
307    /// Query arguments.
308    pub data: Vec<u8>,
309}
310
311/// Custom query result.
312#[derive(Clone, Debug, Default, cbor::Encode, cbor::Decode)]
313#[cbor(transparent)]
314pub struct CustomQueryResult(pub Vec<u8>);
315
316/// An event emitted from a contract, wrapped to include additional metadata.
317#[derive(Clone, Debug, Default, cbor::Encode, cbor::Decode)]
318pub struct ContractEvent {
319    /// Identifier of the instance that emitted the event.
320    pub id: InstanceId,
321    /// Raw event data emitted by the instance.
322    #[cbor(optional)]
323    pub data: Vec<u8>,
324}
325
326#[cfg(test)]
327mod test {
328    use super::*;
329
330    #[test]
331    fn test_instanceid_to_address() {
332        let tcs = vec![
333            (
334                InstanceId::from(0),
335                "oasis1qq08mjlkztsgpgrar082rzzxwjaplxmgjs5ftugn",
336            ),
337            (
338                InstanceId::from(1),
339                "oasis1qpg6jv8mxwlv4z578xyjxl7d793jamltdg9czzkx",
340            ),
341            (
342                InstanceId::from(14324),
343                "oasis1qzasj0kq0hlq6vzw4ajhrwgp3tqx6rnwvg2ylu2v",
344            ),
345            (
346                InstanceId::from(u64::MAX),
347                "oasis1qqr0nxsu5aqpu4k85z4h5z08vrfmawnnqycl6gup",
348            ),
349        ];
350
351        for (id, address) in tcs {
352            let instance_address = Instance::address_for(id);
353            assert_eq!(
354                instance_address.to_bech32(),
355                address.to_string(),
356                "instance address should match"
357            );
358        }
359    }
360}