diff --git a/components/zcash_address/src/kind/unified/fvk.rs b/components/zcash_address/src/kind/unified/fvk.rs index b0e7c9d60..c8c02a462 100644 --- a/components/zcash_address/src/kind/unified/fvk.rs +++ b/components/zcash_address/src/kind/unified/fvk.rs @@ -1,8 +1,6 @@ use std::cmp; use std::convert::{TryFrom, TryInto}; -use crate::kind; - use super::{ private::{SealedContainer, SealedItem}, Encoding, ParseError, Container, Typecode, @@ -33,16 +31,6 @@ pub enum Fvk { /// extended public key. P2pkh([u8; 78]), - /// The raw data of a P2SH address. - /// - /// # Security - /// - /// P2SH addresses are hashes of scripts, and as such have no generic HD mechanism for - /// us to derive independent-but-linked P2SH addresses. As such, if someone constructs - /// a UFVK containing a P2SH address, and then derives diversified UAs from it, those - /// UAs will be trivially linkable as they will share the same P2SH address. - P2sh(kind::p2sh::Data), - Unknown { typecode: u32, data: Vec, @@ -68,15 +56,13 @@ impl TryFrom<(u32, &[u8])> for Fvk { type Error = ParseError; fn try_from((typecode, data): (u32, &[u8])) -> Result { + let data = data.to_vec(); match typecode.try_into()? { Typecode::P2pkh => data.try_into().map(Fvk::P2pkh), - Typecode::P2sh => data.try_into().map(Fvk::P2sh), + Typecode::P2sh => Err(data), Typecode::Sapling => data.try_into().map(Fvk::Sapling), Typecode::Orchard => data.try_into().map(Fvk::Orchard), - Typecode::Unknown(_) => Ok(Fvk::Unknown { - typecode, - data: data.to_vec(), - }), + Typecode::Unknown(_) => Ok(Fvk::Unknown { typecode, data }), } .map_err(|e| { ParseError::InvalidEncoding(format!("Invalid fvk for typecode {}: {:?}", typecode, e)) @@ -88,7 +74,6 @@ impl SealedItem for Fvk { fn typecode(&self) -> Typecode { match self { Fvk::P2pkh(_) => Typecode::P2pkh, - Fvk::P2sh(_) => Typecode::P2sh, Fvk::Sapling(_) => Typecode::Sapling, Fvk::Orchard(_) => Typecode::Orchard, Fvk::Unknown { typecode, .. } => Typecode::Unknown(*typecode), @@ -98,7 +83,6 @@ impl SealedItem for Fvk { fn data(&self) -> &[u8] { match self { Fvk::P2pkh(data) => data, - Fvk::P2sh(data) => data, Fvk::Sapling(data) => data, Fvk::Orchard(data) => data, Fvk::Unknown { data, .. } => data, @@ -150,10 +134,7 @@ impl SealedContainer for Ufvk { mod tests { use assert_matches::assert_matches; - use proptest::{ - array::{uniform20, uniform32}, - prelude::*, - }; + use proptest::{array::uniform32, prelude::*}; use super::{Fvk, ParseError, Typecode, Ufvk}; use crate::kind::unified::{private::SealedContainer, Encoding, Container}; @@ -185,11 +166,7 @@ mod tests { } fn arb_transparent_fvk() -> BoxedStrategy { - prop_oneof![ - uniform78().prop_map(Fvk::P2pkh), - uniform20(0u8..).prop_map(Fvk::P2sh), - ] - .boxed() + uniform78().prop_map(Fvk::P2pkh).boxed() } prop_compose! { @@ -310,17 +287,6 @@ mod tests { ); } - #[test] - fn p2pkh_and_p2sh() { - // Construct and serialize an invalid UFVK. - let ufvk = Ufvk(vec![Fvk::P2pkh([0; 78]), Fvk::P2sh([0; 20])]); - let encoded = ufvk.to_bytes(Ufvk::MAINNET); - assert_eq!( - Ufvk::try_from_bytes(Ufvk::MAINNET, &encoded[..]), - Err(ParseError::BothP2phkAndP2sh) - ); - } - #[test] fn only_transparent() { // Encoding of `Ufvk(vec![Fvk::P2pkh([0; 78])])`. diff --git a/components/zcash_address/src/kind/unified/ivk.rs b/components/zcash_address/src/kind/unified/ivk.rs index 2c69d7afd..4a0c94294 100644 --- a/components/zcash_address/src/kind/unified/ivk.rs +++ b/components/zcash_address/src/kind/unified/ivk.rs @@ -1,8 +1,6 @@ use std::cmp; use std::convert::{TryFrom, TryInto}; -use crate::kind; - use super::{ private::{SealedContainer, SealedItem}, Encoding, ParseError, Container, Typecode, @@ -37,16 +35,6 @@ pub enum Ivk { /// extended public key. P2pkh([u8; 78]), - /// The raw data of a P2SH address. - /// - /// # Security - /// - /// P2SH addresses are hashes of scripts, and as such have no generic HD mechanism for - /// us to derive independent-but-linked P2SH addresses. As such, if someone constructs - /// a UIVK containing a P2SH address, and then derives diversified UAs from it, those - /// UAs will be trivially linkable as they will share the same P2SH address. - P2sh(kind::p2sh::Data), - Unknown { typecode: u32, data: Vec, @@ -72,15 +60,13 @@ impl TryFrom<(u32, &[u8])> for Ivk { type Error = ParseError; fn try_from((typecode, data): (u32, &[u8])) -> Result { + let data = data.to_vec(); match typecode.try_into()? { Typecode::P2pkh => data.try_into().map(Ivk::P2pkh), - Typecode::P2sh => data.try_into().map(Ivk::P2sh), + Typecode::P2sh => Err(data), Typecode::Sapling => data.try_into().map(Ivk::Sapling), Typecode::Orchard => data.try_into().map(Ivk::Orchard), - Typecode::Unknown(_) => Ok(Ivk::Unknown { - typecode, - data: data.to_vec(), - }), + Typecode::Unknown(_) => Ok(Ivk::Unknown { typecode, data }), } .map_err(|e| { ParseError::InvalidEncoding(format!("Invalid ivk for typecode {}: {:?}", typecode, e)) @@ -92,7 +78,6 @@ impl SealedItem for Ivk { fn typecode(&self) -> Typecode { match self { Ivk::P2pkh(_) => Typecode::P2pkh, - Ivk::P2sh(_) => Typecode::P2sh, Ivk::Sapling(_) => Typecode::Sapling, Ivk::Orchard(_) => Typecode::Orchard, Ivk::Unknown { typecode, .. } => Typecode::Unknown(*typecode), @@ -102,7 +87,6 @@ impl SealedItem for Ivk { fn data(&self) -> &[u8] { match self { Ivk::P2pkh(data) => data, - Ivk::P2sh(data) => data, Ivk::Sapling(data) => data, Ivk::Orchard(data) => data, Ivk::Unknown { data, .. } => data, @@ -155,7 +139,7 @@ mod tests { use assert_matches::assert_matches; use proptest::{ - array::{uniform14, uniform20, uniform32}, + array::{uniform14, uniform32}, prelude::*, }; @@ -189,11 +173,7 @@ mod tests { } fn arb_transparent_ivk() -> BoxedStrategy { - prop_oneof![ - uniform78().prop_map(Ivk::P2pkh), - uniform20(0u8..).prop_map(Ivk::P2sh), - ] - .boxed() + uniform78().prop_map(Ivk::P2pkh).boxed() } prop_compose! { @@ -304,17 +284,6 @@ mod tests { ); } - #[test] - fn p2pkh_and_p2sh() { - // Construct and serialize an invalid UIVK. - let uivk = Uivk(vec![Ivk::P2pkh([0; 78]), Ivk::P2sh([0; 20])]); - let encoded = uivk.to_bytes(Uivk::MAINNET); - assert_eq!( - Uivk::try_from_bytes(Uivk::MAINNET, &encoded[..]), - Err(ParseError::BothP2phkAndP2sh) - ); - } - #[test] fn only_transparent() { // Encoding of `Uivk(vec![Ivk::P2pkh([0; 78])])`.