code.vegaprotocol.io/vega@v0.79.0/core/staking/stake_verifier_snapshot.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 17 18 import ( 19 "context" 20 21 "code.vegaprotocol.io/vega/core/events" 22 "code.vegaprotocol.io/vega/core/types" 23 "code.vegaprotocol.io/vega/libs/proto" 24 "code.vegaprotocol.io/vega/logging" 25 ) 26 27 var ( 28 depositedKey = (&types.PayloadStakeVerifierDeposited{}).Key() 29 removedKey = (&types.PayloadStakeVerifierRemoved{}).Key() 30 31 hashKeys = []string{ 32 depositedKey, 33 removedKey, 34 } 35 ) 36 37 type stakeVerifierSnapshotState struct { 38 serialisedDeposited []byte 39 serialisedRemoved []byte 40 } 41 42 func (s *StakeVerifier) serialisePendingSD() ([]byte, error) { 43 s.log.Info("serialising pending SD", logging.Int("n", len(s.pendingSDs))) 44 deposited := make([]*types.StakeDeposited, 0, len(s.pendingSDs)) 45 46 for _, p := range s.pendingSDs { 47 deposited = append(deposited, p.StakeDeposited) 48 } 49 50 pl := types.Payload{ 51 Data: &types.PayloadStakeVerifierDeposited{ 52 StakeVerifierDeposited: deposited, 53 }, 54 } 55 return proto.Marshal(pl.IntoProto()) 56 } 57 58 func (s *StakeVerifier) serialisePendingSR() ([]byte, error) { 59 s.log.Info("serialising pending SR", logging.Int("n", len(s.pendingSRs))) 60 removed := make([]*types.StakeRemoved, 0, len(s.pendingSRs)) 61 62 for _, p := range s.pendingSRs { 63 removed = append(removed, p.StakeRemoved) 64 } 65 66 pl := types.Payload{ 67 Data: &types.PayloadStakeVerifierRemoved{ 68 StakeVerifierRemoved: removed, 69 }, 70 } 71 72 return proto.Marshal(pl.IntoProto()) 73 } 74 75 func (s *StakeVerifier) serialiseK(serialFunc func() ([]byte, error), dataField *[]byte) ([]byte, error) { 76 data, err := serialFunc() 77 if err != nil { 78 return nil, err 79 } 80 *dataField = data 81 return data, nil 82 } 83 84 // get the serialised form and hash of the given key. 85 func (s *StakeVerifier) serialise(k string) ([]byte, error) { 86 switch k { 87 case depositedKey: 88 return s.serialiseK(s.serialisePendingSD, &s.svss.serialisedDeposited) 89 case removedKey: 90 return s.serialiseK(s.serialisePendingSR, &s.svss.serialisedRemoved) 91 default: 92 return nil, types.ErrSnapshotKeyDoesNotExist 93 } 94 } 95 96 func (s *StakeVerifier) Namespace() types.SnapshotNamespace { 97 return types.StakeVerifierSnapshot 98 } 99 100 func (s *StakeVerifier) Keys() []string { 101 return hashKeys 102 } 103 104 func (s *StakeVerifier) Stopped() bool { 105 return false 106 } 107 108 func (s *StakeVerifier) GetState(k string) ([]byte, []types.StateProvider, error) { 109 data, err := s.serialise(k) 110 return data, nil, err 111 } 112 113 func (s *StakeVerifier) LoadState(ctx context.Context, payload *types.Payload) ([]types.StateProvider, error) { 114 if s.Namespace() != payload.Data.Namespace() { 115 return nil, types.ErrInvalidSnapshotNamespace 116 } 117 118 switch pl := payload.Data.(type) { 119 case *types.PayloadStakeVerifierDeposited: 120 return nil, s.restorePendingSD(ctx, pl.StakeVerifierDeposited, payload) 121 case *types.PayloadStakeVerifierRemoved: 122 return nil, s.restorePendingSR(ctx, pl.StakeVerifierRemoved, payload) 123 default: 124 return nil, types.ErrUnknownSnapshotType 125 } 126 } 127 128 func (s *StakeVerifier) restorePendingSD(ctx context.Context, deposited []*types.StakeDeposited, p *types.Payload) error { 129 s.log.Debug("restoring pendingSDs snapshot", logging.Int("n_pending", len(deposited))) 130 s.pendingSDs = make([]*pendingSD, 0, len(deposited)) 131 evts := []events.Event{} 132 for _, d := range deposited { 133 // this populates the id/hash structs 134 if !s.ensureNotDuplicate(d.ID, d.IntoStakeLinking().Hash()) { 135 s.log.Panic("pendingSD's unexpectedly pre-populated when restoring from snapshot") 136 } 137 138 pending := &pendingSD{ 139 StakeDeposited: d, 140 chainID: s.accs.chainID, 141 check: func() error { return s.ocv.CheckStakeDeposited(d) }, 142 } 143 144 s.pendingSDs = append(s.pendingSDs, pending) 145 s.log.Debug("restoring witness resource") 146 if err := s.witness.RestoreResource(pending, s.onEventVerified); err != nil { 147 s.log.Panic("unable to restore pending stake deposited resource", logging.String("id", pending.ID), logging.Error(err)) 148 } 149 evts = append(evts, events.NewStakeLinking(ctx, *pending.IntoStakeLinking())) 150 } 151 var err error 152 s.svss.serialisedDeposited, err = proto.Marshal(p.IntoProto()) 153 s.broker.SendBatch(evts) 154 155 // now populate "seen" map with finalised events from accounting 156 for _, acc := range s.accs.hashableAccounts { 157 for _, evt := range acc.Events { 158 sl := types.StakeLinkingFromProto(evt.IntoProto()) 159 if !s.ensureNotDuplicate(sl.ID, sl.Hash()) { 160 s.log.Panic("finalised events unexpectedly pre-populated when restoring from snapshot") 161 } 162 } 163 } 164 165 return err 166 } 167 168 func (s *StakeVerifier) OnStateLoaded(ctx context.Context) error { 169 // tell the internal EEF where it got up to so we do not resend events we're already seen 170 lastBlockSeen := s.getLastBlockSeen() 171 if lastBlockSeen == 0 { 172 lastBlockSeen = s.accs.getLastBlockSeen() 173 } 174 if lastBlockSeen != 0 { 175 s.log.Info("restoring staking bridge starting block", logging.Uint64("block", lastBlockSeen)) 176 // s.ethEventSource.UpdateStakingStartingBlock(lastBlockSeen) 177 } 178 return nil 179 } 180 181 func (s *StakeVerifier) restorePendingSR(ctx context.Context, removed []*types.StakeRemoved, p *types.Payload) error { 182 s.log.Debug("restoring pendingSRs snapshot", logging.Int("n_pending", len(removed))) 183 s.pendingSRs = make([]*pendingSR, 0, len(removed)) 184 evts := []events.Event{} 185 for _, r := range removed { 186 // this populates the id/hash structs 187 if !s.ensureNotDuplicate(r.ID, r.IntoStakeLinking().Hash()) { 188 s.log.Panic("pendingSR's unexpectedly pre-populated when restoring from snapshot") 189 } 190 191 pending := &pendingSR{ 192 StakeRemoved: r, 193 chainID: s.accs.chainID, 194 check: func() error { return s.ocv.CheckStakeRemoved(r) }, 195 } 196 197 s.pendingSRs = append(s.pendingSRs, pending) 198 if err := s.witness.RestoreResource(pending, s.onEventVerified); err != nil { 199 s.log.Panic("unable to restore pending stake removed resource", logging.String("id", pending.ID), logging.Error(err)) 200 } 201 evts = append(evts, events.NewStakeLinking(ctx, *pending.IntoStakeLinking())) 202 } 203 204 var err error 205 s.svss.serialisedRemoved, err = proto.Marshal(p.IntoProto()) 206 s.broker.SendBatch(evts) 207 return err 208 }