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 }