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 }