Skip to content

Commit

Permalink
Merge pull request #2679 from nspcc-dev/nns-upd
Browse files Browse the repository at this point in the history
examples: NNS update, part 1
  • Loading branch information
roman-khimov authored Sep 16, 2022
2 parents 8ecafaa + 94852ab commit 1f94ebe
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 7 deletions.
17 changes: 13 additions & 4 deletions examples/nft-nd-nns/nns.go
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -118,6 +118,7 @@ func Properties(tokenID []byte) map[string]interface{} {
return map[string]interface{}{
"name": ns.Name,
"expiration": ns.Expiration,
"admin": ns.Admin,
}
}

Expand Down Expand Up @@ -507,6 +508,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 {
Expand All @@ -525,12 +528,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.
Expand Down Expand Up @@ -686,6 +689,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) {
Expand Down
31 changes: 28 additions & 3 deletions examples/nft-nd-nns/nns_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -154,20 +157,34 @@ 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
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))
props.Add(stackitem.Make("admin"), stackitem.Null{}) // no admin was set
c.Invoke(t, props, "properties", "neo.com")
c.Invoke(t, 1, "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) {
Expand Down Expand Up @@ -303,13 +320,19 @@ 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.
cOwner.InvokeFail(t, "not witnessed by admin", "setAdmin", "neo.com", admin.ScriptHash())
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")
Expand Down Expand Up @@ -420,6 +443,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))
}

Expand Down

0 comments on commit 1f94ebe

Please sign in to comment.