Skip to main content

dpp/errors/consensus/state/
state_error.rs

1use crate::errors::ProtocolError;
2use bincode::{Decode, DecodeUntrusted, Encode};
3use platform_serialization_derive::{
4    PlatformDeserializeTrusted, PlatformDeserializeUntrusted, PlatformSerialize,
5};
6use thiserror::Error;
7
8use crate::consensus::state::address_funds::{AddressDoesNotExistError, AddressInvalidNonceError, AddressNotEnoughFundsError, AddressesNotEnoughFundsError};
9use crate::consensus::state::shielded::insufficient_pool_notes_error::InsufficientPoolNotesError;
10use crate::consensus::state::shielded::insufficient_shielded_fee_error::InsufficientShieldedFeeError;
11use crate::consensus::state::shielded::invalid_anchor_error::InvalidAnchorError;
12use crate::consensus::state::shielded::invalid_shielded_proof_error::InvalidShieldedProofError;
13use crate::consensus::state::shielded::nullifier_already_spent_error::NullifierAlreadySpentError;
14use crate::consensus::state::contract_group::{
15    ContractGroupAlreadyExistsError, ContractGroupNotFoundError,
16    ContractGroupAdminNotFoundError, IdentityNotContractGroupOwnerOrAdminError,
17};
18use crate::consensus::state::data_contract::data_contract_already_present_error::DataContractAlreadyPresentError;
19use crate::consensus::state::data_contract::data_contract_config_update_error::DataContractConfigUpdateError;
20use crate::consensus::state::data_contract::data_contract_is_readonly_error::DataContractIsReadonlyError;
21use crate::consensus::state::data_trigger::DataTriggerError;
22use crate::consensus::state::document::document_already_present_error::DocumentAlreadyPresentError;
23use crate::consensus::state::document::document_not_found_error::DocumentNotFoundError;
24use crate::consensus::state::document::document_owner_id_mismatch_error::DocumentOwnerIdMismatchError;
25use crate::consensus::state::document::document_timestamp_window_violation_error::DocumentTimestampWindowViolationError;
26use crate::consensus::state::document::document_timestamps_mismatch_error::DocumentTimestampsMismatchError;
27use crate::consensus::state::document::duplicate_unique_index_error::DuplicateUniqueIndexError;
28use crate::consensus::state::document::invalid_document_revision_error::InvalidDocumentRevisionError;
29use crate::consensus::state::identity::duplicated_identity_public_key_id_state_error::DuplicatedIdentityPublicKeyIdStateError;
30use crate::consensus::state::identity::duplicated_identity_public_key_state_error::DuplicatedIdentityPublicKeyStateError;
31use crate::consensus::state::identity::identity_public_key_is_disabled_error::IdentityPublicKeyIsDisabledError;
32use crate::consensus::state::identity::identity_public_key_is_read_only_error::IdentityPublicKeyIsReadOnlyError;
33use crate::consensus::state::identity::invalid_identity_public_key_id_error::InvalidIdentityPublicKeyIdError;
34use crate::consensus::state::identity::invalid_identity_revision_error::InvalidIdentityRevisionError;
35use crate::consensus::state::identity::max_identity_public_key_limit_reached_error::MaxIdentityPublicKeyLimitReachedError;
36use crate::consensus::state::identity::missing_identity_public_key_ids_error::MissingIdentityPublicKeyIdsError;
37use crate::consensus::state::identity::{IdentityAlreadyExistsError, IdentityInsufficientBalanceError, RecipientIdentityDoesNotExistError};
38use crate::consensus::ConsensusError;
39use crate::consensus::state::data_contract::data_contract_not_found_error::DataContractNotFoundError;
40use crate::consensus::state::data_contract::data_contract_update_action_not_allowed_error::DataContractUpdateActionNotAllowedError;
41use crate::consensus::state::data_contract::data_contract_update_permission_error::DataContractUpdatePermissionError;
42use crate::consensus::state::data_contract::document_type_update_error::DocumentTypeUpdateError;
43use crate::consensus::state::document::document_contest_currently_locked_error::DocumentContestCurrentlyLockedError;
44use crate::consensus::state::document::document_contest_document_with_same_id_already_present_error::DocumentContestDocumentWithSameIdAlreadyPresentError;
45use crate::consensus::state::document::document_contest_identity_already_contestant::DocumentContestIdentityAlreadyContestantError;
46use crate::consensus::state::document::document_contest_index_mismatch_error::DocumentContestIndexMismatchError;
47use crate::consensus::state::document::document_contest_not_joinable_error::DocumentContestNotJoinableError;
48use crate::consensus::state::document::document_contest_not_paid_for_error::DocumentContestNotPaidForError;
49use crate::consensus::state::document::document_contest_not_required_error::DocumentContestNotRequiredError;
50use crate::consensus::state::document::referenced_document_type_deletable_error::ReferencedDocumentTypeDeletableError;
51use crate::consensus::state::document::referenced_document_type_not_found_error::ReferencedDocumentTypeNotFoundError;
52use crate::consensus::state::document::referenced_entity_not_found_error::ReferencedEntityNotFoundError;
53use crate::consensus::state::document::referenced_identity_key_disabled_error::ReferencedIdentityKeyDisabledError;
54use crate::consensus::state::document::referenced_identity_key_not_found_error::ReferencedIdentityKeyNotFoundError;
55use crate::consensus::state::document::referenced_document_property_agreement_invalid_error::ReferencedDocumentPropertyAgreementInvalidError;
56use crate::consensus::state::document::referenced_document_property_mismatch_error::ReferencedDocumentPropertyMismatchError;
57use crate::consensus::state::document::referenced_key_id_property_invalid_error::ReferencedKeyIdPropertyInvalidError;
58use crate::consensus::state::document::document_incorrect_purchase_price_error::DocumentIncorrectPurchasePriceError;
59use crate::consensus::state::document::document_not_for_sale_error::DocumentNotForSaleError;
60use crate::consensus::state::group::{GroupActionAlreadyCompletedError, GroupActionAlreadySignedByIdentityError, GroupActionDoesNotExistError, IdentityMemberOfGroupNotFoundError, IdentityNotMemberOfGroupError, ModificationOfGroupActionMainParametersNotPermittedError};
61use crate::consensus::state::identity::identity_for_token_configuration_not_found_error::IdentityInTokenConfigurationNotFoundError;
62use crate::consensus::state::identity::identity_public_key_already_exists_for_unique_contract_bounds_error::IdentityPublicKeyAlreadyExistsForUniqueContractBoundsError;
63use crate::consensus::state::identity::identity_public_key_already_expired_error::IdentityPublicKeyAlreadyExpiredError;
64use crate::consensus::state::identity::identity_public_key_budget_exceeded_error::IdentityPublicKeyBudgetExceededError;
65use crate::consensus::state::identity::identity_public_key_limit_not_raised_error::IdentityPublicKeyLimitNotRaisedError;
66use crate::consensus::state::identity::identity_public_key_limit_not_set_error::IdentityPublicKeyLimitNotSetError;
67use crate::consensus::state::identity::identity_to_freeze_does_not_exist_error::IdentityToFreezeDoesNotExistError;
68use crate::consensus::state::identity::invalid_identity_contract_nonce_error::InvalidIdentityNonceError;
69use crate::consensus::state::identity::missing_transfer_key_error::MissingTransferKeyError;
70use crate::consensus::state::identity::no_transfer_key_for_core_withdrawal_available_error::NoTransferKeyForCoreWithdrawalAvailableError;
71use crate::consensus::state::prefunded_specialized_balances::prefunded_specialized_balance_insufficient_error::PrefundedSpecializedBalanceInsufficientError;
72use crate::consensus::state::prefunded_specialized_balances::prefunded_specialized_balance_not_found_error::PrefundedSpecializedBalanceNotFoundError;
73use crate::consensus::state::token::{IdentityDoesNotHaveEnoughTokenBalanceError, IdentityTokenAccountFrozenError, IdentityTokenAccountNotFrozenError, InvalidGroupPositionError, NewAuthorizedActionTakerGroupDoesNotExistError, NewAuthorizedActionTakerIdentityDoesNotExistError, NewAuthorizedActionTakerMainGroupNotSetError, NewTokensDestinationIdentityDoesNotExistError, TokenMintPastMaxSupplyError, TokenSettingMaxSupplyToLessThanCurrentSupplyError, UnauthorizedTokenActionError, IdentityTokenAccountAlreadyFrozenError, TokenAlreadyPausedError, TokenIsPausedError, TokenNotPausedError, InvalidTokenClaimPropertyMismatch, InvalidTokenClaimNoCurrentRewards, InvalidTokenClaimWrongClaimant, PreProgrammedDistributionTimestampInPastError, TokenTransferRecipientIdentityNotExistError, IdentityHasNotAgreedToPayRequiredTokenAmountError, RequiredTokenPaymentInfoNotSetError, IdentityTryingToPayWithWrongTokenError, TokenDirectPurchaseUserPriceTooLow, TokenAmountUnderMinimumSaleAmount, TokenNotForDirectSale, InvalidTokenPositionStateError};
74use crate::consensus::state::voting::masternode_incorrect_voter_identity_id_error::MasternodeIncorrectVoterIdentityIdError;
75use crate::consensus::state::voting::masternode_incorrect_voting_address_error::MasternodeIncorrectVotingAddressError;
76use crate::consensus::state::voting::masternode_not_found_error::MasternodeNotFoundError;
77use crate::consensus::state::voting::masternode_vote_already_present_error::MasternodeVoteAlreadyPresentError;
78use crate::consensus::state::voting::masternode_voted_too_many_times::MasternodeVotedTooManyTimesError;
79use crate::consensus::state::voting::vote_poll_not_available_for_voting_error::VotePollNotAvailableForVotingError;
80use crate::consensus::state::voting::vote_poll_not_found_error::VotePollNotFoundError;
81
82use super::document::document_timestamps_are_equal_error::DocumentTimestampsAreEqualError;
83
84#[derive(
85    Error,
86    Debug,
87    PartialEq,
88    Encode,
89    Decode,
90    PlatformSerialize,
91    PlatformDeserializeTrusted,
92    PlatformDeserializeUntrusted,
93    Clone,
94    DecodeUntrusted,
95)]
96pub enum StateError {
97    /*
98
99    DO NOT CHANGE ORDER OF VARIANTS WITHOUT INTRODUCING OF NEW VERSION
100
101    */
102    #[error(transparent)]
103    DataContractAlreadyPresentError(DataContractAlreadyPresentError),
104
105    #[error(transparent)]
106    DataTriggerError(DataTriggerError),
107
108    #[error(transparent)]
109    DocumentAlreadyPresentError(DocumentAlreadyPresentError),
110
111    #[error(transparent)]
112    DocumentContestCurrentlyLockedError(DocumentContestCurrentlyLockedError),
113
114    #[error(transparent)]
115    DocumentContestNotJoinableError(DocumentContestNotJoinableError),
116
117    #[error(transparent)]
118    DocumentContestIdentityAlreadyContestantError(DocumentContestIdentityAlreadyContestantError),
119
120    #[error(transparent)]
121    DocumentContestNotPaidForError(DocumentContestNotPaidForError),
122
123    #[error(transparent)]
124    DocumentContestDocumentWithSameIdAlreadyPresentError(
125        DocumentContestDocumentWithSameIdAlreadyPresentError,
126    ),
127
128    #[error(transparent)]
129    DocumentNotFoundError(DocumentNotFoundError),
130
131    #[error(transparent)]
132    DocumentNotForSaleError(DocumentNotForSaleError),
133
134    #[error(transparent)]
135    DocumentIncorrectPurchasePriceError(DocumentIncorrectPurchasePriceError),
136
137    #[error(transparent)]
138    DocumentOwnerIdMismatchError(DocumentOwnerIdMismatchError),
139
140    #[error(transparent)]
141    DocumentTimestampsMismatchError(DocumentTimestampsMismatchError),
142
143    #[error(transparent)]
144    DocumentTimestampWindowViolationError(DocumentTimestampWindowViolationError),
145
146    #[error(transparent)]
147    DuplicateUniqueIndexError(DuplicateUniqueIndexError),
148
149    #[error(transparent)]
150    InvalidDocumentRevisionError(InvalidDocumentRevisionError),
151
152    #[error(transparent)]
153    IdentityAlreadyExistsError(IdentityAlreadyExistsError),
154
155    #[error(transparent)]
156    IdentityPublicKeyAlreadyExistsForUniqueContractBoundsError(
157        IdentityPublicKeyAlreadyExistsForUniqueContractBoundsError,
158    ),
159
160    #[error(transparent)]
161    IdentityPublicKeyIsReadOnlyError(IdentityPublicKeyIsReadOnlyError),
162
163    #[error(transparent)]
164    MissingIdentityPublicKeyIdsError(MissingIdentityPublicKeyIdsError),
165
166    #[error(transparent)]
167    MissingTransferKeyError(MissingTransferKeyError),
168
169    #[error(transparent)]
170    NoTransferKeyForCoreWithdrawalAvailableError(NoTransferKeyForCoreWithdrawalAvailableError),
171
172    #[error(transparent)]
173    InvalidIdentityPublicKeyIdError(InvalidIdentityPublicKeyIdError),
174
175    #[error(transparent)]
176    InvalidIdentityRevisionError(InvalidIdentityRevisionError),
177
178    #[error(transparent)]
179    InvalidIdentityNonceError(InvalidIdentityNonceError),
180
181    #[error(transparent)]
182    MaxIdentityPublicKeyLimitReachedError(MaxIdentityPublicKeyLimitReachedError),
183
184    #[error(transparent)]
185    DuplicatedIdentityPublicKeyStateError(DuplicatedIdentityPublicKeyStateError),
186
187    #[error(transparent)]
188    DuplicatedIdentityPublicKeyIdStateError(DuplicatedIdentityPublicKeyIdStateError),
189
190    #[error(transparent)]
191    IdentityPublicKeyIsDisabledError(IdentityPublicKeyIsDisabledError),
192
193    #[error(transparent)]
194    IdentityInsufficientBalanceError(IdentityInsufficientBalanceError),
195
196    #[error(transparent)]
197    DocumentTimestampsAreEqualError(DocumentTimestampsAreEqualError),
198
199    #[error(transparent)]
200    DataContractIsReadonlyError(DataContractIsReadonlyError),
201
202    #[error(transparent)]
203    DataContractConfigUpdateError(DataContractConfigUpdateError),
204
205    #[error(transparent)]
206    DocumentTypeUpdateError(DocumentTypeUpdateError),
207
208    #[error(transparent)]
209    PrefundedSpecializedBalanceInsufficientError(PrefundedSpecializedBalanceInsufficientError),
210
211    #[error(transparent)]
212    PrefundedSpecializedBalanceNotFoundError(PrefundedSpecializedBalanceNotFoundError),
213
214    #[error(transparent)]
215    DataContractUpdatePermissionError(DataContractUpdatePermissionError),
216
217    #[error(transparent)]
218    MasternodeNotFoundError(MasternodeNotFoundError),
219
220    #[error(transparent)]
221    MasternodeIncorrectVoterIdentityIdError(MasternodeIncorrectVoterIdentityIdError),
222
223    #[error(transparent)]
224    MasternodeIncorrectVotingAddressError(MasternodeIncorrectVotingAddressError),
225
226    #[error(transparent)]
227    VotePollNotFoundError(VotePollNotFoundError),
228
229    #[error(transparent)]
230    VotePollNotAvailableForVotingError(VotePollNotAvailableForVotingError),
231
232    #[error(transparent)]
233    MasternodeVotedTooManyTimesError(MasternodeVotedTooManyTimesError),
234
235    #[error(transparent)]
236    MasternodeVoteAlreadyPresentError(MasternodeVoteAlreadyPresentError),
237
238    #[error(transparent)]
239    RecipientIdentityDoesNotExistError(RecipientIdentityDoesNotExistError),
240
241    #[error(transparent)]
242    IdentityDoesNotHaveEnoughTokenBalanceError(IdentityDoesNotHaveEnoughTokenBalanceError),
243
244    #[error(transparent)]
245    UnauthorizedTokenActionError(UnauthorizedTokenActionError),
246
247    #[error(transparent)]
248    IdentityTokenAccountFrozenError(IdentityTokenAccountFrozenError),
249
250    #[error(transparent)]
251    IdentityTokenAccountNotFrozenError(IdentityTokenAccountNotFrozenError),
252
253    #[error(transparent)]
254    IdentityNotMemberOfGroupError(IdentityNotMemberOfGroupError),
255
256    #[error(transparent)]
257    GroupActionDoesNotExistError(GroupActionDoesNotExistError),
258
259    #[error(transparent)]
260    GroupActionAlreadyCompletedError(GroupActionAlreadyCompletedError),
261
262    #[error(transparent)]
263    GroupActionAlreadySignedByIdentityError(GroupActionAlreadySignedByIdentityError),
264
265    #[error(transparent)]
266    DataContractUpdateActionNotAllowedError(DataContractUpdateActionNotAllowedError),
267
268    #[error(transparent)]
269    TokenSettingMaxSupplyToLessThanCurrentSupplyError(
270        TokenSettingMaxSupplyToLessThanCurrentSupplyError,
271    ),
272
273    #[error(transparent)]
274    TokenMintPastMaxSupplyError(TokenMintPastMaxSupplyError),
275
276    #[error(transparent)]
277    InvalidTokenClaimPropertyMismatch(InvalidTokenClaimPropertyMismatch),
278
279    #[error(transparent)]
280    InvalidTokenClaimNoCurrentRewards(InvalidTokenClaimNoCurrentRewards),
281
282    #[error(transparent)]
283    InvalidTokenClaimWrongClaimant(InvalidTokenClaimWrongClaimant),
284
285    #[error(transparent)]
286    NewTokensDestinationIdentityDoesNotExistError(NewTokensDestinationIdentityDoesNotExistError),
287
288    #[error(transparent)]
289    NewAuthorizedActionTakerIdentityDoesNotExistError(
290        NewAuthorizedActionTakerIdentityDoesNotExistError,
291    ),
292
293    #[error(transparent)]
294    NewAuthorizedActionTakerGroupDoesNotExistError(NewAuthorizedActionTakerGroupDoesNotExistError),
295
296    #[error(transparent)]
297    NewAuthorizedActionTakerMainGroupNotSetError(NewAuthorizedActionTakerMainGroupNotSetError),
298
299    #[error(transparent)]
300    InvalidGroupPositionError(InvalidGroupPositionError),
301
302    #[error(transparent)]
303    TokenIsPausedError(TokenIsPausedError),
304
305    #[error(transparent)]
306    IdentityTokenAccountAlreadyFrozenError(IdentityTokenAccountAlreadyFrozenError),
307
308    #[error(transparent)]
309    TokenAlreadyPausedError(TokenAlreadyPausedError),
310
311    #[error(transparent)]
312    TokenNotPausedError(TokenNotPausedError),
313
314    #[error(transparent)]
315    TokenTransferRecipientIdentityNotExistError(TokenTransferRecipientIdentityNotExistError),
316
317    #[error(transparent)]
318    PreProgrammedDistributionTimestampInPastError(PreProgrammedDistributionTimestampInPastError),
319
320    #[error(transparent)]
321    IdentityHasNotAgreedToPayRequiredTokenAmountError(
322        IdentityHasNotAgreedToPayRequiredTokenAmountError,
323    ),
324
325    #[error(transparent)]
326    RequiredTokenPaymentInfoNotSetError(RequiredTokenPaymentInfoNotSetError),
327
328    #[error(transparent)]
329    IdentityTryingToPayWithWrongTokenError(IdentityTryingToPayWithWrongTokenError),
330
331    #[error(transparent)]
332    TokenDirectPurchaseUserPriceTooLow(TokenDirectPurchaseUserPriceTooLow),
333
334    #[error(transparent)]
335    TokenAmountUnderMinimumSaleAmount(TokenAmountUnderMinimumSaleAmount),
336
337    #[error(transparent)]
338    TokenNotForDirectSale(TokenNotForDirectSale),
339
340    #[error(transparent)]
341    IdentityInTokenConfigurationNotFoundError(IdentityInTokenConfigurationNotFoundError),
342
343    #[error(transparent)]
344    IdentityMemberOfGroupNotFoundError(IdentityMemberOfGroupNotFoundError),
345
346    #[error(transparent)]
347    ModificationOfGroupActionMainParametersNotPermittedError(
348        ModificationOfGroupActionMainParametersNotPermittedError,
349    ),
350
351    #[error(transparent)]
352    IdentityToFreezeDoesNotExistError(IdentityToFreezeDoesNotExistError),
353
354    #[error(transparent)]
355    DataContractNotFoundError(DataContractNotFoundError),
356
357    #[error(transparent)]
358    InvalidTokenPositionStateError(InvalidTokenPositionStateError),
359
360    #[error(transparent)]
361    AddressDoesNotExistError(AddressDoesNotExistError),
362
363    #[error(transparent)]
364    AddressNotEnoughFundsError(AddressNotEnoughFundsError),
365
366    #[error(transparent)]
367    AddressesNotEnoughFundsError(AddressesNotEnoughFundsError),
368
369    #[error(transparent)]
370    AddressInvalidNonceError(AddressInvalidNonceError),
371
372    #[error(transparent)]
373    InvalidAnchorError(InvalidAnchorError),
374
375    #[error(transparent)]
376    NullifierAlreadySpentError(NullifierAlreadySpentError),
377
378    #[error(transparent)]
379    InvalidShieldedProofError(InvalidShieldedProofError),
380
381    #[error(transparent)]
382    InsufficientPoolNotesError(InsufficientPoolNotesError),
383
384    #[error(transparent)]
385    InsufficientShieldedFeeError(InsufficientShieldedFeeError),
386
387    #[error(transparent)]
388    DocumentContestIndexMismatchError(DocumentContestIndexMismatchError),
389
390    #[error(transparent)]
391    DocumentContestNotRequiredError(DocumentContestNotRequiredError),
392
393    #[error(transparent)]
394    ReferencedEntityNotFoundError(ReferencedEntityNotFoundError),
395
396    #[error(transparent)]
397    ReferencedDocumentTypeNotFoundError(ReferencedDocumentTypeNotFoundError),
398
399    #[error(transparent)]
400    ReferencedDocumentTypeDeletableError(ReferencedDocumentTypeDeletableError),
401
402    #[error(transparent)]
403    ReferencedIdentityKeyNotFoundError(ReferencedIdentityKeyNotFoundError),
404
405    #[error(transparent)]
406    ReferencedIdentityKeyDisabledError(ReferencedIdentityKeyDisabledError),
407
408    #[error(transparent)]
409    ReferencedKeyIdPropertyInvalidError(ReferencedKeyIdPropertyInvalidError),
410
411    #[error(transparent)]
412    ReferencedDocumentPropertyAgreementInvalidError(
413        ReferencedDocumentPropertyAgreementInvalidError,
414    ),
415
416    #[error(transparent)]
417    ReferencedDocumentPropertyMismatchError(ReferencedDocumentPropertyMismatchError),
418
419    // Contract groups (protocol version 14).
420    #[error(transparent)]
421    ContractGroupAlreadyExistsError(ContractGroupAlreadyExistsError),
422
423    #[error(transparent)]
424    ContractGroupNotFoundError(ContractGroupNotFoundError),
425
426    #[error(transparent)]
427    IdentityNotContractGroupOwnerOrAdminError(IdentityNotContractGroupOwnerOrAdminError),
428
429    #[error(transparent)]
430    ContractGroupAdminNotFoundError(ContractGroupAdminNotFoundError),
431
432    // Authentication key limits (protocol version 14).
433    #[error(transparent)]
434    IdentityPublicKeyBudgetExceededError(IdentityPublicKeyBudgetExceededError),
435
436    #[error(transparent)]
437    IdentityPublicKeyAlreadyExpiredError(IdentityPublicKeyAlreadyExpiredError),
438
439    // Identity key limits update (protocol version 14).
440    #[error(transparent)]
441    IdentityPublicKeyLimitNotSetError(IdentityPublicKeyLimitNotSetError),
442
443    #[error(transparent)]
444    IdentityPublicKeyLimitNotRaisedError(IdentityPublicKeyLimitNotRaisedError),
445}
446
447impl From<StateError> for ConsensusError {
448    fn from(error: StateError) -> Self {
449        Self::StateError(error)
450    }
451}
452
453#[cfg(test)]
454mod tests {
455    use super::*;
456    use crate::consensus::state::identity::identity_public_key_limit_not_set_error::KeyLimit;
457    use platform_value::Identifier;
458
459    /// `StateError` is encoded by variant position, so inserting a variant
460    /// anywhere but the end silently reassigns the discriminant of every
461    /// variant after it — consensus errors travel to WASM and JavaScript
462    /// clients, which would then decode an existing error as a different one.
463    /// These are the frozen discriminants of the first variant, of the variant
464    /// that follows the document contest block (the one an insertion there
465    /// would shift first), and of the last four.
466    fn discriminant_of(error: StateError) -> u8 {
467        let bytes = bincode::encode_to_vec(error, bincode::config::standard())
468            .expect("expected to encode the state error");
469        // Discriminants below 251 are a single byte under bincode's varint.
470        bytes[0]
471    }
472
473    #[test]
474    fn state_error_discriminants_are_frozen() {
475        assert_eq!(
476            discriminant_of(StateError::DataContractAlreadyPresentError(
477                DataContractAlreadyPresentError::new(Identifier::from([1; 32]))
478            )),
479            0
480        );
481        assert_eq!(
482            discriminant_of(StateError::DocumentNotFoundError(
483                DocumentNotFoundError::new(Identifier::from([1; 32]))
484            )),
485            8
486        );
487        assert_eq!(
488            discriminant_of(StateError::InsufficientShieldedFeeError(
489                InsufficientShieldedFeeError::new("fee".to_string())
490            )),
491            90
492        );
493        assert_eq!(
494            discriminant_of(StateError::DocumentContestIndexMismatchError(
495                DocumentContestIndexMismatchError::new(
496                    Identifier::from([1; 32]),
497                    "expected".to_string(),
498                    "provided".to_string(),
499                )
500            )),
501            91
502        );
503        assert_eq!(
504            discriminant_of(StateError::DocumentContestNotRequiredError(
505                DocumentContestNotRequiredError::new(
506                    Identifier::from([1; 32]),
507                    "provided".to_string(),
508                )
509            )),
510            92
511        );
512        assert_eq!(
513            discriminant_of(StateError::ReferencedEntityNotFoundError(
514                ReferencedEntityNotFoundError::new(
515                    Identifier::from([1; 32]),
516                    crate::data_contract::document_type::DocumentPropertyReferenceTarget::Identity,
517                    "toUserId".to_string(),
518                )
519            )),
520            93
521        );
522        assert_eq!(
523            discriminant_of(StateError::ReferencedDocumentTypeNotFoundError(
524                ReferencedDocumentTypeNotFoundError::new(
525                    Identifier::from([1; 32]),
526                    "note".to_string(),
527                    "parentNoteId".to_string(),
528                )
529            )),
530            94
531        );
532        assert_eq!(
533            discriminant_of(StateError::ReferencedDocumentTypeDeletableError(
534                ReferencedDocumentTypeDeletableError::new(
535                    Identifier::from([1; 32]),
536                    "note".to_string(),
537                    "parentNoteId".to_string(),
538                )
539            )),
540            95
541        );
542        assert_eq!(
543            discriminant_of(StateError::ReferencedIdentityKeyNotFoundError(
544                ReferencedIdentityKeyNotFoundError::new(
545                    Identifier::from([1; 32]),
546                    2,
547                    "toUserId".to_string(),
548                )
549            )),
550            96
551        );
552        assert_eq!(
553            discriminant_of(StateError::ReferencedIdentityKeyDisabledError(
554                ReferencedIdentityKeyDisabledError::new(
555                    Identifier::from([1; 32]),
556                    2,
557                    "toUserId".to_string(),
558                )
559            )),
560            97
561        );
562        assert_eq!(
563            discriminant_of(StateError::ReferencedKeyIdPropertyInvalidError(
564                ReferencedKeyIdPropertyInvalidError::new(
565                    "recipientKeyIndex".to_string(),
566                    "toUserId".to_string(),
567                    "missing".to_string(),
568                )
569            )),
570            98
571        );
572        assert_eq!(
573            discriminant_of(StateError::ReferencedDocumentPropertyAgreementInvalidError(
574                ReferencedDocumentPropertyAgreementInvalidError::new(
575                    "like.postId".to_string(),
576                    "hashtag".to_string(),
577                    "hashtag".to_string(),
578                    "missing".to_string(),
579                )
580            )),
581            99
582        );
583        assert_eq!(
584            discriminant_of(StateError::ReferencedDocumentPropertyMismatchError(
585                ReferencedDocumentPropertyMismatchError::new(
586                    "postId".to_string(),
587                    "hashtag".to_string(),
588                    "hashtag".to_string(),
589                )
590            )),
591            100
592        );
593        // Contract groups (protocol version 14).
594        let group_id = Identifier::from([1u8; 32]);
595        let identity_id = Identifier::from([2u8; 32]);
596        assert_eq!(
597            discriminant_of(StateError::ContractGroupAlreadyExistsError(
598                ContractGroupAlreadyExistsError::new(group_id)
599            )),
600            101
601        );
602        assert_eq!(
603            discriminant_of(StateError::ContractGroupNotFoundError(
604                ContractGroupNotFoundError::new(group_id)
605            )),
606            102
607        );
608        assert_eq!(
609            discriminant_of(StateError::IdentityNotContractGroupOwnerOrAdminError(
610                IdentityNotContractGroupOwnerOrAdminError::new(identity_id, group_id)
611            )),
612            103
613        );
614        assert_eq!(
615            discriminant_of(StateError::ContractGroupAdminNotFoundError(
616                ContractGroupAdminNotFoundError::new(group_id, identity_id)
617            )),
618            104
619        );
620        // Authentication key limits (protocol version 14): the tail of the enum.
621        assert_eq!(
622            discriminant_of(StateError::IdentityPublicKeyBudgetExceededError(
623                IdentityPublicKeyBudgetExceededError::new(identity_id, 1, 2, 3)
624            )),
625            105
626        );
627        assert_eq!(
628            discriminant_of(StateError::IdentityPublicKeyAlreadyExpiredError(
629                IdentityPublicKeyAlreadyExpiredError::new(1, 2, 3)
630            )),
631            106
632        );
633        // Identity key limits update (protocol version 14): the tail of the enum.
634        assert_eq!(
635            discriminant_of(StateError::IdentityPublicKeyLimitNotSetError(
636                IdentityPublicKeyLimitNotSetError::new(1, KeyLimit::Budget)
637            )),
638            107
639        );
640        assert_eq!(
641            discriminant_of(StateError::IdentityPublicKeyLimitNotRaisedError(
642                IdentityPublicKeyLimitNotRaisedError::new(1, KeyLimit::Expiry, 2, 3)
643            )),
644            108
645        );
646    }
647}