github.com/bytom/bytom@v1.1.2-0.20221014091027-bbcba3df6075/common/address.go (about) 1 package common 2 3 import ( 4 "bytes" 5 "errors" 6 "fmt" 7 "strings" 8 9 "github.com/bytom/bytom/common/bech32" 10 "github.com/bytom/bytom/consensus" 11 ) 12 13 var ( 14 // ErrChecksumMismatch describes an error where decoding failed due 15 // to a bad checksum. 16 ErrChecksumMismatch = errors.New("checksum mismatch") 17 18 // ErrUnknownAddressType describes an error where an address can not 19 // decoded as a specific address type due to the string encoding 20 // begining with an identifier byte unknown to any standard or 21 // registered (via chaincfg.Register) network. 22 ErrUnknownAddressType = errors.New("unknown address type") 23 24 // ErrAddressCollision describes an error where an address can not 25 // be uniquely determined as either a pay-to-pubkey-hash or 26 // pay-to-script-hash address since the leading identifier is used for 27 // describing both address kinds, but for different networks. Rather 28 // than assuming or defaulting to one or the other, this error is 29 // returned and the caller must decide how to decode the address. 30 ErrAddressCollision = errors.New("address collision") 31 32 // ErrUnsupportedWitnessVer describes an error where a segwit address being 33 // decoded has an unsupported witness version. 34 ErrUnsupportedWitnessVer = errors.New("unsupported witness version") 35 36 // ErrUnsupportedWitnessProgLen describes an error where a segwit address 37 // being decoded has an unsupported witness program length. 38 ErrUnsupportedWitnessProgLen = errors.New("unsupported witness program length") 39 ) 40 41 // Address is an interface type for any type of destination a transaction 42 // output may spend to. This includes pay-to-pubkey (P2PK), pay-to-pubkey-hash 43 // (P2PKH), and pay-to-script-hash (P2SH). Address is designed to be generic 44 // enough that other kinds of addresses may be added in the future without 45 // changing the decoding and encoding API. 46 type Address interface { 47 // String returns the string encoding of the transaction output 48 // destination. 49 // 50 // Please note that String differs subtly from EncodeAddress: String 51 // will return the value as a string without any conversion, while 52 // EncodeAddress may convert destination types (for example, 53 // converting pubkeys to P2PKH addresses) before encoding as a 54 // payment address string. 55 String() string 56 57 // EncodeAddress returns the string encoding of the payment address 58 // associated with the Address value. See the comment on String 59 // for how this method differs from String. 60 EncodeAddress() string 61 62 // ScriptAddress returns the raw bytes of the address to be used 63 // when inserting the address into a txout's script. 64 ScriptAddress() []byte 65 66 // IsForNet returns whether or not the address is associated with the 67 // passed bytom network. 68 IsForNet(*consensus.Params) bool 69 } 70 71 // encodeSegWitAddress creates a bech32 encoded address string representation 72 // from witness version and witness program. 73 func encodeSegWitAddress(hrp string, witnessVersion byte, witnessProgram []byte) (string, error) { 74 // Group the address bytes into 5 bit groups, as this is what is used to 75 // encode each character in the address string. 76 converted, err := bech32.ConvertBits(witnessProgram, 8, 5, true) 77 if err != nil { 78 return "", err 79 } 80 81 // Concatenate the witness version and program, and encode the resulting 82 // bytes using bech32 encoding. 83 combined := make([]byte, len(converted)+1) 84 combined[0] = witnessVersion 85 copy(combined[1:], converted) 86 bech, err := bech32.Bech32Encode(hrp, combined) 87 if err != nil { 88 return "", err 89 } 90 91 // Check validity by decoding the created address. 92 version, program, err := decodeSegWitAddress(bech) 93 if err != nil { 94 return "", fmt.Errorf("invalid segwit address: %v", err) 95 } 96 97 if version != witnessVersion || !bytes.Equal(program, witnessProgram) { 98 return "", fmt.Errorf("invalid segwit address") 99 } 100 101 return bech, nil 102 } 103 104 // DecodeAddress decodes the string encoding of an address and returns 105 // the Address if addr is a valid encoding for a known address type. 106 // 107 // The bytom network the address is associated with is extracted if possible. 108 // When the address does not encode the network, such as in the case of a raw 109 // public key, the address will be associated with the passed defaultNet. 110 func DecodeAddress(addr string, param *consensus.Params) (Address, error) { 111 // Bech32 encoded segwit addresses start with a human-readable part 112 // (hrp) followed by '1'. For Bytom mainnet the hrp is "bm", and for 113 // testnet it is "tm". If the address string has a prefix that matches 114 // one of the prefixes for the known networks, we try to decode it as 115 // a segwit address. 116 oneIndex := strings.LastIndexByte(addr, '1') 117 if oneIndex > 1 { 118 prefix := addr[:oneIndex+1] 119 if consensus.IsBech32SegwitPrefix(prefix, param) { 120 witnessVer, witnessProg, err := decodeSegWitAddress(addr) 121 if err != nil { 122 return nil, err 123 } 124 125 // We currently only support P2WPKH and P2WSH, which is 126 // witness version 0. 127 if witnessVer != 0 { 128 return nil, ErrUnsupportedWitnessVer 129 } 130 131 // The HRP is everything before the found '1'. 132 hrp := prefix[:len(prefix)-1] 133 134 switch len(witnessProg) { 135 case 20: 136 return newAddressWitnessPubKeyHash(hrp, witnessProg) 137 case 32: 138 return newAddressWitnessScriptHash(hrp, witnessProg) 139 default: 140 return nil, ErrUnsupportedWitnessProgLen 141 } 142 } 143 } 144 return nil, ErrUnknownAddressType 145 } 146 147 // decodeSegWitAddress parses a bech32 encoded segwit address string and 148 // returns the witness version and witness program byte representation. 149 func decodeSegWitAddress(address string) (byte, []byte, error) { 150 // Decode the bech32 encoded address. 151 _, data, err := bech32.Bech32Decode(address) 152 if err != nil { 153 return 0, nil, err 154 } 155 156 // The first byte of the decoded address is the witness version, it must 157 // exist. 158 if len(data) < 1 { 159 return 0, nil, fmt.Errorf("no witness version") 160 } 161 162 // ...and be <= 16. 163 version := data[0] 164 if version > 16 { 165 return 0, nil, fmt.Errorf("invalid witness version: %v", version) 166 } 167 168 // The remaining characters of the address returned are grouped into 169 // words of 5 bits. In order to restore the original witness program 170 // bytes, we'll need to regroup into 8 bit words. 171 regrouped, err := bech32.ConvertBits(data[1:], 5, 8, false) 172 if err != nil { 173 return 0, nil, err 174 } 175 176 // The regrouped data must be between 2 and 40 bytes. 177 if len(regrouped) < 2 || len(regrouped) > 40 { 178 return 0, nil, fmt.Errorf("invalid data length") 179 } 180 181 // For witness version 0, address MUST be exactly 20 or 32 bytes. 182 if version == 0 && len(regrouped) != 20 && len(regrouped) != 32 { 183 return 0, nil, fmt.Errorf("invalid data length for witness "+ 184 "version 0: %v", len(regrouped)) 185 } 186 187 return version, regrouped, nil 188 } 189 190 // AddressWitnessPubKeyHash is an Address for a pay-to-witness-pubkey-hash 191 // (P2WPKH) output. See BIP 173 for further details regarding native segregated 192 // witness address encoding: 193 // https://github.com/bitcoin/bips/blob/master/bip-0173.mediawiki 194 type AddressWitnessPubKeyHash struct { 195 hrp string 196 witnessVersion byte 197 witnessProgram [20]byte 198 } 199 200 // NewAddressWitnessPubKeyHash returns a new AddressWitnessPubKeyHash. 201 func NewAddressWitnessPubKeyHash(witnessProg []byte, param *consensus.Params) (*AddressWitnessPubKeyHash, error) { 202 return newAddressWitnessPubKeyHash(param.Bech32HRPSegwit, witnessProg) 203 } 204 205 // newAddressWitnessPubKeyHash is an internal helper function to create an 206 // AddressWitnessPubKeyHash with a known human-readable part, rather than 207 // looking it up through its parameters. 208 func newAddressWitnessPubKeyHash(hrp string, witnessProg []byte) (*AddressWitnessPubKeyHash, error) { 209 // Check for valid program length for witness version 0, which is 20 210 // for P2WPKH. 211 if len(witnessProg) != 20 { 212 return nil, errors.New("witness program must be 20 bytes for p2wpkh") 213 } 214 215 addr := &AddressWitnessPubKeyHash{ 216 hrp: strings.ToLower(hrp), 217 witnessVersion: 0x00, 218 } 219 220 copy(addr.witnessProgram[:], witnessProg) 221 222 return addr, nil 223 } 224 225 // EncodeAddress returns the bech32 string encoding of an 226 // AddressWitnessPubKeyHash. 227 // Part of the Address interface. 228 func (a *AddressWitnessPubKeyHash) EncodeAddress() string { 229 str, err := encodeSegWitAddress(a.hrp, a.witnessVersion, 230 a.witnessProgram[:]) 231 if err != nil { 232 return "" 233 } 234 return str 235 } 236 237 // ScriptAddress returns the witness program for this address. 238 // Part of the Address interface. 239 func (a *AddressWitnessPubKeyHash) ScriptAddress() []byte { 240 return a.witnessProgram[:] 241 } 242 243 // IsForNet returns whether or not the AddressWitnessPubKeyHash is associated 244 // with the passed bitcoin network. 245 // Part of the Address interface. 246 func (a *AddressWitnessPubKeyHash) IsForNet(param *consensus.Params) bool { 247 return a.hrp == param.Bech32HRPSegwit 248 } 249 250 // String returns a human-readable string for the AddressWitnessPubKeyHash. 251 // This is equivalent to calling EncodeAddress, but is provided so the type 252 // can be used as a fmt.Stringer. 253 // Part of the Address interface. 254 func (a *AddressWitnessPubKeyHash) String() string { 255 return a.EncodeAddress() 256 } 257 258 // Hrp returns the human-readable part of the bech32 encoded 259 // AddressWitnessPubKeyHash. 260 func (a *AddressWitnessPubKeyHash) Hrp() string { 261 return a.hrp 262 } 263 264 // WitnessVersion returns the witness version of the AddressWitnessPubKeyHash. 265 func (a *AddressWitnessPubKeyHash) WitnessVersion() byte { 266 return a.witnessVersion 267 } 268 269 // WitnessProgram returns the witness program of the AddressWitnessPubKeyHash. 270 func (a *AddressWitnessPubKeyHash) WitnessProgram() []byte { 271 return a.witnessProgram[:] 272 } 273 274 // Hash160 returns the witness program of the AddressWitnessPubKeyHash as a 275 // byte array. 276 func (a *AddressWitnessPubKeyHash) Hash160() *[20]byte { 277 return &a.witnessProgram 278 } 279 280 // AddressWitnessScriptHash is an Address for a pay-to-witness-script-hash 281 // (P2WSH) output. See BIP 173 for further details regarding native segregated 282 // witness address encoding: 283 // https://github.com/bitcoin/bips/blob/master/bip-0173.mediawiki 284 type AddressWitnessScriptHash struct { 285 hrp string 286 witnessVersion byte 287 witnessProgram [32]byte 288 } 289 290 // NewAddressWitnessScriptHash returns a new AddressWitnessPubKeyHash. 291 func NewAddressWitnessScriptHash(witnessProg []byte, param *consensus.Params) (*AddressWitnessScriptHash, error) { 292 return newAddressWitnessScriptHash(param.Bech32HRPSegwit, witnessProg) 293 } 294 295 // newAddressWitnessScriptHash is an internal helper function to create an 296 // AddressWitnessScriptHash with a known human-readable part, rather than 297 // looking it up through its parameters. 298 func newAddressWitnessScriptHash(hrp string, witnessProg []byte) (*AddressWitnessScriptHash, error) { 299 // Check for valid program length for witness version 0, which is 32 300 // for P2WSH. 301 if len(witnessProg) != 32 { 302 return nil, errors.New("witness program must be 32 bytes for p2wsh") 303 } 304 305 addr := &AddressWitnessScriptHash{ 306 hrp: strings.ToLower(hrp), 307 witnessVersion: 0x00, 308 } 309 310 copy(addr.witnessProgram[:], witnessProg) 311 312 return addr, nil 313 } 314 315 // EncodeAddress returns the bech32 string encoding of an 316 // AddressWitnessScriptHash. 317 // Part of the Address interface. 318 func (a *AddressWitnessScriptHash) EncodeAddress() string { 319 str, err := encodeSegWitAddress(a.hrp, a.witnessVersion, 320 a.witnessProgram[:]) 321 if err != nil { 322 return "" 323 } 324 return str 325 } 326 327 // ScriptAddress returns the witness program for this address. 328 // Part of the Address interface. 329 func (a *AddressWitnessScriptHash) ScriptAddress() []byte { 330 return a.witnessProgram[:] 331 } 332 333 // IsForNet returns whether or not the AddressWitnessScriptHash is associated 334 // with the passed bytom network. 335 // Part of the Address interface. 336 func (a *AddressWitnessScriptHash) IsForNet(param *consensus.Params) bool { 337 return a.hrp == param.Bech32HRPSegwit 338 } 339 340 // String returns a human-readable string for the AddressWitnessScriptHash. 341 // This is equivalent to calling EncodeAddress, but is provided so the type 342 // can be used as a fmt.Stringer. 343 // Part of the Address interface. 344 func (a *AddressWitnessScriptHash) String() string { 345 return a.EncodeAddress() 346 } 347 348 // Hrp returns the human-readable part of the bech32 encoded 349 // AddressWitnessScriptHash. 350 func (a *AddressWitnessScriptHash) Hrp() string { 351 return a.hrp 352 } 353 354 // WitnessVersion returns the witness version of the AddressWitnessScriptHash. 355 func (a *AddressWitnessScriptHash) WitnessVersion() byte { 356 return a.witnessVersion 357 } 358 359 // WitnessProgram returns the witness program of the AddressWitnessScriptHash. 360 func (a *AddressWitnessScriptHash) WitnessProgram() []byte { 361 return a.witnessProgram[:] 362 } 363 364 // Sha256 returns the witness program of the AddressWitnessPubKeyHash as a 365 // byte array. 366 func (a *AddressWitnessScriptHash) Sha256() *[32]byte { 367 return &a.witnessProgram 368 }