使用Go與以太坊智慧合約互動
儘管最近遇到了些麻煩,但以太坊仍然是區塊鏈領域內智慧合約的最大參與者,這似乎不會很快改變。
在我看來,技術本身具有很大的潛力,是從學術的角度看很有意思,但正如上面提到的問題和之前的許多問題是區塊鏈技術方面的,智慧合約,特別是具有Solidity的以太坊生態系統還是不太成熟的,並沒有為prime-time和生產用例做好準備。
然而,這是一個學習和了解這項技術的好時機,並且當它達到嚴格應用程式的可接受成熟度前,需要做好準備。
在我之前關於Solidity的帖子 中,我建立了一個帶有簡單的Winner-Takes-All Crowdfunding合約的小應用程式。在這篇文章中,我們將用到其中的contract.sol,看看我們是否可以使用Go部署它並與之互動。
為什麼是go?好問題,go語言是令人驚訝的而且使用最廣泛的以太坊客戶端使用go寫的,這意味著有一個很好的生態系統使用已經轉為具有很好的功能,如程式碼生成和可重複使用的助手和智慧合約互動的共享庫。
在這個例子中,我們將不使用真實的區塊鏈作為部署目標,而是使用由go-ethereum,所以我們可以安全地測試並沒有花費任何金錢實驗提供的SimulatedBackend。
智慧合約本身非常簡單:我不會詳細介紹它的功能或工作方式,因為已經涵蓋了這一點。可以說,合約部署有3個引數:
- 專案的最低入場費。
- 提交新專案的截止日期。
- 支援專案的截止日期。
然後,在第一階段,可以使用名稱和網址提交專案,其中至少包含交易的最低費用。在第二階段,可以通過將以太傳送到合約中的地址來支援專案。
但是,在這篇文章中,我們將重點關注:
- 部署合約
- 從合約中讀取資料
- 與合約互動(交易)
- 通過地址例項化已部署的合約
我們將在Go和70行程式碼中完成所有操作。讓我們開始吧!
程式碼示例
為了能夠跟蹤,你需要一些東西。首先也是最重要的是,你需要solc Solidity編譯器。
然後,只需獲取go-ethereum並構建它:
go get github.com/ethereum/go-ethereum cd $GOPATH/src/github.com/ethereum/go-ethereum/ make make devtools
好吧,使用solc和geth devtools,我們可以從生成contract.sol檔案的Go版本開始,該檔案包含我們的智慧合約:
abigen --sol=Contract.sol --pkg=main --out=contract.go
生成的程式碼看這裡 。
如你所見,我們有部署和例項化合約的方法,以及所有公共合約方法到Go的對映。
下一步是將合約部署到模擬後端。
為此,需要進行一些設定。如上所述,為了簡單起見,我們將使用SimulatedBackend作為我們的目標區塊鏈,但在本文的最後,將有一個關於如何使用testnet甚至真正的以太坊區塊鏈進行此操作的簡短部分。
使用go-ethereum的一些依賴關係,我們可以開始設定:
import( "fmt" "log" "math/big" "time" "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/accounts/abi/bind/backends" "github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/crypto" ) func main() { key, _ := crypto.GenerateKey() auth := bind.NewKeyedTransactor(key) alloc := make(core.GenesisAlloc) alloc[auth.From] = core.GenesisAccount{Balance: big.NewInt(133700000)} sim := backends.NewSimulatedBackend(alloc)
我們只需建立一個金鑰,用一堆以太建立一個Genesis帳戶並啟動模擬後端,它會返回一個bind.ContractBackend。
現在我們可以使用生成的DeployWinnerTakesAll方法部署合約:
addr, _, contract, err := DeployWinnerTakesAll(auth, sim, big.NewInt(10), big.NewInt(time.Now().Add(2*time.Minute).Unix()), big.NewInt(time.Now().Add(5*time.Minute).Unix())) if err != nil { log.Fatalf("could not deploy contract: %v", err) }
我們使用bigInt傳遞一個auth物件,它表示我們的身份,後端sim和最小入場費,專案截止日期和活動截止日期的值。該方法返回將部署合約的地址以及合約的控制代碼和錯誤。還有一個返回的交易物件,但我們不會在這裡處理它。
現在合約已經部署,我們應該能夠與它進行互動。例如,我們可以檢查我們傳送的截止日期是否在合約中正確設定:
deadlineCampaign, _ := contract.DeadlineCampaign(nil) fmt.Printf("Pre-mining Campaign Deadline: %s\n", deadlineCampaign)
但是,如果我們執行此操作,我們會在截止日期前返回
fmt.Println("Mining...") sim.Commit() postDeadlineCampaign, _ := contract.DeadlineCampaign(nil) fmt.Printf("Post-mining Campaign Deadline: %s\n", time.Unix(postDeadlineCampaign.Int64(), 0))
我們回到部署期間設定的日期:
Post-mining Campaign Deadline: 2017-07-23 20:37:22 +0200 CEST
ok。因此,我們可以讀取合約中公開的資料。現在我們想與它互動。在這種情況下,最簡單的事情是我們通過傳送一個帶有名稱和專案網址的交易來提出一個新專案,其中至少有最低費用作為值:
numOfProjects, _ := contract.NumberOfProjects(nil) fmt.Printf("Number of Projects before: %d\n", numOfProjects) fmt.Println("Adding new project...") contract.SubmitProject(&bind.TransactOpts{ From:auth.From, Signer:auth.Signer, GasLimit: big.NewInt(2381623), Value:big.NewInt(10), }, "test project", "http://www.example.com")
當然我們需要繼續挖礦:
fmt.Println("Mining...") sim.Commit() numOfProjects, _ = contract.NumberOfProjects(nil) fmt.Printf("Number of Projects after: %d\n", numOfProjects) info, _ := contract.GetProjectInfo(nil, auth.From) fmt.Printf("Project Info: %v\n", info)
…但是我們得到以下輸出:
Number of Projects before: 0 Adding new project... Mining... Number of Projects after: 1 Project Info: {test project http://www.example.com 0}
太棒了,這意味著我們的專案已經建立。因此,我們能夠部署合約,對其進行讀寫。
但是如果合約已經部署並且我們只想與它進行互動怎麼辦?幸運的是,生成的程式碼包含一個NewWinnerTakesAll方法,它只使用已部署合約的地址,允許我們例項化合約:
instContract, err := NewWinnerTakesAll(addr, sim) if err != nil { log.Fatalf("could not instantiate contract: %v", err) } numOfProjects, _ = instContract.NumberOfProjects(nil) fmt.Printf("Number of Projects of instantiated Contract: %d\n", numOfProjects)
我們獲得與已部署合約相同的返回值,並且可以與此版本完全相同的方式進行互動,該版本由地址例項化。
好的,所以我們完成了與合約有意義地互動所需的所有步驟,但僅限於模擬的後端。為了使用testnet或真正的以太坊區塊鏈,我們只需要調整一些事項:
const key = "your key json" conn, err := rpc.NewIPCClient("/path/to/your/.ethereum/testnet/geth.ipc") if err != nil { log.Fatalf("could not create ipc client: %v", err) } auth, err := bind.NewTransactor(strings.NewReader(key), "your password") if err != nil { log.Fatalf("could not create auth: %v", err) }
這會產生我們自己建立的auth物件。當然,請不要在程式碼中使用純文字的金鑰和/或密碼,而是以安全的方式載入它們。:)
如果已經部署了合約,我們不需要建立NewIPCClient,但只需Dial一個節點:
conn, err := ethclient.Dial("/path/to/your/.ethereum/testnet/geth.ipc") if err != nil { log.Fatalf("could not connect to remote node: %v", err) }
如此而已!可以在此處 找到該示例的完整程式碼。
結論
正如我在本文開頭所述,在我看來,依靠Solidity智慧合約進行認真的應用還為時尚早,但這種以及其他幾種基於區塊鏈的智慧合約方法的潛力巨大,因此瞭解周邊技術肯定是值得的。
Go非常適合與基於以太坊的智慧合約互動的任務,因為有很多來自geth的可重用程式碼,甚至還有一些關於如何開始使用的文件。這當然可以用任何其他語言來實現(例如:使用web3),但如果Go是你喜歡的,它似乎是一個可靠的選擇。:)
======================================================================
分享一些比特幣、以太坊、EOS、Fabric等區塊鏈相關的互動式線上程式設計實戰教程:
- java比特幣開發教程,本課程面向初學者,內容即涵蓋比特幣的核心概念,例如區塊鏈儲存、去中心化共識機制、金鑰與指令碼、交易與UTXO等,同時也詳細講解如何在Java程式碼中整合比特幣支援功能,例如建立地址、管理錢包、構造裸交易等,是Java工程師不可多得的比特幣開發學習課程。
- php比特幣開發教程,本課程面向初學者,內容即涵蓋比特幣的核心概念,例如區塊鏈儲存、去中心化共識機制、金鑰與指令碼、交易與UTXO等,同時也詳細講解如何在Php程式碼中整合比特幣支援功能,例如建立地址、管理錢包、構造裸交易等,是Php工程師不可多得的比特幣開發學習課程。
- c#比特幣開發教程,本課程面向初學者,內容即涵蓋比特幣的核心概念,例如區塊鏈儲存、去中心化共識機制、金鑰與指令碼、交易與UTXO等,同時也詳細講解如何在C#程式碼中整合比特幣支援功能,例如建立地址、管理錢包、構造裸交易等,是C#工程師不可多得的比特幣開發學習課程。
- java以太坊開發教程,主要是針對java和android程式設計師進行區塊鏈以太坊開發的web3j詳解。
- python以太坊,主要是針對python工程師使用web3.py進行區塊鏈以太坊開發的詳解。
- php以太坊,主要是介紹使用php進行智慧合約開發互動,進行賬號建立、交易、轉賬、代幣開發以及過濾器和交易等內容。
- 以太坊入門教程,主要介紹智慧合約與dapp應用開發,適合入門。
- 以太坊開發進階教程,主要是介紹使用node.js、mongodb、區塊鏈、ipfs實現去中心化電商DApp實戰,適合進階。
- ERC721以太坊通證實戰,課程以一個數字藝術品創作與分享DApp的實戰開發為主線,深入講解以太坊非同質化通證的概念、標準與開發方案。內容包含ERC-721標準的自主實現,講解OpenZeppelin合約程式碼庫二次開發,實戰專案採用Truffle,IPFS,實現了通證以及去中心化的通證交易所。
- C#以太坊,主要講解如何使用C#開發基於.Net的以太坊應用,包括賬戶管理、狀態與交易、智慧合約開發與互動、過濾器和交易等。
- EOS入門教程,本課程幫助你快速入門EOS區塊鏈去中心化應用的開發,內容涵蓋EOS工具鏈、賬戶與錢包、發行代幣、智慧合約開發與部署、使用程式碼與智慧合約互動等核心知識點,最後綜合運用各知識點完成一個便籤DApp的開發。
- 深入淺出玩轉EOS錢包開發 ,本課程以手機EOS錢包的完整開發過程為主線,深入學習EOS區塊鏈應用開發,課程內容即涵蓋賬戶、計算資源、智慧合約、動作與交易等EOS區塊鏈的核心概念,同時也講解如何使用eosjs和eosjs-ecc開發包訪問EOS區塊鏈,以及如何在React前端應用中整合對EOS區塊鏈的支援。課程內容深入淺出,非常適合前端工程師深入學習EOS區塊鏈應用開發。
- Hyperledger Fabric 區塊鏈開發詳解 ,本課程面向初學者,內容即包含Hyperledger Fabric的身份證書與MSP服務、許可權策略、通道配置與啟動、鏈碼通訊介面等核心概念,也包含Fabric網路設計、nodejs鏈碼與應用開發的操作實踐,是Nodejs工程師學習Fabric區塊鏈開發的最佳選擇。
- Hyperledger Fabric java 區塊鏈開發詳解 ,課程面向初學者,內容即包含Hyperledger Fabric的身份證書與MSP服務、許可權策略、通道配置與啟動、鏈碼通訊介面等核心概念,也包含Fabric網路設計、java鏈碼與應用開發的操作實踐,是java工程師學習Fabric區塊鏈開發的最佳選擇。
- tendermint區塊鏈開發詳解 ,本課程適合希望使用tendermint進行區塊鏈開發的工程師,課程內容即包括tendermint應用開發模型中的核心概念,例如ABCI介面、默克爾樹、多版本狀態庫等,也包括代幣發行等豐富的實操程式碼,是go語言工程師快速入門區塊鏈開發的最佳選擇。
匯智網原創翻譯,轉載請標明出處。這裡是使用Go與以太坊智慧合約互動