《第十三届服创大赛A23项目-基于区块链的艺术品数字资产确权流通系统》的未完成版

文章目录



开始前

首先声明,这个比赛是由我室友,学长学姐以及本人共同参与完成(虽然这个项目还没完全做完来着,但好歹是终于交上去了)我只负责了其中的后端代码的一部分内容,而且由于一开始完全不懂的关系,基本上是属于走一步看一步学一步的过程,所以进度一度十分缓慢,并且之中有很多的部分也不能保证完全正确,只能说是暂时先用着,如果之后发现错误会及时更改,并且这个项目也在不断完善的过程中,等全部完成后会再发一次博客,这次的就当完成一部分交上去之后的一个小小的总结,记录一下我大学第一次参加的比赛项目过程,以及心路历程。
在此,感谢我的室友,还有学长学姐的帮助,才能让这个项目得以顺利进行
项目进行过程中所用到的所有资料链接我都会放在最后,而具体的代码我也会放在文章中(因为大部分都是环境的部署,以及未完成的关系,我的代码其实尤其的少,估计等全部完成后就会变多),其余的则打包上传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)
Python2
Docker
Go v1.10 (1.9+ ,version1.10 recommended)
Git
Node.js v8.11.2 or later

这个环境是真的折磨人,他对版本的要求很死板,前面的几个都问题不大,直接在Ubuntu的终端里面用install下载即可,注意下版本就行,把python的版本切成2就可用。
最为恶心的是后面的工具部分,首先是这个node.js,他要求的版本是8.11.2或者之后的,但还是建议下载8.11.2(别问,问就是别的版本各种报错不适配)将解压包解压然后安装即可(压缩过程就是普通的Ubuntu压缩操作,去搜一下就有),压缩包千万别选错了,我就是因为傻乎乎的选错了,在那调了半天bug,链接在此:
https://registry.npmmirror.com/binary.html?path=node/v8.11.2/
然后是go-vnt(gvnt),这个是用来搭建本地的私链用的(虽然我在后面其实并没有用到,因为种种原因我是直接跳过本地私链这部分,直接跳到官方的测试网上的,具体原因看到博客后面有,这里不做过多赘述)

Download下载方式如下:
git clone https://github.com/vntchain/go-vnt.git
Switch tree好像是切换版本,如果不切换的话会有报错:
git checkout v0.6.4-alpha.6
compille试运行(这里有可能会出现找不到gvnt目录的情况,建议先找到所在目录再运行,然后之后如果调用gvnt只需要加上目录即可,比如:./....../gvnt):
make gvnt
If failed , please install go v1.10 and retry.(可能有用的修改方法,我反正没试过)
link to your environment(连接网络)

bottle的下载倒是挺简单,没有报错直接下载就行了

sudo docker pull vntchain/bottle:0.6.1
sudo docker image ls
输入上面的代码会得到以下这个反馈
REPOSITORY        TAG       IMAGE ID       CREATED       SIZE  
vntchain/bottle   0.6.1     647ad4101419   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 https://github.com/vntchain/vnt.js.git
npm install --save https://github.com/vntchain/vnt-kit.js.git
npm install --save [email protected]
npm install --save ethereumjs-account`

3.编写合约的环境

智能合约的编写只需要vntlib.h这个官方库就好,因为有些方法的定义都在这个里面

wget https://github.com/vntchain/vnt-documentation/blob/master/smart-contract/vntlib.h
但是上面这个方法我是行不通,你们可以去试试,我下载下来之后全都是web前端的格式,完全用不了,我是直接去官方网站把他的方法给copy到文档里面去使用的
链接在这:https://github.com/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 node4
sudo ./build/bin/gvnt account new --datadir node5

会得到返回值如下,记下地址,后面会用到

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}

创建连接

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 

接着输入如下指令激活节点

sudo rm -rf node4/gvnt
sudo rm -rf node5/gvnt

然后就饿可以启动节点

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

之后解锁节点


> personal.unlockAccount(core.coinbase, "", 3153600000)
true
> bp.start()
> personal.unlockAccount(core.coinbase, "", 3153600000)
true
> bp.start()

到此,个人的私链便搭建完毕了,连接到私链当中的节点只有两个,也可以增加连接的节点使得私链更加完善。

三、编写并且编译智能合约

智能合约的编写需要使用C语言进行编写,同时记得将vntlib.h的头文件下载下来,文件的下载连接为
https://github.com/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();
    
}

//UNMUTABLE
MUTABLE
string 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);
}

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));
}*/

合约之后还要进行编译,运用到的是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/Sample.compress"
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 {
          // 打印交易的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)
          })
      }
    });
}

// 调用部署函数
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)
}


// 准备代码和abi
var baseDir = "/src/github.com/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字段为合约调用的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);
    // 使用之前准备好的私钥,对交易签名
    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 {
          // 打印交易的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
}

接着就可以进入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/
官方指导函数文档https://github.com/vntchain/vnt.js/blob/master/doc/api-reference.md#returns-46
指导文档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的各位大佬的博客

总结

以上就是本次比赛我所有的所作所为的总结了,这篇博客也只能先草草结束了,因为最近欠的事情有点多,需要做的也很多,得花时间一件件去补,再加上我也好久没写博客(主要是因为懒,自从去年寒假集训之后就没写过了,鸽子王名不虚传,不过接下来还是会继续写下去,顺便记录一下我的大学学习和生活)本来还想把遇到的各种问题都写上去,但时间跨度真的太长了,实在是力不从心,只能想一点写一点,最后也只完成了这份大概的初稿,不过这是一次很难忘很难忘的经历,毕竟好几个周末加工作日的晚上我都泡在那里敲代码,属实是顶不住了,这是一次很好的锻炼机会,我也在这之中学到了很多,感谢学长学姐还有我的室友给我的帮助。
但是如你所见,我也还有很多很多不足的地方,还有很多的东西需要学,这个项目也还有很多的部分需要去完成,这篇博客到这就结束了,但是这个项目还没有结束,学习也还没有结束,继续加油!
ps:轻喷,我知道我真的很菜,要是有不足的地方请在下方指出,同时也欢迎大佬来指点我一下,或者有想一起学习的也可以在下方留言,那就这样,谢谢!!!!

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
THE END
分享
二维码
< <上一篇
下一篇>>