-
Notifications
You must be signed in to change notification settings - Fork 75
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
chore(sequencer)!: exclusively use Borsh encoding for stored data (ENG-768) #1492
base: main
Are you sure you want to change the base?
Conversation
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.
High level comment on the approach taken in this design:
At a high level, sequencer is defined by a set of components, each of which provides ways to change and read their respective state. So far this also meant that each component had full control over how the objects written to its state are converted to/from the domain types.
The storage
and stored_value
modules invert this logic by defining and passing in the on-disk types into the components.
I am ambivalent about this change since on the one hand it potentially allows avoiding code duplication. But on the other hand it breaks with the separation between the components we had so far.
I see that as one of the main problems with the existing approach. It's because we've allowed this flexibility that different components use different serialization for the same domain types. In a lot of cases, there is only the domain type - the component would serialize directly from the domain type into bytes. I'm very keen to remove that flexibility so that all components have to use
This is only temporary until #1436 is completed. When that work is completed, the components will be dealing with the domain types only.
Well, I don't think there's complete separation currently. For example, |
Summary
This PR primarily changes the encoding format of all data being written to storage to Borsh.
Background
We currently have a variety of different encoding formats, and this can be confusing, sub-optimal (in terms of storage space consumed and serialization/deserialization performance) and potentially problematic as e.g. JSON-encoding leaves a lot of flexibility in how the actual serialized data can look.
This PR is part one of three which aim to improve the performance and quality of the storage component. As such, the APIs of the various
StateReadExt
andStateWriteExt
extension traits were updated slightly in preparation for the upcoming changes. In broad terms, for getters this meant having ref parameters rather than value ones (even for copyable types like[u8; 32]
this is significantly more performant), and for "putters", parameters which are used for DB keys are refs, while the DB value parameters become values, since in the next PR these values will be added to a cache.Changes
storage
module. This will ultimately contain our own equivalents of thecnidarium
types, but for now consists only of a collection of submodules for types currently being written to storage. There is a top-level enumStoredValue
which becomes the only type being written to storage by our own code.astria-core
andastria-merkle
, some of these have been provided with constructors namedunchecked_from_parts
. This allows the type to be constructed from a trusted source like our own DB, skipping any validation steps which might otherwise be done.StateReadExt
andStateWriteExt
traits to use the newStoredValue
, which internally uses Borsh encoding.[u8; 32]
and[u8; 20]
arrays, and that has unfortunately made the PR larger than expected.serde
traits have had that removed, since it only existed to support JSON-encoding the type for storing. In one case it was for JSON-encoding to a debug log line, but I replaced that with aDisplay
impl.Testing
StateReadExt
andStateWriteExt
traits already had almost full coverage. Where coverage was missing, I added round trip tests.Breaking Changelist
Related Issues
Closes #1434.