Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
OnMessagesDelivered callback
  • Loading branch information
svyatonik committed Jun 18, 2021
commit 61ec89e9bfde5403cb4f83570e8bf430b6d121e9
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions bin/millau/runtime/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -384,6 +384,7 @@ impl pallet_bridge_messages::Config<WithRialtoMessagesInstance> for Runtime {
GetDeliveryConfirmationTransactionFee,
RootAccountForPayments,
>;
type OnMessagesDelivered = ();

type SourceHeaderChain = crate::rialto_messages::Rialto;
type MessageDispatch = crate::rialto_messages::FromRialtoMessageDispatch;
Expand Down
1 change: 1 addition & 0 deletions bin/rialto/runtime/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -491,6 +491,7 @@ impl pallet_bridge_messages::Config<WithMillauMessagesInstance> for Runtime {
GetDeliveryConfirmationTransactionFee,
RootAccountForPayments,
>;
type OnMessagesDelivered = ();

type SourceHeaderChain = crate::millau_messages::Millau;
type MessageDispatch = crate::millau_messages::FromMillauMessageDispatch;
Expand Down
82 changes: 80 additions & 2 deletions modules/messages/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,9 @@ use crate::outbound_lane::{OutboundLane, OutboundLaneStorage, ReceivalConfirmati
use crate::weights::WeightInfo;

use bp_messages::{
source_chain::{LaneMessageVerifier, MessageDeliveryAndDispatchPayment, RelayersRewards, TargetHeaderChain},
source_chain::{
LaneMessageVerifier, MessageDeliveryAndDispatchPayment, OnMessagesDelivered, RelayersRewards, TargetHeaderChain,
},
target_chain::{DispatchMessage, MessageDispatch, ProvedLaneMessages, ProvedMessages, SourceHeaderChain},
total_unrewarded_messages, DeliveredMessages, InboundLaneData, LaneId, MessageData, MessageKey, MessageNonce,
OperatingMode, OutboundLaneData, Parameter as MessagesParameter, UnrewardedRelayersState,
Expand Down Expand Up @@ -146,6 +148,8 @@ pub trait Config<I = DefaultInstance>: frame_system::Config {
type LaneMessageVerifier: LaneMessageVerifier<Self::AccountId, Self::OutboundPayload, Self::OutboundMessageFee>;
/// Message delivery payment.
type MessageDeliveryAndDispatchPayment: MessageDeliveryAndDispatchPayment<Self::AccountId, Self::OutboundMessageFee>;
/// Handler for delivered messages.
type OnMessagesDelivered: OnMessagesDelivered;

// Types that are used by inbound_lane (on target chain).

Expand Down Expand Up @@ -636,6 +640,10 @@ decl_module! {
},
};
if let Some(confirmed_messages) = confirmed_messages {
// handle messages delivery
T::OnMessagesDelivered::on_messages_delivered(&confirmed_messages);

// emit 'delivered' event
let received_range = confirmed_messages.begin..=confirmed_messages.end;
Self::deposit_event(RawEvent::MessagesDelivered(lane_id, confirmed_messages));

Expand Down Expand Up @@ -957,6 +965,10 @@ mod tests {
fn send_regular_message() {
get_ready_for_events();

let message_nonce = outbound_lane::<TestRuntime, DefaultInstance>(TEST_LANE_ID)
.data()
.latest_generated_nonce
+ 1;
assert_ok!(Pallet::<TestRuntime>::send_message(
Origin::signed(1),
TEST_LANE_ID,
Expand All @@ -969,7 +981,7 @@ mod tests {
System::<TestRuntime>::events(),
vec![EventRecord {
phase: Phase::Initialization,
event: TestEvent::Messages(RawEvent::MessageAccepted(TEST_LANE_ID, 1)),
event: TestEvent::Messages(RawEvent::MessageAccepted(TEST_LANE_ID, message_nonce)),
topics: vec![],
}],
);
Expand Down Expand Up @@ -1837,4 +1849,70 @@ mod tests {
);
});
}

#[test]
fn messages_delivered_callbacks_are_called() {
run_test(|| {
send_regular_message();
send_regular_message();
send_regular_message();

// messages 1+2 are confirmed in 1 tx, message 3 in a separate tx
// dispatch of message 2 has failed
let mut delivered_messages_1_and_2 = DeliveredMessages::new(1, true);
delivered_messages_1_and_2.note_dispatched_message(false);
let messages_1_and_2_proof = Ok((
TEST_LANE_ID,
InboundLaneData {
last_confirmed_nonce: 0,
relayers: vec![UnrewardedRelayer {
relayer: 0,
messages: delivered_messages_1_and_2.clone(),
}]
.into_iter()
.collect(),
},
));
let delivered_message_3 = DeliveredMessages::new(3, true);
let messages_3_proof = Ok((
TEST_LANE_ID,
InboundLaneData {
last_confirmed_nonce: 0,
relayers: vec![UnrewardedRelayer {
relayer: 0,
messages: delivered_message_3.clone(),
}]
.into_iter()
.collect(),
},
));

// first tx with messages 1+2
assert_ok!(Pallet::<TestRuntime>::receive_messages_delivery_proof(
Origin::signed(1),
TestMessagesDeliveryProof(messages_1_and_2_proof),
UnrewardedRelayersState {
unrewarded_relayer_entries: 1,
total_messages: 2,
..Default::default()
},
));
// second tx with message 3
assert_ok!(Pallet::<TestRuntime>::receive_messages_delivery_proof(
Origin::signed(1),
TestMessagesDeliveryProof(messages_3_proof),
UnrewardedRelayersState {
unrewarded_relayer_entries: 1,
total_messages: 1,
..Default::default()
},
));

// ensure that both callbacks have been called twice: for 1+2, then for 3
crate::mock::TestOnMessagesDelivered1::ensure_called(&delivered_messages_1_and_2);
crate::mock::TestOnMessagesDelivered1::ensure_called(&delivered_message_3);
crate::mock::TestOnMessagesDelivered2::ensure_called(&delivered_messages_1_and_2);
crate::mock::TestOnMessagesDelivered2::ensure_called(&delivered_message_3);
});
}
}
42 changes: 41 additions & 1 deletion modules/messages/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@ use crate::Config;
use bitvec::prelude::*;
use bp_messages::{
source_chain::{
LaneMessageVerifier, MessageDeliveryAndDispatchPayment, RelayersRewards, Sender, TargetHeaderChain,
LaneMessageVerifier, MessageDeliveryAndDispatchPayment, OnMessagesDelivered, RelayersRewards, Sender,
TargetHeaderChain,
},
target_chain::{DispatchMessage, MessageDispatch, ProvedLaneMessages, ProvedMessages, SourceHeaderChain},
DeliveredMessages, InboundLaneData, LaneId, Message, MessageData, MessageKey, MessageNonce, OutboundLaneData,
Expand Down Expand Up @@ -170,6 +171,7 @@ impl Config for TestRuntime {
type TargetHeaderChain = TestTargetHeaderChain;
type LaneMessageVerifier = TestLaneMessageVerifier;
type MessageDeliveryAndDispatchPayment = TestMessageDeliveryAndDispatchPayment;
type OnMessagesDelivered = (TestOnMessagesDelivered1, TestOnMessagesDelivered2);

type SourceHeaderChain = TestSourceHeaderChain;
type MessageDispatch = TestMessageDispatch;
Expand Down Expand Up @@ -346,6 +348,44 @@ impl MessageDeliveryAndDispatchPayment<AccountId, TestMessageFee> for TestMessag
}
}

/// First on-messages-delivered callback.
#[derive(Debug)]
pub struct TestOnMessagesDelivered1;

impl TestOnMessagesDelivered1 {
/// Verify that the callback has been called with given delivered messages.
pub fn ensure_called(messages: &DeliveredMessages) {
let key = (b"TestOnMessagesDelivered1", messages).encode();
assert_eq!(frame_support::storage::unhashed::get(&key), Some(true));
}
}

impl OnMessagesDelivered for TestOnMessagesDelivered1 {
fn on_messages_delivered(messages: &DeliveredMessages) {
let key = (b"TestOnMessagesDelivered1", messages).encode();
frame_support::storage::unhashed::put(&key, &true);
}
}

/// Seconde on-messages-delivered callback.
#[derive(Debug)]
pub struct TestOnMessagesDelivered2;

impl TestOnMessagesDelivered2 {
/// Verify that the callback has been called with given delivered messages.
pub fn ensure_called(messages: &DeliveredMessages) {
let key = (b"TestOnMessagesDelivered2", messages).encode();
assert_eq!(frame_support::storage::unhashed::get(&key), Some(true));
}
}

impl OnMessagesDelivered for TestOnMessagesDelivered2 {
fn on_messages_delivered(messages: &DeliveredMessages) {
let key = (b"TestOnMessagesDelivered2", messages).encode();
frame_support::storage::unhashed::put(&key, &true);
}
}

/// Source header chain that is used in tests.
#[derive(Debug)]
pub struct TestSourceHeaderChain;
Expand Down
1 change: 1 addition & 0 deletions primitives/messages/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0"
[dependencies]
bitvec = { version = "0.20", default-features = false, features = ["alloc"] }
codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive", "bit-vec"] }
impl-trait-for-tuples = "0.2"
serde = { version = "1.0.101", optional = true, features = ["derive"] }

# Bridge dependencies
Expand Down
11 changes: 10 additions & 1 deletion primitives/messages/src/source_chain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@

//! Primitives of messages module, that are used on the source chain.

use crate::{InboundLaneData, LaneId, MessageNonce, OutboundLaneData};
use crate::{DeliveredMessages, InboundLaneData, LaneId, MessageNonce, OutboundLaneData};

use bp_runtime::Size;
use frame_support::{Parameter, RuntimeDebug};
Expand Down Expand Up @@ -135,6 +135,15 @@ pub trait MessageDeliveryAndDispatchPayment<AccountId, Balance> {
}
}

/// Handler for delivered messages.
#[impl_trait_for_tuples::impl_for_tuples(30)]
pub trait OnMessagesDelivered {
/// Called when we receive confirmation that our messages have been delivered to the
/// target chain. The confirmation aso has single bit dispatch result for every
/// confirmed message (see `DeliveredMessages` for details).
fn on_messages_delivered(_messages: &DeliveredMessages) {}
}

/// Structure that may be used in place of `TargetHeaderChain`, `LaneMessageVerifier` and
/// `MessageDeliveryAndDispatchPayment` on chains, where outbound messages are forbidden.
pub struct ForbidOutboundMessages;
Expand Down