Skip to content

Commit

Permalink
common: Implement hardfork by time (#2437)
Browse files Browse the repository at this point in the history
* common: Implement hardfork by time

* fix the interface and add pass timestamp param

* fix eval

* fixes

* fix next nextHardforkBlock

* fix next hf

* fix shanghai time

* fix hf cond

* handle edgecase

* add some permuation combinations for two timestamp based hardforks

* fix blockchain checkAndTransition hardfork

* remove null/undefined hardforks from geth genesis while parsing

* address feedback

* incorp feedback

* improve wording

Co-authored-by: acolytec3 <[email protected]>

* Rename unofficial hardforks

Co-authored-by: acolytec3 <[email protected]>
  • Loading branch information
g11tech and acolytec3 authored Dec 14, 2022
1 parent 7e77b0f commit 1875375
Show file tree
Hide file tree
Showing 26 changed files with 2,064 additions and 82 deletions.
2 changes: 1 addition & 1 deletion packages/block/src/header.ts
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,7 @@ export class BlockHeader {

const hardforkByBlockNumber = options.hardforkByBlockNumber ?? false
if (hardforkByBlockNumber || options.hardforkByTTD !== undefined) {
this._common.setHardforkByBlockNumber(number, options.hardforkByTTD)
this._common.setHardforkByBlockNumber(number, options.hardforkByTTD, timestamp)
}

if (this._common.isActivatedEIP(1559) === true) {
Expand Down
12 changes: 8 additions & 4 deletions packages/blockchain/src/blockchain.ts
Original file line number Diff line number Diff line change
Expand Up @@ -275,7 +275,7 @@ export class Blockchain implements BlockchainInterface {
if (this._hardforkByHeadBlockNumber) {
const latestHeader = await this._getHeader(this._headHeaderHash)
const td = await this.getTotalDifficulty(this._headHeaderHash)
this.checkAndTransitionHardForkByNumber(latestHeader.number, td)
this.checkAndTransitionHardForkByNumber(latestHeader.number, td, latestHeader.timestamp)
}

this._isInitialized = true
Expand Down Expand Up @@ -498,7 +498,7 @@ export class Blockchain implements BlockchainInterface {
this._headBlockHash = blockHash
}
if (this._hardforkByHeadBlockNumber) {
this.checkAndTransitionHardForkByNumber(blockNumber, td)
this.checkAndTransitionHardForkByNumber(blockNumber, td, header.timestamp)
}

// delete higher number assignments and overwrite stale canonical chain
Expand Down Expand Up @@ -1172,8 +1172,12 @@ export class Blockchain implements BlockchainInterface {
return this.dbManager.getHeader(hash, number)
}

protected checkAndTransitionHardForkByNumber(number: bigint, td?: BigIntLike): void {
this._common.setHardforkByBlockNumber(number, td)
protected checkAndTransitionHardForkByNumber(
number: bigint,
td?: BigIntLike,
timestamp?: BigIntLike
): void {
this._common.setHardforkByBlockNumber(number, td, timestamp)

// If custom consensus algorithm is used, skip merge hardfork consensus checks
if (!Object.values(ConsensusAlgorithm).includes(this.consensus.algorithm as ConsensusAlgorithm))
Expand Down
6 changes: 5 additions & 1 deletion packages/client/lib/blockchain/chain.ts
Original file line number Diff line number Diff line change
Expand Up @@ -225,7 +225,11 @@ export class Chain {
this._headers = headers
this._blocks = blocks

this.config.chainCommon.setHardforkByBlockNumber(headers.latest.number, headers.td)
this.config.chainCommon.setHardforkByBlockNumber(
headers.latest.number,
headers.td,
headers.latest.timestamp
)

if (emit) {
this.config.events.emit(Event.CHAIN_UPDATED)
Expand Down
12 changes: 6 additions & 6 deletions packages/client/lib/execution/vmexecution.ts
Original file line number Diff line number Diff line change
Expand Up @@ -97,12 +97,12 @@ export class VMExecution extends Execution {
throw new Error('cannot get iterator head: blockchain has no getIteratorHead function')
}
const headBlock = await this.vm.blockchain.getIteratorHead()
const { number } = headBlock.header
const { number, timestamp } = headBlock.header
if (typeof this.vm.blockchain.getTotalDifficulty !== 'function') {
throw new Error('cannot get iterator head: blockchain has no getTotalDifficulty function')
}
const td = await this.vm.blockchain.getTotalDifficulty(headBlock.header.hash())
this.config.execCommon.setHardforkByBlockNumber(number, td)
this.config.execCommon.setHardforkByBlockNumber(number, td, timestamp)
this.hardfork = this.config.execCommon.hardfork()
this.config.logger.info(`Initializing VM execution hardfork=${this.hardfork}`)
if (number === BigInt(0)) {
Expand Down Expand Up @@ -232,21 +232,21 @@ export class VMExecution extends Execution {
}
// run block, update head if valid
try {
const { number } = block.header
const { number, timestamp } = block.header
if (typeof blockchain.getTotalDifficulty !== 'function') {
throw new Error(
'cannot get iterator head: blockchain has no getTotalDifficulty function'
)
}
const td = await blockchain.getTotalDifficulty(block.header.parentHash)

const hardfork = this.config.execCommon.getHardforkByBlockNumber(number, td)
const hardfork = this.config.execCommon.getHardforkByBlockNumber(number, td, timestamp)
if (hardfork !== this.hardfork) {
const hash = short(block.hash())
this.config.logger.info(
`Execution hardfork switch on block number=${number} hash=${hash} old=${this.hardfork} new=${hardfork}`
)
this.hardfork = this.config.execCommon.setHardforkByBlockNumber(number, td)
this.hardfork = this.config.execCommon.setHardforkByBlockNumber(number, td, timestamp)
}
let skipBlockValidation = false
if (this.config.execCommon.consensusType() === ConsensusType.ProofOfAuthority) {
Expand Down Expand Up @@ -413,7 +413,7 @@ export class VMExecution extends Execution {
throw new Error('cannot get iterator head: blockchain has no getTotalDifficulty function')
}
const td = await vm.blockchain.getTotalDifficulty(block.header.parentHash)
vm._common.setHardforkByBlockNumber(blockNumber, td)
vm._common.setHardforkByBlockNumber(blockNumber, td, block.header.timestamp)

if (txHashes.length === 0) {
// we are skipping header validation because the block has been picked from the
Expand Down
4 changes: 3 additions & 1 deletion packages/client/lib/net/protocol/ethprotocol.ts
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,9 @@ export class EthProtocol extends Protocol {
this.chain.headers.latest?.number ?? // Use latest header number if available OR
this.config.syncTargetHeight ?? // Use sync target height if available OR
common.hardforkBlock(common.hardfork()) ?? // Use current hardfork block number OR
BigInt(0) // Use chainstart
BigInt(0), // Use chainstart,
undefined,
this.chain.headers.latest?.timestamp ?? Math.floor(Date.now() / 1000)
)
return txs.map((txData) => TransactionFactory.fromSerializedData(txData, { common }))
},
Expand Down
4 changes: 3 additions & 1 deletion packages/client/lib/net/protocol/lesprotocol.ts
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,9 @@ export class LesProtocol extends Protocol {
this.config.chainCommon.hardfork(),
this.chain.genesis.hash()
)
const nextFork = this.config.chainCommon.nextHardforkBlock(this.config.chainCommon.hardfork())
const nextFork = this.config.chainCommon.nextHardforkBlockOrTimestamp(
this.config.chainCommon.hardfork()
)
const forkID = [Buffer.from(forkHash.slice(2), 'hex'), bigIntToUnpaddedBuffer(nextFork ?? 0n)]

return {
Expand Down
3 changes: 2 additions & 1 deletion packages/client/lib/rpc/modules/engine.ts
Original file line number Diff line number Diff line change
Expand Up @@ -229,13 +229,14 @@ const assembleBlock = async (
feeRecipient: coinbase,
transactions,
withdrawals: withdrawalsData,
timestamp,
} = payload
const { config } = chain
const common = config.chainCommon.copy()

// This is a post merge block, so set its common accordingly
const ttd = common.hardforkTTD(Hardfork.Merge)
common.setHardforkByBlockNumber(number, ttd !== null ? ttd : undefined)
common.setHardforkByBlockNumber(number, ttd !== null ? ttd : undefined, timestamp)

const txs = []
for (const [index, serializedTx] of transactions.entries()) {
Expand Down
2 changes: 1 addition & 1 deletion packages/client/lib/rpc/modules/eth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -851,7 +851,7 @@ export class Eth {
// Set the tx common to an appropriate HF to create a tx
// with matching HF rules
if (typeof syncTargetHeight === 'bigint' && syncTargetHeight !== BigInt(0)) {
common.setHardforkByBlockNumber(syncTargetHeight)
common.setHardforkByBlockNumber(syncTargetHeight, undefined, Math.floor(Date.now() / 1000))
}

let tx
Expand Down
3 changes: 2 additions & 1 deletion packages/client/lib/sync/beaconsync.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,8 @@ export class BeaconSynchronizer extends Synchronizer {
const { height: number, td } = this.chain.blocks
const hash = this.chain.blocks.latest!.hash()
this.startingBlock = number
this.config.chainCommon.setHardforkByBlockNumber(number, td)
const timestamp = this.chain.blocks.latest?.header.timestamp
this.config.chainCommon.setHardforkByBlockNumber(number, td, timestamp)

this.config.logger.info(
`Latest local block number=${Number(number)} td=${td} hash=${hash.toString(
Expand Down
5 changes: 3 additions & 2 deletions packages/client/lib/sync/fullsync.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,8 @@ export class FullSynchronizer extends Synchronizer {
const { height: number, td } = this.chain.blocks
const hash = this.chain.blocks.latest!.hash()
this.startingBlock = number
this.config.chainCommon.setHardforkByBlockNumber(number, td)
const timestamp = this.chain.blocks.latest?.header.timestamp
this.config.chainCommon.setHardforkByBlockNumber(number, td, timestamp)

this.config.logger.info(
`Latest local block number=${Number(number)} td=${td} hash=${short(
Expand Down Expand Up @@ -221,7 +222,7 @@ export class FullSynchronizer extends Synchronizer {
: ''

let attentionHF: string | null = null
const nextHFBlockNum = this.config.chainCommon.nextHardforkBlock()
const nextHFBlockNum = this.config.chainCommon.nextHardforkBlockOrTimestamp()
if (nextHFBlockNum !== null) {
const remaining = nextHFBlockNum - last
if (remaining <= BigInt(10000)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
"muirGlacierBlock": 0,
"berlinBlock": 0,
"londonBlock": 0,
"shanghaiBlock": 0,
"shanghaiTime": 0,
"clique": {
"blockperiodseconds": 5,
"epochlength": 30000
Expand Down
Loading

0 comments on commit 1875375

Please sign in to comment.