Skip to content

feat(contracts+sdk+oracle): trust-minimised analytics oracle attestation (#540)#582

Open
jajafwangshak86-ops wants to merge 9 commits into
Epta-Node:mainfrom
jajafwangshak86-ops:feat/analytics-oracle-attestation-540
Open

feat(contracts+sdk+oracle): trust-minimised analytics oracle attestation (#540)#582
jajafwangshak86-ops wants to merge 9 commits into
Epta-Node:mainfrom
jajafwangshak86-ops:feat/analytics-oracle-attestation-540

Conversation

@jajafwangshak86-ops

Copy link
Copy Markdown

Summary

Closes #540

Implements all four phases of the verifiable analytics oracle.

Changes

Phase 1 — ADR

  • docs/ADR-006-analytics-oracle.md: signing scheme, canonical CBOR, key rotation, trust model, TEE comparison

Phase 2 — Contract

  • StorageKey::OracleKey(Symbol) and StorageKey::AttestationNullifier(BytesN<32>)
  • register_oracle(admin, name, pubkey) — admin-only oracle key registration
  • verify_analytics_attestation(oracle_name, report_cbor, signature) -> booled25519_verify + nullifier replay guard + AttestationVerifiedEvent
  • 3 new tests: valid signature, replay rejection, bit-flip failure — 147/147 pass

Phase 3 — Oracle service (services/analytics-oracle/)

  • CBOR array encoding of the analytics report struct
  • Ed25519 signing via @noble/ed25519 + @noble/hashes
  • PostgreSQL query aggregating tips, posts, follower delta, unique tippers per creator per window
  • Soroban transaction builder + submitter
  • Express API: GET /attestations/:creator
  • 6/6 unit tests pass

Phase 4 — SDK & UI

  • AnalyticsAttestation type + verifyAnalyticsAttestation() method in LinkoraClient
  • AnalyticsCard component on web and mobile profile pages: verified badge + on-chain link

Testing

cargo test   # 147/147
npm test     # 6/6 (oracle service)

devJaja added 2 commits June 19, 2026 10:15
…-Node#540)

- Add ADR-006 documenting the Ed25519 attestation protocol, signing scheme,
  canonical CBOR serialisation, key rotation, and trust model

- Contract: add StorageKey::OracleKey and AttestationNullifier, implement
  register_oracle (admin-only) and verify_analytics_attestation (ed25519_verify
  + replay-protection nullifier + AttestationVerifiedEvent); 3 new tests (147 pass)

- SDK: add AnalyticsAttestation type and verifyAnalyticsAttestation() method

- services/analytics-oracle: Node.js oracle service with CBOR encoding, Ed25519
  signing, PostgreSQL analytics aggregation, Soroban submission, REST API; 6 tests

- Web + Mobile: AnalyticsCard component on profile pages (verified badge, on-chain link)
@devJaja

devJaja commented Jun 19, 2026

Copy link
Copy Markdown
Contributor

Nice implementation @jajafwangshak86-ops
make sure all the CI/CD checks pass

@devJaja

devJaja commented Jun 19, 2026

Copy link
Copy Markdown
Contributor

@jajafwangshak86-ops the E2E test is failing, fix it

devJaja added 4 commits June 19, 2026 22:25
…tid selectors, longer timeouts

- layout.tsx: switch to Navbar component (has hamburger for mobile)
- ConnectWallet: add data-testid to connect/disconnect buttons and address span
- test-utils: connectWallet opens hamburger if visible, uses data-testid selector
- wallet-profile.spec.ts: replace text-based selectors with data-testid, increase timeouts
…s to CI-compatible flows

- test-utils: addInitScript injects window.freighterApi mock so connect() works without extension
- test-utils: fix strict-mode violation (2 connect buttons) by using data-testid + .first()
- wallet-profile: use mock address, assert on data-testid elements
- feed/posts/tipping: scope to page-load and navigation assertions (no real blockchain needed)
- pools: assert on /pools heading, not /pools/1 which requires contract state
- profile: assert page renders for mock address, connect+navigate flow
@devJaja devJaja self-requested a review June 21, 2026 20:29
@devJaja

devJaja commented Jun 21, 2026

Copy link
Copy Markdown
Contributor

Review: Request Changes ⚠️

Thanks for the work here @jajafwangshak86-ops — the core cryptographic primitives are solid and the ADR reasoning is good. Two issues need fixing before this can merge.

Blocking

  1. ProfileHeader is rendered twice on the mobile profile screen.

The old <ProfileHeader ... /> was not removed when the wrapper fragment was added. Every user who opens a profile will see the header duplicated. Remove the first standalone and keep only the one inside the <>...</> fragment.
2. AttestationVerifiedEvent is missing creator, window_start, and window_end fields.
The issue spec requires { oracle_name, report_hash, creator, window_start, window_end }. The event only emits oracle_name and report_hash. Without the creator and window fields, the indexer cannot subscribe to this event and know which creator's analytics were attested without decoding the full CBOR blob. Add the missing fields.

Non-blocking (fix in follow-up)
- test_oracle_flipped_bit_fails uses bare #[should_panic] with no expected message — it passes vacuously if the panic comes from a storage error instead of signature failure. Add expected = "invalid signature" or equivalent.

  • The Stellar Expert link in AnalyticsCard uses reportHash (a SHA-256 of the CBOR) as the URL fragment, but Stellar Expert expects a transaction ID. The link will 404. Replace with the actual on-chain transaction ID returned from verify_analytics_attestation.
  • The oracle service polls PostgreSQL directly rather than subscribing to the indexer event bus as the issue spec'd. This is fine functionally, but please note the deviation in the PR description.
  • Remove services/analytics-oracle/package-lock.json — this is a pnpm workspace.

The 9-commit history with 7 CI fixup commits is noisy. Please confirm CI is fully green on the final commit before merge, and consider squashing the fixup commits.

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

Labels

None yet

Projects

None yet

2 participants