區塊鏈3
拍賣系統:
知識點:
全結點儲存有完整的區塊鏈,輕結點則部分。
安裝[email protected],ganache-cli,[email protected]。其中npm install:若無-g,則把包安裝到當前目錄,若有-g,則全域性安裝,裝到其他位置。
執行ganache-cli:搭建以太坊環境,開啟8545埠。
npm init:初始化package.json。
建立一個簡易合約:
solcjs --abi aa.sol:編譯aaa.sol後生成abi檔案
node a.js:執行a.js檔案
在node中呼叫合約中的test方法:
varcontractInstance=web3.eth.contract(abi).at(合約的部署地址); contractInstance.test({from:web3.eth.accounts[0]}); // 呼叫合約函式時,要傳入是誰呼叫了該函式{from:web3.eth.accounts[0]}js引擎執行js檔案,進而呼叫合約的test方法:
varMyContract=newweb3.eth.Contract(abi, 合約地址); MyContract.methods.test().call().then(i=>alert(i)); //test方法的返回值給i,隨後alert(i)由於require不能被js引擎識別,只能被node識別,所以需要webpack翻譯:webpack index.js indexed.js,然後html頁面引用indexed.js,同時還要把Web3引入進來:
<scripttype="text/javascript"src="https://cdn.jsdelivr.net/gh/ethereum/web3.js/dist/web3.min.js"></script>
IPFS:分散式檔案系統,存到各個節點,類似於世界硬碟
安裝:https://pan.baidu.com/s/1H9DRYZLKmGvdEzP0-DzjJA,再配置環境變數path,輸入ipfs init初始化倉庫,輸入ipfs daemon開啟守護程序,隨後可以訪問127.0.0.1:5001/webui
上傳檔案到ipfs,同時會得到一個雜湊值:
通過此雜湊訪問此檔案:
遠端訪問:
本地訪問:
安裝ipfs-api庫:npm install -g ipfs-api
js檔案裡的require無法由瀏覽器直接識別,需要通過webpack index.js index2.js,轉到index2.js才行。
步驟:
執行ganache-cli開啟區塊鏈環境
生成abi檔案:solc --abiEcommerceStore.sol
部署合約:node deploy.js,其中deploy.js:
// 部署合約 var Web3=require('web3') // 獲得模組 var fs = require('fs') var web3=new Web3(new Web3.providers.HttpProvider('http://localhost:8545')) var solc = require('solc') //sudo chmod 666 aaa.sol// linux要寫這句:修改檔案許可權使能讀 var sourceCode=fs.readFileSync('EcommerceStore.sol').toString() //拿到sol檔案 var compiledCode=solc.compile(sourceCode) //用編譯器編譯它 var abi = JSON.parse(compiledCode.contracts[':EcommerceStore'].interface) //獲得其中編譯的abi var byteCode = compiledCode.contracts[':EcommerceStore'].bytecode//獲得位元組碼 var VotingContract = web3.eth.contract(abi)//建立合約物件 var deployTxObj = {data:byteCode,from:web3.eth.accounts[0],gas:3000000}//構建一個交易 VotingContract.new(deployTxObj); //定義合約例項, 第一個引數可選,是合約的建構函式要接受的引數
此時ganache-cli裡面就有了合約地址:
為了把檔案上傳到ipfs,需要開啟ipfs:ipfs daemon
上傳幾個檔案並得到對應的雜湊:ipfs add 檔案地址
給合約變數賦值:node seed.js,其中seed.js:// 執行node來新增東西(給合約變數賦值) var fs = require('fs') var solc = require('solc') var Web3=require('web3') // 獲得模組 var web3=new Web3(new Web3.providers.HttpProvider('http://localhost:8545')) //sudo chmod 666 aaa.sol// linux要寫這句:修改檔案許可權使能讀 var sourceCode=fs.readFileSync('EcommerceStore.sol').toString() //拿到sol檔案 var compiledCode=solc.compile(sourceCode) //用編譯器編譯它 var abi = JSON.parse(compiledCode.contracts[':EcommerceStore'].interface) //獲得其中編譯的abi // node compile.js後,可從ganache-cli可以獲得合約地址:0x32ccbdb064098d160fe946e814137da6880701c1 var contractAddr = "0xd0eb6cb24bdec0f6985792777a7da4329d3b75be"; var contractInstance = web3.eth.contract(abi).at(contractAddr); // 開始新增產品 current_time = Math.round(new Date() / 1000); amt_1 = web3.toWei(1, 'ether'); contractInstance.addProductToStore('iphone 5', 'Cell Phones & Accessories', 'QmekZaRsMQXHwwDT7qu41khcPspwFLANnv1QEv8xdAR7Cz', 'QmbLRFj5U6UGTy3o9Zt8jEnVDuAw2GKzvrrv3RED9wyGRk', current_time, current_time + 200, 2*amt_1, 0,{from:web3.eth.accounts[0]}).call().then(); contractInstance.addProductToStore('iphone 5s', 'Cell Phones & Accessories', 'QmPyt3L7VYM31KndYoEpAv23HSDSdhx7UYhpSYrwpUhpCt', 'QmbLRFj5U6UGTy3o9Zt8jEnVDuAw2GKzvrrv3RED9wyGRk', current_time, current_time + 200, 2*amt_1, 0,{from:web3.eth.accounts[0]}).call().then();
建立index.js渲染頁面:
// 與合約互動從而渲染頁面 const ipfsAPI = require('ipfs-api'); const ethUtil = require('ethereumjs-util'); const ipfs = ipfsAPI({host: 'localhost', port: '5001', protocol: 'http'}); window.addEventListener('load', function() { // 若已經有web3物件(比如metamask給瀏覽器注入了web3),則使用現成的,否則新建一個 if (typeof web3 !== 'undefined') { console.log("web3已經存在"); window.web3 = new Web3(web3.currentProvider); } else { console.log("web3不存在,現在建立"); var Web3=require('web3'); window.web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")); } var abi = JSON.parse('[{"constant":true,"inputs":[],"name":"getT","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_productId","type":"uint256"}],"name":"totalBids","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_name","type":"string"},{"name":"_category","type":"string"},{"name":"_imageLink","type":"string"},{"name":"_descLink","type":"string"},{"name":"_auctionStartTime","type":"uint256"},{"name":"_auctionEndTime","type":"uint256"},{"name":"_startPrice","type":"uint256"},{"name":"_productCondition","type":"uint256"}],"name":"addProductToStore","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_productId","type":"uint256"}],"name":"getProduct","outputs":[{"name":"","type":"uint256"},{"name":"","type":"string"},{"name":"","type":"string"},{"name":"","type":"string"},{"name":"","type":"string"},{"name":"","type":"uint256"},{"name":"","type":"uint256"},{"name":"","type":"uint256"},{"name":"","type":"uint8"},{"name":"","type":"uint8"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"productIndex","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_productId","type":"uint256"}],"name":"highestBidderInfo","outputs":[{"name":"","type":"address"},{"name":"","type":"uint256"},{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_productId","type":"uint256"},{"name":"_bid","type":"bytes32"}],"name":"bid","outputs":[{"name":"","type":"bool"}],"payable":true,"stateMutability":"payable","type":"function"},{"constant":false,"inputs":[{"name":"_productId","type":"uint256"},{"name":"_amount","type":"string"},{"name":"_secret","type":"string"}],"name":"revealBid","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"test","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"inputs":[],"payable":false,"stateMutability":"nonpayable","type":"constructor"}]') var contractAddr = "0xd0eb6cb24bdec0f6985792777a7da4329d3b75be"; var MyContract = new web3.eth.Contract(abi, contractAddr); // 賦給全域性 window.web3 = web3; window.MyContract = MyContract; renderStore(); }); function renderStore() { // 得到產品:呼叫合約裡面的getProduct方法,然後非同步進入then,其中getProduct的返回值給i // MyContract.methods.getProduct(1).call().then(p=>console.log(p)); MyContract.methods.getProduct(1).call().then(p=>$("#product-list").append(buildProduct(p))); MyContract.methods.getProduct(2).call().then(p=>$("#product-list").append(buildProduct(p))); } function buildProduct(product) { let node = $("<div/>"); node.addClass("col-sm-3 text-center col-margin-bottom-1"); node.append("<img src='http://localhost:8080/ipfs/" + product[3] + "' width='150px' />"); node.append("<div>" + product[1]+ "</div>"); node.append("<div>" + product[2]+ "</div>"); node.append("<div>" + product[5]+ "</div>"); node.append("<div>" + product[6]+ "</div>"); node.append("<div>Ether " + product[7] + "</div>"); return node; }
為了解釋require,webpack index.js indexed.js
html頁面引入js檔案:
<head> <title>去中心化</title> <link href='https://fonts.proxy.ustclug.org/css?family=Open+Sans:400,700' rel='stylesheet' type='text/css'> <link href='https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css' rel='stylesheet' type='text/css'> <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script> <script type="text/javascript" src="https://cdn.jsdelivr.net/gh/ethereum/web3.js/dist/web3.min.js"></script> <script src="indexed.js"></script> </head>
開啟html