103 lines
3.4 KiB
Rust
103 lines
3.4 KiB
Rust
// Copyright 2019-2025 Parity Technologies (UK) Ltd.
|
|
// This file is dual-licensed as Apache-2.0 or GPL-3.0.
|
|
// see LICENSE for license details.
|
|
|
|
use codec::{Decode, Encode};
|
|
|
|
// This code is taken from sp_core::crypto::DeriveJunction. The logic should be identical,
|
|
// though the API is tweaked a touch.
|
|
|
|
/// The length of the junction identifier. Note that this is also referred to as the
|
|
/// `CHAIN_CODE_LENGTH` in the context of Schnorrkel.
|
|
pub const JUNCTION_ID_LEN: usize = 32;
|
|
|
|
/// A since derivation junction description. It is the single parameter used when creating
|
|
/// a new secret key from an existing secret key and, in the case of `SoftRaw` and `SoftIndex`
|
|
/// a new public key from an existing public key.
|
|
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug, Encode, Decode)]
|
|
pub enum DeriveJunction {
|
|
/// Soft (vanilla) derivation. Public keys have a correspondent derivation.
|
|
Soft([u8; JUNCTION_ID_LEN]),
|
|
/// Hard ("hardened") derivation. Public keys do not have a correspondent derivation.
|
|
Hard([u8; JUNCTION_ID_LEN]),
|
|
}
|
|
|
|
impl DeriveJunction {
|
|
/// Consume self to return a soft derive junction with the same chain code.
|
|
pub fn soften(self) -> Self {
|
|
DeriveJunction::Soft(self.into_inner())
|
|
}
|
|
|
|
/// Consume self to return a hard derive junction with the same chain code.
|
|
pub fn harden(self) -> Self {
|
|
DeriveJunction::Hard(self.into_inner())
|
|
}
|
|
|
|
/// Create a new soft (vanilla) DeriveJunction from a given, encodable, value.
|
|
///
|
|
/// If you need a hard junction, use `hard()`.
|
|
pub fn soft<T: Encode>(index: T) -> Self {
|
|
let mut cc: [u8; JUNCTION_ID_LEN] = Default::default();
|
|
index.using_encoded(|data| {
|
|
if data.len() > JUNCTION_ID_LEN {
|
|
cc.copy_from_slice(&pezsp_crypto_hashing::blake2_256(data));
|
|
} else {
|
|
cc[0..data.len()].copy_from_slice(data);
|
|
}
|
|
});
|
|
DeriveJunction::Soft(cc)
|
|
}
|
|
|
|
/// Create a new hard (hardened) DeriveJunction from a given, encodable, value.
|
|
///
|
|
/// If you need a soft junction, use `soft()`.
|
|
pub fn hard<T: Encode>(index: T) -> Self {
|
|
Self::soft(index).harden()
|
|
}
|
|
|
|
/// Consume self to return the chain code.
|
|
pub fn into_inner(self) -> [u8; JUNCTION_ID_LEN] {
|
|
match self {
|
|
DeriveJunction::Hard(c) | DeriveJunction::Soft(c) => c,
|
|
}
|
|
}
|
|
|
|
/// Get a reference to the inner junction id.
|
|
pub fn inner(&self) -> &[u8; JUNCTION_ID_LEN] {
|
|
match self {
|
|
DeriveJunction::Hard(c) | DeriveJunction::Soft(c) => c,
|
|
}
|
|
}
|
|
|
|
/// Return `true` if the junction is soft.
|
|
pub fn is_soft(&self) -> bool {
|
|
matches!(*self, DeriveJunction::Soft(_))
|
|
}
|
|
|
|
/// Return `true` if the junction is hard.
|
|
pub fn is_hard(&self) -> bool {
|
|
matches!(*self, DeriveJunction::Hard(_))
|
|
}
|
|
}
|
|
|
|
impl<T: AsRef<str>> From<T> for DeriveJunction {
|
|
fn from(j: T) -> DeriveJunction {
|
|
let j = j.as_ref();
|
|
let (code, hard) = if let Some(stripped) = j.strip_prefix('/') {
|
|
(stripped, true)
|
|
} else {
|
|
(j, false)
|
|
};
|
|
|
|
let res = if let Ok(n) = str::parse::<u64>(code) {
|
|
// number
|
|
DeriveJunction::soft(n)
|
|
} else {
|
|
// something else
|
|
DeriveJunction::soft(code)
|
|
};
|
|
|
|
if hard { res.harden() } else { res }
|
|
}
|
|
}
|