nns: keep isAvailable
in sync with register
If conflicting records '*.domain' are present on new domain
registration, then `isAvailable` should return false for this
domain. Ref.
f25296b17a
.
This commit is contained in:
parent
d5b1c0e429
commit
d8e0a02a86
2 changed files with 31 additions and 30 deletions
|
@ -208,7 +208,7 @@ func GetPrice() int {
|
||||||
|
|
||||||
// IsAvailable checks whether provided domain name is available.
|
// IsAvailable checks whether provided domain name is available.
|
||||||
func IsAvailable(name string) bool {
|
func IsAvailable(name string) bool {
|
||||||
fragments := splitAndCheck(name, false)
|
fragments := splitAndCheck(name, true)
|
||||||
if fragments == nil {
|
if fragments == nil {
|
||||||
panic("invalid domain name format")
|
panic("invalid domain name format")
|
||||||
}
|
}
|
||||||
|
@ -220,7 +220,27 @@ func IsAvailable(name string) bool {
|
||||||
}
|
}
|
||||||
return true
|
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 expired.
|
// parentExpired returns true if any domain from fragments doesn't exist or expired.
|
||||||
|
@ -273,15 +293,8 @@ func Register(name string, owner interop.Hash160, email string, refresh, retry,
|
||||||
ns := std.Deserialize(nsBytes.([]byte)).(NameState)
|
ns := std.Deserialize(nsBytes.([]byte)).(NameState)
|
||||||
ns.checkAdmin()
|
ns.checkAdmin()
|
||||||
|
|
||||||
parentRecKey := append([]byte{prefixRecord}, parentKey...)
|
if conflict := getParentConflictingRecord(ctx, name, fragments); len(conflict) != 0 {
|
||||||
it := storage.Find(ctx, parentRecKey, storage.ValuesOnly|storage.DeserializeValues)
|
panic("parent domain has conflicting records: " + conflict)
|
||||||
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)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -125,29 +125,15 @@ func TestExpiration(t *testing.T) {
|
||||||
require.NoError(t, bc.AddBlock(e.SignBlock(b2)))
|
require.NoError(t, bc.AddBlock(e.SignBlock(b2)))
|
||||||
e.CheckHalt(t, tx.Hash(), stackitem.NewBool(true))
|
e.CheckHalt(t, tx.Hash(), stackitem.NewBool(true))
|
||||||
|
|
||||||
tx = cAcc.PrepareInvoke(t, "isAvailable", "first.com")
|
b3 := e.NewUnsignedBlock(t)
|
||||||
b3 := e.NewUnsignedBlock(t, tx)
|
|
||||||
b3.Index = b2.Index + 1
|
b3.Index = b2.Index + 1
|
||||||
b3.PrevHash = b2.Hash()
|
b3.PrevHash = b2.Hash()
|
||||||
b3.Timestamp = b1.Timestamp + (uint64(expire)*1000 + 1)
|
b3.Timestamp = b1.Timestamp + (uint64(expire) * 1000)
|
||||||
require.NoError(t, bc.AddBlock(e.SignBlock(b3)))
|
require.NoError(t, bc.AddBlock(e.SignBlock(b3)))
|
||||||
e.CheckHalt(t, tx.Hash(), stackitem.NewBool(true)) // "first.com" has been expired
|
|
||||||
|
|
||||||
tx = cAcc.PrepareInvoke(t, "isAvailable", "second.com")
|
cAcc.Invoke(t, true, "isAvailable", "first.com") // "first.com" has been expired
|
||||||
b4 := e.NewUnsignedBlock(t, tx)
|
cAcc.Invoke(t, true, "isAvailable", "second.com") // TLD "com" has been expired
|
||||||
b4.Index = b3.Index + 1
|
cAcc.InvokeFail(t, "name has expired", "getRecords", "first.com", int64(nns.TXT))
|
||||||
b4.PrevHash = b3.Hash()
|
|
||||||
b4.Timestamp = b3.Timestamp + 1000
|
|
||||||
require.NoError(t, bc.AddBlock(e.SignBlock(b4)))
|
|
||||||
e.CheckHalt(t, tx.Hash(), stackitem.NewBool(true)) // TLD "com" has been expired
|
|
||||||
|
|
||||||
tx = cAcc.PrepareInvoke(t, "getRecords", "first.com", int64(nns.TXT))
|
|
||||||
b5 := e.NewUnsignedBlock(t, tx)
|
|
||||||
b5.Index = b4.Index + 1
|
|
||||||
b5.PrevHash = b4.Hash()
|
|
||||||
b5.Timestamp = b4.Timestamp + 1000
|
|
||||||
require.NoError(t, bc.AddBlock(e.SignBlock(b5)))
|
|
||||||
e.CheckFault(t, tx.Hash(), "name has expired")
|
|
||||||
|
|
||||||
// TODO: According to the new code, we can't re-register expired "com" TLD, because it's already registered; at the
|
// TODO: According to the new code, we can't re-register expired "com" TLD, because it's already registered; at the
|
||||||
// same time we can't renew it because it's already expired. We likely need to change this logic in the contract and
|
// same time we can't renew it because it's already expired. We likely need to change this logic in the contract and
|
||||||
|
@ -629,11 +615,13 @@ func TestNNSRegisterArbitraryLevelDomain(t *testing.T) {
|
||||||
"another.fs.neo.com", int64(nns.A), "4.3.2.1")
|
"another.fs.neo.com", int64(nns.A), "4.3.2.1")
|
||||||
|
|
||||||
c2 = c.WithSigners(acc, acc2)
|
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",
|
c2.InvokeFail(t, "parent domain has conflicting records: something.mainnet.fs.neo.com",
|
||||||
"register", args...)
|
"register", args...)
|
||||||
|
|
||||||
c1.Invoke(t, stackitem.Null{}, "deleteRecords",
|
c1.Invoke(t, stackitem.Null{}, "deleteRecords",
|
||||||
"something.mainnet.fs.neo.com", int64(nns.A))
|
"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.Invoke(t, true, "register", args...)
|
||||||
|
|
||||||
c2 = c.WithSigners(acc2)
|
c2 = c.WithSigners(acc2)
|
||||||
|
|
Loading…
Reference in a new issue