github.com/turingchain2020/turingchain@v1.1.21/common/merkle/hash.go (about) 1 // Copyright Turing Corp. 2018 All Rights Reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package merkle 6 7 import ( 8 "encoding/hex" 9 "fmt" 10 ) 11 12 //HashSize hash长度 13 const HashSize = 32 14 15 //Hash 哈希 16 type Hash [HashSize]byte 17 18 //MaxHashStringSize 最大hash字符串长度 19 const MaxHashStringSize = HashSize * 2 20 21 //ErrHashStrSize error 22 var ErrHashStrSize = fmt.Errorf("max hash string length is %v bytes", MaxHashStringSize) 23 24 // CloneBytes returns a copy of the bytes which represent the hash as a byte slice. 25 // NOTE: It is generally cheaper to just slice the hash directly thereby reusing 26 // the same bytes rather than calling this method. 27 func (hash *Hash) CloneBytes() []byte { 28 newHash := make([]byte, HashSize) 29 copy(newHash, hash[:]) 30 31 return newHash 32 } 33 34 // String returns the Hash as the hexadecimal string of the byte-reversed hash. 35 func (hash Hash) String() string { 36 for i := 0; i < HashSize/2; i++ { 37 hash[i], hash[HashSize-1-i] = hash[HashSize-1-i], hash[i] 38 } 39 return hex.EncodeToString(hash[:]) 40 } 41 42 // NewHash returns a new Hash from a byte slice. An error is returned if 43 // the number of bytes passed in is not HashSize. 44 func NewHash(newHash []byte) (*Hash, error) { 45 var sh Hash 46 err := sh.SetBytes(newHash) 47 if err != nil { 48 return nil, err 49 } 50 return &sh, err 51 } 52 53 // SetBytes sets the bytes which represent the hash. An error is returned if 54 // the number of bytes passed in is not HashSize. 55 func (hash *Hash) SetBytes(newHash []byte) error { 56 nhlen := len(newHash) 57 if nhlen != HashSize { 58 return fmt.Errorf("invalid hash length of %v, want %v", nhlen, 59 HashSize) 60 } 61 copy(hash[:], newHash) 62 63 return nil 64 } 65 66 // NewHashFromStr creates a Hash from a hash string. The string should be 67 // the hexadecimal string of a byte-reversed hash, but any missing characters 68 // result in zero padding at the end of the Hash. 69 func NewHashFromStr(hash string) (*Hash, error) { 70 ret := new(Hash) 71 err := Decode(ret, hash) 72 if err != nil { 73 return nil, err 74 } 75 return ret, nil 76 } 77 78 // Decode decodes the byte-reversed hexadecimal string encoding of a Hash to a 79 // destination. 80 func Decode(dst *Hash, src string) error { 81 // Return error if hash string is too long. 82 if len(src) > MaxHashStringSize { 83 return ErrHashStrSize 84 } 85 86 // Hex decoder expects the hash to be a multiple of two. When not, pad 87 // with a leading zero. 88 var srcBytes []byte 89 if len(src)%2 == 0 { 90 srcBytes = []byte(src) 91 } else { 92 srcBytes = make([]byte, 1+len(src)) 93 srcBytes[0] = '0' 94 copy(srcBytes[1:], src) 95 } 96 97 // Hex decode the source bytes to a temporary destination. 98 var reversedHash Hash 99 _, err := hex.Decode(reversedHash[HashSize-hex.DecodedLen(len(srcBytes)):], srcBytes) 100 if err != nil { 101 return err 102 } 103 104 // Reverse copy from the temporary hash to destination. Because the 105 // temporary was zeroed, the written result will be correctly padded. 106 for i, b := range reversedHash[:HashSize/2] { 107 dst[i], dst[HashSize-1-i] = reversedHash[HashSize-1-i], b 108 } 109 110 return nil 111 }