Skip to content
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

Make relay CLI generic #849

Merged
merged 21 commits into from
Apr 1, 2021
Merged

Make relay CLI generic #849

merged 21 commits into from
Apr 1, 2021

Conversation

tomusdrw
Copy link
Contributor

@tomusdrw tomusdrw commented Mar 30, 2021

The purpose of this PR is to make it easy to add new chains. It's a follow up on #734.

Initially I thought that we can orient the CLI around various bridges/chains and simply duplicate the code responsible for handling the CLI commands (see src/rialto_millau module). Later on I figure that it's quite a lot of code to duplicate, but was still hoping that we can get around this by using some macros.
However since the code is split into multiple files it's not that trivial to macro-ify the code + it heavily reduces readability and ability to debug errors.

This PR introduces a different approach, where we try to keep the code generic enough so that a lot of code can be shared without introducing a macro, but all the things that are difficult to make generic, or depend on particular sourceNetwork-targetNetwork bridge pair are resolved via macro-shared code.

The most important part of the PR is the select_bridge! macro, which allows us to write some $generic code, without actually naming all of the types (which would be hard).
I've refactored RelayHeaders and InitBridge for now, but since the PR is getting quite big, I've decided to make it a draft and let you decide if I should continue or if we rather review & merge like this and change the rest in a follow up PR.

There is a bunch of unaddressed and unassigned TODOs for now, and most likely some bash scripts require updating as well.

Follow up tasks:

  • Remove target-specific stuff from CliChain.
  • Support multiple bridges in BridgeSendMessage Call.
  • Remove source_* target_* CLI methods (e.g. add Into<ConnectionParams>)
  • Consider using structopt renames for Singing and Connection parameters.
  • Create arg-enum-like macro with kebab-case support or use existing proc-macro crates.

@tomusdrw tomusdrw requested review from svyatonik and HCastano March 30, 2021 15:22
Copy link
Contributor

@HCastano HCastano left a comment

Choose a reason for hiding this comment

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

I didn't have the brainpower to look at this as in depth as I wanted to today. I do have a couple of thoughts though:

  • My gut says no to the macros, but it might just be PTSD from the Substrate ones
  • Please don't refactor the whole CLI in this PR, the diff is already large enough 😄

I'll also try and do some thinking about how we can architect this so that multi-network support isn't such a pain

Copy link
Contributor

@HCastano HCastano left a comment

Choose a reason for hiding this comment

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

In general it looks all right.

Before we merge this I would like to see the TODOs have issues attached to them so any of us can pick them up and help with this effort.

I'll take another look after this leaves the draft state.

spec_name: sp_version::create_runtime_str!("westend"),
impl_name: sp_version::create_runtime_str!("parity-westend"),
authoring_version: 2,
spec_version: 50,
Copy link
Contributor

Choose a reason for hiding this comment

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

Do we need to make sure we keep up with the spec_version changes in the Westend runtime?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yup, but I think it will be covered by a test in Polkadot repo. Alternatively the relayer could query a running node and make sure this matches.

relays/bin-substrate/src/cli/init_bridge.rs Outdated Show resolved Hide resolved
relays/bin-substrate/src/cli/init_bridge.rs Outdated Show resolved Hide resolved

/// Bridge Message Payload type.
///
/// TODO [ToDr] This should be removed in favour of target-specifc types.
Copy link
Contributor

Choose a reason for hiding this comment

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

Can you elaborate on what you mean here?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

In case we have multiple bridges the MessagePayload type will be different.
For instance for RialtoToWestend and RialtoToMillau the MessagePayload and encode_call will look quite differently.
The TODO is there cause it's not the right way to abstract the code, however since right now we don't have a chain with two bridges that include MessageLanes it's good enough, but I already have an idea how to improve it, hence the TODO.


/// Numeric value of SS58 format.
fn ss58_format() -> u16;

/// Parse CLI call and encode it to be dispatched on this specific chain.
fn encode_call(call: crate::rialto_millau::cli::Call) -> Result<Self::Call, String>;
Copy link
Contributor

Choose a reason for hiding this comment

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

Shouldn't this call type be generic?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

If you mean the fact that it has rialto_millau in the module path, then yes. The Call is in fact already generic, but I wanted to avoid moving all the types to top-level cli/mod.rs file just yet. Will be fixed later when the rialto_millau module is dissolved.

@@ -19,68 +19,24 @@
use frame_support::weights::Weight;
Copy link
Contributor

Choose a reason for hiding this comment

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

With your follow up PRs this file will end up being replaced by an enum + macro combo, right?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Each sub-command will have it's own module in src/cli/ and there is going to be less duplication. I expect the entire file to be removed after the refactor is finished.

relays/bin-substrate/src/rialto_millau/cli.rs Outdated Show resolved Hide resolved
}
}
}

async fn run_relay_messages(command: cli::RelayMessages) -> Result<(), String> {
match command {
cli::RelayMessages::MillauToRialto {
Copy link
Contributor

Choose a reason for hiding this comment

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

This will be macro-ified too, right?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yup. I initially started off with trying to extract the common parts, so that both branches look the same. After that I started moving the code to make it generic, but these commands are still left to do.

///
/// This will change the `ss58format` of the account to match the requested one.
/// Note that a warning will be produced in case the current format does not match
/// the requested one, but the conversion always succeeds.
pub fn enforce_chain<T: AccountChain>(&mut self) {
pub fn enforce_chain<T: CliChain>(&mut self) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Looking back at it I'm not sure if enforce is the right word to use here, considering that even if the expected format doesn't match this call still "succeeds" (by converting to the right address format)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

What do you suggest then? force_convert::<Rialto>()?

}
}

impl AccountChain for Rialto {
const NAME: &'static str = "Rialto";
impl CliChain for Westend {
Copy link
Contributor

Choose a reason for hiding this comment

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

This impl should probably have an issue attached to it

Copy link
Contributor Author

Choose a reason for hiding this comment

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

How so? We don't really support Westend, the fact that we can't implement all methods means the abstraction is not fine-grained enough (i.e. there are sub-commands that are not even available for westend, but the trait is shared between sub-commands), but I would rather go with coarse abstraction and later on split it if it turns out to be correct.

@tomusdrw tomusdrw marked this pull request as ready for review March 31, 2021 19:24
@adoerr adoerr self-requested a review April 1, 2021 05:37
/// A call to the Rialto Bridge Messages pallet to send a message over the bridge.
RialtoSendMessage {
// TODO [#853] Support multiple bridges.
/// A call to the specific Message Lane pallet to send a message over the bridge.
Copy link
Contributor

Choose a reason for hiding this comment

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

Quote from #853:

Currently the Call CLI enum, supports BridgeSendMessage variant. However in case there are multiple bridges on one source chain, we need to specify what Target chain we want to send the message to.

I'm a bit confused now - I thought that this variant is to call over the bridge the other bridge (deployed on the target chain) to send other message. So it may be Source --- (M1) ---> Target --- (M2) ---> Source or Source1 --- (M1) ---> Target --- (M2) ---> Source2 iiuc. So the quote should be the "multiple bridges on the target chain", no?

I guess it was introduced in the PR about printing encoded messages, so it isn't actually used in messages sending. In practice it is only used by the encode-call subcommand. But since it is available to the send-message command as well, maybe it worth at least to expand docs a bit - e.g instead of "specific Message Lane pallet" say "Message Lane pallet on the target chain", for payload change it to the "encoded Call of the source chain", etc.

P.S.: 'Message Lane pallet' is also changed to 'Messages pallet' everywhere ;)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, that's a good point. Indeed I was thinking about it from the encode-call perspective, I'll update the docs.

Copy link
Contributor

@adoerr adoerr left a comment

Choose a reason for hiding this comment

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

For me, this goes into the right direction. If anything, I want to see more of this approach. My kind of ideal in the end would be having a bridge procedural macro, similar to the pallet macro. Basically generating a specific bridge implementation, batteries (CLI) included.

So I 'approve' but keep this as comment only.

}

macro_rules! select_bridge {
($bridge: expr, $generic: tt) => {
Copy link
Contributor

Choose a reason for hiding this comment

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

generic is generic here in the sense that it can be an arbitrary closure?

}

macro_rules! select_bridge {
($bridge: expr, $generic: tt) => {
Copy link
Contributor

Choose a reason for hiding this comment

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

Same here w.r.t. to generic.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It's actually not a closure, but a piece of arbitrary code that will use generic parameters type Source =/ type Target = that is set in the particular branch of match statement.

@@ -42,6 +42,19 @@ pub enum Error {
Custom(String),
}

impl std::error::Error for Error {
Copy link
Contributor

Choose a reason for hiding this comment

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

Perhaps we can agree on using the thiserror / anyhow combo for all our errors and start migrate towards this.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, logged here #857

@tomusdrw tomusdrw merged commit 2a07bd5 into master Apr 1, 2021
@tomusdrw tomusdrw deleted the td-relay-macro branch April 1, 2021 10:49
@tomusdrw tomusdrw mentioned this pull request Apr 3, 2021
svyatonik pushed a commit that referenced this pull request Jul 17, 2023
* ERCSC

* update

* Update Substrate & Polkadot

Co-authored-by: doordashcon <[email protected]>
Co-authored-by: Bastian Köcher <[email protected]>
serban300 pushed a commit to serban300/parity-bridges-common that referenced this pull request Mar 27, 2024
* Start generalizing rialto-millau commands.

* cargo fmt --all

* Introduce generic balance.

* Unify message payloads.

* cargo fmt --all

* init - generic

* Attempt to unify send message.

* Start moving things around.

* cargo fmt --all

* Move init-bridge.

* cargo fmt --all

* Improve UX of bridge argument.

* Fix clippy.

* Fix docs and scripts.

* Add docs.

* Apply suggestions from code review

Co-authored-by: Hernando Castano <[email protected]>

* Fix copyright.

* Add issue numbers.

* More todos.

* Update comments.

Co-authored-by: Hernando Castano <[email protected]>
serban300 pushed a commit to serban300/parity-bridges-common that referenced this pull request Apr 8, 2024
* Start generalizing rialto-millau commands.

* cargo fmt --all

* Introduce generic balance.

* Unify message payloads.

* cargo fmt --all

* init - generic

* Attempt to unify send message.

* Start moving things around.

* cargo fmt --all

* Move init-bridge.

* cargo fmt --all

* Improve UX of bridge argument.

* Fix clippy.

* Fix docs and scripts.

* Add docs.

* Apply suggestions from code review

Co-authored-by: Hernando Castano <[email protected]>

* Fix copyright.

* Add issue numbers.

* More todos.

* Update comments.

Co-authored-by: Hernando Castano <[email protected]>
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.

4 participants