github.com/amazechain/amc@v0.1.3/common/types/address.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  	"strings"
    25  
    26  	"github.com/amazechain/amc/common/hexutil"
    27  	"github.com/libp2p/go-libp2p/core/crypto"
    28  	"golang.org/x/crypto/sha3"
    29  )
    30  
    31  const (
    32  	AddressLength = 20
    33  	// IncarnationLength length of uint64 for contract incarnations
    34  	IncarnationLength = 2
    35  	// Address32Length is the expected length of the Starknet address (in bytes)
    36  	Address32Length = 32
    37  )
    38  
    39  var (
    40  	prefixAddress = "AMC"
    41  	nullAddress   = Address{0}
    42  )
    43  
    44  type Address [AddressLength]byte
    45  
    46  // BytesToAddress returns Address with value b.
    47  // If b is larger than len(h), b will be cropped from the left.
    48  func BytesToAddress(b []byte) Address {
    49  	var a Address
    50  	a.SetBytes(b)
    51  	return a
    52  }
    53  
    54  // HexToAddress returns Address with byte values of s.
    55  // If s is larger than len(h), s will be cropped from the left.
    56  func HexToAddress(s string) Address { return BytesToAddress(FromHex1(s)) }
    57  
    58  func PublicToAddress(key crypto.PubKey) Address {
    59  	bPub, err := crypto.MarshalPublicKey(key)
    60  	if err != nil {
    61  		return Address{0}
    62  	}
    63  
    64  	h := sha3.New256()
    65  	h.Write(bPub)
    66  	hash := h.Sum(nil)
    67  	var addr Address
    68  	copy(addr[:], hash[:AddressLength])
    69  	return addr
    70  }
    71  
    72  func PrivateToAddress(key crypto.PrivKey) Address {
    73  	return PublicToAddress(key.GetPublic())
    74  }
    75  
    76  func HexToString(hexs string) (Address, error) {
    77  	a := Address{0}
    78  	if !strings.HasPrefix(strings.ToUpper(hexs), prefixAddress) {
    79  		return a, fmt.Errorf("invalid prefix address")
    80  	}
    81  
    82  	b, err := hex.DecodeString(hexs[len(prefixAddress):])
    83  	if err != nil {
    84  		return a, err
    85  	}
    86  
    87  	copy(a[:], b)
    88  
    89  	return a, nil
    90  }
    91  
    92  // IsHexAddress verifies whether a string can represent a valid hex-encoded
    93  // Ethereum address or not.
    94  func IsHexAddress(s string) bool {
    95  	if has0xPrefix(s) {
    96  		s = s[2:]
    97  	}
    98  	return len(s) == 2*AddressLength && isHex(s)
    99  }
   100  
   101  // Bytes gets the string representation of the underlying address.
   102  func (a Address) Bytes() []byte { return a[:] }
   103  
   104  // Hash converts an address to a hash by left-padding it with zeros.
   105  func (a Address) Hash() Hash { return BytesToHash(a[:]) }
   106  
   107  // Hex returns an EIP55-compliant hex string representation of the address.
   108  func (a Address) Hex() string {
   109  	return string(a.checksumHex())
   110  }
   111  
   112  // String implements fmt.Stringer.
   113  func (a Address) String() string {
   114  	return a.Hex()
   115  }
   116  
   117  // Addresses is a slice of common.Address, implementing sort.Interface
   118  type Addresses []Address
   119  
   120  func (addrs Addresses) Len() int {
   121  	return len(addrs)
   122  }
   123  func (addrs Addresses) Less(i, j int) bool {
   124  	return bytes.Compare(addrs[i][:], addrs[j][:]) == -1
   125  }
   126  func (addrs Addresses) Swap(i, j int) {
   127  	addrs[i], addrs[j] = addrs[j], addrs[i]
   128  }
   129  
   130  func (a *Address) checksumHex() []byte {
   131  	buf := a.hex()
   132  
   133  	// compute checksum
   134  	sha := sha3.NewLegacyKeccak256()
   135  	//nolint:errcheck
   136  	sha.Write(buf[2:])
   137  	hash := sha.Sum(nil)
   138  	for i := 2; i < len(buf); i++ {
   139  		hashByte := hash[(i-2)/2]
   140  		if i%2 == 0 {
   141  			hashByte = hashByte >> 4
   142  		} else {
   143  			hashByte &= 0xf
   144  		}
   145  		if buf[i] > '9' && hashByte > 7 {
   146  			buf[i] -= 32
   147  		}
   148  	}
   149  	return buf
   150  }
   151  
   152  func (a Address) hex() []byte {
   153  	var buf [len(a)*2 + 2]byte
   154  	copy(buf[:2], "0x")
   155  	hex.Encode(buf[2:], a[:])
   156  	return buf[:]
   157  }
   158  
   159  func (a *Address) DecodeBytes(b []byte) bool {
   160  	if len(b) != AddressLength {
   161  		return false
   162  	}
   163  
   164  	copy(a[:], b)
   165  	return true
   166  }
   167  
   168  func (a *Address) DecodeString(s string) bool {
   169  	if !strings.HasPrefix(strings.ToUpper(s), prefixAddress) {
   170  		return false
   171  	}
   172  
   173  	b, err := hex.DecodeString(s[len(prefixAddress):])
   174  	if err != nil {
   175  		a = &Address{0}
   176  		return false
   177  	}
   178  
   179  	copy(a[:], b)
   180  	return true
   181  }
   182  
   183  func (a Address) Equal(other Address) bool {
   184  	return bytes.Equal(a[:], other[:])
   185  }
   186  
   187  func (a *Address) IsNull() bool {
   188  	return bytes.Equal(a[:], nullAddress[:])
   189  }
   190  
   191  func (a Address) Marshal() ([]byte, error) {
   192  	return a.Bytes(), nil
   193  }
   194  
   195  func (a *Address) MarshalTo(data []byte) (n int, err error) {
   196  	copy(data, a[:])
   197  	return len(data), nil
   198  }
   199  
   200  func (a *Address) Unmarshal(data []byte) error {
   201  	if len(data) != AddressLength {
   202  		return fmt.Errorf("invalid bytes len: %d, hex: %s", len(data), a.Hex())
   203  	}
   204  
   205  	copy(a[:], data)
   206  	return nil
   207  }
   208  
   209  // SetBytes sets the address to the value of b.
   210  // If b is larger than len(a), b will be cropped from the left.
   211  func (a *Address) SetBytes(b []byte) *Address {
   212  	if len(b) > len(a) {
   213  		b = b[len(b)-AddressLength:]
   214  	}
   215  	copy(a[AddressLength-len(b):], b)
   216  	return a
   217  }
   218  
   219  // MarshalText returns the hex representation of a.
   220  func (a Address) MarshalText() ([]byte, error) {
   221  	return hexutil.Bytes(a[:]).MarshalText()
   222  }
   223  
   224  // UnmarshalText parses a hash in hex syntax.
   225  func (a *Address) UnmarshalText(input []byte) error {
   226  	return hexutil.UnmarshalFixedText("Address", input, a[:])
   227  }
   228  
   229  // UnmarshalJSON parses a hash in hex syntax.
   230  func (a *Address) UnmarshalJSON(input []byte) error {
   231  	return hexutil.UnmarshalFixedJSON(addressT, input, a[:])
   232  }
   233  
   234  // Scan implements Scanner for database/sql.
   235  func (a *Address) Scan(src interface{}) error {
   236  	srcB, ok := src.([]byte)
   237  	if !ok {
   238  		return fmt.Errorf("can't scan %T into Address", src)
   239  	}
   240  	if len(srcB) != AddressLength {
   241  		return fmt.Errorf("can't scan []byte of len %d into Address, want %d", len(srcB), AddressLength)
   242  	}
   243  	copy(a[:], srcB)
   244  	return nil
   245  }
   246  
   247  // Value implements valuer for database/sql.
   248  func (a Address) Value() (driver.Value, error) {
   249  	return a[:], nil
   250  }
   251  
   252  func (a Address) Size() int {
   253  	return AddressLength
   254  }
   255  
   256  // isHex validates whether each byte is valid hexadecimal string.
   257  func isHex(str string) bool {
   258  	if len(str)%2 != 0 {
   259  		return false
   260  	}
   261  	for _, c := range []byte(str) {
   262  		if !isHexCharacter(c) {
   263  			return false
   264  		}
   265  	}
   266  	return true
   267  }
   268  
   269  // isHexCharacter returns bool of c being a valid hexadecimal.
   270  func isHexCharacter(c byte) bool {
   271  	return ('0' <= c && c <= '9') || ('a' <= c && c <= 'f') || ('A' <= c && c <= 'F')
   272  }