diff --git a/docs/implement-a-customized-actuator-en.md b/docs/implement-a-customized-actuator-en.md index 551a6d63d3b..9cd5b4958db 100644 --- a/docs/implement-a-customized-actuator-en.md +++ b/docs/implement-a-customized-actuator-en.md @@ -36,13 +36,19 @@ message Transaction { AccountCreateContract = 0; TransferContract = 1; ........ - SumContract = 52; + SumContract = 60; } ... } ``` -Then register a function to ensure that gRPC can receive and identify the requests of this contract. Currently, gRPC protocols are all defined in `src/main/protos/api/api.proto`. To add an `InvokeSum` interface in Wallet Service: +Then register a function to ensure that gRPC can receive and identify the requests of this contract. Currently, gRPC protocols are all defined in `src/main/protos/api/api.proto`. First add the import for the new proto file at the top of `api.proto`: + +```protobuf +import "core/contract/math_contract.proto"; +``` + +Then add an `InvokeSum` interface in the Wallet service: ```protobuf service Wallet { @@ -60,13 +66,11 @@ service Wallet { ``` At last, recompile the modified proto files. Compiling the java-tron project directly will compile the proto files as well, `protoc` command is also supported. -*Currently, java-tron uses protoc v3.4.0. Please keep the same version when compiling by `protoc` command.* - ```shell -# recommended +# recommended — also recompiles proto files automatically ./gradlew build -x test -# or build via protoc +# or build via protoc (ensure the protoc version matches the one declared in build.gradle) protoc -I=src/main/protos -I=src/main/protos/core --java_out=src/main/java Tron.proto protoc -I=src/main/protos/core/contract --java_out=src/main/java math_contract.proto protoc -I=src/main/protos/api -I=src/main/protos/core -I=src/main/protos --java_out=src/main/java api.proto @@ -78,7 +82,11 @@ After compilation, the corresponding .class under the java_out directory will be For now, the default Actuator supported by java-tron is located in `org.tron.core.actuator`. Creating `SumActuator` under this directory: +> **Note**: The Actuator must be placed in the `org.tron.core.actuator` package. At node startup, `TransactionRegister.registerActuator()` uses reflection to scan that package and auto-discovers every `AbstractActuator` subclass. Each subclass is instantiated once (triggering the `super()` constructor which calls `TransactionFactory.register()`), so no manual registration code is needed. + ```java +import static org.tron.core.config.Parameter.ChainConstant.TRANSFER_FEE; + public class SumActuator extends AbstractActuator { public SumActuator() { @@ -210,48 +218,47 @@ At last, run a test class to validate whether the above steps are correct: ```java public class SumActuatorTest { private static final Logger logger = LoggerFactory.getLogger("Test"); - private String serviceNode = "127.0.0.1:50051"; - private String confFile = "config-localtest.conf"; - private String dbPath = "output-directory"; - private TronApplicationContext context; - private Application appTest; - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; + private static final String SERVICE_NODE = "127.0.0.1:50051"; + + @ClassRule + public static TemporaryFolder temporaryFolder = new TemporaryFolder(); + + @Rule + public Timeout timeout = new Timeout(30, TimeUnit.SECONDS); + + private static TronApplicationContext context; + private static Application appTest; + private static ManagedChannel channelFull; + private static WalletGrpc.WalletBlockingStub blockingStubFull; /** - * init the application. + * init the application once for all tests in this class. */ - @Before - public void init() { - CommonParameter argsTest = Args.getInstance(); - Args.setParam(new String[]{"--output-directory", dbPath}, - confFile); + @BeforeClass + public static void init() throws IOException { + Args.setParam(new String[]{"--output-directory", + temporaryFolder.newFolder().toString()}, "config-localtest.conf"); context = new TronApplicationContext(DefaultConfig.class); - RpcApiService rpcApiService = context.getBean(RpcApiService.class); appTest = ApplicationFactory.create(context); - appTest.addService(rpcApiService); - appTest.initServices(argsTest); - appTest.startServices(); appTest.startup(); - channelFull = ManagedChannelBuilder.forTarget(serviceNode) + channelFull = ManagedChannelBuilder.forTarget(SERVICE_NODE) .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); } /** - * destroy the context. + * destroy the context after all tests finish. */ - @After - public void destroy() throws InterruptedException { + @AfterClass + public static void destroy() throws InterruptedException { if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); + channelFull.shutdown(); + channelFull.awaitTermination(5, TimeUnit.SECONDS); } - Args.clearParam(); - appTest.shutdownServices(); appTest.shutdown(); context.destroy(); - FileUtil.deleteDir(new File(dbPath)); + Args.clearParam(); } @Test diff --git a/docs/implement-a-customized-actuator-zh.md b/docs/implement-a-customized-actuator-zh.md index a03f6aeb228..1c2bcd8f082 100644 --- a/docs/implement-a-customized-actuator-zh.md +++ b/docs/implement-a-customized-actuator-zh.md @@ -38,13 +38,19 @@ message Transaction { AccountCreateContract = 0; TransferContract = 1; ........ - SumContract = 52; + SumContract = 60; } ... } ``` -然后还需要注册一个方法来保证 gRPC 能够接收并识别该类型合约的请求,目前 gRPC 协议统一定义在 src/main/protos/api/api.proto,在 api.proto 中的 Wallet Service 新增 `InvokeSum` 接口: +然后还需要注册一个方法来保证 gRPC 能够接收并识别该类型合约的请求,目前 gRPC 协议统一定义在 src/main/protos/api/api.proto。首先在 `api.proto` 顶部添加对新 proto 文件的 import: + +```protobuf +import "core/contract/math_contract.proto"; +``` + +然后在 Wallet service 中新增 `InvokeSum` 接口: ```protobuf service Wallet { @@ -62,13 +68,11 @@ service Wallet { ``` 最后重新编译修改过 proto 文件,可自行编译也可直接通过编译 java-tron 项目来编译 proto 文件: -*目前 java-tron 采用的是 protoc v3.4.0,自行编译时确保 protoc 版本一致。* - ```shell -# recommended +# 推荐方式 —— 直接编译项目,proto 文件会自动重新编译 ./gradlew build -x test -# or build via protoc +# 或者手动使用 protoc(版本需与 build.gradle 中声明的一致) protoc -I=src/main/protos -I=src/main/protos/core --java_out=src/main/java Tron.proto protoc -I=src/main/protos/core/contract --java_out=src/main/java math_contract.proto protoc -I=src/main/protos/api -I=src/main/protos/core -I=src/main/protos --java_out=src/main/java api.proto @@ -80,7 +84,11 @@ protoc -I=src/main/protos/api -I=src/main/protos/core -I=src/main/protos --java 目前 java-tron 默认支持的 Actuator 存放在该模块的 org.tron.core.actuator 目录下,同样在该目录下创建 `SumActuator` : +> **注意**:Actuator 必须放在 `org.tron.core.actuator` 包下。节点启动时,`TransactionRegister.registerActuator()` 会通过反射扫描该包,自动发现所有 `AbstractActuator` 的子类,并各实例化一次(触发 `super()` 构造器,进而调用 `TransactionFactory.register()`)。因此无需手动编写注册代码。 + ```java +import static org.tron.core.config.Parameter.ChainConstant.TRANSFER_FEE; + public class SumActuator extends AbstractActuator { public SumActuator() { @@ -212,48 +220,47 @@ public class WalletApi extends WalletImplBase { ```java public class SumActuatorTest { private static final Logger logger = LoggerFactory.getLogger("Test"); - private String serviceNode = "127.0.0.1:50051"; - private String confFile = "config-localtest.conf"; - private String dbPath = "output-directory"; - private TronApplicationContext context; - private Application appTest; - private ManagedChannel channelFull = null; - private WalletGrpc.WalletBlockingStub blockingStubFull = null; + private static final String SERVICE_NODE = "127.0.0.1:50051"; + + @ClassRule + public static TemporaryFolder temporaryFolder = new TemporaryFolder(); + + @Rule + public Timeout timeout = new Timeout(30, TimeUnit.SECONDS); + + private static TronApplicationContext context; + private static Application appTest; + private static ManagedChannel channelFull; + private static WalletGrpc.WalletBlockingStub blockingStubFull; /** - * init the application. + * 整个测试类只初始化一次应用上下文。 */ - @Before - public void init() { - CommonParameter argsTest = Args.getInstance(); - Args.setParam(new String[]{"--output-directory", dbPath}, - confFile); + @BeforeClass + public static void init() throws IOException { + Args.setParam(new String[]{"--output-directory", + temporaryFolder.newFolder().toString()}, "config-localtest.conf"); context = new TronApplicationContext(DefaultConfig.class); - RpcApiService rpcApiService = context.getBean(RpcApiService.class); appTest = ApplicationFactory.create(context); - appTest.addService(rpcApiService); - appTest.initServices(argsTest); - appTest.startServices(); appTest.startup(); - channelFull = ManagedChannelBuilder.forTarget(serviceNode) + channelFull = ManagedChannelBuilder.forTarget(SERVICE_NODE) .usePlaintext() .build(); blockingStubFull = WalletGrpc.newBlockingStub(channelFull); } /** - * destroy the context. + * 所有测试结束后统一销毁上下文。 */ - @After - public void destroy() throws InterruptedException { + @AfterClass + public static void destroy() throws InterruptedException { if (channelFull != null) { - channelFull.shutdown().awaitTermination(5, TimeUnit.SECONDS); + channelFull.shutdown(); + channelFull.awaitTermination(5, TimeUnit.SECONDS); } - Args.clearParam(); - appTest.shutdownServices(); appTest.shutdown(); context.destroy(); - FileUtil.deleteDir(new File(dbPath)); + Args.clearParam(); } @Test diff --git a/docs/modular-deployment-en.md b/docs/modular-deployment-en.md index ef48f54b269..c93ba6c39d8 100644 --- a/docs/modular-deployment-en.md +++ b/docs/modular-deployment-en.md @@ -1,8 +1,8 @@ # How to deploy java-tron after modularization -After modularization, java-tron is launched via shell script instead of typing command: `java -jar FullNode.jar`. +After modularization, the recommended way to launch java-tron is via the shell script generated in `bin/`. The classic `java -jar FullNode.jar` command is still fully supported as an alternative. -*`java -jar FullNode.jar` still works, but will be deprecated in future*. +> **Supported platforms**: Linux and macOS. Windows is not supported. ## Download @@ -29,7 +29,7 @@ After unzip, two directories will be generated in java-tron: `bin` and `lib`, sh ## Startup -Use the corresponding script to start java-tron according to the OS type, use `*.bat` on Windows, Linux demo is as below: +Use the shell script to start java-tron (Linux / macOS): ``` # default java-tron-1.0.0/bin/FullNode @@ -45,12 +45,11 @@ java-tron-1.0.0/bin/FullNode -c config.conf -w JVM options can also be specified, located in `bin/java-tron.vmoptions`: ``` -# demo --XX:+UseConcMarkSweepGC +# demo (compatible with JDK 8 / JDK 17) +-Xms2g +-Xmx9g -XX:+PrintGCDetails -Xloggc:./gc.log -XX:+PrintGCDateStamps --XX:+CMSParallelRemarkEnabled -XX:ReservedCodeCacheSize=256m --XX:+CMSScavengeBeforeRemark ``` \ No newline at end of file diff --git a/docs/modular-deployment-zh.md b/docs/modular-deployment-zh.md index 54a42df7d1f..27cc2ab3856 100644 --- a/docs/modular-deployment-zh.md +++ b/docs/modular-deployment-zh.md @@ -1,8 +1,8 @@ # 模块化后的 java-tron 部署方式 -模块化后,命令行下的程序启动方式将不再使用 `java -jar FullNode.jar` 的方式启动,而是使用脚本的方式启动,本文内容基于 develop 分支。 +模块化后,推荐使用 `bin/` 目录下生成的脚本启动 java-tron。原有的 `java -jar FullNode.jar` 方式仍完全支持,作为备选方式使用。 -*原有的启动方式依然保留,但即将废弃*。 +> **支持平台**:Linux 和 macOS。不支持 Windows。 ## 下载 @@ -29,7 +29,7 @@ unzip -o java-tron-1.0.0.zip ## 启动 -不同的 os 对应不同脚本,windows 即为 bat 文件,以 linux 系统为例启动 java-tron: +使用脚本启动 java-tron(Linux / macOS): ``` # 默认配置文件启动 java-tron-1.0.0/bin/FullNode @@ -43,12 +43,11 @@ java-tron-1.0.0/bin/FullNode -c config.conf -w java-tron 支持对 jvm 参数进行配置,配置文件为 bin 目录下的 java-tron.vmoptions 文件。 ``` -# demo --XX:+UseConcMarkSweepGC +# demo(兼容 JDK 8 / JDK 17) +-Xms2g +-Xmx9g -XX:+PrintGCDetails -Xloggc:./gc.log -XX:+PrintGCDateStamps --XX:+CMSParallelRemarkEnabled -XX:ReservedCodeCacheSize=256m --XX:+CMSScavengeBeforeRemark ``` \ No newline at end of file diff --git a/docs/modular-introduction-en.md b/docs/modular-introduction-en.md index eab212e9771..1a4827ded42 100644 --- a/docs/modular-introduction-en.md +++ b/docs/modular-introduction-en.md @@ -16,7 +16,7 @@ The aim of java-tron modularization is to enable developers to easily build a de ![modular-structure](https://github.com/tronprotocol/java-tron/blob/develop/docs/images/module.png) -A modularized java-tron consists of six modules: framework, protocol, common, chainbase, consensus and actuator. The function of each module is elaborated below. +A modularized java-tron consists of eight modules: framework, protocol, common, chainbase, consensus, actuator, crypto and plugins. The function of each module is elaborated below. ### framework @@ -67,4 +67,11 @@ Actuator module defines the `Actuator` interface, which includes 4 different met 4. calcFee: define the logic of calculating transaction fees Depending on their businesses, developers may set up Actuator accordingly and customize the processing of different types of transactions. - \ No newline at end of file + +### crypto + +Crypto module encapsulates cryptographic primitives used across the project, including elliptic curve key operations, hash functions and signature verification. It depends only on `common` and has no dependency on other business modules, keeping cryptographic logic isolated and auditable. + +### plugins + +Plugins module provides standalone operational tools packaged as independent executable JARs, such as `Toolkit.jar` and `ArchiveManifest.jar`. These tools support database maintenance tasks like migration, compaction and lite-node data pruning, and can be run without starting a full node. diff --git a/docs/modular-introduction-zh.md b/docs/modular-introduction-zh.md index ba2c5d4b8f5..58d8d172a7f 100644 --- a/docs/modular-introduction-zh.md +++ b/docs/modular-introduction-zh.md @@ -14,7 +14,7 @@ java-tron 模块化的目的是为了帮助开发者方便地构建出特定应 ![modular-structure](https://github.com/tronprotocol/java-tron/blob/develop/docs/images/module.png) -模块化后的 java-tron 目前分为6个模块:framework、protocol、common、chainbase、consensus、actuator,下面分别简单介绍一下各个模块的作用。 +模块化后的 java-tron 目前分为8个模块:framework、protocol、common、chainbase、consensus、actuator、crypto、plugins,下面分别简单介绍一下各个模块的作用。 ### framework @@ -65,4 +65,11 @@ actuator模块定义了 Actuator 接口,该接口有4个方法: 4. calcFee: 定义交易手续费计算逻辑 开发者可以根据自身业务实现 Actuator 接口,就能实现自定义交易类型的处理。 - \ No newline at end of file + +### crypto + +crypto 模块封装了项目中使用的密码学原语,包括椭圆曲线密钥操作、哈希函数及签名验证等。该模块仅依赖 `common`,不依赖其他业务模块,保持密码学逻辑的独立性与可审计性。 + +### plugins + +plugins 模块提供独立的运维工具,打包为可单独执行的 JAR(如 `Toolkit.jar`、`ArchiveManifest.jar`)。这些工具支持数据库迁移、压缩、轻节点数据裁剪等维护任务,无需启动完整节点即可运行。