code.vegaprotocol.io/vega@v0.79.0/core/validators/erc20multisig/topology_snapshot_state.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 17 18 import ( 19 "context" 20 "sort" 21 22 "code.vegaprotocol.io/vega/core/types" 23 vgcontext "code.vegaprotocol.io/vega/libs/context" 24 "code.vegaprotocol.io/vega/libs/proto" 25 "code.vegaprotocol.io/vega/logging" 26 eventspb "code.vegaprotocol.io/vega/protos/vega/events/v1" 27 snapshotpb "code.vegaprotocol.io/vega/protos/vega/snapshot/v1" 28 ) 29 30 var ( 31 verifiedStateKey = (&types.PayloadERC20MultiSigTopologyVerified{}).Key() 32 pendingStateKey = (&types.PayloadERC20MultiSigTopologyPending{}).Key() 33 34 hashKeys = []string{ 35 verifiedStateKey, 36 pendingStateKey, 37 } 38 ) 39 40 func (t *Topology) Namespace() types.SnapshotNamespace { 41 return types.ERC20MultiSigTopologySnapshot 42 } 43 44 func (t *Topology) Keys() []string { 45 return hashKeys 46 } 47 48 func (t *Topology) GetState(k string) ([]byte, []types.StateProvider, error) { 49 data, err := t.serialise(k) 50 return data, nil, err 51 } 52 53 func (t *Topology) Stopped() bool { 54 return false 55 } 56 57 func (t *Topology) LoadState(ctx context.Context, payload *types.Payload) ([]types.StateProvider, error) { 58 if t.Namespace() != payload.Data.Namespace() { 59 return nil, types.ErrInvalidSnapshotNamespace 60 } 61 62 switch pl := payload.Data.(type) { 63 case *types.PayloadERC20MultiSigTopologyVerified: 64 return nil, t.restoreVerifiedState(ctx, pl.Verified) 65 case *types.PayloadERC20MultiSigTopologyPending: 66 return nil, t.restorePendingState(ctx, pl.Pending) 67 default: 68 return nil, types.ErrUnknownSnapshotType 69 } 70 } 71 72 func (t *Topology) restoreVerifiedState( 73 ctx context.Context, s *snapshotpb.ERC20MultiSigTopologyVerified, 74 ) error { 75 t.log.Debug("restoring snapshot verified state") 76 if s.Threshold != nil { 77 t.log.Debug("restoring threshold") 78 t.threshold = types.SignerThresholdSetEventFromEventProto(s.Threshold) 79 } 80 81 t.log.Debug("restoring seen events", logging.Int("n", len(s.SeenEvents))) 82 for _, v := range s.SeenEvents { 83 t.seen[v] = struct{}{} 84 } 85 86 t.log.Debug("restoring signers", logging.Int("n", len(s.Signers))) 87 for _, v := range s.Signers { 88 t.signers[v] = struct{}{} 89 } 90 91 t.log.Debug("restoring events per address", logging.Int("n", len(s.EventsPerAddress))) 92 for _, v := range s.EventsPerAddress { 93 events := make([]*types.SignerEvent, 0, len(v.Events)) 94 for _, e := range v.Events { 95 events = append(events, types.SignerEventFromEventProto(e)) 96 } 97 t.eventsPerAddress[v.Address] = events 98 } 99 100 if vgcontext.InProgressUpgradeFrom(ctx, "v0.76.8") { 101 lastSeen := t.getLastBlockSeen() 102 103 t.log.Info("migration code updating multisig last seen", 104 logging.String("address", t.ocv.GetMultiSigAddress()), 105 logging.Uint64("last-seen", lastSeen), 106 logging.String("chain-id", t.chainID), 107 ) 108 t.ethEventSource.UpdateContractBlock(t.ocv.GetMultiSigAddress(), t.chainID, lastSeen) 109 } 110 111 return nil 112 } 113 114 func (t *Topology) restorePendingState( 115 _ context.Context, s *snapshotpb.ERC20MultiSigTopologyPending, 116 ) error { 117 t.log.Debug("restoring snapshot pending state", logging.String("chain-id", t.chainID)) 118 t.log.Debug("restoring witness signers", logging.Int("n", len(s.WitnessedSigners))) 119 for _, v := range s.WitnessedSigners { 120 t.witnessedSigners[v] = struct{}{} 121 } 122 123 t.log.Debug("restoring witness threshold sets", logging.Int("n", len(s.WitnessedThresholdSets))) 124 for _, v := range s.WitnessedThresholdSets { 125 t.witnessedThresholds[v] = struct{}{} 126 } 127 128 t.log.Debug("restoring pending signers", logging.Int("n", len(s.PendingSigners))) 129 for _, v := range s.PendingSigners { 130 evt := types.SignerEventFromEventProto(v) 131 pending := &pendingSigner{ 132 SignerEvent: evt, 133 check: func() error { return t.ocv.CheckSignerEvent(evt) }, 134 } 135 136 t.pendingSigners[evt.ID] = pending 137 // if we have witnessed it already, 138 if _, ok := t.witnessedSigners[evt.ID]; !ok { 139 if err := t.witness.RestoreResource(pending, t.onEventVerified); err != nil { 140 t.log.Panic("unable to restore pending signer resource", logging.String("id", pending.ID), logging.Error(err)) 141 } 142 } 143 } 144 145 t.log.Debug("restoring pending threshold set", logging.Int("n", len(s.PendingThresholdSet))) 146 for _, v := range s.PendingThresholdSet { 147 evt := types.SignerThresholdSetEventFromEventProto(v) 148 pending := &pendingThresholdSet{ 149 SignerThresholdSetEvent: evt, 150 check: func() error { return t.ocv.CheckThresholdSetEvent(evt) }, 151 } 152 153 t.pendingThresholds[evt.ID] = pending 154 // if we have witnessed it already, 155 if _, ok := t.witnessedThresholds[evt.ID]; !ok { 156 if err := t.witness.RestoreResource(pending, t.onEventVerified); err != nil { 157 t.log.Panic("unable to restore pending threshold resource", logging.String("id", pending.ID), logging.Error(err)) 158 } 159 } 160 } 161 162 return nil 163 } 164 165 func (t *Topology) constructVerifiedState() *snapshotpb.ERC20MultiSigTopologyVerified { 166 out := &snapshotpb.ERC20MultiSigTopologyVerified{} 167 t.log.Debug("serialising snapshot verified state") 168 // first serialise seen events 169 t.log.Debug("serialising seen", logging.Int("n", len(t.seen))) 170 out.SeenEvents = make([]string, 0, len(t.seen)) 171 for k := range t.seen { 172 out.SeenEvents = append(out.SeenEvents, k) 173 } 174 sort.Strings(out.SeenEvents) 175 176 // then the current known list of signers 177 t.log.Debug("serialising signers", logging.Int("n", len(t.signers))) 178 out.Signers = make([]string, 0, len(t.signers)) 179 for k := range t.signers { 180 out.Signers = append(out.Signers, k) 181 } 182 // sort it + reuse it next in the eventsPerAddress 183 sort.Strings(out.Signers) 184 185 evts := make([]*snapshotpb.SignerEventsPerAddress, 0, len(t.eventsPerAddress)) 186 // now the signers events 187 for k, v := range t.eventsPerAddress { 188 events := make([]*eventspb.ERC20MultiSigSignerEvent, 0, len(v)) 189 190 t.log.Debug("serialising events", logging.String("signer", k), logging.Int("n", len(v))) 191 for _, v := range v { 192 events = append(events, v.IntoProto()) 193 } 194 195 evts = append( 196 evts, 197 &snapshotpb.SignerEventsPerAddress{ 198 Address: k, 199 Events: events, 200 }, 201 ) 202 } 203 sort.SliceStable(evts, func(i, j int) bool { return evts[i].Address < evts[j].Address }) 204 out.EventsPerAddress = evts 205 206 // finally do the current threshold 207 if t.threshold != nil { 208 t.log.Debug("serialising threshold") 209 out.Threshold = t.threshold.IntoProto() 210 } 211 212 return out 213 } 214 215 func (t *Topology) serialiseVerifiedState() ([]byte, error) { 216 return proto.Marshal(types.Payload{ 217 Data: &types.PayloadERC20MultiSigTopologyVerified{ 218 Verified: t.constructVerifiedState(), 219 }, 220 }.IntoProto()) 221 } 222 223 func (t *Topology) constructPendingState() *snapshotpb.ERC20MultiSigTopologyPending { 224 t.log.Debug("serialising pending state") 225 out := &snapshotpb.ERC20MultiSigTopologyPending{} 226 227 t.log.Debug("serialising witness signers", logging.Int("n", len(t.witnessedSigners))) 228 out.WitnessedSigners = make([]string, 0, len(t.witnessedSigners)) 229 for k := range t.witnessedSigners { 230 out.WitnessedSigners = append(out.WitnessedSigners, k) 231 } 232 sort.Strings(out.WitnessedSigners) 233 234 t.log.Debug("serialising witness threshold sets", logging.Int("n", len(t.witnessedThresholds))) 235 out.WitnessedThresholdSets = make([]string, 0, len(t.witnessedThresholds)) 236 for k := range t.witnessedThresholds { 237 out.WitnessedThresholdSets = append(out.WitnessedThresholdSets, k) 238 } 239 sort.Strings(out.WitnessedThresholdSets) 240 241 t.log.Debug("serialising pending signers", logging.Int("n", len(t.pendingSigners))) 242 out.PendingSigners = make([]*eventspb.ERC20MultiSigSignerEvent, 0, len(t.pendingSigners)) 243 for _, v := range t.pendingSigners { 244 out.PendingSigners = append(out.PendingSigners, v.IntoProto()) 245 } 246 sort.SliceStable(out.PendingSigners, func(i, j int) bool { 247 return out.PendingSigners[i].Id < out.PendingSigners[j].Id 248 }) 249 250 t.log.Debug("serialising pending thresholds", logging.Int("n", len(t.pendingThresholds))) 251 out.PendingThresholdSet = make([]*eventspb.ERC20MultiSigThresholdSetEvent, 0, len(t.pendingThresholds)) 252 for _, v := range t.pendingThresholds { 253 out.PendingThresholdSet = append(out.PendingThresholdSet, v.IntoProto()) 254 } 255 sort.SliceStable(out.PendingThresholdSet, func(i, j int) bool { 256 return out.PendingThresholdSet[i].Id < out.PendingThresholdSet[j].Id 257 }) 258 259 return out 260 } 261 262 func (t *Topology) serialisePendingState() ([]byte, error) { 263 return proto.Marshal(types.Payload{ 264 Data: &types.PayloadERC20MultiSigTopologyPending{ 265 Pending: t.constructPendingState(), 266 }, 267 }.IntoProto()) 268 } 269 270 // get the serialised form of the given key. 271 func (t *Topology) serialise(k string) ([]byte, error) { 272 switch k { 273 case verifiedStateKey: 274 return t.serialiseVerifiedState() 275 case pendingStateKey: 276 return t.serialisePendingState() 277 default: 278 return nil, types.ErrSnapshotKeyDoesNotExist 279 } 280 }