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// }