first commit

This commit is contained in:
2026-02-09 17:45:06 +08:00
commit a9c1b81aea
29 changed files with 985 additions and 0 deletions

45
.gitignore vendored Normal file
View File

@@ -0,0 +1,45 @@
.gradle
build/
!gradle/wrapper/gradle-wrapper.jar
!**/src/main/**/build/
!**/src/test/**/build/
.kotlin
### IntelliJ IDEA ###
.idea/modules.xml
.idea/jarRepositories.xml
.idea/compiler.xml
.idea/libraries/
*.iws
*.iml
*.ipr
out/
!**/src/main/**/out/
!**/src/test/**/out/
### Eclipse ###
.apt_generated
.classpath
.factorypath
.project
.settings
.springBeans
.sts4-cache
bin/
!**/src/main/**/bin/
!**/src/test/**/bin/
### NetBeans ###
/nbproject/private/
/nbbuild/
/dist/
/nbdist/
/.nb-gradle/
### VS Code ###
.vscode/
### Mac OS ###
.DS_Store
fisco/

10
.idea/.gitignore generated vendored Normal file
View File

@@ -0,0 +1,10 @@
# Default ignored files
/shelf/
/workspace.xml
# Ignored default folder with query files
/queries/
# Datasource local storage ignored files
/dataSources/
/dataSources.local.xml
# Editor-based HTTP Client requests
/httpRequests/

17
.idea/gradle.xml generated Normal file
View File

@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="GradleMigrationSettings" migrationVersion="1" />
<component name="GradleSettings">
<option name="linkedExternalProjectsSettings">
<GradleProjectSettings>
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="gradleHome" value="" />
<option name="modules">
<set>
<option value="$PROJECT_DIR$" />
</set>
</option>
</GradleProjectSettings>
</option>
</component>
</project>

7
.idea/misc.xml generated Normal file
View File

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ExternalStorageConfigurationManager" enabled="true" />
<component name="ProjectRootManager" version="2" languageLevel="JDK_17" default="true" project-jdk-name="17" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/out" />
</component>
</project>

131
README.md Normal file
View File

@@ -0,0 +1,131 @@
# FISCO BCOS 合约开发项目
## 项目简介
这是一个基于 FISCO BCOS 区块链平台的 Java 开发项目,提供了与 FISCO BCOS 区块链交互的完整示例代码。项目包含账户管理、智能合约部署和调用等核心功能,适合作为 FISCO BCOS 应用开发的学习和实践基础。
## 技术栈
- **编程语言**: Java
- **构建工具**: Gradle
- **区块链平台**: FISCO BCOS
- **核心依赖**:
- FISCO BCOS Java SDK 2.9.1
- SLF4J 日志框架
## 主要功能
### 1. 账户管理
- **账户生成**: 支持生成 ECDSA 和国密 SM 两种加密类型的区块链账户
- **PEM 格式**: 账户以 PEM 格式存储,包含私钥、公钥和地址信息
- **账户加载**: 支持从 PEM 文件加载已有账户
- **多账户管理**: 可批量生成和管理多个用户账户
### 2. 智能合约交互
- HelloWorld 智能合约示例
- 合约部署和调用演示
- 支持使用指定账户与合约交互
### 3. 区块链节点连接
- 配置化的节点连接管理
- 支持多种加密类型ECDSA / 国密 SM
- 证书和密钥管理
## 项目结构
```
contract/
├── account/ # 生成的账户文件目录 (PEM 格式)
├── conf/ # 配置文件目录
├── fisco/ # FISCO BCOS 相关文件
├── src/
│ └── main/
│ └── java/
│ └── com/org/fisco/
│ ├── AccountGenerator.java # 账户生成工具
│ ├── HelloWorld.java # HelloWorld 合约示例
│ ├── HelloWorldWithAccount.java # 带账户的合约调用示例
│ └── BcosSDKTest.java # SDK 测试类
├── build.gradle # Gradle 构建配置
└── README.md # 项目说明文档
```
## 快速开始
### 前置要求
- JDK 8 或更高版本
- Gradle 6.0 或更高版本
- FISCO BCOS 区块链节点(运行中)
### 安装与构建
1. 克隆项目到本地
2. 配置区块链节点连接信息(在 `conf` 目录下)
3. 构建项目:
```bash
./gradlew build
```
### 运行账户生成工具
```bash
./gradlew run
```
该命令会运行 `AccountGenerator` 主类,自动生成示例账户并保存到 `account` 目录。
生成的账户包括:
- user_pem.pem
- alice.pem
- bob.pem
- charlie.pem
## 使用说明
### 生成账户
```java
import com.org.fisco.AccountGenerator;
import org.fisco.bcos.sdk.model.CryptoType;
// 生成 ECDSA 类型账户
AccountGenerator.generatePEMAccount("myAccount", CryptoType.ECDSA_TYPE);
// 生成国密 SM 类型账户
AccountGenerator.generatePEMAccount("myAccount", CryptoType.SM_TYPE);
```
### 加载账户
```java
// 从 PEM 文件加载账户
CryptoKeyPair keyPair = AccountGenerator.loadPEMAccount("account/alice.pem", CryptoType.SM_TYPE);
```
## 配置说明
项目配置文件位于 `conf` 目录,主要包括:
- 节点连接配置
- 证书文件
- 群组配置
- 加密类型配置
## 开发环境
- IDE: IntelliJ IDEA推荐
- 操作系统: macOS / Linux / Windows
- Java 版本: JDK 8+
## 许可证
本项目采用开源许可证发布。
## 相关资源
- [FISCO BCOS 官方文档](https://fisco-bcos-documentation.readthedocs.io/)
- [FISCO BCOS Java SDK 文档](https://fisco-bcos-documentation.readthedocs.io/zh_CN/latest/docs/sdk/java_sdk/index.html)
## 贡献
欢迎提交 Issue 和 Pull Request 来改进这个项目。

12
account/alice.pem Normal file
View File

@@ -0,0 +1,12 @@
-----BEGIN PRIVATE KEY-----
1120cf8793ccb6df2a4a4f371503e9699d1512d2e35d73daa3202c20c8e11731
-----END PRIVATE KEY-----
-----BEGIN PUBLIC KEY-----
6b68d579030462d7a0232b65a96c19a27bc98fd12ba8e5b09fdc83237ee54191ce8ff77d630341209d26bcd04640cf9e95f96af08718da3d258cef5e6e99bd08
-----END PUBLIC KEY-----
-----BEGIN ADDRESS-----
0xfffecbb1ef05e897e8d7f9da10fa13255c5c7b17
-----END ADDRESS-----
-----BEGIN CRYPTO TYPE-----
1
-----END CRYPTO TYPE-----

12
account/bob.pem Normal file
View File

@@ -0,0 +1,12 @@
-----BEGIN PRIVATE KEY-----
23230366ba1af4d9fe798a4891302e6f4d765f2cdb4e47836ceac4a3d5f50967
-----END PRIVATE KEY-----
-----BEGIN PUBLIC KEY-----
8bd59280cc6deee3de64d88c45227cf1342a6603607e30099371a0b5ab469e832dc2b72a00f7c3acbc5b40fc6a0fc298ae8545467e67dab4d3037b129c608ba9
-----END PUBLIC KEY-----
-----BEGIN ADDRESS-----
0x863a9a841c4242c7cab7ab3d5399f41ae21d05f9
-----END ADDRESS-----
-----BEGIN CRYPTO TYPE-----
1
-----END CRYPTO TYPE-----

12
account/charlie.pem Normal file
View File

@@ -0,0 +1,12 @@
-----BEGIN PRIVATE KEY-----
3855d3f52955a2ff799d52996fa0828d077d8dbb19242e6bd1d7b3a6f8dfbf29
-----END PRIVATE KEY-----
-----BEGIN PUBLIC KEY-----
aeb5629ca59d24e78f0aab53a03405fc6814316a1bdac4fba56385e8639b10d8ab04a53a7b7d94a5138f51ee02de7a7481ff8dc350c1b5d015dfa95273f48025
-----END PUBLIC KEY-----
-----BEGIN ADDRESS-----
0xdb52dabfe568e15331d302f4d9a411d6993c3606
-----END ADDRESS-----
-----BEGIN CRYPTO TYPE-----
1
-----END CRYPTO TYPE-----

12
account/user_pem.pem Normal file
View File

@@ -0,0 +1,12 @@
-----BEGIN PRIVATE KEY-----
e9c890670f4af89b804ea94e4068f604170d6c39f428bc04b62e8e2b5d05fdf2
-----END PRIVATE KEY-----
-----BEGIN PUBLIC KEY-----
f7e50297ef82600b324685265cae5b3e9030fd3c8d45b643a1c4316ecfae282b1a241c3f1d42d1d129a24d66f636dcb17b3e0a4ca34b3cb6475f774e1cb0b83a
-----END PUBLIC KEY-----
-----BEGIN ADDRESS-----
0x7843803067240dd872e50a26b254c83bc77d77ed
-----END ADDRESS-----
-----BEGIN CRYPTO TYPE-----
1
-----END CRYPTO TYPE-----

31
build.gradle Normal file
View File

@@ -0,0 +1,31 @@
plugins {
id 'java'
id 'application'
}
group = 'org.example'
version = '1.0-SNAPSHOT'
repositories {
mavenCentral()
}
dependencies {
implementation ('org.fisco-bcos.java-sdk:fisco-bcos-java-sdk:2.9.1')
// 添加日志实现,避免 SLF4J 警告
implementation 'org.slf4j:slf4j-simple:1.7.36'
testImplementation platform('org.junit:junit-bom:5.10.0')
testImplementation 'org.junit.jupiter:junit-jupiter'
testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
}
test {
useJUnitPlatform()
}
application {
mainClass = 'com.org.fisco.AccountGenerator'
}

18
conf/ca.crt Normal file
View File

@@ -0,0 +1,18 @@
-----BEGIN CERTIFICATE-----
MIIC9zCCAd8CFCHZXCvdfXdVqezsonFAU3f2LgNMMA0GCSqGSIb3DQEBCwUAMDcx
EDAOBgNVBAMMB2FnZW5jeUExEzARBgNVBAoMCmZpc2NvLWJjb3MxDjAMBgNVBAsM
BWNoYWluMCAXDTI2MDIwNjA0MDEwNVoYDzIxMjYwMTEzMDQwMTA1WjA3MRAwDgYD
VQQDDAdhZ2VuY3lBMRMwEQYDVQQKDApmaXNjby1iY29zMQ4wDAYDVQQLDAVjaGFp
bjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANQbqCgGZqEpM5aDOGFd
6lN7Z8cmV7Tbx2GviSU2AtcUjHhlGRfYepruSYbLLthhtjZVLzbSNliDYS7n7+AE
TAaR1RTtfL/6WIdMMmoPwHQHzNQ088dcMxcjHiUamvzKyJwxYlxRwCIQqQsiq0uE
boSlPmYVcWs4ahfydMJoEoALCj4/A+MSIxWBfki7G5p5vMbFy55dMc1ugPfw7XJm
rEiBo3XgXHT8yi41tMurh8Cr/F2gOMcLunbUb5aUpPTjdMqTkb/yGrGCHdLZI/g/
QOibfd5NDNs6l66zy0JQDWzWzHZ5Yzw5J2oPu4hwaX/1ub6x4j77n9k9VbCesTfu
cTcCAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAEIqWVURjPmtC09GXcKhVvSm0esmw
fzTe1rfzXZI7Qzfv7If0fRaGwFA8EI4qE435UykVE7P4V1nqRsJQdWxu+5N0JlXF
QbbYvjho0Vb3Nd0rqeJtQyKLPH3idsFsYi26vbMaX5iEOssDiy4wLvfKt1fYglGd
Ytd5KnVqqTB9/C0RJYUsyGk/+rnXcOpeu83rdH5afDuQVF5WfpfX9XGrQJWrAQwJ
cNETHLc7Yd7HeJmEIIRxJKiKsOcRc1kezy/ZYeeotJO0ZCJ9qCtWO9AHwpZutXXT
ULO1CTfAcczyOpRrWtegbriyqenCZfKpcJ/UZNgP+HdPhZSI+aTsPfUPGg==
-----END CERTIFICATE-----

29
conf/cert.cnf Normal file
View File

@@ -0,0 +1,29 @@
[ca]
default_ca=default_ca
[default_ca]
default_days = 365
default_md = sha256
[req]
distinguished_name = req_distinguished_name
req_extensions = v3_req
[req_distinguished_name]
countryName = CN
countryName_default = CN
stateOrProvinceName = State or Province Name (full name)
stateOrProvinceName_default =GuangDong
localityName = Locality Name (eg, city)
localityName_default = ShenZhen
organizationalUnitName = Organizational Unit Name (eg, section)
organizationalUnitName_default = fisco-bcos
commonName = Organizational commonName (eg, fisco-bcos)
commonName_default = fisco-bcos
commonName_max = 64
[ v3_req ]
basicConstraints = CA:FALSE
keyUsage = nonRepudiation, digitalSignature, keyEncipherment
[ v4_req ]
basicConstraints = CA:TRUE

12
conf/gm/gmca.crt Normal file
View File

@@ -0,0 +1,12 @@
-----BEGIN CERTIFICATE-----
MIIBxTCCAWqgAwIBAgIJAPSAlCTqOJY3MAoGCCqBHM9VAYN1MDcxEDAOBgNVBAMM
B2dtY2hhaW4xEzARBgNVBAoMCmZpc2NvLWJjb3MxDjAMBgNVBAsMBWNoYWluMCAX
DTI2MDIwNjA0MDEwNVoYDzIxMjYwMTEzMDQwMTA1WjA3MRAwDgYDVQQDDAdnbWNo
YWluMRMwEQYDVQQKDApmaXNjby1iY29zMQ4wDAYDVQQLDAVjaGFpbjBZMBMGByqG
SM49AgEGCCqBHM9VAYItA0IABLmhQY65M64nPOre8lfW5S4WLm3nI5UDHmgg/Ug/
pMmpolL7Noc528pK9HFOZYA+1Wgp1e3DizsO85OR4W+F4lKjXTBbMB0GA1UdDgQW
BBR8ewFMkuB1I40ls9/R2ZIP3yp4FjAfBgNVHSMEGDAWgBR8ewFMkuB1I40ls9/R
2ZIP3yp4FjAMBgNVHRMEBTADAQH/MAsGA1UdDwQEAwIBBjAKBggqgRzPVQGDdQNJ
ADBGAiEAjVNUxBNYAZj/Cv041LbBwWkLj0pPjpGX1k3ZgruUKOACIQDvtSp38lD7
jpi5W7mTXH6OMm6AUVziRGh8ODQKnCRp8Q==
-----END CERTIFICATE-----

11
conf/gm/gmensdk.crt Normal file
View File

@@ -0,0 +1,11 @@
-----BEGIN CERTIFICATE-----
MIIBgjCCASegAwIBAgIJAL+zBlcZ31NIMAoGCCqBHM9VAYN1MDsxEzARBgNVBAMM
CmFnZW5jeUEtZ20xEzARBgNVBAoMCmZpc2NvLWJjb3MxDzANBgNVBAsMBmFnZW5j
eTAgFw0yNjAyMDYwNDAxMDZaGA8yMTI2MDExMzA0MDEwNlowMzEMMAoGA1UEAwwD
c2RrMRMwEQYDVQQKDApmaXNjby1iY29zMQ4wDAYDVQQLDAVlbnNkazBZMBMGByqG
SM49AgEGCCqBHM9VAYItA0IABBWEvtek8MGJoF528A9ECUooZ6MpDiF1S0V2BYSE
Wlibu+2VYJYSZtRLY8fPaFtiU1fRmS0hoDxmLW8MLcCsTPWjGjAYMAkGA1UdEwQC
MAAwCwYDVR0PBAQDAgM4MAoGCCqBHM9VAYN1A0kAMEYCIQDtT30Osq4PQ9KeTeJI
jnxan8Fm7Za3mez9w7IE1BQXlAIhAOqXF68GsigOqHFZ7Y8FGdfuP6tpoTaVRTLF
n0/Ceo8X
-----END CERTIFICATE-----

5
conf/gm/gmensdk.key Normal file
View File

@@ -0,0 +1,5 @@
-----BEGIN PRIVATE KEY-----
MIGHAgEAMBMGByqGSM49AgEGCCqBHM9VAYItBG0wawIBAQQgG1YrjGc1e/Lfd5Eb
e3i+qTpf+sBU6YBQsjMz1G86RvChRANCAAQVhL7XpPDBiaBedvAPRAlKKGejKQ4h
dUtFdgWEhFpYm7vtlWCWEmbUS2PHz2hbYlNX0ZktIaA8Zi1vDC3ArEz1
-----END PRIVATE KEY-----

35
conf/gm/gmsdk.crt Normal file
View File

@@ -0,0 +1,35 @@
-----BEGIN CERTIFICATE-----
MIIBfzCCASWgAwIBAgIJAL+zBlcZ31NHMAoGCCqBHM9VAYN1MDsxEzARBgNVBAMM
CmFnZW5jeUEtZ20xEzARBgNVBAoMCmZpc2NvLWJjb3MxDzANBgNVBAsMBmFnZW5j
eTAgFw0yNjAyMDYwNDAxMDZaGA8yMTI2MDExMzA0MDEwNlowMTEMMAoGA1UEAwwD
c2RrMRMwEQYDVQQKDApmaXNjby1iY29zMQwwCgYDVQQLDANzZGswWTATBgcqhkjO
PQIBBggqgRzPVQGCLQNCAARjprE8r7lT893QkAl6XUPo2VHTYJWplJULE5fEd10J
Qr39IQinuu3EfdN/EJcQWKGs8g0LpBJzyTt1DVH7eMfhoxowGDAJBgNVHRMEAjAA
MAsGA1UdDwQEAwIGwDAKBggqgRzPVQGDdQNIADBFAiBOxkoOw89pKV45oS9xkayR
a8b48zFCwhl64e/C4Cd9RAIhAOp3tu311JO92zS+1F9KE1PviigxM5Wwawu5ZgSV
bSho
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIBxzCCAW6gAwIBAgIJAMoFIqx10XfAMAoGCCqBHM9VAYN1MDcxEDAOBgNVBAMM
B2dtY2hhaW4xEzARBgNVBAoMCmZpc2NvLWJjb3MxDjAMBgNVBAsMBWNoYWluMCAX
DTI2MDIwNjA0MDEwNVoYDzIxMjYwMTEzMDQwMTA1WjA7MRMwEQYDVQQDDAphZ2Vu
Y3lBLWdtMRMwEQYDVQQKDApmaXNjby1iY29zMQ8wDQYDVQQLDAZhZ2VuY3kwWTAT
BgcqhkjOPQIBBggqgRzPVQGCLQNCAATQI9maMxt/8i75GN0xv3aApeYf1xU8+JpA
vzzP925b2KOE4vfsnunsrV7NdC48O0FsSOJQsJs4TP40xcGIeX0oo10wWzAdBgNV
HQ4EFgQUhzVrLyY4bq+m1UklHuaBOiAsxMYwHwYDVR0jBBgwFoAUfHsBTJLgdSON
JbPf0dmSD98qeBYwDAYDVR0TBAUwAwEB/zALBgNVHQ8EBAMCAQYwCgYIKoEcz1UB
g3UDRwAwRAIgeyET44D0eDRuPCXg3vqpKXfF+Ks/h0h50Cd1AsvPjggCID/HYDTe
OEwICO0uVYC+rc+XAVhrTrMhFyerjbty1fMK
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIBxTCCAWqgAwIBAgIJAPSAlCTqOJY3MAoGCCqBHM9VAYN1MDcxEDAOBgNVBAMM
B2dtY2hhaW4xEzARBgNVBAoMCmZpc2NvLWJjb3MxDjAMBgNVBAsMBWNoYWluMCAX
DTI2MDIwNjA0MDEwNVoYDzIxMjYwMTEzMDQwMTA1WjA3MRAwDgYDVQQDDAdnbWNo
YWluMRMwEQYDVQQKDApmaXNjby1iY29zMQ4wDAYDVQQLDAVjaGFpbjBZMBMGByqG
SM49AgEGCCqBHM9VAYItA0IABLmhQY65M64nPOre8lfW5S4WLm3nI5UDHmgg/Ug/
pMmpolL7Noc528pK9HFOZYA+1Wgp1e3DizsO85OR4W+F4lKjXTBbMB0GA1UdDgQW
BBR8ewFMkuB1I40ls9/R2ZIP3yp4FjAfBgNVHSMEGDAWgBR8ewFMkuB1I40ls9/R
2ZIP3yp4FjAMBgNVHRMEBTADAQH/MAsGA1UdDwQEAwIBBjAKBggqgRzPVQGDdQNJ
ADBGAiEAjVNUxBNYAZj/Cv041LbBwWkLj0pPjpGX1k3ZgruUKOACIQDvtSp38lD7
jpi5W7mTXH6OMm6AUVziRGh8ODQKnCRp8Q==
-----END CERTIFICATE-----

5
conf/gm/gmsdk.key Normal file
View File

@@ -0,0 +1,5 @@
-----BEGIN PRIVATE KEY-----
MIGHAgEAMBMGByqGSM49AgEGCCqBHM9VAYItBG0wawIBAQQgoxmrcKs1GIs5Ew2z
MtY/LPzpypmdrP2YcfGE9iKE4cyhRANCAARjprE8r7lT893QkAl6XUPo2VHTYJWp
lJULE5fEd10JQr39IQinuu3EfdN/EJcQWKGs8g0LpBJzyTt1DVH7eMfh
-----END PRIVATE KEY-----

1
conf/gm/gmsdk.publickey Normal file
View File

@@ -0,0 +1 @@
63a6b13cafb953f3ddd090097a5d43e8d951d36095a994950b1397c4775d0942bdfd2108a7baedc47dd37f10971058a1acf20d0ba41273c93b750d51fb78c7e1

18
conf/sdk.crt Normal file
View File

@@ -0,0 +1,18 @@
-----BEGIN CERTIFICATE-----
MIIC+zCCAeMCFAuwtZkiTBgmFOw4C/QNXnVg6Qm+MA0GCSqGSIb3DQEBCwUAMDcx
EDAOBgNVBAMMB2FnZW5jeUExEzARBgNVBAoMCmZpc2NvLWJjb3MxDjAMBgNVBAsM
BWNoYWluMCAXDTI2MDIwNjA0MDEwNloYDzIxMjYwMTEzMDQwMTA2WjA7MRMwEQYD
VQQDDApGSVNDTy1CQ09TMRMwEQYDVQQKDApmaXNjby1iY29zMQ8wDQYDVQQLDAZh
Z2VuY3kwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQD1LZn9mPsId0uY
7ewKt2NCMoSdM4eE6BOFdIdZnM5qieOucqOhR8xMjBZtkaHX5yHzEOA4NZtNhvCs
l5kUHmQGxTalLjCwkZWMf88gEqoR26a5RR6uq5Zd3cH/Eb6eHYM70Y5TUVFgNhDU
zaAXFP9J4BCx9tHGC4bDhhRALDJ8rUyAyUSQypW4vetegfaRVzXcOfbVUQxp1/xw
Gp66APSfzhAIvS5VuqBfO4ZU7IJlbwyqwgkZyoDKq25Q5W9wE6Y0tsFqVEZihPHP
pInX4ynXAQm8FkAyUVS6cpAXs0ZOpceN8ibSz811Kp/HjbvxY2Em66uu4XsrZnXs
+FuA/yETAgMBAAEwDQYJKoZIhvcNAQELBQADggEBAGikh1Lcx3tMaS5o3GVHybF7
N4UZr71YBONJcR5tuqDpjAuF8XX9bRq25IDN8Fk3q/GQYRLMCETJeQwP1xSyuEBp
5clmA9UvGOCXPsG04BkwOovE718mWTm6Ip2iEWf6OMlnmMPPYY/w5pDk0UjBKpPj
l7Nn9iIWS46HGGBzBvX+DAkmXdB3xXD0uloPNrMsudKeJITUOUKev1Ar7sf7Knh/
Es+HbusUWphdfMz6YdctAEcjm3J6IGmtSQmiYre7TNG7iVEA4tP933miyR9ihhP5
+Vchd6BCC35Lk7mial1Vc0bV3oLicHrQMcMQ7WLuExyUcbtST4nVuLKlFAj/Juk=
-----END CERTIFICATE-----

28
conf/sdk.key Normal file
View File

@@ -0,0 +1,28 @@
-----BEGIN PRIVATE KEY-----
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQD1LZn9mPsId0uY
7ewKt2NCMoSdM4eE6BOFdIdZnM5qieOucqOhR8xMjBZtkaHX5yHzEOA4NZtNhvCs
l5kUHmQGxTalLjCwkZWMf88gEqoR26a5RR6uq5Zd3cH/Eb6eHYM70Y5TUVFgNhDU
zaAXFP9J4BCx9tHGC4bDhhRALDJ8rUyAyUSQypW4vetegfaRVzXcOfbVUQxp1/xw
Gp66APSfzhAIvS5VuqBfO4ZU7IJlbwyqwgkZyoDKq25Q5W9wE6Y0tsFqVEZihPHP
pInX4ynXAQm8FkAyUVS6cpAXs0ZOpceN8ibSz811Kp/HjbvxY2Em66uu4XsrZnXs
+FuA/yETAgMBAAECggEAAd29KH0pGqk5yz9dsWkwRA6OttmaZExrQElLnHGBRWCo
+dNyjmWLAbbRQY0/Dkh6mCyJNbRRayIl+Seq6R3KxMhsgDkH8tgbgMxvlFQVX6Rs
h517PHjJi2EG5dJJ6/nX3V/cyvfj/Cz9LM7R3fXGyaupxN5W6MB+tUSd09fiRyj7
YHFEtIQ18TAHPRGYDPhI/qWsBYeKOcgpC8BlhS4kbszoJ5BrlzH6HHNi9NzfF/1B
emrYTPohonmiwIbBjmSFPTugzYMn2ntp1PvyG+NbseeyAGe1/98u7ktXI3FDMqU9
x1YYHOkbc36HwfkPtM8b0i1bg/OCdDCrLbJe5cZqfQKBgQD+oPcZKUkE+C8w2iYp
gRsB8rwXLnichDNwo3PPCmOFy9efknJk9h0l1jFI1lU4kmXEV6BsByFzrNReUZyR
Pgiu8s9ckXU9a78XAKgidMmP2sCFp5kZmh+haYAaAwW8N/nX1D2mg910FGucIie9
3jnxf7rvRaM3D8appQDsFIcTnwKBgQD2f5uGGBbXdFzmmit/y2FBt7YnOZad626T
4n31R/OBrLMl5GuNRSaaDGt0BaZzNU4nOF1f7DSVZr8VC8StXYor0M/ao7Dqh3Fx
kfGqGj4qvjYg+zuudr4TYZKHILQNr3bx6NA9a1DvGA19W5dAxYHlXui0NmyApfQd
hVqa4pmeDQKBgBhdUKegsrL+CI31Idew2eO61VKmiLX5VG6/xTIXfWRtF+nV+oo8
npdjQn4EvEzYfVJnTBtqJ0JJVFzeFEw1kmEjLMJfzMceyz8pOe1qHWtddDSVz+mK
POKWFMLobSEQfiCv12JaldMorQ9YmVLqs8KvBTUmBbMcGFddSZRNdotjAoGBAMUY
T5Cu3kS0RDwW9cUfJ8rWTA2dHHN09lvE9BYVy/zZy/z2YZD5w93VJG4GvorMCouN
pAu44Gq9VvhLCp3cd0iFlE0sKZ+9YNYAbg0nIqImqT1B5Pyg8Wap0/G8EnwG2sKe
9zLFBlfHEbI0dAJUaoKumr7N7YAIMeMQ59uEaHRZAoGBALge3B+I24Psq8CFWJ98
BjOUFC9DqU5ImW59aioBFe6ukvQgMcjQ0DxHLg1fGUHv70lk6xcCVmypTAmvhyQt
2TnhJgpwW848kdDsrRiHHImmOWXlnMONexVVyB3TanX2A1puF2wutInmA8+aUA34
LhI9mFGkzTEOr5osJJJSdhEF
-----END PRIVATE KEY-----

113
diagnose-certs.ps1 Normal file
View File

@@ -0,0 +1,113 @@
Write-Host "=== FISCO BCOS 国密证书诊断 ===" -ForegroundColor Cyan
Write-Host ""
$projectRoot = Get-Location
Write-Host "项目目录: $projectRoot" -ForegroundColor Gray
Write-Host ""
# 检查证书目录
Write-Host "1. 检查证书目录结构..." -ForegroundColor Yellow
$certPath = "conf\gm"
if (Test-Path "conf") {
Write-Host " ✓ conf 目录存在" -ForegroundColor Green
if (Test-Path $certPath) {
Write-Host " ✓ conf\gm 目录存在" -ForegroundColor Green
} else {
Write-Host " ✗ conf\gm 目录不存在" -ForegroundColor Red
Write-Host ""
Write-Host "请创建目录: mkdir conf\gm -Force" -ForegroundColor Yellow
}
} else {
Write-Host " ✗ conf 目录不存在" -ForegroundColor Red
Write-Host ""
Write-Host "请创建目录: mkdir conf\gm -Force" -ForegroundColor Yellow
}
Write-Host ""
# 检查证书文件
Write-Host "2. 检查国密证书文件..." -ForegroundColor Yellow
$requiredFiles = @(
"gmca.crt",
"gmsdk.crt",
"gmsdk.key",
"gmensdk.crt",
"gmensdk.key"
)
$allPresent = $true
foreach ($file in $requiredFiles) {
$filePath = "conf\gm\$file"
if (Test-Path $filePath) {
$fileSize = (Get-Item $filePath).Length
$firstLine = (Get-Content $filePath -First 1 -ErrorAction SilentlyContinue)
if ($firstLine -match "BEGIN") {
Write-Host "$file ($fileSize 字节) - 格式正确" -ForegroundColor Green
} else {
Write-Host "$file ($fileSize 字节) - 格式可能有问题" -ForegroundColor Yellow
}
} else {
Write-Host "$file - 文件不存在" -ForegroundColor Red
$allPresent = $false
}
}
Write-Host ""
# 检查配置文件
Write-Host "3. 检查配置文件..." -ForegroundColor Yellow
if (Test-Path "config.toml") {
Write-Host " ✓ config.toml 存在" -ForegroundColor Green
$content = Get-Content "config.toml" -Raw
if ($content -match 'useSMCrypto\s*=\s*"true"') {
Write-Host " ✓ 国密模式已启用" -ForegroundColor Green
} else {
Write-Host " ⚠ 国密模式未启用" -ForegroundColor Yellow
}
if ($content -match 'certPath\s*=\s*"([^"]+)"') {
$certPathConfig = $matches[1]
Write-Host " 证书路径配置: $certPathConfig" -ForegroundColor Gray
}
} else {
Write-Host " ✗ config.toml 不存在" -ForegroundColor Red
}
Write-Host ""
# 检查 resources 目录
Write-Host "4. 检查 resources 配置..." -ForegroundColor Yellow
if (Test-Path "src\main\resources\config.toml") {
Write-Host " ✓ src\main\resources\config.toml 存在" -ForegroundColor Green
} else {
Write-Host " ✗ src\main\resources\config.toml 不存在" -ForegroundColor Red
Write-Host " 需要复制: copy config.toml src\main\resources\" -ForegroundColor Yellow
}
Write-Host ""
# 总结
Write-Host "=== 诊断总结 ===" -ForegroundColor Cyan
if ($allPresent) {
Write-Host "✓ 所有证书文件都已就位" -ForegroundColor Green
Write-Host ""
Write-Host "如果仍然连接失败,请检查:" -ForegroundColor Yellow
Write-Host " 1. 证书是否来自正确的节点服务器" -ForegroundColor Gray
Write-Host " 2. 证书文件内容是否完整" -ForegroundColor Gray
Write-Host " 3. 节点是否确实使用国密模式" -ForegroundColor Gray
} else {
Write-Host "✗ 缺少必要的证书文件" -ForegroundColor Red
Write-Host ""
Write-Host "请按以下步骤获取证书:" -ForegroundColor Yellow
Write-Host " 1. 在节点服务器上: cd /path/to/fisco/nodes/127.0.0.1/sdk" -ForegroundColor Gray
Write-Host " 2. 打包证书: tar -czf ~/fisco-gm-certs.tar.gz gm/" -ForegroundColor Gray
Write-Host " 3. 下载到 Windows 并解压到项目的 conf 目录" -ForegroundColor Gray
}
Write-Host ""
Write-Host "需要更详细的帮助,请查看节点日志或联系管理员" -ForegroundColor Gray

BIN
gradle/wrapper/gradle-wrapper.jar vendored Normal file

Binary file not shown.

View File

@@ -0,0 +1,6 @@
#Thu Feb 05 15:52:41 CST 2026
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-9.0.0-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists

234
gradlew vendored Executable file
View File

@@ -0,0 +1,234 @@
#!/bin/sh
#
# Copyright © 2015-2021 the original authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
##############################################################################
#
# Gradle start up script for POSIX generated by Gradle.
#
# Important for running:
#
# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
# noncompliant, but you have some other compliant shell such as ksh or
# bash, then to run this script, type that shell name before the whole
# command line, like:
#
# ksh Gradle
#
# Busybox and similar reduced shells will NOT work, because this script
# requires all of these POSIX shell features:
# * functions;
# * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
# «${var#prefix}», «${var%suffix}», and «$( cmd )»;
# * compound commands having a testable exit status, especially «case»;
# * various built-in commands including «command», «set», and «ulimit».
#
# Important for patching:
#
# (2) This script targets any POSIX shell, so it avoids extensions provided
# by Bash, Ksh, etc; in particular arrays are avoided.
#
# The "traditional" practice of packing multiple parameters into a
# space-separated string is a well documented source of bugs and security
# problems, so this is (mostly) avoided, by progressively accumulating
# options in "$@", and eventually passing that to Java.
#
# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
# see the in-line comments for details.
#
# There are tweaks for specific operating systems such as AIX, CygWin,
# Darwin, MinGW, and NonStop.
#
# (3) This script is generated from the Groovy template
# https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
# within the Gradle project.
#
# You can find Gradle at https://github.com/gradle/gradle/.
#
##############################################################################
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
app_path=$0
# Need this for daisy-chained symlinks.
while
APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
[ -h "$app_path" ]
do
ls=$( ls -ld "$app_path" )
link=${ls#*' -> '}
case $link in #(
/*) app_path=$link ;; #(
*) app_path=$APP_HOME$link ;;
esac
done
APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
APP_NAME="Gradle"
APP_BASE_NAME=${0##*/}
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD=maximum
warn () {
echo "$*"
} >&2
die () {
echo
echo "$*"
echo
exit 1
} >&2
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
nonstop=false
case "$( uname )" in #(
CYGWIN* ) cygwin=true ;; #(
Darwin* ) darwin=true ;; #(
MSYS* | MINGW* ) msys=true ;; #(
NONSTOP* ) nonstop=true ;;
esac
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD=$JAVA_HOME/jre/sh/java
else
JAVACMD=$JAVA_HOME/bin/java
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD=java
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
# Increase the maximum file descriptors if we can.
if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
case $MAX_FD in #(
max*)
MAX_FD=$( ulimit -H -n ) ||
warn "Could not query maximum file descriptor limit"
esac
case $MAX_FD in #(
'' | soft) :;; #(
*)
ulimit -n "$MAX_FD" ||
warn "Could not set maximum file descriptor limit to $MAX_FD"
esac
fi
# Collect all arguments for the java command, stacking in reverse order:
# * args from the command line
# * the main class name
# * -classpath
# * -D...appname settings
# * --module-path (only if needed)
# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
# For Cygwin or MSYS, switch paths to Windows format before running java
if "$cygwin" || "$msys" ; then
APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
JAVACMD=$( cygpath --unix "$JAVACMD" )
# Now convert the arguments - kludge to limit ourselves to /bin/sh
for arg do
if
case $arg in #(
-*) false ;; # don't mess with options #(
/?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
[ -e "$t" ] ;; #(
*) false ;;
esac
then
arg=$( cygpath --path --ignore --mixed "$arg" )
fi
# Roll the args list around exactly as many times as the number of
# args, so each arg winds up back in the position where it started, but
# possibly modified.
#
# NB: a `for` loop captures its iteration list before it begins, so
# changing the positional parameters here affects neither the number of
# iterations, nor the values presented in `arg`.
shift # remove old arg
set -- "$@" "$arg" # push replacement arg
done
fi
# Collect all arguments for the java command;
# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
# shell script including quotes and variable substitutions, so put them in
# double quotes to make sure that they get re-expanded; and
# * put everything else in single quotes, so that it's not re-expanded.
set -- \
"-Dorg.gradle.appname=$APP_BASE_NAME" \
-classpath "$CLASSPATH" \
org.gradle.wrapper.GradleWrapperMain \
"$@"
# Use "xargs" to parse quoted args.
#
# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
#
# In Bash we could simply go:
#
# readarray ARGS < <( xargs -n1 <<<"$var" ) &&
# set -- "${ARGS[@]}" "$@"
#
# but POSIX shell has neither arrays nor command substitution, so instead we
# post-process each arg (as a line of input to sed) to backslash-escape any
# character that might be a shell metacharacter, then use eval to reverse
# that process (while maintaining the separation between arguments), and wrap
# the whole thing up as a single "set" statement.
#
# This will of course break if any of these variables contains a newline or
# an unmatched quote.
#
eval "set -- $(
printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
xargs -n1 |
sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
tr '\n' ' '
)" '"$@"'
exec "$JAVACMD" "$@"

89
gradlew.bat vendored Normal file
View File

@@ -0,0 +1,89 @@
@rem
@rem Copyright 2015 the original author or authors.
@rem
@rem Licensed under the Apache License, Version 2.0 (the "License");
@rem you may not use this file except in compliance with the License.
@rem You may obtain a copy of the License at
@rem
@rem https://www.apache.org/licenses/LICENSE-2.0
@rem
@rem Unless required by applicable law or agreed to in writing, software
@rem distributed under the License is distributed on an "AS IS" BASIS,
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@rem See the License for the specific language governing permissions and
@rem limitations under the License.
@rem
@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto execute
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto execute
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
:end
@rem End local scope for the variables with windows NT shell
if "%ERRORLEVEL%"=="0" goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
exit /b 1
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega

1
settings.gradle Normal file
View File

@@ -0,0 +1 @@
rootProject.name = 'contract'

View File

@@ -0,0 +1,16 @@
package org.example;
//TIP To <b>Run</b> code, press <shortcut actionId="Run"/> or
// click the <icon src="AllIcons.Actions.Execute"/> icon in the gutter.
public class Main {
public static void main(String[] args) {
//TIP Press <shortcut actionId="ShowIntentionActions"/> with your caret at the highlighted text
// to see how IntelliJ IDEA suggests fixing it.
System.out.printf("Hello and welcome!");
for (int i = 1; i <= 5; i++) {
//TIP Press <shortcut actionId="Debug"/> to start debugging your code. We have set one <icon src="AllIcons.Debugger.Db_set_breakpoint"/> breakpoint
// for you, but you can always add more by pressing <shortcut actionId="ToggleLineBreakpoint"/>.
System.out.println("i = " + i);
}
}
}

View File

@@ -0,0 +1,55 @@
[cryptoMaterial]
certPath = "conf" # The certification path
useSMCrypto = "true"
# The following configurations take the certPath by default if commented
# caCert = "conf/ca.crt" # CA cert file path
# If connect to the GM node, default CA cert path is ${certPath}/gm/gmca.crt
# sslCert = "conf/sdk.crt" # SSL cert file path
# If connect to the GM node, the default SDK cert path is ${certPath}/gm/gmsdk.crt
# sslKey = "conf/sdk.key" # SSL key file path
# If connect to the GM node, the default SDK privateKey path is ${certPath}/gm/gmsdk.key
# enSslCert = "conf/gm/gmensdk.crt" # GM encryption cert file path
# default load the GM SSL encryption cert from ${certPath}/gm/gmensdk.crt
# enSslKey = "conf/gm/gmensdk.key" # GM ssl cert file path
# default load the GM SSL encryption privateKey from ${certPath}/gm/gmensdk.key
[network]
peers=["121.196.226.157:20200", "8.137.93.11:20200"] # The peer list to connect
# Configure a private topic as a topic message sender.
# [[amop]]
# topicName = "PrivateTopic1"
# publicKeys = [ "conf/amop/consumer_public_key_1.pem" ] # Public keys of the nodes that you want to send AMOP message of this topic to.
# Configure a private topic as a topic subscriber.
# [[amop]]
# topicName = "PrivateTopic2"
# privateKey = "conf/amop/consumer_private_key.p12" # Your private key that used to subscriber verification.
# password = "123456"
[account]
keyStoreDir = "account" # The directory to load/store the account file, default is "account"
# accountFilePath = "" # The account file path (default load from the path specified by the keyStoreDir)
accountFileFormat = "pem" # The storage format of account file (Default is "pem", "p12" as an option)
accountAddress = "" # The transactions sending account address
# Default is a randomly generated account
# The randomly generated account is stored in the path specified by the keyStoreDir
password = "" # The password used to load the account file
[threadPool]
# channelProcessorThreadSize = "16" # The size of the thread pool to process channel callback
# Default is the number of cpu cores
# receiptProcessorThreadSize = "16" # The size of the thread pool to process transaction receipt notification
# Default is the number of cpu cores
maxBlockingQueueSize = "102400" # The max blocking queue size of the thread pool
maxTotal = "100"
maxPerRoute = "100"

View File

@@ -0,0 +1,20 @@
# SLF4J Simple Logger 配置
# 设置默认日志级别为 ERROR只显示错误信息
org.slf4j.simpleLogger.defaultLogLevel=error
# 对于 FISCO BCOS SDK设置为 INFO 级别
org.slf4j.simpleLogger.log.org.fisco.bcos=info
# 对于 Netty设置为 ERROR 级别,隐藏警告
org.slf4j.simpleLogger.log.io.netty=error
# 显示日志名称
org.slf4j.simpleLogger.showLogName=true
# 显示线程名称
org.slf4j.simpleLogger.showThreadName=false
# 显示时间戳
org.slf4j.simpleLogger.showDateTime=true
org.slf4j.simpleLogger.dateTimeFormat=yyyy-MM-dd HH:mm:ss