github.com/theQRL/go-zond@v0.2.1/common/types.go (about) 1 // Copyright 2015 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 common 18 19 import ( 20 "bytes" 21 "database/sql/driver" 22 "encoding/hex" 23 "encoding/json" 24 "errors" 25 "fmt" 26 "math/big" 27 "math/rand" 28 "reflect" 29 "strconv" 30 31 "github.com/theQRL/go-zond/common/hexutil" 32 "golang.org/x/crypto/sha3" 33 ) 34 35 // Lengths of hashes and addresses in bytes. 36 const ( 37 // HashLength is the expected length of the hash 38 HashLength = 32 39 // AddressLength is the expected length of the address 40 AddressLength = 20 41 ) 42 43 var ( 44 hashT = reflect.TypeOf(Hash{}) 45 addressT = reflect.TypeOf(Address{}) 46 47 // MaxAddress represents the maximum possible address value. 48 MaxAddress, _ = NewAddressFromString("Zffffffffffffffffffffffffffffffffffffffff") 49 50 // MaxHash represents the maximum possible hash value. 51 MaxHash = HexToHash("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff") 52 53 ErrInvalidAddress = errors.New("invalid address") 54 ) 55 56 // Hash represents the 32 byte Keccak256 hash of arbitrary data. 57 type Hash [HashLength]byte 58 59 // BytesToHash sets b to hash. 60 // If b is larger than len(h), b will be cropped from the left. 61 func BytesToHash(b []byte) Hash { 62 var h Hash 63 h.SetBytes(b) 64 return h 65 } 66 67 // BigToHash sets byte representation of b to hash. 68 // If b is larger than len(h), b will be cropped from the left. 69 func BigToHash(b *big.Int) Hash { return BytesToHash(b.Bytes()) } 70 71 // HexToHash sets byte representation of s to hash. 72 // If b is larger than len(h), b will be cropped from the left. 73 func HexToHash(s string) Hash { return BytesToHash(FromHex(s)) } 74 75 // Cmp compares two hashes. 76 func (h Hash) Cmp(other Hash) int { 77 return bytes.Compare(h[:], other[:]) 78 } 79 80 // Bytes gets the byte representation of the underlying hash. 81 func (h Hash) Bytes() []byte { return h[:] } 82 83 // Big converts a hash to a big integer. 84 func (h Hash) Big() *big.Int { return new(big.Int).SetBytes(h[:]) } 85 86 // Hex converts a hash to a hex string. 87 func (h Hash) Hex() string { return hexutil.Encode(h[:]) } 88 89 // TerminalString implements log.TerminalStringer, formatting a string for console 90 // output during logging. 91 func (h Hash) TerminalString() string { 92 return fmt.Sprintf("%x..%x", h[:3], h[29:]) 93 } 94 95 // String implements the stringer interface and is used also by the logger when 96 // doing full logging into a file. 97 func (h Hash) String() string { 98 return h.Hex() 99 } 100 101 // Format implements fmt.Formatter. 102 // Hash supports the %v, %s, %q, %x, %X and %d format verbs. 103 func (h Hash) Format(s fmt.State, c rune) { 104 hexb := make([]byte, 2+len(h)*2) 105 copy(hexb, "0x") 106 hex.Encode(hexb[2:], h[:]) 107 108 switch c { 109 case 'x', 'X': 110 if !s.Flag('#') { 111 hexb = hexb[2:] 112 } 113 if c == 'X' { 114 hexb = bytes.ToUpper(hexb) 115 } 116 fallthrough 117 case 'v', 's': 118 s.Write(hexb) 119 case 'q': 120 q := []byte{'"'} 121 s.Write(q) 122 s.Write(hexb) 123 s.Write(q) 124 case 'd': 125 fmt.Fprint(s, ([len(h)]byte)(h)) 126 default: 127 fmt.Fprintf(s, "%%!%c(hash=%x)", c, h) 128 } 129 } 130 131 // UnmarshalText parses a hash in hex syntax. 132 func (h *Hash) UnmarshalText(input []byte) error { 133 return hexutil.UnmarshalFixedText("Hash", input, h[:]) 134 } 135 136 // UnmarshalJSON parses a hash in hex syntax. 137 func (h *Hash) UnmarshalJSON(input []byte) error { 138 return hexutil.UnmarshalFixedJSON(hashT, input, h[:]) 139 } 140 141 // MarshalText returns the hex representation of h. 142 func (h Hash) MarshalText() ([]byte, error) { 143 return hexutil.Bytes(h[:]).MarshalText() 144 } 145 146 // SetBytes sets the hash to the value of b. 147 // If b is larger than len(h), b will be cropped from the left. 148 func (h *Hash) SetBytes(b []byte) { 149 if len(b) > len(h) { 150 b = b[len(b)-HashLength:] 151 } 152 153 copy(h[HashLength-len(b):], b) 154 } 155 156 // Generate implements testing/quick.Generator. 157 func (h Hash) Generate(rand *rand.Rand, size int) reflect.Value { 158 m := rand.Intn(len(h)) 159 for i := len(h) - 1; i > m; i-- { 160 h[i] = byte(rand.Uint32()) 161 } 162 return reflect.ValueOf(h) 163 } 164 165 // Scan implements Scanner for database/sql. 166 func (h *Hash) Scan(src interface{}) error { 167 srcB, ok := src.([]byte) 168 if !ok { 169 return fmt.Errorf("can't scan %T into Hash", src) 170 } 171 if len(srcB) != HashLength { 172 return fmt.Errorf("can't scan []byte of len %d into Hash, want %d", len(srcB), HashLength) 173 } 174 copy(h[:], srcB) 175 return nil 176 } 177 178 // Value implements valuer for database/sql. 179 func (h Hash) Value() (driver.Value, error) { 180 return h[:], nil 181 } 182 183 // ImplementsGraphQLType returns true if Hash implements the specified GraphQL type. 184 func (Hash) ImplementsGraphQLType(name string) bool { return name == "Bytes32" } 185 186 // UnmarshalGraphQL unmarshals the provided GraphQL query data. 187 func (h *Hash) UnmarshalGraphQL(input interface{}) error { 188 var err error 189 switch input := input.(type) { 190 case string: 191 err = h.UnmarshalText([]byte(input)) 192 default: 193 err = fmt.Errorf("unexpected type %T for Hash", input) 194 } 195 return err 196 } 197 198 // UnprefixedHash allows marshaling a Hash without 0x prefix. 199 type UnprefixedHash Hash 200 201 // UnmarshalText decodes the hash from hex. The 0x prefix is optional. 202 func (h *UnprefixedHash) UnmarshalText(input []byte) error { 203 return hexutil.UnmarshalFixedUnprefixedText("UnprefixedHash", input, h[:]) 204 } 205 206 // MarshalText encodes the hash as hex. 207 func (h UnprefixedHash) MarshalText() ([]byte, error) { 208 return []byte(hex.EncodeToString(h[:])), nil 209 } 210 211 /////////// Address 212 213 // Address represents the 20 byte address of a Zond account. 214 type Address [AddressLength]byte 215 216 // BytesToAddress returns Address with value b. 217 // If b is larger than len(h), b will be cropped from the left. 218 func BytesToAddress(b []byte) Address { 219 var a Address 220 a.SetBytes(b) 221 return a 222 } 223 224 // BigToAddress returns Address with byte values of b. 225 // If b is larger than len(h), b will be cropped from the left. 226 func BigToAddress(b *big.Int) Address { return BytesToAddress(b.Bytes()) } 227 228 // NewAddressFromString returns Address with byte values of s. 229 func NewAddressFromString(hexaddr string) (Address, error) { 230 if !IsAddress(hexaddr) { 231 return Address{}, ErrInvalidAddress 232 } 233 rawAddr, _ := hex.DecodeString(hexaddr[1:]) 234 return BytesToAddress(rawAddr), nil 235 } 236 237 // IsAddress verifies whether a string can represent a valid hex-encoded 238 // Zond address or not. 239 func IsAddress(s string) bool { 240 if !hasZPrefix(s) { 241 return false 242 } 243 s = s[1:] 244 245 return len(s) == 2*AddressLength && isHex(s) 246 } 247 248 // Cmp compares two addresses. 249 func (a Address) Cmp(other Address) int { 250 return bytes.Compare(a[:], other[:]) 251 } 252 253 // Bytes gets the string representation of the underlying address. 254 func (a Address) Bytes() []byte { return a[:] } 255 256 // Hash converts an address to a hash by left-padding it with zeros. 257 func (a Address) Hash() Hash { return BytesToHash(a[:]) } 258 259 // Big converts an address to a big integer. 260 func (a Address) Big() *big.Int { return new(big.Int).SetBytes(a[:]) } 261 262 // Hex returns an EIP55-compliant hex string representation of the address. 263 func (a Address) Hex() string { 264 return string(a.checksumHex()) 265 } 266 267 // String implements fmt.Stringer. 268 func (a Address) String() string { 269 return a.Hex() 270 } 271 272 func (a *Address) checksumHex() []byte { 273 buf := a.hex() 274 275 // compute checksum 276 sha := sha3.NewLegacyKeccak256() 277 sha.Write(buf[1:]) 278 hash := sha.Sum(nil) 279 for i := 1; i < len(buf); i++ { 280 hashByte := hash[(i-1)/2] 281 if (i+1)%2 == 0 { 282 hashByte = hashByte >> 4 283 } else { 284 hashByte &= 0xf 285 } 286 if buf[i] > '9' && hashByte > 7 { 287 buf[i] -= 32 288 } 289 } 290 return buf[:] 291 } 292 293 func (a Address) hex() []byte { 294 var buf [len(a)*2 + 1]byte 295 copy(buf[:1], hexutil.PrefixZ) 296 hex.Encode(buf[1:], a[:]) 297 return buf[:] 298 } 299 300 // Format implements fmt.Formatter. 301 // Address supports the %v, %s, %q, %x, %X and %d format verbs. 302 func (a Address) Format(s fmt.State, c rune) { 303 switch c { 304 case 'v', 's': 305 s.Write(a.checksumHex()) 306 case 'q': 307 q := []byte{'"'} 308 s.Write(q) 309 s.Write(a.checksumHex()) 310 s.Write(q) 311 case 'x', 'X': 312 // %x disables the checksum. 313 hex := a.hex() 314 if !s.Flag('#') { 315 hex = hex[1:] 316 } 317 if c == 'X' { 318 hex = bytes.ToUpper(hex) 319 } 320 s.Write(hex) 321 case 'd': 322 fmt.Fprint(s, ([len(a)]byte)(a)) 323 default: 324 fmt.Fprintf(s, "%%!%c(address=%x)", c, a) 325 } 326 } 327 328 // SetBytes sets the address to the value of b. 329 // If b is larger than len(a), b will be cropped from the left. 330 func (a *Address) SetBytes(b []byte) { 331 if len(b) > len(a) { 332 b = b[len(b)-AddressLength:] 333 } 334 copy(a[AddressLength-len(b):], b) 335 } 336 337 // MarshalText returns the hex representation of a. 338 func (a Address) MarshalText() ([]byte, error) { 339 return hexutil.BytesZ(a[:]).MarshalText() 340 } 341 342 // UnmarshalText parses a hash in hex syntax. 343 func (a *Address) UnmarshalText(input []byte) error { 344 return hexutil.UnmarshalFixedTextZ("Address", input, a[:]) 345 } 346 347 // UnmarshalJSON parses a address in hex syntax. 348 func (a *Address) UnmarshalJSON(input []byte) error { 349 return hexutil.UnmarshalFixedJSONZ(addressT, input, a[:]) 350 } 351 352 // Scan implements Scanner for database/sql. 353 func (a *Address) Scan(src interface{}) error { 354 srcB, ok := src.([]byte) 355 if !ok { 356 return fmt.Errorf("can't scan %T into Address", src) 357 } 358 if len(srcB) != AddressLength { 359 return fmt.Errorf("can't scan []byte of len %d into Address, want %d", len(srcB), AddressLength) 360 } 361 copy(a[:], srcB) 362 return nil 363 } 364 365 // Value implements valuer for database/sql. 366 func (a Address) Value() (driver.Value, error) { 367 return a[:], nil 368 } 369 370 // ImplementsGraphQLType returns true if Address implements the specified GraphQL type. 371 func (a Address) ImplementsGraphQLType(name string) bool { return name == "Address" } 372 373 // UnmarshalGraphQL unmarshals the provided GraphQL query data. 374 func (a *Address) UnmarshalGraphQL(input interface{}) error { 375 var err error 376 switch input := input.(type) { 377 case string: 378 err = a.UnmarshalText([]byte(input)) 379 default: 380 err = fmt.Errorf("unexpected type %T for Address", input) 381 } 382 return err 383 } 384 385 // MixedcaseAddress retains the original string, which may or may not be 386 // correctly checksummed 387 type MixedcaseAddress struct { 388 addr Address 389 original string 390 } 391 392 // NewMixedcaseAddress constructor (mainly for testing) 393 func NewMixedcaseAddress(addr Address) MixedcaseAddress { 394 return MixedcaseAddress{addr: addr, original: addr.Hex()} 395 } 396 397 // NewMixedcaseAddressFromString is mainly meant for unit-testing 398 func NewMixedcaseAddressFromString(hexaddr string) (*MixedcaseAddress, error) { 399 if !IsAddress(hexaddr) { 400 return nil, ErrInvalidAddress 401 } 402 rawAddr, _ := hex.DecodeString(hexaddr[1:]) 403 return &MixedcaseAddress{addr: BytesToAddress(rawAddr), original: hexaddr}, nil 404 } 405 406 // UnmarshalJSON parses MixedcaseAddress 407 func (ma *MixedcaseAddress) UnmarshalJSON(input []byte) error { 408 if err := hexutil.UnmarshalFixedJSONZ(addressT, input, ma.addr[:]); err != nil { 409 return err 410 } 411 return json.Unmarshal(input, &ma.original) 412 } 413 414 // MarshalJSON marshals the original value 415 func (ma MixedcaseAddress) MarshalJSON() ([]byte, error) { 416 return json.Marshal(ma.original) 417 } 418 419 // Address returns the address 420 func (ma *MixedcaseAddress) Address() Address { 421 return ma.addr 422 } 423 424 // String implements fmt.Stringer 425 func (ma *MixedcaseAddress) String() string { 426 if ma.ValidChecksum() { 427 return fmt.Sprintf("%s [chksum ok]", ma.original) 428 } 429 return fmt.Sprintf("%s [chksum INVALID]", ma.original) 430 } 431 432 // ValidChecksum returns true if the address has valid checksum 433 func (ma *MixedcaseAddress) ValidChecksum() bool { 434 return ma.original == ma.addr.Hex() 435 } 436 437 // Original returns the mixed-case input string 438 func (ma *MixedcaseAddress) Original() string { 439 return ma.original 440 } 441 442 type Decimal uint64 443 444 func isString(input []byte) bool { 445 return len(input) >= 2 && input[0] == '"' && input[len(input)-1] == '"' 446 } 447 448 // UnmarshalJSON parses a hash in hex syntax. 449 func (d *Decimal) UnmarshalJSON(input []byte) error { 450 if !isString(input) { 451 return &json.UnmarshalTypeError{Value: "non-string", Type: reflect.TypeOf(uint64(0))} 452 } 453 if i, err := strconv.ParseInt(string(input[1:len(input)-1]), 10, 64); err == nil { 454 *d = Decimal(i) 455 return nil 456 } else { 457 return err 458 } 459 } 460 461 type PrettyBytes []byte 462 463 // TerminalString implements log.TerminalStringer, formatting a string for console 464 // output during logging. 465 func (b PrettyBytes) TerminalString() string { 466 if len(b) < 7 { 467 return fmt.Sprintf("%x", b) 468 } 469 return fmt.Sprintf("%#x...%x (%dB)", b[:3], b[len(b)-3:], len(b)) 470 }