Chopsticks

repository·master·Indexed 41 days ago

https://github.com/acalanetwork/chopsticks

A 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.

Tokens
42.4K
Snippets
154
Records
186
Agent score
51%

What's inside Chopsticks

  1. What is Chopsticks?

    master
    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.
  2. Overview of Chopsticks packages

    master

    Chopsticks 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.
  3. How Bridged-XCM testing works

    master

    The connectBridgeHubs utility relays messages between two forked bridge hubs. It does not build blocks itself; instead, it reads state, builds storage proofs, writes ImportedParaHeads directly, and pushes extrinsics to pools. It operates via two reactive loops:

    1. deliver: Pushes receive_messages_proof for the range of un-delivered messages to the destination pool.
    2. confirm: Proves the destination's InboundLanes and pushes receive_messages_delivery_proof to the source pool to advance the latest_received_nonce.

    Important Requirements:

    • Each relayer signer must hold a balance on both hubs.
    • To relay in the reverse direction, call connectBridgeHubs with 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();
  4. Extend Chopsticks with Plugins

    master

    Chopsticks is extensible via two types of plugins:

    1. cli plugins: Extend the Chopsticks Command Line Interface.
    2. rpc plugins: Extend the Chopsticks RPC interface.

    For implementation guidance, refer to the run-block plugin in packages/chopsticks/src/plugins/run-block/.

  5. Setup XCM multichain and bridged-XCM environments

    master

    Chopsticks 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-hub
  6. Install Chopsticks from source

    master

    To 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-wasm
  7. Use the Try-Runtime CLI for runtime migration checks

    master

    The try-runtime command 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 PreAndPost
  8. Resume network state with --resume

    master

    Chopsticks allows you to resume testing from a specific block hash, block number, or the latest block in the database.

    Single Network Resumption

    Use the --resume flag with the CLI:

    npx @acala-network/chopsticks@latest -c configs/acala.yml --resume=12345

    Multi-Chain Resumption

    In a multi-chain XCM setup, specify the resume key in each chain's .yml configuration file. Each network should also have its own unique db path to allow independent state persistence.

    Example Config (configs/polkadot.yml):

    endpoint: wss://polkadot-rpc.n.dwellir.com
    db: ./db-polkadot.sqlite
    resume: 12345

    Running 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>
    ...
  9. Prefetch and cache storages for migrations

    master

    When 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-storages section to your .yml config. 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-storages CLI Subcommand

    Use 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.sqlite

    Arguments 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 the db: key in each config file instead of using CLI flags.

    prefetch-storages:
      - '0x123456'
      - Balances
      - Tokens.Accounts
      - Tokens.Accounts: [5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY]
  10. Use @acala-network/chopsticks-testing for blockchain data tests

    master

    The @acala-network/chopsticks-testing package provides utilities to check events, system events, UMP, and HRMP messages. Use withExpect to initialize the testing utilities with your test runner's (e.g., Vitest or Jest) expect function, and setupContext to 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');
      });
    });
  11. Run a local test node with custom storage

    master

    You 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.json
  12. Quick Start: Fork a network

    master

    You 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 bun is 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