比特币價格的(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   &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ì)宜。