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  }