code.vegaprotocol.io/vega@v0.79.0/core/netparams/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 netparams 17 18 import ( 19 "context" 20 "encoding/json" 21 "fmt" 22 "sort" 23 24 "code.vegaprotocol.io/vega/core/types" 25 vgcontext "code.vegaprotocol.io/vega/libs/context" 26 "code.vegaprotocol.io/vega/libs/proto" 27 "code.vegaprotocol.io/vega/logging" 28 vegapb "code.vegaprotocol.io/vega/protos/vega" 29 ) 30 31 type snapState struct { 32 data []byte 33 pl *types.NetParams 34 index map[string]int 35 t *types.PayloadNetParams 36 } 37 38 func newSnapState(store map[string]value) *snapState { 39 state := &snapState{ 40 pl: &types.NetParams{}, 41 index: make(map[string]int, len(store)), 42 t: &types.PayloadNetParams{}, 43 } 44 // set pointer 45 state.t.NetParams = state.pl 46 // set the initial state 47 state.build(store) 48 return state 49 } 50 51 func (s *snapState) build(store map[string]value) { 52 params := make([]*types.NetworkParameter, 0, len(store)) 53 for k, v := range store { 54 params = append(params, &types.NetworkParameter{ 55 Key: k, 56 Value: v.String(), 57 }) 58 } 59 // sort by key 60 sort.SliceStable(params, func(i, j int) bool { 61 return params[i].Key < params[j].Key 62 }) 63 // build the index 64 for i, p := range params { 65 s.index[p.Key] = i 66 } 67 s.pl.Params = params 68 } 69 70 func (s *snapState) Keys() []string { 71 return []string{ 72 s.t.Key(), 73 } 74 } 75 76 func (s *snapState) Namespace() types.SnapshotNamespace { 77 return s.t.Namespace() 78 } 79 80 func (s *snapState) hashState() error { 81 // apparently the payload types can't me marshalled by themselves 82 pl := types.Payload{ 83 Data: s.t, 84 } 85 data, err := proto.Marshal(pl.IntoProto()) 86 if err != nil { 87 return err 88 } 89 s.data = data 90 return nil 91 } 92 93 func (s *snapState) GetState(_ string) ([]byte, error) { 94 if err := s.hashState(); err != nil { 95 return nil, err 96 } 97 return s.data, nil 98 } 99 100 func (s *snapState) update(k, v string) { 101 i, ok := s.index[k] 102 if !ok { 103 i = len(s.pl.Params) 104 s.pl.Params = append(s.pl.Params, &types.NetworkParameter{ 105 Key: k, 106 }) 107 } 108 s.pl.Params[i].Value = v 109 } 110 111 // make Store implement/forward the dataprovider interface 112 113 func (s *Store) Namespace() types.SnapshotNamespace { 114 return s.state.Namespace() 115 } 116 117 func (s *Store) Keys() []string { 118 return s.state.Keys() 119 } 120 121 func (s *Store) Stopped() bool { 122 return false 123 } 124 125 func (s *Store) GetState(k string) ([]byte, []types.StateProvider, error) { 126 state, err := s.state.GetState(k) 127 return state, nil, err 128 } 129 130 func (s *Store) LoadState(ctx context.Context, pl *types.Payload) ([]types.StateProvider, error) { 131 if pl.Namespace() != s.state.Namespace() { 132 return nil, types.ErrInvalidSnapshotNamespace 133 } 134 135 s.isProtocolUpgradeRunning = vgcontext.InProgressUpgrade(ctx) 136 137 np, ok := pl.Data.(*types.PayloadNetParams) 138 if !ok { 139 return nil, types.ErrInconsistentNamespaceKeys // it's the only possible key/namespace combo here 140 } 141 142 for _, kv := range np.NetParams.Params { 143 if err := s.UpdateOptionalValidation(ctx, kv.Key, kv.Value, false, false); err != nil { 144 return nil, err 145 } 146 } 147 148 if vgcontext.InProgressUpgradeFrom(ctx, "v0.76.8") { 149 bridgeConfig := &vegapb.EthereumConfig{} 150 if err := s.GetJSONStruct(BlockchainsPrimaryEthereumConfig, bridgeConfig); err != nil { 151 s.log.Panic("expected ethereum block chain config", logging.Error(err)) 152 } 153 154 // update ethereum config block-time to 12s 155 if bridgeConfig.BlockTime == "" { 156 bridgeConfig.BlockTime = "12s" 157 v, err := json.Marshal(bridgeConfig) 158 if err != nil { 159 s.log.Panic("unable to update ethereum chain block time", logging.Error(err)) 160 } 161 162 if err := s.UpdateOptionalValidation(ctx, BlockchainsPrimaryEthereumConfig, string(v), false, false); err != nil { 163 return nil, err 164 } 165 } 166 } 167 168 // Now they have been loaded, dispatch the changes so that the other engines pick them up 169 for k := range s.store { 170 if err := s.dispatchUpdate(ctx, k); err != nil { 171 return nil, fmt.Errorf("could not propagate netparams update to listener, %v: %v", k, err) 172 } 173 } 174 175 var err error 176 s.state.data, err = proto.Marshal(pl.IntoProto()) 177 s.paramUpdates = map[string]struct{}{} 178 return nil, err 179 }