1 // Copyright (c) 2013-2016 The btcsuite developers
2 // Copyright (c) 2015 The Decred developers
3 // Use of this source code is governed by an ISC
4 // license that can be found in the LICENSE file.
13 // HashSize of array used to store hashes. See Hash.
16 // MaxHashStringSize is the maximum length of a Hash hash string.
17 const MaxHashStringSize = HashSize * 2
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)
23 // Hash is used in several of the bitcoin messages and common structures. It
24 // typically represents the double sha256 of data.
25 type Hash [HashSize]byte
27 // String returns the Hash as the hexadecimal string of the byte-reversed
29 func (hash Hash) String() string {
30 for i := 0; i < HashSize/2; i++ {
31 hash[i], hash[HashSize-1-i] = hash[HashSize-1-i], hash[i]
33 return hex.EncodeToString(hash[:])
36 // CloneBytes returns a copy of the bytes which represent the hash as a byte
39 // NOTE: It is generally cheaper to just slice the hash directly thereby reusing
40 // the same bytes rather than calling this method.
41 func (hash *Hash) CloneBytes() []byte {
42 newHash := make([]byte, HashSize)
43 copy(newHash, hash[:])
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 *Hash) SetBytes(newHash []byte) error {
52 if nhlen != HashSize {
53 return fmt.Errorf("invalid hash length of %v, want %v", nhlen,
56 copy(hash[:], newHash)
61 // IsEqual returns true if target is the same as hash.
62 func (hash *Hash) IsEqual(target *Hash) bool {
63 if hash == nil && target == nil {
66 if hash == nil || target == nil {
69 return *hash == *target
72 // NewHash returns a new Hash from a byte slice. An error is returned if
73 // the number of bytes passed in is not HashSize.
74 func NewHash(newHash []byte) (*Hash, error) {
76 err := sh.SetBytes(newHash)
83 // NewHashFromStr creates a Hash from a hash string. The string should be
84 // the hexadecimal string of a byte-reversed hash, but any missing characters
85 // result in zero padding at the end of the Hash.
86 func NewHashFromStr(hash string) (*Hash, error) {
88 err := Decode(ret, hash)
95 // Decode decodes the byte-reversed hexadecimal string encoding of a Hash to a
97 func Decode(dst *Hash, src string) error {
98 // Return error if hash string is too long.
99 if len(src) > MaxHashStringSize {
100 return ErrHashStrSize
103 // Hex decoder expects the hash to be a multiple of two. When not, pad
104 // with a leading zero.
107 srcBytes = []byte(src)
109 srcBytes = make([]byte, 1+len(src))
111 copy(srcBytes[1:], src)
114 // Hex decode the source bytes to a temporary destination.
115 var reversedHash Hash
116 _, err := hex.Decode(reversedHash[HashSize-hex.DecodedLen(len(srcBytes)):], srcBytes)
121 // Reverse copy from the temporary hash to destination. Because the
122 // temporary was zeroed, the written result will be correctly padded.
123 for i, b := range reversedHash[:HashSize/2] {
124 dst[i], dst[HashSize-1-i] = reversedHash[HashSize-1-i], b