成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

python和flask框架開發(fā)以太坊智能合約

UnixAgain / 2377人閱讀

摘要:是以太坊開發(fā)的個人區(qū)塊鏈,可用于部署合約,開發(fā)應用程序和運行測試。安裝是一個用于與以太坊交互的庫。啟動以太坊測試區(qū)塊鏈服務(wù)器要部署智能合約,我們應該啟動測試以太坊服務(wù)器。最后,你將在以太坊合約中設(shè)置調(diào)用用戶對象時獲得的值。

將數(shù)據(jù)存儲在數(shù)據(jù)庫中是任何軟件應用程序不可或缺的一部分。無論如何控制該數(shù)據(jù)庫都有一個該數(shù)據(jù)的主控。區(qū)塊鏈技術(shù)將數(shù)據(jù)存儲到區(qū)塊鏈網(wǎng)絡(luò)內(nèi)的區(qū)塊中。因此,只要某個節(jié)點與網(wǎng)絡(luò)同步,它們就會獲得區(qū)塊中數(shù)據(jù)的副本。因此,該技術(shù)中沒有特定的數(shù)據(jù)主控。

在本教程中,我們將編寫一份智能合約(我將進一步解釋),以便在區(qū)塊鏈上保留用戶數(shù)據(jù)。我們將使用python web3(web3的python庫)來開發(fā)和部署智能合約。一旦我們在區(qū)塊鏈上部署了智能合約。我們將使用flask API與智能合約進行交互以存儲一些數(shù)據(jù)/信息。我們將它存儲在區(qū)塊鏈上,它是不可變的。

環(huán)境要求

Python 3.6

安裝

1.創(chuàng)建一個python虛擬環(huán)境。

Virtualenv將你的Python軟件包本地化保存在你項目的虛擬環(huán)境中,而不是強迫你在系統(tǒng)范圍內(nèi)安裝軟件包。

$ virtualenv -p /usr/bin/python3.6 venv
$ source venv/bin/activate

2.現(xiàn)在我們需要Ganache那樣的以太坊測試鏈。

Ganache是以太坊開發(fā)的個人區(qū)塊鏈,可用于部署合約,開發(fā)應用程序和運行測試。

$ npm install -g ganache-cli

3.安裝python web3

Web3.py是一個用于與以太坊交互的python庫。它的API源自Web3.js Javascript API,對于使用過web3.js的人來說應該很熟悉。

$ pip3 install web3

4.Flask

Flask是一個python輕量級框架。

$ pip3 install flask

5.Flask Restful

Flask-RESTful是Flask的擴展,增加了對快速構(gòu)建REST API的支持。

$ pip3 install flask-restful

Flask Marshmallow

Flask marshmallow是一個對象序列化/反序列化庫。

$ pip3 install flask-marshmallow
啟動以太坊測試區(qū)塊鏈服務(wù)器

要部署智能合約,我們應該啟動測試以太坊服務(wù)器。我們正在使用ganache進行測試。在終端中鍵入以下命令:

$ ganache-cli

Ganache為我們提供了10個默認測試帳戶,每個帳戶中有100個假ether,用于交易。我們將使用這些帳戶在合約中部署和設(shè)置各種值。

我們可以看到gas價格和限制以及部署ganachehost:port。我們在部署合約時需要這個。

創(chuàng)建user.sol文件

現(xiàn)在我們將用Solidity編寫智能合約。Solidity是在ethereum上編寫智能合約的語言。智能合約包括我們將在區(qū)塊鏈上存儲的數(shù)據(jù),數(shù)據(jù)和getter方法的可選驗證函數(shù),訪問數(shù)據(jù)的setter方法。

例如,要在區(qū)塊鏈上進行考勤注冊,你將擁有一組用戶對象。它將可以訪問用戶的getter,setter方法。由于每個用戶每天只能標記一次出勤,因此你需要一個驗證功能來檢查,智能合約與我們通常用其他任何語言開發(fā)的應用程序非常相似。

在下面的文件中,我們使用getter,setter函數(shù)構(gòu)建簡單的用戶合約。

1.在.sol文件中聲明solidity編譯器版本。

pragma solidity ^ 0.4.21;

了解使用的編譯器版本。

$ solidity?—?version

2.導入庫文件Import library。我們應該將庫用于常用的實用程序函數(shù)。庫可以只編譯一次并反復使用(點擊這里獲取一些好的庫資源)。

import“stringUtils.sol”;

3.為用戶聲明合約

contract userRecords {}

4.現(xiàn)在,對于基本演示,我們將存儲有關(guān)用戶的名稱和性別信息。因此,使用struct和enum數(shù)據(jù)類型初始化這兩個變量。

//枚舉類型變量來存儲用戶性別
enum genderType { male, female } 
//我們將存儲在以太坊合約中的實際用戶對象
struct user{ 
    string name; genderType gender; 
}

5.現(xiàn)在我們將聲明user(struct)類型的用戶對象。也可以將其聲明為public,以便從合約外部訪問它(有關(guān)可見范圍,請單擊此處)。

user user_obj;

6.現(xiàn)在為用戶對象添加getter,setter方法。我們將在區(qū)塊鏈上保留每個用戶的信息。我們應該始終公開此方法,因為我們將從合約外部訪問它們。

//設(shè)置用戶公共功能
//這類似于db中的持久對象。
function setUser(string name, string gender) public {
    genderType gender_type = getGenderFromString(gender);
    user_obj = user({name:name, gender: gender_type});
}
//獲取用戶公共功能
//這類似于從db獲取對象。
function getUser() public returns (string, string) { 
    return (user_obj.name, getGenderToString(user_obj.gender));
}

7.請注意,我們使用了兩個內(nèi)部函數(shù)getGenderFromString()getGenderToString()。讓我們添加這個內(nèi)部函數(shù)。將它們聲明為內(nèi)部,因為我們不會在外面使用它們。

//用于從string中轉(zhuǎn)換genderType枚舉的內(nèi)部函數(shù)
function getGenderFromString(string gender) internal returns(genderType) {
    if(StringUtils.equal(gender, "male")) {
        return genderType.male;
    } else {
        return genderType.female;
    }
}
//將genderType枚舉轉(zhuǎn)換為字符串的內(nèi)部函數(shù)
(string) {
    if(gender == genderType.male) {
        return "male";
    } else {
        return "female";
    }
}

我們正在使用stringUtils.equal()庫函數(shù)。由于此版本的solidity不支持使用(==)進行字符串比較。

8.現(xiàn)在我們的user.sol文件合約如下所示:

pragma solidity ^0.4.21;
// import library file
import "stringUtils.sol";
contract userRecords {
  // enum type variable to store user gender
  enum genderType { male, female };
  // Actual user object which we will store
  struct user{
    string name;
    genderType gender;
  }
  // user object
  user user_obj;
  //Internal function to conver genderType enum from string
  function getGenderFromString(string gender) internal returns   (genderType) {
    if(StringUtils.equal(gender, "male")) {
      return genderType.male;
    } else {
      return genderType.female;
    }
  }
  //Internal function to convert genderType enum to string
  function getGenderToString(genderType gender) internal returns (string) {
    if(gender == genderType.male) {
      return "male";
    } else {
      return "female";
    }
  }
  // set user public function
  // This is similar to persisting object in db.
  function setUser(string name, string gender) public {
    genderType gender_type = getGenderFromString(gender);
    user_obj = user({name:name, gender: gender_type});
  }
  
  // get user public function
  // This is similar to getting object from db.
  function getUser() public returns (string, string) {
    return (user_obj.name, getGenderToString(user_obj.gender));
  }
}
使用python腳本編譯和部署solidity文件。

1.在下面的python腳本中,我們需要實例化python-web3測試以太坊節(jié)點。我們將設(shè)置ganche url為測試以太坊節(jié)點。我們將使用下面的w3對象來部署合約。

from web3 import Web3
# web3.py instance
w3 = Web3(Web3.HTTPProvider("http://127.0.0.1:8545"))

2.現(xiàn)在我們將編譯solidity代碼。為了編譯solidity代碼,我們使用py-solc,它是用于solidity編譯器的python擴展。

from solc import compile_files
# 編譯所有合約文件
contracts = compile_files(["user.sol", "stringUtils.sol"])
# 多帶帶的主文件和鏈接文件
main_contract = contracts.pop("user.sol:userRecords")
library_link = contracts.pop("stringUtils.sol:StringUtils")

3.每當使用import語句編譯.sol文件時。我們還需要鏈接導入文件的部署地址以及主合約。 因此,對于部署所有鏈接首先通過編譯它(如果已經(jīng)部署然后保存地址)請參見下圖主合約的bin。

當你編譯主合約時,如果你看到它的bin部分,你將找到我們正在導入的庫的_stringUtils.sol:StringUtils ___________(它也可以用于合約)。 這部分我們應該通過在部署合約之前的庫地址來替換它。

4.然后我們將庫地址與主合約相關(guān)聯(lián)。

from solc import link_code
def deploy_contract(contract_interface):
    #實例化和部署合約
    contract = w3.eth.contract(
        abi=contract_interface["abi"],
        bytecode=contract_interface["bin"]
    )
    #從已部署的合約中獲取交易哈希
    tx_hash = contract.deploy(
        transaction={"from": w3.eth.accounts[1]}
    )
    #獲取tx收據(jù)以獲取合約地址
    tx_receipt = w3.eth.getTransactionReceipt(tx_hash)
    return tx_receipt["contractAddress"]
library_address = {
    "stringUtils.sol:StringUtils": deploy_contract(library_link)
}
main_contract["bin"] = link_code(
    main_contract["bin"], library_address
)

鏈接后主合約bin的見下圖:

你將看到導入庫的bin已添加。

5.現(xiàn)在使用我們的w3對象部署主合約。使用ethereum account {"from":w3.eth.accounts [1]}的默認地址進行部署。

def deploy_contract(contract_interface):
    # 實例化和部署合約
    contract = w3.eth.contract(
        abi=contract_interface["abi"],
        bytecode=contract_interface["bin"]
    )
    # 從部署的合約中獲取交易哈希
    tx_hash = contract.deploy(
        transaction={"from": w3.eth.accounts[1]}
    )
    # 獲取tx收據(jù)以獲取合同地址
    tx_receipt = w3.eth.getTransactionReceipt(tx_hash)
    return tx_receipt["contractAddress"]
contract_address = deploy_contract(main_contract)

你將在運行g(shù)anache測試服務(wù)器的選項卡中看到以下這行:

這與合約部署后在tx_receipt中獲得的信息相同。

6.現(xiàn)在將abi和contract_address存儲在json文件中。這樣我們以后可以在flask api中使用它來存儲合約中的用戶對象。

# 在json文件中添加abi(應用程序二進制接口)和交易收據(jù)
with open("data.json", "w") as outfile:
    data = {
       "abi": main_contract["abi"],
       "contract_address": deploy_contract(main_contract)
    }
    json.dump(data, outfile, indent=4, sort_keys=True)

7.現(xiàn)在我們的完整腳本如下所示:

import json
from web3 import Web3
from solc import compile_files, link_code, compile_source
# web3.py instance
w3 = Web3(Web3.HTTPProvider("http://127.0.0.1:8545"))
def deploy_contract(contract_interface):
    # Instantiate and deploy contract
    contract = w3.eth.contract(
        abi=contract_interface["abi"],
        bytecode=contract_interface["bin"]
    )
    # Get transaction hash from deployed contract
    tx_hash =contract.deploy(transaction{"from":w3.eth.accounts[1]})
    # Get tx receipt to get contract address
    tx_receipt = w3.eth.getTransactionReceipt(tx_hash)
    return tx_receipt["contractAddress"]
# compile all contract files
contracts = compile_files(["user.sol", "stringUtils.sol"])
# separate main file and link file
main_contract = contracts.pop("user.sol:userRecords")
library_link = contracts.pop("stringUtils.sol:StringUtils")
# print bin part in  console you will see "stringUtils" in that we need to link library address in that bin code.
# to that we have to deploy library code first then link it
library_address = {
    "stringUtils.sol:StringUtils": deploy_contract(library_link)
}
main_contract["bin"] = link_code(
    main_contract["bin"], library_address)
# add abi(application binary interface) and transaction reciept in json file
with open("data.json", "w") as outfile:
    data = {
        "abi": main_contract["abi"],
        "contract_address": deploy_contract(main_contract)
    }
    json.dump(data, outfile, indent=4, sort_keys=True)
創(chuàng)建flask api以為用戶存儲不同的值

你只需部署一次合約。但是使用它的地址,你會一次又一次地存儲數(shù)據(jù)。同樣,在db的世界中,你只需定義一次模型/模式,但你將在db中添加不同的行/文檔。

我們將使用flask post api來獲取用戶的用戶信息并返回成功。

from flask import Flask, Response, request, jsonify
from marshmallow import Schema, fields, ValidationError
def check_gender(data):
    valid_list = ["male", "female"]
    if data not in valid_list:
        raise ValidationError(
            "Invalid gender. Valid choices are"+ valid_list
        )
#For api validations
class UserSchema(Schema):
    name = fields.String(required=True)
    gender = fields.String(required=True, validate=check_gender)
# Initializing flask app
app = Flask(__name__)
# api to set new user every api call
@app.route("/blockchain/user", methods=["POST"])
def user():
    body = request.get_json()
    result, error = UserSchema().load(body)
    if error:
        return jsonify(error), 422
    return jsonify({"data": result}), 200

由于這不是flask教程,我不會詳細說明這一點,如果flask不熟悉可以看這個flask教程學習下。我們的API用戶將從客戶端獲取數(shù)據(jù)(curl請求)并對其進行驗證將其返回給客戶端(curl請求)

2.現(xiàn)在我們將初始化web3對象以與已部署的用戶合約進行通信。

from web3 import Web3
# web3.py instance
w3 = Web3(Web3.HTTPProvider("http://127.0.0.1:8545"))

3.現(xiàn)在我們將獲得之前存儲在data.json文件中的abi和合約地址。

with open("data.json", "r") as f:
     datastore = json.load(f)
     abi = datastore["abi"]
     contract_address = datastore["contract_address"]

4.選擇交易的默認帳戶地址。每次在合約中為用戶設(shè)置新值。你會從錢包里拿出一些gas。

w3.eth.defaultAccount = w3.eth.accounts[1]

5.最后,你將在以太坊合約中設(shè)置api調(diào)用用戶對象時獲得的值。

@app.route("/blockchain/user", methods=["POST"])
def user():
    # Create the contract instance with the newly-deployed address
    user = w3.eth.contract(address=contract_address, abi=abi)
    body = request.get_json()
    result, error = UserSchema().load(body)
    if error:
        return jsonify(error), 422
    tx_hash = user.functions.setUser(
        result["name"],result["gender"]
    )
    tx_hash = tx_hash.transact()
    # Wait for transaction to be mined...
    w3.eth.waitForTransactionReceipt(tx_hash)
    user_data = user.functions.getUser().call()
    return jsonify({"data": user_data}), 200

我們首先使用abi和contract_address獲得部署合約。

user = w3.eth.contract(address=contract_address, abi=abi)

然后我們可以使用合約實例調(diào)用任何合約公共函數(shù)。在為用戶設(shè)置值之后,我們將使用transact方法將其公之于眾。這將在以太坊區(qū)塊中添加新的用戶值。

tx_hash = user.functions.setUser(
    result["name"],result["gender"]
).transact()

現(xiàn)在我們可以使用call方法獲得已在合約中設(shè)置的值,這將調(diào)用合約函數(shù)而不在區(qū)塊鏈中添加任何區(qū)塊。

user_data = user.functions.getUser().call()

我們的api文件的最終代碼如下所示。將其另存為app.py。

import json
from flask import Flask, Response, request, jsonify
from marshmallow import Schema, fields, ValidationError
from web3 import Web3
# web3.py instance
w3 = Web3(Web3.HTTPProvider("http://127.0.0.1:8545"))
w3.eth.defaultAccount = w3.eth.accounts[1]
# Get stored abi and contract_address
with open("data.json", "r") as f:
    datastore = json.load(f)
    abi = datastore["abi"]
    contract_address = datastore["contract_address"]
def check_gender(data):
    valid_list = ["male", "female"]
    if data not in valid_list:
        raise ValidationError(
            "Invalid gender. Valid choices are"+ valid_list
        )
#For api validations
class UserSchema(Schema):
    name = fields.String(required=True)
    gender = fields.String(required=True, validate=check_gender)
# Initializing flask app
app = Flask(__name__)
# api to set new user every api call
@app.route("/blockchain/user", methods=["POST"])
def user():
    # Create the contract instance with the newly-deployed address
    user = w3.eth.contract(address=contract_address, abi=abi)
    body = request.get_json()
    result, error = UserSchema().load(body)
    if error:
        return jsonify(error), 422
    tx_hash = user.functions.setUser(
        result["name"],result["gender"]
    ).transact()
    # Wait for transaction to be mined...
    receipt = w3.eth.waitForTransactionReceipt(tx_hash)
    user_data = user.functions.getUser().call()
    return jsonify({"data": user_data}), 200

運行以下命令以啟動服務(wù)器。

$ FLASK_APP=app.py flask run
用curl調(diào)用api
$ curl -H "Content-Type: application/json" --request POST -d "{"name":"John Doe","gender":"male"}" http://localhost:5000/blockchain/user

你也可以在這里找到完整代碼。

python用web3.py庫開發(fā)以太坊來說非常的方便,有興趣的用戶可以關(guān)注我們的python以太坊教程,主要是針對python工程師使用web3.py進行區(qū)塊鏈以太坊開發(fā)的詳解。

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/42325.html

相關(guān)文章

  • pythonflask框架開發(fā)以太智能合約

    摘要:是以太坊開發(fā)的個人區(qū)塊鏈,可用于部署合約,開發(fā)應用程序和運行測試。安裝是一個用于與以太坊交互的庫。啟動以太坊測試區(qū)塊鏈服務(wù)器要部署智能合約,我們應該啟動測試以太坊服務(wù)器。最后,你將在以太坊合約中設(shè)置調(diào)用用戶對象時獲得的值。 將數(shù)據(jù)存儲在數(shù)據(jù)庫中是任何軟件應用程序不可或缺的一部分。無論如何控制該數(shù)據(jù)庫都有一個該數(shù)據(jù)的主控。區(qū)塊鏈技術(shù)將數(shù)據(jù)存儲到區(qū)塊鏈網(wǎng)絡(luò)內(nèi)的區(qū)塊中。因此,只要某個節(jié)點與網(wǎng)...

    enrecul101 評論0 收藏0
  • 2018以太智能合約編程語言solidity的最佳IDEs

    摘要:使用基于以太坊的智能合約的集成開發(fā)環(huán)境。以太坊教程,主要介紹智能合約與應用開發(fā),適合入門。以太坊,主要是介紹使用進行智能合約開發(fā)交互,進行賬號創(chuàng)建交易轉(zhuǎn)賬代幣開發(fā)以及過濾器和事件等內(nèi)容。 Solidity是一種以智能合約為導向的編程語言。這是一種只有四年的年輕語言,旨在幫助開發(fā)基于以太坊數(shù)字貨幣的智能合約。 理解它官方文檔應該是學習Solidity的最佳來源:solidity.read...

    darkerXi 評論0 收藏0
  • python使用web3py與以太智能合約交互

    摘要:合約規(guī)定了公共職能部門,以創(chuàng)造新的投資和撤資,這將成為對沖基金的主要職能。對沖基金的用戶通過其以太坊地址來識別,該地址相當于公鑰。我發(fā)現(xiàn)與其他程序如程序的以太坊智能合約進行交互的最簡單方法是使用他們的。 在以太坊和其他區(qū)塊鏈中,仍有很多被證明的概念正在實施,開發(fā)人員在嘗試如何應對這些新概念。作為dInvest 系列文章一部分,我也在研究以太坊并嘗試在區(qū)塊鏈中實施對沖基金。在上一篇文章中...

    Joyven 評論0 收藏0
  • 以太是什么 - 以太開發(fā)入門指南

    摘要:以太坊是什么以太坊是一個建立在區(qū)塊鏈技術(shù)之上,去中心化應用平臺。運行環(huán)境以太坊虛擬機是以太坊中智能合約的運行環(huán)境。是由以太坊客戶端提供的是典型的開發(fā)以太坊時使用的客戶端,基于語言開發(fā)。 本文首發(fā)于深入淺出區(qū)塊鏈社區(qū)原文鏈接:以太坊是什么 - 以太坊開發(fā)入門指南原文已更新,請讀者前往原文閱讀 很多同學已經(jīng)躍躍欲試投入到區(qū)塊鏈開發(fā)隊伍當中來,可是又感覺無從下手,本文將基于以太坊平臺,以通俗...

    tomlingtm 評論0 收藏0
  • 以太:Dapp及相關(guān)開發(fā)工具介紹

    摘要:郵件列表以太坊上的開發(fā)者郵件列表停止使用。開發(fā)的移動以太坊瀏覽器開發(fā)階段由支持的瀏覽器內(nèi)。是以太坊的開發(fā)環(huán)境,測試框架和資產(chǎn)管道。審查隨機數(shù)以太坊虛擬機是以太坊智能合約的執(zhí)行環(huán)境。 去中心化應用去中心化應用是可以使用戶和供應商之間直接互動的服務(wù)(例如,連接某些市場上的買方和賣方,文件存儲里的持有者和儲存者)。以太坊去中心化應用典型地通過HTML/Javascript網(wǎng)絡(luò)應用與用戶互動,...

    FleyX 評論0 收藏0

發(fā)表評論

0條評論

UnixAgain

|高級講師

TA的文章

閱讀更多
最新活動
閱讀需要支付1元查看
<