Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -80,8 +80,7 @@ The java-tron project comes with several runnable artifacts and helper scripts f
| :---------------------- | :---------- |
| **`FullNode.jar`** | Main TRON node executable (generated in `build/libs/` after a successful build following the above guidance). Runs as a full node by default. `java -jar FullNode.jar --help` for command line options|
| **`Toolkit.jar`** | Node management utility (generated in `build/libs/`): partition, prune, copy, convert DBs; shadow-fork tool. [Usage](https://tronprotocol.github.io/documentation-en/using_javatron/toolkit/#toolkit-a-java-tron-node-maintenance-suite) |
| **`start.sh`** | Quick start script (x86_64, JDK 8) to download/build/run `FullNode.jar`. See the tool [guide](./shell.md). |
| **`start.sh.simple`** | Quick start script template (ARM64, JDK 17). See usage notes inside the script. |
| **`start.sh`** | Quick start script to download/build/run `FullNode.jar` on x86_64 (JDK 8) and ARM64 (JDK 17). See the tool [guide](./shell.md). |

# Running java-tron

Expand Down
31 changes: 0 additions & 31 deletions chainbase/src/main/java/org/tron/core/db/KhaosDatabase.java
Original file line number Diff line number Diff line change
Expand Up @@ -205,37 +205,6 @@ private void checkNull(Object o) throws NonCommonBlockException {
}
}

/**
* Find two block's most recent common parent block.
*/
@Deprecated
public Pair<LinkedList<BlockCapsule>, LinkedList<BlockCapsule>> getBranch(
BlockId block1, BlockId block2) {
LinkedList<BlockCapsule> list1 = new LinkedList<>();
LinkedList<BlockCapsule> list2 = new LinkedList<>();
KhaosBlock kblk1 = miniStore.getByHash(block1);
KhaosBlock kblk2 = miniStore.getByHash(block2);

if (kblk1 != null && kblk2 != null) {
while (!Objects.equals(kblk1, kblk2)) {
if (kblk1.num > kblk2.num) {
list1.add(kblk1.blk);
kblk1 = kblk1.getParent();
} else if (kblk1.num < kblk2.num) {
list2.add(kblk2.blk);
kblk2 = kblk2.getParent();
} else {
list1.add(kblk1.blk);
list2.add(kblk2.blk);
kblk1 = kblk1.getParent();
kblk2 = kblk2.getParent();
}
}
}

return new Pair<>(list1, list2);
}

// only for unit test
public BlockCapsule getParentBlock(Sha256Hash hash) {
return Stream.of(miniStore.getByHash(hash), miniUnlinkedStore.getByHash(hash))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,10 @@ public abstract class HttpService extends AbstractService {

protected long maxRequestSize = 4 * 1024 * 1024; // 4MB

// Once maxHttpConnectNumber is reached, open connections time out after this much
// inactivity, so connections that send nothing cannot hold every slot.
private static final long CONNECTION_LIMIT_IDLE_TIMEOUT_MS = 10_000;

@VisibleForTesting
public long getMaxRequestSize() {
return this.maxRequestSize;
Expand Down Expand Up @@ -80,7 +84,9 @@ protected void initServer() {
this.apiServer = new Server(this.port);
int maxHttpConnectNumber = Args.getInstance().getMaxHttpConnectNumber();
if (maxHttpConnectNumber > 0) {
this.apiServer.addBean(new ConnectionLimit(maxHttpConnectNumber, this.apiServer));
ConnectionLimit connectionLimit = new ConnectionLimit(maxHttpConnectNumber, this.apiServer);
connectionLimit.setIdleTimeout(CONNECTION_LIMIT_IDLE_TIMEOUT_MS);
this.apiServer.addBean(connectionLimit);
}
this.apiServer.setErrorHandler(new OversizedRequestErrorHandler());
}
Expand Down
6 changes: 4 additions & 2 deletions framework/src/main/java/org/tron/core/config/args/Args.java
Original file line number Diff line number Diff line change
Expand Up @@ -1017,14 +1017,16 @@ private static void loadDnsPublishParameters(NodeConfig.DnsConfig dns,
if (dns.getChangeThreshold() > 0) {
publishConfig.setChangeThreshold(dns.getChangeThreshold());
} else if (Double.compare(dns.getChangeThreshold(), 0.0) != 0) {
logger.error("Check node.dns.changeThreshold, should be bigger than 0, default 0.1");
throw new TronError("Check node.dns.changeThreshold, should be bigger than 0, default 0.1",
TronError.ErrCode.PARAMETER_INIT);
}

int maxMergeSize = dns.getMaxMergeSize();
if (maxMergeSize >= 1 && maxMergeSize <= 5) {
publishConfig.setMaxMergeSize(maxMergeSize);
} else if (maxMergeSize != 0) {
logger.error("Check node.dns.maxMergeSize, should be [1~5], default 5");
throw new TronError("Check node.dns.maxMergeSize, should be [1~5], default 5",
TronError.ErrCode.PARAMETER_INIT);
}

if (StringUtils.isNotEmpty(dns.getDnsPrivate())) {
Expand Down
1 change: 0 additions & 1 deletion framework/src/main/java/org/tron/core/db/Manager.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
import static org.tron.common.math.Maths.min;
import static org.tron.common.utils.Commons.adjustBalance;
import static org.tron.core.Constant.TRANSACTION_MAX_BYTE_SIZE;
import static org.tron.core.exception.BadBlockException.TypeEnum.CALC_MERKLE_ROOT_FAILED;
import static org.tron.protos.Protocol.Transaction.Contract.ContractType.TransferContract;
import static org.tron.protos.Protocol.Transaction.Result.contractResult.SUCCESS;

Expand Down
148 changes: 148 additions & 0 deletions framework/src/test/java/org/tron/common/jetty/ConnectionLimitTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
package org.tron.common.jetty;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.SocketException;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.server.AbstractConnector;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHolder;
import org.junit.AfterClass;
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.ClassRule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import org.tron.common.TestConstants;
import org.tron.common.application.HttpService;
import org.tron.common.utils.PublicMethod;
import org.tron.core.config.args.Args;

/**
* Tests the connection limit configured in {@link HttpService}: once connections that send
* nothing hold every slot, the server closes them after the limit's idle timeout and serves
* new clients, instead of waiting for the connector's 30-second idle timeout.
*/
public class ConnectionLimitTest {

private static final int MAX_CONNECTIONS = 2;

// Below the connector's default 30-second idle timeout, above the limit's 10-second one
// applied twice (Jetty half-closes an idle connection before closing it).
private static final int TIMEOUT_MS = 25_000;

@ClassRule
public static final TemporaryFolder temporaryFolder = new TemporaryFolder();

private static TestHttpService httpService;
private static int port;

public static class OkServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
resp.setStatus(HttpServletResponse.SC_OK);
resp.getWriter().print("ok");
}
}

static class TestHttpService extends HttpService {
TestHttpService(int port) {
this.port = port;
this.contextPath = "/";
}

@Override
protected void addServlet(ServletContextHandler context) {
context.addServlet(new ServletHolder(new OkServlet()), "/*");
}

int connectedEndPoints() {
return ((AbstractConnector) apiServer.getConnectors()[0]).getConnectedEndPoints().size();
}
}

@BeforeClass
public static void setup() throws Exception {
Args.setParam(new String[]{"-d", temporaryFolder.newFolder().toString()},
TestConstants.TEST_CONF);
Args.getInstance().setMaxHttpConnectNumber(MAX_CONNECTIONS);
port = PublicMethod.chooseRandomPort();
httpService = new TestHttpService(port);
httpService.start().get(10, TimeUnit.SECONDS);
}

@AfterClass
public static void teardown() throws Exception {
try {
if (httpService != null) {
httpService.stop();
}
} finally {
Args.clearParam();
}
}

@Test(timeout = 60_000)
public void testIdleConnectionsDoNotLockOutClients() throws Exception {
List<Socket> idleSockets = new ArrayList<>();
try {
for (int i = 0; i < MAX_CONNECTIONS; i++) {
Socket socket = new Socket();
socket.connect(new InetSocketAddress("localhost", port), TIMEOUT_MS);
idleSockets.add(socket);
awaitConnectedEndPoints(i + 1);
}

Assert.assertEquals("HTTP/1.1 200 OK", get());
for (Socket socket : idleSockets) {
assertClosedByServer(socket);
}
} finally {
for (Socket socket : idleSockets) {
socket.close();
}
}
}

private static void awaitConnectedEndPoints(int expected) throws InterruptedException {
long deadline = System.currentTimeMillis() + TIMEOUT_MS;
while (httpService.connectedEndPoints() < expected) {
Assert.assertTrue("server did not accept connection " + expected,
System.currentTimeMillis() < deadline);
Thread.sleep(10);
}
}

private static String get() throws IOException {
try (Socket socket = new Socket()) {
socket.connect(new InetSocketAddress("localhost", port), TIMEOUT_MS);
socket.setSoTimeout(TIMEOUT_MS);
OutputStream out = socket.getOutputStream();
out.write("GET / HTTP/1.1\r\nHost: localhost\r\nConnection: close\r\n\r\n"
.getBytes(StandardCharsets.US_ASCII));
out.flush();
BufferedReader in = new BufferedReader(
new InputStreamReader(socket.getInputStream(), StandardCharsets.US_ASCII));
return in.readLine();
}
}

private static void assertClosedByServer(Socket socket) throws IOException {
socket.setSoTimeout(TIMEOUT_MS);
try {
Assert.assertEquals(-1, socket.getInputStream().read());
} catch (SocketException e) {
// a reset also means the server dropped the connection
}
}
}
24 changes: 24 additions & 0 deletions framework/src/test/java/org/tron/core/config/args/ArgsTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -544,6 +544,30 @@ public void testDnsPublishRejectsEmptyRequiredParameterWithParameterInitError()
error.getMessage());
}

@Test
public void testDnsPublishRejectsInvalidChangeThresholdWithParameterInitError() {
Config config = dnsPublishConfig("node.dns.changeThreshold", "-0.1");

TronError error = Assert.assertThrows(TronError.class,
() -> Args.loadDnsPublishConfig(NodeConfig.fromConfig(config)));

Assert.assertEquals(TronError.ErrCode.PARAMETER_INIT, error.getErrCode());
Assert.assertEquals("Check node.dns.changeThreshold, should be bigger than 0, default 0.1",
error.getMessage());
}

@Test
public void testDnsPublishRejectsInvalidMaxMergeSizeWithParameterInitError() {
Config config = dnsPublishConfig("node.dns.maxMergeSize", "6");

TronError error = Assert.assertThrows(TronError.class,
() -> Args.loadDnsPublishConfig(NodeConfig.fromConfig(config)));

Assert.assertEquals(TronError.ErrCode.PARAMETER_INIT, error.getErrCode());
Assert.assertEquals("Check node.dns.maxMergeSize, should be [1~5], default 5",
error.getMessage());
}

@Test
public void testCommitteeConfigRejectsOldRewardOptimizationWithoutPrerequisite() {
Map<String, Object> configMap = new HashMap<>();
Expand Down
40 changes: 31 additions & 9 deletions shell.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ If you already downloaded the `FullNode.jar`, you can use `start.sh` to run it,

The script is available in the java-tron project at [github](https://github.com/tronprotocol/java-tron), or if you need a separate script: [start.sh](https://github.com/tronprotocol/java-tron/blob/develop/start.sh)

The script runs on x86_64 with JDK 8 and on ARM64 with JDK 17. It picks the JVM options for the Java version it finds, and downloads the release jars built for that architecture (`FullNode-aarch64.jar` on ARM64).

Downloaded release jars are verified against the GPG signature published with each release, made by the key listed under "Integrity Check" in the [README](./README.md), so `gpg` must be installed; a jar that fails verification is not used. The mainnet config is downloaded from java-tron and the Nile testnet config from [nile-testnet](https://github.com/tron-nile-testnet/nile-testnet).

***

# Usage
Expand All @@ -32,6 +36,8 @@ The script is available in the java-tron project at [github](https://github.com/
sh start.sh --stop
```

`--run` records the process id in `<jar name>.pid` (`FullNode.jar.pid` by default) next to `start.log`, and `--stop` reads it. Run `--stop` in the directory the node was started from, with the same `-j` name if one was given. After `--release` or `-cb` the node runs in `FullNode/`; `--stop` finds it there from the parent directory as well. A node started by an earlier version of the script (a `start.log` but no pid file) is still found by its jar name.

* Get the latest version of `FullNode.jar` and start it

```
Expand All @@ -58,17 +64,21 @@ The script is available in the java-tron project at [github](https://github.com/

start the service

* `--stop`
* `--stop` or `-s`

stop the service started from the current directory

* `--`

stop the service
Everything after it is passed to `FullNode.jar` unchanged. Options the script does not know are passed on as well, so `--` is only needed when a value of such an option looks like a script option or a jar name.

* `-c`

Specify the configuration file, by default it will load the `config.conf` in the same directory as `FullNode.jar`
Specify the configuration file, by default it will load the `config.conf` in the current directory

* `-d`

Specify the database storage path, The default path is the same directory where `FullNode.jar` is located.
Specify the database storage path. The default is `output-directory` in the directory the script is run from (`FullNode/` after `--release` or `-cb`).

* `-j`

Expand All @@ -79,7 +89,7 @@ The script is available in the java-tron project at [github](https://github.com/
Specify the maximum memory of the `FullNode.jar` service in`MB`, jvm's startup maximum memory will be adjusted according to this parameter.

* `--net`
Select test and private networks.
Select test (Nile) and private networks.

### build project

Expand All @@ -91,6 +101,14 @@ The script is available in the java-tron project at [github](https://github.com/

Get the latest released version of the `jar` package from github.

* `--upgrade`

Replace the local `jar` package with the latest release; the previous one is kept as `FullNode.jar_bak`.

* `--download`

Download the latest released `jar` package into the current directory without starting it.


### rebuild the manifest

Expand All @@ -100,7 +118,7 @@ The script is available in the java-tron project at [github](https://github.com/

* `-m`

specify the minimum required manifest file size ,unit:M,default:0
specify the minimum required manifest file size ,unit:M,default:128

* `-b`

Expand Down Expand Up @@ -152,7 +170,7 @@ sh start.sh --stop
Format:

```
sh start.sh <[--release | -cb]> <--run> [-m <manifest size>] | [-b <batch size>] | [-d <db database-directory> | [-dr | --disable-rewrite-manifes]]
sh start.sh <[--release | -cb]> <--run> [-m <manifest size>] | [-b <batch size>] | [-d <db database-directory> | [-dr | --disable-rewrite-manifest]]
```

Get the latest released version.
Expand All @@ -162,13 +180,15 @@ Get the latest released version.
sh start.sh --release --run
```

Following file structure will be generated after executing the above command and the `FullNode.jar` will be started.
Following file structure will be generated after executing the above command and the `FullNode.jar` will be started. The node runs from `FullNode/`, so later `--run` commands are executed there with the copied script; `--stop` works both there and from the parent directory.

```
├── ...
├── FullNode/
├── config.conf
├── FullNode.jar
├── FullNode.jar.pid
├── start.log
├── start.sh
```

Expand Down Expand Up @@ -214,12 +234,14 @@ Following file structure will be created:
├── FullNode/
|── config.conf
├── FullNode.jar
├── FullNode.jar.pid
├── start.log
├── start.sh
```

### 3. rebuild manifest tool

This tool provides the ability to reformat the manifest based on current database, Enabled by default.
This tool provides the ability to reformat the manifest based on current database, Enabled by default. It applies to LevelDB only and is skipped on ARM64, which runs RocksDB.

1.Local mode:

Expand Down
Loading
Loading