浏览代码

Merge pull request #62 from Relayz-io/silvestr/improve-keypair

Improve keypair API
develop
Predko Silvestr 2 年前
父节点
当前提交
e1d86bb6c8
没有帐户链接到提交者的电子邮件

+ 26
- 12
.github/workflows/ci.yml 查看文件

@@ -3,7 +3,7 @@ name: CI
3 3
 env:
4 4
   CARGO_TERM_COLOR: always
5 5
 
6
-on: 
6
+on:
7 7
   push:
8 8
     branches:
9 9
       - main
@@ -23,8 +23,8 @@ jobs:
23 23
       - name: Install Rust Toolchain
24 24
         uses: actions-rs/toolchain@v1
25 25
         with:
26
-            toolchain: nightly
27
-            components: rustfmt
26
+          toolchain: nightly
27
+          components: rustfmt
28 28
       - name: cargo fmt
29 29
         run: cargo +nightly fmt -- --check
30 30
   clippy:
@@ -36,14 +36,14 @@ jobs:
36 36
       - name: Install Rust Toolchain
37 37
         uses: actions-rs/toolchain@v1
38 38
         with:
39
-            toolchain: nightly
40
-            components: clippy
39
+          toolchain: nightly
40
+          components: clippy
41 41
       - name: cargo clippy
42
-        run: cargo +nightly clippy --all --tests -- -D warnings
42
+        run: cargo +nightly clippy --workspace --tests -- -D warnings
43 43
       - name: Install wasm32-unknown-unknown
44 44
         run: rustup +nightly target add wasm32-unknown-unknown
45 45
       - name: cargo clippy for wasm32-unknown-unknown
46
-        run: cargo +nightly clippy --all --target wasm32-unknown-unknown -- -D warnings
46
+        run: cargo +nightly clippy --workspace --target wasm32-unknown-unknown -- -D warnings
47 47
   build:
48 48
     name: build
49 49
     needs: [clippy, fmt]
@@ -53,10 +53,24 @@ jobs:
53 53
       - name: Install Rust Toolchain
54 54
         uses: actions-rs/toolchain@v1
55 55
         with:
56
-            toolchain: stable
56
+          toolchain: stable
57 57
       - name: Install wasm32-unknown-unknown
58 58
         run: rustup target add wasm32-unknown-unknown
59
-      - name: cargo build [wasm-client, near-client] for wasm
60
-        run: cargo build --all --target wasm32-unknown-unknown --release
61
-      - name: cargo build [near-client]
62
-        run: cargo build --all --release
59
+      - name: cargo build [web-client, near-client, common-api] for wasm
60
+        run: cargo build -p web-client -p near-client -p common-api --target wasm32-unknown-unknown --release
61
+      - name: cargo build [near-client, common-api]
62
+        run: cargo build -p near-client -p common-api --tests --release
63
+  tests:
64
+    name: tests
65
+    needs: [clippy, fmt]
66
+    runs-on: ubuntu-latest
67
+    steps:
68
+      - uses: actions/checkout@v3
69
+      - name: Install Rust Toolchain
70
+        uses: actions-rs/toolchain@v1
71
+        with:
72
+          toolchain: stable
73
+      - name: Run unit-tests for [common-api]
74
+        run: cargo test -p common-api crypto
75
+      - name: Run integration-tests for [common-api]
76
+        run: cargo test -p common-api --test crypto

+ 0
- 16
.github/workflows/issue-link.yml 查看文件

@@ -1,16 +0,0 @@
1
-name: 'Issue Links'
2
-on:
3
-  pull_request:
4
-    types: [opened]
5
-
6
-jobs:
7
-  issue-links:
8
-    runs-on: ubuntu-latest
9
-    steps:
10
-      - uses: actions/checkout@v3
11
-      - uses: tkt-actions/add-issue-links@v1.8.0
12
-        with:
13
-          header: '### Issue'
14
-          repo-token: '${{ secrets.GITHUB_TOKEN }}'
15
-          resolve: 'true'
16
-          branch-prefix: '/'

+ 0
- 1
common-api/Cargo.toml 查看文件

@@ -20,6 +20,5 @@ thiserror = "1"
20 20
 x25519-dalek = { version = "1", features = ["serde"] }
21 21
 
22 22
 [dev-dependencies]
23
-anyhow = "1"
24 23
 rand = "0.8.5"
25 24
 rand_chacha = "0.3"

+ 58
- 6
common-api/src/crypto/ed25519.rs 查看文件

@@ -10,19 +10,21 @@ use std::{
10 10
     fmt::Display,
11 11
     hash::{Hash, Hasher},
12 12
     io::{Error as IoError, ErrorKind},
13
+    str::FromStr,
13 14
 };
14 15
 
15 16
 use super::{split_encoded_str, Error, Key, Result, ED25519};
16 17
 
17 18
 pub use ed25519_dalek::{
18
-    PUBLIC_KEY_LENGTH as ED25519_PUBLIC_KEY_LENGTH, SECRET_KEY_LENGTH as ED25519_SECRET_KEY_LENGTH,
19
-    SIGNATURE_LENGTH as ED25519_SIGNATURE_LENGTH,
19
+    KEYPAIR_LENGTH as ED25519_KEYPAIR_LENGTH, PUBLIC_KEY_LENGTH as ED25519_PUBLIC_KEY_LENGTH,
20
+    SECRET_KEY_LENGTH as ED25519_SECRET_KEY_LENGTH, SIGNATURE_LENGTH as ED25519_SIGNATURE_LENGTH,
20 21
 };
21 22
 
22
-#[derive(Copy, Clone, Default, Eq, PartialEq)]
23
+#[derive(Copy, Clone, Debug, Default, Eq, PartialEq)]
23 24
 pub struct Ed25519PublicKey(PublicKey);
24 25
 
25 26
 impl Ed25519PublicKey {
27
+    /// Verifies the signature of a signed data
26 28
     pub fn verify(&self, data: &[u8], signature: &Ed25519Signature) -> Result<()> {
27 29
         self.0
28 30
             .verify(data, &signature.0)
@@ -95,6 +97,7 @@ impl Display for Ed25519PublicKey {
95 97
 pub struct Ed25519SecretKey(SecretKey);
96 98
 
97 99
 impl Ed25519SecretKey {
100
+    /// Sign a `data` with a private key
98 101
     pub fn sign(&self, data: &[u8], public_key: &Ed25519PublicKey) -> Ed25519Signature {
99 102
         let expanded_key = ExpandedSecretKey::from(&self.0);
100 103
         Ed25519Signature(expanded_key.sign(data, &public_key.0))
@@ -156,7 +159,7 @@ impl BorshSerialize for Ed25519SecretKey {
156 159
     }
157 160
 }
158 161
 
159
-#[derive(Copy, Clone, Eq, PartialEq)]
162
+#[derive(Copy, Clone, Debug, Eq, PartialEq)]
160 163
 pub struct Ed25519Signature(Signature);
161 164
 
162 165
 impl Key<ED25519_SIGNATURE_LENGTH> for Ed25519Signature {
@@ -207,6 +210,7 @@ impl Display for Ed25519Signature {
207 210
     }
208 211
 }
209 212
 
213
+/// Contains public and secret user keys
210 214
 #[derive(Serialize, Deserialize)]
211 215
 pub struct Keypair {
212 216
     public_key: Ed25519PublicKey,
@@ -222,8 +226,8 @@ impl Keypair {
222 226
         }
223 227
     }
224 228
 
225
-    pub fn from_encoded(encoded: &str) -> Result<Self> {
226
-        let secret_key = Ed25519SecretKey::from_expanded(encoded)?;
229
+    pub fn from_expanded_secret(expanded: &str) -> Result<Self> {
230
+        let secret_key = Ed25519SecretKey::from_expanded(expanded)?;
227 231
         let public_key = Ed25519PublicKey::from(&secret_key);
228 232
         Ok(Self {
229 233
             public_key,
@@ -248,6 +252,54 @@ impl Keypair {
248 252
     }
249 253
 }
250 254
 
255
+impl ToString for Keypair {
256
+    fn to_string(&self) -> String {
257
+        let keypair_bytes = self
258
+            .secret_key()
259
+            .as_bytes()
260
+            .iter()
261
+            .chain(self.public_key().as_bytes().iter())
262
+            .copied()
263
+            .collect_vec();
264
+
265
+        format!("{ED25519}:{}", bs58::encode(keypair_bytes).into_string())
266
+    }
267
+}
268
+
269
+impl FromStr for Keypair {
270
+    type Err = Error;
271
+
272
+    fn from_str(s: &str) -> Result<Self> {
273
+        let (key_type, data) = split_encoded_str(s)?;
274
+
275
+        if key_type != ED25519 {
276
+            return Err(Error::WrongKeyType {
277
+                key_type: key_type.to_owned(),
278
+                expected_key_type: ED25519,
279
+            });
280
+        }
281
+
282
+        let byte_data = bs58::decode(data)
283
+            .into_vec()
284
+            .map_err(|err| Error::from_string::<Keypair>(data.to_owned(), err.to_string()))?;
285
+
286
+        if byte_data.len() != ED25519_KEYPAIR_LENGTH {
287
+            return Err(Error::from_bytes::<Keypair>(
288
+                &byte_data,
289
+                format!(
290
+                    "Keypair byte array length doesn't equal\
291
+                     to requested length {ED25519_KEYPAIR_LENGTH}"
292
+                ),
293
+            ));
294
+        }
295
+
296
+        Ok(Self {
297
+            secret_key: Ed25519SecretKey::try_from_bytes(&byte_data[..ED25519_SECRET_KEY_LENGTH])?,
298
+            public_key: Ed25519PublicKey::try_from_bytes(&byte_data[ED25519_SECRET_KEY_LENGTH..])?,
299
+        })
300
+    }
301
+}
302
+
251 303
 serde_impl!(Ed25519PublicKey);
252 304
 serde_impl!(Ed25519SecretKey);
253 305
 serde_impl!(Ed25519Signature);

+ 1
- 2
common-api/src/crypto/mod.rs 查看文件

@@ -167,7 +167,7 @@ mod tests {
167 167
     use super::{split_encoded_str, Error, ED25519, X25519};
168 168
 
169 169
     #[test]
170
-    fn split_encoded() -> anyhow::Result<()> {
170
+    fn split_encoded() {
171 171
         let bs58_str = bs58::encode(vec![0, 0, 0]).into_string();
172 172
         assert!(matches!(
173 173
                 split_encoded_str(&format!("ed25519:{}", bs58_str)),
@@ -179,6 +179,5 @@ mod tests {
179 179
             split_encoded_str(&bs58_str),
180 180
             Err(Error::UnknownKeyType(..))
181 181
         ));
182
-        Ok(())
183 182
     }
184 183
 }

+ 84
- 70
common-api/tests/crypto.rs 查看文件

@@ -1,3 +1,5 @@
1
+use std::str::FromStr;
2
+
1 3
 use borsh::BorshDeserialize;
2 4
 use common_api::crypto::prelude::*;
3 5
 use ed25519_dalek::{ExpandedSecretKey, SecretKey as DalekSecretKey};
@@ -5,10 +7,10 @@ use rand::{RngCore, SeedableRng};
5 7
 use rand_chacha::ChaChaRng;
6 8
 
7 9
 #[test]
8
-fn try_from_bytes_ed25519() -> anyhow::Result<()> {
9
-    let sk = Ed25519SecretKey::try_from_bytes(&random_bits())?;
10
+fn try_from_bytes_ed25519() {
11
+    let sk = Ed25519SecretKey::try_from_bytes(&random_bits()).unwrap();
10 12
     let pk = Ed25519PublicKey::from(&sk);
11
-    let _ = Ed25519PublicKey::try_from_bytes(pk.as_bytes())?;
13
+    let _ = Ed25519PublicKey::try_from_bytes(pk.as_bytes()).unwrap();
12 14
 
13 15
     assert!(matches!(
14 16
         Ed25519PublicKey::try_from_bytes(&[0, 0, 0]),
@@ -19,13 +21,11 @@ fn try_from_bytes_ed25519() -> anyhow::Result<()> {
19 21
         Ed25519SecretKey::try_from_bytes(&[0, 0, 0]),
20 22
         Err(Error::ConvertFromBytes { .. })
21 23
     ));
22
-
23
-    Ok(())
24 24
 }
25 25
 
26 26
 #[test]
27
-fn to_string_ed25519() -> anyhow::Result<()> {
28
-    let sk = Ed25519SecretKey::try_from_bytes(&random_bits())?;
27
+fn to_string_ed25519() {
28
+    let sk = Ed25519SecretKey::try_from_bytes(&random_bits()).unwrap();
29 29
     let pk = Ed25519PublicKey::from(&sk);
30 30
 
31 31
     assert_eq!(
@@ -36,22 +36,22 @@ fn to_string_ed25519() -> anyhow::Result<()> {
36 36
         format!("ed25519:{}", bs58::encode(pk.as_bytes()).into_string()),
37 37
         pk.string()
38 38
     );
39
-
40
-    Ok(())
41 39
 }
42 40
 
43 41
 #[test]
44
-fn from_string_ed25519() -> anyhow::Result<()> {
45
-    let sk = Ed25519SecretKey::try_from_bytes(&random_bits())?;
42
+fn from_string_ed25519() {
43
+    let sk = Ed25519SecretKey::try_from_bytes(&random_bits()).unwrap();
46 44
     let pk = Ed25519PublicKey::from(&sk);
47 45
 
48 46
     let _ = Ed25519SecretKey::from_string(
49 47
         format!("ed25519:{}", bs58::encode(sk.as_bytes()).into_string()).as_str(),
50
-    )?;
48
+    )
49
+    .unwrap();
51 50
 
52 51
     let _ = Ed25519PublicKey::from_string(
53 52
         format!("ed25519:{}", bs58::encode(pk.as_bytes()).into_string()).as_str(),
54
-    )?;
53
+    )
54
+    .unwrap();
55 55
 
56 56
     assert!(matches!(
57 57
         Ed25519PublicKey::from_string(
@@ -83,26 +83,23 @@ fn from_string_ed25519() -> anyhow::Result<()> {
83 83
         Ed25519PublicKey::from_string(format!("ed25519:{}", "==1234%#").as_str(),),
84 84
         Err(Error::ConvertFromString { .. })
85 85
     ));
86
-
87
-    Ok(())
88 86
 }
89 87
 
90 88
 #[test]
91
-fn from_expanded() -> anyhow::Result<()> {
92
-    let dalek_sk = ExpandedSecretKey::from(&DalekSecretKey::from_bytes(&random_bits())?);
89
+fn from_expanded() {
90
+    let dalek_sk = ExpandedSecretKey::from(&DalekSecretKey::from_bytes(&random_bits()).unwrap());
93 91
     let exp_str = format!(
94 92
         "ed25519:{}",
95 93
         bs58::encode(dalek_sk.to_bytes()).into_string()
96 94
     );
97
-    let sk = Ed25519SecretKey::from_expanded(&exp_str)?;
95
+    let sk = Ed25519SecretKey::from_expanded(&exp_str).unwrap();
98 96
 
99 97
     assert_eq!(sk.as_bytes(), &dalek_sk.to_bytes()[..32]);
100
-    Ok(())
101 98
 }
102 99
 
103 100
 #[test]
104
-fn from_expanded_fail() -> anyhow::Result<()> {
105
-    let dalek_sk = ExpandedSecretKey::from(&DalekSecretKey::from_bytes(&random_bits())?);
101
+fn from_expanded_fail() {
102
+    let dalek_sk = ExpandedSecretKey::from(&DalekSecretKey::from_bytes(&random_bits()).unwrap());
106 103
 
107 104
     let exp_str = bs58::encode(dalek_sk.to_bytes()).into_string();
108 105
     assert!(matches!(
@@ -121,15 +118,13 @@ fn from_expanded_fail() -> anyhow::Result<()> {
121 118
         Ed25519SecretKey::from_expanded(&exp_str),
122 119
         Err(Error::ConvertFromString { .. })
123 120
     ));
124
-
125
-    Ok(())
126 121
 }
127 122
 
128 123
 #[test]
129
-fn try_from_bytes_x25519() -> anyhow::Result<()> {
130
-    let sk = SecretKey::try_from_bytes(&random_bits())?;
124
+fn try_from_bytes_x25519() {
125
+    let sk = SecretKey::try_from_bytes(&random_bits()).unwrap();
131 126
     let pk = PublicKey::from(&sk);
132
-    let _ = PublicKey::try_from_bytes(&pk.to_bytes())?;
127
+    let _ = PublicKey::try_from_bytes(&pk.to_bytes()).unwrap();
133 128
 
134 129
     assert!(matches!(
135 130
         PublicKey::try_from_bytes(&[0, 0, 0]),
@@ -140,13 +135,11 @@ fn try_from_bytes_x25519() -> anyhow::Result<()> {
140 135
         SecretKey::try_from_bytes(&[0, 0, 0]),
141 136
         Err(Error::ConvertFromBytes { .. })
142 137
     ));
143
-
144
-    Ok(())
145 138
 }
146 139
 
147 140
 #[test]
148
-fn to_string_x25519() -> anyhow::Result<()> {
149
-    let sk = SecretKey::try_from_bytes(&random_bits())?;
141
+fn to_string_x25519() {
142
+    let sk = SecretKey::try_from_bytes(&random_bits()).unwrap();
150 143
     let pk = PublicKey::from(&sk);
151 144
 
152 145
     assert_eq!(
@@ -157,22 +150,22 @@ fn to_string_x25519() -> anyhow::Result<()> {
157 150
         format!("x25519:{}", bs58::encode(&pk.to_bytes()).into_string()),
158 151
         pk.string()
159 152
     );
160
-
161
-    Ok(())
162 153
 }
163 154
 
164 155
 #[test]
165
-fn from_string_x25519() -> anyhow::Result<()> {
166
-    let sk = SecretKey::try_from_bytes(&random_bits())?;
156
+fn from_string_x25519() {
157
+    let sk = SecretKey::try_from_bytes(&random_bits()).unwrap();
167 158
     let pk = PublicKey::from(&sk);
168 159
 
169 160
     let _ = SecretKey::from_string(
170 161
         format!("x25519:{}", bs58::encode(&sk.to_bytes()).into_string()).as_str(),
171
-    )?;
162
+    )
163
+    .unwrap();
172 164
 
173 165
     let _ = PublicKey::from_string(
174 166
         format!("x25519:{}", bs58::encode(&pk.to_bytes()).into_string()).as_str(),
175
-    )?;
167
+    )
168
+    .unwrap();
176 169
 
177 170
     assert!(matches!(
178 171
         PublicKey::from_string(
@@ -211,76 +204,97 @@ fn from_string_x25519() -> anyhow::Result<()> {
211 204
         PublicKey::from_string(format!("x25519:{}", "==1234%#").as_str(),),
212 205
         Err(Error::ConvertFromString { .. })
213 206
     ));
214
-
215
-    Ok(())
216 207
 }
217 208
 
218 209
 #[test]
219
-fn public_key_verify() -> anyhow::Result<()> {
220
-    let sk = Ed25519SecretKey::try_from_bytes(&random_bits())?;
210
+fn public_key_verify() {
211
+    let sk = Ed25519SecretKey::try_from_bytes(&random_bits()).unwrap();
221 212
     let pk = Ed25519PublicKey::from(&sk);
222 213
 
223 214
     let signature = sk.sign(b"message", &pk);
224
-    pk.verify(b"message", &signature)?;
225
-
226
-    Ok(())
215
+    pk.verify(b"message", &signature).unwrap();
227 216
 }
228 217
 
229 218
 #[test]
230
-fn keypair_verify() -> anyhow::Result<()> {
231
-    let keypair = Keypair::new(Ed25519SecretKey::try_from_bytes(&random_bits())?);
219
+fn keypair_verify() {
220
+    let keypair = Keypair::new(Ed25519SecretKey::try_from_bytes(&random_bits()).unwrap());
232 221
     let signature = keypair.sign(b"message");
233
-    keypair.verify(b"message", &signature)?;
234
-
235
-    Ok(())
222
+    keypair.verify(b"message", &signature).unwrap();
236 223
 }
237 224
 
238 225
 #[test]
239
-fn key_exchange() -> anyhow::Result<()> {
240
-    let alice_sk = SecretKey::try_from_bytes(&random_bits())?;
226
+fn key_exchange() {
227
+    let alice_sk = SecretKey::try_from_bytes(&random_bits()).unwrap();
241 228
     let alice_pk = PublicKey::from(&alice_sk);
242 229
 
243
-    let bob_sk = SecretKey::try_from_bytes(&random_bits())?;
230
+    let bob_sk = SecretKey::try_from_bytes(&random_bits()).unwrap();
244 231
     let bob_pk = PublicKey::from(&bob_sk);
245 232
 
246 233
     assert_eq!(alice_sk.exchange(&bob_pk), bob_sk.exchange(&alice_pk));
247
-    Ok(())
248 234
 }
249 235
 
250 236
 #[test]
251
-fn borsh_ed25519() -> anyhow::Result<()> {
252
-    let sk = Ed25519SecretKey::try_from_bytes(&random_bits())?;
253
-    let sk_bytes = borsh::to_vec(&sk)?;
237
+fn borsh_ed25519() {
238
+    let sk = Ed25519SecretKey::try_from_bytes(&random_bits()).unwrap();
239
+    let sk_bytes = borsh::to_vec(&sk).unwrap();
254 240
     let pk = Ed25519PublicKey::from(&sk);
255
-    let pk_bytes = borsh::to_vec(&pk)?;
241
+    let pk_bytes = borsh::to_vec(&pk).unwrap();
256 242
 
257 243
     assert_eq!(pk_bytes.len(), pk.as_bytes().len() + 1);
258 244
     assert_eq!(pk_bytes[0], 0);
259 245
     assert_eq!(sk_bytes.len(), sk.as_bytes().len());
260 246
 
261
-    let sk = Ed25519SecretKey::try_from_slice(&sk_bytes)?;
262
-    let pk = Ed25519PublicKey::try_from_slice(&pk_bytes)?;
247
+    let sk = Ed25519SecretKey::try_from_slice(&sk_bytes).unwrap();
248
+    let pk = Ed25519PublicKey::try_from_slice(&pk_bytes).unwrap();
263 249
 
264
-    let signature_bytes = borsh::to_vec(&sk.sign(b"message", &pk))?;
250
+    let signature_bytes = borsh::to_vec(&sk.sign(b"message", &pk)).unwrap();
265 251
     pk.verify(
266 252
         b"message",
267
-        &Ed25519Signature::try_from_slice(&signature_bytes)?,
268
-    )?;
269
-
270
-    Ok(())
253
+        &Ed25519Signature::try_from_slice(&signature_bytes).unwrap(),
254
+    )
255
+    .unwrap();
271 256
 }
272 257
 
273 258
 #[test]
274
-fn borsh_x25519() -> anyhow::Result<()> {
275
-    let sk = SecretKey::try_from_bytes(&random_bits())?;
276
-    let sk_bytes = borsh::to_vec(&sk)?;
259
+fn borsh_x25519() {
260
+    let sk = SecretKey::try_from_bytes(&random_bits()).unwrap();
261
+    let sk_bytes = borsh::to_vec(&sk).unwrap();
277 262
     let pk = PublicKey::from(&sk);
278
-    let pk_bytes = borsh::to_vec(&pk)?;
263
+    let pk_bytes = borsh::to_vec(&pk).unwrap();
264
+
265
+    // just try to serialize and deserialize. We doesn't support key-exchange for now
266
+    let _ = SecretKey::try_from_slice(&sk_bytes).unwrap();
267
+    let _ = PublicKey::try_from_slice(&pk_bytes).unwrap();
268
+}
269
+
270
+#[test]
271
+fn keypair_from_str() {
272
+    let sk = Ed25519SecretKey::try_from_bytes(&random_bits()).unwrap();
273
+    let pk = Ed25519PublicKey::from(&sk);
274
+
275
+    let mut sk_bytes = sk.to_bytes().to_vec();
276
+    sk_bytes.extend_from_slice(&pk.to_bytes());
277
+
278
+    let keypair_bs58 = format!("ed25519:{}", bs58::encode(sk_bytes).into_string());
279
+
280
+    let keypair = Keypair::from_str(&keypair_bs58).unwrap();
281
+
282
+    assert_eq!(keypair.secret_key().to_bytes(), sk.to_bytes());
283
+    assert_eq!(keypair.public_key().to_bytes(), pk.to_bytes());
284
+}
285
+
286
+#[test]
287
+fn keypair_to_string() {
288
+    let sk = Ed25519SecretKey::try_from_bytes(&random_bits()).unwrap();
289
+    let pk = Ed25519PublicKey::from(&sk);
290
+
291
+    let mut sk_bytes = sk.to_bytes().to_vec();
292
+    sk_bytes.extend_from_slice(&pk.to_bytes());
279 293
 
280
-    let _ = SecretKey::try_from_slice(&sk_bytes)?;
281
-    let _ = PublicKey::try_from_slice(&pk_bytes)?;
294
+    let keypair_bs58 = format!("ed25519:{}", bs58::encode(sk_bytes).into_string());
295
+    let keypair = Keypair::new(sk);
282 296
 
283
-    Ok(())
297
+    assert_eq!(keypair_bs58, keypair.to_string());
284 298
 }
285 299
 
286 300
 fn random_bits() -> [u8; ED25519_SECRET_KEY_LENGTH] {

正在加载...
取消
保存