@aztec/p2p 0.0.1-commit.f2ce05ee → 0.0.1-commit.f8ca9b2f3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dest/client/factory.d.ts +3 -3
- package/dest/client/factory.d.ts.map +1 -1
- package/dest/client/factory.js +38 -7
- package/dest/client/interface.d.ts +26 -15
- package/dest/client/interface.d.ts.map +1 -1
- package/dest/client/p2p_client.d.ts +31 -35
- package/dest/client/p2p_client.d.ts.map +1 -1
- package/dest/client/p2p_client.js +97 -138
- package/dest/config.d.ts +10 -2
- package/dest/config.d.ts.map +1 -1
- package/dest/config.js +9 -0
- package/dest/index.d.ts +2 -1
- package/dest/index.d.ts.map +1 -1
- package/dest/index.js +1 -0
- package/dest/mem_pools/attestation_pool/attestation_pool.d.ts +18 -11
- package/dest/mem_pools/attestation_pool/attestation_pool.d.ts.map +1 -1
- package/dest/mem_pools/attestation_pool/attestation_pool.js +62 -37
- package/dest/mem_pools/attestation_pool/attestation_pool_test_suite.d.ts +1 -1
- package/dest/mem_pools/attestation_pool/attestation_pool_test_suite.d.ts.map +1 -1
- package/dest/mem_pools/attestation_pool/attestation_pool_test_suite.js +53 -53
- package/dest/mem_pools/attestation_pool/index.d.ts +2 -2
- package/dest/mem_pools/attestation_pool/index.d.ts.map +1 -1
- package/dest/mem_pools/attestation_pool/index.js +1 -1
- package/dest/mem_pools/index.d.ts +2 -1
- package/dest/mem_pools/index.d.ts.map +1 -1
- package/dest/mem_pools/interface.d.ts +3 -3
- package/dest/mem_pools/interface.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool_v2/deleted_pool.d.ts +87 -0
- package/dest/mem_pools/tx_pool_v2/deleted_pool.d.ts.map +1 -0
- package/dest/mem_pools/tx_pool_v2/deleted_pool.js +180 -0
- package/dest/mem_pools/tx_pool_v2/index.d.ts +2 -1
- package/dest/mem_pools/tx_pool_v2/index.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool_v2/index.js +1 -0
- package/dest/mem_pools/tx_pool_v2/interfaces.d.ts +3 -3
- package/dest/mem_pools/tx_pool_v2/interfaces.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool_v2/tx_metadata.d.ts +25 -3
- package/dest/mem_pools/tx_pool_v2/tx_metadata.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool_v2/tx_metadata.js +36 -4
- package/dest/mem_pools/tx_pool_v2/tx_pool_v2_impl.d.ts +1 -1
- package/dest/mem_pools/tx_pool_v2/tx_pool_v2_impl.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool_v2/tx_pool_v2_impl.js +77 -74
- package/dest/msg_validators/tx_validator/aggregate_tx_validator.d.ts +3 -3
- package/dest/msg_validators/tx_validator/aggregate_tx_validator.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/block_header_validator.d.ts +16 -3
- package/dest/msg_validators/tx_validator/block_header_validator.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/block_header_validator.js +1 -1
- package/dest/msg_validators/tx_validator/double_spend_validator.d.ts +13 -3
- package/dest/msg_validators/tx_validator/double_spend_validator.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/double_spend_validator.js +4 -4
- package/dest/msg_validators/tx_validator/timestamp_validator.d.ts +20 -4
- package/dest/msg_validators/tx_validator/timestamp_validator.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/timestamp_validator.js +2 -2
- package/dest/services/dummy_service.d.ts +6 -2
- package/dest/services/dummy_service.d.ts.map +1 -1
- package/dest/services/dummy_service.js +3 -0
- package/dest/services/encoding.d.ts +2 -2
- package/dest/services/encoding.d.ts.map +1 -1
- package/dest/services/encoding.js +2 -2
- package/dest/services/libp2p/libp2p_service.d.ts +11 -3
- package/dest/services/libp2p/libp2p_service.d.ts.map +1 -1
- package/dest/services/libp2p/libp2p_service.js +71 -35
- package/dest/services/reqresp/interface.d.ts +10 -1
- package/dest/services/reqresp/interface.d.ts.map +1 -1
- package/dest/services/reqresp/interface.js +15 -1
- package/dest/services/reqresp/protocols/block_txs/block_txs_handler.d.ts +3 -3
- package/dest/services/reqresp/protocols/block_txs/block_txs_handler.d.ts.map +1 -1
- package/dest/services/reqresp/protocols/block_txs/block_txs_reqresp.d.ts +7 -1
- package/dest/services/reqresp/protocols/block_txs/block_txs_reqresp.d.ts.map +1 -1
- package/dest/services/reqresp/protocols/block_txs/block_txs_reqresp.js +15 -0
- package/dest/services/reqresp/protocols/tx.d.ts +7 -1
- package/dest/services/reqresp/protocols/tx.d.ts.map +1 -1
- package/dest/services/reqresp/protocols/tx.js +20 -0
- package/dest/services/reqresp/reqresp.d.ts +1 -1
- package/dest/services/reqresp/reqresp.d.ts.map +1 -1
- package/dest/services/reqresp/reqresp.js +11 -4
- package/dest/services/service.d.ts +18 -1
- package/dest/services/service.d.ts.map +1 -1
- package/dest/services/tx_collection/config.d.ts +7 -1
- package/dest/services/tx_collection/config.d.ts.map +1 -1
- package/dest/services/tx_collection/config.js +16 -0
- package/dest/services/tx_collection/fast_tx_collection.d.ts +3 -1
- package/dest/services/tx_collection/fast_tx_collection.d.ts.map +1 -1
- package/dest/services/tx_collection/fast_tx_collection.js +17 -3
- package/dest/services/tx_collection/file_store_tx_collection.d.ts +44 -0
- package/dest/services/tx_collection/file_store_tx_collection.d.ts.map +1 -0
- package/dest/services/tx_collection/file_store_tx_collection.js +118 -0
- package/dest/services/tx_collection/file_store_tx_source.d.ts +27 -0
- package/dest/services/tx_collection/file_store_tx_source.d.ts.map +1 -0
- package/dest/services/tx_collection/file_store_tx_source.js +57 -0
- package/dest/services/tx_collection/index.d.ts +2 -1
- package/dest/services/tx_collection/index.d.ts.map +1 -1
- package/dest/services/tx_collection/index.js +1 -0
- package/dest/services/tx_collection/slow_tx_collection.d.ts +3 -1
- package/dest/services/tx_collection/slow_tx_collection.d.ts.map +1 -1
- package/dest/services/tx_collection/slow_tx_collection.js +48 -19
- package/dest/services/tx_collection/tx_collection.d.ts +17 -7
- package/dest/services/tx_collection/tx_collection.d.ts.map +1 -1
- package/dest/services/tx_collection/tx_collection.js +58 -2
- package/dest/services/tx_collection/tx_collection_sink.d.ts +15 -6
- package/dest/services/tx_collection/tx_collection_sink.d.ts.map +1 -1
- package/dest/services/tx_collection/tx_collection_sink.js +13 -7
- package/dest/services/tx_file_store/config.d.ts +1 -3
- package/dest/services/tx_file_store/config.d.ts.map +1 -1
- package/dest/services/tx_file_store/config.js +0 -4
- package/dest/services/tx_file_store/tx_file_store.d.ts +3 -3
- package/dest/services/tx_file_store/tx_file_store.d.ts.map +1 -1
- package/dest/services/tx_provider.d.ts +3 -3
- package/dest/services/tx_provider.d.ts.map +1 -1
- package/dest/services/tx_provider.js +5 -4
- package/dest/test-helpers/make-test-p2p-clients.d.ts +3 -3
- package/dest/test-helpers/make-test-p2p-clients.d.ts.map +1 -1
- package/dest/test-helpers/mock-pubsub.d.ts +27 -1
- package/dest/test-helpers/mock-pubsub.d.ts.map +1 -1
- package/dest/test-helpers/mock-pubsub.js +97 -2
- package/dest/test-helpers/testbench-utils.d.ts +30 -24
- package/dest/test-helpers/testbench-utils.d.ts.map +1 -1
- package/dest/test-helpers/testbench-utils.js +87 -35
- package/dest/testbench/p2p_client_testbench_worker.js +1 -1
- package/package.json +14 -14
- package/src/client/factory.ts +65 -8
- package/src/client/interface.ts +26 -13
- package/src/client/p2p_client.ts +123 -158
- package/src/config.ts +16 -0
- package/src/index.ts +1 -0
- package/src/mem_pools/attestation_pool/attestation_pool.ts +87 -44
- package/src/mem_pools/attestation_pool/attestation_pool_test_suite.ts +57 -53
- package/src/mem_pools/attestation_pool/index.ts +3 -3
- package/src/mem_pools/index.ts +3 -0
- package/src/mem_pools/interface.ts +2 -2
- package/src/mem_pools/tx_pool_v2/README.md +59 -9
- package/src/mem_pools/tx_pool_v2/deleted_pool.ts +234 -0
- package/src/mem_pools/tx_pool_v2/index.ts +1 -0
- package/src/mem_pools/tx_pool_v2/interfaces.ts +2 -2
- package/src/mem_pools/tx_pool_v2/tx_metadata.ts +51 -5
- package/src/mem_pools/tx_pool_v2/tx_pool_v2_impl.ts +90 -77
- package/src/msg_validators/tx_validator/aggregate_tx_validator.ts +2 -2
- package/src/msg_validators/tx_validator/block_header_validator.ts +15 -3
- package/src/msg_validators/tx_validator/double_spend_validator.ts +11 -6
- package/src/msg_validators/tx_validator/timestamp_validator.ts +19 -14
- package/src/services/dummy_service.ts +6 -0
- package/src/services/encoding.ts +2 -2
- package/src/services/libp2p/libp2p_service.ts +70 -37
- package/src/services/reqresp/interface.ts +26 -1
- package/src/services/reqresp/protocols/block_txs/block_txs_handler.ts +2 -2
- package/src/services/reqresp/protocols/block_txs/block_txs_reqresp.ts +17 -0
- package/src/services/reqresp/protocols/tx.ts +22 -0
- package/src/services/reqresp/reqresp.ts +13 -3
- package/src/services/service.ts +20 -0
- package/src/services/tx_collection/config.ts +26 -0
- package/src/services/tx_collection/fast_tx_collection.ts +14 -2
- package/src/services/tx_collection/file_store_tx_collection.ts +152 -0
- package/src/services/tx_collection/file_store_tx_source.ts +70 -0
- package/src/services/tx_collection/index.ts +1 -0
- package/src/services/tx_collection/slow_tx_collection.ts +55 -26
- package/src/services/tx_collection/tx_collection.ts +78 -12
- package/src/services/tx_collection/tx_collection_sink.ts +17 -7
- package/src/services/tx_file_store/config.ts +0 -6
- package/src/services/tx_file_store/tx_file_store.ts +4 -4
- package/src/services/tx_provider.ts +8 -7
- package/src/test-helpers/make-test-p2p-clients.ts +3 -3
- package/src/test-helpers/mock-pubsub.ts +133 -3
- package/src/test-helpers/testbench-utils.ts +100 -40
- package/src/testbench/p2p_client_testbench_worker.ts +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"attestation_pool.d.ts","sourceRoot":"","sources":["../../../src/mem_pools/attestation_pool/attestation_pool.ts"],"names":[],"mappings":"AAAA,OAAO,EAAyB,UAAU,EAAE,MAAM,iCAAiC,CAAC;AAIpF,OAAO,KAAK,EAAE,iBAAiB,EAAqC,MAAM,iBAAiB,CAAC;AAC5F,OAAO,EACL,aAAa,EACb,qBAAqB,EAErB,KAAK,sBAAsB,EAC5B,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,KAAK,eAAe,EAAsB,MAAM,yBAAyB,CAAC;AAInF,4EAA4E;AAC5E,MAAM,MAAM,YAAY,GAAG;IACzB,iCAAiC;IACjC,KAAK,EAAE,OAAO,CAAC;IACf,6CAA6C;IAC7C,aAAa,EAAE,OAAO,CAAC;IACvB
|
|
1
|
+
{"version":3,"file":"attestation_pool.d.ts","sourceRoot":"","sources":["../../../src/mem_pools/attestation_pool/attestation_pool.ts"],"names":[],"mappings":"AAAA,OAAO,EAAyB,UAAU,EAAE,MAAM,iCAAiC,CAAC;AAIpF,OAAO,KAAK,EAAE,iBAAiB,EAAqC,MAAM,iBAAiB,CAAC;AAC5F,OAAO,EACL,aAAa,EACb,qBAAqB,EAErB,KAAK,sBAAsB,EAC5B,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,KAAK,eAAe,EAAsB,MAAM,yBAAyB,CAAC;AAInF,4EAA4E;AAC5E,MAAM,MAAM,YAAY,GAAG;IACzB,iCAAiC;IACjC,KAAK,EAAE,OAAO,CAAC;IACf,6CAA6C;IAC7C,aAAa,EAAE,OAAO,CAAC;IACvB;;;mFAG+E;IAC/E,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,eAAO,MAAM,iCAAiC,IAAI,CAAC;AACnD,eAAO,MAAM,gCAAgC,IAAI,CAAC;AAClD,oFAAoF;AACpF,eAAO,MAAM,oCAAoC,IAAI,CAAC;AAEtD,kGAAkG;AAClG,MAAM,MAAM,kBAAkB,GAAG,IAAI,CACnC,eAAe,EACb,qBAAqB,GACrB,kBAAkB,GAClB,0BAA0B,GAC1B,uBAAuB,GACvB,8BAA8B,GAC9B,6BAA6B,GAC7B,iBAAiB,GACjB,kCAAkC,GAClC,6CAA6C,GAC7C,SAAS,CACZ,CAAC;AAEF;;;;;GAKG;AACH,qBAAa,eAAe;IA0BxB,OAAO,CAAC,KAAK;IAEb,OAAO,CAAC,GAAG;IA3Bb,OAAO,CAAC,OAAO,CAA6C;IAI5D,OAAO,CAAC,sBAAsB,CAAgC;IAG9D,OAAO,CAAC,mBAAmB,CAAgC;IAI3D,OAAO,CAAC,0BAA0B,CAAqC;IAGvE,OAAO,CAAC,cAAc,CAAgC;IAItD,OAAO,CAAC,6BAA6B,CAAqC;IAI1E,OAAO,CAAC,sCAAsC,CAAqC;IAEnF,YACU,KAAK,EAAE,iBAAiB,EAChC,SAAS,GAAE,eAAsC,EACzC,GAAG,yCAAyC,EAerD;IAED,OAAO,CAAC,SAAS,CAIf;IAEF,yCAAyC;IAC5B,OAAO,IAAI,OAAO,CAAC,OAAO,CAAC,CAQvC;IAED,OAAO,CAAC,cAAc;IAYtB,OAAO,CAAC,iBAAiB;IAIzB,2EAA2E;IAC3E,OAAO,CAAC,6BAA6B;IAKrC,yFAAyF;IACzF,OAAO,CAAC,iCAAiC;IAKzC,gHAAgH;IAChH,OAAO,CAAC,gBAAgB;IAKxB,0EAA0E;IAC1E,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,UAAU,CAAM;IACxC,6DAA6D;IAC7D,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAyC;IAE1E,wFAAwF;IACxF,OAAO,CAAC,mBAAmB;IAS3B;;;;;;;;;;OAUG;IACU,mBAAmB,CAAC,aAAa,EAAE,aAAa,GAAG,OAAO,CAAC,YAAY,CAAC,CAsCpF;IAED,4FAA4F;IAC5F,OAAO,CAAC,gCAAgC;YAS1B,gBAAgB;IAU9B;;;;;;OAMG;IACU,gBAAgB,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,GAAG,SAAS,CAAC,CAW5E;IAED;;;;;;;;;;;;;;OAcG;IACU,wBAAwB,CAAC,QAAQ,EAAE,sBAAsB,GAAG,OAAO,CAAC,YAAY,CAAC,CA2B7F;YAGa,qBAAqB;IAQnC;;;;;;;;OAQG;IACU,qBAAqB,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,sBAAsB,GAAG,SAAS,CAAC,CAW1F;IAED;;;OAGG;IACU,4BAA4B,CAAC,YAAY,EAAE,qBAAqB,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAgC9F;IAED;;;;;OAKG;IACU,gCAAgC,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,qBAAqB,EAAE,CAAC,CAShG;IAED;;;;;;OAMG;IACU,2CAA2C,CACtD,IAAI,EAAE,UAAU,EAChB,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,qBAAqB,EAAE,CAAC,CASlC;IAED;;;;OAIG;IACU,eAAe,CAAC,UAAU,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAmDlE;IAED;;;;;;;;;;;OAWG;IACU,2BAA2B,CAAC,WAAW,EAAE,qBAAqB,GAAG,OAAO,CAAC,YAAY,CAAC,CA8DlG;YAGa,gCAAgC;CAI/C;AAED,0EAA0E;AAC1E,wBAAsB,yBAAyB,CAAC,SAAS,CAAC,EAAE,eAAe,GAAG,OAAO,CAAC,eAAe,CAAC,CAIrG"}
|
|
@@ -4,9 +4,9 @@ import { createLogger } from '@aztec/foundation/log';
|
|
|
4
4
|
import { BlockProposal, CheckpointAttestation, CheckpointProposal } from '@aztec/stdlib/p2p';
|
|
5
5
|
import { getTelemetryClient } from '@aztec/telemetry-client';
|
|
6
6
|
import { PoolInstrumentation, PoolName } from '../instrumentation.js';
|
|
7
|
-
export const
|
|
8
|
-
export const
|
|
9
|
-
export const
|
|
7
|
+
export const MAX_CHECKPOINT_PROPOSALS_PER_SLOT = 5;
|
|
8
|
+
export const MAX_BLOCK_PROPOSALS_PER_POSITION = 3;
|
|
9
|
+
/** Maximum attestations a single signer can make per slot before being rejected. */ export const MAX_ATTESTATIONS_PER_SLOT_AND_SIGNER = 3;
|
|
10
10
|
/**
|
|
11
11
|
* Pool for storing attestations and proposals collected by a validator.
|
|
12
12
|
*
|
|
@@ -29,6 +29,9 @@ export const ATTESTATION_CAP_BUFFER = 10;
|
|
|
29
29
|
// Block proposals indexed by slot and index-within-checkpoint for duplicate detection
|
|
30
30
|
// Key: (slot << 10) | indexWithinCheckpoint, Value: archive string
|
|
31
31
|
blockProposalsForSlotAndIndex;
|
|
32
|
+
// Checkpoint attestations indexed by (slot, signer) for tracking attestations per (slot, signer) for duplicate detection
|
|
33
|
+
// Key: `${Fr(slot).toString()}-${signerAddress}` string (padded for lexicographic ordering), Value: `proposalId` strings
|
|
34
|
+
checkpointAttestationsPerSlotAndSigner;
|
|
32
35
|
constructor(store, telemetry = getTelemetryClient(), log = createLogger('aztec:attestation_pool')){
|
|
33
36
|
this.store = store;
|
|
34
37
|
this.log = log;
|
|
@@ -42,6 +45,7 @@ export const ATTESTATION_CAP_BUFFER = 10;
|
|
|
42
45
|
this.blockProposalsForSlotAndIndex = store.openMultiMap('block_proposals_for_slot_and_index');
|
|
43
46
|
// Initialize checkpoint attestations storage
|
|
44
47
|
this.checkpointAttestations = store.openMap('checkpoint_attestations');
|
|
48
|
+
this.checkpointAttestationsPerSlotAndSigner = store.openMultiMap('checkpoint_attestations_per_slot_and_signer');
|
|
45
49
|
// Initialize checkpoint proposal storage
|
|
46
50
|
this.checkpointProposals = store.openMap('checkpoint_proposals');
|
|
47
51
|
this.checkpointProposalsForSlot = store.openMultiMap('checkpoint_proposals_for_slot');
|
|
@@ -79,6 +83,10 @@ export const ATTESTATION_CAP_BUFFER = 10;
|
|
|
79
83
|
end: `${proposalKey}-Z`
|
|
80
84
|
};
|
|
81
85
|
}
|
|
86
|
+
/** Creates a key for the per-signer-per-slot attestation index. Uses padded slot for lexicographic ordering. */ getSlotSignerKey(slot, signerAddress) {
|
|
87
|
+
const slotStr = new Fr(slot).toString();
|
|
88
|
+
return `${slotStr}-${signerAddress}`;
|
|
89
|
+
}
|
|
82
90
|
/** Number of bits reserved for indexWithinCheckpoint in position keys. */ static INDEX_BITS = 10;
|
|
83
91
|
/** Maximum indexWithinCheckpoint value (2^10 - 1 = 1023). */ static MAX_INDEX = (1 << AttestationPool.INDEX_BITS) - 1;
|
|
84
92
|
/** Creates a position key for block proposals: (slot << 10) | indexWithinCheckpoint. */ getBlockPositionKey(slot, indexWithinCheckpoint) {
|
|
@@ -103,20 +111,20 @@ export const ATTESTATION_CAP_BUFFER = 10;
|
|
|
103
111
|
// Check if already exists
|
|
104
112
|
const alreadyExists = await this.blockProposals.hasAsync(proposalId);
|
|
105
113
|
if (alreadyExists) {
|
|
106
|
-
const
|
|
114
|
+
const count = await this.getBlockProposalCountForPosition(blockProposal.slotNumber, blockProposal.indexWithinCheckpoint);
|
|
107
115
|
return {
|
|
108
116
|
added: false,
|
|
109
117
|
alreadyExists: true,
|
|
110
|
-
|
|
118
|
+
count
|
|
111
119
|
};
|
|
112
120
|
}
|
|
113
121
|
// Get current count for position and check cap, do not add if exceeded
|
|
114
|
-
const
|
|
115
|
-
if (
|
|
122
|
+
const count = await this.getBlockProposalCountForPosition(blockProposal.slotNumber, blockProposal.indexWithinCheckpoint);
|
|
123
|
+
if (count >= MAX_BLOCK_PROPOSALS_PER_POSITION) {
|
|
116
124
|
return {
|
|
117
125
|
added: false,
|
|
118
126
|
alreadyExists: false,
|
|
119
|
-
|
|
127
|
+
count
|
|
120
128
|
};
|
|
121
129
|
}
|
|
122
130
|
// Add the proposal
|
|
@@ -129,7 +137,7 @@ export const ATTESTATION_CAP_BUFFER = 10;
|
|
|
129
137
|
return {
|
|
130
138
|
added: true,
|
|
131
139
|
alreadyExists: false,
|
|
132
|
-
|
|
140
|
+
count: count + 1
|
|
133
141
|
};
|
|
134
142
|
});
|
|
135
143
|
}
|
|
@@ -182,20 +190,20 @@ export const ATTESTATION_CAP_BUFFER = 10;
|
|
|
182
190
|
// Check if already exists
|
|
183
191
|
const alreadyExists = await this.checkpointProposals.hasAsync(proposalId);
|
|
184
192
|
if (alreadyExists) {
|
|
185
|
-
const
|
|
193
|
+
const count = await this.checkpointProposalsForSlot.getValueCountAsync(proposal.slotNumber);
|
|
186
194
|
return {
|
|
187
195
|
added: false,
|
|
188
196
|
alreadyExists: true,
|
|
189
|
-
|
|
197
|
+
count
|
|
190
198
|
};
|
|
191
199
|
}
|
|
192
200
|
// Get current count for slot and check cap
|
|
193
|
-
const
|
|
194
|
-
if (
|
|
201
|
+
const count = await this.checkpointProposalsForSlot.getValueCountAsync(proposal.slotNumber);
|
|
202
|
+
if (count >= MAX_CHECKPOINT_PROPOSALS_PER_SLOT) {
|
|
195
203
|
return {
|
|
196
204
|
added: false,
|
|
197
205
|
alreadyExists: false,
|
|
198
|
-
|
|
206
|
+
count
|
|
199
207
|
};
|
|
200
208
|
}
|
|
201
209
|
// Add the proposal if cap not exceeded
|
|
@@ -207,7 +215,7 @@ export const ATTESTATION_CAP_BUFFER = 10;
|
|
|
207
215
|
return {
|
|
208
216
|
added: true,
|
|
209
217
|
alreadyExists: false,
|
|
210
|
-
|
|
218
|
+
count: count + 1
|
|
211
219
|
};
|
|
212
220
|
});
|
|
213
221
|
}
|
|
@@ -310,6 +318,15 @@ export const ATTESTATION_CAP_BUFFER = 10;
|
|
|
310
318
|
await this.checkpointAttestations.delete(key);
|
|
311
319
|
numberOfAttestations++;
|
|
312
320
|
}
|
|
321
|
+
// Clean up per-signer-per-slot index. Keys are formatted as `${Fr(slot).toString()}-${signerAddress}`.
|
|
322
|
+
// Since Fr pads to fixed-width hex, Fr(oldestSlot) is lexicographically greater than any key with
|
|
323
|
+
// a smaller slot (even with the signer suffix), so using it as the exclusive end bound is correct.
|
|
324
|
+
const slotSignerEndKey = new Fr(oldestSlot).toString();
|
|
325
|
+
for await (const key of this.checkpointAttestationsPerSlotAndSigner.keysAsync({
|
|
326
|
+
end: slotSignerEndKey
|
|
327
|
+
})){
|
|
328
|
+
await this.checkpointAttestationsPerSlotAndSigner.delete(key);
|
|
329
|
+
}
|
|
313
330
|
// Delete checkpoint proposals for slots < oldestSlot, using checkpointProposalsForSlot as index
|
|
314
331
|
for await (const slot of this.checkpointProposalsForSlot.keysAsync({
|
|
315
332
|
end: oldestSlot
|
|
@@ -347,13 +364,13 @@ export const ATTESTATION_CAP_BUFFER = 10;
|
|
|
347
364
|
*
|
|
348
365
|
* This method performs validation and addition in a single call:
|
|
349
366
|
* - Checks if the attestation already exists (returns alreadyExists: true if so)
|
|
350
|
-
* - Checks if
|
|
367
|
+
* - Checks if this signer has reached the per-signer attestation cap for this slot
|
|
351
368
|
* - Adds the attestation if validation passes
|
|
352
369
|
*
|
|
353
370
|
* @param attestation - The checkpoint attestation to add
|
|
354
|
-
* @
|
|
355
|
-
*
|
|
356
|
-
*/ async tryAddCheckpointAttestation(attestation
|
|
371
|
+
* @returns Result indicating whether the attestation was added, existence info, and count of
|
|
372
|
+
* attestations by this signer for this slot (for equivocation detection)
|
|
373
|
+
*/ async tryAddCheckpointAttestation(attestation) {
|
|
357
374
|
const slotNumber = attestation.payload.header.slotNumber;
|
|
358
375
|
const proposalId = attestation.archive.toString();
|
|
359
376
|
const sender = attestation.getSender();
|
|
@@ -361,50 +378,58 @@ export const ATTESTATION_CAP_BUFFER = 10;
|
|
|
361
378
|
return {
|
|
362
379
|
added: false,
|
|
363
380
|
alreadyExists: false,
|
|
364
|
-
|
|
381
|
+
count: 0
|
|
365
382
|
};
|
|
366
383
|
}
|
|
384
|
+
const signerAddress = sender.toString();
|
|
367
385
|
return await this.store.transactionAsync(async ()=>{
|
|
368
|
-
const key = this.getAttestationKey(slotNumber, proposalId,
|
|
386
|
+
const key = this.getAttestationKey(slotNumber, proposalId, signerAddress);
|
|
369
387
|
const alreadyExists = await this.checkpointAttestations.hasAsync(key);
|
|
388
|
+
// Get count of attestations by this signer for this slot (for duplicate detection)
|
|
389
|
+
const signerAttestationCount = await this.getSignerAttestationCountForSlot(slotNumber, signerAddress);
|
|
370
390
|
if (alreadyExists) {
|
|
371
|
-
const total = await this.getAttestationCount(slotNumber, proposalId);
|
|
372
391
|
return {
|
|
373
392
|
added: false,
|
|
374
393
|
alreadyExists: true,
|
|
375
|
-
|
|
394
|
+
count: signerAttestationCount
|
|
376
395
|
};
|
|
377
396
|
}
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
397
|
+
// Check if this signer has exceeded the per-signer cap for this slot
|
|
398
|
+
if (signerAttestationCount >= MAX_ATTESTATIONS_PER_SLOT_AND_SIGNER) {
|
|
399
|
+
this.log.debug(`Rejecting attestation: signer ${signerAddress} exceeded per-slot cap for slot ${slotNumber}`, {
|
|
400
|
+
slotNumber,
|
|
401
|
+
signerAddress,
|
|
402
|
+
proposalId,
|
|
403
|
+
signerAttestationCount
|
|
404
|
+
});
|
|
381
405
|
return {
|
|
382
406
|
added: false,
|
|
383
407
|
alreadyExists: false,
|
|
384
|
-
|
|
408
|
+
count: signerAttestationCount
|
|
385
409
|
};
|
|
386
410
|
}
|
|
411
|
+
// Add the attestation
|
|
387
412
|
await this.checkpointAttestations.set(key, attestation.toBuffer());
|
|
388
|
-
this
|
|
413
|
+
// Track this attestation in the per-signer-per-slot index for duplicate detection
|
|
414
|
+
const slotSignerKey = this.getSlotSignerKey(slotNumber, signerAddress);
|
|
415
|
+
await this.checkpointAttestationsPerSlotAndSigner.set(slotSignerKey, proposalId);
|
|
416
|
+
this.log.debug(`Added checkpoint attestation for slot ${slotNumber} from ${signerAddress}`, {
|
|
389
417
|
signature: attestation.signature.toString(),
|
|
390
418
|
slotNumber,
|
|
391
|
-
address:
|
|
419
|
+
address: signerAddress,
|
|
392
420
|
proposalId
|
|
393
421
|
});
|
|
422
|
+
// Return the new count
|
|
394
423
|
return {
|
|
395
424
|
added: true,
|
|
396
425
|
alreadyExists: false,
|
|
397
|
-
|
|
426
|
+
count: signerAttestationCount + 1
|
|
398
427
|
};
|
|
399
428
|
});
|
|
400
429
|
}
|
|
401
|
-
/** Gets the count of attestations for a given
|
|
402
|
-
const
|
|
403
|
-
|
|
404
|
-
for await (const _ of this.checkpointAttestations.keysAsync(range)){
|
|
405
|
-
count++;
|
|
406
|
-
}
|
|
407
|
-
return count;
|
|
430
|
+
/** Gets the count of attestations by a specific signer for a given slot. */ async getSignerAttestationCountForSlot(slot, signerAddress) {
|
|
431
|
+
const slotSignerKey = this.getSlotSignerKey(slot, signerAddress);
|
|
432
|
+
return await this.checkpointAttestationsPerSlotAndSigner.getValueCountAsync(slotSignerKey);
|
|
408
433
|
}
|
|
409
434
|
}
|
|
410
435
|
/** Creates an AttestationPool backed by a temporary store for testing. */ export async function createTestAttestationPool(telemetry) {
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import { type AttestationPool } from './attestation_pool.js';
|
|
2
2
|
export declare function describeAttestationPool(getAttestationPool: () => AttestationPool): void;
|
|
3
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
3
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXR0ZXN0YXRpb25fcG9vbF90ZXN0X3N1aXRlLmQudHMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvbWVtX3Bvb2xzL2F0dGVzdGF0aW9uX3Bvb2wvYXR0ZXN0YXRpb25fcG9vbF90ZXN0X3N1aXRlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQVlBLE9BQU8sRUFDTCxLQUFLLGVBQWUsRUFHckIsTUFBTSx1QkFBdUIsQ0FBQztBQUsvQix3QkFBZ0IsdUJBQXVCLENBQUMsa0JBQWtCLEVBQUUsTUFBTSxlQUFlLFFBMnJCaEYifQ==
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"attestation_pool_test_suite.d.ts","sourceRoot":"","sources":["../../../src/mem_pools/attestation_pool/attestation_pool_test_suite.ts"],"names":[],"mappings":"AAYA,OAAO,
|
|
1
|
+
{"version":3,"file":"attestation_pool_test_suite.d.ts","sourceRoot":"","sources":["../../../src/mem_pools/attestation_pool/attestation_pool_test_suite.ts"],"names":[],"mappings":"AAYA,OAAO,EACL,KAAK,eAAe,EAGrB,MAAM,uBAAuB,CAAC;AAK/B,wBAAgB,uBAAuB,CAAC,kBAAkB,EAAE,MAAM,eAAe,QA2rBhF"}
|
|
@@ -3,7 +3,7 @@ import { Secp256k1Signer } from '@aztec/foundation/crypto/secp256k1-signer';
|
|
|
3
3
|
import { Fr } from '@aztec/foundation/curves/bn254';
|
|
4
4
|
import { CheckpointHeader } from '@aztec/stdlib/rollup';
|
|
5
5
|
import { makeBlockHeader, makeBlockProposal, makeCheckpointHeader, makeCheckpointProposal } from '@aztec/stdlib/testing';
|
|
6
|
-
import {
|
|
6
|
+
import { MAX_BLOCK_PROPOSALS_PER_POSITION, MAX_CHECKPOINT_PROPOSALS_PER_SLOT } from './attestation_pool.js';
|
|
7
7
|
import { mockCheckpointAttestation } from './mocks.js';
|
|
8
8
|
const NUMBER_OF_SIGNERS_PER_TEST = 4;
|
|
9
9
|
export function describeAttestationPool(getAttestationPool) {
|
|
@@ -167,7 +167,7 @@ export function describeAttestationPool(getAttestationPool) {
|
|
|
167
167
|
const result = await ap.tryAddBlockProposal(proposal);
|
|
168
168
|
expect(result.added).toBe(true);
|
|
169
169
|
expect(result.alreadyExists).toBe(false);
|
|
170
|
-
expect(result.
|
|
170
|
+
expect(result.count).toBe(1);
|
|
171
171
|
const retrievedProposal = await ap.getBlockProposal(proposalId);
|
|
172
172
|
expect(retrievedProposal).toBeDefined();
|
|
173
173
|
expect(retrievedProposal).toEqual(proposal);
|
|
@@ -222,7 +222,7 @@ export function describeAttestationPool(getAttestationPool) {
|
|
|
222
222
|
const result = await ap.tryAddCheckpointProposal(proposal);
|
|
223
223
|
expect(result.added).toBe(true);
|
|
224
224
|
expect(result.alreadyExists).toBe(false);
|
|
225
|
-
expect(result.
|
|
225
|
+
expect(result.count).toBe(1);
|
|
226
226
|
const retrievedProposal = await ap.getCheckpointProposal(proposalId);
|
|
227
227
|
expect(retrievedProposal).toBeDefined();
|
|
228
228
|
expect(retrievedProposal.toBuffer()).toEqual(proposal.toBuffer());
|
|
@@ -275,19 +275,19 @@ export function describeAttestationPool(getAttestationPool) {
|
|
|
275
275
|
});
|
|
276
276
|
it('should return added=false when exceeding capacity', async ()=>{
|
|
277
277
|
const slotNumber = 420;
|
|
278
|
-
// Add
|
|
279
|
-
for(let i = 0; i <
|
|
278
|
+
// Add MAX_CHECKPOINT_PROPOSALS_PER_SLOT proposals
|
|
279
|
+
for(let i = 0; i < MAX_CHECKPOINT_PROPOSALS_PER_SLOT; i++){
|
|
280
280
|
const proposal = await mockCheckpointProposalForPool(signers[i % NUMBER_OF_SIGNERS_PER_TEST], slotNumber);
|
|
281
281
|
const result = await ap.tryAddCheckpointProposal(proposal);
|
|
282
282
|
expect(result.added).toBe(true);
|
|
283
|
-
expect(result.
|
|
283
|
+
expect(result.count).toBe(i + 1);
|
|
284
284
|
}
|
|
285
285
|
// The next proposal should not be added
|
|
286
286
|
const extraProposal = await mockCheckpointProposalForPool(signers[0], slotNumber);
|
|
287
287
|
const result = await ap.tryAddCheckpointProposal(extraProposal);
|
|
288
288
|
expect(result.added).toBe(false);
|
|
289
289
|
expect(result.alreadyExists).toBe(false);
|
|
290
|
-
expect(result.
|
|
290
|
+
expect(result.count).toBe(MAX_CHECKPOINT_PROPOSALS_PER_SLOT);
|
|
291
291
|
});
|
|
292
292
|
});
|
|
293
293
|
describe('Duplicate proposal detection', ()=>{
|
|
@@ -303,12 +303,12 @@ export function describeAttestationPool(getAttestationPool) {
|
|
|
303
303
|
});
|
|
304
304
|
};
|
|
305
305
|
describe('tryAddBlockProposal duplicate detection', ()=>{
|
|
306
|
-
it('should return
|
|
306
|
+
it('should return count=1 when pool is empty', async ()=>{
|
|
307
307
|
const proposal = await mockBlockProposalWithIndex(signers[0], 100, 0);
|
|
308
308
|
const result = await ap.tryAddBlockProposal(proposal);
|
|
309
309
|
expect(result.added).toBe(true);
|
|
310
310
|
expect(result.alreadyExists).toBe(false);
|
|
311
|
-
expect(result.
|
|
311
|
+
expect(result.count).toBe(1);
|
|
312
312
|
});
|
|
313
313
|
it('should return alreadyExists when same proposal exists', async ()=>{
|
|
314
314
|
const proposal = await mockBlockProposalWithIndex(signers[0], 100, 0);
|
|
@@ -316,22 +316,22 @@ export function describeAttestationPool(getAttestationPool) {
|
|
|
316
316
|
const result = await ap.tryAddBlockProposal(proposal);
|
|
317
317
|
expect(result.added).toBe(false);
|
|
318
318
|
expect(result.alreadyExists).toBe(true);
|
|
319
|
-
expect(result.
|
|
319
|
+
expect(result.count).toBe(1);
|
|
320
320
|
});
|
|
321
|
-
it('should detect duplicate via
|
|
321
|
+
it('should detect duplicate via count when different proposal exists at same position', async ()=>{
|
|
322
322
|
const slotNumber = 100;
|
|
323
323
|
const indexWithinCheckpoint = 2;
|
|
324
324
|
// Add first proposal
|
|
325
325
|
const proposal1 = await mockBlockProposalWithIndex(signers[0], slotNumber, indexWithinCheckpoint);
|
|
326
326
|
const result1 = await ap.tryAddBlockProposal(proposal1);
|
|
327
|
-
expect(result1.
|
|
327
|
+
expect(result1.count).toBe(1);
|
|
328
328
|
// Add a different proposal at same position - this is a duplicate (equivocation)
|
|
329
329
|
const proposal2 = await mockBlockProposalWithIndex(signers[1], slotNumber, indexWithinCheckpoint);
|
|
330
330
|
const result2 = await ap.tryAddBlockProposal(proposal2);
|
|
331
331
|
expect(result2.added).toBe(true);
|
|
332
332
|
expect(result2.alreadyExists).toBe(false);
|
|
333
|
-
//
|
|
334
|
-
expect(result2.
|
|
333
|
+
// count >= 2 indicates duplicate detection
|
|
334
|
+
expect(result2.count).toBe(2);
|
|
335
335
|
});
|
|
336
336
|
it('should not detect duplicate for different positions in same slot', async ()=>{
|
|
337
337
|
const slotNumber = 100;
|
|
@@ -342,8 +342,8 @@ export function describeAttestationPool(getAttestationPool) {
|
|
|
342
342
|
const proposal2 = await mockBlockProposalWithIndex(signers[1], slotNumber, 1);
|
|
343
343
|
const result = await ap.tryAddBlockProposal(proposal2);
|
|
344
344
|
expect(result.added).toBe(true);
|
|
345
|
-
//
|
|
346
|
-
expect(result.
|
|
345
|
+
// count = 1 means no duplicate for this position
|
|
346
|
+
expect(result.count).toBe(1);
|
|
347
347
|
});
|
|
348
348
|
it('should not detect duplicate for same position in different slots', async ()=>{
|
|
349
349
|
const indexWithinCheckpoint = 0;
|
|
@@ -354,41 +354,41 @@ export function describeAttestationPool(getAttestationPool) {
|
|
|
354
354
|
const proposal2 = await mockBlockProposalWithIndex(signers[1], 200, indexWithinCheckpoint);
|
|
355
355
|
const result = await ap.tryAddBlockProposal(proposal2);
|
|
356
356
|
expect(result.added).toBe(true);
|
|
357
|
-
//
|
|
358
|
-
expect(result.
|
|
357
|
+
// count = 1 means no duplicate for this position
|
|
358
|
+
expect(result.count).toBe(1);
|
|
359
359
|
});
|
|
360
|
-
it('should track multiple duplicates correctly via
|
|
360
|
+
it('should track multiple duplicates correctly via count', async ()=>{
|
|
361
361
|
const slotNumber = 100;
|
|
362
362
|
const indexWithinCheckpoint = 0;
|
|
363
363
|
// Add multiple proposals for same position
|
|
364
364
|
const proposal1 = await mockBlockProposalWithIndex(signers[0], slotNumber, indexWithinCheckpoint);
|
|
365
365
|
const result1 = await ap.tryAddBlockProposal(proposal1);
|
|
366
|
-
expect(result1.
|
|
366
|
+
expect(result1.count).toBe(1);
|
|
367
367
|
const proposal2 = await mockBlockProposalWithIndex(signers[1], slotNumber, indexWithinCheckpoint);
|
|
368
368
|
const result2 = await ap.tryAddBlockProposal(proposal2);
|
|
369
|
-
expect(result2.
|
|
369
|
+
expect(result2.count).toBe(2);
|
|
370
370
|
// Add a third proposal for same position
|
|
371
371
|
const proposal3 = await mockBlockProposalWithIndex(signers[2], slotNumber, indexWithinCheckpoint);
|
|
372
372
|
const result3 = await ap.tryAddBlockProposal(proposal3);
|
|
373
373
|
expect(result3.added).toBe(true);
|
|
374
|
-
expect(result3.
|
|
374
|
+
expect(result3.count).toBe(3);
|
|
375
375
|
});
|
|
376
376
|
it('should return added=false when exceeding capacity', async ()=>{
|
|
377
377
|
const slotNumber = 100;
|
|
378
378
|
const indexWithinCheckpoint = 0;
|
|
379
|
-
// Add
|
|
380
|
-
for(let i = 0; i <
|
|
379
|
+
// Add MAX_BLOCK_PROPOSALS_PER_POSITION proposals
|
|
380
|
+
for(let i = 0; i < MAX_BLOCK_PROPOSALS_PER_POSITION; i++){
|
|
381
381
|
const proposal = await mockBlockProposalWithIndex(signers[i % NUMBER_OF_SIGNERS_PER_TEST], slotNumber, indexWithinCheckpoint);
|
|
382
382
|
const result = await ap.tryAddBlockProposal(proposal);
|
|
383
383
|
expect(result.added).toBe(true);
|
|
384
|
-
expect(result.
|
|
384
|
+
expect(result.count).toBe(i + 1);
|
|
385
385
|
}
|
|
386
386
|
// The next proposal should not be added
|
|
387
387
|
const extraProposal = await mockBlockProposalWithIndex(signers[0], slotNumber, indexWithinCheckpoint);
|
|
388
388
|
const result = await ap.tryAddBlockProposal(extraProposal);
|
|
389
389
|
expect(result.added).toBe(false);
|
|
390
390
|
expect(result.alreadyExists).toBe(false);
|
|
391
|
-
expect(result.
|
|
391
|
+
expect(result.count).toBe(MAX_BLOCK_PROPOSALS_PER_POSITION);
|
|
392
392
|
});
|
|
393
393
|
it('should clean up block position index when deleting old data', async ()=>{
|
|
394
394
|
const slotNumber = 100;
|
|
@@ -396,16 +396,16 @@ export function describeAttestationPool(getAttestationPool) {
|
|
|
396
396
|
// Add proposal
|
|
397
397
|
const proposal1 = await mockBlockProposalWithIndex(signers[0], slotNumber, indexWithinCheckpoint);
|
|
398
398
|
await ap.tryAddBlockProposal(proposal1);
|
|
399
|
-
// Verify it's tracked (adding another should show
|
|
399
|
+
// Verify it's tracked (adding another should show count = 2)
|
|
400
400
|
const proposal2 = await mockBlockProposalWithIndex(signers[1], slotNumber, indexWithinCheckpoint);
|
|
401
401
|
let result = await ap.tryAddBlockProposal(proposal2);
|
|
402
|
-
expect(result.
|
|
402
|
+
expect(result.count).toBe(2);
|
|
403
403
|
// Delete old data
|
|
404
404
|
await ap.deleteOlderThan(SlotNumber(slotNumber + 1));
|
|
405
|
-
// Verify position index is cleaned up (
|
|
405
|
+
// Verify position index is cleaned up (count should be 1 now)
|
|
406
406
|
const proposal3 = await mockBlockProposalWithIndex(signers[2], slotNumber, indexWithinCheckpoint);
|
|
407
407
|
result = await ap.tryAddBlockProposal(proposal3);
|
|
408
|
-
expect(result.
|
|
408
|
+
expect(result.count).toBe(1);
|
|
409
409
|
});
|
|
410
410
|
it('should correctly delete block proposals at slot boundary', async ()=>{
|
|
411
411
|
// Add proposals at slots 99, 100, and 101 with various indices
|
|
@@ -422,14 +422,14 @@ export function describeAttestationPool(getAttestationPool) {
|
|
|
422
422
|
// Slot 99 proposals should have their index cleaned up
|
|
423
423
|
const newProposal99 = await mockBlockProposalWithIndex(signers[0], 99, 0);
|
|
424
424
|
const result99 = await ap.tryAddBlockProposal(newProposal99);
|
|
425
|
-
expect(result99.
|
|
425
|
+
expect(result99.count).toBe(1); // Index was cleaned up
|
|
426
426
|
// Slot 100 and 101 should still be tracked
|
|
427
427
|
const newProposal100 = await mockBlockProposalWithIndex(signers[1], 100, 0);
|
|
428
428
|
const result100 = await ap.tryAddBlockProposal(newProposal100);
|
|
429
|
-
expect(result100.
|
|
429
|
+
expect(result100.count).toBe(2); // Still has the original
|
|
430
430
|
const newProposal101 = await mockBlockProposalWithIndex(signers[2], 101, 0);
|
|
431
431
|
const result101 = await ap.tryAddBlockProposal(newProposal101);
|
|
432
|
-
expect(result101.
|
|
432
|
+
expect(result101.count).toBe(2); // Still has the original
|
|
433
433
|
});
|
|
434
434
|
it('should delete all indices for a given slot', async ()=>{
|
|
435
435
|
const slotNumber = 50;
|
|
@@ -445,13 +445,13 @@ export function describeAttestationPool(getAttestationPool) {
|
|
|
445
445
|
// All indices should be cleaned up
|
|
446
446
|
const newProposal0 = await mockBlockProposalWithIndex(signers[0], slotNumber, 0);
|
|
447
447
|
const result0 = await ap.tryAddBlockProposal(newProposal0);
|
|
448
|
-
expect(result0.
|
|
448
|
+
expect(result0.count).toBe(1);
|
|
449
449
|
const newProposal1 = await mockBlockProposalWithIndex(signers[1], slotNumber, 1);
|
|
450
450
|
const result1 = await ap.tryAddBlockProposal(newProposal1);
|
|
451
|
-
expect(result1.
|
|
451
|
+
expect(result1.count).toBe(1);
|
|
452
452
|
const newProposal2 = await mockBlockProposalWithIndex(signers[2], slotNumber, 2);
|
|
453
453
|
const result2 = await ap.tryAddBlockProposal(newProposal2);
|
|
454
|
-
expect(result2.
|
|
454
|
+
expect(result2.count).toBe(1);
|
|
455
455
|
});
|
|
456
456
|
it('should delete block proposals from storage when deleting old data', async ()=>{
|
|
457
457
|
const oldSlot = 50;
|
|
@@ -488,12 +488,12 @@ export function describeAttestationPool(getAttestationPool) {
|
|
|
488
488
|
});
|
|
489
489
|
return proposal.toCore();
|
|
490
490
|
};
|
|
491
|
-
it('should return
|
|
491
|
+
it('should return count=1 when pool is empty', async ()=>{
|
|
492
492
|
const proposal = await mockCheckpointProposalCoreForPool(signers[0], 100);
|
|
493
493
|
const result = await ap.tryAddCheckpointProposal(proposal);
|
|
494
494
|
expect(result.added).toBe(true);
|
|
495
495
|
expect(result.alreadyExists).toBe(false);
|
|
496
|
-
expect(result.
|
|
496
|
+
expect(result.count).toBe(1);
|
|
497
497
|
});
|
|
498
498
|
it('should return alreadyExists when same proposal exists', async ()=>{
|
|
499
499
|
const proposal = await mockCheckpointProposalCoreForPool(signers[0], 100);
|
|
@@ -501,21 +501,21 @@ export function describeAttestationPool(getAttestationPool) {
|
|
|
501
501
|
const result = await ap.tryAddCheckpointProposal(proposal);
|
|
502
502
|
expect(result.added).toBe(false);
|
|
503
503
|
expect(result.alreadyExists).toBe(true);
|
|
504
|
-
expect(result.
|
|
504
|
+
expect(result.count).toBe(1);
|
|
505
505
|
});
|
|
506
|
-
it('should detect duplicate via
|
|
506
|
+
it('should detect duplicate via count when different proposal exists for same slot', async ()=>{
|
|
507
507
|
const slotNumber = 100;
|
|
508
508
|
// Add first proposal
|
|
509
509
|
const proposal1 = await mockCheckpointProposalCoreForPool(signers[0], slotNumber);
|
|
510
510
|
const result1 = await ap.tryAddCheckpointProposal(proposal1);
|
|
511
|
-
expect(result1.
|
|
511
|
+
expect(result1.count).toBe(1);
|
|
512
512
|
// Add a different proposal for same slot - this is a duplicate (equivocation)
|
|
513
513
|
const proposal2 = await mockCheckpointProposalCoreForPool(signers[1], slotNumber);
|
|
514
514
|
const result2 = await ap.tryAddCheckpointProposal(proposal2);
|
|
515
515
|
expect(result2.added).toBe(true);
|
|
516
516
|
expect(result2.alreadyExists).toBe(false);
|
|
517
|
-
//
|
|
518
|
-
expect(result2.
|
|
517
|
+
// count >= 2 indicates duplicate detection
|
|
518
|
+
expect(result2.count).toBe(2);
|
|
519
519
|
});
|
|
520
520
|
it('should not detect duplicate for different slots', async ()=>{
|
|
521
521
|
// Add proposal at slot 100
|
|
@@ -525,23 +525,23 @@ export function describeAttestationPool(getAttestationPool) {
|
|
|
525
525
|
const proposal2 = await mockCheckpointProposalCoreForPool(signers[1], 200);
|
|
526
526
|
const result = await ap.tryAddCheckpointProposal(proposal2);
|
|
527
527
|
expect(result.added).toBe(true);
|
|
528
|
-
//
|
|
529
|
-
expect(result.
|
|
528
|
+
// count = 1 means no duplicate for this slot
|
|
529
|
+
expect(result.count).toBe(1);
|
|
530
530
|
});
|
|
531
|
-
it('should track multiple duplicates correctly via
|
|
531
|
+
it('should track multiple duplicates correctly via count', async ()=>{
|
|
532
532
|
const slotNumber = 100;
|
|
533
533
|
// Add multiple proposals for same slot
|
|
534
534
|
const proposal1 = await mockCheckpointProposalCoreForPool(signers[0], slotNumber);
|
|
535
535
|
const result1 = await ap.tryAddCheckpointProposal(proposal1);
|
|
536
|
-
expect(result1.
|
|
536
|
+
expect(result1.count).toBe(1);
|
|
537
537
|
const proposal2 = await mockCheckpointProposalCoreForPool(signers[1], slotNumber);
|
|
538
538
|
const result2 = await ap.tryAddCheckpointProposal(proposal2);
|
|
539
|
-
expect(result2.
|
|
539
|
+
expect(result2.count).toBe(2);
|
|
540
540
|
// Add a third proposal for same slot
|
|
541
541
|
const proposal3 = await mockCheckpointProposalCoreForPool(signers[2], slotNumber);
|
|
542
542
|
const result3 = await ap.tryAddCheckpointProposal(proposal3);
|
|
543
543
|
expect(result3.added).toBe(true);
|
|
544
|
-
expect(result3.
|
|
544
|
+
expect(result3.count).toBe(3);
|
|
545
545
|
});
|
|
546
546
|
it('should not count attestations as proposals for duplicate detection', async ()=>{
|
|
547
547
|
const slotNumber = 100;
|
|
@@ -556,8 +556,8 @@ export function describeAttestationPool(getAttestationPool) {
|
|
|
556
556
|
const result = await ap.tryAddCheckpointProposal(proposal);
|
|
557
557
|
expect(result.added).toBe(true);
|
|
558
558
|
expect(result.alreadyExists).toBe(false);
|
|
559
|
-
//
|
|
560
|
-
expect(result.
|
|
559
|
+
// count should be 1, NOT 2 - attestations should not count as proposals
|
|
560
|
+
expect(result.count).toBe(1);
|
|
561
561
|
});
|
|
562
562
|
it('should not count attestations for different proposals as duplicates', async ()=>{
|
|
563
563
|
const slotNumber = 100;
|
|
@@ -574,12 +574,12 @@ export function describeAttestationPool(getAttestationPool) {
|
|
|
574
574
|
const proposal1 = await mockCheckpointProposalCoreForPool(signers[2], slotNumber, archive1);
|
|
575
575
|
const result1 = await ap.tryAddCheckpointProposal(proposal1);
|
|
576
576
|
expect(result1.added).toBe(true);
|
|
577
|
-
expect(result1.
|
|
577
|
+
expect(result1.count).toBe(1);
|
|
578
578
|
// Add the second checkpoint proposal - this IS a duplicate (different archive, same slot)
|
|
579
579
|
const proposal2 = await mockCheckpointProposalCoreForPool(signers[3], slotNumber, archive2);
|
|
580
580
|
const result2 = await ap.tryAddCheckpointProposal(proposal2);
|
|
581
581
|
expect(result2.added).toBe(true);
|
|
582
|
-
expect(result2.
|
|
582
|
+
expect(result2.count).toBe(2);
|
|
583
583
|
});
|
|
584
584
|
});
|
|
585
585
|
});
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export { AttestationPool, type AttestationPoolApi, type TryAddResult, createTestAttestationPool,
|
|
2
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
1
|
+
export { AttestationPool, type AttestationPoolApi, type TryAddResult, createTestAttestationPool, MAX_CHECKPOINT_PROPOSALS_PER_SLOT, MAX_BLOCK_PROPOSALS_PER_POSITION, MAX_ATTESTATIONS_PER_SLOT_AND_SIGNER, } from './attestation_pool.js';
|
|
2
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguZC50cyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9tZW1fcG9vbHMvYXR0ZXN0YXRpb25fcG9vbC9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQ0wsZUFBZSxFQUNmLEtBQUssa0JBQWtCLEVBQ3ZCLEtBQUssWUFBWSxFQUNqQix5QkFBeUIsRUFDekIsaUNBQWlDLEVBQ2pDLGdDQUFnQyxFQUNoQyxvQ0FBb0MsR0FDckMsTUFBTSx1QkFBdUIsQ0FBQyJ9
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/mem_pools/attestation_pool/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,eAAe,EACf,KAAK,kBAAkB,EACvB,KAAK,YAAY,EACjB,yBAAyB,EACzB,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/mem_pools/attestation_pool/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,eAAe,EACf,KAAK,kBAAkB,EACvB,KAAK,YAAY,EACjB,yBAAyB,EACzB,iCAAiC,EACjC,gCAAgC,EAChC,oCAAoC,GACrC,MAAM,uBAAuB,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export { AttestationPool, createTestAttestationPool,
|
|
1
|
+
export { AttestationPool, createTestAttestationPool, MAX_CHECKPOINT_PROPOSALS_PER_SLOT, MAX_BLOCK_PROPOSALS_PER_POSITION, MAX_ATTESTATIONS_PER_SLOT_AND_SIGNER } from './attestation_pool.js';
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
export { AttestationPool, type AttestationPoolApi } from './attestation_pool/attestation_pool.js';
|
|
2
2
|
export { type MemPools } from './interface.js';
|
|
3
3
|
export { type TxPool } from './tx_pool/tx_pool.js';
|
|
4
|
-
|
|
4
|
+
export { type TxPoolV2, type TxPoolV2Config, type TxPoolV2Events, type AddTxsResult } from './tx_pool_v2/index.js';
|
|
5
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguZC50cyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9tZW1fcG9vbHMvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLGVBQWUsRUFBRSxLQUFLLGtCQUFrQixFQUFFLE1BQU0sd0NBQXdDLENBQUM7QUFDbEcsT0FBTyxFQUFFLEtBQUssUUFBUSxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFFL0MsT0FBTyxFQUFFLEtBQUssTUFBTSxFQUFFLE1BQU0sc0JBQXNCLENBQUM7QUFFbkQsT0FBTyxFQUFFLEtBQUssUUFBUSxFQUFFLEtBQUssY0FBYyxFQUFFLEtBQUssY0FBYyxFQUFFLEtBQUssWUFBWSxFQUFFLE1BQU0sdUJBQXVCLENBQUMifQ==
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/mem_pools/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,KAAK,kBAAkB,EAAE,MAAM,wCAAwC,CAAC;AAClG,OAAO,EAAE,KAAK,QAAQ,EAAE,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/mem_pools/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,KAAK,kBAAkB,EAAE,MAAM,wCAAwC,CAAC;AAClG,OAAO,EAAE,KAAK,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAE/C,OAAO,EAAE,KAAK,MAAM,EAAE,MAAM,sBAAsB,CAAC;AAEnD,OAAO,EAAE,KAAK,QAAQ,EAAE,KAAK,cAAc,EAAE,KAAK,cAAc,EAAE,KAAK,YAAY,EAAE,MAAM,uBAAuB,CAAC"}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import type { AttestationPoolApi } from './attestation_pool/attestation_pool.js';
|
|
2
|
-
import type {
|
|
2
|
+
import type { TxPoolV2 } from './tx_pool_v2/interfaces.js';
|
|
3
3
|
/**
|
|
4
4
|
* A interface the combines all mempools
|
|
5
5
|
*/
|
|
6
6
|
export type MemPools = {
|
|
7
|
-
txPool:
|
|
7
|
+
txPool: TxPoolV2;
|
|
8
8
|
attestationPool: AttestationPoolApi;
|
|
9
9
|
};
|
|
10
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
10
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW50ZXJmYWNlLmQudHMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvbWVtX3Bvb2xzL2ludGVyZmFjZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEtBQUssRUFBRSxrQkFBa0IsRUFBRSxNQUFNLHdDQUF3QyxDQUFDO0FBQ2pGLE9BQU8sS0FBSyxFQUFFLFFBQVEsRUFBRSxNQUFNLDRCQUE0QixDQUFDO0FBRTNEOztHQUVHO0FBQ0gsTUFBTSxNQUFNLFFBQVEsR0FBRztJQUNyQixNQUFNLEVBQUUsUUFBUSxDQUFDO0lBQ2pCLGVBQWUsRUFBRSxrQkFBa0IsQ0FBQztDQUNyQyxDQUFDIn0=
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"interface.d.ts","sourceRoot":"","sources":["../../src/mem_pools/interface.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,wCAAwC,CAAC;AACjF,OAAO,KAAK,EAAE,
|
|
1
|
+
{"version":3,"file":"interface.d.ts","sourceRoot":"","sources":["../../src/mem_pools/interface.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,wCAAwC,CAAC;AACjF,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,4BAA4B,CAAC;AAE3D;;GAEG;AACH,MAAM,MAAM,QAAQ,GAAG;IACrB,MAAM,EAAE,QAAQ,CAAC;IACjB,eAAe,EAAE,kBAAkB,CAAC;CACrC,CAAC"}
|