@aztec/sequencer-client 0.0.1-commit.3fd054f6 → 0.0.1-commit.42ee6df9b
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/global_variable_builder/global_builder.d.ts +3 -3
- package/dest/global_variable_builder/global_builder.d.ts.map +1 -1
- package/dest/global_variable_builder/global_builder.js +7 -4
- package/dest/publisher/sequencer-publisher.d.ts +46 -24
- package/dest/publisher/sequencer-publisher.d.ts.map +1 -1
- package/dest/publisher/sequencer-publisher.js +72 -40
- package/dest/sequencer/checkpoint_proposal_job.d.ts +28 -9
- package/dest/sequencer/checkpoint_proposal_job.d.ts.map +1 -1
- package/dest/sequencer/checkpoint_proposal_job.js +149 -74
- package/dest/sequencer/checkpoint_voter.d.ts +1 -2
- package/dest/sequencer/checkpoint_voter.d.ts.map +1 -1
- package/dest/sequencer/checkpoint_voter.js +2 -5
- package/dest/sequencer/sequencer.d.ts +14 -4
- package/dest/sequencer/sequencer.d.ts.map +1 -1
- package/dest/sequencer/sequencer.js +60 -15
- package/package.json +27 -27
- package/src/global_variable_builder/global_builder.ts +15 -3
- package/src/publisher/sequencer-publisher.ts +113 -51
- package/src/sequencer/checkpoint_proposal_job.ts +181 -77
- package/src/sequencer/checkpoint_voter.ts +1 -12
- package/src/sequencer/sequencer.ts +89 -19
|
@@ -436,9 +436,11 @@ function _apply_decs_2203_r(targetClass, memberDecs, classDecs, parentClass) {
|
|
|
436
436
|
return (_apply_decs_2203_r = applyDecs2203RFactory())(targetClass, memberDecs, classDecs, parentClass);
|
|
437
437
|
}
|
|
438
438
|
var _dec, _dec1, _dec2, _dec3, _dec4, _dec5, _dec6, _dec7, _initProto;
|
|
439
|
-
import {
|
|
439
|
+
import { RollupContract } from '@aztec/ethereum/contracts';
|
|
440
|
+
import { BlockNumber, CheckpointNumber, IndexWithinCheckpoint } from '@aztec/foundation/branded-types';
|
|
440
441
|
import { randomInt } from '@aztec/foundation/crypto/random';
|
|
441
442
|
import { flipSignature, generateRecoverableSignature, generateUnrecoverableSignature } from '@aztec/foundation/crypto/secp256k1-signer';
|
|
443
|
+
import { Signature } from '@aztec/foundation/eth-signature';
|
|
442
444
|
import { filter } from '@aztec/foundation/iterator';
|
|
443
445
|
import { createLogger } from '@aztec/foundation/log';
|
|
444
446
|
import { sleep, sleepUntil } from '@aztec/foundation/sleep';
|
|
@@ -446,7 +448,7 @@ import { Timer } from '@aztec/foundation/timer';
|
|
|
446
448
|
import { isErrorClass, unfreeze } from '@aztec/foundation/types';
|
|
447
449
|
import { CommitteeAttestationsAndSigners, MaliciousCommitteeAttestationsAndSigners } from '@aztec/stdlib/block';
|
|
448
450
|
import { validateCheckpoint } from '@aztec/stdlib/checkpoint';
|
|
449
|
-
import { getSlotStartBuildTimestamp, getTimestampForSlot } from '@aztec/stdlib/epoch-helpers';
|
|
451
|
+
import { computeQuorum, getSlotStartBuildTimestamp, getTimestampForSlot } from '@aztec/stdlib/epoch-helpers';
|
|
450
452
|
import { Gas } from '@aztec/stdlib/gas';
|
|
451
453
|
import { InsufficientValidTxsError } from '@aztec/stdlib/interfaces/server';
|
|
452
454
|
import { computeInHashFromL1ToL2Messages } from '@aztec/stdlib/messaging';
|
|
@@ -473,7 +475,6 @@ _dec = trackSpan('CheckpointProposalJob.execute'), _dec1 = trackSpan('Checkpoint
|
|
|
473
475
|
*/ export class CheckpointProposalJob {
|
|
474
476
|
slotNow;
|
|
475
477
|
targetSlot;
|
|
476
|
-
epochNow;
|
|
477
478
|
targetEpoch;
|
|
478
479
|
checkpointNumber;
|
|
479
480
|
syncedToBlockNumber;
|
|
@@ -499,6 +500,7 @@ _dec = trackSpan('CheckpointProposalJob.execute'), _dec1 = trackSpan('Checkpoint
|
|
|
499
500
|
eventEmitter;
|
|
500
501
|
setStateFn;
|
|
501
502
|
tracer;
|
|
503
|
+
proposedCheckpointData;
|
|
502
504
|
static{
|
|
503
505
|
({ e: [_initProto] } = _apply_decs_2203_r(this, [
|
|
504
506
|
[
|
|
@@ -544,11 +546,12 @@ _dec = trackSpan('CheckpointProposalJob.execute'), _dec1 = trackSpan('Checkpoint
|
|
|
544
546
|
], []));
|
|
545
547
|
}
|
|
546
548
|
log;
|
|
547
|
-
|
|
548
|
-
|
|
549
|
+
/** Tracks the fire-and-forget L1 submission promise so it can be awaited during shutdown. */ pendingL1Submission;
|
|
550
|
+
/** Fee header override computed during proposeCheckpoint, reused in enqueueCheckpointForSubmission. */ computedForceProposedFeeHeader;
|
|
551
|
+
constructor(slotNow, targetSlot, targetEpoch, checkpointNumber, syncedToBlockNumber, // TODO(palla/mbps): Can we remove the proposer in favor of attestorAddress? Need to check fisherman-node flows.
|
|
552
|
+
proposer, publisher, attestorAddress, invalidateCheckpoint, validatorClient, globalsBuilder, p2pClient, worldState, l1ToL2MessageSource, l2BlockSource, checkpointsBuilder, blockSink, l1Constants, config, timetable, slasherClient, epochCache, dateProvider, metrics, eventEmitter, setStateFn, tracer, bindings, proposedCheckpointData){
|
|
549
553
|
this.slotNow = slotNow;
|
|
550
554
|
this.targetSlot = targetSlot;
|
|
551
|
-
this.epochNow = epochNow;
|
|
552
555
|
this.targetEpoch = targetEpoch;
|
|
553
556
|
this.checkpointNumber = checkpointNumber;
|
|
554
557
|
this.syncedToBlockNumber = syncedToBlockNumber;
|
|
@@ -574,28 +577,31 @@ _dec = trackSpan('CheckpointProposalJob.execute'), _dec1 = trackSpan('Checkpoint
|
|
|
574
577
|
this.eventEmitter = eventEmitter;
|
|
575
578
|
this.setStateFn = setStateFn;
|
|
576
579
|
this.tracer = tracer;
|
|
580
|
+
this.proposedCheckpointData = proposedCheckpointData;
|
|
577
581
|
_initProto(this);
|
|
578
582
|
this.log = createLogger('sequencer:checkpoint-proposal', {
|
|
579
583
|
...bindings,
|
|
580
584
|
instanceId: `slot-${this.slotNow}`
|
|
581
585
|
});
|
|
582
586
|
}
|
|
583
|
-
/**
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
/** The wall-clock epoch. */ get epoch() {
|
|
587
|
-
return this.epochNow;
|
|
587
|
+
/** Awaits the pending L1 submission if one is in progress. Call during shutdown. */ async awaitPendingSubmission() {
|
|
588
|
+
this.log.info('Awaiting pending L1 payload submission');
|
|
589
|
+
await this.pendingL1Submission;
|
|
588
590
|
}
|
|
589
591
|
/**
|
|
590
592
|
* Executes the checkpoint proposal job.
|
|
591
|
-
*
|
|
593
|
+
* Builds blocks, collects attestations, enqueues requests, and schedules L1 submission as a
|
|
594
|
+
* background task so the work loop can return to IDLE immediately.
|
|
595
|
+
* Returns the built checkpoint if successful, undefined otherwise.
|
|
592
596
|
*/ async execute() {
|
|
593
597
|
// Enqueue governance and slashing votes (returns promises that will be awaited later)
|
|
594
598
|
// In fisherman mode, we simulate slashing but don't actually publish to L1
|
|
595
599
|
// These are constant for the whole slot, so we only enqueue them once
|
|
596
600
|
const votesPromises = new CheckpointVoter(this.targetSlot, this.publisher, this.attestorAddress, this.validatorClient, this.slasherClient, this.l1Constants, this.config, this.metrics, this.log).enqueueVotes();
|
|
597
|
-
// Build and propose the checkpoint.
|
|
598
|
-
|
|
601
|
+
// Build and propose the checkpoint. Builds blocks, broadcasts, collects attestations, and signs.
|
|
602
|
+
// Does NOT enqueue to L1 yet — that happens after the pipeline sleep.
|
|
603
|
+
const proposalResult = await this.proposeCheckpoint();
|
|
604
|
+
const checkpoint = proposalResult?.checkpoint;
|
|
599
605
|
// Wait until the voting promises have resolved, so all requests are enqueued (not sent)
|
|
600
606
|
await Promise.all(votesPromises);
|
|
601
607
|
if (checkpoint) {
|
|
@@ -606,42 +612,72 @@ _dec = trackSpan('CheckpointProposalJob.execute'), _dec1 = trackSpan('Checkpoint
|
|
|
606
612
|
await this.handleCheckpointEndAsFisherman(checkpoint);
|
|
607
613
|
return;
|
|
608
614
|
}
|
|
609
|
-
//
|
|
610
|
-
if (
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
});
|
|
617
|
-
await sleepUntil(new Date(Number(submissionSlotTimestamp) * 1000), this.dateProvider.nowAsDate());
|
|
618
|
-
// After waking, verify the parent checkpoint wasn't pruned during the sleep.
|
|
619
|
-
// We check L1's pending tip directly instead of canProposeAt, which also validates the proposer
|
|
620
|
-
// identity and would fail because the timestamp resolves to a different slot's proposer.
|
|
621
|
-
const l1Tips = await this.publisher.rollupContract.getTips();
|
|
622
|
-
if (l1Tips.pending < this.checkpointNumber - 1) {
|
|
623
|
-
this.log.warn(`Parent checkpoint was pruned during pipelining sleep (L1 pending=${l1Tips.pending}, expected>=${this.checkpointNumber - 1}), skipping L1 submission for checkpoint ${this.checkpointNumber}`);
|
|
624
|
-
return undefined;
|
|
615
|
+
// Enqueue the checkpoint for L1 submission
|
|
616
|
+
if (proposalResult) {
|
|
617
|
+
try {
|
|
618
|
+
await this.enqueueCheckpointForSubmission(proposalResult);
|
|
619
|
+
} catch (err) {
|
|
620
|
+
this.log.error(`Failed to enqueue checkpoint for L1 submission at slot ${this.targetSlot}`, err);
|
|
621
|
+
// Continue to sendRequestsAt so votes are still sent
|
|
625
622
|
}
|
|
626
623
|
}
|
|
627
|
-
//
|
|
628
|
-
const
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
})
|
|
643
|
-
|
|
624
|
+
// Compute the earliest time to submit: pipeline slot start when pipelining, now otherwise.
|
|
625
|
+
const submitAfter = this.epochCache.isProposerPipeliningEnabled() ? new Date(Number(getTimestampForSlot(this.targetSlot, this.l1Constants)) * 1000) : new Date(this.dateProvider.now());
|
|
626
|
+
// TODO(https://github.com/AztecProtocol/aztec-packages/pull/21250): should discard the pending submission if a reorg occurs underneath
|
|
627
|
+
// Schedule L1 submission in the background so the work loop returns immediately.
|
|
628
|
+
// The publisher will sleep until submitAfter, then send the bundled requests.
|
|
629
|
+
// The promise is stored so it can be awaited during shutdown.
|
|
630
|
+
this.pendingL1Submission = this.publisher.sendRequestsAt(submitAfter).then(async (l1Response)=>{
|
|
631
|
+
const proposedAction = l1Response?.successfulActions.find((a)=>a === 'propose');
|
|
632
|
+
if (proposedAction) {
|
|
633
|
+
this.eventEmitter.emit('checkpoint-published', {
|
|
634
|
+
checkpoint: this.checkpointNumber,
|
|
635
|
+
slot: this.targetSlot
|
|
636
|
+
});
|
|
637
|
+
const coinbase = checkpoint?.header.coinbase;
|
|
638
|
+
await this.metrics.incFilledSlot(this.publisher.getSenderAddress().toString(), coinbase);
|
|
639
|
+
} else if (checkpoint) {
|
|
640
|
+
this.eventEmitter.emit('checkpoint-publish-failed', {
|
|
641
|
+
...l1Response,
|
|
642
|
+
slot: this.targetSlot
|
|
643
|
+
});
|
|
644
|
+
if (this.epochCache.isProposerPipeliningEnabled()) {
|
|
645
|
+
this.metrics.recordPipelineDiscard();
|
|
646
|
+
}
|
|
647
|
+
}
|
|
648
|
+
}).catch((err)=>{
|
|
649
|
+
this.log.error(`Background L1 submission failed for slot ${this.targetSlot}`, err);
|
|
650
|
+
if (checkpoint) {
|
|
651
|
+
this.eventEmitter.emit('checkpoint-publish-failed', {
|
|
652
|
+
slot: this.targetSlot
|
|
653
|
+
});
|
|
654
|
+
if (this.epochCache.isProposerPipeliningEnabled()) {
|
|
655
|
+
this.metrics.recordPipelineDiscard();
|
|
656
|
+
}
|
|
657
|
+
}
|
|
658
|
+
});
|
|
659
|
+
// Return the built checkpoint immediately — the work loop is now unblocked
|
|
660
|
+
return checkpoint;
|
|
661
|
+
}
|
|
662
|
+
/** Enqueues the checkpoint for L1 submission. Called after pipeline sleep in execute(). */ async enqueueCheckpointForSubmission(result) {
|
|
663
|
+
const { checkpoint, attestations, attestationsSignature } = result;
|
|
664
|
+
this.setStateFn(SequencerState.PUBLISHING_CHECKPOINT, this.targetSlot);
|
|
665
|
+
const aztecSlotDuration = this.l1Constants.slotDuration;
|
|
666
|
+
const submissionSlotStart = Number(getTimestampForSlot(this.targetSlot, this.l1Constants));
|
|
667
|
+
const txTimeoutAt = new Date((submissionSlotStart + aztecSlotDuration) * 1000);
|
|
668
|
+
// If we have been configured to potentially skip publishing checkpoint then roll the dice here
|
|
669
|
+
if (this.config.skipPublishingCheckpointsPercent !== undefined && this.config.skipPublishingCheckpointsPercent > 0) {
|
|
670
|
+
const roll = Math.max(0, randomInt(100));
|
|
671
|
+
if (roll < this.config.skipPublishingCheckpointsPercent) {
|
|
672
|
+
this.log.warn(`Skipping publishing proposal for checkpoint ${checkpoint.number}. Configured percentage: ${this.config.skipPublishingCheckpointsPercent}, generated value: ${roll}`);
|
|
673
|
+
return;
|
|
674
|
+
}
|
|
644
675
|
}
|
|
676
|
+
await this.publisher.enqueueProposeCheckpoint(checkpoint, attestations, attestationsSignature, {
|
|
677
|
+
txTimeoutAt,
|
|
678
|
+
forcePendingCheckpointNumber: this.invalidateCheckpoint?.forcePendingCheckpointNumber,
|
|
679
|
+
forceProposedFeeHeader: this.computedForceProposedFeeHeader
|
|
680
|
+
});
|
|
645
681
|
}
|
|
646
682
|
async proposeCheckpoint() {
|
|
647
683
|
try {
|
|
@@ -657,7 +693,7 @@ _dec = trackSpan('CheckpointProposalJob.execute'), _dec1 = trackSpan('Checkpoint
|
|
|
657
693
|
// Start the checkpoint
|
|
658
694
|
this.setStateFn(SequencerState.INITIALIZING_CHECKPOINT, this.targetSlot);
|
|
659
695
|
this.log.info(`Starting checkpoint proposal`, {
|
|
660
|
-
buildSlot: this.
|
|
696
|
+
buildSlot: this.slotNow,
|
|
661
697
|
submissionSlot: this.targetSlot,
|
|
662
698
|
pipelining: this.epochCache.isProposerPipeliningEnabled(),
|
|
663
699
|
proposer: this.proposer?.toString(),
|
|
@@ -668,8 +704,19 @@ _dec = trackSpan('CheckpointProposalJob.execute'), _dec1 = trackSpan('Checkpoint
|
|
|
668
704
|
if (this.invalidateCheckpoint && !this.config.skipInvalidateBlockAsProposer) {
|
|
669
705
|
this.publisher.enqueueInvalidateCheckpoint(this.invalidateCheckpoint);
|
|
670
706
|
}
|
|
671
|
-
// Create checkpoint builder for the slot
|
|
672
|
-
|
|
707
|
+
// Create checkpoint builder for the slot.
|
|
708
|
+
// When pipelining, force the proposed checkpoint number and fee header to our parent so the
|
|
709
|
+
// fee computation sees the same chain tip that L1 will see once the previous pipelined checkpoint lands.
|
|
710
|
+
const isPipelining = this.epochCache.isProposerPipeliningEnabled();
|
|
711
|
+
const parentCheckpointNumber = isPipelining ? CheckpointNumber(this.checkpointNumber - 1) : undefined;
|
|
712
|
+
// Compute the parent's fee header override when pipelining
|
|
713
|
+
if (isPipelining && this.proposedCheckpointData) {
|
|
714
|
+
this.computedForceProposedFeeHeader = await this.computeForceProposedFeeHeader(parentCheckpointNumber);
|
|
715
|
+
}
|
|
716
|
+
const checkpointGlobalVariables = await this.globalsBuilder.buildCheckpointGlobalVariables(coinbase, feeRecipient, this.targetSlot, {
|
|
717
|
+
forcePendingCheckpointNumber: parentCheckpointNumber,
|
|
718
|
+
forceProposedFeeHeader: this.computedForceProposedFeeHeader
|
|
719
|
+
});
|
|
673
720
|
// Collect L1 to L2 messages for the checkpoint and compute their hash
|
|
674
721
|
const l1ToL2Messages = await this.l1ToL2MessageSource.getL1ToL2Messages(this.checkpointNumber);
|
|
675
722
|
const inHash = computeInHashFromL1ToL2Messages(l1ToL2Messages);
|
|
@@ -741,7 +788,7 @@ _dec = trackSpan('CheckpointProposalJob.execute'), _dec1 = trackSpan('Checkpoint
|
|
|
741
788
|
maxTxsPerCheckpoint: this.config.maxTxsPerCheckpoint
|
|
742
789
|
});
|
|
743
790
|
} catch (err) {
|
|
744
|
-
this.log.error(`Built an invalid checkpoint at slot ${this.
|
|
791
|
+
this.log.error(`Built an invalid checkpoint at slot ${this.slotNow} (skipping proposal)`, err, {
|
|
745
792
|
checkpoint: checkpoint.header.toInspect()
|
|
746
793
|
});
|
|
747
794
|
return undefined;
|
|
@@ -756,7 +803,11 @@ _dec = trackSpan('CheckpointProposalJob.execute'), _dec1 = trackSpan('Checkpoint
|
|
|
756
803
|
blocksBuilt: blocksInCheckpoint.length
|
|
757
804
|
});
|
|
758
805
|
this.metrics.recordCheckpointSuccess();
|
|
759
|
-
return
|
|
806
|
+
return {
|
|
807
|
+
checkpoint,
|
|
808
|
+
attestations: CommitteeAttestationsAndSigners.empty(),
|
|
809
|
+
attestationsSignature: Signature.empty()
|
|
810
|
+
};
|
|
760
811
|
}
|
|
761
812
|
// Include the block pending broadcast in the checkpoint proposal if any
|
|
762
813
|
const lastBlock = blockPendingBroadcast && {
|
|
@@ -785,24 +836,12 @@ _dec = trackSpan('CheckpointProposalJob.execute'), _dec1 = trackSpan('Checkpoint
|
|
|
785
836
|
}
|
|
786
837
|
throw err;
|
|
787
838
|
}
|
|
788
|
-
//
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
if (this.config.skipPublishingCheckpointsPercent !== undefined && this.config.skipPublishingCheckpointsPercent > 0) {
|
|
795
|
-
const result = Math.max(0, randomInt(100));
|
|
796
|
-
if (result < this.config.skipPublishingCheckpointsPercent) {
|
|
797
|
-
this.log.warn(`Skipping publishing proposal for checkpoint ${checkpoint.number}. Configured percentage: ${this.config.skipPublishingCheckpointsPercent}, generated value: ${result}`);
|
|
798
|
-
return checkpoint;
|
|
799
|
-
}
|
|
800
|
-
}
|
|
801
|
-
await this.publisher.enqueueProposeCheckpoint(checkpoint, attestations, attestationsSignature, {
|
|
802
|
-
txTimeoutAt,
|
|
803
|
-
forcePendingCheckpointNumber: this.invalidateCheckpoint?.forcePendingCheckpointNumber
|
|
804
|
-
});
|
|
805
|
-
return checkpoint;
|
|
839
|
+
// Return the result for the caller to enqueue after the pipeline sleep
|
|
840
|
+
return {
|
|
841
|
+
checkpoint,
|
|
842
|
+
attestations,
|
|
843
|
+
attestationsSignature
|
|
844
|
+
};
|
|
806
845
|
} catch (e) {
|
|
807
846
|
env.error = e;
|
|
808
847
|
env.hasError = true;
|
|
@@ -815,7 +854,7 @@ _dec = trackSpan('CheckpointProposalJob.execute'), _dec1 = trackSpan('Checkpoint
|
|
|
815
854
|
// swallow this error. It's already been logged by a function deeper in the stack
|
|
816
855
|
return undefined;
|
|
817
856
|
}
|
|
818
|
-
this.log.error(`Error building checkpoint at slot ${this.
|
|
857
|
+
this.log.error(`Error building checkpoint at slot ${this.targetSlot}`, err);
|
|
819
858
|
return undefined;
|
|
820
859
|
}
|
|
821
860
|
}
|
|
@@ -1010,6 +1049,8 @@ _dec = trackSpan('CheckpointProposalJob.execute'), _dec1 = trackSpan('Checkpoint
|
|
|
1010
1049
|
manaPerSec,
|
|
1011
1050
|
...blockStats
|
|
1012
1051
|
});
|
|
1052
|
+
// `slot` is the target/submission slot (may be one ahead when pipelining),
|
|
1053
|
+
// `buildSlot` is the wall-clock slot during which the block was actually built.
|
|
1013
1054
|
this.eventEmitter.emit('block-proposed', {
|
|
1014
1055
|
blockNumber: block.number,
|
|
1015
1056
|
slot: this.targetSlot,
|
|
@@ -1110,7 +1151,7 @@ _dec = trackSpan('CheckpointProposalJob.execute'), _dec1 = trackSpan('Checkpoint
|
|
|
1110
1151
|
committee
|
|
1111
1152
|
});
|
|
1112
1153
|
}
|
|
1113
|
-
const numberOfRequiredAttestations =
|
|
1154
|
+
const numberOfRequiredAttestations = computeQuorum(committee.length);
|
|
1114
1155
|
if (this.config.skipCollectingAttestations) {
|
|
1115
1156
|
this.log.warn('Skipping attestation collection as per config (attesting with own keys only)');
|
|
1116
1157
|
const attestations = await this.validatorClient?.collectOwnAttestations(proposal);
|
|
@@ -1216,7 +1257,7 @@ _dec = trackSpan('CheckpointProposalJob.execute'), _dec1 = trackSpan('Checkpoint
|
|
|
1216
1257
|
* Gossip doesn't echo messages back to the sender, so the proposer's archiver/world-state
|
|
1217
1258
|
* would never receive its own block without this explicit sync.
|
|
1218
1259
|
*/ async syncProposedBlockToArchiver(block) {
|
|
1219
|
-
if (this.config.skipPushProposedBlocksToArchiver
|
|
1260
|
+
if (this.config.skipPushProposedBlocksToArchiver) {
|
|
1220
1261
|
this.log.warn(`Skipping push of proposed block ${block.number} to archiver`, {
|
|
1221
1262
|
blockNumber: block.number,
|
|
1222
1263
|
slot: block.header.globalVariables.slotNumber
|
|
@@ -1268,6 +1309,40 @@ _dec = trackSpan('CheckpointProposalJob.execute'), _dec1 = trackSpan('Checkpoint
|
|
|
1268
1309
|
}
|
|
1269
1310
|
return false;
|
|
1270
1311
|
}
|
|
1312
|
+
/**
|
|
1313
|
+
* In times of congestion we need to simulate using the correct fee header override for the previous block
|
|
1314
|
+
* We calculate the correct fee header values.
|
|
1315
|
+
*
|
|
1316
|
+
* If we are in block 1, or the checkpoint we are querying does not exist, we return undefined. However
|
|
1317
|
+
* If we are pipelining - where this function is called, the grandparentCheckpointNumber should always exist
|
|
1318
|
+
* @param parentCheckpointNumber
|
|
1319
|
+
* @returns
|
|
1320
|
+
*/ async computeForceProposedFeeHeader(parentCheckpointNumber) {
|
|
1321
|
+
if (!this.proposedCheckpointData) {
|
|
1322
|
+
return undefined;
|
|
1323
|
+
}
|
|
1324
|
+
const rollup = this.publisher.rollupContract;
|
|
1325
|
+
const grandparentCheckpointNumber = CheckpointNumber(this.checkpointNumber - 2);
|
|
1326
|
+
try {
|
|
1327
|
+
const [grandparentCheckpoint, manaTarget] = await Promise.all([
|
|
1328
|
+
rollup.getCheckpoint(grandparentCheckpointNumber),
|
|
1329
|
+
rollup.getManaTarget()
|
|
1330
|
+
]);
|
|
1331
|
+
if (!grandparentCheckpoint || !grandparentCheckpoint.feeHeader) {
|
|
1332
|
+
this.log.error(`Grandparent checkpoint or its feeHeader is undefined for checkpointNumber=${grandparentCheckpointNumber.toString()}`);
|
|
1333
|
+
return undefined;
|
|
1334
|
+
} else {
|
|
1335
|
+
const parentFeeHeader = RollupContract.computeChildFeeHeader(grandparentCheckpoint.feeHeader, this.proposedCheckpointData.totalManaUsed, this.proposedCheckpointData.feeAssetPriceModifier, manaTarget);
|
|
1336
|
+
return {
|
|
1337
|
+
checkpointNumber: parentCheckpointNumber,
|
|
1338
|
+
feeHeader: parentFeeHeader
|
|
1339
|
+
};
|
|
1340
|
+
}
|
|
1341
|
+
} catch (err) {
|
|
1342
|
+
this.log.error(`Failed to fetch grandparent checkpoint or mana target for checkpointNumber=${grandparentCheckpointNumber.toString()}: ${err}`);
|
|
1343
|
+
return undefined;
|
|
1344
|
+
}
|
|
1345
|
+
}
|
|
1271
1346
|
/** Waits until a specific time within the current slot */ async waitUntilTimeInSlot(targetSecondsIntoSlot) {
|
|
1272
1347
|
const slotStartTimestamp = this.getSlotStartBuildTimestamp();
|
|
1273
1348
|
const targetTimestamp = slotStartTimestamp + targetSecondsIntoSlot;
|
|
@@ -1277,7 +1352,7 @@ _dec = trackSpan('CheckpointProposalJob.execute'), _dec1 = trackSpan('Checkpoint
|
|
|
1277
1352
|
await sleep(TXS_POLLING_MS);
|
|
1278
1353
|
}
|
|
1279
1354
|
getSlotStartBuildTimestamp() {
|
|
1280
|
-
return getSlotStartBuildTimestamp(this.
|
|
1355
|
+
return getSlotStartBuildTimestamp(this.slotNow, this.l1Constants);
|
|
1281
1356
|
}
|
|
1282
1357
|
getSecondsIntoSlot() {
|
|
1283
1358
|
const slotStartTimestamp = this.getSlotStartBuildTimestamp();
|
|
@@ -20,7 +20,6 @@ export declare class CheckpointVoter {
|
|
|
20
20
|
private readonly config;
|
|
21
21
|
private readonly metrics;
|
|
22
22
|
private readonly log;
|
|
23
|
-
private slotTimestamp;
|
|
24
23
|
private governanceSigner;
|
|
25
24
|
private slashingSigner;
|
|
26
25
|
constructor(slot: SlotNumber, publisher: SequencerPublisher, attestorAddress: EthAddress, validatorClient: ValidatorClient, slasherClient: SlasherClientInterface | undefined, l1Constants: SequencerRollupConstants, config: ResolvedSequencerConfig, metrics: SequencerMetrics, log: Logger);
|
|
@@ -32,4 +31,4 @@ export declare class CheckpointVoter {
|
|
|
32
31
|
private enqueueGovernanceVote;
|
|
33
32
|
private enqueueSlashingVote;
|
|
34
33
|
}
|
|
35
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
34
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2hlY2twb2ludF92b3Rlci5kLnRzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3NlcXVlbmNlci9jaGVja3BvaW50X3ZvdGVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sS0FBSyxFQUFFLFVBQVUsRUFBRSxNQUFNLGlDQUFpQyxDQUFDO0FBQ2xFLE9BQU8sS0FBSyxFQUFFLFVBQVUsRUFBRSxNQUFNLCtCQUErQixDQUFDO0FBQ2hFLE9BQU8sS0FBSyxFQUFFLE1BQU0sRUFBRSxNQUFNLHVCQUF1QixDQUFDO0FBQ3BELE9BQU8sS0FBSyxFQUFFLHNCQUFzQixFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFDN0QsT0FBTyxLQUFLLEVBQUUsdUJBQXVCLEVBQUUsTUFBTSxpQ0FBaUMsQ0FBQztBQUMvRSxPQUFPLEtBQUssRUFBRSxlQUFlLEVBQUUsTUFBTSx5QkFBeUIsQ0FBQztBQU0vRCxPQUFPLEtBQUssRUFBRSxrQkFBa0IsRUFBRSxNQUFNLHFDQUFxQyxDQUFDO0FBQzlFLE9BQU8sS0FBSyxFQUFFLGdCQUFnQixFQUFFLE1BQU0sY0FBYyxDQUFDO0FBQ3JELE9BQU8sS0FBSyxFQUFFLHdCQUF3QixFQUFFLE1BQU0sWUFBWSxDQUFDO0FBRTNEOztHQUVHO0FBQ0gscUJBQWEsZUFBZTtJQUt4QixPQUFPLENBQUMsUUFBUSxDQUFDLElBQUk7SUFDckIsT0FBTyxDQUFDLFFBQVEsQ0FBQyxTQUFTO0lBQzFCLE9BQU8sQ0FBQyxRQUFRLENBQUMsZUFBZTtJQUNoQyxPQUFPLENBQUMsUUFBUSxDQUFDLGVBQWU7SUFDaEMsT0FBTyxDQUFDLFFBQVEsQ0FBQyxhQUFhO0lBQzlCLE9BQU8sQ0FBQyxRQUFRLENBQUMsV0FBVztJQUM1QixPQUFPLENBQUMsUUFBUSxDQUFDLE1BQU07SUFDdkIsT0FBTyxDQUFDLFFBQVEsQ0FBQyxPQUFPO0lBQ3hCLE9BQU8sQ0FBQyxRQUFRLENBQUMsR0FBRztJQVp0QixPQUFPLENBQUMsZ0JBQWdCLENBQXVEO0lBQy9FLE9BQU8sQ0FBQyxjQUFjLENBQXVEO0lBRTdFLFlBQ21CLElBQUksRUFBRSxVQUFVLEVBQ2hCLFNBQVMsRUFBRSxrQkFBa0IsRUFDN0IsZUFBZSxFQUFFLFVBQVUsRUFDM0IsZUFBZSxFQUFFLGVBQWUsRUFDaEMsYUFBYSxFQUFFLHNCQUFzQixHQUFHLFNBQVMsRUFDakQsV0FBVyxFQUFFLHdCQUF3QixFQUNyQyxNQUFNLEVBQUUsdUJBQXVCLEVBQy9CLE9BQU8sRUFBRSxnQkFBZ0IsRUFDekIsR0FBRyxFQUFFLE1BQU0sRUFXN0I7SUFFRDs7O09BR0c7SUFDSCxZQUFZLElBQUksQ0FBQyxPQUFPLENBQUMsT0FBTyxHQUFHLFNBQVMsQ0FBQyxFQUFFLE9BQU8sQ0FBQyxPQUFPLEdBQUcsU0FBUyxDQUFDLENBQUMsQ0FVM0U7WUFFYSxxQkFBcUI7WUErQnJCLG1CQUFtQjtDQTJCbEMifQ==
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"checkpoint_voter.d.ts","sourceRoot":"","sources":["../../src/sequencer/checkpoint_voter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iCAAiC,CAAC;AAClE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,+BAA+B,CAAC;AAChE,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAC;AACpD,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"checkpoint_voter.d.ts","sourceRoot":"","sources":["../../src/sequencer/checkpoint_voter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iCAAiC,CAAC;AAClE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,+BAA+B,CAAC;AAChE,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAC;AACpD,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,gBAAgB,CAAC;AAC7D,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,iCAAiC,CAAC;AAC/E,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAM/D,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,qCAAqC,CAAC;AAC9E,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AACrD,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,YAAY,CAAC;AAE3D;;GAEG;AACH,qBAAa,eAAe;IAKxB,OAAO,CAAC,QAAQ,CAAC,IAAI;IACrB,OAAO,CAAC,QAAQ,CAAC,SAAS;IAC1B,OAAO,CAAC,QAAQ,CAAC,eAAe;IAChC,OAAO,CAAC,QAAQ,CAAC,eAAe;IAChC,OAAO,CAAC,QAAQ,CAAC,aAAa;IAC9B,OAAO,CAAC,QAAQ,CAAC,WAAW;IAC5B,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,GAAG;IAZtB,OAAO,CAAC,gBAAgB,CAAuD;IAC/E,OAAO,CAAC,cAAc,CAAuD;IAE7E,YACmB,IAAI,EAAE,UAAU,EAChB,SAAS,EAAE,kBAAkB,EAC7B,eAAe,EAAE,UAAU,EAC3B,eAAe,EAAE,eAAe,EAChC,aAAa,EAAE,sBAAsB,GAAG,SAAS,EACjD,WAAW,EAAE,wBAAwB,EACrC,MAAM,EAAE,uBAAuB,EAC/B,OAAO,EAAE,gBAAgB,EACzB,GAAG,EAAE,MAAM,EAW7B;IAED;;;OAGG;IACH,YAAY,IAAI,CAAC,OAAO,CAAC,OAAO,GAAG,SAAS,CAAC,EAAE,OAAO,CAAC,OAAO,GAAG,SAAS,CAAC,CAAC,CAU3E;YAEa,qBAAqB;YA+BrB,mBAAmB;CA2BlC"}
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { getTimestampForSlot } from '@aztec/stdlib/epoch-helpers';
|
|
2
1
|
import { DutyAlreadySignedError } from '@aztec/validator-ha-signer/errors';
|
|
3
2
|
import { DutyType } from '@aztec/validator-ha-signer/types';
|
|
4
3
|
/**
|
|
@@ -13,7 +12,6 @@ import { DutyType } from '@aztec/validator-ha-signer/types';
|
|
|
13
12
|
config;
|
|
14
13
|
metrics;
|
|
15
14
|
log;
|
|
16
|
-
slotTimestamp;
|
|
17
15
|
governanceSigner;
|
|
18
16
|
slashingSigner;
|
|
19
17
|
constructor(slot, publisher, attestorAddress, validatorClient, slasherClient, l1Constants, config, metrics, log){
|
|
@@ -26,7 +24,6 @@ import { DutyType } from '@aztec/validator-ha-signer/types';
|
|
|
26
24
|
this.config = config;
|
|
27
25
|
this.metrics = metrics;
|
|
28
26
|
this.log = log;
|
|
29
|
-
this.slotTimestamp = getTimestampForSlot(this.slot, this.l1Constants);
|
|
30
27
|
// Create separate signers with appropriate duty contexts for governance and slashing votes
|
|
31
28
|
// These use HA protection to ensure only one node signs per slot/duty
|
|
32
29
|
const governanceContext = {
|
|
@@ -69,7 +66,7 @@ import { DutyType } from '@aztec/validator-ha-signer/types';
|
|
|
69
66
|
governanceProposerPayload: governanceProposerPayload.toString()
|
|
70
67
|
});
|
|
71
68
|
try {
|
|
72
|
-
return await this.publisher.enqueueGovernanceCastSignal(governanceProposerPayload, this.slot, this.
|
|
69
|
+
return await this.publisher.enqueueGovernanceCastSignal(governanceProposerPayload, this.slot, this.attestorAddress, this.governanceSigner);
|
|
73
70
|
} catch (err) {
|
|
74
71
|
if (err instanceof DutyAlreadySignedError) {
|
|
75
72
|
this.log.info(`Governance vote already signed by another node`, {
|
|
@@ -93,7 +90,7 @@ import { DutyType } from '@aztec/validator-ha-signer/types';
|
|
|
93
90
|
actionCount: actions.length
|
|
94
91
|
});
|
|
95
92
|
this.metrics.recordSlashingAttempt(actions.length);
|
|
96
|
-
return await this.publisher.enqueueSlashingActions(actions, this.slot, this.
|
|
93
|
+
return await this.publisher.enqueueSlashingActions(actions, this.slot, this.attestorAddress, this.slashingSigner);
|
|
97
94
|
} catch (err) {
|
|
98
95
|
if (err instanceof DutyAlreadySignedError) {
|
|
99
96
|
this.log.info(`Slashing vote already signed by another node`, {
|
|
@@ -8,7 +8,7 @@ import type { TypedEventEmitter } from '@aztec/foundation/types';
|
|
|
8
8
|
import type { P2P } from '@aztec/p2p';
|
|
9
9
|
import type { SlasherClientInterface } from '@aztec/slasher';
|
|
10
10
|
import type { BlockData, L2BlockSink, L2BlockSource, ValidateCheckpointResult } from '@aztec/stdlib/block';
|
|
11
|
-
import type { Checkpoint } from '@aztec/stdlib/checkpoint';
|
|
11
|
+
import type { Checkpoint, ProposedCheckpointData } from '@aztec/stdlib/checkpoint';
|
|
12
12
|
import { type ResolvedSequencerConfig, type SequencerConfig, type WorldStateSynchronizer } from '@aztec/stdlib/interfaces/server';
|
|
13
13
|
import type { L1ToL2MessageSource } from '@aztec/stdlib/messaging';
|
|
14
14
|
import { type TelemetryClient, type Tracer } from '@aztec/telemetry-client';
|
|
@@ -60,6 +60,8 @@ export declare class Sequencer extends Sequencer_base {
|
|
|
60
60
|
private lastCheckpointProposed;
|
|
61
61
|
/** The last epoch for which we logged strategy comparison in fisherman mode. */
|
|
62
62
|
private lastEpochForStrategyComparison;
|
|
63
|
+
/** The last checkpoint proposal job, tracked so we can await its pending L1 submission during shutdown. */
|
|
64
|
+
private lastCheckpointProposalJob;
|
|
63
65
|
/** The maximum number of seconds that the sequencer can be into a slot to transition to a particular state. */
|
|
64
66
|
protected timetable: SequencerTimetable;
|
|
65
67
|
/** Config for the sequencer */
|
|
@@ -88,8 +90,13 @@ export declare class Sequencer extends Sequencer_base {
|
|
|
88
90
|
* - Submit checkpoint
|
|
89
91
|
*/
|
|
90
92
|
protected work(): Promise<Checkpoint | undefined>;
|
|
91
|
-
|
|
92
|
-
|
|
93
|
+
/**
|
|
94
|
+
* Prepares the checkpoint proposal by performing all necessary checks and setup.
|
|
95
|
+
* This is the initial step in the main loop.
|
|
96
|
+
* @returns CheckpointProposalJob if successful, undefined if we are not yet synced or are not the proposer.
|
|
97
|
+
*/
|
|
98
|
+
protected prepareCheckpointProposal(slot: SlotNumber, targetSlot: SlotNumber, epoch: EpochNumber, targetEpoch: EpochNumber, ts: bigint, nowSeconds: bigint): Promise<CheckpointProposalJob | undefined>;
|
|
99
|
+
protected createCheckpointProposalJob(slot: SlotNumber, targetSlot: SlotNumber, targetEpoch: EpochNumber, checkpointNumber: CheckpointNumber, syncedToBlockNumber: BlockNumber, proposer: EthAddress | undefined, publisher: SequencerPublisher, attestorAddress: EthAddress, invalidateCheckpoint: InvalidateCheckpointRequest | undefined, proposedCheckpointData?: ProposedCheckpointData): CheckpointProposalJob;
|
|
93
100
|
/**
|
|
94
101
|
* Returns the current sequencer state.
|
|
95
102
|
*/
|
|
@@ -194,9 +201,12 @@ export declare class Sequencer extends Sequencer_base {
|
|
|
194
201
|
type SequencerSyncCheckResult = {
|
|
195
202
|
blockData?: BlockData;
|
|
196
203
|
checkpointNumber: CheckpointNumber;
|
|
204
|
+
checkpointedCheckpointNumber: CheckpointNumber;
|
|
197
205
|
blockNumber: BlockNumber;
|
|
198
206
|
archive: Fr;
|
|
207
|
+
hasProposedCheckpoint: boolean;
|
|
208
|
+
proposedCheckpointData?: ProposedCheckpointData;
|
|
199
209
|
syncedL2Slot: SlotNumber;
|
|
200
210
|
pendingChainValidationStatus: ValidateCheckpointResult;
|
|
201
211
|
};
|
|
202
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
212
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2VxdWVuY2VyLmQudHMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvc2VxdWVuY2VyL3NlcXVlbmNlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFFQSxPQUFPLEtBQUssRUFBRSxVQUFVLEVBQUUsTUFBTSxvQkFBb0IsQ0FBQztBQUNyRCxPQUFPLEVBQW9CLEtBQUssY0FBYyxFQUFFLE1BQU0sMkJBQTJCLENBQUM7QUFDbEYsT0FBTyxFQUFFLFdBQVcsRUFBRSxnQkFBZ0IsRUFBRSxXQUFXLEVBQUUsVUFBVSxFQUFFLE1BQU0saUNBQWlDLENBQUM7QUFFekcsT0FBTyxFQUFFLEVBQUUsRUFBRSxNQUFNLGdDQUFnQyxDQUFDO0FBQ3BELE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSwrQkFBK0IsQ0FBQztBQUczRCxPQUFPLEtBQUssRUFBRSxZQUFZLEVBQUUsTUFBTSx5QkFBeUIsQ0FBQztBQUM1RCxPQUFPLEtBQUssRUFBRSxpQkFBaUIsRUFBRSxNQUFNLHlCQUF5QixDQUFDO0FBQ2pFLE9BQU8sS0FBSyxFQUFFLEdBQUcsRUFBRSxNQUFNLFlBQVksQ0FBQztBQUN0QyxPQUFPLEtBQUssRUFBRSxzQkFBc0IsRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBQzdELE9BQU8sS0FBSyxFQUFFLFNBQVMsRUFBRSxXQUFXLEVBQUUsYUFBYSxFQUFFLHdCQUF3QixFQUFFLE1BQU0scUJBQXFCLENBQUM7QUFDM0csT0FBTyxLQUFLLEVBQUUsVUFBVSxFQUFFLHNCQUFzQixFQUFFLE1BQU0sMEJBQTBCLENBQUM7QUFFbkYsT0FBTyxFQUNMLEtBQUssdUJBQXVCLEVBQzVCLEtBQUssZUFBZSxFQUVwQixLQUFLLHNCQUFzQixFQUM1QixNQUFNLGlDQUFpQyxDQUFDO0FBQ3pDLE9BQU8sS0FBSyxFQUFFLG1CQUFtQixFQUFFLE1BQU0seUJBQXlCLENBQUM7QUFHbkUsT0FBTyxFQUFjLEtBQUssZUFBZSxFQUFFLEtBQUssTUFBTSxFQUFpQyxNQUFN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
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sequencer.d.ts","sourceRoot":"","sources":["../../src/sequencer/sequencer.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,EAAoB,KAAK,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAClF,OAAO,EAAE,WAAW,EAAE,gBAAgB,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,iCAAiC,CAAC;AAEzG,OAAO,EAAE,EAAE,EAAE,MAAM,gCAAgC,CAAC;AACpD,OAAO,EAAE,UAAU,EAAE,MAAM,+BAA+B,CAAC;AAG3D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAC5D,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AACjE,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,gBAAgB,CAAC;AAC7D,OAAO,KAAK,EAAE,SAAS,EAAE,WAAW,EAAE,aAAa,EAAE,wBAAwB,EAAE,MAAM,qBAAqB,CAAC;AAC3G,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;
|
|
1
|
+
{"version":3,"file":"sequencer.d.ts","sourceRoot":"","sources":["../../src/sequencer/sequencer.ts"],"names":[],"mappings":"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"}
|