Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Nakamoto: Add timestamp to block headers #4541

Open
kantai opened this issue Mar 14, 2024 · 21 comments
Open

Nakamoto: Add timestamp to block headers #4541

kantai opened this issue Mar 14, 2024 · 21 comments

Comments

@kantai
Copy link
Member

kantai commented Mar 14, 2024

In Stacks 2.x, Stacks blocks do not have a timestamp. This is okay because they correspond directly with bitcoin blocks, so they can be thought of as occurring at the associated bitcoin block's timestamp. In Nakamoto, this is no longer the case, so we should add a timestamp field to the Stacks block. This timestamp's relative accuracy can even be checked by signers.

My proposal is to understand timestamps as:

  1. A positive value greater than the block's associated burn block (i.e., the timestamp must be greater than the timestamp of the burn block whose consensus_hash = block.consensus_hash).
  2. Increasing between a tenure's blocks: a given miner should never build a block B off of block A with a smaller timestamp.
@kantai
Copy link
Member Author

kantai commented Mar 14, 2024

Relevant: #4220

@jcnelson
Copy link
Member

A positive value greater than the block's associated burn block (i.e., the timestamp must be greater than the timestamp of the burn block whose consensus_hash = block.consensus_hash).

I'm not sure that this is desirable? Bitcoin block timestamps can vary substantially, and I don't think they even need to increase monotonically (see https://en.bitcoin.it/wiki/Block_timestamp). This criterion would magnify that problem for Stacks blocks -- we'd have entire tenures of blocks whose timestamps would be monotonically increasing within the tenure, but could also be ahead of their children blocks' timestamps.


Broadly speaking, I think if we want a Stacks-specific timestamp above and beyond Bitcoin, we would be better off if we did one of the following:

  • Disregard Bitcoin timestamps altogether, and include something like the median UTC timestamp of all signers' times in the block. Each signer's UTC time is included as part of the signing round data.

  • Don't record an absolute block time in Stacks blocks, but instead add a relative blocktime (e.g. this block was produced XXX seconds after the tenure began).

  • Don't do anything time-related, and instead expose the relative sequence of the block in the tenure. Users can figure out from the Bitcoin block time arrival and the target block production rate what the approximate block timestamp is.

@kantai
Copy link
Member Author

kantai commented Mar 14, 2024

I think the miner should set the timestamp and signers can just validate it -- trying to get this information from the signers to the miner before they assemble the block seems too complicated to be worthwhile.

I think to keep things simpler, I'd suggest two other options:

  1. There's two constraints on the timestamp: it must be greater than its parent block's timestamp, and it cannot be more than 30 seconds in the future from now. Signers will simply not approve a block with a timestamp later than that (they will use their local clock).
  2. There's no constraints whatsoever on the timestamp. It's essentially just a number picked by the miner.

@hstove
Copy link
Contributor

hstove commented Mar 14, 2024

Don't record an absolute block time in Stacks blocks, but instead add a relative blocktime (e.g. this block was produced XXX seconds after the tenure began).

I think this makes sense, but it's also essentially equivalent to the original post's proposal. In both cases we can accept that a block's timestamp (either via an explicit timestamp, or via calculating burn time + diff) can be "backwards in time" relative to parent blocks.

@saralab
Copy link
Contributor

saralab commented Mar 15, 2024

Consensus breaking for 3.0

@cylewitruk
Copy link
Member

cylewitruk commented Apr 5, 2024

I +1 this for future investigation in reference to a number of related questions being asked on slack and discord. Wall-clock/calendar time can be a very valid use-case when it comes to monthly-related actions (i.e. subscription-based).

There's no need for the time accuracy to be on an atomic-clock level.

This could also be a general security measure for all nodes. In PCI-DSS environments, all nodes in the environment must be within Nms of eachother, otherwise they are dispelled from participating in serving requests. Similar requirements apply to TLS, etc.

So time synchronization between nodes really doesn't seem that unreasonable, and can be used as a security feature as well (maybe it's already done in some form, I'm not sure, do we use mTLS or similar?)

@zone117x
Copy link
Member

zone117x commented Apr 5, 2024

Can we just copy what Bitcoin or Ethereum do?

@kantai
Copy link
Member Author

kantai commented Apr 8, 2024

Can we just copy what Bitcoin or Ethereum do?

I think that's a good idea. All ethereum's consensus rules do is mandate that a block's timestamp be greater than the prior blocks. The default node implementations, though, reject any block further than 15 seconds into the future. Nakamoto could do something very similar: stacker/signers could refuse to sign any proposed block with a timestamp further than 15 seconds into the future.

@blaizew
Copy link

blaizew commented Apr 23, 2024

I'd like to boost this issue and highlight how beneficial a Nakamoto timestamp would be for DeFi teams building on Stacks. Timestamps are a standard component of DeFi-enabling blockchains bc they allow interest calculations without the imprecise guesswork of interpolating time based on block heights. Not having timestamps has created real complexities for existing DeFi teams that will negatively impact user experience, and will hinder future builders moving to Stacks from other ecosystems.

The current issues we face without timestamps are:
- Calculating interest: Interest calculations can only be as granular as the most-granular time source, which currently the last Bitcoin timestamp. Since Bitcoin timestamps are only accurate to within ~30 min and block times vary from 0-90 min, our granularity is limited to that time scale. Nakamoto does not increase this granularity since there is no requirement for a miner to produce a certain number of blocks (or any blocks) inside a given tenure. At best, this is a poor user experience; at worst, it could introduce attack vectors / MEV.
- Pyth price freshness: There is no way to know how fresh Pyth's price data is when it is delivered from the storage contract. The only control is that new price data will not be written to the storage contract if the attestation is >2h old, but we do not know the actual age of the price data the storage contract delivers since we have no time benchmark to compare it to. This may introduce MEV / attack vectors.

Both of these issues could be addressed with a timestamp on Nakamoto blocks.

@y0s0n
Copy link

y0s0n commented Apr 23, 2024

I echo the sentiment above from @blaizew . We are building Zest, a lending protocol on Stacks and interest calculations and good functionality on oracles are at the heart of building any money market applications. Timestamps would allow for feature parity with EVM lending protocols.

@renashah
Copy link

It seems like a non-starter for DeFi primitives to be built on stacks, which will be needed mainly to prevent attacks with malicious miners.

@muneeb-ali
Copy link
Member

+1 to timestamps. Seems necessary for DeFi apps.

In terms of how to implement these, my preference would be to go for something that is very simple and easy to implement.

@fiftyeightandeight
Copy link

Can we just copy what Bitcoin or Ethereum do?

I think that's a good idea. All ethereum's consensus rules do is mandate that a block's timestamp be greater than the prior blocks. The default node implementations, though, reject any block further than 15 seconds into the future. Nakamoto could do something very similar: stacker/signers could refuse to sign any proposed block with a timestamp further than 15 seconds into the future.

This makes sense to me too.

@hstove
Copy link
Contributor

hstove commented Apr 25, 2024

It's also important that we expose this in Clarity, likely via get-block-info?.

I think this implied but adding here to make sure we're tracking everything.

@jakob-btc
Copy link

I'm highly in favor of making reliable timestamps available with Nakamoto.

At Hermetica, native time-stamping would allow us to considerably streamline our smart contracts and remove or supplement critical dependencies on oracles (which have caused me a number of sleepless nights 😁).

Thank you for consistently improving our tooling

@friedger
Copy link
Collaborator

friedger commented May 7, 2024

Added Addendum to SIP 21 including time on stacks block level: stacksgov/sips#178

@obycode obycode self-assigned this May 16, 2024
@obycode
Copy link
Contributor

obycode commented May 16, 2024

Ok, I'm going to begin implementation work for this. Based on the discussions, I think the following seems like a reasonable solution:

  • The miner sets a Unix time timestamp in the block header (based on its own local clock)
  • Signers will validate the block if the timestamp is:
    • Greater than the timestamp of the previous block
    • Less than 15 seconds into the future (according to their local clocks)

@obycode
Copy link
Contributor

obycode commented May 16, 2024

Note that this ignores the Bitcoin block's timestamp, so there is no guaranteed correlation between the Bitcoin block's timestamp and the Stacks blocks timestamps.

@obycode
Copy link
Contributor

obycode commented May 16, 2024

The miner will set this timestamp before processing any transactions, so transactions can access the timestamp of the current block via Clarity's get-block-info? function.

@obycode
Copy link
Contributor

obycode commented Jun 3, 2024

The miner will set this timestamp before processing any transactions, so transactions can access the timestamp of the current block via Clarity's get-block-info? function.

I realized that the get-block-info? function can currently only be used for previous blocks, not the current block. If we decide to make the change to allow retrieving info for the current block (which should be possible with Nakamoto), this would be a new feature, so I will keep that separate from this change.

@obycode
Copy link
Contributor

obycode commented Jun 4, 2024

Additionally, get-block-info? includes fields that cannot be known until after the block is mined, so it does not make sense to retrieve info for the current block. This will be left as-is.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Status: Status: In Review
Development

No branches or pull requests