Skip to content

zlabwork/btc-lib

Repository files navigation

BTC Transfer Library

专业级的比特币转账类库,支持完整的 UTXO 管理、多种地址格式、动态手续费估算、多签、Taproot。

🚀 核心特性

基础功能

  • ✅ 指定数量划转
  • ✅ 全部余额划转(自动预留手续费)
  • ✅ 自动找零到指定地址
  • ✅ 第三方项目友好的 API 设计

专业功能

  • 🔐 多种签名方式:P2PKH (Legacy)、P2WPKH (SegWit)、P2TR (Taproot)
  • 🏦 UTXO 智能管理:自动选择最优 UTXO 组合
  • 💰 手续费策略:动态估算、自定义费率、批量优化
  • 🎯 地址格式全支持:Legacy、SegWit、Native SegWit (Bech32)、Taproot (Bech32m)
  • 🔄 RBF 支持:Replace-By-Fee 交易加速
  • 👥 多签地址:支持 M-of-N 多签交易(1-of-2, 2-of-3, 3-of-5 等)
  • 🔑 HD 钱包支持:BIP39 助记词、BIP44 派生路径、多账户管理
  • 🌐 多节点支持:自建节点、第三方 API(Blockstream, Blockchain.com)
  • 🧪 测试网支持:Mainnet/Testnet 无缝切换
  • 📊 交易追踪:查询交易状态、确认数、区块高度
  • 🛡️ 安全特性:交易签名前验证、余额检查、双花检测
  • 📝 完整日志:操作审计、错误追踪
  • 🚀 Taproot 支持:Schnorr 签名、更小交易、更强隐私

📦 安装

go get github.com/zlabwork/btc-lib

🔧 快速开始

生成各种格式地址

package main

import (
    "fmt"
    "github.com/btcsuite/btcd/btcec/v2"
    "github.com/btcsuite/btcd/btcutil"
    "github.com/btcsuite/btcd/chaincfg"
    btc "github.com/zlabwork/btc-lib/pkg"
)

func main() {
    network := btc.TestNet
    params := &chaincfg.TestNet3Params

    // --- 单签地址 ---
    privKey, _ := btcec.NewPrivateKey()
    wif, _ := btcutil.NewWIF(privKey, params, true)
    
    parsedKey, _, _ := btc.ParsePrivateKey(wif.String(), network)
    
    legacyAddr, _ := btc.GenerateAddress(parsedKey, "legacy", network)
    fmt.Printf("P2PKH (Legacy) : %s\n", legacyAddr) // 1... / m... / n...
    
    segwitAddr, _ := btc.GenerateAddress(parsedKey, "segwit", network)
    fmt.Printf("P2WPKH (SegWit) : %s\n", segwitAddr) // bc1q... / tb1q...

    taprootAddr, _ := btc.GenerateTaprootAddress(parsedKey, network)
    fmt.Printf("P2TR (Taproot) : %s\n", taprootAddr) // bc1p... / tb1p...

    // --- 多签地址 (2-of-3) ---
    priv2, _ := btcec.NewPrivateKey()
    wif2, _ := btcutil.NewWIF(priv2, params, true)
    priv3, _ := btcec.NewPrivateKey()
    wif3, _ := btcutil.NewWIF(priv3, params, true)
    
    wifs := []string{wif.String(), wif2.String(), wif3.String()}

    p2shAddr, _, _, _ := btc.CreateMultiSigAddressFromWIFs(2, wifs, network)
    fmt.Printf("P2SH (传统多签) : %s\n", p2shAddr) // 3... / 2...

    p2wshAddr, _, _, _ := btc.CreateSegWitMultiSigAddressFromWIFs(2, wifs, network)
    fmt.Printf("P2WSH (SegWit 多签) : %s\n", p2wshAddr) // bc1q... (64 chars)
}

基础转账

package main

import (
    "fmt"
    "log"
    btc "github.com/zlabwork/btc-lib/pkg"
)

func main() {
    // 1. 创建客户端
    client := btc.NewClient(&btc.Config{
        Network:  btc.MainNet,
        NodeURL:  "https://blockstream.info/api",
        LogLevel: btc.InfoLevel,
    })

    // 2. 执行转账
    result, err := client.Transfer(&btc.TransferRequest{
        FromPrivKey:   "你的WIF私钥",
        ToAddress:     "bc1qxy2kgdygjrsqtzq2n0yrf2493p83kkfjhx0wlh",
        Amount:        50000, // 50,000 聪
        FeeRate:       10,    // 10 sat/vB
        ChangeAddress: "",    // 空则自动使用发送地址
    })

    if err != nil {
        log.Fatal(err)
    }

    fmt.Printf("✅ 转账成功!\n")
    fmt.Printf("TxID: %s\n", result.TxID)
    fmt.Printf("手续费: %d sats\n", result.Fee)
}

多签转账(2-of-3)

// 1. 创建 2-of-3 多签地址
wifs := []string{"key1", "key2", "key3"}
multiSigAddr, redeemScript, _, err := btc.CreateMultiSigAddressFromWIFs(2, wifs, btc.MainNet)

// 2. 从多签地址转账(使用其中 2 个私钥)
result, err := client.TransferFromMultiSig(&btc.MultiSigTransferRequest{
    FromAddress:   multiSigAddr,
    PrivKeys:      []string{"key1", "key2"}, // 只需要 2 个
    RedeemScript:  redeemScript,
    ToAddress:     "bc1q...",
    Amount:        100000,
    FeeRate:       10,
})

Taproot 转账

// 1. 生成 Taproot 地址
privKey, _, _ := btc.ParsePrivateKey("your_wif", btc.MainNet)
taprootAddr, _ := btc.GenerateTaprootAddress(privKey, btc.MainNet)
// 地址格式: bc1p... (使用 Schnorr 签名)

// 2. 从 Taproot 地址转账
result, err := client.TransferFromTaproot(&btc.TaprootTransferRequest{
    FromPrivKey: "your_wif",
    ToAddress:   "bc1q...",
    Amount:      200000,
    FeeRate:     5, // Taproot 手续费更低
})

HD 钱包(BIP39/BIP44)

// 1. 生成 12 词助记词
mnemonic, _ := btc.GenerateMnemonic(btc.Strength128)
// 例如: "abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about"

// 2. 从助记词创建 HD 钱包
wallet, _ := btc.NewHDWallet(mnemonic, "", btc.MainNet)

// 3. 派生第一个接收地址 (m/44'/0'/0'/0/0)
path := btc.GetDefaultDerivationPath(btc.MainNet, 0, 0)
address, privKey, _ := wallet.DeriveAddress(path, "segwit")

// 4. 批量生成 10 个接收地址
addresses, _ := wallet.GetReceivingAddresses(0, 10, "segwit")

// 5. 生成找零地址 (m/44'/0'/0'/1/0)
changeAddrs, _ := wallet.GetChangeAddresses(0, 5, "segwit")

// 6. 恢复钱包
restoredWallet, _ := btc.RestoreWalletFromMnemonic(mnemonic, btc.MainNet)

批量转账

// 一次交易发送给多个地址(节省手续费)
result, err := client.BatchTransfer(&btc.BatchTransferRequest{
    FromPrivKey: "your_wif",
    Outputs: []btc.Output{
        {Address: "bc1q...", Amount: 10000},
        {Address: "bc1q...", Amount: 20000},
        {Address: "bc1q...", Amount: 30000},
    },
    FeeRate: 8,
})

📖 API 文档

配置选项

type Config struct {
    Network      NetworkType    // MainNet, TestNet
    NodeURL      string         // Bitcoin 节点 RPC 或 API URL
    NodeUser     string         // RPC 用户名(可选)
    NodePassword string         // RPC 密码(可选)
    LogLevel     LogLevel       // Debug, Info, Warn, Error
    Timeout      time.Duration  // 请求超时
}

转账请求

type TransferRequest struct {
    FromPrivKey   string      // WIF 格式私钥
    ToAddress     string      // 接收地址
    Amount        int64       // 转账金额(satoshi),0 表示全部转账
    FeeRate       int64       // 手续费率(sat/vB),0 则自动估算
    FeeStrategy   FeeStrategy // Fast, Normal, Slow
    ChangeAddress string      // 找零地址
    UTXOs         []UTXO      // 指定 UTXO(可选)
    RBF           bool        // 启用 Replace-By-Fee
    Memo          string      // OP_RETURN 备注(可选)
}

多签配置

// 创建 M-of-N 多签地址
func CreateMultiSigAddress(m int, pubKeys []*btcec.PublicKey, network NetworkType) (string, []byte, error)

// 从 WIF 私钥列表创建多签地址
func CreateMultiSigAddressFromWIFs(m int, wifs []string, network NetworkType) (string, []byte, []*btcec.PublicKey, error)

// 多签转账请求
type MultiSigTransferRequest struct {
    FromAddress   string   // 多签地址
    PrivKeys      []string // 至少 M 个私钥
    RedeemScript  []byte   // 赎回脚本
    ToAddress     string   // 接收地址
    Amount        int64    // 转账金额
    FeeRate       int64    // 手续费率
}

Taproot API

// 生成 Taproot 地址
func GenerateTaprootAddress(privKey *btcec.PrivateKey, network NetworkType) (string, error)

// Taproot 转账请求
type TaprootTransferRequest struct {
    FromPrivKey   string // WIF 私钥
    ToAddress     string // 接收地址
    Amount        int64  // 转账金额
    FeeRate       int64  // 手续费率
}

// 判断是否为 Taproot 地址
func IsTaprootAddress(address string, network NetworkType) bool

HD 钱包 API (BIP39/BIP44)

// 生成助记词
func GenerateMnemonic(strength MnemonicStrength) (string, error)
// strength: Strength128 (12 词) 或 Strength256 (24 词)

// 验证助记词
func ValidateMnemonic(mnemonic string) bool

// 创建 HD 钱包
func NewHDWallet(mnemonic string, passphrase string, network NetworkType) (*HDWallet, error)

// HD 钱包方法
type HDWallet struct {
    // 派生单个地址
    DeriveAddress(path *DerivationPath, addressType string) (string, *btcec.PrivateKey, error)
    
    // 批量生成接收地址
    GetReceivingAddresses(account uint32, count uint32, addressType string) ([]AddressInfo, error)
    
    // 批量生成找零地址
    GetChangeAddresses(account uint32, count uint32, addressType string) ([]AddressInfo, error)
    
    // 获取主公钥 (xpub/tpub)
    GetMasterPublicKey() (string, error)
}

// 派生路径
type DerivationPath struct {
    Purpose      uint32 // 44' (BIP44)
    CoinType     uint32 // 0' (Bitcoin), 1' (Testnet)
    Account      uint32 // 账户索引
    Change       uint32 // 0 (接收), 1 (找零)
    AddressIndex uint32 // 地址索引
}

// 恢复钱包
func RestoreWalletFromMnemonic(mnemonic string, network NetworkType) (*HDWallet, error)

// 导出私钥为 WIF
func ExportPrivateKeyWIF(privKey *btcec.PrivateKey, network NetworkType) (string, error)

工具函数

// 查询余额
balance, _ := client.GetBalance("bc1q...")

// 查询 UTXO
utxos, _ := client.GetUTXOs("bc1q...")

// 查询交易状态
tx, _ := client.GetTransaction("txid")

// 估算手续费
feeEstimate, _ := client.EstimateFee()
// feeEstimate.Fast   - 快速确认
// feeEstimate.Normal - 正常确认
// feeEstimate.Slow   - 慢速确认

// 地址验证
isValid := btc.ValidateAddress("bc1q...", btc.MainNet)

// 地址类型识别
addrType, _ := btc.GetAddressType("bc1q...", btc.MainNet)
// P2PKH, P2SH, P2WPKH, P2WSH, P2TR

// 判断 SegWit 地址
isSegWit := btc.IsSegWitAddress("bc1q...", btc.MainNet)

📂 项目结构

btc-lib/
├── pkg/          # 核心库
│   ├── types.go           # 类型定义
│   ├── client.go          # 客户端入口
│   ├── transaction.go     # 交易构建与签名(P2PKH/P2WPKH)
│   ├── multisig.go        # 多签功能
│   ├── taproot.go         # Taproot 支持
│   ├── wallet.go          # 钱包功能(私钥/地址)
│   ├── address.go         # 地址工具
│   ├── node.go            # 节点交互(Blockstream API)
│   └── logger.go          # 日志系统
├── examples/              # 使用示例
│   ├── basic_transfer.go      # 基础转账
│   ├── batch_transfer.go      # 批量转账
│   ├── multisig_transfer.go   # 多签转账
│   ├── taproot_transfer.go    # Taproot 转账
│   └── advanced_features.go   # 高级功能
├── tests/                 # 单元测试
│   ├── transaction_test.go
│   ├── wallet_test.go
│   ├── multisig_test.go
│   └── taproot_test.go
└── README.md

🔥 特性对比

特性 Legacy (P2PKH) SegWit (P2WPKH) Taproot (P2TR)
地址前缀 1... bc1q... bc1p...
签名算法 ECDSA ECDSA Schnorr
交易大小 ~230 bytes ~140 vBytes ~110 vBytes
手续费
隐私性
多签可见性 可见 可见 不可见
推荐使用 ❌ 已过时 ✅ 推荐 ✅✅ 强烈推荐

🎯 使用场景

1. 单签钱包

// 普通转账 - 推荐使用 SegWit 或 Taproot
client.Transfer(&btc.TransferRequest{
    FromPrivKey: "wif_key",
    ToAddress:   "bc1q...",
    Amount:      100000,
})

2. 多签钱包(公司财务)

// 2-of-3 多签:需要 3 个管理者中的任意 2 个批准
multiSigAddr, redeemScript, _ := btc.CreateMultiSigAddressFromWIFs(
    2, []string{"ceo_key", "cfo_key", "cto_key"}, btc.MainNet)

// 转账时使用其中 2 个私钥
client.TransferFromMultiSig(&btc.MultiSigTransferRequest{
    PrivKeys: []string{"ceo_key", "cfo_key"},
    // ...
})

3. 批量发放(节省手续费)

// 给多个员工发工资 - 一次交易完成
client.BatchTransfer(&btc.BatchTransferRequest{
    Outputs: []btc.Output{
        {Address: "employee1_addr", Amount: 500000},
        {Address: "employee2_addr", Amount: 600000},
        {Address: "employee3_addr", Amount: 700000},
    },
})

4. Taproot(最新技术)

// 使用 Taproot - 更小、更快、更隐私
client.TransferFromTaproot(&btc.TaprootTransferRequest{
    FromPrivKey: "wif_key",
    ToAddress:   "bc1p...",
    Amount:      1000000,
})

5. HD 钱包(BIP39/BIP44)

// 生成助记词并创建 HD 钱包
mnemonic, _ := btc.GenerateMnemonic(btc.Strength128) // 12 词
wallet, _ := btc.NewHDWallet(mnemonic, "", btc.MainNet)

// 批量生成 100 个接收地址(用户充值地址)
addresses, _ := wallet.GetReceivingAddresses(0, 100, "segwit")

// 只需备份一个助记词,恢复所有地址
restoredWallet, _ := btc.RestoreWalletFromMnemonic(mnemonic, btc.MainNet)

🧪 运行测试

# 安装依赖
make install

# 运行所有测试
make test

# 带覆盖率
make test-cover

# 运行示例
make example-basic
make example-batch
make example-multisig
make example-taproot

🛡️ 安全建议

  1. 永远不要硬编码私钥 - 使用环境变量或密钥管理系统
  2. 生产环境使用冷钱包签名 - 本库支持离线签名
  3. 测试先在 Testnet - 确保逻辑正确
  4. 监控交易状态 - 等待足够确认数(建议 6 confirmations)
  5. 备份助记词和私钥 - 私钥丢失 = 资产永久丢失
  6. 小额测试 - 生产环境前先用小金额测试完整流程
  7. 验证接收地址 - 仔细核对接收地址,交易不可撤销
  8. 使用 RBF - 启用 RBF 可以在交易拥堵时加速

🚨 已知限制

  • ✅ P2PKH (Legacy) 签名 - 完整支持
  • ✅ P2WPKH (SegWit) 签名 - 完整支持
  • ✅ P2SH 多签 - 完整支持
  • ✅ P2TR (Taproot) 签名 - 完整支持
  • ✅ BIP39 助记词 - 完整支持
  • ✅ BIP44 HD 钱包 - 完整支持
  • ✅ P2WSH SegWit 多签 - 完整支持
  • ⚠️ 硬件钱包集成 - 未实现(可扩展)

📝 Changelog

v1.1.0 (2026-03-25)

  • ✅ 完整的 P2PKH/P2WPKH 签名实现
  • ✅ 多签地址创建与转账(M-of-N)
  • ✅ Taproot 支持(Schnorr 签名)
  • ✅ BIP39 助记词支持(12/24 词)
  • ✅ BIP44 HD 钱包(多账户、多地址派生)
  • ✅ 批量转账功能
  • ✅ 动态手续费估算
  • ✅ RBF 交易加速
  • ✅ 完整单元测试
  • ✅ Blockstream API 集成

📚 参考资料

📄 License

MIT License - 详见 LICENSE 文件

🤝 贡献

欢迎提交 Issue 和 Pull Request!

📧 联系方式

About

No description, website, or topics provided.

Resources

Contributing

Stars

Watchers

Forks

Packages

 
 
 

Contributors