package grapevine import ( "testing" "smesh.lol/pkg/nostr/event" "smesh.lol/pkg/nostr/kind" "smesh.lol/pkg/nostr/signer/p8k" "smesh.lol/pkg/nostr/tag" "smesh.lol/pkg/store" ) func openTmp(t *testing.T) *store.Engine { t.Helper() eng, err := store.Open(t.TempDir()) if err != nil { t.Fatal(err) } t.Cleanup(func() { eng.Close() }) return eng } func genSigner(t *testing.T) *p8k.Signer { t.Helper() s := p8k.MustNew() if err := s.Generate(); err != nil { t.Fatal(err) } return s } func binPubkey(s *p8k.Signer) []byte { pk := []byte{:33} copy(pk, s.Pub()) // pk[32] = 0 already return pk } func makeFollowList(t *testing.T, signer *p8k.Signer, follows ...*p8k.Signer) *event.E { t.Helper() tags := tag.NewSWithCap(len(follows)) for _, f := range follows { *tags = append(*tags, tag.NewFromBytesSlice([]byte("p"), binPubkey(f))) } ev := &event.E{ CreatedAt: 1700000000, Kind: kind.FollowList.K, Tags: tags, } if err := ev.Sign(signer); err != nil { t.Fatal(err) } return ev } func TestComputeDepth1(t *testing.T) { eng := openTmp(t) seed := genSigner(t) alice := genSigner(t) bob := genSigner(t) // seed follows alice and bob if err := eng.SaveEvent(makeFollowList(t, seed, alice, bob)); err != nil { t.Fatal(err) } w := New(eng) scores := w.Compute(seed.Pub(), 1) if len(scores) != 2 { t.Fatalf("expected 2 scores, got %d", len(scores)) } // depth 1 decay = 1/2^0 = 1.0 for _, sc := range scores { if sc.Value != 1.0 { t.Errorf("expected score 1.0, got %f", sc.Value) } if sc.Depth != 1 { t.Errorf("expected depth 1, got %d", sc.Depth) } } } func TestComputeDepth2(t *testing.T) { eng := openTmp(t) seed := genSigner(t) alice := genSigner(t) bob := genSigner(t) // seed -> alice -> bob if err := eng.SaveEvent(makeFollowList(t, seed, alice)); err != nil { t.Fatal(err) } if err := eng.SaveEvent(makeFollowList(t, alice, bob)); err != nil { t.Fatal(err) } w := New(eng) scores := w.Compute(seed.Pub(), 2) found := false for _, sc := range scores { if string(sc.Pubkey) == string(bob.Pub()) { found = true // depth 2 decay = 1/2^1 = 0.5 if sc.Value != 0.5 { t.Errorf("expected bob score 0.5, got %f", sc.Value) } } } if !found { t.Fatal("bob not found in scores") } } func TestIsTrusted(t *testing.T) { scores := []Score{ {Pubkey: []byte("aaa"), Value: 0.8}, {Pubkey: []byte("bbb"), Value: 0.3}, } if !IsTrusted(scores, []byte("aaa"), 0.5) { t.Error("aaa should be trusted at 0.5 threshold") } if IsTrusted(scores, []byte("bbb"), 0.5) { t.Error("bbb should not be trusted at 0.5 threshold") } if IsTrusted(scores, []byte("ccc"), 0.1) { t.Error("unknown pubkey should not be trusted") } }