Skip to main content

drive/util/batch/drive_op_batch/
identity.rs

1use crate::drive::Drive;
2use crate::error::Error;
3use crate::fees::op::LowLevelDriveOperation;
4use crate::util::batch::drive_op_batch::DriveLowLevelOperationConverter;
5use dpp::block::block_info::BlockInfo;
6use dpp::fee::Credits;
7use dpp::identity::{Identity, IdentityPublicKey, KeyID, TimestampMillis};
8use dpp::prelude::{IdentityNonce, Revision};
9
10use crate::drive::identity::update::methods::merge_identity_nonce::MergeIdentityContractNonceResultToResult;
11use crate::drive::votes::resolved::votes::ResolvedVote;
12use crate::state_transition_action::identity::masternode_vote::v0::PreviousVoteCount;
13use dpp::version::PlatformVersion;
14use dpp::voting::vote_choices::resource_vote_choice::ResourceVoteChoice;
15use grovedb::batch::KeyInfoPath;
16use grovedb::{EstimatedLayerInformation, TransactionArg};
17use std::collections::HashMap;
18
19/// Operations on Identities
20#[allow(clippy::large_enum_variant)]
21#[derive(Clone, Debug)]
22pub enum IdentityOperationType {
23    /// Inserts a new identity to the `Identities` subtree.
24    /// A masternode identity is an identity, but can not have unique keys.
25    /// It also will skip testing for unique keys when adding non unique keys, so no one will
26    /// take a key, then add it to a masternode
27    AddNewIdentity {
28        /// The identity we wish to insert
29        identity: Identity,
30        /// Is this identity a masternode identity
31        /// On Masternode identities we do not add lookup key hashes
32        is_masternode_identity: bool,
33    },
34    /// Adds balance to an identity
35    AddToIdentityBalance {
36        /// The identity id of the identity
37        identity_id: [u8; 32],
38        /// The added balance
39        added_balance: u64,
40    },
41    /// Removes balance from an identity
42    RemoveFromIdentityBalance {
43        /// The identity id of the identity
44        identity_id: [u8; 32],
45        /// The balance that will be removed from the identity
46        /// This needs to be verified in advance
47        balance_to_remove: u64,
48    },
49    /// Adds an array of keys to the identity
50    AddNewKeysToIdentity {
51        /// The identity id of the identity
52        identity_id: [u8; 32],
53        /// The unique keys to be added
54        unique_keys_to_add: Vec<IdentityPublicKey>,
55        /// The non unique keys to be added
56        non_unique_keys_to_add: Vec<IdentityPublicKey>,
57    },
58    /// Adds an array of non unique keys to a masternode identity
59    /// A key whose hash is already a unique key hash is added without a non unique key hash
60    /// reference, matching how keys are stored when a masternode identity is created
61    AddNewKeysToMasternodeIdentity {
62        /// The identity id of the masternode identity
63        identity_id: [u8; 32],
64        /// The non unique keys to be added
65        non_unique_keys_to_add: Vec<IdentityPublicKey>,
66    },
67    /// Disable Identity Keys
68    DisableIdentityKeys {
69        /// The identity id of the identity
70        identity_id: [u8; 32],
71        /// The keys to be added
72        keys_ids: Vec<KeyID>,
73    },
74
75    /// Raises the limits of one identity key: the key is rewritten with the new total budget
76    /// and expiry, and its remaining budget grows by the amount the total budget grew
77    UpdateIdentityKeyLimits {
78        /// The identity id of the identity
79        identity_id: [u8; 32],
80        /// The key whose limits are raised, as stored before the update
81        key: IdentityPublicKey,
82        /// The new total budget, `None` to leave it as it is
83        total_budget: Option<Credits>,
84        /// The new expiry, `None` to leave it as it is
85        expires_at: Option<TimestampMillis>,
86    },
87
88    /// Re-Enable Identity Keys
89    /// This should only be used internally in Drive (for masternode identities)
90    ReEnableIdentityKeys {
91        /// The identity id of the identity
92        identity_id: [u8; 32],
93        /// The keys to be added
94        keys_ids: Vec<KeyID>,
95    },
96
97    /// Updates an identities revision.
98    UpdateIdentityRevision {
99        /// The revision id
100        identity_id: [u8; 32],
101        /// The revision we are updating to
102        revision: Revision,
103    },
104    /// Casts a votes as a masternode.
105    MasternodeCastVote {
106        /// The pro tx hash of the masternode doing the voting
107        voter_pro_tx_hash: [u8; 32],
108        /// The strength of the vote, masternodes have 1, evonodes have 4,
109        strength: u8,
110        /// Contested Vote type
111        vote: ResolvedVote,
112        /// Remove previous contested resource vote choice
113        previous_resource_vote_choice_to_remove: Option<(ResourceVoteChoice, PreviousVoteCount)>,
114    },
115    /// Updates an identities nonce for a specific contract.
116    UpdateIdentityNonce {
117        /// The revision id
118        identity_id: [u8; 32],
119        /// The nonce we are updating to
120        nonce: IdentityNonce,
121    },
122
123    /// Updates an identities nonce for a specific contract.
124    UpdateIdentityContractNonce {
125        /// The revision id
126        identity_id: [u8; 32],
127        /// The contract id
128        contract_id: [u8; 32],
129        /// The nonce we are updating to
130        nonce: IdentityNonce,
131    },
132}
133
134impl DriveLowLevelOperationConverter for IdentityOperationType {
135    fn into_low_level_drive_operations(
136        self,
137        drive: &Drive,
138        estimated_costs_only_with_layer_info: &mut Option<
139            HashMap<KeyInfoPath, EstimatedLayerInformation>,
140        >,
141        block_info: &BlockInfo,
142        transaction: TransactionArg,
143        platform_version: &PlatformVersion,
144    ) -> Result<Vec<LowLevelDriveOperation>, Error> {
145        match self {
146            IdentityOperationType::AddNewIdentity {
147                identity,
148                is_masternode_identity,
149            } => drive.add_new_identity_operations(
150                identity,
151                is_masternode_identity,
152                block_info,
153                &mut None,
154                estimated_costs_only_with_layer_info,
155                transaction,
156                platform_version,
157            ),
158            IdentityOperationType::AddToIdentityBalance {
159                identity_id,
160                added_balance,
161            } => drive.add_to_identity_balance_operations(
162                identity_id,
163                added_balance,
164                estimated_costs_only_with_layer_info,
165                transaction,
166                platform_version,
167            ),
168            IdentityOperationType::RemoveFromIdentityBalance {
169                identity_id,
170                balance_to_remove,
171            } => drive.remove_from_identity_balance_operations(
172                identity_id,
173                balance_to_remove,
174                estimated_costs_only_with_layer_info,
175                transaction,
176                platform_version,
177            ),
178            IdentityOperationType::AddNewKeysToIdentity {
179                identity_id,
180                unique_keys_to_add,
181                non_unique_keys_to_add,
182            } => drive.add_new_keys_to_identity_operations(
183                identity_id,
184                unique_keys_to_add,
185                non_unique_keys_to_add,
186                true,
187                &block_info.epoch,
188                estimated_costs_only_with_layer_info,
189                transaction,
190                platform_version,
191            ),
192            IdentityOperationType::AddNewKeysToMasternodeIdentity {
193                identity_id,
194                non_unique_keys_to_add,
195            } => drive.add_new_keys_to_masternode_identity_operations(
196                identity_id,
197                non_unique_keys_to_add,
198                &block_info.epoch,
199                estimated_costs_only_with_layer_info,
200                transaction,
201                platform_version,
202            ),
203            IdentityOperationType::DisableIdentityKeys {
204                identity_id,
205                keys_ids,
206            } => drive.disable_identity_keys_operations(
207                identity_id,
208                keys_ids,
209                block_info.time_ms,
210                &block_info.epoch,
211                estimated_costs_only_with_layer_info,
212                transaction,
213                platform_version,
214            ),
215            IdentityOperationType::UpdateIdentityKeyLimits {
216                identity_id,
217                key,
218                total_budget,
219                expires_at,
220            } => drive.update_identity_key_limits_operations(
221                identity_id,
222                key,
223                total_budget,
224                expires_at,
225                &block_info.epoch,
226                estimated_costs_only_with_layer_info,
227                transaction,
228                platform_version,
229            ),
230            IdentityOperationType::ReEnableIdentityKeys {
231                identity_id,
232                keys_ids,
233            } => drive.re_enable_identity_keys_operations(
234                identity_id,
235                keys_ids,
236                &block_info.epoch,
237                estimated_costs_only_with_layer_info,
238                transaction,
239                platform_version,
240            ),
241            IdentityOperationType::UpdateIdentityRevision {
242                identity_id,
243                revision,
244            } => Ok(vec![drive.update_identity_revision_operation(
245                identity_id,
246                revision,
247                estimated_costs_only_with_layer_info,
248                platform_version,
249            )?]),
250            IdentityOperationType::MasternodeCastVote {
251                voter_pro_tx_hash,
252                strength,
253                vote,
254                previous_resource_vote_choice_to_remove,
255            } => {
256                // No need to have estimated_costs_only_with_layer_info and block_info here
257                // This is because voting is a special operation with a fixed cost
258                drive.register_identity_vote_operations(
259                    voter_pro_tx_hash,
260                    strength,
261                    vote,
262                    previous_resource_vote_choice_to_remove,
263                    transaction,
264                    platform_version,
265                )
266            }
267            IdentityOperationType::UpdateIdentityContractNonce {
268                identity_id,
269                contract_id,
270                nonce,
271            } => {
272                let (result, operations) = drive.merge_identity_contract_nonce_operations(
273                    identity_id,
274                    contract_id,
275                    nonce,
276                    block_info,
277                    estimated_costs_only_with_layer_info,
278                    transaction,
279                    platform_version,
280                )?;
281                result.to_result()?;
282                Ok(operations)
283            }
284            IdentityOperationType::UpdateIdentityNonce { identity_id, nonce } => {
285                let (result, operations) = drive.merge_identity_nonce_operations(
286                    identity_id,
287                    nonce,
288                    block_info,
289                    estimated_costs_only_with_layer_info,
290                    transaction,
291                    platform_version,
292                )?;
293                result.to_result()?;
294                Ok(operations)
295            }
296        }
297    }
298}