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 {
18
    super::*,
19
    dp_core::ParaId,
20
    frame_support::{dispatch::DispatchErrorWithPostInfo, pallet_prelude::*},
21
    serde::{de::DeserializeOwned, Serialize},
22
    tp_traits::{apply, derive_scale_codec, derive_storage_traits},
23
};
24

            
25
// Data preserver profile.
26
#[apply(derive_scale_codec)]
27
#[derive(RuntimeDebugNoBound, PartialEqNoBound, EqNoBound, CloneNoBound, MaxEncodedLen)]
28
#[scale_info(skip_type_params(T))]
29
pub struct Profile<T: Config> {
30
    pub url: BoundedVec<u8, T::MaxNodeUrlLen>,
31
    pub para_ids: ParaIdsFilter<T>,
32
    pub mode: ProfileMode,
33
    pub assignment_request: ProviderRequestOf<T>,
34
}
35

            
36
#[apply(derive_scale_codec)]
37
#[derive(RuntimeDebugNoBound, PartialEqNoBound, EqNoBound, CloneNoBound, MaxEncodedLen)]
38
#[scale_info(skip_type_params(T))]
39
pub enum ParaIdsFilter<T: Config> {
40
621
    AnyParaId,
41
398
    Whitelist(BoundedBTreeSet<ParaId, T::MaxParaIdsVecLen>),
42
    Blacklist(BoundedBTreeSet<ParaId, T::MaxParaIdsVecLen>),
43
}
44

            
45
impl<T: Config> ParaIdsFilter<T> {
46
    #[allow(clippy::len_without_is_empty)]
47
252
    pub fn len(&self) -> usize {
48
252
        match self {
49
96
            Self::AnyParaId => 0,
50
156
            Self::Whitelist(list) | Self::Blacklist(list) => list.len(),
51
        }
52
252
    }
53

            
54
215
    pub fn can_assign(&self, para_id: &ParaId) -> bool {
55
215
        match self {
56
176
            ParaIdsFilter::AnyParaId => true,
57
39
            ParaIdsFilter::Whitelist(list) => list.contains(para_id),
58
            ParaIdsFilter::Blacklist(list) => !list.contains(para_id),
59
        }
60
215
    }
61
}
62

            
63
#[apply(derive_storage_traits)]
64
#[derive(MaxEncodedLen)]
65
pub enum ProfileMode {
66
968
    Bootnode,
67
51
    Rpc { supports_ethereum_rpcs: bool },
68
}
69

            
70
/// Profile with additional data:
71
/// - the account id which created (and manage) the profile
72
/// - the amount deposited to register the profile
73
#[apply(derive_scale_codec)]
74
#[derive(RuntimeDebugNoBound, PartialEqNoBound, EqNoBound, CloneNoBound, MaxEncodedLen)]
75
#[scale_info(skip_type_params(T))]
76
pub struct RegisteredProfile<T: Config> {
77
    pub account: T::AccountId,
78
    pub deposit: BalanceOf<T>,
79
    pub profile: Profile<T>,
80
    /// There can be at most 1 assignment per profile.
81
    pub assignment: Option<(ParaId, AssignmentWitnessOf<T>)>,
82
}
83

            
84
/// Allows to process various kinds of payment options for assignments.
85
pub trait AssignmentProcessor<AccountId> {
86
    /// Providers requests which kind of payment it accepts.
87
    type ProviderRequest: tp_traits::StorageTraits + Serialize + DeserializeOwned + MaxEncodedLen;
88
    /// Extra parameter the assigner provides.
89
    type AssignerParameter: tp_traits::StorageTraits + Serialize + DeserializeOwned;
90
    /// Represents the succesful outcome of the assignment.
91
    type AssignmentWitness: tp_traits::StorageTraits + Serialize + DeserializeOwned + MaxEncodedLen;
92

            
93
    fn try_start_assignment(
94
        assigner: AccountId,
95
        provider: AccountId,
96
        request: &Self::ProviderRequest,
97
        extra: Self::AssignerParameter,
98
    ) -> Result<Self::AssignmentWitness, DispatchErrorWithPostInfo>;
99

            
100
    fn try_stop_assignment(
101
        provider: AccountId,
102
        witness: Self::AssignmentWitness,
103
    ) -> Result<(), DispatchErrorWithPostInfo>;
104

            
105
    /// Return the values for a free assignment if it is supported.
106
    /// This is required to perform automatic migration from old Bootnodes storage.
107
    fn free_variant_values() -> Option<(
108
        Self::ProviderRequest,
109
        Self::AssignerParameter,
110
        Self::AssignmentWitness,
111
    )>;
112

            
113
    // The values returned by the following functions should match with each other.
114
    #[cfg(feature = "runtime-benchmarks")]
115
    fn benchmark_provider_request() -> Self::ProviderRequest;
116

            
117
    #[cfg(feature = "runtime-benchmarks")]
118
    fn benchmark_assigner_parameter() -> Self::AssignerParameter;
119

            
120
    #[cfg(feature = "runtime-benchmarks")]
121
    fn benchmark_assignment_witness() -> Self::AssignmentWitness;
122
}