github.com/baptiste-b-pegasys/quorum/v22@v22.4.2/accounts/pluggable/wallet_test.go (about)

     1  package pluggable
     2  
     3  import (
     4  	"math/big"
     5  	"math/rand"
     6  	"testing"
     7  
     8  	"github.com/ethereum/go-ethereum/accounts"
     9  	"github.com/ethereum/go-ethereum/accounts/pluggable/internal/testutils/mock_plugin"
    10  	"github.com/ethereum/go-ethereum/common"
    11  	"github.com/ethereum/go-ethereum/core/types"
    12  	"github.com/ethereum/go-ethereum/crypto"
    13  	"github.com/golang/mock/gomock"
    14  	"github.com/stretchr/testify/assert"
    15  	"github.com/stretchr/testify/require"
    16  )
    17  
    18  var (
    19  	scheme = "scheme"
    20  
    21  	wltUrl = accounts.URL{
    22  		Scheme: scheme,
    23  		Path:   "uripath",
    24  	}
    25  
    26  	acct1 = accounts.Account{
    27  		Address: common.HexToAddress("0x4d6d744b6da435b5bbdde2526dc20e9a41cb72e5"),
    28  		URL:     wltUrl,
    29  	}
    30  
    31  	acct2 = accounts.Account{
    32  		Address: common.HexToAddress("0x2332f90a329c2c55ba120b1449d36a144d1f9fe4"),
    33  		URL:     accounts.URL{Scheme: scheme, Path: "path/to/file2.json"},
    34  	}
    35  	acct3 = accounts.Account{
    36  		Address: common.HexToAddress("0x992d7a8fca612c963796ecbfe78b300370b9545a"),
    37  		URL:     accounts.URL{Scheme: scheme, Path: "path/to/file3.json"},
    38  	}
    39  	acct4 = accounts.Account{
    40  		Address: common.HexToAddress("0x39ac8f3ae3681b4422fdf808ae18ba4365e37da8"),
    41  		URL:     accounts.URL{Scheme: scheme, Path: "path/to/file4.json"},
    42  	}
    43  )
    44  
    45  func validWallet(m *mock_plugin.MockService) *wallet {
    46  	return &wallet{
    47  		url:           wltUrl,
    48  		pluginService: m,
    49  	}
    50  }
    51  
    52  func TestWallet_Url(t *testing.T) {
    53  	w := validWallet(nil)
    54  	got := w.URL()
    55  	assert.Equal(t, wltUrl, got)
    56  }
    57  
    58  func TestWallet_Status(t *testing.T) {
    59  	ctrl := gomock.NewController(t)
    60  	defer ctrl.Finish()
    61  
    62  	want := "status"
    63  
    64  	mockClient := mock_plugin.NewMockService(ctrl)
    65  	mockClient.
    66  		EXPECT().
    67  		Status(gomock.Any()).
    68  		Return(want, nil)
    69  
    70  	w := validWallet(mockClient)
    71  	status, err := w.Status()
    72  
    73  	assert.NoError(t, err)
    74  	assert.Equal(t, want, status)
    75  }
    76  
    77  func TestWallet_Open(t *testing.T) {
    78  	ctrl := gomock.NewController(t)
    79  	defer ctrl.Finish()
    80  
    81  	mockClient := mock_plugin.NewMockService(ctrl)
    82  	mockClient.
    83  		EXPECT().
    84  		Open(gomock.Any(), "pwd").
    85  		Return(nil)
    86  
    87  	w := validWallet(mockClient)
    88  	err := w.Open("pwd")
    89  
    90  	assert.NoError(t, err)
    91  }
    92  
    93  func TestWallet_Close(t *testing.T) {
    94  	ctrl := gomock.NewController(t)
    95  	defer ctrl.Finish()
    96  
    97  	mockClient := mock_plugin.NewMockService(ctrl)
    98  	mockClient.
    99  		EXPECT().
   100  		Close(gomock.Any()).
   101  		Return(nil)
   102  
   103  	w := validWallet(mockClient)
   104  	err := w.Close()
   105  
   106  	assert.NoError(t, err)
   107  }
   108  
   109  func TestWallet_Accounts(t *testing.T) {
   110  	ctrl := gomock.NewController(t)
   111  	defer ctrl.Finish()
   112  
   113  	want := []accounts.Account{acct1, acct2, acct3, acct4}
   114  
   115  	mockClient := mock_plugin.NewMockService(ctrl)
   116  	mockClient.
   117  		EXPECT().
   118  		Accounts(gomock.Any()).
   119  		Return(want)
   120  
   121  	w := validWallet(mockClient)
   122  	got := w.Accounts()
   123  
   124  	assert.Equal(t, want, got)
   125  }
   126  
   127  func TestWallet_Contains(t *testing.T) {
   128  	ctrl := gomock.NewController(t)
   129  	defer ctrl.Finish()
   130  
   131  	mockClient := mock_plugin.NewMockService(ctrl)
   132  	mockClient.
   133  		EXPECT().
   134  		Contains(gomock.Any(), acct1).
   135  		Return(true)
   136  
   137  	w := validWallet(mockClient)
   138  	got := w.Contains(acct1)
   139  
   140  	assert.True(t, got)
   141  }
   142  
   143  func TestWallet_Derive(t *testing.T) {
   144  	w := validWallet(nil)
   145  	_, err := w.Derive(accounts.DerivationPath{}, true)
   146  	if assert.Error(t, err) {
   147  		assert.Equal(t, accounts.ErrNotSupported, err)
   148  	}
   149  }
   150  
   151  func TestWallet_SelfDerive(t *testing.T) {
   152  	w := validWallet(nil)
   153  	// does nothing
   154  	w.SelfDerive([]accounts.DerivationPath{}, nil)
   155  }
   156  
   157  func TestWallet_SignData(t *testing.T) {
   158  	ctrl := gomock.NewController(t)
   159  	defer ctrl.Finish()
   160  
   161  	toSign := []byte("somedata")
   162  	want := []byte("signeddata")
   163  
   164  	mockClient := mock_plugin.NewMockService(ctrl)
   165  	mockClient.
   166  		EXPECT().
   167  		Sign(gomock.Any(), acct1, crypto.Keccak256(toSign)).
   168  		Return(want, nil)
   169  
   170  	w := validWallet(mockClient)
   171  	got, err := w.SignData(acct1, "", toSign)
   172  
   173  	assert.NoError(t, err)
   174  	assert.Equal(t, want, got)
   175  }
   176  
   177  func TestWallet_SignDataWithPassphrase(t *testing.T) {
   178  	ctrl := gomock.NewController(t)
   179  	defer ctrl.Finish()
   180  
   181  	toSign := []byte("somedata")
   182  	want := []byte("signeddata")
   183  
   184  	mockClient := mock_plugin.NewMockService(ctrl)
   185  	mockClient.
   186  		EXPECT().
   187  		UnlockAndSign(gomock.Any(), acct1, crypto.Keccak256(toSign), "pwd").
   188  		Return(want, nil)
   189  
   190  	w := validWallet(mockClient)
   191  	got, err := w.SignDataWithPassphrase(acct1, "pwd", "", toSign)
   192  
   193  	assert.NoError(t, err)
   194  	assert.Equal(t, want, got)
   195  }
   196  
   197  func TestWallet_SignText(t *testing.T) {
   198  	ctrl := gomock.NewController(t)
   199  	defer ctrl.Finish()
   200  
   201  	toSign := []byte("somedata")
   202  	want := []byte("signeddata")
   203  
   204  	mockClient := mock_plugin.NewMockService(ctrl)
   205  	mockClient.
   206  		EXPECT().
   207  		Sign(gomock.Any(), acct1, accounts.TextHash(toSign)).
   208  		Return(want, nil)
   209  
   210  	w := validWallet(mockClient)
   211  	got, err := w.SignText(acct1, toSign)
   212  
   213  	assert.NoError(t, err)
   214  	assert.Equal(t, want, got)
   215  }
   216  
   217  func TestWallet_SignTextWithPassphrase(t *testing.T) {
   218  	ctrl := gomock.NewController(t)
   219  	defer ctrl.Finish()
   220  
   221  	toSign := []byte("somedata")
   222  	want := []byte("signeddata")
   223  
   224  	mockClient := mock_plugin.NewMockService(ctrl)
   225  	mockClient.
   226  		EXPECT().
   227  		UnlockAndSign(gomock.Any(), acct1, accounts.TextHash(toSign), "pwd").
   228  		Return(want, nil)
   229  
   230  	w := validWallet(mockClient)
   231  	got, err := w.SignTextWithPassphrase(acct1, "pwd", toSign)
   232  
   233  	assert.NoError(t, err)
   234  	assert.Equal(t, want, got)
   235  }
   236  
   237  func TestWallet_SignTx(t *testing.T) {
   238  	ctrl := gomock.NewController(t)
   239  	defer ctrl.Finish()
   240  
   241  	tests := []struct {
   242  		name      string
   243  		isPrivate bool
   244  		chainID   *big.Int
   245  		signer    types.Signer
   246  	}{
   247  		{
   248  			name:      "Public EIP155 tx",
   249  			isPrivate: false,
   250  			chainID:   big.NewInt(20),
   251  			signer:    types.NewEIP155Signer(big.NewInt(20)),
   252  		},
   253  		{
   254  			name:      "Public Homestead tx",
   255  			isPrivate: false,
   256  			chainID:   nil,
   257  			signer:    types.HomesteadSigner{},
   258  		},
   259  		{
   260  			name:      "Private tx",
   261  			isPrivate: true,
   262  			chainID:   nil,
   263  			signer:    types.QuorumPrivateTxSigner{},
   264  		},
   265  	}
   266  
   267  	toSign := types.NewTransaction(
   268  		1,
   269  		common.HexToAddress("0x2332f90a329c2c55ba120b1449d36a144d1f9fe4"),
   270  		big.NewInt(1),
   271  		0,
   272  		big.NewInt(1),
   273  		nil,
   274  	)
   275  
   276  	for _, tt := range tests {
   277  		t.Run(tt.name, func(t *testing.T) {
   278  			if tt.isPrivate {
   279  				toSign.SetPrivate()
   280  			}
   281  
   282  			hashToSign := tt.signer.Hash(toSign)
   283  
   284  			mockSig := make([]byte, 65)
   285  			rand.Read(mockSig)
   286  
   287  			mockClient := mock_plugin.NewMockService(ctrl)
   288  			mockClient.
   289  				EXPECT().
   290  				Sign(gomock.Any(), acct1, hashToSign.Bytes()).
   291  				Return(mockSig, nil)
   292  
   293  			w := validWallet(mockClient)
   294  			got, err := w.SignTx(acct1, toSign, tt.chainID)
   295  			require.NoError(t, err)
   296  
   297  			gotV, gotR, gotS := got.RawSignatureValues()
   298  
   299  			wantR, wantS, wantV, err := tt.signer.SignatureValues(types.NewTransaction(
   300  				0,
   301  				common.Address{},
   302  				nil,
   303  				0,
   304  				nil,
   305  				nil,
   306  			), mockSig) // tx param is unused by method
   307  			require.NoError(t, err)
   308  
   309  			// assert the correct signature is added to the tx
   310  			assert.Equal(t, wantV, gotV)
   311  			assert.Equal(t, wantR, gotR)
   312  			assert.Equal(t, wantS, gotS)
   313  
   314  			// assert the rest of the tx is unchanged
   315  			assert.Equal(t, toSign.Nonce(), got.Nonce())
   316  			assert.Equal(t, toSign.GasPrice(), got.GasPrice())
   317  			assert.Equal(t, toSign.Gas(), got.Gas())
   318  			assert.Equal(t, toSign.To(), got.To())
   319  			assert.Equal(t, toSign.Value(), got.Value())
   320  			assert.Equal(t, toSign.Data(), got.Data())
   321  		})
   322  	}
   323  }
   324  
   325  func TestWallet_SignTxWithPassphrase(t *testing.T) {
   326  	ctrl := gomock.NewController(t)
   327  	defer ctrl.Finish()
   328  
   329  	tests := []struct {
   330  		name      string
   331  		isPrivate bool
   332  		chainID   *big.Int
   333  		signer    types.Signer
   334  	}{
   335  		{
   336  			name:      "Public EIP155 tx",
   337  			isPrivate: false,
   338  			chainID:   big.NewInt(20),
   339  			signer:    types.NewEIP155Signer(big.NewInt(20)),
   340  		},
   341  		{
   342  			name:      "Public Homestead tx",
   343  			isPrivate: false,
   344  			chainID:   nil,
   345  			signer:    types.HomesteadSigner{},
   346  		},
   347  		{
   348  			name:      "Private tx",
   349  			isPrivate: true,
   350  			chainID:   nil,
   351  			signer:    types.QuorumPrivateTxSigner{},
   352  		},
   353  	}
   354  
   355  	toSign := types.NewTransaction(
   356  		1,
   357  		common.HexToAddress("0x2332f90a329c2c55ba120b1449d36a144d1f9fe4"),
   358  		big.NewInt(1),
   359  		0,
   360  		big.NewInt(1),
   361  		nil,
   362  	)
   363  
   364  	for _, tt := range tests {
   365  		t.Run(tt.name, func(t *testing.T) {
   366  			if tt.isPrivate {
   367  				toSign.SetPrivate()
   368  			}
   369  
   370  			hashToSign := tt.signer.Hash(toSign)
   371  
   372  			mockSig := make([]byte, 65)
   373  			rand.Read(mockSig)
   374  
   375  			mockClient := mock_plugin.NewMockService(ctrl)
   376  			mockClient.
   377  				EXPECT().
   378  				UnlockAndSign(gomock.Any(), acct1, hashToSign.Bytes(), "pwd").
   379  				Return(mockSig, nil)
   380  
   381  			w := validWallet(mockClient)
   382  			got, err := w.SignTxWithPassphrase(acct1, "pwd", toSign, tt.chainID)
   383  			require.NoError(t, err)
   384  
   385  			gotV, gotR, gotS := got.RawSignatureValues()
   386  
   387  			wantR, wantS, wantV, err := tt.signer.SignatureValues(types.NewTransaction(
   388  				0,
   389  				common.Address{},
   390  				nil,
   391  				0,
   392  				nil,
   393  				nil,
   394  			), mockSig) // tx param is unused by method
   395  			require.NoError(t, err)
   396  
   397  			// assert the correct signature is added to the tx
   398  			assert.Equal(t, wantV, gotV)
   399  			assert.Equal(t, wantR, gotR)
   400  			assert.Equal(t, wantS, gotS)
   401  
   402  			// assert the rest of the tx is unchanged
   403  			assert.Equal(t, toSign.Nonce(), got.Nonce())
   404  			assert.Equal(t, toSign.GasPrice(), got.GasPrice())
   405  			assert.Equal(t, toSign.Gas(), got.Gas())
   406  			assert.Equal(t, toSign.To(), got.To())
   407  			assert.Equal(t, toSign.Value(), got.Value())
   408  			assert.Equal(t, toSign.Data(), got.Data())
   409  		})
   410  	}
   411  }