Skip to content

Commit

Permalink
Revert "chore: remove unnecessary timeouts in tests"
Browse files Browse the repository at this point in the history
This reverts commit f688a4e.
  • Loading branch information
konstantinabl committed Oct 14, 2024
1 parent f688a4e commit 6cb081b
Show file tree
Hide file tree
Showing 5 changed files with 73 additions and 117 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@
"acceptancetest:api_batch3": "nyc ts-mocha packages/server/tests/acceptance/index.spec.ts -g '@api-batch-3' --exit",
"acceptancetest:erc20": "nyc ts-mocha packages/server/tests/acceptance/index.spec.ts -g '@erc20' --exit",
"acceptancetest:ratelimiter": "nyc ts-mocha packages/ws-server/tests/acceptance/index.spec.ts -g '@web-socket-ratelimiter' --exit && ts-mocha packages/server/tests/acceptance/index.spec.ts -g '@ratelimiter' --exit",
"acceptancetest:hbarlimiter": "HBAR_RATE_LIMIT_TINYBAR=1500000000 nyc ts-mocha packages/server/tests/acceptance/index.spec.ts -g '@hbarlimiter' --exit",
"acceptancetest:hbarlimiter": "HBAR_RATE_LIMIT_TINYBAR=3000000000 nyc ts-mocha packages/server/tests/acceptance/index.spec.ts -g '@hbarlimiter' --exit",
"acceptancetest:tokencreate": "nyc ts-mocha packages/server/tests/acceptance/index.spec.ts -g '@tokencreate' --exit",
"acceptancetest:tokenmanagement": "nyc ts-mocha packages/server/tests/acceptance/index.spec.ts -g '@tokenmanagement' --exit",
"acceptancetest:htsprecompilev1": "nyc ts-mocha packages/server/tests/acceptance/index.spec.ts -g '@htsprecompilev1' --exit",
Expand Down
178 changes: 71 additions & 107 deletions packages/server/tests/acceptance/hbarLimiter.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,21 +19,12 @@
*/

import fs from 'fs';
import chai, { expect } from 'chai';
import chaiAsPromised from 'chai-as-promised';
import { expect } from 'chai';
import { resolve } from 'path';
import { Logger } from 'pino';
import dotenv, { config } from 'dotenv';
import { BaseContract, ethers } from 'ethers';
import { Registry } from 'prom-client';
import { predefined } from '@hashgraph/json-rpc-relay';
import { SubscriptionTier } from '@hashgraph/json-rpc-relay/dist/lib/db/types/hbarLimiter/subscriptionTier';
import { ITransfer, RequestDetails } from '@hashgraph/json-rpc-relay/dist/lib/types';
import { CacheService } from '@hashgraph/json-rpc-relay/dist/lib/services/cacheService/cacheService';
import { HbarSpendingPlanRepository } from '@hashgraph/json-rpc-relay/dist/lib/db/repositories/hbarLimiter/hbarSpendingPlanRepository';
import { EthAddressHbarSpendingPlanRepository } from '@hashgraph/json-rpc-relay/dist/lib/db/repositories/hbarLimiter/ethAddressHbarSpendingPlanRepository';
import { IPAddressHbarSpendingPlanRepository } from '@hashgraph/json-rpc-relay/dist/lib/db/repositories/hbarLimiter/ipAddressHbarSpendingPlanRepository';
import constants from '@hashgraph/json-rpc-relay/dist/lib/constants';

// Local resources
import { Utils } from '../helpers/utils';
Expand All @@ -47,17 +38,23 @@ import { estimateFileTransactionsFee, overrideEnvsInMochaDescribe } from '@hashg

// Contracts used in tests
import parentContractJson from '../contracts/Parent.json';
import { SubscriptionTier } from '@hashgraph/json-rpc-relay/dist/lib/db/types/hbarLimiter/subscriptionTier';
import EstimateGasContract from '../contracts/EstimateGasContract.json';
import largeContractJson from '../contracts/hbarLimiterContracts/largeSizeContract.json';
import mediumSizeContract from '../contracts/hbarLimiterContracts/mediumSizeContract.json';

chai.use(chaiAsPromised);
import { ITransfer, RequestDetails } from '@hashgraph/json-rpc-relay/dist/lib/types';
import { Registry } from 'prom-client';
import { CacheService } from '@hashgraph/json-rpc-relay/dist/lib/services/cacheService/cacheService';
import { HbarSpendingPlanRepository } from '@hashgraph/json-rpc-relay/dist/lib/db/repositories/hbarLimiter/hbarSpendingPlanRepository';
import { EthAddressHbarSpendingPlanRepository } from '@hashgraph/json-rpc-relay/dist/lib/db/repositories/hbarLimiter/ethAddressHbarSpendingPlanRepository';
import { IPAddressHbarSpendingPlanRepository } from '@hashgraph/json-rpc-relay/dist/lib/db/repositories/hbarLimiter/ipAddressHbarSpendingPlanRepository';
import { HbarLimitService } from '@hashgraph/json-rpc-relay/dist/lib/services/hbarLimitService';

config({ path: resolve(__dirname, '../localAcceptance.env') });
const DOT_ENV = dotenv.parse(fs.readFileSync(resolve(__dirname, '../localAcceptance.env')));
let hbarSpendingPlanRepository: HbarSpendingPlanRepository;
let ethAddressSpendingPlanRepository: EthAddressHbarSpendingPlanRepository;
let ipSpendingPlanRepository: IPAddressHbarSpendingPlanRepository;
let hbarSpendingPlanRepository: HbarSpendingPlanRepository,
ethAddressSpendingPlanRepository: EthAddressHbarSpendingPlanRepository,
ipSpendingPlanRepository: IPAddressHbarSpendingPlanRepository;

describe('@hbarlimiter HBAR Limiter Acceptance Tests', function () {
// @ts-ignore
Expand Down Expand Up @@ -174,22 +171,7 @@ describe('@hbarlimiter HBAR Limiter Acceptance Tests', function () {
return sumAccountTransfers(ethereumTransaction.transfers, operatorAccount);
};

const getResetTimestamp = (): Date => {
const todayAtMidnight = new Date().setHours(0, 0, 0, 0);
let resetDate = new Date(todayAtMidnight);
while (resetDate.getTime() < Date.now()) {
// 1. Calculate the difference between the current time and the reset time.
// 2. Determine how many intervals of size `limitDuration` have passed since the last reset.
// 3. Calculate the new reset date by adding the required intervals to the original reset date.
const intervalsPassed = Math.ceil((Date.now() - resetDate.getTime()) / constants.HBAR_RATE_LIMIT_DURATION);
resetDate = new Date(resetDate.getTime() + intervalsPassed * constants.HBAR_RATE_LIMIT_DURATION);
}
return resetDate;
};

describe('HBAR Rate Limit Tests', function () {
overrideEnvsInMochaDescribe({ GET_RECORD_DEFAULT_TO_CONSENSUS_NODE: 'true' });

this.timeout(480 * 1000); // 480 seconds

const accounts: AliasAccount[] = [];
Expand Down Expand Up @@ -230,23 +212,12 @@ describe('@hbarlimiter HBAR Limiter Acceptance Tests', function () {
global.accounts.push(...accounts);
});

beforeEach(async () => {
// Unlinking the ip address, since localhost used for all accounts when running tests in CI
const basicPlans = await hbarSpendingPlanRepository.findAllActiveBySubscriptionTier(
[SubscriptionTier.BASIC],
requestDetails,
);
for (const plan of basicPlans) {
await ipSpendingPlanRepository.deleteAllByPlanId(plan.id, 'deleteAllByPlanId', requestDetails);
}
beforeEach(async function () {
await new Promise((r) => setTimeout(r, 3000));
});

describe('Total HBAR Limit', () => {
before(async () => {
logger.info(`${requestDetails.formattedRequestId} Waiting until the next reset of the HBAR rate limiter`);
const nextReset = getResetTimestamp();
await new Promise((r) => setTimeout(r, nextReset.getTime() - Date.now()));
});
describe('Remaining HBAR Limit', () => {
overrideEnvsInMochaDescribe({ GET_RECORD_DEFAULT_TO_CONSENSUS_NODE: 'true' });

it('should execute "eth_sendRawTransaction" for BASIC user without triggering HBAR rate limit exceeded', async function () {
const parentContract = await deployContract(parentContractJson, accounts[0].wallet);
Expand Down Expand Up @@ -338,24 +309,7 @@ describe('@hbarlimiter HBAR Limiter Acceptance Tests', function () {
});
});

describe('Tiered HBAR Rate Limit', () => {
before(async () => {
// Clear the cache from all BASIC plans
const basicPlans = await hbarSpendingPlanRepository.findAllActiveBySubscriptionTier(
[SubscriptionTier.BASIC],
requestDetails,
);
for (const plan of basicPlans) {
await hbarSpendingPlanRepository.delete(plan.id, requestDetails);
await ethAddressSpendingPlanRepository.deleteAllByPlanId(plan.id, 'before', requestDetails);
await ipSpendingPlanRepository.deleteAllByPlanId(plan.id, 'before', requestDetails);
}
// Wait until the next reset of the HBAR rate limiter
logger.info(`${requestDetails.formattedRequestId} Waiting until the next reset of the HBAR rate limiter`);
const nextReset = getResetTimestamp();
await new Promise((r) => setTimeout(r, nextReset.getTime() - Date.now()));
});

describe('Rate Limit', () => {
it('HBAR limiter is updated within acceptable tolerance range in relation to actual spent amount by the relay operator', async function () {
const TOLERANCE = 0.02;
const remainingHbarsBefore = Number(await metrics.get(testConstants.METRICS.REMAINING_HBAR_LIMIT));
Expand All @@ -379,29 +333,30 @@ describe('@hbarlimiter HBAR Limiter Acceptance Tests', function () {
});

it('should create a BASIC spending plan for a new user and use the same plan on second transaction', async function () {
expect(ethAddressSpendingPlanRepository.findByAddress(accounts[2].address, requestDetails)).to.be.rejected;

const parentContract = await deployContract(parentContractJson, accounts[2].wallet);
const parentContract = await deployContract(parentContractJson, accounts[0].wallet);
const parentContractAddress = parentContract.target as string;
global.logger.trace(
`${requestDetails.formattedRequestId} Deploy parent contract on address ${parentContractAddress}`,
);

//Unlinking the ipAdress, since ipAddress when running tests in CI and locally is the same
await ipSpendingPlanRepository.deleteAll(requestDetails);
expect(ethAddressSpendingPlanRepository.findByAddress(accounts[3].address, requestDetails)).to.be.rejected;
const gasPrice = await relay.gasPrice(requestId);
const transaction = {
...defaultLondonTransactionData,
to: parentContractAddress,
nonce: await relay.getAccountNonce(accounts[2].address, requestId),
nonce: await relay.getAccountNonce(accounts[3].address, requestId),
maxPriorityFeePerGas: gasPrice,
maxFeePerGas: gasPrice,
};
const signedTx = await accounts[2].wallet.signTransaction(transaction);
const signedTx = await accounts[3].wallet.signTransaction(transaction);

await expect(relay.call(testConstants.ETH_ENDPOINTS.ETH_SEND_RAW_TRANSACTION, [signedTx], requestId)).to.be
.fulfilled;

const ethSpendingPlan = await ethAddressSpendingPlanRepository.findByAddress(
accounts[2].address,
accounts[3].address,
requestDetails,
);
expect(ethSpendingPlan).to.not.be.undefined;
Expand All @@ -415,40 +370,66 @@ describe('@hbarlimiter HBAR Limiter Acceptance Tests', function () {
const secondTransaction = {
...defaultLondonTransactionData,
to: parentContractAddress,
nonce: await relay.getAccountNonce(accounts[2].address, requestId),
nonce: await relay.getAccountNonce(accounts[3].address, requestId),
maxPriorityFeePerGas: gasPrice,
maxFeePerGas: gasPrice,
};
const signedTxSecond = await accounts[2].wallet.signTransaction(secondTransaction);
const signedTxSecond = await accounts[3].wallet.signTransaction(secondTransaction);

await expect(relay.call(testConstants.ETH_ENDPOINTS.ETH_SEND_RAW_TRANSACTION, [signedTxSecond], requestId)).to
.be.fulfilled;

await new Promise((r) => setTimeout(r, 3000));
const spendingPlanAssociatedAfterSecond = await hbarSpendingPlanRepository.findByIdWithDetails(
ethSpendingPlan.planId,
requestDetails,
);
expect(amountSpendAfterFirst).to.be.lt(spendingPlanAssociatedAfterSecond.amountSpent);
});

// it should use a different BASIC plan for another user
const thirdTransaction = {
...defaultLondonTransactionData,
to: parentContractAddress,
nonce: await relay.getAccountNonce(accounts[3].address, requestId),
maxPriorityFeePerGas: gasPrice,
maxFeePerGas: gasPrice,
};
const signedTxThird = await accounts[3].wallet.signTransaction(thirdTransaction);

await expect(relay.call(testConstants.ETH_ENDPOINTS.ETH_SEND_RAW_TRANSACTION, [signedTxThird], requestId)).to
.be.fulfilled;
it('should eventually exhaust the hbar limit for a BASIC user after multiple deployments of large contracts', async function () {
const fileChunkSize = Number(process.env.FILE_APPEND_CHUNK_SIZE) || 5120;
const exchangeRateResult = (await mirrorNode.get(`/network/exchangerate`, requestId)).current_rate;
const exchangeRateInCents = exchangeRateResult.cent_equivalent / exchangeRateResult.hbar_equivalent;

const ethSpendingPlanThird = await ethAddressSpendingPlanRepository.findByAddress(
accounts[3].address,
requestDetails,
const factory = new ethers.ContractFactory(
largeContractJson.abi,
largeContractJson.bytecode,
accounts[0].wallet,
);
expect(ethSpendingPlanThird).to.not.be.undefined;
expect(ethSpendingPlanThird.planId).to.not.equal(ethSpendingPlan.planId);
const deployedTransaction = await factory.getDeployTransaction();
const estimatedTxFee = estimateFileTransactionsFee(
deployedTransaction.data.length,
fileChunkSize,
exchangeRateInCents,
);

//Unlinking the ipAdress, since ipAddress when running tests in CI and locally is the same
await ipSpendingPlanRepository.deleteAll(requestDetails);
expect(ethAddressSpendingPlanRepository.findByAddress(accounts[2].address, requestDetails)).to.be.rejected;
try {
for (let i = 0; i < 50; i++) {
await deployContract(largeContractJson, accounts[2].wallet);
}
expect.fail(`Expected an error but nothing was thrown`);
} catch (e: any) {
expect(e.message).to.contain(predefined.HBAR_RATE_LIMIT_EXCEEDED.message);

const ethSpendingPlan = await ethAddressSpendingPlanRepository.findByAddress(
accounts[2].wallet.address,
requestDetails,
);

const spendingPlanAssociated = await hbarSpendingPlanRepository.findByIdWithDetails(
ethSpendingPlan.planId,
requestDetails,
);
const basicSpendingLimit = HbarLimitService.TIER_LIMITS[SubscriptionTier.BASIC];
const amountSpent = spendingPlanAssociated.amountSpent;

// Explanation: A preemptive rate limit check triggers the HBAR_RATE_LIMIT_EXCEED error when basicSpendingLimit < estimatedTxFee + amountSpent.
expect(basicSpendingLimit.toTinybars().toNumber()).to.be.lt(estimatedTxFee + amountSpent);
}
});

it.skip('multiple deployments of large contracts should eventually exhaust the remaining hbar limit', async function () {
Expand All @@ -457,27 +438,10 @@ describe('@hbarlimiter HBAR Limiter Acceptance Tests', function () {
let exchangeRateResult = (await mirrorNode.get(`/network/exchangerate`, requestId)).current_rate;
const exchangeRateInCents = exchangeRateResult.cent_equivalent / exchangeRateResult.hbar_equivalent;

// Create a PRIVILEGED spending plan for the user in order to be able to deploy multiple large contracts
const ttl = 60000; // 1 minute
const hbarSpendingPlan = await hbarSpendingPlanRepository.create(
SubscriptionTier.PRIVILEGED,
requestDetails,
ttl,
);

await ethAddressSpendingPlanRepository.save(
{
ethAddress: accounts[4].address,
planId: hbarSpendingPlan.id,
},
requestDetails,
ttl,
);

const factory = new ethers.ContractFactory(
largeContractJson.abi,
largeContractJson.bytecode,
accounts[4].wallet,
accounts[0].wallet,
);
const deployedTransaction = await factory.getDeployTransaction();
const estimatedTxFee = estimateFileTransactionsFee(
Expand All @@ -490,7 +454,7 @@ describe('@hbarlimiter HBAR Limiter Acceptance Tests', function () {
expect(remainingHbarsBefore).to.be.gt(0);
try {
for (let i = 0; i < 50; i++) {
const contract = await deployContract(largeContractJson, accounts[4].wallet);
const contract = await deployContract(largeContractJson, accounts[0].wallet);
await contract.waitForDeployment();
const remainingHbars = Number(await metrics.get(testConstants.METRICS.REMAINING_HBAR_LIMIT));
expect(remainingHbars).to.be.lt(lastRemainingHbars);
Expand Down
4 changes: 1 addition & 3 deletions packages/server/tests/localAcceptance.env
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,4 @@ LIMIT_DURATION=90000
SERVER_REQUEST_TIMEOUT_MS=60000
MEMWATCH_ENABLED=true
WRITE_SNAPSHOT_ON_MEMORY_LEAK=false
HBAR_RATE_LIMIT_DURATION=60000# 1 minute
HBAR_RATE_LIMIT_TINYBAR=3000000000# 30 HBARs
HBAR_RATE_LIMIT_BASIC=600000000# 6 HBARs
HBAR_RATE_LIMIT_BASIC=3000000000 # 30 hbar
3 changes: 0 additions & 3 deletions packages/server/tests/previewnetAcceptance.env
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,3 @@ SERVER_REQUEST_TIMEOUT_MS=60000
MEMWATCH_ENABLED=false
WRITE_SNAPSHOT_ON_MEMORY_LEAK=false
TEST_INITIAL_ACCOUNT_STARTING_BALANCE=500
HBAR_RATE_LIMIT_DURATION=60000# 1 minute
HBAR_RATE_LIMIT_TINYBAR=3000000000# 30 HBARs
HBAR_RATE_LIMIT_BASIC=600000000# 6 HBARs
3 changes: 0 additions & 3 deletions packages/server/tests/testnetAcceptance.env
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,3 @@ SERVER_REQUEST_TIMEOUT_MS=60000
MEMWATCH_ENABLED=false
WRITE_SNAPSHOT_ON_MEMORY_LEAK=false
TEST_INITIAL_ACCOUNT_STARTING_BALANCE=500
HBAR_RATE_LIMIT_DURATION=60000# 1 minute
HBAR_RATE_LIMIT_TINYBAR=3000000000# 30 HBARs
HBAR_RATE_LIMIT_BASIC=600000000# 6 HBARs

0 comments on commit 6cb081b

Please sign in to comment.