@@ -42,3 +42,9 @@ contract-libs/coreLib/sdk-base-0.6.0-SNAPSHOT.jar | |||
contract-libs/coreLib/utils-common-1.6.1-SNAPSHOT.jar | |||
source/tools/tools-initializer/bftsmart.config | |||
test/test-integration/runtime/ | |||
deploy/docker/docker-demo/docker/zip/docker-sdk-1.4.0.RELEASE.jar | |||
deploy/docker/docker-demo/docker/zip/jdchain-gateway-1.4.0.RELEASE.zip | |||
deploy/docker/docker-demo/docker/zip/jdchain-peer-1.4.0.RELEASE.zip | |||
deploy/docker/docker-demo/src/main/docker/zip/docker-sdk-1.4.0.RELEASE.jar | |||
deploy/docker/docker-demo/src/main/docker/zip/jdchain-gateway-1.4.0.RELEASE.zip | |||
deploy/docker/docker-demo/src/main/docker/zip/jdchain-peer-1.4.0.RELEASE.zip |
@@ -16,6 +16,7 @@ | |||
[submodule "test"] | |||
path = test | |||
url = git@github.com:blockchain-jd-com/jdchain-test.git | |||
[submodule "kvdb"] | |||
path = kvdb | |||
[submodule "libs/kvdb"] | |||
path = libs/kvdb | |||
url = git@github.com:blockchain-jd-com/jdchain-kvdb.git | |||
@@ -1,4 +1,3 @@ | |||
#调用当前脚本目录下 env.sh 脚本,设置环境变量,处理当前传入参数; | |||
if [ ! $ENV_SHELL ] | |||
then | |||
@@ -103,6 +102,10 @@ do | |||
cd $BASE_DIR | |||
done | |||
#首次执行同步更新子模块的远程仓库 origin 的地址会将主项目地址更改,以下操作确保主项目远程仓库地址正确 | |||
git config remote.origin.url $REMOTE_ORIGIN_URL | |||
git config remote.origin.pushurl $REMOTE_ORIGIN_URL | |||
#检查是否要跳过子模块更新环节; | |||
if [ $SKIP_SUBMODULES_UPDATE == 1 ] | |||
then | |||
@@ -1 +1 @@ | |||
Subproject commit ec842b88f4ea19ffa8f9a00f31317e5e4dc5218b | |||
Subproject commit 21a80d9ecb7567af775c35cdb68290fe1de1e413 |
@@ -5,7 +5,7 @@ | |||
<parent> | |||
<groupId>com.jd.blockchain</groupId> | |||
<artifactId>deploy-root</artifactId> | |||
<version>1.3.0.RELEASE</version> | |||
<version>1.4.0.RELEASE</version> | |||
</parent> | |||
<artifactId>deploy-gateway</artifactId> | |||
@@ -15,45 +15,9 @@ public class GatewayBooter { | |||
public static void main(String[] args) { | |||
try { | |||
writePID(); | |||
GatewayServerBooter.main(args); | |||
} catch (Exception e) { | |||
System.err.println("Error!!! --[" + e.getClass().getName() + "] " + e.getMessage()); | |||
} | |||
} | |||
private static final void writePID() throws Exception { | |||
URL url = GatewayBooter.class.getProtectionDomain().getCodeSource().getLocation(); | |||
String currPath = java.net.URLDecoder.decode(url.getPath(), "UTF-8"); | |||
if (currPath.contains("!/")) { | |||
currPath = currPath.substring(5, currPath.indexOf("!/")); | |||
} | |||
if (currPath.endsWith(".jar")) { | |||
currPath = currPath.substring(0, currPath.lastIndexOf("/") + 1); | |||
} | |||
System.out.printf("currentPath = %s \r\n", currPath); | |||
File file = new File(currPath); | |||
String homeDir = file.getParent(); | |||
String pidFilePath = homeDir + File.separator + "bin" + File.separator + "PID.log"; | |||
File pidFile = new File(pidFilePath); | |||
if (!pidFile.exists()) { | |||
File dir = pidFile.getParentFile(); | |||
if (!dir.exists()) { | |||
dir.mkdirs(); | |||
} | |||
pidFile.createNewFile(); | |||
} | |||
String name = ManagementFactory.getRuntimeMXBean().getName(); | |||
String pid = name.split("@")[0]; | |||
List<String> bootInfos = new ArrayList<>(); | |||
bootInfos.add("JDChain gateway starts to boot ......\r\n"); | |||
bootInfos.add(String.format("GW_BOOT_TIME = [%s] \r\n", new Date().toString())); | |||
bootInfos.add(String.format("GW_BOOT_PID = [%s] \r\n", pid)); | |||
try (FileOutputStream outputStream = new FileOutputStream(pidFile)) { | |||
for (String bootInfo : bootInfos) { | |||
outputStream.write(bootInfo.getBytes(StandardCharsets.UTF_8)); | |||
} | |||
outputStream.flush(); | |||
} | |||
} | |||
} |
@@ -5,20 +5,12 @@ http.port=8080 | |||
#网关的HTTP服务上下文路径,可选; | |||
#http.context-path= | |||
#对端Peer节点的数量 | |||
peer.size=2 | |||
#共识节点的服务地址(与该网关节点连接的Peer节点的IP地址); | |||
peer.0.host=127.0.0.1 | |||
peer.host=127.0.0.1 | |||
#共识节点的服务端口(与该网关节点连接的Peer节点的端口,即在Peer节点的peer-startup.sh中定义的端口); | |||
peer.0.port=7080 | |||
peer.port=7080 | |||
#共识节点的服务是否启用安全证书; | |||
peer.0.secure=false | |||
#共识节点的服务地址(与该网关节点连接的Peer节点的IP地址); | |||
peer.1.host=127.0.0.1 | |||
#共识节点的服务端口(与该网关节点连接的Peer节点的端口,即在Peer节点的peer-startup.sh中定义的端口); | |||
peer.1.port=7081 | |||
#共识节点的服务是否启用安全证书; | |||
peer.1.secure=false | |||
peer.secure=false | |||
#共识节点的服务提供解析器 | |||
#BftSmart共识Provider:com.jd.blockchain.consensus.bftsmart.BftsmartConsensusProvider | |||
@@ -0,0 +1,39 @@ | |||
<?xml version="1.0" encoding="UTF-8"?> | |||
<configuration status="WARN" monitorInterval="60"> | |||
<appenders> | |||
<console name="Console" target="SYSTEM_OUT"> | |||
<ThresholdFilter level="fatal" onMatch="ACCEPT" onMismatch="DENY"/> | |||
<PatternLayout pattern="%d{HH:mm:ss.SSS} %-5level %class{36} %L %M - %msg%xEx%n"/> | |||
</console> | |||
<RollingFile name="GWRolling" fileName="${sys:jdchain.log}/gw.log" | |||
filePattern="${sys:jdchain.log}/$${date:yyyy-MM}/gw-%d{yyyy-MM-dd}-%i.log"> | |||
<ThresholdFilter level="info" onMatch="ACCEPT" onMismatch="DENY"/> | |||
<PatternLayout pattern="[%date{yyyy-MM-dd HH:mm:ss:SSS}] [%thread] [%p] - %l - %m%n"/> | |||
<Policies> | |||
<TimeBasedTriggeringPolicy/> | |||
<SizeBasedTriggeringPolicy size="100 MB"/> | |||
</Policies> | |||
<DefaultRolloverStrategy max="100"/> | |||
</RollingFile> | |||
<RollingFile name="GWRollingError" fileName="${sys:jdchain.log}/gw.error.log" | |||
filePattern="${sys:jdchain.log}/$${date:yyyy-MM}/gw.error-%d{yyyy-MM-dd}-%i.log"> | |||
<ThresholdFilter level="error" onMatch="ACCEPT" onMismatch="DENY"/> | |||
<PatternLayout pattern="[%date{yyyy-MM-dd HH:mm:ss:SSS}] [%thread] [%p] - %l - %m%n"/> | |||
<Policies> | |||
<TimeBasedTriggeringPolicy/> | |||
<SizeBasedTriggeringPolicy size="100 MB"/> | |||
</Policies> | |||
</RollingFile> | |||
</appenders> | |||
<loggers> | |||
<logger name="org.springframework" level="error"></logger> | |||
<logger name="bftsmart" level="error"></logger> | |||
<!--修改此处,以变更日志等级--> | |||
<root level="info"> | |||
<appender-ref ref="Console"/> | |||
<appender-ref ref="GWRolling"/> | |||
<appender-ref ref="GWRollingError"/> | |||
</root> | |||
</loggers> | |||
</configuration> |
@@ -3,23 +3,23 @@ | |||
<dependency> | |||
<groupId>com.jd.blockchain</groupId> | |||
<artifactId>sdk-client</artifactId> | |||
<version>1.3.0.RELEASE</version> | |||
<version>1.4.0.RELEASE</version> | |||
</dependency> | |||
<dependency> | |||
<groupId>com.jd.blockchain</groupId> | |||
<artifactId>contract-starter</artifactId> | |||
<version>1.3.0.RELEASE</version> | |||
<version>1.4.0.RELEASE</version> | |||
</dependency> | |||
<dependency> | |||
<groupId>com.jd.blockchain</groupId> | |||
<artifactId>crypto-classic</artifactId> | |||
<version>1.3.0.RELEASE</version> | |||
<version>1.4.0.RELEASE</version> | |||
</dependency> | |||
<dependency> | |||
<groupId>com.jd.blockchain</groupId> | |||
<artifactId>crypto-sm</artifactId> | |||
<version>1.3.0.RELEASE</version> | |||
<version>1.4.0.RELEASE</version> | |||
</dependency> | |||
``` | |||
# 2. 数据快速上链 | |||
@@ -1,32 +1,65 @@ | |||
#!/bin/bash | |||
#启动Home路径 | |||
BOOT_HOME=$(cd `dirname $0`;cd ../; pwd) | |||
#进程启动后PID.log所在路径 | |||
PID_LOG=$BOOT_HOME/bin/PID.log | |||
#从启动文件中读取PID | |||
if [ -f "$PID_LOG" ]; then | |||
# File exist | |||
echo "Read PID From File:[$PID_LOG] ..." | |||
PID_LINE=`sed -n '$p' $PID_LOG` | |||
echo "Last Gateway Boot Info = $PID_LINE ..." | |||
if [[ $PID_LINE == *GW_BOOT_PID* ]]; then | |||
LOG_PID=$(echo $PID_LINE | cut -d "=" -f 2 | cut -d "[" -f 2 | cut -d "]" -f 1) | |||
echo "Last Gateway Boot PID = $LOG_PID ..." | |||
PID=`ps -ef | grep deploy-gateway- | grep $LOG_PID | grep -v grep | awk '{print $2}'` | |||
#定义程序启动的Jar包前缀 | |||
APP_JAR_PREFIX=deploy-gateway- | |||
#获取当前的根目录 | |||
APP_HOME=$(cd `dirname $0`;cd ../; pwd) | |||
#System路径 | |||
APP_LIB_PATH=$APP_HOME/lib | |||
#获取Peer节点的启动Jar包 | |||
APP_JAR=$(ls $APP_LIB_PATH | grep $APP_JAR_PREFIX) | |||
#APP_JAR的具体路径 | |||
APP_JAR_PATH=$APP_LIB_PATH/$APP_JAR | |||
################################### | |||
#(函数)判断程序是否已启动 | |||
# | |||
#说明: | |||
#使用awk,分割出pid ($1部分),及Java程序名称($2部分) | |||
################################### | |||
#初始化psid变量(全局) | |||
psid=0 | |||
checkpid() { | |||
psid=`ps -ef | grep $APP_JAR_PATH | grep -v grep | awk '{print $2}'` | |||
} | |||
################################### | |||
#(函数)停止程序 | |||
# | |||
#说明: | |||
#1. 首先调用checkpid函数,刷新$psid全局变量 | |||
#2. 如果程序已经启动($psid不等于0),则开始执行停止,否则,提示程序未运行 | |||
#3. 使用kill -9 pid命令进行强制杀死进程 | |||
#4. 执行kill命令行紧接其后,马上查看上一句命令的返回值: $? | |||
#5. 如果步骤4的结果$?等于0,则打印[OK],否则打印[Failed] | |||
#注意:echo -n 表示打印字符后,不换行 | |||
#注意: 在shell编程中,"$?" 表示上一句命令或者一个函数的返回值 | |||
################################### | |||
stop() { | |||
checkpid | |||
if [[ $psid -ne 0 ]]; then | |||
echo "Stopping Gateway ......(pid=$psid) " | |||
JAVA_CMD="kill -9 $psid" | |||
sleep 1 | |||
$JAVA_CMD | |||
if [[ $? -eq 0 ]]; then | |||
echo "[OK]" | |||
else | |||
echo "[Failed]" | |||
fi | |||
#启动文件不存在则直接通过PS进行过滤 | |||
else | |||
PID=`ps -ef | grep $BOOT_HOME/lib/deploy-gateway- | grep -v grep | awk '{print $2}'` | |||
fi | |||
#通过Kill命令将进程杀死 | |||
if [ -z "$PID" ]; then | |||
echo "Unable to find gateway PID. stop aborted." | |||
else | |||
echo "Start to kill PID = $PID ..." | |||
kill -9 $PID | |||
echo "Gateway has been stopped ..." | |||
fi | |||
else | |||
echo "================================" | |||
echo "WARN: Gateway is not running" | |||
echo "================================" | |||
fi | |||
} | |||
#真正停止的处理流程 | |||
stop |
@@ -1,19 +1,103 @@ | |||
#!/bin/bash | |||
HOME=$(cd `dirname $0`;cd ../; pwd) | |||
GATEWAY=$(ls $HOME/lib | grep deploy-gateway-) | |||
PROC_INFO=$HOME/lib/$GATEWAY" -c "$HOME/config/gateway.conf | |||
#echo $PROC_INFO | |||
#get PID | |||
PID=`ps -ef | grep "$PROC_INFO" | grep -v grep | awk '{print $2}'` | |||
#echo $PID | |||
if [[ ! -z $PID ]] | |||
then | |||
echo "process already exists,please check... If necessary, you should kill the process first." | |||
exit | |||
#设置Java命令 | |||
JAVA_BIN=java | |||
#定义程序启动的Jar包前缀 | |||
APP_JAR_PREFIX=deploy-gateway- | |||
#检查Java环境变量 | |||
if [ ! -n "$JAVA_HOME" ]; then | |||
echo "UnFound environment variable[JAVA_HOME], will use command[java]..." | |||
else | |||
JAVA_BIN=$JAVA_HOME/bin/java | |||
fi | |||
if [ ! -n "$GATEWAY" ]; then | |||
echo "GateWay Is Null !!!" | |||
#获取当前的根目录 | |||
APP_HOME=$(cd `dirname $0`;cd ../; pwd) | |||
#Lib目录 | |||
APP_LIB_PATH=$APP_HOME/lib | |||
#nohup输出日志路径 | |||
LOG_OUT=$APP_HOME/bin/gw.out | |||
#获取Peer节点的启动Jar包 | |||
APP_JAR=$(ls $APP_LIB_PATH | grep $APP_JAR_PREFIX) | |||
#Config配置路径 | |||
CONFIG_PATH=$APP_HOME/config | |||
#gateway.conf完整路径 | |||
GATEWAY_CONFIG=$CONFIG_PATH/gateway.conf | |||
#定义程序启动的参数 | |||
JAVA_OPTS="-jar -server -Xms1024m -Xmx1024m -Djdchain.log=$APP_HOME/logs -Dlogging.config=file:$APP_HOME/config/log4j2-gw.xml" | |||
#APP具体相关命令 | |||
APP_CMD=$APP_LIB_PATH/$APP_JAR" -c "$GATEWAY_CONFIG | |||
#APP_JAR的具体路径 | |||
APP_JAR_PATH=$APP_LIB_PATH/$APP_JAR | |||
#JAVA_CMD具体命令 | |||
JAVA_CMD="$JAVA_BIN $JAVA_OPTS $APP_CMD" | |||
################################### | |||
#(函数)判断程序是否已启动 | |||
# | |||
#说明: | |||
#使用awk,分割出pid ($1部分),及Java程序名称($2部分) | |||
################################### | |||
#初始化psid变量(全局) | |||
psid=0 | |||
checkpid() { | |||
javaps=`ps -ef | grep $APP_JAR_PATH | grep -v grep | awk '{print $2}'` | |||
if [[ -n "$javaps" ]]; then | |||
psid=$javaps | |||
else | |||
psid=0 | |||
fi | |||
} | |||
################################### | |||
#(函数)打印系统环境参数 | |||
################################### | |||
info() { | |||
echo "System Information:" | |||
echo "****************************" | |||
echo `uname -a` | |||
echo | |||
echo `$JAVA_BIN -version` | |||
echo | |||
echo "APP_HOME=$APP_HOME" | |||
echo "APP_JAR=$APP_JAR" | |||
echo "CONFIG_PATH=$CONFIG_PATH" | |||
echo "APP_JAR_PATH=$APP_JAR_PATH" | |||
echo | |||
echo "JAVA_CMD=$JAVA_CMD" | |||
echo "****************************" | |||
} | |||
#真正启动的处理流程 | |||
checkpid | |||
if [[ $psid -ne 0 ]]; then | |||
echo "================================" | |||
echo "warn: Gateway already started! (pid=$psid)" | |||
echo "================================" | |||
else | |||
nohup java -jar -server -Djdchain.log=$HOME $PROC_INFO $* >$HOME/bin/gw.out 2>&1 & | |||
echo "Starting Gateway ......" | |||
nohup $JAVA_BIN $JAVA_OPTS $APP_CMD $* >$LOG_OUT 2>&1 & | |||
JAVA_CMD="$JAVA_BIN $JAVA_OPTS $APP_CMD $*" | |||
sleep 1 | |||
checkpid | |||
if [[ $psid -ne 0 ]]; then | |||
echo "(pid=$psid) [OK]" | |||
info | |||
else | |||
echo "[Failed]" | |||
fi | |||
fi |
@@ -1,99 +0,0 @@ | |||
<?xml version="1.0" encoding="UTF-8"?> | |||
<project xmlns="http://maven.apache.org/POM/4.0.0" | |||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | |||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> | |||
<parent> | |||
<artifactId>deploy-root</artifactId> | |||
<groupId>com.jd.blockchain</groupId> | |||
<version>1.3.0.RELEASE</version> | |||
</parent> | |||
<modelVersion>4.0.0</modelVersion> | |||
<artifactId>deploy-kvdb</artifactId> | |||
<version>1.0.1.RELEASE</version> | |||
<dependencies> | |||
<dependency> | |||
<groupId>com.jd.blockchain</groupId> | |||
<artifactId>kvdb-protocol</artifactId> | |||
<version>${kvdb.version}</version> | |||
</dependency> | |||
<dependency> | |||
<groupId>com.jd.blockchain</groupId> | |||
<artifactId>kvdb-engine</artifactId> | |||
<version>${kvdb.version}</version> | |||
</dependency> | |||
<dependency> | |||
<groupId>com.jd.blockchain</groupId> | |||
<artifactId>kvdb-server</artifactId> | |||
<version>${kvdb.version}</version> | |||
</dependency> | |||
<dependency> | |||
<groupId>com.jd.blockchain</groupId> | |||
<artifactId>kvdb-cli</artifactId> | |||
<version>${kvdb.version}</version> | |||
</dependency> | |||
<dependency> | |||
<groupId>com.jd.blockchain</groupId> | |||
<artifactId>kvdb-benchmark</artifactId> | |||
<version>${kvdb.version}</version> | |||
</dependency> | |||
<dependency> | |||
<groupId>com.jd.blockchain</groupId> | |||
<artifactId>kvdb-client</artifactId> | |||
<version>${kvdb.version}</version> | |||
</dependency> | |||
</dependencies> | |||
<build> | |||
<plugins> | |||
<plugin> | |||
<groupId>org.apache.maven.plugins</groupId> | |||
<artifactId>maven-assembly-plugin</artifactId> | |||
<executions> | |||
<execution> | |||
<id>make-assembly</id> | |||
<phase>package</phase> | |||
<goals> | |||
<goal>single</goal> | |||
</goals> | |||
<configuration> | |||
<finalName>kvdb</finalName> | |||
<descriptors> | |||
<descriptor>src/main/resources/assembly.xml</descriptor> | |||
</descriptors> | |||
</configuration> | |||
</execution> | |||
</executions> | |||
</plugin> | |||
<!-- 生成SHA-256校验文件 --> | |||
<plugin> | |||
<groupId>net.nicoulaj.maven.plugins</groupId> | |||
<artifactId>checksum-maven-plugin</artifactId> | |||
<version>1.8</version> | |||
<executions> | |||
<execution> | |||
<goals> | |||
<goal>artifacts</goal> | |||
</goals> | |||
</execution> | |||
</executions> | |||
<configuration> | |||
<algorithms> | |||
<algorithm>SHA-256</algorithm> <!--采用SHA-256算法,还支持其他算法--> | |||
</algorithms> | |||
<file>${project.basedir}/target/deployment-kvdb-${project.version}.zip</file><!--给zip文件进行加密--> | |||
<xmlSummary>true</xmlSummary><!--生成XML格式的md5文件--> | |||
<xmlSummaryFile>${project.basedir}/target/SHA-256.xml</xmlSummaryFile> | |||
</configuration> | |||
</plugin> | |||
</plugins> | |||
</build> | |||
</project> |
@@ -1,54 +0,0 @@ | |||
<?xml version='1.0' encoding='UTF-8'?> | |||
<assembly xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0" | |||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | |||
xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0 | |||
http://maven.apache.org/xsd/assembly-1.1.0.xsd"> | |||
<id>${project.version}</id> | |||
<formats> | |||
<format>zip</format> | |||
</formats> | |||
<includeBaseDirectory>false</includeBaseDirectory> | |||
<fileSets> | |||
<fileSet> | |||
<directory>src/main/resources/script</directory> | |||
<outputDirectory>bin</outputDirectory> | |||
<lineEnding>unix</lineEnding> | |||
</fileSet> | |||
<fileSet> | |||
<directory>src/main/resources/config</directory> | |||
<outputDirectory>config</outputDirectory> | |||
<lineEnding>unix</lineEnding> | |||
</fileSet> | |||
<fileSet> | |||
<directory>src/main/resources/system</directory> | |||
<outputDirectory>system</outputDirectory> | |||
<lineEnding>unix</lineEnding> | |||
</fileSet> | |||
</fileSets> | |||
<dependencySets> | |||
<dependencySet> | |||
<unpack>false</unpack> | |||
<useProjectArtifact>true</useProjectArtifact> | |||
<outputDirectory>libs</outputDirectory> | |||
</dependencySet> | |||
</dependencySets> | |||
<moduleSets> | |||
<moduleSet> | |||
<useAllReactorProjects>true</useAllReactorProjects> | |||
<includes> | |||
<include>com.jd.blockchain:kvdb-engine</include> | |||
<include>com.jd.blockchain:kvdb-benchmark</include> | |||
<include>com.jd.blockchain:kvdb-client</include> | |||
<include>com.jd.blockchain:kvdb-protocol</include> | |||
<include>com.jd.blockchain:kvdb-cli</include> | |||
<include>com.jd.blockchain:kvdb-server</include> | |||
</includes> | |||
<binaries> | |||
<outputDirectory>libs</outputDirectory> | |||
<unpack>false</unpack> | |||
</binaries> | |||
</moduleSet> | |||
</moduleSets> | |||
</assembly> |
@@ -1,11 +0,0 @@ | |||
# 数据库集群的分片数,每一个分片都赋予唯一的编号,分片编号最小为 0,所有分片的编号必须连续递增 | |||
#cluster.test1.partitions=2 | |||
# 数据库集群 ‘<name>’ 的第 1 个分片的数据库实例地址(URL格式); | |||
#cluster.test1.0=kvdb://localhost:7078/test1 | |||
# 数据库集群 ‘<name>’ 的第 2 个分片的数据库实例地址(URL格式); | |||
#cluster.test1.1=kvdb://localhost:7079/test1 | |||
# 指定多个不同的集群 | |||
#cluster.test2.partitions=2 | |||
#cluster.test2.0=kvdb://localhost:7078/test2 | |||
#cluster.test2.1=kvdb://localhost:7079/test2 |
@@ -1,15 +0,0 @@ | |||
# 数据库服务的本机监听地址; | |||
server.host=0.0.0.0 | |||
# 数据库服务的本机监听端口; | |||
server.port=7078 | |||
# 管理控制台的端口; | |||
# 注:管理控制台总是绑定到环回地址 127.0.0.1,只允许本机访问; | |||
manager.port=7060 | |||
# 数据库实例默认的根目录 | |||
dbs.rootdir=../dbs | |||
# 数据库实例默认的本地分区数 | |||
dbs.partitions=4 |
@@ -1,12 +0,0 @@ | |||
#!/bin/bash | |||
HOME=$(cd `dirname $0`;cd ../; pwd) | |||
KVDB=$(ls $HOME/libs | grep kvdb-benchmark) | |||
JVM_SET="-Xmx2g -Xms2g" | |||
LOG_SET="-Dlogging.path="$HOME/logs" -Dlogging.level=error" | |||
PROC_INFO=$HOME/libs/$KVDB | |||
if [ ! -n "$KVDB" ]; then | |||
echo "Can not find kvdb-benchmark !!!" | |||
else | |||
java -jar $LOG_SET $JVM_SET $PROC_INFO $* | |||
fi |
@@ -1,12 +0,0 @@ | |||
#!/bin/bash | |||
HOME=$(cd `dirname $0`;cd ../; pwd) | |||
KVDB=$(ls $HOME/libs | grep kvdb-cli) | |||
JVM_SET="-Xmx2g -Xms2g" | |||
LOG_SET="-Dlogging.path="$HOME/logs" -Dlogging.level.root=error" | |||
PROC_INFO=$HOME/libs/$KVDB | |||
if [ ! -n "$KVDB" ]; then | |||
echo "Can not find kvdb-cli !!!" | |||
else | |||
java -jar $LOG_SET $JVM_SET $PROC_INFO $* | |||
fi |
@@ -1,23 +0,0 @@ | |||
#!/bin/bash | |||
HOME=$(cd `dirname $0`;cd ../; pwd) | |||
KVDB=$(ls $HOME/libs | grep kvdb-server) | |||
JVM_SET="-Xmx2g -Xms2g" | |||
PROC_INFO=$HOME/libs/$KVDB" -home "$HOME | |||
LOG_SET="-Dlogging.path="$HOME/logs" -Dlogging.level=error" | |||
#echo $PROC_INFO | |||
#get PID | |||
PID=`ps -ef | grep "$PROC_INFO" | grep -v grep | awk '{print $2}'` | |||
#echo $PID | |||
if [[ ! -z $PID ]] | |||
then | |||
echo "process already exists,please check... If necessary, you should kill the process first." | |||
exit | |||
fi | |||
if [ ! -n "$KVDB" ]; then | |||
echo "Can not find kvdb-server !!!" | |||
else | |||
nohup java -jar $LOG_SET $JVM_SET $PROC_INFO $* >/dev/null 2>&1 & | |||
echo $! > $HOME/system/pid | |||
fi |
@@ -1,27 +0,0 @@ | |||
#!/bin/bash | |||
#启动Home路径 | |||
HOME=$(cd `dirname $0`;cd ../; pwd) | |||
#进程启动后PID.log所在路径 | |||
PID_LOG=$HOME/system/pid | |||
#从启动文件中读取PID | |||
if [ -f "$PID_LOG" ]; then | |||
# File exist | |||
echo "Read PID From File:[$PID_LOG] ..." | |||
PID=`sed -n '$p' $PID_LOG` | |||
#启动文件不存在则直接通过PS进行过滤 | |||
else | |||
PID=`ps -ef | grep $HOME/libs/kvdb-server | grep -v grep | awk '{print $2}'` | |||
fi | |||
#通过Kill命令将进程杀死 | |||
if [ -z "$PID" ]; then | |||
echo "Unable to find kvdb PID. stop aborted." | |||
else | |||
echo "Start to kill PID = $PID ..." | |||
kill -9 $PID | |||
echo "kvdb has been stopped ..." | |||
echo "" > $PID_LOG | |||
fi |
@@ -1,2 +0,0 @@ | |||
#通过配置enable为true可以在kvdb-server启动时创建或加载指定数据库 | |||
#db.test1.enable=true |
@@ -5,7 +5,7 @@ | |||
<parent> | |||
<groupId>com.jd.blockchain</groupId> | |||
<artifactId>deploy-root</artifactId> | |||
<version>1.3.0.RELEASE</version> | |||
<version>1.4.0.RELEASE</version> | |||
</parent> | |||
<artifactId>deploy-peer</artifactId> | |||
@@ -58,6 +58,24 @@ | |||
<version>${core.version}</version> | |||
</dependency> | |||
<dependency> | |||
<groupId>com.jd.blockchain</groupId> | |||
<artifactId>tools-regparti-booter</artifactId> | |||
<version>${core.version}</version> | |||
</dependency> | |||
<dependency> | |||
<groupId>com.jd.blockchain</groupId> | |||
<artifactId>tools-activeparti-booter</artifactId> | |||
<version>${core.version}</version> | |||
</dependency> | |||
<dependency> | |||
<groupId>com.jd.blockchain</groupId> | |||
<artifactId>tools-deactiveparti-booter</artifactId> | |||
<version>${core.version}</version> | |||
</dependency> | |||
</dependencies> | |||
<build> | |||
@@ -33,12 +33,8 @@ public class PeerBooter { | |||
public static void main(String[] args) { | |||
try { | |||
HomeContext homeContext = HomeBooter.createHomeContext(args); | |||
startPeer(homeContext); | |||
writePID(homeContext.getHomeDir()); | |||
} catch (Exception e) { | |||
System.err.println("Error!!! --[" + e.getClass().getName() + "] " + e.getMessage()); | |||
} | |||
@@ -56,24 +52,4 @@ public class PeerBooter { | |||
SYSTEM_MAIN_CLASS, home.getSystemClassLoader(), home.getStartingArgs() }; | |||
modularFactoryMethod.invoke(null, systemStartingArgs); | |||
} | |||
private static final void writePID(String homeDir) throws IOException { | |||
String pidFilePath = homeDir + File.separator + "bin" + File.separator + "PID.log"; | |||
File pidFile = new File(pidFilePath); | |||
if (!pidFile.exists()) { | |||
pidFile.createNewFile(); | |||
} | |||
String name = ManagementFactory.getRuntimeMXBean().getName(); | |||
String pid = name.split("@")[0]; | |||
List<String> bootInfos = new ArrayList<>(); | |||
bootInfos.add("JDChain peer node starts to boot ......\r\n"); | |||
bootInfos.add(String.format("PEER_BOOT_TIME = [%s] \r\n", new Date().toString())); | |||
bootInfos.add(String.format("PEER_BOOT_PID = [%s] \r\n", pid)); | |||
try (FileOutputStream outputStream = new FileOutputStream(pidFile)) { | |||
for (String bootInfo : bootInfos) { | |||
outputStream.write(bootInfo.getBytes(StandardCharsets.UTF_8)); | |||
} | |||
outputStream.flush(); | |||
} | |||
} | |||
} |
@@ -55,7 +55,7 @@ system.server.3.network.secure=false | |||
#system.authentication.hmacAlgorithm = HmacSHA1 | |||
#Specify if the communication system should use a thread to send data (true or false) | |||
system.communication.useSenderThread = true | |||
#system.communication.useSenderThread = true //unused property; | |||
#Force all processes to use the same public/private keys pair and secret key. This is useful when deploying experiments | |||
#and benchmarks, but must not be used in production systems. | |||
@@ -74,6 +74,8 @@ system.servers.f = 1 | |||
#Timeout to asking for a client request | |||
system.totalordermulticast.timeout = 60000 | |||
#Allowable time tolerance range(millisecond) | |||
system.totalordermulticast.timeTolerance = 3000000 | |||
#Maximum batch size (in number of messages) | |||
system.totalordermulticast.maxbatchsize = 2000 | |||
@@ -92,6 +94,12 @@ system.communication.inQueueSize = 500000 | |||
# Quantity of messages that can be stored in the send queue of each replica | |||
system.communication.outQueueSize = 500000 | |||
#The time interval for retrying to send message after connection failure. In milliseconds; | |||
system.communication.send.retryInterval=2000 | |||
#The number of retries to send message after connection failure. | |||
system.communication.send.retryCount=100 | |||
#Set to 1 if SMaRt should use signatures, set to 0 if otherwise | |||
system.communication.useSignatures = 0 | |||
@@ -126,7 +134,7 @@ system.totalordermulticast.timeout_highMark = 200 | |||
system.totalordermulticast.log = true | |||
system.totalordermulticast.log_parallel = false | |||
system.totalordermulticast.log_to_disk = false | |||
system.totalordermulticast.log_to_disk = true | |||
system.totalordermulticast.sync_log = false | |||
#Period at which BFT-SMaRt requests the state to the application (for the state transfer state protocol) | |||
@@ -146,7 +154,7 @@ system.totalordermulticast.sync_ckp = false | |||
system.initial.view = 0,1,2,3 | |||
#The ID of the trust third party (TTP) | |||
system.ttp.id = 7002 | |||
system.ttp.id = 2001 | |||
#This sets if the system will function in Byzantine or crash-only mode. Set to "true" to support Byzantine faults | |||
system.bft = true | |||
@@ -0,0 +1,39 @@ | |||
<?xml version="1.0" encoding="UTF-8"?> | |||
<configuration status="WARN" monitorInterval="60"> | |||
<appenders> | |||
<console name="Console" target="SYSTEM_OUT"> | |||
<ThresholdFilter level="fatal" onMatch="ACCEPT" onMismatch="DENY"/> | |||
<PatternLayout pattern="%d{HH:mm:ss.SSS} %-5level %class{36} %L %M - %msg%xEx%n"/> | |||
</console> | |||
<RollingFile name="PeerRolling" fileName="${sys:jdchain.log}/peer.log" | |||
filePattern="${sys:jdchain.log}/$${date:yyyy-MM}/peer-%d{yyyy-MM-dd}-%i.log"> | |||
<ThresholdFilter level="info" onMatch="ACCEPT" onMismatch="DENY"/> | |||
<PatternLayout pattern="[%date{yyyy-MM-dd HH:mm:ss:SSS}] [%thread] [%p] - %l - %m%n"/> | |||
<Policies> | |||
<TimeBasedTriggeringPolicy/> | |||
<SizeBasedTriggeringPolicy size="100 MB"/> | |||
</Policies> | |||
<DefaultRolloverStrategy max="100"/> | |||
</RollingFile> | |||
<RollingFile name="PeerRollingError" fileName="${sys:jdchain.log}/peer.error.log" | |||
filePattern="${sys:jdchain.log}/$${date:yyyy-MM}/peer.error-%d{yyyy-MM-dd}-%i.log"> | |||
<ThresholdFilter level="error" onMatch="ACCEPT" onMismatch="DENY"/> | |||
<PatternLayout pattern="[%date{yyyy-MM-dd HH:mm:ss:SSS}] [%thread] [%p] - %l - %m%n"/> | |||
<Policies> | |||
<TimeBasedTriggeringPolicy/> | |||
<SizeBasedTriggeringPolicy size="100 MB"/> | |||
</Policies> | |||
</RollingFile> | |||
</appenders> | |||
<loggers> | |||
<logger name="org.springframework" level="error"></logger> | |||
<logger name="bftsmart" level="error"></logger> | |||
<!--修改此处,以变更日志等级--> | |||
<root level="info"> | |||
<appender-ref ref="Console"/> | |||
<appender-ref ref="PeerRolling"/> | |||
<appender-ref ref="PeerRollingError"/> | |||
</root> | |||
</loggers> | |||
</configuration> |
@@ -1,6 +1,6 @@ | |||
# JDChain安装部署指南 | |||
本部署指南基于JDChain1.3.0.RELEASE版本来构建。 | |||
本部署指南基于JDChain1.4.0.RELEASE版本来构建。 | |||
## 1. 部署环境 | |||
### 1.1 系统部署结构 | |||
![部署结构](imgs/structure.png) | |||
@@ -0,0 +1,10 @@ | |||
#!/bin/bash | |||
HOME=$(cd `dirname $0`;cd ../; pwd) | |||
boot_file=$(ls ../libs | grep tools-activeparti-booter-) | |||
if [ ! -n "$boot_file" ]; then | |||
echo "tools-activeparti-booter is null" | |||
else | |||
echo "active participant" | |||
java -jar $HOME/libs/$boot_file $* | |||
fi |
@@ -0,0 +1,10 @@ | |||
#!/bin/bash | |||
HOME=$(cd `dirname $0`;cd ../; pwd) | |||
boot_file=$(ls ../libs | grep tools-deactiveparti-booter-) | |||
if [ ! -n "$boot_file" ]; then | |||
echo "tools-deactiveparti-booter is null" | |||
else | |||
echo "deactive participant" | |||
java -jar $HOME/libs/$boot_file $* | |||
fi |
@@ -5,5 +5,5 @@ boot_file=$(ls $HOME/libs | grep tools-initializer-booter-) | |||
if [ ! -n "$boot_file" ]; then | |||
echo "tools-initializer-booter is null" | |||
else | |||
java -jar -server -Djdchain.log=$HOME $HOME/libs/$boot_file -l $HOME/config/init/local.conf -i $HOME/config/init/ledger.init $* | |||
java -jar -server -Djdchain.log=$HOME/logs $HOME/libs/$boot_file -l $HOME/config/init/local.conf -i $HOME/config/init/ledger.init $* | |||
fi |
@@ -1,32 +1,65 @@ | |||
#!/bin/bash | |||
#启动Home路径 | |||
BOOT_HOME=$(cd `dirname $0`;cd ../; pwd) | |||
#进程启动后PID.log所在路径 | |||
PID_LOG=$BOOT_HOME/bin/PID.log | |||
#从启动文件中读取PID | |||
if [ -f "$PID_LOG" ]; then | |||
# File exist | |||
echo "Read PID From File:[$PID_LOG] ..." | |||
PID_LINE=`sed -n '$p' $PID_LOG` | |||
echo "Last Peer Boot Info = $PID_LINE ..." | |||
if [[ $PID_LINE == *PEER_BOOT_PID* ]]; then | |||
LOG_PID=$(echo $PID_LINE | cut -d "=" -f 2 | cut -d "[" -f 2 | cut -d "]" -f 1) | |||
echo "Last Peer Boot PID = $LOG_PID ..." | |||
PID=`ps -ef | grep deploy-peer- | grep $LOG_PID | grep -v grep | awk '{print $2}'` | |||
#定义程序启动的Jar包前缀 | |||
APP_JAR_PREFIX=deploy-peer- | |||
#获取当前的根目录 | |||
APP_HOME=$(cd `dirname $0`;cd ../; pwd) | |||
#System路径 | |||
APP_SYSTEM_PATH=$APP_HOME/system | |||
#获取Peer节点的启动Jar包 | |||
APP_JAR=$(ls $APP_SYSTEM_PATH | grep $APP_JAR_PREFIX) | |||
#APP_JAR的具体路径 | |||
APP_JAR_PATH=$APP_SYSTEM_PATH/$APP_JAR | |||
################################### | |||
#(函数)判断程序是否已启动 | |||
# | |||
#说明: | |||
#使用awk,分割出pid ($1部分),及Java程序名称($2部分) | |||
################################### | |||
#初始化psid变量(全局) | |||
psid=0 | |||
checkpid() { | |||
psid=`ps -ef | grep $APP_JAR_PATH | grep -v grep | awk '{print $2}'` | |||
} | |||
################################### | |||
#(函数)停止程序 | |||
# | |||
#说明: | |||
#1. 首先调用checkpid函数,刷新$psid全局变量 | |||
#2. 如果程序已经启动($psid不等于0),则开始执行停止,否则,提示程序未运行 | |||
#3. 使用kill -9 pid命令进行强制杀死进程 | |||
#4. 执行kill命令行紧接其后,马上查看上一句命令的返回值: $? | |||
#5. 如果步骤4的结果$?等于0,则打印[OK],否则打印[Failed] | |||
#注意:echo -n 表示打印字符后,不换行 | |||
#注意: 在shell编程中,"$?" 表示上一句命令或者一个函数的返回值 | |||
################################### | |||
stop() { | |||
checkpid | |||
if [[ $psid -ne 0 ]]; then | |||
echo "Stopping Peer ......(pid=$psid) " | |||
JAVA_CMD="kill -9 $psid" | |||
sleep 1 | |||
$JAVA_CMD | |||
if [[ $? -eq 0 ]]; then | |||
echo "[OK]" | |||
else | |||
echo "[Failed]" | |||
fi | |||
#启动文件不存在则直接通过PS进行过滤 | |||
else | |||
PID=`ps -ef | grep $BOOT_HOME/system/deploy-peer- | grep -v grep | awk '{print $2}'` | |||
fi | |||
#通过Kill命令将进程杀死 | |||
if [ -z "$PID" ]; then | |||
echo "Unable to find peer PID. stop aborted." | |||
else | |||
echo "Start to kill PID = $PID ..." | |||
kill -9 $PID | |||
echo "Peer has been stopped ..." | |||
fi | |||
else | |||
echo "================================" | |||
echo "WARN: Peer is not running" | |||
echo "================================" | |||
fi | |||
} | |||
#真正停止的处理流程 | |||
stop |
@@ -1,19 +1,117 @@ | |||
#!/bin/bash | |||
HOME=$(cd `dirname $0`;cd ../; pwd) | |||
PEER=$(ls $HOME/system | grep deploy-peer-) | |||
PROC_INFO=$HOME/system/$PEER" -home="$HOME" -c "$HOME/config/ledger-binding.conf" -p 7080" | |||
#echo $PROC_INFO | |||
#get PID | |||
PID=`ps -ef | grep "$PROC_INFO" | grep -v grep | awk '{print $2}'` | |||
#echo $PID | |||
if [[ ! -z $PID ]] | |||
then | |||
echo "process already exists,please check... If necessary, you should kill the process first." | |||
exit | |||
#设置Java命令 | |||
JAVA_BIN=java | |||
#定义程序启动的Jar包前缀 | |||
APP_JAR_PREFIX=deploy-peer- | |||
#Peer节点Web端口 | |||
#请运维根据实际环境进行调整或通过-p参数传入 | |||
WEB_PORT=7080 | |||
#端口配置参数 | |||
IS_CONFIG=false | |||
for i in "$@"; do | |||
if [ $i = "-p" ];then | |||
IS_CONFIG=true | |||
fi | |||
done | |||
#检查Java环境变量 | |||
if [ ! -n "$JAVA_HOME" ]; then | |||
echo "UnFound environment variable[JAVA_HOME], will use command[java]..." | |||
else | |||
JAVA_BIN=$JAVA_HOME/bin/java | |||
fi | |||
if [ ! -n "$PEER" ]; then | |||
echo "Peer Is Null !!!" | |||
#获取当前的根目录 | |||
APP_HOME=$(cd `dirname $0`;cd ../; pwd) | |||
#System目录 | |||
APP_SYSTEM_PATH=$APP_HOME/system | |||
#nohup输出日志路径 | |||
LOG_OUT=$APP_HOME/bin/peer.out | |||
#获取Peer节点的启动Jar包 | |||
APP_JAR=$(ls $APP_SYSTEM_PATH | grep $APP_JAR_PREFIX) | |||
#Config配置路径 | |||
CONFIG_PATH=$APP_HOME/config | |||
#ledger-binding.conf完整路径 | |||
LEDGER_BINDING_CONFIG=$CONFIG_PATH/ledger-binding.conf | |||
#定义程序启动的参数 | |||
JAVA_OPTS="-jar -server -Xms2048m -Xmx2048m -Djdchain.log=$APP_HOME/logs -Dlogging.config=file:$APP_HOME/config/log4j2-peer.xml" | |||
#APP具体相关命令 | |||
APP_CMD=$APP_SYSTEM_PATH/$APP_JAR" -home="$APP_HOME" -c "$LEDGER_BINDING_CONFIG" -p "$WEB_PORT | |||
if [ $IS_CONFIG = true ];then | |||
APP_CMD=$APP_SYSTEM_PATH/$APP_JAR" -home="$APP_HOME" -c "$LEDGER_BINDING_CONFIG | |||
fi | |||
#APP_JAR的具体路径 | |||
APP_JAR_PATH=$APP_SYSTEM_PATH/$APP_JAR | |||
#JAVA_CMD具体命令 | |||
JAVA_CMD="$JAVA_BIN $JAVA_OPTS $APP_CMD" | |||
################################### | |||
#(函数)判断程序是否已启动 | |||
# | |||
#说明: | |||
#使用awk,分割出pid ($1部分),及Java程序名称($2部分) | |||
################################### | |||
#初始化psid变量(全局) | |||
psid=0 | |||
checkpid() { | |||
javaps=`ps -ef | grep $APP_JAR_PATH | grep -v grep | awk '{print $2}'` | |||
if [[ -n "$javaps" ]]; then | |||
psid=$javaps | |||
else | |||
psid=0 | |||
fi | |||
} | |||
################################### | |||
#(函数)打印系统环境参数 | |||
################################### | |||
info() { | |||
echo "System Information:" | |||
echo "****************************" | |||
echo `uname -a` | |||
echo | |||
echo `$JAVA_BIN -version` | |||
echo | |||
echo "APP_HOME=$APP_HOME" | |||
echo "APP_JAR=$APP_JAR" | |||
echo "CONFIG_PATH=$CONFIG_PATH" | |||
echo "APP_JAR_PATH=$APP_JAR_PATH" | |||
echo | |||
echo "JAVA_CMD=$JAVA_CMD" | |||
echo "****************************" | |||
} | |||
#真正启动的处理流程 | |||
checkpid | |||
if [[ $psid -ne 0 ]]; then | |||
echo "================================" | |||
echo "warn: Peer already started! (pid=$psid)" | |||
echo "================================" | |||
else | |||
nohup java -jar -server -Xmx1g -Xms1g -Djdchain.log=$HOME $PROC_INFO $* >$HOME/bin/peer.out 2>&1 & | |||
echo "Starting Peer ......" | |||
nohup $JAVA_BIN $JAVA_OPTS $APP_CMD $* >$LOG_OUT 2>&1 & | |||
JAVA_CMD="$JAVA_BIN $JAVA_OPTS $APP_CMD $*" | |||
sleep 1 | |||
checkpid | |||
if [[ $psid -ne 0 ]]; then | |||
echo "(pid=$psid) [OK]" | |||
info | |||
else | |||
echo "[Failed]" | |||
fi | |||
fi |
@@ -0,0 +1,10 @@ | |||
#!/bin/bash | |||
HOME=$(cd `dirname $0`;cd ../; pwd) | |||
boot_file=$(ls ../libs | grep tools-regparti-booter-) | |||
if [ ! -n "$boot_file" ]; then | |||
echo "tools-regparti-booter is null" | |||
else | |||
echo "register new participant" | |||
java -jar $HOME/libs/$boot_file $* | |||
fi |
@@ -0,0 +1,135 @@ | |||
<?xml version="1.0" encoding="UTF-8"?> | |||
<project xmlns="http://maven.apache.org/POM/4.0.0" | |||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | |||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> | |||
<parent> | |||
<artifactId>docker</artifactId> | |||
<groupId>com.jd.blockchain</groupId> | |||
<version>1.4.0.RELEASE</version> | |||
</parent> | |||
<modelVersion>4.0.0</modelVersion> | |||
<artifactId>docker-demo</artifactId> | |||
<dependencies> | |||
<dependency> | |||
<groupId>com.jd.blockchain</groupId> | |||
<artifactId>docker-sdk</artifactId> | |||
<version>${project.version}</version> | |||
</dependency> | |||
</dependencies> | |||
<build> | |||
<finalName>jdchain-demo</finalName> | |||
<plugins> | |||
<plugin> | |||
<groupId>org.apache.maven.plugins</groupId> | |||
<artifactId>maven-compiler-plugin</artifactId> | |||
<configuration> | |||
<source>1.8</source> | |||
<target>1.8</target> | |||
<encoding>UTF-8</encoding> | |||
<optimize>false</optimize> | |||
<debug>true</debug> | |||
<showDeprecation>false</showDeprecation> | |||
<showWarnings>false</showWarnings> | |||
</configuration> | |||
</plugin> | |||
<!-- <plugin>--> | |||
<!-- <groupId>org.apache.maven.plugins</groupId>--> | |||
<!-- <artifactId>maven-dependency-plugin</artifactId>--> | |||
<!-- <executions>--> | |||
<!-- <execution>--> | |||
<!-- <id>copy-dependencies</id>--> | |||
<!-- <phase>package</phase>--> | |||
<!-- <goals>--> | |||
<!-- <goal>copy-dependencies</goal>--> | |||
<!-- </goals>--> | |||
<!-- <configuration>--> | |||
<!-- <outputDirectory>${project.build.directory}/dependencies</outputDirectory>--> | |||
<!-- <excludeTransitive>false</excludeTransitive>--> | |||
<!-- <stripVersion>false</stripVersion>--> | |||
<!-- <includeScope>runtime</includeScope>--> | |||
<!-- </configuration>--> | |||
<!-- </execution>--> | |||
<!-- </executions>--> | |||
<!-- </plugin>--> | |||
<plugin> | |||
<artifactId>maven-resources-plugin</artifactId> | |||
<version>3.0.2</version> | |||
<executions> | |||
<execution> | |||
<id>copy-resources</id> | |||
<phase>validate</phase> | |||
<goals> | |||
<goal>copy-resources</goal> | |||
</goals> | |||
<configuration> | |||
<!-- 将资源文件拷贝到config目录下 --> | |||
<encoding>UTF-8</encoding> | |||
<outputDirectory>${project.basedir}/src/main/docker/zip</outputDirectory> | |||
<overwrite>false</overwrite> | |||
<resources> | |||
<resource> | |||
<directory>${project.basedir}/../../deploy-peer/target/</directory> | |||
<filtering>false</filtering> | |||
<includes> | |||
<include>jdchain-peer-${project.version}.zip</include> | |||
</includes> | |||
</resource> | |||
<resource> | |||
<directory>${project.basedir}/../../deploy-gateway/target/</directory> | |||
<filtering>false</filtering> | |||
<includes> | |||
<include>jdchain-gateway-${project.version}.zip</include> | |||
</includes> | |||
</resource> | |||
<!-- sdk --> | |||
<resource> | |||
<directory>${project.basedir}/../docker-sdk/target/</directory> | |||
<filtering>false</filtering> | |||
<includes> | |||
<include>docker-sdk-${project.version}.jar</include> | |||
</includes> | |||
</resource> | |||
</resources> | |||
</configuration> | |||
</execution> | |||
</executions> | |||
</plugin> | |||
<!-- 使用Maven插件直接将应用打包为一个Docker镜像 --> | |||
<plugin> | |||
<groupId>com.spotify</groupId> | |||
<artifactId>docker-maven-plugin</artifactId> | |||
<version>1.2.2</version> | |||
<!--将插件绑定在某个phase执行--> | |||
<executions> | |||
<execution> | |||
<id>build-image</id> | |||
<!--将插件绑定在package这个phase上。也就是说,用户只需执行mvn package ,就会自动执行mvn docker:build--> | |||
<phase>package</phase> | |||
<goals> | |||
<goal>build</goal> | |||
</goals> | |||
</execution> | |||
</executions> | |||
<configuration> | |||
<imageName>jdchain-demo</imageName> | |||
<imageTags> | |||
<imageTag>${project.version}</imageTag> | |||
</imageTags> | |||
<!-- 指定 Dockerfile 路径--> | |||
<dockerDirectory>${project.basedir}/target</dockerDirectory> | |||
</configuration> | |||
</plugin> | |||
</plugins> | |||
</build> | |||
</project> |
@@ -0,0 +1,37 @@ | |||
FROM centos:8.2.2004 | |||
# install tools | |||
RUN yum install wget -y \ | |||
&& wget -O /etc/yum.repos.d/epel-7.repo http://mirrors.aliyun.com/repo/epel-7.repo \ | |||
&& yum install java net-tools nc crontabs expect unzip -y \ | |||
&& yum install langpacks-zh_CN.noarch -y \ | |||
&& yum install dos2unix -y \ | |||
&& echo "LANG=zh_CN.utf8" >> /etc/locale.conf \ | |||
&& source /etc/locale.conf \ | |||
&& yum clean all | |||
WORKDIR /export/jdchain | |||
COPY zip/* /export/jdchain/ | |||
# env | |||
ENV RELEASE_DIR=/export/jdchain | |||
ENV RELEASE_VERSION=1.3.0 | |||
#ENV DATA_DIR=/shared | |||
ENV NAME=conf | |||
ENV SERVER_NAME_PEER=deploy-peer | |||
ENV SERVER_NAME_GW=deploy-gateway | |||
COPY script/* /export/jdchain/ | |||
RUN dos2unix /export/jdchain/*.sh | |||
RUN chmod +x /export/jdchain/*.sh | |||
# ports | |||
EXPOSE 8080 | |||
#EXPOSE 16000 | |||
#EXPOSE 16010 | |||
#EXPOSE 16020 | |||
#EXPOSE 16030 | |||
#ENTRYPOINT ["/bin/sh","-c","/export/jdchain/start.sh"] | |||
ENTRYPOINT sh /export/jdchain/start.sh | |||
@@ -0,0 +1,4 @@ | |||
#!/bin/bash | |||
ps -ef|grep 'jdchain'|grep -v grep|cut -c 9-15|xargs kill -9 | |||
@@ -0,0 +1,34 @@ | |||
#!/bin/bash | |||
cd $RELEASE_DIR | |||
# check the files; | |||
peer_file="./jdchain-peer-$RELEASE_VERSION.RELEASE.zip" | |||
gw_file="./jdchain-gateway-$RELEASE_VERSION.RELEASE.zip" | |||
sdk_file="./docker-sdk-$RELEASE_VERSION.RELEASE.jar" | |||
if [[ ! -f $peer_file ]] || [[ ! -f $gw_file ]] || [[ ! -f $sdk_file ]] ; then | |||
echo "not find $peer_file or $gw_file or $sdk_file in the $RELEASE_DIR, please check the image of jdchain-demo:$RELEASE_VERSION." | |||
exit 1 | |||
fi | |||
unzip -o conf.zip | |||
for i in `seq 0 3` | |||
do | |||
unzip -n -d ./peer$i jdchain-peer-$RELEASE_VERSION.RELEASE.zip | |||
chmod +x ./peer$i/bin/* | |||
done | |||
unzip -n -d ./gw jdchain-gateway-$RELEASE_VERSION.RELEASE.zip | |||
chmod +x ./gw/bin/* | |||
sh ./peer0/bin/peer-startup.sh | |||
sh ./peer1/bin/peer-startup.sh | |||
sh ./peer2/bin/peer-startup.sh | |||
sh ./peer3/bin/peer-startup.sh | |||
sleep 30 | |||
sh ./gw/bin/startup.sh | |||
sleep 10 | |||
java -jar docker-sdk-1.3.0.RELEASE.jar > sdk.log | |||
tail -f /dev/null |
@@ -0,0 +1,36 @@ | |||
version: '2' | |||
services: | |||
demo: | |||
image: "jdchain-demo:1.3.0" | |||
container_name: jdchain-demo | |||
networks: | |||
jdchain_default: | |||
aliases: | |||
- demo | |||
hostname: demo | |||
restart: always | |||
ports: | |||
- "11010:11010" | |||
- "7080:7080" | |||
- "10080:10080" | |||
- "10081:10081" | |||
- "11011:11011" | |||
- "7081:7081" | |||
- "10082:10082" | |||
- "10083:10083" | |||
- "11012:11012" | |||
- "7082:7082" | |||
- "10084:10084" | |||
- "10085:10085" | |||
- "11013:11013" | |||
- "7083:7083" | |||
- "10086:10086" | |||
- "10087:10087" | |||
- "8080:8080" | |||
# volumes: | |||
# - "./logs:/export/jdchain/peer0/logs" | |||
networks: | |||
jdchain_default: | |||
driver: bridge |
@@ -0,0 +1,5 @@ | |||
#!/bin/bash | |||
echo "停止network" | |||
docker-compose -f docker-compose-all.yaml down | |||
echo "启动jdchain" | |||
docker-compose -f docker-compose-all.yaml up -d |
@@ -0,0 +1,9 @@ | |||
#/bin/bash | |||
# all in one; | |||
allIn1_file="./jdchain-demo_1.3.0.tar.gz" | |||
if [ -f $allIn1_file ] ; then | |||
rm -rf $allIn1_file | |||
fi | |||
docker save jdchain-demo:1.3.0 -o jdchain-demo_1.3.0.tar | |||
gzip jdchain-demo_1.3.0.tar |
@@ -0,0 +1,66 @@ | |||
<?xml version="1.0" encoding="UTF-8"?> | |||
<project xmlns="http://maven.apache.org/POM/4.0.0" | |||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | |||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> | |||
<parent> | |||
<artifactId>docker</artifactId> | |||
<groupId>com.jd.blockchain</groupId> | |||
<version>1.4.0.RELEASE</version> | |||
</parent> | |||
<modelVersion>4.0.0</modelVersion> | |||
<artifactId>docker-sdk</artifactId> | |||
<dependencies> | |||
<dependency> | |||
<groupId>com.jd.blockchain</groupId> | |||
<artifactId>crypto-classic</artifactId> | |||
<version>${project.version}</version> | |||
</dependency> | |||
<dependency> | |||
<groupId>com.jd.blockchain</groupId> | |||
<artifactId>crypto-sm</artifactId> | |||
<version>${project.version}</version> | |||
</dependency> | |||
<dependency> | |||
<groupId>com.jd.blockchain</groupId> | |||
<artifactId>ledger-model</artifactId> | |||
<version>${project.version}</version> | |||
</dependency> | |||
<dependency> | |||
<groupId>com.jd.blockchain</groupId> | |||
<artifactId>sdk-client</artifactId> | |||
<version>${project.version}</version> | |||
</dependency> | |||
</dependencies> | |||
<build> | |||
<plugins> | |||
<plugin> | |||
<artifactId>maven-assembly-plugin</artifactId> | |||
<configuration> | |||
<appendAssemblyId>false</appendAssemblyId> | |||
<descriptorRefs> | |||
<descriptorRef>jar-with-dependencies</descriptorRef> | |||
</descriptorRefs> | |||
<archive> | |||
<manifest> | |||
<!-- 程序入口 --> | |||
<mainClass>com.jd.blockchain.SDKDemo</mainClass> | |||
</manifest> | |||
</archive> | |||
</configuration> | |||
<executions> | |||
<execution> | |||
<id>make-assembly</id> | |||
<phase>package</phase> | |||
<goals> | |||
<goal>single</goal> | |||
</goals> | |||
</execution> | |||
</executions> | |||
</plugin> | |||
</plugins> | |||
</build> | |||
</project> |
@@ -0,0 +1,107 @@ | |||
package com.jd.blockchain; | |||
import com.jd.blockchain.ledger.BlockchainIdentity; | |||
import com.jd.blockchain.ledger.BlockchainKeypair; | |||
public class ContractParams { | |||
String contractZipName; | |||
BlockchainKeypair signAdminKey; | |||
BlockchainIdentity contractIdentity; | |||
boolean isDeploy; | |||
boolean isExecute; | |||
boolean hasVersion; //contract's version; | |||
long version; | |||
BlockchainIdentity dataAccount; | |||
String key; | |||
String value; | |||
public String getContractZipName() { | |||
return contractZipName; | |||
} | |||
public ContractParams setContractZipName(String contractZipName) { | |||
this.contractZipName = contractZipName; | |||
return this; | |||
} | |||
public BlockchainKeypair getSignAdminKey() { | |||
return signAdminKey; | |||
} | |||
public ContractParams setSignAdminKey(BlockchainKeypair signAdminKey) { | |||
this.signAdminKey = signAdminKey; | |||
return this; | |||
} | |||
public BlockchainIdentity getContractIdentity() { | |||
return contractIdentity; | |||
} | |||
public ContractParams setContractIdentity(BlockchainIdentity contractIdentity) { | |||
this.contractIdentity = contractIdentity; | |||
return this; | |||
} | |||
public boolean isDeploy() { | |||
return isDeploy; | |||
} | |||
public ContractParams setDeploy(boolean deploy) { | |||
isDeploy = deploy; | |||
return this; | |||
} | |||
public boolean isExecute() { | |||
return isExecute; | |||
} | |||
public ContractParams setExecute(boolean execute) { | |||
isExecute = execute; | |||
return this; | |||
} | |||
public boolean isHasVersion() { | |||
return hasVersion; | |||
} | |||
public ContractParams setHasVersion(boolean hasVersion) { | |||
this.hasVersion = hasVersion; | |||
return this; | |||
} | |||
public long getVersion() { | |||
return version; | |||
} | |||
public ContractParams setVersion(long version) { | |||
this.version = version; | |||
return this; | |||
} | |||
public BlockchainIdentity getDataAccount() { | |||
return dataAccount; | |||
} | |||
public ContractParams setDataAccount(BlockchainIdentity dataAccount) { | |||
this.dataAccount = dataAccount; | |||
return this; | |||
} | |||
public String getKey() { | |||
return key; | |||
} | |||
public ContractParams setKey(String key) { | |||
this.key = key; | |||
return this; | |||
} | |||
public String getValue() { | |||
return value; | |||
} | |||
public ContractParams setValue(String value) { | |||
this.value = value; | |||
return this; | |||
} | |||
} |
@@ -0,0 +1,68 @@ | |||
package com.jd.blockchain; | |||
import com.jd.blockchain.ledger.*; | |||
import org.apache.commons.codec.binary.Base64; | |||
import java.util.Random; | |||
import java.util.UUID; | |||
public class SDKDemo extends SDK_Base_Demo{ | |||
public static void main(String[] args) { | |||
SDKDemo sdkDemo = new SDKDemo(); | |||
//注册用户; | |||
sdkDemo.registerUsers(); | |||
//构建数据账户; | |||
sdkDemo.genDataAccount(); | |||
//发布和执行合约; | |||
sdkDemo.deployContract(); | |||
} | |||
//注册用户; | |||
public void registerUsers(){ | |||
this.registerUser(); | |||
} | |||
//构建数据账户; | |||
public void genDataAccount(){ | |||
byte[] arr = new byte[1024]; | |||
new Random().nextBytes(arr); | |||
String value = Base64.encodeBase64String(arr); | |||
this.insertData(null,null,"key1",value,-1); | |||
} | |||
public BlockchainKeypair insertData(BlockchainKeypair dataAccount, BlockchainKeypair signAdminKey, | |||
String key, String value, long version) { | |||
// 在本地定义注册账号的 TX; | |||
TransactionTemplate txTemp = blockchainService.newTransaction(ledgerHash); | |||
//采用KeyGenerator来生成BlockchainKeypair; | |||
if(dataAccount == null){ | |||
dataAccount = BlockchainKeyGenerator.getInstance().generate(); | |||
txTemp.dataAccounts().register(dataAccount.getIdentity()); | |||
} | |||
System.out.println("current dataAccount=" + dataAccount.getAddress()); | |||
txTemp.dataAccount(dataAccount.getAddress()).setText(key, value, version); | |||
txTemp.dataAccount(dataAccount.getAddress()).setTimestamp(UUID.randomUUID().toString(),System.currentTimeMillis(),-1); | |||
// TX 准备就绪 | |||
commit(txTemp,signAdminKey); | |||
//get the version | |||
TypedKVEntry[] kvData = blockchainService.getDataEntries(ledgerHash, | |||
dataAccount.getAddress().toBase58(), key); | |||
System.out.println(String.format("key1 info:key=%s,value=%s,version=%d", | |||
kvData[0].getKey(),kvData[0].getValue().toString(),kvData[0].getVersion())); | |||
return dataAccount; | |||
} | |||
public void deployContract(){ | |||
ContractParams contractParams = new ContractParams(); | |||
contractParams.setContractZipName("contract-compile-1.3.0.RELEASE.car").setDeploy(true).setExecute(false); | |||
BlockchainIdentity contractAddress = | |||
this.contractHandle(contractParams); | |||
contractParams.setContractIdentity(contractAddress); | |||
this.contractHandle(contractParams); | |||
this.contractHandle(contractParams.setExecute(true)); | |||
} | |||
} |
@@ -0,0 +1,46 @@ | |||
package com.jd.blockchain; | |||
import com.jd.blockchain.crypto.KeyGenUtils; | |||
import com.jd.blockchain.crypto.PrivKey; | |||
import com.jd.blockchain.crypto.PubKey; | |||
import com.jd.blockchain.ledger.BlockchainKeypair; | |||
import org.apache.commons.io.FileUtils; | |||
import org.springframework.core.io.ClassPathResource; | |||
import java.io.File; | |||
import java.io.InputStream; | |||
public class SDKDemo_Constant { | |||
public static String GW_IPADDR = "localhost"; | |||
public static int GW_PORT = 8080; | |||
public static String GW_PUB_KEY = "3snPdw7i7PisoLpqqtETdqzQeKVjQReP2Eid9wYK67q9z6trvByGZs"; | |||
public static String GW_PRIV_KEY = "177gk2PbxhHeEdfAAqGfShJQyeV4XvGsJ9CvJFUbToBqwW1YJd5obicySE1St6SvPPaRrUP"; | |||
public static String GW_PASSWORD = "8EjkXVSTxMFjCvNNsTo8RBMDEVQmk7gYkW4SCDuvdsBG"; | |||
public static PrivKey gwPrivkey0 = KeyGenUtils.decodePrivKey(GW_PRIV_KEY, GW_PASSWORD); | |||
public static PubKey gwPubKey0 = KeyGenUtils.decodePubKey(GW_PUB_KEY); | |||
public static BlockchainKeypair adminKey = new BlockchainKeypair(gwPubKey0, gwPrivkey0); | |||
public static final byte[] readChainCodes(String contractZip) { | |||
// 构建合约的字节数组; | |||
try { | |||
ClassPathResource contractPath = new ClassPathResource(contractZip); | |||
// File contractFile = new File(contractPath.getURI()); | |||
InputStream in = contractPath.getInputStream(); | |||
// 将文件写入至config目录下 | |||
File directory = new File("."); | |||
String configPath = directory.getAbsolutePath() + File.separator + "contract.jar"; | |||
File targetFile = new File(configPath); | |||
// 先将原来文件删除再Copy | |||
if (targetFile.exists()) { | |||
FileUtils.forceDelete(targetFile); | |||
} | |||
FileUtils.copyInputStreamToFile(in, targetFile); | |||
return FileUtils.readFileToByteArray(targetFile); | |||
} catch (Exception e) { | |||
throw new IllegalStateException(e); | |||
} | |||
} | |||
} |
@@ -0,0 +1,186 @@ | |||
package com.jd.blockchain; | |||
import com.jd.blockchain.crypto.HashDigest; | |||
import com.jd.blockchain.ledger.*; | |||
import com.jd.blockchain.sdk.BlockchainService; | |||
import com.jd.blockchain.sdk.client.GatewayServiceFactory; | |||
import com.jd.blockchain.transaction.GenericValueHolder; | |||
import com.jd.blockchain.utils.Bytes; | |||
import com.jd.chain.contract.TransferContract; | |||
import static com.jd.blockchain.SDKDemo_Constant.readChainCodes; | |||
import static com.jd.blockchain.transaction.ContractReturnValue.decode; | |||
public abstract class SDK_Base_Demo { | |||
protected BlockchainKeypair adminKey; | |||
protected HashDigest ledgerHash; | |||
protected BlockchainService blockchainService; | |||
public SDK_Base_Demo() { | |||
init(); | |||
} | |||
public void init() { | |||
// 生成连接网关的账号 | |||
adminKey = SDKDemo_Constant.adminKey; | |||
// 连接网关 | |||
GatewayServiceFactory serviceFactory = GatewayServiceFactory.connect(SDKDemo_Constant.GW_IPADDR, | |||
SDKDemo_Constant.GW_PORT, false, adminKey); | |||
// 获取网关对应的Service处理类 | |||
blockchainService = serviceFactory.getBlockchainService(); | |||
HashDigest[] ledgerHashs = blockchainService.getLedgerHashs(); | |||
// 获取当前账本Hash | |||
ledgerHash = ledgerHashs[0]; | |||
} | |||
public TransactionResponse commit(TransactionTemplate txTpl){ | |||
return this.commitA(txTpl,null); | |||
} | |||
/** | |||
* 默认使用A方式commit; | |||
* @param txTpl | |||
* @param signAdminKey | |||
* @return | |||
*/ | |||
public TransactionResponse commit(TransactionTemplate txTpl, BlockchainKeypair signAdminKey){ | |||
return commitA(txTpl, signAdminKey); | |||
} | |||
/** | |||
* 采用A方式提交; | |||
* @param txTpl | |||
* @param signAdminKey | |||
* @return | |||
*/ | |||
public TransactionResponse commitA(TransactionTemplate txTpl, BlockchainKeypair signAdminKey) { | |||
PreparedTransaction ptx = txTpl.prepare(); | |||
if(signAdminKey != null){ | |||
System.out.println("signAdminKey's pubKey = "+signAdminKey.getIdentity().getPubKey()); | |||
ptx.sign(signAdminKey); | |||
}else { | |||
System.out.println("adminKey's pubKey = "+adminKey.getIdentity().getPubKey()); | |||
ptx.sign(adminKey); | |||
} | |||
TransactionResponse transactionResponse = ptx.commit(); | |||
if (transactionResponse.isSuccess()) { | |||
System.out.println(String.format("height=%d, ###OK#, contentHash=%s, executionState=%s", | |||
transactionResponse.getBlockHeight(), | |||
transactionResponse.getContentHash(), transactionResponse.getExecutionState().toString())); | |||
} else { | |||
System.out.println(String.format("height=%d, ###exception#, contentHash=%s, executionState=%s", | |||
transactionResponse.getBlockHeight(), | |||
transactionResponse.getContentHash(), transactionResponse.getExecutionState().toString())); | |||
} | |||
return transactionResponse; | |||
} | |||
/** | |||
* 生成一个区块链用户,并注册到区块链; | |||
*/ | |||
public BlockchainKeypair registerUser() { | |||
return this.registerUser(null,null,null); | |||
} | |||
public BlockchainKeypair registerUser(String cryptoType, BlockchainKeypair signAdminKey, BlockchainKeypair userKeypair) { | |||
// 在本地定义注册账号的 TX; | |||
TransactionTemplate txTemp = blockchainService.newTransaction(ledgerHash); | |||
if(userKeypair == null){ | |||
if("SM2".equals(cryptoType)){ | |||
userKeypair = BlockchainKeyGenerator.getInstance().generate(cryptoType); | |||
}else { | |||
userKeypair = BlockchainKeyGenerator.getInstance().generate(); | |||
} | |||
} | |||
System.out.println("user'address="+userKeypair.getAddress()); | |||
txTemp.users().register(userKeypair.getIdentity()); | |||
// TX 准备就绪; | |||
commit(txTemp,signAdminKey); | |||
return userKeypair; | |||
} | |||
public BlockchainKeypair registerUser(BlockchainKeypair signAdminKey, BlockchainKeypair userKeypair) { | |||
return registerUser(null,signAdminKey,userKeypair); | |||
} | |||
/** | |||
* 生成一个区块链用户,并注册到区块链; | |||
*/ | |||
public BlockchainKeypair registerUserByNewSigner(BlockchainKeypair signer) { | |||
return this.registerUser(signer,null); | |||
} | |||
public BlockchainIdentity createDataAccount() { | |||
// 首先注册一个数据账户 | |||
BlockchainKeypair newDataAccount = BlockchainKeyGenerator.getInstance().generate(); | |||
TransactionTemplate txTpl = blockchainService.newTransaction(ledgerHash); | |||
txTpl.dataAccounts().register(newDataAccount.getIdentity()); | |||
commit(txTpl); | |||
return newDataAccount.getIdentity(); | |||
} | |||
public String create1(Bytes contractAddress, String address, String account, String content) { | |||
System.out.println(String.format("params,String address=%s, String account=%s, String content=%s, Bytes contractAddress=%s", | |||
address,account,content,contractAddress.toBase58())); | |||
TransactionTemplate txTpl = blockchainService.newTransaction(ledgerHash); | |||
// 使用合约创建 | |||
TransferContract guanghu = txTpl.contract(contractAddress, TransferContract.class); | |||
GenericValueHolder<String> result = decode(guanghu.putval(address, account, content, System.currentTimeMillis())); | |||
commit(txTpl); | |||
return result.get(); | |||
} | |||
public BlockchainIdentity contractHandle(ContractParams contractParams) { | |||
if(contractParams.getContractZipName() == null){ | |||
contractParams.setContractZipName("contract-JDChain-Contract.jar"); | |||
} | |||
// 发布jar包 | |||
// 定义交易模板 | |||
TransactionTemplate txTpl = blockchainService.newTransaction(ledgerHash); | |||
Bytes contractAddress = null; | |||
if(contractParams.getContractIdentity() != null){ | |||
contractAddress = contractParams.getContractIdentity().getAddress(); | |||
} | |||
if(contractParams.isDeploy){ | |||
// 将jar包转换为二进制数据 | |||
byte[] contractCode = readChainCodes(contractParams.getContractZipName()); | |||
// 生成一个合约账号 | |||
if(contractParams.getContractIdentity() == null){ | |||
contractParams.setContractIdentity(BlockchainKeyGenerator.getInstance().generate().getIdentity()); | |||
} | |||
contractAddress = contractParams.getContractIdentity().getAddress(); | |||
System.out.println("contract's address=" + contractAddress); | |||
// 生成发布合约操作 | |||
txTpl.contracts().deploy(contractParams.contractIdentity, contractCode); | |||
// 生成预发布交易; | |||
commit(txTpl,contractParams.getSignAdminKey()); | |||
} | |||
if(contractParams.isExecute){ | |||
// 注册一个数据账户 | |||
if(contractParams.dataAccount == null){ | |||
contractParams.dataAccount = createDataAccount(); | |||
contractParams.key = "jd_zhangsan"; | |||
contractParams.value = "{\"dest\":\"KA006\",\"id\":\"cc-fin08-01\",\"items\":\"FIN001|3030\",\"source\":\"FIN001\"}"; | |||
} | |||
// 获取数据账户地址x | |||
String dataAddress = contractParams.dataAccount.getAddress().toBase58(); | |||
// 打印数据账户地址 | |||
System.out.printf("DataAccountAddress = %s \r\n", dataAddress); | |||
System.out.println("return value = "+create1(contractAddress, dataAddress, contractParams.key, contractParams.value)); | |||
} | |||
return contractParams.contractIdentity; | |||
} | |||
} |
@@ -0,0 +1,32 @@ | |||
package com.jd.chain.contract; | |||
import com.jd.blockchain.contract.Contract; | |||
import com.jd.blockchain.contract.ContractEvent; | |||
@Contract | |||
public interface TransferContract { | |||
@ContractEvent(name = "create") | |||
String create(String address, String account, long money); | |||
@ContractEvent(name = "transfer") | |||
String transfer(String address, String from, String to, long money); | |||
@ContractEvent(name = "read") | |||
long read(String address, String account); | |||
@ContractEvent(name = "readAll") | |||
String readAll(String address, String account); | |||
@ContractEvent(name = "putval1") | |||
String putval(String address, String account, String content, Long time); | |||
@ContractEvent(name = "putvalBif") | |||
String putvalBifurcation(String address, String account, String content, String isHalf); | |||
@ContractEvent(name = "getTxSigners") | |||
String getTxSigners(String input); | |||
@ContractEvent(name = "test") | |||
String test(String input); | |||
} |
@@ -0,0 +1,21 @@ | |||
<?xml version="1.0" encoding="UTF-8"?> | |||
<project xmlns="http://maven.apache.org/POM/4.0.0" | |||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | |||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> | |||
<parent> | |||
<artifactId>deploy-root</artifactId> | |||
<groupId>com.jd.blockchain</groupId> | |||
<version>1.4.0.RELEASE</version> | |||
</parent> | |||
<modelVersion>4.0.0</modelVersion> | |||
<packaging>pom</packaging> | |||
<artifactId>docker</artifactId> | |||
<modules> | |||
<module>docker-sdk</module> | |||
<module>docker-demo</module> | |||
</modules> | |||
</project> |
@@ -0,0 +1,44 @@ | |||
# jdchain-demo镜像使用说明 | |||
本镜像主要为快速构建JDChain测试环境使用,内嵌固定的公私钥,不可用于生产正式环境。 | |||
JDChain在docker中的安装路径:/export/jdchain,网关对外端口为:8080。可通过docker-compose-all文件来修改端口。 | |||
demo环境构建完成后执行sdk加载部分测试数据,区块高度:7,交易总数:8,用户总数:5,数据账户总数:2,合约总数:1。 | |||
## 如何生成镜像 | |||
1. 如果构建的docker镜像为当前开发版本,将docker模块中的<version>和<docker-tag>跟主版本对齐,然后在deploy模块执行:mvn clean package即可。 | |||
如果镜像版本与所在开发版本不一致(举例说明:构建1.3.0的镜像版本,但当前开发版本是1.4.0),需要预先在deploy-peer和deploy-gateway的 | |||
target文件夹下放置相应版本zip安装包(jdchain-peer-xxx.zip,jdchain-gateway-xxx.zip),然后在docker模块执行:mvn clean package。 | |||
2. 在maven构建过程中,两个zip安装包和docker-sdk-xxx.jar,会放至docker-demo模块src/main/docker/zip文件夹下。 | |||
3. maven构建完成后,控制台执行:docker images,可看到构建的jdchain-peer镜像。 | |||
4. 生成镜像文件。执行docker-demo模块中src/main/resources/zip.sh,可生成镜像的tar.gz压缩包; | |||
## 镜像快速使用 | |||
1.在已经安装docker工具的环境中,装入jdchain-demo镜像: | |||
```` | |||
docker load -i jdchain-demo_1.3.0.tar.gz | |||
```` | |||
2.启动脚本 | |||
每次执行启动脚本时,会删除原有的容器,然后重新构建全新的容器。 | |||
所以每次执行之后,会清除原先链上新增的区块。 | |||
```` | |||
sh start-net.sh | |||
```` | |||
3.卸载容器 | |||
如果不再使用容器,在start-net.sh脚本所在路径下执行: | |||
```` | |||
docker-compose -f docker-compose-all.yaml down | |||
```` | |||
## SDK连接网关参数 | |||
```` | |||
ip=localhost | |||
port=8080 | |||
#默认公钥的内容(Base58编码数据); | |||
keys.default.pubkey=3snPdw7i7PisoLpqqtETdqzQeKVjQReP2Eid9wYK67q9z6trvByGZs | |||
#默认私钥的内容(加密的Base58编码数据);在 pk-path 和 pk 之间必须设置其一; | |||
keys.default.privkey=177gk2PbxhHeEdfAAqGfShJQyeV4XvGsJ9CvJFUbToBqwW1YJd5obicySE1St6SvPPaRrUP | |||
#默认私钥的解码密码; | |||
keys.default.privkey-password=8EjkXVSTxMFjCvNNsTo8RBMDEVQmk7gYkW4SCDuvdsBG | |||
```` | |||
@@ -9,19 +9,18 @@ | |||
<relativePath>../project/parent</relativePath> | |||
</parent> | |||
<artifactId>deploy-root</artifactId> | |||
<version>1.3.0.RELEASE</version> | |||
<version>1.4.0.RELEASE</version> | |||
<packaging>pom</packaging> | |||
<properties> | |||
<core.version>1.3.0.RELEASE</core.version> | |||
<kvdb.version>1.0.1.RELEASE</kvdb.version> | |||
<core.version>1.4.0.RELEASE</core.version> | |||
</properties> | |||
<modules> | |||
<module>../core</module> | |||
<module>deploy-gateway</module> | |||
<module>deploy-peer</module> | |||
<module>deploy-kvdb</module> | |||
</modules> | |||
<module>docker</module> | |||
</modules> | |||
</project> |
@@ -1 +1 @@ | |||
Subproject commit 7baa88521acd1043fa03408a693c0d0a2546ad93 | |||
Subproject commit eaee8a2dd0f367f1fd6751f46bd1db527e5a6ba1 |
@@ -1 +1 @@ | |||
Subproject commit b5e7aec41425d85f6374c8bf2a604c69b6adad83 | |||
Subproject commit 02331175672597cbd627396c74ece32bead3f4ce |
@@ -1 +0,0 @@ | |||
Subproject commit 410de24918b6c7214bafe316f5cc734d87c5b433 |
@@ -1 +1 @@ | |||
Subproject commit 26482cf43365583e5d303544ddf05d44a2ad4a41 | |||
Subproject commit f817655c4632ca020411a403e4b7555b250c0dfb |
@@ -0,0 +1 @@ | |||
Subproject commit a264eb1cbdbacad1482e4823ff2fa643af6a3540 |
@@ -5,7 +5,7 @@ | |||
<groupId>com.jd.blockchain</groupId> | |||
<artifactId>jdchain-root</artifactId> | |||
<version>1.2.1.RELEASE</version> | |||
<version>1.4.0.RELEASE</version> | |||
<packaging>pom</packaging> | |||
<description>jdchain root project</description> | |||
@@ -13,7 +13,6 @@ | |||
<module>project</module> | |||
<module>framework</module> | |||
<module>core</module> | |||
<module>kvdb</module> | |||
<module>deploy</module> | |||
<module>test</module> | |||
<module>samples</module> | |||
@@ -0,0 +1,60 @@ | |||
## JD Chain Samples | |||
本项目为`JD Chain SDK`的使用样例,开发者可以参考此项目快速上手`JD Chain SDK`,主要包括[交易发送查询](#交易发送查询),[合约开发部署](#合约开发部署)两部分。 | |||
本项目提供了基于内存的`JD Chain`四节点+网关的网络环境启动程序[TestNet](/sdk-samples/src/main/java/com/jdchain/samples/sdk/TestNet.java),运行`TestNet`的`main`方法启动测试网络,等待日志输出:`START TESTNET SUCCESS`,网络启动成功会写入一些测试数据,可直接运行本项目提供的所有测试用例。 | |||
> `TestNet`测试网络默认会占用`8910`/`8920`/`8930`/`8940`/`8911`/`8921`/`8931`/`8941`用于共识服务,`12000`/`12010`/`12020`/`12030`用于四节点`API`服务端口,`11000`用于网关`API`服务端口,启动前请检查相关端口可用。 | |||
### 交易发送查询 | |||
相关代码放在[sdk-sample](/sdk-samples/src)下。 | |||
> 若并非使用`TestNet`启动的测试网络,开发者在运行本样例前,请根据实际环境修改[config.properties](/sdk-samples/src/main/resources/config.properties)中的网关配置,用户配置等信息。 | |||
#### 交易发送 | |||
参照[UserSample](/sdk-samples/src/test/java/com/jdchain/samples/sdk/UserSample.java)实现注册用户,配置用户角色权限功能; | |||
参照[DataAccountSample](/sdk-samples/src/test/java/com/jdchain/samples/sdk/DataAccountSample.java)实现注册数据账户,存储`KV`数据功能; | |||
参照[EventSample](/sdk-samples/src/test/java/com/jdchain/samples/sdk/EventSample.java)实现注册事件账户,发布事件,事件监听功能; | |||
参照[ContractSample](/sdk-samples/src/test/java/com/jdchain/samples/sdk/ContractSample.java)实现合约调用,非插件方式合约部署功能。 | |||
#### 数据查询 | |||
参照[QuerySample](/sdk-samples/src/test/java/com/jdchain/samples/sdk/QuerySample.java)实现对于区块链上数据查询功能。 | |||
### 合约开发部署 | |||
[contract-samples](/contract-samples/src)提供了通过合约注册用户,注册数据账户,注册事件账户,设置`KV`,发布事件的简单合约样例。 | |||
> 若并非使用`TestNet`启动的测试网络,开发者在运行本样例前,请根据实际环境修改[pom.xml](/contract-samples/pom.xml)中的网关配置,用户配置等信息。 | |||
修改相关代码,确认配置正确,`contract-samples`项目目录下命令行执行: | |||
- 合约打包 | |||
```bash | |||
mvn clean package | |||
``` | |||
可以生成`car`包,可以用于`SDK`方式合约部署。 | |||
- 合约部署 | |||
```bash | |||
mvn clean deploy | |||
``` | |||
可以直接部署合约上链。 | |||
### 了解更多 | |||
访问[JD Chain官网](http://ledger.jd.com/)查阅设计及文档。 | |||
访问[github主页](https://github.com/blockchain-jd-com)阅读`JD Chain`源码并参与社区建设。 | |||
Thanks~ |
@@ -4,73 +4,79 @@ | |||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> | |||
<modelVersion>4.0.0</modelVersion> | |||
<parent> | |||
<groupId>com.jd.blockchain</groupId> | |||
<artifactId>jdchain-samples</artifactId> | |||
<version>1.2.1.RELEASE</version> | |||
</parent> | |||
<groupId>com.jd.blockchain</groupId> | |||
<artifactId>jdchain-samples</artifactId> | |||
<version>1.4.0.RELEASE</version> | |||
</parent> | |||
<artifactId>contract-samples</artifactId> | |||
<!-- 声明为合约代码工程,编译输出扩展名为".car"合约代码 --> | |||
<packaging>contract</packaging> | |||
<artifactId>contract-samples</artifactId> | |||
<name>contract-samples</name> | |||
<dependencies> | |||
<dependency> | |||
<groupId>com.jd.blockchain</groupId> | |||
<artifactId>ledger-model</artifactId> | |||
<scope>provided</scope> | |||
</dependency> | |||
<dependency> | |||
<groupId>com.jd.blockchain</groupId> | |||
<artifactId>crypto-framework</artifactId> | |||
<artifactId>contract-starter</artifactId> | |||
<version>${framework.version}</version> | |||
<scope>provided</scope> | |||
</dependency> | |||
<dependency> | |||
<groupId>com.alibaba</groupId> | |||
<artifactId>fastjson</artifactId> | |||
</dependency> | |||
</dependencies> | |||
<build> | |||
<plugins> | |||
<plugin> | |||
<artifactId>maven-assembly-plugin</artifactId> | |||
<groupId>org.apache.maven.plugins</groupId> | |||
<artifactId>maven-compiler-plugin</artifactId> | |||
<configuration> | |||
<finalName>complex</finalName> | |||
<appendAssemblyId>false</appendAssemblyId> | |||
<archive> | |||
<manifest> | |||
<mainClass>com.jd.blockchain.contract.ComplexContractImpl</mainClass> | |||
</manifest> | |||
</archive> | |||
<descriptorRefs> | |||
<descriptorRef>jar-with-dependencies</descriptorRef> | |||
</descriptorRefs> | |||
<source>1.8</source> | |||
<target>1.8</target> | |||
<encoding>UTF-8</encoding> | |||
<optimize>false</optimize> | |||
<debug>true</debug> | |||
<showDeprecation>false</showDeprecation> | |||
<showWarnings>false</showWarnings> | |||
</configuration> | |||
<executions> | |||
<execution> | |||
<id>make-assembly</id> | |||
<phase>package</phase> | |||
<goals> | |||
<goal>single</goal> | |||
</goals> | |||
</execution> | |||
</executions> | |||
</plugin> | |||
<!-- 合约编译、打包、发布插件 --> | |||
<plugin> | |||
<groupId>org.apache.maven.plugins</groupId> | |||
<artifactId>maven-deploy-plugin</artifactId> | |||
<version>2.8.2</version> | |||
<groupId>com.jd.blockchain</groupId> | |||
<artifactId>contract-maven-plugin</artifactId> | |||
<version>${framework.version}</version> | |||
<extensions>true</extensions> | |||
<!-- 合约发布配置,不配置时请不要执行deploy阶段 --> | |||
<configuration> | |||
<skip>true</skip> | |||
<!-- <maxCarSize>1</maxCarSize>--> | |||
<!-- <maxCarSizeUnit>MB</maxCarSizeUnit>--> | |||
<deployment> | |||
<!-- 线上网关的配置,必选项 --> | |||
<gateway> | |||
<host>localhost</host> | |||
<port>11000</port> | |||
</gateway> | |||
<!-- 账本,不填默认选择列表第一个 --> | |||
<!-- <ledger>j5uXbSp6V9VCXxHQzp8pFGKoR9NrAkE6TUvfwWxvEVR5HK</ledger>--> | |||
<!-- 更新已存在合约代码 --> | |||
<!-- <contractAddress>--> | |||
<!-- <pubKey></pubKey>--> | |||
<!-- </contractAddress>--> | |||
<!-- 用户信息,必选项,任何一个合约发布都需要拥有者进行签名 --> | |||
<signer> | |||
<pubKey>3snPdw7i7PjVKiTH2VnXZu5H8QmNaSXpnk4ei533jFpuifyjS5zzH9</pubKey> | |||
<privKey>177gjzHTznYdPgWqZrH43W3yp37onm74wYXT4v9FukpCHBrhRysBBZh7Pzdo5AMRyQGJD7x</privKey> | |||
<privKeyPwd>DYu3G8aGTMBW1WrTw76zxQJQU4DHLw9MLyy7peG4LKkY</privKeyPwd> | |||
</signer> | |||
</deployment> | |||
</configuration> | |||
</plugin> | |||
</plugins> | |||
</build> | |||
</project> |
@@ -1,7 +0,0 @@ | |||
package com.jd.blockchain.contract; | |||
@Contract | |||
public interface ComplexContract { | |||
@ContractEvent(name = "read-key") | |||
String read(String address, String key); | |||
} |
@@ -1,12 +0,0 @@ | |||
package com.jd.blockchain.contract; | |||
import com.alibaba.fastjson.JSON; | |||
public class ComplexContractImpl implements ComplexContract { | |||
@Override | |||
public String read(String address, String key) { | |||
String json = JSON.toJSONString(address); | |||
return System.currentTimeMillis() + "" + json; | |||
} | |||
} |
@@ -1,11 +0,0 @@ | |||
package com.jd.blockchain.contract; | |||
@Contract | |||
public interface RandomContract { | |||
@ContractEvent(name = "random-put") | |||
void put(String address, String key, String value); | |||
@ContractEvent(name = "random-putAndGet") | |||
String putAndGet(String address, String key, String value); | |||
} |
@@ -1,43 +0,0 @@ | |||
package com.jd.blockchain.contract; | |||
import com.jd.blockchain.crypto.HashDigest; | |||
import java.util.Random; | |||
public class RandomContractImpl implements RandomContract, EventProcessingAware { | |||
private static final Random RANDOM_TIME = new Random(); | |||
private ContractEventContext eventContext; | |||
private HashDigest ledgerHash; | |||
@Override | |||
public void beforeEvent(ContractEventContext eventContext) { | |||
this.eventContext = eventContext; | |||
this.ledgerHash = eventContext.getCurrentLedgerHash(); | |||
} | |||
@Override | |||
public void postEvent(ContractEventContext eventContext, Exception error) { | |||
} | |||
@Override | |||
public void put(String address, String key, String value) { | |||
String saveVal = value + "-" + RANDOM_TIME.nextInt(1024); | |||
eventContext.getLedger().dataAccount(address).setText(key, saveVal, -1L); | |||
} | |||
@Override | |||
public String putAndGet(String address, String key, String value) { | |||
String saveVal = value + "-" + RANDOM_TIME.nextInt(1024); | |||
eventContext.getLedger().dataAccount(address).setText(key, saveVal, -1L); | |||
return address; | |||
} | |||
} |
@@ -1,15 +0,0 @@ | |||
package com.jd.blockchain.contract; | |||
@Contract | |||
public interface ReadContract { | |||
@ContractEvent(name = "read-key") | |||
String read(String address, String key); | |||
@ContractEvent(name = "version-key") | |||
Long readVersion(String address, String key); | |||
int test(); | |||
} | |||
@@ -1,50 +0,0 @@ | |||
package com.jd.blockchain.contract; | |||
import com.jd.blockchain.crypto.HashDigest; | |||
import com.jd.blockchain.ledger.TypedKVEntry; | |||
@Contract | |||
public class ReadContractImpl implements EventProcessingAware, ReadContract { | |||
private ContractEventContext eventContext; | |||
private HashDigest ledgerHash; | |||
@Override | |||
public void beforeEvent(ContractEventContext eventContext) { | |||
this.eventContext = eventContext; | |||
this.ledgerHash = eventContext.getCurrentLedgerHash(); | |||
} | |||
@Override | |||
public void postEvent(ContractEventContext eventContext, Exception error) { | |||
} | |||
@Override | |||
@ContractEvent(name = "read-key") | |||
public String read(String address, String key) { | |||
TypedKVEntry[] kvDataEntries = eventContext.getLedger().getDataEntries(ledgerHash, address, key); | |||
if (kvDataEntries != null && kvDataEntries.length == 1) { | |||
return kvDataEntries[0].getValue().toString(); | |||
} | |||
return null; | |||
} | |||
@Override | |||
@ContractEvent(name = "version-key") | |||
public Long readVersion(String address, String key) { | |||
TypedKVEntry[] kvDataEntries = eventContext.getLedger().getDataEntries(ledgerHash, address, key); | |||
if (kvDataEntries != null && kvDataEntries.length == 1) { | |||
return kvDataEntries[0].getVersion(); | |||
} | |||
return -1L; | |||
} | |||
@Override | |||
public int test() { | |||
return 0; | |||
} | |||
} |
@@ -1,17 +0,0 @@ | |||
package com.jd.blockchain.contract; | |||
@Contract | |||
public interface TransferContract { | |||
@ContractEvent(name = "create") | |||
String create(String address, String account, long money); | |||
@ContractEvent(name = "transfer") | |||
String transfer(String address, String from, String to, long money); | |||
@ContractEvent(name = "read") | |||
long read(String address, String account); | |||
@ContractEvent(name = "readAll") | |||
String readAll(String address, String account); | |||
} |
@@ -1,109 +0,0 @@ | |||
package com.jd.blockchain.contract; | |||
import com.alibaba.fastjson.JSON; | |||
import com.jd.blockchain.crypto.HashDigest; | |||
import com.jd.blockchain.ledger.TypedKVEntry; | |||
import com.jd.blockchain.ledger.KVDataVO; | |||
import com.jd.blockchain.ledger.KVInfoVO; | |||
public class TransferContractImpl implements EventProcessingAware, TransferContract { | |||
private ContractEventContext eventContext; | |||
private HashDigest ledgerHash; | |||
@Override | |||
public String create(String address, String account, long money) { | |||
TypedKVEntry[] kvDataEntries = eventContext.getLedger().getDataEntries(ledgerHash, address, account); | |||
// 肯定有返回值,但若不存在则返回version=-1 | |||
if (kvDataEntries != null && kvDataEntries.length > 0) { | |||
long currVersion = kvDataEntries[0].getVersion(); | |||
if (currVersion > -1) { | |||
throw new IllegalStateException(String.format("%s -> %s already have created !!!", address, account)); | |||
} | |||
eventContext.getLedger().dataAccount(address).setInt64(account, money, -1L); | |||
} else { | |||
throw new IllegalStateException(String.format("Ledger[%s] inner Error !!!", ledgerHash.toBase58())); | |||
} | |||
return String.format("DataAccountAddress[%s] -> Create(By Contract Operation) Account = %s and Money = %s Success!!! \r\n", | |||
address, account, money); | |||
} | |||
@Override | |||
public String transfer(String address, String from, String to, long money) { | |||
// 首先查询余额 | |||
TypedKVEntry[] kvDataEntries = eventContext.getLedger().getDataEntries(ledgerHash, address, from, to); | |||
if (kvDataEntries == null || kvDataEntries.length != 2) { | |||
throw new IllegalStateException(String.format("%s -> %s - %s may be not created !!!", address, from, to)); | |||
} else { | |||
// 判断from账号中钱数量是否足够 | |||
long fromMoney = 0L, toMoney = 0L, fromVersion = 0L, toVersion = 0L; | |||
for (TypedKVEntry kvDataEntry : kvDataEntries) { | |||
if (kvDataEntry.getKey().equals(from)) { | |||
fromMoney = (long) kvDataEntry.getValue(); | |||
fromVersion = kvDataEntry.getVersion(); | |||
} else { | |||
toMoney = (long) kvDataEntry.getValue(); | |||
toVersion = kvDataEntry.getVersion(); | |||
} | |||
} | |||
if (fromMoney < money) { | |||
throw new IllegalStateException(String.format("%s -> %s not have enough money !!!", address, from)); | |||
} | |||
long fromNewMoney = fromMoney - money; | |||
long toNewMoney = toMoney + money; | |||
// 重新设置 | |||
eventContext.getLedger().dataAccount(address).setInt64(from, fromNewMoney, fromVersion); | |||
eventContext.getLedger().dataAccount(address).setInt64(to, toNewMoney, toVersion); | |||
} | |||
return String.format("DataAccountAddress[%s] transfer from [%s] to [%s] and [money = %s] Success !!!", address, from, to, money); | |||
} | |||
@Override | |||
public long read(String address, String account) { | |||
TypedKVEntry[] kvDataEntries = eventContext.getLedger().getDataEntries(ledgerHash, address, account); | |||
if (kvDataEntries == null || kvDataEntries.length == 0) { | |||
return -1; | |||
} | |||
return (long)kvDataEntries[0].getValue(); | |||
} | |||
@Override | |||
public String readAll(String address, String account) { | |||
TypedKVEntry[] kvDataEntries = eventContext.getLedger().getDataEntries(ledgerHash, address, account); | |||
// 获取最新的版本号 | |||
if (kvDataEntries == null || kvDataEntries.length == 0) { | |||
return ""; | |||
} | |||
long newestVersion = kvDataEntries[0].getVersion(); | |||
if (newestVersion == -1) { | |||
return ""; | |||
} | |||
KVDataVO[] kvDataVOS = new KVDataVO[1]; | |||
long[] versions = new long[(int)newestVersion + 1]; | |||
for (int i = 0; i < versions.length; i++) { | |||
versions[i] = i; | |||
} | |||
KVDataVO kvDataVO = new KVDataVO(account, versions); | |||
kvDataVOS[0] = kvDataVO; | |||
KVInfoVO kvInfoVO = new KVInfoVO(kvDataVOS); | |||
TypedKVEntry[] allEntries = eventContext.getLedger().getDataEntries(ledgerHash, address, kvInfoVO); | |||
return JSON.toJSONString(allEntries); | |||
} | |||
@Override | |||
public void beforeEvent(ContractEventContext eventContext) { | |||
this.eventContext = eventContext; | |||
this.ledgerHash = eventContext.getCurrentLedgerHash(); | |||
} | |||
@Override | |||
public void postEvent(ContractEventContext eventContext, Exception error) { | |||
} | |||
} |
@@ -0,0 +1,77 @@ | |||
package com.jdchain.samples.contract; | |||
import com.jd.blockchain.contract.Contract; | |||
import com.jd.blockchain.contract.ContractEvent; | |||
/** | |||
* 合约样例,提供通过合约创建用户/数据账户/事件账户,写入KV,发布事件等功能 | |||
*/ | |||
@Contract | |||
public interface SampleContract { | |||
/** | |||
* 设置KV | |||
* | |||
* @param address 数据账户地址 | |||
* @param key 键 | |||
* @param value 值 | |||
* @param version 版本 | |||
*/ | |||
@ContractEvent(name = "setKVWithVersion") | |||
void setKVWithVersion(String address, String key, String value, long version); | |||
/** | |||
* 设置KV,基于最新数据版本 | |||
* | |||
* @param address 数据账户地址 | |||
* @param key 键 | |||
* @param value 值 | |||
*/ | |||
@ContractEvent(name = "setKV") | |||
void setKV(String address, String key, String value); | |||
/** | |||
* 注册用户 | |||
* | |||
* @param seed 种子,不小于32个字符 | |||
*/ | |||
@ContractEvent(name = "registerUser") | |||
String registerUser(String seed); | |||
/** | |||
* 注册数据账户 | |||
* | |||
* @param seed 种子,不小于32个字符 | |||
*/ | |||
@ContractEvent(name = "registerDataAccount") | |||
String registerDataAccount(String seed); | |||
/** | |||
* 注册事件账户 | |||
* | |||
* @param seed 种子,不小于32个字符 | |||
*/ | |||
@ContractEvent(name = "registerEventAccount") | |||
String registerEventAccount(String seed); | |||
/** | |||
* 发布事件 | |||
* | |||
* @param address 事件账户地址 | |||
* @param topic 消息名称 | |||
* @param content 内容 | |||
* @param sequence 当前消息名称下最大序号(初始为-1) | |||
*/ | |||
@ContractEvent(name = "publishEventWithSequence") | |||
void publishEventWithSequence(String address, String topic, String content, long sequence); | |||
/** | |||
* 发布事件,基于最新时间序号 | |||
* | |||
* @param address 事件账户地址 | |||
* @param topic 消息名称 | |||
* @param content 内容 | |||
*/ | |||
@ContractEvent(name = "publishEvent") | |||
void publishEvent(String address, String topic, String content); | |||
} |
@@ -0,0 +1,106 @@ | |||
package com.jdchain.samples.contract; | |||
import com.jd.blockchain.contract.ContractEventContext; | |||
import com.jd.blockchain.contract.EventProcessingAware; | |||
import com.jd.blockchain.crypto.AsymmetricKeypair; | |||
import com.jd.blockchain.crypto.Crypto; | |||
import com.jd.blockchain.crypto.CryptoAlgorithm; | |||
import com.jd.blockchain.crypto.SignatureFunction; | |||
import com.jd.blockchain.ledger.BlockchainKeypair; | |||
import com.jd.blockchain.ledger.Event; | |||
import com.jd.blockchain.ledger.TypedKVEntry; | |||
import com.jd.blockchain.utils.Bytes; | |||
/** | |||
* 合约样例实现 | |||
*/ | |||
public class SampleContractImpl implements EventProcessingAware, SampleContract { | |||
private ContractEventContext eventContext; | |||
@Override | |||
public void setKVWithVersion(String address, String key, String value, long version) { | |||
eventContext.getLedger().dataAccount(Bytes.fromBase58(address)).setText(key, value, version); | |||
} | |||
@Override | |||
public void setKV(String address, String key, String value) { | |||
// 查询最新版本,初始为-1 | |||
TypedKVEntry[] entries = eventContext.getLedger().getDataEntries(eventContext.getCurrentLedgerHash(), address, key); | |||
long version = -1; | |||
if (null != entries && entries.length > 0) { | |||
version = entries[0].getVersion(); | |||
} | |||
eventContext.getLedger().dataAccount(Bytes.fromBase58(address)).setText(key, value, version); | |||
} | |||
@Override | |||
public String registerUser(String seed) { | |||
CryptoAlgorithm algorithm = Crypto.getAlgorithm("ed25519"); | |||
SignatureFunction signFunc = Crypto.getSignatureFunction(algorithm); | |||
AsymmetricKeypair cryptoKeyPair = signFunc.generateKeypair(seed.getBytes()); | |||
BlockchainKeypair keypair = new BlockchainKeypair(cryptoKeyPair.getPubKey(), cryptoKeyPair.getPrivKey()); | |||
eventContext.getLedger().users().register(keypair.getIdentity()); | |||
return keypair.getAddress().toBase58(); | |||
} | |||
@Override | |||
public String registerDataAccount(String seed) { | |||
CryptoAlgorithm algorithm = Crypto.getAlgorithm("ed25519"); | |||
SignatureFunction signFunc = Crypto.getSignatureFunction(algorithm); | |||
AsymmetricKeypair cryptoKeyPair = signFunc.generateKeypair(seed.getBytes()); | |||
BlockchainKeypair keypair = new BlockchainKeypair(cryptoKeyPair.getPubKey(), cryptoKeyPair.getPrivKey()); | |||
eventContext.getLedger().dataAccounts().register(keypair.getIdentity()); | |||
return keypair.getAddress().toBase58(); | |||
} | |||
@Override | |||
public String registerEventAccount(String seed) { | |||
CryptoAlgorithm algorithm = Crypto.getAlgorithm("ed25519"); | |||
SignatureFunction signFunc = Crypto.getSignatureFunction(algorithm); | |||
AsymmetricKeypair cryptoKeyPair = signFunc.generateKeypair(seed.getBytes()); | |||
BlockchainKeypair keypair = new BlockchainKeypair(cryptoKeyPair.getPubKey(), cryptoKeyPair.getPrivKey()); | |||
eventContext.getLedger().eventAccounts().register(keypair.getIdentity()); | |||
return keypair.getAddress().toBase58(); | |||
} | |||
@Override | |||
public void publishEventWithSequence(String address, String topic, String content, long sequence) { | |||
eventContext.getLedger().eventAccount(Bytes.fromBase58(address)).publish(topic, content, sequence); | |||
} | |||
@Override | |||
public void publishEvent(String address, String topic, String content) { | |||
// 查询最新序号,初始为-1 | |||
Event event = eventContext.getLedger().getLatestEvent(eventContext.getCurrentLedgerHash(), address, topic); | |||
long sequence = -1; | |||
if (null != event) { | |||
sequence = event.getSequence(); | |||
} | |||
eventContext.getLedger().eventAccount(Bytes.fromBase58(address)).publish(topic, content, sequence); | |||
} | |||
/** | |||
* 合约方法调用前操作 | |||
* | |||
* @param eventContext | |||
*/ | |||
@Override | |||
public void beforeEvent(ContractEventContext eventContext) { | |||
this.eventContext = eventContext; | |||
} | |||
/** | |||
* 合约方法调用后操作 | |||
* | |||
* @param eventContext | |||
* @param error | |||
*/ | |||
@Override | |||
public void postEvent(ContractEventContext eventContext, Exception error) { | |||
} | |||
} |
@@ -1,50 +1,40 @@ | |||
<project xmlns="http://maven.apache.org/POM/4.0.0" | |||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | |||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> | |||
<modelVersion>4.0.0</modelVersion> | |||
<parent> | |||
<groupId>com.jd.blockchain</groupId> | |||
<artifactId>jdchain-parent</artifactId> | |||
<version>1.1.4.RELEASE</version> | |||
<relativePath>../project/parent</relativePath> | |||
</parent> | |||
<groupId>com.jd.blockchain</groupId> | |||
<artifactId>jdchain-samples</artifactId> | |||
<version>1.2.0.RELEASE</version> | |||
<packaging>pom</packaging> | |||
<properties> | |||
<framework.version>1.3.0.RELEASE</framework.version> | |||
</properties> | |||
<modules> | |||
<module>../framework</module> | |||
<module>sdk-samples</module> | |||
<module>contract-samples</module> | |||
</modules> | |||
<dependencyManagement> | |||
<dependencies> | |||
<dependency> | |||
<groupId>com.jd.blockchain</groupId> | |||
<artifactId>sdk-client</artifactId> | |||
<version>${framework.version}</version> | |||
</dependency> | |||
<dependency> | |||
<groupId>com.jd.blockchain</groupId> | |||
<artifactId>ledger-model</artifactId> | |||
<version>${framework.version}</version> | |||
</dependency> | |||
<dependency> | |||
<groupId>com.jd.blockchain</groupId> | |||
<artifactId>crypto-framework</artifactId> | |||
<version>${framework.version}</version> | |||
</dependency> | |||
</dependencies> | |||
</dependencyManagement> | |||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | |||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> | |||
<modelVersion>4.0.0</modelVersion> | |||
<groupId>com.jd.blockchain</groupId> | |||
<artifactId>jdchain-samples</artifactId> | |||
<version>1.4.0.RELEASE</version> | |||
<packaging>pom</packaging> | |||
<properties> | |||
<framework.version>1.4.0.RELEASE</framework.version> | |||
</properties> | |||
<modules> | |||
<module>sdk-samples</module> | |||
<module>contract-samples</module> | |||
</modules> | |||
<build> | |||
<plugins> | |||
<plugin> | |||
<groupId>org.apache.maven.plugins</groupId> | |||
<artifactId>maven-compiler-plugin</artifactId> | |||
<version>3.8.1</version> | |||
<configuration> | |||
<source>1.8</source> | |||
<target>1.8</target> | |||
<encoding>UTF-8</encoding> | |||
<optimize>false</optimize> | |||
<debug>true</debug> | |||
<showDeprecation>false</showDeprecation> | |||
<showWarnings>false</showWarnings> | |||
</configuration> | |||
</plugin> | |||
</plugins> | |||
</build> | |||
</project> |
@@ -1,46 +1,79 @@ | |||
<project xmlns="http://maven.apache.org/POM/4.0.0" | |||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | |||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> | |||
<modelVersion>4.0.0</modelVersion> | |||
<parent> | |||
<groupId>com.jd.blockchain</groupId> | |||
<artifactId>jdchain-samples</artifactId> | |||
<version>1.2.1.RELEASE</version> | |||
</parent> | |||
<artifactId>sdk-samples</artifactId> | |||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | |||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> | |||
<modelVersion>4.0.0</modelVersion> | |||
<parent> | |||
<groupId>com.jd.blockchain</groupId> | |||
<artifactId>jdchain-samples</artifactId> | |||
<version>1.4.0.RELEASE</version> | |||
</parent> | |||
<artifactId>sdk-samples</artifactId> | |||
<dependencies> | |||
<dependency> | |||
<groupId>com.jd.blockchain</groupId> | |||
<artifactId>sdk-client</artifactId> | |||
</dependency> | |||
<dependency> | |||
<groupId>com.jd.blockchain</groupId> | |||
<artifactId>ledger-model</artifactId> | |||
</dependency> | |||
<dependency> | |||
<groupId>com.jd.blockchain</groupId> | |||
<artifactId>contract-samples</artifactId> | |||
<version>${project.version}</version> | |||
</dependency> | |||
</dependencies> | |||
<dependencies> | |||
<!--以下依赖用于SDK常规使用--> | |||
<dependency> | |||
<groupId>com.jd.blockchain</groupId> | |||
<artifactId>sdk-client</artifactId> | |||
<version>${framework.version}</version> | |||
</dependency> | |||
<build> | |||
<plugins> | |||
<plugin> | |||
<groupId>org.apache.maven.plugins</groupId> | |||
<artifactId>maven-deploy-plugin</artifactId> | |||
<configuration> | |||
<skip>true</skip> | |||
</configuration> | |||
</plugin> | |||
<!--<plugin> --> | |||
<!--<groupId>org.springframework.boot</groupId> --> | |||
<!--<artifactId>spring-boot-maven-plugin</artifactId> --> | |||
<!--<configuration> --> | |||
<!--<mainClass>com.jd.blockchain.sdk.samples.SDKDemo_RegisterTest</mainClass> --> | |||
<!--</configuration> --> | |||
<!--</plugin> --> | |||
</plugins> | |||
</build> | |||
<dependency> | |||
<groupId>com.jd.blockchain</groupId> | |||
<artifactId>sdk-rpc</artifactId> | |||
<version>${framework.version}</version> | |||
</dependency> | |||
<dependency> | |||
<groupId>com.jd.blockchain</groupId> | |||
<artifactId>crypto-classic</artifactId> | |||
<version>${framework.version}</version> | |||
</dependency> | |||
<dependency> | |||
<groupId>com.jd.blockchain</groupId> | |||
<artifactId>ledger-model</artifactId> | |||
<version>${framework.version}</version> | |||
</dependency> | |||
<!--样例程序中使用到的合约--> | |||
<dependency> | |||
<groupId>com.jd.blockchain</groupId> | |||
<artifactId>contract-samples</artifactId> | |||
<version>${framework.version}</version> | |||
</dependency> | |||
<!--以下依赖用于 com.jdchain.samples.Network 中四节点网路环境初始化和启动 --> | |||
<dependency> | |||
<groupId>org.reflections</groupId> | |||
<artifactId>reflections</artifactId> | |||
<version>0.9.12</version> | |||
</dependency> | |||
<dependency> | |||
<groupId>com.jd.blockchain</groupId> | |||
<artifactId>tools-initializer</artifactId> | |||
<version>${framework.version}</version> | |||
</dependency> | |||
<dependency> | |||
<groupId>com.jd.blockchain</groupId> | |||
<artifactId>peer</artifactId> | |||
<version>${framework.version}</version> | |||
</dependency> | |||
<dependency> | |||
<groupId>com.jd.blockchain</groupId> | |||
<artifactId>utils-common</artifactId> | |||
<version>${framework.version}</version> | |||
</dependency> | |||
<dependency> | |||
<groupId>com.jd.blockchain</groupId> | |||
<artifactId>gateway</artifactId> | |||
<version>${framework.version}</version> | |||
</dependency> | |||
<!--Junit--> | |||
<dependency> | |||
<groupId>junit</groupId> | |||
<artifactId>junit</artifactId> | |||
<version>4.12</version> | |||
</dependency> | |||
</dependencies> | |||
</project> |
@@ -1,93 +0,0 @@ | |||
package com.jd.blockchain.contract; | |||
import com.jd.blockchain.utils.BaseConstant; | |||
import com.jd.blockchain.utils.ConsoleUtils; | |||
import com.jd.blockchain.utils.io.FileUtils; | |||
import org.slf4j.Logger; | |||
import org.slf4j.LoggerFactory; | |||
import org.springframework.core.io.ClassPathResource; | |||
import java.io.*; | |||
import java.util.*; | |||
import static com.jd.blockchain.utils.BaseConstant.SYS_CONTRACT_CONF; | |||
import static com.jd.blockchain.utils.BaseConstant.SYS_CONTRACT_PROPS_NAME; | |||
/** | |||
* | |||
* @author zhaogw | |||
* date 2019/3/15 18:22 | |||
*/ | |||
public enum ContractConfigure { | |||
instance(); | |||
private static final Logger LOGGER = LoggerFactory.getLogger(ContractConfigure.class); | |||
static Properties pp; | |||
ContractConfigure(){ | |||
init(); | |||
} | |||
private void init(){ | |||
String contractConfPath = System.getProperty(SYS_CONTRACT_CONF); | |||
System.out.println("contractConfPath="+contractConfPath); | |||
try { | |||
if (contractConfPath == null) { | |||
ConsoleUtils.info("Load build-in default contractConf in ContractConfigure ..."); | |||
ClassPathResource contractConfigResource = new ClassPathResource(SYS_CONTRACT_PROPS_NAME); | |||
InputStream in = contractConfigResource.getInputStream(); | |||
pp = FileUtils.readProperties(in, BaseConstant.CHARSET_UTF_8); | |||
} else { | |||
ConsoleUtils.info("Load configuration in ContractConfigure,contractConfPath="+contractConfPath); | |||
File file = new File(contractConfPath); | |||
pp = FileUtils.readProperties(file, BaseConstant.CHARSET_UTF_8); | |||
} | |||
} catch (Exception e) { | |||
LOGGER.info(SYS_CONTRACT_PROPS_NAME+"文件异常!"+e.getMessage()); | |||
} | |||
} | |||
public String values(String key) { | |||
if(pp == null){ | |||
init(); | |||
} | |||
return pp.getProperty(key); | |||
} | |||
public String allValues() { | |||
if(pp == null){ | |||
init(); | |||
} | |||
Set<String> allKeys = pp.stringPropertyNames(); | |||
List<String> propList = new ArrayList(); | |||
for(String _key : allKeys){ | |||
String value = pp.getProperty(_key); | |||
propList.add(_key+": "+value); | |||
LOGGER.info("key={}, value={}",_key,value); | |||
} | |||
return propList.toString(); | |||
} | |||
//写入资源文件信息 | |||
public static void writeProperties(String fileAllName, String comments, Map<String,String> map){ | |||
Properties properties=new Properties(); | |||
try { | |||
File file = new File(fileAllName); | |||
if (!file.getParentFile().exists()) { | |||
boolean result = file.getParentFile().mkdirs(); | |||
if (!result) { | |||
System.out.println("文件创建失败."); | |||
} | |||
} | |||
OutputStream outputStream=new FileOutputStream(file); | |||
for(Map.Entry<String,String> entry : map.entrySet()){ | |||
properties.setProperty(entry.getKey(), entry.getValue()); | |||
} | |||
properties.store(outputStream, comments); | |||
outputStream.close(); | |||
} catch (FileNotFoundException e) { | |||
e.printStackTrace(); | |||
} catch (IOException e) { | |||
e.printStackTrace(); | |||
} | |||
} | |||
} |
@@ -1,35 +0,0 @@ | |||
package com.jd.blockchain.contract.samples; | |||
import com.jd.blockchain.contract.Contract; | |||
import com.jd.blockchain.contract.ContractEvent; | |||
/** | |||
* 示例:一个“资产管理”智能合约; | |||
* | |||
* @author huanghaiquan | |||
* | |||
*/ | |||
@Contract | |||
public interface AssetContract { | |||
/** | |||
* 发行资产; | |||
* | |||
* @param amount 新发行的资产数量; | |||
* @param assetHolderAddress 新发行的资产的持有账户; | |||
*/ | |||
@ContractEvent(name = "issue-asset") | |||
void issue(long amount, String assetHolderAddress); | |||
/** | |||
* 转移资产 | |||
* | |||
* @param fromAddress 转出账户; | |||
* @param toAddress 转入账户; | |||
* @param amount 转移的资产数额; | |||
* @return 返回转出账户的余额; | |||
*/ | |||
@ContractEvent(name = "transfer-asset") | |||
long transfer(String fromAddress, String toAddress, long amount); | |||
} |
@@ -1,53 +0,0 @@ | |||
//package com.jd.blockchain.contract.samples; | |||
// | |||
//import com.jd.blockchain.binaryproto.DataContract; | |||
//import com.jd.blockchain.consts.DataCodes; | |||
//import com.jd.blockchain.contract.Contract; | |||
//import com.jd.blockchain.contract.ContractEvent; | |||
//import com.jd.blockchain.ledger.ContractBizContent; | |||
//import com.jd.blockchain.ledger.TransactionContentBody; | |||
//import com.jd.blockchain.utils.Bytes; | |||
// | |||
//import java.math.BigDecimal; | |||
// | |||
///** | |||
// * 示例:一个“资产管理”智能合约; | |||
// * | |||
// * @author zhaogw | |||
// */ | |||
//@Contract | |||
//public interface AssetContract2 { | |||
// | |||
// /** | |||
// * 发行资产; | |||
// * 新发行的资产数量; | |||
// * @param assetHolderAddress | |||
// * 新发行的资产的持有账户; | |||
// */ | |||
// @ContractEvent(name = "issue-asset-0") | |||
// void issue(ContractBizContent contractBizContent, String assetHolderAddress); | |||
// | |||
// /** | |||
// * issue asset; | |||
// * @param contractBizContent | |||
// * @param assetHolderAddress | |||
// * @param cashNumber | |||
// */ | |||
// @ContractEvent(name = "issue-asset") | |||
// public void issue(ContractBizContent contractBizContent, String assetHolderAddress, long cashNumber); | |||
// | |||
// /** | |||
// * Bytes can bring the byte[]; | |||
// * @param bytes | |||
// * @param assetHolderAddress | |||
// * @param cashNumber | |||
// */ | |||
// @ContractEvent(name = "issue-asset-2") | |||
// void issue(Bytes bytes,String assetHolderAddress, long cashNumber); | |||
// | |||
// @ContractEvent(name = "issue-asset-3") | |||
// void issue(Byte bytes, String assetHolderAddress, long cashNumber); | |||
// | |||
// @ContractEvent(name = "issue-asset-4") | |||
// void issue(Byte byteObj, String assetHolderAddress, Bytes cashNumber); | |||
//} |
@@ -1,173 +0,0 @@ | |||
package com.jd.blockchain.contract.samples; | |||
import java.util.HashMap; | |||
import java.util.Map; | |||
import java.util.Set; | |||
import com.jd.blockchain.contract.ContractEventContext; | |||
import com.jd.blockchain.contract.ContractException; | |||
import com.jd.blockchain.contract.EventProcessingAware; | |||
import com.jd.blockchain.crypto.HashDigest; | |||
import com.jd.blockchain.ledger.BlockchainIdentity; | |||
import com.jd.blockchain.ledger.TypedKVEntry; | |||
import com.jd.blockchain.ledger.TypedKVData; | |||
import com.jd.blockchain.utils.Bytes; | |||
/** | |||
* 示例:一个“资产管理”智能合约的实现; | |||
* | |||
* 注: 1、实现 EventProcessingAwire 接口以便合约实例在运行时可以从上下文获得合约生命周期事件的通知; 2、实现 | |||
* AssetContract 接口定义的合约方法; | |||
* | |||
* @author huanghaiquan | |||
* | |||
*/ | |||
public class AssetContractImpl implements EventProcessingAware, AssetContract { | |||
// 资产管理账户的地址; | |||
private static final String ASSET_ADDRESS = "2njZBNbFQcmKd385DxVejwSjy4driRzf9Pk"; | |||
// 保存资产总数的键; | |||
private static final String KEY_TOTAL = "TOTAL"; | |||
// 合约事件上下文; | |||
private ContractEventContext eventContext; | |||
/** | |||
* ------------------- 定义可以由外部用户通过提交“交易”触发的调用方法 ------------------ | |||
*/ | |||
@Override | |||
public void issue(long amount, String assetHolderAddress) { | |||
checkAllOwnersAgreementPermission(); | |||
// 新发行的资产数量; | |||
if (amount < 0) { | |||
throw new ContractException("The amount is negative!"); | |||
} | |||
if (amount == 0) { | |||
return; | |||
} | |||
// 查询当前值; | |||
TypedKVEntry[] kvEntries = eventContext.getLedger().getDataEntries(currentLedgerHash(), ASSET_ADDRESS, KEY_TOTAL, | |||
assetHolderAddress); | |||
// 计算资产的发行总数; | |||
TypedKVData currTotal = (TypedKVData) kvEntries[0]; | |||
long newTotal = currTotal.longValue() + amount; | |||
eventContext.getLedger().dataAccount(ASSET_ADDRESS).setInt64(KEY_TOTAL, newTotal, currTotal.getVersion()); | |||
// 分配到持有者账户; | |||
TypedKVData holderAmount = (TypedKVData) kvEntries[1]; | |||
long newHodlerAmount = holderAmount.longValue() + amount; | |||
eventContext.getLedger().dataAccount(ASSET_ADDRESS) | |||
.setInt64(assetHolderAddress, newHodlerAmount, holderAmount.getVersion()).setText("K2", "info2", -1) | |||
.setText("k3", "info3", 3); | |||
} | |||
@Override | |||
public long transfer(String fromAddress, String toAddress, long amount) { | |||
if (amount < 0) { | |||
throw new ContractException("The amount is negative!"); | |||
} | |||
if (amount > 20000) { | |||
throw new ContractException("The amount exceeds the limit of 20000!"); | |||
} | |||
// 校验“转出账户”是否已签名; | |||
checkSignerPermission(fromAddress); | |||
// 查询现有的余额; | |||
TypedKVEntry[] origBalances = eventContext.getLedger().getDataEntries(currentLedgerHash(), ASSET_ADDRESS, | |||
fromAddress, toAddress); | |||
TypedKVEntry fromBalanceKV = origBalances[0]; | |||
TypedKVEntry toBalanceKV = origBalances[1]; | |||
long fromBalance = fromBalanceKV.getVersion() == -1 ? 0 : (long) fromBalanceKV.getValue(); | |||
long toBalance = toBalanceKV.getVersion() == -1 ? 0 : (long) toBalanceKV.getValue(); | |||
// 检查是否余额不足; | |||
if ((fromBalance - amount) < 0) { | |||
throw new ContractException("The balance is insufficient and the transfer failed!"); | |||
} | |||
fromBalance = fromBalance + amount; | |||
toBalance = toBalance + amount; | |||
// 把数据的更改写入到账本; | |||
eventContext.getLedger().dataAccount(fromAddress).setInt64(ASSET_ADDRESS, fromBalance, fromBalanceKV.getVersion()); | |||
eventContext.getLedger().dataAccount(toAddress).setInt64(ASSET_ADDRESS, toBalance, toBalanceKV.getVersion()); | |||
return -1; | |||
} | |||
// ------------------------------------------------------------- | |||
// ------------------- 定义只在合约内部调用的方法 ------------------ | |||
// ------------------------------------------------------------- | |||
/** | |||
* 只有全部的合约拥有者同意才能通过校验; | |||
*/ | |||
private void checkAllOwnersAgreementPermission() { | |||
Set<BlockchainIdentity> owners = eventContext.getContracOwners(); | |||
Set<BlockchainIdentity> requestors = eventContext.getTxSigners(); | |||
if (requestors.size() != owners.size()) { | |||
throw new ContractException("Permission Error! -- The requestors is not exactlly being owners!"); | |||
} | |||
Map<Bytes, BlockchainIdentity> ownerMap = new HashMap<>(); | |||
for (BlockchainIdentity o : owners) { | |||
ownerMap.put(o.getAddress(), o); | |||
} | |||
for (BlockchainIdentity r : requestors) { | |||
if (!ownerMap.containsKey(r.getAddress())) { | |||
throw new ContractException("Permission Error! -- No agreement of all owners!"); | |||
} | |||
} | |||
} | |||
private HashDigest currentLedgerHash() { | |||
return eventContext.getCurrentLedgerHash(); | |||
} | |||
/** | |||
* 校验指定的账户是否签署了当前交易; | |||
* | |||
* @param address | |||
*/ | |||
private void checkSignerPermission(String address) { | |||
Set<BlockchainIdentity> requestors = eventContext.getTxSigners(); | |||
for (BlockchainIdentity r : requestors) { | |||
if (r.getAddress().equals(address)) { | |||
return; | |||
} | |||
} | |||
throw new ContractException("Permission Error! -- No signature !"); | |||
} | |||
// ---------------------------------------------------------- | |||
// ------------------- 在运行时捕捉上下文事件 ------------------ | |||
// ---------------------------------------------------------- | |||
/* | |||
* (non-Javadoc) | |||
* | |||
* @see | |||
* com.jd.blockchain.contract.model.EventProcessingAwire#beforeEvent(com.jd. | |||
* blockchain.contract.model.ContractEventContext) | |||
*/ | |||
@Override | |||
public void beforeEvent(ContractEventContext eventContext) { | |||
this.eventContext = eventContext; | |||
} | |||
/* | |||
* (non-Javadoc) | |||
* | |||
* @see com.jd.blockchain.contract.model.EventProcessingAwire#postEvent(com.jd. | |||
* blockchain.contract.model.ContractEventContext, | |||
* com.jd.blockchain.contract.model.ContractError) | |||
*/ | |||
@Override | |||
public void postEvent(ContractEventContext eventContext, Exception error) { | |||
this.eventContext = null; | |||
} | |||
} |
@@ -1,69 +0,0 @@ | |||
package com.jd.blockchain.sdk.samples; | |||
import com.jd.blockchain.ledger.TransactionResponse; | |||
import com.jd.blockchain.utils.http.ResponseConverter; | |||
import com.jd.blockchain.utils.web.client.WebResponseConverter; | |||
import org.apache.http.HttpResponse; | |||
import org.apache.http.client.HttpClient; | |||
import org.apache.http.client.entity.UrlEncodedFormEntity; | |||
import org.apache.http.client.methods.HttpPost; | |||
import org.apache.http.impl.client.HttpClients; | |||
import org.apache.http.message.BasicNameValuePair; | |||
import java.util.ArrayList; | |||
import java.util.List; | |||
/** | |||
* @Author: zhangshuang | |||
* @Date: 2020/5/27 5:18 PM | |||
* Version 1.0 | |||
*/ | |||
public class SDKDemo_ActiveParticipant { | |||
// 接受激活参与方操作的共识节点Http服务地址, 根据具体环境配置进行修改 | |||
private static String httpIp = "127.0.0.1"; | |||
private static String httpPort = "7085"; | |||
public static void main(String[] args) { | |||
String url = "http://" + httpIp + ":" + httpPort + "/management/delegate/activeparticipant"; | |||
System.out.println("url = " + url); | |||
HttpPost httpPost = new HttpPost(url); | |||
List<BasicNameValuePair> para=new ArrayList<BasicNameValuePair>(); | |||
// 账本值根据具体情况进行修改 | |||
BasicNameValuePair base58LedgerHash = new BasicNameValuePair("ledgerHash", "j5n3SmYT3rS5aDgwQbDUxBYUMEP9GvVfMiQK3Tcr3vxz3M"); | |||
// 激活的新参与方的共识网络地址 | |||
BasicNameValuePair host = new BasicNameValuePair("consensusHost", "127.0.0.1"); | |||
BasicNameValuePair port = new BasicNameValuePair("consensusPort", "20000"); | |||
// 指定已经启动的其他共识节点的HTTP管理端口 | |||
BasicNameValuePair manageHost = new BasicNameValuePair("remoteManageHost", "127.0.0.1"); | |||
BasicNameValuePair managePort = new BasicNameValuePair("remoteManagePort", "12000"); | |||
para.add(base58LedgerHash); | |||
para.add(host); | |||
para.add(port); | |||
para.add(manageHost); | |||
para.add(managePort); | |||
try { | |||
httpPost.setEntity(new UrlEncodedFormEntity(para,"UTF-8")); | |||
HttpClient httpClient = HttpClients.createDefault(); | |||
HttpResponse response = httpClient.execute(httpPost); | |||
ResponseConverter responseConverter = new WebResponseConverter(TransactionResponse.class); | |||
Object converterResponse = responseConverter.getResponse(null, response.getEntity().getContent(), null); | |||
System.out.println("response result = " + ((TransactionResponse)converterResponse).getExecutionState()); | |||
} catch (Exception e) { | |||
e.printStackTrace(); | |||
System.out.println("Active participant post request error!"); | |||
} | |||
} | |||
} |
@@ -1,97 +0,0 @@ | |||
/** | |||
* Copyright: Copyright 2016-2020 JD.COM All Right Reserved | |||
* FileName: com.jd.blockchain.sdk.samples.SDKDemo_RegisterUser | |||
* Author: shaozhuguang | |||
* Department: 区块链研发部 | |||
* Date: 2018/10/18 下午2:00 | |||
* Description: 注册用户 | |||
*/ | |||
package com.jd.blockchain.sdk.samples; | |||
import com.jd.blockchain.binaryproto.DataContractRegistry; | |||
import com.jd.blockchain.crypto.AsymmetricKeypair; | |||
import com.jd.blockchain.crypto.HashDigest; | |||
import com.jd.blockchain.crypto.PrivKey; | |||
import com.jd.blockchain.crypto.PubKey; | |||
import com.jd.blockchain.ledger.*; | |||
import com.jd.blockchain.sdk.BlockchainService; | |||
import com.jd.blockchain.sdk.client.GatewayServiceFactory; | |||
import com.jd.blockchain.utils.ConsoleUtils; | |||
/** | |||
* 注册用户 | |||
* | |||
* @author shaozhuguang | |||
* @create 2018/10/18 | |||
* @since 1.0.0 | |||
*/ | |||
public class SDKDemo_ConfigureSecurity { | |||
public static void main(String[] args) { | |||
String GATEWAY_IPADDR = "127.0.0.1"; | |||
int GATEWAY_PORT = 8081; | |||
if (args != null && args.length == 2) { | |||
GATEWAY_IPADDR = args[0]; | |||
GATEWAY_PORT = Integer.parseInt(args[1]); | |||
} | |||
// 注册相关class | |||
DataContractRegistry.register(TransactionContent.class); | |||
DataContractRegistry.register(TransactionContentBody.class); | |||
DataContractRegistry.register(TransactionRequest.class); | |||
DataContractRegistry.register(NodeRequest.class); | |||
DataContractRegistry.register(EndpointRequest.class); | |||
DataContractRegistry.register(TransactionResponse.class); | |||
PrivKey privKey = SDKDemo_Params.privkey1; | |||
PubKey pubKey = SDKDemo_Params.pubKey1; | |||
BlockchainKeypair CLIENT_CERT = new BlockchainKeypair(SDKDemo_Params.pubKey0, SDKDemo_Params.privkey0); | |||
boolean SECURE = false; | |||
GatewayServiceFactory serviceFactory = GatewayServiceFactory.connect(GATEWAY_IPADDR, GATEWAY_PORT, SECURE, | |||
CLIENT_CERT); | |||
BlockchainService service = serviceFactory.getBlockchainService(); | |||
HashDigest[] ledgerHashs = service.getLedgerHashs(); | |||
// 在本地定义注册账号的 TX; | |||
TransactionTemplate txTemp = service.newTransaction(ledgerHashs[0]); | |||
// existed signer | |||
AsymmetricKeypair signer = getSigner(); | |||
BlockchainKeypair user = BlockchainKeyGenerator.getInstance().generate(); | |||
// 注册 | |||
txTemp.users().register(user.getIdentity()); | |||
txTemp.security().roles() | |||
.configure("ADMIN") | |||
.enable(LedgerPermission.REGISTER_USER, LedgerPermission.REGISTER_DATA_ACCOUNT) | |||
.enable(TransactionPermission.DIRECT_OPERATION) | |||
.configure("GUEST") | |||
.enable(TransactionPermission.CONTRACT_OPERATION); | |||
txTemp.security().authorziations() | |||
.forUser(user.getIdentity()) | |||
.authorize("ADMIN", "MANAGER") | |||
.forUser(CLIENT_CERT.getAddress()) | |||
.authorize("GUEST"); | |||
// TX 准备就绪; | |||
PreparedTransaction prepTx = txTemp.prepare(); | |||
// 使用私钥进行签名; | |||
prepTx.sign(signer); | |||
// 提交交易; | |||
TransactionResponse transactionResponse = prepTx.commit(); | |||
ConsoleUtils.info("register user complete, result is [%s]", transactionResponse.isSuccess()); | |||
} | |||
private static AsymmetricKeypair getSigner() { | |||
return new BlockchainKeypair(SDKDemo_Params.pubKey1, SDKDemo_Params.privkey1); | |||
} | |||
} |
@@ -1,53 +0,0 @@ | |||
package com.jd.blockchain.sdk.samples; | |||
import org.apache.commons.io.FileUtils; | |||
import org.springframework.core.io.ClassPathResource; | |||
import java.io.File; | |||
public class SDKDemo_Constant { | |||
public static final String GW_IPADDR = "127.0.0.1"; | |||
// public static final String GW_IPADDR = "192.168.151.41"; | |||
public static final int GW_PORT = 11000; | |||
// public static final int GW_PORT = 18081; | |||
public static final String[] PUB_KEYS = { | |||
"3snPdw7i7PjVKiTH2VnXZu5H8QmNaSXpnk4ei533jFpuifyjS5zzH9", | |||
"3snPdw7i7PajLB35tEau1kmixc6ZrjLXgxwKbkv5bHhP7nT5dhD9eX", | |||
"3snPdw7i7PZi6TStiyc6mzjprnNhgs2atSGNS8wPYzhbKaUWGFJt7x", | |||
"3snPdw7i7PifPuRX7fu3jBjsb3rJRfDe9GtbDfvFJaJ4V4hHXQfhwk"}; | |||
public static final String[] PRIV_KEYS = { | |||
"177gjzHTznYdPgWqZrH43W3yp37onm74wYXT4v9FukpCHBrhRysBBZh7Pzdo5AMRyQGJD7x", | |||
"177gju9p5zrNdHJVEQnEEKF4ZjDDYmAXyfG84V5RPGVc5xFfmtwnHA7j51nyNLUFffzz5UT", | |||
"177gjtwLgmSx5v1hFb46ijh7L9kdbKUpJYqdKVf9afiEmAuLgo8Rck9yu5UuUcHknWJuWaF", | |||
"177gk1pudweTq5zgJTh8y3ENCTwtSFsKyX7YnpuKPo7rKgCkCBXVXh5z2syaTCPEMbuWRns"}; | |||
// public static final String[] PUB_KEYS = { | |||
// "3snPdw7i7PXvEDgq96QyzcKhfWL4mgYspzKwvgXiuAidWb2rkRMgDY", | |||
// "3snPdw7i7PajLB35tEau1kmixc6ZrjLXgxwKbkv5bHhP7nT5dhD9eX", | |||
// "3snPdw7i7PZi6TStiyc6mzjprnNhgs2atSGNS8wPYzhbKaUWGFJt7x", | |||
// "3snPdw7i7PifPuRX7fu3jBjsb3rJRfDe9GtbDfvFJaJ4V4hHXQfhwk"}; | |||
// | |||
// public static final String[] PRIV_KEYS = { | |||
// "177gjsxj2ezADGthZ4tGqWeCAqRAwtNvesPjRnyKqCb1huU8LKZmJ3HGZNMPKWQJK3DP1B2", | |||
// "177gju9p5zrNdHJVEQnEEKF4ZjDDYmAXyfG84V5RPGVc5xFfmtwnHA7j51nyNLUFffzz5UT", | |||
// "177gjtwLgmSx5v1hFb46ijh7L9kdbKUpJYqdKVf9afiEmAuLgo8Rck9yu5UuUcHknWJuWaF", | |||
// "177gk1pudweTq5zgJTh8y3ENCTwtSFsKyX7YnpuKPo7rKgCkCBXVXh5z2syaTCPEMbuWRns"}; | |||
public static final String PASSWORD = "abc"; | |||
public static final byte[] readChainCodes(String contractZip) { | |||
// 构建合约的字节数组; | |||
try { | |||
ClassPathResource contractPath = new ClassPathResource(contractZip); | |||
File contractFile = new File(contractPath.getURI()); | |||
return FileUtils.readFileToByteArray(contractFile); | |||
} catch (Exception e) { | |||
throw new IllegalStateException(e); | |||
} | |||
} | |||
} |
@@ -1,153 +0,0 @@ | |||
package com.jd.blockchain.sdk.samples; | |||
import com.jd.blockchain.contract.samples.AssetContract; | |||
import com.jd.blockchain.crypto.AsymmetricKeypair; | |||
import com.jd.blockchain.crypto.Crypto; | |||
import com.jd.blockchain.crypto.HashDigest; | |||
import com.jd.blockchain.crypto.SignatureFunction; | |||
import com.jd.blockchain.ledger.BlockchainKeyGenerator; | |||
import com.jd.blockchain.ledger.BlockchainKeypair; | |||
import com.jd.blockchain.ledger.PreparedTransaction; | |||
import com.jd.blockchain.ledger.TransactionTemplate; | |||
import com.jd.blockchain.sdk.BlockchainService; | |||
import com.jd.blockchain.sdk.client.GatewayServiceFactory; | |||
import com.jd.blockchain.transaction.ContractReturnValue; | |||
import com.jd.blockchain.transaction.LongValueHolder; | |||
import com.jd.blockchain.utils.io.ByteArray; | |||
import com.jd.blockchain.utils.net.NetworkAddress; | |||
import com.jd.blockchain.utils.serialize.json.JSONSerializeUtils; | |||
/** | |||
* 演示合约执行的过程; | |||
* | |||
* @author huanghaiquan | |||
* | |||
*/ | |||
public class SDKDemo_Contract { | |||
public static BlockchainKeypair CLIENT_CERT = BlockchainKeyGenerator.getInstance().generate("ED25519"); | |||
public static void main(String[] args) { | |||
demoContract(); | |||
} | |||
/** | |||
* 演示合约执行的过程; | |||
*/ | |||
public static void demoContract() { | |||
// 账本地址; | |||
String ledgerAddress = "j5rpuGWVxSuUbU3gK7MDREfui797AjfdHzvAMiSaSzydu7"; | |||
// 节点地址列表; | |||
// NetworkAddress[] peerAddrs = { new NetworkAddress("192.168.10.10", 8080), | |||
// new NetworkAddress("192.168.10.11", 8080), new NetworkAddress("192.168.10.12", 8080), | |||
// new NetworkAddress("192.168.10.13", 8080) }; | |||
// 创建服务代理; | |||
final String GATEWAY_IP = "localhost"; | |||
final int GATEWAY_PORT = 11000; | |||
final boolean SECURE = false; | |||
GatewayServiceFactory serviceFactory = GatewayServiceFactory.connect(GATEWAY_IP, GATEWAY_PORT, SECURE, | |||
CLIENT_CERT); | |||
BlockchainService service = serviceFactory.getBlockchainService(); | |||
HashDigest ledgerHash = getLedgerHash(); | |||
// -------------------------------------- | |||
// 一个贸易账户,贸易结算后的利润将通过一个合约账户来执行利润分配; | |||
// 合约账户被设置为通用的账户,不具备对贸易结算账户的直接权限; | |||
// 只有当前交易发起人具备对贸易账户的直接权限,当交易发起人对交易进行签名之后,权限被间接传递给合约账户; | |||
String commerceAccount = "LdeP13gKE6319LvYPyWAT4UXr2brvpitPRBN1"; | |||
// 处理利润分成的通用业务逻辑的合约账户; | |||
String profitDistributionContract = "LdeP13gKE6319LvYPyWAT4UXr2brvpitPRBN1"; | |||
// 收益人账户; | |||
String receiptorAccount1 = "LdeP13gKE6319LvYPyWAT4UXr2brvpitPRBN1"; | |||
String receiptorAccount2 = "LdeP13gKE6319LvYPyWAT4UXr2brvpitPRBN1"; | |||
// 资产编码; | |||
String assetKey = "RMB-ASSET"; | |||
// 此次待分配利润; | |||
long profit = 1000000; | |||
// 备注信息; | |||
Remark remark = new Remark(); | |||
String remarkJSON = JSONSerializeUtils.serializeToJSON(remark); | |||
// 发起交易; | |||
TransactionTemplate txTemp = service.newTransaction(ledgerHash); | |||
AssetContract assetContract = txTemp.contract(profitDistributionContract, AssetContract.class); | |||
assetContract.issue(1000, receiptorAccount1); | |||
LongValueHolder balance = ContractReturnValue.decode(assetContract.transfer(receiptorAccount1, receiptorAccount2, 600)); | |||
// TX 准备就绪; | |||
PreparedTransaction prepTx = txTemp.prepare(); | |||
// 使用私钥进行签名; | |||
AsymmetricKeypair keyPair = getSponsorKey();//示例方法,取发起人的私钥; | |||
prepTx.sign(keyPair); | |||
// 提交交易; | |||
prepTx.commit(); | |||
//获取返回值; | |||
System.out.println("balance = " + balance.get()); | |||
} | |||
private static HashDigest getLedgerHash() { | |||
// TODO Init ledger hash; | |||
return null; | |||
} | |||
/** | |||
* 交易发起人的私钥;<br> | |||
* | |||
* 注:私钥由调用方在本地保管和使用; | |||
* | |||
* @return | |||
*/ | |||
private static AsymmetricKeypair getSponsorKey() { | |||
SignatureFunction signatureFunction = Crypto.getSignatureFunction("ED25519"); | |||
return signatureFunction.generateKeypair(); | |||
} | |||
/** | |||
* 商品信息; | |||
* | |||
* @author huanghaiquan | |||
* | |||
*/ | |||
public static class Remark { | |||
private String code; | |||
private String name; | |||
private String venderAddress; | |||
public String getCode() { | |||
return code; | |||
} | |||
public void setCode(String code) { | |||
this.code = code; | |||
} | |||
public String getName() { | |||
return name; | |||
} | |||
public void setName(String name) { | |||
this.name = name; | |||
} | |||
public String getVenderAddress() { | |||
return venderAddress; | |||
} | |||
public void setVenderAddress(String venderAddress) { | |||
this.venderAddress = venderAddress; | |||
} | |||
} | |||
} |
@@ -1,81 +0,0 @@ | |||
package com.jd.blockchain.sdk.samples; | |||
import com.jd.blockchain.crypto.AsymmetricKeypair; | |||
import com.jd.blockchain.crypto.Crypto; | |||
import com.jd.blockchain.crypto.HashDigest; | |||
import com.jd.blockchain.crypto.SignatureFunction; | |||
import com.jd.blockchain.ledger.BlockchainKeyGenerator; | |||
import com.jd.blockchain.ledger.BlockchainKeypair; | |||
import com.jd.blockchain.ledger.PreparedTransaction; | |||
import com.jd.blockchain.ledger.TransactionTemplate; | |||
import com.jd.blockchain.sdk.BlockchainTransactionService; | |||
import com.jd.blockchain.sdk.client.GatewayServiceFactory; | |||
import com.jd.blockchain.utils.net.NetworkAddress; | |||
public class SDKDemo_DataAccount { | |||
public static BlockchainKeypair CLIENT_CERT = BlockchainKeyGenerator.getInstance().generate("ED25519"); | |||
/** | |||
* 生成一个区块链用户,并注册到区块链; | |||
*/ | |||
public static void registerDataAccount() { | |||
// 区块链共识域; | |||
String realm = "SUPPLY_CHAIN_ALLIANCE"; | |||
// 节点地址列表; | |||
NetworkAddress[] peerAddrs = { new NetworkAddress("192.168.10.10", 8080), | |||
new NetworkAddress("192.168.10.11", 8080), new NetworkAddress("192.168.10.12", 8080), | |||
new NetworkAddress("192.168.10.13", 8080) }; | |||
// 网关客户端编号; | |||
int gatewayId = 1001; | |||
// 账本地址; | |||
String ledgerAddress = "ffkjhkeqwiuhivnsh3298josijdocaijsda=="; | |||
// 客户端的认证账户; | |||
String clientAddress = "kkjsafieweqEkadsfaslkdslkae998232jojf=="; | |||
String privKey = "safefsd32q34vdsvs"; | |||
// 创建服务代理; | |||
final String GATEWAY_IP = "127.0.0.1"; | |||
final int GATEWAY_PORT = 80; | |||
final boolean SECURE = false; | |||
GatewayServiceFactory serviceFactory = GatewayServiceFactory.connect(GATEWAY_IP, GATEWAY_PORT, SECURE, | |||
CLIENT_CERT); | |||
BlockchainTransactionService service = serviceFactory.getBlockchainService(); | |||
HashDigest ledgerHash = getLedgerHash(); | |||
// 在本地定义注册账号的 TX; | |||
TransactionTemplate txTemp = service.newTransaction(ledgerHash); | |||
// -------------------------------------- | |||
// 在本地产生要注册的账户的秘钥; | |||
BlockchainKeyGenerator generator = BlockchainKeyGenerator.getInstance(); | |||
BlockchainKeypair dataAccount = generator.generate("ED25519"); | |||
txTemp.dataAccounts().register(dataAccount.getIdentity()); | |||
// -------------------------------------- | |||
// TX 准备就绪; | |||
PreparedTransaction prepTx = txTemp.prepare(); | |||
// 使用私钥进行签名; | |||
AsymmetricKeypair keyPair = getSponsorKey(); | |||
prepTx.sign(keyPair); | |||
// 提交交易; | |||
prepTx.commit(); | |||
} | |||
private static HashDigest getLedgerHash() { | |||
// TODO Init ledger hash; | |||
return null; | |||
} | |||
private static AsymmetricKeypair getSponsorKey() { | |||
SignatureFunction signatureFunction = Crypto.getSignatureFunction("ED25519"); | |||
return signatureFunction.generateKeypair(); | |||
} | |||
} |
@@ -1,74 +0,0 @@ | |||
//package com.jd.blockchain.sdk.samples; | |||
// | |||
//import com.jd.blockchain.ledger.BlockchainEventType; | |||
//import com.jd.blockchain.ledger.BlockchainKeyGenerator; | |||
//import com.jd.blockchain.ledger.BlockchainKeyPair; | |||
//import com.jd.blockchain.ledger.CryptoKeyType; | |||
//import com.jd.blockchain.ledger.StateMap; | |||
//import com.jd.blockchain.sdk.BlockchainEventHandle; | |||
//import com.jd.blockchain.sdk.BlockchainEventListener; | |||
//import com.jd.blockchain.sdk.BlockchainEventMessage; | |||
//import com.jd.blockchain.sdk.BlockchainService; | |||
//import com.jd.blockchain.sdk.client.BlockchainServiceFactory; | |||
// | |||
//import my.utils.net.NetworkAddress; | |||
// | |||
///** | |||
// * 演示监听区块链事件的过程; | |||
// * | |||
// * @author huanghaiquan | |||
// * | |||
// */ | |||
//public class SDKDemo_EventListener { | |||
// | |||
// public static BlockchainKeyPair CLIENT_CERT = BlockchainKeyGenerator.getInstance().generate(CryptoKeyType.ED25519); | |||
// | |||
// /** | |||
// * 演示合约执行的过程; | |||
// */ | |||
// public static void demoContract() { | |||
// // 区块链共识域; | |||
// String realm = "SUPPLY_CHAIN_ALLIANCE"; | |||
// // 节点地址列表; | |||
// NetworkAddress[] peerAddrs = { new NetworkAddress("192.168.10.10", 8080), | |||
// new NetworkAddress("192.168.10.11", 8080), new NetworkAddress("192.168.10.12", 8080), | |||
// new NetworkAddress("192.168.10.13", 8080) }; | |||
// | |||
// // 网关客户端编号; | |||
// int gatewayId = 1001; | |||
// // 账本地址; | |||
// String ledgerAddress = "ffkjhkeqwiuhivnsh3298josijdocaijsda=="; | |||
// // 客户端的认证账户; | |||
// String clientAddress = "kkjsafieweqEkadsfaslkdslkae998232jojf=="; | |||
// String privKey = "safefsd32q34vdsvs"; | |||
// // 创建服务代理; | |||
// final String GATEWAY_IP = "127.0.0.1"; | |||
// final int GATEWAY_PORT = 80; | |||
// final boolean SECURE = false; | |||
// BlockchainServiceFactory serviceFactory = BlockchainServiceFactory.connect(GATEWAY_IP, GATEWAY_PORT, SECURE, | |||
// CLIENT_CERT); | |||
// BlockchainService service = serviceFactory.getBlockchainService(); | |||
// | |||
// // 监听账户变动; | |||
// String walletAccount = "MMMEy902jkjjJJDkshreGeasdfassdfajjf=="; | |||
// service.addBlockchainEventListener(BlockchainEventType.PAYLOAD_UPDATED.CODE, null, walletAccount, | |||
// new BlockchainEventListener() { | |||
// @Override | |||
// public void onEvent(BlockchainEventMessage eventMessage, BlockchainEventHandle eventHandle) { | |||
// // 钱包余额; | |||
// StateMap balancePayload = service.getState(walletAccount, "RMB-ASSET","name"); | |||
// Long balance = (Long) balancePayload.get("RMB-ASSET").longValue(); | |||
// if (balance != null) { | |||
// // notify balance change; | |||
// } else { | |||
// // wallet is empty and isn't listened any more; | |||
// eventHandle.cancel(); | |||
// } | |||
// } | |||
// }); | |||
// | |||
// // 销毁服务代理; | |||
// serviceFactory.close(); | |||
// } | |||
// | |||
//} |
@@ -1,127 +0,0 @@ | |||
package com.jd.blockchain.sdk.samples; | |||
import com.jd.blockchain.crypto.AsymmetricKeypair; | |||
import com.jd.blockchain.crypto.Crypto; | |||
import com.jd.blockchain.crypto.HashDigest; | |||
import com.jd.blockchain.crypto.SignatureFunction; | |||
import com.jd.blockchain.ledger.BlockchainKeyGenerator; | |||
import com.jd.blockchain.ledger.BlockchainKeypair; | |||
import com.jd.blockchain.ledger.PreparedTransaction; | |||
import com.jd.blockchain.ledger.TransactionTemplate; | |||
import com.jd.blockchain.sdk.BlockchainService; | |||
import com.jd.blockchain.sdk.client.GatewayServiceFactory; | |||
import com.jd.blockchain.utils.io.ByteArray; | |||
import com.jd.blockchain.utils.net.NetworkAddress; | |||
/** | |||
* 演示数据写入的调用过程; | |||
* | |||
* @author huanghaiquan | |||
* | |||
*/ | |||
public class SDKDemo_InsertData { | |||
public static BlockchainKeypair CLIENT_CERT = BlockchainKeyGenerator.getInstance().generate("ED25519"); | |||
/** | |||
* 演示数据写入的调用过程; | |||
*/ | |||
public static void insertData() { | |||
// 区块链共识域; | |||
String realm = "SUPPLY_CHAIN_ALLIANCE"; | |||
// 节点地址列表; | |||
NetworkAddress[] peerAddrs = { new NetworkAddress("192.168.10.10", 8080), | |||
new NetworkAddress("192.168.10.11", 8080), new NetworkAddress("192.168.10.12", 8080), | |||
new NetworkAddress("192.168.10.13", 8080) }; | |||
// 网关客户端编号; | |||
int gatewayId = 1001; | |||
// 账本地址; | |||
String ledgerAddress = "ffkjhkeqwiuhivnsh3298josijdocaijsda=="; | |||
// 客户端的认证账户; | |||
String clientAddress = "kkjsafieweqEkadsfaslkdslkae998232jojf=="; | |||
String privKey = "safefsd32q34vdsvs"; | |||
// 创建服务代理; | |||
final String GATEWAY_IP = "127.0.0.1"; | |||
final int GATEWAY_PORT = 80; | |||
final boolean SECURE = false; | |||
GatewayServiceFactory serviceFactory = GatewayServiceFactory.connect(GATEWAY_IP, GATEWAY_PORT, SECURE, | |||
CLIENT_CERT); | |||
BlockchainService service = serviceFactory.getBlockchainService(); | |||
HashDigest ledgerHash = getLedgerHash(); | |||
// 在本地定义注册账号的 TX; | |||
TransactionTemplate txTemp = service.newTransaction(ledgerHash); | |||
// -------------------------------------- | |||
// 将商品信息写入到指定的账户中; | |||
// 对象将被序列化为 JSON 形式存储,并基于 JSON 结构建立查询索引; | |||
String commodityDataAccount = "GGhhreGeasdfasfUUfehf9932lkae99ds66jf=="; | |||
Commodity commodity1 = new Commodity(); | |||
txTemp.dataAccount(commodityDataAccount).setText("ASSET_CODE", commodity1.getCode(), -1); | |||
// TX 准备就绪; | |||
PreparedTransaction prepTx = txTemp.prepare(); | |||
String txHash = ByteArray.toBase64(prepTx.getHash().toBytes()); | |||
// 使用私钥进行签名; | |||
AsymmetricKeypair keyPair = getSponsorKey(); | |||
prepTx.sign(keyPair); | |||
// 提交交易; | |||
prepTx.commit(); | |||
} | |||
private static HashDigest getLedgerHash() { | |||
// TODO Init ledger hash; | |||
return null; | |||
} | |||
private static AsymmetricKeypair getSponsorKey() { | |||
SignatureFunction signatureFunction = Crypto.getSignatureFunction("ED25519"); | |||
return signatureFunction.generateKeypair(); | |||
} | |||
/** | |||
* 商品信息; | |||
* | |||
* @author huanghaiquan | |||
* | |||
*/ | |||
public static class Commodity { | |||
private String code; | |||
private String name; | |||
private String venderAddress; | |||
public String getCode() { | |||
return code; | |||
} | |||
public void setCode(String code) { | |||
this.code = code; | |||
} | |||
public String getName() { | |||
return name; | |||
} | |||
public void setName(String name) { | |||
this.name = name; | |||
} | |||
public String getVenderAddress() { | |||
return venderAddress; | |||
} | |||
public void setVenderAddress(String venderAddress) { | |||
this.venderAddress = venderAddress; | |||
} | |||
} | |||
} |
@@ -1,46 +0,0 @@ | |||
/** | |||
* Copyright: Copyright 2016-2020 JD.COM All Right Reserved | |||
* FileName: com.jd.blockchain.sdk.samples.SDKDemo_Params | |||
* Author: shaozhuguang | |||
* Department: 区块链研发部 | |||
* Date: 2018/10/18 下午2:16 | |||
* Description: | |||
*/ | |||
package com.jd.blockchain.sdk.samples; | |||
import com.jd.blockchain.crypto.KeyGenUtils; | |||
import com.jd.blockchain.crypto.PrivKey; | |||
import com.jd.blockchain.crypto.PubKey; | |||
/** | |||
* | |||
* @author shaozhuguang | |||
* @create 2018/10/18 | |||
* @since 1.0.0 | |||
*/ | |||
public class SDKDemo_Params { | |||
public static final String PASSWORD = "abc"; | |||
public static final String[] PUB_KEYS = { | |||
"3snPdw7i7PjVKiTH2VnXZu5H8QmNaSXpnk4ei533jFpuifyjS5zzH9", | |||
"3snPdw7i7PajLB35tEau1kmixc6ZrjLXgxwKbkv5bHhP7nT5dhD9eX", | |||
"3snPdw7i7PZi6TStiyc6mzjprnNhgs2atSGNS8wPYzhbKaUWGFJt7x", | |||
"3snPdw7i7PifPuRX7fu3jBjsb3rJRfDe9GtbDfvFJaJ4V4hHXQfhwk" }; | |||
public static final String[] PRIV_KEYS = { | |||
"177gjzHTznYdPgWqZrH43W3yp37onm74wYXT4v9FukpCHBrhRysBBZh7Pzdo5AMRyQGJD7x", | |||
"177gju9p5zrNdHJVEQnEEKF4ZjDDYmAXyfG84V5RPGVc5xFfmtwnHA7j51nyNLUFffzz5UT", | |||
"177gjtwLgmSx5v1hFb46ijh7L9kdbKUpJYqdKVf9afiEmAuLgo8Rck9yu5UuUcHknWJuWaF", | |||
"177gk1pudweTq5zgJTh8y3ENCTwtSFsKyX7YnpuKPo7rKgCkCBXVXh5z2syaTCPEMbuWRns" }; | |||
public static PrivKey privkey0 = KeyGenUtils.decodePrivKeyWithRawPassword(PRIV_KEYS[0], PASSWORD); | |||
public static PrivKey privkey1 = KeyGenUtils.decodePrivKeyWithRawPassword(PRIV_KEYS[1], PASSWORD); | |||
public static PrivKey privkey2 = KeyGenUtils.decodePrivKeyWithRawPassword(PRIV_KEYS[2], PASSWORD); | |||
public static PrivKey privkey3 = KeyGenUtils.decodePrivKeyWithRawPassword(PRIV_KEYS[3], PASSWORD); | |||
public static PubKey pubKey0 = KeyGenUtils.decodePubKey(PUB_KEYS[0]); | |||
public static PubKey pubKey1 = KeyGenUtils.decodePubKey(PUB_KEYS[1]); | |||
public static PubKey pubKey2 = KeyGenUtils.decodePubKey(PUB_KEYS[2]); | |||
public static PubKey pubKey3 = KeyGenUtils.decodePubKey(PUB_KEYS[3]); | |||
} |
@@ -1,75 +0,0 @@ | |||
package com.jd.blockchain.sdk.samples; | |||
public class SDKDemo_PrivilegeSetting { | |||
// public static BlockchainKeyPair CLIENT_CERT = BlockchainKeyGenerator.getInstance().generate(CryptoKeyType.ED25519); | |||
// | |||
// /** | |||
// * 生成一个区块链账户,并注册到区块链; | |||
// */ | |||
// public static void registerAccount() { | |||
// // 区块链共识域; | |||
// String realm = "SUPPLY_CHAIN_ALLIANCE"; | |||
// // 节点地址列表; | |||
// NetworkAddress[] peerAddrs = { new NetworkAddress("192.168.10.10", 8080), | |||
// new NetworkAddress("192.168.10.11", 8080), new NetworkAddress("192.168.10.12", 8080), | |||
// new NetworkAddress("192.168.10.13", 8080) }; | |||
// | |||
// // 网关客户端编号; | |||
// int gatewayId = 1001; | |||
// // 账本地址; | |||
// String ledgerAddress = "ffkjhkeqwiuhivnsh3298josijdocaijsda=="; | |||
// // 客户端的认证账户; | |||
// String clientAddress = "kkjsafieweqEkadsfaslkdslkae998232jojf=="; | |||
// String privKey = "safefsd32q34vdsvs"; | |||
// // 创建服务代理; | |||
// final String GATEWAY_IP = "127.0.0.1"; | |||
// final int GATEWAY_PORT = 80; | |||
// final boolean SECURE = false; | |||
// BlockchainServiceFactory serviceFactory = BlockchainServiceFactory.connect(GATEWAY_IP, GATEWAY_PORT, SECURE, | |||
// CLIENT_CERT); | |||
// BlockchainTransactionService service = serviceFactory.getBlockchainService(); | |||
// | |||
// HashDigest ledgerHash = getLedgerHash(); | |||
// // 在本地定义注册账号的 TX; | |||
// TransactionTemplate txTemp = service.newTransaction(ledgerHash); | |||
// | |||
// // -------------------------------------- | |||
// // 配置账户的权限; | |||
// String walletAccount = "Kjfe8832hfa9jjjJJDkshrFjksjdlkfj93F=="; | |||
// String user1 = "MMMEy902jkjjJJDkshreGeasdfassdfajjf=="; | |||
// String user2 = "Kjfe8832hfa9jjjJJDkshrFjksjdlkfj93F=="; | |||
// // 配置: | |||
// // “状态数据的写入权限”的阈值为 100; | |||
// // 需要 user1、user2 两个账户的联合签名才能写入; | |||
// // 当前账户仅用于表示一个业务钱包,禁止自身的写入权限,只能由业务角色的账户才能操作; | |||
// | |||
// | |||
// | |||
// txTemp.configPrivilege(walletAccount).setThreshhold(PrivilegeType.STATE_WRITE, 100) | |||
// .enable(PrivilegeType.STATE_WRITE, user1, 50).enable(PrivilegeType.STATE_WRITE, user2, 50) | |||
// .disable(PrivilegeType.STATE_WRITE, walletAccount); | |||
// // -------------------------------------- | |||
// | |||
// // TX 准备就绪; | |||
// PreparedTransaction prepTx = txTemp.prepare(); | |||
// | |||
// // 使用私钥进行签名; | |||
// BlockchainKeyPair sponsorKey = getSponsorKey(); | |||
// prepTx.sign(sponsorKey); | |||
// | |||
// // 提交交易; | |||
// prepTx.commit(); | |||
// } | |||
// | |||
// private static HashDigest getLedgerHash() { | |||
// // TODO Init ledger hash; | |||
// return null; | |||
// } | |||
// | |||
// private static BlockchainKeyPair getSponsorKey() { | |||
// // TODO Auto-generated method stub | |||
// return null; | |||
// } | |||
} |
@@ -1,86 +0,0 @@ | |||
package com.jd.blockchain.sdk.samples; | |||
import com.jd.blockchain.crypto.Crypto; | |||
import com.jd.blockchain.crypto.HashDigest; | |||
import com.jd.blockchain.ledger.BlockchainKeyGenerator; | |||
import com.jd.blockchain.ledger.BlockchainKeypair; | |||
import com.jd.blockchain.ledger.TypedKVEntry; | |||
import com.jd.blockchain.ledger.LedgerBlock; | |||
import com.jd.blockchain.ledger.LedgerTransaction; | |||
import com.jd.blockchain.ledger.Transaction; | |||
import com.jd.blockchain.sdk.BlockchainService; | |||
import com.jd.blockchain.sdk.client.GatewayServiceFactory; | |||
import com.jd.blockchain.utils.net.NetworkAddress; | |||
/** | |||
* 演示区块链信息查询的过程; | |||
* | |||
* @author huanghaiquan | |||
* | |||
*/ | |||
public class SDKDemo_Query { | |||
public static BlockchainKeypair CLIENT_CERT = BlockchainKeyGenerator.getInstance().generate("ED25519"); | |||
public static final HashDigest LEDGER_HASH = Crypto.getHashFunction("SHA256") | |||
.hash("xkxjcioewfqwe".getBytes()); | |||
/** | |||
* 演示合约执行的过程; | |||
*/ | |||
public static void demoContract() { | |||
// 区块链共识域; | |||
String realm = "SUPPLY_CHAIN_ALLIANCE"; | |||
// 节点地址列表; | |||
NetworkAddress[] peerAddrs = { new NetworkAddress("192.168.10.10", 8080), | |||
new NetworkAddress("192.168.10.11", 8080), new NetworkAddress("192.168.10.12", 8080), | |||
new NetworkAddress("192.168.10.13", 8080) }; | |||
// 网关客户端编号; | |||
int gatewayId = 1001; // 客户端的认证账户; | |||
// 账本地址; | |||
String ledgerAddress = "ffkjhkeqwiuhivnsh3298josijdocaijsda=="; | |||
String clientAddress = "kkjsafieweqEkadsfaslkdslkae998232jojf=="; | |||
String privKey = "safefsd32q34vdsvs"; | |||
// 创建服务代理; | |||
final String GATEWAY_IP = "127.0.0.1"; | |||
final int GATEWAY_PORT = 80; | |||
final boolean SECURE = false; | |||
GatewayServiceFactory serviceFactory = GatewayServiceFactory.connect(GATEWAY_IP, GATEWAY_PORT, SECURE, | |||
CLIENT_CERT); | |||
BlockchainService service = serviceFactory.getBlockchainService(); | |||
// 查询区块信息; | |||
// 区块高度; | |||
long ledgerNumber = service.getLedger(LEDGER_HASH).getLatestBlockHeight(); | |||
// 最新区块; | |||
LedgerBlock latestBlock = service.getBlock(LEDGER_HASH, ledgerNumber); | |||
// 区块中的交易的数量; | |||
long txCount = service.getTransactionCount(LEDGER_HASH, latestBlock.getHash()); | |||
// 获取交易列表; | |||
LedgerTransaction[] txList = service.getTransactions(LEDGER_HASH, ledgerNumber, 0, 100); | |||
// 根据交易的 hash 获得交易;注:客户端生成 PrepareTransaction 时得到交易hash; | |||
HashDigest txHash = txList[0].getTransactionContent().getHash(); | |||
Transaction tx = service.getTransactionByContentHash(LEDGER_HASH, txHash); | |||
// 获取数据; | |||
String commerceAccount = "GGhhreGeasdfasfUUfehf9932lkae99ds66jf=="; | |||
String[] objKeys = new String[] { "x001", "x002" }; | |||
TypedKVEntry[] kvData = service.getDataEntries(LEDGER_HASH, commerceAccount, objKeys); | |||
long payloadVersion = kvData[0].getVersion(); | |||
// boolean exist = service.containState(LEDGER_HASH, commerceAccount, "x003"); | |||
// 按条件查询; | |||
// 1、从保存会员信息的账户地址查询; | |||
// String condition = "female = true AND age > 18 AND address.city = 'beijing'"; | |||
// String memberInfoAccountAddress = "kkf2io39823jfIjfiIRWKQj30203fx=="; | |||
// StateMap memberInfo = service.queryObject(LEDGER_HASH, memberInfoAccountAddress, condition); | |||
// | |||
// // 2、从保存会员信息的账户地址查询; | |||
// Map<String, StateMap> memberInfoWithAccounts = service.queryObject(LEDGER_HASH, condition); | |||
} | |||
} |
@@ -1,85 +0,0 @@ | |||
package com.jd.blockchain.sdk.samples; | |||
import com.jd.blockchain.binaryproto.DataContractRegistry; | |||
import com.jd.blockchain.crypto.*; | |||
import com.jd.blockchain.ledger.*; | |||
import com.jd.blockchain.sdk.BlockchainService; | |||
import com.jd.blockchain.sdk.client.GatewayServiceFactory; | |||
import com.jd.blockchain.utils.net.NetworkAddress; | |||
/** | |||
* @Author: zhangshuang | |||
* @Date: 2020/5/27 5:18 PM | |||
* Version 1.0 | |||
*/ | |||
public class SDKDemo_RegistParticipant { | |||
public static void main(String[] args) { | |||
PrivKey privKey; | |||
PubKey pubKey; | |||
BlockchainKeypair CLIENT_CERT = null; | |||
String GATEWAY_IPADDR = null; | |||
int GATEWAY_PORT; | |||
boolean SECURE; | |||
BlockchainService service; | |||
//根据密码工具产生的公私钥 | |||
String PUB = "3snPdw7i7PkdgqiGX7GbZuFSi1cwZn7vtjw4vifb1YoXgr9k6Kfmis"; | |||
String PRIV = "177gjtZu8w1phqHFVNiFhA35cfimXmP6VuqrBFhfbXBWK8s4TRwro2tnpffwP1Emwr6SMN6"; | |||
privKey = SDKDemo_Params.privkey1; | |||
pubKey = SDKDemo_Params.pubKey1; | |||
CLIENT_CERT = new BlockchainKeypair(SDKDemo_Params.pubKey0, SDKDemo_Params.privkey0); | |||
GATEWAY_IPADDR = "127.0.0.1"; | |||
GATEWAY_PORT = 11000; | |||
SECURE = false; | |||
GatewayServiceFactory serviceFactory = GatewayServiceFactory.connect(GATEWAY_IPADDR, GATEWAY_PORT, SECURE, | |||
CLIENT_CERT); | |||
service = serviceFactory.getBlockchainService(); | |||
DataContractRegistry.register(TransactionContent.class); | |||
DataContractRegistry.register(TransactionContentBody.class); | |||
DataContractRegistry.register(TransactionRequest.class); | |||
DataContractRegistry.register(NodeRequest.class); | |||
DataContractRegistry.register(EndpointRequest.class); | |||
DataContractRegistry.register(TransactionResponse.class); | |||
DataContractRegistry.register(ParticipantRegisterOperation.class); | |||
DataContractRegistry.register(ParticipantStateUpdateOperation.class); | |||
DataContractRegistry.register(ConsensusSettingsUpdateOperation.class); | |||
HashDigest[] ledgerHashs = service.getLedgerHashs(); | |||
// 在本地定义注册账号的 TX; | |||
TransactionTemplate txTemp = service.newTransaction(ledgerHashs[0]); | |||
//existed signer | |||
AsymmetricKeypair keyPair = new BlockchainKeypair(pubKey, privKey); | |||
privKey = KeyGenUtils.decodePrivKeyWithRawPassword(PRIV, SDKDemo_Constant.PASSWORD); | |||
pubKey = KeyGenUtils.decodePubKey(PUB); | |||
System.out.println("Address = " + AddressEncoding.generateAddress(pubKey)); | |||
BlockchainKeypair user = new BlockchainKeypair(pubKey, privKey); | |||
// 注册参与方 | |||
txTemp.participants().register("Peer4", user.getIdentity()); | |||
// TX 准备就绪; | |||
PreparedTransaction prepTx = txTemp.prepare(); | |||
// 使用私钥进行签名; | |||
prepTx.sign(keyPair); | |||
// 提交交易; | |||
TransactionResponse transactionResponse = prepTx.commit(); | |||
} | |||
} |
@@ -1,57 +0,0 @@ | |||
package com.jd.blockchain.sdk.samples; | |||
import com.jd.blockchain.binaryproto.DataContractRegistry; | |||
import com.jd.blockchain.crypto.AsymmetricKeypair; | |||
import com.jd.blockchain.crypto.HashDigest; | |||
import com.jd.blockchain.ledger.*; | |||
import com.jd.blockchain.sdk.BlockchainService; | |||
import com.jd.blockchain.sdk.client.GatewayServiceFactory; | |||
import com.jd.blockchain.utils.ConsoleUtils; | |||
public class SDKDemo_RegisterAccount { | |||
public static void main(String[] args) { | |||
String GATEWAY_IPADDR = "127.0.0.1"; | |||
int GATEWAY_PORT = 8081; | |||
if (args != null && args.length == 2) { | |||
GATEWAY_IPADDR = args[0]; | |||
GATEWAY_PORT = Integer.parseInt(args[1]); | |||
} | |||
DataContractRegistry.register(TransactionContent.class); | |||
DataContractRegistry.register(TransactionContentBody.class); | |||
DataContractRegistry.register(TransactionRequest.class); | |||
DataContractRegistry.register(NodeRequest.class); | |||
DataContractRegistry.register(EndpointRequest.class); | |||
DataContractRegistry.register(TransactionResponse.class); | |||
BlockchainKeypair CLIENT_CERT = new BlockchainKeypair(SDKDemo_Params.pubKey0, SDKDemo_Params.privkey0); | |||
boolean SECURE = false; | |||
GatewayServiceFactory serviceFactory = GatewayServiceFactory.connect(GATEWAY_IPADDR, GATEWAY_PORT, SECURE, | |||
CLIENT_CERT); | |||
BlockchainService service = serviceFactory.getBlockchainService(); | |||
HashDigest[] ledgerHashs = service.getLedgerHashs(); | |||
// 在本地定义注册账号的 TX; | |||
TransactionTemplate txTemp = service.newTransaction(ledgerHashs[0]); | |||
//existed signer | |||
AsymmetricKeypair keyPair = new BlockchainKeypair(SDKDemo_Params.pubKey1, SDKDemo_Params.privkey1); | |||
BlockchainKeypair dataAcount = BlockchainKeyGenerator.getInstance().generate(); | |||
// 注册 | |||
txTemp.dataAccounts().register(dataAcount.getIdentity()); | |||
// TX 准备就绪; | |||
PreparedTransaction prepTx = txTemp.prepare(); | |||
prepTx.sign(keyPair); | |||
// 提交交易; | |||
TransactionResponse transactionResponse = prepTx.commit(); | |||
ConsoleUtils.info("register dataaccount complete, result is [%s]", transactionResponse.isSuccess()); | |||
} | |||
} |
@@ -1,39 +0,0 @@ | |||
/** | |||
* Copyright: Copyright 2016-2020 JD.COM All Right Reserved | |||
* FileName: com.jd.blockchain.sdk.samples.SDKDemo_RegisterUser | |||
* Author: shaozhuguang | |||
* Department: 区块链研发部 | |||
* Date: 2018/10/18 下午2:00 | |||
* Description: 注册用户 | |||
*/ | |||
package com.jd.blockchain.sdk.samples; | |||
import com.jd.blockchain.binaryproto.DataContractRegistry; | |||
import com.jd.blockchain.crypto.AsymmetricKeypair; | |||
import com.jd.blockchain.crypto.HashDigest; | |||
import com.jd.blockchain.crypto.PrivKey; | |||
import com.jd.blockchain.crypto.PubKey; | |||
import com.jd.blockchain.ledger.*; | |||
import com.jd.blockchain.sdk.BlockchainService; | |||
import com.jd.blockchain.sdk.client.GatewayServiceFactory; | |||
import com.jd.blockchain.utils.ConsoleUtils; | |||
/** | |||
* 注册用户 | |||
* @author shaozhuguang | |||
* @create 2018/10/18 | |||
* @since 1.0.0 | |||
*/ | |||
public class SDKDemo_RegisterTest { | |||
public static void main(String[] args) { | |||
if (args != null) { | |||
if (args[0].equals("user")) { | |||
SDKDemo_RegisterUser.main(null); | |||
} else if (args[0].equals("dataaccount")) { | |||
SDKDemo_RegisterAccount.main(null); | |||
} | |||
} | |||
} | |||
} |
@@ -1,86 +0,0 @@ | |||
/** | |||
* Copyright: Copyright 2016-2020 JD.COM All Right Reserved | |||
* FileName: com.jd.blockchain.sdk.samples.SDKDemo_RegisterUser | |||
* Author: shaozhuguang | |||
* Department: 区块链研发部 | |||
* Date: 2018/10/18 下午2:00 | |||
* Description: 注册用户 | |||
*/ | |||
package com.jd.blockchain.sdk.samples; | |||
import com.jd.blockchain.binaryproto.DataContractRegistry; | |||
import com.jd.blockchain.crypto.AsymmetricKeypair; | |||
import com.jd.blockchain.crypto.HashDigest; | |||
import com.jd.blockchain.crypto.PrivKey; | |||
import com.jd.blockchain.crypto.PubKey; | |||
import com.jd.blockchain.ledger.*; | |||
import com.jd.blockchain.sdk.BlockchainService; | |||
import com.jd.blockchain.sdk.client.GatewayServiceFactory; | |||
import com.jd.blockchain.utils.ConsoleUtils; | |||
/** | |||
* 注册用户 | |||
* | |||
* @author shaozhuguang | |||
* @create 2018/10/18 | |||
* @since 1.0.0 | |||
*/ | |||
public class SDKDemo_RegisterUser { | |||
public static void main(String[] args) { | |||
String GATEWAY_IPADDR = "127.0.0.1"; | |||
int GATEWAY_PORT = 8081; | |||
if (args != null && args.length == 2) { | |||
GATEWAY_IPADDR = args[0]; | |||
GATEWAY_PORT = Integer.parseInt(args[1]); | |||
} | |||
// 注册相关class | |||
DataContractRegistry.register(TransactionContent.class); | |||
DataContractRegistry.register(TransactionContentBody.class); | |||
DataContractRegistry.register(TransactionRequest.class); | |||
DataContractRegistry.register(NodeRequest.class); | |||
DataContractRegistry.register(EndpointRequest.class); | |||
DataContractRegistry.register(TransactionResponse.class); | |||
PrivKey privKey = SDKDemo_Params.privkey1; | |||
PubKey pubKey = SDKDemo_Params.pubKey1; | |||
BlockchainKeypair CLIENT_CERT = new BlockchainKeypair(SDKDemo_Params.pubKey0, SDKDemo_Params.privkey0); | |||
boolean SECURE = false; | |||
GatewayServiceFactory serviceFactory = GatewayServiceFactory.connect(GATEWAY_IPADDR, GATEWAY_PORT, SECURE, | |||
CLIENT_CERT); | |||
BlockchainService service = serviceFactory.getBlockchainService(); | |||
HashDigest[] ledgerHashs = service.getLedgerHashs(); | |||
// 在本地定义注册账号的 TX; | |||
TransactionTemplate txTemp = service.newTransaction(ledgerHashs[0]); | |||
// existed signer | |||
AsymmetricKeypair keyPair = new BlockchainKeypair(pubKey, privKey); | |||
BlockchainKeypair user = BlockchainKeyGenerator.getInstance().generate(); | |||
// 注册 | |||
txTemp.users().register(user.getIdentity()); | |||
// 定义角色权限; | |||
txTemp.security().roles().configure("MANAGER") | |||
.enable(LedgerPermission.REGISTER_USER, LedgerPermission.REGISTER_DATA_ACCOUNT) | |||
.enable(TransactionPermission.CONTRACT_OPERATION); | |||
txTemp.security().authorziations().forUser(user.getIdentity()).authorize("MANAGER"); | |||
// TX 准备就绪; | |||
PreparedTransaction prepTx = txTemp.prepare(); | |||
// 使用私钥进行签名; | |||
prepTx.sign(keyPair); | |||
// 提交交易; | |||
TransactionResponse transactionResponse = prepTx.commit(); | |||
ConsoleUtils.info("register user complete, result is [%s]", transactionResponse.isSuccess()); | |||
} | |||
} |
@@ -1,112 +0,0 @@ | |||
/** | |||
* Copyright: Copyright 2016-2020 JD.COM All Right Reserved | |||
* FileName: com.jd.blockchain.sdk.samples.SDKDemo_RegisterUser | |||
* Author: shaozhuguang | |||
* Department: 区块链研发部 | |||
* Date: 2018/10/18 下午2:00 | |||
* Description: 注册用户 | |||
*/ | |||
package com.jd.blockchain.sdk.samples; | |||
import com.jd.blockchain.binaryproto.BinaryProtocol; | |||
import com.jd.blockchain.binaryproto.DataContractRegistry; | |||
import com.jd.blockchain.crypto.AsymmetricKeypair; | |||
import com.jd.blockchain.crypto.HashDigest; | |||
import com.jd.blockchain.crypto.PrivKey; | |||
import com.jd.blockchain.crypto.PubKey; | |||
import com.jd.blockchain.ledger.*; | |||
import com.jd.blockchain.sdk.BlockchainService; | |||
import com.jd.blockchain.sdk.client.GatewayServiceFactory; | |||
import com.jd.blockchain.transaction.SignatureUtils; | |||
import com.jd.blockchain.utils.ConsoleUtils; | |||
/** | |||
* 注册用户 | |||
* | |||
* @author shaozhuguang | |||
* @create 2018/10/18 | |||
* @since 1.0.0 | |||
*/ | |||
public class SDKDemo_Tx_Persistance { | |||
public static void main(String[] args) { | |||
String GATEWAY_IPADDR = "127.0.0.1"; | |||
int GATEWAY_PORT = 11000; | |||
if (args != null && args.length == 2) { | |||
GATEWAY_IPADDR = args[0]; | |||
GATEWAY_PORT = Integer.parseInt(args[1]); | |||
} | |||
// 注册相关class | |||
DataContractRegistry.register(TransactionContent.class); | |||
DataContractRegistry.register(TransactionContentBody.class); | |||
DataContractRegistry.register(TransactionRequest.class); | |||
DataContractRegistry.register(NodeRequest.class); | |||
DataContractRegistry.register(EndpointRequest.class); | |||
DataContractRegistry.register(TransactionResponse.class); | |||
PrivKey privKey1 = SDKDemo_Params.privkey0; | |||
PubKey pubKey1 = SDKDemo_Params.pubKey0; | |||
PrivKey privKey2 = SDKDemo_Params.privkey1; | |||
PubKey pubKey2 = SDKDemo_Params.pubKey1; | |||
BlockchainKeypair CLIENT_CERT = new BlockchainKeypair(SDKDemo_Params.pubKey0, SDKDemo_Params.privkey0); | |||
boolean SECURE = false; | |||
GatewayServiceFactory gatewayServiceFactory = GatewayServiceFactory.connect(GATEWAY_IPADDR, GATEWAY_PORT, SECURE, | |||
CLIENT_CERT); | |||
BlockchainService blockchainService = gatewayServiceFactory.getBlockchainService(); | |||
HashDigest[] ledgerHashs = blockchainService.getLedgerHashs(); | |||
// 在本地定义注册账号的 TX; | |||
TransactionTemplate txTemp = blockchainService.newTransaction(ledgerHashs[0]); | |||
// existed signer | |||
AsymmetricKeypair keyPair1 = new BlockchainKeypair(pubKey1, privKey1); | |||
AsymmetricKeypair keyPair2 = new BlockchainKeypair(pubKey2, privKey2); | |||
BlockchainKeypair user = BlockchainKeyGenerator.getInstance().generate(); | |||
// 注册 | |||
txTemp.users().register(user.getIdentity()); | |||
// 定义角色权限; | |||
txTemp.security().roles().configure("MANAGER") | |||
.enable(LedgerPermission.REGISTER_USER, LedgerPermission.REGISTER_DATA_ACCOUNT) | |||
.enable(TransactionPermission.CONTRACT_OPERATION); | |||
txTemp.security().authorziations().forUser(user.getIdentity()).authorize("MANAGER"); | |||
// TX 准备就绪; | |||
PreparedTransaction prepTx = txTemp.prepare(); | |||
// 序列化交易内容; | |||
byte[] txContentBytes = BinaryProtocol.encode(prepTx.getTransactionContent(), TransactionContent.class); | |||
// 反序列化交易内容; | |||
TransactionContent txContent = BinaryProtocol.decode(txContentBytes, TransactionContent.class); | |||
// 对交易内容签名; | |||
DigitalSignature signature1 = SignatureUtils.sign(txContent, keyPair1); | |||
// 根据交易内容重新准备交易; | |||
PreparedTransaction decodedPrepTx = blockchainService.prepareTransaction(txContent); | |||
// 使用私钥进行签名,或附加签名; | |||
decodedPrepTx.addSignature(signature1); | |||
decodedPrepTx.sign(keyPair2); | |||
// 提交交易; | |||
TransactionResponse transactionResponse = decodedPrepTx.commit(); | |||
// 解析返回结果;如果是合约调用的操作,需要自行解析返回结果; | |||
if (transactionResponse.isSuccess()) { | |||
// 操作结果对应于交易中的操作顺序;无返回结果的操作对应结果为 null; | |||
OperationResult opResult = transactionResponse.getOperationResults()[0];// | |||
Class<?> dataClazz = null;//返回值的类型; | |||
Object value = BytesValueEncoding.decode(opResult.getResult(), dataClazz); | |||
} | |||
ConsoleUtils.info("register user complete, result is [%s]", transactionResponse.isSuccess()); | |||
} | |||
} |
@@ -1,95 +0,0 @@ | |||
package com.jd.blockchain.sdk.samples; | |||
import com.jd.blockchain.crypto.AsymmetricKeypair; | |||
import com.jd.blockchain.crypto.Crypto; | |||
import com.jd.blockchain.crypto.HashDigest; | |||
import com.jd.blockchain.crypto.SignatureFunction; | |||
import com.jd.blockchain.ledger.BlockchainKeyGenerator; | |||
import com.jd.blockchain.ledger.BlockchainKeypair; | |||
import com.jd.blockchain.ledger.PreparedTransaction; | |||
import com.jd.blockchain.ledger.TransactionTemplate; | |||
import com.jd.blockchain.sdk.BlockchainTransactionService; | |||
import com.jd.blockchain.sdk.client.GatewayServiceFactory; | |||
import com.jd.blockchain.utils.net.NetworkAddress; | |||
public class SDKDemo_User { | |||
public static BlockchainKeypair CLIENT_CERT = BlockchainKeyGenerator.getInstance().generate(); | |||
/** | |||
* 生成一个区块链用户,并注册到区块链; | |||
*/ | |||
public static void registerUser() { | |||
// 区块链共识域; | |||
String realm = "SUPPLY_CHAIN_ALLIANCE"; | |||
// 节点地址列表; | |||
NetworkAddress[] peerAddrs = { new NetworkAddress("192.168.10.10", 8080), | |||
new NetworkAddress("192.168.10.11", 8080), new NetworkAddress("192.168.10.12", 8080), | |||
new NetworkAddress("192.168.10.13", 8080) }; | |||
// 网关客户端编号; | |||
int gatewayId = 1001; | |||
// 账本地址; | |||
String ledgerAddress = "ffkjhkeqwiuhivnsh3298josijdocaijsda=="; | |||
// 客户端的认证账户; | |||
String clientAddress = "kkjsafieweqEkadsfaslkdslkae998232jojf=="; | |||
String privKey = "safefsd32q34vdsvs"; | |||
// 创建服务代理; | |||
final String GATEWAY_IP = "127.0.0.1"; | |||
final int GATEWAY_PORT = 80; | |||
final boolean SECURE = false; | |||
GatewayServiceFactory serviceFactory = GatewayServiceFactory.connect(GATEWAY_IP, GATEWAY_PORT, SECURE, | |||
CLIENT_CERT); | |||
BlockchainTransactionService service = serviceFactory.getBlockchainService(); | |||
HashDigest ledgerHash = getLedgerHash(); | |||
// 在本地定义注册账号的 TX; | |||
TransactionTemplate txTemp = service.newTransaction(ledgerHash); | |||
// -------------------------------------- | |||
// 配置账户的权限; | |||
String walletAccount = "Kjfe8832hfa9jjjJJDkshrFjksjdlkfj93F=="; | |||
String user1 = "MMMEy902jkjjJJDkshreGeasdfassdfajjf=="; | |||
String user2 = "Kjfe8832hfa9jjjJJDkshrFjksjdlkfj93F=="; | |||
// 配置: | |||
// “状态数据的写入权限”的阈值为 100; | |||
// 需要 user1、user2 两个账户的联合签名才能写入; | |||
// 当前账户仅用于表示一个业务钱包,禁止自身的写入权限,只能由业务角色的账户才能操作; | |||
String userPubKeyStr = "Kjfe8832hfa9jjjJJDkshrFjksjdlkfj93F=="; | |||
// 在本地产生要注册的账户的秘钥; | |||
//BlockchainKeyGenerator generator = BlockchainKeyGenerator.getInstance(); | |||
//BlockchainKeyPair user = generator.generate(CryptoKeyType.PUBLIC); | |||
SignatureFunction signatureFunction = Crypto.getSignatureFunction("ED25519"); | |||
AsymmetricKeypair cryptoKeyPair = signatureFunction.generateKeypair(); | |||
BlockchainKeypair user = new BlockchainKeypair(cryptoKeyPair.getPubKey(), cryptoKeyPair.getPrivKey()); | |||
txTemp.users().register(user.getIdentity()); | |||
// -------------------------------------- | |||
// TX 准备就绪; | |||
PreparedTransaction prepTx = txTemp.prepare(); | |||
// 使用私钥进行签名; | |||
AsymmetricKeypair keyPair = getSponsorKey(); | |||
prepTx.sign(keyPair); | |||
// 提交交易; | |||
prepTx.commit(); | |||
} | |||
private static HashDigest getLedgerHash() { | |||
// TODO Init ledger hash; | |||
return null; | |||
} | |||
private static AsymmetricKeypair getSponsorKey() { | |||
SignatureFunction signatureFunction = Crypto.getSignatureFunction("ED25519"); | |||
return signatureFunction.generateKeypair(); | |||
} | |||
} |
@@ -1,51 +0,0 @@ | |||
package com.jd.blockchain.sdk.samples; | |||
import com.jd.blockchain.crypto.HashDigest; | |||
import com.jd.blockchain.crypto.KeyGenUtils; | |||
import com.jd.blockchain.crypto.PrivKey; | |||
import com.jd.blockchain.crypto.PubKey; | |||
import com.jd.blockchain.ledger.BlockchainKeypair; | |||
import com.jd.blockchain.ledger.PreparedTransaction; | |||
import com.jd.blockchain.ledger.TransactionResponse; | |||
import com.jd.blockchain.ledger.TransactionTemplate; | |||
import com.jd.blockchain.sdk.BlockchainService; | |||
import com.jd.blockchain.sdk.client.GatewayServiceFactory; | |||
public abstract class SDK_Base_Demo { | |||
protected BlockchainKeypair adminKey; | |||
protected HashDigest ledgerHash; | |||
protected BlockchainService blockchainService; | |||
public SDK_Base_Demo() { | |||
init(); | |||
} | |||
public void init() { | |||
// 生成连接网关的账号 | |||
PrivKey privKey = KeyGenUtils.decodePrivKeyWithRawPassword(SDKDemo_Constant.PRIV_KEYS[0], SDKDemo_Constant.PASSWORD); | |||
PubKey pubKey = KeyGenUtils.decodePubKey(SDKDemo_Constant.PUB_KEYS[0]); | |||
adminKey = new BlockchainKeypair(pubKey, privKey); | |||
// 连接网关 | |||
GatewayServiceFactory serviceFactory = GatewayServiceFactory.connect(SDKDemo_Constant.GW_IPADDR, | |||
SDKDemo_Constant.GW_PORT, false, adminKey); | |||
// 获取网关对应的Service处理类 | |||
blockchainService = serviceFactory.getBlockchainService(); | |||
HashDigest[] ledgerHashs = blockchainService.getLedgerHashs(); | |||
// 获取当前账本Hash | |||
ledgerHash = ledgerHashs[0]; | |||
} | |||
public TransactionResponse commit(TransactionTemplate txTpl) { | |||
PreparedTransaction ptx = txTpl.prepare(); | |||
ptx.sign(adminKey); | |||
return ptx.commit(); | |||
} | |||
} |
@@ -1,70 +0,0 @@ | |||
package com.jd.blockchain.sdk.samples; | |||
import static com.jd.blockchain.sdk.samples.SDKDemo_Constant.readChainCodes; | |||
import static com.jd.blockchain.transaction.ContractReturnValue.decode; | |||
import com.jd.blockchain.ledger.BlockchainKeyGenerator; | |||
import com.jd.blockchain.ledger.BlockchainKeypair; | |||
import com.jd.blockchain.ledger.PreparedTransaction; | |||
import com.jd.blockchain.ledger.TransactionResponse; | |||
import com.jd.blockchain.ledger.TransactionTemplate; | |||
import com.jd.blockchain.transaction.GenericValueHolder; | |||
import com.jd.blockchain.utils.Bytes; | |||
import com.jd.chain.contracts.ContractTestInf; | |||
public class SDK_Contract_Check_Demo extends SDK_Base_Demo { | |||
public static void main(String[] args) { | |||
new SDK_Contract_Check_Demo().executeContract(); | |||
} | |||
public void executeContract() { | |||
// 发布jar包 | |||
// 定义交易模板 | |||
TransactionTemplate txTpl = blockchainService.newTransaction(ledgerHash); | |||
// 将jar包转换为二进制数据 | |||
byte[] contractCode = readChainCodes("contract-jdchain.jar"); | |||
// 生成一个合约账号 | |||
BlockchainKeypair contractDeployKey = BlockchainKeyGenerator.getInstance().generate(); | |||
// 生成发布合约操作 | |||
txTpl.contracts().deploy(contractDeployKey.getIdentity(), contractCode); | |||
// 生成预发布交易; | |||
PreparedTransaction ptx = txTpl.prepare(); | |||
// 对交易进行签名 | |||
ptx.sign(adminKey); | |||
// 提交并等待共识返回; | |||
TransactionResponse txResp = ptx.commit(); | |||
// 获取合约地址 | |||
Bytes contractAddress = contractDeployKey.getAddress(); | |||
// 打印交易返回信息 | |||
System.out.printf("Tx[%s] -> BlockHeight = %s, BlockHash = %s, isSuccess = %s, ExecutionState = %s \r\n", | |||
txResp.getContentHash().toBase58(), txResp.getBlockHeight(), txResp.getBlockHash().toBase58(), | |||
txResp.isSuccess(), txResp.getExecutionState()); | |||
// 打印合约地址 | |||
System.out.printf("ContractAddress = %s \r\n", contractAddress.toBase58()); | |||
// 执行合约 | |||
exeContract(contractAddress); | |||
} | |||
private void exeContract(Bytes contractAddress) { | |||
TransactionTemplate txTpl = blockchainService.newTransaction(ledgerHash); | |||
ContractTestInf contract = txTpl.contract(contractAddress, ContractTestInf.class); | |||
GenericValueHolder<String> result = decode(contract.randomChars(1024)); | |||
commit(txTpl); | |||
String random = result.get(); | |||
System.out.println(random); | |||
} | |||
} |
@@ -1,156 +0,0 @@ | |||
package com.jd.blockchain.sdk.samples; | |||
import static com.jd.blockchain.sdk.samples.SDKDemo_Constant.readChainCodes; | |||
import static com.jd.blockchain.transaction.ContractReturnValue.decode; | |||
import com.jd.blockchain.contract.TransferContract; | |||
import com.jd.blockchain.ledger.BlockchainKeyGenerator; | |||
import com.jd.blockchain.ledger.BlockchainKeypair; | |||
import com.jd.blockchain.ledger.PreparedTransaction; | |||
import com.jd.blockchain.ledger.TransactionResponse; | |||
import com.jd.blockchain.ledger.TransactionTemplate; | |||
import com.jd.blockchain.ledger.TypedKVEntry; | |||
import com.jd.blockchain.transaction.GenericValueHolder; | |||
import com.jd.blockchain.transaction.LongValueHolder; | |||
import com.jd.blockchain.utils.Bytes; | |||
public class SDK_Contract_Demo extends SDK_Base_Demo { | |||
public static void main(String[] args) { | |||
new SDK_Contract_Demo().executeContract(); | |||
} | |||
public void executeContract() { | |||
// 发布jar包 | |||
// 定义交易模板 | |||
TransactionTemplate txTpl = blockchainService.newTransaction(ledgerHash); | |||
// 将jar包转换为二进制数据 | |||
byte[] contractCode = readChainCodes("transfer.jar"); | |||
// 生成一个合约账号 | |||
BlockchainKeypair contractDeployKey = BlockchainKeyGenerator.getInstance().generate(); | |||
// 生成发布合约操作 | |||
txTpl.contracts().deploy(contractDeployKey.getIdentity(), contractCode); | |||
// 生成预发布交易; | |||
PreparedTransaction ptx = txTpl.prepare(); | |||
// 对交易进行签名 | |||
ptx.sign(adminKey); | |||
// 提交并等待共识返回; | |||
TransactionResponse txResp = ptx.commit(); | |||
// 获取合约地址 | |||
Bytes contractAddress = contractDeployKey.getAddress(); | |||
// 打印交易返回信息 | |||
System.out.printf("Tx[%s] -> BlockHeight = %s, BlockHash = %s, isSuccess = %s, ExecutionState = %s \r\n", | |||
txResp.getContentHash().toBase58(), txResp.getBlockHeight(), txResp.getBlockHash().toBase58(), | |||
txResp.isSuccess(), txResp.getExecutionState()); | |||
// 打印合约地址 | |||
System.out.printf("ContractAddress = %s \r\n", contractAddress.toBase58()); | |||
// 注册一个数据账户 | |||
BlockchainKeypair dataAccount = createDataAccount(); | |||
// 获取数据账户地址 | |||
String dataAddress = dataAccount.getAddress().toBase58(); | |||
// 打印数据账户地址 | |||
System.out.printf("DataAccountAddress = %s \r\n", dataAddress); | |||
// 创建两个账号: | |||
String account0 = "jd_zhangsan", account1 = "jd_lisi"; | |||
long account0Money = 3000L, account1Money = 2000L; | |||
// 创建两个账户 | |||
// 使用KV操作创建一个账户 | |||
System.out.println(create(dataAddress, account0, account0Money, false, null)); | |||
// 使用合约创建一个账户 | |||
System.out.println(create(dataAddress, account1, account1Money, true, contractAddress)); | |||
// 转账,使得双方钱达到一致 | |||
System.out.println(transfer(dataAddress, account0, account1, 500L, contractAddress)); | |||
// 通过合约读取account0的当前信息 | |||
System.out.printf("Read DataAccountAddress[%s] Account = %s 's money = %s (By Contract)\r\n", dataAddress, | |||
account0, readByContract(dataAddress, account0, contractAddress)); | |||
// 通过KV读取account1的当前信息 | |||
System.out.printf("Read DataAccountAddress[%s] Account = %s 's money = %s (By KV Operation)\r\n", dataAddress, | |||
account1, readByKvOperation(dataAddress, account1)); | |||
// 通过合约读取account0的历史信息 | |||
System.out.println(readAll(dataAddress, account0, contractAddress)); | |||
// 通过合约读取account1的历史信息 | |||
System.out.println(readAll(dataAddress, account1, contractAddress)); | |||
} | |||
private String readAll(String address, String account, Bytes contractAddress) { | |||
TransactionTemplate txTpl = blockchainService.newTransaction(ledgerHash); | |||
// 使用合约创建 | |||
TransferContract transferContract = txTpl.contract(contractAddress, TransferContract.class); | |||
GenericValueHolder<String> result = decode(transferContract.readAll(address, account)); | |||
commit(txTpl); | |||
return result.get(); | |||
} | |||
private long readByContract(String address, String account, Bytes contractAddress) { | |||
TransactionTemplate txTpl = blockchainService.newTransaction(ledgerHash); | |||
// 使用合约创建 | |||
TransferContract transferContract = txTpl.contract(contractAddress, TransferContract.class); | |||
LongValueHolder result = decode(transferContract.read(address, account)); | |||
commit(txTpl); | |||
return result.get(); | |||
} | |||
private long readByKvOperation(String address, String account) { | |||
TypedKVEntry[] kvDataEntries = blockchainService.getDataEntries(ledgerHash, address, account); | |||
if (kvDataEntries == null || kvDataEntries.length == 0) { | |||
throw new IllegalStateException(String.format("Ledger %s Service inner Error !!!", ledgerHash.toBase58())); | |||
} | |||
TypedKVEntry kvDataEntry = kvDataEntries[0]; | |||
if (kvDataEntry.getVersion() == -1) { | |||
return 0L; | |||
} | |||
return (long) (kvDataEntry.getValue()); | |||
} | |||
private String transfer(String address, String from, String to, long money, Bytes contractAddress) { | |||
TransactionTemplate txTpl = blockchainService.newTransaction(ledgerHash); | |||
// 使用合约创建 | |||
TransferContract transferContract = txTpl.contract(contractAddress, TransferContract.class); | |||
GenericValueHolder<String> result = decode(transferContract.transfer(address, from, to, money)); | |||
commit(txTpl); | |||
return result.get(); | |||
} | |||
private BlockchainKeypair createDataAccount() { | |||
// 首先注册一个数据账户 | |||
BlockchainKeypair newDataAccount = BlockchainKeyGenerator.getInstance().generate(); | |||
TransactionTemplate txTpl = blockchainService.newTransaction(ledgerHash); | |||
txTpl.dataAccounts().register(newDataAccount.getIdentity()); | |||
commit(txTpl); | |||
return newDataAccount; | |||
} | |||
private String create(String address, String account, long money, boolean useContract, Bytes contractAddress) { | |||
TransactionTemplate txTpl = blockchainService.newTransaction(ledgerHash); | |||
if (useContract) { | |||
// 使用合约创建 | |||
TransferContract transferContract = txTpl.contract(contractAddress, TransferContract.class); | |||
GenericValueHolder<String> result = decode(transferContract.create(address, account, money)); | |||
commit(txTpl); | |||
return result.get(); | |||
} else { | |||
// 通过KV创建 | |||
txTpl.dataAccount(address).setInt64(account, money, -1); | |||
TransactionResponse txResp = commit(txTpl); | |||
return String.format( | |||
"DataAccountAddress[%s] -> Create(By KV Operation) Account = %s and Money = %s Success!!! \r\n", | |||
address, account, money); | |||
} | |||
} | |||
} |
@@ -1,120 +0,0 @@ | |||
package com.jd.blockchain.sdk.samples; | |||
import com.jd.blockchain.contract.RandomContract; | |||
import com.jd.blockchain.contract.TransferContract; | |||
import com.jd.blockchain.ledger.*; | |||
import com.jd.blockchain.transaction.GenericValueHolder; | |||
import com.jd.blockchain.transaction.LongValueHolder; | |||
import com.jd.blockchain.utils.Bytes; | |||
import java.util.Random; | |||
import static com.jd.blockchain.sdk.samples.SDKDemo_Constant.readChainCodes; | |||
import static com.jd.blockchain.transaction.ContractReturnValue.decode; | |||
public class SDK_Contract_Random_Demo extends SDK_Base_Demo { | |||
public static void main(String[] args) throws Exception { | |||
new SDK_Contract_Random_Demo().executeContract(); | |||
} | |||
public void executeContract() throws Exception { | |||
// 发布jar包 | |||
// 定义交易模板 | |||
TransactionTemplate txTpl = blockchainService.newTransaction(ledgerHash); | |||
// 将jar包转换为二进制数据 | |||
byte[] contractCode = readChainCodes("random.jar"); | |||
// 生成一个合约账号 | |||
BlockchainKeypair contractDeployKey = BlockchainKeyGenerator.getInstance().generate(); | |||
// 生成发布合约操作 | |||
txTpl.contracts().deploy(contractDeployKey.getIdentity(), contractCode); | |||
// 生成预发布交易; | |||
PreparedTransaction ptx = txTpl.prepare(); | |||
// 对交易进行签名 | |||
ptx.sign(adminKey); | |||
// 提交并等待共识返回; | |||
TransactionResponse txResp = ptx.commit(); | |||
// 获取合约地址 | |||
Bytes contractAddress = contractDeployKey.getAddress(); | |||
// 打印交易返回信息 | |||
System.out.printf("Tx[%s] -> BlockHeight = %s, BlockHash = %s, isSuccess = %s, ExecutionState = %s \r\n", | |||
txResp.getContentHash().toBase58(), txResp.getBlockHeight(), txResp.getBlockHash().toBase58(), | |||
txResp.isSuccess(), txResp.getExecutionState()); | |||
// 打印合约地址 | |||
System.out.printf("ContractAddress = %s \r\n", contractAddress.toBase58()); | |||
String result = create("LdeNzfhZd2qiBRk3YrEX6GZgiVRZJaf3MKJAY", "zhangshuang", "jingdong", contractAddress); | |||
Thread.sleep(5000); | |||
System.out.println(result); | |||
} | |||
private String readAll(String address, String account, Bytes contractAddress) { | |||
TransactionTemplate txTpl = blockchainService.newTransaction(ledgerHash); | |||
// 使用合约创建 | |||
TransferContract transferContract = txTpl.contract(contractAddress, TransferContract.class); | |||
GenericValueHolder<String> result = decode(transferContract.readAll(address, account)); | |||
commit(txTpl); | |||
return result.get(); | |||
} | |||
private long readByContract(String address, String account, Bytes contractAddress) { | |||
TransactionTemplate txTpl = blockchainService.newTransaction(ledgerHash); | |||
// 使用合约创建 | |||
TransferContract transferContract = txTpl.contract(contractAddress, TransferContract.class); | |||
LongValueHolder result = decode(transferContract.read(address, account)); | |||
commit(txTpl); | |||
return result.get(); | |||
} | |||
private long readByKvOperation(String address, String account) { | |||
TypedKVEntry[] kvDataEntries = blockchainService.getDataEntries(ledgerHash, address, account); | |||
if (kvDataEntries == null || kvDataEntries.length == 0) { | |||
throw new IllegalStateException(String.format("Ledger %s Service inner Error !!!", ledgerHash.toBase58())); | |||
} | |||
TypedKVEntry kvDataEntry = kvDataEntries[0]; | |||
if (kvDataEntry.getVersion() == -1) { | |||
return 0L; | |||
} | |||
return (long) (kvDataEntry.getValue()); | |||
} | |||
private String transfer(String address, String from, String to, long money, Bytes contractAddress) { | |||
TransactionTemplate txTpl = blockchainService.newTransaction(ledgerHash); | |||
// 使用合约创建 | |||
TransferContract transferContract = txTpl.contract(contractAddress, TransferContract.class); | |||
GenericValueHolder<String> result = decode(transferContract.transfer(address, from, to, money)); | |||
commit(txTpl); | |||
return result.get(); | |||
} | |||
private BlockchainKeypair createDataAccount() { | |||
// 首先注册一个数据账户 | |||
BlockchainKeypair newDataAccount = BlockchainKeyGenerator.getInstance().generate(); | |||
TransactionTemplate txTpl = blockchainService.newTransaction(ledgerHash); | |||
txTpl.dataAccounts().register(newDataAccount.getIdentity()); | |||
commit(txTpl); | |||
return newDataAccount; | |||
} | |||
private String create(String address, String account, String value, Bytes contractAddress) { | |||
TransactionTemplate txTpl = blockchainService.newTransaction(ledgerHash); | |||
// 使用合约创建 | |||
RandomContract randomContract = txTpl.contract(contractAddress, RandomContract.class); | |||
GenericValueHolder<String> result = decode(randomContract.putAndGet(address, account, value)); | |||
commit(txTpl); | |||
return result.get(); | |||
} | |||
} |
@@ -1,49 +0,0 @@ | |||
package com.jd.blockchain.sdk.samples; | |||
import com.jd.blockchain.contract.TransferContract; | |||
import com.jd.blockchain.ledger.*; | |||
import com.jd.blockchain.transaction.GenericValueHolder; | |||
import com.jd.blockchain.transaction.LongValueHolder; | |||
import com.jd.blockchain.utils.Bytes; | |||
import static com.jd.blockchain.sdk.samples.SDKDemo_Constant.readChainCodes; | |||
import static com.jd.blockchain.transaction.ContractReturnValue.decode; | |||
public class SDK_DataAccount_Demo extends SDK_Base_Demo { | |||
public static void main(String[] args) { | |||
new SDK_DataAccount_Demo().executeDataAccount(); | |||
} | |||
public void executeDataAccount() { | |||
// 定义交易模板 | |||
TransactionTemplate txTpl = blockchainService.newTransaction(ledgerHash); | |||
// 注册一个数据账户 | |||
BlockchainKeypair dataAccount = createDataAccount(); | |||
// 获取数据账户地址 | |||
String dataAddress = dataAccount.getAddress().toBase58(); | |||
// 打印数据账户地址 | |||
System.out.printf("DataAccountAddress = %s \r\n", dataAddress); | |||
// 通过KV创建 | |||
txTpl.dataAccount(dataAddress) | |||
.setText("zhangsan", "我的世界", -1) | |||
.setText("张三", "My World", -1); | |||
TransactionResponse txResp = commit(txTpl); | |||
System.out.println(txResp.isSuccess()); | |||
} | |||
private BlockchainKeypair createDataAccount() { | |||
// 首先注册一个数据账户 | |||
BlockchainKeypair newDataAccount = BlockchainKeyGenerator.getInstance().generate(); | |||
TransactionTemplate txTpl = blockchainService.newTransaction(ledgerHash); | |||
txTpl.dataAccounts().register(newDataAccount.getIdentity()); | |||
commit(txTpl); | |||
return newDataAccount; | |||
} | |||
} |
@@ -1,96 +0,0 @@ | |||
package com.jd.blockchain.sdk.samples; | |||
import com.jd.blockchain.ledger.BlockchainKeyGenerator; | |||
import com.jd.blockchain.ledger.BlockchainKeypair; | |||
import com.jd.blockchain.ledger.BytesValue; | |||
import com.jd.blockchain.ledger.Event; | |||
import com.jd.blockchain.ledger.SystemEvent; | |||
import com.jd.blockchain.ledger.TransactionTemplate; | |||
import com.jd.blockchain.sdk.EventContext; | |||
import com.jd.blockchain.sdk.EventListenerHandle; | |||
import com.jd.blockchain.sdk.SystemEventListener; | |||
import com.jd.blockchain.sdk.SystemEventPoint; | |||
import com.jd.blockchain.sdk.UserEventListener; | |||
import com.jd.blockchain.sdk.UserEventPoint; | |||
import com.jd.blockchain.utils.io.BytesUtils; | |||
public class SDK_Event_Demo extends SDK_Base_Demo { | |||
// 注册事件账户 | |||
private BlockchainKeypair createEventAccount() { | |||
BlockchainKeypair eventAccount = BlockchainKeyGenerator.getInstance().generate(); | |||
TransactionTemplate txTpl = blockchainService.newTransaction(ledgerHash); | |||
txTpl.eventAccounts().register(eventAccount.getIdentity()); | |||
commit(txTpl); | |||
return eventAccount; | |||
} | |||
/** | |||
* 发布事件 | |||
* | |||
* @param eventAccount 事件账户 | |||
*/ | |||
private void publishEvent(BlockchainKeypair eventAccount) { | |||
TransactionTemplate txTpl = blockchainService.newTransaction(ledgerHash); | |||
// sequence传递当前事件名链上最新序号,不存在时传-1 | |||
Event event = blockchainService.getLatestEvent(ledgerHash, eventAccount.getAddress().toBase58(), "name"); | |||
long sequence = null != event ? event.getSequence() : -1; | |||
txTpl.eventAccount(eventAccount.getAddress()).publish("name", "string", sequence + 1); | |||
txTpl.eventAccount(eventAccount.getAddress()).publish("name", 0, sequence + 2); | |||
commit(txTpl); | |||
} | |||
/** | |||
* 监听用户自定义事件 | |||
* | |||
* @param eventAccount 事件账户 | |||
* @param eventName 事件名 | |||
*/ | |||
private void monitorUserEvent(BlockchainKeypair eventAccount, String eventName) { | |||
EventListenerHandle<UserEventPoint> handler = blockchainService.monitorUserEvent(ledgerHash, eventAccount.getAddress().toBase58(), eventName, 0, new UserEventListener<UserEventPoint>() { | |||
@Override | |||
public void onEvent(Event eventMessage, EventContext<UserEventPoint> eventContext) { | |||
BytesValue content = eventMessage.getContent(); | |||
switch (content.getType()) { | |||
case TEXT: | |||
System.out.println(content.getBytes().toUTF8String()); | |||
break; | |||
case INT64: | |||
System.out.println(BytesUtils.toLong(content.getBytes().toBytes())); | |||
break; | |||
default: | |||
break; | |||
} | |||
// 关闭监听的两种方式:1 | |||
eventContext.getHandle().cancel(); | |||
} | |||
}); | |||
// 关闭监听的两种方式:2 | |||
handler.cancel(); | |||
} | |||
/** | |||
* 监听新区块生成事件 | |||
*/ | |||
private void monitorNewBlockCreatedEvent() { | |||
EventListenerHandle<SystemEventPoint> handler = blockchainService.monitorSystemEvent(ledgerHash, SystemEvent.NEW_BLOCK_CREATED, 0, new SystemEventListener<SystemEventPoint>() { | |||
@Override | |||
public void onEvents(Event[] eventMessages, EventContext<SystemEventPoint> eventContext) { | |||
for (Event eventMessage : eventMessages) { | |||
BytesValue content = eventMessage.getContent(); | |||
// content中存放的是当前链上最新高度 | |||
System.out.println(BytesUtils.toLong(content.getBytes().toBytes())); | |||
} | |||
// 关闭监听的两种方式:1 | |||
eventContext.getHandle().cancel(); | |||
} | |||
}); | |||
// 关闭监听的两种方式:2 | |||
handler.cancel(); | |||
} | |||
} |
@@ -1,120 +0,0 @@ | |||
package com.jd.blockchain.sdk.samples; | |||
import com.jd.blockchain.crypto.HashDigest; | |||
import com.jd.blockchain.ledger.*; | |||
import com.jd.blockchain.sdk.converters.ClientResolveUtil; | |||
public class SDK_InsertData_Demo extends SDK_Base_Demo { | |||
public static void main(String[] args) { | |||
SDK_InsertData_Demo sdkDemo_insertData = new SDK_InsertData_Demo(); | |||
sdkDemo_insertData.insertData(); | |||
} | |||
/** | |||
* 生成一个区块链数据账户,并注册到区块链; | |||
*/ | |||
public void insertData() { | |||
// 在本地定义注册账号的 TX; | |||
TransactionTemplate txTemp = blockchainService.newTransaction(ledgerHash); | |||
//采用原始的方式来生成BlockchainKeypair; | |||
// SignatureFunction signatureFunction = Crypto.getSignatureFunction("ED25519"); | |||
// AsymmetricKeypair cryptoKeyPair = signatureFunction.generateKeypair(); | |||
// BlockchainKeypair dataAccount = new BlockchainKeypair(cryptoKeyPair.getPubKey(), cryptoKeyPair.getPrivKey()); | |||
//采用KeyGenerator来生成BlockchainKeypair; | |||
BlockchainKeypair dataAccount = BlockchainKeyGenerator.getInstance().generate(); | |||
txTemp.dataAccounts().register(dataAccount.getIdentity()); | |||
txTemp.dataAccount(dataAccount.getAddress()).setText("key1","value1",-1); | |||
// TX 准备就绪 | |||
PreparedTransaction prepTx = txTemp.prepare(); | |||
prepTx.sign(adminKey); | |||
// 提交交易; | |||
prepTx.commit(); | |||
getData(dataAccount.getAddress().toBase58()); | |||
} | |||
public void getData(String commerceAccount) { | |||
// 查询区块信息; | |||
// 区块高度; | |||
long ledgerNumber = blockchainService.getLedger(ledgerHash).getLatestBlockHeight(); | |||
// 最新区块; | |||
LedgerBlock latestBlock = blockchainService.getBlock(ledgerHash, ledgerNumber); | |||
// 区块中的交易的数量; | |||
long txCount = blockchainService.getTransactionCount(ledgerHash, latestBlock.getHash()); | |||
// 获取交易列表; | |||
LedgerTransaction[] txList = blockchainService.getTransactions(ledgerHash, ledgerNumber, 0, 100); | |||
// 遍历交易列表 | |||
for (LedgerTransaction ledgerTransaction : txList) { | |||
TransactionContent txContent = ledgerTransaction.getTransactionContent(); | |||
Operation[] operations = txContent.getOperations(); | |||
if (operations != null && operations.length > 0) { | |||
for (Operation operation : operations) { | |||
operation = ClientResolveUtil.read(operation); | |||
// 操作类型:数据账户注册操作 | |||
if (operation instanceof DataAccountRegisterOperation) { | |||
DataAccountRegisterOperation daro = (DataAccountRegisterOperation) operation; | |||
BlockchainIdentity blockchainIdentity = daro.getAccountID(); | |||
} | |||
// 操作类型:用户注册操作 | |||
else if (operation instanceof UserRegisterOperation) { | |||
UserRegisterOperation uro = (UserRegisterOperation) operation; | |||
BlockchainIdentity blockchainIdentity = uro.getUserID(); | |||
} | |||
// 操作类型:账本注册操作 | |||
else if (operation instanceof LedgerInitOperation) { | |||
LedgerInitOperation ledgerInitOperation = (LedgerInitOperation)operation; | |||
LedgerInitSetting ledgerInitSetting = ledgerInitOperation.getInitSetting(); | |||
ParticipantNode[] participantNodes = ledgerInitSetting.getConsensusParticipants(); | |||
} | |||
// 操作类型:合约发布操作 | |||
else if (operation instanceof ContractCodeDeployOperation) { | |||
ContractCodeDeployOperation ccdo = (ContractCodeDeployOperation) operation; | |||
BlockchainIdentity blockchainIdentity = ccdo.getContractID(); | |||
} | |||
// 操作类型:合约执行操作 | |||
else if (operation instanceof ContractEventSendOperation) { | |||
ContractEventSendOperation ceso = (ContractEventSendOperation) operation; | |||
} | |||
// 操作类型:KV存储操作 | |||
else if (operation instanceof DataAccountKVSetOperation) { | |||
DataAccountKVSetOperation.KVWriteEntry[] kvWriteEntries = | |||
((DataAccountKVSetOperation) operation).getWriteSet(); | |||
if (kvWriteEntries != null && kvWriteEntries.length > 0) { | |||
for (DataAccountKVSetOperation.KVWriteEntry kvWriteEntry : kvWriteEntries) { | |||
BytesValue bytesValue = kvWriteEntry.getValue(); | |||
DataType dataType = bytesValue.getType(); | |||
Object showVal = ClientResolveUtil.readValueByBytesValue(bytesValue); | |||
System.out.println("writeSet.key=" + kvWriteEntry.getKey()); | |||
System.out.println("writeSet.value=" + showVal); | |||
System.out.println("writeSet.type=" + dataType); | |||
System.out.println("writeSet.version=" + kvWriteEntry.getExpectedVersion()); | |||
} | |||
} | |||
} | |||
} | |||
} | |||
} | |||
//根据交易的 hash 获得交易;注:客户端生成 PrepareTransaction 时得到交易hash; | |||
HashDigest txHash = txList[0].getTransactionContent().getHash(); | |||
// Transaction tx = blockchainService.getTransactionByContentHash(ledgerHash, txHash); | |||
// String[] objKeys = new String[] { "x001", "x002" }; | |||
// KVDataEntry[] kvData = blockchainService.getDataEntries(ledgerHash, commerceAccount, objKeys); | |||
// 获取数据账户下所有的KV列表 | |||
TypedKVEntry[] kvData = blockchainService.getDataEntries(ledgerHash, commerceAccount, 0, 100); | |||
if (kvData != null && kvData.length > 0) { | |||
for (TypedKVEntry kvDatum : kvData) { | |||
System.out.println("kvData.key=" + kvDatum.getKey()); | |||
System.out.println("kvData.version=" + kvDatum.getVersion()); | |||
System.out.println("kvData.type=" + kvDatum.getType()); | |||
System.out.println("kvData.value=" + kvDatum.getValue()); | |||
} | |||
} | |||
} | |||
} |
@@ -1,47 +0,0 @@ | |||
package com.jd.blockchain.sdk.samples; | |||
import com.jd.blockchain.crypto.AddressEncoding; | |||
import com.jd.blockchain.crypto.KeyGenUtils; | |||
import com.jd.blockchain.crypto.PrivKey; | |||
import com.jd.blockchain.crypto.PubKey; | |||
import com.jd.blockchain.ledger.*; | |||
public class SDK_RegistParticipant_Demo extends SDK_Base_Demo { | |||
public static void main(String[] args) { | |||
new SDK_RegistParticipant_Demo().regParticipant(); | |||
} | |||
public void regParticipant() { | |||
//新参与方的公私钥 | |||
String PUB = "3snPdw7i7PjVKiTH2VnXZu5H8QmNaSXpnk4ei533jFpuifyjS5zzH9"; | |||
String PRIV = "177gjzHTznYdPgWqZrH43W3yp37onm74wYXT4v9FukpCHBrhRysBBZh7Pzdo5AMRyQGJD7x"; | |||
PrivKey privKey = KeyGenUtils.decodePrivKeyWithRawPassword(PRIV, SDKDemo_Constant.PASSWORD); | |||
PubKey pubKey = KeyGenUtils.decodePubKey(PUB); | |||
System.out.println("Address = " + AddressEncoding.generateAddress(pubKey)); | |||
BlockchainKeypair user = new BlockchainKeypair(pubKey, privKey); | |||
// 定义交易模板 | |||
TransactionTemplate txTpl = blockchainService.newTransaction(ledgerHash); | |||
// 注册参与方 | |||
txTpl.participants().register("Peer4", user.getIdentity()); | |||
// TX 准备就绪; | |||
PreparedTransaction prepTx = txTpl.prepare(); | |||
// 使用私钥进行签名; | |||
prepTx.sign(adminKey); | |||
// 提交交易; | |||
TransactionResponse transactionResponse = prepTx.commit(); | |||
System.out.println(transactionResponse.isSuccess()); | |||
} | |||
} |
@@ -1,26 +0,0 @@ | |||
package com.jd.blockchain.sdk.samples; | |||
import com.jd.blockchain.ledger.*; | |||
public class SDK_RoleConfig_Demo extends SDK_Base_Demo { | |||
public static void main(String[] args) { | |||
new SDK_RoleConfig_Demo().executeRoleConfig(); | |||
} | |||
public void executeRoleConfig() { | |||
// 定义交易模板 | |||
TransactionTemplate txTpl = blockchainService.newTransaction(ledgerHash); | |||
// 新增加一个角色 | |||
txTpl.security().roles().configure("MyRole") | |||
.enable(LedgerPermission.APPROVE_TX, LedgerPermission.CONSENSUS_TX) | |||
.disable(TransactionPermission.CONTRACT_OPERATION); | |||
TransactionResponse txResp = commit(txTpl); | |||
System.out.println(txResp.isSuccess()); | |||
} | |||
} |
@@ -1,56 +0,0 @@ | |||
package com.jd.blockchain.sdk.samples; | |||
import com.jd.blockchain.ledger.*; | |||
import com.jd.blockchain.utils.codec.Base58Utils; | |||
import java.util.Random; | |||
import java.util.concurrent.CountDownLatch; | |||
import java.util.concurrent.ExecutorService; | |||
import java.util.concurrent.Executors; | |||
public class SDK_Threads_KvInsert_Demo extends SDK_Base_Demo { | |||
public static void main(String[] args) throws Exception { | |||
new SDK_Threads_KvInsert_Demo().executeThreadsInsert(); | |||
} | |||
public void executeThreadsInsert() throws Exception { | |||
final int MAX = 30; | |||
final String dataAddress = "LdeNqP4S88t1YjkGQaCGbX95ygD6hA2B6yjp6"; | |||
ExecutorService threadPool = Executors.newFixedThreadPool(50); | |||
final CountDownLatch latch = new CountDownLatch(MAX); | |||
for (int i = 0; i < MAX; i++) { | |||
threadPool.execute(() -> { | |||
TransactionTemplate txTemp = blockchainService.newTransaction(ledgerHash); | |||
String key = System.currentTimeMillis() + "-" + | |||
System.nanoTime() + "-" + | |||
new Random(Thread.currentThread().getId()).nextInt(1024); | |||
txTemp.dataAccount(dataAddress).setText(key,"value1",-1); | |||
// TX 准备就绪 | |||
PreparedTransaction prepTx = txTemp.prepare(); | |||
prepTx.sign(adminKey); | |||
// 提交交易; | |||
TransactionResponse response = prepTx.commit(); | |||
System.out.printf("Key = %s, Result = %s \r\n", key, response.isSuccess()); | |||
latch.countDown(); | |||
}); | |||
} | |||
latch.await(); | |||
System.out.println("It is Over !!!"); | |||
System.exit(0); | |||
} | |||
} |
@@ -1,44 +0,0 @@ | |||
package com.jd.blockchain.sdk.samples; | |||
import com.jd.blockchain.ledger.*; | |||
import com.jd.blockchain.utils.Bytes; | |||
public class SDK_User2Role_Demo extends SDK_Base_Demo { | |||
public static void main(String[] args) { | |||
new SDK_User2Role_Demo().executeUser2Role(); | |||
} | |||
public void executeUser2Role() { | |||
// 定义交易模板 | |||
TransactionTemplate txTpl = blockchainService.newTransaction(ledgerHash); | |||
// 注册一个用户 | |||
BlockchainKeypair user = createUser(); | |||
Bytes userAddress = user.getAddress(); | |||
// 获取数据账户地址 | |||
System.out.printf("UserAddress = %s \r\n", userAddress.toBase58()); | |||
txTpl.security().authorziations().forUser(user.getIdentity()) | |||
.authorize("MYROLE") | |||
.setPolicy(RolesPolicy.UNION) | |||
.unauthorize("MYROLE"); | |||
TransactionResponse txResp = commit(txTpl); | |||
System.out.println(txResp.isSuccess()); | |||
} | |||
private BlockchainKeypair createUser() { | |||
// 首先注册一个数据账户 | |||
BlockchainKeypair newUser = BlockchainKeyGenerator.getInstance().generate(); | |||
TransactionTemplate txTpl = blockchainService.newTransaction(ledgerHash); | |||
txTpl.users().register(newUser.getIdentity()); | |||
commit(txTpl); | |||
return newUser; | |||
} | |||
} |