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