Skip to content

Filter out redundant attestations in input builder #100

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

Open
wants to merge 5 commits into
base: main
Choose a base branch
from

Conversation

willemolding
Copy link
Collaborator

Modifies the input builder to be more intelligent and skip adding attestations once it has detected enough to meet the super-majority requirement.

This requires the input builder to receive a little more information, namely the config that the guest is using and a state reader.

No changes to the guest code are included in this PR except for exporting some functions from core.


This will make quite a significant different to both the input size and the cycle count as extra attestations means more expensive signature checks. When the chain is receiving near 100% participation (as is typical) and our threshold is set to 85% we expect close to a 15% improvement with this one simple trick.

@willemolding willemolding requested a review from a team as a code owner July 4, 2025 05:16
Copy link
Collaborator

@Wollac Wollac left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you have the actual performance numbers for this?
It's not easy to determine which transactions are necessary for balance drift, etc., so I've always been reluctant to do this and discard valid attestations.

Comment on lines 54 to 57
#[error("Error in called verify method: {0}")]
VerifyError(#[from] z_core::VerifyError),
#[error("Arithmetic error")]
Arith(safe_arith::ArithError),
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Usu

Suggested change
#[error("Error in called verify method: {0}")]
VerifyError(#[from] z_core::VerifyError),
#[error("Arithmetic error")]
Arith(safe_arith::ArithError),
#[error("Error in called verify method")]
VerifyError(#[from] z_core::VerifyError),
#[error("Arithmetic error: {0:?}")]
ArithError(safe_arith::ArithError),

Usually the best practice is to not use any {} when there is a #[from] or #[source], because then std error chaining can and will be used.
Otherwise use it.
we call this ArithError anywhere else, so we should do the same here.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See changes

}
}

pub struct InputBuilder<'a, E, CR, SR> {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since this has a lifetime now anyways, lets also use chain_reader: &'a CR,

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See changes

) -> Result<Vec<Attestation<E>>, InputBuilderError> {
let active_validators: BTreeMap<_, _> = self
.state_reader
.active_validators(target_epoch)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not correct in general. Only if the ssz reader or an equivalent reader is used. The host reader uses the active balance information about the actual epoch and not only the trusted epoch, so this might significantly diviate.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah right yes. I have never been happy about how the expected behavior of StateReader is different depending on the type and this is a great example of why it is kind of dangerous. I think using the SszReader and then also sharing the committee cache is a workable solution for now

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've changed how the host state reader operates so now it has a trusted epoch the same as the others. On the plus side this allowed me to remove the hack in AssertStateReader as the results from reading the validators matches now.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Alternative approach. This just grabs the balances and slashed status from the trusted state which replicates the SSZ Reader approach for the values used in this function. It is also much simpler than trying to modify the Host reader

@willemolding willemolding requested a review from Wollac July 6, 2025 06:28
Wollac
Wollac previously approved these changes Jul 6, 2025
Copy link
Collaborator

@Wollac Wollac left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not a fan of modifying the active validators returned by the HostStateReader. I liked the idea that it always returns the actual, correct values of the state. Removing this property seems error-prone and inconsistent to me.
One compromise I could accept is modifying the returned iterator in the input_builder for this purpose only.

@Wollac Wollac self-requested a review July 6, 2025 19:55
@Wollac Wollac dismissed their stale review July 6, 2025 19:55

misclick, didn't properly review it yet.

@Wollac Wollac marked this pull request as draft July 7, 2025 17:12
@willemolding willemolding marked this pull request as ready for review July 10, 2025 02:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants