github.com/amazechain/amc@v0.1.3/common/types/hash.go (about)

     1  // Copyright 2022 The AmazeChain Authors
     2  // This file is part of the AmazeChain library.
     3  //
     4  // The AmazeChain library is free software: you can redistribute it and/or modify
     5  // it under the terms of the GNU Lesser General Public License as published by
     6  // the Free Software Foundation, either version 3 of the License, or
     7  // (at your option) any later version.
     8  //
     9  // The AmazeChain library is distributed in the hope that it will be useful,
    10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    12  // GNU Lesser General Public License for more details.
    13  //
    14  // You should have received a copy of the GNU Lesser General Public License
    15  // along with the AmazeChain library. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  package types
    18  
    19  import (
    20  	"bytes"
    21  	"database/sql/driver"
    22  	"encoding/hex"
    23  	"fmt"
    24  
    25  	"github.com/amazechain/amc/common/hexutil"
    26  
    27  	"hash"
    28  	"math/big"
    29  	"math/rand"
    30  	"reflect"
    31  
    32  	"golang.org/x/crypto/sha3"
    33  )
    34  
    35  const (
    36  	HashLength = 32
    37  )
    38  
    39  var (
    40  	hashT    = reflect.TypeOf(Hash{})
    41  	addressT = reflect.TypeOf(Address{})
    42  	//addressSt = reflect.TypeOf(Address32{})
    43  )
    44  
    45  type Hash [HashLength]byte
    46  
    47  // Bytes gets the byte representation of the underlying hash.
    48  func (h Hash) Bytes() []byte { return h[:] }
    49  
    50  // Big converts a hash to a big integer.
    51  func (h Hash) Big() *big.Int { return new(big.Int).SetBytes(h[:]) }
    52  
    53  // Hex converts a hash to a hex string.
    54  func (h Hash) Hex() string { return hexutil.Encode(h[:]) }
    55  
    56  // TerminalString implements log.TerminalStringer, formatting a string for console
    57  // output during logging.
    58  func (h Hash) TerminalString() string {
    59  	return fmt.Sprintf("%x…%x", h[:3], h[29:])
    60  }
    61  
    62  // UnmarshalText parses a hash in hex syntax.
    63  func (h *Hash) UnmarshalText(input []byte) error {
    64  	return hexutil.UnmarshalFixedText("Hash", input, h[:])
    65  }
    66  
    67  // MarshalText returns the hex representation of h.
    68  func (h Hash) MarshalText() ([]byte, error) {
    69  	return hexutil.Bytes(h[:]).MarshalText()
    70  }
    71  
    72  // SetBytes sets the hash to the value of b.
    73  func (h *Hash) SetBytes(b []byte) error {
    74  	if len(b) != HashLength {
    75  		return fmt.Errorf("invalid bytes len %d", len(b))
    76  	}
    77  
    78  	copy(h[:], b[:HashLength])
    79  	return nil
    80  }
    81  
    82  // Generate implements testing/quick.Generator.
    83  func (h Hash) Generate(rand *rand.Rand, size int) reflect.Value {
    84  	m := rand.Intn(len(h))
    85  	for i := len(h) - 1; i > m; i-- {
    86  		h[i] = byte(rand.Uint32())
    87  	}
    88  	return reflect.ValueOf(h)
    89  }
    90  
    91  // Scan implements Scanner for database/sql.
    92  func (h *Hash) Scan(src interface{}) error {
    93  	srcB, ok := src.([]byte)
    94  	if !ok {
    95  		return fmt.Errorf("can't scan %T into Hash", src)
    96  	}
    97  	if len(srcB) != HashLength {
    98  		return fmt.Errorf("can't scan []byte of len %d into Hash, want %d", len(srcB), HashLength)
    99  	}
   100  	copy(h[:], srcB)
   101  	return nil
   102  }
   103  
   104  // Value implements valuer for database/sql.
   105  func (h Hash) Value() (driver.Value, error) {
   106  	return h[:], nil
   107  }
   108  
   109  func BytesHash(b []byte) Hash {
   110  	h3 := sha3.New256()
   111  	h3.Write(b)
   112  	r := h3.Sum(nil)
   113  	var h Hash
   114  	copy(h[:], r[:HashLength])
   115  	return h
   116  }
   117  
   118  func BytesToHash(b []byte) Hash {
   119  	var h Hash
   120  	h.SetBytes(b)
   121  	return h
   122  }
   123  
   124  func StringToHash(s string) Hash {
   125  	var h Hash
   126  	b, err := hex.DecodeString(s)
   127  	if err == nil {
   128  		//copy(h[:], b[:HashLength])
   129  		return BytesToHash(b)
   130  	}
   131  
   132  	return h
   133  }
   134  
   135  func (h Hash) String() string {
   136  	return hex.EncodeToString(h[:])
   137  }
   138  
   139  func (h Hash) HexBytes() []byte {
   140  	s := h.String()
   141  	return []byte(s)
   142  }
   143  
   144  func (h *Hash) SetString(s string) error {
   145  	if len(s) != HashLength*2 {
   146  		return fmt.Errorf("invalid string len %v, len(%d)", string(s), len(s))
   147  	}
   148  
   149  	b, err := hex.DecodeString(s)
   150  	if err != nil {
   151  		return err
   152  	}
   153  
   154  	return h.SetBytes(b)
   155  }
   156  
   157  func (h Hash) Marshal() ([]byte, error) {
   158  	return h.Bytes(), nil
   159  }
   160  
   161  func (h *Hash) MarshalTo(data []byte) (n int, err error) {
   162  	copy(data, h.Bytes())
   163  	return len(h.Bytes()), err
   164  }
   165  
   166  func (h *Hash) Unmarshal(data []byte) error {
   167  	return h.SetBytes(data)
   168  }
   169  
   170  func (h *Hash) Size() int {
   171  	return len(h.Bytes())
   172  }
   173  
   174  // Format implements fmt.Formatter.
   175  // Hash supports the %v, %s, %v, %x, %X and %d format verbs.
   176  func (h Hash) Format(s fmt.State, c rune) {
   177  	hexb := make([]byte, 2+len(h)*2)
   178  	copy(hexb, "0x")
   179  	hex.Encode(hexb[2:], h[:])
   180  
   181  	switch c {
   182  	case 'x', 'X':
   183  		if !s.Flag('#') {
   184  			hexb = hexb[2:]
   185  		}
   186  		if c == 'X' {
   187  			hexb = bytes.ToUpper(hexb)
   188  		}
   189  		fallthrough
   190  	case 'v', 's':
   191  		s.Write(hexb)
   192  	case 'q':
   193  		q := []byte{'"'}
   194  		s.Write(q)
   195  		s.Write(hexb)
   196  		s.Write(q)
   197  	case 'd':
   198  		fmt.Fprint(s, ([len(h)]byte)(h))
   199  	default:
   200  		fmt.Fprintf(s, "%%!%c(hash=%x)", c, h)
   201  	}
   202  }
   203  
   204  // UnmarshalJSON parses a hash in hex syntax.
   205  func (h *Hash) UnmarshalJSON(input []byte) error {
   206  	return hexutil.UnmarshalFixedJSON(hashT, input, h[:])
   207  }
   208  
   209  func (h Hash) Equal(other Hash) bool {
   210  	return bytes.Equal(h.Bytes(), other.Bytes())
   211  }
   212  
   213  // HashDifference returns a new set which is the difference between a and b.
   214  func HashDifference(a, b []Hash) []Hash {
   215  	keep := make([]Hash, 0, len(a))
   216  
   217  	remove := make(map[Hash]struct{})
   218  	for _, hash := range b {
   219  		remove[hash] = struct{}{}
   220  	}
   221  
   222  	for _, hash := range a {
   223  		if _, ok := remove[hash]; !ok {
   224  			keep = append(keep, hash)
   225  		}
   226  	}
   227  
   228  	return keep
   229  }
   230  
   231  // keccakState wraps sha3.state. In addition to the usual hash methods, it also supports
   232  // Read to get a variable amount of data from the hash state. Read is faster than Sum
   233  // because it doesn't copy the internal state, but also modifies the internal state.
   234  type keccakState interface {
   235  	hash.Hash
   236  	Read([]byte) (int, error)
   237  }
   238  
   239  type Hasher struct {
   240  	Sha keccakState
   241  }
   242  
   243  var hasherPools = make(chan *Hasher, 128)
   244  
   245  func NewHasher() *Hasher {
   246  	var h *Hasher
   247  	select {
   248  	case h = <-hasherPools:
   249  	default:
   250  		h = &Hasher{Sha: sha3.NewLegacyKeccak256().(keccakState)}
   251  	}
   252  	return h
   253  }
   254  
   255  func ReturnHasherToPool(h *Hasher) {
   256  	select {
   257  	case hasherPools <- h:
   258  	default:
   259  		fmt.Printf("Allowing Hasher to be garbage collected, pool is full\n")
   260  	}
   261  }
   262  
   263  func HashData(data []byte) (Hash, error) {
   264  	h := NewHasher()
   265  	defer ReturnHasherToPool(h)
   266  	h.Sha.Reset()
   267  
   268  	_, err := h.Sha.Write(data)
   269  	if err != nil {
   270  		return Hash{}, err
   271  	}
   272  
   273  	var buf Hash
   274  	_, err = h.Sha.Read(buf[:])
   275  	if err != nil {
   276  		return Hash{}, err
   277  	}
   278  	return buf, nil
   279  }
   280  
   281  // Bytes2Hex returns the hexadecimal encoding of d.
   282  func Bytes2Hex(d []byte) string {
   283  	return hex.EncodeToString(d)
   284  }
   285  
   286  // HexToHash sets byte representation of s to hash.
   287  // If b is larger than len(h), b will be cropped from the left.
   288  func HexToHash(s string) Hash { return BytesToHash(FromHex2Bytes(s)) }
   289  
   290  // FromHex returns the bytes represented by the hexadecimal string s.
   291  // s may be prefixed with "0x".
   292  func FromHex2Bytes(s string) []byte {
   293  	if has0xPrefix(s) {
   294  		s = s[2:]
   295  	}
   296  	if len(s)%2 == 1 {
   297  		s = "0" + s
   298  	}
   299  	return Hex2Bytes(s)
   300  }
   301  
   302  // Hashes is a slice of common.Hash, implementing sort.Interface
   303  type Hashes []Hash
   304  
   305  func (hashes Hashes) Len() int {
   306  	return len(hashes)
   307  }
   308  func (hashes Hashes) Less(i, j int) bool {
   309  	return bytes.Compare(hashes[i][:], hashes[j][:]) == -1
   310  }
   311  func (hashes Hashes) Swap(i, j int) {
   312  	hashes[i], hashes[j] = hashes[j], hashes[i]
   313  }