Skip to content

Commit

Permalink
fix rpc interception issues
Browse files Browse the repository at this point in the history
  • Loading branch information
jfschwarz committed Aug 14, 2024
1 parent 614484d commit 8ca5de0
Showing 1 changed file with 52 additions and 7 deletions.
59 changes: 52 additions & 7 deletions extension/src/background.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ const activeExtensionTabs = new Set<number>()

const startTrackingTab = (tabId: number) => {
activeExtensionTabs.add(tabId)
clearStaleRules()
updateHeadersRule()
console.log('Pilot: started tracking tab', tabId)
}
Expand All @@ -21,6 +22,7 @@ const stopTrackingTab = (tabId: number) => {
removeRpcRedirectRules(tabId)
activeExtensionTabs.delete(tabId)
simulatingExtensionTabs.delete(tabId)
clearStaleRules()
updateHeadersRule()
console.log('Pilot: stopped tracking tab', tabId)
}
Expand Down Expand Up @@ -99,12 +101,10 @@ chrome.action.onClicked.addListener(toggle)
// a fork network.
const simulatingExtensionTabs = new Map<number, Fork>()

// Hash the RPC URL+ tab ID to a number, so we can use it as a declarativeNetRequest rule ID.
// Hash the RPC URL + tab ID to a number, so we can use it as a declarativeNetRequest rule ID.
// Implementation taken from https://github.com/darkskyapp/string-hash (CC0 Public Domain)
function hash(rpcUrl: string, tabId: number) {
const urlComponents = rpcUrl.split('/')
const forkId = urlComponents[urlComponents.length - 1]
const str = `${tabId}:${forkId}`
const str = `${tabId}:${rpcUrl}`
const MAX_RULE_ID = 0xffffff // chrome throws an error if the rule ID is too large ("expected integer, got number")

let hash = 5381,
Expand All @@ -120,6 +120,46 @@ function hash(rpcUrl: string, tabId: number) {
return (hash >>> 0) % MAX_RULE_ID
}

async function clearStaleRules() {
const openTabIds = await new Promise<Set<number>>((resolve) => {
chrome.tabs.query({}, (tabs) => {
resolve(new Set(tabs.map((tab) => tab.id).filter(Boolean) as number[]))
})
})

// clear activeExtensionTabs that are not open anymore
activeExtensionTabs.difference(openTabIds).forEach((tabId) => {
activeExtensionTabs.delete(tabId)
})
console.log({ activeExtensionTabs, openTabIds })

// clear simulatingExtensionTabs that are not active (= extension is activated) anymore
const simulatingTabIds = new Set(simulatingExtensionTabs.keys())
simulatingTabIds.difference(activeExtensionTabs).forEach((tabId) => {
simulatingExtensionTabs.delete(tabId)
})

// remove rules for tabs that are not simulating anymore
const staleRules = await new Promise<chrome.declarativeNetRequest.Rule[]>(
(resolve) => {
chrome.declarativeNetRequest.getSessionRules((rules) => {
resolve(
rules.filter(
(rule) =>
rule.condition.tabIds?.length === 1 &&
!simulatingExtensionTabs.has(rule.condition.tabIds[0])
)
)
})
}
)
chrome.declarativeNetRequest.updateSessionRules({
removeRuleIds: staleRules.map((r) => r.id),
})

console.debug('Cleared stale rules', staleRules)
}

const updateRpcRedirectRules = (tabId: number) => {
const fork = simulatingExtensionTabs.get(tabId)
if (!fork) {
Expand Down Expand Up @@ -156,6 +196,10 @@ const updateRpcRedirectRules = (tabId: number) => {
addRules,
removeRuleIds: ruleIds,
})

chrome.declarativeNetRequest.getSessionRules((rules) => {
console.debug('RPC redirect rules updated', tabId, rules)
})
}

const removeRpcRedirectRules = (tabId: number) => {
Expand All @@ -176,9 +220,6 @@ const removeRpcRedirectRules = (tabId: number) => {
735219801
)
)
chrome.declarativeNetRequest.getSessionRules((rules) =>
console.log('removeRpcRedirectRules getSessionRules', rules)
)
}

chrome.runtime.onMessage.addListener((message, sender) => {
Expand All @@ -202,6 +243,7 @@ chrome.runtime.onMessage.addListener((message, sender) => {
rpcUrl
)
}

if (message.type === 'stopSimulating') {
console.log('stopSimulating', sender.tab.id, { simulatingExtensionTabs })
simulatingExtensionTabs.delete(sender.tab.id)
Expand Down Expand Up @@ -233,6 +275,9 @@ chrome.webRequest.onBeforeRequest.addListener(
// don't consider requests that are already redirected to the fork RPC
if (details.url === simulatingExtensionTabs.get(details.tabId)?.rpcUrl)
return
// ignore requests to fork RPCs
if (details.url.startsWith('https://virtual.mainnet.rpc.tenderly.co/'))
return
// only consider requests with a JSON RPC body
if (!getJsonRpcBody(details)) return

Expand Down

0 comments on commit 8ca5de0

Please sign in to comment.