diff --git a/nns/namestate.go b/nns/namestate.go index 72bbf94..ea186c8 100644 --- a/nns/namestate.go +++ b/nns/namestate.go @@ -7,19 +7,14 @@ import ( // NameState represents domain name state. type NameState struct { - Owner interop.Hash160 - Name string + Owner interop.Hash160 + Name string + // Expiration field used to contain wall-clock time of a domain expiration. + // It is preserved for backwards compatibility, but is unused by the contract and should be ignored. Expiration int64 Admin interop.Hash160 } -// ensureNotExpired panics if domain name is expired. -func (n NameState) ensureNotExpired() { - if int64(runtime.GetTime()) >= n.Expiration { - panic("name has expired") - } -} - // checkAdmin panics if script container is not signed by the domain name admin. func (n NameState) checkAdmin() { if runtime.CheckWitness(n.Owner) { diff --git a/nns/nns_contract.go b/nns/nns_contract.go index d4bc83b..ce8523a 100644 --- a/nns/nns_contract.go +++ b/nns/nns_contract.go @@ -148,8 +148,7 @@ func Properties(tokenID []byte) map[string]any { ctx := storage.GetReadOnlyContext() ns := getNameState(ctx, tokenID) return map[string]any{ - "name": ns.Name, - "expiration": ns.Expiration, + "name": ns.Name, } } @@ -308,7 +307,6 @@ func extractCnametgt(ctx storage.Context, name, domain string) string { // checkParent returns parent domain or empty string if domain not found. func checkParent(ctx storage.Context, fragments []string) string { - now := int64(runtime.GetTime()) last := len(fragments) - 1 name := fragments[last] parent := "" @@ -320,10 +318,6 @@ func checkParent(ctx storage.Context, fragments []string) string { if nsBytes == nil { continue } - ns := std.Deserialize(nsBytes.([]byte)).(NameState) - if now >= ns.Expiration { - panic("domain expired: " + name) - } parent = name } return parent @@ -390,19 +384,15 @@ func register(ctx storage.Context, name string, owner interop.Hash160, email str nsBytes := storage.Get(ctx, append([]byte{prefixName}, tokenKey...)) if nsBytes != nil { ns := std.Deserialize(nsBytes.([]byte)).(NameState) - if int64(runtime.GetTime()) < ns.Expiration { - return false - } oldOwner = ns.Owner updateBalance(ctx, []byte(name), oldOwner, -1) } else { updateTotalSupply(ctx, +1) } ns := NameState{ - Owner: owner, - Name: name, - // NNS expiration is in milliseconds - Expiration: int64(runtime.GetTime() + expire*1000), + Owner: owner, + Name: name, + Expiration: 0, } checkAvailableGlobalDomain(ctx, name) @@ -415,18 +405,6 @@ func register(ctx storage.Context, name string, owner interop.Hash160, email str return true } -// Renew increases domain expiration date. -func Renew(name string) int64 { - checkDomainNameLength(name) - runtime.BurnGas(GetPrice()) - ctx := storage.GetContext() - ns := getNameState(ctx, []byte(name)) - ns.checkAdmin() - ns.Expiration += millisecondsInYear - putNameState(ctx, ns) - return ns.Expiration -} - // UpdateSOA updates soa record. func UpdateSOA(name, email string, refresh, retry, expire, ttl int) { checkDomainNameLength(name) @@ -731,9 +709,7 @@ func getNameStateWithKey(ctx storage.Context, tokenKey []byte) NameState { if nsBytes == nil { panic("token not found") } - ns := std.Deserialize(nsBytes.([]byte)).(NameState) - ns.ensureNotExpired() - return ns + return std.Deserialize(nsBytes.([]byte)).(NameState) } // putNameState stores domain name state. @@ -801,7 +777,7 @@ func addRecord(ctx storage.Context, tokenId []byte, name string, typ RecordType, ns := NameState{ Name: globalDomain, Owner: nsOriginal.Owner, - Expiration: nsOriginal.Expiration, + Expiration: 0, Admin: nsOriginal.Admin, } @@ -1125,10 +1101,7 @@ func tokenIDFromName(name string) string { nameKey := append([]byte{prefixName}, tokenKey...) nsBytes := storage.Get(ctx, nameKey) if nsBytes != nil { - ns := std.Deserialize(nsBytes.([]byte)).(NameState) - if int64(runtime.GetTime()) < ns.Expiration { - return name[sum:] - } + return name[sum:] } sum += len(fragments[i]) + 1 } diff --git a/rpcclient/nns/client.go b/rpcclient/nns/client.go index adfc41e..43c0d0a 100644 --- a/rpcclient/nns/client.go +++ b/rpcclient/nns/client.go @@ -286,28 +286,6 @@ func (c *Contract) RegisterUnsigned(name string, owner util.Uint160, email strin return c.actor.MakeUnsignedRun(script, nil) } -// Renew creates a transaction invoking `renew` method of the contract. -// This transaction is signed and immediately sent to the network. -// The values returned are its hash, ValidUntilBlock value and error if any. -func (c *Contract) Renew(name string) (util.Uint256, uint32, error) { - return c.actor.SendCall(c.hash, "renew", name) -} - -// RenewTransaction creates a transaction invoking `renew` method of the contract. -// This transaction is signed, but not sent to the network, instead it's -// returned to the caller. -func (c *Contract) RenewTransaction(name string) (*transaction.Transaction, error) { - return c.actor.MakeCall(c.hash, "renew", name) -} - -// RenewUnsigned creates a transaction invoking `renew` method of the contract. -// This transaction is not signed, it's simply returned to the caller. -// Any fields of it that do not affect fees can be changed (ValidUntilBlock, -// Nonce), fee values (NetworkFee, SystemFee) can be increased as well. -func (c *Contract) RenewUnsigned(name string) (*transaction.Transaction, error) { - return c.actor.MakeUnsignedCall(c.hash, "renew", nil, name) -} - // SetAdmin creates a transaction invoking `setAdmin` method of the contract. // This transaction is signed and immediately sent to the network. // The values returned are its hash, ValidUntilBlock value and error if any. diff --git a/tests/nns_test.go b/tests/nns_test.go index 66db77a..4661a9f 100644 --- a/tests/nns_test.go +++ b/tests/nns_test.go @@ -4,7 +4,6 @@ import ( "fmt" "math/big" "path" - "strings" "testing" "time" @@ -551,45 +550,6 @@ func TestNNSGetAllRecords(t *testing.T) { require.False(t, iter.Next()) } -func TestExpiration(t *testing.T) { - c := newNNSInvoker(t, true) - - refresh, retry, expire, ttl := int64(101), int64(102), int64(msPerYear/1000*10), int64(104) - c.Invoke(t, true, "register", - "testdomain.com", c.CommitteeHash, - "myemail@frostfs.info", refresh, retry, expire, ttl) - - checkProperties := func(t *testing.T, expiration uint64) { - expected := stackitem.NewMapWithValue([]stackitem.MapElement{ - {Key: stackitem.Make("name"), Value: stackitem.Make("testdomain.com")}, - {Key: stackitem.Make("expiration"), Value: stackitem.Make(expiration)}, - }) - s, err := c.TestInvoke(t, "properties", "testdomain.com") - require.NoError(t, err) - require.Equal(t, expected.Value(), s.Top().Item().Value()) - } - - top := c.TopBlock(t) - expiration := top.Timestamp + uint64(expire*1000) - checkProperties(t, expiration) - - b := c.NewUnsignedBlock(t) - b.Timestamp = expiration - 2 // test invoke is done with +1 timestamp - require.NoError(t, c.Chain.AddBlock(c.SignBlock(b))) - checkProperties(t, expiration) - - b = c.NewUnsignedBlock(t) - b.Timestamp = expiration - 1 - require.NoError(t, c.Chain.AddBlock(c.SignBlock(b))) - - _, err := c.TestInvoke(t, "properties", "testdomain.com") - require.Error(t, err) - require.True(t, strings.Contains(err.Error(), "name has expired")) - - c.InvokeFail(t, "name has expired", "getAllRecords", "testdomain.com") - c.InvokeFail(t, "name has expired", "ownerOf", "testdomain.com") -} - func TestNNSSetAdmin(t *testing.T) { c := newNNSInvoker(t, true) @@ -691,31 +651,6 @@ func TestNNSIsAvailable(t *testing.T) { c.InvokeFail(t, "domain name too long", "isAvailable", getTooLongDomainName(255)) } -func TestNNSRenew(t *testing.T) { - c := newNNSInvoker(t, true) - - acc := c.NewAccount(t) - c1 := c.WithSigners(c.Committee, acc) - refresh, retry, expire, ttl := int64(101), int64(102), int64(103), int64(104) - c1.Invoke(t, true, "register", - "testdomain.com", c.CommitteeHash, - "myemail@frostfs.info", refresh, retry, expire, ttl) - - const msPerYear = 365 * 24 * time.Hour / time.Millisecond - b := c.TopBlock(t) - ts := b.Timestamp + uint64(expire*1000) + uint64(msPerYear) - - cAcc := c.WithSigners(acc) - cAcc.InvokeFail(t, "not witnessed by admin", "renew", "testdomain.com") - c1.Invoke(t, ts, "renew", "testdomain.com") - expected := stackitem.NewMapWithValue([]stackitem.MapElement{ - {Key: stackitem.Make("name"), Value: stackitem.Make("testdomain.com")}, - {Key: stackitem.Make("expiration"), Value: stackitem.Make(ts)}, - }) - cAcc.Invoke(t, expected, "properties", "testdomain.com") - c.InvokeFail(t, "domain name too long", "renew", getTooLongDomainName(255)) -} - func TestNNSResolve(t *testing.T) { c := newNNSInvoker(t, true)