文章目錄
開始前
首先聲明,這個(gè)比賽是由我室友,學(xué)長(zhǎng)學(xué)姐以及本人共同參與完成(雖然這個(gè)項(xiàng)目還沒完全做完來(lái)著,但好歹是終于交上去了)我只負(fù)責(zé)了其中的后端代碼的一部分內(nèi)容,而且由于一開始完全不懂的關(guān)系,基本上是屬于走一步看一步學(xué)一步的過(guò)程,所以進(jìn)度一度十分緩慢,并且之中有很多的部分也不能保證完全正確,只能說(shuō)是暫時(shí)先用著,如果之后發(fā)現(xiàn)錯(cuò)誤會(huì)及時(shí)更改,并且這個(gè)項(xiàng)目也在不斷完善的過(guò)程中,等全部完成后會(huì)再發(fā)一次博客,這次的就當(dāng)完成一部分交上去之后的一個(gè)小小的總結(jié),記錄一下我大學(xué)第一次參加的比賽項(xiàng)目過(guò)程,以及心路歷程。
在此,感謝我的室友,還有學(xué)長(zhǎng)學(xué)姐的幫助,才能讓這個(gè)項(xiàng)目得以順利進(jìn)行
項(xiàng)目進(jìn)行過(guò)程中所用到的所有資料鏈接我都會(huì)放在最后,而具體的代碼我也會(huì)放在文章中(因?yàn)榇蟛糠侄际黔h(huán)境的部署,以及未完成的關(guān)系,我的代碼其實(shí)尤其的少,估計(jì)等全部完成后就會(huì)變多),其余的則打包上傳github(等我弄明白github怎么搞就上傳),大概就是這樣。
零、相關(guān)概念
1.區(qū)塊鏈?zhǔn)鞘裁矗?/h3>
區(qū)塊鏈作為一個(gè)新興的詞匯,在近幾年逐漸變得活躍,但是其含義還是很抽象,其實(shí)到現(xiàn)在我也不能說(shuō)完全理解,只能說(shuō)是在基于這個(gè)項(xiàng)目的基礎(chǔ)之上有我自己的理解,首先區(qū)塊鏈?zhǔn)且粋€(gè)完全的去中心化的,相當(dāng)于是不存在所謂的管理員這一職務(wù),每一個(gè)加入到區(qū)塊鏈中的個(gè)體都是管理者。
可以打一個(gè)比喻,我們平時(shí)向他人發(fā)送交易的時(shí)候,如果交易的記錄被人篡改,那么交易本身就會(huì)出現(xiàn)很多問(wèn)題,而引起交易篡改的可能性很多,比如你的計(jì)算機(jī)被人黑了,又或者網(wǎng)絡(luò)出現(xiàn)了數(shù)據(jù)的丟失,又或者管理員在管理數(shù)據(jù)的時(shí)候出現(xiàn)了差錯(cuò),這些都有可能,但是在區(qū)塊鏈中,當(dāng)你發(fā)起了一個(gè)交易之后,社區(qū)里的其他人都會(huì)來(lái)記錄這個(gè)交易記錄,如果之后需要查詢交易的情況,只需要看社區(qū)里大家的記錄單即可,若有人想要篡改交易記錄,那他就需要把社區(qū)里至少一半以上的人的記錄全部修改才行,如果把這放到現(xiàn)實(shí)生活中,很明顯,把全球一半的電腦全部搞崩潰,這件事本身就幾乎不可能,因此,交易記錄便具有了安全性與不可更改性。
而同時(shí),我們時(shí)常聽到的區(qū)塊鏈挖礦機(jī)制,其實(shí)就是社區(qū)里的人來(lái)爭(zhēng)奪誰(shuí)來(lái)第一個(gè)抄錄這份交易情況,而給予記錄者的獎(jiǎng)勵(lì)就是我們平時(shí)所講的虛擬貨幣,如比特幣等,當(dāng)?shù)谝粋€(gè)人記錄了之后,其他人只要把他的消息給記錄下來(lái)即可,但是其他人則不具有第一個(gè)記錄的獎(jiǎng)勵(lì)。
2.NFT是什么?
NFT的全稱是Non-Fungible Token,指非同質(zhì)化代幣,是用于表示數(shù)字資產(chǎn)(包括jpg和視頻剪輯形式)的唯一加密貨幣令牌,可以買賣。
也就是相當(dāng)于一種電子藝術(shù)品,將其變?yōu)橐环N可以交易的電子信息,其具有不可仿造性和完整性,可以避免現(xiàn)實(shí)生活中的藝術(shù)品仿制造假現(xiàn)象。
3.智能合約是什么?
智能合約是一種寫在區(qū)塊鏈上的一份合約,我們可以通過(guò)向這個(gè)合約發(fā)起交易,來(lái)吧我們的交易記錄在合約上,從而存儲(chǔ)在區(qū)塊鏈中,而智能合約的內(nèi)容主要是以各種函數(shù)方法為主,可以通過(guò)調(diào)用方法,來(lái)發(fā)起交易,而交易的貨幣則是以虛擬貨幣為主。
4.我這個(gè)后端究竟在干啥?
說(shuō)到這里,可能會(huì)有點(diǎn)迷糊的感覺,我當(dāng)時(shí)在加入之后也是理解了很久才搞清楚我到底應(yīng)該做什么,以下就是我整理之后的主要工作內(nèi)容:
從前面我們可以知道,智能合約是存儲(chǔ)在區(qū)塊鏈上的,我們可以通過(guò)調(diào)用合約中的函數(shù)方法來(lái)進(jìn)行交易的發(fā)起,將我們的交易記錄通過(guò)交易的形式發(fā)送到合約上,比如我們要購(gòu)買某一個(gè)東西,我們把自己購(gòu)買的詳細(xì)信息:誰(shuí)購(gòu)買的,從誰(shuí)那買的,買的什么,價(jià)格是多少,什么時(shí)候買的等等。將這些信息打包,通過(guò)向合約發(fā)起交易的形式存儲(chǔ)到合約中。
因此,我要做的便是智能合約的編寫,將藝術(shù)品交易平臺(tái)上用到的各種函數(shù)方法都編寫進(jìn)去,并且通過(guò)調(diào)用合約的方法存儲(chǔ)交易記錄,把調(diào)用的方法發(fā)給前端,從而實(shí)現(xiàn)網(wǎng)頁(yè)版的藝術(shù)品交易平臺(tái)的設(shè)計(jì)。
一、準(zhǔn)備工作-環(huán)境的部署
這個(gè)后端代碼的部署環(huán)境過(guò)于離譜,以至于光是配環(huán)境就花費(fèi)了我和學(xué)長(zhǎng)好久好久的時(shí)間,其中包含了大部分從未見過(guò)的、莫名其妙的、甚至已經(jīng)相對(duì)比較老的bug,所以整個(gè)環(huán)境的部署十分的艱難,我也是查找了大量的CSDN,百度,知網(wǎng)以及guthub和求助萬(wàn)能的學(xué)長(zhǎng)才解決了部分,以下是環(huán)境內(nèi)容。
1.虛擬機(jī)以及l(fā)inux布置
我采用的是VMware Workstation Pro作為虛擬機(jī),使用的linux是ubuntu18.04版本,因?yàn)槭褂幂^為順手,而且為了貼合那奇怪的環(huán)境,我也不敢用更新的版本,怕有奇怪的bug。
虛擬機(jī)我是在大一的網(wǎng)絡(luò)安全課上就以及使用過(guò)并且當(dāng)時(shí)是安裝了win7版本,使用我會(huì)使用,但是這個(gè)linux,,,我只能說(shuō),很離譜,我是真的從來(lái)沒聽過(guò)這玩意,以至于我第一次進(jìn)入的時(shí)候我人都傻了,這是個(gè)嘛玩意啊,怎么全是英文,文件在哪,瀏覽器在哪,終端為什么長(zhǎng)這樣子,完全和我的印象里的操作系統(tǒng)完全不一樣,我光是研究這個(gè)linux就用了好多時(shí)間,也是到后來(lái)我才逐漸適應(yīng)。
以下我會(huì)列舉一些常用的語(yǔ)句,都是我熟悉的不能再熟悉的語(yǔ)句
cd 用來(lái)選擇文件的目錄路徑
touch example.c 在當(dāng)前目錄創(chuàng)建example.c文件
vi example.c 修改文件
gedit example.c 打開文件并且修改,比上面的vi操作要更加貼近我的習(xí)慣
ctrl+f 選擇所要查詢的關(guān)鍵字
sudo 在語(yǔ)句前面加上這個(gè),增加權(quán)限,為了防止有permission報(bào)錯(cuò)
install 下載指令,可以下載相關(guān)指令
2.在編寫合約之前所做的準(zhǔn)備
按照官方給的文檔來(lái)看,環(huán)境有以下一大堆
Ubuntu 18.04、Manjaro(Or other OS based on Linux release)
Python2
Docker
Go v1.10 (1.9+ ,version1.10 recommended)
Git
Node.js v8.11.2 or later
這個(gè)環(huán)境是真的折磨人,他對(duì)版本的要求很死板,前面的幾個(gè)都問(wèn)題不大,直接在Ubuntu的終端里面用install下載即可,注意下版本就行,把python的版本切成2就可用。
最為惡心的是后面的工具部分,首先是這個(gè)node.js,他要求的版本是8.11.2或者之后的,但還是建議下載8.11.2(別問(wèn),問(wèn)就是別的版本各種報(bào)錯(cuò)不適配)將解壓包解壓然后安裝即可(壓縮過(guò)程就是普通的Ubuntu壓縮操作,去搜一下就有),壓縮包千萬(wàn)別選錯(cuò)了,我就是因?yàn)樯岛鹾醯倪x錯(cuò)了,在那調(diào)了半天bug,鏈接在此:https://registry.npmmirror.com/binary.html?path=node/v8.11.2/
然后是go-vnt(gvnt),這個(gè)是用來(lái)搭建本地的私鏈用的(雖然我在后面其實(shí)并沒有用到,因?yàn)榉N種原因我是直接跳過(guò)本地私鏈這部分,直接跳到官方的測(cè)試網(wǎng)上的,具體原因看到博客后面有,這里不做過(guò)多贅述)
Download下載方式如下:
git clone https://github.com/vntchain/go-vnt.git
Switch tree好像是切換版本,如果不切換的話會(huì)有報(bào)錯(cuò):
git checkout v0.6.4-alpha.6
compille試運(yùn)行(這里有可能會(huì)出現(xiàn)找不到gvnt目錄的情況,建議先找到所在目錄再運(yùn)行,然后之后如果調(diào)用gvnt只需要加上目錄即可,比如:./....../gvnt):
make gvnt
If failed , please install go v1.10 and retry.(可能有用的修改方法,我反正沒試過(guò))
link to your environment(連接網(wǎng)絡(luò))
bottle的下載倒是挺簡(jiǎn)單,沒有報(bào)錯(cuò)直接下載就行了
sudo docker pull vntchain/bottle:0.6.1
sudo docker image ls
輸入上面的代碼會(huì)得到以下這個(gè)反饋
REPOSITORY TAG IMAGE ID CREATED SIZE
vntchain/bottle 0.6.1 647ad4101419 2 years ago 1.9GB
vnt.js && vnt-kit.js這個(gè)是最最最惡心的部分,是部署合約的環(huán)境,按理來(lái)說(shuō)按照下面的部分代碼一個(gè)個(gè)下載過(guò)去就好了,但問(wèn)題就是如果前面的其他環(huán)境有錯(cuò)誤或者版本不適配,就會(huì)導(dǎo)致這里死活下不了,而且就算前面都沒問(wèn)題,到了這里下載也還是會(huì)出問(wèn)題,因?yàn)樗@個(gè)都是安裝在node-modules里面的,是作為node的一個(gè)環(huán)境配置(node就是相當(dāng)于前端的模擬環(huán)境,類似于vscode的環(huán)境放到Ubuntu里面來(lái)),但是很詭異,當(dāng)下載了vnt的時(shí)候,再去下載vnt-kit,他會(huì)自動(dòng)把vnt刪掉,反過(guò)來(lái)也是如此,我也不知道這兩什么仇什么怨,就是無(wú)法同時(shí)下載,因此我是先把vnt下載好拷貝好,在下載vnt-kit之后再把vnt拷貝進(jìn)去,這樣就不會(huì)被自動(dòng)刪除掉了,下載代碼如下:
npm install --save https://github.com/vntchain/vnt.js.git
npm install --save https://github.com/vntchain/vnt-kit.js.git
npm install --save ethereumjs-tx@1.3.7
npm install --save ethereumjs-account`
3.編寫合約的環(huán)境
智能合約的編寫只需要vntlib.h這個(gè)官方庫(kù)就好,因?yàn)橛行┓椒ǖ亩x都在這個(gè)里面
wget https://github.com/vntchain/vnt-documentation/blob/master/smart-contract/vntlib.h
但是上面這個(gè)方法我是行不通,你們可以去試試,我下載下來(lái)之后全都是web前端的格式,完全用不了,我是直接去官方網(wǎng)站把他的方法給copy到文檔里面去使用的
鏈接在這:https://github.com/vntchain/vnt-documentation/blob/master/smart-contract/vntlib.h
4.編譯合約的環(huán)境
智能合約的編譯只需要docker的安裝即可,在上面的環(huán)境安裝中就已安裝,這里便不做過(guò)多贅述。
5.部署合約的環(huán)境
智能合約的部署環(huán)境就是vnt,vnt-kit,然后在編譯的時(shí)候也有可能會(huì)報(bào)錯(cuò)說(shuō)缺少別的環(huán)境,如bignumber.js和node-XMLHttpRequest-1.8.0.js等,這些都可以在GitHub·上搜到,隨意挑選一個(gè)版本安裝到node-moudles中就行。
部署前記得npm init一下就行。
node在前面就已經(jīng)安裝,合約的部署也需要用到node。
6.調(diào)用合約的環(huán)境
合約的調(diào)用就只需要進(jìn)入node,然后將撰寫完成的合約調(diào)用文件運(yùn)行之后調(diào)用其中的方法即可,歸根到底還是把node搭建好,node-moudles配置完成就行。
二、私鏈的搭建
我們按照開發(fā)者文檔中的步驟,進(jìn)行了下列的操作,來(lái)自己模擬搭建了一個(gè)私鏈(雖然到后面其實(shí)并沒有用到,而是直接使用了官方的測(cè)試網(wǎng)絡(luò),但是可以通過(guò)私鏈的搭建對(duì)賬戶和節(jié)點(diǎn)進(jìn)行更深層次的了解):
首先是創(chuàng)建私鏈文件夾來(lái)存放節(jié)點(diǎn)
cd ~/project/vntchain/testnet
創(chuàng)建兩個(gè)節(jié)點(diǎn)和
sudo ./build/bin/gvnt account new --datadir node4
sudo ./build/bin/gvnt account new --datadir node5
會(huì)得到返回值如下,記下地址,后面會(huì)用到
huang@ubuntu:/src/github.com/vntchain/go-vnt/testnet$ sudo /src/github.com/vntchain/go-vnt/build/bin/gvnt account new --datadir node4
INFO [03-18|19:18:46] Maximum peer count VNT=25 LES=0 total=25
Your new account is locked with a password. Please give a password. Do not forget this password.
Passphrase:
Repeat passphrase:
Address: {ef53ac803c72cfeeb4565c6ff14dc23c9c82da41}
huang@ubuntu:/src/github.com/vntchain/go-vnt/testnet$ sudo /src/github.com/vntchain/go-vnt/build/bin/gvnt account new --datadir node5
INFO [03-18|19:21:20] Maximum peer count VNT=25 LES=0 total=25
Your new account is locked with a password. Please give a password. Do not forget this password.
Passphrase:
Repeat passphrase:
Address: {1e18fd9240ab043ebb88703abc43bdac98e4eb7d}
創(chuàng)建連接
sudo /src/github.com/vntchain/go-vnt/build/bin/gvnt --datadir node4 --port 13000 console
udo /src/github.com/vntchain/go-vnt/build/bin/gvnt --datadir node5 --port 13001 console
并且分別輸入如下指令
admin.nodeInfo.vnode
得到的返回值如下
huang@ubuntu:/src/github.com/vntchain/go-vnt/testnet$ sudo /src/github.com/vntchain/go-vnt/build/bin/gvnt --datadir node4 --port 13000 console
INFO [03-18|19:23:23] Maximum peer count VNT=25 LES=0 total=25
INFO [03-18|19:23:23] Starting peer-to-peer node instance=Gvnt/v0.6.4/linux-amd64/go1.10.4
INFO [03-18|19:23:23] Allocated cache and file handles database=/src/github.com/vntchain/go-vnt/testnet/node4/gvnt/chaindata cache=768 handles=512
INFO [03-18|19:23:23] Writing default main-net genesis block
INFO [03-18|19:23:23] Persisted trie from memory database nodes=60 size=9.31kB time=238.947μs gcnodes=0 gcsize=0.00B gctime=0s livenodes=1 livesize=0.00B
INFO [03-18|19:23:23] Initialised chain configuration config="{ChainID: 1 Hubble: <nil> Engine: dpos}"
INFO [03-18|19:23:23] Initialising VNT protocol versions="[63 62]" network=1
INFO [03-18|19:23:23] Loaded most recent local header number=0 hash=f2ba87…83e5ad td=1
INFO [03-18|19:23:23] Loaded most recent local full block number=0 hash=f2ba87…83e5ad td=1
INFO [03-18|19:23:23] Loaded most recent local fast block number=0 hash=f2ba87…83e5ad td=1
INFO [03-18|19:23:23] Regenerated local transaction journal transactions=0 accounts=0
WARN [03-18|19:23:23] There is no witness candidates. If you want to be a witness, please register now.
INFO [03-18|19:23:23] test services kind=*vnt.VNT
INFO [03-18|19:23:23] test services kind=*whisperv6.Whisper
INFO [03-18|19:23:23] ConstructDHT addr=/ip4/127.0.0.1/tcp/13000/ipfs/1kHErkJDvoexWxGUCefSwiYMYrP1KuLKBAv2UsKiJVMVw6t
INFO [03-18|19:23:23] started whisper v.6.0
INFO [03-18|19:23:23] IPC endpoint opened url=/src/github.com/vntchain/go-vnt/testnet/node4/gvnt.ipc
Welcome to the Gvnt JavaScript console!
instance: Gvnt/v0.6.4/linux-amd64/go1.10.4
INFO [03-18|19:23:23] Coinbase automatically configured address=0xEF53aC803C72CFEeb4565c6ff14dC23c9c82DA41
coinbase: 0xef53ac803c72cfeeb4565c6ff14dc23c9c82da41
at block: 0 (Sun, 30 Jun 2019 09:00:00 PDT)
datadir: /src/github.com/vntchain/go-vnt/testnet/node4
modules: admin:1.0 bp:1.0 core:1.0 debug:1.0 dpos:1.0 net:1.0 personal:1.0 rpc:1.0 shh:1.0 txpool:1.0 vnt:1.0
> admin.nodeInfo.vnode
"/ip4/127.0.0.1/tcp/13000/ipfs/1kHErkJDvoexWxGUCefSwiYMYrP1KuLKBAv2UsKiJVMVw6t"
> INFO [03-18|19:24:06] IPC endpoint closed endpoint=/src/github.com/vntchain/go-vnt/testnet/node4/gvnt.ipc
INFO [03-18|19:24:06] P2P server is being closed...
INFO [03-18|19:24:06] Blockchain manager stopped
INFO [03-18|19:24:06] Stopping VNT protocol
INFO [03-18|19:24:06] VNT protocol stopped
INFO [03-18|19:24:06] Transaction pool stopped
INFO [03-18|19:24:06] Database closed database=/src/github.com/vntchain/go-vnt/testnet/node4/gvnt/chaindata
INFO [03-18|19:24:06] stop services kind=*vnt.VNT
INFO [03-18|19:24:06] whisper stopped
INFO [03-18|19:24:06] stop services kind=*whisperv6.Whisper
INFO [03-18|19:24:06] Server is Stopping!
INFO [03-18|19:24:06] Server stop
huang@ubuntu:/src/github.com/vntchain/go-vnt/testnet$ sudo /src/github.com/vntchain/go-vnt/build/bin/gvnt --datadir node5 --port 13001 console
INFO [03-18|19:24:29] Maximum peer count VNT=25 LES=0 total=25
INFO [03-18|19:24:29] Starting peer-to-peer node instance=Gvnt/v0.6.4/linux-amd64/go1.10.4
INFO [03-18|19:24:29] Allocated cache and file handles database=/src/github.com/vntchain/go-vnt/testnet/node5/gvnt/chaindata cache=768 handles=512
INFO [03-18|19:24:29] Writing default main-net genesis block
INFO [03-18|19:24:29] Persisted trie from memory database nodes=60 size=9.31kB time=216.093μs gcnodes=0 gcsize=0.00B gctime=0s livenodes=1 livesize=0.00B
INFO [03-18|19:24:29] Initialised chain configuration config="{ChainID: 1 Hubble: <nil> Engine: dpos}"
INFO [03-18|19:24:29] Initialising VNT protocol versions="[63 62]" network=1
INFO [03-18|19:24:29] Loaded most recent local header number=0 hash=f2ba87…83e5ad td=1
INFO [03-18|19:24:29] Loaded most recent local full block number=0 hash=f2ba87…83e5ad td=1
INFO [03-18|19:24:29] Loaded most recent local fast block number=0 hash=f2ba87…83e5ad td=1
INFO [03-18|19:24:29] Regenerated local transaction journal transactions=0 accounts=0
WARN [03-18|19:24:29] There is no witness candidates. If you want to be a witness, please register now.
INFO [03-18|19:24:29] test services kind=*vnt.VNT
INFO [03-18|19:24:29] test services kind=*whisperv6.Whisper
INFO [03-18|19:24:29] ConstructDHT addr=/ip4/127.0.0.1/tcp/13001/ipfs/1kHhfi3oKZnt8qGhQHS7QezUfjQZoHHm4T2HK6M4qVKCseb
INFO [03-18|19:24:29] started whisper v.6.0
INFO [03-18|19:24:29] IPC endpoint opened url=/src/github.com/vntchain/go-vnt/testnet/node5/gvnt.ipc
Welcome to the Gvnt JavaScript console!
instance: Gvnt/v0.6.4/linux-amd64/go1.10.4
INFO [03-18|19:24:29] Coinbase automatically configured address=0x1E18Fd9240aB043EBB88703AbC43bDac98E4eB7d
coinbase: 0x1e18fd9240ab043ebb88703abc43bdac98e4eb7d
at block: 0 (Sun, 30 Jun 2019 09:00:00 PDT)
datadir: /src/github.com/vntchain/go-vnt/testnet/node5
modules: admin:1.0 bp:1.0 core:1.0 debug:1.0 dpos:1.0 net:1.0 personal:1.0 rpc:1.0 shh:1.0 txpool:1.0 vnt:1.0
> admin.nodeInfo.vnode
"/ip4/127.0.0.1/tcp/13001/ipfs/1kHhfi3oKZnt8qGhQHS7QezUfjQZoHHm4T2HK6M4qVKCseb"
> INFO [03-18|19:24:40] IPC endpoint closed endpoint=/src/github.com/vntchain/go-vnt/testnet/node5/gvnt.ipc
INFO [03-18|19:24:40] P2P server is being closed...
INFO [03-18|19:24:40] Blockchain manager stopped
INFO [03-18|19:24:40] Stopping VNT protocol
INFO [03-18|19:24:40] VNT protocol stopped
INFO [03-18|19:24:40] Transaction pool stopped
INFO [03-18|19:24:40] Database closed database=/src/github.com/vntchain/go-vnt/testnet/node5/gvnt/chaindata
INFO [03-18|19:24:40] stop services kind=*vnt.VNT
INFO [03-18|19:24:40] whisper stopped
INFO [03-18|19:24:40] stop services kind=*whisperv6.Whisper
INFO [03-18|19:24:40] Server is Stopping!
INFO [03-18|19:24:40] Server stop
接著輸入如下指令激活節(jié)點(diǎn)
sudo rm -rf node4/gvnt
sudo rm -rf node5/gvnt
然后就餓可以啟動(dòng)節(jié)點(diǎn)
huang@ubuntu:/src/github.com/vntchain/go-vnt/testnet$ sudo /src/github.com/vntchain/go-vnt/build/bin/gvnt --networkid 1012 --datadir node4 --port 13000 console
huang@ubuntu:/src/github.com/vntchain/go-vnt/testnet$ sudo /src/github.com/vntchain/go-vnt/build/bin/gvnt --networkid 1012 --datadir node5 --port 13001 --vntbootnode "/ip4/127.0.0.1/tcp/13000/ipfs/1kHErkJDvoexWxGUCefSwiYMYrP1KuLKBAv2UsKiJVMVw6t" console
之后解鎖節(jié)點(diǎn)
> personal.unlockAccount(core.coinbase, "", 3153600000)
true
> bp.start()
> personal.unlockAccount(core.coinbase, "", 3153600000)
true
> bp.start()
到此,個(gè)人的私鏈便搭建完畢了,連接到私鏈當(dāng)中的節(jié)點(diǎn)只有兩個(gè),也可以增加連接的節(jié)點(diǎn)使得私鏈更加完善。
三、編寫并且編譯智能合約
智能合約的編寫需要使用C語(yǔ)言進(jìn)行編寫,同時(shí)記得將vntlib.h的頭文件下載下來(lái),文件的下載連接為https://github.com/vntchain/vnt-documentation/blob/master/smart-contract/vntlib.h
將頭文件下載完成之后便可以開始編寫智能合約,由于這是未完成版,所以我也只完成了藝術(shù)品的簡(jiǎn)單上傳和查詢功能,只能簡(jiǎn)單的由時(shí)間戳來(lái)生成藝術(shù)品的ID,并且通過(guò)ID來(lái)查詢藝術(shù)品的名稱,擁有者等信息,功能還是十分簡(jiǎn)陋的,后續(xù)我會(huì)不斷完善,等整個(gè)作業(yè)徹底完成后我會(huì)再發(fā)一篇博客,這里便只記錄目前為止的簡(jiǎn)陋功能(輕噴?。。?/p>
#include "vntlib.h"
typedef struct{
string name;
address creator;
address owner;
uint256 price;
uint256 id;
bool flag;
}item;
KEY uint64 itemAccount=0;//商品總數(shù),用來(lái)管理全部的商品
KEY mapping(uint256,item)itemMap;//商品的ID映射到商品
KEY mapping(uint64,uint256)toId;//商品的序號(hào)(由總數(shù)決定)映射商品的ID
//獲取發(fā)起者地址GetSender();
KEY address contractOwner;
constructor NFTshop3(){
contractOwner = GetSender();
}
//UNMUTABLE
MUTABLE
string addItemToShop(
string itemName,
uint256 itemPrice,
string itemUrl
){
address itemCreator=GetSender();
uint64 timeStamp=GetTimestamp();
//將字符串轉(zhuǎn)化為uint64,uint64 ToU64(string value);
uint64 a=ToU64(AddressToString(itemCreator));
// uint64轉(zhuǎn)成uint256,uint256 U256FromU64(uint64 x);
uint256 nftId = U256FromU64(timeStamp+a);
itemAccount=itemAccount+1;
toId.key=itemAccount;
toId.value=nftId;//將新的商品加入總庫(kù)
itemMap.key=nftId;
itemMap.value.name = itemName;
itemMap.value.creator=itemCreator;
itemMap.value.owner=itemCreator;
itemMap.value.price=itemPrice;
itemMap.value.id=nftId;
itemMap.value.flag=true;
toId.key=itemAccount;
return U256ToString(U256FromU64(itemAccount));
//return U256ToString(toId.value);
//return U256ToString(itemMap.value.id);
//return U256ToString(nftId);
}
UNMUTABLE
string findNameFromShop(uint64 x){
//toId.key=itemAccount;
//return U256ToString(toId.value);
toId.key=x;
itemMap.key=toId.value;
return itemMap.value.name;
//return U256ToString(U256FromU64(itemAccount));
}
UNMUTABLE
string findIdFromShop(uint64 x){
toId.key=x;
itemMap.key=toId.value;
return U256ToString(itemMap.value.id);
}
UNMUTABLE
address findCreatorFromShop(uint64 x){
toId.key=x;
itemMap.key=toId.value;
return U256ToString(itemMap.value.creator);
}
UNMUTABLE
address findOwnerFromShop(uint64 x){
toId.key=x;
itemMap.key=toId.value;
return itemMap.value.owner;
}
UNMUTABLE
string findPriceFromShop(uint64 x){
toId.key=x;
itemMap.key=toId.value;
return U256ToString(itemMap.value.price);
}
/*
UNMUTABLE
string findNameFromShop(string Id){
itemMap.key=U256From(Id);
string out=itemMap.value.name;
return out;
//return U256ToString(U256FromU64(itemAccount));
}*/
合約之后還要進(jìn)行編譯,運(yùn)用到的是docker來(lái)編譯,只需要修改文件路徑和文件名稱即可
docker run --rm -v /home/lemon/project/vntchain/testnet/demo/contract:/tmp vntchain/bottle:0.6.1 compile -code /tmp/sample.c
四、部署智能合約
將合約進(jìn)行編譯之后便是合約的部署,將編譯完成之后的合約部署到測(cè)試網(wǎng)上,而部署的語(yǔ)言采用的是js語(yǔ)言,我在這之前也是從未接觸過(guò)js語(yǔ)言,這屬實(shí)是讓我重新學(xué)到了很多的新知識(shí),包括js語(yǔ)言的語(yǔ)法,以及在這之中也遇到了很多的問(wèn)題,包括合約的部署是通過(guò)發(fā)起交易的形式來(lái)進(jìn)行的,賬戶的解鎖也與官方文檔不一致,需要進(jìn)行修改才可以部署等等,不過(guò)到了現(xiàn)在這個(gè)地步,我已經(jīng)很熟練的可以部署了哈哈,畢竟曾經(jīng)一天把測(cè)試代幣全部花完用來(lái)部署合約的能力可不是蓋的。
首先是部署文件,通過(guò)該部署文件才能進(jìn)行下面的部署工作:
var fs = require('fs');
var Vnt = require("vnt")
var vntkit = require("vnt-kit")
var Tx = require("ethereumjs-tx")
//var config = require("./config")
// 設(shè)置連接的節(jié)點(diǎn)
var vnt = new Vnt();
vnt.setProvider(new vnt.providers.HttpProvider("http://47.111.100.232:8880"));
// 解鎖用戶
var privateKey='私鑰用自己的就行'
var pass1 = '自己設(shè)置的賬戶密碼'
function openAccount(file, passwd) {
var content = fs.readFileSync(file).toString("utf-8")
return vntkit.account.decrypt(content, passwd, false)
}
try{
var account = openAccount('私鑰存放位置即可', pass1)
console.log(account)
}catch(err){
console.log(err.message)
}
// 準(zhǔn)備代碼和abi
//將代碼的編譯后的文件路徑放入
var codeFile = "/home/huang/output/Sample.compress"
var abiFile = "/home/huang/output/Sample.abi"
var wasmabi = fs.readFileSync(abiFile)
//將abi數(shù)據(jù)解析成json結(jié)構(gòu)
var abi = JSON.parse(wasmabi.toString("utf-8"))
// 部署合約
function getTransactionReceipt(tx, cb) {
var receipt = vnt.core.getTransactionReceipt(tx);
if (!receipt) {
setTimeout(function() {
getTransactionReceipt(tx, cb)
}, 1000);
} else {
cb(receipt)
}
}
//這是合約創(chuàng)建主函數(shù)
function deployWasmContract() {
// 通過(guò)abi與代碼路徑初始化合約
var contract = vnt.core.contract(abi).codeFile(codeFile)
// 生成合約創(chuàng)建的數(shù)據(jù)
var data = contract.packContructorData()
var gas = vnt.core.estimateGas({data: data});
var nonce = vnt.core.getTransactionCount('填寫自己的賬戶地址就行');
// 生成交易的結(jié)構(gòu)體,指定nonce, gasPirce, gasLimit, value, data等字段
var options = {
nonce: vnt.toHex(nonce),
gasPrice: vnt.toHex(30000000000000),
gasLimit: vnt.toHex(gas),
value: '0x00',
data: data,
chainId: 2 //這里必須指定chainId,即你所連接的node的chainId,否則交易簽名將出錯(cuò)
}
// 生成交易
var tx = new Tx(options);
// 使用之前準(zhǔn)備好的私鑰,對(duì)交易簽名
tx.sign(new Buffer(privateKey, "hex"));
// 將交易數(shù)據(jù)進(jìn)行序列化
var serializedTx = tx.serialize();
// 發(fā)送交易
vnt.core.sendRawTransaction('0x' + serializedTx.toString('hex'),
function(err, txHash) {
if (err) {
console.log("err happened: ", err)
} else {
// 打印交易的hash
console.log("transaction hash: ", txHash);
// 獲取交易的清單
getTransactionReceipt(txHash, function(receipt) {
console.log("tx receipt: ", receipt)
console.log("tx status: ", receipt.status)
console.log("contract address: ", receipt.contractAddress)
})
}
});
}
// 調(diào)用部署函數(shù)
deployWasmContract();
之后只要node上面的部署代碼文件即可,會(huì)返回合約的地址,可以在測(cè)試網(wǎng)中查詢到合約的信息:
node deploy_script.js
五、調(diào)用智能合約
第二個(gè)大頭來(lái)了,上面的合約的編寫和這里的調(diào)用都是大問(wèn)題,因?yàn)楹霞s的調(diào)用涉及到是否有鏈上的內(nèi)容修改產(chǎn)生,若有產(chǎn)生需要發(fā)起交易才行,這也導(dǎo)致了我在寫這部分的時(shí)候被折磨的不輕,怎么調(diào)用怎么報(bào)錯(cuò),還好最后時(shí)刻還是解決了,以下是我的調(diào)用部分代碼,也是未完成版,只能對(duì)上述的合約進(jìn)行調(diào)用,并且沒有設(shè)計(jì)到虛擬貨幣的交易情況,這部分代碼我也會(huì)在之后繼續(xù)完善,希望可以早點(diǎn)完成,如何交易記錄是可以在合約里查詢到的,也是在測(cè)試網(wǎng)中搜索合約,會(huì)有該合約的交易記錄顯示在下方。
這是調(diào)用的代碼,也是js文件(太難了):
var fs = require('fs');
var Vnt = require("vnt")
var vntkit = require("vnt-kit")
var Tx= require("ethereumjs-tx")
// 設(shè)置連接的節(jié)點(diǎn)
var vnt = new Vnt();
vnt.setProvider(new vnt.providers.HttpProvider("http://47.111.100.232:8880"))
// 合約部署地址
var contractAddress = '合約的地址'
var chainid = 2;
// 解鎖用戶
var account_address = '賬戶地址';
var account_password = '賬戶密碼';
var privateKey='賬戶私鑰'
function openAccount(file, passwd) {
var content = fs.readFileSync(file).toString("utf-8")
return vntkit.account.decrypt(content, passwd, false)
}
try{
var account = openAccount('/home/huang/keystore', account_password)
console.log(account)
}catch(err){
console.log(err.message)
}
// 準(zhǔn)備代碼和abi
var baseDir = "/src/github.com/vntchain/go-vnt/testnet/demo/contract/output/"
var abiFile = baseDir+"NFTshop3.abi"
var wasmabi = fs.readFileSync(abiFile)
//將abi數(shù)據(jù)解析成json結(jié)構(gòu)
var abi = JSON.parse(wasmabi.toString("utf-8"))
function call_addItemToShop(name,price,url){
var contract = vnt.core.contract(abi)
var data = contract.packFunctionData("addItemToShop", [name,price,url]);
console.log("addItemToShop : "+data);
// 獲取下一個(gè)nonce值
var nonce = vnt.core.getTransactionCount(account_address);
console.log("nonce : "+nonce);
// 其中to字段為合約地址,data字段為合約調(diào)用的data
var options = {
from:account_address,
to:contractAddress,
nonce: vnt.toHex(nonce),
gasPrice: vnt.toHex(30000000000000),
gasLimit: vnt.toHex(4000000),
value: '0x00',
data: data,
chainId: 2
}
// 生成交易
var tx = new Tx(options);
// 使用之前準(zhǔn)備好的私鑰,對(duì)交易簽名
tx.sign(new Buffer('賬戶私鑰', "hex"));
// 將交易數(shù)據(jù)進(jìn)行序列化
var serializedTx = tx.serialize();
// 發(fā)送交易
vnt.core.sendRawTransaction('0x' + serializedTx.toString('hex'),
function(err, txHash) {
if (err) {
console.log("err happened: ", err)
} else {
// 打印交易的hash
console.log("transaction hash: ", txHash);
// 獲取交易的清單
getTransactionReceipt(txHash, function(receipt) {
console.log("tx receipt: ", receipt)
console.log("tx status: ", receipt.status)
console.log("contract address: ", receipt.contractAddress)
})
}
});
var result = vnt.core.call(options);
console.log('id : '+contract.unPackOutput("addItemToShop", result).toString());
}
function call_findNameFromShop(id){
var contract = vnt.core.contract(abi).at(contractAddress);
var res = contract.findNameFromShop.call(id,{from:account_address});
console.log('call_findNameFromShop output : '+res);
return res;
}
function call_findIdFromShop(id){
var contract = vnt.core.contract(abi).at(contractAddress);
var res = contract.findIdFromShop.call(id,{from:account_address});
console.log('call_findIdFromShop output : '+res);
return res;
}
function call_findCreatorFromShop(id){
var contract = vnt.core.contract(abi).at(contractAddress);
var res = contract.findCreatorFromShop.call(id,{from:account_address});
console.log('call_findCreatorFromShop output : '+res);
return res;
}
function call_findOwnerFromShop(id){
var contract = vnt.core.contract(abi).at(contractAddress);
var res = contract.findOwnerFromShop.call(id,{from:account_address});
console.log('call_findOwnerFromShop output : '+res);
return res;
}
function call_findPriceFromShop(id){
var contract = vnt.core.contract(abi).at(contractAddress);
var res = contract.findPriceFromShop.call(id,{from:account_address});
console.log('call_findPriceFromShop output : '+res);
return res;
}
module.exports={
addItemToShop:call_addItemToShop,
findNameFromShop:call_findNameFromShop,
findPriceFromShop:call_findPriceFromShop,
findCreatorFromShop:call_findCreatorFromShop,
findOwnerFromShop:call_findOwnerFromShop,
findIdFromShop:call_findIdFromShop
}
接著就可以進(jìn)入node進(jìn)行模擬了,因?yàn)閚ode就是模擬的前端,所以在node中只要打開調(diào)用文件,然后調(diào)用相關(guān)方法即可:
調(diào)用格式如下:(先輸入node進(jìn)入虛擬環(huán)境)
> var cs = require('./call_sample.js')
> cs.getName()
call_getName output : GenjiLemon
'GenjiLemon'
> cs.setName('lll')
undefined
六、參考文獻(xiàn)
這些是我的部分參考文檔文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-415053.html
VNT測(cè)試網(wǎng)以及相關(guān)指導(dǎo)https://hubscan.vnt.link/
官方指導(dǎo)函數(shù)文檔https://github.com/vntchain/vnt.js/blob/master/doc/api-reference.md#returns-46
指導(dǎo)文檔2https://github.com/vntchain/vnt-documentation/blob/master/api/vnt-json-rpc-api.md)
https://github.com/vntchain/vnt-documentation/blob/master/api/vnt-json-rpc-api.md
一位不知名大佬的參考合約編寫https://github.com/search?l=C&q=vntchain&type=Repositories)
https://github.com/search?l=C&q=vntchain&type=Repositories
以及還有CSDN的各位大佬的博客
總結(jié)
以上就是本次比賽我所有的所作所為的總結(jié)了,這篇博客也只能先草草結(jié)束了,因?yàn)樽罱返氖虑橛悬c(diǎn)多,需要做的也很多,得花時(shí)間一件件去補(bǔ),再加上我也好久沒寫博客(主要是因?yàn)閼?,自從去年寒假集?xùn)之后就沒寫過(guò)了,鴿子王名不虛傳,不過(guò)接下來(lái)還是會(huì)繼續(xù)寫下去,順便記錄一下我的大學(xué)學(xué)習(xí)和生活)本來(lái)還想把遇到的各種問(wèn)題都寫上去,但時(shí)間跨度真的太長(zhǎng)了,實(shí)在是力不從心,只能想一點(diǎn)寫一點(diǎn),最后也只完成了這份大概的初稿,不過(guò)這是一次很難忘很難忘的經(jīng)歷,畢竟好幾個(gè)周末加工作日的晚上我都泡在那里敲代碼,屬實(shí)是頂不住了,這是一次很好的鍛煉機(jī)會(huì),我也在這之中學(xué)到了很多,感謝學(xué)長(zhǎng)學(xué)姐還有我的室友給我的幫助。
但是如你所見,我也還有很多很多不足的地方,還有很多的東西需要學(xué),這個(gè)項(xiàng)目也還有很多的部分需要去完成,這篇博客到這就結(jié)束了,但是這個(gè)項(xiàng)目還沒有結(jié)束,學(xué)習(xí)也還沒有結(jié)束,繼續(xù)加油!
ps:輕噴,我知道我真的很菜,要是有不足的地方請(qǐng)?jiān)谙路街赋觯瑫r(shí)也歡迎大佬來(lái)指點(diǎn)我一下,或者有想一起學(xué)習(xí)的也可以在下方留言,那就這樣,謝謝!?。?!文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-415053.html
到了這里,關(guān)于《第十三屆服創(chuàng)大賽A23項(xiàng)目-基于區(qū)塊鏈的藝術(shù)品數(shù)字資產(chǎn)確權(quán)流通系統(tǒng)》的未完成版的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!