github.1485827954.workers.dev/ethereum/go-ethereum@v1.14.3/common/hexutil/json.go (about) 1 // Copyright 2016 The go-ethereum Authors 2 // This file is part of the go-ethereum library. 3 // 4 // The go-ethereum 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 go-ethereum 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 go-ethereum library. If not, see <http://www.gnu.org/licenses/>. 16 17 package hexutil 18 19 import ( 20 "encoding/hex" 21 "encoding/json" 22 "fmt" 23 "math/big" 24 "reflect" 25 "strconv" 26 27 "github.com/holiman/uint256" 28 ) 29 30 var ( 31 bytesT = reflect.TypeOf(Bytes(nil)) 32 bigT = reflect.TypeOf((*Big)(nil)) 33 uintT = reflect.TypeOf(Uint(0)) 34 uint64T = reflect.TypeOf(Uint64(0)) 35 u256T = reflect.TypeOf((*uint256.Int)(nil)) 36 ) 37 38 // Bytes marshals/unmarshals as a JSON string with 0x prefix. 39 // The empty slice marshals as "0x". 40 type Bytes []byte 41 42 // MarshalText implements encoding.TextMarshaler 43 func (b Bytes) MarshalText() ([]byte, error) { 44 result := make([]byte, len(b)*2+2) 45 copy(result, `0x`) 46 hex.Encode(result[2:], b) 47 return result, nil 48 } 49 50 // UnmarshalJSON implements json.Unmarshaler. 51 func (b *Bytes) UnmarshalJSON(input []byte) error { 52 if !isString(input) { 53 return errNonString(bytesT) 54 } 55 return wrapTypeError(b.UnmarshalText(input[1:len(input)-1]), bytesT) 56 } 57 58 // UnmarshalText implements encoding.TextUnmarshaler. 59 func (b *Bytes) UnmarshalText(input []byte) error { 60 raw, err := checkText(input, true) 61 if err != nil { 62 return err 63 } 64 dec := make([]byte, len(raw)/2) 65 if _, err = hex.Decode(dec, raw); err != nil { 66 err = mapError(err) 67 } else { 68 *b = dec 69 } 70 return err 71 } 72 73 // String returns the hex encoding of b. 74 func (b Bytes) String() string { 75 return Encode(b) 76 } 77 78 // ImplementsGraphQLType returns true if Bytes implements the specified GraphQL type. 79 func (b Bytes) ImplementsGraphQLType(name string) bool { return name == "Bytes" } 80 81 // UnmarshalGraphQL unmarshals the provided GraphQL query data. 82 func (b *Bytes) UnmarshalGraphQL(input interface{}) error { 83 var err error 84 switch input := input.(type) { 85 case string: 86 data, err := Decode(input) 87 if err != nil { 88 return err 89 } 90 *b = data 91 default: 92 err = fmt.Errorf("unexpected type %T for Bytes", input) 93 } 94 return err 95 } 96 97 // UnmarshalFixedJSON decodes the input as a string with 0x prefix. The length of out 98 // determines the required input length. This function is commonly used to implement the 99 // UnmarshalJSON method for fixed-size types. 100 func UnmarshalFixedJSON(typ reflect.Type, input, out []byte) error { 101 if !isString(input) { 102 return errNonString(typ) 103 } 104 return wrapTypeError(UnmarshalFixedText(typ.String(), input[1:len(input)-1], out), typ) 105 } 106 107 // UnmarshalFixedText decodes the input as a string with 0x prefix. The length of out 108 // determines the required input length. This function is commonly used to implement the 109 // UnmarshalText method for fixed-size types. 110 func UnmarshalFixedText(typname string, input, out []byte) error { 111 raw, err := checkText(input, true) 112 if err != nil { 113 return err 114 } 115 if len(raw)/2 != len(out) { 116 return fmt.Errorf("hex string has length %d, want %d for %s", len(raw), len(out)*2, typname) 117 } 118 // Pre-verify syntax before modifying out. 119 for _, b := range raw { 120 if decodeNibble(b) == badNibble { 121 return ErrSyntax 122 } 123 } 124 hex.Decode(out, raw) 125 return nil 126 } 127 128 // UnmarshalFixedUnprefixedText decodes the input as a string with optional 0x prefix. The 129 // length of out determines the required input length. This function is commonly used to 130 // implement the UnmarshalText method for fixed-size types. 131 func UnmarshalFixedUnprefixedText(typname string, input, out []byte) error { 132 raw, err := checkText(input, false) 133 if err != nil { 134 return err 135 } 136 if len(raw)/2 != len(out) { 137 return fmt.Errorf("hex string has length %d, want %d for %s", len(raw), len(out)*2, typname) 138 } 139 // Pre-verify syntax before modifying out. 140 for _, b := range raw { 141 if decodeNibble(b) == badNibble { 142 return ErrSyntax 143 } 144 } 145 hex.Decode(out, raw) 146 return nil 147 } 148 149 // Big marshals/unmarshals as a JSON string with 0x prefix. 150 // The zero value marshals as "0x0". 151 // 152 // Negative integers are not supported at this time. Attempting to marshal them will 153 // return an error. Values larger than 256bits are rejected by Unmarshal but will be 154 // marshaled without error. 155 type Big big.Int 156 157 // MarshalText implements encoding.TextMarshaler 158 func (b Big) MarshalText() ([]byte, error) { 159 return []byte(EncodeBig((*big.Int)(&b))), nil 160 } 161 162 // UnmarshalJSON implements json.Unmarshaler. 163 func (b *Big) UnmarshalJSON(input []byte) error { 164 if !isString(input) { 165 return errNonString(bigT) 166 } 167 return wrapTypeError(b.UnmarshalText(input[1:len(input)-1]), bigT) 168 } 169 170 // UnmarshalText implements encoding.TextUnmarshaler 171 func (b *Big) UnmarshalText(input []byte) error { 172 raw, err := checkNumberText(input) 173 if err != nil { 174 return err 175 } 176 if len(raw) > 64 { 177 return ErrBig256Range 178 } 179 words := make([]big.Word, len(raw)/bigWordNibbles+1) 180 end := len(raw) 181 for i := range words { 182 start := end - bigWordNibbles 183 if start < 0 { 184 start = 0 185 } 186 for ri := start; ri < end; ri++ { 187 nib := decodeNibble(raw[ri]) 188 if nib == badNibble { 189 return ErrSyntax 190 } 191 words[i] *= 16 192 words[i] += big.Word(nib) 193 } 194 end = start 195 } 196 var dec big.Int 197 dec.SetBits(words) 198 *b = (Big)(dec) 199 return nil 200 } 201 202 // ToInt converts b to a big.Int. 203 func (b *Big) ToInt() *big.Int { 204 return (*big.Int)(b) 205 } 206 207 // String returns the hex encoding of b. 208 func (b *Big) String() string { 209 return EncodeBig(b.ToInt()) 210 } 211 212 // ImplementsGraphQLType returns true if Big implements the provided GraphQL type. 213 func (b Big) ImplementsGraphQLType(name string) bool { return name == "BigInt" } 214 215 // UnmarshalGraphQL unmarshals the provided GraphQL query data. 216 func (b *Big) UnmarshalGraphQL(input interface{}) error { 217 var err error 218 switch input := input.(type) { 219 case string: 220 return b.UnmarshalText([]byte(input)) 221 case int32: 222 var num big.Int 223 num.SetInt64(int64(input)) 224 *b = Big(num) 225 default: 226 err = fmt.Errorf("unexpected type %T for BigInt", input) 227 } 228 return err 229 } 230 231 // U256 marshals/unmarshals as a JSON string with 0x prefix. 232 // The zero value marshals as "0x0". 233 type U256 uint256.Int 234 235 // MarshalText implements encoding.TextMarshaler 236 func (b U256) MarshalText() ([]byte, error) { 237 u256 := (*uint256.Int)(&b) 238 return []byte(u256.Hex()), nil 239 } 240 241 // UnmarshalJSON implements json.Unmarshaler. 242 func (b *U256) UnmarshalJSON(input []byte) error { 243 // The uint256.Int.UnmarshalJSON method accepts "dec", "0xhex"; we must be 244 // more strict, hence we check string and invoke SetFromHex directly. 245 if !isString(input) { 246 return errNonString(u256T) 247 } 248 // The hex decoder needs to accept empty string ("") as '0', which uint256.Int 249 // would reject. 250 if len(input) == 2 { 251 (*uint256.Int)(b).Clear() 252 return nil 253 } 254 err := (*uint256.Int)(b).SetFromHex(string(input[1 : len(input)-1])) 255 if err != nil { 256 return &json.UnmarshalTypeError{Value: err.Error(), Type: u256T} 257 } 258 return nil 259 } 260 261 // UnmarshalText implements encoding.TextUnmarshaler 262 func (b *U256) UnmarshalText(input []byte) error { 263 // The uint256.Int.UnmarshalText method accepts "dec", "0xhex"; we must be 264 // more strict, hence we check string and invoke SetFromHex directly. 265 return (*uint256.Int)(b).SetFromHex(string(input)) 266 } 267 268 // String returns the hex encoding of b. 269 func (b *U256) String() string { 270 return (*uint256.Int)(b).Hex() 271 } 272 273 // Uint64 marshals/unmarshals as a JSON string with 0x prefix. 274 // The zero value marshals as "0x0". 275 type Uint64 uint64 276 277 // MarshalText implements encoding.TextMarshaler. 278 func (b Uint64) MarshalText() ([]byte, error) { 279 buf := make([]byte, 2, 10) 280 copy(buf, `0x`) 281 buf = strconv.AppendUint(buf, uint64(b), 16) 282 return buf, nil 283 } 284 285 // UnmarshalJSON implements json.Unmarshaler. 286 func (b *Uint64) UnmarshalJSON(input []byte) error { 287 if !isString(input) { 288 return errNonString(uint64T) 289 } 290 return wrapTypeError(b.UnmarshalText(input[1:len(input)-1]), uint64T) 291 } 292 293 // UnmarshalText implements encoding.TextUnmarshaler 294 func (b *Uint64) UnmarshalText(input []byte) error { 295 raw, err := checkNumberText(input) 296 if err != nil { 297 return err 298 } 299 if len(raw) > 16 { 300 return ErrUint64Range 301 } 302 var dec uint64 303 for _, byte := range raw { 304 nib := decodeNibble(byte) 305 if nib == badNibble { 306 return ErrSyntax 307 } 308 dec *= 16 309 dec += nib 310 } 311 *b = Uint64(dec) 312 return nil 313 } 314 315 // String returns the hex encoding of b. 316 func (b Uint64) String() string { 317 return EncodeUint64(uint64(b)) 318 } 319 320 // ImplementsGraphQLType returns true if Uint64 implements the provided GraphQL type. 321 func (b Uint64) ImplementsGraphQLType(name string) bool { return name == "Long" } 322 323 // UnmarshalGraphQL unmarshals the provided GraphQL query data. 324 func (b *Uint64) UnmarshalGraphQL(input interface{}) error { 325 var err error 326 switch input := input.(type) { 327 case string: 328 return b.UnmarshalText([]byte(input)) 329 case int32: 330 *b = Uint64(input) 331 default: 332 err = fmt.Errorf("unexpected type %T for Long", input) 333 } 334 return err 335 } 336 337 // Uint marshals/unmarshals as a JSON string with 0x prefix. 338 // The zero value marshals as "0x0". 339 type Uint uint 340 341 // MarshalText implements encoding.TextMarshaler. 342 func (b Uint) MarshalText() ([]byte, error) { 343 return Uint64(b).MarshalText() 344 } 345 346 // UnmarshalJSON implements json.Unmarshaler. 347 func (b *Uint) UnmarshalJSON(input []byte) error { 348 if !isString(input) { 349 return errNonString(uintT) 350 } 351 return wrapTypeError(b.UnmarshalText(input[1:len(input)-1]), uintT) 352 } 353 354 // UnmarshalText implements encoding.TextUnmarshaler. 355 func (b *Uint) UnmarshalText(input []byte) error { 356 var u64 Uint64 357 err := u64.UnmarshalText(input) 358 if u64 > Uint64(^uint(0)) || err == ErrUint64Range { 359 return ErrUintRange 360 } else if err != nil { 361 return err 362 } 363 *b = Uint(u64) 364 return nil 365 } 366 367 // String returns the hex encoding of b. 368 func (b Uint) String() string { 369 return EncodeUint64(uint64(b)) 370 } 371 372 func isString(input []byte) bool { 373 return len(input) >= 2 && input[0] == '"' && input[len(input)-1] == '"' 374 } 375 376 func bytesHave0xPrefix(input []byte) bool { 377 return len(input) >= 2 && input[0] == '0' && (input[1] == 'x' || input[1] == 'X') 378 } 379 380 func checkText(input []byte, wantPrefix bool) ([]byte, error) { 381 if len(input) == 0 { 382 return nil, nil // empty strings are allowed 383 } 384 if bytesHave0xPrefix(input) { 385 input = input[2:] 386 } else if wantPrefix { 387 return nil, ErrMissingPrefix 388 } 389 if len(input)%2 != 0 { 390 return nil, ErrOddLength 391 } 392 return input, nil 393 } 394 395 func checkNumberText(input []byte) (raw []byte, err error) { 396 if len(input) == 0 { 397 return nil, nil // empty strings are allowed 398 } 399 if !bytesHave0xPrefix(input) { 400 return nil, ErrMissingPrefix 401 } 402 input = input[2:] 403 if len(input) == 0 { 404 return nil, ErrEmptyNumber 405 } 406 if len(input) > 1 && input[0] == '0' { 407 return nil, ErrLeadingZero 408 } 409 return input, nil 410 } 411 412 func wrapTypeError(err error, typ reflect.Type) error { 413 if _, ok := err.(*decError); ok { 414 return &json.UnmarshalTypeError{Value: err.Error(), Type: typ} 415 } 416 return err 417 } 418 419 func errNonString(typ reflect.Type) error { 420 return &json.UnmarshalTypeError{Value: "non-string", Type: typ} 421 }