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

     1  package common
     2  
     3  import (
     4  	"bytes"
     5  	"database/sql/driver"
     6  	"encoding/hex"
     7  	"fmt"
     8  	"reflect"
     9  
    10  	"github.com/dominant-strategies/go-quai/common/hexutil"
    11  	"golang.org/x/crypto/sha3"
    12  )
    13  
    14  type InternalAddress [AddressLength]byte
    15  
    16  // Bytes gets the bytes representation of the underlying address.
    17  func (a InternalAddress) Bytes() []byte { return a[:] }
    18  
    19  // Bytes20 gets the bytes20 representation of the underlying address.
    20  func (a InternalAddress) Bytes20() (addr AddressBytes) { copy(addr[:], a[:]); return addr } // this is not very performant
    21  
    22  // Hash converts an address to a hash by left-padding it with zeros.
    23  func (a InternalAddress) Hash() Hash { return BytesToHash(a[:]) }
    24  
    25  // Hex returns a hex string representation of the address.
    26  func (a InternalAddress) Hex() string {
    27  	return string(a.checksumHex())
    28  }
    29  
    30  // String implements fmt.Stringer.
    31  func (a InternalAddress) String() string {
    32  	return a.Hex()
    33  }
    34  
    35  func (a *InternalAddress) checksumHex() []byte {
    36  	buf := a.hex()
    37  
    38  	// compute checksum
    39  	sha := sha3.NewLegacyKeccak256()
    40  	sha.Write(buf[2:])
    41  	hash := sha.Sum(nil)
    42  	for i := 2; i < len(buf); i++ {
    43  		hashByte := hash[(i-2)/2]
    44  		if i%2 == 0 {
    45  			hashByte = hashByte >> 4
    46  		} else {
    47  			hashByte &= 0xf
    48  		}
    49  		if buf[i] > '9' && hashByte > 7 {
    50  			buf[i] -= 32
    51  		}
    52  	}
    53  	return buf[:]
    54  }
    55  
    56  func (a InternalAddress) hex() []byte {
    57  	var buf [len(a)*2 + 2]byte
    58  	copy(buf[:2], "0x")
    59  	hex.Encode(buf[2:], a[:])
    60  	return buf[:]
    61  }
    62  
    63  // Format implements fmt.Formatter.
    64  // Address supports the %v, %s, %v, %x, %X and %d format verbs.
    65  func (a InternalAddress) Format(s fmt.State, c rune) {
    66  	switch c {
    67  	case 'v', 's':
    68  		s.Write(a.checksumHex())
    69  	case 'q':
    70  		q := []byte{'"'}
    71  		s.Write(q)
    72  		s.Write(a.checksumHex())
    73  		s.Write(q)
    74  	case 'x', 'X':
    75  		// %x disables the checksum.
    76  		hex := a.hex()
    77  		if !s.Flag('#') {
    78  			hex = hex[2:]
    79  		}
    80  		if c == 'X' {
    81  			hex = bytes.ToUpper(hex)
    82  		}
    83  		s.Write(hex)
    84  	case 'd':
    85  		fmt.Fprint(s, ([len(a)]byte)(a))
    86  	default:
    87  		fmt.Fprintf(s, "%%!%c(address=%x)", c, a)
    88  	}
    89  }
    90  
    91  // SetBytes sets the address to the value of b.
    92  // If b is larger than len(a), b will be cropped from the left.
    93  func (a *InternalAddress) setBytes(b []byte) { // May want to check scope here
    94  	if len(b) > len(a) {
    95  		b = b[len(b)-AddressLength:]
    96  	}
    97  	copy(a[AddressLength-len(b):], b)
    98  }
    99  
   100  // MarshalText returns the hex representation of a.
   101  func (a InternalAddress) MarshalText() ([]byte, error) {
   102  	return hexutil.Bytes(a[:]).MarshalText()
   103  }
   104  
   105  // UnmarshalText parses a hash in hex syntax.
   106  func (a *InternalAddress) UnmarshalText(input []byte) error {
   107  	return hexutil.UnmarshalFixedText("Address", input, a[:])
   108  }
   109  
   110  // UnmarshalJSON parses a hash in hex syntax.
   111  func (a *InternalAddress) UnmarshalJSON(input []byte) error {
   112  	return hexutil.UnmarshalFixedJSON(reflect.TypeOf(InternalAddress{}), input, a[:])
   113  }
   114  
   115  // Scan implements Scanner for database/sql.
   116  func (a *InternalAddress) Scan(src interface{}) error {
   117  	srcB, ok := src.([]byte)
   118  	if !ok {
   119  		return fmt.Errorf("can't scan %T into Address", src)
   120  	}
   121  	if len(srcB) != AddressLength {
   122  		return fmt.Errorf("can't scan []byte of len %d into Address, want %d", len(srcB), AddressLength)
   123  	}
   124  	copy(a[:], srcB)
   125  	return nil
   126  }
   127  
   128  // Value implements valuer for database/sql.
   129  func (a InternalAddress) Value() (driver.Value, error) {
   130  	return a[:], nil
   131  }
   132  
   133  func (a InternalAddress) Location() *Location {
   134  	return &NodeLocation
   135  }