github.com/TrueBlocks/trueblocks-core/src/apps/chifra@v0.0.0-20241022031540-b362680128f7/pkg/validate/blockvalidate.go (about) 1 // Copyright 2021 The TrueBlocks Authors. All rights reserved. 2 // Use of this source code is governed by a license that can 3 // be found in the LICENSE file. 4 5 package validate 6 7 import ( 8 "errors" 9 "fmt" 10 "strconv" 11 "strings" 12 13 "github.com/TrueBlocks/trueblocks-core/src/apps/chifra/pkg/base" 14 "github.com/TrueBlocks/trueblocks-core/src/apps/chifra/pkg/identifiers" 15 "github.com/TrueBlocks/trueblocks-core/src/apps/chifra/pkg/tslib" 16 "github.com/TrueBlocks/trueblocks-core/src/apps/chifra/pkg/utils" 17 18 "github.com/bykof/gostradamus" 19 ) 20 21 func IsBlockHash(str string) bool { 22 if !strings.HasPrefix(str, "0x") { 23 return false 24 } 25 26 if len(str) != 66 { 27 return false 28 } 29 30 if !base.IsHex(str) { 31 return false 32 } 33 34 return true 35 } 36 37 type blknum_t = uint32 38 39 func IsTimestamp(str string) (bool, blknum_t) { 40 ok, bn := IsBlockNumber(str) 41 if !ok { 42 return false, 0 43 } 44 return bn >= utils.EarliestEvmTs, bn 45 } 46 47 func IsBlockNumber(str string) (bool, blknum_t) { 48 base := 10 49 source := str 50 51 if strings.HasPrefix(str, "0x") { 52 base = 16 53 source = str[2:] 54 } 55 56 value, err := strconv.ParseUint(source, base, 32) 57 if err != nil { 58 return false, 0 59 } 60 61 return true, blknum_t(value) 62 } 63 64 func IsBlockNumberList(strs []string) (bool, []blknum_t) { 65 result := make([]blknum_t, len(strs)) 66 67 for index, stringValue := range strs { 68 check, value := IsBlockNumber(stringValue) 69 if !check { 70 return false, nil 71 } 72 73 result[index] = value 74 } 75 76 return true, result 77 } 78 79 func IsDateTimeString(str string) bool { 80 if strings.Count(str, "-") != 2 { 81 return false 82 } 83 84 bRange, err := identifiers.NewBlockRange(str) 85 if err != nil { 86 return false 87 } 88 return bRange.StartType == identifiers.BlockDate 89 } 90 91 func ToIsoDateStr2(dateStr string) string { 92 // assumes an already validated date string 93 str := strings.Replace(dateStr, "T", " ", -1) 94 if strings.Count(str, ":") == 0 { 95 if strings.Count(str, " ") == 1 { 96 str += ":00:00" 97 } else { 98 str += " 00:00:00" 99 } 100 } else if strings.Count(str, ":") == 1 { 101 str += ":00" 102 } 103 str = strings.Replace(str, " ", "T", -1) 104 str += ".000000" 105 return str 106 } 107 108 func isBeforeFirstBlock(chain, dateStr string) bool { 109 if !IsDateTimeString(dateStr) { 110 return false 111 } 112 113 isoStr := ToIsoDateStr2(dateStr) 114 dt, _ := gostradamus.Parse(isoStr, gostradamus.Iso8601) // already validated as a date 115 firstDate, _ := tslib.FromNameToDate(chain, "0") 116 return dt.Time().Before(firstDate.Time()) 117 } 118 119 func IsRange(chain, str string) (bool, error) { 120 // Disallow "start only ranges" like "1000" or "london" 121 if !strings.Contains(str, "-") { 122 return false, &InvalidIdentifierLiteralError{ 123 Value: str, 124 } 125 } 126 127 bRange, err := identifiers.NewBlockRange(str) 128 129 if err == nil { 130 if bRange.Start.Special == "latest" { 131 return false, errors.New("cannot start range with 'latest'") 132 } 133 134 if bRange.StartType == identifiers.BlockSpecial && 135 !tslib.IsSpecialBlock(chain, bRange.Start.Special) { 136 return false, &InvalidIdentifierLiteralError{ 137 Value: bRange.Start.Special, 138 } 139 } 140 141 if bRange.EndType == identifiers.BlockSpecial && 142 !tslib.IsSpecialBlock(chain, bRange.End.Special) { 143 return false, &InvalidIdentifierLiteralError{ 144 Value: bRange.End.Special, 145 } 146 } 147 148 onlyNumbers := bRange.StartType == identifiers.BlockNumber && 149 bRange.EndType == identifiers.BlockNumber 150 151 if onlyNumbers && bRange.Start.Number >= bRange.End.Number { 152 return false, errors.New("'stop' must be strictly larger than 'start'") 153 } 154 155 return true, nil 156 } 157 158 if modifierErr, ok := err.(*identifiers.WrongModifierError); ok { 159 return false, errors.New("Input argument appears to be invalid. No such skip marker: " + modifierErr.Token) 160 } 161 162 return false, err 163 } 164 165 // Errors returned by ValidateIdentifiers (note: it can also return an 166 // error passed from IsRange) 167 168 var ErrTooManyRanges = errors.New("too many ranges") 169 170 type InvalidIdentifierLiteralError struct { 171 Value string 172 Msg string 173 } 174 175 func (e *InvalidIdentifierLiteralError) Error() string { 176 if len(e.Msg) == 0 { 177 e.Msg = "is not a valid identifier." 178 } 179 return fmt.Sprintf("The given value '%s' %s", e.Value, e.Msg) 180 } 181 182 func IsValidBlockId(chain string, ids []string, validTypes ValidArgumentType) (bool, error) { 183 err := ValidateIdentifiers(chain, ids, validTypes, 1, nil) 184 return err == nil, err 185 }