Notion of time slots with PoT

I noticed a “small” implementation problem.

Out notion of time was fixed before PoT, what I mean by that is that our time slots were basically current time - time of the block #1 divided by the time slot duration.

However, I think this will fundamentally stop working with PoT.

Specifically, what if we’re running a chain and timekeeper stops producing proofs for a few time slots (let’s say it is a local dev chain and timekeeper was restarted)?
Unless we change how we produce/count time slots, time slots will continue to move forward and timekeeper (when they get back) will lag behind the current time slot forever, so farmer will never receive proof in the time slot they expect and chain will be stuck forever.

At least that is my understanding right now.

If my understanding is in fact correct, then I’m afraid we need to change how we tick time slots to “pause” while we are waiting for PoT proofs to arrive, meaning there is no direct mapping of time slots to Unix time we had before and this might have some unexpected consequences (including implementation-wise where probably will have to fork sc-consensus-slots and change the implementation).

Curious what you folks think about this and whether it was already discussed and I missed it.

It is indeed an issue, but may be not as big as it seems.
Generally, the case when there is no timekeeper online is outside of our security model, but the issue you are raising can also happen if a timekeeper with the most potent hardware leaves and other timekeepers are slower and will start lagging behind.
This can be mitigated by a difficulty adjustment mechanism, similar to the one we have for solution ranges in farming. It would temporarily lower the number of iterations per slot until the number of slot proofs produced will match the target wall-clock slot. The chain would stall until PoT catches up, but not forever.
The idea was to launch w/o automatic difficulty adjustment and address these situations by manually updating the number of iterations per slot on a case-by-case basis. However we can discuss the design here, I recall @Barak had some proposals.

In the long run we’ll have to decouple time slots and local clock (that is, the expected time slot according to the local clock).

Launching Mainnet beta without proof-of-time difficulty adjustments assumes they will stay strongly coupled, while integrating difficulty adjustments implies they will not stay coupled forever.

The challenge is that right now timestamps in pallet-timestamp and slots are inherently coupled (https://github.com/subspace/subspace/blob/acf255b27ba0b9b0b35fb618f40fef0b85ae7c50/crates/pallet-subspace/src/lib.rs#L1558-L1575) and we make block producer solve challenges on every slot. The way you describe it seems to imply that we will have difficulty adjustment without block production, I’m not sure how that would work and be verifiable.

This was my assumption as well and that we will simply manually adjust the parameters over time, not dynamically. However this does lead to chain stalls that can’t be recovered it seems.

I’m not concerned with something lagging temporarily, I’m worried we have a chance to get into unrecoverable situation and I don’t understand how to handle it.

The way I envision this is that when PoT catches up a farmer will be able to claim a block in a “correct” slot and will include the PoT for “skipped” slots in the header pre-digest items, just like it normally would, so it will be verifiable. One thing we do need is for verification to account for iteration adjustments.

Well, that is tricky. “correct” slot would “technically” be in the past, meaning it should also include timestamp from the past or we need to decouple timestamps from slots already.

I feel like this needs to be written into the spec since it is not trivial, at least it doesn’t really match the way current implementation works.

By “correct” I mean when slot number in the proof matches the current wall clock slot number, so it won’t be in the past. My understanding was that the farmer isn’t able to claim past slots in the current implementation anyway?
I’ll put down something in the spec.

As the result of discussion with @dariolina we basically came to conclusion that we need to decouple slots from time completely.
Instead we can start slots from zero (or any arbitrary number really, but zero is the easiest) and make slot worker that issues challenges for farmer tick on proof of time arrival rather than every second. Assuming no one can run proof of time faster than others in private, everyone will get time slots ticking at the same rate just like before.

There might be some implementation or other challenges we do not foresee, but so far seems totally doable and not too difficult.

How would the farmer be challenged if she doesn’t have the proof of time?
I understand that this is related to the issue you raised, but you seem to also say that this is how it works now:

No proof - no time slot, so farmer will have to wait for proof to arrive (or produce it locally). Since proofs are typically known a bit into the future, this shouldn’t be an issue on production network.

One side effect I thought of just now is that since proofs are available into the future, we basically have a different notion of block production.

Faster farmers will be able to produce blocks a bit sooner than other, essentially “winning” the fork choice rule in case more than one block is produced for the same time slot.

Not sure if it actually makes sense considering they may not be able to collect as much fees as they would otherwise, but something to think about.

This point has been raised. Since Nakamoto-style consensus is a race, it is not a rational strategy to wait, and therefore the client for farmers should not follow it. Consider it the desired behaviour as I do understand that currently it’s not implemented like that.

I guess that if waiting is important, we can enforce a rule that blocks should solve on challenge n but also include in the header the proof of time/challenge for n+delay. Just an idea, it’s a bit off, and not straightforward that it works (it’s just an artificial value, and perhaps farmers, know they already won, will try to send their block even without the other challenge…).

It is actually somewhat similar to getting parent block early, which is a disadvantage in Nakamoto-style consensus for sure, but it is kind of inherent to the design. It is worse in our case due to short block interval.

We can also do something like rejecting blocks for which we don’t see n+delay proof yet, meaning it was announced too early, but that is probably not going to work very well.

We may remove the reveal delay if we let farmers claim slots a little in the past. However, faster farmers will still be able to solve faster anyway.