#![cfg_attr(not(feature = "std"), no_std)]
use super::*;
use parity_scale_codec::{Decode, Encode};
use core::fmt::Debug;
pub use common_primitives::msa::{
Delegation, DelegatorId, KeyInfoResponse, MessageSourceId, ProviderId,
};
use common_primitives::{node::BlockNumber, schema::SchemaId};
use common_primitives::{
signatures::{get_eip712_encoding_prefix, AccountAddressMapper, EthereumAddressMapper},
utils::to_abi_compatible_number,
};
use scale_info::TypeInfo;
use sp_core::U256;
pub const EMPTY_FUNCTION: fn(MessageSourceId) -> DispatchResult = |_| Ok(());
#[derive(
TypeInfo, RuntimeDebugNoBound, Clone, Decode, DecodeWithMemTracking, Encode, PartialEq, Eq,
)]
#[scale_info(skip_type_params(T))]
pub struct AddKeyData<T: Config> {
pub msa_id: MessageSourceId,
pub expiration: BlockNumberFor<T>,
pub new_public_key: T::AccountId,
}
impl<T: Config> EIP712Encode for AddKeyData<T> {
fn encode_eip_712(&self) -> Box<[u8]> {
lazy_static! {
static ref PREFIX_DOMAIN_SEPARATOR: Box<[u8]> =
get_eip712_encoding_prefix("0xcccccccccccccccccccccccccccccccccccccccc");
static ref MAIN_TYPE_HASH: [u8; 32] = sp_io::hashing::keccak_256(
b"AddKeyData(uint64 msaId,uint32 expiration,address newPublicKey)",
);
}
let coded_owner_msa_id = to_abi_compatible_number(self.msa_id);
let expiration: U256 = self.expiration.into();
let coded_expiration = to_abi_compatible_number(expiration.as_u128());
let converted_public_key = T::ConvertIntoAccountId32::convert(self.new_public_key.clone());
let mut zero_prefixed_address = [0u8; 32];
zero_prefixed_address[12..]
.copy_from_slice(&EthereumAddressMapper::to_ethereum_address(converted_public_key).0);
let message = sp_io::hashing::keccak_256(
&[
MAIN_TYPE_HASH.as_slice(),
&coded_owner_msa_id,
&coded_expiration,
&zero_prefixed_address,
]
.concat(),
);
let combined = [PREFIX_DOMAIN_SEPARATOR.as_ref(), &message].concat();
combined.into_boxed_slice()
}
}
#[derive(TypeInfo, Clone, Debug, Decode, DecodeWithMemTracking, Encode, PartialEq, Eq)]
pub struct AddProvider {
pub authorized_msa_id: MessageSourceId,
pub schema_ids: Vec<SchemaId>,
pub expiration: BlockNumber,
}
impl EIP712Encode for AddProvider {
fn encode_eip_712(&self) -> Box<[u8]> {
lazy_static! {
static ref PREFIX_DOMAIN_SEPARATOR: Box<[u8]> =
get_eip712_encoding_prefix("0xcccccccccccccccccccccccccccccccccccccccc");
static ref MAIN_TYPE_HASH: [u8; 32] = sp_io::hashing::keccak_256(
b"AddProvider(uint64 authorizedMsaId,uint16[] schemaIds,uint32 expiration)"
);
}
let coded_authorized_msa_id = to_abi_compatible_number(self.authorized_msa_id);
let schema_ids: Vec<u8> = self
.schema_ids
.iter()
.flat_map(|schema_id| to_abi_compatible_number(*schema_id))
.collect();
let schema_ids = sp_io::hashing::keccak_256(&schema_ids);
let coded_expiration = to_abi_compatible_number(self.expiration);
let message = sp_io::hashing::keccak_256(
&[MAIN_TYPE_HASH.as_slice(), &coded_authorized_msa_id, &schema_ids, &coded_expiration]
.concat(),
);
let combined = [PREFIX_DOMAIN_SEPARATOR.as_ref(), &message].concat();
combined.into_boxed_slice()
}
}
impl AddProvider {
pub fn new(
authorized_msa_id: MessageSourceId,
schema_ids: Option<Vec<SchemaId>>,
expiration: BlockNumber,
) -> Self {
let schema_ids = schema_ids.unwrap_or_default();
Self { authorized_msa_id, schema_ids, expiration }
}
}
pub trait PermittedDelegationSchemas<T: Config> {
fn try_insert_schema(&mut self, schema_id: SchemaId) -> Result<(), DispatchError>;
fn try_insert_schemas(&mut self, schema_ids: Vec<SchemaId>) -> Result<(), DispatchError> {
for schema_id in schema_ids.into_iter() {
self.try_insert_schema(schema_id)?;
}
Ok(())
}
fn try_get_mut_schemas(
&mut self,
schema_ids: Vec<SchemaId>,
block_number: BlockNumberFor<T>,
) -> Result<(), DispatchError> {
for schema_id in schema_ids.into_iter() {
self.try_get_mut_schema(schema_id, block_number)?;
}
Ok(())
}
fn try_get_mut_schema(
&mut self,
schema_id: SchemaId,
block_number: BlockNumberFor<T>,
) -> Result<(), DispatchError>;
}
impl<T: Config> PermittedDelegationSchemas<T>
for Delegation<SchemaId, BlockNumberFor<T>, T::MaxSchemaGrantsPerDelegation>
{
fn try_insert_schema(&mut self, schema_id: SchemaId) -> Result<(), DispatchError> {
self.schema_permissions
.try_insert(schema_id, Default::default())
.map_err(|_| Error::<T>::ExceedsMaxSchemaGrantsPerDelegation)?;
Ok(())
}
fn try_get_mut_schema(
&mut self,
schema_id: SchemaId,
block_number: BlockNumberFor<T>,
) -> Result<(), DispatchError> {
let schema = self
.schema_permissions
.get_mut(&schema_id)
.ok_or(Error::<T>::SchemaNotGranted)?;
*schema = block_number;
Ok(())
}
}