Skip to content

Commit

Permalink
[#266] nns: Keep isAvailable in sync with register
Browse files Browse the repository at this point in the history
If conflicting records '*.domain' are present on new domain
registration, then `isAvailable` should return false for this
domain. Ref.
f25296b.

Signed-off-by: Anna Shaleva <[email protected]>
  • Loading branch information
AnnaShaleva committed Sep 14, 2022
1 parent c2e411c commit 6f49a54
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 11 deletions.
35 changes: 24 additions & 11 deletions nns/nns_contract.go
Original file line number Diff line number Diff line change
Expand Up @@ -224,7 +224,7 @@ func GetPrice() int {

// IsAvailable checks whether the provided domain name is available.
func IsAvailable(name string) bool {
fragments := splitAndCheck(name, false)
fragments := splitAndCheck(name, true)
if fragments == nil {
panic("invalid domain name format")
}
Expand All @@ -236,7 +236,27 @@ func IsAvailable(name string) bool {
}
return true
}
return parentExpired(ctx, 0, fragments)
if !parentExpired(ctx, 0, fragments) {
return false
}
return len(getParentConflictingRecord(ctx, name, fragments)) == 0
}

// getPrentConflictingRecord returns record of '*.name' format if they are presented.
// These records conflict with domain name to be registered.
func getParentConflictingRecord(ctx storage.Context, name string, fragments []string) string {
parentKey := getTokenKey([]byte(name[len(fragments[0])+1:]))
parentRecKey := append([]byte{prefixRecord}, parentKey...)
it := storage.Find(ctx, parentRecKey, storage.ValuesOnly|storage.DeserializeValues)
suffix := []byte(name)
for iterator.Next(it) {
r := iterator.Value(it).(RecordState)
ind := std.MemorySearchLastIndex([]byte(r.Name), suffix, len(r.Name))
if ind > 0 && ind+len(suffix) == len(r.Name) {
return r.Name
}
}
return ""
}

// parentExpired returns true if any domain from fragments doesn't exist or is expired.
Expand Down Expand Up @@ -290,15 +310,8 @@ func Register(name string, owner interop.Hash160, email string, refresh, retry,
ns := std.Deserialize(nsBytes.([]byte)).(NameState)
ns.checkAdmin()

parentRecKey := append([]byte{prefixRecord}, parentKey...)
it := storage.Find(ctx, parentRecKey, storage.ValuesOnly|storage.DeserializeValues)
suffix := []byte(name)
for iterator.Next(it) {
r := iterator.Value(it).(RecordState)
ind := std.MemorySearchLastIndex([]byte(r.Name), suffix, len(r.Name))
if ind > 0 && ind+len(suffix) == len(r.Name) {
panic("parent domain has conflicting records: " + r.Name)
}
if conflict := getParentConflictingRecord(ctx, name, fragments); len(conflict) != 0 {
panic("parent domain has conflicting records: " + conflict)
}
}

Expand Down
2 changes: 2 additions & 0 deletions tests/nns_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -178,11 +178,13 @@ func TestNNSRegisterMulti(t *testing.T) {
"another.fs.neo.com", int64(nns.A), "4.3.2.1")

c2 = c.WithSigners(acc, acc2)
c2.Invoke(t, stackitem.NewBool(false), "isAvailable", "mainnet.fs.neo.com")
c2.InvokeFail(t, "parent domain has conflicting records: something.mainnet.fs.neo.com",
"register", args...)

c1.Invoke(t, stackitem.Null{}, "deleteRecords",
"something.mainnet.fs.neo.com", int64(nns.A))
c2.Invoke(t, stackitem.NewBool(true), "isAvailable", "mainnet.fs.neo.com")
c2.Invoke(t, true, "register", args...)

c2 = c.WithSigners(acc2)
Expand Down

0 comments on commit 6f49a54

Please sign in to comment.