Skip to content

Commit a2d2896

Browse files
author
gege251
committed
Add validity range functions
1 parent 58031bf commit a2d2896

File tree

3 files changed

+90
-4
lines changed

3 files changed

+90
-4
lines changed

src/BotPlutusInterface/CardanoCLI.hs

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ module BotPlutusInterface.CardanoCLI (
1212
validatorScriptFilePath,
1313
unsafeSerialiseAddress,
1414
policyScriptFilePath,
15+
validateRange,
1516
utxosAt,
1617
queryTip,
1718
) where
@@ -49,10 +50,17 @@ import Data.Set qualified as Set
4950
import Data.Text (Text)
5051
import Data.Text qualified as Text
5152
import Data.Text.Encoding (decodeUtf8)
53+
import Ledger (Slot (Slot), SlotRange)
5254
import Ledger qualified
5355
import Ledger.Ada qualified as Ada
5456
import Ledger.Address (Address (..))
5557
import Ledger.Crypto (PubKey, PubKeyHash)
58+
import Ledger.Interval (
59+
Extended (Finite, NegInf, PosInf),
60+
Interval (Interval),
61+
LowerBound (LowerBound),
62+
UpperBound (UpperBound),
63+
)
5664
import Ledger.Scripts (Datum, DatumHash (..))
5765
import Ledger.Scripts qualified as Scripts
5866
import Ledger.Tx (
@@ -185,9 +193,7 @@ isRawBuildMode :: BuildMode -> Bool
185193
isRawBuildMode (BuildRaw _) = True
186194
isRawBuildMode _ = False
187195

188-
{- | Build a tx body and write it to disk
189-
If a fee if specified, it uses the build-raw command
190-
-}
196+
-- | Build a tx body and write it to disk
191197
buildTx ::
192198
forall (w :: Type) (effs :: [Type -> Type]).
193199
Member (PABEffect w) effs =>
@@ -211,6 +217,7 @@ buildTx pabConf ownPkh buildMode tx =
211217
, txInCollateralOpts (txCollateral tx)
212218
, txOutOpts pabConf (txData tx) (txOutputs tx)
213219
, mintOpts pabConf buildMode (txMintScripts tx) (txRedeemers tx) (txMint tx)
220+
, validRangeOpts (txValidRange tx)
214221
, requiredSigners
215222
, case buildMode of
216223
BuildRaw fee -> ["--fee", showText fee]
@@ -350,6 +357,20 @@ mintOpts pabConf buildMode mintingPolicies redeemers mintValue =
350357
else []
351358
]
352359

360+
-- | This function does not check if the range is valid, that
361+
validRangeOpts :: SlotRange -> [Text]
362+
validRangeOpts (Interval lowerBound upperBound) =
363+
mconcat
364+
[ case lowerBound of
365+
LowerBound (Finite (Slot x)) True -> ["--invalid-hereafter", showText x]
366+
LowerBound (Finite (Slot x)) False -> ["--invalid-hereafter", showText (x + 1)]
367+
_ -> []
368+
, case upperBound of
369+
UpperBound (Finite (Slot x)) True -> ["--invalid-before", showText (x + 1)]
370+
UpperBound (Finite (Slot x)) False -> ["--invalid-before", showText x]
371+
_ -> []
372+
]
373+
353374
txOutOpts :: PABConfig -> Map DatumHash Datum -> [TxOut] -> [Text]
354375
txOutOpts pabConf datums =
355376
concatMap
@@ -417,6 +438,14 @@ exBudgetToCliArg (ExBudget (ExCPU steps) (ExMemory memory)) =
417438
showText :: forall (a :: Type). Show a => a -> Text
418439
showText = Text.pack . show
419440

441+
validateRange :: SlotRange -> Bool
442+
validateRange (Interval (LowerBound PosInf _) _) = False
443+
validateRange (Interval _ (UpperBound NegInf _)) = False
444+
validateRange (Interval (LowerBound (Finite lowerBound) _) (UpperBound (Finite upperBound) _))
445+
| lowerBound >= upperBound = False
446+
| otherwise = True
447+
validateRange _ = True
448+
420449
-- -- TODO: There is some issue with this function, the generated wallet key is incorrect
421450
-- toWalletKey :: Wallet -> Text
422451
-- toWalletKey =

src/BotPlutusInterface/PreBalance.hs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import Control.Monad (foldM, void, zipWithM)
1414
import Control.Monad.Freer (Eff, Member)
1515
import Control.Monad.Trans.Class (lift)
1616
import Control.Monad.Trans.Either (EitherT, hoistEither, newEitherT, runEitherT)
17+
import Data.Default (Default (def))
1718
import Data.Either.Combinators (maybeToRight, rightToMaybe)
1819
import Data.Kind (Type)
1920
import Data.List (partition, (\\))
@@ -30,6 +31,8 @@ import Ledger.Address (Address (..))
3031
import Ledger.Constraints.OffChain (UnbalancedTx (..), fromScriptOutput)
3132
import Ledger.Crypto (PrivateKey, PubKeyHash)
3233
import Ledger.Scripts (Datum, DatumHash)
34+
import Ledger.Time (POSIXTimeRange)
35+
import Ledger.TimeSlot (posixTimeRangeToContainedSlotRange)
3336
import Ledger.Tx (
3437
Tx (..),
3538
TxIn (..),
@@ -64,7 +67,7 @@ preBalanceTxIO pabConf ownPkh unbalancedTx =
6467
utxos <- lift $ CardanoCLI.utxosAt @w pabConf $ Ledger.pubKeyHashAddress (Ledger.PaymentPubKeyHash ownPkh) Nothing
6568
privKeys <- newEitherT $ Files.readPrivateKeys @w pabConf
6669
let utxoIndex = fmap Tx.toTxOut utxos <> fmap (Ledger.toTxOut . fromScriptOutput) (unBalancedTxUtxoIndex unbalancedTx)
67-
tx = unBalancedTxTx unbalancedTx
70+
tx = addValidRange (unBalancedTxValidityTimeRange unbalancedTx) (unBalancedTxTx unbalancedTx)
6871
requiredSigs = map Ledger.unPaymentPubKeyHash $ Map.keys (unBalancedTxRequiredSignatories unbalancedTx)
6972

7073
lift $ printLog @w Debug $ show utxoIndex
@@ -259,6 +262,10 @@ addSignatories ownPkh privKeys pkhs tx =
259262
tx
260263
(ownPkh : pkhs)
261264

265+
addValidRange :: POSIXTimeRange -> Tx -> Tx
266+
addValidRange timeRange tx =
267+
tx {txValidRange = posixTimeRangeToContainedSlotRange def timeRange}
268+
262269
showText :: forall (a :: Type). Show a => a -> Text
263270
showText = Text.pack . show
264271

test/Spec/BotPlutusInterface/Contract.hs

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,10 @@ import Ledger qualified
2121
import Ledger.Ada qualified as Ada
2222
import Ledger.Address qualified as Address
2323
import Ledger.Constraints qualified as Constraints
24+
import Ledger.Interval (interval)
2425
import Ledger.Scripts qualified as Scripts
2526
import Ledger.Slot (Slot)
27+
import Ledger.Time (POSIXTime (POSIXTime))
2628
import Ledger.Tx (CardanoTx, TxOut (TxOut), TxOutRef (TxOutRef))
2729
import Ledger.Tx qualified as Tx
2830
import Ledger.TxId qualified as TxId
@@ -78,6 +80,7 @@ tests =
7880
, testCase "Spend to validator script" spendToValidator
7981
, testCase "Redeem from validator script" redeemFromValidator
8082
, testCase "Multiple txs in a contract" multiTx
83+
, testCase "With valid range" withValidRange
8184
, testCase "Use Writer in a contract" useWriter
8285
, testCase "Wait for next block" waitNextBlock
8386
]
@@ -678,6 +681,53 @@ multiTx = do
678681
]
679682
Right _ -> assertFailure "Wrong number of txs"
680683

684+
withValidRange :: Assertion
685+
withValidRange = do
686+
let txOutRef = TxOutRef "e406b0cf676fc2b1a9edb0617f259ad025c20ea6f0333820aa7cef1bfe7302e5" 0
687+
txOut = TxOut pkhAddr1 (Ada.lovelaceValueOf 1250) Nothing
688+
initState = def & utxos .~ [(txOutRef, txOut)]
689+
inTxId = encodeByteString $ fromBuiltin $ TxId.getTxId $ Tx.txOutRefId txOutRef
690+
691+
contract :: Contract () (Endpoint "SendAda" ()) Text CardanoTx
692+
contract = do
693+
let constraints =
694+
Constraints.mustPayToPubKey paymentPkh2 (Ada.lovelaceValueOf 1000)
695+
<> Constraints.mustValidateIn (interval (POSIXTime 1643636293000) (POSIXTime 1646314693000))
696+
submitTx constraints
697+
698+
assertContractWithTxId contract initState $ \state outTxId ->
699+
assertCommandHistory
700+
state
701+
[
702+
( 2
703+
, [text|
704+
cardano-cli transaction build-raw --alonzo-era
705+
--tx-in ${inTxId}#0
706+
--tx-in-collateral ${inTxId}#0
707+
--tx-out ${addr2}+1000
708+
--invalid-hereafter 47577202
709+
--invalid-before 50255602
710+
--required-signer ./signing-keys/signing-key-${pkh1'}.skey
711+
--fee 0
712+
--protocol-params-file ./protocol.json --out-file ./txs/tx-${outTxId}.raw
713+
|]
714+
)
715+
,
716+
( 6
717+
, [text|
718+
cardano-cli transaction build --alonzo-era
719+
--tx-in ${inTxId}#0
720+
--tx-in-collateral ${inTxId}#0
721+
--tx-out ${addr2}+1000
722+
--invalid-hereafter 47577202
723+
--invalid-before 50255602
724+
--required-signer ./signing-keys/signing-key-${pkh1'}.skey
725+
--change-address ${addr1}
726+
--mainnet --protocol-params-file ./protocol.json --out-file ./txs/tx-${outTxId}.raw
727+
|]
728+
)
729+
]
730+
681731
useWriter :: Assertion
682732
useWriter = do
683733
let txOutRef = TxOutRef "e406b0cf676fc2b1a9edb0617f259ad025c20ea6f0333820aa7cef1bfe7302e5" 0

0 commit comments

Comments
 (0)