bitcoinjs学习笔记4—p2pkh、p2sh、p2wpkh地址生成

BitcoinJS 学习笔记 4 --- P2PKH、P2SH、P2WPKH 地址生成大纲


1. 概述
  • 目标 : 学习如何使用 BitcoinJS 生成三种常见的比特币地址类型:
    1. P2PKH(Pay-to-Public-Key-Hash)
    2. P2SH(Pay-to-Script-Hash)
    3. P2WPKH(Pay-to-Witness-Public-Key-Hash)
  • 工具: BitcoinJS 库、比特币测试网(Testnet)或回归测试网络(Regtest)。

2. P2PKH 地址生成
  • 定义 : P2PKH 是最常见的比特币地址类型,以 1 开头。
  • 生成步骤 :
    1. 生成密钥对(私钥和公钥)。
    2. 对公钥进行哈希(SHA-256 + RIPEMD-160)生成公钥哈希。
    3. 使用 Base58Check 编码生成地址。
  • 代码示例:
javascript 复制代码
const bitcoin = require('bitcoinjs-lib');
const network = bitcoin.networks.regtest;
ECPairFactory = require('ecpair').default;
ecc = require('tiny-secp256k1');
ECPair = ECPairFactory(ecc);

const keyPair = bitcoin.ECPair.makeRandom({ network });
const { address } = bitcoin.payments.p2pkh({
  pubkey: keyPair.publicKey,
  network,
});

console.log('P2PKH Address:', address);

3. P2SH 地址生成
  • 定义 : P2SH 是一种支持多重签名和复杂脚本的地址类型,以 3 开头。
  • 生成步骤 :
    1. 创建赎回脚本(Redeem Script),例如多重签名脚本。
    2. 对赎回脚本进行哈希(SHA-256 + RIPEMD-160)生成脚本哈希。
    3. 使用 Base58Check 编码生成地址。
  • 代码示例:
javascript 复制代码
const bitcoin = require('bitcoinjs-lib');
const network = bitcoin.networks.regtest;
ECPairFactory = require('ecpair').default;
ecc = require('tiny-secp256k1');
ECPair = ECPairFactory(ecc);
const { signECDSA } = require('@scure/btc-signer/utils');
const hashtype = bitcoin.Transaction.SIGHASH_ALL;

// 3.p2sh地址生成
const ONE = Buffer.from('0000000000000000000000000000000000000000000000000000000000000001', 'hex',);
const keyPairAlice = ECPair.fromPrivateKey(ONE,  { network });
const TWO = Buffer.from('0000000000000000000000000000000000000000000000000000000000000002', 'hex',);
const keyPairBob = ECPair.fromPrivateKey(TWO, { network });

// 3.1 Bob的交易信息
const previousTxHex_Bob = '02000000000101cecc606da73967ef24c219eb79422c8170aa1e8b2d7d8c4832d6d6e7bb3c1db00100000000fdffffff02f0412e1201000000160014862a1210923c5f90a1e4bd575f798f72e874fa7c00e1f5050000000016001406afd46bcdfd22ef94ac122aa11f241244a37ecc02473044022066f4cc42730accc40c8f69bb0144b676bef1d2b53c52df898d42b662154ab547022008856664818aaf3e8f87b7f48906559f097b53fa87634dc132bb9803aa6a1a1d01210251250ede05c16d0060b23bdce6585cda09fa0edddb77830266c0cf410a6096f3b8000000';
const utxo_Bob = bitcoin.Transaction.fromHex(previousTxHex_Bob);
const txid_Bob = utxo_Bob.getId();
txIndex_Bob = 1;
const amount_Bob = utxo_Bob.outs[txIndex_Bob].value;

// 3.2将Bob交易信息拼接成字符串,作为签名
x0=(Buffer.from(keyPairBob.publicKey)).toString('hex');
str= x0.concat(' ',  txid_Bob, txIndex_Bob.toString(), amount_Bob.toString(), hashtype.toString()) // Bob pays Alice
hashOut = bitcoin.crypto.hash160(str);
sig0 = signECDSA(hashOut, keyPairAlice.privateKey);
signature0Hash = bitcoin.crypto.hash160(sig0);

// 3.3构造p2sh锁定脚本
locking_script_Alice = bitcoin.script.compile([
   bitcoin.opcodes.OP_HASH160,
   signature0Hash,
   bitcoin.opcodes.OP_EQUALVERIFY,
   bitcoin.opcodes.OP_1,
]);
console.log('Locking_script_Alice: ' + Buffer.from(locking_script_Alice).toString('hex'));
//Complete the script of the previousTx, and deploy it
p2sh = bitcoin.payments.p2sh({redeem: {output: locking_script_Alice, network}, network})
console.log('p2sh.address  ', p2sh.address)

4. P2WPKH 地址生成
  • 定义 : P2WPKH 是 SegWit 地址类型,以 bc1 开头(主网)或 tb1 开头(测试网)。
  • 生成步骤 :
    1. 生成密钥对(私钥和公钥)。
    2. 对公钥进行哈希(SHA-256 + RIPEMD-160)生成公钥哈希。
    3. 使用 Bech32 编码生成地址。
  • 代码示例:
javascript 复制代码
const bitcoin = require('bitcoinjs-lib');
const network = bitcoin.networks.regtest;
ECPairFactory = require('ecpair').default;
ecc = require('tiny-secp256k1');
ECPair = ECPairFactory(ecc);

const keyPair = ECPair.makeRandom({ network });
const p2wpkh = bitcoin.payments.p2wpkh({
 pubkey: keyPair.publicKey,
 network,
});
console.log("p2wpkh address:", p2wpkh.address);

5.由私钥恢复公钥
javascript 复制代码
const bitcoin = require('bitcoinjs-lib');
const network = bitcoin.networks.regtest;
ECPairFactory = require('ecpair').default;
ecc = require('tiny-secp256k1');
ECPair = ECPairFactory(ecc);
// 4.两种记录私钥格式,hex形式以及WIF格式,还有memorica助记词格式的(bitcoinjs在GitHub上的示例中有使用助记词形式,但使用的是ts语法,感兴趣的可以看看官方代码)
// hex格式
const privateKey = '87e03af6877f730b54e082ddaf46d7dc2888c0d33ac6ff1307ab98ff1960ecfb';
// WIF格式
const WIF = 'cS8pu3rrhjmYeRjmCRjJdVpUfqv7nAgkPG7o7nqr9xyxcJVZJb5s';

// hex格式私钥恢复密钥对
const keyPairByHex = ECPair.fromPrivateKey(Buffer.from(privateKey,'hex'), { network });
console.log("Public Key By Hex:", Buffer.from(keyPairByHex.publicKey).toString('hex'));

const keyPairByWIF = ECPair.fromWIF(WIF, network);
console.log("Public Key By WIF:", Buffer.from(keyPairByWIF.publicKey).toString('hex'))
6. 地址生成的比较
特性 P2PKH P2SH P2WPKH
地址格式 Base58Check(1 开头) Base58Check(3 开头) Bech32(bc1tb1 开头)
脚本类型 简单脚本(公钥哈希) 复杂脚本(多重签名等) 简单脚本(公钥哈希)
签名存储 解锁脚本 解锁脚本 见证部分
交易大小 较大 较大 较小
手续费 较高 较高 较低
兼容性 所有钱包支持 所有钱包支持 需要 SegWit 支持

3种协议地址生成代码汇总
javascript 复制代码
const bitcoin = require('bitcoinjs-lib');
const network = bitcoin.networks.regtest;
ECPairFactory = require('ecpair').default;
ecc = require('tiny-secp256k1');
ECPair = ECPairFactory(ecc);
const { signECDSA } = require('@scure/btc-signer/utils');
const hashtype = bitcoin.Transaction.SIGHASH_ALL;

// 1.p2pkh地址生成
const keyPair = ECPair.makeRandom({ network });
const p2pkh = bitcoin.payments.p2pkh({
  pubkey: keyPair.publicKey,
  network,
});
// 2.p2wpkh地址生成
const p2wpkh = bitcoin.payments.p2wpkh({
  pubkey: keyPair.publicKey,
  network,
});
console.log('private key (HEX):', Buffer.from(keyPair.privateKey).toString('hex'));
console.log('Private Key (WIF):', keyPair.toWIF());
console.log("Public Key:", Buffer.from(keyPair.publicKey).toString('hex'));
console.log("p2pkh address:", p2pkh.address);
console.log("p2wpkh address:", p2wpkh.address);

// 3.p2sh地址生成
const ONE = Buffer.from('0000000000000000000000000000000000000000000000000000000000000001', 'hex',);
const keyPairAlice = ECPair.fromPrivateKey(ONE,  { network });
const TWO = Buffer.from('0000000000000000000000000000000000000000000000000000000000000002', 'hex',);
const keyPairBob = ECPair.fromPrivateKey(TWO, { network });

// 3.1 Bob的交易信息
const previousTxHex_Bob = '02000000000101cecc606da73967ef24c219eb79422c8170aa1e8b2d7d8c4832d6d6e7bb3c1db00100000000fdffffff02f0412e1201000000160014862a1210923c5f90a1e4bd575f798f72e874fa7c00e1f5050000000016001406afd46bcdfd22ef94ac122aa11f241244a37ecc02473044022066f4cc42730accc40c8f69bb0144b676bef1d2b53c52df898d42b662154ab547022008856664818aaf3e8f87b7f48906559f097b53fa87634dc132bb9803aa6a1a1d01210251250ede05c16d0060b23bdce6585cda09fa0edddb77830266c0cf410a6096f3b8000000';
const utxo_Bob = bitcoin.Transaction.fromHex(previousTxHex_Bob);
const txid_Bob = utxo_Bob.getId();
txIndex_Bob = 1;
const amount_Bob = utxo_Bob.outs[txIndex_Bob].value;

// 3.2将Bob交易信息拼接成字符串,作为签名
x0=(Buffer.from(keyPairBob.publicKey)).toString('hex');
str= x0.concat(' ',  txid_Bob, txIndex_Bob.toString(), amount_Bob.toString(), hashtype.toString()) // Bob pays Alice
hashOut = bitcoin.crypto.hash160(str);
sig0 = signECDSA(hashOut, keyPairAlice.privateKey);
signature0Hash = bitcoin.crypto.hash160(sig0);

// 3.3构造p2sh锁定脚本
locking_script_Alice = bitcoin.script.compile([
    bitcoin.opcodes.OP_HASH160,
    signature0Hash,
    bitcoin.opcodes.OP_EQUALVERIFY,
    bitcoin.opcodes.OP_1,
]);
console.log('Locking_script_Alice: ' + Buffer.from(locking_script_Alice).toString('hex'));
//Complete the script of the previousTx, and deploy it
p2sh = bitcoin.payments.p2sh({redeem: {output: locking_script_Alice, network}, network})
console.log('p2sh.address  ', p2sh.address)


// 4.两种记录私钥格式,hex形式以及WIF格式,还有memorica助记词格式的(bitcoinjs在GitHub上的示例中有使用助记词形式,但使用的是ts语法,感兴趣的可以看看官方代码)
// hex格式
const privateKey = '87e03af6877f730b54e082ddaf46d7dc2888c0d33ac6ff1307ab98ff1960ecfb';
// WIF格式
const WIF = 'cS8pu3rrhjmYeRjmCRjJdVpUfqv7nAgkPG7o7nqr9xyxcJVZJb5s';

// hex格式私钥恢复密钥对
const keyPairByHex = ECPair.fromPrivateKey(Buffer.from(privateKey,'hex'), { network });
console.log("Public Key By Hex:", Buffer.from(keyPairByHex.publicKey).toString('hex'));

const keyPairByWIF = ECPair.fromWIF(WIF, network);
console.log("Public Key By WIF:", Buffer.from(keyPairByWIF.publicKey).toString('hex'))
相关推荐
卡提西亚3 分钟前
数据库笔记-4-SQL语言之DCL
数据库·笔记·sql
Radan小哥12 分钟前
Docker学习笔记—day0010
笔记·学习·docker
im_AMBER16 分钟前
Canvas架构手记 05 鼠标事件监听 | 原生事件封装 | ctx 结构化对象
前端·笔记·学习·架构
老神在在00121 分钟前
Mybatis01
后端·学习·spring·java-ee·mybatis
Y***890828 分钟前
Neo4j图数据库学习(二)——SpringBoot整合Neo4j
数据库·学习·neo4j
理人综艺好会35 分钟前
MySQL学习之go-mysql
学习·mysql·golang
想要成为计算机高手41 分钟前
π*0.6: 从实践中学习 -- 2025.11.17 -- Physical Intelligence (π) -- 未开源
人工智能·学习·机器人·多模态·具身智能·vla
N***73851 小时前
区块链跨链技术实现
区块链
O***p6041 小时前
区块链在智能合约安全中的审计
安全·区块链·智能合约
A***07171 小时前
Web3.0在去中心化存储中的数据检索
web3·去中心化·区块链