-
Notifications
You must be signed in to change notification settings - Fork 9
/
key_vault.go
118 lines (97 loc) · 2.72 KB
/
key_vault.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
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
package eth2keymanager
import (
"github.com/google/uuid"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
"github.com/ssvlabs/eth2-key-manager/core"
"github.com/ssvlabs/eth2-key-manager/wallets/hd"
"github.com/ssvlabs/eth2-key-manager/wallets/nd"
// Force import a transitive dependency to fix an ambiguous import error.
// See https://github.com/btcsuite/btcd/issues/1839
_ "github.com/btcsuite/btcd/btcec/v2"
)
// InitCrypto initializes cryptography
func InitCrypto() {
// !!!VERY IMPORTANT!!!
if err := core.InitBLS(); err != nil {
logrus.Fatal(err)
}
}
// KeyVault is an EIP 2333,2334,2335 compliant hierarchical deterministic portfolio
// https://eips.ethereum.org/EIPS/eip-2333
// https://github.com/ethereum/EIPs/blob/master/EIPS/eip-2334.md
// https://eips.ethereum.org/EIPS/eip-2335
type KeyVault struct {
Context *core.WalletContext
walletID uuid.UUID
}
// Wallet returns wallet
func (kv *KeyVault) Wallet() (core.Wallet, error) {
return kv.Context.Storage.OpenWallet()
}
// OpenKeyVault opens an existing KeyVault (and wallet) from memory
func OpenKeyVault(options *KeyVaultOptions) (*KeyVault, error) {
storage, err := setupStorage(options)
if err != nil {
return nil, err
}
// wallet Context
context := &core.WalletContext{
Storage: storage,
}
// try and open a wallet
wallet, err := storage.OpenWallet()
if err != nil {
return nil, err
}
return &KeyVault{
Context: context,
walletID: wallet.ID(),
}, nil
}
// NewKeyVault creates a new wallet (with new ids) and will save it to storage
// Import and New are the same action.
func NewKeyVault(options *KeyVaultOptions) (*KeyVault, error) {
storage, err := setupStorage(options)
if err != nil {
return nil, err
}
// wallet Context
context := &core.WalletContext{
Storage: storage,
}
// create wallet
var wallet core.Wallet
if options.walletType == core.NDWallet {
wallet = nd.NewWallet(context)
} else { // ND wallet by default
wallet = hd.NewWallet(context)
}
ret := &KeyVault{
Context: context,
walletID: wallet.ID(),
}
storage, ok := options.storage.(core.Storage)
if !ok {
return nil, errors.Errorf("unexpected storage type %T", options.storage)
}
if err := storage.SaveWallet(wallet); err != nil {
return nil, err
}
return ret, nil
}
func setupStorage(options *KeyVaultOptions) (core.Storage, error) {
storage, ok := options.storage.(core.Storage)
if !ok {
return nil, errors.New("storage does not implement core.Storage")
}
if options.encryptor != nil && options.password != nil {
storage.SetEncryptor(options.encryptor, options.password)
}
return storage, nil
}
// This function calls anyway when this package is imported by someone.
// No needed to call this in each function.
func init() {
InitCrypto()
}