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  }