dpp/state_transition/traits/
state_transition_identity_signed.rs

1#[cfg(any(
2    feature = "state-transition-signing",
3    feature = "state-transition-validation"
4))]
5use crate::consensus::signature::{
6    InvalidSignaturePublicKeySecurityLevelError, PublicKeyIsDisabledError,
7};
8use anyhow::anyhow;
9use dashcore::secp256k1::{PublicKey as RawPublicKey, SecretKey as RawSecretKey};
10
11#[cfg(feature = "state-transition-validation")]
12use crate::state_transition::errors::WrongPublicKeyPurposeError;
13
14#[cfg(any(
15    feature = "state-transition-signing",
16    feature = "state-transition-validation"
17))]
18use crate::identity::identity_public_key::accessors::v0::IdentityPublicKeyGettersV0;
19use crate::state_transition::StateTransitionLike;
20#[cfg(any(
21    feature = "state-transition-signing",
22    feature = "state-transition-validation"
23))]
24use crate::state_transition::StateTransitionSigningOptions;
25
26#[cfg(any(
27    feature = "state-transition-signing",
28    feature = "state-transition-validation"
29))]
30use crate::identity::IdentityPublicKey;
31use crate::identity::Purpose;
32use crate::{
33    identity::{KeyID, SecurityLevel},
34    prelude::*,
35};
36
37pub trait StateTransitionIdentitySigned: StateTransitionLike {
38    fn signature_public_key_id(&self) -> KeyID;
39    fn set_signature_public_key_id(&mut self, key_id: KeyID);
40
41    //this is not versioned because of it just being the base trait default
42    #[cfg(any(
43        feature = "state-transition-signing",
44        feature = "state-transition-validation"
45    ))]
46    /// Verifies that the supplied public key has the correct security level
47    /// and purpose to sign the state transition
48    /// This should only be used for authentication
49    fn verify_public_key_level_and_purpose(
50        &self,
51        public_key: &IdentityPublicKey,
52        options: StateTransitionSigningOptions,
53    ) -> Result<(), ProtocolError> {
54        if !options.allow_signing_with_any_purpose
55            && !self.purpose_requirement().contains(&public_key.purpose())
56        {
57            return Err(ProtocolError::WrongPublicKeyPurposeError(
58                WrongPublicKeyPurposeError::new(public_key.purpose(), self.purpose_requirement()),
59            ));
60        }
61
62        // Otherwise, key security level should be less than MASTER but more or equal than required
63        if !options.allow_signing_with_any_security_level
64            && !self
65                .security_level_requirement(public_key.purpose())
66                .contains(&public_key.security_level())
67        {
68            return Err(ProtocolError::InvalidSignaturePublicKeySecurityLevelError(
69                InvalidSignaturePublicKeySecurityLevelError::new(
70                    public_key.security_level(),
71                    self.security_level_requirement(public_key.purpose()),
72                ),
73            ));
74        }
75
76        Ok(())
77    }
78
79    //this is not versioned because of it just being the base trait default
80    #[cfg(any(
81        feature = "state-transition-signing",
82        feature = "state-transition-validation"
83    ))]
84    fn verify_public_key_is_enabled(
85        &self,
86        public_key: &IdentityPublicKey,
87    ) -> Result<(), ProtocolError> {
88        if public_key.disabled_at().is_some() {
89            return Err(ProtocolError::PublicKeyIsDisabledError(
90                PublicKeyIsDisabledError::new(public_key.id()),
91            ));
92        }
93        Ok(())
94    }
95
96    /// Returns minimal key security level that can be used to sign this ST.
97    /// Override this method if the ST requires a different security level.
98    fn security_level_requirement(&self, purpose: Purpose) -> Vec<SecurityLevel>;
99
100    /// The purpose requirement for the signing key
101    /// The default is authentication
102    /// However for Withdrawals and Fund Transfers the requirement is TRANSFER
103    fn purpose_requirement(&self) -> Vec<Purpose> {
104        vec![Purpose::AUTHENTICATION]
105    }
106}
107
108pub fn get_compressed_public_ec_key(private_key: &[u8]) -> Result<[u8; 33], ProtocolError> {
109    let sk = RawSecretKey::from_slice(private_key)
110        .map_err(|e| anyhow!("Invalid ECDSA private key: {}", e))?;
111
112    let secp = dashcore::secp256k1::Secp256k1::new();
113    let public_key_compressed = RawPublicKey::from_secret_key(&secp, &sk).serialize();
114    Ok(public_key_compressed)
115}
116
117//
118// #[cfg(test)]
119// mod test {
120//     use chrono::Utc;
121//     use platform_value::{BinaryData, Value};
122//     use rand::rngs::StdRng;
123//     use rand::SeedableRng;
124//     use serde::{Deserialize, Serialize};
125//     use serde_json::json;
126//     use std::convert::TryInto;
127//     use std::vec;
128//
129//     use crate::ProtocolError::InvalidSignaturePublicKeySecurityLevelError;
130//     use crate::{
131//         assert_error_contains,
132//         identity::{KeyID, SecurityLevel},
133//         state_transition::{
134//             StateTransition, StateTransitionFieldTypes, StateTransitionLike, StateTransitionType,
135//         },
136//         util::hash::ripemd160_sha256,
137//         NativeBlsModule,
138//     };
139//     use platform_value::string_encoding::Encoding;
140//
141//     use super::StateTransitionIdentitySignedV0;
142//     use super::*;
143//     use crate::serialization::PlatformDeserializable;
144//     use crate::serialization::PlatformSerializable;
145//     use crate::serialization::Signable;
146//     use crate::version::FeatureVersion;
147//     use bincode::{config, Decode, Encode};
148//     use platform_serialization_derive::{PlatformDeserialize, PlatformSerialize, PlatformSignable};
149//
150//     #[derive(
151//         Debug,
152//         Clone,
153//         Encode,
154//         Decode,
155//         Serialize,
156//         Deserialize,
157//         PlatformDeserialize,
158//         PlatformSerialize,
159//         PlatformSignable,
160//     )]
161//
162//     #[serde(rename_all = "camelCase")]
163//     struct ExampleStateTransition {
164//         pub protocol_version: u32,
165//         pub transition_type: StateTransitionType,
166//         pub owner_id: Identifier,
167//         #[platform_signable(exclude_from_sig_hash)]
168//         pub signature: BinaryData,
169//         #[platform_signable(exclude_from_sig_hash)]
170//         pub signature_public_key_id: KeyID,
171//     }
172//
173//     impl StateTransitionFieldTypes for ExampleStateTransition {
174//         fn binary_property_paths() -> Vec<&'static str> {
175//             vec!["signature"]
176//         }
177//         fn identifiers_property_paths() -> Vec<&'static str> {
178//             vec![]
179//         }
180//         fn signature_property_paths() -> Vec<&'static str> {
181//             vec!["signature", "signaturePublicKeyId"]
182//         }
183//
184//         fn to_cleaned_object(&self, _skip_signature: bool) -> Result<Value, ProtocolError> {
185//             todo!()
186//         }
187//     }
188//
189//     impl From<ExampleStateTransition> for StateTransition {
190//         fn from(_val: ExampleStateTransition) -> Self {
191//             let st = DocumentsBatchTransition::default();
192//             StateTransition::DocumentsBatch(st)
193//         }
194//     }
195//
196//     impl StateTransitionLike for ExampleStateTransition {
197//         fn state_transition_protocol_version(&self) -> FeatureVersion {
198//             1
199//         }
200//         fn state_transition_type(&self) -> StateTransitionType {
201//             StateTransitionType::DocumentsBatch
202//         }
203//         fn signature(&self) -> &BinaryData {
204//             &self.signature
205//         }
206//         fn set_signature(&mut self, signature: BinaryData) {
207//             self.signature = signature
208//         }
209//
210//         fn set_signature_bytes(&mut self, signature: Vec<u8>) {
211//             self.signature = BinaryData::new(signature)
212//         }
213//
214//         fn modified_data_ids(&self) -> Vec<Identifier> {
215//             vec![]
216//         }
217//     }
218//
219//     impl StateTransitionIdentitySignedV0 for ExampleStateTransition {
220//         fn get_owner_id(&self) -> &Identifier {
221//             &self.owner_id
222//         }
223//         fn get_security_level_requirement(&self) -> Vec<SecurityLevel> {
224//             vec![SecurityLevel::HIGH]
225//         }
226//
227//         fn get_signature_public_key_id(&self) -> Option<KeyID> {
228//             self.signature_public_key_id
229//         }
230//
231//         fn set_signature_public_key_id(&mut self, key_id: KeyID) {
232//             self.signature_public_key_id = key_id;
233//         }
234//     }
235//
236//     fn get_mock_state_transition() -> ExampleStateTransition {
237//         let owner_id = Identifier::from_string(
238//             "AX5o22ARWFYZE9JZTA5SSeyvprtetBcvbQLSBZ7cR7Gw",
239//             Encoding::Base58,
240//         )
241//         .unwrap();
242//         ExampleStateTransition {
243//             protocol_version: 1,
244//             transition_type: StateTransitionType::DocumentsBatch,
245//             signature: Default::default(),
246//             signature_public_key_id: 1,
247//             owner_id,
248//         }
249//     }
250//
251//     struct Keys {
252//         pub ec_private: Vec<u8>,
253//         pub ec_public_compressed: Vec<u8>,
254//         pub ec_public_uncompressed: Vec<u8>,
255//         pub bls_private: Vec<u8>,
256//         pub bls_public: Vec<u8>,
257//         pub identity_public_key: IdentityPublicKey,
258//         pub public_key_id: KeyID,
259//     }
260//
261//     fn get_test_keys() -> Keys {
262//         let secp = dashcore::secp256k1::Secp256k1::new();
263//         let mut rng = dashcore::secp256k1::rand::thread_rng();
264//         let mut std_rng = StdRng::seed_from_u64(99999);
265//         let (private_key, public_key) = secp.generate_keypair(&mut rng);
266//
267//         let public_key_id = 1;
268//         let ec_private_key_bytes = private_key.secret_bytes();
269//         let ec_public_compressed_bytes = public_key.serialize();
270//         let ec_public_uncompressed_bytes = public_key.serialize_uncompressed();
271//
272//         let bls_private =
273//             bls_signatures::PrivateKey::generate_dash(&mut std_rng).expect("expected private key");
274//         let bls_public = bls_private
275//             .g1_element()
276//             .expect("expected to make public key");
277//         let bls_private_bytes = bls_private.to_bytes().to_vec();
278//         let bls_public_bytes = bls_public.to_bytes().to_vec();
279//
280//         let identity_public_key = IdentityPublicKey {
281//             id: public_key_id,
282//             key_type: KeyType::ECDSA_SECP256K1,
283//             purpose: Purpose::AUTHENTICATION,
284//             security_level: SecurityLevel::HIGH,
285//             data: BinaryData::new(ec_public_compressed_bytes.try_into().unwrap()),
286//             read_only: false,
287//             disabled_at: None,
288//         };
289//
290//         Keys {
291//             ec_private: ec_private_key_bytes.to_vec(),
292//             ec_public_compressed: ec_public_compressed_bytes.to_vec(),
293//             ec_public_uncompressed: ec_public_uncompressed_bytes.to_vec(),
294//             bls_private: bls_private_bytes,
295//             bls_public: bls_public_bytes,
296//             identity_public_key,
297//             public_key_id,
298//         }
299//     }
300//
301//     #[test]
302//     fn to_object_with_signature() {
303//         let st = get_mock_state_transition();
304//         let st_object = st.to_object(false).unwrap();
305//
306//         assert_eq!(st_object["protocolVersion"].to_integer::<u32>().unwrap(), 1);
307//         assert_eq!(st_object["transitionType"].to_integer::<u8>().unwrap(), 1);
308//         assert_eq!(
309//             st_object["signaturePublicKeyId"]
310//                 .to_integer::<u32>()
311//                 .unwrap(),
312//             1
313//         );
314//         assert!(st_object["signature"].as_bytes().unwrap().is_empty());
315//     }
316//
317//     #[test]
318//     fn to_object_without_signature() {
319//         let st = get_mock_state_transition();
320//         let st_object = st.to_object(true).unwrap();
321//
322//         assert_eq!(st_object["protocolVersion"].to_integer::<u32>().unwrap(), 1);
323//         assert_eq!(st_object["transitionType"].to_integer::<u8>().unwrap(), 1);
324//         assert!(!st_object.has("signaturePublicKeyId").unwrap());
325//         assert!(!st_object.has("signature").unwrap());
326//     }
327//
328//     #[test]
329//     fn to_json() {
330//         let st = get_mock_state_transition();
331//         let st_json = st.to_json(false).unwrap();
332//         assert_eq!(
333//             st_json,
334//             json!({
335//                 "protocolVersion" : 1,
336//                 "signature": "",
337//                 "signaturePublicKeyId": 1,
338//                 "transitionType" : 1,
339//                 "ownerId" : "AX5o22ARWFYZE9JZTA5SSeyvprtetBcvbQLSBZ7cR7Gw"
340//             })
341//         );
342//     }
343//
344//     #[test]
345//     fn to_hash() {
346//         let st = get_mock_state_transition();
347//         let hash = st.hash(false).unwrap();
348//         assert_eq!(
349//             "39b9c5951e5d83668f98909bb73d390d49867c47bbfe043a42ac83de898142c0",
350//             hex::encode(hash)
351//         )
352//     }
353//
354//     #[test]
355//     fn to_buffer() {
356//         let st = get_mock_state_transition();
357//         let hash = st.to_cbor_buffer(false).unwrap();
358//         let result = hex::encode(hash);
359//
360//         assert_eq!("01a4676f776e6572496458208d6e06cac6cd2c4b9020806a3f1a4ec48fc90defd314330a5ce7d8548dfc2524697369676e617475726540747369676e61747572655075626c69634b65794964016e7472616e736974696f6e5479706501", result.as_str());
361//     }
362//
363//     #[test]
364//     fn to_buffer_no_signature() {
365//         let st = get_mock_state_transition();
366//         let hash = st.to_cbor_buffer(true).unwrap();
367//         let result = hex::encode(hash);
368//
369//         assert_eq!("01a2676f776e6572496458208d6e06cac6cd2c4b9020806a3f1a4ec48fc90defd314330a5ce7d8548dfc25246e7472616e736974696f6e5479706501", result);
370//     }
371//
372//     #[test]
373//     fn get_signature_public_key_id() {
374//         let st = get_mock_state_transition();
375//         let keys = get_test_keys();
376//         assert_eq!(Some(keys.public_key_id), st.get_signature_public_key_id())
377//     }
378//
379//     #[test]
380//     fn sign_validate_with_private_key() {
381//         let bls = NativeBlsModule::default();
382//         let mut st = get_mock_state_transition();
383//         let keys = get_test_keys();
384//
385//         st.sign(&keys.identity_public_key, &keys.ec_private, &bls)
386//             .unwrap();
387//         st.verify_signature(&keys.identity_public_key, &bls)
388//             .expect("the verification shouldn't fail");
389//     }
390//
391//     #[test]
392//     fn sign_validate_signature_ecdsa_hash160() {
393//         let bls = NativeBlsModule::default();
394//         let mut st = get_mock_state_transition();
395//         let mut keys = get_test_keys();
396//         keys.identity_public_key.key_type = KeyType::ECDSA_HASH160;
397//         keys.identity_public_key.data =
398//             BinaryData::new(ripemd160_sha256(keys.identity_public_key.data.as_slice()).to_vec());
399//
400//         st.sign(&keys.identity_public_key, &keys.ec_private, &bls)
401//             .unwrap();
402//         st.verify_signature(&keys.identity_public_key, &bls)
403//             .expect("the verification shouldn't fail");
404//     }
405//
406//     #[test]
407//     fn error_when_sign_with_wrong_public_key() {
408//         let bls = NativeBlsModule::default();
409//         let mut st = get_mock_state_transition();
410//         let mut keys = get_test_keys();
411//
412//         let secp = dashcore::secp256k1::Secp256k1::new();
413//         let mut rng = dashcore::secp256k1::rand::thread_rng();
414//         let (_, public_key) = secp.generate_keypair(&mut rng);
415//
416//         keys.identity_public_key.data = BinaryData::new(public_key.serialize().to_vec());
417//
418//         let sign_result = st.sign(&keys.identity_public_key, &keys.ec_private, &bls);
419//         assert_error_contains!(sign_result, "Invalid signature public key");
420//     }
421//
422//     #[test]
423//     fn error_if_security_level_is_not_met() {
424//         let bls = NativeBlsModule::default();
425//         let mut st = get_mock_state_transition();
426//         let mut keys = get_test_keys();
427//         keys.identity_public_key.security_level = SecurityLevel::MEDIUM;
428//
429//         let sign_error = st
430//             .sign(&keys.identity_public_key, &keys.ec_private, &bls)
431//             .unwrap_err();
432//         match sign_error {
433//             InvalidSignaturePublicKeySecurityLevelError(err) => {
434//                 assert_eq!(SecurityLevel::MEDIUM, err.public_key_security_level());
435//                 assert_eq!(vec![SecurityLevel::HIGH], err.allowed_key_security_levels());
436//             }
437//             error => {
438//                 panic!("invalid error type: {}", error)
439//             }
440//         };
441//     }
442//
443//     #[test]
444//     fn error_if_key_purpose_not_authenticated() {
445//         let bls = NativeBlsModule::default();
446//         let mut st = get_mock_state_transition();
447//         let mut keys = get_test_keys();
448//         keys.identity_public_key.purpose = Purpose::ENCRYPTION;
449//
450//         let sign_error = st
451//             .sign(&keys.identity_public_key, &keys.ec_private, &bls)
452//             .unwrap_err();
453//         match sign_error {
454//             ProtocolError::WrongPublicKeyPurposeError(err) => {
455//                 assert_eq!(Purpose::ENCRYPTION, err.public_key_purpose());
456//                 assert_eq!(Purpose::AUTHENTICATION, err.key_purpose_requirement());
457//             }
458//             error => {
459//                 panic!("invalid error type: {}", error)
460//             }
461//         };
462//     }
463//
464//     #[test]
465//     fn should_sign_validate_with_bls_signature() {
466//         let bls = NativeBlsModule::default();
467//         let mut st = get_mock_state_transition();
468//         let mut keys = get_test_keys();
469//         keys.identity_public_key.key_type = KeyType::BLS12_381;
470//         keys.identity_public_key.data = BinaryData::new(keys.bls_public.clone());
471//
472//         st.sign(&keys.identity_public_key, &keys.bls_private, &bls)
473//             .expect("validation should be successful");
474//     }
475//
476//     #[test]
477//     fn error_if_transition_is_not_signed_ecdsa() {
478//         let bls = NativeBlsModule::default();
479//         let st = get_mock_state_transition();
480//         let keys = get_test_keys();
481//
482//         let verify_error = st
483//             .verify_signature(&keys.identity_public_key, &bls)
484//             .unwrap_err();
485//         match verify_error {
486//             ProtocolError::StateTransitionIsNotSignedError { .. } => {}
487//             error => {
488//                 panic!("invalid error type: {}", error)
489//             }
490//         };
491//     }
492//
493//     #[test]
494//     fn error_if_transition_is_not_signed_bls() {
495//         let bls = NativeBlsModule::default();
496//         let st = get_mock_state_transition();
497//         let mut keys = get_test_keys();
498//         keys.identity_public_key.key_type = KeyType::BLS12_381;
499//         keys.identity_public_key.data = BinaryData::new(keys.bls_public.clone());
500//
501//         let verify_error = st
502//             .verify_signature(&keys.identity_public_key, &bls)
503//             .unwrap_err();
504//         match verify_error {
505//             ProtocolError::StateTransitionIsNotSignedError { .. } => {}
506//             error => {
507//                 panic!("invalid error type: {}", error)
508//             }
509//         };
510//     }
511//
512//     #[test]
513//     fn set_signature() {
514//         let mut st = get_mock_state_transition();
515//         let signature = "some_signature";
516//         st.set_signature(BinaryData::new(signature.as_bytes().to_owned()));
517//         assert_eq!(signature.as_bytes(), st.signature().as_slice());
518//     }
519//
520//     #[test]
521//     fn set_signature_public_key_id() {
522//         let mut st = get_mock_state_transition();
523//         let public_key_id = 2;
524//         st.set_signature_public_key_id(public_key_id);
525//         assert_eq!(Some(public_key_id), st.get_signature_public_key_id());
526//     }
527//
528//     #[test]
529//     fn should_throw_public_key_is_disabled_error_if_public_key_is_disabled() {
530//         let bls = NativeBlsModule::default();
531//         let mut st = get_mock_state_transition();
532//         let mut keys = get_test_keys();
533//         keys.identity_public_key
534//             .set_disabled_at(Utc::now().timestamp_millis() as u64);
535//
536//         let result = st
537//             .sign(&keys.identity_public_key, &keys.bls_private, &bls)
538//             .expect_err("the protocol error should be returned");
539//
540//         assert!(matches!(
541//             result,
542//             ProtocolError::PublicKeyIsDisabledError { .. }
543//         ))
544//     }
545//
546//     #[test]
547//     fn should_throw_invalid_signature_public_key_security_level_error() {
548//         let bls = NativeBlsModule::default();
549//         // should throw InvalidSignaturePublicKeySecurityLevel Error if public key with master level is used to sign non update state transition
550//         let mut st = get_mock_state_transition();
551//         let mut keys = get_test_keys();
552//
553//         st.transition_type = StateTransitionType::DataContractCreate;
554//         keys.identity_public_key.security_level = SecurityLevel::MASTER;
555//
556//         let result = st
557//             .sign(&keys.identity_public_key, &keys.bls_private, &bls)
558//             .expect_err("the protocol error should be returned");
559//
560//         match result {
561//             ProtocolError::InvalidSignaturePublicKeySecurityLevelError(err) => {
562//                 assert_eq!(err.public_key_security_level(), SecurityLevel::MASTER);
563//                 assert_eq!(err.allowed_key_security_levels(), vec![SecurityLevel::HIGH]);
564//             }
565//             error => panic!(
566//                 "expected InvalidSignaturePublicKeySecurityLevelError, got {}",
567//                 error
568//             ),
569//         }
570//     }
571// }