Skip to content
[OPEN_POKER]
A flow diagram showing a completed Open Poker hand becoming canonical JSON, a SHA-256 hash, a Constellation fingerprint, and a public proof.

The Engineering Choices Behind Open Poker's Evidence Layer

JJoão Carvalho||Actualizado |9 min read

Open Poker's Digital Evidence integration is built around one engineering idea: proof should make hand records stronger without becoming part of the critical poker path. We wanted completed hands to be verifiable through Constellation Digital Evidence, but we did not want a proof API, network delay, or finalization wait to decide whether a hand can finish or a pot can be awarded.

Disclosure: I am the founder of openpoker.ai. This is Part 2 of a two-part series. Part 1 explains the product reason; this post explains the engineering choices without turning into a code walkthrough.

Part 1: Product - Why Open Poker Uses Constellation Digital Evidence.

Part 2: Engineering - the design choices behind the evidence layer: when we create proof, what we hash, what stays private, and how verification stays independent.

Key Takeaways

  • Open Poker starts evidence work only after the hand result is committed to the database.
  • The document hash is SHA-256 over deterministic JSON for the public hand payload.
  • Local evidence states are explicit: pending, submitted, finalized, or error.
  • The hand page exposes status, document hash, fingerprint, explorer link, and the canonical payload needed for verification.

The design goal

The evidence layer had to satisfy two needs at once: be strong enough to make hand-history tampering visible, and boring enough that it never changes how poker hands are played.

That led to a simple boundary. Open Poker runs the game, saves the hand, and exposes the public hand page. After the database commit, a background evidence service creates a fingerprint and sends it to Constellation Digital Evidence. If the proof is delayed, the hand still exists. If the proof fails, the hand still exists. If the proof finalizes, the hand gets a stronger public record.

That boundary is the most important engineering decision in the integration.

The proof pipeline

The pipeline is intentionally short.

Open Poker Digital Evidence flow: completed hand, canonical JSON, SHA-256 document hash, Constellation fingerprint, public verification page.

First, a hand completes and Open Poker saves the result. Then we build a public hand payload from the saved data: board cards, public shown cards, winners, actions, stack movement, hand number, table ID, and timestamps.

Next, that payload is turned into deterministic JSON with sorted keys and no extra whitespace. Deterministic matters because the proof is only useful if the same hand data always produces the same bytes. This is the same general problem addressed by the IETF's JSON Canonicalization Scheme (RFC 8785), but Open Poker's local document hash does not claim full RFC 8785 compatibility. Those bytes are hashed with SHA-256, a member of the Secure Hash Standard family defined by NIST (FIPS 180-4), producing the document hash users can recompute later.

Then the fingerprint is submitted through Constellation Digital Evidence, following Constellation's documented submit-and-verify model (developer docs, find and verify docs). Open Poker stores the proof status and explorer link next to the hand, so the hand page can show whether the record is pending, submitted, finalized, or errored.

That is the full shape: saved hand, public payload, deterministic hash, external fingerprint, visible proof.

Why we hash public hand data

Poker has a privacy problem that many "put it on-chain" ideas ignore: hidden information is part of the game. If a proof system leaks folded hole cards, it has made the product worse.

Open Poker hashes the public record, not the hidden game. The evidence payload is meant to match what a hand review can safely show: public actions, public cards, winners, and stack changes. It does not include folded hole cards, API keys, private agent IDs, or internal owner state.

This gives us the property we actually want. A builder can verify that the public hand record has not quietly changed, without forcing Open Poker to publish information that should remain hidden.

Why it runs after the hand is saved

The evidence layer starts after persistence because a proof should refer to a real record. If a hand fails to save, there is no stable public hand history to prove.

This ordering also protects the game loop. The hand does not wait for a proof service before finishing. Open Poker records the outcome first, then evidence work happens in the background.

That makes the integration resilient in normal production failure modes:

  • The external API can be slow.
  • Finalization can take time.
  • Credentials can be missing in a non-production environment.
  • A retry can happen without changing the hand result.

None of those should affect whether a pot is awarded correctly.

Why we keep local evidence state

Open Poker keeps a local evidence record because users need clear status, not a black box. A record can be pending, submitted, finalized, or error. If evidence was disabled when the hand completed, there may be no evidence record at all, which is different from pretending proof exists.

That state is what lets the UI be honest. A pending proof should say pending. A finalized proof should show the explorer link. A missing proof should not pretend to exist.

The local record also gives Open Poker a place to store the document hash and canonical payload needed for self-verification. The external proof is useful, but the user still needs the exact payload bytes to recompute the hash.

It also makes retry behavior explicit. Pending submissions can retry without changing the saved hand, submitted fingerprints can be polled until finalization, and exhausted retries can become an error state that the UI can show honestly.

Why the UI matters

Most users will not read an API response or inspect a fingerprint directly. The proof has to show up where the question appears: on the hand page.

The hand detail view shows the status, fingerprint, document hash, confirmation time, Constellation explorer link, and a short "how to verify" flow. It can also expose the canonical payload used for the document hash. That turns the evidence layer from backend plumbing into an actual product feature.

The UI has one job: make verification feel concrete. You should be able to look at a hand, see that proof exists, open the explorer, and understand what the hash represents.

What independent verification means here

Independent verification does not mean Open Poker becomes fully trustless. It means the public hand payload can be checked against a cryptographic commitment outside our database.

The verification idea is:

  1. Fetch the public hand payload.
  2. Hash the canonical payload.
  3. Compare it with the document hash shown by Open Poker.
  4. Check the fingerprint on Constellation Digital Evidence.

If the public hand payload changes after commitment, the hash changes. That makes quiet edits detectable.

This is a narrow claim, but it is useful because it is testable.

What we deliberately avoided

We avoided turning Digital Evidence into a gameplay dependency. The proof layer should not decide whether a hand can end, whether a bot can act, or whether a river card is dealt.

We also avoided publishing private game state. More data is not always better proof. In poker, the wrong data can damage the integrity of future hands.

And we avoided making the feature require crypto knowledge. The product surface is a hash, a status, and an explorer link. That is enough for a builder to understand the trust model without caring about every internal implementation detail.

Lessons for builders

If you are adding evidence or notarization to an application, the pattern is reusable:

  1. Pick the record users actually need to trust.
  2. Define the public payload carefully.
  3. Make the payload deterministic before hashing.
  4. Commit the fingerprint outside your primary database.
  5. Keep the proof layer off the critical runtime path.
  6. Give users a visible way to verify the result.

The key is restraint. Evidence systems work best when the claim is narrow, the boundary is clear, and the verification path is easy to explain.

For Open Poker, the claim is this: once a completed hand is fingerprinted, the public hand record cannot be quietly changed without breaking verification.

That is the engineering story. The code exists to support that claim, not to make the feature sound more complicated than it is.

Engineering references

The engineering choices above are grounded in a few external standards and product docs:

FAQ

Why not notarize during the hand?

Because proof should not slow or interrupt gameplay. Open Poker saves the hand first, then creates evidence in the background. That keeps the proof layer separate from the live game loop.

What exactly is being verified?

The public hand payload: actions, public cards, winners, stack movement, hand IDs, and timestamps. Private folded cards and internal secrets are not part of the proof.

Does a finalized proof mean the poker engine had no bug?

No. It means the committed public hand record can be checked for later tampering. Engine correctness still depends on tests, monitoring, replay, and review.

What happens if the proof service is down?

The hand still completes and remains reviewable. Evidence submission can retry in the background, and if retries are exhausted the evidence record can move to an error state instead of blocking gameplay.

Why use Constellation Digital Evidence?

It gives Open Poker an external fingerprint and public lookup path for completed hand records. That is exactly the trust primitive we needed: verifiable evidence without moving the whole game onto a chain.

What should other builders copy?

Copy the boundary. Save your source-of-truth record first, hash a deterministic public payload, submit proof asynchronously, and make the verification result visible where users already review the record.

Seguir Leyendo