投票智能合約的編譯和調(diào)用

基礎(chǔ)的編程:智能合約簡(jiǎn)單編程

  1. 部署
    部署參考只能合約的簡(jiǎn)單編程。
  2. 智能合約代碼
    // title 授權(quán)投票
    contract Ballot
    {
        // 這里聲明了復(fù)雜類型
        // 將會(huì)在被后面的參數(shù)使用
        // 代表一個(gè)獨(dú)立的投票人。
        struct Voter
        {
            uint weight; // 累積的權(quán)重,也就是具有的投票數(shù)
            bool voted;  // 如果為真,則表示該投票人已經(jīng)投票。
            address delegate; // 委托的投票代表(如果自己不投,委托給別人,這個(gè)別人的地址)
            uint vote;   // 投票選擇的提案索引號(hào)(投的提案)
        }
    
        // 這是一個(gè)獨(dú)立提案的類型
        struct Proposal
        {
            string name;   // 提案的短名稱
            uint voteCount; // 提案累計(jì)獲得的票數(shù)
        }
        // 提案創(chuàng)建者地址
        address public chairperson;
        // 這里聲明一個(gè)狀態(tài)變量,保存每個(gè)獨(dú)立地址的`Voter` 結(jié)構(gòu)
        mapping(address => Voter) public voters;
        // 一個(gè)存儲(chǔ)`Proposal`結(jié)構(gòu)的動(dòng)態(tài)數(shù)組
        Proposal[] public proposals;
        // 提案名字?jǐn)?shù)組
        string[] public myProposalNames;
    
        // 創(chuàng)建一個(gè)新的投票用于選出一個(gè)提案名`proposalNames`
        // 這個(gè)構(gòu)造函數(shù),會(huì)在合約執(zhí)行的第一次直接調(diào)用
        function Ballot() public
        {
            // 提案創(chuàng)建者
            chairperson = msg.sender;
            // 這個(gè)地址的投票數(shù)為1,只有一票
            voters[chairperson].weight = 1;
            // 數(shù)組元素
            myProposalNames = ['tom', 'david', 'Bob'];
    
            // 對(duì)提供的每一個(gè)提案名稱,創(chuàng)建一個(gè)新的提案
            // 對(duì)象添加到數(shù)組末尾
            for (uint i = 0; i < myProposalNames.length; i++)
                // 添加到了提案數(shù)組`proposals`末尾
                proposals.push(
                    // 創(chuàng)建了一個(gè)臨時(shí)的提案對(duì)象
                    Proposal({
                        name: myProposalNames[i],
                        voteCount: 0
                    })
                );
        }
    
        // 給投票人`voter`參加投票的投票權(quán),
        // 只能由投票主持人`chairperson`調(diào)用。
        function giveRightToVote(address voter)
        {
            // 添加可以投票的人,這個(gè)人不可以是投票創(chuàng)建者,不能已經(jīng)投過票
            if (msg.sender != chairperson || voters[voter].voted)
                // `throw`會(huì)終止和撤銷所有的狀態(tài)和以太改變。
                // 如果函數(shù)調(diào)用無效,這通常是一個(gè)好的選擇。
                // 但是需要注意,這會(huì)消耗提供的所有g(shù)as。
                throw;
            // 這個(gè)新的可以投票的人,擁有一票
            voters[voter].weight = 1;
        }
    
        // 委托你的投票權(quán)到一個(gè)投票代表,自己不投,權(quán)利給別人
        function delegate(address to)
        {
            // 首先確定這個(gè)更改投票權(quán)的人,本身自投票人列表中
            Voter sender = voters[msg.sender];
            // 確定他是否已經(jīng)投票
            if (sender.voted)
                throw;
    
            // 當(dāng)投票代表`to`也委托給別人時(shí),尋找到最終的投票代表
            while (voters[to].delegate != address(0) &&
                   voters[to].delegate != msg.sender)
                to = voters[to].delegate;
            // 當(dāng)最終投票代表等于調(diào)用者,是不被允許的。
            if (to == msg.sender)
                throw;
    
            // 因?yàn)閌sender`是一個(gè)引用,
            // 當(dāng)你把投票權(quán)給別人時(shí),你本身是已投票狀態(tài)。
            sender.voted = true;
            // 你的投票代理
            sender.delegate = to;
            // 代理者
            Voter delegate = voters[to];
            // 如果你委托的投票者,已經(jīng)投票
            if (delegate.voted)
                // 那么你的票,直接累加在委托者投票的提案上
                proposals[delegate.vote].voteCount += sender.weight;
            else
                // 如果投票代表還沒有投票,則修改委托者擁有的投票數(shù)量。
                delegate.weight += sender.weight;
        }
    
        // 投出你的選票(包括委托給你的選票)
        // 給 `proposals[proposal].name`。
        function vote(uint proposal)
        {
            // 獲得要投票的對(duì)象
            Voter sender = voters[msg.sender];
            // 判斷是否投票
            if (sender.voted) throw;
            // 修改為已投
            sender.voted = true;
            // 記錄投票者的選擇
            sender.vote = proposal;
            // 如果`proposal`索引超出了給定的提案數(shù)組范圍
            // 將會(huì)自動(dòng)拋出異常,并撤銷所有的改變。
            proposals[proposal].voteCount += sender.weight;
        }
    
       // 根據(jù)當(dāng)前所有的投票計(jì)算出當(dāng)前的勝出提案
        function winningProposal() constant
                returns (uint winningProposal)
        {
            // 獲得投票數(shù),最多的提案編號(hào)
            uint winningVoteCount = 0;
            for (uint p = 0; p < proposals.length; p++)
            {   
                // 記錄投票最多的提案編號(hào)   
                if (proposals[p].voteCount > winningVoteCount)
                {
                    winningVoteCount = proposals[p].voteCount;
                    winningProposal = p;
                }
            }
        }
    }
    
  3. 調(diào)用
    • 部署之后的立刻調(diào)用和之前沒啥區(qū)別
    • 部署之后其他節(jié)點(diǎn)的調(diào)用或者重新打開配置環(huán)境再次調(diào)用
      // 部署之后的再次調(diào)用,需要記住abi
      abi = [{"constant":false,"inputs":[{"name":"proposal","type":"uint256"}],"name":"vote","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"","type":"uint256"}],"name":"proposals","outputs":[{"name":"name","type":"string"},{"name":"voteCount","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"chairperson","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"to","type":"address"}],"name":"delegate","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"winningProposal","outputs":[{"name":"winningProposal","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"uint256"}],"name":"myProposalNames","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"voter","type":"address"}],"name":"giveRightToVote","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"}],"name":"voters","outputs":[{"name":"weight","type":"uint256"},{"name":"voted","type":"bool"},{"name":"delegate","type":"address"},{"name":"vote","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"inputs":[],"payable":false,"stateMutability":"nonpayable","type":"constructor"}]
      // 需要記住部署成功后的Contract mined! address
      contractMinedAddress = '0xcd4dc04ce4452ed24d76b04a80fe4094b178dc22'
      // 獲得bytecode
      // bytecode = eth.getCode(adress);
      // 合約
      contract = web3.eth.contract(abi)
      // 合約實(shí)例對(duì)象
      myContractInstance = contract.at(contractMinedAddress)
      
    • 合約函數(shù)或者數(shù)組,變量的調(diào)用
      1. 一個(gè)公開的變量可以如此
          > myContractInstance.chairperson()
              "0x4079a3f5ffeeb7a84a4a582e9fc5f25579c3bba0"
      2. 一個(gè)公開的數(shù)組
          > myContractInstance.myProposalNames(0)
              "tom"
          // 不可以,需要后綴第幾個(gè)元素,這個(gè)被eth.accounts誤導(dǎo),這個(gè)命令直接輸出數(shù)組,而下面函數(shù)必須輸入index
          > myContractInstance.myProposalNames()
      3. 一個(gè)復(fù)雜的調(diào)用,即如果這個(gè)調(diào)用需要得到礦工去確認(rèn)的
          // 先解鎖
          > personal.unlockAccount(user,'abc123')
          // 然后如此調(diào)用投票給第一個(gè)元素即index為0的元素
          > myContractInstance.vote.sendTransaction(0, {from:user, gas:4700000})
          // 需要去挖礦,才能得到確認(rèn)
          > miner.start()
      

參考資料
Solidity 官方文檔中文版
Solidity 官方文檔
Solidity瀏覽器編譯
智能合約調(diào)用示例

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容