Skip to content

Commit 8a59b2e

Browse files
authored
Add acceptance test support for eth_getLogs (#292)
Add acceptance test support for eth_getLogs Signed-off-by: nikolay <[email protected]>
1 parent 3f0b6e3 commit 8a59b2e

File tree

7 files changed

+399
-13
lines changed

7 files changed

+399
-13
lines changed

packages/relay/src/lib/constants.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,11 @@ enum CACHE_TTL {
2626
ONE_HOUR = 3_600_000
2727
}
2828

29+
enum ORDER {
30+
ASC = 'asc',
31+
DESC = 'desc'
32+
}
33+
2934
export default {
3035
TINYBAR_TO_WEIBAR_COEF: 10_000_000_000,
3136
CACHE_KEY,
@@ -39,5 +44,6 @@ export default {
3944
TYPE_CONTRACT: 'contract',
4045
TYPE_ACCOUNT: 'account',
4146

42-
FEE_HISTORY_MAX_RESULTS: Number(process.env.FEE_HISTORY_MAX_RESULTS || 10)
47+
FEE_HISTORY_MAX_RESULTS: Number(process.env.FEE_HISTORY_MAX_RESULTS || 10),
48+
ORDER
4349
};

packages/relay/src/lib/eth.ts

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1054,16 +1054,25 @@ export class EthImpl implements Eth {
10541054
];
10551055
}
10561056
}
1057-
else if (fromBlock && toBlock) {
1058-
const blocksResult = await this.mirrorNodeClient.getBlocks([
1059-
`gte:${fromBlock}`,
1060-
`lte:${toBlock}`
1061-
]);
1057+
else if (fromBlock || toBlock) {
1058+
const filters = [];
1059+
let order;
1060+
if(toBlock) {
1061+
// @ts-ignore
1062+
filters.push(`lte:${parseInt(toBlock)}`);
1063+
order = constants.ORDER.DESC;
1064+
}
1065+
if(fromBlock) {
1066+
// @ts-ignore
1067+
filters.push(`gte:${parseInt(fromBlock)}`);
1068+
order = constants.ORDER.ASC;
1069+
}
1070+
const blocksResult = await this.mirrorNodeClient.getBlocks(filters, undefined , {order});
10621071

10631072
const blocks = blocksResult?.blocks;
10641073
if (blocks?.length) {
1065-
const firstBlock = blocks[0];
1066-
const lastBlock = blocks[blocks.length - 1];
1074+
const firstBlock = (order == constants.ORDER.DESC) ? blocks[blocks.length - 1] : blocks[0];
1075+
const lastBlock = (order == constants.ORDER.DESC) ? blocks[0] : blocks[blocks.length - 1];
10671076
params.timestamp = [
10681077
`gte:${firstBlock.timestamp.from}`,
10691078
`lte:${lastBlock.timestamp.to}`

packages/relay/tests/lib/eth.spec.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -998,7 +998,7 @@ describe('Eth calls using MirrorNode', async function () {
998998
};
999999
mock.onGet(`contracts/${contractId1}/results/${contractTimestamp1}`).reply(200, defaultDetailedContractResults);
10001000
mock.onGet(`contracts/results/logs?timestamp=gte:${defaultBlock.timestamp.from}&timestamp=lte:${defaultBlock.timestamp.to}`).reply(200, filteredLogs);
1001-
mock.onGet('blocks?block.number=gte:0x5&block.number=lte:0x10').reply(200, {
1001+
mock.onGet('blocks?block.number=lte:16&block.number=gte:5&order=asc').reply(200, {
10021002
blocks: [defaultBlock]
10031003
});
10041004
const result = await ethImpl.getLogs(null, '0x5', '0x10', null, null);

packages/server/src/server.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -341,12 +341,13 @@ rpc.use('eth_getBlockTransactionCountByNumber', async (params: any) => {
341341
* returns: Logs - Array of log objects
342342
*/
343343
rpc.use('eth_getLogs', async (params: any) => {
344+
params = params[0] ?? [];
344345
return logAndHandleResponse('eth_getLogs', () => relay.eth().getLogs(
346+
params?.blockHash || null,
345347
params?.fromBlock || null,
346348
params?.toBlock || null,
347349
params?.address || null,
348-
params?.topics || null,
349-
params?.blockhash || null
350+
params?.topics || null
350351
));
351352
});
352353

packages/server/tests/acceptance/rpc.spec.ts

Lines changed: 134 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ import {AccountBalanceQuery, ContractFunctionParameters} from '@hashgraph/sdk';
2929
// local resources
3030
import parentContractJson from '../contracts/Parent.json';
3131
import basicContractJson from '../contracts/Basic.json';
32+
import logsContractJson from '../contracts/Logs.json';
3233
import { predefined } from '../../../relay/src/lib/errors';
3334

3435
describe('RPC Server Acceptance Tests', function () {
@@ -96,6 +97,137 @@ describe('RPC Server Acceptance Tests', function () {
9697
mirrorSecondaryAccount = (await mirrorNode.get(`accounts?account.id=${accounts[1].accountId}`)).accounts[0];
9798
});
9899

100+
describe('eth_getLogs', () => {
101+
102+
let log0Block, log4Block, contractAddress;
103+
104+
it('should deploy a contract', async () => {
105+
const logsContract = await servicesNode.deployContract(logsContractJson);
106+
const mirrorNodeResp = await mirrorNode.get(`/contracts/${logsContract.contractId}`);
107+
expect(mirrorNodeResp).to.have.property('evm_address');
108+
expect(mirrorNodeResp.env_address).to.not.be.null;
109+
contractAddress = mirrorNodeResp.evm_address;
110+
111+
const params = new ContractFunctionParameters().addUint256(1);
112+
const log0 = await accounts[1].client.executeContractCall(logsContract.contractId, 'log0', params);
113+
await accounts[1].client.executeContractCall(logsContract.contractId, 'log1', params);
114+
115+
params.addUint256(1);
116+
await accounts[1].client.executeContractCall(logsContract.contractId, 'log2', params);
117+
118+
params.addUint256(1);
119+
await accounts[1].client.executeContractCall(logsContract.contractId, 'log3', params);
120+
121+
params.addUint256(1);
122+
const log4 = await accounts[1].client.executeContractCall(logsContract.contractId, 'log4', params);
123+
124+
await new Promise(r => setTimeout(r, 5000));
125+
126+
const logs = await relay.call('eth_getLogs', [{}]);
127+
expect(logs.length).to.be.greaterThan(0);
128+
const txIndexLogIndexMapping: any[] = [];
129+
for(let i in logs) {
130+
expect(logs[i]).to.have.property('address');
131+
expect(logs[i]).to.have.property('logIndex');
132+
133+
const key = `${logs[i].transactionHash}---${logs[i].logIndex}`;
134+
txIndexLogIndexMapping.push(key);
135+
}
136+
const uniqueTxIndexLogIndexMapping = txIndexLogIndexMapping.filter((value, index, self) =>
137+
self.indexOf(value) === index
138+
);
139+
expect(txIndexLogIndexMapping.length).to.equal(uniqueTxIndexLogIndexMapping.length);
140+
141+
log0Block = await relay.call('eth_getTransactionByHash', [log0.contractExecutedTransactionId]);
142+
expect(log0Block).to.have.property('blockNumber');
143+
144+
log4Block = await relay.call('eth_getTransactionByHash', [log4.contractExecutedTransactionId]);
145+
expect(log4Block).to.have.property('blockNumber');
146+
});
147+
148+
it('should be able to use `fromBlock` param', async () => {
149+
const logs = await relay.call('eth_getLogs', [{
150+
'fromBlock': log4Block.blockNumber
151+
}]);
152+
expect(logs.length).to.be.greaterThan(0);
153+
154+
const log4BlockInt = parseInt(log4Block.blockNumber);
155+
for(let i in logs) {
156+
expect(logs[i].blockNumber).to.be.greaterThanOrEqual(log4BlockInt);
157+
}
158+
});
159+
160+
it('should be able to use `toBlock` param', async () => {
161+
const logs = await relay.call('eth_getLogs', [{
162+
'toBlock': log0Block.blockNumber
163+
}]);
164+
expect(logs.length).to.be.greaterThan(0);
165+
166+
const log0BlockInt = parseInt(log0Block.blockNumber);
167+
for(let i in logs) {
168+
expect(logs[i].blockNumber).to.be.lessThanOrEqual(log0BlockInt);
169+
}
170+
});
171+
172+
it('should be able to use range of `fromBlock` and `toBlock` params', async () => {
173+
const logs = await relay.call('eth_getLogs', [{
174+
'fromBlock': log0Block.blockNumber,
175+
'toBlock': log4Block.blockNumber
176+
}]);
177+
expect(logs.length).to.be.greaterThan(0);
178+
179+
const log0BlockInt = parseInt(log0Block.blockNumber);
180+
const log4BlockInt = parseInt(log4Block.blockNumber);
181+
for (let i in logs) {
182+
expect(logs[i].blockNumber).to.be.greaterThanOrEqual(log0BlockInt);
183+
expect(logs[i].blockNumber).to.be.lessThanOrEqual(log4BlockInt);
184+
}
185+
});
186+
187+
it('should be able to use `address` param', async() => {
188+
const logs = await relay.call('eth_getLogs', [{
189+
'address': contractAddress
190+
}]);
191+
expect(logs.length).to.be.greaterThan(0);
192+
193+
for(let i in logs) {
194+
expect(logs[i].address).to.equal(contractAddress);
195+
}
196+
});
197+
198+
it('should be able to use `blockHash` param', async() => {
199+
const logs = await relay.call('eth_getLogs', [{
200+
'blockHash': log0Block.blockHash
201+
}]);
202+
expect(logs.length).to.be.greaterThan(0);
203+
204+
for(let i in logs) {
205+
expect(logs[i].blockHash).to.equal(log0Block.blockHash);
206+
}
207+
});
208+
209+
it('should be able to use `topics` param', async() => {
210+
const logs = await relay.call('eth_getLogs', [{
211+
'fromBlock': log0Block.blockNumber,
212+
'toBlock': log4Block.blockNumber,
213+
}]);
214+
expect(logs.length).to.be.greaterThan(0);
215+
const topic = logs[0].topics[0];
216+
217+
const logsWithTopic = await relay.call('eth_getLogs', [{
218+
'fromBlock': log0Block.blockNumber,
219+
'toBlock': log4Block.blockNumber,
220+
'topics': [logs[0].topics[0]]
221+
}]);
222+
expect(logsWithTopic.length).to.be.greaterThan(0);
223+
224+
for(let i in logsWithTopic) {
225+
expect(logsWithTopic[i].topics.length).to.be.greaterThan(0);
226+
expect(logsWithTopic[i].topics[0]).to.be.equal(topic);
227+
}
228+
});
229+
});
230+
99231
describe('Block related RPC calls', () => {
100232

101233
let mirrorBlock;
@@ -820,7 +952,7 @@ describe('RPC Server Acceptance Tests', function () {
820952
describe('Gas Price related RPC endpoints', () => {
821953
let lastBlockBeforeUpdate;
822954
let lastBlockAfterUpdate;
823-
955+
824956
before(async () => {
825957
await servicesNode.updateFileContent(FEE_SCHEDULE_FILE_ID, FEE_SCHEDULE_FILE_CONTENT_DEFAULT);
826958
await servicesNode.updateFileContent(EXCHANGE_RATE_FILE_ID, EXCHANGE_RATE_FILE_CONTENT_DEFAULT);
@@ -857,7 +989,7 @@ describe('RPC Server Acceptance Tests', function () {
857989
await relay.call('eth_feeHistory', ['0x1', newestBlockNumberHex, null]);
858990
} catch (error) {
859991
Assertions.jsonRpcError(error, predefined.REQUEST_BEYOND_HEAD_BLOCK(newestBlockNumber, latestBlock.number));
860-
}
992+
}
861993
});
862994

863995
it('should call eth_feeHistory with zero block count', async function() {

0 commit comments

Comments
 (0)