Skip to content

Commit

Permalink
Support conversion between target and difficulty
Browse files Browse the repository at this point in the history
  • Loading branch information
Lbqds committed May 1, 2024
1 parent 649e22d commit a2c598c
Show file tree
Hide file tree
Showing 2 changed files with 60 additions and 0 deletions.
35 changes: 35 additions & 0 deletions packages/web3/src/utils/utils.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -107,4 +107,39 @@ describe('utils', function () {
check('00000000000a11fc7e30525ff1c2d783de3344b85a9c76abdd207ad8e1401566', 1, 2)
check('00000000000d09d9f9cf3c3619ca18b84c44437d61cdf0b423831e23e1847e20', 0, 0)
})

it('should convert between target and difficulty', () => {
const maxBigInt = 1n << 256n
for (let num = 1; num < 256; num += 1) {
const targetValue = 1n << BigInt(num)
const diff = maxBigInt / targetValue
const compactedTarget = utils.difficultyToTarget(diff)
expect(utils.targetToDifficulty(compactedTarget)).toEqual(diff)
}

expect(utils.targetToDifficulty('03010101')).toEqual(
1759945423332515547604927348026201994942774834186624170344224826469580800n
)
expect(
utils.difficultyToTarget(1759945423332515547604927348026201994942774834186624170344224826469580800n)
).toEqual('03010101')
expect(utils.targetToDifficulty('10010000')).toEqual(87112285931760246646623899502532662132736n)
expect(utils.difficultyToTarget(87112285931760246646623899502532662132736n)).toEqual('10010000')
expect(utils.targetToDifficulty('12ffffff')).toEqual(5192297168019855896620738275246080n)
expect(utils.difficultyToTarget(5192297168019855896620738275246080n)).toEqual('12ffffff')
expect(utils.targetToDifficulty('20ffffff')).toEqual(1n)
expect(utils.difficultyToTarget(1n)).toEqual('20ffffff')
expect(utils.targetToDifficulty('1b01ae98')).toEqual(167344728152528n)
expect(utils.difficultyToTarget(167344728152528n)).toEqual('1b01ae98')

expect(() => utils.targetToDifficulty('1b01ae9')).toThrow(
'Invalid target 1b01ae9, expected a hex string of length 8'
)
expect(() => utils.targetToDifficulty('1b01ae988')).toThrow(
'Invalid target 1b01ae988, expected a hex string of length 8'
)
expect(() => utils.targetToDifficulty('1b01ae9z')).toThrow(
'Invalid target 1b01ae9z, expected a hex string of length 8'
)
})
})
25 changes: 25 additions & 0 deletions packages/web3/src/utils/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,31 @@ export function isDevnet(networkId?: number): boolean {
return networkId !== 0 && networkId !== 1
}

export function targetToDifficulty(compactedTarget: HexString): bigint {
if (!isHexString(compactedTarget) || compactedTarget.length !== 8) {
throw Error(`Invalid target ${compactedTarget}, expected a hex string of length 8`)
}
const size = hexToBinUnsafe(compactedTarget.slice(0, 2))[0]
const mantissa = BigInt('0x' + compactedTarget.slice(2))
const maxBigInt = 1n << 256n
const target = size <= 3 ? mantissa >> BigInt(8 * (3 - size)) : mantissa << BigInt(8 * (size - 3))
return maxBigInt / target
}

export function difficultyToTarget(diff: bigint): HexString {
const maxBigInt = 1n << 256n
const target = diff === 1n ? maxBigInt - 1n : maxBigInt / diff
const size = Math.floor((target.toString(2).length + 7) / 8)
const mantissa =
size <= 3
? BigInt.asIntN(32, target) << BigInt(8 * (3 - size))
: BigInt.asIntN(32, target >> BigInt(8 * (size - 3)))
const mantissaBytes = Buffer.alloc(4)
mantissaBytes.writeInt32BE(Number(mantissa), 0)
const bytes = new Uint8Array([size, ...mantissaBytes.slice(1)])
return binToHex(bytes)
}

type _Eq<X, Y> = (<T>() => T extends X ? 1 : 2) extends <T>() => T extends Y ? 1 : 2 ? true : false
export type Eq<X, Y> = _Eq<{ [P in keyof X]: X[P] }, { [P in keyof Y]: Y[P] }>
// eslint-disable-next-line @typescript-eslint/no-empty-function, @typescript-eslint/no-unused-vars
Expand Down

0 comments on commit a2c598c

Please sign in to comment.