1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
use crate::crypto::{
    address::Address,
    bip32::{DerivedPublicKey, DerivedSecretKey},
    bip39::Mnemonic,
    bip44::ChildNumber,
    Algorithm,
};
use crate::types::{AccountIdentifier, CurveType, PublicKey};
use anyhow::Result;

/// Signer derives keys from a mnemonic.
pub struct Signer {
    secp256k1: DerivedSecretKey,
    secp256k1_recoverable: DerivedSecretKey,
    secp256r1: DerivedSecretKey,
    ed25519: DerivedSecretKey,
    sr25519: DerivedSecretKey,
}

impl Signer {
    /// Creates a new signer from a mnemonic and password.
    pub fn new(mnemonic: &Mnemonic, password: &str) -> Result<Self> {
        let secp256k1 = DerivedSecretKey::new(mnemonic, password, Algorithm::EcdsaSecp256k1)?;
        let secp256k1_recoverable =
            DerivedSecretKey::new(mnemonic, password, Algorithm::EcdsaRecoverableSecp256k1)?;
        let secp256r1 = DerivedSecretKey::new(mnemonic, password, Algorithm::EcdsaSecp256r1)?;
        let ed25519 = DerivedSecretKey::new(mnemonic, password, Algorithm::Ed25519)?;
        let sr25519 = DerivedSecretKey::new(mnemonic, password, Algorithm::Sr25519)?;
        Ok(Self {
            secp256k1,
            secp256k1_recoverable,
            secp256r1,
            ed25519,
            sr25519,
        })
    }

    /// Creates a new ephemeral signer.
    pub fn generate() -> Result<Self> {
        let mnemonic = crate::mnemonic::generate_mnemonic()?;
        Self::new(&mnemonic, "")
    }

    /// Derives a master key from a mnemonic.
    pub fn master_key(&self, algorithm: Algorithm) -> Result<&DerivedSecretKey> {
        Ok(match algorithm {
            Algorithm::EcdsaSecp256k1 => &self.secp256k1,
            Algorithm::EcdsaRecoverableSecp256k1 => &self.secp256k1_recoverable,
            Algorithm::EcdsaSecp256r1 => &self.secp256r1,
            Algorithm::Ed25519 => &self.ed25519,
            Algorithm::Sr25519 => &self.sr25519,
        })
    }

    /// Derives a bip44 key from a mnemonic.
    pub fn bip44_account(
        &self,
        algorithm: Algorithm,
        coin: u32,
        account: u32,
    ) -> Result<DerivedSecretKey> {
        self.master_key(algorithm)?
            .derive(ChildNumber::hardened_from_u32(44))?
            .derive(ChildNumber::hardened_from_u32(coin))?
            .derive(ChildNumber::hardened_from_u32(account))?
            .derive(ChildNumber::non_hardened_from_u32(0))
    }
}

/// Conversion trait for public keys.
pub trait RosettaPublicKey {
    /// Returns a rosetta public key.
    fn to_rosetta(&self) -> PublicKey;
}

impl RosettaPublicKey for DerivedPublicKey {
    fn to_rosetta(&self) -> PublicKey {
        PublicKey {
            curve_type: match self.public_key().algorithm() {
                Algorithm::EcdsaSecp256k1 => CurveType::Secp256k1,
                Algorithm::EcdsaRecoverableSecp256k1 => CurveType::Secp256k1,
                Algorithm::EcdsaSecp256r1 => CurveType::Secp256r1,
                Algorithm::Ed25519 => CurveType::Edwards25519,
                Algorithm::Sr25519 => CurveType::Schnorrkel,
            },
            hex_bytes: hex::encode(self.public_key().to_bytes()),
        }
    }
}

/// Conversion trait for account identifiers.
pub trait RosettaAccount {
    /// Returns a rosetta account identifier.
    fn to_rosetta(&self) -> AccountIdentifier;
}

impl RosettaAccount for Address {
    fn to_rosetta(&self) -> AccountIdentifier {
        AccountIdentifier {
            address: self.address().into(),
            sub_account: None,
            metadata: None,
        }
    }
}