tezos_smart_rollup_installer_config/binary/
instr.rs

1// SPDX-FileCopyrightText: 2023 TriliTech <contact@trili.tech>
2// SPDX-FileCopyrightText: 2023 Nomadic Labs <contact@nomadic-labs.com>
3// SPDX-FileCopyrightText: 2023 Functori <contact@functori.com>
4//
5// SPDX-License-Identifier: MIT
6
7use tezos_smart_rollup_core::PREIMAGE_HASH_SIZE;
8use tezos_smart_rollup_host::path::RefPath;
9
10#[derive(Debug, PartialEq, Eq)]
11pub struct RefBytes<'a>(pub &'a [u8]);
12
13impl<'a> AsRef<[u8]> for RefBytes<'a> {
14    fn as_ref(&self) -> &[u8] {
15        self.0
16    }
17}
18
19#[allow(clippy::from_over_into)]
20impl<'a> Into<[u8; PREIMAGE_HASH_SIZE]> for RefBytes<'a> {
21    fn into(self) -> [u8; PREIMAGE_HASH_SIZE] {
22        self.0.try_into().unwrap()
23    }
24}
25
26#[derive(Debug, PartialEq, Eq)]
27pub struct MoveInstruction<Path> {
28    pub from: Path,
29    pub to: Path,
30}
31
32// Value dependent instructions start here
33
34#[derive(Debug, PartialEq, Eq)]
35pub struct RevealInstruction<Path, Bytes> {
36    pub hash: Bytes,
37    pub to: Path,
38}
39
40#[derive(Debug, PartialEq, Eq)]
41pub struct SetInstruction<Path, Bytes> {
42    pub value: Bytes,
43    pub to: Path,
44}
45
46#[derive(Debug, PartialEq, Eq)]
47pub enum ConfigInstruction<Path, Bytes> {
48    Reveal(RevealInstruction<Path, Bytes>),
49    Move(MoveInstruction<Path>),
50    Set(SetInstruction<Path, Bytes>),
51}
52
53pub type RefConfigInstruction<'a> = ConfigInstruction<RefPath<'a>, RefBytes<'a>>;
54
55#[cfg(feature = "alloc")]
56pub mod owned {
57    use crate::binary::evaluation::eval_config_instr;
58    use tezos_smart_rollup_encoding::dac::PreimageHash;
59    use tezos_smart_rollup_host::{
60        path::{OwnedPath, PathError},
61        runtime::Runtime,
62    };
63    use thiserror::Error;
64
65    use super::*;
66
67    #[derive(Debug, PartialEq, Eq)]
68    pub struct OwnedBytes(pub Vec<u8>);
69
70    impl AsRef<[u8]> for OwnedBytes {
71        fn as_ref(&self) -> &[u8] {
72            &self.0
73        }
74    }
75
76    pub type OwnedConfigInstruction = ConfigInstruction<OwnedPath, OwnedBytes>;
77
78    #[derive(Debug, PartialEq, Eq)]
79    pub struct OwnedConfigProgram(pub Vec<OwnedConfigInstruction>);
80
81    impl OwnedConfigProgram {
82        pub fn evaluate(&self, host: &mut impl Runtime) -> Result<(), &'static str> {
83            for instruction in self.0.iter() {
84                eval_config_instr(host, instruction)?
85            }
86            Ok(())
87        }
88    }
89
90    #[derive(Debug, Error, PartialEq)]
91    pub enum RevealInstrError {
92        #[error("Invalid preimage hash size: {0}")]
93        InvalidRevealHashSize(usize),
94        #[error("Invalid reveal path: {0}")]
95        PathError(PathError),
96    }
97
98    impl OwnedConfigInstruction {
99        pub fn reveal_instr(hash: PreimageHash, to: OwnedPath) -> Self {
100            OwnedConfigInstruction::Reveal(RevealInstruction {
101                hash: OwnedBytes(hash.into()),
102                to,
103            })
104        }
105
106        pub fn move_instr(from: OwnedPath, to: OwnedPath) -> Self {
107            OwnedConfigInstruction::Move(MoveInstruction { from, to })
108        }
109
110        pub fn set_instr(value: OwnedBytes, to: OwnedPath) -> Self {
111            OwnedConfigInstruction::Set(SetInstruction { value, to })
112        }
113    }
114}
115
116pub mod evaluation {
117    use crate::binary::instr::{MoveInstruction, RevealInstruction, SetInstruction};
118    use crate::binary::reveal_root_hash_to_store;
119    use tezos_smart_rollup_host::path::Path as HostPath;
120    use tezos_smart_rollup_host::runtime::Runtime;
121
122    use super::ConfigInstruction;
123
124    /// Configuration instruction evaluation
125    ///
126    /// This functions takes a config instruction and evaluates it with the according
127    /// intended behaviour.
128    ///
129    /// Here's an example of how you can use this function:
130    /// ```
131    /// use tezos_smart_rollup_installer_config::binary::evaluation::eval_config_instr;
132    /// use tezos_smart_rollup_host::KERNEL_BOOT_PATH;
133    /// use tezos_smart_rollup_host::path::OwnedPath;
134    /// use tezos_smart_rollup_host::path::RefPath;
135    /// use tezos_smart_rollup_installer_config::binary::owned::OwnedConfigInstruction;
136    /// use tezos_smart_rollup_installer_config::binary::owned::OwnedConfigProgram;
137    /// use tezos_smart_rollup_installer_config::binary::promote::upgrade_reveal_flow;
138    /// use tezos_smart_rollup_core::PREIMAGE_HASH_SIZE;
139    /// use tezos_smart_rollup_host::runtime::Runtime;
140    ///
141    ///
142    /// pub fn upgrade_kernel(host: &mut impl Runtime) -> Result<(), &'static str> {
143    ///     let root_hash = [0; PREIMAGE_HASH_SIZE];
144    ///
145    ///     // Create config consisting of a reveal instruction followed by a move.
146    ///     let config = upgrade_reveal_flow(root_hash);
147    ///
148    ///     config.evaluate(host)
149    /// }
150    /// ```
151    pub fn eval_config_instr<Path: HostPath, Bytes: AsRef<[u8]>>(
152        host: &mut impl Runtime,
153        config_instr: &ConfigInstruction<Path, Bytes>,
154    ) -> Result<(), &'static str> {
155        match config_instr {
156            ConfigInstruction::Reveal(RevealInstruction { hash, to }) => {
157                let hash = &hash
158                    .as_ref()
159                    .try_into()
160                    .map_err(|_| "Invalid hash conversion.")?;
161                reveal_root_hash_to_store(host, hash, to)
162            }
163            ConfigInstruction::Move(MoveInstruction { from, to }) => {
164                Runtime::store_move(host, from, to)
165                    .map_err(|_| "Couldn't move path during config application")
166            }
167            ConfigInstruction::Set(SetInstruction { value, to }) => {
168                Runtime::store_write(host, to, value.as_ref(), 0)
169                    .map_err(|_| "Couldn't set key during config application")
170            }
171        }
172    }
173}
174
175#[cfg(feature = "alloc")]
176pub mod promote {
177    use super::owned::{OwnedConfigInstruction, OwnedConfigProgram};
178    use tezos_smart_rollup_core::PREIMAGE_HASH_SIZE;
179    use tezos_smart_rollup_host::{
180        path::{OwnedPath, RefPath},
181        KERNEL_BOOT_PATH,
182    };
183
184    const TMP_REVEAL_PATH: RefPath = RefPath::assert_from(b"/__sdk/installer/reveal");
185
186    pub fn upgrade_reveal_flow(
187        root_hash: [u8; PREIMAGE_HASH_SIZE],
188    ) -> OwnedConfigProgram {
189        OwnedConfigProgram(vec![
190            OwnedConfigInstruction::reveal_instr(
191                root_hash.to_vec().into(),
192                OwnedPath::from(&TMP_REVEAL_PATH),
193            ),
194            OwnedConfigInstruction::move_instr(
195                (&TMP_REVEAL_PATH).into(),
196                (&KERNEL_BOOT_PATH).into(),
197            ),
198        ])
199    }
200}