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 }