Submit (& sign) extrinsics from the runtime. (#3514)

* 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 <bkchr@users.noreply.github.com>

* Fix tests & address grumbles.

* Fix build.

* Fix runtime tests.

* Fix bound test.

* Fix bound test.
This commit is contained in:
Tomasz Drwięga
2019-09-01 02:19:04 +02:00
committed by Gavin Wood
parent 0cae7217d8
commit feecfc856d
15 changed files with 346 additions and 71 deletions
+60 -3
View File
@@ -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,
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;
@@ -80,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,
};
@@ -392,11 +393,13 @@ impl sudo::Trait for Runtime {
type Proposal = Call;
}
type SubmitTransaction = TransactionSubmitter<ImOnlineId, Runtime, UncheckedExtrinsic>;
impl im_online::Trait for Runtime {
type AuthorityId = ImOnlineId;
type Call = Call;
type Event = Event;
type UncheckedExtrinsic = UncheckedExtrinsic;
type SubmitTransaction = SubmitTransaction;
type ReportUnresponsiveness = Offences;
type CurrentElectedSet = staking::CurrentElectedStashAccounts<Runtime>;
}
@@ -424,6 +427,33 @@ impl finality_tracker::Trait for Runtime {
type ReportLatency = ReportLatency;
}
impl system::offchain::CreateTransaction<Runtime, UncheckedExtrinsic> for Runtime {
type Signature = Signature;
fn create_transaction<F: system::offchain::Signer<AccountId, Self::Signature>>(
call: Call,
account: AccountId,
index: Index,
) -> Option<(Call, <UncheckedExtrinsic as traits::Extrinsic>::SignaturePayload)> {
let period = 1 << 8;
let current_block = System::block_number().saturated_into::<u64>();
let tip = 0;
let extra: SignedExtra = (
system::CheckVersion::<Runtime>::new(),
system::CheckGenesis::<Runtime>::new(),
system::CheckEra::<Runtime>::from(generic::Era::mortal(period, current_block)),
system::CheckNonce::<Runtime>::from(index),
system::CheckWeight::<Runtime>::new(),
balances::TakeFees::<Runtime>::from(tip),
);
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)))
}
}
construct_runtime!(
pub enum Runtime where
Block = Block,
@@ -475,6 +505,8 @@ pub type SignedExtra = (
);
/// Unchecked extrinsic type as expected by this runtime.
pub type UncheckedExtrinsic = generic::UncheckedExtrinsic<Address, Call, Signature, SignedExtra>;
/// The payload being signed in transactions.
pub type SignedPayload = generic::SignedPayload<Call, SignedExtra>;
/// Extrinsic type that has already been checked.
pub type CheckedExtrinsic = generic::CheckedExtrinsic<AccountId, Call, SignedExtra>;
/// Executive: handles dispatch to the various modules.
@@ -609,3 +641,28 @@ impl_runtime_apis! {
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use sr_primitives::app_crypto::RuntimeAppPublic;
use system::offchain::SubmitSignedTransaction;
fn is_submit_signed_transaction<T, Signer>(_arg: T) where
T: SubmitSignedTransaction<
Runtime,
Call,
Extrinsic=UncheckedExtrinsic,
CreateTransaction=Runtime,
Signer=Signer,
>,
Signer: RuntimeAppPublic + From<AccountId>,
Signer::Signature: Into<Signature>,
{}
#[test]
fn validate_bounds() {
let x = SubmitTransaction::default();
is_submit_signed_transaction(x);
}
}