1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
use codec::{Decode, Encode};
use scale_info::TypeInfo;
use sp_runtime::RuntimeDebug;
use sp_std::collections::btree_map::BTreeMap;

use sp_std::vec::*;

type StateKey = [u8; 32];
// Keep Values as Vector although check if no longer than 64 bytes
type StateVal = Vec<u8>;

pub type State = BTreeMap<StateKey, StateVal>;

use crate::Bytes;
use sp_io::hashing::twox_256;

#[derive(Clone, Eq, PartialEq, Default, Encode, Decode, RuntimeDebug, TypeInfo)]
pub struct LocalState {
    pub state: State,
}

impl LocalState {
    pub fn new() -> Self {
        LocalState {
            state: BTreeMap::new(),
        }
    }
}

impl Volatile for LocalState {
    fn get_state_mut(&mut self) -> &mut State {
        &mut self.state
    }

    fn get_state(&self) -> &State {
        &self.state
    }
}

pub trait Volatile {
    fn get_state_mut(&mut self) -> &mut State;

    fn get_state(&self) -> &State;

    fn hash(x: &[u8]) -> [u8; 32] {
        twox_256(x)
    }

    fn key_2_state_key<K: Encode>(key: K) -> [u8; 32] {
        let key_as_array = &key.encode()[..];
        Self::hash(key_as_array)
    }

    fn stick_key_with_prefix(mut key: Bytes, prefix: Bytes) -> Bytes {
        let mut prefixed_key = prefix;
        prefixed_key.append(&mut key);
        prefixed_key.to_vec()
    }

    fn get<K: Encode>(&self, key: K) -> Option<&StateVal> {
        self.get_state().get(&Self::key_2_state_key(key))
    }

    fn cmp<K: Encode>(&self, key: K, cmp_value: Vec<u8>) -> bool {
        self.get(key) == Some(cmp_value).as_ref()
    }

    fn value_2_state_value(value: Vec<u8>) -> Result<Vec<u8>, &'static str> {
        if value.len() > 64 {
            Err("Value is larger than max. 64 bytes allowed in the Volatile State")
        } else {
            Ok(value)
        }
    }

    fn insert<K: Encode>(
        &mut self,
        key: K,
        val: Vec<u8>,
    ) -> Result<(StateKey, StateVal), &'static str> {
        let key_candidate = Self::key_2_state_key(key);
        if self.get_state().contains_key(&key_candidate) {
            return Err("Key already exists in the Volatile State")
        }
        let value_candidate = Self::value_2_state_value(val)?;

        match self
            .get_state_mut()
            .insert(key_candidate, value_candidate.clone())
        {
            Some(_) => Err("Critical ERR - key override in Volatile storage, despite check!"),
            None => Ok((key_candidate, value_candidate)),
        }
    }
}

pub const FROM_2XX_32B_HASH: [u8; 32] = [
    47u8, 140u8, 44u8, 35u8, 27u8, 124u8, 17u8, 66u8, 71u8, 139u8, 84u8, 182u8, 189u8, 44u8, 255u8,
    9u8, 216u8, 225u8, 72u8, 92u8, 140u8, 153u8, 36u8, 176u8, 243u8, 84u8, 204u8, 37u8, 235u8,
    116u8, 243u8, 46u8,
];
pub const TO_2XX_32B_HASH: [u8; 32] = [
    158u8, 28u8, 58u8, 252u8, 48u8, 192u8, 42u8, 109u8, 5u8, 152u8, 177u8, 124u8, 120u8, 75u8,
    35u8, 127u8, 172u8, 179u8, 9u8, 243u8, 249u8, 54u8, 121u8, 35u8, 254u8, 120u8, 104u8, 24u8,
    148u8, 166u8, 97u8, 122u8,
];
pub const VALUE_2XX_32B_HASH: [u8; 32] = [
    92u8, 190u8, 233u8, 194u8, 88u8, 78u8, 131u8, 17u8, 72u8, 80u8, 231u8, 10u8, 137u8, 245u8,
    128u8, 209u8, 66u8, 12u8, 149u8, 254u8, 145u8, 206u8, 210u8, 112u8, 210u8, 191u8, 191u8, 97u8,
    176u8, 219u8, 170u8, 83u8,
];

#[cfg(test)]
pub mod tests {
    use super::*;
    use hex_literal::hex;

    #[test]
    fn successfully_generates_correct_keys_for_inserted_values() {
        let _encoded_transfer_args_input = vec![
            hex!("0909090909090909090909090909090909090909090909090909090909090909").into(),
            hex!("0606060606060606060606060606060606060606060606060606060606060606").into(),
            1u64.encode(),
        ];
        let mut local_state = LocalState::new();

        let mut res = local_state.insert(
            "from",
            hex!("0909090909090909090909090909090909090909090909090909090909090909").into(),
        );
        assert_eq!(
            res,
            Ok((
                FROM_2XX_32B_HASH,
                hex!("0909090909090909090909090909090909090909090909090909090909090909").into()
            ))
        );

        res = local_state.insert(
            "to",
            hex!("0606060606060606060606060606060606060606060606060606060606060606").into(),
        );
        assert_eq!(
            res,
            Ok((
                TO_2XX_32B_HASH,
                hex!("0606060606060606060606060606060606060606060606060606060606060606").into()
            ))
        );

        res = local_state.insert("value", 1u64.encode());
        assert_eq!(
            res,
            Ok((VALUE_2XX_32B_HASH, hex!("0100000000000000").into()))
        );
    }
}