@aztec/stdlib 6.0.0-nightly.20260810 → 6.0.0-nightly.20260821
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/dest/abi/abi.d.ts +4 -3
- package/dest/abi/abi.d.ts.map +1 -1
- package/dest/abi/abi.js +5 -1
- package/dest/abi/contract_artifact.d.ts +7 -2
- package/dest/abi/contract_artifact.d.ts.map +1 -1
- package/dest/abi/contract_artifact.js +18 -19
- package/dest/avm/avm.d.ts +3 -2
- package/dest/avm/avm.d.ts.map +1 -1
- package/dest/avm/avm.js +9 -3
- package/dest/avm/avm_proving_request.d.ts +70 -70
- package/dest/block/l2_block.d.ts +1 -2
- package/dest/block/l2_block.d.ts.map +1 -1
- package/dest/block/l2_block.js +2 -3
- package/dest/block/l2_block_source.d.ts +3 -6
- package/dest/block/l2_block_source.d.ts.map +1 -1
- package/dest/block/l2_block_stream/event_driven_l2_block_stream.d.ts +11 -20
- package/dest/block/l2_block_stream/event_driven_l2_block_stream.d.ts.map +1 -1
- package/dest/block/l2_block_stream/event_driven_l2_block_stream.js +12 -116
- package/dest/checkpoint/checkpoint_data.d.ts +14 -2
- package/dest/checkpoint/checkpoint_data.d.ts.map +1 -1
- package/dest/checkpoint/checkpoint_data.js +2 -1
- package/dest/checkpoint/index.d.ts +2 -1
- package/dest/checkpoint/index.d.ts.map +1 -1
- package/dest/checkpoint/index.js +1 -0
- package/dest/checkpoint/previous_checkpoint_inbox_rolling_hash.d.ts +21 -0
- package/dest/checkpoint/previous_checkpoint_inbox_rolling_hash.d.ts.map +1 -0
- package/dest/checkpoint/previous_checkpoint_inbox_rolling_hash.js +34 -0
- package/dest/checkpoint/simulation_overrides.d.ts +2 -2
- package/dest/checkpoint/simulation_overrides.d.ts.map +1 -1
- package/dest/checkpoint/simulation_overrides.js +11 -8
- package/dest/config/network-consensus-config.d.ts +4 -3
- package/dest/config/network-consensus-config.d.ts.map +1 -1
- package/dest/config/network-consensus-config.js +9 -4
- package/dest/config/node-rpc-config.d.ts +13 -1
- package/dest/config/node-rpc-config.d.ts.map +1 -1
- package/dest/config/node-rpc-config.js +34 -1
- package/dest/deserialization/index.d.ts +17 -17
- package/dest/deserialization/index.d.ts.map +1 -1
- package/dest/deserialization/index.js +18 -18
- package/dest/gas/gas_settings.d.ts +17 -5
- package/dest/gas/gas_settings.d.ts.map +1 -1
- package/dest/gas/gas_settings.js +4 -4
- package/dest/gas/tx_gas_limits.d.ts +3 -4
- package/dest/gas/tx_gas_limits.d.ts.map +1 -1
- package/dest/gas/tx_gas_limits.js +4 -5
- package/dest/interfaces/archiver.d.ts +2 -2
- package/dest/interfaces/archiver.d.ts.map +1 -1
- package/dest/interfaces/archiver.js +32 -5
- package/dest/interfaces/aztec-node-admin.d.ts +2 -1
- package/dest/interfaces/aztec-node-admin.d.ts.map +1 -1
- package/dest/interfaces/aztec-node.d.ts +22 -4
- package/dest/interfaces/aztec-node.d.ts.map +1 -1
- package/dest/interfaces/aztec-node.js +11 -9
- package/dest/interfaces/block-builder.d.ts +11 -2
- package/dest/interfaces/block-builder.d.ts.map +1 -1
- package/dest/interfaces/configs.d.ts +7 -1
- package/dest/interfaces/configs.d.ts.map +1 -1
- package/dest/interfaces/configs.js +2 -1
- package/dest/interfaces/p2p.d.ts +18 -1
- package/dest/interfaces/p2p.d.ts.map +1 -1
- package/dest/interfaces/p2p.js +8 -0
- package/dest/interfaces/proving-job.d.ts +17 -42
- package/dest/interfaces/proving-job.d.ts.map +1 -1
- package/dest/interfaces/proving-job.js +16 -47
- package/dest/interfaces/server_circuit_prover.d.ts +8 -15
- package/dest/interfaces/server_circuit_prover.d.ts.map +1 -1
- package/dest/interfaces/validator.d.ts +7 -7
- package/dest/interfaces/validator.d.ts.map +1 -1
- package/dest/messaging/append_l1_to_l2_messages.d.ts +5 -5
- package/dest/messaging/append_l1_to_l2_messages.d.ts.map +1 -1
- package/dest/messaging/append_l1_to_l2_messages.js +4 -8
- package/dest/messaging/inbox_bucket.d.ts +77 -0
- package/dest/messaging/inbox_bucket.d.ts.map +1 -0
- package/dest/messaging/inbox_bucket.js +73 -0
- package/dest/messaging/inbox_consumption.d.ts +55 -0
- package/dest/messaging/inbox_consumption.d.ts.map +1 -0
- package/dest/messaging/inbox_consumption.js +53 -0
- package/dest/messaging/inbox_rolling_hash.d.ts +16 -0
- package/dest/messaging/inbox_rolling_hash.d.ts.map +1 -0
- package/dest/messaging/inbox_rolling_hash.js +23 -0
- package/dest/messaging/index.d.ts +6 -3
- package/dest/messaging/index.d.ts.map +1 -1
- package/dest/messaging/index.js +5 -2
- package/dest/messaging/l1_to_l2_message_bundle.d.ts +31 -0
- package/dest/messaging/l1_to_l2_message_bundle.d.ts.map +1 -0
- package/dest/messaging/l1_to_l2_message_bundle.js +51 -0
- package/dest/messaging/l1_to_l2_message_source.d.ts +44 -10
- package/dest/messaging/l1_to_l2_message_source.d.ts.map +1 -1
- package/dest/messaging/l1_to_l2_message_sponge.d.ts +40 -0
- package/dest/messaging/l1_to_l2_message_sponge.d.ts.map +1 -0
- package/dest/messaging/l1_to_l2_message_sponge.js +56 -0
- package/dest/noir/index.d.ts +3 -3
- package/dest/noir/index.d.ts.map +1 -1
- package/dest/p2p/block_proposal.d.ts +24 -9
- package/dest/p2p/block_proposal.d.ts.map +1 -1
- package/dest/p2p/block_proposal.js +42 -20
- package/dest/p2p/checkpoint_attestation.d.ts +1 -1
- package/dest/p2p/checkpoint_proposal.d.ts +13 -3
- package/dest/p2p/checkpoint_proposal.d.ts.map +1 -1
- package/dest/p2p/checkpoint_proposal.js +26 -8
- package/dest/p2p/consensus_payload.d.ts +1 -1
- package/dest/p2p/index.d.ts +2 -1
- package/dest/p2p/index.d.ts.map +1 -1
- package/dest/p2p/index.js +1 -0
- package/dest/p2p/validated_proposal.d.ts +35 -0
- package/dest/p2p/validated_proposal.d.ts.map +1 -0
- package/dest/p2p/validated_proposal.js +17 -0
- package/dest/p2p/wire_compat_fixtures.d.ts +7 -0
- package/dest/p2p/wire_compat_fixtures.d.ts.map +1 -0
- package/dest/p2p/wire_compat_fixtures.js +14 -0
- package/dest/parity/inbox_parity_private_inputs.d.ts +61 -0
- package/dest/parity/inbox_parity_private_inputs.d.ts.map +1 -0
- package/dest/parity/inbox_parity_private_inputs.js +79 -0
- package/dest/parity/index.d.ts +2 -3
- package/dest/parity/index.d.ts.map +1 -1
- package/dest/parity/index.js +1 -2
- package/dest/parity/parity_public_inputs.d.ts +15 -14
- package/dest/parity/parity_public_inputs.d.ts.map +1 -1
- package/dest/parity/parity_public_inputs.js +13 -15
- package/dest/proofs/proving_request_type.d.ts +11 -14
- package/dest/proofs/proving_request_type.d.ts.map +1 -1
- package/dest/proofs/proving_request_type.js +10 -13
- package/dest/rollup/block_constant_data.d.ts +8 -8
- package/dest/rollup/block_constant_data.js +4 -4
- package/dest/rollup/block_rollup_public_inputs.d.ts +18 -6
- package/dest/rollup/block_rollup_public_inputs.d.ts.map +1 -1
- package/dest/rollup/block_rollup_public_inputs.js +14 -7
- package/dest/rollup/block_root_rollup_private_inputs.d.ts +109 -113
- package/dest/rollup/block_root_rollup_private_inputs.d.ts.map +1 -1
- package/dest/rollup/block_root_rollup_private_inputs.js +79 -130
- package/dest/rollup/checkpoint_header.d.ts +14 -6
- package/dest/rollup/checkpoint_header.d.ts.map +1 -1
- package/dest/rollup/checkpoint_header.js +18 -14
- package/dest/rollup/checkpoint_rollup_public_inputs.d.ts +22 -2
- package/dest/rollup/checkpoint_rollup_public_inputs.d.ts.map +1 -1
- package/dest/rollup/checkpoint_rollup_public_inputs.js +14 -3
- package/dest/rollup/checkpoint_root_rollup_private_inputs.d.ts +27 -6
- package/dest/rollup/checkpoint_root_rollup_private_inputs.d.ts.map +1 -1
- package/dest/rollup/checkpoint_root_rollup_private_inputs.js +17 -4
- package/dest/rollup/root_rollup_public_inputs.d.ts +10 -2
- package/dest/rollup/root_rollup_public_inputs.d.ts.map +1 -1
- package/dest/rollup/root_rollup_public_inputs.js +9 -3
- package/dest/stats/stats.d.ts +2 -2
- package/dest/stats/stats.d.ts.map +1 -1
- package/dest/tests/factories.d.ts +7 -7
- package/dest/tests/factories.d.ts.map +1 -1
- package/dest/tests/factories.js +26 -22
- package/dest/tests/fixtures.d.ts +1 -1
- package/dest/tests/fixtures.d.ts.map +1 -1
- package/dest/tests/fixtures.js +2 -0
- package/dest/tests/mocks.d.ts +4 -2
- package/dest/tests/mocks.d.ts.map +1 -1
- package/dest/tests/mocks.js +4 -7
- package/dest/tx/state_reference.d.ts +5 -2
- package/dest/tx/state_reference.d.ts.map +1 -1
- package/dest/tx/state_reference.js +5 -5
- package/package.json +8 -8
- package/src/abi/abi.ts +7 -2
- package/src/abi/contract_artifact.ts +20 -23
- package/src/avm/avm.ts +11 -1
- package/src/block/l2_block.ts +2 -3
- package/src/block/l2_block_source.ts +2 -5
- package/src/block/l2_block_stream/event_driven_l2_block_stream.ts +17 -143
- package/src/checkpoint/checkpoint_data.ts +14 -1
- package/src/checkpoint/index.ts +1 -0
- package/src/checkpoint/previous_checkpoint_inbox_rolling_hash.ts +46 -0
- package/src/checkpoint/simulation_overrides.ts +11 -8
- package/src/config/network-consensus-config.ts +17 -4
- package/src/config/node-rpc-config.ts +51 -1
- package/src/deserialization/index.ts +18 -18
- package/src/gas/README.md +4 -3
- package/src/gas/gas_settings.ts +7 -3
- package/src/gas/tx_gas_limits.ts +4 -12
- package/src/interfaces/archiver.ts +19 -2
- package/src/interfaces/aztec-node.ts +33 -12
- package/src/interfaces/block-builder.ts +10 -1
- package/src/interfaces/configs.ts +6 -0
- package/src/interfaces/p2p.ts +21 -0
- package/src/interfaces/proving-job.ts +19 -70
- package/src/interfaces/server_circuit_prover.ts +13 -37
- package/src/interfaces/validator.ts +6 -5
- package/src/kernel/private_kernel_reset_dimensions.ts +1 -1
- package/src/messaging/append_l1_to_l2_messages.ts +5 -13
- package/src/messaging/inbox_bucket.ts +125 -0
- package/src/messaging/inbox_consumption.ts +74 -0
- package/src/messaging/inbox_rolling_hash.ts +24 -0
- package/src/messaging/index.ts +5 -2
- package/src/messaging/l1_to_l2_message_bundle.ts +65 -0
- package/src/messaging/l1_to_l2_message_source.ts +48 -10
- package/src/messaging/l1_to_l2_message_sponge.ts +69 -0
- package/src/noir/index.ts +1 -2
- package/src/p2p/block_proposal.ts +41 -28
- package/src/p2p/checkpoint_proposal.ts +31 -6
- package/src/p2p/index.ts +1 -0
- package/src/p2p/validated_proposal.ts +43 -0
- package/src/p2p/wire_compat_fixtures.ts +23 -0
- package/src/parity/inbox_parity_private_inputs.ts +116 -0
- package/src/parity/index.ts +1 -2
- package/src/parity/parity_public_inputs.ts +12 -14
- package/src/proofs/proving_request_type.ts +2 -5
- package/src/rollup/block_constant_data.ts +4 -4
- package/src/rollup/block_rollup_public_inputs.ts +14 -5
- package/src/rollup/block_root_rollup_private_inputs.ts +117 -153
- package/src/rollup/checkpoint_header.ts +17 -13
- package/src/rollup/checkpoint_rollup_public_inputs.ts +15 -0
- package/src/rollup/checkpoint_root_rollup_private_inputs.ts +16 -3
- package/src/rollup/root_rollup_public_inputs.ts +10 -0
- package/src/stats/stats.ts +4 -5
- package/src/tests/factories.ts +38 -32
- package/src/tests/fixtures.ts +3 -0
- package/src/tests/mocks.ts +6 -7
- package/src/tx/state_reference.ts +5 -12
- package/dest/messaging/in_hash.d.ts +0 -6
- package/dest/messaging/in_hash.d.ts.map +0 -1
- package/dest/messaging/in_hash.js +0 -10
- package/dest/messaging/inbox_leaf.d.ts +0 -25
- package/dest/messaging/inbox_leaf.d.ts.map +0 -1
- package/dest/messaging/inbox_leaf.js +0 -42
- package/dest/parity/parity_base_private_inputs.d.ts +0 -39
- package/dest/parity/parity_base_private_inputs.d.ts.map +0 -1
- package/dest/parity/parity_base_private_inputs.js +0 -51
- package/dest/parity/parity_root_private_inputs.d.ts +0 -39
- package/dest/parity/parity_root_private_inputs.d.ts.map +0 -1
- package/dest/parity/parity_root_private_inputs.js +0 -46
- package/src/messaging/in_hash.ts +0 -12
- package/src/messaging/inbox_leaf.ts +0 -44
- package/src/parity/parity_base_private_inputs.ts +0 -71
- package/src/parity/parity_root_private_inputs.ts +0 -64
|
@@ -1,156 +1,51 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { createLogger } from '@aztec/foundation/log';
|
|
2
2
|
import { RunningPromise } from '@aztec/foundation/running-promise';
|
|
3
3
|
|
|
4
|
-
import type { BlockData } from '../block_data.js';
|
|
5
|
-
import type { L2Block } from '../l2_block.js';
|
|
6
4
|
import {
|
|
7
5
|
type ArchiverEmitter,
|
|
8
|
-
type BlockQuery,
|
|
9
|
-
type BlocksQuery,
|
|
10
6
|
type L2BlockSource,
|
|
11
7
|
type L2BlockSourceEventEmitter,
|
|
12
8
|
L2BlockSourceEvents,
|
|
13
|
-
type L2BlockSourceUpdatedEvent,
|
|
14
|
-
type L2Tips,
|
|
15
9
|
} from '../l2_block_source.js';
|
|
16
|
-
import {
|
|
17
|
-
import { L2BlockStream, type L2BlockStreamOptions
|
|
18
|
-
|
|
19
|
-
/** Derives the metadata-only {@link BlockData} view of a hydrated {@link L2Block}. */
|
|
20
|
-
async function l2BlockToBlockData(block: L2Block): Promise<BlockData> {
|
|
21
|
-
return {
|
|
22
|
-
header: block.header,
|
|
23
|
-
archive: block.archive,
|
|
24
|
-
blockHash: await block.hash(),
|
|
25
|
-
checkpointNumber: block.checkpointNumber,
|
|
26
|
-
indexWithinCheckpoint: block.indexWithinCheckpoint,
|
|
27
|
-
};
|
|
28
|
-
}
|
|
10
|
+
import type { L2BlockStreamEventHandler, L2BlockStreamLocalDataProvider } from './interfaces.js';
|
|
11
|
+
import { L2BlockStream, type L2BlockStreamOptions } from './l2_block_stream.js';
|
|
29
12
|
|
|
30
13
|
/** Returns the event emitter of a source that exposes one, or undefined for plain (e.g. RPC-backed) sources. */
|
|
31
14
|
function getEmitter(source: L2BlockSource | L2BlockSourceEventEmitter): ArchiverEmitter | undefined {
|
|
32
15
|
return 'events' in source ? source.events : undefined;
|
|
33
16
|
}
|
|
34
17
|
|
|
35
|
-
/** Fast-path context for a single sync pass: blocks to serve by number, plus the tips to report as the source's. */
|
|
36
|
-
type ActiveUpdate = { byNumber: Map<number, L2Block>; toTips: L2Tips };
|
|
37
|
-
|
|
38
|
-
/**
|
|
39
|
-
* Wraps a block source so a single sync pass can be served from blocks delivered by an aggregate update event,
|
|
40
|
-
* avoiding round-trips to archiver storage. The fast path is only armed (via {@link activate}) for a pass that is
|
|
41
|
-
* confirmed caught up to the event's pre-pass tips: in that case the event's `blocksAdded` contiguously cover the
|
|
42
|
-
* pass's download range and `toTips` is the exact post-pass tip, so `getL2Tips` can report it without querying the
|
|
43
|
-
* source. When the fast path is not armed, every read delegates to the source, so a stale or partial cache never
|
|
44
|
-
* changes the sync outcome.
|
|
45
|
-
*/
|
|
46
|
-
class HotBlockSourceAdapter implements L2BlockStreamSource {
|
|
47
|
-
/** Set for the duration of one fast-path pass; undefined when reads must delegate to the source. */
|
|
48
|
-
private active: ActiveUpdate | undefined;
|
|
49
|
-
|
|
50
|
-
constructor(
|
|
51
|
-
private readonly source: L2BlockStreamSource,
|
|
52
|
-
private readonly log: Logger,
|
|
53
|
-
) {}
|
|
54
|
-
|
|
55
|
-
/** Arms the fast path for the current pass: serve these blocks and report `toTips` as the source tips. */
|
|
56
|
-
public activate(blocks: readonly L2Block[], toTips: L2Tips): void {
|
|
57
|
-
const byNumber = new Map<number, L2Block>();
|
|
58
|
-
for (const block of blocks) {
|
|
59
|
-
byNumber.set(block.number, block);
|
|
60
|
-
}
|
|
61
|
-
this.active = { byNumber, toTips };
|
|
62
|
-
this.log.trace(`Armed hot-block fast path`, { blocks: byNumber.size, toTips });
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
/** Disarms the fast path so subsequent reads delegate to the source again. */
|
|
66
|
-
public deactivate(): void {
|
|
67
|
-
this.active = undefined;
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
public getL2Tips(): Promise<L2Tips> {
|
|
71
|
-
return this.active ? Promise.resolve(this.active.toTips) : this.source.getL2Tips();
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
public getBlocks(query: BlocksQuery): Promise<L2Block[]> {
|
|
75
|
-
const served = this.active ? this.tryServeBlocksFromCache(query) : undefined;
|
|
76
|
-
return served ? Promise.resolve(served) : this.source.getBlocks(query);
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
public getBlockData(query: BlockQuery): Promise<BlockData | undefined> {
|
|
80
|
-
if (this.active && 'number' in query) {
|
|
81
|
-
const block = this.active.byNumber.get(query.number);
|
|
82
|
-
if (block) {
|
|
83
|
-
return l2BlockToBlockData(block);
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
return this.source.getBlockData(query);
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
/** Serves a block range from the cache only when it is fully covered by contiguous cached blocks. */
|
|
90
|
-
private tryServeBlocksFromCache(query: BlocksQuery): L2Block[] | undefined {
|
|
91
|
-
// Only the by-range form is cacheable, and only for the full (not checkpointed-only) chain: the cache may hold
|
|
92
|
-
// uncheckpointed blocks that an onlyCheckpointed query must not receive.
|
|
93
|
-
if (!this.active || !('from' in query) || query.onlyCheckpointed) {
|
|
94
|
-
return undefined;
|
|
95
|
-
}
|
|
96
|
-
const from = query.from;
|
|
97
|
-
const to = from + query.limit - 1;
|
|
98
|
-
const blocks: L2Block[] = [];
|
|
99
|
-
for (let n = from; n <= to; n++) {
|
|
100
|
-
const block = this.active.byNumber.get(n);
|
|
101
|
-
if (!block) {
|
|
102
|
-
// A gap inside the requested range: bail out and let the source serve the whole range.
|
|
103
|
-
return undefined;
|
|
104
|
-
}
|
|
105
|
-
blocks.push(block);
|
|
106
|
-
}
|
|
107
|
-
return blocks;
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
|
|
111
18
|
/**
|
|
112
19
|
* Event-driven wrapper around {@link L2BlockStream}. Subscribes to the source's aggregate `l2BlockSourceUpdated`
|
|
113
|
-
* event (when the source exposes one)
|
|
114
|
-
*
|
|
115
|
-
*
|
|
116
|
-
*
|
|
117
|
-
*
|
|
118
|
-
* the stream's local tips match the event's `fromTips` (it is caught up to where the event began), the event's
|
|
119
|
-
* hydrated blocks are served back through a hot-block cache and the event's `toTips` is reported as the source tips
|
|
120
|
-
* — so the triggered sync re-reads neither block bodies nor tips from the archiver. Otherwise the pass delegates
|
|
121
|
-
* entirely to the source, and the periodic poll guarantees eventual catch-up.
|
|
20
|
+
* event (when the source exposes one) and uses it purely as a doorbell: each event triggers an immediate
|
|
21
|
+
* reconciliation pass instead of waiting for the next tick, while the periodic poll remains the correctness
|
|
22
|
+
* fallback. Every pass reads tips and blocks authoritatively from the source, so a missed, stale, or duplicated
|
|
23
|
+
* event only affects latency. Subsystems keep consuming the same {@link L2BlockStreamEvent}s; the archiver
|
|
24
|
+
* aggregate event is handled entirely here.
|
|
122
25
|
*/
|
|
123
26
|
export class EventDrivenL2BlockStream {
|
|
124
|
-
private readonly adapter: HotBlockSourceAdapter;
|
|
125
27
|
private readonly blockStream: L2BlockStream;
|
|
126
|
-
private readonly runningPromise: RunningPromise
|
|
28
|
+
private readonly runningPromise: RunningPromise;
|
|
127
29
|
private readonly emitter: ArchiverEmitter | undefined;
|
|
128
30
|
private started = false;
|
|
129
31
|
|
|
130
|
-
private readonly onSourceUpdated = (
|
|
32
|
+
private readonly onSourceUpdated = () => {
|
|
131
33
|
// Fire-and-forget: trigger coalesces with any in-flight or periodic pass (see RunningPromise.trigger), so a
|
|
132
34
|
// burst of events does not run passes concurrently. Errors are swallowed by the inner stream's own handler.
|
|
133
|
-
void this.runningPromise
|
|
134
|
-
.trigger(event)
|
|
135
|
-
.catch(err => this.log.error(`Error in event-triggered block stream sync`, err));
|
|
35
|
+
void this.runningPromise.trigger().catch(err => this.log.error(`Error in event-triggered block stream sync`, err));
|
|
136
36
|
};
|
|
137
37
|
|
|
138
38
|
constructor(
|
|
139
39
|
source: L2BlockSource | L2BlockSourceEventEmitter,
|
|
140
|
-
|
|
40
|
+
localData: L2BlockStreamLocalDataProvider,
|
|
141
41
|
handler: L2BlockStreamEventHandler,
|
|
142
42
|
private readonly log = createLogger('types:event_driven_block_stream'),
|
|
143
43
|
opts: L2BlockStreamOptions = {},
|
|
144
44
|
) {
|
|
145
|
-
this.adapter = new HotBlockSourceAdapter(source, log);
|
|
146
45
|
// The inner stream's own RunningPromise is never started; this wrapper owns the polling loop and drives the
|
|
147
46
|
// stream through `sync()` (which runs `work()` directly when the inner loop is stopped).
|
|
148
|
-
this.blockStream = new L2BlockStream(
|
|
149
|
-
this.runningPromise = new RunningPromise
|
|
150
|
-
this.runPass.bind(this),
|
|
151
|
-
log,
|
|
152
|
-
opts.pollIntervalMS ?? 1000,
|
|
153
|
-
);
|
|
47
|
+
this.blockStream = new L2BlockStream(source, localData, handler, log, opts);
|
|
48
|
+
this.runningPromise = new RunningPromise(() => this.blockStream.sync(), log, opts.pollIntervalMS ?? 1000);
|
|
154
49
|
this.emitter = getEmitter(source);
|
|
155
50
|
}
|
|
156
51
|
|
|
@@ -176,32 +71,11 @@ export class EventDrivenL2BlockStream {
|
|
|
176
71
|
}
|
|
177
72
|
|
|
178
73
|
/**
|
|
179
|
-
* Runs a synchronization pass now, bypassing the poll interval
|
|
180
|
-
*
|
|
181
|
-
*
|
|
182
|
-
* window. The periodic poll and per-pass reorg handling make the gap a latency effect, never a correctness one.
|
|
74
|
+
* Runs a synchronization pass now, bypassing the poll interval. Resolves once a pass that started after this call
|
|
75
|
+
* completes, so the caller observes state at least as fresh as the moment it asked. Concurrent callers coalesce
|
|
76
|
+
* onto a single such pass. Rejects if the stream is stopped before that pass runs.
|
|
183
77
|
*/
|
|
184
78
|
public sync(): Promise<void> {
|
|
185
79
|
return this.runningPromise.trigger();
|
|
186
80
|
}
|
|
187
|
-
|
|
188
|
-
/**
|
|
189
|
-
* Runs a single pass over the underlying block stream. When triggered by an aggregate event and the stream is
|
|
190
|
-
* caught up to the event's pre-pass tips, the event's blocks and tips serve the pass directly; the fast path is
|
|
191
|
-
* always disarmed afterwards so a subsequent poll-driven pass reads from the source.
|
|
192
|
-
*/
|
|
193
|
-
private async runPass(event?: L2BlockSourceUpdatedEvent): Promise<void> {
|
|
194
|
-
if (event) {
|
|
195
|
-
const localTips = await this.localData.getL2Tips();
|
|
196
|
-
if (localTipsMatch(localTips, event.fromTips)) {
|
|
197
|
-
this.adapter.activate(event.blocksAdded, event.toTips);
|
|
198
|
-
}
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
try {
|
|
202
|
-
await this.blockStream.sync();
|
|
203
|
-
} finally {
|
|
204
|
-
this.adapter.deactivate();
|
|
205
|
-
}
|
|
206
|
-
}
|
|
207
81
|
}
|
|
@@ -42,6 +42,18 @@ export type ProposedOnlyCheckpointData = {
|
|
|
42
42
|
feeAssetPriceModifier: bigint;
|
|
43
43
|
};
|
|
44
44
|
|
|
45
|
+
/** Inbox consumption record of a proposed checkpoint, mirroring what `propose` writes for it on L1. */
|
|
46
|
+
export type ProposedInboxConsumption = {
|
|
47
|
+
/**
|
|
48
|
+
* Cumulative Inbox message count consumed as of this checkpoint: its last block's L1-to-L2 message tree leaf count
|
|
49
|
+
* under compact indexing. L1 records this per checkpoint and reads it back as the parent total
|
|
50
|
+
* when validating the next checkpoint's consumption, so a simulation against a not-yet-mined parent must override
|
|
51
|
+
* the parent's cell with it — otherwise the parent reads as having consumed nothing and the child's consumption
|
|
52
|
+
* looks larger than it is.
|
|
53
|
+
*/
|
|
54
|
+
inboxMsgTotal: bigint;
|
|
55
|
+
};
|
|
56
|
+
|
|
45
57
|
/** Lightweight checkpoint metadata without full block data. */
|
|
46
58
|
export type CheckpointData = CommonCheckpointData & StorageEnrichedCheckpointData & L1EnrichedCheckpointData;
|
|
47
59
|
|
|
@@ -51,7 +63,7 @@ export type ProposedCheckpointInput = CommonCheckpointData & ProposedOnlyCheckpo
|
|
|
51
63
|
|
|
52
64
|
/** Full data for a proposed checkpoint (proposed but not yet L1-confirmed).
|
|
53
65
|
* Includes fee-relevant fields used during pipelining to compute the fee header override. */
|
|
54
|
-
export type ProposedCheckpointData = ProposedCheckpointInput & StorageEnrichedCheckpointData;
|
|
66
|
+
export type ProposedCheckpointData = ProposedCheckpointInput & StorageEnrichedCheckpointData & ProposedInboxConsumption;
|
|
55
67
|
|
|
56
68
|
export const ProposedCheckpointDataSchema = z.object({
|
|
57
69
|
checkpointNumber: CheckpointNumberSchema,
|
|
@@ -62,6 +74,7 @@ export const ProposedCheckpointDataSchema = z.object({
|
|
|
62
74
|
blockCount: z.number(),
|
|
63
75
|
totalManaUsed: schemas.BigInt,
|
|
64
76
|
feeAssetPriceModifier: schemas.BigInt,
|
|
77
|
+
inboxMsgTotal: schemas.BigInt,
|
|
65
78
|
});
|
|
66
79
|
|
|
67
80
|
export const CheckpointDataSchema = z
|
package/src/checkpoint/index.ts
CHANGED
|
@@ -3,6 +3,7 @@ export * from './checkpoint_data.js';
|
|
|
3
3
|
export * from './checkpoint_info.js';
|
|
4
4
|
export * from './checkpoint_reexecution_tracker.js';
|
|
5
5
|
export * from './digest.js';
|
|
6
|
+
export * from './previous_checkpoint_inbox_rolling_hash.js';
|
|
6
7
|
export * from './previous_checkpoint_out_hashes.js';
|
|
7
8
|
export * from './published_checkpoint.js';
|
|
8
9
|
export * from './simulation_overrides.js';
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { CheckpointNumber } from '@aztec/foundation/branded-types';
|
|
2
|
+
import { Fr } from '@aztec/foundation/curves/bn254';
|
|
3
|
+
import type { Logger } from '@aztec/foundation/log';
|
|
4
|
+
|
|
5
|
+
import type { L2BlockSource } from '../block/l2_block_source.js';
|
|
6
|
+
import type { ProposedCheckpointData } from './checkpoint_data.js';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Returns the inbox rolling hash chain-start for `checkpointNumber`: the `inboxRollingHash` of the immediately
|
|
10
|
+
* preceding checkpoint. Unlike the epoch out-hash tree, the rolling-hash chain is continuous across epoch boundaries,
|
|
11
|
+
* so the parent is always `checkpointNumber - 1` regardless of epoch. The genesis checkpoint (and the first checkpoint
|
|
12
|
+
* built on it) starts the chain at zero.
|
|
13
|
+
*
|
|
14
|
+
* Under proposer pipelining the parent may not be confirmed on L1 yet, so the locally-known proposed checkpoint is
|
|
15
|
+
* preferred when it is the parent, mirroring `getPreviousCheckpointOutHashes`.
|
|
16
|
+
*/
|
|
17
|
+
export async function getPreviousCheckpointInboxRollingHash(input: {
|
|
18
|
+
blockSource: Pick<L2BlockSource, 'getCheckpointData' | 'getProposedCheckpointData'>;
|
|
19
|
+
checkpointNumber: CheckpointNumber;
|
|
20
|
+
proposedCheckpointData?: ProposedCheckpointData;
|
|
21
|
+
log?: Logger;
|
|
22
|
+
}): Promise<Fr> {
|
|
23
|
+
const { blockSource, checkpointNumber, proposedCheckpointData, log } = input;
|
|
24
|
+
if (checkpointNumber <= 1) {
|
|
25
|
+
return Fr.ZERO;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const parent = CheckpointNumber(checkpointNumber - 1);
|
|
29
|
+
|
|
30
|
+
if (proposedCheckpointData?.checkpointNumber === parent) {
|
|
31
|
+
log?.debug(`Using pipelined parent cp ${parent} inbox rolling hash for cp ${checkpointNumber}`);
|
|
32
|
+
return proposedCheckpointData.header.inboxRollingHash;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const confirmed = await blockSource.getCheckpointData({ number: parent });
|
|
36
|
+
if (confirmed) {
|
|
37
|
+
return confirmed.header.inboxRollingHash;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
const proposed = await blockSource.getProposedCheckpointData({ number: parent });
|
|
41
|
+
if (proposed) {
|
|
42
|
+
return proposed.header.inboxRollingHash;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
throw new Error(`Cannot source inbox rolling hash for parent checkpoint ${parent} of checkpoint ${checkpointNumber}`);
|
|
46
|
+
}
|
|
@@ -45,7 +45,7 @@ type CheckpointSimulationOverridesPlanInput = {
|
|
|
45
45
|
/**
|
|
46
46
|
* Builds the SimulationOverridesPlan describing the simulated L1 rollup state for a checkpoint's
|
|
47
47
|
* enqueue-time simulations: `canProposeAt` (in Sequencer.doWork) and the propose-related sims
|
|
48
|
-
* (
|
|
48
|
+
* (validateCheckpointHeader, simulateProposeTx). The plan reflects "as if our pipelined parent
|
|
49
49
|
* checkpoint has landed and any required invalidation has executed" — the gap that needs to be
|
|
50
50
|
* bridged at enqueue time.
|
|
51
51
|
*
|
|
@@ -73,21 +73,24 @@ export async function buildCheckpointSimulationOverridesPlan(
|
|
|
73
73
|
builder.withChainTips({ pending: overridenChainTip, proven: overridenChainTip });
|
|
74
74
|
|
|
75
75
|
if (input.proposedCheckpointData) {
|
|
76
|
-
const { header, archive, checkpointOutHash, feeAssetPriceModifier } = input.proposedCheckpointData;
|
|
76
|
+
const { header, archive, checkpointOutHash, feeAssetPriceModifier, inboxMsgTotal } = input.proposedCheckpointData;
|
|
77
77
|
builder.withPendingArchive(archive.root);
|
|
78
78
|
// Override every locally-derivable `tempCheckpointLogs[parent]` field that L1 will eventually
|
|
79
|
-
// write. `slotNumber` is
|
|
79
|
+
// write. `slotNumber` is required by `STFLib.canPruneAtTime`: without it the cell reads
|
|
80
80
|
// slotNumber 0, the contract treats the pending tip as belonging to an expired epoch, and
|
|
81
81
|
// `getEffectivePendingCheckpointNumber` silently collapses pending back to proven — producing
|
|
82
|
-
// a spurious `Rollup__InvalidArchive` against the on-chain genesis archive.
|
|
83
|
-
//
|
|
84
|
-
//
|
|
85
|
-
//
|
|
86
|
-
//
|
|
82
|
+
// a spurious `Rollup__InvalidArchive` against the on-chain genesis archive. `inboxMsgTotal` is
|
|
83
|
+
// read by `ProposeLib.validateInboxConsumption` as the parent's consumed total: left at zero it
|
|
84
|
+
// makes our consumption look like the Inbox's entire history and trips
|
|
85
|
+
// `Rollup__TooManyInboxMessagesConsumed`. The remaining fields (headerHash, outHash,
|
|
86
|
+
// payloadDigest) are not read by `canProposeAt` / `validateCheckpointHeader`, but mirroring the full
|
|
87
|
+
// cell keeps the simulation byte-faithful with what the actual `propose()` send will observe,
|
|
88
|
+
// which is a defense against future reads taking dependencies on them.
|
|
87
89
|
builder.withPendingTempCheckpointLogFields({
|
|
88
90
|
headerHash: header.hash(),
|
|
89
91
|
outHash: checkpointOutHash,
|
|
90
92
|
slotNumber: header.slotNumber,
|
|
93
|
+
inboxMsgTotal,
|
|
91
94
|
payloadDigest: computeCheckpointPayloadDigest({
|
|
92
95
|
header,
|
|
93
96
|
archiveRoot: archive.root,
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import { type L1ContractsConfig, l1ContractsConfigMappings, validateSlotDurations } from '@aztec/ethereum/config';
|
|
2
2
|
import { type EnvVar, pickConfigMappings } from '@aztec/foundation/config';
|
|
3
3
|
|
|
4
|
+
import { MAX_ATTESTABLE_BLOCKS_PER_CHECKPOINT } from '../deserialization/index.js';
|
|
4
5
|
import type { SequencerConfig } from '../interfaces/configs.js';
|
|
6
|
+
import { MIN_BLOCKS_FOR_INBOX_CATCHUP } from '../messaging/inbox_consumption.js';
|
|
5
7
|
import {
|
|
6
8
|
DEFAULT_CHECKPOINT_PROPOSAL_INIT_TIME,
|
|
7
9
|
DEFAULT_CHECKPOINT_PROPOSAL_PREPARE_TIME,
|
|
@@ -47,7 +49,6 @@ export const NETWORK_CONSENSUS_ENV_VARS = [
|
|
|
47
49
|
'AZTEC_EJECTION_THRESHOLD',
|
|
48
50
|
'AZTEC_LOCAL_EJECTION_THRESHOLD',
|
|
49
51
|
'AZTEC_EXIT_DELAY_SECONDS',
|
|
50
|
-
'AZTEC_INBOX_LAG',
|
|
51
52
|
'AZTEC_PROOF_SUBMISSION_EPOCHS',
|
|
52
53
|
'AZTEC_MANA_TARGET',
|
|
53
54
|
'AZTEC_PROVING_COST_PER_MANA',
|
|
@@ -142,7 +143,8 @@ export function getConsensusConfigFromNetworkEnv(
|
|
|
142
143
|
* The check requires `maxBlocksPerCheckpoint` to be *exactly* what a {@link ProposerTimetable} built from the
|
|
143
144
|
* same slot timings and the production default budgets derives. This exact-equality requirement ensures the
|
|
144
145
|
* published network value is precisely what the production default budgets produce, so every node running those
|
|
145
|
-
* defaults agrees on the per-checkpoint block count without clamping.
|
|
146
|
+
* defaults agrees on the per-checkpoint block count without clamping. It must also be at least
|
|
147
|
+
* {@link MIN_BLOCKS_FOR_INBOX_CATCHUP}, without which the network is permanently haltable.
|
|
146
148
|
*/
|
|
147
149
|
export function validateNetworkConsensusConfig(config: NetworkConsensusConfig): string[] {
|
|
148
150
|
const errors: string[] = [];
|
|
@@ -165,8 +167,19 @@ export function validateNetworkConsensusConfig(config: NetworkConsensusConfig):
|
|
|
165
167
|
`blockDurationMs (${config.blockDurationMs}ms) exceeds aztecSlotDuration (${config.aztecSlotDuration}s)`,
|
|
166
168
|
);
|
|
167
169
|
}
|
|
168
|
-
if (config.maxBlocksPerCheckpoint <
|
|
169
|
-
errors.push(
|
|
170
|
+
if (config.maxBlocksPerCheckpoint < MIN_BLOCKS_FOR_INBOX_CATCHUP) {
|
|
171
|
+
errors.push(
|
|
172
|
+
`maxBlocksPerCheckpoint must be at least ${MIN_BLOCKS_FOR_INBOX_CATCHUP} so a checkpoint can always clear a ` +
|
|
173
|
+
`mandatory streaming-Inbox backlog (got ${config.maxBlocksPerCheckpoint}); lower the block duration or raise ` +
|
|
174
|
+
`the slot duration so the proposer budgets derive at least that many blocks`,
|
|
175
|
+
);
|
|
176
|
+
}
|
|
177
|
+
if (config.maxBlocksPerCheckpoint > MAX_ATTESTABLE_BLOCKS_PER_CHECKPOINT) {
|
|
178
|
+
errors.push(
|
|
179
|
+
`maxBlocksPerCheckpoint (${config.maxBlocksPerCheckpoint}) exceeds the ` +
|
|
180
|
+
`${MAX_ATTESTABLE_BLOCKS_PER_CHECKPOINT} blocks nodes will build or attest to, so the network would ` +
|
|
181
|
+
`reject block indices its own configuration admits`,
|
|
182
|
+
);
|
|
170
183
|
}
|
|
171
184
|
if (config.checkpointProposalSyncGraceSeconds < 0) {
|
|
172
185
|
errors.push(
|
|
@@ -1,7 +1,13 @@
|
|
|
1
|
-
import { type ConfigMappingsType, numberConfigHelper } from '@aztec/foundation/config';
|
|
1
|
+
import { type ConfigMappingsType, booleanConfigHelper, numberConfigHelper } from '@aztec/foundation/config';
|
|
2
2
|
|
|
3
3
|
import { DEFAULT_MAX_DEBUG_LOG_MEMORY_READS } from '../avm/avm.js';
|
|
4
4
|
|
|
5
|
+
const parseCommaSeparatedList = (value: string) =>
|
|
6
|
+
value
|
|
7
|
+
.split(',')
|
|
8
|
+
.map(item => item.trim())
|
|
9
|
+
.filter(Boolean);
|
|
10
|
+
|
|
5
11
|
export const nodeRpcConfigMappings: ConfigMappingsType<NodeRPCConfig> = {
|
|
6
12
|
rpcSimulatePublicMaxGasLimit: {
|
|
7
13
|
env: 'RPC_SIMULATE_PUBLIC_MAX_GAS_LIMIT',
|
|
@@ -24,6 +30,33 @@ export const nodeRpcConfigMappings: ConfigMappingsType<NodeRPCConfig> = {
|
|
|
24
30
|
description: 'Maximum allowed batch size for JSON RPC batch requests.',
|
|
25
31
|
defaultValue: '1mb',
|
|
26
32
|
},
|
|
33
|
+
rpcHttpKeepAliveTimeoutMs: {
|
|
34
|
+
env: 'RPC_HTTP_KEEP_ALIVE_TIMEOUT_MS',
|
|
35
|
+
description: 'HTTP keep-alive timeout for JSON RPC connections in milliseconds.',
|
|
36
|
+
...numberConfigHelper(5_000),
|
|
37
|
+
},
|
|
38
|
+
rpcHttpHeadersTimeoutMs: {
|
|
39
|
+
env: 'RPC_HTTP_HEADERS_TIMEOUT_MS',
|
|
40
|
+
description: 'Timeout for receiving complete HTTP headers on JSON RPC connections in milliseconds.',
|
|
41
|
+
...numberConfigHelper(60_000),
|
|
42
|
+
},
|
|
43
|
+
rpcCorsAllowedOrigins: {
|
|
44
|
+
env: 'RPC_CORS_ALLOWED_ORIGINS',
|
|
45
|
+
description: 'Origins allowed to make credentialed cross-origin JSON RPC requests, separated by commas.',
|
|
46
|
+
parseEnv: parseCommaSeparatedList,
|
|
47
|
+
defaultValue: [],
|
|
48
|
+
},
|
|
49
|
+
rpcCorsAllowedHeaders: {
|
|
50
|
+
env: 'RPC_CORS_ALLOWED_HEADERS',
|
|
51
|
+
description: 'Headers allowed in cross-origin JSON RPC requests, separated by commas.',
|
|
52
|
+
parseEnv: parseCommaSeparatedList,
|
|
53
|
+
defaultValue: [],
|
|
54
|
+
},
|
|
55
|
+
rpcCorsAllowAnyOrigin: {
|
|
56
|
+
env: 'RPC_CORS_ALLOW_ANY_ORIGIN',
|
|
57
|
+
description: 'Allow credentialed cross-origin JSON RPC requests from any origin.',
|
|
58
|
+
...booleanConfigHelper(false),
|
|
59
|
+
},
|
|
27
60
|
};
|
|
28
61
|
|
|
29
62
|
export type NodeRPCConfig = {
|
|
@@ -35,4 +68,21 @@ export type NodeRPCConfig = {
|
|
|
35
68
|
rpcMaxBatchSize: number;
|
|
36
69
|
/** The maximum body size the RPC server will accept */
|
|
37
70
|
rpcMaxBodySize: string;
|
|
71
|
+
/** HTTP keep-alive timeout for JSON RPC connections in milliseconds. */
|
|
72
|
+
rpcHttpKeepAliveTimeoutMs: number;
|
|
73
|
+
/** Timeout for receiving complete HTTP headers on JSON RPC connections in milliseconds. */
|
|
74
|
+
rpcHttpHeadersTimeoutMs: number;
|
|
75
|
+
/** Origins allowed to make credentialed cross-origin requests to the RPC server. */
|
|
76
|
+
rpcCorsAllowedOrigins: string[];
|
|
77
|
+
/** Headers allowed in cross-origin requests to the RPC server. */
|
|
78
|
+
rpcCorsAllowedHeaders: string[];
|
|
79
|
+
/** Whether to allow credentialed cross-origin requests from any origin. */
|
|
80
|
+
rpcCorsAllowAnyOrigin: boolean;
|
|
38
81
|
};
|
|
82
|
+
|
|
83
|
+
/** Resolves the CORS origin policy for an RPC server. */
|
|
84
|
+
export function getRpcCorsAllowedOrigins(
|
|
85
|
+
config: Pick<NodeRPCConfig, 'rpcCorsAllowedOrigins' | 'rpcCorsAllowAnyOrigin'>,
|
|
86
|
+
): string[] {
|
|
87
|
+
return config.rpcCorsAllowAnyOrigin ? ['*'] : config.rpcCorsAllowedOrigins;
|
|
88
|
+
}
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* These constants define maximum allowed sizes during deserialization
|
|
4
4
|
* to prevent DoS attacks via maliciously crafted messages.
|
|
5
5
|
*/
|
|
6
|
-
import { BLOBS_PER_CHECKPOINT, FIELDS_PER_BLOB } from '@aztec/constants';
|
|
6
|
+
import { BLOBS_PER_CHECKPOINT, FIELDS_PER_BLOB, MAX_BLOCKS_PER_CHECKPOINT } from '@aztec/constants';
|
|
7
7
|
|
|
8
8
|
/** Max transactions per block for deserialization validation */
|
|
9
9
|
export const MAX_TXS_PER_BLOCK = 2 ** 16;
|
|
@@ -17,35 +17,35 @@ export const MAX_COMMITTEE_SIZE = 2048;
|
|
|
17
17
|
*
|
|
18
18
|
* This MUST be >= the number of blocks the proving system can carry, or a structurally-valid, provable
|
|
19
19
|
* checkpoint that L1 accepts would be rejected on ingest (`validateCheckpoint`) and wedge the archiver.
|
|
20
|
-
* The
|
|
21
|
-
* blob-field budget:
|
|
20
|
+
* The checkpoint root circuit caps a checkpoint at {@link MAX_BLOCKS_PER_CHECKPOINT} blocks, well under
|
|
21
|
+
* the looser ceiling the blob-field budget imposes:
|
|
22
22
|
*
|
|
23
23
|
* budget = BLOBS_PER_CHECKPOINT * FIELDS_PER_BLOB = 6 * 4096 = 24,576 fields
|
|
24
24
|
*
|
|
25
|
-
* per-block minimal blob footprint:
|
|
26
|
-
*
|
|
27
|
-
*
|
|
25
|
+
* per-block minimal blob footprint (every block carries a per-block l1-to-l2 root):
|
|
26
|
+
* a block with no txs = 7 fields (NUM_BLOCK_END_BLOB_FIELDS)
|
|
27
|
+
* a block with one minimal tx = 7 + 4 = 11 fields
|
|
28
28
|
* (NUM_BLOCK_END_BLOB_FIELDS + a 4-field minimal tx:
|
|
29
29
|
* tx start marker + tx hash + fee + 1 mandatory nullifier)
|
|
30
30
|
* + 1 checkpoint-end marker (NUM_CHECKPOINT_END_MARKER_FIELDS)
|
|
31
31
|
*
|
|
32
|
-
* max N: 7 +
|
|
32
|
+
* max N: 7 + 11*(N - 1) + 1 <= 24,576 => 11*(N - 1) <= 24,568 => N <= 2,234
|
|
33
33
|
*
|
|
34
|
-
*
|
|
35
|
-
*
|
|
36
|
-
*
|
|
37
|
-
*
|
|
38
|
-
*
|
|
39
|
-
* Invariant checked by the unit test in deserialization.test.ts.
|
|
34
|
+
* 2234 is kept as the deserialization bound: it is far above the circuit cap, so it never rejects a
|
|
35
|
+
* provable checkpoint, while still bounding how much a malformed blob payload can allocate. L1 carries
|
|
36
|
+
* no block count of its own, so an over-cap (and therefore unprovable) checkpoint can only reach it with
|
|
37
|
+
* a malicious committee supermajority — a terminal network compromise. Invariant checked by the unit
|
|
38
|
+
* test in deserialization.test.ts.
|
|
40
39
|
*/
|
|
41
|
-
export const MAX_CAPACITY_BLOCKS_PER_CHECKPOINT =
|
|
40
|
+
export const MAX_CAPACITY_BLOCKS_PER_CHECKPOINT = 2234;
|
|
42
41
|
|
|
43
42
|
/**
|
|
44
|
-
* Max blocks per checkpoint we are willing to build or attest to
|
|
45
|
-
*
|
|
46
|
-
*
|
|
43
|
+
* Max blocks per checkpoint we are willing to build or attest to, and the default block-count limit for
|
|
44
|
+
* `validateCheckpoint`. This is the protocol cap the checkpoint root circuit enforces: anything above it
|
|
45
|
+
* is unprovable, so a node must never build or attest to it. Distinct from
|
|
46
|
+
* {@link MAX_CAPACITY_BLOCKS_PER_CHECKPOINT}, the looser bound used when deserializing untrusted payloads.
|
|
47
47
|
*/
|
|
48
|
-
export const MAX_ATTESTABLE_BLOCKS_PER_CHECKPOINT =
|
|
48
|
+
export const MAX_ATTESTABLE_BLOCKS_PER_CHECKPOINT = MAX_BLOCKS_PER_CHECKPOINT;
|
|
49
49
|
|
|
50
50
|
/** Max tx effects per body (based on blob capacity per checkpoint) */
|
|
51
51
|
export const MAX_TX_EFFECTS_PER_BODY = BLOBS_PER_CHECKPOINT * FIELDS_PER_BLOB;
|
package/src/gas/README.md
CHANGED
|
@@ -226,7 +226,8 @@ must also be buildable into a block and fit a valid checkpoint.
|
|
|
226
226
|
### Per-tx protocol maxima
|
|
227
227
|
|
|
228
228
|
Hard ceilings on what any single tx may declare, independent of network configuration. Declaring more is
|
|
229
|
-
rejected
|
|
229
|
+
rejected by `GasLimitsValidator` at every tx validation entry point except simulation, which is exempt
|
|
230
|
+
because gas estimation deliberately declares limits above the per-tx maximum.
|
|
230
231
|
|
|
231
232
|
- **`MAX_TX_DA_GAS`** (271,200) — `MAX_TX_BLOB_DATA_SIZE_IN_FIELDS` (8,475) × `DA_GAS_PER_FIELD` (32). This
|
|
232
233
|
is the most DA a single tx's effects can encode into a blob, so it is the most DA gas a tx could ever use.
|
|
@@ -300,8 +301,8 @@ The outermost limits, enforced as proposal validity in `validateCheckpointLimits
|
|
|
300
301
|
|
|
301
302
|
| Limit | Value (mainnet defaults) | Scope | Where enforced |
|
|
302
303
|
| --------------------------------------- | ------------------------------- | ------------- | ----------------------------------------------------------- |
|
|
303
|
-
| `MAX_TX_DA_GAS` | 271,200 | per-tx |
|
|
304
|
-
| `MAX_PROCESSABLE_L2_GAS` | 6,540,000 | per-tx |
|
|
304
|
+
| `MAX_TX_DA_GAS` | 271,200 | per-tx | `GasLimitsValidator` (hard ceiling; simulation exempt) |
|
|
305
|
+
| `MAX_PROCESSABLE_L2_GAS` | 6,540,000 | per-tx | `GasLimitsValidator` (hard ceiling; simulation exempt) |
|
|
305
306
|
| Network DA admission limit | min(271,200, ceil(784,448/10×1.5)) = 117,668 | per-tx (relay) | RPC, gossip, pending pool (`GasLimitsValidator`) |
|
|
306
307
|
| Network L2 admission limit | min(6,540,000, ceil(manaLimit/10×1.2)) | per-tx (relay) | RPC, gossip, pending pool (`GasLimitsValidator`) |
|
|
307
308
|
| Per-block fair share + caps | remaining budget / blocks × multiplier, min absolute caps & blob-field cap | per-block | `CheckpointBuilder.capLimitsByCheckpointBudgets` |
|
package/src/gas/gas_settings.ts
CHANGED
|
@@ -20,9 +20,13 @@ export const GAS_ESTIMATION_DA_GAS_LIMIT = GAS_ESTIMATION_TEARDOWN_DA_GAS_LIMIT
|
|
|
20
20
|
/** Gas usage and fees limits set by the transaction sender for different dimensions and phases. */
|
|
21
21
|
export class GasSettings {
|
|
22
22
|
constructor(
|
|
23
|
+
/** Total gas the tx may consume across all phases, teardown included. */
|
|
23
24
|
public readonly gasLimits: Gas,
|
|
25
|
+
/** Portion of gasLimits reserved for the teardown phase, billed in full when the tx has a teardown call. */
|
|
24
26
|
public readonly teardownGasLimits: Gas,
|
|
27
|
+
/** Maximum fees per gas unit the sender is willing to pay. */
|
|
25
28
|
public readonly maxFeesPerGas: GasFees,
|
|
29
|
+
/** Maximum priority fees per gas unit the sender is willing to pay on top of the base fee. */
|
|
26
30
|
public readonly maxPriorityFeesPerGas: GasFees,
|
|
27
31
|
) {}
|
|
28
32
|
// docs:end:gas_settings_vars
|
|
@@ -132,9 +136,9 @@ export class GasSettings {
|
|
|
132
136
|
* the effective gas available for app logic is gasLimits - teardownGasLimits - privateOverhead.
|
|
133
137
|
* To ensure estimation never hits gas caps, we set both limits above what the protocol allows:
|
|
134
138
|
* teardown gets MAX_PROCESSABLE and gasLimits gets teardown + MAX_PROCESSABLE, so the full
|
|
135
|
-
* processable amount remains available for each phase independently.
|
|
136
|
-
*
|
|
137
|
-
*
|
|
139
|
+
* processable amount remains available for each phase independently. Tx validation exempts
|
|
140
|
+
* simulated txs from gas-limit admission (`isValidTx` with `isSimulation: true`), so these
|
|
141
|
+
* inflated limits pass validation; the wallet clamps the real tx to the admission limit afterward.
|
|
138
142
|
*/
|
|
139
143
|
static forEstimation(overrides: {
|
|
140
144
|
gasLimits?: Gas;
|
package/src/gas/tx_gas_limits.ts
CHANGED
|
@@ -1,8 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
NUM_BLOCK_END_BLOB_FIELDS,
|
|
3
|
-
NUM_CHECKPOINT_END_MARKER_FIELDS,
|
|
4
|
-
NUM_FIRST_BLOCK_END_BLOB_FIELDS,
|
|
5
|
-
} from '@aztec/blob-lib/encoding';
|
|
1
|
+
import { NUM_BLOCK_END_BLOB_FIELDS, NUM_CHECKPOINT_END_MARKER_FIELDS } from '@aztec/blob-lib/encoding';
|
|
6
2
|
import {
|
|
7
3
|
BLOBS_PER_CHECKPOINT,
|
|
8
4
|
DA_GAS_PER_FIELD,
|
|
@@ -38,9 +34,8 @@ export const MIN_PER_BLOCK_DA_ALLOCATION_MULTIPLIER = 1.5;
|
|
|
38
34
|
* raw blob capacity (`BLOBS_PER_CHECKPOINT * FIELDS_PER_BLOB * DA_GAS_PER_FIELD`) minus the fields the blob
|
|
39
35
|
* encoding reserves for overhead that no tx pays DA gas for:
|
|
40
36
|
*
|
|
41
|
-
* - one checkpoint-end marker field (`NUM_CHECKPOINT_END_MARKER_FIELDS`),
|
|
42
|
-
* - the
|
|
43
|
-
* - `NUM_BLOCK_END_BLOB_FIELDS` (6) for each of the `blocks - 1` subsequent blocks.
|
|
37
|
+
* - one checkpoint-end marker field (`NUM_CHECKPOINT_END_MARKER_FIELDS`), and
|
|
38
|
+
* - `NUM_BLOCK_END_BLOB_FIELDS` (7, including the per-block l1-to-l2 root) for each of the `blocks` blocks.
|
|
44
39
|
*
|
|
45
40
|
* Subtracting the overhead for every block (not just the first) keeps the network DA admission limit at or
|
|
46
41
|
* below the builder's first-block blob-field cap at every geometry. The builder is the MOST generous for the
|
|
@@ -57,10 +52,7 @@ export function getDaCheckpointBudgetForTxs(maxBlocksPerCheckpoint: number): num
|
|
|
57
52
|
// raw blob capacity, which would otherwise yield a negative advertised DA budget.
|
|
58
53
|
const fields = Math.max(
|
|
59
54
|
0,
|
|
60
|
-
BLOBS_PER_CHECKPOINT * FIELDS_PER_BLOB -
|
|
61
|
-
NUM_CHECKPOINT_END_MARKER_FIELDS -
|
|
62
|
-
NUM_FIRST_BLOCK_END_BLOB_FIELDS -
|
|
63
|
-
(blocks - 1) * NUM_BLOCK_END_BLOB_FIELDS,
|
|
55
|
+
BLOBS_PER_CHECKPOINT * FIELDS_PER_BLOB - NUM_CHECKPOINT_END_MARKER_FIELDS - blocks * NUM_BLOCK_END_BLOB_FIELDS,
|
|
64
56
|
);
|
|
65
57
|
return fields * DA_GAS_PER_FIELD;
|
|
66
58
|
}
|