IntersectMBO / plutus

The Plutus language implementation and tools
Apache License 2.0
1.57k stars 479 forks source link

Transaction validity range in slots #4635

Closed ch1bo closed 4 months ago

ch1bo commented 2 years ago

Describe the feature you'd like

We would love to have access to the transaction's validity range as SlotNo in the TxInfo. AFAIK that is ground truth present in the described Cardano transaction.

Describe alternatives you've considered

Using POSIXTime is possible, but makes it unnecessarily complicated for our protocol. The POSIXTime equivalent is ideally purely informational in our case.

michaelpj commented 2 years ago

This was a deliberate design choice. Slot numbers don't have a stable meaning, because the slot length is a protocol parameter that can change!

Our belief was that applications mostly care about actual time passing, not arbitrary ticks as represented by slots on chain. And representing actual time with slots is not safe because of the slot length problem.

ch1bo commented 2 years ago

Thanks for the response. Let me give you some context where this ask is coming from:

In the case for Hydra, slots are used to represent the concept of a contestation period & deadline. The contestation period T is a parameter to each Hydra Head. It shall start when closing the Head and the Head can only be finalized after that passed. To ensure that nobody can finalize the head before that time passed, a contestation deadline is determined from the upper validity bound T_final = r_max + T. That deadline is relevant for on-chain verification of both, contest transactions and finalizing fanout transactions. Contest needs to have an upper validity bound r_max < T_final and fanout needs to have a lower validity bound r_min > T_final. The specification does not say much about the required properties of the contestation period or deadline, but it certainly assumes that slots are strictly monotonically increasing.

To realize this using plutus we need to

So.. in our setting it would be perfectly fine to "just" have access to SlotNo of the transactions to ensure contestation periods are handled consistently. It would mean that a contestation period is longer/shorter than originally agreed in wall clock time should a protocol update be performed while a Hydra Head is open. But how often did that happen? These updates come with some epoch lead time, so a Hydra Head could be closed before if someone is not happy with the shorter slot lengths.

Hope that helps to understand what our user story for this feature request is. Thanks for considering.

michaelpj commented 2 years ago

It would mean that a contestation period is longer/shorter than originally agreed in wall clock time should a protocol update be performed while a Hydra Head is open. But how often did that happen? These updates come with some epoch lead time, so a Hydra Head could be closed before if someone is not happy with the shorter slot lengths.

It may be true that such a change would be acceptable in the context of Hydra, but I do no think it is true in general. And we have to worry about the general case. If we allow contracts to be sensitive to slots, then people will depend on it. And that then effectively means we can't change the slot length, because it would break many existing scripts.

So the logic is a bit backwards: it's not that we're worried that we will change the slot length regularly and break things (we won't), but that we don't want to be unable to change the slot length. Then Plutus would have taken a part of the system that should be changeable and made it unchangeable.


More generally, changing protocol parameters shouldn't change the behaviour of existing scripts. One way to maintain this property would have been to back-translate the "real" slots into the "hypothetical" slots that the script would expect given the time when it was created. But this is quite complicated: we need to record when the output was created, and do the back-translation.

And even then it's still not safe: scripts that "chain" by requiring an ongoing output locked with the same script would "lose" their creation time and start getting the wrong slot lengths.

ch1bo commented 2 years ago

I see. I do accept this for an answer! :+1: Maybe this is even written somewhere and I just didn't read the manual?

michaelpj commented 2 years ago

No, this should be in the technical report...

ch1bo commented 2 years ago

Then Plutus would have taken a part of the system that should be changeable and made it unchangeable.

I would like to extend the discussion here a bit after stumbling over how plutus-apps is converting time between slots and POSIXTime: https://github.com/input-output-hk/plutus-apps/blob/6d1600f084e894a257e02d3d0095b1f7a752b464/plutus-ledger/src/Ledger/TimeSlot.hs#L133-L138

We have tried hard in Hydra to not do the simple thing of blindly dividing time by slotLength and use the era-aware Interpreter from ouroboros-consensus (obtained from a cardano-node).

As we now run into issues of converting too-far-away slots into POSIXTime using that mechanism, we are facing PastHorizonExceptions (i.e. if looking past epoch boundary). We are even considering using unsafeExtendSafeZone to pretend there will be no further era and same slot length forever. But that is not much better than just dividing.

Which brings me back to the point.. how can one practically use POSIXTime without running into these problems? Will people be forced to do it as plutus-apps and just divide time by slotLength? Will they do it even unknowingly?

To me, this is a leaky abstraction and we much rather would like to have our users decide and ultimately only care about slots in our application. What do you think of all this @michaelpj?

CC @KtorZ

michaelpj commented 2 years ago

I don't think it's a leaky abstraction. You're saying its an unacceptably difficult abstraction to use, and so you're worried that people will bypass the correct methods and do the wrong thing. I do agree that we should make it easier to do the right thing! Maybe cardano-api could expose a way to specify the validity interval in PosixTime and convert it properly for you. But some of the difficulty is inescapable: the reason you can't predict the slot that far in the future is because you don't know that the slot length won't change.

Note that I think the node will also reject transactions with upper bounds that are outside the stability window, for this reason!

I need to read your example again carefully to try and give a more useful response, but my intuitive feeling is that you should be able to operate as follows:

Why does that not work for you?

ch1bo commented 2 years ago

you're worried that people will bypass the correct methods and do the wrong thing

Not only worried, I see it happening (one example even being plutus-apps, but I don't want to blame them directly).

Note that I think the node will also reject transactions with upper bounds that are outside the stability window, for this reason!

Note that we would not need to submit a transaction with bounds (in slots) outside the safe zone, but only to our script as a deadline. Eventually that slot will come, ideally it corresponds to the users intuition.

Use PosixTime almost everywhere

That's maybe a good idea! I did not consider it that way around yet - I think because slots is the first thing you get from a node and functions for converting POSIXTime -> SlotNo are not so readily available as the other way around, but we are past that point.

Rephrasing the idea (correct me if I'm wrong): points in time far into the future (e.g. our deadline) would be already in POSIXTime and only when crafting or observing transactions we need to convert POSIXTime -> SlotNo, while that would be closer to "now" and hence within the safe zone.

I suppose this would only work if the cardano-node does not allow past-horizon tx bounds, because we would try to convert them to POSIXTime when observing these transactions.

dcoutts commented 2 years ago

I suppose this would only work if the cardano-node does not allow past-horizon tx bounds, because we would try to convert them to POSIXTime when observing these transactions.

For txs that use Plutus scripts, it does require the validity bounds to be within the time horizon, since that's the only range in which it can convert slots to wall clock time (i.e. posix time). (For txs that do not use Plutus scripts it allows any bounds that include "now").

michaelpj commented 2 years ago

Not only worried, I see it happening (one example even being plutus-apps, but I don't want to blame them directly).

That code in plutus-apps likely precedes the Alonzo node. It's just one of the many things that need to eventually be converted to do the right thing, rather than something where it was too difficult.

waalge commented 1 year ago

No, this should be in the technical report...

@michaelpj Is this the one linked from the README? I get access denied.

effectfully commented 1 year ago

@michaelpj what's the status of this issue?

michaelpj commented 1 year ago

I don't think we have any intention of exposing the range in slots, nor is this repo the place to put stuff to make slot conversion easier. I do want to document it in the technical report, so we can leave it open as a reminder or close it.

effectfully commented 1 year ago

I don't think we have any intention of exposing the range in slots, nor is this repo the place to put stuff to make slot conversion easier. I do want to document it in the technical report, so we can leave it open as a reminder or close it.

Great, let's keep it open then.

uhbif19 commented 1 year ago

@michaelpj

Our belief was that applications mostly care about actual time passing, not arbitrary ticks as represented by slots on chain. And representing actual time with slots is not safe because of the slot length problem. If we allow contracts to be sensitive to slots, then people will depend on it. And that then effectively means we can't change the slot length, because it would break many existing scripts.

On another issue I read your comment, from which I understand that plutus-ledger-api is "only interface for the ledger" and types are supposed to "correspond simply to what is going on in a transaction", while end users safety is out of scope of plutus-ledger-api goals.

https://github.com/input-output-hk/plutus/issues/4811#issuecomment-1574222742

And the correct tradeoff will differ for different users who have different safety tolerances and desires.

That seems like exactly the case when some user "have lower safety desire". I do not understand how this issue is different from issue #4811.

So now I am confused which are the goals and supposed users of plutus-ledger-api package. Are they stated somewhere?

effectfully commented 4 months ago

I don't think we have any intention of exposing the range in slots, nor is this repo the place to put stuff to make slot conversion easier. I do want to document it in the technical report, so we can leave it open as a reminder or close it.

Michael has left IOG and it doesn't seem like anybody's going to work on that, so I'm closing the issue.

@zliu41 please reopen if we want to allocate resources to this issue actually.