@@ -4,7 +4,7 @@ pub use pallet::*;
4
4
use pallet_mmr:: { LeafDataProvider , ParentNumberAndHash , verify_leaves_proof} ;
5
5
use sp_consensus_beefy:: mmr:: MmrLeafVersion ;
6
6
7
- use frame_support:: { dispatch:: { DispatchResult } , pallet_prelude:: * , } ;
7
+ use frame_support:: { dispatch:: { DispatchResult } , pallet_prelude:: * , WeakBoundedVec } ;
8
8
use frame_system:: pallet_prelude:: * ;
9
9
use cumulus_primitives_core:: { ParaId , GetBeefyRoot } ;
10
10
use sp_runtime:: traits:: { Hash as HashT , Keccak256 } ;
@@ -34,6 +34,18 @@ type XcmpMessages<T, I> = <<T as crate::Config<I>>::XcmpDataProvider as XcmpMess
34
34
type MmrProof = Proof < H256 > ;
35
35
type LeafOf < T , I > = <crate :: Pallet < T , I > as LeafDataProvider >:: LeafData ;
36
36
type ChannelId = u64 ;
37
+ type BinaryMerkleProof = ( ) ;
38
+
39
+
40
+ #[ derive( Debug , PartialEq , Eq , Clone , Encode , Decode , TypeInfo ) ]
41
+ pub struct XcmpProof {
42
+ // TODO: Probably should rename each of these stages to some fancy name
43
+ // TODO: Remove tuples
44
+ pub stage_1 : ( MmrProof , Vec < EncodableOpaqueLeaf > ) ,
45
+ pub stage_2 : BinaryMerkleProof ,
46
+ pub stage_3 : BinaryMerkleProof ,
47
+ pub stage_4 : ( MmrProof , Vec < EncodableOpaqueLeaf > ) ,
48
+ }
37
49
38
50
#[ frame_support:: pallet]
39
51
pub mod pallet {
@@ -48,6 +60,7 @@ pub mod pallet {
48
60
type RelayerOrigin : EnsureOrigin < Self :: RuntimeOrigin > ;
49
61
/// This is used when updating the current `XcmpChannelRoots`
50
62
type BeefyRootProvider : GetBeefyRoot ;
63
+ type MaxBeefyRootsKept : Get < u32 > ;
51
64
}
52
65
53
66
#[ pallet:: pallet]
@@ -58,6 +71,14 @@ pub mod pallet {
58
71
#[ pallet:: getter( fn xcmp_channel_roots) ]
59
72
pub type XcmpChannelRoots < T : Config < I > , I : ' static = ( ) > = StorageMap < _ , Identity , ChannelId , H256 , OptionQuery > ;
60
73
74
+ #[ pallet:: storage]
75
+ #[ pallet:: getter( fn seen_beefy_roots) ]
76
+ pub type SeenBeefyRoots < T : Config < I > , I : ' static = ( ) > = StorageMap < _ , Identity , H256 , BlockNumberFor < T > , OptionQuery > ;
77
+
78
+ #[ pallet:: storage]
79
+ #[ pallet:: getter( fn seen_beefy_roots_order) ]
80
+ pub type SeenBeefyRootsOrder < T : Config < I > , I : ' static = ( ) > = StorageValue < _ , WeakBoundedVec < H256 , T :: MaxBeefyRootsKept > , ValueQuery > ;
81
+
61
82
#[ pallet:: event]
62
83
#[ pallet:: generate_deposit( pub ( super ) fn deposit_event) ]
63
84
pub enum Event < T : Config < I > , I : ' static = ( ) > {
@@ -77,13 +98,30 @@ pub mod pallet {
77
98
XcmpProofAccepted ,
78
99
XcmpProofLeavesNotValid ,
79
100
XcmpNoChannelRootForChannelId ,
101
+ XcmpBeefyRootTargetedNeverSeen ,
102
+ }
103
+
104
+ #[ pallet:: hooks]
105
+ impl < T : Config < I > , I : ' static > Hooks < BlockNumberFor < T > > for Pallet < T , I > {
106
+ fn on_initialize ( n : BlockNumberFor < T > ) -> Weight {
107
+ // TODO: Remove Temporary.. change from unwrapping default..
108
+ let beefy_root = T :: BeefyRootProvider :: get_root ( ) . unwrap_or_default ( ) ;
109
+ SeenBeefyRoots :: < T , I > :: insert ( & beefy_root. clone ( ) . into ( ) , n) ;
110
+
111
+ let mut order = SeenBeefyRootsOrder :: < T , I > :: get ( ) . into_inner ( ) ;
112
+ order. push ( beefy_root. into ( ) ) ;
113
+
114
+ let item = WeakBoundedVec :: force_from ( order, None ) ;
115
+ SeenBeefyRootsOrder :: < T , I > :: put ( item) ;
116
+
117
+ T :: DbWeight :: get ( ) . writes ( 3 )
118
+ }
80
119
}
81
120
82
121
#[ pallet:: call]
83
122
impl < T : Config < I > , I : ' static > Pallet < T , I > {
84
123
85
- // TODO: Retrieve latest valid MmrChannelRoots from Relaychain (Perhaps this is done in on_initialize)
86
-
124
+ // TODO: This will
87
125
#[ pallet:: call_index( 0 ) ]
88
126
#[ pallet:: weight( Weight :: from_parts( 10_000 , 0 ) + T :: DbWeight :: get( ) . writes( 1 ) ) ]
89
127
pub fn submit_xcmp_proof ( origin : OriginFor < T > , mmr_proof : MmrProof , leaves : Vec < EncodableOpaqueLeaf > , channel_id : u64 ) -> DispatchResult {
@@ -140,6 +178,101 @@ pub mod pallet {
140
178
) ;
141
179
Ok ( ( ) )
142
180
}
181
+
182
+ /// For now there is just one leaf in each membership proof
183
+ /// TODO: Change to support multiple leaves..
184
+ #[ pallet:: call_index( 2 ) ]
185
+ #[ pallet:: weight( Weight :: from_parts( 10_000 , 0 ) + T :: DbWeight :: get( ) . writes( 1 ) ) ]
186
+ pub fn submit_big_proof ( origin : OriginFor < T > , xcmp_proof : XcmpProof , beefy_root_targeted : H256 ) -> DispatchResult {
187
+ ensure_signed ( origin) ?;
188
+
189
+ log:: info!(
190
+ target: LOG_TARGET ,
191
+ "Called submit big proof, targeting BEEFY_ROOT {:?}" ,
192
+ beefy_root_targeted
193
+ ) ;
194
+
195
+ if !SeenBeefyRoots :: < T , I > :: contains_key ( & beefy_root_targeted) {
196
+ return Err ( Error :: < T , I > :: XcmpBeefyRootTargetedNeverSeen . into ( ) )
197
+ }
198
+
199
+ // Verify stage 1 via grabbing Beefy Root and checking against stage 1
200
+ let ( stage_1_proof, stage_1_leaves) = xcmp_proof. stage_1 ;
201
+
202
+ let nodes: Vec < _ > = stage_1_leaves
203
+ . clone ( )
204
+ . into_iter ( )
205
+ . map ( |leaf|DataOrHash :: < Keccak256 , _ > :: Data ( leaf. into_opaque_leaf ( ) ) )
206
+ . collect ( ) ;
207
+
208
+ // TODO: Replace this error with an Error that specifies stage_1 of proof verification failed
209
+ verify_leaves_proof ( beefy_root_targeted. into ( ) , nodes, stage_1_proof) . map_err ( |_| Error :: < T , I > :: XcmpProofNotValid ) ?;
210
+
211
+ log:: info!(
212
+ target: LOG_TARGET ,
213
+ "Verified Stage 1 Big XCMP Proof Successfully!!!" ,
214
+ ) ;
215
+
216
+ // Verify stage 2..
217
+ // grab ParaHeader root from stage_1_proof
218
+ // let para_header_root = Decode::decode(stage_1_leaves)
219
+ // let (stage_2_proof, stage_2_leaves) = xcmp_proof.stage_2;
220
+
221
+ // These are different leaves they arent the MmrLeaves they are Binary Merkle Leaves
222
+ // This will be a bit different but same rough idea as the Mmr
223
+ // let nodes: Vec<_> = stage_2_leaves
224
+ // .clone()
225
+ // .into_iter()
226
+ // .map(|leaf|DataOrHash::<Keccak256, _>::Data(leaf.into_opaque_leaf()))
227
+ // .collect();
228
+
229
+ // binary merkle proof verification of para_header_root against stage_2_proof(leaves are (para_id, para_header))
230
+ // verify_proof(root, nodes, stage_2_proof);
231
+
232
+ // let (para_id, para_header) = Decode::decode(stage_2_leaves);
233
+ // Check channels storage to make sure this ParaId is someone that we support
234
+ // if !XcmpChannels::<T>::exists(para_id) {
235
+ // return Error::<T>::XcmpProofNoChannelWithSender
236
+ // }
237
+
238
+ // Verify stage 3..
239
+ // extract xcmp_root from paraheader..
240
+ // let xcmp_root = extract(para_header)
241
+ // let (stage_3_proof, stage_3_leaves) = xcmp_proof.stage_3;
242
+
243
+ // These are different leaves they arent the MmrLeaves they are Binary Merkle Leaves
244
+ // This will be a bit different but same rough idea as the Mmr
245
+ // let nodes: Vec<_> = stage_3_leaves
246
+ // .clone()
247
+ // .into_iter()
248
+ // .map(|leaf|DataOrHash::<Keccak256, _>::Data(leaf.into_opaque_leaf()))
249
+ // .collect();
250
+
251
+ // binary merkle proof verification of xcmp_root against stage_3_proof(mmr_root_from_sender)
252
+ // verify_proof(xcmp_root, nodes, stage_3_proof)?;
253
+
254
+ // Verify stage 4..
255
+ // let mmr_root = Decode::decode(stage_3_leaves);
256
+ // let (stage_4_proof, stage_4_leaves) = xcmp_proof.stage_4;
257
+
258
+ // let nodes: Vec<_> = stage_4_leaves
259
+ // .clone()
260
+ // .into_iter()
261
+ // .map(|leaf|DataOrHash::<Keccak256, _>::Data(leaf.into_opaque_leaf()))
262
+ // .collect();
263
+
264
+ // TODO: Replace this error with an Error that specifies stage_4 of proof verification failed
265
+ // verify_leaves_proof(mmr_root.into(), nodes, stage_4_proof).map_err(|_| Error::<T, I>::XcmpProofNotValid)?;
266
+
267
+ // Now process messages upstream
268
+ // let xcmp_messages = Decode::decode(stage_4_leaves);
269
+ // Send Xcmp Messages upstream to be decoded to XCM messages and processed
270
+ // T::ProcessXcmpMessages(xcmp_messages);
271
+
272
+ // Log Event..
273
+
274
+ Ok ( ( ) )
275
+ }
143
276
}
144
277
145
278
}
0 commit comments