Use safe approach for eth_getLogs requests (#581)
This commit is contained in:
parent
92e1b597c4
commit
3e5e50c06e
@ -35,7 +35,7 @@ async function initialize() {
|
|||||||
try {
|
try {
|
||||||
const checkHttps = checkHTTPS(ORACLE_ALLOW_HTTP_FOR_RPC, logger)
|
const checkHttps = checkHTTPS(ORACLE_ALLOW_HTTP_FOR_RPC, logger)
|
||||||
|
|
||||||
web3.currentProvider.urls.forEach(checkHttps(config.chain))
|
web3.currentProvider.subProvider.urls.forEach(checkHttps(config.chain))
|
||||||
|
|
||||||
attached = await isAttached()
|
attached = await isAttached()
|
||||||
if (attached) {
|
if (attached) {
|
||||||
|
@ -40,7 +40,7 @@ async function initialize() {
|
|||||||
try {
|
try {
|
||||||
const checkHttps = checkHTTPS(process.env.ORACLE_ALLOW_HTTP_FOR_RPC, logger)
|
const checkHttps = checkHTTPS(process.env.ORACLE_ALLOW_HTTP_FOR_RPC, logger)
|
||||||
|
|
||||||
web3.currentProvider.urls.forEach(checkHttps(config.chain))
|
web3.currentProvider.subProvider.urls.forEach(checkHttps(config.chain))
|
||||||
|
|
||||||
GasPrice.start(config.id)
|
GasPrice.start(config.id)
|
||||||
|
|
||||||
|
@ -2,6 +2,8 @@ const fetch = require('node-fetch')
|
|||||||
const promiseRetry = require('promise-retry')
|
const promiseRetry = require('promise-retry')
|
||||||
const { FALLBACK_RPC_URL_SWITCH_TIMEOUT } = require('../utils/constants')
|
const { FALLBACK_RPC_URL_SWITCH_TIMEOUT } = require('../utils/constants')
|
||||||
|
|
||||||
|
const { onInjected } = require('./injectedLogger')
|
||||||
|
|
||||||
// From EIP-1474 and Infura documentation
|
// From EIP-1474 and Infura documentation
|
||||||
const JSONRPC_ERROR_CODES = [-32603, -32002, -32005]
|
const JSONRPC_ERROR_CODES = [-32603, -32002, -32005]
|
||||||
|
|
||||||
@ -33,14 +35,10 @@ function HttpListProvider(urls, options = {}) {
|
|||||||
this.options = { ...defaultOptions, ...options }
|
this.options = { ...defaultOptions, ...options }
|
||||||
this.currentIndex = 0
|
this.currentIndex = 0
|
||||||
this.lastTimeUsedPrimary = 0
|
this.lastTimeUsedPrimary = 0
|
||||||
this.logger = {
|
|
||||||
debug: () => {},
|
|
||||||
info: () => {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
HttpListProvider.prototype.setLogger = function(logger) {
|
onInjected(logger => {
|
||||||
this.logger = logger.child({ module: `HttpListProvider:${this.options.name}` })
|
this.logger = logger.child({ module: `HttpListProvider:${this.options.name}` })
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
HttpListProvider.prototype.send = async function send(payload, callback) {
|
HttpListProvider.prototype.send = async function send(payload, callback) {
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
const promiseRetry = require('promise-retry')
|
const promiseRetry = require('promise-retry')
|
||||||
const { promiseAny } = require('../utils/utils')
|
const { promiseAny } = require('../utils/utils')
|
||||||
const { defaultOptions, HttpListProviderError, send } = require('./HttpListProvider')
|
const { defaultOptions, HttpListProviderError, send } = require('./HttpListProvider')
|
||||||
|
const { onInjected } = require('./injectedLogger')
|
||||||
|
|
||||||
function RedundantHttpListProvider(urls, options = {}) {
|
function RedundantHttpListProvider(urls, options = {}) {
|
||||||
if (!(this instanceof RedundantHttpListProvider)) {
|
if (!(this instanceof RedundantHttpListProvider)) {
|
||||||
@ -13,10 +14,9 @@ function RedundantHttpListProvider(urls, options = {}) {
|
|||||||
|
|
||||||
this.urls = urls
|
this.urls = urls
|
||||||
this.options = { ...defaultOptions, ...options }
|
this.options = { ...defaultOptions, ...options }
|
||||||
}
|
onInjected(logger => {
|
||||||
|
this.logger = logger.child({ module: `RedundantHttpListProvider:${this.options.name}` })
|
||||||
RedundantHttpListProvider.prototype.setLogger = function(logger) {
|
})
|
||||||
this.logger = logger.child({ module: `RedundantHttpListProvider:${this.options.name}` })
|
|
||||||
}
|
}
|
||||||
|
|
||||||
RedundantHttpListProvider.prototype.send = async function send(payload, callback) {
|
RedundantHttpListProvider.prototype.send = async function send(payload, callback) {
|
||||||
|
41
oracle/src/services/SafeEthLogsProvider.js
Normal file
41
oracle/src/services/SafeEthLogsProvider.js
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
const { hexToNumber, isHexStrict } = require('web3').utils
|
||||||
|
|
||||||
|
const { onInjected } = require('./injectedLogger')
|
||||||
|
|
||||||
|
function SafeEthLogsProvider(provider) {
|
||||||
|
this.subProvider = provider
|
||||||
|
onInjected(logger => {
|
||||||
|
this.logger = logger.child({ module: 'SafeEthLogsProvider' })
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
SafeEthLogsProvider.prototype.send = function send(payload, callback) {
|
||||||
|
if (payload.method === 'eth_getLogs' && isHexStrict(payload.params[0].toBlock)) {
|
||||||
|
this.logger.debug('Modifying eth_getLogs request to include batch eth_blockNumber request')
|
||||||
|
|
||||||
|
const newPayload = [payload, { jsonrpc: '2.0', id: payload.id + 1, method: 'eth_blockNumber', params: [] }]
|
||||||
|
this.subProvider.send(newPayload, (err, res) => {
|
||||||
|
if (err) {
|
||||||
|
callback(err, null)
|
||||||
|
} else {
|
||||||
|
const rawLogs = res.find(({ id }) => id === payload.id)
|
||||||
|
const rawBlockNumber = res.find(({ id }) => id === payload.id + 1)
|
||||||
|
const blockNumber = hexToNumber(rawBlockNumber.result)
|
||||||
|
const toBlock = hexToNumber(payload.params[0].toBlock)
|
||||||
|
|
||||||
|
if (blockNumber < toBlock) {
|
||||||
|
this.logger.warn({ toBlock, blockNumber }, 'Returned block number is less than the specified toBlock')
|
||||||
|
callback(new Error('block number too low'), null)
|
||||||
|
} else {
|
||||||
|
callback(null, rawLogs)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
this.subProvider.send(payload, callback)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
SafeEthLogsProvider
|
||||||
|
}
|
27
oracle/src/services/injectedLogger.js
Normal file
27
oracle/src/services/injectedLogger.js
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
// workaround to avoid circular dependencies in module imports
|
||||||
|
// e.g. logger -> config -> web3 -> provider -> logger
|
||||||
|
// transforms to the following import chain
|
||||||
|
// logger -> config -> web3 -> provider -> injectedLogger
|
||||||
|
// logger -> injectedLogger
|
||||||
|
|
||||||
|
let logger
|
||||||
|
|
||||||
|
const callbacks = []
|
||||||
|
|
||||||
|
function onInjected(cb) {
|
||||||
|
if (logger) {
|
||||||
|
cb(logger)
|
||||||
|
} else {
|
||||||
|
callbacks.push(cb)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function setLogger(newLogger) {
|
||||||
|
logger = newLogger
|
||||||
|
callbacks.forEach(cb => cb(logger))
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
onInjected,
|
||||||
|
setLogger
|
||||||
|
}
|
@ -1,15 +1,7 @@
|
|||||||
const pino = require('pino')
|
const pino = require('pino')
|
||||||
const path = require('path')
|
const path = require('path')
|
||||||
const {
|
|
||||||
web3Home,
|
const { setLogger } = require('./injectedLogger')
|
||||||
web3Foreign,
|
|
||||||
web3ForeignArchive,
|
|
||||||
web3Side,
|
|
||||||
web3HomeFallback,
|
|
||||||
web3ForeignFallback,
|
|
||||||
web3HomeRedundant,
|
|
||||||
web3ForeignRedundant
|
|
||||||
} = require('./web3')
|
|
||||||
|
|
||||||
const config = process.env.NODE_ENV !== 'test' ? require(path.join('../../config/', process.argv[2])) : {}
|
const config = process.env.NODE_ENV !== 'test' ? require(path.join('../../config/', process.argv[2])) : {}
|
||||||
|
|
||||||
@ -25,19 +17,6 @@ const logger = pino({
|
|||||||
: {}
|
: {}
|
||||||
})
|
})
|
||||||
|
|
||||||
web3Home.currentProvider.setLogger(logger)
|
setLogger(logger)
|
||||||
web3Foreign.currentProvider.setLogger(logger)
|
|
||||||
web3HomeFallback.currentProvider.setLogger(logger)
|
|
||||||
web3ForeignFallback.currentProvider.setLogger(logger)
|
|
||||||
web3HomeRedundant.currentProvider.setLogger(logger)
|
|
||||||
web3ForeignRedundant.currentProvider.setLogger(logger)
|
|
||||||
|
|
||||||
if (web3ForeignArchive) {
|
|
||||||
web3ForeignArchive.currentProvider.setLogger(logger)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (web3Side) {
|
|
||||||
web3Side.currentProvider.setLogger(logger)
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = logger
|
module.exports = logger
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
const Web3 = require('web3')
|
const Web3 = require('web3')
|
||||||
const { HttpListProvider } = require('./HttpListProvider')
|
const { HttpListProvider } = require('./HttpListProvider')
|
||||||
|
const { SafeEthLogsProvider } = require('./SafeEthLogsProvider')
|
||||||
const { RedundantHttpListProvider } = require('./RedundantHttpListProvider')
|
const { RedundantHttpListProvider } = require('./RedundantHttpListProvider')
|
||||||
const { RETRY_CONFIG } = require('../utils/constants')
|
const { RETRY_CONFIG } = require('../utils/constants')
|
||||||
|
|
||||||
@ -37,10 +38,10 @@ const foreignOptions = {
|
|||||||
retry: RETRY_CONFIG
|
retry: RETRY_CONFIG
|
||||||
}
|
}
|
||||||
|
|
||||||
const homeProvider = new HttpListProvider(homeUrls, homeOptions)
|
const homeProvider = new SafeEthLogsProvider(new HttpListProvider(homeUrls, homeOptions))
|
||||||
const web3Home = new Web3(homeProvider)
|
const web3Home = new Web3(homeProvider)
|
||||||
|
|
||||||
const foreignProvider = new HttpListProvider(foreignUrls, foreignOptions)
|
const foreignProvider = new SafeEthLogsProvider(new HttpListProvider(foreignUrls, foreignOptions))
|
||||||
const web3Foreign = new Web3(foreignProvider)
|
const web3Foreign = new Web3(foreignProvider)
|
||||||
|
|
||||||
let web3ForeignArchive = null
|
let web3ForeignArchive = null
|
||||||
|
@ -34,7 +34,7 @@ async function initialize() {
|
|||||||
try {
|
try {
|
||||||
const checkHttps = checkHTTPS(process.env.ORACLE_ALLOW_HTTP_FOR_RPC, logger)
|
const checkHttps = checkHTTPS(process.env.ORACLE_ALLOW_HTTP_FOR_RPC, logger)
|
||||||
|
|
||||||
web3.currentProvider.urls.forEach(checkHttps(chain))
|
web3.currentProvider.subProvider.urls.forEach(checkHttps(chain))
|
||||||
|
|
||||||
await getLastProcessedBlock()
|
await getLastProcessedBlock()
|
||||||
connectWatcherToQueue({
|
connectWatcherToQueue({
|
||||||
|
Loading…
Reference in New Issue
Block a user