Fish Improvement Proposal Process

FIP-2 Enforce Sequential Block Time

description

Restrict block header from having timestamp earlier than previous block.

authors

ygao76

discussion

https://discourse.ironfish.network/t/proposal-restrict-block-from-having-timestamp-earlier-than-previous-block/50

status

Last Call

category

Core

created

2023-7-19

Abstract 

To handle the common problems of clock unsynchronization among the servers, current Iron Fish's consensus allows blocks with timestamps that are earlier than timestamps from previous blocks. Miners are incentivized to exploit it by manipulating the block timestamps to consistently gain more mining rewards. I propose to update the block header verification in the consensus layer to enforce sequential block timestamps in the same order as the block sequences.

Motivation 

Currently, Iron Fish’s consensus allows a 15 seconds grace period window when verifies the timestamp of a new block. The new block is considered valid if its timestamp falls between the timestamp of previous block minus the grace period and the timestamp of the moment when verification happens plus the grace period. This grace period is to handle the common problems of clock unsynchronization among the servers, for example clock drifting and clock skews. This design allows new block with timestamps that are earlier than timestamps from previous blocks, which leads to the possibility of negative block mine time. There is speculation among miners that negative block mine time can potentially manipulate the mining difficulty. People believe that the ability to creat a block with negative mine time gives these miners an edge in a “tie-breaking” scenario since making the timestamp low enough might increase the block’s mining difficulty. Miners are incentivized to set the timestamp as early as possible to gain the system with possible more mining rewards.

This negative mine time in the block header causes confusion for users. For example, in Iron Fish block explorer, It will cause negative duration for the ‘Mined In’ column in The Iron Fish block explorer. The same issue exists for the Oreoscan. In Iron Fish CLI, it also uses the block timestamp to display the time a transaction occurred in wallet:transactions, this led to less reliable creation time for transactions.

Specification 

Block header timestamp Timestamp according to the miner who mined the block. The timestamp is in millisecond. Miners must verify that it is an appropriate distance to the previous blocks timestamp.

Block mine time This is calculated from the interval of the current block timestamp from the previous block timestamp. When the timestamp of the current block header is earlier than the timestamp of the previous block, it will result in negative block mine time.

I propose following two changes to address the negative block mine time problem

Change block header verification in Consensus 

Only allow block header with a timestamp greater than the timestamp of the previous block. The block header verification in the consensus will consider a block header is valid only if block_header(n).timestamp > block_header(n-1).timestamp.

Change new block template in Mining Manager 

When the mining manager creates a new block template, the timestamp for the new block will be adjusted to comply with the new rule. For the official mining manager, it will use both the previous block timestamp and current time when calculating the timestamp in the new block template. This way also allows us to avoid the potential issue caused by clocks not synced across servers. This change will not be protected by the block sequence condition since this change only affects new blocks.

For mining pools using non official mining managers, they will have to change their logic of setting the timestamp in the new block template to comply with the new rule.

Backwards Compatibility 

The proposed consensus change will support backward compatibility. For all the existing blocks with negative mine times, they are still valid and not affected by the new rule. To achieve backward compatibility, the new rule will be enforced based on the block sequence. This block sequence that turns on the new rule will be decided in a hard fork upgrade proposal.

Reference Implementation 

Consensus 

  • Block header verifies the block timestamp > the timestamp of the previous block.

Current

if (
      current.timestamp.getTime() <
      previousHeader.timestamp.getTime() -
        this.chain.consensus.parameters.allowedBlockFutureSeconds * 1000
    ) {
      return { valid: false, reason: VerificationResultReason.BLOCK_TOO_OLD }
    }

New

if (
      current.timestamp.getTime() <=
      previousHeader.timestamp.getTime() 
    ) {
      return { valid: false, reason: VerificationResultReason.BLOCK_TOO_OLD }
    }
  • Enforce the new rule by checking the block sequence to achieve backward compatible

Define the block sequence at which the new rule will start to apply

export type ConsensusParameters = {
   // new parameter
   /**
   * Before upgrade we have block timestamp smaller than previous block. After this
   * block we enforce the block timestamps in the sequential order as the block sequences.
   */
   enforceSequentialBlockTime: number
}

Condition to apply the new rule

if (
      this.chain.consensus.isActive(this.chain.consensus.enforceSequentialBlockTime, block.header.sequence)
    ) {
		// apply the new rule
}else{
    // apply the existing rule
}

Mining Manager 

  • When mining manager creates a new block template, the timestamp for the new block will be adjusted to comply with the new rule

Current

const header = new BlockHeader(
        previousSequence + 1,
        previousBlockHash,
        noteCommitment,
        transactionCommitment(transactions),
        target,
        BigInt(0),
        new Date(Date.now()),
        graffiti,
        noteSize,
        BigInt(0),
      )

New

const timestamp = new Date(Date.now())
const header = new BlockHeader(
        previousSequence + 1,
        previousBlockHash,
        noteCommitment,
        transactionCommitment(transactions),
        target,
        BigInt(0),
        Math.max(timestamp, previous.timestamp + 1 (millisecond)),
        graffiti,
        noteSize,
        BigInt(0),
      )

Copyright 

Copyright and related rights waived via CC0.

Edit on Github

Join our newsletter and stay up to date with privacy and crypto.

Learn

  • FAQ
  • Whitepaper
  • Tokenomics
  • Blog

Use

  • Get Started
  • Node App
  • Mine
  • Block Explorer
  • Ecosystem

Developers

  • Documentation
  • Github

Community

  • Highlights
  • Media
  • Community Wiki
  • Our community

IF Labs

  • About Us
  • Media Kit
  • Contact Us
Privacy Policy

|

Copyright 2024 Iron Fish.