PathrockNetwork Gno Explorer
HomeBlocksTransactionsRealmsPackagesValidatorsAnalytics

PathrockNetwork Gno Explorer — an independent explorer for Gno.land Mainnet (gnoland-1), operated by PathrockNetwork. Not an official Gno.land service.

gnowebarchive RPC

gno.land/r/moul/x/daily/commitrevealdemo/v0

Realm
Open in gnoweb ↗

Overview

Kind
Realm (renderable)
Name
v0
Namespace
moul / x / daily / commitrevealdemo
Files
3 (README)(gnomod.toml)
Exported functions
1
Module
gno.land/r/moul/x/daily/commitrevealdemo/v0
gno
0.9

Files (3)

  • README.mdmarkdown
  • gnomod.tomltoml
  • commitrevealdemo.gnogno
commitrevealdemo.gnogno
1// Package commitrevealdemo is a small gnoweb demo of the commit-reveal scheme2// provided by the [p/moul/x/daily/commitreveal](/p/moul/x/daily/commitreveal/v0)3// library: the two phases, and what the salt is for.4//5// It contains no crypto of its own. Stateless, so Render is deterministic —6// which is precisely what the library is for.7package commitrevealdemo89import (10	"strings"1112	"gno.land/p/moul/x/daily/commitreveal/v0"13)1415// Render renders the demo for gnoweb.16func Render(path string) string {17	var b strings.Builder18	b.WriteString("# Commit–Reveal\n\n")19	b.WriteString("Bind to a choice without disclosing it, demoing the ")20	b.WriteString("[`p/moul/x/daily/commitreveal`](/p/moul/x/daily/commitreveal/v0) library.\n\n")2122	b.WriteString("## The problem\n\n")23	b.WriteString("A transaction is public before it executes. In a sealed-bid auction or ")24	b.WriteString("a simultaneous-move game, whoever moves last reads everyone else's ")25	b.WriteString("move and wins for free.\n\n")2627	aliceSalt := "alice-secret-salt-1"28	bobSalt := "bob-secret-salt-0001"29	aliceCommit := commitreveal.MustCommit("rock", aliceSalt)30	bobCommit := commitreveal.MustCommit("paper", bobSalt)3132	b.WriteString("## Phase 1 — commit\n\n")33	b.WriteString("Each player publishes only `H(value ‖ salt)`. Nothing about the move ")34	b.WriteString("leaks, but neither can change it later.\n\n")35	b.WriteString("| player | commitment |\n|---|---|\n")36	b.WriteString("| alice | `" + short(aliceCommit) + "` |\n")37	b.WriteString("| bob | `" + short(bobCommit) + "` |\n")3839	b.WriteString("\n## Phase 2 — reveal\n\n")40	b.WriteString("Now the values and salts are published and checked against the ")41	b.WriteString("commitments recorded earlier:\n\n")42	b.WriteString("| check | result |\n|---|---|\n")43	row(&b, "alice opens with `rock`", commitreveal.Open(aliceCommit, "rock", aliceSalt))44	row(&b, "bob opens with `paper`", commitreveal.Open(bobCommit, "paper", bobSalt))45	row(&b, "bob tries `scissors` instead", commitreveal.Open(bobCommit, "scissors", bobSalt))46	row(&b, "bob claims alice's commitment", commitreveal.Open(aliceCommit, "rock", bobSalt))4748	b.WriteString("\nBob cannot switch his move after seeing Alice's, and cannot pass off ")49	b.WriteString("her commitment as his own.\n\n")5051	b.WriteString("## Why the salt is mandatory\n\n")52	b.WriteString("Rock-paper-scissors has three possible moves. Without a salt there are ")53	b.WriteString("exactly three possible hashes, and hashing all three breaks the scheme ")54	b.WriteString("outright. The library refuses a salt shorter than `")55	b.WriteString(itoa(commitreveal.MinSaltLen) + "` bytes rather than leaving that as advice:\n\n")56	_, err := commitreveal.Commit("rock", "tooshort")57	b.WriteString("- `Commit(\"rock\", \"tooshort\")` → `")58	if err != nil {59		b.WriteString(err.Error())60	}61	b.WriteString("`\n\n")62	b.WriteString("The salt also keeps two players who pick the *same* move from ")63	b.WriteString("publishing the same commitment:\n\n")64	one := commitreveal.MustCommit("rock", "salt-one-0123456789")65	two := commitreveal.MustCommit("rock", "salt-two-0123456789")66	b.WriteString("| same move, different salt | commitment |\n|---|---|\n")67	b.WriteString("| player 1 | `" + short(one) + "` |\n")68	b.WriteString("| player 2 | `" + short(two) + "` |\n")6970	b.WriteString("\n## Two details that are easy to get wrong\n\n")71	b.WriteString("- **Length-prefixed hashing.** With plain concatenation `(\"ab\",\"cd…\")` ")72	b.WriteString("and `(\"abc\",\"d…\")` hash identically, so one commitment could be opened ")73	b.WriteString("two different ways.\n")74	b.WriteString("- **Constant-time comparison.** A short-circuiting check leaks, through ")75	b.WriteString("timing, how many leading bytes of a guess were right — enough to rebuild ")76	b.WriteString("a commitment byte by byte.\n")77	return b.String()78}7980func row(b *strings.Builder, label string, err error) {81	b.WriteString("| " + label + " | ")82	if err == nil {83		b.WriteString("✅ accepted")84	} else {85		b.WriteString("❌ `" + err.Error() + "`")86	}87	b.WriteString(" |\n")88}8990func short(c string) string { return c[:16] + "…" }9192func itoa(i int) string {93	if i == 0 {94		return "0"95	}96	s := ""97	for i > 0 {98		s = string(rune('0'+i%10)) + s99		i /= 10100	}101	return s102}103

Functions

  • Render(path string) string

Signatures reconstructed verbatim from vm/qfuncs — interface params keep their inline definitions.

Rendered

RenderedRawgnoweb ↗

vm/qrender output, sanitized (docs/render-security.md) and displayed in an empty-sandbox iframe — scripts, forms and popups cannot run. Links stay inert in-preview; right-click to open.