Эх сурвалжийг харах

feat(contract_manager): latency script for entropy (#1367)

* feat(contract_manager): latency script for entropy
Amin Moghaddam 1 жил өмнө
parent
commit
6adfdb1beb

+ 1 - 1
contract_manager/scripts/common.ts

@@ -67,7 +67,7 @@ export const COMMON_DEPLOY_OPTIONS = {
   "private-key": {
     type: "string",
     demandOption: true,
-    desc: "Private key to sign the trnasactions with",
+    desc: "Private key to sign the transactions with",
   },
   chain: {
     type: "array",

+ 67 - 0
contract_manager/scripts/latency_entropy.ts

@@ -0,0 +1,67 @@
+import yargs from "yargs";
+import { hideBin } from "yargs/helpers";
+import { DefaultStore, toPrivateKey } from "../src";
+import { COMMON_DEPLOY_OPTIONS } 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>"
+  )
+  .options({
+    contract: {
+      type: "string",
+      demandOption: true,
+      desc: "Contract to test latency for",
+    },
+    "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 provider = await contract.getDefaultProvider();
+  const providerInfo = await contract.getProviderInfo(provider);
+  const userRandomNumber = contract.generateUserRandomNumber();
+  const privateKey = toPrivateKey(argv.privateKey);
+  const requestResponse = await contract.requestRandomness(
+    userRandomNumber,
+    provider,
+    privateKey
+  );
+  console.log("Request tx hash: ", requestResponse.transactionHash);
+  const startTime = Date.now();
+  const sequenceNumber = providerInfo.sequenceNumber;
+  const revealUrl = providerInfo.uri + `/revelations/${sequenceNumber}`;
+  console.log("Checking this url for revelation:", revealUrl);
+  // eslint-disable-next-line no-constant-condition
+  while (true) {
+    const fortunaResponse = await fetch(revealUrl);
+    if (fortunaResponse.status === 200) {
+      const payload = await fortunaResponse.json();
+      const endTime = Date.now();
+      console.log(`Fortuna Latency: ${endTime - startTime}ms`);
+      const providerRevelation = "0x" + payload.value.data;
+      const revealResponse = await contract.revealRandomness(
+        userRandomNumber,
+        providerRevelation,
+        provider,
+        sequenceNumber,
+        privateKey
+      );
+      console.log("Reveal tx hash: ", revealResponse.transactionHash);
+      break;
+    }
+    await new Promise((resolve) => setTimeout(resolve, 300));
+  }
+}
+
+main();

+ 20 - 0
contract_manager/src/chains.ts

@@ -22,6 +22,7 @@ import {
 import { Network } from "@injectivelabs/networks";
 import { SuiClient } from "@mysten/sui.js/client";
 import { Ed25519Keypair } from "@mysten/sui.js/keypairs/ed25519";
+import { TransactionObject } from "web3/eth/types";
 
 export type ChainConfig = Record<string, string> & {
   mainnet: boolean;
@@ -386,6 +387,25 @@ export class EvmChain extends Chain {
     return gasPrice;
   }
 
+  async estiamteAndSendTransaction(
+    transactionObject: TransactionObject<any>,
+    txParams: { from?: string; value?: string }
+  ) {
+    const GAS_ESTIMATE_MULTIPLIER = 2;
+    const gasEstimate = await transactionObject.estimateGas({
+      gas: 15000000,
+      ...txParams,
+    });
+    // Some networks like Filecoin do not support the normal transaction type and need a type 2 transaction.
+    // To send a type 2 transaction, remove the ``gasPrice`` field and add the `type` field with the value
+    // `0x2` to the transaction configuration parameters.
+    return transactionObject.send({
+      gas: gasEstimate * GAS_ESTIMATE_MULTIPLIER,
+      gasPrice: await this.getGasPrice(),
+      ...txParams,
+    });
+  }
+
   /**
    * Deploys a contract on this chain
    * @param privateKey hex string of the 32 byte private key without the 0x prefix

+ 64 - 42
contract_manager/src/contracts/evm.ts

@@ -7,7 +7,6 @@ import { DataSource, EvmExecute } from "xc_admin_common";
 import { WormholeContract } from "./wormhole";
 
 // Just to make sure tx gas limit is enough
-const GAS_ESTIMATE_MULTIPLIER = 2;
 const EXTENDED_ENTROPY_ABI = [
   {
     inputs: [],
@@ -394,18 +393,10 @@ export class WormholeEvmContract extends WormholeContract {
     const transactionObject = wormholeContract.methods.submitNewGuardianSet(
       "0x" + vaa.toString("hex")
     );
-    const gasEstiamte = await transactionObject.estimateGas({
-      from: address,
-      gas: 15000000,
-    });
-    // Some networks like Filecoin do not support the normal transaction type and need a type 2 transaction.
-    // To send a type 2 transaction, remove the ``gasPrice`` field and add the `type` field with the value
-    // `0x2` to the transaction configuration parameters.
-    const result = await transactionObject.send({
-      from: address,
-      gas: gasEstiamte * GAS_ESTIMATE_MULTIPLIER,
-      gasPrice: await this.chain.getGasPrice(),
-    });
+    const result = await this.chain.estiamteAndSendTransaction(
+      transactionObject,
+      { from: address }
+    );
     return { id: result.transactionHash, info: result };
   }
 }
@@ -543,6 +534,54 @@ export class EvmEntropyContract extends Storable {
       uri: Web3.utils.toAscii(info.uri),
     };
   }
+
+  generateUserRandomNumber() {
+    const web3 = new Web3(this.chain.getRpcUrl());
+    return web3.utils.randomHex(32);
+  }
+
+  async requestRandomness(
+    userRandomNumber: string,
+    provider: string,
+    senderPrivateKey: PrivateKey
+  ) {
+    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
+    );
+    return this.chain.estiamteAndSendTransaction(transactionObject, {
+      from: address,
+      value: fee,
+    });
+  }
+
+  async revealRandomness(
+    userRevelation: string,
+    providerRevelation: string,
+    provider: string,
+    sequenceNumber: string,
+    senderPrivateKey: PrivateKey
+  ) {
+    const web3 = new Web3(this.chain.getRpcUrl());
+    const contract = new web3.eth.Contract(EXTENDED_ENTROPY_ABI, this.address);
+    const { address } = web3.eth.accounts.wallet.add(senderPrivateKey);
+    const transactionObject = contract.methods.reveal(
+      provider,
+      sequenceNumber,
+      userRevelation,
+      providerRevelation
+    );
+    return this.chain.estiamteAndSendTransaction(transactionObject, {
+      from: address,
+    });
+  }
 }
 
 export class EvmExecutorContract {
@@ -602,15 +641,10 @@ export class EvmExecutorContract {
     const transactionObject = executorContract.methods.execute(
       "0x" + vaa.toString("hex")
     );
-    const gasEstimate = await transactionObject.estimateGas({
-      from: address,
-      gas: 100000000,
-    });
-    const result = await transactionObject.send({
-      from: address,
-      gas: gasEstimate * GAS_ESTIMATE_MULTIPLIER,
-      gasPrice: await this.chain.getGasPrice(),
-    });
+    const result = await this.chain.estiamteAndSendTransaction(
+      transactionObject,
+      { from: address }
+    );
     return { id: result.transactionHash, info: result };
   }
 }
@@ -787,17 +821,10 @@ export class EvmPriceFeedContract extends PriceFeedContract {
       .call();
     const transactionObject =
       pythContract.methods.updatePriceFeeds(priceFeedUpdateData);
-    const gasEstimate = await transactionObject.estimateGas({
-      from: address,
-      gas: 15000000,
-      value: updateFee,
-    });
-    const result = await transactionObject.send({
-      from: address,
-      value: updateFee,
-      gas: gasEstimate * GAS_ESTIMATE_MULTIPLIER,
-      gasPrice: await this.chain.getGasPrice(),
-    });
+    const result = await this.chain.estiamteAndSendTransaction(
+      transactionObject,
+      { from: address, value: updateFee }
+    );
     return { id: result.transactionHash, info: result };
   }
 
@@ -811,15 +838,10 @@ export class EvmPriceFeedContract extends PriceFeedContract {
     const transactionObject = pythContract.methods.executeGovernanceInstruction(
       "0x" + vaa.toString("hex")
     );
-    const gasEstiamte = await transactionObject.estimateGas({
-      from: address,
-      gas: 15000000,
-    });
-    const result = await transactionObject.send({
-      from: address,
-      gas: gasEstiamte * GAS_ESTIMATE_MULTIPLIER,
-      gasPrice: await this.chain.getGasPrice(),
-    });
+    const result = await this.chain.estiamteAndSendTransaction(
+      transactionObject,
+      { from: address }
+    );
     return { id: result.transactionHash, info: result };
   }