@@ -94,3 +94,118 @@ impl<AbsoluteLocation: Get<MultiLocation>> Reserve
94
94
} )
95
95
}
96
96
}
97
+
98
+ // https://github.com/AstarNetwork/Astar/blob/2a8df8d098f6abc3fdf5aaf6514e94f615f9bdab/primitives/src/xcm/mod.rs#L276-L418
99
+ // TODO: remove this after uplift to `polkadot-v0.9.44` or beyond, and replace it with code in XCM builder.
100
+
101
+ use codec:: { Compact , Encode } ;
102
+ use sp_io:: hashing:: blake2_256;
103
+ use sp_std:: prelude:: * ;
104
+ use xcm_executor:: traits:: Convert as XcmConvert ;
105
+
106
+ /// Means of converting a location into a stable and unique descriptive identifier.
107
+ pub trait DescribeLocation {
108
+ /// Create a description of the given `location` if possible. No two locations should have the
109
+ /// same descriptor.
110
+ fn describe_location ( location : & MultiLocation ) -> Option < Vec < u8 > > ;
111
+ }
112
+
113
+ #[ impl_trait_for_tuples:: impl_for_tuples( 30 ) ]
114
+ impl DescribeLocation for Tuple {
115
+ fn describe_location ( l : & MultiLocation ) -> Option < Vec < u8 > > {
116
+ for_tuples ! ( #(
117
+ match Tuple :: describe_location( l) {
118
+ Some ( result) => return Some ( result) ,
119
+ None => { } ,
120
+ }
121
+ ) * ) ;
122
+ None
123
+ }
124
+ }
125
+
126
+ pub struct DescribeTerminus ;
127
+ impl DescribeLocation for DescribeTerminus {
128
+ fn describe_location ( l : & MultiLocation ) -> Option < Vec < u8 > > {
129
+ match ( l. parents , & l. interior ) {
130
+ ( 0 , Here ) => Some ( Vec :: new ( ) ) ,
131
+ _ => return None ,
132
+ }
133
+ }
134
+ }
135
+
136
+ pub struct DescribePalletTerminal ;
137
+ impl DescribeLocation for DescribePalletTerminal {
138
+ fn describe_location ( l : & MultiLocation ) -> Option < Vec < u8 > > {
139
+ match ( l. parents , & l. interior ) {
140
+ ( 0 , X1 ( PalletInstance ( i) ) ) =>
141
+ Some ( ( b"Pallet" , Compact :: < u32 > :: from ( * i as u32 ) ) . encode ( ) ) ,
142
+ _ => return None ,
143
+ }
144
+ }
145
+ }
146
+
147
+ pub struct DescribeAccountId32Terminal ;
148
+ impl DescribeLocation for DescribeAccountId32Terminal {
149
+ fn describe_location ( l : & MultiLocation ) -> Option < Vec < u8 > > {
150
+ match ( l. parents , & l. interior ) {
151
+ ( 0 , X1 ( AccountId32 { id, .. } ) ) => Some ( ( b"AccountId32" , id) . encode ( ) ) ,
152
+ _ => return None ,
153
+ }
154
+ }
155
+ }
156
+
157
+ pub struct DescribeAccountKey20Terminal ;
158
+ impl DescribeLocation for DescribeAccountKey20Terminal {
159
+ fn describe_location ( l : & MultiLocation ) -> Option < Vec < u8 > > {
160
+ match ( l. parents , & l. interior ) {
161
+ ( 0 , X1 ( AccountKey20 { key, .. } ) ) => Some ( ( b"AccountKey20" , key) . encode ( ) ) ,
162
+ _ => return None ,
163
+ }
164
+ }
165
+ }
166
+
167
+ pub type DescribeAccountIdTerminal = ( DescribeAccountId32Terminal , DescribeAccountKey20Terminal ) ;
168
+
169
+ pub type DescribeAllTerminal = (
170
+ DescribeTerminus ,
171
+ DescribePalletTerminal ,
172
+ DescribeAccountId32Terminal ,
173
+ DescribeAccountKey20Terminal ,
174
+ ) ;
175
+
176
+ pub struct DescribeFamily < DescribeInterior > ( PhantomData < DescribeInterior > ) ;
177
+ impl < Suffix : DescribeLocation > DescribeLocation for DescribeFamily < Suffix > {
178
+ fn describe_location ( l : & MultiLocation ) -> Option < Vec < u8 > > {
179
+ match ( l. parents , l. interior . first ( ) ) {
180
+ ( 0 , Some ( Parachain ( index) ) ) => {
181
+ let tail = l. interior . split_first ( ) . 0 ;
182
+ let interior = Suffix :: describe_location ( & tail. into ( ) ) ?;
183
+ Some ( ( b"ChildChain" , Compact :: < u32 > :: from ( * index) , interior) . encode ( ) )
184
+ } ,
185
+ ( 1 , Some ( Parachain ( index) ) ) => {
186
+ let tail = l. interior . split_first ( ) . 0 ;
187
+ let interior = Suffix :: describe_location ( & tail. into ( ) ) ?;
188
+ Some ( ( b"SiblingChain" , Compact :: < u32 > :: from ( * index) , interior) . encode ( ) )
189
+ } ,
190
+ ( 1 , _) => {
191
+ let tail = l. interior . into ( ) ;
192
+ let interior = Suffix :: describe_location ( & tail) ?;
193
+ Some ( ( b"ParentChain" , interior) . encode ( ) )
194
+ } ,
195
+ _ => return None ,
196
+ }
197
+ }
198
+ }
199
+
200
+ pub struct HashedDescription < AccountId , Describe > ( PhantomData < ( AccountId , Describe ) > ) ;
201
+ impl < AccountId : From < [ u8 ; 32 ] > + Clone , Describe : DescribeLocation >
202
+ XcmConvert < MultiLocation , AccountId > for HashedDescription < AccountId , Describe >
203
+ {
204
+ fn convert ( value : MultiLocation ) -> Result < AccountId , MultiLocation > {
205
+ if let Some ( description) = Describe :: describe_location ( & value) {
206
+ Ok ( blake2_256 ( & description) . into ( ) )
207
+ } else {
208
+ Err ( value)
209
+ }
210
+ }
211
+ }
0 commit comments