github.com/igggame/nebulas-go@v2.1.0+incompatible/core/compatibility.go (about) 1 // Copyright (C) 2018 go-nebulas authors 2 // 3 // This file is part of the go-nebulas library. 4 // 5 // the go-nebulas library is free software: you can redistribute it and/or modify 6 // it under the terms of the GNU General Public License as published by 7 // the Free Software Foundation, either version 3 of the License, or 8 // (at your option) any later version. 9 // 10 // the go-nebulas library is distributed in the hope that it will be useful, 11 // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 // GNU General Public License for more details. 14 // 15 // You should have received a copy of the GNU General Public License 16 // along with the go-nebulas library. If not, see <http://www.gnu.org/licenses/>. 17 // 18 19 package core 20 21 import ( 22 "bytes" 23 "errors" 24 "os" 25 "path/filepath" 26 "strconv" 27 "strings" 28 29 "github.com/nebulasio/go-nebulas/util/logging" 30 "github.com/sirupsen/logrus" 31 ) 32 33 const ( 34 // MainNetID mainnet id 35 MainNetID uint32 = 1 36 37 // TestNetID testnet id 38 TestNetID uint32 = 1001 39 ) 40 41 /********** js lib relative BEGIN **********/ 42 const ( 43 // DefaultV8JSLibVersion default version 44 DefaultV8JSLibVersion = "1.0.0" 45 ) 46 47 type version struct { 48 major, minor, patch int 49 } 50 51 // var .. 52 var ( 53 // NOTE: versions should be arranged in ascending order 54 // map[libname][versions] 55 V8JSLibs = map[string][]string{ 56 "execution_env.js": {"1.0.0", "1.0.5"}, 57 "bignumber.js": {"1.0.0"}, 58 "random.js": {"1.0.0", "1.0.5", "1.1.0"}, 59 "date.js": {"1.0.0", "1.0.5"}, 60 "tsc.js": {"1.0.0"}, 61 "util.js": {"1.0.0"}, 62 "esprima.js": {"1.0.0"}, 63 "assert.js": {"1.0.0"}, 64 "instruction_counter.js": {"1.0.0", "1.1.0"}, 65 "typescriptServices.js": {"1.0.0"}, 66 "blockchain.js": {"1.0.0", "1.0.5", "1.1.0"}, 67 "console.js": {"1.0.0"}, 68 "event.js": {"1.0.0"}, 69 "storage.js": {"1.0.0"}, 70 "crypto.js": {"1.0.5"}, 71 "uint.js": {"1.0.5"}, 72 } 73 74 digitalized = make(map[string][]*version) 75 ) 76 77 var ( 78 // ErrInvalidJSLibVersion .. 79 ErrInvalidJSLibVersion = errors.New("invalid js lib version") 80 ) 81 82 /********** js lib relative END **********/ 83 84 // V8JSLibVersionHeightMap key is version in string format, value is height 85 type V8JSLibVersionHeightMap struct { 86 Data map[string]uint64 87 DescKeys []string 88 } 89 90 // GetHeightOfVersion .. 91 func (v *V8JSLibVersionHeightMap) GetHeightOfVersion(version string) uint64 { 92 if r, ok := v.Data[version]; ok { 93 return r 94 } 95 return 0 96 } 97 98 func (v *V8JSLibVersionHeightMap) String() string { 99 var buf bytes.Buffer 100 buf.WriteString("{") 101 for _, ver := range v.DescKeys { 102 if buf.Len() > 1 { 103 buf.WriteString(",") 104 } 105 buf.WriteString(ver + "=" + strconv.FormatUint(v.Data[ver], 10)) 106 } 107 buf.WriteString("}") 108 return buf.String() 109 } 110 111 func (v *V8JSLibVersionHeightMap) validate() { 112 var lastVersion *version 113 for _, key := range v.DescKeys { 114 cur, err := parseVersion(key) 115 if err != nil { 116 logging.VLog().WithFields(logrus.Fields{ 117 "version": key, 118 "err": err, 119 }).Fatal("parse version error.") 120 } 121 122 if lastVersion != nil { 123 if compareVersion(cur, lastVersion) >= 0 || v.Data[key] >= v.Data[lastVersion.String()] { 124 logging.VLog().WithFields(logrus.Fields{ 125 "version": key, 126 "height": v.Data[key], 127 }).Fatal("non descending order version map.") 128 } 129 } 130 131 lastVersion = cur 132 } 133 } 134 135 // Compatibility .. 136 type Compatibility interface { 137 TransferFromContractEventRecordableHeight() uint64 138 AcceptFuncAvailableHeight() uint64 139 RandomAvailableHeight() uint64 140 DateAvailableHeight() uint64 141 RecordCallContractResultHeight() uint64 142 NvmMemoryLimitWithoutInjectHeight() uint64 143 WsResetRecordDependencyHeight() uint64 //reserve address of to 144 V8JSLibVersionControlHeight() uint64 145 TransferFromContractFailureEventRecordableHeight() uint64 146 NewNvmExeTimeoutConsumeGasHeight() uint64 147 NvmExeTimeoutHeight() []uint64 148 V8JSLibVersionHeightMap() *V8JSLibVersionHeightMap 149 NvmGasLimitWithoutTimeoutHeight() uint64 150 WsResetRecordDependencyHeight2() uint64 //reserve change log 151 TransferFromContractFailureEventRecordableHeight2() uint64 152 NvmValueCheckUpdateHeight() uint64 153 NbreAvailableHeight() uint64 154 Nrc20SecurityCheckHeight() uint64 155 NbreSplitHeight() uint64 156 } 157 158 // NebCompatibility .. 159 var NebCompatibility = NewCompatibilityTestNet() 160 161 // SetCompatibilityOptions set compatibility height according to chain_id 162 func SetCompatibilityOptions(chainID uint32) { 163 164 if chainID == MainNetID { 165 NebCompatibility = NewCompatibilityMainNet() 166 } else if chainID == TestNetID { 167 NebCompatibility = NewCompatibilityTestNet() 168 } else { 169 NebCompatibility = NewCompatibilityLocal() 170 } 171 172 logging.VLog().WithFields(logrus.Fields{ 173 "chain_id": chainID, 174 "TransferFromContractEventRecordableHeight": NebCompatibility.TransferFromContractEventRecordableHeight(), 175 "AcceptFuncAvailableHeight": NebCompatibility.AcceptFuncAvailableHeight(), 176 "RandomAvailableHeight": NebCompatibility.RandomAvailableHeight(), 177 "DateAvailableHeight": NebCompatibility.DateAvailableHeight(), 178 "RecordCallContractResultHeight": NebCompatibility.RecordCallContractResultHeight(), 179 "NvmMemoryLimitWithoutInjectHeight": NebCompatibility.NvmMemoryLimitWithoutInjectHeight(), 180 "WsResetRecordDependencyHeight": NebCompatibility.WsResetRecordDependencyHeight(), 181 "WsResetRecordDependencyHeight2": NebCompatibility.WsResetRecordDependencyHeight2(), 182 "V8JSLibVersionControlHeight": NebCompatibility.V8JSLibVersionControlHeight(), 183 "V8JSLibVersionHeightMap": NebCompatibility.V8JSLibVersionHeightMap().String(), 184 "TransferFromContractFailureHeight": NebCompatibility.TransferFromContractFailureEventRecordableHeight(), 185 "TransferFromContractFailureHeight2": NebCompatibility.TransferFromContractFailureEventRecordableHeight2(), 186 "NewNvmExeTimeoutConsumeGasHeight": NebCompatibility.NewNvmExeTimeoutConsumeGasHeight(), 187 "NvmExeTimeoutHeight": NebCompatibility.NvmExeTimeoutHeight(), 188 "NbreAvailableHeight": NebCompatibility.NbreAvailableHeight(), 189 }).Info("Set compatibility options.") 190 191 NebCompatibility.V8JSLibVersionHeightMap().validate() 192 checkJSLib() 193 } 194 195 // FindLastNearestLibVersion .. 196 func FindLastNearestLibVersion(deployVersion, libname string) string { 197 if len(deployVersion) == 0 || len(libname) == 0 { 198 logging.VLog().WithFields(logrus.Fields{ 199 "libname": libname, 200 "deployVersion": deployVersion, 201 }).Error("empty arguments.") 202 return "" 203 } 204 205 if libs, ok := digitalized[libname]; ok { 206 v, err := parseVersion(deployVersion) 207 if err != nil { 208 logging.VLog().WithFields(logrus.Fields{ 209 "err": err, 210 "deployVersion": deployVersion, 211 "lib": libname, 212 }).Debug("parse deploy version error.") 213 return "" 214 } 215 for i := len(libs) - 1; i >= 0; i-- { 216 if compareVersion(libs[i], v) <= 0 { 217 /* 218 logging.VLog().WithFields(logrus.Fields{ 219 "libname": libname, 220 "deployVersion": deployVersion, 221 "return": libs[i], 222 }).Debug("filter js lib.") 223 */ 224 return V8JSLibs[libname][i] 225 } 226 } 227 } else { 228 logging.VLog().WithFields(logrus.Fields{ 229 "libname": libname, 230 "deployVersion": deployVersion, 231 }).Debug("js lib not configured.") 232 } 233 return "" 234 } 235 236 func compareVersion(a, b *version) int { 237 if a.major > b.major { 238 return 1 239 } 240 if a.major < b.major { 241 return -1 242 } 243 244 if a.minor > b.minor { 245 return 1 246 } 247 if a.minor < b.minor { 248 return -1 249 } 250 251 if a.patch > b.patch { 252 return 1 253 } 254 if a.patch < b.patch { 255 return -1 256 } 257 return 0 258 } 259 260 func checkJSLib() { 261 for lib, vers := range V8JSLibs { 262 for _, ver := range vers { 263 p := filepath.Join("lib", ver, lib) 264 fi, err := os.Stat(p) 265 if os.IsNotExist(err) { 266 logging.VLog().WithFields(logrus.Fields{ 267 "path": p, 268 }).Fatal("lib file not exist.") 269 } 270 if fi.IsDir() { 271 logging.VLog().WithFields(logrus.Fields{ 272 "path": p, 273 }).Fatal("directory already exists with the same name.") 274 } 275 276 logging.VLog().WithFields(logrus.Fields{ 277 "path": p, 278 }).Debug("check js lib.") 279 } 280 } 281 } 282 283 func parseVersion(ver string) (*version, error) { 284 ss := strings.Split(ver, ".") 285 if len(ss) != 3 { 286 return nil, ErrInvalidJSLibVersion 287 } 288 289 major, err := strconv.Atoi(ss[0]) 290 if err != nil { 291 return nil, err 292 } 293 294 minor, err := strconv.Atoi(ss[1]) 295 if err != nil { 296 return nil, err 297 } 298 299 patch, err := strconv.Atoi(ss[2]) 300 if err != nil { 301 return nil, err 302 } 303 return &version{major, minor, patch}, nil 304 } 305 306 func (v *version) String() string { 307 return strings.Join([]string{ 308 strconv.Itoa(v.major), 309 strconv.Itoa(v.minor), 310 strconv.Itoa(v.patch), 311 }, ".") 312 } 313 314 // convert V8JSLibs from string to type `version` 315 func init() { 316 for lib, vers := range V8JSLibs { 317 for _, ver := range vers { 318 v, err := parseVersion(ver) 319 if err != nil { 320 logging.VLog().WithFields(logrus.Fields{ 321 "err": err, 322 "lib": lib, 323 "version": ver, 324 }).Fatal("parse js lib version error.") 325 } 326 327 if _, ok := digitalized[lib]; !ok { 328 digitalized[lib] = make([]*version, 0) 329 } 330 digitalized[lib] = append(digitalized[lib], v) 331 } 332 } 333 } 334 335 // GetMaxV8JSLibVersionAtHeight .. 336 func GetMaxV8JSLibVersionAtHeight(blockHeight uint64) string { 337 m := NebCompatibility.V8JSLibVersionHeightMap() 338 for _, v := range m.DescKeys { 339 if blockHeight >= m.Data[v] { 340 return v 341 } 342 } 343 return "" 344 } 345 346 // V8BlockSeedAvailableAtHeight .. 347 func V8BlockSeedAvailableAtHeight(blockHeight uint64) bool { 348 /* For old contract, Blockchain.block.seed should not be disable 349 * return blockHeight >= NebCompatibility.RandomAvailableHeight() && 350 * blockHeight < NebCompatibility.V8JSLibVersionHeightMap().GetHeightOfVersion("1.1.0") 351 */ 352 353 return blockHeight >= NebCompatibility.RandomAvailableHeight() 354 } 355 356 // V8JSLibVersionControlAtHeight .. 357 func V8JSLibVersionControlAtHeight(blockHeight uint64) bool { 358 return blockHeight >= NebCompatibility.V8JSLibVersionControlHeight() 359 } 360 361 // RandomAvailableAtHeight .. 362 func RandomAvailableAtHeight(blockHeight uint64) bool { 363 return blockHeight >= NebCompatibility.RandomAvailableHeight() 364 } 365 366 // DateAvailableAtHeight .. 367 func DateAvailableAtHeight(blockHeight uint64) bool { 368 return blockHeight >= NebCompatibility.DateAvailableHeight() 369 } 370 371 // AcceptAvailableAtHeight .. 372 func AcceptAvailableAtHeight(blockHeight uint64) bool { 373 return blockHeight >= NebCompatibility.AcceptFuncAvailableHeight() 374 } 375 376 // WsResetRecordDependencyAtHeight .. 377 func WsResetRecordDependencyAtHeight(blockHeight uint64) bool { 378 return blockHeight >= NebCompatibility.WsResetRecordDependencyHeight() 379 } 380 381 // WsResetRecordDependencyAtHeight2 .. 382 func WsResetRecordDependencyAtHeight2(blockHeight uint64) bool { 383 return blockHeight >= NebCompatibility.WsResetRecordDependencyHeight2() 384 } 385 386 // RecordCallContractResultAtHeight .. 387 func RecordCallContractResultAtHeight(blockHeight uint64) bool { 388 return blockHeight >= NebCompatibility.RecordCallContractResultHeight() 389 } 390 391 // NvmMemoryLimitWithoutInjectAtHeight .. 392 func NvmMemoryLimitWithoutInjectAtHeight(blockHeight uint64) bool { 393 return blockHeight >= NebCompatibility.NvmMemoryLimitWithoutInjectHeight() 394 } 395 396 // NewNvmExeTimeoutConsumeGasAtHeight .. 397 func NewNvmExeTimeoutConsumeGasAtHeight(blockHeight uint64) bool { 398 return blockHeight >= NebCompatibility.NewNvmExeTimeoutConsumeGasHeight() 399 } 400 401 // TransferFromContractEventRecordableAtHeight .. 402 func TransferFromContractEventRecordableAtHeight(blockHeight uint64) bool { 403 return blockHeight >= NebCompatibility.TransferFromContractEventRecordableHeight() 404 } 405 406 // TransferFromContractFailureEventRecordableAtHeight .. 407 func TransferFromContractFailureEventRecordableAtHeight(blockHeight uint64) bool { 408 return blockHeight >= NebCompatibility.TransferFromContractFailureEventRecordableHeight() 409 } 410 411 // TransferFromContractFailureEventRecordableAtHeight2 .. 412 func TransferFromContractFailureEventRecordableAtHeight2(blockHeight uint64) bool { 413 return blockHeight >= NebCompatibility.TransferFromContractFailureEventRecordableHeight2() 414 } 415 416 // NvmGasLimitWithoutTimeoutAtHeight .. 417 func NvmGasLimitWithoutTimeoutAtHeight(blockHeight uint64) bool { 418 return blockHeight >= NebCompatibility.NvmGasLimitWithoutTimeoutHeight() 419 } 420 421 // NvmExeTimeoutAtHeight .. 422 func NvmExeTimeoutAtHeight(blockHeight uint64) bool { 423 for _, height := range NebCompatibility.NvmExeTimeoutHeight() { 424 if blockHeight == height { 425 return true 426 } 427 } 428 return false 429 } 430 431 // GetNearestInstructionCounterVersionAtHeight .. 432 func GetNearestInstructionCounterVersionAtHeight(blockHeight uint64) string { 433 m := NebCompatibility.V8JSLibVersionHeightMap() 434 for _, v := range m.DescKeys { 435 if v == "1.1.0" && blockHeight >= m.Data[v] { 436 return v 437 } 438 } 439 return "1.0.0" 440 } 441 442 // EnableInnerContractAtHeight .. 443 func EnableInnerContractAtHeight(blockHeight uint64) bool { 444 m := NebCompatibility.V8JSLibVersionHeightMap() 445 return blockHeight >= m.Data["1.1.0"] 446 } 447 448 // NvmValueCheckUpdateHeight .. 449 func NvmValueCheckUpdateHeight(blockHeight uint64) bool { 450 return blockHeight >= NebCompatibility.NvmValueCheckUpdateHeight() 451 } 452 453 // NbreAvailableHeight .. 454 func NbreAvailableHeight(blockHeight uint64) bool { 455 return blockHeight >= NebCompatibility.NbreAvailableHeight() 456 } 457 458 // Nrc20SecurityCheckAtHeight .. 459 func Nrc20SecurityCheckAtHeight(blockHeight uint64) bool { 460 return blockHeight >= NebCompatibility.Nrc20SecurityCheckHeight() 461 } 462 463 // NbreSplitAtHeight .. 464 func NbreSplitAtHeight(blockHeight uint64) bool { 465 return blockHeight >= NebCompatibility.NbreSplitHeight() 466 }