Skip to main content

dpp/state_transition/state_transitions/document/batch_transition/
mod.rs

1use bincode::{Decode, Encode};
2
3use std::convert::TryInto;
4
5use derive_more::From;
6
7use platform_value::Value;
8#[cfg(feature = "serde-conversion")]
9use serde::{Deserialize, Serialize};
10
11use crate::ProtocolError;
12use crate::{identity::SecurityLevel, state_transition::StateTransitionFieldTypes};
13
14pub use self::batched_transition::{
15    document_base_transition, document_create_transition,
16    document_create_transition::DocumentCreateTransition, document_delete_transition,
17    document_delete_transition::DocumentDeleteTransition, document_replace_transition,
18    document_replace_transition::DocumentReplaceTransition, token_base_transition,
19    token_burn_transition, token_burn_transition::TokenBurnTransition, token_claim_transition,
20    token_claim_transition::TokenClaimTransition, token_config_update_transition,
21    token_config_update_transition::TokenConfigUpdateTransition,
22    token_destroy_frozen_funds_transition,
23    token_destroy_frozen_funds_transition::TokenDestroyFrozenFundsTransition,
24    token_direct_purchase_transition,
25    token_direct_purchase_transition::TokenDirectPurchaseTransition,
26    token_emergency_action_transition,
27    token_emergency_action_transition::TokenEmergencyActionTransition, token_freeze_transition,
28    token_freeze_transition::TokenFreezeTransition, token_mint_transition,
29    token_mint_transition::TokenMintTransition, token_set_price_for_direct_purchase_transition,
30    token_set_price_for_direct_purchase_transition::TokenSetPriceForDirectPurchaseTransition,
31    token_transfer_transition, token_transfer_transition::TokenTransferTransition,
32    token_unfreeze_transition, token_unfreeze_transition::TokenUnfreezeTransition,
33};
34
35use platform_serialization_derive::{PlatformDeserialize, PlatformSerialize, PlatformSignable};
36use platform_versioning::PlatformVersioned;
37
38pub mod accessors;
39pub mod batched_transition;
40pub mod fields;
41mod identity_signed;
42pub mod methods;
43pub mod resolvers;
44mod state_transition_estimated_fee_validation;
45mod state_transition_like;
46mod v0;
47mod v1;
48#[cfg(feature = "validation")]
49mod validation;
50mod version;
51
52use crate::state_transition::data_contract_update_transition::{
53    SIGNATURE, SIGNATURE_PUBLIC_KEY_ID,
54};
55
56use crate::state_transition::batch_transition::fields::property_names;
57
58use crate::identity::state_transition::OptionallyAssetLockProved;
59pub use v0::*;
60pub use v1::*;
61
62#[derive(
63    Debug,
64    Clone,
65    PartialEq,
66    Encode,
67    Decode,
68    PlatformDeserialize,
69    PlatformSerialize,
70    PlatformSignable,
71    PlatformVersioned,
72    From,
73)]
74#[cfg_attr(
75    feature = "serde-conversion",
76    derive(Serialize, Deserialize),
77    serde(tag = "$formatVersion")
78)]
79#[platform_serialize(unversioned)] //versioned directly, no need to use platform_version
80#[platform_version_path_bounds(
81    "dpp.state_transition_serialization_versions.batch_state_transition"
82)]
83pub enum BatchTransition {
84    #[cfg_attr(feature = "serde-conversion", serde(rename = "0"))]
85    V0(BatchTransitionV0),
86    #[cfg_attr(feature = "serde-conversion", serde(rename = "1"))]
87    V1(BatchTransitionV1),
88}
89
90#[cfg(all(feature = "json-conversion", feature = "serde-conversion"))]
91impl crate::serialization::JsonConvertible for BatchTransition {}
92
93#[cfg(all(feature = "value-conversion", feature = "serde-conversion"))]
94impl crate::serialization::ValueConvertible for BatchTransition {}
95
96impl StateTransitionFieldTypes for BatchTransition {
97    fn binary_property_paths() -> Vec<&'static str> {
98        vec![SIGNATURE]
99    }
100
101    fn identifiers_property_paths() -> Vec<&'static str> {
102        vec![property_names::OWNER_ID]
103    }
104
105    fn signature_property_paths() -> Vec<&'static str> {
106        vec![SIGNATURE, SIGNATURE_PUBLIC_KEY_ID]
107    }
108}
109
110#[cfg(all(
111    test,
112    feature = "json-conversion",
113    feature = "value-conversion",
114    feature = "serde-conversion"
115))]
116pub(crate) mod json_convertible_tests {
117    use super::*;
118    use platform_value::{platform_value, BinaryData, Identifier};
119    use serde_json::json;
120
121    pub(crate) fn fixture() -> BatchTransition {
122        BatchTransition::V0(BatchTransitionV0 {
123            owner_id: Identifier::new([0xc0; 32]),
124            transitions: vec![], // empty transitions list — sub-types tested separately
125            user_fee_increase: 23,
126            signature_public_key_id: 4,
127            signature: BinaryData::new(vec![0xd0; 65]),
128        })
129    }
130
131    #[test]
132    fn json_round_trip_with_full_wire_shape() {
133        use crate::serialization::JsonConvertible;
134        let original = fixture();
135        let json = original.to_json().expect("to_json");
136        // `BatchTransition` is internally tagged `$formatVersion`; V0 fields use
137        // camelCase. `userFeeIncrease` is `u16`, `signaturePublicKeyId` is `u32`
138        // — JSON has only one number type, so sized variants are erased on the
139        // wire (the value-path test below pins the typed variants). `Identifier`
140        // is base58 in JSON HR; `BinaryData` is base64.
141        assert_eq!(
142            json,
143            json!({
144                "$formatVersion": "0",
145                "ownerId": "DyRkUpQxYG2VnP2SkMdQs5BTsVPeKCpSHLxzByc2Sxvj",
146                "transitions": [],
147                "userFeeIncrease": 23,
148                "signaturePublicKeyId": 4,
149                "signature": "0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NA=",
150            })
151        );
152        let recovered = BatchTransition::from_json(json).expect("from_json");
153        assert_eq!(original, recovered);
154    }
155
156    #[test]
157    fn value_round_trip_with_full_wire_shape() {
158        use crate::serialization::ValueConvertible;
159        use platform_value::Value;
160        let original = fixture();
161        let value = original.to_object().expect("to_object");
162        let owner_id = Identifier::new([0xc0; 32]);
163        // `userFeeIncrease` is `u16` (UserFeeIncrease alias), `signaturePublicKeyId`
164        // is `u32` (KeyID alias) — explicit suffixes lock in the typed variants.
165        // `BinaryData` is `Value::Bytes` in non-HR.
166        assert_eq!(
167            value,
168            platform_value!({
169                "$formatVersion": "0",
170                "ownerId": owner_id,
171                "transitions": Value::Array(vec![]),
172                "userFeeIncrease": 23u16,
173                "signaturePublicKeyId": 4u32,
174                "signature": Value::Bytes(vec![0xd0; 65]),
175            })
176        );
177        let recovered = BatchTransition::from_object(value).expect("from_object");
178        assert_eq!(original, recovered);
179    }
180}
181
182// TODO: Make a DocumentType method
183pub fn get_security_level_requirement(v: &Value, default: SecurityLevel) -> SecurityLevel {
184    let maybe_security_level: Option<u64> = v
185        .get_optional_integer(property_names::SECURITY_LEVEL_REQUIREMENT)
186        // TODO: Data Contract must already valid so there is no chance that this will fail
187        .expect("document schema must be a map");
188
189    match maybe_security_level {
190        Some(some_level) => (some_level as u8).try_into().unwrap_or(default),
191        None => default,
192    }
193}
194
195impl OptionallyAssetLockProved for BatchTransition {}
196
197#[cfg(test)]
198mod tests;