Skip to content

Commit

Permalink
chore: cherry picked PR#2751 (#2752)
Browse files Browse the repository at this point in the history
feat: added preemtiveCheck for HBAR ratelimit (#2751)

Signed-off-by: Logan Nguyen <logan.nguyen@swirldslabs.com>
  • Loading branch information
quiet-node authored Jul 24, 2024
1 parent b95bf52 commit 7f2fc68
Show file tree
Hide file tree
Showing 4 changed files with 51 additions and 1 deletion.
24 changes: 23 additions & 1 deletion packages/relay/src/lib/clients/sdkClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -249,11 +249,34 @@ export class SDKClient {
const ethereumTransaction = new EthereumTransaction();
const interactingEntity = ethereumTransactionData.toJSON()['to'].toString();
let fileId: FileId | null = null;
const requestIdPrefix = formatRequestIdMessage(requestId);

// if callData's size is greater than `fileAppendChunkSize` => employ HFS to create new file to carry the rest of the contents of callData
if (ethereumTransactionData.callData.length <= this.fileAppendChunkSize) {
ethereumTransaction.setEthereumData(ethereumTransactionData.toBytes());
} else {
// notice: this solution is temporary and subject to change.
const isPreemtiveCheckOn = process.env.HBAR_RATE_LIMIT_PREEMTIVE_CHECK
? process.env.HBAR_RATE_LIMIT_PREEMTIVE_CHECK === 'true'
: false;

if (isPreemtiveCheckOn) {
const numFileCreateTxs = 1;
const numFileAppendTxs = Math.ceil(ethereumTransactionData.callData.length / this.fileAppendChunkSize);
const fileCreateFee = Number(process.env.HOT_FIX_FILE_CREATE_FEE || 100000000); // 1 hbar
const fileAppendFee = Number(process.env.HOT_FIX_FILE_APPEND_FEE || 120000000); // 1.2 hbar

const totalPreemtiveTransactionFee = numFileCreateTxs * fileCreateFee + numFileAppendTxs * fileAppendFee;

const shouldPreemtivelyLimit = this.hbarLimiter.shouldPreemtivelyLimit(totalPreemtiveTransactionFee);
if (shouldPreemtivelyLimit) {
this.logger.trace(
`${requestIdPrefix} The total preemptive transaction fee exceeds the current remaining HBAR budget due to an excessively large callData size.: numFileCreateTxs=${numFileCreateTxs}, numFileAppendTxs=${numFileAppendTxs}, totalPreemtiveTransactionFee=${totalPreemtiveTransactionFee}, callDataSize=${ethereumTransactionData.callData.length}`,
);
throw predefined.HBAR_RATE_LIMIT_PREEMTIVE_EXCEEDED;
}
}

fileId = await this.createFile(
ethereumTransactionData.callData,
this.clientMain,
Expand All @@ -262,7 +285,6 @@ export class SDKClient {
interactingEntity,
);
if (!fileId) {
const requestIdPrefix = formatRequestIdMessage(requestId);
throw new SDKClientError({}, `${requestIdPrefix} No fileId created for transaction. `);
}
ethereumTransactionData.callData = new Uint8Array();
Expand Down
4 changes: 4 additions & 0 deletions packages/relay/src/lib/errors/JsonRpcError.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,10 @@ export const predefined = {
code: -32606,
message: 'HBAR Rate limit exceeded',
}),
HBAR_RATE_LIMIT_PREEMTIVE_EXCEEDED: new JsonRpcError({
code: -32606,
message: 'The HBAR rate limit was preemptively exceeded due to an excessively large callData size.',
}),
INSUFFICIENT_ACCOUNT_BALANCE: new JsonRpcError({
code: -32000,
message: 'Insufficient funds for transfer',
Expand Down
12 changes: 12 additions & 0 deletions packages/relay/src/lib/hbarlimiter/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ export default class HbarLimit {
this.duration = duration;
}
this.remainingBudget = this.total;
this.logger.trace(`this.remainingBudget: ${this.remainingBudget}`);

this.reset = currentDateNow + this.duration;

const metricCounterName = 'rpc_relay_hbar_rate_limit';
Expand Down Expand Up @@ -88,6 +90,16 @@ export default class HbarLimit {
return false;
}

/**
* Determines whether a transaction fee should be preemptively limited based on the remaining budget.
* @param {number} transactionFee - The transaction fee to be evaluated.
* @returns {boolean} A boolean indicating whether the transaction fee should be preemptively limited.
*/

shouldPreemtivelyLimit(transactionFee: number): boolean {
return this.remainingBudget - transactionFee <= 0;
}

/**
* Add expense to the remaining budget.
*/
Expand Down
12 changes: 12 additions & 0 deletions packages/relay/tests/lib/hbarLimiter.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -168,4 +168,16 @@ describe('HBAR Rate Limiter', async function () {
expect(limiterResetTime).to.equal(futureDate + validDuration);
expect(limiterRemainingBudget).to.equal(validTotal - 100);
});

it('Should preemtively limit while expected transactionFee is greater than remaining balance', () => {
const validTotalTxFee = validTotal - 100;
const invalidTotalTxFee = validTotal + 100;
rateLimiter = new HbarLimit(logger, currentDateNow, validTotal, validDuration, registry);

const shouldNotPreemtivelyLimit = rateLimiter.shouldPreemtivelyLimit(validTotalTxFee);
const shouldPreemtivelyLimit = rateLimiter.shouldPreemtivelyLimit(invalidTotalTxFee);

expect(shouldPreemtivelyLimit).to.be.true;
expect(shouldNotPreemtivelyLimit).to.be.false;
});
});

0 comments on commit 7f2fc68

Please sign in to comment.