code.vegaprotocol.io/vega@v0.79.0/core/nodewallets/registry/registry.go (about)

     1  // Copyright (C) 2023 Gobalsky Labs Limited
     2  //
     3  // This program is free software: you can redistribute it and/or modify
     4  // it under the terms of the GNU Affero General Public License as
     5  // published by the Free Software Foundation, either version 3 of the
     6  // License, or (at your option) any later version.
     7  //
     8  // This program is distributed in the hope that it will be useful,
     9  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    10  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    11  // GNU Affero General Public License for more details.
    12  //
    13  // You should have received a copy of the GNU Affero General Public License
    14  // along with this program.  If not, see <http://www.gnu.org/licenses/>.
    15  
    16  package registry
    17  
    18  import (
    19  	"encoding/json"
    20  	"errors"
    21  	"fmt"
    22  
    23  	vgfs "code.vegaprotocol.io/vega/libs/fs"
    24  	"code.vegaprotocol.io/vega/paths"
    25  )
    26  
    27  var (
    28  	errInternalWrongPassphrase = errors.New("couldn't decrypt buffer: cipher: message authentication failed")
    29  	ErrWrongPassphrase         = errors.New("wrong passphrase")
    30  )
    31  
    32  const (
    33  	EthereumWalletTypeKeyStore ethereumWalletType = "key-store"
    34  	EthereumWalletTypeClef     ethereumWalletType = "clef"
    35  )
    36  
    37  type Registry struct {
    38  	Tendermint *RegisteredTendermintPubkey `json:"tendermint,omitempty"`
    39  	Ethereum   *RegisteredEthereumWallet   `json:"ethereum,omitempty"`
    40  	Vega       *RegisteredVegaWallet       `json:"vega,omitempty"`
    41  }
    42  
    43  type ethereumWalletType string
    44  
    45  type EthereumWalletDetails interface {
    46  	ETHWallet()
    47  }
    48  
    49  type EthereumKeyStoreWallet struct {
    50  	Name       string `json:"name"`
    51  	Passphrase string `json:"passphrase"`
    52  }
    53  
    54  func (e EthereumKeyStoreWallet) ETHWallet() {}
    55  
    56  type EthereumClefWallet struct {
    57  	Name           string `json:"name"`
    58  	AccountAddress string `json:"account-address"`
    59  	ClefAddress    string `json:"clef-address"`
    60  }
    61  
    62  func (e EthereumClefWallet) ETHWallet() {}
    63  
    64  type RegisteredEthereumWallet struct {
    65  	Type    ethereumWalletType    `json:"type"`
    66  	Details EthereumWalletDetails `json:"details"`
    67  }
    68  
    69  func (rw *RegisteredEthereumWallet) UnmarshalJSON(data []byte) error {
    70  	input := struct {
    71  		Type    string          `json:"type"`
    72  		Details json.RawMessage `json:"details"`
    73  	}{}
    74  
    75  	if err := json.Unmarshal(data, &input); err != nil {
    76  		return err
    77  	}
    78  
    79  	rw.Type = ethereumWalletType(input.Type)
    80  
    81  	switch rw.Type {
    82  	case EthereumWalletTypeKeyStore:
    83  		var keyStore EthereumKeyStoreWallet
    84  		if err := json.Unmarshal(input.Details, &keyStore); err != nil {
    85  			return err
    86  		}
    87  
    88  		rw.Details = keyStore
    89  	case EthereumWalletTypeClef:
    90  		var clef EthereumClefWallet
    91  		if err := json.Unmarshal(input.Details, &clef); err != nil {
    92  			return err
    93  		}
    94  
    95  		rw.Details = clef
    96  	default:
    97  		return fmt.Errorf("unknown Ethereum wallet type %s", rw.Type)
    98  	}
    99  
   100  	return nil
   101  }
   102  
   103  type RegisteredVegaWallet struct {
   104  	Name       string `json:"name"`
   105  	Passphrase string `json:"passphrase"`
   106  }
   107  
   108  type RegisteredTendermintPubkey struct {
   109  	Pubkey string `json:"pubkey"`
   110  }
   111  
   112  type Loader struct {
   113  	registryFilePath string
   114  }
   115  
   116  func NewLoader(vegaPaths paths.Paths, passphrase string) (*Loader, error) {
   117  	registryFilePath, err := vegaPaths.CreateConfigPathFor(paths.NodeWalletsConfigFile)
   118  	if err != nil {
   119  		return nil, fmt.Errorf("couldn't get config path for %s: %w", paths.NodeWalletsConfigFile, err)
   120  	}
   121  
   122  	exists, err := vgfs.FileExists(registryFilePath)
   123  	if err != nil {
   124  		return nil, fmt.Errorf("couldn't verify the presence of %s: %w", paths.NodeWalletsConfigFile, err)
   125  	}
   126  	if !exists {
   127  		err := paths.WriteEncryptedFile(registryFilePath, passphrase, &Registry{})
   128  		if err != nil {
   129  			return nil, fmt.Errorf("couldn't write default file %s: %w", registryFilePath, err)
   130  		}
   131  	}
   132  
   133  	return &Loader{
   134  		registryFilePath: registryFilePath,
   135  	}, nil
   136  }
   137  
   138  func (l *Loader) Get(passphrase string) (*Registry, error) {
   139  	registry := &Registry{}
   140  	if err := paths.ReadEncryptedFile(l.registryFilePath, passphrase, registry); err != nil {
   141  		if err.Error() == errInternalWrongPassphrase.Error() {
   142  			return nil, ErrWrongPassphrase
   143  		}
   144  		return nil, fmt.Errorf("couldn't read encrypted file %s: %w", l.registryFilePath, err)
   145  	}
   146  	return registry, nil
   147  }
   148  
   149  func (l *Loader) Save(registry *Registry, passphrase string) error {
   150  	err := paths.WriteEncryptedFile(l.registryFilePath, passphrase, registry)
   151  	if err != nil {
   152  		return fmt.Errorf("couldn't write encrypted file %s: %w", l.registryFilePath, err)
   153  	}
   154  	return nil
   155  }
   156  
   157  func (l *Loader) RegistryFilePath() string {
   158  	return l.registryFilePath
   159  }