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  }