在Xuper链上部署Java语言智能合约和分析存证合约的实现逻辑

44次阅读

共计 4636 个字符,预计需要花费 12 分钟才能阅读完成。

前言

这篇文章咱们先简略的叙述下官网刚公布的最新版本中的 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 排版

正文完
 0