91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

以太坊怎么實現中心化投票DApp與智能合約

發布時間:2022-01-15 14:42:53 來源:億速云 閱讀:180 作者:iii 欄目:互聯網科技

這篇文章主要介紹“以太坊怎么實現中心化投票DApp與智能合約”的相關知識,小編通過實際案例向大家展示操作過程,操作方法簡單快捷,實用性強,希望這篇“以太坊怎么實現中心化投票DApp與智能合約”文章能幫助大家解決問題。

為什么要開發去中心化投票應用?

從本質上講,利用區塊鏈技術的去中心化應用程序允許你在沒有可信賴的第三方的情況下執行與今天相同的操作(如轉移資金)。最好的dApp具有特定的真實世界的用例,以便利用區塊鏈的獨特特征。

  • 從本質上講,區塊鏈是一個共享的,可編程的,加密安全的,可信賴的分類賬本,沒有任何一個用戶可以控制,任何人都可以查詢。- Klaus Schwab

即使投票應用對大家來說可能不是一個偉大的應用程序,但是我選擇使用它作為本指南,這是因為區塊鏈解決的主要問題:透明度,安全性,可訪問性,可信任,是困擾當前民主選舉的主要問題。

由于區塊鏈是去中心化的交易(投票)的永久記錄,因此每次投票都可以無可辯駁地追溯到它發生的時間和地點,而不會泄露選民的身份。此外,過去的投票也不能被改變,而現在也不能被黑客攻擊,因為每個交易都是由網絡中的每個節點驗證的。任何外部或內部攻擊者必須控制51%的節點才能改變記錄。

即使攻擊者能夠在偽造用戶輸入真實身份證投票時也能實現這一點,但端到端投票系統可以讓選民驗證他們的投票是否在系統中正確輸入,這使得系統極其安全。

以太坊的核心組成部分

我希望你讀本指南的其余部分前,了解了區塊鏈和以太坊。這里有一個很棒的指南,寫了我想讓你知道的核心組件的簡要概述。

  • 智能合約充當后端邏輯和存儲。合約是用Solidity一種智能合約語言編寫的,是一個代碼和數據的集合,駐留在以太坊區塊鏈的特定地址。它與面向對象編程中的類非常相似,它包含函數和狀態變量。智能合約以及區塊鏈是所有權力下放應用程序的基礎。像Blockchain一樣,它們是不可變的和分布式的,這意味著如果它們已經在以太坊網絡上,升級它們將是一種痛苦。幸運的是,這里有一些方法可以做到這一點。

  • 以太坊虛擬機(EVM)處理整個以太坊網絡的內部狀態和計算。將EVM視為這種大規模去中心化計算機,其中包含能夠執行代碼,更改數據和相互交互的addresses

  • Web3.js是一個Javascript API,允許你與區塊鏈進行交互,包括進行交易和調用智能合約。此API抽象了與以太坊客戶端的通信,允許開發人員專注于他們的應用程序的內容。你必須在瀏覽器中嵌入一個web3實例才能執行此操作。

我們將使用的其他工具

  • Truffle是以太坊的流行測試開發框架。它包括開發區塊鏈,編譯和遷移腳本,用于將合約部署到區塊鏈,合約測試等。它使開發更容易!

  • Truffle Contracts是Web3 Javascript API之上的抽象,允許你輕松連接智能合約并與之互動。

  • Metamask將以太坊帶入你的瀏覽器。它是一個瀏覽器擴展,提供鏈接到你的以太坊地址的安全web3實例,允許你使用去中心化應用程序。我們不會在本教程中使用Metamask,但它是人們在生產中與DApp交互的一種方式。相反,我們將在開發期間注入我們自己的web3實例。有關更多信息,請查看此鏈接。

開始吧!

為簡單起見,我們實際上不會構建我之前描述的完整投票系統。為了便于說明,它只是一個單頁應用程序,用戶可以輸入他們的ID并為候選人投票。還將有一個按鈕,計算并顯示每個候選人的投票數。

這樣,我們將能夠專注于在應用程序中創建智能合約并與之交互的過程。整個應用程序的源代碼將在此存儲庫中,你需要安裝Node.js和npm。

1.首先,讓我們在全局范圍內安裝Truffle。
npm install -g truffle

要使用Truffle命令,必須在現有項目中運行它們。

git clone https://github.com/tko22/truffle-webpack-boilerplate
cd truffle-webpack-boilerplate
npm install

這個存儲庫只是一個Truffle Box的框架,它是可以在一個命令中獲得的樣板或示例應用程序 - truffle unbox [box name]。但是,帶有webpack的Truffle box未使用最新版本進行更新,并包含一個示例應用程序。因此,我創建了這個repo。

2.目錄結構

你的目錄結構應包括以下內容:

  • contracts/:包括所有合約的文件夾。不要刪除Migrations.sol

  • migrations/:包含Migration files的文件夾,可幫助你將智能合約部署到區塊鏈中。

  • src/:保存應用程序的HTML/CSS和Javascript文件。

  • truffle.js:truffle配置文件。

  • build/:在編譯合約之前,你不會看到此文件夾。此文件夾包含構建文件,因此不要修改任何這些文件!構建文件描述了合約的功能和體系結構,并提供了有關如何與區塊鏈中的智能合約進行交互的Truffle Contracts和web3信息。

1.寫下你的智能合約

設置和介紹完,讓我們開始寫代碼吧!首先,我們將編寫我們的智能合約,這是用Solidity編寫的(其他語言不那么受歡迎)。這可能看起來很不爽,但事實并非如此。

對于任何應用程序,你希望智能合約盡可能簡單,甚至是非常簡單。請記住,你必須為你所做的每筆計算/交易付費,而你的智能合約將永遠存在于區塊鏈中。所以,你真的希望它能夠完美地運作——也就是說,它越復雜,就越容易犯錯誤。

我們的合約將包括:

  • 狀態變量:包含永久存儲在區塊鏈中的值的變量。我們將使用狀態變量來保存選民和候選人的名單和數量。

  • 函數:函數是智能合約的可執行文件。它們是我們要求與區塊鏈進行交互的內容,具有不同級別的內部和外部可見性。請記住,無論何時你想要更改變量的值/狀態,都必須進行交易——這要耗費以太幣。你也可以calls區塊鏈,這不會花費任何以太,因為你所做的更改將被銷毀(當我們實際進行transactionscall時,在下面會有更多內容)。

  • 事件:每當調用事件時,傳遞給事件的值都將記錄在交易日志中。這允許Javascript回調函數或已解析的promises查看你想要在交易之后傳回的特定值。這是因為每次進行交易時,都會返回交易日志。我們將使用一個事件來記錄新創建的候選者的ID,我們將顯示該ID。

  • 結構類型 - 這與C結構非常相似。Structs允許你保存多個變量,并且對于具有多個屬性的事物非常棒。Candidates只會有他們的名字和黨派,但你絕對可以為他們添加更多屬性。

  • 映射 - 將它們視為hash映射或字典,它具有鍵值對。我們將使用兩個映射。

這里沒有列出更多類型,但有些類型稍微復雜一些。這五個包含了智能合約通常使用的大部分結構。這里將更深入地解釋這些類型。

作為參考,這是智能合約的代碼。請注意,此文件應該被稱為Voting.sol但我希望Github gist具有style,所以我給它一個.js擴展名。與本指南的其余部分一樣,我將在代碼中提供注釋解釋它正在做什么,然后我將在指出某些警告和邏輯的同時解釋大體思路。

pragma solidity ^0.4.18;
// written for Solidity version 0.4.18 and above that doesnt break functionality

contract Voting {
    // an event that is called whenever a Candidate is added so the frontend could
    // appropriately display the candidate with the right element id (it is used
    // to vote for the candidate, since it is one of arguments for the function "vote")
    event AddedCandidate(uint candidateID);

    // describes a Voter, which has an id and the ID of the candidate they voted for
    struct Voter {
        bytes32 uid; // bytes32 type are basically strings
        uint candidateIDVote;
    }
    // describes a Candidate
    struct Candidate {
        bytes32 name;
        bytes32 party; 
        // "bool doesExist" is to check if this Struct exists
        // This is so we can keep track of the candidates 
        bool doesExist; 
    }

    // These state variables are used keep track of the number of Candidates/Voters 
    // and used to as a way to index them     
    uint numCandidates; // declares a state variable - number Of Candidates
    uint numVoters;

    
    // Think of these as a hash table, with the key as a uint and value of 
    // the struct Candidate/Voter. These mappings will be used in the majority
    // of our transactions/calls
    // These mappings will hold all the candidates and Voters respectively
    mapping (uint => Candidate) candidates;
    mapping (uint => Voter) voters;
    
    /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
     *  These functions perform transactions, editing the mappings *
     * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

    function addCandidate(bytes32 name, bytes32 party) public {
        // candidateID is the return variable
        uint candidateID = numCandidates++;
        // Create new Candidate Struct with name and saves it to storage.
        candidates[candidateID] = Candidate(name,party,true);
        AddedCandidate(candidateID);
    }

    function vote(bytes32 uid, uint candidateID) public {
        // checks if the struct exists for that candidate
        if (candidates[candidateID].doesExist == true) {
            uint voterID = numVoters++; //voterID is the return variable
            voters[voterID] = Voter(uid,candidateID);
        }
    }

    /* * * * * * * * * * * * * * * * * * * * * * * * * * 
     *  Getter Functions, marked by the key word "view" *
     * * * * * * * * * * * * * * * * * * * * * * * * * */
    

    // finds the total amount of votes for a specific candidate by looping
    // through voters 
    function totalVotes(uint candidateID) view public returns (uint) {
        uint numOfVotes = 0; // we will return this
        for (uint i = 0; i < numVoters; i++) {
            // if the voter votes for this specific candidate, we increment the number
            if (voters[i].candidateIDVote == candidateID) {
                numOfVotes++;
            }
        }
        return numOfVotes; 
    }

    function getNumOfCandidates() public view returns(uint) {
        return numCandidates;
    }

    function getNumOfVoters() public view returns(uint) {
        return numVoters;
    }
    // returns candidate information, including its ID, name, and party
    function getCandidate(uint candidateID) public view returns (uint,bytes32, bytes32) {
        return (candidateID,candidates[candidateID].name,candidates[candidateID].party);
    }
}

基本上,我們有兩個Structs(包含多個變量的類型),用于描述選民和候選人。使用Structs,我們可以為它們分配多個屬性,例如電子郵件,地址等。

為了跟蹤選民和候選人,我們將它們放入單獨的映射中,它們是整數索引的。候選人或選民的索引/密鑰——讓我們稱之為ID——是函數訪問它們的唯一方式。

我們還會跟蹤選民和候選人的數量,這將有助于我們為他們編制索引。此外,不要忘記第8行中的事件,該事件將在添加時記錄候選人的ID。我們的界面將使用此事件,因為我們需要跟蹤候選人的ID以便為候選人投票。

  • 1.我知道,與我之前所說的關于使合約變得非常簡單的說法相反,我認為這個合約與這個應用實際上做的相比有點復雜。但是,我這樣做是為了讓你們更容易進行編輯并在之后為此應用程序添加功能(最后更多內容)。如果你想制作一個更簡單的投票應用程序,智能合約可以在不到15行代碼。

  • 2.請注意,狀態變量numCandidatesnumVoters未聲明為public。默認情況下,這些變量具有internal可見性,這意味著它們只能由當前合約或派生合約直接訪問(不用擔心,我們不會使用它)。

  • 3.我們使用32bytes用于字符串而不是使用string類型。我們的EVM具有32字節的字大小,因此它被optimized以處理32字節的塊中的數據。(當數據不是32字節的塊時,編譯器,例如Solidity,必須做更多的工作并生成更多的字節碼,這實際上會導致更高的天然氣成本。)

  • 4.當用戶投票時,會創建一個新的Voter結構并將其添加到映射中。為了計算某個候選人的投票數,你必須遍歷所有選民并計算投票數。候選人的行為相同。因此,這些映射將保留所有候選人和選民的歷史。

2.實例化web3和合約

完成我們的智能合約后,我們現在需要運行我們的測試區塊鏈并將此合約部署到區塊鏈上。我們還需要一種方法來與它交互,這將通過web3.js完成。

在我們開始測試區塊鏈之前,我們必須在/contracts文件夾中創建一個名為2_deploy_contracts.js的文件,告訴它在遷移時包含你的投票智能合約。

var Voting = artifacts.require("Voting")

module.exports = function(deployer) {
  deployer.deploy(Voting)
}

要開始開發以太坊區塊鏈,請轉到命令行并運行:

truffle develop

由于Solidity是一種編譯語言,我們必須首先將其編譯為字節碼,以便EVM執行。

compile

你現在應該在目錄中看到一個文件夾build/。此文件夾包含構建文件,這對Truffle的內部工作至關重要,因此請勿修改它們!

接下來,我們必須遷移合約。migrations是一個truffle腳本,可幫助你在開發時更改應用程序合約的狀態。請記住,你的合約已部署到區塊鏈上的某個地址,因此無論何時進行更改,你的合約都將位于不同的地址。 遷移可幫助你執行此操作,還可幫助你移動數據。

migrate

恭喜!你的智能合約現在永遠在區塊鏈上。好吧,還不是真的...... 因為truffle develop會在每次停止時刷新。

如果你想擁有一個持久的區塊鏈,可以考慮一下由Truffle開發的Ganache。如果你使用的是Ganache,則無需調用truffle develop。相反,你將運行truffle compiletruffle migrate。要了解在沒有Truffle的情況下部署合約需要什么,請查看此博客文章。

一旦我們將智能合約部署到區塊鏈,我們將不得不在應用程序啟動時在瀏覽器上使用Javascript設置web3.0實例。因此,下一段代碼將放在js/app.js的底部。請注意,我們使用的是web3.0版本0.20.1。

// When the page loads, we create a web3 instance and set a provider. We then set up the app
window.addEventListener("load", function() {
  // Is there an injected web3 instance?
  if (typeof web3 !== "undefined") {
    console.warn("Using web3 detected from external source like Metamask")
    // If there is a web3 instance(in Mist/Metamask), then we use its provider to create our web3object
    window.web3 = new Web3(web3.currentProvider)
  } else {
    console.warn("No web3 detected. Falling back to http://localhost:9545. You should remove this fallback when you deploy live, as it's inherently insecure. Consider switching to Metamask for development. More info here: http://truffleframework.com/tutorials/truffle-and-metamask")
    // fallback - use your fallback strategy (local node / hosted node + in-dapp id mgmt / fail)
    window.web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:9545"))
  }
  // initializing the App
  window.App.start()
})

如果你不理解這段代碼,你真的不必太擔心。只要知道這將在應用程序啟動時運行,并將檢查瀏覽器中是否已存在web3實例(Metamask)。如果沒有,我們將創建一個與localhost:9545交互Truffle開發區塊鏈。

如果你正在使用Ganache,你必須將端口更改為7545.一旦創建了一個實例,我們將調用start函數。

3.添加功能

我們需要做的最后一件事是為應用程序編寫接口。這涉及任何Web應用程序的基本要素——HTML,CSS和Javascript(我們已經編寫了一些用于創建web3實例的Javascript)。首先,讓我們創建我們的HTML文件。

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <!-- The above 3 meta tags *must* come first in the head; any other head content must come *after* these tags -->
    <title>Ethereum Voting Dapp</title>

    <!-- Bootstrap -->
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta.3/css/bootstrap.min.css" integrity="sha384-Zug+QiDoJOrZ5t4lssLdxGhVrurbmBWopoEl+M6BdEfwnCJZtKxi1KgxUyJq13dy" crossorigin="anonymous">
    
  </head>
  <body>
    <div class="container">
      <div class="row">
        <div>
          <h2 class="text-center">Ethereum Voting Dapp</h2>
          <hr/>
          <br/>
        </div>
      </div>
      <div class="row">
        <div class="col-md-4">
          <p>Add ID and click candidate to vote</p>
          <div class="input-group mb-3">
            <input type="text" class="form-control" id="id-input" placeholder="Enter ID">
          </div>
          <div class="candidate-box"></div>
          <button class="btn btn-primary" onclick="App.vote()">Vote</button>
          <div class="msg"></div>
        </div>
        <div class="col-md-6">
            <button class="btn btn-primary" onclick="App.findNumOfVotes()">Count Votes</button>
            <div id="vote-box"></div>
        </div>
      </div>
    </div>

    <!-- jQuery (necessary for Bootstrap's JavaScript plugins) -->
    <script src="https://code.jquery.com/jquery-3.2.1.slim.min.js" integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN" crossorigin="anonymous"></script>
    <!-- Include all compiled plugins (below), or include individual files as needed -->
    <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js" integrity="sha384-ApNbgh9B+Y1QKtv3Rn7W3mgPxhU9K/ScQsAP7hUibX39j7fakFPskvXusvfa0b4Q" crossorigin="anonymous"></script>
    <script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta.3/js/bootstrap.min.js" integrity="sha384-a5N7Y/aK3qNeh25eJKGWxsqtnX/wWdSZSKp+81YjTmS15nvnvxKHuzaWwXHDli+4" crossorigin="anonymous"></script>

    <!-- Custom Scripts -->
    <script src="app.js"></script>
  </body>
</html>

這是一個非常簡單的頁面,帶有用戶ID的輸入表單,以及用于投票和計票的按鈕。點擊這些按鈕后,他們將調用投票的特定功能,并找到候選人的投票數。

但是有三個重要的div元素,其中有id:candidate-boxmsgvote-box,它們分別包含每個候選者的復選框,一條消息和一個投票數。我們還導入了JQuery,Bootstrap和app.js

現在,我們只需要與合約互動并實施投票和計算每個候選人的投票數量的功能。JQuery將控制DOM,當我們進行交易或調用Blockchain時,我們將使用Promises。以下是app.js的代碼。

// import CSS. Webpack with deal with it
import "../css/style.css"

// Import libraries we need.
import { default as Web3} from "web3"
import { default as contract } from "truffle-contract"

// get build artifacts from compiled smart contract and create the truffle contract
import votingArtifacts from "../../build/contracts/Voting.json"
var VotingContract = contract(votingArtifacts)

/*
 * This holds all the functions for the app
 */
window.App = {
  // called when web3 is set up
  start: function() { 
    // setting up contract providers and transaction defaults for ALL contract instances
    VotingContract.setProvider(window.web3.currentProvider)
    VotingContract.defaults({from: window.web3.eth.accounts[0],gas:6721975})

    // creates an VotingContract instance that represents default address managed by VotingContract
    VotingContract.deployed().then(function(instance){

      // calls getNumOfCandidates() function in Smart Contract, 
      // this is not a transaction though, since the function is marked with "view" and
      // truffle contract automatically knows this
      instance.getNumOfCandidates().then(function(numOfCandidates){

        // adds candidates to Contract if there aren't any
        if (numOfCandidates == 0){
          // calls addCandidate() function in Smart Contract and adds candidate with name "Candidate1"
          // the return value "result" is just the transaction, which holds the logs,
          // which is an array of trigger events (1 item in this case - "addedCandidate" event)
          // We use this to get the candidateID
          instance.addCandidate("Candidate1","Democratic").then(function(result){ 
            $("#candidate-box").append(`<div class='form-check'><input class='form-check-input' type='checkbox' value='' id=${result.logs[0].args.candidateID}><label class='form-check-label' for=0>Candidate1</label></div>`)
          })
          instance.addCandidate("Candidate2","Republican").then(function(result){
            $("#candidate-box").append(`<div class='form-check'><input class='form-check-input' type='checkbox' value='' id=${result.logs[0].args.candidateID}><label class='form-check-label' for=1>Candidate1</label></div>`)
          })
          // the global variable will take the value of this variable
          numOfCandidates = 2 
        }
        else { // if candidates were already added to the contract we loop through them and display them
          for (var i = 0; i < numOfCandidates; i++ ){
            // gets candidates and displays them
            instance.getCandidate(i).then(function(data){
              $("#candidate-box").append(`<div class="form-check"><input class="form-check-input" type="checkbox" value="" id=${data[0]}><label class="form-check-label" for=${data[0]}>${window.web3.toAscii(data[1])}</label></div>`)
            })
          }
        }
        // sets global variable for number of Candidates
        // displaying and counting the number of Votes depends on this
        window.numOfCandidates = numOfCandidates 
      })
    }).catch(function(err){ 
      console.error("ERROR! " + err.message)
    })
  },

  // Function that is called when user clicks the "vote" button
  vote: function() {
    var uid = $("#id-input").val() //getting user inputted id

    // Application Logic 
    if (uid == ""){
      $("#msg").html("<p>Please enter id.</p>")
      return
    }
    // Checks whether a candidate is chosen or not.
    // if it is, we get the Candidate's ID, which we will use
    // when we call the vote function in Smart Contracts
    if ($("#candidate-box :checkbox:checked").length > 0){ 
      // just takes the first checked box and gets its id
      var candidateID = $("#candidate-box :checkbox:checked")[0].id
    } 
    else {
      // print message if user didn't vote for candidate
      $("#msg").html("<p>Please vote for a candidate.</p>")
      return
    }
    // Actually voting for the Candidate using the Contract and displaying "Voted"
    VotingContract.deployed().then(function(instance){
      instance.vote(uid,parseInt(candidateID)).then(function(result){
        $("#msg").html("<p>Voted</p>")
      })
    }).catch(function(err){ 
      console.error("ERROR! " + err.message)
    })
  },

  // function called when the "Count Votes" button is clicked
  findNumOfVotes: function() {
    VotingContract.deployed().then(function(instance){
      // this is where we will add the candidate vote Info before replacing whatever is in #vote-box
      var box = $("<section></section>") 

      // loop through the number of candidates and display their votes
      for (var i = 0; i < window.numOfCandidates; i++){
        // calls two smart contract functions
        var candidatePromise = instance.getCandidate(i)
        var votesPromise = instance.totalVotes(i)

        // resolves Promises by adding them to the variable box
        Promise.all([candidatePromise,votesPromise]).then(function(data){
          box.append(`<p>${window.web3.toAscii(data[0][1])}: ${data[1]}</p>`)
        }).catch(function(err){ 
          console.error("ERROR! " + err.message)
        })
      }
      $("#vote-box").html(box) // displays the "box" and replaces everything that was in it before
    })
  }
}

// When the page loads, we create a web3 instance and set a provider. We then set up the app
window.addEventListener("load", function() {
  // Is there an injected web3 instance?
  if (typeof web3 !== "undefined") {
    console.warn("Using web3 detected from external source like Metamask")
    // If there is a web3 instance(in Mist/Metamask), then we use its provider to create our web3object
    window.web3 = new Web3(web3.currentProvider)
  } else {
    console.warn("No web3 detected. Falling back to http://localhost:9545. You should remove this fallback when you deploy live, as it's inherently insecure. Consider switching to Metamask for deployment. More info here: http://truffleframework.com/tutorials/truffle-and-metamask")
    // fallback - use your fallback strategy (local node / hosted node + in-dapp id mgmt / fail)
    window.web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:9545"))
  }
  // initializing the App
  window.App.start()
})

請注意,我在上一步中用于創建web3實例的代碼也在這里。首先,我們導入必要的庫和webpack內容,包括web3和Truffle Contracts。我們將使用Truffle Contracts,它建立在web3之上,與Blockchain進行交互。

要使用它,我們將獲取在編譯投票智能合約時自動構建的構建文件,并使用它們來創建Truffle Contracts。最后,我們在全局變量windows中設置函數,用于啟動應用程序,投票給候選人,以及查找投票數。

要實際與區塊鏈交互,我們必須使用deployed的功能創建松露合約的實例。反過來,這將返回一個承諾,該實例作為你將用于從智能合約調用函數的返回值。

有兩種方法可以與這些功能進行交互:交易和調用。交易是一種寫操作,它將被廣播到整個網絡并由礦工處理(因此,成本為Ether)。如果要更改狀態變量,則必須執行交易,因為它將更改區塊鏈的狀態。

call是一種讀操作,模擬交易但丟棄狀態變化。因此,它不會花費以太。這非常適合調用getter函數(查看我們之前在智能合約中編寫的四個getter函數)。

要使用Truffle Contracts進行交易,你可以編寫instance.functionName(param1,param2),將instance作為deployed函數返回的實例(例如,檢查第36行)。此事務將返回一個以交易數據作為返回值的promise。因此,如果在智能合約函數中返回一個值,但是使用相同的函數執行交易,則不會返回該值。

這就是為什么我們有一個事件會記錄你想要寫入要返回的交易數據的任何內容。在第36-37行,我們進行交易以添加一個候選人即Candidate。當我們確定promise時,我們在結果中有交易數據。

要獲取我們使用事件AddedCandidate()記錄的候選ID(檢查智能合約以查看它0),我們必須檢查日志并檢索它:result.logs[0].args.candidateID

要真正了解正在發生的事情,請使用Chrome開發人員工具打印result并查看其result結構。

要進行調用,你將編寫instance.functionName.call(param1,param2)。但是,如果某個函數具有關鍵字view,那么Truffle Contracts將自動創建一個調用,因此你無需添加.call`。

這就是我們的getter函數具有view關鍵字的原因。與進行交易不同,返回的調用promise將具有智能合約函數返回的任何返回值。

我現在將簡要解釋這三個函數,但如果你構建了從數據存儲中檢索/更改數據并相應地操作DOM的應用程序,那么這應該非常熟悉。將Blockchain視為你的數據庫,將Truffle Contracts視為從數據庫獲取數據的API。

App.start()

創建web3實例后立即調用此函數。要使Truffle Contracts正常工作,我們必須將接口設置為創建的web3實例并設置默認值(例如你正在使用的帳戶以及你要為交易支付的gas量)。

由于我們處于開發模式,我們可以使用任何數量的gas和任何帳戶。在生產過程中,我們將采用MetaMask提供的帳戶,并嘗試找出你可以使用的最少量的gas,因為它實際上是真錢。

設置好所有內容后,我們現在將顯示每個候選人的復選框,供用戶投票。為此,我們必須創建合約實例并獲取候選人的信息。如果沒有候選人,我們將創建他們。為了讓用戶投票給候選人,我們必須提供該特定候選人的ID。因此,我們使每個checkbox元素具有候選ID的id(HTML元素屬性)。另外,我們將把候選數量添加到全局變量numOfCandidates中,我們將在App.findNumOfVotes()中使用它。JQuery用于將每個復選框及其候選名稱附加到.candidate-box

App.vote()

此功能將根據單擊的復選框及其id屬性為某個候選人投票。

  • 1.我們將檢查用戶是否輸入了他們的userID,這是他們的身份。如果他們沒有,我們會顯示一條消息告訴他們需要這樣做。

  • 2.我們將檢查用戶是否正在為候選人投票,檢查是否至少有一個被點擊的復選框。如果沒有點擊任何復選框,我們也會顯示一條消息,告訴他們請投票給候選人。如果單擊其中一個復選框,我們將獲取該復選框的id屬性,該屬性也是鏈接候選人的ID,并使用該屬性為候選人投票。

交易完成后,我們將解決退回的承諾并顯示Voted已經完成投票的消息。

App.findNumOfVotes()

最后一個函數將找到每個候選人的投票數并顯示它們。我們將通過候選人并調用兩個智能合約函數,getCandidatetotalVotes。我們將解決這些承諾并為該特定候選人創建HTML元素。

現在,啟動應用程序,你將在`http://localhost:8080/上看到它!

npm run dev

資源

我知道,這很多......當你慢慢開發這個應用程序并真正了解正在發生的事情時,你可能會暫時打開這篇文章。但那是在學習!請使用以太網,truffle以及我在下面提供的所有文檔補充本指南。我試圖點擊本文中的許多關鍵點,但這只是一個簡短的概述,這些資源將有很大幫助。

  • 關于Solidity和Smart Contracts的一切:我的意思是一切。

  • 關于truffle一切

  • truffle contract 文檔

  • Web3 Javascript API:這將是很好的知識和參考,但松露合約抽象了很多部分。

  • 有用的DApp模式

  • 以太坊文件:看目錄,有很多東西。

  • CryptoKitties代碼說明:作者介紹了CryptoKitties的智能合約的重要部分。

  • 智能合約最佳實踐:必讀。

關于“以太坊怎么實現中心化投票DApp與智能合約”的內容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業相關的知識,可以關注億速云行業資訊頻道,小編每天都會為大家更新不同的知識點。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

子长县| 辽源市| 辽宁省| 新乐市| 张家界市| 长沙县| 石嘴山市| 瓦房店市| 蚌埠市| 宁海县| 甘肃省| 绿春县| 芦山县| 焦作市| 枣强县| 浠水县| 定襄县| 登封市| 乌鲁木齐县| 潢川县| 北安市| 茂名市| 时尚| 江源县| 洞口县| 泽普县| 惠安县| 米易县| 新营市| 抚宁县| 阜南县| 泰来县| 敖汉旗| 东光县| 蒲城县| 永济市| 邮箱| 肃南| 民勤县| 翁源县| 固镇县|