Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
54 commits
Select commit Hold shift + click to select a range
5241155
feat(dpp): add ReducedPlatformState stored in replicated state for st…
PastaPastaPasta Aug 28, 2026
61ae581
feat(dashmate): add state sync options to config schema
PastaPastaPasta Aug 28, 2026
0ccf084
feat(dashmate): default state sync on, except for local networks
PastaPastaPasta Aug 28, 2026
3991c40
feat(dashmate): wire state sync into the tenderdash config template
PastaPastaPasta Aug 28, 2026
f5cbbed
feat(dashmate): pass snapshot settings to drive-abci
PastaPastaPasta Aug 28, 2026
04e2b0f
feat(dashmate): migrate configs to the state sync options
PastaPastaPasta Aug 28, 2026
6dedff4
feat(drive): store and fetch reduced platform state bytes in the Misc…
PastaPastaPasta Aug 28, 2026
0ab4b99
feat(dashmate): account for snapshot disk headroom in doctor
PastaPastaPasta Aug 28, 2026
1d9a47a
docs(dashmate): document state sync configuration
PastaPastaPasta Aug 28, 2026
e6ed7e2
style(dashmate): fix lint in new state sync code
PastaPastaPasta Aug 28, 2026
eb8cc28
feat(platform-version): add protocol v15 with state sync version plum…
PastaPastaPasta Aug 28, 2026
ff454d7
feat(drive-abci): run_block_proposal v1 writes reduced platform state…
PastaPastaPasta Aug 28, 2026
63270c7
feat(drive-abci): write initial reduced platform state on transition …
PastaPastaPasta Aug 28, 2026
428052c
fix(dashmate): review fixes for state sync doctor severity and durati…
PastaPastaPasta Aug 28, 2026
3329685
feat(drive-abci): serve state sync snapshots from the checkpoint regi…
PastaPastaPasta Aug 28, 2026
e8892d2
feat(drive-abci): consume state sync snapshots via offer and apply ch…
PastaPastaPasta Aug 28, 2026
4fd9b7a
feat(drive-abci): reconstruct platform state from the reduced state a…
PastaPastaPasta Aug 28, 2026
1d68e82
feat(drive-abci): consensus_params_update v2 emits evidence params on…
PastaPastaPasta Aug 28, 2026
aad6880
test(drive-abci): two-instance state sync integration tests
PastaPastaPasta Aug 29, 2026
832a51f
Merge branch 'feat/state-sync-v15' into feat/state-sync-e2e
PastaPastaPasta Aug 29, 2026
c5897a6
Merge branch 'worktree-agent-a1cb3d1250c0bc43f' (dashmate state sync …
PastaPastaPasta Aug 29, 2026
de645cb
fix(drive-abci): commit state sync re-derivation before publishing re…
PastaPastaPasta Aug 29, 2026
04ca295
feat(dashmate): task to join a full node to a running local network
PastaPastaPasta Aug 29, 2026
2fcffd1
test(dashmate): e2e test for joining a local network via state sync
PastaPastaPasta Aug 29, 2026
685c55b
ci(dashmate): run the state sync e2e spec in the dashmate e2e matrix
PastaPastaPasta Aug 29, 2026
9122f7a
Merge branch 'feat/state-sync-v15' (state sync re-derivation fix de64…
PastaPastaPasta Aug 29, 2026
da186a3
fix(dashmate): harden join task and isolate state sync e2e host ports
PastaPastaPasta Aug 29, 2026
846709e
feat(dashmate): allow more than one join node on a local network
PastaPastaPasta Aug 29, 2026
0a98e9d
test(dashmate): add platform seeding and proof verification helpers f…
PastaPastaPasta Aug 29, 2026
148e547
test(dashmate): seed state and add churn, fallback and ops checks to …
PastaPastaPasta Aug 29, 2026
01e0c35
test(dashmate): make the state sync churn scenario and teardown trust…
PastaPastaPasta Aug 29, 2026
a318665
test(dashmate): fund the seeding wallet from Core and survive a block…
PastaPastaPasta Aug 29, 2026
f6347e5
test(dashmate): dump joiner diagnostics when a state sync never compl…
PastaPastaPasta Aug 29, 2026
80b3155
fix(drive-abci): FEATURE FIX — clear Drive caches when offer_snapshot…
PastaPastaPasta Aug 29, 2026
5185e01
fix(drive-abci): never wedge a node on an interrupted or unusable sta…
PastaPastaPasta Aug 29, 2026
62091fa
test(drive-abci): cover the state sync restore sentinel and the never…
PastaPastaPasta Aug 29, 2026
21af3b4
docs(platform-version): flag the FEE_VERSION2 fee_version_number coll…
PastaPastaPasta Aug 29, 2026
f9848dd
fix(drive-abci): clear the checkpoint registry on wipe and stop faili…
PastaPastaPasta Aug 29, 2026
b3fd742
docs(drive-abci): drop the future wire-v2 framing from state sync docs
PastaPastaPasta Aug 29, 2026
7a4aaca
test(dashmate): activate local sporks on a node that joins after setup
PastaPastaPasta Aug 29, 2026
833d2f3
test(dashmate): give the snapshot headroom and explain a block-sync f…
PastaPastaPasta Aug 29, 2026
dbdfe81
Merge branch 'feat/state-sync-v15' into test/state-sync-qa-live
PastaPastaPasta Aug 29, 2026
1a005de
chore(qa): TEMPORARY grovedb patch to dashpay/grovedb#840 — drop at t…
PastaPastaPasta Aug 29, 2026
b67e4b3
test(dashmate): prove state sync from the ABCI app, not earliest_bloc…
PastaPastaPasta Aug 29, 2026
701c4c6
test(dashmate): scope the state sync restore check to one boot
PastaPastaPasta Aug 29, 2026
18c0819
test(dashmate): read DAPI status through the API it actually exposes
PastaPastaPasta Aug 29, 2026
48b1389
fix(dapi-client): stop rewriting explicit loopback addresses on regtest
PastaPastaPasta Aug 29, 2026
a78d949
fix(wasm-sdk): tolerate masternode discovery failure in trusted conte…
PastaPastaPasta Aug 29, 2026
4c35b54
fix(drive): do not clobber genesis evidence params at InitChain
PastaPastaPasta Aug 29, 2026
a686b03
test(dashmate): make e2e funding and proof verification fail at the b…
PastaPastaPasta Aug 29, 2026
947a99a
test(dashmate): prove the truncated block history state sync promises
PastaPastaPasta Aug 29, 2026
15736ee
fix(wasm-sdk): scope discovery tolerance to regtest; assert restore h…
PastaPastaPasta Aug 29, 2026
7a815ec
test(drive-abci): QA-branch-only — invert the grovedb sum-tree tripwires
PastaPastaPasta Aug 30, 2026
380adfd
test(dashmate): start the seeding wallet scan at the computed core he…
PastaPastaPasta Aug 30, 2026
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: 3 additions & 0 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -530,6 +530,9 @@ jobs:
- name: Local network
test-pattern: test/e2e/localNetwork.spec.js
restore_local_network_data: true
- name: Local network state sync
test-pattern: test/e2e/localNetworkStateSync.spec.js
restore_local_network_data: true
Comment on lines +533 to +535

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

🔴 Blocking: Give the state-sync E2E job enough time to finish

This new matrix entry invokes .github/workflows/tests-dashmate.yml, where the entire reusable job has timeout-minutes: 30. The reported state-sync suite already takes approximately 29 minutes, while that job must also perform checkout, dependency setup, artifact downloads, image pulls, cache or volume restoration, and other preparation; the reusable workflow notes that cold image pulls alone can consume much of 15 minutes. The suite's 120-minute Mocha timeout cannot help because GitHub cancels the enclosing job first. Add a per-matrix timeout input, raise the reusable timeout, split the suite, or reduce its runtime enough to leave meaningful setup and execution margin.

source: ['claude']

- name: Testnet fullnode
test-pattern: test/e2e/testnetFullnode.spec.js
restore_local_network_data: false
Expand Down
3 changes: 3 additions & 0 deletions .pnp.cjs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

32 changes: 16 additions & 16 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

29 changes: 29 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -131,3 +131,32 @@ opt-level = 3

version = "4.2.0-dev.5"
rust-version = "1.92"

# ============================================================================
# TEMPORARY — QA ONLY. DROP THIS AT THE REAL RE-PIN.
#
# Every grovedb crate is pinned in the package manifests to dashpay/grovedb
# rev 6c882c3, which carries a restore defect for sum trees: applying a state
# sync snapshot chunk fails GroveDB verification ("apply_snapshot_chunk grovedb
# verification failed with N incorrect hashes"), so a joining node can never
# complete a state sync. packages/rs-drive-abci/tests/sum_tree_sync_probe.rs
# pins that defect in-tree.
#
# dashpay/grovedb#840 (branch feat/state-sync-v2 on the PastaPastaPasta fork,
# head 10a63e1) fixes it, and its restore wire version is 1, which is inside
# drive-abci's supported set — so no protocol plumbing changes with it.
#
# This section exists so the state sync e2e can be run against the fix before
# the fork is merged and re-pinned by rev. It MUST be removed once the real
# pin lands: a branch reference is not reproducible, and a workspace [patch]
# silently overrides every manifest's rev.
# ============================================================================
[patch."https://github.com/dashpay/grovedb"]
grovedb = { git = "https://github.com/PastaPastaPasta/grovedb", branch = "feat/state-sync-v2" }
grovedb-costs = { git = "https://github.com/PastaPastaPasta/grovedb", branch = "feat/state-sync-v2" }
grovedb-path = { git = "https://github.com/PastaPastaPasta/grovedb", branch = "feat/state-sync-v2" }
grovedb-storage = { git = "https://github.com/PastaPastaPasta/grovedb", branch = "feat/state-sync-v2" }
grovedb-version = { git = "https://github.com/PastaPastaPasta/grovedb", branch = "feat/state-sync-v2" }
grovedb-epoch-based-storage-flags = { git = "https://github.com/PastaPastaPasta/grovedb", branch = "feat/state-sync-v2" }
grovedb-query = { git = "https://github.com/PastaPastaPasta/grovedb", branch = "feat/state-sync-v2" }
grovedb-commitment-tree = { git = "https://github.com/PastaPastaPasta/grovedb", branch = "feat/state-sync-v2" }
Comment on lines +154 to +162

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

🔴 Blocking: Replace the mutable GroveDB fork override before merge

The workspace patch replaces every manifest-pinned GroveDB crate with a branch on a contributor-owned fork. Cargo.lock currently records commit 10a63e1e2dab39b6cc59af8253dc42e187f071c6, but lockfile regeneration or an update follows the branch head, making consensus-critical storage and proof code mutable and dependent on a personal fork. The PR description and in-file comment explicitly identify this override as temporary and release-blocking. Remove the patch and update the package pins and lockfile to the immutable reviewed revision in dashpay/grovedb after the fix merges.

source: ['claude']

17 changes: 17 additions & 0 deletions packages/dashmate/configs/defaults/getBaseConfigFactory.js
Original file line number Diff line number Diff line change
Expand Up @@ -356,6 +356,13 @@ export default function getBaseConfigFactory() {
txProcessingTimeLimit: null,
},
epochTime: 788400,
stateSync: {
snapshots: {
enabled: true,
frequencySeconds: 600,
maxCount: 6,
},
},
},
tenderdash: {
mode: 'full',
Expand Down Expand Up @@ -460,6 +467,16 @@ export default function getBaseConfigFactory() {
},
},
moniker: null,
// Serving snapshots to peers is always on in Tenderdash; `enabled`
// only makes a fresh node bootstrap from a snapshot, and Tenderdash
// ignores it once the node has local state, so it is safe on by
// default for existing nodes.
stateSync: {
enabled: true,
retries: 3,
chunkRequestTimeout: '15s',
fetchersCount: 4,
},
},
},
sourcePath: null,
Expand Down
10 changes: 10 additions & 0 deletions packages/dashmate/configs/defaults/getLocalConfigFactory.js
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,11 @@ export default function getLocalConfigFactory(getBaseConfig) {
metrics: {
port: 46660,
},
// A local network genesis starts every node from scratch at the
// same time, so there is no populated peer to state sync from.
stateSync: {
enabled: false,
},
},
abci: {
tokioConsole: {
Expand Down Expand Up @@ -141,6 +146,11 @@ export default function getLocalConfigFactory(getBaseConfig) {
rotation: false,
},
},
stateSync: {
snapshots: {
enabled: false,
},
},
},
},
},
Expand Down
17 changes: 17 additions & 0 deletions packages/dashmate/configs/getConfigFileMigrationsFactory.js
Original file line number Diff line number Diff line change
Expand Up @@ -1764,6 +1764,23 @@ export default function getConfigFileMigrationsFactory(homeDir, defaultConfigs)

return configFile;
},
'4.2.0-dev.6': (configFile) => {
// State sync options are required by the schema now. Pulled from the
// default config matching each config's name or group, so the local
// preset gets its disables while everything else gets the base
// defaults (consume and serve snapshots).
Object.entries(configFile.configs)
.forEach(([name, options]) => {
const defaultConfig = getDefaultConfigByNameOrGroup(name, options.group);

options.platform.drive.tenderdash.stateSync = defaultConfig
.getStored('platform.drive.tenderdash.stateSync');
options.platform.drive.abci.stateSync = defaultConfig
.getStored('platform.drive.abci.stateSync');
});

return configFile;
},
};
}

Expand Down
5 changes: 5 additions & 0 deletions packages/dashmate/docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,11 @@ services:
- GROVEDB_VISUALIZER_ADDRESS=0.0.0.0:${PLATFORM_DRIVE_ABCI_GROVEDB_VISUALIZER_PORT:?err}
- PROPOSER_TX_PROCESSING_TIME_LIMIT=${PLATFORM_DRIVE_ABCI_PROPOSER_TX_PROCESSING_TIME_LIMIT}
- NETWORK=${NETWORK:?err}
# Checkpoints live in the default CHECKPOINTS_PATH (DB_PATH/checkpoints),
# inside the drive_abci_data volume
- SNAPSHOTS_ENABLED=${PLATFORM_DRIVE_ABCI_STATE_SYNC_SNAPSHOTS_ENABLED:?err}
- SNAPSHOTS_FREQUENCY_SECONDS=${PLATFORM_DRIVE_ABCI_STATE_SYNC_SNAPSHOTS_FREQUENCY_SECONDS:?err}
- MAX_NUM_SNAPSHOTS=${PLATFORM_DRIVE_ABCI_STATE_SYNC_SNAPSHOTS_MAX_COUNT:?err}
stop_grace_period: 30s
expose:
- 26658
Expand Down
12 changes: 12 additions & 0 deletions packages/dashmate/docs/config/drive-abci.md
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,18 @@ These settings control developer and debugging tools:
- Tokio Console: A debugging tool for Rust's async runtime
- GroveDB Visualizer: A visualization tool for the GroveDB database structure

## State Sync Snapshots

These settings control the serving side of state sync: Drive periodically takes GroveDB checkpoints and hands them to Tenderdash, which offers them to peers bootstrapping via state sync. The consuming side is configured on Tenderdash (see [Tenderdash configuration](./tenderdash.md#state-sync)).

| Option | Description | Default | Example |
|--------|-------------|---------|---------|
| `platform.drive.abci.stateSync.snapshots.enabled` | Take and serve state sync snapshots | `true` | `false` |
| `platform.drive.abci.stateSync.snapshots.frequencySeconds` | How often to take a snapshot, in seconds, at least 60 | `600` | `3600` |
| `platform.drive.abci.stateSync.snapshots.maxCount` | Snapshots kept before pruning the oldest, at least 2 | `6` | `10` |

Checkpoints are stored inside the Drive data volume under `db/checkpoints`. They hard-link unchanged data, so keeping several costs only a fraction of the database size. The local preset disables snapshots along with state sync consumption.

## Other options

| Option | Description | Default | Example |
Expand Down
15 changes: 15 additions & 0 deletions packages/dashmate/docs/config/tenderdash.md
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,21 @@ The RPC interface is used for:
- Submitting transactions
- Fetching network status

## State Sync

State sync bootstraps a fresh node from a recent state snapshot fetched from peers instead of replaying every block. These settings control the consuming side; serving snapshots to peers is always on in Tenderdash and is fed by Drive's snapshots (see [Drive ABCI configuration](./drive-abci.md#state-sync-snapshots)).

| Option | Description | Default | Example |
|--------|-------------|---------|---------|
| `platform.drive.tenderdash.stateSync.enabled` | Bootstrap a fresh node from a snapshot | `true` | `false` |
| `platform.drive.tenderdash.stateSync.retries` | Retries before falling back to block sync, `0` disables retries | `3` | `5` |
| `platform.drive.tenderdash.stateSync.chunkRequestTimeout` | Timeout before re-requesting a snapshot chunk, at least `5s` | `15s` | `30s` |
| `platform.drive.tenderdash.stateSync.fetchersCount` | Concurrent chunk fetchers, 1 to 64 | `4` | `8` |

- Enabling is safe for existing nodes: Tenderdash only attempts state sync when the node has no local state and disables it by itself otherwise. Only a freshly set up (or reset) node consumes a snapshot, and it ends up with a truncated block history starting at the snapshot height.
- Snapshots are verified through the P2P layer. The alternative RPC state provider needs at least two reachable Tenderdash RPC servers, but dashmate publishes the Tenderdash RPC on loopback only, without TLS and unproxied by the gateway, so the rendered config hardcodes `use-p2p = true`.
- The local preset disables state sync: a local network genesis starts every node from scratch, so there is no populated peer to sync from.

## Metrics and Profiling

These settings control monitoring and profiling tools:
Expand Down
3 changes: 3 additions & 0 deletions packages/dashmate/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -102,8 +102,11 @@
},
"devDependencies": {
"@babel/core": "^7.26.10",
"@dashevo/dpns-contract": "workspace:*",
"@dashevo/evo-sdk": "workspace:*",
"chai": "^4.3.10",
"chai-as-promised": "^7.1.1",
"dash": "workspace:*",
"dirty-chai": "^2.0.1",
"eslint": "^9.18.0",
"globby": "^11",
Expand Down
Loading
Loading