code.vegaprotocol.io/vega@v0.79.0/core/validators/erc20multisig/checkpoint_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 erc20multisig_test
    17  
    18  import (
    19  	"context"
    20  	"testing"
    21  	"time"
    22  
    23  	"code.vegaprotocol.io/vega/core/types"
    24  	"code.vegaprotocol.io/vega/core/validators"
    25  
    26  	"github.com/golang/mock/gomock"
    27  	"github.com/stretchr/testify/assert"
    28  	"github.com/stretchr/testify/require"
    29  )
    30  
    31  func TestMultisigTopologyCheckpoint(t *testing.T) {
    32  	top := getTestTopology(t)
    33  	defer top.ctrl.Finish()
    34  
    35  	top.OnTick(context.Background(), time.Unix(10, 0))
    36  	// first set the threshold and 1 validator
    37  
    38  	// Let's create threshold
    39  	// first assert we have no threshold
    40  	assert.Equal(t, uint32(0), top.GetThreshold())
    41  
    42  	thresholdEvent1 := types.SignerThresholdSetEvent{
    43  		Threshold:   666,
    44  		BlockNumber: 10,
    45  		LogIndex:    11,
    46  		TxHash:      "0xacbde",
    47  		ID:          "someid",
    48  		Nonce:       "123",
    49  		BlockTime:   123456789,
    50  	}
    51  
    52  	var cb func(interface{}, bool)
    53  	var res validators.Resource
    54  	top.witness.EXPECT().StartCheck(gomock.Any(), gomock.Any(), gomock.Any()).Times(1).DoAndReturn(func(r validators.Resource, f func(interface{}, bool), _ time.Time) error {
    55  		cb = f
    56  		res = r
    57  		return nil
    58  	})
    59  
    60  	assert.NoError(t, top.ProcessThresholdEvent(&thresholdEvent1))
    61  
    62  	// now we can call the callback
    63  	cb(res, true)
    64  
    65  	// now we can update the time
    66  	top.ocv.EXPECT().GetMultiSigAddress().AnyTimes()
    67  	top.ethEventSource.EXPECT().UpdateContractBlock(gomock.Any(), gomock.Any(), gomock.Any()).AnyTimes()
    68  	top.broker.EXPECT().Send(gomock.Any()).Times(1)
    69  	top.OnTick(context.Background(), time.Unix(11, 0))
    70  	assert.Equal(t, top.GetThreshold(), uint32(666))
    71  
    72  	// now the signer
    73  
    74  	// first assert we have no signers
    75  	assert.Len(t, top.GetSigners(), 0)
    76  
    77  	signerEvent1 := types.SignerEvent{
    78  		BlockNumber: 150,
    79  		LogIndex:    11,
    80  		TxHash:      "0xacbde",
    81  		ID:          "someid",
    82  		Address:     "0xe82EfC4187705655C9b484dFFA25f240e8A6B0BA",
    83  		Nonce:       "123",
    84  		BlockTime:   123456789,
    85  		Kind:        types.SignerEventKindAdded,
    86  	}
    87  
    88  	top.witness.EXPECT().StartCheck(gomock.Any(), gomock.Any(), gomock.Any()).Times(1).DoAndReturn(func(r validators.Resource, f func(interface{}, bool), _ time.Time) error {
    89  		cb = f
    90  		res = r
    91  		return nil
    92  	})
    93  
    94  	assert.NoError(t, top.ProcessSignerEvent(&signerEvent1))
    95  
    96  	// now we can call the callback
    97  	cb(res, true)
    98  
    99  	// now we can update the time
   100  	top.broker.EXPECT().Send(gomock.Any()).Times(1)
   101  	top.OnTick(context.Background(), time.Unix(12, 0))
   102  
   103  	t.Run("ensure the signer list is updated", func(t *testing.T) {
   104  		signers := top.GetSigners()
   105  		assert.Len(t, signers, 1)
   106  		assert.Equal(t, "0xe82EfC4187705655C9b484dFFA25f240e8A6B0BA", signers[0])
   107  	})
   108  
   109  	t.Run("check if our party IsSigner", func(t *testing.T) {
   110  		assert.True(t, top.IsSigner("0xe82EfC4187705655C9b484dFFA25f240e8A6B0BA"))
   111  	})
   112  
   113  	t.Run("check excess signers", func(t *testing.T) {
   114  		okAddresses := []string{"0xe82EfC4187705655C9b484dFFA25f240e8A6B0BA"}
   115  		koAddresses := []string{}
   116  
   117  		assert.True(t, top.ExcessSigners(koAddresses))
   118  		assert.False(t, top.ExcessSigners(okAddresses))
   119  	})
   120  
   121  	// now we will add some pending ones
   122  
   123  	thresholdEvent2 := types.SignerThresholdSetEvent{
   124  		Threshold:   500,
   125  		BlockNumber: 150,
   126  		LogIndex:    1,
   127  		TxHash:      "0xacbde2",
   128  		ID:          "someidthreshold2",
   129  		Nonce:       "1234",
   130  		BlockTime:   133456790,
   131  	}
   132  
   133  	top.witness.EXPECT().StartCheck(gomock.Any(), gomock.Any(), gomock.Any()).Times(1).DoAndReturn(func(r validators.Resource, f func(interface{}, bool), _ time.Time) error {
   134  		return nil
   135  	})
   136  
   137  	assert.NoError(t, top.ProcessThresholdEvent(&thresholdEvent2))
   138  
   139  	signerEvent2 := types.SignerEvent{
   140  		BlockNumber: 101,
   141  		LogIndex:    19,
   142  		TxHash:      "0xacbde3",
   143  		ID:          "someid3",
   144  		Address:     "0xa587765281c2514E899ecFFa9626b6254582a3bA",
   145  		Nonce:       "1239",
   146  		BlockTime:   133456789,
   147  		Kind:        types.SignerEventKindAdded,
   148  	}
   149  
   150  	top.witness.EXPECT().StartCheck(gomock.Any(), gomock.Any(), gomock.Any()).Times(1).DoAndReturn(func(r validators.Resource, f func(interface{}, bool), _ time.Time) error {
   151  		return nil
   152  	})
   153  
   154  	assert.NoError(t, top.ProcessSignerEvent(&signerEvent2))
   155  
   156  	// now we can make a checkpoint and load it.
   157  	// here we expect the following:
   158  	// threshold set to 666
   159  	// 1 validator
   160  	// block set to the most recent pending
   161  
   162  	cp, err := top.Checkpoint()
   163  	assert.NoError(t, err)
   164  	assert.True(t, len(cp) > 0)
   165  
   166  	top2 := getTestTopology(t)
   167  	top2.ocv.EXPECT().GetMultiSigAddress().AnyTimes()
   168  	top2.ethEventSource.EXPECT().UpdateContractBlock(gomock.Any(), gomock.Any(), gomock.Any()).AnyTimes()
   169  
   170  	top2.broker.EXPECT().Send(gomock.Any()).Times(2)
   171  	require.NoError(t, top2.Load(context.Background(), cp))
   172  
   173  	// no assert state is restored correctly
   174  	assert.Equal(t, int(top2.GetThreshold()), 666)
   175  	signers := top2.GetSigners()
   176  	assert.Len(t, signers, 1)
   177  	assert.Equal(t, signers[0], "0xe82EfC4187705655C9b484dFFA25f240e8A6B0BA")
   178  }