java使用spring boot、web3j、ethereum打造區塊鏈dapp
來源:互聯網
上載者:User
區塊鏈最近IT世界的流行語之一。這項有關數字加密貨幣的技術,並與比特幣一起構成了這個熱門的流行趨勢。它是去中心化的,不可變的分塊資料結構,這是可以安全連線和使用的密碼演算法。在這種結構中的每一區塊通常包含前一個區塊的加密雜湊,一個時間戳記,和交易資料。區塊鏈是點對點管理網路的,並在加入每一個新的塊之前進行節點間通訊的驗證。這是關於區塊鏈的部分理論。簡而言之,這是一種技術,它允許我們使用一個去中心化的方式管理雙方的交易。現在,問題是我們如何在我們的系統中實現它。於是以太坊來了。這是一個Vitarik Buterin提供的去中心化的平台,可以通過指令碼語言建立開發應用。它的想法是從比特幣獲得的,並由新的叫Ether即以太坊幣的加密數字幣驅動。今天,以太幣是繼比特幣之後的第二大加密數字貨幣。以太坊技術的核心是EVM(以太坊虛擬機器),它可以被視為類似於Java虛擬機器,而且用一種完全去中心化的節點網路。基於java世界實現以太坊交易我們使用web3j庫。這是一個輕量級的、響應式、型別安全的java和Android庫結合了以太坊區塊鏈節點。更多的細節可以在這裡找到[web3j.io中文版](http://blog.hubwiz.com/2018/07/10/web3j-index/)。![](http://blog.hubwiz.com/2018/08/13/ethereum-java-web3j-springboot/blockchain-logo.png)### 1.本地運行雖然有許多針對區塊鏈文章,但以太坊相關的網路內容中不容易找到一個解決方案描述如何準備在本地機器使用執行個體運行以太坊。值得一提的是,一般有兩種最基本的用戶端可以使用:Geth和Parity。原來,我們可以很容易地在本地使用Docker容器運行節點。預設情況下,串連節點的以太坊主網路(公有鏈)。或者,你可以將它串連到測試網路或Rinkeby網路。但開始最好的選擇就是運行在設定了開發參數(--dev)的開發模式下,並在Docker容器中運行命令。下面的命令啟動Docker容器開發模式在連接埠8545調用以太坊RPC API。```$ docker run -d --name ethereum -p 8545:8545 -p 30303:30303 ethereum/client-go --rpc --rpcaddr "0.0.0.0" --rpcapi="db,eth,net,web3,personal" --rpccorsdomain "*" --dev```在開發模式中運行該容器時,一個非常好的訊息是,在預設的測試帳戶上有大量的Ether。在這種情況下,你不必挖掘任何Ether,便能夠開始測試。超級棒!現在,讓我們建立一些其他的測試帳號,並做一些檢查。為了實現這一點,我們需要在容器內部運行Geth的互動式JavaScript控制台。```$ docker exec -it ethereum geth attach ipc:/tmp/geth.ipc```### 2.以太坊節點使用JavaScript控制台管理運行JavaScript控制台可以方便顯示預設帳戶(Coinbase),所有可用的賬戶及其餘額清單。這裡的螢幕顯示我的以太坊結果。![](http://blog.hubwiz.com/2018/08/13/ethereum-java-web3j-springboot/blockchain-1.png)現在,我們必須建立一些測試帳號。我們可以通過調用`personal.newAccount(password)`函數來實現這一點。在建立必需的帳戶之後,我們可以使用JavaScript控制台執行一些測試交易,並將一些資金從基礎帳戶轉移到新建立的帳戶。下面是用於建立帳戶和執行交易的命令。![](http://blog.hubwiz.com/2018/08/13/ethereum-java-web3j-springboot/blockchain-2.png)### 3.系統體繫結構我們的demo系統的體繫結構非常簡單。不用想複雜的事情,只是告訴大家如何發送交易到geth節點和接收交易收據。而`transaction-service`發送新交易到以太坊節點,`bonus-service`節點監聽傳入的交易。然後每10筆交易寄件者的帳戶收到一次獎金(bonus)。這裡的圖表說明了一個我們的demo的系統架構。![](http://blog.hubwiz.com/2018/08/13/ethereum-java-web3j-springboot/blockchain-arch.png)### 4.spring boot應用程式使用web3j我想現在我們清楚了我們到底想做什麼。所以,讓我們來進行實施。首先,我們應該包括所有必需的依賴項,以便能夠在Spring boot應用程式中使用`web3j`庫。幸運的是,有一個starter可以使用。```<dependency> <groupId>org.web3j</groupId> <artifactId>web3j-spring-boot-starter</artifactId> <version>1.6.0</version></dependency>```因為我們在Docker容器運行以太坊用戶端需要改變用戶端的自動預設配置的`web3j`的調用地址。```spring: application: name: transaction-serviceserver: port: ${PORT:8090}web3j: client-address: http://192.168.99.100:8545```### 5.構建應用如果我們將`web3j starter`包含到項目依賴項中,需要的是自動裝載web3j bean。web3j負責向Geth用戶端節點發送交易。它用交易雜湊接收響應,不管是節點接受或由於錯誤被拒絕。在建立交易對象時,重要的是將gas限制最小值設定為21000。如果發送較低的值,則可能會收到錯誤資訊:[intrinsic gas too low](http://cw.hubwiz.com/card/c/ethereum-FAQ/1/2/4/)。```@Servicepublic class BlockchainService { private static final Logger LOGGER = LoggerFactory.getLogger(BlockchainService.class); @Autowired Web3j web3j; public BlockchainTransaction process(BlockchainTransaction trx) throws IOException { EthAccounts accounts = web3j.ethAccounts().send(); EthGetTransactionCount transactionCount = web3j.ethGetTransactionCount(accounts.getAccounts().get(trx.getFromId()), DefaultBlockParameterName.LATEST).send(); Transaction transaction = Transaction.createEtherTransaction(accounts.getAccounts().get(trx.getFromId()), transactionCount.getTransactionCount(), BigInteger.valueOf(trx.getValue()), BigInteger.valueOf(21_000), accounts.getAccounts().get(trx.getToId()),BigInteger.valueOf(trx.getValue())); EthSendTransaction response = web3j.ethSendTransaction(transaction).send(); if (response.getError() != null) { trx.setAccepted(false); return trx; } trx.setAccepted(true); String txHash = response.getTransactionHash(); LOGGER.info("Tx hash: {}", txHash); trx.setId(txHash); EthGetTransactionReceipt receipt = web3j.ethGetTransactionReceipt(txHash).send(); if (receipt.getTransactionReceipt().isPresent()) { LOGGER.info("Tx receipt: {}", receipt.getTransactionReceipt().get().getCumulativeGasUsed().intValue()); } return trx; } }```@Service從上面的代碼看由控制器調用。POST方法的需要`BlockchainTransaction`對象作為參數。你可以發送寄件者ID,接收人ID和交易金額。寄件者和接收者ID是通過eth.account[index]可查詢的。```@RestControllerpublic class BlockchainController { @Autowired BlockchainService service; @PostMapping("/transaction") public BlockchainTransaction execute(@RequestBody BlockchainTransaction transaction) throws NoSuchAlgorithmException, NoSuchProviderException, InvalidAlgorithmParameterException, CipherException, IOException { return service.process(transaction); } }```你可以用下面的命令調用POST方法發送測試交易。在發送任何交易之前,你應該解鎖發送人帳戶。```$ curl --header "Content-Type: application/json" --request POST --data '{"fromId":2,"toId":1,"value":3}' http://localhost:8090/transaction```應用程式`bonus-service`監聽由以太坊節點處理的交易。它通過調用`web3j.transactionObservable().subscribe(...)`方法從web3j庫訂閱通知訊息。它將從該地址每10個交易返回後,發送一次到寄件者的帳戶。下面是`bonus-service`中可監聽方法的實現。```@AutowiredWeb3j web3j; @PostConstructpublic void listen() { Subscription subscription = web3j.transactionObservable().subscribe(tx -> { LOGGER.info("New tx: id={}, block={}, from={}, to={}, value={}", tx.getHash(), tx.getBlockHash(), tx.getFrom(), tx.getTo(), tx.getValue().intValue()); try { EthCoinbase coinbase = web3j.ethCoinbase().send(); EthGetTransactionCount transactionCount = web3j.ethGetTransactionCount(tx.getFrom(), DefaultBlockParameterName.LATEST).send(); LOGGER.info("Tx count: {}", transactionCount.getTransactionCount().intValue()); if (transactionCount.getTransactionCount().intValue() % 10 == 0) { EthGetTransactionCount tc = web3j.ethGetTransactionCount(coinbase.getAddress(), DefaultBlockParameterName.LATEST).send(); Transaction transaction = Transaction.createEtherTransaction(coinbase.getAddress(), tc.getTransactionCount(), tx.getValue(), BigInteger.valueOf(21_000), tx.getFrom(), tx.getValue()); web3j.ethSendTransaction(transaction).send(); } } catch (IOException e) { LOGGER.error("Error getting transactions", e); } }); LOGGER.info("Subscribed");```### 總結區塊鏈和數字貨幣不是容易開始的話題。通過提供完整的指令碼語言,以太坊簡化了使用區塊鏈進行應用程式開發的難度。使用web3j、spring boot和以太坊geth用戶端的docker容器鏡像,可以快速啟動解決方案,實現區塊鏈技術的本地開發。如果你想進行本地開發時clone我的庫,可以在github上[下載原始碼](https://github.com/piomin/sample-spring-blockchain.git)。如果希望快速進行web3j、java、以太坊開發,那請看我們精心打造的教程:> - [web3j教程](http://xc.hubwiz.com/course/5b2b6e82c02e6b6a59171de2?affid=815studygolang),主要是針對java和android程式員進行區塊鏈以太坊開發的web3j詳解。其他以太坊教程如下:> - [以太坊教程](http://xc.hubwiz.com/course/5a952991adb3847553d205d1?affid=815studygolang),主要介紹智能合約與dapp應用開發,適合入門。> - [以太坊開發](http://xc.hubwiz.com/course/5abbb7acc02e6b6a59171dd6?affid=815studygolang),主要是介紹使用node.js、mongodb、區塊鏈、ipfs實現去中心化電商DApp實戰,適合進階。> - [python以太坊](http://xc.hubwiz.com/course/5b40462cc02e6b6a59171de4?affid=815studygolang),主要是針對python工程師使用web3.py進行區塊鏈以太坊開發的詳解。> - [php以太坊](http://xc.hubwiz.com/course/5b36629bc02e6b6a59171de3?affid=815studygolang),主要是介紹使用php進行智能合約開發互動,進行帳號建立、交易、轉賬、代幣開發以及過濾器和事件等內容。> - [C#以太坊](http://xc.hubwiz.com/course/5b6048c3c02e6b6a59171dee?affid=815studygolang),主要講解如何使用C#開發基於.Net的以太坊應用,包括賬戶管理、狀態與交易、智能合約開發與互動、過濾器和事件等。這裡是[原文](http://blog.hubwiz.com/2018/08/13/ethereum-java-web3j-springboot/)96 次點擊