github.com/Bytom/bytom@v1.1.2-0.20210127130405-ae40204c0b09/protocol/bc/hash.go (about) 1 package bc 2 3 import ( 4 "bytes" 5 "encoding/binary" 6 "encoding/hex" 7 "encoding/json" 8 "fmt" 9 "io" 10 11 "golang.org/x/crypto/sha3" 12 ) 13 14 // EmptyStringHash represents a 256-bit hash. 15 var EmptyStringHash = NewHash(sha3.Sum256(nil)) 16 17 // NewHash convert the input byte array to hash 18 func NewHash(b32 [32]byte) (h Hash) { 19 h.V0 = binary.BigEndian.Uint64(b32[0:8]) 20 h.V1 = binary.BigEndian.Uint64(b32[8:16]) 21 h.V2 = binary.BigEndian.Uint64(b32[16:24]) 22 h.V3 = binary.BigEndian.Uint64(b32[24:32]) 23 return h 24 } 25 26 // Byte32 return the byte array representation 27 func (h Hash) Byte32() (b32 [32]byte) { 28 binary.BigEndian.PutUint64(b32[0:8], h.V0) 29 binary.BigEndian.PutUint64(b32[8:16], h.V1) 30 binary.BigEndian.PutUint64(b32[16:24], h.V2) 31 binary.BigEndian.PutUint64(b32[24:32], h.V3) 32 return b32 33 } 34 35 // MarshalText satisfies the TextMarshaler interface. 36 // It returns the bytes of h encoded in hex, 37 // for formats that can't hold arbitrary binary data. 38 // It never returns an error. 39 func (h Hash) MarshalText() ([]byte, error) { 40 b := h.Byte32() 41 v := make([]byte, 64) 42 hex.Encode(v, b[:]) 43 return v, nil 44 } 45 46 // UnmarshalText satisfies the TextUnmarshaler interface. 47 // It decodes hex data from b into h. 48 func (h *Hash) UnmarshalText(v []byte) error { 49 var b [32]byte 50 if len(v) != 64 { 51 return fmt.Errorf("bad length hash string %d", len(v)) 52 } 53 _, err := hex.Decode(b[:], v) 54 *h = NewHash(b) 55 return err 56 } 57 58 // UnmarshalJSON satisfies the json.Unmarshaler interface. 59 // If b is a JSON-encoded null, it copies the zero-value into h. Othwerwise, it 60 // decodes hex data from b into h. 61 func (h *Hash) UnmarshalJSON(b []byte) error { 62 if bytes.Equal(b, []byte("null")) { 63 *h = Hash{} 64 return nil 65 } 66 var s string 67 if err := json.Unmarshal(b, &s); err != nil { 68 return err 69 } 70 return h.UnmarshalText([]byte(s)) 71 } 72 73 // Bytes returns the byte representation 74 func (h Hash) Bytes() []byte { 75 b32 := h.Byte32() 76 return b32[:] 77 } 78 79 // WriteTo satisfies the io.WriterTo interface. 80 func (h Hash) WriteTo(w io.Writer) (int64, error) { 81 n, err := w.Write(h.Bytes()) 82 return int64(n), err 83 } 84 85 // ReadFrom satisfies the io.ReaderFrom interface. 86 func (h *Hash) ReadFrom(r io.Reader) (int64, error) { 87 var b32 [32]byte 88 n, err := io.ReadFull(r, b32[:]) 89 if err != nil { 90 return int64(n), err 91 } 92 *h = NewHash(b32) 93 return int64(n), nil 94 } 95 96 // IsZero tells whether a Hash pointer is nil or points to an all-zero 97 // hash. 98 func (h *Hash) IsZero() bool { 99 if h == nil { 100 return true 101 } 102 return *h == Hash{} 103 }