Skip to content

Commit

Permalink
fix: throw error if log.block_number or log.index is null or log.bloc…
Browse files Browse the repository at this point in the history
…k_hash is empty

Signed-off-by: Logan Nguyen <[email protected]>
  • Loading branch information
quiet-node committed Jan 8, 2025
1 parent 8687322 commit 051f326
Show file tree
Hide file tree
Showing 3 changed files with 63 additions and 36 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -346,13 +346,28 @@ export class CommonService implements ICommonService {

const logs: Log[] = [];
for (const log of logResults) {
if (log.block_number == null || log.index == null || log.block_hash === EthImpl.emptyHex) {
if (this.logger.isLevelEnabled('debug')) {
this.logger.debug(

Check warning on line 351 in packages/relay/src/lib/services/ethService/ethCommonService/index.ts

View check run for this annotation

Codecov / codecov/patch

packages/relay/src/lib/services/ethService/ethCommonService/index.ts#L351

Added line #L351 was not covered by tests
`${
requestDetails.formattedRequestId
} Log entry is missing required fields: block_number, index, or block_hash is an empty hex (0x). log=${JSON.stringify(
log,
)}`,
);
}
throw predefined.INTERNAL_ERROR(
`The log entry from the remote Mirror Node server is missing required fields. `,
);
}

logs.push(
new Log({
address: log.address,
blockHash: toHash32(log.block_hash),
blockNumber: nullableNumberTo0x(log.block_number),
blockNumber: numberTo0x(log.block_number),
data: log.data,
logIndex: nullableNumberTo0x(log.index),
logIndex: numberTo0x(log.index),
removed: false,
topics: log.topics,
transactionHash: toHash32(log.transaction_hash),
Expand Down
38 changes: 22 additions & 16 deletions packages/relay/tests/lib/eth/eth_getBlockByHash.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -367,28 +367,34 @@ describe('@ethGetBlockByHash using MirrorNode', async function () {
});
});

it('eth_getBlockByHash should gracefully handle nulbale entities found in logs', async function () {
it('eth_getBlockByHash should throw an error if nulbale entities found in logs', async function () {
// mirror node request mocks
restMock.onGet(`blocks/${BLOCK_HASH}`).reply(200, DEFAULT_BLOCK);
restMock.onGet(CONTRACT_RESULTS_WITH_FILTER_URL).reply(200, defaultContractResults);
restMock.onGet('network/fees').reply(200, DEFAULT_NETWORK_FEES);

const nullEntitiedLogs = {
logs: [{ ...DEFAULT_LOGS.logs[0], block_number: null, transaction_index: null, logIndex: null }],
};

restMock.onGet(CONTRACT_RESULTS_LOGS_WITH_FILTER_URL).reply(200, nullEntitiedLogs);
const nullEntitiedLogs = [
{
logs: [{ ...DEFAULT_LOGS.logs[0], block_number: null }],
},
{
logs: [{ ...DEFAULT_LOGS.logs[0], index: null }],
},
{
logs: [{ ...DEFAULT_LOGS.logs[0], block_hash: '0x' }],
},
];

const result = await ethImpl.getBlockByHash(BLOCK_HASH, false, requestDetails);
for (const logEntry of nullEntitiedLogs) {
try {
restMock.onGet(CONTRACT_RESULTS_LOGS_WITH_FILTER_URL).reply(200, logEntry);

RelayAssertions.assertBlock(result, {
hash: BLOCK_HASH_TRIMMED,
gasUsed: TOTAL_GAS_USED,
number: BLOCK_NUMBER_HEX,
parentHash: BLOCK_HASH_PREV_TRIMMED,
timestamp: BLOCK_TIMESTAMP_HEX,
transactions: [CONTRACT_HASH_1, CONTRACT_HASH_2],
receiptsRoot: DEFAULT_BLOCK_RECEIPTS_ROOT_HASH,
});
await ethImpl.getBlockByHash(BLOCK_HASH, false, requestDetails);
expect.fail('should have thrown an error');
} catch (error) {
expect(error).to.exist;
expect(error.message).to.include('The log entry from the remote Mirror Node server is missing required fields');
}
}
});
});
42 changes: 24 additions & 18 deletions packages/relay/tests/lib/eth/eth_getBlockByNumber.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -612,28 +612,34 @@ describe('@ethGetBlockByNumber using MirrorNode', async function () {
});
});

it('eth_getBlockByNumber should gracefully handle nulbale entities found in logs', async function () {
it('eth_getBlockByNumber should throw an error if nulbale entities found in logs', async function () {
// mirror node request mocks
restMock.onGet(`blocks/${BLOCK_HASH}`).reply(200, DEFAULT_BLOCK);
restMock.onGet(CONTRACT_RESULTS_WITH_FILTER_URL).reply(200, defaultContractResults);
restMock.onGet('network/fees').reply(200, DEFAULT_NETWORK_FEES);

const nullEntitiedLogs = {
logs: [{ ...DEFAULT_LOGS.logs[0], block_number: null, transaction_index: null, logIndex: null }],
};

restMock.onGet(CONTRACT_RESULTS_LOGS_WITH_FILTER_URL).reply(200, nullEntitiedLogs);

const result = await ethImpl.getBlockByNumber(BLOCK_HASH, false, requestDetails);

RelayAssertions.assertBlock(result, {
hash: BLOCK_HASH_TRIMMED,
gasUsed: TOTAL_GAS_USED,
number: BLOCK_NUMBER_HEX,
parentHash: BLOCK_HASH_PREV_TRIMMED,
timestamp: BLOCK_TIMESTAMP_HEX,
transactions: [CONTRACT_HASH_1, CONTRACT_HASH_2],
receiptsRoot: DEFAULT_BLOCK_RECEIPTS_ROOT_HASH,
});
const nullEntitiedLogs = [
{
logs: [{ ...DEFAULT_LOGS.logs[0], block_number: null }],
},
{
logs: [{ ...DEFAULT_LOGS.logs[0], index: null }],
},
{
logs: [{ ...DEFAULT_LOGS.logs[0], block_hash: '0x' }],
},
];

for (const logEntry of nullEntitiedLogs) {
try {
restMock.onGet(CONTRACT_RESULTS_LOGS_WITH_FILTER_URL).reply(200, logEntry);

await ethImpl.getBlockByNumber(BLOCK_HASH, false, requestDetails);
expect.fail('should have thrown an error');
} catch (error) {
expect(error).to.exist;
expect(error.message).to.include('The log entry from the remote Mirror Node server is missing required fields');
}
}
});
});

0 comments on commit 051f326

Please sign in to comment.