diff --git a/nns/nns_contract.go b/nns/nns_contract.go index 8daad18..3f86690 100644 --- a/nns/nns_contract.go +++ b/nns/nns_contract.go @@ -687,6 +687,8 @@ func checkCommittee() { } // checkFragment validates root or a part of domain name. +// 1. Root domain must start with a letter. +// 2. All other fragments must start and end in a letter or a digit. func checkFragment(v string, isRoot bool) bool { maxLength := maxDomainNameFragmentLength if isRoot { @@ -705,12 +707,12 @@ func checkFragment(v string, isRoot bool) bool { return false } } - for i := 1; i < len(v); i++ { - if !isAlNum(v[i]) { + for i := 1; i < len(v)-1; i++ { + if v[i] != '-' && !isAlNum(v[i]) { return false } } - return true + return isAlNum(v[len(v)-1]) } // isAlNum checks whether provided char is a lowercase letter or a number. diff --git a/tests/nns_test.go b/tests/nns_test.go index 8d3b1cd..c0feb47 100644 --- a/tests/nns_test.go +++ b/tests/nns_test.go @@ -82,6 +82,17 @@ func TestNNSRegister(t *testing.T) { "myemail@nspcc.ru", refresh, retry, expire, ttl) c3 := c.WithSigners(accTop, acc) + t.Run("domain names with hyphen", func(t *testing.T) { + c3.InvokeFail(t, "invalid domain name format", "register", + "-testdomain.com", acc.ScriptHash(), + "myemail@nspcc.ru", refresh, retry, expire, ttl) + c3.InvokeFail(t, "invalid domain name format", "register", + "testdomain-.com", acc.ScriptHash(), + "myemail@nspcc.ru", refresh, retry, expire, ttl) + c3.Invoke(t, true, "register", + "test-domain.com", acc.ScriptHash(), + "myemail@nspcc.ru", refresh, retry, expire, ttl) + }) c3.Invoke(t, true, "register", "testdomain.com", acc.ScriptHash(), "myemail@nspcc.ru", refresh, retry, expire, ttl)