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
//! Crate containing various traits used by moondance crates allowing to connect pallet
18
//! with each other or with mocks.
19

            
20
#![cfg_attr(not(feature = "std"), no_std)]
21
extern crate alloc;
22

            
23
use {
24
    core::marker::PhantomData,
25
    frame_support::{
26
        traits::{BatchesFootprints, EnqueueMessage, QueueFootprint, QueueFootprintQuery},
27
        BoundedSlice,
28
    },
29
    pallet_message_queue::OnQueueChanged,
30
    sp_core::MaxEncodedLen,
31
};
32

            
33
/// Means of converting an origin to a different one before calling an EnqueueMessage impl
34
/// Useful for certain cases like pallet parachains inclusion
35
/// This pallet assumes single-aggregate origin which is not the case in our runtime
36
pub struct MessageQueueWrapper<Origin, NewOrigin, InnerMessageQueue>(
37
    PhantomData<(Origin, NewOrigin, InnerMessageQueue)>,
38
);
39

            
40
impl<Origin, NewOrigin, InnerMessageQueue> EnqueueMessage<Origin>
41
    for MessageQueueWrapper<Origin, NewOrigin, InnerMessageQueue>
42
where
43
    Origin: Clone + MaxEncodedLen,
44
    NewOrigin: From<Origin> + Clone + MaxEncodedLen,
45
    InnerMessageQueue: EnqueueMessage<NewOrigin>,
46
{
47
    type MaxMessageLen = <InnerMessageQueue as EnqueueMessage<NewOrigin>>::MaxMessageLen;
48

            
49
    fn enqueue_message(message: BoundedSlice<u8, Self::MaxMessageLen>, origin: Origin) {
50
        let new_origin: NewOrigin = origin.into();
51
        InnerMessageQueue::enqueue_message(message, new_origin)
52
    }
53

            
54
    fn enqueue_messages<'a>(
55
        messages: impl Iterator<Item = BoundedSlice<'a, u8, Self::MaxMessageLen>>,
56
        origin: Origin,
57
    ) {
58
        let new_origin: NewOrigin = origin.into();
59
        InnerMessageQueue::enqueue_messages(messages, new_origin)
60
    }
61

            
62
    fn sweep_queue(origin: Origin) {
63
        let new_origin: NewOrigin = origin.into();
64
        InnerMessageQueue::sweep_queue(new_origin)
65
    }
66
}
67

            
68
/// Means of converting an origin to a different one before calling a QueueFootprintQuery impl
69
/// Useful for certain cases like pallet parachains inclusion
70
/// This pallet assumes single-aggregate origin which is not the case in our runtime
71
impl<Origin, NewOrigin, InnerMessageQueue> QueueFootprintQuery<Origin>
72
    for MessageQueueWrapper<Origin, NewOrigin, InnerMessageQueue>
73
where
74
    Origin: Clone + MaxEncodedLen,
75
    NewOrigin: From<Origin> + Clone + MaxEncodedLen,
76
    InnerMessageQueue: QueueFootprintQuery<NewOrigin>,
77
{
78
    type MaxMessageLen = <InnerMessageQueue as QueueFootprintQuery<NewOrigin>>::MaxMessageLen;
79
    fn get_batches_footprints<'a>(
80
        origin: Origin,
81
        msgs: impl Iterator<Item = BoundedSlice<'a, u8, Self::MaxMessageLen>>,
82
        total_pages_limit: u32,
83
    ) -> BatchesFootprints {
84
        let new_origin: NewOrigin = origin.into();
85
        InnerMessageQueue::get_batches_footprints(new_origin, msgs, total_pages_limit)
86
    }
87

            
88
26
    fn footprint(origin: Origin) -> QueueFootprint {
89
26
        let new_origin: NewOrigin = origin.into();
90
26
        InnerMessageQueue::footprint(new_origin)
91
26
    }
92
}
93

            
94
/// Means of converting an origin to a different one before calling an OnQueueChanged impl
95
/// Useful for certain cases like pallet parachains inclusion
96
/// This pallet assumes single-aggregate origin which is not the case in our runtime
97
pub struct OnQueueChangedWrapper<Origin, NewOrigin, InnerOnQueueChanged>(
98
    PhantomData<(Origin, NewOrigin, InnerOnQueueChanged)>,
99
);
100

            
101
impl<Origin, NewOrigin, InnerOnQueueChanged> OnQueueChanged<Origin>
102
    for OnQueueChangedWrapper<Origin, NewOrigin, InnerOnQueueChanged>
103
where
104
    Origin: Clone + MaxEncodedLen,
105
    NewOrigin: Clone + MaxEncodedLen + TryFrom<Origin>,
106
    InnerOnQueueChanged: OnQueueChanged<NewOrigin>,
107
{
108
308
    fn on_queue_changed(origin: Origin, fp: QueueFootprint) {
109
        // Do not do anyhting if the result is not OK
110
        // This is important, an example of this is what we are going to use it for in our runtimes
111
        // we have a multi-vaiant enum aggregate origin but parachains_inclusion pallet only works with
112
        // single-variant enum aggregate origin. therefore we need to convert one of our variants to the single-enum origin
113
        // we dont want to do anything if the conversion is unsuccesful
114
308
        let new_origin = origin.try_into();
115
308
        match new_origin {
116
16
            Ok(new_origin) => InnerOnQueueChanged::on_queue_changed(new_origin, fp),
117
292
            _ => {}
118
        }
119
308
    }
120
}