use crate::constants::VM_DEFAULT_FRAGMENT_NAME;
use crate::state::{DidAccount, VerificationMethodFlags, VerificationMethodType};
use crate::{Service, VerificationMethod};
use anchor_lang::prelude::*;
use anchor_lang::{AccountDeserialize, AccountSerialize, Owner};
use borsh::BorshDeserialize;
use num_traits::*;
use std::str::FromStr;
#[derive(Clone, BorshDeserialize)]
pub struct LegacyServiceEndpoint {
pub id: String,
pub endpoint_type: String,
pub endpoint: String,
pub description: String,
}
impl LegacyServiceEndpoint {
pub fn post_migration_size(&self) -> usize {
4 + self.id.len() + 4 + self.endpoint_type.len() + 4 + self.endpoint.len()
}
}
#[derive(Clone, BorshDeserialize)]
pub struct LegacyVerificationMethod {
pub id: String,
pub verification_type: String,
pub pubkey: Pubkey,
}
impl LegacyVerificationMethod {
pub fn post_migration_size(&self) -> usize {
4 + self.id.len() + 2 + 1 + 4 + 32 }
}
#[derive(Clone, BorshDeserialize)]
pub struct LegacyDidAccount {
pub account_version: u8,
pub authority: Pubkey,
pub version: String,
pub controller: Vec<Pubkey>,
pub verification_method: Vec<LegacyVerificationMethod>,
pub authentication: Vec<String>,
pub capability_invocation: Vec<String>,
pub capability_delegation: Vec<String>,
pub key_agreement: Vec<String>,
pub assertion_method: Vec<String>,
pub service: Vec<LegacyServiceEndpoint>,
}
impl LegacyDidAccount {
pub fn post_migration_size(&self) -> usize {
let mut size = DidAccount::initial_size();
size += self
.verification_method
.iter()
.fold(0, |accum, item| accum + item.post_migration_size()); size += self
.service
.iter()
.fold(0, |accum, item| accum + item.post_migration_size()); size += self.controller.len() * 32; size += 8; size
}
pub fn migrate(&self, into: &mut DidAccount, bump: u8) -> Result<()> {
let default_flags = self.get_flags(&VM_DEFAULT_FRAGMENT_NAME.to_string())
| VerificationMethodFlags::OWNERSHIP_PROOF
| VerificationMethodFlags::PROTECTED;
into.init(bump, &self.authority, default_flags);
let migrated = self.migrate_verification_methods();
into.set_verification_methods(Vec::new(), migrated)?;
let migrated = self.migrate_services();
into.set_services(migrated, false)?;
into.set_native_controllers(self.controller.clone())?;
Ok(())
}
fn migrate_verification_methods(&self) -> Vec<VerificationMethod> {
self.verification_method
.iter()
.map(|vm| VerificationMethod {
fragment: vm.id.clone(),
method_type: VerificationMethodType::Ed25519VerificationKey2018
.to_u8()
.unwrap(),
flags: self.get_flags(&vm.id).bits(),
key_data: vm.pubkey.to_bytes().to_vec(),
})
.collect()
}
fn get_flags(&self, vm_fragment: &String) -> VerificationMethodFlags {
let mut flags = VerificationMethodFlags::NONE;
if self.authentication.contains(vm_fragment) {
flags |= VerificationMethodFlags::AUTHENTICATION;
}
if self.assertion_method.contains(vm_fragment) {
flags |= VerificationMethodFlags::ASSERTION;
}
if self.capability_invocation.contains(vm_fragment) {
flags |= VerificationMethodFlags::CAPABILITY_INVOCATION;
}
if self.capability_delegation.contains(vm_fragment) {
flags |= VerificationMethodFlags::CAPABILITY_DELEGATION;
}
if self.key_agreement.contains(vm_fragment) {
flags |= VerificationMethodFlags::KEY_AGREEMENT;
}
if self.capability_invocation.is_empty() && vm_fragment == VM_DEFAULT_FRAGMENT_NAME {
flags |= VerificationMethodFlags::CAPABILITY_INVOCATION;
}
flags
}
fn migrate_services(&self) -> Vec<Service> {
self.service
.iter()
.map(|se| {
Service {
fragment: se.id.clone(),
service_type: se.endpoint_type.clone(),
service_endpoint: se.endpoint.clone(),
}
})
.collect()
}
}
impl AccountDeserialize for LegacyDidAccount {
fn try_deserialize_unchecked(buf: &mut &[u8]) -> Result<Self> {
AnchorDeserialize::deserialize(buf).map_err(|_| ErrorCode::AccountDidNotDeserialize.into())
}
}
impl AccountSerialize for LegacyDidAccount {}
impl Owner for LegacyDidAccount {
fn owner() -> Pubkey {
Pubkey::from_str("idDa4XeCjVwKcprVAo812coUQbovSZ4kDGJf2sPaBnM").unwrap()
}
}