code.vegaprotocol.io/vega@v0.79.0/core/staking/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 staking_test 17 18 import ( 19 "context" 20 "testing" 21 22 "code.vegaprotocol.io/vega/core/staking" 23 "code.vegaprotocol.io/vega/core/staking/mocks" 24 "code.vegaprotocol.io/vega/core/types" 25 "code.vegaprotocol.io/vega/libs/num" 26 "code.vegaprotocol.io/vega/libs/proto" 27 "code.vegaprotocol.io/vega/logging" 28 checkpoint "code.vegaprotocol.io/vega/protos/vega/checkpoint/v1" 29 30 "github.com/golang/mock/gomock" 31 "github.com/stretchr/testify/assert" 32 "github.com/stretchr/testify/require" 33 34 _ "embed" 35 ) 36 37 //go:embed testcp/20220627071230-316971-11a4d958cb7e0448f0cea0b7c617a1e4535e90c0d0f18fd86e961c97147757d7.cp 38 var cpFile []byte 39 40 type checkpointTest struct { 41 *staking.Checkpoint 42 sv *stakeVerifierTest 43 acc *accountingTest 44 45 ctrl *gomock.Controller 46 ethEventSource *mocks.MockEthereumEventSource 47 } 48 49 func getCheckpointTest(t *testing.T) *checkpointTest { 50 t.Helper() 51 sv := getStakeVerifierTest(t) 52 acc := getAccountingTest(t) 53 54 ctrl := gomock.NewController(t) 55 ethEventSource := mocks.NewMockEthereumEventSource(ctrl) 56 57 return &checkpointTest{ 58 Checkpoint: staking.NewCheckpoint( 59 logging.NewTestLogger(), 60 acc.Accounting, 61 sv.StakeVerifier, 62 ethEventSource, 63 ), 64 sv: sv, 65 acc: acc, 66 ctrl: ctrl, 67 ethEventSource: ethEventSource, 68 } 69 } 70 71 func (c *checkpointTest) Finish() { 72 c.ctrl.Finish() 73 c.sv.ctrl.Finish() 74 } 75 76 // TestCheckpointLoadNoDuplicates is testing that with the recent changes 77 // balance on mainnet are reconciled accurately. Due to a bug some eth events 78 // go duplicated and balances became incorrect. The Load call without duplication 79 // for the events would have panicked, this should not. 80 func TestCheckpointLoadNoDuplicates(t *testing.T) { 81 cptest := getCheckpointTest(t) 82 defer cptest.Finish() 83 84 cp := &checkpoint.Checkpoint{} 85 if err := proto.Unmarshal(cpFile, cp); err != nil { 86 t.Fatal(err) 87 } 88 89 cptest.acc.broker.EXPECT().Send(gomock.Any()).AnyTimes() 90 cptest.acc.broker.EXPECT().SendBatch(gomock.Any()).Times(1) 91 cptest.sv.ocv.EXPECT().GetStakingBridgeAddresses().Times(1).Return([]string{"hello"}) 92 cptest.ethEventSource.EXPECT().UpdateContractBlock(gomock.Any(), gomock.Any(), gomock.Any()).Do( 93 func(_, _ string, block uint64) { 94 // ensure we restart at the right block 95 // which is the last pending event we've seen 96 assert.Equal(t, int(block), 15026715) 97 }, 98 ) 99 require.NotPanics(t, func() { cptest.Load(context.Background(), cp.Staking) }) 100 101 // now we ensure the balance which were incorrect are now OK 102 balance, err := cptest.acc.GetAvailableBalance( 103 "657c2a8a5867c43c831e24820b7544e2fdcc1cf610cfe0ece940fe78137400fd") 104 assert.NoError(t, err) 105 assert.Equal(t, balance, num.NewUint(0)) 106 } 107 108 func TestCheckpoint(t *testing.T) { 109 cptest := getCheckpointTest(t) 110 defer cptest.Finish() 111 112 cptest.setupAccounting(t) 113 cptest.setupStakeVerifier(t) 114 115 cp, err := cptest.Checkpoint.Checkpoint() 116 assert.NoError(t, err) 117 assert.True(t, len(cp) > 0) 118 119 cptest2 := getCheckpointTest(t) 120 121 cptest2.acc.broker.EXPECT().Send(gomock.Any()).AnyTimes() 122 cptest2.sv.ocv.EXPECT().GetStakingBridgeAddresses().AnyTimes().Return([]string{"hello"}) 123 cptest2.ethEventSource.EXPECT().UpdateContractBlock(gomock.Any(), gomock.Any(), gomock.Any()).Do( 124 func(_, _ string, block uint64) { 125 // ensure we restart at the right block 126 // which is the last pending event we've seen 127 assert.Equal(t, int(block), 42) 128 }, 129 ) 130 131 cptest2.acc.broker.EXPECT().SendBatch(gomock.Any()).Times(1) 132 assert.NoError(t, cptest2.Load(context.Background(), cp)) 133 134 bal, err := cptest2.acc.GetAvailableBalance(testParty) 135 assert.NoError(t, err) 136 assert.Equal(t, bal, num.NewUint(10)) 137 } 138 139 func (c *checkpointTest) setupAccounting(t *testing.T) { 140 t.Helper() 141 ctx := context.Background() 142 c.acc.broker.EXPECT().Send(gomock.Any()).Times(1) 143 144 evt := &types.StakeLinking{ 145 ID: "someid1", 146 Type: types.StakeLinkingTypeDeposited, 147 TS: 100, 148 Party: testParty, 149 Amount: num.NewUint(10), 150 Status: types.StakeLinkingStatusAccepted, 151 FinalizedAt: 100, 152 TxHash: "0x123456", 153 BlockHeight: 1000, 154 BlockTime: 10, 155 LogIndex: 100, 156 EthereumAddress: "0x123456", 157 } 158 c.acc.AddEvent(ctx, evt) 159 } 160 161 func (c *checkpointTest) setupStakeVerifier(t *testing.T) { 162 t.Helper() 163 c.sv.tsvc.EXPECT().GetTimeNow().Times(1) 164 c.sv.broker.EXPECT().Send(gomock.Any()).Times(1) 165 c.sv.witness.EXPECT().StartCheck(gomock.Any(), gomock.Any(), gomock.Any()).Times(1) 166 167 event := &types.StakeDeposited{ 168 BlockNumber: 42, 169 LogIndex: 1789, 170 TxID: "somehash", 171 ID: "someid", 172 VegaPubKey: "somepubkey", 173 EthereumAddress: "0xnothex", 174 Amount: num.NewUint(1000), 175 BlockTime: 100000, 176 } 177 178 err := c.sv.ProcessStakeDeposited(context.Background(), event) 179 require.Nil(t, err) 180 }