Skip to content

feat(archive): add historical state archive support - #136

Open
halibobo1205 wants to merge 168 commits into
developfrom
feat/archive-node
Open

feat(archive): add historical state archive support#136
halibobo1205 wants to merge 168 commits into
developfrom
feat/archive-node

Conversation

@halibobo1205

Copy link
Copy Markdown
Owner

Summary

  • Add an opt-in archive sidecar for transaction-level historical state.
  • Provide canonical historical reads without fallback to live state.
  • Add asynchronous publication, backpressure, fail-stop recovery, schema validation, and metrics.

Supported Historical APIs

API Description
eth_getBalance Query historical TRX account balances
eth_getCode Query historical contract runtime bytecode
eth_getStorageAt Query historical contract storage slots
eth_call Execute read-only TVM contract calls against historical state

Validation

Archive/Historical regression suites, private-chain E2E, restart/offline database checks, and SIGKILL recovery passed. The feature remains disabled by default pending mainnet scale and soak validation.

…ministic-proto for map-bearing domains, contract abi-strip)
…ct store-specific + service wiring + enabled integration test)
…ced import emits redundant value-correct record)
…t/getCode/getStorage, three-state, no latest fallback, inclusive-after)
… cursor; survives restart, mirrors temporal store)
…ervice (temporal/ + index/ subdirs, close both)
…geAt/getCode via archive (resolver + adapter, latest/disabled preserved)
@codeant-ai

codeant-ai Bot commented Jul 27, 2026

Copy link
Copy Markdown

Skipping CodeAnt AI review — this PR changes more than 100 files, which usually means a migration, codemod, or vendored drop. Line-level review on diffs this large produces duplicate findings on the same rewrite pattern and drowns out anything that actually matters.

If you still want a review, comment @codeant-ai : review. For better signal, consider splitting the PR into smaller chunks.

@github-actions

Copy link
Copy Markdown

❌ Math Usage Detection Results

Found forbidden usage of java.lang.Math in the following files:

./chainbase/src/main/java/org/tron/common/storage/rocksdb/RocksDbDataSourceImpl.java
./chainbase/src/main/java/org/tron/core/archive/ArchiveDiskSpaceSampler.java
./chainbase/src/main/java/org/tron/core/archive/ArchiveInFlightCodec.java
./chainbase/src/main/java/org/tron/core/archive/ArchiveLifecycle.java
./chainbase/src/main/java/org/tron/core/archive/ArchiveMetrics.java
./chainbase/src/main/java/org/tron/core/archive/ArchiveRocksReadOptions.java
./chainbase/src/main/java/org/tron/core/archive/DefaultArchiveService.java
./chainbase/src/main/java/org/tron/core/archive/capture/ArchiveCaptureEngine.java
./chainbase/src/main/java/org/tron/core/archive/capture/ArchiveChangeRecord.java
./chainbase/src/main/java/org/tron/core/archive/identity/UnifiedArchiveIdentityPayload.java
./chainbase/src/main/java/org/tron/core/archive/query/ArchiveQueryCoordinator.java
./chainbase/src/main/java/org/tron/core/archive/query/ArchiveQueryRequestScope.java
./chainbase/src/main/java/org/tron/core/archive/query/QueryContext.java
./chainbase/src/main/java/org/tron/core/archive/reader/DefaultArchiveStateReader.java
./chainbase/src/main/java/org/tron/core/archive/txnum/InMemoryArchiveTxNumIndex.java
./chainbase/src/main/java/org/tron/core/archive/unified/UnifiedArchiveDb.java
./chainbase/src/test/java/org/tron/core/archive/ArchiveInFlightValidatorTest.java
./chainbase/src/test/java/org/tron/core/archive/DefaultArchiveServiceAsyncPublisherTest.java
./chainbase/src/test/java/org/tron/core/archive/DefaultArchiveServiceIncrementalDifferentialTest.java
./chainbase/src/test/java/org/tron/core/archive/UnifiedArchiveBackendTest.java
./chainbase/src/test/java/org/tron/core/archive/capture/ArchiveCaptureEngineTest.java
./chainbase/src/test/java/org/tron/core/archive/query/ArchiveQueryRequestScopeTest.java
./chainbase/src/test/java/org/tron/core/archive/temporal/UnifiedArchiveTemporalStoreOracleTest.java
./framework/src/main/java/org/tron/core/db/Manager.java
./framework/src/main/java/org/tron/core/services/jsonrpc/ArchiveJsonRpcExecutor.java
./framework/src/main/java/org/tron/core/services/jsonrpc/JsonRpcServlet.java

Please review if this usage is intended.

Caution

Note: You should use org.tron.common.math.StrictMathWrapper.
If you need to use java.lang.Math, please provide a justification.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 4655abb5ac

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +235 to +237
if (isNotification(rootNode)) {
output.discard();
writeEmptyResponse(resp);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Return errors for malformed id-less requests

Do not classify every object without an id as a notification. For malformed requests such as {} or {"jsonrpc":"2.0","method":1}, rpcServer.handleRequest can serialize an Invalid Request response with a null ID, but this branch discards it solely because the original object lacks id. This regresses both single requests and batch elements from returning the required error to returning no response; only structurally valid notification requests should suppress output.

Useful? React with 👍 / 👎.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: b18587edc1

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread build.gradle Outdated
Comment on lines +83 to +89
if (project.hasProperty('testJavaVersion')) {
tasks.withType(Test).configureEach {
javaLauncher.set(javaToolchains.launcherFor {
languageVersion = JavaLanguageVersion.of(
Integer.parseInt(project.property('testJavaVersion').toString()))
})
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Keep Error Prone tests on the build JVM

Exclude the errorprone project from this JDK 8 launcher override. In the checked docker-build-rockylinux and docker-build-debian11 jobs, clean build passes -PtestJavaVersion=8, so this block also launches :errorprone:test on JDK 8; however, errorprone/build.gradle enables those tests because Gradle itself runs on JDK 17 and supplies Java 9+ --add-exports/--add-opens options. JDK 8 cannot start that test JVM, causing both required x86 builds to fail before validating the application tests.

Useful? React with 👍 / 👎.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

public static double pow(double a, double b) {
double strictResult = StrictMath.pow(a, b);
return powData.getOrDefault(new PowData(a, b), strictResult);

P1 Badge Preserve the pre-fork x86 Math implementation

When allowStrictMath and the hardened exchange calculation are disabled, ExchangeTransactionActuator deliberately routes consensus exchange pricing through Maths.pow(..., false), but moving the ARM wrapper into the common source set makes that path call StrictMath.pow on x86 instead of the previous Math.pow. These functions can differ by one ULP and change the integer payout—for example, balances 206236204630717/954057449968570 and quantity 120133495269460 produce 351179218498520 with Math but 351179218498519 with StrictMath—so upgraded and older x86 nodes can compute different state on chains where the proposal remains inactive. Keep the x86 implementation until the existing consensus flag selects strict math.

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Route archive math through StrictMathWrapper, keep tests compatible with JDK 8 and both bundled RocksDB versions, document every archive reference setting, and restore protobuf plugin verification metadata.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: c03b17bac1

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".


private boolean isHistoricalArchiveCall() {
Repository repository = getDeposit();
return isConstantCall() && repository != null && repository.isHistoricalArchive();

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Route non-constant historical replays through bounded proof execution

When debug_traceTransaction replays a transaction that invokes VerifyTransferProof, HistoricalDebugTraceExecutor passes constantCall=false even though the repository is historical. This predicate therefore returns false, selecting the canonical workersInNonConstantCall pool and awaitLegacyProofTasks; after its timed latch wait, that path performs unbounded Future.get() calls and does not cancel unfinished work. Such traces can exceed the archive query deadline, occupy the dedicated trace worker, and contend with canonical proof execution. Classify any historical archive repository as historical here, independently of the constant-call flag.

Useful? React with 👍 / 👎.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: a0616c8879

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +85 to +86
if (configuredArchivePath.isAbsolute()) {
protectedPaths.add(canonicalDbRoot);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Reject relative archive paths that overlap canonical stores

Protect the canonical database layout for relative paths as well. With archive enabled, values such as storage.archive.db.directory = "." or "account" resolve to the canonical DB root or an existing default store directory, but this conditional omits canonicalDbRoot from conflict validation solely because the value is relative. The archive can therefore open its unified RocksDB over canonical node storage, causing incompatible data to share a directory and risking database corruption; allow the default archive child explicitly while rejecting the root and known store children.

Useful? React with 👍 / 👎.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant