1package jury23import (4 "testing"56 "gno.land/p/moul/agents/commit/v0"7 "gno.land/p/nt/testutils/v0"8 "gno.land/p/nt/uassert/v0"9)1011var (12 opener = testutils.TestAddress("opener")13 j1 = testutils.TestAddress("juror1")14 j2 = testutils.TestAddress("juror2")15 j3 = testutils.TestAddress("juror3")16 nobody = testutils.TestAddress("nobody")17)1819// Full happy path: 3 jurors commit blind, then reveal; majority upholds.20func TestCommitRevealMajority(cur realm, t *testing.T) {21 testing.SetRealm(testing.NewUserRealm(opener))22 id := OpenCase(cross(cur), "receipt#7", []address{j1, j2, j3})23 uassert.Equal(t, string(PhaseCommit), string(Get(id).Phase))2425 // Each juror commits a hidden verdict (hash computed off-chain).26 commitAs(cur, j1, id, true, "s1")27 commitAs(cur, j2, id, false, "s2")28 uassert.Equal(t, string(PhaseCommit), string(Get(id).Phase)) // not all in yet29 commitAs(cur, j3, id, true, "s3")30 uassert.Equal(t, string(PhaseReveal), string(Get(id).Phase)) // auto-advanced3132 revealAs(cur, j1, id, true, "s1")33 revealAs(cur, j2, id, false, "s2")34 revealAs(cur, j3, id, true, "s3")3536 c := Get(id)37 uassert.Equal(t, string(PhaseClosed), string(c.Phase))38 uassert.Equal(t, "upheld", c.Outcome) // 2 yes vs 1 no39 uassert.Equal(t, 2, c.Yes)40 uassert.Equal(t, 1, c.No)4142 uassert.True(t, len(Render("")) > 0)43 uassert.True(t, len(Render("1")) > 0)44}4546// A juror cannot change their vote at reveal time: the commitment binds it.47func TestRevealMustMatchCommitment(cur realm, t *testing.T) {48 testing.SetRealm(testing.NewUserRealm(opener))49 id := OpenCase(cross(cur), "claim#3", []address{j1})50 commitAs(cur, j1, id, true, "salt")5152 testing.SetRealm(testing.NewUserRealm(j1))53 uassert.AbortsWithMessage(t, cur, "reveal does not match commitment", func(cur realm) {54 Reveal(cur, id, false, "salt") // flipped verdict55 })56}5758func TestOnlyPanelJurors(cur realm, t *testing.T) {59 testing.SetRealm(testing.NewUserRealm(opener))60 id := OpenCase(cross(cur), "x", []address{j1})61 testing.SetRealm(testing.NewUserRealm(nobody))62 uassert.AbortsWithMessage(t, cur, "caller is not on this jury", func(cur realm) {63 Commit(cur, id, commit.Verdict(true, "s"))64 })65}6667func TestNoDuplicateJurors(cur realm, t *testing.T) {68 testing.SetRealm(testing.NewUserRealm(opener))69 uassert.AbortsWithMessage(t, cur, "duplicate juror: "+j1.String(), func(cur realm) {70 OpenCase(cur, "x", []address{j1, j1})71 })72}7374// helpers7576func commitAs(cur realm, juror address, id uint64, verdict bool, salt string) {77 testing.SetRealm(testing.NewUserRealm(juror))78 Commit(cross(cur), id, commit.Verdict(verdict, salt))79}8081func revealAs(cur realm, juror address, id uint64, verdict bool, salt string) {82 testing.SetRealm(testing.NewUserRealm(juror))83 Reveal(cross(cur), id, verdict, salt)84}85Commit(cur interface {.seal func(); Address func() .uverse.address; IsCode func() bool; IsCurrent func() bool; IsEphemeral func() bool; IsUser func() bool; IsUserCall func() bool; IsUserRun func() bool; PkgPath func() string; Previous func() .uverse.realm; String func() string; Sub func(string) .uverse.realm; Subpath func() string}, caseID uint64, commitment string)
Count() int
Get(caseID uint64) struct{ID uint64; Subject string; Opener .uverse.address; Phase gno.land/r/moul/agents/jury/v0.Phase; Jurors []*gno.land/r/moul/agents/jury/v0.Juror; OpenedAt int64; Outcome string; Yes int; No int}
OpenCase(cur interface {.seal func(); Address func() .uverse.address; IsCode func() bool; IsCurrent func() bool; IsEphemeral func() bool; IsUser func() bool; IsUserCall func() bool; IsUserRun func() bool; PkgPath func() string; Previous func() .uverse.realm; String func() string; Sub func(string) .uverse.realm; Subpath func() string}, subject string, jurors [].uverse.address) uint64
Outcome(caseID uint64) string
Render(path string) string
Reveal(cur interface {.seal func(); Address func() .uverse.address; IsCode func() bool; IsCurrent func() bool; IsEphemeral func() bool; IsUser func() bool; IsUserCall func() bool; IsUserRun func() bool; PkgPath func() string; Previous func() .uverse.realm; String func() string; Sub func(string) .uverse.realm; Subpath func() string}, caseID uint64, verdict bool, salt string)
Signatures reconstructed verbatim from vm/qfuncs — interface params keep their inline definitions.
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.