diff --git a/scripts/resolver/service/snrc-resolve.py b/scripts/resolver/service/snrc-resolve.py index 4d33d3d73..0abc54ad7 100755 --- a/scripts/resolver/service/snrc-resolve.py +++ b/scripts/resolver/service/snrc-resolve.py @@ -893,8 +893,9 @@ def owned_by(address: str, offset: int = 0): Enumeration is read off the ERC-721 registrar, so a name acquired by transfer counts, and a lapsed one stays listed until re-registered - it is reported with its `status`, not filtered. `inUse` is what a recovery scan - asks; holding a name is only one way to be in use, so the nonce and balance - it is derived from are reported too. + asks, derived from this chain's nonce and balance and the names above: an + account holding only other tokens is not seen, and neither is one used on + another chain. """ if not is_address(address): return 400, { @@ -919,7 +920,7 @@ def owned_by(address: str, offset: int = 0): "configuredTlds": [], } - now = int(time.time()) + now = chain_now() names, truncated = [], False for tld, registrar in configured.items(): grace = grace_period(registrar) diff --git a/scripts/resolver/service/test_snrc_resolve.py b/scripts/resolver/service/test_snrc_resolve.py index 52912d682..3d036b84b 100644 --- a/scripts/resolver/service/test_snrc_resolve.py +++ b/scripts/resolver/service/test_snrc_resolve.py @@ -1048,12 +1048,13 @@ class OwnedByTests(unittest.TestCase): ALICE = 0x9C0257114EB9399A2985F8E75DAD7600C5D89FE3824FFA99EC1C3EB8BF3B0501 def setUp(self): - self._saved = (snrc.REGISTRARS, snrc.eth_call, snrc.rpc) + self._saved = (snrc.REGISTRARS, snrc.eth_call, snrc.rpc, snrc.chain_now) snrc.REGISTRARS = {"testing": self.REGISTRAR, "simplex": ""} snrc.rpc = lambda method, params: "0x0" + snrc.chain_now = lambda: int(time.time()) def tearDown(self): - snrc.REGISTRARS, snrc.eth_call, snrc.rpc = self._saved + snrc.REGISTRARS, snrc.eth_call, snrc.rpc, snrc.chain_now = self._saved def _chain(self, held, expires, label=b"alice"): def call(to, data): @@ -1125,6 +1126,15 @@ class OwnedByTests(unittest.TestCase): self.assertEqual(status, 400) self.assertEqual(body["error"], "badAddress") + def test_status_follows_the_block_clock_not_the_host(self): + """A name the host clock still calls registered is in grace once the + chain has passed its expiry.""" + expires = int(time.time()) + 86400 + snrc.eth_call = self._chain(1, expires) + snrc.chain_now = lambda: expires + 1 + _, body = snrc.owned_by(self.ADDR) + self.assertEqual(body["names"][0]["status"], "grace") + def test_a_negative_offset_is_refused(self): snrc.eth_call = self._chain(1, int(time.time()) + 86400) status, body = snrc.owned_by(self.ADDR, -1) diff --git a/src/Simplex/Messaging/Names/Record.hs b/src/Simplex/Messaging/Names/Record.hs index 5f8feecd8..51c20e28b 100644 --- a/src/Simplex/Messaging/Names/Record.hs +++ b/src/Simplex/Messaging/Names/Record.hs @@ -92,10 +92,11 @@ data NameRegistration NRReserved {reservedReason :: NameReservedReason} deriving (Eq, Show) --- | What the registry holds for an address: the names it owns, and whether --- the account has been used at all. Holding a name is only one way to be in --- use, so a recovery scan that reads only `ownNames` hands out an account its --- owner is already using. +-- | What the registry holds for an address: the names it owns, and whether the +-- account is in use, which holding a name is only one way to be. `ownInUse` is +-- what the resolver could see on its own chain - the nonce, the balance and the +-- names - so an account used only for other tokens, or on another chain, reads +-- as unused. data OwnedNames = OwnedNames { ownNames :: [OwnedName], ownInUse :: Bool,