Chopsticks
repository·master·Indexed 41 days ago
https://github.com/acalanetwork/chopsticksA developer tool for creating local 'parallel realities' of Substrate-based blockchains. It enables advanced testing scenarios including block replaying, state diffing, XCM multichain simulation, and bridged-XCM testing without live network deployment. Features include a `trace-transaction` plugin for Acala & Karura EVM+, a `try-runtime` CLI for migration checks, and the `@acala-network/chopsticks-testing` package for blockchain data and XCM verification.
What's inside Chopsticks
- Chopsticks is a tool for creating a "parallel reality" of a Substrate-based network. It allows developers to locally fork existing chains to replay blocks, examine how extrinsics affect state, and perform XCM testing without deploying to a live network. This enables testing custom blockchain configurations in a local development environment.
Overview of Chopsticks packages
masterChopsticks is composed of several specialized packages. The primary entry points for users are:
@acala-network/chopsticks: Provides the Chopsticks CLI and RPC server, including EVM+ tracing capabilities.@acala-network/chopsticks-core: Defines the underlying blockchain data structures used by the system.
How Bridged-XCM testing works
masterThe
connectBridgeHubsutility relays messages between two forked bridge hubs. It does not build blocks itself; instead, it reads state, builds storage proofs, writesImportedParaHeadsdirectly, and pushes extrinsics to pools. It operates via two reactive loops:- deliver: Pushes
receive_messages_prooffor the range of un-delivered messages to the destination pool. - confirm: Proves the destination's
InboundLanesand pushesreceive_messages_delivery_proofto the source pool to advance thelatest_received_nonce.
Important Requirements:
- Each relayer signer must hold a balance on both hubs.
- To relay in the reverse direction, call
connectBridgeHubswith the hubs swapped and a distinct signer to avoid nonce collisions. - Pallet names and para IDs are auto-detected from metadata.
import { connectBridgeHubs, setupContext } from '@acala-network/chopsticks-testing'; import { Keyring } from '@polkadot/keyring'; const bhp = await setupContext({ endpoint: 'wss://polkadot-bridge-hub-rpc.polkadot.io' }); const bhk = await setupContext({ endpoint: 'wss://kusama-bridge-hub-rpc.polkadot.io' }); const signer = new Keyring({ type: 'sr25519' }).addFromUri('//Alice'); const handle = await connectBridgeHubs(bhp.api, bhk.api, { signer }); // ... drive blocks ... await handle.disconnect();- deliver: Pushes
Extend Chopsticks with Plugins
masterChopsticks is extensible via two types of plugins:
cliplugins: Extend the Chopsticks Command Line Interface.rpcplugins: Extend the Chopsticks RPC interface.
For implementation guidance, refer to the
run-blockplugin inpackages/chopsticks/src/plugins/run-block/.Setup XCM multichain and bridged-XCM environments
masterChopsticks provides specialized commands for testing cross-chain messaging (XCM).
XCM Multichain: Connect multiple parachains. You can also connect multiple parachains without a relaychain.
Bridged-XCM: Setup bridging between two ecosystems. Note that one parachain on each side must host
pallet_bridge_messages; Chopsticks handles the wiring in both directions automatically.# Setup XCM multichain (e.g., Kusama relaychain with Karura and Statemine parachains) npx @acala-network/chopsticks@latest xcm -r kusama -p karura -p statemine # Setup bridged-XCM between Polkadot and Kusama ecosystems npx @acala-network/chopsticks@latest bridge \ -r polkadot -p polkadot-bridge-hub -p polkadot-asset-hub \ -R kusama -P kusama-bridge-hub -P kusama-asset-hubInstall Chopsticks from source
masterTo install Chopsticks from the repository, ensure you have a Rust environment (version >= 1.64) set up. You must include submodules (specifically
smoldot) during cloning.Important: Do not use your IDE's built-in tools to build WASM; use the provided yarn command.
# Clone with submodules git clone --recurse-submodules https://github.com/AcalaNetwork/chopsticks.git && cd chopsticks # Install dependencies yarn # Build WASM yarn build-wasmUse the Try-Runtime CLI for runtime migration checks
masterThe
try-runtimecommand in Chopsticks allows you to perform runtime migration checks.Note: This is an experimental feature. Currently, it only supports weight checks; it does not support PoV (Proof of Validity) measures.
To run a migration check, you must provide a remote endpoint, the path to the WASM runtime, and the specific checks you wish to perform (e.g.,
PreAndPost).npx @acala-network/chopsticks try-runtime \ --endpoint <wss://remote.endpoint> \ --runtime <wasm_runtime_path> \ --checks PreAndPostResume network state with --resume
masterChopsticks allows you to resume testing from a specific block hash, block number, or the latest block in the database.
Single Network Resumption
Use the
--resumeflag with the CLI:npx @acala-network/chopsticks@latest -c configs/acala.yml --resume=12345Multi-Chain Resumption
In a multi-chain XCM setup, specify the
resumekey in each chain's.ymlconfiguration file. Each network should also have its own uniquedbpath to allow independent state persistence.Example Config (
configs/polkadot.yml):endpoint: wss://polkadot-rpc.n.dwellir.com db: ./db-polkadot.sqlite resume: 12345Running the XCM setup:
npx @acala-network/chopsticks@latest xcm \ -r configs/polkadot.yml \ -p configs/acala.yml# configs/polkadot.yml ... db: <db-filepath> resume: <block-number> | <block-hash> ...Prefetch and cache storages for migrations
masterWhen testing large migrations, you can prefetch and cache storages to speed up the process. There are two methods:
Method 1: Configuration File
Add a
prefetch-storagessection to your.ymlconfig. Supported formats include:- Hex prefix:
'0x123456' - Pallet Name:
Balances - Pallet.Storage:
Tokens.Accounts - Specific Storage for an Account:
Tokens.Accounts: [5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY'] - Specific Storage with extra params:
Tokens.Accounts: [5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY, { token: DOT }]
Method 2:
fetch-storagesCLI SubcommandUse the subcommand to fetch and cache storages directly to a SQLite database.
npx @acala-network/chopsticks@latest fetch-storages 0x123456 Balances Tokens.Accounts \ --endpoint=wss://acala-rpc-0.aca-api.network \ --block=<blockhash> \ --db=acala.sqliteArguments for
fetch-storages:hex: Fetch all storages with this prefix.PalletName: Fetch all storages for this pallet.PalletName.StorageName: Fetch all storages for this specific storage.
Note: Fetched storages are saved in the SQLite file specified by
--db. If not provided, it defaults to./db-{network}-{block}.sqlite. In multi-chain scenarios, define thedb:key in each config file instead of using CLI flags.prefetch-storages: - '0x123456' - Balances - Tokens.Accounts - Tokens.Accounts: [5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY]- Hex prefix:
Use @acala-network/chopsticks-testing for blockchain data tests
masterThe
@acala-network/chopsticks-testingpackage provides utilities to check events, system events, UMP, and HRMP messages. UsewithExpectto initialize the testing utilities with your test runner's (e.g., Vitest or Jest)expectfunction, andsetupContextto establish a connection to a network endpoint.import { withExpect, setupContext } from '@acala-network/chopsticks-testing'; import { describe, expect, it } from 'vitest'; const { check, checkEvents, checkSystemEvents, checkUmp, checkHrmp } = withExpect(expect); describe('My Chain Tests', () => { it('should process events correctly', async () => { const network = await setupContext({ endpoint: 'wss://polkadot-rpc.n.dwellir.com' }); // Check and redact system events await checkSystemEvents(network) .redact({ number: 2, hash: true }) .toMatchSnapshot('system events'); // Filter specific events await checkSystemEvents(network, 'balances', { section: 'system', method: 'ExtrinsicSuccess' }) .toMatchSnapshot('filtered events'); }); });Run a local test node with custom storage
masterYou can run a local test node that acts as a parallel reality. Once running, you can connect to it using Polkadot.js Apps at
ws://localhost:8000. Any transactions submitted to this node will produce new blocks in the local fork.You can optionally pre-define or override the initial state using the
-s|--import-storage=<file_path>option with a JSON or YAML file.# Run the test node npx @acala-network/chopsticks@latest --endpoint=wss://acala-rpc-2.aca-api.network/ws # Run with custom initial storage npx @acala-network/chopsticks@latest --endpoint=wss://acala-rpc-2.aca-api.network/ws -s my_storage.jsonQuick Start: Fork a network
masterYou can quickly fork a network like Acala mainnet by providing an endpoint to the CLI.
Note: It is highly recommended to use a configuration file for more complex setups. You can find examples in the
configs/directory of the repository.Warning: Using
bunis not recommended due to known issues with Bun's WASM support which can cause the Chopsticks instance to hang.# Fork Acala mainnet using an endpoint npx @acala-network/chopsticks@latest --endpoint=wss://acala-rpc.aca-api.network/ws # Run using a config file (e.g., configs/acala.yml) npx @acala-network/chopsticks@latest -c acala