From 07887c160ef8b6f5eabffd40a51e973dcbaa6c3c Mon Sep 17 00:00:00 2001 From: Nabarun Gogoi Date: Wed, 25 Oct 2023 11:04:12 +0530 Subject: [PATCH] Use block number for eth_call in `rpc-eth-client` (#435) * Update subgraph readme to run fill before job-runner * Fix getContractEntitiesMap incase of template data sources * Use rpcSupportsBlockHashParam flag to use blockNumber for rpc client eth_call * Fix optional baseFeePerGas in rpc-eth-client * Fix graph-node tests after changes * Remove completed TODO --- .../src/data/entities/BlockProgress.yaml | 2 +- .../src/data/entities/StateSyncStatus.yaml | 3 --- packages/codegen/src/entity.ts | 2 ++ .../src/templates/config-template.handlebars | 3 +++ packages/codegen/subgraph-demo.md | 10 +++++++++- packages/graph-node/src/call-handler.test.ts | 1 + packages/graph-node/src/crypto.test.ts | 2 +- packages/graph-node/src/eden.test.ts | 3 +++ packages/graph-node/src/eth-abi.test.ts | 2 +- packages/graph-node/src/eth-call.test.ts | 1 + packages/graph-node/src/json.test.ts | 2 +- packages/graph-node/src/loader.test.ts | 4 ++-- packages/graph-node/src/loader.ts | 18 +++++++++++++++--- packages/graph-node/src/numbers.test.ts | 2 +- packages/graph-node/src/storage-call.test.ts | 1 + .../graph-node/src/type-conversion.test.ts | 2 +- packages/graph-node/src/watcher.ts | 6 +++++- packages/rpc-eth-client/src/eth-client.ts | 2 +- packages/util/src/config.ts | 1 + packages/util/src/graph/state-utils.ts | 7 ++++++- packages/util/src/graph/utils.ts | 2 +- packages/util/src/indexer.ts | 4 ++-- packages/util/src/state-helper.ts | 2 +- packages/util/src/types.ts | 2 +- 24 files changed, 61 insertions(+), 23 deletions(-) diff --git a/packages/codegen/src/data/entities/BlockProgress.yaml b/packages/codegen/src/data/entities/BlockProgress.yaml index d7bb75f4..e5db3740 100644 --- a/packages/codegen/src/data/entities/BlockProgress.yaml +++ b/packages/codegen/src/data/entities/BlockProgress.yaml @@ -14,7 +14,7 @@ columns: columnType: PrimaryGeneratedColumn - name: cid pgType: varchar - tsType: string + tsType: string | null columnType: Column columnOptions: - option: nullable diff --git a/packages/codegen/src/data/entities/StateSyncStatus.yaml b/packages/codegen/src/data/entities/StateSyncStatus.yaml index f402e2ba..0a62d5c1 100644 --- a/packages/codegen/src/data/entities/StateSyncStatus.yaml +++ b/packages/codegen/src/data/entities/StateSyncStatus.yaml @@ -12,9 +12,6 @@ columns: pgType: integer tsType: number columnType: Column - columnOptions: - - option: nullable - value: true imports: - toImport: - Entity diff --git a/packages/codegen/src/entity.ts b/packages/codegen/src/entity.ts index 374ccb1b..981d5a25 100644 --- a/packages/codegen/src/entity.ts +++ b/packages/codegen/src/entity.ts @@ -538,6 +538,8 @@ export class Entity { option: 'nullable', value: 'true' }); + + columnObject.tsType = `${tsType} | null`; } entityObject.columns.push(columnObject); diff --git a/packages/codegen/src/templates/config-template.handlebars b/packages/codegen/src/templates/config-template.handlebars index 63ea8ce3..35e76ed4 100644 --- a/packages/codegen/src/templates/config-template.handlebars +++ b/packages/codegen/src/templates/config-template.handlebars @@ -30,6 +30,9 @@ # Use -1 for skipping check on block range. maxEventsBlockRange = 1000 + # Flag to specify whether RPC endpoint supports block hash as block tag parameter + rpcSupportsBlockHashParam = true + # GQL cache settings [server.gqlCache] enabled = true diff --git a/packages/codegen/subgraph-demo.md b/packages/codegen/subgraph-demo.md index acde0745..58144214 100644 --- a/packages/codegen/subgraph-demo.md +++ b/packages/codegen/subgraph-demo.md @@ -116,7 +116,15 @@ yarn && yarn build ``` -* In `packages/test-watcher`, run the job-runner: +* In `packages/test-watcher`, run fill for the subgraph start block: + + ```bash + yarn fill --start-block 10 --end-block 10 + ``` + + * Subgraph start block is the lowest `startBlock` in example [subgraph.yaml](../graph-node/test/subgraph/example1/subgraph.yaml) + +* Run the job-runner: ```bash yarn job-runner diff --git a/packages/graph-node/src/call-handler.test.ts b/packages/graph-node/src/call-handler.test.ts index 4bd9214d..6e6d4522 100644 --- a/packages/graph-node/src/call-handler.test.ts +++ b/packages/graph-node/src/call-handler.test.ts @@ -71,6 +71,7 @@ xdescribe('call handler in mapping code', () => { indexer, provider, { + rpcSupportsBlockHashParam: true, block: dummyEventData.block, contractAddress: dummyGraphData.dataSource.address }, diff --git a/packages/graph-node/src/crypto.test.ts b/packages/graph-node/src/crypto.test.ts index 80f4e584..67cc25dd 100644 --- a/packages/graph-node/src/crypto.test.ts +++ b/packages/graph-node/src/crypto.test.ts @@ -33,7 +33,7 @@ describe('crypto host api', () => { db, indexer, provider, - {}, + { rpcSupportsBlockHashParam: true }, filePath, dummyGraphData ); diff --git a/packages/graph-node/src/eden.test.ts b/packages/graph-node/src/eden.test.ts index 7f3d9628..1a295279 100644 --- a/packages/graph-node/src/eden.test.ts +++ b/packages/graph-node/src/eden.test.ts @@ -90,6 +90,7 @@ xdescribe('eden wasm loader tests', async () => { indexer, provider, { + rpcSupportsBlockHashParam: true, block: dummyEventData.block, contractAddress }, @@ -210,6 +211,7 @@ xdescribe('eden wasm loader tests', async () => { indexer, provider, { + rpcSupportsBlockHashParam: true, block: dummyEventData.block, contractAddress }, @@ -328,6 +330,7 @@ xdescribe('eden wasm loader tests', async () => { indexer, provider, { + rpcSupportsBlockHashParam: true, block: dummyEventData.block, contractAddress }, diff --git a/packages/graph-node/src/eth-abi.test.ts b/packages/graph-node/src/eth-abi.test.ts index f59d1534..a014231c 100644 --- a/packages/graph-node/src/eth-abi.test.ts +++ b/packages/graph-node/src/eth-abi.test.ts @@ -33,7 +33,7 @@ describe('ethereum ABI encode decode', () => { db, indexer, provider, - {}, + { rpcSupportsBlockHashParam: true }, filePath, dummyGraphData ); diff --git a/packages/graph-node/src/eth-call.test.ts b/packages/graph-node/src/eth-call.test.ts index 700612fe..31642f30 100644 --- a/packages/graph-node/src/eth-call.test.ts +++ b/packages/graph-node/src/eth-call.test.ts @@ -51,6 +51,7 @@ xdescribe('eth-call wasm tests', () => { indexer, provider, { + rpcSupportsBlockHashParam: true, block: dummyEventData.block, contractAddress }, diff --git a/packages/graph-node/src/json.test.ts b/packages/graph-node/src/json.test.ts index 7bb0fe2f..76603799 100644 --- a/packages/graph-node/src/json.test.ts +++ b/packages/graph-node/src/json.test.ts @@ -31,7 +31,7 @@ describe('json host api', () => { db, indexer, provider, - {}, + { rpcSupportsBlockHashParam: true }, filePath, dummyGraphData ); diff --git a/packages/graph-node/src/loader.test.ts b/packages/graph-node/src/loader.test.ts index 59666563..1912eb6a 100644 --- a/packages/graph-node/src/loader.test.ts +++ b/packages/graph-node/src/loader.test.ts @@ -35,7 +35,7 @@ describe('wasm loader tests', () => { db, indexer, provider, - {}, + { rpcSupportsBlockHashParam: true }, filePath, dummyGraphData ); @@ -113,7 +113,7 @@ describe('wasm loader tests', () => { db, indexer, provider, - {}, + { rpcSupportsBlockHashParam: true }, module, dummyGraphData ); diff --git a/packages/graph-node/src/loader.ts b/packages/graph-node/src/loader.ts index d8b157cb..82e78e12 100644 --- a/packages/graph-node/src/loader.ts +++ b/packages/graph-node/src/loader.ts @@ -47,8 +47,9 @@ export interface GraphData { } export interface Context { - block?: Block - contractAddress?: string + rpcSupportsBlockHashParam: boolean; + block?: Block; + contractAddress?: string; } const log = debug('vulcanize:graph-node'); @@ -173,10 +174,21 @@ export const instantiate = async ( functionParams = await Promise.all(functionParamsPromise); assert(context.block); + let result: any; // TODO: Check for function overloading. console.time(`time:loader#ethereum.call-${functionName}`); - let result = await contract[functionName](...functionParams, { blockTag: context.block.blockHash }); + if (context.rpcSupportsBlockHashParam) { + result = await contract[functionName]( + ...functionParams, + { blockTag: context.block.blockHash } + ); + } else { + result = await contract[functionName]( + ...functionParams, + { blockTag: BigNumber.from(context.block.blockNumber).toHexString() } + ); + } console.timeEnd(`time:loader#ethereum.call-${functionName}`); // Using function signature does not work. diff --git a/packages/graph-node/src/numbers.test.ts b/packages/graph-node/src/numbers.test.ts index f8fe3b96..4a88e8fa 100644 --- a/packages/graph-node/src/numbers.test.ts +++ b/packages/graph-node/src/numbers.test.ts @@ -44,7 +44,7 @@ describe('numbers wasm tests', () => { db, indexer, provider, - {}, + { rpcSupportsBlockHashParam: true }, filePath, dummyGraphData ); diff --git a/packages/graph-node/src/storage-call.test.ts b/packages/graph-node/src/storage-call.test.ts index eafb5c77..fa2bd73e 100644 --- a/packages/graph-node/src/storage-call.test.ts +++ b/packages/graph-node/src/storage-call.test.ts @@ -52,6 +52,7 @@ xdescribe('storage-call wasm tests', () => { indexer, provider, { + rpcSupportsBlockHashParam: true, block: dummyEventData.block, contractAddress }, diff --git a/packages/graph-node/src/type-conversion.test.ts b/packages/graph-node/src/type-conversion.test.ts index 6d9cbce0..c4315edb 100644 --- a/packages/graph-node/src/type-conversion.test.ts +++ b/packages/graph-node/src/type-conversion.test.ts @@ -33,7 +33,7 @@ describe('typeConversion wasm tests', () => { db, indexer, provider, - {}, + { rpcSupportsBlockHashParam: true }, filePath, dummyGraphData ); diff --git a/packages/graph-node/src/watcher.ts b/packages/graph-node/src/watcher.ts index 2dc6f9ed..dcea7f45 100644 --- a/packages/graph-node/src/watcher.ts +++ b/packages/graph-node/src/watcher.ts @@ -52,7 +52,7 @@ export class GraphWatcher { _dataSourceMap: { [key: string]: DataSource } = {}; _transactionsMap: Map = new Map(); - _context: Context = {}; + _context: Context; constructor (database: GraphDatabase, ethClient: EthClient, ethProvider: providers.BaseProvider, serverConfig: ServerConfig) { this._database = database; @@ -60,6 +60,10 @@ export class GraphWatcher { this._ethProvider = ethProvider; this._subgraphPath = serverConfig.subgraphPath; this._wasmRestartBlocksInterval = serverConfig.wasmRestartBlocksInterval; + + this._context = { + rpcSupportsBlockHashParam: Boolean(serverConfig.rpcSupportsBlockHashParam) + }; } async init () { diff --git a/packages/rpc-eth-client/src/eth-client.ts b/packages/rpc-eth-client/src/eth-client.ts index dc940013..e68fada0 100644 --- a/packages/rpc-eth-client/src/eth-client.ts +++ b/packages/rpc-eth-client/src/eth-client.ts @@ -166,7 +166,7 @@ export class EthClient implements EthClientInterface { Extra: rawBlock.extraData, MixDigest: rawBlock.mixHash, Nonce: BigInt(rawBlock.nonce), - BaseFee: BigInt(rawBlock.baseFeePerGas) + BaseFee: rawBlock.baseFeePerGas ?? BigInt(rawBlock.baseFeePerGas) }; const rlpData = encodeHeader(header); diff --git a/packages/util/src/config.ts b/packages/util/src/config.ts index 211adf6f..e74d8010 100644 --- a/packages/util/src/config.ts +++ b/packages/util/src/config.ts @@ -221,6 +221,7 @@ export interface ServerConfig { p2p: P2PConfig; + // TODO: Move flag to config upstream.ethServer // Flag to specify whether RPC endpoint supports block hash as block tag parameter // https://ethereum.org/en/developers/docs/apis/json-rpc/#default-block rpcSupportsBlockHashParam: boolean; diff --git a/packages/util/src/graph/state-utils.ts b/packages/util/src/graph/state-utils.ts index ba56a5e9..ce807107 100644 --- a/packages/util/src/graph/state-utils.ts +++ b/packages/util/src/graph/state-utils.ts @@ -151,7 +151,12 @@ export const getContractEntitiesMap = (dataSources: any[]): Map { const { source: { address: contractAddress }, mapping: { entities } } = dataSource; - contractEntitiesMap.set(ethers.utils.getAddress(contractAddress), entities as string[]); + + // TODO: Handle template data source + // TODO: Avoid mapping subgraph entities to contract address in watcher state + if (contractAddress) { + contractEntitiesMap.set(ethers.utils.getAddress(contractAddress), entities as string[]); + } }); return contractEntitiesMap; diff --git a/packages/util/src/graph/utils.ts b/packages/util/src/graph/utils.ts index d1c3d005..57c7163d 100644 --- a/packages/util/src/graph/utils.ts +++ b/packages/util/src/graph/utils.ts @@ -550,7 +550,7 @@ export const toEntityValue = async (instanceExports: any, entityInstance: any, d // Check if the entity property is nullable. // No need to set the property if the value is null as well. if (isNullable && value === null) { - return; + return value; } const entityValue = await formatEntityValue(instanceExports, subgraphValue, type, value, isArray); diff --git a/packages/util/src/indexer.ts b/packages/util/src/indexer.ts index 99799631..8914fbed 100644 --- a/packages/util/src/indexer.ts +++ b/packages/util/src/indexer.ts @@ -52,7 +52,7 @@ export interface StateStatus { export type ResultState = { block: { - cid: string; + cid: string | null; hash: string; number: number; timestamp: number; @@ -66,7 +66,7 @@ export type ResultState = { export type ResultEvent = { block: { - cid: string; + cid: string | null; hash: string; number: number; timestamp: number; diff --git a/packages/util/src/state-helper.ts b/packages/util/src/state-helper.ts index cfaf9877..e8bbfc8d 100644 --- a/packages/util/src/state-helper.ts +++ b/packages/util/src/state-helper.ts @@ -20,7 +20,7 @@ export interface StateDataMeta { }, ethBlock: { cid: { - '/': string + '/': string | null }, num: number } diff --git a/packages/util/src/types.ts b/packages/util/src/types.ts index d359a23d..604af557 100644 --- a/packages/util/src/types.ts +++ b/packages/util/src/types.ts @@ -19,7 +19,7 @@ export enum StateKind { export interface BlockProgressInterface { id: number; - cid: string; + cid: string | null; blockHash: string; parentHash: string; blockNumber: number;