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
mod pallet_xcm_benchmarks_fungible;
18
mod pallet_xcm_benchmarks_generic;
19

            
20
use frame_support::BoundedVec;
21
use xcm::latest::AssetTransferFilter;
22
use {
23
    crate::Runtime,
24
    frame_support::weights::Weight,
25
    pallet_xcm_benchmarks_fungible::WeightInfo as XcmBalancesWeight,
26
    pallet_xcm_benchmarks_generic::WeightInfo as XcmGeneric,
27
    sp_std::prelude::*,
28
    xcm::{
29
        latest::{prelude::*, Weight as XCMWeight},
30
        DoubleEncoded,
31
    },
32
};
33

            
34
const MAX_ASSETS: u64 = 1;
35

            
36
pub enum AssetTypes {
37
    Balances,
38
    Unknown,
39
}
40

            
41
impl From<&Asset> for AssetTypes {
42
10
    fn from(asset: &Asset) -> Self {
43
10
        match asset {
44
            Asset {
45
                id:
46
                    AssetId(Location {
47
                        parents: 0,
48
                        interior: Here,
49
                    }),
50
                ..
51
10
            } => AssetTypes::Balances,
52
            _ => AssetTypes::Unknown,
53
        }
54
10
    }
55
}
56

            
57
trait WeighAssets {
58
    fn weigh_assets(&self, balances_weight: Weight) -> Weight;
59
}
60

            
61
impl WeighAssets for AssetFilter {
62
    fn weigh_assets(&self, balances_weight: Weight) -> Weight {
63
        match self {
64
            Self::Definite(assets) => assets
65
                .inner()
66
                .into_iter()
67
                .map(From::from)
68
                .map(|t| match t {
69
                    AssetTypes::Balances => balances_weight,
70
                    AssetTypes::Unknown => Weight::MAX,
71
                })
72
                .fold(Weight::zero(), |acc, x| acc.saturating_add(x)),
73
            Self::Wild(AllOf { .. } | AllOfCounted { .. }) => balances_weight,
74
            Self::Wild(AllCounted(count)) => {
75
                balances_weight.saturating_mul(MAX_ASSETS.min(*count as u64))
76
            }
77
            Self::Wild(All) => balances_weight.saturating_mul(MAX_ASSETS),
78
        }
79
    }
80
}
81

            
82
impl WeighAssets for Assets {
83
10
    fn weigh_assets(&self, balances_weight: Weight) -> Weight {
84
10
        self.inner()
85
10
            .into_iter()
86
10
            .map(|m| <AssetTypes as From<&Asset>>::from(m))
87
10
            .map(|t| match t {
88
10
                AssetTypes::Balances => balances_weight,
89
                AssetTypes::Unknown => Weight::MAX,
90
10
            })
91
10
            .fold(Weight::zero(), |acc, x| acc.saturating_add(x))
92
10
    }
93
}
94

            
95
// For now we are returning benchmarked weights only for generic XCM instructions.
96
// Fungible XCM instructions will return a fixed weight value of
97
// 200_000_000 ref_time and its proper PoV weight taken from statemint benchmarks.
98
//
99
// TODO: add the fungible benchmarked values once these are calculated.
100
pub struct XcmWeight<RuntimeCall>(core::marker::PhantomData<RuntimeCall>);
101
impl<RuntimeCall> XcmWeightInfo<RuntimeCall> for XcmWeight<RuntimeCall>
102
where
103
    Runtime: frame_system::Config,
104
{
105
    fn withdraw_asset(assets: &Assets) -> XCMWeight {
106
        assets.weigh_assets(XcmBalancesWeight::<Runtime>::withdraw_asset())
107
    }
108
    fn reserve_asset_deposited(assets: &Assets) -> XCMWeight {
109
        assets.weigh_assets(XcmBalancesWeight::<Runtime>::reserve_asset_deposited())
110
    }
111
    fn receive_teleported_asset(assets: &Assets) -> XCMWeight {
112
        assets.weigh_assets(XcmBalancesWeight::<Runtime>::receive_teleported_asset())
113
    }
114
    fn query_response(
115
        _query_id: &u64,
116
        _response: &Response,
117
        _max_weight: &Weight,
118
        _querier: &Option<Location>,
119
    ) -> XCMWeight {
120
        XcmGeneric::<Runtime>::query_response()
121
    }
122
1
    fn transfer_asset(assets: &Assets, _dest: &Location) -> XCMWeight {
123
1
        assets.weigh_assets(XcmBalancesWeight::<Runtime>::transfer_asset())
124
1
    }
125
    fn transfer_reserve_asset(assets: &Assets, _dest: &Location, _xcm: &Xcm<()>) -> XCMWeight {
126
        assets.weigh_assets(XcmBalancesWeight::<Runtime>::transfer_reserve_asset())
127
    }
128
    fn transact(
129
        _origin_type: &OriginKind,
130
        _require_weight_at_most: &Option<Weight>,
131
        _call: &DoubleEncoded<RuntimeCall>,
132
    ) -> XCMWeight {
133
        XcmGeneric::<Runtime>::transact()
134
    }
135
    fn hrmp_new_channel_open_request(
136
        _sender: &u32,
137
        _max_message_size: &u32,
138
        _max_capacity: &u32,
139
    ) -> XCMWeight {
140
        // XCM Executor does not currently support HRMP channel operations
141
        Weight::MAX
142
    }
143
    fn hrmp_channel_accepted(_recipient: &u32) -> XCMWeight {
144
        // XCM Executor does not currently support HRMP channel operations
145
        Weight::MAX
146
    }
147
    fn hrmp_channel_closing(_initiator: &u32, _sender: &u32, _recipient: &u32) -> XCMWeight {
148
        // XCM Executor does not currently support HRMP channel operations
149
        Weight::MAX
150
    }
151
    fn clear_origin() -> XCMWeight {
152
        XcmGeneric::<Runtime>::clear_origin()
153
    }
154
    fn descend_origin(_who: &InteriorLocation) -> XCMWeight {
155
        XcmGeneric::<Runtime>::descend_origin()
156
    }
157
    fn report_error(_query_response_info: &QueryResponseInfo) -> XCMWeight {
158
        XcmGeneric::<Runtime>::report_error()
159
    }
160
    fn deposit_asset(assets: &AssetFilter, _dest: &Location) -> XCMWeight {
161
        assets.weigh_assets(XcmBalancesWeight::<Runtime>::deposit_asset())
162
    }
163
    fn deposit_reserve_asset(assets: &AssetFilter, _dest: &Location, _xcm: &Xcm<()>) -> XCMWeight {
164
        assets.weigh_assets(XcmBalancesWeight::<Runtime>::deposit_reserve_asset())
165
    }
166
    fn exchange_asset(_give: &AssetFilter, _receive: &Assets, _maximal: &bool) -> XCMWeight {
167
        Weight::MAX
168
    }
169
    fn initiate_reserve_withdraw(
170
        assets: &AssetFilter,
171
        _reserve: &Location,
172
        _xcm: &Xcm<()>,
173
    ) -> XCMWeight {
174
        assets.weigh_assets(XcmBalancesWeight::<Runtime>::initiate_reserve_withdraw())
175
    }
176
    fn initiate_teleport(assets: &AssetFilter, _dest: &Location, _xcm: &Xcm<()>) -> XCMWeight {
177
        assets.weigh_assets(XcmBalancesWeight::<Runtime>::initiate_teleport())
178
    }
179
    fn report_holding(_response_info: &QueryResponseInfo, _assets: &AssetFilter) -> Weight {
180
        XcmGeneric::<Runtime>::report_holding()
181
    }
182
    fn buy_execution(_fees: &Asset, _weight_limit: &WeightLimit) -> XCMWeight {
183
        XcmGeneric::<Runtime>::buy_execution()
184
    }
185
    fn refund_surplus() -> XCMWeight {
186
        XcmGeneric::<Runtime>::refund_surplus()
187
    }
188
    fn set_error_handler(_xcm: &Xcm<RuntimeCall>) -> XCMWeight {
189
        XcmGeneric::<Runtime>::set_error_handler()
190
    }
191
    fn set_appendix(_xcm: &Xcm<RuntimeCall>) -> XCMWeight {
192
        XcmGeneric::<Runtime>::set_appendix()
193
    }
194
    fn clear_error() -> XCMWeight {
195
        XcmGeneric::<Runtime>::clear_error()
196
    }
197
    fn claim_asset(_assets: &Assets, _ticket: &Location) -> XCMWeight {
198
        XcmGeneric::<Runtime>::claim_asset()
199
    }
200
    fn trap(_code: &u64) -> XCMWeight {
201
        XcmGeneric::<Runtime>::trap()
202
    }
203
    fn subscribe_version(_query_id: &QueryId, _max_response_weight: &Weight) -> XCMWeight {
204
        XcmGeneric::<Runtime>::subscribe_version()
205
    }
206
    fn unsubscribe_version() -> XCMWeight {
207
        XcmGeneric::<Runtime>::unsubscribe_version()
208
    }
209
    fn burn_asset(assets: &Assets) -> Weight {
210
        assets.weigh_assets(XcmGeneric::<Runtime>::burn_asset())
211
    }
212
    fn expect_asset(assets: &Assets) -> Weight {
213
        assets.weigh_assets(XcmGeneric::<Runtime>::expect_asset())
214
    }
215
    fn expect_origin(_origin: &Option<Location>) -> Weight {
216
        XcmGeneric::<Runtime>::expect_origin()
217
    }
218
    fn expect_error(_error: &Option<(u32, XcmError)>) -> Weight {
219
        XcmGeneric::<Runtime>::expect_error()
220
    }
221
    fn expect_transact_status(_transact_status: &MaybeErrorCode) -> Weight {
222
        XcmGeneric::<Runtime>::expect_transact_status()
223
    }
224
    fn query_pallet(_module_name: &Vec<u8>, _response_info: &QueryResponseInfo) -> Weight {
225
        XcmGeneric::<Runtime>::query_pallet()
226
    }
227
    fn expect_pallet(
228
        _index: &u32,
229
        _name: &Vec<u8>,
230
        _module_name: &Vec<u8>,
231
        _crate_major: &u32,
232
        _min_crate_minor: &u32,
233
    ) -> Weight {
234
        XcmGeneric::<Runtime>::expect_pallet()
235
    }
236
    fn report_transact_status(_response_info: &QueryResponseInfo) -> Weight {
237
        XcmGeneric::<Runtime>::report_transact_status()
238
    }
239
    fn clear_transact_status() -> Weight {
240
        XcmGeneric::<Runtime>::clear_transact_status()
241
    }
242
    fn universal_origin(_: &Junction) -> Weight {
243
        Weight::MAX
244
    }
245
1
    fn export_message(_: &NetworkId, _: &Junctions, _: &Xcm<()>) -> Weight {
246
1
        Weight::MAX
247
1
    }
248
    fn lock_asset(_: &Asset, _: &Location) -> Weight {
249
        Weight::MAX
250
    }
251
    fn unlock_asset(_: &Asset, _: &Location) -> Weight {
252
        Weight::MAX
253
    }
254
    fn note_unlockable(_: &Asset, _: &Location) -> Weight {
255
        Weight::MAX
256
    }
257
    fn request_unlock(_: &Asset, _: &Location) -> Weight {
258
        Weight::MAX
259
    }
260
    fn set_fees_mode(_: &bool) -> Weight {
261
        XcmGeneric::<Runtime>::set_fees_mode()
262
    }
263
    fn set_topic(_topic: &[u8; 32]) -> Weight {
264
        XcmGeneric::<Runtime>::set_topic()
265
    }
266
    fn clear_topic() -> Weight {
267
        XcmGeneric::<Runtime>::clear_topic()
268
    }
269
    fn alias_origin(_: &Location) -> Weight {
270
        // XCM Executor does not currently support alias origin operations
271
        Weight::MAX
272
    }
273
    fn unpaid_execution(_: &WeightLimit, _: &Option<Location>) -> Weight {
274
        XcmGeneric::<Runtime>::unpaid_execution()
275
    }
276

            
277
    fn pay_fees(_asset: &Asset) -> Weight {
278
        XcmGeneric::<Runtime>::pay_fees()
279
    }
280

            
281
    fn initiate_transfer(
282
        _dest: &Location,
283
        remote_fees: &Option<AssetTransferFilter>,
284
        _preserve_origin: &bool,
285
        assets: &Vec<AssetTransferFilter>,
286
        _xcm: &Xcm<()>,
287
    ) -> Weight {
288
        let mut weight = if let Some(remote_fees) = remote_fees {
289
            let fees = remote_fees.inner();
290
            fees.weigh_assets(XcmBalancesWeight::<Runtime>::initiate_transfer())
291
        } else {
292
            Weight::zero()
293
        };
294
        for asset_filter in assets {
295
            let assets = asset_filter.inner();
296
            let extra = assets.weigh_assets(XcmBalancesWeight::<Runtime>::initiate_transfer());
297
            weight = weight.saturating_add(extra);
298
        }
299
        weight
300
    }
301

            
302
    fn execute_with_origin(
303
        _descendant_origin: &Option<InteriorLocation>,
304
        _xcm: &Xcm<RuntimeCall>,
305
    ) -> Weight {
306
        XcmGeneric::<Runtime>::execute_with_origin()
307
    }
308

            
309
    fn set_hints(hints: &BoundedVec<Hint, HintNumVariants>) -> Weight {
310
        let mut weight = Weight::zero();
311
        for hint in hints {
312
            match hint {
313
                AssetClaimer { .. } => {
314
                    weight = weight.saturating_add(XcmGeneric::<Runtime>::asset_claimer());
315
                }
316
            }
317
        }
318
        weight
319
    }
320
}