比特幣 - P2PKH 和 P2SH 地址生成之間的技術區別?
我確信以 ‘1’ 和 ‘3’ 開頭的地址生成之間的唯一區別只是將添加到摘要中的前綴從 0x00 更改為 0x05 在成熟md160 部分之後。
雖然我得到的地址與來自比特幣核心錢包的地址不匹配,但在導入相同的私鑰時,以及來自<https://segwitaddress.org/>的地址。前綴 04 是保持不變還是也發生了變化?我缺少一些東西。能否請你幫忙?謝謝你。
[編輯]
這是我目前的方法,但仍然不起作用。我肯定誤解了一些東西..
def getPublicAddress(self, digest): oSk = ecdsa.SigningKey.from_string(digest, curve=ecdsa.SECP256k1) oVk = oSk.get_verifying_key() hexlify = codecs.getencoder('hex') self.pubkey = str(hexlify(b'\04' + oVk.to_string())[0].decode('utf-8')) ripemd160 = hashlib.new('ripemd160') keyhash = hashlib.sha256(codecs.decode(self.pubkey, "hex")).digest() ripemd160.update(keyhash) redeem_script = hashlib.new('ripemd160') redeem_script.update(b'\x00\x14' + ripemd160.digest()) prefix = b'\x05' m = prefix + redeem_script.digest() checksum = hashlib.sha256(hashlib.sha256(m).digest()).digest()[:4] return base58.b58encode(m + checksum)
P2PKH、P2SH 和 Segwit 都是不同的地址類型。Segwit 和 P2SH 地址不一樣。
P2PKH 和 P2SH 地址以類似的方式生成。P2PKH 獲取公鑰的 hash160(公鑰的 SHA256 的 RIPMED160),將版本字節附加
0x00
到 hash160,Base58 Check 對其進行編碼。P2SH 地址是腳本的 hash160 的 Base58 Check 編碼(稱為redeemScript)。它使用版本字節
0x05
代替。其餘編碼相同,只是Base58 Check編碼。對於隔離見證地址,有多種類型。有遵循 Bech32 標準的本地隔離見證地址。還有 P2SH 包裝的隔離見證地址。
對於包裹在 P2SH 地址中的 P2WPKH(付費見證公鑰雜湊),redeemScript 是
0x0014 <hash 160 of the pubkey>
. 該redeemScript 以典型的P2SH 方式進行散列和編碼。對於包裹在 P2SH 地址中的 P2WSH(支付見證腳本雜湊),首先使用 SHA256 對見證腳本(redeemScript,但用於隔離見證地址)進行雜湊處理。那麼 P2SH 的兌換腳本就是
0x0020 <SHA256 of witnessScript>
. 這個redeemScript 的hash160 然後以典型的P2SH 方式編碼。至於您的程式碼,您將附加
0x04
到您的公鑰,這根本不正確。不是地址編碼的0x04
一部分,它是公鑰編碼本身的一部分。您的公鑰生成器應該已經為您執行此操作。請注意,如果公鑰被壓縮,則前綴字節將為0x02
或0x03
(取決於公鑰的 Y 值),而不是0x04
未壓縮的公鑰。[技術差異 - 範例解決方案]
`
def hash160(self, v): r = hashlib.new('ripemd160') r.update(hashlib.sha256(v).digest()) return r def doublehash256(self, v): return hashlib.sha256(hashlib.sha256(v).digest()) def ecdsaSECP256k1(self, digest): # SECP256k1 - Bitcoin elliptic curve sk = ecdsa.SigningKey.from_string(digest, curve=ecdsa.SECP256k1) return sk.get_verifying_key() def publicaddress1(self): prefix_a = b'\x04' prefix_b = b'\x00' digest = self.privkeyhex.digest() p = prefix_a + self.ecdsaSECP256k1(digest).to_string() # 1 + 32 bytes + 32 bytes self.pubkey = str(binascii.hexlify(p).decode('utf-8')) hash160 = self.hash160(p) m = prefix_b + hash160.digest() checksum = self.doublehash256(m).digest()[:4] self.pubaddr1 = base58.b58encode(m + checksum) def publicaddress3(self): prefix_even = b'\x02' prefix_odd = b'\x03' prefix_a = prefix_odd prefix_b = b'\x05' prefix_redeem = b'\x00\x14' digest = self.privkeyhex.digest() ecdsa_digest = self.ecdsaSECP256k1(digest).to_string() x_coord = ecdsa_digest[:int(len(ecdsa_digest)/2)] y_coord = ecdsa_digest[int(len(ecdsa_digest)/2):] if (int(binascii.hexlify(y_coord),16) % 2 == 0): prefix_a = prefix_even p = prefix_a + x_coord self.pubkeycompressed = str(binascii.hexlify(p).decode('utf-8')) redeem_script = self.hash160(prefix_redeem + self.hash160(p).digest()).digest() # 20 bytes m = prefix_b + redeem_script checksum = self.doublehash256(m).digest()[:4] self.pubaddr3 = base58.b58encode(m + checksum)`