code.vegaprotocol.io/vega@v0.79.0/wallet/api/admin_generate_key_test.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 api_test
    17  
    18  import (
    19  	"context"
    20  	"fmt"
    21  	"testing"
    22  
    23  	"code.vegaprotocol.io/vega/libs/jsonrpc"
    24  	vgrand "code.vegaprotocol.io/vega/libs/rand"
    25  	"code.vegaprotocol.io/vega/wallet/api"
    26  	"code.vegaprotocol.io/vega/wallet/api/mocks"
    27  	"code.vegaprotocol.io/vega/wallet/wallet"
    28  
    29  	"github.com/golang/mock/gomock"
    30  	"github.com/stretchr/testify/assert"
    31  	"github.com/stretchr/testify/require"
    32  )
    33  
    34  func TestAdminGenerateKey(t *testing.T) {
    35  	t.Run("Documentation matches the code", testAdminGenerateKeySchemaCorrect)
    36  	t.Run("Generating a key with invalid params fails", testGeneratingKeyWithInvalidParamsFails)
    37  	t.Run("Generating a key with valid params succeeds", testGeneratingKeyWithValidParamsSucceeds)
    38  	t.Run("Generating a key on unknown wallet fails", testGeneratingKeyOnUnknownWalletFails)
    39  	t.Run("Getting internal error during wallet verification doesn't generate the key", testGettingInternalErrorDuringWalletVerificationDoesNotGenerateKey)
    40  	t.Run("Getting internal error during wallet retrieval doesn't generate the key", testGettingInternalErrorDuringWalletRetrievalDoesNotGenerateKey)
    41  	t.Run("Getting internal error during wallet saving doesn't generate the key", testGettingInternalErrorDuringWalletSavingDoesNotGenerateKey)
    42  }
    43  
    44  func testAdminGenerateKeySchemaCorrect(t *testing.T) {
    45  	assertEqualSchema(t, "admin.generate_key", api.AdminGenerateKeyParams{}, api.AdminGenerateKeyResult{})
    46  }
    47  
    48  func testGeneratingKeyWithInvalidParamsFails(t *testing.T) {
    49  	tcs := []struct {
    50  		name          string
    51  		params        interface{}
    52  		expectedError error
    53  	}{
    54  		{
    55  			name:          "with nil params",
    56  			params:        nil,
    57  			expectedError: api.ErrParamsRequired,
    58  		}, {
    59  			name:          "with wrong type of params",
    60  			params:        "test",
    61  			expectedError: api.ErrParamsDoNotMatch,
    62  		}, {
    63  			name: "with empty name",
    64  			params: api.AdminGenerateKeyParams{
    65  				Wallet: "",
    66  			},
    67  			expectedError: api.ErrWalletIsRequired,
    68  		},
    69  	}
    70  
    71  	for _, tc := range tcs {
    72  		t.Run(tc.name, func(tt *testing.T) {
    73  			// given
    74  			ctx := context.Background()
    75  
    76  			// setup
    77  			handler := newGenerateKeyHandler(tt)
    78  
    79  			// when
    80  			result, errorDetails := handler.handle(t, ctx, tc.params)
    81  
    82  			// then
    83  			require.Empty(tt, result)
    84  			assertInvalidParams(tt, errorDetails, tc.expectedError)
    85  		})
    86  	}
    87  }
    88  
    89  func testGeneratingKeyWithValidParamsSucceeds(t *testing.T) {
    90  	// given
    91  	ctx := context.Background()
    92  	name := vgrand.RandomStr(5)
    93  	expectedWallet, _, err := wallet.NewHDWallet(name)
    94  	if err != nil {
    95  		t.Fatal(err)
    96  	}
    97  
    98  	// setup
    99  	handler := newGenerateKeyHandler(t)
   100  	// -- expected calls
   101  	handler.walletStore.EXPECT().WalletExists(ctx, name).Times(1).Return(true, nil)
   102  	handler.walletStore.EXPECT().IsWalletAlreadyUnlocked(ctx, expectedWallet.Name()).Times(1).Return(true, nil)
   103  	handler.walletStore.EXPECT().GetWallet(ctx, name).Times(1).Return(expectedWallet, nil)
   104  	handler.walletStore.EXPECT().UpdateWallet(ctx, expectedWallet).Times(1).Return(nil)
   105  
   106  	// when
   107  	result, errorDetails := handler.handle(t, ctx, api.AdminGenerateKeyParams{
   108  		Wallet:   name,
   109  		Metadata: []wallet.Metadata{{Key: "mode", Value: "test"}},
   110  	})
   111  
   112  	// then
   113  	require.Nil(t, errorDetails)
   114  	assert.Equal(t, name, expectedWallet.Name())
   115  	assert.Len(t, expectedWallet.ListKeyPairs(), 1)
   116  	keyPair := expectedWallet.ListKeyPairs()[0]
   117  	assert.Equal(t, []wallet.Metadata{{Key: "mode", Value: "test"}, {Key: "name", Value: "Key 1"}}, keyPair.Metadata())
   118  	// Verify the result.
   119  	assert.Equal(t, keyPair.PublicKey(), result.PublicKey)
   120  	assert.Equal(t, keyPair.AlgorithmName(), result.Algorithm.Name)
   121  	assert.Equal(t, keyPair.AlgorithmVersion(), result.Algorithm.Version)
   122  	assert.Equal(t, keyPair.Metadata(), result.Metadata)
   123  }
   124  
   125  func testGeneratingKeyOnUnknownWalletFails(t *testing.T) {
   126  	// given
   127  	ctx := context.Background()
   128  	name := vgrand.RandomStr(5)
   129  
   130  	// setup
   131  	handler := newGenerateKeyHandler(t)
   132  	// -- expected calls
   133  	handler.walletStore.EXPECT().WalletExists(ctx, name).Times(1).Return(false, nil)
   134  
   135  	// when
   136  	result, errorDetails := handler.handle(t, ctx, api.AdminGenerateKeyParams{
   137  		Wallet: name,
   138  	})
   139  
   140  	// then
   141  	require.NotNil(t, errorDetails)
   142  	assert.Empty(t, result)
   143  	assertInvalidParams(t, errorDetails, api.ErrWalletDoesNotExist)
   144  }
   145  
   146  func testGettingInternalErrorDuringWalletVerificationDoesNotGenerateKey(t *testing.T) {
   147  	// given
   148  	ctx := context.Background()
   149  	name := vgrand.RandomStr(5)
   150  
   151  	// setup
   152  	handler := newGenerateKeyHandler(t)
   153  	// -- expected calls
   154  	handler.walletStore.EXPECT().WalletExists(ctx, name).Times(1).Return(false, assert.AnError)
   155  
   156  	// when
   157  	result, errorDetails := handler.handle(t, ctx, api.AdminGenerateKeyParams{
   158  		Wallet: name,
   159  	})
   160  
   161  	// then
   162  	require.NotNil(t, errorDetails)
   163  	assert.Empty(t, result)
   164  	assertInternalError(t, errorDetails, fmt.Errorf("could not verify the wallet exists: %w", assert.AnError))
   165  }
   166  
   167  func testGettingInternalErrorDuringWalletRetrievalDoesNotGenerateKey(t *testing.T) {
   168  	// given
   169  	ctx := context.Background()
   170  	name := vgrand.RandomStr(5)
   171  
   172  	// setup
   173  	handler := newGenerateKeyHandler(t)
   174  	// -- expected calls
   175  	handler.walletStore.EXPECT().WalletExists(ctx, name).Times(1).Return(true, nil)
   176  	handler.walletStore.EXPECT().IsWalletAlreadyUnlocked(ctx, name).Times(1).Return(true, nil)
   177  	handler.walletStore.EXPECT().GetWallet(ctx, name).Times(1).Return(nil, assert.AnError)
   178  
   179  	// when
   180  	result, errorDetails := handler.handle(t, ctx, api.AdminGenerateKeyParams{
   181  		Wallet: name,
   182  	})
   183  
   184  	// then
   185  	require.NotNil(t, errorDetails)
   186  	assert.Empty(t, result)
   187  	assertInternalError(t, errorDetails, fmt.Errorf("could not retrieve the wallet: %w", assert.AnError))
   188  }
   189  
   190  func testGettingInternalErrorDuringWalletSavingDoesNotGenerateKey(t *testing.T) {
   191  	// given
   192  	ctx := context.Background()
   193  	name := vgrand.RandomStr(5)
   194  	expectedWallet, _, err := wallet.NewHDWallet(name)
   195  	if err != nil {
   196  		t.Fatal(err)
   197  	}
   198  
   199  	// setup
   200  	handler := newGenerateKeyHandler(t)
   201  	// -- expected calls
   202  	handler.walletStore.EXPECT().WalletExists(ctx, name).Times(1).Return(true, nil)
   203  	handler.walletStore.EXPECT().IsWalletAlreadyUnlocked(ctx, expectedWallet.Name()).Times(1).Return(true, nil)
   204  	handler.walletStore.EXPECT().GetWallet(ctx, name).Times(1).Return(expectedWallet, nil)
   205  	handler.walletStore.EXPECT().UpdateWallet(ctx, gomock.Any()).Times(1).Return(assert.AnError)
   206  
   207  	// when
   208  	result, errorDetails := handler.handle(t, ctx, api.AdminGenerateKeyParams{
   209  		Wallet: name,
   210  	})
   211  
   212  	// then
   213  	require.NotNil(t, errorDetails)
   214  	assert.Empty(t, result)
   215  	assertInternalError(t, errorDetails, fmt.Errorf("could not save the wallet: %w", assert.AnError))
   216  }
   217  
   218  type generateKeyHandler struct {
   219  	*api.AdminGenerateKey
   220  	ctrl        *gomock.Controller
   221  	walletStore *mocks.MockWalletStore
   222  }
   223  
   224  func (h *generateKeyHandler) handle(t *testing.T, ctx context.Context, params jsonrpc.Params) (api.AdminGenerateKeyResult, *jsonrpc.ErrorDetails) {
   225  	t.Helper()
   226  
   227  	rawResult, err := h.Handle(ctx, params)
   228  	if rawResult != nil {
   229  		result, ok := rawResult.(api.AdminGenerateKeyResult)
   230  		if !ok {
   231  			t.Fatal("AdminGenerateKey handler result is not a AdminGenerateKeyResult")
   232  		}
   233  		return result, err
   234  	}
   235  	return api.AdminGenerateKeyResult{}, err
   236  }
   237  
   238  func newGenerateKeyHandler(t *testing.T) *generateKeyHandler {
   239  	t.Helper()
   240  
   241  	ctrl := gomock.NewController(t)
   242  	walletStore := mocks.NewMockWalletStore(ctrl)
   243  
   244  	return &generateKeyHandler{
   245  		AdminGenerateKey: api.NewAdminGenerateKey(walletStore),
   246  		ctrl:             ctrl,
   247  		walletStore:      walletStore,
   248  	}
   249  }