Skip to content

How to Use Chopsticks to Fork Your Appchain

Introduction

Chopsticks provides a developer-friendly method of locally forking existing Substrate-based chains. It allows for the replaying of blocks to easily examine how transactions affect the state, the forking of multiple Tanssi appchains for XCM testing, and more. This empowers developers to test and experiment with their custom blockchain configurations in a local development environment without deploying a live network.

Overall, Chopsticks aims to simplify the process of building blockchain applications on Substrate and make it accessible to a wider range of developers.

This article will cover using Chopsticks to fork and interact with the local copy of a Tanssi appchain.

Note

Chopsticks currently does not support calls done via the Ethereum JSON-RPC. Consequently, you can't fork your chain using Chopsticks and connect Metamask to it.

Prerequisites

To follow along with this tutorial, you will need to clone the repository along with its submodules(Smoldot):

git clone --recurse-submodules https://github.com/AcalaNetwork/chopsticks.git

Then, get into the folder and install the dependencies using yarn:

 cd chopsticks && yarn

Finally, build the project:

yarn build-wasm

Now the development environment is ready to start testing and debugging Tanssi-deployed appchains.

Forking a Demo EVM Appchain with Chopsticks

To fork a Tanssi appchain using Chopsticks, execute the command with only the RPC endpoint as a parameter:

yarn start --endpoint wss://fraa-dancebox-3001-rpc.a.dancebox.tanssi.network

This command will start a local clone of the chain as it was in the latest block.

chopsticks % yarn start --endpoint wss://fraa-dancebox-3001-rpc.a.dancebox.tanssi.network [01:59:42.628] INFO (xcm/59650): Frontier Container 3001 RPC listening on port 8000

Typically, the configuration parameters are stored in a configuration file, as are the configurations in the repository's configs folder for the relay chains and parachains deployed in the Dotsama ecosystem. The following configuration file works for the demo EVM appchain, overriding the chain's sudo account with Alith's and additionally funding the account with tokens:

endpoint: wss://fraa-dancebox-3001-rpc.a.dancebox.tanssi.network
mock-signature-host: true
allow-unresolved-imports: true
db: ./tmp/db_ftrcon.sqlite

import-storage:
  System:
    Account:
      - - - "0xf24FF3a9CF04c71Dbc94D0b566f7A27B94566cac" # Alith
        - providers: 1
          sufficients: 1
          consumers: 1
          data:
            free: "100000000000000000000000"
  Sudo:
    Key: "0xf24FF3a9CF04c71Dbc94D0b566f7A27B94566cac"

The configuration file accepts all of the following parameters:

Option Description
genesis The link to a parachain's raw genesis file to build the fork from, instead of an endpoint.
timestamp Timestamp of the block to fork from.
endpoint The endpoint of the parachain to fork.
block Use to specify at which block hash or number to replay the fork.
wasm-override Path of the Wasm to use as the parachain runtime instead of an endpoint's runtime.
db Path to the name of the file that stores or will store the parachain's database.
config Path or URL of the config file.
port The port to expose an endpoint on.
build-block-mode How blocks should be built in the fork: batch, manual, instant.
import-storage A pre-defined JSON/YAML storage file path to override in the parachain's storage.
allow-unresolved-imports Whether to allow Wasm unresolved imports when using a Wasm to build the parachain.
html Include to generate storage diff preview between blocks.
mock-signature-host Mock signature host so that any signature starts with 0xdeadbeef and filled by 0xcd is considered valid.

You can run the command yarn start to fork chains by specifying a local configuration file. Alternatively, the name or the GitHub URL can be used if the chain is listed in the repository's configs folder.

yarn start --config=configs/polkadot.yml
yarn start --config=polkadot
yarn start \
--config=https://github.com/AcalaNetwork/chopsticks.git/master/configs/polkadot.yml

All settings (except genesis and timestamp) can also be passed as flags to configure the environment completely in the command line. For example, the following command forks the demo EVM appchain at block 100.

yarn start --endpoint wss://fraa-dancebox-3001-rpc.a.dancebox.tanssi.network --block 100

Interacting with a Fork

When running a fork, by default, it will be accessible at:

ws://localhost:8000

You can interact with the parachain via libraries such as Polkadot.js and its user interface, Polkadot.js Apps.

Polkadot Js

You should now be able to interact with the forked chain as you would with the real one.

Note

If your browser cannot connect to the WebSocket endpoint provided by Chopsticks, you might need to allow insecure connections for the Polkadot.js Apps URL. Another solution is to run the Docker version of Polkadot.js Apps.

Replaying Blocks

If you would like to replay a block and retrieve its information to dissect the effects of an extrinsic, you can use the yarn start run-block command. Its following flags are:

Flag Description
endpoint The endpoint of the parachain to fork.
block Use to specify at which block hash or number to replay the fork.
wasm-override Path of the Wasm to use as the parachain runtime instead of an endpoint's runtime.
db Path to the name of the file that stores or will store the parachain's database.
config Path or URL of the config file.
output-path=/[file_path] Use to print out results to a JSON file instead of printing it out in the console.
html Include to generate an HTML representation of the storage diff preview between blocks.
open Whether to open the HTML representation.

For example, running the following command will re-run the demo EVM appchains's block 1000 and write the storage diff and other data in a chain-output.json file:

yarn start run-block  \
--endpoint wss://fraa-dancebox-3001-rpc.a.dancebox.tanssi.network  \
--output-path=./chain-output.json  \
--block 1000

WebSocket Commands

Chopstick's internal WebSocket server has special endpoints that allow the manipulation of the local Substrate chain.

These are the methods that can be invoked and their parameters:

dev_newBlock (options) — Generates one or more new blocks
  • options - { "to": number, "count": number } - a JSON object where "to" will create blocks up to a certain value, and "count" will increase by a certain number of blocks. Use only one entry at a time within the JSON object
import { WsProvider } from '@polkadot/api'
const ws = new WsProvider(`ws://localhost:8000`)
// Creates five new blocks
await ws.send('dev_newBlock', [{ count: 5 }])
dev_setStorage (values, blockHash) — Creates or overwrites the value of any storage
  • values - Object - a JSON object resembling the path to a storage value, similar to what you would retrieve via Polkadot.js
  • blockHash - String - optional, the block hash at which the storage value is changed
import { WsProvider } from '@polkadot/api';
const ws = new WsProvider(`ws://localhost:8000`);
// Overwrites the sudo key
await ws.send('dev_setStorage', 
    [{"Sudo": { "Key": "0x6Be02d1d3665660d22FF9624b7BE0551ee1Ac91b" }}]
);
dev_timeTravel (date) — Sets the timestamp of the block to the date value
  • date - Date - a string compatible with the JavaScript Date library that will change the timestamp at which the next blocks being created will be. All future blocks will be sequentially created after that point in time
import { WsProvider } from '@polkadot/api';
const ws = new WsProvider(`ws://localhost:8000`);
// Sets the timestamp of the block to 15th August 2030
await ws.send('dev_timeTravel', ["2030-08-15T00:00:00"]);
dev_setHead (hashOrNumber) — Sets the head of the blockchain to a specific hash or number
  • hashOrNumber - number | string - if found, the chain head will be set to the block with the block number or block hash of this value
import { WsProvider } from '@polkadot/api';
const ws = new WsProvider(`ws://localhost:8000`);
// Sets the head to block number 500
await ws.send('dev_setHead', [500]);
The information presented herein has been provided by third parties and is made available solely for general information purposes. Tanssi does not endorse any project listed and described on the Tanssi Doc Website (https://docs.tanssi.network/). Tanssi Foundation does not warrant the accuracy, completeness or usefulness of this information. Any reliance you place on such information is strictly at your own risk. Tanssi Foundation disclaims all liability and responsibility arising from any reliance placed on this information by you or by anyone who may be informed of any of its contents. All statements and/or opinions expressed in these materials are solely the responsibility of the person or entity providing those materials and do not necessarily represent the opinion of Tanssi Foundation. The information should not be construed as professional or financial advice of any kind. Advice from a suitably qualified professional should always be sought in relation to any particular matter or circumstance. The information herein may link to or integrate with other websites operated or content provided by third parties, and such other websites may link to this website. Tanssi Foundation has no control over any such other websites or their content and will have no liability arising out of or related to such websites or their content. The existence of any such link does not constitute an endorsement of such websites, the content of the websites, or the operators of the websites. These links are being provided to you only as a convenience and you release and hold Tanssi Foundation harmless from any and all liability arising from your use of this information or the information provided by any third-party website or service.
Last update: May 10, 2024
| Created: January 23, 2024