github.com/amazechain/amc@v0.1.3/common/types/hash.go (about) 1 // Copyright 2022 The AmazeChain Authors 2 // This file is part of the AmazeChain library. 3 // 4 // The AmazeChain 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 AmazeChain 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 AmazeChain library. If not, see <http://www.gnu.org/licenses/>. 16 17 package types 18 19 import ( 20 "bytes" 21 "database/sql/driver" 22 "encoding/hex" 23 "fmt" 24 25 "github.com/amazechain/amc/common/hexutil" 26 27 "hash" 28 "math/big" 29 "math/rand" 30 "reflect" 31 32 "golang.org/x/crypto/sha3" 33 ) 34 35 const ( 36 HashLength = 32 37 ) 38 39 var ( 40 hashT = reflect.TypeOf(Hash{}) 41 addressT = reflect.TypeOf(Address{}) 42 //addressSt = reflect.TypeOf(Address32{}) 43 ) 44 45 type Hash [HashLength]byte 46 47 // Bytes gets the byte representation of the underlying hash. 48 func (h Hash) Bytes() []byte { return h[:] } 49 50 // Big converts a hash to a big integer. 51 func (h Hash) Big() *big.Int { return new(big.Int).SetBytes(h[:]) } 52 53 // Hex converts a hash to a hex string. 54 func (h Hash) Hex() string { return hexutil.Encode(h[:]) } 55 56 // TerminalString implements log.TerminalStringer, formatting a string for console 57 // output during logging. 58 func (h Hash) TerminalString() string { 59 return fmt.Sprintf("%x…%x", h[:3], h[29:]) 60 } 61 62 // UnmarshalText parses a hash in hex syntax. 63 func (h *Hash) UnmarshalText(input []byte) error { 64 return hexutil.UnmarshalFixedText("Hash", input, h[:]) 65 } 66 67 // MarshalText returns the hex representation of h. 68 func (h Hash) MarshalText() ([]byte, error) { 69 return hexutil.Bytes(h[:]).MarshalText() 70 } 71 72 // SetBytes sets the hash to the value of b. 73 func (h *Hash) SetBytes(b []byte) error { 74 if len(b) != HashLength { 75 return fmt.Errorf("invalid bytes len %d", len(b)) 76 } 77 78 copy(h[:], b[:HashLength]) 79 return nil 80 } 81 82 // Generate implements testing/quick.Generator. 83 func (h Hash) Generate(rand *rand.Rand, size int) reflect.Value { 84 m := rand.Intn(len(h)) 85 for i := len(h) - 1; i > m; i-- { 86 h[i] = byte(rand.Uint32()) 87 } 88 return reflect.ValueOf(h) 89 } 90 91 // Scan implements Scanner for database/sql. 92 func (h *Hash) Scan(src interface{}) error { 93 srcB, ok := src.([]byte) 94 if !ok { 95 return fmt.Errorf("can't scan %T into Hash", src) 96 } 97 if len(srcB) != HashLength { 98 return fmt.Errorf("can't scan []byte of len %d into Hash, want %d", len(srcB), HashLength) 99 } 100 copy(h[:], srcB) 101 return nil 102 } 103 104 // Value implements valuer for database/sql. 105 func (h Hash) Value() (driver.Value, error) { 106 return h[:], nil 107 } 108 109 func BytesHash(b []byte) Hash { 110 h3 := sha3.New256() 111 h3.Write(b) 112 r := h3.Sum(nil) 113 var h Hash 114 copy(h[:], r[:HashLength]) 115 return h 116 } 117 118 func BytesToHash(b []byte) Hash { 119 var h Hash 120 h.SetBytes(b) 121 return h 122 } 123 124 func StringToHash(s string) Hash { 125 var h Hash 126 b, err := hex.DecodeString(s) 127 if err == nil { 128 //copy(h[:], b[:HashLength]) 129 return BytesToHash(b) 130 } 131 132 return h 133 } 134 135 func (h Hash) String() string { 136 return hex.EncodeToString(h[:]) 137 } 138 139 func (h Hash) HexBytes() []byte { 140 s := h.String() 141 return []byte(s) 142 } 143 144 func (h *Hash) SetString(s string) error { 145 if len(s) != HashLength*2 { 146 return fmt.Errorf("invalid string len %v, len(%d)", string(s), len(s)) 147 } 148 149 b, err := hex.DecodeString(s) 150 if err != nil { 151 return err 152 } 153 154 return h.SetBytes(b) 155 } 156 157 func (h Hash) Marshal() ([]byte, error) { 158 return h.Bytes(), nil 159 } 160 161 func (h *Hash) MarshalTo(data []byte) (n int, err error) { 162 copy(data, h.Bytes()) 163 return len(h.Bytes()), err 164 } 165 166 func (h *Hash) Unmarshal(data []byte) error { 167 return h.SetBytes(data) 168 } 169 170 func (h *Hash) Size() int { 171 return len(h.Bytes()) 172 } 173 174 // Format implements fmt.Formatter. 175 // Hash supports the %v, %s, %v, %x, %X and %d format verbs. 176 func (h Hash) Format(s fmt.State, c rune) { 177 hexb := make([]byte, 2+len(h)*2) 178 copy(hexb, "0x") 179 hex.Encode(hexb[2:], h[:]) 180 181 switch c { 182 case 'x', 'X': 183 if !s.Flag('#') { 184 hexb = hexb[2:] 185 } 186 if c == 'X' { 187 hexb = bytes.ToUpper(hexb) 188 } 189 fallthrough 190 case 'v', 's': 191 s.Write(hexb) 192 case 'q': 193 q := []byte{'"'} 194 s.Write(q) 195 s.Write(hexb) 196 s.Write(q) 197 case 'd': 198 fmt.Fprint(s, ([len(h)]byte)(h)) 199 default: 200 fmt.Fprintf(s, "%%!%c(hash=%x)", c, h) 201 } 202 } 203 204 // UnmarshalJSON parses a hash in hex syntax. 205 func (h *Hash) UnmarshalJSON(input []byte) error { 206 return hexutil.UnmarshalFixedJSON(hashT, input, h[:]) 207 } 208 209 func (h Hash) Equal(other Hash) bool { 210 return bytes.Equal(h.Bytes(), other.Bytes()) 211 } 212 213 // HashDifference returns a new set which is the difference between a and b. 214 func HashDifference(a, b []Hash) []Hash { 215 keep := make([]Hash, 0, len(a)) 216 217 remove := make(map[Hash]struct{}) 218 for _, hash := range b { 219 remove[hash] = struct{}{} 220 } 221 222 for _, hash := range a { 223 if _, ok := remove[hash]; !ok { 224 keep = append(keep, hash) 225 } 226 } 227 228 return keep 229 } 230 231 // keccakState wraps sha3.state. In addition to the usual hash methods, it also supports 232 // Read to get a variable amount of data from the hash state. Read is faster than Sum 233 // because it doesn't copy the internal state, but also modifies the internal state. 234 type keccakState interface { 235 hash.Hash 236 Read([]byte) (int, error) 237 } 238 239 type Hasher struct { 240 Sha keccakState 241 } 242 243 var hasherPools = make(chan *Hasher, 128) 244 245 func NewHasher() *Hasher { 246 var h *Hasher 247 select { 248 case h = <-hasherPools: 249 default: 250 h = &Hasher{Sha: sha3.NewLegacyKeccak256().(keccakState)} 251 } 252 return h 253 } 254 255 func ReturnHasherToPool(h *Hasher) { 256 select { 257 case hasherPools <- h: 258 default: 259 fmt.Printf("Allowing Hasher to be garbage collected, pool is full\n") 260 } 261 } 262 263 func HashData(data []byte) (Hash, error) { 264 h := NewHasher() 265 defer ReturnHasherToPool(h) 266 h.Sha.Reset() 267 268 _, err := h.Sha.Write(data) 269 if err != nil { 270 return Hash{}, err 271 } 272 273 var buf Hash 274 _, err = h.Sha.Read(buf[:]) 275 if err != nil { 276 return Hash{}, err 277 } 278 return buf, nil 279 } 280 281 // Bytes2Hex returns the hexadecimal encoding of d. 282 func Bytes2Hex(d []byte) string { 283 return hex.EncodeToString(d) 284 } 285 286 // HexToHash sets byte representation of s to hash. 287 // If b is larger than len(h), b will be cropped from the left. 288 func HexToHash(s string) Hash { return BytesToHash(FromHex2Bytes(s)) } 289 290 // FromHex returns the bytes represented by the hexadecimal string s. 291 // s may be prefixed with "0x". 292 func FromHex2Bytes(s string) []byte { 293 if has0xPrefix(s) { 294 s = s[2:] 295 } 296 if len(s)%2 == 1 { 297 s = "0" + s 298 } 299 return Hex2Bytes(s) 300 } 301 302 // Hashes is a slice of common.Hash, implementing sort.Interface 303 type Hashes []Hash 304 305 func (hashes Hashes) Len() int { 306 return len(hashes) 307 } 308 func (hashes Hashes) Less(i, j int) bool { 309 return bytes.Compare(hashes[i][:], hashes[j][:]) == -1 310 } 311 func (hashes Hashes) Swap(i, j int) { 312 hashes[i], hashes[j] = hashes[j], hashes[i] 313 }