@cofhe/hardhat-3-plugin 0.7.1 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +21 -0
- package/README.md +44 -7
- package/dist/chunk-6G2MCXNM.js +217 -0
- package/dist/{chunk-E7DR6EGV.js → chunk-FDCRLC5K.js} +43 -15
- package/dist/{chunk-IVRNGFNF.js → chunk-NYXXHYHW.js} +3 -3
- package/dist/{config-YK3LB5IH.js → config-VUCAYBHC.js} +1 -0
- package/dist/{hre-CYH6NXPG.js → hre-T3TPXWIY.js} +18 -2
- package/dist/index.d.ts +73 -2
- package/dist/index.js +27 -7
- package/dist/{set-log-ops-GVEQWMZP.js → set-log-ops-2OIBBSDL.js} +1 -1
- package/dist/test-gas-summary-WK6CULNO.js +19 -0
- package/package.json +3 -3
- package/src/config.ts +1 -0
- package/src/deploy.ts +48 -13
- package/src/gas.ts +340 -0
- package/src/hooks/hre.ts +23 -0
- package/src/index.ts +7 -1
- package/src/logging.ts +3 -3
- package/src/tasks/test-gas-summary.ts +22 -0
- package/src/type-extensions.ts +31 -0
- package/src/utils.ts +3 -3
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,26 @@
|
|
|
1
1
|
# @cofhe/hardhat-3-plugin
|
|
2
2
|
|
|
3
|
+
## 0.8.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 6f7a4c5: Resolve the Task Manager through the `CoFHEAddressBook` (`@fhenixprotocol/cofhe-contracts@1.0.0`). **Breaking:** `TASK_MANAGER_ADDRESS` is removed from `@cofhe/sdk`. Use `getTaskManagerAddress(publicClient)`, which reads `getTm(TASK_MANAGER_ID)` from the book at `COFHE_ADDRESS_BOOK_ADDRESS` (both exported) and caches the result per chain. If the chain has no book, or the id is unset, it throws `TASK_MANAGER_UNRESOLVED`. `verifyDecryptResult`, the ACL/ACP lookups and `useCofheEnabled` / `useCofheReadDecryptionResults` now resolve the Task Manager this way. `@cofhe/react` adds `useCofheTaskManagerAddress()`.
|
|
8
|
+
|
|
9
|
+
Mocks: a new `MockCoFHEAddressBook` is deployed at FHE.sol's `COFHE_ADDRESS_BOOK`, and `MockTaskManager` moves to `MOCKS_TASK_MANAGER_ADDRESS` (`0x…5000`) and is registered in the book. `MockACL` now stores its Task Manager (`setTaskManager` / `getTaskManagerAddress`) instead of reading a constant, so its `TASK_MANAGER_ADDRESS_()` getter is gone. All three plugins deploy and wire the book. Hardhat 2 exposes `hre.cofhe.mocks.getMockCoFHEAddressBook()`, Hardhat 3 exposes `conn.cofhe.mocks.MockCoFHEAddressBook`, and Foundry exposes `CofheTest.mockAddressBook`. Contracts must be built against `@fhenixprotocol/cofhe-contracts@1.0.0` or later (the hardhat plugin's peer range is now `>=1.0.0`). Each FHE op now makes one extra `getTm` call on the book, as it does on real networks, so expect slightly higher gas numbers.
|
|
10
|
+
|
|
11
|
+
### Patch Changes
|
|
12
|
+
|
|
13
|
+
- ccb7b68: Realistic gas reporting for mocks. Under Foundry, mock-only work is now excluded from gas metering by default (opt out with `mockTaskManager.setMockGasExcluded(false)`), so expect `forge snapshot` numbers to drop. Under Hardhat, mock transactions emit `MockGasConsumed` events (extra receipt logs), and the plugins add `getAdjustedGasUsed(receipt)` / `getAdjustedGasBreakdown(receipt)` plus an opt-in `cofhe.gasSummary` report.
|
|
14
|
+
- Updated dependencies [17ff23e]
|
|
15
|
+
- Updated dependencies [0fe40c3]
|
|
16
|
+
- Updated dependencies [6f7a4c5]
|
|
17
|
+
- Updated dependencies [552d118]
|
|
18
|
+
- Updated dependencies [22eebcc]
|
|
19
|
+
- Updated dependencies [ccb7b68]
|
|
20
|
+
- Updated dependencies [42fccae]
|
|
21
|
+
- @cofhe/sdk@0.8.0
|
|
22
|
+
- @cofhe/mock-contracts@0.8.0
|
|
23
|
+
|
|
3
24
|
## 0.7.1
|
|
4
25
|
|
|
5
26
|
### Patch Changes
|
package/README.md
CHANGED
|
@@ -36,18 +36,20 @@ export default defineConfig({
|
|
|
36
36
|
|
|
37
37
|
// Optional cofhe config (all values shown are their defaults)
|
|
38
38
|
cofhe: {
|
|
39
|
-
gasWarning:
|
|
40
|
-
|
|
39
|
+
gasWarning: false, // warn when mock ops report higher gas than real FHE
|
|
40
|
+
gasSummary: false, // print a per-method adjusted-gas summary after `hardhat test`
|
|
41
|
+
logMocks: false, // enable mock contract event logging
|
|
41
42
|
},
|
|
42
43
|
});
|
|
43
44
|
```
|
|
44
45
|
|
|
45
46
|
### Config options
|
|
46
47
|
|
|
47
|
-
| Option | Type | Default | Description
|
|
48
|
-
| ------------ | --------- | ------- |
|
|
49
|
-
| `gasWarning` | `boolean` | `
|
|
50
|
-
| `
|
|
48
|
+
| Option | Type | Default | Description |
|
|
49
|
+
| ------------ | --------- | ------- | ------------------------------------------------------------------------------------------------- |
|
|
50
|
+
| `gasWarning` | `boolean` | `false` | Print a warning after mock deployment reminding that mock gas costs differ from live FHE |
|
|
51
|
+
| `gasSummary` | `boolean` | `false` | Print a per-method gas summary after `hardhat test`, with mock-only overhead excluded (see below) |
|
|
52
|
+
| `logMocks` | `boolean` | `false` | Enable event-based logging inside mock contracts |
|
|
51
53
|
|
|
52
54
|
---
|
|
53
55
|
|
|
@@ -127,6 +129,40 @@ const client = await cofhe.createClientWithBatteries(walletClient);
|
|
|
127
129
|
|
|
128
130
|
---
|
|
129
131
|
|
|
132
|
+
### `cofhe.getAdjustedGasUsed(receipt)` / `cofhe.getAdjustedGasBreakdown(receipt)`
|
|
133
|
+
|
|
134
|
+
Mock transactions consume more gas than they would on a real CoFHE network, because the off-chain FHE work is replicated on-chain. The mock task manager measures that overhead and emits a `MockGasConsumed(uint256)` event per block of mock-only work, letting the plugin report corrected numbers:
|
|
135
|
+
|
|
136
|
+
```typescript
|
|
137
|
+
const hash = await myContract.write.doFheThings();
|
|
138
|
+
const receipt = await publicClient.waitForTransactionReceipt({ hash });
|
|
139
|
+
|
|
140
|
+
// Gas usage excluding mock overhead — an estimate of real-network cost.
|
|
141
|
+
const adjusted = cofhe.getAdjustedGasUsed(receipt);
|
|
142
|
+
|
|
143
|
+
// Or the full breakdown:
|
|
144
|
+
const { gasUsed, mockGas, adjustedGasUsed, mockGasEvents } = cofhe.getAdjustedGasBreakdown(receipt);
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
Both are pure functions of the receipt (no RPC calls). On a real network the receipt carries no mock events, so `adjustedGasUsed` equals `gasUsed` — the same code works everywhere.
|
|
148
|
+
|
|
149
|
+
With `cofhe: { gasSummary: true }` in the config, a per-method table (raw vs adjusted gas) is printed after `hardhat test`:
|
|
150
|
+
|
|
151
|
+
```
|
|
152
|
+
[COFHE-MOCKS] Gas summary — adjusted ≈ cost excluding mock-only overhead
|
|
153
|
+
┌──────────────────┬──────────────────────────┬───────┬─────────────────┬────────────────────┬───────────────┐
|
|
154
|
+
│ Contract │ Method │ Calls │ Avg gas (mocks) │ Avg gas (adjusted) │ Mock overhead │
|
|
155
|
+
├──────────────────┼──────────────────────────┼───────┼─────────────────┼────────────────────┼───────────────┤
|
|
156
|
+
│ MyFHEContract │ doFheThings() │ 9 │ 146,199 │ 109,595 │ 25% │
|
|
157
|
+
└──────────────────┴──────────────────────────┴───────┴─────────────────┴────────────────────┴───────────────┘
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
Note: `eth_estimateGas` is not adjusted — the mock work really does execute, so transactions still need the raw gas limit. Use a testnet for estimate-sensitive flows.
|
|
161
|
+
|
|
162
|
+
The summary table is collected per test worker at process exit and reconstructed from chain history: transactions rolled back by snapshots won't appear, and it is best-effort after forced exits (`process.exit`, Ctrl+C) — use `getAdjustedGasUsed(receipt)` inside tests for exact per-transaction numbers.
|
|
163
|
+
|
|
164
|
+
---
|
|
165
|
+
|
|
130
166
|
### `cofhe.mocks`
|
|
131
167
|
|
|
132
168
|
#### Contract descriptors
|
|
@@ -205,7 +241,8 @@ The plugin deploys these core contracts automatically on every `network.connect(
|
|
|
205
241
|
|
|
206
242
|
| Contract | Address | Description |
|
|
207
243
|
| ---------------------- | -------------------------------------------- | ------------------------------------------------------- |
|
|
208
|
-
| `
|
|
244
|
+
| `MockCoFHEAddressBook` | `0xC0F4e00E531a2B086492Ae3DCC1515038307196b` | Resolves the TaskManager for FHE.sol (`getTm(1)`) |
|
|
245
|
+
| `MockTaskManager` | `0x0000000000000000000000000000000000005000` | Coordinates FHE operations and ACL |
|
|
209
246
|
| `MockACL` | dynamic | Access Control List — address resolved from TaskManager |
|
|
210
247
|
| `MockZkVerifier` | `0x0000000000000000000000000000000000005001` | Verifies ZK proofs for encrypted inputs |
|
|
211
248
|
| `MockThresholdNetwork` | `0x0000000000000000000000000000000000005002` | Simulates the threshold decryption network |
|
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
// src/gas.ts
|
|
2
|
+
import chalk from "chalk";
|
|
3
|
+
import fs from "fs";
|
|
4
|
+
import path from "path";
|
|
5
|
+
import { parseAbiItem, toEventSelector, toFunctionSelector, toFunctionSignature } from "viem";
|
|
6
|
+
import { MOCKS_TASK_MANAGER_ADDRESS } from "@cofhe/sdk";
|
|
7
|
+
var MOCK_GAS_CONSUMED_EVENT = parseAbiItem("event MockGasConsumed(uint256 gas)");
|
|
8
|
+
var MOCK_GAS_CONSUMED_TOPIC = toEventSelector(MOCK_GAS_CONSUMED_EVENT);
|
|
9
|
+
var mock_getAdjustedGasBreakdown = (receipt) => {
|
|
10
|
+
let mockGas = 0n;
|
|
11
|
+
let mockGasEvents = 0;
|
|
12
|
+
for (const log of receipt.logs ?? []) {
|
|
13
|
+
if (log.address.toLowerCase() === MOCKS_TASK_MANAGER_ADDRESS.toLowerCase() && log.topics[0]?.toLowerCase() === MOCK_GAS_CONSUMED_TOPIC) {
|
|
14
|
+
mockGas += BigInt(log.data);
|
|
15
|
+
mockGasEvents += 1;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
const gasUsed = BigInt(receipt.gasUsed);
|
|
19
|
+
return { gasUsed, mockGas, adjustedGasUsed: mockGas > gasUsed ? 0n : gasUsed - mockGas, mockGasEvents };
|
|
20
|
+
};
|
|
21
|
+
var mock_getAdjustedGasUsed = (receipt) => mock_getAdjustedGasBreakdown(receipt).adjustedGasUsed;
|
|
22
|
+
var SUMMARY_DIR_NAME = "cofhe-gas-summary";
|
|
23
|
+
var registeredConnections = [];
|
|
24
|
+
var summaryDir;
|
|
25
|
+
var exitHookInstalled = false;
|
|
26
|
+
var exitHookRan = false;
|
|
27
|
+
var shortAddress = (address) => `${address.slice(0, 6)}..${address.slice(-4)}`;
|
|
28
|
+
var buildSelectorNameMap = async (artifacts) => {
|
|
29
|
+
const selectorNames = /* @__PURE__ */ new Map();
|
|
30
|
+
for (const fqn of await artifacts.getAllFullyQualifiedNames()) {
|
|
31
|
+
try {
|
|
32
|
+
const artifact = await artifacts.readArtifact(fqn);
|
|
33
|
+
for (const item of artifact.abi) {
|
|
34
|
+
if (item.type !== "function") continue;
|
|
35
|
+
const selector = toFunctionSelector(item);
|
|
36
|
+
if (!selectorNames.has(selector)) selectorNames.set(selector, toFunctionSignature(item));
|
|
37
|
+
}
|
|
38
|
+
} catch {
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
return selectorNames;
|
|
42
|
+
};
|
|
43
|
+
var buildAddressNameMap = async (publicClient, artifacts, addresses) => {
|
|
44
|
+
const codeToName = /* @__PURE__ */ new Map();
|
|
45
|
+
for (const fqn of await artifacts.getAllFullyQualifiedNames()) {
|
|
46
|
+
try {
|
|
47
|
+
const artifact = await artifacts.readArtifact(fqn);
|
|
48
|
+
if (artifact.deployedBytecode && artifact.deployedBytecode !== "0x") {
|
|
49
|
+
codeToName.set(artifact.deployedBytecode.toLowerCase(), artifact.contractName);
|
|
50
|
+
}
|
|
51
|
+
} catch {
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
const addressNames = /* @__PURE__ */ new Map();
|
|
55
|
+
for (const address of addresses) {
|
|
56
|
+
try {
|
|
57
|
+
const code = await publicClient.getCode({ address }) ?? "0x";
|
|
58
|
+
addressNames.set(address, codeToName.get(code.toLowerCase()) ?? shortAddress(address));
|
|
59
|
+
} catch {
|
|
60
|
+
addressNames.set(address, shortAddress(address));
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
return addressNames;
|
|
64
|
+
};
|
|
65
|
+
var collectMockGasRows = async (publicClient, artifacts, fromBlock = 0n) => {
|
|
66
|
+
let logs;
|
|
67
|
+
try {
|
|
68
|
+
logs = await publicClient.getLogs({
|
|
69
|
+
address: MOCKS_TASK_MANAGER_ADDRESS,
|
|
70
|
+
event: MOCK_GAS_CONSUMED_EVENT,
|
|
71
|
+
fromBlock,
|
|
72
|
+
toBlock: "latest"
|
|
73
|
+
});
|
|
74
|
+
} catch {
|
|
75
|
+
return [];
|
|
76
|
+
}
|
|
77
|
+
if (logs.length === 0) return [];
|
|
78
|
+
const mockGasPerTx = /* @__PURE__ */ new Map();
|
|
79
|
+
for (const log of logs) {
|
|
80
|
+
if (log.transactionHash === null) continue;
|
|
81
|
+
mockGasPerTx.set(log.transactionHash, (mockGasPerTx.get(log.transactionHash) ?? 0n) + (log.args.gas ?? 0n));
|
|
82
|
+
}
|
|
83
|
+
const aggregates = /* @__PURE__ */ new Map();
|
|
84
|
+
for (const [txHash, mockGas] of mockGasPerTx) {
|
|
85
|
+
try {
|
|
86
|
+
const receipt = await publicClient.getTransactionReceipt({ hash: txHash });
|
|
87
|
+
const tx = await publicClient.getTransaction({ hash: txHash });
|
|
88
|
+
const target = tx.to ?? receipt.contractAddress;
|
|
89
|
+
if (!target) continue;
|
|
90
|
+
const selector = tx.to ? (tx.input ?? "0x").slice(0, 10) : "(deployment)";
|
|
91
|
+
const key = `${target}:${selector}`;
|
|
92
|
+
const aggregate = aggregates.get(key) ?? { to: target, selector, calls: 0, totalGasUsed: 0n, totalMockGas: 0n };
|
|
93
|
+
aggregate.calls += 1;
|
|
94
|
+
aggregate.totalGasUsed += receipt.gasUsed;
|
|
95
|
+
aggregate.totalMockGas += mockGas;
|
|
96
|
+
aggregates.set(key, aggregate);
|
|
97
|
+
} catch {
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
if (aggregates.size === 0) return [];
|
|
101
|
+
const selectorNames = await buildSelectorNameMap(artifacts);
|
|
102
|
+
const addressNames = await buildAddressNameMap(publicClient, artifacts, [
|
|
103
|
+
...new Set([...aggregates.values()].map((a) => a.to))
|
|
104
|
+
]);
|
|
105
|
+
return [...aggregates.values()].map((a) => ({
|
|
106
|
+
contract: addressNames.get(a.to) ?? shortAddress(a.to),
|
|
107
|
+
method: selectorNames.get(a.selector) ?? a.selector,
|
|
108
|
+
calls: a.calls,
|
|
109
|
+
totalGasUsed: a.totalGasUsed.toString(),
|
|
110
|
+
totalMockGas: a.totalMockGas.toString()
|
|
111
|
+
}));
|
|
112
|
+
};
|
|
113
|
+
var registerGasSummaryConnection = (publicClient, artifacts, cacheDir, fromBlock) => {
|
|
114
|
+
registeredConnections.push({ publicClient, artifacts, fromBlock });
|
|
115
|
+
summaryDir = path.join(cacheDir, SUMMARY_DIR_NAME);
|
|
116
|
+
if (exitHookInstalled) return;
|
|
117
|
+
exitHookInstalled = true;
|
|
118
|
+
process.on("beforeExit", () => {
|
|
119
|
+
if (exitHookRan) return;
|
|
120
|
+
exitHookRan = true;
|
|
121
|
+
void (async () => {
|
|
122
|
+
const rows = [];
|
|
123
|
+
for (const { publicClient: client, artifacts: arts, fromBlock: fromBlock2 } of registeredConnections) {
|
|
124
|
+
try {
|
|
125
|
+
rows.push(...await collectMockGasRows(client, arts, fromBlock2));
|
|
126
|
+
} catch {
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
if (rows.length === 0 || summaryDir === void 0) return;
|
|
130
|
+
try {
|
|
131
|
+
fs.mkdirSync(summaryDir, { recursive: true });
|
|
132
|
+
const file = path.join(summaryDir, `rows-${process.pid}-${Date.now()}.json`);
|
|
133
|
+
fs.writeFileSync(file, JSON.stringify(rows), "utf8");
|
|
134
|
+
} catch {
|
|
135
|
+
}
|
|
136
|
+
})();
|
|
137
|
+
});
|
|
138
|
+
};
|
|
139
|
+
var cleanGasSummaryDir = (cacheDir) => {
|
|
140
|
+
try {
|
|
141
|
+
fs.rmSync(path.join(cacheDir, SUMMARY_DIR_NAME), { recursive: true, force: true });
|
|
142
|
+
} catch {
|
|
143
|
+
}
|
|
144
|
+
};
|
|
145
|
+
var printMockGasSummaryFromDir = (cacheDir) => {
|
|
146
|
+
const dir = path.join(cacheDir, SUMMARY_DIR_NAME);
|
|
147
|
+
let files;
|
|
148
|
+
try {
|
|
149
|
+
files = fs.readdirSync(dir).filter((f) => f.endsWith(".json"));
|
|
150
|
+
} catch {
|
|
151
|
+
return;
|
|
152
|
+
}
|
|
153
|
+
const merged = /* @__PURE__ */ new Map();
|
|
154
|
+
for (const file of files) {
|
|
155
|
+
try {
|
|
156
|
+
const rows2 = JSON.parse(fs.readFileSync(path.join(dir, file), "utf8"));
|
|
157
|
+
for (const r of rows2) {
|
|
158
|
+
const key = `${r.contract}:${r.method}`;
|
|
159
|
+
const row = merged.get(key) ?? { contract: r.contract, method: r.method, calls: 0, gasUsed: 0n, mockGas: 0n };
|
|
160
|
+
row.calls += r.calls;
|
|
161
|
+
row.gasUsed += BigInt(r.totalGasUsed);
|
|
162
|
+
row.mockGas += BigInt(r.totalMockGas);
|
|
163
|
+
merged.set(key, row);
|
|
164
|
+
}
|
|
165
|
+
} catch {
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
cleanGasSummaryDir(cacheDir);
|
|
169
|
+
if (merged.size === 0) return;
|
|
170
|
+
const rows = [...merged.values()].map((r) => {
|
|
171
|
+
const avgGasUsed = r.gasUsed / BigInt(r.calls);
|
|
172
|
+
const avgMockGas = r.mockGas / BigInt(r.calls);
|
|
173
|
+
return {
|
|
174
|
+
contract: r.contract,
|
|
175
|
+
method: r.method,
|
|
176
|
+
calls: r.calls,
|
|
177
|
+
avgGasUsed,
|
|
178
|
+
avgAdjusted: avgMockGas > avgGasUsed ? 0n : avgGasUsed - avgMockGas,
|
|
179
|
+
overheadPct: avgGasUsed === 0n ? 0 : Math.min(100, Number(avgMockGas * 100n / avgGasUsed))
|
|
180
|
+
};
|
|
181
|
+
}).sort((a, b) => a.contract.localeCompare(b.contract) || a.method.localeCompare(b.method));
|
|
182
|
+
const headers = ["Contract", "Method", "Calls", "Avg gas (mocks)", "Avg gas (adjusted)", "Mock overhead"];
|
|
183
|
+
const cells = rows.map((r) => [
|
|
184
|
+
r.contract,
|
|
185
|
+
r.method,
|
|
186
|
+
String(r.calls),
|
|
187
|
+
r.avgGasUsed.toLocaleString(),
|
|
188
|
+
r.avgAdjusted.toLocaleString(),
|
|
189
|
+
`${r.overheadPct}%`
|
|
190
|
+
]);
|
|
191
|
+
const widths = headers.map((h, i) => Math.max(h.length, ...cells.map((row) => row[i].length)));
|
|
192
|
+
const line = (row) => `\u2502 ${row.map((cell, i) => cell.padEnd(widths[i])).join(" \u2502 ")} \u2502`;
|
|
193
|
+
const divider = (l, m, r) => `${l}${widths.map((w) => "\u2500".repeat(w + 2)).join(m)}${r}`;
|
|
194
|
+
console.log("");
|
|
195
|
+
console.log(chalk.bold("[COFHE-MOCKS] Gas summary") + chalk.dim(" \u2014 adjusted \u2248 cost excluding mock-only overhead"));
|
|
196
|
+
console.log(divider("\u250C", "\u252C", "\u2510"));
|
|
197
|
+
console.log(line(headers));
|
|
198
|
+
console.log(divider("\u251C", "\u253C", "\u2524"));
|
|
199
|
+
for (const row of cells) console.log(line(row));
|
|
200
|
+
console.log(divider("\u2514", "\u2534", "\u2518"));
|
|
201
|
+
console.log(
|
|
202
|
+
chalk.dim(
|
|
203
|
+
"Raw numbers include on-chain replication of off-chain CoFHE work; adjusted numbers estimate real-network cost. estimateGas remains unadjusted."
|
|
204
|
+
)
|
|
205
|
+
);
|
|
206
|
+
};
|
|
207
|
+
|
|
208
|
+
export {
|
|
209
|
+
MOCK_GAS_CONSUMED_EVENT,
|
|
210
|
+
MOCK_GAS_CONSUMED_TOPIC,
|
|
211
|
+
mock_getAdjustedGasBreakdown,
|
|
212
|
+
mock_getAdjustedGasUsed,
|
|
213
|
+
collectMockGasRows,
|
|
214
|
+
registerGasSummaryConnection,
|
|
215
|
+
cleanGasSummaryDir,
|
|
216
|
+
printMockGasSummaryFromDir
|
|
217
|
+
};
|
|
@@ -2,9 +2,16 @@
|
|
|
2
2
|
import { createTestClient, custom } from "viem";
|
|
3
3
|
import chalk from "chalk";
|
|
4
4
|
import { privateKeyToAccount } from "viem/accounts";
|
|
5
|
-
import { MockACLArtifact, MockTaskManagerArtifact, MockThresholdNetworkArtifact } from "@cofhe/mock-contracts";
|
|
6
5
|
import {
|
|
7
|
-
|
|
6
|
+
MockACLArtifact,
|
|
7
|
+
MockCoFHEAddressBookArtifact,
|
|
8
|
+
MockTaskManagerArtifact,
|
|
9
|
+
MockThresholdNetworkArtifact
|
|
10
|
+
} from "@cofhe/mock-contracts";
|
|
11
|
+
import {
|
|
12
|
+
COFHE_ADDRESS_BOOK_ADDRESS,
|
|
13
|
+
TASK_MANAGER_ID,
|
|
14
|
+
MOCKS_TASK_MANAGER_ADDRESS,
|
|
8
15
|
MOCKS_ZK_VERIFIER_ADDRESS,
|
|
9
16
|
MOCKS_ZK_VERIFIER_SIGNER_ADDRESS,
|
|
10
17
|
MOCKS_ZK_VERIFIER_SIGNER_PRIVATE_KEY,
|
|
@@ -28,11 +35,13 @@ async function deployMocks(ctx, options = {}) {
|
|
|
28
35
|
return {};
|
|
29
36
|
}
|
|
30
37
|
log("vv", chalk.bold("cofhe-hardhat-3-plugin :: deploy mocks"), 0);
|
|
31
|
-
await deployFixed(ctx.publicClient, "
|
|
32
|
-
logDeployment("
|
|
38
|
+
await deployFixed(ctx.publicClient, "MockCoFHEAddressBook", COFHE_ADDRESS_BOOK_ADDRESS, ctx.artifacts);
|
|
39
|
+
logDeployment("MockCoFHEAddressBook", COFHE_ADDRESS_BOOK_ADDRESS);
|
|
40
|
+
await deployFixed(ctx.publicClient, "MockTaskManager", MOCKS_TASK_MANAGER_ADDRESS, ctx.artifacts);
|
|
41
|
+
logDeployment("MockTaskManager", MOCKS_TASK_MANAGER_ADDRESS);
|
|
33
42
|
const [account] = await ctx.walletClient.getAddresses();
|
|
34
43
|
await ctx.walletClient.writeContract({
|
|
35
|
-
address:
|
|
44
|
+
address: MOCKS_TASK_MANAGER_ADDRESS,
|
|
36
45
|
abi: MockTaskManagerArtifact.abi,
|
|
37
46
|
functionName: "initialize",
|
|
38
47
|
args: [account],
|
|
@@ -40,7 +49,16 @@ async function deployMocks(ctx, options = {}) {
|
|
|
40
49
|
chain: null
|
|
41
50
|
});
|
|
42
51
|
await ctx.walletClient.writeContract({
|
|
43
|
-
address:
|
|
52
|
+
address: COFHE_ADDRESS_BOOK_ADDRESS,
|
|
53
|
+
abi: MockCoFHEAddressBookArtifact.abi,
|
|
54
|
+
functionName: "setTm",
|
|
55
|
+
args: [TASK_MANAGER_ID, MOCKS_TASK_MANAGER_ADDRESS],
|
|
56
|
+
account,
|
|
57
|
+
chain: null
|
|
58
|
+
});
|
|
59
|
+
log("vv", "TaskManager registered in CoFHEAddressBook", 2);
|
|
60
|
+
await ctx.walletClient.writeContract({
|
|
61
|
+
address: MOCKS_TASK_MANAGER_ADDRESS,
|
|
44
62
|
abi: MockTaskManagerArtifact.abi,
|
|
45
63
|
functionName: "setSecurityZones",
|
|
46
64
|
args: [0, 1],
|
|
@@ -50,7 +68,7 @@ async function deployMocks(ctx, options = {}) {
|
|
|
50
68
|
const aclAddress = await deployVariable(ctx, "MockACL", []);
|
|
51
69
|
logDeployment("MockACL", aclAddress);
|
|
52
70
|
await ctx.walletClient.writeContract({
|
|
53
|
-
address:
|
|
71
|
+
address: MOCKS_TASK_MANAGER_ADDRESS,
|
|
54
72
|
abi: MockTaskManagerArtifact.abi,
|
|
55
73
|
functionName: "setACLContract",
|
|
56
74
|
args: [aclAddress],
|
|
@@ -58,6 +76,15 @@ async function deployMocks(ctx, options = {}) {
|
|
|
58
76
|
chain: null
|
|
59
77
|
});
|
|
60
78
|
log("vv", "ACL address set in TaskManager", 2);
|
|
79
|
+
await ctx.walletClient.writeContract({
|
|
80
|
+
address: aclAddress,
|
|
81
|
+
abi: MockACLArtifact.abi,
|
|
82
|
+
functionName: "setTaskManager",
|
|
83
|
+
args: [MOCKS_TASK_MANAGER_ADDRESS],
|
|
84
|
+
account,
|
|
85
|
+
chain: null
|
|
86
|
+
});
|
|
87
|
+
log("vv", "TaskManager address set in ACL", 2);
|
|
61
88
|
const acpRevokerAddress = await deployVariable(ctx, "ACPTimestampRevoker", []);
|
|
62
89
|
logDeployment("ACPTimestampRevoker", acpRevokerAddress);
|
|
63
90
|
await ctx.walletClient.writeContract({
|
|
@@ -82,7 +109,7 @@ async function deployMocks(ctx, options = {}) {
|
|
|
82
109
|
log("vv", "Share registry set in ACL", 2);
|
|
83
110
|
const verifierSigner = privateKeyToAccount(MOCKS_ZK_VERIFIER_SIGNER_PRIVATE_KEY);
|
|
84
111
|
await ctx.walletClient.writeContract({
|
|
85
|
-
address:
|
|
112
|
+
address: MOCKS_TASK_MANAGER_ADDRESS,
|
|
86
113
|
abi: MockTaskManagerArtifact.abi,
|
|
87
114
|
functionName: "setVerifierSigner",
|
|
88
115
|
args: [verifierSigner.address],
|
|
@@ -92,7 +119,7 @@ async function deployMocks(ctx, options = {}) {
|
|
|
92
119
|
log("vv", "Verifier signer set", 2);
|
|
93
120
|
const decryptSigner = privateKeyToAccount(MOCKS_DECRYPT_RESULT_SIGNER_PRIVATE_KEY);
|
|
94
121
|
await ctx.walletClient.writeContract({
|
|
95
|
-
address:
|
|
122
|
+
address: MOCKS_TASK_MANAGER_ADDRESS,
|
|
96
123
|
abi: MockTaskManagerArtifact.abi,
|
|
97
124
|
functionName: "setDecryptResultSigner",
|
|
98
125
|
args: [decryptSigner.address],
|
|
@@ -120,7 +147,7 @@ async function deployMocks(ctx, options = {}) {
|
|
|
120
147
|
address: MockThresholdNetworkArtifact.fixedAddress,
|
|
121
148
|
abi: MockThresholdNetworkArtifact.abi,
|
|
122
149
|
functionName: "initialize",
|
|
123
|
-
args: [
|
|
150
|
+
args: [MOCKS_TASK_MANAGER_ADDRESS, aclAddress],
|
|
124
151
|
account,
|
|
125
152
|
chain: null
|
|
126
153
|
});
|
|
@@ -128,13 +155,14 @@ async function deployMocks(ctx, options = {}) {
|
|
|
128
155
|
if (gasWarning) {
|
|
129
156
|
logEmpty("v");
|
|
130
157
|
logWarning(
|
|
131
|
-
"When using mocks, FHE operations
|
|
158
|
+
"When using mocks, FHE operations consume extra gas replicating off-chain CoFHE work on-chain. Use conn.cofhe.getAdjustedGasUsed(receipt) or set 'cofhe.gasSummary: true' to see gas numbers with that overhead excluded.\n(Disable this warning by setting 'cofhe.gasWarning: false' in your Hardhat config)",
|
|
132
159
|
0
|
|
133
160
|
);
|
|
134
161
|
}
|
|
135
162
|
logEmpty("v");
|
|
136
163
|
return {
|
|
137
|
-
|
|
164
|
+
MockCoFHEAddressBook: COFHE_ADDRESS_BOOK_ADDRESS,
|
|
165
|
+
MockTaskManager: MOCKS_TASK_MANAGER_ADDRESS,
|
|
138
166
|
MockACL: aclAddress,
|
|
139
167
|
ACPTimestampRevoker: acpRevokerAddress,
|
|
140
168
|
ACPShareRegistry: acpShareRegistryAddress,
|
|
@@ -186,7 +214,7 @@ var logDeployment = (contractName, address) => {
|
|
|
186
214
|
};
|
|
187
215
|
|
|
188
216
|
// src/utils.ts
|
|
189
|
-
import {
|
|
217
|
+
import { MOCKS_TASK_MANAGER_ADDRESS as MOCKS_TASK_MANAGER_ADDRESS2, MOCKS_ZK_VERIFIER_ADDRESS as MOCKS_ZK_VERIFIER_ADDRESS2 } from "@cofhe/sdk";
|
|
190
218
|
import path from "path";
|
|
191
219
|
import fs from "fs";
|
|
192
220
|
import { createRequire } from "module";
|
|
@@ -216,7 +244,7 @@ async function mock_getPlaintext(publicClient, ctHash) {
|
|
|
216
244
|
return void 0;
|
|
217
245
|
}
|
|
218
246
|
return publicClient.readContract({
|
|
219
|
-
address:
|
|
247
|
+
address: MOCKS_TASK_MANAGER_ADDRESS2,
|
|
220
248
|
abi: [
|
|
221
249
|
{
|
|
222
250
|
name: "mockStorage",
|
|
@@ -236,7 +264,7 @@ async function mock_expectPlaintext(publicClient, ctHash, expectedValue) {
|
|
|
236
264
|
return;
|
|
237
265
|
}
|
|
238
266
|
const exists = await publicClient.readContract({
|
|
239
|
-
address:
|
|
267
|
+
address: MOCKS_TASK_MANAGER_ADDRESS2,
|
|
240
268
|
abi: [
|
|
241
269
|
{
|
|
242
270
|
name: "inMockStorage",
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
// src/logging.ts
|
|
2
2
|
import chalk from "chalk";
|
|
3
3
|
import { MockTaskManagerArtifact } from "@cofhe/mock-contracts";
|
|
4
|
-
import {
|
|
4
|
+
import { MOCKS_TASK_MANAGER_ADDRESS } from "@cofhe/sdk";
|
|
5
5
|
async function getLoggingEnabled(publicClient) {
|
|
6
6
|
return publicClient.readContract({
|
|
7
|
-
address:
|
|
7
|
+
address: MOCKS_TASK_MANAGER_ADDRESS,
|
|
8
8
|
abi: MockTaskManagerArtifact.abi,
|
|
9
9
|
functionName: "logOps",
|
|
10
10
|
args: []
|
|
@@ -13,7 +13,7 @@ async function getLoggingEnabled(publicClient) {
|
|
|
13
13
|
async function setLoggingEnabled(publicClient, walletClient, enabled) {
|
|
14
14
|
const [account] = await walletClient.getAddresses();
|
|
15
15
|
const hash = await walletClient.writeContract({
|
|
16
|
-
address:
|
|
16
|
+
address: MOCKS_TASK_MANAGER_ADDRESS,
|
|
17
17
|
abi: MockTaskManagerArtifact.abi,
|
|
18
18
|
functionName: "setLogOps",
|
|
19
19
|
args: [enabled],
|
|
@@ -46,6 +46,7 @@ function resolvePluginConfig(userConfig, resolvedConfig) {
|
|
|
46
46
|
resolvedConfig.cofhe = {
|
|
47
47
|
logMocks: userConfig.cofhe?.logMocks ?? false,
|
|
48
48
|
gasWarning: userConfig.cofhe?.gasWarning ?? false,
|
|
49
|
+
gasSummary: userConfig.cofhe?.gasSummary ?? false,
|
|
49
50
|
mocksDeployVerbosity: userConfig.cofhe?.mocksDeployVerbosity ?? "v"
|
|
50
51
|
};
|
|
51
52
|
}
|
|
@@ -3,17 +3,23 @@ import {
|
|
|
3
3
|
getMockContractsNpmPaths,
|
|
4
4
|
mock_expectPlaintext,
|
|
5
5
|
mock_getPlaintext
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-FDCRLC5K.js";
|
|
7
7
|
import {
|
|
8
8
|
mock_setLoggingEnabled,
|
|
9
9
|
mock_withLogs
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-NYXXHYHW.js";
|
|
11
|
+
import {
|
|
12
|
+
mock_getAdjustedGasBreakdown,
|
|
13
|
+
mock_getAdjustedGasUsed,
|
|
14
|
+
registerGasSummaryConnection
|
|
15
|
+
} from "./chunk-6G2MCXNM.js";
|
|
11
16
|
|
|
12
17
|
// src/hooks/hre.ts
|
|
13
18
|
import { FileBuildResultType } from "hardhat/types/solidity";
|
|
14
19
|
import { createPublicClient, createWalletClient, custom } from "viem";
|
|
15
20
|
import { privateKeyToAccount } from "viem/accounts";
|
|
16
21
|
import {
|
|
22
|
+
MockCoFHEAddressBookArtifact,
|
|
17
23
|
MockTaskManagerArtifact,
|
|
18
24
|
MockACLArtifact,
|
|
19
25
|
MockZkVerifierArtifact,
|
|
@@ -44,6 +50,8 @@ function createCofheConnection(publicClient, walletClient, transport, artifacts,
|
|
|
44
50
|
createClient(config) {
|
|
45
51
|
return createCofheClient(config);
|
|
46
52
|
},
|
|
53
|
+
getAdjustedGasUsed: mock_getAdjustedGasUsed,
|
|
54
|
+
getAdjustedGasBreakdown: mock_getAdjustedGasBreakdown,
|
|
47
55
|
async createClientWithBatteries(signerWalletClient) {
|
|
48
56
|
let signerClient;
|
|
49
57
|
let address;
|
|
@@ -85,6 +93,10 @@ function createCofheConnection(publicClient, walletClient, transport, artifacts,
|
|
|
85
93
|
async expectPlaintext(ctHash, expectedValue) {
|
|
86
94
|
await mock_expectPlaintext(publicClient, ctHash, expectedValue);
|
|
87
95
|
},
|
|
96
|
+
MockCoFHEAddressBook: {
|
|
97
|
+
address: deployedMockContracts.MockCoFHEAddressBook,
|
|
98
|
+
abi: MockCoFHEAddressBookArtifact.abi
|
|
99
|
+
},
|
|
88
100
|
MockTaskManager: { address: deployedMockContracts.MockTaskManager, abi: MockTaskManagerArtifact.abi },
|
|
89
101
|
MockACL: { address: deployedMockContracts.MockACL, abi: MockACLArtifact.abi },
|
|
90
102
|
MockZkVerifier: { address: deployedMockContracts.MockZkVerifier, abi: MockZkVerifierArtifact.abi },
|
|
@@ -136,6 +148,10 @@ var hreHooks = {
|
|
|
136
148
|
mocksDeployVerbosity: hre.config.cofhe.mocksDeployVerbosity
|
|
137
149
|
}
|
|
138
150
|
);
|
|
151
|
+
if (hre.config.cofhe.gasSummary && deployedMockContracts.MockTaskManager !== void 0) {
|
|
152
|
+
const fromBlock = await publicClient.getBlockNumber();
|
|
153
|
+
registerGasSummaryConnection(publicClient, hre.artifacts, hre.config.paths.cache, fromBlock);
|
|
154
|
+
}
|
|
139
155
|
conn.cofhe = createCofheConnection(
|
|
140
156
|
publicClient,
|
|
141
157
|
walletClient,
|