code.vegaprotocol.io/vega@v0.79.0/core/validators/topology_snapshot_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 validators_test 17 18 import ( 19 "bytes" 20 "context" 21 "encoding/hex" 22 "testing" 23 24 "code.vegaprotocol.io/vega/core/types" 25 "code.vegaprotocol.io/vega/core/validators" 26 vegactx "code.vegaprotocol.io/vega/libs/context" 27 "code.vegaprotocol.io/vega/libs/proto" 28 commandspb "code.vegaprotocol.io/vega/protos/vega/commands/v1" 29 snapshot "code.vegaprotocol.io/vega/protos/vega/snapshot/v1" 30 31 "github.com/golang/mock/gomock" 32 "github.com/stretchr/testify/assert" 33 "github.com/stretchr/testify/require" 34 ) 35 36 var topKey = (&types.PayloadTopology{}).Key() 37 38 func TestEmptySnapshot(t *testing.T) { 39 top := getTestTopology(t) 40 defer top.ctrl.Finish() 41 42 s, p, err := top.GetState(topKey) 43 assert.Nil(t, err) 44 assert.Empty(t, p) 45 assert.NotEmpty(t, s) 46 47 assert.Equal(t, 1, len(top.Keys())) 48 } 49 50 func TestChangeOnValidatorPerfUpdate(t *testing.T) { 51 top := getTestTopology(t) 52 defer top.ctrl.Finish() 53 top.timeService.EXPECT().GetTimeNow().AnyTimes() 54 55 s, _, err := top.GetState(topKey) 56 assert.Nil(t, err) 57 assert.NotEmpty(t, s) 58 59 updateValidatorPerformanceToNonDefaultState(t, top.Topology) 60 61 s2, _, err := top.GetState(topKey) 62 assert.Nil(t, err) 63 assert.NotEmpty(t, s2) 64 require.False(t, bytes.Equal(s, s2)) 65 } 66 67 func TestTopologySnapshot(t *testing.T) { 68 top := getTestTopWithMockedSignatures(t) 69 defer top.ctrl.Finish() 70 top.timeService.EXPECT().GetTimeNow().AnyTimes() 71 72 top.signatures.EXPECT().PrepareValidatorSignatures(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).AnyTimes() 73 top.signatures.EXPECT().SetNonce(gomock.Any()).Times(2) 74 top.signatures.EXPECT().ClearStaleSignatures().Times(2) 75 top.signatures.EXPECT().SerialisePendingSignatures().Times(1) 76 updateValidatorPerformanceToNonDefaultState(t, top.Topology) 77 s1, _, err := top.GetState(topKey) 78 require.Nil(t, err) 79 80 tmPubKeys := []string{"2w5hxsVqWFTV6/f0swyNVqOhY1vWI42MrfO0xkUqsiA=", "67g7+123M0kfMR35U7LLq09eEU1dVr6jHBEgEtPzkrs="} 81 ctx := context.Background() 82 83 nr1 := commandspb.AnnounceNode{ 84 Id: "vega-master-pubkey", 85 ChainPubKey: tmPubKeys[0], 86 VegaPubKey: hexEncode("vega-key"), 87 EthereumAddress: "0x6d53C489bbda35B8096C8b4Cb362e2889F82E19B", 88 SubmitterAddress: "0x6d53C489bbda35B8096C8b4Cb362e2889F82E19B", 89 } 90 err = top.AddNewNode(ctx, &nr1, validators.ValidatorStatusTendermint) 91 assert.NoError(t, err) 92 nr2 := commandspb.AnnounceNode{ 93 Id: "vega-master-pubkey-2", 94 ChainPubKey: tmPubKeys[1], 95 VegaPubKey: hexEncode("vega-key-2"), 96 EthereumAddress: "0x6d53C489bbda35B8096C8b4Cb362e2889F82E19B", 97 } 98 err = top.AddNewNode(ctx, &nr2, validators.ValidatorStatusTendermint) 99 assert.NoError(t, err) 100 101 kr1 := &commandspb.KeyRotateSubmission{ 102 NewPubKeyIndex: 1, 103 TargetBlock: 10, 104 NewPubKey: "new-vega-key", 105 CurrentPubKeyHash: hashKey("vega-key"), 106 } 107 108 err = top.AddKeyRotate(ctx, nr1.Id, 5, kr1) 109 assert.NoError(t, err) 110 111 kr2 := &commandspb.KeyRotateSubmission{ 112 NewPubKeyIndex: 1, 113 TargetBlock: 11, 114 NewPubKey: "new-vega-key-2", 115 CurrentPubKeyHash: hashKey("vega-key-2"), 116 } 117 err = top.AddKeyRotate(ctx, nr2.Id, 5, kr2) 118 assert.NoError(t, err) 119 ekr1 := newEthereumKeyRotationSubmission("0x6d53C489bbda35B8096C8b4Cb362e2889F82E19B", "0x69bA3B3e6B5b1226A2e26De9a9E2D9C98f2b144B", 10, "") 120 err = top.ProcessEthereumKeyRotation(ctx, hexEncode("vega-key"), ekr1, MockVerify) 121 assert.NoError(t, err) 122 123 ekr2 := newEthereumKeyRotationSubmission("0x6d53C489bbda35B8096C8b4Cb362e2889F82E19B", "0xd6B6e9514f2793Af89745Fd69FDa0DAbC228d336", 11, "") 124 err = top.ProcessEthereumKeyRotation(ctx, hexEncode("vega-key-2"), ekr2, MockVerify) 125 assert.NoError(t, err) 126 127 // Check the hashes have changed after each state change 128 top.signatures.EXPECT().SerialisePendingSignatures().Times(1) 129 s3, _, err := top.GetState(topKey) 130 require.Nil(t, err) 131 require.False(t, bytes.Equal(s1, s3)) 132 133 // Get the state ready to load into a new instance of the engine 134 top.signatures.EXPECT().SerialisePendingSignatures().Times(1) 135 state, _, _ := top.GetState(topKey) 136 snap := &snapshot.Payload{} 137 err = proto.Unmarshal(state, snap) 138 require.Nil(t, err) 139 140 snapTop := getTestTopWithMockedSignatures(t) 141 defer snapTop.ctrl.Finish() 142 snapTop.timeService.EXPECT().GetTimeNow().AnyTimes() 143 snapTop.signatures.EXPECT().SetNonce(gomock.Any()).Times(1) 144 snapTop.signatures.EXPECT().RestorePendingSignatures(gomock.Any()).Times(1) 145 146 ctx = vegactx.WithBlockHeight(ctx, 100) 147 _, err = snapTop.LoadState(ctx, types.PayloadFromProto(snap)) 148 require.Nil(t, err) 149 150 // Check the new reloaded engine is the same as the original 151 snapTop.signatures.EXPECT().SerialisePendingSignatures().Times(1) 152 s4, _, err := snapTop.GetState(topKey) 153 require.Nil(t, err) 154 require.True(t, bytes.Equal(s3, s4)) 155 assert.ElementsMatch(t, top.AllNodeIDs(), snapTop.AllNodeIDs()) 156 assert.ElementsMatch(t, top.AllVegaPubKeys(), snapTop.AllVegaPubKeys()) 157 assert.Equal(t, top.IsValidator(), snapTop.IsValidator()) 158 assert.Equal(t, top.GetPendingKeyRotation(kr1.TargetBlock, nr1.Id), snapTop.GetPendingKeyRotation(kr1.TargetBlock, nr1.Id)) 159 assert.Equal(t, top.GetPendingKeyRotation(kr2.TargetBlock, nr2.Id), snapTop.GetPendingKeyRotation(kr2.TargetBlock, nr2.Id)) 160 assert.Equal(t, top.GetPendingEthereumKeyRotation(ekr1.TargetBlock, nr1.Id), snapTop.GetPendingEthereumKeyRotation(ekr1.TargetBlock, nr1.Id)) 161 assert.Equal(t, top.GetPendingEthereumKeyRotation(ekr2.TargetBlock, nr2.Id), snapTop.GetPendingEthereumKeyRotation(ekr2.TargetBlock, nr2.Id)) 162 } 163 164 func updateValidatorPerformanceToNonDefaultState(t *testing.T, top *validators.Topology) { 165 t.Helper() 166 top.BeginBlock(context.Background(), 1, hex.EncodeToString(address1)) 167 168 // expecting address1 to propose but got address3 169 top.BeginBlock(context.Background(), 1, hex.EncodeToString(address3)) 170 }