store: one link per key and resolver digests

This commit is contained in:
shum committed 2026-10-21 22:07:25 +00:00
1 parent dc79568e22
commit 27a99dc19a
2 files changed
+36 -12

No files matched your search

@@ -5,20 +5,24 @@ module StoreService.Names.Registration
( Registration (..),
RegisterIntent (..),
sponsorDomain,
resolverDomain,
makeCommitment,
commitCalldata,
registerWithCreditCalldata,
registerIntentDigest,
verifyRegisterIntent,
setTextDigest,
clearRecordsDigest,
)
where
import Control.Monad (unless, when)
import Control.Monad.Except (ExceptT (..), runExceptT, throwError)
import Crypto.Number.Serialize (os2ip)
import Data.ByteString (ByteString)
import qualified Data.ByteString as B
import Data.Maybe (catMaybes)
import Data.Text (Text)
import qualified Data.Text as T
import Data.Text.Encoding (encodeUtf8)
import Data.Word (Word64)
import Simplex.Messaging.Crypto (keccak256)
@@ -36,8 +40,8 @@ data Registration = Registration
rDuration :: Word64,
rSecret :: ByteString,
rResolver :: Address,
rContactLinks :: [Text],
rChannelLinks :: [Text]
rContactLink :: Maybe Text,
rChannelLink :: Maybe Text
}
data RegisterIntent = RegisterIntent
@@ -50,6 +54,9 @@ data RegisterIntent = RegisterIntent
sponsorDomain :: Word64 -> Address -> Eip712Domain
sponsorDomain edChainId edVerifyingContract = Eip712Domain {edName = "SimplexSponsor", edVersion = "1", edChainId, edVerifyingContract}
resolverDomain :: Word64 -> Address -> Eip712Domain
resolverDomain edChainId edVerifyingContract = Eip712Domain {edName = "SimplexResolver", edVersion = "1", edChainId, edVerifyingContract}
makeCommitment :: Registration -> ByteString
makeCommitment r = keccak256 $ abiTuple [Dynamic $ registrationTuple r]
@@ -87,6 +94,23 @@ verifyRegisterIntent domain now RegisterIntent {riRegistration = r@Registration
signer <- ExceptT $ recoverAddress riSignature $ registerIntentDigest domain r riNonce riDeadline
unless (signer == rOwner) $ throwError "intent is not signed by the owner"
setTextDigest :: Eip712Domain -> ByteString -> Text -> Text -> Word64 -> Word64 -> ByteString
setTextDigest domain node key value nonce deadline =
hashTypedData
domain
"SetText(bytes32 node,string key,string value,uint256 nonce,uint256 deadline)"
[bytes32 node, VBytes $ encodeUtf8 key, VBytes $ encodeUtf8 value, VUint $ fromIntegral nonce, VUint $ fromIntegral deadline]
clearRecordsDigest :: Eip712Domain -> ByteString -> Word64 -> Word64 -> ByteString
clearRecordsDigest domain node nonce deadline =
hashTypedData
domain
"ClearRecords(bytes32 node,uint256 nonce,uint256 deadline)"
[bytes32 node, VUint $ fromIntegral nonce, VUint $ fromIntegral deadline]
bytes32 :: ByteString -> Eip712Value
bytes32 = VUint . fromInteger . os2ip
registrationTuple :: Registration -> ByteString
registrationTuple r@Registration {rLabel, rOwner, rDuration, rSecret, rResolver} =
abiTuple
@@ -104,12 +128,12 @@ registrationTuple r@Registration {rLabel, rOwner, rDuration, rSecret, rResolver}
referrer = B.replicate 32 0
recordCalls :: Registration -> [ByteString]
recordCalls Registration {rLabel, rTLD, rContactLinks, rChannelLinks} =
[setText key ls | (key, ls) <- [("simplex.contact", rContactLinks), ("simplex.channel", rChannelLinks)], not (null ls)]
recordCalls Registration {rLabel, rTLD, rContactLink, rChannelLink} =
catMaybes [setText "simplex.contact" <$> rContactLink, setText "simplex.channel" <$> rChannelLink]
where
setText key ls =
setText key link =
selector "setText(bytes32,string,string)"
<> abiTuple [Static node, Dynamic $ abiBytes key, Dynamic $ abiBytes $ encodeUtf8 $ T.intercalate ";" ls]
<> abiTuple [Static node, Dynamic $ abiBytes key, Dynamic $ abiBytes $ encodeUtf8 link]
node = namehash rTLD rLabel
namehash :: SimplexTLD -> Text -> ByteString
@@ -43,17 +43,17 @@ testRegisterCalldataWithRecords :: TVar ChaChaDRG -> IO ()
testRegisterCalldataWithRecords g = do
intent <- knownIntent g knownRegistration
toHex (registerWithCreditCalldata intent)
`shouldBe` "c4bd2ab50000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f4865700000000000000000000000000000000000000000000000000000000000000048000000000000000000000000000000000000000000000000000000000000001000000000000000000000000009858effd232b4033e47d90003d41ec34ecaeda940000000000000000000000000000000000000000000000000000000003c2670011111111111111111111111111111111111111111111111111111111111111110000000000000000000000002279b7a0a67db372996a5fab50d91eaa73d2ebe6000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000762616b657279310000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000000e410f13a8c58c186cadf476923d25ea4950487d1aaf21906ba5574c87f5b9435b61b994370000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000000f73696d706c65782e636f6e746163740000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002068747470733a2f2f736d702e73696d706c65782e696d2f6123636f6e7461637400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010410f13a8c58c186cadf476923d25ea4950487d1aaf21906ba5574c87f5b9435b61b994370000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000000f73696d706c65782e6368616e6e656c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003b68747470733a2f2f736d70312e73696d706c65782e696d2f63236f6e653b68747470733a2f2f736d70322e73696d706c65782e696d2f632374776f00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000417caacde8c40eab73721947d6d811746266da03d0cb50da2e7efea9c7c926b7124cc612132c7c5e178fcf75afcc709994ca96b16ef30d9763ab22102192e9ac441b00000000000000000000000000000000000000000000000000000000000000"
`shouldBe` "c4bd2ab50000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f4865700000000000000000000000000000000000000000000000000000000000000046000000000000000000000000000000000000000000000000000000000000001000000000000000000000000009858effd232b4033e47d90003d41ec34ecaeda940000000000000000000000000000000000000000000000000000000003c2670011111111111111111111111111111111111111111111111111111111111111110000000000000000000000002279b7a0a67db372996a5fab50d91eaa73d2ebe6000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000762616b657279310000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000000e410f13a8c58c186cadf476923d25ea4950487d1aaf21906ba5574c87f5b9435b61b994370000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000000f73696d706c65782e636f6e746163740000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002068747470733a2f2f736d702e73696d706c65782e696d2f6123636f6e746163740000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e410f13a8c58c186cadf476923d25ea4950487d1aaf21906ba5574c87f5b9435b61b994370000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000000f73696d706c65782e6368616e6e656c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001d68747470733a2f2f736d70312e73696d706c65782e696d2f63236f6e65000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000041f310b273d0e0ab0975a66d383fe818a5ec3474fcd922dbf3fe70094a3c0ceae86559b13ea0728a330613c6fe236a89a026daf345dcc8c0616e9eda2c69cbeb091b00000000000000000000000000000000000000000000000000000000000000"
testRegisterCalldataWithoutRecords :: TVar ChaChaDRG -> IO ()
testRegisterCalldataWithoutRecords g = do
intent <- knownIntent g knownRegistration {rContactLinks = [], rChannelLinks = []}
intent <- knownIntent g knownRegistration {rContactLink = Nothing, rChannelLink = Nothing}
toHex (registerWithCreditCalldata intent)
`shouldBe` "c4bd2ab50000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f486570000000000000000000000000000000000000000000000000000000000000001e000000000000000000000000000000000000000000000000000000000000001000000000000000000000000009858effd232b4033e47d90003d41ec34ecaeda940000000000000000000000000000000000000000000000000000000003c2670011111111111111111111111111111111111111111111111111111111111111110000000000000000000000002279b7a0a67db372996a5fab50d91eaa73d2ebe6000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000762616b6572793100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000411d0b3a477c99fbcadada2937b71127bf6da202f5cd25856649829653d8cf6a8c0ce0afb8505e398e23b3b01fcb3b17ffcf82d8ba6d24e9b854506894b2864ecf1c00000000000000000000000000000000000000000000000000000000000000"
testCommitCalldata :: IO ()
testCommitCalldata =
toHex (commitCalldata $ makeCommitment knownRegistration) `shouldBe` "f14fcbc843aeb4617085160f4dc7ad495d1119f39bca441276b1990123fd3ecb8a40a360"
toHex (commitCalldata $ makeCommitment knownRegistration) `shouldBe` "f14fcbc8810f0645b8d9839e3744bb956f9da4fa12bb51ec97459e08739c576a36cba0df"
testVerifyOtherSigner :: TVar ChaChaDRG -> IO ()
testVerifyOtherSigner g = do
@@ -102,8 +102,8 @@ knownRegistration =
rDuration = 63072000,
rSecret = B.replicate 32 0x11,
rResolver = address "0x2279b7a0a67db372996a5fab50d91eaa73d2ebe6",
rContactLinks = ["https://smp.simplex.im/a#contact"],
rChannelLinks = ["https://smp1.simplex.im/c#one", "https://smp2.simplex.im/c#two"]
rContactLink = Just "https://smp.simplex.im/a#contact",
rChannelLink = Just "https://smp1.simplex.im/c#one"
}
knownIntent :: TVar ChaChaDRG -> Registration -> IO RegisterIntent