-
Notifications
You must be signed in to change notification settings - Fork 3.6k
/
record.go
132 lines (108 loc) · 3.5 KB
/
record.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
119
120
121
122
123
124
125
126
127
128
129
130
131
132
package keyring
import (
"errors"
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
"github.com/cosmos/cosmos-sdk/crypto/hd"
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
"github.com/cosmos/cosmos-sdk/types"
)
// ErrPrivKeyExtr is used to output an error if extraction of a private key from Local item fails
var ErrPrivKeyExtr = errors.New("private key extraction works only for Local")
func newRecord(name string, pk cryptotypes.PubKey, item isRecord_Item) (*Record, error) {
any, err := codectypes.NewAnyWithValue(pk)
if err != nil {
return nil, err
}
return &Record{name, any, item}, nil
}
// NewLocalRecord creates a new Record with local key item
func NewLocalRecord(name string, priv cryptotypes.PrivKey, pk cryptotypes.PubKey) (*Record, error) {
any, err := codectypes.NewAnyWithValue(priv)
if err != nil {
return nil, err
}
recordLocal := &Record_Local{any}
recordLocalItem := &Record_Local_{recordLocal}
return newRecord(name, pk, recordLocalItem)
}
// NewLedgerRecord creates a new Record with ledger item
func NewLedgerRecord(name string, pk cryptotypes.PubKey, path *hd.BIP44Params) (*Record, error) {
recordLedger := &Record_Ledger{path}
recordLedgerItem := &Record_Ledger_{recordLedger}
return newRecord(name, pk, recordLedgerItem)
}
func (rl *Record_Ledger) GetPath() *hd.BIP44Params {
return rl.Path
}
// NewOfflineRecord creates a new Record with offline item
func NewOfflineRecord(name string, pk cryptotypes.PubKey) (*Record, error) {
recordOffline := &Record_Offline{}
recordOfflineItem := &Record_Offline_{recordOffline}
return newRecord(name, pk, recordOfflineItem)
}
// NewMultiRecord creates a new Record with multi item
func NewMultiRecord(name string, pk cryptotypes.PubKey) (*Record, error) {
recordMulti := &Record_Multi{}
recordMultiItem := &Record_Multi_{recordMulti}
return newRecord(name, pk, recordMultiItem)
}
// GetPubKey fetches a public key of the record
func (k *Record) GetPubKey() (cryptotypes.PubKey, error) {
pk, ok := k.PubKey.GetCachedValue().(cryptotypes.PubKey)
if !ok {
return nil, errors.New("unable to cast any to cryptotypes.PubKey")
}
return pk, nil
}
// GetAddress fetches an address of the record
func (k Record) GetAddress() (types.AccAddress, error) {
pk, err := k.GetPubKey()
if err != nil {
return nil, err
}
return pk.Address().Bytes(), nil
}
// GetType fetches type of the record
func (k Record) GetType() KeyType {
switch {
case k.GetLocal() != nil:
return TypeLocal
case k.GetLedger() != nil:
return TypeLedger
case k.GetMulti() != nil:
return TypeMulti
case k.GetOffline() != nil:
return TypeOffline
default:
panic("unrecognized record type")
}
}
// UnpackInterfaces implements UnpackInterfacesMessage.UnpackInterfaces
func (k *Record) UnpackInterfaces(unpacker codectypes.AnyUnpacker) error {
var pk cryptotypes.PubKey
if err := unpacker.UnpackAny(k.PubKey, &pk); err != nil {
return err
}
if l := k.GetLocal(); l != nil {
var priv cryptotypes.PrivKey
return unpacker.UnpackAny(l.PrivKey, &priv)
}
return nil
}
func extractPrivKeyFromRecord(k *Record) (cryptotypes.PrivKey, error) {
rl := k.GetLocal()
if rl == nil {
return nil, ErrPrivKeyExtr
}
return extractPrivKeyFromLocal(rl)
}
func extractPrivKeyFromLocal(rl *Record_Local) (cryptotypes.PrivKey, error) {
if rl.PrivKey == nil {
return nil, errors.New("private key is not available")
}
priv, ok := rl.PrivKey.GetCachedValue().(cryptotypes.PrivKey)
if !ok {
return nil, errors.New("unable to cast any to cryptotypes.PrivKey")
}
return priv, nil
}