github.com/amazechain/amc@v0.1.3/modules/rpc/jsonrpc/util.go (about) 1 // Copyright 2022 The AmazeChain Authors 2 // This file is part of the AmazeChain library. 3 // 4 // The AmazeChain library is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU Lesser General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // The AmazeChain library is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU Lesser General Public License for more details. 13 // 14 // You should have received a copy of the GNU Lesser General Public License 15 // along with the AmazeChain library. If not, see <http://www.gnu.org/licenses/>. 16 17 package jsonrpc 18 19 import ( 20 "encoding/hex" 21 "fmt" 22 "github.com/amazechain/amc/common/types" 23 "strconv" 24 ) 25 26 const uintBits = 32 << (uint64(^uint(0)) >> 63) 27 28 var ( 29 ErrEmptyString = &decError{"empty hex string"} 30 ErrSyntax = &decError{"invalid hex string"} 31 ErrMissingPrefix = &decError{"hex string without 0x prefix"} 32 ErrOddLength = &decError{"hex string of odd length"} 33 ErrEmptyNumber = &decError{"hex string \"0x\""} 34 ErrLeadingZero = &decError{"hex number with leading zero digits"} 35 ErrUint64Range = &decError{"hex number > 64 bits"} 36 ErrUintRange = &decError{fmt.Sprintf("hex number > %d bits", uintBits)} 37 ErrBig256Range = &decError{"hex number > 256 bits"} 38 ) 39 40 const badNibble = ^uint64(0) 41 42 type decError struct{ msg string } 43 44 func (err decError) Error() string { return err.msg } 45 46 func DecodeUint64(input string) (uint64, error) { 47 raw, err := checkNumber(input) 48 if err != nil { 49 return 0, err 50 } 51 dec, err := strconv.ParseUint(raw, 16, 64) 52 if err != nil { 53 err = mapError(err) 54 } 55 return dec, err 56 } 57 58 func mapError(err error) error { 59 if err, ok := err.(*strconv.NumError); ok { 60 switch err.Err { 61 case strconv.ErrRange: 62 return ErrUint64Range 63 case strconv.ErrSyntax: 64 return ErrSyntax 65 } 66 } 67 if _, ok := err.(hex.InvalidByteError); ok { 68 return ErrSyntax 69 } 70 if err == hex.ErrLength { 71 return ErrOddLength 72 } 73 return err 74 } 75 76 func has0xPrefix(input string) bool { 77 return len(input) >= 2 && input[0] == '0' && (input[1] == 'x' || input[1] == 'X') 78 } 79 80 func checkNumber(input string) (raw string, err error) { 81 if len(input) == 0 { 82 return "", ErrEmptyString 83 } 84 if !has0xPrefix(input) { 85 return "", ErrMissingPrefix 86 } 87 input = input[2:] 88 if len(input) == 0 { 89 return "", ErrEmptyNumber 90 } 91 if len(input) > 1 && input[0] == '0' { 92 return "", ErrLeadingZero 93 } 94 return input, nil 95 } 96 97 func bytesHave0xPrefix(input []byte) bool { 98 return len(input) >= 2 && input[0] == '0' && (input[1] == 'x' || input[1] == 'X') 99 } 100 101 func checkText(input []byte, wantPrefix bool) ([]byte, error) { 102 if len(input) == 0 { 103 return nil, nil // empty strings are allowed 104 } 105 if bytesHave0xPrefix(input) { 106 input = input[2:] 107 } else if wantPrefix { 108 return nil, ErrMissingPrefix 109 } 110 if len(input)%2 != 0 { 111 return nil, ErrOddLength 112 } 113 return input, nil 114 } 115 116 func UnmarshalFixedText(typname string, input, out []byte) error { 117 raw, err := checkText(input, true) 118 if err != nil { 119 return err 120 } 121 if len(raw)/2 != len(out) { 122 return fmt.Errorf("hex string has length %d, want %d for %s", len(raw), len(out)*2, typname) 123 } 124 // Pre-verify syntax before modifying out. 125 for _, b := range raw { 126 if decodeNibble(b) == badNibble { 127 return ErrSyntax 128 } 129 } 130 hex.Decode(out, raw) 131 return nil 132 } 133 134 func decodeNibble(in byte) uint64 { 135 switch { 136 case in >= '0' && in <= '9': 137 return uint64(in - '0') 138 case in >= 'A' && in <= 'F': 139 return uint64(in - 'A' + 10) 140 case in >= 'a' && in <= 'f': 141 return uint64(in - 'a' + 10) 142 default: 143 return badNibble 144 } 145 } 146 func UnmarshalText(h types.Hash, input []byte) error { 147 return UnmarshalFixedText("Hash", input, h[:]) 148 } 149 150 func IsTemporaryError(err error) bool { 151 tempErr, ok := err.(interface { 152 Temporary() bool 153 }) 154 return ok && tempErr.Temporary() || isPacketTooBig(err) 155 }