比特币的地址类型
这部分内容主要来自于btcutil/address.go
一直困惑比特币是如何验证交易的,看了这个地质类型算是有点豁然开朗,实际上比特币的交易验证规则还是有点复杂的,它并不像以太坊那么简单明确.
个人理解,比特币对于交易的处理,首先是根据 pubkey script 判断是什么地址类型,然后进行不同的验证方法. 比如如果地质类型是AddressWitnessPubKeyHash,那么验证规则就明显和 P2PKH 不一样.
以下是address.go 中如何解析出地址:
// 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) (Address, error) {
// Bech32 encoded segwit addresses start with a human-readable part
// (hrp) followed by '1'. For Bitcoin mainnet the hrp is "bc", and for
// testnet it is "tb". If the address string has a prefix that matches
// one of the prefixes for the known networks, we try to decode it as
// a segwit address.
oneIndex := strings.LastIndexByte(addr, '1')
if oneIndex > 1 {
// The HRP is everything before the found '1'.
hrp := strings.ToLower(addr[:oneIndex])
if hrp == defaultNet.Bech32HRPSegwit {
witnessVer, witnessProg, err := decodeSegWitAddress(addr)
if err != nil {
return nil, err
}
// We currently only support P2WPKH and P2WSH, which is
// witness version 0.
if witnessVer != 0 {
return nil, UnsupportedWitnessVerError(witnessVer)
}
switch len(witnessProg) {
case 20:
return newAddressWitnessPubKeyHash(hrp, witnessProg)
case 32:
return newAddressWitnessScriptHash(hrp, witnessProg)
default:
return nil, UnsupportedWitnessProgLenError(len(witnessProg))
}
}
}
// 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 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, ErrChecksumMismatch
}
return nil, errors.New("decoded address is of unknown format")
}
switch len(decoded) {
case ripemd160.Size: // P2PKH or P2SH
isP2PKH := netID == defaultNet.PubKeyHashAddrID
isP2SH := netID == defaultNet.ScriptHashAddrID
switch hash160 := decoded; {
case isP2PKH && isP2SH:
return nil, ErrAddressCollision
case isP2PKH:
return newAddressPubKeyHash(hash160, netID)
case isP2SH:
return newAddressScriptHashFromHash(hash160, netID)
default:
return nil, ErrUnknownAddressType
}
default:
return nil, errors.New("decoded address is of unknown size")
}
}
总共有四中地质类型:
AddressPubKey
// AddressPubKey is an Address for a pay-to-pubkey transaction.
type AddressPubKey struct {
pubKeyFormat PubKeyFormat
pubKey *btcec.PublicKey
pubKeyHashID byte
}
AddressPubKeyHash
// AddressPubKeyHash is an Address for a pay-to-pubkey-hash (P2PKH)
// transaction.
type AddressPubKeyHash struct {
hash [ripemd160.Size]byte
netID byte
}
AddressScriptHash
// AddressScriptHash is an Address for a pay-to-script-hash (P2SH)
// transaction.
type AddressScriptHash struct {
hash [ripemd160.Size]byte
netID byte
}
AddressScriptHash
// AddressScriptHash is an Address for a pay-to-script-hash (P2SH)
// transaction.
type AddressScriptHash struct {
hash [ripemd160.Size]byte
netID byte
}
AddressWitnessPubKeyHash
// AddressWitnessPubKeyHash is an Address for a pay-to-witness-pubkey-hash
// (P2WPKH) output. See BIP 173 for further details regarding native segregated
// witness address encoding:
// https://github.com/bitcoin/bips/blob/master/bip-0173.mediawiki
type AddressWitnessPubKeyHash struct {
hrp string
witnessVersion byte
witnessProgram [20]byte
}
AddressWitnessScriptHash
// AddressWitnessScriptHash is an Address for a pay-to-witness-script-hash
// (P2WSH) output. See BIP 173 for further details regarding native segregated
// witness address encoding:
// https://github.com/bitcoin/bips/blob/master/bip-0173.mediawiki
type AddressWitnessScriptHash struct {
hrp string
witnessVersion byte
witnessProgram [32]byte
}