Merge pull request #542 from apoelstra/2021-01--keyread
PublicKey: add read_from method to be symmetric with write_into
This commit is contained in:
commit
b48f374c2c
|
@ -109,6 +109,24 @@ impl PublicKey {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Read the public key from a reader
|
||||||
|
///
|
||||||
|
/// This internally reads the first byte before reading the rest, so
|
||||||
|
/// use of a `BufReader` is recommended.
|
||||||
|
pub fn read_from<R: io::Read>(mut reader: R) -> Result<Self, io::Error> {
|
||||||
|
let mut bytes = [0; 65];
|
||||||
|
|
||||||
|
reader.read_exact(&mut bytes[0..1])?;
|
||||||
|
let bytes = if bytes[0] < 4 {
|
||||||
|
&mut bytes[..33]
|
||||||
|
} else {
|
||||||
|
&mut bytes[..65]
|
||||||
|
};
|
||||||
|
|
||||||
|
reader.read_exact(&mut bytes[1..])?;
|
||||||
|
Self::from_slice(bytes).map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))
|
||||||
|
}
|
||||||
|
|
||||||
/// Serialize the public key to bytes
|
/// Serialize the public key to bytes
|
||||||
pub fn to_bytes(&self) -> Vec<u8> {
|
pub fn to_bytes(&self) -> Vec<u8> {
|
||||||
let mut buf = Vec::new();
|
let mut buf = Vec::new();
|
||||||
|
@ -378,6 +396,7 @@ impl<'de> ::serde::Deserialize<'de> for PublicKey {
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::{PrivateKey, PublicKey};
|
use super::{PrivateKey, PublicKey};
|
||||||
use secp256k1::Secp256k1;
|
use secp256k1::Secp256k1;
|
||||||
|
use std::io;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
use hashes::hex::ToHex;
|
use hashes::hex::ToHex;
|
||||||
use network::constants::Network::Testnet;
|
use network::constants::Network::Testnet;
|
||||||
|
@ -481,4 +500,53 @@ mod tests {
|
||||||
assert_tokens(&pk_u.compact(), &[Token::BorrowedBytes(&PK_BYTES_U[..])]);
|
assert_tokens(&pk_u.compact(), &[Token::BorrowedBytes(&PK_BYTES_U[..])]);
|
||||||
assert_tokens(&pk_u.readable(), &[Token::BorrowedStr(PK_STR_U)]);
|
assert_tokens(&pk_u.readable(), &[Token::BorrowedStr(PK_STR_U)]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn random_key(mut seed: u8) -> PublicKey {
|
||||||
|
loop {
|
||||||
|
let mut data = [0; 65];
|
||||||
|
for byte in &mut data[..] {
|
||||||
|
*byte = seed;
|
||||||
|
// totally a rng
|
||||||
|
seed = seed.wrapping_mul(41).wrapping_add(43);
|
||||||
|
}
|
||||||
|
if data[0] % 2 == 0 {
|
||||||
|
data[0] = 4;
|
||||||
|
if let Ok(key) = PublicKey::from_slice(&data[..]) {
|
||||||
|
return key;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
data[0] = 2 + (data[0] >> 7);
|
||||||
|
if let Ok(key) = PublicKey::from_slice(&data[..33]) {
|
||||||
|
return key;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn pubkey_read_write() {
|
||||||
|
const N_KEYS: usize = 20;
|
||||||
|
let keys: Vec<_> = (0..N_KEYS).map(|i| random_key(i as u8)).collect();
|
||||||
|
|
||||||
|
let mut v = vec![];
|
||||||
|
for k in &keys {
|
||||||
|
k.write_into(&mut v).expect("writing into vec");
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut dec_keys = vec![];
|
||||||
|
let mut cursor = io::Cursor::new(&v);
|
||||||
|
for _ in 0..N_KEYS {
|
||||||
|
dec_keys.push(PublicKey::read_from(&mut cursor).expect("reading from vec"));
|
||||||
|
}
|
||||||
|
|
||||||
|
assert_eq!(keys, dec_keys);
|
||||||
|
|
||||||
|
// sanity checks
|
||||||
|
assert!(PublicKey::read_from(&mut cursor).is_err());
|
||||||
|
assert!(PublicKey::read_from(io::Cursor::new(&[])).is_err());
|
||||||
|
assert!(PublicKey::read_from(io::Cursor::new(&[0; 33][..])).is_err());
|
||||||
|
assert!(PublicKey::read_from(io::Cursor::new(&[2; 32][..])).is_err());
|
||||||
|
assert!(PublicKey::read_from(io::Cursor::new(&[0; 65][..])).is_err());
|
||||||
|
assert!(PublicKey::read_from(io::Cursor::new(&[4; 64][..])).is_err());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue