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
93
    fn validate(message: &TanssiMessage) -> Result<(Self::Ticket, Fee<u64>), SendError> {
28
93
        log::trace!("TanssiEthMessageValidatorV1: {:?}", message);
29
        // The inner payload should not be too large
30
93
        let payload = message.command.abi_encode();
31
93
        ensure!(
32
93
            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
92
        ensure!(
38
92
            T::Channels::contains(&message.channel_id),
39
1
            SendError::InvalidChannel
40
        );
41

            
42
        // Generate a unique message id unless one is provided
43
91
        let message_id: H256 = message
44
91
            .id
45
91
            .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
91
        let queued_message: VersionedQueuedTanssiMessage = QueuedTanssiMessage {
54
91
            id: message_id,
55
91
            channel_id: message.channel_id,
56
91
            command: message.command.clone(),
57
91
        }
58
91
        .into();
59
        // The whole message should not be too large
60
91
        let encoded = queued_message
61
91
            .encode()
62
91
            .try_into()
63
91
            .map_err(|_| SendError::MessageTooLarge)?;
64

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

            
75
91
        Ok((ticket, fee))
76
93
    }
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
8
    fn validate(message: &TanssiMessage) -> Result<(Self::Ticket, Fee<u64>), SendError> {
90
8
        log::trace!("MessageValidatorV2: {:?}", message);
91
        // The inner payload should not be too large
92
8
        let payload = message.command.abi_encode();
93

            
94
        // make it dependent on pallet-v2
95
8
        ensure!(
96
8
            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
7
        let origin = crate::TanssiAgentIdOf::convert_location(&OwnOrigin::get())
103
7
            .ok_or(SendError::InvalidOrigin)?;
104

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

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

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

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

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

            
136
7
        Ok((ticket, fee))
137
8
    }
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
4
    fn validate(message: &TanssiMessage) -> Result<(Self::Ticket, Fee<u64>), SendError> {
153
4
        if UseV2::get() {
154
2
            TanssiEthMessageValidatorV2::<T, OwnOrigin>::validate(message)
155
2
                .map(|(ticket, fee)| (ticket.into(), fee))
156
        } else {
157
2
            TanssiEthMessageValidatorV1::<T>::validate(message)
158
2
                .map(|(ticket, fee)| (ticket.into(), fee))
159
        }
160
4
    }
161
}