Skip to content

Feat/sdp audit bridge - #79

Merged
Eras256 merged 4 commits into
nirium-protocol:mainfrom
Flames4fun:feat/sdp-audit-bridge
Aug 27, 2026
Merged

Eras256 merged 4 commits into
nirium-protocol:mainfrom
Flames4fun:feat/sdp-audit-bridge

Conversation

@Flames4fun

@Flames4fun Flames4fun commented Aug 26, 2026 •

Copy link
Copy Markdown
Contributor

Closes #71

Summary

This PR adds a reusable, testnet-only SDP audit bridge under examples/sdp-audit-bridge/. It accepts either explicit transaction hashes or a distribution account plus UTC time window, reads the corresponding payment records directly from Stellar Horizon, produces a deterministic PII-free aggregate, and anchors that record through Nirium's anchorAuditRecord().

It also adds a separate CID-only verification path. The verifier retrieves the anchored document from IPFS, recomputes its canonical SHA-256 digest and optional Ed25519 attestation statement, then independently retrieves and reconciles every cited transaction against Horizon. It does not accept the anchored aggregate as proof of its own claims.

Design decision

Three in-scope implementation strategies were evaluated independently:

  1. Strict Horizon REST/HAL adapter with runtime validation (selected). This keeps network boundaries explicit, validates untrusted Horizon and IPFS JSON before use, supports both classic payments and SAC transfers exposed by Horizon's payment endpoints, and provides deterministic normalization with bounded pagination and concurrency. It offers the clearest fail-closed behavior and the smallest auditable dependency surface for this example.
  2. Stellar SDK CallBuilder-centric adapter. This is a valid and ergonomic alternative for pagination and endpoint construction. It was not selected because SDK response types do not remove the need to validate evolving runtime fields such as asset_balance_changes, muxed-account representations, or malformed gateway responses. The additional abstraction would not replace the security-critical checks required here.
  3. Streaming async-iterator reconciliation pipeline. This would reduce peak memory for very large account histories and is also technically valid. It was not selected because Nirium's 8 KiB record limit bounds the final proof pack to 119 transaction hashes, while streaming introduces more cancellation, ordering, and partial-failure state. Bounded page traversal and concurrency are simpler to review without sacrificing performance within the issue's limits.

The selected design remains an adapter rather than an SDP fork or dashboard. It never queries recipient PII, accesses custody keys, or submits Stellar transactions.

Implementation

  • Reconciles successful payment operations from Horizon using transaction hashes or { sourceAccount, from, to }.
  • Treats the source account as the payment source, independent of an SDP channel account that may submit the transaction envelope.
  • Supports native assets, issued assets, muxed destinations, and SAC invoke_host_function payment records.
  • Uses exact integer stroop arithmetic and rejects mixed assets, ambiguous SAC balance changes, malformed records, contradictory muxed fields, duplicate hashes, and non-testnet Horizon responses.
  • Sorts transaction hashes deterministically and excludes raw recipient addresses and other recipient PII from the aggregate.
  • Recomputes content_sha256 locally and signs only the domain-separated statement nirium-audit-v1:<content_sha256> when an agent key is configured.
  • Verifies IPFS content, optional agent attestation, aggregate totals, recipient count, asset identity, and every cited transaction independently.
  • Documents operational trust boundaries, testnet reset limitations, completeness limitations, and precise Providencia Onchain prior art.

Findings and hardening

Review of the first implementation identified several important correctness gaps. SDP payments can use a distribution account as the operation source while a channel account submits the envelope, so envelope-source filtering was replaced with payment-source filtering. Horizon's payment endpoints were used to cover both classic payments and SAC balance changes consistently. Issued assets now compare code and issuer, and monetary aggregation uses stroops rather than floating-point arithmetic.

The adversarial review then found three additional boundary cases: a classic muxed destination and an SAC G-address:id representation could be counted as different recipients; a malicious response could return a payment record belonging to a different requested transaction; and contradictory to, to_muxed, and to_muxed_id fields could be accepted. Canonical muxed-account reconstruction, strict per-record transaction-hash matching, and muxed-field coherence checks now reject those cases. The focused suite contains 41 passing tests covering normal flows, malformed external data, pagination limits, SAC ambiguity, signature substitution, aggregate tampering, and these adversarial cases.

Testnet acceptance evidence

The bridge was exercised end-to-end against three real XLM payments created by a self-hosted SDP v7.0.0 instance built from official backend commit d36cfaa (disbursement 8ffa4b5e-d19e-4524-96c6-3707db2b2696). Both explicit-hash and source-window selection produced three recipients and 6.6000000 XLM.

The README records all three transaction hashes and the reproducible verification command. It credits Providencia Onchain / VIIO for the deployment-specific on-chain traceability pattern and limits this contribution's claim to a generic reusable adapter.

Validation

  • TypeScript typecheck: passed
  • Test suite: 41/41 passed
  • Production build: passed
  • Dependency audit: 0 known vulnerabilities

Assistance disclosure

The repository's contribution guidance requires disclosure of AI assistance. OpenAI Codex was used only as an engineering assistant for implementation review, documentation research, test execution, and adversarial analysis. The contributor retained authorship, technical judgment, and responsibility for the submitted work. The guidance's literal Claude-specific co-author trailer was not used because it would inaccurately attribute co-authorship to a different system; no AI system is represented as an author or co-author of these commits.

Resolve explicit transaction hashes or a source-account time window through bounded Horizon payment queries. Normalize classic and SAC transfers into deterministic, exact, PII-free aggregate evidence.
Anchor locally hashed aggregates through Nirium with optional domain-separated Ed25519 attestations. Add a CID-only verifier that recomputes content integrity and reconstructs every cited payment through Horizon.
Exercise malformed Horizon and IPFS responses, pagination bounds, SAC and muxed semantics, cross-transaction evidence, exact arithmetic, record tampering, and domain-separated attestations.
Describe integration and verification workflows, trust boundaries, Providencia Onchain attribution, and reproducible evidence from a three-payment SDP Testnet disbursement.
@Eras256
Eras256 merged commit 6764804 into nirium-protocol:main Aug 27, 2026
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.

[Advanced] Generic Stellar Disbursement Platform (SDP) reconciliation adapter via Nirium's Audit Trail

2 participants