區塊鏈——以太坊、智慧合約簡介

_if_else_發表於2018-06-27

An Introduction to Ethereum and Smart Contracts: Bitcoin & The Blockchain

Learn about Bitcoin and the genius behind the blockchain concept as we delve into Ethereum

本文原版英文出處點選這裡,可能需要翻牆,本文使用谷歌翻譯,有錯誤或不準確的地方歡迎大家批評。

比特幣在2009年讓世界大吃一驚,並普及了分散式安全貨幣交易的想法。 然而,它背後的概念可以擴充套件到遠遠超過數字貨幣。 以太坊試圖做到這一點,將分散交易的權力與圖靈完整的合同制結合起來。 請繼續閱讀,瞭解它的工作原理!

“以太坊將分散交易的權力與圖靈完成合同結合在一起!”
這裡寫圖片描述

這是3系列的第一部分。

介紹:比特幣和雙重支出問題

2009年,一位筆名叫Satoshi Nakamoto的人釋出了一篇標誌性的比特幣白皮書。 比特幣準備好解決一個非常具體的問題:如果在沒有認證中心為每一筆交易做仲裁,出現雙重支出問題怎麼解決呢?

公平起見,在比特幣釋出之前,這個問題一直存在於研究人員的腦海裡。 但是,在以前的解決方案具有研究質量的地方,比特幣成功地為大眾帶來了一個可用於生產的設計。

最早提及直接應用於比特幣的一些概念是從20世紀90年代開始的。 2005年,電腦科學家Nick Szabo介紹了Bitcoin的前身Bitgold的概念,分享了它的許多概念。 Bitgold和比特幣之間的相似性足以讓一些人推測他可能是Satoshi Nakamoto。

雙重支出問題是交易處理的一個特例。 根據定義,交易必須發生或不發生。 此外,一些(但不是全部)交易必須提供在其他交易之前或之後發生的擔保(換句話說,它們必須是原子的)。 原子性導致了訂購的概念:交易在其他交易之前或之後發生或不發生。 缺乏原子性恰恰是雙重支出問題的問題:“支出”或從支出方A向接收方B傳送資金必須發生在特定時間點以及任何其他交易之前和之後。 如果情況並非如此,那麼可以在分開但同時進行的交易中花費不止一次的資金。

雙重支出問題

談到日常貨幣運作時,交易通常由銀行進行仲裁。 當使用者登入他或她的個人銀行系統並執行電匯時,銀行確保過去和未來的操作都是一致的。 雖然這個過程對於外部人來說似乎很簡單,但它實際上是一個涉及清算程式和結算要求的相關流程。 事實上,其中一些程式考慮了雙重支出情況的可能性以及在這些情況下應該採取的措施。 這些相當複雜的過程不應該讓人吃驚,這導致了電腦科學研究人員的目標在很大程度上似乎不可能超越延遲。

這裡寫圖片描述

區塊鏈

因此,任何融資交易系統必須解決的主要問題是“如何在沒有中央當局的情況下訂購交易”。 此外,過去的交易順序是否有效也不容懷疑。 為了貨幣系統的成功,任何一方都不可以修改以前的交易。 換句話說,過去交易的“審批流程”也必須到位。 這正是比特幣區塊鏈系統旨在解決的問題。

如果您有興趣閱讀必須達成共識的系統及其面臨的問題,那麼拜占庭將軍問題的論文是一個好的開始。

雖然在這一點上區塊鏈的概念是模糊的,但在詳細討論它之前,讓我們回顧一下區塊鏈試圖解決的問題。

驗證事務

公鑰加密是處理事務驗證其中一個問題的重要工具。公鑰密碼學依賴於非常具體的一組問題的非對稱數學複雜性。公鑰密碼學中的不對稱體現在兩個金鑰的存在:公鑰和私鑰。這些鍵為了特定目的而串聯使用。尤其是:

  • 使用公鑰加密的資料只能使用私鑰解密。
  • 用私鑰簽名的資料可以使用公鑰進行驗證。
  • 私鑰不能從公鑰中派生,但公鑰可以從私鑰派生。公共金鑰是安全共享的,通常可以自由地暴露給任何人。

建立一組可驗證的事務的關鍵是操作簽署資料。讓我們看看如何通過使用公鑰密碼體系來驗證一個非常簡單的事務。

假設有一個賬戶持有人A擁有50個加密貨幣。作為之前交易的一部分,這些加密貨幣被髮送給他。賬戶持有人A現在想要將這些加密貨幣傳送給賬戶持有人B.B和任何其他想要仔細檢查該交易的人必須能夠確認實際上是誰將加密貨幣傳送給乙。此外,他們必須能夠看到B兌現了他們,而沒有其他人。顯然,他們也應該能夠找到相對於其他交易發生的確切時間點。但是,在這一點上,我們不能這樣做。幸運的是,我們可以做所有其他事情。

舉個簡單的例子,假設交易中的資料只是前一個交易(一個給予A50加密貨幣的交易)的識別符號,當前所有者的公鑰和前一個所有者的簽名(確認他或她首先將這些代幣寄給A):

{ 
    "previous-transaction-id": "FEDCBA987654321...",
    "owner-pubkey": "123456789ABCDEF...",
    "prev-owner-signature": "AABBCCDDEEFF112233..."
}

當前交易的加密貨幣數量是多餘的:它與其上一筆交易的金額相同。

證明A是這些加密貨幣的所有者已經存在:他或她的公鑰已嵌入到交易中。 現在無論採取什麼行動都必須以某種方式進行驗證。 一種方法是將資訊新增到交易中,然後生成新的簽名。 由於A想要向B匯款,所增加的資訊可能只是B的公鑰。 在建立這個新事務後,它可以使用A的私鑰進行簽名。 這證明了A,並且只有A參與了建立這項交易。 換句話說,在基於JavaScript的虛擬碼中:

function aToB(privateKeyA, previousTransaction, publicKeyB) {
    const transaction = {
        "previous-transaction-id": hash(previousTransaction),
        "owner-pubkey": publicKeyB        
    };

    transaction["prev-owner-signature"] = sign(privateKeyA, transaction);

    return transaction;
}

值得注意的是,我們已將事務ID定義為其二進位制表示的雜湊值。換句話說,一個事務ID就是它的雜湊(在這一點上,使用未指定的雜湊演算法)。由於我們稍後將解釋的幾個原因,這很方便。目前,這只是一種可能的做事方式。

讓我們分開程式碼並逐步寫下程式碼:

  • 一個新的交易構成指向前一個交易(持有A的50個硬幣的交易)並且包括B的公共簽名(新交易=舊交易ID加接收方的公鑰)。
  • 使用新交易和先前交易所有者的私鑰(A的私鑰)生成簽名。

因此,新交易中的簽名在新交易和舊交易之間建立了可驗證的連結。新交易明確指向舊交易,新交易的簽名只能由舊交易的私鑰持有者生成(舊交易通過owner-pubkey欄位明確告訴我們這是誰)。所以舊事務持有可以使用它的人的公鑰,新事務持有接收它的人的公共金鑰以及使用私人金鑰建立的簽名。

這裡寫圖片描述

如果這一點看起來很難理解,那麼可以這樣想:它全部來源於這個簡單的表示式:使用公鑰可以驗證用私鑰簽名的資料。沒有什麼更多。消費者只需簽署一段說明“我是交易ID XXX所有者”的資料,我在此將其中的每一枚硬幣都傳送給B“。 B和其他任何人都可以檢查它是否是A,只有A,誰寫的。為此,他們只需訪問A的公鑰,該公鑰在交易中可用。從數學上保證除了A的私鑰以外不能使用與A的公共金鑰串聯的金鑰。所以通過簡單地訪問A的公鑰,任何人都可以看到A是誰給B發錢。這使B成為這筆錢的合法所有者。當然,這是一個簡化。有兩件事我們沒有考慮過:誰說這50個硬幣在哪裡A的財產(或者換句話說,A確實擁有一些隨機交易的所有權,他或她是合法的所有者? B的硬幣(在其他交易之前還是之後?)。

如果您有興趣瞭解更多關於公鑰密碼學背後的數學知識,可以參閱JWT手冊第7章的程式碼示例簡單介紹。
在討論訂購問題之前,我們先來解決硬幣生成的問題。在我們的例子中,我們假定A是50個硬幣的合法所有者,因為給A他或她的硬幣的交易只是像任何其他交易一樣建模:它在所有者欄位中擁有A的公鑰,並且它指向先前交易。那麼,誰把這些硬幣給了A?更重要的是,誰把硬幣交給了另一個人?我們只需要遵循交易連結。每筆交易指向鏈中的前一筆交易,那麼這50個硬幣從哪裡來?在某些時候,鏈條必須結束。

為了理解這是如何工作的,最好考慮一個實際案例,讓我們看看比特幣如何處理它。比特幣中的硬幣有兩種不同的建立方式。首先是獨特的起源區塊。起始塊是一個特殊的硬編碼事務,指向其他以前的事務。這是系統中的第一筆交易,具有特定數量的比特幣,並指向屬於比特幣建立者Satoshi Nakamoto的公鑰。這筆交易中的一些硬幣被髮送到某些地址,但他們從來沒有真正使用過這麼多。比特幣中的大部分硬幣來自另一個地方:它們是一種誘因。正如我們將在下一節中看到的關於排序事務一樣,用於執行此操作的方案需要網路中的節點以計算形式貢獻工作。為了激勵更多的節點貢獻計算,一定數量的硬幣在成功完成任務時被賦予貢獻節點。這種激勵主要導致生成新硬幣的特殊交易。這些交易也是交易連結以及創世區塊的終點。比特幣中的每一枚硬幣都可以追溯到這些激勵措施中的一種或起源塊。許多加密貨幣系統採用這種硬幣發生模式,每種模式都有自己的細微差別和對硬幣創造的要求。在比特幣中,按照設計,隨著更多的硬幣被建立,更少的硬幣被獎勵為獎勵。最終,硬幣的創造將停止。

訂購交易

比特幣給現有加密貨幣計劃帶來的最大貢獻是使交易成為原子的分散方式。 比特幣之前,研究人員提出了不同的方案來實現這一點 其中一個計劃是一個簡單的投票系統。 為了更好地理解比特幣方法的魔力,最好探索這些嘗試。

在投票系統中,每個事務都由執行它的節點廣播。 因此,繼續A向A傳送50個硬幣的例子,A準備一個新的交易指向給他或她那50個硬幣的交易,然後將B的公鑰放入其中並使用他或她自己的私鑰 (A’s)簽名。 然後該事務被髮送到網路中由A所知的每個節點。 假設除了A和B之外,還有三個其他節點:C,D,E。

這裡寫圖片描述

現在讓我們假設A實際上是一個惡意節點。 儘管看起來A想要傳送B 50個加密貨幣,但同時A播放這個交易,它也播放一個不同的一個:A將這50個相同的加密貨幣傳送給C.

const aToB = { 
    "previous-transaction-id": "FEDCBA987654321...",
    "owner-pubkey": "123456789ABCDEF...", // B
    "prev-owner-signature": "..."
};

const aToC = { 
    "previous-transaction-id": "FEDCBA987654321...",
    "owner-pubkey": "00112233445566...", // C
    "prev-owner-signature": "..."
};

請注意previous-transaction-id指向同一個事務。 A同時將此事務傳送到網路中的不同節點。 誰得到50個加密貨幣? 更糟糕的是,如果這50枚加密幣被用來換取東西,A可能會從B和C獲得貨物,儘管其中一枚加密貨幣不會獲得加密幣。

由於這是一個分散式網路,每個節點在決策中應該有一定的權重。 讓我們考慮一下前面提到的投票系統。 現在每個節點都應該對是否選擇哪個事務進行投票。


Node    Vote
A       A to B
B       A to B
C       A to C
D       A to C
E       A to B

每個節點都投了一票,A到B被選為應該首先進行的交易。顯然,這使得A到C交易無效,指向與A到B相同的硬幣。看起來這個解決方案有效,但只是表面上看起來如此。讓我們看看為什麼。

首先,我們考慮一下情況A與其他節點勾結。 E投了一個隨機投票還是以某種方式激勵A選擇了另一個交易?沒有真正的方法來確定這一點。

其次,我們的模型不考慮交易傳播的速度。在一個足夠大的節點網路中,一些節點可能會在其他節點之前看到一些事務。這會導致投票不平衡。無法確定未來的交易是否會使已到達的交易無效。更重要的是,無法確定剛剛到達的交易是在等待投票的其他交易之前或之後進行的。除非交易被所有節點看到,否則投票可能是不公平的。更糟糕的是,一些節點可能會主動延遲事務的傳播。

最後,惡意節點可能會注入無效事務以導致目標拒絕服務。這可以用來支援某些交易而不是其他交易。

投票不能解決這些問題,因為它們是系統設計的固有特徵。不管用什麼來支援一種交易,都不能選擇。只要一個節點或一組節點能以某種方式支援某些事務而不是其他事務,系統就無法工作。正是這個元素使得加密貨幣的設計變得如此艱辛。需要一個天才的中風來克服這樣一個深刻的設計問題。

在分散式系統中惡意節點投票的問題最為人所知的是拜占庭將軍問題。雖然有數學證明,只要存在一定比例的非惡意節點,就可以克服這個問題,但這並不能解決加密貨幣的問題:節點新增便宜。因此,不同的解決方案是必要的。
物理對救援

無論使用哪種系統來確保某些交易優於其他交易,節點都不應該能夠100%確定地選擇哪些交易。只有一種方法可以確定是這種情況:如果節點能夠做到這一點在物理上是不可能的。節點新增起來很便宜,因此無論惡意使用者控制多少節點,他或她都很難將其用於他或她的優勢。

答案是CPU的能力。如果訂購交易需要一定量的工作和可驗證的工作,那麼最初的工作很難執行,但驗證起來很便宜。從某種意義上說,密碼學的工作原理是相同的:某些相關操作在計算上不可行,而其他操作便宜。加密資料在暴力加密金鑰旁邊很便宜。從私鑰中獲得公共金鑰很便宜,而以相反方式實現則是不可行的。雜湊資料很便宜,但通過修改輸入資料找到具有特定要求的雜湊卻不是。這是比特幣和其他加密貨幣所依賴的主要操作,以確保平均而言,任何節點都無法超越其他節點。讓我們看看這是如何工作的。

首先,我們來定義一個塊是什麼。塊只是一組交易。在塊內部,這些交易按照特定順序設定並滿足任何交易的基本要求。特別是,無效交易(例如從沒有資金的賬戶獲得資金)不能成為一個區塊的一部分。除了交易之外,一個區塊還有一些被稱為工作證明的東西。工作證明是允許任何節點驗證建立該塊的人執行了大量計算工作的資料。換句話說,沒有節點可以建立一個有效的塊,而不需要執行不確定的但相當多的工作。我們將在稍後看到這是如何工作的,但現在知道建立任何塊需要一定的計算能力,並且任何其他節點都可以檢查該塊建立的人是否已經花費了該功耗。

現在讓我們回到我們先前的惡意節點A的例子,它試圖同時建立兩個單獨的交易,一個向B傳送資金,另一個向C傳送資金,然後將兩個交易廣播到網路中,每個建立塊的節點(可能包括A)都會選擇一些事務並按照他們喜歡的方式進行排序。這些節點會注意到兩個不相容的事務是同一個塊的一部分,並且會丟棄一個。他們可以自由選擇丟棄哪一個。在按照他們選擇的順序放置這些事務之後,每個節點開始解決找到符合協議設定條件的塊的雜湊的難題。一個簡單的條件可能是“用三個前導零找到該塊的雜湊”。

這裡寫圖片描述

這建立了一個有趣的場景,因為即使A是惡意節點並控制另一個節點(例如E),網路上的任何其他節點仍然有機會找到不同的有效塊。 換句話說,這種方案使得惡意節點很難控制網路。

proof-of-work

但是,必須考慮大量惡意節點串通並共享CPU功率的情況。實際上,控制大多數節點的實體(根據CPU功率而非數量)可以通過比其他節點更快地建立塊來執行雙重支出攻擊。足夠大的網路依靠積聚CPU能力的困難。在投票系統中,攻擊者只需要向網路新增節點(這很容易,因為免費訪問網路是設計目標),但在基於CPU電源的方案中,攻擊者面臨物理限制:越來越多地訪問強大的硬體。

定義

最後,我們可以嘗試對區塊鏈是什麼以及它是如何工作的完整定義。區塊鏈是一個可驗證的交易資料庫,它載有所有發生的所有交易的有序列表。事務儲存在塊中。建立塊是一項特意計算密集型任務。建立有效塊的困難迫使任何人花費一定的工作量。這確保了足夠大網路中的惡意使用者不會輕易超越誠實使用者。網路中的每個塊都指向前一個塊,從而有效地建立一個鏈。區塊鏈中區塊的時間越長(離最後一個區塊越遠),其可能從中移除的概率就越小。換句話說,塊越老,它就越安全。

這裡寫圖片描述

我們在前面段落中留下的一個重要細節是當兩個不同節點同時發現不同但仍然有效的塊時發生的情況。從某種意義上說,這看起來像交易所面臨的同樣的問題:選擇哪一個。與交易相比,每個區塊所需的工作量證明系統讓我們找到一個方便的解決方案:由於每個區塊都需要一定的工作量,因此唯一有效的區塊鏈是其中最多區塊的區塊鏈。想一想:如果工作證明系統工作,因為每個塊需要一定量的工作(和時間),最長的一組有效塊是最難破的。如果一個惡意節點或一組節點試圖建立一組不同的有效塊,通過總是選擇最長的塊鏈,他們總是必須重做更多的塊(因為每個節點指向前一塊,改變一塊塊之後的所有塊都強制改變)。這也是惡意節點組需要控制超過50%的網路計算能力來實際進行攻擊的原因。少於這一點,網路的其他部分將更快地建立更長的區塊鏈。

如果較長版本的區塊鏈是由其他節點計算的,則有效的區塊有效,但可以找到區塊鏈較短的區塊。廢棄區塊中的交易再次傳送到等待納入未來區塊的交易池中。這會導致新交易保持未經確認的狀態,直到他們找到儘可能長的區塊鏈。節點定期從其他節點接收更新版本的區塊鏈。

這裡寫圖片描述

如果有足夠多的節點同時從網路的另一部分斷開連線,則網路完全可能分叉。如果發生這種情況,每個分支將繼續與另一個分離建立塊。如果網路將來再次合併,節點將比較不同版本的區塊鏈並選擇更長的區塊鏈。具有更大計算能力的分支將永遠贏。如果分叉要持續足夠長的時間,合併發生時大量的交易將被撤銷。正是由於這個原因,叉子是有問題的。

更換協議或執行節點的軟體也可能導致分叉。這些更改可能導致節點使其他節點認為有效的塊無效。效果與網路相關的分支相同。

另外:使用WebTasks和比特幣的永久訊息系統

雖然我們還沒有深入研究比特幣或以太坊如何處理交易的細節,但它們內建了一定的可程式設計性。比特幣允許在每筆交易中指定特定條件。如果滿足這些條件,交易可以花費。另一方面,以太坊則更進一步:系統內建了圖靈完整的程式語言。我們將在本系列的下一篇文章中關注以太坊,但現在我們來看看創新的方式,區塊鏈的概念可以被利用,而不僅僅是傳送金錢。為此,我們將在比特幣之上開發一個簡單的永久訊息系統。它將如何工作?

我們已經看到了可以驗證的區塊鏈商店交易。每個交易都由可執行該交易的人簽署,然後再廣播到網路。然後在執行工作證明後將其儲存在塊內。這意味著交易中嵌入的任何資訊都會永久儲存在區塊鏈中。塊的時間戳用作訊息日期的證明,並且工作證明過程用作其不可變性質的證明。

比特幣使用指令碼系統來描述使用者為了花錢而必須執行的步驟。最常見的指令碼就是“簡單地通過簽署此訊息證明您是某個私鑰的所有者”。這就是所謂的“付給pubkey雜湊”指令碼。以反編譯的形式,它看起來像:

<sig> <pubKey> OP_DUP OP_HASH160 <pubKeyHash> OP_EQUALVERIFY OP_CHECKSIG

其中和由消費者提供,其餘部分由原始傳送者指定。這只是一系列混合的資料和操作。此指令碼的直譯器是基於堆疊的虛擬機器。執行的細節超出了本文的範圍,但您可以在比特幣維基上找到一個很好的總結。重要的是,交易可以在指令碼中嵌入資料。

實際上,在事務中嵌入資料的操作碼是有效的:OP_RETURN操作碼。無論資料如何,OP_RETURN操作碼都儲存在事務中。當然,允許的資料量有限制:40位元組。這是非常少的,但仍然有一些有趣的應用程式可以用這麼小的儲存空間來執行。其中之一是我們的永久訊息系統。另一個有趣的用例是“存在證明”概念。通過將資產的雜湊儲存在區塊鏈中,它可以在新增到區塊的位置證明其存在。事實上,已經有這樣一個專案。沒有什麼能夠阻止您將我們的永久訊息系統用於類似的用途。還有一些其他用途允許系統準備只有在滿足條件後才能使用的交易,或者當提供者提供具有某種數字資產的證據時,以及某個最小數量的使用者同意使用該交易的時間。與傳統的貨幣系統相比,可程式設計性開闢了許多可能性,併為加密貨幣帶來了另一大優勢。

實施

我們的系統將作為HTTP服務工作。資料將作為POST請求的主體以JSON格式傳遞。該服務將有三個端點加上一個用於除錯。

THE /NEW ENDPOINT

它使用傳入的使用者名稱和密碼建立一個新使用者。示例主體:

{ 
    "id": "username:password", // password is not hashed for simplicity, 
                               // TLS is required!
    "testnet": true            // True to use Bitcoin's test network
}

The response is of the form:

{
    "address": "..."            // A Bitcoin address for the user just created
}

THE /ADDRESS ENDPOINT

Returns the address for an existing user. Sample body:

{ 
    "id": "username:password", // password is not hashed for simplicity, 
                               // TLS is required!
}

The response is identical to the /new endpoint.

THE /MESSAGE ENDPOINT

Broadcasts a transaction to the Bitcoin network with the message stored in it. A fee is usually required for the network to accept the transaction (though some nodes may accept transactions with no fees). Messages can be at most 33 bytes long. Sample body:

{ 
    "id": "username:password", 
    "fee": 667, 
    "message": "test" 
}

The response is either a transaction id or an error message. Sample of a successful response:

{ 
    "status": "Message sent!",
    "transactionId": "3818b4f03fbbf091d5b52edd0a58ee1f1834967693f5029e5112d36f5fdbf2f3"
}

Using the transaction id one can see the message stored in it. One can use any publicly available blockchain explorer to do this.

THE /DEBUGNEW ENDPOINT

Similar to the /new endpoint but allows one to create an user with an existing Bitcoin private key (and address). Sample body:

{ 
    "id": "username:password", // password is not hashed for simplicity, 
                               // TLS is required!
    "testnet": true,           // True to use Bitcoin's test network
    "privateKeyWIF": "..."     // A private key in WIF format.
                               // Note testnet keys are different from livenet keys,
                               // so the private key must agree with the 
                               // value of the "testnet" key in this object
}

The response is identical to the /new endpoint.

The Code

The most interesting endpoint is the one that builds and broadcasts the transaction (/message). We use the bitcore-lib and bitcore-explorers libraries to do this:

getUnspentUtxos(from).then(utxos => {
    let inputTotal = 0;
    utxos.some(utxo => {
        inputTotal += parseInt(utxo.satoshis);
        return inputTotal >= req.body.fee;
    });
    if(inputTotal < req.body.fee) {
        res.status(402).send('Not enough balance in account for fee');
        return;
    }

    const dummyPrivateKey = new bitcore.PrivateKey();
    const dummyAddress = dummyPrivateKey.toAddress();

    const transaction = 
        bitcore.Transaction()
                .from(utxos)
                .to(dummyAddress, 0)
                .fee(req.body.fee)
                .change(from)
                .addData(`${messagePrefix}${req.body.message}`)
                .sign(req.account.privateKeyWIF);

    broadcast(transaction.uncheckedSerialize()).then(body => {
        if(req.webtaskContext.secrets.debug) {
            res.json({
                status: 'Message sent!',
                transactionId: body,
                transaction: transaction.toString(),
                dummyPrivateKeyWIF: dummyPrivateKey.toWIF() 
            });
        } else {
            res.json({
                status: 'Message sent!',
                transactionId: body
            });
        }
    }, error => {
        res.status(500).send(error.toString());
    });
}, error => {
    res.status(500).send(error.toString());
});

具體程式碼非常簡單:

獲取地址的未使用的交易(即可用的硬幣,餘額)。
使用未使用的事務作為輸入來構建新的事務。
將交易指向新的空白地址。將0個硬幣分配給該地址(不要不必要地傳送金錢)。
設定費用。
設定未用完的錢將被送回的地址(更改地址)。
新增我們的訊息。
廣播交易。
比特幣需要使用以前交易的資金來構建交易。也就是說,當傳送硬幣時,它不是指定的起始地址,而是指向包含在指向不同目標地址的新事務中的那個地址的事務。從這些交易中扣除傳送到目的地的貨幣。在我們的案例中,我們使用這些交易來支付費用。其他一切都會發回我們的地址。

部署示例

由於WebTasks的強大功能,部署和使用這些程式碼是小菜一碟。首先克隆儲存庫:

git clone git@github.com:auth0-blog/ethereum-series-bitcoin-perpetual-message-example.git

現在確保您安裝了Webtask命令列工具:

npm install -g wt-cli

如果您還沒有這樣做,請初始化您的WebTask憑證(這是一次性過程):

wt init

Now deploy the project:

cd ethereum-series-bitcoin-perpetual-message-example
wt create --name bitcoin-perpetual-message --meta 'wt-node-dependencies={"bcryptjs":"2.4.3","bitcore-lib":"0.13.19","bitcore-explorers-bitcore-lib-0.13.19":"1.0.1-3"}' app.js

Your project is now ready to test! Use CURL to try it out:

curl -X POST https://wt-sebastian_peyrott-auth0_com-0.run.webtask.io/bitcoin-perpetual-message/new -d '{ "id":"test:test", "testnet":true }' -H "Content-Type: application/json"
{"address":"mopYghMw5i7rYiq5pfdrqFt4GvBus8G3no"} # This is your Bitcoin address

您現在必須為您的新比特幣地址新增一些資金。 如果你在比特幣的測試網上,你可以簡單地使用一個水龍頭。

水龍頭是比特幣網站,免費提供硬幣到地址。 這些測試網很容易獲得。 對於“livenet”,您需要使用比特幣交易所購買比特幣。
現在傳送訊息!

curl -X POST https://wt-sebastian_peyrott-auth0_com-0.run.webtask.io/bitcoin-perpetual-message/message -d '{ "id":"test:test", "fee":667, "message":"test" }' -H "Content-Type: application/json"
{"status":"Message sent!","transactionId":"3818b4f03fbbf091d5b52edd0a58ee1f1834967693f5029e

現在,您可以使用區塊鏈瀏覽器和事務ID來檢視事務。如果您在連結的頁面底部前往WTMSG:test字首前看到我們的訊息。這將永久儲存在區塊鏈中。

自己試試! https://wt-sebastian_peyrott-auth0_com-0.run.webtask.io/bitcoin-perpetual-message/上的web任務現場直播。不過,您需要建立自己的帳戶併為其提供資金。

您也可以獲取此示例的完整程式碼並執行它!

結論

區塊鏈支援分散式的驗證事務。同時他們為雙重支出問題提供了創造性的解決方案。這促使了cryptcoin的興起,其中比特幣是最受歡迎的例子。比特幣每天都有數百萬美元的交易,而且這種趨勢並沒有任何放緩的跡象。比特幣提供了一組有限的操作來定製交易。儘管如此,許多創造性的應用程式通過區塊鏈和計算的結合而出現。以太坊是其中最好的例子:將分散交易與圖靈完整的執行環境結合在一起。在本系列的下一篇文章中,我們將仔細研究以太坊與比特幣的不同之處以及分散式應用程式的概念如何通過它實現。

相關文章