code.vegaprotocol.io/vega@v0.79.0/core/netparams/netparams.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 "errors" 21 "fmt" 22 "sort" 23 "sync" 24 "time" 25 26 "code.vegaprotocol.io/vega/core/events" 27 "code.vegaprotocol.io/vega/libs/num" 28 "code.vegaprotocol.io/vega/logging" 29 30 "golang.org/x/exp/maps" 31 ) 32 33 var ( 34 ErrUnknownKey = errors.New("unknown key") 35 ErrNetworkParameterUpdateDisabledFor = func(key string) error { 36 return fmt.Errorf("network parameter update disabled for %v", key) 37 } 38 ErrNetworkParameterDeprecated = func(key string) error { 39 return fmt.Errorf("network parameter has been deprecated: %v", key) 40 } 41 // a list of network parameter which cannot be updated. 42 updateDisallowed = []string{ 43 BlockchainsPrimaryEthereumConfig, 44 BlockchainsEVMBridgeConfigs, 45 } 46 ) 47 48 // Broker - event bus. 49 type Broker interface { 50 Send(e events.Event) 51 SendBatch(evts []events.Event) 52 } 53 54 type Reset interface { 55 Reset() 56 } 57 58 //nolint:interfacebloat 59 type value interface { 60 Validate(value string) error 61 Update(value string) error 62 UpdateOptionalValidation(value string, validate bool) error 63 String() string 64 ToDecimal() (num.Decimal, error) 65 ToInt() (int64, error) 66 ToUint() (*num.Uint, error) 67 ToBool() (bool, error) 68 ToString() (string, error) 69 ToDuration() (time.Duration, error) 70 ToJSONStruct(Reset) error 71 AddRules(...interface{}) error 72 GetDispatch() func(context.Context, interface{}) error 73 CheckDispatch(interface{}) error 74 } 75 76 type WatchParam struct { 77 Param string 78 // this is to be cast to a function accepting the 79 // inner type of the parameters 80 // e.g: for a String value, the expected function 81 // is to be of the type: func(string) error 82 Watcher interface{} 83 } 84 85 type Store struct { 86 log *logging.Logger 87 cfg Config 88 store map[string]value 89 mu sync.RWMutex 90 broker Broker 91 92 watchers map[string][]WatchParam 93 paramUpdates map[string]struct{} 94 95 checkpointOverwrites map[string]struct{} 96 97 state *snapState 98 99 isProtocolUpgradeRunning bool 100 } 101 102 func New(log *logging.Logger, cfg Config, broker Broker) *Store { 103 log = log.Named(namedLogger) 104 log.SetLevel(cfg.Level.Get()) 105 store := defaultNetParams() 106 return &Store{ 107 log: log, 108 cfg: cfg, 109 store: store, 110 broker: broker, 111 watchers: map[string][]WatchParam{}, 112 paramUpdates: map[string]struct{}{}, 113 checkpointOverwrites: map[string]struct{}{}, 114 state: newSnapState(store), 115 } 116 } 117 118 // UponGenesis load the initial network parameters 119 // from the genesis state. 120 func (s *Store) UponGenesis(ctx context.Context, rawState []byte) (err error) { 121 s.log.Debug("Entering netparams.Store.UponGenesis") 122 defer func() { 123 if err != nil { 124 s.log.Debug("Failure in netparams.Store.UponGenesis", logging.Error(err)) 125 } else { 126 s.log.Debug("Leaving netparams.Store.UponGenesis without error") 127 } 128 }() 129 130 state, err := LoadGenesisState(rawState) 131 if err != nil { 132 s.log.Error("unable to load genesis state", 133 logging.Error(err)) 134 return err 135 } 136 137 evts := make([]events.Event, 0, len(s.store)) 138 keys := maps.Keys(s.store) 139 sort.Strings(keys) 140 // first we going to send the initial state through the broker 141 for _, k := range keys { 142 evts = append(evts, events.NewNetworkParameterEvent(ctx, k, s.store[k].String())) 143 } 144 s.broker.SendBatch(evts) 145 146 // now iterate over all parameters and update the existing ones 147 keys = maps.Keys(state) 148 sort.Strings(keys) 149 for _, k := range keys { 150 if err := s.UpdateOptionalValidation(ctx, k, state[k], false, true); err != nil { 151 return fmt.Errorf("%v: %v", k, err) 152 } 153 } 154 155 // now we are going to iterate over ALL the netparams, 156 // and run validation, so we will know if any was forgotten, 157 // and left to a default which required explicit UponGenesis 158 // through the genesis block 159 for k := range AllKeys { 160 v, err := s.Get(k) 161 if err != nil { 162 return fmt.Errorf("%v: %v", k, err) 163 } 164 if err := s.Validate(k, v); err != nil { 165 return fmt.Errorf("%v: %v", k, err) 166 } 167 } 168 169 // now we can iterate again over ALL the net params, 170 // and dispatch the value of them all so any watchers can get updated 171 // with genesis values 172 keys = maps.Keys(s.store) 173 sort.Strings(keys) 174 for _, k := range keys { 175 if err := s.dispatchUpdate(ctx, k); err != nil { 176 return fmt.Errorf("could not propagate netparams update to listener, %v: %v", k, err) 177 } 178 } 179 180 overwrites, err := LoadGenesisStateOverwrite(rawState) 181 if err != nil { 182 s.log.Error("unable to load genesis state overwrites", 183 logging.Error(err)) 184 return err 185 } 186 187 for _, v := range overwrites { 188 if _, ok := AllKeys[v]; !ok { 189 s.log.Error("unknown network parameter", logging.String("netp", v)) 190 } 191 s.checkpointOverwrites[v] = struct{}{} 192 } 193 194 return nil 195 } 196 197 // Watch a list of parameters updates. 198 func (s *Store) Watch(wp ...WatchParam) error { 199 for _, v := range wp { 200 // type check the function to dispatch updates to 201 if err := s.store[v.Param].CheckDispatch(v.Watcher); err != nil { 202 return fmt.Errorf("%v: %v", v.Param, err) 203 } 204 if watchers, ok := s.watchers[v.Param]; ok { 205 s.watchers[v.Param] = append(watchers, v) 206 } else { 207 s.watchers[v.Param] = []WatchParam{v} 208 } 209 } 210 return nil 211 } 212 213 // dispatch the update of a network parameters to all the listeners. 214 func (s *Store) dispatchUpdate(ctx context.Context, p string) error { 215 val := s.store[p] 216 fn := val.GetDispatch() 217 218 var err error 219 for _, v := range s.watchers[p] { 220 if newerr := fn(ctx, v.Watcher); newerr != nil { 221 if err != nil { 222 err = fmt.Errorf("%v, %w", err, newerr) 223 } else { 224 err = newerr 225 } 226 } 227 } 228 return err 229 } 230 231 func (s *Store) AnyWatchers(p string) bool { 232 return len(s.watchers[p]) > 0 233 } 234 235 // OnTick is trigger once per blocks 236 // we will send parameters update to watchers. 237 func (s *Store) OnTick(ctx context.Context, _ time.Time) { 238 // This is useful only when a protocol upgrade 239 // is running. we will dispatch all new parameter 240 // on the first time update here. 241 // we propagate all parameters update to compensate 242 // for previous release where parameters didn't 243 // get propagated. 244 if s.isProtocolUpgradeRunning { 245 keys := maps.Keys(s.store) 246 sort.Strings(keys) 247 248 for _, k := range keys { 249 s.broker.Send(events.NewNetworkParameterEvent(ctx, k, s.store[k].String())) 250 } 251 252 s.isProtocolUpgradeRunning = false 253 } 254 255 if len(s.paramUpdates) <= 0 { 256 return 257 } 258 259 // sort for deterministic order of processing. 260 params := make([]string, 0, len(s.paramUpdates)) 261 for k := range s.paramUpdates { 262 params = append(params, k) 263 } 264 sort.Strings(params) 265 266 for _, k := range params { 267 if err := s.dispatchUpdate(ctx, k); err != nil { 268 s.log.Debug("unable to dispatch netparams update", logging.Error(err)) 269 } 270 } 271 s.paramUpdates = map[string]struct{}{} 272 } 273 274 func (s *Store) DispatchChanges(ctx context.Context) { 275 if len(s.paramUpdates) <= 0 { 276 return 277 } 278 for k := range s.paramUpdates { 279 if err := s.dispatchUpdate(ctx, k); err != nil { 280 s.log.Debug("unable to dispatch netparams update", logging.Error(err)) 281 } 282 } 283 s.paramUpdates = map[string]struct{}{} 284 } 285 286 // Validate will call validation on the Value stored 287 // for the given key. 288 func (s *Store) Validate(key, value string) error { 289 s.mu.RLock() 290 defer s.mu.RUnlock() 291 svalue, ok := s.store[key] 292 if !ok { 293 return ErrUnknownKey 294 } 295 if err := svalue.Validate(value); err != nil { 296 return fmt.Errorf("unable to validate %s: %w", key, err) 297 } 298 return nil 299 } 300 301 // Update will update the stored value for a given key 302 // will return an error if the value do not pass validation. 303 func (s *Store) Update(ctx context.Context, key, value string) error { 304 return s.UpdateOptionalValidation(ctx, key, value, true, true) 305 } 306 307 func (s *Store) UpdateOptionalValidation(ctx context.Context, key, value string, validate, failIfUnknown bool) error { 308 s.mu.Lock() 309 defer s.mu.Unlock() 310 svalue, ok := s.store[key] 311 if !ok { 312 if failIfUnknown { 313 return ErrUnknownKey 314 } 315 316 s.log.Warn("unknown network parameter", logging.String("key", key)) 317 return nil 318 } 319 320 if err := svalue.UpdateOptionalValidation(value, validate); err != nil { 321 return fmt.Errorf("unable to update %s: %w", key, err) 322 } 323 324 // update was successful we want to notify watchers 325 s.paramUpdates[key] = struct{}{} 326 // and also send it to the broker 327 s.broker.Send(events.NewNetworkParameterEvent(ctx, key, value)) 328 s.state.update(key, value) 329 330 return nil 331 } 332 333 func (s *Store) updateBatch(ctx context.Context, params map[string]string) error { 334 evts := make([]events.Event, 0, len(params)) 335 s.mu.Lock() 336 defer s.mu.Unlock() 337 keys := maps.Keys(params) 338 sort.Strings(keys) 339 for _, k := range keys { 340 v := params[k] 341 svalue, ok := s.store[k] 342 if !ok { 343 s.log.Warn("unknown network parameter read from checkpoint", logging.String("param", k)) 344 continue 345 } 346 if err := svalue.UpdateOptionalValidation(v, false); err != nil { 347 return fmt.Errorf("unable to update %s: %w", k, err) 348 } 349 s.paramUpdates[k] = struct{}{} 350 s.state.update(k, v) 351 evts = append(evts, events.NewNetworkParameterEvent(ctx, k, v)) 352 } 353 s.broker.SendBatch(evts) 354 return nil 355 } 356 357 // Exists check if a value exist for the given key. 358 func (s *Store) Exists(key string) bool { 359 s.mu.RLock() 360 defer s.mu.RUnlock() 361 _, ok := s.store[key] 362 return ok 363 } 364 365 // Get a value associated to the given key. 366 func (s *Store) Get(key string) (string, error) { 367 s.mu.RLock() 368 defer s.mu.RUnlock() 369 svalue, ok := s.store[key] 370 if !ok { 371 return "", ErrUnknownKey 372 } 373 return svalue.String(), nil 374 } 375 376 // GetDecimal a value associated to the given key. 377 func (s *Store) GetDecimal(key string) (num.Decimal, error) { 378 s.mu.RLock() 379 defer s.mu.RUnlock() 380 svalue, ok := s.store[key] 381 if !ok { 382 return num.DecimalZero(), ErrUnknownKey 383 } 384 return svalue.ToDecimal() 385 } 386 387 // GetInt a value associated to the given key. 388 func (s *Store) GetInt(key string) (int64, error) { 389 s.mu.RLock() 390 defer s.mu.RUnlock() 391 svalue, ok := s.store[key] 392 if !ok { 393 return 0, ErrUnknownKey 394 } 395 return svalue.ToInt() 396 } 397 398 // GetUint a value associated to the given key. 399 func (s *Store) GetUint(key string) (*num.Uint, error) { 400 s.mu.RLock() 401 defer s.mu.RUnlock() 402 svalue, ok := s.store[key] 403 if !ok { 404 return num.UintZero(), ErrUnknownKey 405 } 406 v, err := svalue.ToUint() 407 if err != nil { 408 return num.UintZero(), err 409 } 410 return v.Clone(), nil 411 } 412 413 // GetBool a value associated to the given key. 414 func (s *Store) GetBool(key string) (bool, error) { 415 s.mu.RLock() 416 defer s.mu.RUnlock() 417 svalue, ok := s.store[key] 418 if !ok { 419 return false, ErrUnknownKey 420 } 421 return svalue.ToBool() 422 } 423 424 // GetDuration a value associated to the given key. 425 func (s *Store) GetDuration(key string) (time.Duration, error) { 426 s.mu.RLock() 427 defer s.mu.RUnlock() 428 svalue, ok := s.store[key] 429 if !ok { 430 return 0, ErrUnknownKey 431 } 432 return svalue.ToDuration() 433 } 434 435 // GetString a value associated to the given key. 436 func (s *Store) GetString(key string) (string, error) { 437 s.mu.RLock() 438 defer s.mu.RUnlock() 439 svalue, ok := s.store[key] 440 if !ok { 441 return "", ErrUnknownKey 442 } 443 return svalue.ToString() 444 } 445 446 // GetJSONStruct a value associated to the given key. 447 func (s *Store) GetJSONStruct(key string, v Reset) error { 448 s.mu.RLock() 449 defer s.mu.RUnlock() 450 svalue, ok := s.store[key] 451 if !ok { 452 return ErrUnknownKey 453 } 454 return svalue.ToJSONStruct(v) 455 } 456 457 func (s *Store) AddRules(params ...AddParamRules) error { 458 s.mu.RLock() 459 defer s.mu.RUnlock() 460 for _, v := range params { 461 value, ok := s.store[v.Param] 462 if !ok { 463 return ErrUnknownKey 464 } 465 if err := value.AddRules(v.Rules...); err != nil { 466 return err 467 } 468 } 469 return nil 470 } 471 472 func (s *Store) IsUpdateAllowed(key string) error { 473 s.mu.RLock() 474 defer s.mu.RUnlock() 475 _, ok := s.store[key] 476 if !ok { 477 return ErrUnknownKey 478 } 479 480 if _, ok := Deprecated[key]; ok { 481 return ErrNetworkParameterDeprecated(key) 482 } 483 484 for _, v := range updateDisallowed { 485 if v == key { 486 return ErrNetworkParameterUpdateDisabledFor(key) 487 } 488 } 489 490 return nil 491 } 492 493 type AddParamRules struct { 494 Param string 495 Rules []interface{} 496 } 497 498 func ParamStringRules(key string, rules ...StringRule) AddParamRules { 499 irules := []interface{}{} 500 for _, v := range rules { 501 irules = append(irules, v) 502 } 503 return AddParamRules{ 504 Param: key, 505 Rules: irules, 506 } 507 } 508 509 func ParamIntRules(key string, rules ...IntRule) AddParamRules { 510 irules := []interface{}{} 511 for _, v := range rules { 512 irules = append(irules, v) 513 } 514 return AddParamRules{ 515 Param: key, 516 Rules: irules, 517 } 518 } 519 520 func ParamDurationRules(key string, rules ...DurationRule) AddParamRules { 521 irules := []interface{}{} 522 for _, v := range rules { 523 irules = append(irules, v) 524 } 525 return AddParamRules{ 526 Param: key, 527 Rules: irules, 528 } 529 } 530 531 func ParamJSONRules(key string, rules ...JSONRule) AddParamRules { 532 irules := []interface{}{} 533 for _, v := range rules { 534 irules = append(irules, v) 535 } 536 return AddParamRules{ 537 Param: key, 538 Rules: irules, 539 } 540 }