code.vegaprotocol.io/vega@v0.79.0/datanode/sqlstore/notary_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 sqlstore_test
    17  
    18  import (
    19  	"context"
    20  	"fmt"
    21  	"testing"
    22  
    23  	"code.vegaprotocol.io/vega/datanode/entities"
    24  	"code.vegaprotocol.io/vega/datanode/sqlstore"
    25  	v1 "code.vegaprotocol.io/vega/protos/vega/commands/v1"
    26  
    27  	"github.com/stretchr/testify/assert"
    28  	"github.com/stretchr/testify/require"
    29  )
    30  
    31  func TestNotary(t *testing.T) {
    32  	t.Run("Adding a single signature", testAddSignatures)
    33  	t.Run("Adding multiple signatures for multiple resources", testAddMultipleSignatures)
    34  	t.Run("Getting a non-existing resource signatures", testNoResource)
    35  	t.Run("GetByTxHash", testSignatureGetByTx)
    36  }
    37  
    38  func setupNotaryStoreTests(t *testing.T) (*sqlstore.Notary, *sqlstore.Blocks, sqlstore.Connection) {
    39  	t.Helper()
    40  	ns := sqlstore.NewNotary(connectionSource)
    41  	bs := sqlstore.NewBlocks(connectionSource)
    42  	return ns, bs, connectionSource
    43  }
    44  
    45  func testAddSignatures(t *testing.T) {
    46  	ctx := tempTransaction(t)
    47  
    48  	ws, bs, conn := setupNotaryStoreTests(t)
    49  
    50  	var rowCount int
    51  
    52  	err := conn.QueryRow(ctx, `select count(*) from withdrawals`).Scan(&rowCount)
    53  	require.NoError(t, err)
    54  	assert.Equal(t, 0, rowCount)
    55  
    56  	ns := getTestNodeSignature(t, ctx, bs, "deadbeef", "iamsig")
    57  	err = ws.Add(ctx, ns)
    58  	require.NoError(t, err)
    59  
    60  	err = conn.QueryRow(ctx, `select count(*) from node_signatures`).Scan(&rowCount)
    61  	assert.NoError(t, err)
    62  	assert.Equal(t, 1, rowCount)
    63  }
    64  
    65  func testAddMultipleSignatures(t *testing.T) {
    66  	ctx := tempTransaction(t)
    67  
    68  	ws, bs, _ := setupNotaryStoreTests(t)
    69  
    70  	nodeSig1 := getTestNodeSignature(t, ctx, bs, "deadbeef", "iamsig")
    71  	nodeSig2 := getTestNodeSignature(t, ctx, bs, "deadbeef", "iamsig")         // this will have a different sig
    72  	nodeSig3 := getTestNodeSignature(t, ctx, bs, "deadbeef", "iamsig")         // this will be a dupe of ns2
    73  	nodeSig4 := getTestNodeSignature(t, ctx, bs, "deadbeefdeadbeef", "iamsig") // this will have a different sig and id
    74  
    75  	nodeSig2.Sig = []byte("iamdifferentsig")
    76  	nodeSig4.Sig = []byte("iamdifferentsigagain")
    77  
    78  	err := ws.Add(ctx, nodeSig1)
    79  	require.NoError(t, err)
    80  
    81  	err = ws.Add(ctx, nodeSig2)
    82  	require.NoError(t, err)
    83  
    84  	err = ws.Add(ctx, nodeSig3)
    85  	require.NoError(t, err)
    86  
    87  	err = ws.Add(ctx, nodeSig4)
    88  	require.NoError(t, err)
    89  
    90  	res, _, err := ws.GetByResourceID(ctx, "deadbeef", entities.CursorPagination{})
    91  	require.NoError(t, err)
    92  	require.Len(t, res, 2)
    93  
    94  	res, _, err = ws.GetByResourceID(ctx, "deadbeefdeadbeef", entities.CursorPagination{})
    95  	require.NoError(t, err)
    96  	require.Len(t, res, 1)
    97  }
    98  
    99  func getTestNodeSignature(t *testing.T, ctx context.Context, bs *sqlstore.Blocks, id string, sig string) *entities.NodeSignature {
   100  	t.Helper()
   101  	block := addTestBlock(t, ctx, bs)
   102  	ns, err := entities.NodeSignatureFromProto(
   103  		&v1.NodeSignature{
   104  			Id:   id,
   105  			Sig:  []byte(sig),
   106  			Kind: v1.NodeSignatureKind_NODE_SIGNATURE_KIND_ASSET_WITHDRAWAL,
   107  		},
   108  		generateTxHash(),
   109  		block.VegaTime,
   110  	)
   111  	require.NoError(t, err)
   112  	return ns
   113  }
   114  
   115  func testNoResource(t *testing.T) {
   116  	ctx := tempTransaction(t)
   117  
   118  	ws, _, _ := setupNotaryStoreTests(t)
   119  
   120  	res, _, err := ws.GetByResourceID(ctx, "deadbeefdeadbeef", entities.CursorPagination{})
   121  	require.NoError(t, err)
   122  	require.Len(t, res, 0)
   123  }
   124  
   125  func testSignatureGetByTx(t *testing.T) {
   126  	ctx := tempTransaction(t)
   127  
   128  	ns, bs, _ := setupNotaryStoreTests(t)
   129  
   130  	signature := getTestNodeSignature(t, ctx, bs, "deadbeef", "iamsig")
   131  	require.NoError(t, ns.Add(ctx, signature))
   132  
   133  	signature2 := getTestNodeSignature(t, ctx, bs, "deadbaef", "iamsig")
   134  	require.NoError(t, ns.Add(ctx, signature2))
   135  
   136  	signatures, err := ns.GetByTxHash(ctx, signature.TxHash)
   137  	require.NoError(t, err)
   138  	require.Len(t, signatures, 1)
   139  	require.Equal(t, *signature, signatures[0])
   140  
   141  	signatures, err = ns.GetByTxHash(ctx, signature2.TxHash)
   142  	require.NoError(t, err)
   143  	require.Len(t, signatures, 1)
   144  	require.Equal(t, *signature2, signatures[0])
   145  }
   146  
   147  func TestNodeSignaturePagination(t *testing.T) {
   148  	t.Run("should return all node signatures if no pagination is specified", testNodeSignaturePaginationNoPagination)
   149  	t.Run("should return first page of node signatures if first pagination is specified", testNodeSignaturePaginationFirst)
   150  	t.Run("should return last page of node signatures if last pagination is specified", testNodeSignaturePaginationLast)
   151  	t.Run("should return specified page of node signatures if first and after pagination is specified", testNodeSignaturePaginationFirstAfter)
   152  	t.Run("should return specified page of node signatures if last and before pagination is specified", testNodeSignaturePaginationLastBefore)
   153  
   154  	t.Run("should return all node signatures if no pagination is specified - newest first", testNodeSignaturePaginationNoPaginationNewestFirst)
   155  	t.Run("should return first page of node signatures if first pagination is specified - newest first", testNodeSignaturePaginationFirstNewestFirst)
   156  	t.Run("should return last page of node signatures if last pagination is specified - newest first", testNodeSignaturePaginationLastNewestFirst)
   157  	t.Run("should return specified page of node signatures if first and after pagination is specified - newest first", testNodeSignaturePaginationFirstAfterNewestFirst)
   158  	t.Run("should return specified page of node signatures if last and before pagination is specified - newest first", testNodeSignaturePaginationLastBeforeNewestFirst)
   159  }
   160  
   161  func testNodeSignaturePaginationNoPagination(t *testing.T) {
   162  	ctx := tempTransaction(t)
   163  
   164  	ns, sigs := setupNodeSignaturePaginationTest(t, ctx)
   165  	pagination, err := entities.NewCursorPagination(nil, nil, nil, nil, false)
   166  	require.NoError(t, err)
   167  
   168  	got, pageInfo, err := ns.GetByResourceID(ctx, "deadbeef", pagination)
   169  	require.NoError(t, err)
   170  	want := sigs
   171  	assert.Equal(t, want, got)
   172  	assert.Equal(t, entities.PageInfo{
   173  		HasNextPage:     false,
   174  		HasPreviousPage: false,
   175  		StartCursor:     want[0].Cursor().Encode(),
   176  		EndCursor:       want[9].Cursor().Encode(),
   177  	}, pageInfo)
   178  }
   179  
   180  func testNodeSignaturePaginationFirst(t *testing.T) {
   181  	ctx := tempTransaction(t)
   182  
   183  	ns, sigs := setupNodeSignaturePaginationTest(t, ctx)
   184  	first := int32(3)
   185  	pagination, err := entities.NewCursorPagination(&first, nil, nil, nil, false)
   186  	require.NoError(t, err)
   187  
   188  	got, pageInfo, err := ns.GetByResourceID(ctx, "deadbeef", pagination)
   189  	require.NoError(t, err)
   190  	want := sigs[:3]
   191  	assert.Equal(t, want, got)
   192  	assert.Equal(t, entities.PageInfo{
   193  		HasNextPage:     true,
   194  		HasPreviousPage: false,
   195  		StartCursor:     want[0].Cursor().Encode(),
   196  		EndCursor:       want[2].Cursor().Encode(),
   197  	}, pageInfo)
   198  }
   199  
   200  func testNodeSignaturePaginationLast(t *testing.T) {
   201  	ctx := tempTransaction(t)
   202  
   203  	ns, sigs := setupNodeSignaturePaginationTest(t, ctx)
   204  	last := int32(3)
   205  	pagination, err := entities.NewCursorPagination(nil, nil, &last, nil, false)
   206  	require.NoError(t, err)
   207  
   208  	got, pageInfo, err := ns.GetByResourceID(ctx, "deadbeef", pagination)
   209  	require.NoError(t, err)
   210  	want := sigs[7:]
   211  	assert.Equal(t, want, got)
   212  	assert.Equal(t, entities.PageInfo{
   213  		HasNextPage:     false,
   214  		HasPreviousPage: true,
   215  		StartCursor:     want[0].Cursor().Encode(),
   216  		EndCursor:       want[2].Cursor().Encode(),
   217  	}, pageInfo)
   218  }
   219  
   220  func testNodeSignaturePaginationFirstAfter(t *testing.T) {
   221  	ctx := tempTransaction(t)
   222  
   223  	ns, sigs := setupNodeSignaturePaginationTest(t, ctx)
   224  	first := int32(3)
   225  	after := sigs[2].Cursor().Encode()
   226  	pagination, err := entities.NewCursorPagination(&first, &after, nil, nil, false)
   227  	require.NoError(t, err)
   228  
   229  	got, pageInfo, err := ns.GetByResourceID(ctx, "deadbeef", pagination)
   230  	require.NoError(t, err)
   231  	want := sigs[3:6]
   232  	assert.Equal(t, want, got)
   233  	assert.Equal(t, entities.PageInfo{
   234  		HasNextPage:     true,
   235  		HasPreviousPage: true,
   236  		StartCursor:     want[0].Cursor().Encode(),
   237  		EndCursor:       want[2].Cursor().Encode(),
   238  	}, pageInfo)
   239  }
   240  
   241  func testNodeSignaturePaginationLastBefore(t *testing.T) {
   242  	ctx := tempTransaction(t)
   243  
   244  	ns, sigs := setupNodeSignaturePaginationTest(t, ctx)
   245  	last := int32(3)
   246  	before := sigs[7].Cursor().Encode()
   247  	pagination, err := entities.NewCursorPagination(nil, nil, &last, &before, false)
   248  	require.NoError(t, err)
   249  
   250  	got, pageInfo, err := ns.GetByResourceID(ctx, "deadbeef", pagination)
   251  	require.NoError(t, err)
   252  	want := sigs[4:7]
   253  	assert.Equal(t, want, got)
   254  	assert.Equal(t, entities.PageInfo{
   255  		HasNextPage:     true,
   256  		HasPreviousPage: true,
   257  		StartCursor:     want[0].Cursor().Encode(),
   258  		EndCursor:       want[2].Cursor().Encode(),
   259  	}, pageInfo)
   260  }
   261  
   262  func testNodeSignaturePaginationNoPaginationNewestFirst(t *testing.T) {
   263  	ctx := tempTransaction(t)
   264  
   265  	ns, sigs := setupNodeSignaturePaginationTest(t, ctx)
   266  	pagination, err := entities.NewCursorPagination(nil, nil, nil, nil, true)
   267  	require.NoError(t, err)
   268  
   269  	got, pageInfo, err := ns.GetByResourceID(ctx, "deadbeef", pagination)
   270  	require.NoError(t, err)
   271  	want := entities.ReverseSlice(sigs)
   272  	assert.Equal(t, want, got)
   273  	assert.Equal(t, entities.PageInfo{
   274  		HasNextPage:     false,
   275  		HasPreviousPage: false,
   276  		StartCursor:     want[0].Cursor().Encode(),
   277  		EndCursor:       want[9].Cursor().Encode(),
   278  	}, pageInfo)
   279  }
   280  
   281  func testNodeSignaturePaginationFirstNewestFirst(t *testing.T) {
   282  	ctx := tempTransaction(t)
   283  
   284  	ns, sigs := setupNodeSignaturePaginationTest(t, ctx)
   285  	first := int32(3)
   286  	pagination, err := entities.NewCursorPagination(&first, nil, nil, nil, true)
   287  	require.NoError(t, err)
   288  
   289  	got, pageInfo, err := ns.GetByResourceID(ctx, "deadbeef", pagination)
   290  	require.NoError(t, err)
   291  	want := entities.ReverseSlice(sigs)[:3]
   292  	assert.Equal(t, want, got)
   293  	assert.Equal(t, entities.PageInfo{
   294  		HasNextPage:     true,
   295  		HasPreviousPage: false,
   296  		StartCursor:     want[0].Cursor().Encode(),
   297  		EndCursor:       want[2].Cursor().Encode(),
   298  	}, pageInfo)
   299  }
   300  
   301  func testNodeSignaturePaginationLastNewestFirst(t *testing.T) {
   302  	ctx := tempTransaction(t)
   303  
   304  	ns, sigs := setupNodeSignaturePaginationTest(t, ctx)
   305  	last := int32(3)
   306  	pagination, err := entities.NewCursorPagination(nil, nil, &last, nil, true)
   307  	require.NoError(t, err)
   308  
   309  	got, pageInfo, err := ns.GetByResourceID(ctx, "deadbeef", pagination)
   310  	require.NoError(t, err)
   311  	want := entities.ReverseSlice(sigs)[7:]
   312  	assert.Equal(t, want, got)
   313  	assert.Equal(t, entities.PageInfo{
   314  		HasNextPage:     false,
   315  		HasPreviousPage: true,
   316  		StartCursor:     want[0].Cursor().Encode(),
   317  		EndCursor:       want[2].Cursor().Encode(),
   318  	}, pageInfo)
   319  }
   320  
   321  func testNodeSignaturePaginationFirstAfterNewestFirst(t *testing.T) {
   322  	ctx := tempTransaction(t)
   323  
   324  	ns, sigs := setupNodeSignaturePaginationTest(t, ctx)
   325  	first := int32(3)
   326  	after := sigs[7].Cursor().Encode()
   327  	pagination, err := entities.NewCursorPagination(&first, &after, nil, nil, true)
   328  	require.NoError(t, err)
   329  
   330  	got, pageInfo, err := ns.GetByResourceID(ctx, "deadbeef", pagination)
   331  	require.NoError(t, err)
   332  	want := entities.ReverseSlice(sigs)[3:6]
   333  	assert.Equal(t, want, got)
   334  	assert.Equal(t, entities.PageInfo{
   335  		HasNextPage:     true,
   336  		HasPreviousPage: true,
   337  		StartCursor:     want[0].Cursor().Encode(),
   338  		EndCursor:       want[2].Cursor().Encode(),
   339  	}, pageInfo)
   340  }
   341  
   342  func testNodeSignaturePaginationLastBeforeNewestFirst(t *testing.T) {
   343  	ctx := tempTransaction(t)
   344  
   345  	ns, sigs := setupNodeSignaturePaginationTest(t, ctx)
   346  	last := int32(3)
   347  	before := sigs[2].Cursor().Encode()
   348  	pagination, err := entities.NewCursorPagination(nil, nil, &last, &before, true)
   349  	require.NoError(t, err)
   350  
   351  	got, pageInfo, err := ns.GetByResourceID(ctx, "deadbeef", pagination)
   352  	require.NoError(t, err)
   353  	want := entities.ReverseSlice(sigs)[4:7]
   354  	assert.Equal(t, want, got)
   355  	assert.Equal(t, entities.PageInfo{
   356  		HasNextPage:     true,
   357  		HasPreviousPage: true,
   358  		StartCursor:     want[0].Cursor().Encode(),
   359  		EndCursor:       want[2].Cursor().Encode(),
   360  	}, pageInfo)
   361  }
   362  
   363  func setupNodeSignaturePaginationTest(t *testing.T, ctx context.Context) (*sqlstore.Notary, []entities.NodeSignature) {
   364  	t.Helper()
   365  	bs := sqlstore.NewBlocks(connectionSource)
   366  	ns := sqlstore.NewNotary(connectionSource)
   367  	signatures := make([]entities.NodeSignature, 10)
   368  
   369  	for i := 0; i < 10; i++ {
   370  		signature := getTestNodeSignature(t, ctx, bs, "deadbeef", fmt.Sprintf("sig%02d", i+1))
   371  		signatures[i] = *signature
   372  		err := ns.Add(ctx, signature)
   373  		require.NoError(t, err)
   374  	}
   375  
   376  	return ns, signatures
   377  }
   378  
   379  func TestNodeSignatureKindEnum(t *testing.T) {
   380  	var nodeSignatureKind v1.NodeSignatureKind
   381  	sigKinds := getEnums(t, nodeSignatureKind)
   382  	assert.Len(t, sigKinds, 6)
   383  	for k, kind := range sigKinds {
   384  		t.Run(kind, func(t *testing.T) {
   385  			ctx := tempTransaction(t)
   386  
   387  			ws, bs, _ := setupNotaryStoreTests(t)
   388  
   389  			ns := getTestNodeSignature(t, ctx, bs, "deadbeef", "iamsig")
   390  			ns.Kind = entities.NodeSignatureKind(k)
   391  			require.NoError(t, ws.Add(ctx, ns))
   392  			got, err := ws.GetByTxHash(ctx, ns.TxHash)
   393  			require.NoError(t, err)
   394  			assert.Len(t, got, 1)
   395  			assert.Equal(t, ns.Kind, got[0].Kind)
   396  		})
   397  	}
   398  }