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

rendezvous_test.gno

3.41 Kb · 103 lines
  1package wesh
  2
  3import (
  4	"encoding/hex"
  5	"testing"
  6
  7	"gno.land/p/nt/uassert/v0"
  8)
  9
 10// Reference vectors produced by running weshnet's own algorithm
 11// (rendezvous.GenerateRendezvousPointForPeriod) against these inputs:
 12// topic = accountPK, seed = seed, interval = 24h.
 13const (
 14	testAccountPKHex = "2152f8d19b791d24453242e15f2eab6cb7cffa7b6a5ed30097960e069881db12"
 15	testSeedHex      = "abababababababababababababababababababababababababababababababab"
 16)
 17
 18func TestRoundPeriod(t *testing.T) {
 19	cases := []struct {
 20		name     string
 21		unixSec  int64
 22		interval int64
 23		want     int64
 24	}{
 25		{"epoch", 0, DefaultRotationInterval, 0},
 26		{"exactly on a boundary", 1789171200, DefaultRotationInterval, 1789171200},
 27		{"one second before the next", 1789257599, DefaultRotationInterval, 1789171200},
 28		{"one second after a boundary", 1789171201, DefaultRotationInterval, 1789171200},
 29		{"a negative interval is taken as positive", 1789257599, -DefaultRotationInterval, 1789171200},
 30		{"an hourly interval", 1789174800 + 59, 3600, 1789174800},
 31	}
 32	for _, tc := range cases {
 33		uassert.Equal(t, tc.want, RoundPeriod(tc.unixSec, tc.interval), tc.name)
 34	}
 35}
 36
 37func TestNextPeriod(t *testing.T) {
 38	uassert.Equal(t, int64(1789257600), NextPeriod(1789171200, DefaultRotationInterval))
 39	uassert.Equal(t, int64(1789257600), NextPeriod(1789257599, DefaultRotationInterval))
 40}
 41
 42// TestRendezvousPointMatchesWeshnet pins the derivation against vectors
 43// computed with weshnet's implementation. A divergence here means a gno-derived
 44// rendezvous point would not match the one the account actually announces on,
 45// which makes a published identity unverifiable.
 46func TestRendezvousPointMatchesWeshnet(t *testing.T) {
 47	pk := mustHex(t, testAccountPKHex)
 48	seed := mustHex(t, testSeedHex)
 49
 50	cases := []struct {
 51		name        string
 52		periodStart int64
 53		want        string
 54	}{
 55		{
 56			"period 0",
 57			0,
 58			"04500fdede2a684f4e61cd67968b46ecdbf10d45604041bb7e0350572b8cc9cc",
 59		},
 60		{
 61			"period starting 1789171200",
 62			1789171200,
 63			"aad2926c39dacabaabbbde48522d043557c8945b6a2dc7b08499c112c72587da",
 64		},
 65	}
 66	for _, tc := range cases {
 67		got := hex.EncodeToString(RendezvousPoint(pk, seed, tc.periodStart))
 68		uassert.Equal(t, tc.want, got, tc.name)
 69	}
 70}
 71
 72// TestRendezvousPointAtIsStableWithinAPeriod is the property that makes
 73// rotation useful: every instant inside one interval maps to the same point,
 74// and the next interval maps somewhere unrelated.
 75func TestRendezvousPointAtIsStableWithinAPeriod(t *testing.T) {
 76	c := Contact{AccountPK: mustHex(t, testAccountPKHex), Seed: mustHex(t, testSeedHex)}
 77
 78	start, err := c.RendezvousPointAt(1789171200, DefaultRotationInterval)
 79	uassert.NoError(t, err)
 80	end, err := c.RendezvousPointAt(1789257599, DefaultRotationInterval)
 81	uassert.NoError(t, err)
 82	next, err := c.RendezvousPointAt(1789257600, DefaultRotationInterval)
 83	uassert.NoError(t, err)
 84
 85	uassert.Equal(t, hex.EncodeToString(start), hex.EncodeToString(end),
 86		"the point is stable for the whole period")
 87	uassert.False(t, hex.EncodeToString(start) == hex.EncodeToString(next),
 88		"the point rotates at the period boundary")
 89}
 90
 91func TestRendezvousPointAtRejectsAnInvalidContact(t *testing.T) {
 92	_, err := Contact{AccountPK: repeat(1, 32), Seed: repeat(2, 31)}.RendezvousPointAt(0, DefaultRotationInterval)
 93	uassert.ErrorIs(t, err, ErrBadSeedLen)
 94}
 95
 96func mustHex(t *testing.T, s string) []byte {
 97	t.Helper()
 98	b, err := hex.DecodeString(s)
 99	if err != nil {
100		t.Fatalf("bad hex fixture: %v", err)
101	}
102	return b
103}