github.com/ledgerwatch/erigon-lib@v1.0.0/common/hash.go (about) 1 /* 2 Copyright 2021 Erigon contributors 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 package common 17 18 import ( 19 "bytes" 20 "database/sql/driver" 21 "encoding/hex" 22 "fmt" 23 "math/big" 24 "math/rand" 25 "reflect" 26 27 "github.com/ledgerwatch/erigon-lib/common/hexutility" 28 "github.com/ledgerwatch/erigon-lib/common/length" 29 ) 30 31 var ( 32 hashT = reflect.TypeOf(Hash{}) 33 ) 34 35 const ( 36 hexPrefix = `0x` 37 ) 38 39 // Hash represents the 32 byte Keccak256 hash of arbitrary data. 40 type Hash [length.Hash]byte 41 42 // BytesToHash sets b to hash. 43 // If b is larger than len(h), b will be cropped from the left. 44 func BytesToHash(b []byte) Hash { 45 var h Hash 46 h.SetBytes(b) 47 return h 48 } 49 50 // CastToHash - sets b to hash 51 // If b is larger than len(h), b will be cropped from the left. 52 // panics if input is shorter than 32 bytes, see https://go.dev/doc/go1.17#language 53 // faster than BytesToHash 54 func CastToHash(b []byte) Hash { return *(*Hash)(b) } 55 56 // BigToHash sets byte representation of b to hash. 57 // If b is larger than len(h), b will be cropped from the left. 58 func BigToHash(b *big.Int) Hash { return BytesToHash(b.Bytes()) } 59 60 // HexToHash sets byte representation of s to hash. 61 // If b is larger than len(h), b will be cropped from the left. 62 func HexToHash(s string) Hash { return BytesToHash(hexutility.FromHex(s)) } 63 64 // Bytes gets the byte representation of the underlying hash. 65 func (h Hash) Bytes() []byte { return h[:] } 66 67 // Big converts a hash to a big integer. 68 func (h Hash) Big() *big.Int { return new(big.Int).SetBytes(h[:]) } 69 70 // Hex converts a hash to a hex string. 71 func (h Hash) Hex() string { return hexutility.Encode(h[:]) } 72 73 // TerminalString implements log.TerminalStringer, formatting a string for console 74 // output during logging. 75 func (h Hash) TerminalString() string { 76 return fmt.Sprintf("%x…%x", h[:3], h[29:]) 77 } 78 79 // String implements the stringer interface and is used also by the logger when 80 // doing full logging into a file. 81 func (h Hash) String() string { 82 return h.Hex() 83 } 84 85 // Format implements fmt.Formatter. 86 // Hash supports the %v, %s, %v, %x, %X and %d format verbs. 87 func (h Hash) Format(s fmt.State, c rune) { 88 hexb := make([]byte, 2+len(h)*2) 89 copy(hexb, "0x") 90 hex.Encode(hexb[2:], h[:]) 91 92 switch c { 93 case 'x', 'X': 94 if !s.Flag('#') { 95 hexb = hexb[2:] 96 } 97 if c == 'X' { 98 hexb = bytes.ToUpper(hexb) 99 } 100 fallthrough 101 case 'v', 's': 102 s.Write(hexb) 103 case 'q': 104 q := []byte{'"'} 105 s.Write(q) 106 s.Write(hexb) 107 s.Write(q) 108 case 'd': 109 fmt.Fprint(s, ([len(h)]byte)(h)) 110 default: 111 fmt.Fprintf(s, "%%!%c(hash=%x)", c, h) 112 } 113 } 114 115 // UnmarshalText parses a hash in hex syntax. 116 func (h *Hash) UnmarshalText(input []byte) error { 117 return hexutility.UnmarshalFixedText("Hash", input, h[:]) 118 } 119 120 // UnmarshalJSON parses a hash in hex syntax. 121 func (h *Hash) UnmarshalJSON(input []byte) error { 122 return hexutility.UnmarshalFixedJSON(hashT, input, h[:]) 123 } 124 125 // MarshalText returns the hex representation of h. 126 func (h Hash) MarshalText() ([]byte, error) { 127 b := h[:] 128 result := make([]byte, len(b)*2+2) 129 copy(result, hexPrefix) 130 hex.Encode(result[2:], b) 131 return result, nil 132 } 133 134 // SetBytes sets the hash to the value of b. 135 // If b is larger than len(h), b will be cropped from the left. 136 func (h *Hash) SetBytes(b []byte) { 137 if len(b) > len(h) { 138 b = b[len(b)-length.Hash:] 139 } 140 141 copy(h[length.Hash-len(b):], b) 142 } 143 144 // Generate implements testing/quick.Generator. 145 func (h Hash) Generate(rand *rand.Rand, size int) reflect.Value { 146 m := rand.Intn(len(h)) 147 for i := len(h) - 1; i > m; i-- { 148 h[i] = byte(rand.Uint32()) 149 } 150 return reflect.ValueOf(h) 151 } 152 153 // Scan implements Scanner for database/sql. 154 func (h *Hash) Scan(src interface{}) error { 155 srcB, ok := src.([]byte) 156 if !ok { 157 return fmt.Errorf("can't scan %T into Hash", src) 158 } 159 if len(srcB) != length.Hash { 160 return fmt.Errorf("can't scan []byte of len %d into Hash, want %d", len(srcB), length.Hash) 161 } 162 copy(h[:], srcB) 163 return nil 164 } 165 166 // Value implements valuer for database/sql. 167 func (h Hash) Value() (driver.Value, error) { 168 return h[:], nil 169 } 170 171 func FromHex(in string) []byte { 172 return hexutility.MustDecodeHex(in) 173 } 174 175 type CodeRecord struct { 176 BlockNumber uint64 177 TxNumber uint64 178 CodeHash Hash 179 }