Skip to content
This repository was archived by the owner on Nov 24, 2025. It is now read-only.

Commit 965ae4b

Browse files
committed
check defpacts for completion in preinsert check
Change-Id: Id00000006fd84f56c27dcd113bb387c19f70ff18
1 parent 4f5ef1e commit 965ae4b

File tree

2 files changed

+23
-7
lines changed

2 files changed

+23
-7
lines changed

src/Chainweb/Pact/Mempool/Mempool.hs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -244,6 +244,7 @@ data InsertError
244244
| InsertErrorTimedOut
245245
| InsertErrorPactParseError Text
246246
| InsertErrorWrongChain Text Text
247+
| InsertErrorDefPactComplete Text
247248
deriving (Generic, Eq, NFData)
248249

249250
instance Show InsertError where
@@ -270,6 +271,8 @@ instance Show InsertError where
270271
, "It should be rounded to at most 12 decimal places."
271272
]
272273
InsertErrorTooManySigs -> "Too many signatures"
274+
InsertErrorDefPactComplete i ->
275+
"This transaction is attempting to complete an already-completed defpact ID: " <> T.unpack i
273276

274277
instance Exception InsertError
275278

src/Chainweb/Pact/PactService.hs

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -106,17 +106,21 @@ import Network.HTTP.Client qualified as HTTP
106106
import P2P.TaskQueue (Priority(..))
107107
import Pact.Core.ChainData qualified as Pact
108108
import Pact.Core.Command.Types qualified as Pact
109+
import Pact.Core.Command.RPC qualified as Pact
109110
import Pact.Core.Errors qualified as Pact
110111
import Pact.Core.Evaluate qualified as Pact
111112
import Pact.Core.Gas qualified as Pact
112113
import Pact.Core.Hash qualified as Pact
114+
import Pact.Core.Names qualified as Pact
113115
import Pact.Core.StableEncoding qualified as Pact
114116
import Pact.JSON.Encode qualified as J
115117
import Prelude hiding (lookup)
116118
import System.LogLevel
117119
import Chainweb.Version.Guards (pact5)
118120
import Control.Concurrent.MVar (newMVar)
119121
import Chainweb.Pact.Payload.RestAPI.Client (payloadClient)
122+
import qualified Pact.Core.Persistence as Pact
123+
import qualified Pact.Core.Info as Pact
120124

121125
withPactService
122126
:: (Logger logger, CanPayloadCas tbl)
@@ -790,13 +794,22 @@ execPreInsertCheckReq logger serviceEnv txs = do
790794
fakeParentCreationTime <- Checkpointer.mkFakeParentCreationTime
791795
let act sql = Checkpointer.readFromLatest logger cid sql fakeParentCreationTime $ Checkpointer.PactRead
792796
{ pact5Read = \blockEnv bh -> do
793-
forM txs $ \tx ->
794-
fmap (either Just (\_ -> Nothing)) $ runExceptT $ do
795-
-- it's safe to use initialBlockHandle here because it's
796-
-- only used to check for duplicate pending txs in a block
797-
() <- mapExceptT liftIO
798-
$ Pact.validateParsedChainwebTx logger blockEnv tx
799-
evalStateT (attemptBuyGas blockEnv tx) bh
797+
liftIO $ flip evalStateT bh $ doChainwebPactDbTransaction (blockEnv ^. psBlockDbEnv) Nothing $ \pdb _ -> do
798+
forM txs $ \tx ->
799+
fmap (either Just (\_ -> Nothing)) $ runExceptT $ do
800+
-- it's safe to use initialBlockHandle here because it's
801+
-- only used to check for duplicate pending txs in a block
802+
() <- mapExceptT liftIO
803+
$ Pact.validateParsedChainwebTx logger blockEnv tx
804+
evalStateT (attemptBuyGas blockEnv tx) bh
805+
case tx ^? Pact.cmdPayload . Pact.payloadObj . Pact.pPayload . Pact._Continuation of
806+
Just contMsg -> do
807+
let pactId = Pact._cmPactId contMsg
808+
defPactState <- liftIO $ Pact.ignoreGas (Pact.LineInfo 0) $ Pact._pdbRead pdb Pact.DDefPacts pactId
809+
let isComplete = defPactState == Just Nothing
810+
when isComplete $
811+
throwError (InsertErrorDefPactComplete (sshow pactId))
812+
Nothing -> return ()
800813
-- pessimistically, if we're catching up and not even past the Pact
801814
-- 5 activation, just badlist everything as in-the-future.
802815
, pact4Read = \_ -> return $ Just InsertErrorTimeInFuture <$ txs

0 commit comments

Comments
 (0)