1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
// KILT Blockchain – https://botlabs.org
// Copyright (C) 2019-2024 BOTLabs GmbH

// The KILT Blockchain is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.

// The KILT Blockchain is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <https://www.gnu.org/licenses/>.

// If you feel like getting in touch with us, you can do so at info@botlabs.org

use scale_info::TypeInfo;
use sp_runtime::DispatchError;

use crate::did_details::DidVerificationKeyRelationship;

/// All the errors that can be generated when validating a DID operation.
#[derive(Debug, Eq, PartialEq, TypeInfo)]
pub enum DidError {
	/// See [`StorageError`].
	Storage(StorageError),
	/// See [`SignatureError`].
	Signature(SignatureError),
	/// See [`InputError`].
	Input(InputError),
	/// An error that is not supposed to take place, yet it happened.
	Internal,
	/// An error that is related to updating the deposit.
	Deposit(DispatchError),
}

impl From<DispatchError> for DidError {
	fn from(err: DispatchError) -> Self {
		DidError::Deposit(err)
	}
}

impl From<StorageError> for DidError {
	fn from(err: StorageError) -> Self {
		DidError::Storage(err)
	}
}

impl From<InputError> for DidError {
	fn from(err: InputError) -> Self {
		DidError::Input(err)
	}
}

/// Error involving the pallet's storage.
#[derive(Debug, Eq, PartialEq, TypeInfo)]
pub enum StorageError {
	/// The DID being created is already present on chain.
	AlreadyExists,
	/// The expected DID cannot be found on chain.
	NotFound(NotFoundKind),
	/// The maximum number of public keys for this DID key identifier has
	/// been reached.
	MaxPublicKeysExceeded,
	/// The maximum number of key agreements has been reached for the DID
	/// subject.
	MaxTotalKeyAgreementKeysExceeded,
	/// The DID has already been previously deleted.
	AlreadyDeleted,
}

/// Error involving the pallet's storage.
#[derive(Debug, Eq, PartialEq, TypeInfo)]
pub enum NotFoundKind {
	/// The expected DID cannot be found on chain.
	Did,
	/// At least one key referenced is not stored under the given DID.
	Key(KeyType),
}

/// Enum describing the different did key types.
#[derive(Debug, Eq, PartialEq, TypeInfo)]
pub enum KeyType {
	/// Authentication key type.
	/// This key is used to authenticate the DID subject.
	Authentication,
	/// Key agreement key type.
	/// This key is used to encrypt messages to the DID subject.
	/// It can be used to derive shared secrets.
	KeyAgreement,
	/// Assertion method key type.
	/// This key is used to assert statements on behalf of the DID subject.
	/// It is generally used to attest things.
	AssertionMethod,
	/// Delegation key type.
	/// This key is used to delegate the DID subject's capabilities.
	Delegation,
}

impl From<DidVerificationKeyRelationship> for KeyType {
	fn from(key_type: DidVerificationKeyRelationship) -> Self {
		match key_type {
			DidVerificationKeyRelationship::Authentication => KeyType::Authentication,
			DidVerificationKeyRelationship::AssertionMethod => KeyType::AssertionMethod,
			DidVerificationKeyRelationship::CapabilityDelegation
			| DidVerificationKeyRelationship::CapabilityInvocation => KeyType::Delegation,
		}
	}
}

/// Error generated when validating a DID operation.
#[derive(Debug, Eq, PartialEq, TypeInfo)]
pub enum SignatureError {
	/// The signature is not in the format the verification key expects.
	InvalidFormat,
	/// The signature is invalid for the payload and the verification key
	/// provided.
	InvalidData,
	/// The operation nonce is not equal to the current DID nonce + 1.
	InvalidNonce,
	/// The provided operation block number is not valid.
	TransactionExpired,
}

/// Error generated when some extrinsic input does not respect the pallet's
/// constraints.
#[derive(Debug, Eq, PartialEq, TypeInfo)]
pub enum InputError {
	/// A number of new key agreement keys greater than the maximum allowed has
	/// been provided.
	MaxKeyAgreementKeysLimitExceeded,
	/// The maximum number of service endpoints for a DID has been exceeded.
	MaxServicesCountExceeded,
	/// The maximum number of URLs for a service endpoint has been exceeded.
	MaxUrlCountExceeded,
	/// The maximum number of types for a service endpoint has been exceeded.
	MaxTypeCountExceeded,
	/// The service endpoint ID exceeded the maximum allowed length.
	MaxIdLengthExceeded,
	/// One of the service endpoint URLs exceeded the maximum allowed length.
	MaxUrlLengthExceeded,
	/// One of the service endpoint types exceeded the maximum allowed length.
	MaxTypeLengthExceeded,
	/// One of the service endpoint details contains non-ASCII characters.
	InvalidEncoding,
}