比特币中的P2WPKH地址(Pay-to-Witness-Public-Key-Hash)是SegregatedWitness(隔离见证,简称SegWit)的一种地址类型。生成比特币的NativeSegWit地址(也称为bech32地址)
比特币中的P2WPKH地址(Pay-to-Witness-Public-Key-Hash)是Segregated Witness(隔离见证,简称SegWit)的一种地址类型。生成比特币的 Native SegWit 地址(也称为 bech32 地址),SegWit是对比特币协议的一项更新,旨在改善交易吞吐量、降低交易费用并提高安全性和灵活性。P2WPKH地址通常以“bc1”开头,且直接嵌入见证数据,不再占用区块的常规部分,从而减小交易大小和费用。
Native SegWit (P2WPKH) 是比特币的一种地址类型,它支持隔离见证(Segregated Witness),优化了交易签名和存储效率。生成 Native SegWit 地址的过程可以概括为以下步骤:
首先,你需要生成一个椭圆曲线(Elliptic Curve)密钥对,这是基于 secp256k1 算法的。这个过程包括生成一个私钥和一个对应的公钥。(也可以通过公钥直接生成地址,这种方式可以验证函数是否正确)
0x02
或 0x03
)。使用 SHA256 和 RIPEMD160 哈希算法生成公钥的哈希值。
Native SegWit 地址的 Witness Program 由版本号和公钥哈希组成:
0
(表示 P2WPKH)。所以 Witness Program 是 0x00
后跟 20 字节的公钥哈希。
使用 Bech32 编码将 Witness Program 转换为人类可读的比特币地址格式。Bech32 编码包括两部分:
bc
,测试网是 tb
。经过 Bech32 编码后的字符串就是 Native SegWit 地址,它通常以 bc1
开头(主网)或 tb1
开头(测试网)。
import { createHash } from 'crypto';
import { bech32 } from 'bech32';
// 计算 SHA256 + RIPEMD160
function hash160(data: Buffer): Buffer {
// Step 1: SHA-256
const sha256Hash = createHash('sha256').update(data).digest();
// Step 2: RIPEMD-160
const ripemd160Hash = createHash('ripemd160').update(sha256Hash).digest();
return ripemd160Hash;
}
export function generateNativeSegWitAddress(publicKeyHex: string): string {
// Step 1: 解码 16 进制公钥
const pubKeyBytes = Buffer.from(publicKeyHex, 'hex');
// Step 2: 计算公钥哈希
const pubKeyHash = hash160(pubKeyBytes);
// Step 3: Bech32 编码
const witnessVersion = 0x00; // P2WPKH 的版本号为 0
// 将 witness version 转换为 Bech32 words
const words = [witnessVersion, ...bech32.toWords(pubKeyHash)];
// Bech32 编码
const address = bech32.encode('bc', words);
// 返回结果
return address;
}
package utils
import (
"crypto/sha256"
"encoding/hex"
"fmt"
"github.com/btcsuite/btcutil/bech32"
"golang.org/x/crypto/ripemd160"
)
// Hash160 计算 SHA256 + RIPEMD160
func hash160(data []byte) []byte {
sha256Hash := sha256.Sum256(data)
ripemd160Hasher := ripemd160.New()
ripemd160Hasher.Write(sha256Hash[:])
return ripemd160Hasher.Sum(nil)
}
func GenerateNativeSegWitAddress(publicKeyHex string) (string, error) {
// Step 1: 解码 16 进制公钥
pubKeyBytes, err := hex.DecodeString(publicKeyHex)
if err != nil {
return "", fmt.Errorf("failed to decode public key: %v", err)
}
// Step 2: 计算公钥哈希
pubKeyHash := hash160(pubKeyBytes)
// Step 3: 准备 SegWit 地址编码数据
witnessVersion := byte(0x00) // P2WPKH 的版本号为 0
// Step 4: 使用 bech32 库进行编码
data, err := bech32.ConvertBits(pubKeyHash, 8, 5, true) // 将 8-bit 转换为 5-bit
if err != nil {
return "", fmt.Errorf("failed to convert bits: %v", err)
}
// 将版本号和转换后的数据合并
combinedData := append([]byte{witnessVersion}, data...)
// Bech32 编码
address, err := bech32.Encode("bc", combinedData)
if err != nil {
return "", fmt.Errorf("failed to encode Bech32 address: %v", err)
}
// 返回 Bech32 编码的地址
return address, nil
}
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!