@aztec/l1-artifacts 5.0.0-rc.2 → 5.0.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.
@@ -1,12 +1,17 @@
1
1
  #!/usr/bin/env node
2
- // forge_broadcast.js — Run `forge script --broadcast` safely on anvil.
2
+ // forge_broadcast.js — Run `forge script --broadcast` fast and reliably on anvil.
3
3
  //
4
- // Bug: anvil's auto-miner races with batched transactions. When a batch is sent,
5
- // anvil mines a block for the first tx but the rest arrive after the auto-mine
6
- // trigger fired, leaving them stranded or dropped. Temporarily switching to 1s
7
- // interval mining for the duration of the broadcast avoids both variants.
4
+ // anvil's automine mines each deploy transaction essentially instantly, which is what we want for
5
+ // speed. But a batched broadcast (forge's default sends many txs at once) can race the auto-miner:
6
+ // it mines a block on the first ready tx and may leave txs that arrived just after the trigger
7
+ // sitting in the pool, so forge waits forever for their receipts. We avoid the race without touching
8
+ // anvil's mining mode by broadcasting one tx at a time (`--batch-size 1`) only when anvil has
9
+ // automine ON: with a single tx in flight there is nothing for the auto-miner to strand.
8
10
  //
9
- // Only activates when anvil is in automine mode.
11
+ // When anvil is in interval (or no) mining mode the race does not exist — the miner drains the whole
12
+ // pool on each block — and serializing to one tx per block would stall the deploy for a full block
13
+ // interval per transaction, blowing past the broadcast timeout. There (and on real chains) we keep a
14
+ // larger batch size. A hard timeout guards against a broadcast hanging indefinitely.
10
15
  //
11
16
  // Usage: ./scripts/forge_broadcast.js <forge script args...>
12
17
  // (without --broadcast or --batch-size — added automatically)
@@ -36,38 +41,59 @@ function extractArg(args, flag) {
36
41
  const args = process.argv.slice(2);
37
42
  const rpcUrl = extractArg(args, "--rpc-url");
38
43
 
44
+ // Broadcast one tx at a time only on an automining anvil, where batching races the auto-miner.
45
+ // Interval-mining anvil and real chains keep a larger batch size: there is no race there, and
46
+ // serializing would stall the deploy one block interval per tx.
39
47
  const [isAnvil, isAutomine] = rpcUrl
40
48
  ? await Promise.all([
41
- rpc(rpcUrl, "web3_clientVersion").then((v) => v.toLowerCase().includes("anvil")).catch(() => false),
49
+ rpc(rpcUrl, "web3_clientVersion")
50
+ .then((v) => v.toLowerCase().includes("anvil"))
51
+ .catch(() => false),
42
52
  rpc(rpcUrl, "anvil_getAutomine").catch(() => false),
43
53
  ])
44
54
  : [false, false];
45
55
 
46
- if (isAnvil && isAutomine) {
47
- await rpc(rpcUrl, "evm_setAutomine", [false]);
48
- await rpc(rpcUrl, "evm_setIntervalMining", [1]);
49
- }
56
+ const batchSize = isAnvil && isAutomine ? "1" : "8";
57
+ const timeoutMs =
58
+ Number(process.env.FORGE_BROADCAST_TIMEOUT_MS) ||
59
+ (isAnvil ? 120_000 : 1_200_000);
50
60
 
51
- const proc = spawn("forge", ["script", ...args, "--broadcast", "--batch-size", "8"], {
52
- stdio: ["ignore", "pipe", "inherit"],
53
- });
61
+ const proc = spawn(
62
+ "forge",
63
+ ["script", ...args, "--broadcast", "--batch-size", batchSize],
64
+ {
65
+ stdio: ["ignore", "pipe", "inherit"],
66
+ },
67
+ );
54
68
 
55
69
  const stdout = [];
56
70
  proc.stdout.on("data", (chunk) => stdout.push(chunk));
57
71
 
72
+ let timedOut = false;
58
73
  const exitCode = await new Promise((resolve) => {
59
- proc.on("error", () => resolve(1));
60
- proc.on("close", (code) => resolve(code ?? 1));
74
+ const timeout = setTimeout(() => {
75
+ timedOut = true;
76
+ log(`Broadcast timed out after ${timeoutMs}ms; killing forge.`);
77
+ proc.kill("SIGTERM");
78
+ const sigkill = setTimeout(() => proc.kill("SIGKILL"), 5_000);
79
+ sigkill.unref?.();
80
+ }, timeoutMs);
81
+ timeout.unref?.();
82
+ proc.on("error", () => {
83
+ clearTimeout(timeout);
84
+ resolve(1);
85
+ });
86
+ proc.on("close", (code) => {
87
+ clearTimeout(timeout);
88
+ resolve(timedOut ? 1 : (code ?? 1));
89
+ });
61
90
  });
62
91
 
63
- if (isAnvil && isAutomine) {
64
- try {
65
- await rpc(rpcUrl, "evm_setIntervalMining", [0]);
66
- await rpc(rpcUrl, "evm_setAutomine", [true]);
67
- } catch {}
68
- }
69
-
70
- log(exitCode === 0 ? "Broadcast succeeded." : `Broadcast failed (exit ${exitCode}).`);
92
+ log(
93
+ exitCode === 0
94
+ ? "Broadcast succeeded."
95
+ : `Broadcast failed (exit ${exitCode}).`,
96
+ );
71
97
  const data = Buffer.concat(stdout);
72
98
  if (data.length > 0) writeSync(1, data);
73
99
  process.exit(exitCode);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aztec/l1-artifacts",
3
- "version": "5.0.0-rc.2",
3
+ "version": "5.0.0",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  "./*": "./dest/*.js",