code.vegaprotocol.io/vega@v0.79.0/commands/transaction_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 commands_test
    17  
    18  import (
    19  	"errors"
    20  	"testing"
    21  
    22  	"code.vegaprotocol.io/vega/commands"
    23  	"code.vegaprotocol.io/vega/libs/crypto"
    24  	commandspb "code.vegaprotocol.io/vega/protos/vega/commands/v1"
    25  
    26  	"github.com/stretchr/testify/assert"
    27  	"github.com/stretchr/testify/require"
    28  	"google.golang.org/protobuf/proto"
    29  )
    30  
    31  func TestCheckTransaction(t *testing.T) {
    32  	t.Run("Submitting valid transaction succeeds", testSubmittingInvalidSignature)
    33  	t.Run("Submitting valid transaction succeeds", testSubmittingValidTransactionSucceeds)
    34  	t.Run("Submitting empty transaction fails", testSubmittingEmptyTransactionFails)
    35  	t.Run("Submitting nil transaction fails", testSubmittingNilTransactionFails)
    36  	t.Run("Submitting transaction without version fails", testSubmittingTransactionWithoutVersionFails)
    37  	t.Run("Submitting transaction with unsupported version fails", testSubmittingTransactionWithUnsupportedVersionFails)
    38  	t.Run("Submitting transaction without input data fails", testSubmittingTransactionWithoutInputDataFails)
    39  	t.Run("Submitting transaction without signature fails", testSubmittingTransactionWithoutSignatureFails)
    40  	t.Run("Submitting transaction without signature value fails", testSubmittingTransactionWithoutSignatureValueFails)
    41  	t.Run("Submitting transaction without signature algo fails", testSubmittingTransactionWithoutSignatureAlgoFails)
    42  	t.Run("Submitting transaction without from fails", testSubmittingTransactionWithoutFromFails)
    43  	t.Run("Submitting transaction without public key fails", testSubmittingTransactionWithoutPubKeyFromFails)
    44  	t.Run("Submitting transaction with invalid encoding of value fails", testSubmittingTransactionWithInvalidEncodingOfValueFails)
    45  	t.Run("Submitting transaction with invalid encoding of public key fails", testSubmittingTransactionWithInvalidEncodingOfPubKeyFails)
    46  }
    47  
    48  func testSubmittingInvalidSignature(t *testing.T) {
    49  	tx := newValidTransactionV2(t)
    50  	tx.Signature = &commandspb.Signature{
    51  		Value:   crypto.RandomHash(),
    52  		Algo:    "vega/ed25519",
    53  		Version: 1,
    54  	}
    55  	err := checkTransaction(tx)
    56  	require.Error(t, err)
    57  	require.Equal(t, commands.ErrInvalidSignature, err["tx.signature.value"][0])
    58  }
    59  
    60  func testSubmittingValidTransactionSucceeds(t *testing.T) {
    61  	tx := newValidTransactionV2(t)
    62  
    63  	err := checkTransaction(tx)
    64  
    65  	assert.True(t, err.Empty(), err.Error())
    66  }
    67  
    68  func testSubmittingEmptyTransactionFails(t *testing.T) {
    69  	err := checkTransaction(&commandspb.Transaction{})
    70  
    71  	assert.Error(t, err)
    72  }
    73  
    74  func testSubmittingNilTransactionFails(t *testing.T) {
    75  	err := checkTransaction(nil)
    76  
    77  	assert.Contains(t, err.Get("tx"), commands.ErrIsRequired)
    78  }
    79  
    80  func testSubmittingTransactionWithoutVersionFails(t *testing.T) {
    81  	tx := newValidTransactionV2(t)
    82  	tx.Version = 0
    83  
    84  	err := checkTransaction(tx)
    85  
    86  	assert.Contains(t, err.Get("tx.version"), commands.ErrIsRequired)
    87  }
    88  
    89  func testSubmittingTransactionWithUnsupportedVersionFails(t *testing.T) {
    90  	tcs := []struct {
    91  		name    string
    92  		version uint32
    93  	}{
    94  		{
    95  			name:    "version 1",
    96  			version: 1,
    97  		}, {
    98  			name:    "version 4",
    99  			version: 4,
   100  		},
   101  	}
   102  
   103  	for _, tc := range tcs {
   104  		t.Run(tc.name, func(tt *testing.T) {
   105  			tx := newValidTransactionV2(tt)
   106  			tx.Version = commandspb.TxVersion(tc.version)
   107  
   108  			err := checkTransaction(tx)
   109  
   110  			assert.Contains(tt, err.Get("tx.version"), commands.ErrIsNotSupported)
   111  		})
   112  	}
   113  }
   114  
   115  func testSubmittingTransactionWithoutInputDataFails(t *testing.T) {
   116  	tx := newValidTransactionV2(t)
   117  	tx.InputData = []byte{}
   118  
   119  	err := checkTransaction(tx)
   120  
   121  	assert.Contains(t, err.Get("tx.input_data"), commands.ErrIsRequired)
   122  }
   123  
   124  func testSubmittingTransactionWithoutSignatureFails(t *testing.T) {
   125  	tx := newValidTransactionV2(t)
   126  	tx.Signature = nil
   127  
   128  	err := checkTransaction(tx)
   129  
   130  	assert.Contains(t, err.Get("tx.signature"), commands.ErrIsRequired)
   131  }
   132  
   133  func testSubmittingTransactionWithoutSignatureValueFails(t *testing.T) {
   134  	tx := newValidTransactionV2(t)
   135  	tx.Signature.Value = ""
   136  
   137  	err := checkTransaction(tx)
   138  
   139  	assert.Contains(t, err.Get("tx.signature.value"), commands.ErrIsRequired)
   140  }
   141  
   142  func testSubmittingTransactionWithoutSignatureAlgoFails(t *testing.T) {
   143  	tx := newValidTransactionV2(t)
   144  	tx.Signature.Algo = ""
   145  
   146  	err := checkTransaction(tx)
   147  
   148  	assert.Contains(t, err.Get("tx.signature.algo"), commands.ErrIsRequired)
   149  }
   150  
   151  func testSubmittingTransactionWithoutFromFails(t *testing.T) {
   152  	tx := newValidTransactionV2(t)
   153  	tx.From = nil
   154  
   155  	err := checkTransaction(tx)
   156  
   157  	assert.Contains(t, err.Get("tx.from"), commands.ErrIsRequired)
   158  }
   159  
   160  func testSubmittingTransactionWithoutPubKeyFromFails(t *testing.T) {
   161  	tx := newValidTransactionV2(t)
   162  	tx.From = &commandspb.Transaction_PubKey{
   163  		PubKey: "",
   164  	}
   165  
   166  	err := checkTransaction(tx)
   167  
   168  	assert.Contains(t, err.Get("tx.from.pub_key"), commands.ErrIsRequired)
   169  }
   170  
   171  func testSubmittingTransactionWithInvalidEncodingOfValueFails(t *testing.T) {
   172  	tx := newValidTransactionV2(t)
   173  	tx.Signature.Value = "invalid-hex-encoding"
   174  
   175  	err := checkTransaction(tx)
   176  
   177  	assert.Contains(t, err.Get("tx.signature.value"), commands.ErrShouldBeHexEncoded, err.Error())
   178  }
   179  
   180  func testSubmittingTransactionWithInvalidEncodingOfPubKeyFails(t *testing.T) {
   181  	tx := newValidTransactionV2(t)
   182  	tx.From = &commandspb.Transaction_PubKey{
   183  		PubKey: "my-pub-key",
   184  	}
   185  
   186  	err := checkTransaction(tx)
   187  
   188  	assert.Contains(t, err.Get("tx.from.pub_key"), commands.ErrShouldBeAValidVegaPublicKey)
   189  }
   190  
   191  func checkTransaction(cmd *commandspb.Transaction) commands.Errors {
   192  	_, err := commands.CheckTransaction(cmd, "testnet")
   193  
   194  	var e commands.Errors
   195  	if ok := errors.As(err, &e); !ok {
   196  		return commands.NewErrors()
   197  	}
   198  
   199  	return e
   200  }
   201  
   202  func newValidTransactionV2(t *testing.T) *commandspb.Transaction {
   203  	t.Helper()
   204  
   205  	inputData := &commandspb.InputData{
   206  		Nonce:       123456789,
   207  		BlockHeight: 1789,
   208  		Command: &commandspb.InputData_OrderCancellation{
   209  			OrderCancellation: &commandspb.OrderCancellation{
   210  				MarketId: "USD/BTC",
   211  				OrderId:  "7fa6d9f6a9dfa9f66fada",
   212  			},
   213  		},
   214  	}
   215  
   216  	rawInputData, err := proto.Marshal(inputData)
   217  	if err != nil {
   218  		t.Fatal(err)
   219  	}
   220  
   221  	return &commandspb.Transaction{
   222  		InputData: rawInputData,
   223  		Signature: &commandspb.Signature{
   224  			Algo:    "vega/ed25519",
   225  			Value:   "876e46defc40030391b5feb2c9bb0b6b68b2d95a6b5fd17a730a46ea73f3b1808420c8c609be6f1c6156e472ecbcd09202f750da000dee41429947a4b7eca00b",
   226  			Version: 1,
   227  		},
   228  		From: &commandspb.Transaction_PubKey{
   229  			PubKey: "b5fd9d3c4ad553cb3196303b6e6df7f484cf7f5331a572a45031239fd71ad8a0",
   230  		},
   231  		Version: 2,
   232  	}
   233  }