github.com/Finschia/finschia-sdk@v0.48.1/crypto/keyring/info.go (about) 1 package keyring 2 3 import ( 4 "fmt" 5 6 "github.com/Finschia/finschia-sdk/codec/legacy" 7 codectypes "github.com/Finschia/finschia-sdk/codec/types" 8 "github.com/Finschia/finschia-sdk/crypto/hd" 9 "github.com/Finschia/finschia-sdk/crypto/keys/multisig" 10 cryptotypes "github.com/Finschia/finschia-sdk/crypto/types" 11 "github.com/Finschia/finschia-sdk/types" 12 ) 13 14 // Info is the publicly exposed information about a keypair 15 type Info interface { 16 // Human-readable type for key listing 17 GetType() KeyType 18 // Name of the key 19 GetName() string 20 // Public key 21 GetPubKey() cryptotypes.PubKey 22 // Address 23 GetAddress() types.AccAddress 24 // Bip44 Path 25 GetPath() (*hd.BIP44Params, error) 26 // Algo 27 GetAlgo() hd.PubKeyType 28 } 29 30 var ( 31 _ Info = &localInfo{} 32 _ Info = &ledgerInfo{} 33 _ Info = &offlineInfo{} 34 _ Info = &multiInfo{} 35 ) 36 37 // localInfo is the public information about a locally stored key 38 // Note: Algo must be last field in struct for backwards amino compatibility 39 type localInfo struct { 40 Name string `json:"name"` 41 PubKey cryptotypes.PubKey `json:"pubkey"` 42 PrivKeyArmor string `json:"privkey.armor"` 43 Algo hd.PubKeyType `json:"algo"` 44 } 45 46 func newLocalInfo(name string, pub cryptotypes.PubKey, privArmor string, algo hd.PubKeyType) Info { 47 return &localInfo{ 48 Name: name, 49 PubKey: pub, 50 PrivKeyArmor: privArmor, 51 Algo: algo, 52 } 53 } 54 55 // GetType implements Info interface 56 func (i localInfo) GetType() KeyType { 57 return TypeLocal 58 } 59 60 // GetType implements Info interface 61 func (i localInfo) GetName() string { 62 return i.Name 63 } 64 65 // GetType implements Info interface 66 func (i localInfo) GetPubKey() cryptotypes.PubKey { 67 return i.PubKey 68 } 69 70 // GetType implements Info interface 71 func (i localInfo) GetAddress() types.AccAddress { 72 return i.PubKey.Address().Bytes() 73 } 74 75 // GetType implements Info interface 76 func (i localInfo) GetAlgo() hd.PubKeyType { 77 return i.Algo 78 } 79 80 // GetType implements Info interface 81 func (i localInfo) GetPath() (*hd.BIP44Params, error) { 82 return nil, fmt.Errorf("BIP44 Paths are not available for this type") 83 } 84 85 // ledgerInfo is the public information about a Ledger key 86 // Note: Algo must be last field in struct for backwards amino compatibility 87 type ledgerInfo struct { 88 Name string `json:"name"` 89 PubKey cryptotypes.PubKey `json:"pubkey"` 90 Path hd.BIP44Params `json:"path"` 91 Algo hd.PubKeyType `json:"algo"` 92 } 93 94 func newLedgerInfo(name string, pub cryptotypes.PubKey, path hd.BIP44Params, algo hd.PubKeyType) Info { 95 return &ledgerInfo{ 96 Name: name, 97 PubKey: pub, 98 Path: path, 99 Algo: algo, 100 } 101 } 102 103 // GetType implements Info interface 104 func (i ledgerInfo) GetType() KeyType { 105 return TypeLedger 106 } 107 108 // GetName implements Info interface 109 func (i ledgerInfo) GetName() string { 110 return i.Name 111 } 112 113 // GetPubKey implements Info interface 114 func (i ledgerInfo) GetPubKey() cryptotypes.PubKey { 115 return i.PubKey 116 } 117 118 // GetAddress implements Info interface 119 func (i ledgerInfo) GetAddress() types.AccAddress { 120 return i.PubKey.Address().Bytes() 121 } 122 123 // GetPath implements Info interface 124 func (i ledgerInfo) GetAlgo() hd.PubKeyType { 125 return i.Algo 126 } 127 128 // GetPath implements Info interface 129 func (i ledgerInfo) GetPath() (*hd.BIP44Params, error) { 130 tmp := i.Path 131 return &tmp, nil 132 } 133 134 // offlineInfo is the public information about an offline key 135 // Note: Algo must be last field in struct for backwards amino compatibility 136 type offlineInfo struct { 137 Name string `json:"name"` 138 PubKey cryptotypes.PubKey `json:"pubkey"` 139 Algo hd.PubKeyType `json:"algo"` 140 } 141 142 func newOfflineInfo(name string, pub cryptotypes.PubKey, algo hd.PubKeyType) Info { 143 return &offlineInfo{ 144 Name: name, 145 PubKey: pub, 146 Algo: algo, 147 } 148 } 149 150 // GetType implements Info interface 151 func (i offlineInfo) GetType() KeyType { 152 return TypeOffline 153 } 154 155 // GetName implements Info interface 156 func (i offlineInfo) GetName() string { 157 return i.Name 158 } 159 160 // GetPubKey implements Info interface 161 func (i offlineInfo) GetPubKey() cryptotypes.PubKey { 162 return i.PubKey 163 } 164 165 // GetAlgo returns the signing algorithm for the key 166 func (i offlineInfo) GetAlgo() hd.PubKeyType { 167 return i.Algo 168 } 169 170 // GetAddress implements Info interface 171 func (i offlineInfo) GetAddress() types.AccAddress { 172 return i.PubKey.Address().Bytes() 173 } 174 175 // GetPath implements Info interface 176 func (i offlineInfo) GetPath() (*hd.BIP44Params, error) { 177 return nil, fmt.Errorf("BIP44 Paths are not available for this type") 178 } 179 180 // Deprecated: this structure is not used anymore and it's here only to allow 181 // decoding old multiInfo records from keyring. 182 // The problem with legacy.Cdc.UnmarshalLengthPrefixed - the legacy codec doesn't 183 // tolerate extensibility. 184 type multisigPubKeyInfo struct { 185 PubKey cryptotypes.PubKey `json:"pubkey"` 186 Weight uint `json:"weight"` 187 } 188 189 // multiInfo is the public information about a multisig key 190 type multiInfo struct { 191 Name string `json:"name"` 192 PubKey cryptotypes.PubKey `json:"pubkey"` 193 Threshold uint `json:"threshold"` 194 PubKeys []multisigPubKeyInfo `json:"pubkeys"` 195 } 196 197 // NewMultiInfo creates a new multiInfo instance 198 func NewMultiInfo(name string, pub cryptotypes.PubKey) (Info, error) { 199 if _, ok := pub.(*multisig.LegacyAminoPubKey); !ok { 200 return nil, fmt.Errorf("MultiInfo supports only multisig.LegacyAminoPubKey, got %T", pub) 201 } 202 return &multiInfo{ 203 Name: name, 204 PubKey: pub, 205 }, nil 206 } 207 208 // GetType implements Info interface 209 func (i multiInfo) GetType() KeyType { 210 return TypeMulti 211 } 212 213 // GetName implements Info interface 214 func (i multiInfo) GetName() string { 215 return i.Name 216 } 217 218 // GetPubKey implements Info interface 219 func (i multiInfo) GetPubKey() cryptotypes.PubKey { 220 return i.PubKey 221 } 222 223 // GetAddress implements Info interface 224 func (i multiInfo) GetAddress() types.AccAddress { 225 return i.PubKey.Address().Bytes() 226 } 227 228 // GetPath implements Info interface 229 func (i multiInfo) GetAlgo() hd.PubKeyType { 230 return hd.MultiType 231 } 232 233 // GetPath implements Info interface 234 func (i multiInfo) GetPath() (*hd.BIP44Params, error) { 235 return nil, fmt.Errorf("BIP44 Paths are not available for this type") 236 } 237 238 // UnpackInterfaces implements UnpackInterfacesMessage.UnpackInterfaces 239 func (i multiInfo) UnpackInterfaces(unpacker codectypes.AnyUnpacker) error { 240 multiPK := i.PubKey.(*multisig.LegacyAminoPubKey) 241 242 return codectypes.UnpackInterfaces(multiPK, unpacker) 243 } 244 245 // encoding info 246 func marshalInfo(i Info) []byte { 247 return legacy.Cdc.MustMarshalLengthPrefixed(i) 248 } 249 250 // decoding info 251 func unmarshalInfo(bz []byte) (info Info, err error) { 252 err = legacy.Cdc.UnmarshalLengthPrefixed(bz, &info) 253 if err != nil { 254 return nil, err 255 } 256 257 // After unmarshalling into &info, if we notice that the info is a 258 // multiInfo, then we unmarshal again, explicitly in a multiInfo this time. 259 // Since multiInfo implements UnpackInterfacesMessage, this will correctly 260 // unpack the underlying anys inside the multiInfo. 261 // 262 // This is a workaround, as go cannot check that an interface (Info) 263 // implements another interface (UnpackInterfacesMessage). 264 _, ok := info.(multiInfo) 265 if ok { 266 var multi multiInfo 267 err = legacy.Cdc.UnmarshalLengthPrefixed(bz, &multi) 268 269 return multi, err 270 } 271 272 return 273 }