Skip to content

Commit

Permalink
[master] Make scilla tests parallel-friendly. (#3762)
Browse files Browse the repository at this point in the history
* Separate eth signers and zil signers

* Add more scilla tests

* Remove useless packages

* Fix init-signers to batch fund zil addresses

* Fix packages

* Bump s-h-p version

* new tests

* bump hardhat-scilla-plugin version

* Fix HelloWorld test

* Fix FungibleToken tests

* Fix GetBalance test

* Refactor, add new script to fund from eth accounts

* Update CI script

* fix ci

* Update readme
  • Loading branch information
its-saeed committed Oct 3, 2023
1 parent 5b59c76 commit 5400dd1
Show file tree
Hide file tree
Showing 36 changed files with 691 additions and 440 deletions.
1 change: 1 addition & 0 deletions scripts/integration_test_js.sh
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@ else

cd tests/EvmAcceptanceTests/
npm install
npx hardhat run scripts/FundAccountsFromEth.ts
DEBUG=true MOCHA_TIMEOUT=40000 npx hardhat test --bail 2>&1 > npx.out

retVal=$?
Expand Down
73 changes: 57 additions & 16 deletions tests/EvmAcceptanceTests/AddConfigHelpersToHre.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,12 @@ import {Contract as Web3Contract} from "web3-eth-contract";
import {SignerWithAddress} from "@nomiclabs/hardhat-ethers/signers";
import {TransactionRequest, TransactionResponse} from "@ethersproject/providers";
import BN from "bn.js";
import {ScillaContract, Setup} from "hardhat-scilla-plugin";
import {Account} from "@zilliqa-js/zilliqa";

declare module "hardhat/types/runtime" {
interface HardhatRuntimeEnvironment {
zilliqaSetup: Setup;
signer_pool: SingerPool;
debug: boolean;
parallel: boolean;
Expand All @@ -24,10 +27,15 @@ declare module "hardhat/types/runtime" {
getProtocolVersion: () => number;
getMiningState: () => boolean;
getNetworkName: () => string;
getASignerForContractDeployment: () => Promise<SignerWithAddress>;
allocateSigner: () => SignerWithAddress;
releaseSigner: (...signer: SignerWithAddress[]) => void;
sendTransaction: (txn: TransactionRequest) => Promise<{response: TransactionResponse; signer_address: string}>;
getEthSignerForContractDeployment: () => Promise<SignerWithAddress>;
getZilSignerForContractDeployment: () => Account;
allocateEthSigner: () => SignerWithAddress;
allocateZilSigner: () => Account;
releaseEthSigner: (...signer: SignerWithAddress[]) => void;
releaseZilSigner: (...signer: Account[]) => void;
sendEthTransaction: (txn: TransactionRequest) => Promise<{response: TransactionResponse; signer_address: string}>;
deployScillaContract2: (name: string, ...args: any[]) => Promise<ScillaContract>;
deployScillaContractWithSigner: (name: string, signer: Account, ...args: any[]) => Promise<ScillaContract>;
deployContract: (name: string, ...args: any[]) => Promise<Contract>;
deployContractWithSigner: (name: string, signer: Signer, ...args: any[]) => Promise<Contract>;
deployContractWeb3: (
Expand Down Expand Up @@ -79,33 +87,66 @@ extendEnvironment((hre: HardhatRuntimeEnvironment) => {
return (hre as any).network.name;
};

hre.getASignerForContractDeployment = async (): Promise<SignerWithAddress> => {
hre.getEthSignerForContractDeployment = async (): Promise<SignerWithAddress> => {
if (hre.parallel) {
return hre.signer_pool.takeSigner();
return hre.signer_pool.takeEthSigner();
} else {
return (await hre.ethers.getSigners())[0];
}
};

/// If you call this function, consequently you must call `releaseSigner`, otherwise you'll run out of signers.
hre.allocateSigner = (): SignerWithAddress => {
return hre.signer_pool.takeSigner();
hre.getZilSignerForContractDeployment = (): Account => {
if (hre.parallel) {
return hre.signer_pool.takeZilSigner();
} else {
return hre.signer_pool.getZilSigner(0);
}
};

/// If you call this function, consequently you must call `releaseEthSigner`, otherwise you'll run out of signers.
hre.allocateEthSigner = (): SignerWithAddress => {
return hre.signer_pool.takeEthSigner();
};

/// If you call this function, consequently you must call `releaseZilSigner`, otherwise you'll run out of signers.
hre.allocateZilSigner = (): Account => {
return hre.signer_pool.takeZilSigner();
};

hre.releaseSigner = (...signer: SignerWithAddress[]) => {
hre.signer_pool.releaseSigner(...signer);
hre.releaseEthSigner = (...signer: SignerWithAddress[]) => {
hre.signer_pool.releaseEthSigner(...signer);
};

hre.sendTransaction = async (txn: TransactionRequest) => {
const signer = hre.allocateSigner();
hre.releaseZilSigner = (...signer: Account[]) => {
hre.signer_pool.releaseZilSigner(...signer);
};

hre.sendEthTransaction = async (txn: TransactionRequest) => {
const signer = hre.allocateEthSigner();
const response = await signer.sendTransaction(txn);
hre.releaseSigner(signer);
hre.releaseEthSigner(signer);

return {response, signer_address: await signer.getAddress()};
};

hre.deployScillaContract2 = async (name: string, ...args: any[]): Promise<ScillaContract> => {
const signer = hre.getZilSignerForContractDeployment();
hre.setActiveAccount(signer);
return hre.deployScillaContract(name, ...args);
};

hre.deployScillaContractWithSigner = async (
name: string,
signer: Account,
...args: any[]
): Promise<ScillaContract> => {
hre.setActiveAccount(signer);
let contract = await hre.deployScillaContract(name, ...args);
return contract.connect(signer);
};

hre.deployContract = async (name: string, ...args: any[]): Promise<Contract> => {
const signer = await hre.getASignerForContractDeployment();
const signer = await hre.getEthSignerForContractDeployment();
return hre.deployContractWithSigner(name, signer, ...args);
};

Expand All @@ -120,7 +161,7 @@ extendEnvironment((hre: HardhatRuntimeEnvironment) => {
options: {gasPrice?: string; gasLimit?: number; value?: BN},
...args: any[]
): Promise<Web3Contract> => {
const signer = await hre.getASignerForContractDeployment();
const signer = await hre.getEthSignerForContractDeployment();

const contractRaw = hre.artifacts.readArtifactSync(contractName);
const contract = new hre.web3.eth.Contract(contractRaw.abi);
Expand Down
9 changes: 7 additions & 2 deletions tests/EvmAcceptanceTests/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -401,8 +401,8 @@ npx hardhat transfer --from db11cfa086b92497c8ed5a4cc6edb3a5bfe3a640c43ffb9fc6aa
To get the balances of the current accounts, run:

```bash
npx hardhat run scripts/Accounts.js
npx hardhat run scripts/Accounts.js --network public_testnet
npx hardhat run scripts/Accounts.ts
npx hardhat run scripts/Accounts.ts --network public_testnet
```

When you start a testnet, your funds are initially in zil addresses, which is inconvenient.
Expand All @@ -413,6 +413,11 @@ and moves half of the funds at that address to the same address, but eth style.
npx hardhat run scripts/FundAccountsFromZil.ts --network testnet
```

Similarly you can do the same job if your initial accounts have funds in their eth addresses:
```bash
npx hardhat run scripts/FundAccountsFromEth.ts --network your_network
```

## Setup github pre-commit hook

You may want to set up pre-commit hook to fix your code before commit by:
Expand Down
28 changes: 23 additions & 5 deletions tests/EvmAcceptanceTests/hardhat.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,6 @@ import "@nomiclabs/hardhat-web3";
import {HardhatUserConfig} from "hardhat/types";
import "dotenv/config";
import {ENV_VARS} from "./helpers/EnvVarParser";
import "./tasks/ZilBalance";
import "./tasks/Transfer";
import "./tasks/InitSigners";
import fs from "fs";

if (ENV_VARS.scilla) {
Expand Down Expand Up @@ -36,7 +33,21 @@ const loadFromSignersFile = (network_name: string): string[] => {
const config: HardhatUserConfig = {
solidity: "0.8.9",
defaultNetwork: "isolated_server",

networks: {
public_devnet: {
url: "https://api.devnet.zilliqa.com",
websocketUrl: "ws://api.devnet.zilliqa.com",
accounts: [
"4CC853DE4F9FE4A9155185C65B56B6A9B024F896B54528B9E9448B6CD9B8F329",
...loadFromSignersFile("public_devnet")
],
chainId: 33385,
zilliqaNetwork: true,
web3ClientVersion: "Zilliqa/v8.2",
protocolVersion: 0x41,
miningState: false
},
localdev2: {
url: "http://localdev-l2api.localdomain",
websocketUrl: "ws://localdev-l2api.localdomain",
Expand Down Expand Up @@ -130,13 +141,20 @@ import "./AddConfigHelpersToHre";
import {extendEnvironment} from "hardhat/config";
import SignerPool from "./helpers/parallel-tests/SignerPool";
extendEnvironment(async (hre) => {
const private_keys: string[] = hre.network["config"]["accounts"] as string[];

hre.debug = ENV_VARS.debug;
hre.scillaTesting = ENV_VARS.scilla;
hre.signer_pool = new SignerPool();
hre.zilliqaSetup = initZilliqa(hre.getNetworkUrl(), hre.getZilliqaChainId(), private_keys, 30);
});

import "./tasks/Balances"; // To fix tsc error
import "./tasks/Setup"; // To fix tsc error
import "./tasks/Balances";
import "./tasks/Setup";
import "./tasks/ParallelTest";
import "./tasks/Test";
import "./tasks/ZilBalance";
import "./tasks/Transfer";
import "./tasks/InitSigners";
import {initZilliqa} from "hardhat-scilla-plugin";
export default config;
10 changes: 3 additions & 7 deletions tests/EvmAcceptanceTests/helpers/Parallelizer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import {getAddressFromPrivateKey} from "@zilliqa-js/crypto";
import BN from "bn.js";
import hre, {ethers as hh_ethers, web3} from "hardhat";
import {initZilliqa, ScillaContract, Setup, UserDefinedLibrary} from "hardhat-scilla-plugin";
import {} from "hardhat-scilla-plugin/dist/src/index";

export type DeployOptions = {
gasPrice?: string;
Expand All @@ -11,13 +12,9 @@ export type DeployOptions = {

export class Parallelizer {
constructor() {
let privateKey = "254d9924fc1dcdca44ce92d80255c6a0bb690f867abde80e626fbfef4d357004";
if (process.env.PRIMARY_ACCOUNT !== undefined) {
privateKey = process.env.PRIMARY_ACCOUNT;
}
const private_keys: string[] = hre.network["config"]["accounts"] as string[];

this.zilliqaAccountAddress = getAddressFromPrivateKey(privateKey);
this.zilliqaSetup = initZilliqa(hre.getNetworkUrl(), hre.getZilliqaChainId(), [privateKey], 30);
this.zilliqaSetup = initZilliqa(hre.getNetworkUrl(), hre.getZilliqaChainId(), private_keys, 30);
}

async deployScillaContract(contractName: string, ...args: any[]): Promise<ScillaContract> {
Expand All @@ -36,7 +33,6 @@ export class Parallelizer {
return hre.deployScillaContractWithLib(libraryName, userDefinedLibraries, ...args);
}

zilliqaAccountAddress: string;
zilliqaSetup: Setup;
}

Expand Down
42 changes: 32 additions & 10 deletions tests/EvmAcceptanceTests/helpers/parallel-tests/SignerPool.ts
Original file line number Diff line number Diff line change
@@ -1,27 +1,49 @@
import {SignerWithAddress} from "@nomiclabs/hardhat-ethers/signers";
import {Account} from "@zilliqa-js/account";

export default class SignerPool {
public takeSigner(): SignerWithAddress {
if (this.signers.length == 0) {
public takeEthSigner(): SignerWithAddress {
if (this.eth_signers.length == 0) {
throw new Error(
"No more signers to return. Either you haven't initialized this pool, or you just ran out of signers."
);
}

return this.signers.pop()!;
return this.eth_signers.pop()!;
}

public initSigners(...signer: SignerWithAddress[]) {
this.releaseSigner(...signer);
public takeZilSigner(): Account {
if (this.zil_signers.length == 0) {
throw new Error(
"No more signers to return. Either you haven't initialized this pool, or you just ran out of signers."
);
}

return this.zil_signers.pop()!;
}

public initSigners(signer: SignerWithAddress[], privateKeys: string[]) {
this.releaseEthSigner(...signer);

this.zil_signers.push(...privateKeys.map((key) => new Account(key)));
}

public releaseEthSigner(...signer: SignerWithAddress[]) {
this.eth_signers.push(...signer);
}

public releaseZilSigner(...signer: Account[]) {
this.zil_signers.push(...signer);
}

public releaseSigner(...signer: SignerWithAddress[]) {
this.signers.push(...signer);
public getZilSigner(index: number): Account {
return this.zil_signers[index];
}

public count(): number {
return this.signers.length;
public count(): [eth_count: number, zil_count: number] {
return [this.eth_signers.length, this.zil_signers.length];
}

private signers: SignerWithAddress[] = [];
private eth_signers: SignerWithAddress[] = [];
private zil_signers: Account[] = [];
}

0 comments on commit 5400dd1

Please sign in to comment.