From ce66610369cfc4b0433ede1a37ceba93a7d4d2c8 Mon Sep 17 00:00:00 2001 From: Anna Shaleva Date: Mon, 5 Sep 2022 17:30:38 +0300 Subject: [PATCH 1/4] nns: adjust maxDomainNameFragmentLength Port https://github.com/nspcc-dev/neofs-contract/pull/238. --- examples/nft-nd-nns/nns.go | 2 +- examples/nft-nd-nns/nns_test.go | 16 +++++++++++++--- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/examples/nft-nd-nns/nns.go b/examples/nft-nd-nns/nns.go index 8f67beecb..dd07ff66c 100644 --- a/examples/nft-nd-nns/nns.go +++ b/examples/nft-nd-nns/nns.go @@ -48,7 +48,7 @@ const ( // maxRootLength is the maximum domain root length. maxRootLength = 16 // maxDomainNameFragmentLength is the maximum length of the domain name fragment. - maxDomainNameFragmentLength = 62 + maxDomainNameFragmentLength = 63 // minDomainNameLength is minimum domain length. minDomainNameLength = 3 // maxDomainNameLength is maximum domain length. diff --git a/examples/nft-nd-nns/nns_test.go b/examples/nft-nd-nns/nns_test.go index dcd0f6993..1e80ed7ce 100644 --- a/examples/nft-nd-nns/nns_test.go +++ b/examples/nft-nd-nns/nns_test.go @@ -137,7 +137,10 @@ func TestExpiration(t *testing.T) { cAcc.Invoke(t, stackitem.Null{}, "resolve", "first.com", int64(nns.TXT)) } -const millisecondsInYear = 365 * 24 * 3600 * 1000 +const ( + millisecondsInYear = 365 * 24 * 3600 * 1000 + maxDomainNameFragmentLength = 63 +) func TestRegisterAndRenew(t *testing.T) { c := newNSClient(t) @@ -154,9 +157,16 @@ func TestRegisterAndRenew(t *testing.T) { c.InvokeFail(t, "invalid domain name format", "register", "neo.com\n", e.CommitteeHash) c.InvokeWithFeeFail(t, "GAS limit exceeded", defaultNameServiceSysfee, "register", "neo.org", e.CommitteeHash) c.InvokeWithFeeFail(t, "GAS limit exceeded", defaultNameServiceDomainPrice, "register", "neo.com", e.CommitteeHash) + var maxLenFragment string + for i := 0; i < maxDomainNameFragmentLength; i++ { + maxLenFragment += "q" + } + c.Invoke(t, true, "isAvailable", maxLenFragment+".com") + c.Invoke(t, true, "register", maxLenFragment+".com", e.CommitteeHash) + c.InvokeFail(t, "invalid domain name format", "register", maxLenFragment+"q.com", e.CommitteeHash) c.Invoke(t, true, "isAvailable", "neo.com") - c.Invoke(t, 0, "balanceOf", e.CommitteeHash) + c.Invoke(t, 1, "balanceOf", e.CommitteeHash) c.Invoke(t, true, "register", "neo.com", e.CommitteeHash) topBlock := e.TopBlock(t) expectedExpiration := topBlock.Timestamp + millisecondsInYear @@ -167,7 +177,7 @@ func TestRegisterAndRenew(t *testing.T) { props.Add(stackitem.Make("name"), stackitem.Make("neo.com")) props.Add(stackitem.Make("expiration"), stackitem.Make(expectedExpiration)) c.Invoke(t, props, "properties", "neo.com") - c.Invoke(t, 1, "balanceOf", e.CommitteeHash) + c.Invoke(t, 2, "balanceOf", e.CommitteeHash) c.Invoke(t, e.CommitteeHash.BytesBE(), "ownerOf", []byte("neo.com")) t.Run("invalid token ID", func(t *testing.T) { From e97467726ce6ac57b84e18b23fcd310c5f1cd488 Mon Sep 17 00:00:00 2001 From: Anna Shaleva Date: Mon, 5 Sep 2022 17:30:43 +0300 Subject: [PATCH 2/4] nns: allow hyphen in domain names Port https://github.com/nspcc-dev/neofs-contract/pull/183. --- examples/nft-nd-nns/nns.go | 8 +++++--- examples/nft-nd-nns/nns_test.go | 8 +++++++- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/examples/nft-nd-nns/nns.go b/examples/nft-nd-nns/nns.go index dd07ff66c..529f24f88 100644 --- a/examples/nft-nd-nns/nns.go +++ b/examples/nft-nd-nns/nns.go @@ -507,6 +507,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 { @@ -525,12 +527,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/examples/nft-nd-nns/nns_test.go b/examples/nft-nd-nns/nns_test.go index 1e80ed7ce..38c10f9af 100644 --- a/examples/nft-nd-nns/nns_test.go +++ b/examples/nft-nd-nns/nns_test.go @@ -173,11 +173,17 @@ func TestRegisterAndRenew(t *testing.T) { c.Invoke(t, false, "register", "neo.com", e.CommitteeHash) c.Invoke(t, false, "isAvailable", "neo.com") + t.Run("domain names with hyphen", func(t *testing.T) { + c.InvokeFail(t, "invalid domain name format", "register", "-testdomain.com", e.CommitteeHash) + c.InvokeFail(t, "invalid domain name format", "register", "testdomain-.com", e.CommitteeHash) + c.Invoke(t, true, "register", "test-domain.com", e.CommitteeHash) + }) + props := stackitem.NewMap() props.Add(stackitem.Make("name"), stackitem.Make("neo.com")) props.Add(stackitem.Make("expiration"), stackitem.Make(expectedExpiration)) c.Invoke(t, props, "properties", "neo.com") - c.Invoke(t, 2, "balanceOf", e.CommitteeHash) + c.Invoke(t, 3, "balanceOf", e.CommitteeHash) c.Invoke(t, e.CommitteeHash.BytesBE(), "ownerOf", []byte("neo.com")) t.Run("invalid token ID", func(t *testing.T) { From c03e420355e8ead3ce73b07ffbbf235430a97441 Mon Sep 17 00:00:00 2001 From: Anna Shaleva Date: Mon, 5 Sep 2022 17:31:00 +0300 Subject: [PATCH 3/4] nns: allow to resolve FQDN Port https://github.com/nspcc-dev/neofs-contract/pull/139/commits/4041924a75a7d292b2e42b83f5795d7cb961bcba. --- examples/nft-nd-nns/nns.go | 6 ++++++ examples/nft-nd-nns/nns_test.go | 2 ++ 2 files changed, 8 insertions(+) diff --git a/examples/nft-nd-nns/nns.go b/examples/nft-nd-nns/nns.go index 529f24f88..e50abc9db 100644 --- a/examples/nft-nd-nns/nns.go +++ b/examples/nft-nd-nns/nns.go @@ -688,6 +688,12 @@ func resolve(ctx storage.Context, name string, typ RecordType, redirect int) str if redirect < 0 { panic("invalid redirect") } + if len(name) == 0 { + panic("invalid name") + } + if name[len(name)-1] == '.' { + name = name[:len(name)-1] + } records := getRecords(ctx, name) cname := "" for iterator.Next(records) { diff --git a/examples/nft-nd-nns/nns_test.go b/examples/nft-nd-nns/nns_test.go index 38c10f9af..426899675 100644 --- a/examples/nft-nd-nns/nns_test.go +++ b/examples/nft-nd-nns/nns_test.go @@ -436,6 +436,8 @@ func TestResolve(t *testing.T) { c.Invoke(t, "1.2.3.4", "resolve", "neo.com", int64(nns.A)) c.Invoke(t, "alias.com", "resolve", "neo.com", int64(nns.CNAME)) c.Invoke(t, "sometxt", "resolve", "neo.com", int64(nns.TXT)) + c.Invoke(t, "sometxt", "resolve", "neo.com.", int64(nns.TXT)) + c.InvokeFail(t, "invalid domain name format", "resolve", "neo.com..", int64(nns.TXT)) c.Invoke(t, stackitem.Null{}, "resolve", "neo.com", int64(nns.AAAA)) } From 94852ab7f4b4726925557f171cc775e9d2607059 Mon Sep 17 00:00:00 2001 From: Anna Shaleva Date: Mon, 5 Sep 2022 17:31:03 +0300 Subject: [PATCH 4/4] nns: add admin to properties See https://github.com/neo-project/non-native-contracts/blob/14f43ba8cf169323b61c23a3a701ac77d9a4e3eb/src/NameService/NameService.cs#L69. --- examples/nft-nd-nns/nns.go | 1 + examples/nft-nd-nns/nns_test.go | 7 +++++++ 2 files changed, 8 insertions(+) diff --git a/examples/nft-nd-nns/nns.go b/examples/nft-nd-nns/nns.go index e50abc9db..5a6800d47 100644 --- a/examples/nft-nd-nns/nns.go +++ b/examples/nft-nd-nns/nns.go @@ -118,6 +118,7 @@ func Properties(tokenID []byte) map[string]interface{} { return map[string]interface{}{ "name": ns.Name, "expiration": ns.Expiration, + "admin": ns.Admin, } } diff --git a/examples/nft-nd-nns/nns_test.go b/examples/nft-nd-nns/nns_test.go index 426899675..9032bb9d2 100644 --- a/examples/nft-nd-nns/nns_test.go +++ b/examples/nft-nd-nns/nns_test.go @@ -182,6 +182,7 @@ func TestRegisterAndRenew(t *testing.T) { props := stackitem.NewMap() props.Add(stackitem.Make("name"), stackitem.Make("neo.com")) props.Add(stackitem.Make("expiration"), stackitem.Make(expectedExpiration)) + props.Add(stackitem.Make("admin"), stackitem.Null{}) // no admin was set c.Invoke(t, props, "properties", "neo.com") c.Invoke(t, 3, "balanceOf", e.CommitteeHash) c.Invoke(t, e.CommitteeHash.BytesBE(), "ownerOf", []byte("neo.com")) @@ -319,6 +320,7 @@ func TestSetAdmin(t *testing.T) { c.Invoke(t, stackitem.Null{}, "addRoot", "com") cOwner.Invoke(t, true, "register", "neo.com", owner.ScriptHash()) + expectedExpiration := e.TopBlock(t).Timestamp + millisecondsInYear cGuest.InvokeFail(t, "not witnessed", "setAdmin", "neo.com", admin.ScriptHash()) // Must be witnessed by both owner and admin. @@ -326,6 +328,11 @@ func TestSetAdmin(t *testing.T) { cAdmin.InvokeFail(t, "not witnessed by owner", "setAdmin", "neo.com", admin.ScriptHash()) cc := c.WithSigners(owner, admin) cc.Invoke(t, stackitem.Null{}, "setAdmin", "neo.com", admin.ScriptHash()) + props := stackitem.NewMap() + props.Add(stackitem.Make("name"), stackitem.Make("neo.com")) + props.Add(stackitem.Make("expiration"), stackitem.Make(expectedExpiration)) + props.Add(stackitem.Make("admin"), stackitem.Make(admin.ScriptHash().BytesBE())) + c.Invoke(t, props, "properties", "neo.com") t.Run("set and delete by admin", func(t *testing.T) { cAdmin.Invoke(t, stackitem.Null{}, "setRecord", "neo.com", int64(nns.TXT), "sometext")