以太坊智能合约简介(Solidity)
本文會通過兩個示例來簡單介紹智能合約
示例一:存儲(Storage)
下面這段代碼實現(xiàn)了一個uint值的存儲。
pragma solidity ^0.4.0;contract SimpleStorage {uint storedData;function set(uint x) public {storedData = x;}function get() public constant returns (uint) {return storedData;} }在某種意義上,Solidity合約就是在以太坊區(qū)塊鏈中特定地址內(nèi)的一組代碼(合約的函數(shù))和數(shù)據(jù)(合約的state)的集合。
uint?storedData;
這一行聲明了一個uint(256bit的無符號整數(shù))類型的state變量:storedData。你可以認為storedData是數(shù)據(jù)庫中的一個存儲單元,它可以被通過執(zhí)行數(shù)據(jù)庫管理代碼的方式查詢和修改。在以太坊中只有合約的所有者能這樣做。示例代碼中,set、get函數(shù)可以被用于修改或檢索變量的值
獲取state對象,不需要像其他語言那樣加this.前綴
由于此合約僅存儲了一個完全公開的數(shù)字,所以它的發(fā)布是無法被阻止的。但任何人都可以通過以另一參數(shù)調(diào)用set來覆蓋你剛剛保存的數(shù)字(但你寫過的那個數(shù)字仍會被保存在區(qū)塊鏈歷史中)。稍后,你將看到如何設(shè)置限制以確保只有你自己可以修改這個變量的值
注意,所有標(biāo)識符(如合約名,變量名,函數(shù)名等)只能使用ascii字符集。UTF-8編碼的數(shù)據(jù)可以存儲在字符串變量中
使用與其他字符相似的Unicode字符時需要保持小心
?
示例二:子貨幣(Subcurrency)
下面的合約將會實現(xiàn)一種最簡單的加密貨幣。這里定義的貨幣可以憑空產(chǎn)生,但只有創(chuàng)建合約的人才有能力憑空生成貨幣(實現(xiàn)一個不同的發(fā)幣計劃是件微不足道的小事)。 此外,任何人都可以互相發(fā)送貨幣而不需要使用用戶名和密碼進行注冊——進行所有的一切,只需要一個以太坊密鑰對。
pragma solidity ^0.4.21;contract Coin {// The keyword "public" makes those variables// readable from outside.address public minter;mapping (address => uint) public balances;// Events allow light clients to react on// changes efficiently.event Sent(address from, address to, uint amount);// This is the constructor whose code is// run only when the contract is created.function Coin() public {minter = msg.sender;}function mint(address receiver, uint amount) public {if (msg.sender != minter) return;balances[receiver] += amount;}function send(address receiver, uint amount) public {if (balances[msg.sender] < amount) return;balances[msg.sender] -= amount;balances[receiver] += amount;emit Sent(msg.sender, receiver, amount);} }這段合約帶來了一些新的概念,以下將一一介紹
?
address?public?minter;聲明了一個address類型的state變量,這個變量是所有人都可以讀取的。address類型是一個不允許進行任何算術(shù)操作的160位值。它很適合被用來存儲合約地址或?qū)儆谕獠總€人的密鑰對。關(guān)鍵字public會自動生成一個允許你從合約外部獲取一個state變量當(dāng)前值的函數(shù)。若沒有這個關(guān)鍵字,其他合約將無法獲取到這個變量。由編譯器生成的代碼和下面這行代碼大致相同
function minter() returns (address) { return minter; }(直接加上這句會導(dǎo)致編譯器報錯,因為此函數(shù)和state變量重名)
下一行:mapping?(address?=>?uint)?public?balances;
這句話創(chuàng)建了一個數(shù)據(jù)類型更加復(fù)雜的公共state變量——一個從地址到無符號整型的映射。此處的映射可以被看做一個虛擬初始化了的hash表,以便每個可能的密鑰存在,并映射到一個字節(jié)表示全是0的值上(這個比喻不太合理,因為包含一個有映射的所有鍵的列表是不可能的,包含所有值也是不可能的)。因此要么保存添加到映射中的內(nèi)容,要么在不需要這種內(nèi)容的部分使用它(就像這句)。由public關(guān)鍵字創(chuàng)建的getter函數(shù)【注1】在這種情況下更加復(fù)雜一些。看起來大概是這樣的:
function balances(address _account) public view returns (uint) {return balances[_account]; }用這個函數(shù)可以輕松查詢一個賬戶的余額
?
event?Sent(address?from,?address?to,?uint?amount);
這行聲明了一個所謂的“event(事件)”,它被最后的send函數(shù)發(fā)出。包括服務(wù)端應(yīng)用在內(nèi)的用戶接口可以以較低的成本監(jiān)聽這些被發(fā)送到區(qū)塊鏈上的事件。一旦事件被發(fā)送,監(jiān)聽者就會獲取到from、to、amount參數(shù),以便監(jiān)聽者跟蹤交易。為監(jiān)聽這一事件,我們會使用
Coin.Sent().watch({}, '', function(error, result) {if (!error) {console.log("Coin transfer: " + result.args.amount +" coins were sent from " + result.args.from +" to " + result.args.to + ".");console.log("Balances now:\n" +"Sender: " + Coin.balances.call(result.args.from) +"Receiver: " + Coin.balances.call(result.args.to));} })注意,自動生成的函數(shù)balance是怎樣從用戶接口調(diào)用的
?
Coin這個特殊的函數(shù)時在創(chuàng)建合約時調(diào)用的構(gòu)造器,他不能在合約構(gòu)造完成后再被調(diào)用。它永久存儲了合約創(chuàng)建者的地址:msg(和tx、block一起)。msg是一個神奇的全局變量,包含一些允許連接到區(qū)塊鏈的屬性。msg.sender永遠是當(dāng)前的(外部)函數(shù)調(diào)用所來自的地址。
?
這個合約中的函數(shù)可以被用戶和其他合約調(diào)用,如mint和send。mint只能被合約創(chuàng)建者進行有效的調(diào)用。而send可以被任何已經(jīng)持有一些這種幣的人調(diào)用來向他人進行轉(zhuǎn)賬。注意如果你用這個合約發(fā)送幣到其他地址,你在區(qū)塊鏈瀏覽器上瀏覽目標(biāo)地址時并不會看到任何效果產(chǎn)生,因為你發(fā)送了幣并改變余額的事實只存儲于這個特定的貨幣合約的數(shù)據(jù)存儲中。因為有了事件的使用,創(chuàng)建一個用于跟蹤你自己的貨幣的交易和余額的“區(qū)塊鏈瀏覽器”變得比較簡單。
?
?
【注1】:getter函數(shù)時編譯器為所有public的state變量自動創(chuàng)建的,它會返回一個uint類型的名為“data”的state變量值。狀態(tài)變量的初始化可以在聲明時完成。
?
總結(jié)
以上是生活随笔為你收集整理的以太坊智能合约简介(Solidity)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: PostgreSQL触发器的使用
- 下一篇: 解析Linux 多应用程序docker自