書いて覚えるSwift入門

第30回SD読者ならわかるブロックチェーン入門

前号の予告に変えて

前回の記事ではSwiftのSequenceプロトコルを取り上げたうえで、次回はそのSequenceの中でもランダムアクセス可能なCollectionを取り上げる予定でしたが、もう1回ある特殊なSequenceを取り上げることにします。それも、今後のITの世界を一変させる可能性を秘めた、とあるSequenceです。それはSwiftのコードにすれば、

protocol Block {
    associatedtype Signature
    associatedtype Payload
    func isValid(prev:Self)->Bool
}

enum BlockError: Error {
    case Invalid
}

protocol BlockChain : Sequence {
    associatedtype Element:Block
    var last:Element? { get }
    mutating func append(_ block:Element)
throws

}

と表現されるSequenceすなわちブロックチェーンという名のSequenceです。

ブログでも発表したとおり、このたび私、小飼弾は株式会社VALUのリードエンジニアに就任いたしました図1⁠。同社のサービスであるVALUはVAという個人の指標をビットコイン$BTC)で売買する市場を備えたSNSで、その売買手数料が同社の収益源なのですが、それは売上が100%ビットコインだということ。ビットコインあってのVALUなのです。

図1 筆者のVALU
図1 筆者のVALU

そしてそのビットコインは、ブロックチェーン(blockchain)という技術で成り立っています。ビットコインはブロックチェーンの最初にして現時点における最重要のアプリケーションではありますが、ブロックチェーンでできることの氷山の一角に過ぎません。

断言します。ブロックチェーンはWWW以来、最重要のIT(Information Technology)である、と。

本誌の読者であれば、今年中にHTTP(S)やHTMLなみにごく当然のようにわきまえておかねばならない常識になる、と。

と言っても慌てる必要はありません。ブロックチェーンが今後不可欠な基盤技術であることと受け入れられたのはごく最近なのですし、理解と習得に何年もかかるほど難解なものではないのですから。図2のチャートをご覧ください。これは日本国内最大級の交換所、bitFlyer社の2017年08月19日における、ビットコインと日本円の交換レートなのですが、注目していただきたいのは急騰している右上ではなく左下。Nov '16とあります。同社のチャートでさえこれしか歴史がないのです。今から学習しても十分間に合います。

図2 https://bitflyer.jp/ja/bitcoin-chart
図2 https://bitflyer.jp/ja/bitcoin-chart

Welcome to the blockchain!

ブロックチェーンとはいったい何か? 刻々と追記されるデータをP2Pネットワークで安全確実に同期する技術。これだけです。どうやってそれを実現しているかを知る前に、まずは「すでに記録が完了したデータをP2Pネットワークで安全確実に同期する」方法をおさらいしておきましょう。

「すでに記録が完了したデータ」と言えば、ファイル。P2Pと聞いて本誌の読者の皆さんが思い出すのは、WinnyやBitTorrentといった、ファイルを取得するためのP2Pではないでしょうか。誰からもらったのかもわからないファイルが改ざんされていないことを、我々はどう確かめたら良いのでしょう? そのファイルに固有の特徴(signature)を見ていますよね。

たとえばOSのインストーライメージであれば、md5やSHA-1やSHA-256といったチェックサム(checksum)が記載されたファイルが必ず配布ディレクトリに配置されています。なのでubuntu-16.04.3-desktop-amd64.iso[1]のSHA-256ダイジェストが1384ac8f2c2a6479ba2a9cbe90a585618834560c477a699a4a7ebe7b5345ddc1であることを確かめれば、正体不明の人からそれをもらっても間違いなく正しいファイルであることを確認できるわけです。

ファイルであれば、ファイルそのものは信頼できない経路でもらっても、signatureさえ信頼できる経路でもらえばOKですが、それを「終わりなきデータ」で実現するにはどうしたら良いのでしょうか?

適当にデータがたまったら、それをファイルにして、そのファイルの前のファイルのsignatureをわかるようにしておけばいい。これがブロックチェーンの基本的な考えで、基本はそれだけです。この「すでに記録が完了した」データを、⁠ファイル」ではなく「ブロック」と呼称しているだけです。次は前のブロックのhashvalueを署名とする最も簡単なブロックチェーンの実装です。

struct SimpleBlock<D:Hashable> : Block {
    typealias Signature = Int
    typealias Payload = D
    let prevSign:Signature
    let payload:D
    func isValid(prev:SimpleBlock<D>)->Bool {
        return prev.payload.hashValue == self.prevSign
    }
}

struct SimpleBlockChain<D:Hashable> : BlockChain {
typealias Element = SimpleBlock<D>
    var blocks:[Element]
    var last:Element? {
        return blocks.last
    }
    mutating func append(_ block:Element) throws {
        if blocks.isEmpty ¦¦ block.isValid(prev: last!) {
            blocks.append(block)
        } else {
            throw BlockError.Invalid
        }
    }
    func makeIterator() -> AnyIterator<Element> {
        var count = 0
        return AnyIterator {
            if count == self.blocks.count {
                return nil
            } else {
                defer { count += 1 }
                return self.blocks[count]
            }
        }
    }
}

次の処理結果を見てのとおり、直前のブロックのpayloadhashValueが一致しないとappendに失敗します。

extension SimpleBlockChain {
    init() { blocks = [] }
}

var sbc = SimpleBlockChain<String>()

do {
    try sbc.append( // 最初のブロック
      SimpleBlock(prevSign: 0, payload: "Zero")
    )
    try sbc.append( // 次の不正なブロック
      SimpleBlock(prevSign: 0, payload: "1")
    )
} catch {
    print(error)
}
try sbc.append(
    SimpleBlock(  // 次の正しいブロック
       prevSign: 4799450038612711877,
       payload: "one"
    ) 
  )
for b in sbc {
    print(b.payload)
}

しかしこれだと、あるデータの続きを作るだけなら誰でもできてしまうことになります。前にあるデータのsignatureは誰にでも作れてしまうのですから。つまりデータはフォーク(fork)する可能性があるのです。実際ビットコインも今年8月1日にフォークしたのですが、ブロックチェーンが保証するのはその前までのデータであって、その次以降のデータはその限りではないということは、大事なことなので忘れないようにしておいてください。

しかしそれではフォークだらけになって収拾がつかなくなるのは目に見えています。それを防ぐにはどうしたら良いでしょう? ここで紙の世界を見てみましょう。複数のページからなる契約書があるとします。この契約書がひとつながりの契約書であることをどう保証しているか? 全ページに同じ人が署名するのです。実際には各ページにはイニシャル程度の略式の署名をし、最後のページに本署名するのが現在確立されたスタイルですが、要は誰でも勝手に署名できない形で署名してしまえば、紙であろうがブロックであろうが、それがひとつながりのデータであることは保証できるわけです。

中央集権から分散へ

本誌の読者であれば電子署名がすでに枯れた技術であることはご存じかと思います。iOSやAndroidのアプリはすべてストアによって電子署名されていて、アプリを構成するデータがそのストアで配布されたことを保証しています。だからこそアプリストアが成り立つわけですが、だからこそアプリストアは中央集権なのです。アプリに署名できるのはストア主だけなのですから。

これを分散するにはどうしたら良いでしょう?複数の人が署名できるようにするだけならさほど難儀でありません。署名する権限がある人のリストを用意しておき、誰が署名したかをブロックごとに検証していけば良いだけです。しかしこれでも署名者登録が中央集権的にならざるをえません。世界最重要の分散型データベースであるDNSも、ルートサーバはInternicという組織がトップダウンに配布しています。

分散型ネットワークであるインターネットも、このように分散不可能な要素を抱えているのです。これを真の意味で分散可能にできないか? ブロックチェーンであればその根幹である署名プロセスを分散できないか?

Bitcoinのしくみ

そこに颯爽と登場したのが、Satoshi Nakamotoを名乗る1人の天才でした。彼は特権なしで誰でも署名できる一貫性のある方法を論文で提示したのです。

その方法は実にシンプルなものでした。

  • ① 最初に署名した人が正しい署名ということにする
  • ② ただし署名するにはそれなりの労力をかけてもらう
  • ③ その労力に対し代価を支払う(ビットコインで)
  • ④ 署名できなかった人はその署名を検証する

あとは、⁠それなりの労力がかかる」方法さえあればいい。Bitcoinではその方法は次のとおりです。

  • ① 署名元のデータに、32bitのnonceというデータを足す
  • ② それに電子署名する
  • ③ その署名結果、つまり2進法の数値が一定以下であれば正しい署名として認める。それ以外は不正な署名とする

図3はblockchain.infoによる481455番目のbitcoin blockの内訳ですが、右側にHashesという値があります。16進数表示で64桁、つまり256bitの数値ですがこれが署名です。いずれも頭に0がいくつも並んでます。この0が一定個数以下のものだけ、正しい署名と認めることにするのです。

図3 481455番目のbitcoin blockの内訳
図3 481455番目のbitcoin blockの内訳

この署名を得るために、署名者はnonceを変えては署名して、不正ならnonceを変えてまた署名……という作業を延々と繰り返します。この作業のことを業界では「採掘(mining⁠⁠」と呼んでいますが、そうして正しく署名したブロックをP2Pネットワークに流し、ほかのネットワークノードに検証してもらって初めて、そのブロックは正当なブロックとして承認されます。

正しい署名が見つかる確率を難易度(difficulty)と言いますが、ビットコインでは10分に1ブロック増える程度に都度調整されるようになっています。⁠送金に10分」というのはこれが理由です。送金記録がブロックに掲載され、それがチェーンにつながれたとき、その取引は正当なものとなるのです。

そう。送金記録。48万個を超えるブロックの連鎖からなり、今も10分に1つずつ増えていく、過去と未来すべての入出金の歴史。それこそがビットコインの真の姿。その意味ではそれを「台帳」(ledger)ではなく「コイン」という言葉を選んだSatoshi Nakamotoは罪作りではあります。しかし「コイン」という言葉の沿革を見ると、ビットコインという命名はなかなか渋い。中央銀行以上に信用があり得るものといえば金[2]で、金でできた貨幣をコインと呼ぶのですから。

押さえておくべき3ポイント

ここでブロックチェーンに話を戻すと、見てのとおりブロックチェーンとは刻一刻と付け加えられるデータを全員で共有するための技術に過ぎず、どんなデータでも流せることは明らかです。分散署名も署名者を固定すれば不要で、たとえば日銀が電子署名する「日銀チェーン」だってあり得ますし、クローズドな環境ならば電子署名さえ不要で、さらにはログの共有などに用いても何の問題もありません[3]⁠。

とはいえブロックチェーンという言葉がバズるところまで来たのは、何と言っても分散署名の方法をNakamotoがBitcoinとともに提示し、実際にそれを用いた取引が根付いてから。Nakamoto論文の公開は2008年。そこから10年足らずで「ただの思いつき」はビットコインだけでも約7兆円、仮想通貨全体では14兆円もの経済活動をカバーするにいたっています。IPOの代わりの資金調達手段としてICO(Initial Coin Offering)というものも登場しましたし、ブロックチェーンの世界の片隅で暮らし始めた筆者にもブロックチェーンの適応と放散の速度には眩暈(めまい)を禁じえません。

そろそろ紙幅も尽きるのでまとめます。

  1. ブロックチェーンとは刻々と追記されるデータをP2Pネットワークで安全確実に同期する技術
  2. チェーンにブロックを追加するには、追加前のブロックを署名する
  3. Satoshi Nakamotoが提示したのは、誰がブロックを用いて署名してもチェーンが切れない方法。ビットコインはそれを使って入出金記録を記録し続けるためのプロトコル(protocol)

これだけ押さえておけば、ブロックチェーンにはついていけます。読者のあなたの学習チェーンにぜひこの知識をつなげてみてください。

Software Design

本誌最新号をチェック!
Software Design 2022年9月号

2022年8月18日発売
B5判/192ページ
定価1,342円
(本体1,220円+税10%)

  • 第1特集
    MySQL アプリ開発者の必修5科目
    不意なトラブルに困らないためのRDB基礎知識
  • 第2特集
    「知りたい」⁠使いたい」⁠発信したい」をかなえる
    OSSソースコードリーディングのススメ
  • 特別企画
    企業のシステムを支えるOSとエコシステムの全貌
    [特別企画]Red Hat Enterprise Linux 9最新ガイド
  • 短期連載
    今さら聞けないSSH
    [前編]リモートログインとコマンドの実行
  • 短期連載
    MySQLで学ぶ文字コード
    [最終回]文字コードのハマりどころTips集
  • 短期連載
    新生「Ansible」徹底解説
    [4]Playbookの実行環境(基礎編)

おすすめ記事

記事・ニュース一覧