Add version bytes consts

BIP-32 defines 4 4-byte consts used as version bytes; currently we are
hardcoding the version bytes in multiple places.

Add BIP-32 version bytes consts and use them throughout the module.
This commit is contained in:
Tobin C. Harding 2023-08-22 09:20:49 +10:00
parent 5bf2117dc4
commit f18f684ad2
No known key found for this signature in database
GPG Key ID: 40BF9E4C269D6607
1 changed files with 31 additions and 22 deletions

View File

@ -26,6 +26,15 @@ use crate::io::Write;
use crate::network::Network; use crate::network::Network;
use crate::prelude::*; use crate::prelude::*;
/// Version bytes for extended public keys on the Bitcoin network.
const VERSION_BYTES_MAINNET_PUBLIC: [u8; 4] = [0x04, 0x88, 0xB2, 0x1E];
/// Version bytes for extended private keys on the Bitcoin network.
const VERSION_BYTES_MAINNET_PRIVATE: [u8; 4] = [0x04, 0x88, 0xAD, 0xE4];
/// Version bytes for extended public keys on any of the testnet networks.
const VERSION_BYTES_TESTNETS_PUBLIC: [u8; 4] = [0x04, 0x35, 0x87, 0xCF];
/// Version bytes for extended private keys on any of the testnet networks.
const VERSION_BYTES_TESTNETS_PRIVATE: [u8; 4] = [0x04, 0x35, 0x83, 0x94];
/// A chain code /// A chain code
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct ChainCode([u8; 32]); pub struct ChainCode([u8; 32]);
@ -623,11 +632,13 @@ impl ExtendedPrivKey {
return Err(Error::WrongExtendedKeyLength(data.len())); return Err(Error::WrongExtendedKeyLength(data.len()));
} }
let network = match data { let network = if data.starts_with(&VERSION_BYTES_MAINNET_PRIVATE) {
[0x04u8, 0x88, 0xAD, 0xE4, ..] => Network::Bitcoin, Network::Bitcoin
[0x04u8, 0x35, 0x83, 0x94, ..] => Network::Testnet, } else if data.starts_with(&VERSION_BYTES_TESTNETS_PRIVATE) {
[b0, b1, b2, b3, ..] => return Err(Error::UnknownVersion([*b0, *b1, *b2, *b3])), Network::Testnet
_ => unreachable!("length checked above"), } else {
let (b0, b1, b2, b3) = (data[0], data[1], data[2], data[3]);
return Err(Error::UnknownVersion([b0, b1, b2, b3]));
}; };
Ok(ExtendedPrivKey { Ok(ExtendedPrivKey {
@ -647,12 +658,10 @@ impl ExtendedPrivKey {
/// Extended private key binary encoding according to BIP 32 /// Extended private key binary encoding according to BIP 32
pub fn encode(&self) -> [u8; 78] { pub fn encode(&self) -> [u8; 78] {
let mut ret = [0; 78]; let mut ret = [0; 78];
ret[0..4].copy_from_slice( ret[0..4].copy_from_slice(&match self.network {
&match self.network { Network::Bitcoin => VERSION_BYTES_MAINNET_PRIVATE,
Network::Bitcoin => [0x04, 0x88, 0xAD, 0xE4], Network::Testnet | Network::Signet | Network::Regtest => VERSION_BYTES_TESTNETS_PRIVATE,
Network::Testnet | Network::Signet | Network::Regtest => [0x04, 0x35, 0x83, 0x94], });
}[..],
);
ret[4] = self.depth; ret[4] = self.depth;
ret[5..9].copy_from_slice(&self.parent_fingerprint[..]); ret[5..9].copy_from_slice(&self.parent_fingerprint[..]);
ret[9..13].copy_from_slice(&u32::from(self.child_number).to_be_bytes()); ret[9..13].copy_from_slice(&u32::from(self.child_number).to_be_bytes());
@ -758,11 +767,13 @@ impl ExtendedPubKey {
return Err(Error::WrongExtendedKeyLength(data.len())); return Err(Error::WrongExtendedKeyLength(data.len()));
} }
let network = match data { let network = if data.starts_with(&VERSION_BYTES_MAINNET_PUBLIC) {
[0x04u8, 0x88, 0xB2, 0x1E, ..] => Network::Bitcoin, Network::Bitcoin
[0x04u8, 0x35, 0x87, 0xCF, ..] => Network::Testnet, } else if data.starts_with(&VERSION_BYTES_TESTNETS_PUBLIC) {
[b0, b1, b2, b3, ..] => return Err(Error::UnknownVersion([*b0, *b1, *b2, *b3])), Network::Testnet
_ => unreachable!("length checked above"), } else {
let (b0, b1, b2, b3) = (data[0], data[1], data[2], data[3]);
return Err(Error::UnknownVersion([b0, b1, b2, b3]));
}; };
Ok(ExtendedPubKey { Ok(ExtendedPubKey {
@ -782,12 +793,10 @@ impl ExtendedPubKey {
/// Extended public key binary encoding according to BIP 32 /// Extended public key binary encoding according to BIP 32
pub fn encode(&self) -> [u8; 78] { pub fn encode(&self) -> [u8; 78] {
let mut ret = [0; 78]; let mut ret = [0; 78];
ret[0..4].copy_from_slice( ret[0..4].copy_from_slice(&match self.network {
&match self.network { Network::Bitcoin => VERSION_BYTES_MAINNET_PUBLIC,
Network::Bitcoin => [0x04u8, 0x88, 0xB2, 0x1E], Network::Testnet | Network::Signet | Network::Regtest => VERSION_BYTES_TESTNETS_PUBLIC,
Network::Testnet | Network::Signet | Network::Regtest => [0x04u8, 0x35, 0x87, 0xCF], });
}[..],
);
ret[4] = self.depth; ret[4] = self.depth;
ret[5..9].copy_from_slice(&self.parent_fingerprint[..]); ret[5..9].copy_from_slice(&self.parent_fingerprint[..]);
ret[9..13].copy_from_slice(&u32::from(self.child_number).to_be_bytes()); ret[9..13].copy_from_slice(&u32::from(self.child_number).to_be_bytes());