dcrd/dcrutil/address.go
2018-02-18 12:26:52 -06:00

757 lines
25 KiB
Go

// Copyright (c) 2013, 2014 The btcsuite developers
// Copyright (c) 2015-2016 The Decred developers
// Use of this source code is governed by an ISC
// license that can be found in the LICENSE file.
package dcrutil
import (
"errors"
"fmt"
"golang.org/x/crypto/ripemd160"
"github.com/decred/base58"
"github.com/decred/dcrd/chaincfg"
"github.com/decred/dcrd/chaincfg/chainec"
)
var (
// ErrChecksumMismatch describes an error where decoding failed due
// to a bad checksum.
ErrChecksumMismatch = errors.New("checksum mismatch")
// ErrUnknownAddressType describes an error where an address can not
// decoded as a specific address type due to the string encoding
// beginning with an identifier byte unknown to any standard or
// registered (via chaincfg.Register) network.
ErrUnknownAddressType = errors.New("unknown address type")
// ErrAddressCollision describes an error where an address can not
// be uniquely determined as either a pay-to-pubkey-hash or
// pay-to-script-hash address since the leading identifier is used for
// describing both address kinds, but for different networks. Rather
// than assuming or defaulting to one or the other, this error is
// returned and the caller must decide how to decode the address.
ErrAddressCollision = errors.New("address collision")
// ErrMissingDefaultNet describes an error in DecodeAddress that
// attempts to decode an address without defining which network to decode
// for.
ErrMissingDefaultNet = errors.New("default net not defined")
)
// encodeAddress returns a human-readable payment address given a ripemd160 hash
// and netID which encodes the network and address type. It is used in both
// pay-to-pubkey-hash (P2PKH) and pay-to-script-hash (P2SH) address encoding.
func encodeAddress(hash160 []byte, netID [2]byte) string {
// Format is 2 bytes for a network and address class (i.e. P2PKH vs
// P2SH), 20 bytes for a RIPEMD160 hash, and 4 bytes of checksum.
return base58.CheckEncode(hash160[:ripemd160.Size], netID)
}
// encodePKAddress returns a human-readable payment address to a public key
// given a serialized public key, a netID, and a signature suite.
func encodePKAddress(serializedPK []byte, netID [2]byte, algo int) string {
pubKeyBytes := []byte{0x00}
switch algo {
case chainec.ECTypeSecp256k1:
pubKeyBytes[0] = byte(chainec.ECTypeSecp256k1)
case chainec.ECTypeEdwards:
pubKeyBytes[0] = byte(chainec.ECTypeEdwards)
case chainec.ECTypeSecSchnorr:
pubKeyBytes[0] = byte(chainec.ECTypeSecSchnorr)
}
// Pubkeys are encoded as [0] = type/ybit, [1:33] = serialized pubkey
compressed := serializedPK
if algo == chainec.ECTypeSecp256k1 || algo == chainec.ECTypeSecSchnorr {
pub, err := chainec.Secp256k1.ParsePubKey(serializedPK)
if err != nil {
return ""
}
pubSerComp := pub.SerializeCompressed()
// Set the y-bit if needed.
if pubSerComp[0] == 0x03 {
pubKeyBytes[0] |= (1 << 7)
}
compressed = pubSerComp[1:]
}
pubKeyBytes = append(pubKeyBytes, compressed...)
return base58.CheckEncode(pubKeyBytes, netID)
}
// Address is an interface type for any type of destination a transaction
// output may spend to. This includes pay-to-pubkey (P2PK), pay-to-pubkey-hash
// (P2PKH), and pay-to-script-hash (P2SH). Address is designed to be generic
// enough that other kinds of addresses may be added in the future without
// changing the decoding and encoding API.
type Address interface {
// String returns the string encoding of the transaction output
// destination.
//
// Please note that String differs subtly from EncodeAddress: String
// will return the value as a string without any conversion, while
// EncodeAddress may convert destination types (for example,
// converting pubkeys to P2PKH addresses) before encoding as a
// payment address string.
String() string
// EncodeAddress returns the string encoding of the payment address
// associated with the Address value. See the comment on String
// for how this method differs from String.
EncodeAddress() string
// ScriptAddress returns the raw bytes of the address to be used
// when inserting the address into a txout's script.
ScriptAddress() []byte
// Hash160 returns the Hash160(data) where data is the data normally
// hashed to 160 bits from the respective address type.
Hash160() *[ripemd160.Size]byte
// IsForNet returns whether or not the address is associated with the
// passed network.
IsForNet(*chaincfg.Params) bool
// DSA returns the digital signature algorithm for the address.
DSA(*chaincfg.Params) int
// Net returns the network parameters of the address.
Net() *chaincfg.Params
}
// NewAddressPubKey returns a new Address. decoded must
// be 33 bytes.
func NewAddressPubKey(decoded []byte, net *chaincfg.Params) (Address, error) {
if len(decoded) == 33 {
// First byte is the signature suite and ybit.
suite := decoded[0]
suite &= ^uint8(1 << 7)
ybit := !(decoded[0]&(1<<7) == 0)
toAppend := uint8(0x02)
if ybit {
toAppend = 0x03
}
switch int(suite) {
case chainec.ECTypeSecp256k1:
return NewAddressSecpPubKey(
append([]byte{toAppend}, decoded[1:]...),
net)
case chainec.ECTypeEdwards:
return NewAddressEdwardsPubKey(decoded, net)
case chainec.ECTypeSecSchnorr:
return NewAddressSecSchnorrPubKey(
append([]byte{toAppend}, decoded[1:]...),
net)
}
return nil, ErrUnknownAddressType
}
return nil, ErrUnknownAddressType
}
// DecodeAddress decodes the string encoding of an address and returns
// the Address if addr is a valid encoding for a known address type
func DecodeAddress(addr string) (Address, error) {
// Switch on decoded length to determine the type.
decoded, netID, err := base58.CheckDecode(addr)
if err != nil {
if err == base58.ErrChecksum {
return nil, ErrChecksumMismatch
}
return nil, fmt.Errorf("decoded address is of unknown format: %v",
err.Error())
}
net, err := detectNetworkForAddress(addr)
if err != nil {
return nil, ErrUnknownAddressType
}
switch netID {
case net.PubKeyAddrID:
return NewAddressPubKey(decoded, net)
case net.PubKeyHashAddrID:
return NewAddressPubKeyHash(decoded, net, chainec.ECTypeSecp256k1)
case net.PKHEdwardsAddrID:
return NewAddressPubKeyHash(decoded, net, chainec.ECTypeEdwards)
case net.PKHSchnorrAddrID:
return NewAddressPubKeyHash(decoded, net, chainec.ECTypeSecSchnorr)
case net.ScriptHashAddrID:
return NewAddressScriptHashFromHash(decoded, net)
default:
return nil, ErrUnknownAddressType
}
}
// detectNetworkForAddress pops the first character from a string encoded
// address and detects what network type it is for.
func detectNetworkForAddress(addr string) (*chaincfg.Params, error) {
if len(addr) < 1 {
return nil, fmt.Errorf("empty string given for network detection")
}
networkChar := addr[0:1]
switch networkChar {
case chaincfg.MainNetParams.NetworkAddressPrefix:
return &chaincfg.MainNetParams, nil
case chaincfg.TestNet2Params.NetworkAddressPrefix:
return &chaincfg.TestNet2Params, nil
case chaincfg.SimNetParams.NetworkAddressPrefix:
return &chaincfg.SimNetParams, nil
}
return nil, fmt.Errorf("unknown network type in string encoded address")
}
// AddressPubKeyHash is an Address for a pay-to-pubkey-hash (P2PKH)
// transaction.
type AddressPubKeyHash struct {
net *chaincfg.Params
hash [ripemd160.Size]byte
netID [2]byte
}
// NewAddressPubKeyHash returns a new AddressPubKeyHash. pkHash must
// be 20 bytes.
func NewAddressPubKeyHash(pkHash []byte, net *chaincfg.Params,
algo int) (*AddressPubKeyHash, error) {
var addrID [2]byte
switch algo {
case chainec.ECTypeSecp256k1:
addrID = net.PubKeyHashAddrID
case chainec.ECTypeEdwards:
addrID = net.PKHEdwardsAddrID
case chainec.ECTypeSecSchnorr:
addrID = net.PKHSchnorrAddrID
default:
return nil, errors.New("unknown ECDSA algorithm")
}
apkh, err := newAddressPubKeyHash(pkHash, addrID)
if err != nil {
return nil, err
}
apkh.net = net
return apkh, nil
}
// newAddressPubKeyHash is the internal API to create a pubkey hash address
// with a known leading identifier byte for a network, rather than looking
// it up through its parameters. This is useful when creating a new address
// structure from a string encoding where the identifer byte is already
// known.
func newAddressPubKeyHash(pkHash []byte, netID [2]byte) (*AddressPubKeyHash,
error) {
// Check for a valid pubkey hash length.
if len(pkHash) != ripemd160.Size {
return nil, errors.New("pkHash must be 20 bytes")
}
addr := &AddressPubKeyHash{netID: netID}
copy(addr.hash[:], pkHash)
return addr, nil
}
// EncodeAddress returns the string encoding of a pay-to-pubkey-hash
// address. Part of the Address interface.
func (a *AddressPubKeyHash) EncodeAddress() string {
return encodeAddress(a.hash[:], a.netID)
}
// ScriptAddress returns the bytes to be included in a txout script to pay
// to a pubkey hash. Part of the Address interface.
func (a *AddressPubKeyHash) ScriptAddress() []byte {
return a.hash[:]
}
// IsForNet returns whether or not the pay-to-pubkey-hash address is associated
// with the passed network.
func (a *AddressPubKeyHash) IsForNet(net *chaincfg.Params) bool {
return a.netID == net.PubKeyHashAddrID ||
a.netID == net.PKHEdwardsAddrID ||
a.netID == net.PKHSchnorrAddrID
}
// String returns a human-readable string for the pay-to-pubkey-hash address.
// This is equivalent to calling EncodeAddress, but is provided so the type can
// be used as a fmt.Stringer.
func (a *AddressPubKeyHash) String() string {
return a.EncodeAddress()
}
// Hash160 returns the underlying array of the pubkey hash. This can be useful
// when an array is more appropriate than a slice (for example, when used as map
// keys).
func (a *AddressPubKeyHash) Hash160() *[ripemd160.Size]byte {
return &a.hash
}
// DSA returns the digital signature algorithm for the associated public key
// hash.
func (a *AddressPubKeyHash) DSA(net *chaincfg.Params) int {
switch a.netID {
case net.PubKeyHashAddrID:
return chainec.ECTypeSecp256k1
case net.PKHEdwardsAddrID:
return chainec.ECTypeEdwards
case net.PKHSchnorrAddrID:
return chainec.ECTypeSecSchnorr
}
return -1
}
// Net returns the network for the address.
func (a *AddressPubKeyHash) Net() *chaincfg.Params {
return a.net
}
// AddressScriptHash is an Address for a pay-to-script-hash (P2SH)
// transaction.
type AddressScriptHash struct {
net *chaincfg.Params
hash [ripemd160.Size]byte
netID [2]byte
}
// NewAddressScriptHash returns a new AddressScriptHash.
func NewAddressScriptHash(serializedScript []byte,
net *chaincfg.Params) (*AddressScriptHash, error) {
scriptHash := Hash160(serializedScript)
ash, err := newAddressScriptHashFromHash(scriptHash, net.ScriptHashAddrID)
if err != nil {
return nil, err
}
ash.net = net
return ash, nil
}
// NewAddressScriptHashFromHash returns a new AddressScriptHash. scriptHash
// must be 20 bytes.
func NewAddressScriptHashFromHash(scriptHash []byte,
net *chaincfg.Params) (*AddressScriptHash, error) {
ash, err := newAddressScriptHashFromHash(scriptHash, net.ScriptHashAddrID)
if err != nil {
return nil, err
}
ash.net = net
return ash, nil
}
// newAddressScriptHashFromHash is the internal API to create a script hash
// address with a known leading identifier byte for a network, rather than
// looking it up through its parameters. This is useful when creating a new
// address structure from a string encoding where the identifer byte is already
// known.
func newAddressScriptHashFromHash(scriptHash []byte,
netID [2]byte) (*AddressScriptHash, error) {
// Check for a valid script hash length.
if len(scriptHash) != ripemd160.Size {
return nil, errors.New("scriptHash must be 20 bytes")
}
addr := &AddressScriptHash{netID: netID}
copy(addr.hash[:], scriptHash)
return addr, nil
}
// EncodeAddress returns the string encoding of a pay-to-script-hash
// address. Part of the Address interface.
func (a *AddressScriptHash) EncodeAddress() string {
return encodeAddress(a.hash[:], a.netID)
}
// ScriptAddress returns the bytes to be included in a txout script to pay
// to a script hash. Part of the Address interface.
func (a *AddressScriptHash) ScriptAddress() []byte {
return a.hash[:]
}
// IsForNet returns whether or not the pay-to-script-hash address is associated
// with the passed network.
func (a *AddressScriptHash) IsForNet(net *chaincfg.Params) bool {
return a.netID == net.ScriptHashAddrID
}
// String returns a human-readable string for the pay-to-script-hash address.
// This is equivalent to calling EncodeAddress, but is provided so the type can
// be used as a fmt.Stringer.
func (a *AddressScriptHash) String() string {
return a.EncodeAddress()
}
// Hash160 returns the underlying array of the script hash. This can be useful
// when an array is more appropriate than a slice (for example, when used as map
// keys).
func (a *AddressScriptHash) Hash160() *[ripemd160.Size]byte {
return &a.hash
}
// DSA returns -1 (invalid) as the digital signature algorithm for scripts,
// as scripts may not involve digital signatures at all.
func (a *AddressScriptHash) DSA(net *chaincfg.Params) int {
return -1
}
// Net returns the network for the address.
func (a *AddressScriptHash) Net() *chaincfg.Params {
return a.net
}
// PubKeyFormat describes what format to use for a pay-to-pubkey address.
type PubKeyFormat int
const (
// PKFUncompressed indicates the pay-to-pubkey address format is an
// uncompressed public key.
PKFUncompressed PubKeyFormat = iota
// PKFCompressed indicates the pay-to-pubkey address format is a
// compressed public key.
PKFCompressed
// PKFHybrid indicates the pay-to-pubkey address format is a hybrid
// public key.
PKFHybrid
)
// AddressSecpPubKey is an Address for a secp256k1 pay-to-pubkey transaction.
type AddressSecpPubKey struct {
net *chaincfg.Params
pubKeyFormat PubKeyFormat
pubKey chainec.PublicKey
pubKeyHashID [2]byte
}
// NewAddressSecpPubKey returns a new AddressSecpPubKey which represents a
// pay-to-pubkey address, using a secp256k1 pubkey. The serializedPubKey
// parameter must be a valid pubkey and can be uncompressed, compressed, or
// hybrid.
func NewAddressSecpPubKey(serializedPubKey []byte,
net *chaincfg.Params) (*AddressSecpPubKey, error) {
pubKey, err := chainec.Secp256k1.ParsePubKey(serializedPubKey)
if err != nil {
return nil, err
}
// Set the format of the pubkey. This probably should be returned
// from dcrec, but do it here to avoid API churn. We already know the
// pubkey is valid since it parsed above, so it's safe to simply examine
// the leading byte to get the format.
pkFormat := PKFUncompressed
switch serializedPubKey[0] {
case 0x02, 0x03:
pkFormat = PKFCompressed
case 0x06, 0x07:
pkFormat = PKFHybrid
}
return &AddressSecpPubKey{
net: net,
pubKeyFormat: pkFormat,
pubKey: pubKey,
pubKeyHashID: net.PubKeyHashAddrID,
}, nil
}
// serialize returns the serialization of the public key according to the
// format associated with the address.
func (a *AddressSecpPubKey) serialize() []byte {
switch a.pubKeyFormat {
default:
fallthrough
case PKFUncompressed:
return a.pubKey.SerializeUncompressed()
case PKFCompressed:
return a.pubKey.SerializeCompressed()
case PKFHybrid:
return a.pubKey.SerializeHybrid()
}
}
// EncodeAddress returns the string encoding of the public key as a
// pay-to-pubkey-hash. Note that the public key format (uncompressed,
// compressed, etc) will change the resulting address. This is expected since
// pay-to-pubkey-hash is a hash of the serialized public key which obviously
// differs with the format. At the time of this writing, most Decred addresses
// are pay-to-pubkey-hash constructed from the uncompressed public key.
//
// Part of the Address interface.
func (a *AddressSecpPubKey) EncodeAddress() string {
return encodeAddress(Hash160(a.serialize()), a.pubKeyHashID)
}
// ScriptAddress returns the bytes to be included in a txout script to pay
// to a public key. Setting the public key format will affect the output of
// this function accordingly. Part of the Address interface.
func (a *AddressSecpPubKey) ScriptAddress() []byte {
return a.serialize()
}
// Hash160 returns the underlying array of the pubkey hash. This can be useful
// when an array is more appropriate than a slice (for example, when used as map
// keys).
func (a *AddressSecpPubKey) Hash160() *[ripemd160.Size]byte {
h160 := Hash160(a.pubKey.SerializeCompressed())
array := new([ripemd160.Size]byte)
copy(array[:], h160)
return array
}
// IsForNet returns whether or not the pay-to-pubkey address is associated
// with the passed network.
func (a *AddressSecpPubKey) IsForNet(net *chaincfg.Params) bool {
return a.pubKeyHashID == net.PubKeyHashAddrID
}
// String returns the hex-encoded human-readable string for the pay-to-pubkey
// address. This is not the same as calling EncodeAddress.
func (a *AddressSecpPubKey) String() string {
return encodePKAddress(a.serialize(), a.net.PubKeyAddrID,
chainec.ECTypeSecp256k1)
}
// Format returns the format (uncompressed, compressed, etc) of the
// pay-to-pubkey address.
func (a *AddressSecpPubKey) Format() PubKeyFormat {
return a.pubKeyFormat
}
// AddressPubKeyHash returns the pay-to-pubkey address converted to a
// pay-to-pubkey-hash address. Note that the public key format (uncompressed,
// compressed, etc) will change the resulting address. This is expected since
// pay-to-pubkey-hash is a hash of the serialized public key which obviously
// differs with the format. At the time of this writing, most Decred addresses
// are pay-to-pubkey-hash constructed from the uncompressed public key.
func (a *AddressSecpPubKey) AddressPubKeyHash() *AddressPubKeyHash {
addr := &AddressPubKeyHash{net: a.net, netID: a.pubKeyHashID}
copy(addr.hash[:], Hash160(a.serialize()))
return addr
}
// PubKey returns the underlying public key for the address.
func (a *AddressSecpPubKey) PubKey() chainec.PublicKey {
return a.pubKey
}
// DSA returns the underlying digital signature algorithm for the
// address.
func (a *AddressSecpPubKey) DSA(net *chaincfg.Params) int {
switch a.pubKeyHashID {
case net.PubKeyHashAddrID:
return chainec.ECTypeSecp256k1
case net.PKHSchnorrAddrID:
return chainec.ECTypeSecSchnorr
}
return -1
}
// Net returns the network for the address.
func (a *AddressSecpPubKey) Net() *chaincfg.Params {
return a.net
}
// NewAddressSecpPubKeyCompressed creates a new address using a compressed public key
func NewAddressSecpPubKeyCompressed(pubkey chainec.PublicKey, params *chaincfg.Params) (*AddressSecpPubKey, error) {
return NewAddressSecpPubKey(pubkey.SerializeCompressed(), params)
}
// AddressEdwardsPubKey is an Address for an Ed25519 pay-to-pubkey transaction.
type AddressEdwardsPubKey struct {
net *chaincfg.Params
pubKey chainec.PublicKey
pubKeyHashID [2]byte
}
// NewAddressEdwardsPubKey returns a new AddressEdwardsPubKey which represents a
// pay-to-pubkey address, using an Ed25519 pubkey. The serializedPubKey
// parameter must be a valid 32 byte serialized public key.
func NewAddressEdwardsPubKey(serializedPubKey []byte,
net *chaincfg.Params) (*AddressEdwardsPubKey, error) {
pubKey, err := chainec.Edwards.ParsePubKey(serializedPubKey)
if err != nil {
return nil, err
}
return &AddressEdwardsPubKey{
net: net,
pubKey: pubKey,
pubKeyHashID: net.PKHEdwardsAddrID,
}, nil
}
// serialize returns the serialization of the public key.
func (a *AddressEdwardsPubKey) serialize() []byte {
return a.pubKey.Serialize()
}
// EncodeAddress returns the string encoding of the public key as a
// pay-to-pubkey-hash.
//
// Part of the Address interface.
func (a *AddressEdwardsPubKey) EncodeAddress() string {
return encodeAddress(Hash160(a.serialize()), a.pubKeyHashID)
}
// ScriptAddress returns the bytes to be included in a txout script to pay
// to a public key. Setting the public key format will affect the output of
// this function accordingly. Part of the Address interface.
func (a *AddressEdwardsPubKey) ScriptAddress() []byte {
return a.serialize()
}
// Hash160 returns the underlying array of the pubkey hash. This can be useful
// when an array is more appropriate than a slice (for example, when used as map
// keys).
func (a *AddressEdwardsPubKey) Hash160() *[ripemd160.Size]byte {
h160 := Hash160(a.pubKey.Serialize())
array := new([ripemd160.Size]byte)
copy(array[:], h160)
return array
}
// IsForNet returns whether or not the pay-to-pubkey address is associated
// with the passed network.
func (a *AddressEdwardsPubKey) IsForNet(net *chaincfg.Params) bool {
return a.pubKeyHashID == net.PKHEdwardsAddrID
}
// String returns the hex-encoded human-readable string for the pay-to-pubkey
// address. This is not the same as calling EncodeAddress.
func (a *AddressEdwardsPubKey) String() string {
return encodePKAddress(a.serialize(), a.net.PubKeyAddrID,
chainec.ECTypeEdwards)
}
// AddressPubKeyHash returns the pay-to-pubkey address converted to a
// pay-to-pubkey-hash address.
func (a *AddressEdwardsPubKey) AddressPubKeyHash() *AddressPubKeyHash {
addr := &AddressPubKeyHash{net: a.net, netID: a.pubKeyHashID}
copy(addr.hash[:], Hash160(a.serialize()))
return addr
}
// PubKey returns the underlying public key for the address.
func (a *AddressEdwardsPubKey) PubKey() chainec.PublicKey {
return a.pubKey
}
// DSA returns the underlying digital signature algorithm for the
// address.
func (a *AddressEdwardsPubKey) DSA(net *chaincfg.Params) int {
return chainec.ECTypeEdwards
}
// Net returns the network for the address.
func (a *AddressEdwardsPubKey) Net() *chaincfg.Params {
return a.net
}
// AddressSecSchnorrPubKey is an Address for a secp256k1 pay-to-pubkey
// transaction.
type AddressSecSchnorrPubKey struct {
net *chaincfg.Params
pubKey chainec.PublicKey
pubKeyHashID [2]byte
}
// NewAddressSecSchnorrPubKey returns a new AddressSecpPubKey which represents a
// pay-to-pubkey address, using a secp256k1 pubkey. The serializedPubKey
// parameter must be a valid pubkey and can be uncompressed, compressed, or
// hybrid.
func NewAddressSecSchnorrPubKey(serializedPubKey []byte,
net *chaincfg.Params) (*AddressSecSchnorrPubKey, error) {
pubKey, err := chainec.SecSchnorr.ParsePubKey(serializedPubKey)
if err != nil {
return nil, err
}
return &AddressSecSchnorrPubKey{
net: net,
pubKey: pubKey,
pubKeyHashID: net.PKHSchnorrAddrID,
}, nil
}
// serialize returns the serialization of the public key according to the
// format associated with the address.
func (a *AddressSecSchnorrPubKey) serialize() []byte {
return a.pubKey.Serialize()
}
// EncodeAddress returns the string encoding of the public key as a
// pay-to-pubkey-hash. Note that the public key format (uncompressed,
// compressed, etc) will change the resulting address. This is expected since
// pay-to-pubkey-hash is a hash of the serialized public key which obviously
// differs with the format. At the time of this writing, most Decred addresses
// are pay-to-pubkey-hash constructed from the uncompressed public key.
//
// Part of the Address interface.
func (a *AddressSecSchnorrPubKey) EncodeAddress() string {
return encodeAddress(Hash160(a.serialize()), a.pubKeyHashID)
}
// ScriptAddress returns the bytes to be included in a txout script to pay
// to a public key. Setting the public key format will affect the output of
// this function accordingly. Part of the Address interface.
func (a *AddressSecSchnorrPubKey) ScriptAddress() []byte {
return a.serialize()
}
// Hash160 returns the underlying array of the pubkey hash. This can be useful
// when an array is more appropriate than a slice (for example, when used as map
// keys).
func (a *AddressSecSchnorrPubKey) Hash160() *[ripemd160.Size]byte {
h160 := Hash160(a.pubKey.Serialize())
array := new([ripemd160.Size]byte)
copy(array[:], h160)
return array
}
// IsForNet returns whether or not the pay-to-pubkey address is associated
// with the passed network.
func (a *AddressSecSchnorrPubKey) IsForNet(net *chaincfg.Params) bool {
return a.pubKeyHashID == net.PubKeyHashAddrID
}
// String returns the hex-encoded human-readable string for the pay-to-pubkey
// address. This is not the same as calling EncodeAddress.
func (a *AddressSecSchnorrPubKey) String() string {
return encodePKAddress(a.serialize(), a.net.PubKeyAddrID,
chainec.ECTypeSecSchnorr)
}
// AddressPubKeyHash returns the pay-to-pubkey address converted to a
// pay-to-pubkey-hash address.
func (a *AddressSecSchnorrPubKey) AddressPubKeyHash() *AddressPubKeyHash {
addr := &AddressPubKeyHash{net: a.net, netID: a.pubKeyHashID}
copy(addr.hash[:], Hash160(a.serialize()))
return addr
}
// DSA returns the underlying digital signature algorithm for the
// address.
func (a *AddressSecSchnorrPubKey) DSA(net *chaincfg.Params) int {
return chainec.ECTypeSecSchnorr
}
// Net returns the network for the address.
func (a *AddressSecSchnorrPubKey) Net() *chaincfg.Params {
return a.net
}