github.com/status-im/status-go@v1.1.0/eth-node/types/hash.go (about) 1 // Code extracted from vendor/github.com/ethereum/go-ethereum/common/types.go 2 3 package types 4 5 import ( 6 "encoding/hex" 7 "fmt" 8 "reflect" 9 ) 10 11 const ( 12 // HashLength is the expected length of the hash 13 HashLength = 32 14 ) 15 16 // Hash represents the 32 byte Keccak256 hash of arbitrary data. 17 type Hash [HashLength]byte 18 19 var hashT = reflect.TypeOf(Hash{}) 20 21 // Encode encodes b as a hex string with 0x prefix. 22 func encode(b []byte) string { 23 enc := make([]byte, len(b)*2+2) 24 copy(enc, "0x") 25 hex.Encode(enc[2:], b) 26 return string(enc) 27 } 28 29 // FromHex returns the bytes represented by the hexadecimal string s. 30 // s may be prefixed with "0x". 31 func FromHex(s string) []byte { 32 if has0xPrefix(s) { 33 s = s[2:] 34 } 35 if len(s)%2 == 1 { 36 s = "0" + s 37 } 38 return Hex2Bytes(s) 39 } 40 41 // HexToHash sets byte representation of s to hash. 42 // If b is larger than len(h), b will be cropped from the left. 43 func HexToHash(s string) Hash { return BytesToHash(FromHex(s)) } 44 45 // Hex converts a hash to a hex string. 46 func (h *Hash) Hex() string { return encode(h[:]) } 47 48 // Bytes gets the byte representation of the underlying hash. 49 func (h Hash) Bytes() []byte { return h[:] } 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 // SetBytes sets the hash to the value of b. 58 // If b is larger than len(h), b will be cropped from the left. 59 func (h *Hash) SetBytes(b []byte) { 60 if len(b) > len(h) { 61 b = b[len(b)-HashLength:] 62 } 63 64 copy(h[HashLength-len(b):], b) 65 } 66 67 // UnmarshalText parses a hash in hex syntax. 68 func (h *Hash) UnmarshalText(input []byte) error { 69 return UnmarshalFixedText("Hash", input, h[:]) 70 } 71 72 // UnmarshalJSON parses a hash in hex syntax. 73 func (h *Hash) UnmarshalJSON(input []byte) error { 74 return UnmarshalFixedJSON(hashT, input, h[:]) 75 } 76 77 // MarshalText returns the hex representation of h. 78 func (h Hash) MarshalText() ([]byte, error) { 79 return HexBytes(h[:]).MarshalText() 80 } 81 82 // BytesToHash sets b to hash. 83 // If b is larger than len(h), b will be cropped from the left. 84 func BytesToHash(b []byte) Hash { 85 var h Hash 86 h.SetBytes(b) 87 return h 88 } 89 90 // UnmarshalFixedJSON decodes the input as a string with 0x prefix. The length of out 91 // determines the required input length. This function is commonly used to implement the 92 // UnmarshalJSON method for fixed-size types. 93 func UnmarshalFixedJSON(typ reflect.Type, input, out []byte) error { 94 if !isString(input) { 95 return errNonString(typ) 96 } 97 return wrapTypeError(UnmarshalFixedText(typ.String(), input[1:len(input)-1], out), typ) 98 } 99 100 // UnmarshalFixedText decodes the input as a string with 0x prefix. The length of out 101 // determines the required input length. This function is commonly used to implement the 102 // UnmarshalText method for fixed-size types. 103 func UnmarshalFixedText(typname string, input, out []byte) error { 104 raw, err := checkText(input, true) 105 if err != nil { 106 return err 107 } 108 if len(raw)/2 != len(out) { 109 return fmt.Errorf("hex string has length %d, want %d for %s", len(raw), len(out)*2, typname) 110 } 111 // Pre-verify syntax before modifying out. 112 for _, b := range raw { 113 if decodeNibble(b) == badNibble { 114 return ErrSyntax 115 } 116 } 117 _, err = hex.Decode(out, raw) 118 return err 119 }