Macros to define subprotocol packet ids in chain sync #10341
Conversation
|
It looks like @elferdo signed our Contributor License Agreement. 👍 Many thanks, Parity Technologies CLA Bot |
|
Couldn't we have something like: #[derive(EnumMap)]
enum Packet {
#[packet = ETH_PACKET]
StatusMessage = 0x01,
...
#[packet = WARP_SYNC_PACKET]
GetSnapshotManifestPacket = 0x11,
}and |
|
You mean that the attribute |
|
That would be the idea yeah, if possible |
|
I think the syntax would need to look somewhat different, because attributes for derive-macros must be predefined, but I think we can achieve something along those lines. I'll look into it. For some reason I prefer closed solutions to open-ended ones, or at least try not to generalize too early, but I can't see any big downside to your idea right now. I would see, for example, that instead of |
Co-Authored-By: elferdo <elferdo@gmail.com>
Co-Authored-By: elferdo <elferdo@gmail.com>
|
@elferdo Can you update the PR description to reflect your recent changes? |
|
@ngotchac Oh, sure, sorry, I will update it right now. |
dvdplm
left a comment
There was a problem hiding this comment.
This looks pretty great! :)
One question though. If I try to use #[derive(SyncPackets)] on two enums I get this error:
24 | #[derive(SyncPackets, Clone, Copy, Debug, PartialEq)]
| ----------- previous import of the type `PacketId` here
...
30 | #[derive(SyncPackets, Clone, Copy, Debug, PartialEq)]
| ^^^^^^^^^^^
| |
| `PacketId` reimported here
| help: remove unnecessary import
Seems like a bug yeah?
Code:
#[derive(SyncPackets, Clone, Copy, Debug, PartialEq)]
enum Packets {
#[protocol(MY_PROTOCOL0)] Packet0 = 0x00,
#[protocol(MY_PROTOCOL1)] Packet1 = 0x01,
}
#[derive(SyncPackets, Clone, Copy, Debug, PartialEq)]
enum Bovine {
#[protocol(BEEF)] Bull = 0x00,
#[protocol(BEEF)] Cow = 0x01,
}
|
@elferdo It'd be good to have some module level docs here with an example or two. Pretty please? |
Sure! I'll address your two issues asap. |
The macro was designed with one specific use case in mind, namely that of putting all the p2p protocol IDs into one place. One of the restrictions these IDs must meet is that they are unique, and by allowing only one enum the language itself will take care of that.
I guess you don't want: right? Where is the other enum used? The solution to the problem is quite straightforward, I'm just wondering what the use case is. |
There isn't one, just me playing around with the code while reviewing it and noticing a surprising error message: I think the expectation is that a macro should work even when applied several times? If it becomes terribly complicated to fix, I'm fine with some good docs explaining how to go about applying the macro to several |
|
Just to be clear: I think this is a terrific improvement and I'm prepared to merge it even if imperfect, just as long as it's properly doc'd. :) |
No, not really, I already have it in place. My worries are that it gets abused and then all of a sudden we end up having, again, uncontrolled IDs. Like it should be obvious how to properly update IDs, or add a new one, and it should be difficult to make it wrong. Let's make it reusable, just in case. The code as it is should be obviously easy to maintain, and if someone wants it s/he can have it. |
So this is used in |
|
ping @elferdo |
dvdplm
left a comment
There was a problem hiding this comment.
On a second look I think this is fine as-is. My code example is clearly a misuse and while it'd be nice to get a good compiler error I also think that with good module-level docs and tests for bad usage this is good to go.
| // Arguments to invocation attributes are delivered as a list | ||
| match argument { | ||
| Meta::Word(_) => Err(syn::Error::new_spanned(input, "protocol attribute without argument")), | ||
| Meta::List(args) => parse_protocol_arguments(&args).map(|ok| ok.clone()), |
There was a problem hiding this comment.
Should this check that there's a single argument in the list as well?
There was a problem hiding this comment.
This is checked in parse_protocol_arguments, do you think here would be a better place?
|
@elferdo ping |
@elferdo please address the issues and reopen the pr :) |
This PR elaborates on comments by @tomusdrw in #10315
Synchronization of a node's blockchain with other nodes happens through an exchange of packets over the network. In parity we support a number of different synchronization protocols that are transmitted and received as devp2p subprotocols.
In devp2p, subprotocol and the particular message within it are identified with a single number instead of two, one for protocol and one for message. Care must be taken to ensure that each type of package within each subprotocol gets a globally unique id that does not collide with other subprotocols.
This PR is a first proposal of a derive-macro that can be applied to an enum and attributes for the enum variants. Code would possibly look like the following:
Benefits of the approach:
from_u8so that ids read from the network can be directly converted to the appropriate identifier.from_u8method returns anOption<Packet>PacketDrawbacks: