Skip to content

Commit 296a784

Browse files
committed
feat(toolkit): add --exclude-historical-balance for lite snapshot split
Default behavior is unchanged: balance-trace and account-trace stay in the lite snapshot as before, so default operators (historyBalanceLookup=off) see no difference. Opt-in via `--exclude-historical-balance=true` on `split -t snapshot` excludes the two trace stores from the snapshot for size-conscious operators. A loud warning is printed at split time noting that this loss is permanent for nodes that had historyBalanceLookup=true (merge cannot restore the feature) and that operators who need historical balance lookup on the resulting lite node must NOT enable this flag. `split -t history` and `merge` ignore the flag and continue using the legacy 5-db archive set, so merge logic stays untouched. Includes: - DbLite: new CLI option, helper method, runtime warning. - README: parameter documentation and worked example. - DbLiteTest: 3-arg testTools overload and packaging-contract assertion. - DbLiteExcludeHistoricalBalanceRocksDbTest: opt-in path coverage. close #6597
1 parent 980c707 commit 296a784

4 files changed

Lines changed: 108 additions & 6 deletions

File tree

plugins/README.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,16 +75,20 @@ DB lite provides lite database, parameters are compatible with previous `LiteFul
7575
- `-fn | --fn-data-path`: The database path to be split or merged.
7676
- `-ds | --dataset-path`: When operation is `split`,`dataset-path` is the path that store the `snapshot` or `history`, when
7777
operation is `split`, `dataset-path` is the `history` data path.
78+
- `--exclude-historical-balance`: Only used with `operate=split -t snapshot`, default: false. When set to true, `balance-trace` and `account-trace` are excluded from the lite snapshot. The flag has functional impact only when the source full node ran with `historyBalanceLookup=true` (off by default; most operators are unaffected). **WARNING:** for nodes that had `historyBalanceLookup=true`, this loss is permanent — a lite node booted from such a snapshot cannot answer historical balance lookups (`getBlockBalance` / `getAccountBalance`), and running `merge` afterwards will NOT restore the feature. If you need historical balance lookup on the resulting lite node, do **not** enable this flag. `split -t history` and `merge` ignore this flag.
7879
- `-h | --help`: Provide the help info.
7980

8081
### Examples:
8182

8283
```shell script
8384
# full command
84-
java -jar Toolkit.jar db lite [-h] -ds=<datasetPath> -fn=<fnDataPath> [-o=<operate>] [-t=<type>]
85+
java -jar Toolkit.jar db lite [-h] -ds=<datasetPath> -fn=<fnDataPath> [-o=<operate>] [-t=<type>] [--exclude-historical-balance]
8586
# examples
8687
#split and get a snapshot dataset
8788
java -jar Toolkit.jar db lite -o split -t snapshot --fn-data-path output-directory/database --dataset-path /tmp
89+
#split and get a snapshot dataset without balance-trace / account-trace (smaller snapshot;
90+
#historical balance lookup will be permanently unavailable on the resulting lite node)
91+
java -jar Toolkit.jar db lite -o split -t snapshot --fn-data-path output-directory/database --dataset-path /tmp --exclude-historical-balance
8892
#split and get a history dataset
8993
java -jar Toolkit.jar db lite -o split -t history --fn-data-path output-directory/database --dataset-path /tmp
9094
#merge history dataset and snapshot dataset

plugins/src/main/java/common/org/tron/plugins/DbLite.java

Lines changed: 65 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import java.util.concurrent.Callable;
2121
import java.util.stream.Collectors;
2222
import java.util.stream.LongStream;
23+
import java.util.stream.Stream;
2324
import lombok.extern.slf4j.Slf4j;
2425
import me.tongfei.progressbar.ProgressBar;
2526
import org.rocksdb.RocksDBException;
@@ -57,6 +58,8 @@ public class DbLite implements Callable<Integer> {
5758
private static final String TRANSACTION_HISTORY_DB_NAME = "transactionHistoryStore";
5859
private static final String PROPERTIES_DB_NAME = "properties";
5960
private static final String TRANS_CACHE_DB_NAME = "trans-cache";
61+
private static final String BALANCE_TRACE_DB_NAME = "balance-trace";
62+
private static final String ACCOUNT_TRACE_DB_NAME = "account-trace";
6063

6164
private static final List<String> archiveDbs = Arrays.asList(
6265
BLOCK_DB_NAME,
@@ -65,6 +68,10 @@ public class DbLite implements Callable<Integer> {
6568
TRANSACTION_RET_DB_NAME,
6669
TRANSACTION_HISTORY_DB_NAME);
6770

71+
private static final List<String> traceDbs = Arrays.asList(
72+
BALANCE_TRACE_DB_NAME,
73+
ACCOUNT_TRACE_DB_NAME);
74+
6875
enum Operate { split, merge }
6976

7077
enum Type { snapshot, history }
@@ -105,8 +112,25 @@ enum Type { snapshot, history }
105112
private String datasetPath;
106113

107114
@CommandLine.Option(
108-
names = {"--help", "-h"},
115+
names = {"--exclude-historical-balance"},
116+
defaultValue = "false",
117+
description = "only used with `operate=split -t snapshot`: when true, balance-trace "
118+
+ "and account-trace are excluded from the lite snapshot. "
119+
+ "Default: ${DEFAULT-VALUE} (legacy behavior; trace stores stay in the snapshot). "
120+
+ "This flag only has a functional impact when the source full node ran with "
121+
+ "`historyBalanceLookup=true` (off by default; most operators are unaffected). "
122+
+ "WARNING: when historyBalanceLookup was enabled, this loss is permanent: a lite "
123+
+ "node booted from such a snapshot cannot answer historical balance lookups "
124+
+ "(getBlockBalance / getAccountBalance), and running merge afterwards will NOT "
125+
+ "restore the feature. If you need to keep historyBalanceLookup working on the "
126+
+ "resulting lite node, do NOT enable this flag. `split -t history` and `merge` "
127+
+ "ignore this flag.",
109128
order = 5)
129+
private boolean excludeHistoricalBalance;
130+
131+
@CommandLine.Option(
132+
names = {"--help", "-h"},
133+
order = 6)
110134
private boolean help;
111135

112136

@@ -119,6 +143,7 @@ public Integer call() {
119143
try {
120144
switch (this.operate) {
121145
case split:
146+
warnIfExcludingHistoricalBalance();
122147
if (Type.snapshot == this.type) {
123148
generateSnapshot(fnDataPath, datasetPath);
124149
} else if (Type.history == type) {
@@ -253,12 +278,50 @@ public void completeHistoryData(String historyDir, String liteDir) {
253278
spec.commandLine().getOut().format("Merge history finished, take %d s.", during).println();
254279
}
255280

281+
/**
282+
* Compute the directories to exclude from the lite snapshot.
283+
* <p>
284+
* Default ({@code --exclude-historical-balance=false}): the legacy archive set
285+
* (5 dbs); {@link #BALANCE_TRACE_DB_NAME} / {@link #ACCOUNT_TRACE_DB_NAME}
286+
* stay with the snapshot as state-style stores.
287+
* <p>
288+
* Opt-in ({@code --exclude-historical-balance=true}): the trace stores are
289+
* additionally excluded, producing a smaller lite snapshot at the cost of
290+
* dropping historical balance lookup support on the resulting lite node.
291+
* Only {@code split -t snapshot} consults this. {@code split -t history}
292+
* and {@code merge} always use the legacy archive set.
293+
*/
294+
private List<String> snapshotExclusion() {
295+
if (!excludeHistoricalBalance) {
296+
return archiveDbs;
297+
}
298+
return Stream.concat(archiveDbs.stream(), traceDbs.stream())
299+
.collect(Collectors.toList());
300+
}
301+
302+
private void warnIfExcludingHistoricalBalance() {
303+
if (!excludeHistoricalBalance) {
304+
return;
305+
}
306+
String msg = "WARNING: --exclude-historical-balance is enabled. balance-trace / account-trace "
307+
+ "will be excluded from the lite snapshot. This only matters when the source full "
308+
+ "node ran with historyBalanceLookup=true (off by default; most operators are "
309+
+ "unaffected). When that switch was enabled, this loss is permanent: lite nodes "
310+
+ "booted from this snapshot cannot answer historical balance lookups "
311+
+ "(getBlockBalance / getAccountBalance), and running merge afterwards will NOT "
312+
+ "restore the feature. If you need to keep historyBalanceLookup working on the "
313+
+ "resulting lite node, do NOT use this flag.";
314+
logger.warn(msg);
315+
spec.commandLine().getErr().println(msg);
316+
}
317+
256318
private List<String> getSnapshotDbs(String sourceDir) {
257319
List<String> snapshotDbs = Lists.newArrayList();
258320
File basePath = new File(sourceDir);
321+
List<String> excluded = snapshotExclusion();
259322
Arrays.stream(Objects.requireNonNull(basePath.listFiles()))
260323
.filter(File::isDirectory)
261-
.filter(dir -> !archiveDbs.contains(dir.getName()))
324+
.filter(dir -> !excluded.contains(dir.getName()))
262325
.forEach(dir -> snapshotDbs.add(dir.getName()));
263326
return snapshotDbs;
264327
}

plugins/src/test/java/org/tron/plugins/DbLiteTest.java

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
11
package org.tron.plugins;
22

3+
import static org.junit.Assert.assertFalse;
4+
import static org.junit.Assert.assertTrue;
35
import static org.tron.common.utils.PublicMethod.getRandomPrivateKey;
46

57
import io.grpc.ManagedChannel;
68
import io.grpc.ManagedChannelBuilder;
79
import java.io.File;
810
import java.io.IOException;
11+
import java.nio.file.Path;
912
import java.nio.file.Paths;
1013
import lombok.extern.slf4j.Slf4j;
1114
import org.junit.After;
@@ -89,10 +92,19 @@ public void clear() {
8992

9093
public void testTools(String dbType, int checkpointVersion)
9194
throws InterruptedException, IOException {
92-
logger.info("dbType {}, checkpointVersion {}", dbType, checkpointVersion);
95+
testTools(dbType, checkpointVersion, false);
96+
}
97+
98+
public void testTools(String dbType, int checkpointVersion, boolean excludeHistoricalBalance)
99+
throws InterruptedException, IOException {
100+
logger.info("dbType {}, checkpointVersion {}, excludeHistoricalBalance {}",
101+
dbType, checkpointVersion, excludeHistoricalBalance);
93102
init(dbType);
94-
final String[] argsForSnapshot =
95-
new String[] {"-o", "split", "-t", "snapshot", "--fn-data-path",
103+
final String[] argsForSnapshot = excludeHistoricalBalance
104+
? new String[] {"-o", "split", "-t", "snapshot", "--fn-data-path",
105+
dbPath + File.separator + databaseDir, "--dataset-path",
106+
dbPath, "--exclude-historical-balance"}
107+
: new String[] {"-o", "split", "-t", "snapshot", "--fn-data-path",
96108
dbPath + File.separator + databaseDir, "--dataset-path",
97109
dbPath};
98110
final String[] argsForHistory =
@@ -114,6 +126,16 @@ public void testTools(String dbType, int checkpointVersion)
114126
FileUtil.deleteDir(Paths.get(dbPath, databaseDir, "trans-cache").toFile());
115127
// generate snapshot
116128
cli.execute(argsForSnapshot);
129+
Path snapshotDir = Paths.get(dbPath, "snapshot");
130+
if (excludeHistoricalBalance) {
131+
// when --exclude-historical-balance=true, the lite snapshot must not ship
132+
// balance-trace / account-trace
133+
assertFalse(snapshotDir.resolve("balance-trace").toFile().exists());
134+
assertFalse(snapshotDir.resolve("account-trace").toFile().exists());
135+
} else {
136+
assertTrue(snapshotDir.resolve("balance-trace").toFile().exists());
137+
assertTrue(snapshotDir.resolve("account-trace").toFile().exists());
138+
}
117139
// start fullNode
118140
startApp();
119141
// produce transactions
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package org.tron.plugins.rocksdb;
2+
3+
import java.io.IOException;
4+
import org.junit.Test;
5+
import org.tron.plugins.DbLiteTest;
6+
7+
public class DbLiteExcludeHistoricalBalanceRocksDbTest extends DbLiteTest {
8+
9+
@Test
10+
public void testToolsWithExcludeHistoricalBalance() throws InterruptedException, IOException {
11+
testTools("ROCKSDB", 1, true);
12+
}
13+
}

0 commit comments

Comments
 (0)