Skip to content

Commit

Permalink
refactor: restrict HD wallet functionality to only deriving aeternity…
Browse files Browse the repository at this point in the history
… addresses
  • Loading branch information
randomshinichi committed Nov 11, 2019
1 parent df76365 commit 6f37c3b
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 23 deletions.
25 changes: 19 additions & 6 deletions account/hdwallet.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package account

import (
"bytes"
"fmt"

"github.com/tyler-smith/go-bip39"
"golang.org/x/crypto/nacl/sign"
Expand All @@ -27,27 +28,39 @@ func BIP32KeyToAeKey(key *Key) (acc *Account, err error) {
}

// DerivePathFromSeed derives a BIP32 Key given a seed (usually derived from a
// mnemonic) and a path. Due to ed25519, only hardened path nodes are supported.
// Hardened nodes are denoted with apostrophes ', e.g. "m/44'/457'/0'/0'/0'".
func DerivePathFromSeed(masterSeed []byte, path string) (key *Key, err error) {
// mnemonic) and an account index and address index, as standardized by AEX-10.
func DerivePathFromSeed(masterSeed []byte, accountIndex, addressIndex uint32) (key *Key, err error) {
path := buildPath(accountIndex, addressIndex)
mK, err := NewMasterKey(masterSeed)
if err != nil {
return
}

return derivePath(mK, path)
}

// buildPath ensures that only aeternity BIP32 addresses can be calculated. Due
// to ed25519, only hardened path nodes are supported. Hardened nodes are
// denoted with apostrophes ', e.g. "m/44'/457'/0'/0'/0'".
func buildPath(accountIndex, addressIndex uint32) string {
return fmt.Sprintf("m/44'/457'/%d'/0'/%d'", accountIndex, addressIndex)
}

func derivePath(key *Key, path string) (childKey *Key, err error) {
parsedPath, err := ParsePath(path)
if err != nil {
return
}

key = mK
childKey = key
for _, p := range parsedPath.Elements {
if p.Master {
continue
}
key, err = key.NewChildKey(p.ChildNumber)
childKey, err = childKey.NewChildKey(p.ChildNumber)
if err != nil {
return
}
}
return key, nil
return
}
41 changes: 24 additions & 17 deletions account/hdwallet_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,31 +8,34 @@ import (
)

func TestDerivePathFromSeedAeAccount(t *testing.T) {
type args struct {
accountIndex uint32
addressIndex uint32
}
tests := []struct {
name string
seed string
path string
args args
wantAddress string
wantErr bool
}{
{
name: "Standard Seed, m/0'",
seed: "60812c7c93d6f9cb346bbcf799957b6ec776aea84b01bdd9f9b7916522cc52c6ea5d07960b68668cd37b0a77f6c4fe283f146bd916153c426df126a8b8707b39",
path: "m/0'",
wantAddress: "ak_2o3zmfG3hMFu4oveTs4VcsmdimnsUBX7sEp3LwXhj9kutRm8mN",
wantErr: false,
},
{
name: "Standard Seed, m/44'/457'/0'/0'/0'",
seed: "60812c7c93d6f9cb346bbcf799957b6ec776aea84b01bdd9f9b7916522cc52c6ea5d07960b68668cd37b0a77f6c4fe283f146bd916153c426df126a8b8707b39",
path: "m/44'/457'/0'/0'/0'",
name: "Standard Seed, m/44'/457'/0'/0'/0'",
seed: "60812c7c93d6f9cb346bbcf799957b6ec776aea84b01bdd9f9b7916522cc52c6ea5d07960b68668cd37b0a77f6c4fe283f146bd916153c426df126a8b8707b39",
args: args{
accountIndex: 0,
addressIndex: 0,
},
wantAddress: "ak_2Z74Jhbo3xqF47k2h6NoUpr5gTfc9EQFX7wPH2Vf7Q5PCVcZSW",
wantErr: false,
},
{
name: "Standard Seed, m/44'/457'/0'/0'/3'",
seed: "60812c7c93d6f9cb346bbcf799957b6ec776aea84b01bdd9f9b7916522cc52c6ea5d07960b68668cd37b0a77f6c4fe283f146bd916153c426df126a8b8707b39",
path: "m/44'/457'/0'/0'/3'",
name: "Standard Seed, m/44'/457'/0'/0'/3'",
seed: "60812c7c93d6f9cb346bbcf799957b6ec776aea84b01bdd9f9b7916522cc52c6ea5d07960b68668cd37b0a77f6c4fe283f146bd916153c426df126a8b8707b39",
args: args{
accountIndex: 0,
addressIndex: 3,
},
wantAddress: "ak_2wPpjbxDhdn8PURqLPsunqBTWYSbe9iac1gjfJcQVzY4aZYEzq",
wantErr: false,
},
Expand All @@ -42,7 +45,7 @@ func TestDerivePathFromSeedAeAccount(t *testing.T) {
if err != nil {
t.Fatal(err)
}
key, err := DerivePathFromSeed(seedBytes, tt.path)
key, err := DerivePathFromSeed(seedBytes, tt.args.accountIndex, tt.args.addressIndex)
if err != nil {
t.Fatal(err)
}
Expand All @@ -57,7 +60,7 @@ func TestDerivePathFromSeedAeAccount(t *testing.T) {
}
}

func TestDerivePathFromSeed_SLIP0010_TestVectors(t *testing.T) {
func TestDerivePath_SLIP0010_TestVectors(t *testing.T) {
// BIP32 adds an extra 0 byte of padding in the beginning of the public key.
// We do not use the padded public key. Instead we just feed the private key
// into the official ed25519 scheme and use its public key. Nevertheless it
Expand Down Expand Up @@ -185,7 +188,11 @@ func TestDerivePathFromSeed_SLIP0010_TestVectors(t *testing.T) {
if err != nil {
t.Fatal(err)
}
key, err := DerivePathFromSeed(seedBytes, tt.path)
masterKey, err := NewMasterKey(seedBytes)
if err != nil {
t.Fatal(err)
}
key, err := derivePath(masterKey, tt.path)
if err != nil {
t.Fatal(err)
}
Expand Down

0 comments on commit 6f37c3b

Please sign in to comment.