Skip to content

Commit f33bc03

Browse files
committed
rust/bip32: collect methods into a new Xpub struct
More ergonomic and Rust-like to have a struct with related methods on it.
1 parent e9386f7 commit f33bc03

File tree

8 files changed

+161
-160
lines changed

8 files changed

+161
-160
lines changed

src/rust/bitbox02-rust/src/bip32.rs

Lines changed: 127 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -18,69 +18,111 @@ use alloc::vec::Vec;
1818

1919
pub use pb::btc_pub_request::XPubType;
2020

21-
/// Serializes a protobuf XPub to bytes according to the BIP32 specification. If xpub_type is None,
22-
/// the four version bytes are skipped.
23-
pub fn serialize_xpub(xpub: &pb::XPub, xpub_type: Option<XPubType>) -> Result<Vec<u8>, ()> {
24-
if xpub.depth.len() != 1
25-
|| xpub.parent_fingerprint.len() != 4
26-
|| xpub.chain_code.len() != 32
27-
|| xpub.public_key.len() != 33
28-
{
29-
return Err(());
21+
#[derive(Clone)]
22+
pub struct Xpub {
23+
xpub: pb::XPub,
24+
}
25+
26+
impl core::convert::From<pb::XPub> for Xpub {
27+
fn from(xpub: pb::XPub) -> Self {
28+
Xpub { xpub }
3029
}
30+
}
3131

32-
// Version bytes for mainnet public, see BIP32.
33-
let mut result: Vec<u8> = Vec::new();
34-
if let Some(xpub_type) = xpub_type {
35-
let version = match xpub_type {
36-
XPubType::Tpub => b"\x04\x35\x87\xcf",
37-
XPubType::Xpub => b"\x04\x88\xb2\x1e",
38-
XPubType::Ypub => b"\x04\x9d\x7c\xb2",
39-
XPubType::Zpub => b"\x04\xb2\x47\x46",
40-
XPubType::Vpub => b"\x04\x5f\x1c\xf6",
41-
XPubType::Upub => b"\x04\x4a\x52\x62",
42-
XPubType::CapitalVpub => b"\x02\x57\x54\x83",
43-
XPubType::CapitalZpub => b"\x02\xaa\x7e\xd3",
44-
XPubType::CapitalUpub => b"\x02\x42\x89\xef",
45-
XPubType::CapitalYpub => b"\x02\x95\xb4\x3f",
46-
};
47-
result.extend_from_slice(version);
32+
impl core::convert::From<&pb::XPub> for Xpub {
33+
fn from(xpub: &pb::XPub) -> Self {
34+
Xpub { xpub: xpub.clone() }
4835
}
49-
result.extend_from_slice(&xpub.depth);
50-
result.extend_from_slice(&xpub.parent_fingerprint);
51-
result.extend_from_slice(&xpub.child_num.to_be_bytes());
52-
result.extend_from_slice(&xpub.chain_code);
53-
result.extend_from_slice(&xpub.public_key);
54-
Ok(result)
5536
}
5637

57-
/// Serialize an xpub as a Base58Check encoded string according to BIP32.
58-
pub fn serialize_xpub_str(xpub: &pb::XPub, xpub_type: XPubType) -> Result<String, ()> {
59-
Ok(bs58::encode(serialize_xpub(xpub, Some(xpub_type))?)
60-
.with_check()
61-
.into_string())
38+
impl core::convert::From<Xpub> for pb::XPub {
39+
fn from(xpub: Xpub) -> Self {
40+
xpub.xpub
41+
}
6242
}
6343

64-
/// Parses an 78-ytes xpub bytestring, encoded according to BIP32. The 4 version bytes are not
65-
/// checked and discarded.
66-
pub fn parse_xpub_bytes(xpub: &[u8]) -> Result<pb::XPub, ()> {
67-
if xpub.len() != 78 {
68-
return Err(());
44+
impl Xpub {
45+
/// Parses an 78-ytes xpub bytestring, encoded according to BIP32. The 4 version bytes are not
46+
/// checked and discarded.
47+
pub fn from_bytes(xpub: &[u8]) -> Result<Self, ()> {
48+
if xpub.len() != 78 {
49+
return Err(());
50+
}
51+
Ok(Self::from(pb::XPub {
52+
depth: xpub[4..5].to_vec(),
53+
parent_fingerprint: xpub[5..9].to_vec(),
54+
child_num: u32::from_be_bytes(core::convert::TryInto::try_into(&xpub[9..13]).unwrap()),
55+
chain_code: xpub[13..45].to_vec(),
56+
public_key: xpub[45..78].to_vec(),
57+
}))
58+
}
59+
/// Serializes a protobuf XPub to bytes according to the BIP32 specification. If xpub_type is
60+
/// None, the four version bytes are skipped.
61+
pub fn serialize(&self, xpub_type: Option<XPubType>) -> Result<Vec<u8>, ()> {
62+
let xpub = &self.xpub;
63+
if xpub.depth.len() != 1
64+
|| xpub.parent_fingerprint.len() != 4
65+
|| xpub.chain_code.len() != 32
66+
|| xpub.public_key.len() != 33
67+
{
68+
return Err(());
69+
}
70+
71+
// Version bytes for mainnet public, see BIP32.
72+
let mut result: Vec<u8> = Vec::new();
73+
if let Some(xpub_type) = xpub_type {
74+
let version = match xpub_type {
75+
XPubType::Tpub => b"\x04\x35\x87\xcf",
76+
XPubType::Xpub => b"\x04\x88\xb2\x1e",
77+
XPubType::Ypub => b"\x04\x9d\x7c\xb2",
78+
XPubType::Zpub => b"\x04\xb2\x47\x46",
79+
XPubType::Vpub => b"\x04\x5f\x1c\xf6",
80+
XPubType::Upub => b"\x04\x4a\x52\x62",
81+
XPubType::CapitalVpub => b"\x02\x57\x54\x83",
82+
XPubType::CapitalZpub => b"\x02\xaa\x7e\xd3",
83+
XPubType::CapitalUpub => b"\x02\x42\x89\xef",
84+
XPubType::CapitalYpub => b"\x02\x95\xb4\x3f",
85+
};
86+
result.extend_from_slice(version);
87+
}
88+
result.extend_from_slice(&xpub.depth);
89+
result.extend_from_slice(&xpub.parent_fingerprint);
90+
result.extend_from_slice(&xpub.child_num.to_be_bytes());
91+
result.extend_from_slice(&xpub.chain_code);
92+
result.extend_from_slice(&xpub.public_key);
93+
Ok(result)
94+
}
95+
96+
/// Serialize an xpub as a Base58Check encoded string according to BIP32.
97+
pub fn serialize_str(&self, xpub_type: XPubType) -> Result<String, ()> {
98+
Ok(bs58::encode(self.serialize(Some(xpub_type))?)
99+
.with_check()
100+
.into_string())
101+
}
102+
103+
/// Returns the 33 bytes secp256k1 compressed pubkey.
104+
pub fn public_key(&self) -> &[u8] {
105+
self.xpub.public_key.as_slice()
106+
}
107+
108+
/// Return the hash160 of the secp256k1 public key.
109+
pub fn pubkey_hash160(&self) -> Vec<u8> {
110+
bitbox02::hash160(self.public_key()).to_vec()
111+
}
112+
113+
/// Return the 65 byte secp256k1 compressed pubkey:
114+
///
115+
/// (<0x04><64 bytes X><64 bytes Y>).
116+
pub fn pubkey_uncompressed(&self) -> Result<[u8; 65], ()> {
117+
bitbox02::keystore::secp256k1_pubkey_compressed_to_uncompressed(self.public_key())
69118
}
70-
Ok(pb::XPub {
71-
depth: xpub[4..5].to_vec(),
72-
parent_fingerprint: xpub[5..9].to_vec(),
73-
child_num: u32::from_be_bytes(core::convert::TryInto::try_into(&xpub[9..13]).unwrap()),
74-
chain_code: xpub[13..45].to_vec(),
75-
public_key: xpub[45..78].to_vec(),
76-
})
77119
}
78120

79121
/// Parses a Base58Check-encoded xpub string. The 4 version bytes are not checked and discarded.
80122
#[cfg(test)]
81123
pub fn parse_xpub(xpub: &str) -> Result<pb::XPub, ()> {
82124
let decoded = bs58::decode(xpub).with_check(None).into_vec().or(Err(()))?;
83-
parse_xpub_bytes(&decoded)
125+
Ok(Xpub::from_bytes(&decoded)?.into())
84126
}
85127

86128
#[cfg(test)]
@@ -89,50 +131,74 @@ mod tests {
89131

90132
#[test]
91133
fn test_parse_serialize_xpub() {
92-
let xpub = parse_xpub("xpub6Eu7xJRyXRCi4eLYhJPnfZVjgAQtM7qFaEZwUhvgxGf4enEZMxevGzWvZTawCj9USP2MFTEhKQAwnqHwoaPHetTLqGuvq5r5uaLKyGx5QDZ").unwrap();
134+
let xpub = Xpub::from(parse_xpub("xpub6Eu7xJRyXRCi4eLYhJPnfZVjgAQtM7qFaEZwUhvgxGf4enEZMxevGzWvZTawCj9USP2MFTEhKQAwnqHwoaPHetTLqGuvq5r5uaLKyGx5QDZ").unwrap());
93135
assert_eq!(
94-
serialize_xpub(&xpub, None).unwrap(),
136+
xpub.serialize(None).unwrap(),
95137
hex::decode("04b9d184d180000002b5b571ead68edac616c38491d9fd78d4697077e7675333452b586e3282705a3a0281bec7de8d182945744445948b54800e95267a5ac039bab6218a03b8e6f4b38a").unwrap(),
96138
);
97139
assert_eq!(
98-
serialize_xpub_str(&xpub, XPubType::Tpub).unwrap().as_str(),
140+
xpub.serialize_str(XPubType::Tpub).unwrap().as_str(),
99141
"tpubDFGkUYFfEhAALSXQ9VNssUq71HWYLWLK7sAEqFyqJBQxQ4uGSBW1RSBkoVfijE6iEHZFs2kZrVzzV1nZCSEXYKudtsfEWcWKVXvjjLeRyd8",
100142
);
101143
assert_eq!(
102-
serialize_xpub_str(&xpub, XPubType::Xpub).unwrap().as_str(),
144+
xpub.serialize_str(XPubType::Xpub).unwrap().as_str(),
103145
"xpub6Eu7xJRyXRCi4eLYhJPnfZVjgAQtM7qFaEZwUhvgxGf4enEZMxevGzWvZTawCj9USP2MFTEhKQAwnqHwoaPHetTLqGuvq5r5uaLKyGx5QDZ",
104146
);
105147
assert_eq!(
106-
serialize_xpub_str(&xpub, XPubType::Ypub).unwrap().as_str(),
148+
xpub.serialize_str(XPubType::Ypub).unwrap().as_str(),
107149
"ypub6ZjPFy6tg6kBuwXfXfBQsebEr8ZLHjpkVM6AG6paLH2wht3nccpUu4B4afYXCdoPr299zvqFn4XVg7uWXGoJT88whccMQzfaBJPyMrVtPLb",
108150
);
109151
assert_eq!(
110-
serialize_xpub_str(&xpub, XPubType::Zpub).unwrap().as_str(),
152+
xpub.serialize_str(XPubType::Zpub).unwrap().as_str(),
111153
"zpub6tZeZdmopnHfmEinN1y35jgk26hnEMpFQTcP3ViTiHQpkys1sGz3X7qCbsW7CYTKFfFxkQRpEit3ZQX5EyDKFMpYZxJmzuV4T2TckTXCeKB",
112154
);
113155
assert_eq!(
114-
serialize_xpub_str(&xpub, XPubType::Vpub).unwrap().as_str(),
156+
xpub.serialize_str(XPubType::Vpub).unwrap().as_str(),
115157
"vpub5bEbLy69E47kN3xK2apYFPJjLE7zTsrFk1XVuv8vCFuJYac6reKo2sCeX3fmCuqdd6njkW3aQ5Tr2G4pNBZG4R696bX5fGD7N8D3CBtsPoq",
116158
);
117159
assert_eq!(
118-
serialize_xpub_str(&xpub, XPubType::Upub).unwrap().as_str(),
160+
xpub.serialize_str(XPubType::Upub).unwrap().as_str(),
119161
"upub5GQL3JRE5NaGWkmCCE2v3JDEAFyYXFrkpu1H8XF2pFXRVUnsbzAEQoYWVqiBD1BiDTfw12T1wR7J8yTFeV9FGBQYEFpf5MPd6Q9PoXnSeMz",
120162
);
121163
assert_eq!(
122-
serialize_xpub_str(&xpub, XPubType::CapitalVpub).unwrap().as_str(),
164+
xpub.serialize_str(XPubType::CapitalVpub).unwrap().as_str(),
123165
"Vpub5n8gUCpao1g7nd7gyFHX5TeY42AFgEXr4HBAqBQTa2jiAmB1d3i57z4aKkdEmM4XrZrid63hHHrM9RgafQiDCuCow4dV4fg7FrUun5qYdcZ",
124166
);
125167
assert_eq!(
126-
serialize_xpub_str(&xpub, XPubType::CapitalZpub).unwrap().as_str(),
168+
xpub.serialize_str(XPubType::CapitalZpub).unwrap().as_str(),
127169
"Zpub75TjgsWFPjr3BotAJgS1up2Yjtk3SiVqijG3xkz164FEPARvdgNKcEh8QaTakygDV8KwczRw7wGYga8qYCNGPqwDQRRBQJx4LkjVLLY6Yta",
128170
);
129171
assert_eq!(
130-
serialize_xpub_str(&xpub, XPubType::CapitalUpub).unwrap().as_str(),
172+
xpub.serialize_str(XPubType::CapitalUpub).unwrap().as_str(),
131173
"Upub5TJRAY9feL8dwKva8tVtsNZ2t41ojcYM9Aex3nWaC2Mq7fMnNPYWVvQSJYfemSQcSvjuscT8pdVoG951wiJCQfXD4iw4Ukrcz8RGPZ1BoeD",
132174
);
133175
assert_eq!(
134-
serialize_xpub_str(&xpub, XPubType::CapitalYpub).unwrap().as_str(),
176+
xpub.serialize_str(XPubType::CapitalYpub).unwrap().as_str(),
135177
"Ypub6kdUPCqLF4JZLWh3UKePhiw3ZvbbW6WLocjqBN67i3sML4chP2CkzB2zPNVzm52J5VD8sWqNfGuzoHXGpVxFbcFcY5ikpQ8a52fqwpAmYX2",
136178
);
137179
}
180+
181+
#[test]
182+
fn test_pubkey_hash160() {
183+
let xpub = Xpub::from(parse_xpub("xpub6GugPDcUhrSudznFss7wXvQV3gwFTEanxHdCyoNoHnZEr3PTbh2Fosg4JjfphaYAsqjBhmtTZ3Yo8tmGjSHtaPhExNiMCSvPzreqjrX4Wr7").unwrap());
184+
assert_eq!(
185+
xpub.pubkey_hash160(),
186+
*b"\xb5\x12\x5c\xec\xa0\xc1\xc8\x90\xda\x07\x9a\x12\x88\xdc\xf7\x7a\xa6\xac\xc4\x99"
187+
);
188+
189+
let xpub = Xpub::from(parse_xpub("xpub6FiMwSqu98LjKsbGy1PfgGRQA9XH7k6dfsyPedsyrdBRJDPwc658JA3qGc7DV2dWUYVGEqzRicztwzCj1NprQSRbSubWcnkKxM3Gwnyh4xo").unwrap());
190+
assert_eq!(
191+
xpub.pubkey_hash160(),
192+
*b"\xe5\xf8\x9a\xb6\x54\x37\x44\xf7\x8f\x15\x86\x7c\x43\x06\xee\x86\x6b\xb1\x1d\xf9"
193+
);
194+
}
195+
196+
#[test]
197+
fn test_secp256k1_pubkey_uncompressed() {
198+
let xpub = Xpub::from(parse_xpub("xpub6FiMwSqu98LjKsbGy1PfgGRQA9XH7k6dfsyPedsyrdBRJDPwc658JA3qGc7DV2dWUYVGEqzRicztwzCj1NprQSRbSubWcnkKxM3Gwnyh4xo").unwrap());
199+
assert_eq!(
200+
xpub.pubkey_uncompressed().unwrap(),
201+
*b"\x04\x77\xa4\x4a\xa9\xe8\xc8\xfb\x51\x05\xef\x5e\xe2\x39\x4e\x8a\xed\x89\xad\x73\xfc\x74\x36\x14\x25\xf0\x63\x47\xec\xfe\x32\x61\x31\xe1\x33\x93\x67\xee\x3c\xbe\x87\x71\x92\x85\xa0\x7f\x77\x4b\x17\xeb\x93\x3e\xcf\x0b\x9b\x82\xac\xeb\xc1\x95\x22\x6d\x63\x42\x44",
202+
);
203+
}
138204
}

src/rust/bitbox02-rust/src/hww/api/bitcoin.rs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -105,10 +105,9 @@ async fn xpub(
105105
) -> Result<Response, Error> {
106106
let params = params::get(coin);
107107
keypath::validate_xpub(keypath, params.bip44_coin, params.taproot_support)?;
108-
let xpub = crate::bip32::serialize_xpub_str(
109-
&keystore::get_xpub(keypath).or(Err(Error::InvalidInput))?,
110-
xpub_type,
111-
)?;
108+
let xpub = keystore::get_xpub(keypath)
109+
.or(Err(Error::InvalidInput))?
110+
.serialize_str(xpub_type)?;
112111
if display {
113112
let title = format!("{}\naccount #{}", params.name, keypath[2] - HARDENED + 1);
114113
let confirm_params = confirm::Params {

src/rust/bitbox02-rust/src/hww/api/bitcoin/common.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ impl Payload {
7777
) -> Result<Self, Error> {
7878
match simple_type {
7979
SimpleType::P2wpkh => Ok(Payload {
80-
data: keystore::secp256k1_pubkey_hash160(keypath)?,
80+
data: keystore::get_xpub(keypath)?.pubkey_hash160(),
8181
output_type: BtcOutputType::P2wpkh,
8282
}),
8383
SimpleType::P2wpkhP2sh => {

src/rust/bitbox02-rust/src/hww/api/bitcoin/multisig.rs

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,8 @@ pub fn convert_multisig(multisig: &Multisig) -> Result<bitbox02::app_btc::Multis
4040
xpubs: {
4141
let mut xpubs = [[0u8; 78]; MAX_SIGNERS];
4242
for (i, xpub) in multisig.xpubs.iter().enumerate() {
43-
xpubs[i] = bip32::serialize_xpub(xpub, Some(bip32::XPubType::Xpub))
43+
xpubs[i] = bip32::Xpub::from(xpub)
44+
.serialize(Some(bip32::XPubType::Xpub))
4445
.or(Err(Error::InvalidInput))?
4546
.try_into()
4647
.or(Err(Error::Generic))?;
@@ -100,7 +101,7 @@ pub fn get_hash(
100101
let mut xpubs_serialized: Vec<Vec<u8>> = multisig
101102
.xpubs
102103
.iter()
103-
.map(|xpub| bip32::serialize_xpub(xpub, None))
104+
.map(|xpub| bip32::Xpub::from(xpub).serialize(None))
104105
.collect::<Result<Vec<Vec<u8>>, ()>>()?;
105106
if let SortXpubs::Yes = sort_xpubs {
106107
xpubs_serialized.sort();
@@ -236,8 +237,9 @@ pub async fn confirm_extended(
236237
};
237238
let num_cosigners = multisig.xpubs.len();
238239
for (i, xpub) in multisig.xpubs.iter().enumerate() {
239-
let xpub_str =
240-
bip32::serialize_xpub_str(xpub, output_xpub_type).or(Err(Error::InvalidInput))?;
240+
let xpub_str = bip32::Xpub::from(xpub)
241+
.serialize_str(output_xpub_type)
242+
.or(Err(Error::InvalidInput))?;
241243
confirm::confirm(&confirm::Params {
242244
title,
243245
body: (if i == multisig.our_xpub_index as usize {
@@ -287,9 +289,9 @@ pub fn validate(multisig: &Multisig, keypath: &[u32], expected_coin: u32) -> Res
287289
)
288290
.or(Err(Error::InvalidInput))?;
289291

290-
let our_xpub = bip32::serialize_xpub(&crate::keystore::get_xpub(keypath)?, None)?;
292+
let our_xpub = crate::keystore::get_xpub(keypath)?.serialize(None)?;
291293
let maybe_our_xpub =
292-
bip32::serialize_xpub(&multisig.xpubs[multisig.our_xpub_index as usize], None)?;
294+
bip32::Xpub::from(&multisig.xpubs[multisig.our_xpub_index as usize]).serialize(None)?;
293295
if our_xpub != maybe_our_xpub {
294296
return Err(Error::InvalidInput);
295297
}
@@ -774,7 +776,7 @@ mod tests {
774776
// invalid keypath, wrong purpose
775777
let mut invalid = multisig.clone();
776778
let keypath = &[49 + HARDENED, expected_coin, 0 + HARDENED, 2 + HARDENED];
777-
invalid.xpubs[1] = crate::keystore::get_xpub(keypath).unwrap();
779+
invalid.xpubs[1] = crate::keystore::get_xpub(keypath).unwrap().into();
778780
assert!(validate(&invalid, keypath, expected_coin).is_err());
779781
}
780782

@@ -783,7 +785,7 @@ mod tests {
783785

784786
let mut invalid = multisig.clone();
785787
let keypath = &[48 + HARDENED, expected_coin + 1, 0 + HARDENED, 2 + HARDENED];
786-
invalid.xpubs[1] = crate::keystore::get_xpub(keypath).unwrap();
788+
invalid.xpubs[1] = crate::keystore::get_xpub(keypath).unwrap().into();
787789
assert!(validate(&invalid, keypath, expected_coin).is_err());
788790
}
789791

@@ -792,7 +794,7 @@ mod tests {
792794

793795
let mut invalid = multisig.clone();
794796
let keypath = &[48 + HARDENED, expected_coin, 100 + HARDENED, 2 + HARDENED];
795-
invalid.xpubs[1] = crate::keystore::get_xpub(keypath).unwrap();
797+
invalid.xpubs[1] = crate::keystore::get_xpub(keypath).unwrap().into();
796798
assert!(validate(&invalid, keypath, expected_coin).is_err());
797799
}
798800

@@ -801,7 +803,7 @@ mod tests {
801803

802804
let mut invalid = multisig.clone();
803805
let keypath = &[48 + HARDENED, expected_coin, 0 + HARDENED, 1 + HARDENED];
804-
invalid.xpubs[1] = crate::keystore::get_xpub(keypath).unwrap();
806+
invalid.xpubs[1] = crate::keystore::get_xpub(keypath).unwrap().into();
805807
assert!(validate(&invalid, keypath, expected_coin).is_err());
806808
}
807809

src/rust/bitbox02-rust/src/hww/api/bitcoin/signtx.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -275,7 +275,7 @@ fn sighash_script(
275275
| pb::btc_script_config::SimpleType::P2wpkh => {
276276
// See https://github.com/bitcoin/bips/blob/master/bip-0143.mediawiki#specification, item 5:
277277
// > For P2WPKH witness program, the scriptCode is 0x1976a914{20-byte-pubkey-hash}88ac.
278-
let pubkey_hash160 = crate::keystore::secp256k1_pubkey_hash160(keypath)?;
278+
let pubkey_hash160 = crate::keystore::get_xpub(keypath)?.pubkey_hash160();
279279
let mut result = Vec::<u8>::new();
280280
result.extend_from_slice(b"\x76\xa9\x14");
281281
result.extend_from_slice(&pubkey_hash160);

src/rust/bitbox02-rust/src/hww/api/electrum.rs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -39,10 +39,9 @@ pub async fn process(
3939
{
4040
return Err(Error::InvalidInput);
4141
}
42-
let xpub = bip32::serialize_xpub_str(
43-
&keystore::get_xpub(keypath).or(Err(Error::InvalidInput))?,
44-
bip32::XPubType::Xpub,
45-
)?;
42+
let xpub = keystore::get_xpub(keypath)
43+
.or(Err(Error::InvalidInput))?
44+
.serialize_str(bip32::XPubType::Xpub)?;
4645

4746
Ok(Response::ElectrumEncryptionKey(
4847
pb::ElectrumEncryptionKeyResponse { key: xpub },

src/rust/bitbox02-rust/src/hww/api/ethereum/pubrequest.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -47,8 +47,9 @@ async fn process_address(request: &pb::EthPubRequest) -> Result<Response, Error>
4747
if !super::keypath::is_valid_keypath_address(&request.keypath) {
4848
return Err(Error::InvalidInput);
4949
}
50-
let pubkey = crate::keystore::secp256k1_pubkey_uncompressed(&request.keypath)
51-
.or(Err(Error::InvalidInput))?;
50+
let pubkey = crate::keystore::get_xpub(&request.keypath)
51+
.or(Err(Error::InvalidInput))?
52+
.pubkey_uncompressed()?;
5253
let address = super::address::from_pubkey(&pubkey);
5354

5455
if request.display {
@@ -79,10 +80,9 @@ fn process_xpub(request: &pb::EthPubRequest) -> Result<Response, Error> {
7980
if !super::keypath::is_valid_keypath_xpub(&request.keypath) {
8081
return Err(Error::InvalidInput);
8182
}
82-
let xpub = bip32::serialize_xpub_str(
83-
&keystore::get_xpub(&request.keypath).or(Err(Error::InvalidInput))?,
84-
bip32::XPubType::Xpub,
85-
)?;
83+
let xpub = keystore::get_xpub(&request.keypath)
84+
.or(Err(Error::InvalidInput))?
85+
.serialize_str(bip32::XPubType::Xpub)?;
8686

8787
Ok(Response::Pub(pb::PubResponse { r#pub: xpub }))
8888
}

0 commit comments

Comments
 (0)