-
Notifications
You must be signed in to change notification settings - Fork 1.4k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #1094 from jasonandjay/btc
docs: ECDSA signature analysis & P2PKH
- Loading branch information
Showing
3 changed files
with
153 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
# 简介 | ||
|
||
[P2PKH(Pay-to-Public-Key-Hash)](../wallet/address.js#L42)是比特币网络中最常用的一种交易类型,设计用来将比特币支付到某个具体的公钥哈希,而不是直接到公钥本身。这种方式提供了更高的安全性和隐私保护。在P2PKH交易中,比特币被发送到一个地址,这个地址实际上是持有者公钥的哈希版本。这种地址通常以数字"1"开头。地址不仅简洁,而且通过哈希公钥,隐藏了公钥的实际内容,增加了隐私保护层。 | ||
|
||
# 工作过程 | ||
|
||
## ScriptPubKey(锁定脚本) | ||
|
||
P2PKH脚本模式包含一个公钥哈希,该哈希和以下操作码共同构成锁定脚本 | ||
|
||
```js | ||
// 模版 | ||
OP_DUP OP_HASH160 <Public Key Hash> OP_EQUALVERIFY OP_CHECKSIG | ||
|
||
OP_DUP // 复制栈顶的元素 | ||
OP_HASH160 // 弹出栈顶元素,计算其SHA-256散列,然后计算RIPEMD-160散列 | ||
OP_PUSHBYTES_20 // 推送20字节到栈顶 | ||
18e1fad25b2983d5dbb2e2b96e3ce756a69b3bc2 // 公钥哈希 | ||
OP_EQUALVERIFY // 比较栈顶元素 | ||
OP_CHECKSIG // 验证数字签名 | ||
|
||
``` | ||
|
||
## ScriptSig(解锁脚本) | ||
|
||
要解锁花费此脚本,上面公钥的所有者需要提供原始公钥以及的有效签名 | ||
|
||
```js | ||
// 模版 | ||
<Singature> <Public Key> | ||
|
||
OP_PUSHBYTES_72 // 推送72字节到栈顶 | ||
3045022100c233c3a8a510e03ad18b0a24694ef00c78101bfd5ac075b8c1037952ce26e91e02205aa5f8f88f29bb4ad5808ebc12abfd26bd791256f367b04c6d955f01f28a772401 // 签名数据 | ||
OP_PUSHBYTES_33 // 推送33字节到栈顶 | ||
03480b6822120e9936b43859d84c380583c3d0292409b21453ae962815090f8117 // 压缩公钥 | ||
``` | ||
|
||
## 执行过程 | ||
|
||
1. 脚本合并,ScriptSig在前ScriptPubKey在后 | ||
|
||
```js | ||
<Singature> <Public Key> OP_DUP OP_HASH160 <Public Key Hash> OP_EQUALVERIFY OP_CHECKSIG | ||
``` | ||
|
||
2. 栈内执行 | ||
|
||
- OP_DUP 从栈里取出公钥,复制并做HASH160推进栈顶 | ||
- OP_EQUALVERIFY 对比上一步的计算结果和Public Key Hash | ||
- OP_CHECKSIG 校验数字签名,如果通过锁定脚本合法可以花费对应UTXO,如果不通过交易失败 | ||
|
||
## 地址生成 | ||
|
||
P2PKH支付方式从公钥生成地址遵循以下详细步骤: | ||
|
||
### 步骤1: 计算公钥哈希 | ||
|
||
1. **计算公钥的SHA-256哈希值**:首先,对公钥进行SHA-256哈希运算。 | ||
2. **计算RIPEMD-160哈希值**:然后,对SHA-256的结果再进行RIPEMD-160哈希运算。这两步哈希运算的结果称为公钥哈希(PKH)。 | ||
|
||
### 步骤2: 添加版本字节 | ||
|
||
- **添加版本字节**:在公钥哈希前添加一个版本字节(比特币主网络的P2PKH地址的版本是0x00, 测试网是0x6f)。这有助于钱包软件识别和处理不同类型的地址。 | ||
|
||
### 步骤3: 计算校验和 | ||
|
||
1. **双重SHA-256哈希**:对带有版本字节的公钥哈希进行两次SHA-256哈希运算。 | ||
2. **取前四个字节**:从双重哈希的结果中取出前四个字节,这部分称为校验和。 | ||
|
||
### 步骤4: 生成地址 | ||
|
||
- **组合和Base58编码**:将版本字节和公钥哈希以及校验和组合在一起,整个结构为: | ||
```js | ||
[version byte][public key hash][checksum] | ||
``` | ||
然后,对整个字节串进行Base58编码,以生成最终的P2PKH地址。 | ||
|
||
### 示例 | ||
|
||
假设有一个公钥,步骤如下: | ||
|
||
1. **公钥**: `04480b6822120e9936b43859d84c380583c3d0292409b21453ae962815090f8117883c2a3fd7571b12f34491809d48467dae4e2f162aef23de91e4532d0fc1e0c5` | ||
2. **SHA-256哈希**:计算结果。 | ||
3. **RIPEMD-160哈希**:计算结果。 | ||
4. **添加版本字节**:`00` + [RIPEMD-160哈希结果]。 | ||
5. **计算校验和**:对上述结果执行两次SHA-256,取前四个字节。 | ||
6. **Base58编码**:将最终字节串转换为Base58编码:13GZvxKVCw1YadDCBJ7rAuerLiYGXLQBVp |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
# BTC地址 | ||
|
||
在比特币系统中,随着技术的发展和用户需求的变化,钱包现在支持多种不同类型的地址格式,每种格式都对应不同的技术标准和特点。这些地址格式包括传统的P2PKH(以1开头),P2SH(以3开头),以及更加现代的SegWit地址(通常以bc1q或bc1p开头)。进行交易时,我们需要为收款者创建一个交易输出,这个输出指定了收款方的地址和交易的金额。 | ||
|
||
# BTC地址到交易完成 | ||
|
||
下面以P2PKH(Pay-to-Public-Key-Hash)为例介绍从比特币收款地址到交易构建的详细步骤: | ||
|
||
1. 收款地址的获取和格式 | ||
收款方提供一个P2PKH类型的比特币地址,这种地址通常以数字1开始,例如 1BvBMSEYstWetqTFn5Au4m4GFg7xJaNVN2。这个地址是经过编码的,通常使用Base58Check编码,其中包含了收款方的公钥哈希(public key hash)。 | ||
|
||
2. Base58Check解码 | ||
当付款方接收到一个比特币地址后,他们会使用Base58Check解码来提取地址中的公钥哈希。Base58Check编码不仅帮助减少字符混淆(移除了容易混淆的字符如0(零)、O(大写字母O)、I(大写字母i)和l(小写字母L)),还内嵌了一个错误检测机制。 | ||
|
||
3. 构建锁定脚本(ScriptPubKey) | ||
解码过程提取出的公钥哈希接着用来构建一个所谓的锁定脚本(ScriptPubKey),这个脚本是交易输出的一部分。对于P2PKH地址,锁定脚本的格式通常如下: | ||
|
||
```js | ||
OP_DUP OP_HASH160 <Public Key Hash> OP_EQUALVERIFY OP_CHECKSIG | ||
``` | ||
|
||
4. 构建交易 | ||
付款方将锁定脚本放置在新的交易输出中,并指定转账金额。这个输出现在会被添加到新的交易中。除此之外,交易还需要包含至少一个输入(来自付款方的一个或多个以前的交易输出),这些输入提供了足够的资金来覆盖转账金额和网络矿工费。 | ||
|
||
5. 签名和广播交易 | ||
一旦交易构建完毕,付款方需要用他们的私钥对交易进行签名,证明他们有权使用指定的输入资金。完成签名后,交易将被广播到比特币网络,网络的矿工们开始验证这个交易的合法性,如果合法,最终将其加入到区块链中,完成资金的转移。 | ||
|
||
# 常见支付方式 | ||
|
||
- [P2PKH](./P2PKH.md) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters