Skip to content

Commit

Permalink
Validate unsigned (#226)
Browse files Browse the repository at this point in the history
* validate unsigned

* docs

* disabling async backing resolves region transfer e2e test error

* fix test

* fix other tests

* remove code duplication
  • Loading branch information
Szegoo authored Aug 8, 2024
1 parent 5890fcd commit b99b5c7
Show file tree
Hide file tree
Showing 8 changed files with 78 additions and 30 deletions.
22 changes: 22 additions & 0 deletions e2e_tests/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,27 @@ async function submitExtrinsic(
});
}

async function submitUnsigned(
call: SubmittableExtrinsic<'promise'>,
): Promise<void> {
return new Promise((resolve, reject) => {
const unsub = call.send(({ status, isError }) => {
console.log(`Current status is ${status}`);
if (status.isInBlock) {
console.log(`Transaction included at blockHash ${status.asInBlock}`);
} else if (status.isFinalized) {
console.log(`Transaction finalized at blockHash ${status.asFinalized}`);
unsub.then();
return resolve();
} else if (isError) {
console.log('Transaction error');
unsub.then();
return reject();
}
});
});
}

async function setupRelayAsset(api: ApiPromise, signer: KeyringPair, initialBalance = 0n) {
// The relay asset is registered in the genesis block.

Expand Down Expand Up @@ -147,6 +168,7 @@ export {
sleep,
openHrmpChannel,
submitExtrinsic,
submitUnsigned,
transferRelayAssetToPara,
getAddressFromModuleId,
getFreeBalance,
Expand Down
22 changes: 2 additions & 20 deletions e2e_tests/ismp.common.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { ApiPromise } from '@polkadot/api';
import { KeyringPair } from '@polkadot/keyring/types';
import { ISubmittableResult } from '@polkadot/types/types';
import { submitExtrinsic } from './common';
import { submitExtrinsic, submitUnsigned } from './common';
import { Get, IsmpRequest } from './types';

async function ismpAddParachain(signer: KeyringPair, regionXApi: ApiPromise) {
Expand Down Expand Up @@ -59,24 +58,7 @@ async function makeIsmpResponse(
},
},
]);

return new Promise((resolve, reject) => {
const unsub = response.send((result: ISubmittableResult) => {
const { status, isError } = result;
console.log(`Current status is ${status}`);
if (status.isInBlock) {
console.log(`Transaction included at blockHash ${status.asInBlock}`);
} else if (status.isFinalized) {
console.log(`Transaction finalized at blockHash ${status.asFinalized}`);
unsub.then();
return resolve();
} else if (isError) {
console.log('Transaction error');
unsub.then();
return reject();
}
});
});
await submitUnsigned(response);
} else {
new Error('Expected a Get request');
}
Expand Down
4 changes: 2 additions & 2 deletions e2e_tests/xc-regions.common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { ApiPromise, Keyring } from '@polkadot/api';
import { KeyringPair } from '@polkadot/keyring/types';
import { getEncodedRegionId, RegionId } from 'coretime-utils';
import assert from 'node:assert';
import { sleep, submitExtrinsic } from './common';
import { sleep, submitExtrinsic, submitUnsigned } from './common';
import { makeIsmpResponse, queryRequest } from './ismp.common';

const REGIONX_SOVEREIGN_ACCOUNT = '5Eg2fntJ27qsari4FGrGhrMqKFDRnkNSR6UshkZYBGXmSuC8';
Expand Down Expand Up @@ -69,7 +69,7 @@ async function transferRegionToRegionX(
await sleep(5000);

const requestRecord = regionXApi.tx.regions.requestRegionRecord(regionId);
await submitExtrinsic(sender, requestRecord, {});
await submitUnsigned(requestRecord);

let regions = await regionXApi.query.regions.regions.entries();
assert.equal(regions.length, 1);
Expand Down
2 changes: 2 additions & 0 deletions pallets/market/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,7 @@ impl<T: crate::Config> IsmpDispatcher for MockDispatcher<T> {

parameter_types! {
pub const CoretimeChain: StateMachine = StateMachine::Kusama(1005); // coretime-kusama
pub const RegionsUnsignedPriority: TransactionPriority = TransactionPriority::max_value();
}

impl pallet_regions::Config for Test {
Expand All @@ -138,6 +139,7 @@ impl pallet_regions::Config for Test {
type IsmpDispatcher = MockDispatcher<Self>;
type StateMachineHeightProvider = MockStateMachineHeightProvider;
type Timeout = ConstU64<1000>;
type UnsignedPriority = RegionsUnsignedPriority;
type WeightInfo = ();
}

Expand Down
2 changes: 2 additions & 0 deletions pallets/processor/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,7 @@ impl<T: crate::Config> IsmpDispatcher for MockDispatcher<T> {

parameter_types! {
pub const CoretimeChainStateMachine: StateMachine = StateMachine::Kusama(1005); // coretime-kusama
pub const RegionsUnsignedPriority: TransactionPriority = TransactionPriority::max_value();
}

impl pallet_regions::Config for Test {
Expand All @@ -173,6 +174,7 @@ impl pallet_regions::Config for Test {
type IsmpDispatcher = MockDispatcher<Self>;
type StateMachineHeightProvider = MockStateMachineHeightProvider;
type Timeout = ConstU64<1000>;
type UnsignedPriority = RegionsUnsignedPriority;
type WeightInfo = ();
}

Expand Down
39 changes: 39 additions & 0 deletions pallets/regions/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,10 @@ const LOG_TARGET: &str = "runtime::regions";
/// Constant Pallet ID
pub const PALLET_ID: ModuleId = ModuleId::Pallet(PalletId(*b"regionsp"));

// Custom transaction error codes
const REGION_NOT_FOUND: u8 = 1;
const REGION_NOT_UNAVAILABLE: u8 = 2;

#[frame_support::pallet]
pub mod pallet {
use super::*;
Expand Down Expand Up @@ -93,6 +97,10 @@ pub mod pallet {
/// Number of seconds before a GET request times out.
type Timeout: Get<u64>;

/// The priority of unsigned transactions.
#[pallet::constant]
type UnsignedPriority: Get<TransactionPriority>;

/// Weight Info
type WeightInfo: WeightInfo;
}
Expand Down Expand Up @@ -281,6 +289,37 @@ pub mod pallet {
Ok(key)
}
}

#[pallet::validate_unsigned]
impl<T: Config> ValidateUnsigned for Pallet<T> {
type Call = Call<T>;
fn validate_unsigned(_source: TransactionSource, call: &Self::Call) -> TransactionValidity {
let region_id = match call {
Call::request_region_record { region_id } => region_id,
_ => return InvalidTransaction::Call.into(),
};

let Some(region) = Regions::<T>::get(region_id) else {
return InvalidTransaction::Custom(REGION_NOT_FOUND).into()
};

if !region.record.is_unavailable() {
return InvalidTransaction::Custom(REGION_NOT_UNAVAILABLE).into()
}

ValidTransaction::with_tag_prefix("RecordRequest")
.priority(T::UnsignedPriority::get())
.and_provides(region_id)
.propagate(true)
.build()
}

fn pre_dispatch(_call: &Self::Call) -> Result<(), TransactionValidityError> {
// Given that the `request_region_record` function contains checks there is no need to
// call `validate_unsigned` again.
Ok(())
}
}
}

/// Module callback for the pallet
Expand Down
2 changes: 2 additions & 0 deletions pallets/regions/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ impl pallet_balances::Config for Test {

parameter_types! {
pub const CoretimeChain: StateMachine = StateMachine::Kusama(1005); // coretime-kusama
pub const RegionsUnsignedPriority: TransactionPriority = TransactionPriority::max_value();
}

pub struct MockStateMachineHeightProvider;
Expand All @@ -101,6 +102,7 @@ impl crate::Config for Test {
type IsmpDispatcher = MockDispatcher<Self>;
type StateMachineHeightProvider = MockStateMachineHeightProvider;
type Timeout = ConstU64<1000>;
type UnsignedPriority = RegionsUnsignedPriority;
type WeightInfo = ();
}

Expand Down
15 changes: 7 additions & 8 deletions runtime/cocos/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ use sp_runtime::{
traits::{
AccountIdConversion, AccountIdLookup, BlakeTwo256, Block as BlockT, Convert, IdentityLookup,
},
transaction_validity::{TransactionSource, TransactionValidity},
transaction_validity::{TransactionPriority, TransactionSource, TransactionValidity},
ApplyExtrinsicResult,
};

Expand Down Expand Up @@ -207,7 +207,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion {
/// up by `pallet_aura` to implement `fn slot_duration()`.
///
/// Change this to adjust the block time.
pub const MILLISECS_PER_BLOCK: u64 = 6000;
pub const MILLISECS_PER_BLOCK: u64 = 12000;

// NOTE: Currently it is not possible to change the slot duration after the chain has started.
// Attempting to do so will brick block production.
Expand All @@ -234,7 +234,7 @@ pub const fn deposit(items: u32, bytes: u32) -> Balance {

/// Maximum number of blocks simultaneously accepted by the Runtime, not yet included
/// into the relay chain.
const UNINCLUDED_SEGMENT_CAPACITY: u32 = 3;
const UNINCLUDED_SEGMENT_CAPACITY: u32 = 1;
/// How many parachain blocks are processed by the relay chain per parent. Limits the
/// number of blocks authored per slot.
const BLOCK_PROCESSING_VELOCITY: u32 = 1;
Expand All @@ -254,7 +254,7 @@ const NORMAL_DISPATCH_RATIO: Perbill = Perbill::from_percent(75);

/// We allow for 0.5 of a second of compute with a 12 second average block time.
const MAXIMUM_BLOCK_WEIGHT: Weight = Weight::from_parts(
WEIGHT_REF_TIME_PER_SECOND.saturating_mul(2),
WEIGHT_REF_TIME_PER_SECOND.saturating_div(2),
cumulus_primitives_core::relay_chain::MAX_POV_SIZE as u64,
);

Expand Down Expand Up @@ -352,9 +352,6 @@ impl pallet_timestamp::Config for Runtime {
/// A timestamp: milliseconds since the unix epoch.
type Moment = u64;
type OnTimestampSet = Aura;
#[cfg(feature = "experimental")]
type MinimumPeriod = ConstU64<0>;
#[cfg(not(feature = "experimental"))]
type MinimumPeriod = ConstU64<{ SLOT_DURATION / 2 }>;
type WeightInfo = weights::pallet_timestamp::WeightInfo<Runtime>;
}
Expand Down Expand Up @@ -571,7 +568,7 @@ impl pallet_aura::Config for Runtime {
type AuthorityId = AuraId;
type DisabledValidators = ();
type MaxAuthorities = ConstU32<100_000>;
type AllowMultipleBlocksPerSlot = ConstBool<true>;
type AllowMultipleBlocksPerSlot = ConstBool<false>;
}

parameter_types! {
Expand Down Expand Up @@ -615,6 +612,7 @@ impl StateMachineHeightProviderT for StateMachineHeightProvider {

parameter_types! {
pub const CoretimeChain: StateMachine = StateMachine::Kusama(CORETIME_CHAIN_PARA_ID); // coretime-kusama
pub const RegionsUnsignedPriority: TransactionPriority = TransactionPriority::max_value();
}

impl pallet_regions::Config for Runtime {
Expand All @@ -624,6 +622,7 @@ impl pallet_regions::Config for Runtime {
type IsmpDispatcher = Ismp;
type StateMachineHeightProvider = StateMachineHeightProvider;
type Timeout = ConstU64<300>; // 5 minutes
type UnsignedPriority = RegionsUnsignedPriority;
type WeightInfo = weights::pallet_regions::WeightInfo<Runtime>;
}

Expand Down

0 comments on commit b99b5c7

Please sign in to comment.