Skip to content

feat: add Custom Chain Params, Snapshots, and Multi-Wallet E2E testing#9

Open
intelliDean wants to merge 144 commits into
zecdev:mainfrom
intelliDean:main
Open

feat: add Custom Chain Params, Snapshots, and Multi-Wallet E2E testing#9
intelliDean wants to merge 144 commits into
zecdev:mainfrom
intelliDean:main

Conversation

@intelliDean
Copy link
Copy Markdown

Summary

This PR implements the Milestone 5 features: Custom Chain Params, Data Volume Snapshots, and Multi-Wallet Arrays, along with comprehensive E2E tests in the action and local test script.

Changes

  • CLI (zeckit up):
    • Exposes --block-interval and --activation-heights flags.
    • Sets ZECKIT_ACTIVATION_HEIGHTS and BLOCK_INTERVAL host environment variables.
    • Automatically edits and injects custom activation heights into zebra.toml and zebra-sync.toml.
    • Added a docker-native continuous background miner loop container (zebra-miner-loop) in docker-compose.yml to support custom mining intervals in the background.
  • CLI (zeckit snapshot):
    • Added a snapshot subcommand group supporting create <name>, restore <name>, list, and delete <name>.
    • Serializes/deserializes docker volumes dynamically using a lightweight helper alpine container (fully compatible across Linux, macOS, and Windows/WSL2).
  • Faucet Service:
    • Added get_configured_activation_heights to parse the heights environment variable and apply them to the Zingo configuration.
  • GitHub Action (action.yml):
    • Exposed block_interval and activation_heights inputs and forwarded them to zeckit up.

Verification

Test Name Location Result
Cargo Workspace Tests ZecKit/ ✅ Passed (4 unit tests)
E2E Custom Block Interval Test zeckit-sample-test/test-local.sh ✅ Passed (Asserted 3 blocks generated in 15s)
E2E Snapshot & Restore Lifecycle zeckit-sample-test/test-local.sh ✅ Passed (State successfully recovered to block height 270)
ZecKit Smoke Tests (8/8) zeckit-sample-test/test-local.sh ✅ Passed (Includes multi-wallet array E2E)
Node.js Example App Flow zeckit-sample-test/example-app/check-balance.js ✅ Passed (Alice funds shielded to Orchard and private Orchard transfer to Bob unified address)

Implements Milestone 3 deliverables on top of the existing M1/M2 foundation:

## GitHub Actions CI
- e2e-test.yml: Full devnet startup, smoke tests, artifact upload on failure
- smoke-test.yml: Lightweight health checks on every push
- Job timeout set to 120 minutes to accommodate Docker build time

## Two-Node Zebra Regtest Cluster
- zebra-miner: internal miner, mines blocks continuously
- zebra-sync: second node for cluster readiness verification
- Fixed zebra-sync.toml config fields for Zebra 4.1.0 compatibility
  (initial_testnet_peers, crawl_new_peer_interval)
- All indexer/faucet services point to zebra-miner for reliable data

## CLI Enhancements (zeckit up / test)
- health.rs: detailed RPC error messages surfaced during wait loops
- up.rs: periodic error reporting during Zebra startup
- test.rs: 7-test smoke suite; cluster sync is warn-only (Regtest P2P
  peering is best-effort in isolated CI environments)

## Docker / Entrypoint
- entrypoint.sh: verbose startup logging, config validation, zebrad --version
- Sync node waits for miner to be reachable before starting zebrad
- Removed container_name fields to prevent naming conflicts in CI
- Relaxed port bindings to 0.0.0.0 for CI compatibility

## E2E Golden Flow (verified in CI)
  fund (650 ZEC coinbase) -> shield (transparent->Orchard) -> shielded send (0.05 ZEC)
  TXID confirmed on-chain, faucet live with 650+ ZEC Orchard balance

## README
- CI badges (E2E Tests, Smoke Test, License)
- M3 complete status with deliverable list
- Updated test suite table (7 tests with WARN explanation)
- M4 roadmap entry
Previously, the --timeout flag was applied independently to each
service (Miner, Sync, Backend, Faucet) in sequence. In the worst
case, a 1-minute timeout could compound into 4+ minutes of actual
wait time, making the CI startup_timeout_minutes parameter
unreliable.

This refactor introduces a single shared deadline computed once at
the start of Step 3:

  let deadline = Instant::now() + Duration::from_secs(timeout * 60);

Every wait-loop now checks Instant::now() >= deadline against this
shared clock. When the global budget expires anywhere in the
startup sequence, the process immediately fails with a clear error
message indicating the global timeout was exceeded.

The sync-parity soft-fail retains its 30-second local budget but
now also respects the global deadline, so it can no longer silently
consume time that allows startup to escape the requested timeout.

Progress percentages for Backend and Faucet now reflect the
remaining global budget rather than a fresh per-stage clock.

Fixes: Failure Drill 'startup-timeout' drill incorrectly reporting
'pass' because the devnet became healthy after the injected 1-minute
window due to compound per-service timeouts.
…ix dynamically, and fix volume cleanup names
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