@aztec/archiver 4.4.0-nightly.20260617 → 4.4.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/modules/data_store_updater.d.ts +1 -1
- package/dest/modules/data_store_updater.d.ts.map +1 -1
- package/dest/modules/data_store_updater.js +8 -7
- package/dest/store/block_store.d.ts +7 -2
- package/dest/store/block_store.d.ts.map +1 -1
- package/dest/store/block_store.js +113 -1
- package/dest/store/contract_class_store.d.ts +1 -1
- package/dest/store/contract_class_store.d.ts.map +1 -1
- package/dest/store/contract_class_store.js +12 -0
- package/dest/store/contract_instance_store.d.ts +1 -1
- package/dest/store/contract_instance_store.d.ts.map +1 -1
- package/dest/store/contract_instance_store.js +11 -0
- package/dest/store/l2_tips_cache.d.ts +5 -6
- package/dest/store/l2_tips_cache.d.ts.map +1 -1
- package/dest/store/l2_tips_cache.js +6 -75
- package/dest/store/log_store.d.ts +1 -1
- package/dest/store/log_store.d.ts.map +1 -1
- package/dest/store/log_store.js +20 -9
- package/package.json +13 -13
- package/src/modules/data_store_updater.ts +8 -7
- package/src/store/block_store.ts +135 -0
- package/src/store/contract_class_store.ts +12 -0
- package/src/store/contract_instance_store.ts +11 -0
- package/src/store/l2_tips_cache.ts +7 -69
- package/src/store/log_store.ts +22 -9
|
@@ -85,4 +85,4 @@ export declare class ArchiverDataStoreUpdater {
|
|
|
85
85
|
private storeBroadcastedIndividualFunctions;
|
|
86
86
|
}
|
|
87
87
|
export {};
|
|
88
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
88
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGF0YV9zdG9yZV91cGRhdGVyLmQudHMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvbW9kdWxlcy9kYXRhX3N0b3JlX3VwZGF0ZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFdBQVcsRUFBRSxnQkFBZ0IsRUFBRSxNQUFNLGlDQUFpQyxDQUFDO0FBYWhGLE9BQU8sS0FBSyxFQUFFLE9BQU8sRUFBRSx3QkFBd0IsRUFBRSxNQUFNLHFCQUFxQixDQUFDO0FBQzdFLE9BQU8sRUFBRSxLQUFLLG1CQUFtQixFQUFzQixNQUFNLDBCQUEwQixDQUFDO0FBZXhGLE9BQU8sS0FBSyxFQUFFLG1CQUFtQixFQUFFLE1BQU0sK0JBQStCLENBQUM7QUFDekUsT0FBTyxLQUFLLEVBQUUsV0FBVyxFQUFFLE1BQU0sMkJBQTJCLENBQUM7QUFRN0QsNkVBQTZFO0FBQzdFLEtBQUssMEJBQTBCLEdBQUc7SUFDaEMsbUVBQW1FO0lBQ25FLFlBQVksRUFBRSxPQUFPLEVBQUUsR0FBRyxTQUFTLENBQUM7SUFDcEMsaUZBQWlGO0lBQ2pGLDhCQUE4QixFQUFFLFdBQVcsR0FBRyxTQUFTLENBQUM7Q0FDekQsQ0FBQztBQUVGLGtFQUFrRTtBQUNsRSxxQkFBYSx3QkFBd0I7SUFJakMsT0FBTyxDQUFDLEtBQUs7SUFDYixPQUFPLENBQUMsV0FBVyxDQUFDO0lBQ3BCLE9BQU8sQ0FBQyxJQUFJO0lBTGQsT0FBTyxDQUFDLFFBQVEsQ0FBQyxHQUFHLENBQTBDO0lBRTlELFlBQ1UsS0FBSyxFQUFFLG1CQUFtQixFQUMxQixXQUFXLENBQUMseUJBQWEsRUFDekIsSUFBSSxHQUFFO1FBQUUsZUFBZSxDQUFDLEVBQUUsTUFBTSxDQUFBO0tBQU8sRUFDN0M7SUFFSjs7Ozs7Ozs7O09BU0c7SUFDVSxnQkFBZ0IsQ0FDM0IsS0FBSyxFQUFFLE9BQU8sRUFDZCw0QkFBNEIsQ0FBQyxFQUFFLHdCQUF3QixHQUN0RCxPQUFPLENBQUMsT0FBTyxDQUFDLENBaUJsQjtJQUVEOzs7Ozs7Ozs7O09BVUc7SUFDVSxjQUFjLENBQ3pCLFdBQVcsRUFBRSxtQkFBbUIsRUFBRSxFQUNsQyw0QkFBNEIsQ0FBQyxFQUFFLHdCQUF3QixHQUN0RCxPQUFPLENBQUMsMEJBQTBCLENBQUMsQ0E2QnJDO1lBUWEsMkJBQTJCO0lBbUV6Qzs7Ozs7Ozs7T0FRRztJQUNVLCtCQUErQixDQUFDLFdBQVcsRUFBRSxXQUFXLEdBQUcsT0FBTyxDQUFDLE9BQU8sRUFBRSxDQUFDLENBZXpGO1lBTWEsaUJBQWlCO0lBYS9COzs7Ozs7OztPQVFHO0lBQ1Usc0JBQXNCLENBQUMsZ0JBQWdCLEVBQUUsZ0JBQWdCLEdBQUcsT0FBTyxDQUFDLE9BQU8sQ0FBQyxDQWdCeEY7SUFFRDs7O09BR0c7SUFDVSx5QkFBeUIsQ0FBQyxnQkFBZ0IsRUFBRSxnQkFBZ0IsR0FBRyxPQUFPLENBQUMsSUFBSSxDQUFDLENBS3hGO0lBRUQ7OztPQUdHO0lBQ1UsNEJBQTRCLENBQUMsZ0JBQWdCLEVBQUUsZ0JBQWdCLEdBQUcsT0FBTyxDQUFDLElBQUksQ0FBQyxDQUszRjtJQUVELDZEQUE2RDtJQUM3RCxPQUFPLENBQUMsbUJBQW1CO0lBSTNCLHFEQUFxRDtJQUNyRCxPQUFPLENBQUMsd0JBQXdCO1lBS2xCLHNCQUFzQjtZQW9CdEIsOEJBQThCO1lBK0M5QiwrQkFBK0I7WUEwQy9CLDhCQUE4QjtZQTZCOUIsbUNBQW1DO0NBd0RsRCJ9
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"data_store_updater.d.ts","sourceRoot":"","sources":["../../src/modules/data_store_updater.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,iCAAiC,CAAC;AAahF,OAAO,KAAK,EAAE,OAAO,EAAE,wBAAwB,EAAE,MAAM,qBAAqB,CAAC;AAC7E,OAAO,EAAE,KAAK,mBAAmB,EAAsB,MAAM,0BAA0B,CAAC;AAexF,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,+BAA+B,CAAC;AACzE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AAQ7D,6EAA6E;AAC7E,KAAK,0BAA0B,GAAG;IAChC,mEAAmE;IACnE,YAAY,EAAE,OAAO,EAAE,GAAG,SAAS,CAAC;IACpC,iFAAiF;IACjF,8BAA8B,EAAE,WAAW,GAAG,SAAS,CAAC;CACzD,CAAC;AAEF,kEAAkE;AAClE,qBAAa,wBAAwB;IAIjC,OAAO,CAAC,KAAK;IACb,OAAO,CAAC,WAAW,CAAC;IACpB,OAAO,CAAC,IAAI;IALd,OAAO,CAAC,QAAQ,CAAC,GAAG,CAA0C;IAE9D,YACU,KAAK,EAAE,mBAAmB,EAC1B,WAAW,CAAC,yBAAa,EACzB,IAAI,GAAE;QAAE,eAAe,CAAC,EAAE,MAAM,CAAA;KAAO,EAC7C;IAEJ;;;;;;;;;OASG;IACU,gBAAgB,CAC3B,KAAK,EAAE,OAAO,EACd,4BAA4B,CAAC,EAAE,wBAAwB,GACtD,OAAO,CAAC,OAAO,CAAC,CAiBlB;IAED;;;;;;;;;;OAUG;IACU,cAAc,CACzB,WAAW,EAAE,mBAAmB,EAAE,EAClC,4BAA4B,CAAC,EAAE,wBAAwB,GACtD,OAAO,CAAC,0BAA0B,CAAC,CA6BrC;YAQa,2BAA2B;IAmEzC;;;;;;;;OAQG;IACU,+BAA+B,CAAC,WAAW,EAAE,WAAW,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC,CAezF;YAMa,iBAAiB;IAa/B;;;;;;;;OAQG;IACU,sBAAsB,CAAC,gBAAgB,EAAE,gBAAgB,GAAG,OAAO,CAAC,OAAO,CAAC,
|
|
1
|
+
{"version":3,"file":"data_store_updater.d.ts","sourceRoot":"","sources":["../../src/modules/data_store_updater.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,iCAAiC,CAAC;AAahF,OAAO,KAAK,EAAE,OAAO,EAAE,wBAAwB,EAAE,MAAM,qBAAqB,CAAC;AAC7E,OAAO,EAAE,KAAK,mBAAmB,EAAsB,MAAM,0BAA0B,CAAC;AAexF,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,+BAA+B,CAAC;AACzE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AAQ7D,6EAA6E;AAC7E,KAAK,0BAA0B,GAAG;IAChC,mEAAmE;IACnE,YAAY,EAAE,OAAO,EAAE,GAAG,SAAS,CAAC;IACpC,iFAAiF;IACjF,8BAA8B,EAAE,WAAW,GAAG,SAAS,CAAC;CACzD,CAAC;AAEF,kEAAkE;AAClE,qBAAa,wBAAwB;IAIjC,OAAO,CAAC,KAAK;IACb,OAAO,CAAC,WAAW,CAAC;IACpB,OAAO,CAAC,IAAI;IALd,OAAO,CAAC,QAAQ,CAAC,GAAG,CAA0C;IAE9D,YACU,KAAK,EAAE,mBAAmB,EAC1B,WAAW,CAAC,yBAAa,EACzB,IAAI,GAAE;QAAE,eAAe,CAAC,EAAE,MAAM,CAAA;KAAO,EAC7C;IAEJ;;;;;;;;;OASG;IACU,gBAAgB,CAC3B,KAAK,EAAE,OAAO,EACd,4BAA4B,CAAC,EAAE,wBAAwB,GACtD,OAAO,CAAC,OAAO,CAAC,CAiBlB;IAED;;;;;;;;;;OAUG;IACU,cAAc,CACzB,WAAW,EAAE,mBAAmB,EAAE,EAClC,4BAA4B,CAAC,EAAE,wBAAwB,GACtD,OAAO,CAAC,0BAA0B,CAAC,CA6BrC;YAQa,2BAA2B;IAmEzC;;;;;;;;OAQG;IACU,+BAA+B,CAAC,WAAW,EAAE,WAAW,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC,CAezF;YAMa,iBAAiB;IAa/B;;;;;;;;OAQG;IACU,sBAAsB,CAAC,gBAAgB,EAAE,gBAAgB,GAAG,OAAO,CAAC,OAAO,CAAC,CAgBxF;IAED;;;OAGG;IACU,yBAAyB,CAAC,gBAAgB,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC,CAKxF;IAED;;;OAGG;IACU,4BAA4B,CAAC,gBAAgB,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC,CAK3F;IAED,6DAA6D;IAC7D,OAAO,CAAC,mBAAmB;IAI3B,qDAAqD;IACrD,OAAO,CAAC,wBAAwB;YAKlB,sBAAsB;YAoBtB,8BAA8B;YA+C9B,+BAA+B;YA0C/B,8BAA8B;YA6B9B,mCAAmC;CAwDlD"}
|
|
@@ -45,9 +45,9 @@ import groupBy from 'lodash.groupby';
|
|
|
45
45
|
// Unroll all logs emitted during the retrieved block and extract any contract classes and instances from it
|
|
46
46
|
this.addContractDataToDb(block)
|
|
47
47
|
]);
|
|
48
|
-
await this.l2TipsCache?.refresh();
|
|
49
48
|
return opResults.every(Boolean);
|
|
50
49
|
});
|
|
50
|
+
await this.l2TipsCache?.refresh();
|
|
51
51
|
return result;
|
|
52
52
|
}
|
|
53
53
|
/**
|
|
@@ -80,12 +80,12 @@ import groupBy from 'lodash.groupby';
|
|
|
80
80
|
// Unroll all logs emitted during the retrieved blocks and extract any contract classes and instances from them
|
|
81
81
|
...newBlocks.map((block)=>this.addContractDataToDb(block))
|
|
82
82
|
]);
|
|
83
|
-
await this.l2TipsCache?.refresh();
|
|
84
83
|
return {
|
|
85
84
|
prunedBlocks,
|
|
86
85
|
lastAlreadyInsertedBlockNumber
|
|
87
86
|
};
|
|
88
87
|
});
|
|
88
|
+
await this.l2TipsCache?.refresh();
|
|
89
89
|
return result;
|
|
90
90
|
}
|
|
91
91
|
/**
|
|
@@ -172,9 +172,9 @@ import groupBy from 'lodash.groupby';
|
|
|
172
172
|
throw new Error(`Cannot remove blocks after ${blockNumber} because checkpointed blocks exist up to ${lastCheckpointedBlockNumber}`);
|
|
173
173
|
}
|
|
174
174
|
const result = await this.removeBlocksAfter(blockNumber);
|
|
175
|
-
await this.l2TipsCache?.refresh();
|
|
176
175
|
return result;
|
|
177
176
|
});
|
|
177
|
+
await this.l2TipsCache?.refresh();
|
|
178
178
|
return result;
|
|
179
179
|
}
|
|
180
180
|
/**
|
|
@@ -199,7 +199,7 @@ import groupBy from 'lodash.groupby';
|
|
|
199
199
|
* @param checkpointNumber - Remove all checkpoints strictly after this one.
|
|
200
200
|
* @returns True if the operation is successful.
|
|
201
201
|
*/ async removeCheckpointsAfter(checkpointNumber) {
|
|
202
|
-
|
|
202
|
+
const result = await this.store.transactionAsync(async ()=>{
|
|
203
203
|
const { blocksRemoved = [] } = await this.store.removeCheckpointsAfter(checkpointNumber);
|
|
204
204
|
const opResults = await Promise.all([
|
|
205
205
|
// Prune rolls back to the last proven block, which is by definition valid
|
|
@@ -210,9 +210,10 @@ import groupBy from 'lodash.groupby';
|
|
|
210
210
|
...blocksRemoved.map((block)=>this.removeContractDataFromDb(block)),
|
|
211
211
|
this.store.deleteLogs(blocksRemoved)
|
|
212
212
|
]);
|
|
213
|
-
await this.l2TipsCache?.refresh();
|
|
214
213
|
return opResults.every(Boolean);
|
|
215
214
|
});
|
|
215
|
+
await this.l2TipsCache?.refresh();
|
|
216
|
+
return result;
|
|
216
217
|
}
|
|
217
218
|
/**
|
|
218
219
|
* Updates the proven checkpoint number and refreshes the L2 tips cache.
|
|
@@ -220,8 +221,8 @@ import groupBy from 'lodash.groupby';
|
|
|
220
221
|
*/ async setProvenCheckpointNumber(checkpointNumber) {
|
|
221
222
|
await this.store.transactionAsync(async ()=>{
|
|
222
223
|
await this.store.setProvenCheckpointNumber(checkpointNumber);
|
|
223
|
-
await this.l2TipsCache?.refresh();
|
|
224
224
|
});
|
|
225
|
+
await this.l2TipsCache?.refresh();
|
|
225
226
|
}
|
|
226
227
|
/**
|
|
227
228
|
* Updates the finalized checkpoint number and refreshes the L2 tips cache.
|
|
@@ -229,8 +230,8 @@ import groupBy from 'lodash.groupby';
|
|
|
229
230
|
*/ async setFinalizedCheckpointNumber(checkpointNumber) {
|
|
230
231
|
await this.store.transactionAsync(async ()=>{
|
|
231
232
|
await this.store.setFinalizedCheckpointNumber(checkpointNumber);
|
|
232
|
-
await this.l2TipsCache?.refresh();
|
|
233
233
|
});
|
|
234
|
+
await this.l2TipsCache?.refresh();
|
|
234
235
|
}
|
|
235
236
|
/** Extracts and stores contract data from a single block. */ addContractDataToDb(block) {
|
|
236
237
|
return this.updateContractDataOnDb(block, 0);
|
|
@@ -2,7 +2,7 @@ import { BlockNumber, CheckpointNumber, SlotNumber } from '@aztec/foundation/bra
|
|
|
2
2
|
import { Fr } from '@aztec/foundation/curves/bn254';
|
|
3
3
|
import type { AztecAsyncKVStore } from '@aztec/kv-store';
|
|
4
4
|
import type { AztecAddress } from '@aztec/stdlib/aztec-address';
|
|
5
|
-
import { type BlockData, BlockHash, CheckpointedL2Block, L2Block, type ValidateCheckpointResult } from '@aztec/stdlib/block';
|
|
5
|
+
import { type BlockData, BlockHash, CheckpointedL2Block, L2Block, type L2Tips, type ValidateCheckpointResult } from '@aztec/stdlib/block';
|
|
6
6
|
import { type CheckpointData, PublishedCheckpoint } from '@aztec/stdlib/checkpoint';
|
|
7
7
|
import { type L1RollupConstants } from '@aztec/stdlib/epoch-helpers';
|
|
8
8
|
import { BlockHeader, type IndexedTxEffect, TxHash, TxReceipt } from '@aztec/stdlib/tx';
|
|
@@ -72,6 +72,11 @@ export declare class BlockStore {
|
|
|
72
72
|
removeBlocksAfter(blockNumber: BlockNumber): Promise<L2Block[]>;
|
|
73
73
|
getProvenBlockNumber(): Promise<BlockNumber>;
|
|
74
74
|
getLatestBlockNumber(): Promise<BlockNumber>;
|
|
75
|
+
/**
|
|
76
|
+
* Resolves all L2 chain tips in a single read transaction so the snapshot is internally consistent.
|
|
77
|
+
* The result is guaranteed to satisfy finalized <= proven <= checkpointed <= proposed by block number.
|
|
78
|
+
*/
|
|
79
|
+
getL2TipsData(genesisBlockHash: Fr): Promise<L2Tips>;
|
|
75
80
|
getLatestCheckpointNumber(): Promise<CheckpointNumber>;
|
|
76
81
|
getCheckpointedBlock(number: BlockNumber): Promise<CheckpointedL2Block | undefined>;
|
|
77
82
|
/**
|
|
@@ -193,4 +198,4 @@ export declare class BlockStore {
|
|
|
193
198
|
*/
|
|
194
199
|
setPendingChainValidationStatus(status: ValidateCheckpointResult | undefined): Promise<void>;
|
|
195
200
|
}
|
|
196
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
201
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYmxvY2tfc3RvcmUuZC50cyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9zdG9yZS9ibG9ja19zdG9yZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFDQSxPQUFPLEVBQUUsV0FBVyxFQUFFLGdCQUFnQixFQUF5QixVQUFVLEVBQUUsTUFBTSxpQ0FBaUMsQ0FBQztBQUNuSCxPQUFPLEVBQUUsRUFBRSxFQUFFLE1BQU0sZ0NBQWdDLENBQUM7QUFNcEQsT0FBTyxLQUFLLEVBQUUsaUJBQWlCLEVBQTZDLE1BQU0saUJBQWlCLENBQUM7QUFDcEcsT0FBTyxLQUFLLEVBQUUsWUFBWSxFQUFFLE1BQU0sNkJBQTZCLENBQUM7QUFDaEUsT0FBTyxFQUNMLEtBQUssU0FBUyxFQUNkLFNBQVMsRUFFVCxtQkFBbUIsRUFHbkIsT0FBTyxFQUVQLEtBQUssTUFBTSxFQUNYLEtBQUssd0JBQXdCLEVBRzlCLE1BQU0scUJBQXFCLENBQUM7QUFDN0IsT0FBTyxFQUFFLEtBQUssY0FBYyxFQUFtQixtQkFBbUIsRUFBRSxNQUFNLDBCQUEwQixDQUFDO0FBQ3JHLE9BQU8sRUFBRSxLQUFLLGlCQUFpQixFQUFrQixNQUFNLDZCQUE2QixDQUFDO0FBR3JGLE9BQU8sRUFDTCxXQUFXLEVBQ1gsS0FBSyxlQUFlLEVBRXBCLE1BQU0sRUFDTixTQUFTLEVBSVYsTUFBTSxrQkFBa0IsQ0FBQztBQWMxQixPQUFPLEVBQUUsU0FBUyxFQUFFLEtBQUssUUFBUSxFQUFFLEtBQUssTUFBTSxFQUFFLE1BQU0sa0JBQWtCLENBQUM7QUF1QnpFLE1BQU0sTUFBTSx1QkFBdUIsR0FBRztJQUFFLGFBQWEsRUFBRSxPQUFPLEVBQUUsR0FBRyxTQUFTLENBQUE7Q0FBRSxDQUFDO0FBRS9FOztHQUVHO0FBQ0gscUJBQWEsVUFBVTs7SUF1Q1QsT0FBTyxDQUFDLEVBQUU7SUFBdEIsWUFBb0IsRUFBRSxFQUFFLGlCQUFpQixFQWF4QztJQUVEOzs7O09BSUc7SUFDRyx5QkFBeUIsSUFB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
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"block_store.d.ts","sourceRoot":"","sources":["../../src/store/block_store.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,gBAAgB,EAAyB,UAAU,EAAE,MAAM,iCAAiC,CAAC;AACnH,OAAO,EAAE,EAAE,EAAE,MAAM,gCAAgC,CAAC;AAMpD,OAAO,KAAK,EAAE,iBAAiB,EAA6C,MAAM,iBAAiB,CAAC;AACpG,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAChE,OAAO,EACL,KAAK,SAAS,EACd,SAAS,EAET,mBAAmB,
|
|
1
|
+
{"version":3,"file":"block_store.d.ts","sourceRoot":"","sources":["../../src/store/block_store.ts"],"names":[],"mappings":"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"}
|
|
@@ -6,7 +6,7 @@ import { createLogger } from '@aztec/foundation/log';
|
|
|
6
6
|
import { BufferReader } from '@aztec/foundation/serialize';
|
|
7
7
|
import { bufferToHex } from '@aztec/foundation/string';
|
|
8
8
|
import { isDefined } from '@aztec/foundation/types';
|
|
9
|
-
import { Body, CheckpointedL2Block, CommitteeAttestation, L2Block, deserializeValidateCheckpointResult, serializeValidateCheckpointResult } from '@aztec/stdlib/block';
|
|
9
|
+
import { BlockHash, Body, CheckpointedL2Block, CommitteeAttestation, GENESIS_CHECKPOINT_HEADER_HASH, L2Block, deserializeValidateCheckpointResult, serializeValidateCheckpointResult } from '@aztec/stdlib/block';
|
|
10
10
|
import { L1PublishedData } from '@aztec/stdlib/checkpoint';
|
|
11
11
|
import { getEpochAtSlot } from '@aztec/stdlib/epoch-helpers';
|
|
12
12
|
import { CheckpointHeader } from '@aztec/stdlib/rollup';
|
|
@@ -452,6 +452,118 @@ export { TxReceipt } from '@aztec/stdlib/tx';
|
|
|
452
452
|
}));
|
|
453
453
|
return typeof latestBlocknumber === 'number' ? BlockNumber(latestBlocknumber) : BlockNumber(INITIAL_L2_BLOCK_NUM - 1);
|
|
454
454
|
}
|
|
455
|
+
/**
|
|
456
|
+
* Resolves all L2 chain tips in a single read transaction so the snapshot is internally consistent.
|
|
457
|
+
* The result is guaranteed to satisfy finalized <= proven <= checkpointed <= proposed by block number.
|
|
458
|
+
*/ async getL2TipsData(genesisBlockHash) {
|
|
459
|
+
return await this.db.transactionAsync(async ()=>{
|
|
460
|
+
const genesisBlockNumber = BlockNumber(INITIAL_L2_BLOCK_NUM - 1);
|
|
461
|
+
const genesisCheckpointNumber = CheckpointNumber(INITIAL_CHECKPOINT_NUMBER - 1);
|
|
462
|
+
const genesisBlockId = {
|
|
463
|
+
number: genesisBlockNumber,
|
|
464
|
+
hash: genesisBlockHash.toString()
|
|
465
|
+
};
|
|
466
|
+
const genesisCheckpointId = {
|
|
467
|
+
number: genesisCheckpointNumber,
|
|
468
|
+
hash: GENESIS_CHECKPOINT_HEADER_HASH.toString()
|
|
469
|
+
};
|
|
470
|
+
const genesisTip = {
|
|
471
|
+
block: genesisBlockId,
|
|
472
|
+
checkpoint: genesisCheckpointId
|
|
473
|
+
};
|
|
474
|
+
const [latestBlockEntry] = await toArray(this.#blocks.entriesAsync({
|
|
475
|
+
reverse: true,
|
|
476
|
+
limit: 1
|
|
477
|
+
}));
|
|
478
|
+
const [latestCheckpointEntry] = await toArray(this.#checkpoints.entriesAsync({
|
|
479
|
+
reverse: true,
|
|
480
|
+
limit: 1
|
|
481
|
+
}));
|
|
482
|
+
const latestCheckpointNumber = latestCheckpointEntry ? CheckpointNumber(latestCheckpointEntry[0]) : genesisCheckpointNumber;
|
|
483
|
+
const [provenRaw, finalizedRaw] = await Promise.all([
|
|
484
|
+
this.#lastProvenCheckpoint.getAsync(),
|
|
485
|
+
this.#lastFinalizedCheckpoint.getAsync()
|
|
486
|
+
]);
|
|
487
|
+
const provenCheckpointNumber = CheckpointNumber(Math.min(provenRaw ?? 0, latestCheckpointNumber));
|
|
488
|
+
const finalizedCheckpointNumber = CheckpointNumber(Math.min(finalizedRaw ?? 0, provenCheckpointNumber));
|
|
489
|
+
const checkpointStorageCache = new Map();
|
|
490
|
+
if (latestCheckpointEntry) {
|
|
491
|
+
checkpointStorageCache.set(CheckpointNumber(latestCheckpointEntry[0]), latestCheckpointEntry[1]);
|
|
492
|
+
}
|
|
493
|
+
const loadCheckpointStorage = async (checkpointNumber)=>{
|
|
494
|
+
if (checkpointNumber === genesisCheckpointNumber) {
|
|
495
|
+
return undefined;
|
|
496
|
+
}
|
|
497
|
+
if (!checkpointStorageCache.has(checkpointNumber)) {
|
|
498
|
+
const checkpointStorage = await this.#checkpoints.getAsync(checkpointNumber);
|
|
499
|
+
if (!checkpointStorage) {
|
|
500
|
+
throw new CheckpointNotFoundError(checkpointNumber);
|
|
501
|
+
}
|
|
502
|
+
checkpointStorageCache.set(checkpointNumber, checkpointStorage);
|
|
503
|
+
}
|
|
504
|
+
return checkpointStorageCache.get(checkpointNumber);
|
|
505
|
+
};
|
|
506
|
+
const [provenCheckpoint, finalizedCheckpoint] = await Promise.all([
|
|
507
|
+
loadCheckpointStorage(provenCheckpointNumber),
|
|
508
|
+
loadCheckpointStorage(finalizedCheckpointNumber)
|
|
509
|
+
]);
|
|
510
|
+
const blockHashCache = new Map();
|
|
511
|
+
blockHashCache.set(genesisBlockNumber, genesisBlockHash.toString());
|
|
512
|
+
if (latestBlockEntry) {
|
|
513
|
+
blockHashCache.set(BlockNumber(latestBlockEntry[0]), BlockHash.fromBuffer(latestBlockEntry[1].blockHash).toString());
|
|
514
|
+
}
|
|
515
|
+
const loadBlockHash = async (blockNumber)=>{
|
|
516
|
+
if (!blockHashCache.has(blockNumber)) {
|
|
517
|
+
const blockStorage = await this.#blocks.getAsync(blockNumber);
|
|
518
|
+
if (!blockStorage) {
|
|
519
|
+
throw new BlockNotFoundError(blockNumber);
|
|
520
|
+
}
|
|
521
|
+
blockHashCache.set(blockNumber, BlockHash.fromBuffer(blockStorage.blockHash).toString());
|
|
522
|
+
}
|
|
523
|
+
return blockHashCache.get(blockNumber);
|
|
524
|
+
};
|
|
525
|
+
const proposed = latestBlockEntry === undefined ? genesisBlockId : {
|
|
526
|
+
number: BlockNumber(latestBlockEntry[0]),
|
|
527
|
+
hash: BlockHash.fromBuffer(latestBlockEntry[1].blockHash).toString()
|
|
528
|
+
};
|
|
529
|
+
const buildTipFromCheckpoint = async (stored)=>{
|
|
530
|
+
if (!stored) {
|
|
531
|
+
return genesisTip;
|
|
532
|
+
}
|
|
533
|
+
const blockNumber = BlockNumber(stored.startBlock + stored.blockCount - 1);
|
|
534
|
+
return {
|
|
535
|
+
block: {
|
|
536
|
+
number: blockNumber,
|
|
537
|
+
hash: await loadBlockHash(blockNumber)
|
|
538
|
+
},
|
|
539
|
+
checkpoint: {
|
|
540
|
+
number: CheckpointNumber(stored.checkpointNumber),
|
|
541
|
+
hash: CheckpointHeader.fromBuffer(stored.header).hash().toString()
|
|
542
|
+
}
|
|
543
|
+
};
|
|
544
|
+
};
|
|
545
|
+
const [checkpointed, proven, finalized] = await Promise.all([
|
|
546
|
+
buildTipFromCheckpoint(latestCheckpointEntry?.[1]),
|
|
547
|
+
buildTipFromCheckpoint(provenCheckpoint),
|
|
548
|
+
buildTipFromCheckpoint(finalizedCheckpoint)
|
|
549
|
+
]);
|
|
550
|
+
if (proposed.number < checkpointed.block.number) {
|
|
551
|
+
throw new Error(`Inconsistent block store: latest block ${proposed.number} is behind checkpointed block ${checkpointed.block.number}`);
|
|
552
|
+
}
|
|
553
|
+
if (finalized.checkpoint.number > proven.checkpoint.number || proven.checkpoint.number > checkpointed.checkpoint.number) {
|
|
554
|
+
throw new Error(`Inconsistent checkpoint numbers in chain tips: finalized=${finalized.checkpoint.number} proven=${proven.checkpoint.number} checkpointed=${checkpointed.checkpoint.number}`);
|
|
555
|
+
}
|
|
556
|
+
if (finalized.block.number > proven.block.number || proven.block.number > checkpointed.block.number || checkpointed.block.number > proposed.number) {
|
|
557
|
+
throw new Error(`Inconsistent block numbers in chain tips: finalized=${finalized.block.number} proven=${proven.block.number} checkpointed=${checkpointed.block.number} proposed=${proposed.number}`);
|
|
558
|
+
}
|
|
559
|
+
return {
|
|
560
|
+
proposed,
|
|
561
|
+
checkpointed,
|
|
562
|
+
proven,
|
|
563
|
+
finalized
|
|
564
|
+
};
|
|
565
|
+
});
|
|
566
|
+
}
|
|
455
567
|
async getLatestCheckpointNumber() {
|
|
456
568
|
const [latestCheckpointNumber] = await toArray(this.#checkpoints.keysAsync({
|
|
457
569
|
reverse: true,
|
|
@@ -15,4 +15,4 @@ export declare class ContractClassStore {
|
|
|
15
15
|
getContractClassIds(): Promise<Fr[]>;
|
|
16
16
|
addFunctions(contractClassId: Fr, newPrivateFunctions: ExecutablePrivateFunctionWithMembershipProof[], newUtilityFunctions: UtilityFunctionWithMembershipProof[]): Promise<boolean>;
|
|
17
17
|
}
|
|
18
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
18
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29udHJhY3RfY2xhc3Nfc3RvcmUuZC50cyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9zdG9yZS9jb250cmFjdF9jbGFzc19zdG9yZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsRUFBRSxFQUFFLE1BQU0sZ0NBQWdDLENBQUM7QUFHcEQsT0FBTyxLQUFLLEVBQUUsaUJBQWlCLEVBQWlCLE1BQU0saUJBQWlCLENBQUM7QUFHeEUsT0FBTyxLQUFLLEVBQ1YsbUJBQW1CLEVBRW5CLDRDQUE0QyxFQUM1QyxrQ0FBa0MsRUFDbkMsTUFBTSx3QkFBd0IsQ0FBQztBQUdoQzs7R0FFRztBQUNILHFCQUFhLGtCQUFrQjs7SUFJakIsT0FBTyxDQUFDLEVBQUU7SUFBdEIsWUFBb0IsRUFBRSxFQUFFLGlCQUFpQixFQUd4QztJQUVLLGdCQUFnQixDQUNwQixhQUFhLEVBQUUsbUJBQW1CLEVBQ2xDLGtCQUFrQixFQUFFLEVBQUUsRUFDdEIsV0FBVyxFQUFFLE1BQU0sR0FDbEIsT0FBTyxDQUFDLElBQUksQ0FBQyxDQWtCZjtJQUVLLHFCQUFxQixDQUFDLGFBQWEsRUFBRSxtQkFBbUIsRUFBRSxXQUFXLEVBQUUsTUFBTSxHQUFHLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FhbEc7SUFFSyxnQkFBZ0IsQ0FBQyxFQUFFLEVBQUUsRUFBRSxHQUFHLE9BQU8sQ0FBQyxtQkFBbUIsR0FBRyxTQUFTLENBQUMsQ0FHdkU7SUFFSyxxQkFBcUIsQ0FBQyxFQUFFLEVBQUUsRUFBRSxHQUFHLE9BQU8sQ0FBQyxFQUFFLEdBQUcsU0FBUyxDQUFDLENBRzNEO0lBRUssbUJBQW1CLElBQUksT0FBTyxDQUFDLEVBQUUsRUFBRSxDQUFDLENBRXpDO0lBRUssWUFBWSxDQUNoQixlQUFlLEVBQUUsRUFBRSxFQUNuQixtQkFBbUIsRUFBRSw0Q0FBNEMsRUFBRSxFQUNuRSxtQkFBbUIsRUFBRSxrQ0FBa0MsRUFBRSxHQUN4RCxPQUFPLENBQUMsT0FBTyxDQUFDLENBeUJsQjtDQUNGIn0=
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"contract_class_store.d.ts","sourceRoot":"","sources":["../../src/store/contract_class_store.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,EAAE,EAAE,MAAM,gCAAgC,CAAC;AAGpD,OAAO,KAAK,EAAE,iBAAiB,EAAiB,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"contract_class_store.d.ts","sourceRoot":"","sources":["../../src/store/contract_class_store.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,EAAE,EAAE,MAAM,gCAAgC,CAAC;AAGpD,OAAO,KAAK,EAAE,iBAAiB,EAAiB,MAAM,iBAAiB,CAAC;AAGxE,OAAO,KAAK,EACV,mBAAmB,EAEnB,4CAA4C,EAC5C,kCAAkC,EACnC,MAAM,wBAAwB,CAAC;AAGhC;;GAEG;AACH,qBAAa,kBAAkB;;IAIjB,OAAO,CAAC,EAAE;IAAtB,YAAoB,EAAE,EAAE,iBAAiB,EAGxC;IAEK,gBAAgB,CACpB,aAAa,EAAE,mBAAmB,EAClC,kBAAkB,EAAE,EAAE,EACtB,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,IAAI,CAAC,CAkBf;IAEK,qBAAqB,CAAC,aAAa,EAAE,mBAAmB,EAAE,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAalG;IAEK,gBAAgB,CAAC,EAAE,EAAE,EAAE,GAAG,OAAO,CAAC,mBAAmB,GAAG,SAAS,CAAC,CAGvE;IAEK,qBAAqB,CAAC,EAAE,EAAE,EAAE,GAAG,OAAO,CAAC,EAAE,GAAG,SAAS,CAAC,CAG3D;IAEK,mBAAmB,IAAI,OAAO,CAAC,EAAE,EAAE,CAAC,CAEzC;IAEK,YAAY,CAChB,eAAe,EAAE,EAAE,EACnB,mBAAmB,EAAE,4CAA4C,EAAE,EACnE,mBAAmB,EAAE,kCAAkC,EAAE,GACxD,OAAO,CAAC,OAAO,CAAC,CAyBlB;CACF"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Fr } from '@aztec/foundation/curves/bn254';
|
|
2
2
|
import { toArray } from '@aztec/foundation/iterable';
|
|
3
3
|
import { BufferReader, numToUInt8, serializeToBuffer } from '@aztec/foundation/serialize';
|
|
4
|
+
import { isProtocolContractClass } from '@aztec/protocol-contracts';
|
|
4
5
|
import { FunctionSelector } from '@aztec/stdlib/abi';
|
|
5
6
|
import { Vector } from '@aztec/stdlib/types';
|
|
6
7
|
/**
|
|
@@ -18,6 +19,12 @@ import { Vector } from '@aztec/stdlib/types';
|
|
|
18
19
|
await this.db.transactionAsync(async ()=>{
|
|
19
20
|
const key = contractClass.id.toString();
|
|
20
21
|
if (await this.#contractClasses.hasAsync(key)) {
|
|
22
|
+
// Protocol contracts are preloaded at block 0, so a later on-chain (re-)publish of a bundled
|
|
23
|
+
// protocol class id is valid and must be a no-op. Keep the existing block-0 entry untouched
|
|
24
|
+
// (do not bump its block number) so it survives reorgs of the publishing block.
|
|
25
|
+
if (isProtocolContractClass(contractClass.id)) {
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
21
28
|
throw new Error(`Contract class ${key} already exists, cannot add again at block ${blockNumber}`);
|
|
22
29
|
}
|
|
23
30
|
await this.#contractClasses.set(key, serializeContractClassPublic({
|
|
@@ -28,6 +35,11 @@ import { Vector } from '@aztec/stdlib/types';
|
|
|
28
35
|
});
|
|
29
36
|
}
|
|
30
37
|
async deleteContractClasses(contractClass, blockNumber) {
|
|
38
|
+
// Protocol contracts are preloaded at block 0 and must never be deleted, even when the block that
|
|
39
|
+
// (re-)published them on-chain is unwound by a reorg.
|
|
40
|
+
if (isProtocolContractClass(contractClass.id)) {
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
31
43
|
const restoredContractClass = await this.#contractClasses.getAsync(contractClass.id.toString());
|
|
32
44
|
if (restoredContractClass && deserializeContractClassPublic(restoredContractClass).l2BlockNumber >= blockNumber) {
|
|
33
45
|
await this.db.transactionAsync(async ()=>{
|
|
@@ -21,4 +21,4 @@ export declare class ContractInstanceStore {
|
|
|
21
21
|
getContractInstanceDeploymentBlockNumber(address: AztecAddress): Promise<number | undefined>;
|
|
22
22
|
}
|
|
23
23
|
export {};
|
|
24
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
24
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29udHJhY3RfaW5zdGFuY2Vfc3RvcmUuZC50cyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9zdG9yZS9jb250cmFjdF9pbnN0YW5jZV9zdG9yZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEtBQUssRUFBRSxFQUFFLEVBQUUsTUFBTSxnQ0FBZ0MsQ0FBQztBQUN6RCxPQUFPLEtBQUssRUFBRSxpQkFBaUIsRUFBaUIsTUFBTSxpQkFBaUIsQ0FBQztBQUV4RSxPQUFPLEtBQUssRUFBRSxZQUFZLEVBQUUsTUFBTSw2QkFBNkIsQ0FBQztBQUNoRSxPQUFPLEVBQ0wsS0FBSyxpQ0FBaUMsRUFDdEMsS0FBSywyQkFBMkIsRUFHakMsTUFBTSx3QkFBd0IsQ0FBQztBQUNoQyxPQUFPLEtBQUssRUFBRSxNQUFNLEVBQUUsTUFBTSxxQkFBcUIsQ0FBQztBQUVsRCxLQUFLLHlCQUF5QixHQUFHLENBQUMsTUFBTSxFQUFFLE1BQU0sQ0FBQyxHQUFHLENBQUMsTUFBTSxFQUFFLE1BQU0sRUFBRSxNQUFNLENBQUMsQ0FBQztBQUU3RTs7R0FFRztBQUNILHFCQUFhLHFCQUFxQjs7SUFLcEIsT0FBTyxDQUFDLEVBQUU7SUFBdEIsWUFBb0IsRUFBRSxFQUFFLGlCQUFpQixFQUl4QztJQUVELG1CQUFtQixDQUFDLGdCQUFnQixFQUFFLDJCQUEyQixFQUFFLFdBQVcsRUFBRSxNQUFNLEdBQUcsT0FBTyxDQUFDLElBQUksQ0FBQyxDQWdCckc7SUFFRCxzQkFBc0IsQ0FBQyxnQkFBZ0IsRUFBRSwyQkFBMkIsR0FBRyxPQUFPLENBQUMsSUFBSSxDQUFDLENBVW5GO0lBRUQsWUFBWSxDQUFDLGVBQWUsRUFBRSxZQUFZLEVBQUUsU0FBUyxFQUFFLE1BQU0sRUFBRSxRQUFRLENBQUMsRUFBRSxNQUFNLEdBQUcseUJBQXlCLENBTTNHO0lBRUQseUJBQXlCLENBQ3ZCLHNCQUFzQixFQUFFLGlDQUFpQyxFQUN6RCxTQUFTLEVBQUUsTUFBTSxFQUNqQixRQUFRLEVBQUUsTUFBTSxHQUNmLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FLZjtJQUVELDRCQUE0QixDQUMxQixzQkFBc0IsRUFBRSxpQ0FBaUMsRUFDekQsU0FBUyxFQUFFLE1BQU0sRUFDakIsUUFBUSxFQUFFLE1BQU0sR0FDZixPQUFPLENBQUMsSUFBSSxDQUFDLENBRWY7SUFFSyxpQ0FBaUMsQ0FBQyxPQUFPLEVBQUUsWUFBWSxFQUFFLFNBQVMsRUFBRSxNQUFNLEVBQUUsZUFBZSxFQUFFLEVBQUUsR0FBRyxPQUFPLENBQUMsRUFBRSxDQUFDLENBb0JsSDtJQUVLLG1CQUFtQixDQUN2QixPQUFPLEVBQUUsWUFBWSxFQUNyQixTQUFTLEVBQUUsTUFBTSxHQUNoQixPQUFPLENBQUMsMkJBQTJCLEdBQUcsU0FBUyxDQUFDLENBYWxEO0lBRUQsd0NBQXdDLENBQUMsT0FBTyxFQUFFLFlBQVksR0FBRyxPQUFPLENBQUMsTUFBTSxHQUFHLFNBQVMsQ0FBQyxDQUUzRjtDQUNGIn0=
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"contract_instance_store.d.ts","sourceRoot":"","sources":["../../src/store/contract_instance_store.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,gCAAgC,CAAC;AACzD,OAAO,KAAK,EAAE,iBAAiB,EAAiB,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"contract_instance_store.d.ts","sourceRoot":"","sources":["../../src/store/contract_instance_store.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,gCAAgC,CAAC;AACzD,OAAO,KAAK,EAAE,iBAAiB,EAAiB,MAAM,iBAAiB,CAAC;AAExE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAChE,OAAO,EACL,KAAK,iCAAiC,EACtC,KAAK,2BAA2B,EAGjC,MAAM,wBAAwB,CAAC;AAChC,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAElD,KAAK,yBAAyB,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;AAE7E;;GAEG;AACH,qBAAa,qBAAqB;;IAKpB,OAAO,CAAC,EAAE;IAAtB,YAAoB,EAAE,EAAE,iBAAiB,EAIxC;IAED,mBAAmB,CAAC,gBAAgB,EAAE,2BAA2B,EAAE,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAgBrG;IAED,sBAAsB,CAAC,gBAAgB,EAAE,2BAA2B,GAAG,OAAO,CAAC,IAAI,CAAC,CAUnF;IAED,YAAY,CAAC,eAAe,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,yBAAyB,CAM3G;IAED,yBAAyB,CACvB,sBAAsB,EAAE,iCAAiC,EACzD,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,IAAI,CAAC,CAKf;IAED,4BAA4B,CAC1B,sBAAsB,EAAE,iCAAiC,EACzD,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,IAAI,CAAC,CAEf;IAEK,iCAAiC,CAAC,OAAO,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,EAAE,eAAe,EAAE,EAAE,GAAG,OAAO,CAAC,EAAE,CAAC,CAoBlH;IAEK,mBAAmB,CACvB,OAAO,EAAE,YAAY,EACrB,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,2BAA2B,GAAG,SAAS,CAAC,CAalD;IAED,wCAAwC,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAE3F;CACF"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { isProtocolContract } from '@aztec/protocol-contracts';
|
|
1
2
|
import { SerializableContractInstance, SerializableContractInstanceUpdate } from '@aztec/stdlib/contract';
|
|
2
3
|
/**
|
|
3
4
|
* LMDB-based contract instance storage for the archiver.
|
|
@@ -16,6 +17,11 @@ import { SerializableContractInstance, SerializableContractInstanceUpdate } from
|
|
|
16
17
|
return this.db.transactionAsync(async ()=>{
|
|
17
18
|
const key = contractInstance.address.toString();
|
|
18
19
|
if (await this.#contractInstances.hasAsync(key)) {
|
|
20
|
+
// Protocol contracts are preloaded at block 0, so a later on-chain (re-)publish of a bundled
|
|
21
|
+
// protocol instance is valid and must be a no-op. Keep the existing block-0 entry untouched.
|
|
22
|
+
if (isProtocolContract(contractInstance.address)) {
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
19
25
|
throw new Error(`Contract instance at ${key} already exists (deployed at block ${await this.#contractInstancePublishedAt.getAsync(key)}), cannot add again at block ${blockNumber}`);
|
|
20
26
|
}
|
|
21
27
|
await this.#contractInstances.set(key, new SerializableContractInstance(contractInstance).toBuffer());
|
|
@@ -23,6 +29,11 @@ import { SerializableContractInstance, SerializableContractInstanceUpdate } from
|
|
|
23
29
|
});
|
|
24
30
|
}
|
|
25
31
|
deleteContractInstance(contractInstance) {
|
|
32
|
+
// Protocol contracts are preloaded at block 0 and must never be deleted, even when the block that
|
|
33
|
+
// (re-)published them on-chain is unwound by a reorg.
|
|
34
|
+
if (isProtocolContract(contractInstance.address)) {
|
|
35
|
+
return Promise.resolve();
|
|
36
|
+
}
|
|
26
37
|
return this.db.transactionAsync(async ()=>{
|
|
27
38
|
await this.#contractInstances.delete(contractInstance.address.toString());
|
|
28
39
|
await this.#contractInstancePublishedAt.delete(contractInstance.address.toString());
|
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { L2Tips } from '@aztec/stdlib/block';
|
|
2
2
|
import type { BlockStore } from './block_store.js';
|
|
3
3
|
/**
|
|
4
4
|
* In-memory cache for L2 chain tips (proposed, checkpointed, proven, finalized).
|
|
5
5
|
* Populated from the BlockStore on first access, then kept up-to-date by the ArchiverDataStoreUpdater.
|
|
6
|
-
* Refresh calls should happen
|
|
6
|
+
* Refresh calls should happen after the store transaction that mutates block data has committed,
|
|
7
|
+
* so the cache loads from committed state and is never replaced if the writer aborts.
|
|
7
8
|
*/
|
|
8
9
|
export declare class L2TipsCache {
|
|
9
10
|
#private;
|
|
@@ -11,9 +12,7 @@ export declare class L2TipsCache {
|
|
|
11
12
|
constructor(blockStore: BlockStore);
|
|
12
13
|
/** Returns the cached L2 tips. Loads from the block store on first call. */
|
|
13
14
|
getL2Tips(): Promise<L2Tips>;
|
|
14
|
-
/** Reloads the L2 tips from the block store. Should be called
|
|
15
|
+
/** Reloads the L2 tips from the block store. Should be called after the writer transaction has committed. */
|
|
15
16
|
refresh(): Promise<void>;
|
|
16
|
-
private loadFromStore;
|
|
17
|
-
private getCheckpointIdForBlock;
|
|
18
17
|
}
|
|
19
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
18
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibDJfdGlwc19jYWNoZS5kLnRzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3N0b3JlL2wyX3RpcHNfY2FjaGUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQ0EsT0FBTyxLQUFLLEVBQUUsTUFBTSxFQUFFLE1BQU0scUJBQXFCLENBQUM7QUFFbEQsT0FBTyxLQUFLLEVBQUUsVUFBVSxFQUFFLE1BQU0sa0JBQWtCLENBQUM7QUFFbkQ7Ozs7O0dBS0c7QUFDSCxxQkFBYSxXQUFXOztJQUdWLE9BQU8sQ0FBQyxVQUFVO0lBQTlCLFlBQW9CLFVBQVUsRUFBRSxVQUFVLEVBQUk7SUFFOUMsNEVBQTRFO0lBQ3JFLFNBQVMsSUFBSSxPQUFPLENBQUMsTUFBTSxDQUFDLENBRWxDO0lBRUQsNkdBQTZHO0lBQ2hHLE9BQU8sSUFBSSxPQUFPLENBQUMsSUFBSSxDQUFDLENBR3BDO0NBQ0YifQ==
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"l2_tips_cache.d.ts","sourceRoot":"","sources":["../../src/store/l2_tips_cache.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"l2_tips_cache.d.ts","sourceRoot":"","sources":["../../src/store/l2_tips_cache.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAElD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAEnD;;;;;GAKG;AACH,qBAAa,WAAW;;IAGV,OAAO,CAAC,UAAU;IAA9B,YAAoB,UAAU,EAAE,UAAU,EAAI;IAE9C,4EAA4E;IACrE,SAAS,IAAI,OAAO,CAAC,MAAM,CAAC,CAElC;IAED,6GAA6G;IAChG,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,CAGpC;CACF"}
|
|
@@ -1,10 +1,9 @@
|
|
|
1
|
-
import { GENESIS_BLOCK_HEADER_HASH
|
|
2
|
-
import { BlockNumber, CheckpointNumber } from '@aztec/foundation/branded-types';
|
|
3
|
-
import { GENESIS_CHECKPOINT_HEADER_HASH } from '@aztec/stdlib/block';
|
|
1
|
+
import { GENESIS_BLOCK_HEADER_HASH } from '@aztec/constants';
|
|
4
2
|
/**
|
|
5
3
|
* In-memory cache for L2 chain tips (proposed, checkpointed, proven, finalized).
|
|
6
4
|
* Populated from the BlockStore on first access, then kept up-to-date by the ArchiverDataStoreUpdater.
|
|
7
|
-
* Refresh calls should happen
|
|
5
|
+
* Refresh calls should happen after the store transaction that mutates block data has committed,
|
|
6
|
+
* so the cache loads from committed state and is never replaced if the writer aborts.
|
|
8
7
|
*/ export class L2TipsCache {
|
|
9
8
|
blockStore;
|
|
10
9
|
#tipsPromise;
|
|
@@ -12,78 +11,10 @@ import { GENESIS_CHECKPOINT_HEADER_HASH } from '@aztec/stdlib/block';
|
|
|
12
11
|
this.blockStore = blockStore;
|
|
13
12
|
}
|
|
14
13
|
/** Returns the cached L2 tips. Loads from the block store on first call. */ getL2Tips() {
|
|
15
|
-
return this.#tipsPromise ??= this.
|
|
14
|
+
return this.#tipsPromise ??= this.blockStore.getL2TipsData(GENESIS_BLOCK_HEADER_HASH);
|
|
16
15
|
}
|
|
17
|
-
/** Reloads the L2 tips from the block store. Should be called
|
|
18
|
-
this.#tipsPromise = this.
|
|
16
|
+
/** Reloads the L2 tips from the block store. Should be called after the writer transaction has committed. */ async refresh() {
|
|
17
|
+
this.#tipsPromise = this.blockStore.getL2TipsData(GENESIS_BLOCK_HEADER_HASH);
|
|
19
18
|
await this.#tipsPromise;
|
|
20
19
|
}
|
|
21
|
-
async loadFromStore() {
|
|
22
|
-
const [latestBlockNumber, provenBlockNumber, checkpointedBlockNumber, finalizedBlockNumber] = await Promise.all([
|
|
23
|
-
this.blockStore.getLatestBlockNumber(),
|
|
24
|
-
this.blockStore.getProvenBlockNumber(),
|
|
25
|
-
this.blockStore.getCheckpointedL2BlockNumber(),
|
|
26
|
-
this.blockStore.getFinalizedL2BlockNumber()
|
|
27
|
-
]);
|
|
28
|
-
const genesisBlockHeader = {
|
|
29
|
-
blockHash: GENESIS_BLOCK_HEADER_HASH,
|
|
30
|
-
checkpointNumber: CheckpointNumber.ZERO
|
|
31
|
-
};
|
|
32
|
-
const beforeInitialBlockNumber = BlockNumber(INITIAL_L2_BLOCK_NUM - 1);
|
|
33
|
-
const getBlockData = (blockNumber)=>blockNumber > beforeInitialBlockNumber ? this.blockStore.getBlockData(blockNumber) : genesisBlockHeader;
|
|
34
|
-
const [latestBlockData, provenBlockData, checkpointedBlockData, finalizedBlockData] = await Promise.all([
|
|
35
|
-
latestBlockNumber,
|
|
36
|
-
provenBlockNumber,
|
|
37
|
-
checkpointedBlockNumber,
|
|
38
|
-
finalizedBlockNumber
|
|
39
|
-
].map(getBlockData));
|
|
40
|
-
if (!latestBlockData || !provenBlockData || !finalizedBlockData || !checkpointedBlockData) {
|
|
41
|
-
throw new Error('Failed to load block data for L2 tips');
|
|
42
|
-
}
|
|
43
|
-
const [provenCheckpointId, finalizedCheckpointId, checkpointedCheckpointId] = await Promise.all([
|
|
44
|
-
this.getCheckpointIdForBlock(provenBlockData),
|
|
45
|
-
this.getCheckpointIdForBlock(finalizedBlockData),
|
|
46
|
-
this.getCheckpointIdForBlock(checkpointedBlockData)
|
|
47
|
-
]);
|
|
48
|
-
return {
|
|
49
|
-
proposed: {
|
|
50
|
-
number: latestBlockNumber,
|
|
51
|
-
hash: latestBlockData.blockHash.toString()
|
|
52
|
-
},
|
|
53
|
-
proven: {
|
|
54
|
-
block: {
|
|
55
|
-
number: provenBlockNumber,
|
|
56
|
-
hash: provenBlockData.blockHash.toString()
|
|
57
|
-
},
|
|
58
|
-
checkpoint: provenCheckpointId
|
|
59
|
-
},
|
|
60
|
-
finalized: {
|
|
61
|
-
block: {
|
|
62
|
-
number: finalizedBlockNumber,
|
|
63
|
-
hash: finalizedBlockData.blockHash.toString()
|
|
64
|
-
},
|
|
65
|
-
checkpoint: finalizedCheckpointId
|
|
66
|
-
},
|
|
67
|
-
checkpointed: {
|
|
68
|
-
block: {
|
|
69
|
-
number: checkpointedBlockNumber,
|
|
70
|
-
hash: checkpointedBlockData.blockHash.toString()
|
|
71
|
-
},
|
|
72
|
-
checkpoint: checkpointedCheckpointId
|
|
73
|
-
}
|
|
74
|
-
};
|
|
75
|
-
}
|
|
76
|
-
async getCheckpointIdForBlock(blockData) {
|
|
77
|
-
const checkpointData = await this.blockStore.getCheckpointData(blockData.checkpointNumber);
|
|
78
|
-
if (!checkpointData) {
|
|
79
|
-
return {
|
|
80
|
-
number: CheckpointNumber.ZERO,
|
|
81
|
-
hash: GENESIS_CHECKPOINT_HEADER_HASH.toString()
|
|
82
|
-
};
|
|
83
|
-
}
|
|
84
|
-
return {
|
|
85
|
-
number: checkpointData.checkpointNumber,
|
|
86
|
-
hash: checkpointData.header.hash().toString()
|
|
87
|
-
};
|
|
88
|
-
}
|
|
89
20
|
}
|
|
@@ -51,4 +51,4 @@ export declare class LogStore {
|
|
|
51
51
|
*/
|
|
52
52
|
getContractClassLogs(filter: LogFilter): Promise<GetContractClassLogsResponse>;
|
|
53
53
|
}
|
|
54
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
54
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibG9nX3N0b3JlLmQudHMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvc3RvcmUvbG9nX3N0b3JlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQU1BLE9BQU8sS0FBSyxFQUFFLGlCQUFpQixFQUFpQixNQUFNLGlCQUFpQixDQUFDO0FBQ3hFLE9BQU8sS0FBSyxFQUFFLFlBQVksRUFBRSxNQUFNLDZCQUE2QixDQUFDO0FBQ2hFLE9BQU8sRUFBYSxPQUFPLEVBQUUsTUFBTSxxQkFBcUIsQ0FBQztBQUV6RCxPQUFPLEtBQUssRUFBRSw0QkFBNEIsRUFBRSxxQkFBcUIsRUFBRSxNQUFNLGlDQUFpQyxDQUFDO0FBQzNHLE9BQU8sRUFJTCxLQUFLLFNBQVMsRUFHZCxLQUFLLFNBQVMsRUFDZCxHQUFHLEVBQ0gsYUFBYSxFQUNkLE1BQU0sb0JBQW9CLENBQUM7QUFHNUIsT0FBTyxLQUFLLEVBQUUsVUFBVSxFQUFFLE1BQU0sa0JBQWtCLENBQUM7QUFhbkQ7O0dBRUc7QUFDSCxxQkFBYSxRQUFROztJQWFqQixPQUFPLENBQUMsRUFBRTtJQUNWLE9BQU8sQ0FBQyxVQUFVO0lBRnBCLFlBQ1UsRUFBRSxFQUFFLGlCQUFpQixFQUNyQixVQUFVLEVBQUUsVUFBVSxFQUM5QixlQUFlLEdBQUUsTUFBYSxFQVUvQjtJQWdORDs7OztPQUlHO0lBQ0gsT0FBTyxDQUFDLE1BQU0sRUFBRSxPQUFPLEVBQUUsR0FBRyxPQUFPLENBQUMsT0FBTyxDQUFDLENBUzNDO0lBZ0JELFVBQVUsQ0FBQyxNQUFNLEVBQUUsT0FBTyxFQUFFLEdBQUcsT0FBTyxDQUFDLE9BQU8sQ0FBQyxDQTBEOUM7SUFFRDs7Ozs7OztPQU9HO0lBQ0csb0JBQW9CLENBQUMsSUFBSSxFQUFFLFNBQVMsRUFBRSxFQUFFLElBQUksR0FBRSxNQUFVLEdBQUcsT0FBTyxDQUFDLGFBQWEsRUFBRSxFQUFFLENBQUMsQ0FRMUY7SUFFRDs7Ozs7Ozs7T0FRRztJQUNHLCtCQUErQixDQUNuQyxlQUFlLEVBQUUsWUFBWSxFQUM3QixJQUFJLEVBQUUsR0FBRyxFQUFFLEVBQ1gsSUFBSSxHQUFFLE1BQVUsR0FDZixPQUFPLENBQUMsYUFBYSxFQUFFLEVBQUUsQ0FBQyxDQWE1QjtJQUVEOzs7O09BSUc7SUFDSCxhQUFhLENBQUMsTUFBTSxFQUFFLFNBQVMsR0FBRyxPQUFPLENBQUMscUJBQXFCLENBQUMsQ0FRL0Q7SUErRkQ7Ozs7T0FJRztJQUNILG9CQUFvQixDQUFDLE1BQU0sRUFBRSxTQUFTLEdBQUcsT0FBTyxDQUFDLDRCQUE0QixDQUFDLENBUTdFO0NBNktGIn0=
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"log_store.d.ts","sourceRoot":"","sources":["../../src/store/log_store.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,iBAAiB,EAAiB,MAAM,iBAAiB,CAAC;AACxE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAChE,OAAO,EAAa,OAAO,EAAE,MAAM,qBAAqB,CAAC;AAEzD,OAAO,KAAK,EAAE,4BAA4B,EAAE,qBAAqB,EAAE,MAAM,iCAAiC,CAAC;AAC3G,OAAO,EAIL,KAAK,SAAS,EAGd,KAAK,SAAS,EACd,GAAG,EACH,aAAa,EACd,MAAM,oBAAoB,CAAC;AAG5B,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"log_store.d.ts","sourceRoot":"","sources":["../../src/store/log_store.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,iBAAiB,EAAiB,MAAM,iBAAiB,CAAC;AACxE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAChE,OAAO,EAAa,OAAO,EAAE,MAAM,qBAAqB,CAAC;AAEzD,OAAO,KAAK,EAAE,4BAA4B,EAAE,qBAAqB,EAAE,MAAM,iCAAiC,CAAC;AAC3G,OAAO,EAIL,KAAK,SAAS,EAGd,KAAK,SAAS,EACd,GAAG,EACH,aAAa,EACd,MAAM,oBAAoB,CAAC;AAG5B,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAanD;;GAEG;AACH,qBAAa,QAAQ;;IAajB,OAAO,CAAC,EAAE;IACV,OAAO,CAAC,UAAU;IAFpB,YACU,EAAE,EAAE,iBAAiB,EACrB,UAAU,EAAE,UAAU,EAC9B,eAAe,GAAE,MAAa,EAU/B;IAgND;;;;OAIG;IACH,OAAO,CAAC,MAAM,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC,OAAO,CAAC,CAS3C;IAgBD,UAAU,CAAC,MAAM,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC,OAAO,CAAC,CA0D9C;IAED;;;;;;;OAOG;IACG,oBAAoB,CAAC,IAAI,EAAE,SAAS,EAAE,EAAE,IAAI,GAAE,MAAU,GAAG,OAAO,CAAC,aAAa,EAAE,EAAE,CAAC,CAQ1F;IAED;;;;;;;;OAQG;IACG,+BAA+B,CACnC,eAAe,EAAE,YAAY,EAC7B,IAAI,EAAE,GAAG,EAAE,EACX,IAAI,GAAE,MAAU,GACf,OAAO,CAAC,aAAa,EAAE,EAAE,CAAC,CAa5B;IAED;;;;OAIG;IACH,aAAa,CAAC,MAAM,EAAE,SAAS,GAAG,OAAO,CAAC,qBAAqB,CAAC,CAQ/D;IA+FD;;;;OAIG;IACH,oBAAoB,CAAC,MAAM,EAAE,SAAS,GAAG,OAAO,CAAC,4BAA4B,CAAC,CAQ7E;CA6KF"}
|
package/dest/store/log_store.js
CHANGED
|
@@ -8,6 +8,15 @@ import { BlockHash } from '@aztec/stdlib/block';
|
|
|
8
8
|
import { MAX_LOGS_PER_TAG } from '@aztec/stdlib/interfaces/api-limit';
|
|
9
9
|
import { ContractClassLog, ExtendedContractClassLog, ExtendedPublicLog, LogId, PublicLog, TxScopedL2Log } from '@aztec/stdlib/logs';
|
|
10
10
|
import { TxHash } from '@aztec/stdlib/tx';
|
|
11
|
+
/**
|
|
12
|
+
* Tag key for a log: the string form of its first field, or the empty string when the log carries no
|
|
13
|
+
* fields. A protocol-valid public log can carry zero fields (e.g. a raw AVM `EMITPUBLICLOG` with
|
|
14
|
+
* `logSize = 0`), which has no tag to index by. Keying it under the empty tag keeps it retrievable via
|
|
15
|
+
* the per-block read (and droppable on reorg) while never matching a real tag query — instead of reading
|
|
16
|
+
* `fields[0]` off an empty array and aborting the whole block-ingestion transaction.
|
|
17
|
+
*/ function tagKeyForLog(fields) {
|
|
18
|
+
return fields.length > 0 ? fields[0].toString() : '';
|
|
19
|
+
}
|
|
11
20
|
/**
|
|
12
21
|
* A store for logs
|
|
13
22
|
*/ export class LogStore {
|
|
@@ -48,19 +57,21 @@ import { TxHash } from '@aztec/stdlib/tx';
|
|
|
48
57
|
block.body.txEffects.forEach((txEffect)=>{
|
|
49
58
|
const txHash = txEffect.txHash;
|
|
50
59
|
txEffect.privateLogs.forEach((log)=>{
|
|
51
|
-
// Private logs use SiloedTag (already siloed by kernel)
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
60
|
+
// Private logs use SiloedTag (already siloed by kernel). A zero-field log has no tag and is keyed
|
|
61
|
+
// under the empty tag rather than throwing on log.fields[0].
|
|
62
|
+
const tagKey = tagKeyForLog(log.fields);
|
|
63
|
+
this.#log.debug(`Found private log with tag ${tagKey} in block ${block.number}`);
|
|
64
|
+
const currentLogs = privateTaggedLogs.get(tagKey) ?? [];
|
|
55
65
|
currentLogs.push(new TxScopedL2Log(txHash, block.number, block.timestamp, log.getEmittedFields(), txEffect.noteHashes, txEffect.nullifiers[0]).toBuffer());
|
|
56
|
-
privateTaggedLogs.set(
|
|
66
|
+
privateTaggedLogs.set(tagKey, currentLogs);
|
|
57
67
|
});
|
|
58
68
|
txEffect.publicLogs.forEach((log)=>{
|
|
59
|
-
// Public logs use Tag directly (not siloed) and are stored with contract address
|
|
60
|
-
|
|
69
|
+
// Public logs use Tag directly (not siloed) and are stored with contract address. A zero-field
|
|
70
|
+
// log has no tag and is keyed under the empty tag rather than throwing on log.fields[0].
|
|
71
|
+
const tagKey = tagKeyForLog(log.fields);
|
|
61
72
|
const contractAddress = log.contractAddress;
|
|
62
|
-
const key = `${contractAddress.toString()}_${
|
|
63
|
-
this.#log.debug(`Found public log with tag ${
|
|
73
|
+
const key = `${contractAddress.toString()}_${tagKey}`;
|
|
74
|
+
this.#log.debug(`Found public log with tag ${tagKey} from contract ${contractAddress.toString()} in block ${block.number}`);
|
|
64
75
|
const currentLogs = publicTaggedLogs.get(key) ?? [];
|
|
65
76
|
currentLogs.push(new TxScopedL2Log(txHash, block.number, block.timestamp, log.getEmittedFields(), txEffect.noteHashes, txEffect.nullifiers[0]).toBuffer());
|
|
66
77
|
publicTaggedLogs.set(key, currentLogs);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aztec/archiver",
|
|
3
|
-
"version": "4.4.0
|
|
3
|
+
"version": "4.4.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"exports": {
|
|
6
6
|
".": "./dest/index.js",
|
|
@@ -65,18 +65,18 @@
|
|
|
65
65
|
]
|
|
66
66
|
},
|
|
67
67
|
"dependencies": {
|
|
68
|
-
"@aztec/blob-client": "4.4.0
|
|
69
|
-
"@aztec/blob-lib": "4.4.0
|
|
70
|
-
"@aztec/constants": "4.4.0
|
|
71
|
-
"@aztec/epoch-cache": "4.4.0
|
|
72
|
-
"@aztec/ethereum": "4.4.0
|
|
73
|
-
"@aztec/foundation": "4.4.0
|
|
74
|
-
"@aztec/kv-store": "4.4.0
|
|
75
|
-
"@aztec/l1-artifacts": "4.4.0
|
|
76
|
-
"@aztec/noir-protocol-circuits-types": "4.4.0
|
|
77
|
-
"@aztec/protocol-contracts": "4.4.0
|
|
78
|
-
"@aztec/stdlib": "4.4.0
|
|
79
|
-
"@aztec/telemetry-client": "4.4.0
|
|
68
|
+
"@aztec/blob-client": "4.4.0",
|
|
69
|
+
"@aztec/blob-lib": "4.4.0",
|
|
70
|
+
"@aztec/constants": "4.4.0",
|
|
71
|
+
"@aztec/epoch-cache": "4.4.0",
|
|
72
|
+
"@aztec/ethereum": "4.4.0",
|
|
73
|
+
"@aztec/foundation": "4.4.0",
|
|
74
|
+
"@aztec/kv-store": "4.4.0",
|
|
75
|
+
"@aztec/l1-artifacts": "4.4.0",
|
|
76
|
+
"@aztec/noir-protocol-circuits-types": "4.4.0",
|
|
77
|
+
"@aztec/protocol-contracts": "4.4.0",
|
|
78
|
+
"@aztec/stdlib": "4.4.0",
|
|
79
|
+
"@aztec/telemetry-client": "4.4.0",
|
|
80
80
|
"lodash.groupby": "^4.6.0",
|
|
81
81
|
"lodash.omit": "^4.5.0",
|
|
82
82
|
"tslib": "^2.5.0",
|
|
@@ -80,9 +80,9 @@ export class ArchiverDataStoreUpdater {
|
|
|
80
80
|
this.addContractDataToDb(block),
|
|
81
81
|
]);
|
|
82
82
|
|
|
83
|
-
await this.l2TipsCache?.refresh();
|
|
84
83
|
return opResults.every(Boolean);
|
|
85
84
|
});
|
|
85
|
+
await this.l2TipsCache?.refresh();
|
|
86
86
|
return result;
|
|
87
87
|
}
|
|
88
88
|
|
|
@@ -125,9 +125,9 @@ export class ArchiverDataStoreUpdater {
|
|
|
125
125
|
...newBlocks.map(block => this.addContractDataToDb(block)),
|
|
126
126
|
]);
|
|
127
127
|
|
|
128
|
-
await this.l2TipsCache?.refresh();
|
|
129
128
|
return { prunedBlocks, lastAlreadyInsertedBlockNumber };
|
|
130
129
|
});
|
|
130
|
+
await this.l2TipsCache?.refresh();
|
|
131
131
|
return result;
|
|
132
132
|
}
|
|
133
133
|
|
|
@@ -224,9 +224,9 @@ export class ArchiverDataStoreUpdater {
|
|
|
224
224
|
}
|
|
225
225
|
|
|
226
226
|
const result = await this.removeBlocksAfter(blockNumber);
|
|
227
|
-
await this.l2TipsCache?.refresh();
|
|
228
227
|
return result;
|
|
229
228
|
});
|
|
229
|
+
await this.l2TipsCache?.refresh();
|
|
230
230
|
return result;
|
|
231
231
|
}
|
|
232
232
|
|
|
@@ -257,7 +257,7 @@ export class ArchiverDataStoreUpdater {
|
|
|
257
257
|
* @returns True if the operation is successful.
|
|
258
258
|
*/
|
|
259
259
|
public async removeCheckpointsAfter(checkpointNumber: CheckpointNumber): Promise<boolean> {
|
|
260
|
-
|
|
260
|
+
const result = await this.store.transactionAsync(async () => {
|
|
261
261
|
const { blocksRemoved = [] } = await this.store.removeCheckpointsAfter(checkpointNumber);
|
|
262
262
|
|
|
263
263
|
const opResults = await Promise.all([
|
|
@@ -268,9 +268,10 @@ export class ArchiverDataStoreUpdater {
|
|
|
268
268
|
this.store.deleteLogs(blocksRemoved),
|
|
269
269
|
]);
|
|
270
270
|
|
|
271
|
-
await this.l2TipsCache?.refresh();
|
|
272
271
|
return opResults.every(Boolean);
|
|
273
272
|
});
|
|
273
|
+
await this.l2TipsCache?.refresh();
|
|
274
|
+
return result;
|
|
274
275
|
}
|
|
275
276
|
|
|
276
277
|
/**
|
|
@@ -280,8 +281,8 @@ export class ArchiverDataStoreUpdater {
|
|
|
280
281
|
public async setProvenCheckpointNumber(checkpointNumber: CheckpointNumber): Promise<void> {
|
|
281
282
|
await this.store.transactionAsync(async () => {
|
|
282
283
|
await this.store.setProvenCheckpointNumber(checkpointNumber);
|
|
283
|
-
await this.l2TipsCache?.refresh();
|
|
284
284
|
});
|
|
285
|
+
await this.l2TipsCache?.refresh();
|
|
285
286
|
}
|
|
286
287
|
|
|
287
288
|
/**
|
|
@@ -291,8 +292,8 @@ export class ArchiverDataStoreUpdater {
|
|
|
291
292
|
public async setFinalizedCheckpointNumber(checkpointNumber: CheckpointNumber): Promise<void> {
|
|
292
293
|
await this.store.transactionAsync(async () => {
|
|
293
294
|
await this.store.setFinalizedCheckpointNumber(checkpointNumber);
|
|
294
|
-
await this.l2TipsCache?.refresh();
|
|
295
295
|
});
|
|
296
|
+
await this.l2TipsCache?.refresh();
|
|
296
297
|
}
|
|
297
298
|
|
|
298
299
|
/** Extracts and stores contract data from a single block. */
|
package/src/store/block_store.ts
CHANGED
|
@@ -14,7 +14,10 @@ import {
|
|
|
14
14
|
Body,
|
|
15
15
|
CheckpointedL2Block,
|
|
16
16
|
CommitteeAttestation,
|
|
17
|
+
GENESIS_CHECKPOINT_HEADER_HASH,
|
|
17
18
|
L2Block,
|
|
19
|
+
type L2TipId,
|
|
20
|
+
type L2Tips,
|
|
18
21
|
type ValidateCheckpointResult,
|
|
19
22
|
deserializeValidateCheckpointResult,
|
|
20
23
|
serializeValidateCheckpointResult,
|
|
@@ -625,6 +628,138 @@ export class BlockStore {
|
|
|
625
628
|
: BlockNumber(INITIAL_L2_BLOCK_NUM - 1);
|
|
626
629
|
}
|
|
627
630
|
|
|
631
|
+
/**
|
|
632
|
+
* Resolves all L2 chain tips in a single read transaction so the snapshot is internally consistent.
|
|
633
|
+
* The result is guaranteed to satisfy finalized <= proven <= checkpointed <= proposed by block number.
|
|
634
|
+
*/
|
|
635
|
+
async getL2TipsData(genesisBlockHash: Fr): Promise<L2Tips> {
|
|
636
|
+
return await this.db.transactionAsync(async () => {
|
|
637
|
+
const genesisBlockNumber = BlockNumber(INITIAL_L2_BLOCK_NUM - 1);
|
|
638
|
+
const genesisCheckpointNumber = CheckpointNumber(INITIAL_CHECKPOINT_NUMBER - 1);
|
|
639
|
+
const genesisBlockId = { number: genesisBlockNumber, hash: genesisBlockHash.toString() };
|
|
640
|
+
const genesisCheckpointId = {
|
|
641
|
+
number: genesisCheckpointNumber,
|
|
642
|
+
hash: GENESIS_CHECKPOINT_HEADER_HASH.toString(),
|
|
643
|
+
};
|
|
644
|
+
const genesisTip: L2TipId = { block: genesisBlockId, checkpoint: genesisCheckpointId };
|
|
645
|
+
|
|
646
|
+
const [latestBlockEntry] = await toArray(this.#blocks.entriesAsync({ reverse: true, limit: 1 }));
|
|
647
|
+
const [latestCheckpointEntry] = await toArray(this.#checkpoints.entriesAsync({ reverse: true, limit: 1 }));
|
|
648
|
+
const latestCheckpointNumber = latestCheckpointEntry
|
|
649
|
+
? CheckpointNumber(latestCheckpointEntry[0])
|
|
650
|
+
: genesisCheckpointNumber;
|
|
651
|
+
|
|
652
|
+
const [provenRaw, finalizedRaw] = await Promise.all([
|
|
653
|
+
this.#lastProvenCheckpoint.getAsync(),
|
|
654
|
+
this.#lastFinalizedCheckpoint.getAsync(),
|
|
655
|
+
]);
|
|
656
|
+
|
|
657
|
+
const provenCheckpointNumber = CheckpointNumber(Math.min(provenRaw ?? 0, latestCheckpointNumber));
|
|
658
|
+
const finalizedCheckpointNumber = CheckpointNumber(Math.min(finalizedRaw ?? 0, provenCheckpointNumber));
|
|
659
|
+
|
|
660
|
+
const checkpointStorageCache = new Map<CheckpointNumber, CheckpointStorage>();
|
|
661
|
+
if (latestCheckpointEntry) {
|
|
662
|
+
checkpointStorageCache.set(CheckpointNumber(latestCheckpointEntry[0]), latestCheckpointEntry[1]);
|
|
663
|
+
}
|
|
664
|
+
|
|
665
|
+
const loadCheckpointStorage = async (
|
|
666
|
+
checkpointNumber: CheckpointNumber,
|
|
667
|
+
): Promise<CheckpointStorage | undefined> => {
|
|
668
|
+
if (checkpointNumber === genesisCheckpointNumber) {
|
|
669
|
+
return undefined;
|
|
670
|
+
}
|
|
671
|
+
if (!checkpointStorageCache.has(checkpointNumber)) {
|
|
672
|
+
const checkpointStorage = await this.#checkpoints.getAsync(checkpointNumber);
|
|
673
|
+
if (!checkpointStorage) {
|
|
674
|
+
throw new CheckpointNotFoundError(checkpointNumber);
|
|
675
|
+
}
|
|
676
|
+
checkpointStorageCache.set(checkpointNumber, checkpointStorage);
|
|
677
|
+
}
|
|
678
|
+
return checkpointStorageCache.get(checkpointNumber)!;
|
|
679
|
+
};
|
|
680
|
+
|
|
681
|
+
const [provenCheckpoint, finalizedCheckpoint] = await Promise.all([
|
|
682
|
+
loadCheckpointStorage(provenCheckpointNumber),
|
|
683
|
+
loadCheckpointStorage(finalizedCheckpointNumber),
|
|
684
|
+
]);
|
|
685
|
+
|
|
686
|
+
const blockHashCache = new Map<BlockNumber, string>();
|
|
687
|
+
blockHashCache.set(genesisBlockNumber, genesisBlockHash.toString());
|
|
688
|
+
if (latestBlockEntry) {
|
|
689
|
+
blockHashCache.set(
|
|
690
|
+
BlockNumber(latestBlockEntry[0]),
|
|
691
|
+
BlockHash.fromBuffer(latestBlockEntry[1].blockHash).toString(),
|
|
692
|
+
);
|
|
693
|
+
}
|
|
694
|
+
|
|
695
|
+
const loadBlockHash = async (blockNumber: BlockNumber): Promise<string> => {
|
|
696
|
+
if (!blockHashCache.has(blockNumber)) {
|
|
697
|
+
const blockStorage = await this.#blocks.getAsync(blockNumber);
|
|
698
|
+
if (!blockStorage) {
|
|
699
|
+
throw new BlockNotFoundError(blockNumber);
|
|
700
|
+
}
|
|
701
|
+
blockHashCache.set(blockNumber, BlockHash.fromBuffer(blockStorage.blockHash).toString());
|
|
702
|
+
}
|
|
703
|
+
return blockHashCache.get(blockNumber)!;
|
|
704
|
+
};
|
|
705
|
+
|
|
706
|
+
const proposed =
|
|
707
|
+
latestBlockEntry === undefined
|
|
708
|
+
? genesisBlockId
|
|
709
|
+
: {
|
|
710
|
+
number: BlockNumber(latestBlockEntry[0]),
|
|
711
|
+
hash: BlockHash.fromBuffer(latestBlockEntry[1].blockHash).toString(),
|
|
712
|
+
};
|
|
713
|
+
|
|
714
|
+
const buildTipFromCheckpoint = async (stored: CheckpointStorage | undefined): Promise<L2TipId> => {
|
|
715
|
+
if (!stored) {
|
|
716
|
+
return genesisTip;
|
|
717
|
+
}
|
|
718
|
+
const blockNumber = BlockNumber(stored.startBlock + stored.blockCount - 1);
|
|
719
|
+
return {
|
|
720
|
+
block: { number: blockNumber, hash: await loadBlockHash(blockNumber) },
|
|
721
|
+
checkpoint: {
|
|
722
|
+
number: CheckpointNumber(stored.checkpointNumber),
|
|
723
|
+
hash: CheckpointHeader.fromBuffer(stored.header).hash().toString(),
|
|
724
|
+
},
|
|
725
|
+
};
|
|
726
|
+
};
|
|
727
|
+
|
|
728
|
+
const [checkpointed, proven, finalized] = await Promise.all([
|
|
729
|
+
buildTipFromCheckpoint(latestCheckpointEntry?.[1]),
|
|
730
|
+
buildTipFromCheckpoint(provenCheckpoint),
|
|
731
|
+
buildTipFromCheckpoint(finalizedCheckpoint),
|
|
732
|
+
]);
|
|
733
|
+
|
|
734
|
+
if (proposed.number < checkpointed.block.number) {
|
|
735
|
+
throw new Error(
|
|
736
|
+
`Inconsistent block store: latest block ${proposed.number} is behind checkpointed block ${checkpointed.block.number}`,
|
|
737
|
+
);
|
|
738
|
+
}
|
|
739
|
+
|
|
740
|
+
if (
|
|
741
|
+
finalized.checkpoint.number > proven.checkpoint.number ||
|
|
742
|
+
proven.checkpoint.number > checkpointed.checkpoint.number
|
|
743
|
+
) {
|
|
744
|
+
throw new Error(
|
|
745
|
+
`Inconsistent checkpoint numbers in chain tips: finalized=${finalized.checkpoint.number} proven=${proven.checkpoint.number} checkpointed=${checkpointed.checkpoint.number}`,
|
|
746
|
+
);
|
|
747
|
+
}
|
|
748
|
+
|
|
749
|
+
if (
|
|
750
|
+
finalized.block.number > proven.block.number ||
|
|
751
|
+
proven.block.number > checkpointed.block.number ||
|
|
752
|
+
checkpointed.block.number > proposed.number
|
|
753
|
+
) {
|
|
754
|
+
throw new Error(
|
|
755
|
+
`Inconsistent block numbers in chain tips: finalized=${finalized.block.number} proven=${proven.block.number} checkpointed=${checkpointed.block.number} proposed=${proposed.number}`,
|
|
756
|
+
);
|
|
757
|
+
}
|
|
758
|
+
|
|
759
|
+
return { proposed, checkpointed, proven, finalized };
|
|
760
|
+
});
|
|
761
|
+
}
|
|
762
|
+
|
|
628
763
|
async getLatestCheckpointNumber(): Promise<CheckpointNumber> {
|
|
629
764
|
const [latestCheckpointNumber] = await toArray(this.#checkpoints.keysAsync({ reverse: true, limit: 1 }));
|
|
630
765
|
if (latestCheckpointNumber === undefined) {
|
|
@@ -2,6 +2,7 @@ import { Fr } from '@aztec/foundation/curves/bn254';
|
|
|
2
2
|
import { toArray } from '@aztec/foundation/iterable';
|
|
3
3
|
import { BufferReader, numToUInt8, serializeToBuffer } from '@aztec/foundation/serialize';
|
|
4
4
|
import type { AztecAsyncKVStore, AztecAsyncMap } from '@aztec/kv-store';
|
|
5
|
+
import { isProtocolContractClass } from '@aztec/protocol-contracts';
|
|
5
6
|
import { FunctionSelector } from '@aztec/stdlib/abi';
|
|
6
7
|
import type {
|
|
7
8
|
ContractClassPublic,
|
|
@@ -31,6 +32,12 @@ export class ContractClassStore {
|
|
|
31
32
|
await this.db.transactionAsync(async () => {
|
|
32
33
|
const key = contractClass.id.toString();
|
|
33
34
|
if (await this.#contractClasses.hasAsync(key)) {
|
|
35
|
+
// Protocol contracts are preloaded at block 0, so a later on-chain (re-)publish of a bundled
|
|
36
|
+
// protocol class id is valid and must be a no-op. Keep the existing block-0 entry untouched
|
|
37
|
+
// (do not bump its block number) so it survives reorgs of the publishing block.
|
|
38
|
+
if (isProtocolContractClass(contractClass.id)) {
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
34
41
|
throw new Error(`Contract class ${key} already exists, cannot add again at block ${blockNumber}`);
|
|
35
42
|
}
|
|
36
43
|
await this.#contractClasses.set(
|
|
@@ -42,6 +49,11 @@ export class ContractClassStore {
|
|
|
42
49
|
}
|
|
43
50
|
|
|
44
51
|
async deleteContractClasses(contractClass: ContractClassPublic, blockNumber: number): Promise<void> {
|
|
52
|
+
// Protocol contracts are preloaded at block 0 and must never be deleted, even when the block that
|
|
53
|
+
// (re-)published them on-chain is unwound by a reorg.
|
|
54
|
+
if (isProtocolContractClass(contractClass.id)) {
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
45
57
|
const restoredContractClass = await this.#contractClasses.getAsync(contractClass.id.toString());
|
|
46
58
|
if (restoredContractClass && deserializeContractClassPublic(restoredContractClass).l2BlockNumber >= blockNumber) {
|
|
47
59
|
await this.db.transactionAsync(async () => {
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { Fr } from '@aztec/foundation/curves/bn254';
|
|
2
2
|
import type { AztecAsyncKVStore, AztecAsyncMap } from '@aztec/kv-store';
|
|
3
|
+
import { isProtocolContract } from '@aztec/protocol-contracts';
|
|
3
4
|
import type { AztecAddress } from '@aztec/stdlib/aztec-address';
|
|
4
5
|
import {
|
|
5
6
|
type ContractInstanceUpdateWithAddress,
|
|
@@ -29,6 +30,11 @@ export class ContractInstanceStore {
|
|
|
29
30
|
return this.db.transactionAsync(async () => {
|
|
30
31
|
const key = contractInstance.address.toString();
|
|
31
32
|
if (await this.#contractInstances.hasAsync(key)) {
|
|
33
|
+
// Protocol contracts are preloaded at block 0, so a later on-chain (re-)publish of a bundled
|
|
34
|
+
// protocol instance is valid and must be a no-op. Keep the existing block-0 entry untouched.
|
|
35
|
+
if (isProtocolContract(contractInstance.address)) {
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
32
38
|
throw new Error(
|
|
33
39
|
`Contract instance at ${key} already exists (deployed at block ${await this.#contractInstancePublishedAt.getAsync(key)}), cannot add again at block ${blockNumber}`,
|
|
34
40
|
);
|
|
@@ -39,6 +45,11 @@ export class ContractInstanceStore {
|
|
|
39
45
|
}
|
|
40
46
|
|
|
41
47
|
deleteContractInstance(contractInstance: ContractInstanceWithAddress): Promise<void> {
|
|
48
|
+
// Protocol contracts are preloaded at block 0 and must never be deleted, even when the block that
|
|
49
|
+
// (re-)published them on-chain is unwound by a reorg.
|
|
50
|
+
if (isProtocolContract(contractInstance.address)) {
|
|
51
|
+
return Promise.resolve();
|
|
52
|
+
}
|
|
42
53
|
return this.db.transactionAsync(async () => {
|
|
43
54
|
await this.#contractInstances.delete(contractInstance.address.toString());
|
|
44
55
|
await this.#contractInstancePublishedAt.delete(contractInstance.address.toString());
|
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
import { GENESIS_BLOCK_HEADER_HASH
|
|
2
|
-
import {
|
|
3
|
-
import { type BlockData, type CheckpointId, GENESIS_CHECKPOINT_HEADER_HASH, type L2Tips } from '@aztec/stdlib/block';
|
|
1
|
+
import { GENESIS_BLOCK_HEADER_HASH } from '@aztec/constants';
|
|
2
|
+
import type { L2Tips } from '@aztec/stdlib/block';
|
|
4
3
|
|
|
5
4
|
import type { BlockStore } from './block_store.js';
|
|
6
5
|
|
|
7
6
|
/**
|
|
8
7
|
* In-memory cache for L2 chain tips (proposed, checkpointed, proven, finalized).
|
|
9
8
|
* Populated from the BlockStore on first access, then kept up-to-date by the ArchiverDataStoreUpdater.
|
|
10
|
-
* Refresh calls should happen
|
|
9
|
+
* Refresh calls should happen after the store transaction that mutates block data has committed,
|
|
10
|
+
* so the cache loads from committed state and is never replaced if the writer aborts.
|
|
11
11
|
*/
|
|
12
12
|
export class L2TipsCache {
|
|
13
13
|
#tipsPromise: Promise<L2Tips> | undefined;
|
|
@@ -16,74 +16,12 @@ export class L2TipsCache {
|
|
|
16
16
|
|
|
17
17
|
/** Returns the cached L2 tips. Loads from the block store on first call. */
|
|
18
18
|
public getL2Tips(): Promise<L2Tips> {
|
|
19
|
-
return (this.#tipsPromise ??= this.
|
|
19
|
+
return (this.#tipsPromise ??= this.blockStore.getL2TipsData(GENESIS_BLOCK_HEADER_HASH));
|
|
20
20
|
}
|
|
21
21
|
|
|
22
|
-
/** Reloads the L2 tips from the block store. Should be called
|
|
22
|
+
/** Reloads the L2 tips from the block store. Should be called after the writer transaction has committed. */
|
|
23
23
|
public async refresh(): Promise<void> {
|
|
24
|
-
this.#tipsPromise = this.
|
|
24
|
+
this.#tipsPromise = this.blockStore.getL2TipsData(GENESIS_BLOCK_HEADER_HASH);
|
|
25
25
|
await this.#tipsPromise;
|
|
26
26
|
}
|
|
27
|
-
|
|
28
|
-
private async loadFromStore(): Promise<L2Tips> {
|
|
29
|
-
const [latestBlockNumber, provenBlockNumber, checkpointedBlockNumber, finalizedBlockNumber] = await Promise.all([
|
|
30
|
-
this.blockStore.getLatestBlockNumber(),
|
|
31
|
-
this.blockStore.getProvenBlockNumber(),
|
|
32
|
-
this.blockStore.getCheckpointedL2BlockNumber(),
|
|
33
|
-
this.blockStore.getFinalizedL2BlockNumber(),
|
|
34
|
-
]);
|
|
35
|
-
|
|
36
|
-
const genesisBlockHeader = {
|
|
37
|
-
blockHash: GENESIS_BLOCK_HEADER_HASH,
|
|
38
|
-
checkpointNumber: CheckpointNumber.ZERO,
|
|
39
|
-
} as const;
|
|
40
|
-
const beforeInitialBlockNumber = BlockNumber(INITIAL_L2_BLOCK_NUM - 1);
|
|
41
|
-
|
|
42
|
-
const getBlockData = (blockNumber: BlockNumber) =>
|
|
43
|
-
blockNumber > beforeInitialBlockNumber ? this.blockStore.getBlockData(blockNumber) : genesisBlockHeader;
|
|
44
|
-
|
|
45
|
-
const [latestBlockData, provenBlockData, checkpointedBlockData, finalizedBlockData] = await Promise.all(
|
|
46
|
-
[latestBlockNumber, provenBlockNumber, checkpointedBlockNumber, finalizedBlockNumber].map(getBlockData),
|
|
47
|
-
);
|
|
48
|
-
|
|
49
|
-
if (!latestBlockData || !provenBlockData || !finalizedBlockData || !checkpointedBlockData) {
|
|
50
|
-
throw new Error('Failed to load block data for L2 tips');
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
const [provenCheckpointId, finalizedCheckpointId, checkpointedCheckpointId] = await Promise.all([
|
|
54
|
-
this.getCheckpointIdForBlock(provenBlockData),
|
|
55
|
-
this.getCheckpointIdForBlock(finalizedBlockData),
|
|
56
|
-
this.getCheckpointIdForBlock(checkpointedBlockData),
|
|
57
|
-
]);
|
|
58
|
-
|
|
59
|
-
return {
|
|
60
|
-
proposed: { number: latestBlockNumber, hash: latestBlockData.blockHash.toString() },
|
|
61
|
-
proven: {
|
|
62
|
-
block: { number: provenBlockNumber, hash: provenBlockData.blockHash.toString() },
|
|
63
|
-
checkpoint: provenCheckpointId,
|
|
64
|
-
},
|
|
65
|
-
finalized: {
|
|
66
|
-
block: { number: finalizedBlockNumber, hash: finalizedBlockData.blockHash.toString() },
|
|
67
|
-
checkpoint: finalizedCheckpointId,
|
|
68
|
-
},
|
|
69
|
-
checkpointed: {
|
|
70
|
-
block: { number: checkpointedBlockNumber, hash: checkpointedBlockData.blockHash.toString() },
|
|
71
|
-
checkpoint: checkpointedCheckpointId,
|
|
72
|
-
},
|
|
73
|
-
};
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
private async getCheckpointIdForBlock(blockData: Pick<BlockData, 'checkpointNumber'>): Promise<CheckpointId> {
|
|
77
|
-
const checkpointData = await this.blockStore.getCheckpointData(blockData.checkpointNumber);
|
|
78
|
-
if (!checkpointData) {
|
|
79
|
-
return {
|
|
80
|
-
number: CheckpointNumber.ZERO,
|
|
81
|
-
hash: GENESIS_CHECKPOINT_HEADER_HASH.toString(),
|
|
82
|
-
};
|
|
83
|
-
}
|
|
84
|
-
return {
|
|
85
|
-
number: checkpointData.checkpointNumber,
|
|
86
|
-
hash: checkpointData.header.hash().toString(),
|
|
87
|
-
};
|
|
88
|
-
}
|
|
89
27
|
}
|
package/src/store/log_store.ts
CHANGED
|
@@ -24,6 +24,17 @@ import { TxHash } from '@aztec/stdlib/tx';
|
|
|
24
24
|
|
|
25
25
|
import type { BlockStore } from './block_store.js';
|
|
26
26
|
|
|
27
|
+
/**
|
|
28
|
+
* Tag key for a log: the string form of its first field, or the empty string when the log carries no
|
|
29
|
+
* fields. A protocol-valid public log can carry zero fields (e.g. a raw AVM `EMITPUBLICLOG` with
|
|
30
|
+
* `logSize = 0`), which has no tag to index by. Keying it under the empty tag keeps it retrievable via
|
|
31
|
+
* the per-block read (and droppable on reorg) while never matching a real tag query — instead of reading
|
|
32
|
+
* `fields[0]` off an empty array and aborting the whole block-ingestion transaction.
|
|
33
|
+
*/
|
|
34
|
+
function tagKeyForLog(fields: Fr[]): string {
|
|
35
|
+
return fields.length > 0 ? fields[0].toString() : '';
|
|
36
|
+
}
|
|
37
|
+
|
|
27
38
|
/**
|
|
28
39
|
* A store for logs
|
|
29
40
|
*/
|
|
@@ -70,11 +81,12 @@ export class LogStore {
|
|
|
70
81
|
const txHash = txEffect.txHash;
|
|
71
82
|
|
|
72
83
|
txEffect.privateLogs.forEach(log => {
|
|
73
|
-
// Private logs use SiloedTag (already siloed by kernel)
|
|
74
|
-
|
|
75
|
-
|
|
84
|
+
// Private logs use SiloedTag (already siloed by kernel). A zero-field log has no tag and is keyed
|
|
85
|
+
// under the empty tag rather than throwing on log.fields[0].
|
|
86
|
+
const tagKey = tagKeyForLog(log.fields);
|
|
87
|
+
this.#log.debug(`Found private log with tag ${tagKey} in block ${block.number}`);
|
|
76
88
|
|
|
77
|
-
const currentLogs = privateTaggedLogs.get(
|
|
89
|
+
const currentLogs = privateTaggedLogs.get(tagKey) ?? [];
|
|
78
90
|
currentLogs.push(
|
|
79
91
|
new TxScopedL2Log(
|
|
80
92
|
txHash,
|
|
@@ -85,16 +97,17 @@ export class LogStore {
|
|
|
85
97
|
txEffect.nullifiers[0],
|
|
86
98
|
).toBuffer(),
|
|
87
99
|
);
|
|
88
|
-
privateTaggedLogs.set(
|
|
100
|
+
privateTaggedLogs.set(tagKey, currentLogs);
|
|
89
101
|
});
|
|
90
102
|
|
|
91
103
|
txEffect.publicLogs.forEach(log => {
|
|
92
|
-
// Public logs use Tag directly (not siloed) and are stored with contract address
|
|
93
|
-
|
|
104
|
+
// Public logs use Tag directly (not siloed) and are stored with contract address. A zero-field
|
|
105
|
+
// log has no tag and is keyed under the empty tag rather than throwing on log.fields[0].
|
|
106
|
+
const tagKey = tagKeyForLog(log.fields);
|
|
94
107
|
const contractAddress = log.contractAddress;
|
|
95
|
-
const key = `${contractAddress.toString()}_${
|
|
108
|
+
const key = `${contractAddress.toString()}_${tagKey}`;
|
|
96
109
|
this.#log.debug(
|
|
97
|
-
`Found public log with tag ${
|
|
110
|
+
`Found public log with tag ${tagKey} from contract ${contractAddress.toString()} in block ${block.number}`,
|
|
98
111
|
);
|
|
99
112
|
|
|
100
113
|
const currentLogs = publicTaggedLogs.get(key) ?? [];
|