Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
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
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

86 changes: 86 additions & 0 deletions pallets/ah-migrator/src/call.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
// Copyright (C) Parity Technologies (UK) Ltd.
// This file is part of Polkadot.

// Polkadot 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.

// Polkadot 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 Polkadot. If not, see <http://www.gnu.org/licenses/>.

use crate::*;
use frame_support::traits::Bounded;

pub type BoundedCallOf<T> =
Bounded<<T as frame_system::Config>::RuntimeCall, <T as frame_system::Config>::Hashing>;

impl<T: Config> Pallet<T> {
pub fn map_rc_ah_call(
rc_bounded_call: &BoundedCallOf<T>,
) -> Result<BoundedCallOf<T>, Error<T>> {
let encoded_call = if let Ok(e) = Self::fetch_preimage(rc_bounded_call) {
e
} else {
return Err(Error::<T>::PreimageNotFound);
};

if let Some(hash) = rc_bounded_call.lookup_hash() {
if T::Preimage::is_requested(&hash) {
T::Preimage::unrequest(&hash);
}
}

let call = if let Ok(call) = T::RcToAhCall::try_convert(&encoded_call) {
call
} else {
return Err(Error::<T>::FailedToConvertCall);
};

log::info!("MAPPED CALL: {:?}", call);

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

ups, my debug log


let ah_bounded_call = T::Preimage::bound(call).map_err(|err| {
Comment thread
ggwpez marked this conversation as resolved.
defensive!("Failed to bound call: {:?}", err);
Error::<T>::FailedToBoundCall
})?;

if ah_bounded_call.lookup_needed() {
// Noted preimages for referendums that did not pass will need to be manually removed
// later.
log::info!("New preimage was noted for call");
}

Ok(ah_bounded_call)
}

fn fetch_preimage(bounded_call: &BoundedCallOf<T>) -> Result<Vec<u8>, Error<T>> {
match bounded_call {
Bounded::Inline(encoded) => Ok(encoded.clone().into_inner()),
Bounded::Legacy { hash, .. } => {
let encoded = if let Ok(encoded) = T::Preimage::fetch(hash, None) {
encoded
} else {
// not an error since a submitter can delete the preimage for ongoing referendum
log::warn!("No preimage found for call hash: {:?}", hash);
return Err(Error::<T>::PreimageNotFound);
};
Ok(encoded.into_owned())
},
Bounded::Lookup { hash, len } => {
let encoded = if let Ok(encoded) = T::Preimage::fetch(hash, Some(*len)) {
encoded
} else {
// not an error since a submitter can delete the preimage for ongoing referendum
log::warn!("No preimage found for call hash: {:?}", (hash, len));
return Err(Error::<T>::PreimageNotFound);
};
Ok(encoded.into_owned())
},
}
}
}
33 changes: 30 additions & 3 deletions pallets/ah-migrator/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,12 @@
#![cfg_attr(not(feature = "std"), no_std)]

pub mod account;
pub mod call;
pub mod multisig;
pub mod preimage;
pub mod proxy;
pub mod referenda;
pub mod scheduler;
pub mod staking;
pub mod types;

Expand All @@ -46,7 +48,7 @@ use frame_support::{
storage::{transactional::with_transaction_opaque_err, TransactionOutcome},
traits::{
fungible::{InspectFreeze, Mutate, MutateFreeze, MutateHold},
Defensive, LockableCurrency, OriginTrait, QueryPreimage, ReservableCurrency,
Defensive, LockableCurrency, OriginTrait, QueryPreimage, ReservableCurrency, StorePreimage,
WithdrawReasons as LockWithdrawReasons,
},
};
Expand Down Expand Up @@ -90,6 +92,7 @@ pub mod pallet {
+ pallet_preimage::Config<Hash = H256>
+ pallet_referenda::Config<Votes = u128>
+ pallet_nomination_pools::Config
+ pallet_scheduler::Config
{
/// The overarching event type.
type RuntimeEvent: From<Event<Self>> + IsType<<Self as frame_system::Config>::RuntimeEvent>;
Expand Down Expand Up @@ -126,10 +129,10 @@ pub mod pallet {
/// Convert a Relay Chain origin to an Asset Hub one.
type RcToAhPalletsOrigin: TryConvert<
Self::RcPalletsOrigin,
<Self::RuntimeOrigin as OriginTrait>::PalletsOrigin,
<<Self as frame_system::Config>::RuntimeOrigin as OriginTrait>::PalletsOrigin,
>;
/// Preimage registry.
type Preimage: QueryPreimage<H = <Self as frame_system::Config>::Hashing>;
type Preimage: QueryPreimage<H = <Self as frame_system::Config>::Hashing> + StorePreimage;
/// Convert a Relay Chain Call to a local AH one.
type RcToAhCall: for<'a> TryConvert<&'a [u8], <Self as frame_system::Config>::RuntimeCall>;
}
Expand All @@ -152,6 +155,10 @@ pub mod pallet {
FailedToConvertType,
/// Failed to fetch preimage.
PreimageNotFound,
/// Failed to convert RC call to AH call.
FailedToConvertCall,
/// Failed to bound a call.
FailedToBoundCall,
}

#[pallet::event]
Expand Down Expand Up @@ -267,6 +274,16 @@ pub mod pallet {
count_bad: u32,
},
ReferendaProcessed,
SchedulerMessagesReceived {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I added a generic variant with a PalletName that we can use as to not copy&paste this always for new pallets.

/// How many scheduler messages are in the batch.
count: u32,
},
SchedulerMessagesProcessed {
/// How many scheduler messages were successfully integrated.
count_good: u32,
/// How many scheduler messages failed to integrate.
count_bad: u32,
},
}

#[pallet::pallet]
Expand Down Expand Up @@ -395,6 +412,16 @@ pub mod pallet {

Self::do_receive_referendums(referendums).map_err(Into::into)
}

#[pallet::call_index(12)]
pub fn receive_scheduler_messages(
origin: OriginFor<T>,
messages: Vec<scheduler::RcSchedulerMessageOf<T>>,
) -> DispatchResult {
ensure_root(origin)?;

Self::do_receive_scheduler_messages(messages).map_err(Into::into)
}
}

#[pallet::hooks]
Expand Down
110 changes: 49 additions & 61 deletions pallets/ah-migrator/src/referenda.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,11 @@
// along with Polkadot. If not, see <http://www.gnu.org/licenses/>.

use crate::*;
use frame_support::traits::{schedule::v3::Anon, Bounded, BoundedInline, DefensiveTruncateFrom};
use call::BoundedCallOf;
use frame_support::traits::{schedule::v3::Anon, DefensiveTruncateFrom};
use pallet_referenda::{
BalanceOf, BoundedCallOf, DecidingCount, ReferendumCount, ReferendumInfo, ReferendumInfoFor,
ReferendumInfoOf, ReferendumStatus, ReferendumStatusOf, ScheduleAddressOf, TallyOf, TrackIdOf,
TrackQueue,
BalanceOf, DecidingCount, ReferendumCount, ReferendumInfo, ReferendumInfoFor, ReferendumStatus,
ScheduleAddressOf, TallyOf, TrackIdOf, TrackQueue,
};

/// ReferendumInfoOf for RC.
Expand All @@ -33,7 +33,7 @@ pub type RcReferendumInfoOf<T, I> = ReferendumInfo<
TrackIdOf<T, I>,
<T as Config>::RcPalletsOrigin,
BlockNumberFor<T>,
BoundedCallOf<T, I>,
BoundedCallOf<T>,
BalanceOf<T, I>,
TallyOf<T, I>,
<T as frame_system::Config>::AccountId,
Expand All @@ -47,7 +47,31 @@ pub type RcReferendumStatusOf<T, I> = ReferendumStatus<
TrackIdOf<T, I>,
<T as Config>::RcPalletsOrigin,
BlockNumberFor<T>,
BoundedCallOf<T, I>,
BoundedCallOf<T>,
BalanceOf<T, I>,
TallyOf<T, I>,
<T as frame_system::Config>::AccountId,
ScheduleAddressOf<T, I>,
>;

/// Asset Hub ReferendumInfoOf.
pub type ReferendumInfoOf<T, I> = ReferendumInfo<
TrackIdOf<T, I>,
<<T as frame_system::Config>::RuntimeOrigin as OriginTrait>::PalletsOrigin,
BlockNumberFor<T>,
BoundedCallOf<T>,
BalanceOf<T, I>,
TallyOf<T, I>,
<T as frame_system::Config>::AccountId,
ScheduleAddressOf<T, I>,
>;

/// ReferendumStatusOf for Asset Hub.
pub type ReferendumStatusOf<T, I> = ReferendumStatus<
TrackIdOf<T, I>,
<<T as frame_system::Config>::RuntimeOrigin as OriginTrait>::PalletsOrigin,
BlockNumberFor<T>,
BoundedCallOf<T>,
BalanceOf<T, I>,
TallyOf<T, I>,
<T as frame_system::Config>::AccountId,
Expand Down Expand Up @@ -113,42 +137,18 @@ impl<T: Config> Pallet<T> {
},
};

let encoded_call = if let Ok(e) = Self::fetch_preimage(&status.proposal) {
e
} else {
log::warn!("Failed to fetch preimage for referendum {}", id);
cancel_referendum(id, status);
return Ok(());
};

let call = if let Ok(call) = T::RcToAhCall::try_convert(&encoded_call) {
call
let proposal = if let Ok(proposal) = Self::map_rc_ah_call(&status.proposal) {
proposal
} else {
// TODO: replace with defensive if we expect all referendum calls to be mapped.
log::warn!("Failed to convert RC call to AH call for referendum {}", id);
cancel_referendum(id, status);
return Ok(());
};

let inline = if let Ok(i) = BoundedInline::try_from(call.encode()) {
i
} else {
let data = call.encode();
log::error!("Failed to bound call for referendum {}, orig_len={}, new_len={}, pallet={:?}, call={:?}, hex={}",
id, encoded_call.len(), data.len(), data.clone()[0], data.clone()[1], hex::encode(data));
//defensive!("Call encoded length is too large for inline encoding");
// TODO: if we have such a case we would need to dispatch two call on behalf of
// the original preimage submitter to release the funds for the new preimage
// deposit and dispatch the call to note a new preimage. or we provide a
// better sdk for this case.
log::error!("Failed to convert RC call to AH call for referendum {}", id);
cancel_referendum(id, status);
return Ok(());
};

let status = ReferendumStatusOf::<T, ()> {
track: status.track,
origin,
proposal: Bounded::Inline(inline),
proposal,
enactment: status.enactment,
submitted: status.submitted,
submission_deposit: status.submission_deposit,
Expand All @@ -168,7 +168,7 @@ impl<T: Config> Pallet<T> {
ReferendumInfo::Killed(a) => ReferendumInfo::Killed(a),
};

ReferendumInfoFor::<T, ()>::insert(id, referendum);
alias::ReferendumInfoFor::<T>::insert(id, referendum);

log::debug!(target: LOG_TARGET, "Referendum {} integrated", id);

Expand All @@ -195,33 +195,21 @@ impl<T: Config> Pallet<T> {
log::info!(target: LOG_TARGET, "Referenda pallet integrated");
Ok(())
}

fn fetch_preimage(bounded_call: &BoundedCallOf<T, ()>) -> Result<Vec<u8>, Error<T>> {
match bounded_call {
Bounded::Inline(encoded) => Ok(encoded.clone().into_inner()),
Bounded::Legacy { hash, .. } => {
let encoded = if let Ok(encoded) = T::Preimage::fetch(hash, None) {
encoded
} else {
// not an error since a submitter can delete the preimage for ongoing referendum
log::warn!("No preimage found for call hash: {:?}", hash);
return Err(Error::<T>::PreimageNotFound);
};
Ok(encoded.into_owned())
},
Bounded::Lookup { hash, len } => {
let encoded = if let Ok(encoded) = T::Preimage::fetch(hash, Some(*len)) {
encoded
} else {
// not an error since a submitter can delete the preimage for ongoing referendum
log::warn!("No preimage found for call hash: {:?}", (hash, len));
return Err(Error::<T>::PreimageNotFound);
};
Ok(encoded.into_owned())
},
}
}
}

pub mod alias {
use super::*;
use pallet_referenda::ReferendumIndex;

/// Information concerning any given referendum.
/// FROM: https://github.com/paritytech/polkadot-sdk/blob/f373af0d1c1e296c1b07486dd74710b40089250e/substrate/frame/referenda/src/lib.rs#L249
#[frame_support::storage_alias(pallet_name)]
pub type ReferendumInfoFor<T: pallet_referenda::Config<()>> = StorageMap<
pallet_referenda::Pallet<T, ()>,
Blake2_128Concat,
ReferendumIndex,
ReferendumInfoOf<T, ()>,
>;
}
// TODO: shift referendums' time block by the time of the migration
// TODO: schedule `one_fewer_deciding` for referendums canceled during migration
Loading