一(yī)文(wén)看(kàn)懂(dǒng)怎樣用(π♦∞•yòng) Python 創建比特币交易

2018-04-04 15:20

 

比特币價格的(de)上(shàng)上(shàng)下(xià)下(xià)φ¥,始終撩動著(zhe)每一(yī)個(gè)人♦∏α↓(rén)無比關切的(de)小(xiǎo)心髒。從("÷αcóng)去(qù)年(nián)初的(de) 800 美(měi)元左↑☆右,飛(fēi)漲到(dào)去(qù)年(nián)底到(dào) 197∏☆83.21 美(měi)元最高(gāo)點,不(bù)到(dào)1±&年(nián),便有(yǒu)将近(jìn) 25 倍的(de)升值速度。盡管÷↑₩‍眼下(xià)又(yòu)掉回 8000✔™ 多(duō)美(měi)元的(de)價格,但(dànβεΩ)價格差不(bù)多(duō)能(néng§φ¥ )搞出去(qù)年(nián)同期一(yī±≥)個(gè)數(shù)量級,币圈人(rén)士×€•“過去(qù)一(yī)年(nγ✘ián)比以往 10 年(nián)掙的(de)都(dōu)多(duō)&rd <★quo;,已經是(shì)不(bù)争的(de)事( φshì)實。

而對(duì)區(qū)塊鏈開(kāi)發者來(lái)說(shuō ¶),據說(shuō)也(yě)已經有(yǒu)拿(n ←≠á)到(dào)年(nián)新 500 ★λ>©萬的(de)天價。所以“跑步進入區∞★α>(qū)塊鏈”,已經成為(wèi)不(bùσλ )少(shǎo)程序員(yuán)的(de)共識。但(dàn)是(shì ≤‌&)看(kàn)過很(hěn)多(duō)遠(yuǎ↕​>n)離(lí),我們如(rú)何才能(néng)迅速上(σ♣shàng)手呢(ne)?國(guó)外(wài)網友(yǒ↓®'u) Ken Shirriff 在博客中分(fēn)享了(le)他(tā☆γ)在手動茶古劍比特币交易時(shí)的(de)代碼與對(duì)‌§↑比特币協議(yì)的(de)心得(de),區(qū)塊₹₹©鏈大(dà)本營編譯如(rú)下(xià)。

 

近(jìn)期,媒體(tǐ)行(xíng)業(yè)對πε↑‍(duì)比特币表現(xiàn)出極大(dà)的(de™ ±©)熱(rè)情,這(zhè)鼓舞(wǔ)著(zhe)我從(cóng)Ω♦β網絡底層的(de)數(shù)據流開(kāi)始,認真學習(xí)↑δ≈比特币的(de)工(gōng)作(zuò)原理(lǐ)。通(tōng)常人α™Ω€(rén)們會(huì)使用(yòng)錢(qián)包軟件(j><§iàn)來(lái)進行(xíng)比特币交易,錢(qi∞Ωán)包軟件(jiàn)在方便用(yòng)戶的(d∞Ω®e)同時(shí),向用(yòng)戶隐藏了(le)比特币的(d© ₩e)交易流程,而我想親自(zì)動手來(lá↓↔↕i)體(tǐ)驗比特币交易,我的(de)目标是(shì)用(yònεΩg)Python手動創建一(yī)筆(bǐ"≤)比特币交易,以十六進制(zhì)數(shù)據的(de ÷)形式将交易廣播到(dào)比特币網絡中,然後觀♠$₹察這(zhè)筆(bǐ)交易是(shì)怎麽被加入₹ 到(dào)區(qū)塊鏈中的(de)。事(shì)實證明(míng),↓✔≤↕這(zhè)個(gè)過程很(hěn)有(yǒu)趣,希望δσ♥♦你(nǐ)也(yě)對(duì)它感興趣。

 

在本篇文(wén)章(zhāng)中,首先我‍≠σ會(huì)對(duì)比特币進行(xíng)一(™φ☆¶yī)個(gè)簡單的(de)概述,之後,我會‍'β (huì)從(cóng)以下(xià)幾個(gè)方面帶領你±Ω(nǐ)們學習(xí)比特币:創建一(yī)個(g♥∑è)比特币地(dì)址(比特币中的(de)賬戶),進ε↔ 行(xíng)一(yī)筆(bǐ)比特币交易,簽φ'σ署交易,将交易廣播到(dào)比特币網絡中,最後等待交易的(de)σ$确認。

 

比特币簡述:

 

首先,我會(huì)介紹一(yī)下(xià)比特币系統是(shì)€& ↔怎麽運轉的(de),然後再深入探討(tǎ×α☆o)整個(gè)細節。比特币是(shì)一(yī)個(gè∞$★≈)基于點對(duì)點網絡的(de)電(diàn)子(zǐ)貨币,你×→(nǐ)可(kě)以用(yòng)現(xiàn)金(jīn)在網上(€→×₽shàng)購(gòu)買比特币,用(yòng)比特币向他(tā  ®)人(rén)轉賬,在有(yǒu)些(xiē₹​)商家(jiā),你(nǐ)可(kě)以像使用(£®yòng)支付寶一(yī)樣使用(yòng)比特币付款,當然,你εδ★(nǐ)也(yě)可(kě)以賣出所持有(yǒu)的(de)比®λ☆π特币換回現(xiàn)金(jīn)。

 

簡而言之,在比特币網絡中,分(fēn)布式賬本(區<>(qū)塊鏈)記錄并随時(shí)更新著(zhe)每個(gè)比特币的(de)ε ₽所有(yǒu)權。與銀(yín)行(xíng)不≤σ(bù)同的(de)是(shì),比特币并沒有(yǒ¶>↔u)與個(gè)人(rén)或個(gè)人(r>σ<én)的(de)賬戶綁定,相(xiàng)反的(de),比特币隻屬于一(yī₽<×‌)個(gè)個(gè)比特币地(dì)址,比如(rú):1KKKK6N2₩π♣1XKo48zWKuQKXdvSsCf95ibHFa。這(zhè)裡(lǐ¥ )你(nǐ)可(kě)能(néng)已經繞暈了(∏Ω ₹le),難道(dào)這(zhè)段字符中藏著(zhe)比特©‍币?當然不(bù)是(shì),比特币地(dì)址是(shδ ↓>ì)比特币網絡中的(de)一(yī)個(gè‌©®)身(shēn)份,也(yě)可(kě)以通(tōng)俗地($♣∏dì)說(shuō)是(shì)你(nǐ)在比特币中開(kāi)的(dβΩ±≠e)一(yī)個(gè)“銀(yín)行(xíng)賬戶&r± δ•dquo;,我們用(yòng)這(zhè)個(gè)&ldqu₽↕€o;賬戶”來(lái)進行(xíng)交易。在網站(zh€' δàn):blockchain.info中,你(nǐ)可(kě)以查到(×β​®dào)所有(yǒu)的(de)交易信息:

 

比特币賬戶信息

 

但(dàn)是(shì)怎麽證明(míng)這(zhè)個(gè↕≤ )賬戶是(shì)我的(de)呢(ne),不(bù)急,先往下(xià)看§☆π₽(kàn),你(nǐ)的(de)疑問(wèn)我會Ω↑↕±(huì)為(wèi)你(nǐ)一(yī)一(yī€→≤)解答(dá)。

 

比特币交易

 

如(rú)何像使用(yòng)現(xiàn)金(jīn)一(yī)樣使用(yò∞βλ↓ng)比特币呢(ne)?答(dá)案是(shì)創建一(y♣<ī)筆(bǐ)交易。在一(yī)筆(bǐ)交易中,比特币的(de)所'✘有(yǒu)者(上(shàng)文(wén)提到(dào)過比特币的(de)所¶±有(yǒu)者是(shì)比特币地(dì)址)将所有☆←'(yǒu)權轉移到(dào)一(yī)個(gè)新的(de)比₽♠♣‍特币地(dì)址。比特币的(de)一(yī)→∑個(gè)颠覆性創新就(jiù)是(shì)通( ∏ <tōng)過鼓勵節點記賬(也(yě)叫礦工(gōng)挖礦),将交易記↑✘→♣錄放(fàng)在一(yī)個(gè)分(fēn)γ£布式的(de)數(shù)據庫中。交易被集合在區(qū)©γ÷塊中,大(dà)概每十分(fēn)鐘(zh↕♥"ōng)比特币網絡中産生(shēng)一(yī)個(g≤&φ☆è)新的(de)區(qū)塊,成為(wèi)Ω&δ交易記錄的(de)一(yī)部分(fēn),稱為(wèi)區(q₩∑↔‍ū)塊鏈。加入到(dào)區(qū)塊鏈中的(de)交易可(kě)以→₩ 被認為(wèi)是(shì)一(yī)筆(bǐ)Ωε♦成功的(de)交易。現(xiàn)在問(wèn)題來(lái)了(le),§≤誰來(lái)給你(nǐ)記賬呢(ne)?是(shì)礦工(§↓"gōng),礦工(gōng)的(de)挖礦過程就("↕Ωjiù)是(shì)在往區(qū)塊鏈中記賬,礦工(gōng)要(β→yào)核實每筆(bǐ)交易是(shì)否正确,核實完後,礦工(gōngα¶λ)們就(jiù)開(kāi)始算(suàn)一(yī)道(dào)很(h £↓ěn)難的(de)數(shù)學題(密碼學中♠§"的(de)哈希函數(shù)),最早算(suàn)出答(dá)案的(de)人≈α(rén)就(jiù)能(néng)生(shēng)成一(♥φyī)個(gè)區(qū)塊,也(yě)叫挖出了(le)一(yī)個₩↑↓(gè)新的(de)區(qū)塊,這(zhè)個(gè)區(qū)塊将γ☆≠♥成為(wèi)區(qū)塊鏈的(de)新‌α‌一(yī)部分(fēn)。

 

也(yě)許你(nǐ)會(huì)問(wèn)了(≠≤le),明(míng)明(míng)是(shì)記賬,幹著(z≠&δhe)會(huì)計(jì)的(de)活,為(wèi)什(shé→ n)麽要(yào)叫挖礦呢(ne)?和(hé)傳統的(d∞♣↓₩e)在地(dì)下(xià)挖礦石一(yī)樣÷←★ ,比特币挖礦也(yě)是(shì)會(h™↔↑≥uì)有(yǒu)收獲的(de)。挖礦是(shì→☆β)一(yī)種新發行(xíng)比特币的(de)過程♣>,當前,每挖到(dào)一(yī)個(gè)礦&§∑,礦工(gōng)會(huì)得(de)到(dào)∑ 系統獎勵的(de)12.5個(gè)比特币,按目前一(yī)個(gè)比>✘ 特币接近(jìn)一(yī)萬美(měi)元的(de)市(shì)價,這(↔∏‌∞zhè)就(jiù)是(shì)一(yī)筆(bǐ)1€™'2.5萬美(měi)元的(de)巨款。此外(wài),礦工(gōng)還(há→≠i)可(kě)以獲得(de)本區(qū)塊中βα所有(yǒu)的(de)交易費(fèi),舉例來(lá¥÷i)說(shuō),在高(gāo)度為(wèi)51258★ε₩7的(de)區(qū)塊中,幸運的(de)礦工(gōng)總共收獲了(le)‌≠$¶12.829個(gè)比特币。正因如(rú)此,礦工(gōng)之間"ε(jiān)的(de)競争十分(fēn)激烈,采礦的(de)難度與礦工(gō↓λ€ng)間(jiān)激烈的(de)競争是(shì)比特币安全的(de)重要←>(yào)保證,因為(wèi)這(zhè)樣可(kě)以保證沒有"↑(yǒu)壞人(rén)能(néng)操縱系統。

 

點對(duì)點網絡

 

比特币并沒有(yǒu)一(yī)個(gè)中央服務器(qì)  ₩,相(xiàng)反,比特币在一(yī)個(gè)點對(duì)點網絡±≈φ←中運行(xíng)。如(rú)果你(nǐ)運行(xíng)一(yī✔₩)個(gè)比特币節點,那(nà)你(nǐλ‌α)就(jiù)成了(le)網絡的(de)一(yī∏₩)部分(fēn)。比特币網絡中的(de)節點彼此交換自(zì)己存儲§$✔ 的(de)交易,區(qū)塊,以及IP地(dì)址信息(用(yònλ♥g)于節點間(jiān)建立連接互相(xiàngφ≥≥→)通(tōng)信)。當你(nǐ)第一(yī)次連接到(dào)比σ>÷特币網絡,你(nǐ)的(de)節點會(huì)從(cóng)随機(jī)挑選的γ↕♦ (de)節點中下(xià)載區(qū)塊鏈的(de)信息。反過來(láiσ♥),你(nǐ)的(de)節點也(yě)會(huì)向後加入者σ≠≤↑提供信息。當你(nǐ)要(yào)創建一(yī)筆(bǐ)比特币交‌•×易時(shí),你(nǐ)要(yào)把這(zhè)筆(bǐ)交易發送給一↔↕(yī)些(xiē)節點,這(zhè)些(xiē​↔<φ)節點會(huì)在比特币網絡中廣播這(zhè♠π♠)筆(bǐ)交易,直到(dào)全網都(dōu)收到(d✔&σào)這(zhè)筆(bǐ)交易。礦工(g&α☆<ōng)們會(huì)收集你(nǐ)的(d♦♦e)交易信息,生(shēng)成一(yī)個(gè)含有(yǒu)你(n✔&'ǐ)這(zhè)筆(bǐ)交易的(de)區(qū)塊,向全網廣播,這(z♦δhè)時(shí),你(nǐ)的(de)節點也(y₹λ™ě)會(huì)收到(dào)這(zhè)個(gè)✔↕區(qū)塊信息,通(tōng)過驗證,這(zhè)筆(bǐ)>↕交易被加入到(dào)了(le)區(qū)塊鏈中,£☆™你(nǐ)就(jiù)交易成功了(le)。 

 

加密技(jì)術(shù)

 

現(xiàn)在回到(dào)證明(míng)比特>>↔↔币賬戶是(shì)誰的(de)這(zhè)個(gè)問(wèn)題。比特币使™€↑®用(yòng)數(shù)字簽名技(jì)術(shù)以确保隻有(yβ¶ǒu)比特币賬戶的(de)所有(yǒu)者才能(néng)使用(yòng)↔§£賬戶中的(de)比特币。比特币地(dì)址的(de)所有♠™ ≤(yǒu)者擁有(yǒu)與該地(dì)址相(xiàng)匹配的↕™(de)私鑰,當花(huā)費(fèi)比特币時×€α(shí),你(nǐ)用(yòng)要(yào)這(zhè)個(gè)↑∏私鑰在交易上(shàng)簽名,證明(míng)自(zì)己是(shì)這(×✘₩∑zhè)個(gè)賬戶的(de)所有(yǒu)者。這(zhè)↓ε有(yǒu)點像現(xiàn)實生(shēng)活®"≠中的(de)蓋章(zhāng),蓋章(zhāng)就(jiù)意味著(z©★±§he)授權。怎麽驗證呢(ne),公鑰與比特币賬戶相× ±(xiàng)關聯,用(yòng)公鑰就(jiù)可(kě)以☆<驗證簽名是(shì)否正确。這(zhè)樣就(jiù)解δ' ₩決了(le)比特币賬戶是(shì)誰的(de)這(zhè)個(gè)問(wèn∞∑↑±)題。

 

怎麽來(lái)區(qū)分(fēn)不(bù)同的(d©≠♥e)交易呢(ne)?交易和(hé)區(qū)塊都(dōu)↓• ±使用(yòng)密碼學上(shàng)的(de)哈希值進行(xín&α♥g)索引,是(shì)不(bù)是(shì)有(yǒu)點耳熟,對(duì),¶↑在比特币協議(yì)中,多(duō)處使用(yòng)λ>✔到(dào)了(le)哈希函數(shù),<∞¥π礦工(gōng)們剛才算(suàn)的(de)數(shù)學題就(j¶&iù)是(shì)在算(suàn)哈希函數(shù)。

 

比特币協議(yì)探究

 

在接下(xià)來(lái)的(de)文(wén)章(zγ∏hāng)裡(lǐ),我将逐步介紹我是(shì)怎樣手動進行(≥♦♣xíng)一(yī)次比特币交易的(de)。首∑€​先,我生(shēng)成了(le)一(yī)個(gè)♣λ比特币賬戶以及對(duì)應的(de)公鑰★→ε,私鑰。接下(xià)來(lái)我發起了(₩α¥ le)一(yī)筆(bǐ)比特币交易,我向這(zhè)個(gè)新生(shēn↑☆g)成的(de)賬戶轉了(le)一(yī₽→✘ )小(xiǎo)筆(bǐ)比特币。期間(jiān)手動'☆簽署這(zhè)筆(bǐ)交易很(hěn)困難,它花(huā)費(fèiλ≠÷♠)了(le)我很(hěn)多(duō)的(dφ‍e)時(shí)間(jiān)。最後,我将這(zhè)筆(π×↑bǐ)交易發送到(dào)比特币網絡,等待它被加入區(qū)塊鏈。本文♠ (wén)的(de)其餘部分(fēn)會(huì)詳細地(dì)介紹這©♠↑‌(zhè)些(xiē)步驟。

 

事(shì)實證明(míng),手動進行(xíng)比特∞↔币交易比我想象中的(de)更加困難。正如(rú)你α♠§"(nǐ)所看(kàn)到(dào)的(de),比特币的(de)協議(yì)有₩®(yǒu)些(xiē)許混亂:它使用(yòng)了(le)大(dà)端格式數£÷(shù)字(高(gāo)位編址,将高(gāo)序字節存儲在起始♣♦§'地(dì)址),小(xiǎo)端格式數(shù)字(低(d$♥ī)位編址,将低(dī)序字節存儲在起始位置),固定長(cháng)§•度數(shù)字,可(kě)變長(cháng)度數(shù)字,自(zì)定α&義編碼格式,DER編碼格式以及各種加密算(suàn¶∑©)法。因此,僅僅是(shì)将數(shù)據轉換為(wèi)α α正确的(de)格式就(jiù)浪費(fèi)了(le)很(hěn)多(&Ω∏duō)時(shí)間(jiān)。

 

我遇到(dào)的(de)第二個(gè)難題就(jiù)是(s±☆÷ hì)加密,嘗試一(yī)下(xià)手動加密γ ®,你(nǐ)就(jiù)會(huì)發現(xiàn)密碼學對(duì)人(r‍₩₩☆én)們多(duō)不(bù)友(yǒu)好(hǎo),甚至可(kě)以說(s$>σ×huō)是(shì)無情。即使你(nǐ)隻輸錯(cuò)了Ωγ¥(le)一(yī)個(gè)字節,交易就(jiù)會(huì)因出✘×♥≠錯(cuò)被拒絕,而且它不(bù)會(huì)告訴‍'你(nǐ)哪裡(lǐ)出錯(cuò)了(le),你(nǐ)隻能(néng&"£)重來(lái)。

 

最後,手動簽署交易的(de)過程也(yě)比想象中難得(de)多(du₽₹ ō),簽署交易時(shí)每個(gè)環節φ✔↓ε都(dōu)必須零失誤,要(yào)麽又(yòu)要(yào≠←≠π)退回重來(lái)。

 

比特币地(dì)址和(hé)密鑰

 

第一(yī)步,我創建了(le)一(yī)個(gè)比特币地(dì)址。通(♠₹tōng)常情況下(xià),人(rén)們¶£‌♥都(dōu)是(shì)使用(yòng)比特币客戶端軟件(®↓jiàn)來(lái)創建比特币地(dì)址和(hé)與♣×之相(xiàng)關的(de)密鑰。本著(zhe)學習(xí)的(de)态→®φ∑度,我寫了(le)一(yī)些(xiē)Python代碼來← ☆(lái)生(shēng)成比特币地(dì)址,∑&從(cóng)而揭示地(dì)址創建的(de)機(jī)理(lǐ)。•≠&®

 

比特币使用(yòng)了(le)一(yī)系列的(de)密鑰和(hé∑↔$)地(dì)址,下(xià)圖解釋了(le)它們的(dσ ¶φe)關系。首先你(nǐ)要(yào)創建一(yī)個($"φ×gè)随機(jī)的(de)256位的(de)私鑰,這ε​♣±(zhè)個(gè)私鑰用(yòng)于在✘§₩σ花(huā)費(fèi)比特币時(shí)簽署交♣¥↑ 易。因此,私鑰必須保密,否則你(nǐ)的(d¶​®e)比特币可(kě)能(néng)會(huì)被盜用(yòn♦δ£φg)。

 

橢圓曲線數(shù)字簽名算(suàn)法(Elliptic Cuγ™rve Digital Signature ♥λ>Algorithm,ECDSA,美(měi)國(guó)政₽ ₽&府的(de)标準,接下(xià)來(lái)我們會(huì)討(tǎo)論它)✘>會(huì)從(cóng)私鑰中生(shēng)成☆‌一(yī)個(gè)512位的(de)公鑰,這(zε hè)個(gè)公鑰用(yòng)于驗證交易的(de)簽名↕β☆ 。但(dàn)不(bù)方便的(de)是(shì),比特币σ≠βφ協議(yì)中需要(yào)在這(zhè÷©"​)個(gè)公鑰上(shàng)添加了(le)前綴04,這(zhè)個(®δ&±gè)公鑰在交易簽署之前不(bù)會(huì)被洩露,不(£→γαbù)像其它系統中公鑰就(jiù)是(shì)為(wèi)¥©了(le)公之于衆的(de)。

 

比特币地(dì)址與公鑰的(de)關系

 

下(xià)一(yī)步就(jiù)是(shì)生(shēng)成與他(tā)λ↕人(rén)交易時(shí)使用(yòng)的→>>(de)比特币地(dì)址了(le)。512位的(de)公鑰太長σ <(cháng)不(bù)方便使用(yòng),因此™γ♣ 使用(yòng)SHA-256和(hé)RIPE✔φMD哈希算(suàn)法将其縮小(xiǎo)為(wèi)160位。然後使用(y<↕òng)比特币定義的(de)Base58Check 編碼将密 ↑γ‌鑰編碼為(wèi)ASCII(American S'±∑tandard Code for Information I×γδ<nterchange,美(měi)國(guó)信息交換标準代碼)格式。得(d±δ±e)到(dào)的(de)地(dì)址(例如(rú)上(shàng)文(wén✘®≤Ω)中的(de):1KKKK6N21XKo48zWKuα"÷☆QKXdvSsCf95ibHFa)就(jiù)是(shì)你±♥(nǐ)接收别人(rén)比特币時(shíδ←φ↕)要(yào)發布的(de)地(dì)址。需要₽π₩(yào)注意的(de)是(shì),你(n'↓←♠ǐ)無法從(cóng)比特币地(dì)址中×δ→λ複原出公鑰或私鑰。如(rú)果你(nǐ)丢失了(le)你®γ≈(nǐ)的(de)私鑰(比如(rú)說(★←€>shuō)你(nǐ)把私鑰存在你(nǐ)的(de)硬盤上(shàng),↔§∏但(dàn)硬盤丢失),你(nǐ)的(de)比特币±αβ将永遠(yuǎn)丢失。

 

最後,錢(qián)包交換格式密鑰(WIF)₩✔♥用(yòng)于将私鑰添加到(dào)你(nǐ)的(de)♥ 錢(qián)包軟件(jiàn)中,這(zhè)隻是(sh¥​ì)将私鑰進行(xíng)Base58Check編碼轉換為(wèi)↓₽≈✘ASCII格式,這(zhè)一(yī)步是(shì)可(kě)逆的(dε §☆e),而且很(hěn)容易經過逆變換恢複出256位的(de)私鑰。(圖↑Ω$中有(yǒu)我的(de)私鑰,我很(hěn)好(hǎo)奇是(shì)否有♠§(yǒu)人(rén)會(huì)用(yòng)我的(de)私鑰去(qù)偷(©¶通(tōng)過私鑰簽署交易,從(cóng)而轉走)我那(nà)價值80美(₹¥σměi)分(fēn)的(de)比特币,然而真有(yǒu€✔✔)人(rén)那(nà)麽做(zuò)了(le),可& σ↔(kě)以在

https://blockchain.info/add​♠•ress/1KKKK6N21XKo48zWKuQKXdvSsCf95ibHFa®★∞ 看(kàn)到(dào),也(yě)算(™εφsuàn)是(shì)為(wèi)教學做(zuò)貢獻了(le∑×)。)

 

總之,共有(yǒu)三種密鑰:私鑰,公鑰,公鑰的(de)哈希值,經過使用(yδ←☆→òng)Base58Check編碼,它們對(duì)‌γ ‍外(wài)都(dōu)是(shì)以ASCII格式表示。私鑰是(sγσ hì)其中最重要(yào)的(de)密鑰,因為(wèi)花(huā)π ★費(fèi)比特币時(shí)需要(yào)私鑰簽署交易,而且其他(tā☆δ)的(de)密鑰都(dōu)可(kě)以從(£δ→cóng)私鑰中産生(shēng)。公鑰的(de)哈希♦±值就(jiù)是(shì)你(nǐ)們剛看(kàn)的(d€​£e)的(de)比特币地(dì)址。

 

我使用(yòng)下(xià)面的(de)代碼片段來(lái)生σ™₽•(shēng)成WIF格式的(de)私鑰和(>σ♥←hé)地(dì)址。私鑰隻是(shì)一(yī©×)個(gè)随機(jī)的(de)256位的(de)數(shù)字≤σ,使用(yòng)橢圓曲線數(shù)字簽名算(suàn)法從®Ω&(cóng)私鑰中生(shēng)成公鑰,公鑰使用(yòng)SHA​$-256算(suàn)法,RIPEMD-160算(suàn)法進行(xín©≥"g)哈希計(jì)算(suàn),再經Base58編≠π€☆碼并進行(xíng)校(xiào)驗後得(de)到(dβλ₽ào)比特币地(dì)址。最後,私鑰用(yòng)Base58Ch₩₹"↓eck編碼以生(shēng)成用(yòng×→"α)于将私鑰輸入錢(qián)包軟件(jiàn)的(de)WIF編碼。注意,這(↔>zhè)段Python随機(jī)函數(shù)代碼在密碼學上(shàn§¥✔g)安全性并不(bù)高(gāo),如(rγ®ú)果你(nǐ)想要(yào)嘗試這(zhè)一(yī)步驟,建議(yì)使用φ←±☆(yòng)更安全的(de)錢(qián)包軟件(jiàn)來(lái)×€生(shēng)成比特币地(dì)址和(hé)密鑰。

 

def privateKeyToWif(key_hex):    ₹     retu± rn utils.base58CheckEncod↕↔✔e(0x80, key_hex.decode('he∑×x'))    def priv↑↔​ateKeyToPublicKey(s): ​​&α   sk = ecdsa.≈εβSigningKey.from_string(s.¶☆♣↑decode('hex'), curve=ecdsa.SECP≠σ₽ 256k1)    vk ✘↕​✘= sk.verifying_key    
   return ('\04''→ + sk.verifying_key.to™♦'_string()).encode('hex') &★<nbsp;
 def pubKeyToAddr(s):   &nbs←'↓p;ripemd160 = hashlib.new(↓♠ ×9;ripemd160')    ri©≥™pemd160.update(hashl≠∏"₽ib.sha256(s.decode('&÷hex')).digest())    
   return utils.base58C♥÷☆₩heckEncode(0, ripemd160.d™‍igest())

def keyToAddr(s):    
   return pubKeyT'£oAddr(privateKeyToPublicKey(s))

# Warning: this random Ω>×function is not cryptographically stron'₽±Ωg and is just for example
private_key = ''.jo"•in(['%x' % random.randranδ♣ge(16) for x in range(0, 64)]) pri‌$Ωnt keyUtils.privateKeyToWif(₩€©∑private_key) print keyUtils.keyToAddr(p$§rivate_key)

keyUtils.py

 

從(cóng)內(nèi)部分(fēn)析一(y ₩≈♣ī)筆(bǐ)交易

 

交易是(shì)比特币系統的(de)基本操作(zuò),也(yě)許你∞×(nǐ)會(huì)認為(wèi)交易就(jiù)是(shì)簡單地$₩¶↓(dì)把比特币從(cóng)一(yī)個(g•>®è)地(dì)址轉移到(dào)另一(yī)個(gè€✔✔÷)地(dì)址,但(dàn)交易其實并不(≈∏bù)簡單。一(yī)筆(bǐ)交易包含一(yī)個(gè)或多(duō)σβ個(gè)輸入和(hé)輸出,交易中的(de)每個(€✘gè)輸入的(de)地(dì)址都(dōu)φΩ✘提供比特币,每個(gè)輸出的(de)地(dì)址都(↔↓¶≈dōu)接受比特币。

 

一(yī)筆(bǐ)簡單的(de)比特币交易,交易C花(huā)σ★費(fèi)了(le)從(cóng)交易A和(hé)交易B獲得(d'∞e)的(de)0.008個(gè)比特币,其中0.✘>ΩΩ001個(gè)比特币被當作(zuò)交易費(fèi)付給礦工(gōn↔σ→g)

 

上(shàng)圖顯示了(le)一(yī‍≠Ω)筆(bǐ)簡單的(de)比特币交易“C”,在這(zh πè)筆(bǐ)交易中,有(yǒu)0.005個(gè)比特币是(shì)在交®≥​易A中獲得(de)的(de),0.003個(gè)比特币是(shì)在交易σ↕✔ B中獲得(de)的(de)。(圖中箭頭是(shì)由♣♠π<新交易的(de)輸入指向得(de)到(dào)這(zhè)些•♥(xiē)比特币的(de)交易的(de)輸出,所以比∞₹∑λ特币的(de)流向是(shì)逆著(zhe)箭頭方向的(deπ ♥)。)對(duì)于輸出,有(yǒu)0.003個(gλ​☆è)比特币給了(le)第一(yī)個(gè)比特币地✘≈Ω(dì)址,有(yǒu)0.004個(gè)∏¥¶±比特币給了(le)第二個(gè)比特币地(dì)址,σ÷©>剩餘的(de)0.001個(gè)比特币作(zuò)為(wèi)交易費(β∑¶fèi)付給礦工(gōng)。請(qǐng)注意,本次交易并沒有(÷₩yǒu)影(yǐng)響到(dào)在交易A中另一(yī)個(gè)輸出為‍♥±•(wèi)0.015的(de)比特币。 

 

在一(yī)筆(bǐ)交易中,輸入的(de)比特币地(dì)址必須™↔™ 花(huā)出所有(yǒu)的(de)比特币,>₽£ 假如(rú)你(nǐ)在之前的(de)交易收到(dào)了(le)1γ✘$→00個(gè)比特币,但(dàn)你(nǐ)隻想£•✘花(huā)1個(gè)比特币,創建這(zhè)筆(bǐ)交易你(nǐ)× 必須花(huā)完所有(yǒu)的(de)£β100個(gè)比特币,那(nà)剩下(xià)的π™∞(de)99個(gè)比特币怎麽辦呢(ne)?解決方案就(jiù)是(shì)β₹∑在交易中再增加一(yī)個(gè)輸出,将剩餘的(de)99個‌β(gè)比特币轉給自(zì)己。這(zhè)樣你(☆♠₹nǐ)就(jiù)可(kě)以花(huā)費(fèi)任意數(sh♣™≈≤ù)額的(de)比特币。 

 

通(tōng)常交易要(yào)支付交易費(fèi),如(rú)♠©↓↔果一(yī)筆(bǐ)交易中輸入的(de)比特币總和(hé)大(d∞♠à)于輸出的(de)比特币的(de)總和(hé),剩餘的(de)費(fè☆♣i)用(yòng)就(jiù)是(shì)給礦工(gōng)的(de)交易費♥ε"←(fèi)。這(zhè)筆(bǐ)費(fèλ€™☆i)用(yòng)并沒有(yǒu)明(míng)确要(yào)求,但‌≥‌→(dàn)是(shì)對(duì)于礦工(gōng)而言,沒β>×有(yǒu)交易費(fèi)的(de)交易就(jiù)會(±←→αhuì)被列為(wèi)低(dī)優先級交易,可(kě)能(néngε÷)要(yào)等上(shàng)幾天才會(huì)被處理(lǐ)甚™§γ÷至被礦工(gōng)直接丢棄。交易費(fèi)通(tōnΩ✔g)常并不(bù)高(gāo),但(dàn)它可(kě)能(néβ♣λπng)影(yǐng)響著(zhe)你(n ↓‍ǐ)的(de)交易。

 

手動創建一(yī)筆(bǐ)交易

 

如(rú)下(xià)圖所示,在我的(de)實驗中我發起了(le)一(y&÷'ī)筆(bǐ)隻有(yǒu)一(yī)個(£÷gè)輸入一(yī)個(gè)輸出的(d¶₹∞§e)交易。我在Coinbase上(shàng✔¶σ)買了(le)一(yī)些(xiē)比特币,并将0.0010÷π1234個(gè)比特币放(fàng)入地(dì)址:

1MMMMSUb1piy2ufrSguNUdFmAcvqrQF8MΩ™5中,這(zhè)筆(bǐ)交易哈希為(wèi"δ↓):

81b4c832d70cb56ff957589752eb4125a4caδεπb78a25a8fc52d6a09e5bd4404d4 ♣π8,我的(de)目标是(shì)創建一(yī)筆(bǐ)交易,将©'≥這(zhè)些(xiē)比特币轉入我的(de)另一(yī)個(gè)地(dα∞♥ì)址:

1KKKK6N21XKo48zWKuQKXdv↓₹SsCf95ibHFa,扣除0.0001 ‌∞個(gè)比特币的(de)交易費(fèi)後,目标地(dì)址将獲得(de)γ↑$0.00091234個(gè)比特币。

比特币交易結構實例

 

 Blockchain.info上(shà★&≤ng)的(de)交易記錄

https://blockchain.info♥λ/address/1MMMMSUb1piy2ufrSguNUd®£FmAcvqrQF8M5?filter=4

 

按照(zhào)協議(yì)标準,創建這(zhè)筆( ®₩πbǐ)交易很(hěn)簡單。如(rú)下(xià)表所示,這(zhè)筆(bǐ♠₩✔)交易隻有(yǒu)一(yī)個(gè)輸入,源÷δφ 自(zì)于81b4c832d70cb56ff95©'∑7589752eb4125a4cab78a25a8fc52d6a÷$09e5bd4404d48中的(de)輸↓♥×出0(第一(yī)個(gè)輸出)。輸出為(wèi)0.000"‍91234個(gè)比特币(91234在十六進制(zhì)中用(∞α∞yòng)0x016462表示),它以小(xiǎo)端格式"™™存儲在值區(qū)域中。加密過程中的(de)scriptSig和(hé)scr≤<iptPubKey較為(wèi)複雜(zá),我們稍後再做(zuò)φ&討(tǎo)論。

version

01 00 00 00

input count

01

input

previous output hash(₹β♣♣reversed)

48 4d 40 d4 5b 9e a0 ™₹↑ d6 52 fc a8 25 8a b7 ca a4 25 →≥≤≈41 eb 52 97 58 57 f9 §≤∑6f b5 0c d7 32 c8 b4 81

previous output index

00 00 00 00

script length

 

scriptSig

script containing signature

sequence

ff ff ff ff

output count

01

output

value

62 64 01 00 00 00 00 00

script length

 

scriptPubKey

script containing destination address

block lock time

00 00 00 00

這(zhè)是(shì)我生(shēng)成交易使用(yòng)的(de)代≠‍ 碼,這(zhè)段代碼隻是(shì)把數(shù)據打包成​∞二進制(zhì)文(wén)件(jiàn)。簽署交易較為(wèi)困難,我們等♠​一(yī)會(huì)兒(ér)再說(shuō)。

 


 

# Makes a transaction from ★₹α∞the inputs# outputs is a list of [redem♠&≥βptionSatoshis, outputScript] ∏σ
def makeRawTransaction(≥₹€outputTransactionHash, sou₩ <rceIndex, scriptSig, outputs↔≤​♦):    
          d<♣ef makeOutput(data):   &nbs₽δ€p;      €φ γ     redemptionSatos'¶his, outputScript = data
         ₽​     return (struct.pack(&quo≤≤☆t;<Q", redemption‍γ±Satoshis).encode('hex'∞✔) +
       →♦;      '₹σα '%02x' % len(out×®βputScript.decode('hex↓ε♥¶')) + outputScript)    φ"α↓;       formatted↔∞♦Outputs = ''.joinΩ§©(map(makeOutput, out∑★puts))
         ↔α>•; return (   &nδ≥bsp;    
          &n÷ λbsp;   "01000000" + # 4>÷♥ bytes version   &​‌nbsp;         &nbs∑ p; "01" + # varint for n '"umber of inputs  •£         &nbs∏ ☆p;   outputTran£©sactionHash.decode('hex‌®σ≤')[::-1].encode('hex∞↓') + # reverse outputTr®☆±ansactionHash       &nbs§∏p;       struct.$®→pack('<L', sourceInd∑✘β ex).encode('hex♠φ9;) +        
        &nbs↑∑α↓p;     '%02x' % len(÷ε♣scriptSig.decode('hex'§‍★)) + scriptSig +      ∞δ'  
         <♠∞;     "fffff≈€fff" + # sequence  "π      ∏✘¶       "↓φ→ ;%02x" % len(outputs) + # number o±€‍±f outputs     &nbλσsp;      ≥δ   formattedOutpu‍♣±ts +       &nb≤¥sp;
        &nγ₩bsp;     "00¶φ☆000000" # lockTime
          &nb♣♦ ★sp;   )

txnUtils.py

 

比特币交易怎樣簽署

 

下(xià)圖為(wèi)我們簡單描述了(le)交易™>是(shì)如(rú)何簽署并相(xiàng)互連接的(de)。針對(dα₩§uì)中間(jiān)這(zhè)筆(bǐ)從(cóng)比特币地(dì)址B₹ π轉賬到(dào)比特币地(dì)址C的(♥β×↔de)交易。交易的(de)內(nèi)容(包括前一(yεπī)個(gè)交易的(de)哈希值(索引))被進行‌γ≥(xíng)哈希計(jì)算(suàn)并用(yòng ₹)B的(de)私鑰簽名。另外(wài),B的(de) →公鑰也(yě)被包含在了(le)交易中。 

 

通(tōng)過執行(xíng)幾個(gè)簡單運算(suàn),任何人(r±λλén)都(dōu)能(néng)驗證B是(shì)否簽署了γ• (le)這(zhè)筆(bǐ)交易。首先,B的(÷σde)公鑰與之前收到(dào)這(zhè)筆(bǐ)¶‍€比特币交易的(de)地(dì)址做(zuò)驗證,證明(míng)B§♣的(de)公鑰有(yǒu)效。(正如(rú)前面所說(shuō)的(de)✘ &✘,地(dì)址很(hěn)容易從(cóng)公鑰中計(jì)算'→ ∞(suàn)獲得(de))。接下(xià)來(£♥¥✔lái),可(kě)以通(tōng)過B的(de)公鑰驗證B交易簽名的(d≥€e)真僞。這(zhè)些(xiē)步驟能(néng₽"φ)确保交易的(de)有(yǒu)效性和(h‍→​δé)交易得(de)到(dào)B的(de)授權。比特币于衆不>★ (bù)同的(de)一(yī)點是(shì),B的(de←±™≈)公鑰在B發起交易之前是(shì)不(bù)公開(®∑kāi)的(de)。 

 

在比特币系統中,比特币通(tōng)過區(qū)塊鏈上(shàng)的(de)₩>±≥一(yī)筆(bǐ)筆(bǐ)交易在不(bù)同的(de)σ♠地(dì)址間(jiān)傳遞。區(qū)σλ♦塊鏈上(shàng)的(de)每一(yī)筆(bǐ)交易都(dōu)能(né↕£$"ng)被驗證以确保比特币交易的(de)有(y<≤©ǒu)效性。

 

比特币腳本語言

 

你(nǐ)可(kě)能(néng)會(huì)以為(wèi)僅僅通(tōng​↓)過在交易內(nèi)容中附上(shàng)簽名就Ωβ'>(jiù)可(kě)以簽署比特币交易,其實不(bù)然,這(z₩≠εhè)個(gè)過程十分(fēn)複雜(z€≤$á)。實際上(shàng),每一(yī)筆(bǐ)交易中都 ≠ (dōu)包含一(yī)個(gè)“小(xiǎo)程序&rdq₹≤¥uo;,用(yòng)于确認交易是(shì)否有(y✘↔&πǒu)效。這(zhè)個(gè)“小(≈ xiǎo)程序”用(yòng)→€腳本語言寫成,通(tōng)過這(zhè)種基于堆棧的(de)比特币腳γ♥ 本語言,我們可(kě)以應對(duì)許多(duō)複雜Ω "(zá)的(de)比特币支付場(chǎng)景。例如(rú),托管'ε₩系統可(kě)以設定隻要(yào)經過三分(fēn)之二≠ 的(de)用(yòng)戶授權,就(jiù)可(kě)執行(xíngφδβ≠)交易的(de)規則,也(yě)可(kě)以設置其他(tā)的(de)合約。&×σ‍ nbsp;

 

腳本語言十分(fēn)複雜(zá),大(dà)約有(yǒu)80種操作(zσ™÷™uò)碼,包括算(suàn)數(shù)計÷÷σ&(jì)算(suàn),按位操作(zuò),字符串處理(l≠ε'☆ǐ),條件(jiàn)語句和(hé)堆棧操作(zuò)。腳本語言✘→★↓也(yě)包含一(yī)些(xiē)必要‍←<(yào)的(de)密碼學操作(zuò)φ α (SHA-256,RIPEMD等等)作(‍Ω¥zuò)為(wèi)原語(原語是(shì) ₹☆α執行(xíng)過程中不(bù)可(kě)被打斷的(de)基本操作(zuò),¥↕你(nǐ)可(kě)以理(lǐ)解為(wèi)一(yī)段代碼)。為→≥☆(wèi)了(le)确保腳本語言可(kě)以運行•®♥φ(xíng)完畢自(zì)動退出,該語言不(bù)支持任何±≠♦ε循環操作(zuò),因此它不(bù)是(shì)圖靈完備的(de)。然± λ而,實際上(shàng),它隻支持少(shε>ǎo)數(shù)類型的(de)交易。 

 

前一(yī)個(gè)交易中的(de)腳本稱為(wèi)script≈>PubKey,當前交易中的(de)腳本稱為(wèi‍→ )scriptSig。要(yào)驗證交易時(shí),先執行(xí♣ ₩•ng)scriptSig,然後再執行(xíng)scriptPubKey。←♦π如(rú)果兩個(gè)腳本都(dōu)成功執行(xíng),交易就(ji♠ β☆ù)被認定為(wèi)有(yǒu)效,交易中的(de)比特‌£ε✘币就(jiù)可(kě)以成功花(huā)出。否則,交易無效。要(yào)×π注意的(de)是(shì)前一(yī)個(gè)交易中的( ≤§Ωde)scriptPubKey規定了(le)花(huā)費(fèi)比&∑特币的(de)條件(jiàn),當前交易的(de→¶δ•)scriptSig必須滿足這(zhè)↑λ₹個(gè)條件(jiàn)。 

 

在一(yī)個(gè)标準的(de)交易中,scri¥€Ω♠ptSig腳本将從(cóng)私鑰中生(shēng)成的(de)簽名并壓入☆♣堆棧中,再壓入公鑰。接下(xià)來(lái)scriα£÷ptPubKey腳本會(huì)執行(xíng)運算(suàn)先¶✘驗證公鑰的(de)有(yǒu)效性,再驗證簽名α↕的(de)有(yǒu)效性。

 

正如(rú)腳本中所表示,scriptSig:

 


 

PUSHDATA
signature data and SIGHASH_ALL
PUSHDATA
public key data

 

scriptPubKey:

 


 

OP_DUP OP_HASH160 PUSHDATA Bitcoin a☆®®ddress (public key hash) OP_Eφ​QUALVERIFY OP_CHECKSIG

 

當這(zhè)段代碼執行(xíng)時(shí),PUSHDATA操作(☆←↑zuò)首先會(huì)把簽名壓入堆棧,接著(zhe)把公 →鑰壓入堆棧。OPHASH-160操作(zuò)• 計(jì)算(suàn)公鑰的(de)160位哈希值,σ PUSHDATA操作(zuò)再把交易中的(de)輸‍ ×λ入地(dì)址(輸入賬号)壓入堆棧,然後,OP-EQUALVERIFY操 ε'作(zuò)驗證驗證前兩個(gè)堆棧中的(de)值是(shì)否Ω"₽相(xiàng)等(驗證這(zhè)筆(bǐ)交易中你(nǐ) ¥'<使用(yòng)的(de)比特币是(shì)否屬于你(nǐ)自(zì)己)-‌‍如(rú)果公鑰的(de)哈希等于之前交易中的(de)輸出地¥αδ"(dì)址,這(zhè)就(jiù)證明(míng)公鑰是(shì≥$)有(yǒu)效的(de)(證明(míng)這(zhè)個£π'®(gè)比特币是(shì)你(nǐ)的(de))。最後,<≤ ‌OP_CHECKSIG操作(zuò)将檢查交易的(de)簽名是(shì)否與↔∑π÷堆棧裡(lǐ)的(de)公鑰和(hé)簽名匹配& ,匹配就(jiù)證明(míng)簽名是(shì)有(yǒu)效的(de)(‍"證明(míng)交易的(de)到(dào)了&<&(le)你(nǐ)的(de)授權)

 

簽署交易

 

我發現(xiàn)簽署這(zhè)筆(bǐ)交易是(shì)手動使用×​♥(yòng)比特币時(shí)最難的(de)地(dì)方,這(z<εhè)一(yī)過程出奇地(dì)困難且容φ∏易出錯(cuò)。簽名的(de)基本思想​•很(hěn)簡單,使用(yòng)橢圓曲線簽名算(suàn)法和(hé)私$ 鑰來(lái)生(shēng)成交易的(de)數(shù)字簽名,但(dàn≥<)細節非常棘手。簽署交易的(de)過程可(kě)以通(tōng)過這(zhè)α&≈σ19個(gè)步驟描述。

 

 

簽署交易的(de)19個(gè)步驟

 

對(duì)交易的(de)簽名讓我面臨巨大(dà)的 ↔(de)挑戰,這(zhè)涉及到(dào)一(yī)個(gè)如(rú¶©)何在交易內(nèi)容中還(hái)沒有∑≤(yǒu)加入簽名時(shí)簽署這(zhè)筆(bǐ)交易的(de)問φ≤'±(wèn)題。為(wèi)了(le)避免這(zhè)個(gè)問(w ☆ &èn)題,在計(jì)算(suàn)生(shēng)成簽名之前,我把<​​scriptPubKey這(zhè)個(gè)腳本δ"<從(cóng)上(shàng)一(yī)筆(bǐ)交易複制(zhì)到(dà↔∏≥"o)當前交易中(當前這(zhè)筆(bǐ)交易正在被簽署),然後将簽≠π名轉換為(wèi)腳本語言的(de)代碼,創建嵌入在當前✔ ↔交易中的(de)scriptSig腳本。對(duì)ε®§♠于具有(yǒu)多(duō)個(gè)輸入的(de)交易 ♠​§,簽署交易環節更加複雜(zá),因為(wèi)每個(gè)輸入都(dōu)λ∑π×需要(yào)單獨的(de)簽名,這(zhè)裡(lǐ)我就(jiù)ΩΩ≈★不(bù)做(zuò)詳細討(tǎo)論了(le)。

 

哈希值這(zhè)一(yī)步驟難倒了(le±→£)我。在簽名之前,交易中有(yǒu)一(yī)個(gè)臨時(s←♣£✘hí)附加的(de)哈希值常量。對(duì)于常規的(de)交易,©≈<≠這(zhè)個(gè)值是(shì)SIGHASH_ALL(0x★φ00000001)。簽名後,這(zhè)個(gè) ←☆'哈希值将從(cóng)交易內(nèi)容的(de)最後删÷₹Ω×除,附加到(dào)scriptSig腳本♣≤∑∑中。

 

在比特币中另一(yī)件(jiàn)令人(rén)討₽↕§≤(tǎo)厭(yàn)的(de)事(shì)情是(shì)雖然簽名和φ£(hé)公鑰都(dōu)是(shì)512位的(de)橢圓曲線值,但(dàδ φn)它們的(de)表示方式完全不(bù)同:簽名用(yòng)DER編&±碼方式編碼,而公鑰用(yòng)純字節表示。另外(wài),兩λ≈♦個(gè)值都(dōu)有(yǒu)一(Ω yī)個(gè)額外(wài)的(de)字節,但(dàn)位★'→置并不(bù)一(yī)緻:SIGHASH_ALL這(zhè₩​∞)個(gè)附加的(de)哈希值常量放(fàng)在簽名£©♣後面,而04這(zhè)個(gè)值放(f ↕φàng)在公鑰前面。

 

由于ECDSA算(suàn)法需要(yào)使用(y§'&òng)随機(jī)數(shù),所以調試簽名十分(fēn)±↓♠困難。每次計(jì)算(suàn)出的(de)簽名都(dōu)會(λ€÷huì)有(yǒu)所不(bù)同,因此無法與已知(zhī)正确的(d ↕e)簽名進行(xíng)比較。

 

正是(shì)由于上(shàng)述的(de)複雜(zá)性,我<•‍花(huā)了(le)很(hěn)長(cháng)時(shí)間(jiā×π≤n)才得(de)到(dào)了(le)一¥ (yī)個(gè)簽名。不(bù)過,最終我找出了(∞≤<<le)簽名代碼中所有(yǒu)的(de)錯(cuò)誤,并成功用(yòn≤δ★‌g)它簽署了(le)一(yī)筆(bǐ)交易。這(zhè)是(sδ ÷hì)我使用(yòng)的(de)簽名代碼:↔↔♦

 

def makeSignedTransaction(privateKey, ↕♥♦ΩoutputTransactionHash, sourc ±™eIndex, scriptPubKey, ÷α↓₽outputs):    myTxn_forS"​‍♥ig = (makeRawTransactio↕←"✘n(outputTransactionHash, sourceIn≤¥σ↑dex, scriptPubKey, outputs)   >φ>      αΩ+ "01000000") # hash☆γε code    s256 = has♦♠hlib.sha256(hashlib.sha256(myTxn_forSi→δ≠ g.decode('hex')).£γdigest()).digest()   &nbs→δ<σp;sk = ecdsa.SigningKey.from_string(pr£ΩivateKey.decode('hex'), c§∑®↕urve=ecdsa.SECP256k1) &nb✔‍₩≤sp;  sig = sk.sign_digest(s2₽♥<56, sigencode=ecdsa.φ∞λγutil.sigencode_der) + '®✘\01' # 01 is hashtype   &n★✔•λbsp;pubKey = keyUtils.♥αprivateKeyToPublicKeλ♣≤y(privateKey)    €&scriptSig = utils.var¥"str(sig).encode('hex') + uti±≥‌★ls.varstr(pubKey.decode(₩&π≈'hex')).encode('hex')₽ β∑    signed_txn =​♥₽ makeRawTransaction(o<₩↔"utputTransactionHash, sΩ₽ourceIndex, scriptSig, outputs) &nbs<δp;  verifyTxnSignatu€ε♣↓re(signed_txn)    
   return signed2_txn

txnUtils.py

 

最終的(de)scriptSig腳本中包含簽名以及比特币™‍≈↕源地(dì)址的(de)公鑰(1MMMMSUb1piy2ufrSguNUdFφ±£↓mAcvqrQF8M5)。 這(zhè)證明(mí∞↔ ng)這(zhè)筆(bǐ)交易有(yǒu)效,我可(kě)以花(huā)費(©>✔₩fèi)這(zhè)些(xiē)比特币。

 

PUSHDATA 47

47

signature(DER)

sequence

30

length

44

integer

02

length

20

X

2c b2 65 bf 10 70 7b f4 93 46 c3 51 5¶≈"d d3 d1 6f c4 54 61 8c 58₹∏∑ ec 0a 0f f4 48 a6 76 c5 4f f7 13

integer

02

length

20

Y

6c 66 24 d7 62 a1 fc ef 46 ∑‍↓18 28 4e ad 8f 08 67 8a c0 5b 13 c8 ↕ ≠≤42 35 f1 65 4e 6a d1 68 23 3e 82 ✔

SIGHASH_ALL

01

PUSHDATA 41

41

public key

type

04

X

14 e3 01 b2 32 8f 17 44 2c 0b 83©✘¶  10 d7 87 bf 3d 8a 40 4c fb d★™0 70 4f 13 5b 6a d4 σ₩b2 d3 ee 75 13

Y

10 f9 81 92 6e 53 a6 ÷​∑γe8 c3 9b d7 d3 fe fd 57 6c 54 3c ce 49£α 3c ba c0 63 88 f2 65 1d ∞'‍1a ac bf cd

   
   

 

最終的(de)scriptPubKey腳本包含成功花(huā)費(fèi)比≠ε÷特币時(shí)必須執行(xíng)的(de)腳本。需要(yào ¶")注意的(de)是(shì),這(zhè)個±​←€(gè)腳本将在未來(lái)花(huā)費(fèi✔✔&)這(zhè)些(xiē)比特币的(de)時(shí)候執行☆π×(xíng)。它包含以十六進制(zhì)表示而不(bù)是(shì)以Bπ$ ×ase58Check表示的(de)目标地(dì)址••♦≠1KKKK6N21XKo48zWKuQKXd₽φvSsCf95ibHFa,腳本的(de)效果是(™π®shì)隻有(yǒu)這(zhè)個(gè)目标地(dì)址的(de)私★₽•'鑰所有(yǒu)者才能(néng)使用(yòng)比特币,因此₩§∑目标地(dì)址實際上(shàng)是(shì)這(zhè)些(xiē)比特币ε↕的(de)所有(yǒu)者

 

OP_DUP

76

OP_HASH160

a9

PUSHDATA 14

14

public key hash

c8 e9 09 96 c7 c6 08 0e e0 62 84 60 0δ×c 68 4e d9 04 d1 4c 5c

OP_EQUALVERIFY

88

OP_CHECKSIG

ac

 

最終的(de)交易

 

經過上(shàng)述的(de)一(yī)系列操作(zuò),我們完成了(l>₹↔•e)最終的(de)交易。但(dàn)是(shì),别忘了(le),此時₽≤(shí)的(de)交易還(hái)沒加入區γ₽£(qū)塊鏈中,接收方還(hái)沒有(yǒu)收到(dào)你(nǐ) ₽γ的(de)比特币。

 

privateKey = keyUtils.wifToPriv$§₩©ateKey("5HusYj2b2x4nr♣↔δ≤oApgfvaSfKYZhRbKFH41bVyPooymbCε$☆≥6KfgSXdD") #1MMMM

signed_txn = txnUtils.makeSi¥ ₽βgnedTransaction(privateKey,  &₹ε☆      

"81b4c832d70cb56ff957589752eb4125€•'a4cab78a25a8fc52d6a09e5bd4404d↕α↔∞48", # output (prev) tr ✘₽ansaction hash  $✔;      0, # s↑ ↔✘ourceIndex     &nb§€₹sp;  
keyUtils.addrHashToScriptPubKey(&q∏•→uot;1MMMMSUb1piy2ufrSguNUdFmAcv₩δqrQF8M5"),     &n​πεσbsp;  [[91234, #satoshis≤♣​÷      'α™≤;  
keyUtils.addrHashToSc≥£riptPubKey("1KKKK6N2α®↑1XKo48zWKuQKXdvSsCf95ibHFa")]×Ω☆™]        )  ₹₩;   txnUtils.verifyTxnSignature(♠σsigned_txn)
print'SIGNED TXN', β↕signed_txn

makeTransaction.py

 

最終的(de)交易信息如(rú)下(xià)所示:

version

01 00 00 00

input count

01

input

previous output hash(rever×'βΩsed)

48 4d 40 d4 5b 9e a0 d6 52 fc a8 2₩∞☆5 8a b7 ca a4 25 41 e€γ→®b 52 97 58 57 f9 6f b5★& 0c d7 32 c8 b4 81

previous output index

00 00 00 00

script length

8a

scriptSig

47 30 44 02 20 2c b2 65 bfλ→÷ 10 70 7b f4 93 46 c3 51 5d d3 d1 ₩♠σ¥6f c4 54 61 8c 58 ec ☆Ωα•0a 0f f4 48 a6 76 c5 4f f7 13 02 20∞§δ 6c 66 24 d7 62 a1 fc ef 46 1§£ €8 28 4e ad 8f 08 67 8a c0 5b 13 c8 ' β✔42 35 f1 65 4e 6a d1 68 23 →☆3e 82 01 41 04 14 e3 01 b2 32§☆λ 8f 17 44 2c 0b 83 10 d7 87 bf 3d 8"∏♥§a 40 4c fb d0 70 4f 13 5b 6a  ☆∑d4 b2 d3 ee 75 13 10 f✘σ÷9 81 92 6e 53 a6 e8 c≠←™3 9b d7 d3 fe fd 57 6c 54 3c ce 49 ₹σ3c ba c0 63 88 f2 65 1d 1a ac © ‌ bf cd

sequence

ff ff ff ff

output count

01

output

value

62 64 01 00 00 00 00 00

script length

19

scriptPubKey

76 a9 14 c8 e9 09 96 c7 c6 08 0e e0 §ε62 84 60 0c 68 4e d9 04 d1 4c 5c 88π÷ ac

block lock time

00 00 00 00

 

小(xiǎo)插曲:橢圓曲線簽名

 

比特币的(de)簽名算(suàn)法使用(yòng)到(dào)ε±×₹了(le)橢圓曲線簽名算(suàn)法,這(zhα¶✔→è)麽實用(yòng)的(de)功能(néng£‌$),你(nǐ)可(kě)能(néng)會(huì)λ☆好(hǎo)奇它是(shì)怎麽做(zuò)到(dào)的(de)?在當>δ年(nián)英國(guó)數(shù)學家(jiā)安ε☆德魯·懷爾斯攻克費(fèi)馬大(dà)★‌↓∑定理(lǐ)時(shí),我第一(yī)次接觸到(dàoλγ)了(le)橢圓曲線的(de)算(suàn)法。橢圓曲線的(de)數(shù✔←)學思想很(hěn)有(yǒu)意思,所以在這(zhè)裡(lǐ)我給大(dà•' ©)家(jiā)做(zuò)一(yī)個(g£>✔è)快(kuài)速的(de)概述。

 

橢圓曲線這(zhè)個(gè)叫法令人(rén)迷惑,因↔&©±為(wèi)橢圓曲線并不(bù)是(sh₹♥ì)橢圓,而且看(kàn)起來(lái)也(yě)不<♠‍(bù)像橢圓,甚至橢圓曲線與橢圓相(xiàng)關性都(d€↓>ōu)很(hěn)少(shǎo)。通(tōng)§∑俗地(dì)講,橢圓曲線就(jiù)是(shì)滿足一↕Ω(yī)個(gè)簡單方程y ^ 2 = x ^ 3 + ax + b的(Ω±∞de)曲線。比特币中使用(yòng)的(de)稱為(wèi)secp‌®βΩ256k1的(de)橢圓曲線,它滿足的(de)方程為(wèi)y ‌←☆Ω^ 2 = x ^ 3 + 7。

 

 

secp256k1橢圓曲線

 

橢圓曲線的(de)一(yī)個(gè)重要(yào)特性就(jiù)是 >↑•(shì)你(nǐ)可(kě)以用(yòng)一(yī)個(g↓&è)簡單的(de)規則來(lái)定義橢圓曲線上(shàng)點的(d₽♥e)相(xiàng)加:如(rú)果在曲線上♦‌♣♥(shàng)繪制(zhì)一(yī)條直線,這(zh÷♣ ★è)條直線與曲線交與A,B,C三個(gè)點,那(nà)麽這(zhβσè)個(gè)加法定義為(wèi)A+B+C=0。由這(zhè)個(gè)加'✘←法的(de)定義,我們可(kě)以定義整數(≈©shù)乘法:例如(rú)4A = A + A + A + A。

 

為(wèi)什(shén)麽橢圓曲線在密φ♠碼學上(shàng)很(hěn)有(yǒu)用(yòng)?因為(w→π♥∞èi)橢圓曲線做(zuò)整數(shù)乘法運算(suàn)速度很(hěnσ←)快(kuài),但(dàn)做(zuò)除法時(shí)需要(yào)蠻力。‍Ω例如(rú),你(nǐ)可(kě)以快(kuài)速地(dì)計(j£₹φì)算(suàn)一(yī)個(gè)乘法©≥12345678*A = Q,但(dàn)是(shì)↔≠ ™如(rú)果你(nǐ)隻知(zhī)道(dào)ε↑&A和(hé)Q,求解n*A=Q中的(de)n十分(fēn)>₽困難。因此在橢圓曲線算(suàn)法中,這(zhè)裡(lǐ)的(d>€e)12345678将是(shì)私鑰,曲線上(↓★shàng)的(de)點Q将是(shì)公鑰。

 

在密碼學中,點的(de)坐(zuò)标并不(bù)是(£↑shì)它在曲線上(shàng)的(de)實值點β→€ ,而是(shì)對(duì)整數(shù)的(de)模數(shù)。橢圓"↓曲線的(de)一(yī)個(gè)好(hǎ  →o)用(yòng)的(de)特性就(jiù)是(s↕÷♠hì)對(duì)實數(shù)或模數(shù)進行(xíng)"✘φ運算(suàn)的(de)數(shù)學運算(s'γφΩuàn)幾乎相(xiàng)同。正因為(wèi)如(rú)此,比特币的(γ≥✘‌de)橢圓曲線并不(bù)像上(shàng)面的(de)圖片,而是(shìπ←× )一(yī)團雜(zá)亂無章(zhāng)的(de)↔"256位點集(想想在一(yī)個(gè)空(kōng)間(↕​jiān)中充滿了(le)大(dà)量雜(zá)亂無章(zhāng±♦↔α)的(de)點)。

 

橢圓曲線數(shù)字簽名算(suàn)法γ∑ (ECDSA)接收交易的(de)哈希值,使用(yòng)該交易數(sh↕≠ù)據,私鑰,以及一(yī)個(gè)随機(jī)數(shù)從(♣≤♥↔cóng)橢圓曲線上(shàng)生(shēng)成¥↓一(yī)個(gè)新的(de)點,從(cóng)而實現(xià ​n)對(duì)交易的(de)簽名。任何擁有(yǒu)公鑰,交易數(s∏•hù)據,和(hé)簽名的(de)人(rén)都(dōu)可(kě)以通(tōγΩ ng)過做(zuò)一(yī)個(gè)簡單的(de)橢圓→‍曲線運算(suàn)來(lái)驗證簽名的(de)有(yǒu)效性。讀(d♦←<♦ú)到(dào)這(zhè)裡(lǐ),你(nǐ)應該明(mí∑βγαng)白(bái)了(le)為(wèi)什(sπ€hén)麽隻有(yǒu)擁有(yǒu)私→✘鑰的(de)人(rén)才能(néng)簽署消息≤↑↑ ,但(dàn)擁有(yǒu)公鑰的(de)任何人π≥≠×(rén)都(dōu)可(kě)以驗證該消息。

 

把交易發送到(dào)比特币網絡

 

回到(dào)交易中來(lái),别忘了(le)此時(→•shí)我們的(de)交易還(hái)沒有(yǒu)被加入到(d €φào)區(qū)塊鏈中,還(hái)不(bù)是(shì)£♠≥§一(yī)筆(bǐ)有(yǒu)效交易。剛剛我創建并β>☆簽署了(le)一(yī)筆(bǐ)交易。下(xià)一♥λδ(yī)步就(jiù)是(shì)将這(zhè)筆(bǐ)交易發送到(d< ‍¥ào)比特币網絡中,網絡中的(de)礦工(gōng)會(huì)收集交≠♣♥易并把它打包進區(qū)塊中。

 

如(rú)何找到(dào)比特币網絡的(de)節點β π¶

 

首先我要(yào)在比特币的(de)點對(duì)點網絡中找到(dào)一‍₹•&(yī)個(gè)節點。節點的(de)列表會(huì)随節點的(∞♥<de)進出動态更新,當一(yī)個(gè)₽ε≠ 比特币節點連接到(dào)另一(yī)個(®"γgè)節點時(shí),它們就(jiù)會(huì)不(b•γ♦ù)斷交換彼此新發現(xiàn)的(de)比特币節點信息 ¶,因此,新節點加入的(de)消息會(huì)快(kuài)速₹✘<β地(dì)傳遍整個(gè)網絡。

 

然而,新的(de)比特币節點如(rú)何第一(yī±'≤♠)次找到(dào)比特币節點?這(zhè)是(shì)一(yī)個(gè)>≈‍≤先有(yǒu)雞還(hái)是(shì)先"¥有(yǒu)蛋的(de)問(wèn)題。比特α ±币節點通(tōng)過以下(xià)幾種'¥方法來(lái)解決這(zhè)個(gè)問(wèn)題。有(yǒu)幾‌×≤個(gè)可(kě)信的(de)比特币節點會(huì)以bitsee∑<‍₹d.xf2.org的(de)域名在DNS系統(Domain Na♠↑‌me System,域名系統,萬維網上(shàng)作(zuò)為(wèi)域♠♦↕"名和(hé)IP地(dì)址相(xiàng)互映射的>ε↕<(de)一(yī)個(gè)分(fēn)布式數(shù)​∞¥據庫)上(shàng)注冊,通(tōng)過執行(xíng)nslo×∏‌≤okup命令,你(nǐ)就(jiù)可(kě)以得(de)到(dào)♠'♣這(zhè)些(xiē)節點的(de)IP地(dì)址,隻要(yà÷₽"★o)有(yǒu)一(yī)個(gè)在工(gōng)作( ©zuò)即可(kě)。如(rú)果很(hěn)不(bù)幸它們都(•∞₽δdōu)沒有(yǒu)工(gōng)作(z§₹<φuò)的(de)話(huà),你(nǐ)可(kě)  βα以試著(zhe)連接那(nà)幾個(gè)已經在你(nǐ≠γ)的(de)客戶端中硬編碼記錄下(xià)來(lái)的(de)地(dì)址。"€$

 

 

Nslookup命令可(kě)以用(yòng)來(lái)尋 $找比特币節點

 

當用(yòng)戶啓動或停止比特币客戶端時(shí),節點就(jiù)會(hu<✘ì)加入或離(lí)開(kāi)比特币網絡。所以連接節點有(yǒu)很δπα☆(hěn)大(dà)的(de)不(bù)确定性,在我實驗時(shí),就∞ ✔(jiù)遇到(dào)了(le)連接的(de→>→★)節點已經離(lí)開(kāi)比特币網絡的(de)情況,如(rú)果≠'±π你(nǐ)想重複我的(de)實驗,最好(hǎo)多(duō)找幾個(g•σ≤è)節點,可(kě)能(néng)需要( ★↕σyào)多(duō)次嘗試才能(néng)找到(dào)一(yī)β♠‍個(gè)運行(xíng)著(zhe)的(de)節點。

 

與比特币節點通(tōng)信

 

一(yī)旦獲得(de)了(le)一(yī$÷)個(gè)正在工(gōng)作(zuò)的(de)比特币節點↓•的(de)IP地(dì)址,當務之急就(jiù)≥π€通(tōng)過這(zhè)個(gè)節點是(shì)把我的(de)交易發¶≤®€送到(dào)比特币的(de)點對(duì)點網絡中。♥♣≈★使用(yòng)點對(duì)點的(de)網絡協議(yì)十分(fēn)簡單✘♣÷,我在端口8333上(shàng)打開(kāi)了(le¶↔)一(yī)個(gè)到(dào)任意對(duì)等端的(de)TC$α  P連接,發送消息,然後接受反饋消息。比特币的(de)點&÷§對(duì)點協議(yì)對(duì)用→εε(yòng)戶很(hěn)友(yǒu)好(hǎo),即使我的(de)請✘≥(qǐng)求數(shù)據出錯(cuò™π)時(shí),還(hái)是(shì)繼續與我保持通(tōnγδ g)信。 

 

重要(yào)提示:正如(rú)一(yī)些(xi↔§ ē)人(rén)指出的(de)那(nà)樣,如(rú)果你(nǐ)想重複我✔©&'的(de)實驗,切記要(yào)使用(yòng)比特币的(de)測試網絡,在測£✘←試網絡上(shàng),你(nǐ)可(kě)以使用(yòng)“•↕虛拟”的(de)比特币來(lá↑→↓i)進行(xíng)交易。因為(wèi)在真實網絡上(shàn§∏≈g),萬一(yī)你(nǐ)不(bù)小(xiǎo)心,有(yǒ ₽✔u)可(kě)能(néng)會(huì)失去(qù)所≠≥☆♣有(yǒu)的(de)比特币。還(hái)記得(de)上≤♣§→(shàng)面提到(dào)的(de)那(nà)個(g"φ↑>è)100個(gè)比特币轉賬1個(gè)✔<>≈的(de)交易麽,如(rú)果你(nǐ)忘了(le)将剩餘的(de↔‌←)比特币轉給自(zì)己,那(nà)麽剩餘的(de)9α©≠9個(gè)比特币就(jiù)會(huì)作(zuò)為(w±∏​γèi)交易費(fèi)支付給礦工(gōng)。但(dàn)是(sh®↔≤ì)本著(zhe)科(kē)學的(de)态度,我并不(bù)在意在真實的(de÷≤)比特币網絡中損失我這(zhè)些(xiē)價值1美(měi)元的₹•×&(de)比特币。

 

協議(yì)中包含24種不(bù)同的(de)信息種類。每一(yī)條信息都(∑‌§•dōu)是(shì)一(yī)個(gè)簡單±≥的(de)二進制(zhì)大(dà)對(duì)象(binary large §₩object ,BLOB,是(shì)一(€$‍☆yī)個(gè)可(kě)以存儲二進制(zhì)文(w↕‌ εén)件(jiàn)的(de)容器(qì)),其中包含一(yī)個(gè)A‍≤↑SCII命令和(hé)一(yī)個(gè)适用(yòng)‍×該命令的(de)二進制(zhì)有(yǒu)效參數(shù)。該協議±≤₽♥(yì)可(kě)以在比特币的(de)維基上(shàn±'g)查詢。 

 

連接到(dào)比特币網絡的(de)第一(yī)步←φ§β就(jiù)是(shì)通(tōng)過交換客戶端版本&•信息來(lái)建立連接。首先,我發送了(le)一£ (yī)條客戶端版本信息,其中包含我的(de)協議(yì)版本号,I★✘P地(dì)址和(hé)其他(tā)內(nèi)容。比特币✔♣€©節點也(yě)向我回複了(le)它的(de)版本信息。在此之後,我應該回複一Ω♣&★(yī)個(gè)verack信息(version✘₩ acknowledgement,版本确認)來(lái)确認它的(↕↔≈de)版本信息。正如(rú)我所說(shuō),比特币點對(duì)點&±≥₽網絡協議(yì)對(duì)用(yòng)戶十分(fē• n)友(yǒu)好(hǎo),即使我跳(tiào)過了≥∏(le)verack信息,之後的(de)操作(zuò)也$←≤(yě)是(shì)一(yī)切正常。 

 

交換版本信息這(zhè)一(yī)步并不(bù)簡單,因為(wèi)信息具​®☆有(yǒu)标準的(de)格式,不(bù)♣∑過不(bù)用(yòng)害怕,可(kě)以用(y ₩γòng)幾行(xíng)代碼來(lái)創≤π↔∞建這(zhè)些(xiē)信息。下(xià)面代碼段中的(de)β↓γγmakeMessage函數(shù)可(kě)以由随機(jī)數✘£✔(shù),命令名以及命令的(de)參數(sh¶✘₹γù)來(lái)生(shēng)成一(yī)條消息。£¶ getVersionMessage函數(shù)通(tōng)&♠§Ω過将各個(gè)字段打包在一(yī)起來(lái)為πλφ(wèi)版本消息創建參數(shù)。

 

magic = 0xd9b4bef9

def makeMessage(magic, command, pa₹ ±yload):    checksum =
hashlib.sha256(hashli₽•b.sha256(payload).digest()).diφαgest()[0:4]   &nb $sp;
   return struct.pε↑ack('L12sL4s', magic, commaε¶ nd, len(payload), checksum) + p$¥ayload
   
def getVersionMsg():    ♣₽;
   version = 60002₹≥    services = 1   &n★&→bsp;timestamp = int(time.time(∏≥♦))    addr_me =♠♥ utils.netaddr(socket.inet_aton↔∑σ("127.0.0.1"), 8333) &nΩ¶bsp;  addr_you = utils.netaddr>♦(socket.inet_aton("₹♥‍α127.0.0.1"), 8333) £↕δ≥   nonce = random.getra≈륕ndbits(64)    sub_vers§£σ​ion_num = utils.varstr('') &nγ bsp;  start_height = 0   &nbs§✘p;payload = struct.pack('&l₹π¶t;LQQ26s26sQsL',£α•  version, services, timestamp, addr_me<™βφ,      ∏≠€φ;  addr_you, nonce, sub_version_®®♣♥num, start_height) &®≥✔♥nbsp;  
   return makeMessage→$ ‍(magic, 'version¶★¥φ', payload)

msgUtils.py

 

發送交易tx

 

我使用(yòng)下(xià)面精簡的(de)Python代碼 β≤把我的(de)交易發送到(dào)比特币網絡中,這(zhè)個(gè)代☆<碼發送一(yī)條客戶端版本信息,接受(也(yě)可(k£©₹ě)以忽略)比特币節點的(de)版本信息♥¶和(hé)verack信息。最後将我的(de≈₹ )交易以tx信息發送。代碼中這(zhè)個(gè)1α"δ​6進制(zhì)的(de)字符串是(shì)我之前創建的(de)交易。↕★↔♥

 

def getTxMsg(payload):  retur<✔∏n makeMessage(magic, 't✔£x', payload) sock = socket.s≤$ocket(socket.AF_INET, socket.SOCK_S✔ TREAM) sock.connect(("97• ☆✔.88.151.164", 8333)) sock.send(‌↓​×msgUtils.getVersionMsg()) sock.recv(100±₩∏0) # receive version sock.™‍Ωrecv(1000) # receive €♠verack sock.send(msgUtil≥×≈s.getTxMsg("0100000001484×±d40d45b9ea0d652fca8258ab7caa42541e π∞ b52975857f96fb50cd732δ★c8b481000000008a47304402202c¶→™b265bf10707bf49346c3515dd3d16fc454↓γ♣618c58ec0a0ff448a676c54ff7130220♣✔♥↑6c6624d762a1fcef4618284φ¶ead8f08678ac05b13c84235f1654e6ad16≤<β8233e8201410414e301b2328f17442c≈<☆0b8310d787bf3d8a404cfbd¥‌★0704f135b6ad4b2d3ee751310f98192<₽6e53a6e8c39bd7d3fefd576c543cce493c✘¥bac06388f2651d1aacbfcdffffffff✔φ₹φ0162640100000000001976a914c8e90996c7c6Ω×080ee06284600c684ed904d14c5c88a>Ωc00000000".decode≥₹♣↑('hex')))

minimalSendTxn.py

 

以下(xià)Wireshark(一(yī)個(gè)抓取,♣₽∞分(fēn)析網絡封包的(de)軟件(jiàn®™φ<))軟件(jiàn)的(de)截圖顯示出Ωδ我是(shì)如(rú)何将交易發送到(dào)比特币網絡中的(de)。我用(®✘€™yòng)Python編寫了(le)腳本來(lái)分(fēn)析網絡✔α數(shù)據,為(wèi)了(le)簡單起見(jiàn),在這(zhè)裡✘£(lǐ)我使用(yòng)Wireshar≥βk。從(cóng)圖中可(kě)以看(kàn)到(dào)我的(de)•₽₽這(zhè)筆(bǐ)tx交易。

 

 

 

Wireshark中抓取的(de)這(zhè)筆(bǐ)正<φ☆在上(shàng)傳至比特币網絡的(de₩‍≥♠)交易tx

 

為(wèi)了(le)實時(shí)監控我這(zhè)筆(bǐ)交易©β←的(de)進度,我在比特币網絡中新運行(δ<←≈xíng)了(le)一(yī)個(gè)節點,在把≈∏∞我交易發到(dào)比特币網絡5秒(miǎo)鐘(&‌λ‍zhōng)之後,另一(yī)個(gè)節點給我發送了(le)這(zh✔<'®è)個(gè)tx消息,其中包含我剛剛發送的(de)這(zhè)筆(bǐ)交易β←‍✔的(de)哈希,由此可(kě)見(jiàn),在僅僅這(zhè)$αδ幾秒(miǎo)中,我的(de)交易已經傳遍了(le)比特币網絡,至少(s∏±hǎo)也(yě)是(shì)比特币網絡的(de)一(yī)部分(f≥≠∞ēn)。

 

交易成功:我的(de)交易被加入區(qū☆¶®÷)塊鏈

 

在将我的(de)交易發送比特币網絡之後,我需要(yào)等待它被礦工(g♣φπōng)開(kāi)采出來(lái)加入到(dà✘&∞✔o)區(qū)塊鏈中,然後才能(néng)宣稱我的(de)實驗圓滿成功。10∞♦分(fēn)鐘(zhōng)後,我的(de) φ比特币節點收到(dào)一(yī)條含有€∞(yǒu)新區(qū)塊信息的(de)inv消息(參見(ji®λ♠↔àn)下(xià)圖Wireshark抓到(§Ω"Ωdào)的(de)網絡封包),檢查這(zhè)​λ Ω個(gè)區(qū)塊後發現(xiàn)我的(de)交易被包含在☆↔ 了(le)區(qū)塊中,證明(míng)我的(de)交易是(sλλ♣hì)有(yǒu)效的(de),我的(de)實驗成功了(le)。通(tōngδ♠≤)過我的(de)比特币錢(qián)包軟☆α±件(jiàn)和(hé)在線查詢,再一(yī)次确認了(le)我已經交易成功✘λ。可(kě)以說(shuō),經過不(bù)斷的(de)努力,我成功•α手動創建了(le)一(yī)筆(bǐ)交易,并讓比特币系統接受了(le)♠±它。(當然了(le),我也(yě)經過了(le)幾次失敗的(de↕π)嘗試,這(zhè)些(xiē)錯(cuò)誤的(de)交易都(↔≠€§dōu)消失在了(le)網絡之中,永遠(yuǎn)都(dōu)不(bù)會Ω≥(huì)被檢索到(dào)。

 

Wireshark中抓取的(de)新區(qū)塊産生≠€(shēng)的(de)封包信息

 

我的(de)交易是(shì)被當時(shí)哈希算(suàn)力(挖礦速度)↑™♠最大(dà)的(de)礦池(多(duō)個(gδ♦≥è)礦工(gōng)一(yī)起挖礦)G♦∏​Hash.IO挖出,區(qū)塊高(gāo)度為(wèi)27906∑​ 8,區(qū)塊哈希為(wèi)00000¥β♠ 00000000001a27b1d6eb8c405410398ece796e7£↑42da3b3e35363c2219ee,在上(shàng)圖Wire€σ shark數(shù)據包中inv消息的(de)哈≠☆希值是(shì)經前後反轉得(de)到(dào)的(de)e∑§e192……。你(nǐ)₹≥應該會(huì)發現(xiàn)區(qū)塊的(de)哈希值→δ★'以大(dà)量的(de)0開(kāi)頭,在一(yī)個(gè)16進制(®"★ zhì)的(de)哈希值中發現(xiàn)一(yī)個(gè)以這(₹₩zhè)麽多(duō)0開(kāi)頭的(de)數(s₩§¶€hù),這(zhè)就(jiù)是(shì)為(wèi)什(shén)麽挖礦如♠↓δ(rú)此困難的(de)原因。這(zhè)個(↔&∑gè)區(qū)塊中由462筆(bǐ)交易,我的(de)交易是× δ✘(shì)其中之一(yī)。

高(gāo)度為(wèi)279068的(de)區(qū)塊™§ 以及我發起的(de)這(zhè)筆(bǐ)交易

(https://blockchain.info/€↓block-index/341440/0000∑δ £000000000001a27b1d6eb8c'σ​€405410398ece796e742da3b3e35363c221×>9ee)

 

挖到(dào)這(zhè)個(gè)區(q•↓÷☆ū)塊的(de)礦工(gōng)們收到(dào)了(le)25個(gè)比> δ‍特币的(de)獎勵,交易費(fèi)總共是(shì)0.104個(±≈¥gè)比特币,按當時(shí)的(de)市(shì)價分(fēn)别為(wπ$€èi)19000美(měi)元和(hé)80美(m↔'∏ěi)元。我支付了(le)0.0001個(gè♠↕•★)比特币的(de)交易費(fèi),大(dà)約是(shì)我交←÷易額的(de)10%,按當時(shí)的(de)市(shì)↑✔價為(wèi)8美(měi)分(fēn)。

 

結論

 

手動進行(xíng)比特币交易比我想象中困難得(de)多(duō),但λ✘(dàn)是(shì)在這(zhè)個(gè)過∏→∞€程中我學到(dào)了(le)很(hěn)多(duō),希望你(nǐΩ♥₹)也(yě)是(shì)。我的(de)Python代♠®≈∏碼僅僅是(shì)為(wèi)了(le)介紹,如(rú€φ)果你(nǐ)想跟我一(yī)樣用(yò≥π♠δng)Python手動進行(xíng)比 ✘特币交易,也(yě)可(kě)以試試這(zhè)幾個(gè)項目。

 

https://en.bitcoin.it/wik®®∑i/Bitcoin-python

https://github.com/richard™→∞kiss/pycoin

https://github.com/jgarzi→ k/python-bitcoinlib

 

 

寫在最後

2017年(nián)是(shì)區(qū)塊鏈的(de) &井噴之年(nián),經過一(yī)年(→∑β nián)的(de)積攢,2018年(nián)将迎來(lái)÷∞區(qū)塊鏈的(de)落地(dì)之年(nián),♦₹<區(qū)塊鏈會(huì)逐漸颠覆各行(♠α₩‍xíng)各業(yè)。對(duì)于個(gè)人(rén),δ§π區(qū)塊鏈的(de)機(jī)會(huì)會(huì)越來(lái≠ε€ )越多(duō),也(yě)許你(nǐ)錯(cuò)'δ過了(le)比特币的(de)投資,不(bù)妨現(xiàn)在抓住區(↕☆&×qū)塊鏈這(zhè)個(gè)風(fēng)口,投資自(λ  ®zì)己,多(duō)學習(xí)相(xiàng)關知(zh×≤¥ī)識,區(qū)塊鏈大(dà)有(yǒu)可(kě)為(wèi),投×$Ω±身(shēn)區(qū)塊鏈的(de)你(nǐ)将大(dà)有(yǒu)作(★→αzuò)為(wèi)!

*聲明(míng):推送內(nèi)容及圖片來★$(lái)源于網絡,部分(fēn)內(nèi)容會♣ (huì)有(yǒu)所改動,版權歸原作(zuò)者所有(yǒu),如σ™δ(rú)來(lái)源信息有(yǒu)誤或侵犯權益,請(qǐng)聯系我們删除∏↓ '或授權事(shì)宜。