Skip to content

Commit

Permalink
feat(contract_manager): latency script for entropy v2 (#1494)
Browse files Browse the repository at this point in the history
* latency script for entropy v2

* add block number difference

* correct desc

* refactor request randomness

* refactor and use chain as arg instead of contract

* unnecessary condition

* js doc

* correct desc

* use blockhash
  • Loading branch information
Dev Kalra authored Apr 23, 2024
1 parent c7883c8 commit 4b8b9bf
Show file tree
Hide file tree
Showing 4 changed files with 149 additions and 21 deletions.
33 changes: 32 additions & 1 deletion contract_manager/scripts/common.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { DefaultStore, EvmChain, PrivateKey } from "../src";
import { DefaultStore, EvmChain, EvmEntropyContract, PrivateKey } from "../src";
import { existsSync, readFileSync, writeFileSync } from "fs";
import { join } from "path";
import Web3 from "web3";
Expand Down Expand Up @@ -181,3 +181,34 @@ export function getSelectedChains(argv: {
}
return selectedChains;
}

/**
* Finds the entropy contract for a given EVM chain.
* @param {EvmChain} chain The EVM chain to find the entropy contract for.
* @returns The entropy contract for the given EVM chain.
* @throws {Error} an error if the entropy contract is not found for the given EVM chain.
*/
export function findEntropyContract(chain: EvmChain): EvmEntropyContract {
for (const contract of Object.values(DefaultStore.entropy_contracts)) {
if (contract.getChain().getId() === chain.getId()) {
return contract;
}
}
throw new Error(`Entropy contract not found for chain ${chain.getId()}`);
}

/**
* Finds an EVM chain by its name.
* @param {string} chainName The name of the chain to find.
* @returns The EVM chain instance.
* @throws {Error} an error if the chain is not found or is not an EVM chain.
*/
export function findEvmChain(chainName: string): EvmChain {
const chain = DefaultStore.chains[chainName];
if (!chain) {
throw new Error(`Chain ${chainName} not found`);
} else if (!(chain instanceof EvmChain)) {
throw new Error(`Chain ${chainName} is not an EVM chain`);
}
return chain;
}
25 changes: 12 additions & 13 deletions contract_manager/scripts/latency_entropy.ts
Original file line number Diff line number Diff line change
@@ -1,33 +1,32 @@
import yargs from "yargs";
import { hideBin } from "yargs/helpers";
import { DefaultStore, toPrivateKey } from "../src";
import { COMMON_DEPLOY_OPTIONS } from "./common";
import { toPrivateKey } from "../src";
import {
COMMON_DEPLOY_OPTIONS,
findEntropyContract,
findEvmChain,
} from "./common";

const parser = yargs(hideBin(process.argv))
.usage(
"Requests and reveals a random number from an entropy contract while measuing the\n" +
"latency between request submission and availablity of the provider revelation from fortuna.\n" +
"Usage: $0 --contract <entropy_contract_id> --private-key <private-key>"
"Usage: $0 --chain <chain-id> --private-key <private-key>"
)
.options({
contract: {
chain: {
type: "string",
demandOption: true,
desc: "Contract to test latency for",
desc: "test latency for the contract on this chain",
},
"private-key": COMMON_DEPLOY_OPTIONS["private-key"],
});

async function main() {
const argv = await parser.argv;
const contract = DefaultStore.entropy_contracts[argv.contract];
if (!contract) {
throw new Error(
`Contract ${argv.contract} not found. Contracts found: ${Object.keys(
DefaultStore.entropy_contracts
)}`
);
}
const chain = findEvmChain(argv.chain);
const contract = findEntropyContract(chain);

const provider = await contract.getDefaultProvider();
const providerInfo = await contract.getProviderInfo(provider);
const userRandomNumber = contract.generateUserRandomNumber();
Expand Down
87 changes: 87 additions & 0 deletions contract_manager/scripts/latency_entropy_with_callback.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
import yargs from "yargs";
import { hideBin } from "yargs/helpers";
import { toPrivateKey } from "../src";
import {
COMMON_DEPLOY_OPTIONS,
findEntropyContract,
findEvmChain,
} from "./common";
import Web3 from "web3";

const parser = yargs(hideBin(process.argv))
.usage(
"Requests a random number from an entropy contract and measures the\n" +
"latency between request submission and fulfillment by the Fortuna keeper service.\n" +
"Usage: $0 --chain-id <chain-id> --private-key <private-key>"
)
.options({
chain: {
type: "string",
demandOption: true,
desc: "test latency for the contract on this chain",
},
"private-key": COMMON_DEPLOY_OPTIONS["private-key"],
});

async function main() {
const argv = await parser.argv;

const chain = findEvmChain(argv.chain);
const contract = findEntropyContract(chain);

const provider = await contract.getDefaultProvider();
const userRandomNumber = contract.generateUserRandomNumber();
const privateKey = toPrivateKey(argv.privateKey);
const requestResponse = await contract.requestRandomness(
userRandomNumber,
provider,
privateKey,
true // with callback
);
console.log(`Request tx hash : ${requestResponse.transactionHash}`);
// Read the sequence number for the request from the transaction events.
const sequenceNumber =
requestResponse.events.RequestedWithCallback.returnValues.sequenceNumber;
console.log(`sequence : ${sequenceNumber}`);

const startTime = Date.now();

let fromBlock = requestResponse.blockNumber;
const web3 = new Web3(contract.chain.getRpcUrl());
const entropyContract = contract.getContract();

// eslint-disable-next-line no-constant-condition
while (true) {
const currentBlock = await web3.eth.getBlockNumber();

if (fromBlock > currentBlock) {
continue;
}

const events = await entropyContract.getPastEvents("RevealedWithCallback", {
fromBlock: fromBlock,
toBlock: currentBlock,
});
fromBlock = currentBlock + 1;

const event = events.find(
(event) => event.returnValues.request[1] == sequenceNumber
);

if (event !== undefined) {
console.log(`Random number : ${event.returnValues.randomNumber}`);
const endTime = Date.now();
console.log(`Fortuna Latency : ${endTime - startTime}ms`);
console.log(
`Revealed after : ${
currentBlock - requestResponse.blockNumber
} blocks`
);
break;
}

await new Promise((resolve) => setTimeout(resolve, 300));
}
}

main();
25 changes: 18 additions & 7 deletions contract_manager/src/contracts/evm.ts
Original file line number Diff line number Diff line change
Expand Up @@ -592,19 +592,30 @@ export class EvmEntropyContract extends Storable {
async requestRandomness(
userRandomNumber: string,
provider: string,
senderPrivateKey: PrivateKey
senderPrivateKey: PrivateKey,
withCallback?: boolean
) {
const web3 = new Web3(this.chain.getRpcUrl());
const userCommitment = web3.utils.keccak256(userRandomNumber);
const contract = new web3.eth.Contract(EXTENDED_ENTROPY_ABI, this.address);
const fee = await contract.methods.getFee(provider).call();
const { address } = web3.eth.accounts.wallet.add(senderPrivateKey);
const useBlockHash = false;
const transactionObject = contract.methods.request(
provider,
userCommitment,
useBlockHash
);

let transactionObject;
if (withCallback) {
transactionObject = contract.methods.requestWithCallback(
provider,
userCommitment
);
} else {
const useBlockHash = false;
transactionObject = contract.methods.request(
provider,
userCommitment,
useBlockHash
);
}

return this.chain.estiamteAndSendTransaction(transactionObject, {
from: address,
value: fee,
Expand Down

0 comments on commit 4b8b9bf

Please sign in to comment.