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::ensure;
18
use {crate::*, core::marker::PhantomData, snowbridge_outbound_queue_primitives::SendError};
19

            
20
/// Custom Impl
21
pub struct TanssiEthMessageValidatorV1<T: snowbridge_pallet_outbound_queue::Config>(PhantomData<T>);
22
impl<T: snowbridge_pallet_outbound_queue::Config> ValidateMessage
23
    for TanssiEthMessageValidatorV1<T>
24
{
25
    type Ticket = TanssiTicketV1<T>;
26

            
27
94
    fn validate(message: &TanssiMessage) -> Result<(Self::Ticket, Fee<u64>), SendError> {
28
94
        log::trace!("TanssiEthMessageValidatorV1: {:?}", message);
29
        // The inner payload should not be too large
30
94
        let payload = message.command.abi_encode();
31
94
        ensure!(
32
94
            payload.len() < T::MaxMessagePayloadSize::get() as usize,
33
1
            SendError::MessageTooLarge
34
        );
35

            
36
        // Ensure there is a registered channel we can transmit this message on
37
93
        ensure!(
38
93
            T::Channels::contains(&message.channel_id),
39
1
            SendError::InvalidChannel
40
        );
41

            
42
        // Generate a unique message id unless one is provided
43
92
        let message_id: H256 = message
44
92
            .id
45
92
            .unwrap_or_else(|| unique((message.channel_id, &message.command)).into());
46

            
47
        // Fee not used
48
        /*
49
        let gas_used_at_most = T::GasMeter::maximum_gas_used_at_most(&message.command);
50
        let fee = Self::calculate_fee(gas_used_at_most, T::PricingParameters::get());
51
         */
52

            
53
92
        let queued_message: VersionedQueuedTanssiMessage = QueuedTanssiMessage {
54
92
            id: message_id,
55
92
            channel_id: message.channel_id,
56
92
            command: message.command.clone(),
57
92
        }
58
92
        .into();
59
        // The whole message should not be too large
60
92
        let encoded = queued_message
61
92
            .encode()
62
92
            .try_into()
63
92
            .map_err(|_| SendError::MessageTooLarge)?;
64

            
65
92
        let ticket = Ticket {
66
92
            message_id,
67
92
            channel_id: message.channel_id,
68
92
            message: encoded,
69
92
        };
70
92
        let fee = Fee {
71
92
            local: Default::default(),
72
92
            remote: Default::default(),
73
92
        };
74

            
75
92
        Ok((ticket, fee))
76
94
    }
77
}
78

            
79
pub struct TanssiEthMessageValidatorV2<
80
    T: snowbridge_pallet_outbound_queue_v2::Config,
81
    OwnOrigin: Get<Location>,
82
>(PhantomData<(T, OwnOrigin)>);
83

            
84
impl<T: snowbridge_pallet_outbound_queue_v2::Config, OwnOrigin: Get<Location>> ValidateMessage
85
    for TanssiEthMessageValidatorV2<T, OwnOrigin>
86
{
87
    type Ticket = TanssiTicketV2<T>;
88

            
89
47
    fn validate(message: &TanssiMessage) -> Result<(Self::Ticket, Fee<u64>), SendError> {
90
47
        log::trace!("MessageValidatorV2: {:?}", message);
91
        // The inner payload should not be too large
92
47
        let payload = message.command.abi_encode();
93

            
94
        // make it dependent on pallet-v2
95
47
        ensure!(
96
47
            payload.len() < T::MaxMessagePayloadSize::get() as usize,
97
1
            SendError::MessageTooLarge
98
        );
99

            
100
        // This is only called by system level pallets
101
        // so we can put the origin to system
102
46
        let origin = crate::TanssiAgentIdOf::convert_location(&OwnOrigin::get())
103
46
            .ok_or(SendError::InvalidOrigin)?;
104

            
105
        // Generate a unique message id unless one is provided
106
46
        let message_id: H256 = message
107
46
            .id
108
46
            .unwrap_or_else(|| unique((message.channel_id, &message.command)).into());
109

            
110
46
        let queued_message: VersionedQueuedTanssiMessage = QueuedTanssiMessage {
111
46
            id: message_id,
112
46
            channel_id: message.channel_id,
113
46
            command: message.command.clone(),
114
46
        }
115
46
        .into();
116

            
117
        // The whole message should not be too large
118
46
        let encoded = queued_message
119
46
            .encode()
120
46
            .try_into()
121
46
            .map_err(|_| SendError::MessageTooLarge)?;
122

            
123
46
        let ticket = TanssiTicketV2::<T> {
124
46
            origin,
125
46
            id: message_id,
126
46
            fee: 0,
127
46
            message: encoded,
128
46
        };
129

            
130
        // Fee not used for now
131
46
        let fee = Fee {
132
46
            local: Default::default(),
133
46
            remote: Default::default(),
134
46
        };
135

            
136
46
        Ok((ticket, fee))
137
47
    }
138
}
139

            
140
pub struct VersionedTanssiEthMessageValidator<
141
    T: snowbridge_pallet_outbound_queue::Config + snowbridge_pallet_outbound_queue_v2::Config,
142
    OwnOrigin: Get<Location>,
143
    UseV2: Get<bool>,
144
>(PhantomData<(T, OwnOrigin, UseV2)>);
145
impl<
146
        T: snowbridge_pallet_outbound_queue::Config + snowbridge_pallet_outbound_queue_v2::Config,
147
        OwnOrigin: Get<Location>,
148
        UseV2: Get<bool>,
149
    > ValidateMessage for VersionedTanssiEthMessageValidator<T, OwnOrigin, UseV2>
150
{
151
    type Ticket = VersionedTanssiTicket<T>;
152
86
    fn validate(message: &TanssiMessage) -> Result<(Self::Ticket, Fee<u64>), SendError> {
153
86
        if UseV2::get() {
154
41
            TanssiEthMessageValidatorV2::<T, OwnOrigin>::validate(message)
155
41
                .map(|(ticket, fee)| (ticket.into(), fee))
156
        } else {
157
45
            TanssiEthMessageValidatorV1::<T>::validate(message)
158
45
                .map(|(ticket, fee)| (ticket.into(), fee))
159
        }
160
86
    }
161
}