github.com/mit-dci/lit@v0.0.0-20221102210550-8c3d3b49f2ce/btcutil/address.go (about) 1 // Copyright (c) 2013, 2014 The btcsuite developers 2 // Use of this source code is governed by an ISC 3 // license that can be found in the LICENSE file. 4 5 package btcutil 6 7 import ( 8 "bytes" 9 "encoding/hex" 10 "errors" 11 "github.com/mit-dci/lit/btcutil/base58" 12 "github.com/mit-dci/lit/coinparam" 13 "github.com/mit-dci/lit/crypto/koblitz" 14 "github.com/mit-dci/lit/crypto/ripemd160" 15 ) 16 17 var ( 18 // ErrChecksumMismatch describes an error where decoding failed due 19 // to a bad checksum. 20 ErrChecksumMismatch = errors.New("checksum mismatch") 21 22 // ErrUnknownAddressType describes an error where an address can not 23 // decoded as a specific address type due to the string encoding 24 // beginning with an identifier byte unknown to any standard or 25 // registered (via coinparam.Register) network. 26 ErrUnknownAddressType = errors.New("unknown address type") 27 28 // ErrAddressCollision describes an error where an address can not 29 // be uniquely determined as either a pay-to-pubkey-hash or 30 // pay-to-script-hash address since the leading identifier is used for 31 // describing both address kinds, but for different networks. Rather 32 // than assuming or defaulting to one or the other, this error is 33 // returned and the caller must decide how to decode the address. 34 ErrAddressCollision = errors.New("address collision") 35 ) 36 37 // encodeAddress returns a human-readable payment address given a ripemd160 hash 38 // and netID which encodes the bitcoin network and address type. It is used 39 // in both pay-to-pubkey-hash (P2PKH) and pay-to-script-hash (P2SH) address 40 // encoding. 41 func encodeAddress(addrData []byte, netID byte) string { 42 // Format is 1 byte for a network and address class (i.e. P2PKH vs 43 // P2SH), 20 bytes for a RIPEMD160 hash, and 4 bytes of checksum. 44 return base58.CheckEncode(addrData, netID) 45 } 46 47 // encodeSegWitAddress returns a human-readable payment address given a witness 48 // program, it's corresponding version, and the netID which encodes the bitcoin 49 // network, and address type. Currently, it is used to encode both 50 // pay-to-witness-pubkey-hash (P2WPKH) and pay-to-witness-script-hash (P2WSH) 51 // addresses. 52 func encodeSegWitAddress(witnessProgram []byte, netID byte, witnessVersion byte) string { 53 // The encoding format for segregated witness pkscript outputs is as 54 // follows: 1 byte for the witness program version, a 0 byte for 55 // padding, and finally, the witness program itself. The witness 56 // program can be of length 32-bytes or 20-bytes. 57 witnessEncoding := make([]byte, 0, 1+1+len(witnessProgram)) 58 59 buf := bytes.NewBuffer(witnessEncoding) 60 buf.Write([]byte{witnessVersion}) 61 buf.Write([]byte{0x00}) 62 buf.Write(witnessProgram) 63 64 // After constructing the witness encoding, apply base58 check encoding 65 // to the raw bytes. 66 return encodeAddress(buf.Bytes(), netID) 67 } 68 69 // Address is an interface type for any type of destination a transaction 70 // output may spend to. This includes pay-to-pubkey (P2PK), pay-to-pubkey-hash 71 // (P2PKH), pay-to-script-hash (P2SH), pay-to-witness-pubkey-hash (P2WPKH), and 72 // pay-to-witness-script-hash (P2WSH). Address is designed to be generic 73 // enough that other kinds of addresses may be added in the future without 74 // changing the decoding and encoding API. 75 type Address interface { 76 // String returns the string encoding of the transaction output 77 // destination. 78 // 79 // Please note that String differs subtly from EncodeAddress: String 80 // will return the value as a string without any conversion, while 81 // EncodeAddress may convert destination types (for example, 82 // converting pubkeys to P2PKH addresses) before encoding as a 83 // payment address string. 84 String() string 85 86 // EncodeAddress returns the string encoding of the payment address 87 // associated with the Address value. See the comment on String 88 // for how this method differs from String. 89 EncodeAddress() string 90 91 // ScriptAddress returns the raw bytes of the address to be used 92 // when inserting the address into a txout's script. 93 ScriptAddress() []byte 94 95 // IsForNet returns whether or not the address is associated with the 96 // passed bitcoin network. 97 IsForNet(*coinparam.Params) bool 98 } 99 100 // DecodeAddress decodes the string encoding of an address and returns 101 // the Address if addr is a valid encoding for a known address type. 102 // 103 // The bitcoin network the address is associated with is extracted if possible. 104 // When the address does not encode the network, such as in the case of a raw 105 // public key, the address will be associated with the passed defaultNet. 106 func DecodeAddress(addr string, defaultNet *coinparam.Params) (Address, error) { 107 // Serialized public keys are either 65 bytes (130 hex chars) if 108 // uncompressed/hybrid or 33 bytes (66 hex chars) if compressed. 109 if len(addr) == 130 || len(addr) == 66 { 110 serializedPubKey, err := hex.DecodeString(addr) 111 if err != nil { 112 return nil, err 113 } 114 return NewAddressPubKey(serializedPubKey, defaultNet) 115 } 116 117 // Switch on decoded length to determine the type. 118 decoded, netID, err := base58.CheckDecode(addr) 119 if err != nil { 120 if err == base58.ErrChecksum { 121 return nil, ErrChecksumMismatch 122 } 123 return nil, errors.New("decoded address is of unknown format") 124 } 125 126 switch len(decoded) { 127 case ripemd160.Size: // P2PKH or P2SH 128 isP2PKH := coinparam.IsPubKeyHashAddrID(netID) 129 isP2SH := coinparam.IsScriptHashAddrID(netID) 130 switch hash160 := decoded; { 131 case isP2PKH && isP2SH: 132 return nil, ErrAddressCollision 133 case isP2PKH: 134 return newAddressPubKeyHash(hash160, netID) 135 case isP2SH: 136 return newAddressScriptHashFromHash(hash160, netID) 137 default: 138 return nil, ErrUnknownAddressType 139 } 140 141 default: 142 return nil, errors.New("decoded address is of unknown size") 143 } 144 } 145 146 // AddressPubKeyHash is an Address for a pay-to-pubkey-hash (P2PKH) 147 // transaction. 148 type AddressPubKeyHash struct { 149 hash [ripemd160.Size]byte 150 netID byte 151 } 152 153 // NewAddressPubKeyHash returns a new AddressPubKeyHash. pkHash must be 20 154 // bytes. 155 func NewAddressPubKeyHash(pkHash []byte, net *coinparam.Params) (*AddressPubKeyHash, error) { 156 return newAddressPubKeyHash(pkHash, net.PubKeyHashAddrID) 157 } 158 159 // newAddressPubKeyHash is the internal API to create a pubkey hash address 160 // with a known leading identifier byte for a network, rather than looking 161 // it up through its parameters. This is useful when creating a new address 162 // structure from a string encoding where the identifer byte is already 163 // known. 164 func newAddressPubKeyHash(pkHash []byte, netID byte) (*AddressPubKeyHash, error) { 165 // Check for a valid pubkey hash length. 166 if len(pkHash) != ripemd160.Size { 167 return nil, errors.New("pkHash must be 20 bytes") 168 } 169 170 addr := &AddressPubKeyHash{netID: netID} 171 copy(addr.hash[:], pkHash) 172 return addr, nil 173 } 174 175 // EncodeAddress returns the string encoding of a pay-to-pubkey-hash 176 // address. Part of the Address interface. 177 func (a *AddressPubKeyHash) EncodeAddress() string { 178 return encodeAddress(a.hash[:], a.netID) 179 } 180 181 // ScriptAddress returns the bytes to be included in a txout script to pay 182 // to a pubkey hash. Part of the Address interface. 183 func (a *AddressPubKeyHash) ScriptAddress() []byte { 184 return a.hash[:] 185 } 186 187 // IsForNet returns whether or not the pay-to-pubkey-hash address is associated 188 // with the passed bitcoin network. 189 func (a *AddressPubKeyHash) IsForNet(net *coinparam.Params) bool { 190 return a.netID == net.PubKeyHashAddrID 191 } 192 193 // String returns a human-readable string for the pay-to-pubkey-hash address. 194 // This is equivalent to calling EncodeAddress, but is provided so the type can 195 // be used as a fmt.Stringer. 196 func (a *AddressPubKeyHash) String() string { 197 return a.EncodeAddress() 198 } 199 200 // Hash160 returns the underlying array of the pubkey hash. This can be useful 201 // when an array is more appropriate than a slice (for example, when used as map 202 // keys). 203 func (a *AddressPubKeyHash) Hash160() *[ripemd160.Size]byte { 204 return &a.hash 205 } 206 207 // AddressScriptHash is an Address for a pay-to-script-hash (P2SH) 208 // transaction. 209 type AddressScriptHash struct { 210 hash [ripemd160.Size]byte 211 netID byte 212 } 213 214 // NewAddressScriptHash returns a new AddressScriptHash. 215 func NewAddressScriptHash(serializedScript []byte, net *coinparam.Params) (*AddressScriptHash, error) { 216 scriptHash := Hash160(serializedScript) 217 return newAddressScriptHashFromHash(scriptHash, net.ScriptHashAddrID) 218 } 219 220 // NewAddressScriptHashFromHash returns a new AddressScriptHash. scriptHash 221 // must be 20 bytes. 222 func NewAddressScriptHashFromHash(scriptHash []byte, net *coinparam.Params) (*AddressScriptHash, error) { 223 return newAddressScriptHashFromHash(scriptHash, net.ScriptHashAddrID) 224 } 225 226 // newAddressScriptHashFromHash is the internal API to create a script hash 227 // address with a known leading identifier byte for a network, rather than 228 // looking it up through its parameters. This is useful when creating a new 229 // address structure from a string encoding where the identifer byte is already 230 // known. 231 func newAddressScriptHashFromHash(scriptHash []byte, netID byte) (*AddressScriptHash, error) { 232 // Check for a valid script hash length. 233 if len(scriptHash) != ripemd160.Size { 234 return nil, errors.New("scriptHash must be 20 bytes") 235 } 236 237 addr := &AddressScriptHash{netID: netID} 238 copy(addr.hash[:], scriptHash) 239 return addr, nil 240 } 241 242 // EncodeAddress returns the string encoding of a pay-to-script-hash 243 // address. Part of the Address interface. 244 func (a *AddressScriptHash) EncodeAddress() string { 245 return encodeAddress(a.hash[:], a.netID) 246 } 247 248 // ScriptAddress returns the bytes to be included in a txout script to pay 249 // to a script hash. Part of the Address interface. 250 func (a *AddressScriptHash) ScriptAddress() []byte { 251 return a.hash[:] 252 } 253 254 // IsForNet returns whether or not the pay-to-script-hash address is associated 255 // with the passed bitcoin network. 256 func (a *AddressScriptHash) IsForNet(net *coinparam.Params) bool { 257 return a.netID == net.ScriptHashAddrID 258 } 259 260 // String returns a human-readable string for the pay-to-script-hash address. 261 // This is equivalent to calling EncodeAddress, but is provided so the type can 262 // be used as a fmt.Stringer. 263 func (a *AddressScriptHash) String() string { 264 return a.EncodeAddress() 265 } 266 267 // Hash160 returns the underlying array of the script hash. This can be useful 268 // when an array is more appropriate than a slice (for example, when used as map 269 // keys). 270 func (a *AddressScriptHash) Hash160() *[ripemd160.Size]byte { 271 return &a.hash 272 } 273 274 // PubKeyFormat describes what format to use for a pay-to-pubkey address. 275 type PubKeyFormat int 276 277 const ( 278 // PKFUncompressed indicates the pay-to-pubkey address format is an 279 // uncompressed public key. 280 PKFUncompressed PubKeyFormat = iota 281 282 // PKFCompressed indicates the pay-to-pubkey address format is a 283 // compressed public key. 284 PKFCompressed 285 286 // PKFHybrid indicates the pay-to-pubkey address format is a hybrid 287 // public key. 288 PKFHybrid 289 ) 290 291 // AddressPubKey is an Address for a pay-to-pubkey transaction. 292 type AddressPubKey struct { 293 pubKeyFormat PubKeyFormat 294 pubKey *koblitz.PublicKey 295 pubKeyHashID byte 296 } 297 298 // NewAddressPubKey returns a new AddressPubKey which represents a pay-to-pubkey 299 // address. The serializedPubKey parameter must be a valid pubkey and can be 300 // uncompressed, compressed, or hybrid. 301 func NewAddressPubKey(serializedPubKey []byte, net *coinparam.Params) (*AddressPubKey, error) { 302 pubKey, err := koblitz.ParsePubKey(serializedPubKey, koblitz.S256()) 303 if err != nil { 304 return nil, err 305 } 306 307 // Set the format of the pubkey. This probably should be returned 308 // from koblitz, but do it here to avoid API churn. We already know the 309 // pubkey is valid since it parsed above, so it's safe to simply examine 310 // the leading byte to get the format. 311 pkFormat := PKFUncompressed 312 switch serializedPubKey[0] { 313 case 0x02, 0x03: 314 pkFormat = PKFCompressed 315 case 0x06, 0x07: 316 pkFormat = PKFHybrid 317 } 318 319 return &AddressPubKey{ 320 pubKeyFormat: pkFormat, 321 pubKey: pubKey, 322 pubKeyHashID: net.PubKeyHashAddrID, 323 }, nil 324 } 325 326 // serialize returns the serialization of the public key according to the 327 // format associated with the address. 328 func (a *AddressPubKey) serialize() []byte { 329 switch a.pubKeyFormat { 330 default: 331 fallthrough 332 case PKFUncompressed: 333 return a.pubKey.SerializeUncompressed() 334 335 case PKFCompressed: 336 return a.pubKey.SerializeCompressed() 337 338 case PKFHybrid: 339 return a.pubKey.SerializeHybrid() 340 } 341 } 342 343 // EncodeAddress returns the string encoding of the public key as a 344 // pay-to-pubkey-hash. Note that the public key format (uncompressed, 345 // compressed, etc) will change the resulting address. This is expected since 346 // pay-to-pubkey-hash is a hash of the serialized public key which obviously 347 // differs with the format. At the time of this writing, most Bitcoin addresses 348 // are pay-to-pubkey-hash constructed from the uncompressed public key. 349 // 350 // Part of the Address interface. 351 func (a *AddressPubKey) EncodeAddress() string { 352 return encodeAddress(Hash160(a.serialize()), a.pubKeyHashID) 353 } 354 355 // ScriptAddress returns the bytes to be included in a txout script to pay 356 // to a public key. Setting the public key format will affect the output of 357 // this function accordingly. Part of the Address interface. 358 func (a *AddressPubKey) ScriptAddress() []byte { 359 return a.serialize() 360 } 361 362 // IsForNet returns whether or not the pay-to-pubkey address is associated 363 // with the passed bitcoin network. 364 func (a *AddressPubKey) IsForNet(net *coinparam.Params) bool { 365 return a.pubKeyHashID == net.PubKeyHashAddrID 366 } 367 368 // String returns the hex-encoded human-readable string for the pay-to-pubkey 369 // address. This is not the same as calling EncodeAddress. 370 func (a *AddressPubKey) String() string { 371 return hex.EncodeToString(a.serialize()) 372 } 373 374 // Format returns the format (uncompressed, compressed, etc) of the 375 // pay-to-pubkey address. 376 func (a *AddressPubKey) Format() PubKeyFormat { 377 return a.pubKeyFormat 378 } 379 380 // SetFormat sets the format (uncompressed, compressed, etc) of the 381 // pay-to-pubkey address. 382 func (a *AddressPubKey) SetFormat(pkFormat PubKeyFormat) { 383 a.pubKeyFormat = pkFormat 384 } 385 386 // AddressPubKeyHash returns the pay-to-pubkey address converted to a 387 // pay-to-pubkey-hash address. Note that the public key format (uncompressed, 388 // compressed, etc) will change the resulting address. This is expected since 389 // pay-to-pubkey-hash is a hash of the serialized public key which obviously 390 // differs with the format. At the time of this writing, most Bitcoin addresses 391 // are pay-to-pubkey-hash constructed from the uncompressed public key. 392 func (a *AddressPubKey) AddressPubKeyHash() *AddressPubKeyHash { 393 addr := &AddressPubKeyHash{netID: a.pubKeyHashID} 394 copy(addr.hash[:], Hash160(a.serialize())) 395 return addr 396 } 397 398 // PubKey returns the underlying public key for the address. 399 func (a *AddressPubKey) PubKey() *koblitz.PublicKey { 400 return a.pubKey 401 }