github.com/arieschain/arieschain@v0.0.0-20191023063405-37c074544356/common/types.go (about) 1 package common 2 3 import ( 4 "encoding/hex" 5 "encoding/json" 6 "fmt" 7 "math/big" 8 "math/rand" 9 "reflect" 10 "strings" 11 12 "github.com/quickchainproject/quickchain/common/hexutil" 13 "github.com/quickchainproject/quickchain/crypto/sha3" 14 ) 15 16 const ( 17 HashLength = 32 18 AddressLength = 20 19 UUIDLength = 16 20 ) 21 22 var ( 23 hashT = reflect.TypeOf(Hash{}) 24 addressT = reflect.TypeOf(Address{}) 25 ) 26 27 // Hash represents the 32 byte Keccak256 hash of arbitrary data. 28 type Hash [HashLength]byte 29 30 func BytesToHash(b []byte) Hash { 31 var h Hash 32 h.SetBytes(b) 33 return h 34 } 35 func BigToHash(b *big.Int) Hash { return BytesToHash(b.Bytes()) } 36 func HexToHash(s string) Hash { return BytesToHash(FromHex(s)) } 37 func StringToHash(s string) Hash { return BytesToHash([]byte(s)) } 38 39 // Get the string representation of the underlying hash 40 func (h Hash) Str() string { return string(h[:]) } 41 func (h Hash) Bytes() []byte { return h[:] } 42 func (h Hash) Big() *big.Int { return new(big.Int).SetBytes(h[:]) } 43 func (h Hash) Hex() string { return hexutil.Encode(h[:]) } 44 45 // TerminalString implements log.TerminalStringer, formatting a string for console 46 // output during logging. 47 func (h Hash) TerminalString() string { 48 return fmt.Sprintf("%x…%x", h[:3], h[29:]) 49 } 50 51 // String implements the stringer interface and is used also by the logger when 52 // doing full logging into a file. 53 func (h Hash) String() string { 54 return h.Hex() 55 } 56 57 // Format implements fmt.Formatter, forcing the byte slice to be formatted as is, 58 // without going through the stringer interface used for logging. 59 func (h Hash) Format(s fmt.State, c rune) { 60 fmt.Fprintf(s, "%"+string(c), h[:]) 61 } 62 63 // UnmarshalText parses a hash in hex syntax. 64 func (h *Hash) UnmarshalText(input []byte) error { 65 return hexutil.UnmarshalFixedText("Hash", input, h[:]) 66 } 67 68 // UnmarshalJSON parses a hash in hex syntax. 69 func (h *Hash) UnmarshalJSON(input []byte) error { 70 return hexutil.UnmarshalFixedJSON(hashT, input, h[:]) 71 } 72 73 // MarshalText returns the hex representation of h. 74 func (h Hash) MarshalText() ([]byte, error) { 75 return hexutil.Bytes(h[:]).MarshalText() 76 } 77 78 // Sets the hash to the value of b. If b is larger than len(h), 'b' will be cropped (from the left). 79 func (h *Hash) SetBytes(b []byte) { 80 if len(b) > len(h) { 81 b = b[len(b)-HashLength:] 82 } 83 84 copy(h[HashLength-len(b):], b) 85 } 86 87 // Set string `s` to h. If s is larger than len(h) s will be cropped (from left) to fit. 88 func (h *Hash) SetString(s string) { h.SetBytes([]byte(s)) } 89 90 // Sets h to other 91 func (h *Hash) Set(other Hash) { 92 for i, v := range other { 93 h[i] = v 94 } 95 } 96 97 // Generate implements testing/quick.Generator. 98 func (h Hash) Generate(rand *rand.Rand, size int) reflect.Value { 99 m := rand.Intn(len(h)) 100 for i := len(h) - 1; i > m; i-- { 101 h[i] = byte(rand.Uint32()) 102 } 103 return reflect.ValueOf(h) 104 } 105 106 func EmptyHash(h Hash) bool { 107 return h == Hash{} 108 } 109 110 // UnprefixedHash allows marshaling a Hash without 0x prefix. 111 type UnprefixedHash Hash 112 113 // UnmarshalText decodes the hash from hex. The 0x prefix is optional. 114 func (h *UnprefixedHash) UnmarshalText(input []byte) error { 115 return hexutil.UnmarshalFixedUnprefixedText("UnprefixedHash", input, h[:]) 116 } 117 118 // MarshalText encodes the hash as hex. 119 func (h UnprefixedHash) MarshalText() ([]byte, error) { 120 return []byte(hex.EncodeToString(h[:])), nil 121 } 122 123 /////////// Address 124 125 // Address represents the 20 byte address of an Ethereum account. 126 type Address [AddressLength]byte 127 128 var ( 129 ZeroAddress = Address{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0} 130 ZeroAddressString = "0x0000000000000000000000000000000000000000" 131 ) 132 133 func BytesToAddress(b []byte) Address { 134 var a Address 135 a.SetBytes(b) 136 return a 137 } 138 func BigToAddress(b *big.Int) Address { return BytesToAddress(b.Bytes()) } 139 func HexToAddress(s string) Address { return BytesToAddress(FromHex(s)) } 140 func StringToAddress(s string) Address { return BytesToAddress([]byte(s)) } 141 142 // IsHexAddress verifies whether a string can represent a valid hex-encoded 143 // Ethereum address or not. 144 func IsHexAddress(s string) bool { 145 if hasHexPrefix(s) { 146 s = s[2:] 147 } 148 return len(s) == 2*AddressLength && isHex(s) 149 } 150 151 // Get the string representation of the underlying address 152 func (a Address) Str() string { return string(a[:]) } 153 func (a Address) Bytes() []byte { return a[:] } 154 func (a Address) Big() *big.Int { return new(big.Int).SetBytes(a[:]) } 155 func (a Address) Hash() Hash { return BytesToHash(a[:]) } 156 157 // Hex returns an EIP55-compliant hex string representation of the address. 158 func (a Address) Hex() string { 159 unchecksummed := hex.EncodeToString(a[:]) 160 sha := sha3.NewKeccak256() 161 sha.Write([]byte(unchecksummed)) 162 hash := sha.Sum(nil) 163 164 result := []byte(unchecksummed) 165 for i := 0; i < len(result); i++ { 166 hashByte := hash[i/2] 167 if i%2 == 0 { 168 hashByte = hashByte >> 4 169 } else { 170 hashByte &= 0xf 171 } 172 if result[i] > '9' && hashByte > 7 { 173 result[i] -= 32 174 } 175 } 176 return "0x" + string(result) 177 } 178 179 // String implements the stringer interface and is used also by the logger. 180 func (a Address) String() string { 181 return a.Hex() 182 } 183 184 // Format implements fmt.Formatter, forcing the byte slice to be formatted as is, 185 // without going through the stringer interface used for logging. 186 func (a Address) Format(s fmt.State, c rune) { 187 fmt.Fprintf(s, "%"+string(c), a[:]) 188 } 189 190 // Sets the address to the value of b. If b is larger than len(a) it will panic 191 func (a *Address) SetBytes(b []byte) { 192 if len(b) > len(a) { 193 b = b[len(b)-AddressLength:] 194 } 195 copy(a[AddressLength-len(b):], b) 196 } 197 198 // Set string `s` to a. If s is larger than len(a) it will panic 199 func (a *Address) SetString(s string) { a.SetBytes([]byte(s)) } 200 201 // Sets a to other 202 func (a *Address) Set(other Address) { 203 for i, v := range other { 204 a[i] = v 205 } 206 } 207 208 // MarshalText returns the hex representation of a. 209 func (a Address) MarshalText() ([]byte, error) { 210 return hexutil.Bytes(a[:]).MarshalText() 211 } 212 213 // UnmarshalText parses a hash in hex syntax. 214 func (a *Address) UnmarshalText(input []byte) error { 215 return hexutil.UnmarshalFixedText("Address", input, a[:]) 216 } 217 218 // UnmarshalJSON parses a hash in hex syntax. 219 func (a *Address) UnmarshalJSON(input []byte) error { 220 return hexutil.UnmarshalFixedJSON(addressT, input, a[:]) 221 } 222 223 // UnprefixedHash allows marshaling an Address without 0x prefix. 224 type UnprefixedAddress Address 225 226 // UnmarshalText decodes the address from hex. The 0x prefix is optional. 227 func (a *UnprefixedAddress) UnmarshalText(input []byte) error { 228 return hexutil.UnmarshalFixedUnprefixedText("UnprefixedAddress", input, a[:]) 229 } 230 231 // MarshalText encodes the address as hex. 232 func (a UnprefixedAddress) MarshalText() ([]byte, error) { 233 return []byte(hex.EncodeToString(a[:])), nil 234 } 235 236 // MixedcaseAddress retains the original string, which may or may not be 237 // correctly checksummed 238 type MixedcaseAddress struct { 239 addr Address 240 original string 241 } 242 243 // NewMixedcaseAddress constructor (mainly for testing) 244 func NewMixedcaseAddress(addr Address) MixedcaseAddress { 245 return MixedcaseAddress{addr: addr, original: addr.Hex()} 246 } 247 248 // NewMixedcaseAddressFromString is mainly meant for unit-testing 249 func NewMixedcaseAddressFromString(hexaddr string) (*MixedcaseAddress, error) { 250 if !IsHexAddress(hexaddr) { 251 return nil, fmt.Errorf("Invalid address") 252 } 253 a := FromHex(hexaddr) 254 return &MixedcaseAddress{addr: BytesToAddress(a), original: hexaddr}, nil 255 } 256 257 // UnmarshalJSON parses MixedcaseAddress 258 func (ma *MixedcaseAddress) UnmarshalJSON(input []byte) error { 259 if err := hexutil.UnmarshalFixedJSON(addressT, input, ma.addr[:]); err != nil { 260 return err 261 } 262 return json.Unmarshal(input, &ma.original) 263 } 264 265 // MarshalJSON marshals the original value 266 func (ma *MixedcaseAddress) MarshalJSON() ([]byte, error) { 267 if strings.HasPrefix(ma.original, "0x") || strings.HasPrefix(ma.original, "0X") { 268 return json.Marshal(fmt.Sprintf("0x%s", ma.original[2:])) 269 } 270 return json.Marshal(fmt.Sprintf("0x%s", ma.original)) 271 } 272 273 // Address returns the address 274 func (ma *MixedcaseAddress) Address() Address { 275 return ma.addr 276 } 277 278 // String implements fmt.Stringer 279 func (ma *MixedcaseAddress) String() string { 280 if ma.ValidChecksum() { 281 return fmt.Sprintf("%s [chksum ok]", ma.original) 282 } 283 return fmt.Sprintf("%s [chksum INVALID]", ma.original) 284 } 285 286 // ValidChecksum returns true if the address has valid checksum 287 func (ma *MixedcaseAddress) ValidChecksum() bool { 288 return ma.original == ma.addr.Hex() 289 } 290 291 // Original returns the mixed-case input string 292 func (ma *MixedcaseAddress) Original() string { 293 return ma.original 294 } 295 296 /////////// UUID 297 298 // UUID represents the 16 byte address. 299 type UUID [UUIDLength]byte 300 301 var ( 302 ZeroUUID = UUID{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0} 303 ZeroUUIDString = "0x00000000000000000000000000000000" 304 ) 305 306 func BytesToUUID(b []byte) UUID { 307 var a UUID 308 a.SetBytes(b) 309 return a 310 } 311 312 func BigToUUID(b *big.Int) UUID { return BytesToUUID(b.Bytes()) } 313 func HexToUUID(s string) UUID { return BytesToUUID(FromHex(s)) } 314 315 // IsHexAddress verifies whether a string can represent a valid hex-encoded 316 // Ethereum address or not. 317 func IsHexUUID(s string) bool { 318 if hasHexPrefix(s) { 319 s = s[2:] 320 } 321 return len(s) == 2*UUIDLength && isHex(s) 322 } 323 324 // Get the string representation of the underlying UUID 325 func (a UUID) Str() string { return string(a[:]) } 326 func (a UUID) Bytes() []byte { return a[:] } 327 func (a UUID) Big() *big.Int { return new(big.Int).SetBytes(a[:]) } 328 func (a UUID) Hash() Hash { return BytesToHash(a[:]) } 329 330 // Hex returns an EIP55-compliant hex string representation of the address. 331 func (a UUID) Hex() string { 332 unchecksummed := hex.EncodeToString(a[:]) 333 sha := sha3.NewKeccak256() 334 sha.Write([]byte(unchecksummed)) 335 hash := sha.Sum(nil) 336 337 result := []byte(unchecksummed) 338 for i := 0; i < len(result); i++ { 339 hashByte := hash[i/2] 340 if i%2 == 0 { 341 hashByte = hashByte >> 4 342 } else { 343 hashByte &= 0xf 344 } 345 if result[i] > '9' && hashByte > 7 { 346 result[i] -= 32 347 } 348 } 349 return "0x" + string(result) 350 } 351 352 // String implements the stringer interface and is used also by the logger. 353 func (a UUID) String() string { 354 return a.Hex() 355 } 356 357 // Format implements fmt.Formatter, forcing the byte slice to be formatted as is, 358 // without going through the stringer interface used for logging. 359 func (a UUID) Format(s fmt.State, c rune) { 360 fmt.Fprintf(s, "%"+string(c), a[:]) 361 } 362 363 // Sets the UUID to the value of b. If b is larger than len(a) it will panic 364 func (a *UUID) SetBytes(b []byte) { 365 if len(b) > len(a) { 366 b = b[len(b)-UUIDLength:] 367 } 368 copy(a[UUIDLength-len(b):], b) 369 } 370 371 // Set string `s` to a. If s is larger than len(a) it will panic 372 func (a *UUID) SetString(s string) { a.SetBytes([]byte(s)) } 373 374 // Sets a to other 375 func (a *UUID) Set(other UUID) { 376 for i, v := range other { 377 a[i] = v 378 } 379 }