t3rn_types/
side_effect.rs

1use codec::{Decode, Encode};
2use scale_info::{
3    prelude::{fmt::Debug, vec::Vec},
4    TypeInfo,
5};
6
7pub type TargetId = [u8; 4];
8pub type EventSignature = Vec<u8>;
9pub type SideEffectName = Vec<u8>;
10type Bytes = Vec<u8>;
11
12#[derive(Clone, Eq, PartialEq, Encode, Default, Decode, Debug, TypeInfo)]
13pub struct SideEffect<AccountId, BlockNumber, BalanceOf> {
14    pub target: TargetId,
15    pub prize: BalanceOf,
16    pub ordered_at: BlockNumber,
17    pub encoded_action: Bytes,
18    pub encoded_args: Vec<Bytes>,
19    pub signature: Bytes,
20    pub enforce_executioner: Option<AccountId>,
21}
22
23#[cfg(feature = "runtime")]
24impl<
25        AccountId: Encode,
26        BlockNumber: Ord + Copy + sp_runtime::traits::Zero + Encode,
27        BalanceOf: Copy + sp_runtime::traits::Zero + Encode + Decode,
28    > SideEffect<AccountId, BlockNumber, BalanceOf>
29{
30    pub fn generate_id<Hasher: sp_core::Hasher>(&self) -> <Hasher as sp_core::Hasher>::Out {
31        Hasher::hash(Encode::encode(self).as_ref())
32    }
33
34    pub fn id_as_bytes<Hasher: sp_core::Hasher>(id: <Hasher as sp_core::Hasher>::Out) -> Bytes {
35        id.as_ref().to_vec()
36    }
37}
38
39#[derive(Clone, Eq, PartialEq, Encode, Decode, Debug, TypeInfo)]
40pub enum ConfirmationOutcome {
41    Success,
42    MisbehaviourMalformedValues {
43        key: Bytes,
44        expected: Bytes,
45        received: Bytes,
46    },
47    TimedOut,
48}
49
50impl Default for ConfirmationOutcome {
51    fn default() -> Self {
52        ConfirmationOutcome::Success
53    }
54}
55
56#[derive(Clone, Eq, PartialEq, Encode, Decode, Debug, TypeInfo)]
57pub struct ConfirmedSideEffect<AccountId, BlockNumber, BalanceOf> {
58    pub err: Option<ConfirmationOutcome>,
59    pub output: Option<Bytes>,
60    pub encoded_effect: Bytes,
61    pub inclusion_proof: Option<Bytes>,
62    pub executioner: AccountId,
63    pub received_at: BlockNumber,
64    pub cost: Option<BalanceOf>,
65}
66
67#[derive(Clone, Eq, PartialEq, PartialOrd, Ord, Encode, Decode, Debug, TypeInfo)]
68pub enum SecurityLvl {
69    Dirty,
70    Optimistic,
71    Escrowed,
72}
73
74impl Default for SecurityLvl {
75    fn default() -> Self {
76        SecurityLvl::Dirty
77    }
78}
79
80// Side effects conversion error.
81#[derive(Debug, PartialEq)]
82pub enum Error {
83    /// Failed to decode a property while hardening.
84    HardeningDecodeError,
85    /// Expected confirmation to FSX wasn't there while hardening.
86    HardeningMissingConfirmationError,
87}
88
89#[cfg(test)]
90mod tests {
91    use super::*;
92
93    use sp_core::crypto::AccountId32;
94
95    type BlockNumber = u64;
96    type BalanceOf = u128;
97    type AccountId = AccountId32;
98
99    #[test]
100    fn successfully_creates_empty_side_effect() {
101        let empty_side_effect = SideEffect::<AccountId, BlockNumber, BalanceOf> {
102            target: [0, 0, 0, 0],
103            prize: 0,
104            ordered_at: 0,
105            encoded_action: vec![],
106            encoded_args: vec![],
107            signature: vec![],
108            enforce_executioner: None,
109        };
110
111        assert_eq!(
112            empty_side_effect,
113            SideEffect {
114                target: [0, 0, 0, 0],
115                prize: 0,
116                ordered_at: 0,
117                encoded_action: vec![],
118                encoded_args: vec![],
119                signature: vec![],
120                enforce_executioner: None,
121            }
122        );
123    }
124
125    #[test]
126    fn successfully_encodes_transfer_full_side_effect_with_confirmation() {
127        let from: AccountId32 = AccountId32::new([1u8; 32]);
128        let to: AccountId32 = AccountId32::new([2u8; 32]);
129        let value: BalanceOf = 1u128;
130        let optional_insurance = 2u128;
131        let optional_reward = 3u128;
132
133        let tsfx_input = SideEffect::<AccountId, BlockNumber, BalanceOf> {
134            target: [0, 0, 0, 0],
135            prize: 0,
136            ordered_at: 0,
137            encoded_action: vec![],
138            encoded_args: vec![
139                from.encode(),
140                to.encode(),
141                value.encode(),
142                [optional_insurance.encode(), optional_reward.encode()].concat(),
143            ],
144            signature: vec![],
145            enforce_executioner: None,
146        };
147
148        assert_eq!(
149            tsfx_input,
150            SideEffect {
151                target: [0, 0, 0, 0],
152                prize: 0,
153                ordered_at: 0,
154                encoded_action: vec![],
155                encoded_args: vec![
156                    vec![
157                        1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
158                        1, 1, 1, 1, 1, 1, 1
159                    ],
160                    vec![
161                        2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
162                        2, 2, 2, 2, 2, 2, 2
163                    ],
164                    vec![1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
165                    vec![
166                        2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0,
167                        0, 0, 0, 0, 0, 0, 0
168                    ]
169                ],
170                signature: vec![],
171                enforce_executioner: None,
172            }
173        );
174    }
175
176    #[test]
177    fn successfully_defaults_side_effect_to_an_empty_one() {
178        let empty_side_effect = SideEffect::<u64, BlockNumber, BalanceOf> {
179            target: [0, 0, 0, 0],
180            prize: 0,
181            ordered_at: 0,
182            encoded_action: vec![],
183            encoded_args: vec![],
184            signature: vec![],
185            enforce_executioner: None,
186        };
187
188        assert_eq!(empty_side_effect, SideEffect::default(),);
189    }
190}