Skip to content

Commit

Permalink
Merge pull request #1006 from pokt-foundation/gnosis-merge
Browse files Browse the repository at this point in the history
feat: gnosis merge checker
  • Loading branch information
crisog authored Dec 8, 2022
2 parents db45798 + 74aba5b commit 0da3cf9
Show file tree
Hide file tree
Showing 4 changed files with 125 additions and 8 deletions.
33 changes: 29 additions & 4 deletions src/services/merge-checker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,28 @@ import extractDomain from 'extract-domain'
import { MetricsRecorder } from '../services/metrics-recorder'
import { blockHexToDecimal } from '../utils/block'
import { removeChecksCache, removeNodeFromSession, removeSessionCache } from '../utils/cache'
import { CheckMethods, CHECK_TIMEOUT, PERCENTAGE_THRESHOLD_TO_REMOVE_SESSION } from '../utils/constants'
import {
CheckMethods,
CHECK_TIMEOUT,
ETHEREUM_BLOCKCHAIN_IDS,
GNOSIS_BLOCKCHAIN_IDS,
PERCENTAGE_THRESHOLD_TO_REMOVE_SESSION,
} from '../utils/constants'
import { checkEnforcementJSON } from '../utils/enforcements'
import { CheckResult, RelayResponse } from '../utils/types'
import { Cache } from './cache'

const logger = require('../services/logger')

const MERGE_BLOCK_NUMBER = 15537394
const TERMINAL_TOTAL_DIFFICULTY = BigInt('58750003716598352816469')
const MERGE_BLOCK_NUMBER = {
ethereum: 15537394,
gnosis: 25349536,
}

const TERMINAL_TOTAL_DIFFICULTY = {
ethereum: BigInt('58750003716598352816469'),
gnosis: BigInt('8626000110427538733349499292577475819600160930'),
}

const MERGE_CHECK_PAYLOAD = JSON.stringify({
jsonrpc: '2.0',
Expand Down Expand Up @@ -123,7 +136,19 @@ export class MergeChecker {
const { serviceUrl: serviceURL } = node
const serviceDomain = extractDomain(serviceURL)

if (BigInt(nodeTotalDifficulty) === TERMINAL_TOTAL_DIFFICULTY && nodeBlockNumber >= MERGE_BLOCK_NUMBER) {
let blockchain = ''

if (ETHEREUM_BLOCKCHAIN_IDS.includes(blockchainID)) {
blockchain = 'ethereum'
} else if (GNOSIS_BLOCKCHAIN_IDS.includes(blockchainID)) {
blockchain = 'gnosis'
}

if (
blockchain &&
BigInt(nodeTotalDifficulty) === TERMINAL_TOTAL_DIFFICULTY[blockchain] &&
nodeBlockNumber >= MERGE_BLOCK_NUMBER[blockchain]
) {
logger.log(
'info',
'MERGE CHECK SUCCESS: ' +
Expand Down
4 changes: 2 additions & 2 deletions src/services/pocket-relayer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import { MergeFilterOptions, MergeChecker } from '../services/merge-checker'
import { MetricsRecorder } from '../services/metrics-recorder'
import { ConsensusFilterOptions, SyncChecker, SyncCheckOptions } from '../services/sync-checker'
import { removeNodeFromSession } from '../utils/cache'
import { SESSION_TIMEOUT, DEFAULT_ALTRUIST_TIMEOUT } from '../utils/constants'
import { SESSION_TIMEOUT, DEFAULT_ALTRUIST_TIMEOUT, MERGE_CHECK_BLOCKCHAIN_IDS } from '../utils/constants'
import {
checkEnforcementJSON,
isRelayError,
Expand Down Expand Up @@ -702,7 +702,7 @@ export class PocketRelayer {
return new Error("session doesn't have any available nodes")
}

if (blockchainID === '0021' || blockchainID === '0022' || blockchainID === '0028') {
if (MERGE_CHECK_BLOCKCHAIN_IDS.includes(blockchainID)) {
const mergeStatusOptions: MergeFilterOptions = {
nodes,
requestID,
Expand Down
13 changes: 13 additions & 0 deletions src/utils/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,16 @@ export enum CheckMethods {
ChainCheck = 'chaincheck',
MergeCheck = 'mergecheck',
}

export const GNOSIS_BLOCKCHAIN_IDS = [
'0027', // Gnosis Chain
'000C', // Gnosis Chain Archival
]

export const ETHEREUM_BLOCKCHAIN_IDS = [
'0021', // Ethereum Mainnet
'0022', // Ethereum Rinkeby
'0028', // Ethereum Archival Trace
]

export const MERGE_CHECK_BLOCKCHAIN_IDS = [...ETHEREUM_BLOCKCHAIN_IDS, ...GNOSIS_BLOCKCHAIN_IDS]
83 changes: 81 additions & 2 deletions tests/unit/merge-checker.unit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,18 @@ const MERGE_CHECK_PAYLOAD = '{"jsonrpc":"2.0","method":"eth_getBlockByNumber","p
const SUCCESS_MERGE_CHECK_RESPONSE =
'{"jsonrpc":"2.0","id":1,"result":{"number":"0xed14f2","totalDifficulty":"0xc70d815d562d3cfa955"}}'

// Gnosis Success (merged node)
const SUCCESS_GNOSIS_MERGE_CHECK_RESPONSE =
'{"jsonrpc":"2.0","id":1,"result":{"number":"0x182cda0","totalDifficulty":"0x182cd9fffffffffffffffffffffffffea9528a2"}}'

// Failure (non-merged node)
const FAILURE_MERGE_CHECK_RESPONSE =
'{"jsonrpc":"2.0","id":1,"result":{"number":"0xed1353","totalDifficulty":"0xc7098c61d0934e949f3"}}'

// Failure (non-merged node)
const FAILURE_GNOSIS_MERGE_CHECK_RESPONSE =
'{"jsonrpc":"2.0","id":1,"result":{"number":"0xed1353","totalDifficulty":"0xc7098c61d0934e949f3"}}'

const { POCKET_AAT } = DEFAULT_MOCK_VALUES

describe('Merge checker service (unit)', () => {
Expand Down Expand Up @@ -185,7 +193,7 @@ describe('Merge checker service (unit)', () => {
})
})

it('performs the merge check successfully', async () => {
it('performs the ETH merge check successfully', async () => {
const nodes = DEFAULT_NODES

const relayer = pocketMock.object()
Expand Down Expand Up @@ -231,7 +239,55 @@ describe('Merge checker service (unit)', () => {
expect(cacheSetSpy.callCount).to.be.equal(2)
})

it('fails the merge check', async () => {
it('performs the GNO merge check successfully', async () => {
pocketMock.relayResponse[MERGE_CHECK_PAYLOAD] = SUCCESS_GNOSIS_MERGE_CHECK_RESPONSE

const nodes = DEFAULT_NODES

const relayer = pocketMock.object()
const session = await relayer.getNewSession(undefined)

const cacheGetSpy = sinon.spy(cache, 'get')
const cacheSetSpy = sinon.spy(cache, 'set')

let checkedNodes = (
await mergeChecker.mergeStatusFilter({
nodes,
requestID: '1234',
blockchainID: '0027',
relayer,
applicationID: '',
applicationPublicKey: '',
pocketAAT: POCKET_AAT,
session,
})
).nodes

expect(checkedNodes).to.be.Array()
expect(checkedNodes).to.have.length(5)

expect(cacheGetSpy.callCount).to.be.equal(2)
expect(cacheSetSpy.callCount).to.be.equal(2)

// Subsequent calls should retrieve results from cache instead
checkedNodes = (
await mergeChecker.mergeStatusFilter({
nodes,
requestID: '1234',
blockchainID: '0021',
relayer,
applicationID: '',
applicationPublicKey: '',
pocketAAT: POCKET_AAT,
session,
})
).nodes

expect(cacheGetSpy.callCount).to.be.equal(3)
expect(cacheSetSpy.callCount).to.be.equal(2)
})

it('fails the ETH merge check', async () => {
const nodes = DEFAULT_NODES

// By default, nodes pass the merge check
Expand All @@ -254,6 +310,29 @@ describe('Merge checker service (unit)', () => {
expect(checkedNodes).to.have.length(0)
})

it('fails the GNO merge check', async () => {
const nodes = DEFAULT_NODES

// By default, nodes pass the merge check
pocketMock.relayResponse[MERGE_CHECK_PAYLOAD] = FAILURE_GNOSIS_MERGE_CHECK_RESPONSE
const relayer = pocketMock.object()
const session = await relayer.getNewSession(undefined)

const { nodes: checkedNodes } = await mergeChecker.mergeStatusFilter({
nodes,
requestID: '1234',
blockchainID: '0021',
relayer,
applicationID: '',
applicationPublicKey: '',
pocketAAT: POCKET_AAT,
session,
})

expect(checkedNodes).to.be.Array()
expect(checkedNodes).to.have.length(0)
})

it('Fails the chain check due to max relays error on a node', async () => {
const nodes = DEFAULT_NODES
const blockchainID = '0021'
Expand Down

0 comments on commit 0da3cf9

Please sign in to comment.