How it works

Draw Logic is the live draw service for competitions. It runs in an AWS Nitro Enclave. The calling site sends the competition. The enclave creates the private seed. The site does not receive that seed until the competition has ended.

The public site and the parent API run on the EC2 host. They accept the call and pass it into the enclave over vsock. Prize placement, ticket issue, and the draw run inside the enclave. The host does not generate the seed.

Two kinds of competition

A standard competition sells tickets and, at the end, draws from the tickets Draw Logic has issued. It has no fixed prizes and no instant wins.

An instant-win competition does that same end draw, and also places prizes onto a fixed-size pool when it is created. Some of those prizes sit on ticket numbers the site chose. The rest are placed at random. Prize names, claims, and payment stay on the site.

Either kind can be finished automatically or manually. An automatic finish runs the stored formula. A manual finish stores the operator's selection and a source for that draw.

Commitment

At creation, Draw Logic returns a competition id and the SHA-256 hash of the private seed, taken over the seed as UTF-8. That hash is the commitment. The private seed is not in the create response. When the competition is finished, the private seed is released with the result. Hashing the released seed must reproduce the commitment made at creation.

The formula version is stored with the competition. Later issuance, the draw, and replay use that version.

The formula

Prize placement, ticket issue on a fixed pool, and an automatic end draw share one method. Hash the seed, a purpose, and an index, joined with colons, as UTF-8. Read the 32-byte digest as one integer. The position is the remainder of that integer divided by the length of the list still available for that step.

digest = SHA-256(seed + ":" + purpose + ":" + index)
value  = the digest read as one big-endian integer
pick   = value % length

After a number is taken, it leaves the list before the next step. The next remainder is taken from what is left. A fixed prize is not produced by this formula. Replay applies the ticket number the site sent.

Pools

An omitted pool size, or 0, is open-ended. Draw Logic does not build a ticket list. The next issued ticket is one higher than the last. Instant wins need a fixed size, so this configuration has none.

A fixed pool is every number from 0 through poolSize - 1, including numbers with no prize. The account cap is 5,000,000. A larger pool is rejected.

Placing prizes

The site may draft a competition in its own admin. Draw Logic is called when that competition is created for real. Placement runs once, inside the enclave.

Fixed prizes are written onto the chosen numbers first. A number outside the pool, or a repeated number, is rejected. Random instant wins then walk prize order, and copy order inside each prize. Each copy is placed on a ticket that does not already hold a prize. That ticket can still be sold, and it can still win the end draw.

Draw Logic returns the prize pairs and the commitment. It does not return the private seed. The site stores the pairs. It does not recompute the ticket numbers. Draw Logic does not store the title, the images, or the prize names.

End prizes are counted at creation. They are not placed then. Each one is drawn when the competition finishes.

Issuing tickets

The site prompts Draw Logic to issue tickets once an order is paid and confirmed. One order can cover more than one competition. Once numbers are issued, they are not reversed.

On an open-ended pool, numbers are issued in sequence. On a fixed pool, Draw Logic creates a public order seed and takes one free number per ticket, using the order step of the formula.

The end draw

The draw uses the issued numbers. Unsold numbers are not in it. An open-ended pool issues in sequence, and still draws from that issued set.

Each end prize is a separate draw. The winner is removed before the next prize, so two end prizes do not land on the same ticket. A ticket that already holds an instant win or a fixed prize can also win an end prize. If nothing has been sold, the draw is skipped.

Automatic finish asks the enclave to run the formula and returns the winning numbers with the private seed. Manual finish sends the winning numbers and a source. Those numbers must already be sold. The formula is not run. Finish can be called once. Tickets are not issued after the competition has ended.

Replay

Once the private seed is public, placement, issuance, and an automatic draw can be run again. Placement must reproduce the prize pairs. Issuance walks each order in the stored sequence, with that order's public seed, and must reproduce the issued numbers. An automatic draw must reproduce the winning numbers.

A manual draw is not checked against the formula. Replay reports that the draw was manual and points at the source. The stored winning numbers are the operator's selection.

What stays on the site

Draw Logic does not handle customers, prize values, claims, or payment. It keeps ticket numbers and prize indexes. The site keeps the names and pays the prizes. Archive is a site timer, 30 days after the draw by default. Archiving on the site does not remove the competition from the enclave.

Attestation

The attestation page has the browser confirm that the running code is the code Draw Logic says it is running. That code will be published on the GitHub branch. The branch is not populated yet. The enclave image is measured when it is built. While it is running, AWS signs a live attestation of that image. The page checks the signature in the browser and checks the live measurement against the measurement published for the deployment.