common_primitives/
handles.rs

1use crate::msa::MessageSourceId;
2#[cfg(feature = "std")]
3use crate::utils::*;
4use frame_support::BoundedVec;
5use parity_scale_codec::{Decode, DecodeWithMemTracking, Encode};
6use scale_info::TypeInfo;
7#[cfg(feature = "std")]
8use serde::{Deserialize, Serialize};
9use sp_core::ConstU32;
10extern crate alloc;
11use crate::{
12	node::EIP712Encode, signatures::get_eip712_encoding_prefix, utils::to_abi_compatible_number,
13};
14use alloc::{boxed::Box, vec::Vec};
15use lazy_static::lazy_static;
16use sp_core::U256;
17
18/// The minimum base and canonical handle (not including suffix or delimiter) length in characters
19pub const HANDLE_CHARS_MIN: u32 = 3;
20/// The minimum base and canonical handle (not including suffix or delimiter) length in bytes
21pub const HANDLE_BYTES_MIN: u32 = 1 * HANDLE_CHARS_MIN;
22/// The maximum base and canonical handle (not including suffix or delimiter) length in characters
23pub const HANDLE_CHARS_MAX: u32 = 20;
24/// The maximum base and canonical handle (not including suffix or delimiter) length in bytes
25pub const HANDLE_BYTES_MAX: u32 = 32; // Hard limit of 32 bytes
26/// The maximum number of digits in a suffix
27pub const SUFFIX_MAX_DIGITS: usize = 5; // The max value of a HandleSuffix (u16) is 65535 which is 5 digits.
28/// The maximum count of suffixes allowed to be requested at once
29pub const MAX_SUFFIXES_COUNT: u16 = 100;
30/// The default count of suffixes to request if none is provided
31pub const DEFAULT_SUFFIX_COUNT: u16 = 1;
32/// A generic handle type  (base, canonical, or display)
33type Handle = BoundedVec<u8, ConstU32<HANDLE_BYTES_MAX>>;
34/// A base handle, which is chosen by the user
35pub type BaseHandle = Handle;
36/// A canonical base, which is a reduced/translated version of the base handle
37pub type CanonicalBase = Handle;
38/// A display handle, which is a base handle with suffix separated by a delimiter
39pub type DisplayHandle =
40	BoundedVec<u8, ConstU32<{ HANDLE_BYTES_MAX + SUFFIX_MAX_DIGITS as u32 + 1u32 }>>;
41/// The handle suffix
42pub type HandleSuffix = u16;
43
44/// The handle suffix range type
45pub type SuffixRangeType = u16;
46
47/// The cursor into the shuffled suffix sequence
48pub type SequenceIndex = u16;
49
50/// Claim handle payload
51#[derive(TypeInfo, Clone, Debug, Decode, DecodeWithMemTracking, Encode, PartialEq, Eq)]
52pub struct ClaimHandlePayload<BlockNumber> {
53	/// The desired base handle
54	pub base_handle: Vec<u8>,
55	/// The block number at which the proof for grant_delegation expires.
56	pub expiration: BlockNumber,
57}
58
59impl<BlockNumber> ClaimHandlePayload<BlockNumber> {
60	/// Create a new ClaimHandlePayload
61	pub fn new(base_handle: Vec<u8>, expiration: BlockNumber) -> Self {
62		ClaimHandlePayload { base_handle, expiration }
63	}
64}
65
66impl<BlockNumber> EIP712Encode for ClaimHandlePayload<BlockNumber>
67where
68	BlockNumber: Into<U256> + TryFrom<U256> + Copy,
69{
70	fn encode_eip_712(&self, chain_id: u32) -> Box<[u8]> {
71		lazy_static! {
72			// signed payload
73			static ref MAIN_TYPE_HASH: [u8; 32] =
74				sp_io::hashing::keccak_256(b"ClaimHandlePayload(string handle,uint32 expiration)");
75		}
76		// get prefix and domain separator
77		let prefix_domain_separator: Box<[u8]> =
78			get_eip712_encoding_prefix("0xcccccccccccccccccccccccccccccccccccccccc", chain_id);
79		let coded_handle = sp_io::hashing::keccak_256(self.base_handle.as_ref());
80		let expiration: U256 = self.expiration.into();
81		let coded_expiration = to_abi_compatible_number(expiration.as_u128());
82		let message = sp_io::hashing::keccak_256(
83			&[MAIN_TYPE_HASH.as_slice(), &coded_handle, &coded_expiration].concat(),
84		);
85		let combined = [prefix_domain_separator.as_ref(), &message].concat();
86		combined.into_boxed_slice()
87	}
88}
89
90/// RPC Response form for a Handle
91#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
92#[derive(Clone, Encode, Decode, PartialEq, Debug, TypeInfo, Eq)]
93pub struct HandleResponse {
94	/// Base handle (without delimiter or suffix)
95	#[cfg_attr(feature = "std", serde(with = "as_string"))]
96	pub base_handle: Vec<u8>,
97	/// Canonical handle (reduced/translated version of base)
98	#[cfg_attr(feature = "std", serde(with = "as_string"))]
99	pub canonical_base: Vec<u8>,
100	/// Suffix
101	pub suffix: HandleSuffix,
102}
103
104/// A behavior that allows for retrieving a `Handle` for a given `MessageSourceAccount`
105pub trait HandleProvider {
106	/// Validate a handle for a given `MessageSourceAccount`
107	fn get_handle_for_msa(key: MessageSourceId) -> Option<HandleResponse>;
108}
109
110/// Blanket implementation for testing.
111impl HandleProvider for () {
112	fn get_handle_for_msa(_key: MessageSourceId) -> Option<HandleResponse> {
113		None
114	}
115}
116
117/// Output response for retrieving the next suffixes for a given handle
118#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
119#[derive(Clone, Encode, Decode, PartialEq, Debug, TypeInfo, Eq)]
120pub struct PresumptiveSuffixesResponse {
121	/// The base handle
122	#[cfg_attr(feature = "std", serde(with = "as_string"))]
123	pub base_handle: Vec<u8>,
124	/// The suffixes
125	pub suffixes: Vec<HandleSuffix>,
126}
127
128/// Output response for retrieving the next suffixes for a given handle
129#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
130#[derive(Clone, Encode, Decode, PartialEq, Debug, TypeInfo, Eq)]
131pub struct CheckHandleResponse {
132	/// The base handle
133	#[cfg_attr(feature = "std", serde(with = "as_string"))]
134	pub base_handle: Vec<u8>,
135	/// The canonical handle
136	#[cfg_attr(feature = "std", serde(with = "as_string"))]
137	pub canonical_base: Vec<u8>,
138	/// The current suffix index
139	pub suffix_index: u16,
140	/// Are additional suffixes available?
141	pub suffixes_available: bool,
142	/// Validity
143	pub valid: bool,
144}
145
146impl Default for CheckHandleResponse {
147	fn default() -> Self {
148		Self {
149			base_handle: Vec::new(),
150			canonical_base: Vec::new(),
151			suffix_index: 0,
152			suffixes_available: false,
153			valid: false,
154		}
155	}
156}