1
// Copyright 2019-2025 PureStake Inc.
2
// This file is part of Moonbeam.
3

            
4
// Moonbeam is free software: you can redistribute it and/or modify
5
// it under the terms of the GNU General Public License as published by
6
// the Free Software Foundation, either version 3 of the License, or
7
// (at your option) any later version.
8

            
9
// Moonbeam is distributed in the hope that it will be useful,
10
// but WITHOUT ANY WARRANTY; without even the implied warranty of
11
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
// GNU General Public License for more details.
13

            
14
// You should have received a copy of the GNU General Public License
15
// along with Moonbeam.  If not, see <http://www.gnu.org/licenses/>.
16

            
17
use bip32::{
18
	Error as Bip32Error, ExtendedPrivateKey, PrivateKey as PrivateKeyT, PrivateKeyBytes,
19
	PublicKey as PublicKeyT, PublicKeyBytes,
20
};
21
use bip39::{Language, Mnemonic, MnemonicType, Seed};
22
use clap::Parser;
23
use libsecp256k1::{PublicKey, SecretKey};
24
use primitive_types::H256;
25
use sp_runtime::traits::IdentifyAccount;
26

            
27
#[derive(Debug, Parser)]
28
pub struct GenerateAccountKey {
29
	/// Generate 12 words mnemonic instead of 24
30
	#[clap(long, short = 'w')]
31
	w12: bool,
32

            
33
	/// Specify the mnemonic
34
	#[clap(long, short = 'm')]
35
	mnemonic: Option<String>,
36

            
37
	/// The account index to use in the derivation path
38
	#[clap(long = "account-index", short = 'a')]
39
	account_index: Option<u32>,
40
}
41

            
42
impl GenerateAccountKey {
43
	pub fn run(&self) {
44
		// Retrieve the mnemonic from the args or generate random ones
45
		let mnemonic = if let Some(phrase) = &self.mnemonic {
46
			Mnemonic::from_phrase(phrase, Language::English).expect("invalid mnemonic")
47
		} else {
48
			match self.w12 {
49
				true => Mnemonic::new(MnemonicType::Words12, Language::English),
50
				false => Mnemonic::new(MnemonicType::Words24, Language::English),
51
			}
52
		};
53

            
54
		// Retrieves the seed from the mnemonic
55
		let seed = Seed::new(&mnemonic, "");
56
		let derivation_path = format!("m/44'/60'/0'/0/{}", self.account_index.unwrap_or(0));
57
		let private_key = if let Some(private_key) =
58
			derivation_path.parse().ok().and_then(|derivation_path| {
59
				let extended = ExtendedPrivateKey::<Secp256k1SecretKey>::derive_from_path(
60
					&seed,
61
					&derivation_path,
62
				)
63
				.expect("invalid extended private key");
64
				Some(extended.private_key().0)
65
			}) {
66
			private_key
67
		} else {
68
			panic!("invalid extended private key");
69
		};
70

            
71
		// Retrieves the public key
72
		let public_key = PublicKey::from_secret_key(&private_key);
73

            
74
		// Convert into Ethereum-style address.
75
		let signer: account::EthereumSigner = public_key.into();
76
		let address = signer.into_account();
77

            
78
		println!("Address:      {:?}", address);
79
		println!("Mnemonic:     {}", mnemonic.phrase());
80
		println!("Private Key:  {:?}", H256::from(private_key.serialize()));
81
		println!("Path:         {}", derivation_path);
82
	}
83
}
84

            
85
// `libsecp256k1::PublicKey` wrapped type
86
pub struct Secp256k1PublicKey(pub PublicKey);
87
// `libsecp256k1::Secret`  wrapped type
88
pub struct Secp256k1SecretKey(pub SecretKey);
89

            
90
impl PublicKeyT for Secp256k1PublicKey {
91
	fn from_bytes(bytes: PublicKeyBytes) -> Result<Self, Bip32Error> {
92
		let public = PublicKey::parse_compressed(&bytes).map_err(|_| return Bip32Error::Decode)?;
93
		Ok(Self(public))
94
	}
95

            
96
140
	fn to_bytes(&self) -> PublicKeyBytes {
97
140
		self.0.serialize_compressed()
98
140
	}
99

            
100
	fn derive_child(&self, other: PrivateKeyBytes) -> Result<Self, Bip32Error> {
101
		let mut child = self.0.clone();
102
		let secret = SecretKey::parse(&other).map_err(|_| return Bip32Error::Decode)?;
103
		let _ = child.tweak_add_assign(&secret);
104
		Ok(Self(child))
105
	}
106
}
107

            
108
impl PrivateKeyT for Secp256k1SecretKey {
109
	type PublicKey = Secp256k1PublicKey;
110

            
111
20
	fn from_bytes(bytes: &PrivateKeyBytes) -> Result<Self, Bip32Error> {
112
20
		let secret = SecretKey::parse(&bytes).map_err(|_| return Bip32Error::Decode)?;
113
20
		Ok(Self(secret))
114
20
	}
115

            
116
60
	fn to_bytes(&self) -> PrivateKeyBytes {
117
60
		self.0.serialize()
118
60
	}
119

            
120
100
	fn derive_child(&self, other: PrivateKeyBytes) -> Result<Self, Bip32Error> {
121
100
		let mut child = self.0.clone();
122
100
		let secret = SecretKey::parse(&other).map_err(|_| return Bip32Error::Decode)?;
123
100
		let _ = child.tweak_add_assign(&secret);
124
100
		Ok(Self(child))
125
100
	}
126

            
127
140
	fn public_key(&self) -> Self::PublicKey {
128
140
		Secp256k1PublicKey(PublicKey::from_secret_key(&self.0))
129
140
	}
130
}