Skip to content

Commit

Permalink
feat: deprecate ETH_POPULATE_SYNTHETIC_CONTRACT_RESULTS env (#2768)
Browse files Browse the repository at this point in the history
* chore: remove env

Signed-off-by: nikolay <[email protected]>

* chore: modify test

Signed-off-by: nikolay <[email protected]>

---------

Signed-off-by: nikolay <[email protected]>
  • Loading branch information
natanasow authored Jul 30, 2024
1 parent 59ede4c commit e0fc473
Show file tree
Hide file tree
Showing 6 changed files with 25 additions and 676 deletions.
1 change: 0 additions & 1 deletion docs/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,6 @@ Unless you need to set a non-default value, it is recommended to only populate o
| `ETH_GET_TRANSACTION_COUNT_MAX_BLOCK_RANGE` | "1000" | The maximum number of transactions to return when running eth_getBlockByHash or eth_getBlockByNumber with transaction objects set to true call. |
| `FEE_HISTORY_MAX_RESULTS` | "10" | The maximum number of results to returns as part of `eth_feeHistory`. |
| `ETH_FEE_HISTORY_FIXED` | "true" | Flag to set if eth_feeHistory should return a fixed fee for the set of results. |
| `ETH_POPULATE_SYNTHETIC_CONTRACT_RESULTS` | "true" | Flag to set if the relay should populate the contract results for synthetic contracts. |
| `GAS_PRICE_PERCENTAGE_BUFFER` | "0" | The additional buffer that adds a percentage on top of the calculated network gasPrice. This may be used by operators to reduce the chances of `INSUFFICIENT_TX_FEE` errors experienced by users caused by minor fluctuations in the exchange rate. |
| `GAS_PRICE_TINY_BAR_BUFFER` | "10000000000" | The additional buffer range to allow during a relay precheck of gas price. This supports slight fluctuations in network gasprice calculations. |
| `HAPI_CLIENT_DURATION_RESET` | "3600000" | Time until client reinitialization. (ms) |
Expand Down
96 changes: 13 additions & 83 deletions packages/relay/src/lib/eth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -171,13 +171,6 @@ export class EthImpl implements Eth {
private readonly estimateGasThrows = process.env.ESTIMATE_GAS_THROWS
? process.env.ESTIMATE_GAS_THROWS === 'true'
: true;
private readonly syntheticLogCacheTtl = parseNumericEnvVar(
'SYNTHETIC_LOG_CACHE_TTL',
'DEFAULT_SYNTHETIC_LOG_CACHE_TTL',
);
private readonly shouldPopulateSyntheticContractResults = process.env.ETH_POPULATE_SYNTHETIC_CONTRACT_RESULTS
? process.env.ETH_POPULATE_SYNTHETIC_CONTRACT_RESULTS === 'true'
: true;

private readonly ethGasPRiceCacheTtlMs = parseNumericEnvVar(
'ETH_GET_GAS_PRICE_CACHE_TTL_MS',
Expand Down Expand Up @@ -1957,24 +1950,24 @@ export class EthImpl implements Eth {
async getTransactionByHash(hash: string, requestIdPrefix?: string): Promise<Transaction | null> {
this.logger.trace(`${requestIdPrefix} getTransactionByHash(hash=${hash})`, hash);

if (this.shouldPopulateSyntheticContractResults) {
// check if tx is synthetic and exists in cache
const cacheKeySyntheticLog = `${constants.CACHE_KEY.SYNTHETIC_LOG_TRANSACTION_HASH}${hash}`;
const cachedLog = await this.cacheService.getSharedWithFallback(
cacheKeySyntheticLog,
EthImpl.ethGetTransactionReceipt,
const contractResult = await this.mirrorNodeClient.getContractResultWithRetry(hash, requestIdPrefix);
if (contractResult === null || contractResult.hash === undefined) {
// handle synthetic transactions
const syntheticLogs = await this.common.getLogsWithParams(
null,
{
'transaction.hash': hash,
},
requestIdPrefix,
);

if (cachedLog) {
const tx: Transaction1559 = this.createTransactionFromLog(cachedLog);
return tx;
// no tx found
if (!syntheticLogs.length) {
this.logger.trace(`${requestIdPrefix} no tx for ${hash}`);
return null;
}
}

const contractResult = await this.mirrorNodeClient.getContractResultWithRetry(hash, requestIdPrefix);
if (contractResult === null || contractResult.hash === undefined) {
return null;
return this.createTransactionFromLog(syntheticLogs[0]);
}

if (!contractResult.block_number || (!contractResult.transaction_index && contractResult.transaction_index !== 0)) {
Expand Down Expand Up @@ -2251,10 +2244,6 @@ export class EthImpl implements Eth {
}

const blockHash = toHash32(blockResponse.hash);
// Gating feature in case of unexpected behavior with other apps.
if (this.shouldPopulateSyntheticContractResults) {
this.filterAndPopulateSyntheticContractResults(showDetails, logs, transactionArray, requestIdPrefix);
}
return new Block({
baseFeePerGas: await this.gasPrice(requestIdPrefix),
difficulty: EthImpl.zeroHex,
Expand All @@ -2280,65 +2269,6 @@ export class EthImpl implements Eth {
});
}

/**
* Filter contract logs to remove the duplicate ones with the contract results to get only the synthetic ones.
* If showDetails is set to false filter the contract logs and add missing transaction hashes
* If showDetails is set to true filter the contract logs and add construct missing transaction objects
* @param showDetails
* @param logs
* @param transactionArray
* @param requestIdPrefix
*/
filterAndPopulateSyntheticContractResults(
showDetails: boolean,
logs: Log[],
transactionArray: Array<any>,
requestIdPrefix?: string,
): void {
let filteredLogs: Log[];
const keyValuePairs: Record<string, any> = {}; // Object to accumulate cache entries

if (showDetails) {
filteredLogs = logs.filter(
(log) => !transactionArray.some((transaction) => transaction.hash === log.transactionHash),
);
filteredLogs.forEach((log) => {
const transaction: Transaction1559 = this.createTransactionFromLog(log);
transactionArray.push(transaction);

const cacheKey = `${constants.CACHE_KEY.SYNTHETIC_LOG_TRANSACTION_HASH}${log.transactionHash}`;
keyValuePairs[cacheKey] = log;
});
} else {
filteredLogs = logs.filter((log) => !transactionArray.includes(log.transactionHash));
filteredLogs.forEach((log) => {
transactionArray.push(log.transactionHash);

const cacheKey = `${constants.CACHE_KEY.SYNTHETIC_LOG_TRANSACTION_HASH}${log.transactionHash}`;
keyValuePairs[cacheKey] = log;
});

this.logger.trace(
`${requestIdPrefix} ${filteredLogs.length} Synthetic transaction hashes will be added in the block response`,
);
}
// cache the whole array using mSet
if (Object.keys(keyValuePairs).length > 0) {
this.cacheService.multiSet(
keyValuePairs,
EthImpl.ethGetBlockByHash,
this.syntheticLogCacheTtl,
requestIdPrefix,
true,
);
}
}

/**
* Creates a new instance of transaction object using the information in the log, all unavailable information will be null
* @param log
* @returns Transaction Object
*/
private createTransactionFromLog(log: Log): Transaction1559 {
return new Transaction1559({
accessList: undefined, // we don't support access lists for now
Expand Down
33 changes: 0 additions & 33 deletions packages/relay/tests/lib/eth/eth_getTransactionByHash.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -283,37 +283,4 @@ describe('@ethGetTransactionByHash eth_getTransactionByHash tests', async functi
maxPriorityFeePerGas: '0x43',
});
});

it('returns synthetic transaction when it matches cache', async function () {
// prepare cache with synthetic log
const cacheKeySyntheticLog = `${constants.CACHE_KEY.SYNTHETIC_LOG_TRANSACTION_HASH}${defaultDetailedContractResultByHash.hash}`;
const cachedLog = new Log({
address: defaultLogs1[0].address,
blockHash: toHash32(defaultLogs1[0].block_hash),
blockNumber: numberTo0x(defaultLogs1[0].block_number),
data: defaultLogs1[0].data,
logIndex: numberTo0x(defaultLogs1[0].index),
removed: false,
topics: defaultLogs1[0].topics,
transactionHash: toHash32(defaultLogs1[0].transaction_hash),
transactionIndex: nullableNumberTo0x(defaultLogs1[0].transaction_index),
});

cacheService.set(cacheKeySyntheticLog, cachedLog, EthImpl.ethGetTransactionReceipt);

const transaction = await ethImpl.getTransactionByHash(DEFAULT_TX_HASH);

if (transaction) {
// Assert the respnse tx
expect(transaction.blockHash).to.eq(cachedLog.blockHash);
expect(transaction.blockNumber).to.eq(cachedLog.blockNumber);
expect(transaction.from).to.eq(cachedLog.address);
expect(transaction.gas).to.eq(EthImpl.defaultTxGas);
expect(transaction.gasPrice).to.eq(EthImpl.invalidEVMInstruction);
expect(transaction.value).to.eq(EthImpl.oneTwoThreeFourHex);
expect(transaction.to).to.eq(cachedLog.address);
expect(transaction.hash).to.eq(cachedLog.transactionHash);
expect(transaction.transactionIndex).to.eq(cachedLog.transactionIndex);
}
});
});
Loading

0 comments on commit e0fc473

Please sign in to comment.