Skip to content

Commit 0474636

Browse files
committed
wip: waitTxStatusChange rework
- added chain-index polling interval and timeout - todo: config and tests
1 parent 4ad6321 commit 0474636

File tree

5 files changed

+103
-46
lines changed

5 files changed

+103
-46
lines changed

src/BotPlutusInterface/Config.hs

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import BotPlutusInterface.Effects (
1414
ShellArgs (..),
1515
callLocalCommand,
1616
)
17-
import BotPlutusInterface.Types (CLILocation (..), LogLevel (..), PABConfig (..))
17+
import BotPlutusInterface.Types (CLILocation (..), LogLevel (..), PABConfig (..), TxStatusPolling)
1818

1919
import Cardano.Api (NetworkId (Mainnet, Testnet), unNetworkMagic)
2020
import Config (Section (Section), Value (Atom, Sections, Text))
@@ -74,6 +74,13 @@ logLevelSpec =
7474
<!> Info <$ atomSpec "info"
7575
<!> Debug <$ atomSpec "debug"
7676

77+
instance ToValue TxStatusPolling where
78+
toValue = error "TODO: toValue TxStatusPolling"
79+
80+
txStatusPollingSpec :: ValueSpec TxStatusPolling
81+
txStatusPollingSpec = error "TODO: txStatusPollingSpec"
82+
83+
7784
{- ORMOLU_DISABLE -}
7885
instance ToValue PABConfig where
7986
toValue
@@ -95,6 +102,7 @@ instance ToValue PABConfig where
95102
pcPort
96103
pcEnableTxEndpoint
97104
pcCollectStats
105+
pcTxStausPolling
98106
) =
99107
Sections
100108
()
@@ -116,6 +124,7 @@ instance ToValue PABConfig where
116124
, Section () "port" $ toValue pcPort
117125
, Section () "enableTxEndpoint" $ toValue pcEnableTxEndpoint
118126
, Section () "collectStats" $ toValue pcCollectStats
127+
, Section () "pcTxStausPolling" $ toValue pcTxStausPolling
119128
]
120129
{- ORMOLU_ENABLE -}
121130

@@ -206,6 +215,13 @@ pabConfigSpec = sectionsSpec "PABConfig" $ do
206215
trueOrFalseSpec
207216
"Save some stats during contract run (only transactions execution budgets supported atm)"
208217

218+
pcTxStausPolling <-
219+
sectionWithDefault'
220+
(pcTxStausPolling def)
221+
"pcTxStausPolling"
222+
txStatusPollingSpec
223+
(error "TODO: TxStatusPolling config help")
224+
209225
pure PABConfig {..}
210226

211227
docPABConfig :: String

src/BotPlutusInterface/Contract.hs

Lines changed: 73 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -24,15 +24,15 @@ import BotPlutusInterface.Effects (
2424
saveBudget,
2525
slotToPOSIXTime,
2626
threadDelay,
27-
uploadDir,
27+
uploadDir
2828
)
2929
import BotPlutusInterface.Files (DummyPrivKey (FromSKey, FromVKey))
3030
import BotPlutusInterface.Files qualified as Files
3131
import BotPlutusInterface.Types (
3232
ContractEnvironment (..),
3333
LogLevel (Debug, Warn),
3434
Tip (block, slot),
35-
TxFile (Signed),
35+
TxFile (Signed), spInterval, spBlocksTimeOut
3636
)
3737
import Cardano.Api (AsType (..), EraInMode (..), Tx (Tx))
3838
import Control.Lens (preview, (^.))
@@ -45,7 +45,6 @@ import Control.Monad.Trans.Class (lift)
4545
import Control.Monad.Trans.Either (EitherT, eitherT, firstEitherT, newEitherT)
4646
import Data.Aeson (ToJSON, Value (Array, Bool, Null, Number, Object, String))
4747
import Data.Aeson.Extras (encodeByteString)
48-
import Data.Either (fromRight)
4948
import Data.HashMap.Strict qualified as HM
5049
import Data.Kind (Type)
5150
import Data.Map qualified as Map
@@ -210,27 +209,59 @@ awaitTxStatusChange ::
210209
Ledger.TxId ->
211210
Eff effs TxStatus
212211
awaitTxStatusChange contractEnv txId = do
213-
-- The depth (in blocks) after which a transaction cannot be rolled back anymore (from Plutus.ChainIndex.TxIdState)
214-
let chainConstant = 8
215-
216-
mTx <- queryChainIndexForTxState
217-
case mTx of
218-
Nothing -> pure Unknown
219-
Just txState -> do
220-
printBpiLog @w Debug $ "Found transaction in node, waiting" <+> pretty chainConstant <+> " blocks for it to settle."
221-
awaitNBlocks @w contractEnv (chainConstant + 1)
222-
-- Check if the tx is still present in chain-index, in case of a rollback
223-
-- we might not find it anymore.
224-
ciTxState' <- queryChainIndexForTxState
225-
case ciTxState' of
226-
Nothing -> pure Unknown
227-
Just _ -> do
228-
blk <- fromInteger <$> currentBlock contractEnv
229-
-- This will set the validity correctly based on the txState.
230-
-- The tx will always be committed, as we wait for chainConstant + 1 blocks
231-
let status = transactionStatus blk txState txId
232-
pure $ fromRight Unknown status
212+
let txStatusPolling = contractEnv.cePABConfig.pcTxStausPolling
213+
pollInterval = fromIntegral $ spInterval txStatusPolling
214+
pollTimeOut = fromIntegral $ spBlocksTimeOut txStatusPolling
215+
cutOffBlock <- (pollTimeOut +) <$> currentBlock contractEnv
216+
printBpiLog @w Debug $ pretty $ "Awaiting status change for " ++ show txId
217+
txStausCheckLoop txId contractEnv pollInterval cutOffBlock
218+
219+
txStausCheckLoop ::
220+
forall (w :: Type) (effs :: [Type -> Type]).
221+
Member (PABEffect w) effs =>
222+
Ledger.TxId ->
223+
ContractEnvironment w ->
224+
Int ->
225+
Integer ->
226+
Eff effs TxStatus
227+
txStausCheckLoop txId contractEnv pollInterval cutOffBlock = do
228+
currBlock <- currentBlock contractEnv
229+
txStatus <- getStatus
230+
case (txStatus, currBlock > cutOffBlock) of
231+
(status, True) -> do
232+
logDebug $ "Awaiting preiod for TxId " ++ show txId
233+
++ " status change is over, current status: " ++ show status
234+
return status
235+
(Unknown, _) -> do
236+
threadDelay @w pollInterval
237+
txStausCheckLoop txId contractEnv pollInterval cutOffBlock
238+
(status, _) -> return status
233239
where
240+
-- | get Tx status with extensive debug logging
241+
getStatus = do
242+
mTx <- queryChainIndexForTxState
243+
case mTx of
244+
Nothing -> do
245+
logDebug $ "TxId " ++ show txId ++ " not found in index"
246+
return Unknown
247+
Just txState -> do
248+
logDebug $ "TxId " ++ show txId ++ " found in index, checking status"
249+
blk <- fromInteger <$> currentBlock contractEnv
250+
case transactionStatus blk txState txId of
251+
Left e -> do
252+
logDebug $ "Staus check for TxId " ++ show txId ++ " failed with " ++ show e
253+
return Unknown
254+
Right st -> case st of
255+
Unknown -> do
256+
logDebug $ "Staus for TxId " ++ show txId ++ " is Unknown"
257+
return Unknown
258+
other -> do
259+
logDebug $
260+
"Staus for TxId " ++ show txId ++ " is " ++ show other
261+
pure other
262+
263+
logDebug = printBpiLog @w Debug . pretty
264+
234265
queryChainIndexForTxState :: Eff effs (Maybe TxIdState)
235266
queryChainIndexForTxState = do
236267
mTx <- join . preview _TxIdResponse <$> (queryChainIndex @w $ TxFromTxId txId)
@@ -355,25 +386,25 @@ awaitSlot contractEnv s@(Slot n) = do
355386
| n < tip'.slot -> pure $ Slot tip'.slot
356387
_ -> awaitSlot contractEnv s
357388

358-
-- | Wait for n Blocks.
359-
awaitNBlocks ::
360-
forall (w :: Type) (effs :: [Type -> Type]).
361-
Member (PABEffect w) effs =>
362-
ContractEnvironment w ->
363-
Integer ->
364-
Eff effs ()
365-
awaitNBlocks contractEnv n = do
366-
current <- currentBlock contractEnv
367-
go current
368-
where
369-
go :: Integer -> Eff effs ()
370-
go start = do
371-
threadDelay @w (fromIntegral contractEnv.cePABConfig.pcTipPollingInterval)
372-
tip <- CardanoCLI.queryTip @w contractEnv.cePABConfig
373-
case tip of
374-
Right tip'
375-
| start + n <= tip'.block -> pure ()
376-
_ -> go start
389+
-- -- | Wait for n Blocks.
390+
-- awaitNBlocks ::
391+
-- forall (w :: Type) (effs :: [Type -> Type]).
392+
-- Member (PABEffect w) effs =>
393+
-- ContractEnvironment w ->
394+
-- Integer ->
395+
-- Eff effs ()
396+
-- awaitNBlocks contractEnv n = do
397+
-- current <- currentBlock contractEnv
398+
-- go current
399+
-- where
400+
-- go :: Integer -> Eff effs ()
401+
-- go start = do
402+
-- threadDelay @w (fromIntegral contractEnv.cePABConfig.pcTipPollingInterval)
403+
-- tip <- CardanoCLI.queryTip @w contractEnv.cePABConfig
404+
-- case tip of
405+
-- Right tip'
406+
-- | start + n <= tip'.block -> pure ()
407+
-- _ -> go start
377408

378409
{- | Wait at least until the given time. Uses the awaitSlot under the hood, so the same constraints
379410
are applying here as well.

src/BotPlutusInterface/Types.hs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ module BotPlutusInterface.Types (
2222
SpendBudgets,
2323
MintBudgets,
2424
ContractStats (..),
25+
TxStatusPolling(..),
2526
addBudget,
2627
) where
2728

@@ -83,6 +84,13 @@ data PABConfig = PABConfig
8384
, pcPort :: !Port
8485
, pcEnableTxEndpoint :: !Bool
8586
, pcCollectStats :: !Bool
87+
, pcTxStausPolling :: !TxStatusPolling
88+
}
89+
deriving stock (Show, Eq)
90+
91+
data TxStatusPolling = TxStatusPolling
92+
{ spInterval :: !Natural -- ^ mocroseconds
93+
, spBlocksTimeOut :: !Natural -- ^ blocks until timeout, most likely `Unknown` state will be returned
8694
}
8795
deriving stock (Show, Eq)
8896

@@ -221,6 +229,7 @@ instance Default PABConfig where
221229
, pcPort = 9080
222230
, pcEnableTxEndpoint = False
223231
, pcCollectStats = False
232+
, pcTxStausPolling = TxStatusPolling 1_000 8
224233
}
225234

226235
data RawTx = RawTx

test/Spec/BotPlutusInterface/Config.hs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
module Spec.BotPlutusInterface.Config (tests) where
44

55
import BotPlutusInterface.Config (loadPABConfig, savePABConfig)
6-
import BotPlutusInterface.Types (CLILocation (..), LogLevel (..), PABConfig (..))
6+
import BotPlutusInterface.Types (CLILocation (..), LogLevel (..), PABConfig (..), TxStatusPolling (TxStatusPolling))
77
import Cardano.Api (
88
AnyPlutusScriptVersion (..),
99
CostModel (..),
@@ -113,4 +113,5 @@ pabConfigExample =
113113
, pcPort = 1021
114114
, pcEnableTxEndpoint = True
115115
, pcCollectStats = False
116+
, pcTxStausPolling = TxStatusPolling 1_000 8
116117
}

test/Spec/MockContract.hs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -330,8 +330,8 @@ runPABEffectPure initState req =
330330
incTip Tip {tipSlot, tipBlockId, tipBlockNo} =
331331
Tip
332332
{ tipSlot = tipSlot + 1
333-
, tipBlockId = tipBlockId
334-
, tipBlockNo = tipBlockNo
333+
, tipBlockId = tipBlockId -- FIXME: will need that for testing await status timeout probably
334+
, tipBlockNo = tipBlockNo -- FIXME: will need that for testing await status timeout probably
335335
}
336336

337337
mockCallCommand ::

0 commit comments

Comments
 (0)