Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New utility methods for Common (loosely connected to Eth64 implementation) #805

Merged
merged 1 commit into from
Jul 4, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
}

/**
* 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
jochem-brouwer marked this conversation as resolved.
Show resolved Hide resolved
}, 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
jochem-brouwer marked this conversation as resolved.
Show resolved Hide resolved
}

/**
* 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()
})
})