@aztec/archiver 0.76.4 → 0.77.0-testnet-ignition.21
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/README.md +1 -1
- package/dest/archiver/archiver.d.ts +22 -10
- package/dest/archiver/archiver.d.ts.map +1 -1
- package/dest/archiver/archiver.js +762 -713
- package/dest/archiver/archiver_store.d.ts +20 -7
- package/dest/archiver/archiver_store.d.ts.map +1 -1
- package/dest/archiver/archiver_store.js +4 -2
- package/dest/archiver/archiver_store_test_suite.d.ts +2 -2
- package/dest/archiver/archiver_store_test_suite.d.ts.map +1 -1
- package/dest/archiver/archiver_store_test_suite.js +398 -227
- package/dest/archiver/config.d.ts +1 -1
- package/dest/archiver/config.d.ts.map +1 -1
- package/dest/archiver/config.js +10 -12
- package/dest/archiver/data_retrieval.d.ts +17 -14
- package/dest/archiver/data_retrieval.d.ts.map +1 -1
- package/dest/archiver/data_retrieval.js +90 -88
- package/dest/archiver/errors.js +1 -2
- package/dest/archiver/index.d.ts +1 -1
- package/dest/archiver/index.d.ts.map +1 -1
- package/dest/archiver/index.js +0 -1
- package/dest/archiver/instrumentation.d.ts +3 -1
- package/dest/archiver/instrumentation.d.ts.map +1 -1
- package/dest/archiver/instrumentation.js +37 -17
- package/dest/archiver/kv_archiver_store/block_store.d.ts +5 -3
- package/dest/archiver/kv_archiver_store/block_store.d.ts.map +1 -1
- package/dest/archiver/kv_archiver_store/block_store.js +125 -130
- package/dest/archiver/kv_archiver_store/contract_class_store.d.ts +2 -1
- package/dest/archiver/kv_archiver_store/contract_class_store.d.ts.map +1 -1
- package/dest/archiver/kv_archiver_store/contract_class_store.js +45 -37
- package/dest/archiver/kv_archiver_store/contract_instance_store.d.ts +10 -2
- package/dest/archiver/kv_archiver_store/contract_instance_store.d.ts.map +1 -1
- package/dest/archiver/kv_archiver_store/contract_instance_store.js +54 -15
- package/dest/archiver/kv_archiver_store/kv_archiver_store.d.ts +16 -9
- package/dest/archiver/kv_archiver_store/kv_archiver_store.d.ts.map +1 -1
- package/dest/archiver/kv_archiver_store/kv_archiver_store.js +143 -160
- package/dest/archiver/kv_archiver_store/log_store.d.ts +5 -3
- package/dest/archiver/kv_archiver_store/log_store.d.ts.map +1 -1
- package/dest/archiver/kv_archiver_store/log_store.js +296 -255
- package/dest/archiver/kv_archiver_store/message_store.d.ts +3 -3
- package/dest/archiver/kv_archiver_store/message_store.d.ts.map +1 -1
- package/dest/archiver/kv_archiver_store/message_store.js +45 -50
- package/dest/archiver/kv_archiver_store/nullifier_store.d.ts +2 -2
- package/dest/archiver/kv_archiver_store/nullifier_store.d.ts.map +1 -1
- package/dest/archiver/kv_archiver_store/nullifier_store.js +36 -43
- package/dest/archiver/memory_archiver_store/l1_to_l2_message_store.d.ts +2 -2
- package/dest/archiver/memory_archiver_store/l1_to_l2_message_store.d.ts.map +1 -1
- package/dest/archiver/memory_archiver_store/l1_to_l2_message_store.js +17 -26
- package/dest/archiver/memory_archiver_store/memory_archiver_store.d.ts +16 -7
- package/dest/archiver/memory_archiver_store/memory_archiver_store.d.ts.map +1 -1
- package/dest/archiver/memory_archiver_store/memory_archiver_store.js +287 -247
- package/dest/archiver/structs/data_retrieval.js +5 -2
- package/dest/archiver/structs/published.js +1 -2
- package/dest/factory.d.ts +20 -6
- package/dest/factory.d.ts.map +1 -1
- package/dest/factory.js +54 -30
- package/dest/index.js +0 -1
- package/dest/rpc/index.d.ts +2 -1
- package/dest/rpc/index.d.ts.map +1 -1
- package/dest/rpc/index.js +8 -4
- package/dest/test/index.js +0 -1
- package/dest/test/mock_archiver.d.ts +3 -2
- package/dest/test/mock_archiver.d.ts.map +1 -1
- package/dest/test/mock_archiver.js +8 -13
- package/dest/test/mock_l1_to_l2_message_source.d.ts +2 -2
- package/dest/test/mock_l1_to_l2_message_source.d.ts.map +1 -1
- package/dest/test/mock_l1_to_l2_message_source.js +4 -4
- package/dest/test/mock_l2_block_source.d.ts +5 -3
- package/dest/test/mock_l2_block_source.d.ts.map +1 -1
- package/dest/test/mock_l2_block_source.js +71 -68
- package/package.json +15 -16
- package/src/archiver/archiver.ts +149 -89
- package/src/archiver/archiver_store.ts +27 -27
- package/src/archiver/archiver_store_test_suite.ts +22 -15
- package/src/archiver/config.ts +1 -1
- package/src/archiver/data_retrieval.ts +32 -44
- package/src/archiver/index.ts +1 -1
- package/src/archiver/instrumentation.ts +11 -1
- package/src/archiver/kv_archiver_store/block_store.ts +10 -4
- package/src/archiver/kv_archiver_store/contract_class_store.ts +9 -9
- package/src/archiver/kv_archiver_store/contract_instance_store.ts +81 -3
- package/src/archiver/kv_archiver_store/kv_archiver_store.ts +44 -29
- package/src/archiver/kv_archiver_store/log_store.ts +56 -32
- package/src/archiver/kv_archiver_store/message_store.ts +4 -3
- package/src/archiver/kv_archiver_store/nullifier_store.ts +3 -2
- package/src/archiver/memory_archiver_store/l1_to_l2_message_store.ts +3 -3
- package/src/archiver/memory_archiver_store/memory_archiver_store.ts +110 -57
- package/src/factory.ts +44 -25
- package/src/rpc/index.ts +2 -6
- package/src/test/mock_archiver.ts +3 -2
- package/src/test/mock_l1_to_l2_message_source.ts +2 -2
- package/src/test/mock_l2_block_source.ts +16 -15
|
@@ -1,266 +1,350 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import '@aztec/circuit-types/jest';
|
|
3
|
-
import { AztecAddress, Fr, INITIAL_L2_BLOCK_NUM, L1_TO_L2_MSG_SUBTREE_HEIGHT, MAX_NULLIFIERS_PER_TX, PRIVATE_LOG_SIZE_IN_FIELDS, PUBLIC_LOG_DATA_SIZE_IN_FIELDS, PrivateLog, PublicLog, SerializableContractInstance, computePublicBytecodeCommitment, } from '@aztec/circuits.js';
|
|
4
|
-
import { makeContractClassPublic, makeExecutablePrivateFunctionWithMembershipProof, makeUnconstrainedFunctionWithMembershipProof, } from '@aztec/circuits.js/testing';
|
|
1
|
+
import { INITIAL_L2_BLOCK_NUM, L1_TO_L2_MSG_SUBTREE_HEIGHT, MAX_NULLIFIERS_PER_TX, PRIVATE_LOG_SIZE_IN_FIELDS, PUBLIC_LOG_DATA_SIZE_IN_FIELDS } from '@aztec/constants';
|
|
5
2
|
import { times, timesParallel } from '@aztec/foundation/collection';
|
|
6
3
|
import { randomInt } from '@aztec/foundation/crypto';
|
|
4
|
+
import { Fr } from '@aztec/foundation/fields';
|
|
5
|
+
import { AztecAddress } from '@aztec/stdlib/aztec-address';
|
|
6
|
+
import { L2Block, wrapInBlock } from '@aztec/stdlib/block';
|
|
7
|
+
import { SerializableContractInstance, computePublicBytecodeCommitment } from '@aztec/stdlib/contract';
|
|
8
|
+
import { LogId, PrivateLog, PublicLog } from '@aztec/stdlib/logs';
|
|
9
|
+
import { InboxLeaf } from '@aztec/stdlib/messaging';
|
|
10
|
+
import { makeContractClassPublic, makeExecutablePrivateFunctionWithMembershipProof, makeUnconstrainedFunctionWithMembershipProof } from '@aztec/stdlib/testing';
|
|
11
|
+
import '@aztec/stdlib/testing/jest';
|
|
12
|
+
import { TxEffect, TxHash } from '@aztec/stdlib/tx';
|
|
7
13
|
/**
|
|
8
14
|
* @param testName - The name of the test suite.
|
|
9
15
|
* @param getStore - Returns an instance of a store that's already been initialized.
|
|
10
|
-
*/
|
|
11
|
-
|
|
12
|
-
describe(testName, () => {
|
|
16
|
+
*/ export function describeArchiverDataStore(testName, getStore) {
|
|
17
|
+
describe(testName, ()=>{
|
|
13
18
|
let store;
|
|
14
19
|
let blocks;
|
|
15
20
|
const blockTests = [
|
|
16
|
-
[
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
+
[
|
|
22
|
+
1,
|
|
23
|
+
1,
|
|
24
|
+
()=>blocks.slice(0, 1)
|
|
25
|
+
],
|
|
26
|
+
[
|
|
27
|
+
10,
|
|
28
|
+
1,
|
|
29
|
+
()=>blocks.slice(9, 10)
|
|
30
|
+
],
|
|
31
|
+
[
|
|
32
|
+
1,
|
|
33
|
+
10,
|
|
34
|
+
()=>blocks.slice(0, 10)
|
|
35
|
+
],
|
|
36
|
+
[
|
|
37
|
+
2,
|
|
38
|
+
5,
|
|
39
|
+
()=>blocks.slice(1, 6)
|
|
40
|
+
],
|
|
41
|
+
[
|
|
42
|
+
5,
|
|
43
|
+
2,
|
|
44
|
+
()=>blocks.slice(4, 6)
|
|
45
|
+
]
|
|
21
46
|
];
|
|
22
|
-
const makeL1Published = (block, l1BlockNumber)
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
beforeEach(async ()
|
|
47
|
+
const makeL1Published = (block, l1BlockNumber)=>({
|
|
48
|
+
data: block,
|
|
49
|
+
l1: {
|
|
50
|
+
blockNumber: BigInt(l1BlockNumber),
|
|
51
|
+
blockHash: `0x${l1BlockNumber}`,
|
|
52
|
+
timestamp: BigInt(l1BlockNumber * 1000)
|
|
53
|
+
}
|
|
54
|
+
});
|
|
55
|
+
beforeEach(async ()=>{
|
|
31
56
|
store = await getStore();
|
|
32
|
-
blocks = await timesParallel(10, async (i)
|
|
57
|
+
blocks = await timesParallel(10, async (i)=>makeL1Published(await L2Block.random(i + 1), i + 10));
|
|
33
58
|
});
|
|
34
|
-
describe('addBlocks', ()
|
|
35
|
-
it('returns success when adding blocks', async ()
|
|
59
|
+
describe('addBlocks', ()=>{
|
|
60
|
+
it('returns success when adding blocks', async ()=>{
|
|
36
61
|
await expect(store.addBlocks(blocks)).resolves.toBe(true);
|
|
37
62
|
});
|
|
38
|
-
it('allows duplicate blocks', async ()
|
|
63
|
+
it('allows duplicate blocks', async ()=>{
|
|
39
64
|
await store.addBlocks(blocks);
|
|
40
65
|
await expect(store.addBlocks(blocks)).resolves.toBe(true);
|
|
41
66
|
});
|
|
42
67
|
});
|
|
43
|
-
describe('unwindBlocks', ()
|
|
44
|
-
it('unwinding blocks will remove blocks from the chain', async ()
|
|
68
|
+
describe('unwindBlocks', ()=>{
|
|
69
|
+
it('unwinding blocks will remove blocks from the chain', async ()=>{
|
|
45
70
|
await store.addBlocks(blocks);
|
|
46
71
|
const blockNumber = await store.getSynchedL2BlockNumber();
|
|
47
|
-
expect(await store.getBlocks(blockNumber, 1)).toEqual([
|
|
72
|
+
expect(await store.getBlocks(blockNumber, 1)).toEqual([
|
|
73
|
+
blocks[blocks.length - 1]
|
|
74
|
+
]);
|
|
48
75
|
await store.unwindBlocks(blockNumber, 1);
|
|
49
76
|
expect(await store.getSynchedL2BlockNumber()).toBe(blockNumber - 1);
|
|
50
77
|
expect(await store.getBlocks(blockNumber, 1)).toEqual([]);
|
|
51
78
|
});
|
|
52
|
-
it('can unwind multiple empty blocks', async ()
|
|
53
|
-
const emptyBlocks = await timesParallel(10, async (i)
|
|
79
|
+
it('can unwind multiple empty blocks', async ()=>{
|
|
80
|
+
const emptyBlocks = await timesParallel(10, async (i)=>makeL1Published(await L2Block.random(i + 1, 0), i + 10));
|
|
54
81
|
await store.addBlocks(emptyBlocks);
|
|
55
82
|
expect(await store.getSynchedL2BlockNumber()).toBe(10);
|
|
56
83
|
await store.unwindBlocks(10, 3);
|
|
57
84
|
expect(await store.getSynchedL2BlockNumber()).toBe(7);
|
|
58
|
-
expect((await store.getBlocks(1, 10)).map(b
|
|
85
|
+
expect((await store.getBlocks(1, 10)).map((b)=>b.data.number)).toEqual([
|
|
86
|
+
1,
|
|
87
|
+
2,
|
|
88
|
+
3,
|
|
89
|
+
4,
|
|
90
|
+
5,
|
|
91
|
+
6,
|
|
92
|
+
7
|
|
93
|
+
]);
|
|
59
94
|
});
|
|
60
|
-
it('refuses to unwind blocks if the tip is not the last block', async ()
|
|
95
|
+
it('refuses to unwind blocks if the tip is not the last block', async ()=>{
|
|
61
96
|
await store.addBlocks(blocks);
|
|
62
97
|
await expect(store.unwindBlocks(5, 1)).rejects.toThrow(/can only unwind blocks from the tip/i);
|
|
63
98
|
});
|
|
64
99
|
});
|
|
65
|
-
describe('getBlocks', ()
|
|
66
|
-
beforeEach(async ()
|
|
100
|
+
describe('getBlocks', ()=>{
|
|
101
|
+
beforeEach(async ()=>{
|
|
67
102
|
await store.addBlocks(blocks);
|
|
68
103
|
});
|
|
69
|
-
it.each(blockTests)('retrieves previously stored blocks', async (start, limit, getExpectedBlocks)
|
|
104
|
+
it.each(blockTests)('retrieves previously stored blocks', async (start, limit, getExpectedBlocks)=>{
|
|
70
105
|
await expect(store.getBlocks(start, limit)).resolves.toEqual(getExpectedBlocks());
|
|
71
106
|
});
|
|
72
|
-
it('returns an empty array if no blocks are found', async ()
|
|
107
|
+
it('returns an empty array if no blocks are found', async ()=>{
|
|
73
108
|
await expect(store.getBlocks(12, 1)).resolves.toEqual([]);
|
|
74
109
|
});
|
|
75
|
-
it('throws an error if limit is invalid', async ()
|
|
110
|
+
it('throws an error if limit is invalid', async ()=>{
|
|
76
111
|
await expect(store.getBlocks(1, 0)).rejects.toThrow('Invalid limit: 0');
|
|
77
112
|
});
|
|
78
|
-
it('throws an error if `from` it is out of range', async ()
|
|
113
|
+
it('throws an error if `from` it is out of range', async ()=>{
|
|
79
114
|
await expect(store.getBlocks(INITIAL_L2_BLOCK_NUM - 100, 1)).rejects.toThrow('Invalid start: -99');
|
|
80
115
|
});
|
|
81
116
|
});
|
|
82
|
-
describe('getSyncedL2BlockNumber', ()
|
|
83
|
-
it('returns the block number before INITIAL_L2_BLOCK_NUM if no blocks have been added', async ()
|
|
117
|
+
describe('getSyncedL2BlockNumber', ()=>{
|
|
118
|
+
it('returns the block number before INITIAL_L2_BLOCK_NUM if no blocks have been added', async ()=>{
|
|
84
119
|
await expect(store.getSynchedL2BlockNumber()).resolves.toEqual(INITIAL_L2_BLOCK_NUM - 1);
|
|
85
120
|
});
|
|
86
|
-
it("returns the most recently added block's number", async ()
|
|
121
|
+
it("returns the most recently added block's number", async ()=>{
|
|
87
122
|
await store.addBlocks(blocks);
|
|
88
123
|
await expect(store.getSynchedL2BlockNumber()).resolves.toEqual(blocks.at(-1).data.number);
|
|
89
124
|
});
|
|
90
125
|
});
|
|
91
|
-
describe('getSynchPoint', ()
|
|
92
|
-
it('returns undefined if no blocks have been added', async ()
|
|
126
|
+
describe('getSynchPoint', ()=>{
|
|
127
|
+
it('returns undefined if no blocks have been added', async ()=>{
|
|
93
128
|
await expect(store.getSynchPoint()).resolves.toEqual({
|
|
94
129
|
blocksSynchedTo: undefined,
|
|
95
|
-
messagesSynchedTo: undefined
|
|
130
|
+
messagesSynchedTo: undefined
|
|
96
131
|
});
|
|
97
132
|
});
|
|
98
|
-
it('returns the L1 block number in which the most recent L2 block was published', async ()
|
|
133
|
+
it('returns the L1 block number in which the most recent L2 block was published', async ()=>{
|
|
99
134
|
await store.addBlocks(blocks);
|
|
100
135
|
await expect(store.getSynchPoint()).resolves.toEqual({
|
|
101
136
|
blocksSynchedTo: 19n,
|
|
102
|
-
messagesSynchedTo: undefined
|
|
137
|
+
messagesSynchedTo: undefined
|
|
103
138
|
});
|
|
104
139
|
});
|
|
105
|
-
it('returns the L1 block number that most recently added messages from inbox', async ()
|
|
140
|
+
it('returns the L1 block number that most recently added messages from inbox', async ()=>{
|
|
106
141
|
await store.addL1ToL2Messages({
|
|
107
142
|
lastProcessedL1BlockNumber: 1n,
|
|
108
|
-
retrievedData: [
|
|
143
|
+
retrievedData: [
|
|
144
|
+
new InboxLeaf(1n, Fr.ZERO)
|
|
145
|
+
]
|
|
109
146
|
});
|
|
110
147
|
await expect(store.getSynchPoint()).resolves.toEqual({
|
|
111
148
|
blocksSynchedTo: undefined,
|
|
112
|
-
messagesSynchedTo: 1n
|
|
149
|
+
messagesSynchedTo: 1n
|
|
113
150
|
});
|
|
114
151
|
});
|
|
115
152
|
});
|
|
116
|
-
describe('addLogs', ()
|
|
117
|
-
it('adds private & public logs', async ()
|
|
153
|
+
describe('addLogs', ()=>{
|
|
154
|
+
it('adds private & public logs', async ()=>{
|
|
118
155
|
const block = blocks[0].data;
|
|
119
|
-
await expect(store.addLogs([
|
|
156
|
+
await expect(store.addLogs([
|
|
157
|
+
block
|
|
158
|
+
])).resolves.toEqual(true);
|
|
120
159
|
});
|
|
121
160
|
});
|
|
122
|
-
describe('deleteLogs', ()
|
|
123
|
-
it('deletes private & public logs', async ()
|
|
161
|
+
describe('deleteLogs', ()=>{
|
|
162
|
+
it('deletes private & public logs', async ()=>{
|
|
124
163
|
const block = blocks[0].data;
|
|
125
|
-
await store.addBlocks([
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
expect(
|
|
164
|
+
await store.addBlocks([
|
|
165
|
+
blocks[0]
|
|
166
|
+
]);
|
|
167
|
+
await expect(store.addLogs([
|
|
168
|
+
block
|
|
169
|
+
])).resolves.toEqual(true);
|
|
170
|
+
expect((await store.getPrivateLogs(1, 1)).length).toEqual(block.body.txEffects.map((txEffect)=>txEffect.privateLogs).flat().length);
|
|
171
|
+
expect((await store.getPublicLogs({
|
|
172
|
+
fromBlock: 1
|
|
173
|
+
})).logs.length).toEqual(block.body.txEffects.map((txEffect)=>txEffect.publicLogs).flat().length);
|
|
129
174
|
// This one is a pain for memory as we would never want to just delete memory in the middle.
|
|
130
|
-
await store.deleteLogs([
|
|
175
|
+
await store.deleteLogs([
|
|
176
|
+
block
|
|
177
|
+
]);
|
|
131
178
|
expect((await store.getPrivateLogs(1, 1)).length).toEqual(0);
|
|
132
|
-
expect((await store.getPublicLogs({
|
|
179
|
+
expect((await store.getPublicLogs({
|
|
180
|
+
fromBlock: 1
|
|
181
|
+
})).logs.length).toEqual(0);
|
|
133
182
|
});
|
|
134
183
|
});
|
|
135
|
-
describe('getPrivateLogs', ()
|
|
136
|
-
it('gets added private logs', async ()
|
|
184
|
+
describe('getPrivateLogs', ()=>{
|
|
185
|
+
it('gets added private logs', async ()=>{
|
|
137
186
|
const block = blocks[0].data;
|
|
138
|
-
await store.addBlocks([
|
|
139
|
-
|
|
187
|
+
await store.addBlocks([
|
|
188
|
+
blocks[0]
|
|
189
|
+
]);
|
|
190
|
+
await store.addLogs([
|
|
191
|
+
block
|
|
192
|
+
]);
|
|
140
193
|
const privateLogs = await store.getPrivateLogs(1, 1);
|
|
141
|
-
expect(privateLogs).toEqual(block.body.txEffects.map(txEffect
|
|
194
|
+
expect(privateLogs).toEqual(block.body.txEffects.map((txEffect)=>txEffect.privateLogs).flat());
|
|
142
195
|
});
|
|
143
196
|
});
|
|
144
|
-
describe('getTxEffect', ()
|
|
145
|
-
beforeEach(async ()
|
|
146
|
-
await store.addLogs(blocks.map(b
|
|
197
|
+
describe('getTxEffect', ()=>{
|
|
198
|
+
beforeEach(async ()=>{
|
|
199
|
+
await store.addLogs(blocks.map((b)=>b.data));
|
|
147
200
|
await store.addBlocks(blocks);
|
|
148
201
|
});
|
|
149
202
|
it.each([
|
|
150
|
-
()
|
|
151
|
-
()
|
|
152
|
-
()
|
|
153
|
-
()
|
|
154
|
-
()
|
|
155
|
-
])('retrieves a previously stored transaction', async (getExpectedTx)
|
|
203
|
+
()=>wrapInBlock(blocks[0].data.body.txEffects[0], blocks[0].data),
|
|
204
|
+
()=>wrapInBlock(blocks[9].data.body.txEffects[3], blocks[9].data),
|
|
205
|
+
()=>wrapInBlock(blocks[3].data.body.txEffects[1], blocks[3].data),
|
|
206
|
+
()=>wrapInBlock(blocks[5].data.body.txEffects[2], blocks[5].data),
|
|
207
|
+
()=>wrapInBlock(blocks[1].data.body.txEffects[0], blocks[1].data)
|
|
208
|
+
])('retrieves a previously stored transaction', async (getExpectedTx)=>{
|
|
156
209
|
const expectedTx = await getExpectedTx();
|
|
157
210
|
const actualTx = await store.getTxEffect(expectedTx.data.txHash);
|
|
158
211
|
expect(actualTx).toEqual(expectedTx);
|
|
159
212
|
});
|
|
160
|
-
it('returns undefined if tx is not found', async ()
|
|
213
|
+
it('returns undefined if tx is not found', async ()=>{
|
|
161
214
|
await expect(store.getTxEffect(TxHash.random())).resolves.toBeUndefined();
|
|
162
215
|
});
|
|
163
216
|
it.each([
|
|
164
|
-
()
|
|
165
|
-
()
|
|
166
|
-
()
|
|
167
|
-
()
|
|
168
|
-
()
|
|
169
|
-
])('tries to retrieves a previously stored transaction after deleted', async (getExpectedTx)
|
|
217
|
+
()=>wrapInBlock(blocks[0].data.body.txEffects[0], blocks[0].data),
|
|
218
|
+
()=>wrapInBlock(blocks[9].data.body.txEffects[3], blocks[9].data),
|
|
219
|
+
()=>wrapInBlock(blocks[3].data.body.txEffects[1], blocks[3].data),
|
|
220
|
+
()=>wrapInBlock(blocks[5].data.body.txEffects[2], blocks[5].data),
|
|
221
|
+
()=>wrapInBlock(blocks[1].data.body.txEffects[0], blocks[1].data)
|
|
222
|
+
])('tries to retrieves a previously stored transaction after deleted', async (getExpectedTx)=>{
|
|
170
223
|
await store.unwindBlocks(blocks.length, blocks.length);
|
|
171
224
|
const expectedTx = await getExpectedTx();
|
|
172
225
|
const actualTx = await store.getTxEffect(expectedTx.data.txHash);
|
|
173
226
|
expect(actualTx).toEqual(undefined);
|
|
174
227
|
});
|
|
175
|
-
it('returns undefined if tx is not found', async ()
|
|
228
|
+
it('returns undefined if tx is not found', async ()=>{
|
|
176
229
|
await expect(store.getTxEffect(TxHash.random())).resolves.toBeUndefined();
|
|
177
230
|
});
|
|
178
231
|
});
|
|
179
|
-
describe('L1 to L2 Messages', ()
|
|
232
|
+
describe('L1 to L2 Messages', ()=>{
|
|
180
233
|
const l2BlockNumber = 13n;
|
|
181
234
|
const l1ToL2MessageSubtreeSize = 2 ** L1_TO_L2_MSG_SUBTREE_HEIGHT;
|
|
182
|
-
const generateBlockMessages = (blockNumber, numMessages)
|
|
183
|
-
|
|
235
|
+
const generateBlockMessages = (blockNumber, numMessages)=>Array.from({
|
|
236
|
+
length: numMessages
|
|
237
|
+
}, (_, i)=>new InboxLeaf(InboxLeaf.smallestIndexFromL2Block(blockNumber) + BigInt(i), Fr.random()));
|
|
238
|
+
it('returns messages in correct order', async ()=>{
|
|
184
239
|
const msgs = generateBlockMessages(l2BlockNumber, l1ToL2MessageSubtreeSize);
|
|
185
|
-
const shuffledMessages = msgs.slice().sort(()
|
|
186
|
-
await store.addL1ToL2Messages({
|
|
240
|
+
const shuffledMessages = msgs.slice().sort(()=>randomInt(1) - 0.5);
|
|
241
|
+
await store.addL1ToL2Messages({
|
|
242
|
+
lastProcessedL1BlockNumber: 100n,
|
|
243
|
+
retrievedData: shuffledMessages
|
|
244
|
+
});
|
|
187
245
|
const retrievedMessages = await store.getL1ToL2Messages(l2BlockNumber);
|
|
188
|
-
const expectedLeavesOrder = msgs.map(msg
|
|
246
|
+
const expectedLeavesOrder = msgs.map((msg)=>msg.leaf);
|
|
189
247
|
expect(expectedLeavesOrder).toEqual(retrievedMessages);
|
|
190
248
|
});
|
|
191
|
-
it('throws if it is impossible to sequence messages correctly', async ()
|
|
249
|
+
it('throws if it is impossible to sequence messages correctly', async ()=>{
|
|
192
250
|
const msgs = generateBlockMessages(l2BlockNumber, l1ToL2MessageSubtreeSize - 1);
|
|
193
251
|
// We replace a message with index 4 with a message with index at the end of the tree
|
|
194
252
|
// --> with that there will be a gap and it will be impossible to sequence the
|
|
195
253
|
// end of tree = start of next tree/block - 1
|
|
196
254
|
msgs[4] = new InboxLeaf(InboxLeaf.smallestIndexFromL2Block(l2BlockNumber + 1n) - 1n, Fr.random());
|
|
197
|
-
await store.addL1ToL2Messages({
|
|
198
|
-
|
|
255
|
+
await store.addL1ToL2Messages({
|
|
256
|
+
lastProcessedL1BlockNumber: 100n,
|
|
257
|
+
retrievedData: msgs
|
|
258
|
+
});
|
|
259
|
+
await expect(async ()=>{
|
|
199
260
|
await store.getL1ToL2Messages(l2BlockNumber);
|
|
200
261
|
}).rejects.toThrow(`L1 to L2 message gap found in block ${l2BlockNumber}`);
|
|
201
262
|
});
|
|
202
263
|
});
|
|
203
|
-
describe('contractInstances', ()
|
|
264
|
+
describe('contractInstances', ()=>{
|
|
204
265
|
let contractInstance;
|
|
205
266
|
const blockNum = 10;
|
|
206
|
-
beforeEach(async ()
|
|
207
|
-
const
|
|
208
|
-
|
|
209
|
-
|
|
267
|
+
beforeEach(async ()=>{
|
|
268
|
+
const classId = Fr.random();
|
|
269
|
+
const randomInstance = await SerializableContractInstance.random({
|
|
270
|
+
currentContractClassId: classId,
|
|
271
|
+
originalContractClassId: classId
|
|
272
|
+
});
|
|
273
|
+
contractInstance = {
|
|
274
|
+
...randomInstance,
|
|
275
|
+
address: await AztecAddress.random()
|
|
276
|
+
};
|
|
277
|
+
await store.addContractInstances([
|
|
278
|
+
contractInstance
|
|
279
|
+
], blockNum);
|
|
210
280
|
});
|
|
211
|
-
it('returns previously stored contract instances', async ()
|
|
281
|
+
it('returns previously stored contract instances', async ()=>{
|
|
212
282
|
await expect(store.getContractInstance(contractInstance.address)).resolves.toMatchObject(contractInstance);
|
|
213
283
|
});
|
|
214
|
-
it('returns undefined if contract instance is not found', async ()
|
|
284
|
+
it('returns undefined if contract instance is not found', async ()=>{
|
|
215
285
|
await expect(store.getContractInstance(await AztecAddress.random())).resolves.toBeUndefined();
|
|
216
286
|
});
|
|
217
|
-
it('returns undefined if previously stored contract instances was deleted', async ()
|
|
218
|
-
await store.deleteContractInstances([
|
|
287
|
+
it('returns undefined if previously stored contract instances was deleted', async ()=>{
|
|
288
|
+
await store.deleteContractInstances([
|
|
289
|
+
contractInstance
|
|
290
|
+
], blockNum);
|
|
219
291
|
await expect(store.getContractInstance(contractInstance.address)).resolves.toBeUndefined();
|
|
220
292
|
});
|
|
221
293
|
});
|
|
222
|
-
describe('contractClasses', ()
|
|
294
|
+
describe('contractClasses', ()=>{
|
|
223
295
|
let contractClass;
|
|
224
296
|
const blockNum = 10;
|
|
225
|
-
beforeEach(async ()
|
|
297
|
+
beforeEach(async ()=>{
|
|
226
298
|
contractClass = await makeContractClassPublic();
|
|
227
|
-
await store.addContractClasses([
|
|
299
|
+
await store.addContractClasses([
|
|
300
|
+
contractClass
|
|
301
|
+
], [
|
|
302
|
+
await computePublicBytecodeCommitment(contractClass.packedBytecode)
|
|
303
|
+
], blockNum);
|
|
228
304
|
});
|
|
229
|
-
it('returns previously stored contract class', async ()
|
|
305
|
+
it('returns previously stored contract class', async ()=>{
|
|
230
306
|
await expect(store.getContractClass(contractClass.id)).resolves.toMatchObject(contractClass);
|
|
231
307
|
});
|
|
232
|
-
it('returns undefined if the initial deployed contract class was deleted', async ()
|
|
233
|
-
await store.deleteContractClasses([
|
|
308
|
+
it('returns undefined if the initial deployed contract class was deleted', async ()=>{
|
|
309
|
+
await store.deleteContractClasses([
|
|
310
|
+
contractClass
|
|
311
|
+
], blockNum);
|
|
234
312
|
await expect(store.getContractClass(contractClass.id)).resolves.toBeUndefined();
|
|
235
313
|
});
|
|
236
|
-
it('returns contract class if later "deployment" class was deleted', async ()
|
|
237
|
-
await store.addContractClasses([
|
|
238
|
-
|
|
314
|
+
it('returns contract class if later "deployment" class was deleted', async ()=>{
|
|
315
|
+
await store.addContractClasses([
|
|
316
|
+
contractClass
|
|
317
|
+
], [
|
|
318
|
+
await computePublicBytecodeCommitment(contractClass.packedBytecode)
|
|
319
|
+
], blockNum + 1);
|
|
320
|
+
await store.deleteContractClasses([
|
|
321
|
+
contractClass
|
|
322
|
+
], blockNum + 1);
|
|
239
323
|
await expect(store.getContractClass(contractClass.id)).resolves.toMatchObject(contractClass);
|
|
240
324
|
});
|
|
241
|
-
it('returns undefined if contract class is not found', async ()
|
|
325
|
+
it('returns undefined if contract class is not found', async ()=>{
|
|
242
326
|
await expect(store.getContractClass(Fr.random())).resolves.toBeUndefined();
|
|
243
327
|
});
|
|
244
|
-
it('adds new private functions', async ()
|
|
328
|
+
it('adds new private functions', async ()=>{
|
|
245
329
|
const fns = times(3, makeExecutablePrivateFunctionWithMembershipProof);
|
|
246
330
|
await store.addFunctions(contractClass.id, fns, []);
|
|
247
331
|
const stored = await store.getContractClass(contractClass.id);
|
|
248
332
|
expect(stored?.privateFunctions).toEqual(fns);
|
|
249
333
|
});
|
|
250
|
-
it('does not duplicate private functions', async ()
|
|
334
|
+
it('does not duplicate private functions', async ()=>{
|
|
251
335
|
const fns = times(3, makeExecutablePrivateFunctionWithMembershipProof);
|
|
252
336
|
await store.addFunctions(contractClass.id, fns.slice(0, 1), []);
|
|
253
337
|
await store.addFunctions(contractClass.id, fns, []);
|
|
254
338
|
const stored = await store.getContractClass(contractClass.id);
|
|
255
339
|
expect(stored?.privateFunctions).toEqual(fns);
|
|
256
340
|
});
|
|
257
|
-
it('adds new unconstrained functions', async ()
|
|
341
|
+
it('adds new unconstrained functions', async ()=>{
|
|
258
342
|
const fns = times(3, makeUnconstrainedFunctionWithMembershipProof);
|
|
259
343
|
await store.addFunctions(contractClass.id, [], fns);
|
|
260
344
|
const stored = await store.getContractClass(contractClass.id);
|
|
261
345
|
expect(stored?.unconstrainedFunctions).toEqual(fns);
|
|
262
346
|
});
|
|
263
|
-
it('does not duplicate unconstrained functions', async ()
|
|
347
|
+
it('does not duplicate unconstrained functions', async ()=>{
|
|
264
348
|
const fns = times(3, makeUnconstrainedFunctionWithMembershipProof);
|
|
265
349
|
await store.addFunctions(contractClass.id, [], fns.slice(0, 1));
|
|
266
350
|
await store.addFunctions(contractClass.id, [], fns);
|
|
@@ -268,46 +352,49 @@ export function describeArchiverDataStore(testName, getStore) {
|
|
|
268
352
|
expect(stored?.unconstrainedFunctions).toEqual(fns);
|
|
269
353
|
});
|
|
270
354
|
});
|
|
271
|
-
describe('getLogsByTags', ()
|
|
355
|
+
describe('getLogsByTags', ()=>{
|
|
272
356
|
const numBlocks = 3;
|
|
273
357
|
const numTxsPerBlock = 4;
|
|
274
358
|
const numPrivateLogsPerTx = 3;
|
|
275
359
|
const numPublicLogsPerTx = 2;
|
|
276
360
|
let blocks;
|
|
277
|
-
const makeTag = (blockNumber, txIndex, logIndex, isPublic = false)
|
|
361
|
+
const makeTag = (blockNumber, txIndex, logIndex, isPublic = false)=>new Fr((blockNumber * 100 + txIndex * 10 + logIndex) * (isPublic ? 123 : 1));
|
|
278
362
|
// See parseLogFromPublic
|
|
279
363
|
// Search the codebase for "disgusting encoding" to see other hardcoded instances of this encoding, that you might need to change if you ever find yourself here.
|
|
280
|
-
const makeLengthsField = (publicValuesLen, privateValuesLen)
|
|
364
|
+
const makeLengthsField = (publicValuesLen, privateValuesLen)=>{
|
|
281
365
|
const buf = Buffer.alloc(32);
|
|
282
366
|
buf.writeUint16BE(publicValuesLen, 27);
|
|
283
367
|
buf.writeUint16BE(privateValuesLen, 30);
|
|
284
368
|
return Fr.fromBuffer(buf);
|
|
285
369
|
};
|
|
286
|
-
const makePrivateLog = (tag)
|
|
370
|
+
const makePrivateLog = (tag)=>PrivateLog.fromFields([
|
|
371
|
+
tag,
|
|
372
|
+
...times(PRIVATE_LOG_SIZE_IN_FIELDS - 1, (i)=>new Fr(tag.toNumber() + i))
|
|
373
|
+
]);
|
|
287
374
|
// The tag lives in field 1, not 0, of a public log
|
|
288
375
|
// See extractTaggedLogsFromPublic and noir-projects/aztec-nr/aztec/src/macros/notes/mod.nr -> emit_log
|
|
289
|
-
const makePublicLog = (tag)
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
const mockPrivateLogs = (blockNumber, txIndex)
|
|
296
|
-
return times(numPrivateLogsPerTx, (logIndex)
|
|
376
|
+
const makePublicLog = (tag)=>PublicLog.fromFields([
|
|
377
|
+
AztecAddress.fromNumber(1).toField(),
|
|
378
|
+
makeLengthsField(2, PUBLIC_LOG_DATA_SIZE_IN_FIELDS - 3),
|
|
379
|
+
tag,
|
|
380
|
+
...times(PUBLIC_LOG_DATA_SIZE_IN_FIELDS - 1, (i)=>new Fr(tag.toNumber() + i))
|
|
381
|
+
]);
|
|
382
|
+
const mockPrivateLogs = (blockNumber, txIndex)=>{
|
|
383
|
+
return times(numPrivateLogsPerTx, (logIndex)=>{
|
|
297
384
|
const tag = makeTag(blockNumber, txIndex, logIndex);
|
|
298
385
|
return makePrivateLog(tag);
|
|
299
386
|
});
|
|
300
387
|
};
|
|
301
|
-
const mockPublicLogs = (blockNumber, txIndex)
|
|
302
|
-
return times(numPublicLogsPerTx, (logIndex)
|
|
388
|
+
const mockPublicLogs = (blockNumber, txIndex)=>{
|
|
389
|
+
return times(numPublicLogsPerTx, (logIndex)=>{
|
|
303
390
|
const tag = makeTag(blockNumber, txIndex, logIndex, /* isPublic */ true);
|
|
304
391
|
return makePublicLog(tag);
|
|
305
392
|
});
|
|
306
393
|
};
|
|
307
|
-
const mockBlockWithLogs = async (blockNumber)
|
|
394
|
+
const mockBlockWithLogs = async (blockNumber)=>{
|
|
308
395
|
const block = await L2Block.random(blockNumber);
|
|
309
396
|
block.header.globalVariables.blockNumber = new Fr(blockNumber);
|
|
310
|
-
block.body.txEffects = await timesParallel(numTxsPerBlock, async (txIndex)
|
|
397
|
+
block.body.txEffects = await timesParallel(numTxsPerBlock, async (txIndex)=>{
|
|
311
398
|
const txEffect = await TxEffect.random();
|
|
312
399
|
txEffect.privateLogs = mockPrivateLogs(blockNumber, txIndex);
|
|
313
400
|
txEffect.publicLogs = mockPublicLogs(blockNumber, txIndex);
|
|
@@ -315,203 +402,242 @@ export function describeArchiverDataStore(testName, getStore) {
|
|
|
315
402
|
});
|
|
316
403
|
return {
|
|
317
404
|
data: block,
|
|
318
|
-
l1: {
|
|
405
|
+
l1: {
|
|
406
|
+
blockNumber: BigInt(blockNumber),
|
|
407
|
+
blockHash: `0x${blockNumber}`,
|
|
408
|
+
timestamp: BigInt(blockNumber)
|
|
409
|
+
}
|
|
319
410
|
};
|
|
320
411
|
};
|
|
321
|
-
beforeEach(async ()
|
|
322
|
-
blocks = await timesParallel(numBlocks, (index)
|
|
412
|
+
beforeEach(async ()=>{
|
|
413
|
+
blocks = await timesParallel(numBlocks, (index)=>mockBlockWithLogs(index));
|
|
323
414
|
await store.addBlocks(blocks);
|
|
324
|
-
await store.addLogs(blocks.map(b
|
|
415
|
+
await store.addLogs(blocks.map((b)=>b.data));
|
|
325
416
|
});
|
|
326
|
-
it('is possible to batch request private logs via tags', async ()
|
|
327
|
-
const tags = [
|
|
417
|
+
it('is possible to batch request private logs via tags', async ()=>{
|
|
418
|
+
const tags = [
|
|
419
|
+
makeTag(1, 1, 2),
|
|
420
|
+
makeTag(0, 2, 0)
|
|
421
|
+
];
|
|
328
422
|
const logsByTags = await store.getLogsByTags(tags);
|
|
329
423
|
expect(logsByTags).toEqual([
|
|
330
424
|
[
|
|
331
425
|
expect.objectContaining({
|
|
332
426
|
blockNumber: 1,
|
|
333
427
|
logData: makePrivateLog(tags[0]).toBuffer(),
|
|
334
|
-
isFromPublic: false
|
|
335
|
-
})
|
|
428
|
+
isFromPublic: false
|
|
429
|
+
})
|
|
336
430
|
],
|
|
337
431
|
[
|
|
338
432
|
expect.objectContaining({
|
|
339
433
|
blockNumber: 0,
|
|
340
434
|
logData: makePrivateLog(tags[1]).toBuffer(),
|
|
341
|
-
isFromPublic: false
|
|
342
|
-
})
|
|
343
|
-
]
|
|
435
|
+
isFromPublic: false
|
|
436
|
+
})
|
|
437
|
+
]
|
|
344
438
|
]);
|
|
345
439
|
});
|
|
346
|
-
it('is possible to batch request all logs (private and public) via tags', async ()
|
|
440
|
+
it('is possible to batch request all logs (private and public) via tags', async ()=>{
|
|
347
441
|
// Tag(0, 0, 0) is shared with the first private log and the first public log.
|
|
348
|
-
const tags = [
|
|
442
|
+
const tags = [
|
|
443
|
+
makeTag(0, 0, 0)
|
|
444
|
+
];
|
|
349
445
|
const logsByTags = await store.getLogsByTags(tags);
|
|
350
446
|
expect(logsByTags).toEqual([
|
|
351
447
|
[
|
|
352
448
|
expect.objectContaining({
|
|
353
449
|
blockNumber: 0,
|
|
354
450
|
logData: makePrivateLog(tags[0]).toBuffer(),
|
|
355
|
-
isFromPublic: false
|
|
451
|
+
isFromPublic: false
|
|
356
452
|
}),
|
|
357
453
|
expect.objectContaining({
|
|
358
454
|
blockNumber: 0,
|
|
359
455
|
logData: makePublicLog(tags[0]).toBuffer(),
|
|
360
|
-
isFromPublic: true
|
|
361
|
-
})
|
|
362
|
-
]
|
|
456
|
+
isFromPublic: true
|
|
457
|
+
})
|
|
458
|
+
]
|
|
363
459
|
]);
|
|
364
460
|
});
|
|
365
|
-
it('is possible to batch request logs that have the same tag but different content', async ()
|
|
366
|
-
const tags = [
|
|
461
|
+
it('is possible to batch request logs that have the same tag but different content', async ()=>{
|
|
462
|
+
const tags = [
|
|
463
|
+
makeTag(1, 2, 1)
|
|
464
|
+
];
|
|
367
465
|
// Create a block containing logs that have the same tag as the blocks before.
|
|
368
466
|
const newBlockNumber = numBlocks;
|
|
369
467
|
const newBlock = await mockBlockWithLogs(newBlockNumber);
|
|
370
468
|
const newLog = newBlock.data.body.txEffects[1].privateLogs[1];
|
|
371
469
|
newLog.fields[0] = tags[0];
|
|
372
470
|
newBlock.data.body.txEffects[1].privateLogs[1] = newLog;
|
|
373
|
-
await store.addBlocks([
|
|
374
|
-
|
|
471
|
+
await store.addBlocks([
|
|
472
|
+
newBlock
|
|
473
|
+
]);
|
|
474
|
+
await store.addLogs([
|
|
475
|
+
newBlock.data
|
|
476
|
+
]);
|
|
375
477
|
const logsByTags = await store.getLogsByTags(tags);
|
|
376
478
|
expect(logsByTags).toEqual([
|
|
377
479
|
[
|
|
378
480
|
expect.objectContaining({
|
|
379
481
|
blockNumber: 1,
|
|
380
482
|
logData: makePrivateLog(tags[0]).toBuffer(),
|
|
381
|
-
isFromPublic: false
|
|
483
|
+
isFromPublic: false
|
|
382
484
|
}),
|
|
383
485
|
expect.objectContaining({
|
|
384
486
|
blockNumber: newBlockNumber,
|
|
385
487
|
logData: newLog.toBuffer(),
|
|
386
|
-
isFromPublic: false
|
|
387
|
-
})
|
|
388
|
-
]
|
|
488
|
+
isFromPublic: false
|
|
489
|
+
})
|
|
490
|
+
]
|
|
389
491
|
]);
|
|
390
492
|
});
|
|
391
|
-
it('is possible to request logs for non-existing tags and determine their position', async ()
|
|
392
|
-
const tags = [
|
|
493
|
+
it('is possible to request logs for non-existing tags and determine their position', async ()=>{
|
|
494
|
+
const tags = [
|
|
495
|
+
makeTag(99, 88, 77),
|
|
496
|
+
makeTag(1, 1, 1)
|
|
497
|
+
];
|
|
393
498
|
const logsByTags = await store.getLogsByTags(tags);
|
|
394
499
|
expect(logsByTags).toEqual([
|
|
395
|
-
[
|
|
396
|
-
// No logs for the first tag.
|
|
397
|
-
],
|
|
500
|
+
[],
|
|
398
501
|
[
|
|
399
502
|
expect.objectContaining({
|
|
400
503
|
blockNumber: 1,
|
|
401
504
|
logData: makePrivateLog(tags[1]).toBuffer(),
|
|
402
|
-
isFromPublic: false
|
|
403
|
-
})
|
|
404
|
-
]
|
|
505
|
+
isFromPublic: false
|
|
506
|
+
})
|
|
507
|
+
]
|
|
405
508
|
]);
|
|
406
509
|
});
|
|
407
|
-
it('is not possible to add public logs by tag if they are invalid', async ()
|
|
510
|
+
it('is not possible to add public logs by tag if they are invalid', async ()=>{
|
|
408
511
|
const tag = makeTag(99, 88, 77);
|
|
409
512
|
const invalidLogs = [
|
|
410
513
|
PublicLog.fromFields([
|
|
411
514
|
AztecAddress.fromNumber(1).toField(),
|
|
412
|
-
makeLengthsField(2, 3),
|
|
515
|
+
makeLengthsField(2, 3),
|
|
413
516
|
tag,
|
|
414
|
-
...times(PUBLIC_LOG_DATA_SIZE_IN_FIELDS - 1, i
|
|
517
|
+
...times(PUBLIC_LOG_DATA_SIZE_IN_FIELDS - 1, (i)=>new Fr(tag.toNumber() + i))
|
|
415
518
|
]),
|
|
416
519
|
PublicLog.fromFields([
|
|
417
520
|
AztecAddress.fromNumber(1).toField(),
|
|
418
|
-
makeLengthsField(2, PUBLIC_LOG_DATA_SIZE_IN_FIELDS),
|
|
521
|
+
makeLengthsField(2, PUBLIC_LOG_DATA_SIZE_IN_FIELDS),
|
|
419
522
|
tag,
|
|
420
|
-
...times(PUBLIC_LOG_DATA_SIZE_IN_FIELDS - 1, i
|
|
421
|
-
])
|
|
523
|
+
...times(PUBLIC_LOG_DATA_SIZE_IN_FIELDS - 1, (i)=>new Fr(tag.toNumber() + i))
|
|
524
|
+
])
|
|
422
525
|
];
|
|
423
526
|
// Create a block containing these invalid logs
|
|
424
527
|
const newBlockNumber = numBlocks;
|
|
425
528
|
const newBlock = await mockBlockWithLogs(newBlockNumber);
|
|
426
529
|
newBlock.data.body.txEffects[0].publicLogs = invalidLogs;
|
|
427
|
-
await store.addBlocks([
|
|
428
|
-
|
|
429
|
-
|
|
530
|
+
await store.addBlocks([
|
|
531
|
+
newBlock
|
|
532
|
+
]);
|
|
533
|
+
await store.addLogs([
|
|
534
|
+
newBlock.data
|
|
535
|
+
]);
|
|
536
|
+
const logsByTags = await store.getLogsByTags([
|
|
537
|
+
tag
|
|
538
|
+
]);
|
|
430
539
|
// Neither of the logs should have been added:
|
|
431
|
-
expect(logsByTags).toEqual([
|
|
540
|
+
expect(logsByTags).toEqual([
|
|
541
|
+
[]
|
|
542
|
+
]);
|
|
432
543
|
});
|
|
433
544
|
});
|
|
434
|
-
describe('getPublicLogs', ()
|
|
545
|
+
describe('getPublicLogs', ()=>{
|
|
435
546
|
const txsPerBlock = 4;
|
|
436
547
|
const numPublicFunctionCalls = 3;
|
|
437
548
|
const numPublicLogs = 2;
|
|
438
549
|
const numBlocks = 10;
|
|
439
550
|
let blocks;
|
|
440
|
-
beforeEach(async ()
|
|
441
|
-
blocks = await timesParallel(numBlocks, async (index)
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
551
|
+
beforeEach(async ()=>{
|
|
552
|
+
blocks = await timesParallel(numBlocks, async (index)=>({
|
|
553
|
+
data: await L2Block.random(index + 1, txsPerBlock, numPublicFunctionCalls, numPublicLogs),
|
|
554
|
+
l1: {
|
|
555
|
+
blockNumber: BigInt(index),
|
|
556
|
+
blockHash: `0x${index}`,
|
|
557
|
+
timestamp: BigInt(index)
|
|
558
|
+
}
|
|
559
|
+
}));
|
|
445
560
|
await store.addBlocks(blocks);
|
|
446
|
-
await store.addLogs(blocks.map(b
|
|
561
|
+
await store.addLogs(blocks.map((b)=>b.data));
|
|
447
562
|
});
|
|
448
|
-
it('no logs returned if deleted ("txHash" filter param is respected variant)', async ()
|
|
563
|
+
it('no logs returned if deleted ("txHash" filter param is respected variant)', async ()=>{
|
|
449
564
|
// get random tx
|
|
450
565
|
const targetBlockIndex = randomInt(numBlocks);
|
|
451
566
|
const targetTxIndex = randomInt(txsPerBlock);
|
|
452
567
|
const targetTxHash = blocks[targetBlockIndex].data.body.txEffects[targetTxIndex].txHash;
|
|
453
568
|
await Promise.all([
|
|
454
569
|
store.unwindBlocks(blocks.length, blocks.length),
|
|
455
|
-
store.deleteLogs(blocks.map(b
|
|
570
|
+
store.deleteLogs(blocks.map((b)=>b.data))
|
|
456
571
|
]);
|
|
457
|
-
const response = await store.getPublicLogs({
|
|
572
|
+
const response = await store.getPublicLogs({
|
|
573
|
+
txHash: targetTxHash
|
|
574
|
+
});
|
|
458
575
|
const logs = response.logs;
|
|
459
576
|
expect(response.maxLogsHit).toBeFalsy();
|
|
460
577
|
expect(logs.length).toEqual(0);
|
|
461
578
|
});
|
|
462
|
-
it('"txHash" filter param is respected', async ()
|
|
579
|
+
it('"txHash" filter param is respected', async ()=>{
|
|
463
580
|
// get random tx
|
|
464
581
|
const targetBlockIndex = randomInt(numBlocks);
|
|
465
582
|
const targetTxIndex = randomInt(txsPerBlock);
|
|
466
583
|
const targetTxHash = blocks[targetBlockIndex].data.body.txEffects[targetTxIndex].txHash;
|
|
467
|
-
const response = await store.getPublicLogs({
|
|
584
|
+
const response = await store.getPublicLogs({
|
|
585
|
+
txHash: targetTxHash
|
|
586
|
+
});
|
|
468
587
|
const logs = response.logs;
|
|
469
588
|
expect(response.maxLogsHit).toBeFalsy();
|
|
470
589
|
const expectedNumLogs = numPublicFunctionCalls * numPublicLogs;
|
|
471
590
|
expect(logs.length).toEqual(expectedNumLogs);
|
|
472
591
|
const targeBlockNumber = targetBlockIndex + INITIAL_L2_BLOCK_NUM;
|
|
473
|
-
for (const log of logs)
|
|
592
|
+
for (const log of logs){
|
|
474
593
|
expect(log.id.blockNumber).toEqual(targeBlockNumber);
|
|
475
594
|
expect(log.id.txIndex).toEqual(targetTxIndex);
|
|
476
595
|
}
|
|
477
596
|
});
|
|
478
|
-
it('"fromBlock" and "toBlock" filter params are respected', async ()
|
|
597
|
+
it('"fromBlock" and "toBlock" filter params are respected', async ()=>{
|
|
479
598
|
// Set "fromBlock" and "toBlock"
|
|
480
599
|
const fromBlock = 3;
|
|
481
600
|
const toBlock = 7;
|
|
482
|
-
const response = await store.getPublicLogs({
|
|
601
|
+
const response = await store.getPublicLogs({
|
|
602
|
+
fromBlock,
|
|
603
|
+
toBlock
|
|
604
|
+
});
|
|
483
605
|
const logs = response.logs;
|
|
484
606
|
expect(response.maxLogsHit).toBeFalsy();
|
|
485
607
|
const expectedNumLogs = txsPerBlock * numPublicFunctionCalls * numPublicLogs * (toBlock - fromBlock);
|
|
486
608
|
expect(logs.length).toEqual(expectedNumLogs);
|
|
487
|
-
for (const log of logs)
|
|
609
|
+
for (const log of logs){
|
|
488
610
|
const blockNumber = log.id.blockNumber;
|
|
489
611
|
expect(blockNumber).toBeGreaterThanOrEqual(fromBlock);
|
|
490
612
|
expect(blockNumber).toBeLessThan(toBlock);
|
|
491
613
|
}
|
|
492
614
|
});
|
|
493
|
-
it('"contractAddress" filter param is respected', async ()
|
|
615
|
+
it('"contractAddress" filter param is respected', async ()=>{
|
|
494
616
|
// Get a random contract address from the logs
|
|
495
617
|
const targetBlockIndex = randomInt(numBlocks);
|
|
496
618
|
const targetTxIndex = randomInt(txsPerBlock);
|
|
497
619
|
const targetLogIndex = randomInt(numPublicLogs * numPublicFunctionCalls);
|
|
498
620
|
const targetContractAddress = blocks[targetBlockIndex].data.body.txEffects[targetTxIndex].publicLogs[targetLogIndex].contractAddress;
|
|
499
|
-
const response = await store.getPublicLogs({
|
|
621
|
+
const response = await store.getPublicLogs({
|
|
622
|
+
contractAddress: targetContractAddress
|
|
623
|
+
});
|
|
500
624
|
expect(response.maxLogsHit).toBeFalsy();
|
|
501
|
-
for (const extendedLog of response.logs)
|
|
625
|
+
for (const extendedLog of response.logs){
|
|
502
626
|
expect(extendedLog.log.contractAddress.equals(targetContractAddress)).toBeTruthy();
|
|
503
627
|
}
|
|
504
628
|
});
|
|
505
|
-
it('"afterLog" filter param is respected', async ()
|
|
629
|
+
it('"afterLog" filter param is respected', async ()=>{
|
|
506
630
|
// Get a random log as reference
|
|
507
631
|
const targetBlockIndex = randomInt(numBlocks);
|
|
508
632
|
const targetTxIndex = randomInt(txsPerBlock);
|
|
509
633
|
const targetLogIndex = randomInt(numPublicLogs);
|
|
510
634
|
const afterLog = new LogId(targetBlockIndex + INITIAL_L2_BLOCK_NUM, targetTxIndex, targetLogIndex);
|
|
511
|
-
const response = await store.getPublicLogs({
|
|
635
|
+
const response = await store.getPublicLogs({
|
|
636
|
+
afterLog
|
|
637
|
+
});
|
|
512
638
|
const logs = response.logs;
|
|
513
639
|
expect(response.maxLogsHit).toBeFalsy();
|
|
514
|
-
for (const log of logs)
|
|
640
|
+
for (const log of logs){
|
|
515
641
|
const logId = log.id;
|
|
516
642
|
expect(logId.blockNumber).toBeGreaterThanOrEqual(afterLog.blockNumber);
|
|
517
643
|
if (logId.blockNumber === afterLog.blockNumber) {
|
|
@@ -522,48 +648,87 @@ export function describeArchiverDataStore(testName, getStore) {
|
|
|
522
648
|
}
|
|
523
649
|
}
|
|
524
650
|
});
|
|
525
|
-
it('"txHash" filter param is ignored when "afterLog" is set', async ()
|
|
651
|
+
it('"txHash" filter param is ignored when "afterLog" is set', async ()=>{
|
|
526
652
|
// Get random txHash
|
|
527
653
|
const txHash = TxHash.random();
|
|
528
654
|
const afterLog = new LogId(1, 0, 0);
|
|
529
|
-
const response = await store.getPublicLogs({
|
|
655
|
+
const response = await store.getPublicLogs({
|
|
656
|
+
txHash,
|
|
657
|
+
afterLog
|
|
658
|
+
});
|
|
530
659
|
expect(response.logs.length).toBeGreaterThan(1);
|
|
531
660
|
});
|
|
532
|
-
it('intersecting works', async ()
|
|
533
|
-
let logs = (await store.getPublicLogs({
|
|
661
|
+
it('intersecting works', async ()=>{
|
|
662
|
+
let logs = (await store.getPublicLogs({
|
|
663
|
+
fromBlock: -10,
|
|
664
|
+
toBlock: -5
|
|
665
|
+
})).logs;
|
|
534
666
|
expect(logs.length).toBe(0);
|
|
535
667
|
// "fromBlock" gets correctly trimmed to range and "toBlock" is exclusive
|
|
536
|
-
logs = (await store.getPublicLogs({
|
|
537
|
-
|
|
538
|
-
|
|
668
|
+
logs = (await store.getPublicLogs({
|
|
669
|
+
fromBlock: -10,
|
|
670
|
+
toBlock: 5
|
|
671
|
+
})).logs;
|
|
672
|
+
let blockNumbers = new Set(logs.map((log)=>log.id.blockNumber));
|
|
673
|
+
expect(blockNumbers).toEqual(new Set([
|
|
674
|
+
1,
|
|
675
|
+
2,
|
|
676
|
+
3,
|
|
677
|
+
4
|
|
678
|
+
]));
|
|
539
679
|
// "toBlock" should be exclusive
|
|
540
|
-
logs = (await store.getPublicLogs({
|
|
680
|
+
logs = (await store.getPublicLogs({
|
|
681
|
+
fromBlock: 1,
|
|
682
|
+
toBlock: 1
|
|
683
|
+
})).logs;
|
|
541
684
|
expect(logs.length).toBe(0);
|
|
542
|
-
logs = (await store.getPublicLogs({
|
|
685
|
+
logs = (await store.getPublicLogs({
|
|
686
|
+
fromBlock: 10,
|
|
687
|
+
toBlock: 5
|
|
688
|
+
})).logs;
|
|
543
689
|
expect(logs.length).toBe(0);
|
|
544
690
|
// both "fromBlock" and "toBlock" get correctly capped to range and logs from all blocks are returned
|
|
545
|
-
logs = (await store.getPublicLogs({
|
|
546
|
-
|
|
691
|
+
logs = (await store.getPublicLogs({
|
|
692
|
+
fromBlock: -100,
|
|
693
|
+
toBlock: +100
|
|
694
|
+
})).logs;
|
|
695
|
+
blockNumbers = new Set(logs.map((log)=>log.id.blockNumber));
|
|
547
696
|
expect(blockNumbers.size).toBe(numBlocks);
|
|
548
697
|
// intersecting with "afterLog" works
|
|
549
|
-
logs = (await store.getPublicLogs({
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
698
|
+
logs = (await store.getPublicLogs({
|
|
699
|
+
fromBlock: 2,
|
|
700
|
+
toBlock: 5,
|
|
701
|
+
afterLog: new LogId(4, 0, 0)
|
|
702
|
+
})).logs;
|
|
703
|
+
blockNumbers = new Set(logs.map((log)=>log.id.blockNumber));
|
|
704
|
+
expect(blockNumbers).toEqual(new Set([
|
|
705
|
+
4
|
|
706
|
+
]));
|
|
707
|
+
logs = (await store.getPublicLogs({
|
|
708
|
+
toBlock: 5,
|
|
709
|
+
afterLog: new LogId(5, 1, 0)
|
|
710
|
+
})).logs;
|
|
553
711
|
expect(logs.length).toBe(0);
|
|
554
|
-
logs = (await store.getPublicLogs({
|
|
712
|
+
logs = (await store.getPublicLogs({
|
|
713
|
+
fromBlock: 2,
|
|
714
|
+
toBlock: 5,
|
|
715
|
+
afterLog: new LogId(100, 0, 0)
|
|
716
|
+
})).logs;
|
|
555
717
|
expect(logs.length).toBe(0);
|
|
556
718
|
});
|
|
557
|
-
it('"txIndex" and "logIndex" are respected when "afterLog.blockNumber" is equal to "fromBlock"', async ()
|
|
719
|
+
it('"txIndex" and "logIndex" are respected when "afterLog.blockNumber" is equal to "fromBlock"', async ()=>{
|
|
558
720
|
// Get a random log as reference
|
|
559
721
|
const targetBlockIndex = randomInt(numBlocks);
|
|
560
722
|
const targetTxIndex = randomInt(txsPerBlock);
|
|
561
723
|
const targetLogIndex = randomInt(numPublicLogs);
|
|
562
724
|
const afterLog = new LogId(targetBlockIndex + INITIAL_L2_BLOCK_NUM, targetTxIndex, targetLogIndex);
|
|
563
|
-
const response = await store.getPublicLogs({
|
|
725
|
+
const response = await store.getPublicLogs({
|
|
726
|
+
afterLog,
|
|
727
|
+
fromBlock: afterLog.blockNumber
|
|
728
|
+
});
|
|
564
729
|
const logs = response.logs;
|
|
565
730
|
expect(response.maxLogsHit).toBeFalsy();
|
|
566
|
-
for (const log of logs)
|
|
731
|
+
for (const log of logs){
|
|
567
732
|
const logId = log.id;
|
|
568
733
|
expect(logId.blockNumber).toBeGreaterThanOrEqual(afterLog.blockNumber);
|
|
569
734
|
if (logId.blockNumber === afterLog.blockNumber) {
|
|
@@ -575,24 +740,28 @@ export function describeArchiverDataStore(testName, getStore) {
|
|
|
575
740
|
}
|
|
576
741
|
});
|
|
577
742
|
});
|
|
578
|
-
describe('findNullifiersIndexesWithBlock', ()
|
|
743
|
+
describe('findNullifiersIndexesWithBlock', ()=>{
|
|
579
744
|
let blocks;
|
|
580
745
|
const numBlocks = 10;
|
|
581
746
|
const nullifiersPerBlock = new Map();
|
|
582
|
-
beforeEach(async ()
|
|
583
|
-
blocks = await timesParallel(numBlocks, (index)
|
|
584
|
-
blocks.forEach((block, blockIndex)
|
|
585
|
-
nullifiersPerBlock.set(blockIndex, block.body.txEffects.flatMap(txEffect
|
|
747
|
+
beforeEach(async ()=>{
|
|
748
|
+
blocks = await timesParallel(numBlocks, (index)=>L2Block.random(index + 1, 1));
|
|
749
|
+
blocks.forEach((block, blockIndex)=>{
|
|
750
|
+
nullifiersPerBlock.set(blockIndex, block.body.txEffects.flatMap((txEffect)=>txEffect.nullifiers));
|
|
586
751
|
});
|
|
587
752
|
});
|
|
588
|
-
it('returns wrapped nullifiers with blocks if they exist', async ()
|
|
753
|
+
it('returns wrapped nullifiers with blocks if they exist', async ()=>{
|
|
589
754
|
await store.addNullifiers(blocks);
|
|
590
|
-
const nullifiersToRetrieve = [
|
|
755
|
+
const nullifiersToRetrieve = [
|
|
756
|
+
...nullifiersPerBlock.get(0),
|
|
757
|
+
...nullifiersPerBlock.get(5),
|
|
758
|
+
Fr.random()
|
|
759
|
+
];
|
|
591
760
|
const blockScopedNullifiers = await store.findNullifiersIndexesWithBlock(10, nullifiersToRetrieve);
|
|
592
761
|
expect(blockScopedNullifiers).toHaveLength(nullifiersToRetrieve.length);
|
|
593
762
|
const [undefinedNullifier] = blockScopedNullifiers.slice(-1);
|
|
594
763
|
const realNullifiers = blockScopedNullifiers.slice(0, -1);
|
|
595
|
-
realNullifiers.forEach((blockScopedNullifier, index)
|
|
764
|
+
realNullifiers.forEach((blockScopedNullifier, index)=>{
|
|
596
765
|
expect(blockScopedNullifier).not.toBeUndefined();
|
|
597
766
|
const { data, l2BlockNumber } = blockScopedNullifier;
|
|
598
767
|
expect(data).toEqual(expect.any(BigInt));
|
|
@@ -600,24 +769,26 @@ export function describeArchiverDataStore(testName, getStore) {
|
|
|
600
769
|
});
|
|
601
770
|
expect(undefinedNullifier).toBeUndefined();
|
|
602
771
|
});
|
|
603
|
-
it('returns wrapped nullifiers filtering by blockNumber', async ()
|
|
772
|
+
it('returns wrapped nullifiers filtering by blockNumber', async ()=>{
|
|
604
773
|
await store.addNullifiers(blocks);
|
|
605
|
-
const nullifiersToRetrieve = [
|
|
774
|
+
const nullifiersToRetrieve = [
|
|
775
|
+
...nullifiersPerBlock.get(0),
|
|
776
|
+
...nullifiersPerBlock.get(5)
|
|
777
|
+
];
|
|
606
778
|
const blockScopedNullifiers = await store.findNullifiersIndexesWithBlock(5, nullifiersToRetrieve);
|
|
607
779
|
expect(blockScopedNullifiers).toHaveLength(nullifiersToRetrieve.length);
|
|
608
780
|
const undefinedNullifiers = blockScopedNullifiers.slice(-MAX_NULLIFIERS_PER_TX);
|
|
609
781
|
const realNullifiers = blockScopedNullifiers.slice(0, -MAX_NULLIFIERS_PER_TX);
|
|
610
|
-
realNullifiers.forEach(blockScopedNullifier
|
|
782
|
+
realNullifiers.forEach((blockScopedNullifier)=>{
|
|
611
783
|
expect(blockScopedNullifier).not.toBeUndefined();
|
|
612
784
|
const { data, l2BlockNumber } = blockScopedNullifier;
|
|
613
785
|
expect(data).toEqual(expect.any(BigInt));
|
|
614
786
|
expect(l2BlockNumber).toEqual(1);
|
|
615
787
|
});
|
|
616
|
-
undefinedNullifiers.forEach(undefinedNullifier
|
|
788
|
+
undefinedNullifiers.forEach((undefinedNullifier)=>{
|
|
617
789
|
expect(undefinedNullifier).toBeUndefined();
|
|
618
790
|
});
|
|
619
791
|
});
|
|
620
792
|
});
|
|
621
793
|
});
|
|
622
794
|
}
|
|
623
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXJjaGl2ZXJfc3RvcmVfdGVzdF9zdWl0ZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9hcmNoaXZlci9hcmNoaXZlcl9zdG9yZV90ZXN0X3N1aXRlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxTQUFTLEVBQUUsT0FBTyxFQUFFLEtBQUssRUFBRSxRQUFRLEVBQUUsTUFBTSxFQUFFLFdBQVcsRUFBRSxNQUFNLHNCQUFzQixDQUFDO0FBQ2hHLE9BQU8sMkJBQTJCLENBQUM7QUFDbkMsT0FBTyxFQUNMLFlBQVksRUFHWixFQUFFLEVBQ0Ysb0JBQW9CLEVBQ3BCLDJCQUEyQixFQUMzQixxQkFBcUIsRUFDckIsMEJBQTBCLEVBQzFCLDhCQUE4QixFQUM5QixVQUFVLEVBQ1YsU0FBUyxFQUNULDRCQUE0QixFQUM1QiwrQkFBK0IsR0FDaEMsTUFBTSxvQkFBb0IsQ0FBQztBQUM1QixPQUFPLEVBQ0wsdUJBQXVCLEVBQ3ZCLGdEQUFnRCxFQUNoRCw0Q0FBNEMsR0FDN0MsTUFBTSw0QkFBNEIsQ0FBQztBQUNwQyxPQUFPLEVBQUUsS0FBSyxFQUFFLGFBQWEsRUFBRSxNQUFNLDhCQUE4QixDQUFDO0FBQ3BFLE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSwwQkFBMEIsQ0FBQztBQUtyRDs7O0dBR0c7QUFDSCxNQUFNLFVBQVUseUJBQXlCLENBQ3ZDLFFBQWdCLEVBQ2hCLFFBQThEO0lBRTlELFFBQVEsQ0FBQyxRQUFRLEVBQUUsR0FBRyxFQUFFO1FBQ3RCLElBQUksS0FBd0IsQ0FBQztRQUM3QixJQUFJLE1BQThCLENBQUM7UUFDbkMsTUFBTSxVQUFVLEdBQXFEO1lBQ25FLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxHQUFHLEVBQUUsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQztZQUNoQyxDQUFDLEVBQUUsRUFBRSxDQUFDLEVBQUUsR0FBRyxFQUFFLENBQUMsTUFB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
|