Skip to content

Commit

Permalink
chore: Delay proof quote collection (#8967)
Browse files Browse the repository at this point in the history
First sequencer in the epoch starts block building at the same time as
the prover nodes start generating quotes. If we collect quotes at the
beginning of block building, we don't give prover nodes enough time to
send the quotes. This delays collecting quotes until last minute.
  • Loading branch information
spalladino authored Oct 3, 2024
1 parent 1c3cb63 commit 640b661
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 44 deletions.
2 changes: 1 addition & 1 deletion yarn-project/prover-node/src/prover-node.ts
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ export class ProverNode implements ClaimsMonitorHandler, EpochMonitorHandler {
await this.handleEpochCompleted(epochNumber);
} else if (claim && claim.bondProvider.equals(this.publisher.getSenderAddress())) {
const lastEpochProven = await this.l2BlockSource.getProvenL2EpochNumber();
if (!lastEpochProven || lastEpochProven < claim.epochToProve) {
if (lastEpochProven === undefined || lastEpochProven < claim.epochToProve) {
await this.handleClaim(claim);
}
}
Expand Down
83 changes: 40 additions & 43 deletions yarn-project/sequencer-client/src/sequencer/sequencer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -407,14 +407,6 @@ export class Sequencer {

const newGlobalVariables = proposalHeader.globalVariables;

// Kick off the process of collecting and validating proof quotes here so it runs alongside block building
const proofQuotePromise = this.createProofClaimForPreviousEpoch(newGlobalVariables.slotNumber.toBigInt()).catch(
e => {
this.log.warn(`Failed to create proof claim quote ${e}`);
return undefined;
},
);

this.metrics.recordNewBlock(newGlobalVariables.blockNumber.toNumber(), validTxs.length);
const workTimer = new Timer();
this.state = SequencerState.CREATING_BLOCK;
Expand Down Expand Up @@ -491,8 +483,8 @@ export class Sequencer {
const attestations = await this.collectAttestations(block, txHashes);
this.log.verbose('Attestations collected');

const proofQuote = await proofQuotePromise;

this.log.verbose('Collecting proof quotes');
const proofQuote = await this.createProofClaimForPreviousEpoch(newGlobalVariables.slotNumber.toBigInt());
this.log.verbose(proofQuote ? `Using proof quote ${inspect(proofQuote.payload)}` : 'No proof quote available');

try {
Expand Down Expand Up @@ -548,42 +540,47 @@ export class Sequencer {
}

protected async createProofClaimForPreviousEpoch(slotNumber: bigint): Promise<EpochProofQuote | undefined> {
// Find out which epoch we are currently in
const epochForBlock = await this.publisher.getEpochForSlotNumber(slotNumber);
if (epochForBlock < 1n) {
// It's the 0th epoch, nothing to be proven yet
this.log.verbose(`First epoch has no claim`);
return undefined;
}
const epochToProve = epochForBlock - 1n;
// Find out the next epoch that can be claimed
const canClaim = await this.publisher.nextEpochToClaim();
if (canClaim != epochToProve) {
// It's not the one we are looking to claim
this.log.verbose(`Unable to claim previous epoch (${canClaim} != ${epochToProve})`);
return undefined;
}
// Get quotes for the epoch to be proven
const quotes = await this.p2pClient.getEpochProofQuotes(epochToProve);
this.log.verbose(`Retrieved ${quotes.length} quotes, slot: ${slotNumber}, epoch to prove: ${epochToProve}`);
for (const quote of quotes) {
this.log.verbose(inspect(quote.payload));
}
// ensure these quotes are still valid for the slot and have the contract validate them
const validQuotesPromise = Promise.all(
quotes.filter(x => x.payload.validUntilSlot >= slotNumber).map(x => this.publisher.validateProofQuote(x)),
);
try {
// Find out which epoch we are currently in
const epochForBlock = await this.publisher.getEpochForSlotNumber(slotNumber);
if (epochForBlock < 1n) {
// It's the 0th epoch, nothing to be proven yet
this.log.verbose(`First epoch has no claim`);
return undefined;
}
const epochToProve = epochForBlock - 1n;
// Find out the next epoch that can be claimed
const canClaim = await this.publisher.nextEpochToClaim();
if (canClaim != epochToProve) {
// It's not the one we are looking to claim
this.log.verbose(`Unable to claim previous epoch (${canClaim} != ${epochToProve})`);
return undefined;
}
// Get quotes for the epoch to be proven
const quotes = await this.p2pClient.getEpochProofQuotes(epochToProve);
this.log.verbose(`Retrieved ${quotes.length} quotes, slot: ${slotNumber}, epoch to prove: ${epochToProve}`);
for (const quote of quotes) {
this.log.verbose(inspect(quote.payload));
}
// ensure these quotes are still valid for the slot and have the contract validate them
const validQuotesPromise = Promise.all(
quotes.filter(x => x.payload.validUntilSlot >= slotNumber).map(x => this.publisher.validateProofQuote(x)),
);

const validQuotes = (await validQuotesPromise).filter((q): q is EpochProofQuote => !!q);
if (!validQuotes.length) {
this.log.verbose(`Failed to find any valid proof quotes`);
const validQuotes = (await validQuotesPromise).filter((q): q is EpochProofQuote => !!q);
if (!validQuotes.length) {
this.log.verbose(`Failed to find any valid proof quotes`);
return undefined;
}
// pick the quote with the lowest fee
const sortedQuotes = validQuotes.sort(
(a: EpochProofQuote, b: EpochProofQuote) => a.payload.basisPointFee - b.payload.basisPointFee,
);
return sortedQuotes[0];
} catch (err) {
this.log.error(`Failed to create proof claim for previous epoch: ${err}`);
return undefined;
}
// pick the quote with the lowest fee
const sortedQuotes = validQuotes.sort(
(a: EpochProofQuote, b: EpochProofQuote) => a.payload.basisPointFee - b.payload.basisPointFee,
);
return sortedQuotes[0];
}

/**
Expand Down

0 comments on commit 640b661

Please sign in to comment.