Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Recovery Using Mnemonic #305

Merged
merged 1 commit into from
Oct 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions cmd/subcommands/keys.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ var (
blsFilePath string
blsShardID uint32
blsCount uint32
coinType uint32 // coin type used for key path derivation BIP-44 (1023 default for Harmony; 60 for Ethereum or for Metamask mnemonics)
keyIndex uint32
ppPrompt = fmt.Sprintf(
"prompt for passphrase, otherwise use default passphrase: \"`%s`\"", c.DefaultPassphrase,
)
Expand Down Expand Up @@ -214,7 +216,11 @@ func keysSub() []*cobra.Command {
if !bip39.IsMnemonicValid(m) {
return mnemonic.InvalidMnemonic
}

acc.Mnemonic = m
acc.CoinType = &coinType
acc.HdIndexNumber = &keyIndex

if err := account.CreateNewLocalAccount(&acc); err != nil {
return err
}
Expand All @@ -226,6 +232,8 @@ func keysSub() []*cobra.Command {
}
cmdRecoverMnemonic.Flags().BoolVar(&userProvidesPassphrase, "passphrase", false, ppPrompt)
cmdRecoverMnemonic.Flags().StringVar(&passphraseFilePath, "passphrase-file", "", "path to a file containing the passphrase")
cmdRecoverMnemonic.Flags().Uint32Var(&coinType, "coin-type", 1023, "coin type used for key path derivation (1023 default for Harmony; 60 for Ethereum or for Metamask mnemonics)")
cmdRecoverMnemonic.Flags().Uint32Var(&keyIndex, "index", 0, "index of the key recovered from the provided mnemonic")

cmdImportKS := &cobra.Command{
Use: "import-ks <KEYSTORE_FILE_PATH> [ACCOUNT_NAME]",
Expand Down
15 changes: 13 additions & 2 deletions pkg/account/creation.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ type Creation struct {
Mnemonic string
HdAccountNumber *uint32
HdIndexNumber *uint32
CoinType *uint32
}

func New() string {
Expand All @@ -34,8 +35,18 @@ func CreateNewLocalAccount(candidate *Creation) error {
if candidate.Mnemonic == "" {
candidate.Mnemonic = mnemonic.Generate()
}
// Hardcoded index of 0 here.
private, _ := keys.FromMnemonicSeedAndPassphrase(candidate.Mnemonic, 0)

index := uint32(0)
if candidate.HdIndexNumber != nil {
index = *candidate.HdIndexNumber
}

coinType := uint32(1023)
if candidate.CoinType != nil {
coinType = *candidate.CoinType
}

private, _ := keys.FromMnemonicSeedAndPassphrase(candidate.Mnemonic, int(index), int(coinType))
_, err := ks.ImportECDSA(private.ToECDSA(), candidate.Passphrase)
if err != nil {
return err
Expand Down
4 changes: 2 additions & 2 deletions pkg/keys/mnemonic.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,13 @@ import (
// FromMnemonicSeedAndPassphrase mimics the Harmony JS sdk in deriving the
// private, public key pair from the mnemonic, its index, and empty string password.
// Note that an index k would be the k-th key generated using the same mnemonic.
func FromMnemonicSeedAndPassphrase(mnemonic string, index int) (*secp256k1.PrivateKey, *secp256k1.PublicKey) {
func FromMnemonicSeedAndPassphrase(mnemonic string, index int, coinType int) (*secp256k1.PrivateKey, *secp256k1.PublicKey) {
seed := bip39.NewSeed(mnemonic, "")
master, ch := hd.ComputeMastersFromSeed(seed)
private, _ := hd.DerivePrivateKeyForPath(
master,
ch,
fmt.Sprintf("44'/1023'/0'/0/%d", index),
fmt.Sprintf("44'/%d'/0'/0/%d", coinType, index),
)

return secp256k1.PrivKeyFromBytes(secp256k1.S256(), private[:])
Expand Down
3 changes: 2 additions & 1 deletion pkg/keys/mnemonic_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,11 @@ const (
index = 0
publicKey = "0x030b64624e60c6e6758711fdf00f7e873f40a22e647a6918ba73807fab194d09ba"
privateKey = "0xda4bc68857640103942ce7dd22a9fcdb96f3cfe0380254e81352a94ac8262ed2"
coinType = 1023
)

func TestMnemonic(t *testing.T) {
private, public := FromMnemonicSeedAndPassphrase(phrase, index)
private, public := FromMnemonicSeedAndPassphrase(phrase, index, coinType)
sk, pkCompressed := func() (string, string) {
dump := EncodeHex(private, public)
return dump.PrivateKey, dump.PublicKeyCompressed
Expand Down
Loading