bip32: Add serde for Extended(Priv|Pub)Key
This commit is contained in:
parent
c93a70487f
commit
3c66418f3a
|
@ -400,6 +400,63 @@ macro_rules! serde_struct_impl {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
macro_rules! serde_string_impl {
|
||||||
|
($name:ident, $expecting:expr) => {
|
||||||
|
#[cfg(feature = "serde")]
|
||||||
|
impl<'de> $crate::serde::Deserialize<'de> for $name {
|
||||||
|
fn deserialize<D>(deserializer: D) -> Result<$name, D::Error>
|
||||||
|
where
|
||||||
|
D: $crate::serde::de::Deserializer<'de>,
|
||||||
|
{
|
||||||
|
use std::fmt::{self, Formatter};
|
||||||
|
use std::str::FromStr;
|
||||||
|
|
||||||
|
struct Visitor;
|
||||||
|
impl<'de> $crate::serde::de::Visitor<'de> for Visitor {
|
||||||
|
type Value = $name;
|
||||||
|
|
||||||
|
fn expecting(&self, formatter: &mut Formatter) -> fmt::Result {
|
||||||
|
formatter.write_str($expecting)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
|
||||||
|
where
|
||||||
|
E: $crate::serde::de::Error,
|
||||||
|
{
|
||||||
|
$name::from_str(v).map_err(E::custom)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_borrowed_str<E>(self, v: &'de str) -> Result<Self::Value, E>
|
||||||
|
where
|
||||||
|
E: $crate::serde::de::Error,
|
||||||
|
{
|
||||||
|
self.visit_str(v)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_string<E>(self, v: String) -> Result<Self::Value, E>
|
||||||
|
where
|
||||||
|
E: $crate::serde::de::Error,
|
||||||
|
{
|
||||||
|
self.visit_str(&v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
deserializer.deserialize_str(Visitor)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "serde")]
|
||||||
|
impl<'de> $crate::serde::Serialize for $name {
|
||||||
|
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||||
|
where
|
||||||
|
S: $crate::serde::Serializer,
|
||||||
|
{
|
||||||
|
serializer.serialize_str(&self.to_string())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
macro_rules! user_enum {
|
macro_rules! user_enum {
|
||||||
(
|
(
|
||||||
$(#[$attr:meta])*
|
$(#[$attr:meta])*
|
||||||
|
|
|
@ -46,9 +46,6 @@ use std::str::FromStr;
|
||||||
use bitcoin_bech32::{self, WitnessProgram, u5};
|
use bitcoin_bech32::{self, WitnessProgram, u5};
|
||||||
use bitcoin_hashes::{hash160, Hash};
|
use bitcoin_hashes::{hash160, Hash};
|
||||||
|
|
||||||
#[cfg(feature = "serde")]
|
|
||||||
use serde;
|
|
||||||
|
|
||||||
use blockdata::opcodes;
|
use blockdata::opcodes;
|
||||||
use blockdata::script;
|
use blockdata::script;
|
||||||
use network::constants::Network;
|
use network::constants::Network;
|
||||||
|
@ -75,6 +72,7 @@ pub struct Address {
|
||||||
/// The network on which this address is usable
|
/// The network on which this address is usable
|
||||||
pub network: Network,
|
pub network: Network,
|
||||||
}
|
}
|
||||||
|
serde_string_impl!(Address, "a Bitcoin address");
|
||||||
|
|
||||||
impl Address {
|
impl Address {
|
||||||
/// Creates a pay to (compressed) public key hash address from a public key
|
/// Creates a pay to (compressed) public key hash address from a public key
|
||||||
|
@ -299,59 +297,6 @@ impl ::std::fmt::Debug for Address {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "serde")]
|
|
||||||
impl<'de> serde::Deserialize<'de> for Address {
|
|
||||||
#[inline]
|
|
||||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
|
||||||
where
|
|
||||||
D: serde::Deserializer<'de>,
|
|
||||||
{
|
|
||||||
use std::fmt::{self, Formatter};
|
|
||||||
|
|
||||||
struct Visitor;
|
|
||||||
impl<'de> serde::de::Visitor<'de> for Visitor {
|
|
||||||
type Value = Address;
|
|
||||||
|
|
||||||
fn expecting(&self, formatter: &mut Formatter) -> fmt::Result {
|
|
||||||
formatter.write_str("a Bitcoin address")
|
|
||||||
}
|
|
||||||
|
|
||||||
fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
|
|
||||||
where
|
|
||||||
E: serde::de::Error,
|
|
||||||
{
|
|
||||||
Address::from_str(v).map_err(E::custom)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn visit_borrowed_str<E>(self, v: &'de str) -> Result<Self::Value, E>
|
|
||||||
where
|
|
||||||
E: serde::de::Error,
|
|
||||||
{
|
|
||||||
self.visit_str(v)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn visit_string<E>(self, v: String) -> Result<Self::Value, E>
|
|
||||||
where
|
|
||||||
E: serde::de::Error,
|
|
||||||
{
|
|
||||||
self.visit_str(&v)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
deserializer.deserialize_str(Visitor)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(feature = "serde")]
|
|
||||||
impl serde::Serialize for Address {
|
|
||||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
|
||||||
where
|
|
||||||
S: serde::Serializer,
|
|
||||||
{
|
|
||||||
serializer.serialize_str(&self.to_string())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
|
|
@ -62,6 +62,7 @@ pub struct ExtendedPrivKey {
|
||||||
/// Chain code
|
/// Chain code
|
||||||
pub chain_code: ChainCode
|
pub chain_code: ChainCode
|
||||||
}
|
}
|
||||||
|
serde_string_impl!(ExtendedPrivKey, "a BIP-32 extended private key");
|
||||||
|
|
||||||
/// Extended public key
|
/// Extended public key
|
||||||
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
|
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
|
||||||
|
@ -79,6 +80,7 @@ pub struct ExtendedPubKey {
|
||||||
/// Chain code
|
/// Chain code
|
||||||
pub chain_code: ChainCode
|
pub chain_code: ChainCode
|
||||||
}
|
}
|
||||||
|
serde_string_impl!(ExtendedPubKey, "a BIP-32 extended public key");
|
||||||
|
|
||||||
/// A child number for a derived key
|
/// A child number for a derived key
|
||||||
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
|
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
|
||||||
|
@ -213,6 +215,7 @@ impl serde::Serialize for ChildNumber {
|
||||||
#[derive(Clone, PartialEq, Eq)]
|
#[derive(Clone, PartialEq, Eq)]
|
||||||
pub struct DerivationPath(Vec<ChildNumber>);
|
pub struct DerivationPath(Vec<ChildNumber>);
|
||||||
impl_index_newtype!(DerivationPath, ChildNumber);
|
impl_index_newtype!(DerivationPath, ChildNumber);
|
||||||
|
serde_string_impl!(DerivationPath, "a BIP-32 derivation path");
|
||||||
|
|
||||||
impl From<Vec<ChildNumber>> for DerivationPath {
|
impl From<Vec<ChildNumber>> for DerivationPath {
|
||||||
fn from(numbers: Vec<ChildNumber>) -> Self {
|
fn from(numbers: Vec<ChildNumber>) -> Self {
|
||||||
|
@ -349,44 +352,6 @@ impl fmt::Debug for DerivationPath {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "serde")]
|
|
||||||
impl<'de> serde::Deserialize<'de> for DerivationPath {
|
|
||||||
fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
|
|
||||||
use std::fmt;
|
|
||||||
use serde::de;
|
|
||||||
|
|
||||||
struct Visitor;
|
|
||||||
impl<'de> de::Visitor<'de> for Visitor {
|
|
||||||
type Value = DerivationPath;
|
|
||||||
|
|
||||||
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
|
||||||
formatter.write_str("a Bitcoin address")
|
|
||||||
}
|
|
||||||
|
|
||||||
fn visit_str<E: de::Error>(self, v: &str) -> Result<Self::Value, E> {
|
|
||||||
DerivationPath::from_str(v).map_err(E::custom)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn visit_borrowed_str<E: de::Error>(self, v: &'de str) -> Result<Self::Value, E> {
|
|
||||||
self.visit_str(v)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn visit_string<E: de::Error>(self, v: String) -> Result<Self::Value, E> {
|
|
||||||
self.visit_str(&v)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
deserializer.deserialize_str(Visitor)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(feature = "serde")]
|
|
||||||
impl serde::Serialize for DerivationPath {
|
|
||||||
fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
|
|
||||||
serializer.serialize_str(&self.to_string())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// A BIP32 error
|
/// A BIP32 error
|
||||||
#[derive(Clone, PartialEq, Eq, Debug)]
|
#[derive(Clone, PartialEq, Eq, Debug)]
|
||||||
pub enum Error {
|
pub enum Error {
|
||||||
|
|
Loading…
Reference in New Issue