Skip to content

Commit 6adfdb1

Browse files
authored
feat(contract_manager): latency script for entropy (#1367)
* feat(contract_manager): latency script for entropy
1 parent ac37b95 commit 6adfdb1

File tree

4 files changed

+152
-43
lines changed

4 files changed

+152
-43
lines changed

contract_manager/scripts/common.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ export const COMMON_DEPLOY_OPTIONS = {
6767
"private-key": {
6868
type: "string",
6969
demandOption: true,
70-
desc: "Private key to sign the trnasactions with",
70+
desc: "Private key to sign the transactions with",
7171
},
7272
chain: {
7373
type: "array",
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
import yargs from "yargs";
2+
import { hideBin } from "yargs/helpers";
3+
import { DefaultStore, toPrivateKey } from "../src";
4+
import { COMMON_DEPLOY_OPTIONS } from "./common";
5+
6+
const parser = yargs(hideBin(process.argv))
7+
.usage(
8+
"Requests and reveals a random number from an entropy contract while measuing the\n" +
9+
"latency between request submission and availablity of the provider revelation from fortuna.\n" +
10+
"Usage: $0 --contract <entropy_contract_id> --private-key <private-key>"
11+
)
12+
.options({
13+
contract: {
14+
type: "string",
15+
demandOption: true,
16+
desc: "Contract to test latency for",
17+
},
18+
"private-key": COMMON_DEPLOY_OPTIONS["private-key"],
19+
});
20+
21+
async function main() {
22+
const argv = await parser.argv;
23+
const contract = DefaultStore.entropy_contracts[argv.contract];
24+
if (!contract) {
25+
throw new Error(
26+
`Contract ${argv.contract} not found. Contracts found: ${Object.keys(
27+
DefaultStore.entropy_contracts
28+
)}`
29+
);
30+
}
31+
const provider = await contract.getDefaultProvider();
32+
const providerInfo = await contract.getProviderInfo(provider);
33+
const userRandomNumber = contract.generateUserRandomNumber();
34+
const privateKey = toPrivateKey(argv.privateKey);
35+
const requestResponse = await contract.requestRandomness(
36+
userRandomNumber,
37+
provider,
38+
privateKey
39+
);
40+
console.log("Request tx hash: ", requestResponse.transactionHash);
41+
const startTime = Date.now();
42+
const sequenceNumber = providerInfo.sequenceNumber;
43+
const revealUrl = providerInfo.uri + `/revelations/${sequenceNumber}`;
44+
console.log("Checking this url for revelation:", revealUrl);
45+
// eslint-disable-next-line no-constant-condition
46+
while (true) {
47+
const fortunaResponse = await fetch(revealUrl);
48+
if (fortunaResponse.status === 200) {
49+
const payload = await fortunaResponse.json();
50+
const endTime = Date.now();
51+
console.log(`Fortuna Latency: ${endTime - startTime}ms`);
52+
const providerRevelation = "0x" + payload.value.data;
53+
const revealResponse = await contract.revealRandomness(
54+
userRandomNumber,
55+
providerRevelation,
56+
provider,
57+
sequenceNumber,
58+
privateKey
59+
);
60+
console.log("Reveal tx hash: ", revealResponse.transactionHash);
61+
break;
62+
}
63+
await new Promise((resolve) => setTimeout(resolve, 300));
64+
}
65+
}
66+
67+
main();

contract_manager/src/chains.ts

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import {
2222
import { Network } from "@injectivelabs/networks";
2323
import { SuiClient } from "@mysten/sui.js/client";
2424
import { Ed25519Keypair } from "@mysten/sui.js/keypairs/ed25519";
25+
import { TransactionObject } from "web3/eth/types";
2526

2627
export type ChainConfig = Record<string, string> & {
2728
mainnet: boolean;
@@ -386,6 +387,25 @@ export class EvmChain extends Chain {
386387
return gasPrice;
387388
}
388389

390+
async estiamteAndSendTransaction(
391+
transactionObject: TransactionObject<any>,
392+
txParams: { from?: string; value?: string }
393+
) {
394+
const GAS_ESTIMATE_MULTIPLIER = 2;
395+
const gasEstimate = await transactionObject.estimateGas({
396+
gas: 15000000,
397+
...txParams,
398+
});
399+
// Some networks like Filecoin do not support the normal transaction type and need a type 2 transaction.
400+
// To send a type 2 transaction, remove the ``gasPrice`` field and add the `type` field with the value
401+
// `0x2` to the transaction configuration parameters.
402+
return transactionObject.send({
403+
gas: gasEstimate * GAS_ESTIMATE_MULTIPLIER,
404+
gasPrice: await this.getGasPrice(),
405+
...txParams,
406+
});
407+
}
408+
389409
/**
390410
* Deploys a contract on this chain
391411
* @param privateKey hex string of the 32 byte private key without the 0x prefix

contract_manager/src/contracts/evm.ts

Lines changed: 64 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ import { DataSource, EvmExecute } from "xc_admin_common";
77
import { WormholeContract } from "./wormhole";
88

99
// Just to make sure tx gas limit is enough
10-
const GAS_ESTIMATE_MULTIPLIER = 2;
1110
const EXTENDED_ENTROPY_ABI = [
1211
{
1312
inputs: [],
@@ -394,18 +393,10 @@ export class WormholeEvmContract extends WormholeContract {
394393
const transactionObject = wormholeContract.methods.submitNewGuardianSet(
395394
"0x" + vaa.toString("hex")
396395
);
397-
const gasEstiamte = await transactionObject.estimateGas({
398-
from: address,
399-
gas: 15000000,
400-
});
401-
// Some networks like Filecoin do not support the normal transaction type and need a type 2 transaction.
402-
// To send a type 2 transaction, remove the ``gasPrice`` field and add the `type` field with the value
403-
// `0x2` to the transaction configuration parameters.
404-
const result = await transactionObject.send({
405-
from: address,
406-
gas: gasEstiamte * GAS_ESTIMATE_MULTIPLIER,
407-
gasPrice: await this.chain.getGasPrice(),
408-
});
396+
const result = await this.chain.estiamteAndSendTransaction(
397+
transactionObject,
398+
{ from: address }
399+
);
409400
return { id: result.transactionHash, info: result };
410401
}
411402
}
@@ -543,6 +534,54 @@ export class EvmEntropyContract extends Storable {
543534
uri: Web3.utils.toAscii(info.uri),
544535
};
545536
}
537+
538+
generateUserRandomNumber() {
539+
const web3 = new Web3(this.chain.getRpcUrl());
540+
return web3.utils.randomHex(32);
541+
}
542+
543+
async requestRandomness(
544+
userRandomNumber: string,
545+
provider: string,
546+
senderPrivateKey: PrivateKey
547+
) {
548+
const web3 = new Web3(this.chain.getRpcUrl());
549+
const userCommitment = web3.utils.keccak256(userRandomNumber);
550+
const contract = new web3.eth.Contract(EXTENDED_ENTROPY_ABI, this.address);
551+
const fee = await contract.methods.getFee(provider).call();
552+
const { address } = web3.eth.accounts.wallet.add(senderPrivateKey);
553+
const useBlockHash = false;
554+
const transactionObject = contract.methods.request(
555+
provider,
556+
userCommitment,
557+
useBlockHash
558+
);
559+
return this.chain.estiamteAndSendTransaction(transactionObject, {
560+
from: address,
561+
value: fee,
562+
});
563+
}
564+
565+
async revealRandomness(
566+
userRevelation: string,
567+
providerRevelation: string,
568+
provider: string,
569+
sequenceNumber: string,
570+
senderPrivateKey: PrivateKey
571+
) {
572+
const web3 = new Web3(this.chain.getRpcUrl());
573+
const contract = new web3.eth.Contract(EXTENDED_ENTROPY_ABI, this.address);
574+
const { address } = web3.eth.accounts.wallet.add(senderPrivateKey);
575+
const transactionObject = contract.methods.reveal(
576+
provider,
577+
sequenceNumber,
578+
userRevelation,
579+
providerRevelation
580+
);
581+
return this.chain.estiamteAndSendTransaction(transactionObject, {
582+
from: address,
583+
});
584+
}
546585
}
547586

548587
export class EvmExecutorContract {
@@ -602,15 +641,10 @@ export class EvmExecutorContract {
602641
const transactionObject = executorContract.methods.execute(
603642
"0x" + vaa.toString("hex")
604643
);
605-
const gasEstimate = await transactionObject.estimateGas({
606-
from: address,
607-
gas: 100000000,
608-
});
609-
const result = await transactionObject.send({
610-
from: address,
611-
gas: gasEstimate * GAS_ESTIMATE_MULTIPLIER,
612-
gasPrice: await this.chain.getGasPrice(),
613-
});
644+
const result = await this.chain.estiamteAndSendTransaction(
645+
transactionObject,
646+
{ from: address }
647+
);
614648
return { id: result.transactionHash, info: result };
615649
}
616650
}
@@ -787,17 +821,10 @@ export class EvmPriceFeedContract extends PriceFeedContract {
787821
.call();
788822
const transactionObject =
789823
pythContract.methods.updatePriceFeeds(priceFeedUpdateData);
790-
const gasEstimate = await transactionObject.estimateGas({
791-
from: address,
792-
gas: 15000000,
793-
value: updateFee,
794-
});
795-
const result = await transactionObject.send({
796-
from: address,
797-
value: updateFee,
798-
gas: gasEstimate * GAS_ESTIMATE_MULTIPLIER,
799-
gasPrice: await this.chain.getGasPrice(),
800-
});
824+
const result = await this.chain.estiamteAndSendTransaction(
825+
transactionObject,
826+
{ from: address, value: updateFee }
827+
);
801828
return { id: result.transactionHash, info: result };
802829
}
803830

@@ -811,15 +838,10 @@ export class EvmPriceFeedContract extends PriceFeedContract {
811838
const transactionObject = pythContract.methods.executeGovernanceInstruction(
812839
"0x" + vaa.toString("hex")
813840
);
814-
const gasEstiamte = await transactionObject.estimateGas({
815-
from: address,
816-
gas: 15000000,
817-
});
818-
const result = await transactionObject.send({
819-
from: address,
820-
gas: gasEstiamte * GAS_ESTIMATE_MULTIPLIER,
821-
gasPrice: await this.chain.getGasPrice(),
822-
});
841+
const result = await this.chain.estiamteAndSendTransaction(
842+
transactionObject,
843+
{ from: address }
844+
);
823845
return { id: result.transactionHash, info: result };
824846
}
825847

0 commit comments

Comments
 (0)