github.com/annchain/OG@v0.0.9/common/hash.go (about)

     1  // Copyright 2015 The go-ethereum Authors
     2  // This file is part of the go-ethereum library.
     3  //
     4  // The go-ethereum 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 go-ethereum 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 go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  package common
    18  
    19  import (
    20  	"crypto/sha256"
    21  	"fmt"
    22  	"github.com/annchain/OG/arefactor/common/utilfuncs"
    23  	"github.com/annchain/OG/common/math"
    24  	"math/big"
    25  	"math/rand"
    26  	"reflect"
    27  
    28  	"bytes"
    29  	"strings"
    30  
    31  	"github.com/annchain/OG/common/hexutil"
    32  )
    33  
    34  //go:generate msgp
    35  
    36  // Length of hash in bytes.
    37  const (
    38  	HashLength = 32
    39  )
    40  
    41  var (
    42  	hashT = reflect.TypeOf(Hash{})
    43  )
    44  
    45  type Padding uint
    46  
    47  const (
    48  	PaddingLeft Padding = iota
    49  	PaddingRight
    50  	PaddingNone
    51  )
    52  
    53  // Hash represents the 32 byte of Hash.
    54  //msgp:tuple Hash
    55  type Hash struct {
    56  	Bytes [HashLength]byte `msgp:"bytes"`
    57  }
    58  
    59  //msgp:tuple Hashes
    60  type Hashes []Hash
    61  
    62  type HashBytes [HashLength]byte
    63  
    64  func (h *Hash) Empty() bool {
    65  	var hs Hash
    66  	return bytes.Equal(h.Bytes[:], hs.Bytes[:])
    67  }
    68  
    69  // BytesToHash sets b to hash.
    70  // If b is larger than len(h), b will be cropped from the left.
    71  func BytesToHash(b []byte) Hash {
    72  	var h Hash
    73  	h.MustSetBytes(b, PaddingLeft)
    74  	return h
    75  }
    76  
    77  // BigToHash sets byte representation of b to Hash.
    78  // If b is larger than len(h), b will be cropped from the left.
    79  func BigToHash(b *big.Int) Hash { return BytesToHash(b.Bytes()) }
    80  
    81  // HexToHash sets byte representation of s to Hash.
    82  // If b is larger than len(h), b will be cropped from the left.
    83  func HexToHash(s string) (hash Hash, err error) {
    84  	bytes, err := FromHex(s)
    85  	if err != nil {
    86  		return
    87  	}
    88  	hash = BytesToHash(bytes)
    89  	return
    90  }
    91  
    92  func HexToHashNoError(s string) (hash Hash) {
    93  	hash, err := HexToHash(s)
    94  	utilfuncs.PanicIfError(err, "hexToHash")
    95  	return
    96  }
    97  
    98  func HexStringsToHashes(ss []string) (hashes Hashes, err error) {
    99  	hashes = make([]Hash, len(ss))
   100  	for i, s := range ss {
   101  		hashes[i], err = HexToHash(s)
   102  		if err != nil {
   103  			return
   104  		}
   105  	}
   106  	return
   107  }
   108  
   109  // ToBytes convers hash to []byte.
   110  func (h Hash) ToBytes() []byte { return h.Bytes[:] }
   111  
   112  // Big converts an Hash to a big integer.
   113  func (h Hash) Big() *big.Int { return new(big.Int).SetBytes(h.Bytes[:]) }
   114  
   115  // Hex converts a Hash to a hex string.
   116  func (h Hash) Hex() string { return hexutil.Encode(h.Bytes[:]) }
   117  
   118  // TerminalString implements log.TerminalStringer, formatting a string for console
   119  // output during logging.
   120  func (h Hash) TerminalString() string {
   121  	return fmt.Sprintf("%x…%x", h.Bytes[:3], h.Bytes[len(h.Bytes)-3:])
   122  }
   123  
   124  // String implements the stringer interface and is used also by the logger when
   125  // doing full logging into a file.
   126  func (h Hash) String() string {
   127  	s := h.Hex()
   128  	return "0x" + s[len(s)-8:]
   129  	//return h.Hex()[:10]
   130  }
   131  
   132  // Format implements fmt.Formatter, forcing the byte slice to be formatted as is,
   133  // without going through the stringer interface used for logging.
   134  //func (h Hash) Format(s fmt.State, c rune) {
   135  //	fmt.Fprintf(s, "%"+string(c), h.KeyBytes)
   136  //}
   137  
   138  // UnmarshalText parses an Hash in hex syntax.
   139  func (h *Hash) UnmarshalText(input []byte) error {
   140  	return hexutil.UnmarshalFixedText("Hash", input, h.Bytes[:])
   141  }
   142  
   143  // UnmarshalJSON parses an Hash in hex syntax.
   144  func (h *Hash) UnmarshalJSON(input []byte) error {
   145  	return hexutil.UnmarshalFixedJSON(hashT, input, h.Bytes[:])
   146  }
   147  
   148  // MarshalText returns the hex representation of h.
   149  func (h Hash) MarshalText() ([]byte, error) {
   150  	return hexutil.Bytes(h.Bytes[:]).MarshalText()
   151  }
   152  
   153  // SetBytes sets the Hash to the value of b.
   154  // If b is larger than len(h), panic. It usually indicates a logic error.
   155  func (h *Hash) MustSetBytes(b []byte, padding Padding) {
   156  	if len(b) > HashLength {
   157  		panic(fmt.Sprintf("bytes to set is longer than expected length: %d > %d", len(b), HashLength))
   158  	}
   159  
   160  	h.Bytes = [HashLength]byte{}
   161  	switch padding {
   162  	case PaddingLeft:
   163  		copy(h.Bytes[HashLength-len(b):], b)
   164  	case PaddingRight:
   165  		copy(h.Bytes[:], b)
   166  	case PaddingNone:
   167  		if len(b) != HashLength {
   168  			panic(fmt.Sprintf("bytes to set is not expected length: %d != %d", len(b), HashLength))
   169  		}
   170  		copy(h.Bytes[:], b)
   171  	}
   172  
   173  }
   174  
   175  func (h *Hash) SetBytes(b []byte) error {
   176  	if len(b) > HashLength {
   177  		return fmt.Errorf("byte to set is longer than expected length: %d > %d", len(b), HashLength)
   178  	}
   179  	h.Bytes = [HashLength]byte{}
   180  	copy(h.Bytes[:], b)
   181  	return nil
   182  }
   183  
   184  // Generate implements testing/quick.Generator.
   185  func (h Hash) Generate(rand *rand.Rand, size int) reflect.Value {
   186  	m := rand.Intn(HashLength)
   187  	for i := HashLength - 1; i > m; i-- {
   188  		h.Bytes[i] = byte(rand.Uint32())
   189  	}
   190  	return reflect.ValueOf(h)
   191  }
   192  
   193  // Cmp compares two hashes.
   194  // Returns  0 if two hashes are same.
   195  // Returns -1 if the self hash is less than parameter hash.
   196  // Returns  1 if the self hash is larger than parameter hash.
   197  func (h Hash) Cmp(another Hash) int {
   198  	for i := 0; i < HashLength; i++ {
   199  		if h.Bytes[i] < another.Bytes[i] {
   200  			return -1
   201  		} else if h.Bytes[i] > another.Bytes[i] {
   202  			return 1
   203  		}
   204  	}
   205  	return 0
   206  }
   207  
   208  func (a Hashes) Len() int           { return len(a) }
   209  func (a Hashes) Swap(i, j int)      { a[i], a[j] = a[j], a[i] }
   210  func (a Hashes) Less(i, j int) bool { return a[i].Hex() < a[j].Hex() }
   211  
   212  func (h Hashes) String() string {
   213  	if h == nil {
   214  		return ""
   215  	}
   216  	var strs []string
   217  	for _, v := range h {
   218  		strs = append(strs, v.String())
   219  	}
   220  	return strings.Join(strs, ", ")
   221  }
   222  
   223  func randomHash() Hash {
   224  	v := math.NewBigInt(rand.Int63())
   225  	sh := BigToHash(v.Value)
   226  	h := sha256.New()
   227  	data := []byte("456544546fhjsiodiruheswer8ih")
   228  	h.Write(sh.Bytes[:])
   229  	h.Write(data)
   230  	sum := h.Sum(nil)
   231  	sh.MustSetBytes(sum, PaddingRight)
   232  	return sh
   233  }
   234  
   235  func RandomHash() Hash {
   236  	return randomHash()
   237  }
   238  
   239  func RandomAddress() Address {
   240  	return randomAddress()
   241  }
   242  
   243  func randomAddress() Address {
   244  	v := math.NewBigInt(rand.Int63())
   245  	adr := BigToAddress(v.Value)
   246  	h := sha256.New()
   247  	data := []byte("abcd8342804fhddhfhisfdyr89")
   248  	h.Write(adr.Bytes[:])
   249  	h.Write(data)
   250  	sum := h.Sum(nil)
   251  	adr.MustSetBytes(sum[:20])
   252  	return adr
   253  }