github.com/arieschain/arieschain@v0.0.0-20191023063405-37c074544356/common/types.go (about)

     1  package common
     2  
     3  import (
     4  	"encoding/hex"
     5  	"encoding/json"
     6  	"fmt"
     7  	"math/big"
     8  	"math/rand"
     9  	"reflect"
    10  	"strings"
    11  
    12  	"github.com/quickchainproject/quickchain/common/hexutil"
    13  	"github.com/quickchainproject/quickchain/crypto/sha3"
    14  )
    15  
    16  const (
    17  	HashLength    = 32
    18  	AddressLength = 20
    19  	UUIDLength    = 16
    20  )
    21  
    22  var (
    23  	hashT    = reflect.TypeOf(Hash{})
    24  	addressT = reflect.TypeOf(Address{})
    25  )
    26  
    27  // Hash represents the 32 byte Keccak256 hash of arbitrary data.
    28  type Hash [HashLength]byte
    29  
    30  func BytesToHash(b []byte) Hash {
    31  	var h Hash
    32  	h.SetBytes(b)
    33  	return h
    34  }
    35  func BigToHash(b *big.Int) Hash { return BytesToHash(b.Bytes()) }
    36  func HexToHash(s string) Hash   { return BytesToHash(FromHex(s)) }
    37  func StringToHash(s string) Hash { return BytesToHash([]byte(s)) }
    38  
    39  // Get the string representation of the underlying hash
    40  func (h Hash) Str() string   { return string(h[:]) }
    41  func (h Hash) Bytes() []byte { return h[:] }
    42  func (h Hash) Big() *big.Int { return new(big.Int).SetBytes(h[:]) }
    43  func (h Hash) Hex() string   { return hexutil.Encode(h[:]) }
    44  
    45  // TerminalString implements log.TerminalStringer, formatting a string for console
    46  // output during logging.
    47  func (h Hash) TerminalString() string {
    48  	return fmt.Sprintf("%x…%x", h[:3], h[29:])
    49  }
    50  
    51  // String implements the stringer interface and is used also by the logger when
    52  // doing full logging into a file.
    53  func (h Hash) String() string {
    54  	return h.Hex()
    55  }
    56  
    57  // Format implements fmt.Formatter, forcing the byte slice to be formatted as is,
    58  // without going through the stringer interface used for logging.
    59  func (h Hash) Format(s fmt.State, c rune) {
    60  	fmt.Fprintf(s, "%"+string(c), h[:])
    61  }
    62  
    63  // UnmarshalText parses a hash in hex syntax.
    64  func (h *Hash) UnmarshalText(input []byte) error {
    65  	return hexutil.UnmarshalFixedText("Hash", input, h[:])
    66  }
    67  
    68  // UnmarshalJSON parses a hash in hex syntax.
    69  func (h *Hash) UnmarshalJSON(input []byte) error {
    70  	return hexutil.UnmarshalFixedJSON(hashT, input, h[:])
    71  }
    72  
    73  // MarshalText returns the hex representation of h.
    74  func (h Hash) MarshalText() ([]byte, error) {
    75  	return hexutil.Bytes(h[:]).MarshalText()
    76  }
    77  
    78  // Sets the hash to the value of b. If b is larger than len(h), 'b' will be cropped (from the left).
    79  func (h *Hash) SetBytes(b []byte) {
    80  	if len(b) > len(h) {
    81  		b = b[len(b)-HashLength:]
    82  	}
    83  
    84  	copy(h[HashLength-len(b):], b)
    85  }
    86  
    87  // Set string `s` to h. If s is larger than len(h) s will be cropped (from left) to fit.
    88  func (h *Hash) SetString(s string) { h.SetBytes([]byte(s)) }
    89  
    90  // Sets h to other
    91  func (h *Hash) Set(other Hash) {
    92  	for i, v := range other {
    93  		h[i] = v
    94  	}
    95  }
    96  
    97  // Generate implements testing/quick.Generator.
    98  func (h Hash) Generate(rand *rand.Rand, size int) reflect.Value {
    99  	m := rand.Intn(len(h))
   100  	for i := len(h) - 1; i > m; i-- {
   101  		h[i] = byte(rand.Uint32())
   102  	}
   103  	return reflect.ValueOf(h)
   104  }
   105  
   106  func EmptyHash(h Hash) bool {
   107  	return h == Hash{}
   108  }
   109  
   110  // UnprefixedHash allows marshaling a Hash without 0x prefix.
   111  type UnprefixedHash Hash
   112  
   113  // UnmarshalText decodes the hash from hex. The 0x prefix is optional.
   114  func (h *UnprefixedHash) UnmarshalText(input []byte) error {
   115  	return hexutil.UnmarshalFixedUnprefixedText("UnprefixedHash", input, h[:])
   116  }
   117  
   118  // MarshalText encodes the hash as hex.
   119  func (h UnprefixedHash) MarshalText() ([]byte, error) {
   120  	return []byte(hex.EncodeToString(h[:])), nil
   121  }
   122  
   123  /////////// Address
   124  
   125  // Address represents the 20 byte address of an Ethereum account.
   126  type Address [AddressLength]byte
   127  
   128  var (
   129  	ZeroAddress       = Address{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}
   130  	ZeroAddressString = "0x0000000000000000000000000000000000000000"
   131  )
   132  
   133  func BytesToAddress(b []byte) Address {
   134  	var a Address
   135  	a.SetBytes(b)
   136  	return a
   137  }
   138  func BigToAddress(b *big.Int) Address { return BytesToAddress(b.Bytes()) }
   139  func HexToAddress(s string) Address   { return BytesToAddress(FromHex(s)) }
   140  func StringToAddress(s string) Address { return BytesToAddress([]byte(s)) }
   141  
   142  // IsHexAddress verifies whether a string can represent a valid hex-encoded
   143  // Ethereum address or not.
   144  func IsHexAddress(s string) bool {
   145  	if hasHexPrefix(s) {
   146  		s = s[2:]
   147  	}
   148  	return len(s) == 2*AddressLength && isHex(s)
   149  }
   150  
   151  // Get the string representation of the underlying address
   152  func (a Address) Str() string   { return string(a[:]) }
   153  func (a Address) Bytes() []byte { return a[:] }
   154  func (a Address) Big() *big.Int { return new(big.Int).SetBytes(a[:]) }
   155  func (a Address) Hash() Hash    { return BytesToHash(a[:]) }
   156  
   157  // Hex returns an EIP55-compliant hex string representation of the address.
   158  func (a Address) Hex() string {
   159  	unchecksummed := hex.EncodeToString(a[:])
   160  	sha := sha3.NewKeccak256()
   161  	sha.Write([]byte(unchecksummed))
   162  	hash := sha.Sum(nil)
   163  
   164  	result := []byte(unchecksummed)
   165  	for i := 0; i < len(result); i++ {
   166  		hashByte := hash[i/2]
   167  		if i%2 == 0 {
   168  			hashByte = hashByte >> 4
   169  		} else {
   170  			hashByte &= 0xf
   171  		}
   172  		if result[i] > '9' && hashByte > 7 {
   173  			result[i] -= 32
   174  		}
   175  	}
   176  	return "0x" + string(result)
   177  }
   178  
   179  // String implements the stringer interface and is used also by the logger.
   180  func (a Address) String() string {
   181  	return a.Hex()
   182  }
   183  
   184  // Format implements fmt.Formatter, forcing the byte slice to be formatted as is,
   185  // without going through the stringer interface used for logging.
   186  func (a Address) Format(s fmt.State, c rune) {
   187  	fmt.Fprintf(s, "%"+string(c), a[:])
   188  }
   189  
   190  // Sets the address to the value of b. If b is larger than len(a) it will panic
   191  func (a *Address) SetBytes(b []byte) {
   192  	if len(b) > len(a) {
   193  		b = b[len(b)-AddressLength:]
   194  	}
   195  	copy(a[AddressLength-len(b):], b)
   196  }
   197  
   198  // Set string `s` to a. If s is larger than len(a) it will panic
   199  func (a *Address) SetString(s string) { a.SetBytes([]byte(s)) }
   200  
   201  // Sets a to other
   202  func (a *Address) Set(other Address) {
   203  	for i, v := range other {
   204  		a[i] = v
   205  	}
   206  }
   207  
   208  // MarshalText returns the hex representation of a.
   209  func (a Address) MarshalText() ([]byte, error) {
   210  	return hexutil.Bytes(a[:]).MarshalText()
   211  }
   212  
   213  // UnmarshalText parses a hash in hex syntax.
   214  func (a *Address) UnmarshalText(input []byte) error {
   215  	return hexutil.UnmarshalFixedText("Address", input, a[:])
   216  }
   217  
   218  // UnmarshalJSON parses a hash in hex syntax.
   219  func (a *Address) UnmarshalJSON(input []byte) error {
   220  	return hexutil.UnmarshalFixedJSON(addressT, input, a[:])
   221  }
   222  
   223  // UnprefixedHash allows marshaling an Address without 0x prefix.
   224  type UnprefixedAddress Address
   225  
   226  // UnmarshalText decodes the address from hex. The 0x prefix is optional.
   227  func (a *UnprefixedAddress) UnmarshalText(input []byte) error {
   228  	return hexutil.UnmarshalFixedUnprefixedText("UnprefixedAddress", input, a[:])
   229  }
   230  
   231  // MarshalText encodes the address as hex.
   232  func (a UnprefixedAddress) MarshalText() ([]byte, error) {
   233  	return []byte(hex.EncodeToString(a[:])), nil
   234  }
   235  
   236  // MixedcaseAddress retains the original string, which may or may not be
   237  // correctly checksummed
   238  type MixedcaseAddress struct {
   239  	addr     Address
   240  	original string
   241  }
   242  
   243  // NewMixedcaseAddress constructor (mainly for testing)
   244  func NewMixedcaseAddress(addr Address) MixedcaseAddress {
   245  	return MixedcaseAddress{addr: addr, original: addr.Hex()}
   246  }
   247  
   248  // NewMixedcaseAddressFromString is mainly meant for unit-testing
   249  func NewMixedcaseAddressFromString(hexaddr string) (*MixedcaseAddress, error) {
   250  	if !IsHexAddress(hexaddr) {
   251  		return nil, fmt.Errorf("Invalid address")
   252  	}
   253  	a := FromHex(hexaddr)
   254  	return &MixedcaseAddress{addr: BytesToAddress(a), original: hexaddr}, nil
   255  }
   256  
   257  // UnmarshalJSON parses MixedcaseAddress
   258  func (ma *MixedcaseAddress) UnmarshalJSON(input []byte) error {
   259  	if err := hexutil.UnmarshalFixedJSON(addressT, input, ma.addr[:]); err != nil {
   260  		return err
   261  	}
   262  	return json.Unmarshal(input, &ma.original)
   263  }
   264  
   265  // MarshalJSON marshals the original value
   266  func (ma *MixedcaseAddress) MarshalJSON() ([]byte, error) {
   267  	if strings.HasPrefix(ma.original, "0x") || strings.HasPrefix(ma.original, "0X") {
   268  		return json.Marshal(fmt.Sprintf("0x%s", ma.original[2:]))
   269  	}
   270  	return json.Marshal(fmt.Sprintf("0x%s", ma.original))
   271  }
   272  
   273  // Address returns the address
   274  func (ma *MixedcaseAddress) Address() Address {
   275  	return ma.addr
   276  }
   277  
   278  // String implements fmt.Stringer
   279  func (ma *MixedcaseAddress) String() string {
   280  	if ma.ValidChecksum() {
   281  		return fmt.Sprintf("%s [chksum ok]", ma.original)
   282  	}
   283  	return fmt.Sprintf("%s [chksum INVALID]", ma.original)
   284  }
   285  
   286  // ValidChecksum returns true if the address has valid checksum
   287  func (ma *MixedcaseAddress) ValidChecksum() bool {
   288  	return ma.original == ma.addr.Hex()
   289  }
   290  
   291  // Original returns the mixed-case input string
   292  func (ma *MixedcaseAddress) Original() string {
   293  	return ma.original
   294  }
   295  
   296  /////////// UUID
   297  
   298  // UUID represents the 16 byte address.
   299  type UUID [UUIDLength]byte
   300  
   301  var (
   302  	ZeroUUID       = UUID{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}
   303  	ZeroUUIDString = "0x00000000000000000000000000000000"
   304  )
   305  
   306  func BytesToUUID(b []byte) UUID {
   307  	var a UUID
   308  	a.SetBytes(b)
   309  	return a
   310  }
   311  
   312  func BigToUUID(b *big.Int) UUID { return BytesToUUID(b.Bytes()) }
   313  func HexToUUID(s string) UUID   { return BytesToUUID(FromHex(s)) }
   314  
   315  // IsHexAddress verifies whether a string can represent a valid hex-encoded
   316  // Ethereum address or not.
   317  func IsHexUUID(s string) bool {
   318  	if hasHexPrefix(s) {
   319  		s = s[2:]
   320  	}
   321  	return len(s) == 2*UUIDLength && isHex(s)
   322  }
   323  
   324  // Get the string representation of the underlying UUID
   325  func (a UUID) Str() string   { return string(a[:]) }
   326  func (a UUID) Bytes() []byte { return a[:] }
   327  func (a UUID) Big() *big.Int { return new(big.Int).SetBytes(a[:]) }
   328  func (a UUID) Hash() Hash    { return BytesToHash(a[:]) }
   329  
   330  // Hex returns an EIP55-compliant hex string representation of the address.
   331  func (a UUID) Hex() string {
   332  	unchecksummed := hex.EncodeToString(a[:])
   333  	sha := sha3.NewKeccak256()
   334  	sha.Write([]byte(unchecksummed))
   335  	hash := sha.Sum(nil)
   336  
   337  	result := []byte(unchecksummed)
   338  	for i := 0; i < len(result); i++ {
   339  		hashByte := hash[i/2]
   340  		if i%2 == 0 {
   341  			hashByte = hashByte >> 4
   342  		} else {
   343  			hashByte &= 0xf
   344  		}
   345  		if result[i] > '9' && hashByte > 7 {
   346  			result[i] -= 32
   347  		}
   348  	}
   349  	return "0x" + string(result)
   350  }
   351  
   352  // String implements the stringer interface and is used also by the logger.
   353  func (a UUID) String() string {
   354  	return a.Hex()
   355  }
   356  
   357  // Format implements fmt.Formatter, forcing the byte slice to be formatted as is,
   358  // without going through the stringer interface used for logging.
   359  func (a UUID) Format(s fmt.State, c rune) {
   360  	fmt.Fprintf(s, "%"+string(c), a[:])
   361  }
   362  
   363  // Sets the UUID to the value of b. If b is larger than len(a) it will panic
   364  func (a *UUID) SetBytes(b []byte) {
   365  	if len(b) > len(a) {
   366  		b = b[len(b)-UUIDLength:]
   367  	}
   368  	copy(a[UUIDLength-len(b):], b)
   369  }
   370  
   371  // Set string `s` to a. If s is larger than len(a) it will panic
   372  func (a *UUID) SetString(s string) { a.SetBytes([]byte(s)) }
   373  
   374  // Sets a to other
   375  func (a *UUID) Set(other UUID) {
   376  	for i, v := range other {
   377  		a[i] = v
   378  	}
   379  }