pub mod ecc_compact;
pub mod ed25519;
pub mod secp256k1;
#[cfg(feature = "ecc608")]
pub mod ecc608;
#[cfg(feature = "tpm")]
pub mod tpm;
#[cfg(feature = "multisig")]
pub mod multisig;
#[cfg(feature = "multisig")]
pub use multihash;
pub mod error;
pub mod public_key;
pub mod public_key_binary;
mod keypair;
pub use error::{Error, Result};
pub use keypair::{Keypair, Sign};
pub use public_key::{PublicKey, PublicKeySize, Verify};
pub use public_key_binary::PublicKeyBinary;
use std::{
convert::{From, TryFrom, TryInto},
fmt,
hash::Hash,
str::FromStr,
};
#[derive(Debug, PartialEq, Eq, Clone, Hash, serde::Deserialize, PartialOrd, Ord)]
#[serde(rename_all = "lowercase")]
pub enum Network {
MainNet,
TestNet,
}
impl Copy for Network {}
impl Default for Network {
fn default() -> Self {
Self::MainNet
}
}
#[derive(Debug, PartialEq, Eq, Clone, serde::Deserialize)]
#[serde(rename_all = "lowercase")]
pub enum KeyType {
Secp256k1,
Ed25519,
#[serde(rename = "ecc_compact")]
EccCompact,
#[cfg(feature = "multisig")]
MultiSig,
}
impl Copy for KeyType {}
impl Default for KeyType {
fn default() -> Self {
Self::Ed25519
}
}
#[derive(Debug, Default, PartialEq, Eq, Clone)]
pub struct KeyTag {
pub network: Network,
pub key_type: KeyType,
}
impl Copy for KeyTag {}
impl TryFrom<u8> for KeyTag {
type Error = Error;
fn try_from(v: u8) -> Result<Self> {
Ok(KeyTag {
network: v.try_into()?,
key_type: v.try_into()?,
})
}
}
impl From<KeyTag> for u8 {
fn from(v: KeyTag) -> Self {
u8::from(v.network) | u8::from(v.key_type)
}
}
impl TryFrom<u8> for Network {
type Error = Error;
fn try_from(v: u8) -> Result<Self> {
match v & 0xF0 {
NETTYPE_MAIN => Ok(Self::MainNet),
NETTYPE_TEST => Ok(Self::TestNet),
_ => Err(Error::invalid_keytype(v)),
}
}
}
impl FromStr for Network {
type Err = Error;
fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
match s {
NETTYPE_MAIN_STR => Ok(Self::MainNet),
NETTYPE_TEST_STR => Ok(Self::TestNet),
_ => Err(Error::invalid_keytype_str(s)),
}
}
}
impl fmt::Display for Network {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> std::result::Result<(), fmt::Error> {
f.write_str(match self {
Self::MainNet => NETTYPE_MAIN_STR,
Self::TestNet => NETTYPE_TEST_STR,
})
}
}
impl From<Network> for u8 {
fn from(v: Network) -> Self {
match v {
Network::MainNet => NETTYPE_MAIN,
Network::TestNet => NETTYPE_TEST,
}
}
}
impl FromStr for KeyType {
type Err = Error;
fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
match s {
KEYTYPE_SECP256K1_STR => Ok(Self::Secp256k1),
KEYTYPE_ED25519_STR => Ok(Self::Ed25519),
KEYTYPE_ECC_COMPACT_STR => Ok(Self::EccCompact),
#[cfg(feature = "multisig")]
KEYTYPE_MULTISIG_STR => Ok(Self::MultiSig),
_ => Err(Error::invalid_keytype_str(s)),
}
}
}
impl fmt::Display for KeyType {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> std::result::Result<(), fmt::Error> {
f.write_str(match self {
Self::Secp256k1 => KEYTYPE_SECP256K1_STR,
Self::Ed25519 => KEYTYPE_ED25519_STR,
Self::EccCompact => KEYTYPE_ECC_COMPACT_STR,
#[cfg(feature = "multisig")]
Self::MultiSig => KEYTYPE_MULTISIG_STR,
})
}
}
impl TryFrom<u8> for KeyType {
type Error = Error;
fn try_from(v: u8) -> Result<Self> {
match v & 0xF {
KEYTYPE_SECP256K1 => Ok(Self::Secp256k1),
KEYTYPE_ED25519 => Ok(Self::Ed25519),
KEYTYPE_ECC_COMPACT => Ok(Self::EccCompact),
#[cfg(feature = "multisig")]
KEYTYPE_MULTISIG => Ok(Self::MultiSig),
_ => Err(Error::invalid_keytype(v)),
}
}
}
impl From<KeyType> for u8 {
fn from(v: KeyType) -> Self {
match v {
KeyType::EccCompact => KEYTYPE_ECC_COMPACT,
KeyType::Ed25519 => KEYTYPE_ED25519,
#[cfg(feature = "multisig")]
KeyType::MultiSig => KEYTYPE_MULTISIG,
KeyType::Secp256k1 => KEYTYPE_SECP256K1,
}
}
}
impl ReadFrom for KeyTag {
fn read_from<R: std::io::Read>(input: &mut R) -> Result<Self> {
let mut buf = [0u8];
input.read_exact(&mut buf)?;
Self::try_from(buf[0])
}
}
pub const KEYTYPE_SECP256K1: u8 = 0x03;
pub const KEYTYPE_MULTISIG: u8 = 0x02;
pub const KEYTYPE_ED25519: u8 = 0x01;
pub const KEYTYPE_ECC_COMPACT: u8 = 0x00;
pub const KEYTYPE_SECP256K1_STR: &str = "secp256k1";
pub const KEYTYPE_MULTISIG_STR: &str = "multisig";
pub const KEYTYPE_ED25519_STR: &str = "ed25519";
pub const KEYTYPE_ECC_COMPACT_STR: &str = "ecc_compact";
pub const NETTYPE_MAIN: u8 = 0x00;
pub const NETTYPE_TEST: u8 = 0x10;
pub const NETTYPE_MAIN_STR: &str = "mainnet";
pub const NETTYPE_TEST_STR: &str = "testnet";
pub trait WriteTo {
fn write_to<W: std::io::Write>(&self, output: &mut W) -> std::io::Result<()>;
}
pub trait ReadFrom {
fn read_from<R: std::io::Read>(input: &mut R) -> Result<Self>
where
Self: Sized;
}
#[cfg(test)]
mod tests {
use super::*;
use serde_test::{assert_de_tokens, assert_de_tokens_error, Token};
#[test]
fn network_can_deserialize() {
assert_de_tokens(
&Network::MainNet,
&[Token::UnitVariant {
name: "Network",
variant: "mainnet",
}],
);
assert_de_tokens(
&Network::TestNet,
&[Token::UnitVariant {
name: "Network",
variant: "testnet",
}],
);
assert_de_tokens_error::<Network>(
&[Token::UnitVariant {
name: "Network",
variant: "other",
}],
"unknown variant `other`, expected `mainnet` or `testnet`",
);
}
#[test]
fn keytype_can_deserialize() {
assert_de_tokens(
&KeyType::Ed25519,
&[Token::UnitVariant {
name: "KeyType",
variant: "ed25519",
}],
);
assert_de_tokens(
&KeyType::EccCompact,
&[Token::UnitVariant {
name: "KeyType",
variant: "ecc_compact",
}],
);
assert_de_tokens(
&KeyType::Secp256k1,
&[Token::UnitVariant {
name: "KeyType",
variant: "secp256k1",
}],
);
let deser_error: &str = if cfg!(feature = "multisig") {
"unknown variant `other`, expected one of `secp256k1`, `ed25519`, `ecc_compact`, `multisig`"
} else {
"unknown variant `other`, expected one of `secp256k1`, `ed25519`, `ecc_compact`"
};
assert_de_tokens_error::<KeyType>(
&[Token::UnitVariant {
name: "KeyType",
variant: "other",
}],
deser_error,
);
}
}