Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
72 changes: 68 additions & 4 deletions packages/rs-dpp/src/identity/identity_public_key/key_type.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
#[cfg(feature = "random-public-keys")]
use crate::util::hash::ripemd160_sha256;
use anyhow::bail;
use bincode::{Decode, Encode};
Expand All @@ -8,16 +7,14 @@ use ciborium::value::Value as CborValue;
use dashcore::secp256k1::rand::rngs::StdRng as EcdsaRng;
#[cfg(feature = "random-public-keys")]
use dashcore::secp256k1::rand::SeedableRng;
#[cfg(feature = "random-public-keys")]
use dashcore::secp256k1::Secp256k1;
#[cfg(feature = "random-public-keys")]
use dashcore::Network;
use itertools::Itertools;
use lazy_static::lazy_static;

use crate::fee::Credits;
use crate::version::PlatformVersion;
use crate::ProtocolError;
use crate::{InvalidVectorSizeError, ProtocolError};
#[cfg(feature = "random-public-keys")]
use rand::rngs::StdRng;
#[cfg(feature = "random-public-keys")]
Expand Down Expand Up @@ -204,6 +201,73 @@ impl KeyType {
}
}

/// Gets the public key data for a private key depending on the key type
pub fn public_key_data_from_private_key_data(
&self,
private_key_bytes: &[u8],
network: Network,
) -> Result<Vec<u8>, ProtocolError> {
match self {
KeyType::ECDSA_SECP256K1 => {
let secp = Secp256k1::new();
let secret_key = dashcore::secp256k1::SecretKey::from_slice(private_key_bytes)
.map_err(|e| ProtocolError::Generic(e.to_string()))?;
let private_key = dashcore::PrivateKey::new(secret_key, network);

Ok(private_key.public_key(&secp).to_bytes())
}
KeyType::BLS12_381 => {
#[cfg(feature = "bls-signatures")]
{
let private_key =
bls_signatures::PrivateKey::from_bytes(private_key_bytes, false)
.map_err(|e| ProtocolError::Generic(e.to_string()))?;
let public_key_bytes = private_key
.g1_element()
.expect("expected to get a public key from a bls private key")
.to_bytes()
.to_vec();
Ok(public_key_bytes)
}
#[cfg(not(feature = "bls-signatures"))]
return Err(ProtocolError::NotSupported(
"Converting a private key to a bls public key is not supported without the bls-signatures feature".to_string(),
));
}
Comment on lines +219 to +236
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Improve error handling in BLS12_381 implementation

The BLS12_381 implementation is generally correct, but there's room for improvement in error handling:

  1. The use of expect() when calling g1_element() could lead to a panic. Consider using map_err() to convert any error to a ProtocolError instead.

  2. The error handling for the not(feature = "bls-signatures") case is good, returning a NotSupported error.

Consider replacing the expect() call with proper error handling:

-    let public_key_bytes = private_key
-        .g1_element()
-        .expect("expected to get a public key from a bls private key")
-        .to_bytes()
-        .to_vec();
+    let public_key_bytes = private_key
+        .g1_element()
+        .map_err(|e| ProtocolError::Generic(e.to_string()))?
+        .to_bytes()
+        .to_vec();

This change will propagate any errors from g1_element() as a ProtocolError instead of panicking.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
KeyType::BLS12_381 => {
#[cfg(feature = "bls-signatures")]
{
let private_key =
bls_signatures::PrivateKey::from_bytes(private_key_bytes, false)
.map_err(|e| ProtocolError::Generic(e.to_string()))?;
let public_key_bytes = private_key
.g1_element()
.expect("expected to get a public key from a bls private key")
.to_bytes()
.to_vec();
Ok(public_key_bytes)
}
#[cfg(not(feature = "bls-signatures"))]
return Err(ProtocolError::NotSupported(
"Converting a private key to a bls public key is not supported without the bls-signatures feature".to_string(),
));
}
KeyType::BLS12_381 => {
#[cfg(feature = "bls-signatures")]
{
let private_key =
bls_signatures::PrivateKey::from_bytes(private_key_bytes, false)
.map_err(|e| ProtocolError::Generic(e.to_string()))?;
let public_key_bytes = private_key
.g1_element()
.map_err(|e| ProtocolError::Generic(e.to_string()))?
.to_bytes()
.to_vec();
Ok(public_key_bytes)
}
#[cfg(not(feature = "bls-signatures"))]
return Err(ProtocolError::NotSupported(
"Converting a private key to a bls public key is not supported without the bls-signatures feature".to_string(),
));
}

KeyType::ECDSA_HASH160 => {
let secp = Secp256k1::new();
let secret_key = dashcore::secp256k1::SecretKey::from_slice(private_key_bytes)
.map_err(|e| ProtocolError::Generic(e.to_string()))?;
let private_key = dashcore::PrivateKey::new(secret_key, network);

Ok(ripemd160_sha256(private_key.public_key(&secp).to_bytes().as_slice()).to_vec())
}
KeyType::EDDSA_25519_HASH160 => {
#[cfg(feature = "ed25519-dalek")]
{
let key_pair = ed25519_dalek::SigningKey::from_bytes(
&private_key_bytes.try_into().map_err(|_| {
ProtocolError::InvalidVectorSizeError(InvalidVectorSizeError::new(
32,
private_key_bytes.len(),
))
})?,
);
Ok(ripemd160_sha256(key_pair.verifying_key().to_bytes().as_slice()).to_vec())
}
#[cfg(not(feature = "ed25519-dalek"))]
return Err(ProtocolError::NotSupported(
"Converting a private key to a eddsa hash 160 is not supported without the ed25519-dalek feature".to_string(),
));
}
KeyType::BIP13_SCRIPT_HASH => {
return Err(ProtocolError::NotSupported(
"Converting a private key to a script hash is not supported".to_string(),
));
}
}
}

#[cfg(feature = "random-public-keys")]
/// Gets the default size of the public key
pub fn random_public_and_private_key_data_v0(&self, rng: &mut StdRng) -> (Vec<u8>, Vec<u8>) {
Expand Down