drive/util/batch/drive_op_batch/contract_moderation.rs
1use crate::drive::contract::moderation::types::ContractTeamActionWrite;
2use crate::drive::Drive;
3use crate::error::Error;
4use crate::fees::op::LowLevelDriveOperation;
5use crate::util::batch::drive_op_batch::DriveLowLevelOperationConverter;
6use dpp::block::block_info::BlockInfo;
7use dpp::data_contract::config::moderation::{
8 ContractDocumentRemoval, ContractModerationReason, ContractWarning,
9};
10use dpp::identifier::Identifier;
11use dpp::identity::TimestampMillis;
12use grovedb::batch::KeyInfoPath;
13use grovedb::{EstimatedLayerInformation, TransactionArg};
14use platform_version::version::PlatformVersion;
15use std::collections::HashMap;
16
17/// Operations on a moderated contract's banlist, suspension list, warning list, document
18/// removal records and, for an elected contract, its team's moderation action counts and the
19/// actions it votes on.
20#[derive(Clone, Debug)]
21pub enum ContractModerationOperationType {
22 /// Puts an identity on the banlist.
23 AddBan {
24 /// The moderated contract.
25 contract_id: Identifier,
26 /// The identity to ban.
27 identity_id: Identifier,
28 /// Why, stored with the entry.
29 reason: ContractModerationReason,
30 /// The identity that pays for the entry and receives its refund.
31 moderator_id: Identifier,
32 },
33 /// Takes an identity off the banlist.
34 RemoveBan {
35 /// The moderated contract.
36 contract_id: Identifier,
37 /// The identity to unban.
38 identity_id: Identifier,
39 },
40 /// Puts an identity on the suspension list until a block time, replacing an entry it
41 /// already has.
42 AddSuspension {
43 /// The moderated contract.
44 contract_id: Identifier,
45 /// The identity to suspend.
46 identity_id: Identifier,
47 /// The block time, in milliseconds, at which the suspension lapses.
48 until: TimestampMillis,
49 /// Why, stored with the entry.
50 reason: ContractModerationReason,
51 /// Whether the identity already has an entry, which is then replaced.
52 replaces_existing: bool,
53 /// The identity that pays for the entry and receives its refund.
54 moderator_id: Identifier,
55 },
56 /// Takes an identity off the suspension list, lapsed or not.
57 RemoveSuspension {
58 /// The moderated contract.
59 contract_id: Identifier,
60 /// The identity to unsuspend.
61 identity_id: Identifier,
62 },
63 /// Writes an identity's warning list entry with one warning more, replacing the entry it
64 /// already has.
65 AddWarning {
66 /// The moderated contract.
67 contract_id: Identifier,
68 /// The identity to warn.
69 identity_id: Identifier,
70 /// The identity's warnings after this one, oldest first: what the entry holds.
71 warnings: Vec<ContractWarning>,
72 /// Whether the identity already has an entry, which is then replaced.
73 replaces_existing: bool,
74 /// The identity that pays for the entry and receives its refund.
75 moderator_id: Identifier,
76 },
77 /// Takes an identity off the warning list: every warning it carries goes.
78 RemoveWarnings {
79 /// The moderated contract.
80 contract_id: Identifier,
81 /// The identity whose warnings are cleared.
82 identity_id: Identifier,
83 },
84 /// Writes the record of a moderator's deletion of a document: a fresh one, or the
85 /// replacement of the record the document already has. A record is replaced when a
86 /// moderator restores the document (the record then carries the restoration, the
87 /// deletion itself undone by a document operation of the same batch) and when a restored
88 /// document is deleted again (a fresh record, in place of the restored one). A document id
89 /// is produced at most once, so those are the only ways a record can exist already.
90 AddDocumentRemoval {
91 /// The moderated contract.
92 contract_id: Identifier,
93 /// The document type the document belonged to.
94 document_type_name: String,
95 /// The id the document had.
96 document_id: Identifier,
97 /// Whose it was, who removed it, why and when, what it was, and whether it was
98 /// restored since. Boxed: with the fields it keeps, it outweighs every other
99 /// operation of the kind.
100 removal: Box<ContractDocumentRemoval>,
101 /// The stored size of the record the document already has, which is then replaced;
102 /// `None` for a fresh record. An estimate prices a replacement by what it adds.
103 replaced_record_size: Option<u32>,
104 /// What the type's records are estimated to keep
105 /// (`types::estimated_document_removal_kept_fields_size`): the size the records a
106 /// write walks past are estimated at.
107 estimated_kept_fields_size: u32,
108 /// The identity that pays for the record, or for the bytes a replacement adds, and
109 /// receives its refund: the moderator that removed the document, or the one that
110 /// restored it.
111 moderator_id: Identifier,
112 },
113 /// Writes a seated moderation team member's proposal or approval of one of the contract's
114 /// team actions, closing the action when it meets its rule: see
115 /// `Drive::add_contract_team_action_signature_operations`.
116 AddTeamActionSignature {
117 /// The contract whose seated team votes on the action.
118 contract_id: Identifier,
119 /// The action.
120 action_id: Identifier,
121 /// The member that proposes or approves, who pays for what it adds.
122 signer_id: Identifier,
123 /// What the signature writes: a proposal, an approval, or the closing approval.
124 write: ContractTeamActionWrite,
125 },
126 /// Writes nothing: marks the batch it is in as one whose document operations' storage
127 /// removals refund nobody (`Drive::apply_drive_operations` generation 1, which applies them
128 /// as a GroveDB batch of their own when the batch also frees moderation storage someone is
129 /// owed). A
130 /// moderator's document deletion carries it, so whoever paid for the deleted document, its
131 /// owner or an earlier one, gets no storage refund, and nor does whoever created an index
132 /// subtree the deletion empties, unless the document's type refunds the owner
133 /// (`moderatorAbilities.deleteRefundsOwner`); the removal record the deletion replaces and
134 /// the team action approvals it moves refund as ever.
135 ForfeitStorageRefunds,
136 /// Writes a seated moderation team member's count of moderation actions on an elected
137 /// contract since the moderators pot was last settled.
138 SetActionCount {
139 /// The elected contract.
140 contract_id: Identifier,
141 /// The member that signed the action.
142 identity_id: Identifier,
143 /// The count to store, the action included.
144 count: u32,
145 },
146 /// Deletes moderation action counts of an elected contract: the reset of a settle of its
147 /// moderators pot. Each count must exist.
148 RemoveActionCounts {
149 /// The elected contract.
150 contract_id: Identifier,
151 /// The members whose counts go.
152 identity_ids: Vec<Identifier>,
153 },
154}
155
156impl DriveLowLevelOperationConverter for ContractModerationOperationType {
157 fn into_low_level_drive_operations(
158 self,
159 drive: &Drive,
160 estimated_costs_only_with_layer_info: &mut Option<
161 HashMap<KeyInfoPath, EstimatedLayerInformation>,
162 >,
163 block_info: &BlockInfo,
164 transaction: TransactionArg,
165 platform_version: &PlatformVersion,
166 ) -> Result<Vec<LowLevelDriveOperation>, Error> {
167 match self {
168 ContractModerationOperationType::AddBan {
169 contract_id,
170 identity_id,
171 reason,
172 moderator_id,
173 } => drive.add_contract_ban_operations(
174 contract_id,
175 identity_id,
176 &reason,
177 moderator_id,
178 block_info,
179 estimated_costs_only_with_layer_info,
180 transaction,
181 platform_version,
182 ),
183 ContractModerationOperationType::RemoveBan {
184 contract_id,
185 identity_id,
186 } => drive.remove_contract_ban_operations(
187 contract_id,
188 identity_id,
189 block_info,
190 estimated_costs_only_with_layer_info,
191 transaction,
192 platform_version,
193 ),
194 ContractModerationOperationType::AddSuspension {
195 contract_id,
196 identity_id,
197 until,
198 reason,
199 replaces_existing,
200 moderator_id,
201 } => drive.add_contract_suspension_operations(
202 contract_id,
203 identity_id,
204 until,
205 &reason,
206 replaces_existing,
207 moderator_id,
208 block_info,
209 estimated_costs_only_with_layer_info,
210 transaction,
211 platform_version,
212 ),
213 ContractModerationOperationType::RemoveSuspension {
214 contract_id,
215 identity_id,
216 } => drive.remove_contract_suspension_operations(
217 contract_id,
218 identity_id,
219 block_info,
220 estimated_costs_only_with_layer_info,
221 transaction,
222 platform_version,
223 ),
224 ContractModerationOperationType::AddWarning {
225 contract_id,
226 identity_id,
227 warnings,
228 replaces_existing,
229 moderator_id,
230 } => drive.add_contract_warning_operations(
231 contract_id,
232 identity_id,
233 &warnings,
234 replaces_existing,
235 moderator_id,
236 block_info,
237 estimated_costs_only_with_layer_info,
238 transaction,
239 platform_version,
240 ),
241 ContractModerationOperationType::RemoveWarnings {
242 contract_id,
243 identity_id,
244 } => drive.remove_contract_warnings_operations(
245 contract_id,
246 identity_id,
247 block_info,
248 estimated_costs_only_with_layer_info,
249 transaction,
250 platform_version,
251 ),
252 ContractModerationOperationType::AddDocumentRemoval {
253 contract_id,
254 document_type_name,
255 document_id,
256 removal,
257 replaced_record_size,
258 estimated_kept_fields_size,
259 moderator_id,
260 } => drive.add_contract_document_removal_operations(
261 contract_id,
262 &document_type_name,
263 document_id,
264 &removal,
265 replaced_record_size,
266 estimated_kept_fields_size,
267 moderator_id,
268 block_info,
269 estimated_costs_only_with_layer_info,
270 transaction,
271 platform_version,
272 ),
273 ContractModerationOperationType::AddTeamActionSignature {
274 contract_id,
275 action_id,
276 signer_id,
277 write,
278 } => drive.add_contract_team_action_signature_operations(
279 contract_id,
280 action_id,
281 signer_id,
282 &write,
283 block_info,
284 estimated_costs_only_with_layer_info,
285 transaction,
286 platform_version,
287 ),
288 ContractModerationOperationType::ForfeitStorageRefunds => Ok(vec![]),
289 ContractModerationOperationType::SetActionCount {
290 contract_id,
291 identity_id,
292 count,
293 } => drive.set_contract_moderation_action_count_operations(
294 contract_id,
295 identity_id,
296 count,
297 estimated_costs_only_with_layer_info,
298 platform_version,
299 ),
300 ContractModerationOperationType::RemoveActionCounts {
301 contract_id,
302 identity_ids,
303 } => drive.remove_contract_moderation_action_counts_operations(
304 contract_id,
305 &identity_ids,
306 estimated_costs_only_with_layer_info,
307 transaction,
308 platform_version,
309 ),
310 }
311 }
312}