github.com/chain5j/chain5j-pkg@v1.0.7/types/hash.go (about) 1 // Package types 2 // 3 // @author: xwc1125 4 package types 5 6 import ( 7 "database/sql/driver" 8 "encoding/hex" 9 "fmt" 10 "math/big" 11 "math/rand" 12 "reflect" 13 14 "github.com/chain5j/chain5j-pkg/crypto/hashalg/sha3" 15 "github.com/chain5j/chain5j-pkg/util/hexutil" 16 ) 17 18 // HashLength hash长度 19 const HashLength = 32 20 21 var ( 22 hashT = reflect.TypeOf(Hash{}) 23 EmptyHash = Hash{} 24 EmptyCode = sha3.Keccak256(nil) 25 EmptyCodeHash = BytesToHash(EmptyCode) 26 EmptyRootHash = HexToHash("56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421") 27 // EmptyRootHash, _ = hashalg.RootHash(codec.Codecor(), nil) 28 ) 29 30 type Hash [HashLength]byte 31 32 func BytesToHash(b []byte) Hash { 33 var h Hash 34 h.SetBytes(b) 35 return h 36 } 37 38 func StringToHash(s string) Hash { 39 return BytesToHash([]byte(s)) 40 } 41 42 func BigToHash(b *big.Int) Hash { 43 return BytesToHash(b.Bytes()) 44 } 45 46 func HexToHash(s string) Hash { 47 return BytesToHash(hexutil.MustDecode(s)) 48 } 49 50 // Bytes gets the byte representation of the underlying hash. 51 func (h Hash) Bytes() []byte { return h[:] } 52 53 // Big converts a hash to a big integer. 54 func (h Hash) Big() *big.Int { return new(big.Int).SetBytes(h[:]) } 55 56 // Hex converts a hash to a hex string. 57 func (h Hash) Hex() string { return hexutil.Encode(h[:]) } 58 59 func (h Hash) HexNoPrefix() string { 60 return hexutil.Encode(h[:])[2:] 61 } 62 63 // TerminalString implements log.TerminalStringer, formatting a string for console 64 // output during logging. 65 func (h Hash) TerminalString() string { 66 // return fmt.Sprintf("%x…%x", h[:3], h[29:]) 67 return h.Hex() 68 } 69 70 // String implements the stringer interface and is used also by the logger when 71 // doing full logging into a file. 72 func (h Hash) String() string { 73 return h.Hex() 74 } 75 76 // Format implements fmt.Formatter, forcing the byte slice to be formatted as is, 77 // without going through the stringer interface used for logging. 78 func (h Hash) Format(s fmt.State, c rune) { 79 fmt.Fprintf(s, "%"+string(c), h[:]) 80 } 81 82 // UnmarshalText parses a hash in hex syntax. 83 func (h *Hash) UnmarshalText(input []byte) error { 84 return hexutil.UnmarshalFixedText("Hash", input, h[:]) 85 } 86 87 // UnmarshalJSON parses a hash in hex syntax. 88 func (h *Hash) UnmarshalJSON(input []byte) error { 89 return hexutil.UnmarshalFixedJSON(hashT, input, h[:]) 90 } 91 92 // MarshalText returns the hex representation of h. 93 func (h Hash) MarshalText() ([]byte, error) { 94 return hexutil.Bytes(h[:]).MarshalText() 95 } 96 97 // SetBytes sets the hash to the value of b. 98 // If b is larger than len(h), b will be cropped from the left. 99 func (h *Hash) SetBytes(b []byte) { 100 if len(b) > len(h) { 101 b = b[len(b)-HashLength:] 102 } 103 104 copy(h[HashLength-len(b):], b) 105 } 106 107 // Generate implements testing/quick.Generator. 108 func (h Hash) Generate(rand *rand.Rand, size int) reflect.Value { 109 m := rand.Intn(len(h)) 110 for i := len(h) - 1; i > m; i-- { 111 h[i] = byte(rand.Uint32()) 112 } 113 return reflect.ValueOf(h) 114 } 115 116 func IsEmptyHash(h Hash) bool { 117 return h == Hash{} 118 } 119 120 // Scan implements Scanner for database/sql. 121 func (h *Hash) Scan(src interface{}) error { 122 srcB, ok := src.([]byte) 123 if !ok { 124 return fmt.Errorf("can't scan %T into Hash", src) 125 } 126 if len(srcB) != HashLength { 127 return fmt.Errorf("can't scan []byte of len %d into Hash, want %d", len(srcB), HashLength) 128 } 129 copy(h[:], srcB) 130 return nil 131 } 132 133 // Value implements valuer for database/sql. 134 func (h Hash) Value() (driver.Value, error) { 135 return h[:], nil 136 } 137 138 func (h Hash) Nil() bool { 139 return h == Hash{} 140 } 141 142 // UnprefixedHash allows marshaling a Hash without 0x prefix. 143 type UnprefixedHash Hash 144 145 // UnmarshalText decodes the hash from hex. The 0x prefix is optional. 146 func (h *UnprefixedHash) UnmarshalText(input []byte) error { 147 return hexutil.UnmarshalFixedUnprefixedText("UnprefixedHash", input, h[:]) 148 } 149 150 // MarshalText encodes the hash as hex. 151 func (h UnprefixedHash) MarshalText() ([]byte, error) { 152 return []byte(hex.EncodeToString(h[:])), nil 153 }