Testing and Debugging¶
Introduction¶
Cross-Consensus Messaging (XCM) is a core feature of the Polkadot ecosystem, enabling communication between parachains, relay chains, and system chains. To ensure the reliability of XCM-powered blockchains, thorough testing and debugging are essential before production deployment.
This article explores two indispensable tools for XCM testing, the XCM Simulator and the XCM Emulator, to help developers onboard and test their solutions effectively.
XCM Simulator¶
Setting up a live network with multiple interconnected parachains for XCM testing can be complex and resource-intensive. To address this, the xcm-simulator
was developed. This versatile tool enables developers to test and experiment with XCM in a controlled, simulated network environment.
The xcm-simulator
offers a fast and efficient way to test XCM instructions against the xcm-executor
. It serves as an experimental playground for developers, supporting features such as:
- Mocking Downward Message Passing (DMP) - retrieve incoming XCMs from the relay chain using the
received_dmp
getter - Rapid iteration - test XCM messages in isolation without relying on full network simulations
The xcm-simulator
achieves this by utilizing mocked runtimes for both the relay chain and connected parachains, enabling developers to focus on message logic and configuration without needing a live network.
How does it work?¶
The xcm-simulator
provides the following macros for building a mocked simulation environment:
-
decl_test_relay_chain
- implements upward message passing (UMP) for the specified relay chain struct. The struct must define the XCM configuration for the relay chain:decl_test_relay_chain! { pub struct Relay { Runtime = relay_chain::Runtime, XcmConfig = relay_chain::XcmConfig, new_ext = relay_ext(), } }
The
relay_ext()
sets up a test environment for the relay chain with predefined storage, then returns aTestExternalities
instance for further testing. -
decl_test_parachain
- implements theXcmMessageHandlerT
andDmpMessageHandlerT
traits for the specified parachain struct. Requires the parachain struct to include theXcmpMessageHandler
andDmpMessageHandler
pallets, which define the logic for processing messages (implemented throughmock_message_queue
). The patter must be the following:decl_test_parachain! { pub struct ParaA { Runtime = parachain::Runtime, XcmpMessageHandler = parachain::MsgQueue, DmpMessageHandler = parachain::MsgQueue, new_ext = para_ext(1), } }
The
para_ext(para_id: u32)
function initializes a test environment for a parachain with a specifiedpara_id
, sets the initial configuration of the parachain, returning aTestExternalities
instance for testing.Note
Developers can take this idea and define as many parachains as they want, like
ParaA
,ParaB
,ParaC
, etc -
decl_test_network
- defines a testing network consisting of a relay chain and multiple parachains. Takes a network struct as input and implements functionalities for testing, includingParachainXcmRouter
andRelayChainXcmRouter
. The struct must specify the relay chain and an indexed list of parachains to be included in the network:
By leveraging these macros, developers can customize their testing networks by defining relay chains and parachains tailored to their needs.
For guidance on implementing a mock runtime for a Polkadot SDK-based chain, refer to the Pallet Testing article. This framework enables thorough testing of runtime and cross-chain interactions.
For a complete example of how to use the xcm-simulator
, explore the sample
provided in the xcm-simulator
codebase.
XCM Emulator¶
The xcm-emulator
is a tool designed to simulate the execution of XCM programs using predefined runtime configurations. These configurations include those utilized by live networks like Kusama, Polkadot, and the Asset Hub.
This tool enables testing of cross-chain message passing, providing a way to verify outcomes, weights, and side effects efficiently.
The xcm-emulator
relies on transport layer pallets. However, the messages do not leverage the same messaging infrastructure as live networks since the transport mechanism is mocked. Additionally, consensus-related events are not covered, such as disputes, staking, and ImOnline events. Parachains should use end-to-end (E2E) tests to validate these events.
Pros and Cons¶
The XCM Emulator provides both advantages and limitations when testing cross-chain communication in simulated environments.
-
Pros:
- Interactive debugging - offers tracing capabilities similar to EVM, enabling detailed analysis of issues
- Runtime composability - facilitates testing and integration of multiple runtime components
- Immediate feedback - supports Test-Driven Development (TDD) by providing rapid test results
- Seamless integration testing - simplifies the process of testing new runtime versions in an isolated environment
-
Cons:
- Simplified emulation - always assumes message delivery, which may not mimic real-world network behavior
- Dependency challenges - requires careful management of dependency versions and patching. Refer to the Cargo dependency documentation
- Compilation overhead - testing environments can be resource-intensive, requiring frequent compilation updates
How Does It Work?¶
The xcm-emulator
package builds upon the functionality provided by the xcm-simulator
package, offering the same set of macros while extending their capabilities. In addition to the standard features, xcm-emulator
introduces new tools that make testing cross-chain communication more comprehensive.
One of the key additions is the decl_test_bridges
macro. This macro allows developers to define and implement mock bridges for testing interoperability in the Polkadot ecosystem.
-
decl_test_bridges
- enables the creation of multiple bridges between chains, specifying their source chain, target chain, and the handler responsible for processing messages
Utilizing the capabilities of the xcm-emulator, developers can effectively design, test, and optimize cross-chain functionality, fostering interoperability within the Polkadot ecosystem.
| Created: October 18, 2024