Skip to main content

Midnight

Midnight is the chain DPO2U uses for private attestation: a compliance verdict is sealed on-chain while the zero-knowledge proof is produced inside a Compact circuit, so the underlying evidence is never published. The officially documented network is preview. This page does not claim mainnet support.

Role in DPO2U​

  • Gateway route. The pilot gateway accepts attestation attempts with chain=midnight and hands them to processAttestationMidnight (packages/pilot-gateway/src/routes/attestation.ts:203-204, :269).
  • Feature flag. The route is gated by MIDNIGHT_CHAIN_ENABLED=1. With the flag off, the attempt fails with code midnight_disabled; Stellar and Solana routes are untouched (attestation.ts:29-31, :270-275).
  • Asynchronous anchoring. The gateway does not submit a transaction itself. It enqueues the seal with a warm self-funding agent (packages/pilot-gateway/src/lib/midnight-driver.ts, sealManagedMidnight). The returned handle points to the public verify page; the on-chain result appears once the agent seals it (attestation.ts:267-268, midnight-driver.ts:51).
  • Compliance engine driver. MidnightDriver implements ComplianceChainClient against preview. It never runs a wallet or syncs shielded history; it pushes work to the agent queue and reads results back from the agent ledger and the public preview indexer (packages/compliance-engine/src/chain/MidnightDriver.ts:1-23).
  • Proof generation. The ZK proof is produced inside the on-chain circuit by a local proof-server (MidnightDriver.ts:8-10).
  • Verdict encoding. 0 FAIL, 1 PASS, 2 REVIEW (MidnightDriver.ts:102).

Preview endpoints used by the driver​

SettingDefaultSource
Indexer (GraphQL)https://indexer.preview.midnight.network/api/v4/graphqlMidnightDriver.ts:28, :63
Networkpreview (also accepts preprod, standalone)MidnightDriver.ts:32
Proof-serverlocal, overridable via MIDNIGHT_PROOF_SERVER_URLMidnightDriver.ts:29, :64
Indexer verdict readoff unless MIDNIGHT_VERIFY_VIA_INDEXER=1MidnightDriver.ts:33-34

No contract addresses are published here.

Compact contracts (lab)​

The lab repository dpo2u-midnight-lab holds three Compact contracts under contracts/, all declaring pragma language_version >= 0.21.0. They store hashes (Bytes<32>), not personal data.

The full contract catalogue of the agent system is documented in Self-funding agents.

note

The gateway and driver seal on the ComplianceRegistry contract owned by the self-funding agent repository (MidnightDriver.ts:6-9), not on the three lab contracts below.

ConsentRegistry​

LGPD/GDPR consent. contracts/ConsentRegistry.compact.

  • Ledgers (lines 27-31): consent_status, consent_purposes, consent_policy_version (each Map<Bytes<32>, Uint<8>>), total_consents_granted, total_revocations (Counter).
  • Circuits: grantConsent(subject_id, purposes, policy_version) (line 36), revokeConsent (51), updateConsentPurposes (60), and read circuits getConsentStatus, getConsentPurposes, getConsentPolicyVersion, getTotalConsentsGranted, getTotalRevocations (75-97).
  • Encoding: purposes is a bitmask (1 essential, 2 analytics, 4 marketing, 8 third-party sharing, 16 profiling); status 0 no record, 1 active, 2 revoked (header comments, lines 12-25).

DataAuditLog​

Processing event log. contracts/DataAuditLog.compact.

  • Ledgers (28-34): event_count, deletion_requests, deletions_confirmed, breach_events (Counter); events_by_controller (Map<Bytes<32>, Uint<64>>), last_event_type (Uint<8>), last_event_block (Uint<64>).
  • Circuits: logEvent (38), logDeletionRequest (56), confirmDeletion (73), logBreachEvent (90), and getters getControllerEventCount, getLastEventType, getLastEventBlock, getTotalEvents, getTotalDeletionRequests, getTotalDeletionsConfirmed, getTotalBreachEvents (105-135).

DataSubjectRights​

LGPD data-subject requests with a deadline. contracts/DataSubjectRights.compact.

  • Ledgers (36-43): request_status, request_type (Uint<8>), request_submitted_block, request_resolved_block (Uint<32>), total_requests, total_fulfilled, total_rejected, total_overdue (Counter).
  • Circuits: submitRequest (52), fulfillRequest (69), rejectRequest (85), markRequestOverdue (101), getters getRequestStatus, getRequestType, getRequestSubmittedBlock, getRequestResolvedBlock, getTotalRequests, getTotalFulfilled, getTotalRejected, getTotalOverdue (119-154). lgpd_deadline_blocks is a pure circuit returning 21600 blocks (15 days at one block per minute, LGPD Art. 19; lines 47-49).

Version matrix (lab)​

ComponentVersionSource
Compact compiler (compactc)0.31.0scripts/compile-contracts.sh:16
Nodemidnightntwrk/midnight-node:0.21.0docker-compose.yml:3
Indexermidnightntwrk/indexer-standalone:3.1.0docker-compose.yml:24
Proof-servermidnightntwrk/proof-server:7.0.0docker-compose.yml:51
compact-js2.4.0package.json:18
compact-runtime0.14.0package.json:19
ledger-v77.0.0package.json:20
midnight-js-*3.0.0package.json:21-27
wallet-sdk-facade1.0.0package.json:31
Node.js>= 22package.json:6

The compose file is a standalone/local stack (indexer network_id: "undeployed", indexer-config.yaml:5). scripts/pre-deploy-check.sh:19-22 and scripts/check-version-consistency.sh keep the duplicated version constants in sync.

Development flow​

From the lab root (package.json:8-15):

StepCommandWhat it runs
Compile contractsnpm run compilescripts/compile-contracts.sh (optionally --contract <name>)
Check version driftnpm run check-versionsscripts/check-version-consistency.sh
Typechecknpm run typechecktsc --noEmit -p tsconfig.json
Pre-deploy checksnpm run predeployscripts/pre-deploy-check.sh [--network standalone|preprod|preview]
Deploy allnpm run deploy:alltsx scripts/deploy-all.ts
Statusnpm run statustsx scripts/status.ts
Interactnpm run interacttsx scripts/interact-full-suite.ts

compile-contracts.sh aborts when /tmp has less than 500 MB free, because compactc fails with an unreadable assertion on a full disk (compile-contracts.sh:67-70).

Known pitfalls​

  1. Facade API 1.0.0 vs 2.0.0. WalletFacade.init({...}) is the 2.0.0 API; with wallet-sdk-facade 1.0.0 it throws WalletFacade.init is not a function. The lab pins 1.0.0 and builds the wallet through new WalletFacade(...) plus start() in scripts/lib/wallet-facade.ts (see logs/2026-09-26-dev.md:6-8, :24-35). Do not mix SDK and infrastructure versions.
  2. Indexer tag: preview vs preprod. Indexer tags differ per network tier. scripts/pre-deploy-check.sh:22 records that a preview-tier tag (4.0.0-rc.4) had been mismatched against the preprod node 0.21.0 and was corrected to 3.1.0. The driver's preview indexer endpoint is /api/v4/graphql, while the lab's preprod scripts use /api/v3/graphql (scripts/status.ts:91).
  3. PROOF_SERVER_URL when another proof-server owns the default port. If a different project's container already listens on the default proof-server port, the pre-deploy check fails with a version mismatch (scripts/pre-deploy-check.sh:55-68). Start a proof-server 7.0.0 on another port and point PROOF_SERVER_URL at it; the deploy and status scripts honor the variable. The gateway-side driver reads MIDNIGHT_PROOF_SERVER_URL instead (MidnightDriver.ts:29).