當前位置:
首頁 > 最新 > 面向小白的以太坊開發教程漢化版

面向小白的以太坊開發教程漢化版

區塊鏈研習社

最好的區塊鏈學習社群

本頁面的目的是介紹以太坊的基礎知識,從開發的角度來看,您需要了解以太坊的基礎知識,以生成合同和分散的應用程序。有關以太坊的一般介紹,請參閱白皮書,如需完整的技術規格,請參閱黃皮書,但這些不是本頁面的先決條件; 也就是說,這個頁面是專門針對應用程序開發人員的以太坊的替代介紹。

介紹

以太坊是一個平台,旨在讓人們使用區塊鏈技術輕鬆編寫分散式應用程序(?apps)。分散的應用程序是為用戶提供某種特定用途的應用程序,但具有應用程序本身不依賴於任何特定方的重要屬性。?app不是作為銷售或提供特定的一方的服務的前端,而是一個不用任何集中的中間媒介而在一起互動的人們和組織的工具。

即使是通常是集中供應商的領域(例如過濾,身份管理,託管和爭議解決)的必要「中介」功能,也可以由網路直接處理,或者使用諸如內部令牌系統和信譽之類的工具讓任何人參與系統來確保用戶獲得高質量的服務。?apps的早期例子包括BitTorrent文件共享和比特幣貨幣。以太坊採用BitTorrent和比特幣,點對點網路和區塊鏈所使用的主要開發方式,並將其推廣,以便開發人員將這些技術用於任何目的。

以太坊區塊鏈可以被交替地描述為一個內置編程語言的區塊鏈,或者是一個基於共識的全局執行的虛擬機。實際處理內部狀態和計算的協議部分稱為以太坊虛擬機(EVM)。從實際的角度來看,EVM可以被看作是一個大型的分散式計算機,其中包含數百萬個對象,稱為「賬戶」,能夠維護內部資料庫,執行代碼並相互通話。

有兩種類型的帳戶:

外部擁有賬戶(EOAs):由私鑰控制的賬戶,如果您擁有與EOA關聯的私鑰,則可以從其發送以太和消息。

合同:一個擁有自己代碼的賬戶,由代碼控制。

默認情況下,以太坊執行環境無生氣,沒有任何事情發生,每個帳戶的狀態保持不變。但是,任何用戶都可以通過從外部擁有的賬戶發送交易來觸發行動,從而使以太坊的輪子運動。如果交易的目的地是另一個EOA,那麼該交易可能轉移一些以太,但否則什麼都不做。但是,如果目的地是合同,合同又會激活,並自動運行其代碼。

代碼能夠讀/寫自己的內部存儲器(資料庫將32位元組的密鑰映射到32位元組的值),讀取接收到的消息的存儲,並將消息發送到其他契約,從而觸發它們的執行。一旦執行停止,並且由合同發送的消息觸發的所有子執行都會停止(這一切都以確定性和同步的順序進行,即子調用在父調用進一步之前完全完成),則執行環境將停止再一次,直到下一次交易被喚醒。

合同通常有四個目的:

維護一個數據存儲,代表對其他合同或外部世界有用的東西; 其中一個例子是模擬貨幣的合同,另一個例子是記錄特定組織的成員資格的合同。

作為一種具有更複雜訪問策略的外部賬戶; 這被稱為「轉發合同」,並且通常只涉及在滿足某些條件的情況下簡單地將傳入消息重新發送到某個期望的目的地; 例如,可以有一個轉發合同,等待直到給定的三個私鑰中的兩個在重新發送它之前確認了一個特定的消息(即multisig)。更複雜的轉發合同根據發送的消息的性質具有不同的條件; 這個功能的最簡單的用例是一個可以通過一些更複雜的訪問過程被覆蓋的提取限制。

管理多個用戶之間正在進行的合同或關係。這方面的例子包括一個金融合同,一些特定的調解人的代管,或者某種保險。也可以有一方開放合同,讓任何一方隨時參與; 其中一個例子就是一個合同,它會自動支付給誰提出一個有效的解決方案給一些數學問題,或者證明它提供了一些計算資源。

為其他合同提供職能; 基本上作為一個軟體庫。

合同通過交替地稱為「呼叫」或「發送消息」的活動彼此交互。「消息」是一個包含一定數量的以太(在以太坊中使用的一個特殊的內部貨幣,主要目的是支付交易費用),任意大小的數據的位元組數組,發送者和接收者的地址的對象。當合同收到一條消息時,它可以選擇返回一些數據,然後消息的原始發送者可以立即使用這些數據。這樣,發送消息就像調用一個函數一樣。

因為合同可以扮演不同的角色,所以我們期望合約會互相影響。舉一個例子,考慮一下Alice和Bob打賭100 GavCoin的情況,即舊金山的氣溫在明年的任何時候都不會超過35oC。然而,Alice非常注重安全性,而且她的主賬戶使用轉發合同,這個轉發合同只能通過三個私人密鑰中的兩個批准發送消息。鮑勃對量子密碼學是偏執的,所以他使用轉發契約,只傳遞與傳統的ECDSA一起簽名Lamport簽名的消息(但由於他是老式的,他傾向於使用基於SHA256的Lamport sigs版本,這是以太坊直接不支持)。

投注合約本身需要從某個合同中提取有關舊金山天氣的數據,並且在需要將GavCoin實際發送給Alice或Bob(或者更確切地說,Alice或Bob的轉發)時還需要與GavCoin合同交談合同)。我們可以顯示賬戶之間的關係:

當鮑勃想完成下注時,會發生以下步驟:

發送交易,觸發Bob的EOA到Bob的轉發合同的消息。

Bob的轉發合同將消息的散列和Lamport簽名發送到用作Lamport簽名驗證庫的合同。

Lamport簽名驗證庫看到Bob想要一個基於SHA256的Lamport sig,所以根據需要多次調用SHA256庫來驗證簽名。

一旦Lamport簽名驗證庫返回1,表示簽名已經過驗證,它會向代表該合同的合同發送一條消息。

投注合約檢查提供舊金山溫度的合約以查看溫度。

投注合同認為對消息的回應顯示溫度高於35oC,因此它向GavCoin合同發送一條消息,將GavCoin從其賬戶轉移到Bob的轉發合同。

請注意,GavCoin全部「存儲」為GavCoin合同資料庫中的條目; 在步驟6的上下文中的「帳戶」一詞僅僅意味著在GavCoin合同存儲器中存在具有用於投注合同地址的密鑰和其餘額的值的數據條目。收到此消息後,GavCoin合同將此值減少一定數量,並增加與Bob的轉發合同地址對應的條目中的值。我們可以在下圖中看到這些步驟:

狀態機

EVM中的計算是使用基於堆棧的位元組碼語言完成的,就像比特幣腳本,傳統彙編和Lisp(Lisp部分歸因於遞歸消息發送功能)之間的交叉。EVM中的程序是一系列操作碼,如下所示:

PUSH1 0 CALLDATALOAD SLOAD NOT PUSH1 9 JUMPI STOP JUMPDEST PUSH1 32 CALLDATALOAD PUSH1 0 CALLDATALOAD SSTORE

這個特定的合同的目的是作為一個名字登記處; 任何人都可以發送包含64位元組數據的消息,其中32個是關鍵字,32個是數值。合同檢查密鑰是否已經在存儲器中註冊,如果沒有,則合同在該密鑰處註冊該值。

在執行過程中,維持一個稱為「存儲器」的無限可擴展位元組數組,指向當前指令的「程序計數器」和一堆32位元組值。在執行開始時,內存和堆棧是空的,PC是零。現在讓我們假設這個代碼的合同是第一次被訪問,並且一個消息被發送到123 wei(10 18 wei = 1 ether)和64個位元組的數據,其中前32個位元組編碼了54和第二個32位元組編碼2020202020。

因此,開始時的狀態是:

PC: 0 STACK: [] MEM: [], STORAGE: {}

位置0處的指令是PUSH1,它將一個單位元組的值壓入堆棧並在代碼中跳轉兩步。因此,我們有:

PC: 2 STACK: [0] MEM: [], STORAGE: {}

位置2處的指令是CALLDATALOAD,它從堆棧中彈出一個值,從該索引開始載入32個位元組的消息數據,並將其壓入堆棧。回想一下,這裡的前32個位元組編碼為54。

PC: 3 STACK: [54] MEM: [], STORAGE: {}

SLOAD彈出堆棧中的一個,並將該索引處的合同存儲中的值壓入堆棧。由於合同是第一次使用,它什麼也沒有,所以零。

PC: 4 STACK: [0] MEM: [], STORAGE: {}

不彈出一個值,如果值為零則推1,否則為0

PC: 5 STACK: [1] MEM: [], STORAGE: {}

接下來,我們PUSH1 9。

PC: 7 STACK: [1, 9] MEM: [], STORAGE: {}

JUMPI指令彈出2個值,只有第二個值不為零時才跳轉到第一個指定的指令。在這裡,第二個是非零的,所以我們跳。如果存儲索引54中的值不是零,那麼堆棧頂部的第二個值將為0(由於NOT),所以我們不會跳轉,並且我們將前進到STOP指令,導致我們停止執行。

PC: 9 STACK: [] MEM: [], STORAGE: {}

在這裡,我們PUSH1 32。

PC: 11 STACK: [32] MEM: [], STORAGE: {}

現在,我們再次調用CALLDATALOAD,彈出32,並將消息數據中的位元組從位元組32開始,直到位元組63。

接下來,我們PUSH1 0。

現在,我們再次載入消息數據位元組0-31(載入消息數據就像載入內存一樣便宜,所以我們不費心將其保存在內存中)

最後,我們SSTORE將2020202020的值存儲在索引54處。

PC: 17 STACK: [] MEM: [], STORAGE:

幸運的是,您不必在低級程序集中編程; 一個高級語言的存在,特別是為寫作合同而設計的,被稱為Solidity的存在,使你更容易編寫合同(還有其他幾個,也包括LLL,Serpent和Mutan,你可能會發現更容易學習或根據你的經驗使用)。您用這些語言編寫的任何代碼都會被編譯到EVM中,並創建發送包含EVM位元組碼的事務的合約。

有兩種類型的交易:發送交易和合同創建交易。發送事務是標準事務,包含接收地址,以太量,數據位元組陣列和一些其他參數,以及來自與發送者賬戶相關聯的私鑰的簽名。合同創建交易看起來像一個標準的交易,除了收貨地址是空白的。當創建交易的合同進入區塊鏈時,交易中的數據位元組陣列被解釋為EVM代碼,並且該EVM執行返回的值被視為新合同的代碼; 因此,您可以在初始化過程中執行某些事務。新合同的地址是根據發送地址和發送帳戶之前進行交易的次數(此值稱為帳戶現時也由於不相關的安全原因而被保留)確定性計算的。因此,您需要將其放在區塊鏈上以生成上述名稱註冊表的完整代碼如下所示:

PUSH1 16 DUP PUSH1 12 PUSH1 0 CODECOPY PUSH1 0 RETURN STOP PUSH1 0 CALLDATALOAD

SLOAD NOT PUSH1 9 JUMPI STOP PUSH1 32 CALLDATALOAD PUSH1 0 CALLDATALOAD SSTORE

關鍵操作碼是CODECOPY,將從位元組12開始的16位元組代碼複製到從索引0開始的內存中,並將RETURN返回到內存位元組0-16,即。代碼位元組12-28(可以自由地在紙上「手動」執行,以驗證代碼和內存的這些部分實際上被複制並返回)。代碼位元組12-28當然是我們上面看到的實際代碼。

加油站

EVM工作方式的一個重要方面是EVM中執行的每一個操作實際上是由每個完整節點同時執行的。這是以太坊1.0共識模式的必要組成部分,其優點是EVM的任何合同都可以以幾乎零成本的方式調用任何其他合同,但也有缺點,EVM的計算步驟非常昂貴。粗略地說,使用一個好的啟發是,你將無法在EVM上做任何你從1999年起無法在智能手機上做的事情。EVM的可接受使用包括運行業務邏輯(「如果這樣的話」)和驗證簽名和其他密碼對象; 在這個上限的應用程序驗證其他區塊鏈(例如分散的以太幣到比特幣交易所)的部分;

為了防止故意的攻擊和濫用,以太坊協議每計算一步收費。費用以市場為基礎,雖然在實踐中是強制性的; 可以包含在一個區塊中的操作數量的浮動限制迫使即使是能夠承擔交易費用的礦工也能夠接近無償地向整個網路收取相當於交易成本的費用; 請參閱白皮書中有關費用的更多細節,了解我們的費用和運營限制系統的經濟基礎。

收費的方式如下。每筆交易都必須包含一個GASPRICE和一個STARTGAS價值。STARTGAS是交易分配的「天然氣」數量,GASPRICE是交易單位天然氣支付的費用; 因此,在交易發送時,評估過程中首先要做的是STARTGAS * GASPRICE從發送賬戶餘額中減去wei加上交易的價值。GASPRICE是由交易發送者設定的,但是礦工可能會拒絕處理GASPRICE太低的交易。

氣體可以粗略地被認為是計算步驟的一個計數器,並且在交易執行期間存在,但不在其外部。當事務執行開始時,剩餘的氣體被設定為STARTGAS - 21000 - 68 * TXDATALEN,其中TXDATALEN是在交易數據的位元組數(注意:零個位元組將只4氣體因零個位元組長串的更大的可壓縮)。每一個計算步驟,從總量中減去一定量(通常是1,有時更多取決於操作)。如果天然氣下降到零,那麼所有的執行都會恢復,但交易仍然有效,發送者仍然需要支付燃氣費用。如果交易執行結束,N >= 0天然氣剩餘,則發送的賬戶將退還給N * GASPRICEwei。

在合同執行過程中,當合同發送消息時,該消息調用本身帶有氣體限制,而且子執行的工作方式相同(也就是說,它可以用盡氣體,恢復或執行成功並返回一個值) 。如果子執行耗盡,父執行繼續; 因此,如果您對子執行設置了氣體限制,則合同可以調用另一個合同是完全「安全」的。如果子執行有一些剩餘氣體,那麼該氣體返回到父執行繼續使用。

虛擬機操作碼

EVM中操作碼的完整列表可以在黃色文件中找到。請注意,高級語言通常會為這些操作碼擁有自己的包裝器,有時界面也會有很大的不同。

以太坊區塊鏈(或「分類帳」)是分散的,大規模複製的資料庫,其中存儲了所有帳戶的當前狀態。區塊鏈使用名為Patricia樹(或「trie」)的資料庫來存儲所有帳戶; 這本質上是一種特殊的Merkle樹,充當通用的鍵/值存儲。像標準Merkle樹一樣,Patricia樹有一個可以用來引用整個樹的「根哈希」,並且在不改變根哈希的情況下,樹的內容不能被修改。對於每個帳戶,樹存儲一個4元組[account_nonce, ether_balance, code_hash, storage_root],其中包含account_nonce從該帳戶發送的交易數量(保留以防止重播攻擊),ether_balance是帳戶的餘額,code_hash如果賬戶是合同,則代碼的散列,否則storage_root是「」,並且是存儲存儲數據的另一個派翠西亞樹的根。

每一分鐘,礦工都會產生一個新的區塊(在Ethereum中採礦的概念與比特幣中的概念完全一樣;請參閱任何比特幣教程以獲取更多信息),該區塊包含自上一個區塊以來發生的交易清單,代表新狀態(「狀態樹」)的帕特里夏樹的根哈希應用那些事務並給礦工一個創建塊的以太獎勵。

由於帕特里夏樹的工作方式,如果做了很少的改變,那麼樹的大部分將和最後一塊完全一樣。因此,不需要兩次存儲數據,因為新樹中的節點將簡單地能夠指向存儲舊樹的節點的相同的存儲器地址,其中新樹和舊樹完全相同。如果千塊數據在塊N和塊之間改變N + 1,則即使樹的總大小是幾千兆位元組,也需要為塊存儲新的數據量N + 1最多只有幾百千位元組,通常要少得多(尤其是在同一合同內發生多重變更的情況下)。每個塊都包含前一個塊的散列(這使得塊設置為「鏈」)以及輔助數據(如塊號,時間戳,礦工地址和氣體限制)。

圖形界面(OUTDATED API)

合同本身是一個強大的東西,但它不是一個完整的?app。一個?app被定義為一個契約和一個使用該契約的圖形界面的組合(注意:現在只有這樣,未來版本的以太坊將包括竊竊私語,允許?app中的節點直接發送彼此之間沒有區塊鏈的點對點消息)。現在,界面被實現為一個HTML / CSS / JS網頁,帶有一個特殊的JavaScript API,eth用於與以太坊區塊鏈一起工作。Javascript API的關鍵部分如下:

eth.transact(from, ethervalue, to, data, gaslimit, gasprice)- 從期望的地址(注意:from必須是私鑰並且to必須是十六進位形式的地址)發送交易到所需的地址

(string).pad(n)- 將編碼為字元串的數字轉換為二進位形式的n位元組

eth.gasPrice - 返回當前的天然氣價格

eth.secretToAddress(key) - 將私鑰轉換為地址

eth.storageAt(acct, index) - 在所需索引處返回所需帳戶的存儲條目

eth.key - 用戶的私鑰

eth.watch(acct, index, f)- f給定帳戶的給定存儲條目發生更改時調用

您不需要任何特殊的源文件或庫來使用該eth對象; 但是,您的?app只能在以太坊客戶端打開時才能使用,而不是常規的Web瀏覽器。

作者:wiki,區塊鏈兄弟,版權歸原作者所有

英文地址:https://github.com/ethereum/wiki/wiki/Ethereum-Development-Tutorial


喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 區塊鏈與數字貨幣 的精彩文章:

TAG:區塊鏈與數字貨幣 |