github.com/gnolang/gno@v0.0.0-20240520182011-228e9d0192ce/tm2/pkg/crypto/keys/types.go (about)

     1  package keys
     2  
     3  import (
     4  	"fmt"
     5  
     6  	"github.com/gnolang/gno/tm2/pkg/amino"
     7  	"github.com/gnolang/gno/tm2/pkg/crypto"
     8  	"github.com/gnolang/gno/tm2/pkg/crypto/hd"
     9  	"github.com/gnolang/gno/tm2/pkg/crypto/multisig"
    10  )
    11  
    12  // Keybase exposes operations on a generic keystore
    13  type Keybase interface {
    14  	// CRUD on the keystore
    15  	List() ([]Info, error)
    16  	HasByNameOrAddress(nameOrBech32 string) (bool, error)
    17  	HasByName(name string) (bool, error)
    18  	HasByAddress(address crypto.Address) (bool, error)
    19  	GetByNameOrAddress(nameOrBech32 string) (Info, error)
    20  	GetByName(name string) (Info, error)
    21  	GetByAddress(address crypto.Address) (Info, error)
    22  	Delete(name, passphrase string, skipPass bool) error
    23  
    24  	// Sign some bytes, looking up the private key to use
    25  	Sign(name, passphrase string, msg []byte) ([]byte, crypto.PubKey, error)
    26  	Verify(name string, msg, sig []byte) error
    27  
    28  	// CreateAccount creates an account based using the BIP44 path (44'/118'/{account}'/0/{index}
    29  	// Encrypt the key to disk using encryptPasswd.
    30  	// See https://github.com/tendermint/classic/sdk/issues/2095
    31  	CreateAccount(name, mnemonic, bip39Passwd, encryptPasswd string, account uint32, index uint32) (Info, error)
    32  
    33  	// Like CreateAccount but from general bip44 params.
    34  	CreateAccountBip44(name, mnemonic, bip39Passwd, encryptPasswd string, params hd.BIP44Params) (Info, error)
    35  
    36  	// CreateLedger creates, stores, and returns a new Ledger key reference
    37  	CreateLedger(name string, algo SigningAlgo, hrp string, account, index uint32) (info Info, err error)
    38  
    39  	// CreateOffline creates, stores, and returns a new offline key reference
    40  	CreateOffline(name string, pubkey crypto.PubKey) (info Info, err error)
    41  
    42  	// CreateMulti creates, stores, and returns a new multsig (offline) key reference
    43  	CreateMulti(name string, pubkey crypto.PubKey) (info Info, err error)
    44  
    45  	// The following operations will *only* work on locally-stored keys
    46  	Update(name, oldpass string, getNewpass func() (string, error)) error
    47  	Import(name string, armor string) (err error)
    48  	ImportPrivKey(name, armor, decryptPassphrase, encryptPassphrase string) error
    49  	ImportPrivKeyUnsafe(name, armor, encryptPassphrase string) error
    50  	ImportPubKey(name string, armor string) (err error)
    51  	Export(name string) (armor string, err error)
    52  	ExportPubKey(name string) (armor string, err error)
    53  	ExportPrivKey(name, decryptPassphrase, encryptPassphrase string) (armor string, err error)
    54  	ExportPrivKeyUnsafe(name, decryptPassphrase string) (armor string, err error)
    55  
    56  	// ExportPrivateKeyObject *only* works on locally-stored keys. Temporary method until we redo the exporting API
    57  	ExportPrivateKeyObject(name string, passphrase string) (crypto.PrivKey, error)
    58  
    59  	// CloseDB closes the database.
    60  	CloseDB()
    61  }
    62  
    63  // KeyType reflects a human-readable type for key listing.
    64  type KeyType uint
    65  
    66  // Info KeyTypes
    67  const (
    68  	TypeLocal   KeyType = 0
    69  	TypeLedger  KeyType = 1
    70  	TypeOffline KeyType = 2
    71  	TypeMulti   KeyType = 3
    72  )
    73  
    74  var keyTypes = map[KeyType]string{
    75  	TypeLocal:   "local",
    76  	TypeLedger:  "ledger",
    77  	TypeOffline: "offline",
    78  	TypeMulti:   "multi",
    79  }
    80  
    81  // String implements the stringer interface for KeyType.
    82  func (kt KeyType) String() string {
    83  	return keyTypes[kt]
    84  }
    85  
    86  // Info is the publicly exposed information about a keypair
    87  type Info interface {
    88  	// Human-readable type for key listing
    89  	GetType() KeyType
    90  	// Name of the key
    91  	GetName() string
    92  	// Public key
    93  	GetPubKey() crypto.PubKey
    94  	// Address
    95  	GetAddress() crypto.Address
    96  	// Bip44 Path
    97  	GetPath() (*hd.BIP44Params, error)
    98  }
    99  
   100  var (
   101  	_ Info = &localInfo{}
   102  	_ Info = &ledgerInfo{}
   103  	_ Info = &offlineInfo{}
   104  	_ Info = &multiInfo{}
   105  )
   106  
   107  // localInfo is the public information about a locally stored key
   108  type localInfo struct {
   109  	Name         string        `json:"name"`
   110  	PubKey       crypto.PubKey `json:"pubkey"`
   111  	PrivKeyArmor string        `json:"privkey.armor"`
   112  }
   113  
   114  func newLocalInfo(name string, pub crypto.PubKey, privArmor string) Info {
   115  	return &localInfo{
   116  		Name:         name,
   117  		PubKey:       pub,
   118  		PrivKeyArmor: privArmor,
   119  	}
   120  }
   121  
   122  // GetType implements Info interface
   123  func (i localInfo) GetType() KeyType {
   124  	return TypeLocal
   125  }
   126  
   127  // GetType implements Info interface
   128  func (i localInfo) GetName() string {
   129  	return i.Name
   130  }
   131  
   132  // GetType implements Info interface
   133  func (i localInfo) GetPubKey() crypto.PubKey {
   134  	return i.PubKey
   135  }
   136  
   137  // GetType implements Info interface
   138  func (i localInfo) GetAddress() crypto.Address {
   139  	return i.PubKey.Address()
   140  }
   141  
   142  // GetType implements Info interface
   143  func (i localInfo) GetPath() (*hd.BIP44Params, error) {
   144  	return nil, fmt.Errorf("BIP44 Paths are not available for this type")
   145  }
   146  
   147  // ledgerInfo is the public information about a Ledger key
   148  type ledgerInfo struct {
   149  	Name   string         `json:"name"`
   150  	PubKey crypto.PubKey  `json:"pubkey"`
   151  	Path   hd.BIP44Params `json:"path"`
   152  }
   153  
   154  func newLedgerInfo(name string, pub crypto.PubKey, path hd.BIP44Params) Info {
   155  	return &ledgerInfo{
   156  		Name:   name,
   157  		PubKey: pub,
   158  		Path:   path,
   159  	}
   160  }
   161  
   162  // GetType implements Info interface
   163  func (i ledgerInfo) GetType() KeyType {
   164  	return TypeLedger
   165  }
   166  
   167  // GetName implements Info interface
   168  func (i ledgerInfo) GetName() string {
   169  	return i.Name
   170  }
   171  
   172  // GetPubKey implements Info interface
   173  func (i ledgerInfo) GetPubKey() crypto.PubKey {
   174  	return i.PubKey
   175  }
   176  
   177  // GetAddress implements Info interface
   178  func (i ledgerInfo) GetAddress() crypto.Address {
   179  	return i.PubKey.Address()
   180  }
   181  
   182  // GetPath implements Info interface
   183  func (i ledgerInfo) GetPath() (*hd.BIP44Params, error) {
   184  	tmp := i.Path
   185  	return &tmp, nil
   186  }
   187  
   188  // offlineInfo is the public information about an offline key
   189  type offlineInfo struct {
   190  	Name   string        `json:"name"`
   191  	PubKey crypto.PubKey `json:"pubkey"`
   192  }
   193  
   194  func newOfflineInfo(name string, pub crypto.PubKey) Info {
   195  	return &offlineInfo{
   196  		Name:   name,
   197  		PubKey: pub,
   198  	}
   199  }
   200  
   201  // GetType implements Info interface
   202  func (i offlineInfo) GetType() KeyType {
   203  	return TypeOffline
   204  }
   205  
   206  // GetName implements Info interface
   207  func (i offlineInfo) GetName() string {
   208  	return i.Name
   209  }
   210  
   211  // GetPubKey implements Info interface
   212  func (i offlineInfo) GetPubKey() crypto.PubKey {
   213  	return i.PubKey
   214  }
   215  
   216  // GetAddress implements Info interface
   217  func (i offlineInfo) GetAddress() crypto.Address {
   218  	return i.PubKey.Address()
   219  }
   220  
   221  // GetPath implements Info interface
   222  func (i offlineInfo) GetPath() (*hd.BIP44Params, error) {
   223  	return nil, fmt.Errorf("BIP44 Paths are not available for this type")
   224  }
   225  
   226  type multisigPubKeyInfo struct {
   227  	PubKey crypto.PubKey `json:"pubkey"`
   228  	Weight uint          `json:"weight"`
   229  }
   230  
   231  // multiInfo is the public information about a multisig key
   232  type multiInfo struct {
   233  	Name      string               `json:"name"`
   234  	PubKey    crypto.PubKey        `json:"pubkey"`
   235  	Threshold uint                 `json:"threshold"`
   236  	PubKeys   []multisigPubKeyInfo `json:"pubkeys"`
   237  }
   238  
   239  // NewMultiInfo creates a new multiInfo instance
   240  func NewMultiInfo(name string, pub crypto.PubKey) Info {
   241  	multiPK := pub.(multisig.PubKeyMultisigThreshold)
   242  
   243  	pubKeys := make([]multisigPubKeyInfo, len(multiPK.PubKeys))
   244  	for i, pk := range multiPK.PubKeys {
   245  		// TODO: Recursively check pk for total weight?
   246  		pubKeys[i] = multisigPubKeyInfo{pk, 1}
   247  	}
   248  
   249  	return &multiInfo{
   250  		Name:      name,
   251  		PubKey:    pub,
   252  		Threshold: multiPK.K,
   253  		PubKeys:   pubKeys,
   254  	}
   255  }
   256  
   257  // GetType implements Info interface
   258  func (i multiInfo) GetType() KeyType {
   259  	return TypeMulti
   260  }
   261  
   262  // GetName implements Info interface
   263  func (i multiInfo) GetName() string {
   264  	return i.Name
   265  }
   266  
   267  // GetPubKey implements Info interface
   268  func (i multiInfo) GetPubKey() crypto.PubKey {
   269  	return i.PubKey
   270  }
   271  
   272  // GetAddress implements Info interface
   273  func (i multiInfo) GetAddress() crypto.Address {
   274  	return i.PubKey.Address()
   275  }
   276  
   277  // GetPath implements Info interface
   278  func (i multiInfo) GetPath() (*hd.BIP44Params, error) {
   279  	return nil, fmt.Errorf("BIP44 Paths are not available for this type")
   280  }
   281  
   282  // encoding info
   283  func writeInfo(i Info) []byte {
   284  	return amino.MustMarshalAnySized(i)
   285  }
   286  
   287  // decoding info
   288  func readInfo(bz []byte) (info Info, err error) {
   289  	err = amino.UnmarshalAnySized(bz, &info)
   290  	return
   291  }