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