前言

这篇文章咱们先简略的叙述下官网刚公布的最新版本中的native部署java语言编写的智能合约的过程而后再说下存证合约的代码实现逻辑,下一篇文章咱们说下如何依据本人公司的业务逻辑定义合约外面的数据结构来实现智能合约

先简略说下对于文档拜访慢的问题

官网文档是 https://xuperchain.readthedoc..._documents/XuperModel.html

该文档是在国外部署的,所以国内拜访的话,如果本人所在的网络不太好的状况下,关上网页是很慢的,这种状况大家能够将相应版本的文档下载到本人的本地,这样的话 就不会受网速的影响了

下载地址:

https://readthedocs.org/proje...

抉择相应的版本即可

版本升级已反对java语言编写的智能合约

大略2020年7月13号左右的时候 官网更新了一版本 在master分支上 该版本已反对了java语言编写的智能合约

接下来咱们首先下拉下最新的代码、而后编译、运行下,这个过程咱之前发过的文章也曾经很具体的形容过了,这里就不再赘述了,感兴趣的敌人 能够看下这2篇文章

在百度超级链Xuper上部署智能合约并实现存证性能 和 对百度超级链Xuper应用过程中的进一步了解

native模式下java智能合约的部署

java智能合约是native部署的形式,所以首先须要批改下配置文件以开启native合约部署

`vim 每个节点门路/conf/xchain.yaml
# 治理native合约的配置
native:
enable: true`

启动命令

`nohup ./xchain &
这里没有加--vm ixvm 这个是wasm合约部署的形式`

因为这里批改了配置 所以须要先删除数据,再启动 我这是在本地环境搭建的,所以节点数据都不太重要,要是公司的数据,那么就不须要轻易的批改配置了

编译环境

编译Java sdk:Java版本不低于Java1.8版本

包管理器:maven,mvn版本3.6+

配置maven环境

`vim /etc/profile
export M2_HOME=/Users/mengfanxiao/Documents/third_software/maven/apache-maven-3.6.2
export PATH=$PATH:$M2_HOME/bin
source /etc/profile
mvn -v`

编译合约sdk

`cd xuperchain/core/contractsdk/java
mvn install -f pom.xml`

产出二进制文件target/java-contract-sdk-0.1.0.jar,并主动装置到mvn本地仓库下

编译native合约时,以contractsdk/java/example中的counter合约为例

`cd contractsdk/java/example/counter
mvn package -f pom.xml`

产出二进制文件target/counter-0.1.0-jar-with-dependencies.jar,用于合约部署

合约部署

./xchain-cli native deploy --account XC1111111111111111@xuper --fee 15587517 --runtime java xuperchain/data/javacontract/counter-0.1.0-jar-with-dependencies.jar --cname javacounter

合约调用

  • 命令行调用

./xchain-cli native invoke --method Increase -a '{"key":"test"}' javacounter --fee 10

  • 通过java sdk 发动合约交易

`@Test
public void invokeContract() throws Exception {
Map<String, byte[]> args = new HashMap<>();
args.put("key", "icexin".getBytes());
Transaction tx = client.invokeContract(account, "native", "javacounter", "increase", args);
System.out.println("invoke txid: " + tx.getTxid());
System.out.println("response: " + tx.getContractResponse().getBodyStr());
System.out.println("gas: " + tx.getGasUsed());
}`

留神这里肯定要是native模式

合约查问

  • 通过Java sdk 查问

`@Test
public void queryContractJava() throws Exception {
Map<String, byte[]> args = new HashMap<>();
args.put("key", "icexin".getBytes());
Transaction tx = client.queryContract(account, "native", "javacounter", "get", args);
System.out.println("response: " + tx.getContractResponse().getBodyStr());
System.out.println("gas: " + tx.getGasUsed());
}`

native模式下go语言编写的智能合约部署

还是以counter合约文件为例

`cd contractsdk/go/example/counter
go build counter.go`

部署合约文件

./xchain-cli native deploy --account XC1111111111111111@xuper -a '{"creator":"XC1111111111111111@xuper"}' --fee 15587517 --runtime go xuperchain/data/gocontract/counter --cname golangcounter

调用合约文件

  • 命令行调用

./xchain-cli native invoke --method Increase -a '{"key":"test"}' golangcounter --fee 10

  • Javasdk调用

`@Test
public void invokeContractG0() throws Exception {
Map<String, byte[]> args = new HashMap<>();
args.put("key", "icexin".getBytes());
Transaction tx = client.invokeContract(account, "native", "golangcounter", "increase", args);
System.out.println("invoke txid: " + tx.getTxid());
System.out.println("response: " + tx.getContractResponse().getBodyStr());
System.out.println("gas: " + tx.getGasUsed());
}`

查问合约文件

通过Javasdk查问

`@Test
public void queryContractGo() throws Exception {
Map<String, byte[]> args = new HashMap<>();
args.put("key", "icexin".getBytes());
Transaction tx = client.queryContract(account, "native", "golangcounter", "get", args);
System.out.println("response: " + tx.getContractResponse().getBodyStr());
System.out.println("gas: " + tx.getGasUsed());
}`

别离部署完了java和go语言写的counter合约之后 咱们其实就晓得了 流程都是截然不同的

可能呈现的异样信息

  • 如果报 contract type native not found 阐明没有开启native合约配置
  • 如果报 context deadline exceeded 阐明 你可能用的是旧版本的合约文件 所以须要从新编译下新版本的合约源码生成合约文件
    • *

下面简略形容了截止目前7月15号基于最新版本部署的过程以及通过native合约部署的形式别离部署和应用go和java2种语言编写的智能合约的过程,上面联合公司的业务来形容下存证智能合约的实现逻辑

存证智能合约目前版本还没有java语言编写的合约模版,大略2周之后才会有

上面咱剖析下go语言版本的存证合约的逻辑

先简略说下数据结构

`user对象的数据结构
{
"Owner":"xiaoming" , # 这个示意用户名
"UserFiles":{ # 这个是一个map汇合
"filehash":{ # map汇合的key是文件hash
"Timestamp":"" # 工夫戳
"Hashval":"" # []byte(filehash) 其实也是hash值
}
}
}`

合约部署的时候数据初始化

在合约部署的时候会调用Initialize办法

首先获取到部署命令中的owner参数示意用户名 而后调用链上的办法GetObject来查问该用户名对应的value

智能合约调用的链上的办法就2个 一个是PutObject 将key-value保留到链上

另外一个是GetObject 依据key获取对应的value

如果value为空的话 则初始化一个空的user对象 并转换成json字符串上链保留

合约上链交易的办法

这个办法首先依据owner(代表用户名称)去链上查问对应的value 依据下面的剖析 该value保留着一个用户对象,第一次调用的时候该用户对象是外面的属性都没有进行初始化呢 而后调用putFile办法

首先初始化一个UserFile对象 这外面保留了一条上链的信息

将该对象作为一个元素 保留到 user对象外面的userfiles这个map汇合中 key是filehash value是userFile

而后将用户对象转换成json字符串保留到链上

合约交易查问

通过用户名称到链上查问到了用户对象

依据filehash遍历该用户对象的userfiles这个map汇合 找到对应的userfile元素

截止到这里 是不是发现了 这个存证合约模版的逻辑其实很简略

总结下下面的逻辑

智能合约调用链上的2个办法

  • PutObject 将k-v上链保留
  • GetObject 通过k查问v

一个数据结构

  • 一个user对象 外面有一个map汇合 外面的元素是每次上链的数据 能够通过map的key来定位到那一条上链数据

问题发现

filehash反复

大家看过下面的代码有没有发现一个问题

圈红的中央是将单次上链数据userFile 放入map汇合中 ,key是filehash,如果2次上传的filehash雷同,那么就会把之前的filehash对应的value值给替换掉

然而呢 雷同的上链数据却返回不同的交易id,外部实现机制是怎么的和如果依据公司的业务来定义数据结构以实现智能合约等下一篇文章咱们再剖析下。

本文应用 mdnice 排版