@aztec/stdlib 5.0.0-rc.1 → 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.
- package/dest/abi/buffer.d.ts +6 -2
- package/dest/abi/buffer.d.ts.map +1 -1
- package/dest/abi/buffer.js +13 -1
- package/dest/avm/avm.js +1 -1
- package/dest/aztec-address/index.d.ts +35 -5
- package/dest/aztec-address/index.d.ts.map +1 -1
- package/dest/aztec-address/index.js +32 -8
- package/dest/block/attestation_info.d.ts +1 -1
- package/dest/block/attestation_info.d.ts.map +1 -1
- package/dest/block/attestation_info.js +7 -4
- package/dest/block/l2_block_source.d.ts +44 -27
- package/dest/block/l2_block_source.d.ts.map +1 -1
- package/dest/block/l2_block_source.js +15 -1
- package/dest/block/l2_block_stream/event_driven_l2_block_stream.d.ts +39 -0
- package/dest/block/l2_block_stream/event_driven_l2_block_stream.d.ts.map +1 -0
- package/dest/block/l2_block_stream/event_driven_l2_block_stream.js +165 -0
- package/dest/block/l2_block_stream/index.d.ts +2 -1
- package/dest/block/l2_block_stream/index.d.ts.map +1 -1
- package/dest/block/l2_block_stream/index.js +1 -0
- package/dest/block/l2_block_stream/interfaces.d.ts +40 -6
- package/dest/block/l2_block_stream/interfaces.d.ts.map +1 -1
- package/dest/block/l2_block_stream/interfaces.js +25 -1
- package/dest/block/l2_block_stream/l2_block_stream.d.ts +23 -15
- package/dest/block/l2_block_stream/l2_block_stream.d.ts.map +1 -1
- package/dest/block/l2_block_stream/l2_block_stream.js +140 -152
- package/dest/block/l2_block_stream/l2_tips_store_base.d.ts +10 -2
- package/dest/block/l2_block_stream/l2_tips_store_base.d.ts.map +1 -1
- package/dest/block/l2_block_stream/l2_tips_store_base.js +33 -15
- package/dest/block/proposal/attestations_and_signers.d.ts +19 -1
- package/dest/block/proposal/attestations_and_signers.d.ts.map +1 -1
- package/dest/block/proposal/attestations_and_signers.js +47 -7
- package/dest/block/test/l2_tips_store_test_suite.d.ts +1 -1
- package/dest/block/test/l2_tips_store_test_suite.d.ts.map +1 -1
- package/dest/block/test/l2_tips_store_test_suite.js +94 -3
- package/dest/block/validate_block_result.d.ts +16 -1
- package/dest/block/validate_block_result.d.ts.map +1 -1
- package/dest/block/validate_block_result.js +18 -3
- 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/simulation_overrides.d.ts +61 -0
- package/dest/checkpoint/simulation_overrides.d.ts.map +1 -0
- package/dest/checkpoint/simulation_overrides.js +98 -0
- package/dest/config/network-consensus-config.d.ts +1 -1
- package/dest/config/network-consensus-config.d.ts.map +1 -1
- package/dest/config/network-consensus-config.js +2 -10
- package/dest/contract/contract_address.d.ts +5 -4
- package/dest/contract/contract_address.d.ts.map +1 -1
- package/dest/contract/contract_instance.d.ts +16 -2
- package/dest/contract/contract_instance.d.ts.map +1 -1
- package/dest/contract/contract_instance.js +45 -0
- package/dest/contract/interfaces/contract_data_source.d.ts +3 -5
- package/dest/contract/interfaces/contract_data_source.d.ts.map +1 -1
- package/dest/contract/interfaces/contract_instance.d.ts +71 -10
- package/dest/contract/interfaces/contract_instance.d.ts.map +1 -1
- package/dest/contract/interfaces/contract_instance.js +7 -2
- package/dest/contract/partial_address.d.ts +9 -3
- package/dest/contract/partial_address.d.ts.map +1 -1
- package/dest/contract/partial_address.js +8 -2
- package/dest/database-version/version_manager.d.ts +18 -4
- package/dest/database-version/version_manager.d.ts.map +1 -1
- package/dest/database-version/version_manager.js +76 -6
- package/dest/file-store/factory.d.ts +1 -1
- package/dest/file-store/factory.d.ts.map +1 -1
- package/dest/file-store/factory.js +7 -0
- package/dest/file-store/index.d.ts +2 -1
- package/dest/file-store/index.d.ts.map +1 -1
- package/dest/file-store/index.js +1 -0
- package/dest/file-store/memory.d.ts +24 -0
- package/dest/file-store/memory.d.ts.map +1 -0
- package/dest/file-store/memory.js +80 -0
- package/dest/ha-signing/config.d.ts +19 -5
- package/dest/ha-signing/config.d.ts.map +1 -1
- package/dest/ha-signing/config.js +9 -3
- package/dest/ha-signing/local_config.d.ts +10 -2
- package/dest/ha-signing/local_config.d.ts.map +1 -1
- package/dest/ha-signing/local_config.js +8 -2
- package/dest/hash/hash.d.ts +1 -2
- package/dest/hash/hash.d.ts.map +1 -1
- package/dest/hash/hash.js +0 -7
- package/dest/interfaces/archiver.d.ts +8 -1
- package/dest/interfaces/archiver.d.ts.map +1 -1
- package/dest/interfaces/archiver.js +3 -2
- package/dest/interfaces/aztec-node-admin.d.ts +5 -2
- package/dest/interfaces/aztec-node-admin.d.ts.map +1 -1
- package/dest/interfaces/aztec-node-debug.d.ts +26 -1
- package/dest/interfaces/aztec-node-debug.d.ts.map +1 -1
- package/dest/interfaces/aztec-node-debug.js +20 -0
- package/dest/interfaces/aztec-node.d.ts +20 -20
- package/dest/interfaces/aztec-node.d.ts.map +1 -1
- package/dest/interfaces/aztec-node.js +8 -15
- package/dest/interfaces/chain_tips.d.ts +8 -47
- package/dest/interfaces/chain_tips.d.ts.map +1 -1
- package/dest/interfaces/chain_tips.js +1 -6
- package/dest/interfaces/checkpoint_parameter.d.ts +3 -3
- package/dest/interfaces/checkpoint_parameter.d.ts.map +1 -1
- package/dest/interfaces/checkpoint_parameter.js +3 -3
- package/dest/interfaces/configs.d.ts +4 -1
- package/dest/interfaces/configs.d.ts.map +1 -1
- package/dest/interfaces/configs.js +1 -0
- package/dest/interfaces/private_kernel_prover.d.ts +9 -11
- package/dest/interfaces/private_kernel_prover.d.ts.map +1 -1
- package/dest/interfaces/prover-node.d.ts +6 -7
- package/dest/interfaces/prover-node.d.ts.map +1 -1
- package/dest/interfaces/prover-node.js +15 -10
- package/dest/interfaces/proving-job.d.ts +87 -74
- package/dest/interfaces/proving-job.d.ts.map +1 -1
- package/dest/interfaces/proving-job.js +13 -4
- package/dest/interfaces/server_circuit_prover.d.ts +3 -3
- package/dest/interfaces/server_circuit_prover.d.ts.map +1 -1
- package/dest/interfaces/validator.d.ts +7 -3
- package/dest/interfaces/validator.d.ts.map +1 -1
- package/dest/interfaces/world_state.d.ts +14 -1
- package/dest/interfaces/world_state.d.ts.map +1 -1
- package/dest/kernel/hints/find_private_kernel_reset_dimensions.d.ts +8 -2
- package/dest/kernel/hints/find_private_kernel_reset_dimensions.d.ts.map +1 -1
- package/dest/kernel/hints/find_private_kernel_reset_dimensions.js +12 -74
- package/dest/kernel/hints/read_request.js +1 -1
- package/dest/kernel/index.d.ts +2 -2
- package/dest/kernel/index.d.ts.map +1 -1
- package/dest/kernel/index.js +1 -1
- package/dest/kernel/log_hash.d.ts +1 -1
- package/dest/kernel/log_hash.d.ts.map +1 -1
- package/dest/kernel/log_hash.js +2 -2
- package/dest/kernel/note_hash.js +1 -1
- package/dest/kernel/nullifier.js +1 -1
- package/dest/kernel/private_circuit_public_inputs.d.ts +13 -3
- package/dest/kernel/private_circuit_public_inputs.d.ts.map +1 -1
- package/dest/kernel/private_circuit_public_inputs.js +14 -7
- package/dest/kernel/private_context_inputs.d.ts +4 -3
- package/dest/kernel/private_context_inputs.d.ts.map +1 -1
- package/dest/kernel/private_context_inputs.js +7 -3
- package/dest/kernel/private_kernel_circuit_public_inputs.d.ts +7 -1
- package/dest/kernel/private_kernel_circuit_public_inputs.d.ts.map +1 -1
- package/dest/kernel/private_kernel_circuit_public_inputs.js +7 -0
- package/dest/kernel/private_kernel_init_2_circuit_private_inputs.d.ts +2 -3
- package/dest/kernel/private_kernel_init_2_circuit_private_inputs.d.ts.map +1 -1
- package/dest/kernel/private_kernel_init_2_circuit_private_inputs.js +3 -5
- package/dest/kernel/private_kernel_init_3_circuit_private_inputs.d.ts +2 -3
- package/dest/kernel/private_kernel_init_3_circuit_private_inputs.d.ts.map +1 -1
- package/dest/kernel/private_kernel_init_3_circuit_private_inputs.js +3 -5
- package/dest/kernel/private_kernel_init_circuit_private_inputs.d.ts +1 -9
- package/dest/kernel/private_kernel_init_circuit_private_inputs.d.ts.map +1 -1
- package/dest/kernel/private_kernel_init_circuit_private_inputs.js +2 -6
- package/dest/kernel/private_kernel_reset_dimensions.d.ts +7 -8
- package/dest/kernel/private_kernel_reset_dimensions.d.ts.map +1 -1
- package/dest/kernel/private_kernel_reset_tail_circuit_private_inputs.d.ts +29 -0
- package/dest/kernel/private_kernel_reset_tail_circuit_private_inputs.d.ts.map +1 -0
- package/dest/kernel/private_kernel_reset_tail_circuit_private_inputs.js +36 -0
- package/dest/kernel/private_log_data.d.ts +1 -1
- package/dest/kernel/private_log_data.d.ts.map +1 -1
- package/dest/kernel/private_log_data.js +1 -1
- package/dest/keys/derivation.d.ts +41 -6
- package/dest/keys/derivation.d.ts.map +1 -1
- package/dest/keys/derivation.js +49 -26
- package/dest/logs/app_tagging_secret.d.ts +30 -7
- package/dest/logs/app_tagging_secret.d.ts.map +1 -1
- package/dest/logs/app_tagging_secret.js +46 -39
- package/dest/logs/contract_class_log.d.ts +1 -2
- package/dest/logs/contract_class_log.d.ts.map +1 -1
- package/dest/logs/contract_class_log.js +0 -4
- package/dest/logs/index.d.ts +1 -3
- package/dest/logs/index.d.ts.map +1 -1
- package/dest/logs/index.js +0 -2
- package/dest/logs/shared_secret_derivation.d.ts +19 -6
- package/dest/logs/shared_secret_derivation.d.ts.map +1 -1
- package/dest/logs/shared_secret_derivation.js +26 -11
- package/dest/messaging/l1_to_l2_message.d.ts +23 -2
- package/dest/messaging/l1_to_l2_message.d.ts.map +1 -1
- package/dest/messaging/l1_to_l2_message.js +36 -11
- package/dest/p2p/attestation_utils.d.ts +1 -1
- package/dest/p2p/attestation_utils.d.ts.map +1 -1
- package/dest/p2p/attestation_utils.js +8 -1
- package/dest/p2p/checkpoint_attestation.d.ts +10 -1
- package/dest/p2p/checkpoint_attestation.d.ts.map +1 -1
- package/dest/p2p/checkpoint_attestation.js +10 -0
- package/dest/p2p/checkpoint_proposal.d.ts +2 -1
- package/dest/p2p/checkpoint_proposal.d.ts.map +1 -1
- package/dest/p2p/consensus_payload.d.ts +2 -1
- package/dest/p2p/consensus_payload.d.ts.map +1 -1
- package/dest/p2p/signature_utils.d.ts +10 -1
- package/dest/p2p/signature_utils.d.ts.map +1 -1
- package/dest/p2p/signature_utils.js +9 -1
- package/dest/rollup/avm_proof_data.d.ts +3 -3
- package/dest/rollup/avm_proof_data.d.ts.map +1 -1
- package/dest/rollup/checkpoint_header.d.ts +8 -3
- package/dest/rollup/checkpoint_header.d.ts.map +1 -1
- package/dest/rollup/checkpoint_header.js +20 -10
- package/dest/stats/stats.d.ts +2 -2
- package/dest/stats/stats.d.ts.map +1 -1
- package/dest/tests/factories.d.ts +1 -1
- package/dest/tests/factories.d.ts.map +1 -1
- package/dest/tests/factories.js +7 -15
- package/dest/trees/nullifier_membership_witness.d.ts +5 -8
- package/dest/trees/nullifier_membership_witness.d.ts.map +1 -1
- package/dest/trees/nullifier_membership_witness.js +0 -9
- package/dest/trees/public_data_witness.d.ts +7 -17
- package/dest/trees/public_data_witness.d.ts.map +1 -1
- package/dest/trees/public_data_witness.js +0 -27
- package/dest/tx/execution_payload.d.ts +1 -1
- package/dest/tx/execution_payload.d.ts.map +1 -1
- package/dest/tx/execution_payload.js +1 -1
- package/dest/tx/global_variable_builder.d.ts +2 -12
- package/dest/tx/global_variable_builder.d.ts.map +1 -1
- package/dest/tx/global_variables.js +2 -2
- package/dest/tx/private_tx_constant_data.d.ts +18 -2
- package/dest/tx/private_tx_constant_data.d.ts.map +1 -1
- package/dest/tx/private_tx_constant_data.js +13 -4
- package/dest/tx/simulated_tx.d.ts +10 -6
- package/dest/tx/simulated_tx.d.ts.map +1 -1
- package/dest/world-state/genesis_data.d.ts +9 -1
- package/dest/world-state/genesis_data.d.ts.map +1 -1
- package/dest/world-state/genesis_data.js +1 -0
- package/package.json +8 -8
- package/src/abi/buffer.ts +13 -1
- package/src/avm/avm.ts +1 -1
- package/src/aztec-address/index.ts +36 -6
- package/src/block/attestation_info.ts +7 -2
- package/src/block/l2_block_source.ts +64 -17
- package/src/block/l2_block_stream/event_driven_l2_block_stream.ts +207 -0
- package/src/block/l2_block_stream/index.ts +1 -0
- package/src/block/l2_block_stream/interfaces.ts +60 -6
- package/src/block/l2_block_stream/l2_block_stream.ts +201 -178
- package/src/block/l2_block_stream/l2_tips_store_base.ts +36 -15
- package/src/block/proposal/attestations_and_signers.ts +53 -7
- package/src/block/test/l2_tips_store_test_suite.ts +73 -4
- package/src/block/validate_block_result.ts +48 -2
- package/src/checkpoint/index.ts +1 -0
- package/src/checkpoint/simulation_overrides.ts +171 -0
- package/src/config/network-consensus-config.ts +2 -13
- package/src/contract/contract_address.ts +4 -3
- package/src/contract/contract_instance.ts +62 -1
- package/src/contract/interfaces/contract_data_source.ts +2 -4
- package/src/contract/interfaces/contract_instance.ts +26 -8
- package/src/contract/partial_address.ts +8 -2
- package/src/database-version/version_manager.ts +96 -6
- package/src/file-store/factory.ts +7 -0
- package/src/file-store/index.ts +1 -0
- package/src/file-store/memory.ts +94 -0
- package/src/ha-signing/config.ts +23 -5
- package/src/ha-signing/local_config.ts +20 -1
- package/src/hash/hash.ts +0 -8
- package/src/interfaces/archiver.ts +9 -1
- package/src/interfaces/aztec-node-debug.ts +37 -0
- package/src/interfaces/aztec-node.ts +30 -33
- package/src/interfaces/chain_tips.ts +8 -16
- package/src/interfaces/checkpoint_parameter.ts +3 -3
- package/src/interfaces/configs.ts +3 -0
- package/src/interfaces/private_kernel_prover.ts +10 -12
- package/src/interfaces/prover-node.ts +19 -11
- package/src/interfaces/proving-job.ts +15 -3
- package/src/interfaces/server_circuit_prover.ts +2 -2
- package/src/interfaces/world_state.ts +14 -0
- package/src/kernel/hints/find_private_kernel_reset_dimensions.ts +22 -112
- package/src/kernel/hints/read_request.ts +1 -1
- package/src/kernel/index.ts +1 -1
- package/src/kernel/log_hash.ts +5 -2
- package/src/kernel/note_hash.ts +1 -1
- package/src/kernel/nullifier.ts +1 -1
- package/src/kernel/private_circuit_public_inputs.ts +12 -1
- package/src/kernel/private_context_inputs.ts +10 -3
- package/src/kernel/private_kernel_circuit_public_inputs.ts +9 -0
- package/src/kernel/private_kernel_init_2_circuit_private_inputs.ts +0 -3
- package/src/kernel/private_kernel_init_3_circuit_private_inputs.ts +0 -3
- package/src/kernel/private_kernel_init_circuit_private_inputs.ts +0 -6
- package/src/kernel/private_kernel_reset_dimensions.ts +15 -5
- package/src/kernel/private_kernel_reset_tail_circuit_private_inputs.ts +69 -0
- package/src/kernel/private_log_data.ts +4 -1
- package/src/keys/derivation.ts +69 -24
- package/src/logs/app_tagging_secret.ts +62 -39
- package/src/logs/contract_class_log.ts +0 -9
- package/src/logs/index.ts +0 -2
- package/src/logs/shared_secret_derivation.ts +31 -15
- package/src/messaging/l1_to_l2_message.ts +51 -13
- package/src/p2p/attestation_utils.ts +8 -1
- package/src/p2p/checkpoint_attestation.ts +12 -0
- package/src/p2p/signature_utils.ts +9 -0
- package/src/rollup/avm_proof_data.ts +2 -2
- package/src/rollup/checkpoint_header.ts +16 -2
- package/src/stats/stats.ts +2 -2
- package/src/tests/factories.ts +6 -12
- package/src/trees/nullifier_membership_witness.ts +0 -11
- package/src/trees/public_data_witness.ts +0 -31
- package/src/tx/execution_payload.ts +2 -1
- package/src/tx/global_variable_builder.ts +1 -17
- package/src/tx/global_variables.ts +2 -2
- package/src/tx/private_tx_constant_data.ts +25 -2
- package/src/world-state/genesis_data.ts +10 -0
- package/dest/kernel/private_kernel_tail_circuit_private_inputs.d.ts +0 -47
- package/dest/kernel/private_kernel_tail_circuit_private_inputs.d.ts.map +0 -1
- package/dest/kernel/private_kernel_tail_circuit_private_inputs.js +0 -38
- package/dest/logs/message_context.d.ts +0 -27
- package/dest/logs/message_context.d.ts.map +0 -1
- package/dest/logs/message_context.js +0 -74
- package/dest/logs/pending_tagged_log.d.ts +0 -13
- package/dest/logs/pending_tagged_log.d.ts.map +0 -1
- package/dest/logs/pending_tagged_log.js +0 -34
- package/src/kernel/private_kernel_tail_circuit_private_inputs.ts +0 -58
- package/src/logs/message_context.ts +0 -76
- package/src/logs/pending_tagged_log.ts +0 -39
|
@@ -94,14 +94,18 @@ export function testL2TipsStore(makeTipsStore: () => Promise<L2TipsStore>) {
|
|
|
94
94
|
return new PublishedCheckpoint(checkpoint, L1PublishedData.random(), []);
|
|
95
95
|
};
|
|
96
96
|
|
|
97
|
-
/** Creates a chain-checkpointed event
|
|
98
|
-
const makeCheckpointedEvent = async (
|
|
99
|
-
const lastBlock =
|
|
97
|
+
/** Creates a thin chain-checkpointed event carrying the block + checkpoint ids of the checkpoint's last block. */
|
|
98
|
+
const makeCheckpointedEvent = async (published: PublishedCheckpoint) => {
|
|
99
|
+
const lastBlock = published.checkpoint.blocks.at(-1)!;
|
|
100
100
|
const blockId: L2BlockId = {
|
|
101
101
|
number: lastBlock.number,
|
|
102
102
|
hash: (await lastBlock.hash()).toString(),
|
|
103
103
|
};
|
|
104
|
-
|
|
104
|
+
const checkpointId = {
|
|
105
|
+
number: published.checkpoint.number,
|
|
106
|
+
hash: published.checkpoint.hash().toString(),
|
|
107
|
+
};
|
|
108
|
+
return { type: 'chain-checkpointed' as const, checkpoint: checkpointId, block: blockId };
|
|
105
109
|
};
|
|
106
110
|
|
|
107
111
|
it('returns zero if no tips are stored', async () => {
|
|
@@ -123,6 +127,71 @@ export function testL2TipsStore(makeTipsStore: () => Promise<L2TipsStore>) {
|
|
|
123
127
|
expect(await tipsStore.getL2BlockHash(3)).toEqual(blockHashes.get(3));
|
|
124
128
|
});
|
|
125
129
|
|
|
130
|
+
it('records the proposed tip number and hash from a chain-proposed event', async () => {
|
|
131
|
+
// chain-proposed is the sole writer of proposed-tip history in tips-only mode: no preceding blocks-added.
|
|
132
|
+
await tipsStore.handleBlockStreamEvent({
|
|
133
|
+
type: 'chain-proposed',
|
|
134
|
+
block: { number: BlockNumber(5), hash: new Fr(500).toString() },
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
const tips = await tipsStore.getL2Tips();
|
|
138
|
+
expect(tips.proposed).toEqual({ number: BlockNumber(5), hash: new Fr(500).toString() });
|
|
139
|
+
// The hash is recorded in the same index the walk-back reads, so it resolves as a sparse anchor.
|
|
140
|
+
expect(await tipsStore.getL2BlockHash(5)).toEqual(new Fr(500).toString());
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
it('serves sparse proposed anchors from chain-proposed events for the walk-back', async () => {
|
|
144
|
+
// Two tip-moving polls in tips-only mode, with no blocks in between (sparse history).
|
|
145
|
+
await tipsStore.handleBlockStreamEvent({
|
|
146
|
+
type: 'chain-proposed',
|
|
147
|
+
block: { number: BlockNumber(4), hash: new Fr(400).toString() },
|
|
148
|
+
});
|
|
149
|
+
await tipsStore.handleBlockStreamEvent({
|
|
150
|
+
type: 'chain-proposed',
|
|
151
|
+
block: { number: BlockNumber(9), hash: new Fr(900).toString() },
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
// Both recorded heights resolve; the heights between them were never seen and stay undefined.
|
|
155
|
+
expect(await tipsStore.getL2BlockHash(4)).toEqual(new Fr(400).toString());
|
|
156
|
+
expect(await tipsStore.getL2BlockHash(9)).toEqual(new Fr(900).toString());
|
|
157
|
+
expect(await tipsStore.getL2BlockHash(6)).toBeUndefined();
|
|
158
|
+
|
|
159
|
+
const tips = await tipsStore.getL2Tips();
|
|
160
|
+
expect(tips.proposed).toEqual({ number: BlockNumber(9), hash: new Fr(900).toString() });
|
|
161
|
+
});
|
|
162
|
+
|
|
163
|
+
it('records block-hash witnesses without moving any tip cursor', async () => {
|
|
164
|
+
// Establish a proposed tip at 9 in tips-only fashion (sole writer of proposed history).
|
|
165
|
+
await tipsStore.handleBlockStreamEvent({
|
|
166
|
+
type: 'chain-proposed',
|
|
167
|
+
block: { number: BlockNumber(9), hash: new Fr(900).toString() },
|
|
168
|
+
});
|
|
169
|
+
|
|
170
|
+
// Record sparse witnesses at heights below the tip (e.g. a consumer materializing per-height state).
|
|
171
|
+
await tipsStore.recordBlockHashes([
|
|
172
|
+
{ number: BlockNumber(4), hash: new Fr(404).toString() },
|
|
173
|
+
{ number: BlockNumber(6), hash: new Fr(606).toString() },
|
|
174
|
+
]);
|
|
175
|
+
|
|
176
|
+
// Each recorded height resolves; an unrecorded gap stays undefined.
|
|
177
|
+
expect(await tipsStore.getL2BlockHash(4)).toEqual(new Fr(404).toString());
|
|
178
|
+
expect(await tipsStore.getL2BlockHash(6)).toEqual(new Fr(606).toString());
|
|
179
|
+
expect(await tipsStore.getL2BlockHash(5)).toBeUndefined();
|
|
180
|
+
|
|
181
|
+
// No tip cursor moved: the proposed tip is still 9, and every other tier is at genesis.
|
|
182
|
+
const tips = await tipsStore.getL2Tips();
|
|
183
|
+
expect(tips.proposed).toEqual({ number: BlockNumber(9), hash: new Fr(900).toString() });
|
|
184
|
+
expect(tips.checkpointed.block).toEqual(makeTip(0));
|
|
185
|
+
expect(tips.proven.block).toEqual(makeTip(0));
|
|
186
|
+
expect(tips.finalized.block).toEqual(makeTip(0));
|
|
187
|
+
});
|
|
188
|
+
|
|
189
|
+
it('skips witnesses with no hash and tolerates an empty list', async () => {
|
|
190
|
+
await tipsStore.recordBlockHashes([]);
|
|
191
|
+
await tipsStore.recordBlockHashes([{ number: BlockNumber(3), hash: '' }]);
|
|
192
|
+
expect(await tipsStore.getL2BlockHash(3)).toBeUndefined();
|
|
193
|
+
});
|
|
194
|
+
|
|
126
195
|
it('checkpoints all proposed blocks', async () => {
|
|
127
196
|
// Propose blocks 1-5
|
|
128
197
|
const blocks = await Promise.all(times(5, i => makeBlock(i + 1)));
|
|
@@ -1,7 +1,9 @@
|
|
|
1
|
+
import type { ViemCommitteeAttestations } from '@aztec/ethereum/contracts';
|
|
1
2
|
import { EpochNumber, EpochNumberSchema } from '@aztec/foundation/branded-types';
|
|
2
3
|
import { EthAddress } from '@aztec/foundation/eth-address';
|
|
3
4
|
import { type ZodFor, schemas } from '@aztec/foundation/schemas';
|
|
4
5
|
import { BufferReader, serializeToBuffer } from '@aztec/foundation/serialize';
|
|
6
|
+
import { bufferToHex, hexToBuffer } from '@aztec/foundation/string';
|
|
5
7
|
|
|
6
8
|
import { z } from 'zod';
|
|
7
9
|
|
|
@@ -30,6 +32,14 @@ export type ValidateCheckpointNegativeResult =
|
|
|
30
32
|
attestors: EthAddress[];
|
|
31
33
|
/** Committee attestations for this checkpoint as they were posted to L1 */
|
|
32
34
|
attestations: CommitteeAttestation[];
|
|
35
|
+
/**
|
|
36
|
+
* The exact packed `CommitteeAttestations` tuple as posted to L1 calldata, carried verbatim so the
|
|
37
|
+
* invalidation evidence is byte-faithful to the stored `attestationsHash`. A repack via
|
|
38
|
+
* `packAttestations` is not a round-trip inverse of `fromPacked`, so it would diverge from the hash
|
|
39
|
+
* and revert `invalidateBadAttestation`/`invalidateInsufficientAttestations`. Always populated on the
|
|
40
|
+
* calldata validation path, the only production source of invalidation evidence.
|
|
41
|
+
*/
|
|
42
|
+
verbatimAttestations: ViemCommitteeAttestations;
|
|
33
43
|
/** Reason for the checkpoint being invalid: not enough attestations were posted */
|
|
34
44
|
reason: 'insufficient-attestations';
|
|
35
45
|
}
|
|
@@ -47,6 +57,12 @@ export type ValidateCheckpointNegativeResult =
|
|
|
47
57
|
attestors: EthAddress[];
|
|
48
58
|
/** Committee attestations for this checkpoint as they were posted to L1 */
|
|
49
59
|
attestations: CommitteeAttestation[];
|
|
60
|
+
/**
|
|
61
|
+
* The exact packed `CommitteeAttestations` tuple as posted to L1 calldata, carried verbatim so the
|
|
62
|
+
* invalidation evidence is byte-faithful to the stored `attestationsHash`. See the same field on the
|
|
63
|
+
* insufficient-attestations variant for why a repack cannot be used.
|
|
64
|
+
*/
|
|
65
|
+
verbatimAttestations: ViemCommitteeAttestations;
|
|
50
66
|
/** Reason for the checkpoint being invalid: an invalid attestation was posted */
|
|
51
67
|
reason: 'invalid-attestation';
|
|
52
68
|
/** Index in the attestations array of the invalid attestation posted */
|
|
@@ -56,6 +72,12 @@ export type ValidateCheckpointNegativeResult =
|
|
|
56
72
|
/** Result type for validating checkpoint attestations */
|
|
57
73
|
export type ValidateCheckpointResult = { valid: true } | ValidateCheckpointNegativeResult;
|
|
58
74
|
|
|
75
|
+
/** Zod schema for the raw packed `CommitteeAttestations` viem tuple (two 0x-prefixed hex strings). */
|
|
76
|
+
const ViemCommitteeAttestationsSchema: ZodFor<ViemCommitteeAttestations> = z.object({
|
|
77
|
+
signatureIndices: schemas.HexStringWith0x,
|
|
78
|
+
signaturesOrAddresses: schemas.HexStringWith0x,
|
|
79
|
+
});
|
|
80
|
+
|
|
59
81
|
export const ValidateCheckpointResultSchema: ZodFor<ValidateCheckpointResult> = z.union([
|
|
60
82
|
z.object({ valid: z.literal(true) }),
|
|
61
83
|
z.object({
|
|
@@ -66,6 +88,7 @@ export const ValidateCheckpointResultSchema: ZodFor<ValidateCheckpointResult> =
|
|
|
66
88
|
seed: schemas.BigInt,
|
|
67
89
|
attestors: z.array(schemas.EthAddress),
|
|
68
90
|
attestations: z.array(CommitteeAttestation.schema),
|
|
91
|
+
verbatimAttestations: ViemCommitteeAttestationsSchema,
|
|
69
92
|
reason: z.literal('insufficient-attestations'),
|
|
70
93
|
}),
|
|
71
94
|
z.object({
|
|
@@ -76,6 +99,7 @@ export const ValidateCheckpointResultSchema: ZodFor<ValidateCheckpointResult> =
|
|
|
76
99
|
seed: schemas.BigInt,
|
|
77
100
|
attestors: z.array(schemas.EthAddress),
|
|
78
101
|
attestations: z.array(CommitteeAttestation.schema),
|
|
102
|
+
verbatimAttestations: ViemCommitteeAttestationsSchema,
|
|
79
103
|
reason: z.literal('invalid-attestation'),
|
|
80
104
|
invalidIndex: z.number(),
|
|
81
105
|
}),
|
|
@@ -87,6 +111,8 @@ export function serializeValidateCheckpointResult(result: ValidateCheckpointResu
|
|
|
87
111
|
}
|
|
88
112
|
|
|
89
113
|
const checkpointBuffer = serializeCheckpointInfo(result.checkpoint);
|
|
114
|
+
const signatureIndices = hexToBuffer(result.verbatimAttestations.signatureIndices);
|
|
115
|
+
const signaturesOrAddresses = hexToBuffer(result.verbatimAttestations.signaturesOrAddresses);
|
|
90
116
|
return serializeToBuffer(
|
|
91
117
|
result.valid,
|
|
92
118
|
result.reason,
|
|
@@ -101,6 +127,10 @@ export function serializeValidateCheckpointResult(result: ValidateCheckpointResu
|
|
|
101
127
|
result.attestations.length,
|
|
102
128
|
result.attestations,
|
|
103
129
|
result.reason === 'invalid-attestation' ? result.invalidIndex : 0,
|
|
130
|
+
signatureIndices.length,
|
|
131
|
+
signatureIndices,
|
|
132
|
+
signaturesOrAddresses.length,
|
|
133
|
+
signaturesOrAddresses,
|
|
104
134
|
);
|
|
105
135
|
}
|
|
106
136
|
|
|
@@ -118,10 +148,26 @@ export function deserializeValidateCheckpointResult(bufferOrReader: Buffer | Buf
|
|
|
118
148
|
const attestors = reader.readVector(EthAddress, MAX_COMMITTEE_SIZE);
|
|
119
149
|
const attestations = reader.readVector(CommitteeAttestation, MAX_COMMITTEE_SIZE);
|
|
120
150
|
const invalidIndex = reader.readNumber();
|
|
151
|
+
const verbatimAttestations: ViemCommitteeAttestations = {
|
|
152
|
+
signatureIndices: bufferToHex(reader.readBuffer()),
|
|
153
|
+
signaturesOrAddresses: bufferToHex(reader.readBuffer()),
|
|
154
|
+
};
|
|
155
|
+
|
|
121
156
|
if (reason === 'insufficient-attestations') {
|
|
122
|
-
return { valid, reason, checkpoint, committee, epoch, seed, attestors, attestations };
|
|
157
|
+
return { valid, reason, checkpoint, committee, epoch, seed, attestors, attestations, verbatimAttestations };
|
|
123
158
|
} else if (reason === 'invalid-attestation') {
|
|
124
|
-
return {
|
|
159
|
+
return {
|
|
160
|
+
valid,
|
|
161
|
+
reason,
|
|
162
|
+
checkpoint,
|
|
163
|
+
committee,
|
|
164
|
+
epoch,
|
|
165
|
+
seed,
|
|
166
|
+
attestors,
|
|
167
|
+
invalidIndex,
|
|
168
|
+
attestations,
|
|
169
|
+
verbatimAttestations,
|
|
170
|
+
};
|
|
125
171
|
} else {
|
|
126
172
|
const _: never = reason;
|
|
127
173
|
throw new Error(`Unknown reason: ${reason}`);
|
package/src/checkpoint/index.ts
CHANGED
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
import {
|
|
2
|
+
type FeeHeader,
|
|
3
|
+
RollupContract,
|
|
4
|
+
SimulationOverridesBuilder,
|
|
5
|
+
type SimulationOverridesPlan,
|
|
6
|
+
} from '@aztec/ethereum/contracts';
|
|
7
|
+
import { CheckpointNumber } from '@aztec/foundation/branded-types';
|
|
8
|
+
import type { Logger } from '@aztec/foundation/log';
|
|
9
|
+
|
|
10
|
+
import type { CoordinationSignatureContext } from '../p2p/signature_utils.js';
|
|
11
|
+
import type { ProposedCheckpointData } from './checkpoint_data.js';
|
|
12
|
+
import { computeCheckpointPayloadDigest } from './digest.js';
|
|
13
|
+
|
|
14
|
+
type CheckpointSimulationOverridesPlanInput = {
|
|
15
|
+
/** Target rollup contract. */
|
|
16
|
+
rollup: RollupContract;
|
|
17
|
+
/** Checkpoint number to be proposed. */
|
|
18
|
+
checkpointNumber: CheckpointNumber;
|
|
19
|
+
/** Logger instance. */
|
|
20
|
+
log: Logger;
|
|
21
|
+
/**
|
|
22
|
+
* The proposed parent checkpoint when pipelining. Its `checkpointNumber` must equal
|
|
23
|
+
* `checkpointNumber - 1`; the helper enforces this. Mutually exclusive with
|
|
24
|
+
* `invalidateToPendingCheckpointNumber`.
|
|
25
|
+
*/
|
|
26
|
+
proposedCheckpointData?: ProposedCheckpointData;
|
|
27
|
+
/**
|
|
28
|
+
* The pending checkpoint number we'll end up at after invalidation lands. Mutually exclusive
|
|
29
|
+
* with `proposedCheckpointData`.
|
|
30
|
+
*/
|
|
31
|
+
invalidateToPendingCheckpointNumber?: CheckpointNumber;
|
|
32
|
+
/**
|
|
33
|
+
* The real on-chain pending checkpoint number (typically `syncedTo.checkpointedCheckpointNumber`).
|
|
34
|
+
* Used as the snapshot we pin both `pending` and `proven` to avoid prunes in simulation.
|
|
35
|
+
*/
|
|
36
|
+
checkpointedCheckpointNumber: CheckpointNumber;
|
|
37
|
+
/**
|
|
38
|
+
* Chain-level consensus signature context. Used to recompute the parent's `payloadDigest` for the
|
|
39
|
+
* pipelined simulation override so it matches what `propose` will write into `tempCheckpointLogs[parent]`
|
|
40
|
+
* once the parent lands.
|
|
41
|
+
*/
|
|
42
|
+
signatureContext: CoordinationSignatureContext;
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Builds the SimulationOverridesPlan describing the simulated L1 rollup state for a checkpoint's
|
|
47
|
+
* enqueue-time simulations: `canProposeAt` (in Sequencer.doWork) and the propose-related sims
|
|
48
|
+
* (validateBlockHeader, simulateProposeTx). The plan reflects "as if our pipelined parent
|
|
49
|
+
* checkpoint has landed and any required invalidation has executed" — the gap that needs to be
|
|
50
|
+
* bridged at enqueue time.
|
|
51
|
+
*
|
|
52
|
+
* Pipelining (`proposedCheckpointData`) and invalidation (`invalidateToPendingCheckpointNumber`)
|
|
53
|
+
* are mutually exclusive; passing both throws.
|
|
54
|
+
*/
|
|
55
|
+
export async function buildCheckpointSimulationOverridesPlan(
|
|
56
|
+
input: CheckpointSimulationOverridesPlanInput,
|
|
57
|
+
): Promise<SimulationOverridesPlan | undefined> {
|
|
58
|
+
if (input.proposedCheckpointData && input.invalidateToPendingCheckpointNumber !== undefined) {
|
|
59
|
+
throw new Error(
|
|
60
|
+
'Error in buildCheckpointSimulationOverridesPlan: proposedCheckpointData and invalidateToPendingCheckpointNumber are mutually exclusive',
|
|
61
|
+
);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
const builder = new SimulationOverridesBuilder();
|
|
65
|
+
const pendingCheckpointNumber = derivePendingCheckpointNumber(input);
|
|
66
|
+
|
|
67
|
+
// Override the latest checkpoint number when invalidating or pipelining, so our checkpoint
|
|
68
|
+
// follows from it. We also override the proven chain tip so we dont need to worry about
|
|
69
|
+
// prunes kicking in that would break out simulation if there's a prune pending. We always
|
|
70
|
+
// assume that a proof will land in time. If we don't have a pending checkpoint number to force,
|
|
71
|
+
// we still set both tips to the current checkpoint number to avoid the prune trigger.
|
|
72
|
+
const overridenChainTip = pendingCheckpointNumber ?? input.checkpointedCheckpointNumber;
|
|
73
|
+
builder.withChainTips({ pending: overridenChainTip, proven: overridenChainTip });
|
|
74
|
+
|
|
75
|
+
if (input.proposedCheckpointData) {
|
|
76
|
+
const { header, archive, checkpointOutHash, feeAssetPriceModifier } = input.proposedCheckpointData;
|
|
77
|
+
builder.withPendingArchive(archive.root);
|
|
78
|
+
// Override every locally-derivable `tempCheckpointLogs[parent]` field that L1 will eventually
|
|
79
|
+
// write. `slotNumber` is load-bearing for `STFLib.canPruneAtTime`: without it the cell reads
|
|
80
|
+
// slotNumber 0, the contract treats the pending tip as belonging to an expired epoch, and
|
|
81
|
+
// `getEffectivePendingCheckpointNumber` silently collapses pending back to proven — producing
|
|
82
|
+
// a spurious `Rollup__InvalidArchive` against the on-chain genesis archive. The other fields
|
|
83
|
+
// (headerHash, outHash, payloadDigest) are not strictly load-bearing for `canProposeAt` /
|
|
84
|
+
// `validateBlockHeader`, but mirroring the full cell keeps the simulation byte-faithful with
|
|
85
|
+
// what the actual `propose()` send will observe, which is a defense against future reads
|
|
86
|
+
// taking dependencies on them.
|
|
87
|
+
builder.withPendingTempCheckpointLogFields({
|
|
88
|
+
headerHash: header.hash(),
|
|
89
|
+
outHash: checkpointOutHash,
|
|
90
|
+
slotNumber: header.slotNumber,
|
|
91
|
+
payloadDigest: computeCheckpointPayloadDigest({
|
|
92
|
+
header,
|
|
93
|
+
archiveRoot: archive.root,
|
|
94
|
+
feeAssetPriceModifier,
|
|
95
|
+
signatureContext: input.signatureContext,
|
|
96
|
+
}),
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
const feeHeader = await computePipelinedParentFeeHeader({
|
|
100
|
+
checkpointNumber: input.checkpointNumber,
|
|
101
|
+
proposedCheckpointData: input.proposedCheckpointData,
|
|
102
|
+
rollup: input.rollup,
|
|
103
|
+
log: input.log,
|
|
104
|
+
});
|
|
105
|
+
if (feeHeader) {
|
|
106
|
+
builder.withPendingFeeHeader(feeHeader);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
return builder.build();
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
function derivePendingCheckpointNumber(input: CheckpointSimulationOverridesPlanInput): CheckpointNumber | undefined {
|
|
114
|
+
if (input.invalidateToPendingCheckpointNumber !== undefined) {
|
|
115
|
+
return input.invalidateToPendingCheckpointNumber;
|
|
116
|
+
}
|
|
117
|
+
if (!input.proposedCheckpointData) {
|
|
118
|
+
return undefined;
|
|
119
|
+
}
|
|
120
|
+
if (input.checkpointNumber < 1) {
|
|
121
|
+
throw new Error(`Cannot build simulation override for checkpoint ${input.checkpointNumber}: no parent exists`);
|
|
122
|
+
}
|
|
123
|
+
const expectedParent = CheckpointNumber(input.checkpointNumber - 1);
|
|
124
|
+
if (input.proposedCheckpointData.checkpointNumber !== expectedParent) {
|
|
125
|
+
throw new Error(
|
|
126
|
+
`Cannot build simulation override for checkpoint ${input.checkpointNumber}: proposedCheckpointData.checkpointNumber (${input.proposedCheckpointData.checkpointNumber}) does not match expected parent ${expectedParent}`,
|
|
127
|
+
);
|
|
128
|
+
}
|
|
129
|
+
return expectedParent;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
type PipelinedParentFeeHeaderInput = {
|
|
133
|
+
checkpointNumber: CheckpointNumber;
|
|
134
|
+
proposedCheckpointData: ProposedCheckpointData;
|
|
135
|
+
rollup: RollupContract;
|
|
136
|
+
log: Logger;
|
|
137
|
+
};
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* Derives the pending parent fee header used during pipelined proposal simulation. Returns
|
|
141
|
+
* `undefined` only when no grandparent exists (i.e. the proposed parent is the genesis
|
|
142
|
+
* checkpoint); all other failure modes (missing grandparent state, missing fee header, RPC
|
|
143
|
+
* errors) throw so callers don't silently desync the fee-header override.
|
|
144
|
+
*/
|
|
145
|
+
export async function computePipelinedParentFeeHeader(
|
|
146
|
+
input: PipelinedParentFeeHeaderInput,
|
|
147
|
+
): Promise<FeeHeader | undefined> {
|
|
148
|
+
if (input.checkpointNumber < 2) {
|
|
149
|
+
return undefined;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
const grandparentCheckpointNumber = CheckpointNumber(input.checkpointNumber - 2);
|
|
153
|
+
|
|
154
|
+
const [grandparentCheckpoint, manaTarget] = await Promise.all([
|
|
155
|
+
input.rollup.getCheckpoint(grandparentCheckpointNumber),
|
|
156
|
+
input.rollup.getManaTarget(),
|
|
157
|
+
]);
|
|
158
|
+
|
|
159
|
+
if (!grandparentCheckpoint?.feeHeader) {
|
|
160
|
+
throw new Error(
|
|
161
|
+
`Grandparent checkpoint or feeHeader missing for checkpoint ${grandparentCheckpointNumber.toString()}`,
|
|
162
|
+
);
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
return RollupContract.computeChildFeeHeader(
|
|
166
|
+
grandparentCheckpoint.feeHeader,
|
|
167
|
+
input.proposedCheckpointData.totalManaUsed,
|
|
168
|
+
input.proposedCheckpointData.feeAssetPriceModifier,
|
|
169
|
+
manaTarget,
|
|
170
|
+
);
|
|
171
|
+
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type L1ContractsConfig, l1ContractsConfigMappings } from '@aztec/ethereum/config';
|
|
1
|
+
import { type L1ContractsConfig, l1ContractsConfigMappings, validateSlotDurations } from '@aztec/ethereum/config';
|
|
2
2
|
import { type EnvVar, pickConfigMappings } from '@aztec/foundation/config';
|
|
3
3
|
|
|
4
4
|
import type { SequencerConfig } from '../interfaces/configs.js';
|
|
@@ -156,21 +156,10 @@ export function validateNetworkConsensusConfig(config: NetworkConsensusConfig):
|
|
|
156
156
|
return errors;
|
|
157
157
|
}
|
|
158
158
|
|
|
159
|
-
|
|
160
|
-
errors.push(`ethereumSlotDuration must be positive (got ${config.ethereumSlotDuration})`);
|
|
161
|
-
}
|
|
159
|
+
errors.push(...validateSlotDurations(config));
|
|
162
160
|
if (config.blockDurationMs <= 0) {
|
|
163
161
|
errors.push(`blockDurationMs must be positive (got ${config.blockDurationMs})`);
|
|
164
162
|
}
|
|
165
|
-
if (config.aztecSlotDuration <= 0) {
|
|
166
|
-
errors.push(`aztecSlotDuration must be positive (got ${config.aztecSlotDuration})`);
|
|
167
|
-
}
|
|
168
|
-
if (config.ethereumSlotDuration > 0 && config.aztecSlotDuration % config.ethereumSlotDuration !== 0) {
|
|
169
|
-
errors.push(
|
|
170
|
-
`aztecSlotDuration (${config.aztecSlotDuration}s) must be a multiple of ethereumSlotDuration ` +
|
|
171
|
-
`(${config.ethereumSlotDuration}s)`,
|
|
172
|
-
);
|
|
173
|
-
}
|
|
174
163
|
if (config.blockDurationMs / 1000 > config.aztecSlotDuration) {
|
|
175
164
|
errors.push(
|
|
176
165
|
`blockDurationMs (${config.blockDurationMs}ms) exceeds aztecSlotDuration (${config.aztecSlotDuration}s)`,
|
|
@@ -6,7 +6,8 @@ import { type FunctionAbi, FunctionSelector, encodeArguments } from '../abi/inde
|
|
|
6
6
|
import type { AztecAddress } from '../aztec-address/index.js';
|
|
7
7
|
import { computeVarArgsHash } from '../hash/hash.js';
|
|
8
8
|
import { computeAddress } from '../keys/index.js';
|
|
9
|
-
import type { ContractInstance } from './interfaces/contract_instance.js';
|
|
9
|
+
import type { ContractInstance, ContractInstancePreimage } from './interfaces/contract_instance.js';
|
|
10
|
+
import type { PartialAddress } from './partial_address.js';
|
|
10
11
|
|
|
11
12
|
// TODO(@spalladino): Review all generator indices in this file
|
|
12
13
|
|
|
@@ -21,7 +22,7 @@ import type { ContractInstance } from './interfaces/contract_instance.js';
|
|
|
21
22
|
*/
|
|
22
23
|
export async function computeContractAddressFromInstance(
|
|
23
24
|
instance:
|
|
24
|
-
|
|
|
25
|
+
| ContractInstancePreimage
|
|
25
26
|
| ({ originalContractClassId: Fr; saltedInitializationHash: Fr } & Pick<ContractInstance, 'publicKeys'>),
|
|
26
27
|
): Promise<AztecAddress> {
|
|
27
28
|
const partialAddress = await computePartialAddress(instance);
|
|
@@ -36,7 +37,7 @@ export async function computePartialAddress(
|
|
|
36
37
|
instance:
|
|
37
38
|
| Pick<ContractInstance, 'originalContractClassId' | 'initializationHash' | 'salt' | 'deployer' | 'immutablesHash'>
|
|
38
39
|
| { originalContractClassId: Fr; saltedInitializationHash: Fr },
|
|
39
|
-
): Promise<
|
|
40
|
+
): Promise<PartialAddress> {
|
|
40
41
|
const saltedInitializationHash =
|
|
41
42
|
'saltedInitializationHash' in instance
|
|
42
43
|
? instance.saltedInitializationHash
|
|
@@ -18,7 +18,12 @@ import {
|
|
|
18
18
|
computeInitializationHash,
|
|
19
19
|
computeInitializationHashFromEncodedArgs,
|
|
20
20
|
} from './contract_address.js';
|
|
21
|
-
import type {
|
|
21
|
+
import type {
|
|
22
|
+
ContractInstance,
|
|
23
|
+
ContractInstancePreimage,
|
|
24
|
+
ContractInstancePreimageWithAddress,
|
|
25
|
+
ContractInstanceWithAddress,
|
|
26
|
+
} from './interfaces/contract_instance.js';
|
|
22
27
|
|
|
23
28
|
const VERSION = 2 as const;
|
|
24
29
|
|
|
@@ -115,6 +120,62 @@ export class SerializableContractInstance {
|
|
|
115
120
|
}
|
|
116
121
|
}
|
|
117
122
|
|
|
123
|
+
export class SerializableContractInstancePreimage {
|
|
124
|
+
public readonly version = VERSION;
|
|
125
|
+
public readonly salt: Fr;
|
|
126
|
+
public readonly deployer: AztecAddress;
|
|
127
|
+
public readonly originalContractClassId: Fr;
|
|
128
|
+
public readonly initializationHash: Fr;
|
|
129
|
+
public readonly immutablesHash: Fr;
|
|
130
|
+
public readonly publicKeys: PublicKeys;
|
|
131
|
+
|
|
132
|
+
constructor(instance: ContractInstancePreimage) {
|
|
133
|
+
if (instance.version !== VERSION) {
|
|
134
|
+
throw new Error(`Unexpected contract class version ${instance.version}`);
|
|
135
|
+
}
|
|
136
|
+
this.salt = instance.salt;
|
|
137
|
+
this.deployer = instance.deployer;
|
|
138
|
+
this.originalContractClassId = instance.originalContractClassId;
|
|
139
|
+
this.initializationHash = instance.initializationHash;
|
|
140
|
+
this.immutablesHash = instance.immutablesHash;
|
|
141
|
+
this.publicKeys = instance.publicKeys;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
public toBuffer() {
|
|
145
|
+
return serializeToBuffer(
|
|
146
|
+
numToUInt8(this.version),
|
|
147
|
+
this.salt,
|
|
148
|
+
this.deployer,
|
|
149
|
+
this.originalContractClassId,
|
|
150
|
+
this.initializationHash,
|
|
151
|
+
this.immutablesHash,
|
|
152
|
+
this.publicKeys,
|
|
153
|
+
);
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
/** Returns a copy of this object with its address included. */
|
|
157
|
+
withAddress(address: AztecAddress): ContractInstancePreimageWithAddress {
|
|
158
|
+
return { ...this, address };
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
static fromBuffer(bufferOrReader: Buffer | BufferReader): SerializableContractInstancePreimage {
|
|
162
|
+
const reader = BufferReader.asReader(bufferOrReader);
|
|
163
|
+
const version = reader.readUInt8();
|
|
164
|
+
if (version !== VERSION) {
|
|
165
|
+
throw new Error(`Unexpected contract instance preimage version ${version}`);
|
|
166
|
+
}
|
|
167
|
+
return new SerializableContractInstancePreimage({
|
|
168
|
+
version: VERSION,
|
|
169
|
+
salt: reader.readObject(Fr),
|
|
170
|
+
deployer: reader.readObject(AztecAddress),
|
|
171
|
+
originalContractClassId: reader.readObject(Fr),
|
|
172
|
+
initializationHash: reader.readObject(Fr),
|
|
173
|
+
immutablesHash: reader.readObject(Fr),
|
|
174
|
+
publicKeys: reader.readObject(PublicKeys),
|
|
175
|
+
});
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
|
|
118
179
|
/**
|
|
119
180
|
* Generates a Contract Instance from some instantiation params.
|
|
120
181
|
* @param artifact - The account contract build artifact.
|
|
@@ -25,11 +25,9 @@ export interface ContractDataSource {
|
|
|
25
25
|
/**
|
|
26
26
|
* Returns a publicly deployed contract instance given its address.
|
|
27
27
|
* @param address - Address of the deployed contract.
|
|
28
|
-
* @param timestamp - Timestamp at which to
|
|
29
|
-
* be used.
|
|
30
|
-
* TODO(#15170): Fix the implementations ignoring the timestamp param and make timestamp required.
|
|
28
|
+
* @param timestamp - Timestamp at which to resolve the contract instance's current class id.
|
|
31
29
|
*/
|
|
32
|
-
getContract(address: AztecAddress, timestamp
|
|
30
|
+
getContract(address: AztecAddress, timestamp: UInt64): Promise<ContractInstanceWithAddress | undefined>;
|
|
33
31
|
|
|
34
32
|
/**
|
|
35
33
|
* Returns the list of all class ids known.
|
|
@@ -9,19 +9,19 @@ import { schemas, zodFor } from '../../schemas/index.js';
|
|
|
9
9
|
const VERSION = 2 as const;
|
|
10
10
|
|
|
11
11
|
/**
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
12
|
+
* The address preimage of a contract instance: the immutable data that hashes to its address, i.e. everything a
|
|
13
|
+
* contract deployment commits to.
|
|
14
|
+
*
|
|
15
|
+
* Note that `originaContractClassId` is not necessarily the instance's _current_ class id, in case of upgrades: that
|
|
16
|
+
* one is not part of the preimage and is instead derived from chain state.
|
|
15
17
|
*/
|
|
16
|
-
export interface
|
|
18
|
+
export interface ContractInstancePreimage {
|
|
17
19
|
/** Version identifier. Initially one, bumped for any changes to the contract instance struct. */
|
|
18
20
|
version: typeof VERSION;
|
|
19
21
|
/** User-generated pseudorandom value for uniqueness. */
|
|
20
22
|
salt: Fr;
|
|
21
23
|
/** Optional deployer address or zero if this was a universal deploy. */
|
|
22
24
|
deployer: AztecAddress;
|
|
23
|
-
/** Identifier of the contract class for this instance. */
|
|
24
|
-
currentContractClassId: Fr;
|
|
25
25
|
/** Identifier of the original (at deployment) contract class for this instance */
|
|
26
26
|
originalContractClassId: Fr;
|
|
27
27
|
/** Hash of the selector and arguments to the constructor. */
|
|
@@ -32,14 +32,24 @@ export interface ContractInstance {
|
|
|
32
32
|
publicKeys: PublicKeys;
|
|
33
33
|
}
|
|
34
34
|
|
|
35
|
+
/**
|
|
36
|
+
* The address preimage plus the current contract class id, which is chain-tracked state derived from the
|
|
37
|
+
* ContractInstanceRegistry (it equals the original class id unless the contract has been upgraded).
|
|
38
|
+
*/
|
|
39
|
+
export interface ContractInstance extends ContractInstancePreimage {
|
|
40
|
+
/** Identifier of the contract class this instance currently runs (as of some block). */
|
|
41
|
+
currentContractClassId: Fr;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export type ContractInstancePreimageWithAddress = ContractInstancePreimage & { address: AztecAddress };
|
|
45
|
+
|
|
35
46
|
export type ContractInstanceWithAddress = ContractInstance & { address: AztecAddress };
|
|
36
47
|
|
|
37
|
-
export const
|
|
48
|
+
export const ContractInstancePreimageSchema = zodFor<ContractInstancePreimage>()(
|
|
38
49
|
z.object({
|
|
39
50
|
version: z.literal(VERSION),
|
|
40
51
|
salt: schemas.Fr,
|
|
41
52
|
deployer: schemas.AztecAddress,
|
|
42
|
-
currentContractClassId: schemas.Fr,
|
|
43
53
|
originalContractClassId: schemas.Fr,
|
|
44
54
|
initializationHash: schemas.Fr,
|
|
45
55
|
immutablesHash: schemas.Fr,
|
|
@@ -47,6 +57,14 @@ export const ContractInstanceSchema = zodFor<ContractInstance>()(
|
|
|
47
57
|
}),
|
|
48
58
|
);
|
|
49
59
|
|
|
60
|
+
export const ContractInstanceSchema = zodFor<ContractInstance>()(
|
|
61
|
+
ContractInstancePreimageSchema.and(z.object({ currentContractClassId: schemas.Fr })),
|
|
62
|
+
);
|
|
63
|
+
|
|
64
|
+
export const ContractInstancePreimageWithAddressSchema = zodFor<ContractInstancePreimageWithAddress>()(
|
|
65
|
+
ContractInstancePreimageSchema.and(z.object({ address: schemas.AztecAddress })),
|
|
66
|
+
);
|
|
67
|
+
|
|
50
68
|
export const ContractInstanceWithAddressSchema = zodFor<ContractInstanceWithAddress>()(
|
|
51
69
|
ContractInstanceSchema.and(z.object({ address: schemas.AztecAddress })),
|
|
52
70
|
);
|
|
@@ -1,7 +1,13 @@
|
|
|
1
1
|
import type { Fr } from '@aztec/foundation/curves/bn254';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
|
-
*
|
|
5
|
-
*
|
|
4
|
+
* The contract-side preimage of an Aztec address, i.e. the commitment to a specific contract instance.
|
|
5
|
+
*
|
|
6
|
+
* A partial address commits to a contract's code and initialization
|
|
7
|
+
* (`hash(contract_class_id, salted_initialization_hash)`) but not to its keys. Combined with an account's `PublicKeys`,
|
|
8
|
+
* it fully determines the address: `address = (hash(public_keys_hash, partial_address) * G + Ivpk_m).x`. Two accounts
|
|
9
|
+
* therefore share an address only if they share both their public keys and their partial address.
|
|
10
|
+
*
|
|
11
|
+
* See `computePartialAddress` for the derivation.
|
|
6
12
|
*/
|
|
7
13
|
export type PartialAddress = Fr;
|