mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-05-31 06:21:02 +00:00
Do not require new headers if lane is empty (#1725)
* do not require new headers if lane is empty * handle edge case (need proof-of-delivery-confirmations to be able to submit delivery tx) in required_source_header_at_target * clippy
This commit is contained in:
committed by
Bastian Köcher
parent
b51da6451d
commit
1b9b134f30
@@ -318,16 +318,31 @@ where
|
|||||||
&self,
|
&self,
|
||||||
current_best: &SourceHeaderIdOf<P>,
|
current_best: &SourceHeaderIdOf<P>,
|
||||||
) -> Option<SourceHeaderIdOf<P>> {
|
) -> Option<SourceHeaderIdOf<P>> {
|
||||||
|
let has_nonces_to_deliver = !self.strategy.is_empty();
|
||||||
let header_required_for_messages_delivery =
|
let header_required_for_messages_delivery =
|
||||||
self.strategy.required_source_header_at_target(current_best);
|
self.strategy.required_source_header_at_target(current_best);
|
||||||
let header_required_for_reward_confirmations_delivery =
|
let header_required_for_reward_confirmations_delivery = self
|
||||||
self.latest_confirmed_nonces_at_source.back().map(|(id, _)| id.clone());
|
.latest_confirmed_nonces_at_source
|
||||||
|
.back()
|
||||||
|
.filter(|(id, nonce)| *nonce != 0 && id.0 > current_best.0)
|
||||||
|
.map(|(id, _)| id.clone());
|
||||||
match (
|
match (
|
||||||
|
has_nonces_to_deliver,
|
||||||
header_required_for_messages_delivery,
|
header_required_for_messages_delivery,
|
||||||
header_required_for_reward_confirmations_delivery,
|
header_required_for_reward_confirmations_delivery,
|
||||||
) {
|
) {
|
||||||
(Some(id1), Some(id2)) => Some(if id1.0 > id2.0 { id1 } else { id2 }),
|
// if we need to delver messages and proof-of-delivery-confirmations, then we need to
|
||||||
(a, b) => a.or(b),
|
// select the most recent header to avoid extra roundtrips
|
||||||
|
(true, Some(id1), Some(id2)) => Some(if id1.0 > id2.0 { id1 } else { id2 }),
|
||||||
|
// if we only need to deliver messages - fine, let's require some source header
|
||||||
|
//
|
||||||
|
// if we need new header for proof-of-delivery-confirmations - let's also ask for that.
|
||||||
|
// Even though it may require additional header, we'll be sure that we won't block the
|
||||||
|
// lane (sometimes we can't deliver messages without proof-of-delivery-confirmations)
|
||||||
|
(true, a, b) => a.or(b),
|
||||||
|
// we never submit delivery transaction without messages, so if `has_nonces_to_deliver`
|
||||||
|
// if `false`, we don't need any source headers at target
|
||||||
|
(false, _, _) => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -926,38 +941,58 @@ mod tests {
|
|||||||
// - all messages [20; 23] have been generated at source block#1;
|
// - all messages [20; 23] have been generated at source block#1;
|
||||||
let (mut state, mut strategy) = prepare_strategy();
|
let (mut state, mut strategy) = prepare_strategy();
|
||||||
//
|
//
|
||||||
// - messages [20; 21] have been delivered, but messages [11; 20] can't be delivered because
|
// - messages [20; 23] have been delivered
|
||||||
// of unrewarded relayers vector capacity;
|
|
||||||
strategy.max_unconfirmed_nonces_at_target = 2;
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
strategy.select_nonces_to_deliver(state.clone()).await,
|
strategy.select_nonces_to_deliver(state.clone()).await,
|
||||||
Some(((20..=21), proof_parameters(false, 2)))
|
Some(((20..=23), proof_parameters(false, 4)))
|
||||||
);
|
);
|
||||||
strategy.finalized_target_nonces_updated(
|
strategy.finalized_target_nonces_updated(
|
||||||
TargetClientNonces {
|
TargetClientNonces {
|
||||||
latest_nonce: 21,
|
latest_nonce: 23,
|
||||||
nonces_data: DeliveryRaceTargetNoncesData {
|
nonces_data: DeliveryRaceTargetNoncesData {
|
||||||
confirmed_nonce: 19,
|
confirmed_nonce: 19,
|
||||||
unrewarded_relayers: UnrewardedRelayersState {
|
unrewarded_relayers: UnrewardedRelayersState {
|
||||||
unrewarded_relayer_entries: 2,
|
unrewarded_relayer_entries: 1,
|
||||||
messages_in_oldest_entry: 2,
|
messages_in_oldest_entry: 4,
|
||||||
total_messages: 2,
|
total_messages: 4,
|
||||||
last_delivered_nonce: 19,
|
last_delivered_nonce: 23,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
&mut state,
|
&mut state,
|
||||||
);
|
);
|
||||||
assert_eq!(strategy.select_nonces_to_deliver(state).await, None);
|
// nothing needs to be delivered now and we don't need any new headers
|
||||||
|
assert_eq!(strategy.select_nonces_to_deliver(state.clone()).await, None);
|
||||||
|
assert_eq!(strategy.required_source_header_at_target(&header_id(1)), None);
|
||||||
|
|
||||||
|
// now let's generate two more nonces [24; 25] at the soruce;
|
||||||
|
strategy.source_nonces_updated(header_id(2), source_nonces(24..=25, 19, 0));
|
||||||
//
|
//
|
||||||
// - messages [1; 10] receiving confirmation has been delivered at source block#2;
|
// - so now we'll need to relay source block#2 to be able to accept messages [24; 25].
|
||||||
strategy.source_nonces_updated(
|
assert_eq!(strategy.select_nonces_to_deliver(state.clone()).await, None);
|
||||||
header_id(2),
|
|
||||||
SourceClientNonces { new_nonces: MessageDetailsMap::new(), confirmed_nonce: Some(21) },
|
|
||||||
);
|
|
||||||
//
|
|
||||||
// - so now we'll need to relay source block#11 to be able to accept messages [11; 20].
|
|
||||||
assert_eq!(strategy.required_source_header_at_target(&header_id(1)), Some(header_id(2)));
|
assert_eq!(strategy.required_source_header_at_target(&header_id(1)), Some(header_id(2)));
|
||||||
|
|
||||||
|
// let's relay source block#2
|
||||||
|
state.best_finalized_source_header_id_at_source = Some(header_id(2));
|
||||||
|
state.best_finalized_source_header_id_at_best_target = Some(header_id(2));
|
||||||
|
state.best_target_header_id = Some(header_id(2));
|
||||||
|
state.best_finalized_target_header_id = Some(header_id(2));
|
||||||
|
|
||||||
|
// and ask strategy again => still nothing to deliver, because parallel confirmations
|
||||||
|
// race need to be pushed further
|
||||||
|
assert_eq!(strategy.select_nonces_to_deliver(state.clone()).await, None);
|
||||||
|
assert_eq!(strategy.required_source_header_at_target(&header_id(2)), None);
|
||||||
|
|
||||||
|
// let's confirm messages [20; 23]
|
||||||
|
strategy.source_nonces_updated(header_id(2), source_nonces(24..=25, 23, 0));
|
||||||
|
|
||||||
|
// and ask strategy again => now we have everything required to deliver remaining
|
||||||
|
// [24; 25] nonces and proof of [20; 23] confirmation
|
||||||
|
assert_eq!(
|
||||||
|
strategy.select_nonces_to_deliver(state).await,
|
||||||
|
Some(((24..=25), proof_parameters(true, 2))),
|
||||||
|
);
|
||||||
|
assert_eq!(strategy.required_source_header_at_target(&header_id(2)), None);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[async_std::test]
|
#[async_std::test]
|
||||||
@@ -985,4 +1020,38 @@ mod tests {
|
|||||||
Some(((20..=24), proof_parameters(false, 5)))
|
Some(((20..=24), proof_parameters(false, 5)))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[allow(clippy::reversed_empty_ranges)]
|
||||||
|
fn no_source_headers_required_at_target_if_lanes_are_empty() {
|
||||||
|
let mut strategy = TestStrategy {
|
||||||
|
max_unrewarded_relayer_entries_at_target: 4,
|
||||||
|
max_unconfirmed_nonces_at_target: 4,
|
||||||
|
max_messages_in_single_batch: 4,
|
||||||
|
max_messages_weight_in_single_batch: Weight::from_ref_time(4),
|
||||||
|
max_messages_size_in_single_batch: 4,
|
||||||
|
latest_confirmed_nonces_at_source: VecDeque::new(),
|
||||||
|
lane_source_client: TestSourceClient::default(),
|
||||||
|
lane_target_client: TestTargetClient::default(),
|
||||||
|
metrics_msg: None,
|
||||||
|
target_nonces: None,
|
||||||
|
strategy: BasicStrategy::new(),
|
||||||
|
};
|
||||||
|
|
||||||
|
let source_header_id = header_id(10);
|
||||||
|
strategy.source_nonces_updated(
|
||||||
|
source_header_id,
|
||||||
|
// MessageDeliveryRaceSource::nonces returns Some(0), because that's how it is
|
||||||
|
// represented in memory (there's no Options in OutboundLaneState)
|
||||||
|
source_nonces(1u64..=0u64, 0, 0),
|
||||||
|
);
|
||||||
|
|
||||||
|
// even though `latest_confirmed_nonces_at_source` is not empty, new headers are not
|
||||||
|
// requested
|
||||||
|
assert_eq!(
|
||||||
|
strategy.latest_confirmed_nonces_at_source,
|
||||||
|
VecDeque::from([(source_header_id, 0)])
|
||||||
|
);
|
||||||
|
assert_eq!(strategy.required_source_header_at_target(&source_header_id), None);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user