Blockchain – DECODE https://decode.red/blog data decode, decoder or decoded ... design of code Mon, 15 Dec 2025 06:15:00 +0000 ja hourly 1 https://wordpress.org/?v=4.7.29 Hierarchical Deterministic Wallets ../../../202209101492/ Sat, 10 Sep 2022 00:37:48 +0000 ../../../?p=1492 暗号資産の取引をする際に必要な財布を作成するとき、ニーモニックコードというものを使います。
12文字からなる単語の並びで、これをもとにウォレットを表すアドレスを生成します。
下記BitlifeCoinの記事を書いているとき、ウォレットのアドレスが同じニーモニックコードから生成しているにもかかわらずアドレスが一致しなかったことから、Hierarchical Deterministic Pathというものがあることを知りました。
(一つのキーから階層的にアドレスを決定するしくみ)
http://bitlife.me/bc/2022/08/18/

m/44’/60’/0’/0/{account_index}
このような文字列で表せれ、最後のaccount_indexによって複数のアドレスを生成できます。

こちらのサイトにとても詳しく書かれています。
https://techblog.recochoku.jp/8227

このサイトにあるコードで実際にBitlifeCoinの環境のニーモニックから生成されるアドレスが正しいか試してみました。(ニーモニックはカレントディレクトにある.secretファイルに記載)

環境) WSL / Windows 11
インストール

pip install hdwallet

from hdwallet import HDWallet
from hdwallet.symbols import ETH
from pprint import pprint

mnemonic = ''
hd_wallet_account = HDWallet(symbol=ETH).from_mnemonic(mnemonic=mnemonic).from_path(path="m/44'/60'/0'/0/1")

hd_wallet_account_info = hd_wallet_account.dumps()
pprint(hd_wallet_account_info)

PATHは、コードではaccount_indexは1となっています。これを0から順に変えてgoerliの環境の複数のアドレスが正しいか確認したところ一致しました。

あとニーモニックを作成するわかりやすいコードが下記にありましたので、それを動かしてみました。
https://qiita.com/yamaguchi3/items/2c216eee5593ee0f66db

const fs = require('fs');
const crypto = require('crypto');
const words = fs.readFileSync('english.txt').toString().trim().split('\n');
const ent = Buffer.from('7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f', 'hex');
const checksum = crypto.createHash('sha256').update(ent).digest().slice(0, ent.length/4);
const data = Buffer.concat([ent, checksum]);
let bin = '';
for(let d of data) {
    bin += ('00000000' + d.toString(2)).slice(-8);
}

let mnemonic = [];
for(var i=0; i<3*ent.length/4; i++) {
    var idx = parseInt(bin.slice(11*i, 11*(i+1)), 2);
    mnemonic.push(words[idx]);
}
console.log(mnemonic.join(' '));

https://github.com/bitcoin/bips/blob/master/bip-0039/english.txt
ここから取得するenglish.txtには、2048の英単語が書かれており、この中からニーモニックにつかわれる単語が選ばれるようです。
最初にウォレットを作ったとき、たった12文字の並び替えだけで衝突しないアドレスが生成できるのか、と思いましたが2048の候補から選んだうえ並び変えているのですね。
ブロックチェーン界隈では、このようないろいろなしくみが考えられていてとても興味深いです。

]]>
Proof of Work ../../../202201041398/ Tue, 04 Jan 2022 10:03:25 +0000 ../../../?p=1398 ブロックチェーンにはネットワークを安定に維持するしくみが多くあり、技術的にとても興味深い題材ばかりです。

過去に書いた、ビットコイン論文ついての記事

Block Chain

その中でマイニングと呼ばれるしくみはとても秀逸にできています。

参考書籍) 「ビットコインとブロックチェーン(Mastering Bitcoin)」(NTT出版)

ここではProof-of-Workとよばれるハッシュ計算を実際に動かしてみました。
マイナーが多数いようと少数だろうと約10分で新しいブロックが作り出せるように、計算にかかる難易度をコントロールしています。
Difficulty Targetと呼ばれる値よりも小さいハッシュ値がでるようにnonceを変えながらトライし、見つけたら正解という単純なものですが、このTarget値が1bit変わるだけで、劇的に計算量が変化します。
これをPythonで実装されたサンプルを出力を見やすくして実行してみました。

オリジナル) https://github.com/bitcoinbook/bitcoinbook/blob/develop/code/proof-of-work-example.py

#!/usr/bin/env python
# example of proof-of-work algorithm

import hashlib
import time

try:
    long        # Python 2
    xrange
except NameError:
    long = int  # Python 3
    xrange = range

max_nonce = 2 ** 32  # 4 billion

def proof_of_work(header, difficulty_bits):
    target = 2 ** (256 - difficulty_bits)

    for nonce in xrange(max_nonce):
        hash_result = hashlib.sha256((str(header) + str(nonce)).encode()).hexdigest()

        # check if this is a valid result, equal to or below the target
        if long(hash_result, 16) <= target:
            print("Nonce:  %d" % nonce)
            print("Hash:   %s" % hash_result)
            print("Target: {:064X}".format(target))
            return (hash_result, nonce)

    print("Failed after %d (max_nonce) tries" % nonce)
    return nonce


if __name__ == '__main__':
    nonce = 0
    hash_result = ''

    # difficulty from 0 to 31 bits
    for difficulty_bits in xrange(32):
        print("Difficulty: %d bits" % difficulty_bits)

        # checkpoint the current time
        start_time = time.time()

        # make a new block which includes the hash from the previous block
        # we fake a block of transactions - just a string
        new_block = 'test block with transactions' + hash_result

        # find a valid nonce for the new block
        (hash_result, nonce) = proof_of_work(new_block, difficulty_bits)

        # checkpoint how long it took to find a result
        end_time = time.time()

        elapsed_time = end_time - start_time
        print("Elapsed Time:  %.4f seconds" % elapsed_time)

        if elapsed_time > 0:
            # estimate the hashes per second
            hash_power = float(long(nonce) / elapsed_time)
            print("Hashing Power: %ld hashes per second" % hash_power)

        print("")

% python proof-of-work-example.py
Difficulty: 0 bits
Nonce:  0
Hash:   ff8253ed10b5f719d52a709a66af8cd5e2054f702e675af4ca0cae70f0988634
Target: 10000000000000000000000000000000000000000000000000000000000000000
Elapsed Time:  0.0005 seconds
Hashing Power: 0 hashes per second

Difficulty: 1 bits
Nonce:  0
Hash:   22c608547e239faf5c353e7ebd204042760b93891d1d0be9ab488d36c73c077b
Target: 8000000000000000000000000000000000000000000000000000000000000000
Elapsed Time:  0.0000 seconds
Hashing Power: 0 hashes per second

Difficulty: 2 bits
Nonce:  2
Hash:   0635f41cdb98c6e73516f84fc88da19a13a3bac6298dbfc0df5170bac93ba4dd
Target: 4000000000000000000000000000000000000000000000000000000000000000
Elapsed Time:  0.0000 seconds
Hashing Power: 95325 hashes per second

Difficulty: 3 bits
Nonce:  9
Hash:   1c1c105e65b47142f028a8f93ddf3dabb9260491bc64474738133ce5256cb3c1
Target: 2000000000000000000000000000000000000000000000000000000000000000
Elapsed Time:  0.0000 seconds
Hashing Power: 224694 hashes per second

Difficulty: 4 bits
Nonce:  25
Hash:   0f7becfd3bcd1a82e06663c97176add89e7cae0268de46f94e7e11bc3863e148
Target: 1000000000000000000000000000000000000000000000000000000000000000
Elapsed Time:  0.0001 seconds
Hashing Power: 284166 hashes per second

Difficulty: 5 bits
Nonce:  36
Hash:   029ae6e5004302a120630adcbb808452346ab1cf0b94c5189ba8bac1d47e7903
Target: 0800000000000000000000000000000000000000000000000000000000000000
Elapsed Time:  0.0001 seconds
Hashing Power: 294912 hashes per second

Difficulty: 6 bits
Nonce:  0
Hash:   0083214fa878cea749bd07bd77e92b311be876dd72f3d4924d5ae4ead54febe5
Target: 0400000000000000000000000000000000000000000000000000000000000000
Elapsed Time:  0.0000 seconds
Hashing Power: 0 hashes per second

Difficulty: 7 bits
Nonce:  26
Hash:   00f7abab177613afc42270e3f5f79ffddd694093030663b32fe26ce2a377a993
Target: 0200000000000000000000000000000000000000000000000000000000000000
Elapsed Time:  0.0001 seconds
Hashing Power: 286225 hashes per second

Difficulty: 8 bits
Nonce:  33
Hash:   0055c56d412e6ab765048f1b8e7fce3b2553435c765c2899ee1bd3124d056098
Target: 0100000000000000000000000000000000000000000000000000000000000000
Elapsed Time:  0.0001 seconds
Hashing Power: 234199 hashes per second

Difficulty: 9 bits
Nonce:  2
Hash:   0025a3e3e764ad05f7945eb65d2a21445eded2209a2cd0e26fa8571bd886b0da
Target: 0080000000000000000000000000000000000000000000000000000000000000
Elapsed Time:  0.0000 seconds
Hashing Power: 104857 hashes per second

Difficulty: 10 bits
Nonce:  1514
Hash:   002a67dc2d861c93843e6dfdb0402f4fed2e87c8c30408f016ac83521e8f091b
Target: 0040000000000000000000000000000000000000000000000000000000000000
Elapsed Time:  0.0046 seconds
Hashing Power: 330566 hashes per second

Difficulty: 11 bits
Nonce:  856
Hash:   0014739d631bf69324d51dfa4ebcd28b03d09e6285d76fc9dc8b7c1e8ad1bf47
Target: 0020000000000000000000000000000000000000000000000000000000000000
Elapsed Time:  0.0026 seconds
Hashing Power: 329236 hashes per second

Difficulty: 12 bits
Nonce:  2933
Hash:   00034d0888fb1cc74a4ee823eae4b71d8949e453da89f24caf3088b557f241c2
Target: 0010000000000000000000000000000000000000000000000000000000000000
Elapsed Time:  0.0091 seconds
Hashing Power: 321988 hashes per second

Difficulty: 13 bits
Nonce:  2142
Hash:   00014006170118b30d97b81e4a824357d416866b469dfc56d16db31e5486f5a0
Target: 0008000000000000000000000000000000000000000000000000000000000000
Elapsed Time:  0.0066 seconds
Hashing Power: 325090 hashes per second

Difficulty: 14 bits
Nonce:  8955
Hash:   0003295d9c3908df0275e074cd820af49a3e5975c487014a23fd7ba5fb98635b
Target: 0004000000000000000000000000000000000000000000000000000000000000
Elapsed Time:  0.0313 seconds
Hashing Power: 286101 hashes per second

Difficulty: 15 bits
Nonce:  32930
Hash:   00009a09fa6f72af0861650e655cf8901b33cf37614ddc0fcfa230294ee22988
Target: 0002000000000000000000000000000000000000000000000000000000000000
Elapsed Time:  0.1012 seconds
Hashing Power: 325253 hashes per second

Difficulty: 16 bits
Nonce:  285299
Hash:   00009d85ce6e17b625bc50caafc7a42eab41d108a177cbfce39c4045bee69fd8
Target: 0001000000000000000000000000000000000000000000000000000000000000
Elapsed Time:  0.8588 seconds
Hashing Power: 332214 hashes per second

Difficulty: 17 bits
Nonce:  10460
Hash:   000012726c26b999bb05e81322379a9ed9ecf08bd85347c752a913ec5e6942e6
Target: 0000800000000000000000000000000000000000000000000000000000000000
Elapsed Time:  0.0309 seconds
Hashing Power: 338817 hashes per second

Difficulty: 18 bits
Nonce:  11980
Hash:   000020b111acbfe28ac4e68aa267154b12cb224bbf49f2c56db346f039b21395
Target: 0000400000000000000000000000000000000000000000000000000000000000
Elapsed Time:  0.0389 seconds
Hashing Power: 307621 hashes per second

Difficulty: 19 bits
Nonce:  573192
Hash:   00001cce66856179a3feed94420d126a9dbddfa8830fc41b7fc5d36fdbf03ba0
Target: 0000200000000000000000000000000000000000000000000000000000000000
Elapsed Time:  1.7196 seconds
Hashing Power: 333336 hashes per second

Difficulty: 20 bits
Nonce:  237723
Hash:   000005720acd8c7207cbf495e85733f196feb1e3692405bea0ee864104039350
Target: 0000100000000000000000000000000000000000000000000000000000000000
Elapsed Time:  0.7161 seconds
Hashing Power: 331977 hashes per second

Difficulty: 21 bits
Nonce:  687438
Hash:   000003a6eeee97491a9183e4c57458172edb6f9466377bf44afbd74e410f6eef
Target: 0000080000000000000000000000000000000000000000000000000000000000
Elapsed Time:  2.0783 seconds
Hashing Power: 330763 hashes per second

Difficulty: 22 bits
Nonce:  1759164
Hash:   0000008bb8f0e731f0496b8e530da984e85fb3cd2bd81882fe8ba3610b6cefc3
Target: 0000040000000000000000000000000000000000000000000000000000000000
Elapsed Time:  5.2847 seconds
Hashing Power: 332877 hashes per second

Difficulty: 23 bits
Nonce:  14214729
Hash:   000001408cf12dbd20fcba6372a223e098d58786c6ff93488a9f74f5df4df0a3
Target: 0000020000000000000000000000000000000000000000000000000000000000
Elapsed Time:  42.8228 seconds
Hashing Power: 331942 hashes per second

Difficulty: 24 bits
Nonce:  24586379
Hash:   0000002c3d6b370fccd699708d1b7cb4a94388595171366b944d68b2acce8b95
Target: 0000010000000000000000000000000000000000000000000000000000000000
Elapsed Time:  73.9447 seconds
Hashing Power: 332496 hashes per second

Difficulty: 25 bits
Nonce:  8570323
Hash:   00000009ecccb8289d6f94b3e861804e41c4530b0f879534597ff4d09aaa446d
Target: 0000008000000000000000000000000000000000000000000000000000000000
Elapsed Time:  25.7419 seconds
Hashing Power: 332932 hashes per second

Difficulty: 26 bits
Nonce:  84561291
Hash:   0000001f0ea21e676b6dde5ad429b9d131a9f2b000802ab2f169cbca22b1e21a
Target: 0000004000000000000000000000000000000000000000000000000000000000
Elapsed Time:  254.2355 seconds
Hashing Power: 332610 hashes per second

Difficulty: 27 bits
Nonce:  10256713
Hash:   00000006dc70d218bafb37c31f3166e49b1b0d28f3fea500431ecb22e954c99e
Target: 0000002000000000000000000000000000000000000000000000000000000000
Elapsed Time:  30.8556 seconds
Hashing Power: 332409 hashes per second

Difficulty: 28 bits
Nonce:  139905000
Hash:   0000000e4da88b53f70b2c5fc142500f0633e6407a4793462c54e6e704a687f3
Target: 0000001000000000000000000000000000000000000000000000000000000000
Elapsed Time:  420.3545 seconds
Hashing Power: 332826 hashes per second

Difficulty: 29 bits
Nonce:  61508685
Hash:   0000000135c4a4e6c78c12e956ea970e5c6b2f586bedcde2cf8507e2b08b87eb
Target: 0000000800000000000000000000000000000000000000000000000000000000
Elapsed Time:  184.9352 seconds
Hashing Power: 332595 hashes per second

Difficulty: 30 bits
Nonce:  590689799
Hash:   0000000339323dfd8e68d9460ba4311efa5da8393aa986ff2c00e7f4a54e9761
Target: 0000000400000000000000000000000000000000000000000000000000000000
Elapsed Time:  1950.6458 seconds
Hashing Power: 302817 hashes per second

Targetの数が小さくなると急激にハッシュを見つけ出す時間がかかるようになります。
下記は過去からの実際のBitcoinのハッシュレートと難易度の変化を表したグラフです。
170m TH/sということは、THのmはメガ? 170 EH/s ってすごい計算量ということがわかります。
(上記は、古いPCで約30万/s)

TH/s(テラハッシュ) 1秒間に1,000,000,000,000(1兆)回
PH/s(ペタハッシュ) 1秒間に1,000,000,000,000,000(1000兆)回
EH/s(エクサハッシュ) 1秒間に1,000,000,000,000,000,000(100京)回

https://www.blockchain.com/charts/hash-rate より

https://www.blockchain.com/charts/difficulty より

ハッシュレートと難易度が同じ動きをしていることがわかります。このように動的に計算負荷をコントールしているのですね。
昔は、PCのCPUでマイニングし、次にGPU、そしてFPGAにASICとハードウェアも変遷しているようですが、マイニングがいかにコストがかかるよく表しています。
それにしても何もかもオープンなんだと、あらためて感じました。

ブロックチェーンはBitcoinに限らす社会に影響を大きく与える技術だけに、そのしくみを知りたいという気持ちが強くなってきました。上記参考書籍はとても詳しくわかりやすく書かれており、おすすめです。
今年はブロックチェーンテクノロジーの探求に力を入れていきたいと思います。

専用ブログ開始しました!

http://bitlife.me/bc/

]]>
Block Chain ../../../20160409562/ Sat, 09 Apr 2016 07:57:16 +0000 ../../../?p=562 ビットコインの論文の中に、悪意あるノードと善意のノードがプロックチェーンの伸ばし合いの競争をしたとき、善意のノードが僅かでも多ければブロックチェーンを乗っ取れる確率がかなり低い、ということを説明したコードがありますが、これを実際に実行して試してみました。

ビットコイン論文
http://bitcoin.peryaudo.org/vendor/bitcoin.pdf

#include <stdio.h>
#include <math.h>
double AttackerSuccessProbability(double q, int z)
{
       double p = 1.0 - q;
       double lambda = z * (q / p);
       double sum = 1.0;
       int i, k;
       for (k = 0; k <= z; k++)
       {
           double poisson = exp(-lambda);
           for (i = 1; i <= k; i++)
               poisson *= lambda / i;
           sum -= poisson * (1 - pow(q / p, z - k));
       }
       return sum;
}
int main()
{
        printf("   ");
        for(double q=0.1 ; q <= 0.55 ; q += 0.05){
                printf("q = %1.2f  ", q);
        }
        printf("\n");
        for(int i=0; i<30; i++){
                printf("%2d ", i);
                for(double q=0.1 ; q <= 0.55 ; q += 0.05){
                        double d = AttackerSuccessProbability(q, i);
                        printf("%f  ", d);
                }
                printf("\n");
        }
}

実行結果
bitcoin1

論文より
p = probability an honest node finds the next block
q = probability the attacker finds the next block
qz = probability the attacker will ever catch up from z blocks behind
実行結果にあるqは q=1-p の関係で、AttackerSuccessProbabilityはqz、zは縦軸の先行されているブロック数に相当します。

論文の説明にある

P < 0.001 q=0.10 z=5 q=0.15 z=8 q=0.20 z=11 q=0.25 z=15 q=0.30 z=24 q=0.35 z=41 q=0.40 z=89 q=0.45 z=340

の一番最初は、悪意あるノードが10%のとき、5ブロック後から追いつく確率が0.001(0.1%)以下という意味になります。実行結果は0.000914であっていることが確認できます。
もっと違うケースを見てみると実行結果から、悪意あるノードが50%の場合は、100%乗っ取られることがわかります。そんなことはまず想定しなくてもいいということなのでしょう。
30%のときは、5ブロックビハインドで18%くらいまで一気に下がります。またビハインドがゼロのときは悪意のノードがたとえ10%でも100%乗っ取れる計算になりますが、これはありえないということなのでしょう。

]]>