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 frame_support::pallet_prelude::*;
18
use parity_scale_codec::DecodeAll;
19
use snowbridge_core::{Channel, PRIMARY_GOVERNANCE_CHANNEL};
20
use snowbridge_router_primitives::inbound::envelope::Envelope;
21
use snowbridge_router_primitives::inbound::MessageProcessor;
22
use sp_runtime::DispatchError;
23
use sp_std::vec::Vec;
24

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

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

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

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

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

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

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

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