code.vegaprotocol.io/vega@v0.79.0/core/netparams/checks/checks.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 checks 17 18 import ( 19 "errors" 20 "fmt" 21 "time" 22 23 "code.vegaprotocol.io/vega/libs/num" 24 "code.vegaprotocol.io/vega/logging" 25 types "code.vegaprotocol.io/vega/protos/vega" 26 ) 27 28 type Collateral interface { 29 AssetExists(asset string) bool 30 } 31 32 type Assets interface { 33 IsEnabled(asset string) bool 34 } 35 36 func SpamPoWHashFunction(supportedFunctions []string) func(string) error { 37 return func(name string) error { 38 for _, v := range supportedFunctions { 39 if v == name { 40 return nil 41 } 42 } 43 return errors.New("Spam Proof of Work hash function must be SHA3") 44 } 45 } 46 47 func LongBlockAuctionDurationTable() func(interface{}, interface{}) error { 48 return func(v interface{}, _ interface{}) error { 49 lbadTable, ok := v.(*types.LongBlockAuctionDurationTable) 50 if !ok { 51 return fmt.Errorf("invalid long block auction duration table") 52 } 53 seenThresholds := map[string]struct{}{} 54 for i, tad := range lbadTable.ThresholdAndDuration { 55 thr, err := time.ParseDuration(tad.Threshold) 56 if err != nil { 57 return fmt.Errorf("invalid long block auction duration table - threshold at index %d is not a valid duration", i) 58 } 59 if thr.Nanoseconds() <= 0 { 60 return fmt.Errorf("invalid long block auction duration table - threshold at index %d is not a positive duration", i) 61 } 62 dur, err := time.ParseDuration(tad.Duration) 63 if err != nil { 64 return fmt.Errorf("invalid long block auction duration table - duration at index %d is not a valid duration", i) 65 } 66 if dur.Nanoseconds() <= 0 { 67 return fmt.Errorf("invalid long block auction duration table - duration at index %d is not a positive duration", i) 68 } 69 if dur.Seconds() < 1 { 70 return fmt.Errorf("invalid long block auction duration table - duration at index %d is less than one second", i) 71 } 72 if _, ok := seenThresholds[tad.Threshold]; ok { 73 return fmt.Errorf("invalid long block auction duration table - duplicate threshold") 74 } 75 seenThresholds[tad.Threshold] = struct{}{} 76 } 77 return nil 78 } 79 } 80 81 func MarginScalingFactor() func(interface{}, interface{}) error { 82 return func(v interface{}, _ interface{}) error { 83 sf := v.(*types.ScalingFactors) 84 if sf.SearchLevel >= sf.InitialMargin || sf.InitialMargin >= sf.CollateralRelease { 85 return errors.New("invalid scaling factors (searchLevel < initialMargin < collateralRelease)") 86 } 87 return nil 88 } 89 } 90 91 func MarginScalingFactorRange(min, max num.Decimal) func(interface{}, interface{}) error { 92 return func(v interface{}, _ interface{}) error { 93 sf := v.(*types.ScalingFactors) 94 if sf.SearchLevel < min.InexactFloat64() || sf.CollateralRelease > max.InexactFloat64() { 95 return errors.New("invalid scaling factors (" + min.String() + "< searchLevel < initialMargin < collateralRelease <=" + max.String() + ")") 96 } 97 return nil 98 } 99 } 100 101 func PriceMonitoringParametersAuctionExtension(min, max time.Duration) func(interface{}, interface{}) error { 102 return func(v interface{}, _ interface{}) error { 103 pmp := v.(*types.PriceMonitoringParameters) 104 for _, pmt := range pmp.Triggers { 105 if time.Duration(pmt.AuctionExtension*int64(time.Second)) < min || time.Duration(pmt.AuctionExtension*int64(time.Second)) > max { 106 return errors.New("invalid AuctionExtension: must be between " + min.String() + " and " + max.String()) 107 } 108 } 109 return nil 110 } 111 } 112 113 func PriceMonitoringParametersHorizon(min, max time.Duration) func(interface{}, interface{}) error { 114 return func(v interface{}, _ interface{}) error { 115 pmp := v.(*types.PriceMonitoringParameters) 116 for _, pmt := range pmp.Triggers { 117 if time.Duration(pmt.Horizon*int64(time.Second)) < min || time.Duration(pmt.Horizon*int64(time.Second)) > max { 118 return errors.New("invalid Horizon: must be between " + min.String() + " and " + max.String()) 119 } 120 } 121 return nil 122 } 123 } 124 125 func PriceMonitoringParametersProbability(min, max num.Decimal) func(interface{}, interface{}) error { 126 return func(v interface{}, _ interface{}) error { 127 pmp := v.(*types.PriceMonitoringParameters) 128 for _, pmt := range pmp.Triggers { 129 p, e := num.DecimalFromString(pmt.Probability) 130 if e != nil { 131 return e 132 } 133 if p.LessThan(min) || p.GreaterThanOrEqual(max) { 134 return errors.New("invalid Probability: must be " + min.String() + " <= x < " + max.String()) 135 } 136 } 137 return nil 138 } 139 } 140 141 func RewardAssetUpdate( 142 log *logging.Logger, 143 assets Assets, 144 collateral Collateral, 145 ) func(value string) error { 146 return func(value string) error { 147 if !assets.IsEnabled(value) { 148 log.Debug("tried to push a reward update with an non-enabled asset", 149 logging.String("asset-id", value)) 150 return fmt.Errorf("invalid asset %v", value) 151 } 152 153 if !collateral.AssetExists(value) { 154 log.Debug("unable to update reward asset in collateral", 155 logging.String("asset-id", value)) 156 return fmt.Errorf("asset does not exists in collateral %v", value) 157 } 158 return nil 159 } 160 }