-
Notifications
You must be signed in to change notification settings - Fork 53
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
72f296c
commit 63f4554
Showing
11 changed files
with
1,419 additions
and
352 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
73 changes: 73 additions & 0 deletions
73
solo-chains/runtime/dancelight/src/symbiotic_message_processor.rs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
use frame_support::pallet_prelude::*; | ||
use parity_scale_codec::DecodeAll; | ||
use snowbridge_core::Channel; | ||
use snowbridge_router_primitives::inbound::envelope::Envelope; | ||
use snowbridge_router_primitives::inbound::MessageProcessor; | ||
use sp_runtime::DispatchError; | ||
use sp_std::vec::Vec; | ||
|
||
/// Magic bytes are added in every payload intended for this processor to make sure | ||
/// that we are the intended recipient of the message. Reason being scale encoding is not type aware. | ||
/// So a same set of bytes can be decoded for two different data structures if their | ||
/// total size is same. Magic bytes can be checked after decoding to make sure that the sender | ||
/// indeed send a message intended for this processor. | ||
pub const MAGIC_BYTES: [u8; 4] = [112, 21, 0, 56]; | ||
|
||
#[derive(Encode, Decode)] | ||
pub struct Payload<T> | ||
where | ||
T: pallet_external_validators::Config, | ||
{ | ||
pub magic_bytes: [u8; 4], | ||
pub message: Message<T>, | ||
} | ||
|
||
#[derive(Encode, Decode)] | ||
pub enum Message<T> | ||
where | ||
T: pallet_external_validators::Config, | ||
{ | ||
V1(Command<T>), | ||
} | ||
|
||
#[derive(Encode, Decode)] | ||
pub enum Command<T> | ||
where | ||
T: pallet_external_validators::Config, | ||
{ | ||
ReceiveValidators { | ||
validators: Vec<<T as pallet_external_validators::Config>::ValidatorId>, | ||
}, | ||
} | ||
|
||
pub struct SymbioticMessageProcessor<T>(PhantomData<T>); | ||
|
||
impl<T> MessageProcessor for SymbioticMessageProcessor<T> | ||
where | ||
T: pallet_external_validators::Config, | ||
{ | ||
fn can_process_message(_channel: &Channel, envelope: &Envelope) -> bool { | ||
let decode_result = Payload::<T>::decode_all(&mut envelope.payload.as_slice()); | ||
if let Ok(payload) = decode_result { | ||
payload.magic_bytes == MAGIC_BYTES | ||
} else { | ||
false | ||
} | ||
} | ||
|
||
fn process_message(_channel: Channel, envelope: Envelope) -> Result<(), DispatchError> { | ||
let decode_result = Payload::<T>::decode_all(&mut envelope.payload.as_slice()); | ||
let message = if let Ok(payload) = decode_result { | ||
payload.message | ||
} else { | ||
return Err(DispatchError::Other("unable to parse the payload")); | ||
}; | ||
|
||
match message { | ||
Message::V1(Command::ReceiveValidators { validators }) => { | ||
pallet_external_validators::Pallet::<T>::set_external_validators(validators)?; | ||
Ok(()) | ||
} | ||
} | ||
} | ||
} |
98 changes: 98 additions & 0 deletions
98
solo-chains/runtime/dancelight/src/tests/inbound_queue_tests/integration_tests.rs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,98 @@ | ||
use crate::symbiotic_message_processor::{Command, Payload, MAGIC_BYTES}; | ||
use crate::tests::inbound_queue_tests::mock::{ | ||
mock_ext, AccountId, ExternalValidators as MockExternalValidators, InboundQueue, | ||
Test as TestRuntime, MOCK_CHANNEL_ID, | ||
}; | ||
use alloy_sol_types::SolEvent; | ||
use frame_system::pallet_prelude::OriginFor; | ||
use keyring::AccountKeyring; | ||
use parity_scale_codec::Encode; | ||
use snowbridge_beacon_primitives::types::deneb; | ||
use snowbridge_beacon_primitives::{ExecutionProof, VersionedExecutionPayloadHeader}; | ||
use snowbridge_core::inbound::{Log, Message, Proof}; | ||
use snowbridge_router_primitives::inbound::envelope::OutboundMessageAccepted; | ||
use sp_core::H256; | ||
use sp_runtime::DispatchError; | ||
|
||
#[test] | ||
fn test_inbound_queue_message_passing() { | ||
mock_ext().execute_with(|| { | ||
let current_nonce = 1; | ||
|
||
let dummy_proof = Proof { receipt_proof: (vec![], vec![]), execution_proof: ExecutionProof { | ||
header: Default::default(), | ||
ancestry_proof: None, | ||
execution_header: VersionedExecutionPayloadHeader::Deneb(deneb::ExecutionPayloadHeader { | ||
parent_hash: Default::default(), | ||
fee_recipient: Default::default(), | ||
state_root: Default::default(), | ||
receipts_root: Default::default(), | ||
logs_bloom: vec![], | ||
prev_randao: Default::default(), | ||
block_number: 0, | ||
gas_limit: 0, | ||
gas_used: 0, | ||
timestamp: 0, | ||
extra_data: vec![], | ||
base_fee_per_gas: Default::default(), | ||
block_hash: Default::default(), | ||
transactions_root: Default::default(), | ||
withdrawals_root: Default::default(), | ||
blob_gas_used: 0, | ||
excess_blob_gas: 0, | ||
}), | ||
execution_branch: vec![], | ||
} }; | ||
|
||
let event_with_empty_payload = OutboundMessageAccepted { | ||
channel_id: MOCK_CHANNEL_ID.into(), | ||
nonce: current_nonce, | ||
message_id: Default::default(), | ||
payload: vec![], | ||
}; | ||
|
||
assert_eq!(InboundQueue::submit(OriginFor::<TestRuntime>::signed(AccountId::new([0; 32])), Message { | ||
event_log: Log { | ||
address: <TestRuntime as snowbridge_pallet_inbound_queue::Config>::GatewayAddress::get(), | ||
topics: event_with_empty_payload.encode_topics().into_iter().map(|word| H256::from(word.0.0)).collect(), | ||
data: event_with_empty_payload.encode_data(), | ||
}, | ||
proof: dummy_proof.clone(), | ||
}), Err(DispatchError::Other("No handler for message found"))); | ||
|
||
assert_eq!(MockExternalValidators::validators(), MockExternalValidators::whitelisted_validators()); | ||
|
||
let payload_validators = vec![ | ||
AccountKeyring::Charlie.to_account_id(), | ||
AccountKeyring::Ferdie.to_account_id(), | ||
AccountKeyring::BobStash.to_account_id() | ||
]; | ||
|
||
let payload = Payload { | ||
magic_bytes: MAGIC_BYTES, | ||
message: crate::symbiotic_message_processor::Message::V1(Command::<TestRuntime>::ReceiveValidators { | ||
validators: payload_validators.clone() | ||
}), | ||
}; | ||
|
||
let event_with_valid_payload = OutboundMessageAccepted { | ||
channel_id: MOCK_CHANNEL_ID.into(), | ||
nonce: current_nonce, | ||
message_id: Default::default(), | ||
payload: payload.encode(), | ||
}; | ||
|
||
assert_eq!(InboundQueue::submit(OriginFor::<TestRuntime>::signed(AccountId::new([0; 32])), Message { | ||
event_log: Log { | ||
address: <TestRuntime as snowbridge_pallet_inbound_queue::Config>::GatewayAddress::get(), | ||
topics: event_with_valid_payload.encode_topics().into_iter().map(|word| H256::from(word.0.0)).collect(), | ||
data: event_with_valid_payload.encode_data(), | ||
}, | ||
proof: dummy_proof.clone(), | ||
}), Ok(())); | ||
|
||
|
||
let expected_validators = [MockExternalValidators::whitelisted_validators(), payload_validators].concat(); | ||
assert_eq!(MockExternalValidators::validators(), expected_validators); | ||
}); | ||
} |
Oops, something went wrong.