Skip to content

Commit 3f9f409

Browse files
Add validity interval to release-funds, and provide example VFunction (#183)
* Add validity interval to release-funds, and provide example VFunction * cleanup --------- Co-authored-by: Krisztian Pinter <[email protected]>
1 parent 97fe0ca commit 3f9f409

File tree

23 files changed

+371
-13
lines changed

23 files changed

+371
-13
lines changed
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
kind: Added
2+
body: Example V function
3+
time: 2025-01-09T14:42:13.317947+01:00
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
kind: Changed
2+
body: '`reserve-release-funds` now sets up validity interval from the current time to +infinity'
3+
time: 2025-01-09T14:42:41.875132+01:00

offchain/spago.dhall

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
, "const"
1616
, "control"
1717
, "datetime"
18+
, "effect"
1819
, "either"
1920
, "exceptions"
2021
, "foldable-traversable"
@@ -33,6 +34,7 @@
3334
, "node-process"
3435
, "node-streams"
3536
, "nonempty"
37+
, "now"
3638
, "optparse"
3739
, "ordered-collections"
3840
, "parsing"

offchain/src/Main.purs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,11 @@ import TrustlessSidechain.EndpointResp
3131
, UpdatePermissionedCandidatesResp
3232
, ListVersionedScriptsResp
3333
, ReserveResp
34+
, GetVFunctionCBORResp
3435
)
3536
, stringifyEndpointResp
3637
)
38+
import TrustlessSidechain.ExampleVFunction as ExampleVFunction
3739
import TrustlessSidechain.GetSidechainAddresses as GetSidechainAddresses
3840
import TrustlessSidechain.Governance.Utils (updateGovernance)
3941
import TrustlessSidechain.InitSidechain.Governance (initGovernance)
@@ -69,6 +71,7 @@ import TrustlessSidechain.Options.Types
6971
, DepositReserve
7072
, ReleaseReserveFunds
7173
, HandoverReserve
74+
, GetVFunctionCBOR
7275
)
7376
)
7477
import TrustlessSidechain.PermissionedCandidates as PermissionedCandidates
@@ -274,6 +277,10 @@ runTxEndpoint genesisUtxo endpoint =
274277
txHash <- handover genesisUtxo utxo
275278
pure $ ReserveResp { transactionHash: txHashToByteArray txHash }
276279

280+
GetVFunctionCBOR { unixTimestamp } -> do
281+
vFunctionCBOR <- ExampleVFunction.decodeExampleVFunctionPolicy unixTimestamp
282+
pure $ GetVFunctionCBORResp { vFunctionCBOR }
283+
277284
printEndpointResp :: EndpointResp -> Effect Unit
278285
printEndpointResp =
279286
log <<< stringifyEndpointResp

offchain/src/TrustlessSidechain/Effects/App.purs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,14 @@ import Run (AFF, EFFECT)
77
import Run.Except (EXCEPT)
88
import TrustlessSidechain.Effects.Contract (CONTRACT)
99
import TrustlessSidechain.Effects.Log (LOG)
10+
import TrustlessSidechain.Effects.Time (TIME)
1011
import TrustlessSidechain.Effects.Transaction (TRANSACTION)
1112
import TrustlessSidechain.Effects.Wallet (WALLET)
1213
import TrustlessSidechain.Error (OffchainError)
1314
import Type.Row (type (+))
1415

1516
-- | The top level effects
16-
type APP r = EXCEPT OffchainError + WALLET + TRANSACTION + LOG + r
17+
type APP r = EXCEPT OffchainError + WALLET + TRANSACTION + LOG + TIME + r
1718

1819
-- | The base effects
1920
type BASE r = CONTRACT + EFFECT + AFF + r

offchain/src/TrustlessSidechain/Effects/Run.purs

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,8 @@ import Run.Except (EXCEPT, runExcept)
1616
import TrustlessSidechain.Effects.App (APP, BASE)
1717
import TrustlessSidechain.Effects.Contract (liftContract, unliftContract)
1818
import TrustlessSidechain.Effects.Contract as Effect
19-
import TrustlessSidechain.Effects.Log (LogF, handleLogLive, handleLogWith)
19+
import TrustlessSidechain.Effects.Log (LOG, LogF, handleLogLive, handleLogWith)
20+
import TrustlessSidechain.Effects.Time (TimeF, handleTimeLive, handleTimeWith)
2021
import TrustlessSidechain.Effects.Transaction
2122
( TRANSACTION
2223
, TransactionF
@@ -46,12 +47,17 @@ runAppWith ::
4647
( EXCEPT OffchainError + WALLET + TRANSACTION + r
4748
)
4849
) ->
50+
( TimeF ~> Run
51+
( EXCEPT OffchainError + WALLET + TRANSACTION + LOG + r
52+
)
53+
) ->
4954
Run (APP + r) ~>
5055
Run (EXCEPT OffchainError + r)
51-
runAppWith handleTransaction handleWallet handleLog f =
56+
runAppWith handleTransaction handleWallet handleLog handleTime f =
5257
handleTransactionWith handleTransaction
5358
$ handleWalletWith handleWallet
5459
$ handleLogWith handleLog
60+
$ handleTimeWith handleTime
5561
$ f
5662

5763
-- | Run the effect stack down to an `Aff` using the live handlers
@@ -64,6 +70,7 @@ runAppLive contractParams = runBaseAff'
6470
<<< runExcept
6571
<<< Effect.runContract contractParams
6672
<<< runAppWith handleTransactionLive handleWalletLive handleLogLive
73+
handleTimeLive
6774

6875
-- | Strip away the `APP` effect using the live handlers
6976
runToBase ::
@@ -72,6 +79,7 @@ runToBase f =
7279
runAppWith handleTransactionLive
7380
handleWalletLive
7481
handleLogLive
82+
handleTimeLive
7583
$ f
7684

7785
-- | Unlift an effect stack which contains a `CONTRACT` effect to the `Contract` monad
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
module TrustlessSidechain.Effects.Time
2+
( TIME
3+
, TimeF
4+
, handleTimeLive
5+
, handleTimeWith
6+
, getCurrentEra
7+
, getSystemStart
8+
) where
9+
10+
import Contract.Prelude
11+
12+
import Contract.Log (logDebug', logInfo', logWarn') as Contract
13+
import Contract.Time as Time
14+
import Effect.Aff (Error)
15+
import Run (Run, interpret, on, send)
16+
import Run as Run
17+
import Run.Except (EXCEPT)
18+
import TrustlessSidechain.Effects.Contract (CONTRACT, withTry)
19+
import TrustlessSidechain.Effects.Errors.Context
20+
( ErrorContext(ErrorContext)
21+
, ErrorContextType(Log)
22+
)
23+
import TrustlessSidechain.Effects.Errors.Parser
24+
( parseDefaultError
25+
, parseFromError
26+
)
27+
import TrustlessSidechain.Error (OffchainError)
28+
import Type.Proxy (Proxy(Proxy))
29+
import Type.Row (type (+))
30+
31+
data TimeF a
32+
= GetCurrentEra' (Time.EraSummary -> a)
33+
| GetSystemStart' (Time.SystemStart -> a)
34+
35+
derive instance functorTimeF :: Functor TimeF
36+
37+
type TIME r = (time :: TimeF | r)
38+
39+
_time :: Proxy "time"
40+
_time = Proxy
41+
42+
handleTimeWith ::
43+
forall r. (TimeF ~> Run r) -> Run (TIME + r) ~> Run r
44+
handleTimeWith f = interpret (on _time f send)
45+
46+
getCurrentEra ::
47+
forall r. Run (TIME + r) Time.EraSummary
48+
getCurrentEra = Run.lift _time
49+
(GetCurrentEra' identity)
50+
51+
getSystemStart ::
52+
forall r. Run (TIME + r) Time.SystemStart
53+
getSystemStart = Run.lift _time
54+
(GetSystemStart' identity)
55+
56+
handleTimeLive ::
57+
forall r. TimeF ~> Run (EXCEPT OffchainError + CONTRACT + r)
58+
handleTimeLive =
59+
case _ of
60+
GetCurrentEra' f -> f <$> withTry
61+
(fromError "getCurrentEra: ")
62+
(Time.getCurrentEra)
63+
GetSystemStart' f -> f <$> withTry
64+
(fromError "getSystemStart: ")
65+
(Time.getSystemStart)
66+
where
67+
fromError :: String -> Error -> OffchainError
68+
fromError ctx =
69+
parseFromError parseDefaultError (Just (ErrorContext Log ctx))

offchain/src/TrustlessSidechain/EndpointResp.purs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ data EndpointResp
5151
, versionedValidators :: List (Tuple Types.ScriptId PlutusScript)
5252
}
5353
| ReserveResp { transactionHash :: ByteArray }
54+
| GetVFunctionCBORResp { vFunctionCBOR :: ByteArray }
5455

5556
-- Note [BigInt values and JSON]
5657
-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -189,6 +190,11 @@ endpointRespCodec = CA.prismaticCodec "EndpointResp" dec enc CA.json
189190
J.fromObject $ Object.fromFoldable
190191
[ "transactionHash" /\ J.fromString (byteArrayToHex transactionHash) ]
191192

193+
GetVFunctionCBORResp { vFunctionCBOR } ->
194+
J.fromObject $ Object.fromFoldable
195+
[ "vFunctionCBOR" /\ J.fromString (byteArrayToHex vFunctionCBOR)
196+
]
197+
192198
-- | Encode the endpoint response to a json object
193199
encodeEndpointResp :: EndpointResp -> J.Json
194200
encodeEndpointResp = CA.encode endpointRespCodec
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
module TrustlessSidechain.ExampleVFunction where
2+
3+
import Contract.Prelude hiding (note)
4+
5+
import Cardano.AsCbor (encodeCbor)
6+
import Cardano.ToData (toData)
7+
import Cardano.Types.BigInt (BigInt)
8+
import Cardano.Types.PlutusScript (PlutusScript, getBytes)
9+
import Data.ByteArray (ByteArray)
10+
import Run (Run)
11+
import Run.Except (EXCEPT)
12+
import TrustlessSidechain.Effects.Wallet (WALLET)
13+
import TrustlessSidechain.Error (OffchainError)
14+
import TrustlessSidechain.Utils.Scripts
15+
( mkMintingPolicyWithParams
16+
)
17+
import TrustlessSidechain.Versioning.ScriptId
18+
( ScriptId
19+
( ExampleVFunctionPolicy
20+
)
21+
)
22+
import Type.Row (type (+))
23+
24+
decodeExampleVFunctionPolicy ::
25+
forall r.
26+
BigInt ->
27+
Run (EXCEPT OffchainError + WALLET + r) ByteArray
28+
decodeExampleVFunctionPolicy unixTimestamp = do
29+
30+
plutusScript <- mkMintingPolicyWithParams ExampleVFunctionPolicy $
31+
[ toData unixTimestamp
32+
]
33+
34+
pure $ unwrap $ encodeCbor plutusScript
35+
36+
exampleVFunctionPolicy ::
37+
forall r.
38+
BigInt ->
39+
Run (EXCEPT OffchainError + WALLET + r) PlutusScript
40+
exampleVFunctionPolicy unixTimestamp = do
41+
42+
mkMintingPolicyWithParams ExampleVFunctionPolicy $
43+
[ toData unixTimestamp
44+
]

offchain/src/TrustlessSidechain/NativeTokenManagement/Reserve.purs

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,10 @@ import Contract.PlutusData
3232
, toData
3333
)
3434
import Contract.ScriptLookups as Lookups
35+
import Contract.Time
36+
( POSIXTime
37+
)
38+
import Contract.Time as Time
3539
import Contract.Transaction
3640
( ScriptRef(..)
3741
, TransactionHash
@@ -45,15 +49,27 @@ import Contract.TxConstraints
4549
import Contract.TxConstraints as TxConstraints
4650
import Contract.Utxos (UtxoMap)
4751
import Contract.Value (add, minus, singleton) as Value
52+
import Data.Array as Array
53+
import Data.Bifunctor (lmap)
54+
import Data.DateTime.Instant (unInstant)
55+
import Data.Int (floor)
4856
import Data.Map as Map
57+
import Data.Time.Duration (Milliseconds(..))
58+
import Effect.Now as Now
59+
import Effect.Unsafe (unsafePerformEffect)
4960
import JS.BigInt as BigInt
61+
import Partial.Unsafe (unsafePartial)
62+
import Run (EFFECT, Run, liftEffect)
5063
import Run (Run)
5164
import Run.Except (EXCEPT, throw)
52-
import TrustlessSidechain.Effects.App (APP)
65+
import TrustlessSidechain.Effects.App (APP, BASE)
66+
import TrustlessSidechain.Effects.Contract (CONTRACT, liftContract)
67+
import TrustlessSidechain.Effects.Time (getCurrentEra, getSystemStart)
5368
import TrustlessSidechain.Effects.Transaction (TRANSACTION, getUtxo, utxosAt)
54-
import TrustlessSidechain.Effects.Util (fromMaybeThrow)
69+
import TrustlessSidechain.Effects.Util (fromEitherThrow, fromMaybeThrow)
5570
import TrustlessSidechain.Effects.Wallet (WALLET)
5671
import TrustlessSidechain.Error (OffchainError(..))
72+
import TrustlessSidechain.Error (OffchainError(GenericInternalError))
5773
import TrustlessSidechain.Governance.Utils as Governance
5874
import TrustlessSidechain.NativeTokenManagement.Types
5975
( ImmutableReserveSettings
@@ -662,6 +678,18 @@ transferToIlliquidCirculationSupply
662678
(GenericInternalError "Could not calculate new ICS value")
663679
(pure (toTransferAsValue `Value.minus` incentiveAsValue))
664680

681+
currentEra <- getCurrentEra
682+
systemStart <- getSystemStart
683+
684+
let summaries = wrap $ Array.singleton currentEra
685+
686+
nowMoment <- fromEitherThrow $ pure
687+
$ lmap (\x -> GenericInternalError (show x))
688+
$ Time.slotToPosixTime summaries systemStart
689+
(unwrap (unwrap currentEra).start).slot
690+
691+
let validityInterval = Time.from nowMoment
692+
665693
let
666694
lookups :: Lookups.ScriptLookups
667695
lookups =
@@ -703,6 +731,7 @@ transferToIlliquidCirculationSupply
703731
PlutusData.unit
704732
DatumInline
705733
illiquidCirculationNewValue
734+
<> TxConstraints.mustValidateIn validityInterval
706735

707736
balanceSignAndSubmit
708737
"Transfer to illiquid circulation supply"

0 commit comments

Comments
 (0)