How Spinveri proves a giveaway winner was picked fairly
Most giveaway winners are picked by a screen recording or a comment picker site, and nobody but the host can tell whether the result was re-rolled or nudged. Spinveri is a verifiable random giveaway picker: the winner is fixed by a number sealed before the final entry list is collected, and anyone can check it afterward.
How a draw works, in plain words
Seal a secret number
When you set up a giveaway, Spinveri picks a secret random number and seals it. Only a fingerprint of the number is kept in view, the way a sealed envelope shows its outside but not what's inside.
Collect and lock the entries
When you press Draw winner, Spinveri collects the comments on your post, keeps the ones that meet your rules, and locks that list. Nothing can be added or removed after this.
Pick the winner
The secret number is opened and combined with the locked list. The result points to exactly one entry. Nobody chooses it: not you, and not Spinveri.
Publish the proof
The verification page shows the winner, your rules, how many entries there were, and the opened number. Anyone can check the number matches its fingerprint and picks the winning entry. Entrants can confirm their own entry, and you can download the full list.
What the proof shows, and what it doesn’t
We’d rather be exact than impressive. Here is what anyone can check on a verification page, and what still depends on trust.
What you can check
- The number that picked the winner is the one that was sealed. It matches its fingerprint, so it wasn't swapped after the entries were known.
- The list is the list that was used. Change one name and the check fails.
- The winner follows from the number and the list. Run the same steps on your downloaded list and you get the same winner.
- Each draw is final. There is no re-roll.
What you still trust
- That Instagram returned every comment. Spinveri uses Instagram's official API, which can rate-limit or miss a comment posted moments before the draw.
- That each commenter is a real person. Bots and duplicate accounts can enter a giveaway; your entry rules are the only filter.
- Exactly when the number was sealed. The sealed time is Spinveri's own record, so that one detail relies on trusting us.
- That the prize is delivered. That's between you and your winner.
The technical proof
This is the same procedure as above, with the exact primitives. Every draw uses protocol version 1.
- Commit. Spinveri generates a 32-byte random seed and stores its SHA-256 hash, the commitment. The seed stays private until the draw.
- Snapshot. On draw, Spinveri fetches the post's comments through Instagram's API, applies your entry rules, and freezes the resulting entrant list. The canonical form of the list is hashed with SHA-256 to give the entrants hash.
- Select. Spinveri computes HMAC-SHA256 with the seed as key and the 32 bytes of the entrants hash as message. The first 8 bytes, read as a big-endian unsigned integer, modulo the number of entrants, give the winner index.
- Reveal. Spinveri publishes the seed, the entrants hash, the entry count and the winner index on the verification page. The host can download the canonical list; anyone can check a single username against it there.
Canonical list
Usernames are lowercased, trimmed, sorted in ascending order and joined with a single newline (no trailing newline). This is the exact byte string that is hashed, so anyone who applies the same rules gets the same hash.
The three checks
- SHA-256 of the revealed seed equals the commitment.
- SHA-256 of the canonical list equals the entrants hash.
- The HMAC rule above, applied to the seed and the entrants hash, gives the published winner index.
Check a draw yourself
Open any verification page, expand Technical proof, and download the entrants list and the verification script. The script needs only Python’s standard library. In essence, it does this:
import hashlib
import hmac
seed = bytes.fromhex(SEED_HEX) # the revealed seed
assert hashlib.sha256(seed).hexdigest() == SEED_HASH # 1. matches the commitment
entrants = sorted(l.strip().lower() for l in open("entrants.txt") if l.strip())
entrants_hash = hashlib.sha256("\n".join(entrants).encode()).hexdigest()
assert entrants_hash == ENTRANTS_HASH # 2. same list that was used
mac = hmac.new(seed, bytes.fromhex(entrants_hash), hashlib.sha256).digest()
index = int.from_bytes(mac[:8], "big") % len(entrants) # 3. winner follows
print(entrants[index])Run python3 verify.py entrants.txt and the real script prints OK or FAIL for the commitment, the entrants hash, the winner index and the winner’s handle.
Glossary
- Commit-reveal
- Publish a fingerprint of a secret now, reveal the secret later. Anyone can check the secret matches the fingerprint, so it can't be changed in between.
- Seed
- The secret random number, 32 bytes long, that decides the winner.
- SHA-256
- A one-way fingerprint function. The same input always gives the same 64-character result; you can't work backwards from the result to the input.
- HMAC
- A keyed fingerprint. Here it mixes the secret seed with the entrant list to give an unpredictable but repeatable number.
- Canonical list
- The entrant list in one agreed form: usernames lowercased and trimmed, sorted A to Z, joined by single line breaks. Anyone who applies these steps gets the same list, and so the same hash.
Questions about the protocol? Email support@spinveri.com, see pricing, or grab our free giveaway rules template.