Skip to content
This repository was archived by the owner on Nov 15, 2023. It is now read-only.
Merged
Changes from 1 commit
Commits
Show all changes
131 commits
Select commit Hold shift + click to select a range
b92c4e1
New approach to offchain signing.
tomusdrw Feb 25, 2020
c27c7bd
Use in im-online
tomusdrw Feb 26, 2020
1b817e3
Rewrite to use Account<T>
tomusdrw Feb 26, 2020
c1e4fb1
DRY signing.
tomusdrw Feb 26, 2020
033a325
Implement send_raw_unsigned_transaction
rakanalh Feb 26, 2020
459c5dd
WiP
tomusdrw Mar 2, 2020
8f7f9ae
Merge.
tomusdrw Mar 2, 2020
f1b2d62
Expunge LocalCall
tomusdrw Mar 2, 2020
e4db565
Expunge LocalCall
tomusdrw Mar 2, 2020
3e11852
Fix compilation.
tomusdrw Mar 2, 2020
726061b
Solve call.
tomusdrw Mar 2, 2020
6bce38e
Make it compile again.
tomusdrw Mar 2, 2020
775df42
Finalize implementation.
tomusdrw Mar 2, 2020
930a7cb
Change CreateTransaction
tomusdrw Mar 2, 2020
31846d9
Clear CreateTransaction.
tomusdrw Mar 2, 2020
25896f0
Add price payload
rakanalh Mar 3, 2020
a62d00d
Send raw transaction
rakanalh Mar 3, 2020
71325fb
Submit signed payload / unsigned transaction (WIP)
rakanalh Mar 3, 2020
3324ef7
Supertrait requirements on T::Signature
rakanalh Mar 3, 2020
b58512c
Validate signature of payload on an unsigned transaction
rakanalh Mar 3, 2020
b850dfd
Fix encoding - part 1
rakanalh Mar 3, 2020
1c8281a
Merge branch 'master' into td-offchain-signing
tomusdrw Mar 3, 2020
5aa5f0f
Make it compile.
tomusdrw Mar 3, 2020
59ce1ba
Fix compilation of unsigned validator.
tomusdrw Mar 3, 2020
748d065
Pass price payload to the transaction
rakanalh Mar 3, 2020
b4e7d43
Merge branch 'td-offchain-signing' of github.com:paritytech/substrate…
rakanalh Mar 3, 2020
064812d
Make block number part of the signed payload
rakanalh Mar 3, 2020
88c95b3
Send signed transaction
rakanalh Mar 4, 2020
83fe399
Implement all_accounts, any_account
rakanalh Mar 4, 2020
e46b0ee
Fix formatting
rakanalh Mar 4, 2020
763f1d9
Implement submit_transaction
rakanalh Mar 4, 2020
eb28754
Submit signed transaction (ForAll, ForAny)
rakanalh Mar 4, 2020
2e27baa
Fix formatting
rakanalh Mar 6, 2020
5c86a37
Implement CreateSignedTransaction
rakanalh Mar 6, 2020
6c3f8b3
Move sign and verify to AppCrypto
tomusdrw Mar 6, 2020
428b3da
Sign transaction
rakanalh Mar 6, 2020
f8b8dd1
Call `use_encoded`
rakanalh Mar 6, 2020
e6b2f33
Remove SubmitAndSignTransaction
rakanalh Mar 7, 2020
1dc8bf0
Implement runtime using new SigningTypes
rakanalh Mar 7, 2020
9f66858
Adapt offchain example to changes
rakanalh Mar 7, 2020
6e14b44
Fix im-online pallet
rakanalh Mar 7, 2020
a3442cb
Merge remote-tracking branch 'upstream/master' into td-offchain-signing
rakanalh Mar 13, 2020
2c75fb5
Quick fix: rename AuthorityId2
rakanalh Mar 13, 2020
1f54eae
Fix offchain example tests
rakanalh Mar 16, 2020
887e0e9
Add a comment on why keystore is required in unsigned transaction test
rakanalh Mar 16, 2020
34afbf2
Use UintAuthorityId instead of u64
rakanalh Mar 18, 2020
d04bd9a
WIP
rakanalh Mar 18, 2020
824940a
Remove IdentifyAccount from UintAuthorityId
rakanalh Mar 18, 2020
259cb98
Implement PublicWrapper type
rakanalh Mar 18, 2020
ea0ffae
Fix im-online tests
rakanalh Mar 18, 2020
853c1f3
Merge remote-tracking branch 'upstream/master' into td-offchain-signing
rakanalh Mar 18, 2020
5fd154d
Fix runtime test
rakanalh Mar 18, 2020
f629bab
Bump spec version
rakanalh Mar 18, 2020
6951887
Fix executor tests
rakanalh Mar 18, 2020
b8702ac
Rename ImOnlineAuthId -> ImOnlineAuthorityId and formatting
rakanalh Mar 23, 2020
09820d1
Merge remote-tracking branch 'upstream/master' into td-offchain-signing
rakanalh Mar 23, 2020
670e26b
Fix merge
rakanalh Mar 23, 2020
f5939cd
Documentation
rakanalh Mar 24, 2020
0ffd1b9
Revert u64 -> UintAuthorityId conversion
rakanalh Mar 24, 2020
324d436
Fix string errors
rakanalh Mar 25, 2020
9fe4409
Document public members in offchain module
rakanalh Mar 25, 2020
dcee66a
Merge remote-tracking branch 'upstream/master' into td-offchain-signing
rakanalh Mar 25, 2020
54cfe80
Merge remote-tracking branch 'upstream/master' into td-offchain-signing
rakanalh Mar 25, 2020
686b218
Merge remote-tracking branch 'upstream/master' into td-offchain-signing
rakanalh Mar 30, 2020
884dc5c
Introduce SubmitTransaction
rakanalh Mar 31, 2020
ac8845f
Update pallets to use SubmitTransaction
rakanalh Mar 31, 2020
55f3fce
WIP
rakanalh Mar 31, 2020
c3df880
Merge remote-tracking branch 'upstream/master' into td-offchain-signing
rakanalh Mar 31, 2020
fda2dd3
Use SubmitTransaction in offchain
rakanalh Mar 31, 2020
44b0701
Use `submit_unsigned_transaction`
rakanalh Mar 31, 2020
ab6c763
Fix tests
rakanalh Mar 31, 2020
0278c8e
Merge remote-tracking branch 'upstream/master' into td-offchain-signing
rakanalh Mar 31, 2020
5fbfe1a
Merge remote-tracking branch 'upstream/master' into td-offchain-signing
rakanalh Apr 1, 2020
de959d6
Update docs
rakanalh Apr 1, 2020
6d3c36b
Remove SigningTypes requirement from `SendTransactionTypes`
rakanalh Apr 2, 2020
f37c783
Fix tests
rakanalh Apr 2, 2020
7279077
Merge remote-tracking branch 'upstream/master' into td-offchain-signing
rakanalh Apr 2, 2020
df8e52c
Merge remote-tracking branch 'upstream/master' into td-offchain-signing
rakanalh Apr 6, 2020
fd70a12
Update frame/system/src/offchain.rs
rakanalh Apr 7, 2020
848adbf
Update frame/system/src/offchain.rs
rakanalh Apr 7, 2020
b4c5765
Update frame/example-offchain-worker/src/tests.rs
rakanalh Apr 7, 2020
f88c1c1
Update frame/system/src/offchain.rs
rakanalh Apr 7, 2020
13a8c84
Update frame/system/src/offchain.rs
rakanalh Apr 7, 2020
61e6987
Remove leftover from previous iterations
rakanalh Apr 7, 2020
c163b22
Change enum to struct
rakanalh Apr 7, 2020
81ba429
Remove public
rakanalh Apr 7, 2020
89b9471
Move mock to node/executor/tests
rakanalh Apr 7, 2020
9f79dc9
Merge branch 'td-offchain-signing' of github.com:paritytech/substrate…
rakanalh Apr 7, 2020
e69848e
Cleanup test-helpers
rakanalh Apr 7, 2020
ad83ed5
Make `application-crypto` `std` feature internal
bkchr Apr 7, 2020
a26379a
Merge remote-tracking branch 'upstream/bkchr-application-crypto-std' …
rakanalh Apr 7, 2020
143bfbe
Revert cargo lock update
rakanalh Apr 7, 2020
9644f85
Use TestAuthorityId from common
rakanalh Apr 7, 2020
aaae8ee
Restore members of account to public
rakanalh Apr 7, 2020
1f39e03
Merge remote-tracking branch 'upstream/master' into td-offchain-signing
rakanalh Apr 7, 2020
917b8a2
Tidy up imports
rakanalh Apr 7, 2020
cdd1af9
Fix benchmarking pallet
rakanalh Apr 7, 2020
ae477bb
Add tests demonstrating ForAll, ForAny on signer
rakanalh Apr 7, 2020
583cdc3
Move definition of AppCrypto
rakanalh Apr 7, 2020
87be138
Merge remote-tracking branch 'upstream/master' into td-offchain-signing
rakanalh Apr 8, 2020
42f4802
Cleanup stray comment
rakanalh Apr 8, 2020
536c8c3
Fix ValidTransaction
rakanalh Apr 8, 2020
2c8676f
Merge remote-tracking branch 'upstream/master' into td-offchain-signing
rakanalh Apr 9, 2020
3253d1f
Re-fix CreateSignedTransaction
rakanalh Apr 9, 2020
27f900e
Address PR feedback
rakanalh Apr 13, 2020
40c2335
Add can_sign method to signer
Apr 14, 2020
9d72eb8
Propagate error
Apr 14, 2020
de39bed
Improve documentation
Apr 14, 2020
4001eda
Fix vec! macro not available
Apr 14, 2020
7ac2b29
Document SendTransactiontypes
Apr 14, 2020
19ce6d8
Add some docs.
tomusdrw Apr 15, 2020
cbb909a
Split signing examples
Apr 15, 2020
79f54ab
Add tests for signing examples
Apr 15, 2020
8491fbc
WIP can_sign - PR feedback
Apr 15, 2020
fe5e74f
Merge branch 'td-offchain-signing' of github.com:paritytech/substrate…
Apr 15, 2020
9d125a1
WIP
Apr 15, 2020
507ef71
Split for_any / for_all into different calls
Apr 16, 2020
5732ff1
Verify payload and signature in test
Apr 16, 2020
2dde0c0
Fix can_sign implementation
Apr 16, 2020
c216977
Merge remote-tracking branch 'upstream/master' into td-offchain-signing
Apr 16, 2020
c378199
Fix impl_version
Apr 16, 2020
4a6d268
Import Box from sp_std
Apr 16, 2020
a94fecc
Create issues for TODOs
Apr 16, 2020
4a61334
Ignore doctest.
tomusdrw Apr 16, 2020
5722163
Add test directly to system. Adjust UintTypes.
tomusdrw Apr 16, 2020
19494c3
Add some tests to account filtering.
tomusdrw Apr 17, 2020
9bdbbc9
Remove code samples and point to example offchain worker
Apr 17, 2020
d35669b
Merge branch 'td-offchain-signing' of github.com:paritytech/substrate…
Apr 17, 2020
6a94d35
Merge remote-tracking branch 'upstream/master' into td-offchain-signing
Apr 17, 2020
2436ca7
Fix doc links
Apr 17, 2020
dec2490
Fix im-online tests using signatures.
tomusdrw Apr 20, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Add some docs.
  • Loading branch information
tomusdrw committed Apr 15, 2020
commit 19ce6d8a65ef05071166076fec9c5e5bedaed224
166 changes: 100 additions & 66 deletions frame/system/src/offchain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,8 @@
//! |account| Call::submit_price(price)
//! );

#![warn(missing_docs)]

use codec::Encode;
use sp_std::convert::{TryInto, TryFrom};
use sp_std::prelude::Vec;
Expand Down Expand Up @@ -248,13 +250,13 @@ impl<T: SigningTypes, C: AppCrypto<T::Public, T::Signature>> Signer<T, C, ForAny
}

impl<T: SigningTypes, C: AppCrypto<T::Public, T::Signature>> SignMessage<T> for Signer<T, C, ForAll> {
type Result = Vec<(Account<T>, T::Signature)>;
type SignatureData = Vec<(Account<T>, T::Signature)>;

fn sign_message(&self, message: &[u8]) -> Self::Result {
fn sign_message(&self, message: &[u8]) -> Self::SignatureData {
self.for_all(|account| C::sign(message, account.public.clone()))
}

fn sign<TPayload, F>(&self, f: F) -> Self::Result where
fn sign<TPayload, F>(&self, f: F) -> Self::SignatureData where
F: Fn(&Account<T>) -> TPayload,
TPayload: SignedPayload<T>,
{
Expand All @@ -263,13 +265,13 @@ impl<T: SigningTypes, C: AppCrypto<T::Public, T::Signature>> SignMessage<T> for
}

impl<T: SigningTypes, C: AppCrypto<T::Public, T::Signature>> SignMessage<T> for Signer<T, C, ForAny> {
type Result = Option<(Account<T>, T::Signature)>;
type SignatureData = Option<(Account<T>, T::Signature)>;

fn sign_message(&self, message: &[u8]) -> Self::Result {
fn sign_message(&self, message: &[u8]) -> Self::SignatureData {
self.for_any(|account| C::sign(message, account.public.clone()))
}

fn sign<TPayload, F>(&self, f: F) -> Self::Result where
fn sign<TPayload, F>(&self, f: F) -> Self::SignatureData where
F: Fn(&Account<T>) -> TPayload,
TPayload: SignedPayload<T>,
{
Expand All @@ -288,9 +290,9 @@ impl<
&self,
f: impl Fn(&Account<T>) -> LocalCall,
) -> Self::Result {
self.for_any(|account| {
self.for_any(|account| {
let call = f(account);
self.submit_signed_transaction(account, call)
self.send_single_signed_transaction(account, call)
})
}
}
Expand All @@ -308,7 +310,7 @@ impl<
) -> Self::Result {
self.for_all(|account| {
let call = f(account);
self.submit_signed_transaction(account, call)
self.send_single_signed_transaction(account, call)
})
}
}
Expand All @@ -327,7 +329,7 @@ impl<
) -> Self::Result
where
F: Fn(&Account<T>) -> TPayload,
TPayload: SignedPayload<T>,
TPayload: SignedPayload<T>,
{
self.for_any(|account| {
let payload = f(account);
Expand Down Expand Up @@ -362,10 +364,13 @@ impl<
}
}

/// Account information used for signing payloads
/// Details of an account for which a private key is contained in the keystore.
pub struct Account<T: SigningTypes> {
/// Index on the provided list of accounts or list of all accounts.
pub index: usize,
/// Runtime-specific `AccountId`.
pub id: T::AccountId,
/// A runtime-specific `Public` key for that key pair.
pub public: T::Public,
}

Expand All @@ -389,32 +394,43 @@ impl<T: SigningTypes> Clone for Account<T> where
}
}

/// App specific crypto trait that provides sign/verify
/// abilities to offchain workers. Implementations of this
/// trait should specify the app-specific public/signature
/// types.
/// App-specific crypto trait that provides sign/verify abilities to offchain workers.
///
/// Implementations of this trait should specify the app-specific public/signature types.
/// This is merely a wrapper around an existing `RuntimeAppPublic` type, but with
/// extra non-application-specific crypto type that is being wrapped (e.g. `sr25519`, `ed25519`).
/// This is needed to later on convert into runtime-specific `Public` key, which might support
/// multiple different crypto.
/// The point of this trait is to be able to easily convert between `RuntimeAppPublic` and
/// the wrapped crypto types.
///
/// TODO [#???] Potentially use `IsWrappedBy` types, or find some other way to make it easy to
/// obtain unwrapped crypto (and wrap it back).
///
/// Example (pseudo-)implementation:
/// ```
/// // im-online specific crypto
/// type RuntimeAppPublic = ImOnline(sr25519::Public);
/// // wrapped "raw" crypto
/// type GenericPublic = sr25519::Public;
/// type GenericSignature = sr25519::Signature;
///
/// // runtime-specific public key
/// type Public = MultiSigner: From<sr25519::Public>;
/// type Signature = MulitSignature: From<sr25519::Signature>;
/// ```
pub trait AppCrypto<Public, Signature> {
/// A application-specific crypto.
type RuntimeAppPublic: RuntimeAppPublic;
// TODO [ToDr] The conversions are messy, clean them up.
//
// The idea would be to have some implementation for `RuntimeAppPublic`
// to convert to and from generic types.
// Maybe even a method like:
// impl RuntimeAppPublic {
// fn into_public<T: From<Self::Generic>>(&self) -> T;
// }
// so an ability to convert the runtime app public into
// some type that is reachable from the inner (wrapped) generic
// crypto type.
// So example:
// ImOnline(sr25519) = RuntimeAppPublic
// sr25519 = Generic
// MutliSigner = From<sr25519>

/// A raw crypto public key wrapped by `RuntimeAppPublic`.
type GenericPublic:
From<Self::RuntimeAppPublic>
+ Into<Self::RuntimeAppPublic>
+ TryFrom<Public>
+ Into<Public>;

/// A matching raw crypto `Signature` type.
type GenericSignature:
From<<Self::RuntimeAppPublic as RuntimeAppPublic>::Signature>
+ Into<<Self::RuntimeAppPublic as RuntimeAppPublic>::Signature>
Expand Down Expand Up @@ -450,36 +466,50 @@ pub trait AppCrypto<Public, Signature> {

x.verify(&payload, &signature)
}

}

/// A wrapper around the types which are used for signing transactions.
/// This trait should be implemented on the runtime.
/// A wrapper around the types which are used for signing.
///
/// This trait adds extra bounds to `Public` and `Signature` types of the runtime
/// that are necessary to use these types for signing.
///
/// TODO [#???] Could this be just `T::Signature as traits::Verify>::Signer`?
/// Seems that this may cause issues with bounds resolution.
pub trait SigningTypes: crate::Trait {
// TODO [ToDr] Could this be just `T::Signature as traits::Verify>::Signer`?
// Seems that this may cause issues with bounds resolution.
/// A public key that is capable of identifing `AccountId`s.
///
/// Usually that's either a raw crypto public key (e.g. `sr25519::Public`) or
/// an aggregate type for multiple crypto public keys, like `MulitSigner`.
type Public: Clone
+ PartialEq
+ IdentifyAccount<AccountId = Self::AccountId>
+ core::fmt::Debug
+ codec::Codec;

/// A matching `Signature` type.
type Signature: Clone
+ PartialEq
+ core::fmt::Debug
+ codec::Codec;
}

/// A wrapper around the transaction and call types.
/// A definition of types required to submit transactions from within the runtime.
pub trait SendTransactionTypes<LocalCall> {
/// The extrinsic type that this runtime submits onchain.
/// The extrinsic type expected by the runtime.
type Extrinsic: ExtrinsicT<Call=Self::OverarchingCall> + codec::Encode;
Copy link
Contributor

Choose a reason for hiding this comment

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

Missing docs for types

/// The runtime's call type.
///
/// This has additional bound to be able to be created from pallet-local `Call` types.
type OverarchingCall: From<LocalCall>;
}

/// Create signed transaction.
///
/// Should be implemented by the runtime to sign transaction data
/// This trait is meant to be implemented by the runtime and is responsible for constructing
/// a payload to be signed and contained within the extrinsic.
/// This will most likely include creation of `SignedExtra` (a set of `SignedExtensions`).
/// Note that the result can be altered by inspecting the `Call` (for instance adjusting
/// fees, or mortality depending on the `pallet` being called).
pub trait CreateSignedTransaction<LocalCall>: SendTransactionTypes<LocalCall> + SigningTypes {
/// Attempt to create signed extrinsic data that encodes call from given account.
///
Expand All @@ -495,57 +525,56 @@ pub trait CreateSignedTransaction<LocalCall>: SendTransactionTypes<LocalCall> +
) -> Option<(Self::OverarchingCall, <Self::Extrinsic as ExtrinsicT>::SignaturePayload)>;
}

/// Sign message payload
/// A message signer.
pub trait SignMessage<T: SigningTypes> {
type Result;
/// A signature data.
///
/// May contain account used for signing and the `Signature` itself.
type SignatureData;

/// Sign message
/// Sign a message.
///
/// Implementation of this method should return
/// a result containing the signature
fn sign_message(&self, message: &[u8]) -> Self::Result;
/// a result containing the signature.
fn sign_message(&self, message: &[u8]) -> Self::SignatureData;

/// Sign payload
/// Construct and sign given payload.
///
/// This method expects `f` to return a `SignedPayload`
/// object which is then used for signing.
///
/// Returns a result that contains the signature of the payload.
fn sign<TPayload, F>(&self, f: F) -> Self::Result where
fn sign<TPayload, F>(&self, f: F) -> Self::SignatureData where
F: Fn(&Account<T>) -> TPayload,
TPayload: SignedPayload<T>,
;
}

/// Submit a signed transaction onchain
/// Submit a signed transaction to the transaction pool.
pub trait SendSignedTransaction<
T: SigningTypes + CreateSignedTransaction<LocalCall>,
C: AppCrypto<T::Public, T::Signature>,
LocalCall
> {
/// A submission result.
///
/// This should contain an indication of success and the account that was used for signing.
type Result;

/// Send a signed onchain transaction
///
/// Calls `f` and expects a Call object to be returned.
/// The call object is then signed and submitted onchain.
/// Submit a signed transaction to the local pool.
///
/// Returns a result of the onchain submission.
/// Given `f` closure will be called for every requested account and expects a `Call` object
/// to be returned.
/// The call is then wrapped into a transaction (see `#CreateSignedTransaction`), signed and
/// submitted to the pool.
fn send_signed_transaction(
&self,
f: impl Fn(&Account<T>) -> LocalCall,
) -> Self::Result;

/// Performs signing and submitting the transaction onchain.
///
/// This method can be used by implementations of `send_signed_transaction`
/// to actually sign and submit the signed transaction.
///
/// Returns a result of the onchain submittion.
fn submit_signed_transaction(
/// Wraps the call into transaction, signs using given account and submits to the pool.
fn send_single_signed_transaction(
&self,
account: &Account<T>,
call: LocalCall
call: LocalCall,
) -> Option<Result<(), ()>> {
let mut account_data = crate::Account::<T>::get(&account.id);
debug::native::debug!(
Expand Down Expand Up @@ -579,13 +608,17 @@ pub trait SendUnsignedTransaction<
T: SigningTypes + SendTransactionTypes<LocalCall>,
LocalCall,
> {
/// A submission result.
///
/// Should contain the submission result and the account(s) that signed the payload.
type Result;

/// Send an unsigned transaction with a signed payload.
///
/// This method takes `f` and `f2` where:
/// - `f` is called and expected to return a `SignedPayload` object.
/// - `f2` is called with the SignedPayload returned by `f` and expected to return a Call object.
/// - `f` is called for every account and is expected to return a `SignedPayload` object.
/// - `f2` is then called with the `SignedPayload` returned by `f` and the signature and is
/// expected to return a `Call` object to be embedded into transaction.
fn send_unsigned_transaction<TPayload, F>(
&self,
f: F,
Expand All @@ -595,7 +628,7 @@ pub trait SendUnsignedTransaction<
F: Fn(&Account<T>) -> TPayload,
TPayload: SignedPayload<T>;

/// Submits an unsigned transaction onchain.
/// Submits an unsigned call to the transaction pool.
fn submit_unsigned_transaction(
&self,
call: LocalCall
Expand All @@ -605,9 +638,10 @@ pub trait SendUnsignedTransaction<
}
}

/// Utility trait to be implemented on payloads
/// that should be signed and submitted onchain.
/// Utility trait to be implemented on payloads that can be signed.
pub trait SignedPayload<T: SigningTypes>: Encode {
/// Return a public key that is expected to have a matching key in the keystore,
/// which should be used to sign the payload.
fn public(&self) -> T::Public;

/// Sign the payload using the implementor's provided public key.
Expand Down