Unverified Commit dd59eb3f authored by Fedor Sakharov's avatar Fedor Sakharov Committed by GitHub
Browse files

Adds an offchain call to submit double vote reports (#966)

* Adds an offchain call to submit double vote reports

* Some tweaks

* Remove unnecessary IdentifyAccount impls

* Adds ValidateDoubleVoteReports to test runtime

* sp-application-crypto is only a dev dependency
parent be1e2b31
Pipeline #88260 passed with stages
in 29 minutes and 5 seconds
......@@ -4355,6 +4355,7 @@ dependencies = [
"serde_derive",
"serde_json",
"sp-api",
"sp-application-crypto",
"sp-core",
"sp-inherents",
"sp-io",
......
......@@ -88,6 +88,17 @@ application_crypto::with_pair! {
/// so we define it to be the same type as `SessionKey`. In the future it may have different crypto.
pub type ValidatorSignature = validator_app::Signature;
/// The key type ID for a fisherman key.
pub const FISHERMAN_KEY_TYPE_ID: KeyTypeId = KeyTypeId(*b"fish");
mod fisherman_app {
use application_crypto::{app_crypto, sr25519};
app_crypto!(sr25519, super::FISHERMAN_KEY_TYPE_ID);
}
/// Identity that fishermen use when generating reports.
pub type FishermanId = fisherman_app::Public;
/// Retriability for a given active para.
#[derive(Clone, Eq, PartialEq, Encode, Decode)]
#[cfg_attr(feature = "std", derive(Debug))]
......
......@@ -39,6 +39,7 @@ hex-literal = "0.2.1"
keyring = { package = "sp-keyring", git = "https://github.com/paritytech/substrate", branch = "master" }
sp-trie = { git = "https://github.com/paritytech/substrate", branch = "master" }
babe = { package = "pallet-babe", git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
sp-application-crypto = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
randomness-collective-flip = { package = "pallet-randomness-collective-flip", git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
pallet-staking-reward-curve = { git = "https://github.com/paritytech/substrate", branch = "master" }
treasury = { package = "pallet-treasury", git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
......
......@@ -57,7 +57,10 @@ use sp_runtime::transaction_validity::InvalidTransaction;
use inherents::{ProvideInherent, InherentData, MakeFatalError, InherentIdentifier};
use system::{ensure_none, ensure_signed};
use system::{
ensure_none, ensure_signed,
offchain::SubmitSignedTransaction,
};
use crate::attestations::{self, IncludedBlocks};
use crate::registrar::Registrar;
......@@ -222,7 +225,7 @@ pub trait Trait: attestations::Trait + session::historical::Trait {
type Origin: From<Origin> + From<system::RawOrigin<Self::AccountId>>;
/// The outer call dispatch type.
type Call: Parameter + Dispatchable<Origin=<Self as Trait>::Origin>;
type Call: Parameter + Dispatchable<Origin=<Self as Trait>::Origin> + From<Call<Self>>;
/// Some way of interacting with balances for fees.
type ParachainCurrency: ParachainCurrency<Self::AccountId>;
......@@ -290,6 +293,9 @@ pub trait Trait: attestations::Trait + session::historical::Trait {
/// A type that converts the opaque hash type to exact one.
type BlockHashConversion: Convert<Self::Hash, primitives::Hash>;
/// Submit a signed transaction.
type SubmitSignedTransaction: SubmitSignedTransaction<Self, <Self as Trait>::Call>;
}
/// Origin for the parachains module.
......@@ -784,6 +790,21 @@ impl<T: Trait> Module<T> {
}
}
/// Submit a double vote report.
pub fn submit_double_vote_report(
report: DoubleVoteReport<T::Proof>,
) -> Option<()> {
let call = Call::report_double_vote(report);
let res = T::SubmitSignedTransaction::submit_signed(call);
if res.iter().any(|(_, r)| r.is_ok()) {
Some(())
} else {
None
}
}
/// Dispatch some messages from a parachain.
fn dispatch_message(
id: ParaId,
......@@ -1426,6 +1447,13 @@ impl<T> sp_std::fmt::Debug for ValidateDoubleVoteReports<T> where
}
}
impl<T> ValidateDoubleVoteReports<T> {
/// Create a new `ValidateDoubleVoteReports` struct.
pub fn new() -> Self {
ValidateDoubleVoteReports(sp_std::marker::PhantomData)
}
}
/// Custom validity error used while validating double vote reports.
#[derive(RuntimeDebug)]
#[repr(u8)]
......@@ -1522,7 +1550,7 @@ mod tests {
Perbill, curve::PiecewiseLinear,
traits::{
BlakeTwo256, IdentityLookup, SaturatedConversion,
OpaqueKeys,
OpaqueKeys, Extrinsic as ExtrinsicT,
},
testing::TestXt,
};
......@@ -1787,6 +1815,31 @@ mod tests {
pub const SlashPeriod: BlockNumber = 50;
}
// This is needed for a custom `AccountId` type which is `u64` in testing here.
pub mod test_keys {
use sp_core::crypto::KeyTypeId;
pub const KEY_TYPE: KeyTypeId = KeyTypeId(*b"test");
mod app {
use sp_application_crypto::{app_crypto, sr25519};
use super::super::Parachains;
app_crypto!(sr25519, super::KEY_TYPE);
impl sp_runtime::traits::IdentifyAccount for Public {
type AccountId = u64;
fn into_account(self) -> Self::AccountId {
Parachains::authorities().iter().position(|b| *b == self.0.clone().into()).unwrap() as u64
}
}
}
pub type ReporterId = app::Public;
pub type ReporterSignature = app::Signature;
}
impl Trait for Test {
type Origin = Origin;
type Call = Call;
......@@ -1807,6 +1860,27 @@ mod tests {
type ReportOffence = Offences;
type BlockHashConversion = sp_runtime::traits::Identity;
type KeyOwnerProofSystem = Historical;
type SubmitSignedTransaction = system::offchain::TransactionSubmitter<
test_keys::ReporterId,
Test,
Extrinsic,
>;
}
type Extrinsic = TestXt<Call, ()>;
impl system::offchain::CreateTransaction<Test, Extrinsic> for Test {
type Public = test_keys::ReporterId;
type Signature = test_keys::ReporterSignature;
fn create_transaction<F: system::offchain::Signer<Self::Public, Self::Signature>>(
call: <Extrinsic as ExtrinsicT>::Call,
_public: Self::Public,
_account: <Test as system::Trait>::AccountId,
nonce: <Test as system::Trait>::Index,
) -> Option<(<Extrinsic as ExtrinsicT>::Call, <Extrinsic as ExtrinsicT>::SignaturePayload)> {
Some((call, (nonce, ())))
}
}
type Parachains = Module<Test>;
......
......@@ -563,6 +563,15 @@ impl<T: Trait> ActiveParas for Module<T> {
pub struct LimitParathreadCommits<T: Trait + Send + Sync>(sp_std::marker::PhantomData<T>) where
<T as system::Trait>::Call: IsSubType<Module<T>, T>;
impl<T: Trait + Send + Sync> LimitParathreadCommits<T> where
<T as system::Trait>::Call: IsSubType<Module<T>, T>
{
/// Create a new `LimitParathreadCommits` struct.
pub fn new() -> Self {
LimitParathreadCommits(sp_std::marker::PhantomData)
}
}
impl<T: Trait + Send + Sync> sp_std::fmt::Debug for LimitParathreadCommits<T> where
<T as system::Trait>::Call: IsSubType<Module<T>, T>
{
......@@ -658,7 +667,7 @@ mod tests {
use sp_runtime::{
traits::{
BlakeTwo256, IdentityLookup, Dispatchable,
AccountIdConversion,
AccountIdConversion, Extrinsic as ExtrinsicT,
}, testing::{UintAuthorityId, TestXt}, KeyTypeId, Perbill, curve::PiecewiseLinear,
};
use primitives::{
......@@ -840,6 +849,32 @@ mod tests {
type FullIdentificationOf = staking::ExposureOf<Self>;
}
// This is needed for a custom `AccountId` type which is `u64` in testing here.
pub mod test_keys {
use sp_core::crypto::KeyTypeId;
pub const KEY_TYPE: KeyTypeId = KeyTypeId(*b"test");
mod app {
use super::super::Parachains;
use sp_application_crypto::{app_crypto, sr25519};
app_crypto!(sr25519, super::KEY_TYPE);
impl sp_runtime::traits::IdentifyAccount for Public {
type AccountId = u64;
fn into_account(self) -> Self::AccountId {
let id = self.0.clone().into();
Parachains::authorities().iter().position(|b| *b == id).unwrap() as u64
}
}
}
pub type ReporterId = app::Public;
pub type ReporterSignature = app::Signature;
}
impl parachains::Trait for Test {
type Origin = Origin;
type Call = Call;
......@@ -858,6 +893,27 @@ mod tests {
type IdentificationTuple = <Self::KeyOwnerProofSystem as KeyOwnerProofSystem<(KeyTypeId, Vec<u8>)>>::IdentificationTuple;
type ReportOffence = ();
type BlockHashConversion = sp_runtime::traits::Identity;
type SubmitSignedTransaction = system::offchain::TransactionSubmitter<
test_keys::ReporterId,
Test,
Extrinsic,
>;
}
type Extrinsic = TestXt<Call, ()>;
impl system::offchain::CreateTransaction<Test, Extrinsic> for Test {
type Public = test_keys::ReporterId;
type Signature = test_keys::ReporterSignature;
fn create_transaction<F: system::offchain::Signer<Self::Public, Self::Signature>>(
call: <Extrinsic as ExtrinsicT>::Call,
_public: Self::Public,
_account: <Test as system::Trait>::AccountId,
nonce: <Test as system::Trait>::Index,
) -> Option<(<Extrinsic as ExtrinsicT>::Call, <Extrinsic as ExtrinsicT>::SignaturePayload)> {
Some((call, (nonce, ())))
}
}
parameter_types! {
......
......@@ -41,7 +41,7 @@ use sp_runtime::{
curve::PiecewiseLinear,
traits::{
BlakeTwo256, Block as BlockT, SignedExtension, OpaqueKeys, ConvertInto, IdentityLookup,
DispatchInfoOf,
DispatchInfoOf, Extrinsic as ExtrinsicT, SaturatedConversion,
},
};
#[cfg(feature = "runtime-benchmarks")]
......@@ -53,7 +53,8 @@ use version::NativeVersion;
use sp_core::OpaqueMetadata;
use sp_staking::SessionIndex;
use frame_support::{
parameter_types, construct_runtime, traits::{KeyOwnerProofSystem, SplitTwoWays, Randomness},
parameter_types, construct_runtime, debug,
traits::{KeyOwnerProofSystem, SplitTwoWays, Randomness},
};
use im_online::sr25519::AuthorityId as ImOnlineId;
use authority_discovery_primitives::AuthorityId as AuthorityDiscoveryId;
......@@ -539,6 +540,46 @@ impl parachains::Trait for Runtime {
type IdentificationTuple = <Self::KeyOwnerProofSystem as KeyOwnerProofSystem<(KeyTypeId, Vec<u8>)>>::IdentificationTuple;
type ReportOffence = Offences;
type BlockHashConversion = sp_runtime::traits::Identity;
type SubmitSignedTransaction = TransactionSubmitter<parachain::FishermanId, Runtime, UncheckedExtrinsic>;
}
impl system::offchain::CreateTransaction<Runtime, UncheckedExtrinsic> for Runtime {
type Public = <primitives::Signature as sp_runtime::traits::Verify>::Signer;
type Signature = primitives::Signature;
fn create_transaction<TSigner: system::offchain::Signer<Self::Public, Self::Signature>>(
call: <UncheckedExtrinsic as ExtrinsicT>::Call,
public: Self::Public,
account: <Runtime as system::Trait>::AccountId,
nonce: <Runtime as system::Trait>::Index,
) -> Option<(Call, <UncheckedExtrinsic as ExtrinsicT>::SignaturePayload)> {
let period = BlockHashCount::get()
.checked_next_power_of_two()
.map(|c| c / 2)
.unwrap_or(2) as u64;
let current_block = System::block_number()
.saturated_into::<u64>()
.saturating_sub(1);
let tip = 0;
let extra: SignedExtra = (
RestrictFunctionality,
system::CheckVersion::<Runtime>::new(),
system::CheckGenesis::<Runtime>::new(),
system::CheckEra::<Runtime>::from(generic::Era::mortal(period, current_block)),
system::CheckNonce::<Runtime>::from(nonce),
system::CheckWeight::<Runtime>::new(),
transaction_payment::ChargeTransactionPayment::<Runtime>::from(tip),
registrar::LimitParathreadCommits::<Runtime>::new(),
parachains::ValidateDoubleVoteReports::<Runtime>::new(),
);
let raw_payload = SignedPayload::new(call, extra).map_err(|e| {
debug::warn!("Unable to create signed payload: {:?}", e)
}).ok()?;
let signature = TSigner::sign(public, &raw_payload)?;
let (call, extra, _) = raw_payload.deconstruct();
Some((call, (account, signature, extra)))
}
}
parameter_types! {
......@@ -769,6 +810,8 @@ pub type UncheckedExtrinsic = generic::UncheckedExtrinsic<Address, Call, Signatu
pub type CheckedExtrinsic = generic::CheckedExtrinsic<AccountId, Nonce, Call>;
/// Executive: handles dispatch to the various modules.
pub type Executive = executive::Executive<Runtime, Block, system::ChainContext<Runtime>, Runtime, AllModules>;
/// The payload being signed in the transactions.
pub type SignedPayload = generic::SignedPayload<Call, SignedExtra>;
sp_api::impl_runtime_apis! {
impl sp_api::Core<Block> for Runtime {
......
......@@ -42,7 +42,7 @@ use sp_runtime::{
curve::PiecewiseLinear,
traits::{
BlakeTwo256, Block as BlockT, SignedExtension, OpaqueKeys, ConvertInto,
IdentityLookup, DispatchInfoOf,
DispatchInfoOf, IdentityLookup, Extrinsic as ExtrinsicT, SaturatedConversion,
},
};
#[cfg(feature = "runtime-benchmarks")]
......@@ -54,7 +54,8 @@ use version::NativeVersion;
use sp_core::OpaqueMetadata;
use sp_staking::SessionIndex;
use frame_support::{
parameter_types, construct_runtime, traits::{KeyOwnerProofSystem, SplitTwoWays, Randomness},
parameter_types, construct_runtime, debug,
traits::{KeyOwnerProofSystem, SplitTwoWays, Randomness},
};
use im_online::sr25519::AuthorityId as ImOnlineId;
use authority_discovery_primitives::AuthorityId as AuthorityDiscoveryId;
......@@ -545,6 +546,46 @@ impl parachains::Trait for Runtime {
type IdentificationTuple = <Self::KeyOwnerProofSystem as KeyOwnerProofSystem<(KeyTypeId, Vec<u8>)>>::IdentificationTuple;
type ReportOffence = Offences;
type BlockHashConversion = sp_runtime::traits::Identity;
type SubmitSignedTransaction = TransactionSubmitter<parachain::FishermanId, Runtime, UncheckedExtrinsic>;
}
impl system::offchain::CreateTransaction<Runtime, UncheckedExtrinsic> for Runtime {
type Public = <primitives::Signature as sp_runtime::traits::Verify>::Signer;
type Signature = primitives::Signature;
fn create_transaction<TSigner: system::offchain::Signer<Self::Public, Self::Signature>>(
call: <UncheckedExtrinsic as ExtrinsicT>::Call,
public: Self::Public,
account: <Runtime as system::Trait>::AccountId,
nonce: <Runtime as system::Trait>::Index,
) -> Option<(Call, <UncheckedExtrinsic as ExtrinsicT>::SignaturePayload)> {
let period = BlockHashCount::get()
.checked_next_power_of_two()
.map(|c| c / 2)
.unwrap_or(2) as u64;
let current_block = System::block_number()
.saturated_into::<u64>()
.saturating_sub(1);
let tip = 0;
let extra: SignedExtra = (
OnlyStakingAndClaims,
system::CheckVersion::<Runtime>::new(),
system::CheckGenesis::<Runtime>::new(),
system::CheckEra::<Runtime>::from(generic::Era::mortal(period, current_block)),
system::CheckNonce::<Runtime>::from(nonce),
system::CheckWeight::<Runtime>::new(),
transaction_payment::ChargeTransactionPayment::<Runtime>::from(tip),
registrar::LimitParathreadCommits::<Runtime>::new(),
parachains::ValidateDoubleVoteReports::<Runtime>::new(),
);
let raw_payload = SignedPayload::new(call, extra).map_err(|e| {
debug::warn!("Unable to create signed payload: {:?}", e)
}).ok()?;
let signature = TSigner::sign(public, &raw_payload)?;
let (call, extra, _) = raw_payload.deconstruct();
Some((call, (account, signature, extra)))
}
}
parameter_types! {
......@@ -687,6 +728,8 @@ pub type UncheckedExtrinsic = generic::UncheckedExtrinsic<Address, Call, Signatu
pub type CheckedExtrinsic = generic::CheckedExtrinsic<AccountId, Nonce, Call>;
/// Executive: handles dispatch to the various modules.
pub type Executive = executive::Executive<Runtime, Block, system::ChainContext<Runtime>, Runtime, AllModules>;
/// The payload being signed in transactions.
pub type SignedPayload = generic::SignedPayload<Call, SignedExtra>;
sp_api::impl_runtime_apis! {
impl sp_api::Core<Block> for Runtime {
......
......@@ -41,7 +41,7 @@ use sp_runtime::{
curve::PiecewiseLinear,
traits::{
BlakeTwo256, Block as BlockT, StaticLookup, SignedExtension, OpaqueKeys, ConvertInto,
DispatchInfoOf,
DispatchInfoOf, Extrinsic as ExtrinsicT, SaturatedConversion,
},
};
use version::RuntimeVersion;
......@@ -51,11 +51,12 @@ use version::NativeVersion;
use sp_core::OpaqueMetadata;
use sp_staking::SessionIndex;
use frame_support::{
parameter_types, construct_runtime,
parameter_types, construct_runtime, debug,
traits::{KeyOwnerProofSystem, Randomness},
};
use pallet_transaction_payment_rpc_runtime_api::RuntimeDispatchInfo;
use session::historical as session_historical;
use system::offchain::TransactionSubmitter;
#[cfg(feature = "std")]
pub use staking::StakerStatus;
......@@ -348,6 +349,47 @@ impl parachains::Trait for Runtime {
>::IdentificationTuple;
type ReportOffence = Offences;
type BlockHashConversion = sp_runtime::traits::Identity;
type SubmitSignedTransaction = TransactionSubmitter<parachain::FishermanId, Runtime, UncheckedExtrinsic>;
}
impl system::offchain::CreateTransaction<Runtime, UncheckedExtrinsic> for Runtime {
type Public = <primitives::Signature as sp_runtime::traits::Verify>::Signer;
type Signature = primitives::Signature;
fn create_transaction<TSigner: system::offchain::Signer<Self::Public, Self::Signature>>(
call: <UncheckedExtrinsic as ExtrinsicT>::Call,
public: Self::Public,
account: <Runtime as system::Trait>::AccountId,
nonce: <Runtime as system::Trait>::Index,
) -> Option<(Call, <UncheckedExtrinsic as ExtrinsicT>::SignaturePayload)> {
let period = BlockHashCount::get()
.checked_next_power_of_two()
.map(|c| c / 2)
.unwrap_or(2) as u64;
let current_block = System::block_number()
.saturated_into::<u64>()
.saturating_sub(1);
let tip = 0;
let extra: SignedExtra = (
RestrictFunctionality,
system::CheckVersion::<Runtime>::new(),
system::CheckGenesis::<Runtime>::new(),
system::CheckEra::<Runtime>::from(generic::Era::mortal(period, current_block)),
system::CheckNonce::<Runtime>::from(nonce),
system::CheckWeight::<Runtime>::new(),
transaction_payment::ChargeTransactionPayment::<Runtime>::from(tip),
registrar::LimitParathreadCommits::<Runtime>::new(),
parachains::ValidateDoubleVoteReports::<Runtime>::new(),
);
let raw_payload = SignedPayload::new(call, extra).map_err(|e| {
debug::warn!("Unable to create signed payload: {:?}", e)
}).ok()?;
let signature = TSigner::sign(public, &raw_payload)?;
let (call, extra, _) = raw_payload.deconstruct();
let address = Indices::unlookup(account);
Some((call, (address, signature, extra)))
}
}
impl offences::Trait for Runtime {
......@@ -467,7 +509,8 @@ pub type SignedExtra = (
system::CheckNonce<Runtime>,
system::CheckWeight<Runtime>,
transaction_payment::ChargeTransactionPayment::<Runtime>,
registrar::LimitParathreadCommits<Runtime>
registrar::LimitParathreadCommits<Runtime>,
parachains::ValidateDoubleVoteReports<Runtime>,
);
/// Unchecked extrinsic type as expected by this runtime.
pub type UncheckedExtrinsic = generic::UncheckedExtrinsic<Address, Call, Signature, SignedExtra>;
......@@ -475,6 +518,8 @@ pub type UncheckedExtrinsic = generic::UncheckedExtrinsic<Address, Call, Signatu
pub type CheckedExtrinsic = generic::CheckedExtrinsic<AccountId, Nonce, Call>;
/// Executive: handles dispatch to the various modules.
pub type Executive = executive::Executive<Runtime, Block, system::ChainContext<Runtime>, Runtime, AllModules>;
/// The payload being signed in transactions.
pub type SignedPayload = generic::SignedPayload<Call, SignedExtra>;
pub type Hash = <Block as BlockT>::Hash;
pub type Extrinsic = <Block as BlockT>::Extrinsic;
......
......@@ -40,7 +40,7 @@ use sp_runtime::{
curve::PiecewiseLinear,
traits::{
BlakeTwo256, Block as BlockT, SignedExtension, OpaqueKeys, ConvertInto, IdentityLookup,
DispatchInfoOf,
DispatchInfoOf, StaticLookup, Extrinsic as ExtrinsicT, SaturatedConversion,
},
};
#[cfg(feature = "runtime-benchmarks")]
......@@ -51,7 +51,10 @@ use grandpa::{AuthorityId as GrandpaId, fg_primitives};
use version::NativeVersion;
use sp_core::OpaqueMetadata;
use sp_staking::SessionIndex;
use frame_support::{parameter_types, construct_runtime, traits::{KeyOwnerProofSystem, Randomness}};
use frame_support::{
parameter_types, construct_runtime, debug,
traits::{KeyOwnerProofSystem, Randomness},
};
use im_online::sr25519::AuthorityId as ImOnlineId;
use authority_discovery_primitives::AuthorityId as AuthorityDiscoveryId;
use system::offchain::TransactionSubmitter;
......@@ -407,6 +410,46 @@ impl parachains::Trait for Runtime {
type IdentificationTuple = <Self::KeyOwnerProofSystem as KeyOwnerProofSystem<(KeyTypeId, Vec<u8>)>>::IdentificationTuple;
type ReportOffence = Offences;
type BlockHashConversion = sp_runtime::traits::Identity;
type SubmitSignedTransaction = TransactionSubmitter<parachain::FishermanId, Runtime, UncheckedExtrinsic>;
}
impl system::offchain::CreateTransaction<Runtime, UncheckedExtrinsic> for Runtime {
type Public = <primitives::Signature as sp_runtime::traits::Verify>::Signer;
type Signature = primitives::Signature;
fn create_transaction<TSigner: system::offchain::Signer<Self::Public, Self::Signature>>(
call: <UncheckedExtrinsic as ExtrinsicT>::Call,
public: Self::Public,
account: <Runtime as system::Trait>::AccountId,
nonce: <Runtime as system::Trait>::Index,
) -> Option<(Call, <UncheckedExtrinsic as ExtrinsicT>::SignaturePayload)> {
let period = BlockHashCount::get()
.checked_next_power_of_two()
.map(|c| c / 2)
.unwrap_or(2) as u64;
let current_block = System::block_number()
.saturated_into::<u64>()
.saturating_sub(1);
let tip = 0;
let extra: SignedExtra = (
RestrictFunctionality,
system::CheckVersion::<Runtime>::new(),
system::CheckGenesis::<Runtime>::new(),
system::CheckEra::<Runtime>::from(generic::Era::mortal(period, current_block)),
system::CheckNonce::<Runtime>::from(nonce),
system::CheckWeight::<Runtime>::new(),
transaction_payment::ChargeTransactionPayment::<Runtime>::from(tip),
registrar::LimitParathreadCommits::<Runtime>::new(),
parachains::ValidateDoubleVoteReports::<Runtime>::new(),
);
let raw_payload = SignedPayload::new(call, extra).map_err(|e| {
debug::warn!("Unable to create signed payload: {:?}", e)
}).ok()?;
let signature = TSigner::sign(public, &raw_payload)?;
let (call, extra, _) = raw_payload.deconstruct();
Some((call, (account, signature, extra)))
}
}
parameter_types! {
......@@ -580,6 +623,8 @@ pub type UncheckedExtrinsic = generic::UncheckedExtrinsic<Address, Call, Signatu
pub type CheckedExtrinsic = generic::CheckedExtrinsic<AccountId, Nonce, Call>;
/// Executive: handles dispatch to the various modules.
pub type Executive = executive::Executive<Runtime, Block, system::ChainContext<Runtime>, Runtime, AllModules>;
/// The payload being signed in transactions.
pub type SignedPayload = generic::SignedPayload<Call, SignedExtra>;
sp_api::impl_runtime_apis! {
impl sp_api::Core<Block> for Runtime {
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment