跳至主要內容
基礎概念 入門

地址

Address

又稱:比特幣地址、Bitcoin Address

比特幣地址是接收比特幣的識別碼,類似於銀行帳號或電子郵件地址。地址由公鑰經過雜湊處理產生,可以安全地公開分享給任何想要付款給你的人。

地址的本質

地址 vs 公鑰

為什麼不直接用公鑰?

公鑰:
- 長度:33 或 65 bytes
- 暴露後有量子計算風險
- 難以人工核對

地址:
- 長度:26-62 字元
- 額外一層雜湊保護
- 包含校驗碼防止輸入錯誤
- 人類可讀格式

地址的用途

功能說明
收款告訴付款方把錢發到哪裡
標識 UTXO鎖定在這個「條件」下的資金
驗證支付確認支付到正確的地方

地址類型完整指南

1. P2PKH(Legacy)

特徵:
- 前綴:1
- 長度:26-34 字元
- 編碼:Base58Check
- 啟用:2009(創世)

範例:
1BvBMSEYstWetqTFn5Au4m4GFg7xJaNVN2

生成過程:
私鑰
  → ECDSA 乘法
公鑰(33 bytes 壓縮)
  → SHA-256
  → RIPEMD-160
公鑰雜湊(20 bytes)
  → 添加版本前綴(0x00)
  → SHA-256 × 2 取前 4 bytes 作為校驗碼
  → Base58 編碼
地址

scriptPubKey:
OP_DUP OP_HASH160 <pubKeyHash> OP_EQUALVERIFY OP_CHECKSIG

2. P2SH(Script Hash)

特徵:
- 前綴:3
- 長度:34 字元
- 編碼:Base58Check
- 啟用:2012(BIP-16)

範例:
3J98t1WpEZ73CNmQviecrnyiWrnqRhWNLy

用途:
- 多重簽名
- 包裝 SegWit(兼容舊錢包)
- 複雜腳本

scriptPubKey:
OP_HASH160 <scriptHash> OP_EQUAL

3. P2WPKH(Native SegWit)

特徵:
- 前綴:bc1q
- 長度:42 字元
- 編碼:Bech32
- 啟用:2017(BIP-141/173)

範例:
bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4

優勢:
- 手續費比 Legacy 低約 38%
- 更好的錯誤檢測
- 全小寫,易於輸入
- 支援二維碼

scriptPubKey:
OP_0 <20-byte pubKeyHash>

4. P2WSH(SegWit Script Hash)

特徵:
- 前綴:bc1q
- 長度:62 字元(比 P2WPKH 長)
- 編碼:Bech32
- 啟用:2017(BIP-141)

範例:
bc1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3qccfmv3

用途:
- SegWit 原生多簽
- 複雜腳本

scriptPubKey:
OP_0 <32-byte scriptHash>

5. P2TR(Taproot)

特徵:
- 前綴:bc1p
- 長度:62 字元
- 編碼:Bech32m
- 啟用:2021(BIP-341)

範例:
bc1p5d7rjq7g6rdk2yhzks9smlaqtedr4dekq08ge8ztwac72sfr9rusxg3297

優勢:
- 更好的隱私(所有交易看起來相同)
- Schnorr 簽名
- 更高效的多簽
- 支援複雜合約

scriptPubKey:
OP_1 <32-byte tweaked-pubkey>

地址格式比較

視覺比較

類型前綴長度範例開頭
P2PKH126-341BvBM…
P2SH3343J98t…
P2SH-P2WPKH3343CKX2…
P2WPKHbc1q42bc1qw5…
P2WSHbc1q62bc1qrp3…
P2TRbc1p62bc1p5d7…

手續費比較

以 1 輸入 2 輸出交易為例:

類型vsize相對成本
P2PKH~226 vB100%
P2SH-P2WPKH~134 vB59%
P2WPKH~110 vB49%
P2TR~111 vB49%

功能比較

特性P2PKHP2SHP2WPKHP2TR
年份2009201220172021
手續費最高較高
錯誤檢測基本基本優秀優秀
隱私
智能合約有限基本基本進階
推薦使用⚠️

編碼格式

Base58Check

用於:P2PKH、P2SH

字符集(58 字元):
123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz

排除的字元:
- 0(零)和 O(大寫 o):易混淆
- I(大寫 i)和 l(小寫 L):易混淆

校驗碼:
- SHA256(SHA256(data)) 的前 4 bytes
- 附加在數據末尾

Bech32

用於:P2WPKH、P2WSH(SegWit v0)

字符集(32 字元):
qpzry9x8gf2tvdw0s3jn54khce6mua7l

特點:
- 全小寫
- 排除易混淆字元:1, b, i, o
- 更強的錯誤檢測(BCH 碼)
- 可檢測最多 4 個錯誤

結構:
bc1q + witness_program + checksum
hrp  + separator + data + checksum

hrp(Human Readable Part):
- 主網:bc
- 測試網:tb

Bech32m

用於:P2TR(SegWit v1+)

與 Bech32 的區別:
- 校驗碼常數不同
- 修復了 Bech32 的一個缺陷
- 防止 v0 和 v1 地址混淆

結構:
bc1p + tweaked_pubkey + checksum

地址生成詳解

P2WPKH 地址生成

const bitcoin = require('bitcoinjs-lib');
const ecc = require('tiny-secp256k1');
const { BIP32Factory } = require('bip32');

const bip32 = BIP32Factory(ecc);

// 從私鑰生成 P2WPKH 地址
function generateP2WPKHAddress(privateKey) {
  // 1. 私鑰 → 公鑰
  const keyPair = ECPair.fromPrivateKey(privateKey);
  const publicKey = keyPair.publicKey; // 33 bytes 壓縮

  // 2. 公鑰 → 地址
  const { address } = bitcoin.payments.p2wpkh({
    pubkey: publicKey,
    network: bitcoin.networks.bitcoin,
  });

  return address; // bc1q...
}

P2TR 地址生成

// Taproot 地址生成
function generateP2TRAddress(privateKey) {
  const keyPair = ECPair.fromPrivateKey(privateKey);

  // 內部公鑰(x-only,32 bytes)
  const internalPubkey = keyPair.publicKey.slice(1, 33);

  const { address } = bitcoin.payments.p2tr({
    internalPubkey: internalPubkey,
    network: bitcoin.networks.bitcoin,
  });

  return address; // bc1p...
}

地址驗證

校驗碼驗證

每種地址格式都有內建校驗碼:

Base58Check 驗證:
1. 解碼 Base58
2. 分離數據和校驗碼(最後 4 bytes)
3. 計算數據的 SHA256(SHA256())
4. 比較前 4 bytes

Bech32/Bech32m 驗證:
1. 檢查 HRP(bc/tb)
2. 檢查分隔符(1)
3. 計算 BCH 校驗碼
4. 驗證校驗碼

驗證程式碼

const bitcoin = require('bitcoinjs-lib');

function validateAddress(address) {
  try {
    // 嘗試解析地址
    const decoded = bitcoin.address.toOutputScript(address, bitcoin.networks.bitcoin);
    return {
      valid: true,
      type: getAddressType(decoded),
      network: 'mainnet',
    };
  } catch (e) {
    // 嘗試測試網
    try {
      bitcoin.address.toOutputScript(address, bitcoin.networks.testnet);
      return { valid: true, network: 'testnet' };
    } catch (e) {
      return { valid: false, error: e.message };
    }
  }
}

function getAddressType(script) {
  if (script.length === 25) return 'P2PKH';
  if (script.length === 23) return 'P2SH';
  if (script.length === 22) return 'P2WPKH';
  if (script.length === 34 && script[0] === 0x00) return 'P2WSH';
  if (script.length === 34 && script[0] === 0x51) return 'P2TR';
  return 'Unknown';
}

地址使用最佳實踐

地址重用的風險

為什麼不應該重用地址?

隱私風險:
- 所有交易可被關聯
- 收支記錄公開可查
- 第三方可追蹤你的資金流動

安全風險:
- 每次簽名都暴露公鑰
- 量子計算可能的風險
- 增加攻擊面

正確做法:
✓ 每次收款使用新地址
✓ HD 錢包自動派生新地址
✓ 使用自動找零功能

驗證地址的習慣

發送前必做:

1. 檢查前幾個字元
   - 主網:1, 3, bc1q, bc1p
   - 測試網:m, n, 2, tb1

2. 核對地址(至少 8 字元)
   - 開頭 4 字元
   - 結尾 4 字元

3. 小額測試
   - 先發送小額確認
   - 確認到帳後再發送大額

4. 防範剪貼板劫持
   - 複製後再次核對
   - 使用二維碼更安全

地址管理

標籤系統:
- 為每個地址添加標籤
- 記錄來源和用途
- 便於稅務和追蹤

範例標籤:
"2024-01 薪水"
"交易所提款 - Coinbase"
"給 Alice 的借款"

特殊地址類型

多簽地址

P2SH 多簽(3 開頭):
- 傳統格式
- 例:3QJmV3qfvL9SuYo34YihAf3sRCW3qSinyC

P2WSH 多簽(bc1q 長地址):
- SegWit 原生
- 更低手續費

辨識方式:
- P2WSH 地址比 P2WPKH 長(62 vs 42 字元)

時間鎖地址

包含時間條件的地址:
- 在特定時間/區塊高度後才能花費
- 用於遺產規劃、定期儲蓄

實現方式:
- P2SH 或 P2WSH 包裝時間鎖腳本

OP_RETURN 輸出

不是真正的「地址」:
- 不可花費的輸出
- 用於在區塊鏈上嵌入數據
- 最多 80 bytes 數據

用途:
- 時間戳服務
- 協議標記
- Ordinals 銘文

測試網地址

格式對照

類型主網測試網/Signet
P2PKH1…m… 或 n…
P2SH3…2…
P2WPKHbc1q…tb1q…
P2TRbc1p…tb1p…

測試網水龍頭

獲取測試幣:
- testnet: coinfaucet.eu/en/btc-testnet
- signet: signetfaucet.com
- regtest: 自己挖礦

注意:
- 測試網地址無法收取主網比特幣
- 發送前確認網路類型

常見問題

發送到錯誤類型的地址?

發送到錯誤地址類型:
- 交易會成功
- 收款方可以花費
- 只是可能需要不同錢包恢復

發送到錯誤網路(主網→測試網):
- 地址校驗會失敗
- 錢包會拒絕發送

地址看起來很奇怪?

檢查清單:
1. 確認網路(主網/測試網)
2. 確認地址類型
3. 確認沒有多餘空格
4. 確認大小寫正確(Legacy 區分大小寫)

Bech32 地址:
- 全小寫是正確的
- 某些錢包顯示大寫僅為易讀

為什麼我的錢包不支援 bc1p?

可能原因:
- 錢包版本過舊
- 不支援 Taproot

解決方案:
- 更新錢包到最新版本
- 換用支援 Taproot 的錢包
- 暫時使用 bc1q 地址
已複製到剪貼簿