feat(lns): add hash service aliases

This commit is contained in:
Virgil 2026-04-02 05:21:54 +00:00
parent 8900185063
commit 9ec0015b14
4 changed files with 178 additions and 0 deletions

43
lns.go
View file

@ -63,6 +63,17 @@ func (s *Service) Resolve(name any) (primitives.Hash, error) {
}
}
// Hash returns the canonical hash for a validated .lthn name.
//
// Hash is the direct service-level alias for Resolve.
//
// c := core.New(core.WithService(lns.Register))
// svc := c.Service("lns").(*lns.Service)
// hash, err := svc.Hash("example.lthn")
func (s *Service) Hash(name any) (primitives.Hash, error) {
return s.Resolve(name)
}
// Verify reports whether a .lthn name is valid after canonicalisation.
//
// This keeps the service-level API aligned with the DNS resolver helpers.
@ -81,6 +92,20 @@ func (s *Service) Verify(name any) bool {
}
}
// HashString returns the canonical hash for a .lthn name supplied as a string.
//
// ok := svc.HashString("example.lthn")
func (s *Service) HashString(name string) (primitives.Hash, error) {
return s.ResolveString(name)
}
// HashBinary returns the canonical hash for a .lthn name supplied as bytes.
//
// ok := svc.HashBinary([]byte("example.lthn"))
func (s *Service) HashBinary(name []byte) (primitives.Hash, error) {
return s.ResolveBinary(name)
}
// ResolveString returns the canonical hash for a .lthn name supplied as a string.
func (s *Service) ResolveString(name string) (primitives.Hash, error) {
normalized, ok := canonicalizeName(name)
@ -110,6 +135,15 @@ func (s *Service) ResolveName(name any) (primitives.Hash, error) {
return s.Resolve(name)
}
// HashName is an alias for Hash.
//
// c := core.New(core.WithService(lns.Register))
// svc := c.Service("lns").(*lns.Service)
// hash, err := svc.HashName("example.lthn")
func (s *Service) HashName(name any) (primitives.Hash, error) {
return s.Hash(name)
}
// VerifyName is an alias for Verify.
//
// c := core.New(core.WithService(lns.Register))
@ -128,6 +162,15 @@ func (s *Service) ResolveByName(name any) (primitives.Hash, error) {
return s.ResolveName(name)
}
// HashByName is an alias for HashName.
//
// c := core.New(core.WithService(lns.Register))
// svc := c.Service("lns").(*lns.Service)
// hash, err := svc.HashByName("example.lthn")
func (s *Service) HashByName(name any) (primitives.Hash, error) {
return s.HashName(name)
}
// VerifyByName is an alias for VerifyName.
//
// c := core.New(core.WithService(lns.Register))

View file

@ -150,6 +150,60 @@ func TestServiceResolveNameAliases(t *testing.T) {
}
}
func TestServiceHashAliases(t *testing.T) {
svc := &Service{}
got, err := svc.Hash("Foo-Bar.lthn")
if err != nil {
t.Fatalf("Hash returned error: %v", err)
}
want := primitives.Hash(sha3.Sum256([]byte("foo-bar")))
if got != want {
t.Fatalf("Hash returned %x, want %x", got, want)
}
got, err = svc.HashString("Foo-Bar.lthn")
if err != nil {
t.Fatalf("HashString returned error: %v", err)
}
if got != want {
t.Fatalf("HashString returned %x, want %x", got, want)
}
got, err = svc.HashBinary([]byte("Foo-Bar.lthn"))
if err != nil {
t.Fatalf("HashBinary returned error: %v", err)
}
if got != want {
t.Fatalf("HashBinary returned %x, want %x", got, want)
}
got, err = svc.HashName("Foo-Bar.lthn")
if err != nil {
t.Fatalf("HashName returned error: %v", err)
}
if got != want {
t.Fatalf("HashName returned %x, want %x", got, want)
}
got, err = svc.HashByName([]byte("Foo-Bar.lthn"))
if err != nil {
t.Fatalf("HashByName returned error: %v", err)
}
if got != want {
t.Fatalf("HashByName returned %x, want %x", got, want)
}
if _, err := svc.Hash(123); err == nil {
t.Fatal("Hash should reject unsupported input types")
}
}
func TestServiceResolveByNameAliases(t *testing.T) {
svc := &Service{}

View file

@ -74,6 +74,13 @@ func (s *Service) Resolve(name any) (primitives.Hash, error) {
return covenant.HashString(normalized)
}
// Hash returns the canonical hash for a .lthn name.
//
// Hash is the direct service-level alias for Resolve.
func (s *Service) Hash(name any) (primitives.Hash, error) {
return s.Resolve(name)
}
// Verify reports whether a .lthn name is valid after canonicalisation.
//
// This mirrors Resolve's input handling but returns a boolean so callers can
@ -90,6 +97,16 @@ func (s *Service) Verify(name any) bool {
return covenant.VerifyString(normalized)
}
// HashString returns the canonical hash for a .lthn name supplied as a string.
func (s *Service) HashString(name string) (primitives.Hash, error) {
return s.ResolveString(name)
}
// HashBinary returns the canonical hash for a .lthn name supplied as bytes.
func (s *Service) HashBinary(name []byte) (primitives.Hash, error) {
return s.ResolveBinary(name)
}
// ResolveString returns the canonical hash for a .lthn name supplied as a string.
//
// svc := dns.NewService()
@ -123,6 +140,11 @@ func (s *Service) ResolveName(name any) (primitives.Hash, error) {
return s.Resolve(name)
}
// HashName is an alias for Hash.
func (s *Service) HashName(name any) (primitives.Hash, error) {
return s.Hash(name)
}
// VerifyString reports whether a .lthn name supplied as a string is valid.
//
// svc := dns.NewService()
@ -160,6 +182,11 @@ func (s *Service) ResolveByName(name any) (primitives.Hash, error) {
return s.ResolveName(name)
}
// HashByName is an alias for HashName.
func (s *Service) HashByName(name any) (primitives.Hash, error) {
return s.HashName(name)
}
// VerifyByName is an alias for VerifyName.
//
// svc := dns.NewService()

View file

@ -48,6 +48,60 @@ func TestResolveNameAliases(t *testing.T) {
}
}
func TestHashAliases(t *testing.T) {
svc := NewService()
got, err := svc.Hash("Foo-Bar.lthn")
if err != nil {
t.Fatalf("Hash returned error: %v", err)
}
want := sha3.Sum256([]byte("foo-bar"))
if got != want {
t.Fatalf("Hash returned %x, want %x", got, want)
}
got, err = svc.HashString("Foo-Bar.lthn")
if err != nil {
t.Fatalf("HashString returned error: %v", err)
}
if got != want {
t.Fatalf("HashString returned %x, want %x", got, want)
}
got, err = svc.HashBinary([]byte("Foo-Bar.lthn"))
if err != nil {
t.Fatalf("HashBinary returned error: %v", err)
}
if got != want {
t.Fatalf("HashBinary returned %x, want %x", got, want)
}
got, err = svc.HashName("Foo-Bar.lthn")
if err != nil {
t.Fatalf("HashName returned error: %v", err)
}
if got != want {
t.Fatalf("HashName returned %x, want %x", got, want)
}
got, err = svc.HashByName([]byte("Foo-Bar.lthn"))
if err != nil {
t.Fatalf("HashByName returned error: %v", err)
}
if got != want {
t.Fatalf("HashByName returned %x, want %x", got, want)
}
if _, err := svc.Hash(123); err == nil {
t.Fatal("Hash should reject unsupported input types")
}
}
func TestResolveByNameAliases(t *testing.T) {
svc := NewService()