parent
ea934b8e30
commit
db9cea5ecc
2 changed files with 71 additions and 15 deletions
|
@ -247,7 +247,7 @@ func parentExpired(ctx storage.Context, first int, fragments []string) bool {
|
|||
|
||||
// Register registers new domain with the specified owner and name if it's available.
|
||||
func Register(name string, owner interop.Hash160, email string, refresh, retry, expire, ttl int) bool {
|
||||
fragments := splitAndCheck(name, false)
|
||||
fragments := splitAndCheck(name, true)
|
||||
if fragments == nil {
|
||||
panic("invalid domain name format")
|
||||
}
|
||||
|
@ -266,9 +266,9 @@ func Register(name string, owner interop.Hash160, email string, refresh, retry,
|
|||
panic("TLD not found")
|
||||
}
|
||||
if parentExpired(ctx, 1, fragments) {
|
||||
panic("one of the parent domains has expired")
|
||||
panic("one of the parent domains is not registered")
|
||||
}
|
||||
parentKey := getTokenKey([]byte(fragments[1]))
|
||||
parentKey := getTokenKey([]byte(name[len(fragments[0])+1:]))
|
||||
nsBytes := storage.Get(ctx, append([]byte{prefixName}, parentKey...))
|
||||
ns := std.Deserialize(nsBytes.([]byte)).(NameState)
|
||||
ns.checkAdmin()
|
||||
|
@ -331,7 +331,7 @@ func putSoaRecord(ctx storage.Context, name, email string, refresh, retry, expir
|
|||
std.Itoa(retry, 10) + " " +
|
||||
std.Itoa(expire, 10) + " " +
|
||||
std.Itoa(ttl, 10)
|
||||
tokenId := []byte(tokenIDFromName(name))
|
||||
tokenId := []byte(tokenIDFromName(ctx, name))
|
||||
putRecord(ctx, tokenId, name, SOA, 0, data)
|
||||
}
|
||||
|
||||
|
@ -428,7 +428,7 @@ func AddRecord(name string, typ RecordType, data string) {
|
|||
|
||||
// checkRecord performs record validness check and returns token ID.
|
||||
func checkRecord(ctx storage.Context, name string, typ RecordType, data string) []byte {
|
||||
tokenID := []byte(tokenIDFromName(name))
|
||||
tokenID := []byte(tokenIDFromName(ctx, name))
|
||||
var ok bool
|
||||
switch typ {
|
||||
case A:
|
||||
|
@ -453,8 +453,8 @@ func checkRecord(ctx storage.Context, name string, typ RecordType, data string)
|
|||
// GetRecords returns domain records of the specified type if they exist or an empty
|
||||
// array if not.
|
||||
func GetRecords(name string, typ RecordType) []string {
|
||||
tokenID := []byte(tokenIDFromName(name))
|
||||
ctx := storage.GetReadOnlyContext()
|
||||
tokenID := []byte(tokenIDFromName(ctx, name))
|
||||
_ = getNameState(ctx, tokenID) // ensure not expired
|
||||
return getRecordsByType(ctx, tokenID, name, typ)
|
||||
}
|
||||
|
@ -464,8 +464,8 @@ func DeleteRecords(name string, typ RecordType) {
|
|||
if typ == SOA {
|
||||
panic("forbidden to delete SOA record")
|
||||
}
|
||||
tokenID := []byte(tokenIDFromName(name))
|
||||
ctx := storage.GetContext()
|
||||
tokenID := []byte(tokenIDFromName(ctx, name))
|
||||
ns := getNameState(ctx, tokenID)
|
||||
ns.checkAdmin()
|
||||
recordsPrefix := getRecordsByTypePrefix(tokenID, name, typ)
|
||||
|
@ -554,7 +554,7 @@ func getNameState(ctx storage.Context, tokenID []byte) NameState {
|
|||
|
||||
// getNameStateWithKey returns domain name state by the specified token key.
|
||||
func getNameStateWithKey(ctx storage.Context, tokenKey []byte) NameState {
|
||||
nameKey := append([]byte{prefixName}, tokenKey...)
|
||||
nameKey := getNameStateKey(tokenKey)
|
||||
nsBytes := storage.Get(ctx, nameKey)
|
||||
if nsBytes == nil {
|
||||
panic("token not found")
|
||||
|
@ -564,6 +564,11 @@ func getNameStateWithKey(ctx storage.Context, tokenKey []byte) NameState {
|
|||
return ns
|
||||
}
|
||||
|
||||
// getNameStateKey returns NameState key for the provided token key.
|
||||
func getNameStateKey(tokenKey []byte) []byte {
|
||||
return append([]byte{prefixName}, tokenKey...)
|
||||
}
|
||||
|
||||
// putNameState stores domain name state.
|
||||
func putNameState(ctx storage.Context, ns NameState) {
|
||||
tokenKey := getTokenKey([]byte(ns.Name))
|
||||
|
@ -806,16 +811,25 @@ func checkIPv6(data string) bool {
|
|||
}
|
||||
|
||||
// tokenIDFromName returns token ID (domain.root) from provided name.
|
||||
func tokenIDFromName(name string) string {
|
||||
func tokenIDFromName(ctx storage.Context, name string) string {
|
||||
fragments := splitAndCheck(name, true)
|
||||
if fragments == nil {
|
||||
panic("invalid domain name format")
|
||||
}
|
||||
l := len(fragments)
|
||||
if l == 1 {
|
||||
return name
|
||||
sum := 0
|
||||
for i := 0; i < len(fragments)-1; i++ {
|
||||
tokenKey := getTokenKey([]byte(name[sum:]))
|
||||
nameKey := getNameStateKey(tokenKey)
|
||||
nsBytes := storage.Get(ctx, nameKey)
|
||||
if nsBytes != nil {
|
||||
ns := std.Deserialize(nsBytes.([]byte)).(NameState)
|
||||
if runtime.GetTime() < ns.Expiration {
|
||||
return name[sum:]
|
||||
}
|
||||
return name[len(name)-(len(fragments[l-1])+len(fragments[l-2])+1):]
|
||||
}
|
||||
sum += len(fragments[i]) + 1
|
||||
}
|
||||
return name
|
||||
}
|
||||
|
||||
// resolve resolves provided name using record with the specified type and given
|
||||
|
@ -855,7 +869,7 @@ func resolve(ctx storage.Context, res []string, name string, typ RecordType, red
|
|||
// specified name. Records returned are of different types and/or different IDs.
|
||||
// No keys are returned.
|
||||
func getAllRecords(ctx storage.Context, name string) iterator.Iterator {
|
||||
tokenID := []byte(tokenIDFromName(name))
|
||||
tokenID := []byte(tokenIDFromName(ctx, name))
|
||||
_ = getNameState(ctx, tokenID) // ensure not expired.
|
||||
recordsPrefix := getRecordsPrefix(tokenID, name)
|
||||
return storage.Find(ctx, recordsPrefix, storage.ValuesOnly|storage.DeserializeValues)
|
||||
|
|
|
@ -168,7 +168,7 @@ func TestRegisterAndRenew(t *testing.T) {
|
|||
c.Invoke(t, true, "register", "com", c.CommitteeHash, mail, refresh, retry, expire, ttl)
|
||||
c.Invoke(t, true, "isAvailable", "neo.com")
|
||||
c.InvokeWithFeeFail(t, "GAS limit exceeded", defaultNameServiceSysfee, "register", "neo.org", e.CommitteeHash, mail, refresh, retry, expire, ttl)
|
||||
c.InvokeFail(t, "invalid domain name format", "register", "docs.neo.org", e.CommitteeHash, mail, refresh, retry, expire, ttl)
|
||||
c.InvokeFail(t, "one of the parent domains is not registered", "register", "docs.neo.org", e.CommitteeHash, mail, refresh, retry, expire, ttl)
|
||||
c.InvokeFail(t, "invalid domain name format", "register", "\nneo.com'", e.CommitteeHash, mail, refresh, retry, expire, ttl)
|
||||
c.InvokeFail(t, "invalid domain name format", "register", "neo.com\n", e.CommitteeHash, mail, refresh, retry, expire, ttl)
|
||||
c.InvokeWithFeeFail(t, "GAS limit exceeded", defaultNameServiceSysfee, "register", "neo.org", e.CommitteeHash, mail, refresh, retry, expire, ttl)
|
||||
|
@ -593,6 +593,48 @@ func TestNNSAddRecord(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestNNSRegisterArbitraryLevelDomain(t *testing.T) {
|
||||
c := newNSClient(t, true)
|
||||
|
||||
newArgs := func(domain string, account neotest.Signer) []interface{} {
|
||||
return []interface{}{
|
||||
domain, account.ScriptHash(), "doesnt@matter.com",
|
||||
int64(101), int64(102), int64(103), int64(104),
|
||||
}
|
||||
}
|
||||
acc := c.NewAccount(t)
|
||||
cBoth := c.WithSigners(c.Committee, acc)
|
||||
args := newArgs("neo.com", acc)
|
||||
cBoth.Invoke(t, true, "register", args...)
|
||||
|
||||
c1 := c.WithSigners(acc)
|
||||
// parent domain is missing
|
||||
args[0] = "testnet.fs.neo.com"
|
||||
c1.InvokeFail(t, "one of the parent domains is not registered", "register", args...)
|
||||
|
||||
args[0] = "fs.neo.com"
|
||||
c1.Invoke(t, true, "register", args...)
|
||||
|
||||
args[0] = "testnet.fs.neo.com"
|
||||
c1.Invoke(t, true, "register", args...)
|
||||
|
||||
acc2 := c.NewAccount(t)
|
||||
c2 := c.WithSigners(c.Committee, acc2)
|
||||
args = newArgs("mainnet.fs.neo.com", acc2)
|
||||
c2.InvokeFail(t, "not witnessed by admin", "register", args...)
|
||||
|
||||
c2 = c.WithSigners(acc, acc2)
|
||||
c2.Invoke(t, true, "register", args...)
|
||||
|
||||
c2 = c.WithSigners(acc2)
|
||||
c2.Invoke(t, stackitem.Null{}, "addRecord",
|
||||
"cdn.mainnet.fs.neo.com", int64(nns.A), "166.15.14.13")
|
||||
result := stackitem.NewArray([]stackitem.Item{
|
||||
stackitem.NewByteArray([]byte("166.15.14.13")),
|
||||
})
|
||||
c2.Invoke(t, result, "resolve", "cdn.mainnet.fs.neo.com", int64(nns.A))
|
||||
}
|
||||
|
||||
const (
|
||||
defaultNameServiceDomainPrice = 10_0000_0000
|
||||
defaultNameServiceSysfee = 6000_0000
|
||||
|
|
Loading…
Reference in a new issue