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'))
相关推荐
suirosu14 小时前
痛风高尿酸血症的治疗方法
笔记·其他·微信·新浪微博
微软技术分享14 小时前
本地部署千问 2.5-1.5B-GGUF + LangChain 封装学习
数据库·学习·langchain
余生皆假期-14 小时前
YuanHub 源码分析【一】FlashDB 初始化与项目应用
笔记·单片机·嵌入式硬件
GISer_Jing15 小时前
AI全栈转型_TS后端学习路线
前端·人工智能·后端·学习
小郑加油15 小时前
python学习Day11:认识与创建CSV文件
开发语言·python·学习
做cv的小昊15 小时前
【TJU】研究生应用统计学课程笔记(6)——第二章 参数估计(2.4 区间估计)
人工智能·笔记·线性代数·算法·机器学习·数学建模·概率论
AI360labs_atyun16 小时前
清华开源AI导师OpenMAIC!30秒生成互动课堂!还能学“养龙虾”
人工智能·科技·学习·ai
学机械的鱼鱼16 小时前
【学习笔记】QGroundControl安装与使用简明指南
笔记·学习
zhangrelay16 小时前
Ubuntu 18.04 经典 / 有趣 / 实用 APT 软件清单
linux·笔记·学习·ubuntu
FserSuN16 小时前
Machine Learning Specialization - Week 1, 1-8学习总结
人工智能·学习·机器学习