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

Upgrade network so that valid block timestamps must be greater than the previous block #1889

Open
bitcartel opened this Issue Nov 20, 2016 · 27 comments

Comments

Projects
@bitcartel
Contributor

bitcartel commented Nov 20, 2016

Evaluate moving to an Ethereum style model of acceptable block timestamps, where in Ethereum:

  1. A valid block timestamp must be greater than previous block timestamp
  2. It must also be less than 900 seconds (15 minutes) into the future from current time.

http://ethereum.stackexchange.com/questions/5924/how-do-ethereum-mining-nodes-maintain-a-time-consistent-with-the-network

Ethereum nodes make use of NTP servers to stay in sync and adjust for clock drift:
http://www.pool.ntp.org/en/

@zookozcash

This comment has been minimized.

Show comment
Hide comment
@zookozcash

zookozcash Nov 20, 2016

I don't want to require Zcash nodes to rely on NTP, but I think this proposal would not require that of them. They could use some other mechanism of setting their clock, or they could actually use the timestamps from the Zcash blockchain to set their clock.

zookozcash commented Nov 20, 2016

I don't want to require Zcash nodes to rely on NTP, but I think this proposal would not require that of them. They could use some other mechanism of setting their clock, or they could actually use the timestamps from the Zcash blockchain to set their clock.

@str4d

This comment has been minimized.

Show comment
Hide comment
@str4d

str4d Nov 21, 2016

Contributor

My initial objection to this was that out-by-hour issues are quite common. However, it should actually be relatively easy for miners and pools to do:

nTime = max(GetTime(), prev->nTime+1)

to ensure that their times are always locally valid. So concept ACK.

Contributor

str4d commented Nov 21, 2016

My initial objection to this was that out-by-hour issues are quite common. However, it should actually be relatively easy for miners and pools to do:

nTime = max(GetTime(), prev->nTime+1)

to ensure that their times are always locally valid. So concept ACK.

@str4d

This comment has been minimized.

Show comment
Hide comment
@str4d

str4d Nov 21, 2016

Contributor

This could also be easily implemented from a consensus rule perspective, because the vast majority of miners are already submitting blocks that satisfy these rules. Implementation-wise it's going to take some work (as I know from I2P...)

Contributor

str4d commented Nov 21, 2016

This could also be easily implemented from a consensus rule perspective, because the vast majority of miners are already submitting blocks that satisfy these rules. Implementation-wise it's going to take some work (as I know from I2P...)

@sammy007

This comment has been minimized.

Show comment
Hide comment
@sammy007

sammy007 Nov 21, 2016

Smells like hard fork?

I don't want to require Zcash nodes to rely on NTP

There is only one requirement - rely on correct time.

sammy007 commented Nov 21, 2016

Smells like hard fork?

I don't want to require Zcash nodes to rely on NTP

There is only one requirement - rely on correct time.

@wangchun

This comment has been minimized.

Show comment
Hide comment
@wangchun

wangchun Nov 21, 2016

I am disappointed to see a proposal like this. It will NOT work and may open other issues. Satoshi initially designed ntime span for a reason. The easier solution might be to, instead of consider blocks [tip-17:tip-1], consider blocks [tip-18:tip-2].

wangchun commented Nov 21, 2016

I am disappointed to see a proposal like this. It will NOT work and may open other issues. Satoshi initially designed ntime span for a reason. The easier solution might be to, instead of consider blocks [tip-17:tip-1], consider blocks [tip-18:tip-2].

@bitcartel

This comment has been minimized.

Show comment
Hide comment
@bitcartel

bitcartel Nov 21, 2016

Contributor

@sammy007 @wangchun Just brainstorming at the moment. All feedback welcome.

Contributor

bitcartel commented Nov 21, 2016

@sammy007 @wangchun Just brainstorming at the moment. All feedback welcome.

@bitcartel

This comment has been minimized.

Show comment
Hide comment
@bitcartel

bitcartel Nov 21, 2016

Contributor

@vbuterin How has Ethereum's block timestamp worked out in production? Any lessons to be learned? If you could, what would you change today?

Contributor

bitcartel commented Nov 21, 2016

@vbuterin How has Ethereum's block timestamp worked out in production? Any lessons to be learned? If you could, what would you change today?

@str4d

This comment has been minimized.

Show comment
Hide comment
@str4d

str4d Nov 21, 2016

Contributor

Smells like hard fork?

My comment #1889 (comment) was saying that this wouldn't require a "hard" fork, because it would be making previously-valid blocks invalid. But even if it did, that's fine - we're already considering other forking upgrades.

There is only one requirement - rely on correct time.

Easier said than done, unfortunately... As discussed in the Chrome talk at RWC 2016, one of the top contributors to SSL certificate errors they see is discrepancies between client and server clocks, with IIRC a spike around an hour difference. So you either have to allow for significant discrepancies (as Bitcoin does), or run your own time-management system (as Ethereum and I2P do).

Contributor

str4d commented Nov 21, 2016

Smells like hard fork?

My comment #1889 (comment) was saying that this wouldn't require a "hard" fork, because it would be making previously-valid blocks invalid. But even if it did, that's fine - we're already considering other forking upgrades.

There is only one requirement - rely on correct time.

Easier said than done, unfortunately... As discussed in the Chrome talk at RWC 2016, one of the top contributors to SSL certificate errors they see is discrepancies between client and server clocks, with IIRC a spike around an hour difference. So you either have to allow for significant discrepancies (as Bitcoin does), or run your own time-management system (as Ethereum and I2P do).

@zookozcash

This comment has been minimized.

Show comment
Hide comment
@zookozcash

zookozcash Nov 21, 2016

@wangchun: why won't the proposal in #1889 (comment) work and what other issues could it raise?

zookozcash commented Nov 21, 2016

@wangchun: why won't the proposal in #1889 (comment) work and what other issues could it raise?

@zookozcash

This comment has been minimized.

Show comment
Hide comment
@zookozcash

zookozcash Nov 21, 2016

There is only one requirement - rely on correct time.

I strongly believe we should not require this! I think it is both expensive/difficult/impossible to achieve, and also unnecessary.

zookozcash commented Nov 21, 2016

There is only one requirement - rely on correct time.

I strongly believe we should not require this! I think it is both expensive/difficult/impossible to achieve, and also unnecessary.

@bitcartel

This comment has been minimized.

Show comment
Hide comment
@bitcartel

bitcartel Nov 21, 2016

Contributor

To avoid DST issues, let's ensure:

  • the code always asks the operating system for time in UTC
  • the code always converts to and from unix timestamps in UTC rather than local time

We can use several sources of time when a new block arrives:

Some security concerns:

Contributor

bitcartel commented Nov 21, 2016

To avoid DST issues, let's ensure:

  • the code always asks the operating system for time in UTC
  • the code always converts to and from unix timestamps in UTC rather than local time

We can use several sources of time when a new block arrives:

Some security concerns:

@zookozcash

This comment has been minimized.

Show comment
Hide comment
@vbuterin

This comment has been minimized.

Show comment
Hide comment
@vbuterin

vbuterin Nov 22, 2016

It's worked fairly well for us so far; setting timestamp to min(now, parent.timestamp + 1) is precisely what miners do. We do have a warning message that triggers when a node connects and it looks like it's out of sync; in my experience it's happened a few times but when it has, a lot of the time the timestamp wasn't just a little bit off, it was way off (eg. 8 hours) due to timezone changes. You probably don't want to rely on NTP exclusively; if a node is online you can rely on a combination of sources including NTP, timestamps of blocks, timestamps of peers on the network, etc.

This should not require a hard fork; the Satoshian scheme is strictly looser than the Ethereum scheme on both sides (if timestamps are increasing, then each timestamp is bigger than the previous median, and if a timestamp is less than the current time, it's less than the current time + 2 hours), so changing over would be a soft fork.

vbuterin commented Nov 22, 2016

It's worked fairly well for us so far; setting timestamp to min(now, parent.timestamp + 1) is precisely what miners do. We do have a warning message that triggers when a node connects and it looks like it's out of sync; in my experience it's happened a few times but when it has, a lot of the time the timestamp wasn't just a little bit off, it was way off (eg. 8 hours) due to timezone changes. You probably don't want to rely on NTP exclusively; if a node is online you can rely on a combination of sources including NTP, timestamps of blocks, timestamps of peers on the network, etc.

This should not require a hard fork; the Satoshian scheme is strictly looser than the Ethereum scheme on both sides (if timestamps are increasing, then each timestamp is bigger than the previous median, and if a timestamp is less than the current time, it's less than the current time + 2 hours), so changing over would be a soft fork.

@daira

This comment has been minimized.

Show comment
Hide comment
@daira

daira Nov 22, 2016

Contributor

This ticket was reported in http://www.newsbtc.com/2016/11/21/zcash-developers-contemplate-switch-ethereum-based-block-timestamping/ as if it were something we'd already decided on (and referring to it as a "new block timestamping protocol", which is rather over-egging the scope of the potential change). The article also totally incorrectly says "This should speed up the ZEC block generation, as timestamps are less than 15 minutes apart from another." No change in target block time is proposed here.

Journalists and readers should be aware that we often discuss speculative changes on this issue tracker. It's an issue tracker, that's what it's for. :eyeroll:

Contributor

daira commented Nov 22, 2016

This ticket was reported in http://www.newsbtc.com/2016/11/21/zcash-developers-contemplate-switch-ethereum-based-block-timestamping/ as if it were something we'd already decided on (and referring to it as a "new block timestamping protocol", which is rather over-egging the scope of the potential change). The article also totally incorrectly says "This should speed up the ZEC block generation, as timestamps are less than 15 minutes apart from another." No change in target block time is proposed here.

Journalists and readers should be aware that we often discuss speculative changes on this issue tracker. It's an issue tracker, that's what it's for. :eyeroll:

@daira

This comment has been minimized.

Show comment
Hide comment
@daira

daira Nov 22, 2016

Contributor

Tentative concept ACK for tightening the block timestamp rules.

Contributor

daira commented Nov 22, 2016

Tentative concept ACK for tightening the block timestamp rules.

@daira

This comment has been minimized.

Show comment
Hide comment
@daira

daira Nov 22, 2016

Contributor

Note that Ethereum apparently doesn't have the 15-minute rule mentioned. Also, I think that we need to be clear on standard vs consensus rules. A rule based on local time can't be a consensus rule, it can only be a standard rule (which probably influenced Ethereum's decision to drop that rule in the Yellow Paper).

Contributor

daira commented Nov 22, 2016

Note that Ethereum apparently doesn't have the 15-minute rule mentioned. Also, I think that we need to be clear on standard vs consensus rules. A rule based on local time can't be a consensus rule, it can only be a standard rule (which probably influenced Ethereum's decision to drop that rule in the Yellow Paper).

@bitcartel

This comment has been minimized.

Show comment
Hide comment
@bitcartel

bitcartel Nov 22, 2016

Contributor

@daira The 15-minute rule made it into the white paper https://github.com/ethereum/wiki/wiki/White-Paper

Check that the timestamp of the block is greater than that of the referenced previous block and less than 15 minutes into the future

But not into the code, here https://github.com/ethereum/go-ethereum/blob/master/core/block_validator.go#L220

if header.Time.Cmp(parent.Time) != 1 {
return BlockEqualTSErr
}

and here https://github.com/ethereum/cpp-ethereum/blob/develop/libethcore/BlockHeader.cpp#L169

if (m_timestamp <= _parent.m_timestamp)
BOOST_THROW_EXCEPTION(InvalidTimestamp());

@vbuterin Is it documented anywhere why the 15 minute rule was dropped? Thanks.

Contributor

bitcartel commented Nov 22, 2016

@daira The 15-minute rule made it into the white paper https://github.com/ethereum/wiki/wiki/White-Paper

Check that the timestamp of the block is greater than that of the referenced previous block and less than 15 minutes into the future

But not into the code, here https://github.com/ethereum/go-ethereum/blob/master/core/block_validator.go#L220

if header.Time.Cmp(parent.Time) != 1 {
return BlockEqualTSErr
}

and here https://github.com/ethereum/cpp-ethereum/blob/develop/libethcore/BlockHeader.cpp#L169

if (m_timestamp <= _parent.m_timestamp)
BOOST_THROW_EXCEPTION(InvalidTimestamp());

@vbuterin Is it documented anywhere why the 15 minute rule was dropped? Thanks.

@nathan-at-least

This comment has been minimized.

Show comment
Hide comment
@nathan-at-least

nathan-at-least Jan 9, 2017

Contributor

Upgrading to this rule requires care, and may need signaling for a soft-fork upgrade behavior, or some kind of hard-fork coordination, etc…

Contributor

nathan-at-least commented Jan 9, 2017

Upgrading to this rule requires care, and may need signaling for a soft-fork upgrade behavior, or some kind of hard-fork coordination, etc…

@tromer

This comment has been minimized.

Show comment
Hide comment
@tromer

tromer Jan 9, 2017

Contributor

Note that keeping an adequate relation between block timestamps and the "real" (wall clock) time is important not just for difficulty adjustment, but also for transaction lock time to have useful semantics.

Contributor

tromer commented Jan 9, 2017

Note that keeping an adequate relation between block timestamps and the "real" (wall clock) time is important not just for difficulty adjustment, but also for transaction lock time to have useful semantics.

@zookozcash

This comment has been minimized.

Show comment
Hide comment
@zookozcash

zookozcash Jan 9, 2017

I'd like to have #1924 running for a while, reliable, and showing a history of past behavior before we deploy any change along these lines.

zookozcash commented Jan 9, 2017

I'd like to have #1924 running for a while, reliable, and showing a history of past behavior before we deploy any change along these lines.

@zookozcash

This comment has been minimized.

Show comment
Hide comment
@zookozcash

zookozcash Jan 9, 2017

I think it is a mistake to conflate "my local clock is synced to 'the real time'" with "my local clock is running at approximately the right speed". I think the latter (my clock runs about approximately the right speed) is necessary and sufficient for the requirements and issues mentioned above (#1889 (comment), #1889 (comment), and "time-warping"). I think that the former assumption (my clock is approximately on the real time) is impossible to ensure in theory (except with a blockchain!), and that relying on the former assumption will, in practice, give high-powered, large-scale attackers (i.e. those who can control widely-trusted NTP servers or attack the NTP protocol) the opportunity to attack our blockchain.

Just to hammer the point home, here it is again in compressed form:

property: "right time", necessary: "no", allows attacks: "yes"
property: "right speed", necessary: "yes", allows attacks: "no"

zookozcash commented Jan 9, 2017

I think it is a mistake to conflate "my local clock is synced to 'the real time'" with "my local clock is running at approximately the right speed". I think the latter (my clock runs about approximately the right speed) is necessary and sufficient for the requirements and issues mentioned above (#1889 (comment), #1889 (comment), and "time-warping"). I think that the former assumption (my clock is approximately on the real time) is impossible to ensure in theory (except with a blockchain!), and that relying on the former assumption will, in practice, give high-powered, large-scale attackers (i.e. those who can control widely-trusted NTP servers or attack the NTP protocol) the opportunity to attack our blockchain.

Just to hammer the point home, here it is again in compressed form:

property: "right time", necessary: "no", allows attacks: "yes"
property: "right speed", necessary: "yes", allows attacks: "no"

@tromer

This comment has been minimized.

Show comment
Hide comment
@tromer

tromer Jan 9, 2017

Contributor

@zookozcash , transaction lock time may be expressed in two ways (depending on whether it's above the 500000000 threshold):

  • as block height, for which it's plausible that "right speed" suffices (we just need difficulty adjustment, hence block pacing, to work well enough)
  • as UNIX timestamp, for which it's necessary for the majority of miners to have an adequate "right time"
Contributor

tromer commented Jan 9, 2017

@zookozcash , transaction lock time may be expressed in two ways (depending on whether it's above the 500000000 threshold):

  • as block height, for which it's plausible that "right speed" suffices (we just need difficulty adjustment, hence block pacing, to work well enough)
  • as UNIX timestamp, for which it's necessary for the majority of miners to have an adequate "right time"
@bitcartel

This comment has been minimized.

Show comment
Hide comment
@bitcartel

bitcartel Jan 10, 2017

Contributor

Some analysis of 42000 blocks:

  • number of blocks mined where timestamp is earlier than one or more previous block = 6271 (14.93%)
  • total number of previous blocks = 19654 (46.80%)
  • longest chain of previous blocks = 5
  • largest negative time delta between block and previous block = 4418 secs
Contributor

bitcartel commented Jan 10, 2017

Some analysis of 42000 blocks:

  • number of blocks mined where timestamp is earlier than one or more previous block = 6271 (14.93%)
  • total number of previous blocks = 19654 (46.80%)
  • longest chain of previous blocks = 5
  • largest negative time delta between block and previous block = 4418 secs
@daira

This comment has been minimized.

Show comment
Hide comment
@daira

daira Jan 10, 2017

Contributor

Recall that the proposed rules are:

  1. A valid block timestamp must be greater than previous block timestamp
  2. It must also be less than 900 seconds (15 minutes) into the future from current time.

Rule 2 cannot be a consensus rule because it mentions current time. So I'm going to interpret it as a rule about what blocks the reference miner will mine on top of.

A potential problem I see is that rule 2 is not incentive-compatible -- a miner gains no advantage from enforcing it, and in fact potentially loses the opportunity to build on a chain that had greater total work. So it is quite possible that non-reference miners will not enforce this rule.

This means that the block timestamps will tend to creep up relative to UTC, since there is nothing to prevent this from happening if only a minority of miners enforce rule 2.

Contributor

daira commented Jan 10, 2017

Recall that the proposed rules are:

  1. A valid block timestamp must be greater than previous block timestamp
  2. It must also be less than 900 seconds (15 minutes) into the future from current time.

Rule 2 cannot be a consensus rule because it mentions current time. So I'm going to interpret it as a rule about what blocks the reference miner will mine on top of.

A potential problem I see is that rule 2 is not incentive-compatible -- a miner gains no advantage from enforcing it, and in fact potentially loses the opportunity to build on a chain that had greater total work. So it is quite possible that non-reference miners will not enforce this rule.

This means that the block timestamps will tend to creep up relative to UTC, since there is nothing to prevent this from happening if only a minority of miners enforce rule 2.

@nathan-at-least

This comment has been minimized.

Show comment
Hide comment
@nathan-at-least

nathan-at-least Jan 17, 2017

Contributor

Note, I've added #2022 which would make future empirical analysis of this kind of issue easier by providing useful local time data.

Contributor

nathan-at-least commented Jan 17, 2017

Note, I've added #2022 which would make future empirical analysis of this kind of issue easier by providing useful local time data.

@jordanmack

This comment has been minimized.

Show comment
Hide comment
@jordanmack

jordanmack Jan 19, 2017

  1. A valid block timestamp must be greater than previous block timestamp
  2. It must also be less than 900 seconds (15 minutes) into the future from current time.

If rule 1 was a consensus rule, miners are forced to use max(now, parent.timestamp + 1) to avoid blocks being rejected. This will eventually inch the time closer to being back on track, but now the time lapsed between two blocks would again be inaccurate. If number 2 is is not a consensus rule, an incorrect date could lead to a scenario where the timestamp is thrown far into the future. You would then have a continuous string of blocks with a timestamp of parent.timestamp + 1, until the current date caught up.

Enforcement of a tighter time window just complicates things. Rather than trying to enforce a time window to prevent an incorrect local timestamp, what if you remove the consensus rules for the timestamp completely, then change the reference miner to use the network adjusted time for block timestamps and ignore the local time completely? To make the network adjusted time less prone to being thrown off by an incorrect date, only include timestamps within a standard deviation range to be included in the median. The network adjusted time should then typically be accurate within a few seconds of NTP. Even if a miner with a completely wrong date was to find a block, the block timestamp would still be correct. There would be no incentive for timejacking attempts since there would be no consensus rule in play to reject a bad timestamp.

jordanmack commented Jan 19, 2017

  1. A valid block timestamp must be greater than previous block timestamp
  2. It must also be less than 900 seconds (15 minutes) into the future from current time.

If rule 1 was a consensus rule, miners are forced to use max(now, parent.timestamp + 1) to avoid blocks being rejected. This will eventually inch the time closer to being back on track, but now the time lapsed between two blocks would again be inaccurate. If number 2 is is not a consensus rule, an incorrect date could lead to a scenario where the timestamp is thrown far into the future. You would then have a continuous string of blocks with a timestamp of parent.timestamp + 1, until the current date caught up.

Enforcement of a tighter time window just complicates things. Rather than trying to enforce a time window to prevent an incorrect local timestamp, what if you remove the consensus rules for the timestamp completely, then change the reference miner to use the network adjusted time for block timestamps and ignore the local time completely? To make the network adjusted time less prone to being thrown off by an incorrect date, only include timestamps within a standard deviation range to be included in the median. The network adjusted time should then typically be accurate within a few seconds of NTP. Even if a miner with a completely wrong date was to find a block, the block timestamp would still be correct. There would be no incentive for timejacking attempts since there would be no consensus rule in play to reject a bad timestamp.

@bitcartel

This comment has been minimized.

Show comment
Hide comment
@bitcartel

bitcartel Feb 23, 2017

Contributor

Testnet first 42000 blocks:

  • number of blocks mined where timestamp is earlier than one or more previous block = 279 (0.66%)
  • total number of previous blocks = 294 (0.70%)
  • longest chain of previous blocks = 5
  • largest negative time delta between block and previous block = 202 secs

By comparison, Mainnet first 42000 blocks (14.93% and 46.80%) #1889 (comment)

Contributor

bitcartel commented Feb 23, 2017

Testnet first 42000 blocks:

  • number of blocks mined where timestamp is earlier than one or more previous block = 279 (0.66%)
  • total number of previous blocks = 294 (0.70%)
  • longest chain of previous blocks = 5
  • largest negative time delta between block and previous block = 202 secs

By comparison, Mainnet first 42000 blocks (14.93% and 46.80%) #1889 (comment)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment