github.com/dominant-strategies/go-quai@v0.28.2/common/address.go (about)

     1  package common
     2  
     3  import (
     4  	"database/sql/driver"
     5  	"encoding/hex"
     6  	"encoding/json"
     7  	"fmt"
     8  	"reflect"
     9  
    10  	"io"
    11  	"math/big"
    12  
    13  	"github.com/dominant-strategies/go-quai/common/hexutil"
    14  	"github.com/dominant-strategies/go-quai/rlp"
    15  	"golang.org/x/crypto/sha3"
    16  )
    17  
    18  type Address struct {
    19  	inner AddressData
    20  }
    21  
    22  type AddressBytes [20]byte
    23  
    24  type AddressData interface {
    25  	Bytes() []byte
    26  	Hash() Hash
    27  	Hex() string
    28  	String() string
    29  	checksumHex() []byte
    30  	Format(s fmt.State, c rune)
    31  	MarshalText() ([]byte, error)
    32  	UnmarshalText(input []byte) error
    33  	UnmarshalJSON(input []byte) error
    34  	Scan(src interface{}) error
    35  	Value() (driver.Value, error)
    36  	Location() *Location
    37  	setBytes(b []byte)
    38  }
    39  
    40  func (a Address) InternalAddress() (InternalAddress, error) {
    41  	if a.inner == nil {
    42  		return InternalAddress{}, nil
    43  	}
    44  	internal, ok := a.inner.(*InternalAddress)
    45  	if !ok {
    46  		return InternalAddress{}, ErrInvalidScope
    47  	}
    48  	return *internal, nil
    49  }
    50  
    51  func (a Address) Equal(b Address) bool {
    52  	if a.inner == nil && b.inner == nil {
    53  		return true
    54  	} else if a.inner == nil || b.inner == nil {
    55  		return false
    56  	}
    57  	return a.Hash() == b.Hash()
    58  }
    59  
    60  // BytesToAddress returns Address with value b.
    61  // If b is larger than len(h), b will be cropped from the left.
    62  func BytesToAddress(b []byte) Address {
    63  	if IsInChainScope(b) {
    64  		var i InternalAddress
    65  		i.setBytes(b)
    66  		return Address{&i}
    67  	} else {
    68  		var e ExternalAddress
    69  		e.setBytes(b)
    70  		return Address{&e}
    71  	}
    72  }
    73  
    74  func Bytes20ToAddress(b [20]byte) Address {
    75  	return BytesToAddress(b[:])
    76  }
    77  
    78  func NewAddressFromData(inner AddressData) Address {
    79  	return Address{inner: inner}
    80  }
    81  
    82  // EncodeRLP serializes b into the Quai RLP block format.
    83  func (a Address) EncodeRLP(w io.Writer) error {
    84  	if a.inner == nil {
    85  		a.inner = &InternalAddress{}
    86  	}
    87  	return rlp.Encode(w, a.inner)
    88  }
    89  
    90  // DecodeRLP decodes the Quai
    91  func (a *Address) DecodeRLP(s *rlp.Stream) error {
    92  	temp := make([]byte, 0, 20)
    93  	if err := s.Decode(&temp); err != nil {
    94  		return err
    95  	}
    96  	*a = BytesToAddress(temp)
    97  	return nil
    98  }
    99  
   100  // Bytes gets the string representation of the underlying address.
   101  func (a Address) Bytes() []byte {
   102  	if a.inner == nil {
   103  		return []byte{}
   104  	}
   105  	return a.inner.Bytes()
   106  }
   107  
   108  // Bytes20 gets the bytes20 representation of the underlying address.
   109  func (a Address) Bytes20() (addr AddressBytes) {
   110  	if a.inner == nil {
   111  		return AddressBytes{}
   112  	}
   113  	copy(addr[:], a.Bytes()[:]) // this is not very performant
   114  	return addr
   115  }
   116  
   117  // Hash converts an address to a hash by left-padding it with zeros.
   118  func (a Address) Hash() Hash {
   119  	if a.inner == nil {
   120  		return Hash{}
   121  	}
   122  	return a.inner.Hash()
   123  }
   124  
   125  // Hex returns a hex string representation of the address.
   126  func (a Address) Hex() string {
   127  	if a.inner == nil {
   128  		return string([]byte{})
   129  	}
   130  	return a.inner.Hex()
   131  }
   132  
   133  // String implements fmt.Stringer.
   134  func (a Address) String() string {
   135  	if a.inner == nil {
   136  		return string([]byte{})
   137  	}
   138  	return a.inner.String()
   139  }
   140  
   141  // Format implements fmt.Formatter.
   142  // Address supports the %v, %s, %v, %x, %X and %d format verbs.
   143  func (a Address) Format(s fmt.State, c rune) {
   144  	if a.inner != nil {
   145  		a.inner.Format(s, c)
   146  	}
   147  }
   148  
   149  // MarshalText returns the hex representation of a.
   150  func (a Address) MarshalText() ([]byte, error) {
   151  	if a.inner == nil {
   152  		return hexutil.Bytes(ZeroInternal[:]).MarshalText()
   153  	}
   154  	return a.inner.MarshalText()
   155  }
   156  
   157  // UnmarshalText parses a hash in hex syntax.
   158  func (a *Address) UnmarshalText(input []byte) error {
   159  	var temp [AddressLength]byte
   160  	if err := hexutil.UnmarshalFixedText("Address", input, temp[:]); err != nil {
   161  		return err
   162  	}
   163  	a.inner = Bytes20ToAddress(temp).inner
   164  	return nil
   165  }
   166  
   167  // MarshalJSON marshals a subscription as its ID.
   168  func (a *Address) MarshalJSON() ([]byte, error) {
   169  	if a.inner == nil {
   170  		return json.Marshal(ZeroAddr)
   171  	}
   172  	return json.Marshal(a.inner)
   173  }
   174  
   175  // UnmarshalJSON parses a hash in hex syntax.
   176  func (a *Address) UnmarshalJSON(input []byte) error {
   177  	var temp [AddressLength]byte
   178  	if err := hexutil.UnmarshalFixedJSON(reflect.TypeOf(InternalAddress{}), input, temp[:]); err != nil {
   179  		if len(input) == 0 {
   180  			a.inner = Bytes20ToAddress(ZeroInternal).inner
   181  			return nil
   182  		}
   183  		return err
   184  	}
   185  	a.inner = Bytes20ToAddress(temp).inner
   186  	return nil
   187  }
   188  
   189  // Scan implements Scanner for database/sql.
   190  func (a *Address) Scan(src interface{}) error {
   191  	var temp [20]byte
   192  	srcB, ok := src.([]byte)
   193  	if !ok {
   194  		return fmt.Errorf("can't scan %T into Address", src)
   195  	}
   196  	if len(srcB) != AddressLength {
   197  		return fmt.Errorf("can't scan []byte of len %d into Address, want %d", len(srcB), AddressLength)
   198  	}
   199  	copy(temp[:], srcB)
   200  	a.inner = Bytes20ToAddress(temp).inner
   201  	return nil
   202  }
   203  
   204  // Value implements valuer for database/sql.
   205  func (a Address) Value() (driver.Value, error) {
   206  	if a.inner == nil {
   207  		return []byte{}, nil
   208  	}
   209  	return a.inner.Value()
   210  }
   211  
   212  // Location looks up the chain location which contains this address
   213  func (a Address) Location() *Location {
   214  	if a.inner == nil {
   215  		return &NodeLocation
   216  	}
   217  	return a.inner.Location()
   218  }
   219  
   220  // BigToAddress returns Address with byte values of b.
   221  // If b is larger than len(h), b will be cropped from the left.
   222  func BigToAddress(b *big.Int) Address { return BytesToAddress(b.Bytes()) }
   223  
   224  // HexToAddress returns Address with byte values of s.
   225  // If s is larger than len(h), s will be cropped from the left.
   226  func HexToAddress(s string) Address { return BytesToAddress(FromHex(s)) }
   227  
   228  // IsHexAddress verifies whether a string can represent a valid hex-encoded
   229  // Quai address or not.
   230  func IsHexAddress(s string) bool {
   231  	if has0xPrefix(s) {
   232  		s = s[2:]
   233  	}
   234  	return len(s) == 2*AddressLength && isHex(s)
   235  }
   236  
   237  // Hex returns a hex string representation of the address.
   238  func (a AddressBytes) Hex() string {
   239  	return string(a.checksumHex())
   240  }
   241  
   242  // String implements fmt.Stringer.
   243  func (a AddressBytes) String() string {
   244  	return a.Hex()
   245  }
   246  
   247  func (a AddressBytes) checksumHex() []byte {
   248  	buf := a.hex()
   249  
   250  	// compute checksum
   251  	sha := sha3.NewLegacyKeccak256()
   252  	sha.Write(buf[2:])
   253  	hash := sha.Sum(nil)
   254  	for i := 2; i < len(buf); i++ {
   255  		hashByte := hash[(i-2)/2]
   256  		if i%2 == 0 {
   257  			hashByte = hashByte >> 4
   258  		} else {
   259  			hashByte &= 0xf
   260  		}
   261  		if buf[i] > '9' && hashByte > 7 {
   262  			buf[i] -= 32
   263  		}
   264  	}
   265  	return buf[:]
   266  }
   267  
   268  func (a AddressBytes) hex() []byte {
   269  	var buf [len(a)*2 + 2]byte
   270  	copy(buf[:2], "0x")
   271  	hex.Encode(buf[2:], a[:])
   272  	return buf[:]
   273  }