tezos_smart_rollup_installer_config/yaml/
convert.rs

1// SPDX-FileCopyrightText: 2023 TriliTech <contact@trili.tech>
2// SPDX-FileCopyrightText: 2023 Nomadic Labs <contact@nomadic-labs.com>
3//
4// SPDX-License-Identifier: MIT
5
6use crate::binary::owned::{OwnedBytes, OwnedConfigInstruction, OwnedConfigProgram};
7use crate::yaml::YamlConfig;
8use hex::FromHexError;
9use tezos_smart_rollup_core::PREIMAGE_HASH_SIZE;
10use tezos_smart_rollup_encoding::dac::PreimageHash;
11use tezos_smart_rollup_host::path::{OwnedPath, PathError};
12use thiserror::Error;
13
14use crate::yaml::Instr;
15
16#[derive(Debug, Error, PartialEq)]
17pub enum ConfigConversionError {
18    #[error("Unable to convert hex to bytes: {0}.")]
19    Hex(FromHexError),
20    #[error("Invalid preimage hash size: {0}")]
21    InvalidRevealHashSize(usize),
22    #[error("Invalid reveal path: {0}")]
23    PathError(PathError),
24}
25
26pub fn reveal_instr_hex(
27    hash_hex: String,
28    to: String,
29) -> Result<OwnedConfigInstruction, ConfigConversionError> {
30    let to = OwnedPath::try_from(to).map_err(ConfigConversionError::PathError)?;
31    let hash = hex::decode(hash_hex.as_str()).map_err(ConfigConversionError::Hex)?;
32
33    let hash_len = hash.len();
34    let hash: [u8; PREIMAGE_HASH_SIZE] = hash
35        .try_into()
36        .map_err(|_| ConfigConversionError::InvalidRevealHashSize(hash_len))?;
37
38    Ok(OwnedConfigInstruction::reveal_instr(
39        PreimageHash::from(&hash),
40        to,
41    ))
42}
43
44pub fn move_instr_str(
45    from: String,
46    to: String,
47) -> Result<OwnedConfigInstruction, ConfigConversionError> {
48    let from = OwnedPath::try_from(from).map_err(ConfigConversionError::PathError)?;
49    let to = OwnedPath::try_from(to).map_err(ConfigConversionError::PathError)?;
50    Ok(OwnedConfigInstruction::move_instr(from, to))
51}
52
53pub fn set_instr_hex(
54    value: String,
55    to: String,
56) -> Result<OwnedConfigInstruction, ConfigConversionError> {
57    let to = OwnedPath::try_from(to).map_err(ConfigConversionError::PathError)?;
58    let value = hex::decode(value.as_str()).map_err(ConfigConversionError::Hex)?;
59    Ok(OwnedConfigInstruction::set_instr(OwnedBytes(value), to))
60}
61
62impl TryFrom<YamlConfig> for OwnedConfigProgram {
63    type Error = ConfigConversionError;
64
65    fn try_from(config: YamlConfig) -> Result<Self, Self::Error> {
66        config
67            .instructions
68            .into_iter()
69            .map(|instr| match instr {
70                Instr::Move(args) => move_instr_str(args.from, args.to),
71                Instr::Reveal(args) => reveal_instr_hex(args.reveal, args.to),
72                Instr::Set(args) => set_instr_hex(args.value, args.to),
73            })
74            .collect::<Result<Vec<OwnedConfigInstruction>, Self::Error>>()
75            .map(OwnedConfigProgram)
76    }
77}
78
79#[cfg(test)]
80mod test {
81    use crate::{
82        binary::owned::OwnedConfigProgram,
83        yaml::{
84            move_instr_str, reveal_instr_hex, set_instr_hex, ConfigConversionError,
85            YamlConfig,
86        },
87    };
88    use std::fs::read_to_string;
89
90    #[test]
91    fn convert_valid_config() {
92        let source_yaml = read_to_string("tests/resources/config_example1.yaml").unwrap();
93        let instrs = serde_yaml::from_str::<YamlConfig>(&source_yaml).unwrap();
94
95        assert_eq!(
96            instrs.try_into(),
97            Ok(OwnedConfigProgram(vec![
98                move_instr_str("/hello/path".to_owned(), "/to/path".to_owned()).unwrap(),
99                reveal_instr_hex(
100                    "a1b2c3a1b2c3a1b2c3a1b2c3a1b2c3a1b2c3a1b2c3a1b2c3a1b2c3a1b2c3a1b2c3"
101                        .to_owned(),
102                    "/path".to_owned()
103                )
104                .unwrap(),
105                set_instr_hex(
106                    "556e20666573746976616c2064652047414454".to_owned(),
107                    "/path/machin".to_owned()
108                )
109                .unwrap()
110            ]))
111        );
112    }
113
114    #[test]
115    fn convert_invalid_reveal_hash_size() {
116        let source_yaml =
117            read_to_string("tests/resources/config_example2_invalid_hash.yaml").unwrap();
118        let instrs = serde_yaml::from_str::<YamlConfig>(&source_yaml).unwrap();
119
120        assert_eq!(
121            instrs.try_into(),
122            Err::<OwnedConfigProgram, ConfigConversionError>(
123                ConfigConversionError::InvalidRevealHashSize(7)
124            )
125        );
126    }
127}