比特币的地址类型

简介: 比特币的地址类型这部分内容主要来自于btcutil/address.go一直困惑比特币是如何验证交易的,看了这个地质类型算是有点豁然开朗,实际上比特币的交易验证规则还是有点复杂的,它并不像以太坊那么简单明确.

比特币的地址类型

这部分内容主要来自于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
}
目录
相关文章
|
6月前
|
算法 搜索推荐 数据处理
值交换解析法(无第三方变量法)
值交换解析法(无第三方变量法)
43 0
|
JavaScript 前端开发 IDE
如何获取某个地址拥有的所有ERC20代币
本文将介绍如何设置Chainbase帐户、编写使用Chainbase API的脚本以及获取ERC20令牌余额的过程。
283 0
|
存储 安全 区块链
储存比特币的钱包开发源码规则解析
储存比特币的钱包开发源码规则解析
|
存储 算法 区块链
虚拟币钱包开发[源码规则解析]
虚拟币钱包开发[源码规则解析]
|
存储 区块链 Python
以太坊中如何获取另外一个智能合约部署的合约地址?
如何获取另外一个智能合约部署的合约地址? 我正试图从另一个工厂合约中签智能合约,然后重新部署新智能合约的地址。然而,它返回的地址是交易哈希值而不是合约地址。
2339 0
|
Unix 区块链 索引
比特币区块结构解析
前言 本文主要具体分析一个区块的值,通过逐字节分析,找出与比特币区块字段对应的部分,我们就可以加深对比特币区块的了解。 准备工作 我们在https://webbtc.com网站上查询区块哈希值为00000000d1145790a8694403d4063f323d499e655c83426834d4ce2f8dd4a2ee的区块,查询到该区块的json格式信息和十六进制格式信息。
2759 0
|
Rust JavaScript 前端开发
区块链开发(八)以太坊不同语言客户端地址
区块链开发(八)以太坊不同语言客户端地址
131 0
|
区块链
solidity智能合约如何判断地址为0或空
solidity智能合约如何判断地址为0或空
416 0
|
区块链
以太坊·将自定义数据写入到区块链中
本文讲述如何将数据保存到区块链中。
6497 0
|
程序员 PHP 区块链
是否可以用以太坊交易EthSendTransaction发送任意文本?
是的。文本应该是ASCII编码的,并在交易的数据中以十六进制字符串的形式提供。示例如下: RawTransaction.
2569 0