1
// Copyright (C) Moondance Labs Ltd.
2
// This file is part of Tanssi.
3

            
4
// Tanssi is free software: you can redistribute it and/or modify
5
// it under the terms of the GNU General Public License as published by
6
// the Free Software Foundation, either version 3 of the License, or
7
// (at your option) any later version.
8

            
9
// Tanssi is distributed in the hope that it will be useful,
10
// but WITHOUT ANY WARRANTY; without even the implied warranty of
11
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
// GNU General Public License for more details.
13

            
14
// You should have received a copy of the GNU General Public License
15
// along with Tanssi.  If not, see <http://www.gnu.org/licenses/>
16

            
17
use {
18
    frame_support::pallet_prelude::*,
19
    parity_scale_codec::DecodeAll,
20
    snowbridge_core::{Channel, PRIMARY_GOVERNANCE_CHANNEL},
21
    snowbridge_router_primitives::inbound::{envelope::Envelope, MessageProcessor},
22
    sp_runtime::DispatchError,
23
    sp_std::vec::Vec,
24
};
25

            
26
/// Magic bytes are added in every payload intended for this processor to make sure
27
/// that we are the intended recipient of the message. Reason being scale encoding is not type aware.
28
/// So a same set of bytes can be decoded for two different data structures if their
29
/// total size is same. Magic bytes can be checked after decoding to make sure that the sender
30
/// indeed send a message intended for this processor.
31
pub const MAGIC_BYTES: [u8; 4] = [112, 21, 0, 56];
32

            
33
/// Payload is the whole data we expect to receive from the relayer
34
#[derive(Encode, Decode)]
35
pub struct Payload<T>
36
where
37
    T: pallet_external_validators::Config,
38
{
39
    pub magic_bytes: [u8; 4],
40
    pub message: Message<T>,
41
}
42

            
43
/// Actual message inside the payload
44
#[derive(Encode, Decode)]
45
pub enum Message<T>
46
where
47
    T: pallet_external_validators::Config,
48
{
49
24
    V1(InboundCommand<T>),
50
}
51

            
52
/// Command to be executed by this message processor
53
#[derive(Encode, Decode)]
54
pub enum InboundCommand<T>
55
where
56
    T: pallet_external_validators::Config,
57
{
58
24
    ReceiveValidators {
59
        validators: Vec<<T as pallet_external_validators::Config>::ValidatorId>,
60
        external_index: u64,
61
    },
62
}
63

            
64
pub struct SymbioticMessageProcessor<T>(PhantomData<T>);
65

            
66
impl<T> MessageProcessor for SymbioticMessageProcessor<T>
67
where
68
    T: pallet_external_validators::Config,
69
{
70
18
    fn can_process_message(_channel: &Channel, envelope: &Envelope) -> bool {
71
18
        let decode_result = Payload::<T>::decode_all(&mut envelope.payload.as_slice());
72
18
        if let Ok(payload) = decode_result {
73
12
            payload.magic_bytes == MAGIC_BYTES
74
        } else {
75
6
            false
76
        }
77
18
    }
78

            
79
12
    fn process_message(_channel: Channel, envelope: Envelope) -> Result<(), DispatchError> {
80
12
        let decode_result = Payload::<T>::decode_all(&mut envelope.payload.as_slice());
81
12
        let message = if let Ok(payload) = decode_result {
82
10
            payload.message
83
        } else {
84
2
            return Err(DispatchError::Other("unable to parse the envelope payload"));
85
        };
86

            
87
10
        match message {
88
10
            Message::V1(InboundCommand::ReceiveValidators {
89
10
                validators,
90
10
                external_index,
91
10
            }) => {
92
10
                if envelope.channel_id != PRIMARY_GOVERNANCE_CHANNEL {
93
2
                    return Err(DispatchError::Other(
94
2
                        "Received governance message from invalid channel id",
95
2
                    ));
96
8
                }
97
8
                pallet_external_validators::Pallet::<T>::set_external_validators_inner(
98
8
                    validators,
99
8
                    external_index,
100
8
                )?;
101
8
                Ok(())
102
            }
103
        }
104
12
    }
105
}