rgbcore/schema/
operations.rs

1// RGB Consensus Library: consensus layer for RGB smart contracts.
2//
3// SPDX-License-Identifier: Apache-2.0
4//
5// Written in 2019-2024 by
6//     Dr Maxim Orlovsky <orlovsky@lnp-bp.org>
7//
8// Copyright (C) 2019-2024 LNP/BP Standards Association. All rights reserved.
9// Copyright (C) 2019-2024 Dr Maxim Orlovsky. All rights reserved.
10//
11// Licensed under the Apache License, Version 2.0 (the "License");
12// you may not use this file except in compliance with the License.
13// You may obtain a copy of the License at
14//
15//     http://www.apache.org/licenses/LICENSE-2.0
16//
17// Unless required by applicable law or agreed to in writing, software
18// distributed under the License is distributed on an "AS IS" BASIS,
19// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20// See the License for the specific language governing permissions and
21// limitations under the License.
22
23use aluvm::library::LibSite;
24use amplify::confinement::{TinyOrdMap, TinyOrdSet};
25use amplify::Wrapper;
26
27use super::{GlobalStateType, Occurrences, TransitionType};
28use crate::schema::schema::MetaType;
29use crate::LIB_NAME_RGB_COMMIT;
30
31#[derive(Wrapper, Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug, From, Display)]
32#[wrapper(FromStr, LowerHex, UpperHex)]
33#[display(inner)]
34#[derive(StrictType, StrictDumb, StrictEncode, StrictDecode)]
35#[strict_type(lib = LIB_NAME_RGB_COMMIT)]
36#[cfg_attr(
37    feature = "serde",
38    derive(Serialize, Deserialize),
39    serde(crate = "serde_crate", rename_all = "camelCase")
40)]
41pub struct AssignmentType(u16);
42impl AssignmentType {
43    pub const fn with(ty: u16) -> Self { Self(ty) }
44    #[inline]
45    pub fn to_le_bytes(&self) -> [u8; 2] { self.0.to_le_bytes() }
46
47    pub const ASSET: Self = AssignmentType(4000);
48    pub fn is_asset(self) -> bool { self == Self::ASSET }
49}
50
51pub type MetaSchema = TinyOrdSet<MetaType>;
52pub type GlobalSchema = TinyOrdMap<GlobalStateType, Occurrences>;
53pub type InputsSchema = TinyOrdMap<AssignmentType, Occurrences>;
54pub type AssignmentsSchema = TinyOrdMap<AssignmentType, Occurrences>;
55
56/// Aggregated type used to supply full contract operation type and transition type information
57#[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug, Display)]
58#[cfg_attr(
59    feature = "serde",
60    derive(Serialize, Deserialize),
61    serde(crate = "serde_crate", rename_all = "camelCase")
62)]
63pub enum OpFullType {
64    /// Genesis operation (no subtypes)
65    ///
66    /// Genesis: single operation per contract, defining contract and
67    /// committing to a specific schema and underlying chain hash
68    #[display("genesis")]
69    Genesis,
70
71    /// State transition contract operation, subtyped by transition type
72    ///
73    /// State transition performing owned change to the state data and committing to (potentially
74    /// multiple) ancestors (i.e. genesis and/or  other state transitions) via spending
75    /// corresponding transaction outputs assigned some state by ancestors
76    #[display("transition #{0}")]
77    StateTransition(TransitionType),
78}
79
80impl OpFullType {
81    pub fn subtype(self) -> u16 {
82        match self {
83            OpFullType::Genesis => 0,
84            OpFullType::StateTransition(ty) => ty.to_inner(),
85        }
86    }
87
88    pub fn is_transition(self) -> bool { matches!(self, Self::StateTransition(_)) }
89}
90
91/// Trait defining common API for all operation type schemata
92pub trait OpSchema {
93    fn metadata(&self) -> &MetaSchema;
94    fn globals(&self) -> &GlobalSchema;
95    fn inputs(&self) -> Option<&InputsSchema>;
96    fn assignments(&self) -> &AssignmentsSchema;
97}
98
99#[derive(Clone, PartialEq, Eq, Debug, Default)]
100#[derive(StrictType, StrictEncode, StrictDecode)]
101#[strict_type(lib = LIB_NAME_RGB_COMMIT)]
102#[cfg_attr(
103    feature = "serde",
104    derive(Serialize, Deserialize),
105    serde(crate = "serde_crate", rename_all = "camelCase")
106)]
107pub struct GenesisSchema {
108    pub metadata: MetaSchema,
109    pub globals: GlobalSchema,
110    pub assignments: AssignmentsSchema,
111    // NB: it is possible to transform option into enum covering other virtual machines
112    pub validator: Option<LibSite>,
113}
114
115#[derive(Clone, PartialEq, Eq, Debug, Default)]
116#[derive(StrictType, StrictEncode, StrictDecode)]
117#[strict_type(lib = LIB_NAME_RGB_COMMIT)]
118#[cfg_attr(
119    feature = "serde",
120    derive(Serialize, Deserialize),
121    serde(crate = "serde_crate", rename_all = "camelCase")
122)]
123pub struct TransitionSchema {
124    pub metadata: MetaSchema,
125    pub globals: GlobalSchema,
126    pub inputs: InputsSchema,
127    pub assignments: AssignmentsSchema,
128    pub validator: Option<LibSite>,
129}
130
131impl OpSchema for GenesisSchema {
132    #[inline]
133    fn metadata(&self) -> &MetaSchema { &self.metadata }
134    #[inline]
135    fn globals(&self) -> &GlobalSchema { &self.globals }
136    #[inline]
137    fn inputs(&self) -> Option<&InputsSchema> { None }
138    #[inline]
139    fn assignments(&self) -> &AssignmentsSchema { &self.assignments }
140}
141
142impl OpSchema for TransitionSchema {
143    #[inline]
144    fn metadata(&self) -> &MetaSchema { &self.metadata }
145    #[inline]
146    fn globals(&self) -> &GlobalSchema { &self.globals }
147    #[inline]
148    fn inputs(&self) -> Option<&AssignmentsSchema> { Some(&self.inputs) }
149    #[inline]
150    fn assignments(&self) -> &AssignmentsSchema { &self.assignments }
151}