use crate::{
env::internal::{self, BytesObject},
unwrap::UnwrapInfallible,
Bytes, BytesN, ConversionError, Env, IntoVal, TryFromVal, Val,
};
pub mod bls12_381;
#[derive(Clone)]
#[repr(transparent)]
pub struct Hash<const N: usize>(BytesN<N>);
impl<const N: usize> Hash<N> {
#[cfg(test)]
pub(crate) fn from_bytes(bytes: BytesN<N>) -> Self {
Self(bytes)
}
#[inline(always)]
pub fn to_bytes(&self) -> BytesN<N> {
self.0.clone()
}
#[inline(always)]
pub fn to_array(&self) -> [u8; N] {
self.0.to_array()
}
pub fn as_val(&self) -> &Val {
self.0.as_val()
}
pub fn to_val(&self) -> Val {
self.0.to_val()
}
pub fn as_object(&self) -> &BytesObject {
self.0.as_object()
}
pub fn to_object(&self) -> BytesObject {
self.0.to_object()
}
}
impl<const N: usize> IntoVal<Env, Val> for Hash<N> {
fn into_val(&self, e: &Env) -> Val {
self.0.into_val(e)
}
}
impl<const N: usize> IntoVal<Env, BytesN<N>> for Hash<N> {
fn into_val(&self, _e: &Env) -> BytesN<N> {
self.0.clone()
}
}
impl<const N: usize> From<Hash<N>> for Bytes {
fn from(v: Hash<N>) -> Self {
v.0.into()
}
}
impl<const N: usize> From<Hash<N>> for BytesN<N> {
fn from(v: Hash<N>) -> Self {
v.0
}
}
impl<const N: usize> Into<[u8; N]> for Hash<N> {
fn into(self) -> [u8; N] {
self.0.into()
}
}
#[allow(deprecated)]
impl<const N: usize> crate::TryFromValForContractFn<Env, Val> for Hash<N> {
type Error = ConversionError;
fn try_from_val_for_contract_fn(env: &Env, v: &Val) -> Result<Self, Self::Error> {
Ok(Hash(BytesN::<N>::try_from_val(env, v)?))
}
}
pub struct Crypto {
env: Env,
}
impl Crypto {
pub(crate) fn new(env: &Env) -> Crypto {
Crypto { env: env.clone() }
}
pub fn env(&self) -> &Env {
&self.env
}
pub fn sha256(&self, data: &Bytes) -> Hash<32> {
let env = self.env();
let bin = internal::Env::compute_hash_sha256(env, data.into()).unwrap_infallible();
unsafe { Hash(BytesN::unchecked_new(env.clone(), bin)) }
}
pub fn keccak256(&self, data: &Bytes) -> Hash<32> {
let env = self.env();
let bin = internal::Env::compute_hash_keccak256(env, data.into()).unwrap_infallible();
unsafe { Hash(BytesN::unchecked_new(env.clone(), bin)) }
}
pub fn ed25519_verify(&self, public_key: &BytesN<32>, message: &Bytes, signature: &BytesN<64>) {
let env = self.env();
let _ = internal::Env::verify_sig_ed25519(
env,
public_key.to_object(),
message.to_object(),
signature.to_object(),
);
}
pub fn secp256k1_recover(
&self,
message_digest: &Hash<32>,
signature: &BytesN<64>,
recorvery_id: u32,
) -> BytesN<65> {
let env = self.env();
CryptoHazmat::new(env).secp256k1_recover(&message_digest.0, signature, recorvery_id)
}
pub fn secp256r1_verify(
&self,
public_key: &BytesN<65>,
message_digest: &Hash<32>,
signature: &BytesN<64>,
) {
let env = self.env();
CryptoHazmat::new(env).secp256r1_verify(public_key, &message_digest.0, signature)
}
pub fn bls12_381(&self) -> bls12_381::Bls12_381 {
bls12_381::Bls12_381::new(self.env())
}
}
#[cfg_attr(any(test, feature = "hazmat-crypto"), visibility::make(pub))]
#[cfg_attr(feature = "docs", doc(cfg(feature = "hazmat-crypto")))]
pub(crate) struct CryptoHazmat {
env: Env,
}
impl CryptoHazmat {
pub(crate) fn new(env: &Env) -> CryptoHazmat {
CryptoHazmat { env: env.clone() }
}
pub fn env(&self) -> &Env {
&self.env
}
pub fn secp256k1_recover(
&self,
message_digest: &BytesN<32>,
signature: &BytesN<64>,
recorvery_id: u32,
) -> BytesN<65> {
let env = self.env();
let bytes = internal::Env::recover_key_ecdsa_secp256k1(
env,
message_digest.to_object(),
signature.to_object(),
recorvery_id.into(),
)
.unwrap_infallible();
unsafe { BytesN::unchecked_new(env.clone(), bytes) }
}
pub fn secp256r1_verify(
&self,
public_key: &BytesN<65>,
message_digest: &BytesN<32>,
signature: &BytesN<64>,
) {
let env = self.env();
let _ = internal::Env::verify_sig_ecdsa_secp256r1(
env,
public_key.to_object(),
message_digest.to_object(),
signature.to_object(),
)
.unwrap_infallible();
}
}