FIP-2 Enforce Sequential Block Time
description
Restrict block header from having timestamp earlier than previous block.
authors
ygao76
discussion
status
Final
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.
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
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.