dpp/
signing.rs

1use crate::identity::KeyType;
2use crate::serialization::PlatformMessageSignable;
3#[cfg(feature = "message-signature-verification")]
4use crate::{
5    consensus::signature::{
6        BasicBLSError, BasicECDSAError, SignatureError, SignatureShouldNotBePresentError,
7    },
8    validation::SimpleConsensusValidationResult,
9};
10#[cfg(feature = "message-signing")]
11use crate::{BlsModule, ProtocolError};
12use dashcore::signer;
13#[cfg(feature = "bls-signatures")]
14use {
15    crate::bls_signatures::{Bls12381G2Impl, Pairing},
16    dashcore::{blsful as bls_signatures, blsful::Signature},
17};
18
19impl PlatformMessageSignable for &[u8] {
20    #[cfg(feature = "message-signature-verification")]
21    fn verify_signature(
22        &self,
23        public_key_type: KeyType,
24        public_key_data: &[u8],
25        signature: &[u8],
26    ) -> SimpleConsensusValidationResult {
27        let signable_data = self;
28        match public_key_type {
29            KeyType::ECDSA_SECP256K1 => {
30                if let Err(e) =
31                    signer::verify_data_signature(signable_data, signature, public_key_data)
32                {
33                    // dbg!(format!(
34                    //     "error with signature {} data {} public key {}",
35                    //     hex::encode(signature),
36                    //     hex::encode(signable_data),
37                    //     hex::encode(public_key_data)
38                    // ));
39                    SimpleConsensusValidationResult::new_with_error(
40                        SignatureError::BasicECDSAError(BasicECDSAError::new(e.to_string())).into(),
41                    )
42                } else {
43                    SimpleConsensusValidationResult::default()
44                }
45            }
46            KeyType::BLS12_381 => {
47                let public_key =
48                    match bls_signatures::PublicKey::<Bls12381G2Impl>::try_from(public_key_data) {
49                        Ok(public_key) => public_key,
50                        Err(e) => {
51                            // dbg!(format!("bls public_key could not be recovered"));
52                            return SimpleConsensusValidationResult::new_with_error(
53                                SignatureError::BasicBLSError(BasicBLSError::new(e.to_string()))
54                                    .into(),
55                            );
56                        }
57                    };
58                let signature_bytes: [u8; 96] = match signature.try_into() {
59                    Ok(bytes) => bytes,
60                    Err(_) => {
61                        return SimpleConsensusValidationResult::new_with_error(
62                            SignatureError::BasicBLSError(BasicBLSError::new(format!(
63                                "Signature was {} bytes, expected 96 bytes",
64                                signature.len()
65                            )))
66                            .into(),
67                        )
68                    }
69                };
70                let g2 = match <Bls12381G2Impl as Pairing>::Signature::from_compressed(
71                    &signature_bytes,
72                )
73                .into_option()
74                {
75                    Some(g2) => g2,
76                    None => {
77                        return SimpleConsensusValidationResult::new_with_error(
78                            SignatureError::BasicBLSError(BasicBLSError::new("bls signature does not conform to proper bls signature serialization".to_string())).into(),
79                        );
80                    }
81                };
82                let signature = Signature::<Bls12381G2Impl>::Basic(g2);
83
84                if signature.verify(&public_key, signable_data).is_err() {
85                    SimpleConsensusValidationResult::new_with_error(
86                        SignatureError::BasicBLSError(BasicBLSError::new(
87                            "bls signature was incorrect".to_string(),
88                        ))
89                        .into(),
90                    )
91                } else {
92                    SimpleConsensusValidationResult::default()
93                }
94            }
95            KeyType::ECDSA_HASH160 => {
96                if !signature.is_empty() {
97                    SimpleConsensusValidationResult::new_with_error(
98                        SignatureError::SignatureShouldNotBePresentError(
99                            SignatureShouldNotBePresentError::new("ecdsa_hash160 keys should not have a signature as that would reveal the public key".to_string()),
100                        ).into()
101                    )
102                } else {
103                    SimpleConsensusValidationResult::default()
104                }
105            }
106            KeyType::BIP13_SCRIPT_HASH => {
107                if !signature.is_empty() {
108                    SimpleConsensusValidationResult::new_with_error(
109                        SignatureError::SignatureShouldNotBePresentError(
110                            SignatureShouldNotBePresentError::new("script hash keys should not have a signature as that would reveal the script".to_string())
111                        ).into())
112                } else {
113                    SimpleConsensusValidationResult::default()
114                }
115            }
116            KeyType::EDDSA_25519_HASH160 => {
117                if !signature.is_empty() {
118                    SimpleConsensusValidationResult::new_with_error(
119                        SignatureError::SignatureShouldNotBePresentError(
120                            SignatureShouldNotBePresentError::new("eddsa hash 160 keys should not have a signature as that would reveal the script".to_string())
121                        ).into()
122                    )
123                } else {
124                    SimpleConsensusValidationResult::default()
125                }
126            }
127        }
128    }
129    #[cfg(feature = "message-signing")]
130    fn sign_by_private_key(
131        &self,
132        private_key: &[u8],
133        key_type: KeyType,
134        bls: &impl BlsModule,
135    ) -> Result<Vec<u8>, ProtocolError> {
136        match key_type {
137            KeyType::BLS12_381 => Ok(bls.sign(self, private_key)?),
138
139            // https://github.com/dashevo/platform/blob/9c8e6a3b6afbc330a6ab551a689de8ccd63f9120/packages/js-dpp/lib/stateTransition/AbstractStateTransition.js#L169
140            KeyType::ECDSA_SECP256K1 | KeyType::ECDSA_HASH160 => {
141                let signature = signer::sign(self, private_key)?;
142                Ok(signature.to_vec())
143            }
144
145            // the default behavior from
146            // https://github.com/dashevo/platform/blob/6b02b26e5cd3a7c877c5fdfe40c4a4385a8dda15/packages/js-dpp/lib/stateTransition/AbstractStateTransition.js#L187
147            // is to return the error for the BIP13_SCRIPT_HASH
148            KeyType::BIP13_SCRIPT_HASH | KeyType::EDDSA_25519_HASH160 => {
149                Err(ProtocolError::InvalidSigningKeyTypeError(format!(
150                    "key type {} can not sign",
151                    key_type
152                )))
153            }
154        }
155    }
156}