sapio_bitcoin/util/
key.rs

1// Rust Bitcoin Library
2// Written in 2014 by
3//     Andrew Poelstra <apoelstra@wpsoftware.net>
4// To the extent possible under law, the author(s) have dedicated all
5// copyright and related and neighboring rights to this software to
6// the public domain worldwide. This software is distributed without
7// any warranty.
8//
9// You should have received a copy of the CC0 Public Domain Dedication
10// along with this software.
11// If not, see <http://creativecommons.org/publicdomain/zero/1.0/>.
12//
13
14//! Bitcoin keys.
15//!
16//! This module provides keys used in Bitcoin that can be roundtrip
17//! (de)serialized.
18
19pub use secp256k1::{XOnlyPublicKey, Keypair as KeyPair};
20
21use prelude::*;
22
23use core::{ops, str::FromStr};
24use core::fmt::{self, Write as _fmtWrite};
25use io;
26#[cfg(feature = "std")] use std::error;
27
28use secp256k1::{self, Secp256k1};
29use network::constants::Network;
30use hashes::{Hash, hash160, hex, hex::FromHex};
31use hash_types::{PubkeyHash, WPubkeyHash};
32use util::base58;
33#[cfg(feature = "schemars")] use schemars::schema::{Schema, SchemaObject};
34#[cfg(feature = "schemars")] use schemars::{gen::SchemaGenerator, JsonSchema};
35
36/// A key-related error.
37#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
38pub enum Error {
39    /// Base58 encoding error
40    Base58(base58::Error),
41    /// secp256k1-related error
42    Secp256k1(secp256k1::Error),
43    /// Invalid key prefix error
44    InvalidKeyPrefix(u8),
45    /// Hex decoding error
46    Hex(hex::Error)
47}
48
49impl fmt::Display for Error {
50    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
51        match *self {
52            Error::Base58(ref e) => write!(f, "Key base58 error: {}", e),
53            Error::Secp256k1(ref e) => write!(f, "Key secp256k1 error: {}", e),
54            Error::InvalidKeyPrefix(ref e) => write!(f, "Key prefix invalid: {}", e),
55            Error::Hex(ref e) => write!(f, "Key hex decoding error: {}", e)
56        }
57    }
58}
59
60#[cfg(feature = "std")]
61#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
62impl ::std::error::Error for Error {
63    fn cause(&self) -> Option<&dyn error::Error> {
64        match *self {
65            Error::Base58(ref e) => Some(e),
66            Error::Secp256k1(ref e) => Some(e),
67            Error::InvalidKeyPrefix(_) => None,
68            Error::Hex(ref e) => Some(e)
69        }
70    }
71}
72
73#[doc(hidden)]
74impl From<base58::Error> for Error {
75    fn from(e: base58::Error) -> Error {
76        Error::Base58(e)
77    }
78}
79
80#[doc(hidden)]
81impl From<secp256k1::Error> for Error {
82    fn from(e: secp256k1::Error) -> Error {
83        Error::Secp256k1(e)
84    }
85}
86
87#[doc(hidden)]
88impl From<hex::Error> for Error {
89    fn from(e: hex::Error) -> Self {
90        Error::Hex(e)
91    }
92}
93
94
95/// A Bitcoin ECDSA public key
96#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
97pub struct PublicKey {
98    /// Whether this public key should be serialized as compressed
99    pub compressed: bool,
100    /// The actual ECDSA key
101    pub inner: secp256k1::PublicKey,
102}
103
104impl PublicKey {
105    /// Constructs compressed ECDSA public key from the provided generic Secp256k1 public key
106    pub fn new(key: secp256k1::PublicKey) -> PublicKey {
107        PublicKey {
108            compressed: true,
109            inner: key,
110        }
111    }
112
113    /// Constructs uncompressed (legacy) ECDSA public key from the provided generic Secp256k1
114    /// public key
115    pub fn new_uncompressed(key: secp256k1::PublicKey) -> PublicKey {
116        PublicKey {
117            compressed: false,
118            inner: key,
119        }
120    }
121
122    /// Returns bitcoin 160-bit hash of the public key
123    pub fn pubkey_hash(&self) -> PubkeyHash {
124        if self.compressed {
125            PubkeyHash::hash(&self.inner.serialize())
126        } else {
127            PubkeyHash::hash(&self.inner.serialize_uncompressed())
128        }
129    }
130
131    /// Returns bitcoin 160-bit hash of the public key for witness program
132    pub fn wpubkey_hash(&self) -> Option<WPubkeyHash> {
133        if self.compressed {
134            Some(WPubkeyHash::from_inner(
135                hash160::Hash::hash(&self.inner.serialize()).into_inner()
136            ))
137        } else {
138            // We can't create witness pubkey hashes for an uncompressed
139            // public keys
140            None
141        }
142    }
143
144    /// Write the public key into a writer
145    pub fn write_into<W: io::Write>(&self, mut writer: W) -> Result<(), io::Error> {
146        if self.compressed {
147            writer.write_all(&self.inner.serialize())
148        } else {
149            writer.write_all(&self.inner.serialize_uncompressed())
150        }
151    }
152
153    /// Read the public key from a reader
154    ///
155    /// This internally reads the first byte before reading the rest, so
156    /// use of a `BufReader` is recommended.
157    pub fn read_from<R: io::Read>(mut reader: R) -> Result<Self, io::Error> {
158        let mut bytes = [0; 65];
159
160        reader.read_exact(&mut bytes[0..1])?;
161        let bytes = if bytes[0] < 4 { &mut bytes[..33] } else { &mut bytes[..65] };
162
163        reader.read_exact(&mut bytes[1..])?;
164        Self::from_slice(bytes).map_err(|e| {
165            // Need a static string for core2
166            #[cfg(feature = "std")]
167            let reason = e;
168            #[cfg(not(feature = "std"))]
169            let reason = match e {
170                Error::Base58(_) => "base58 error",
171                Error::Secp256k1(_) => "secp256k1 error",
172                Error::InvalidKeyPrefix(_) => "invalid key prefix",
173                Error::Hex(_) => "hex decoding error"
174            };
175            io::Error::new(io::ErrorKind::InvalidData, reason)
176        })
177    }
178
179    /// Serialize the public key to bytes
180    pub fn to_bytes(&self) -> Vec<u8> {
181        let mut buf = Vec::new();
182        self.write_into(&mut buf).expect("vecs don't error");
183        buf
184    }
185
186    /// Deserialize a public key from a slice
187    pub fn from_slice(data: &[u8]) -> Result<PublicKey, Error> {
188        let compressed = match data.len() {
189            33 => true,
190            65 => false,
191            len =>  {
192                return Err(base58::Error::InvalidLength(len).into());
193            },
194        };
195
196        if !compressed && data[0] != 0x04 {
197            return Err(Error::InvalidKeyPrefix(data[0]))
198        }
199
200        Ok(PublicKey {
201            compressed,
202            inner: secp256k1::PublicKey::from_slice(data)?,
203        })
204    }
205
206    /// Computes the public key as supposed to be used with this secret
207    pub fn from_private_key<C: secp256k1::Signing>(secp: &Secp256k1<C>, sk: &PrivateKey) -> PublicKey {
208        sk.public_key(secp)
209    }
210}
211
212impl fmt::Display for PublicKey {
213    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
214        if self.compressed {
215            for ch in &self.inner.serialize()[..] {
216                write!(f, "{:02x}", ch)?;
217            }
218        } else {
219            for ch in &self.inner.serialize_uncompressed()[..] {
220                write!(f, "{:02x}", ch)?;
221            }
222        }
223        Ok(())
224    }
225}
226
227#[cfg(feature = "schemars")]
228impl JsonSchema for PublicKey {
229    fn schema_name() -> String {
230        "PublicKey".into()
231    }
232    fn json_schema(gen: &mut SchemaGenerator) -> Schema {
233        let mut schema: SchemaObject = <String>::json_schema(gen).into();
234        const PAT: &'static str = "^([0-9a-fA-F]{2})*$";
235        schema.string = Some(Box::new(schemars::schema::StringValidation {
236            max_length: Some(65*2),
237            min_length: Some(33*2),
238            pattern: Some(PAT.to_owned()),
239        }));
240        schema.into()
241    }
242}
243
244
245impl FromStr for PublicKey {
246    type Err = Error;
247    fn from_str(s: &str) -> Result<PublicKey, Error> {
248        match s.len() {
249            66 => PublicKey::from_slice(&<[u8; 33]>::from_hex(s)?),
250            130 => PublicKey::from_slice(&<[u8; 65]>::from_hex(s)?),
251            len => return Err(Error::Hex(hex::Error::InvalidLength(66, len)))
252        }
253    }
254}
255
256/// A Bitcoin ECDSA private key
257#[derive(Copy, Clone, PartialEq, Eq)]
258#[cfg_attr(feature = "std", derive(Debug))]
259pub struct PrivateKey {
260    /// Whether this private key should be serialized as compressed
261    pub compressed: bool,
262    /// The network on which this key should be used
263    pub network: Network,
264    /// The actual ECDSA key
265    pub inner: secp256k1::SecretKey,
266}
267
268impl PrivateKey {
269    /// Constructs compressed ECDSA private key from the provided generic Secp256k1 private key
270    /// and the specified network
271    pub fn new(key: secp256k1::SecretKey, network: Network) -> PrivateKey {
272        PrivateKey {
273            compressed: true,
274            network,
275            inner: key,
276        }
277    }
278
279    /// Constructs uncompressed (legacy) ECDSA private key from the provided generic Secp256k1
280    /// private key and the specified network
281    pub fn new_uncompressed(key: secp256k1::SecretKey, network: Network) -> PrivateKey {
282        PrivateKey {
283            compressed: false,
284            network,
285            inner: key,
286        }
287    }
288
289    /// Creates a public key from this private key
290    pub fn public_key<C: secp256k1::Signing>(&self, secp: &Secp256k1<C>) -> PublicKey {
291        PublicKey {
292            compressed: self.compressed,
293            inner: secp256k1::PublicKey::from_secret_key(secp, &self.inner)
294        }
295    }
296
297    /// Serialize the private key to bytes
298    pub fn to_bytes(&self) -> Vec<u8> {
299        self.inner[..].to_vec()
300    }
301
302    /// Deserialize a private key from a slice
303    pub fn from_slice(data: &[u8], network: Network) -> Result<PrivateKey, Error> {
304        Ok(PrivateKey::new(secp256k1::SecretKey::from_slice(data)?, network))
305    }
306
307    /// Format the private key to WIF format.
308    pub fn fmt_wif(&self, fmt: &mut dyn fmt::Write) -> fmt::Result {
309        let mut ret = [0; 34];
310        ret[0] = match self.network {
311            Network::Bitcoin => 128,
312            Network::Testnet | Network::Signet | Network::Regtest => 239,
313        };
314        ret[1..33].copy_from_slice(&self.inner[..]);
315        let privkey = if self.compressed {
316            ret[33] = 1;
317            base58::check_encode_slice(&ret[..])
318        } else {
319            base58::check_encode_slice(&ret[..33])
320        };
321        fmt.write_str(&privkey)
322    }
323
324    /// Get WIF encoding of this private key.
325    pub fn to_wif(&self) -> String {
326        let mut buf = String::new();
327        buf.write_fmt(format_args!("{}", self)).unwrap();
328        buf.shrink_to_fit();
329        buf
330    }
331
332    /// Parse WIF encoded private key.
333    pub fn from_wif(wif: &str) -> Result<PrivateKey, Error> {
334        let data = base58::from_check(wif)?;
335
336        let compressed = match data.len() {
337            33 => false,
338            34 => true,
339            _ => {
340                return Err(Error::Base58(base58::Error::InvalidLength(data.len())));
341            }
342        };
343
344        let network = match data[0] {
345            128 => Network::Bitcoin,
346            239 => Network::Testnet,
347            x   => {
348                return Err(Error::Base58(base58::Error::InvalidAddressVersion(x)));
349            }
350        };
351
352        Ok(PrivateKey {
353            compressed,
354            network,
355            inner: secp256k1::SecretKey::from_slice(&data[1..33])?,
356        })
357    }
358}
359
360impl fmt::Display for PrivateKey {
361    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
362        self.fmt_wif(f)
363    }
364}
365
366#[cfg(feature = "schemars")]
367impl JsonSchema for PrivateKey {
368    fn schema_name() -> String {
369        "PrivateKey".into()
370    }
371    fn json_schema(gen: &mut SchemaGenerator) -> Schema {
372        let mut schema: SchemaObject = <String>::json_schema(gen).into();
373        // Base 58 Regex
374        const PAT: &'static str = "^[5KLc9][1-9A-HJ-NP-Za-km-z]{50,51}$";
375        schema.string = Some(Box::new(schemars::schema::StringValidation {
376            max_length: Some(52),
377            min_length: Some(51),
378            pattern: Some(PAT.to_owned()),
379        }));
380        schema.into()
381    }
382}
383
384#[cfg(not(feature = "std"))]
385impl fmt::Debug for PrivateKey {
386    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
387        write!(f, "[private key data]")
388    }
389}
390
391impl FromStr for PrivateKey {
392    type Err = Error;
393    fn from_str(s: &str) -> Result<PrivateKey, Error> {
394        PrivateKey::from_wif(s)
395    }
396}
397
398impl ops::Index<ops::RangeFull> for PrivateKey {
399    type Output = [u8];
400    fn index(&self, _: ops::RangeFull) -> &[u8] {
401        &self.inner[..]
402    }
403}
404
405#[cfg(feature = "serde")]
406#[cfg_attr(docsrs, doc(cfg(feature = "serde")))]
407impl ::serde::Serialize for PrivateKey {
408    fn serialize<S: ::serde::Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
409        s.collect_str(self)
410    }
411}
412
413#[cfg(feature = "serde")]
414#[cfg_attr(docsrs, doc(cfg(feature = "serde")))]
415impl<'de> ::serde::Deserialize<'de> for PrivateKey {
416    fn deserialize<D: ::serde::Deserializer<'de>>(d: D) -> Result<PrivateKey, D::Error> {
417        struct WifVisitor;
418
419        impl<'de> ::serde::de::Visitor<'de> for WifVisitor {
420            type Value = PrivateKey;
421
422            fn expecting(&self, formatter: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
423                formatter.write_str("an ASCII WIF string")
424            }
425
426            fn visit_bytes<E>(self, v: &[u8]) -> Result<Self::Value, E>
427            where
428                E: ::serde::de::Error,
429            {
430                if let Ok(s) = ::core::str::from_utf8(v) {
431                    PrivateKey::from_str(s).map_err(E::custom)
432                } else {
433                    Err(E::invalid_value(::serde::de::Unexpected::Bytes(v), &self))
434                }
435            }
436
437            fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
438            where
439                E: ::serde::de::Error,
440            {
441                PrivateKey::from_str(v).map_err(E::custom)
442            }
443        }
444
445        d.deserialize_str(WifVisitor)
446    }
447}
448
449#[cfg(feature = "serde")]
450#[cfg_attr(docsrs, doc(cfg(feature = "serde")))]
451impl ::serde::Serialize for PublicKey {
452    fn serialize<S: ::serde::Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
453        if s.is_human_readable() {
454            s.collect_str(self)
455        } else {
456            if self.compressed {
457                s.serialize_bytes(&self.inner.serialize()[..])
458            } else {
459                s.serialize_bytes(&self.inner.serialize_uncompressed()[..])
460            }
461        }
462    }
463}
464
465#[cfg(feature = "serde")]
466#[cfg_attr(docsrs, doc(cfg(feature = "serde")))]
467impl<'de> ::serde::Deserialize<'de> for PublicKey {
468    fn deserialize<D: ::serde::Deserializer<'de>>(d: D) -> Result<PublicKey, D::Error> {
469        if d.is_human_readable() {
470            struct HexVisitor;
471
472            impl<'de> ::serde::de::Visitor<'de> for HexVisitor {
473                type Value = PublicKey;
474
475                fn expecting(&self, formatter: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
476                    formatter.write_str("an ASCII hex string")
477                }
478
479                fn visit_bytes<E>(self, v: &[u8]) -> Result<Self::Value, E>
480                where
481                    E: ::serde::de::Error,
482                {
483                    if let Ok(hex) = ::core::str::from_utf8(v) {
484                        PublicKey::from_str(hex).map_err(E::custom)
485                    } else {
486                        Err(E::invalid_value(::serde::de::Unexpected::Bytes(v), &self))
487                    }
488                }
489
490                fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
491                where
492                    E: ::serde::de::Error,
493                {
494                    PublicKey::from_str(v).map_err(E::custom)
495                }
496            }
497            d.deserialize_str(HexVisitor)
498        } else {
499            struct BytesVisitor;
500
501            impl<'de> ::serde::de::Visitor<'de> for BytesVisitor {
502                type Value = PublicKey;
503
504                fn expecting(&self, formatter: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
505                    formatter.write_str("a bytestring")
506                }
507
508                fn visit_bytes<E>(self, v: &[u8]) -> Result<Self::Value, E>
509                where
510                    E: ::serde::de::Error,
511                {
512                    PublicKey::from_slice(v).map_err(E::custom)
513                }
514            }
515
516            d.deserialize_bytes(BytesVisitor)
517        }
518    }
519}
520
521#[cfg(test)]
522mod tests {
523    use io;
524    use super::{PrivateKey, PublicKey};
525    use secp256k1::Secp256k1;
526    use std::str::FromStr;
527    use hashes::hex::ToHex;
528    use network::constants::Network::Testnet;
529    use network::constants::Network::Bitcoin;
530    use util::address::Address;
531
532    #[test]
533    fn test_key_derivation() {
534        // testnet compressed
535        let sk = PrivateKey::from_wif("cVt4o7BGAig1UXywgGSmARhxMdzP5qvQsxKkSsc1XEkw3tDTQFpy").unwrap();
536        assert_eq!(sk.network, Testnet);
537        assert_eq!(sk.compressed, true);
538        assert_eq!(&sk.to_wif(), "cVt4o7BGAig1UXywgGSmARhxMdzP5qvQsxKkSsc1XEkw3tDTQFpy");
539
540        let secp = Secp256k1::new();
541        let pk = Address::p2pkh(&sk.public_key(&secp), sk.network);
542        assert_eq!(&pk.to_string(), "mqwpxxvfv3QbM8PU8uBx2jaNt9btQqvQNx");
543
544        // test string conversion
545        assert_eq!(&sk.to_string(), "cVt4o7BGAig1UXywgGSmARhxMdzP5qvQsxKkSsc1XEkw3tDTQFpy");
546        let sk_str =
547            PrivateKey::from_str("cVt4o7BGAig1UXywgGSmARhxMdzP5qvQsxKkSsc1XEkw3tDTQFpy").unwrap();
548        assert_eq!(&sk.to_wif(), &sk_str.to_wif());
549
550        // mainnet uncompressed
551        let sk = PrivateKey::from_wif("5JYkZjmN7PVMjJUfJWfRFwtuXTGB439XV6faajeHPAM9Z2PT2R3").unwrap();
552        assert_eq!(sk.network, Bitcoin);
553        assert_eq!(sk.compressed, false);
554        assert_eq!(&sk.to_wif(), "5JYkZjmN7PVMjJUfJWfRFwtuXTGB439XV6faajeHPAM9Z2PT2R3");
555
556        let secp = Secp256k1::new();
557        let mut pk = sk.public_key(&secp);
558        assert_eq!(pk.compressed, false);
559        assert_eq!(&pk.to_string(), "042e58afe51f9ed8ad3cc7897f634d881fdbe49a81564629ded8156bebd2ffd1af191923a2964c177f5b5923ae500fca49e99492d534aa3759d6b25a8bc971b133");
560        assert_eq!(pk, PublicKey::from_str("042e58afe51f9ed8ad3cc7897f634d881fdbe49a81564629ded8156bebd2ffd1af191923a2964c177f5b5923ae500fca49e99492d534aa3759d6b25a8bc971b133").unwrap());
561        let addr = Address::p2pkh(&pk, sk.network);
562        assert_eq!(&addr.to_string(), "1GhQvF6dL8xa6wBxLnWmHcQsurx9RxiMc8");
563        pk.compressed = true;
564        assert_eq!(&pk.to_string(), "032e58afe51f9ed8ad3cc7897f634d881fdbe49a81564629ded8156bebd2ffd1af");
565        assert_eq!(pk, PublicKey::from_str("032e58afe51f9ed8ad3cc7897f634d881fdbe49a81564629ded8156bebd2ffd1af").unwrap());
566    }
567
568    #[test]
569    fn test_pubkey_hash() {
570        let pk = PublicKey::from_str("032e58afe51f9ed8ad3cc7897f634d881fdbe49a81564629ded8156bebd2ffd1af").unwrap();
571        let upk = PublicKey::from_str("042e58afe51f9ed8ad3cc7897f634d881fdbe49a81564629ded8156bebd2ffd1af191923a2964c177f5b5923ae500fca49e99492d534aa3759d6b25a8bc971b133").unwrap();
572        assert_eq!(pk.pubkey_hash().to_hex(), "9511aa27ef39bbfa4e4f3dd15f4d66ea57f475b4");
573        assert_eq!(upk.pubkey_hash().to_hex(), "ac2e7daf42d2c97418fd9f78af2de552bb9c6a7a");
574    }
575
576    #[test]
577    fn test_wpubkey_hash() {
578        let pk = PublicKey::from_str("032e58afe51f9ed8ad3cc7897f634d881fdbe49a81564629ded8156bebd2ffd1af").unwrap();
579        let upk = PublicKey::from_str("042e58afe51f9ed8ad3cc7897f634d881fdbe49a81564629ded8156bebd2ffd1af191923a2964c177f5b5923ae500fca49e99492d534aa3759d6b25a8bc971b133").unwrap();
580        assert_eq!(pk.wpubkey_hash().unwrap().to_hex(), "9511aa27ef39bbfa4e4f3dd15f4d66ea57f475b4");
581        assert_eq!(upk.wpubkey_hash(), None);
582    }
583
584    #[cfg(feature = "serde")]
585    #[test]
586    fn test_key_serde() {
587        use serde_test::{Configure, Token, assert_tokens};
588
589        static KEY_WIF: &'static str = "cVt4o7BGAig1UXywgGSmARhxMdzP5qvQsxKkSsc1XEkw3tDTQFpy";
590        static PK_STR: &'static str = "039b6347398505f5ec93826dc61c19f47c66c0283ee9be980e29ce325a0f4679ef";
591        static PK_STR_U: &'static str = "\
592            04\
593            9b6347398505f5ec93826dc61c19f47c66c0283ee9be980e29ce325a0f4679ef\
594            87288ed73ce47fc4f5c79d19ebfa57da7cff3aff6e819e4ee971d86b5e61875d\
595        ";
596        static PK_BYTES: [u8; 33] = [
597            0x03,
598            0x9b, 0x63, 0x47, 0x39, 0x85, 0x05, 0xf5, 0xec,
599            0x93, 0x82, 0x6d, 0xc6, 0x1c, 0x19, 0xf4, 0x7c,
600            0x66, 0xc0, 0x28, 0x3e, 0xe9, 0xbe, 0x98, 0x0e,
601            0x29, 0xce, 0x32, 0x5a, 0x0f, 0x46, 0x79, 0xef,
602        ];
603        static PK_BYTES_U: [u8; 65] = [
604            0x04,
605            0x9b, 0x63, 0x47, 0x39, 0x85, 0x05, 0xf5, 0xec,
606            0x93, 0x82, 0x6d, 0xc6, 0x1c, 0x19, 0xf4, 0x7c,
607            0x66, 0xc0, 0x28, 0x3e, 0xe9, 0xbe, 0x98, 0x0e,
608            0x29, 0xce, 0x32, 0x5a, 0x0f, 0x46, 0x79, 0xef,
609            0x87, 0x28, 0x8e, 0xd7, 0x3c, 0xe4, 0x7f, 0xc4,
610            0xf5, 0xc7, 0x9d, 0x19, 0xeb, 0xfa, 0x57, 0xda,
611            0x7c, 0xff, 0x3a, 0xff, 0x6e, 0x81, 0x9e, 0x4e,
612            0xe9, 0x71, 0xd8, 0x6b, 0x5e, 0x61, 0x87, 0x5d,
613        ];
614
615        let s = Secp256k1::new();
616        let sk = PrivateKey::from_str(&KEY_WIF).unwrap();
617        let pk = PublicKey::from_private_key(&s, &sk);
618        let pk_u = PublicKey {
619            inner: pk.inner,
620            compressed: false,
621        };
622
623        assert_tokens(&sk, &[Token::BorrowedStr(KEY_WIF)]);
624        assert_tokens(&pk.compact(), &[Token::BorrowedBytes(&PK_BYTES[..])]);
625        assert_tokens(&pk.readable(), &[Token::BorrowedStr(PK_STR)]);
626        assert_tokens(&pk_u.compact(), &[Token::BorrowedBytes(&PK_BYTES_U[..])]);
627        assert_tokens(&pk_u.readable(), &[Token::BorrowedStr(PK_STR_U)]);
628
629        #[cfg(feature = "schemars")] {
630            {
631                let js = serde_json::from_str(&serde_json::to_string(&sk).unwrap()).unwrap();
632                let s = schemars::schema_for!(PrivateKey);
633                let string_schema = serde_json::to_string_pretty(&s).unwrap();
634                let schema = serde_json::from_str(&string_schema).unwrap();
635
636                assert!(jsonschema_valid::is_valid(&js, &schema, None, true));
637            }
638
639            {
640
641                let js = serde_json::from_str(&serde_json::to_string(&pk).unwrap()).unwrap();
642                let s = schemars::schema_for!(PublicKey);
643                let string_schema = serde_json::to_string_pretty(&s).unwrap();
644                let schema = serde_json::from_str(&string_schema).unwrap();
645
646                assert!(jsonschema_valid::is_valid(&js, &schema, None, true));
647            }
648
649            {
650
651                let js = serde_json::from_str(&serde_json::to_string(&pk_u).unwrap()).unwrap();
652                let s = schemars::schema_for!(PublicKey);
653                let string_schema = serde_json::to_string_pretty(&s).unwrap();
654                let schema = serde_json::from_str(&string_schema).unwrap();
655
656                assert!(jsonschema_valid::is_valid(&js, &schema, None, true));
657            }
658        }
659    }
660
661    fn random_key(mut seed: u8) -> PublicKey {
662        loop {
663            let mut data = [0; 65];
664            for byte in &mut data[..] {
665                *byte = seed;
666                // totally a rng
667                seed = seed.wrapping_mul(41).wrapping_add(43);
668            }
669            if data[0] % 2 == 0 {
670                data[0] = 4;
671                if let Ok(key) = PublicKey::from_slice(&data[..]) {
672                    return key;
673                }
674            } else {
675                data[0] = 2 + (data[0] >> 7);
676                if let Ok(key) = PublicKey::from_slice(&data[..33]) {
677                    return key;
678                }
679            }
680        }
681    }
682
683    #[test]
684    fn pubkey_read_write() {
685        const N_KEYS: usize = 20;
686        let keys: Vec<_> = (0..N_KEYS).map(|i| random_key(i as u8)).collect();
687
688        let mut v = vec![];
689        for k in &keys {
690            k.write_into(&mut v).expect("writing into vec");
691        }
692
693        let mut dec_keys = vec![];
694        let mut cursor = io::Cursor::new(&v);
695        for _ in 0..N_KEYS {
696            dec_keys.push(PublicKey::read_from(&mut cursor).expect("reading from vec"));
697        }
698
699        assert_eq!(keys, dec_keys);
700
701        // sanity checks
702        assert!(PublicKey::read_from(&mut cursor).is_err());
703        assert!(PublicKey::read_from(io::Cursor::new(&[])).is_err());
704        assert!(PublicKey::read_from(io::Cursor::new(&[0; 33][..])).is_err());
705        assert!(PublicKey::read_from(io::Cursor::new(&[2; 32][..])).is_err());
706        assert!(PublicKey::read_from(io::Cursor::new(&[0; 65][..])).is_err());
707        assert!(PublicKey::read_from(io::Cursor::new(&[4; 64][..])).is_err());
708    }
709}