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 }