Skip to content

Commit

Permalink
fix: The relay relies on fallback gas estimations instead of properly…
Browse files Browse the repository at this point in the history
… sending requests to mirror node (#2860)

* refactor: Validation logic in the `server` package

Signed-off-by: Victor Yanev <[email protected]>

* fix: rpc_batch3.spec.ts

Signed-off-by: Victor Yanev <[email protected]>

* fix: rpc_batch3.spec.ts

Signed-off-by: Victor Yanev <[email protected]>

* chore: address comments

Signed-off-by: Victor Yanev <[email protected]>

* chore: extend tests in `validator.spec.ts` to cover `tracerConfig` type

Signed-off-by: Victor Yanev <[email protected]>

* chore: final touches + address comments

Signed-off-by: Victor Yanev <[email protected]>

* fix: build error

Signed-off-by: Victor Yanev <[email protected]>

* fix: allow "0x" value for BASE_HEX_REGEX

Signed-off-by: Victor Yanev <[email protected]>

* fix: allow ``"0x"` value for `hex` type

Signed-off-by: Victor Yanev <[email protected]>

* fix: allow ``"0x"` value for `hex` type

Signed-off-by: Victor Yanev <[email protected]>

* fix: Bug due to validations of `eth_call`

Signed-off-by: Victor Yanev <[email protected]>

* fix: tests after new validations for Transaction object

Signed-off-by: Victor Yanev <[email protected]>

* fix: The relay relies on fallback gas estimations instead of properly sending requests to mirror node

Signed-off-by: Victor Yanev <[email protected]>

* fix: The relay relies on fallback gas estimations instead of properly sending requests to mirror node

Signed-off-by: Victor Yanev <[email protected]>

* fix: The relay relies on fallback gas estimations instead of properly sending requests to mirror node

Signed-off-by: Victor Yanev <[email protected]>

* chore: add `await` to `ethImpl.contractCallFormat` calls in eth_estimateGas.spec.ts

Signed-off-by: Victor Yanev <[email protected]>

* chore: fix tests in eth_estimateGas.spec.ts

Signed-off-by: Victor Yanev <[email protected]>

* chore: fix tests in eth_estimateGas.spec.ts and eth_call.spec.ts

Signed-off-by: Victor Yanev <[email protected]>

* chore: nit consistency fix

Signed-off-by: Victor Yanev <[email protected]>

* chore: fetch account from mirror node when `OPERATOR_KEY_FORMAT !== 'HEX_ECDSA'`

Signed-off-by: Victor Yanev <[email protected]>

* fix: eth_call.spec.ts and eth_estimateGas.spec.ts

Signed-off-by: Victor Yanev <[email protected]>

* fix: build error

Signed-off-by: Victor Yanev <[email protected]>

---------

Signed-off-by: Victor Yanev <[email protected]>
Signed-off-by: Victor Yanev <[email protected]>
  • Loading branch information
victor-yanev authored Aug 30, 2024
1 parent b03ed7a commit 554dab5
Show file tree
Hide file tree
Showing 5 changed files with 158 additions and 102 deletions.
1 change: 1 addition & 0 deletions packages/relay/src/lib/clients/mirrorNodeClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ import { MirrorNodeClientError } from '../errors/MirrorNodeClientError';
import { formatRequestIdMessage, formatTransactionId } from '../../formatters';
import Axios, { AxiosInstance, AxiosRequestConfig, AxiosResponse } from 'axios';
import {
IAccountInfo,
IContractCallRequest,
IContractCallResponse,
IContractLogsResultsParams,
Expand Down
24 changes: 18 additions & 6 deletions packages/relay/src/lib/eth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ import { DebugService } from './services/debugService';
import { IFeeHistory } from './types/IFeeHistory';
import { ITransactionReceipt } from './types/ITransactionReceipt';
import TransactionService from './services/transactionService/transactionService';
import { IContractCallRequest, IContractCallResponse } from './types/IMirrorNode';
import { IAccountInfo, IContractCallRequest, IContractCallResponse } from './types/IMirrorNode';
import { IReceiptRootHash, ReceiptsRootUtils } from '../receiptsRootUtils';

const _ = require('lodash');
Expand Down Expand Up @@ -617,7 +617,7 @@ export class EthImpl implements Eth {
transaction: IContractCallRequest,
requestIdPrefix?: string,
): Promise<IContractCallResponse | null> {
this.contractCallFormat(transaction);
await this.contractCallFormat(transaction, requestIdPrefix);
const callData = { ...transaction, estimate: true };
return this.mirrorNodeClient.postContractCall(callData, requestIdPrefix);
}
Expand Down Expand Up @@ -689,9 +689,9 @@ export class EthImpl implements Eth {
*
* @param {string} address the address of the account
* @param {string} requestIdPrefix the prefix for the request ID
* @returns the account (if such exists for the given address)
* @returns {Promise<IAccountInfo | null>} the account (if such exists for the given address)
*/
private async getAccount(address: string, requestIdPrefix?: string) {
private async getAccount(address: string, requestIdPrefix?: string): Promise<IAccountInfo | null> {
const key = `${constants.CACHE_KEY.ACCOUNT}_${address}`;
let account = await this.cacheService.getAsync(key, EthImpl.ethEstimateGas, requestIdPrefix);
if (!account) {
Expand All @@ -704,17 +704,29 @@ export class EthImpl implements Eth {
/**
* Perform value format precheck before making contract call towards the mirror node
* @param transaction
* @param requestIdPrefix
*/
contractCallFormat(transaction: IContractCallRequest): void {
async contractCallFormat(transaction: IContractCallRequest, requestIdPrefix?: string): Promise<void> {
if (transaction.value) {
transaction.value = weibarHexToTinyBarInt(transaction.value);
}
if (transaction.gasPrice) {
transaction.gasPrice = parseInt(transaction.gasPrice.toString());
} else {
transaction.gasPrice = await this.gasPrice(requestIdPrefix).then((gasPrice) => parseInt(gasPrice));
}
if (transaction.gas) {
transaction.gas = parseInt(transaction.gas.toString());
}
if (!transaction.from && transaction.value && transaction.value > 0) {
if (process.env.OPERATOR_KEY_FORMAT === 'HEX_ECDSA') {
transaction.from = this.hapiService.getMainClientInstance().operatorPublicKey?.toEvmAddress();
} else {
const operatorId = this.hapiService.getMainClientInstance().operatorAccountId!.toString();
const operatorAccount = await this.getAccount(operatorId, requestIdPrefix);
transaction.from = operatorAccount?.evm_address;
}
}

// Support either data or input. https://ethereum.github.io/execution-apis/api-documentation/ lists input but many EVM tools still use data.
// We chose in the mirror node to use data field as the correct one, however for us to be able to support all tools,
Expand Down Expand Up @@ -1649,7 +1661,7 @@ export class EthImpl implements Eth {
// Get a reasonable value for "gas" if it is not specified.
const gas = this.getCappedBlockGasLimit(call.gas?.toString(), requestIdPrefix);

this.contractCallFormat(call);
await this.contractCallFormat(call, requestIdPrefix);

let result: string | JsonRpcError = '';
try {
Expand Down
24 changes: 23 additions & 1 deletion packages/relay/src/lib/types/IMirrorNode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,28 @@
*
*/

export interface IAccountInfo {
/**
* Account ID string in the form `shard.realm.num`
*/
account: string;
/**
* RFC4648 no-padding base32 encoded string of the account's alias.
*/
alias: string;
balance?: IAccountBalance;
deleted?: boolean;
ethereum_nonce?: number;
evm_address?: string;
memo?: string;
}

export interface IAccountBalance {
balance: number;
timestamp?: string;
tokens?: { token_id: string; balance: number }[];
}

export interface ILimitOrderParams {
limit?: number;
order?: string;
Expand Down Expand Up @@ -59,7 +81,7 @@ export interface IContractCallResponse {
errorMessage?: string;
statusCode?: number;
_status?: {
messages: Array<{ message: string; detail: string; data: string }>;
messages: Array<{ message: string; detail?: string; data?: string }>;
};
}

Expand Down
Loading

0 comments on commit 554dab5

Please sign in to comment.