code.vegaprotocol.io/vega@v0.79.0/core/nodewallets/ethereum_handler.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 nodewallets
    17  
    18  import (
    19  	"fmt"
    20  	"path/filepath"
    21  
    22  	"code.vegaprotocol.io/vega/core/nodewallets/eth"
    23  	"code.vegaprotocol.io/vega/core/nodewallets/eth/clef"
    24  	"code.vegaprotocol.io/vega/core/nodewallets/eth/keystore"
    25  	"code.vegaprotocol.io/vega/core/nodewallets/registry"
    26  	"code.vegaprotocol.io/vega/paths"
    27  
    28  	ethcommon "github.com/ethereum/go-ethereum/common"
    29  	"github.com/ethereum/go-ethereum/rpc"
    30  )
    31  
    32  func GetEthereumWallet(vegaPaths paths.Paths, registryPassphrase string) (*eth.Wallet, error) {
    33  	registryLoader, err := registry.NewLoader(vegaPaths, registryPassphrase)
    34  	if err != nil {
    35  		return nil, fmt.Errorf("couldn't initialise node wallet registry: %v", err)
    36  	}
    37  
    38  	registry, err := registryLoader.Get(registryPassphrase)
    39  	if err != nil {
    40  		return nil, fmt.Errorf("couldn't load node wallet registry: %v", err)
    41  	}
    42  
    43  	if registry.Ethereum == nil {
    44  		return nil, ErrEthereumWalletIsMissing
    45  	}
    46  
    47  	return GetEthereumWalletWithRegistry(vegaPaths, registry)
    48  }
    49  
    50  func GetEthereumWalletWithRegistry(vegaPaths paths.Paths, reg *registry.Registry) (*eth.Wallet, error) {
    51  	switch walletRegistry := reg.Ethereum.Details.(type) {
    52  	case registry.EthereumClefWallet:
    53  		ethAddress := ethcommon.HexToAddress(walletRegistry.AccountAddress)
    54  
    55  		client, err := rpc.Dial(walletRegistry.ClefAddress)
    56  		if err != nil {
    57  			return nil, fmt.Errorf("failed to dial Clef daemon: %w", err)
    58  		}
    59  
    60  		w, err := clef.NewWallet(client, walletRegistry.ClefAddress, ethAddress)
    61  		if err != nil {
    62  			return nil, fmt.Errorf("couldn't initialise Ethereum Clef node wallet: %w", err)
    63  		}
    64  
    65  		return eth.NewWallet(w), nil
    66  	case registry.EthereumKeyStoreWallet:
    67  		walletLoader, err := keystore.InitialiseWalletLoader(vegaPaths)
    68  		if err != nil {
    69  			return nil, fmt.Errorf("couldn't initialise Ethereum key store node wallet loader: %w", err)
    70  		}
    71  
    72  		w, err := walletLoader.Load(walletRegistry.Name, walletRegistry.Passphrase)
    73  		if err != nil {
    74  			return nil, fmt.Errorf("couldn't load Ethereum key store node wallet: %w", err)
    75  		}
    76  
    77  		return eth.NewWallet(w), nil
    78  	default:
    79  		return nil, fmt.Errorf("could not create unknown Ethereum wallet type %q", reg.Ethereum.Type)
    80  	}
    81  }
    82  
    83  func GenerateEthereumWallet(
    84  	vegaPaths paths.Paths,
    85  	registryPassphrase,
    86  	walletPassphrase string,
    87  	clefAddress string,
    88  	overwrite bool,
    89  ) (map[string]string, error) {
    90  	registryLoader, err := registry.NewLoader(vegaPaths, registryPassphrase)
    91  	if err != nil {
    92  		return nil, fmt.Errorf("couldn't initialise node wallet registry: %v", err)
    93  	}
    94  
    95  	reg, err := registryLoader.Get(registryPassphrase)
    96  	if err != nil {
    97  		return nil, fmt.Errorf("couldn't load node wallet registry: %v", err)
    98  	}
    99  
   100  	if !overwrite && reg.Ethereum != nil {
   101  		return nil, ErrEthereumWalletAlreadyExists
   102  	}
   103  
   104  	var data map[string]string
   105  
   106  	if clefAddress != "" {
   107  		client, err := rpc.Dial(clefAddress)
   108  		if err != nil {
   109  			return nil, fmt.Errorf("failed to dial Clef daemon: %w", err)
   110  		}
   111  
   112  		w, err := clef.GenerateNewWallet(client, clefAddress)
   113  		if err != nil {
   114  			return nil, fmt.Errorf("couldn't generate Ethereum clef node wallet: %w", err)
   115  		}
   116  
   117  		data = map[string]string{
   118  			"clefAddress":    clefAddress,
   119  			"accountAddress": w.PubKey().Hex(),
   120  		}
   121  
   122  		reg.Ethereum = &registry.RegisteredEthereumWallet{
   123  			Type: registry.EthereumWalletTypeClef,
   124  			Details: registry.EthereumClefWallet{
   125  				Name:           w.Name(),
   126  				AccountAddress: w.PubKey().Hex(),
   127  				ClefAddress:    clefAddress,
   128  			},
   129  		}
   130  	} else {
   131  		keyStoreLoader, err := keystore.InitialiseWalletLoader(vegaPaths)
   132  		if err != nil {
   133  			return nil, fmt.Errorf("couldn't initialise Ethereum key store node wallet loader: %w", err)
   134  		}
   135  
   136  		w, d, err := keyStoreLoader.Generate(walletPassphrase)
   137  		if err != nil {
   138  			return nil, fmt.Errorf("couldn't generate Ethereum key store node wallet: %w", err)
   139  		}
   140  
   141  		data = d
   142  
   143  		reg.Ethereum = &registry.RegisteredEthereumWallet{
   144  			Type: registry.EthereumWalletTypeKeyStore,
   145  			Details: registry.EthereumKeyStoreWallet{
   146  				Name:       w.Name(),
   147  				Passphrase: walletPassphrase,
   148  			},
   149  		}
   150  	}
   151  
   152  	if err := registryLoader.Save(reg, registryPassphrase); err != nil {
   153  		return nil, fmt.Errorf("couldn't save registry: %w", err)
   154  	}
   155  
   156  	data["registryFilePath"] = registryLoader.RegistryFilePath()
   157  	return data, nil
   158  }
   159  
   160  func ImportEthereumWallet(
   161  	vegaPaths paths.Paths,
   162  	registryPassphrase,
   163  	walletPassphrase,
   164  	clefAccount,
   165  	clefAddress,
   166  	sourceFilePath string,
   167  	overwrite bool,
   168  ) (map[string]string, error) {
   169  	registryLoader, err := registry.NewLoader(vegaPaths, registryPassphrase)
   170  	if err != nil {
   171  		return nil, fmt.Errorf("couldn't initialise node wallet registry: %v", err)
   172  	}
   173  
   174  	reg, err := registryLoader.Get(registryPassphrase)
   175  	if err != nil {
   176  		return nil, fmt.Errorf("couldn't load node wallet registry: %v", err)
   177  	}
   178  
   179  	if !overwrite && reg.Ethereum != nil {
   180  		return nil, ErrEthereumWalletAlreadyExists
   181  	}
   182  
   183  	var data map[string]string
   184  
   185  	if clefAddress != "" {
   186  		if !ethcommon.IsHexAddress(clefAccount) {
   187  			return nil, fmt.Errorf("invalid Ethereum hex address %q", clefAccount)
   188  		}
   189  
   190  		ethAddress := ethcommon.HexToAddress(clefAccount)
   191  
   192  		client, err := rpc.Dial(clefAddress)
   193  		if err != nil {
   194  			return nil, fmt.Errorf("failed to dial Clef daemon: %w", err)
   195  		}
   196  
   197  		w, err := clef.NewWallet(client, clefAddress, ethAddress)
   198  		if err != nil {
   199  			return nil, fmt.Errorf("couldn't initialise Ethereum Clef node wallet: %w", err)
   200  		}
   201  
   202  		data = map[string]string{
   203  			"clefAddress":    clefAddress,
   204  			"accountAddress": w.PubKey().Hex(),
   205  		}
   206  
   207  		reg.Ethereum = &registry.RegisteredEthereumWallet{
   208  			Type: registry.EthereumWalletTypeClef,
   209  			Details: registry.EthereumClefWallet{
   210  				Name:           w.Name(),
   211  				AccountAddress: w.PubKey().Hex(),
   212  				ClefAddress:    clefAddress,
   213  			},
   214  		}
   215  	} else {
   216  		if !filepath.IsAbs(sourceFilePath) {
   217  			return nil, fmt.Errorf("path to the wallet file need to be absolute")
   218  		}
   219  
   220  		ethWalletLoader, err := keystore.InitialiseWalletLoader(vegaPaths)
   221  		if err != nil {
   222  			return nil, fmt.Errorf("couldn't initialise Ethereum node wallet loader: %w", err)
   223  		}
   224  
   225  		w, d, err := ethWalletLoader.Import(sourceFilePath, walletPassphrase)
   226  		if err != nil {
   227  			return nil, fmt.Errorf("couldn't import Ethereum node wallet: %w", err)
   228  		}
   229  
   230  		data = d
   231  
   232  		reg.Ethereum = &registry.RegisteredEthereumWallet{
   233  			Type: registry.EthereumWalletTypeKeyStore,
   234  			Details: registry.EthereumKeyStoreWallet{
   235  				Name:       w.Name(),
   236  				Passphrase: walletPassphrase,
   237  			},
   238  		}
   239  	}
   240  
   241  	if err := registryLoader.Save(reg, registryPassphrase); err != nil {
   242  		return nil, fmt.Errorf("couldn't save registry: %w", err)
   243  	}
   244  
   245  	data["registryFilePath"] = registryLoader.RegistryFilePath()
   246  	return data, nil
   247  }