/
hdwallet.go
67 lines (57 loc) · 1.54 KB
/
hdwallet.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
package keystore
import (
"crypto/ecdsa"
"errors"
"sync"
"github.com/btcsuite/btcd/chaincfg"
"github.com/btcsuite/btcutil/hdkeychain"
"github.com/ethereum/go-ethereum/accounts"
"github.com/layer-3/clearsync/pkg/signer"
)
// Wallet represents a master wallet that can create signers.
type HdWallet struct {
masterKey *hdkeychain.ExtendedKey
mx sync.RWMutex
}
// NewHdWallet creates a new NewHdWallet based on seed.
func NewHdWallet(seed string) (*HdWallet, error) {
if seed == "" {
return nil, errors.New("empty seed")
}
key, err := hdkeychain.NewMaster([]byte(seed), &chaincfg.Params{})
if err != nil {
return &HdWallet{}, err
}
return &HdWallet{
masterKey: key,
}, err
}
// GetOrCreateSigner creates a signer instance based on unique account index.
func (w *HdWallet) GetOrCreateSigner(uniqueIndex uint32) (signer.Signer, error) {
// Define a derivation path and set the account component to be the uniqueIndex.
path := accounts.DefaultBaseDerivationPath
path[2] = uniqueIndex
w.mx.RLock()
priv, err := w.derivePrivateKey(path)
w.mx.RUnlock()
if err != nil {
return nil, err
}
return signer.NewLocalSigner(priv), nil
}
// derivePrivateKey is a helper function to derive an ECDSA private key
func (w *HdWallet) derivePrivateKey(path accounts.DerivationPath) (*ecdsa.PrivateKey, error) {
var err error
key := w.masterKey
for _, n := range path {
key, err = key.Derive(n)
if err != nil {
return nil, err
}
}
privateKey, err := key.ECPrivKey()
if err != nil {
return nil, err
}
return privateKey.ToECDSA(), nil
}