Merge rust-bitcoin/rust-bitcoin#2020: Add version bytes consts

f18f684ad2 Add version bytes consts (Tobin C. Harding)

Pull request description:

  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.

ACKs for top commit:
  apoelstra:
    ACK f18f684ad2
  RCasatta:
    utACK f18f684ad2

Tree-SHA512: 50bf2d26f0f8e3528642ffcc621c03b82f536994deb808a6c84225676b4b8849db8e0d16e46f3819e0810296a422b31cf90d0595739910afdb92fb768ef7696e
This commit is contained in:
Andrew Poelstra 2023-08-25 14:52:19 +00:00
commit 4dc71b0de7
No known key found for this signature in database
GPG Key ID: C588D63CE41B97C1
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 Xpriv {
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(Xpriv { Ok(Xpriv {
@ -647,12 +658,10 @@ impl Xpriv {
/// 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());
@ -755,11 +764,13 @@ impl Xpub {
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(Xpub { Ok(Xpub {
@ -779,12 +790,10 @@ impl Xpub {
/// 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());