Search Apps Documentation Source Content File Folder Download Copy Actions Download State String Boolean Number Struct Map Slice Pointer Function Closure Reference Nil Package Type Interface Unknown

commitreveal.gno

2.34 Kb · 61 lines
 1// Package commitreveal provides a minimal commit-reveal primitive:
 2// commit to (salt, data) by publishing only their hash, then later
 3// reveal the actual salt and data for anyone to verify against the
 4// published commitment. This is the standard way to prevent front-
 5// running on gno.land -- e.g. sealed-bid auctions, commit-based voting,
 6// or any scheme where revealing intent early would let others react to
 7// it before the reveal phase.
 8//
 9// This package holds no chain state and does not manage commit/reveal
10// deadlines itself -- the importing realm stores the returned [32]byte
11// commitment and decides its own phase timing (typically via
12// chain/runtime.ChainHeight(), the same way gno.land/p/demo/ratelimit
13// takes a caller-supplied block height instead of reading the chain
14// itself).
15package commitreveal
16
17import (
18	"crypto/sha256"
19)
20
21const domainPrefix = byte(0x01)
22
23// minSaltLen is a floor on salt entropy. A short salt lets an observer
24// brute-force it (combined with a guessed data value) before the reveal
25// phase, defeating the whole point of committing first -- so Commit
26// refuses to produce a commitment from a salt this short.
27const minSaltLen = 16
28
29func hashCommit(salt, data []byte) [32]byte {
30	buf := make([]byte, 0, 1+len(salt)+len(data))
31	buf = append(buf, domainPrefix)
32	buf = append(buf, salt...)
33	buf = append(buf, data...)
34	return sha256.Sum256(buf)
35}
36
37// Commit produces the commitment hash for (salt, data). salt must be at
38// least 16 bytes; data must be non-empty. Panics otherwise -- this is
39// the "I'm constructing a real commitment" path, so invalid input here
40// is a caller bug, not something to fail quietly on.
41func Commit(salt, data []byte) [32]byte {
42	if len(salt) < minSaltLen {
43		panic("commitreveal: salt must be at least 16 bytes for adequate entropy")
44	}
45	if len(data) == 0 {
46		panic("commitreveal: data cannot be empty")
47	}
48	return hashCommit(salt, data)
49}
50
51// Verify checks whether (salt, data) reveals commitHash. Unlike Commit,
52// this never panics -- a reveal attempt is untrusted input from
53// whoever's revealing, and a malformed one (e.g. a short salt someone
54// hand-crafted) should just fail verification, not abort the caller's
55// whole transaction.
56func Verify(commitHash [32]byte, salt, data []byte) bool {
57	if len(salt) < minSaltLen || len(data) == 0 {
58		return false
59	}
60	return hashCommit(salt, data) == commitHash
61}