nns: support SOA records

Port 7f1ec13ae5
and f4762c1b56.
This commit is contained in:
Anna Shaleva 2022-09-15 22:27:02 +03:00
parent 8790602f69
commit ea934b8e30
4 changed files with 153 additions and 75 deletions

View file

@ -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.
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)
if fragments == nil {
panic("invalid domain name format")
@ -303,14 +303,62 @@ func Register(name string, owner interop.Hash160) bool {
ns := NameState{
Owner: owner,
Name: name,
Expiration: runtime.GetTime() + millisecondsInYear,
Expiration: runtime.GetTime() + expire*1000,
}
putNameStateWithKey(ctx, tokenKey, ns)
putSoaRecord(ctx, name, email, refresh, retry, expire, ttl)
updateBalance(ctx, []byte(name), owner, +1)
postTransfer(oldOwner, owner, []byte(name), nil)
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.
func Renew(name string) int {
if len(name) > maxDomainNameLength {
@ -351,6 +399,7 @@ func SetRecord(name string, typ RecordType, id byte, data string) {
panic("unknown record")
}
putRecord(ctx, tokenID, name, typ, id, data)
updateSoaSerial(ctx, tokenID)
}
// 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")
}
putRecord(ctx, tokenID, name, typ, id, data)
updateSoaSerial(ctx, tokenID)
}
// 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.
func DeleteRecords(name string, typ RecordType) {
if typ == SOA {
panic("forbidden to delete SOA record")
}
tokenID := []byte(tokenIDFromName(name))
ctx := storage.GetContext()
ns := getNameState(ctx, tokenID)
@ -421,6 +474,7 @@ func DeleteRecords(name string, typ RecordType) {
key := iterator.Value(records).(string)
storage.Delete(ctx, key)
}
updateSoaSerial(ctx, tokenID)
}
// Resolve resolves given name (not more than three redirects are allowed) to a set

View file

@ -17,13 +17,24 @@ import (
"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)
e := neotest.NewExecutor(t, bc, acc, acc)
c := neotest.CompileFile(t, e.CommitteeHash, ".", "nns.yml")
e.DeployContract(t, c, nil)
ctr := neotest.CompileFile(t, e.CommitteeHash, ".", "nns.yml")
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) {
@ -32,7 +43,7 @@ func TestNameService_Price(t *testing.T) {
maxPrice = int64(10000_00000000)
)
c := newNSClient(t)
c := newNSClient(t, false)
t.Run("set, not signed by committee", func(t *testing.T) {
acc := c.NewAccount(t)
@ -65,7 +76,7 @@ func TestNameService_Price(t *testing.T) {
}
func TestNonfungible(t *testing.T) {
c := newNSClient(t)
c := newNSClient(t, false)
c.Signers = []neotest.Signer{c.NewAccount(t)}
c.Invoke(t, "NNS", "symbol")
@ -74,38 +85,39 @@ func TestNonfungible(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) {
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) {
acc := c.NewAccount(t)
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) {
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) {
c := newNSClient(t)
c := newNSClient(t, true)
e := c.Executor
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)
cAcc := c.WithSigners(acc)
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())
cAccCommittee.Invoke(t, true, "register", "first.com", acc.ScriptHash(), mail, refresh, retry, expire, ttl)
cAcc.Invoke(t, stackitem.Null{}, "addRecord", "first.com", int64(nns.TXT), "sometext")
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.Index = b1.Index + 1
b2.PrevHash = b1.Hash()
@ -117,7 +129,7 @@ func TestExpiration(t *testing.T) {
b3 := e.NewUnsignedBlock(t, tx)
b3.Index = b2.Index + 1
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)))
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))
}
const (
millisecondsInYear = 365 * 24 * 3600 * 1000
maxDomainNameFragmentLength = 63
)
func TestRegisterAndRenew(t *testing.T) {
c := newNSClient(t)
c := newNSClient(t, false)
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.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.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.InvokeWithFeeFail(t, "GAS limit exceeded", defaultNameServiceSysfee, "register", "neo.org", e.CommitteeHash)
c.InvokeFail(t, "invalid domain name format", "register", "docs.neo.org", e.CommitteeHash)
c.InvokeFail(t, "invalid domain name format", "register", "\nneo.com'", e.CommitteeHash)
c.InvokeFail(t, "invalid domain name format", "register", "neo.com\n", e.CommitteeHash)
c.InvokeWithFeeFail(t, "GAS limit exceeded", defaultNameServiceSysfee, "register", "neo.org", e.CommitteeHash)
c.InvokeWithFeeFail(t, "GAS limit exceeded", defaultNameServiceDomainPrice, "register", "neo.com", 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, 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)
c.InvokeWithFeeFail(t, "GAS limit exceeded", defaultNameServiceDomainPrice, "register", "neo.com", e.CommitteeHash, mail, refresh, retry, expire, ttl)
var maxLenFragment string
for i := 0; i < maxDomainNameFragmentLength; i++ {
maxLenFragment += "q"
}
c.Invoke(t, true, "isAvailable", maxLenFragment+".com")
c.Invoke(t, true, "register", maxLenFragment+".com", e.CommitteeHash)
c.InvokeFail(t, "invalid domain name format", "register", maxLenFragment+"q.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, mail, refresh, retry, expire, ttl)
c.Invoke(t, true, "isAvailable", "neo.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)
expectedExpiration := topBlock.Timestamp + millisecondsInYear
c.Invoke(t, false, "register", "neo.com", e.CommitteeHash)
expectedExpiration := topBlock.Timestamp + uint64(expire*1000)
c.Invoke(t, false, "register", "neo.com", e.CommitteeHash, mail, refresh, retry, expire, ttl)
c.Invoke(t, false, "isAvailable", "neo.com")
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)
c.Invoke(t, true, "register", "test-domain.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, mail, refresh, retry, expire, ttl)
c.Invoke(t, true, "register", "test-domain.com", e.CommitteeHash, mail, refresh, retry, expire, ttl)
})
props := stackitem.NewMap()
@ -211,17 +219,17 @@ func TestRegisterAndRenew(t *testing.T) {
}
func TestSetAddGetRecord(t *testing.T) {
c := newNSClient(t)
c := newNSClient(t, true)
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)
cAcc := c.WithSigners(acc)
c.Invoke(t, true, "register", "com", c.CommitteeHash)
t.Run("set before register", func(t *testing.T) {
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) {
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")
@ -333,8 +341,9 @@ func TestSetAddGetRecord(t *testing.T) {
}
func TestSetAdmin(t *testing.T) {
c := newNSClient(t)
c := newNSClient(t, true)
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)
cOwner := c.WithSigners(owner)
@ -344,11 +353,9 @@ func TestSetAdmin(t *testing.T) {
guest := e.NewAccount(t)
cGuest := c.WithSigners(guest)
c.Invoke(t, true, "register", "com", c.CommitteeHash)
cOwner.InvokeFail(t, "not witnessed by admin", "register", "neo.com", owner.ScriptHash()) // admin is committee
cOwnerCommittee.Invoke(t, true, "register", "neo.com", owner.ScriptHash())
expectedExpiration := e.TopBlock(t).Timestamp + millisecondsInYear
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)
expectedExpiration := e.TopBlock(t).Timestamp + uint64(expire)*1000
cGuest.InvokeFail(t, "not witnessed", "setAdmin", "neo.com", admin.ScriptHash())
// Must be witnessed by both owner and admin.
@ -376,8 +383,9 @@ func TestSetAdmin(t *testing.T) {
}
func TestTransfer(t *testing.T) {
c := newNSClient(t)
c := newNSClient(t, true)
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)
cFrom := c.WithSigners(from)
@ -385,8 +393,7 @@ func TestTransfer(t *testing.T) {
to := e.NewAccount(t)
cTo := c.WithSigners(to)
c.Invoke(t, true, "register", "com", c.CommitteeHash)
cFromCommittee.Invoke(t, true, "register", "neo.com", from.ScriptHash())
cFromCommittee.Invoke(t, true, "register", "neo.com", from.ScriptHash(), mail, refresh, retry, expire, ttl)
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)
c.Invoke(t, false, "transfer", to.ScriptHash(), "neo.com", nil)
@ -415,8 +422,9 @@ func TestTransfer(t *testing.T) {
}
func TestTokensOf(t *testing.T) {
c := newNSClient(t)
c := newNSClient(t, false)
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)
cAcc1Committee := c.WithSigners(acc1, c.Committee)
@ -424,9 +432,9 @@ func TestTokensOf(t *testing.T) {
cAcc2Committee := c.WithSigners(acc2, c.Committee)
tld := []byte("com")
c.Invoke(t, true, "register", tld, c.CommitteeHash)
cAcc1Committee.Invoke(t, true, "register", "neo.com", acc1.ScriptHash())
cAcc2Committee.Invoke(t, true, "register", "nspcc.com", acc2.ScriptHash())
c.Invoke(t, true, "register", tld, c.CommitteeHash, mail, refresh, retry, expire, ttl)
cAcc1Committee.Invoke(t, true, "register", "neo.com", acc1.ScriptHash(), mail, refresh, retry, expire, ttl)
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("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) {
c := newNSClient(t)
c := newNSClient(t, true)
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)
cAcc := c.WithSigners(acc)
cAccCommittee := c.WithSigners(acc, c.Committee)
c.Invoke(t, true, "register", "com", c.CommitteeHash)
cAccCommittee.Invoke(t, true, "register", "neo.com", acc.ScriptHash())
cAccCommittee.Invoke(t, true, "register", "neo.com", acc.ScriptHash(), mail, refresh, retry, expire, ttl)
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")
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.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")
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) {
c := newNSClient(t)
c := newNSClient(t, true)
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)
cAcc := c.WithSigners(acc)
cAccCommittee := c.WithSigners(acc, c.Committee)
c.Invoke(t, true, "register", "com", c.CommitteeHash)
cAccCommittee.Invoke(t, true, "register", "neo.com", acc.ScriptHash())
cAccCommittee.Invoke(t, true, "register", "neo.com", acc.ScriptHash(), mail, refresh, retry, expire, ttl)
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.TXT), "bla0")
cAcc.Invoke(t, stackitem.Null{}, "setRecord", "neo.com", int64(nns.TXT), 0, "bla1") // overwrite
time := e.TopBlock(t).Timestamp
// 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")
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.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.NewByteArray([]byte("neo.com")),
stackitem.Make(nns.TXT),
@ -538,20 +556,20 @@ func TestGetAllRecords(t *testing.T) {
}
func TestGetRecords(t *testing.T) {
c := newNSClient(t)
c := newNSClient(t, true)
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)
cAcc := c.WithSigners(acc)
cAccCommittee := c.WithSigners(acc, c.Committee)
c.Invoke(t, true, "register", "com", c.CommitteeHash)
cAccCommittee.Invoke(t, true, "register", "neo.com", acc.ScriptHash())
cAccCommittee.Invoke(t, true, "register", "neo.com", acc.ScriptHash(), mail, refresh, retry, expire, ttl)
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")
// 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")
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) {
c := newNSClient(t)
c := newNSClient(t, true)
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)
cAccCommittee.Invoke(t, true, "register", "neo.com", c.CommitteeHash, mail, refresh, retry, expire, ttl)
for i := 0; i <= maxRecordID+1; i++ {
if i == maxRecordID+1 {

View file

@ -9,6 +9,8 @@ const (
A RecordType = 1
// CNAME represents canonical name record type.
CNAME RecordType = 5
// SOA represents start of authority record type.
SOA RecordType = 6
// TXT represents text record type.
TXT RecordType = 16
)

View file

@ -21,7 +21,10 @@ import (
"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
// 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
// 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.
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)
require.Equal(t, 1, len(res.Events)) // transfer
tokenID, err := res.Events[0].Item.Value().([]stackitem.Item)[3].TryBytes()