-
Notifications
You must be signed in to change notification settings - Fork 697
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
pallet-xcm: add support to authorize aliases #6336
base: master
Are you sure you want to change the base?
Conversation
ec00d1f
to
d0111c3
Compare
35170ae
to
0332aca
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lgtm, left some small nits/questions
bot bench polkadot-pallet --subcommand=xcm --runtime=westend --pallet=pallet_xcm bot bench cumulus-assets --subcommand=xcm --runtime=asset-hub-westend --pallet=pallet_xcm |
…stend --target_dir=polkadot --pallet=pallet_xcm
…coco --target_dir=polkadot --pallet=pallet_xcm
…set-hub-westend --runtime_dir=assets --target_dir=cumulus --pallet=pallet_xcm
…set-hub-rococo --runtime_dir=assets --target_dir=cumulus --pallet=pallet_xcm
bot clean |
/// their/your name. Once authorized using this call, the `aliaser` can freely impersonate | ||
/// `origin` in XCM programs executed on the local chain. | ||
#[pallet::call_index(14)] | ||
pub fn add_authorized_alias( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we allow this indefinitely or always require an expiry? Thinking of the case where you do trust your account on another chain but maybe that chain gets compromised and you forgot to remove your authorization. Then the parachain can impersonate your account on their chain and in turn impersonate your account on this chain.
An expiry would be annoying but would make it safer. Apps could batch this with the actual action you want to take if they know the expiry is past.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I’m personally not a fan of expiry. It’s a big UX burden and doesn’t bring any value IMO. If the aliaser is compromised then the aliasee is compromised, one cannot rely on an expiry as protection. One should immediately remove the authorisation in such an unlikely case.
The idea is worth evaluating from a UX perspective depending on the following:
A) will users authorise these relationships for repeated actions (effectively needing them alive for longer periods), or
B) will they be used for very occasional one-time actions (so for added security they should either be explicitly removed or automatically expire)
If the usage pattern is B, then an expiry actually helps UX. If it is A, it hinders UX (and adds more complexity - would need to maintain an ordered list based on expirations and manage it on each block - complex and expensive).
I say we keep it simple for now and see where it goes, we can pivot to the more expensive option if needed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see expiry as a way to not allow users to forget that they allowed some location to impersonate them. I think it's a UX improvement to allow users to forget but still clean up after themselves.
The reason why I'm proposing this is because it's not only the location they explicitly allow that could be the problem, they open the surface area of bugs to bugs on the other chain. The main value in my opinion is that if a user on chain A allows an account from chain B to impersonate them and then forgets, a future vulnerability in chain B can't affect them anymore given that it expires.
I'd expect the usage pattern to be B, but if it is A we can still make the expiry refresh every time they make an action with it.
On the implementation side I don't see how it's so complex and expensive. You'd just keep the block number timeout and disallow aliases that are past that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
added expiry here a606607, let me know what you think
polkadot/xcm/pallet-xcm/src/lib.rs
Outdated
/// Entry of an authorized aliaser for a local origin. The aliaser `location` is only authorized | ||
/// until its inner `expiry` block number. | ||
#[derive(Clone, Encode, Decode, Debug, Eq, PartialEq, Ord, PartialOrd, TypeInfo)] | ||
pub(crate) struct OriginAliaser { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I do not really see the reason to make stored types and storage items private. At the end when you need to use it for some reason you just have to copy past them and create an alias storage item.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
not sure what you mean..
should define this other place? or just make it pub
instead of pub(crate)
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, I would make them public
polkadot/xcm/pallet-xcm/src/lib.rs
Outdated
#[derive(Clone, Encode, Decode, Debug, Eq, PartialEq, Ord, PartialOrd, TypeInfo)] | ||
pub(crate) struct OriginAliaser { | ||
pub(crate) location: VersionedLocation, | ||
pub(crate) expiry: Option<u64>, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why not to reference the actual block number type?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
had some trouble storing BlockNumberFor<T>
, then realized the interface is better to be generic - once we move to relay-block-number-provider that type might change again, but u64 will always be compatible
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
two times bigger than what we really use. when we change to configurable provider, the block number type wont change
polkadot/xcm/pallet-xcm/src/lib.rs
Outdated
authorized_aliases | ||
.try_push(aliaser) | ||
.map_err(|_| Error::<T>::TooManyAuthorizedAliases)?; | ||
// todo: hold storage deposit |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
do you plan to address this todo in the current PR?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
just pushed something, want feedback before I clean it up all the way
// todo: hold storage deposit | ||
} | ||
AuthorizedAliases::<T>::insert(&versioned_origin, authorized_aliases); | ||
Ok(()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
some event?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes, still needs events
let block_num = frame_system::Pallet::<T>::block_number().saturated_into::<u64>(); | ||
let mut writes = 0; | ||
// need to iterate keys and modify map in separate steps to avoid undefined behavior | ||
let keys: Vec<VersionedLocation> = AuthorizedAliases::<T>::iter_keys().collect(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this might be too many reads, we should check the weight_cutoff
on every iteration
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
do we need to in practice? iterating over even a million keys should fit in practice, no?
I'm not even sure how we could do partial iterations, how to resume from where we left off...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
in the context of this function (may be I missing a broader picture), it looks wrong. a client passes weight_cutoff
, for this stage we ignore it. we do not know how small or big the weight_cutoff
.
I think we can iterate one by one and if there was no enough weight to complete, we can return RemoveExpiredAliasAuthorizations(Some(cursor))
.
polkadot/xcm/pallet-xcm/src/lib.rs
Outdated
AuthorizedAliases::<T>::get(&target) | ||
.iter() | ||
.find(|&aliaser| { | ||
let current_block = | ||
frame_system::Pallet::<T>::block_number().saturated_into::<u64>(); | ||
let not_expired = | ||
aliaser.expiry.map(|expiry| expiry < current_block).unwrap_or(true); | ||
aliaser.location == origin && not_expired | ||
}) | ||
.is_some() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it will be useful as the Pallet
's function
@@ -170,6 +170,47 @@ pub mod data { | |||
} | |||
} | |||
|
|||
/// Implementation of `NeedsMigration` for `AuthorizedAliases` data. | |||
impl<M: Get<u32>, T: frame_system::Config> NeedsMigration |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nice
Add calls to pallet-xcm for adding and removing authorization for a certain
aliaser
location to alias into the callerorigin
.pallet-xcm
also exposes anAuthorizedAliases
filter implementation usable withxcm_executor::Config::Aliasers
filter to easily allow runtimes to plug in the explicitly authorized aliases using the calls above.Usually useful to allow your local account to be aliased into from a remote location also under your control (like your account on another chain).
One cool example is
Alice
onPara42
doing something on Asset Hub without having to transfer fees fromPara42
, but instead use her local Asset Hub account:Part of Empowered cross-chain origins.
Fixes XCM: Arbitrary Origin Aliases #722