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 }