mirror of https://github.com/zcash/zip32.git
Path derivation
This commit is contained in:
parent
e87fb329f9
commit
f5d6091c93
55
src/lib.rs
55
src/lib.rs
|
@ -50,6 +50,7 @@ impl OutgoingViewingKey {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A Sapling expanded spending key
|
/// A Sapling expanded spending key
|
||||||
|
#[derive(Clone)]
|
||||||
struct ExpandedSpendingKey<E: JubjubEngine> {
|
struct ExpandedSpendingKey<E: JubjubEngine> {
|
||||||
ask: E::Fs,
|
ask: E::Fs,
|
||||||
nsk: E::Fs,
|
nsk: E::Fs,
|
||||||
|
@ -226,6 +227,7 @@ impl DiversifierKey {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A Sapling extended spending key
|
/// A Sapling extended spending key
|
||||||
|
#[derive(Clone)]
|
||||||
pub struct ExtendedSpendingKey {
|
pub struct ExtendedSpendingKey {
|
||||||
depth: u8,
|
depth: u8,
|
||||||
parent_fvk_tag: FVKTag,
|
parent_fvk_tag: FVKTag,
|
||||||
|
@ -245,6 +247,29 @@ pub struct ExtendedFullViewingKey {
|
||||||
dk: DiversifierKey,
|
dk: DiversifierKey,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl std::cmp::PartialEq for ExtendedSpendingKey {
|
||||||
|
fn eq(&self, rhs: &ExtendedSpendingKey) -> bool {
|
||||||
|
self.depth == rhs.depth
|
||||||
|
&& self.parent_fvk_tag == rhs.parent_fvk_tag
|
||||||
|
&& self.child_index == rhs.child_index
|
||||||
|
&& self.chain_code == rhs.chain_code
|
||||||
|
&& self.xsk.ask == rhs.xsk.ask
|
||||||
|
&& self.xsk.nsk == rhs.xsk.nsk
|
||||||
|
&& self.xsk.ovk == rhs.xsk.ovk
|
||||||
|
&& self.dk == rhs.dk
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::fmt::Debug for ExtendedSpendingKey {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
|
||||||
|
write!(
|
||||||
|
f,
|
||||||
|
"ExtendedSpendingKey(d = {}, tag_p = {:?}, i = {:?})",
|
||||||
|
self.depth, self.parent_fvk_tag, self.child_index
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl std::cmp::PartialEq for ExtendedFullViewingKey {
|
impl std::cmp::PartialEq for ExtendedFullViewingKey {
|
||||||
fn eq(&self, rhs: &ExtendedFullViewingKey) -> bool {
|
fn eq(&self, rhs: &ExtendedFullViewingKey) -> bool {
|
||||||
self.depth == rhs.depth
|
self.depth == rhs.depth
|
||||||
|
@ -288,6 +313,15 @@ impl ExtendedSpendingKey {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns the child key corresponding to the path derived from the master key
|
||||||
|
pub fn from_path(master: &ExtendedSpendingKey, path: &[ChildIndex]) -> Self {
|
||||||
|
let mut xsk = master.clone();
|
||||||
|
for &i in path.iter() {
|
||||||
|
xsk = xsk.derive_child(i);
|
||||||
|
}
|
||||||
|
xsk
|
||||||
|
}
|
||||||
|
|
||||||
pub fn derive_child(&self, i: ChildIndex) -> Self {
|
pub fn derive_child(&self, i: ChildIndex) -> Self {
|
||||||
let fvk = FullViewingKey::from_expanded_spending_key(&self.xsk, &JUBJUB);
|
let fvk = FullViewingKey::from_expanded_spending_key(&self.xsk, &JUBJUB);
|
||||||
let tmp = match i {
|
let tmp = match i {
|
||||||
|
@ -404,4 +438,25 @@ mod tests {
|
||||||
assert!(xfvk_5h_7.is_ok());
|
assert!(xfvk_5h_7.is_ok());
|
||||||
assert_eq!(ExtendedFullViewingKey::from(&xsk_5h_7), xfvk_5h_7.unwrap());
|
assert_eq!(ExtendedFullViewingKey::from(&xsk_5h_7), xfvk_5h_7.unwrap());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn path() {
|
||||||
|
let seed = [0; 32];
|
||||||
|
let xsk_m = ExtendedSpendingKey::master(&seed);
|
||||||
|
|
||||||
|
let xsk_5h = xsk_m.derive_child(ChildIndex::Hardened(5));
|
||||||
|
assert_eq!(
|
||||||
|
ExtendedSpendingKey::from_path(&xsk_m, &[ChildIndex::Hardened(5)]),
|
||||||
|
xsk_5h
|
||||||
|
);
|
||||||
|
|
||||||
|
let xsk_5h_7 = xsk_5h.derive_child(ChildIndex::NonHardened(7));
|
||||||
|
assert_eq!(
|
||||||
|
ExtendedSpendingKey::from_path(
|
||||||
|
&xsk_m,
|
||||||
|
&[ChildIndex::Hardened(5), ChildIndex::NonHardened(7)]
|
||||||
|
),
|
||||||
|
xsk_5h_7
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue