code.vegaprotocol.io/vega@v0.79.0/core/notary/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 notary_test
    17  
    18  import (
    19  	"context"
    20  	"testing"
    21  	"time"
    22  
    23  	bmocks "code.vegaprotocol.io/vega/core/broker/mocks"
    24  	"code.vegaprotocol.io/vega/core/notary"
    25  	"code.vegaprotocol.io/vega/core/notary/mocks"
    26  	"code.vegaprotocol.io/vega/core/types"
    27  	"code.vegaprotocol.io/vega/logging"
    28  	commandspb "code.vegaprotocol.io/vega/protos/vega/commands/v1"
    29  
    30  	"github.com/golang/mock/gomock"
    31  	"github.com/stretchr/testify/assert"
    32  )
    33  
    34  type testNotary struct {
    35  	*notary.SnapshotNotary
    36  	// 	*notary.Notary
    37  	ctrl   *gomock.Controller
    38  	top    *mocks.MockValidatorTopology
    39  	cmd    *mocks.MockCommander
    40  	onTick func(context.Context, time.Time)
    41  }
    42  
    43  func getTestNotary(t *testing.T) *testNotary {
    44  	t.Helper()
    45  	ctrl := gomock.NewController(t)
    46  	top := mocks.NewMockValidatorTopology(ctrl)
    47  	broker := bmocks.NewMockBroker(ctrl)
    48  	cmd := mocks.NewMockCommander(ctrl)
    49  	broker.EXPECT().Send(gomock.Any()).AnyTimes()
    50  	broker.EXPECT().SendBatch(gomock.Any()).AnyTimes()
    51  	notr := notary.NewWithSnapshot(logging.NewTestLogger(), notary.NewDefaultConfig(), top, broker, cmd)
    52  	return &testNotary{
    53  		SnapshotNotary: notr,
    54  		top:            top,
    55  		ctrl:           ctrl,
    56  		cmd:            cmd,
    57  		onTick:         notr.OnTick,
    58  	}
    59  }
    60  
    61  func TestNotary(t *testing.T) {
    62  	t.Run("test add key for unknow resource - fail", testAddKeyForKOResource)
    63  	t.Run("test add bad signature for known resource - success", testAddBadSignatureForOKResource)
    64  	t.Run("test add key finalize all sig", testAddKeyFinalize)
    65  	t.Run("test add key finalize all fails if sigs aren't tendermint validators", testAddKeyFinalizeFails)
    66  }
    67  
    68  func testAddKeyForKOResource(t *testing.T) {
    69  	notr := getTestNotary(t)
    70  	kind := types.NodeSignatureKindAssetNew
    71  	resID := "resid"
    72  	key := "123456"
    73  	sig := []byte("123456")
    74  
    75  	ns := commandspb.NodeSignature{
    76  		Sig:  sig,
    77  		Id:   resID,
    78  		Kind: kind,
    79  	}
    80  
    81  	// first try to add a key for invalid resource
    82  	err := notr.RegisterSignature(context.Background(), key, ns)
    83  	assert.EqualError(t, err, notary.ErrUnknownResourceID.Error())
    84  
    85  	// then try to start twice an aggregate
    86  	notr.top.EXPECT().IsValidator().Times(1).Return(true)
    87  
    88  	notr.StartAggregate(resID, kind, sig)
    89  	assert.Panics(t, func() { notr.StartAggregate(resID, kind, sig) }, "expect to panic")
    90  }
    91  
    92  func testAddBadSignatureForOKResource(t *testing.T) {
    93  	notr := getTestNotary(t)
    94  
    95  	kind := types.NodeSignatureKindAssetNew
    96  	resID := "resid"
    97  	key := "123456"
    98  	sig := []byte("123456")
    99  
   100  	// start to aggregate, being a validator or not here doesn't matter
   101  	notr.top.EXPECT().IsValidator().Times(1).Return(false)
   102  	notr.StartAggregate(resID, kind, nil) // we send nil here if we are no validator
   103  
   104  	ns := commandspb.NodeSignature{
   105  		Sig:  sig,
   106  		Id:   resID,
   107  		Kind: kind,
   108  	}
   109  
   110  	// The signature we have received is not from a validator
   111  	notr.top.EXPECT().IsValidatorVegaPubKey(gomock.Any()).AnyTimes().Return(false)
   112  
   113  	err := notr.RegisterSignature(context.Background(), key, ns)
   114  	assert.EqualError(t, err, notary.ErrNotAValidatorSignature.Error())
   115  }
   116  
   117  func testAddKeyFinalize(t *testing.T) {
   118  	notr := getTestNotary(t)
   119  
   120  	kind := types.NodeSignatureKindAssetNew
   121  	resID := "resid"
   122  	key := "123456"
   123  	sig := []byte("123456")
   124  
   125  	// add a valid node
   126  	notr.top.EXPECT().Len().AnyTimes().Return(1)
   127  	notr.top.EXPECT().IsValidatorVegaPubKey(gomock.Any()).AnyTimes().Return(true)
   128  	notr.top.EXPECT().IsTendermintValidator(gomock.Any()).AnyTimes().Return(true)
   129  
   130  	notr.top.EXPECT().IsValidator().Times(1).Return(true)
   131  	notr.StartAggregate(resID, kind, sig)
   132  
   133  	// expect command to be send on next on time update
   134  	notr.cmd.EXPECT().Command(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Times(1)
   135  	notr.onTick(context.Background(), time.Now())
   136  
   137  	ns := commandspb.NodeSignature{
   138  		Sig:  sig,
   139  		Id:   resID,
   140  		Kind: kind,
   141  	}
   142  
   143  	// first try to add a key for invalid resource
   144  	notr.top.EXPECT().SelfVegaPubKey().Times(1).Return(key)
   145  	err := notr.RegisterSignature(context.Background(), key, ns)
   146  	assert.NoError(t, err, notary.ErrUnknownResourceID.Error())
   147  
   148  	signatures, ok := notr.IsSigned(context.Background(), resID, kind)
   149  	assert.True(t, ok)
   150  	assert.Len(t, signatures, 1)
   151  }
   152  
   153  func testAddKeyFinalizeFails(t *testing.T) {
   154  	notr := getTestNotary(t)
   155  
   156  	kind := types.NodeSignatureKindAssetNew
   157  	resID := "resid"
   158  	key := "123456"
   159  	sig := []byte("123456")
   160  
   161  	// add a valid node
   162  	notr.top.EXPECT().Len().AnyTimes().Return(1)
   163  	notr.top.EXPECT().IsValidatorVegaPubKey(gomock.Any()).AnyTimes().Return(true)
   164  	notr.top.EXPECT().IsTendermintValidator(gomock.Any()).AnyTimes().Return(false)
   165  
   166  	notr.top.EXPECT().IsValidator().Times(1).Return(true)
   167  	notr.StartAggregate(resID, kind, sig)
   168  
   169  	// expect command to be send on next on time update
   170  	notr.cmd.EXPECT().Command(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Times(1)
   171  	notr.onTick(context.Background(), time.Now())
   172  
   173  	ns := commandspb.NodeSignature{
   174  		Sig:  sig,
   175  		Id:   resID,
   176  		Kind: kind,
   177  	}
   178  
   179  	// first try to add a key for invalid resource
   180  	notr.top.EXPECT().SelfVegaPubKey().Times(1).Return(key)
   181  	err := notr.RegisterSignature(context.Background(), key, ns)
   182  	assert.NoError(t, err, notary.ErrUnknownResourceID.Error())
   183  
   184  	signatures, ok := notr.IsSigned(context.Background(), resID, kind)
   185  	assert.False(t, ok)
   186  	assert.Len(t, signatures, 0) // no signatures because everyone that signed wasn't a Tendermint validator
   187  }