Neptune-Crypto / neptune-core

anonymous peer-to-peer cash
Apache License 2.0
25 stars 7 forks source link

Reject future blocks #104

Open Sword-Smith opened 8 months ago

Sword-Smith commented 8 months ago

Currently the block validation logic does not check that the block does not have a future timestamp. That check should be added.

This is a check that doesn't not involve the virtual machine. The timestamp field is simply compared to what the hast machine's OS reports being the time. This check should be run by the peer thread but could, in my opinion, be placed in the is_valid function in src/models/blockchain/block/mod.rs.

dan-da commented 7 months ago

A simple check if the timestamp is in the future would create likely create consensus problems, at least temporarily.

Node A's clock is 3 seconds ahead of Node B. A mines a block, notifies B, and B rejects it. Meanwhile nodes C, D, E, and F accept it because their clocks are all synced well. Later C mines a block, and notifies B. B also rejects this block. Later D mines a block, and network hops delay it by 3 seconds, so when it gets to B, B accepts it, and thus also accepts the blocks mined by A and C, finally catching up with the network.

So it seems like we need to be careful and probably should allow some window into the future.

Bitcoin's approach:

A timestamp is accepted as valid if it is greater than the median timestamp of previous 11 blocks, and less than the network-adjusted time + 2 hours. "Network-adjusted time" is the median of the timestamps returned by all nodes connected to you. As a result block timestamps are not exactly accurate, and they do not need to be. Block times are accurate only to within an hour or two.

Whenever a node connects to another node, it gets a UTC timestamp from it, and stores its offset from node-local UTC. The network-adjusted time is then the node-local UTC plus the median offset from all connected nodes. Network time is never adjusted more than 70 minutes from local system time, however.

Ok, so interesting points:

afaik, we do not (yet?) have this concept of network-adjusted time.

My thought is to impl this in two phases:

phase 1: block timestamp must be less than host-time + 2 hours (and greater than last-block timestamp) phase 2: block timestamp must be less than network-adjusted-time + 2 hours (and greater than last-block timestamp)

So I can make a quick commit that just does the host-time + 2 hours check, and impl the network-adjusted time later, once agreed upon. That will be a bigger change/feature.

dan-da commented 7 months ago

commit 0c0e2c5fa6f7890acaeed3b81f1b7e7449637507 implements phase 1.

block timestamp must be less than host-time + 2 hours. with test-case.

aszepieniec commented 7 months ago

Network time is never adjusted more than 70 minutes from local system time, however.

This rule may seem innocuous, but is key!

If it were not present, it would expose the network to a sybil attack. Flood the network with cheap nodes under your control. Once you have 51% of the nodes (not hashpower!) you effectively control the network-adjusted time and then you can release your longer chain which you were only able to compute because of downward adjustments of the difficulty due to timestamp spoofing.

dan-da commented 7 months ago

A timestamp is accepted as valid if it is greater than the median timestamp of previous 11 blocks

At present we just check if the block's timestamp is greater than previous block's timestamp.

Given that miners' clocks may have some variation, that might be problematic...? I haven't really thought through the possible scenarios though.

@aszepieniec @Sword-Smith do you have thoughts/analysis on bitcoin's past-11-blocks-average approach vs our present approach?

Another wrinkle, I think light-nodes would not have access to the past 11 blocks...?