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 }