文章目录
文章目录
文章目录开始前零、相关概念1.区块链是什么?2.NFT是什么?3.智能合约是什么?4.我这个后端究竟在干啥?一、准备工作-环境的部署1.虚拟机以及linux布置2.在编写合约之前所做的准备3.编写合约的环境4.编译合约的环境5.部署合约的环境6.调用合约的环境二、私链的搭建三、编写并且编译智能合约四、部署智能合约五、调用智能合约六、参考文献总结开始前
首先声明,这个比赛是由我室友,学长学姐以及本人共同参与完成(虽然这个项目还没完全做完来着,但好歹是终于交上去了)我只负责了其中的后端代码的一部分内容,而且由于一开始完全不懂的关系,基本上是属于走一步看一步学一步的过程,所以进度一度十分缓慢,并且之中有很多的部分也不能保证完全正确,只能说是暂时先用着,如果之后发现错误会及时更改,并且这个项目也在不断完善的过程中,等全部完成后会再发一次博客,这次的就当完成一部分交上去之后的一个小小的总结,记录一下我大学第一次参加的比赛项目过程,以及心路历程。
在此,感谢我的室友,还有学长学姐的帮助,才能让这个项目得以顺利进行
项目进行过程中所用到的所有资料链接我都会放在最后,而具体的代码我也会放在文章中(因为大部分都是环境的部署,以及未完成的关系,我的代码其实尤其的少,估计等全部完成后就会变多),其余的则打包上传github(等我弄明白github怎么搞就上传),大概就是这样。
零、相关概念
1.区块链是什么?
区块链作为一个新兴的词汇,在近几年逐渐变得活跃,但是其含义还是很抽象,其实到现在我也不能说完全理解,只能说是在基于这个项目的基础之上有我自己的理解,首先区块链是一个完全的去中心化的,相当于是不存在所谓的管理员这一职务,每一个加入到区块链中的个体都是管理者。
可以打一个比喻,我们平时向他人发送交易的时候,如果交易的记录被人篡改,那么交易本身就会出现很多问题,而引起交易篡改的可能性很多,比如你的计算机被人黑了,又或者网络出现了数据的丢失,又或者管理员在管理数据的时候出现了差错,这些都有可能,但是在区块链中,当你发起了一个交易之后,社区里的其他人都会来记录这个交易记录,如果之后需要查询交易的情况,只需要看社区里大家的记录单即可,若有人想要篡改交易记录,那他就需要把社区里至少一半以上的人的记录全部修改才行,如果把这放到现实生活中,很明显,把全球一半的电脑全部搞崩溃,这件事本身就几乎不可能,因此,交易记录便具有了安全性与不可更改性。
而同时,我们时常听到的区块链挖矿机制,其实就是社区里的人来争夺谁来第一个抄录这份交易情况,而给予记录者的奖励就是我们平时所讲的虚拟货币,如比特币等,当第一个人记录了之后,其他人只要把他的消息给记录下来即可,但是其他人则不具有第一个记录的奖励。
2.NFT是什么?
NFT的全称是Non-Fungible Token,指非同质化代币,是用于表示数字资产(包括jpg和视频剪辑形式)的唯一加密货币令牌,可以买卖。
也就是相当于一种电子艺术品,将其变为一种可以交易的电子信息,其具有不可仿造性和完整性,可以避免现实生活中的艺术品仿制造假现象。
3.智能合约是什么?
智能合约是一种写在区块链上的一份合约,我们可以通过向这个合约发起交易,来吧我们的交易记录在合约上,从而存储在区块链中,而智能合约的内容主要是以各种函数方法为主,可以通过调用方法,来发起交易,而交易的货币则是以虚拟货币为主。
4.我这个后端究竟在干啥?
说到这里,可能会有点迷糊的感觉,我当时在加入之后也是理解了很久才搞清楚我到底应该做什么,以下就是我整理之后的主要工作内容:
从前面我们可以知道,智能合约是存储在区块链上的,我们可以通过调用合约中的函数方法来进行交易的发起,将我们的交易记录通过交易的形式发送到合约上,比如我们要购买某一个东西,我们把自己购买的详细信息:谁购买的,从谁那买的,买的什么,价格是多少,什么时候买的等等。将这些信息打包,通过向合约发起交易的形式存储到合约中。
因此,我要做的便是智能合约的编写,将艺术品交易平台上用到的各种函数方法都编写进去,并且通过调用合约的方法存储交易记录,把调用的方法发给前端,从而实现网页版的艺术品交易平台的设计。
一、准备工作-环境的部署
这个后端代码的部署环境过于离谱,以至于光是配环境就花费了我和学长好久好久的时间,其中包含了大部分从未见过的、莫名其妙的、甚至已经相对比较老的bug,所以整个环境的部署十分的艰难,我也是查找了大量的CSDN,百度,知网以及guthub和求助万能的学长才解决了部分,以下是环境内容。
1.虚拟机以及linux布置
我采用的是VMware Workstation Pro作为虚拟机,使用的linux是ubuntu18.04版本,因为使用较为顺手,而且为了贴合那奇怪的环境,我也不敢用更新的版本,怕有奇怪的bug。
虚拟机我是在大一的网络安全课上就以及使用过并且当时是安装了win7版本,使用我会使用,但是这个linux,,,我只能说,很离谱,我是真的从来没听过这玩意,以至于我第一次进入的时候我人都傻了,这是个嘛玩意啊,怎么全是英文,文件在哪,浏览器在哪,终端为什么长这样子,完全和我的印象里的操作系统完全不一样,我光是研究这个linux就用了好多时间,也是到后来我才逐渐适应。
以下我会列举一些常用的语句,都是我熟悉的不能再熟悉的语句
cd 用来选择文件的目录路径touch example.c 在当前目录创建example.c文件vi example.c 修改文件gedit example.c 打开文件并且修改,比上面的vi操作要更加贴近我的习惯ctrl+f 选择所要查询的关键字sudo 在语句前面加上这个,增加权限,为了防止有permission报错install 下载指令,可以下载相关指令
2.在编写合约之前所做的准备
按照官方给的文档来看,环境有以下一大堆
Ubuntu 18.04、Manjaro(Or other OS based on Linux release)Python2DockerGo v1.10 (1.9+ ,version1.10 recommended)GitNode.js v8.11.2 or later
这个环境是真的折磨人,他对版本的要求很死板,前面的几个都问题不大,直接在Ubuntu的终端里面用install下载即可,注意下版本就行,把python的版本切成2就可用。
最为恶心的是后面的工具部分,首先是这个node.js,他要求的版本是8.11.2或者之后的,但还是建议下载8.11.2(别问,问就是别的版本各种报错不适配)将解压包解压然后安装即可(压缩过程就是普通的Ubuntu压缩操作,去搜一下就有),压缩包千万别选错了,我就是因为傻乎乎的选错了,在那调了半天bug,链接在此:
/binary.html?path=node/v8.11.2/
然后是go-vnt(gvnt),这个是用来搭建本地的私链用的(虽然我在后面其实并没有用到,因为种种原因我是直接跳过本地私链这部分,直接跳到官方的测试网上的,具体原因看到博客后面有,这里不做过多赘述)
Download下载方式如下:git clone /vntchain/go-vnt.gitSwitch tree好像是切换版本,如果不切换的话会有报错:git checkout v0.6.4-alpha.6compille试运行(这里有可能会出现找不到gvnt目录的情况,建议先找到所在目录再运行,然后之后如果调用gvnt只需要加上目录即可,比如:./....../gvnt):make gvntIf failed , please install go v1.10 and retry.(可能有用的修改方法,我反正没试过)link to your environment(连接网络)
bottle的下载倒是挺简单,没有报错直接下载就行了
sudo docker pull vntchain/bottle:0.6.1sudo docker image ls输入上面的代码会得到以下这个反馈REPOSITORY TAG IMAGE ID CREATED SIZE vntchain/bottle 0.6.1647ad4101419 2 years ago 1.9GB
vnt.js && vnt-kit.js这个是最最最恶心的部分,是部署合约的环境,按理来说按照下面的部分代码一个个下载过去就好了,但问题就是如果前面的其他环境有错误或者版本不适配,就会导致这里死活下不了,而且就算前面都没问题,到了这里下载也还是会出问题,因为他这个都是安装在node-modules里面的,是作为node的一个环境配置(node就是相当于前端的模拟环境,类似于vscode的环境放到Ubuntu里面来),但是很诡异,当下载了vnt的时候,再去下载vnt-kit,他会自动把vnt删掉,反过来也是如此,我也不知道这两什么仇什么怨,就是无法同时下载,因此我是先把vnt下载好拷贝好,在下载vnt-kit之后再把vnt拷贝进去,这样就不会被自动删除掉了,下载代码如下:
npm install --save /vntchain/vnt.js.gitnpm install --save /vntchain/vnt-kit.js.gitnpm install --save ethereumjs-tx@1.3.7npm install --save ethereumjs-account`
3.编写合约的环境
智能合约的编写只需要vntlib.h这个官方库就好,因为有些方法的定义都在这个里面
wget /vntchain/vnt-documentation/blob/master/smart-contract/vntlib.h但是上面这个方法我是行不通,你们可以去试试,我下载下来之后全都是web前端的格式,完全用不了,我是直接去官方网站把他的方法给copy到文档里面去使用的链接在这:/vntchain/vnt-documentation/blob/master/smart-contract/vntlib.h
4.编译合约的环境
智能合约的编译只需要docker的安装即可,在上面的环境安装中就已安装,这里便不做过多赘述。
5.部署合约的环境
智能合约的部署环境就是vnt,vnt-kit,然后在编译的时候也有可能会报错说缺少别的环境,如bignumber.js和node-XMLHttpRequest-1.8.0.js等,这些都可以在GitHub·上搜到,随意挑选一个版本安装到node-moudles中就行。
部署前记得npm init一下就行。
node在前面就已经安装,合约的部署也需要用到node。
6.调用合约的环境
合约的调用就只需要进入node,然后将撰写完成的合约调用文件运行之后调用其中的方法即可,归根到底还是把node搭建好,node-moudles配置完成就行。
二、私链的搭建
我们按照开发者文档中的步骤,进行了下列的操作,来自己模拟搭建了一个私链(虽然到后面其实并没有用到,而是直接使用了官方的测试网络,但是可以通过私链的搭建对账户和节点进行更深层次的了解):
首先是创建私链文件夹来存放节点
cd ~/project/vntchain/testnet
创建两个节点和
sudo ./build/bin/gvnt account new --datadir node4sudo ./build/bin/gvnt account new --datadir node5
会得到返回值如下,记下地址,后面会用到
huang@ubuntu:/src//vntchain/go-vnt/testnet$ sudo /src//vntchain/go-vnt/build/bin/gvnt account new --datadir node4INFO [03-18|19:18:46] Maximum peer count VNT=25 LES=0 total=25Your new account is locked with a password. Please give a password. Do not forget this password.Passphrase: Repeat passphrase: Address: {ef53ac803c72cfeeb4565c6ff14dc23c9c82da41}huang@ubuntu:/src//vntchain/go-vnt/testnet$ sudo /src//vntchain/go-vnt/build/bin/gvnt account new --datadir node5INFO [03-18|19:21:20] Maximum peer count VNT=25 LES=0 total=25Your new account is locked with a password. Please give a password. Do not forget this password.Passphrase: Repeat passphrase: Address: {1e18fd9240ab043ebb88703abc43bdac98e4eb7d}
创建连接
sudo /src//vntchain/go-vnt/build/bin/gvnt --datadir node4 --port 13000 consoleudo /src//vntchain/go-vnt/build/bin/gvnt --datadir node5 --port 13001 console
并且分别输入如下指令
admin.nodeInfo.vnode
得到的返回值如下
huang@ubuntu:/src//vntchain/go-vnt/testnet$ sudo /src//vntchain/go-vnt/build/bin/gvnt --datadir node4 --port 13000 consoleINFO [03-18|19:23:23] Maximum peer count VNT=25 LES=0 total=25INFO [03-18|19:23:23] Starting peer-to-peer nodeinstance=Gvnt/v0.6.4/linux-amd64/go1.10.4INFO [03-18|19:23:23] Allocated cache and file handles database=/src//vntchain/go-vnt/testnet/node4/gvnt/chaindata cache=768 handles=512INFO [03-18|19:23:23] Writing default main-net genesis block INFO [03-18|19:23:23] Persisted trie from memory databasenodes=60 size=9.31kB time=238.947µs gcnodes=0 gcsize=0.00B gctime=0s livenodes=1 livesize=0.00BINFO [03-18|19:23:23] Initialised chain configurationconfig="{ChainID: 1 Hubble: <nil> Engine: dpos}"INFO [03-18|19:23:23] Initialising VNT protocolversions="[63 62]" network=1INFO [03-18|19:23:23] Loaded most recent local headernumber=0 hash=f2ba87…83e5ad td=1INFO [03-18|19:23:23] Loaded most recent local full blocknumber=0 hash=f2ba87…83e5ad td=1INFO [03-18|19:23:23] Loaded most recent local fast blocknumber=0 hash=f2ba87…83e5ad td=1INFO [03-18|19:23:23] Regenerated local transaction journal transactions=0 accounts=0WARN [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.VNTINFO [03-18|19:23:23] test services kind=*whisperv6.WhisperINFO [03-18|19:23:23] ConstructDHT addr=/ip4/127.0.0.1/tcp/13000/ipfs/1kHErkJDvoexWxGUCefSwiYMYrP1KuLKBAv2UsKiJVMVw6tINFO [03-18|19:23:23] started whisper v.6.0 INFO [03-18|19:23:23] IPC endpoint opened url=/src//vntchain/go-vnt/testnet/node4/gvnt.ipcWelcome to the Gvnt JavaScript console!instance: Gvnt/v0.6.4/linux-amd64/go1.10.4INFO [03-18|19:23:23] Coinbase automatically configured address=0xEF53aC803C72CFEeb4565c6ff14dC23c9c82DA41coinbase: 0xef53ac803c72cfeeb4565c6ff14dc23c9c82da41at block: 0 (Sun, 30 Jun 09:00:00 PDT)datadir: /src//vntchain/go-vnt/testnet/node4modules: 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//vntchain/go-vnt/testnet/node4/gvnt.ipcINFO [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 closeddatabase=/src//vntchain/go-vnt/testnet/node4/gvnt/chaindataINFO [03-18|19:24:06] stop services kind=*vnt.VNTINFO [03-18|19:24:06] whisper stopped INFO [03-18|19:24:06] stop services kind=*whisperv6.WhisperINFO [03-18|19:24:06] Server is Stopping! INFO [03-18|19:24:06] Server stop huang@ubuntu:/src//vntchain/go-vnt/testnet$ sudo /src//vntchain/go-vnt/build/bin/gvnt --datadir node5 --port 13001 consoleINFO [03-18|19:24:29] Maximum peer count VNT=25 LES=0 total=25INFO [03-18|19:24:29] Starting peer-to-peer nodeinstance=Gvnt/v0.6.4/linux-amd64/go1.10.4INFO [03-18|19:24:29] Allocated cache and file handles database=/src//vntchain/go-vnt/testnet/node5/gvnt/chaindata cache=768 handles=512INFO [03-18|19:24:29] Writing default main-net genesis block INFO [03-18|19:24:29] Persisted trie from memory databasenodes=60 size=9.31kB time=216.093µs gcnodes=0 gcsize=0.00B gctime=0s livenodes=1 livesize=0.00BINFO [03-18|19:24:29] Initialised chain configurationconfig="{ChainID: 1 Hubble: <nil> Engine: dpos}"INFO [03-18|19:24:29] Initialising VNT protocolversions="[63 62]" network=1INFO [03-18|19:24:29] Loaded most recent local headernumber=0 hash=f2ba87…83e5ad td=1INFO [03-18|19:24:29] Loaded most recent local full blocknumber=0 hash=f2ba87…83e5ad td=1INFO [03-18|19:24:29] Loaded most recent local fast blocknumber=0 hash=f2ba87…83e5ad td=1INFO [03-18|19:24:29] Regenerated local transaction journal transactions=0 accounts=0WARN [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.VNTINFO [03-18|19:24:29] test services kind=*whisperv6.WhisperINFO [03-18|19:24:29] ConstructDHT addr=/ip4/127.0.0.1/tcp/13001/ipfs/1kHhfi3oKZnt8qGhQHS7QezUfjQZoHHm4T2HK6M4qVKCsebINFO [03-18|19:24:29] started whisper v.6.0 INFO [03-18|19:24:29] IPC endpoint opened url=/src//vntchain/go-vnt/testnet/node5/gvnt.ipcWelcome to the Gvnt JavaScript console!instance: Gvnt/v0.6.4/linux-amd64/go1.10.4INFO [03-18|19:24:29] Coinbase automatically configured address=0x1E18Fd9240aB043EBB88703AbC43bDac98E4eB7dcoinbase: 0x1e18fd9240ab043ebb88703abc43bdac98e4eb7dat block: 0 (Sun, 30 Jun 09:00:00 PDT)datadir: /src//vntchain/go-vnt/testnet/node5modules: 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//vntchain/go-vnt/testnet/node5/gvnt.ipcINFO [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 closeddatabase=/src//vntchain/go-vnt/testnet/node5/gvnt/chaindataINFO [03-18|19:24:40] stop services kind=*vnt.VNTINFO [03-18|19:24:40] whisper stopped INFO [03-18|19:24:40] stop services kind=*whisperv6.WhisperINFO [03-18|19:24:40] Server is Stopping! INFO [03-18|19:24:40] Server stop
接着输入如下指令激活节点
sudo rm -rf node4/gvntsudo rm -rf node5/gvnt
然后就饿可以启动节点
huang@ubuntu:/src//vntchain/go-vnt/testnet$ sudo /src//vntchain/go-vnt/build/bin/gvnt --networkid 1012 --datadir node4 --port 13000 consolehuang@ubuntu:/src//vntchain/go-vnt/testnet$ sudo /src//vntchain/go-vnt/build/bin/gvnt --networkid 1012 --datadir node5 --port 13001 --vntbootnode "/ip4/127.0.0.1/tcp/13000/ipfs/1kHErkJDvoexWxGUCefSwiYMYrP1KuLKBAv2UsKiJVMVw6t" console
之后解锁节点
> personal.unlockAccount(core.coinbase, "", 3153600000)true> bp.start()> personal.unlockAccount(core.coinbase, "", 3153600000)true> bp.start()
到此,个人的私链便搭建完毕了,连接到私链当中的节点只有两个,也可以增加连接的节点使得私链更加完善。
三、编写并且编译智能合约
智能合约的编写需要使用C语言进行编写,同时记得将vntlib.h的头文件下载下来,文件的下载连接为
/vntchain/vnt-documentation/blob/master/smart-contract/vntlib.h
将头文件下载完成之后便可以开始编写智能合约,由于这是未完成版,所以我也只完成了艺术品的简单上传和查询功能,只能简单的由时间戳来生成艺术品的ID,并且通过ID来查询艺术品的名称,拥有者等信息,功能还是十分简陋的,后续我会不断完善,等整个作业彻底完成后我会再发一篇博客,这里便只记录目前为止的简陋功能(轻喷!!)
#include "vntlib.h"typedef struct{string name;address creator;address owner;uint256 price;uint256 id;bool flag;}item;KEY uint64 itemAccount=0;//商品总数,用来管理全部的商品KEY mapping(uint256,item)itemMap;//商品的ID映射到商品KEY mapping(uint64,uint256)toId;//商品的序号(由总数决定)映射商品的ID//获取发起者地址GetSender();KEY address contractOwner;constructor NFTshop3(){contractOwner = GetSender();}//UNMUTABLEMUTABLEstring addItemToShop(string itemName,uint256 itemPrice,string itemUrl){address itemCreator=GetSender();uint64 timeStamp=GetTimestamp();//将字符串转化为uint64,uint64 ToU64(string value);uint64 a=ToU64(AddressToString(itemCreator));// uint64转成uint256,uint256 U256FromU64(uint64 x);uint256 nftId = U256FromU64(timeStamp+a);itemAccount=itemAccount+1;toId.key=itemAccount;toId.value=nftId;//将新的商品加入总库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);}UNMUTABLEstring 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));}UNMUTABLEstring findIdFromShop(uint64 x){toId.key=x;itemMap.key=toId.value;return U256ToString(itemMap.value.id);}UNMUTABLEaddress findCreatorFromShop(uint64 x){toId.key=x;itemMap.key=toId.value;return U256ToString(itemMap.value.creator);}UNMUTABLEaddress findOwnerFromShop(uint64 x){toId.key=x;itemMap.key=toId.value;return itemMap.value.owner;}UNMUTABLEstring findPriceFromShop(uint64 x){toId.key=x;itemMap.key=toId.value;return U256ToString(itemMap.value.price);}/*UNMUTABLEstring findNameFromShop(string Id){itemMap.key=U256From(Id);string out=itemMap.value.name;return out;//return U256ToString(U256FromU64(itemAccount));}*/
合约之后还要进行编译,运用到的是docker来编译,只需要修改文件路径和文件名称即可
docker run --rm -v /home/lemon/project/vntchain/testnet/demo/contract:/tmp vntchain/bottle:0.6.1 compile -code /tmp/sample.c
四、部署智能合约
将合约进行编译之后便是合约的部署,将编译完成之后的合约部署到测试网上,而部署的语言采用的是js语言,我在这之前也是从未接触过js语言,这属实是让我重新学到了很多的新知识,包括js语言的语法,以及在这之中也遇到了很多的问题,包括合约的部署是通过发起交易的形式来进行的,账户的解锁也与官方文档不一致,需要进行修改才可以部署等等,不过到了现在这个地步,我已经很熟练的可以部署了哈哈,毕竟曾经一天把测试代币全部花完用来部署合约的能力可不是盖的。
首先是部署文件,通过该部署文件才能进行下面的部署工作:
var fs = require('fs');var Vnt = require("vnt")var vntkit = require("vnt-kit")var Tx = require("ethereumjs-tx")//var config = require("./config")// 设置连接的节点var vnt = new Vnt();vnt.setProvider(new vnt.providers.HttpProvider("http://47.111.100.232:8880"));// 解锁用户var privateKey='私钥用自己的就行'var pass1 = '自己设置的账户密码'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)}// 准备代码和abi//将代码的编译后的文件路径放入var codeFile = "/home/huang/output/press"var abiFile = "/home/huang/output/Sample.abi"var wasmabi = fs.readFileSync(abiFile)//将abi数据解析成json结构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)}} //这是合约创建主函数function deployWasmContract() {// 通过abi与代码路径初始化合约var contract = vnt.core.contract(abi).codeFile(codeFile)// 生成合约创建的数据var data = contract.packContructorData()var gas = vnt.core.estimateGas({data: data});var nonce = vnt.core.getTransactionCount('填写自己的账户地址就行');// 生成交易的结构体,指定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,否则交易签名将出错}// 生成交易var tx = new Tx(options);// 使用之前准备好的私钥,对交易签名tx.sign(new Buffer(privateKey, "hex"));// 将交易数据进行序列化var serializedTx = tx.serialize();// 发送交易vnt.core.sendRawTransaction('0x' + serializedTx.toString('hex'),function(err, txHash) {if (err) {console.log("err happened: ", err)} else {// 打印交易的hashconsole.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)})}});}// 调用部署函数deployWasmContract();
之后只要node上面的部署代码文件即可,会返回合约的地址,可以在测试网中查询到合约的信息:
node deploy_script.js
五、调用智能合约
第二个大头来了,上面的合约的编写和这里的调用都是大问题,因为合约的调用涉及到是否有链上的内容修改产生,若有产生需要发起交易才行,这也导致了我在写这部分的时候被折磨的不轻,怎么调用怎么报错,还好最后时刻还是解决了,以下是我的调用部分代码,也是未完成版,只能对上述的合约进行调用,并且没有设计到虚拟货币的交易情况,这部分代码我也会在之后继续完善,希望可以早点完成,如何交易记录是可以在合约里查询到的,也是在测试网中搜索合约,会有该合约的交易记录显示在下方。
这是调用的代码,也是js文件(太难了):
var fs = require('fs');var Vnt = require("vnt")var vntkit = require("vnt-kit")var Tx= require("ethereumjs-tx")// 设置连接的节点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)}// 准备代码和abivar baseDir = "/src//vntchain/go-vnt/testnet/demo/contract/output/"var abiFile = baseDir+"NFTshop3.abi"var wasmabi = fs.readFileSync(abiFile)//将abi数据解析成json结构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);// 获取下一个nonce值var nonce = vnt.core.getTransactionCount(account_address);console.log("nonce : "+nonce);// 其中to字段为合约地址,data字段为合约调用的datavar 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);// 使用之前准备好的私钥,对交易签名tx.sign(new Buffer('账户私钥', "hex"));// 将交易数据进行序列化var serializedTx = tx.serialize();// 发送交易vnt.core.sendRawTransaction('0x' + serializedTx.toString('hex'),function(err, txHash) {if (err) {console.log("err happened: ", err)} else {// 打印交易的hashconsole.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}
接着就可以进入node进行模拟了,因为node就是模拟的前端,所以在node中只要打开调用文件,然后调用相关方法即可:
调用格式如下:(先输入node进入虚拟环境)
> var cs = require('./call_sample.js')> cs.getName()call_getName output : GenjiLemon'GenjiLemon'> cs.setName('lll')undefined
六、参考文献
这些是我的部分参考文档
VNT测试网以及相关指导https://hubscan.vnt.link/官方指导函数文档/vntchain/vnt.js/blob/master/doc/api-reference.md#returns-46指导文档2/vntchain/vnt-documentation/blob/master/api/vnt-json-rpc-api.md)/vntchain/vnt-documentation/blob/master/api/vnt-json-rpc-api.md一位不知名大佬的参考合约编写/search?l=C&q=vntchain&type=Repositories)/search?l=C&q=vntchain&type=Repositories以及还有CSDN的各位大佬的博客
总结
以上就是本次比赛我所有的所作所为的总结了,这篇博客也只能先草草结束了,因为最近欠的事情有点多,需要做的也很多,得花时间一件件去补,再加上我也好久没写博客(主要是因为懒,自从去年寒假集训之后就没写过了,鸽子王名不虚传,不过接下来还是会继续写下去,顺便记录一下我的大学学习和生活)本来还想把遇到的各种问题都写上去,但时间跨度真的太长了,实在是力不从心,只能想一点写一点,最后也只完成了这份大概的初稿,不过这是一次很难忘很难忘的经历,毕竟好几个周末加工作日的晚上我都泡在那里敲代码,属实是顶不住了,这是一次很好的锻炼机会,我也在这之中学到了很多,感谢学长学姐还有我的室友给我的帮助。
但是如你所见,我也还有很多很多不足的地方,还有很多的东西需要学,这个项目也还有很多的部分需要去完成,这篇博客到这就结束了,但是这个项目还没有结束,学习也还没有结束,继续加油!
ps:轻喷,我知道我真的很菜,要是有不足的地方请在下方指出,同时也欢迎大佬来指点我一下,或者有想一起学习的也可以在下方留言,那就这样,谢谢!!!!
如果觉得《《第十三届服创大赛A23项目-基于区块链的艺术品数字资产确权流通系统》的未完成版》对你有帮助,请点赞、收藏,并留下你的观点哦!