比特币钱包地址的变迁
比特币钱包地址主要有三种类型,它们分别是:
1. P2PKH地址(Pay-to-Public-Key-Hash)
以数字“1”开头。
例如:1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa
2. P2SH地址(Pay-to-Script-Hash)
以数字“3”开头。
例如:3J98t1WpEZ73CNmQviecrnyiWrnqRhWNLy
3. Bech32地址(SegWit地址)
以“bc1”开头。
例如:bc1qar0srrr7x3n5q0g5x6l6g0z4c2s4h0l8h6k3qf
我将分三篇文章,分别介绍三种地址的生成步骤、地址由来以及应用场景。
生成这些地址将使用Python的ECDSA库,还有hashlib和base58。
P2PKH地址的生成步骤:
from ecdsa import SECP256k1, SigningKey
import hashlib
import base58
private_key = SigningKey.generate(curve=SECP256k1)
public_key = private_key.get_verifying_key()
public_key_bytes = public_key.to_string()
sha256 = hashlib.sha256(public_key_bytes).digest()
ripemd160 = hashlib.new('ripemd160', sha256).digest()
address = b'\x00' + ripemd160 # \x00 bitcoin mainnet
至此,P2PKH的地址主体已经生成了。
checksum = hashlib.sha256(hashlib.sha256(address).digest()).digest()[:4]
address += checksum
address = base58.b58encode(address).decode()
图示生成过程:
最后,找个在线工具验证我们生成的地址
</br>
151Wm9Xps2sR4wnTr8ffszL92U6WTFugC8
</br>
P2PKH地址仅含有公钥信息,所以是公钥哈希地址。只要提供同一公钥,按照相同的步骤总是可以得到相同的地址。所以区块链网络在花费比特币的时候,先拿到交易请求信息内的公钥,进行P2PKH计算得到钱包地址,校验公钥是否合法。其次再用公钥验签私钥签名的交易信息,通过则证明比特币花费请求是合法的。
比特币开放了一个小小的窗口,用于定义校验花费条件。这个窗口为了安全考虑,功能较弱,它称之为比特币脚本语言。基于栈数据结构和定义好的操作码,操作码可以认为是单一功能的函数。
P2PKH地址对应的解锁脚本定义如下示例:
OP_DUP OP_HASH160 ab68025513c3dbd2f7b92a94e0581f5d50f654e7 OP_EQUALVERIFY OP_CHECKSIG
该脚本的处理流程如下:
输入数据到堆栈:
PUSHDATA(Sig):交易签名数据压入栈。
PUSHDATA(PubKey):公钥压入栈。
此时栈内两个元素:
执行操作码,操作堆栈里的数据:
当前,比特币操作码有如下几类,后续我们分析其他类型地址的时候会陆续用到。比特币闪电网络也离不开这些操作码的支持。
以下截取自Bitcoin core项目:
std::string GetOpName(opcodetype opcode)
{
switch (opcode)
{
// push value
case OP_0 : return "0";
case OP_PUSHDATA1 : return "OP_PUSHDATA1";
case OP_PUSHDATA2 : return "OP_PUSHDATA2";
case OP_PUSHDATA4 : return "OP_PUSHDATA4";
case OP_1NEGATE : return "-1";
case OP_RESERVED : return "OP_RESERVED";
case OP_1 : return "1";
case OP_2 : return "2";
case OP_3 : return "3";
case OP_4 : return "4";
case OP_5 : return "5";
case OP_6 : return "6";
case OP_7 : return "7";
case OP_8 : return "8";
case OP_9 : return "9";
case OP_10 : return "10";
case OP_11 : return "11";
case OP_12 : return "12";
case OP_13 : return "13";
case OP_14 : return "14";
case OP_15 : return "15";
case OP_16 : return "16";
// control
case OP_NOP : return "OP_NOP";
case OP_VER : return "OP_VER";
case OP_IF : return "OP_IF";
case OP_NOTIF : return "OP_NOTIF";
case OP_VERIF : return "OP_VERIF";
case OP_VERNOTIF : return "OP_VERNOTIF";
case OP_ELSE : return "OP_ELSE";
case OP_ENDIF : return "OP_ENDIF";
case OP_VERIFY : return "OP_VERIFY";
case OP_RETURN : return "OP_RETURN";
// stack ops
case OP_TOALTSTACK : return "OP_TOALTSTACK";
case OP_FROMALTSTACK : return "OP_FROMALTSTACK";
case OP_2DROP : return "OP_2DROP";
case OP_2DUP : return "OP_2DUP";
case OP_3DUP : return "OP_3DUP";
case OP_2OVER : return "OP_2OVER";
case OP_2ROT : return "OP_2ROT";
case OP_2SWAP : return "OP_2SWAP";
case OP_IFDUP : return "OP_IFDUP";
case OP_DEPTH : return "OP_DEPTH";
case OP_DROP : return "OP_DROP";
case OP_DUP : return "OP_DUP";
case OP_NIP : return "OP_NIP";
case OP_OVER : return "OP_OVER";
case OP_PICK : return "OP_PICK";
case OP_ROLL : return "OP_ROLL";
case OP_ROT : return "OP_ROT";
case OP_SWAP : return "OP_SWAP";
case OP_TUCK : return "OP_TUCK";
// splice ops
case OP_CAT : return "OP_CAT";
case OP_SUBSTR : return "OP_SUBSTR";
case OP_LEFT : return "OP_LEFT";
case OP_RIGHT : return "OP_RIGHT";
case OP_SIZE : return "OP_SIZE";
// bit logic
case OP_INVERT : return "OP_INVERT";
case OP_AND : return "OP_AND";
case OP_OR : return "OP_OR";
case OP_XOR : return "OP_XOR";
case OP_EQUAL : return "OP_EQUAL";
case OP_EQUALVERIFY : return "OP_EQUALVERIFY";
case OP_RESERVED1 : return "OP_RESERVED1";
case OP_RESERVED2 : return "OP_RESERVED2";
// numeric
case OP_1ADD : return "OP_1ADD";
case OP_1SUB : return "OP_1SUB";
case OP_2MUL : return "OP_2MUL";
case OP_2DIV : return "OP_2DIV";
case OP_NEGATE : return "OP_NEGATE";
case OP_ABS : return "OP_ABS";
case OP_NOT : return "OP_NOT";
case OP_0NOTEQUAL : return "OP_0NOTEQUAL";
case OP_ADD : return "OP_ADD";
case OP_SUB : return "OP_SUB";
case OP_MUL : return "OP_MUL";
case OP_DIV : return "OP_DIV";
case OP_MOD : return "OP_MOD";
case OP_LSHIFT : return "OP_LSHIFT";
case OP_RSHIFT : return "OP_RSHIFT";
case OP_BOOLAND : return "OP_BOOLAND";
case OP_BOOLOR : return "OP_BOOLOR";
case OP_NUMEQUAL : return "OP_NUMEQUAL";
case OP_NUMEQUALVERIFY : return "OP_NUMEQUALVERIFY";
case OP_NUMNOTEQUAL : return "OP_NUMNOTEQUAL";
case OP_LESSTHAN : return "OP_LESSTHAN";
case OP_GREATERTHAN : return "OP_GREATERTHAN";
case OP_LESSTHANOREQUAL : return "OP_LESSTHANOREQUAL";
case OP_GREATERTHANOREQUAL : return "OP_GREATERTHANOREQUAL";
case OP_MIN : return "OP_MIN";
case OP_MAX : return "OP_MAX";
case OP_WITHIN : return "OP_WITHIN";
// crypto
case OP_RIPEMD160 : return "OP_RIPEMD160";
case OP_SHA1 : return "OP_SHA1";
case OP_SHA256 : return "OP_SHA256";
case OP_HASH160 : return "OP_HASH160";
case OP_HASH256 : return "OP_HASH256";
case OP_CODESEPARATOR : return "OP_CODESEPARATOR";
case OP_CHECKSIG : return "OP_CHECKSIG";
case OP_CHECKSIGVERIFY : return "OP_CHECKSIGVERIFY";
case OP_CHECKMULTISIG : return "OP_CHECKMULTISIG";
case OP_CHECKMULTISIGVERIFY : return "OP_CHECKMULTISIGVERIFY";
// expansion
case OP_NOP1 : return "OP_NOP1";
case OP_CHECKLOCKTIMEVERIFY : return "OP_CHECKLOCKTIMEVERIFY";
case OP_CHECKSEQUENCEVERIFY : return "OP_CHECKSEQUENCEVERIFY";
case OP_NOP4 : return "OP_NOP4";
case OP_NOP5 : return "OP_NOP5";
case OP_NOP6 : return "OP_NOP6";
case OP_NOP7 : return "OP_NOP7";
case OP_NOP8 : return "OP_NOP8";
case OP_NOP9 : return "OP_NOP9";
case OP_NOP10 : return "OP_NOP10";
// Opcode added by BIP 342 (Tapscript)
case OP_CHECKSIGADD : return "OP_CHECKSIGADD";
case OP_INVALIDOPCODE : return "OP_INVALIDOPCODE";
default: return "OP_UNKNOWN";
}
}
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!