import hashlib class Block(): def __init__(self, data, prev_hash): self.index = 0 self.nonce = 0 self.prev_hash = prev_hash self.data = data def blockhash(self): blockheader = str(self.index) + str(self.prev_hash) + str(self.data) + str(self.nonce) block_hash = hashlib.sha256(blockheader.encode()).hexdigest() return block_hash def __str__(self): return "Block Hash: " + self.blockhash() + "\nPrevious Hash: " + self.prev_hash + "\nindex: " + str(self.index) + "\nData: " + str(self.data) + "\nNonce: " + str(self.nonce) + "\n--------------" class Hashchain(): def __init__(self): self.chain = ["0000000000000000000000000000000000000000000000000000000000000000"] def add(self, hash): self.chain.append(hash) hashchain = Hashchain() target = 0x777777 * 2**(8*(0x1e - 0x03)) for i in range(30): block = Block("Block " + str(i+1), hashchain.chain[-1]) block.index = block.index + i + 1 for n in range(4294967296): block.nonce = block.nonce + n if int(block.blockhash(), 16) < target: print(block) hashchain.add(block.blockhash()) break
Category: Blockchain
Proof of work
簡易的なhash計算
import hashlib input_text = "satoshi" for nonce in range(20): input_data = input_text + str(nonce) hash = hashlib.sha256(input_data.encode("UTF-8")).hexdigest() print(input_data + " → " + hash)
ブロックヘッダのdifficulty bitsにハッシュ値の条件が書かれている
0x1e777777 のような形式で記述されている。
# difficulty_bits = 0x1e777777 # exponent = 0x1e # coefficient = 0x777777 target = 0x777777 * 2**(8*(0x1e - 0x03)) print(target) target_hex = hex(target)[2:].zfill(64) print(target_hex)
import hashlib class Block(): def __init__(self, data, prev_hash): self.index = 0 self.nonce = 0 self.prev_hash = prev_hash self.data = data def blockhash(self): blockheader = str(self.index) + str(self.prev_hash) + str(self.data) + str(self.nonce) block_hash = hashlib.sha256(blockheader.encode()).hexdigest() return block_hash def __str__(self): return "Block Hash: " + self.blockhash() + "\nPrevious Hash: " + self.prev_hash + "\nindex: " + str(self.index) + "\nData: " + str(self.data) + "\nNonce: " + str(self.nonce) + "\n--------------" class Hashchain(): def __init__(self): self.chain = ["0000000000000000000000000000000000000000000000000000000000000000"] def add(self, hash): self.chain.append(hash) hashchain = Hashchain() target = 0x777777 * 2**(8*(0x1e - 0x03)) for i in range(30): block = Block("Block " + str(i+1), hashchain.chain[-1]) block.index = block.index + i + 1 for n in range(4294967296): block.nonce = block.nonce + n if int(block.blockhash(), 16) < target: print(block) hashchain.add(block.blockhash()) break
UTXO
import json import requests address = "3FkenCiXpSLqD8L79intRNXUgjRoH9sjXa" res = requests.get("https://blockchain.info/unspent?active=" + address) utxo_list = json.loads(res.text)["unspent_outputs"] print(str(len(utxo_list)) + "個のutxoが見つかりました") for utxo in utxo_list: print(utxo["tx_hash"] + ":" + str(utxo["value"]) + " satoshis")
blockcain exploreのtransactionからも確認できる。
https://www.blockchain.com/explorer
$ python3 utxo.py
2個のutxoが見つかりました
0aed6c01112af0a2dd51981e983ce41ef271c3bbec834121a47dbe31c30519d7:548546 satoshis
768b2e91eaa99208d32d3dde2a0f70214940584754b66378a33c9e3bd60136c3:311694 satoshis
bitcoin 秘密鍵の生成
import os import binascii private_key = os.urandom(32) print(private_key) print(binascii.hexlify(private_key))
32バイトの乱数を生成して、バイナリデータを16進数に変換
$ python3 wallet.py
b’W~\x9cj\xcc}\x0f1J\xab\xa6Hh\x87\xe7\xa6x2\xb1c,\xe9\x1dZp{R\xc3\x8e9-\xe2′
b’577e9c6acc7d0f314aaba6486887e7a67832b1632ce91d5a707b52c38e392de2′
公開鍵に楕円曲線暗号を使用します。
$ pip install ecdsa
import os import ecdsa import binascii private_key = os.urandom(32) public_key = ecdsa.SigningKey.from_string(private_key, curve=ecdsa.SECP256k1).verifying_key.to_string() print(binascii.hexlify(private_key)) print(binascii.hexlify(public_key))
y^2 = x^3 + 7 mod p
import os import ecdsa import binascii private_key = os.urandom(32) public_key = ecdsa.SigningKey.from_string(private_key, curve=ecdsa.SECP256k1).verifying_key.to_string() print(binascii.hexlify(private_key)) print(binascii.hexlify(public_key)) # public_key y-axis public_key_y = int.from_bytes(public_key[32:], "big") # create compressed public_key if public_key_y % 2 == 0: public_key_compressed = b"\x02" + public_key[:32] else: public_key_compressed = b"\x03" + public_key[:32] print(binascii.hexlify(public_key_compressed))
sakura vpcのalma linuxでbitcoin coreを稼働したい
### sakura vpsの契約
1GB メモリ、100ssdで契約する。1ヶ月990円。
OSはalma linuxをインストール
### メモリ増強
1GBでは足りないらしいので、メモリを増強する
$ sudo fallocate -l 8G /swapfile
$ sudo chmod 600 /swapfile
$ sudo mkswap /swapfile
Setting up swapspace version 1, size = 8 GiB (8589930496 bytes)
no label, UUID=6a1c4a72-0340-40f3-be3a-9b7245afc3f0
$ sudo swapon /swapfile
$ free
total used free shared buff/cache available
Mem: 985552 126696 506488 31216 352368 689008
Swap: 8388604 0 8388604
### ポート解放
パケットフィルターでTCPの8333ポートを解放する
### alma linuxにbitcoin coreをinstall
$ sudo dnf install epel-release
$ sudo dnf upgrade
$ sudo dnf install snapd
$ sudo systemctl enable –now snapd.socket
$ sudo ln -s /var/lib/snapd/snap /snap
$ sudo snap install bitcoin-core
2023-10-31T08:08:07+09:00 INFO Waiting for automatic snapd restart…
bitcoin-core 25.1 from Bitcoin Core installed
### bit coin
$ bitcoin-core.cli –version
Bitcoin Core RPC client version v25.1.0
Copyright (C) 2009-2023 The Bitcoin Core developers
Please contribute if you find Bitcoin Core useful. Visit
The source code is available from
This is experimental software.
Distributed under the MIT software license, see the accompanying file COPYING
or
$ snap info bitcoin-core
name: bitcoin-core
summary: Fully validating Bitcoin peer-to-peer network node, wallet and GUI
publisher: Bitcoin Core
store-url: https://snapcraft.io/bitcoin-core
contact: https://github.com/bitcoin-core/packaging/issues/new?title=snap:
license: unset
description: |
Bitcoin Core connects to the Bitcoin peer-to-peer network to download and
fully validate blocks and transactions. It also includes a wallet and
graphical user interface.
commands:
– bitcoin-core.cli
– bitcoin-core.daemon
– bitcoin-core.qt
– bitcoin-core.tx
– bitcoin-core.util
– bitcoin-core.wallet
$ bitcoin-core.cli -getinfo
error: timeout on transient error: Could not connect to the server 127.0.0.1:8332
Make sure the bitcoind server is running and that you are connecting to the correct RPC port.
### 再起動
VPS再起動
$ bitcoin-core.daemon -testnet
snapでinstallすると、実行コマンドが違うので注意が必要
merkletree
こちらの記事を参考に動かしてみる
https://alis.to/gaxiiiiiiiiiiii/articles/3dy7vLZn0g89
トランザクションのハッシュ値作成の箇所は、Node(left.hash + right.hash)として、hash値を単純に横に繋げてそれをsha256でハッシュ化してるところが面白い。
from hashlib import sha256 class Node: def __init__(self, data): self.left = None self.right = None self.parent = None self.sibling = None self.position = None self.data = data self.hash = sha256(data.encode()).hexdigest() class Tree: def __init__(self, leaves): self.leaves = [Node(leaf) for leaf in leaves] self.layer = self.leaves[::] self.root = None self.build_tree() def build_layer(self): new_layer = [] if len(self.layer) % 2 == 1: self.layer.append(self.layer[-1]) for i in range(0, len(self.layer), 2): left = self.layer[i] right = self.layer[i+1] parent = Node(left.hash + right.hash) left.parent = parent left.sibling = right left.position = "left" right.parent = parent right.sibling = left right.position = "right" parent.left = left parent.right = right new_layer.append(parent) self.layer = new_layer def build_tree(self): while len(self.layer) > 1: self.build_layer() self.root = self.layer[0].hash def search(self, data): target = None hash_value = sha256(data.encode()).hexdigest() for node in self.leaves: if node.hash == hash_value: target = node return target def get_pass(self, data): target = self.search(data) markle_pass = [] if not(target): return markle_pass.append(target.hash) while target.parent: sibling = target.sibling markle_pass.append((sibling.hash, sibling.position)) target = target.parent return markle_pass def caluculator(markle_pass): value = markle_pass[0] for node in markle_pass[1:]: sib = node[0] position = node[1] if position == "right": value = sha256(value.encode() + sib.encode()).hexdigest() else: value = sha256(sib.encode() + value.encode()).hexdigest() return value
【python】マークルツリーのtx1とtx2を組み合わせたhash計算
マークルツリーでsha256のハッシュ計算を行う際に、単純にハッシュ値をつなぎ合わせて、それをさらにsha256で計算しているようだ。
トランザクション1とトランザクション2からのハッシュ値は何度実行しても同じになる。
import hashlib tx1 = 'abc' tx2 = 'cde' tx1hash = hashlib.sha256(tx1.encode()).hexdigest() print(tx1hash) tx2hash = hashlib.sha256(tx2.encode()).hexdigest() print(tx2hash) tx12 = tx1hash + tx2hash tx12hash = hashlib.sha256(tx12.encode()).hexdigest() print(tx12hash)
$ python3 test.py
ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad
08a018a9549220d707e11c5c4fe94d8dd60825f010e71efaa91e5e784f364d7b
e7ea6d8ded8ff13bb4e3fccadb13878004f69bad2d3d9d33f071c13a650303ba
【Python】for ~ inを使ったリスト処理を1行で書く
names = ["Alice", "Bob", "Charlie"] newData = [name + "さん" for name in names] print(newData)
$ python3 test.py
[‘Aliceさん’, ‘Bobさん’, ‘Charlieさん’]
リストで返すようにすれば1行で書ける
【Python】classの__init__の使い方
pythonでの関数の呼び出し
def some_function(something): print(something) some_function("hello world")
Classにした場合
L インスタンスを生成して処理を実行する
L クラスの中の関数をメソッドと呼ぶ
class SomeClass: def __init__(self, something): self.something = something def some_function(self): print(self.something) c = SomeClass("hello world") c.some_function()
class SomeClass: def __init__(self, something): self.something = something def some_function(self): print(self.something) def some_function2(self): return self.something c = SomeClass("hello world") c.some_function() print(c.some_function2())
selfはインスタンス自身のこと
initはデータの初期化の関数
class MyStatus: def __init__(self, age, name, height, weight): self.age = age self.name = name self.height = height self.weight = weight def print_name(self): print(self.name) def print_age(self): print(self.age) def print_height(self): print(self.height) def print_weight(self): print(self.weight) a = MyStatus(14, "yamada", 160, 55) a.print_height()
コーヒーメーカーのClassを作ってみる
class CoffeeMaker: def __init__(self, water, brand, tempreture): self.water = water # mill self.brand = brand self.tempreture = tempreture def boiling(self): boilingTime = self.water / 10 * self.tempreture print(boilingTime) def brew(self): print(self.brand + "を滴れました") a = CoffeeMaker(300, "brend", 3) a.boiling() a.brew()
$ python3 test.py
90.0
brendを滴れました
なるほど、Classと関数とinitの使い方について、自分で例を作ると構造を理解できますね。
phpの場合はinitのところが__contructになります。引数はconstructで定義しています。
class Dog {
private $name;
public function __construct($name) {
$this->name = $name;
}
public function getName(){
echo $this->name;
}
}
$dog = new Dog(“Pochi”);
$dog->getName();
[/code]
ini_set('display_errors', "On"); class CoffeeShop { private $order; private $pay; public function __construct($order, $pay) { $this->order = $order; $this->pay = $pay; } public function coffeePrice(){ switch ($this->order) { case "ブレンド": echo "price is 330 yen\n"; $price = 330; break; case "アメリカン": echo "price is 350 yen\n"; $price = 350; break; case "アイスコーヒー": echo "price is 380 yen\n"; $price = 380; break; default: echo "not available at this store"; } $change = $this->pay - $price; return $change; } } $a = new CoffeeShop("ブレンド", 1000); $b = $a->coffeePrice(); echo $b;
【python】sha256
Pythonのハッシュ値を求める関数はhashlibにある
import hashlib x = 'abc' m = hashlib.md5(x.encode()).hexdigest() sha256 = hashlib.sha256(x.encode()).hexdigest() sha384 = hashlib.sha384(x.encode()).hexdigest() sha512 = hashlib.sha512(x.encode()).hexdigest() print(m) print(sha256) print(sha384) print(sha512)
encodeはコードの符号化
hexdigest は16進数文字列に変換
$ python3 test.py
900150983cd24fb0d6963f7d28e17f72
ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad
cb00753f45a35e8bb5a03d699ac65007272c32ab0eded1631a8b605a43ff5bed8086072ba1e7cc2358baeca134c825a7
ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f