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    /// Disable Identity Keys
59    DisableIdentityKeys {
60        /// The identity id of the identity
61        identity_id: [u8; 32],
62        /// The keys to be added
63        keys_ids: Vec<KeyID>,
64    },
65
66    /// Raises the limits of one identity key: the key is rewritten with the new total budget
67    /// and expiry, and its remaining budget grows by the amount the total budget grew
68    UpdateIdentityKeyLimits {
69        /// The identity id of the identity
70        identity_id: [u8; 32],
71        /// The key whose limits are raised, as stored before the update
72        key: IdentityPublicKey,
73        /// The new total budget, `None` to leave it as it is
74        total_budget: Option<Credits>,
75        /// The new expiry, `None` to leave it as it is
76        expires_at: Option<TimestampMillis>,
77    },
78
79    /// Re-Enable Identity Keys
80    /// This should only be used internally in Drive (for masternode identities)
81    ReEnableIdentityKeys {
82        /// The identity id of the identity
83        identity_id: [u8; 32],
84        /// The keys to be added
85        keys_ids: Vec<KeyID>,
86    },
87
88    /// Updates an identities revision.
89    UpdateIdentityRevision {
90        /// The revision id
91        identity_id: [u8; 32],
92        /// The revision we are updating to
93        revision: Revision,
94    },
95    /// Casts a votes as a masternode.
96    MasternodeCastVote {
97        /// The pro tx hash of the masternode doing the voting
98        voter_pro_tx_hash: [u8; 32],
99        /// The strength of the vote, masternodes have 1, evonodes have 4,
100        strength: u8,
101        /// Contested Vote type
102        vote: ResolvedVote,
103        /// Remove previous contested resource vote choice
104        previous_resource_vote_choice_to_remove: Option<(ResourceVoteChoice, PreviousVoteCount)>,
105    },
106    /// Updates an identities nonce for a specific contract.
107    UpdateIdentityNonce {
108        /// The revision id
109        identity_id: [u8; 32],
110        /// The nonce we are updating to
111        nonce: IdentityNonce,
112    },
113
114    /// Updates an identities nonce for a specific contract.
115    UpdateIdentityContractNonce {
116        /// The revision id
117        identity_id: [u8; 32],
118        /// The contract id
119        contract_id: [u8; 32],
120        /// The nonce we are updating to
121        nonce: IdentityNonce,
122    },
123}
124
125impl DriveLowLevelOperationConverter for IdentityOperationType {
126    fn into_low_level_drive_operations(
127        self,
128        drive: &Drive,
129        estimated_costs_only_with_layer_info: &mut Option<
130            HashMap<KeyInfoPath, EstimatedLayerInformation>,
131        >,
132        block_info: &BlockInfo,
133        transaction: TransactionArg,
134        platform_version: &PlatformVersion,
135    ) -> Result<Vec<LowLevelDriveOperation>, Error> {
136        match self {
137            IdentityOperationType::AddNewIdentity {
138                identity,
139                is_masternode_identity,
140            } => drive.add_new_identity_operations(
141                identity,
142                is_masternode_identity,
143                block_info,
144                &mut None,
145                estimated_costs_only_with_layer_info,
146                transaction,
147                platform_version,
148            ),
149            IdentityOperationType::AddToIdentityBalance {
150                identity_id,
151                added_balance,
152            } => drive.add_to_identity_balance_operations(
153                identity_id,
154                added_balance,
155                estimated_costs_only_with_layer_info,
156                transaction,
157                platform_version,
158            ),
159            IdentityOperationType::RemoveFromIdentityBalance {
160                identity_id,
161                balance_to_remove,
162            } => drive.remove_from_identity_balance_operations(
163                identity_id,
164                balance_to_remove,
165                estimated_costs_only_with_layer_info,
166                transaction,
167                platform_version,
168            ),
169            IdentityOperationType::AddNewKeysToIdentity {
170                identity_id,
171                unique_keys_to_add,
172                non_unique_keys_to_add,
173            } => drive.add_new_keys_to_identity_operations(
174                identity_id,
175                unique_keys_to_add,
176                non_unique_keys_to_add,
177                true,
178                &block_info.epoch,
179                estimated_costs_only_with_layer_info,
180                transaction,
181                platform_version,
182            ),
183            IdentityOperationType::DisableIdentityKeys {
184                identity_id,
185                keys_ids,
186            } => drive.disable_identity_keys_operations(
187                identity_id,
188                keys_ids,
189                block_info.time_ms,
190                &block_info.epoch,
191                estimated_costs_only_with_layer_info,
192                transaction,
193                platform_version,
194            ),
195            IdentityOperationType::UpdateIdentityKeyLimits {
196                identity_id,
197                key,
198                total_budget,
199                expires_at,
200            } => drive.update_identity_key_limits_operations(
201                identity_id,
202                key,
203                total_budget,
204                expires_at,
205                &block_info.epoch,
206                estimated_costs_only_with_layer_info,
207                transaction,
208                platform_version,
209            ),
210            IdentityOperationType::ReEnableIdentityKeys {
211                identity_id,
212                keys_ids,
213            } => drive.re_enable_identity_keys_operations(
214                identity_id,
215                keys_ids,
216                &block_info.epoch,
217                estimated_costs_only_with_layer_info,
218                transaction,
219                platform_version,
220            ),
221            IdentityOperationType::UpdateIdentityRevision {
222                identity_id,
223                revision,
224            } => Ok(vec![drive.update_identity_revision_operation(
225                identity_id,
226                revision,
227                estimated_costs_only_with_layer_info,
228                platform_version,
229            )?]),
230            IdentityOperationType::MasternodeCastVote {
231                voter_pro_tx_hash,
232                strength,
233                vote,
234                previous_resource_vote_choice_to_remove,
235            } => {
236                // No need to have estimated_costs_only_with_layer_info and block_info here
237                // This is because voting is a special operation with a fixed cost
238                drive.register_identity_vote_operations(
239                    voter_pro_tx_hash,
240                    strength,
241                    vote,
242                    previous_resource_vote_choice_to_remove,
243                    transaction,
244                    platform_version,
245                )
246            }
247            IdentityOperationType::UpdateIdentityContractNonce {
248                identity_id,
249                contract_id,
250                nonce,
251            } => {
252                let (result, operations) = drive.merge_identity_contract_nonce_operations(
253                    identity_id,
254                    contract_id,
255                    nonce,
256                    block_info,
257                    estimated_costs_only_with_layer_info,
258                    transaction,
259                    platform_version,
260                )?;
261                result.to_result()?;
262                Ok(operations)
263            }
264            IdentityOperationType::UpdateIdentityNonce { identity_id, nonce } => {
265                let (result, operations) = drive.merge_identity_nonce_operations(
266                    identity_id,
267                    nonce,
268                    block_info,
269                    estimated_costs_only_with_layer_info,
270                    transaction,
271                    platform_version,
272                )?;
273                result.to_result()?;
274                Ok(operations)
275            }
276        }
277    }
278}