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
This commit is contained in:
Nabarun Gogoi 2023-10-25 11:04:12 +05:30 committed by GitHub
parent e8d8476bef
commit 07887c160e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
24 changed files with 61 additions and 23 deletions

View File

@ -14,7 +14,7 @@ columns:
columnType: PrimaryGeneratedColumn columnType: PrimaryGeneratedColumn
- name: cid - name: cid
pgType: varchar pgType: varchar
tsType: string tsType: string | null
columnType: Column columnType: Column
columnOptions: columnOptions:
- option: nullable - option: nullable

View File

@ -12,9 +12,6 @@ columns:
pgType: integer pgType: integer
tsType: number tsType: number
columnType: Column columnType: Column
columnOptions:
- option: nullable
value: true
imports: imports:
- toImport: - toImport:
- Entity - Entity

View File

@ -538,6 +538,8 @@ export class Entity {
option: 'nullable', option: 'nullable',
value: 'true' value: 'true'
}); });
columnObject.tsType = `${tsType} | null`;
} }
entityObject.columns.push(columnObject); entityObject.columns.push(columnObject);

View File

@ -30,6 +30,9 @@
# Use -1 for skipping check on block range. # Use -1 for skipping check on block range.
maxEventsBlockRange = 1000 maxEventsBlockRange = 1000
# Flag to specify whether RPC endpoint supports block hash as block tag parameter
rpcSupportsBlockHashParam = true
# GQL cache settings # GQL cache settings
[server.gqlCache] [server.gqlCache]
enabled = true enabled = true

View File

@ -116,7 +116,15 @@
yarn && yarn build 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 ```bash
yarn job-runner yarn job-runner

View File

@ -71,6 +71,7 @@ xdescribe('call handler in mapping code', () => {
indexer, indexer,
provider, provider,
{ {
rpcSupportsBlockHashParam: true,
block: dummyEventData.block, block: dummyEventData.block,
contractAddress: dummyGraphData.dataSource.address contractAddress: dummyGraphData.dataSource.address
}, },

View File

@ -33,7 +33,7 @@ describe('crypto host api', () => {
db, db,
indexer, indexer,
provider, provider,
{}, { rpcSupportsBlockHashParam: true },
filePath, filePath,
dummyGraphData dummyGraphData
); );

View File

@ -90,6 +90,7 @@ xdescribe('eden wasm loader tests', async () => {
indexer, indexer,
provider, provider,
{ {
rpcSupportsBlockHashParam: true,
block: dummyEventData.block, block: dummyEventData.block,
contractAddress contractAddress
}, },
@ -210,6 +211,7 @@ xdescribe('eden wasm loader tests', async () => {
indexer, indexer,
provider, provider,
{ {
rpcSupportsBlockHashParam: true,
block: dummyEventData.block, block: dummyEventData.block,
contractAddress contractAddress
}, },
@ -328,6 +330,7 @@ xdescribe('eden wasm loader tests', async () => {
indexer, indexer,
provider, provider,
{ {
rpcSupportsBlockHashParam: true,
block: dummyEventData.block, block: dummyEventData.block,
contractAddress contractAddress
}, },

View File

@ -33,7 +33,7 @@ describe('ethereum ABI encode decode', () => {
db, db,
indexer, indexer,
provider, provider,
{}, { rpcSupportsBlockHashParam: true },
filePath, filePath,
dummyGraphData dummyGraphData
); );

View File

@ -51,6 +51,7 @@ xdescribe('eth-call wasm tests', () => {
indexer, indexer,
provider, provider,
{ {
rpcSupportsBlockHashParam: true,
block: dummyEventData.block, block: dummyEventData.block,
contractAddress contractAddress
}, },

View File

@ -31,7 +31,7 @@ describe('json host api', () => {
db, db,
indexer, indexer,
provider, provider,
{}, { rpcSupportsBlockHashParam: true },
filePath, filePath,
dummyGraphData dummyGraphData
); );

View File

@ -35,7 +35,7 @@ describe('wasm loader tests', () => {
db, db,
indexer, indexer,
provider, provider,
{}, { rpcSupportsBlockHashParam: true },
filePath, filePath,
dummyGraphData dummyGraphData
); );
@ -113,7 +113,7 @@ describe('wasm loader tests', () => {
db, db,
indexer, indexer,
provider, provider,
{}, { rpcSupportsBlockHashParam: true },
module, module,
dummyGraphData dummyGraphData
); );

View File

@ -47,8 +47,9 @@ export interface GraphData {
} }
export interface Context { export interface Context {
block?: Block rpcSupportsBlockHashParam: boolean;
contractAddress?: string block?: Block;
contractAddress?: string;
} }
const log = debug('vulcanize:graph-node'); const log = debug('vulcanize:graph-node');
@ -173,10 +174,21 @@ export const instantiate = async (
functionParams = await Promise.all(functionParamsPromise); functionParams = await Promise.all(functionParamsPromise);
assert(context.block); assert(context.block);
let result: any;
// TODO: Check for function overloading. // TODO: Check for function overloading.
console.time(`time:loader#ethereum.call-${functionName}`); 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}`); console.timeEnd(`time:loader#ethereum.call-${functionName}`);
// Using function signature does not work. // Using function signature does not work.

View File

@ -44,7 +44,7 @@ describe('numbers wasm tests', () => {
db, db,
indexer, indexer,
provider, provider,
{}, { rpcSupportsBlockHashParam: true },
filePath, filePath,
dummyGraphData dummyGraphData
); );

View File

@ -52,6 +52,7 @@ xdescribe('storage-call wasm tests', () => {
indexer, indexer,
provider, provider,
{ {
rpcSupportsBlockHashParam: true,
block: dummyEventData.block, block: dummyEventData.block,
contractAddress contractAddress
}, },

View File

@ -33,7 +33,7 @@ describe('typeConversion wasm tests', () => {
db, db,
indexer, indexer,
provider, provider,
{}, { rpcSupportsBlockHashParam: true },
filePath, filePath,
dummyGraphData dummyGraphData
); );

View File

@ -52,7 +52,7 @@ export class GraphWatcher {
_dataSourceMap: { [key: string]: DataSource } = {}; _dataSourceMap: { [key: string]: DataSource } = {};
_transactionsMap: Map<string, Transaction> = new Map(); _transactionsMap: Map<string, Transaction> = new Map();
_context: Context = {}; _context: Context;
constructor (database: GraphDatabase, ethClient: EthClient, ethProvider: providers.BaseProvider, serverConfig: ServerConfig) { constructor (database: GraphDatabase, ethClient: EthClient, ethProvider: providers.BaseProvider, serverConfig: ServerConfig) {
this._database = database; this._database = database;
@ -60,6 +60,10 @@ export class GraphWatcher {
this._ethProvider = ethProvider; this._ethProvider = ethProvider;
this._subgraphPath = serverConfig.subgraphPath; this._subgraphPath = serverConfig.subgraphPath;
this._wasmRestartBlocksInterval = serverConfig.wasmRestartBlocksInterval; this._wasmRestartBlocksInterval = serverConfig.wasmRestartBlocksInterval;
this._context = {
rpcSupportsBlockHashParam: Boolean(serverConfig.rpcSupportsBlockHashParam)
};
} }
async init () { async init () {

View File

@ -166,7 +166,7 @@ export class EthClient implements EthClientInterface {
Extra: rawBlock.extraData, Extra: rawBlock.extraData,
MixDigest: rawBlock.mixHash, MixDigest: rawBlock.mixHash,
Nonce: BigInt(rawBlock.nonce), Nonce: BigInt(rawBlock.nonce),
BaseFee: BigInt(rawBlock.baseFeePerGas) BaseFee: rawBlock.baseFeePerGas ?? BigInt(rawBlock.baseFeePerGas)
}; };
const rlpData = encodeHeader(header); const rlpData = encodeHeader(header);

View File

@ -221,6 +221,7 @@ export interface ServerConfig {
p2p: P2PConfig; p2p: P2PConfig;
// TODO: Move flag to config upstream.ethServer
// Flag to specify whether RPC endpoint supports block hash as block tag parameter // Flag to specify whether RPC endpoint supports block hash as block tag parameter
// https://ethereum.org/en/developers/docs/apis/json-rpc/#default-block // https://ethereum.org/en/developers/docs/apis/json-rpc/#default-block
rpcSupportsBlockHashParam: boolean; rpcSupportsBlockHashParam: boolean;

View File

@ -151,7 +151,12 @@ export const getContractEntitiesMap = (dataSources: any[]): Map<string, string[]
// Populate contractEntitiesMap using data sources from subgraph // Populate contractEntitiesMap using data sources from subgraph
dataSources.forEach((dataSource: any) => { dataSources.forEach((dataSource: any) => {
const { source: { address: contractAddress }, mapping: { entities } } = dataSource; 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; return contractEntitiesMap;

View File

@ -550,7 +550,7 @@ export const toEntityValue = async (instanceExports: any, entityInstance: any, d
// Check if the entity property is nullable. // Check if the entity property is nullable.
// No need to set the property if the value is null as well. // No need to set the property if the value is null as well.
if (isNullable && value === null) { if (isNullable && value === null) {
return; return value;
} }
const entityValue = await formatEntityValue(instanceExports, subgraphValue, type, value, isArray); const entityValue = await formatEntityValue(instanceExports, subgraphValue, type, value, isArray);

View File

@ -52,7 +52,7 @@ export interface StateStatus {
export type ResultState = { export type ResultState = {
block: { block: {
cid: string; cid: string | null;
hash: string; hash: string;
number: number; number: number;
timestamp: number; timestamp: number;
@ -66,7 +66,7 @@ export type ResultState = {
export type ResultEvent = { export type ResultEvent = {
block: { block: {
cid: string; cid: string | null;
hash: string; hash: string;
number: number; number: number;
timestamp: number; timestamp: number;

View File

@ -20,7 +20,7 @@ export interface StateDataMeta {
}, },
ethBlock: { ethBlock: {
cid: { cid: {
'/': string '/': string | null
}, },
num: number num: number
} }

View File

@ -19,7 +19,7 @@ export enum StateKind {
export interface BlockProgressInterface { export interface BlockProgressInterface {
id: number; id: number;
cid: string; cid: string | null;
blockHash: string; blockHash: string;
parentHash: string; parentHash: string;
blockNumber: number; blockNumber: number;