hdwallet_filecoin/
json.rs

1use base64_serde::base64_serde_type;
2use hdwallet::ExtendedPrivKey as SecpExtendedPrivate;
3use secp256k1::SecretKey as SecpPrivate;
4use serde::{Deserialize, Serialize};
5use zeroize::{Zeroize, ZeroizeOnDrop};
6
7use super::secert::SecretKey;
8use crate::error::Error;
9use crate::utils::{bls_deserialize, bls_serialize};
10
11base64_serde_type!(Base64Standard, base64::engine::general_purpose::STANDARD);
12
13#[derive(Serialize, Deserialize, Zeroize)]
14#[serde(rename_all = "lowercase")]
15pub enum SigType {
16    Secp256k1,
17    Bls,
18}
19
20#[derive(Serialize, Deserialize, Zeroize, ZeroizeOnDrop)]
21#[serde(rename_all = "PascalCase")]
22pub struct SecertKeyJson {
23    #[serde(rename = "Type")]
24    pub sig_type: SigType,
25    #[serde(with = "Base64Standard")]
26    pub private_key: Vec<u8>,
27}
28
29impl From<SecretKey> for SecertKeyJson {
30    fn from(value: SecretKey) -> Self {
31        match value {
32            SecretKey::Bls(sk) => Self {
33                sig_type: SigType::Bls,
34                private_key: bls_serialize(&sk).unwrap().to_vec(),
35            },
36            SecretKey::Secp256k1Extended(SecpExtendedPrivate {
37                private_key: sk, ..
38            })
39            | SecretKey::Secp256k1(sk) => Self {
40                sig_type: SigType::Secp256k1,
41                private_key: sk.secret_bytes().to_vec(),
42            },
43        }
44    }
45}
46
47impl TryFrom<SecertKeyJson> for SecretKey {
48    type Error = Error;
49
50    fn try_from(v: SecertKeyJson) -> Result<Self, Self::Error> {
51        match v.sig_type {
52            SigType::Bls => Ok(Self::Bls(bls_deserialize(&v.private_key)?)),
53            SigType::Secp256k1 => Ok(Self::Secp256k1(SecpPrivate::from_slice(&v.private_key)?)),
54        }
55    }
56}
57
58#[cfg(test)]
59mod tests {
60    use data_encoding_macro::hexlower;
61
62    use super::*;
63
64    #[test]
65    fn json_serialize() {
66        let json = r#"{"Type":"bls","PrivateKey":"tm9SKcIie75N6dYTYvOgyKBwgo6epVz1VQwlgTYBuis="}"#;
67        let sk = serde_json::from_str::<SecertKeyJson>(json).unwrap();
68        assert_eq!(json, serde_json::to_string(&sk).unwrap(),);
69    }
70
71    #[test]
72    fn secp_serialize() {
73        let hex = hexlower!("7b2254797065223a22736563703235366b31222c22507269766174654b6579223a226a7244314c48516258503942453964505635787350454237337a717441442b61644c52747a685a6646556f3d227d");
74        let skj = serde_json::from_slice::<SecertKeyJson>(&hex).unwrap();
75        let sk = SecretKey::try_from(skj).unwrap();
76        let addr = sk.public_key().address();
77        assert_eq!(
78            addr.to_string(),
79            "f162husxmdufmecnuuzwzjwlbvuv6vy6hvvzy7x5y"
80        );
81
82        let skj = SecertKeyJson::from(sk);
83        let hex2 = serde_json::to_string(&skj).unwrap();
84        assert_eq!(hex2.as_bytes(), hex);
85    }
86
87    #[test]
88    fn bls_serialize() {
89        let hex = hexlower!("7b2254797065223a22626c73222c22507269766174654b6579223a22746d39534b6349696537354e3664595459764f67794b4277676f366570567a315651776c675459427569733d227d");
90        let skj = serde_json::from_slice::<SecertKeyJson>(&hex).unwrap();
91        let sk = SecretKey::try_from(skj).unwrap();
92        let addr = sk.public_key().address();
93        assert_eq!(addr.to_string(), "f3wo44vs6uyzuzc7dipubydfzrdwfwhjzovcvdx5bqpish5srqx7veq7chbmew4uqiwakzvb6r6gquvt3xvksa");
94
95        let skj = SecertKeyJson::from(sk);
96        let hex2 = serde_json::to_string(&skj).unwrap();
97        assert_eq!(hex2.as_bytes(), hex);
98    }
99}