Skip to content

Wrapper around generic serdes methods #15451

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 1 commit into
base: develop
Choose a base branch
from

Conversation

kasey
Copy link
Contributor

@kasey kasey commented Jun 28, 2025

What type of PR is this?
Feature

What does this PR do? Why is it needed?

#15447 adds a set of generic methods for serdes on ssz lists of fixed or variable sized elements. This PR shows how we could wrap those methods up for more convenient use. The Marshal and Unmarshal methods retain the type safety of the direct methods but are less cumbersome, because they encapsulate the constructor function. As demonstrated here, we could just create one package level value for each type that needs this functionality.

Other notes for review

This PR is built directly on top of 15447 and we should only merge one of the two. I prefer this extra encapsulation but am making separate PRs for feedback on the design.

Acknowledgements

Copy link
Contributor

@potuz potuz left a comment

Choose a reason for hiding this comment

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

First pass. I would leave perhaps commented somewhere or perhaps add a new method for basic types, since these can be marshalled/unmarshalled by a localized unsafe cast that is much more efficient than the loop with memory copying.

Comment on lines 216 to 218
if nElems == 0 {
return nil, nil
}
Copy link
Contributor

Choose a reason for hiding this comment

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

This cannot happen, you already errored out if first < offsetLen and you are guaranteed to be a multiple by the check in line 208, so nElems is guaranteed to be >= 1

// provide the `newt` function that returns a new instance of the type [T] to be unmarshaled.
// This func will be called for each element in the list to create a new instance of [T].
//
// UnmarshalListFixedElement should be used for fixed-size elements.
Copy link
Contributor

Choose a reason for hiding this comment

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

This comment repeats the one for Variable size, do you want this to be variable sized?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Actually it's the other way around - my intention was for eg UnmarshalListFixedElement to refer you to UnmarshalListVariableElement for variable elements, and UnmarshalListVariableElement to refer you to UnmarshalListFixedElement for fixed elements.

Now I've noticed 😱 // UnmarshalListFixedElement unmarshals a ssz-encoded list of variable-sized elements.... I will double check all the comment and clean them up, thanks.

// looking ahead +1 (starting with a `buf` that has already had the first offset sliced off),
// with the final element handled as a special case outside the loop (using the size of the entire buffer
// as the ending bound).
previous := first
Copy link
Contributor

Choose a reason for hiding this comment

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

nit but you can just reuse first here since it is not used again.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

At first I just had a variable called previous, but I thought assignment to a new variable name improved readability.

// SSZ Lists have different encoding rules depending whether their elements are fixed- or variable-sized,
// and we can't differentiate them by the ssz interface, so it is the caller's responsibility to
// pick the correct method.
func UnmarshalListVariableElement[T Unmarshalable](buf []byte, newt func() T) ([]T, error) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Checked the logic of this function and it looks good and safe to me except the discussion offline

@kasey kasey force-pushed the generic-list-serdes-wrapper branch 2 times, most recently from ba7d971 to b51b06b Compare July 3, 2025 02:49
@kasey kasey force-pushed the generic-list-serdes-wrapper branch from b51b06b to fa6a09b Compare July 3, 2025 02:50
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