Segregated-Witness

使用 PYTHON 從 xPub 或 zPub 派生隔離見證地址

  • November 9, 2021

概括

我正在努力理解幾個概念。我想在我的 Ledger Nano S 中使用 Segwit 錢包來派生與我的 Nano 產生的匹配的未硬化(?)子公鑰(以及由此產生的 segwit 地址)。我想使用 Python 3 來做到這一點。我相信創建這樣的地址稱為“手錶錢包”,或者至少在 Bip32 文件中這樣描述:

例如,這允許網店業務讓其網路伺服器為每個訂單或每個客戶生成新地址(公鑰雜湊),而無需讓網路伺服器訪問相應的私鑰(花費收到的資金所需的私鑰)。 <https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki#Motivation>

這正是我試圖為我的 Django 應用程序使用 Python 所做的。我不想使用第三方服務,因為有人告訴我不要相信提供我的擴展公鑰 (xPub)。我想使用我的 Ledger Nano S 中的 xPub。實際上,我不完全確定我的 Nano S 是使用 xpub 還是 zpub,但我已經在一個單獨的問題中提出了這個問題。

Ledger Nano S 是否有用於比特幣錢包的 xPub 或 zPub?

無論如何,我已將“xpub”鍵轉換為“zpub”鍵,並嘗試使用許多不同的 python 模組從兩者中派生新鍵,並且在創建與我的 Nano 生成的地址匹配甚至看起來相似的地址方面的成功率為零。

我試過的

為了消除建議我已經嘗試過的方法的答案,這裡列出了我嘗試過的每種方法的完整且詳盡的列表,並附有 Stack Exchange 上所有類似問題的連結。

起初我嘗試了btclibPycoin

注意:在所有範例中,我都嘗試使用比特幣測試網

from btclib import bip32
from pycoin.networks.registry import network_for_netcode

network = network_for_netcode("XTN") # XTN for the Testnet, BTC for the Mainnet
xpub = "x(z/t)pub-big-long-key-that-starts-with-tpub-zpub-xpub"

child_xpub_key = bip32.derive(xpub, "84'/1'/0'/0/0")
key = network.parse.bip32(child_xpub_key)

print(str("Key: {}").format(child_xpub_key))
print(str("Address: {}").format(key.address())) 

與此問題類似: Derivive public key from xpub? 使用“強化”派生路徑時出現錯誤,為了使錯誤消失,我只能使用路徑 84/1/0/0/0。我什至嘗試過路徑 0 和 0/0。當然,我的 Nano 給我的路徑包括 (’)。據我了解,此派生路徑適用於 zpub 密鑰,但即使我轉換為 zpub,它也不會給我一個與我的 Nano 匹配的地址。我認為這是因為我應該使用 Bip44 或 Bip84 來派生地址?正確的?

我嘗試使用的下一件事是bip_utils

from bip_utils import Bip44, Bip44Coins
key_str = "x(z/t)pub-big-long-key-that-starts-with-tpub-zpub-xpub"
bip44_ctx = Bip44.FromExtendedKey(key_str, Bip44Coins.BITCOIN_TESTNET)

此程式碼有效,但是 bip_utils github 頁面上給出的範常式式碼表明下一行程式碼應該是:

# Derive account 0 for Bitcoin: m/44'/0'/0'
bip44_acc = bip44_ctx.Purpose().Coin().Account(0)

這給了我錯誤

Bip44DepthError: Current depth (3) is not suitable for deriving purpose

我已經知道我不想要 m/44’/0’/0’ 但是文件不知道如何更改路徑,查看原始碼也對我沒有幫助。

然後我嘗試使用著名的 Vitalik Buterin 的 pybitcointools 他甚至參與了有關“手錶錢包”的文件:

出於安全原因,理想情況下,種子和 xprv 應僅存放在冷藏庫中。如果 Web 應用程序需要能夠按需提供地址,則解決方案是使用從 xpub 生成的手錶錢包。例如,讓我們以前面範例中的 Dash xpub 為例:

from cryptos import *
coin = Dash()
xpub = 'xpub-some-xpub-key'
wallet = coin.watch_wallet(xpub)
wallet.is_watching_only
wallet.new_receiving_address()
wallet.new_change_address()

我在想“就是這樣,Vitalik 是我的英雄!他知道我在尋找什麼!” 但是不,這個範常式式碼顯然只適用於 Dash。當我將類更改為 Bitcoin() 時,文件中描述的“watch_wallet”方法都不起作用,或者更確切地說它們不存在。沒有一個例子可以說明如何使用比特幣進行這項工作。

結論

在我嘗試的所有方法中,至少 btclib 沒有給我任何錯誤。我可能錯誤地使用了這些 python 模組,或者我應該使用更好的 python 模組/類。任何方向都會有所幫助。先感謝您。

由於您無法使用 xPubs 分類帳遍歷硬化路徑,因此不會顯示主 xpub,而是顯示派生地址84/0'/0'或任何您的帳號的 xpub。從那裡你需要兩個額外的 0/0 派生來獲得最終的84/0'/0'/0/0公鑰。

生成的公鑰可用於派生 P2PKH 地址(非隔離見證)或 P2WPKH 地址(隔離見證)。Xpub 和 Zpub 都是相同密鑰的編碼,但 Zpub 還指示錢包從中派生 P2WPKH 地址。Ledger 沒有使用這個標準,而是更喜歡使用更通用的 Xpub 編碼(不提供指令)對其進行編碼。

使用我的玩具 Python 庫,您可以使用以下腳本來派生您的地址:

from cryptotools import Xpub

MY_XPUB = 'xpub-as-shown-in-ledger'

key = Xpub.decode(MY_XPUB)

pubkey0 = key/0/0
print(pubkey0.address('P2WPKH'))  # Tell the wallet that you want a P2WPKH address

如果你想要測試網地址設置 envvar CRYPTOTOOLS_NETWOK = ’test'

引用自:https://bitcoin.stackexchange.com/questions/109981