import os import binascii import ecdsa import hmac import hashlib seed = os.urandom(32) root_key = b'Bitcoin Seed' def hmac_sha512(data, keymessage): hash = hmac.new(data, keymessage, hashlib.sha512).digest() return hash def create_pubkey(private_key): publickey = ecdsa.SigningKey.from_string(private_key, curve=ecdsa.SECP256k1).verifying_key.to_string() return publickey master = hmac_sha512(seed, root_key) master_secretkey = master[:32] master_chaincode = master[32:] master_publickey = create_pubkey(master_secretkey) master_publickey_integer = int.from_bytes(master_publickey[32:], byteorder="big") if master_publickey_integer % 2 == 0: master_publickey_x = b"\x02" + master_publickey[:32] else: master_publickey_x = b"\x03" + master_publickey[:32] print("マスター秘密鍵") print(binascii.hexlify(master_secretkey)) print("\n") print("マスターチェーンコード") print(binascii.hexlify(master_chaincode)) print("\n") print("マスター公開鍵") print(binascii.hexlify(master_publickey_x)) index = 0 index_bytes = index.to_bytes(8, "big") data = master_publickey_x + index_bytes result_hmac512 = hmac_sha512(data, master_chaincode) sum_integer = int.from_bytes(master_secretkey, "big") + int.from_bytes(result_hmac512[:32], "big") p = 2**256 - 2**32 - 2**9 - 2**8 - 2**7 - 2**6 - 2**4 - 1 child_secretkey = (sum_integer % p).to_bytes(32, "big") print("\n") print("子秘密鍵") print(binascii.hexlify(child_secretkey))
bitcoin アドレスの生成
import os import ecdsa import hashlib import base58 from Crypto.Hash import RIPEMD160 private_key = os.urandom(32) public_key = ecdsa.SigningKey.from_string(private_key, curve=ecdsa.SECP256k1).verifying_key.to_string() prefix_and_pubkey = b"\x04" + public_key intermediate = hashlib.sha256(prefix_and_pubkey).digest() ripemd160 = RIPEMD160.new() ripemd160.update(intermediate) hash160 = ripemd160.digest() prefix_and_hash160 = b"\x00" + hash160 double_hash = hashlib.sha256(hashlib.sha256(prefix_and_hash160).digest()).digest() checksum = double_hash[:4] pre_address = prefix_and_hash160 + checksum address = base58.b58encode(pre_address) print(address.decode())
hashlibで以下のように書くとエラーになる。
ripemd160 = hashlib.new(‘ripemd160’)
$ python3 address.py
Traceback (most recent call last):
File “/usr/lib/python3.10/hashlib.py”, line 160, in __hash_new
return _hashlib.new(name, data, **kwargs)
ValueError: [digital envelope routines] unsupported
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File “/home/vagrant/dev/work/address.py”, line 12, in
ripemd160 = hashlib.new(‘ripemd160’)
File “/usr/lib/python3.10/hashlib.py”, line 166, in __hash_new
return __get_builtin_constructor(name)(data)
File “/usr/lib/python3.10/hashlib.py”, line 123, in __get_builtin_constructor
raise ValueError(‘unsupported hash type ‘ + name)
ValueError: unsupported hash type ripemd160
従って、pycryptodomeをインストールして、ripemd160を使う
$ pip install pycryptodome
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))
python基礎
bit演算子
print(bin(10)) print(bin(13)) print(bin(10|13))
print(bin(10)) print(bin(13)) print(bin(10&13))
シフト演算
print(bin(15)) print(bin(15<<0)) print(bin(15<<1)) print(bin(15<<2)) print(bin(15<<3)) print(bin(15<<4)) print(bin(15)) print(bin(15>>0)) print(bin(15>>1)) print(bin(15>>2)) print(bin(15>>3)) print(bin(15>>4))
list
list2=[10,20,30] list2.append(40) print(list2) list3=[1,2,3,4,5] list3.insert(3, 10) print(list3) list4=[1,2,3,4,5] print(len(list4))
dictionary
dic1 = {"A": 1, "B": 2} dic2 = {} dic2["key"] = "value" print(dic1) print(dic2)
class, instance
class Greet(): def __init__(self, greet): self.value = greet morning = Greet("おはよう!") evening = Greet("こんばんわ!") print(morning.value) print(evening.value)
__str__(self)は自動的に文字出力する
class Person(): def __init__(self, name, age): self.name = name self.age = age def __str__(self): return "Name:" + self.name + ", Age:" + str(self.age) satoshi = Person("satoshi", 30) print(satoshi)
import
import numpy as np def area_circle(r): ans = np.pi * r **2 return ans print(area_circle(3))
これをfromを使って以下のように書くことができる。コードを省略できるメリットがある。
from numpy import pi def area_circle(r): ans = pi * r **2 return ans print(area_circle(3))
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すると、実行コマンドが違うので注意が必要
shell scriptでメモリ使用率
#!/bin/bash YMD=`date +"%Y/%m/%d %p %I:%M:%S"` MEM_LOG="memory.log" MEM_USED=`free | grep Mem | awk '{print($2-$3)/$2*100}'` SWAP_USED=`free | grep Swap | awk '{print($3)/$2*100}'` echo "$HOSTNAME memory is $MEM_USED %, date is $YMD" >> MEM_LOG echo "$HOSTNAME swap is $SWAP_USED %, date is $YMD" >> MEM_LOG
vagrant memory is 86.4592 %, date is 2023/10/21 PM 07:25:24
vagrant swap is 4.532 %, date is 2023/10/21 PM 07:25:24
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
VS code + parallels + vagrant + ubuntu2204
MacのM1チップではvurtualboxに対応していないため、vagrant + parallelsでubuntu22.04の環境を構築する
% sw_vers
ProductName: macOS
ProductVersion: 13.0
BuildVersion: 22A380
### vagrantインストールおよびubuntuの構築
$ brew install hashicorp/tap/hashicorp-vagrant
$ vagrant -v
$ vagrant plugin install vagrant-parallels
$ vagrant init bento/ubuntu-22.04-arm64
parallelsのsubscriptionを購入する。1年で1万円程度。
https://www.parallels.com/
$ vagrant up –provider=parallels
$ vagrant ssh
$ sudo apt update
### vsコードからの設定
vsコードをインストール
https://azure.microsoft.com/ja-jp/products/visual-studio-code
ExtensionsでRemoteDevelopmentをインストール
次いで、Parallels Desktopもインストールしておく(あまり意味はない)
左メニューのremote exploreでSSHの歯車アイコンから、
Users/${name}/.ssh/configを開く
ここに、vagrant ssh-configの値をそのまま入力する
HostName 10.211.55.3 User vagrant Port 22 UserKnownHostsFile /dev/null StrictHostKeyChecking no PasswordAuthentication no IdentityFile /Users/mac/MyVagrant/ubuntu2204/.vagrant/machines/default/parallels/private_key IdentitiesOnly yes LogLevel FATAL PubkeyAcceptedKeyTypes +ssh-rsa HostKeyAlgorithms +ssh-rsa
ここで下記の記事のようにhostname, user, port, identityfileのみだとうまく接続出来ないので注意が必要
https://qiita.com/yamashin0616/items/87e042b3f5ec52e57017
後は接続するだけです。Cyberduck、sublimeから変えたいと思っていたので割と簡単に出来て良かった。
【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】listのappend
appendとすると、リストの最後に追加される
names = ["Alice", "Bob", "Charlie"] names.append("Dave") print(names)
$ python3 test.py
[‘Alice’, ‘Bob’, ‘Charlie’, ‘Dave’]
カッコで囲んで二つ入れると
names = [(“Alice”,”20″), (“Bob”,”23″), (“Charlie”,”25″)]
names.append((“Dave”,”12″))
print(names)
print(names[0][1])
[/code]
基本的に一つしか入らないがタプルとして入れることもできる
$ python3 test.py
[(‘Alice’, ’20’), (‘Bob’, ’23’), (‘Charlie’, ’25’), (‘Dave’, ’12’)]
20