#
Vesting Example
#
Handling Time
Lecture 3, Part 3
Under most circumstances you can always tell whether a transaction will fail before submitting it to the blockchain. Validation can and does happen off-chain in a user's wallet.
However, the time when a wallet validates a transaction off-chain will be
different than the time when the transaction arrives at a node. The
txInfoValidRange
of a ScriptContext
handles this.
When a node processes a transaction it does basic checks first before running a script. It is at this time that the current time is checked to be within the valid time range.
By default, transactions use the infinite time range. This can be change, such as in the auction example from lecture 1.
Cardano uses slots as a measurement of time. Each slot is 1 second. So it's easy to go back and forth between real time and slots. The definition of a slot could possibly change in the future, so transactions shouldn't have a valid range that is too far in the future. A change to the slot definition requires a hard fork, which comes with an announcement at least 36 hours in advance.
txInfoValidRange
has type POSIXTimeRange
which contains an Interval
and a
POSIXTime
. Interval
optionally contains a LowerBound
and an UpperBound
.
There are a number of convenient functions for working with Intervals
. Some
examples:
member
checks whether a value is included in an intervalalways
is an interval that covers every slotfrom
constructs an interval that starts at a given value and goes on foreverto
is the opposite offrom
before
checks if a value is earlier than a given intervalafter
is the opposite ofbefore
You can play around with intervals by starting up a Nix shell in plutus-apps
cd plutus-apps
nix-shell
Then change into this week's directory
cd ~/plutus-pioneer-program/code/week03
Start a REPL
cabal repl
Import the Interval module
import Plutus.V1.Ledger.Interval
See what an Interval looks like between slot 10 and 20
tenToTwenty = interval (10 :: Integer) 20
tenToTwenty
Interval {ivFrom = LowerBound (Finite 10) True, ivTo = UpperBound (Finite 20) True}
This can be read as "an interval with lower bound 10 inclusive (10 is included) and upper bound 20 inclusive" or even more simply "from slot 10 to 20".
You can check whether a value is a member of this interval
member 9 tenToTwenty
False
member 10 tenToTwenty
True
member 15 tenToTwenty
True
member 20 tenToTwenty
True
member 21 tenToTwenty
False
Another couple more interval examples
fromThirty = from (30 :: Integer)
toThirty = to (30 :: Integer)
member 999 fromThirty
True
member 999 toThirty
False
member 10 fromThirty
False
member 10 toThirty
True
You can get the intersection of two intervals
tenToTwenty = interval (10 :: Integer) 20
twelveToThirty = interval (12 :: Integer) 30
intersection tenToTwenty twelveToThirty
Interval {ivFrom = LowerBound (Finite 12) True, ivTo = UpperBound (Finite 20) True}
You can see we get a new interval where the two inputs intersect (12 to 20).