2020/06/02

PythonでBIP49アドレスを生成 その2

bitcoincrypto-assetpython

概要

この記事の続きです。

pythonでBIP49ベースのprivate keyおよびaddressを生成できないか検証してみました。

今回は、bip-utilsというツールを検証してみました。

実施事項

オンラインツールの使用

まずは、テスト用にmnemonicを生成します。(以下)

abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about

https://test.jochen-hoenicke.de/bip39-standalone.html が便利です。

まずは上記のオンラインのツールを使って "m/49’/1’/0’/0/0"のアドレスを生成してみます。

2Mww8dCYPUpKHofjgcXcBCEGmniw9CoaiD2

が生成されていました。

bip-utilsを使った実装

testnet

今回はtestnetのみ記載します。

import binascii
from base58 import b58encode
import hashlib
from bip_utils.wif import WifConst
from bip_utils import Bip49, Bip44Coins, Bip44Changes, Bip39SeedGenerator


mnemonic = "abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about"
passphrase = ""
seed_bytes = Bip39SeedGenerator(mnemonic).Generate(passphrase)
master_key = Bip49.FromSeed(seed_bytes=seed_bytes, coin_idx=Bip44Coins.BITCOIN_TESTNET) # mainnetの場合は、ここのcoin_idxを変更する
# m/49'/1'/0'/0
bip49_account = master_key.Purpose().Coin().Account(0)
# m/49'/1'/0'/0
bip49_change = bip49_account.Change(Bip44Changes.CHAIN_EXT)
for i in range(20):
    # m/49'/1'/0'/0/i
    bip49_address = bip49_change.AddressIndex(i)
    # wif_net_version: mainnet: "80", testnet: "ef"
    wif_net_version = binascii.hexlify(bip49_address.m_coin_class.WifNetVersion()).decode()
    wif = encode_wif_compressed_manually(
        private_key_hex=bip49_address.PrivateKey().Raw().ToHex(), wif_net_version=wif_net_version)
    print(f"private key wif: {wif}")
    address = bip49_address.PublicKey().ToAddress()
    print(f"address: {address}")

wif formatに変換する関数は自作する必要がありそうだったので、自作しました。

  • wif formatは末尾に’01’を追加してから sha256を2回かけてchecksumを付与し、base58でエンコーディングします。

詳細はWallet import format - Bitcoin Wikiを参照しました。

def encode_wif_compressed_manually(private_key_hex: str, wif_net_version: str):
    hex_extended = wif_net_version + private_key_hex + binascii.hexlify(WifConst.PUB_KEY_SUFFIX).decode()
    digest = hashlib.sha256(binascii.unhexlify(hex_extended)).hexdigest()
    double_digest = hashlib.sha256(binascii.unhexlify(digest)).hexdigest()
    checksum = double_digest[0:8]
    wif = b58encode(binascii.unhexlify(hex_extended + checksum))
    return wif.decode()

こちらを実行すると以下のようになります。

private key wif: cULrpoZGXiuC19Uhvykx7NugygA3k86b3hmdCeyvHYQZSxojGyXJ
address: 2Mww8dCYPUpKHofjgcXcBCEGmniw9CoaiD2
private key wif: cUWvs4gEqYVpQ2Kn4aAt6S1Kn2VKvCEFmnmL7XAvrco4frNWD8iJ
address: 2N55m54k8vr95ggehfUcNkdbUuQvaqG2GxK
private key wif: cPxPzgxKn4tE9vTQU3Sq3p7ypG1tTkdirQHjcVA5NqqwCx1vgQfT
address: 2N9LKph9TKtv1WLDfaUJp4D8EKwsyASYnGX
private key wif: cSzfwxWXgcYfYYAPWAxLpa5CcuHBki8d8QQ117S9fckQtvDimmqC
address: 2MyVXDzGJgATSdkhKHWvStpBoGEZb1fwjha
private key wif: cU4D6GEByRZLoihqp665rSCdGR41gDsk23FvxM5XdQu4dgeS5F3Q
address: 2MuKeQzUHhUQWUZgx5AuNWoQ7YWx6vsXxrv
private key wif: cSE3d8XrFAT44qxqSkczDUgpa5zXFPcufVDh7ty3RSBfvuFSeL9f
address: 2N5pTWRLrRdAPGvTd9agPFLFZvPfGNy7xuM
private key wif: cNGsFhuCDgQpFZHyatEe5kbEgw2FLmyGvSJddkdKqiYCStCbr5nb
address: 2NGH8tu2EGN2EuDdtRhmFFtWDu817ad4ikz
private key wif: cSu3YAmVw7XhyP4aMfXB3K7PiH1ZLy4Zwg9zfPpw865WvZEmapnh
address: 2MsdaNvf3b8iGC9rC3ETr5nUvbRPeAMXNWM
private key wif: cP2wJy9tPLBJLA6xCr8V7L9mRZcmzGNWoMaVYoLieJJDeBVbcnru
address: 2N1FpQEsArj3hGBdwc6n7e2CzggtRAooJTP
private key wif: cTmegCDqDTD5g1qcjVyKgoQpxVMmrbDL5zsPhWoNmqAwQbt3TM5w
address: 2Mtrpqq7cQznHw9wYnsSKroTdZ6u3fsB4kZ
private key wif: cRaBPnVZeuPLPjSvgd242ogSAVAFjpYzU9S12FMVj3aLHu3Tcq92
address: 2N4aDXmzJykaaihDFws574RyM2aFJpT4EzS
private key wif: cSk1snxDvYKGLqK7KjTEHnAFpYD2AYUhiNwnUYWckkm2s4avAvDR
address: 2MzGcncD84os4e8yrexdvDK685k2LVg6A9a
private key wif: cTyDvdtZQj64gSjg9RpP1tTKGUVHbts7WBkSe7FQzVQZN6NrowMs
address: 2N1yy8dDstG2cf3Xt6WzkJZPGV63QpZBFZu
private key wif: cPProvhxCDQbw3LuuAENQZCB4rGqnXrJCAXo7hjsWZXhSjcQ3FXx
address: 2N7AZigbQQje53NybX2AuD9amuF3Kfr5Z8h
private key wif: cQgrkLqqRKpKW15yonEEHGaH7RNVWbY1oHKJWUBP7a7nbTrrUrQ2
address: 2N7Mg3XFUHN9H6kkLjVzxzqB29SCzygjaZX
private key wif: cVXm23CU6gP5yTRgapivr9GUeTXMGuvj2x6rJgfgW3zq7fZrpSqi
address: 2NBRjDXAbHXNpMpo7uKwKyF5hyU8BkzpsM1
private key wif: cNuZ87Wuq9Ag9eKxrUyPyLfvo13XkSE9L7ZZnS1K3t5UZyxJvUS7
address: 2MtsJMgXqk95CYzUMvchm2nfPJeKrVwwMSU
private key wif: cPoouahZX6v44QiSmVcDiYCRrApp4ynmGKPARWiRq3m8ALMs8j8g
address: 2N9q6uC7DhHGSwhEor7Z7JvniLc3T6dYpVc
private key wif: cSsjz4Dq5YtsyxvFi9XJaUsx84y4mUs9SNJNj1p3oB55qd8gSC9a
address: 2N31gWk3ZQygoANPPn39qC9ZQTc9jhqicsE
private key wif: cT36bGHzShcUX5wGqyvCVPHC9Kt5HrDN3nNwgJy2BUmzoTG1m1qC
address: 2MtpC7u3H88WHwMDRsDitc5YnAv12ZWGQzm

オンラインツールで出力されているものと同じデータが得られました。

以上になります。