Gno: An interpreted, stack-based Go virtual machine to build succinct and composable apps + gno.land: a blockchain for timeless code and fair open-source.
In gnodev, the reload operation replays all the transactions. In general this lets the realm functions restore the state. But if some realm functions use time.Now() then this returns the (arbitrary) time of reload, not the time of the original transaction. Therefore, reload does not actually restore the state.
The boards realm uses time.Now() for the displayed post time. Reload should restore the realm state including timestamps from time.Now()
Actual behaviour
The timestamps of all message have the time of reload, erasing important information. This is because to reload gnodev resends the transactions where the block time is the current time of reload. This same timestamp is returned by every call to time.Now() .
(Related, the boards realm in testnet3 was built by replaying transactions, similarly to gnodev reload. The original message timestamps are erased and are set to the same value "2023-08-18 11:44am UTC". https://test3.gno.land/r/demo/boards:testboard .)
Proposed solution
One possible solution: The transaction processing code should have an option to specify the block time. Instead of using a high-level broadcast during replay, gnodev should call the lower-level transaction processing code and supply the correct timestamp of the original transaction. This will be used by time.Now().
Here are the message times before reload:
Here is where all timestamps are reset after reload:
⚠️ Risks and impact if not fixed
A realm developer can't use gnodev with any realm that relies on time.Now(). For example:
Timestamps on posted messages, or any time-based calculations like "number if messages in the last day".
There are hacks to avoid using time.Now() but they introduce security risks of not having reliable timestamps from the transaction.
The long-term technique to do realm versioning may also solve this problem by replaying transactions, and so this also needs to be addressed in this case.
In gnodev, preserve time.Now() values on reload
Description
In gnodev, the reload operation replays all the transactions. In general this lets the realm functions restore the state. But if some realm functions use
time.Now()
then this returns the (arbitrary) time of reload, not the time of the original transaction. Therefore, reload does not actually restore the state.Your environment
Steps to reproduce
CreateThread
as follows:Expected behaviour
The boards realm uses
time.Now()
for the displayed post time. Reload should restore the realm state including timestamps fromtime.Now()
Actual behaviour
The timestamps of all message have the time of reload, erasing important information. This is because to reload gnodev resends the transactions where the block time is the current time of reload. This same timestamp is returned by every call to
time.Now()
.(Related, the boards realm in testnet3 was built by replaying transactions, similarly to gnodev reload. The original message timestamps are erased and are set to the same value "2023-08-18 11:44am UTC". https://test3.gno.land/r/demo/boards:testboard .)
Proposed solution
One possible solution: The transaction processing code should have an option to specify the block time. Instead of using a high-level broadcast during replay, gnodev should call the lower-level transaction processing code and supply the correct timestamp of the original transaction. This will be used by
time.Now()
.Here are the message times before reload:
Here is where all timestamps are reset after reload:
⚠️ Risks and impact if not fixed
A realm developer can't use gnodev with any realm that relies on
time.Now()
. For example:time.Now()
but they introduce security risks of not having reliable timestamps from the transaction.