code.vegaprotocol.io/vega@v0.79.0/core/assets/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 assets 17 18 import ( 19 "context" 20 21 "code.vegaprotocol.io/vega/core/types" 22 vgcontext "code.vegaprotocol.io/vega/libs/context" 23 "code.vegaprotocol.io/vega/libs/proto" 24 "code.vegaprotocol.io/vega/logging" 25 ) 26 27 var ( 28 activeKey = (&types.PayloadActiveAssets{}).Key() 29 pendingKey = (&types.PayloadPendingAssets{}).Key() 30 pendingUpdatesKey = (&types.PayloadPendingAssetUpdates{}).Key() 31 32 hashKeys = []string{ 33 activeKey, 34 pendingKey, 35 pendingUpdatesKey, 36 } 37 ) 38 39 type assetsSnapshotState struct { 40 serialisedActive []byte 41 serialisedPending []byte 42 serialisedPendingUpdates []byte 43 } 44 45 func (s *Service) Namespace() types.SnapshotNamespace { 46 return types.AssetsSnapshot 47 } 48 49 func (s *Service) Keys() []string { 50 return hashKeys 51 } 52 53 func (s *Service) Stopped() bool { 54 return false 55 } 56 57 func (s *Service) serialiseActive() ([]byte, error) { 58 enabled := s.GetEnabledAssets() 59 payload := types.Payload{ 60 Data: &types.PayloadActiveAssets{ 61 ActiveAssets: &types.ActiveAssets{ 62 Assets: enabled, 63 }, 64 }, 65 } 66 return proto.Marshal(payload.IntoProto()) 67 } 68 69 func (s *Service) serialisePending() ([]byte, error) { 70 pending := s.getPendingAssets() 71 payload := types.Payload{ 72 Data: &types.PayloadPendingAssets{ 73 PendingAssets: &types.PendingAssets{ 74 Assets: pending, 75 }, 76 }, 77 } 78 79 return proto.Marshal(payload.IntoProto()) 80 } 81 82 func (s *Service) serialisePendingUpdates() ([]byte, error) { 83 pendingUpdates := s.getPendingAssetUpdates() 84 payload := types.Payload{ 85 Data: &types.PayloadPendingAssetUpdates{ 86 PendingAssetUpdates: &types.PendingAssetUpdates{ 87 Assets: pendingUpdates, 88 }, 89 }, 90 } 91 92 return proto.Marshal(payload.IntoProto()) 93 } 94 95 func (s *Service) serialiseK(serialFunc func() ([]byte, error), dataField *[]byte) ([]byte, error) { 96 data, err := serialFunc() 97 if err != nil { 98 return nil, err 99 } 100 *dataField = data 101 return data, nil 102 } 103 104 func (s *Service) serialise(k string) ([]byte, error) { 105 switch k { 106 case activeKey: 107 return s.serialiseK(s.serialiseActive, &s.ass.serialisedActive) 108 case pendingKey: 109 return s.serialiseK(s.serialisePending, &s.ass.serialisedPending) 110 case pendingUpdatesKey: 111 return s.serialiseK(s.serialisePendingUpdates, &s.ass.serialisedPendingUpdates) 112 default: 113 return nil, types.ErrSnapshotKeyDoesNotExist 114 } 115 } 116 117 func (s *Service) GetState(k string) ([]byte, []types.StateProvider, error) { 118 state, err := s.serialise(k) 119 return state, nil, err 120 } 121 122 func (s *Service) LoadState(ctx context.Context, p *types.Payload) ([]types.StateProvider, error) { 123 if s.Namespace() != p.Data.Namespace() { 124 return nil, types.ErrInvalidSnapshotNamespace 125 } 126 127 switch pl := p.Data.(type) { 128 case *types.PayloadActiveAssets: 129 return nil, s.restoreActive(ctx, pl.ActiveAssets, p) 130 case *types.PayloadPendingAssets: 131 return nil, s.restorePending(ctx, pl.PendingAssets, p) 132 case *types.PayloadPendingAssetUpdates: 133 return nil, s.restorePendingUpdates(ctx, pl.PendingAssetUpdates, p) 134 default: 135 return nil, types.ErrUnknownSnapshotType 136 } 137 } 138 139 func (s *Service) restoreActive(ctx context.Context, active *types.ActiveAssets, p *types.Payload) error { 140 var err error 141 s.assets = map[string]*Asset{} 142 for _, p := range active.Assets { 143 s.applyMigrations(ctx, p) 144 if _, err = s.NewAsset(ctx, p.ID, p.Details); err != nil { 145 return err 146 } 147 148 pa, _ := s.Get(p.ID) 149 150 // at this point asset is always valid because we've loaded from a snapshot and have validated it when it was proposed 151 pa.SetValid() 152 153 if err = s.Enable(ctx, p.ID); err != nil { 154 return err 155 } 156 } 157 s.ass.serialisedActive, err = proto.Marshal(p.IntoProto()) 158 159 return err 160 } 161 162 func (s *Service) restorePending(ctx context.Context, pending *types.PendingAssets, p *types.Payload) error { 163 var err error 164 s.pendingAssets = map[string]*Asset{} 165 for _, p := range pending.Assets { 166 s.applyMigrations(ctx, p) 167 assetID, err := s.NewAsset(ctx, p.ID, p.Details) 168 if err != nil { 169 return err 170 } 171 172 if p.Status == types.AssetStatusPendingListing { 173 s.SetPendingListing(ctx, assetID) 174 } 175 } 176 177 s.ass.serialisedPending, err = proto.Marshal(p.IntoProto()) 178 179 return err 180 } 181 182 func (s *Service) restorePendingUpdates(ctx context.Context, pending *types.PendingAssetUpdates, p *types.Payload) error { 183 var err error 184 s.pendingAssetUpdates = map[string]*Asset{} 185 for _, p := range pending.Assets { 186 s.applyMigrations(ctx, p) 187 if err = s.StageAssetUpdate(p); err != nil { 188 return err 189 } 190 } 191 s.ass.serialisedPendingUpdates, err = proto.Marshal(p.IntoProto()) 192 193 return err 194 } 195 196 func (s *Service) OnStateLoaded(ctx context.Context) error { 197 if !vgcontext.InProgressUpgrade(ctx) || s.isValidator { 198 return nil 199 } 200 201 // note that non-validator nodes do not know the chain-id for the bridges until the network parameters are propagated, but also *validator* nodes need to 202 // restore assets before the network parameters. So for the non-validator nodes only, we have to do the migration to include the chain-id here, after everything 203 // else is restored. 204 s.log.Info("migrating chain-id in existing active assets for non-validator nodes") 205 for k, a := range s.assets { 206 eth, ok := a.ERC20() 207 if !ok || eth.ChainID() != "" { 208 continue 209 } 210 s.log.Info("setting chain-id for active asset", 211 logging.String("asset-id", k), 212 logging.String("chain-id", s.primaryEthChainID), 213 ) 214 eth.SetChainID(s.primaryEthChainID) 215 } 216 217 s.log.Info("migrating chain-id in existing pending assets for non-validator nodes") 218 for k, p := range s.pendingAssets { 219 eth, ok := p.ERC20() 220 if !ok || eth.ChainID() != "" { 221 continue 222 } 223 s.log.Info("setting chain-id for pending asset", 224 logging.String("asset-id", k), 225 logging.String("chain-id", s.primaryEthChainID), 226 ) 227 eth.SetChainID(s.primaryEthChainID) 228 } 229 230 s.log.Info("migrating chain-id in existing update-pending assets for non-validator nodes") 231 for k, pu := range s.pendingAssetUpdates { 232 eth, ok := pu.ERC20() 233 if !ok || eth.ChainID() != "" { 234 continue 235 } 236 s.log.Info("setting chain-id for pending update asset", 237 logging.String("asset-id", k), 238 logging.String("chain-id", s.primaryEthChainID), 239 ) 240 eth.SetChainID(s.primaryEthChainID) 241 } 242 243 return nil 244 } 245 246 func (s *Service) applyMigrations(ctx context.Context, p *types.Asset) { 247 // TODO when we know what versions we are upgrading from we can put in a upgrade from tag 248 if vgcontext.InProgressUpgrade(ctx) && s.isValidator { 249 // Prior the introduction of the second bridge, existing assets did not track 250 // the chain ID they originated from. So, when loaded, assets without a chain 251 // ID are automatically considered to originate from Ethereum Mainnet. 252 if erc20 := p.Details.GetERC20(); erc20 != nil && erc20.ChainID == "" { 253 s.log.Info("migrating chain-id in existin asset for validator nodes", 254 logging.String("asset-id", p.ID), 255 logging.String("chain-id", s.primaryEthChainID), 256 ) 257 erc20.ChainID = s.primaryEthChainID 258 } 259 } 260 }