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'))
相关推荐
爱上妖精的尾巴1 小时前
3-5 WPS JS宏 工作表的移动与复制学习笔记
javascript·笔记·学习·wps·js宏·jsa
屁股割了还要学3 小时前
【计算机网络入门】初学计算机网络(五)
学习·计算机网络·考研·青少年编程
屁股割了还要学3 小时前
【计算机网络入门】初学计算机网络(七)
网络·学习·计算机网络·考研·青少年编程
一天八小时5 小时前
计算机网络学习————(五)TCP/IP学习
学习·tcp/ip·计算机网络
tt5555555555555 小时前
每日一题——接雨水
数据结构·笔记·学习·算法
熊猫烧竹5 小时前
【量化金融自学笔记】--开篇.基本术语及学习路径建议
笔记·学习·金融
wyz09237 小时前
python 之协程笔记
开发语言·笔记·python
安 当 加 密7 小时前
安当全栈式PostgreSQL数据库安全解决方案:透明加密、动态凭据与勒索防护一体化实践
数据库·postgresql·区块链
武昌库里写JAVA7 小时前
【Redis学习】Redis Docker安装,自定义config文件(包括RDB\AOF setup)以及与Spring Boot项目集成
java·开发语言·spring boot·学习·课程设计
姓刘的哦7 小时前
IMX6Ull学习笔记1:汇编点亮LED灯
汇编·笔记·学习