Compare commits

...

5 commits
master ... qqq

Author SHA1 Message Date
2865d8dd2e ss
Signed-off-by: Alexander Chuprov <a.chuprov@yadro.com>
2024-09-23 13:52:44 +03:00
ed82cd42e1 ss
Signed-off-by: Alexander Chuprov <a.chuprov@yadro.com>
2024-09-23 13:48:17 +03:00
dc1cb8c297 [#114] nns: Add docs
All checks were successful
DCO action / DCO (pull_request) Successful in 32s
Code generation / Generate wrappers (pull_request) Successful in 1m6s
Tests / Tests (pull_request) Successful in 1m16s
Signed-off-by: Alexander Chuprov <a.chuprov@yadro.com>
2024-09-23 13:36:33 +03:00
820bd283c1 [#114] nns: Move deleting global aliases along with TXT records
All checks were successful
DCO action / DCO (pull_request) Successful in 27s
Code generation / Generate wrappers (pull_request) Successful in 1m18s
Tests / Tests (pull_request) Successful in 1m20s
Signed-off-by: Alexander Chuprov <a.chuprov@yadro.com>
2024-09-23 13:25:42 +03:00
9632ef8970 [#114] nns: Restrict 'DeleteDomain' to delete domains with subdomains
Signed-off-by: Alexander Chuprov <a.chuprov@yadro.com>
2024-09-19 15:10:41 +03:00
7 changed files with 411 additions and 16 deletions

View file

@ -0,0 +1,162 @@
# Globally unique domain zone
**Make sure you understand the [basic concepts](../nns/README.md) of `NNS`.**
`Globally Unique Domains Zone` (`GUDZ`) is an extension of `NNS` that ensures unique names across multiple domain zones. When this option is enabled, all newly created domains will automatically receive a corresponding alias in the designated global zone. Deleting a domain will also remove its alias from the global zone.
It's important to note that this feature is not retroactive: domains created before this option is enabled will not receive a global alias. Likewise, if the option is later disabled, domains that already have a `GUDZ` alias will retain their records. To fully disable `GUDZ`, all domains must be recreated with the option turned off.
To enable `GUDZ`, add a `cnametgt=$(global domain)` `TXT` record that specifies the global zone.
**Example:**
Domains:
- `poland`
- `sweden`
- `animals.org`
![](img/GUDZ-2.png)
It is necessary to associate the domain zones `.poland` and `.sweden` into the global zone `.animals`.
![](img/GUDZ-1.png)
Create domains:
```
frostfs-adm morph nns register --name="poland" --email="email@email.email" --config /home/achuprov/Documents/work/frostfs-dev-env/frostfs-adm.yml
frostfs-adm morph nns register --name="sweden" --email="email@email.email" --config /home/achuprov/Documents/work/frostfs-dev-env/frostfs-adm.yml
frostfs-adm morph nns register --name="org" --email="email@email.email" --config /home/achuprov/Documents/work/frostfs-dev-env/frostfs-adm.yml
frostfs-adm morph nns register --name="animals.org" --email="email@email.email" --config /home/achuprov/Documents/work/frostfs-dev-env/frostfs-adm.yml
```
Add the `cnametgt` records:
```
frostfs-adm morph nns add-record --name="poland" --data="cnametgt=animals.org" --type="txt" --config /home/achuprov/Documents/work/frostfs-dev-env/frostfs-adm.yml
frostfs-adm morph nns add-record --name="sweden" --data="cnametgt=animals.org" --type="txt" --config /home/achuprov/Documents/work/frostfs-dev-env/frostfs-adm.yml
```
Create a domain with mapping to the global zone:
```
frostfs-adm morph nns register --name="bober.poland" --email="email@email.email" --config /home/achuprov/Documents/work/frostfs-dev-env/frostfs-adm.yml
```
Add any `TXT` record
```
frostfs-adm morph nns add-record --name="bober.poland" --data="CID" --type="txt" --config /home/achuprov/Documents/work/frostfs-dev-env/frostfs-adm.yml
```
Verify that the created domain has alias in the global zone
```
frostfs-adm morph nns tokens -v --config /home/achuprov/Documents/work/frostfs-dev-env/frostfs-adm.yml
balance.frostfs
animals.org
group.frostfs
container
org
container.frostfs
proxy.frostfs
policy.frostfs
alphabet0.frostfs
sweden
frostfsid.frostfs
bober.animals.org (CNAME: bober.sweden)
netmap.frostfs
frostfs
poland
bober.poland
```
Create of a conflicting domain
```
frostfs-adm morph nns register --name="bober.sweden" --email="email@email.email" --config /home/achuprov/Documents/work/frostfs-dev-env/frostfs-adm.yml
unable to register domain: script failed (FAULT state) due to an error: at instruction 1263 (THROW): unhandled exception: "global domain is already taken: bober.animals.org. Domain: bober.sweden
```
**Disable GUDZ**
Delete `cnametgt` records
```
frostfs-adm morph nns delete-records --type=txt --name=poland --config /home/achuprov/Documents/work/frostfs-dev-env/frostfs-adm.yml
```
Create `hamster.poland` and `hamster.sweden`
```
frostfs-adm morph nns register --name="hamster.poland" --email="email@email.email" --config /home/achuprov/Documents/work/frostfs-dev-env/frostfs-adm.yml
frostfs-adm morph nns register --name="hamster.sweden" --email="email@email.email" --config /home/achuprov/Documents/work/frostfs-dev-env/frostfs-adm.yml
```
`hamster.poland` and `hamster.sweden` does not have alias
```
frostfs-adm morph nns tokens -v --config /home/achuprov/Documents/work/frostfs-dev-env/frostfs-adm.yml
balance.frostfs
animals.org
group.frostfs
container
org
container.frostfs
proxy.frostfs
policy.frostfs
alphabet0.frostfs
sweden
frostfsid.frostfs
bober.animals.org (CNAME: bober.poland)
netmap.frostfs
frostfs
poland
bober.poland
hamster.poland
```
Delete global alias of `bober.poland`
```
frostfs-adm morph nns delete-records --name="bober.poland" --type="txt" --config /home/achuprov/Documents/work/frostfs-dev-env/frostfs-adm.yml
```
```
frostfs-adm morph nns tokens -v --config /home/achuprov/Documents/work/frostfs-dev-env/frostfs-adm.yml
balance.frostfs
animals.org
group.frostfs
container
org
container.frostfs
proxy.frostfs
policy.frostfs
alphabet0.frostfs
sweden
frostfsid.frostfs
netmap.frostfs
frostfs
poland
bober.poland
hamster.poland
```
Delete `bober.poland`
```
frostfs-adm morph nns delete --name="bober.poland" --config /home/achuprov/Documents/work/frostfs-dev-env/frostfs-adm.yml
```
```
frostfs-adm morph nns tokens -v --config /home/achuprov/Documents/work/frostfs-dev-env/frostfs-adm.yml
balance.frostfs
animals.org
group.frostfs
container
org
container.frostfs
proxy.frostfs
policy.frostfs
alphabet0.frostfs
sweden
frostfsid.frostfs
netmap.frostfs
frostfs
poland
hamster.poland
```

BIN
docs/img/GUDZ-1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

BIN
docs/img/GUDZ-2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

147
docs/img/GUDZ.drawio Normal file
View file

@ -0,0 +1,147 @@
<mxfile host="app.diagrams.net" agent="Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:129.0) Gecko/20100101 Firefox/129.0" version="24.7.10" pages="2">
<diagram name="Page-1" id="N1NjK5oQ_tQiBXsDL3WT">
<mxGraphModel dx="1185" dy="634" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="0" pageScale="1" pageWidth="850" pageHeight="1100" math="0" shadow="0">
<root>
<mxCell id="0" />
<mxCell id="1" parent="0" />
<mxCell id="XWaVog-Y-J4dgFkAMOIC-1" value=".ns" style="rounded=0;whiteSpace=wrap;html=1;" parent="1" vertex="1">
<mxGeometry x="130" y="170" width="120" height="60" as="geometry" />
</mxCell>
<mxCell id="XWaVog-Y-J4dgFkAMOIC-2" value=".org" style="rounded=0;whiteSpace=wrap;html=1;" parent="1" vertex="1">
<mxGeometry x="440" y="170" width="120" height="60" as="geometry" />
</mxCell>
<mxCell id="XWaVog-Y-J4dgFkAMOIC-3" value=".sweden" style="rounded=0;whiteSpace=wrap;html=1;" parent="1" vertex="1">
<mxGeometry x="250" y="290" width="120" height="60" as="geometry" />
</mxCell>
<mxCell id="XWaVog-Y-J4dgFkAMOIC-4" value=".poland" style="rounded=0;whiteSpace=wrap;html=1;" parent="1" vertex="1">
<mxGeometry x="10" y="290" width="120" height="60" as="geometry" />
</mxCell>
<mxCell id="XWaVog-Y-J4dgFkAMOIC-5" value="" style="endArrow=classic;html=1;rounded=0;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;" parent="1" source="XWaVog-Y-J4dgFkAMOIC-1" target="XWaVog-Y-J4dgFkAMOIC-4" edge="1">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="260" y="490" as="sourcePoint" />
<mxPoint x="310" y="440" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="XWaVog-Y-J4dgFkAMOIC-6" value="" style="endArrow=classic;html=1;rounded=0;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;" parent="1" source="XWaVog-Y-J4dgFkAMOIC-1" target="XWaVog-Y-J4dgFkAMOIC-3" edge="1">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="200" y="240" as="sourcePoint" />
<mxPoint x="80" y="300" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="XWaVog-Y-J4dgFkAMOIC-7" value="bober" style="rounded=0;whiteSpace=wrap;html=1;" parent="1" vertex="1">
<mxGeometry x="10" y="410" width="120" height="60" as="geometry" />
</mxCell>
<mxCell id="XWaVog-Y-J4dgFkAMOIC-8" value="" style="endArrow=classic;html=1;rounded=0;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;" parent="1" source="XWaVog-Y-J4dgFkAMOIC-4" target="XWaVog-Y-J4dgFkAMOIC-7" edge="1">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="190" y="460" as="sourcePoint" />
<mxPoint x="70" y="400" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="XWaVog-Y-J4dgFkAMOIC-9" value="bober" style="rounded=0;whiteSpace=wrap;html=1;dashed=1;strokeColor=#FF6666;" parent="1" vertex="1">
<mxGeometry x="250" y="410" width="120" height="60" as="geometry" />
</mxCell>
<mxCell id="XWaVog-Y-J4dgFkAMOIC-10" value="" style="endArrow=classic;html=1;rounded=0;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;dashed=1;fillColor=#f8cecc;strokeColor=#FF6666;" parent="1" target="XWaVog-Y-J4dgFkAMOIC-9" edge="1">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="310" y="350" as="sourcePoint" />
<mxPoint x="310" y="400" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="XWaVog-Y-J4dgFkAMOIC-11" value="bober" style="rounded=0;whiteSpace=wrap;html=1;" parent="1" vertex="1">
<mxGeometry x="440" y="410" width="120" height="60" as="geometry" />
</mxCell>
<mxCell id="XWaVog-Y-J4dgFkAMOIC-12" value="" style="endArrow=classic;html=1;rounded=0;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;" parent="1" target="XWaVog-Y-J4dgFkAMOIC-11" edge="1">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="500" y="350" as="sourcePoint" />
<mxPoint x="500" y="400" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="XWaVog-Y-J4dgFkAMOIC-14" value="&lt;font style=&quot;font-size: 5px;&quot;&gt;TXT cnametgt=animals.org&lt;/font&gt;" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" parent="1" vertex="1">
<mxGeometry x="30" y="320" width="80" height="30" as="geometry" />
</mxCell>
<mxCell id="XWaVog-Y-J4dgFkAMOIC-15" value=".&lt;span lang=&quot;en&quot; class=&quot;Y2IQFc&quot;&gt;animals&lt;/span&gt;" style="rounded=0;whiteSpace=wrap;html=1;" parent="1" vertex="1">
<mxGeometry x="440" y="290" width="120" height="60" as="geometry" />
</mxCell>
<mxCell id="XWaVog-Y-J4dgFkAMOIC-16" value="" style="endArrow=classic;html=1;rounded=0;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;" parent="1" edge="1">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="499.76" y="230" as="sourcePoint" />
<mxPoint x="499.76" y="290" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="XWaVog-Y-J4dgFkAMOIC-17" value="&lt;font style=&quot;font-size: 5px;&quot;&gt;TXT cnametgt=&lt;/font&gt;&lt;font style=&quot;font-size: 5px;&quot;&gt;animals.org&lt;/font&gt;" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" parent="1" vertex="1">
<mxGeometry x="270" y="320" width="80" height="30" as="geometry" />
</mxCell>
<mxCell id="XWaVog-Y-J4dgFkAMOIC-18" value="" style="shape=umlDestroy;whiteSpace=wrap;html=1;strokeWidth=3;targetShapes=umlLifeline;strokeColor=#FF6666;" parent="1" vertex="1">
<mxGeometry x="292.5" y="360" width="35" height="40" as="geometry" />
</mxCell>
<mxCell id="XWaVog-Y-J4dgFkAMOIC-52" value="&lt;span style=&quot;white-space: pre-wrap;&quot; data-src-align=&quot;0:10&quot; class=&quot;EzKURWReUAB5oZgtQNkl&quot;&gt;[ global&lt;/span&gt;&lt;span style=&quot;white-space: pre-wrap;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;white-space: pre-wrap;&quot; data-src-align=&quot;11:8&quot; class=&quot;EzKURWReUAB5oZgtQNkl&quot;&gt;domain&lt;/span&gt;&lt;span style=&quot;white-space: pre-wrap;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;white-space: pre-wrap;&quot; data-src-align=&quot;20:4&quot; class=&quot;EzKURWReUAB5oZgtQNkl&quot;&gt;zone ]&lt;/span&gt;" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" parent="1" vertex="1">
<mxGeometry x="425" y="110" width="150" height="30" as="geometry" />
</mxCell>
<mxCell id="if11Tw9RqGJKQk6h89ln-2" value="&lt;font style=&quot;font-size: 5px;&quot;&gt;CNAME bober&lt;/font&gt;&lt;font style=&quot;font-size: 5px;&quot;&gt;.&lt;/font&gt;&lt;font style=&quot;font-size: 5px;&quot;&gt;poland&lt;/font&gt;" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" parent="1" vertex="1">
<mxGeometry x="465" y="440" width="70" height="30" as="geometry" />
</mxCell>
</root>
</mxGraphModel>
</diagram>
<diagram id="6GukL70CSGlZ9N7Ng9Eu" name="Page-2">
<mxGraphModel dx="2074" dy="1510" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="0" pageScale="1" pageWidth="850" pageHeight="1100" math="0" shadow="0">
<root>
<mxCell id="0" />
<mxCell id="1" parent="0" />
<mxCell id="lPu7oo0X9kSJSLjapO69-1" value=".ns" style="rounded=0;whiteSpace=wrap;html=1;" parent="1" vertex="1">
<mxGeometry x="130" y="-250" width="120" height="60" as="geometry" />
</mxCell>
<mxCell id="lPu7oo0X9kSJSLjapO69-2" value=".org" style="rounded=0;whiteSpace=wrap;html=1;" parent="1" vertex="1">
<mxGeometry x="440" y="-250" width="120" height="60" as="geometry" />
</mxCell>
<mxCell id="lPu7oo0X9kSJSLjapO69-3" value=".sweden" style="rounded=0;whiteSpace=wrap;html=1;" parent="1" vertex="1">
<mxGeometry x="250" y="-130" width="120" height="60" as="geometry" />
</mxCell>
<mxCell id="lPu7oo0X9kSJSLjapO69-4" value=".poland" style="rounded=0;whiteSpace=wrap;html=1;" parent="1" vertex="1">
<mxGeometry x="10" y="-130" width="120" height="60" as="geometry" />
</mxCell>
<mxCell id="lPu7oo0X9kSJSLjapO69-5" value="" style="endArrow=classic;html=1;rounded=0;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;" parent="1" source="lPu7oo0X9kSJSLjapO69-1" target="lPu7oo0X9kSJSLjapO69-4" edge="1">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="260" y="70" as="sourcePoint" />
<mxPoint x="310" y="20" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="lPu7oo0X9kSJSLjapO69-6" value="" style="endArrow=classic;html=1;rounded=0;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;" parent="1" source="lPu7oo0X9kSJSLjapO69-1" target="lPu7oo0X9kSJSLjapO69-3" edge="1">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="200" y="-180" as="sourcePoint" />
<mxPoint x="80" y="-120" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="lPu7oo0X9kSJSLjapO69-7" value="bober" style="rounded=0;whiteSpace=wrap;html=1;" parent="1" vertex="1">
<mxGeometry x="10" y="-10" width="120" height="60" as="geometry" />
</mxCell>
<mxCell id="lPu7oo0X9kSJSLjapO69-8" value="" style="endArrow=classic;html=1;rounded=0;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;" parent="1" source="lPu7oo0X9kSJSLjapO69-4" target="lPu7oo0X9kSJSLjapO69-7" edge="1">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="190" y="40" as="sourcePoint" />
<mxPoint x="70" y="-20" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="lPu7oo0X9kSJSLjapO69-9" value=".&lt;span lang=&quot;en&quot; class=&quot;Y2IQFc&quot;&gt;animals&lt;/span&gt;" style="rounded=0;whiteSpace=wrap;html=1;" parent="1" vertex="1">
<mxGeometry x="440" y="-130" width="120" height="60" as="geometry" />
</mxCell>
<mxCell id="lPu7oo0X9kSJSLjapO69-10" value="" style="endArrow=classic;html=1;rounded=0;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;" parent="1" edge="1">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="499.76" y="-190" as="sourcePoint" />
<mxPoint x="499.76" y="-130" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="lPu7oo0X9kSJSLjapO69-11" value="" style="endArrow=classic;html=1;rounded=0;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;" parent="1" edge="1">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="309.71000000000004" y="-70" as="sourcePoint" />
<mxPoint x="309.71000000000004" y="-10" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="lPu7oo0X9kSJSLjapO69-12" value="bober" style="rounded=0;whiteSpace=wrap;html=1;" parent="1" vertex="1">
<mxGeometry x="250" y="-10" width="120" height="60" as="geometry" />
</mxCell>
<mxCell id="lPu7oo0X9kSJSLjapO69-13" value="&lt;span style=&quot;white-space: pre-wrap;&quot; data-src-align=&quot;0:10&quot; class=&quot;EzKURWReUAB5oZgtQNkl&quot;&gt;[ without global&lt;/span&gt;&lt;span style=&quot;white-space: pre-wrap;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;white-space: pre-wrap;&quot; data-src-align=&quot;11:8&quot; class=&quot;EzKURWReUAB5oZgtQNkl&quot;&gt;domain&lt;/span&gt;&lt;span style=&quot;white-space: pre-wrap;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;white-space: pre-wrap;&quot; data-src-align=&quot;20:4&quot; class=&quot;EzKURWReUAB5oZgtQNkl&quot;&gt;zone ]&lt;/span&gt;" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" parent="1" vertex="1">
<mxGeometry x="380" y="-310" width="180" height="30" as="geometry" />
</mxCell>
</root>
</mxGraphModel>
</diagram>
</mxfile>

46
nns/README.md Normal file
View file

@ -0,0 +1,46 @@
# NNS
NNS - Neo Name Service is a service that allows manage a domain name as a digital asset (NFT). It has an interface similar to `DNS` but has significant differences in its internal structure.
## Entities:
- Domain
- Record
- Owner
- Committee
### Domain
Domain is string that satisfies the following requirements:
- Length from 2 to 255 characters.
- Root domain must start with a letter.
- All other fragments must start and end with a letter or digit.
Domain has owner, a registration period, and may optionally have records.
A fee established by the committee is charged upon domain registration. After registration, the owner can manage this asset (add/delete records, transfer ownership to another owner) until the end of the domain registration period.
### Record
A record is a pair of values `<type, string>`.
Supported record types:
| Type | Description |
|-------|-------------------------------------------|
| A | Represents address record type |
| AAA | Represents IPv6 address record type |
| TXT | Represents text record type |
| CNAME | Represents canonical name record type |
| SOA | Represents start of authority record type |
### Owner
An owner is a wallet that has the right to manage this NFT (domain).
### Committee
The committee makes new tokens (domains), sets, and charges a fee for issuance.
## Globally Unique Domain Zone
For more information, see [here](../docs/globally-unique-domain-zone.md).

View file

@ -509,13 +509,17 @@ func deleteRecords(ctx storage.Context, name string, typ RecordType) {
tokenID := []byte(tokenIDFromName(name))
ns := getNameState(ctx, tokenID)
ns.checkAdmin()
globalDomainStorage := append([]byte{prefixGlobalDomain}, getTokenKey([]byte(name))...)
globalDomainRaw := storage.Get(ctx, globalDomainStorage)
if typ == TXT {
globalDomainKey := append([]byte{prefixGlobalDomain}, getTokenKey([]byte(name))...)
globalDomainRaw := storage.Get(ctx, globalDomainKey)
if globalDomainRaw != nil {
globalDomain := globalDomainRaw.(string)
if globalDomainRaw != nil && globalDomain != "" {
if globalDomain != "" {
deleteDomain(ctx, globalDomain)
}
storage.Delete(ctx, globalDomainKey)
}
}
recordsKey := getRecordsKeyByType(tokenID, name, typ)
records := storage.Find(ctx, recordsKey, storage.KeysOnly)
@ -534,23 +538,27 @@ func DeleteDomain(name string) {
}
func deleteDomain(ctx storage.Context, name string) {
nameKey := append([]byte{prefixName}, getTokenKey([]byte(name))...)
tldBytes := storage.Get(ctx, nameKey)
if tldBytes == nil {
return
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")
}
}
nsKey := append([]byte{prefixName}, getTokenKey([]byte(name))...)
nsRaw := storage.Get(ctx, nsKey)
if nsRaw == nil {
panic("domain not found")
}
globalDomainRaw := storage.Get(ctx, append([]byte{prefixGlobalDomain}, getTokenKey([]byte(name))...))
globalDomain := globalDomainRaw.(string)
if globalDomainRaw != nil && globalDomain != "" {
deleteDomain(ctx, globalDomain)
}
ns := std.Deserialize(nsRaw.([]byte)).(NameState)
ns.checkAdmin()
deleteRecords(ctx, name, CNAME)
deleteRecords(ctx, name, TXT)
deleteRecords(ctx, name, A)
deleteRecords(ctx, name, AAAA)
storage.Delete(ctx, nameKey)
storage.Delete(ctx, nsKey)
runtime.Notify("DeleteDomain", name)
}

View file

@ -189,6 +189,38 @@ func TestNNSRegister(t *testing.T) {
c.InvokeFail(t, "token not found", "getRecords", "testdomain.com", int64(nns.SOA))
}
func TestDeleteDomain(t *testing.T) {
c := newNNSInvoker(t, false)
acc1 := c.NewAccount(t)
c1 := c.WithSigners(c.Committee, acc1)
acc2 := c.NewAccount(t)
c2 := c.WithSigners(c.Committee, acc2)
c1.Invoke(t, true, "register",
"com", acc1.ScriptHash(),
"myemail@frostfs.info", defaultRefresh, defaultRetry, defaultExpire, defaultTTL)
c1.Invoke(t, true, "register",
"testdomain.com", acc1.ScriptHash(),
"myemail@frostfs.info", defaultRefresh, defaultRetry, defaultExpire, defaultTTL)
c1.Invoke(t, true, "register",
"domik.testdomain.com", acc1.ScriptHash(),
"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.Invoke(t, stackitem.Null{}, "deleteDomain", "testdomain.com")
c1.Invoke(t, true, "register",
"cn", acc1.ScriptHash(),
"myemail@frostfs.info", defaultRefresh, defaultRetry, defaultExpire, defaultTTL)
c2.InvokeFail(t, "not witnessed by admin", "deleteDomain", "cn")
}
func TestGlobalDomain(t *testing.T) {
c := newNNSInvoker(t, false)