code.vegaprotocol.io/vega@v0.79.0/wallet/service/service_v1_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 service_test
    17  
    18  import (
    19  	"context"
    20  	"encoding/json"
    21  	"fmt"
    22  	"net/http"
    23  	"testing"
    24  	"time"
    25  
    26  	vgrand "code.vegaprotocol.io/vega/libs/rand"
    27  	api "code.vegaprotocol.io/vega/protos/vega/api/v1"
    28  	commandspb "code.vegaprotocol.io/vega/protos/vega/commands/v1"
    29  	"code.vegaprotocol.io/vega/wallet/crypto"
    30  	v1 "code.vegaprotocol.io/vega/wallet/service/v1"
    31  	"code.vegaprotocol.io/vega/wallet/wallet"
    32  
    33  	"github.com/golang/mock/gomock"
    34  	"github.com/stretchr/testify/assert"
    35  )
    36  
    37  const (
    38  	testRecoveryPhrase = "swing ceiling chaos green put insane ripple desk match tip melt usual shrug turkey renew icon parade veteran lens govern path rough page render"
    39  
    40  	testRequestTimeout = 10 * time.Second
    41  )
    42  
    43  func TestServiceV1(t *testing.T) {
    44  	t.Run("create wallet ok", testServiceCreateWalletOK)
    45  	t.Run("create wallet fail invalid request", testServiceCreateWalletFailInvalidRequest)
    46  	t.Run("Importing a wallet succeeds", testServiceImportWalletOK)
    47  	t.Run("Importing a wallet with and invalid request fails", testServiceImportWalletFailInvalidRequest)
    48  	t.Run("login wallet ok", testServiceLoginWalletOK)
    49  	t.Run("login wallet fail invalid request", testServiceLoginWalletFailInvalidRequest)
    50  	t.Run("revoke token ok", testServiceRevokeTokenOK)
    51  	t.Run("revoke token fail invalid request", testServiceRevokeTokenFailInvalidRequest)
    52  	t.Run("gen keypair ok", testServiceGenKeypairOK)
    53  	t.Run("gen keypair fail invalid request", testServiceGenKeypairFailInvalidRequest)
    54  	t.Run("list keypair ok", testServiceListPublicKeysOK)
    55  	t.Run("list keypair fail invalid request", testServiceListPublicKeysFailInvalidRequest)
    56  	t.Run("get keypair ok", testServiceGetPublicKeyOK)
    57  	t.Run("get keypair fail invalid request", testServiceGetPublicKeyFailInvalidRequest)
    58  	t.Run("get keypair fail key not found", testServiceGetPublicKeyFailKeyNotFound)
    59  	t.Run("get keypair fail misc error", testServiceGetPublicKeyFailMiscError)
    60  	t.Run("taint ok", testServiceTaintOK)
    61  	t.Run("taint fail invalid request", testServiceTaintFailInvalidRequest)
    62  	t.Run("update metadata", testServiceUpdateMetaOK)
    63  	t.Run("update metadata invalid request", testServiceUpdateMetaFailInvalidRequest)
    64  	t.Run("Signing transaction succeeds", testAcceptSigningTransactionSucceeds)
    65  	t.Run("Checking transaction succeeds", testCheckTransactionSucceeds)
    66  	t.Run("Checking transaction with rejected transaction succeeds", testCheckTransactionWithRejectedTransactionSucceeds)
    67  	t.Run("Checking transaction with failed transaction fails", testCheckTransactionWithFailedTransactionFails)
    68  	t.Run("Decline signing transaction manually succeeds", testDeclineSigningTransactionManuallySucceeds)
    69  	t.Run("Signing transaction fails spam", testAcceptSigningTransactionFailsSpam)
    70  	t.Run("Failed signing of transaction fails", testFailedTransactionSigningFails)
    71  	t.Run("Signing transaction with invalid request fails", testSigningTransactionWithInvalidRequestFails)
    72  	t.Run("Signing anything succeeds", testSigningAnythingSucceeds)
    73  	t.Run("Signing anything with invalid request fails", testSigningAnyDataWithInvalidRequestFails)
    74  	t.Run("Verifying anything succeeds", testVerifyingAnythingSucceeds)
    75  	t.Run("Failed verification fails", testVerifyingAnythingFails)
    76  	t.Run("Verifying anything with invalid request fails", testVerifyingAnyDataWithInvalidRequestFails)
    77  	t.Run("Requesting the chain id is successful", testGetNetworkChainIDSuccess)
    78  	t.Run("Requesting the chain id fails when node in available", testGetNetworkChainIDFailure)
    79  	t.Run("Empty chain id from network fails", TestEmptyChainIDFromNetworkFails)
    80  }
    81  
    82  func testServiceCreateWalletOK(t *testing.T) {
    83  	s := getTestServiceV1(t, "automatic")
    84  
    85  	// given
    86  	walletName := vgrand.RandomStr(5)
    87  	passphrase := vgrand.RandomStr(5)
    88  	payload := fmt.Sprintf(`{"wallet": "%s", "passphrase": "%s"}`, walletName, passphrase)
    89  
    90  	// setup
    91  	s.handler.EXPECT().CreateWallet(walletName, passphrase).Times(1).Return(testRecoveryPhrase, nil)
    92  	s.auth.EXPECT().NewSession(walletName).Times(1).Return("this is a token", nil)
    93  
    94  	// when
    95  	statusCode, _, _ := s.serveHTTP(t, createWalletRequest(t, payload))
    96  
    97  	// then
    98  	assert.Equal(t, http.StatusOK, statusCode)
    99  }
   100  
   101  func testServiceCreateWalletFailInvalidRequest(t *testing.T) {
   102  	tcs := []struct {
   103  		name    string
   104  		payload string
   105  	}{
   106  		{
   107  			name:    "misspelled wallet property",
   108  			payload: `{"wall": "jeremy", "passphrase": "oh yea?"}`,
   109  		}, {
   110  			name:    "misspelled passphrase property",
   111  			payload: `{"wallet": "jeremy", "passrase": "oh yea?"}`,
   112  		},
   113  	}
   114  
   115  	for _, tc := range tcs {
   116  		t.Run(tc.name, func(tt *testing.T) {
   117  			s := getTestServiceV1(tt, "automatic")
   118  
   119  			// when
   120  			statusCode, _, _ := s.serveHTTP(tt, createWalletRequest(tt, tc.payload))
   121  
   122  			// then
   123  			assert.Equal(tt, http.StatusBadRequest, statusCode)
   124  		})
   125  	}
   126  }
   127  
   128  func testServiceImportWalletOK(t *testing.T) {
   129  	tcs := []struct {
   130  		name    string
   131  		version uint32
   132  	}{
   133  		{
   134  			name:    "version 1",
   135  			version: 1,
   136  		}, {
   137  			name:    "version 2",
   138  			version: 2,
   139  		},
   140  	}
   141  
   142  	for _, tc := range tcs {
   143  		t.Run(tc.name, func(tt *testing.T) {
   144  			s := getTestServiceV1(tt, "automatic")
   145  
   146  			// given
   147  			walletName := vgrand.RandomStr(5)
   148  			passphrase := vgrand.RandomStr(5)
   149  			payload := fmt.Sprintf(`{"wallet": "%s", "passphrase": "%s", "recoveryPhrase": "%s", "version": %d}`, walletName, passphrase, testRecoveryPhrase, tc.version)
   150  
   151  			// setup
   152  			s.handler.EXPECT().ImportWallet(walletName, passphrase, testRecoveryPhrase, tc.version).Times(1).Return(nil)
   153  			s.auth.EXPECT().NewSession(walletName).Times(1).Return("this is a token", nil)
   154  
   155  			// when
   156  			statusCode, _, _ := s.serveHTTP(tt, importWalletRequest(tt, payload))
   157  
   158  			// then
   159  			assert.Equal(tt, http.StatusOK, statusCode)
   160  		})
   161  	}
   162  }
   163  
   164  func testServiceImportWalletFailInvalidRequest(t *testing.T) {
   165  	tcs := []struct {
   166  		name    string
   167  		payload string
   168  	}{
   169  		{
   170  			name:    "misspelled wallet property",
   171  			payload: fmt.Sprintf(`{"wall": "jeremy", "passphrase": "oh yea?", "recoveryPhrase": %q}`, testRecoveryPhrase),
   172  		}, {
   173  			name:    "misspelled passphrase property",
   174  			payload: fmt.Sprintf(`{"wallet": "jeremy", "password": "oh yea?", "recoveryPhrase": %q}`, testRecoveryPhrase),
   175  		}, {
   176  			name:    "misspelled recovery phrase property",
   177  			payload: fmt.Sprintf(`{"wallet": "jeremy", "passphrase": "oh yea?", "little_words": %q}`, testRecoveryPhrase),
   178  		},
   179  	}
   180  
   181  	for _, tc := range tcs {
   182  		t.Run(tc.name, func(tt *testing.T) {
   183  			s := getTestServiceV1(tt, "automatic")
   184  
   185  			// when
   186  			statusCode, _, _ := s.serveHTTP(tt, importWalletRequest(tt, tc.payload))
   187  
   188  			// then
   189  			assert.Equal(tt, http.StatusBadRequest, statusCode)
   190  		})
   191  	}
   192  }
   193  
   194  func testServiceLoginWalletOK(t *testing.T) {
   195  	s := getTestServiceV1(t, "automatic")
   196  
   197  	// given
   198  	walletName := vgrand.RandomStr(5)
   199  	passphrase := vgrand.RandomStr(5)
   200  	payload := fmt.Sprintf(`{"wallet": "%s", "passphrase": "%s"}`, walletName, passphrase)
   201  
   202  	// setup
   203  	s.handler.EXPECT().LoginWallet(walletName, passphrase).Times(1).Return(nil)
   204  	s.auth.EXPECT().NewSession(walletName).Times(1).Return("this is a token", nil)
   205  
   206  	// when
   207  	statusCode, _, _ := s.serveHTTP(t, loginRequest(t, payload))
   208  
   209  	// then
   210  	assert.Equal(t, http.StatusOK, statusCode)
   211  }
   212  
   213  func testServiceLoginWalletFailInvalidRequest(t *testing.T) {
   214  	tcs := []struct {
   215  		name    string
   216  		payload string
   217  	}{
   218  		{
   219  			name:    "misspelled wallet property",
   220  			payload: `{"wall": "jeremy", "passphrase": "oh yea?"}`,
   221  		}, {
   222  			name:    "misspelled passphrase property",
   223  			payload: `{"wallet": "jeremy", "passrase": "oh yea?"}`,
   224  		},
   225  	}
   226  
   227  	for _, tc := range tcs {
   228  		t.Run(tc.name, func(tt *testing.T) {
   229  			s := getTestServiceV1(tt, "automatic")
   230  			t.Cleanup(func() {
   231  				s.ctrl.Finish()
   232  			})
   233  
   234  			// when
   235  			statusCode, _, _ := s.serveHTTP(tt, loginRequest(tt, tc.payload))
   236  
   237  			// then
   238  			assert.Equal(tt, http.StatusBadRequest, statusCode)
   239  		})
   240  	}
   241  }
   242  
   243  func testServiceRevokeTokenOK(t *testing.T) {
   244  	s := getTestServiceV1(t, "automatic")
   245  
   246  	// given
   247  	walletName := vgrand.RandomStr(5)
   248  	token := vgrand.RandomStr(5)
   249  	headers := authHeadersV1(t, token)
   250  
   251  	// setup
   252  	s.auth.EXPECT().Revoke(token).Times(1).Return(walletName, nil)
   253  
   254  	// when
   255  	statusCode, _, _ := s.serveHTTP(t, logoutRequest(t, headers))
   256  
   257  	// then
   258  	assert.Equal(t, http.StatusOK, statusCode)
   259  }
   260  
   261  func testServiceRevokeTokenFailInvalidRequest(t *testing.T) {
   262  	tcs := []struct {
   263  		name    string
   264  		headers map[string]string
   265  	}{
   266  		{
   267  			name:    "no header",
   268  			headers: map[string]string{},
   269  		}, {
   270  			name:    "no token",
   271  			headers: authHeadersV1(t, ""),
   272  		},
   273  	}
   274  
   275  	for _, tc := range tcs {
   276  		t.Run(tc.name, func(tt *testing.T) {
   277  			s := getTestServiceV1(t, "automatic")
   278  
   279  			// when
   280  			statusCode, _, _ := s.serveHTTP(tt, logoutRequest(t, tc.headers))
   281  
   282  			// then
   283  			assert.Equal(tt, http.StatusBadRequest, statusCode)
   284  		})
   285  	}
   286  }
   287  
   288  func testServiceGenKeypairOK(t *testing.T) {
   289  	s := getTestServiceV1(t, "automatic")
   290  
   291  	// given
   292  	ed25519 := crypto.NewEd25519()
   293  	key := &wallet.HDPublicKey{
   294  		PublicKey: vgrand.RandomStr(5),
   295  		Algorithm: wallet.Algorithm{
   296  			Name:    ed25519.Name(),
   297  			Version: ed25519.Version(),
   298  		},
   299  		Tainted:      false,
   300  		MetadataList: nil,
   301  	}
   302  	walletName := vgrand.RandomStr(5)
   303  	passphrase := vgrand.RandomStr(5)
   304  	token := vgrand.RandomStr(5)
   305  	headers := authHeadersV1(t, token)
   306  	payload := fmt.Sprintf(`{"passphrase": "%s"}`, passphrase)
   307  
   308  	// setup
   309  	s.auth.EXPECT().VerifyToken(token).Times(1).Return(walletName, nil)
   310  	s.handler.EXPECT().SecureGenerateKeyPair(walletName, passphrase, gomock.Len(0)).Times(1).Return(key.PublicKey, nil)
   311  	s.handler.EXPECT().GetPublicKey(walletName, key.PublicKey).Times(1).Return(key, nil)
   312  
   313  	// when
   314  	statusCode, _, _ := s.serveHTTP(t, generateKeyRequest(t, payload, headers))
   315  
   316  	// then
   317  	assert.Equal(t, http.StatusOK, statusCode)
   318  }
   319  
   320  func testServiceGenKeypairFailInvalidRequest(t *testing.T) {
   321  	tcs := []struct {
   322  		name    string
   323  		headers map[string]string
   324  		payload string
   325  	}{
   326  		{
   327  			name:    "no header",
   328  			headers: map[string]string{},
   329  			payload: `{"passphrase": "oh yea?"}`,
   330  		}, {
   331  			name:    "no token",
   332  			headers: authHeadersV1(t, ""),
   333  			payload: `{"passphrase": "oh yea?"}`,
   334  		}, {
   335  			name:    "invalid request",
   336  			headers: authHeadersV1(t, vgrand.RandomStr(5)),
   337  		},
   338  	}
   339  
   340  	for _, tc := range tcs {
   341  		t.Run(tc.name, func(tt *testing.T) {
   342  			s := getTestServiceV1(tt, "automatic")
   343  
   344  			// when
   345  			statusCode, _, _ := s.serveHTTP(tt, generateKeyRequest(t, tc.payload, tc.headers))
   346  
   347  			// then
   348  			assert.Equal(tt, http.StatusBadRequest, statusCode)
   349  		})
   350  	}
   351  }
   352  
   353  func testServiceListPublicKeysOK(t *testing.T) {
   354  	s := getTestServiceV1(t, "automatic")
   355  
   356  	// given
   357  	walletName := vgrand.RandomStr(5)
   358  	token := vgrand.RandomStr(5)
   359  	headers := authHeadersV1(t, token)
   360  
   361  	// setup
   362  	s.auth.EXPECT().VerifyToken(token).Times(1).Return(walletName, nil)
   363  	s.handler.EXPECT().ListPublicKeys(walletName).Times(1).Return([]wallet.PublicKey{}, nil)
   364  
   365  	// when
   366  	statusCode, _, _ := s.serveHTTP(t, listKeysRequest(t, headers))
   367  
   368  	// then
   369  	assert.Equal(t, http.StatusOK, statusCode)
   370  }
   371  
   372  func testServiceListPublicKeysFailInvalidRequest(t *testing.T) {
   373  	tcs := []struct {
   374  		name    string
   375  		headers map[string]string
   376  	}{
   377  		{
   378  			name:    "no header",
   379  			headers: map[string]string{},
   380  		}, {
   381  			name:    "no token",
   382  			headers: authHeadersV1(t, ""),
   383  		},
   384  	}
   385  
   386  	for _, tc := range tcs {
   387  		t.Run(tc.name, func(tt *testing.T) {
   388  			s := getTestServiceV1(tt, "automatic")
   389  
   390  			// when
   391  			statusCode, _, _ := s.serveHTTP(tt, listKeysRequest(t, tc.headers))
   392  
   393  			// then
   394  			assert.Equal(tt, http.StatusBadRequest, statusCode)
   395  		})
   396  	}
   397  }
   398  
   399  func testServiceGetPublicKeyOK(t *testing.T) {
   400  	s := getTestServiceV1(t, "automatic")
   401  
   402  	// given
   403  	walletName := vgrand.RandomStr(5)
   404  	token := vgrand.RandomStr(5)
   405  	hdPubKey := &wallet.HDPublicKey{
   406  		Idx:       1,
   407  		PublicKey: vgrand.RandomStr(5),
   408  		Algorithm: wallet.Algorithm{
   409  			Name:    "some/algo",
   410  			Version: 1,
   411  		},
   412  		Tainted:      false,
   413  		MetadataList: []wallet.Metadata{{Key: "a", Value: "b"}},
   414  	}
   415  	headers := authHeadersV1(t, token)
   416  
   417  	// setup
   418  	s.auth.EXPECT().VerifyToken(token).Times(1).Return(walletName, nil)
   419  	s.handler.EXPECT().GetPublicKey(walletName, hdPubKey.PublicKey).Times(1).Return(hdPubKey, nil)
   420  
   421  	// when
   422  	statusCode, _, _ := s.serveHTTP(t, getKeyRequest(t, hdPubKey.PublicKey, headers))
   423  
   424  	// then
   425  	assert.Equal(t, http.StatusOK, statusCode)
   426  }
   427  
   428  func testServiceGetPublicKeyFailInvalidRequest(t *testing.T) {
   429  	tcs := []struct {
   430  		name    string
   431  		headers map[string]string
   432  	}{
   433  		{
   434  			name:    "no header",
   435  			headers: map[string]string{},
   436  		}, {
   437  			name:    "no token",
   438  			headers: authHeadersV1(t, ""),
   439  		},
   440  	}
   441  
   442  	for _, tc := range tcs {
   443  		t.Run(tc.name, func(tt *testing.T) {
   444  			s := getTestServiceV1(tt, "automatic")
   445  
   446  			// when
   447  			statusCode, _, _ := s.serveHTTP(t, getKeyRequest(t, vgrand.RandomStr(5), tc.headers))
   448  
   449  			// then
   450  			assert.Equal(tt, http.StatusBadRequest, statusCode)
   451  		})
   452  	}
   453  }
   454  
   455  func testServiceGetPublicKeyFailKeyNotFound(t *testing.T) {
   456  	s := getTestServiceV1(t, "automatic")
   457  
   458  	// given
   459  	walletName := vgrand.RandomStr(5)
   460  	pubKey := vgrand.RandomStr(5)
   461  	token := vgrand.RandomStr(5)
   462  	headers := authHeadersV1(t, token)
   463  
   464  	// setup
   465  	s.auth.EXPECT().VerifyToken(token).Times(1).Return(walletName, nil)
   466  	s.handler.EXPECT().GetPublicKey(walletName, pubKey).Times(1).Return(nil, wallet.ErrPubKeyDoesNotExist)
   467  
   468  	// when
   469  	statusCode, _, _ := s.serveHTTP(t, getKeyRequest(t, pubKey, headers))
   470  
   471  	// then
   472  	assert.Equal(t, http.StatusNotFound, statusCode)
   473  }
   474  
   475  func testServiceGetPublicKeyFailMiscError(t *testing.T) {
   476  	s := getTestServiceV1(t, "automatic")
   477  
   478  	// given
   479  	walletName := vgrand.RandomStr(5)
   480  	pubKey := vgrand.RandomStr(5)
   481  	token := vgrand.RandomStr(5)
   482  	headers := authHeadersV1(t, token)
   483  
   484  	// setup
   485  	s.auth.EXPECT().VerifyToken(token).Times(1).Return(walletName, nil)
   486  	s.handler.EXPECT().GetPublicKey(walletName, pubKey).Times(1).Return(nil, assert.AnError)
   487  
   488  	// when
   489  	statusCode, _, _ := s.serveHTTP(t, getKeyRequest(t, pubKey, headers))
   490  
   491  	// then
   492  	assert.Equal(t, http.StatusInternalServerError, statusCode)
   493  }
   494  
   495  func testServiceTaintOK(t *testing.T) {
   496  	s := getTestServiceV1(t, "automatic")
   497  
   498  	// given
   499  	walletName := vgrand.RandomStr(5)
   500  	pubKey := vgrand.RandomStr(5)
   501  	token := vgrand.RandomStr(5)
   502  	passphrase := vgrand.RandomStr(5)
   503  	headers := authHeadersV1(t, token)
   504  	payload := fmt.Sprintf(`{"passphrase": "%s"}`, passphrase)
   505  
   506  	// setup
   507  	s.auth.EXPECT().VerifyToken(token).Times(1).Return(walletName, nil)
   508  	s.handler.EXPECT().TaintKey(walletName, pubKey, passphrase).Times(1).Return(nil)
   509  
   510  	// when
   511  	statusCode, _, _ := s.serveHTTP(t, taintKeyRequest(t, pubKey, payload, headers))
   512  
   513  	// then
   514  	assert.Equal(t, http.StatusOK, statusCode)
   515  }
   516  
   517  func testServiceTaintFailInvalidRequest(t *testing.T) {
   518  	tcs := []struct {
   519  		name    string
   520  		headers map[string]string
   521  		payload string
   522  	}{
   523  		{
   524  			name:    "no header",
   525  			headers: map[string]string{},
   526  			payload: `{"passphrase": "some data"}`,
   527  		}, {
   528  			name:    "no token",
   529  			headers: authHeadersV1(t, ""),
   530  			payload: `{"passphrase": "some data"}`,
   531  		}, {
   532  			name:    "misspelled passphrase property",
   533  			headers: authHeadersV1(t, vgrand.RandomStr(5)),
   534  			payload: `{"passhp": "some data"}`,
   535  		},
   536  	}
   537  
   538  	for _, tc := range tcs {
   539  		t.Run(tc.name, func(tt *testing.T) {
   540  			s := getTestServiceV1(tt, "automatic")
   541  
   542  			// when
   543  			statusCode, _, _ := s.serveHTTP(tt, taintKeyRequest(tt, vgrand.RandomStr(5), tc.payload, tc.headers))
   544  
   545  			// then
   546  			assert.Equal(tt, http.StatusBadRequest, statusCode)
   547  		})
   548  	}
   549  }
   550  
   551  func testServiceUpdateMetaOK(t *testing.T) {
   552  	s := getTestServiceV1(t, "automatic")
   553  
   554  	// when
   555  	walletName := vgrand.RandomStr(5)
   556  	pubKey := vgrand.RandomStr(5)
   557  	token := vgrand.RandomStr(5)
   558  	passphrase := vgrand.RandomStr(5)
   559  	metaRole := vgrand.RandomStr(5)
   560  	headers := authHeadersV1(t, token)
   561  	payload := fmt.Sprintf(`{"passphrase": "%s", "meta": [{"key":"role", "value":"%s"}]}`, passphrase, metaRole)
   562  
   563  	// setup
   564  	s.auth.EXPECT().VerifyToken(token).Times(1).Return(walletName, nil)
   565  	s.handler.EXPECT().UpdateMeta(walletName, pubKey, passphrase, []wallet.Metadata{{
   566  		Key:   "role",
   567  		Value: metaRole,
   568  	}}).Times(1).Return(nil)
   569  
   570  	// when
   571  	statusCode, _, _ := s.serveHTTP(t, annotateKeyRequest(t, pubKey, payload, headers))
   572  
   573  	// then
   574  	assert.Equal(t, http.StatusOK, statusCode)
   575  }
   576  
   577  func testServiceUpdateMetaFailInvalidRequest(t *testing.T) {
   578  	tcs := []struct {
   579  		name    string
   580  		headers map[string]string
   581  		payload string
   582  	}{
   583  		{
   584  			name:    "no header",
   585  			headers: map[string]string{},
   586  			payload: `{"passphrase": "some data", "meta": [{"key": "role", "value": "signing"}]}`,
   587  		}, {
   588  			name:    "no token",
   589  			headers: authHeadersV1(t, ""),
   590  			payload: `{"passphrase": "some data", "meta": [{"key": "role", "value": "signing"}]}`,
   591  		}, {
   592  			name:    "misspelled passphrase property",
   593  			headers: authHeadersV1(t, vgrand.RandomStr(5)),
   594  			payload: `{"pssphrse": "some data", "meta": [{"key": "role", "value": "signing"}]}`,
   595  		},
   596  	}
   597  
   598  	for _, tc := range tcs {
   599  		t.Run(tc.name, func(tt *testing.T) {
   600  			s := getTestServiceV1(tt, "automatic")
   601  
   602  			// when
   603  			statusCode, _, _ := s.serveHTTP(tt, annotateKeyRequest(tt, vgrand.RandomStr(5), tc.payload, tc.headers))
   604  
   605  			// then
   606  			assert.Equal(tt, http.StatusBadRequest, statusCode)
   607  		})
   608  	}
   609  }
   610  
   611  func testCheckTransactionSucceeds(t *testing.T) {
   612  	s := getTestServiceV1(t, "manual")
   613  
   614  	// given
   615  	walletName := vgrand.RandomStr(5)
   616  	token := vgrand.RandomStr(5)
   617  	chainID := vgrand.RandomStr(5)
   618  	headers := authHeadersV1(t, token)
   619  	pubKey := vgrand.RandomStr(5)
   620  	payload := fmt.Sprintf(`{"pubKey": "%s", "orderCancellation": {}}`, pubKey)
   621  	spamStats := &api.GetSpamStatisticsResponse{
   622  		ChainId: chainID,
   623  		Statistics: &api.SpamStatistics{
   624  			Proposals:         &api.SpamStatistic{},
   625  			Transfers:         &api.SpamStatistic{},
   626  			Delegations:       &api.SpamStatistic{},
   627  			NodeAnnouncements: &api.SpamStatistic{},
   628  			IssueSignatures:   &api.SpamStatistic{},
   629  			CreateReferralSet: &api.SpamStatistic{},
   630  			UpdateReferralSet: &api.SpamStatistic{},
   631  			ApplyReferralCode: &api.SpamStatistic{},
   632  			Votes:             &api.VoteSpamStatistics{},
   633  			Pow: &api.PoWStatistic{
   634  				BlockStates: []*api.PoWBlockState{},
   635  			},
   636  		},
   637  	}
   638  
   639  	// setup
   640  	s.auth.EXPECT().VerifyToken(token).Times(1).Return(walletName, nil)
   641  	s.handler.EXPECT().SignTx(gomock.Any(), gomock.Any(), gomock.Any(), chainID).Times(1).Return(&commandspb.Transaction{}, nil)
   642  	s.nodeForward.EXPECT().CheckTx(gomock.Any(), gomock.Any(), gomock.Any()).Times(1).Return(&api.CheckTransactionResponse{
   643  		Success:   true,
   644  		Code:      0,
   645  		GasWanted: 300,
   646  		GasUsed:   200,
   647  	}, nil)
   648  	s.nodeForward.EXPECT().SpamStatistics(gomock.Any(), gomock.Any()).Times(1).Return(spamStats, 0, nil)
   649  	s.spam.EXPECT().GenerateProofOfWork(pubKey, gomock.Any()).Times(1).Return(&commandspb.ProofOfWork{
   650  		Tid:   "",
   651  		Nonce: 10,
   652  	}, nil)
   653  	// when
   654  
   655  	statusCode, _, body := s.serveHTTP(t, checkTxRequest(t, payload, headers))
   656  	assert.Equal(t, http.StatusOK, statusCode)
   657  
   658  	resp := &api.CheckTransactionResponse{}
   659  	if err := json.Unmarshal(body, resp); err != nil {
   660  		t.Fatalf("couldn't unmarshal responde: %v", err)
   661  	}
   662  	assert.True(t, resp.Success)
   663  	assert.Equal(t, uint32(0), resp.Code)
   664  	assert.Equal(t, int64(300), resp.GasWanted)
   665  }
   666  
   667  func testCheckTransactionWithRejectedTransactionSucceeds(t *testing.T) {
   668  	s := getTestServiceV1(t, "manual")
   669  
   670  	// given
   671  	walletName := vgrand.RandomStr(5)
   672  	chainID := vgrand.RandomStr(5)
   673  	token := vgrand.RandomStr(5)
   674  	headers := authHeadersV1(t, token)
   675  	pubKey := vgrand.RandomStr(5)
   676  	payload := fmt.Sprintf(`{"pubKey": "%s", "orderCancellation": {}}`, pubKey)
   677  	spamStats := &api.GetSpamStatisticsResponse{
   678  		ChainId: chainID,
   679  		Statistics: &api.SpamStatistics{
   680  			Proposals:         &api.SpamStatistic{},
   681  			Transfers:         &api.SpamStatistic{},
   682  			Delegations:       &api.SpamStatistic{},
   683  			NodeAnnouncements: &api.SpamStatistic{},
   684  			IssueSignatures:   &api.SpamStatistic{},
   685  			CreateReferralSet: &api.SpamStatistic{},
   686  			UpdateReferralSet: &api.SpamStatistic{},
   687  			ApplyReferralCode: &api.SpamStatistic{},
   688  			Votes:             &api.VoteSpamStatistics{},
   689  			Pow: &api.PoWStatistic{
   690  				BlockStates: []*api.PoWBlockState{},
   691  			},
   692  		},
   693  	}
   694  
   695  	// setup
   696  	s.auth.EXPECT().VerifyToken(token).Times(1).Return(walletName, nil)
   697  	s.handler.EXPECT().SignTx(gomock.Any(), gomock.Any(), gomock.Any(), chainID).Times(1).Return(&commandspb.Transaction{}, nil)
   698  	s.nodeForward.EXPECT().CheckTx(gomock.Any(), gomock.Any(), gomock.Any()).Times(1).Return(&api.CheckTransactionResponse{
   699  		Success: false,
   700  		Code:    4,
   701  	}, nil)
   702  	s.spam.EXPECT().GenerateProofOfWork(pubKey, gomock.Any()).Times(1).Return(&commandspb.ProofOfWork{
   703  		Tid:   "",
   704  		Nonce: 10,
   705  	}, nil)
   706  	s.nodeForward.EXPECT().SpamStatistics(gomock.Any(), pubKey).Times(1).Return(spamStats, 0, nil)
   707  	// when
   708  
   709  	statusCode, _, body := s.serveHTTP(t, checkTxRequest(t, payload, headers))
   710  	assert.Equal(t, http.StatusOK, statusCode)
   711  
   712  	resp := &api.CheckTransactionResponse{}
   713  	if err := json.Unmarshal(body, resp); err != nil {
   714  		t.Fatalf("couldn't unmarshal responde: %v", err)
   715  	}
   716  	assert.False(t, resp.Success)
   717  	assert.Equal(t, uint32(4), resp.Code)
   718  	assert.Equal(t, int64(0), resp.GasWanted)
   719  }
   720  
   721  func testCheckTransactionWithFailedTransactionFails(t *testing.T) {
   722  	s := getTestServiceV1(t, "manual")
   723  
   724  	// given
   725  	walletName := vgrand.RandomStr(5)
   726  	token := vgrand.RandomStr(5)
   727  	chainID := vgrand.RandomStr(5)
   728  	headers := authHeadersV1(t, token)
   729  	pubKey := vgrand.RandomStr(5)
   730  	payload := fmt.Sprintf(`{"pubKey": "%s", "orderCancellation": {}}`, pubKey)
   731  	spamStats := &api.GetSpamStatisticsResponse{
   732  		ChainId: chainID,
   733  		Statistics: &api.SpamStatistics{
   734  			Proposals:         &api.SpamStatistic{},
   735  			Transfers:         &api.SpamStatistic{},
   736  			Delegations:       &api.SpamStatistic{},
   737  			NodeAnnouncements: &api.SpamStatistic{},
   738  			IssueSignatures:   &api.SpamStatistic{},
   739  			CreateReferralSet: &api.SpamStatistic{},
   740  			UpdateReferralSet: &api.SpamStatistic{},
   741  			ApplyReferralCode: &api.SpamStatistic{},
   742  			Votes:             &api.VoteSpamStatistics{},
   743  			Pow: &api.PoWStatistic{
   744  				BlockStates: []*api.PoWBlockState{},
   745  			},
   746  		},
   747  	}
   748  
   749  	// setup
   750  	s.auth.EXPECT().VerifyToken(token).Times(1).Return(walletName, nil)
   751  	s.handler.EXPECT().SignTx(gomock.Any(), gomock.Any(), gomock.Any(), chainID).Times(1).Return(&commandspb.Transaction{}, nil)
   752  	s.nodeForward.EXPECT().CheckTx(gomock.Any(), gomock.Any(), gomock.Any()).Times(1).Return(nil, assert.AnError)
   753  	s.spam.EXPECT().GenerateProofOfWork(pubKey, gomock.Any()).Times(1).Return(&commandspb.ProofOfWork{
   754  		Tid:   "",
   755  		Nonce: 10,
   756  	}, nil)
   757  	s.nodeForward.EXPECT().SpamStatistics(gomock.Any(), pubKey).Times(1).Return(spamStats, 0, nil)
   758  
   759  	// when
   760  	statusCode, _, _ := s.serveHTTP(t, checkTxRequest(t, payload, headers))
   761  
   762  	// then
   763  	assert.Equal(t, http.StatusInternalServerError, statusCode)
   764  }
   765  
   766  func testAcceptSigningTransactionSucceeds(t *testing.T) {
   767  	s := getTestServiceV1(t, "automatic")
   768  
   769  	// given
   770  	walletName := vgrand.RandomStr(5)
   771  	token := vgrand.RandomStr(5)
   772  	chainID := vgrand.RandomStr(5)
   773  	headers := authHeadersV1(t, token)
   774  	pubKey := vgrand.RandomStr(5)
   775  	payload := fmt.Sprintf(`{"pubKey": "%s", "orderCancellation": {}}`, pubKey)
   776  	spamStats := &api.GetSpamStatisticsResponse{
   777  		ChainId: chainID,
   778  		Statistics: &api.SpamStatistics{
   779  			Proposals:         &api.SpamStatistic{},
   780  			Transfers:         &api.SpamStatistic{},
   781  			Delegations:       &api.SpamStatistic{},
   782  			NodeAnnouncements: &api.SpamStatistic{},
   783  			IssueSignatures:   &api.SpamStatistic{},
   784  			CreateReferralSet: &api.SpamStatistic{},
   785  			UpdateReferralSet: &api.SpamStatistic{},
   786  			ApplyReferralCode: &api.SpamStatistic{},
   787  			Votes:             &api.VoteSpamStatistics{},
   788  			Pow: &api.PoWStatistic{
   789  				BlockStates: []*api.PoWBlockState{},
   790  			},
   791  		},
   792  	}
   793  
   794  	// setup
   795  	s.auth.EXPECT().VerifyToken(token).Times(1).Return(walletName, nil)
   796  	s.handler.EXPECT().SignTx(gomock.Any(), gomock.Any(), gomock.Any(), chainID).Times(1).Return(&commandspb.Transaction{}, nil)
   797  	s.nodeForward.EXPECT().SendTx(gomock.Any(), gomock.Any(), api.SubmitTransactionRequest_TYPE_ASYNC, gomock.Any()).Times(1).
   798  		Return(&api.SubmitTransactionResponse{Success: true}, nil)
   799  	s.spam.EXPECT().GenerateProofOfWork(pubKey, gomock.Any()).Times(1).Return(&commandspb.ProofOfWork{
   800  		Tid:   "",
   801  		Nonce: 10,
   802  	}, nil)
   803  	s.nodeForward.EXPECT().SpamStatistics(gomock.Any(), pubKey).Times(1).Return(spamStats, 0, nil)
   804  	// when
   805  
   806  	statusCode, _, _ := s.serveHTTP(t, signTxRequest(t, payload, headers))
   807  	assert.Equal(t, http.StatusOK, statusCode)
   808  }
   809  
   810  func testDeclineSigningTransactionManuallySucceeds(t *testing.T) {
   811  	s := getTestServiceV1(t, "manual")
   812  
   813  	// given
   814  	token := vgrand.RandomStr(5)
   815  	walletName := vgrand.RandomStr(5)
   816  	headers := authHeadersV1(t, token)
   817  	pubKey := "toBeDeclined"
   818  	payload := fmt.Sprintf(`{"propagate": true, "pubKey": "%s", "orderCancellation": {}}`, pubKey)
   819  
   820  	// setup
   821  	s.auth.EXPECT().VerifyToken(token).Times(1).Return(walletName, nil)
   822  
   823  	ctx, cancelFn := context.WithCancel(context.Background())
   824  	defer cancelFn()
   825  
   826  	go func() {
   827  		for {
   828  			select {
   829  			case <-ctx.Done():
   830  				return
   831  			case req := <-s.consentRequestsCh:
   832  				req.Confirmation <- v1.ConsentConfirmation{
   833  					TxID:     req.TxID,
   834  					Decision: false,
   835  				}
   836  				return
   837  			}
   838  		}
   839  	}()
   840  
   841  	// when
   842  	statusCode, _, _ := s.serveHTTP(t, signTxRequest(t, payload, headers))
   843  	assert.Equal(t, http.StatusUnauthorized, statusCode)
   844  }
   845  
   846  func testFailedTransactionSigningFails(t *testing.T) {
   847  	s := getTestServiceV1(t, "automatic")
   848  
   849  	// given
   850  	walletName := vgrand.RandomStr(5)
   851  	token := vgrand.RandomStr(5)
   852  	chainID := vgrand.RandomStr(5)
   853  	headers := authHeadersV1(t, token)
   854  	pubKey := vgrand.RandomStr(5)
   855  	payload := fmt.Sprintf(`{"propagate": true, "pubKey": "%s", "orderCancellation": {}}`, pubKey)
   856  	spamStats := &api.GetSpamStatisticsResponse{
   857  		ChainId: chainID,
   858  		Statistics: &api.SpamStatistics{
   859  			Proposals:         &api.SpamStatistic{},
   860  			Transfers:         &api.SpamStatistic{},
   861  			Delegations:       &api.SpamStatistic{},
   862  			NodeAnnouncements: &api.SpamStatistic{},
   863  			IssueSignatures:   &api.SpamStatistic{},
   864  			CreateReferralSet: &api.SpamStatistic{},
   865  			UpdateReferralSet: &api.SpamStatistic{},
   866  			ApplyReferralCode: &api.SpamStatistic{},
   867  			Votes:             &api.VoteSpamStatistics{},
   868  			Pow: &api.PoWStatistic{
   869  				BlockStates: []*api.PoWBlockState{},
   870  			},
   871  		},
   872  	}
   873  
   874  	// setup
   875  	s.auth.EXPECT().VerifyToken(token).Times(1).Return(walletName, nil)
   876  	s.handler.EXPECT().SignTx(walletName, gomock.Any(), gomock.Any(), chainID).Times(1).Return(nil, assert.AnError)
   877  	s.nodeForward.EXPECT().SpamStatistics(gomock.Any(), pubKey).Times(1).Return(spamStats, 0, nil)
   878  
   879  	// when
   880  	statusCode, _, _ := s.serveHTTP(t, signTxRequest(t, payload, headers))
   881  
   882  	// then
   883  	assert.Equal(t, http.StatusInternalServerError, statusCode)
   884  }
   885  
   886  func testSigningTransactionWithInvalidRequestFails(t *testing.T) {
   887  	token := vgrand.RandomStr(5)
   888  
   889  	tcs := []struct {
   890  		name    string
   891  		headers map[string]string
   892  		payload string
   893  	}{
   894  		{
   895  			name:    "no header",
   896  			headers: map[string]string{},
   897  			payload: `{"propagate": true, "pubKey": "0xCAFEDUDE", "orderCancellation": {}}`,
   898  		}, {
   899  			name:    "no token",
   900  			headers: authHeadersV1(t, ""),
   901  			payload: `{"propagate": true, "pubKey": "0xCAFEDUDE", "orderCancellation": {}}`,
   902  		}, {
   903  			name:    "misspelled pubKey property",
   904  			headers: authHeadersV1(t, token),
   905  			payload: `{"propagate": true, "puey": "0xCAFEDUDE", "orderCancellation": {}}`,
   906  		}, {
   907  			name:    "without command",
   908  			headers: authHeadersV1(t, token),
   909  			payload: `{"propagate": true, "pubKey": "0xCAFEDUDE", "robMoney": {}}`,
   910  		}, {
   911  			name:    "with unknown command",
   912  			headers: authHeadersV1(t, token),
   913  			payload: `{"propagate": true, "pubKey": "0xCAFEDUDE"}`,
   914  		},
   915  	}
   916  
   917  	for _, tc := range tcs {
   918  		t.Run(tc.name, func(tt *testing.T) {
   919  			s := getTestServiceV1(tt, "automatic")
   920  			if tc.name != "no header" && tc.name != "no token" {
   921  				s.auth.EXPECT().VerifyToken(token).Times(1)
   922  			}
   923  			// when
   924  			statusCode, _, _ := s.serveHTTP(tt, signTxRequest(tt, tc.payload, tc.headers))
   925  			// then
   926  			assert.Equal(tt, http.StatusBadRequest, statusCode)
   927  			tc.headers["Origin"] = "Contains 世界"
   928  			// when
   929  			statusCode, _, _ = s.serveHTTP(tt, signTxRequest(tt, tc.payload, tc.headers))
   930  			// then
   931  			assert.Equal(tt, http.StatusBadRequest, statusCode)
   932  		})
   933  	}
   934  }
   935  
   936  func testAcceptSigningTransactionFailsSpam(t *testing.T) {
   937  	s := getTestServiceV1(t, "automatic")
   938  
   939  	// given
   940  	walletName := vgrand.RandomStr(5)
   941  	token := vgrand.RandomStr(5)
   942  	chainID := vgrand.RandomStr(5)
   943  	headers := authHeadersV1(t, token)
   944  	pubKey := vgrand.RandomStr(5)
   945  	payload := fmt.Sprintf(`{"pubKey": "%s", "orderCancellation": {}}`, pubKey)
   946  	spamStats := &api.GetSpamStatisticsResponse{
   947  		ChainId: chainID,
   948  		Statistics: &api.SpamStatistics{
   949  			Proposals:         &api.SpamStatistic{},
   950  			Transfers:         &api.SpamStatistic{},
   951  			Delegations:       &api.SpamStatistic{},
   952  			NodeAnnouncements: &api.SpamStatistic{},
   953  			IssueSignatures:   &api.SpamStatistic{},
   954  			CreateReferralSet: &api.SpamStatistic{},
   955  			UpdateReferralSet: &api.SpamStatistic{},
   956  			ApplyReferralCode: &api.SpamStatistic{},
   957  			Votes:             &api.VoteSpamStatistics{},
   958  			Pow: &api.PoWStatistic{
   959  				BlockStates: []*api.PoWBlockState{},
   960  			},
   961  		},
   962  	}
   963  	// setup
   964  	s.auth.EXPECT().VerifyToken(token).AnyTimes().Return(walletName, nil)
   965  	s.handler.EXPECT().SignTx(gomock.Any(), gomock.Any(), gomock.Any(), chainID).AnyTimes().Return(&commandspb.Transaction{}, nil)
   966  	s.spam.EXPECT().GenerateProofOfWork(pubKey, gomock.Any()).Times(1).Return(&commandspb.ProofOfWork{
   967  		Tid:   "",
   968  		Nonce: 10,
   969  	}, nil)
   970  	s.nodeForward.EXPECT().SpamStatistics(gomock.Any(), pubKey).Times(1).Return(spamStats, 0, nil)
   971  	// when
   972  
   973  	s.nodeForward.EXPECT().SendTx(gomock.Any(), gomock.Any(), api.SubmitTransactionRequest_TYPE_ASYNC, gomock.Any()).Times(1).
   974  		Return(&api.SubmitTransactionResponse{Success: false, Code: 89}, nil)
   975  
   976  	statusCode, _, _ := s.serveHTTP(t, signTxRequest(t, payload, headers))
   977  	assert.Equal(t, http.StatusTooManyRequests, statusCode)
   978  }
   979  
   980  func testSigningAnythingSucceeds(t *testing.T) {
   981  	s := getTestServiceV1(t, "automatic")
   982  
   983  	// given
   984  	walletName := vgrand.RandomStr(5)
   985  	pubKey := vgrand.RandomStr(5)
   986  	token := vgrand.RandomStr(5)
   987  	headers := authHeadersV1(t, token)
   988  	payload := fmt.Sprintf(`{"inputData": "c3BpY2Ugb2YgZHVuZQ==", "pubKey": "%s"}`, pubKey)
   989  
   990  	// setup
   991  	s.auth.EXPECT().VerifyToken(token).Times(1).Return(walletName, nil)
   992  	s.handler.EXPECT().SignAny(walletName, []byte("spice of dune"), pubKey).Times(1).Return([]byte("some sig"), nil)
   993  
   994  	// when
   995  	statusCode, _, _ := s.serveHTTP(t, signAnyRequest(t, payload, headers))
   996  
   997  	// then
   998  	assert.Equal(t, http.StatusOK, statusCode)
   999  }
  1000  
  1001  func testSigningAnyDataWithInvalidRequestFails(t *testing.T) {
  1002  	tcs := []struct {
  1003  		name    string
  1004  		headers map[string]string
  1005  		payload string
  1006  	}{
  1007  		{
  1008  			name:    "no header",
  1009  			headers: map[string]string{},
  1010  			payload: `{"inputData": "c3BpY2Ugb2YgZHVuZQ==", "pubKey": "asdasasdasd"}`,
  1011  		}, {
  1012  			name:    "no token",
  1013  			headers: authHeadersV1(t, ""),
  1014  			payload: `{"inputData": "c3BpY2Ugb2YgZHVuZQ==", "pubKey": "asdasasdasd"}`,
  1015  		}, {
  1016  			name:    "misspelled pubKey property",
  1017  			headers: authHeadersV1(t, vgrand.RandomStr(5)),
  1018  			payload: `{"inputData": "c3BpY2Ugb2YgZHVuZQ==", "puey": "asdasasdasd"}`,
  1019  		}, {
  1020  			name:    "misspelled inputData property",
  1021  			headers: authHeadersV1(t, vgrand.RandomStr(5)),
  1022  			payload: `{"data": "c3BpY2Ugb2YgZHVuZQ==", "pubKey": "asdasasdasd"}`,
  1023  		},
  1024  	}
  1025  
  1026  	for _, tc := range tcs {
  1027  		t.Run(tc.name, func(tt *testing.T) {
  1028  			s := getTestServiceV1(tt, "automatic")
  1029  
  1030  			// when
  1031  			statusCode, _, _ := s.serveHTTP(tt, signAnyRequest(tt, tc.payload, tc.headers))
  1032  
  1033  			// then
  1034  			assert.Equal(tt, http.StatusBadRequest, statusCode)
  1035  		})
  1036  	}
  1037  }
  1038  
  1039  func testVerifyingAnythingSucceeds(t *testing.T) {
  1040  	s := getTestServiceV1(t, "automatic")
  1041  
  1042  	// given
  1043  	pubKey := vgrand.RandomStr(5)
  1044  	payload := fmt.Sprintf(`{"inputData": "c3BpY2Ugb2YgZHVuZQ==", "pubKey": "%s", "signature": "U2lldGNoIFRhYnI="}`, pubKey)
  1045  
  1046  	// setup
  1047  	s.handler.EXPECT().VerifyAny([]byte("spice of dune"), []byte("Sietch Tabr"), pubKey).Times(1).Return(true, nil)
  1048  
  1049  	// when
  1050  	statusCode, _, body := s.serveHTTP(t, verifyAnyRequest(t, payload))
  1051  
  1052  	// then
  1053  	assert.Equal(t, http.StatusOK, statusCode)
  1054  
  1055  	resp := &v1.VerifyAnyResponse{}
  1056  	if err := json.Unmarshal(body, resp); err != nil {
  1057  		t.Fatalf("couldn't unmarshal responde: %v", err)
  1058  	}
  1059  	assert.True(t, resp.Valid)
  1060  }
  1061  
  1062  func testVerifyingAnythingFails(t *testing.T) {
  1063  	s := getTestServiceV1(t, "automatic")
  1064  
  1065  	// given
  1066  	pubKey := vgrand.RandomStr(5)
  1067  	payload := fmt.Sprintf(`{"inputData": "c3BpY2Ugb2YgZHVuZQ==", "pubKey": "%s", "signature": "U2lldGNoIFRhYnI="}`, pubKey)
  1068  
  1069  	// setup
  1070  	s.handler.EXPECT().VerifyAny([]byte("spice of dune"), []byte("Sietch Tabr"), pubKey).Times(1).Return(false, nil)
  1071  
  1072  	// when
  1073  	statusCode, _, body := s.serveHTTP(t, verifyAnyRequest(t, payload))
  1074  
  1075  	// then
  1076  	assert.Equal(t, http.StatusOK, statusCode)
  1077  
  1078  	resp := &v1.VerifyAnyResponse{}
  1079  	if err := json.Unmarshal(body, resp); err != nil {
  1080  		t.Fatalf("couldn't unmarshal responde: %v", err)
  1081  	}
  1082  	assert.False(t, resp.Valid)
  1083  }
  1084  
  1085  func testVerifyingAnyDataWithInvalidRequestFails(t *testing.T) {
  1086  	tcs := []struct {
  1087  		name    string
  1088  		payload string
  1089  	}{
  1090  		{
  1091  			name:    "misspelled pubKey property",
  1092  			payload: `{"inputData": "c3BpY2Ugb2YgZHVuZQ==", "puey": "asdasasdasd", "signature": "U2lldGNoIFRhYnI="}`,
  1093  		}, {
  1094  			name:    "misspelled inputData property",
  1095  			payload: `{"data": "c3BpY2Ugb2YgZHVuZQ==", "pubKey": "asdasasdasd", "signature": "U2lldGNoIFRhYnI="}`,
  1096  		}, {
  1097  			name:    "misspelled signature property",
  1098  			payload: `{"inputData": "c3BpY2Ugb2YgZHVuZQ==", "pubKey": "asdasasdasd", "sign": "U2lldGNoIFRhYnI="}`,
  1099  		},
  1100  	}
  1101  
  1102  	for _, tc := range tcs {
  1103  		t.Run(tc.name, func(tt *testing.T) {
  1104  			s := getTestServiceV1(tt, "automatic")
  1105  
  1106  			// when
  1107  			statusCode, _, _ := s.serveHTTP(tt, verifyAnyRequest(tt, tc.payload))
  1108  
  1109  			// then
  1110  			assert.Equal(tt, http.StatusBadRequest, statusCode)
  1111  		})
  1112  	}
  1113  }
  1114  
  1115  func testGetNetworkChainIDSuccess(t *testing.T) {
  1116  	s := getTestServiceV1(t, "manual")
  1117  
  1118  	// setup
  1119  	expectedChainID := "some-chain-id"
  1120  	s.nodeForward.EXPECT().LastBlockHeightAndHash(gomock.Any()).AnyTimes().Return(&api.LastBlockHeightResponse{
  1121  		ChainId: expectedChainID,
  1122  	}, 0, nil)
  1123  
  1124  	// when
  1125  	statusCode, _, body := s.serveHTTP(t, chainIDRequest(t))
  1126  	assert.Equal(t, http.StatusOK, statusCode)
  1127  
  1128  	resp := struct {
  1129  		ChainID string `json:"chainID"`
  1130  	}{}
  1131  	if err := json.Unmarshal(body, &resp); err != nil {
  1132  		t.Fatalf("couldn't unmarshal responde: %v", err)
  1133  	}
  1134  	assert.Equal(t, resp.ChainID, expectedChainID)
  1135  }
  1136  
  1137  func testGetNetworkChainIDFailure(t *testing.T) {
  1138  	s := getTestServiceV1(t, "manual")
  1139  
  1140  	// setup
  1141  	s.nodeForward.EXPECT().LastBlockHeightAndHash(gomock.Any()).AnyTimes().Return(nil, 0, assert.AnError)
  1142  
  1143  	// when
  1144  	statusCode, _, _ := s.serveHTTP(t, chainIDRequest(t))
  1145  	assert.Equal(t, http.StatusFailedDependency, statusCode)
  1146  }
  1147  
  1148  func TestEmptyChainIDFromNetworkFails(t *testing.T) {
  1149  	s := getTestServiceV1(t, "manual")
  1150  
  1151  	// given
  1152  	walletName := vgrand.RandomStr(5)
  1153  	token := vgrand.RandomStr(5)
  1154  	headers := authHeadersV1(t, token)
  1155  	pubKey := vgrand.RandomStr(5)
  1156  	payload := fmt.Sprintf(`{"pubKey": "%s", "orderCancellation": {}}`, pubKey)
  1157  	spamStats := &api.GetSpamStatisticsResponse{
  1158  		Statistics: &api.SpamStatistics{
  1159  			Proposals:         &api.SpamStatistic{},
  1160  			Transfers:         &api.SpamStatistic{},
  1161  			Delegations:       &api.SpamStatistic{},
  1162  			NodeAnnouncements: &api.SpamStatistic{},
  1163  			IssueSignatures:   &api.SpamStatistic{},
  1164  			CreateReferralSet: &api.SpamStatistic{},
  1165  			UpdateReferralSet: &api.SpamStatistic{},
  1166  			ApplyReferralCode: &api.SpamStatistic{},
  1167  			Votes:             &api.VoteSpamStatistics{},
  1168  			Pow: &api.PoWStatistic{
  1169  				BlockStates: []*api.PoWBlockState{},
  1170  			},
  1171  		},
  1172  	}
  1173  	// setup
  1174  	s.auth.EXPECT().VerifyToken(token).Times(1).Return(walletName, nil)
  1175  	s.nodeForward.EXPECT().SpamStatistics(gomock.Any(), gomock.Any()).Times(1).Return(spamStats, 0, nil)
  1176  	// when
  1177  
  1178  	statusCode, _, _ := s.serveHTTP(t, checkTxRequest(t, payload, headers))
  1179  	assert.Equal(t, http.StatusInternalServerError, statusCode)
  1180  }
  1181  
  1182  func loginRequest(t *testing.T, payload string) *http.Request {
  1183  	t.Helper()
  1184  	return buildRequest(t, http.MethodPost, "/api/v1/auth/token", payload, nil)
  1185  }
  1186  
  1187  func logoutRequest(t *testing.T, headers map[string]string) *http.Request {
  1188  	t.Helper()
  1189  	return buildRequest(t, http.MethodDelete, "/api/v1/auth/token", "", headers)
  1190  }
  1191  
  1192  func createWalletRequest(t *testing.T, payload string) *http.Request {
  1193  	t.Helper()
  1194  	return buildRequest(t, http.MethodPost, "/api/v1/wallets", payload, nil)
  1195  }
  1196  
  1197  func importWalletRequest(t *testing.T, payload string) *http.Request {
  1198  	t.Helper()
  1199  	return buildRequest(t, http.MethodPost, "/api/v1/wallets/import", payload, nil)
  1200  }
  1201  
  1202  func generateKeyRequest(t *testing.T, payload string, headers map[string]string) *http.Request {
  1203  	t.Helper()
  1204  	return buildRequest(t, http.MethodPost, "/api/v1/keys", payload, headers)
  1205  }
  1206  
  1207  func listKeysRequest(t *testing.T, headers map[string]string) *http.Request {
  1208  	t.Helper()
  1209  	return buildRequest(t, http.MethodGet, "/api/v1/keys", "", headers)
  1210  }
  1211  
  1212  func getKeyRequest(t *testing.T, keyID string, headers map[string]string) *http.Request {
  1213  	t.Helper()
  1214  	return buildRequest(t, http.MethodGet, fmt.Sprintf("/api/v1/keys/%s", keyID), "", headers)
  1215  }
  1216  
  1217  func taintKeyRequest(t *testing.T, id, payload string, headers map[string]string) *http.Request {
  1218  	t.Helper()
  1219  	return buildRequest(t, http.MethodPut, fmt.Sprintf("/api/v1/keys/%s/taint", id), payload, headers)
  1220  }
  1221  
  1222  func annotateKeyRequest(t *testing.T, id, payload string, headers map[string]string) *http.Request {
  1223  	t.Helper()
  1224  	return buildRequest(t, http.MethodPut, fmt.Sprintf("/api/v1/keys/%s/metadata", id), payload, headers)
  1225  }
  1226  
  1227  func checkTxRequest(t *testing.T, payload string, headers map[string]string) *http.Request {
  1228  	t.Helper()
  1229  	return buildRequest(t, http.MethodPost, "/api/v1/command/check", payload, headers)
  1230  }
  1231  
  1232  func signTxRequest(t *testing.T, payload string, headers map[string]string) *http.Request {
  1233  	t.Helper()
  1234  	return buildRequest(t, http.MethodPost, "/api/v1/command", payload, headers)
  1235  }
  1236  
  1237  func signAnyRequest(t *testing.T, payload string, headers map[string]string) *http.Request {
  1238  	t.Helper()
  1239  	return buildRequest(t, http.MethodPost, "/api/v1/sign", payload, headers)
  1240  }
  1241  
  1242  func verifyAnyRequest(t *testing.T, payload string) *http.Request {
  1243  	t.Helper()
  1244  	return buildRequest(t, http.MethodPost, "/api/v1/verify", payload, nil)
  1245  }
  1246  
  1247  func chainIDRequest(t *testing.T) *http.Request {
  1248  	t.Helper()
  1249  	return buildRequest(t, http.MethodGet, "/api/v1/network/chainid", "", map[string]string{})
  1250  }
  1251  
  1252  func authHeadersV1(t *testing.T, token string) map[string]string {
  1253  	t.Helper()
  1254  	return map[string]string{
  1255  		"Authorization": fmt.Sprintf("Bearer %s", token),
  1256  	}
  1257  }