From c783b1341fc19f2ff8d819fa158f299990e91f07 Mon Sep 17 00:00:00 2001 From: shum Date: Wed, 21 Oct 2026 23:33:47 +0000 Subject: [PATCH] store: type the names store's transaction hashes --- .../src/StoreService/Names/Store.hs | 37 +++++++++++-------- tests/Bots/StoreService/NamesStoreTests.hs | 23 ++++++------ 2 files changed, 34 insertions(+), 26 deletions(-) diff --git a/apps/simplex-store-service/src/StoreService/Names/Store.hs b/apps/simplex-store-service/src/StoreService/Names/Store.hs index 479fab42a7..6d8799bb05 100644 --- a/apps/simplex-store-service/src/StoreService/Names/Store.hs +++ b/apps/simplex-store-service/src/StoreService/Names/Store.hs @@ -92,6 +92,7 @@ import Simplex.Messaging.Eth.EIP712 (serializeSignature) import Simplex.Messaging.SimplexName (LabelHash (..)) import Simplex.Messaging.Util (maybeFirstRow, tshow) import StoreService.Names.Abi (hex) +import StoreService.Names.Chain (TxHash (..)) import StoreService.Names.Phases (RegistrationId (..)) import StoreService.Names.Signatures (OrderFields (..), parseSignature) import StoreService.Store (RevokeResult (..)) @@ -165,9 +166,9 @@ data NameRegistration = NameRegistration nrPrice :: Int, nrPayment :: RegistrationPayment, nrReveal :: Maybe NameReveal, - nrCommitTx :: Maybe ByteString, + nrCommitTx :: Maybe TxHash, nrCommitBlock :: Maybe Word64, - nrRegisterTx :: Maybe ByteString, + nrRegisterTx :: Maybe TxHash, nrRegisterBlock :: Maybe Word64, nrRevealAfter :: Maybe Word64, nrRevealBefore :: Maybe Word64, @@ -266,7 +267,7 @@ data NameTransaction = NameTransaction { ntId :: Int64, ntFor :: TxFor, ntRaw :: ByteString, - ntHash :: ByteString, + ntHash :: TxHash, ntNonce :: Word64, ntSentAt :: UTCTime, ntMinedBlock :: Maybe Word64, @@ -276,7 +277,7 @@ data NameTransaction = NameTransaction data NewTransaction = NewTransaction { ntxRaw :: ByteString, - ntxHash :: ByteString, + ntxHash :: TxHash, ntxNonce :: Word64 } @@ -284,7 +285,7 @@ data NewTransaction = NewTransaction data RecordChange = RCSetText Text Text | RCClear deriving (Eq, Show) -data EditState = ESPending | ESMined (Maybe ByteString) | ESReverted (Maybe Text) +data EditState = ESPending | ESMined (Maybe TxHash) | ESReverted (Maybe Text) deriving (Eq, Show) data RecordEdit = RecordEdit @@ -447,9 +448,9 @@ toRegistration nrPrice, nrPayment, nrReveal, - nrCommitTx = fromBinary <$> commitTx, + nrCommitTx = txHash <$> commitTx, nrCommitBlock = word64 <$> commitBlock, - nrRegisterTx = fromBinary <$> registerTx, + nrRegisterTx = txHash <$> registerTx, nrRegisterBlock = word64 <$> registerBlock, nrRevealAfter = word64 <$> revealAfter, nrRevealBefore = word64 <$> revealBefore, @@ -549,7 +550,7 @@ updateRegistration db r now = do |] ( (Binary lh, nrLength, int64 nrDuration, Binary nrCommitment, nrSealed, nrPhase, nrPrice) :. (rvLabel <$> nrReveal, Binary . rvSecret <$> nrReveal, rvContactLink =<< nrReveal, rvChannelLink =<< nrReveal, int64 . rvNonce <$> nrReveal, int64 . rvDeadline <$> nrReveal, Binary . serializeSignature . rvSignature <$> nrReveal) - :. (Binary <$> nrCommitTx, int64 <$> nrCommitBlock, Binary <$> nrRegisterTx, int64 <$> nrRegisterBlock, int64 <$> nrRevealAfter, int64 <$> nrRevealBefore, int64 <$> nrExpiresAt) + :. (txHashField <$> nrCommitTx, int64 <$> nrCommitBlock, txHashField <$> nrRegisterTx, int64 <$> nrRegisterBlock, int64 <$> nrRevealAfter, int64 <$> nrRevealBefore, int64 <$> nrExpiresAt) :. (nrIssuedCodeId, truncateToSecond <$> nrRegisteredAt, truncateToSecond <$> nrFailedAt, nrError, BI live, nrMoves, truncateToSecond <$> nrLinksRefusedAt, truncateToSecond now) :. (rid, nrVersion, BI live, rid, Binary nrCommitment, Binary $ unAddress nrOwner, Binary lh) ) @@ -764,17 +765,17 @@ insertTransaction db for NewTransaction {ntxRaw, ntxHash, ntxNonce} now = do (registration_id, name_record_edit_id, kind, raw, tx_hash, registrar_nonce, sent_at, status) VALUES (?,?,?,?,?,?,?,?) |] - (rid, editId, kind, Binary ntxRaw, Binary ntxHash, int64 ntxNonce, truncateToSecond now, TSPending) + (rid, editId, kind, Binary ntxRaw, txHashField ntxHash, int64 ntxNonce, truncateToSecond now, TSPending) insertedRowId db -- | Moves a transaction on from the status the caller read, so an outcome is never overwritten unseen; False when it is not in that status. -recordTransactionOutcome :: DB.Connection -> ByteString -> TxStatus -> TxStatus -> Maybe Word64 -> IO Bool +recordTransactionOutcome :: DB.Connection -> TxHash -> TxStatus -> TxStatus -> Maybe Word64 -> IO Bool recordTransactionOutcome db hash from status block = (> 0) <$> executeChanging db "UPDATE sx_badge_service_name_transactions SET status = ?, mined_block = ? WHERE tx_hash = ? AND status = ?" - (status, int64 <$> block, Binary hash, from) + (status, int64 <$> block, txHashField hash, from) transactionColumns :: Query transactionColumns = @@ -786,13 +787,13 @@ transactionColumns = type TransactionRow = (Int64, Text, Maybe Text, Maybe Int64, Binary ByteString, Binary ByteString, Int64, UTCTime, Maybe Int64, TxStatus) toTransaction :: TransactionRow -> Either Text NameTransaction -toTransaction (ntId, kind, rid_, editId_, Binary ntRaw, Binary ntHash, nonce, ntSentAt, block, ntStatus) = do +toTransaction (ntId, kind, rid_, editId_, Binary ntRaw, hash, nonce, ntSentAt, block, ntStatus) = do ntFor <- case (kind, rid_, editId_) of ("commit", Just rid, Nothing) -> Right $ TxCommit $ RegistrationId rid ("register", Just rid, Nothing) -> Right $ TxRegister $ RegistrationId rid ("edit", Nothing, Just editId) -> Right $ TxEdit editId _ -> Left $ "name_transactions.kind: " <> kind - pure NameTransaction {ntId, ntFor, ntRaw, ntHash, ntNonce = word64 nonce, ntSentAt, ntMinedBlock = word64 <$> block, ntStatus} + pure NameTransaction {ntId, ntFor, ntRaw, ntHash = txHash hash, ntNonce = word64 nonce, ntSentAt, ntMinedBlock = word64 <$> block, ntStatus} -- | Those without a receipt, in nonce order, for the sender to resume. pendingTransactions :: DB.Connection -> IO [NameTransaction] @@ -863,7 +864,7 @@ toRecordEdit ((reId, Binary lh, Binary owner, nonce, key_, value_, deadline, Bin where decodeState | state == pendingEdit = Right ESPending - | state == minedEdit = Right $ ESMined $ fromBinary <$> minedTx + | state == minedEdit = Right $ ESMined $ txHash <$> minedTx | state == revertedEdit = Right $ ESReverted revert | otherwise = Left $ "name_record_edits.state: " <> state @@ -890,7 +891,7 @@ settleRecordEdit db editId state = <$> executeChanging db "UPDATE sx_badge_service_name_record_edits SET state = ?, revert = ?, mined_tx = ? WHERE name_record_edit_id = ? AND state = ?" - (stateText, revert, Binary <$> minedTx, editId, pendingEdit) + (stateText, revert, txHashField <$> minedTx, editId, pendingEdit) where (stateText, revert, minedTx) = case state of ESPending -> (pendingEdit, Nothing, Nothing) @@ -909,6 +910,12 @@ relayedEditTimes db (LabelHash lh) since = int64 :: Word64 -> Int64 int64 = fromIntegral +txHash :: Binary ByteString -> TxHash +txHash (Binary h) = TxHash h + +txHashField :: TxHash -> Binary ByteString +txHashField (TxHash h) = Binary h + word64 :: Int64 -> Word64 word64 = fromIntegral diff --git a/tests/Bots/StoreService/NamesStoreTests.hs b/tests/Bots/StoreService/NamesStoreTests.hs index 8105d316a7..2e87fd5768 100644 --- a/tests/Bots/StoreService/NamesStoreTests.hs +++ b/tests/Bots/StoreService/NamesStoreTests.hs @@ -23,6 +23,7 @@ import Simplex.Messaging.Agent.Store.Shared (Migration (..), MigrationsToRun (.. import Simplex.Messaging.Crypto.Secp256k1 (RecoverableSignature) import Simplex.Messaging.Eth.Address (Address) import Simplex.Messaging.SimplexName (labelHash) +import StoreService.Names.Chain (TxHash (..)) import StoreService.Names.Phases (RegistrationId (..)) import StoreService.Names.Signatures (OrderFields (..), parseAnyCaseAddress, parseSignature) import StoreService.Names.Store @@ -372,7 +373,7 @@ testVersionBumps = withServiceStore $ \st -> do code <- issue st 1 usable placeCode st "r1" ownerA (order "alicebakery" 1) code `shouldReturn` Right () r1 <- reg st "r1" - write st r1 {nrPhase = PCommitting, nrCommitTx = Just (digestFixture 8)} `shouldReturn` Written 2 + write st r1 {nrPhase = PCommitting, nrCommitTx = Just (TxHash $ digestFixture 8)} `shouldReturn` Written 2 r2 <- reg st "r1" write st r2 {nrPhase = PCommitted, nrRevealAfter = Just 1792828800, nrRevealBefore = Just 1792915140} `shouldReturn` Written 3 r3 <- reg st "r1" @@ -392,9 +393,9 @@ testRoundTrip = withServiceStore $ \st -> do r { nrPhase = PRegistered, nrReveal = Just reveal {rvChannelLink = Just "simplex:/c#xyz"}, - nrCommitTx = Just (digestFixture 8), + nrCommitTx = Just (TxHash $ digestFixture 8), nrCommitBlock = Just 100, - nrRegisterTx = Just (digestFixture 9), + nrRegisterTx = Just (TxHash $ digestFixture 9), nrRegisterBlock = Just 120, nrRevealAfter = Just 1792828800, nrRevealBefore = Just 1792915140, @@ -497,9 +498,9 @@ testRetarget = withServiceStore $ \st -> do r { nrPhase = PTaken, nrReveal = Just reveal, - nrCommitTx = Just (digestFixture 8), + nrCommitTx = Just (TxHash $ digestFixture 8), nrCommitBlock = Just 100, - nrRegisterTx = Just (digestFixture 9), + nrRegisterTx = Just (TxHash $ digestFixture 9), nrRegisterBlock = Just 120, nrRevealAfter = Just 1, nrRevealBefore = Just 2, @@ -710,14 +711,14 @@ testTransactions = withServiceStore $ \st -> do Just editId <- withTransaction st $ \db -> insertRecordEdit db (newEdit ownerA 20 setChannel) t0 let r1 = RegistrationId "r1" tx :: Word8 -> NewTransaction - tx n = NewTransaction {ntxRaw = digestFixture (n + 100), ntxHash = digestFixture n, ntxNonce = fromIntegral n} + tx n = NewTransaction {ntxRaw = digestFixture (n + 100), ntxHash = TxHash $ digestFixture n, ntxNonce = fromIntegral n} [commitId, _, registerId] <- withTransaction st $ \db -> sequence [insertTransaction db (TxCommit r1) (tx 2) (at 1), insertTransaction db (TxEdit editId) (tx 1) (at 2), insertTransaction db (TxRegister r1) (tx 3) (at 3)] unsettled <- withTransaction st pendingTransactions map (\NameTransaction {ntFor, ntNonce, ntStatus} -> (ntFor, ntNonce, ntStatus)) unsettled `shouldBe` [(TxEdit editId, 1, TSPending), (TxCommit r1, 2, TSPending), (TxRegister r1, 3, TSPending)] map ntRaw unsettled `shouldBe` map (\n -> digestFixture (n + 100)) [1, 2, 3] - let outcome n from status block = withTransaction st $ \db -> recordTransactionOutcome db (digestFixture n) from status block + let outcome n from status block = withTransaction st $ \db -> recordTransactionOutcome db (TxHash $ digestFixture n) from status block outcome 2 TSPending TSMined (Just 77) `shouldReturn` True outcome 1 TSPending TSReverted (Just 78) `shouldReturn` True outcome 50 TSPending TSMined (Just 79) `shouldReturn` False @@ -732,9 +733,9 @@ testTransactionFromStatus :: IO () testTransactionFromStatus = withServiceStore $ \st -> do code <- issue st 1 usable placeCode st "r1" ownerA (order "alicebakery" 1) code `shouldReturn` Right () - let outcome from status block = withTransaction st $ \db -> recordTransactionOutcome db (digestFixture 2) from status block + let outcome from status block = withTransaction st $ \db -> recordTransactionOutcome db (TxHash $ digestFixture 2) from status block current = withTransaction st $ \db -> map (\NameTransaction {ntStatus, ntMinedBlock} -> (ntStatus, ntMinedBlock)) <$> registrationTransactions db (RegistrationId "r1") - void $ withTransaction st $ \db -> insertTransaction db (TxCommit $ RegistrationId "r1") NewTransaction {ntxRaw = "raw", ntxHash = digestFixture 2, ntxNonce = 0} t0 + void $ withTransaction st $ \db -> insertTransaction db (TxCommit $ RegistrationId "r1") NewTransaction {ntxRaw = "raw", ntxHash = TxHash $ digestFixture 2, ntxNonce = 0} t0 outcome TSPending TSMined (Just 77) `shouldReturn` True outcome TSPending TSDropped Nothing `shouldReturn` False current `shouldReturn` [(TSMined, Just 77)] @@ -758,7 +759,7 @@ testEditNonceUnique = withServiceStore $ \st -> do testSettleEdit :: IO () testSettleEdit = withServiceStore $ \st -> do Just editId <- withTransaction st $ \db -> insertRecordEdit db (newEdit ownerA 1 setChannel) t0 - withTransaction st (\db -> settleRecordEdit db editId (ESMined (Just $ digestFixture 9))) `shouldReturn` True + withTransaction st (\db -> settleRecordEdit db editId (ESMined (Just $ TxHash $ digestFixture 9))) `shouldReturn` True withTransaction st (\db -> settleRecordEdit db editId (ESReverted Nothing)) `shouldReturn` False edit <- withTransaction st $ \db -> getRecordEdit db editId edit @@ -772,7 +773,7 @@ testSettleEdit = withServiceStore $ \st -> do reDeadline = 1792832400, reSignature = signature, reBodyHash = digestFixture 1, - reState = ESMined (Just $ digestFixture 9), + reState = ESMined (Just $ TxHash $ digestFixture 9), reCreatedAt = t0 }