Bitcoin

Bitcoinとは

GitHubリポジトリ: https://github.com/bitcoin

目的

匿名性を自分で選択できつつ, 安全に価値の移転と保存に特化したシステムを構築すること.

特徴

  • 非中央集権
  • 自律分散
  • トラストレス
  • 耐改ざん性
  • オープンソース
  • 匿名性を選択できる
  • 二重支払いができない
  • 払い(価値の保存と移転)に特化したとても堅牢なシステム(チューリング不完全/マルチシグ/HDウォレット/ニーモニック/Base58とか)

技術

  • 電子署名
  • 公開鍵暗号
  • 暗号学的ハッシュ関数
    • 現像計算困難性 (ハッシュ値から元のメッセージを復元できない)
    • 第二現像計算困難性 (同じハッシュ値になる任意のメッセージがない)
    • 衝突安全性 (任意のメッセージのハッシュ値が衝突しない)
  • ネットワーク
    • P2P
    • Proof of Work
  • スタックマシン
    • ブロック
    • スクリプト
    • オペコード
  • マークル木
  • コンセンサスアルゴリズム

プレイヤー

スケーリング方法

  • コンセンサスアルゴリズムを速くする(分散性のために1ブロック生成にわざと10分かけてる)
  • ブロックに含まれるトランザクションを増やす(Block weightが4MB以下/segwit導入により)
  • オフチェーン(Lightning networkなど)
  • サイドチェーン
  • シャーディング
  • Reference: ブロックチェーンとスケーラビリティ

フルノード

フルノードの立て方

フルノードの分布図

マイナーとノードの違い

  • マイナーも1つのノードではあるが, マイナーの主な役割はプルーフオブワーク(PoW)を行い取引をブロックに収納しネットワークに送信すること.
  • マイナー以外のユーザーがノードを立ち上げる主な目的は, 取引が正しくブロックに取り込まれたかを検証しブロックチェーンに追加する.
  • マイナーには新規発行のビットコインの取得という経済的インセンティブがある.
  • ノードを立ち上げるユーザーには, 自身で取引の正当性を検証することができることと, ノードが増えることで非中央集化するネットワークのセキュリティを強化するというインセンティブがある.
  • Reference: ノードの分布状況から紐解く、世界に広がるビットコインのネットワーク

bitcoindとbitcoin-cliの違い

  • bitcoind: Bitcoinの一通りの機能を実装したしたサーバーのこと.
    • Bitcoinネットワーク(P2Pネットワーク)との通信のフル機能
    • ウォレット機能
    • マイニングプール
    • マイニング
    • JSON-RPC APIサーバー
  • bitcoin-cli: JSON-RPCを使って, bitcoindと通信し, 様々な操作を行えるツールのこと.
  • References: Bitcoinウォレットの比較

bitcoindにcurlでアクセス

# getblockinfo
curl --data-binary '{"jsonrpc":"1.0","id":"curltext","method":"getblockchaininfo","params":[]}' -H 'content-type:text/plain;' http://solareenlo:solareenlo@127.0.0.1:8332/ | jq

bitcoin-cliとxargsの使用例

# ブロック高が一番高いブロックの内容を出力する例
bitcoin-cli getbestblockhash | xargs bitcoin-cli getblock
# 最新ブロックのcoinbase txのトランザクションIDを取得する例
bitcoin-cli getblockhash 1 | xargs -IXXX bitcoin-cli getblock XXX 2 | jq ".tx[0].txid"
# 最新ブロックの一番初めのトランザクション内容を表示する例
bitcoin-cli getbestblockhash | xargs bitcoin-cli getblock | jq ".tx[0]" | xargs bitcoin-cli getrawtransaction | xargs bitcoin-cli decoderawtransaction

References: 開発によく使うbitcoin 関連cliツール

bitcoin-cliを使ってUTXOを集める

Blockchainの中身の見方

アドレス

一般的なアドレス生成の流れ

  1. 秘密鍵からECDSAで公開鍵を生成
  • 公開鍵をハッシュ関数SHA-256に通しハッシュ値を得る
  • そのハッシュ値をさらにハッシュ関数RIPEMD-160に通しハッシュ値を得る
  • ハッシュ値の先頭にプレフィックスとして00を加える
  • ハッシュ関数SHA-256に通す
  • もう一度ハッシュ関数SHA-256に通す
  • 4バイトのチェックサムを一番後ろに加える
  • Base58のフォーマットでエンコーディングする

Reference: 秘密鍵から公開鍵そしてアドレスが生成されるまでの流れ【仮想通貨】

一般的なアドレス生成の図

Reference: 秘密鍵から公開鍵とビットコインアドレスを生成する方法

秘密鍵/公開鍵/アドレスの関係

Reference: 公開鍵、秘密鍵、ビットコインアドレスの関係

秘密鍵/WIF/公開鍵/アドレスの関係

Reference: 暗号通貨(Bitcoin, Monacoin)のプロトコルを理解する: 公開鍵と秘密鍵

HDウォレットにおけるアドレス生成の手順

**Reference:** [bips/bip-0032.mediawiki](https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki)

Entropy ( BIP39 , 128bit, 160bit, 192bit, 224bit, 256bitの長さ)

Mnemonic ( BIP39 , 2048(11bit)個の単語群から選んだ、12個, 15個, 18個, 21個, 24個の単語群)

Master Node ( BIP39 , 512bit(=64byte))

左半分: Master Key( BIP32 ), 右半分: Chain Code( BIP32 )
↓ (Master Key + Chain Code)
拡張鍵 ( BIP32 )

HD Wallet ( BIP32 )

アドレス

Entropyのターミナルでの作成方法

# entropyの生成はmacのターミナルで
$ cat /dev/urandom |LC_ALL=C tr -dc 'a-f0-9' | fold -w 64 | head -n 1
# entropyの生成はlinuxの端末で
$ cat /dev/urandom |tr -dc a-f0-9|head -c${1:-64}

アドレスの種類

Reference: Address

プレフィックス

Decimal prefix Hex Example use Leading symbol(s)
0 00 Pubkey hash (P2PKH address) 1
5 05 Script hash (P2SH address) 3
128 80 Private key (WIF, uncompressed pubkey) 5
128 80 Private key (WIF, compressed pubkey) K or L
4 136 178 30 0488B21E BIP32 pubkey xpub
4 136 173 228 0488ADE4 BIP32 private key xprv
111 6F Testnet pubkey hash m or n
196 C4 Testnet script hash 2
239 EF Testnet Private key (WIF, uncompressed pubkey) 9
239 EF Testnet Private key (WIF, compressed pubkey) c
4 53 135 207 043587CF Testnet BIP32 pubkey tpub
4 53 131 148 04358394 Testnet BIP32 private key tprv
Bech32 pubkey hash or script hash bc1
Bech32 testnet pubkey hash or script hash tb1
List of address prefixes

単位

0.00000001 BTC = 1 Satoshi
1 BTC = 100000000 Satoshi

Script

  • TransactionとScriptとLightning Networkについて分かりやすいスライド
  • スクリプトから理解するライトニングネットワーク
  • サトシは後に, 以下の2つの理由でP2PK ではなくP2PKHを使うことを決めた.
  • 楕円曲線暗号(公開鍵や秘密鍵に使われれている暗号)が, 楕円曲線上の離散対数問題を解くために改良されたショアのアルゴリズムによって解かれてしまうから. 簡単に言うとそれが意味するのは, 理論上, 量子コンピューターがそう遠くない未来に公開鍵から秘密鍵を導出できてしまうということ. ビットコインを使うときだけ公開鍵を公開することによって, そういった攻撃を無力化することができる(一度使われたビットコインアドレスを二度と使わない前提だが).
  • ハッシュサイズがより小さくなるので(20バイトになる), 印刷するにも小さくできるしQRコードのような小さい記録媒体に埋め込むことがより簡単になる.
  • Reference: P2PKH (Pay to Public Key Hash)

ScriptSig

ScriptSigはInputにあって, [$ \sf{ScriptSig} \fallingdotseq \sf{Unlock Script}] ScriptSigにはSigとPubKeyがある. そうすることでP2PKHでは, ScriptPubKeyにあるhash化されたPubKeyとScriptSigにあるPubKeyを見比べてTrueを得た後に, さらにScriptSigにあるSigとPubKeyを見比べてTrueを得ることができる.

ScriptPubKey

ScriptPubKeyはOutputにあって, [$ \sf{ScriptPubKey} \fallingdotseq \sf{Lock Script}] Lockしないと誰でもBTCを取り出せてしますから.

P2SHのScriptPubKey

# P2SHのScriptPubKey
OP_HASH160 [20-byte-hash-value] OP_EQUAL

オンラインでBitcoin Scriptの挙動を確認できるサイト

トランザクション

トランザクション生成と検証の仕方が分かりやすいスライド

Segwit

スクリプト構造

# P2WPKH
witness      : <signature> <pubkey>
scriptSig    : (empty)
scriptPubKey : 0 <20-byte SHA160(pubkey)>
               (0x0014{20-byte SHA160(pubkey)})
# P2WSH
witness      : 0 <signature1> <1 <pubkey1> <pubkey2> 2 CHECKMULTISIG>
scriptSig    : (empty)
scriptPubKey : 0 <32-byte sha256(witness script)>
               (0x0020{32-byte sha256(witness script)})

Base32

**Reference:** https://bc-2.jp/materials/0105_Bech32.pdf

Transaction Fee

References