github.com/chain5j/chain5j-pkg@v1.0.7/types/hash.go (about)

     1  // Package types
     2  //
     3  // @author: xwc1125
     4  package types
     5  
     6  import (
     7  	"database/sql/driver"
     8  	"encoding/hex"
     9  	"fmt"
    10  	"math/big"
    11  	"math/rand"
    12  	"reflect"
    13  
    14  	"github.com/chain5j/chain5j-pkg/crypto/hashalg/sha3"
    15  	"github.com/chain5j/chain5j-pkg/util/hexutil"
    16  )
    17  
    18  // HashLength hash长度
    19  const HashLength = 32
    20  
    21  var (
    22  	hashT         = reflect.TypeOf(Hash{})
    23  	EmptyHash     = Hash{}
    24  	EmptyCode     = sha3.Keccak256(nil)
    25  	EmptyCodeHash = BytesToHash(EmptyCode)
    26  	EmptyRootHash = HexToHash("56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421")
    27  	// EmptyRootHash, _ = hashalg.RootHash(codec.Codecor(), nil)
    28  )
    29  
    30  type Hash [HashLength]byte
    31  
    32  func BytesToHash(b []byte) Hash {
    33  	var h Hash
    34  	h.SetBytes(b)
    35  	return h
    36  }
    37  
    38  func StringToHash(s string) Hash {
    39  	return BytesToHash([]byte(s))
    40  }
    41  
    42  func BigToHash(b *big.Int) Hash {
    43  	return BytesToHash(b.Bytes())
    44  }
    45  
    46  func HexToHash(s string) Hash {
    47  	return BytesToHash(hexutil.MustDecode(s))
    48  }
    49  
    50  // Bytes gets the byte representation of the underlying hash.
    51  func (h Hash) Bytes() []byte { return h[:] }
    52  
    53  // Big converts a hash to a big integer.
    54  func (h Hash) Big() *big.Int { return new(big.Int).SetBytes(h[:]) }
    55  
    56  // Hex converts a hash to a hex string.
    57  func (h Hash) Hex() string { return hexutil.Encode(h[:]) }
    58  
    59  func (h Hash) HexNoPrefix() string {
    60  	return hexutil.Encode(h[:])[2:]
    61  }
    62  
    63  // TerminalString implements log.TerminalStringer, formatting a string for console
    64  // output during logging.
    65  func (h Hash) TerminalString() string {
    66  	// return fmt.Sprintf("%x…%x", h[:3], h[29:])
    67  	return h.Hex()
    68  }
    69  
    70  // String implements the stringer interface and is used also by the logger when
    71  // doing full logging into a file.
    72  func (h Hash) String() string {
    73  	return h.Hex()
    74  }
    75  
    76  // Format implements fmt.Formatter, forcing the byte slice to be formatted as is,
    77  // without going through the stringer interface used for logging.
    78  func (h Hash) Format(s fmt.State, c rune) {
    79  	fmt.Fprintf(s, "%"+string(c), h[:])
    80  }
    81  
    82  // UnmarshalText parses a hash in hex syntax.
    83  func (h *Hash) UnmarshalText(input []byte) error {
    84  	return hexutil.UnmarshalFixedText("Hash", input, h[:])
    85  }
    86  
    87  // UnmarshalJSON parses a hash in hex syntax.
    88  func (h *Hash) UnmarshalJSON(input []byte) error {
    89  	return hexutil.UnmarshalFixedJSON(hashT, input, h[:])
    90  }
    91  
    92  // MarshalText returns the hex representation of h.
    93  func (h Hash) MarshalText() ([]byte, error) {
    94  	return hexutil.Bytes(h[:]).MarshalText()
    95  }
    96  
    97  // SetBytes sets the hash to the value of b.
    98  // If b is larger than len(h), b will be cropped from the left.
    99  func (h *Hash) SetBytes(b []byte) {
   100  	if len(b) > len(h) {
   101  		b = b[len(b)-HashLength:]
   102  	}
   103  
   104  	copy(h[HashLength-len(b):], b)
   105  }
   106  
   107  // Generate implements testing/quick.Generator.
   108  func (h Hash) Generate(rand *rand.Rand, size int) reflect.Value {
   109  	m := rand.Intn(len(h))
   110  	for i := len(h) - 1; i > m; i-- {
   111  		h[i] = byte(rand.Uint32())
   112  	}
   113  	return reflect.ValueOf(h)
   114  }
   115  
   116  func IsEmptyHash(h Hash) bool {
   117  	return h == Hash{}
   118  }
   119  
   120  // Scan implements Scanner for database/sql.
   121  func (h *Hash) Scan(src interface{}) error {
   122  	srcB, ok := src.([]byte)
   123  	if !ok {
   124  		return fmt.Errorf("can't scan %T into Hash", src)
   125  	}
   126  	if len(srcB) != HashLength {
   127  		return fmt.Errorf("can't scan []byte of len %d into Hash, want %d", len(srcB), HashLength)
   128  	}
   129  	copy(h[:], srcB)
   130  	return nil
   131  }
   132  
   133  // Value implements valuer for database/sql.
   134  func (h Hash) Value() (driver.Value, error) {
   135  	return h[:], nil
   136  }
   137  
   138  func (h Hash) Nil() bool {
   139  	return h == Hash{}
   140  }
   141  
   142  // UnprefixedHash allows marshaling a Hash without 0x prefix.
   143  type UnprefixedHash Hash
   144  
   145  // UnmarshalText decodes the hash from hex. The 0x prefix is optional.
   146  func (h *UnprefixedHash) UnmarshalText(input []byte) error {
   147  	return hexutil.UnmarshalFixedUnprefixedText("UnprefixedHash", input, h[:])
   148  }
   149  
   150  // MarshalText encodes the hash as hex.
   151  func (h UnprefixedHash) MarshalText() ([]byte, error) {
   152  	return []byte(hex.EncodeToString(h[:])), nil
   153  }