[#115] nns: Make 'DeleteDomain' faster
Signed-off-by: Alexander Chuprov <a.chuprov@yadro.com>
This commit is contained in:
parent
4e9adc2034
commit
b004b05b17
3 changed files with 99 additions and 16 deletions
23
nns/doc.go
23
nns/doc.go
|
@ -2,17 +2,18 @@
|
|||
|
||||
# Contract storage scheme
|
||||
|
||||
| Key | Value | Description |
|
||||
|--------------------------------------|------------|-----------------------------------|
|
||||
| 0x0 | int | total supply of minted domains |
|
||||
| 0x1 + accountAddr | int | account's balance |
|
||||
| 0x2 + accountAddr + tokenKey | ByteArray | token ID |
|
||||
| 0x10 | int | price for domain registration |
|
||||
| 0x20 | int | set of roots |
|
||||
| 0x21 + tokenKey | ByteArray | serialized NameState struct |
|
||||
| 0x22 + tokenKey + Hash160(tokenName) | Hash160 | container contract hash |
|
||||
| 0x23 + tokenKey + Hash160(tokenName) | string | global domain flag |
|
||||
|
||||
| Key | Value | Description |
|
||||
|--------------------------------------|------------|------------------------------------------------------|
|
||||
| 0x0 | int | total supply of minted domains |
|
||||
| 0x1 + accountAddr | int | account's balance |
|
||||
| 0x2 + accountAddr + tokenKey | ByteArray | token ID |
|
||||
| 0x10 | int | price for domain registration |
|
||||
| 0x20 | int | set of roots |
|
||||
| 0x21 + tokenKey | ByteArray | serialized NameState struct |
|
||||
| 0x22 + tokenKey + Hash160(tokenName) | Hash160 | container contract hash |
|
||||
| 0x23 + tokenKey + Hash160(tokenName) | string | global domain flag |
|
||||
| 0x24 + tokenKey | int | number of subdomains for the TLD domain |
|
||||
| 0x25 + tokenKey | bool | Flag indicating the automatically created TLD domain |
|
||||
*/
|
||||
|
||||
package nns
|
||||
|
|
|
@ -44,6 +44,11 @@ const (
|
|||
//prefixGlobalDomain contains a flag indicating that this domain was created using GlobalDomain.
|
||||
//This is necessary to distinguish it from regular CNAME records.
|
||||
prefixGlobalDomain byte = 0x23
|
||||
// prefixCountSubDomains contains information about the number of subdomains for the TLD domain.
|
||||
// If it is nil, it will definitely be calculated on the first removal
|
||||
prefixCountSubDomains byte = 0x24
|
||||
// prefixAutoCreated contains a flag indicating whether the TLD domain was created automatically
|
||||
prefixAutoCreated = 0x25
|
||||
)
|
||||
|
||||
// Values constraints.
|
||||
|
@ -335,7 +340,8 @@ func Register(name string, owner interop.Hash160, email string, refresh, retry,
|
|||
func register(ctx storage.Context, name string, owner interop.Hash160, email string, refresh, retry, expire, ttl int) bool {
|
||||
fragments := splitAndCheck(name)
|
||||
l := len(fragments)
|
||||
tldKey := append([]byte{prefixRoot}, []byte(fragments[l-1])...)
|
||||
rootZone := []byte(fragments[l-1])
|
||||
tldKey := append([]byte{prefixRoot}, rootZone...)
|
||||
|
||||
tldBytes := storage.Get(ctx, tldKey)
|
||||
if l == 1 {
|
||||
|
@ -348,6 +354,8 @@ func register(ctx storage.Context, name string, owner interop.Hash160, email str
|
|||
parent := checkParent(ctx, fragments)
|
||||
if parent == "" {
|
||||
parent = fragments[len(fragments)-1]
|
||||
|
||||
storage.Put(ctx, append([]byte{prefixAutoCreated}, rootZone...), true)
|
||||
register(ctx, parent, owner, email, refresh, retry, expire, ttl)
|
||||
}
|
||||
|
||||
|
@ -404,6 +412,18 @@ func register(ctx storage.Context, name string, owner interop.Hash160, email str
|
|||
updateBalance(ctx, []byte(name), owner, +1)
|
||||
postTransfer(oldOwner, owner, []byte(name), nil)
|
||||
runtime.Notify("RegisterDomain", name)
|
||||
|
||||
countSubDomain := 0
|
||||
delInfoRaw := storage.Get(ctx, append([]byte{prefixCountSubDomains}, rootZone...))
|
||||
if delInfoRaw != nil {
|
||||
countSubDomain = common.FromFixedWidth64(delInfoRaw.([]byte))
|
||||
}
|
||||
|
||||
if delInfoRaw != nil || l == 1 {
|
||||
countSubDomain = countSubDomain + 1
|
||||
storage.Put(ctx, append([]byte{prefixCountSubDomains}, rootZone...), common.ToFixedWidth64(countSubDomain))
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
|
@ -573,14 +593,37 @@ func DeleteDomain(name string) {
|
|||
deleteDomain(ctx, name)
|
||||
}
|
||||
|
||||
func deleteDomain(ctx storage.Context, name string) {
|
||||
func restoreCountSubDomains(ctx storage.Context, name string) int {
|
||||
countSubDomains := 0
|
||||
it := Tokens()
|
||||
for iterator.Next(it) {
|
||||
domain := iterator.Value(it)
|
||||
if std.MemorySearch([]byte(domain.(string)), []byte(name)) > 0 {
|
||||
panic("can't delete a domain that has subdomains")
|
||||
countSubDomains = countSubDomains + 1
|
||||
}
|
||||
}
|
||||
return countSubDomains
|
||||
}
|
||||
|
||||
func deleteDomain(ctx storage.Context, name string) {
|
||||
fragments := splitAndCheck(name)
|
||||
parent := []byte(fragments[len(fragments)-1])
|
||||
countSubDomainsKey := append([]byte{prefixCountSubDomains}, parent...)
|
||||
autoCreatedPrefix := append([]byte{prefixAutoCreated}, parent...)
|
||||
|
||||
countSubDomain := 0
|
||||
|
||||
countSubDomainRaw := storage.Get(ctx, countSubDomainsKey)
|
||||
if countSubDomainRaw != nil {
|
||||
countSubDomain = common.FromFixedWidth64(countSubDomainRaw.([]byte))
|
||||
} else {
|
||||
countSubDomain = restoreCountSubDomains(ctx, fragments[len(fragments)-1])
|
||||
storage.Put(ctx, countSubDomainsKey, std.Serialize(common.ToFixedWidth64(countSubDomain)))
|
||||
}
|
||||
|
||||
if countSubDomain > 1 && len(fragments) == 1 {
|
||||
panic("can't delete TLD domain that has subdomains")
|
||||
}
|
||||
|
||||
nsKey := append([]byte{prefixName}, getTokenKey([]byte(name))...)
|
||||
nsRaw := storage.Get(ctx, nsKey)
|
||||
|
@ -598,12 +641,26 @@ func deleteDomain(ctx storage.Context, name string) {
|
|||
deleteDomain(ctx, globalDomain)
|
||||
}
|
||||
|
||||
countSubDomain = countSubDomain - 1
|
||||
storage.Put(ctx, countSubDomainsKey, common.ToFixedWidth64(countSubDomain))
|
||||
|
||||
deleteRecords(ctx, name, CNAME)
|
||||
deleteRecords(ctx, name, TXT)
|
||||
deleteRecords(ctx, name, A)
|
||||
deleteRecords(ctx, name, AAAA)
|
||||
storage.Delete(ctx, nsKey)
|
||||
storage.Delete(ctx, append([]byte{prefixRoot}, []byte(name)...))
|
||||
|
||||
isAutoCrated := storage.Get(ctx, autoCreatedPrefix)
|
||||
if countSubDomain == 1 && isAutoCrated != nil {
|
||||
deleteDomain(ctx, fragments[len(fragments)-1])
|
||||
}
|
||||
|
||||
if len(fragments) == 1 {
|
||||
storage.Delete(ctx, countSubDomainsKey)
|
||||
storage.Delete(ctx, autoCreatedPrefix)
|
||||
}
|
||||
|
||||
runtime.Notify("DeleteDomain", name)
|
||||
}
|
||||
|
||||
|
|
|
@ -100,6 +100,18 @@ func TestNNSRegister(t *testing.T) {
|
|||
"com", accTop.ScriptHash(),
|
||||
"myemail@frostfs.info", refresh, retry, expire, ttl)
|
||||
|
||||
c1.Invoke(t, true, "register",
|
||||
"aa.bb.zz", accTop.ScriptHash(),
|
||||
"myemail@frostfs.info", refresh, retry, expire, ttl)
|
||||
|
||||
c1.InvokeFail(t, "TLD already exists", "register",
|
||||
"zz", accTop.ScriptHash(),
|
||||
"myemail@frostfs.info", refresh, retry, expire, ttl)
|
||||
|
||||
c1.Invoke(t, true, "register",
|
||||
"xx.bb.zz", accTop.ScriptHash(),
|
||||
"myemail@frostfs.info", refresh, retry, expire, ttl)
|
||||
|
||||
acc := c.NewAccount(t)
|
||||
c2 := c.WithSigners(c.Committee, acc)
|
||||
c2.InvokeFail(t, "not witnessed by admin", "register",
|
||||
|
@ -251,10 +263,23 @@ func TestDeleteDomain(t *testing.T) {
|
|||
"myemail@frostfs.info", defaultRefresh, defaultRetry, defaultExpire, defaultTTL)
|
||||
|
||||
c1.InvokeFail(t, "domain not found", "deleteDomain", "ru")
|
||||
c1.InvokeFail(t, "can't delete a domain that has subdomains", "deleteDomain", "testdomain.com")
|
||||
c1.Invoke(t, stackitem.Null{}, "deleteDomain", "domik.testdomain.com")
|
||||
c1.InvokeFail(t, "can't delete TLD domain that has subdomains", "deleteDomain", "com")
|
||||
c1.Invoke(t, stackitem.Null{}, "deleteDomain", "testdomain.com")
|
||||
|
||||
c1.Invoke(t, true, "register",
|
||||
"aa.bb.zz", acc1.ScriptHash(),
|
||||
"myemail@frostfs.info", defaultRefresh, defaultRetry, defaultExpire, defaultTTL)
|
||||
|
||||
c1.InvokeFail(t, "TLD already exists", "register",
|
||||
"zz", acc1.ScriptHash(),
|
||||
"myemail@frostfs.info", defaultRefresh, defaultRetry, defaultExpire, defaultTTL)
|
||||
|
||||
c1.Invoke(t, stackitem.Null{}, "deleteDomain", "aa.bb.zz")
|
||||
|
||||
c1.Invoke(t, true, "register",
|
||||
"zz", acc1.ScriptHash(),
|
||||
"myemail@frostfs.info", defaultRefresh, defaultRetry, defaultExpire, defaultTTL)
|
||||
|
||||
c1.Invoke(t, true, "register",
|
||||
"cn", acc1.ScriptHash(),
|
||||
"myemail@frostfs.info", defaultRefresh, defaultRetry, defaultExpire, defaultTTL)
|
||||
|
|
Loading…
Reference in a new issue