parent
8790602f69
commit
ea934b8e30
4 changed files with 153 additions and 75 deletions
|
@ -246,7 +246,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.
|
// Register registers new domain with the specified owner and name if it's available.
|
||||||
func Register(name string, owner interop.Hash160) bool {
|
func Register(name string, owner interop.Hash160, email string, refresh, retry, expire, ttl int) bool {
|
||||||
fragments := splitAndCheck(name, false)
|
fragments := splitAndCheck(name, false)
|
||||||
if fragments == nil {
|
if fragments == nil {
|
||||||
panic("invalid domain name format")
|
panic("invalid domain name format")
|
||||||
|
@ -303,14 +303,62 @@ func Register(name string, owner interop.Hash160) bool {
|
||||||
ns := NameState{
|
ns := NameState{
|
||||||
Owner: owner,
|
Owner: owner,
|
||||||
Name: name,
|
Name: name,
|
||||||
Expiration: runtime.GetTime() + millisecondsInYear,
|
Expiration: runtime.GetTime() + expire*1000,
|
||||||
}
|
}
|
||||||
putNameStateWithKey(ctx, tokenKey, ns)
|
putNameStateWithKey(ctx, tokenKey, ns)
|
||||||
|
putSoaRecord(ctx, name, email, refresh, retry, expire, ttl)
|
||||||
updateBalance(ctx, []byte(name), owner, +1)
|
updateBalance(ctx, []byte(name), owner, +1)
|
||||||
postTransfer(oldOwner, owner, []byte(name), nil)
|
postTransfer(oldOwner, owner, []byte(name), nil)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// UpdateSOA updates soa record.
|
||||||
|
func UpdateSOA(name, email string, refresh, retry, expire, ttl int) {
|
||||||
|
if len(name) > maxDomainNameLength {
|
||||||
|
panic("invalid domain name format")
|
||||||
|
}
|
||||||
|
ctx := storage.GetContext()
|
||||||
|
ns := getNameState(ctx, []byte(name))
|
||||||
|
ns.checkAdmin()
|
||||||
|
putSoaRecord(ctx, name, email, refresh, retry, expire, ttl)
|
||||||
|
}
|
||||||
|
|
||||||
|
// putSoaRecord stores SOA domain record.
|
||||||
|
func putSoaRecord(ctx storage.Context, name, email string, refresh, retry, expire, ttl int) {
|
||||||
|
data := name + " " + email + " " +
|
||||||
|
std.Itoa(runtime.GetTime(), 10) + " " +
|
||||||
|
std.Itoa(refresh, 10) + " " +
|
||||||
|
std.Itoa(retry, 10) + " " +
|
||||||
|
std.Itoa(expire, 10) + " " +
|
||||||
|
std.Itoa(ttl, 10)
|
||||||
|
tokenId := []byte(tokenIDFromName(name))
|
||||||
|
putRecord(ctx, tokenId, name, SOA, 0, data)
|
||||||
|
}
|
||||||
|
|
||||||
|
// updateSoaSerial updates serial of the corresponding SOA domain record.
|
||||||
|
func updateSoaSerial(ctx storage.Context, tokenId []byte) {
|
||||||
|
recordKey := getRecordKey(tokenId, string(tokenId), SOA, 0)
|
||||||
|
|
||||||
|
recBytes := storage.Get(ctx, recordKey)
|
||||||
|
if recBytes == nil {
|
||||||
|
panic("SOA record not found")
|
||||||
|
}
|
||||||
|
rec := std.Deserialize(recBytes.([]byte)).(RecordState)
|
||||||
|
|
||||||
|
split := std.StringSplitNonEmpty(rec.Data, " ")
|
||||||
|
if len(split) != 7 {
|
||||||
|
panic("corrupted SOA record format")
|
||||||
|
}
|
||||||
|
split[2] = std.Itoa(runtime.GetTime(), 10) // update serial
|
||||||
|
rec.Data = split[0] + " " + split[1] + " " +
|
||||||
|
split[2] + " " + split[3] + " " +
|
||||||
|
split[4] + " " + split[5] + " " +
|
||||||
|
split[6]
|
||||||
|
|
||||||
|
recBytes = std.Serialize(rec)
|
||||||
|
storage.Put(ctx, recordKey, recBytes)
|
||||||
|
}
|
||||||
|
|
||||||
// Renew increases domain expiration date.
|
// Renew increases domain expiration date.
|
||||||
func Renew(name string) int {
|
func Renew(name string) int {
|
||||||
if len(name) > maxDomainNameLength {
|
if len(name) > maxDomainNameLength {
|
||||||
|
@ -351,6 +399,7 @@ func SetRecord(name string, typ RecordType, id byte, data string) {
|
||||||
panic("unknown record")
|
panic("unknown record")
|
||||||
}
|
}
|
||||||
putRecord(ctx, tokenID, name, typ, id, data)
|
putRecord(ctx, tokenID, name, typ, id, data)
|
||||||
|
updateSoaSerial(ctx, tokenID)
|
||||||
}
|
}
|
||||||
|
|
||||||
// AddRecord adds new record of the specified type to the provided domain.
|
// AddRecord adds new record of the specified type to the provided domain.
|
||||||
|
@ -374,6 +423,7 @@ func AddRecord(name string, typ RecordType, data string) {
|
||||||
panic("multiple CNAME records")
|
panic("multiple CNAME records")
|
||||||
}
|
}
|
||||||
putRecord(ctx, tokenID, name, typ, id, data)
|
putRecord(ctx, tokenID, name, typ, id, data)
|
||||||
|
updateSoaSerial(ctx, tokenID)
|
||||||
}
|
}
|
||||||
|
|
||||||
// checkRecord performs record validness check and returns token ID.
|
// checkRecord performs record validness check and returns token ID.
|
||||||
|
@ -411,6 +461,9 @@ func GetRecords(name string, typ RecordType) []string {
|
||||||
|
|
||||||
// DeleteRecords removes all domain records with the specified type.
|
// DeleteRecords removes all domain records with the specified type.
|
||||||
func DeleteRecords(name string, typ RecordType) {
|
func DeleteRecords(name string, typ RecordType) {
|
||||||
|
if typ == SOA {
|
||||||
|
panic("forbidden to delete SOA record")
|
||||||
|
}
|
||||||
tokenID := []byte(tokenIDFromName(name))
|
tokenID := []byte(tokenIDFromName(name))
|
||||||
ctx := storage.GetContext()
|
ctx := storage.GetContext()
|
||||||
ns := getNameState(ctx, tokenID)
|
ns := getNameState(ctx, tokenID)
|
||||||
|
@ -421,6 +474,7 @@ func DeleteRecords(name string, typ RecordType) {
|
||||||
key := iterator.Value(records).(string)
|
key := iterator.Value(records).(string)
|
||||||
storage.Delete(ctx, key)
|
storage.Delete(ctx, key)
|
||||||
}
|
}
|
||||||
|
updateSoaSerial(ctx, tokenID)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Resolve resolves given name (not more than three redirects are allowed) to a set
|
// Resolve resolves given name (not more than three redirects are allowed) to a set
|
||||||
|
|
|
@ -17,13 +17,24 @@ import (
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
func newNSClient(t *testing.T) *neotest.ContractInvoker {
|
const (
|
||||||
|
millisecondsInYear = 365 * 24 * 3600 * 1000
|
||||||
|
maxDomainNameFragmentLength = 63
|
||||||
|
)
|
||||||
|
|
||||||
|
func newNSClient(t *testing.T, registerComTLD bool) *neotest.ContractInvoker {
|
||||||
bc, acc := chain.NewSingle(t)
|
bc, acc := chain.NewSingle(t)
|
||||||
e := neotest.NewExecutor(t, bc, acc, acc)
|
e := neotest.NewExecutor(t, bc, acc, acc)
|
||||||
c := neotest.CompileFile(t, e.CommitteeHash, ".", "nns.yml")
|
ctr := neotest.CompileFile(t, e.CommitteeHash, ".", "nns.yml")
|
||||||
e.DeployContract(t, c, nil)
|
e.DeployContract(t, ctr, nil)
|
||||||
|
|
||||||
return e.CommitteeInvoker(c.Hash)
|
c := e.CommitteeInvoker(ctr.Hash)
|
||||||
|
if registerComTLD {
|
||||||
|
// Set expiration big enough to pass all tests.
|
||||||
|
mail, refresh, retry, expire, ttl := "sami@nspcc.ru", int64(101), int64(102), int64(millisecondsInYear/1000*100), int64(104)
|
||||||
|
c.Invoke(t, true, "register", "com", c.CommitteeHash, mail, refresh, retry, expire, ttl)
|
||||||
|
}
|
||||||
|
return c
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestNameService_Price(t *testing.T) {
|
func TestNameService_Price(t *testing.T) {
|
||||||
|
@ -32,7 +43,7 @@ func TestNameService_Price(t *testing.T) {
|
||||||
maxPrice = int64(10000_00000000)
|
maxPrice = int64(10000_00000000)
|
||||||
)
|
)
|
||||||
|
|
||||||
c := newNSClient(t)
|
c := newNSClient(t, false)
|
||||||
|
|
||||||
t.Run("set, not signed by committee", func(t *testing.T) {
|
t.Run("set, not signed by committee", func(t *testing.T) {
|
||||||
acc := c.NewAccount(t)
|
acc := c.NewAccount(t)
|
||||||
|
@ -65,7 +76,7 @@ func TestNameService_Price(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestNonfungible(t *testing.T) {
|
func TestNonfungible(t *testing.T) {
|
||||||
c := newNSClient(t)
|
c := newNSClient(t, false)
|
||||||
|
|
||||||
c.Signers = []neotest.Signer{c.NewAccount(t)}
|
c.Signers = []neotest.Signer{c.NewAccount(t)}
|
||||||
c.Invoke(t, "NNS", "symbol")
|
c.Invoke(t, "NNS", "symbol")
|
||||||
|
@ -74,38 +85,39 @@ func TestNonfungible(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestRegisterTLD(t *testing.T) {
|
func TestRegisterTLD(t *testing.T) {
|
||||||
c := newNSClient(t)
|
c := newNSClient(t, false)
|
||||||
|
mail, refresh, retry, expire, ttl := "sami@nspcc.ru", int64(101), int64(102), int64(millisecondsInYear/1000*100), int64(104)
|
||||||
|
|
||||||
t.Run("invalid format", func(t *testing.T) {
|
t.Run("invalid format", func(t *testing.T) {
|
||||||
c.InvokeFail(t, "invalid domain name format", "register", "", c.CommitteeHash)
|
c.InvokeFail(t, "invalid domain name format", "register", "", c.CommitteeHash, mail, refresh, retry, expire, ttl)
|
||||||
})
|
})
|
||||||
t.Run("not signed by committee", func(t *testing.T) {
|
t.Run("not signed by committee", func(t *testing.T) {
|
||||||
acc := c.NewAccount(t)
|
acc := c.NewAccount(t)
|
||||||
c := c.WithSigners(acc)
|
c := c.WithSigners(acc)
|
||||||
c.InvokeFail(t, "not witnessed by committee", "register", "some", c.CommitteeHash)
|
c.InvokeFail(t, "not witnessed by committee", "register", "some", c.CommitteeHash, mail, refresh, retry, expire, ttl)
|
||||||
})
|
})
|
||||||
|
|
||||||
c.Invoke(t, true, "register", "some", c.CommitteeHash)
|
c.Invoke(t, true, "register", "some", c.CommitteeHash, mail, refresh, retry, expire, ttl)
|
||||||
t.Run("already exists", func(t *testing.T) {
|
t.Run("already exists", func(t *testing.T) {
|
||||||
c.InvokeFail(t, "TLD already exists", "register", "some", c.CommitteeHash)
|
c.InvokeFail(t, "TLD already exists", "register", "some", c.CommitteeHash, mail, refresh, retry, expire, ttl)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestExpiration(t *testing.T) {
|
func TestExpiration(t *testing.T) {
|
||||||
c := newNSClient(t)
|
c := newNSClient(t, true)
|
||||||
e := c.Executor
|
e := c.Executor
|
||||||
bc := e.Chain
|
bc := e.Chain
|
||||||
|
mail, refresh, retry, expire, ttl := "sami@nspcc.ru", int64(101), int64(102), int64(millisecondsInYear/1000*100), int64(104)
|
||||||
|
|
||||||
acc := e.NewAccount(t)
|
acc := e.NewAccount(t)
|
||||||
cAcc := c.WithSigners(acc)
|
cAcc := c.WithSigners(acc)
|
||||||
cAccCommittee := c.WithSigners(acc, c.Committee) // acc + committee signers for ".com"'s subdomains registration
|
cAccCommittee := c.WithSigners(acc, c.Committee) // acc + committee signers for ".com"'s subdomains registration
|
||||||
|
|
||||||
c.Invoke(t, true, "register", "com", c.CommitteeHash)
|
cAccCommittee.Invoke(t, true, "register", "first.com", acc.ScriptHash(), mail, refresh, retry, expire, ttl)
|
||||||
cAccCommittee.Invoke(t, true, "register", "first.com", acc.ScriptHash())
|
|
||||||
cAcc.Invoke(t, stackitem.Null{}, "addRecord", "first.com", int64(nns.TXT), "sometext")
|
cAcc.Invoke(t, stackitem.Null{}, "addRecord", "first.com", int64(nns.TXT), "sometext")
|
||||||
b1 := e.TopBlock(t)
|
b1 := e.TopBlock(t)
|
||||||
|
|
||||||
tx := cAccCommittee.PrepareInvoke(t, "register", "second.com", acc.ScriptHash())
|
tx := cAccCommittee.PrepareInvoke(t, "register", "second.com", acc.ScriptHash(), mail, refresh, retry, expire, ttl)
|
||||||
b2 := e.NewUnsignedBlock(t, tx)
|
b2 := e.NewUnsignedBlock(t, tx)
|
||||||
b2.Index = b1.Index + 1
|
b2.Index = b1.Index + 1
|
||||||
b2.PrevHash = b1.Hash()
|
b2.PrevHash = b1.Hash()
|
||||||
|
@ -117,7 +129,7 @@ func TestExpiration(t *testing.T) {
|
||||||
b3 := e.NewUnsignedBlock(t, tx)
|
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 + (millisecondsInYear + 1)
|
b3.Timestamp = b1.Timestamp + (uint64(expire)*1000 + 1)
|
||||||
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
|
e.CheckHalt(t, tx.Hash(), stackitem.NewBool(true)) // "first.com" has been expired
|
||||||
|
|
||||||
|
@ -145,46 +157,42 @@ func TestExpiration(t *testing.T) {
|
||||||
// cAcc.Invoke(t, stackitem.Null{}, "resolve", "first.com", int64(nns.TXT))
|
// cAcc.Invoke(t, stackitem.Null{}, "resolve", "first.com", int64(nns.TXT))
|
||||||
}
|
}
|
||||||
|
|
||||||
const (
|
|
||||||
millisecondsInYear = 365 * 24 * 3600 * 1000
|
|
||||||
maxDomainNameFragmentLength = 63
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestRegisterAndRenew(t *testing.T) {
|
func TestRegisterAndRenew(t *testing.T) {
|
||||||
c := newNSClient(t)
|
c := newNSClient(t, false)
|
||||||
e := c.Executor
|
e := c.Executor
|
||||||
|
mail, refresh, retry, expire, ttl := "sami@nspcc.ru", int64(101), int64(102), int64(millisecondsInYear/1000*100), int64(104)
|
||||||
|
|
||||||
c.InvokeFail(t, "TLD not found", "isAvailable", "neo.com")
|
c.InvokeFail(t, "TLD not found", "isAvailable", "neo.com")
|
||||||
c.Invoke(t, true, "register", "org", c.CommitteeHash)
|
c.Invoke(t, true, "register", "org", c.CommitteeHash, mail, refresh, retry, expire, ttl)
|
||||||
c.InvokeFail(t, "TLD not found", "isAvailable", "neo.com")
|
c.InvokeFail(t, "TLD not found", "isAvailable", "neo.com")
|
||||||
c.Invoke(t, true, "register", "com", c.CommitteeHash)
|
c.Invoke(t, true, "register", "com", c.CommitteeHash, mail, refresh, retry, expire, ttl)
|
||||||
c.Invoke(t, true, "isAvailable", "neo.com")
|
c.Invoke(t, true, "isAvailable", "neo.com")
|
||||||
c.InvokeWithFeeFail(t, "GAS limit exceeded", defaultNameServiceSysfee, "register", "neo.org", e.CommitteeHash)
|
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)
|
c.InvokeFail(t, "invalid domain name format", "register", "docs.neo.org", e.CommitteeHash, mail, refresh, retry, expire, ttl)
|
||||||
c.InvokeFail(t, "invalid domain name format", "register", "\nneo.com'", e.CommitteeHash)
|
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)
|
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)
|
c.InvokeWithFeeFail(t, "GAS limit exceeded", defaultNameServiceSysfee, "register", "neo.org", e.CommitteeHash, mail, refresh, retry, expire, ttl)
|
||||||
c.InvokeWithFeeFail(t, "GAS limit exceeded", defaultNameServiceDomainPrice, "register", "neo.com", e.CommitteeHash)
|
c.InvokeWithFeeFail(t, "GAS limit exceeded", defaultNameServiceDomainPrice, "register", "neo.com", e.CommitteeHash, mail, refresh, retry, expire, ttl)
|
||||||
var maxLenFragment string
|
var maxLenFragment string
|
||||||
for i := 0; i < maxDomainNameFragmentLength; i++ {
|
for i := 0; i < maxDomainNameFragmentLength; i++ {
|
||||||
maxLenFragment += "q"
|
maxLenFragment += "q"
|
||||||
}
|
}
|
||||||
c.Invoke(t, true, "isAvailable", maxLenFragment+".com")
|
c.Invoke(t, true, "isAvailable", maxLenFragment+".com")
|
||||||
c.Invoke(t, true, "register", maxLenFragment+".com", e.CommitteeHash)
|
c.Invoke(t, true, "register", maxLenFragment+".com", e.CommitteeHash, mail, refresh, retry, expire, ttl)
|
||||||
c.InvokeFail(t, "invalid domain name format", "register", maxLenFragment+"q.com", e.CommitteeHash)
|
c.InvokeFail(t, "invalid domain name format", "register", maxLenFragment+"q.com", e.CommitteeHash, mail, refresh, retry, expire, ttl)
|
||||||
|
|
||||||
c.Invoke(t, true, "isAvailable", "neo.com")
|
c.Invoke(t, true, "isAvailable", "neo.com")
|
||||||
c.Invoke(t, 3, "balanceOf", e.CommitteeHash) // org, com, qqq...qqq.com
|
c.Invoke(t, 3, "balanceOf", e.CommitteeHash) // org, com, qqq...qqq.com
|
||||||
c.Invoke(t, true, "register", "neo.com", e.CommitteeHash)
|
c.Invoke(t, true, "register", "neo.com", e.CommitteeHash, mail, refresh, retry, expire, ttl)
|
||||||
topBlock := e.TopBlock(t)
|
topBlock := e.TopBlock(t)
|
||||||
expectedExpiration := topBlock.Timestamp + millisecondsInYear
|
expectedExpiration := topBlock.Timestamp + uint64(expire*1000)
|
||||||
c.Invoke(t, false, "register", "neo.com", e.CommitteeHash)
|
c.Invoke(t, false, "register", "neo.com", e.CommitteeHash, mail, refresh, retry, expire, ttl)
|
||||||
c.Invoke(t, false, "isAvailable", "neo.com")
|
c.Invoke(t, false, "isAvailable", "neo.com")
|
||||||
|
|
||||||
t.Run("domain names with hyphen", func(t *testing.T) {
|
t.Run("domain names with hyphen", func(t *testing.T) {
|
||||||
c.InvokeFail(t, "invalid domain name format", "register", "-testdomain.com", e.CommitteeHash)
|
c.InvokeFail(t, "invalid domain name format", "register", "-testdomain.com", e.CommitteeHash, mail, refresh, retry, expire, ttl)
|
||||||
c.InvokeFail(t, "invalid domain name format", "register", "testdomain-.com", e.CommitteeHash)
|
c.InvokeFail(t, "invalid domain name format", "register", "testdomain-.com", e.CommitteeHash, mail, refresh, retry, expire, ttl)
|
||||||
c.Invoke(t, true, "register", "test-domain.com", e.CommitteeHash)
|
c.Invoke(t, true, "register", "test-domain.com", e.CommitteeHash, mail, refresh, retry, expire, ttl)
|
||||||
})
|
})
|
||||||
|
|
||||||
props := stackitem.NewMap()
|
props := stackitem.NewMap()
|
||||||
|
@ -211,17 +219,17 @@ func TestRegisterAndRenew(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSetAddGetRecord(t *testing.T) {
|
func TestSetAddGetRecord(t *testing.T) {
|
||||||
c := newNSClient(t)
|
c := newNSClient(t, true)
|
||||||
e := c.Executor
|
e := c.Executor
|
||||||
|
mail, refresh, retry, expire, ttl := "sami@nspcc.ru", int64(101), int64(102), int64(millisecondsInYear/1000*100), int64(104)
|
||||||
|
|
||||||
acc := e.NewAccount(t)
|
acc := e.NewAccount(t)
|
||||||
cAcc := c.WithSigners(acc)
|
cAcc := c.WithSigners(acc)
|
||||||
c.Invoke(t, true, "register", "com", c.CommitteeHash)
|
|
||||||
|
|
||||||
t.Run("set before register", func(t *testing.T) {
|
t.Run("set before register", func(t *testing.T) {
|
||||||
c.InvokeFail(t, "token not found", "addRecord", "neo.com", int64(nns.TXT), "sometext")
|
c.InvokeFail(t, "token not found", "addRecord", "neo.com", int64(nns.TXT), "sometext")
|
||||||
})
|
})
|
||||||
c.Invoke(t, true, "register", "neo.com", e.CommitteeHash)
|
c.Invoke(t, true, "register", "neo.com", e.CommitteeHash, mail, refresh, retry, expire, ttl)
|
||||||
t.Run("invalid parameters", func(t *testing.T) {
|
t.Run("invalid parameters", func(t *testing.T) {
|
||||||
c.InvokeFail(t, "unsupported record type", "addRecord", "neo.com", int64(0xFF), "1.2.3.4")
|
c.InvokeFail(t, "unsupported record type", "addRecord", "neo.com", int64(0xFF), "1.2.3.4")
|
||||||
c.InvokeFail(t, "invalid record", "addRecord", "neo.com", int64(nns.A), "not.an.ip.address")
|
c.InvokeFail(t, "invalid record", "addRecord", "neo.com", int64(nns.A), "not.an.ip.address")
|
||||||
|
@ -333,8 +341,9 @@ func TestSetAddGetRecord(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSetAdmin(t *testing.T) {
|
func TestSetAdmin(t *testing.T) {
|
||||||
c := newNSClient(t)
|
c := newNSClient(t, true)
|
||||||
e := c.Executor
|
e := c.Executor
|
||||||
|
mail, refresh, retry, expire, ttl := "sami@nspcc.ru", int64(101), int64(102), int64(millisecondsInYear/1000*100), int64(104)
|
||||||
|
|
||||||
owner := e.NewAccount(t)
|
owner := e.NewAccount(t)
|
||||||
cOwner := c.WithSigners(owner)
|
cOwner := c.WithSigners(owner)
|
||||||
|
@ -344,11 +353,9 @@ func TestSetAdmin(t *testing.T) {
|
||||||
guest := e.NewAccount(t)
|
guest := e.NewAccount(t)
|
||||||
cGuest := c.WithSigners(guest)
|
cGuest := c.WithSigners(guest)
|
||||||
|
|
||||||
c.Invoke(t, true, "register", "com", c.CommitteeHash)
|
cOwner.InvokeFail(t, "not witnessed by admin", "register", "neo.com", owner.ScriptHash(), mail, refresh, retry, expire, ttl) // admin is committee
|
||||||
|
cOwnerCommittee.Invoke(t, true, "register", "neo.com", owner.ScriptHash(), mail, refresh, retry, expire, ttl)
|
||||||
cOwner.InvokeFail(t, "not witnessed by admin", "register", "neo.com", owner.ScriptHash()) // admin is committee
|
expectedExpiration := e.TopBlock(t).Timestamp + uint64(expire)*1000
|
||||||
cOwnerCommittee.Invoke(t, true, "register", "neo.com", owner.ScriptHash())
|
|
||||||
expectedExpiration := e.TopBlock(t).Timestamp + millisecondsInYear
|
|
||||||
cGuest.InvokeFail(t, "not witnessed", "setAdmin", "neo.com", admin.ScriptHash())
|
cGuest.InvokeFail(t, "not witnessed", "setAdmin", "neo.com", admin.ScriptHash())
|
||||||
|
|
||||||
// Must be witnessed by both owner and admin.
|
// Must be witnessed by both owner and admin.
|
||||||
|
@ -376,8 +383,9 @@ func TestSetAdmin(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestTransfer(t *testing.T) {
|
func TestTransfer(t *testing.T) {
|
||||||
c := newNSClient(t)
|
c := newNSClient(t, true)
|
||||||
e := c.Executor
|
e := c.Executor
|
||||||
|
mail, refresh, retry, expire, ttl := "sami@nspcc.ru", int64(101), int64(102), int64(millisecondsInYear/1000*100), int64(104)
|
||||||
|
|
||||||
from := e.NewAccount(t)
|
from := e.NewAccount(t)
|
||||||
cFrom := c.WithSigners(from)
|
cFrom := c.WithSigners(from)
|
||||||
|
@ -385,8 +393,7 @@ func TestTransfer(t *testing.T) {
|
||||||
to := e.NewAccount(t)
|
to := e.NewAccount(t)
|
||||||
cTo := c.WithSigners(to)
|
cTo := c.WithSigners(to)
|
||||||
|
|
||||||
c.Invoke(t, true, "register", "com", c.CommitteeHash)
|
cFromCommittee.Invoke(t, true, "register", "neo.com", from.ScriptHash(), mail, refresh, retry, expire, ttl)
|
||||||
cFromCommittee.Invoke(t, true, "register", "neo.com", from.ScriptHash())
|
|
||||||
cFrom.Invoke(t, stackitem.Null{}, "addRecord", "neo.com", int64(nns.A), "1.2.3.4")
|
cFrom.Invoke(t, stackitem.Null{}, "addRecord", "neo.com", int64(nns.A), "1.2.3.4")
|
||||||
cFrom.InvokeFail(t, "token not found", "transfer", to.ScriptHash(), "not.exists", nil)
|
cFrom.InvokeFail(t, "token not found", "transfer", to.ScriptHash(), "not.exists", nil)
|
||||||
c.Invoke(t, false, "transfer", to.ScriptHash(), "neo.com", nil)
|
c.Invoke(t, false, "transfer", to.ScriptHash(), "neo.com", nil)
|
||||||
|
@ -415,8 +422,9 @@ func TestTransfer(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestTokensOf(t *testing.T) {
|
func TestTokensOf(t *testing.T) {
|
||||||
c := newNSClient(t)
|
c := newNSClient(t, false)
|
||||||
e := c.Executor
|
e := c.Executor
|
||||||
|
mail, refresh, retry, expire, ttl := "sami@nspcc.ru", int64(101), int64(102), int64(millisecondsInYear/1000*100), int64(104)
|
||||||
|
|
||||||
acc1 := e.NewAccount(t)
|
acc1 := e.NewAccount(t)
|
||||||
cAcc1Committee := c.WithSigners(acc1, c.Committee)
|
cAcc1Committee := c.WithSigners(acc1, c.Committee)
|
||||||
|
@ -424,9 +432,9 @@ func TestTokensOf(t *testing.T) {
|
||||||
cAcc2Committee := c.WithSigners(acc2, c.Committee)
|
cAcc2Committee := c.WithSigners(acc2, c.Committee)
|
||||||
|
|
||||||
tld := []byte("com")
|
tld := []byte("com")
|
||||||
c.Invoke(t, true, "register", tld, c.CommitteeHash)
|
c.Invoke(t, true, "register", tld, c.CommitteeHash, mail, refresh, retry, expire, ttl)
|
||||||
cAcc1Committee.Invoke(t, true, "register", "neo.com", acc1.ScriptHash())
|
cAcc1Committee.Invoke(t, true, "register", "neo.com", acc1.ScriptHash(), mail, refresh, retry, expire, ttl)
|
||||||
cAcc2Committee.Invoke(t, true, "register", "nspcc.com", acc2.ScriptHash())
|
cAcc2Committee.Invoke(t, true, "register", "nspcc.com", acc2.ScriptHash(), mail, refresh, retry, expire, ttl)
|
||||||
|
|
||||||
testTokensOf(t, c, tld, [][]byte{[]byte("neo.com")}, acc1.ScriptHash().BytesBE())
|
testTokensOf(t, c, tld, [][]byte{[]byte("neo.com")}, acc1.ScriptHash().BytesBE())
|
||||||
testTokensOf(t, c, tld, [][]byte{[]byte("nspcc.com")}, acc2.ScriptHash().BytesBE())
|
testTokensOf(t, c, tld, [][]byte{[]byte("nspcc.com")}, acc2.ScriptHash().BytesBE())
|
||||||
|
@ -461,23 +469,23 @@ func testTokensOf(t *testing.T, c *neotest.ContractInvoker, tld []byte, result [
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestResolve(t *testing.T) {
|
func TestResolve(t *testing.T) {
|
||||||
c := newNSClient(t)
|
c := newNSClient(t, true)
|
||||||
e := c.Executor
|
e := c.Executor
|
||||||
|
mail, refresh, retry, expire, ttl := "sami@nspcc.ru", int64(101), int64(102), int64(millisecondsInYear/1000*100), int64(104)
|
||||||
|
|
||||||
acc := e.NewAccount(t)
|
acc := e.NewAccount(t)
|
||||||
cAcc := c.WithSigners(acc)
|
cAcc := c.WithSigners(acc)
|
||||||
cAccCommittee := c.WithSigners(acc, c.Committee)
|
cAccCommittee := c.WithSigners(acc, c.Committee)
|
||||||
|
|
||||||
c.Invoke(t, true, "register", "com", c.CommitteeHash)
|
cAccCommittee.Invoke(t, true, "register", "neo.com", acc.ScriptHash(), mail, refresh, retry, expire, ttl)
|
||||||
cAccCommittee.Invoke(t, true, "register", "neo.com", acc.ScriptHash())
|
|
||||||
cAcc.Invoke(t, stackitem.Null{}, "addRecord", "neo.com", int64(nns.A), "1.2.3.4")
|
cAcc.Invoke(t, stackitem.Null{}, "addRecord", "neo.com", int64(nns.A), "1.2.3.4")
|
||||||
cAcc.Invoke(t, stackitem.Null{}, "addRecord", "neo.com", int64(nns.CNAME), "alias.com")
|
cAcc.Invoke(t, stackitem.Null{}, "addRecord", "neo.com", int64(nns.CNAME), "alias.com")
|
||||||
|
|
||||||
cAccCommittee.Invoke(t, true, "register", "alias.com", acc.ScriptHash())
|
cAccCommittee.Invoke(t, true, "register", "alias.com", acc.ScriptHash(), mail, refresh, retry, expire, ttl)
|
||||||
cAcc.Invoke(t, stackitem.Null{}, "addRecord", "alias.com", int64(nns.TXT), "sometxt from alias1")
|
cAcc.Invoke(t, stackitem.Null{}, "addRecord", "alias.com", int64(nns.TXT), "sometxt from alias1")
|
||||||
cAcc.Invoke(t, stackitem.Null{}, "addRecord", "alias.com", int64(nns.CNAME), "alias2.com")
|
cAcc.Invoke(t, stackitem.Null{}, "addRecord", "alias.com", int64(nns.CNAME), "alias2.com")
|
||||||
|
|
||||||
cAccCommittee.Invoke(t, true, "register", "alias2.com", acc.ScriptHash())
|
cAccCommittee.Invoke(t, true, "register", "alias2.com", acc.ScriptHash(), mail, refresh, retry, expire, ttl)
|
||||||
cAcc.Invoke(t, stackitem.Null{}, "addRecord", "alias2.com", int64(nns.TXT), "sometxt from alias2")
|
cAcc.Invoke(t, stackitem.Null{}, "addRecord", "alias2.com", int64(nns.TXT), "sometxt from alias2")
|
||||||
|
|
||||||
c.Invoke(t, stackitem.NewArray([]stackitem.Item{stackitem.Make("1.2.3.4")}), "resolve", "neo.com", int64(nns.A))
|
c.Invoke(t, stackitem.NewArray([]stackitem.Item{stackitem.Make("1.2.3.4")}), "resolve", "neo.com", int64(nns.A))
|
||||||
|
@ -494,22 +502,23 @@ func TestResolve(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestGetAllRecords(t *testing.T) {
|
func TestGetAllRecords(t *testing.T) {
|
||||||
c := newNSClient(t)
|
c := newNSClient(t, true)
|
||||||
e := c.Executor
|
e := c.Executor
|
||||||
|
mail, refresh, retry, expire, ttl := "sami@nspcc.ru", int64(101), int64(102), int64(millisecondsInYear/1000*100), int64(104)
|
||||||
|
|
||||||
acc := e.NewAccount(t)
|
acc := e.NewAccount(t)
|
||||||
cAcc := c.WithSigners(acc)
|
cAcc := c.WithSigners(acc)
|
||||||
cAccCommittee := c.WithSigners(acc, c.Committee)
|
cAccCommittee := c.WithSigners(acc, c.Committee)
|
||||||
|
|
||||||
c.Invoke(t, true, "register", "com", c.CommitteeHash)
|
cAccCommittee.Invoke(t, true, "register", "neo.com", acc.ScriptHash(), mail, refresh, retry, expire, ttl)
|
||||||
cAccCommittee.Invoke(t, true, "register", "neo.com", acc.ScriptHash())
|
|
||||||
cAcc.Invoke(t, stackitem.Null{}, "addRecord", "neo.com", int64(nns.A), "1.2.3.4")
|
cAcc.Invoke(t, stackitem.Null{}, "addRecord", "neo.com", int64(nns.A), "1.2.3.4")
|
||||||
cAcc.Invoke(t, stackitem.Null{}, "addRecord", "neo.com", int64(nns.CNAME), "alias.com")
|
cAcc.Invoke(t, stackitem.Null{}, "addRecord", "neo.com", int64(nns.CNAME), "alias.com")
|
||||||
cAcc.Invoke(t, stackitem.Null{}, "addRecord", "neo.com", int64(nns.TXT), "bla0")
|
cAcc.Invoke(t, stackitem.Null{}, "addRecord", "neo.com", int64(nns.TXT), "bla0")
|
||||||
cAcc.Invoke(t, stackitem.Null{}, "setRecord", "neo.com", int64(nns.TXT), 0, "bla1") // overwrite
|
cAcc.Invoke(t, stackitem.Null{}, "setRecord", "neo.com", int64(nns.TXT), 0, "bla1") // overwrite
|
||||||
|
time := e.TopBlock(t).Timestamp
|
||||||
|
|
||||||
// Add some arbitrary data.
|
// Add some arbitrary data.
|
||||||
cAccCommittee.Invoke(t, true, "register", "alias.com", acc.ScriptHash())
|
cAccCommittee.Invoke(t, true, "register", "alias.com", acc.ScriptHash(), mail, refresh, retry, expire, ttl)
|
||||||
cAcc.Invoke(t, stackitem.Null{}, "addRecord", "alias.com", int64(nns.TXT), "sometxt")
|
cAcc.Invoke(t, stackitem.Null{}, "addRecord", "alias.com", int64(nns.TXT), "sometxt")
|
||||||
|
|
||||||
script, err := smartcontract.CreateCallAndUnwrapIteratorScript(c.Hash, "getAllRecords", 10, "neo.com")
|
script, err := smartcontract.CreateCallAndUnwrapIteratorScript(c.Hash, "getAllRecords", 10, "neo.com")
|
||||||
|
@ -528,6 +537,15 @@ func TestGetAllRecords(t *testing.T) {
|
||||||
stackitem.NewByteArray([]byte("alias.com")),
|
stackitem.NewByteArray([]byte("alias.com")),
|
||||||
stackitem.NewBigInteger(big.NewInt(0)),
|
stackitem.NewBigInteger(big.NewInt(0)),
|
||||||
}),
|
}),
|
||||||
|
stackitem.NewStruct([]stackitem.Item{
|
||||||
|
stackitem.NewByteArray([]byte("neo.com")),
|
||||||
|
stackitem.Make(nns.SOA),
|
||||||
|
stackitem.NewBuffer([]byte("neo.com" + " " + mail + " " +
|
||||||
|
strconv.Itoa(int(time)) + " " + strconv.Itoa(int(refresh)) + " " +
|
||||||
|
strconv.Itoa(int(retry)) + " " + strconv.Itoa(int(expire)) + " " +
|
||||||
|
strconv.Itoa(int(ttl)))),
|
||||||
|
stackitem.NewBigInteger(big.NewInt(0)),
|
||||||
|
}),
|
||||||
stackitem.NewStruct([]stackitem.Item{
|
stackitem.NewStruct([]stackitem.Item{
|
||||||
stackitem.NewByteArray([]byte("neo.com")),
|
stackitem.NewByteArray([]byte("neo.com")),
|
||||||
stackitem.Make(nns.TXT),
|
stackitem.Make(nns.TXT),
|
||||||
|
@ -538,20 +556,20 @@ func TestGetAllRecords(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestGetRecords(t *testing.T) {
|
func TestGetRecords(t *testing.T) {
|
||||||
c := newNSClient(t)
|
c := newNSClient(t, true)
|
||||||
e := c.Executor
|
e := c.Executor
|
||||||
|
mail, refresh, retry, expire, ttl := "sami@nspcc.ru", int64(101), int64(102), int64(millisecondsInYear/1000*100), int64(104)
|
||||||
|
|
||||||
acc := e.NewAccount(t)
|
acc := e.NewAccount(t)
|
||||||
cAcc := c.WithSigners(acc)
|
cAcc := c.WithSigners(acc)
|
||||||
cAccCommittee := c.WithSigners(acc, c.Committee)
|
cAccCommittee := c.WithSigners(acc, c.Committee)
|
||||||
|
|
||||||
c.Invoke(t, true, "register", "com", c.CommitteeHash)
|
cAccCommittee.Invoke(t, true, "register", "neo.com", acc.ScriptHash(), mail, refresh, retry, expire, ttl)
|
||||||
cAccCommittee.Invoke(t, true, "register", "neo.com", acc.ScriptHash())
|
|
||||||
cAcc.Invoke(t, stackitem.Null{}, "addRecord", "neo.com", int64(nns.A), "1.2.3.4")
|
cAcc.Invoke(t, stackitem.Null{}, "addRecord", "neo.com", int64(nns.A), "1.2.3.4")
|
||||||
cAcc.Invoke(t, stackitem.Null{}, "addRecord", "neo.com", int64(nns.CNAME), "alias.com")
|
cAcc.Invoke(t, stackitem.Null{}, "addRecord", "neo.com", int64(nns.CNAME), "alias.com")
|
||||||
|
|
||||||
// Add some arbitrary data.
|
// Add some arbitrary data.
|
||||||
cAccCommittee.Invoke(t, true, "register", "alias.com", acc.ScriptHash())
|
cAccCommittee.Invoke(t, true, "register", "alias.com", acc.ScriptHash(), mail, refresh, retry, expire, ttl)
|
||||||
cAcc.Invoke(t, stackitem.Null{}, "addRecord", "alias.com", int64(nns.TXT), "sometxt")
|
cAcc.Invoke(t, stackitem.Null{}, "addRecord", "alias.com", int64(nns.TXT), "sometxt")
|
||||||
|
|
||||||
c.Invoke(t, stackitem.NewArray([]stackitem.Item{stackitem.Make("1.2.3.4")}), "getRecords", "neo.com", int64(nns.A))
|
c.Invoke(t, stackitem.NewArray([]stackitem.Item{stackitem.Make("1.2.3.4")}), "getRecords", "neo.com", int64(nns.A))
|
||||||
|
@ -560,11 +578,11 @@ func TestGetRecords(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestNNSAddRecord(t *testing.T) {
|
func TestNNSAddRecord(t *testing.T) {
|
||||||
c := newNSClient(t)
|
c := newNSClient(t, true)
|
||||||
cAccCommittee := c.WithSigners(c.Committee)
|
cAccCommittee := c.WithSigners(c.Committee)
|
||||||
|
mail, refresh, retry, expire, ttl := "sami@nspcc.ru", int64(101), int64(102), int64(millisecondsInYear/1000*100), int64(104)
|
||||||
|
|
||||||
c.Invoke(t, true, "register", "com", c.CommitteeHash)
|
cAccCommittee.Invoke(t, true, "register", "neo.com", c.CommitteeHash, mail, refresh, retry, expire, ttl)
|
||||||
cAccCommittee.Invoke(t, true, "register", "neo.com", c.CommitteeHash)
|
|
||||||
|
|
||||||
for i := 0; i <= maxRecordID+1; i++ {
|
for i := 0; i <= maxRecordID+1; i++ {
|
||||||
if i == maxRecordID+1 {
|
if i == maxRecordID+1 {
|
||||||
|
|
|
@ -9,6 +9,8 @@ const (
|
||||||
A RecordType = 1
|
A RecordType = 1
|
||||||
// CNAME represents canonical name record type.
|
// CNAME represents canonical name record type.
|
||||||
CNAME RecordType = 5
|
CNAME RecordType = 5
|
||||||
|
// SOA represents start of authority record type.
|
||||||
|
SOA RecordType = 6
|
||||||
// TXT represents text record type.
|
// TXT represents text record type.
|
||||||
TXT RecordType = 16
|
TXT RecordType = 16
|
||||||
)
|
)
|
||||||
|
|
|
@ -21,7 +21,10 @@ import (
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
const neoAmount = 99999000
|
const (
|
||||||
|
neoAmount = 99999000
|
||||||
|
millisecondsInYear = 365 * 24 * 3600 * 1000
|
||||||
|
)
|
||||||
|
|
||||||
// Init pushes some predefined set of transactions into the given chain, it needs a path to
|
// Init pushes some predefined set of transactions into the given chain, it needs a path to
|
||||||
// the root project directory.
|
// the root project directory.
|
||||||
|
@ -165,11 +168,12 @@ func Init(t *testing.T, rootpath string, e *neotest.Executor) {
|
||||||
e.Validator.ScriptHash(), e.Committee.ScriptHash(), 1000_00000000, nil) // block #12
|
e.Validator.ScriptHash(), e.Committee.ScriptHash(), 1000_00000000, nil) // block #12
|
||||||
|
|
||||||
// Block #13: add `.com` root to NNS.
|
// Block #13: add `.com` root to NNS.
|
||||||
nsCommitteeInvoker.Invoke(t, true, "register", "com", nsCommitteeInvoker.CommitteeHash) // block #13
|
mail, refresh, retry, expire, ttl := "sami@nspcc.ru", int64(101), int64(102), int64(millisecondsInYear/1000*100), int64(104)
|
||||||
|
nsCommitteeInvoker.Invoke(t, true, "register", "com", nsCommitteeInvoker.CommitteeHash, mail, refresh, retry, expire, ttl) // block #13
|
||||||
|
|
||||||
// Block #14: register `neo.com` via NNS.
|
// Block #14: register `neo.com` via NNS.
|
||||||
registerTxH := nsPriv0CommitteeInvoker.Invoke(t, true, "register",
|
registerTxH := nsPriv0CommitteeInvoker.Invoke(t, true, "register",
|
||||||
"neo.com", priv0ScriptHash) // block #14
|
"neo.com", priv0ScriptHash, mail, refresh, retry, expire, ttl) // block #14
|
||||||
res := e.GetTxExecResult(t, registerTxH)
|
res := e.GetTxExecResult(t, registerTxH)
|
||||||
require.Equal(t, 1, len(res.Events)) // transfer
|
require.Equal(t, 1, len(res.Events)) // transfer
|
||||||
tokenID, err := res.Events[0].Item.Value().([]stackitem.Item)[3].TryBytes()
|
tokenID, err := res.Events[0].Item.Value().([]stackitem.Item)[3].TryBytes()
|
||||||
|
|
Loading…
Reference in a new issue