stacks-network / stacks-core

The Stacks blockchain implementation
https://docs.stacks.co
GNU General Public License v3.0
3.01k stars 668 forks source link

Nakamoto: Add timestamp to block headers #4541

Closed kantai closed 4 months ago

kantai commented 7 months ago

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 commented 7 months ago

Relevant: https://github.com/stacks-network/stacks-core/issues/4220

jcnelson commented 7 months ago

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:

kantai commented 7 months ago

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 commented 7 months ago

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 commented 7 months ago

Consensus breaking for 3.0

cylewitruk commented 7 months ago

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 commented 7 months ago

Can we just copy what Bitcoin or Ethereum do?

kantai commented 7 months ago

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 commented 6 months ago

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 commented 6 months ago

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 commented 6 months ago

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 commented 6 months ago

+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 commented 6 months ago

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 commented 6 months ago

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 commented 6 months ago

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 :grin:).

Thank you for consistently improving our tooling

friedger commented 6 months ago

Added Addendum to SIP 21 including time on stacks block level: https://github.com/stacksgov/sips/pull/178

obycode commented 5 months ago

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

obycode commented 5 months ago

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 commented 5 months ago

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 commented 5 months ago

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 commented 5 months ago

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.

blockstack-devops commented 1 week ago

This issue has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.