-
Notifications
You must be signed in to change notification settings - Fork 68
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
fix: Inconsistent handling of failed EVM transactions #3158
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -48,13 +48,15 @@ import { | |
formatContractResult, | ||
formatTransactionIdWithoutQueryParams, | ||
getFunctionSelector, | ||
hexToASCII, | ||
isHex, | ||
isValidEthereumAddress, | ||
nanOrNumberTo0x, | ||
nullableNumberTo0x, | ||
numberTo0x, | ||
parseNumericEnvVar, | ||
prepend0x, | ||
strip0x, | ||
toHash32, | ||
trimPrecedingZeros, | ||
weibarHexToTinyBarInt, | ||
|
@@ -326,10 +328,9 @@ export class EthImpl implements Eth { | |
requestDetails: RequestDetails, | ||
): Promise<IFeeHistory | JsonRpcError> { | ||
const requestIdPrefix = requestDetails.formattedRequestId; | ||
const maxResults = | ||
ConfigService.get('TEST') | ||
? constants.DEFAULT_FEE_HISTORY_MAX_RESULTS | ||
: Number(ConfigService.get('FEE_HISTORY_MAX_RESULTS')); | ||
const maxResults = ConfigService.get('TEST') | ||
? constants.DEFAULT_FEE_HISTORY_MAX_RESULTS | ||
: Number(ConfigService.get('FEE_HISTORY_MAX_RESULTS')); | ||
|
||
this.logger.trace( | ||
`${requestIdPrefix} feeHistory(blockCount=${blockCount}, newestBlock=${newestBlock}, rewardPercentiles=${rewardPercentiles})`, | ||
|
@@ -2297,9 +2298,20 @@ export class EthImpl implements Eth { | |
throw predefined.MAX_BLOCK_SIZE(blockResponse.count); | ||
} | ||
|
||
const isWrongNonce = (contractResult: { result: string; error_message: any }) => { | ||
return ( | ||
contractResult.result === constants.TRANSACTION_RESULT_STATUS.WRONG_NONCE || | ||
hexToASCII(strip0x(contractResult.error_message ?? '')) === constants.TRANSACTION_RESULT_STATUS.WRONG_NONCE | ||
); | ||
}; | ||
|
||
// prepare transactionArray | ||
let transactionArray: any[] = []; | ||
for (const contractResult of contractResults) { | ||
if (isWrongNonce(contractResult)) { | ||
// skip wrong nonce transactions as they are not valid transactions which should be included in the block | ||
continue; | ||
} | ||
contractResult.from = await this.resolveEvmAddress(contractResult.from, requestDetails, [constants.TYPE_ACCOUNT]); | ||
contractResult.to = await this.resolveEvmAddress(contractResult.to, requestDetails); | ||
contractResult.chain_id = contractResult.chain_id || this.chain; | ||
|
@@ -2308,7 +2320,7 @@ export class EthImpl implements Eth { | |
} | ||
|
||
transactionArray = this.populateSyntheticTransactions(showDetails, logs, transactionArray, requestDetails); | ||
transactionArray = showDetails ? _.uniqBy(transactionArray, 'hash') : _.uniq(transactionArray); | ||
transactionArray = showDetails ? transactionArray : _.uniq(transactionArray); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm not sure There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Well, we never want to show duplicated transaction hashes in the response when Filtering the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hmm, I agree with Luis here. The size should be the same regardless of |
||
|
||
const formattedReceipts: IReceiptRootHash[] = ReceiptsRootUtils.buildReceiptRootHashes( | ||
transactionArray.map((tx) => (showDetails ? tx.hash : tx)), | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -22,7 +22,7 @@ import { expect, use } from 'chai'; | |
import sinon from 'sinon'; | ||
import chaiAsPromised from 'chai-as-promised'; | ||
import { Logger } from 'pino'; | ||
import { predefined } from '../../../src/lib/errors/JsonRpcError'; | ||
import { predefined } from '../../../src'; | ||
import { EthImpl } from '../../../src/lib/eth'; | ||
import { | ||
blockLogsBloom, | ||
|
@@ -34,7 +34,7 @@ import { Block, Transaction } from '../../../src/lib/model'; | |
import { MirrorNodeClient, SDKClient } from '../../../src/lib/clients'; | ||
import RelayAssertions from '../../assertions'; | ||
import constants from '../../../src/lib/constants'; | ||
import { hashNumber, numberTo0x } from '../../../dist/formatters'; | ||
import { ASCIIToHex, hashNumber, numberTo0x, prepend0x } from '../../../dist/formatters'; | ||
import { | ||
BLOCK_HASH, | ||
BLOCK_HASH_PREV_TRIMMED, | ||
|
@@ -566,4 +566,66 @@ describe('@ethGetBlockByNumber using MirrorNode', async function () { | |
args, | ||
); | ||
}); | ||
|
||
it('eth_getBlockByNumber should skip transactions with wrong nonces when showDetails = false', async function () { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Aren't these two test cases basically the same module [false, true].forEach(showDetails => {
it(`eth_getBlockByNumber should skip transactions with wrong nonces when showDetails = ${showDetails}`, async function () {
});
}); There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fair point, that would simplify things a bit |
||
// mirror node request mocks | ||
restMock.onGet(`blocks/${BLOCK_NUMBER}`).reply(200, DEFAULT_BLOCK); | ||
restMock.onGet(BLOCKS_LIMIT_ORDER_URL).reply(200, MOST_RECENT_BLOCK); | ||
restMock.onGet(CONTRACT_RESULTS_WITH_FILTER_URL).reply(200, { | ||
results: [ | ||
...defaultContractResults.results, | ||
{ ...defaultContractResults.results[0], result: 'WRONG_NONCE' }, | ||
{ ...defaultContractResults.results[0], error_message: prepend0x(ASCIIToHex('WRONG_NONCE')) }, | ||
], | ||
}); | ||
restMock.onGet(CONTRACT_RESULTS_LOGS_WITH_FILTER_URL).reply(200, DEFAULT_ETH_GET_BLOCK_BY_LOGS); | ||
|
||
const showDetails = false; | ||
const result = await ethImpl.getBlockByNumber(numberTo0x(BLOCK_NUMBER), showDetails, 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], // should not include the transaction with wrong nonce | ||
receiptsRoot: DEFAULT_BLOCK_RECEIPTS_ROOT_HASH, | ||
}, | ||
showDetails, | ||
); | ||
}); | ||
|
||
it('eth_getBlockByNumber should skip transactions with wrong nonces when showDetails = true', async function () { | ||
// mirror node request mocks | ||
restMock.onGet(`blocks/${BLOCK_NUMBER}`).reply(200, DEFAULT_BLOCK); | ||
restMock.onGet(BLOCKS_LIMIT_ORDER_URL).reply(200, MOST_RECENT_BLOCK); | ||
restMock.onGet(CONTRACT_RESULTS_WITH_FILTER_URL).reply(200, { | ||
results: [ | ||
...defaultContractResults.results, | ||
{ ...defaultContractResults.results[1], result: 'WRONG_NONCE' }, | ||
{ ...defaultContractResults.results[1], error_message: prepend0x(ASCIIToHex('WRONG_NONCE')) }, | ||
], | ||
}); | ||
restMock.onGet(CONTRACT_RESULTS_LOGS_WITH_FILTER_URL).reply(200, DEFAULT_ETH_GET_BLOCK_BY_LOGS); | ||
|
||
const showDetails = true; | ||
const result = await ethImpl.getBlockByHash(numberTo0x(BLOCK_NUMBER), showDetails, 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], // should not include the transaction with wrong nonce | ||
receiptsRoot: DEFAULT_BLOCK_RECEIPTS_ROOT_HASH, | ||
}, | ||
showDetails, | ||
); | ||
}); | ||
}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: for a different PR this feels like something the ConfigService should handle internally.
Is that possible?