-
Notifications
You must be signed in to change notification settings - Fork 1.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Check round ids #15183
Check round ids #15183
Conversation
I see you updated files related to |
Static analysis results are availableHey @eduard-cl, you can view Slither reports in the job summary here or download them as artifact here. |
AER Report: Operator UI CIaer_workflow , commit , Breaking Changes GQL Check 1. Workflow conclusion is failure:[convictional/trigger-workflow-and-wait@f69fa9e]Source of Error:
Why: The triggered workflow did not complete successfully. The conclusion status was "failure" instead of "success," causing the upstream job to fail as well. Suggested fix: Investigate the logs of the triggered workflow (ID: 11800155115) to identify the specific cause of failure and address the underlying issue. Ensure all dependencies and configurations are correct. AER Report: CI Core ran successfully ✅ |
Only checking the epochAndRound doesn't work. We can end up with a situation where the transmitter constantly resends the same transmission and it won't revert. |
// Verify signatures attached to report | ||
_verifySignatures(reportContext, report, rs, ss, rawVs); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just realized we should always verify signatures. This should be placed under _validateReport
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why? To optimize gas costs it's better if we only verify the signatures one time per report.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's an attack vector. You can provide existing reports to the secondary feed that were not signed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, but the existing reports have to have the same timestamp and answer than the one already validated. I thought the biggest benefit of this implementation was to not have to double check the signatures if a report has previously arrived by the other aggregator path.
} | ||
|
||
// Lock/unlock the primary feed and pay the transmitters | ||
s_primaryLocked = isSecondary; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is not easy to understand, as we're only locking for a single block. Let's change this variable to something more direct, saying that the last update was from the secondary feed, and then communicate the implications of this on the reading side
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's true, renamed it to s_latestSecondary
if (epochAndRound != s_hotVars.latestEpochAndRound || !s_latestSecondary) { | ||
if (epochAndRound <= s_hotVars.latestEpochAndRound) { | ||
revert StaleReport(); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm finding these conditions hard to follow. Can you include some comments explaining what different edge cases we are validating for?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added some comments, it's true it's a bit hard to understand, because I inverted some conditionals to not have duplicated code. To help you understand the code, it's the same as this:
// In case the report is the same as the latest and it arrived throw the secondary feed,
// we have to validate it without transmitting a duplicated report
if (epochAndRound == s_hotVars.latestEpochAndRound && s_latestSecondary) {
s_latestSecondary = isSecondary;
_payTransmitter(s_hotVars, report_.juelsPerFeeCoin, uint32(initialGas), msg.sender);
return;
}
// revert because it's older or already arrived throw the primary feed too (if not we would
// have match the previous check)
if (epochAndRound <= s_hotVars.latestEpochAndRound) {
revert StaleReport();
}
_report(s_hotVars, reportContext[0], epochAndRound, report_, isSecondary);
// Store if the latest report was secondary or not
s_latestSecondary = isSecondary;
_payTransmitter(s_hotVars, report_.juelsPerFeeCoin, uint32(initialGas), msg.sender);
The only difference is that I inverted the first conditional to not have this lines duplicated:
s_latestSecondary = isSecondary;
_payTransmitter(s_hotVars, report_.juelsPerFeeCoin, uint32(initialGas), msg.sender);
s_hotVars.latestSecondaryRoundId = roundId; | ||
emit SecondaryRoundIdUpdated(roundId); | ||
|
||
_payTransmitter(s_hotVars, report_.juelsPerFeeCoin, uint32(initialGas), msg.sender); | ||
return; | ||
} | ||
// In case the report doesn't exist, lock the primary feed | ||
s_primaryLocked = true; | ||
} else { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
suggestion: I think we could keep this else and use it for the case where the primary feed deals with receiving an existing, but latest report.
if (epochAndRound == s_hotVars.latestEpochAndRound && s_primaryLocked))
I see this if, else block as where the logic is evaluated for all edge cases where an existing report is sent to either feed. Early returns would happen here as well.
The rest of the function would be to handle and record new reports.
This is very subjective so feel free to disagree.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you develop more this idea? Not sure I'm following how it should be implemented.
Quality Gate passedIssues Measures |
@@ -804,37 +804,46 @@ contract DualAggregator is OCR2Abstract, OwnerIsCreator, AggregatorV2V3Interface | |||
// Validate the report data | |||
_validateReport(reportContext, report, rs, ss); | |||
|
|||
// Verify signatures attached to report | |||
_verifySignatures(reportContext, report, rs, ss, rawVs); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why it got moved? I have to be missing something, but isn't the main gas saving due to skipping this step if the report is already recorded?
Add same
epochAndRound
check to the contract and_checkRounds()
to the tests.