イメージとしては、DNSシードが複数のノードIPを持っていて、シードから取得すると、ノードにアクセスしてハンドシェイクって流れだ。
こんな感じ。

さて、これをどーやってコーディングしていきましょうか。。。
随机应变 ABCD: Always Be Coding and … : хороший
イメージとしては、DNSシードが複数のノードIPを持っていて、シードから取得すると、ノードにアクセスしてハンドシェイクって流れだ。
こんな感じ。

さて、これをどーやってコーディングしていきましょうか。。。
富士通の帳票ソフトウェアではありません。
Bitcoin Improvement Proposal
https://github.com/bitcoin/bips
ソフトフォークとハードフォークでプロセスが異なる
Open Asset Protocolは、仮想通貨以外のアセットを発行・取引する
https://github.com/OpenAssets/open-assets-protocol
bitcoin white paper
https://bitcoin.org/files/bitcoin-paper/bitcoin_jp.pdf
どうなってんだこれ。。
ビットコインのプロトコルに対応するノードはフルノードと呼ばれる全取引データを保持するノードとSPV(Simplified Payment Vertification)と呼ばれるブロックヘッダと自分に関連するデータのみを保持する軽量ノードがある
Bitcoin Coreはフルノード
ブロックのヘッダのみをダウンロードし、必要に応じてフルノードにトランザクションを要求するクライアントでSPVノードと呼ぶ
■ネットワークの発見
最初はDNSシードに問い合わせにいく
– seed.bitcoin.sipa.be
– denseed.bitcoin.dashjr.org
– eed.bitcoinstats.com
– seed.bitcoin.jonasschnelli.ch
DNSシードに問い合わせると、新しい接続を受け入れられるフルノードのIPアドレスが1つ以上返ってくる
vagrant@vagrant-ubuntu-trusty-64:~/bitcoin$ dig seed.bitcoin.sipa.be
; <<>> DiG 9.9.5-3ubuntu0.19-Ubuntu <<>> seed.bitcoin.sipa.be
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 34073
;; flags: qr rd ra; QUERY: 1, ANSWER: 25, AUTHORITY: 0, ADDITIONAL: 1
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 512
;; QUESTION SECTION:
;seed.bitcoin.sipa.be. IN A
;; ANSWER SECTION:
seed.bitcoin.sipa.be. 3599 IN A 104.248.20.174
seed.bitcoin.sipa.be. 3599 IN A 79.124.17.204
seed.bitcoin.sipa.be. 3599 IN A 5.135.186.15
seed.bitcoin.sipa.be. 3599 IN A 104.171.172.17
seed.bitcoin.sipa.be. 3599 IN A 94.130.207.23
seed.bitcoin.sipa.be. 3599 IN A 138.201.56.109
seed.bitcoin.sipa.be. 3599 IN A 73.255.112.134
seed.bitcoin.sipa.be. 3599 IN A 93.115.89.76
seed.bitcoin.sipa.be. 3599 IN A 108.11.187.129
seed.bitcoin.sipa.be. 3599 IN A 116.203.136.157
seed.bitcoin.sipa.be. 3599 IN A 15.164.169.200
seed.bitcoin.sipa.be. 3599 IN A 47.74.245.182
seed.bitcoin.sipa.be. 3599 IN A 74.98.242.97
seed.bitcoin.sipa.be. 3599 IN A 212.170.100.71
seed.bitcoin.sipa.be. 3599 IN A 59.110.18.37
seed.bitcoin.sipa.be. 3599 IN A 193.30.123.209
seed.bitcoin.sipa.be. 3599 IN A 217.125.246.37
seed.bitcoin.sipa.be. 3599 IN A 185.2.101.192
seed.bitcoin.sipa.be. 3599 IN A 94.26.190.7
seed.bitcoin.sipa.be. 3599 IN A 123.134.246.100
seed.bitcoin.sipa.be. 3599 IN A 78.47.168.239
seed.bitcoin.sipa.be. 3599 IN A 23.175.0.212
seed.bitcoin.sipa.be. 3599 IN A 5.2.194.97
seed.bitcoin.sipa.be. 3599 IN A 91.178.131.108
seed.bitcoin.sipa.be. 3599 IN A 173.212.207.249
;; Query time: 271 msec
;; SERVER: 10.0.2.3#53(10.0.2.3)
;; WHEN: Thu Oct 31 15:16:59 UTC 2019
;; MSG SIZE rcvd: 449
他のノードとの接続はディスク上のDBに保存する
プロトコルバージョンのサポート
vagrant@vagrant-ubuntu-trusty-64:~/bitcoin$ bitcoin-cli getnetworkinfo
{
"version": 170100,
"subversion": "/Satoshi:0.17.1/",
"protocolversion": 70015,
"localservices": "000000000000040d",
"localrelay": true,
"timeoffset": 0,
"networkactive": true,
"connections": 3,
"networks": [
{
"name": "ipv4",
"limited": false,
"reachable": true,
"proxy": "",
"proxy_randomize_credentials": false
},
{
"name": "ipv6",
"limited": false,
"reachable": true,
"proxy": "",
"proxy_randomize_credentials": false
},
{
"name": "onion",
"limited": true,
"reachable": false,
"proxy": "",
"proxy_randomize_credentials": false
}
],
"relayfee": 0.00001000,
"incrementalfee": 0.00001000,
"localaddresses": [
],
"warnings": ""
}
コマンドがversionとverackのメッセージを使ってハンドシェイクを行う
相手のノードのバージョンとuser agentが表示され、ハンドシェイクが完了
ブロックチェーンの同期が終わったあとは、ブロードキャストされたブロックを受診してブロックチェーンを更新
支払い形式によって、スクリプトの設定方式が複数存在
– ScriptPubKey
def self.to_address_script(address) hash160 = Bitcoin.hash160_from_address(address) case Bitcoin.address_type(address) when :hash160; to_hash160_script(hash160) when :p2sh; to_p2sh_script(hash160) end end
– ScriptSig
UTXOを使用するには複数の署名が必要になる
m-of-nマルチシグはn人のうちm人が署名すればできる
ScriptPubKeyにスクリプトのハッシュを設定することで単純化したものがP2SH
ハッシュを用いてトランザクションに含まれるデータ量を少なくすることで取引手数料を低く抑える
ロックタイム(OP_CLTV, OP_CSV)
特定のUTXOを使用したトランザクションを設定したブロック高またはUNIXタイムまでブロックに含まれないよう制限をかけることができる
トランザクションはインプット、アウトプット、その他トランザクションに関わる情報を含んでいる
version 4byte 32bit符号なし整数
tx_in_count 1-9byte 可変長整数 インプットのリストに含まれるアイテム数
tx_in 可変 TxIn インプットのリスト
tx_out_count 1-9byte 可変長整数 アウトプットリストに含まれるアイテム数
tx_out 可変 TxOut アウトプットリスト
locktime 4byte 32bit符号なし整数 ブロックに取り込まれる値を制御
インプットの構成
hash 32byte char[32] 全てのビットが0
index 4byte 32bit符号なし整数 値は0xffffffff
coinbase data bytes 可変 可変長整数 コインベースデータのバイト数 2~100
coinbase data 可変 char[] 任意のデータ
sequence 4 32bit符号なし整数 値は0xffffffff
ビットコインではスクリプト言語を利用して電子署名と署名の検証を行なっている
アウトプットのscriptpubkeyには電子署名を検証する命令、インプットのscriptsigには電子署名をスクリプト言語で記述する
電子署名はUTXOの持ち主であることを証明する。署名には秘密鍵を使用
トランザクション -> sha256 -> sha256 -> signature hash -> ecdsa署名 -> signature -> signature -> トランザクション インプット0
トランザクション作成の工程
– インプットにセットするUTXOの準備
– トランザクション全体の作成
– インプットの作成
– アウトプットの作成
– 署名
– ブロードキャスト
ブロックチェーンの仕様の修正はソフトフォークとハードフォークがある。ソフトフォークは古いブロックの仕様と互換性がある仕様の修正。ハードフォークは大きな仕様の変更。マイナーがフォークを採用するかどうかにかかっている
ブロック構造
4バイト: Block Size: ブロックのデータサイズ
80バイト: Block Header: ブロックヘッダ
1〜9バイト: Transaction Counter: ブロックに含まれるトランザクション数
可変長: Transactions: ブロックに含まれるトランザクションのリスト
ブロックの識別子はブロックハッシュとブロック高がある
getchaintipsで先端がわかる
vagrant@vagrant-ubuntu-trusty-64:~/bitcoin$ bitcoin-cli getchaintips
[
{
“height”: 0,
“hash”: “000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f”,
“branchlen”: 0,
“status”: “active”
}
]
マイニング処理
当初の設計ではnonceフィールドの値を順次変更しながらsha-256によるハッシュ値の計算を求め、そのハッシュ値がブロックヘッダのdifficulty targetフィールドで定められた難易度ターゲットよりも小さい数値であれば成功
現在は、Thash/sec, PHash/sec, EHash/sec
新規ブロックの作成と同時にマイナーが作成するコインベーストランザクションの領域を利用
コインベーストランザクションをextraNonceとして利用している
hash char[32] 32byte
index uint32_t 4byte
script bytes compactSize unit
height script
coinbase script None
sequence uint32_2 4byte
マイニング難易度はdifficulty target
target = 係数部*2**(8*(指数部-3))
def target(difficulty_target) exponent=difficulty_target[0..1].hex coefficient=difficulty_target[2..7].hex (coefficient*2**(8*(exponent-3))) end
取引手数料の設定
vagrant@vagrant-ubuntu-trusty-64:~/bitcoin$ bitcoin-cli settxfee 0.00001
true
bitcoin-cli sendfrom <送信元アカウント> <送信先ビットコインアドレス> <送信金額>
トランザクション内容の確認
vagrant@vagrant-ubuntu-trusty-64:~/bitcoin$ bitcoin-cli gettransaction 01307080d1961631b0da844024d8c842bd805dac38bfadb9ce5a771b6a55691a
トランザクションの一覧
vagrant@vagrant-ubuntu-trusty-64:~/bitcoin$ bitcoin-cli listtransactions
支払い請求のURI形式の標準がBIP0021として定義されている
walletの秘密鍵が漏洩すると、資産が盗まれてしまう
→ これってつまり、リミックスもwalletの秘密鍵が盗まれたって事??でも秘密鍵は暗号化していたと会見で言っていたみたいだが。。そういえば、suicaとか電子マネーの上限が決まっているのも、盗難の懸念を考慮してなのかもしれませんね。
オンライン状態をホットストレージ、オフラインをコールドストレージ
秘密鍵はコールドストレージに保管する
ルートシードとマスター秘密鍵
walletのホットストレージ、コールドストレージを挟んだ鍵の設計は非常に複雑だな。。。
リミックスの場合は、ホットウォレットの秘密鍵が全部盗まれ解読されたんかいな。
でも普通、秘密鍵のストレージには外部からアクセスできないように、ファイヤーウォール、ip制御、token管理とかするよね。
Bitcoin Coreで自分のwalletに新しい公開鍵暗号の鍵のペアを作成する
vagrant@vagrant-ubuntu-trusty-64:~/bitcoin$ bitcoind -daemon
Bitcoin server starting
vagrant@vagrant-ubuntu-trusty-64:~/bitcoin$ bitcoin-cli getnewaddress
39Gydphv6RaWwmx3bwEbGihtvXdXWXnobW
walletの秘密鍵の暗号化
vagrant@vagrant-ubuntu-trusty-64:~/bitcoin$ bitcoin-cli encryptwallet password
wallet encrypted; Bitcoin server stopping, restart to run with encrypted wallet. The keypool has been flushed and a new HD seed was generated (if you are using HD). You need to make a new backup.
vagrant@vagrant-ubuntu-trusty-64:~/bitcoin$ bitcoind -daemon
Bitcoin server starting
U01 testnet Faucet https://bitcoinfaucet.uo1.net/

あれ、rpc errorってなってる??

transactionがpendingになっているので、Proof of workがまだって理解でOK?
vagrant@vagrant-ubuntu-trusty-64:~/bitcoin$ bitcoin-cli getbalance
0.00000000
vagrant@vagrant-ubuntu-trusty-64:~/bitcoin$ bitcoin-cli listunspent
[
]
bitcoin coreを動かすと、大分具体的になるね。
require 'bitcoin'
require 'net/http'
require 'json'
Bitcoin.network = :testnet3
RPCUSER =
RPCPASSWORD =
HOST = "localhost"
PORT=18332
def bitcoinRPC(method, param)
http = Net::HTTP.new(HOST, PORT)
request = Net::HTTP::Post.new('/')
request.basic_auth(RPCUSER,RPCPASSWORD)
request.content_type = 'application/json'
request.body = {method: method, params: param, id: 'jsonrpc'}.to_json
JSON.parse(http.request(request).body)["result"]
end
ビットコインの送金は原理的には送金先の公開鍵があればできる
ビットコインで実際に送金先を表す固有名はビットコインアドレス
公開鍵と1対1に対応している
ビットコインアドレスは、チェックサム、プレフィックス、base58エンコーディングの利用を行なっている
0x04 公開鍵x 256ビット 公開鍵y 256ビット
↓ チェックサム
1バイト ペイロード 20バイト(160バイト) 4バイト
↓ base58 エンコーディング
ビットコインアドレス アルファベット26-35文字
base58エンコーディングは1,l,0,o,+,/,=を使わない
プレフィックス
ビットコインアドレスの先頭1バイトはバージョン・種別を表す
0x00(mainnet), 0x6F(testnet), 0x05(mainnet), 0xC4(testnet)
チェックサム
SHA256(SHA256(プレフィックス + 512ビット公開鍵))
暗号学では、一度しか使わないランダムな数値の事をnonceと呼ぶ
メッセージにnonceを追加した上で、そのハッシュ値を計算し、メッセージとハッシュ値を公開した場合、nonceを知っている者だけしかハッシュ値を計算できない
ビットコインのマイニングは、nonceを変更しながらブロックのデータのハッシュ値を繰り返し計算する
ターゲットよりも小さいハッシュ値を最初に得たものが勝利者となる
ハッシュチェーンの一つにマークル木がある
SHA-256とRIPEMD-160をハッシュ関数として標準利用、SHA-1の衝突耐性は失われている
暗号鍵と公開鍵の作成
require 'ecdsa' require 'securerandom' group = ECDSA::Group::Secp256k1 n = group.order private_key = 1 + SecureRandom.random_number(n-1) # print private_key pubKey = group.generator.multiply_by_scalar(private_key) print pubKey.x print pubKey.y
vagrant@vagrant-ubuntu-trusty-64:~/bitcoin$ ruby main.rb
7200274859625909218305600661424454855533433802141920888525182327364340449554183445379063984485161576009152500901248299335294365713023890298728510086562018