Skip to content

Commit

Permalink
feat: add try_from slice for signature & keys (#1145)
Browse files Browse the repository at this point in the history
This commit introduces a trait bound requirement for PublicKey and
Signature that will allow it to be recreated from bytes.

Prior to this commit, such implementation existed only for `FromStr` in
native. However, in some cases - such as in the wallet - the public keys
will be recreated from raw bytes computed from 3rd party libraries. The
serialization of such crypto primitives is a standard, so they can
safely interop with our implementations.
  • Loading branch information
vlopes11 authored Nov 13, 2023
1 parent ed0ae8d commit df169be
Show file tree
Hide file tree
Showing 3 changed files with 61 additions and 17 deletions.
36 changes: 35 additions & 1 deletion module-system/sov-modules-api/src/default_signature.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ use std::str::FromStr;

use borsh::{BorshDeserialize, BorshSerialize};
use ed25519_dalek::{
Signature as DalekSignature, VerifyingKey as DalekPublicKey, PUBLIC_KEY_LENGTH,
Signature as DalekSignature, SigningKey, VerifyingKey as DalekPublicKey, KEYPAIR_LENGTH,
PUBLIC_KEY_LENGTH,
};
use sov_modules_core::{SigVerificationError, Signature};

Expand Down Expand Up @@ -198,6 +199,29 @@ impl BorshSerialize for DefaultPublicKey {
}
}

impl TryFrom<&[u8]> for DefaultPublicKey {
type Error = anyhow::Error;

fn try_from(value: &[u8]) -> Result<Self, Self::Error> {
if value.len() == KEYPAIR_LENGTH {
let mut keypair = [0u8; KEYPAIR_LENGTH];
keypair.copy_from_slice(value);
let keypair = SigningKey::from_keypair_bytes(&keypair).map_err(anyhow::Error::msg)?;
Ok(Self {
pub_key: keypair.verifying_key(),
})
} else if value.len() == PUBLIC_KEY_LENGTH {
let mut public = [0u8; PUBLIC_KEY_LENGTH];
public.copy_from_slice(value);
Ok(Self {
pub_key: DalekPublicKey::from_bytes(&public).map_err(anyhow::Error::msg)?,
})
} else {
anyhow::bail!("Unexpected public key length")
}
}
}

#[cfg_attr(feature = "native", derive(schemars::JsonSchema))]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[derive(PartialEq, Eq, Debug, Clone)]
Expand Down Expand Up @@ -226,6 +250,16 @@ impl BorshSerialize for DefaultSignature {
}
}

impl TryFrom<&[u8]> for DefaultSignature {
type Error = anyhow::Error;

fn try_from(value: &[u8]) -> Result<Self, Self::Error> {
Ok(Self {
msg_sig: DalekSignature::from_slice(value).map_err(anyhow::Error::msg)?,
})
}
}

impl Signature for DefaultSignature {
type PublicKey = DefaultPublicKey;

Expand Down
30 changes: 15 additions & 15 deletions module-system/sov-modules-api/src/transaction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,21 @@ impl<C: Context> Transaction<C> {

Ok(())
}

/// New transaction.
pub fn new(
pub_key: C::PublicKey,
message: Vec<u8>,
signature: C::Signature,
nonce: u64,
) -> Self {
Self {
signature,
runtime_msg: message,
pub_key,
nonce,
}
}
}

#[cfg(feature = "native")]
Expand All @@ -67,19 +82,4 @@ impl<C: Context> Transaction<C> {
nonce,
}
}

/// New transaction.
pub fn new(
pub_key: C::PublicKey,
message: Vec<u8>,
signature: C::Signature,
nonce: u64,
) -> Self {
Self {
signature,
runtime_msg: message,
pub_key,
nonce,
}
}
}
12 changes: 11 additions & 1 deletion module-system/sov-modules-core/src/common/key.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,16 @@ use sov_rollup_interface::RollupAddress;
use crate::common::SigVerificationError;

/// Signature used in the Module System.
pub trait Signature: BorshDeserialize + BorshSerialize + Eq + Clone + Debug + Send + Sync {
pub trait Signature:
BorshDeserialize
+ BorshSerialize
+ for<'a> TryFrom<&'a [u8], Error = anyhow::Error>
+ Eq
+ Clone
+ Debug
+ Send
+ Sync
{
/// The public key associated with the key pair of the signature.
type PublicKey;

Expand All @@ -22,6 +31,7 @@ pub trait Signature: BorshDeserialize + BorshSerialize + Eq + Clone + Debug + Se
pub trait PublicKey:
BorshDeserialize
+ BorshSerialize
+ for<'a> TryFrom<&'a [u8], Error = anyhow::Error>
+ Eq
+ Hash
+ Clone
Expand Down

0 comments on commit df169be

Please sign in to comment.