Skip to content

Commit

Permalink
common: added new methods nextHardforkBlock, isNextHardforkBlock and …
Browse files Browse the repository at this point in the history
…hardforkForForkHash and associated tests
  • Loading branch information
holgerd77 committed Jul 2, 2020
1 parent dacc853 commit 9d3271f
Show file tree
Hide file tree
Showing 2 changed files with 102 additions and 6 deletions.
49 changes: 43 additions & 6 deletions packages/common/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -345,18 +345,43 @@ export default class Common {
}

/**
* True if block number provided is the hardfork (given or set) change block of the current chain
* True if block number provided is the hardfork (given or set) change block
* @param blockNumber Number of the block to check
* @param hardfork Hardfork name, optional if HF set
* @returns True if blockNumber is HF block
*/
isHardforkBlock(blockNumber: number, hardfork?: string): boolean {
hardfork = this._chooseHardfork(hardfork, false)
if (this.hardforkBlock(hardfork) === blockNumber) {
return true
} else {
return false
}
return this.hardforkBlock(hardfork) === blockNumber ? true : false
}

/**
* Returns the change block for the next hardfork after the hardfork provided or set
* @param hardfork Hardfork name, optional if HF set
* @returns Block number or null if not available
*/
nextHardforkBlock(hardfork?: string): number | null {
hardfork = this._chooseHardfork(hardfork, false)
const hfBlock = this.hardforkBlock(hardfork)
// Next fork block number or null if none available
// Logic: if accumulator is still null and on the first occurence of
// a block greater than the current hfBlock set the accumulator,
// pass on the accumulator as the final result from this time on
const nextHfBlock = this.hardforks().reduce((acc: number, hf: any) => {
return hf.block > hfBlock && acc === null ? hf.block : acc
}, null)
return nextHfBlock
}

/**
* True if block number provided is the hardfork change block following the hardfork given or set
* @param blockNumber Number of the block to check
* @param hardfork Hardfork name, optional if HF set
* @returns True if blockNumber is HF block
*/
isNextHardforkBlock(blockNumber: number, hardfork?: string): boolean {
hardfork = this._chooseHardfork(hardfork, false)
return this.nextHardforkBlock(hardfork) === blockNumber
}

/**
Expand Down Expand Up @@ -407,6 +432,18 @@ export default class Common {
return this._calcForkHash(hardfork)
}

/**
*
* @param forkHash Fork hash as a hex string
* @returns Array with hardfork data (name, block, forkHash)
*/
hardforkForForkHash(forkHash: string): any | null {
const resArray = this.hardforks().filter((hf: any) => {
return hf.forkHash === forkHash
})
return resArray.length === 1 ? resArray[0] : null
}

/**
* Returns the Genesis parameters of current chain
* @returns Genesis dictionary
Expand Down
59 changes: 59 additions & 0 deletions packages/common/tests/hardforks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,52 @@ tape('[Common]: Hardfork logic', function (t: tape.Test) {
st.end()
})

t.test('nextHardforkBlock()', function (st: tape.Test) {
let c = new Common('rinkeby', 'chainstart')
let msg =
'should work with HF set / return correct next HF block for chainstart (rinkeby: chainstart -> homestead)'
st.equal(c.nextHardforkBlock(), 1, msg)

msg =
'should correctly skip a HF where block is set to null (rinkeby: homestead -> (dao) -> tangerineWhistle)'
st.equal(c.nextHardforkBlock('homestead'), 2, msg)

msg = 'should return correct next HF (rinkeby: byzantium -> constantinople)'
st.equal(c.nextHardforkBlock('byzantium'), 3660663, msg)

msg = 'should return null if next HF is not available (rinkeby: istanbul -> berlin)'
st.equal(c.nextHardforkBlock('istanbul'), null, msg)

msg =
'should work correctly along the need to skip several forks (ropsten: chainstart -> (homestead) -> (dao) -> (tangerineWhistle) -> spuriousDragon)'
c = new Common('ropsten', 'chainstart')
st.equal(c.nextHardforkBlock(), 10, msg)

st.end()
})

t.test('isNextHardforkBlock()', function (st: tape.Test) {
let c = new Common('rinkeby', 'chainstart')
let msg =
'should work with HF set / return true fro correct next HF block for chainstart (rinkeby: chainstart -> homestead)'
st.equal(c.isNextHardforkBlock(1), true, msg)

msg =
'should correctly skip a HF where block is set to null (rinkeby: homestead -> (dao) -> tangerineWhistle)'
st.equal(c.isNextHardforkBlock(2, 'homestead'), true, msg)

msg = 'should return true for correct next HF (rinkeby: byzantium -> constantinople)'
st.equal(c.isNextHardforkBlock(3660663, 'byzantium'), true, msg)

msg = 'should return false for a block number too low (rinkeby: byzantium -> constantinople)'
st.equal(c.isNextHardforkBlock(124, 'byzantium'), false, msg)

msg = 'should return false for a block number too hight (rinkeby: byzantium -> constantinople)'
st.equal(c.isNextHardforkBlock(605948938, 'byzantium'), false, msg)

st.end()
})

t.test('activeHardforks()', function (st: tape.Test) {
let c = new Common('ropsten')
let msg = 'should return 9 active hardforks for Ropsten'
Expand Down Expand Up @@ -274,4 +320,17 @@ tape('[Common]: Hardfork logic', function (t: tape.Test) {

st.end()
})

t.test('hardforkForForkHash()', function (st: tape.Test) {
let c = new Common('mainnet')

let msg = 'should return the correct HF array for a matching forkHash'
const res = c.hardforkForForkHash('0x3edd5b10')
st.equal(res.name, 'spuriousDragon', msg)

msg = 'should return null for a forkHash not matching any HF'
st.equal(c.hardforkForForkHash('0x12345'), null, msg)

st.end()
})
})

0 comments on commit 9d3271f

Please sign in to comment.