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

Conversation

@tomusdrw
Copy link
Contributor

@tomusdrw tomusdrw commented Aug 29, 2019

This PR introduces a helper types to construct, sign and submit transactions from within the runtime.

I've refactored the im-online code to use the new types and also created a way to submit signed transactions. That's going to be needed for instance for equivocation reporting.
Also all places where signatures where constructed (and hashed) are now replaced with SignedPayload. Proper typing on Extra also detected a bug in subkey (where the transfers did not contain the correct SignedExtensions payload).

Note that to actually use this API, the call needs to be invoked in the specific OffchainCall context.

@tomusdrw tomusdrw added A0-please_review Pull request needs code review. M4-core labels Aug 29, 2019
}
}

impl<Call, Extra> Encode for SignedPayload<Call, Extra> where
Copy link
Member

Choose a reason for hiding this comment

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

Why is this implementation required?

Copy link
Contributor Author

@tomusdrw tomusdrw Aug 30, 2019

Choose a reason for hiding this comment

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

The generic Signer works on anything that is Encode. I'll rather remove the using_encoded function, I've only added it to be able to document the behavior.

Copy link
Member

Choose a reason for hiding this comment

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

You can also put documentation on top of a trait implementation. It will be shown in rustdocs as welll.

/// Get an encoded version of this payload.
///
/// Payloads longer than 256 bytes are going to be `blake2_256`-hashed.
pub fn using_encoded<O>(&self, f: impl FnOnce(&[u8]) -> O) -> O {
Copy link
Member

Choose a reason for hiding this comment

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

Maybe we should give this a different name?

/// is going to be different than the `SignaturePayload` - so the thing the extrinsic
/// actually contains.
pub struct SignedPayload<Call, Extra: SignedExtension> {
raw_payload: (
Copy link
Contributor

Choose a reason for hiding this comment

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

I could not find a reason but I just wonder if you also argued/tought of making this a flat struct rather than one with a single element of a tuple? or is there a strong reason?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yeah, makes sense. I guess, arguably self.raw_payload.using_encoded is more readable than self.0, but indeed it feels simpler to avoid naming it.

type ReportLatency = ReportLatency;
}

impl system::offchain::CreateTransaction<Runtime, UncheckedExtrinsic> for Runtime {
Copy link
Contributor

Choose a reason for hiding this comment

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

where is this being used?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

We pass this as SubmitTransaction to im-online:

type SubmitTransaction = TransactionSubmitter<ImOnlineId, Runtime, UncheckedExtrinsic>;

(see Runtime as the second parameter)


impl<Account, Signature, AppPublic> Signer<Account, Signature> for AppPublic where
AppPublic: RuntimeAppPublic + From<Account>,
AppPublic::Signature: Into<Signature>,
Copy link
Contributor

Choose a reason for hiding this comment

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

I am a bit unclear on these new crypto types: what do the bounds here translate to? Who will end up having this impl?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

My understanding:

So we have a low-level crypto types (like sr25519 and ed25519) that are commonly used within the "core" runtime part (as AccountId, etc).

We also have application-specific crypto types, which are basically wrappers for the low-level types with additional information about the module (i.e. application) they are coming from.

So for instance, im-online is (or may be) using sr25519 as the crypto type, but instead of sr25119::Public you will rather use im_online::app::Public, as this type has additional APP_ID identification to know it's coming from im_online module.
The APP_ID is very useful especially when querying the Keystore cause we might have many sr25519 keys, but only one (or some) of them will be the one used by im_online module.

So the bounds here basically say:

Please let me know the application-specific crypto type that you want to use for a particular Account.

Now that I think of it, in the future it might actually be better to use AppPublic instead of Account right from the start (i.e. when we initiate the signing), rather then convert in the middle of the process.
I'll refactor this if I find it more convenient to use that way, when equivocations reporting will be implemented.

println!("Using a genesis hash of {}", HexDisplay::from(&genesis_hash.as_ref()));

let raw_payload = (
let raw_payload = SignedPayload::from_raw(
Copy link
Contributor

@kianenigma kianenigma Aug 30, 2019

Choose a reason for hiding this comment

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

great that this was identified! I exactly had in on a personal todo list to: check subkey with signed extension.

If not here, at some point I would like to add some tests to it to make sure subkey is always generating stuff that can be verified by node (if that's a correct assumption).

Copy link
Contributor

@kianenigma kianenigma left a comment

Choose a reason for hiding this comment

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

Just a bunch of questions; looks good!

Copy link
Contributor

@andresilva andresilva left a comment

Choose a reason for hiding this comment

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

LGTM. So the idea is that when we use these APIs for equivocation reporting we'll have to call them under offchain context?

@tomusdrw
Copy link
Contributor Author

@andresilva yes. There is a special OffchainCall context (see #3454) and you can specify the desired capabilities (for this you'd need Keystore and TransactionPool).

@gavofyork gavofyork merged commit 25eb50f into master Sep 1, 2019
@gavofyork gavofyork deleted the td-signing branch September 1, 2019 00:19
jimpo pushed a commit to jimpo/substrate that referenced this pull request Sep 3, 2019
* Abstract constructing extrinsic and signing.

* Initial impl of signer.

* Implement get payload.

* Clean up the code.

* Improve docs.

* Bump version.

* Update core/sr-primitives/src/generic/unchecked_extrinsic.rs

Co-Authored-By: Bastian Köcher <[email protected]>

* Fix tests & address grumbles.

* Fix build.

* Fix runtime tests.

* Fix bound test.

* Fix bound test.
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.

6 participants