github.com/BlockABC/godash@v0.0.0-20191112120524-f4aa3a32c566/wire/shahash.go (about)

     1  // Copyright (c) 2013-2015 The btcsuite developers
     2  // Copyright (c) 2016 The Dash developers
     3  // Use of this source code is governed by an ISC
     4  // license that can be found in the LICENSE file.
     5  
     6  package wire
     7  
     8  import (
     9  	"encoding/hex"
    10  	"fmt"
    11  )
    12  
    13  // HashSize is the array size used to store sha hashes.  See ShaHash.
    14  const HashSize = 32
    15  
    16  // MaxHashStringSize is the maximum length of a ShaHash hash string.
    17  const MaxHashStringSize = HashSize * 2
    18  
    19  // ErrHashStrSize describes an error that indicates the caller specified a hash
    20  // string that has too many characters.
    21  var ErrHashStrSize = fmt.Errorf("max hash string length is %v bytes", MaxHashStringSize)
    22  
    23  // ShaHash is used in several of the bitcoin messages and common structures.  It
    24  // typically represents the double sha256 of data.
    25  type ShaHash [HashSize]byte
    26  
    27  // String returns the ShaHash as the hexadecimal string of the byte-reversed
    28  // hash.
    29  func (hash ShaHash) String() string {
    30  	for i := 0; i < HashSize/2; i++ {
    31  		hash[i], hash[HashSize-1-i] = hash[HashSize-1-i], hash[i]
    32  	}
    33  	return hex.EncodeToString(hash[:])
    34  }
    35  
    36  // Bytes returns the bytes which represent the hash as a byte slice.
    37  //
    38  // NOTE: This makes a copy of the bytes and should have probably been named
    39  // CloneBytes.  It is generally cheaper to just slice the hash directly thereby
    40  // reusing the same bytes rather than calling this method.
    41  func (hash *ShaHash) Bytes() []byte {
    42  	newHash := make([]byte, HashSize)
    43  	copy(newHash, hash[:])
    44  
    45  	return newHash
    46  }
    47  
    48  // SetBytes sets the bytes which represent the hash.  An error is returned if
    49  // the number of bytes passed in is not HashSize.
    50  func (hash *ShaHash) SetBytes(newHash []byte) error {
    51  	nhlen := len(newHash)
    52  	if nhlen != HashSize {
    53  		return fmt.Errorf("invalid sha length of %v, want %v", nhlen,
    54  			HashSize)
    55  	}
    56  	copy(hash[:], newHash)
    57  
    58  	return nil
    59  }
    60  
    61  // IsEqual returns true if target is the same as hash.
    62  func (hash *ShaHash) IsEqual(target *ShaHash) bool {
    63  	return *hash == *target
    64  }
    65  
    66  // NewShaHash returns a new ShaHash from a byte slice.  An error is returned if
    67  // the number of bytes passed in is not HashSize.
    68  func NewShaHash(newHash []byte) (*ShaHash, error) {
    69  	var sh ShaHash
    70  	err := sh.SetBytes(newHash)
    71  	if err != nil {
    72  		return nil, err
    73  	}
    74  	return &sh, err
    75  }
    76  
    77  // NewShaHashFromStr creates a ShaHash from a hash string.  The string should be
    78  // the hexadecimal string of a byte-reversed hash, but any missing characters
    79  // result in zero padding at the end of the ShaHash.
    80  func NewShaHashFromStr(hash string) (*ShaHash, error) {
    81  	// Return error if hash string is too long.
    82  	if len(hash) > MaxHashStringSize {
    83  		return nil, ErrHashStrSize
    84  	}
    85  
    86  	// Hex decoder expects the hash to be a multiple of two.
    87  	if len(hash)%2 != 0 {
    88  		hash = "0" + hash
    89  	}
    90  
    91  	// Convert string hash to bytes.
    92  	buf, err := hex.DecodeString(hash)
    93  	if err != nil {
    94  		return nil, err
    95  	}
    96  
    97  	// Un-reverse the decoded bytes, copying into in leading bytes of a
    98  	// ShaHash.  There is no need to explicitly pad the result as any
    99  	// missing (when len(buf) < HashSize) bytes from the decoded hex string
   100  	// will remain zeros at the end of the ShaHash.
   101  	var ret ShaHash
   102  	blen := len(buf)
   103  	mid := blen / 2
   104  	if blen%2 != 0 {
   105  		mid++
   106  	}
   107  	blen--
   108  	for i, b := range buf[:mid] {
   109  		ret[i], ret[blen-i] = buf[blen-i], b
   110  	}
   111  	return &ret, nil
   112  }