Skip to content

Commit bbfb889

Browse files
authored
Refund messages confirmation tx (paritytech#1904)
* Refund messages confirmation tx * Fixes
1 parent b1a0fa7 commit bbfb889

File tree

8 files changed

+407
-210
lines changed

8 files changed

+407
-210
lines changed

bridges/bin/millau/runtime/src/lib.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -453,7 +453,6 @@ impl pallet_bridge_messages::Config<WithRialtoMessagesInstance> for Runtime {
453453
Runtime,
454454
WithRialtoMessagesInstance,
455455
frame_support::traits::ConstU64<100_000>,
456-
frame_support::traits::ConstU64<10_000>,
457456
>;
458457

459458
type SourceHeaderChain = crate::rialto_messages::RialtoAsSourceHeaderChain;
@@ -485,7 +484,6 @@ impl pallet_bridge_messages::Config<WithRialtoParachainMessagesInstance> for Run
485484
Runtime,
486485
WithRialtoParachainMessagesInstance,
487486
frame_support::traits::ConstU64<100_000>,
488-
frame_support::traits::ConstU64<10_000>,
489487
>;
490488

491489
type SourceHeaderChain = crate::rialto_parachain_messages::RialtoParachainAsSourceHeaderChain;

bridges/bin/rialto-parachain/runtime/src/lib.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -571,7 +571,6 @@ impl pallet_bridge_messages::Config<WithMillauMessagesInstance> for Runtime {
571571
Runtime,
572572
WithMillauMessagesInstance,
573573
frame_support::traits::ConstU128<100_000>,
574-
frame_support::traits::ConstU128<100_000>,
575574
>;
576575

577576
type SourceHeaderChain = crate::millau_messages::MillauAsSourceHeaderChain;

bridges/bin/rialto/runtime/src/lib.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -445,7 +445,6 @@ impl pallet_bridge_messages::Config<WithMillauMessagesInstance> for Runtime {
445445
Runtime,
446446
WithMillauMessagesInstance,
447447
frame_support::traits::ConstU128<100_000>,
448-
frame_support::traits::ConstU128<100_000>,
449448
>;
450449

451450
type SourceHeaderChain = crate::millau_messages::MillauAsSourceHeaderChain;

bridges/bin/runtime-common/src/lib.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -77,8 +77,7 @@ where
7777
/// even honest relayers may lose their funds if there are multiple relays running and
7878
/// submitting the same messages/confirmations.
7979
fn validate(call: &T::RuntimeCall) -> TransactionValidity {
80-
call.check_obsolete_receive_messages_proof()?;
81-
call.check_obsolete_receive_messages_delivery_proof()
80+
call.check_obsolete_call()
8281
}
8382
}
8483

bridges/bin/runtime-common/src/messages_call_ext.rs

Lines changed: 137 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -22,25 +22,57 @@ use frame_support::{dispatch::CallableCallFor, traits::IsSubType, RuntimeDebug};
2222
use pallet_bridge_messages::{Config, Pallet};
2323
use sp_runtime::transaction_validity::TransactionValidity;
2424

25-
/// Info about a `ReceiveMessagesProof` call which tries to update a single lane.
25+
/// Generic info about a messages delivery/confirmation proof.
2626
#[derive(PartialEq, RuntimeDebug)]
27-
pub struct ReceiveMessagesProofInfo {
27+
pub struct BaseMessagesProofInfo {
2828
pub lane_id: LaneId,
29-
pub best_proof_nonce: MessageNonce,
29+
pub best_bundled_nonce: MessageNonce,
3030
pub best_stored_nonce: MessageNonce,
3131
}
3232

33-
/// Helper struct that provides methods for working with the `ReceiveMessagesProof` call.
34-
pub struct ReceiveMessagesProofHelper<T: Config<I>, I: 'static> {
33+
impl BaseMessagesProofInfo {
34+
fn is_obsolete(&self) -> bool {
35+
self.best_bundled_nonce <= self.best_stored_nonce
36+
}
37+
}
38+
39+
/// Info about a `ReceiveMessagesProof` call which tries to update a single lane.
40+
#[derive(PartialEq, RuntimeDebug)]
41+
pub struct ReceiveMessagesProofInfo(pub BaseMessagesProofInfo);
42+
43+
/// Info about a `ReceiveMessagesDeliveryProof` call which tries to update a single lane.
44+
#[derive(PartialEq, RuntimeDebug)]
45+
pub struct ReceiveMessagesDeliveryProofInfo(pub BaseMessagesProofInfo);
46+
47+
/// Info about a `ReceiveMessagesProof` or a `ReceiveMessagesDeliveryProof` call
48+
/// which tries to update a single lane.
49+
#[derive(PartialEq, RuntimeDebug)]
50+
pub enum CallInfo {
51+
ReceiveMessagesProof(ReceiveMessagesProofInfo),
52+
ReceiveMessagesDeliveryProof(ReceiveMessagesDeliveryProofInfo),
53+
}
54+
55+
/// Helper struct that provides methods for working with a call supported by `CallInfo`.
56+
pub struct CallHelper<T: Config<I>, I: 'static> {
3557
pub _phantom_data: sp_std::marker::PhantomData<(T, I)>,
3658
}
3759

38-
impl<T: Config<I>, I: 'static> ReceiveMessagesProofHelper<T, I> {
39-
/// Check if the `ReceiveMessagesProof` call delivered at least some of the messages that
40-
/// it contained.
41-
pub fn was_partially_successful(info: &ReceiveMessagesProofInfo) -> bool {
42-
let inbound_lane_data = pallet_bridge_messages::InboundLanes::<T, I>::get(info.lane_id);
43-
inbound_lane_data.last_delivered_nonce() > info.best_stored_nonce
60+
impl<T: Config<I>, I: 'static> CallHelper<T, I> {
61+
/// Check if a call delivered proof/confirmation for at least some of the messages that it
62+
/// contained.
63+
pub fn was_partially_successful(info: &CallInfo) -> bool {
64+
match info {
65+
CallInfo::ReceiveMessagesProof(info) => {
66+
let inbound_lane_data =
67+
pallet_bridge_messages::InboundLanes::<T, I>::get(info.0.lane_id);
68+
inbound_lane_data.last_delivered_nonce() > info.0.best_stored_nonce
69+
},
70+
CallInfo::ReceiveMessagesDeliveryProof(info) => {
71+
let outbound_lane_data =
72+
pallet_bridge_messages::OutboundLanes::<T, I>::get(info.0.lane_id);
73+
outbound_lane_data.latest_received_nonce > info.0.best_stored_nonce
74+
},
75+
}
4476
}
4577
}
4678

@@ -51,17 +83,21 @@ pub trait MessagesCallSubType<T: Config<I, RuntimeCall = Self>, I: 'static>:
5183
/// Create a new instance of `ReceiveMessagesProofInfo` from a `ReceiveMessagesProof` call.
5284
fn receive_messages_proof_info(&self) -> Option<ReceiveMessagesProofInfo>;
5385

54-
/// Create a new instance of `ReceiveMessagesProofInfo` from a `ReceiveMessagesProof` call,
55-
/// if the call is for the provided lane.
56-
fn receive_messages_proof_info_for(&self, lane_id: LaneId) -> Option<ReceiveMessagesProofInfo>;
86+
/// Create a new instance of `ReceiveMessagesDeliveryProofInfo` from
87+
/// a `ReceiveMessagesDeliveryProof` call.
88+
fn receive_messages_delivery_proof_info(&self) -> Option<ReceiveMessagesDeliveryProofInfo>;
89+
90+
/// Create a new instance of `CallInfo` from a `ReceiveMessagesProof`
91+
/// or a `ReceiveMessagesDeliveryProof` call.
92+
fn call_info(&self) -> Option<CallInfo>;
5793

58-
/// Check that a `ReceiveMessagesProof` call is trying to deliver at least some messages that
59-
/// are better than the ones we know of.
60-
fn check_obsolete_receive_messages_proof(&self) -> TransactionValidity;
94+
/// Create a new instance of `CallInfo` from a `ReceiveMessagesProof`
95+
/// or a `ReceiveMessagesDeliveryProof` call, if the call is for the provided lane.
96+
fn call_info_for(&self, lane_id: LaneId) -> Option<CallInfo>;
6197

62-
/// Check that a `ReceiveMessagesDeliveryProof` call is trying to deliver at least some message
63-
/// confirmations that are better than the ones we know of.
64-
fn check_obsolete_receive_messages_delivery_proof(&self) -> TransactionValidity;
98+
/// Check that a `ReceiveMessagesProof` or a `ReceiveMessagesDeliveryProof` call is trying
99+
/// to deliver/confirm at least some messages that are better than the ones we know of.
100+
fn check_obsolete_call(&self) -> TransactionValidity;
65101
}
66102

67103
impl<
@@ -88,59 +124,80 @@ impl<
88124
{
89125
let inbound_lane_data = pallet_bridge_messages::InboundLanes::<T, I>::get(proof.lane);
90126

91-
return Some(ReceiveMessagesProofInfo {
127+
return Some(ReceiveMessagesProofInfo(BaseMessagesProofInfo {
92128
lane_id: proof.lane,
93-
best_proof_nonce: proof.nonces_end,
129+
best_bundled_nonce: proof.nonces_end,
94130
best_stored_nonce: inbound_lane_data.last_delivered_nonce(),
95-
})
131+
}))
96132
}
97133

98134
None
99135
}
100136

101-
fn receive_messages_proof_info_for(&self, lane_id: LaneId) -> Option<ReceiveMessagesProofInfo> {
102-
self.receive_messages_proof_info().filter(|info| info.lane_id == lane_id)
103-
}
104-
105-
fn check_obsolete_receive_messages_proof(&self) -> TransactionValidity {
106-
if let Some(proof_info) = self.receive_messages_proof_info() {
107-
if proof_info.best_proof_nonce <= proof_info.best_stored_nonce {
108-
log::trace!(
109-
target: pallet_bridge_messages::LOG_TARGET,
110-
"Rejecting obsolete messages delivery transaction: \
111-
lane {:?}, bundled {:?}, best {:?}",
112-
proof_info.lane_id,
113-
proof_info.best_proof_nonce,
114-
proof_info.best_stored_nonce,
115-
);
116-
117-
return sp_runtime::transaction_validity::InvalidTransaction::Stale.into()
118-
}
119-
}
120-
121-
Ok(sp_runtime::transaction_validity::ValidTransaction::default())
122-
}
123-
124-
fn check_obsolete_receive_messages_delivery_proof(&self) -> TransactionValidity {
137+
fn receive_messages_delivery_proof_info(&self) -> Option<ReceiveMessagesDeliveryProofInfo> {
125138
if let Some(pallet_bridge_messages::Call::<T, I>::receive_messages_delivery_proof {
126139
ref proof,
127140
ref relayers_state,
128141
..
129142
}) = self.is_sub_type()
130143
{
131144
let outbound_lane_data = pallet_bridge_messages::OutboundLanes::<T, I>::get(proof.lane);
132-
if relayers_state.last_delivered_nonce <= outbound_lane_data.latest_received_nonce {
145+
146+
return Some(ReceiveMessagesDeliveryProofInfo(BaseMessagesProofInfo {
147+
lane_id: proof.lane,
148+
best_bundled_nonce: relayers_state.last_delivered_nonce,
149+
best_stored_nonce: outbound_lane_data.latest_received_nonce,
150+
}))
151+
}
152+
153+
None
154+
}
155+
156+
fn call_info(&self) -> Option<CallInfo> {
157+
if let Some(info) = self.receive_messages_proof_info() {
158+
return Some(CallInfo::ReceiveMessagesProof(info))
159+
}
160+
161+
if let Some(info) = self.receive_messages_delivery_proof_info() {
162+
return Some(CallInfo::ReceiveMessagesDeliveryProof(info))
163+
}
164+
165+
None
166+
}
167+
168+
fn call_info_for(&self, lane_id: LaneId) -> Option<CallInfo> {
169+
self.call_info().filter(|info| {
170+
let actual_lane_id = match info {
171+
CallInfo::ReceiveMessagesProof(info) => info.0.lane_id,
172+
CallInfo::ReceiveMessagesDeliveryProof(info) => info.0.lane_id,
173+
};
174+
actual_lane_id == lane_id
175+
})
176+
}
177+
178+
fn check_obsolete_call(&self) -> TransactionValidity {
179+
match self.call_info() {
180+
Some(CallInfo::ReceiveMessagesProof(proof_info)) if proof_info.0.is_obsolete() => {
133181
log::trace!(
134182
target: pallet_bridge_messages::LOG_TARGET,
135-
"Rejecting obsolete messages confirmation transaction: \
136-
lane {:?}, bundled {:?}, best {:?}",
137-
proof.lane,
138-
relayers_state.last_delivered_nonce,
139-
outbound_lane_data.latest_received_nonce,
183+
"Rejecting obsolete messages delivery transaction: {:?}",
184+
proof_info
140185
);
141186

142187
return sp_runtime::transaction_validity::InvalidTransaction::Stale.into()
143-
}
188+
},
189+
Some(CallInfo::ReceiveMessagesDeliveryProof(proof_info))
190+
if proof_info.0.is_obsolete() =>
191+
{
192+
log::trace!(
193+
target: pallet_bridge_messages::LOG_TARGET,
194+
"Rejecting obsolete messages confirmation transaction: {:?}",
195+
proof_info,
196+
);
197+
198+
return sp_runtime::transaction_validity::InvalidTransaction::Stale.into()
199+
},
200+
_ => {},
144201
}
145202

146203
Ok(sp_runtime::transaction_validity::ValidTransaction::default())
@@ -153,8 +210,8 @@ mod tests {
153210
messages::{
154211
source::FromBridgedChainMessagesDeliveryProof, target::FromBridgedChainMessagesProof,
155212
},
213+
messages_call_ext::MessagesCallSubType,
156214
mock::{TestRuntime, ThisChainRuntimeCall},
157-
BridgeRuntimeFilterCall,
158215
};
159216
use bp_messages::UnrewardedRelayersState;
160217

@@ -169,22 +226,21 @@ mod tests {
169226
nonces_start: bp_messages::MessageNonce,
170227
nonces_end: bp_messages::MessageNonce,
171228
) -> bool {
172-
pallet_bridge_messages::Pallet::<TestRuntime>::validate(
173-
&ThisChainRuntimeCall::BridgeMessages(
174-
pallet_bridge_messages::Call::<TestRuntime, ()>::receive_messages_proof {
175-
relayer_id_at_bridged_chain: 42,
176-
messages_count: (nonces_end - nonces_start + 1) as u32,
177-
dispatch_weight: frame_support::weights::Weight::zero(),
178-
proof: FromBridgedChainMessagesProof {
179-
bridged_header_hash: Default::default(),
180-
storage_proof: vec![],
181-
lane: bp_messages::LaneId([0, 0, 0, 0]),
182-
nonces_start,
183-
nonces_end,
184-
},
229+
ThisChainRuntimeCall::BridgeMessages(
230+
pallet_bridge_messages::Call::<TestRuntime, ()>::receive_messages_proof {
231+
relayer_id_at_bridged_chain: 42,
232+
messages_count: (nonces_end - nonces_start + 1) as u32,
233+
dispatch_weight: frame_support::weights::Weight::zero(),
234+
proof: FromBridgedChainMessagesProof {
235+
bridged_header_hash: Default::default(),
236+
storage_proof: vec![],
237+
lane: bp_messages::LaneId([0, 0, 0, 0]),
238+
nonces_start,
239+
nonces_end,
185240
},
186-
),
241+
},
187242
)
243+
.check_obsolete_call()
188244
.is_ok()
189245
}
190246

@@ -230,21 +286,20 @@ mod tests {
230286
}
231287

232288
fn validate_message_confirmation(last_delivered_nonce: bp_messages::MessageNonce) -> bool {
233-
pallet_bridge_messages::Pallet::<TestRuntime>::validate(
234-
&ThisChainRuntimeCall::BridgeMessages(
235-
pallet_bridge_messages::Call::<TestRuntime>::receive_messages_delivery_proof {
236-
proof: FromBridgedChainMessagesDeliveryProof {
237-
bridged_header_hash: Default::default(),
238-
storage_proof: Vec::new(),
239-
lane: bp_messages::LaneId([0, 0, 0, 0]),
240-
},
241-
relayers_state: UnrewardedRelayersState {
242-
last_delivered_nonce,
243-
..Default::default()
244-
},
289+
ThisChainRuntimeCall::BridgeMessages(
290+
pallet_bridge_messages::Call::<TestRuntime>::receive_messages_delivery_proof {
291+
proof: FromBridgedChainMessagesDeliveryProof {
292+
bridged_header_hash: Default::default(),
293+
storage_proof: Vec::new(),
294+
lane: bp_messages::LaneId([0, 0, 0, 0]),
295+
},
296+
relayers_state: UnrewardedRelayersState {
297+
last_delivered_nonce,
298+
..Default::default()
245299
},
246-
),
300+
},
247301
)
302+
.check_obsolete_call()
248303
.is_ok()
249304
}
250305

bridges/bin/runtime-common/src/mock.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -230,8 +230,7 @@ impl pallet_bridge_messages::Config for TestRuntime {
230230
type DeliveryConfirmationPayments = pallet_bridge_relayers::DeliveryConfirmationPaymentsAdapter<
231231
TestRuntime,
232232
(),
233-
frame_support::traits::ConstU64<100_000>,
234-
frame_support::traits::ConstU64<10_000>,
233+
ConstU64<100_000>,
235234
>;
236235

237236
type SourceHeaderChain = SourceHeaderChainAdapter<OnThisChainBridge>;

0 commit comments

Comments
 (0)