Skip to content
This repository was archived by the owner on Nov 15, 2023. It is now read-only.

Conversation

@kianenigma
Copy link
Contributor

@kianenigma kianenigma commented Jun 23, 2019

Follow up on #2799 #2854.

  • Allows all three types of UnchckedExtrinsic to have a generic a tip enum field.
  • Optionally decoded to the tip upon receiving a tx. Default value if non-existent.
  • Visible to runtime/executive via a Tippable trait.

TODO:

  • Actually, use the tip value in validate_transaction to increase priority.
  • Check tip in the signature.
  • A dual node testnet fails now upon receiving a transaction in block_builder.rs due to an incorrect hash but all tests seem to pass which is kinda very bad. @tomusdrw @bkchr

WIP but pushed to get some initial feedback.

@kianenigma kianenigma added the A3-in_progress Pull request is in progress. No review needed at this stage. label Jun 23, 2019
Copy link
Contributor

@tomusdrw tomusdrw left a comment

Choose a reason for hiding this comment

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

I'd ditch the generic Balance from Tip if possible, and also please triple check that it's part of the signing payload.

/// The function that should be called.
pub function: Call,
/// The tip for this transaction
pub tip: Tip<Balance>,
Copy link
Contributor

Choose a reason for hiding this comment

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

You don't seem to modify fn check function and it's strictly required that tip is part of the payload we are signing. Otherwise you can change it arbitrarly and the signature would still be valid.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

right -- added to the todo list up top.

Copy link
Contributor

Choose a reason for hiding this comment

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

cc @jacogr formats are changing

Copy link
Contributor

Choose a reason for hiding this comment

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

As Jaco noticed we could bump version 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.

check is modified but I will keep the conversation open as a reminder that the extrinsic format has changed slightly.

@kianenigma
Copy link
Contributor Author

@tomusdrw two questions, one important and one more of a nit:

  • unimportant: Just some design decision:

    • Tip can actually be a field in a Signature tuple or SignatureContent struct. I'd say it works better as a separate field (as it is now). I've also added tip to chekc() and will push it soon.
    • Pass the tip also to CheckedExtrinsic (after check()) or not? I initially did this, then removed it. Functional-wise, it is not needed at all. Intuitive-wise, I think the clean approach is to have the tip a field in UncheckedExtrinsic (preferably non pub to depict that it is not checked with the sig yet) and then pass it to CheckedExtrinsic and implement Tippable for CheckedExtrinsic. Again, all of it seems to be optional and works fine as-is. (I will probably do this anyhow, my argument seems reasonable :p)
  • Important: The current situation forces all unsigned extrinsics to also have the tip field. Given your concerns of the tip to always be checked with the signature, Is that okay? The same new_unsigned() for UncheckedMortalCompactExtrinsic is also used somewhere related to inherents. I've so far ignored these details to get going faster but if you have some initial feedback, would be great.

@tomusdrw
Copy link
Contributor

Tip can actually be a field in a Signature tuple or SignatureContent struct. I'd say it works better as a separate field (as it is now). I've also added tip to chekc() and will push it soon.

I don't think it semantically fits the signature. Also note that to produce the Signature you need the Tip to be part of signing payload, which complicates it even further.

Pass the tip also to CheckedExtrinsic (after check()) or not? I initially did this, then removed it. Functional-wise, it is not needed at all. Intuitive-wise, I think the clean approach is to have the tip a field in UncheckedExtrinsic (preferably non pub to depict that it is not checked with the sig yet) and then pass it to CheckedExtrinsic and implement Tippable for CheckedExtrinsic. Again, all of it seems to be optional and works fine as-is. (I will probably do this anyhow, my argument seems reasonable :p)

I think we should do that yes. Tip should be validated (aka checked) if it's valid and only then it can actually be used for anything.
I think we shouldn't really be using anything from Unchecked* structs, since you never know if they are sound before you check them.

Important: The current situation forces all unsigned extrinsics to also have the tip field. Given your concerns of the tip to always be checked with the signature, Is that okay?

So with the current values of Tip enum (None, Sender) the validation part should make sure that if Signature is missing the Tip can't be Sender. If we ever decide to introduce a different type, i.e. Tip::PayedBy(Signature) then we can have an unsigned transaction with Tip containing a signature and that's totally valid. The question is if we want to support something like that.

@kianenigma
Copy link
Contributor Author

This can now be reviewed in more depth. There might still be some work on how the generic balance is handled but I consider that minor detail.

Once #2854 is stable and merged in with this I would like to add as many e2e tests as possible.

For now, my only manual, cumbersome testing method I had is broken due to this issue #2943. I think it is an important one actually.

@kianenigma kianenigma requested a review from tomusdrw June 27, 2019 16:47
@kianenigma kianenigma added A0-please_review Pull request needs code review. and removed A3-in_progress Pull request is in progress. No review needed at this stage. A4-gotissues labels Jun 27, 2019
// TODO: maximise (fee + tip) per weight unit here.
TransactionValidity::Valid {
priority: encoded_len as TransactionPriority,
priority: (encoded_len as TransactionPriority) + tip_value.saturated_into::<TransactionPriority>(),
Copy link
Contributor

Choose a reason for hiding this comment

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

I don't think this is correct. We seem to be adding a bytes length of the extrinsic and the value, but since MakePayment is generic, we don't really know how much each byte of encoded_len is worth, so it's hard to compare it directly with Balance.
I think MakePayment trait, should handle all this (maybe it requires a slight rename though):
fn make_payment(sender, encoded_len, tip) -> Result<Priority>;

So we make payment for both len and tip in one operation and we get the transaction priority back (or something that can be easily converted to priority).

@kianenigma kianenigma added A3-in_progress Pull request is in progress. No review needed at this stage. and removed A1-onice labels Jul 10, 2019
@kianenigma kianenigma requested review from rphmeier and tomusdrw July 10, 2019 09:44
@kianenigma
Copy link
Contributor Author

@rphmeier the road map would be that this will be included in substrate and soonish we can try out replacing the type UncheckedExtrinic = <unchecked_mortal_compact_tipped_extrinsic> in polkadot's runtime directly.

Lookup, Checkable, Extrinsic, SaturatedConversion};
use super::{CheckedExtrinsic, Era, Tip};

const TRANSACTION_VERSION: u8 = 2;
Copy link
Contributor

Choose a reason for hiding this comment

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

Should we use different versioning than UncheckedMortalCompactExtrinsic? Say, start with 1000 or sth.

Copy link
Contributor

@jacogr jacogr Jul 10, 2019

Choose a reason for hiding this comment

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

Not sure we can go that high :)

So the first byte is the encoded value, it is - signed flag & version, where signed flag is 0 for unsigned, or 0b10000000 for signed. So the lowest 7 bits indicate the version.

Tl;DR 127 max :)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

64?

Copy link
Contributor

Choose a reason for hiding this comment

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

Haha, right. I didn't notice it's only one byte :)

signed: Address,
signature: Signature,
era: Era,
tip: Option<Tip<Balance>>
Copy link
Contributor

Choose a reason for hiding this comment

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

should be required, since it's signed.

Suggested change
tip: Option<Tip<Balance>>
tip: Tip<Balance>,

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 my head it makes sense; a signed can say my tip is none (which is practically the same as saying my tip is Sender(0)) but it is still fine as long as it is provided in the byte stream and it can be decoded (afaik None is 0 or 0 0 when encoded?).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

ignore the above ^^ you're right.

Block: traits::Block<Header=System::Header, Hash=System::Hash>,
Context: Default,
Payment: MakePayment<System::AccountId>,
Balance: SimpleArithmetic + Copy,
Copy link
Contributor

Choose a reason for hiding this comment

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

Can't we use BalanceOf<Payment, System::AccountId> instead of additional generic type Balance?

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 indeed we actually don't need this anymore; taking your previous comment balance is now an associated type of make_payment; hence not really needed up here.

@kianenigma kianenigma added A0-please_review Pull request needs code review. and removed A3-in_progress Pull request is in progress. No review needed at this stage. labels Jul 10, 2019
@kianenigma kianenigma requested a review from tomusdrw July 10, 2019 17:40
@gavofyork
Copy link
Member

is Tip<Balance> compact encoded?

/// Most often this is:
/// - `None` if the unchecked extrinsic does not have a tip OR it is unsigned.
/// - `Some` if the opposite.
pub tip: Option<Tip<Balance>>,
Copy link
Member

Choose a reason for hiding this comment

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

should just be an additional arg in signed

Copy link
Contributor Author

Choose a reason for hiding this comment

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

could be moved there but you mean probably in unchecked_mortal_compact_tipped.rs (god, hate this name to type it)? I will also update here but this is not really important anymore.

pub struct CheckedExtrinsic<AccountId, Index, Call, Balance> {
/// Who this purports to be from and the number of extrinsics have come before
/// from the same signer, if anyone (note this is not a signature).
pub signed: Option<(AccountId, Index)>,
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 signed: Option<(AccountId, Index)>,
pub signed: Option<(AccountId, Index, Tip<Balance>)>,

Copy link
Member

Choose a reason for hiding this comment

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

it could theoretically be an option, but as long as it's compact encoded, then there's no point since zero compact encoded is a big as None encoded.

Copy link
Member

@gavofyork gavofyork Jul 10, 2019

Choose a reason for hiding this comment

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

Just make sure Tip<Balance> implements Default. For non-tipping chains, Tip<Balance> can be ().

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 it is part of the signature then it is only visible in signed txs which is the point of the current option. Hence, pub signed: Option<(AccountId, Index, Tip<Balance>)>, looks ok


/// A placeholder tip type that is used to fulfill the generic requirements of `checked_extrinsic`
/// when the underlying `unchecked_extrinsic` actually does not have a tip.
pub type NoTipBalance = u32;
Copy link
Member

Choose a reason for hiding this comment

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

why not ()?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Could not have it meet the type requirements of the generic type (has to be SimpleArithmetic-- probably doable but needs a more handy rust dev with more time -- will try)

pub function: Call,
/// The tip for this transaction. This is always `Some` for a signed transaction and always
/// `None` for unsigned.
pub tip: Option<Tip<Balance>>,
Copy link
Member

Choose a reason for hiding this comment

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

doesn't belong here since it's meaningless unless this is a (signed) transaction.

/// The signature, address, number of extrinsics have come before from
/// the same signer and an era describing the longevity of this transaction,
/// if this is a signed extrinsic.
pub signature: Option<(Address, Signature, Compact<Index>, Era)>,
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 signature: Option<(Address, Signature, Compact<Index>, Era)>,
pub signature: Option<(Address, Signature, Compact<Index>, Era, Tip<Balance>)>,

Copy link
Member

@gavofyork gavofyork left a comment

Choose a reason for hiding this comment

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

Types could do with reworking.

@kianenigma
Copy link
Contributor Author

will be closed by #3102

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

A0-please_review Pull request needs code review.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants