bitcoinjs学习1—P2PKH

1. 概述

在本学习笔记中,我们将深入探讨如何使用 bitcoinjs-lib 库构建和签名一个 P2PKH(Pay-to-PubKey-Hash) 比特币交易。P2PKH 是比特币网络中最常见和最基本的交易类型之一,理解其工作原理是掌握比特币交易构建的关键。

想要详细了解p2pkh工作原理可以查看该网址:p2pkh(Pay to PublicKey Hash)


1.1 目标

  • 主要目标:学习如何使用 bitcoinjs-lib 构建、签名并广播一个 P2PKH 交易。
  • 具体任务
    1. 生成一个 P2PKH 地址。
    2. 构建一个包含输入和输出的交易。
    3. 将交易广播到regtest网络中。

1.2 P2PKH 的工作原理

  1. 锁定资金

    发送方创建一个交易输出,将比特币锁定到接收方的公钥哈希(即地址)。

  2. 解锁资金
  • 接收方在花费比特币时,需要提供:
    • 公钥。
    • 使用私钥生成的签名。
  • 输入脚本(scriptSig)格式:<Signature> <PublicKey>
  1. 验证过程
    • 比特币网络会验证签名是否与公钥匹配,以及公钥哈希是否与输出脚本中的哈希一致。

在比特币脚本中,OP_DUP OP_HASH160 <PubKeyHash> OP_EQUALVERIFY OP_CHECKSIGP2PKH(Pay-to-PubKey-Hash) 交易的 锁定脚本(scriptPubKey) 的核心部分。它定义了如何锁定比特币以及如何解锁比特币的条件。

以下是对每个操作码的详细解释:


1. OP_DUP

  • 作用:复制栈顶元素。
  • 操作
    • 将栈顶的元素复制一份,并将副本压入栈中。
  • 示例
    • 如果栈顶是 A,执行 OP_DUP 后,栈变为 [A, A]

2. OP_HASH160

  • 作用:对栈顶元素进行哈希运算。
  • 操作
    • 弹出栈顶元素,先进行 SHA-256 哈希,再进行 RIPEMD-160 哈希,最后将结果压入栈中。
  • 示例
    • 如果栈顶是 A,执行 OP_HASH160 后,栈变为 [Hash160(A)]

3. <PubKeyHash>

  • 作用:将接收方的公钥哈希压入栈中。
  • 操作
    • 这是一个数据推送操作,将接收方的公钥哈希(20 字节)压入栈中。
  • 示例
    • 如果接收方的公钥哈希是 B,执行后栈变为 [Hash160(A), B]

4. OP_EQUALVERIFY

  • 作用:验证栈顶两个元素是否相等,并移除它们。
  • 操作
    • 弹出栈顶两个元素,比较它们是否相等。
    • 如果相等,继续执行;如果不相等,脚本执行失败。
  • 示例
    • 如果栈顶是 [Hash160(A), B],执行 OP_EQUALVERIFY 后:
      • 如果 Hash160(A) == B,栈为空,继续执行。
      • 如果 Hash160(A) != B,脚本失败。

5. OP_CHECKSIG

  • 作用:验证签名和公钥是否匹配。
  • 操作
    • 弹出栈顶两个元素:签名和公钥。
    • 使用公钥验证签名是否对当前交易有效。
    • 如果验证成功,将 true 压入栈中;否则,将 false 压入栈中。
  • 示例
    • 如果栈顶是 [Signature, PublicKey],执行 OP_CHECKSIG 后:
      • 如果签名有效,栈变为 [true]
      • 如果签名无效,栈变为 [false]

6. 整体脚本的执行流程

假设解锁脚本(scriptSig)提供了签名和公钥:<Signature> <PublicKey>,锁定脚本(scriptPubKey)为 OP_DUP OP_HASH160 <PubKeyHash> OP_EQUALVERIFY OP_CHECKSIG

执行步骤:
  1. 初始栈

    • 解锁脚本将签名和公钥压入栈中:
      [Signature, PublicKey]
      
  2. 执行 OP_DUP

    • 复制公钥:
      [Signature, PublicKey, PublicKey]
      
  3. 执行 OP_HASH160

    • 对公钥进行哈希:
      [Signature, PublicKey, Hash160(PublicKey)]
      
  4. 压入 <PubKeyHash>

    • 将接收方的公钥哈希压入栈中:
      [Signature, PublicKey, Hash160(PublicKey), PubKeyHash]
      
  5. 执行 OP_EQUALVERIFY

    • 比较 Hash160(PublicKey)PubKeyHash
      • 如果相等,移除这两个元素:
        [Signature, PublicKey]
        
      • 如果不相等,脚本失败。
  6. 执行 OP_CHECKSIG

    • 使用公钥验证签名:
      • 如果签名有效,栈变为:
        [true]
        
      • 如果签名无效,栈变为:
        [false]
        
  7. 脚本结果

    • 如果栈顶为 true,交易有效,资金可以解锁。
    • 如果栈顶为 false,交易无效,资金无法解锁。

1.3 工具和技术栈

1.3.1 bitcoinjs-lib
  • 简介bitcoinjs-lib 是一个用于处理比特币交易的 JavaScript 库。它支持构建、签名和解析比特币交易,适用于 Node.js 和浏览器环境。

  • 安装

# 选择一个目录作为项目目录,打开vscode,打开命令行窗口
npm init -y

# 安装依赖
npm i bitcoinjs-lib ecpair tiny-secp256k1
1.3.2 比特币测试网
  • 简介:比特币测试网(Testnet)是一个用于开发和测试的比特币网络,其功能与主网相同,但比特币没有实际价值。(新手建议还是使用regtest,testnet测试网需要申请领取测试币,每次领取金额都较少,一般为10000聪)
  • 用途
    • 测试交易构建和签名。
    • 避免在主网上浪费真实比特币。
  • 获取测试网比特币
    • 使用测试网水龙头(如 testnet-faucet.com)获取免费的测试网比特币。
1.3.3 比特币测试网浏览器
  • 用途:查看交易状态和区块链数据。
  • 推荐工具
    • blockstream.info/testnet
    • mempool.space/testnet

1.4 p2pkh交易demo

1.4.1准备工作

交易:Alice向Bob转账2个比特币
先使用bitcoin-core向Alice的地址转2个比特币,再用这笔未花费交易给Bob发送

在这里插入图片描述

在交易记录中右击刚刚的交易,复制原始交易,再根据上一节预备知识中提到的解析交易

或者使用控制台(命令行窗口)

sendtoaddress mrCDrCybB6J1vRfbwM5hemdJz73FwDBC8r 2
getrawtransaction txid
decoderawtransaction hex

记录交易的txid、vout中是alice的输出的次序n,金额value
在这里插入图片描述

以下是Alice给Bob发送比特币的代码(使用p2pkh)

const bitcoin = require('bitcoinjs-lib');
const network = bitcoin.networks.regtest;

ECPairFactory = require('ecpair').default;
ecc = require('tiny-secp256k1');
const base58check = require('base58check');  //npm i --save base58check
ECPair = ECPairFactory(ecc);
const hashtype = bitcoin.Transaction.SIGHASH_ALL;

// Alice给Bob发送2个比特币
const ONE = Buffer.from('0000000000000000000000000000000000000000000000000000000000000001', 'hex',);
const keyPairAlice = ECPair.fromPrivateKey(ONE, { network });
const TWO = Buffer.from('0000000000000000000000000000000000000000000000000000000000000002', 'hex',);
const keyPairBob = ECPair.fromPrivateKey(TWO, { network });
// alice_address: mrCDrCybB6J1vRfbwM5hemdJz73FwDBC8r
// bob_address: mg8Jz5776UdyiYcBb9Z873NTozEiADRW5H

// alice上一笔未花费的交易的txid,
const txid = '4a3cc600d4973479aafb62b5789590dd7738c3f9f1956a513a361e20ef56f9bb'
const vout = 1; // 上一笔交易中的输出
const amount = BigInt(200000000);// 转账金额

// 收款人bob的地址
const { address } = bitcoin.payments.p2pkh({ pubkey: keyPairBob.publicKey })
var PayeeBobAddr = base58check.decode(address, 'hex')
console.log('Bob_hashPubkey:', Buffer.from(PayeeBobAddr.data, 'Hex').toString('hex'));


const tx = new bitcoin.Transaction(network);

// 添加输入
tx.addInput(Buffer.from(txid, 'hex').reverse(), vout);

// 添加输出
const outputScript = bitcoin.payments.p2pkh({ pubkey: keyPairBob.publicKey }).output;
tx.addOutput(outputScript, amount - BigInt(10000));

// 添加签名
// 上一笔交易的输出脚本
const preoutputScript = bitcoin.payments.p2pkh({ pubkey: keyPairAlice.publicKey }).output;
// 生成比特币交易中某个输入的签名哈希值(sighash)。hashtype=1表示对交易的所有输入都进行哈希处理
const signhash = tx.hashForSignature(0, preoutputScript, hashtype);

// 构造p2pkh的解锁脚本: [签名 公钥]
const scriptSig = bitcoin.script.signature.encode(keyPairAlice.sign(signhash), hashtype);
tx.setInputScript(0,
    bitcoin.script.compile([scriptSig, keyPairAlice.publicKey])
)

// 输出交易原始数据
console.log('Raw Transaction:', tx.toHex());

// 广播交易
//sendrawtransaction <raw_transaction_hex>

// 获取txHex: getrawtransaction txid
// 解析交易: decoderawtransaction txHex

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/968926.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

有限状态系统的抽象定义及CEGAR分析解析理论篇

文章目录 一、有限状态系统的抽象定义及相关阐述1、有限状态系统定义2、 有限状态系统间的抽象关系&#xff08;Abstract&#xff09;2.1 基于函数的抽象定义2.2 基于等价关系的抽象定义 二、 基于上面的定义出发&#xff0c;提出的思考1. 为什么我们想要/需要进行抽象2. 抽象是…

【linux学习指南】线程同步与互斥

文章目录 &#x1f4dd;线程互斥&#x1f320; 库函数strncpy&#x1f309;进程线程间的互斥相关背景概念&#x1f309;互斥量mutex &#x1f320;线程同步&#x1f309;条件变量&#x1f309;同步概念与竞态条件&#x1f309; 条件变量函数 &#x1f6a9;总结 &#x1f4dd;线…

云上话ai

这两天参加了几场ai视频直播 今天想分享一下照片&#xff0c;记录一下&#xff5e;

OpenVINO 2025.0重磅升级:开启⽣成式AI全场景⾰命!

2025年2⽉6⽇&#xff0c;英特尔OpenVINO™ 2025.0版本震撼发布&#xff0c;本次升级堪称近三年最⼤规模技术⾰新&#xff01;从⽣成 式AI性能跃升到全栈硬件⽀持&#xff0c;从开发者⼯具链优化到边缘计算突破&#xff0c;六⼤核⼼升级重新定义AI部署效率。 一&#xff0c;&a…

语言大模型基础概念 一(先了解听说过的名词都是什么)

SFT&#xff08;监督微调&#xff09;和RLHF&#xff08;基于人类反馈的强化学习&#xff09;的区别 STF&#xff08;Supervised Fine-Tuning&#xff09;和RLHF&#xff08;Reinforcement Learning from Human Feedback&#xff09;是两种不同的模型训练方法&#xff0c;分别…

裙子贴图提示词【图生图】

正向&#xff1a; (a plaid short skirt with checkered texture:1.4),(no human figure),wallpaper,incredibly absurdres,huge filesize,highres,absurdres,artbook_game c,s,rt,octane,no light,best quality,illustration,looking at viewer,impasto,canvas,realistic,rea…

【竞技宝】LCK:KT0-3爆冷不敌NS淘汰出局

北京时间2月13日&#xff0c;英雄联盟LCK2025在昨天正式迎来第一阶段的季后赛&#xff0c;首战迎来KT对阵NS&#xff0c;以下是本场比赛的详细战报。 第一局&#xff1a; KT&#xff1a;安蓓萨、大树、沙皇、韦鲁斯、布隆 NS&#xff1a;杰斯、瑟庄妮、阿萝拉、卡莎、泰坦 首…

电脑端调用摄像头拍照:从基础到实现

文章目录 1. 了解navigator.mediaDevices.getUserMedia API2. 创建 HTML 结构3. 编写 JavaScript 代码3.1 打开摄像头3.2 拍照 4. 完整代码5. 测试6. 注意事项及部署 在现代 Web 开发中&#xff0c;调用摄像头进行拍照是一个常见的功能&#xff0c;尤其是在需要用户上传头像、进…

lvs的DR模式

基于Linux的负载均衡集群软件 LVS 全称为Linux Virtual Server,是一款开源的四层(传输层)负载均衡软件 Nginx 支持四层和七层(应用层)负载均衡 HAProxy 和Nginx一样,也可同时支持四层和七层(应用层)负载均衡 基于Linux的高可用集群软件 Keepalived Keepalived是Linux…

STM32 RTC 实时时钟说明

目录 背景 RTC(实时时钟)和后备寄存器 32.768HZ 如何产生1S定时 RTC配置程序 第一次上电RTC配置 第1步、启用备用寄存器外设时钟和PWR外设时钟 第2步、使能RTC和备份寄存器访问 第3步、备份寄存器初始化 第4步、开启LSE 第5步、等待LSE启动后稳定状态 第6步、配置LSE为…

2024年12月电子学会青少年机器人技术等级考试(三级)理论综合真题

202412 青少年等级考试机器人理论真题三级 一、单选题 第 1 题 Arduino UNO/Nano主控板&#xff0c;程序模块如下&#xff0c;该模块运行后&#xff0c;引脚5输出的等效电压为0V&#xff0c;变量i对应的值是&#xff1f;&#xff08; &#xff09; A&#xff1a;0 B&#xff1…

分治中的快速排序(前序遍历)与归并排序(后序遍历)详细对比分析

目录 1. 快速排序&#xff08;前序遍历&#xff09; 核心思想与步骤 关键特性 示例分析 2. 归并排序&#xff08;后序遍历&#xff09; 核心思想与步骤 关键特性 示例分析 3. 对比总结 4. 选择依据与优化策略 5. 实际应用场景 6. 核心差异图示 7. 总结 1. 快速排序…

DeepSeek 助力 Vue 开发:打造丝滑的进度条

前言&#xff1a;哈喽&#xff0c;大家好&#xff0c;今天给大家分享一篇文章&#xff01;并提供具体代码帮助大家深入理解&#xff0c;彻底掌握&#xff01;创作不易&#xff0c;如果能帮助到大家或者给大家一些灵感和启发&#xff0c;欢迎收藏关注哦 &#x1f495; 目录 Deep…

编译和链接【四】链接详解

文章目录 编译和链接【四】链接详解前言系列文章入口符号表和重定位表链接过程分段组装符号决议重定位 编译和链接【四】链接详解 前言 在我大一的时候&#xff0c; 我使用VC6.0对C语言程序进行编译链接和运行 &#xff0c; 然后我接触了VS&#xff0c; Qt creator等众多IDE&…

LeetCode每日精进:876.链表的中间结点

题目链接&#xff1a;876.链表的中间结点 题目描述&#xff1a; 给你单链表的头结点 head &#xff0c;请你找出并返回链表的中间结点。 如果有两个中间结点&#xff0c;则返回第二个中间结点。 示例 1&#xff1a; 输入&#xff1a;head [1,2,3,4,5] 输出&#xff1a;[3,4,5…

数据结构——结构体位域、typedef类型重定义、宏、共用体union、枚举、虚拟内存划分

一、结构体位域 1.1 结构体位域的基础 结构体位域&#xff1a;把结构体字节大小扣到极致的一个类型&#xff0c;以bit单位 格式&#xff1a;struct 位域体名{数据类型 位域名:位域大小;数据类型 位域名:位域大小;...};解析&#xff1a;位域体名&#xff1a;可有可无&#xff…

CZML 格式详解,javascript加载导出CZML文件示例

示例地址&#xff1a;https://dajianshi.blog.csdn.net/article/details/145573994 CZML 格式详解 1. 什么是 CZML&#xff1f; CZML&#xff08;Cesium Zipped Markup Language&#xff09;是一种基于 JSON 的文件格式&#xff0c;用于描述地理空间数据和时间动态场景。它专…

SQL递归技巧

1.读样例 with recursive cet_dpt(id, parent_id, path, org_category, level,depart_name) as (select id ,parent_id,depart_name as path,org_category,1 as level,sd.depart_namefrom isolarerp.sys_depart sdwhere del_flag 0and sd.org_code A09B15union al…

django配置跨域

1、第一种 from django.views.decorators.csrf import csrf_exemptcsrf_exempt第二种 安装 pip install django-cors-headers在配置文件settings.py进入 INSTALLED_APPS [..."corsheaders", # 添加 ]MIDDLEWARE [corsheaders.middleware.CorsMiddleware, # 添加…

设置mysql的主从复制模式

mysql设置主从复制模式似乎很容易&#xff0c;关键在于1&#xff09;主库启用二进制日志&#xff0c;2&#xff09;从库将主库设为主库。另外&#xff0c;主从复制&#xff0c;复制些什么&#xff1f;从我现在获得的还很少的经验来看&#xff0c;复制的内容有表&#xff0c;用户…