Java工程使用Maven或者gradle构建,在fabric 使用docker 构建Java智能合约,构建脚本:
#!/usr/bin/env bash
set -ex
INPUT_DIR=/chaincode/input
OUTPUT_DIR=/chaincode/output
TMP_DIR=$(mktemp -d)
NUM_JARS=$(find ${INPUT_DIR} -name "*.jar" | wc -l)
buildGradle() {
echo "Copying from $1 to ${TMP_DIR}"
cd $1
tar cf - . | (cd ${TMP_DIR}; tar xf -)
cd ${TMP_DIR}
echo "Gradle build"
if [ -f ./gradlew ]; then
chmod +x ./gradlew
./gradlew build shadowJar -x test
else
/root/chaincode-java/gradlew build shadowJar -x test
fi
retval=$?
if [ $retval -ne 0 ]; then
exit $retval
fi
cp build/libs/chaincode.jar $2
retval=$?
if [ $retval -ne 0 ]; then
exit $retval
fi
touch $2/.uberjar
cd "$SAVED" >/dev/null
}
buildMaven() {
echo "Copying from $1 to ${TMP_DIR}"
cd $1
tar cf - . | (cd ${TMP_DIR}; tar xf -)
cd ${TMP_DIR}
echo "Maven build"
if [ -f ./mvnw ]; then
chmod +x ./mvnw
else
cp -r /root/chaincode-java/.mvn .
cp /root/chaincode-java/mvnw .
fi
./mvnw compile package -DskipTests -Dmaven.test.skip=true
retval=$?
if [ $retval -ne 0 ]; then
exit $retval
fi
cp target/chaincode.jar $2
retval=$?
if [ $retval -ne 0 ]; then
exit $retval
fi
touch $2/.uberjar
cd "$SAVED" >/dev/null
}
for DIR in ${INPUT_DIR} ${INPUT_DIR}/src; do
if [ -f ${DIR}/build.gradle -o -f ${DIR}/build.gradle.kts ]; then
buildGradle ${DIR} ${OUTPUT_DIR}
exit 0
elif [ -f ${DIR}/pom.xml ]; then
buildMaven ${DIR} ${OUTPUT_DIR}
exit 0
fi
done
if [ ${NUM_JARS} -eq 0 ]; then
>&2 echo "Not build.gradle nor pom.xml found in chaincode source, don't know how to build chaincode"
>&2 echo "Project folder content:"
>&2 find ${INPUT_DIR} -name "*" -exec ls -ld '{}' \;
exit 255
else
cd ${INPUT_DIR} && tar cf - $(find . -name "*.jar") | (cd ${OUTPUT_DIR} && tar xvf -)
fi
从build.sh看出支持gradle、maven、jar三种方式。
$ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
79333401a4c8 hyperledger/fabric-javaenv:2.5 "/__cacert_entrypoin…" 14 hours ago Up 14 hours unruffled_curran
#进入docker实例
$ docker exec -it 79333401a4c8 /bin/bash
root@79333401a4c8:~/chaincode-java# ll
total 80
drwxr-xr-x 8 root root 4096 May 23 18:11 ./
drwx------ 1 root root 4096 Aug 21 02:04 ../
-rwxr-xr-x 1 root root 1920 May 23 18:03 build.sh*
drwxr-xr-x 4 root root 4096 May 23 18:05 chaincode/
drwxr-xr-x 5 root root 4096 May 23 18:10 .gradle/
drwxr-xr-x 3 root root 4096 May 23 18:10 gradle/
-rwxr-xr-x 1 root root 8692 May 23 18:10 gradlew*
-rw-r--r-- 1 root root 2918 May 23 18:10 gradlew.bat
drwxr-xr-x 2 root root 4096 May 23 18:03 lib/
drwxr-xr-x 3 root root 4096 May 23 18:11 .mvn/
-rwxrwxr-x 1 root root 10069 May 23 18:11 mvnw*
-rw-rw-r-- 1 root root 6607 May 23 18:11 mvnw.cmd
-rw-r--r-- 1 root root 0 May 23 18:10 settings.gradle
drwxr-xr-x 4 root root 4096 May 23 18:05 shim-src/
-rwxr-xr-x 1 root root 740 May 23 18:03 start*
.mvnw 打包使用.mvn目录,.mvn包含maven-wrapper.properties文件。
# ll .mvn/wrapper/
total 72
drwxr-xr-x 2 root root 4096 May 23 18:11 ./
drwxr-xr-x 3 root root 4096 May 23 18:11 ../
-rw-rw-r-- 1 root root 4941 May 23 18:11 MavenWrapperDownloader.java
-rw-rw-r-- 1 root root 50710 May 23 18:11 maven-wrapper.jar
-rw-rw-r-- 1 root root 218 May 23 18:11 maven-wrapper.properties
maven-wrapper.properties:
cat .mvn/wrapper/maven-wrapper.properties
distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.3/apache-maven-3.6.3-bin.zip
wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar
maven是通过Apache网站下载,总所周知,国内下载apache数据比较慢的,maven构建工程慢(或者超时)的原因只是在此。
工程目录结构如下:
$ ll
total 56
drwxrwxr-x 6 along along 4096 Aug 20 20:14 ./
drwxrwxr-x 5 along along 4096 Aug 15 16:30 ../
drwxrwxr-x 8 along along 4096 Aug 20 20:03 .git/
-rw-rw-r-- 1 along along 395 Aug 15 16:30 .gitignore
drwxrwxr-x 3 along along 4096 Aug 20 19:46 .mvn/
-rwxrwxr-x 1 along along 10069 Aug 20 19:46 mvnw*
-rwxrwxr-x 1 along along 6607 Aug 20 19:46 mvnw.cmd*
-rw-rw-r-- 1 along along 5071 Aug 15 16:30 pom.xml
drwxrwxr-x 3 along along 4096 Aug 15 16:30 src/
drwxrwxr-x 6 along along 4096 Aug 20 20:18 target/
$ ./mvnw compile package -DskipTests -Dmaven.test.skip=true
打包完成后:
$ tree target/
target/
├── chaincode.jar
├── classes
│ └── tech
│ └── pplus
│ └── fabric
│ └── chaincode
│ ├── BaseChaincode.class
│ ├── ChaincodeConstants.class
│ ├── supplies
│ │ └── SuppliesChaincode.class
│ └── user
│ ├── module
│ │ ├── User.class
│ │ ├── UserRoleEnum.class
│ │ └── UserStatusEnum.class
│ └── UserChaincode.class
├── generated-sources
│ └── annotations
├── maven-archiver
│ └── pom.properties
├── maven-status
│ └── maven-compiler-plugin
│ └── compile
│ └── default-compile
│ ├── createdFiles.lst
│ └── inputFiles.lst
├── original-chaincode.jar
└── warehouse_supplies-1.0-SNAPSHOT.jar
chaincode.jar是我们需要的合约jar。
# 新建src目录
$ mkdir src
#拷贝chaincode.jar 到src目录
cp fabric_warehouse_supplies/target/chaincode.jar src/
$ tree src/
src/
└── chaincode.jar
$ peer lifecycle chaincode package warehouse_supplies_v1.tar.gz --path /home/along/go/src/github.com/Hyperledger/fabric-java/src/ --lang java --label warehouse_supplies_v1
/home/along/go/src/github.com/Hyperledger/fabric-java/src/
是存放chaincode.jar的目录。
# 解压
$ mkdir chaincode && tar -txvf warehouse_supplies_v1.tar.gz -C chaincode
$ ll chaincode/
total 29748
drwxrwxr-x 2 along along 4096 Aug 21 10:06 ./
drwxrwxr-x 10 along along 4096 Aug 21 10:05 ../
-rw-r--r-- 1 along along 30449390 Jan 1 1970 code.tar.gz
-rw-r--r-- 1 along along 115 Jan 1 1970 metadata.json
$ tar -zxvf code.tar.gz
# 解压后的src
$ tree
.
├── code.tar.gz
├── metadata.json
└── src
└── chaincode.jar
安装链码
# 安装链码
$ peer lifecycle chaincode install warehouse_supplies_v1.tar.gz
2024-08-21 10:07:33.466 CST 0001 INFO [cli.lifecycle.chaincode] submitInstallProposal -> Installed remotely: response:<status:200 payload:"\nVwarehouse_supplies_v1:7773346e816b21e84996a499565eacb31a862b316d5fc38b853667d6bc36fe77\022\025warehouse_supplies_v1" >
2024-08-21 10:07:33.468 CST 0002 INFO [cli.lifecycle.chaincode] submitInstallProposal -> Chaincode code package identifier: warehouse_supplies_v1:7773346e816b21e84996a499565eacb31a862b316d5fc38b853667d6bc36fe77
#查看已安装的链码
$ peer lifecycle chaincode queryinstalled
Installed chaincodes on peer:
Package ID: warehouse_supplies_v1:7773346e816b21e84996a499565eacb31a862b316d5fc38b853667d6bc36fe77, Label: warehouse_supplies_v1
此时链码已经安装成功。
看看执行install指令时monitordocker.sh
输出的信息:
peer0.org1.example.com|2024-08-21 02:07:26.120 UTC 009b INFO [chaincode.externalbuilder.ccaas_builder] waitForExit -> ::Error: chaincode type not supported: java command=detect
awesome_kalam|+ INPUT_DIR=/chaincode/input
awesome_kalam|+ OUTPUT_DIR=/chaincode/output
awesome_kalam|++ mktemp -d
awesome_kalam|+ TMP_DIR=/tmp/tmp.VaQTZDBvRA
awesome_kalam|++ wc -l
awesome_kalam|++ find /chaincode/input -name '*.jar'
awesome_kalam|+ NUM_JARS=1
awesome_kalam|+ for DIR in ${INPUT_DIR} ${INPUT_DIR}/src
awesome_kalam|+ '[' -f /chaincode/input/build.gradle -o -f /chaincode/input/build.gradle.kts ']'
awesome_kalam|+ '[' -f /chaincode/input/pom.xml ']'
awesome_kalam|+ for DIR in ${INPUT_DIR} ${INPUT_DIR}/src
awesome_kalam|+ '[' -f /chaincode/input/src/build.gradle -o -f /chaincode/input/src/build.gradle.kts ']'
awesome_kalam|+ '[' -f /chaincode/input/src/pom.xml ']'
awesome_kalam|+ '[' 1 -eq 0 ']'
awesome_kalam|+ cd /chaincode/input
awesome_kalam|+ cd /chaincode/output
awesome_kalam|+ tar xvf -
awesome_kalam|++ find . -name '*.jar'
awesome_kalam|+ tar cf - ./src/chaincode.jar
awesome_kalam|./src/chaincode.jar
peer0.org1.example.com|2024-08-21 02:07:33.465 UTC 009c INFO [lifecycle] InstallChaincode -> Successfully installed chaincode with package ID 'warehouse_supplies_v1:7773346e816b21e84996a499565eacb31a862b316d5fc38b853667d6bc36fe77'
批准链码:
$ peer lifecycle chaincode approveformyorg \
-o localhost:7050 \
--ordererTLSHostnameOverride orderer.example.com \
--channelID ch1 \
--name warehouse_supplies \
--version 1.0 \
--package-id warehouse_supplies_v1:7773346e816b21e84996a499565eacb31a862b316d5fc38b853667d6bc36fe77 \
--sequence 1 \
--tls \
--cafile "${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem"
2024-08-21 11:01:33.251 CST 0001 INFO [chaincodeCmd] ClientWait -> txid [be566cd87115f9486f2f2b4926c72874b50478a85ee2c34c29340acef4c68488] committed with status (VALID) at localhost:7051
提交链码:
$ peer lifecycle chaincode commit \
-o localhost:7050 \
--ordererTLSHostnameOverride orderer.example.com \
--channelID ch1 \
--name warehouse_supplies \
--version 1.0 \
--sequence 1 \
--tls \
--cafile "${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem" \
--peerAddresses localhost:7051 --tlsRootCertFiles "${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt" \
--peerAddresses localhost:9051 --tlsRootCertFiles "${PWD}/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt"
2024-08-21 11:05:56.086 CST 0001 INFO [chaincodeCmd] ClientWait -> txid [b7d897812e83ae4cd82e5e90782adcf63f7d419206046a0d6b8796a711a1823d] committed with status (VALID) at localhost:7051
2024-08-21 11:05:56.242 CST 0002 INFO [chaincodeCmd] ClientWait -> txid [b7d897812e83ae4cd82e5e90782adcf63f7d419206046a0d6b8796a711a1823d] committed with status (VALID) at localhost:9051
初始化链码:
# 初始化链码
$ peer chaincode invoke \
-o localhost:7050 \
--ordererTLSHostnameOverride orderer.example.com \
--tls \
--cafile "${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem" \
-C ch1 \
-n warehouse_supplies \
--peerAddresses localhost:7051 \
--tlsRootCertFiles "${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt" \
--peerAddresses localhost:9051 \
--tlsRootCertFiles "${PWD}/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt" \
-c '{"function":"init","Args":[]}'
查询链码方法:
$ peer chaincode query -C ch1 -n warehouse_supplies -c '{"function":"getAllUsers","Args":[""]}'
[{"name":"超级管理员","id":"x509::CN=org1admin, OU=admin, O=Hyperledger, ST=North Carolina, C=US::CN=ca.org1.example.com, O=org1.example.com, L=Durham, ST=North Carolina, C=US","roles":[1],"status":1}]