sol_did/state/
did_account.rs

1use crate::errors::DidSolError;
2use anchor_lang::prelude::*;
3use bitflags::bitflags;
4use itertools::Itertools;
5use num_derive::*;
6use num_traits::*;
7use std::fmt::{Display, Formatter};
8
9use crate::constants::VM_DEFAULT_FRAGMENT_NAME;
10use crate::utils::{
11    check_other_controllers, convert_secp256k1pub_key_to_address, derive_did_account,
12    derive_did_account_with_bump, eth_verify_message,
13};
14
15#[account]
16pub struct DidAccount {
17    /// Version identifier
18    pub version: u8,
19    /// Bump
20    pub bump: u8,
21    /// Nonce, for protecting against replay attacks around secp256k1 signatures.
22    pub nonce: u64,
23    /// The initial authority key, automatically being added to the array of all Verification Methods.
24    pub initial_verification_method: VerificationMethod,
25    /// All verification methods
26    pub verification_methods: Vec<VerificationMethod>,
27    /// Services
28    pub services: Vec<Service>,
29    /// Controller (native) - did:sol:<controller>
30    pub native_controllers: Vec<Pubkey>,
31    /// Controller (others) - all others
32    pub other_controllers: Vec<String>,
33}
34
35impl Display for DidAccount {
36    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
37        let base_58_authority_key = &self.native_controllers.first().unwrap().to_string();
38        write!(f, "did:sol:{}", base_58_authority_key)
39    }
40}
41
42impl Default for DidAccount {
43    fn default() -> Self {
44        DidAccount {
45            version: 0,
46            bump: 0,
47            nonce: 0,
48            initial_verification_method: VerificationMethod {
49                fragment: VM_DEFAULT_FRAGMENT_NAME.to_string(),
50                flags: VerificationMethodFlags::CAPABILITY_INVOCATION.bits(),
51                method_type: 0,
52                key_data: vec![],
53            },
54            verification_methods: vec![],
55            services: vec![],
56            native_controllers: vec![],
57            other_controllers: vec![],
58        }
59    }
60}
61
62impl DidAccount {
63    pub fn new(bump: u8, authority_key: &Pubkey) -> Self {
64        Self {
65            version: 0,
66            bump,
67            nonce: 0,
68            initial_verification_method: VerificationMethod::default(
69                VerificationMethodFlags::CAPABILITY_INVOCATION
70                    | VerificationMethodFlags::OWNERSHIP_PROOF,
71                authority_key.to_bytes().to_vec(),
72            ),
73            verification_methods: vec![],
74            services: vec![],
75            native_controllers: vec![],
76            other_controllers: vec![],
77        }
78    }
79
80    pub fn init(&mut self, bump: u8, authority_key: &Pubkey, flags: VerificationMethodFlags) {
81        self.version = 0;
82        self.bump = bump;
83        self.nonce = 0;
84
85        self.initial_verification_method =
86            VerificationMethod::default(flags, authority_key.to_bytes().to_vec());
87    }
88
89    /// Accessor for all verification methods (including the initial one)
90    /// Enables to pass several filters that are ANDed together.
91    pub fn verification_methods(
92        &self,
93        filter_types: Option<&[VerificationMethodType]>,
94        filter_flags: Option<VerificationMethodFlags>,
95        filter_key: Option<&[u8]>,
96        filter_fragment: Option<&String>,
97    ) -> Vec<&VerificationMethod> {
98        std::iter::once(&self.initial_verification_method)
99            .chain(self.verification_methods.iter())
100            .filter(|vm| match filter_types {
101                Some(filter_types) => {
102                    filter_types.contains(&VerificationMethodType::from_u8(vm.method_type).unwrap())
103                }
104                None => true,
105            })
106            .filter(|vm| match filter_flags {
107                Some(filter_flags) => VerificationMethodFlags::from_bits(vm.flags)
108                    .unwrap()
109                    .contains(filter_flags),
110                None => true,
111            })
112            .filter(|vm| match filter_key {
113                Some(filter_key) => vm.key_data == filter_key,
114                None => true,
115            })
116            .filter(|vm| match filter_fragment {
117                Some(filter_fragment) => vm.fragment == *filter_fragment,
118                None => true,
119            })
120            .collect()
121    }
122
123    /// Accessor for all verification methods (including the initial one)
124    /// Enables to pass several filters that are ANDed together.
125    /// Mutable Version
126    pub fn verification_methods_mut(
127        &mut self,
128        filter_types: Option<&[VerificationMethodType]>,
129        filter_flags: Option<VerificationMethodFlags>,
130        filter_key: Option<&[u8]>,
131        filter_fragment: Option<&String>,
132    ) -> Vec<&mut VerificationMethod> {
133        std::iter::once(&mut self.initial_verification_method)
134            .chain(self.verification_methods.iter_mut())
135            .filter(|vm| match filter_types {
136                Some(filter_types) => {
137                    filter_types.contains(&VerificationMethodType::from_u8(vm.method_type).unwrap())
138                }
139                None => true,
140            })
141            .filter(|vm| match filter_flags {
142                Some(filter_flags) => VerificationMethodFlags::from_bits(vm.flags)
143                    .unwrap()
144                    .contains(filter_flags),
145                None => true,
146            })
147            .filter(|vm| match filter_key {
148                Some(filter_key) => vm.key_data == filter_key,
149                None => true,
150            })
151            .filter(|vm| match filter_fragment {
152                Some(filter_fragment) => vm.fragment == *filter_fragment,
153                None => true,
154            })
155            .collect()
156    }
157
158    pub fn remove_verification_method(&mut self, fragment: &String) -> Result<()> {
159        // default case
160        if fragment == &self.initial_verification_method.fragment {
161            self.initial_verification_method.flags = 0;
162            return Ok(());
163        }
164
165        // general case
166        self.verification_methods
167            .iter()
168            .position(|vm| vm.fragment == *fragment)
169            .map(|index| {
170                self.verification_methods.remove(index);
171            })
172            .ok_or_else(|| error!(DidSolError::VmFragmentNotFound))
173    }
174
175    pub fn find_verification_method(
176        &mut self,
177        fragment: &String,
178    ) -> Option<&mut VerificationMethod> {
179        self.verification_methods_mut(None, None, None, Some(fragment))
180            .into_iter()
181            .next()
182    }
183
184    pub fn has_authority_verification_methods(&self) -> bool {
185        !self
186            .verification_methods(
187                Some(&VerificationMethodType::authority_types()),
188                Some(VerificationMethodFlags::CAPABILITY_INVOCATION),
189                None,
190                None,
191            )
192            .is_empty()
193    }
194
195    pub fn find_authority_constraint(
196        &self,
197        sol_authority: &Pubkey,
198        eth_message: &[u8],
199        eth_raw_signature: Option<&Secp256k1RawSignature>,
200        filter_fragment: Option<&String>,
201    ) -> Option<&VerificationMethod> {
202        // find sol authority
203        let vm = self.find_authority(
204            &sol_authority.to_bytes(),
205            Some(&[VerificationMethodType::Ed25519VerificationKey2018]),
206            filter_fragment,
207        );
208        if vm.is_some() {
209            return vm;
210        }
211
212        if let Some(eth_raw_signature) = eth_raw_signature {
213            // recover key
214            let secp256k1_pubkey = eth_verify_message(
215                eth_message,
216                self.nonce,
217                eth_raw_signature.signature,
218                eth_raw_signature.recovery_id,
219            )
220            .ok()?;
221
222            let vm = self.find_authority(
223                &secp256k1_pubkey.to_bytes(),
224                Some(&[VerificationMethodType::EcdsaSecp256k1VerificationKey2019]),
225                filter_fragment,
226            );
227            if vm.is_some() {
228                return vm;
229            }
230
231            let address = convert_secp256k1pub_key_to_address(&secp256k1_pubkey);
232            let vm = self.find_authority(
233                &address,
234                Some(&[VerificationMethodType::EcdsaSecp256k1RecoveryMethod2020]),
235                filter_fragment,
236            );
237            if vm.is_some() {
238                return vm;
239            }
240        }
241
242        None
243    }
244
245    pub fn find_authority(
246        &self,
247        key: &[u8],
248        filter_types: Option<&[VerificationMethodType]>,
249        filter_fragment: Option<&String>,
250    ) -> Option<&VerificationMethod> {
251        // msg!("Checking if key {:?} is an authority", key,);
252        self.verification_methods(
253            filter_types,
254            Some(VerificationMethodFlags::CAPABILITY_INVOCATION),
255            Some(key),
256            filter_fragment,
257        )
258        .into_iter()
259        .next()
260    }
261
262    pub fn authority_key(&self) -> Pubkey {
263        Pubkey::new(self.initial_verification_method.key_data.as_slice())
264    }
265
266    /// Returns true if `other` is a valid controller of this DID
267    pub fn is_directly_controlled_by(&self, other: &DidAccount) -> bool {
268        let other_key = other.authority_key();
269        self.native_controllers.iter().contains(&other_key)
270    }
271
272    /// returns true if the controller chain is valid.
273    /// The chain must be provided in the following order:
274    /// this -> chain[0] -> ... -> chain[n]
275    /// where '->' represents the relationship "is controlled by".
276    /// NOTE: an empty chain returns `true`.
277    pub fn is_controlled_by(&self, chain: &[DidAccount]) -> bool {
278        match chain {
279            [head, tail @ ..] => match self.is_directly_controlled_by(head) {
280                true => head.is_controlled_by(tail),
281                false => false,
282            },
283            _ => true,
284        }
285    }
286
287    pub fn set_services(&mut self, services: Vec<Service>, allow_duplicates: bool) -> Result<()> {
288        let original_size = services.len();
289        // make sure there are not duplicate services
290        // Note: the first service is the one retained.
291        let unique_services = services
292            .into_iter()
293            .unique_by(|x| x.fragment.clone())
294            .collect_vec();
295
296        require!(
297            allow_duplicates || unique_services.len() == original_size,
298            DidSolError::ServiceFragmentAlreadyInUse
299        );
300
301        self.services = unique_services;
302        Ok(())
303    }
304
305    pub fn set_verification_methods(
306        &mut self,
307        existing: Vec<VerificationMethod>,
308        incoming: Vec<VerificationMethod>,
309    ) -> Result<()> {
310        // check that incoming VMs do NOT set any Ownership flags.
311        incoming.iter().try_for_each(|vm| {
312            match VerificationMethodFlags::from_bits(vm.flags)
313                .ok_or(DidSolError::ConversionError)?
314                .contains(VerificationMethodFlags::OWNERSHIP_PROOF)
315            {
316                true => Err(DidSolError::VmOwnershipOnAdd),
317                false => Ok(()),
318            }
319        })?;
320
321        let methods = [existing, incoming].concat();
322        let original_size = methods.len();
323        let mut unique_methods = methods
324            .into_iter()
325            .unique_by(|x| x.fragment.clone())
326            .collect_vec();
327        require!(
328            unique_methods.len() == original_size,
329            DidSolError::VmFragmentAlreadyInUse
330        );
331
332        // handle initial type if it exists
333        // 1. remove from unique_methods
334        // 2. set self.initial_verification_method.flags
335        if let Some(index) = unique_methods
336            .iter()
337            .position(|vm| vm.fragment == self.initial_verification_method.fragment)
338        {
339            self.initial_verification_method.flags = unique_methods.swap_remove(index).flags;
340        }
341
342        self.verification_methods = unique_methods;
343
344        Ok(())
345    }
346
347    pub fn set_native_controllers(&mut self, native_controllers: Vec<Pubkey>) -> Result<()> {
348        self.native_controllers = native_controllers.into_iter().unique().collect_vec();
349
350        let own_authority = Pubkey::new(&self.initial_verification_method.key_data);
351
352        require!(
353            !self.native_controllers.contains(&own_authority),
354            DidSolError::InvalidNativeControllers,
355        );
356
357        Ok(())
358    }
359
360    pub fn set_other_controllers(&mut self, other_controllers: Vec<String>) -> Result<()> {
361        self.other_controllers = other_controllers.into_iter().unique().collect_vec();
362
363        require!(
364            check_other_controllers(&self.other_controllers),
365            DidSolError::InvalidOtherControllers
366        );
367
368        Ok(())
369    }
370
371    // Support generative and non-generative accounts
372    pub fn try_from(
373        did_account: &AccountInfo,
374        initial_authority: &Pubkey,
375        did_account_seed_bump: Option<u8>,
376    ) -> Result<DidAccount> {
377        if did_account.owner == &System::id() {
378            // Generative account
379            let (derived_did_account, bump) =
380                if let Some(did_account_seed_bump) = did_account_seed_bump {
381                    (
382                        derive_did_account_with_bump(
383                            &initial_authority.to_bytes(),
384                            did_account_seed_bump,
385                        )
386                        .map_err(|_| Error::from(ErrorCode::ConstraintSeeds))?,
387                        did_account_seed_bump,
388                    )
389                } else {
390                    derive_did_account(&initial_authority.to_bytes())
391                };
392
393            // wrong authority for generative account
394            if derived_did_account != *did_account.key {
395                return Err(error!(DidSolError::WrongAuthorityForDid));
396            }
397
398            return Ok(DidAccount::new(bump, initial_authority));
399        }
400        // Non-generative account
401        let did_account: Account<DidAccount> = Account::try_from(did_account)?;
402        Ok(did_account.into_inner())
403    }
404
405    pub fn size(&self) -> usize {
406        1 // version
407            + 1 // bump
408            + 8 // nonce
409            + VerificationMethod::default_size() // initial_authority
410            + 4 + self.verification_methods.iter().fold(0, |accum, item| { accum + item.size() }) // verification_methods
411            + 4 + self.services.iter().fold(0, |accum, item| { accum + item.size() }) // services
412            + 4 + self.native_controllers.len() * 32 // native_controllers
413            + 4 + self.other_controllers.iter().fold(0, |accum, item| { accum + 4 + item.len() })
414        // other_controllers
415    }
416
417    pub fn initial_size() -> usize {
418        1 // version
419            + 1 // bump
420            + 8 // nonce
421            + VerificationMethod::default_size() // initial_authority
422            + 4 // verification_methods
423            + 4 // services
424            + 4 // native_controllers
425            + 4 // other_controllers
426    }
427}
428
429#[derive(
430    AnchorSerialize, AnchorDeserialize, Copy, Clone, FromPrimitive, ToPrimitive, PartialEq, Eq,
431)]
432pub enum VerificationMethodType {
433    /// The main Ed25519Verification Method.
434    /// https://w3c-ccg.github.io/lds-ed25519-2018/
435    Ed25519VerificationKey2018,
436    /// Verification Method for For 20-bytes Ethereum Keys
437    EcdsaSecp256k1RecoveryMethod2020,
438    /// Verification Method for a full 32 bytes Secp256k1 Verification Key
439    EcdsaSecp256k1VerificationKey2019,
440}
441
442impl VerificationMethodType {
443    pub fn authority_types() -> [VerificationMethodType; 3] {
444        [
445            VerificationMethodType::Ed25519VerificationKey2018,
446            VerificationMethodType::EcdsaSecp256k1VerificationKey2019,
447            VerificationMethodType::EcdsaSecp256k1RecoveryMethod2020,
448        ]
449    }
450
451    // pub fn is_authority_type(vm_type: u8) -> bool {
452    //     let vm_type = VerificationMethodType::from_u8(vm_type).unwrap();
453    //     VerificationMethodType::authority_types().contains(&vm_type)
454    // }
455}
456
457impl Default for VerificationMethodType {
458    fn default() -> Self {
459        VerificationMethodType::Ed25519VerificationKey2018
460    }
461}
462
463/// The native authority key for a [`DidAccount`]
464#[derive(AnchorSerialize, AnchorDeserialize, Clone)]
465pub struct VerificationMethod {
466    /// fragment
467    pub fragment: String,
468    /// The permissions this key has
469    pub flags: u16,
470    /// The actual verification method
471    pub method_type: u8,
472    // Type: VerificationMethodType- Anchor does not yet provide mappings for enums
473    /// Dynamically sized key matching the given VerificationType
474    pub key_data: Vec<u8>,
475}
476
477impl VerificationMethod {
478    pub fn size(&self) -> usize {
479        4 + self.fragment.len()
480            + 2 // flags
481            + 1 // method
482            + 4 + self.key_data.len()
483    }
484
485    pub fn default(flags: VerificationMethodFlags, key_data: Vec<u8>) -> VerificationMethod {
486        VerificationMethod {
487            fragment: String::from(VM_DEFAULT_FRAGMENT_NAME),
488            flags: flags.bits(),
489            method_type: VerificationMethodType::default().to_u8().unwrap(),
490            key_data,
491        }
492    }
493
494    pub fn default_size() -> usize {
495        4 + 7 // fragment "default"
496            + 2 // flags
497            + 1 // method
498            + 4 + 32 // ed25519 pubkey
499    }
500}
501
502/// A Service Definition [`DidAccount`]
503#[derive(AnchorSerialize, AnchorDeserialize, Default, Clone)]
504pub struct Service {
505    pub fragment: String,
506    pub service_type: String,
507    pub service_endpoint: String,
508}
509
510impl Service {
511    pub fn size(&self) -> usize {
512        4 + self.fragment.len() + 4 + self.service_type.len() + 4 + self.service_endpoint.len()
513    }
514}
515
516#[derive(AnchorSerialize, AnchorDeserialize)]
517pub struct Secp256k1RawSignature {
518    pub signature: [u8; 64],
519    pub recovery_id: u8,
520}
521
522bitflags! {
523    pub struct VerificationMethodFlags: u16 {
524        const NONE = 0;
525        /// The VM is able to authenticate the subject
526        const AUTHENTICATION = 1 << 0;
527        /// The VM is able to proof assertions on the subject
528        const ASSERTION = 1 << 1;
529        /// The VM can be used for encryption
530        const KEY_AGREEMENT = 1 << 2;
531        /// The VM can be used for issuing capabilities. Required for DID Update
532        const CAPABILITY_INVOCATION = 1 << 3;
533        /// The VM can be used for delegating capabilities.
534        const CAPABILITY_DELEGATION = 1 << 4;
535        /// The VM is hidden from the DID Document (off-chain only)
536        const DID_DOC_HIDDEN = 1 << 5;
537        /// The subject did proof to be in possession of the private key
538        const OWNERSHIP_PROOF = 1 << 6;
539    }
540}