code.vegaprotocol.io/vega@v0.79.0/wallet/api/admin_unlock_wallet_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 TestAdminUnlockWallet(t *testing.T) {
    35  	t.Run("Unlocking a key with invalid params fails", testUnlockingWalletWithInvalidParamsFails)
    36  	t.Run("Unlocking a key with valid params succeeds", testUnlockingWalletWithValidParamsSucceeds)
    37  	t.Run("Unlocking an unknown wallet fails", testUnlockingUnknownWalletFails)
    38  	t.Run("Getting internal error during wallet verification doesn't unlock the wallet", testGettingInternalErrorDuringWalletVerificationDoesNotUnlockWallet)
    39  	t.Run("Unlocking the wallet with wrong passphrase fails", testUnlockingWalletWithWrongPassphraseFails)
    40  	t.Run("Getting internal error during wallet unlocking doesn't unlock the wallet", testGettingInternalErrorDuringWalletUnlockingDoesNotUnlockWallet)
    41  }
    42  
    43  func testUnlockingWalletWithInvalidParamsFails(t *testing.T) {
    44  	tcs := []struct {
    45  		name          string
    46  		params        interface{}
    47  		expectedError error
    48  	}{
    49  		{
    50  			name:          "with nil params",
    51  			params:        nil,
    52  			expectedError: api.ErrParamsRequired,
    53  		}, {
    54  			name:          "with wrong type of params",
    55  			params:        "test",
    56  			expectedError: api.ErrParamsDoNotMatch,
    57  		}, {
    58  			name: "with empty name",
    59  			params: api.AdminUnlockWalletParams{
    60  				Wallet:     "",
    61  				Passphrase: vgrand.RandomStr(5),
    62  			},
    63  			expectedError: api.ErrWalletIsRequired,
    64  		}, {
    65  			name: "with empty passphrase",
    66  			params: api.AdminUnlockWalletParams{
    67  				Wallet:     vgrand.RandomStr(5),
    68  				Passphrase: "",
    69  			},
    70  			expectedError: api.ErrPassphraseIsRequired,
    71  		},
    72  	}
    73  
    74  	for _, tc := range tcs {
    75  		t.Run(tc.name, func(tt *testing.T) {
    76  			// given
    77  			ctx := context.Background()
    78  
    79  			// setup
    80  			handler := newUnlockWalletHandler(tt)
    81  
    82  			// when
    83  			errorDetails := handler.handle(t, ctx, tc.params)
    84  
    85  			// then
    86  			assertInvalidParams(tt, errorDetails, tc.expectedError)
    87  		})
    88  	}
    89  }
    90  
    91  func testUnlockingWalletWithValidParamsSucceeds(t *testing.T) {
    92  	// given
    93  	ctx := context.Background()
    94  	expectedWallet := vgrand.RandomStr(5)
    95  	passphrase := vgrand.RandomStr(5)
    96  
    97  	// setup
    98  	handler := newUnlockWalletHandler(t)
    99  	// -- expected calls
   100  	handler.walletStore.EXPECT().WalletExists(ctx, expectedWallet).Times(1).Return(true, nil)
   101  	handler.walletStore.EXPECT().UnlockWallet(ctx, expectedWallet, passphrase).Times(1).Return(nil)
   102  
   103  	// when
   104  	errorDetails := handler.handle(t, ctx, api.AdminUnlockWalletParams{
   105  		Wallet:     expectedWallet,
   106  		Passphrase: passphrase,
   107  	})
   108  
   109  	// then
   110  	require.Nil(t, errorDetails)
   111  }
   112  
   113  func testUnlockingUnknownWalletFails(t *testing.T) {
   114  	// given
   115  	ctx := context.Background()
   116  	passphrase := vgrand.RandomStr(5)
   117  	name := vgrand.RandomStr(5)
   118  
   119  	// setup
   120  	handler := newUnlockWalletHandler(t)
   121  	// -- expected calls
   122  	handler.walletStore.EXPECT().WalletExists(ctx, name).Times(1).Return(false, nil)
   123  
   124  	// when
   125  	errorDetails := handler.handle(t, ctx, api.AdminUnlockWalletParams{
   126  		Wallet:     name,
   127  		Passphrase: passphrase,
   128  	})
   129  
   130  	// then
   131  	require.NotNil(t, errorDetails)
   132  	assertInvalidParams(t, errorDetails, api.ErrWalletDoesNotExist)
   133  }
   134  
   135  func testGettingInternalErrorDuringWalletVerificationDoesNotUnlockWallet(t *testing.T) {
   136  	// given
   137  	ctx := context.Background()
   138  	expectedWallet := vgrand.RandomStr(5)
   139  	passphrase := vgrand.RandomStr(5)
   140  
   141  	// setup
   142  	handler := newUnlockWalletHandler(t)
   143  	// -- expected calls
   144  	handler.walletStore.EXPECT().WalletExists(ctx, expectedWallet).Times(1).Return(false, assert.AnError)
   145  
   146  	// when
   147  	errorDetails := handler.handle(t, ctx, api.AdminUnlockWalletParams{
   148  		Wallet:     expectedWallet,
   149  		Passphrase: passphrase,
   150  	})
   151  
   152  	// then
   153  	require.NotNil(t, errorDetails)
   154  	assertInternalError(t, errorDetails, fmt.Errorf("could not verify the wallet exists: %w", assert.AnError))
   155  }
   156  
   157  func testUnlockingWalletWithWrongPassphraseFails(t *testing.T) {
   158  	// given
   159  	ctx := context.Background()
   160  	passphrase := vgrand.RandomStr(5)
   161  	expectedWallet := vgrand.RandomStr(5)
   162  
   163  	// setup
   164  	handler := newUnlockWalletHandler(t)
   165  	// -- expected calls
   166  	handler.walletStore.EXPECT().WalletExists(ctx, expectedWallet).Times(1).Return(true, nil)
   167  	handler.walletStore.EXPECT().UnlockWallet(ctx, expectedWallet, passphrase).Times(1).Return(wallet.ErrWrongPassphrase)
   168  
   169  	// when
   170  	errorDetails := handler.handle(t, ctx, api.AdminUnlockWalletParams{
   171  		Wallet:     expectedWallet,
   172  		Passphrase: passphrase,
   173  	})
   174  
   175  	// then
   176  	require.NotNil(t, errorDetails)
   177  	assertInvalidParams(t, errorDetails, wallet.ErrWrongPassphrase)
   178  }
   179  
   180  func testGettingInternalErrorDuringWalletUnlockingDoesNotUnlockWallet(t *testing.T) {
   181  	// given
   182  	ctx := context.Background()
   183  	passphrase := vgrand.RandomStr(5)
   184  	expectedWallet := vgrand.RandomStr(5)
   185  
   186  	// setup
   187  	handler := newUnlockWalletHandler(t)
   188  	// -- expected calls
   189  	handler.walletStore.EXPECT().WalletExists(ctx, expectedWallet).Times(1).Return(true, nil)
   190  	handler.walletStore.EXPECT().UnlockWallet(ctx, expectedWallet, passphrase).Times(1).Return(assert.AnError)
   191  
   192  	// when
   193  	errorDetails := handler.handle(t, ctx, api.AdminUnlockWalletParams{
   194  		Wallet:     expectedWallet,
   195  		Passphrase: passphrase,
   196  	})
   197  
   198  	// then
   199  	require.NotNil(t, errorDetails)
   200  	assertInternalError(t, errorDetails, fmt.Errorf("could not unlock the wallet: %w", assert.AnError))
   201  }
   202  
   203  type unlockWalletHandler struct {
   204  	*api.AdminUnlockWallet
   205  	ctrl        *gomock.Controller
   206  	walletStore *mocks.MockWalletStore
   207  }
   208  
   209  func (h *unlockWalletHandler) handle(t *testing.T, ctx context.Context, params jsonrpc.Params) *jsonrpc.ErrorDetails {
   210  	t.Helper()
   211  	rawResult, err := h.Handle(ctx, params)
   212  	require.Nil(t, rawResult)
   213  	return err
   214  }
   215  
   216  func newUnlockWalletHandler(t *testing.T) *unlockWalletHandler {
   217  	t.Helper()
   218  
   219  	ctrl := gomock.NewController(t)
   220  	walletStore := mocks.NewMockWalletStore(ctrl)
   221  
   222  	return &unlockWalletHandler{
   223  		AdminUnlockWallet: api.NewAdminUnlockWallet(walletStore),
   224  		ctrl:              ctrl,
   225  		walletStore:       walletStore,
   226  	}
   227  }