智能合約開發是以太坊的核心,學習過程主要是搭建以太坊開發環境和solidity語言的編程。本文不用任何以太坊Dapp框架,直接在ganache下開發智能合約。node
讓咱們構建一個簡單的"Hello World!" 應用程序, 這是一個投票應用程序。linux
該應用程序很是簡單,它所作的只是初始化一組候選人,讓任何人投票給候選人,並顯示每一個候選人收到的總票數。git
我有意避免使用任何DAPP框架構建這個應用程序,由於框架抽象掉不少細節,你不瞭解系統的內部。此外,當你使用框架時,將對框架所作的繁重工做有更多的體會!github
咱們的目標是:web
咱們使用一個模擬的內存區塊鏈(ganache)代替真實的區塊鏈在進行開發。在本教程的2章,咱們將與真實的區塊鏈交互。下面是安裝ganache、web3js的步驟,而後在linux上啓動一個測試鏈。在macOS上安裝過程也是同樣的。npm
你能夠看到ganache-cli自動建立了10個測試帳號,每一個帳號預分配了100(虛構的)ethers編程
若是須要更詳細的開發環境安裝教程,能夠參考以下文章:ubuntu
咱們將使用solidity編程語言來編寫咱們的合約。若是您熟悉面向對象編程,學習編寫solidity合約應該是垂手可得的事。咱們將編寫一個合約對象,含有一個構造函數初始化候選人數組。合約對象有2個方法:windows
注意:構造函數只被調用一次,當您部署合約到區塊鏈。不像在網絡世界裏的每個部署你的代碼覆蓋舊的代碼,部署後的代碼在區塊鏈上是不變的。例如,若是你更新你的合約而且再次部署,舊合約仍然會在區塊鏈上, 它所存儲的數據不受影響,新的部署將建立一個新實例的合約。數組
下面是投票合約的代碼:
pragma solidity ^0.4.18; // We have to specify what version of compiler this code will compile with contract Voting { /* mapping field below is equivalent to an associative array or hash. The key of the mapping is candidate name stored as type bytes32 and value is an unsigned integer to store the vote count */ mapping (bytes32 => uint8) public votesReceived; /* Solidity doesn't let you pass in an array of strings in the constructor (yet). We will use an array of bytes32 instead to store the list of candidates */ bytes32[] public candidateList; /* This is the constructor which will be called once when you deploy the contract to the blockchain. When we deploy the contract, we will pass an array of candidates who will be contesting in the election */ function Voting(bytes32[] candidateNames) public { candidateList = candidateNames; } // This function returns the total votes a candidate has received so far function totalVotesFor(bytes32 candidate) view public returns (uint8) { require(validCandidate(candidate)); return votesReceived[candidate]; } // This function increments the vote count for the specified candidate. This // is equivalent to casting a vote function voteForCandidate(bytes32 candidate) public { require(validCandidate(candidate)); votesReceived[candidate] += 1; } function validCandidate(bytes32 candidate) view public returns (bool) { for(uint i = 0; i < candidateList.length; i++) { if (candidateList[i] == candidate) { return true; } } return false; } }
複製上面的代碼,在hello_world_voting目錄下建立一個Voting.sol文件。如今讓咱們來編譯代碼並將其部署到ganache的區塊鏈上.
爲了編譯solidity代碼,咱們須要安裝名字爲solc的npm模塊
~/hello_world_voting$ npm install solc
咱們將在node控制檯中使用這個庫來編譯咱們的合約。在上一篇文章中咱們提到,web3js是一個讓咱們能夠經過rpc訪問區塊鏈的庫。咱們將使用該庫來部署咱們的應用程序並與之交互。
首先,在命令行中斷運行node
命令進入node控制檯,初始化solc和文本對象。下面的全部代碼片斷都須要在node控制檯中鍵入
~/hello_world_voting$ node > Web3 = require('web3') > web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545"));
爲了確保web3對象已經初始化、區塊鏈可以訪問,讓咱們試一下查詢區塊鏈上的全部帳戶。您應該看到以下的結果:
> web3.eth.accounts ['0x9c02f5c68e02390a3ab81f63341edc1ba5dbb39e', '0x7d920be073e92a590dc47e4ccea2f28db3f218cc', '0xf8a9c7c65c4d1c0c21b06c06ee5da80bd8f074a9', '0x9d8ee8c3d4f8b1e08803da274bdaff80c2204fc6', '0x26bb5d139aa7bdb1380af0e1e8f98147ef4c406a', '0x622e557aad13c36459fac83240f25ae91882127c', '0xbf8b1630d5640e272f33653e83092ce33d302fd2', '0xe37a3157cb3081ea7a96ba9f9e942c72cf7ad87b', '0x175dae81345f36775db285d368f0b1d49f61b2f8', '0xc26bda5f3370bdd46e7c84bdb909aead4d8f35f3']
從voting.sol加載代碼,保存在一個字符串變量中,而後開始編譯
> code = fs.readFileSync('Voting.sol').toString() > solc = require('solc') > compiledCode = solc.compile(code)
當你的代碼編譯成功並打印了合約對象的內容(在node控制檯中輸出的內容),有2個字段很重要,須要理解它們:
compiledCode.contracts[‘:Voting’].bytecode
: Voting.sol源代碼編譯後獲得的字節碼。這是將被部署到blockchain的代碼。compiledCode.contracts[‘:Voting’].interface
: 合約接口或模板(稱爲ABI)告訴用戶合約含有哪些方法。您須要這些ABI的定義,由於未來你老是須要與合約交互的。更多ABI信息請參考這裏。若是但願能在線學習以太坊DApp的開發,分享一個教程: