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  }