本文仅讨论地址的实现。不同的交易类型使用的的地址类型不同。
关键概念
-
交易类型
具体是指比特币交易中lock/unlock script 的种类。
目前的bitcoin core 实现中包括如下4种:- P2PKH(pay to public key hash)
该类型的脚本可将bitcoin锁定到某一公钥hash上。 - P2SH(pay to script hash)
该类型的脚本可将bitcoin锁定到某一脚本的hash值上。 - P2WPKH(pay to witness public key hash)
类似于P2PKH,不过在交易结构上将unlock script (即 witness )隔离到单独的数据区域。 - P2WSH(pay to witness script hash)
类似于P2SH,在交易结构上也将unlock script (即 witness )隔离到单独的数据区域。地址长度也有所不同。
- P2PKH(pay to public key hash)
-
地址
具体分两种- 公钥hash
锁定到该种地址上的bitcoin,可用密钥签名即可解锁使用。 - 脚本hash
锁定到该种地址上的bitcoin,可用密钥签名+补偿脚本解锁使用。
- 公钥hash
具体实现
地址在bitcoin源码中的实现为(standard.h):
/**
* A txout script template with a specific destination. It is either:
* * CNoDestination: no destination set
* * CKeyID: TX_PUBKEYHASH destination (P2PKH)
* * CScriptID: TX_SCRIPTHASH destination (P2SH)
* * WitnessV0ScriptHash: TX_WITNESS_V0_SCRIPTHASH destination (P2WSH)
* * WitnessV0KeyHash: TX_WITNESS_V0_KEYHASH destination (P2WPKH)
* * WitnessUnknown: TX_WITNESS_UNKNOWN destination (P2W???)
* A CTxDestination is the internal data type encoded in a bitcoin address
*/
typedef boost::variant<CNoDestination, CKeyID, CScriptID, WitnessV0ScriptHash, WitnessV0KeyHash, WitnessUnknown> CTxDestination;
其中P2PKH交易类型的地址实现如下(pubkey.h):
可以看到该地址类型,即为master-bitcoin中所说的公钥hash地址
//! Get the KeyID of this public key (hash of its serialization)
CKeyID GetID() const
{
return CKeyID(Hash160(vch, vch + size()));
}
P2SH 交易类型的地址实现如下(standard.cpp,standard.h)
/** A reference to a CScript: the Hash160 of its serialization (see script.*/
// standard.h
class CScriptID : public uint160
{
public:
CScriptID() : uint160() {}
CScriptID(const CScript& in);
CScriptID(const uint160& in) : uint160(in) {}
};
//standard.cpp
CScriptID::CScriptID(const CScript& in) : uint160(Hash160(in.begin(), in.end())) {}
Vo版本的P2WSH地址实现如下:(standard.h)
struct WitnessV0ScriptHash : public uint256
{
WitnessV0ScriptHash() : uint256() {}
explicit WitnessV0ScriptHash(const uint256& hash) : uint256(hash) {}
using uint256::uint256;
};
Vo版本的P2WPKH地址实现如下(standard.h)
struct WitnessV0KeyHash : public uint160
{
WitnessV0KeyHash() : uint160() {}
explicit WitnessV0KeyHash(const uint160& hash) : uint160(hash) {}
using uint160::uint160;
};