【Python】BitcoinSV用ライブラリ「bitsv」の中身を読み解く①

BitcoinSVのブロックチェーンにPythonからアクセスすることのできるライブラリであるbitsvの関数の引数とか挙動を自分用にメモしている記事。このライブラリを使って何かしたい人には役に立つかもしれないし、ビットコインに自信ニキには今更な情報が多いかもです。

・初期設定

key = '自分の秘密鍵'
my_key = bitsv.Key(key)

ここでのkeyの変数に格納している秘密鍵は、
wallet.pyのclass PrivateKey(BaseKey):~  に飛んでいる

・.getbalance(currency=’satoshi’)

.getbalance()自分の秘密鍵のなかにあるBSVの残高をSatoshi換算で返してくれる関数。中でやっていることは、読み込ませた秘密鍵から所有権のある公開鍵を検出してblockchairのAPIで各アドレスの保有量を検索し、合計した数値を返している。

引数currencyはデフォルトは’satoshi’だが、ほかにも’jpy’、’usd’など各法定通貨建ての価格でも取得可能。その場合の各法定通貨のレートはhttp://bitcoinsv-rates.com/api/rates/ から取得している。

法定通貨換算の場合はまず①usd単位でのbsv価格の取得→②÷10*8でsatoshi単位のbsv価格に換算→③各法定通貨のusd建ての価格をAPIで取得→
④Satoshi単位のusd建てbsv価格×usd建て法定通貨価格の計算結果が戻り値で返ってくる

・send(self, outputs, fee=None, leftover=None, combine=True,message=None, unspents=None, custom_pushdata=False)

send()は標準のbsvトランザクションを発行し、送信する関数。基本的にはoutputをgithubの書式に合わせて設定して実行するだけでOK。

引数feeで任意のトランザクション手数料を設定できる。messageはトランザクションにメッセージを付与できるがその分余計なデータをアップロードしているので手数料があがる。

custom_pushdataは、ビットコインのプログラミング言語であるscriptに搭載されているOP_CODEのpushdata2、pushdata4でデータを送るとき(デフォルトのトランザクションはpushdata1を使っている)にTrueにするっぽい。

scriptにはデフォルトのpushdata1と任意のデータをアップロードするOP_RETURN以外にも様々なOP_CODEがあるが恐らくスマコンの時に使われるのではないかと予想。

send()は内部で
・get_unspents()
・create_transaction()
・network_api.broadcast_tx(tx_hex)
を実行し、戻り値はcalc_txid(tx_hex)の結果を返している

・get_unspents()

get_unspents()は、読み込んだ秘密鍵が保有しているウォレットアドレス(公開鍵)のうち未使用のモノを返す関数。

ビットコインのアドレスはプライバシー保護のためにUTXOという仕組みを使用しており、これは1回の取引ごとに秘密鍵から新しいウォレットアドレス(公開鍵)を発行し、送金した分以外の残りのコイン(お釣り分)はそこに全部移し替えるという、使い捨て方式になっている。

そのため、秘密鍵に紐づけらている公開鍵アドレスは常に一回も使われていない新鮮(未使用/unspent)なアドレスにコインが入っている状態になっている。get_unspents()は自分の秘密鍵がか保有している新鮮な公開鍵アドレスの情報を確認する関数です。

戻り値には、秘密鍵に紐づけられている各公開鍵ウォレットアドレスが[確認数、アドレス、インデックス、残高]の順番で格納された2次元配列が返ってきている。

・create_transaction()

内部でcreate_p2pkh_transaction(self, unspents, outputs, custom_pushdata=custom_pushdata)を呼び出しているだけの関数。

ちなみにp2pkhとは、Pay-to-Public-Key-Hashの略。

P2PKHはBitcoinがSegWitを導入する前に使われていた送金するためのスクリプトです。現在はBitcoinCash、BitcoinSV、Litecoinなどで使われています。

ビットコイン系通貨の送金のスクリプトの基本的なルールは、UTXOのoutputに含まれるLocking Script(scriptPubKey)を解除するためにUnlocking Script(scriptSig)をinputに入れて解除することです。このトランザクションに対して秘密鍵で署名してブロードキャストすることで送金が完了します。

上記を踏まえて、P2PKHはLocking Scriptに送金相手のPublicKey:公開鍵のRIPEMD160(SHA256(PublicKey))したハッシュ値を含むLockgin Scriptで送金することを言います。

参照:https://tomokazu-kozuma.com/explanation-of-bitcoin-script-p2pkh/

・create_p2pkh_transaction(self, unspents, outputs, custom_pushdata=custom_pushdata)

create_p2pkh_transaction()はp2pkhのBSVトランザクションを生成する関数。標準のトランザクションの生成はここがメイン処理っぽい?

中でやっていることのうちまず冒頭でやっている処理がこいつら。

# 秘密鍵から公開鍵を生成
public_key = private_key.public_key

# 生成した公開鍵の長さをバイト列で表現
# Pythonのデフォルト関数のto_bytes()で文字数をバイト列に変換する public_key_len = len(public_key).to_bytes(1, byteorder='little') # ビットコインのプログラミング言語「script」でのトランザクション # 発行コードをバイト列で表現したもの scriptCode = private_key.scriptcode #scriptのコードの長さを計算して整数で返している
scriptCode_len = int_to_varint(len(scriptCode)) 

最後のScriptCodeがよく分からなかったのだが、P2PKHの場合、scriptCodeはscriptPubKeyということになるらしい。要は↓のこと。

OP_DUP OP_HASH160 <pubkey hash> OP_EQUALVERIFY OP_CHECKSIG

ただこれをそのままブロックチェーンにブロードキャストすることができないらしく、ブロックチェーンにscriptのスクリプトをブロードキャストする際は各OP_CODEのコード番号(106とか)を16進数に変換したバイト列で表現してあげる必要があるらしい。

ビットコインのOP_CODEの各WordとかCodeとか16進数(hex)での表現方法は下記参照、ビットコイン(BTC)とビットコインSV(BSV)は、OP_RETURNがないとか若干違うので、正確な参考にはならないがイメージ的にはこんな感じ

https://qiita.com/j0hnta/items/4c55f3d906331389059d

ともかく、BitcoinSVのOP_CODEについてはbitsv内で↓のように定義されているので、これがBitcoinSVでの各OP_CODEのWordとCodeらしい。

tranzaction.py

OP_0 = b'\x00'
OP_CHECKLOCKTIMEVERIFY = b'\xb1'
OP_CHECKSIG = b'\xac'
OP_DUP = b'v'
OP_EQUALVERIFY = b'\x88'
OP_HASH160 = b'\xa9'
OP_PUSH_20 = b'\x14'
OP_RETURN = b'\x6a'
OP_PUSHDATA1 = b'\x4c'
OP_PUSHDATA2 = b'\x4d'
OP_PUSHDATA4 = b'\x4e'

wallet.py

 def scriptcode(self): 
    self._scriptcode = (OP_DUP +
                        OP_HASH160 + 
                        OP_PUSH_20 +
                        address_to_public_key_hash(self.address) +
                        OP_EQUALVERIFY +
                        OP_CHECKSIG) 
    return self._scriptcode

なので、._scriptcodeの中身はb’v\xa9\x14\x17(\xd7!\xaa\xfc\xf5\xd0j[\xf6\xaf\xb7\xd8\xc3\xcc\xa9\x8c)\x96\x88\xac みたいな感じの人間が見ると、なにを命令しているのか分かよく分からないものになっている

そして、create_p2pkh_transaction()の中身の戻ると
version = VERSION_1
lock_time = LOCK_TIME
# sequence = SEQUENCE
hash_type = HASH_TYPE
input_count = int_to_varint(len(unspents))
output_count = int_to_varint(len(outputs))
ここはさっきのscriptcodeとやっていることは同じ、あらかじめ決められているOP_CODEのコード番号を16進数のバイト列で表現しているだけ。
tranzaction.py
VERSION_1 = 0x01.to_bytes(4, byteorder='little')
SEQUENCE = 0xffffffff.to_bytes(4, byteorder='little')
LOCK_TIME = 0x00.to_bytes(4, byteorder='little') 
~# Python 3 doesn't allow bitwise operators on byte objects... 
HASH_TYPE = 0x01.to_bytes(4, byteorder='little')
# BitcoinSV fork ID.
SIGHASH_FORKID = 0x40.to_bytes(4, byteorder='little')
# So we just do this for now.
FIXME HASH_TYPE = 0x41.to_bytes(4, byteorder='little') 
##

そして、その次の

output_block = construct_output_block(outputs, custom_pushdata=custom_pushdata)
の部分はoutblockに使用するアドレスの残高とか諸々の情報をバイト列にして、それを格納して返す関数みたい。これの関数だけでOUTPUTはできているっぽく、create_p2pkh_transaction()の大半はINPUYの作成に費やされている。
OUTPUTはネットワークに送信するトランザクションをロックするだけでINPUT部分はそのロックされた電子署名を解読する処理とか行っているので、その辺がINPUT処理が長い理由かなと思われる。

戻り値は
bytes_to_hex(
version +
input_count +
construct_input_block(inputs) +
output_count +
output_block +
lock_time
)

そして、作成したトランザクションをビットコインネットワークにブロードキャスト(公開)する必要がある。

これにはBitindexというサービスのAPIを使用して行っているみたい。ここのAPIにPOSTするとビットコイントランザクションがネットワークに公開されて、Mempoolに保管され、マイナーによる認証受けたのちブロックに格納される。

終わり

今まで高レイヤーの部分ばっかりやっていたので、低レイヤー部分でよくある16進数とか2進数とかビットとかバイトの処理にぶち当たった経験がなかったので、今回のbitsvのライブラリの解析は非常にためになった。他人の作ったコードの解析をする時はVS_Codeは超便利。

まあこういうことをいちいち理解しなくても直感的に動かせるツールとかが出てきたらDappsとかブロックチェーン回りの開発ももっと加速するかなと思う。これから楽しみ。

プログラミングの独学はとても難しい


プログラミングは小学校の義務教育にも導入され始めており、これから社会人として生きていく上でプログラミングはもはや出来て当たり前、出来なれば論外というエクセルレベルの必須スキルになりつつあります。そしてそういう話を聞いて参考書なりを購入して独学でプログラミング勉強しようと思っている人も少なくないでしょう。しかしプログラミングを独学で勉強し始めようと思うものの



・「分からない箇所で詰まって挫折してしまった」

・「勉強する時間が足りない」

・「ネットの記事だと情報が断片的でよくわからない」

・「コードのエラーの原因が分からない」



という壁にぶち当たって、プログラミングの勉強を止めてしまう方が少なくありません。独学でプログラミングを勉強してる時間のほとんどはつまづいている時間です。実際僕も最初のころ独学でプログラミングを勉強していた頃はエラーの原因が分からず丸1日を不意にしてしまった・・・そんな苦い経験がありました。それで僕は一度はプログラミングの学習を諦めてしまいましたが、就活で現実を知る中で



「プログラミングを勉強して、いずれフリーランスとして自由な生き方がしたい」

「エンジニアとして若いうちから高収入を得たい」



という強い気持ちから一念発起して「侍エンジニアのwebサービスコース」に申し込み、プロのエンジニアの方に対面でマンツーマンでPythonによるWebサービス作り方とWeb技術の基本を教えてもらい、ようやくプログラミングが理解でき、今ではエンジニアとしてそこそこの暮らしができるようになりました。





侍エンジニアでは、とりあえずプログラミングやインターネットの基本を知っておきたい人から、HTML・cssなどでWebサイトやWebアプリを作ってみたい人やPythonを勉強してデータサイエンティストやAIエンジニアになりたい人まで幅広いニーズに応えた様々なコースが用意されています。



IT業界と言ってもエンジニアの仕事はプログラミング言語次第でサーバーから機械学習・ディープラーニングまで多種多様ですし、侍エンジニアの無料レッスン(カウンセリング)を受けてみて、自分のやりたいITの仕事は何なのか?を見つけるのがエンジニアへの第一歩になります。ちなみに今侍エンジニアの無料レッスンを受けると1000円分のAmazonギフト券がもらえるので、試しに受けてみるだけもお得です。


自分は半端に独学やオンラインスクールで勉強して金と時間を無駄にするくらいなら、リアルのプログラミングスクールに通ってしっかりプログラミングを勉強した方がいいと思います。ちなみに今、侍エンジニアに申し込むと、25歳以下の学生の方であれば、受講料が20%OFFになるので超お得です。


そして、プログラミングは大勢で授業を受けたり漫然とオンライン学習をするよりも自分が分からない箇所をピンポイントでプロの講師に直接質問して、ちゃんと納得するというスタイルの方がお金は確かに少し掛かりますが、独学で学ぶよりも絶対にモノになります。


シェアする

  • このエントリーをはてなブックマークに追加

フォローする

   侍エンジニア塾       
侍エンジニアの無料体験レッスンを予約する -->