はじめに
Rubyにはランダムなダミーデータを生成してくれる、fakerというGemがあります。
テストデータとして、既に利用している方も多いかと思います。
例えば、これだけでランダムな名前が自動生成できちゃいます。
(デフォルトはlocaleがenなので外人さんの名前)
require 'faker'
Faker::Name.name
# => "Christophe Bartell"
ビットコインアドレスも自動生成できる
fakerのGitHubを見ていたら偶然、Blockchainというカテゴリを発見。
気になったので内部を拝見すると、どうやら以下のアドレスを自動生成できるようです。
- bitcoin
- ethereum
- tezos(なぜw)
そしてGitHubを見る限り、このbitcoinはlocalesのymlファイルを参照しているわけはなく、それぞれRubyのロジックでランダムな値を生成していることが分かります。
ビットコインアドレスの生成手順
補足として、ビットコインアドレスの生成手順をざっくり纏めると、概ね以下の通りです。
だいたいの雰囲気が分かればとりあえずOKです。
- 公開鍵をSHA256とRIPEMID160で二重ハッシュ化する、これをPayloadと呼ぶ。
- Payload先頭にversion prefixを付与する
- 上記の値をSHA256で2回ハッシュ化し、そこから先頭の4バイトを取得して最後尾に付与する
- 上記の値をBase 58エンコードする
これでビットコインアドレスの完成です。
fakerのコードを覗いてみる
上記の手順を念頭にGitHubのコードを覗いてみます。
コード量がそれほど多くないのでコピペします。
# frozen_string_literal: true
require 'digest'
require 'securerandom'
module Faker
class Blockchain
class Bitcoin < Base
class << self
PROTOCOL_VERSIONS = {
main: 0,
testnet: 111
}.freeze
def address
address_for(:main)
end
def testnet_address
address_for(:testnet)
end
protected
def address_for(network)
version = PROTOCOL_VERSIONS.fetch(network)
packed = version.chr + Faker::Config.random.bytes(20)
checksum = Digest::SHA2.digest(Digest::SHA2.digest(packed))[0..3]
Faker::Base58.encode(packed + checksum)
end
end
end
end
end
def address_forがビットコインアドレスを生成している処理です。
Faker::Config.random.bytes(20)が、手順1のPayloadを想定していると思われます。
その後の処理も読み解くと、fakerはそれなりにビットコインアドレスの生成手順に沿って値を生成していることが分かります。
実際は公開鍵のハッシュ値を参照してるわけではないので、それっぽいアドレスですがビットコインの送受信はできないはずです。
さいごに
余談ですが、Blockchain以外でも偶然「Japanese Media」というカテゴリを発見しました。
内容を見ると、
- dragon_ball
- one_piece
- sword_art_online(なぜw)
今時点で、この3種が用意されてました。
ソードアートオンラインは議論を呼びそうですが、これもコミッターの特権ということで。
dragon_ballだと、キャラの名前だけがランダムに取得できるようです。
Faker::JapaneseMedia::DragonBall.character
# => "Goku"
名前が定義されたymlはlocales/en配下にあるので、localeがenの場合のみ利用できると思われます(試してない)。
そしてワンピースだと、キャラの名前以外にもいろいろな値が自動生成できるようです。
(ドラゴンボールとはえらい違いだ)
Faker::JapaneseMedia::OnePiece.character #=> "Monkey D. Luffy"
Faker::JapaneseMedia::OnePiece.sea #=> "East Blue"
Faker::JapaneseMedia::OnePiece.island #=> "Laftel"
Faker::JapaneseMedia::OnePiece.location #=> "Foosha Village"
Faker::JapaneseMedia::OnePiece.quote #=> "ONE PIECE IS REAL!"
Faker::JapaneseMedia::OnePiece.akuma_no_mi #=> "Gomu Gomu no Mi"
それにしてもこのfakerの使い道がよく分かりませんね。
完全にネタな気がしますが、こうして日本の文化が採用されることを誇りに思いましょうw
以上、読んで頂きありがとうございました。