@aztec/archiver 3.0.0-nightly.20251213 → 3.0.0-nightly.20251216

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.
@@ -5,4 +5,4 @@ import type { ArchiverDataStore } from './archiver_store.js';
5
5
  * @param getStore - Returns an instance of a store that's already been initialized.
6
6
  */
7
7
  export declare function describeArchiverDataStore(testName: string, getStore: () => ArchiverDataStore | Promise<ArchiverDataStore>): void;
8
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXJjaGl2ZXJfc3RvcmVfdGVzdF9zdWl0ZS5kLnRzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2FyY2hpdmVyL2FyY2hpdmVyX3N0b3JlX3Rlc3Rfc3VpdGUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBcUNBLE9BQU8sNEJBQTRCLENBQUM7QUFJcEMsT0FBTyxLQUFLLEVBQUUsaUJBQWlCLEVBQXdCLE1BQU0scUJBQXFCLENBQUM7QUFLbkY7OztHQUdHO0FBQ0gsd0JBQWdCLHlCQUF5QixDQUN2QyxRQUFRLEVBQUUsTUFBTSxFQUNoQixRQUFRLEVBQUUsTUFBTSxpQkFBaUIsR0FBRyxPQUFPLENBQUMsaUJBQWlCLENBQUMsUUFpdEMvRCJ9
8
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXJjaGl2ZXJfc3RvcmVfdGVzdF9zdWl0ZS5kLnRzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2FyY2hpdmVyL2FyY2hpdmVyX3N0b3JlX3Rlc3Rfc3VpdGUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBcUNBLE9BQU8sNEJBQTRCLENBQUM7QUFJcEMsT0FBTyxLQUFLLEVBQUUsaUJBQWlCLEVBQXdCLE1BQU0scUJBQXFCLENBQUM7QUFLbkY7OztHQUdHO0FBQ0gsd0JBQWdCLHlCQUF5QixDQUN2QyxRQUFRLEVBQUUsTUFBTSxFQUNoQixRQUFRLEVBQUUsTUFBTSxpQkFBaUIsR0FBRyxPQUFPLENBQUMsaUJBQWlCLENBQUMsUUFzeEMvRCJ9
@@ -1 +1 @@
1
- {"version":3,"file":"archiver_store_test_suite.d.ts","sourceRoot":"","sources":["../../src/archiver/archiver_store_test_suite.ts"],"names":[],"mappings":"AAqCA,OAAO,4BAA4B,CAAC;AAIpC,OAAO,KAAK,EAAE,iBAAiB,EAAwB,MAAM,qBAAqB,CAAC;AAKnF;;;GAGG;AACH,wBAAgB,yBAAyB,CACvC,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,iBAAiB,GAAG,OAAO,CAAC,iBAAiB,CAAC,QAitC/D"}
1
+ {"version":3,"file":"archiver_store_test_suite.d.ts","sourceRoot":"","sources":["../../src/archiver/archiver_store_test_suite.ts"],"names":[],"mappings":"AAqCA,OAAO,4BAA4B,CAAC;AAIpC,OAAO,KAAK,EAAE,iBAAiB,EAAwB,MAAM,qBAAqB,CAAC;AAKnF;;;GAGG;AACH,wBAAgB,yBAAyB,CACvC,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,iBAAiB,GAAG,OAAO,CAAC,iBAAiB,CAAC,QAsxC/D"}
@@ -10,7 +10,7 @@ import { sleep } from '@aztec/foundation/sleep';
10
10
  import { AztecAddress } from '@aztec/stdlib/aztec-address';
11
11
  import { CommitteeAttestation, EthAddress, L2Block, L2BlockHash, PublishedL2Block, randomBlockInfo, wrapDataInBlock } from '@aztec/stdlib/block';
12
12
  import { SerializableContractInstance, computePublicBytecodeCommitment } from '@aztec/stdlib/contract';
13
- import { LogId, PrivateLog, PublicLog } from '@aztec/stdlib/logs';
13
+ import { ContractClassLog, LogId, PrivateLog, PublicLog } from '@aztec/stdlib/logs';
14
14
  import { InboxLeaf } from '@aztec/stdlib/messaging';
15
15
  import { makeContractClassPublic, makeExecutablePrivateFunctionWithMembershipProof, makeUtilityFunctionWithMembershipProof } from '@aztec/stdlib/testing';
16
16
  import '@aztec/stdlib/testing/jest';
@@ -888,6 +888,7 @@ import { MessageStoreError } from './kv_archiver_store/message_store.js';
888
888
  [
889
889
  expect.objectContaining({
890
890
  blockNumber: 2,
891
+ blockHash: L2BlockHash.fromField(await blocks[2 - 1].block.hash()),
891
892
  log: makePrivateLog(tags[0]),
892
893
  isFromPublic: false
893
894
  })
@@ -895,6 +896,7 @@ import { MessageStoreError } from './kv_archiver_store/message_store.js';
895
896
  [
896
897
  expect.objectContaining({
897
898
  blockNumber: 1,
899
+ blockHash: L2BlockHash.fromField(await blocks[1 - 1].block.hash()),
898
900
  log: makePrivateLog(tags[1]),
899
901
  isFromPublic: false
900
902
  })
@@ -911,11 +913,13 @@ import { MessageStoreError } from './kv_archiver_store/message_store.js';
911
913
  [
912
914
  expect.objectContaining({
913
915
  blockNumber: 1,
916
+ blockHash: L2BlockHash.fromField(await blocks[1 - 1].block.hash()),
914
917
  log: makePrivateLog(tags[0]),
915
918
  isFromPublic: false
916
919
  }),
917
920
  expect.objectContaining({
918
921
  blockNumber: 1,
922
+ blockHash: L2BlockHash.fromField(await blocks[1 - 1].block.hash()),
919
923
  log: makePublicLog(tags[0]),
920
924
  isFromPublic: true
921
925
  })
@@ -943,11 +947,13 @@ import { MessageStoreError } from './kv_archiver_store/message_store.js';
943
947
  [
944
948
  expect.objectContaining({
945
949
  blockNumber: 1,
950
+ blockHash: L2BlockHash.fromField(await blocks[1 - 1].block.hash()),
946
951
  log: makePrivateLog(tags[0]),
947
952
  isFromPublic: false
948
953
  }),
949
954
  expect.objectContaining({
950
955
  blockNumber: newBlockNumber,
956
+ blockHash: L2BlockHash.fromField(await blocks[newBlockNumber - 1].block.hash()),
951
957
  log: newLog,
952
958
  isFromPublic: false
953
959
  })
@@ -965,6 +971,7 @@ import { MessageStoreError } from './kv_archiver_store/message_store.js';
965
971
  [
966
972
  expect.objectContaining({
967
973
  blockNumber: 1,
974
+ blockHash: L2BlockHash.fromField(await blocks[1 - 1].block.hash()),
968
975
  log: makePrivateLog(tags[1]),
969
976
  isFromPublic: false
970
977
  })
@@ -1025,6 +1032,16 @@ import { MessageStoreError } from './kv_archiver_store/message_store.js';
1025
1032
  expect(log.id.txIndex).toEqual(targetTxIndex);
1026
1033
  }
1027
1034
  });
1035
+ it('returns block hash on public log ids', async ()=>{
1036
+ const targetBlock = blocks[0].block;
1037
+ const expectedBlockHash = L2BlockHash.fromField(await targetBlock.hash());
1038
+ const logs = (await store.getPublicLogs({
1039
+ fromBlock: targetBlock.number,
1040
+ toBlock: targetBlock.number + 1
1041
+ })).logs;
1042
+ expect(logs.length).toBeGreaterThan(0);
1043
+ expect(logs.every((log)=>log.id.blockHash.equals(expectedBlockHash))).toBe(true);
1044
+ });
1028
1045
  it('"fromBlock" and "toBlock" filter params are respected', async ()=>{
1029
1046
  // Set "fromBlock" and "toBlock"
1030
1047
  const fromBlock = 3;
@@ -1062,7 +1079,8 @@ import { MessageStoreError } from './kv_archiver_store/message_store.js';
1062
1079
  const targetBlockIndex = randomInt(numBlocks);
1063
1080
  const targetTxIndex = randomInt(txsPerBlock);
1064
1081
  const targetLogIndex = randomInt(numPublicLogs);
1065
- const afterLog = new LogId(BlockNumber(targetBlockIndex + INITIAL_L2_BLOCK_NUM), targetTxIndex, targetLogIndex);
1082
+ const targetBlockHash = L2BlockHash.fromField(await blocks[targetBlockIndex].block.hash());
1083
+ const afterLog = new LogId(BlockNumber(targetBlockIndex + INITIAL_L2_BLOCK_NUM), targetBlockHash, targetTxIndex, targetLogIndex);
1066
1084
  const response = await store.getPublicLogs({
1067
1085
  afterLog
1068
1086
  });
@@ -1082,7 +1100,7 @@ import { MessageStoreError } from './kv_archiver_store/message_store.js';
1082
1100
  it('"txHash" filter param is ignored when "afterLog" is set', async ()=>{
1083
1101
  // Get random txHash
1084
1102
  const txHash = TxHash.random();
1085
- const afterLog = new LogId(BlockNumber(1), 0, 0);
1103
+ const afterLog = new LogId(BlockNumber(1), L2BlockHash.random(), 0, 0);
1086
1104
  const response = await store.getPublicLogs({
1087
1105
  txHash,
1088
1106
  afterLog
@@ -1129,7 +1147,7 @@ import { MessageStoreError } from './kv_archiver_store/message_store.js';
1129
1147
  logs = (await store.getPublicLogs({
1130
1148
  fromBlock: BlockNumber(2),
1131
1149
  toBlock: BlockNumber(5),
1132
- afterLog: new LogId(BlockNumber(4), 0, 0)
1150
+ afterLog: new LogId(BlockNumber(4), L2BlockHash.random(), 0, 0)
1133
1151
  })).logs;
1134
1152
  blockNumbers = new Set(logs.map((log)=>log.id.blockNumber));
1135
1153
  expect(blockNumbers).toEqual(new Set([
@@ -1137,13 +1155,13 @@ import { MessageStoreError } from './kv_archiver_store/message_store.js';
1137
1155
  ]));
1138
1156
  logs = (await store.getPublicLogs({
1139
1157
  toBlock: BlockNumber(5),
1140
- afterLog: new LogId(BlockNumber(5), 1, 0)
1158
+ afterLog: new LogId(BlockNumber(5), L2BlockHash.random(), 1, 0)
1141
1159
  })).logs;
1142
1160
  expect(logs.length).toBe(0);
1143
1161
  logs = (await store.getPublicLogs({
1144
1162
  fromBlock: BlockNumber(2),
1145
1163
  toBlock: BlockNumber(5),
1146
- afterLog: new LogId(BlockNumber(100), 0, 0)
1164
+ afterLog: new LogId(BlockNumber(100), L2BlockHash.random(), 0, 0)
1147
1165
  })).logs;
1148
1166
  expect(logs.length).toBe(0);
1149
1167
  });
@@ -1152,7 +1170,8 @@ import { MessageStoreError } from './kv_archiver_store/message_store.js';
1152
1170
  const targetBlockIndex = randomInt(numBlocks);
1153
1171
  const targetTxIndex = randomInt(txsPerBlock);
1154
1172
  const targetLogIndex = randomInt(numPublicLogs);
1155
- const afterLog = new LogId(BlockNumber(targetBlockIndex + INITIAL_L2_BLOCK_NUM), targetTxIndex, targetLogIndex);
1173
+ const targetBlockHash = L2BlockHash.fromField(await blocks[targetBlockIndex].block.hash());
1174
+ const afterLog = new LogId(BlockNumber(targetBlockIndex + INITIAL_L2_BLOCK_NUM), targetBlockHash, targetTxIndex, targetLogIndex);
1156
1175
  const response = await store.getPublicLogs({
1157
1176
  afterLog,
1158
1177
  fromBlock: afterLog.blockNumber
@@ -1171,6 +1190,36 @@ import { MessageStoreError } from './kv_archiver_store/message_store.js';
1171
1190
  }
1172
1191
  });
1173
1192
  });
1193
+ describe('getContractClassLogs', ()=>{
1194
+ let targetBlock;
1195
+ let expectedContractClassLog;
1196
+ beforeEach(async ()=>{
1197
+ await store.addBlocks(blocks);
1198
+ targetBlock = blocks[0].block;
1199
+ expectedContractClassLog = await ContractClassLog.random();
1200
+ targetBlock.body.txEffects.forEach((txEffect, index)=>{
1201
+ txEffect.contractClassLogs = index === 0 ? [
1202
+ expectedContractClassLog
1203
+ ] : [];
1204
+ });
1205
+ await store.addLogs([
1206
+ targetBlock
1207
+ ]);
1208
+ });
1209
+ it('returns block hash on contract class log ids', async ()=>{
1210
+ const result = await store.getContractClassLogs({
1211
+ fromBlock: targetBlock.number,
1212
+ toBlock: targetBlock.number + 1
1213
+ });
1214
+ expect(result.maxLogsHit).toBeFalsy();
1215
+ expect(result.logs).toHaveLength(1);
1216
+ const [{ id, log }] = result.logs;
1217
+ const expectedBlockHash = L2BlockHash.fromField(await targetBlock.hash());
1218
+ expect(id.blockHash.equals(expectedBlockHash)).toBe(true);
1219
+ expect(id.blockNumber).toEqual(targetBlock.number);
1220
+ expect(log).toEqual(expectedContractClassLog);
1221
+ });
1222
+ });
1174
1223
  describe('pendingChainValidationStatus', ()=>{
1175
1224
  it('should return undefined when no status is set', async ()=>{
1176
1225
  const status = await store.getPendingChainValidationStatus();
@@ -13,7 +13,7 @@ import type { UInt64 } from '@aztec/stdlib/types';
13
13
  import type { ArchiverDataStore, ArchiverL1SynchPoint } from '../archiver_store.js';
14
14
  import type { InboxMessage } from '../structs/inbox_message.js';
15
15
  import type { PublishedL2Block } from '../structs/published.js';
16
- export declare const ARCHIVER_DB_VERSION = 4;
16
+ export declare const ARCHIVER_DB_VERSION = 5;
17
17
  export declare const MAX_FUNCTION_SIGNATURES = 1000;
18
18
  export declare const MAX_FUNCTION_NAME_LEN = 256;
19
19
  /**
@@ -8,7 +8,7 @@ import { ContractClassStore } from './contract_class_store.js';
8
8
  import { ContractInstanceStore } from './contract_instance_store.js';
9
9
  import { LogStore } from './log_store.js';
10
10
  import { MessageStore } from './message_store.js';
11
- export const ARCHIVER_DB_VERSION = 4;
11
+ export const ARCHIVER_DB_VERSION = 5;
12
12
  export const MAX_FUNCTION_SIGNATURES = 1000;
13
13
  export const MAX_FUNCTION_NAME_LEN = 256;
14
14
  /**
@@ -1,6 +1,6 @@
1
- import type { Fr } from '@aztec/foundation/curves/bn254';
1
+ import { Fr } from '@aztec/foundation/curves/bn254';
2
2
  import type { AztecAsyncKVStore } from '@aztec/kv-store';
3
- import type { L2Block } from '@aztec/stdlib/block';
3
+ import { type L2Block } from '@aztec/stdlib/block';
4
4
  import type { GetContractClassLogsResponse, GetPublicLogsResponse } from '@aztec/stdlib/interfaces/client';
5
5
  import { type LogFilter, TxScopedL2Log } from '@aztec/stdlib/logs';
6
6
  import type { BlockStore } from './block_store.js';
@@ -39,4 +39,4 @@ export declare class LogStore {
39
39
  */
40
40
  getContractClassLogs(filter: LogFilter): Promise<GetContractClassLogsResponse>;
41
41
  }
42
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibG9nX3N0b3JlLmQudHMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvYXJjaGl2ZXIva3ZfYXJjaGl2ZXJfc3RvcmUvbG9nX3N0b3JlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUVBLE9BQU8sS0FBSyxFQUFFLEVBQUUsRUFBRSxNQUFNLGdDQUFnQyxDQUFDO0FBR3pELE9BQU8sS0FBSyxFQUFFLGlCQUFpQixFQUFpQixNQUFNLGlCQUFpQixDQUFDO0FBQ3hFLE9BQU8sS0FBSyxFQUFFLE9BQU8sRUFBRSxNQUFNLHFCQUFxQixDQUFDO0FBQ25ELE9BQU8sS0FBSyxFQUFFLDRCQUE0QixFQUFFLHFCQUFxQixFQUFFLE1BQU0saUNBQWlDLENBQUM7QUFDM0csT0FBTyxFQUlMLEtBQUssU0FBUyxFQUdkLGFBQWEsRUFDZCxNQUFNLG9CQUFvQixDQUFDO0FBRTVCLE9BQU8sS0FBSyxFQUFFLFVBQVUsRUFBRSxNQUFNLGtCQUFrQixDQUFDO0FBRW5EOztHQUVHO0FBQ0gscUJBQWEsUUFBUTs7SUFTakIsT0FBTyxDQUFDLEVBQUU7SUFDVixPQUFPLENBQUMsVUFBVTtJQUZwQixZQUNVLEVBQUUsRUFBRSxpQkFBaUIsRUFDckIsVUFBVSxFQUFFLFVBQVUsRUFDOUIsZUFBZSxHQUFFLE1BQWEsRUFRL0I7SUFnQ0Q7Ozs7T0FJRztJQUNILE9BQU8sQ0FBQyxNQUFNLEVBQUUsT0FBTyxFQUFFLEdBQUcsT0FBTyxDQUFDLE9BQU8sQ0FBQyxDQTBEM0M7SUFFRCxVQUFVLENBQUMsTUFBTSxFQUFFLE9BQU8sRUFBRSxHQUFHLE9BQU8sQ0FBQyxPQUFPLENBQUMsQ0F3QjlDO0lBRUQ7Ozs7O09BS0c7SUFDRyxhQUFhLENBQUMsSUFBSSxFQUFFLEVBQUUsRUFBRSxFQUFFLFdBQVcsQ0FBQyxFQUFFLE1BQU0sR0FBRyxPQUFPLENBQUMsYUFBYSxFQUFFLEVBQUUsQ0FBQyxDQVFoRjtJQUVEOzs7O09BSUc7SUFDSCxhQUFhLENBQUMsTUFBTSxFQUFFLFNBQVMsR0FBRyxPQUFPLENBQUMscUJBQXFCLENBQUMsQ0FRL0Q7SUF1RUQ7Ozs7T0FJRztJQUNILG9CQUFvQixDQUFDLE1BQU0sRUFBRSxTQUFTLEdBQUcsT0FBTyxDQUFDLDRCQUE0QixDQUFDLENBUTdFO0NBcUdGIn0=
42
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibG9nX3N0b3JlLmQudHMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvYXJjaGl2ZXIva3ZfYXJjaGl2ZXJfc3RvcmUvbG9nX3N0b3JlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUVBLE9BQU8sRUFBRSxFQUFFLEVBQUUsTUFBTSxnQ0FBZ0MsQ0FBQztBQUdwRCxPQUFPLEtBQUssRUFBRSxpQkFBaUIsRUFBaUIsTUFBTSxpQkFBaUIsQ0FBQztBQUN4RSxPQUFPLEVBQUUsS0FBSyxPQUFPLEVBQWUsTUFBTSxxQkFBcUIsQ0FBQztBQUNoRSxPQUFPLEtBQUssRUFBRSw0QkFBNEIsRUFBRSxxQkFBcUIsRUFBRSxNQUFNLGlDQUFpQyxDQUFDO0FBQzNHLE9BQU8sRUFJTCxLQUFLLFNBQVMsRUFHZCxhQUFhLEVBQ2QsTUFBTSxvQkFBb0IsQ0FBQztBQUU1QixPQUFPLEtBQUssRUFBRSxVQUFVLEVBQUUsTUFBTSxrQkFBa0IsQ0FBQztBQUVuRDs7R0FFRztBQUNILHFCQUFhLFFBQVE7O0lBU2pCLE9BQU8sQ0FBQyxFQUFFO0lBQ1YsT0FBTyxDQUFDLFVBQVU7SUFGcEIsWUFDVSxFQUFFLEVBQUUsaUJBQWlCLEVBQ3JCLFVBQVUsRUFBRSxVQUFVLEVBQzlCLGVBQWUsR0FBRSxNQUFhLEVBUS9CO0lBcUNEOzs7O09BSUc7SUFDRyxPQUFPLENBQUMsTUFBTSxFQUFFLE9BQU8sRUFBRSxHQUFHLE9BQU8sQ0FBQyxPQUFPLENBQUMsQ0E4RGpEO0lBZ0JELFVBQVUsQ0FBQyxNQUFNLEVBQUUsT0FBTyxFQUFFLEdBQUcsT0FBTyxDQUFDLE9BQU8sQ0FBQyxDQXdCOUM7SUFFRDs7Ozs7T0FLRztJQUNHLGFBQWEsQ0FBQyxJQUFJLEVBQUUsRUFBRSxFQUFFLEVBQUUsV0FBVyxDQUFDLEVBQUUsTUFBTSxHQUFHLE9BQU8sQ0FBQyxhQUFhLEVBQUUsRUFBRSxDQUFDLENBUWhGO0lBRUQ7Ozs7T0FJRztJQUNILGFBQWEsQ0FBQyxNQUFNLEVBQUUsU0FBUyxHQUFHLE9BQU8sQ0FBQyxxQkFBcUIsQ0FBQyxDQVEvRDtJQTZFRDs7OztPQUlHO0lBQ0gsb0JBQW9CLENBQUMsTUFBTSxFQUFFLFNBQVMsR0FBRyxPQUFPLENBQUMsNEJBQTRCLENBQUMsQ0FRN0U7Q0E2R0YifQ==
@@ -1 +1 @@
1
- {"version":3,"file":"log_store.d.ts","sourceRoot":"","sources":["../../../src/archiver/kv_archiver_store/log_store.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,gCAAgC,CAAC;AAGzD,OAAO,KAAK,EAAE,iBAAiB,EAAiB,MAAM,iBAAiB,CAAC;AACxE,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,KAAK,EAAE,4BAA4B,EAAE,qBAAqB,EAAE,MAAM,iCAAiC,CAAC;AAC3G,OAAO,EAIL,KAAK,SAAS,EAGd,aAAa,EACd,MAAM,oBAAoB,CAAC;AAE5B,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAEnD;;GAEG;AACH,qBAAa,QAAQ;;IASjB,OAAO,CAAC,EAAE;IACV,OAAO,CAAC,UAAU;IAFpB,YACU,EAAE,EAAE,iBAAiB,EACrB,UAAU,EAAE,UAAU,EAC9B,eAAe,GAAE,MAAa,EAQ/B;IAgCD;;;;OAIG;IACH,OAAO,CAAC,MAAM,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC,OAAO,CAAC,CA0D3C;IAED,UAAU,CAAC,MAAM,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC,OAAO,CAAC,CAwB9C;IAED;;;;;OAKG;IACG,aAAa,CAAC,IAAI,EAAE,EAAE,EAAE,EAAE,WAAW,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,EAAE,EAAE,CAAC,CAQhF;IAED;;;;OAIG;IACH,aAAa,CAAC,MAAM,EAAE,SAAS,GAAG,OAAO,CAAC,qBAAqB,CAAC,CAQ/D;IAuED;;;;OAIG;IACH,oBAAoB,CAAC,MAAM,EAAE,SAAS,GAAG,OAAO,CAAC,4BAA4B,CAAC,CAQ7E;CAqGF"}
1
+ {"version":3,"file":"log_store.d.ts","sourceRoot":"","sources":["../../../src/archiver/kv_archiver_store/log_store.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,EAAE,EAAE,MAAM,gCAAgC,CAAC;AAGpD,OAAO,KAAK,EAAE,iBAAiB,EAAiB,MAAM,iBAAiB,CAAC;AACxE,OAAO,EAAE,KAAK,OAAO,EAAe,MAAM,qBAAqB,CAAC;AAChE,OAAO,KAAK,EAAE,4BAA4B,EAAE,qBAAqB,EAAE,MAAM,iCAAiC,CAAC;AAC3G,OAAO,EAIL,KAAK,SAAS,EAGd,aAAa,EACd,MAAM,oBAAoB,CAAC;AAE5B,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAEnD;;GAEG;AACH,qBAAa,QAAQ;;IASjB,OAAO,CAAC,EAAE;IACV,OAAO,CAAC,UAAU;IAFpB,YACU,EAAE,EAAE,iBAAiB,EACrB,UAAU,EAAE,UAAU,EAC9B,eAAe,GAAE,MAAa,EAQ/B;IAqCD;;;;OAIG;IACG,OAAO,CAAC,MAAM,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC,OAAO,CAAC,CA8DjD;IAgBD,UAAU,CAAC,MAAM,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC,OAAO,CAAC,CAwB9C;IAED;;;;;OAKG;IACG,aAAa,CAAC,IAAI,EAAE,EAAE,EAAE,EAAE,WAAW,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,EAAE,EAAE,CAAC,CAQhF;IAED;;;;OAIG;IACH,aAAa,CAAC,MAAM,EAAE,SAAS,GAAG,OAAO,CAAC,qBAAqB,CAAC,CAQ/D;IA6ED;;;;OAIG;IACH,oBAAoB,CAAC,MAAM,EAAE,SAAS,GAAG,OAAO,CAAC,4BAA4B,CAAC,CAQ7E;CA6GF"}
@@ -1,7 +1,9 @@
1
1
  import { INITIAL_L2_BLOCK_NUM, MAX_NOTE_HASHES_PER_TX } from '@aztec/constants';
2
2
  import { BlockNumber } from '@aztec/foundation/branded-types';
3
+ import { Fr } from '@aztec/foundation/curves/bn254';
3
4
  import { createLogger } from '@aztec/foundation/log';
4
5
  import { BufferReader, numToUInt32BE } from '@aztec/foundation/serialize';
6
+ import { L2BlockHash } from '@aztec/stdlib/block';
5
7
  import { ContractClassLog, ExtendedContractClassLog, ExtendedPublicLog, LogId, PublicLog, TxScopedL2Log } from '@aztec/stdlib/logs';
6
8
  /**
7
9
  * A store for logs
@@ -24,7 +26,8 @@ import { ContractClassLog, ExtendedContractClassLog, ExtendedPublicLog, LogId, P
24
26
  this.#contractClassLogsByBlock = db.openMap('archiver_contract_class_logs_by_block');
25
27
  this.#logsMaxPageSize = logsMaxPageSize;
26
28
  }
27
- #extractTaggedLogs(block) {
29
+ async #extractTaggedLogs(block) {
30
+ const blockHash = L2BlockHash.fromField(await block.hash());
28
31
  const taggedLogs = new Map();
29
32
  const dataStartIndexForBlock = block.header.state.partial.noteHashTree.nextAvailableLeafIndex - block.body.txEffects.length * MAX_NOTE_HASHES_PER_TX;
30
33
  block.body.txEffects.forEach((txEffect, txIndex)=>{
@@ -34,14 +37,14 @@ import { ContractClassLog, ExtendedContractClassLog, ExtendedPublicLog, LogId, P
34
37
  const tag = log.fields[0];
35
38
  this.#log.debug(`Found private log with tag ${tag.toString()} in block ${block.number}`);
36
39
  const currentLogs = taggedLogs.get(tag.toString()) ?? [];
37
- currentLogs.push(new TxScopedL2Log(txHash, dataStartIndexForTx, logIndex, block.number, log).toBuffer());
40
+ currentLogs.push(new TxScopedL2Log(txHash, dataStartIndexForTx, logIndex, block.number, blockHash, log).toBuffer());
38
41
  taggedLogs.set(tag.toString(), currentLogs);
39
42
  });
40
43
  txEffect.publicLogs.forEach((log, logIndex)=>{
41
44
  const tag = log.fields[0];
42
45
  this.#log.debug(`Found public log with tag ${tag.toString()} in block ${block.number}`);
43
46
  const currentLogs = taggedLogs.get(tag.toString()) ?? [];
44
- currentLogs.push(new TxScopedL2Log(txHash, dataStartIndexForTx, logIndex, block.number, log).toBuffer());
47
+ currentLogs.push(new TxScopedL2Log(txHash, dataStartIndexForTx, logIndex, block.number, blockHash, log).toBuffer());
45
48
  taggedLogs.set(tag.toString(), currentLogs);
46
49
  });
47
50
  });
@@ -51,9 +54,10 @@ import { ContractClassLog, ExtendedContractClassLog, ExtendedPublicLog, LogId, P
51
54
  * Append new logs to the store's list.
52
55
  * @param blocks - The blocks for which to add the logs.
53
56
  * @returns True if the operation is successful.
54
- */ addLogs(blocks) {
55
- const taggedLogsToAdd = blocks.map((block)=>this.#extractTaggedLogs(block)).reduce((acc, val)=>{
56
- for (const [tag, logs] of val.entries()){
57
+ */ async addLogs(blocks) {
58
+ const taggedLogsInBlocks = await Promise.all(blocks.map((block)=>this.#extractTaggedLogs(block)));
59
+ const taggedLogsToAdd = taggedLogsInBlocks.reduce((acc, taggedLogs)=>{
60
+ for (const [tag, logs] of taggedLogs.entries()){
57
61
  const currentLogs = acc.get(tag) ?? [];
58
62
  acc.set(tag, currentLogs.concat(logs));
59
63
  }
@@ -71,6 +75,7 @@ import { ContractClassLog, ExtendedContractClassLog, ExtendedPublicLog, LogId, P
71
75
  }
72
76
  });
73
77
  for (const block of blocks){
78
+ const blockHash = await block.hash();
74
79
  const tagsInBlock = [];
75
80
  for (const [tag, logs] of taggedLogsToAdd.entries()){
76
81
  await this.#logsByTag.set(tag, logs);
@@ -87,12 +92,25 @@ import { ContractClassLog, ExtendedContractClassLog, ExtendedPublicLog, LogId, P
87
92
  numToUInt32BE(txEffect.contractClassLogs.length),
88
93
  txEffect.contractClassLogs.map((log)=>log.toBuffer())
89
94
  ].flat()).flat();
90
- await this.#publicLogsByBlock.set(block.number, Buffer.concat(publicLogsInBlock));
91
- await this.#contractClassLogsByBlock.set(block.number, Buffer.concat(contractClassLogsInBlock));
95
+ await this.#publicLogsByBlock.set(block.number, this.#packWithBlockHash(blockHash, publicLogsInBlock));
96
+ await this.#contractClassLogsByBlock.set(block.number, this.#packWithBlockHash(blockHash, contractClassLogsInBlock));
92
97
  }
93
98
  return true;
94
99
  });
95
100
  }
101
+ #packWithBlockHash(blockHash, data) {
102
+ return Buffer.concat([
103
+ blockHash.toBuffer(),
104
+ ...data
105
+ ]);
106
+ }
107
+ #unpackBlockHash(reader) {
108
+ const blockHash = reader.remainingBytes() > 0 ? reader.readObject(Fr) : undefined;
109
+ if (!blockHash) {
110
+ throw new Error('Failed to read block hash from log entry buffer');
111
+ }
112
+ return L2BlockHash.fromField(blockHash);
113
+ }
96
114
  deleteLogs(blocks) {
97
115
  return this.db.transactionAsync(async ()=>{
98
116
  const tagsToDelete = (await Promise.all(blocks.map(async (block)=>{
@@ -149,6 +167,7 @@ import { ContractClassLog, ExtendedContractClassLog, ExtendedPublicLog, LogId, P
149
167
  []
150
168
  ];
151
169
  const reader = new BufferReader(buffer);
170
+ const blockHash = this.#unpackBlockHash(reader);
152
171
  while(reader.remainingBytes() > 0){
153
172
  const indexOfTx = reader.readNumber();
154
173
  const numLogsInTx = reader.readNumber();
@@ -159,7 +178,7 @@ import { ContractClassLog, ExtendedContractClassLog, ExtendedPublicLog, LogId, P
159
178
  }
160
179
  const txLogs = publicLogsInBlock[txIndex];
161
180
  const logs = [];
162
- const maxLogsHit = this.#accumulateLogs(logs, blockNumber, txIndex, txLogs, filter);
181
+ const maxLogsHit = this.#accumulateLogs(logs, blockNumber, blockHash, txIndex, txLogs, filter);
163
182
  return {
164
183
  logs,
165
184
  maxLogsHit
@@ -184,6 +203,7 @@ import { ContractClassLog, ExtendedContractClassLog, ExtendedPublicLog, LogId, P
184
203
  []
185
204
  ];
186
205
  const reader = new BufferReader(logBuffer);
206
+ const blockHash = this.#unpackBlockHash(reader);
187
207
  while(reader.remainingBytes() > 0){
188
208
  const indexOfTx = reader.readNumber();
189
209
  const numLogsInTx = reader.readNumber();
@@ -194,7 +214,7 @@ import { ContractClassLog, ExtendedContractClassLog, ExtendedPublicLog, LogId, P
194
214
  }
195
215
  for(let txIndex = filter.afterLog?.txIndex ?? 0; txIndex < publicLogsInBlock.length; txIndex++){
196
216
  const txLogs = publicLogsInBlock[txIndex];
197
- maxLogsHit = this.#accumulateLogs(logs, blockNumber, txIndex, txLogs, filter);
217
+ maxLogsHit = this.#accumulateLogs(logs, blockNumber, blockHash, txIndex, txLogs, filter);
198
218
  if (maxLogsHit) {
199
219
  this.#log.debug(`Max logs hit at block ${blockNumber}`);
200
220
  break loopOverBlocks;
@@ -235,6 +255,7 @@ import { ContractClassLog, ExtendedContractClassLog, ExtendedPublicLog, LogId, P
235
255
  []
236
256
  ];
237
257
  const reader = new BufferReader(contractClassLogsBuffer);
258
+ const blockHash = this.#unpackBlockHash(reader);
238
259
  while(reader.remainingBytes() > 0){
239
260
  const indexOfTx = reader.readNumber();
240
261
  const numLogsInTx = reader.readNumber();
@@ -245,7 +266,7 @@ import { ContractClassLog, ExtendedContractClassLog, ExtendedPublicLog, LogId, P
245
266
  }
246
267
  const txLogs = contractClassLogsInBlock[txIndex];
247
268
  const logs = [];
248
- const maxLogsHit = this.#accumulateLogs(logs, blockNumber, txIndex, txLogs, filter);
269
+ const maxLogsHit = this.#accumulateLogs(logs, blockNumber, blockHash, txIndex, txLogs, filter);
249
270
  return {
250
271
  logs,
251
272
  maxLogsHit
@@ -270,6 +291,7 @@ import { ContractClassLog, ExtendedContractClassLog, ExtendedPublicLog, LogId, P
270
291
  []
271
292
  ];
272
293
  const reader = new BufferReader(logBuffer);
294
+ const blockHash = this.#unpackBlockHash(reader);
273
295
  while(reader.remainingBytes() > 0){
274
296
  const indexOfTx = reader.readNumber();
275
297
  const numLogsInTx = reader.readNumber();
@@ -280,7 +302,7 @@ import { ContractClassLog, ExtendedContractClassLog, ExtendedPublicLog, LogId, P
280
302
  }
281
303
  for(let txIndex = filter.afterLog?.txIndex ?? 0; txIndex < contractClassLogsInBlock.length; txIndex++){
282
304
  const txLogs = contractClassLogsInBlock[txIndex];
283
- maxLogsHit = this.#accumulateLogs(logs, blockNumber, txIndex, txLogs, filter);
305
+ maxLogsHit = this.#accumulateLogs(logs, blockNumber, blockHash, txIndex, txLogs, filter);
284
306
  if (maxLogsHit) {
285
307
  this.#log.debug(`Max logs hit at block ${blockNumber}`);
286
308
  break loopOverBlocks;
@@ -292,16 +314,18 @@ import { ContractClassLog, ExtendedContractClassLog, ExtendedPublicLog, LogId, P
292
314
  maxLogsHit
293
315
  };
294
316
  }
295
- #accumulateLogs(results, blockNumber, txIndex, txLogs, filter) {
317
+ #accumulateLogs(results, blockNumber, blockHash, txIndex, txLogs, filter = {}) {
296
318
  let maxLogsHit = false;
297
319
  let logIndex = typeof filter.afterLog?.logIndex === 'number' ? filter.afterLog.logIndex + 1 : 0;
298
320
  for(; logIndex < txLogs.length; logIndex++){
299
321
  const log = txLogs[logIndex];
300
322
  if (!filter.contractAddress || log.contractAddress.equals(filter.contractAddress)) {
301
323
  if (log instanceof ContractClassLog) {
302
- results.push(new ExtendedContractClassLog(new LogId(BlockNumber(blockNumber), txIndex, logIndex), log));
324
+ results.push(new ExtendedContractClassLog(new LogId(BlockNumber(blockNumber), blockHash, txIndex, logIndex), log));
325
+ } else if (log instanceof PublicLog) {
326
+ results.push(new ExtendedPublicLog(new LogId(BlockNumber(blockNumber), blockHash, txIndex, logIndex), log));
303
327
  } else {
304
- results.push(new ExtendedPublicLog(new LogId(BlockNumber(blockNumber), txIndex, logIndex), log));
328
+ throw new Error('Unknown log type');
305
329
  }
306
330
  if (results.length >= this.#logsMaxPageSize) {
307
331
  maxLogsHit = true;
@@ -111,8 +111,8 @@ async function main() {
111
111
  logger.info('');
112
112
  logger.info('Retrieving block header from rollup transaction...');
113
113
  logger.info('');
114
- // For this script, we don't have blob hashes, so pass empty array
115
- const result = await retriever.getCheckpointFromRollupTx(txHash, [], CheckpointNumber(l2BlockNumber));
114
+ // For this script, we don't have blob hashes or expected hashes, so pass empty arrays/objects
115
+ const result = await retriever.getCheckpointFromRollupTx(txHash, [], CheckpointNumber(l2BlockNumber), {});
116
116
  logger.info(' Successfully retrieved block header!');
117
117
  logger.info('');
118
118
  logger.info('Block Header Details:');
@@ -32,9 +32,13 @@ export declare class CalldataRetriever {
32
32
  * @param txHash - Hash of the tx that published it.
33
33
  * @param blobHashes - Blob hashes for the checkpoint.
34
34
  * @param checkpointNumber - Checkpoint number.
35
+ * @param expectedHashes - Optional expected hashes from the CheckpointProposed event for validation
35
36
  * @returns Checkpoint header and metadata from the calldata, deserialized
36
37
  */
37
- getCheckpointFromRollupTx(txHash: `0x${string}`, blobHashes: Buffer[], checkpointNumber: CheckpointNumber): Promise<{
38
+ getCheckpointFromRollupTx(txHash: `0x${string}`, blobHashes: Buffer[], checkpointNumber: CheckpointNumber, expectedHashes: {
39
+ attestationsHash?: Hex;
40
+ payloadDigest?: Hex;
41
+ }): Promise<{
38
42
  checkpointNumber: CheckpointNumber;
39
43
  archiveRoot: Fr;
40
44
  header: CheckpointHeader;
@@ -80,14 +84,24 @@ export declare class CalldataRetriever {
80
84
  * @returns The propose calldata from the successful call
81
85
  */
82
86
  protected extractCalldataViaTrace(txHash: Hex): Promise<Hex>;
87
+ /**
88
+ * Extracts the CommitteeAttestations struct definition from RollupAbi.
89
+ * Finds the _attestations parameter by name in the propose function.
90
+ * Lazy-loaded to avoid issues during module initialization.
91
+ */
92
+ private getCommitteeAttestationsStructDef;
83
93
  /**
84
94
  * Decodes propose calldata and builds the checkpoint header structure.
85
95
  * @param proposeCalldata - The propose function calldata
86
96
  * @param blockHash - The L1 block hash containing this transaction
87
97
  * @param checkpointNumber - The checkpoint number
98
+ * @param expectedHashes - Optional expected hashes from the CheckpointProposed event for validation
88
99
  * @returns The decoded checkpoint header and metadata
89
100
  */
90
- protected decodeAndBuildCheckpoint(proposeCalldata: Hex, blockHash: Hex, checkpointNumber: CheckpointNumber): {
101
+ protected decodeAndBuildCheckpoint(proposeCalldata: Hex, blockHash: Hex, checkpointNumber: CheckpointNumber, expectedHashes: {
102
+ attestationsHash?: Hex;
103
+ payloadDigest?: Hex;
104
+ }): {
91
105
  checkpointNumber: CheckpointNumber;
92
106
  archiveRoot: Fr;
93
107
  header: CheckpointHeader;
@@ -95,4 +109,4 @@ export declare class CalldataRetriever {
95
109
  blockHash: string;
96
110
  };
97
111
  }
98
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2FsbGRhdGFfcmV0cmlldmVyLmQudHMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvYXJjaGl2ZXIvbDEvY2FsbGRhdGFfcmV0cmlldmVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUNBLE9BQU8sS0FBSyxFQUFFLGdCQUFnQixFQUFFLHFCQUFxQixFQUFFLE1BQU0sdUJBQXVCLENBQUM7QUFDckYsT0FBTyxFQUFFLGdCQUFnQixFQUFFLE1BQU0saUNBQWlDLENBQUM7QUFDbkUsT0FBTyxFQUFFLEVBQUUsRUFBRSxNQUFNLGdDQUFnQyxDQUFDO0FBQ3BELE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSwrQkFBK0IsQ0FBQztBQUUzRCxPQUFPLEtBQUssRUFBRSxNQUFNLEVBQUUsTUFBTSx1QkFBdUIsQ0FBQztBQVFwRCxPQUFPLEVBQUUsb0JBQW9CLEVBQUUsTUFBTSxxQkFBcUIsQ0FBQztBQUMzRCxPQUFPLEVBQUUsZ0JBQWdCLEVBQUUsTUFBTSxzQkFBc0IsQ0FBQztBQUV4RCxPQUFPLEVBQUUsS0FBSyxHQUFHLEVBQUUsS0FBSyxXQUFXLEVBQXFFLE1BQU0sTUFBTSxDQUFDO0FBRXJILE9BQU8sS0FBSyxFQUFFLHVCQUF1QixFQUFFLE1BQU0sdUJBQXVCLENBQUM7QUFNckU7OztHQUdHO0FBQ0gscUJBQWEsaUJBQWlCO0lBTzFCLE9BQU8sQ0FBQyxRQUFRLENBQUMsWUFBWTtJQUM3QixPQUFPLENBQUMsUUFBUSxDQUFDLFdBQVc7SUFDNUIsT0FBTyxDQUFDLFFBQVEsQ0FBQyxtQkFBbUI7SUFDcEMsT0FBTyxDQUFDLFFBQVEsQ0FBQyxlQUFlO0lBQ2hDLE9BQU8sQ0FBQyxRQUFRLENBQUMsTUFBTTtJQVZ6Qix1REFBdUQ7SUFDdkQsT0FBTyxDQUFDLFFBQVEsQ0FBQyxrQkFBa0IsQ0FBc0I7SUFFekQsT0FBTyxDQUFDLFFBQVEsQ0FBQyxhQUFhLENBQWE7SUFFM0MsWUFDbUIsWUFBWSxFQUFFLGdCQUFnQixFQUM5QixXQUFXLEVBQUUscUJBQXFCLEVBQ2xDLG1CQUFtQixFQUFFLE1BQU0sRUFDM0IsZUFBZSxFQUFFLHVCQUF1QixHQUFHLFNBQVMsRUFDcEQsTUFBTSxFQUFFLE1BQU0sRUFDL0IsaUJBQWlCLEVBQUU7UUFDakIsYUFBYSxFQUFFLFVBQVUsQ0FBQztRQUMxQix5QkFBeUIsRUFBRSxVQUFVLENBQUM7UUFDdEMsdUJBQXVCLEVBQUUsVUFBVSxDQUFDO1FBQ3BDLG1CQUFtQixDQUFDLEVBQUUsVUFBVSxDQUFDO0tBQ2xDLEVBSUY7SUFFRDs7Ozs7OztPQU9HO0lBQ0cseUJBQXlCLENBQzdCLE1BQU0sRUFBRSxLQUFLLE1BQU0sRUFBRSxFQUNyQixVQUFVLEVBQUUsTUFBTSxFQUFFLEVBQ3BCLGdCQUFnQixFQUFFLGdCQUFnQixHQUNqQyxPQUFPLENBQUM7UUFDVCxnQkFBZ0IsRUFBRSxnQkFBZ0IsQ0FBQztRQUNuQyxXQUFXLEVBQUUsRUFBRSxDQUFDO1FBQ2hCLE1BQU0sRUFBRSxnQkFBZ0IsQ0FBQztRQUN6QixZQUFZLEVBQUUsb0JBQW9CLEVBQUUsQ0FBQztRQUNyQyxTQUFTLEVBQUUsTUFBTSxDQUFDO0tBQ25CLENBQUMsQ0FLRDtJQUVELHNEQUFzRDtJQUN0RCxVQUFnQixrQkFBa0IsQ0FBQyxFQUFFLEVBQUUsV0FBVyxFQUFFLGdCQUFnQixFQUFFLGdCQUFnQixHQUFHLE9BQU8sQ0FBQyxHQUFHLENBQUMsQ0ErQnBHO0lBRUQ7Ozs7O09BS0c7SUFDSCxVQUFnQixzQkFBc0IsQ0FBQyxFQUFFLEVBQUUsV0FBVyxHQUFHLE9BQU8sQ0FBQyxHQUFHLEdBQUcsU0FBUyxDQUFDLENBNEJoRjtJQUVEOzs7OztPQUtHO0lBQ0gsU0FBUyxDQUFDLG1CQUFtQixDQUFDLEVBQUUsRUFBRTtRQUFFLEVBQUUsRUFBRSxHQUFHLEdBQUcsSUFBSSxHQUFHLFNBQVMsQ0FBQztRQUFDLEtBQUssRUFBRSxHQUFHLENBQUM7UUFBQyxJQUFJLEVBQUUsR0FBRyxDQUFBO0tBQUUsR0FBRyxHQUFHLEdBQUcsU0FBUyxDQXVGeEc7SUFFRDs7Ozs7T0FLRztJQUNILFNBQVMsQ0FBQyxzQkFBc0IsQ0FBQyxFQUFFLEVBQUU7UUFBRSxFQUFFLEVBQUUsR0FBRyxHQUFHLElBQUksR0FBRyxTQUFTLENBQUM7UUFBQyxLQUFLLEVBQUUsR0FBRyxDQUFDO1FBQUMsSUFBSSxFQUFFLEdBQUcsQ0FBQTtLQUFFLEdBQUcsR0FBRyxHQUFHLFNBQVMsQ0EwQjNHO0lBRUQ7Ozs7OztPQU1HO0lBQ0gsVUFBZ0IsdUJBQXVCLENBQUMsTUFBTSxFQUFFLEdBQUcsR0FBRyxPQUFPLENBQUMsR0FBRyxDQUFDLENBeUNqRTtJQUVEOzs7Ozs7T0FNRztJQUNILFNBQVMsQ0FBQyx3QkFBd0IsQ0FDaEMsZUFBZSxFQUFFLEdBQUcsRUFDcEIsU0FBUyxFQUFFLEdBQUcsRUFDZCxnQkFBZ0IsRUFBRSxnQkFBZ0IsR0FDakM7UUFDRCxnQkFBZ0IsRUFBRSxnQkFBZ0IsQ0FBQztRQUNuQyxXQUFXLEVBQUUsRUFBRSxDQUFDO1FBQ2hCLE1BQU0sRUFBRSxnQkFBZ0IsQ0FBQztRQUN6QixZQUFZLEVBQUUsb0JBQW9CLEVBQUUsQ0FBQztRQUNyQyxTQUFTLEVBQUUsTUFBTSxDQUFDO0tBQ25CLENBNkNBO0NBQ0YifQ==
112
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2FsbGRhdGFfcmV0cmlldmVyLmQudHMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvYXJjaGl2ZXIvbDEvY2FsbGRhdGFfcmV0cmlldmVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUNBLE9BQU8sS0FBSyxFQUFFLGdCQUFnQixFQUFFLHFCQUFxQixFQUFFLE1BQU0sdUJBQXVCLENBQUM7QUFDckYsT0FBTyxFQUFFLGdCQUFnQixFQUFFLE1BQU0saUNBQWlDLENBQUM7QUFDbkUsT0FBTyxFQUFFLEVBQUUsRUFBRSxNQUFNLGdDQUFnQyxDQUFDO0FBQ3BELE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSwrQkFBK0IsQ0FBQztBQUUzRCxPQUFPLEtBQUssRUFBRSxNQUFNLEVBQUUsTUFBTSx1QkFBdUIsQ0FBQztBQVFwRCxPQUFPLEVBQUUsb0JBQW9CLEVBQUUsTUFBTSxxQkFBcUIsQ0FBQztBQUUzRCxPQUFPLEVBQUUsZ0JBQWdCLEVBQUUsTUFBTSxzQkFBc0IsQ0FBQztBQUV4RCxPQUFPLEVBRUwsS0FBSyxHQUFHLEVBQ1IsS0FBSyxXQUFXLEVBT2pCLE1BQU0sTUFBTSxDQUFDO0FBRWQsT0FBTyxLQUFLLEVBQUUsdUJBQXVCLEVBQUUsTUFBTSx1QkFBdUIsQ0FBQztBQU1yRTs7O0dBR0c7QUFDSCxxQkFBYSxpQkFBaUI7SUFPMUIsT0FBTyxDQUFDLFFBQVEsQ0FBQyxZQUFZO0lBQzdCLE9BQU8sQ0FBQyxRQUFRLENBQUMsV0FBVztJQUM1QixPQUFPLENBQUMsUUFBUSxDQUFDLG1CQUFtQjtJQUNwQyxPQUFPLENBQUMsUUFBUSxDQUFDLGVBQWU7SUFDaEMsT0FBTyxDQUFDLFFBQVEsQ0FBQyxNQUFNO0lBVnpCLHVEQUF1RDtJQUN2RCxPQUFPLENBQUMsUUFBUSxDQUFDLGtCQUFrQixDQUFzQjtJQUV6RCxPQUFPLENBQUMsUUFBUSxDQUFDLGFBQWEsQ0FBYTtJQUUzQyxZQUNtQixZQUFZLEVBQUUsZ0JBQWdCLEVBQzlCLFdB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
@@ -1 +1 @@
1
- {"version":3,"file":"calldata_retriever.d.ts","sourceRoot":"","sources":["../../../src/archiver/l1/calldata_retriever.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"calldata_retriever.d.ts","sourceRoot":"","sources":["../../../src/archiver/l1/calldata_retriever.ts"],"names":[],"mappings":"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"}
@@ -3,8 +3,9 @@ import { Fr } from '@aztec/foundation/curves/bn254';
3
3
  import { EthAddress } from '@aztec/foundation/eth-address';
4
4
  import { EmpireSlashingProposerAbi, GovernanceProposerAbi, RollupAbi, SlashFactoryAbi, TallySlashingProposerAbi } from '@aztec/l1-artifacts';
5
5
  import { CommitteeAttestation } from '@aztec/stdlib/block';
6
+ import { ConsensusPayload, SignatureDomainSeparator } from '@aztec/stdlib/p2p';
6
7
  import { CheckpointHeader } from '@aztec/stdlib/rollup';
7
- import { decodeFunctionData, hexToBytes, multicall3Abi, toFunctionSelector } from 'viem';
8
+ import { decodeFunctionData, encodeAbiParameters, hexToBytes, keccak256, multicall3Abi, toFunctionSelector } from 'viem';
8
9
  import { getSuccessfulCallsFromDebug } from './debug_tx.js';
9
10
  import { getCallFromSpireProposer } from './spire_proposer.js';
10
11
  import { getSuccessfulCallsFromTrace } from './trace_tx.js';
@@ -34,14 +35,19 @@ import { getSuccessfulCallsFromTrace } from './trace_tx.js';
34
35
  * @param txHash - Hash of the tx that published it.
35
36
  * @param blobHashes - Blob hashes for the checkpoint.
36
37
  * @param checkpointNumber - Checkpoint number.
38
+ * @param expectedHashes - Optional expected hashes from the CheckpointProposed event for validation
37
39
  * @returns Checkpoint header and metadata from the calldata, deserialized
38
- */ async getCheckpointFromRollupTx(txHash, blobHashes, checkpointNumber) {
39
- this.logger.trace(`Fetching checkpoint ${checkpointNumber} from rollup tx ${txHash}`);
40
+ */ async getCheckpointFromRollupTx(txHash, blobHashes, checkpointNumber, expectedHashes) {
41
+ this.logger.trace(`Fetching checkpoint ${checkpointNumber} from rollup tx ${txHash}`, {
42
+ willValidateHashes: !!expectedHashes.attestationsHash || !!expectedHashes.payloadDigest,
43
+ hasAttestationsHash: !!expectedHashes.attestationsHash,
44
+ hasPayloadDigest: !!expectedHashes.payloadDigest
45
+ });
40
46
  const tx = await this.publicClient.getTransaction({
41
47
  hash: txHash
42
48
  });
43
49
  const proposeCalldata = await this.getProposeCallData(tx, checkpointNumber);
44
- return this.decodeAndBuildCheckpoint(proposeCalldata, tx.blockHash, checkpointNumber);
50
+ return this.decodeAndBuildCheckpoint(proposeCalldata, tx.blockHash, checkpointNumber, expectedHashes);
45
51
  }
46
52
  /** Gets rollup propose calldata from a transaction */ async getProposeCallData(tx, checkpointNumber) {
47
53
  // Try to decode as multicall3 with validation
@@ -283,12 +289,37 @@ import { getSuccessfulCallsFromTrace } from './trace_tx.js';
283
289
  return calls[0].input;
284
290
  }
285
291
  /**
292
+ * Extracts the CommitteeAttestations struct definition from RollupAbi.
293
+ * Finds the _attestations parameter by name in the propose function.
294
+ * Lazy-loaded to avoid issues during module initialization.
295
+ */ getCommitteeAttestationsStructDef() {
296
+ const proposeFunction = RollupAbi.find((item)=>item.type === 'function' && item.name === 'propose');
297
+ if (!proposeFunction) {
298
+ throw new Error('propose function not found in RollupAbi');
299
+ }
300
+ // Find the _attestations parameter by name, not by index
301
+ const attestationsParam = proposeFunction.inputs.find((param)=>param.name === '_attestations');
302
+ if (!attestationsParam) {
303
+ throw new Error('_attestations parameter not found in propose function');
304
+ }
305
+ if (attestationsParam.type !== 'tuple') {
306
+ throw new Error(`Expected _attestations parameter to be a tuple, got ${attestationsParam.type}`);
307
+ }
308
+ // Extract the tuple components (struct fields)
309
+ const tupleParam = attestationsParam;
310
+ return {
311
+ type: 'tuple',
312
+ components: tupleParam.components || []
313
+ };
314
+ }
315
+ /**
286
316
  * Decodes propose calldata and builds the checkpoint header structure.
287
317
  * @param proposeCalldata - The propose function calldata
288
318
  * @param blockHash - The L1 block hash containing this transaction
289
319
  * @param checkpointNumber - The checkpoint number
320
+ * @param expectedHashes - Optional expected hashes from the CheckpointProposed event for validation
290
321
  * @returns The decoded checkpoint header and metadata
291
- */ decodeAndBuildCheckpoint(proposeCalldata, blockHash, checkpointNumber) {
322
+ */ decodeAndBuildCheckpoint(proposeCalldata, blockHash, checkpointNumber, expectedHashes) {
292
323
  const { functionName: rollupFunctionName, args: rollupArgs } = decodeFunctionData({
293
324
  abi: RollupAbi,
294
325
  data: proposeCalldata
@@ -298,6 +329,45 @@ import { getSuccessfulCallsFromTrace } from './trace_tx.js';
298
329
  }
299
330
  const [decodedArgs, packedAttestations, _signers, _attestationsAndSignersSignature, _blobInput] = rollupArgs;
300
331
  const attestations = CommitteeAttestation.fromPacked(packedAttestations, this.targetCommitteeSize);
332
+ const header = CheckpointHeader.fromViem(decodedArgs.header);
333
+ const archiveRoot = new Fr(Buffer.from(hexToBytes(decodedArgs.archive)));
334
+ // Validate attestationsHash if provided (skip for backwards compatibility with older events)
335
+ if (expectedHashes.attestationsHash) {
336
+ // Compute attestationsHash: keccak256(abi.encode(CommitteeAttestations))
337
+ const computedAttestationsHash = keccak256(encodeAbiParameters([
338
+ this.getCommitteeAttestationsStructDef()
339
+ ], [
340
+ packedAttestations
341
+ ]));
342
+ // Compare as buffers to avoid case-sensitivity and string comparison issues
343
+ const computedBuffer = Buffer.from(hexToBytes(computedAttestationsHash));
344
+ const expectedBuffer = Buffer.from(hexToBytes(expectedHashes.attestationsHash));
345
+ if (!computedBuffer.equals(expectedBuffer)) {
346
+ throw new Error(`Attestations hash mismatch for checkpoint ${checkpointNumber}: ` + `computed=${computedAttestationsHash}, expected=${expectedHashes.attestationsHash}`);
347
+ }
348
+ this.logger.trace(`Validated attestationsHash for checkpoint ${checkpointNumber}`, {
349
+ computedAttestationsHash,
350
+ expectedAttestationsHash: expectedHashes.attestationsHash
351
+ });
352
+ }
353
+ // Validate payloadDigest if provided (skip for backwards compatibility with older events)
354
+ if (expectedHashes.payloadDigest) {
355
+ // Use ConsensusPayload to compute the digest - this ensures we match the exact logic
356
+ // used by the network for signing and verification
357
+ const consensusPayload = new ConsensusPayload(header, archiveRoot);
358
+ const payloadToSign = consensusPayload.getPayloadToSign(SignatureDomainSeparator.blockAttestation);
359
+ const computedPayloadDigest = keccak256(payloadToSign);
360
+ // Compare as buffers to avoid case-sensitivity and string comparison issues
361
+ const computedBuffer = Buffer.from(hexToBytes(computedPayloadDigest));
362
+ const expectedBuffer = Buffer.from(hexToBytes(expectedHashes.payloadDigest));
363
+ if (!computedBuffer.equals(expectedBuffer)) {
364
+ throw new Error(`Payload digest mismatch for checkpoint ${checkpointNumber}: ` + `computed=${computedPayloadDigest}, expected=${expectedHashes.payloadDigest}`);
365
+ }
366
+ this.logger.trace(`Validated payloadDigest for checkpoint ${checkpointNumber}`, {
367
+ computedPayloadDigest,
368
+ expectedPayloadDigest: expectedHashes.payloadDigest
369
+ });
370
+ }
301
371
  this.logger.trace(`Decoded propose calldata`, {
302
372
  checkpointNumber,
303
373
  archive: decodedArgs.archive,
@@ -307,8 +377,6 @@ import { getSuccessfulCallsFromTrace } from './trace_tx.js';
307
377
  packedAttestations,
308
378
  targetCommitteeSize: this.targetCommitteeSize
309
379
  });
310
- const header = CheckpointHeader.fromViem(decodedArgs.header);
311
- const archiveRoot = new Fr(Buffer.from(hexToBytes(decodedArgs.archive)));
312
380
  return {
313
381
  checkpointNumber,
314
382
  archiveRoot,