鍍金池/ 教程/ 大數(shù)據(jù)/ 區(qū)塊鏈技術(shù)(三):智能合約入門
區(qū)塊鏈技術(shù)(十):以太坊去中心化淘寶智能合約案例
區(qū)塊鏈技術(shù)(八):以太坊公開拍賣智能合約案例
區(qū)塊鏈技術(shù)(九):以太坊非公開拍賣智能合約案例
區(qū)塊鏈技術(shù)(五):以太坊核心概念(一)
區(qū)塊鏈技術(shù)(一):Truffle開發(fā)入門
區(qū)塊鏈技術(shù)(七):以太坊投票智能合約案例
區(qū)塊鏈技術(shù)(四):區(qū)塊鏈?zhǔn)鞘裁矗?/span>
區(qū)塊鏈技術(shù)(三):智能合約入門
區(qū)塊鏈技術(shù)(二):以太坊編程語(yǔ)言Solidity安裝
區(qū)塊鏈技術(shù)(六):以太坊核心概念(二)

區(qū)塊鏈技術(shù)(三):智能合約入門

一個(gè)簡(jiǎn)單的智能合約

先從一個(gè)非?;A(chǔ)的例子開始

contract ZhaoxiStorage {

    uint storedData;

    function set(uint x) {
        storedData = x;
    }

    function get() constant returns (uint retVal) {
        return storedData;
    }
}

在Solidity中,一個(gè)合約由一組代碼(合約的函數(shù))和數(shù)據(jù)(合約的狀態(tài))組成。合約位于以太坊區(qū)塊鏈上的一個(gè)地址。

uint storedData; 這行代碼聲明了一個(gè)狀態(tài)變量,變量名為storedData,類型為無(wú)符號(hào)整數(shù)uint??梢钥醋鰯?shù)據(jù)庫(kù)里面的一條記錄,可以通過調(diào)用函數(shù)查詢和修改它。在以太坊中,通常只有合約的擁有者才能這樣做。在這個(gè)例子中,函數(shù) set 和 get 分別用于修改和查詢變量的值。

跟很多其他語(yǔ)言一樣,訪問狀態(tài)變量時(shí),不需要在前面增加 this. 這樣的前綴。

任何人都可以調(diào)用set方法設(shè)置一個(gè)不同的數(shù)字覆蓋你發(fā)布的數(shù)字。但是你的數(shù)字將會(huì)留存在區(qū)塊鏈的歷史上。稍后我們會(huì)學(xué)習(xí)如何增加存取限制。

一個(gè)加密貨幣列子

接下來(lái)的合約將實(shí)現(xiàn)一個(gè)形式最簡(jiǎn)單的加密貨幣。通過這份代碼,任何人都可以發(fā)送貨幣給其他人,不需要注冊(cè)用戶名和密碼,只要有一對(duì)以太坊的公私鑰即可。

contract ZhaoxiCoin {

    // 關(guān)鍵字“public”使變量能從合約外部訪問。
    address public minter;
    mapping (address => uint) public balances;

    // 事件讓輕客戶端能高效的對(duì)變化做出反應(yīng)。
    event Sent(address from, address to, uint amount);

    // 這個(gè)構(gòu)造函數(shù)的代碼僅僅只在合約創(chuàng)建的時(shí)候被運(yùn)行。
    function ZhaoxiCoin() {
        minter = msg.sender;
    }

    // 合約創(chuàng)建者可以調(diào)用mint
    function mint(address receiver, uint amount) {
        if (msg.sender != minter) return;
        balances[receiver] += amount;
    }

    // send可以被擁有代幣的任何人調(diào)用
    function send(address receiver, uint amount) {
        if (balances[msg.sender] < amount) return;
        balances[msg.sender] -= amount;
        balances[receiver] += amount;
        Sent(msg.sender, receiver, amount);
    }
}

address public minter 這行代碼聲明了一個(gè)可公開訪問的狀態(tài)變量,類型為address。address類型的值大小為160 bits,適用于存儲(chǔ)合約的地址或其他人的公私鑰。public關(guān)鍵字會(huì)自動(dòng)為其修飾的狀態(tài)變量生成訪問函數(shù)。沒有public關(guān)鍵字的變量將無(wú)法被其他合約訪問。另外只有本合約內(nèi)的代碼才能寫入。自動(dòng)生成的函數(shù)如下:

function minter() returns (address) { return minter; }

下一行代碼mapping (address => uint) public balances; 創(chuàng)建了一個(gè)public的狀態(tài)變量,但是其類型更加的復(fù)雜。該類型將一些address映射到無(wú)符號(hào)整數(shù)。mapping可以被認(rèn)為是一個(gè)哈希表,每一個(gè)可能的key對(duì)應(yīng)的value被虛擬的初始化為全0。對(duì)于一個(gè)mapping,無(wú)法獲取一個(gè)包含其所有key或者value的鏈表。所以我們得自己記著添加了哪些東西到mapping中。在這個(gè)例子中由public關(guān)鍵字生成的訪問函數(shù)將會(huì)更加復(fù)雜,其代碼大致如下:

function balances(address _account) returns (uint balance) {
    return balances[_account];
}

event Sent(address from, address to, uint value)這行代碼聲明了一個(gè)"事件"。由send函數(shù)的最后一行代碼觸發(fā)??蛻舳丝梢员O(jiān)聽這些由區(qū)塊鏈觸發(fā)的事件。事件觸發(fā)時(shí),監(jiān)聽者會(huì)同時(shí)接收到from,to,value這些參數(shù)值,可以方便的用于跟蹤交易。為了監(jiān)聽這個(gè)事件,你可以使用如下代碼:

ZhaoxiCoin.Sent().watch({}, '', function(error, result) {
    if (!error) {
        console.log("ZhaoxiCoin transfer: " + result.args.amount +
            " coins were sent from " + result.args.from +
            " to " + result.args.to + ".");
        console.log("Balances now:\n" +
            "Sender: " + ZhaoxiCoin.balances.call(result.args.from) +
            "Receiver: " + ZhaoxiCoin.balances.call(result.args.to));
    }
}

這里有個(gè)比較特殊的函數(shù) ZhaoxiCoin。它是一個(gè)構(gòu)造函數(shù),會(huì)在合約創(chuàng)建的時(shí)候運(yùn)行,之后就無(wú)法被調(diào)用。它會(huì)永久得存儲(chǔ)合約創(chuàng)建者的地址。msg(以及tx和block)是一個(gè)全局變量,它包含了一些可以被合約代碼訪問的屬于區(qū)塊鏈的屬性。msg.sender 總是存放著當(dāng)前函數(shù)的外部調(diào)用者的地址。

最后,真正被用戶或者其他合約調(diào)用,用來(lái)完成本合約功能的函數(shù)是mint和send。如果合約創(chuàng)建者之外的其他人調(diào)用mint,什么都不會(huì)發(fā)生。而send可以被任何人(擁有一定數(shù)量的代幣)調(diào)用,發(fā)送一些幣給其他人。

以上就是一個(gè)簡(jiǎn)單的加密貨幣的完整代碼和說(shuō)明。

原文:http://wangxiaoming.com/blog/2016/05/03/blockchain-tech-introduciton-to-smart-contracts/