1use clap::builder::PossibleValue;
2use clap::ValueEnum;
3use color_eyre::eyre::eyre;
4use gadget_sdk::keystore::backend::fs::FilesystemKeystore;
5use gadget_sdk::keystore::backend::mem::InMemoryKeystore;
6use gadget_sdk::keystore::backend::GenericKeyStore;
7use gadget_sdk::keystore::Backend;
8use gadget_sdk::parking_lot::RawRwLock;
9use std::path::PathBuf;
10use std::str::FromStr;
11use w3f_bls::serialize::SerializableToBytes;
12
13#[derive(thiserror::Error, Debug)]
14pub enum Error {
15 #[error("Unknown key type: {0}")]
16 UnknownKeyType(String),
17}
18
19#[derive(Clone, Debug)]
20pub enum KeyType {
21 Sr25519,
22 Ed25519,
23 Ecdsa,
24 Bls381,
25 BlsBn254,
26}
27
28impl ValueEnum for KeyType {
29 fn value_variants<'a>() -> &'a [Self] {
30 &[
31 Self::Sr25519,
32 Self::Ed25519,
33 Self::Ecdsa,
34 Self::Bls381,
35 Self::BlsBn254,
36 ]
37 }
38
39 fn to_possible_value(&self) -> Option<PossibleValue> {
40 Some(match self {
41 Self::Sr25519 => PossibleValue::new("sr25519").help("Schnorrkel/Ristretto x25519"),
42 Self::Ed25519 => PossibleValue::new("ed25519").help("Edwards Curve 25519"),
43 Self::Ecdsa => {
44 PossibleValue::new("ecdsa").help("Elliptic Curve Digital Signature Algorithm")
45 }
46 Self::Bls381 => PossibleValue::new("bls381").help("Boneh-Lynn-Shacham on BLS12-381"),
47 Self::BlsBn254 => PossibleValue::new("blsbn254").help("Boneh-Lynn-Shacham on BN254"),
48 })
49 }
50}
51
52impl FromStr for KeyType {
53 type Err = Error;
54
55 fn from_str(s: &str) -> Result<Self, Self::Err> {
56 let lower = s.to_lowercase();
57 match lower.as_str() {
58 "sr25519" => Ok(Self::Sr25519),
59 "ed25519" => Ok(Self::Ed25519),
60 "ecdsa" => Ok(Self::Ecdsa),
61 "bls381" => Ok(Self::Bls381),
62 "blsbn254" => Ok(Self::BlsBn254),
63 _ => Err(Error::UnknownKeyType(lower)),
64 }
65 }
66}
67
68pub fn generate_key(
69 key_type: KeyType,
70 output: Option<PathBuf>,
71 seed: Option<&[u8]>,
72 show_secret: bool,
73) -> color_eyre::Result<()> {
74 let keystore: GenericKeyStore<RawRwLock> = match output {
75 None => GenericKeyStore::Mem(InMemoryKeystore::new()),
76 Some(file_path) => {
77 GenericKeyStore::Fs(FilesystemKeystore::open(file_path)?)
79 }
80 };
81
82 let (public, secret) = match key_type {
83 KeyType::Sr25519 => {
84 let public_key = keystore.sr25519_generate_new(seed)?;
85 let secret = keystore
86 .expose_sr25519_secret(&public_key)?
87 .ok_or(eyre!("Failed to expose secret"))?;
88 (
89 hex::encode(public_key.to_bytes()),
90 hex::encode(secret.to_bytes()),
91 )
92 }
93 KeyType::Ed25519 => {
94 let public_key = keystore.ed25519_generate_new(seed)?;
95 let secret = keystore
96 .expose_ed25519_secret(&public_key)?
97 .ok_or(eyre!("Failed to expose secret"))?;
98 (hex::encode(public_key), hex::encode(secret))
99 }
100 KeyType::Ecdsa => {
101 let public_key = keystore.ecdsa_generate_new(seed)?;
102 let secret = keystore
103 .expose_ecdsa_secret(&public_key)?
104 .ok_or(eyre!("Failed to expose secret"))?;
105 (
106 hex::encode(public_key.to_sec1_bytes()),
107 hex::encode(secret.to_bytes()),
108 )
109 }
110 KeyType::Bls381 => {
111 let public_key = keystore.bls381_generate_new(seed)?;
112 let secret = keystore
113 .expose_bls381_secret(&public_key)?
114 .ok_or(eyre!("Failed to expose secret"))?;
115 (
116 hex::encode(public_key.0.to_string()),
117 hex::encode(secret.to_bytes()),
118 )
119 }
120 KeyType::BlsBn254 => {
121 let public_key = keystore.bls_bn254_generate_new(seed)?;
122 let secret = keystore
123 .expose_bls_bn254_secret(&public_key)?
124 .ok_or(eyre!("Failed to expose secret"))?;
125 (public_key.g1().to_string(), secret.0.to_string())
126 }
127 };
128
129 eprintln!("Generated {:?} key:", key_type);
130 eprintln!("Public key: {}", public);
131 if show_secret || keystore.is_mem() {
132 eprintln!("Private key: {}", secret);
133 }
134
135 Ok(())
136}