use crate::errors::DidMlnError;
use anchor_lang::prelude::*;
use bitflags::bitflags;
use itertools::Itertools;
use num_derive::*;
use num_traits::*;
use std::fmt::{Display, Formatter};
use crate::constants::VM_DEFAULT_FRAGMENT_NAME;
use crate::utils::{
check_other_controllers, convert_secp256k1pub_key_to_address, derive_did_account,
derive_did_account_with_bump, eth_verify_message,
};
#[account]
pub struct DidAccount {
pub version: u8,
pub bump: u8,
pub nonce: u64,
pub initial_verification_method: VerificationMethod,
pub verification_methods: Vec<VerificationMethod>,
pub services: Vec<Service>,
pub native_controllers: Vec<Pubkey>,
pub other_controllers: Vec<String>,
}
impl Display for DidAccount {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
let base_58_authority_key = &self.native_controllers.first().unwrap().to_string();
write!(f, "did:mln:{}", base_58_authority_key)
}
}
impl Default for DidAccount {
fn default() -> Self {
DidAccount {
version: 0,
bump: 0,
nonce: 0,
initial_verification_method: VerificationMethod {
fragment: VM_DEFAULT_FRAGMENT_NAME.to_string(),
flags: VerificationMethodFlags::CAPABILITY_INVOCATION.bits(),
method_type: 0,
key_data: vec![],
},
verification_methods: vec![],
services: vec![],
native_controllers: vec![],
other_controllers: vec![],
}
}
}
impl DidAccount {
pub fn new(bump: u8, authority_key: &Pubkey) -> Self {
Self {
version: 0,
bump,
nonce: 0,
initial_verification_method: VerificationMethod::default(
VerificationMethodFlags::CAPABILITY_INVOCATION
| VerificationMethodFlags::OWNERSHIP_PROOF
| VerificationMethodFlags::PROTECTED,
authority_key.to_bytes().to_vec(),
),
verification_methods: vec![],
services: vec![],
native_controllers: vec![],
other_controllers: vec![],
}
}
pub fn init(&mut self, bump: u8, authority_key: &Pubkey, flags: VerificationMethodFlags) {
self.version = 0;
self.bump = bump;
self.nonce = 0;
self.initial_verification_method =
VerificationMethod::default(flags, authority_key.to_bytes().to_vec());
}
pub fn verification_methods(
&self,
filter_types: Option<&[VerificationMethodType]>,
filter_flags: Option<VerificationMethodFlags>,
filter_key: Option<&[u8]>,
filter_fragment: Option<&String>,
) -> Vec<&VerificationMethod> {
std::iter::once(&self.initial_verification_method)
.chain(self.verification_methods.iter())
.filter(|vm| match filter_types {
Some(filter_types) => {
filter_types.contains(&VerificationMethodType::from_u8(vm.method_type).unwrap())
}
None => true,
})
.filter(|vm| match filter_flags {
Some(filter_flags) => VerificationMethodFlags::from_bits(vm.flags)
.unwrap()
.contains(filter_flags),
None => true,
})
.filter(|vm| match filter_key {
Some(filter_key) => vm.key_data == filter_key,
None => true,
})
.filter(|vm| match filter_fragment {
Some(filter_fragment) => vm.fragment == *filter_fragment,
None => true,
})
.collect()
}
pub fn verification_methods_mut(
&mut self,
filter_types: Option<&[VerificationMethodType]>,
filter_flags: Option<VerificationMethodFlags>,
filter_key: Option<&[u8]>,
filter_fragment: Option<&String>,
) -> Vec<&mut VerificationMethod> {
std::iter::once(&mut self.initial_verification_method)
.chain(self.verification_methods.iter_mut())
.filter(|vm| match filter_types {
Some(filter_types) => {
filter_types.contains(&VerificationMethodType::from_u8(vm.method_type).unwrap())
}
None => true,
})
.filter(|vm| match filter_flags {
Some(filter_flags) => VerificationMethodFlags::from_bits(vm.flags)
.unwrap()
.contains(filter_flags),
None => true,
})
.filter(|vm| match filter_key {
Some(filter_key) => vm.key_data == filter_key,
None => true,
})
.filter(|vm| match filter_fragment {
Some(filter_fragment) => vm.fragment == *filter_fragment,
None => true,
})
.collect()
}
pub fn has_protected_verification_method(&self, filter_fragment: Option<&String>) -> bool {
!self
.verification_methods(
None,
Some(VerificationMethodFlags::PROTECTED),
None,
filter_fragment,
)
.is_empty()
}
pub fn remove_verification_method(&mut self, fragment: &String) -> Result<()> {
if fragment == &self.initial_verification_method.fragment {
self.initial_verification_method.flags = 0;
return Ok(());
}
self.verification_methods
.iter()
.position(|vm| vm.fragment == *fragment)
.map(|index| {
self.verification_methods.remove(index);
})
.ok_or_else(|| error!(DidMlnError::VmFragmentNotFound))
}
pub fn find_verification_method(
&mut self,
fragment: &String,
) -> Option<&mut VerificationMethod> {
self.verification_methods_mut(None, None, None, Some(fragment))
.into_iter()
.next()
}
pub fn has_authority_verification_methods(&self) -> bool {
!self
.verification_methods(
Some(&VerificationMethodType::authority_types()),
Some(VerificationMethodFlags::CAPABILITY_INVOCATION),
None,
None,
)
.is_empty()
}
pub fn find_authority_constraint(
&self,
mln_authority: &Pubkey,
eth_message: &[u8],
eth_raw_signature: Option<&Secp256k1RawSignature>,
filter_fragment: Option<&String>,
) -> Option<&VerificationMethod> {
let vm = self.find_authority(
&mln_authority.to_bytes(),
Some(&[VerificationMethodType::Ed25519VerificationKey2018]),
filter_fragment,
);
if vm.is_some() {
return vm;
}
if let Some(eth_raw_signature) = eth_raw_signature {
let secp256k1_pubkey = eth_verify_message(
eth_message,
self.nonce,
eth_raw_signature.signature,
eth_raw_signature.recovery_id,
)
.ok()?;
let vm = self.find_authority(
&secp256k1_pubkey.to_bytes(),
Some(&[VerificationMethodType::EcdsaSecp256k1VerificationKey2019]),
filter_fragment,
);
if vm.is_some() {
return vm;
}
let address = convert_secp256k1pub_key_to_address(&secp256k1_pubkey);
let vm = self.find_authority(
&address,
Some(&[VerificationMethodType::EcdsaSecp256k1RecoveryMethod2020]),
filter_fragment,
);
if vm.is_some() {
return vm;
}
}
None
}
pub fn find_authority(
&self,
key: &[u8],
filter_types: Option<&[VerificationMethodType]>,
filter_fragment: Option<&String>,
) -> Option<&VerificationMethod> {
self.verification_methods(
filter_types,
Some(VerificationMethodFlags::CAPABILITY_INVOCATION),
Some(key),
filter_fragment,
)
.into_iter()
.next()
}
pub fn authority_key(&self) -> Pubkey {
Pubkey::try_from(self.initial_verification_method.key_data.as_slice()).unwrap()
}
pub fn is_directly_controlled_by(&self, other: &DidAccount) -> bool {
let other_key = other.authority_key();
self.native_controllers.iter().contains(&other_key)
}
pub fn is_controlled_by(&self, chain: &[DidAccount]) -> bool {
match chain {
[head, tail @ ..] => match self.is_directly_controlled_by(head) {
true => head.is_controlled_by(tail),
false => false,
},
_ => true,
}
}
pub fn set_services(&mut self, services: Vec<Service>, allow_duplicates: bool) -> Result<()> {
let original_size = services.len();
let unique_services = services
.into_iter()
.unique_by(|x| x.fragment.clone())
.collect_vec();
require!(
allow_duplicates || unique_services.len() == original_size,
DidMlnError::ServiceFragmentAlreadyInUse
);
self.services = unique_services;
Ok(())
}
pub fn set_verification_methods(
&mut self,
existing: Vec<VerificationMethod>,
incoming: Vec<VerificationMethod>,
) -> Result<()> {
incoming.iter().try_for_each(|vm| {
match VerificationMethodFlags::from_bits(vm.flags)
.ok_or(DidMlnError::ConversionError)?
.intersects(
VerificationMethodFlags::OWNERSHIP_PROOF | VerificationMethodFlags::PROTECTED,
) {
true => Err(DidMlnError::VmGuardedFlagOnAdd),
false => Ok(()),
}
})?;
let methods = [existing, incoming].concat();
let original_size = methods.len();
let mut unique_methods = methods
.into_iter()
.unique_by(|x| x.fragment.clone())
.collect_vec();
require!(
unique_methods.len() == original_size,
DidMlnError::VmFragmentAlreadyInUse
);
if let Some(index) = unique_methods
.iter()
.position(|vm| vm.fragment == self.initial_verification_method.fragment)
{
self.initial_verification_method.flags = unique_methods.swap_remove(index).flags;
}
self.verification_methods = unique_methods;
Ok(())
}
pub fn set_native_controllers(&mut self, native_controllers: Vec<Pubkey>) -> Result<()> {
self.native_controllers = native_controllers.into_iter().unique().collect_vec();
let own_authority = Pubkey::try_from(self.initial_verification_method.key_data.as_slice()).unwrap();
require!(
!self.native_controllers.contains(&own_authority),
DidMlnError::InvalidNativeControllers,
);
Ok(())
}
pub fn set_other_controllers(&mut self, other_controllers: Vec<String>) -> Result<()> {
self.other_controllers = other_controllers.into_iter().unique().collect_vec();
require!(
check_other_controllers(&self.other_controllers),
DidMlnError::InvalidOtherControllers
);
Ok(())
}
pub fn try_from(
did_account: &AccountInfo,
initial_authority: &Pubkey,
did_account_seed_bump: Option<u8>,
) -> Result<DidAccount> {
if did_account.owner == &System::id() {
let (derived_did_account, bump) =
if let Some(did_account_seed_bump) = did_account_seed_bump {
(
derive_did_account_with_bump(
&initial_authority.to_bytes(),
did_account_seed_bump,
)
.map_err(|_| Error::from(ErrorCode::ConstraintSeeds))?,
did_account_seed_bump,
)
} else {
derive_did_account(&initial_authority.to_bytes())
};
if derived_did_account != *did_account.key {
return Err(error!(DidMlnError::WrongAuthorityForDid));
}
return Ok(DidAccount::new(bump, initial_authority));
}
let did_account: Account<DidAccount> = Account::try_from(did_account)?;
Ok(did_account.into_inner())
}
pub fn size(&self) -> usize {
1 + 1 + 8 + VerificationMethod::default_size() + 4 + self.verification_methods.iter().fold(0, |accum, item| { accum + item.size() }) + 4 + self.services.iter().fold(0, |accum, item| { accum + item.size() }) + 4 + self.native_controllers.len() * 32 + 4 + self.other_controllers.iter().fold(0, |accum, item| { accum + 4 + item.len() })
}
pub fn initial_size() -> usize {
1 + 1 + 8 + VerificationMethod::default_size() + 4 + 4 + 4 + 4 }
}
#[derive(
AnchorSerialize, AnchorDeserialize, Copy, Clone, FromPrimitive, ToPrimitive, PartialEq, Eq,
)]
pub enum VerificationMethodType {
Ed25519VerificationKey2018,
EcdsaSecp256k1RecoveryMethod2020,
EcdsaSecp256k1VerificationKey2019,
}
impl VerificationMethodType {
pub fn authority_types() -> [VerificationMethodType; 3] {
[
VerificationMethodType::Ed25519VerificationKey2018,
VerificationMethodType::EcdsaSecp256k1VerificationKey2019,
VerificationMethodType::EcdsaSecp256k1RecoveryMethod2020,
]
}
}
impl Default for VerificationMethodType {
fn default() -> Self {
VerificationMethodType::Ed25519VerificationKey2018
}
}
#[derive(AnchorSerialize, AnchorDeserialize, Clone)]
pub struct VerificationMethod {
pub fragment: String,
pub flags: u16,
pub method_type: u8,
pub key_data: Vec<u8>,
}
impl VerificationMethod {
pub fn size(&self) -> usize {
4 + self.fragment.len()
+ 2 + 1 + 4 + self.key_data.len()
}
pub fn default(flags: VerificationMethodFlags, key_data: Vec<u8>) -> VerificationMethod {
VerificationMethod {
fragment: String::from(VM_DEFAULT_FRAGMENT_NAME),
flags: flags.bits(),
method_type: VerificationMethodType::default().to_u8().unwrap(),
key_data,
}
}
pub fn default_size() -> usize {
4 + 7 + 2 + 1 + 4 + 32 }
}
#[derive(AnchorSerialize, AnchorDeserialize, Default, Clone)]
pub struct Service {
pub fragment: String,
pub service_type: String,
pub service_endpoint: String,
}
impl Service {
pub fn size(&self) -> usize {
4 + self.fragment.len() + 4 + self.service_type.len() + 4 + self.service_endpoint.len()
}
}
#[derive(AnchorSerialize, AnchorDeserialize)]
pub struct Secp256k1RawSignature {
pub signature: [u8; 64],
pub recovery_id: u8,
}
bitflags! {
pub struct VerificationMethodFlags: u16 {
const NONE = 0;
const AUTHENTICATION = 1 << 0;
const ASSERTION = 1 << 1;
const KEY_AGREEMENT = 1 << 2;
const CAPABILITY_INVOCATION = 1 << 3;
const CAPABILITY_DELEGATION = 1 << 4;
const DID_DOC_HIDDEN = 1 << 5;
const OWNERSHIP_PROOF = 1 << 6;
const PROTECTED = 1 << 7;
}
}