mirror of
https://github.com/logos-blockchain/logos-execution-zone.git
synced 2026-03-26 12:13:08 +00:00
Merge 8a6409d43bb33c89d6d77da3097c31a640565e06 into fb083ce91ec10487fc17137a48c47f4322f9c768
This commit is contained in:
commit
72ff3c64fa
@ -8,8 +8,6 @@ license = { workspace = true }
|
|||||||
workspace = true
|
workspace = true
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
secp256k1 = "0.31.1"
|
|
||||||
|
|
||||||
nssa.workspace = true
|
nssa.workspace = true
|
||||||
nssa_core.workspace = true
|
nssa_core.workspace = true
|
||||||
common.workspace = true
|
common.workspace = true
|
||||||
|
|||||||
@ -137,13 +137,13 @@ impl<'a> From<&'a mut ChildKeysPrivate> for &'a mut (KeyChain, nssa::Account) {
|
|||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use nssa_core::NullifierSecretKey;
|
use nssa_core::{NullifierPublicKey, NullifierSecretKey};
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::key_management::{self, secret_holders::ViewingSecretKey};
|
use crate::key_management::{self, secret_holders::ViewingSecretKey};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn master_key_generation() {
|
fn test_master_key_generation() {
|
||||||
let seed: [u8; 64] = [
|
let seed: [u8; 64] = [
|
||||||
252, 56, 204, 83, 232, 123, 209, 188, 187, 167, 39, 213, 71, 39, 58, 65, 125, 134, 255,
|
252, 56, 204, 83, 232, 123, 209, 188, 187, 167, 39, 213, 71, 39, 58, 65, 125, 134, 255,
|
||||||
49, 43, 108, 92, 53, 173, 164, 94, 142, 150, 74, 21, 163, 43, 144, 226, 87, 199, 18,
|
49, 43, 108, 92, 53, 173, 164, 94, 142, 150, 74, 21, 163, 43, 144, 226, 87, 199, 18,
|
||||||
@ -153,7 +153,7 @@ mod tests {
|
|||||||
|
|
||||||
let keys = ChildKeysPrivate::root(seed);
|
let keys = ChildKeysPrivate::root(seed);
|
||||||
|
|
||||||
let expected_ssk = key_management::secret_holders::SecretSpendingKey([
|
let expected_ssk: SecretSpendingKey = key_management::secret_holders::SecretSpendingKey([
|
||||||
246, 79, 26, 124, 135, 95, 52, 51, 201, 27, 48, 194, 2, 144, 51, 219, 245, 128, 139,
|
246, 79, 26, 124, 135, 95, 52, 51, 201, 27, 48, 194, 2, 144, 51, 219, 245, 128, 139,
|
||||||
222, 42, 195, 105, 33, 115, 97, 186, 0, 97, 14, 218, 191,
|
222, 42, 195, 105, 33, 115, 97, 186, 0, 97, 14, 218, 191,
|
||||||
]);
|
]);
|
||||||
@ -168,7 +168,7 @@ mod tests {
|
|||||||
34, 234, 19, 222, 2, 22, 12, 163, 252, 88, 11, 0, 163,
|
34, 234, 19, 222, 2, 22, 12, 163, 252, 88, 11, 0, 163,
|
||||||
];
|
];
|
||||||
|
|
||||||
let expected_npk = nssa_core::NullifierPublicKey([
|
let expected_npk: NullifierPublicKey = nssa_core::NullifierPublicKey([
|
||||||
7, 123, 125, 191, 233, 183, 201, 4, 20, 214, 155, 210, 45, 234, 27, 240, 194, 111, 97,
|
7, 123, 125, 191, 233, 183, 201, 4, 20, 214, 155, 210, 45, 234, 27, 240, 194, 111, 97,
|
||||||
247, 155, 113, 122, 246, 192, 0, 70, 61, 76, 71, 70, 2,
|
247, 155, 113, 122, 246, 192, 0, 70, 61, 76, 71, 70, 2,
|
||||||
]);
|
]);
|
||||||
@ -191,7 +191,7 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn child_keys_generation() {
|
fn test_child_keys_generation() {
|
||||||
let seed: [u8; 64] = [
|
let seed: [u8; 64] = [
|
||||||
252, 56, 204, 83, 232, 123, 209, 188, 187, 167, 39, 213, 71, 39, 58, 65, 125, 134, 255,
|
252, 56, 204, 83, 232, 123, 209, 188, 187, 167, 39, 213, 71, 39, 58, 65, 125, 134, 255,
|
||||||
49, 43, 108, 92, 53, 173, 164, 94, 142, 150, 74, 21, 163, 43, 144, 226, 87, 199, 18,
|
49, 43, 108, 92, 53, 173, 164, 94, 142, 150, 74, 21, 163, 43, 144, 226, 87, 199, 18,
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
use secp256k1::Scalar;
|
use k256::elliptic_curve::{PrimeField as _, sec1::ToEncodedPoint as _};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use crate::key_management::key_tree::traits::KeyNode;
|
use crate::key_management::key_tree::traits::KeyNode;
|
||||||
@ -13,7 +13,6 @@ pub struct ChildKeysPublic {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl ChildKeysPublic {
|
impl ChildKeysPublic {
|
||||||
#[expect(clippy::big_endian_bytes, reason = "BIP-032 uses big endian")]
|
|
||||||
fn compute_hash_value(&self, cci: u32) -> [u8; 64] {
|
fn compute_hash_value(&self, cci: u32) -> [u8; 64] {
|
||||||
let mut hash_input = vec![];
|
let mut hash_input = vec![];
|
||||||
|
|
||||||
@ -21,10 +20,10 @@ impl ChildKeysPublic {
|
|||||||
// Non-harden.
|
// Non-harden.
|
||||||
// BIP-032 compatibility requires 1-byte header from the public_key;
|
// BIP-032 compatibility requires 1-byte header from the public_key;
|
||||||
// Not stored in `self.cpk.value()`.
|
// Not stored in `self.cpk.value()`.
|
||||||
let sk = secp256k1::SecretKey::from_byte_array(*self.csk.value())
|
let sk = k256::SecretKey::from_bytes(self.csk.value().into())
|
||||||
.expect("32 bytes, within curve order");
|
.expect("32 bytes, within curve order");
|
||||||
let pk = secp256k1::PublicKey::from_secret_key(&secp256k1::Secp256k1::new(), &sk);
|
let pk = sk.public_key();
|
||||||
hash_input.extend_from_slice(&secp256k1::PublicKey::serialize(&pk));
|
hash_input.extend_from_slice(&pk.to_encoded_point(true).as_bytes());
|
||||||
} else {
|
} else {
|
||||||
// Harden.
|
// Harden.
|
||||||
hash_input.extend_from_slice(&[0_u8]);
|
hash_input.extend_from_slice(&[0_u8]);
|
||||||
@ -41,7 +40,12 @@ impl KeyNode for ChildKeysPublic {
|
|||||||
fn root(seed: [u8; 64]) -> Self {
|
fn root(seed: [u8; 64]) -> Self {
|
||||||
let hash_value = hmac_sha512::HMAC::mac(seed, "LEE_master_pub");
|
let hash_value = hmac_sha512::HMAC::mac(seed, "LEE_master_pub");
|
||||||
|
|
||||||
let csk = nssa::PrivateKey::try_new(*hash_value.first_chunk::<32>().unwrap()).unwrap();
|
let csk = nssa::PrivateKey::try_new(
|
||||||
|
*hash_value
|
||||||
|
.first_chunk::<32>()
|
||||||
|
.expect("hash_value is 64 bytes, must be safe to get first 32"),
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
let ccc = *hash_value.last_chunk::<32>().unwrap();
|
let ccc = *hash_value.last_chunk::<32>().unwrap();
|
||||||
let cpk = nssa::PublicKey::new_from_private_key(&csk);
|
let cpk = nssa::PublicKey::new_from_private_key(&csk);
|
||||||
|
|
||||||
@ -56,26 +60,20 @@ impl KeyNode for ChildKeysPublic {
|
|||||||
fn nth_child(&self, cci: u32) -> Self {
|
fn nth_child(&self, cci: u32) -> Self {
|
||||||
let hash_value = self.compute_hash_value(cci);
|
let hash_value = self.compute_hash_value(cci);
|
||||||
|
|
||||||
let csk = secp256k1::SecretKey::from_byte_array(
|
|
||||||
*hash_value
|
|
||||||
.first_chunk::<32>()
|
|
||||||
.expect("hash_value is 64 bytes, must be safe to get first 32"),
|
|
||||||
)
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
let csk = nssa::PrivateKey::try_new({
|
let csk = nssa::PrivateKey::try_new({
|
||||||
let scalar = Scalar::from_be_bytes(*self.csk.value()).unwrap();
|
let hash_value = hash_value
|
||||||
|
.first_chunk::<32>()
|
||||||
|
.expect("hash_value is 64 bytes, must be safe to get first 32");
|
||||||
|
|
||||||
csk.add_tweak(&scalar)
|
let value_1 =
|
||||||
.expect("Expect a valid Scalar")
|
k256::Scalar::from_repr((*hash_value).into()).expect("Expect a valid k256 scalar");
|
||||||
.secret_bytes()
|
let value_2 = k256::Scalar::from_repr((*self.csk.value()).into())
|
||||||
|
.expect("Expect a valid k256 scalar");
|
||||||
|
|
||||||
|
let sum = value_1.add(&value_2);
|
||||||
|
sum.to_bytes().into()
|
||||||
})
|
})
|
||||||
.unwrap();
|
.expect("Expect a valid private key");
|
||||||
|
|
||||||
assert!(
|
|
||||||
secp256k1::constants::CURVE_ORDER >= *csk.value(),
|
|
||||||
"Secret key cannot exceed curve order"
|
|
||||||
);
|
|
||||||
|
|
||||||
let ccc = *hash_value
|
let ccc = *hash_value
|
||||||
.last_chunk::<32>()
|
.last_chunk::<32>()
|
||||||
@ -121,7 +119,7 @@ mod tests {
|
|||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn master_keys_generation() {
|
fn test_master_keys_generation() {
|
||||||
let seed = [
|
let seed = [
|
||||||
88, 189, 37, 237, 199, 125, 151, 226, 69, 153, 165, 113, 191, 69, 188, 221, 9, 34, 173,
|
88, 189, 37, 237, 199, 125, 151, 226, 69, 153, 165, 113, 191, 69, 188, 221, 9, 34, 173,
|
||||||
134, 61, 109, 34, 103, 121, 39, 237, 14, 107, 194, 24, 194, 191, 14, 237, 185, 12, 87,
|
134, 61, 109, 34, 103, 121, 39, 237, 14, 107, 194, 24, 194, 191, 14, 237, 185, 12, 87,
|
||||||
@ -153,7 +151,7 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn harden_child_keys_generation() {
|
fn test_harden_child_keys_generation() {
|
||||||
let seed = [
|
let seed = [
|
||||||
88, 189, 37, 237, 199, 125, 151, 226, 69, 153, 165, 113, 191, 69, 188, 221, 9, 34, 173,
|
88, 189, 37, 237, 199, 125, 151, 226, 69, 153, 165, 113, 191, 69, 188, 221, 9, 34, 173,
|
||||||
134, 61, 109, 34, 103, 121, 39, 237, 14, 107, 194, 24, 194, 191, 14, 237, 185, 12, 87,
|
134, 61, 109, 34, 103, 121, 39, 237, 14, 107, 194, 24, 194, 191, 14, 237, 185, 12, 87,
|
||||||
@ -187,7 +185,7 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn nonharden_child_keys_generation() {
|
fn test_nonharden_child_keys_generation() {
|
||||||
let seed = [
|
let seed = [
|
||||||
88, 189, 37, 237, 199, 125, 151, 226, 69, 153, 165, 113, 191, 69, 188, 221, 9, 34, 173,
|
88, 189, 37, 237, 199, 125, 151, 226, 69, 153, 165, 113, 191, 69, 188, 221, 9, 34, 173,
|
||||||
134, 61, 109, 34, 103, 121, 39, 237, 14, 107, 194, 24, 194, 191, 14, 237, 185, 12, 87,
|
134, 61, 109, 34, 103, 121, 39, 237, 14, 107, 194, 24, 194, 191, 14, 237, 185, 12, 87,
|
||||||
@ -221,7 +219,7 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn edge_case_child_keys_generation_2_power_31() {
|
fn test_edge_case_child_keys_generation_2_power_31() {
|
||||||
let seed = [
|
let seed = [
|
||||||
88, 189, 37, 237, 199, 125, 151, 226, 69, 153, 165, 113, 191, 69, 188, 221, 9, 34, 173,
|
88, 189, 37, 237, 199, 125, 151, 226, 69, 153, 165, 113, 191, 69, 188, 221, 9, 34, 173,
|
||||||
134, 61, 109, 34, 103, 121, 39, 237, 14, 107, 194, 24, 194, 191, 14, 237, 185, 12, 87,
|
134, 61, 109, 34, 103, 121, 39, 237, 14, 107, 194, 24, 194, 191, 14, 237, 185, 12, 87,
|
||||||
|
|||||||
@ -19,7 +19,7 @@ sha2.workspace = true
|
|||||||
rand.workspace = true
|
rand.workspace = true
|
||||||
borsh.workspace = true
|
borsh.workspace = true
|
||||||
hex.workspace = true
|
hex.workspace = true
|
||||||
secp256k1 = "0.31.1"
|
k256.workspace = true
|
||||||
risc0-binfmt = "3.0.2"
|
risc0-binfmt = "3.0.2"
|
||||||
log.workspace = true
|
log.workspace = true
|
||||||
|
|
||||||
|
|||||||
@ -29,7 +29,10 @@ pub enum NssaError {
|
|||||||
Io(#[from] io::Error),
|
Io(#[from] io::Error),
|
||||||
|
|
||||||
#[error("Invalid Public Key")]
|
#[error("Invalid Public Key")]
|
||||||
InvalidPublicKey(#[source] secp256k1::Error),
|
InvalidPublicKey(#[source] k256::schnorr::Error),
|
||||||
|
|
||||||
|
#[error("Invalid hex for public key")]
|
||||||
|
InvalidHexPublicKey(hex::FromHexError),
|
||||||
|
|
||||||
#[error("Risc0 error: {0}")]
|
#[error("Risc0 error: {0}")]
|
||||||
ProgramWriteInputFailed(String),
|
ProgramWriteInputFailed(String),
|
||||||
|
|||||||
@ -49,21 +49,28 @@ impl Signature {
|
|||||||
aux_random: [u8; 32],
|
aux_random: [u8; 32],
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let value = {
|
let value = {
|
||||||
let secp = secp256k1::Secp256k1::new();
|
let signing_key = k256::schnorr::SigningKey::from_bytes(key.value())
|
||||||
let secret_key = secp256k1::SecretKey::from_byte_array(*key.value()).unwrap();
|
.expect("Expect valid signing key");
|
||||||
let keypair = secp256k1::Keypair::from_secret_key(&secp, &secret_key);
|
signing_key
|
||||||
let signature = secp.sign_schnorr_with_aux_rand(message, &keypair, &aux_random);
|
.sign_raw(message, &aux_random)
|
||||||
signature.to_byte_array()
|
.expect("Expect to produce a valid signature")
|
||||||
|
.to_bytes()
|
||||||
};
|
};
|
||||||
|
|
||||||
Self { value }
|
Self { value }
|
||||||
}
|
}
|
||||||
|
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn is_valid_for(&self, bytes: &[u8], public_key: &PublicKey) -> bool {
|
pub fn is_valid_for(&self, bytes: &[u8], public_key: &PublicKey) -> bool {
|
||||||
let pk = secp256k1::XOnlyPublicKey::from_byte_array(*public_key.value()).unwrap();
|
let Ok(pk) = k256::schnorr::VerifyingKey::from_bytes(public_key.value()) else {
|
||||||
let secp = secp256k1::Secp256k1::new();
|
return false;
|
||||||
let sig = secp256k1::schnorr::Signature::from_byte_array(self.value);
|
};
|
||||||
secp.verify_schnorr(&sig, bytes, &pk).is_ok()
|
|
||||||
|
let Ok(sig) = k256::schnorr::Signature::try_from(self.value.as_slice()) else {
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
pk.verify_raw(bytes, &sig).is_ok()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -45,7 +45,7 @@ impl PrivateKey {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn is_valid_key(value: [u8; 32]) -> bool {
|
fn is_valid_key(value: [u8; 32]) -> bool {
|
||||||
secp256k1::SecretKey::from_byte_array(value).is_ok()
|
k256::SecretKey::from_bytes(&value.into()).is_ok()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn try_new(value: [u8; 32]) -> Result<Self, NssaError> {
|
pub fn try_new(value: [u8; 32]) -> Result<Self, NssaError> {
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
|
||||||
use borsh::{BorshDeserialize, BorshSerialize};
|
use borsh::{BorshDeserialize, BorshSerialize};
|
||||||
|
use k256::elliptic_curve::sec1::ToEncodedPoint as _;
|
||||||
use nssa_core::account::AccountId;
|
use nssa_core::account::AccountId;
|
||||||
use serde_with::{DeserializeFromStr, SerializeDisplay};
|
use serde_with::{DeserializeFromStr, SerializeDisplay};
|
||||||
use sha2::{Digest as _, Sha256};
|
use sha2::{Digest as _, Sha256};
|
||||||
@ -27,8 +28,7 @@ impl FromStr for PublicKey {
|
|||||||
|
|
||||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||||
let mut bytes = [0_u8; 32];
|
let mut bytes = [0_u8; 32];
|
||||||
hex::decode_to_slice(s, &mut bytes)
|
hex::decode_to_slice(s, &mut bytes).map_err(NssaError::InvalidHexPublicKey)?;
|
||||||
.map_err(|_err| NssaError::InvalidPublicKey(secp256k1::Error::InvalidPublicKey))?;
|
|
||||||
Self::try_new(bytes)
|
Self::try_new(bytes)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -46,19 +46,24 @@ impl PublicKey {
|
|||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn new_from_private_key(key: &PrivateKey) -> Self {
|
pub fn new_from_private_key(key: &PrivateKey) -> Self {
|
||||||
let value = {
|
let value = {
|
||||||
let secret_key = secp256k1::SecretKey::from_byte_array(*key.value()).unwrap();
|
let secret_key = k256::SecretKey::from_bytes(&(*key.value()).into())
|
||||||
let public_key =
|
.expect("Expect a valid private key");
|
||||||
secp256k1::PublicKey::from_secret_key(&secp256k1::Secp256k1::new(), &secret_key);
|
|
||||||
let (x_only, _) = public_key.x_only_public_key();
|
let encoded = secret_key.public_key().to_encoded_point(false);
|
||||||
x_only.serialize()
|
let x_only = encoded
|
||||||
|
.x()
|
||||||
|
.expect("Expect k256 point to have a x-coordinate");
|
||||||
|
|
||||||
|
*x_only.first_chunk().expect("x_only is exactly 32 bytes")
|
||||||
};
|
};
|
||||||
Self(value)
|
Self(value)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn try_new(value: [u8; 32]) -> Result<Self, NssaError> {
|
pub fn try_new(value: [u8; 32]) -> Result<Self, NssaError> {
|
||||||
// Check point is valid
|
// Check point is a valid x-only public key
|
||||||
let _ = secp256k1::XOnlyPublicKey::from_byte_array(value)
|
let _ =
|
||||||
.map_err(NssaError::InvalidPublicKey)?;
|
k256::schnorr::VerifyingKey::from_bytes(&value).map_err(NssaError::InvalidPublicKey)?;
|
||||||
|
|
||||||
Ok(Self(value))
|
Ok(Self(value))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user