-
Notifications
You must be signed in to change notification settings - Fork 3
Validator registry integration #84
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -14,6 +14,7 @@ const pluginCreators = [ | |
| require('./plugins/proxy-router'), | ||
| require('./plugins/contracts'), | ||
| require('./plugins/devices'), | ||
| require('./plugins/validator-registry') | ||
| ] | ||
|
Comment on lines
14
to
18
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Modularity and Scalability IssueHardcoding the paths of plugin modules in the Recommendation: Implement a more dynamic plugin registration system, possibly through a configuration file or a directory scanning mechanism that automatically registers all plugins. This would enhance modularity and make the system more robust and easier to scale as the number of plugins grows. |
||
|
|
||
| function createCore() { | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -3,8 +3,11 @@ const logger = require('../../logger') | |
| const { encrypt } = require('ecies-geth') | ||
| const { Implementation } = require('contracts-js') | ||
| const { remove0xPrefix, add65BytesPrefix } = require('./helpers') | ||
| const { decompressPublicKey } = require('../validator-registry/api') | ||
| const ethereumWallet = require('ethereumjs-wallet').default | ||
|
|
||
| const ZERO_ADDRESS = "0x0000000000000000000000000000000000000000" | ||
|
|
||
| /** | ||
| * @param {import('web3').default} web3 | ||
| * @param {string} implementationAddress | ||
|
|
@@ -45,7 +48,7 @@ async function _loadContractInstance( | |
| _length: length, // duration of the contract in seconds | ||
| _version: version, | ||
| _profitTarget: profitTarget | ||
| }, | ||
| }, | ||
| _startingBlockTimestamp: timestamp, // timestamp of the block at moment of purchase | ||
| _buyer: buyer, // wallet address of the purchasing party | ||
| _seller: seller, // wallet address of the selling party | ||
|
|
@@ -253,73 +256,76 @@ function setContractDeleteStatus(web3, cloneFactory, onUpdate) { | |
| } | ||
| } | ||
|
|
||
|
|
||
| /** | ||
| * | ||
| * @param {import('web3').default} web3 | ||
| * @param {import('contracts-js').CloneFactoryContext} cloneFactory | ||
| * @param {import('contracts-js').LumerinContext} lumerin | ||
| * @returns | ||
| * @returns {(p: {validatorUrl: string, validatorAddr: string, destUrl: string, validatorPubKeyYparity: boolean, validatorPubKeyX: `0x${string}`, contractAddr: string, price: string,version: number, privateKey: string}) => Promise<void>} | ||
| */ | ||
| function purchaseContract(web3, cloneFactory, lumerin) { | ||
| return async (params) => { | ||
| const { walletId, contractId, url, privateKey, price, version } = params | ||
| const sendOptions = { from: walletId } | ||
| const { validatorUrl, destUrl, validatorAddr, validatorPubKeyYparity, validatorPubKeyX, privateKey, contractAddr, price, version } = params; | ||
|
|
||
| //getting pubkey from contract to be purchased | ||
| const implementationContract = Implementation(web3, contractId) | ||
|
|
||
| const pubKey = await implementationContract.methods.pubKey().call() | ||
|
|
||
| //encrypting plaintext url parameter | ||
| const ciphertext = await encrypt( | ||
| Buffer.from(add65BytesPrefix(pubKey), 'hex'), | ||
| Buffer.from(url) | ||
| ) | ||
|
|
||
| const account = web3.eth.accounts.privateKeyToAccount(privateKey) | ||
| web3.eth.accounts.wallet.create(0).add(account) | ||
|
|
||
| const { | ||
| data: { isDead, price: p }, | ||
| } = await _loadContractInstance(web3, contractId) | ||
| if (isDead) { | ||
| throw new Error('Contract is deleted already') | ||
| } | ||
| const implementationContract = Implementation(web3, contractAddr) | ||
| const sellerPubKey = await implementationContract.methods.pubKey().call() | ||
|
|
||
| const isThirdPartyValidator = validatorAddr !== ZERO_ADDRESS; | ||
| const encrDestPubKey = isThirdPartyValidator ? decompressPublicKey(validatorPubKeyYparity, validatorPubKeyX) : sellerPubKey; | ||
|
|
||
| const encrValidatorUrl = await encrypt( | ||
| Buffer.from(add65BytesPrefix(sellerPubKey), 'hex'), | ||
| Buffer.from(validatorUrl) | ||
| ).then(res => res.toString('hex')) | ||
|
|
||
| const encrDestUrl = await encrypt( | ||
| Buffer.from(add65BytesPrefix(encrDestPubKey), 'hex'), | ||
| Buffer.from(destUrl) | ||
| ).then(res => res.toString('hex')) | ||
|
|
||
| const increaseAllowanceEstimate = await lumerin.methods | ||
| .increaseAllowance(cloneFactory.options.address, price) | ||
| .estimateGas({ | ||
| from: walletId, | ||
| from: account.address, | ||
| }) | ||
|
|
||
| await lumerin.methods | ||
| .increaseAllowance(cloneFactory.options.address, price) | ||
| .send({ | ||
| from: walletId, | ||
| from: account.address, | ||
| gas: increaseAllowanceEstimate, | ||
| }) | ||
|
|
||
| const marketplaceFee = await cloneFactory.methods.marketplaceFee().call() | ||
|
|
||
| const purchaseGas = await cloneFactory.methods | ||
| .setPurchaseRentalContract( | ||
| contractId, | ||
| ciphertext.toString('hex'), | ||
| .setPurchaseRentalContractV2( | ||
| contractAddr, | ||
| validatorAddr, | ||
| encrValidatorUrl, | ||
| encrDestUrl, | ||
| version | ||
| ) | ||
| .estimateGas({ | ||
| from: sendOptions.from, | ||
| from: account.address, | ||
| value: marketplaceFee, | ||
| }) | ||
|
|
||
| const purchaseResult = await cloneFactory.methods | ||
| .setPurchaseRentalContract( | ||
| contractId, | ||
| ciphertext.toString('hex'), | ||
| .setPurchaseRentalContractV2( | ||
| contractAddr, | ||
| validatorAddr, | ||
| encrValidatorUrl, | ||
| encrDestUrl, | ||
| version | ||
| ) | ||
| .send({ | ||
| ...sendOptions, | ||
| from: account.address, | ||
| gas: purchaseGas, | ||
| value: marketplaceFee, | ||
| }) | ||
|
Comment on lines
256
to
331
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Security Concern: Insufficient Input ValidationThe function Recommended Solution: |
||
|
|
@@ -357,7 +363,7 @@ function editContract(web3, cloneFactory, lumerin) { | |
| .estimateGas({ | ||
| from: sendOptions.from, | ||
| }); | ||
|
|
||
| const editResult = await cloneFactory.methods | ||
| .setUpdateContractInformationV2(contractId, price, limit, speed, duration, +profit) | ||
| .send({ | ||
|
Comment on lines
363
to
369
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Performance Optimization: Redundant Transaction EstimationIn the Recommended Solution: |
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -3,7 +3,17 @@ | |
| const remove0xPrefix = privateKey => privateKey.replace('0x', ''); | ||
|
|
||
| // https://superuser.com/a/1465498 | ||
| const add65BytesPrefix = key => `04${key}`; | ||
| /** @param {string} key */ | ||
| const add65BytesPrefix = key => { | ||
| key = key.replace("0x", "") | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Redundancy in CodeThe Recommendation: |
||
|
|
||
| // 64 bytes hex string (2 char per byte) | ||
| if (key.length === 64 * 2) { | ||
| return `04${key}` | ||
| } | ||
|
|
||
| return key | ||
| } | ||
|
Comment on lines
3
to
+16
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Lack of Input Validation and Error HandlingBoth Recommendation: |
||
|
|
||
| module.exports = { | ||
| remove0xPrefix, | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,5 +1,5 @@ | ||
| const AxiosDigestAuth = require('@mhoc/axios-digest-auth') | ||
| const cheerio = require('cheerio') | ||
| // const cheerio = require('cheerio') | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The commented-out import of |
||
|
|
||
| const { ConfigurationStrategyInterface } = require('./strategy.interface') | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,6 +1,6 @@ | ||
| const { AbortSignal } = require('@azure/abort-controller') | ||
|
|
||
| const { AntMinerStrategy } = require('./ant-miner-strategy') | ||
| // const { AntMinerStrategy } = require('./ant-miner-strategy') | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The import statement for |
||
| const { TcpConfigurationStrategy } = require('./tcp-strategy') | ||
| const { ConfigurationStrategyInterface } = require('./strategy.interface'); | ||
|
|
||
|
|
@@ -11,7 +11,7 @@ class ConfigurationStrategyFactory { | |
| * @returns {Promise<ConfigurationStrategyInterface|null>} | ||
| */ | ||
| static async createStrategy(host, abort) { | ||
| const strategies = [TcpConfigurationStrategy, AntMinerStrategy] | ||
| const strategies = [TcpConfigurationStrategy] | ||
| for (const Strategy of strategies) { | ||
| try { | ||
| const strategy = new Strategy(host, abort) | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -9,10 +9,16 @@ const isRateLimitError = (response, payload) => { | |
| return true | ||
| } | ||
|
|
||
| if (payload?.method === 'eth_call' && (response.error?.message?.includes('execution reverted') || response.error?.code === -32000)) { | ||
| // Some providers return execution reverted error for eth_call when rate limiting | ||
| if ( | ||
| payload?.method === 'eth_call' && | ||
| response.error?.message?.includes('execution reverted') && | ||
| (response.error?.data === '' || response.error?.data === '0x' || response.error?.data === null || response.error?.data === undefined) | ||
| ) { | ||
| return true | ||
| } | ||
|
|
||
|
|
||
| const message = response.error?.message?.toLowerCase() | ||
| if (!message) { | ||
| return false | ||
|
|
@@ -21,9 +27,9 @@ const isRateLimitError = (response, payload) => { | |
| message.includes('too many requests') || | ||
| message.includes('rate limit exceeded') || | ||
| message.includes('reached maximum qps limit') || | ||
| message.includes('rate limit reached') || | ||
| message.includes('rate limit reached') || | ||
| message.includes("we can't execute this request") || | ||
| message.includes("max message response size exceed") || | ||
| message.includes("max message response size exceed") || | ||
| message.includes("upgrade your plan") || | ||
| message.includes("Failed to validate quota usage") | ||
| ); | ||
|
Comment on lines
27
to
35
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The method Suggested Solution: const rateLimitPatterns = /too many requests|rate limit exceeded|reached maximum qps limit|rate limit reached|we can't execute this request|max message response size exceed|upgrade your plan|Failed to validate quota usage/;
return rateLimitPatterns.test(message); |
||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Performance and Maintainability Issue
The synchronous loading of plugins using
requirewithin thepluginCreatorsarray can lead to performance bottlenecks, especially if the initialization of these plugins is resource-intensive. This approach also makes the system less flexible and harder to maintain because any modifications to the plugins require changes to this core file.Recommendation: Consider using an asynchronous plugin loading mechanism, such as dynamic imports (
import()) which can be used to load modules on demand. This would not only improve the load times but also enhance the system's ability to scale and adapt to changes more gracefully.