@aztec/archiver 0.0.0-test.0 → 0.0.1-commit.24de95ac
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 +27 -6
- package/dest/archiver/archiver.d.ts +126 -46
- package/dest/archiver/archiver.d.ts.map +1 -1
- package/dest/archiver/archiver.js +683 -261
- package/dest/archiver/archiver_store.d.ts +84 -49
- package/dest/archiver/archiver_store.d.ts.map +1 -1
- package/dest/archiver/archiver_store_test_suite.d.ts.map +1 -1
- package/dest/archiver/archiver_store_test_suite.js +707 -213
- package/dest/archiver/config.d.ts +4 -20
- package/dest/archiver/config.d.ts.map +1 -1
- package/dest/archiver/config.js +16 -12
- package/dest/archiver/data_retrieval.d.ts +25 -20
- package/dest/archiver/data_retrieval.d.ts.map +1 -1
- package/dest/archiver/data_retrieval.js +147 -68
- package/dest/archiver/errors.d.ts +8 -0
- package/dest/archiver/errors.d.ts.map +1 -1
- package/dest/archiver/errors.js +12 -0
- package/dest/archiver/index.d.ts +2 -3
- package/dest/archiver/index.d.ts.map +1 -1
- package/dest/archiver/index.js +1 -2
- package/dest/archiver/instrumentation.d.ts +9 -3
- package/dest/archiver/instrumentation.d.ts.map +1 -1
- package/dest/archiver/instrumentation.js +58 -17
- package/dest/archiver/kv_archiver_store/block_store.d.ts +47 -10
- package/dest/archiver/kv_archiver_store/block_store.d.ts.map +1 -1
- package/dest/archiver/kv_archiver_store/block_store.js +216 -63
- package/dest/archiver/kv_archiver_store/contract_class_store.d.ts +2 -2
- package/dest/archiver/kv_archiver_store/contract_class_store.d.ts.map +1 -1
- package/dest/archiver/kv_archiver_store/contract_class_store.js +12 -18
- package/dest/archiver/kv_archiver_store/contract_instance_store.d.ts +10 -7
- package/dest/archiver/kv_archiver_store/contract_instance_store.d.ts.map +1 -1
- package/dest/archiver/kv_archiver_store/contract_instance_store.js +30 -16
- package/dest/archiver/kv_archiver_store/kv_archiver_store.d.ts +49 -34
- package/dest/archiver/kv_archiver_store/kv_archiver_store.d.ts.map +1 -1
- package/dest/archiver/kv_archiver_store/kv_archiver_store.js +88 -46
- package/dest/archiver/kv_archiver_store/log_store.d.ts +1 -1
- package/dest/archiver/kv_archiver_store/log_store.d.ts.map +1 -1
- package/dest/archiver/kv_archiver_store/log_store.js +18 -46
- package/dest/archiver/kv_archiver_store/message_store.d.ts +22 -16
- package/dest/archiver/kv_archiver_store/message_store.d.ts.map +1 -1
- package/dest/archiver/kv_archiver_store/message_store.js +150 -48
- package/dest/archiver/structs/inbox_message.d.ts +15 -0
- package/dest/archiver/structs/inbox_message.d.ts.map +1 -0
- package/dest/archiver/structs/inbox_message.js +38 -0
- package/dest/archiver/structs/published.d.ts +1 -10
- package/dest/archiver/structs/published.d.ts.map +1 -1
- package/dest/archiver/structs/published.js +1 -1
- package/dest/archiver/validation.d.ts +11 -0
- package/dest/archiver/validation.d.ts.map +1 -0
- package/dest/archiver/validation.js +90 -0
- package/dest/factory.d.ts +7 -12
- package/dest/factory.d.ts.map +1 -1
- package/dest/factory.js +18 -49
- package/dest/rpc/index.d.ts +1 -2
- package/dest/rpc/index.d.ts.map +1 -1
- package/dest/rpc/index.js +1 -4
- package/dest/test/mock_archiver.d.ts +1 -1
- package/dest/test/mock_l1_to_l2_message_source.d.ts +4 -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 +14 -1
- package/dest/test/mock_l2_block_source.d.ts +32 -5
- package/dest/test/mock_l2_block_source.d.ts.map +1 -1
- package/dest/test/mock_l2_block_source.js +118 -7
- package/dest/test/mock_structs.d.ts +9 -0
- package/dest/test/mock_structs.d.ts.map +1 -0
- package/dest/test/mock_structs.js +37 -0
- package/package.json +25 -27
- package/src/archiver/archiver.ts +858 -317
- package/src/archiver/archiver_store.ts +97 -55
- package/src/archiver/archiver_store_test_suite.ts +663 -210
- package/src/archiver/config.ts +23 -41
- package/src/archiver/data_retrieval.ts +215 -92
- package/src/archiver/errors.ts +21 -0
- package/src/archiver/index.ts +2 -3
- package/src/archiver/instrumentation.ts +75 -20
- package/src/archiver/kv_archiver_store/block_store.ts +270 -72
- package/src/archiver/kv_archiver_store/contract_class_store.ts +13 -23
- package/src/archiver/kv_archiver_store/contract_instance_store.ts +35 -27
- package/src/archiver/kv_archiver_store/kv_archiver_store.ts +127 -63
- package/src/archiver/kv_archiver_store/log_store.ts +24 -62
- package/src/archiver/kv_archiver_store/message_store.ts +209 -53
- package/src/archiver/structs/inbox_message.ts +41 -0
- package/src/archiver/structs/published.ts +1 -11
- package/src/archiver/validation.ts +99 -0
- package/src/factory.ts +24 -66
- package/src/rpc/index.ts +1 -5
- package/src/test/mock_archiver.ts +1 -1
- package/src/test/mock_l1_to_l2_message_source.ts +14 -3
- package/src/test/mock_l2_block_source.ts +152 -8
- package/src/test/mock_structs.ts +49 -0
- package/dest/archiver/kv_archiver_store/nullifier_store.d.ts +0 -12
- package/dest/archiver/kv_archiver_store/nullifier_store.d.ts.map +0 -1
- package/dest/archiver/kv_archiver_store/nullifier_store.js +0 -73
- package/dest/archiver/memory_archiver_store/l1_to_l2_message_store.d.ts +0 -23
- package/dest/archiver/memory_archiver_store/l1_to_l2_message_store.d.ts.map +0 -1
- package/dest/archiver/memory_archiver_store/l1_to_l2_message_store.js +0 -49
- package/dest/archiver/memory_archiver_store/memory_archiver_store.d.ts +0 -175
- package/dest/archiver/memory_archiver_store/memory_archiver_store.d.ts.map +0 -1
- package/dest/archiver/memory_archiver_store/memory_archiver_store.js +0 -636
- package/src/archiver/kv_archiver_store/nullifier_store.ts +0 -97
- package/src/archiver/memory_archiver_store/l1_to_l2_message_store.ts +0 -61
- package/src/archiver/memory_archiver_store/memory_archiver_store.ts +0 -801
|
@@ -1,15 +1,22 @@
|
|
|
1
|
-
import { INITIAL_L2_BLOCK_NUM,
|
|
1
|
+
import { INITIAL_L2_BLOCK_NUM, NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP, PRIVATE_LOG_SIZE_IN_FIELDS } from '@aztec/constants';
|
|
2
|
+
import { makeTuple } from '@aztec/foundation/array';
|
|
3
|
+
import { Buffer16, Buffer32 } from '@aztec/foundation/buffer';
|
|
2
4
|
import { times, timesParallel } from '@aztec/foundation/collection';
|
|
3
5
|
import { randomInt } from '@aztec/foundation/crypto';
|
|
4
6
|
import { Fr } from '@aztec/foundation/fields';
|
|
7
|
+
import { toArray } from '@aztec/foundation/iterable';
|
|
8
|
+
import { sleep } from '@aztec/foundation/sleep';
|
|
5
9
|
import { AztecAddress } from '@aztec/stdlib/aztec-address';
|
|
6
|
-
import { L2Block, wrapInBlock } from '@aztec/stdlib/block';
|
|
10
|
+
import { CommitteeAttestation, EthAddress, L2Block, L2BlockHash, PublishedL2Block, randomBlockInfo, wrapInBlock } from '@aztec/stdlib/block';
|
|
7
11
|
import { SerializableContractInstance, computePublicBytecodeCommitment } from '@aztec/stdlib/contract';
|
|
8
12
|
import { LogId, PrivateLog, PublicLog } from '@aztec/stdlib/logs';
|
|
9
13
|
import { InboxLeaf } from '@aztec/stdlib/messaging';
|
|
10
|
-
import { makeContractClassPublic, makeExecutablePrivateFunctionWithMembershipProof,
|
|
14
|
+
import { makeContractClassPublic, makeExecutablePrivateFunctionWithMembershipProof, makeUtilityFunctionWithMembershipProof } from '@aztec/stdlib/testing';
|
|
11
15
|
import '@aztec/stdlib/testing/jest';
|
|
12
16
|
import { TxEffect, TxHash } from '@aztec/stdlib/tx';
|
|
17
|
+
import { makeInboxMessage, makeInboxMessages } from '../test/mock_structs.js';
|
|
18
|
+
import { BlockNumberNotSequentialError, InitialBlockNumberNotSequentialError } from './errors.js';
|
|
19
|
+
import { MessageStoreError } from './kv_archiver_store/message_store.js';
|
|
13
20
|
/**
|
|
14
21
|
* @param testName - The name of the test suite.
|
|
15
22
|
* @param getStore - Returns an instance of a store that's already been initialized.
|
|
@@ -44,17 +51,29 @@ import { TxEffect, TxHash } from '@aztec/stdlib/tx';
|
|
|
44
51
|
()=>blocks.slice(4, 6)
|
|
45
52
|
]
|
|
46
53
|
];
|
|
47
|
-
const
|
|
48
|
-
|
|
54
|
+
const makeBlockHash = (blockNumber)=>`0x${blockNumber.toString(16).padStart(64, '0')}`;
|
|
55
|
+
const makePublished = (block, l1BlockNumber)=>PublishedL2Block.fromFields({
|
|
56
|
+
block: block,
|
|
49
57
|
l1: {
|
|
50
58
|
blockNumber: BigInt(l1BlockNumber),
|
|
51
|
-
blockHash:
|
|
59
|
+
blockHash: makeBlockHash(l1BlockNumber),
|
|
52
60
|
timestamp: BigInt(l1BlockNumber * 1000)
|
|
53
|
-
}
|
|
61
|
+
},
|
|
62
|
+
attestations: times(3, CommitteeAttestation.random)
|
|
54
63
|
});
|
|
64
|
+
const expectBlocksEqual = (actual, expected)=>{
|
|
65
|
+
expect(actual.length).toEqual(expected.length);
|
|
66
|
+
for(let i = 0; i < expected.length; i++){
|
|
67
|
+
const expectedBlock = expected[i];
|
|
68
|
+
const actualBlock = actual[i];
|
|
69
|
+
expect(actualBlock.l1).toEqual(expectedBlock.l1);
|
|
70
|
+
expect(actualBlock.block.equals(expectedBlock.block)).toBe(true);
|
|
71
|
+
expect(actualBlock.attestations.every((a, i)=>a.equals(expectedBlock.attestations[i]))).toBe(true);
|
|
72
|
+
}
|
|
73
|
+
};
|
|
55
74
|
beforeEach(async ()=>{
|
|
56
75
|
store = await getStore();
|
|
57
|
-
blocks = await timesParallel(10, async (i)=>
|
|
76
|
+
blocks = await timesParallel(10, async (i)=>makePublished(await L2Block.random(i + 1), i + 10));
|
|
58
77
|
});
|
|
59
78
|
describe('addBlocks', ()=>{
|
|
60
79
|
it('returns success when adding blocks', async ()=>{
|
|
@@ -64,25 +83,40 @@ import { TxEffect, TxHash } from '@aztec/stdlib/tx';
|
|
|
64
83
|
await store.addBlocks(blocks);
|
|
65
84
|
await expect(store.addBlocks(blocks)).resolves.toBe(true);
|
|
66
85
|
});
|
|
86
|
+
it('throws an error if the previous block does not exist in the store', async ()=>{
|
|
87
|
+
const block = makePublished(await L2Block.random(2), 2);
|
|
88
|
+
await expect(store.addBlocks([
|
|
89
|
+
block
|
|
90
|
+
])).rejects.toThrow(InitialBlockNumberNotSequentialError);
|
|
91
|
+
await expect(store.getPublishedBlocks(1, 10)).resolves.toEqual([]);
|
|
92
|
+
});
|
|
93
|
+
it('throws an error if there is a gap in the blocks being added', async ()=>{
|
|
94
|
+
const blocks = [
|
|
95
|
+
makePublished(await L2Block.random(1), 1),
|
|
96
|
+
makePublished(await L2Block.random(3), 3)
|
|
97
|
+
];
|
|
98
|
+
await expect(store.addBlocks(blocks)).rejects.toThrow(BlockNumberNotSequentialError);
|
|
99
|
+
await expect(store.getPublishedBlocks(1, 10)).resolves.toEqual([]);
|
|
100
|
+
});
|
|
67
101
|
});
|
|
68
102
|
describe('unwindBlocks', ()=>{
|
|
69
103
|
it('unwinding blocks will remove blocks from the chain', async ()=>{
|
|
70
104
|
await store.addBlocks(blocks);
|
|
71
105
|
const blockNumber = await store.getSynchedL2BlockNumber();
|
|
72
|
-
|
|
106
|
+
expectBlocksEqual(await store.getPublishedBlocks(blockNumber, 1), [
|
|
73
107
|
blocks[blocks.length - 1]
|
|
74
108
|
]);
|
|
75
109
|
await store.unwindBlocks(blockNumber, 1);
|
|
76
110
|
expect(await store.getSynchedL2BlockNumber()).toBe(blockNumber - 1);
|
|
77
|
-
expect(await store.
|
|
111
|
+
expect(await store.getPublishedBlocks(blockNumber, 1)).toEqual([]);
|
|
78
112
|
});
|
|
79
113
|
it('can unwind multiple empty blocks', async ()=>{
|
|
80
|
-
const emptyBlocks = await timesParallel(10, async (i)=>
|
|
114
|
+
const emptyBlocks = await timesParallel(10, async (i)=>makePublished(await L2Block.random(i + 1, 0), i + 10));
|
|
81
115
|
await store.addBlocks(emptyBlocks);
|
|
82
116
|
expect(await store.getSynchedL2BlockNumber()).toBe(10);
|
|
83
117
|
await store.unwindBlocks(10, 3);
|
|
84
118
|
expect(await store.getSynchedL2BlockNumber()).toBe(7);
|
|
85
|
-
expect((await store.
|
|
119
|
+
expect((await store.getPublishedBlocks(1, 10)).map((b)=>b.block.number)).toEqual([
|
|
86
120
|
1,
|
|
87
121
|
2,
|
|
88
122
|
3,
|
|
@@ -96,22 +130,129 @@ import { TxEffect, TxHash } from '@aztec/stdlib/tx';
|
|
|
96
130
|
await store.addBlocks(blocks);
|
|
97
131
|
await expect(store.unwindBlocks(5, 1)).rejects.toThrow(/can only unwind blocks from the tip/i);
|
|
98
132
|
});
|
|
133
|
+
it('unwound blocks and headers cannot be retrieved by hash or archive', async ()=>{
|
|
134
|
+
await store.addBlocks(blocks);
|
|
135
|
+
const lastBlock = blocks[blocks.length - 1];
|
|
136
|
+
const blockHash = await lastBlock.block.hash();
|
|
137
|
+
const archive = lastBlock.block.archive.root;
|
|
138
|
+
// Verify block and header exist before unwinding
|
|
139
|
+
expect(await store.getPublishedBlockByHash(blockHash)).toBeDefined();
|
|
140
|
+
expect(await store.getPublishedBlockByArchive(archive)).toBeDefined();
|
|
141
|
+
expect(await store.getBlockHeaderByHash(blockHash)).toBeDefined();
|
|
142
|
+
expect(await store.getBlockHeaderByArchive(archive)).toBeDefined();
|
|
143
|
+
// Unwind the block
|
|
144
|
+
await store.unwindBlocks(lastBlock.block.number, 1);
|
|
145
|
+
// Verify neither block nor header can be retrieved after unwinding
|
|
146
|
+
expect(await store.getPublishedBlockByHash(blockHash)).toBeUndefined();
|
|
147
|
+
expect(await store.getPublishedBlockByArchive(archive)).toBeUndefined();
|
|
148
|
+
expect(await store.getBlockHeaderByHash(blockHash)).toBeUndefined();
|
|
149
|
+
expect(await store.getBlockHeaderByArchive(archive)).toBeUndefined();
|
|
150
|
+
});
|
|
99
151
|
});
|
|
100
152
|
describe('getBlocks', ()=>{
|
|
101
153
|
beforeEach(async ()=>{
|
|
102
154
|
await store.addBlocks(blocks);
|
|
103
155
|
});
|
|
104
156
|
it.each(blockTests)('retrieves previously stored blocks', async (start, limit, getExpectedBlocks)=>{
|
|
105
|
-
await
|
|
157
|
+
expectBlocksEqual(await store.getPublishedBlocks(start, limit), getExpectedBlocks());
|
|
106
158
|
});
|
|
107
159
|
it('returns an empty array if no blocks are found', async ()=>{
|
|
108
|
-
await expect(store.
|
|
160
|
+
await expect(store.getPublishedBlocks(12, 1)).resolves.toEqual([]);
|
|
109
161
|
});
|
|
110
162
|
it('throws an error if limit is invalid', async ()=>{
|
|
111
|
-
await expect(store.
|
|
163
|
+
await expect(store.getPublishedBlocks(1, 0)).rejects.toThrow('Invalid limit: 0');
|
|
112
164
|
});
|
|
113
165
|
it('throws an error if `from` it is out of range', async ()=>{
|
|
114
|
-
await expect(store.
|
|
166
|
+
await expect(store.getPublishedBlocks(INITIAL_L2_BLOCK_NUM - 100, 1)).rejects.toThrow('Invalid start: -99');
|
|
167
|
+
});
|
|
168
|
+
it('throws an error if unexpected initial block number is found', async ()=>{
|
|
169
|
+
await store.addBlocks([
|
|
170
|
+
makePublished(await L2Block.random(21), 31)
|
|
171
|
+
], {
|
|
172
|
+
force: true
|
|
173
|
+
});
|
|
174
|
+
await expect(store.getPublishedBlocks(20, 1)).rejects.toThrow(`mismatch`);
|
|
175
|
+
});
|
|
176
|
+
it('throws an error if a gap is found', async ()=>{
|
|
177
|
+
await store.addBlocks([
|
|
178
|
+
makePublished(await L2Block.random(20), 30),
|
|
179
|
+
makePublished(await L2Block.random(22), 32)
|
|
180
|
+
], {
|
|
181
|
+
force: true
|
|
182
|
+
});
|
|
183
|
+
await expect(store.getPublishedBlocks(20, 2)).rejects.toThrow(`mismatch`);
|
|
184
|
+
});
|
|
185
|
+
});
|
|
186
|
+
describe('getPublishedBlockByHash', ()=>{
|
|
187
|
+
beforeEach(async ()=>{
|
|
188
|
+
await store.addBlocks(blocks);
|
|
189
|
+
});
|
|
190
|
+
it('retrieves a block by its hash', async ()=>{
|
|
191
|
+
const expectedBlock = blocks[5];
|
|
192
|
+
const blockHash = await expectedBlock.block.hash();
|
|
193
|
+
const retrievedBlock = await store.getPublishedBlockByHash(blockHash);
|
|
194
|
+
expect(retrievedBlock).toBeDefined();
|
|
195
|
+
expectBlocksEqual([
|
|
196
|
+
retrievedBlock
|
|
197
|
+
], [
|
|
198
|
+
expectedBlock
|
|
199
|
+
]);
|
|
200
|
+
});
|
|
201
|
+
it('returns undefined for non-existent block hash', async ()=>{
|
|
202
|
+
const nonExistentHash = Fr.random();
|
|
203
|
+
await expect(store.getPublishedBlockByHash(nonExistentHash)).resolves.toBeUndefined();
|
|
204
|
+
});
|
|
205
|
+
});
|
|
206
|
+
describe('getPublishedBlockByArchive', ()=>{
|
|
207
|
+
beforeEach(async ()=>{
|
|
208
|
+
await store.addBlocks(blocks);
|
|
209
|
+
});
|
|
210
|
+
it('retrieves a block by its archive root', async ()=>{
|
|
211
|
+
const expectedBlock = blocks[3];
|
|
212
|
+
const archive = expectedBlock.block.archive.root;
|
|
213
|
+
const retrievedBlock = await store.getPublishedBlockByArchive(archive);
|
|
214
|
+
expect(retrievedBlock).toBeDefined();
|
|
215
|
+
expectBlocksEqual([
|
|
216
|
+
retrievedBlock
|
|
217
|
+
], [
|
|
218
|
+
expectedBlock
|
|
219
|
+
]);
|
|
220
|
+
});
|
|
221
|
+
it('returns undefined for non-existent archive root', async ()=>{
|
|
222
|
+
const nonExistentArchive = Fr.random();
|
|
223
|
+
await expect(store.getPublishedBlockByArchive(nonExistentArchive)).resolves.toBeUndefined();
|
|
224
|
+
});
|
|
225
|
+
});
|
|
226
|
+
describe('getBlockHeaderByHash', ()=>{
|
|
227
|
+
beforeEach(async ()=>{
|
|
228
|
+
await store.addBlocks(blocks);
|
|
229
|
+
});
|
|
230
|
+
it('retrieves a block header by its hash', async ()=>{
|
|
231
|
+
const expectedBlock = blocks[7];
|
|
232
|
+
const blockHash = await expectedBlock.block.hash();
|
|
233
|
+
const retrievedHeader = await store.getBlockHeaderByHash(blockHash);
|
|
234
|
+
expect(retrievedHeader).toBeDefined();
|
|
235
|
+
expect(retrievedHeader.equals(expectedBlock.block.getBlockHeader())).toBe(true);
|
|
236
|
+
});
|
|
237
|
+
it('returns undefined for non-existent block hash', async ()=>{
|
|
238
|
+
const nonExistentHash = Fr.random();
|
|
239
|
+
await expect(store.getBlockHeaderByHash(nonExistentHash)).resolves.toBeUndefined();
|
|
240
|
+
});
|
|
241
|
+
});
|
|
242
|
+
describe('getBlockHeaderByArchive', ()=>{
|
|
243
|
+
beforeEach(async ()=>{
|
|
244
|
+
await store.addBlocks(blocks);
|
|
245
|
+
});
|
|
246
|
+
it('retrieves a block header by its archive root', async ()=>{
|
|
247
|
+
const expectedBlock = blocks[2];
|
|
248
|
+
const archive = expectedBlock.block.archive.root;
|
|
249
|
+
const retrievedHeader = await store.getBlockHeaderByArchive(archive);
|
|
250
|
+
expect(retrievedHeader).toBeDefined();
|
|
251
|
+
expect(retrievedHeader.equals(expectedBlock.block.getBlockHeader())).toBe(true);
|
|
252
|
+
});
|
|
253
|
+
it('returns undefined for non-existent archive root', async ()=>{
|
|
254
|
+
const nonExistentArchive = Fr.random();
|
|
255
|
+
await expect(store.getBlockHeaderByArchive(nonExistentArchive)).resolves.toBeUndefined();
|
|
115
256
|
});
|
|
116
257
|
});
|
|
117
258
|
describe('getSyncedL2BlockNumber', ()=>{
|
|
@@ -120,7 +261,7 @@ import { TxEffect, TxHash } from '@aztec/stdlib/tx';
|
|
|
120
261
|
});
|
|
121
262
|
it("returns the most recently added block's number", async ()=>{
|
|
122
263
|
await store.addBlocks(blocks);
|
|
123
|
-
await expect(store.getSynchedL2BlockNumber()).resolves.toEqual(blocks.at(-1).
|
|
264
|
+
await expect(store.getSynchedL2BlockNumber()).resolves.toEqual(blocks.at(-1).block.number);
|
|
124
265
|
});
|
|
125
266
|
});
|
|
126
267
|
describe('getSynchPoint', ()=>{
|
|
@@ -138,21 +279,52 @@ import { TxEffect, TxHash } from '@aztec/stdlib/tx';
|
|
|
138
279
|
});
|
|
139
280
|
});
|
|
140
281
|
it('returns the L1 block number that most recently added messages from inbox', async ()=>{
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
282
|
+
const l1BlockHash = Buffer32.random();
|
|
283
|
+
const l1BlockNumber = 10n;
|
|
284
|
+
await store.setMessageSynchedL1Block({
|
|
285
|
+
l1BlockNumber: 5n,
|
|
286
|
+
l1BlockHash: Buffer32.random()
|
|
146
287
|
});
|
|
288
|
+
await store.addL1ToL2Messages([
|
|
289
|
+
makeInboxMessage(Buffer16.ZERO, {
|
|
290
|
+
l1BlockNumber,
|
|
291
|
+
l1BlockHash
|
|
292
|
+
})
|
|
293
|
+
]);
|
|
147
294
|
await expect(store.getSynchPoint()).resolves.toEqual({
|
|
148
295
|
blocksSynchedTo: undefined,
|
|
149
|
-
messagesSynchedTo:
|
|
296
|
+
messagesSynchedTo: {
|
|
297
|
+
l1BlockHash,
|
|
298
|
+
l1BlockNumber
|
|
299
|
+
}
|
|
300
|
+
});
|
|
301
|
+
});
|
|
302
|
+
it('returns the latest syncpoint if latest message is behind', async ()=>{
|
|
303
|
+
const l1BlockHash = Buffer32.random();
|
|
304
|
+
const l1BlockNumber = 10n;
|
|
305
|
+
await store.setMessageSynchedL1Block({
|
|
306
|
+
l1BlockNumber,
|
|
307
|
+
l1BlockHash
|
|
308
|
+
});
|
|
309
|
+
const msg = makeInboxMessage(Buffer16.ZERO, {
|
|
310
|
+
l1BlockNumber: 5n,
|
|
311
|
+
l1BlockHash: Buffer32.random()
|
|
312
|
+
});
|
|
313
|
+
await store.addL1ToL2Messages([
|
|
314
|
+
msg
|
|
315
|
+
]);
|
|
316
|
+
await expect(store.getSynchPoint()).resolves.toEqual({
|
|
317
|
+
blocksSynchedTo: undefined,
|
|
318
|
+
messagesSynchedTo: {
|
|
319
|
+
l1BlockHash,
|
|
320
|
+
l1BlockNumber
|
|
321
|
+
}
|
|
150
322
|
});
|
|
151
323
|
});
|
|
152
324
|
});
|
|
153
325
|
describe('addLogs', ()=>{
|
|
154
326
|
it('adds private & public logs', async ()=>{
|
|
155
|
-
const block = blocks[0].
|
|
327
|
+
const block = blocks[0].block;
|
|
156
328
|
await expect(store.addLogs([
|
|
157
329
|
block
|
|
158
330
|
])).resolves.toEqual(true);
|
|
@@ -160,7 +332,7 @@ import { TxEffect, TxHash } from '@aztec/stdlib/tx';
|
|
|
160
332
|
});
|
|
161
333
|
describe('deleteLogs', ()=>{
|
|
162
334
|
it('deletes private & public logs', async ()=>{
|
|
163
|
-
const block = blocks[0].
|
|
335
|
+
const block = blocks[0].block;
|
|
164
336
|
await store.addBlocks([
|
|
165
337
|
blocks[0]
|
|
166
338
|
]);
|
|
@@ -183,7 +355,7 @@ import { TxEffect, TxHash } from '@aztec/stdlib/tx';
|
|
|
183
355
|
});
|
|
184
356
|
describe('getPrivateLogs', ()=>{
|
|
185
357
|
it('gets added private logs', async ()=>{
|
|
186
|
-
const block = blocks[0].
|
|
358
|
+
const block = blocks[0].block;
|
|
187
359
|
await store.addBlocks([
|
|
188
360
|
blocks[0]
|
|
189
361
|
]);
|
|
@@ -196,29 +368,55 @@ import { TxEffect, TxHash } from '@aztec/stdlib/tx';
|
|
|
196
368
|
});
|
|
197
369
|
describe('getTxEffect', ()=>{
|
|
198
370
|
beforeEach(async ()=>{
|
|
199
|
-
await store.addLogs(blocks.map((b)=>b.
|
|
371
|
+
await store.addLogs(blocks.map((b)=>b.block));
|
|
200
372
|
await store.addBlocks(blocks);
|
|
201
373
|
});
|
|
202
374
|
it.each([
|
|
203
|
-
()=>
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
375
|
+
()=>({
|
|
376
|
+
data: blocks[0].block.body.txEffects[0],
|
|
377
|
+
block: blocks[0].block,
|
|
378
|
+
txIndexInBlock: 0
|
|
379
|
+
}),
|
|
380
|
+
()=>({
|
|
381
|
+
data: blocks[9].block.body.txEffects[3],
|
|
382
|
+
block: blocks[9].block,
|
|
383
|
+
txIndexInBlock: 3
|
|
384
|
+
}),
|
|
385
|
+
()=>({
|
|
386
|
+
data: blocks[3].block.body.txEffects[1],
|
|
387
|
+
block: blocks[3].block,
|
|
388
|
+
txIndexInBlock: 1
|
|
389
|
+
}),
|
|
390
|
+
()=>({
|
|
391
|
+
data: blocks[5].block.body.txEffects[2],
|
|
392
|
+
block: blocks[5].block,
|
|
393
|
+
txIndexInBlock: 2
|
|
394
|
+
}),
|
|
395
|
+
()=>({
|
|
396
|
+
data: blocks[1].block.body.txEffects[0],
|
|
397
|
+
block: blocks[1].block,
|
|
398
|
+
txIndexInBlock: 0
|
|
399
|
+
})
|
|
208
400
|
])('retrieves a previously stored transaction', async (getExpectedTx)=>{
|
|
209
|
-
const
|
|
210
|
-
const
|
|
401
|
+
const { data, block, txIndexInBlock } = getExpectedTx();
|
|
402
|
+
const expectedTx = {
|
|
403
|
+
data,
|
|
404
|
+
l2BlockNumber: block.number,
|
|
405
|
+
l2BlockHash: L2BlockHash.fromField(await block.hash()),
|
|
406
|
+
txIndexInBlock
|
|
407
|
+
};
|
|
408
|
+
const actualTx = await store.getTxEffect(data.txHash);
|
|
211
409
|
expect(actualTx).toEqual(expectedTx);
|
|
212
410
|
});
|
|
213
411
|
it('returns undefined if tx is not found', async ()=>{
|
|
214
412
|
await expect(store.getTxEffect(TxHash.random())).resolves.toBeUndefined();
|
|
215
413
|
});
|
|
216
414
|
it.each([
|
|
217
|
-
()=>wrapInBlock(blocks[0].
|
|
218
|
-
()=>wrapInBlock(blocks[9].
|
|
219
|
-
()=>wrapInBlock(blocks[3].
|
|
220
|
-
()=>wrapInBlock(blocks[5].
|
|
221
|
-
()=>wrapInBlock(blocks[1].
|
|
415
|
+
()=>wrapInBlock(blocks[0].block.body.txEffects[0], blocks[0].block),
|
|
416
|
+
()=>wrapInBlock(blocks[9].block.body.txEffects[3], blocks[9].block),
|
|
417
|
+
()=>wrapInBlock(blocks[3].block.body.txEffects[1], blocks[3].block),
|
|
418
|
+
()=>wrapInBlock(blocks[5].block.body.txEffects[2], blocks[5].block),
|
|
419
|
+
()=>wrapInBlock(blocks[1].block.body.txEffects[0], blocks[1].block)
|
|
222
420
|
])('tries to retrieves a previously stored transaction after deleted', async (getExpectedTx)=>{
|
|
223
421
|
await store.unwindBlocks(blocks.length, blocks.length);
|
|
224
422
|
const expectedTx = await getExpectedTx();
|
|
@@ -228,42 +426,245 @@ import { TxEffect, TxHash } from '@aztec/stdlib/tx';
|
|
|
228
426
|
it('returns undefined if tx is not found', async ()=>{
|
|
229
427
|
await expect(store.getTxEffect(TxHash.random())).resolves.toBeUndefined();
|
|
230
428
|
});
|
|
429
|
+
it('does not fail if the block is unwound while requesting a tx', async ()=>{
|
|
430
|
+
const expectedTx = await wrapInBlock(blocks[1].block.body.txEffects[0], blocks[1].block);
|
|
431
|
+
let done = false;
|
|
432
|
+
void (async ()=>{
|
|
433
|
+
while(!done){
|
|
434
|
+
void store.getTxEffect(expectedTx.data.txHash);
|
|
435
|
+
await sleep(1);
|
|
436
|
+
}
|
|
437
|
+
})();
|
|
438
|
+
await store.unwindBlocks(blocks.length, blocks.length);
|
|
439
|
+
done = true;
|
|
440
|
+
expect(await store.getTxEffect(expectedTx.data.txHash)).toEqual(undefined);
|
|
441
|
+
});
|
|
231
442
|
});
|
|
232
443
|
describe('L1 to L2 Messages', ()=>{
|
|
233
|
-
const
|
|
234
|
-
const
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
await store.addL1ToL2Messages(
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
444
|
+
const initialL2BlockNumber = 13;
|
|
445
|
+
const checkMessages = async (msgs)=>{
|
|
446
|
+
expect(await store.getLastL1ToL2Message()).toEqual(msgs.at(-1));
|
|
447
|
+
expect(await toArray(store.iterateL1ToL2Messages())).toEqual(msgs);
|
|
448
|
+
expect(await store.getTotalL1ToL2MessageCount()).toEqual(BigInt(msgs.length));
|
|
449
|
+
};
|
|
450
|
+
const makeInboxMessagesWithFullBlocks = (blockCount, opts = {})=>makeInboxMessages(NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP * blockCount, {
|
|
451
|
+
overrideFn: (msg, i)=>{
|
|
452
|
+
const l2BlockNumber = (opts.initialL2BlockNumber ?? initialL2BlockNumber) + Math.floor(i / NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP);
|
|
453
|
+
const index = InboxLeaf.smallestIndexFromL2Block(l2BlockNumber) + BigInt(i % NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP);
|
|
454
|
+
return {
|
|
455
|
+
...msg,
|
|
456
|
+
l2BlockNumber,
|
|
457
|
+
index
|
|
458
|
+
};
|
|
459
|
+
}
|
|
460
|
+
});
|
|
461
|
+
it('stores first message ever', async ()=>{
|
|
462
|
+
const msg = makeInboxMessage(Buffer16.ZERO, {
|
|
463
|
+
index: 0n,
|
|
464
|
+
l2BlockNumber: 1
|
|
465
|
+
});
|
|
466
|
+
await store.addL1ToL2Messages([
|
|
467
|
+
msg
|
|
468
|
+
]);
|
|
469
|
+
await checkMessages([
|
|
470
|
+
msg
|
|
471
|
+
]);
|
|
472
|
+
expect(await store.getL1ToL2Messages(1)).toEqual([
|
|
473
|
+
msg.leaf
|
|
474
|
+
]);
|
|
475
|
+
});
|
|
476
|
+
it('stores single message', async ()=>{
|
|
477
|
+
const msg = makeInboxMessage(Buffer16.ZERO, {
|
|
478
|
+
l2BlockNumber: 2
|
|
479
|
+
});
|
|
480
|
+
await store.addL1ToL2Messages([
|
|
481
|
+
msg
|
|
482
|
+
]);
|
|
483
|
+
await checkMessages([
|
|
484
|
+
msg
|
|
485
|
+
]);
|
|
486
|
+
expect(await store.getL1ToL2Messages(2)).toEqual([
|
|
487
|
+
msg.leaf
|
|
488
|
+
]);
|
|
489
|
+
});
|
|
490
|
+
it('stores and returns messages across different blocks', async ()=>{
|
|
491
|
+
const msgs = makeInboxMessages(5, {
|
|
492
|
+
initialL2BlockNumber
|
|
493
|
+
});
|
|
494
|
+
await store.addL1ToL2Messages(msgs);
|
|
495
|
+
await checkMessages(msgs);
|
|
496
|
+
expect(await store.getL1ToL2Messages(initialL2BlockNumber + 2)).toEqual([
|
|
497
|
+
msgs[2]
|
|
498
|
+
].map((m)=>m.leaf));
|
|
499
|
+
});
|
|
500
|
+
it('stores the same messages again', async ()=>{
|
|
501
|
+
const msgs = makeInboxMessages(5, {
|
|
502
|
+
initialL2BlockNumber
|
|
503
|
+
});
|
|
504
|
+
await store.addL1ToL2Messages(msgs);
|
|
505
|
+
await store.addL1ToL2Messages(msgs.slice(2));
|
|
506
|
+
await checkMessages(msgs);
|
|
507
|
+
});
|
|
508
|
+
it('stores and returns messages across different blocks with gaps', async ()=>{
|
|
509
|
+
const msgs1 = makeInboxMessages(3, {
|
|
510
|
+
initialL2BlockNumber: 1
|
|
511
|
+
});
|
|
512
|
+
const msgs2 = makeInboxMessages(3, {
|
|
513
|
+
initialL2BlockNumber: 20,
|
|
514
|
+
initialHash: msgs1.at(-1).rollingHash
|
|
515
|
+
});
|
|
516
|
+
await store.addL1ToL2Messages(msgs1);
|
|
517
|
+
await store.addL1ToL2Messages(msgs2);
|
|
518
|
+
await checkMessages([
|
|
519
|
+
...msgs1,
|
|
520
|
+
...msgs2
|
|
521
|
+
]);
|
|
522
|
+
expect(await store.getL1ToL2Messages(1)).toEqual([
|
|
523
|
+
msgs1[0].leaf
|
|
524
|
+
]);
|
|
525
|
+
expect(await store.getL1ToL2Messages(4)).toEqual([]);
|
|
526
|
+
expect(await store.getL1ToL2Messages(20)).toEqual([
|
|
527
|
+
msgs2[0].leaf
|
|
528
|
+
]);
|
|
529
|
+
expect(await store.getL1ToL2Messages(24)).toEqual([]);
|
|
530
|
+
});
|
|
531
|
+
it('stores and returns messages with block numbers larger than a byte', async ()=>{
|
|
532
|
+
const msgs = makeInboxMessages(5, {
|
|
533
|
+
initialL2BlockNumber: 1000
|
|
534
|
+
});
|
|
535
|
+
await store.addL1ToL2Messages(msgs);
|
|
536
|
+
await checkMessages(msgs);
|
|
537
|
+
expect(await store.getL1ToL2Messages(1002)).toEqual([
|
|
538
|
+
msgs[2]
|
|
539
|
+
].map((m)=>m.leaf));
|
|
540
|
+
});
|
|
541
|
+
it('stores and returns multiple messages per block', async ()=>{
|
|
542
|
+
const msgs = makeInboxMessagesWithFullBlocks(4);
|
|
543
|
+
await store.addL1ToL2Messages(msgs);
|
|
544
|
+
await checkMessages(msgs);
|
|
545
|
+
const blockMessages = await store.getL1ToL2Messages(initialL2BlockNumber + 1);
|
|
546
|
+
expect(blockMessages).toHaveLength(NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP);
|
|
547
|
+
expect(blockMessages).toEqual(msgs.slice(NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP, NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP * 2).map((m)=>m.leaf));
|
|
548
|
+
});
|
|
549
|
+
it('stores messages in multiple operations', async ()=>{
|
|
550
|
+
const msgs = makeInboxMessages(20, {
|
|
551
|
+
initialL2BlockNumber
|
|
552
|
+
});
|
|
553
|
+
await store.addL1ToL2Messages(msgs.slice(0, 10));
|
|
554
|
+
await store.addL1ToL2Messages(msgs.slice(10, 20));
|
|
555
|
+
expect(await store.getL1ToL2Messages(initialL2BlockNumber + 2)).toEqual([
|
|
556
|
+
msgs[2]
|
|
557
|
+
].map((m)=>m.leaf));
|
|
558
|
+
expect(await store.getL1ToL2Messages(initialL2BlockNumber + 12)).toEqual([
|
|
559
|
+
msgs[12]
|
|
560
|
+
].map((m)=>m.leaf));
|
|
561
|
+
await checkMessages(msgs);
|
|
562
|
+
});
|
|
563
|
+
it('iterates over messages from start index', async ()=>{
|
|
564
|
+
const msgs = makeInboxMessages(10, {
|
|
565
|
+
initialL2BlockNumber
|
|
566
|
+
});
|
|
567
|
+
await store.addL1ToL2Messages(msgs);
|
|
568
|
+
const iterated = await toArray(store.iterateL1ToL2Messages({
|
|
569
|
+
start: msgs[3].index
|
|
570
|
+
}));
|
|
571
|
+
expect(iterated).toEqual(msgs.slice(3));
|
|
572
|
+
});
|
|
573
|
+
it('iterates over messages in reverse', async ()=>{
|
|
574
|
+
const msgs = makeInboxMessages(10, {
|
|
575
|
+
initialL2BlockNumber
|
|
576
|
+
});
|
|
577
|
+
await store.addL1ToL2Messages(msgs);
|
|
578
|
+
const iterated = await toArray(store.iterateL1ToL2Messages({
|
|
579
|
+
reverse: true,
|
|
580
|
+
end: msgs[3].index
|
|
581
|
+
}));
|
|
582
|
+
expect(iterated).toEqual(msgs.slice(0, 4).reverse());
|
|
583
|
+
});
|
|
584
|
+
it('throws if messages are added out of order', async ()=>{
|
|
585
|
+
const msgs = makeInboxMessages(5, {
|
|
586
|
+
overrideFn: (msg, i)=>({
|
|
587
|
+
...msg,
|
|
588
|
+
index: BigInt(10 - i)
|
|
589
|
+
})
|
|
590
|
+
});
|
|
591
|
+
await expect(store.addL1ToL2Messages(msgs)).rejects.toThrow(MessageStoreError);
|
|
592
|
+
});
|
|
593
|
+
it('throws if block number for the first message is out of order', async ()=>{
|
|
594
|
+
const msgs = makeInboxMessages(4, {
|
|
595
|
+
initialL2BlockNumber
|
|
596
|
+
});
|
|
597
|
+
msgs[2].l2BlockNumber = initialL2BlockNumber - 1;
|
|
598
|
+
await store.addL1ToL2Messages(msgs.slice(0, 2));
|
|
599
|
+
await expect(store.addL1ToL2Messages(msgs.slice(2, 4))).rejects.toThrow(MessageStoreError);
|
|
600
|
+
});
|
|
601
|
+
it('throws if rolling hash is not correct', async ()=>{
|
|
602
|
+
const msgs = makeInboxMessages(5);
|
|
603
|
+
msgs[1].rollingHash = Buffer16.random();
|
|
604
|
+
await expect(store.addL1ToL2Messages(msgs)).rejects.toThrow(MessageStoreError);
|
|
605
|
+
});
|
|
606
|
+
it('throws if rolling hash for first message is not correct', async ()=>{
|
|
607
|
+
const msgs = makeInboxMessages(4);
|
|
608
|
+
msgs[2].rollingHash = Buffer16.random();
|
|
609
|
+
await store.addL1ToL2Messages(msgs.slice(0, 2));
|
|
610
|
+
await expect(store.addL1ToL2Messages(msgs.slice(2, 4))).rejects.toThrow(MessageStoreError);
|
|
611
|
+
});
|
|
612
|
+
it('throws if index is not in the correct range', async ()=>{
|
|
613
|
+
const msgs = makeInboxMessages(5, {
|
|
614
|
+
initialL2BlockNumber
|
|
615
|
+
});
|
|
616
|
+
msgs.at(-1).index += 100n;
|
|
617
|
+
await expect(store.addL1ToL2Messages(msgs)).rejects.toThrow(MessageStoreError);
|
|
618
|
+
});
|
|
619
|
+
it('throws if first index in block has gaps', async ()=>{
|
|
620
|
+
const msgs = makeInboxMessages(4, {
|
|
621
|
+
initialL2BlockNumber
|
|
622
|
+
});
|
|
623
|
+
msgs[2].index++;
|
|
624
|
+
await expect(store.addL1ToL2Messages(msgs)).rejects.toThrow(MessageStoreError);
|
|
625
|
+
});
|
|
626
|
+
it('throws if index does not follow previous one', async ()=>{
|
|
627
|
+
const msgs = makeInboxMessages(2, {
|
|
628
|
+
initialL2BlockNumber,
|
|
629
|
+
overrideFn: (msg, i)=>({
|
|
630
|
+
...msg,
|
|
631
|
+
l2BlockNumber: 2,
|
|
632
|
+
index: BigInt(i + NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP * 2)
|
|
633
|
+
})
|
|
634
|
+
});
|
|
635
|
+
msgs[1].index++;
|
|
636
|
+
await expect(store.addL1ToL2Messages(msgs)).rejects.toThrow(MessageStoreError);
|
|
637
|
+
});
|
|
638
|
+
it('removes messages up to the given block number', async ()=>{
|
|
639
|
+
const msgs = makeInboxMessagesWithFullBlocks(4, {
|
|
640
|
+
initialL2BlockNumber: 1
|
|
641
|
+
});
|
|
642
|
+
await store.addL1ToL2Messages(msgs);
|
|
643
|
+
await checkMessages(msgs);
|
|
644
|
+
expect(await store.getL1ToL2Messages(1)).toHaveLength(NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP);
|
|
645
|
+
expect(await store.getL1ToL2Messages(2)).toHaveLength(NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP);
|
|
646
|
+
expect(await store.getL1ToL2Messages(3)).toHaveLength(NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP);
|
|
647
|
+
expect(await store.getL1ToL2Messages(4)).toHaveLength(NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP);
|
|
648
|
+
await store.rollbackL1ToL2MessagesToL2Block(2);
|
|
649
|
+
expect(await store.getL1ToL2Messages(1)).toHaveLength(NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP);
|
|
650
|
+
expect(await store.getL1ToL2Messages(2)).toHaveLength(NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP);
|
|
651
|
+
expect(await store.getL1ToL2Messages(3)).toHaveLength(0);
|
|
652
|
+
expect(await store.getL1ToL2Messages(4)).toHaveLength(0);
|
|
653
|
+
await checkMessages(msgs.slice(0, NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP * 2));
|
|
654
|
+
});
|
|
655
|
+
it('removes messages starting with the given index', async ()=>{
|
|
656
|
+
const msgs = makeInboxMessagesWithFullBlocks(4, {
|
|
657
|
+
initialL2BlockNumber: 1
|
|
658
|
+
});
|
|
659
|
+
await store.addL1ToL2Messages(msgs);
|
|
660
|
+
await store.removeL1ToL2Messages(msgs[13].index);
|
|
661
|
+
await checkMessages(msgs.slice(0, 13));
|
|
262
662
|
});
|
|
263
663
|
});
|
|
264
664
|
describe('contractInstances', ()=>{
|
|
265
665
|
let contractInstance;
|
|
266
666
|
const blockNum = 10;
|
|
667
|
+
const timestamp = 3600n;
|
|
267
668
|
beforeEach(async ()=>{
|
|
268
669
|
const classId = Fr.random();
|
|
269
670
|
const randomInstance = await SerializableContractInstance.random({
|
|
@@ -279,16 +680,103 @@ import { TxEffect, TxHash } from '@aztec/stdlib/tx';
|
|
|
279
680
|
], blockNum);
|
|
280
681
|
});
|
|
281
682
|
it('returns previously stored contract instances', async ()=>{
|
|
282
|
-
await expect(store.getContractInstance(contractInstance.address)).resolves.toMatchObject(contractInstance);
|
|
683
|
+
await expect(store.getContractInstance(contractInstance.address, timestamp)).resolves.toMatchObject(contractInstance);
|
|
283
684
|
});
|
|
284
685
|
it('returns undefined if contract instance is not found', async ()=>{
|
|
285
|
-
await expect(store.getContractInstance(await AztecAddress.random())).resolves.toBeUndefined();
|
|
686
|
+
await expect(store.getContractInstance(await AztecAddress.random(), timestamp)).resolves.toBeUndefined();
|
|
286
687
|
});
|
|
287
688
|
it('returns undefined if previously stored contract instances was deleted', async ()=>{
|
|
288
689
|
await store.deleteContractInstances([
|
|
289
690
|
contractInstance
|
|
290
691
|
], blockNum);
|
|
291
|
-
await expect(store.getContractInstance(contractInstance.address)).resolves.toBeUndefined();
|
|
692
|
+
await expect(store.getContractInstance(contractInstance.address, timestamp)).resolves.toBeUndefined();
|
|
693
|
+
});
|
|
694
|
+
});
|
|
695
|
+
describe('contractInstanceUpdates', ()=>{
|
|
696
|
+
let contractInstance;
|
|
697
|
+
let classId;
|
|
698
|
+
let nextClassId;
|
|
699
|
+
const timestampOfChange = 3600n;
|
|
700
|
+
beforeEach(async ()=>{
|
|
701
|
+
classId = Fr.random();
|
|
702
|
+
nextClassId = Fr.random();
|
|
703
|
+
const randomInstance = await SerializableContractInstance.random({
|
|
704
|
+
currentContractClassId: classId,
|
|
705
|
+
originalContractClassId: classId
|
|
706
|
+
});
|
|
707
|
+
contractInstance = {
|
|
708
|
+
...randomInstance,
|
|
709
|
+
address: await AztecAddress.random()
|
|
710
|
+
};
|
|
711
|
+
await store.addContractInstances([
|
|
712
|
+
contractInstance
|
|
713
|
+
], 1);
|
|
714
|
+
await store.addContractInstanceUpdates([
|
|
715
|
+
{
|
|
716
|
+
prevContractClassId: classId,
|
|
717
|
+
newContractClassId: nextClassId,
|
|
718
|
+
timestampOfChange,
|
|
719
|
+
address: contractInstance.address
|
|
720
|
+
}
|
|
721
|
+
], timestampOfChange - 1n);
|
|
722
|
+
});
|
|
723
|
+
it('gets the correct current class id for a contract not updated yet', async ()=>{
|
|
724
|
+
const fetchedInstance = await store.getContractInstance(contractInstance.address, timestampOfChange - 1n);
|
|
725
|
+
expect(fetchedInstance?.originalContractClassId).toEqual(classId);
|
|
726
|
+
expect(fetchedInstance?.currentContractClassId).toEqual(classId);
|
|
727
|
+
});
|
|
728
|
+
it('gets the correct current class id for a contract that has just been updated', async ()=>{
|
|
729
|
+
const fetchedInstance = await store.getContractInstance(contractInstance.address, timestampOfChange);
|
|
730
|
+
expect(fetchedInstance?.originalContractClassId).toEqual(classId);
|
|
731
|
+
expect(fetchedInstance?.currentContractClassId).toEqual(nextClassId);
|
|
732
|
+
});
|
|
733
|
+
it('gets the correct current class id for a contract that was updated in the past', async ()=>{
|
|
734
|
+
const fetchedInstance = await store.getContractInstance(contractInstance.address, timestampOfChange + 1n);
|
|
735
|
+
expect(fetchedInstance?.originalContractClassId).toEqual(classId);
|
|
736
|
+
expect(fetchedInstance?.currentContractClassId).toEqual(nextClassId);
|
|
737
|
+
});
|
|
738
|
+
it('ignores updates for the wrong contract', async ()=>{
|
|
739
|
+
const otherClassId = Fr.random();
|
|
740
|
+
const randomInstance = await SerializableContractInstance.random({
|
|
741
|
+
currentContractClassId: otherClassId,
|
|
742
|
+
originalContractClassId: otherClassId
|
|
743
|
+
});
|
|
744
|
+
const otherContractInstance = {
|
|
745
|
+
...randomInstance,
|
|
746
|
+
address: await AztecAddress.random()
|
|
747
|
+
};
|
|
748
|
+
await store.addContractInstances([
|
|
749
|
+
otherContractInstance
|
|
750
|
+
], 1);
|
|
751
|
+
const fetchedInstance = await store.getContractInstance(otherContractInstance.address, timestampOfChange + 1n);
|
|
752
|
+
expect(fetchedInstance?.originalContractClassId).toEqual(otherClassId);
|
|
753
|
+
expect(fetchedInstance?.currentContractClassId).toEqual(otherClassId);
|
|
754
|
+
});
|
|
755
|
+
it('bounds its search to the right contract if more than than one update exists', async ()=>{
|
|
756
|
+
const otherClassId = Fr.random();
|
|
757
|
+
const otherNextClassId = Fr.random();
|
|
758
|
+
const randomInstance = await SerializableContractInstance.random({
|
|
759
|
+
currentContractClassId: otherClassId,
|
|
760
|
+
originalContractClassId: otherNextClassId
|
|
761
|
+
});
|
|
762
|
+
const otherContractInstance = {
|
|
763
|
+
...randomInstance,
|
|
764
|
+
address: await AztecAddress.random()
|
|
765
|
+
};
|
|
766
|
+
await store.addContractInstances([
|
|
767
|
+
otherContractInstance
|
|
768
|
+
], 1);
|
|
769
|
+
await store.addContractInstanceUpdates([
|
|
770
|
+
{
|
|
771
|
+
prevContractClassId: otherClassId,
|
|
772
|
+
newContractClassId: otherNextClassId,
|
|
773
|
+
timestampOfChange,
|
|
774
|
+
address: otherContractInstance.address
|
|
775
|
+
}
|
|
776
|
+
], timestampOfChange - 1n);
|
|
777
|
+
const fetchedInstance = await store.getContractInstance(contractInstance.address, timestampOfChange + 1n);
|
|
778
|
+
expect(fetchedInstance?.originalContractClassId).toEqual(classId);
|
|
779
|
+
expect(fetchedInstance?.currentContractClassId).toEqual(nextClassId);
|
|
292
780
|
});
|
|
293
781
|
});
|
|
294
782
|
describe('contractClasses', ()=>{
|
|
@@ -338,18 +826,18 @@ import { TxEffect, TxHash } from '@aztec/stdlib/tx';
|
|
|
338
826
|
const stored = await store.getContractClass(contractClass.id);
|
|
339
827
|
expect(stored?.privateFunctions).toEqual(fns);
|
|
340
828
|
});
|
|
341
|
-
it('adds new
|
|
342
|
-
const fns = times(3,
|
|
829
|
+
it('adds new utility functions', async ()=>{
|
|
830
|
+
const fns = times(3, makeUtilityFunctionWithMembershipProof);
|
|
343
831
|
await store.addFunctions(contractClass.id, [], fns);
|
|
344
832
|
const stored = await store.getContractClass(contractClass.id);
|
|
345
|
-
expect(stored?.
|
|
833
|
+
expect(stored?.utilityFunctions).toEqual(fns);
|
|
346
834
|
});
|
|
347
|
-
it('does not duplicate
|
|
348
|
-
const fns = times(3,
|
|
835
|
+
it('does not duplicate utility functions', async ()=>{
|
|
836
|
+
const fns = times(3, makeUtilityFunctionWithMembershipProof);
|
|
349
837
|
await store.addFunctions(contractClass.id, [], fns.slice(0, 1));
|
|
350
838
|
await store.addFunctions(contractClass.id, [], fns);
|
|
351
839
|
const stored = await store.getContractClass(contractClass.id);
|
|
352
|
-
expect(stored?.
|
|
840
|
+
expect(stored?.utilityFunctions).toEqual(fns);
|
|
353
841
|
});
|
|
354
842
|
});
|
|
355
843
|
describe('getLogsByTags', ()=>{
|
|
@@ -358,27 +846,17 @@ import { TxEffect, TxHash } from '@aztec/stdlib/tx';
|
|
|
358
846
|
const numPrivateLogsPerTx = 3;
|
|
359
847
|
const numPublicLogsPerTx = 2;
|
|
360
848
|
let blocks;
|
|
361
|
-
const makeTag = (blockNumber, txIndex, logIndex, isPublic = false)=>
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
...times(PRIVATE_LOG_SIZE_IN_FIELDS - 1, (i)=>new Fr(tag.toNumber() + i))
|
|
373
|
-
]);
|
|
374
|
-
// The tag lives in field 1, not 0, of a public log
|
|
375
|
-
// See extractTaggedLogsFromPublic and noir-projects/aztec-nr/aztec/src/macros/notes/mod.nr -> emit_log
|
|
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
|
-
]);
|
|
849
|
+
const makeTag = (blockNumber, txIndex, logIndex, isPublic = false)=>blockNumber === 1 && txIndex === 0 && logIndex === 0 ? Fr.ZERO // Shared tag
|
|
850
|
+
: new Fr((blockNumber * 100 + txIndex * 10 + logIndex) * (isPublic ? 123 : 1));
|
|
851
|
+
const makePrivateLog = (tag)=>PrivateLog.from({
|
|
852
|
+
fields: makeTuple(PRIVATE_LOG_SIZE_IN_FIELDS, (i)=>!i ? tag : new Fr(tag.toNumber() + i)),
|
|
853
|
+
emittedLength: PRIVATE_LOG_SIZE_IN_FIELDS
|
|
854
|
+
});
|
|
855
|
+
const makePublicLog = (tag)=>PublicLog.from({
|
|
856
|
+
contractAddress: AztecAddress.fromNumber(1),
|
|
857
|
+
// Arbitrary length
|
|
858
|
+
fields: new Array(10).fill(null).map((_, i)=>!i ? tag : new Fr(tag.toNumber() + i))
|
|
859
|
+
});
|
|
382
860
|
const mockPrivateLogs = (blockNumber, txIndex)=>{
|
|
383
861
|
return times(numPrivateLogsPerTx, (logIndex)=>{
|
|
384
862
|
const tag = makeTag(blockNumber, txIndex, logIndex);
|
|
@@ -393,66 +871,67 @@ import { TxEffect, TxHash } from '@aztec/stdlib/tx';
|
|
|
393
871
|
};
|
|
394
872
|
const mockBlockWithLogs = async (blockNumber)=>{
|
|
395
873
|
const block = await L2Block.random(blockNumber);
|
|
396
|
-
block.header.globalVariables.blockNumber =
|
|
874
|
+
block.header.globalVariables.blockNumber = blockNumber;
|
|
397
875
|
block.body.txEffects = await timesParallel(numTxsPerBlock, async (txIndex)=>{
|
|
398
876
|
const txEffect = await TxEffect.random();
|
|
399
877
|
txEffect.privateLogs = mockPrivateLogs(blockNumber, txIndex);
|
|
400
878
|
txEffect.publicLogs = mockPublicLogs(blockNumber, txIndex);
|
|
401
879
|
return txEffect;
|
|
402
880
|
});
|
|
403
|
-
return {
|
|
404
|
-
|
|
881
|
+
return PublishedL2Block.fromFields({
|
|
882
|
+
block: block,
|
|
883
|
+
attestations: times(3, CommitteeAttestation.random),
|
|
405
884
|
l1: {
|
|
406
885
|
blockNumber: BigInt(blockNumber),
|
|
407
|
-
blockHash:
|
|
886
|
+
blockHash: makeBlockHash(blockNumber),
|
|
408
887
|
timestamp: BigInt(blockNumber)
|
|
409
888
|
}
|
|
410
|
-
};
|
|
889
|
+
});
|
|
411
890
|
};
|
|
412
891
|
beforeEach(async ()=>{
|
|
413
|
-
blocks = await timesParallel(numBlocks, (index)=>mockBlockWithLogs(index));
|
|
892
|
+
blocks = await timesParallel(numBlocks, (index)=>mockBlockWithLogs(index + 1));
|
|
414
893
|
await store.addBlocks(blocks);
|
|
415
|
-
await store.addLogs(blocks.map((b)=>b.
|
|
894
|
+
await store.addLogs(blocks.map((b)=>b.block));
|
|
416
895
|
});
|
|
417
896
|
it('is possible to batch request private logs via tags', async ()=>{
|
|
418
897
|
const tags = [
|
|
419
|
-
makeTag(
|
|
420
|
-
makeTag(
|
|
898
|
+
makeTag(2, 1, 2),
|
|
899
|
+
makeTag(1, 2, 0)
|
|
421
900
|
];
|
|
422
901
|
const logsByTags = await store.getLogsByTags(tags);
|
|
423
902
|
expect(logsByTags).toEqual([
|
|
424
903
|
[
|
|
425
904
|
expect.objectContaining({
|
|
426
|
-
blockNumber:
|
|
427
|
-
|
|
905
|
+
blockNumber: 2,
|
|
906
|
+
log: makePrivateLog(tags[0]),
|
|
428
907
|
isFromPublic: false
|
|
429
908
|
})
|
|
430
909
|
],
|
|
431
910
|
[
|
|
432
911
|
expect.objectContaining({
|
|
433
|
-
blockNumber:
|
|
434
|
-
|
|
912
|
+
blockNumber: 1,
|
|
913
|
+
log: makePrivateLog(tags[1]),
|
|
435
914
|
isFromPublic: false
|
|
436
915
|
})
|
|
437
916
|
]
|
|
438
917
|
]);
|
|
439
918
|
});
|
|
440
919
|
it('is possible to batch request all logs (private and public) via tags', async ()=>{
|
|
441
|
-
// Tag(
|
|
920
|
+
// Tag(1, 0, 0) is shared with the first private log and the first public log.
|
|
442
921
|
const tags = [
|
|
443
|
-
makeTag(
|
|
922
|
+
makeTag(1, 0, 0)
|
|
444
923
|
];
|
|
445
924
|
const logsByTags = await store.getLogsByTags(tags);
|
|
446
925
|
expect(logsByTags).toEqual([
|
|
447
926
|
[
|
|
448
927
|
expect.objectContaining({
|
|
449
|
-
blockNumber:
|
|
450
|
-
|
|
928
|
+
blockNumber: 1,
|
|
929
|
+
log: makePrivateLog(tags[0]),
|
|
451
930
|
isFromPublic: false
|
|
452
931
|
}),
|
|
453
932
|
expect.objectContaining({
|
|
454
|
-
blockNumber:
|
|
455
|
-
|
|
933
|
+
blockNumber: 1,
|
|
934
|
+
log: makePublicLog(tags[0]),
|
|
456
935
|
isFromPublic: true
|
|
457
936
|
})
|
|
458
937
|
]
|
|
@@ -465,26 +944,26 @@ import { TxEffect, TxHash } from '@aztec/stdlib/tx';
|
|
|
465
944
|
// Create a block containing logs that have the same tag as the blocks before.
|
|
466
945
|
const newBlockNumber = numBlocks;
|
|
467
946
|
const newBlock = await mockBlockWithLogs(newBlockNumber);
|
|
468
|
-
const newLog = newBlock.
|
|
947
|
+
const newLog = newBlock.block.body.txEffects[1].privateLogs[1];
|
|
469
948
|
newLog.fields[0] = tags[0];
|
|
470
|
-
newBlock.
|
|
949
|
+
newBlock.block.body.txEffects[1].privateLogs[1] = newLog;
|
|
471
950
|
await store.addBlocks([
|
|
472
951
|
newBlock
|
|
473
952
|
]);
|
|
474
953
|
await store.addLogs([
|
|
475
|
-
newBlock.
|
|
954
|
+
newBlock.block
|
|
476
955
|
]);
|
|
477
956
|
const logsByTags = await store.getLogsByTags(tags);
|
|
478
957
|
expect(logsByTags).toEqual([
|
|
479
958
|
[
|
|
480
959
|
expect.objectContaining({
|
|
481
960
|
blockNumber: 1,
|
|
482
|
-
|
|
961
|
+
log: makePrivateLog(tags[0]),
|
|
483
962
|
isFromPublic: false
|
|
484
963
|
}),
|
|
485
964
|
expect.objectContaining({
|
|
486
965
|
blockNumber: newBlockNumber,
|
|
487
|
-
|
|
966
|
+
log: newLog,
|
|
488
967
|
isFromPublic: false
|
|
489
968
|
})
|
|
490
969
|
]
|
|
@@ -501,46 +980,12 @@ import { TxEffect, TxHash } from '@aztec/stdlib/tx';
|
|
|
501
980
|
[
|
|
502
981
|
expect.objectContaining({
|
|
503
982
|
blockNumber: 1,
|
|
504
|
-
|
|
983
|
+
log: makePrivateLog(tags[1]),
|
|
505
984
|
isFromPublic: false
|
|
506
985
|
})
|
|
507
986
|
]
|
|
508
987
|
]);
|
|
509
988
|
});
|
|
510
|
-
it('is not possible to add public logs by tag if they are invalid', async ()=>{
|
|
511
|
-
const tag = makeTag(99, 88, 77);
|
|
512
|
-
const invalidLogs = [
|
|
513
|
-
PublicLog.fromFields([
|
|
514
|
-
AztecAddress.fromNumber(1).toField(),
|
|
515
|
-
makeLengthsField(2, 3),
|
|
516
|
-
tag,
|
|
517
|
-
...times(PUBLIC_LOG_DATA_SIZE_IN_FIELDS - 1, (i)=>new Fr(tag.toNumber() + i))
|
|
518
|
-
]),
|
|
519
|
-
PublicLog.fromFields([
|
|
520
|
-
AztecAddress.fromNumber(1).toField(),
|
|
521
|
-
makeLengthsField(2, PUBLIC_LOG_DATA_SIZE_IN_FIELDS),
|
|
522
|
-
tag,
|
|
523
|
-
...times(PUBLIC_LOG_DATA_SIZE_IN_FIELDS - 1, (i)=>new Fr(tag.toNumber() + i))
|
|
524
|
-
])
|
|
525
|
-
];
|
|
526
|
-
// Create a block containing these invalid logs
|
|
527
|
-
const newBlockNumber = numBlocks;
|
|
528
|
-
const newBlock = await mockBlockWithLogs(newBlockNumber);
|
|
529
|
-
newBlock.data.body.txEffects[0].publicLogs = invalidLogs;
|
|
530
|
-
await store.addBlocks([
|
|
531
|
-
newBlock
|
|
532
|
-
]);
|
|
533
|
-
await store.addLogs([
|
|
534
|
-
newBlock.data
|
|
535
|
-
]);
|
|
536
|
-
const logsByTags = await store.getLogsByTags([
|
|
537
|
-
tag
|
|
538
|
-
]);
|
|
539
|
-
// Neither of the logs should have been added:
|
|
540
|
-
expect(logsByTags).toEqual([
|
|
541
|
-
[]
|
|
542
|
-
]);
|
|
543
|
-
});
|
|
544
989
|
});
|
|
545
990
|
describe('getPublicLogs', ()=>{
|
|
546
991
|
const txsPerBlock = 4;
|
|
@@ -549,25 +994,26 @@ import { TxEffect, TxHash } from '@aztec/stdlib/tx';
|
|
|
549
994
|
const numBlocks = 10;
|
|
550
995
|
let blocks;
|
|
551
996
|
beforeEach(async ()=>{
|
|
552
|
-
blocks = await timesParallel(numBlocks, async (index)=>({
|
|
553
|
-
|
|
997
|
+
blocks = await timesParallel(numBlocks, async (index)=>PublishedL2Block.fromFields({
|
|
998
|
+
block: await L2Block.random(index + 1, txsPerBlock, numPublicFunctionCalls, numPublicLogs),
|
|
554
999
|
l1: {
|
|
555
1000
|
blockNumber: BigInt(index),
|
|
556
|
-
blockHash:
|
|
1001
|
+
blockHash: makeBlockHash(index),
|
|
557
1002
|
timestamp: BigInt(index)
|
|
558
|
-
}
|
|
1003
|
+
},
|
|
1004
|
+
attestations: times(3, CommitteeAttestation.random)
|
|
559
1005
|
}));
|
|
560
1006
|
await store.addBlocks(blocks);
|
|
561
|
-
await store.addLogs(blocks.map((b)=>b.
|
|
1007
|
+
await store.addLogs(blocks.map((b)=>b.block));
|
|
562
1008
|
});
|
|
563
1009
|
it('no logs returned if deleted ("txHash" filter param is respected variant)', async ()=>{
|
|
564
1010
|
// get random tx
|
|
565
1011
|
const targetBlockIndex = randomInt(numBlocks);
|
|
566
1012
|
const targetTxIndex = randomInt(txsPerBlock);
|
|
567
|
-
const targetTxHash = blocks[targetBlockIndex].
|
|
1013
|
+
const targetTxHash = blocks[targetBlockIndex].block.body.txEffects[targetTxIndex].txHash;
|
|
568
1014
|
await Promise.all([
|
|
569
1015
|
store.unwindBlocks(blocks.length, blocks.length),
|
|
570
|
-
store.deleteLogs(blocks.map((b)=>b.
|
|
1016
|
+
store.deleteLogs(blocks.map((b)=>b.block))
|
|
571
1017
|
]);
|
|
572
1018
|
const response = await store.getPublicLogs({
|
|
573
1019
|
txHash: targetTxHash
|
|
@@ -580,7 +1026,7 @@ import { TxEffect, TxHash } from '@aztec/stdlib/tx';
|
|
|
580
1026
|
// get random tx
|
|
581
1027
|
const targetBlockIndex = randomInt(numBlocks);
|
|
582
1028
|
const targetTxIndex = randomInt(txsPerBlock);
|
|
583
|
-
const targetTxHash = blocks[targetBlockIndex].
|
|
1029
|
+
const targetTxHash = blocks[targetBlockIndex].block.body.txEffects[targetTxIndex].txHash;
|
|
584
1030
|
const response = await store.getPublicLogs({
|
|
585
1031
|
txHash: targetTxHash
|
|
586
1032
|
});
|
|
@@ -617,7 +1063,7 @@ import { TxEffect, TxHash } from '@aztec/stdlib/tx';
|
|
|
617
1063
|
const targetBlockIndex = randomInt(numBlocks);
|
|
618
1064
|
const targetTxIndex = randomInt(txsPerBlock);
|
|
619
1065
|
const targetLogIndex = randomInt(numPublicLogs * numPublicFunctionCalls);
|
|
620
|
-
const targetContractAddress = blocks[targetBlockIndex].
|
|
1066
|
+
const targetContractAddress = blocks[targetBlockIndex].block.body.txEffects[targetTxIndex].publicLogs[targetLogIndex].contractAddress;
|
|
621
1067
|
const response = await store.getPublicLogs({
|
|
622
1068
|
contractAddress: targetContractAddress
|
|
623
1069
|
});
|
|
@@ -740,54 +1186,102 @@ import { TxEffect, TxHash } from '@aztec/stdlib/tx';
|
|
|
740
1186
|
}
|
|
741
1187
|
});
|
|
742
1188
|
});
|
|
743
|
-
describe('
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
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));
|
|
751
|
-
});
|
|
1189
|
+
describe('pendingChainValidationStatus', ()=>{
|
|
1190
|
+
it('should return undefined when no status is set', async ()=>{
|
|
1191
|
+
const status = await store.getPendingChainValidationStatus();
|
|
1192
|
+
expect(status).toBeUndefined();
|
|
752
1193
|
});
|
|
753
|
-
it('
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
const
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
const
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
1194
|
+
it('should store and retrieve a valid validation status', async ()=>{
|
|
1195
|
+
const validStatus = {
|
|
1196
|
+
valid: true
|
|
1197
|
+
};
|
|
1198
|
+
await store.setPendingChainValidationStatus(validStatus);
|
|
1199
|
+
const retrievedStatus = await store.getPendingChainValidationStatus();
|
|
1200
|
+
expect(retrievedStatus).toEqual(validStatus);
|
|
1201
|
+
});
|
|
1202
|
+
it('should store and retrieve an invalid validation status with insufficient attestations', async ()=>{
|
|
1203
|
+
const invalidStatus = {
|
|
1204
|
+
valid: false,
|
|
1205
|
+
block: randomBlockInfo(1),
|
|
1206
|
+
committee: [
|
|
1207
|
+
EthAddress.random(),
|
|
1208
|
+
EthAddress.random()
|
|
1209
|
+
],
|
|
1210
|
+
epoch: 123n,
|
|
1211
|
+
seed: 456n,
|
|
1212
|
+
attestors: [
|
|
1213
|
+
EthAddress.random()
|
|
1214
|
+
],
|
|
1215
|
+
attestations: [
|
|
1216
|
+
CommitteeAttestation.random()
|
|
1217
|
+
],
|
|
1218
|
+
reason: 'insufficient-attestations'
|
|
1219
|
+
};
|
|
1220
|
+
await store.setPendingChainValidationStatus(invalidStatus);
|
|
1221
|
+
const retrievedStatus = await store.getPendingChainValidationStatus();
|
|
1222
|
+
expect(retrievedStatus).toEqual(invalidStatus);
|
|
1223
|
+
});
|
|
1224
|
+
it('should store and retrieve an invalid validation status with invalid attestation', async ()=>{
|
|
1225
|
+
const invalidStatus = {
|
|
1226
|
+
valid: false,
|
|
1227
|
+
block: randomBlockInfo(2),
|
|
1228
|
+
committee: [
|
|
1229
|
+
EthAddress.random()
|
|
1230
|
+
],
|
|
1231
|
+
attestors: [
|
|
1232
|
+
EthAddress.random()
|
|
1233
|
+
],
|
|
1234
|
+
epoch: 789n,
|
|
1235
|
+
seed: 101n,
|
|
1236
|
+
attestations: [
|
|
1237
|
+
CommitteeAttestation.random()
|
|
1238
|
+
],
|
|
1239
|
+
reason: 'invalid-attestation',
|
|
1240
|
+
invalidIndex: 5
|
|
1241
|
+
};
|
|
1242
|
+
await store.setPendingChainValidationStatus(invalidStatus);
|
|
1243
|
+
const retrievedStatus = await store.getPendingChainValidationStatus();
|
|
1244
|
+
expect(retrievedStatus).toEqual(invalidStatus);
|
|
1245
|
+
});
|
|
1246
|
+
it('should overwrite existing status when setting a new one', async ()=>{
|
|
1247
|
+
const firstStatus = {
|
|
1248
|
+
valid: true
|
|
1249
|
+
};
|
|
1250
|
+
const secondStatus = {
|
|
1251
|
+
valid: false,
|
|
1252
|
+
block: randomBlockInfo(3),
|
|
1253
|
+
committee: [
|
|
1254
|
+
EthAddress.random()
|
|
1255
|
+
],
|
|
1256
|
+
epoch: 999n,
|
|
1257
|
+
seed: 888n,
|
|
1258
|
+
attestors: [
|
|
1259
|
+
EthAddress.random()
|
|
1260
|
+
],
|
|
1261
|
+
attestations: [
|
|
1262
|
+
CommitteeAttestation.random()
|
|
1263
|
+
],
|
|
1264
|
+
reason: 'insufficient-attestations'
|
|
1265
|
+
};
|
|
1266
|
+
await store.setPendingChainValidationStatus(firstStatus);
|
|
1267
|
+
await store.setPendingChainValidationStatus(secondStatus);
|
|
1268
|
+
const retrievedStatus = await store.getPendingChainValidationStatus();
|
|
1269
|
+
expect(retrievedStatus).toEqual(secondStatus);
|
|
1270
|
+
});
|
|
1271
|
+
it('should handle empty committee and attestations arrays', async ()=>{
|
|
1272
|
+
const statusWithEmptyArrays = {
|
|
1273
|
+
valid: false,
|
|
1274
|
+
block: randomBlockInfo(4),
|
|
1275
|
+
committee: [],
|
|
1276
|
+
epoch: 0n,
|
|
1277
|
+
seed: 0n,
|
|
1278
|
+
attestors: [],
|
|
1279
|
+
attestations: [],
|
|
1280
|
+
reason: 'insufficient-attestations'
|
|
1281
|
+
};
|
|
1282
|
+
await store.setPendingChainValidationStatus(statusWithEmptyArrays);
|
|
1283
|
+
const retrievedStatus = await store.getPendingChainValidationStatus();
|
|
1284
|
+
expect(retrievedStatus).toEqual(statusWithEmptyArrays);
|
|
791
1285
|
});
|
|
792
1286
|
});
|
|
793
1287
|
});
|