-
Notifications
You must be signed in to change notification settings - Fork 2.7k
Refactor Transaction through runtime & primitives #92
Comments
The rationale for this is based on the idea that the runtime implementation is a user of these transaction types as opposed to their owner. We can imagine a tree
for example. That said, I don't think it's terrible to have crates which are meant to interact with the runtime just link to it and import the types. What I would really like to avoid is any kind of partial deserialization where we just pass bytes into submodules over and over again. StartPublicReferendum(Box<Proposal>, Format) IMO this is actually the correct way to express this relationship in Rust. The alternative is to replace the We should steer away from types which can't be resolved at deserialization time in general. Although in this specific case we might just want to consider splitting off It should be possible to create a generic solution that handles the sub-dispatch to modules. |
The real dependency graph is actually this:
By placing |
I understand your reticence (as a good and loyal rustacean) to use serialised data any more than the strict minimum. However, I fear this attitude is rather throwing the rest of the design under the bus for the sake of a fuzzy feeling that you're doing things by the book. Option 2 would result in one fewer allocation (since you'd never need to fart around with |
This sentiment scares me a lot more than late deserialisation. |
Fill documentation in some TODOs
* create SignedPayload struct * align with generic extra updates Co-authored-by: bwty <whalelephant@users.noreply.github.com>
The
primitives
crate is a dependency of theruntime
crate. Yet theTransaction
type defined inprimitives
, semantically depends on the contents ofruntime
since it expresses all callable endpoints withinruntime
in a strongly typed manner.This combination has a number of problematic side effects:
primitives
crate. If the type hasimpl
logic, then that must be moved too (even if it's highly specialised and not very "primitive") or some other acrobatics used to circumvent.Furthermore, requiring a strongly-typed dispatch at all implies another facepalm: Some endpoints themselves proxy a further dispatchable "proposal", causing a self-reference that means a bare type in the
enum
cannot be used and further allocations are needed. i.e.must become
StartPublicReferendum(Box<Proposal>, Format),
.Aside from these specific side-effects which are cause pain right now, the general ramifications of this leaving this unfixed are a tendency towards spaghetti references and monolithic code.
There are three ways of going that I can see:
1a. Move
Transaction
(and all that depend on it, likeBlock
) toruntime
. This would keep the current types as they are, but leaveprimitives
to be just the super-low-level types andruntime
to be the crate to be imported if high-level typing was needed.1b. Move
Transaction
(and all that depend on it, likeBlock
) to some other module (e.g.highlevel
). This would keep the current types as they are, but leaveprimitives
to be just the super-low-level types.highlevel
would depend onruntime
and be the crate to be imported.2. Avoid making
Transaction
typed around any runtime-dependent information.Transaction
would be more like in Ethereum where the dispatch element is just a byte blob to be interpreted at (or just before) the time of dispatch, not when the transaction is being initially deserialised. This fixes all problems including theProposal
-within-a-Proposal
issue.My preference is for option 2, moving away from this attempt to bake the dispatch logic into the type system, which seems to be forcing such problems on us. Aside from the great view from the ivory tower, I see no great need to represent the dispatch data under strong types prior to the time of dispatch.
CC @rphmeier
The text was updated successfully, but these errors were encountered: