From 7b5fbf3d135725c85b3ba12aff124fe595dd209e Mon Sep 17 00:00:00 2001 From: Nabarun Gogoi Date: Mon, 13 Nov 2023 12:22:23 +0530 Subject: [PATCH] Implement new graph-node host API for BigDecimal exponentiation (#467) * Implement host API for BigDecimal pow * Handle FEVM future block error in rpc-eth-client getFullBlocks * Handle future block error in rpc-eth-client getBlockWithTransactions * Upgrade package versions --- lerna.json | 2 +- packages/cache/package.json | 2 +- packages/cli/package.json | 12 +- packages/codegen/package.json | 4 +- .../src/templates/package-template.handlebars | 10 +- packages/graph-node/package.json | 10 +- packages/graph-node/src/loader.ts | 19 +++ packages/ipld-eth-client/package.json | 6 +- packages/peer/package.json | 2 +- packages/rpc-eth-client/package.json | 8 +- packages/rpc-eth-client/src/eth-client.ts | 134 +++++++++++------- packages/solidity-mapper/package.json | 2 +- packages/test/package.json | 2 +- packages/tracing-client/package.json | 2 +- packages/util/package.json | 8 +- 15 files changed, 134 insertions(+), 89 deletions(-) diff --git a/lerna.json b/lerna.json index ea99338ae..eb71d4897 100644 --- a/lerna.json +++ b/lerna.json @@ -2,7 +2,7 @@ "packages": [ "packages/*" ], - "version": "0.2.69", + "version": "0.2.70", "npmClient": "yarn", "useWorkspaces": true, "command": { diff --git a/packages/cache/package.json b/packages/cache/package.json index 9decedf89..427e68f39 100644 --- a/packages/cache/package.json +++ b/packages/cache/package.json @@ -1,6 +1,6 @@ { "name": "@cerc-io/cache", - "version": "0.2.69", + "version": "0.2.70", "description": "Generic object cache", "main": "dist/index.js", "scripts": { diff --git a/packages/cli/package.json b/packages/cli/package.json index 273f06a3a..6faefc9c5 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -1,6 +1,6 @@ { "name": "@cerc-io/cli", - "version": "0.2.69", + "version": "0.2.70", "main": "dist/index.js", "license": "AGPL-3.0", "scripts": { @@ -12,13 +12,13 @@ }, "dependencies": { "@apollo/client": "^3.7.1", - "@cerc-io/cache": "^0.2.69", - "@cerc-io/ipld-eth-client": "^0.2.69", + "@cerc-io/cache": "^0.2.70", + "@cerc-io/ipld-eth-client": "^0.2.70", "@cerc-io/libp2p": "^0.42.2-laconic-0.1.4", "@cerc-io/nitro-node": "^0.1.15", - "@cerc-io/peer": "^0.2.69", - "@cerc-io/rpc-eth-client": "^0.2.69", - "@cerc-io/util": "^0.2.69", + "@cerc-io/peer": "^0.2.70", + "@cerc-io/rpc-eth-client": "^0.2.70", + "@cerc-io/util": "^0.2.70", "@ethersproject/providers": "^5.4.4", "@graphql-tools/utils": "^9.1.1", "@ipld/dag-cbor": "^8.0.0", diff --git a/packages/codegen/package.json b/packages/codegen/package.json index 323097b4c..57197cefd 100644 --- a/packages/codegen/package.json +++ b/packages/codegen/package.json @@ -1,6 +1,6 @@ { "name": "@cerc-io/codegen", - "version": "0.2.69", + "version": "0.2.70", "description": "Code generator", "private": true, "main": "index.js", @@ -20,7 +20,7 @@ }, "homepage": "https://github.com/cerc-io/watcher-ts#readme", "dependencies": { - "@cerc-io/util": "^0.2.69", + "@cerc-io/util": "^0.2.70", "@graphql-tools/load-files": "^6.5.2", "@poanet/solidity-flattener": "https://github.com/vulcanize/solidity-flattener.git", "@solidity-parser/parser": "^0.13.2", diff --git a/packages/codegen/src/templates/package-template.handlebars b/packages/codegen/src/templates/package-template.handlebars index 37e5bec05..8aefd1c99 100644 --- a/packages/codegen/src/templates/package-template.handlebars +++ b/packages/codegen/src/templates/package-template.handlebars @@ -41,12 +41,12 @@ "homepage": "https://github.com/cerc-io/watcher-ts#readme", "dependencies": { "@apollo/client": "^3.3.19", - "@cerc-io/cli": "^0.2.69", - "@cerc-io/ipld-eth-client": "^0.2.69", - "@cerc-io/solidity-mapper": "^0.2.69", - "@cerc-io/util": "^0.2.69", + "@cerc-io/cli": "^0.2.70", + "@cerc-io/ipld-eth-client": "^0.2.70", + "@cerc-io/solidity-mapper": "^0.2.70", + "@cerc-io/util": "^0.2.70", {{#if (subgraphPath)}} - "@cerc-io/graph-node": "^0.2.69", + "@cerc-io/graph-node": "^0.2.70", {{/if}} "@ethersproject/providers": "^5.4.4", "debug": "^4.3.1", diff --git a/packages/graph-node/package.json b/packages/graph-node/package.json index b31851ae6..48b9af7d0 100644 --- a/packages/graph-node/package.json +++ b/packages/graph-node/package.json @@ -1,10 +1,10 @@ { "name": "@cerc-io/graph-node", - "version": "0.2.69", + "version": "0.2.70", "main": "dist/index.js", "license": "AGPL-3.0", "devDependencies": { - "@cerc-io/solidity-mapper": "^0.2.69", + "@cerc-io/solidity-mapper": "^0.2.70", "@ethersproject/providers": "^5.4.4", "@graphprotocol/graph-ts": "^0.22.0", "@nomiclabs/hardhat-ethers": "^2.0.2", @@ -51,9 +51,9 @@ "dependencies": { "@apollo/client": "^3.3.19", "@cerc-io/assemblyscript": "0.19.10-watcher-ts-0.1.2", - "@cerc-io/cache": "^0.2.69", - "@cerc-io/ipld-eth-client": "^0.2.69", - "@cerc-io/util": "^0.2.69", + "@cerc-io/cache": "^0.2.70", + "@cerc-io/ipld-eth-client": "^0.2.70", + "@cerc-io/util": "^0.2.70", "@types/json-diff": "^0.5.2", "@types/yargs": "^17.0.0", "bn.js": "^4.11.9", diff --git a/packages/graph-node/src/loader.ts b/packages/graph-node/src/loader.ts index e4fc9e7f8..a2eaa14d7 100644 --- a/packages/graph-node/src/loader.ts +++ b/packages/graph-node/src/loader.ts @@ -459,6 +459,25 @@ export const instantiate = async ( return mulResultBigDecimal; }, + 'bigDecimal.pow': async (x: number, y: number) => { + // Create decimal x string. + const xBigDecimal = await BigDecimal.wrap(x); + const xStringPtr = await xBigDecimal.toString(); + const xDecimalString = __getString(xStringPtr); + const xDecimal = new GraphDecimal(xDecimalString); + + // Create decimal y string. + const yBigDecimal = await BigDecimal.wrap(y); + const yStringPtr = await yBigDecimal.toString(); + const yDecimalString = __getString(yStringPtr); + + // Perform the decimal pow operation. + const powResult = xDecimal.pow(yDecimalString); + const ptr = await __newString(powResult.toString()); + const powResultBigDecimal = await BigDecimal.fromString(ptr); + + return powResultBigDecimal; + }, 'bigInt.fromString': async (s: number) => { const string = __getString(s); diff --git a/packages/ipld-eth-client/package.json b/packages/ipld-eth-client/package.json index 842af2c81..03755c75d 100644 --- a/packages/ipld-eth-client/package.json +++ b/packages/ipld-eth-client/package.json @@ -1,6 +1,6 @@ { "name": "@cerc-io/ipld-eth-client", - "version": "0.2.69", + "version": "0.2.70", "description": "IPLD ETH Client", "main": "dist/index.js", "scripts": { @@ -20,8 +20,8 @@ "homepage": "https://github.com/cerc-io/watcher-ts#readme", "dependencies": { "@apollo/client": "^3.7.1", - "@cerc-io/cache": "^0.2.69", - "@cerc-io/util": "^0.2.69", + "@cerc-io/cache": "^0.2.70", + "@cerc-io/util": "^0.2.70", "cross-fetch": "^3.1.4", "debug": "^4.3.1", "ethers": "^5.4.4", diff --git a/packages/peer/package.json b/packages/peer/package.json index de45e2b5b..a0e08a0d5 100644 --- a/packages/peer/package.json +++ b/packages/peer/package.json @@ -1,6 +1,6 @@ { "name": "@cerc-io/peer", - "version": "0.2.69", + "version": "0.2.70", "description": "libp2p module", "main": "dist/index.js", "exports": "./dist/index.js", diff --git a/packages/rpc-eth-client/package.json b/packages/rpc-eth-client/package.json index 7f2a391b6..5286dacaf 100644 --- a/packages/rpc-eth-client/package.json +++ b/packages/rpc-eth-client/package.json @@ -1,6 +1,6 @@ { "name": "@cerc-io/rpc-eth-client", - "version": "0.2.69", + "version": "0.2.70", "description": "RPC ETH Client", "main": "dist/index.js", "scripts": { @@ -19,9 +19,9 @@ }, "homepage": "https://github.com/cerc-io/watcher-ts#readme", "dependencies": { - "@cerc-io/cache": "^0.2.69", - "@cerc-io/ipld-eth-client": "^0.2.69", - "@cerc-io/util": "^0.2.69", + "@cerc-io/cache": "^0.2.70", + "@cerc-io/ipld-eth-client": "^0.2.70", + "@cerc-io/util": "^0.2.70", "chai": "^4.3.4", "ethers": "^5.4.4", "left-pad": "^1.3.0", diff --git a/packages/rpc-eth-client/src/eth-client.ts b/packages/rpc-eth-client/src/eth-client.ts index 14ab70a5d..5913193b0 100644 --- a/packages/rpc-eth-client/src/eth-client.ts +++ b/packages/rpc-eth-client/src/eth-client.ts @@ -6,9 +6,11 @@ import assert from 'assert'; import { errors, providers, utils } from 'ethers'; import { Cache } from '@cerc-io/cache'; -import { encodeHeader, escapeHexString, EthClient as EthClientInterface, EthFullTransaction } from '@cerc-io/util'; +import { encodeHeader, escapeHexString, EthClient as EthClientInterface, EthFullBlock, EthFullTransaction } from '@cerc-io/util'; import { padKey } from '@cerc-io/ipld-eth-client'; +const FUTURE_BLOCK_ERROR = "requested a future epoch (beyond 'latest')"; + export interface Config { cache: Cache | undefined; rpcEndpoint: string; @@ -68,11 +70,12 @@ export class EthClient implements EthClientInterface { const blockHashOrBlockNumber = blockHash ?? blockNumber; assert(blockHashOrBlockNumber); console.time(`time:eth-client#getBlockWithTransactions-${JSON.stringify({ blockNumber, blockHash })}`); - const result = await this._provider.getBlockWithTransactions(blockHashOrBlockNumber); - console.timeEnd(`time:eth-client#getBlockWithTransactions-${JSON.stringify({ blockNumber, blockHash })}`); + let nodes: any[] = []; - const allEthHeaderCids = { - nodes: [ + try { + const result = await this._provider.getBlockWithTransactions(blockHashOrBlockNumber); + + nodes = [ { blockNumber: result.number.toString(), blockHash: result.hash, @@ -88,10 +91,21 @@ export class EthClient implements EthClientInterface { })) } } - ] - }; + ]; + } catch (err: any) { + // Check and ignore future block error + if (!(err.code === errors.SERVER_ERROR && err.error && err.error.message === FUTURE_BLOCK_ERROR)) { + throw err; + } + } finally { + console.timeEnd(`time:eth-client#getBlockWithTransactions-${JSON.stringify({ blockNumber, blockHash })}`); + } - return { allEthHeaderCids }; + return { + allEthHeaderCids: { + nodes + } + }; } async getBlocks ({ blockNumber, blockHash }: { blockNumber?: number, blockHash?: string }): Promise { @@ -125,7 +139,7 @@ export class EthClient implements EthClientInterface { } } catch (err: any) { // Check and ignore future block error - if (!(err.code === errors.SERVER_ERROR && err.error && err.error.message === "requested a future epoch (beyond 'latest')")) { + if (!(err.code === errors.SERVER_ERROR && err.error && err.error.message === FUTURE_BLOCK_ERROR)) { throw err; } } finally { @@ -139,57 +153,69 @@ export class EthClient implements EthClientInterface { }; } - async getFullBlocks ({ blockNumber, blockHash }: { blockNumber?: number, blockHash?: string }): Promise { + async getFullBlocks ({ blockNumber, blockHash }: { blockNumber?: number, blockHash?: string }): Promise { const blockNumberHex = blockNumber ? utils.hexValue(blockNumber) : undefined; const blockHashOrBlockNumber = blockHash ?? blockNumberHex; assert(blockHashOrBlockNumber); - console.time(`time:eth-client#getFullBlocks-${JSON.stringify({ blockNumber, blockHash })}`); - const rawBlock = await this._provider.send( - blockHash ? 'eth_getBlockByHash' : 'eth_getBlockByNumber', - [blockHashOrBlockNumber, false] - ); - console.timeEnd(`time:eth-client#getFullBlocks-${JSON.stringify({ blockNumber, blockHash })}`); - - // Create block header - // https://github.com/cerc-io/go-ethereum/blob/v1.11.6-statediff-5.0.8/core/types/block.go#L64 - const header = { - Parent: rawBlock.parentHash, - UnclesDigest: rawBlock.sha3Uncles, - Beneficiary: rawBlock.miner, - StateRoot: rawBlock.stateRoot, - TxRoot: rawBlock.transactionsRoot, - RctRoot: rawBlock.receiptsRoot, - Bloom: rawBlock.logsBloom, - Difficulty: BigInt(rawBlock.difficulty), - Number: BigInt(rawBlock.number), - GasLimit: BigInt(rawBlock.gasLimit), - GasUsed: BigInt(rawBlock.gasUsed), - Time: Number(rawBlock.timestamp), - Extra: rawBlock.extraData, - MixDigest: rawBlock.mixHash, - Nonce: BigInt(rawBlock.nonce), - BaseFee: rawBlock.baseFeePerGas && BigInt(rawBlock.baseFeePerGas) - }; - const rlpData = encodeHeader(header); - - return [{ - blockNumber: this._provider.formatter.number(rawBlock.number).toString(), - blockHash: this._provider.formatter.hash(rawBlock.hash), - parentHash: this._provider.formatter.hash(rawBlock.parentHash), - timestamp: this._provider.formatter.number(rawBlock.timestamp).toString(), - stateRoot: this._provider.formatter.hash(rawBlock.stateRoot), - td: this._provider.formatter.bigNumber(rawBlock.totalDifficulty).toString(), - txRoot: this._provider.formatter.hash(rawBlock.transactionsRoot), - receiptRoot: this._provider.formatter.hash(rawBlock.receiptsRoot), - uncleRoot: this._provider.formatter.hash(rawBlock.sha3Uncles), - bloom: escapeHexString(this._provider.formatter.hex(rawBlock.logsBloom)), - size: this._provider.formatter.number(rawBlock.size).toString(), - blockByMhKey: { - data: escapeHexString(rlpData) + try { + const rawBlock = await this._provider.send( + blockHash ? 'eth_getBlockByHash' : 'eth_getBlockByNumber', + [blockHashOrBlockNumber, false] + ); + + if (rawBlock) { + // Create block header + // https://github.com/cerc-io/go-ethereum/blob/v1.11.6-statediff-5.0.8/core/types/block.go#L64 + const header = { + Parent: rawBlock.parentHash, + UnclesDigest: rawBlock.sha3Uncles, + Beneficiary: rawBlock.miner, + StateRoot: rawBlock.stateRoot, + TxRoot: rawBlock.transactionsRoot, + RctRoot: rawBlock.receiptsRoot, + Bloom: rawBlock.logsBloom, + Difficulty: BigInt(rawBlock.difficulty), + Number: BigInt(rawBlock.number), + GasLimit: BigInt(rawBlock.gasLimit), + GasUsed: BigInt(rawBlock.gasUsed), + Time: Number(rawBlock.timestamp), + Extra: rawBlock.extraData, + MixDigest: rawBlock.mixHash, + Nonce: BigInt(rawBlock.nonce), + BaseFee: rawBlock.baseFeePerGas && BigInt(rawBlock.baseFeePerGas) + }; + + const rlpData = encodeHeader(header); + + return [{ + blockNumber: this._provider.formatter.number(rawBlock.number).toString(), + blockHash: this._provider.formatter.hash(rawBlock.hash), + parentHash: this._provider.formatter.hash(rawBlock.parentHash), + timestamp: this._provider.formatter.number(rawBlock.timestamp).toString(), + stateRoot: this._provider.formatter.hash(rawBlock.stateRoot), + td: this._provider.formatter.bigNumber(rawBlock.totalDifficulty).toString(), + txRoot: this._provider.formatter.hash(rawBlock.transactionsRoot), + receiptRoot: this._provider.formatter.hash(rawBlock.receiptsRoot), + uncleRoot: this._provider.formatter.hash(rawBlock.sha3Uncles), + bloom: escapeHexString(this._provider.formatter.hex(rawBlock.logsBloom)), + size: this._provider.formatter.number(rawBlock.size).toString(), + blockByMhKey: { + data: escapeHexString(rlpData) + } + }]; + } + } catch (err: any) { + // Check and ignore future block error + if (!(err.code === errors.SERVER_ERROR && err.error && err.error.message === FUTURE_BLOCK_ERROR)) { + throw err; } - }]; + } finally { + console.timeEnd(`time:eth-client#getFullBlocks-${JSON.stringify({ blockNumber, blockHash })}`); + } + + return []; } async getFullTransaction (txHash: string): Promise { diff --git a/packages/solidity-mapper/package.json b/packages/solidity-mapper/package.json index 659b72023..7f47ede45 100644 --- a/packages/solidity-mapper/package.json +++ b/packages/solidity-mapper/package.json @@ -1,6 +1,6 @@ { "name": "@cerc-io/solidity-mapper", - "version": "0.2.69", + "version": "0.2.70", "main": "dist/index.js", "license": "AGPL-3.0", "devDependencies": { diff --git a/packages/test/package.json b/packages/test/package.json index c40d64680..291c4d712 100644 --- a/packages/test/package.json +++ b/packages/test/package.json @@ -1,6 +1,6 @@ { "name": "@cerc-io/test", - "version": "0.2.69", + "version": "0.2.70", "main": "dist/index.js", "license": "AGPL-3.0", "private": true, diff --git a/packages/tracing-client/package.json b/packages/tracing-client/package.json index 9264f0e52..311610c55 100644 --- a/packages/tracing-client/package.json +++ b/packages/tracing-client/package.json @@ -1,6 +1,6 @@ { "name": "@cerc-io/tracing-client", - "version": "0.2.69", + "version": "0.2.70", "description": "ETH VM tracing client", "main": "dist/index.js", "scripts": { diff --git a/packages/util/package.json b/packages/util/package.json index 6bd6cb4d5..c81f2883d 100644 --- a/packages/util/package.json +++ b/packages/util/package.json @@ -1,13 +1,13 @@ { "name": "@cerc-io/util", - "version": "0.2.69", + "version": "0.2.70", "main": "dist/index.js", "license": "AGPL-3.0", "dependencies": { "@apollo/utils.keyvaluecache": "^1.0.1", "@cerc-io/nitro-node": "^0.1.15", - "@cerc-io/peer": "^0.2.69", - "@cerc-io/solidity-mapper": "^0.2.69", + "@cerc-io/peer": "^0.2.70", + "@cerc-io/solidity-mapper": "^0.2.70", "@cerc-io/ts-channel": "1.0.3-ts-nitro-0.1.1", "@ethersproject/properties": "^5.7.0", "@ethersproject/providers": "^5.4.4", @@ -52,7 +52,7 @@ "yargs": "^17.0.1" }, "devDependencies": { - "@cerc-io/cache": "^0.2.69", + "@cerc-io/cache": "^0.2.70", "@nomiclabs/hardhat-waffle": "^2.0.1", "@types/bunyan": "^1.8.8", "@types/express": "^4.17.14",