1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
use frame_support::{dispatch::DispatchResult, traits::Get, BoundedBTreeMap, BoundedVec};
use parity_scale_codec::{Decode, Encode, EncodeLike, Error, MaxEncodedLen};
use scale_info::TypeInfo;
#[cfg(feature = "std")]
use serde::{Deserialize, Serialize};
use sp_runtime::{
	traits::{AtLeast32BitUnsigned, Zero},
	DispatchError, MultiSignature, RuntimeDebug,
};
use sp_std::prelude::Vec;

pub use crate::schema::SchemaId;

/// Message Source Id or msaId is the unique identifier for Message Source Accounts
pub type MessageSourceId = u64;

/// A DelegatorId an MSA Id serving the role of a Delegator.
/// Delegators delegate to Providers.
/// Encodes and Decodes as just a `u64`
#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
#[derive(TypeInfo, Default, Debug, Clone, Copy, PartialEq, MaxEncodedLen, Eq)]
pub struct DelegatorId(pub MessageSourceId);

impl EncodeLike for DelegatorId {}

impl Encode for DelegatorId {
	fn encode(&self) -> Vec<u8> {
		self.0.encode()
	}
}

impl Decode for DelegatorId {
	fn decode<I: parity_scale_codec::Input>(
		input: &mut I,
	) -> Result<Self, parity_scale_codec::Error> {
		match <u64>::decode(input) {
			Ok(x) => Ok(DelegatorId(x)),
			_ => Err(Error::from("Could not decode DelegatorId")),
		}
	}
}

impl From<MessageSourceId> for DelegatorId {
	fn from(t: MessageSourceId) -> Self {
		DelegatorId(t)
	}
}

impl From<DelegatorId> for MessageSourceId {
	fn from(t: DelegatorId) -> MessageSourceId {
		t.0
	}
}

/// RPC response for getting delegated providers with their permissions
#[cfg_attr(feature = "std", derive(Deserialize, Serialize))]
#[derive(TypeInfo, RuntimeDebug, Clone, Decode, Encode, MaxEncodedLen, Eq)]
pub struct DelegationResponse<SchemaId, BlockNumber> {
	/// SchemaId of schema for which permission is/was granted
	pub provider_id: ProviderId,
	/// The list of schema permissions grants
	pub permissions: Vec<SchemaGrant<SchemaId, BlockNumber>>,
}

/// RPC response for getting schema permission grants
#[cfg_attr(feature = "std", derive(Deserialize, Serialize))]
#[derive(TypeInfo, RuntimeDebug, Clone, Decode, Encode, MaxEncodedLen, Eq)]
pub struct SchemaGrant<SchemaId, BlockNumber> {
	/// SchemaId of schema for which permission is/was granted
	pub schema_id: SchemaId,
	/// Block number the permission was/will be revoked (0 = not revoked)
	pub revoked_at: BlockNumber,
}

impl<SchemaId, BlockNumber> PartialEq for DelegationResponse<SchemaId, BlockNumber>
where
	SchemaId: PartialEq,
	BlockNumber: PartialEq,
{
	fn eq(&self, other: &Self) -> bool {
		self.provider_id == other.provider_id && self.permissions == other.permissions
	}
}

impl<SchemaId, BlockNumber> SchemaGrant<SchemaId, BlockNumber> {
	/// Create a new SchemaGrant struct
	pub fn new(schema_id: SchemaId, revoked_at: BlockNumber) -> Self {
		SchemaGrant { schema_id, revoked_at }
	}
}

impl<SchemaId, BlockNumber> PartialEq for SchemaGrant<SchemaId, BlockNumber>
where
	SchemaId: PartialEq,
	BlockNumber: PartialEq,
{
	fn eq(&self, other: &Self) -> bool {
		self.schema_id == other.schema_id && self.revoked_at == other.revoked_at
	}
}

/// Struct for the information of the relationship between an MSA and a Provider
#[derive(TypeInfo, RuntimeDebug, Clone, Decode, Encode, MaxEncodedLen, Eq)]
#[scale_info(skip_type_params(MaxSchemaGrantsPerDelegation))]
pub struct Delegation<SchemaId, BlockNumber, MaxSchemaGrantsPerDelegation>
where
	MaxSchemaGrantsPerDelegation: Get<u32>,
{
	/// Block number the grant will be revoked.
	pub revoked_at: BlockNumber,
	/// Schemas that the provider is allowed to use for a delegated message.
	pub schema_permissions: BoundedBTreeMap<SchemaId, BlockNumber, MaxSchemaGrantsPerDelegation>,
}

// Cannot derive the PartialEq without a mess of impl PartialEq for MaxSchemaGrantsPerDelegation
impl<SchemaId, BlockNumber, MaxSchemaGrantsPerDelegation> PartialEq
	for Delegation<SchemaId, BlockNumber, MaxSchemaGrantsPerDelegation>
where
	SchemaId: PartialEq,
	BlockNumber: PartialEq,
	MaxSchemaGrantsPerDelegation: Get<u32>,
{
	fn eq(&self, other: &Self) -> bool {
		self.revoked_at == other.revoked_at && self.schema_permissions == other.schema_permissions
	}
}

impl<
		SchemaId: Ord + Default,
		BlockNumber: Ord + Copy + Zero + AtLeast32BitUnsigned + Default,
		MaxSchemaGrantsPerDelegation: Get<u32>,
	> Default for Delegation<SchemaId, BlockNumber, MaxSchemaGrantsPerDelegation>
{
	/// Provides the default values for Delegation type.
	fn default() -> Self {
		Delegation {
			revoked_at: BlockNumber::default(),
			schema_permissions: BoundedBTreeMap::<
				SchemaId,
				BlockNumber,
				MaxSchemaGrantsPerDelegation,
			>::new(),
		}
	}
}

/// Provider is the recipient of a delegation.
/// It is a subset of an MSA
/// Encodes and Decodes as just a `u64`
#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
#[derive(TypeInfo, Default, Debug, Clone, Copy, PartialEq, MaxEncodedLen, Eq)]
pub struct ProviderId(pub MessageSourceId);

impl EncodeLike for ProviderId {}

impl Encode for ProviderId {
	fn encode(&self) -> Vec<u8> {
		self.0.encode()
	}
}

impl Decode for ProviderId {
	fn decode<I: parity_scale_codec::Input>(
		input: &mut I,
	) -> Result<Self, parity_scale_codec::Error> {
		match <u64>::decode(input) {
			Ok(x) => Ok(ProviderId(x)),
			_ => Err(Error::from("Could not decode ProviderId")),
		}
	}
}

impl From<MessageSourceId> for ProviderId {
	fn from(t: MessageSourceId) -> Self {
		ProviderId(t)
	}
}

impl From<ProviderId> for MessageSourceId {
	fn from(t: ProviderId) -> MessageSourceId {
		t.0
	}
}

/// This is the metadata associated with a provider. As of now it is just a
/// name, but it will likely be expanded in the future
#[derive(MaxEncodedLen, TypeInfo, Debug, Clone, Decode, Encode, PartialEq, Eq)]
#[scale_info(skip_type_params(T))]
pub struct ProviderRegistryEntry<T>
where
	T: Get<u32>,
{
	/// The provider's name
	pub provider_name: BoundedVec<u8, T>,
}

/// The pointer value for the Signature Registry
#[derive(MaxEncodedLen, TypeInfo, Debug, Clone, Decode, Encode, PartialEq, Eq)]
pub struct SignatureRegistryPointer<BlockNumber> {
	/// The newest signature that will be added to the registry when we get the next newest
	pub newest: MultiSignature,

	/// Block number that `newest` expires at
	pub newest_expires_at: BlockNumber,

	/// Pointer to the oldest signature in the list
	pub oldest: MultiSignature,

	/// Count of signatures in the registry
	/// Will eventually match the `MaxSignaturesStored`, but during initialization is needed to fill the list
	pub count: u32,
}

/// A behavior that allows looking up an MSA id
pub trait MsaLookup {
	/// The association between key and MSA
	type AccountId;

	/// Gets the MSA Id associated with this `AccountId` if any
	fn get_msa_id(key: &Self::AccountId) -> Option<MessageSourceId>;
}

/// A behavior that allows for validating an MSA
pub trait MsaValidator {
	/// The association between key and MSA
	type AccountId;

	/// Check that a key is associated to an MSA and returns key information.
	/// Returns a [`DispatchError`] if there is no MSA associated with the key
	fn ensure_valid_msa_key(key: &Self::AccountId) -> Result<MessageSourceId, DispatchError>;
}

/// A behavior that allows for looking up delegator-provider relationships
pub trait ProviderLookup {
	/// Type for block number.
	type BlockNumber;
	/// Type for maximum number of schemas that can be granted to a provider.
	type MaxSchemaGrantsPerDelegation: Get<u32>;
	/// Schema Id is the unique identifier for a Schema
	type SchemaId;

	/// Gets the relationship information for this delegator, provider pair
	fn get_delegation_of(
		delegator: DelegatorId,
		provider: ProviderId,
	) -> Option<Delegation<Self::SchemaId, Self::BlockNumber, Self::MaxSchemaGrantsPerDelegation>>;
}

/// A behavior that allows for validating a delegator-provider relationship
pub trait DelegationValidator {
	/// Type for block number.
	type BlockNumber;
	/// Type for maximum number of schemas that can be granted to a provider.
	type MaxSchemaGrantsPerDelegation: Get<u32>;
	/// Schema Id is the unique identifier for a Schema
	type SchemaId;

	/// Validates that the delegator and provider have a relationship at this point
	fn ensure_valid_delegation(
		provider: ProviderId,
		delegator: DelegatorId,
		block_number: Option<Self::BlockNumber>,
	) -> Result<
		Delegation<Self::SchemaId, Self::BlockNumber, Self::MaxSchemaGrantsPerDelegation>,
		DispatchError,
	>;
}

/// A behavior that allows for validating a schema grant
pub trait SchemaGrantValidator<BlockNumber> {
	/// Validates if the provider is allowed to use the particular schema id currently
	fn ensure_valid_schema_grant(
		provider_id: ProviderId,
		delegator_id: DelegatorId,
		schema_id: SchemaId,
		block_number: BlockNumber,
	) -> DispatchResult;
}

/// RPC Response for getting getting MSA keys
#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
#[derive(TypeInfo, Debug, Clone, Decode, Encode, PartialEq, Default, MaxEncodedLen)]
pub struct KeyInfoResponse<AccountId> {
	/// The MSA associated with the `key`
	pub msa_id: MessageSourceId,
	/// The list of `AccountId` associated with the `msa_id`
	pub msa_keys: Vec<AccountId>,
}

#[cfg(test)]
mod tests {
	use super::*;

	#[test]
	fn decoding_provider_id_failure() {
		let mut da: &[u8] = b"\xf6\xf5";
		let decoded = DelegatorId::decode(&mut da);
		assert!(decoded.is_err());
	}

	#[test]
	fn decoding_provider_id_success() {
		let val = 16777215_u64.encode();
		let decoded = ProviderId::decode(&mut &val[..]);
		assert_eq!(decoded, Ok(ProviderId(16777215)))
	}

	#[test]
	fn decoding_delegate_id_failure() {
		let mut da: &[u8] = b"\xf6\xf5";
		let decoded = DelegatorId::decode(&mut da);
		assert!(decoded.is_err());
	}

	#[test]
	fn decoding_delegator_id_success() {
		let val = 42_u64.encode();
		let decoded = DelegatorId::decode(&mut &val[..]);
		assert_eq!(decoded, Ok(DelegatorId(42)))
	}
}