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

Introduce CreateBare, deprecated CreateInherent #7597

Open
wants to merge 19 commits into
base: master
Choose a base branch
from

Conversation

gui1117
Copy link
Contributor

@gui1117 gui1117 commented Feb 18, 2025

Rename CreateInherent to CreateBare, add method create_bare and deprecate create_inherent.

Both unsigned transaction and inherent use the extrinsic type Bare.
Before this PR CreateInherent trait was use to generate unsigned transaction, now unsigned transaction can be generated using a proper trait CreateBare.

How to upgrade:

  • Change usage of CreateInherent to CreateBare and create_inherent to create_bare.
  • Implement CreateBare for the runtime, the method create_bare is usually implemented using Extrinsic::new_bare.

@gui1117 gui1117 requested a review from a team as a code owner February 18, 2025 05:13
@gui1117 gui1117 added the R0-silent Changes should not be mentioned in any release notes label Feb 18, 2025
@@ -489,8 +489,14 @@ pub trait CreateSignedTransaction<LocalCall>:
}

/// Interface for creating an inherent.
///
/// It can also be used to create an unsigned transaction as they are both the same extrinsic
/// variant: `Bare`. Unsigned transaction are deprecated in favor of general transaction.
pub trait CreateInherent<LocalCall>: CreateTransactionBase<LocalCall> {
Copy link
Member

Choose a reason for hiding this comment

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

The naming is still just wrong and trying to fix this via docs is not making it better. As I already said in the original pr, the name of the trait is wrong.

I would propose we introduce a new CreateBare with proper docs and tag this trait deprecated.

Copy link
Contributor Author

@gui1117 gui1117 Feb 19, 2025

Choose a reason for hiding this comment

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

I updated the PR: deprecate CreateInherent, introduce CreateBare and replace all usage in polkadot-sdk.

It is a breaking change so I am not sure I can backport anything to 2412, but I will backport it to 2503.

I acknowledge my mistake in transaction extension review, also overall I underestimated the stability and the pace of new feature in polkadot-sdk in 2024.

As a side note I think offchain traits could be improved as well:

  • we could remove LocalCall everywhere, people can bound RuntimeCall: From<Call> in their config
  • CreateTransactionBase could simply bound frame_system::Config as supertrait instead of having a duplicated associated type RuntimeCall that bring name conflict. (We do bound Config as supertrait for SigningTypes).
    But better not to break them.

Copy link
Contributor

Choose a reason for hiding this comment

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

I agree with the offchain trait refactor, but it's probably best to do it after phase 2 of Extrinsic Horizon is done.

@gui1117 gui1117 requested a review from acatangiu as a code owner February 19, 2025 01:38
@gui1117 gui1117 changed the title Improve doc for unsigned transaction WIP: Introduce CreateBare, deprecated CreateInherent Feb 19, 2025
@paritytech-review-bot paritytech-review-bot bot requested a review from a team February 19, 2025 01:39
@gui1117 gui1117 added T1-FRAME This PR/Issue is related to core FRAME, the framework. and removed R0-silent Changes should not be mentioned in any release notes labels Feb 19, 2025
@gui1117 gui1117 changed the title WIP: Introduce CreateBare, deprecated CreateInherent Introduce CreateBare, deprecated CreateInherent Feb 19, 2025
@@ -571,7 +576,7 @@ pub trait SendSignedTransaction<
}

/// Submit an unsigned transaction onchain with a signed payload
pub trait SendUnsignedTransaction<T: SigningTypes + CreateInherent<LocalCall>, LocalCall> {
pub trait SendUnsignedTransaction<T: SigningTypes + CreateBare<LocalCall>, LocalCall> {
Copy link
Member

Choose a reason for hiding this comment

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

If you change this, it basically means that people may have CreateInherent implemented, but it will not be used by anything.

Copy link
Member

Choose a reason for hiding this comment

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

Basically also resulting in compile errors.

Copy link
Contributor Author

@gui1117 gui1117 Feb 20, 2025

Choose a reason for hiding this comment

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

If we do this, runtime will have to implement CreateInherent with the intention of creating a bare extrinsic.

It is ok to me, and the least breaking change, but it keeps the faulty trait usage: CreateInherent, I will also add in the doc of CreateInherent the intention.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I updated the code:

  • CreateInherent has a new method create_bare with default implementation. User can override it to specify the behavior. (not ideal but not a breaking change.)
  • CreateBare is introduced, automatically implemented for CreateInherent using CreateInherent::create_bare.
  • CreateBare is used instead of CreateInherent for SendUnsignedTransaction and it implementation for Signer.
  • pallets such as beefy are not using CreateBare in their trait bound to avoid any breaking change.
  • User are expected to implement CreateInherent for their runtime in order to keep pallet's usage.
  • User are expected to use CreateBare in their pallet, the idiomatic trait to create a bare extrinsic.

Possible alternative design: slightly more breaking, but provides a path forward:

  • I considered deprecated CreateInherent and use CreateBare in polkadot-sdk pallets. That would be a breaking change: e.g. if a pallets bounds beefy config and use T::create_inherent method then their code then it won't compile. They have to use create_bare and import CreateBase trait in scope. (note: we could introduce CreateBare::create_inherent so that rustc give some hint to import the trait in scope.)

Copy link
Contributor

Choose a reason for hiding this comment

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

I think it's ok as it is right now, fixes the name and helps the dev a bit with the default impl.

@paritytech-review-bot paritytech-review-bot bot requested a review from a team February 24, 2025 01:07
@gui1117
Copy link
Contributor Author

gui1117 commented Feb 24, 2025

/cmd fmt

@@ -489,9 +483,37 @@ pub trait CreateSignedTransaction<LocalCall>:
}

/// Interface for creating an inherent.
///
/// Implement this trait for the runtime but use `CreateBare` instead.
/// This trait is defined to avoid a breaking change, and it automatically implements `CreateBare`.
pub trait CreateInherent<LocalCall>: CreateTransactionBase<LocalCall> {
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
pub trait CreateInherent<LocalCall>: CreateTransactionBase<LocalCall> {
#[deprecated(note = "Please use `CreateBare` instead")]
pub trait CreateInherent<LocalCall>: CreateTransactionBase<LocalCall> {

Copy link
Contributor Author

@gui1117 gui1117 Feb 27, 2025

Choose a reason for hiding this comment

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

Then I will also change usage of CreateInherent to CreateBare in pokadot-sdk, in pallets (and runtime but this is less important).

EDIT: otherwise runtime implementing only CreateBare won't be able to use like election-solution pallet which uses CreateInherent.

Copy link
Member

Choose a reason for hiding this comment

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

EDIT: otherwise runtime implementing only CreateBare won't be able to use like election-solution pallet which uses CreateInherent.

I mean you can still implement CreateInherent, just with a allow(deprecated).

Copy link
Contributor

@georgepisaltu georgepisaltu left a comment

Choose a reason for hiding this comment

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

If it only took a couple of months before full adoption of the new interface, this trait would eventually end up only being used to create inherents. We expected the transition period to be much shorter than what it seems it will be, which is a miss on my end definitely.

In order to prevent similar situations in the future, we should push to get out of this "limbo" stage where the feature is partially complete and unsigned extrinsics are still around but so are bare extrinsics and inherents. We should start by delivering phase 2 of Extrinsic Horizon, implemented in #6324 #6325 #6326, to finally get rid of unsigned transactions and become consistent again regarding the terminology we use.

@@ -489,8 +489,14 @@ pub trait CreateSignedTransaction<LocalCall>:
}

/// Interface for creating an inherent.
///
/// It can also be used to create an unsigned transaction as they are both the same extrinsic
/// variant: `Bare`. Unsigned transaction are deprecated in favor of general transaction.
pub trait CreateInherent<LocalCall>: CreateTransactionBase<LocalCall> {
Copy link
Contributor

Choose a reason for hiding this comment

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

I agree with the offchain trait refactor, but it's probably best to do it after phase 2 of Extrinsic Horizon is done.

@@ -571,7 +576,7 @@ pub trait SendSignedTransaction<
}

/// Submit an unsigned transaction onchain with a signed payload
pub trait SendUnsignedTransaction<T: SigningTypes + CreateInherent<LocalCall>, LocalCall> {
pub trait SendUnsignedTransaction<T: SigningTypes + CreateBare<LocalCall>, LocalCall> {
Copy link
Contributor

Choose a reason for hiding this comment

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

I think it's ok as it is right now, fixes the name and helps the dev a bit with the default impl.

@gui1117
Copy link
Contributor Author

gui1117 commented Mar 3, 2025

It doesn't work either, because CreateBare takes a generic so we can't implement it directly when it is derived automatically for CreateInherent:

error[E0119]: conflicting implementations of trait `frame_system::offchain::CreateBare<_>` for type `mock::Test`
  --> substrate/frame/sassafras/src/mock.rs:59:1
   |
59 | / impl<C> frame_system::offchain::CreateBare<C> for Test
60 | | where
61 | |     RuntimeCall: From<C>,
   | |_________________________^
   |
   = note: conflicting implementation in crate `frame_system`:
           - impl<LocalCall, T> frame_system::offchain::CreateBare<LocalCall> for T
             where T: CreateInherent<LocalCall>;
   = note: downstream crates may implement trait `frame_system::offchain::CreateInherent<_>` for type `mock::Test`

For more information about this error, try `rustc --explain E0119`.
error: could not compile `pallet-sassafras` (lib test) due to 1 previous error

So instead I just renamed the trait CreateInherent to CreateBare, deprecated the method create_inherent and added the method create_bare, people updating their code will have a compile error saying create_bare is not implemented, I think it is fine because it is very easy to implement. Other than that there is no breaking change.

The deprecation of a reexport doesn't work in rust, but the doc show the rename so if people use an IDE they will see the trait is renamed.

image

@paritytech paritytech deleted a comment from github-actions bot Mar 4, 2025
@paritytech paritytech deleted a comment from github-actions bot Mar 4, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
T1-FRAME This PR/Issue is related to core FRAME, the framework.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants