소스 검색

feat(contract_manager): latency script for entropy v2 (#1494)

* 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
Dev Kalra 1 년 전
부모
커밋
4b8b9bfd87

+ 32 - 1
contract_manager/scripts/common.ts

@@ -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";
@@ -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;
+}

+ 12 - 13
contract_manager/scripts/latency_entropy.ts

@@ -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();

+ 87 - 0
contract_manager/scripts/latency_entropy_with_callback.ts

@@ -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();

+ 18 - 7
contract_manager/src/contracts/evm.ts

@@ -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,