lbry.go/lbrycrd/address.go
2021-10-06 16:28:17 -04:00

59 lines
1.9 KiB
Go

package lbrycrd
import (
"encoding/hex"
"golang.org/x/crypto/ripemd160"
"github.com/lbryio/lbcd/chaincfg"
"github.com/lbryio/lbcutil"
"github.com/lbryio/lbcutil/base58"
"github.com/cockroachdb/errors"
)
// DecodeAddress decodes the string encoding of an address and returns
// the Address if addr is a valid encoding for a known address type.
//
// The bitcoin network the address is associated with is extracted if possible.
// When the address does not encode the network, such as in the case of a raw
// public key, the address will be associated with the passed defaultNet.
func DecodeAddress(addr string, defaultNet *chaincfg.Params) (lbcutil.Address, error) {
// Serialized public keys are either 65 bytes (130 hex chars) if
// uncompressed/hybrid or 33 bytes (66 hex chars) if compressed.
if len(addr) == 130 || len(addr) == 66 {
serializedPubKey, err := hex.DecodeString(addr)
if err != nil {
return nil, err
}
return lbcutil.NewAddressPubKey(serializedPubKey, defaultNet)
}
// Switch on decoded length to determine the type.
decoded, netID, err := base58.CheckDecode(addr)
if err != nil {
if err == base58.ErrChecksum {
return nil, lbcutil.ErrChecksumMismatch
}
return nil, errors.WithStack(errors.Newf("decoded address[%s] is of unknown format even with default chainparams[%s]", addr, defaultNet.Name))
}
switch len(decoded) {
case ripemd160.Size: // P2PKH or P2SH
isP2PKH := chaincfg.IsPubKeyHashAddrID(netID)
isP2SH := chaincfg.IsScriptHashAddrID(netID)
switch hash160 := decoded; {
case isP2PKH && isP2SH:
return nil, lbcutil.ErrAddressCollision
case isP2PKH:
return lbcutil.NewAddressPubKeyHash(hash160, &chaincfg.Params{PubKeyHashAddrID: netID})
case isP2SH:
return lbcutil.NewAddressScriptHashFromHash(hash160, &chaincfg.Params{ScriptHashAddrID: netID})
default:
return nil, lbcutil.ErrUnknownAddressType
}
default:
return nil, errors.WithStack(errors.New("decoded address is of unknown size"))
}
}