github.com/ethereumproject/go-ethereum@v5.5.2+incompatible/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 "encoding/hex" 21 "encoding/json" 22 "errors" 23 "fmt" 24 "math/big" 25 "math/rand" 26 "reflect" 27 "strings" 28 ) 29 30 const ( 31 HashLength = 32 32 AddressLength = 20 33 ) 34 35 var hashJsonLengthErr = errors.New("common: unmarshalJSON failed: hash must be exactly 32 bytes") 36 37 type ( 38 Hash [HashLength]byte 39 Address [AddressLength]byte 40 ) 41 42 func BytesToHash(b []byte) Hash { 43 var h Hash 44 h.SetBytes(b) 45 return h 46 } 47 func BigToHash(b *big.Int) Hash { return BytesToHash(b.Bytes()) } 48 func HexToHash(s string) Hash { return BytesToHash(FromHex(s)) } 49 50 // Don't use the default 'String' method in case we want to overwrite 51 52 // Get the string representation of the underlying hash 53 func (h Hash) Str() string { return string(h[:]) } 54 func (h Hash) Bytes() []byte { return h[:] } 55 func (h Hash) Big() *big.Int { return new(big.Int).SetBytes(h[:]) } 56 func (h Hash) Hex() string { return "0x" + Bytes2Hex(h[:]) } 57 58 // UnmarshalJSON parses a hash in its hex from to a hash. 59 func (h *Hash) UnmarshalJSON(input []byte) error { 60 length := len(input) 61 if length >= 2 && input[0] == '"' && input[length-1] == '"' { 62 input = input[1 : length-1] 63 } 64 // strip "0x" for length check 65 if len(input) > 1 && strings.ToLower(string(input[:2])) == "0x" { 66 input = input[2:] 67 } 68 69 // validate the length of the input hash 70 if len(input) != HashLength*2 { 71 return hashJsonLengthErr 72 } 73 h.SetBytes(FromHex(string(input))) 74 return nil 75 } 76 77 // Serialize given hash to JSON 78 func (h Hash) MarshalJSON() ([]byte, error) { 79 return json.Marshal(h.Hex()) 80 } 81 82 // Sets the hash to the value of b. If b is larger than len(h) it will panic 83 func (h *Hash) SetBytes(b []byte) { 84 if len(b) > len(h.Bytes()) { 85 b = b[len(b)-HashLength:] 86 } 87 88 copy(h[HashLength-len(b):], b) 89 } 90 91 // Set string `s` to h. If s is larger than len(h) it will panic 92 func (h *Hash) SetString(s string) { h.SetBytes([]byte(s)) } 93 94 // Sets h to other 95 func (h *Hash) Set(other Hash) { 96 for i, v := range other { 97 h[i] = v 98 } 99 } 100 101 // Generate implements testing/quick.Generator. 102 func (h Hash) Generate(rand *rand.Rand, size int) reflect.Value { 103 m := rand.Intn(len(h)) 104 for i := len(h) - 1; i > m; i-- { 105 h[i] = byte(rand.Uint32()) 106 } 107 return reflect.ValueOf(h) 108 } 109 110 func EmptyHash(h Hash) bool { 111 return h == Hash{} 112 } 113 114 func (h Hash) IsEmpty() bool { 115 return EmptyHash(h) 116 } 117 118 /////////// Address 119 func BytesToAddress(b []byte) Address { 120 var a Address 121 a.SetBytes(b) 122 return a 123 } 124 func StringToAddress(s string) Address { return BytesToAddress([]byte(s)) } 125 func BigToAddress(b *big.Int) Address { return BytesToAddress(b.Bytes()) } 126 func HexToAddress(s string) Address { return BytesToAddress(FromHex(s)) } 127 128 func EmptyAddress(a Address) bool { 129 return a == Address{} 130 } 131 132 func (a Address) IsEmpty() bool { 133 return EmptyAddress(a) 134 } 135 136 // IsHexAddress verifies whether a string can represent a valid hex-encoded 137 // Ethereum address or not. 138 func IsHexAddress(s string) bool { 139 if len(s) == 2+2*AddressLength && IsHex(s) { 140 return true 141 } 142 if len(s) == 2*AddressLength && IsHex("0x"+s) { 143 return true 144 } 145 return false 146 } 147 148 // Get the string representation of the underlying address 149 func (a Address) Str() string { return string(a[:]) } 150 func (a Address) Bytes() []byte { return a[:] } 151 func (a Address) Big() *big.Int { return new(big.Int).SetBytes(a[:]) } 152 func (a Address) Hash() Hash { return BytesToHash(a[:]) } 153 func (a Address) Hex() string { return "0x" + Bytes2Hex(a[:]) } 154 155 // Sets the address to the value of b. If b is larger than len(a) it will panic 156 func (a *Address) SetBytes(b []byte) { 157 if len(b) > len(a.Bytes()) { 158 b = b[len(b)-AddressLength:] 159 } 160 copy(a[AddressLength-len(b):], b) 161 } 162 163 // Set string `s` to a. If s is larger than len(a) it will panic 164 func (a *Address) SetString(s string) { a.SetBytes([]byte(s)) } 165 166 // Sets a to other 167 func (a *Address) Set(other Address) { 168 for i, v := range other { 169 a[i] = v 170 } 171 } 172 173 // Serialize given address to JSON 174 func (a Address) MarshalJSON() ([]byte, error) { 175 return json.Marshal(a.Hex()) 176 } 177 178 // Parse address from raw json data 179 func (a *Address) UnmarshalJSON(data []byte) error { 180 if len(data) > 2 && data[0] == '"' && data[len(data)-1] == '"' { 181 data = data[1 : len(data)-1] 182 } 183 184 if len(data) > 2 && data[0] == '0' && data[1] == 'x' { 185 data = data[2:] 186 } 187 188 if len(data) != 2*AddressLength { 189 return fmt.Errorf("Invalid address length, expected %d got %d bytes", 2*AddressLength, len(data)) 190 } 191 192 n, err := hex.Decode(a[:], data) 193 if err != nil { 194 return err 195 } 196 197 if n != AddressLength { 198 return fmt.Errorf("Invalid address") 199 } 200 201 a.Set(HexToAddress(string(data))) 202 return nil 203 } 204 205 // PP Pretty Prints a byte slice in the following format: 206 // hex(value[:4])...(hex[len(value)-4:]) 207 func PP(value []byte) string { 208 if len(value) <= 8 { 209 return Bytes2Hex(value) 210 } 211 212 return fmt.Sprintf("%x...%x", value[:4], value[len(value)-4]) 213 }