From 51c352608176cc30bb4c8532684b9089239250bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Thu, 22 Aug 2019 13:04:35 +0200 Subject: [PATCH 01/12] Abstract constructing extrinsic and signing. --- .../src/generic/unchecked_extrinsic.rs | 14 ++- core/sr-primitives/src/lib.rs | 7 +- core/sr-primitives/src/testing.rs | 6 +- core/sr-primitives/src/traits.rs | 13 ++- core/test-runtime/src/lib.rs | 3 +- node/runtime/src/lib.rs | 4 +- srml/im-online/src/lib.rs | 17 ++-- srml/support/src/inherent.rs | 8 +- srml/system/src/lib.rs | 2 + srml/system/src/offchain.rs | 90 +++++++++++++++++++ 10 files changed, 136 insertions(+), 28 deletions(-) create mode 100644 srml/system/src/offchain.rs diff --git a/core/sr-primitives/src/generic/unchecked_extrinsic.rs b/core/sr-primitives/src/generic/unchecked_extrinsic.rs index cb9330cfaaff0..bc9cccda4c6a6 100644 --- a/core/sr-primitives/src/generic/unchecked_extrinsic.rs +++ b/core/sr-primitives/src/generic/unchecked_extrinsic.rs @@ -72,12 +72,22 @@ impl Extrinsic { type Call = Call; + type SignaturePayload = ( + Address, + Signature, + Extra, + ); + fn is_signed(&self) -> Option { Some(self.signature.is_some()) } - fn new_unsigned(function: Call) -> Option { - Some(UncheckedExtrinsic::new_unsigned(function)) + fn new(function: Call, signed_data: Option) -> Option { + Some(if let Some((address, signature, extra)) = signed_data { + UncheckedExtrinsic::new_signed(function, address, signature, extra) + } else { + UncheckedExtrinsic::new_unsigned(function) + }) } } diff --git a/core/sr-primitives/src/lib.rs b/core/sr-primitives/src/lib.rs index a6a66b80d4c1e..06ceb8a244ffb 100644 --- a/core/sr-primitives/src/lib.rs +++ b/core/sr-primitives/src/lib.rs @@ -847,12 +847,7 @@ impl<'a> ::serde::Deserialize<'a> for OpaqueExtrinsic { impl traits::Extrinsic for OpaqueExtrinsic { type Call = (); - - fn is_signed(&self) -> Option { - None - } - - fn new_unsigned(_call: Self::Call) -> Option { None } + type SignaturePayload = (); } #[cfg(test)] diff --git a/core/sr-primitives/src/testing.rs b/core/sr-primitives/src/testing.rs index c91c8366c1123..ed5ac7fa45675 100644 --- a/core/sr-primitives/src/testing.rs +++ b/core/sr-primitives/src/testing.rs @@ -187,6 +187,7 @@ pub struct ExtrinsicWrapper(Xt); impl traits::Extrinsic for ExtrinsicWrapper { type Call = (); + type SignaturePayload = (); fn is_signed(&self) -> Option { None @@ -274,13 +275,14 @@ impl Checkable for TestXt traits::Extrinsic for TestXt { type Call = Call; + type SignaturePayload = (u64, Extra); fn is_signed(&self) -> Option { Some(self.0.is_some()) } - fn new_unsigned(_c: Call) -> Option { - None + fn new(c: Call, sig: Option) -> Option { + Some(TestXt(sig, c)) } } diff --git a/core/sr-primitives/src/traits.rs b/core/sr-primitives/src/traits.rs index abbbef3a5b260..46ef1a9b859ae 100644 --- a/core/sr-primitives/src/traits.rs +++ b/core/sr-primitives/src/traits.rs @@ -743,13 +743,20 @@ pub trait Extrinsic: Sized { /// The function call. type Call; + /// The signed data for signed extrinsics. + type SignaturePayload; + /// Is this `Extrinsic` signed? /// If no information are available about signed/unsigned, `None` should be returned. fn is_signed(&self) -> Option { None } - /// New instance of an unsigned extrinsic aka "inherent". `None` if this is an opaque - /// extrinsic type. - fn new_unsigned(_call: Self::Call) -> Option { None } + /// Create new instance of the extrinsic. + /// + /// Extrinsics can be split into: + /// 1. Inherents (no signature; created by validators during block production) + /// 2. Unsigned Transactions (no signature; represent "system calls" or other special kinds of calls) + /// 3. Signed Transactions (with signature; a regular transactions with known origin) + fn new(_call: Self::Call, _signed_data: Option) -> Option { None } } /// Extract the hashing type for a block. diff --git a/core/test-runtime/src/lib.rs b/core/test-runtime/src/lib.rs index 55b6ad9b5fe14..f023fd89e137d 100644 --- a/core/test-runtime/src/lib.rs +++ b/core/test-runtime/src/lib.rs @@ -141,6 +141,7 @@ impl BlindCheckable for Extrinsic { impl ExtrinsicT for Extrinsic { type Call = Extrinsic; + type SignaturePayload = (); fn is_signed(&self) -> Option { if let Extrinsic::IncludeData(_) = *self { @@ -150,7 +151,7 @@ impl ExtrinsicT for Extrinsic { } } - fn new_unsigned(call: Self::Call) -> Option { + fn new(call: Self::Call, _signature_payload: Option) -> Option { Some(call) } } diff --git a/node/runtime/src/lib.rs b/node/runtime/src/lib.rs index e80d5fa83ab38..71e649ce54f74 100644 --- a/node/runtime/src/lib.rs +++ b/node/runtime/src/lib.rs @@ -396,7 +396,7 @@ impl sudo::Trait for Runtime { impl im_online::Trait for Runtime { type Call = Call; type Event = Event; - type UncheckedExtrinsic = UncheckedExtrinsic; + type SubmitTransaction = SubmitTransaction; type ReportUnresponsiveness = Offences; type CurrentElectedSet = staking::CurrentElectedStashAccounts; } @@ -424,6 +424,8 @@ impl finality_tracker::Trait for Runtime { type ReportLatency = ReportLatency; } +type SubmitTransaction = system::offchain::TransactionSubmitter<(), UncheckedExtrinsic>; + construct_runtime!( pub enum Runtime where Block = Block, diff --git a/srml/im-online/src/lib.rs b/srml/im-online/src/lib.rs index 628531c9f318f..91d3e1b354d66 100644 --- a/srml/im-online/src/lib.rs +++ b/srml/im-online/src/lib.rs @@ -75,7 +75,7 @@ use session::historical::IdentificationTuple; use sr_io::Printable; use sr_primitives::{ Perbill, ApplyError, - traits::{Extrinsic as ExtrinsicT, Convert}, + traits::Convert, transaction_validity::{TransactionValidity, TransactionLongevity, ValidTransaction}, }; use sr_staking_primitives::{ @@ -86,6 +86,7 @@ use srml_support::{ StorageValue, decl_module, decl_event, decl_storage, StorageDoubleMap, print, ensure }; use system::ensure_none; +use system::offchain::SubmitUnsignedTransaction; mod app { pub use app_crypto::sr25519 as crypto; @@ -125,7 +126,6 @@ struct WorkerStatus { // Error which may occur while executing the off-chain code. enum OffchainErr { DecodeWorkerStatus, - ExtrinsicCreation, FailedSigning, NetworkState, SubmitTransaction, @@ -135,7 +135,6 @@ impl Printable for OffchainErr { fn print(self) { match self { OffchainErr::DecodeWorkerStatus => print("Offchain error: decoding WorkerStatus failed!"), - OffchainErr::ExtrinsicCreation => print("Offchain error: extrinsic creation failed!"), OffchainErr::FailedSigning => print("Offchain error: signing failed!"), OffchainErr::NetworkState => print("Offchain error: fetching network state failed!"), OffchainErr::SubmitTransaction => print("Offchain error: submitting transaction failed!"), @@ -161,12 +160,11 @@ pub trait Trait: system::Trait + session::historical::Trait { /// The overarching event type. type Event: From + Into<::Event>; - /// The function call. + /// An overarching runtime call type. type Call: From>; - /// A extrinsic right from the external world. This is unchecked and so - /// can contain a signature. - type UncheckedExtrinsic: ExtrinsicT::Call> + Encode + Decode; + /// A transaction submitter. + type SubmitTransaction: SubmitUnsignedTransaction::Call>; /// A type that gives us the ability to submit unresponsiveness offence reports. type ReportUnresponsiveness: @@ -319,9 +317,8 @@ impl Module { let signature = key.sign(&heartbeat_data.encode()).ok_or(OffchainErr::FailedSigning)?; let call = Call::heartbeat(heartbeat_data, signature); - let ex = T::UncheckedExtrinsic::new_unsigned(call.into()) - .ok_or(OffchainErr::ExtrinsicCreation)?; - sr_io::submit_transaction(&ex).map_err(|_| OffchainErr::SubmitTransaction)?; + T::SubmitTransaction::submit_unsigned(call) + .map_err(|_| OffchainErr::SubmitTransaction)?; // once finished we set the worker status without comparing // if the existing value changed in the meantime. this is diff --git a/srml/support/src/inherent.rs b/srml/support/src/inherent.rs index 1b6d8fbdd7ed9..935d3b4e74e4f 100644 --- a/srml/support/src/inherent.rs +++ b/srml/support/src/inherent.rs @@ -55,14 +55,16 @@ macro_rules! impl_outer_inherent { fn create_extrinsics(&self) -> $crate::inherent::Vec<<$block as $crate::inherent::BlockT>::Extrinsic> { use $crate::inherent::ProvideInherent; + use $crate::inherent::Extrinsic; let mut inherents = Vec::new(); $( if let Some(inherent) = $module::create_inherent(self) { - inherents.push($uncheckedextrinsic::new_unsigned( - Call::$call(inherent)) - ); + inherents.push($uncheckedextrinsic::new( + Call::$call(inherent), + None, + ).expect("Runtime UncheckedExtrinsic is not Opaque, so it has to return `Some`; qed")); } )* diff --git a/srml/system/src/lib.rs b/srml/system/src/lib.rs index 56093f4f7ec8e..42385583efbd3 100644 --- a/srml/system/src/lib.rs +++ b/srml/system/src/lib.rs @@ -104,6 +104,8 @@ use runtime_io::{twox_128, TestExternalities, Blake2Hasher}; #[cfg(any(feature = "std", test))] use primitives::ChangesTrieConfiguration; +pub mod offchain; + /// Handler for when a new account has been created. pub trait OnNewAccount { /// A new account `who` has been registered. diff --git a/srml/system/src/offchain.rs b/srml/system/src/offchain.rs new file mode 100644 index 0000000000000..2ba0e9f33939f --- /dev/null +++ b/srml/system/src/offchain.rs @@ -0,0 +1,90 @@ +// Copyright 2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Module helpers for offchain calls. + +use sr_primitives::traits::Extrinsic as ExtrinsicT; + +/// A trait responsible for producing signature payload for an extrinsic. +pub trait Signer { + fn sign( + account: T::AccountId, + nonce: T::Index, + call: &Extrinsic::Call, + ) -> Option; +} + +/// A trait to sign and submit transactions in offchain calls. +pub trait SubmitSignedTransaction { + /// Unchecked extrinsic type. + type Extrinsic: ExtrinsicT + codec::Encode; + + /// A runtime-specific function to sign and produce signature payload for extrinsic. + type Sign: Signer; + + /// Sign given call and submit it to the transaction pool. + /// + /// Returns `Ok` if the transaction was submitted correctly + /// and `Err` if the key for given `id` was not found or the + /// transaction was rejected from the pool. + fn sign_and_submit(call: impl Into, id: T::AccountId) -> Result<(), ()> { + let call = call.into(); + let expected = >::account_nonce(&id); + let signature_data = Self::Sign::sign(id, expected, &call).ok_or(())?; + let xt = Self::Extrinsic::new(call, Some(signature_data)).ok_or(())?; + runtime_io::submit_transaction(&xt) + } +} + +/// A trait to submit unsigned transactions in offchain calls. +pub trait SubmitUnsignedTransaction { + /// Unchecked extrinsic type. + type Extrinsic: ExtrinsicT + codec::Encode; + + + /// Submit given call to the transaction pool as unsigned transaction. + /// + /// Returns `Ok` if the transaction was submitted correctly + /// and `Err` if transaction was rejected from the pool. + fn submit_unsigned(call: impl Into) -> Result<(), ()> { + let xt = Self::Extrinsic::new(call.into(), None).ok_or(())?; + runtime_io::submit_transaction(&xt) + } +} + +/// A default type used to submit transactions to the pool. +pub struct TransactionSubmitter { + _signer: rstd::marker::PhantomData<(S, E)>, +} + +/// A blanket implementation to simplify creation of transaction signer & submitter in the runtime. +impl SubmitSignedTransaction for TransactionSubmitter where + T: crate::Trait, + S: Signer, + E: ExtrinsicT + codec::Encode, +{ + type Extrinsic = E; + type Sign = S; +} + +/// A blanket impl to use the same submitter for usigned transactions as well. +impl SubmitUnsignedTransaction for TransactionSubmitter where + T: crate::Trait, + E: ExtrinsicT + codec::Encode, +{ + type Extrinsic = E; +} + From f4e7284927499f749d7ecc684a0fb15fda3340bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Fri, 23 Aug 2019 08:52:46 +0200 Subject: [PATCH 02/12] Initial impl of signer. --- core/sr-primitives/src/generic/mod.rs | 2 +- .../src/generic/unchecked_extrinsic.rs | 63 ++++++++++++++++--- node/cli/src/service.rs | 13 ++-- node/runtime/src/lib.rs | 26 +++++++- srml/system/src/offchain.rs | 59 +++++++++++++++-- subkey/src/main.rs | 15 +++-- 6 files changed, 149 insertions(+), 29 deletions(-) diff --git a/core/sr-primitives/src/generic/mod.rs b/core/sr-primitives/src/generic/mod.rs index 1511753d2c524..0138a15aee21a 100644 --- a/core/sr-primitives/src/generic/mod.rs +++ b/core/sr-primitives/src/generic/mod.rs @@ -27,7 +27,7 @@ mod digest; #[cfg(test)] mod tests; -pub use self::unchecked_extrinsic::UncheckedExtrinsic; +pub use self::unchecked_extrinsic::{UncheckedExtrinsic, SignedPayload}; pub use self::era::{Era, Phase}; pub use self::checked_extrinsic::CheckedExtrinsic; pub use self::header::Header; diff --git a/core/sr-primitives/src/generic/unchecked_extrinsic.rs b/core/sr-primitives/src/generic/unchecked_extrinsic.rs index bc9cccda4c6a6..ad6b260a54634 100644 --- a/core/sr-primitives/src/generic/unchecked_extrinsic.rs +++ b/core/sr-primitives/src/generic/unchecked_extrinsic.rs @@ -108,21 +108,18 @@ where fn check(self, lookup: &Lookup) -> Result { Ok(match self.signature { Some((signed, signature, extra)) => { - let additional_signed = extra.additional_signed()?; - let raw_payload = (self.function, extra, additional_signed); let signed = lookup.lookup(signed)?; + let raw_payload = SignedPayload::new(self.function, extra)?; if !raw_payload.using_encoded(|payload| { - if payload.len() > 256 { - signature.verify(&blake2_256(payload)[..], &signed) - } else { - signature.verify(payload, &signed) - } + signature.verify(payload, &signed) }) { return Err(crate::BAD_SIGNATURE) } + + let (function, extra, _) = raw_payload.deconstruct(); CheckedExtrinsic { - signed: Some((signed, raw_payload.1)), - function: raw_payload.0, + signed: Some((signed, extra)), + function, } } None => CheckedExtrinsic { @@ -133,6 +130,54 @@ where } } +/// A payload to sign for unchecked extrinsics. +pub struct SignedPayload { + raw_payload: ( + Call, + Extra, + Extra::AdditionalSigned, + ), +} + +impl SignedPayload where + Call: Encode, + Extra: SignedExtension, +{ + /// Create new `SignedPayload`. + /// + /// This function may fail if `additional_signed` of `Extra` is not available. + pub fn new(call: Call, extra: Extra) -> Result { + let additional_signed = extra.additional_signed()?; + let raw_payload = (call, extra, additional_signed); + Ok(Self { raw_payload }) + } + + /// Create new `SignedPayload` from raw components. + pub fn from_raw(call: Call, extra: Extra, additional_signed: Extra::AdditionalSigned) -> Self { + Self { + raw_payload: (call, extra, additional_signed), + } + } + + /// Get an encoded version of this payload. + /// + /// Payloads longer than 256 bytes are going to be `blake2_256`-hashed. + pub fn using_encoded(&self, f: impl FnOnce(&[u8]) -> O) -> O { + self.raw_payload.using_encoded(|payload| { + if payload.len() > 256 { + f(&blake2_256(payload)[..]) + } else { + f(payload) + } + }) + } + + /// Deconstruct the payload into it's components. + pub fn deconstruct(self) -> (Call, Extra, Extra::AdditionalSigned) { + self.raw_payload + } +} + impl Decode for UncheckedExtrinsic where diff --git a/node/cli/src/service.rs b/node/cli/src/service.rs index 7022d12d69a0f..1662a488a2fd2 100644 --- a/node/cli/src/service.rs +++ b/node/cli/src/service.rs @@ -479,14 +479,17 @@ mod tests { let take_fees = balances::TakeFees::from(0); let extra = (check_version, check_genesis, check_era, check_nonce, check_weight, take_fees); - let raw_payload = (function, extra.clone(), version, genesis_hash, genesis_hash); - let signature = raw_payload.using_encoded(|payload| if payload.len() > 256 { - signer.sign(&blake2_256(payload)[..]) - } else { + let raw_payload = SignedPayload::from_raw( + function, + extra, + (version, genesis_hash, genesis_hash, (), (), ()) + ); + let signature = raw_payload.using_encoded(|payload| { signer.sign(payload) }); + let (function, extra, _) = raw_payload.deconstruct(); let xt = UncheckedExtrinsic::new_signed( - raw_payload.0, + function, from.into(), signature.into(), extra, diff --git a/node/runtime/src/lib.rs b/node/runtime/src/lib.rs index 71e649ce54f74..e1b192f06b2c4 100644 --- a/node/runtime/src/lib.rs +++ b/node/runtime/src/lib.rs @@ -424,7 +424,15 @@ impl finality_tracker::Trait for Runtime { type ReportLatency = ReportLatency; } -type SubmitTransaction = system::offchain::TransactionSubmitter<(), UncheckedExtrinsic>; +impl system::offchain::GetPayload for Runtime { + fn get_payload(call: Call, index: Index) -> SignedPayload { + unimplemented!() + } +} + +// TODO [ToDr] What type to use here? +type Signer = (ImOnlineId, UncheckedExtrinsic, Indices, Runtime); +type SubmitTransaction = system::offchain::TransactionSubmitter; construct_runtime!( pub enum Runtime where @@ -477,6 +485,8 @@ pub type SignedExtra = ( ); /// Unchecked extrinsic type as expected by this runtime. pub type UncheckedExtrinsic = generic::UncheckedExtrinsic; +/// The payload being signed in transactions. +pub type SignedPayload = generic::SignedPayload; /// Extrinsic type that has already been checked. pub type CheckedExtrinsic = generic::CheckedExtrinsic; /// Executive: handles dispatch to the various modules. @@ -611,3 +621,17 @@ impl_runtime_apis! { } } } + +#[cfg(test)] +mod tests { + use super::*; + use system::offchain::SubmitSignedTransaction; + + fn is_submit_signed_transaction(_arg: impl SubmitSignedTransaction) {} + + #[test] + fn validate_bounds() { + let x = SubmitTransaction::default(); + is_submit_signed_transaction(x); + } +} diff --git a/srml/system/src/offchain.rs b/srml/system/src/offchain.rs index 2ba0e9f33939f..a28d97d279ef8 100644 --- a/srml/system/src/offchain.rs +++ b/srml/system/src/offchain.rs @@ -16,15 +16,54 @@ //! Module helpers for offchain calls. -use sr_primitives::traits::Extrinsic as ExtrinsicT; +use codec::{Encode, Codec}; +use sr_primitives::app_crypto::RuntimeAppPublic; +use sr_primitives::generic::{UncheckedExtrinsic, SignedPayload}; +use sr_primitives::traits::{Extrinsic as ExtrinsicT, SignedExtension, StaticLookup, MaybeDebug}; /// A trait responsible for producing signature payload for an extrinsic. pub trait Signer { fn sign( account: T::AccountId, nonce: T::Index, - call: &Extrinsic::Call, - ) -> Option; + call: Extrinsic::Call, + ) -> (Extrinsic::Call, Option); +} + +pub trait GetPayload { + fn get_payload(call: Call, index: Index) -> Payload; +} + +impl Signer> + for (TSigner, UncheckedExtrinsic, L, P) +where + TSigner: RuntimeAppPublic + From, + TSigner::Signature: Into, + Address: Codec + Clone + PartialEq + MaybeDebug, + Call: Encode, + T: crate::Trait, + Extra: SignedExtension, + L: StaticLookup, + P: GetPayload>, +{ + fn sign( + account: T::AccountId, + nonce: T::Index, + call: Call, + ) -> (Call, Option< + as ExtrinsicT>::SignaturePayload + >) { + let raw_payload = P::get_payload(call, nonce); + let signature = raw_payload.using_encoded(|payload| { + TSigner::from(account.clone()).sign(&payload) + }); + let address = L::unlookup(account); + let (call, extra, _) = raw_payload.deconstruct(); + match signature { + Some(sig) => (call, Some((address, sig.into(), extra))), + None => (call, None), + } + } } /// A trait to sign and submit transactions in offchain calls. @@ -43,8 +82,10 @@ pub trait SubmitSignedTransaction { fn sign_and_submit(call: impl Into, id: T::AccountId) -> Result<(), ()> { let call = call.into(); let expected = >::account_nonce(&id); - let signature_data = Self::Sign::sign(id, expected, &call).ok_or(())?; - let xt = Self::Extrinsic::new(call, Some(signature_data)).ok_or(())?; + let (call, signature_data) = Self::Sign::sign(id, expected, call); + // return an error if there is no signature_data, instead of producing unsigned extrinsic. + let signature_data = Some(signature_data.ok_or(())?); + let xt = Self::Extrinsic::new(call, signature_data).ok_or(())?; runtime_io::submit_transaction(&xt) } } @@ -70,6 +111,14 @@ pub struct TransactionSubmitter { _signer: rstd::marker::PhantomData<(S, E)>, } +impl Default for TransactionSubmitter { + fn default() -> Self { + Self { + _signer: Default::default(), + } + } +} + /// A blanket implementation to simplify creation of transaction signer & submitter in the runtime. impl SubmitSignedTransaction for TransactionSubmitter where T: crate::Trait, diff --git a/subkey/src/main.rs b/subkey/src/main.rs index ba9d1a6cce059..e0ac2cb8b6b0f 100644 --- a/subkey/src/main.rs +++ b/subkey/src/main.rs @@ -29,7 +29,7 @@ use primitives::{ use codec::{Encode, Decode}; use sr_primitives::generic::Era; use node_primitives::{Balance, Index, Hash}; -use node_runtime::{Call, UncheckedExtrinsic, BalancesCall, Runtime}; +use node_runtime::{Call, UncheckedExtrinsic, SignedPayload, BalancesCall, Runtime, VERSION}; mod vanity; @@ -182,22 +182,21 @@ fn execute(matches: clap::ArgMatches) where println!("Using a genesis hash of {}", HexDisplay::from(&genesis_hash.as_ref())); - let raw_payload = ( + let raw_payload = SignedPayload::from_raw( function, extra(index, 0), - (&genesis_hash, &genesis_hash), + (VERSION.spec_version as u32, genesis_hash, genesis_hash, (), (), ()), ); - let signature = raw_payload.using_encoded(|payload| if payload.len() > 256 { - signer.sign(&blake2_256(payload)[..]) - } else { + let signature = raw_payload.using_encoded(|payload| { println!("Signing {}", HexDisplay::from(&payload)); signer.sign(payload) }); + let (function, extra, _) = raw_payload.deconstruct(); let extrinsic = UncheckedExtrinsic::new_signed( - raw_payload.0, + function, signer.public().into(), signature.into(), - extra(index, 0), + extra, ); println!("0x{}", hex::encode(&extrinsic.encode())); } From 9a179d98e0d7a80074f7bf500bce12502e06a6d0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Fri, 23 Aug 2019 10:37:07 +0200 Subject: [PATCH 03/12] Implement get payload. --- node/runtime/src/lib.rs | 17 ++++++++++++++--- srml/support/src/lib.rs | 2 +- srml/system/src/lib.rs | 27 ++++++++++++--------------- 3 files changed, 27 insertions(+), 19 deletions(-) diff --git a/node/runtime/src/lib.rs b/node/runtime/src/lib.rs index 8feeb0eb718eb..f1cdef98966dc 100644 --- a/node/runtime/src/lib.rs +++ b/node/runtime/src/lib.rs @@ -39,7 +39,7 @@ use sr_primitives::{ApplyResult, impl_opaque_keys, generic, create_runtime_str, use sr_primitives::transaction_validity::TransactionValidity; use sr_primitives::weights::Weight; use sr_primitives::traits::{ - BlakeTwo256, Block as BlockT, DigestFor, NumberFor, StaticLookup, + BlakeTwo256, Block as BlockT, DigestFor, NumberFor, StaticLookup, SaturatedConversion, }; use version::RuntimeVersion; use elections::VoteIndex; @@ -426,8 +426,19 @@ impl finality_tracker::Trait for Runtime { impl system::offchain::GetPayload for Runtime { fn get_payload(call: Call, index: Index) -> SignedPayload { - // TODO Get signer extra and convert into `SignedPayload`. - unimplemented!() + // TODO [ToDr] Where to take the fee from? + let fee = unimplemented!(); + let period = 1 << 8; + let current_block = System::block_number().saturated_into::(); + let extra: SignedExtra = ( + system::CheckVersion::::new(), + system::CheckGenesis::::new(), + system::CheckEra::::from(generic::Era::mortal(period, current_block)), + system::CheckNonce::::from(index), + system::CheckWeight::::new(), + balances::TakeFees::::from(fee), + ); + SignedPayload::new(call, extra); } } diff --git a/srml/support/src/lib.rs b/srml/support/src/lib.rs index 5623cab70f2ab..a9ca355110aaf 100644 --- a/srml/support/src/lib.rs +++ b/srml/support/src/lib.rs @@ -113,7 +113,7 @@ macro_rules! parameter_types { } #[doc(inline)] -pub use srml_support_procedural::decl_storage; +pub use ::srml_support_procedural::decl_storage; /// Return Err of the expression: `return Err($expression);`. /// diff --git a/srml/system/src/lib.rs b/srml/system/src/lib.rs index 42385583efbd3..090e1246074ae 100644 --- a/srml/system/src/lib.rs +++ b/srml/system/src/lib.rs @@ -433,7 +433,7 @@ decl_storage! { } } -pub struct EnsureRoot(::rstd::marker::PhantomData); +pub struct EnsureRoot(rstd::marker::PhantomData); impl< O: Into, O>> + From>, AccountId, @@ -447,7 +447,7 @@ impl< } } -pub struct EnsureSigned(::rstd::marker::PhantomData); +pub struct EnsureSigned(rstd::marker::PhantomData); impl< O: Into, O>> + From>, AccountId, @@ -461,7 +461,7 @@ impl< } } -pub struct EnsureSignedBy(::rstd::marker::PhantomData<(Who, AccountId)>); +pub struct EnsureSignedBy(rstd::marker::PhantomData<(Who, AccountId)>); impl< O: Into, O>> + From>, Who: Contains, @@ -476,7 +476,7 @@ impl< } } -pub struct EnsureNone(::rstd::marker::PhantomData); +pub struct EnsureNone(rstd::marker::PhantomData); impl< O: Into, O>> + From>, AccountId, @@ -490,7 +490,7 @@ impl< } } -pub struct EnsureNever(::rstd::marker::PhantomData); +pub struct EnsureNever(rstd::marker::PhantomData); impl EnsureOrigin for EnsureNever { type Success = T; fn try_origin(o: O) -> Result { @@ -879,8 +879,7 @@ impl CheckWeight { } } - /// Utility constructor for tests and client code. - #[cfg(feature = "std")] + /// Creates new `SignedExtension` to check weight of the extrinsic. pub fn new() -> Self { Self(PhantomData) } @@ -935,7 +934,6 @@ impl rstd::fmt::Debug for CheckWeight { #[derive(Encode, Decode, Clone, Eq, PartialEq)] pub struct CheckNonce(#[codec(compact)] T::Index); -#[cfg(feature = "std")] impl CheckNonce { /// utility constructor. Used only in client/factory code. pub fn from(nonce: T::Index) -> Self { @@ -1009,7 +1007,6 @@ impl SignedExtension for CheckNonce { #[derive(Encode, Decode, Clone, Eq, PartialEq)] pub struct CheckEra((Era, rstd::marker::PhantomData)); -#[cfg(feature = "std")] impl CheckEra { /// utility constructor. Used only in client/factory code. pub fn from(era: Era) -> Self { @@ -1049,10 +1046,10 @@ impl rstd::fmt::Debug for CheckGenesis { } } -#[cfg(feature = "std")] impl CheckGenesis { + /// Creates new `SignedExtension` to check genesis hash. pub fn new() -> Self { - Self(std::marker::PhantomData) + Self(rstd::marker::PhantomData) } } @@ -1078,10 +1075,10 @@ impl rstd::fmt::Debug for CheckVersion { } } -#[cfg(feature = "std")] impl CheckVersion { + /// Create new `SignedExtension` to check runtime version. pub fn new() -> Self { - Self(std::marker::PhantomData) + Self(rstd::marker::PhantomData) } } @@ -1096,10 +1093,10 @@ impl SignedExtension for CheckVersion { } } -pub struct ChainContext(::rstd::marker::PhantomData); +pub struct ChainContext(rstd::marker::PhantomData); impl Default for ChainContext { fn default() -> Self { - ChainContext(::rstd::marker::PhantomData) + ChainContext(rstd::marker::PhantomData) } } From 7222869eb64b3a8c2224062dc564294e538ddcd9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Thu, 29 Aug 2019 15:56:14 +0200 Subject: [PATCH 04/12] Clean up the code. --- .../src/generic/unchecked_extrinsic.rs | 15 ++- node/runtime/src/lib.rs | 30 +++-- srml/balances/src/lib.rs | 1 - srml/system/src/offchain.rs | 109 +++++++++--------- 4 files changed, 85 insertions(+), 70 deletions(-) diff --git a/core/sr-primitives/src/generic/unchecked_extrinsic.rs b/core/sr-primitives/src/generic/unchecked_extrinsic.rs index ad6b260a54634..c2bd9997c20b0 100644 --- a/core/sr-primitives/src/generic/unchecked_extrinsic.rs +++ b/core/sr-primitives/src/generic/unchecked_extrinsic.rs @@ -130,7 +130,11 @@ where } } -/// A payload to sign for unchecked extrinsics. +/// A payload that has been signed for a unchecked extrinsics. +/// +/// Note that the payload that we sign to produce unchecked extrinsic signature +/// is going to be different than the `SignaturePayload` - so the thing the extrinsic +/// actually contains. pub struct SignedPayload { raw_payload: ( Call, @@ -178,6 +182,15 @@ impl SignedPayload where } } +impl Encode for SignedPayload where + Call: Encode, + Extra: SignedExtension, +{ + fn using_encoded R>(&self, f: F) -> R { + self.using_encoded(f) + } +} + impl Decode for UncheckedExtrinsic where diff --git a/node/runtime/src/lib.rs b/node/runtime/src/lib.rs index 1031f3ee945a4..5ba954ca2310b 100644 --- a/node/runtime/src/lib.rs +++ b/node/runtime/src/lib.rs @@ -39,7 +39,7 @@ use sr_primitives::{ApplyResult, impl_opaque_keys, generic, create_runtime_str, use sr_primitives::transaction_validity::TransactionValidity; use sr_primitives::weights::Weight; use sr_primitives::traits::{ - BlakeTwo256, Block as BlockT, DigestFor, NumberFor, StaticLookup, SaturatedConversion, + self, BlakeTwo256, Block as BlockT, DigestFor, NumberFor, StaticLookup, SaturatedConversion, }; use version::RuntimeVersion; use elections::VoteIndex; @@ -48,6 +48,7 @@ use version::NativeVersion; use primitives::OpaqueMetadata; use grandpa::{AuthorityId as GrandpaId, AuthorityWeight as GrandpaWeight}; use im_online::sr25519::{AuthorityId as ImOnlineId}; +use system::offchain::TransactionSubmitter; #[cfg(any(feature = "std", test))] pub use sr_primitives::BuildStorage; @@ -396,7 +397,7 @@ impl im_online::Trait for Runtime { type AuthorityId = ImOnlineId; type Call = Call; type Event = Event; - type SubmitTransaction = SubmitTransaction; + type SubmitTransaction = TransactionSubmitter; type ReportUnresponsiveness = Offences; type CurrentElectedSet = staking::CurrentElectedStashAccounts; } @@ -424,28 +425,33 @@ impl finality_tracker::Trait for Runtime { type ReportLatency = ReportLatency; } -impl system::offchain::GetPayload for Runtime { - fn get_payload(call: Call, index: Index) -> SignedPayload { - // TODO [ToDr] Where to take the fee from? - let fee = unimplemented!(); +impl system::offchain::CreateTransaction for Runtime { + type Signature = Signature; + + fn create_transaction>( + call: Call, + account: AccountId, + index: Index, + ) -> Option<(Call, ::SignaturePayload)> { let period = 1 << 8; let current_block = System::block_number().saturated_into::(); + let tip = 0; let extra: SignedExtra = ( system::CheckVersion::::new(), system::CheckGenesis::::new(), system::CheckEra::::from(generic::Era::mortal(period, current_block)), system::CheckNonce::::from(index), system::CheckWeight::::new(), - balances::TakeFees::::from(fee), + balances::TakeFees::::from(tip), ); - SignedPayload::new(call, extra); + let raw_payload = SignedPayload::new(call, extra).ok()?; + let signature = F::sign(account.clone(), &raw_payload)?; + let address = Indices::unlookup(account); + let (call, extra, _) = raw_payload.deconstruct(); + Some((call, (address, signature, extra))) } } -// TODO [ToDr] What type to use here? -type Signer = (ImOnlineId, UncheckedExtrinsic, Indices, Runtime); -type SubmitTransaction = system::offchain::TransactionSubmitter; - construct_runtime!( pub enum Runtime where Block = Block, diff --git a/srml/balances/src/lib.rs b/srml/balances/src/lib.rs index 0c838970451e1..b93422e214ab2 100644 --- a/srml/balances/src/lib.rs +++ b/srml/balances/src/lib.rs @@ -1187,7 +1187,6 @@ pub struct TakeFees, I: Instance = DefaultInstance>(#[codec(compact) impl, I: Instance> TakeFees { /// utility constructor. Used only in client/factory code. - #[cfg(feature = "std")] pub fn from(fee: T::Balance) -> Self { Self(fee) } diff --git a/srml/system/src/offchain.rs b/srml/system/src/offchain.rs index a28d97d279ef8..e91e253ec2533 100644 --- a/srml/system/src/offchain.rs +++ b/srml/system/src/offchain.rs @@ -16,54 +16,44 @@ //! Module helpers for offchain calls. -use codec::{Encode, Codec}; +use codec::Encode; use sr_primitives::app_crypto::RuntimeAppPublic; -use sr_primitives::generic::{UncheckedExtrinsic, SignedPayload}; -use sr_primitives::traits::{Extrinsic as ExtrinsicT, SignedExtension, StaticLookup, MaybeDebug}; +use sr_primitives::traits::Extrinsic as ExtrinsicT; -/// A trait responsible for producing signature payload for an extrinsic. -pub trait Signer { - fn sign( - account: T::AccountId, - nonce: T::Index, - call: Extrinsic::Call, - ) -> (Extrinsic::Call, Option); +/// A trait responsible for signing a payload using given account. +pub trait Signer { + /// Sign any encodable payload with given account and produce a signature. + /// + /// Returns `Some` if signing succeeded and `None` in case the `account` couldn't be used. + fn sign(account: Account, payload: &Payload) -> Option; } -pub trait GetPayload { - fn get_payload(call: Call, index: Index) -> Payload; +impl Signer for AppPublic where + AppPublic: RuntimeAppPublic + From, + AppPublic::Signature: Into, +{ + fn sign(account: Account, raw_payload: &Payload) -> Option { + raw_payload.using_encoded(|payload| { + AppPublic::from(account).sign(&payload).map(Into::into) + }) + } } -impl Signer> - for (TSigner, UncheckedExtrinsic, L, P) -where - TSigner: RuntimeAppPublic + From, - TSigner::Signature: Into, - Address: Codec + Clone + PartialEq + MaybeDebug, - Call: Encode, - T: crate::Trait, - Extra: SignedExtension, - L: StaticLookup, - P: GetPayload>, -{ - fn sign( +/// Creates runtime-specific signed transaction. +pub trait CreateTransaction { + type Signature; + + /// Attempt to create signed extrinsic data that encodes call from given account. + /// + /// Runtime implementation is free to construct the payload to sign and the signature + /// in any way it wants. + /// Returns `None` if signed extrinsic could not be created (either because signing failed + /// or because of any other runtime-specific reason). + fn create_transaction>( + call: Extrinsic::Call, account: T::AccountId, nonce: T::Index, - call: Call, - ) -> (Call, Option< - as ExtrinsicT>::SignaturePayload - >) { - let raw_payload = P::get_payload(call, nonce); - let signature = raw_payload.using_encoded(|payload| { - TSigner::from(account.clone()).sign(&payload) - }); - let address = L::unlookup(account); - let (call, extra, _) = raw_payload.deconstruct(); - match signature { - Some(sig) => (call, Some((address, sig.into(), extra))), - None => (call, None), - } - } + ) -> Option<(Extrinsic::Call, Extrinsic::SignaturePayload)>; } /// A trait to sign and submit transactions in offchain calls. @@ -71,8 +61,14 @@ pub trait SubmitSignedTransaction { /// Unchecked extrinsic type. type Extrinsic: ExtrinsicT + codec::Encode; - /// A runtime-specific function to sign and produce signature payload for extrinsic. - type Sign: Signer; + /// A runtime-specific type to produce signed data for the extrinsic. + type CreateTransaction: CreateTransaction; + + /// A type used to sign transactions created using `CreateTransaction`. + type Signer: Signer< + T::AccountId, + >::Signature, + >; /// Sign given call and submit it to the transaction pool. /// @@ -82,10 +78,10 @@ pub trait SubmitSignedTransaction { fn sign_and_submit(call: impl Into, id: T::AccountId) -> Result<(), ()> { let call = call.into(); let expected = >::account_nonce(&id); - let (call, signature_data) = Self::Sign::sign(id, expected, call); - // return an error if there is no signature_data, instead of producing unsigned extrinsic. - let signature_data = Some(signature_data.ok_or(())?); - let xt = Self::Extrinsic::new(call, signature_data).ok_or(())?; + let (call, signature_data) = Self::CreateTransaction + ::create_transaction::(call, id, expected) + .ok_or(())?; + let xt = Self::Extrinsic::new(call, Some(signature_data)).ok_or(())?; runtime_io::submit_transaction(&xt) } } @@ -95,7 +91,6 @@ pub trait SubmitUnsignedTransaction { /// Unchecked extrinsic type. type Extrinsic: ExtrinsicT + codec::Encode; - /// Submit given call to the transaction pool as unsigned transaction. /// /// Returns `Ok` if the transaction was submitted correctly @@ -107,11 +102,11 @@ pub trait SubmitUnsignedTransaction { } /// A default type used to submit transactions to the pool. -pub struct TransactionSubmitter { - _signer: rstd::marker::PhantomData<(S, E)>, +pub struct TransactionSubmitter { + _signer: rstd::marker::PhantomData<(S, C, E)>, } -impl Default for TransactionSubmitter { +impl Default for TransactionSubmitter { fn default() -> Self { Self { _signer: Default::default(), @@ -120,19 +115,21 @@ impl Default for TransactionSubmitter { } /// A blanket implementation to simplify creation of transaction signer & submitter in the runtime. -impl SubmitSignedTransaction for TransactionSubmitter where +impl SubmitSignedTransaction for TransactionSubmitter where T: crate::Trait, - S: Signer, - E: ExtrinsicT + codec::Encode, + C: CreateTransaction, + S: Signer>::Signature>, + E: ExtrinsicT + codec::Encode, { type Extrinsic = E; - type Sign = S; + type CreateTransaction = C; + type Signer = S; } /// A blanket impl to use the same submitter for usigned transactions as well. -impl SubmitUnsignedTransaction for TransactionSubmitter where +impl SubmitUnsignedTransaction for TransactionSubmitter where T: crate::Trait, - E: ExtrinsicT + codec::Encode, + E: ExtrinsicT + codec::Encode, { type Extrinsic = E; } From f74cfc46627a580ce32c89da401ed4e0d76873a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Thu, 29 Aug 2019 16:02:47 +0200 Subject: [PATCH 05/12] Improve docs. --- core/sr-primitives/src/traits.rs | 6 +++++- srml/support/src/lib.rs | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/core/sr-primitives/src/traits.rs b/core/sr-primitives/src/traits.rs index 8d4a842f7fd4c..fe3d67268f117 100644 --- a/core/sr-primitives/src/traits.rs +++ b/core/sr-primitives/src/traits.rs @@ -743,7 +743,11 @@ pub trait Extrinsic: Sized { /// The function call. type Call; - /// The signed data for signed extrinsics. + /// The payload we carry for signed extrinsics. + /// + /// Usually it will contain a `Signature` and + /// may include some additional data that are specific to signed + /// extrinsics. type SignaturePayload; /// Is this `Extrinsic` signed? diff --git a/srml/support/src/lib.rs b/srml/support/src/lib.rs index 604aaabf58c09..9ebd848fca4c4 100644 --- a/srml/support/src/lib.rs +++ b/srml/support/src/lib.rs @@ -114,7 +114,7 @@ macro_rules! parameter_types { } #[doc(inline)] -pub use ::srml_support_procedural::decl_storage; +pub use srml_support_procedural::decl_storage; /// Return Err of the expression: `return Err($expression);`. /// From 2c23ee0bb592dee911a97a8b0c13623c4915e523 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Thu, 29 Aug 2019 16:03:56 +0200 Subject: [PATCH 06/12] Bump version. --- node/runtime/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/node/runtime/src/lib.rs b/node/runtime/src/lib.rs index 6b3d729f666a1..7a29579e86e7a 100644 --- a/node/runtime/src/lib.rs +++ b/node/runtime/src/lib.rs @@ -81,7 +81,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { // implementation changes and behavior does not, then leave spec_version as // is and increment impl_version. spec_version: 154, - impl_version: 157, + impl_version: 158, apis: RUNTIME_API_VERSIONS, }; From 15160677ec1dbd5ba100642d4d4bb405c17d18e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Fri, 30 Aug 2019 10:32:02 +0200 Subject: [PATCH 07/12] Update core/sr-primitives/src/generic/unchecked_extrinsic.rs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Bastian Köcher --- core/sr-primitives/src/generic/unchecked_extrinsic.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/sr-primitives/src/generic/unchecked_extrinsic.rs b/core/sr-primitives/src/generic/unchecked_extrinsic.rs index c2bd9997c20b0..03cdd0334b3d2 100644 --- a/core/sr-primitives/src/generic/unchecked_extrinsic.rs +++ b/core/sr-primitives/src/generic/unchecked_extrinsic.rs @@ -130,7 +130,7 @@ where } } -/// A payload that has been signed for a unchecked extrinsics. +/// A payload that has been signed for an unchecked extrinsics. /// /// Note that the payload that we sign to produce unchecked extrinsic signature /// is going to be different than the `SignaturePayload` - so the thing the extrinsic From 5ee89366e58647c4b98f664b6b728eb84f03c6b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Fri, 30 Aug 2019 10:41:55 +0200 Subject: [PATCH 08/12] Fix tests & address grumbles. --- .../src/generic/unchecked_extrinsic.rs | 38 ++++++++----------- srml/authority-discovery/src/lib.rs | 2 +- 2 files changed, 16 insertions(+), 24 deletions(-) diff --git a/core/sr-primitives/src/generic/unchecked_extrinsic.rs b/core/sr-primitives/src/generic/unchecked_extrinsic.rs index 03cdd0334b3d2..aebf80edc63ec 100644 --- a/core/sr-primitives/src/generic/unchecked_extrinsic.rs +++ b/core/sr-primitives/src/generic/unchecked_extrinsic.rs @@ -135,13 +135,11 @@ where /// Note that the payload that we sign to produce unchecked extrinsic signature /// is going to be different than the `SignaturePayload` - so the thing the extrinsic /// actually contains. -pub struct SignedPayload { - raw_payload: ( +pub struct SignedPayload(( Call, Extra, Extra::AdditionalSigned, - ), -} +)); impl SignedPayload where Call: Encode, @@ -153,32 +151,17 @@ impl SignedPayload where pub fn new(call: Call, extra: Extra) -> Result { let additional_signed = extra.additional_signed()?; let raw_payload = (call, extra, additional_signed); - Ok(Self { raw_payload }) + Ok(Self(raw_payload)) } /// Create new `SignedPayload` from raw components. pub fn from_raw(call: Call, extra: Extra, additional_signed: Extra::AdditionalSigned) -> Self { - Self { - raw_payload: (call, extra, additional_signed), - } - } - - /// Get an encoded version of this payload. - /// - /// Payloads longer than 256 bytes are going to be `blake2_256`-hashed. - pub fn using_encoded(&self, f: impl FnOnce(&[u8]) -> O) -> O { - self.raw_payload.using_encoded(|payload| { - if payload.len() > 256 { - f(&blake2_256(payload)[..]) - } else { - f(payload) - } - }) + Self((call, extra, additional_signed)) } /// Deconstruct the payload into it's components. pub fn deconstruct(self) -> (Call, Extra, Extra::AdditionalSigned) { - self.raw_payload + self.0 } } @@ -186,8 +169,17 @@ impl Encode for SignedPayload where Call: Encode, Extra: SignedExtension, { + /// Get an encoded version of this payload. + /// + /// Payloads longer than 256 bytes are going to be `blake2_256`-hashed. fn using_encoded R>(&self, f: F) -> R { - self.using_encoded(f) + self.0.using_encoded(|payload| { + if payload.len() > 256 { + f(&blake2_256(payload)[..]) + } else { + f(payload) + } + }) } } diff --git a/srml/authority-discovery/src/lib.rs b/srml/authority-discovery/src/lib.rs index ffcb6672c8662..49495daf65fe5 100644 --- a/srml/authority-discovery/src/lib.rs +++ b/srml/authority-discovery/src/lib.rs @@ -194,7 +194,7 @@ mod tests { type AuthorityId = AuthorityId; type Call = im_online::Call; type Event = (); - type UncheckedExtrinsic = UncheckedExtrinsic<(), im_online::Call, (), ()>; + type SubmitTransaction = (); type ReportUnresponsiveness = (); type CurrentElectedSet = DummyCurrentElectedSet; } From 4f13af40808fdcf1aeb274ce77d114f5223ae010 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Fri, 30 Aug 2019 16:02:20 +0200 Subject: [PATCH 09/12] Fix build. --- srml/authority-discovery/src/lib.rs | 6 +++++- srml/system/src/offchain.rs | 1 - 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/srml/authority-discovery/src/lib.rs b/srml/authority-discovery/src/lib.rs index 49495daf65fe5..74b1c6172f869 100644 --- a/srml/authority-discovery/src/lib.rs +++ b/srml/authority-discovery/src/lib.rs @@ -194,7 +194,11 @@ mod tests { type AuthorityId = AuthorityId; type Call = im_online::Call; type Event = (); - type SubmitTransaction = (); + type SubmitTransaction = system::offchain::TransactionSubmitter< + (), + im_online::Call, + UncheckedExtrinsic<(), im_online::Call, (), ()>, + >; type ReportUnresponsiveness = (); type CurrentElectedSet = DummyCurrentElectedSet; } diff --git a/srml/system/src/offchain.rs b/srml/system/src/offchain.rs index e91e253ec2533..d67598f64fe02 100644 --- a/srml/system/src/offchain.rs +++ b/srml/system/src/offchain.rs @@ -133,4 +133,3 @@ impl SubmitUnsignedTransaction for TransactionSubmitt { type Extrinsic = E; } - From ddf540fcd71096bd8af6929c6cb85f0fb3027399 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Fri, 30 Aug 2019 17:25:35 +0200 Subject: [PATCH 10/12] Fix runtime tests. --- node/runtime/src/lib.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/node/runtime/src/lib.rs b/node/runtime/src/lib.rs index 7a29579e86e7a..a29c48a047612 100644 --- a/node/runtime/src/lib.rs +++ b/node/runtime/src/lib.rs @@ -393,11 +393,13 @@ impl sudo::Trait for Runtime { type Proposal = Call; } +type SubmitTransaction = TransactionSubmitter; + impl im_online::Trait for Runtime { type AuthorityId = ImOnlineId; type Call = Call; type Event = Event; - type SubmitTransaction = TransactionSubmitter; + type SubmitTransaction = SubmitTransaction; type ReportUnresponsiveness = Offences; type CurrentElectedSet = staking::CurrentElectedStashAccounts; } From b14dedbb9a30130ca87dcf8320a6aace36df8232 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Fri, 30 Aug 2019 18:17:19 +0200 Subject: [PATCH 11/12] Fix bound test. --- node/runtime/src/lib.rs | 13 ++++++++++++- srml/im-online/src/lib.rs | 12 ++++++++++++ 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/node/runtime/src/lib.rs b/node/runtime/src/lib.rs index a29c48a047612..5dc8d02eccde7 100644 --- a/node/runtime/src/lib.rs +++ b/node/runtime/src/lib.rs @@ -645,9 +645,20 @@ impl_runtime_apis! { #[cfg(test)] mod tests { use super::*; + use sr_primitives::app_crypto::RuntimeAppPublic; use system::offchain::SubmitSignedTransaction; - fn is_submit_signed_transaction(_arg: impl SubmitSignedTransaction) {} + fn is_submit_signed_transaction(_arg: T) where + T: SubmitSignedTransaction< + Runtime, + Call, + Extrinsic=UncheckedExtrinsic, + CreateTransaction=Runtime, + Signer=Signer, + >, + Signer: RuntimeAppPublic + From, + Signer::Signature: Into, + {} #[test] fn validate_bounds() { diff --git a/srml/im-online/src/lib.rs b/srml/im-online/src/lib.rs index 0dd27fa61acf8..c8494ef633ac8 100644 --- a/srml/im-online/src/lib.rs +++ b/srml/im-online/src/lib.rs @@ -93,6 +93,12 @@ pub mod sr25519 { mod app_sr25519 { use app_crypto::{app_crypto, key_types::IM_ONLINE, sr25519}; app_crypto!(sr25519, IM_ONLINE); + + impl From for sr_primitives::AnySignature { + fn from(sig: Signature) -> Self { + sr25519::Signature::from(sig).into() + } + } } /// An i'm online keypair using sr25519 as its crypto. @@ -110,6 +116,12 @@ pub mod ed25519 { mod app_ed25519 { use app_crypto::{app_crypto, key_types::IM_ONLINE, ed25519}; app_crypto!(ed25519, IM_ONLINE); + + impl From for sr_primitives::AnySignature { + fn from(sig: Signature) -> Self { + ed25519::Signature::from(sig).into() + } + } } /// An i'm online keypair using ed25519 as its crypto. From 09611d379cc4869209345b3c0a8e4b234e427835 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Fri, 30 Aug 2019 18:17:19 +0200 Subject: [PATCH 12/12] Fix bound test. --- node/cli/src/service.rs | 2 +- node/runtime/src/lib.rs | 13 ++++++++++++- srml/im-online/src/lib.rs | 12 ++++++++++++ 3 files changed, 25 insertions(+), 2 deletions(-) diff --git a/node/cli/src/service.rs b/node/cli/src/service.rs index 32e6a6798fa10..1fce1cc370a2d 100644 --- a/node/cli/src/service.rs +++ b/node/cli/src/service.rs @@ -289,7 +289,7 @@ mod tests { crypto::Pair as CryptoPair, blake2_256, sr25519::Public as AddressPublic, H256, }; - use sr_primitives::{generic::{BlockId, Era, Digest}, traits::Block, OpaqueExtrinsic}; + use sr_primitives::{generic::{BlockId, Era, Digest}, traits::Block, OpaqueExtrinsic, SignedPayload}; use timestamp; use finality_tracker; use keyring::AccountKeyring; diff --git a/node/runtime/src/lib.rs b/node/runtime/src/lib.rs index a29c48a047612..5dc8d02eccde7 100644 --- a/node/runtime/src/lib.rs +++ b/node/runtime/src/lib.rs @@ -645,9 +645,20 @@ impl_runtime_apis! { #[cfg(test)] mod tests { use super::*; + use sr_primitives::app_crypto::RuntimeAppPublic; use system::offchain::SubmitSignedTransaction; - fn is_submit_signed_transaction(_arg: impl SubmitSignedTransaction) {} + fn is_submit_signed_transaction(_arg: T) where + T: SubmitSignedTransaction< + Runtime, + Call, + Extrinsic=UncheckedExtrinsic, + CreateTransaction=Runtime, + Signer=Signer, + >, + Signer: RuntimeAppPublic + From, + Signer::Signature: Into, + {} #[test] fn validate_bounds() { diff --git a/srml/im-online/src/lib.rs b/srml/im-online/src/lib.rs index 0dd27fa61acf8..c8494ef633ac8 100644 --- a/srml/im-online/src/lib.rs +++ b/srml/im-online/src/lib.rs @@ -93,6 +93,12 @@ pub mod sr25519 { mod app_sr25519 { use app_crypto::{app_crypto, key_types::IM_ONLINE, sr25519}; app_crypto!(sr25519, IM_ONLINE); + + impl From for sr_primitives::AnySignature { + fn from(sig: Signature) -> Self { + sr25519::Signature::from(sig).into() + } + } } /// An i'm online keypair using sr25519 as its crypto. @@ -110,6 +116,12 @@ pub mod ed25519 { mod app_ed25519 { use app_crypto::{app_crypto, key_types::IM_ONLINE, ed25519}; app_crypto!(ed25519, IM_ONLINE); + + impl From for sr_primitives::AnySignature { + fn from(sig: Signature) -> Self { + ed25519::Signature::from(sig).into() + } + } } /// An i'm online keypair using ed25519 as its crypto.