# Chain33: a modular blockchain framework in Go

> Chain33 is a Go blockchain framework organised in layers, with consensus, execution, P2P, RPC, wallet, a plugin manager and a system extension interface as separate directories. It is BSD-3-Clause licensed, released under a 1.x version line with frequent tags, and it is designed for teams that intend to write their own plugins rather than configure an existing chain.

**33cn/chain33** — 高度模块化, 遵循 KISS原则的区块链开发框架

- Repository: https://github.com/33cn/chain33
- Website: https://chain.33.cn
- Stars: 733 · Forks: 257
- Language: Go
- License: BSD-3-Clause
- Published: 2026-10-21 · Updated: 2026-10-21 · Language: en
- Canonical page: https://hysenlabs.com/projects/33cn-chain33

## A framework in layers, from protobuf types to the command line

Chain33 is a highly modular blockchain development framework that follows the KISS principle, and its most useful feature for a reader is the table of layers in the README, because it maps the repository directories onto the architecture.

The lowest layer is protocol and data, with a types/ directory holding protobuf generated type definitions for transactions, blocks and addresses. Above that sits the blockchain core, with blockchain/, store/, mempool/ and account/ covering block synchronisation and indexing, persistent storage, the transaction pool, and accounts with execution accounts. The consensus and execution layer is consensus/ and executor/, where the consensus interface and the transaction execution engine live, with the concrete consensus algorithms under system/consensus/.

The network and communication layer is p2p/, rpc/, queue/ and client/, which covers the P2P network, three sets of RPC in grpc, jsonrpc and ethrpc, and the in-process message queue. The application layer is wallet/ and system/, giving you a wallet with BIP mnemonic support and pluggable system extensions with interfaces and registration points for dapp, address, crypto and store. Infrastructure is common/, util/, pluginmgr/ and metrics/, meaning shared utility libraries, helper components, the plugin manager and monitoring metrics. And cmd/ holds the binary entry points, the chain33 main process, cli, autotest and execblock among them.

That layering is the argument the framework makes. Instead of one blockchain monolith with the consensus baked in, you get interfaces at the boundaries and directories you can replace.

The project is BSD-3-Clause licensed, the default branch is master, the last push was on 2026-10-16, and the release list shows v1.72.5 on 2026-10-08, v1.72.6 on 2026-10-16 and v1.72.7 on 2026-10-16, so the project ships small version increments often.

## The build needs the source at a specific path

Building from source requires Go 1.21 or newer, and the layout of the checkout is not optional. The README is explicit that the code must be placed at $GOPATH/src/github.com/33cn/chain33, otherwise the go package paths will not be found.

```shell
git clone https://github.com/33cn/chain33.git $GOPATH/src/github.com/33cn/chain33
cd $GOPATH/src/github.com/33cn/chain33
make
```

The default make target builds the binary, the cli and the dependencies, and the Makefile turns on module mode by default. The README also notes that users in China need to configure a proxy to fetch dependency packages, with the module function already enabled in the Makefile:

```shell
export GOPROXY=https://mirrors.aliyun.com/goproxy
```

Running the tests is a single target:

```shell
$ make test
```

The Makefile is worth a glance because it shows how many binaries a chain framework produces. There is a chain33 main process built from cmd/chain33, a chain33-cli from cmd/cli, a signatory-server from cmd/signatory-server and miner_accounts from cmd/miner_accounts, plus an autotest binary. The build also copies two configuration files into the build directory, chain33.toml and bityuan.toml, which means the sample configuration ships with the binary.

The version information is stamped at link time. The Makefile derives the version from git describe, falling back to the short commit hash, and passes the commit, the version and the build time into the version package through ldflags. So a binary built from a tagged checkout reports the tag, and one built from a branch reports a commit.

The dependency target is also part of the toolchain story, since it installs golangci-lint, goimports, mockery, shfmt and gosh, and then installs clang-format and shellcheck through apt. A project with linting for Go, shell and protobuf formatting is telling you something about its conventions before you write a line.

## Running a single node, and where the real work goes

To run a single node environment for development and testing, the command is:

```shell
$ chain33 -f chain33.toml
```

That is the whole operational surface for a local chain, and it is deliberately small. The point of a framework like this is that the interesting work is in the modules you write, not in the node startup.

That is what the system/ directory and the plugin library are for. The system/ directory holds the pluggable system extensions with their interfaces and registration points, and the official plugin repository is published separately at the 33cn/plugin repository. A typical case study is linked as well, bityuan, and the bityuan.toml file that the build copies into the build directory is the configuration for that chain.

The build.bat and build.ps1 files at the top level of the repository are for Windows, which tells you that the project expects to be built on more than one platform even though the Go code itself is portable.

The plugin development guidance in the README is short and has one rule that matters. When developing a plugin you must not use the master branch, you must use a release branch, because the master branch is reserved for staying in sync with the upstream project.

The motivation for the whole design is in the project's history section, which points at a story about the framework's origin, and the acknowledgements mention the Tencent Xuanwu security laboratory. The framework is presented as a highly modular design following KISS, and the layered table above is the concrete shape of that claim.

## The dependency list shows what the framework leans on

The go.mod is long and it is the most direct evidence of what Chain33 actually uses underneath, with the module path github.com/33cn/chain33 and Go 1.21.

There is a replace directive that swaps the upstream avalanchego for a fork maintained under the 33cn organisation, github.com/33cn/avalanchego, pinned at a specific pseudo-version. That is a meaningful line in a dependency file, because it means the consensus and node components are maintained in parallel rather than consumed as published.

The rest of the list falls into recognisable groups. For the peer to peer layer there is the libp2p family, go-libp2p, the kad dht, the kbucket, the pubsub and the msgio packages, plus go-multiaddr for addressing and go-log for logging. For storage there is badger as the embedded database and goleveldb as an alternative, with ethereum/go-ethereum and btcd also present. There is influxdb for metrics, go-metrics and prometheus-style instrumentation through rcrowley/go-metrics, and the TOML parser BurntSushi/toml. The command line is cobra, the config is viper, and the error handling is pkg/errors with testify for tests.

Two dependencies stand out for what they imply about the scope. There is a large set of 33cn packages, which are the project own module sub-packages. And there are several p2p-related packages with their own version pins, which tells you the P2P stack is a first class part of the framework rather than a thin wrapper.

The coverage badge in the README reads 65.5 percent, and the note beside it says that this does not include the protobuf generated code, which is a fair exclusion but worth knowing when you read the number.

## The contribution workflow is unusually well scripted

The README spends a long section on the contribution process, and unusually for a project it offers both a detailed version and a simplified one, with the simplified version built on make targets.

The preparation stage forks the repository to your own account, then clones it to the same GOPATH path, and the README gives the clone command as git clone https://github.com/vipwzw/chain33.git $GOPATH/src/github.com/33cn/chain33.

Adding the upstream remote is a make target, and the Makefile has been updated to include it:

```shell
make addupstream
```

Creating a branch is also a make target, with the branch name as a parameter:

```shell
make branch b=mydevbranchname
```

And pushing the finished work takes the branch name and a commit message. The README notes that if the message is not set, the git commit command will not be run, which is a small convenience that avoids a commit with an empty message.

Working on someone else's pull request is also scripted, with a pull target that takes the author name and the branch:

```shell
make pull name=libangzhu b=chain33-p2p-listenPort
```

and a matching pullpush target for pushing the changes back once you have committed locally.

The underlying principle, stated in the detailed section, is that the master branch in your fork is never modified, so that master always stays in sync with upstream/master. All the development happens on side branches that are cut from an up-to-date master, and the sync is done with a fetch, checkout and merge sequence.

## Where Chain33 is the wrong choice

The first wrong case is a team that wants a chain rather than a framework. You get consensus interfaces and an execution engine, and then you choose a consensus algorithm, design your DApp, write the transaction types, and handle the chain's own upgrade path. If your goal is a working chain with tokens and users, an existing implementation with a live network is a different investment.

The second is a project that has standardised on the Ethereum virtual machine. The framework carries ethrpc among its three RPC surfaces and depends on go-ethereum, so an EVM-shaped design is within reach, but the type system, the transaction model and the system extension interfaces are Chain33's own. Porting an Ethereum application to the system/ extension points is a rewrite, not a configuration.

The third is a team that works in a language other than Go. The whole framework, the plugin interface and the tooling are Go, and the plugin manager loads Go plugins. The examples and the make targets assume a Go toolchain, a GOPATH layout and a POSIX shell.

The fourth is a project that cannot accept the GOPATH requirement. The source must live at $GOPATH/src/github.com/33cn/chain33 for the package paths to resolve, and that is a constraint from the era when Go modules were not the default. It is a small annoyance, but it is an annoyance in every CI setup, container image and developer checkout, and it is documented prominently enough that the maintainers clearly consider it fixed rather than permanent.

The alternative worth weighing is writing on top of an existing chain client library, where you get a node implementation, a wallet and an RPC client, and you keep only your smart contract and your application logic. You lose the ability to replace the consensus, the storage and the P2P layer, which is the whole point of Chain33, but you gain a working network and a far smaller surface to maintain.

## Conclusion

Adopt Chain33 if you are building a chain or a subchain and need consensus, execution, RPC and wallet plumbing that you can read and replace module by module, since the whole repository is organised by layer and the plugin and system extension points are first class. Keep away if you want a working chain rather than a framework, because the consensus algorithm, the DApp and the application logic all come from you. Before you build, note that the source must sit under $GOPATH/src/github.com/33cn/chain33 for the Go package paths to resolve, that the go.mod requires Go 1.21 or newer, and that the release line is on 1.72.x with 1.72.7 tagged on 2026-10-16.

## FAQ

### What is Chain33 and what does the modular architecture give you?

It is a Go blockchain development framework organised in layers, with types for protocol data, blockchain, store, mempool and account for the core, consensus and executor for agreement and execution, p2p, rpc, queue and client for networking, wallet and system for the application layer, and common, util, pluginmgr and metrics for infrastructure. Interfaces and registration points at those boundaries are what you replace or extend.

### How do I build Chain33 from source?

You need Go 1.21 or newer, and the source must be at $GOPATH/src/github.com/33cn/chain33 for the package paths to resolve. Then run git clone into that path, cd into it and run make, which builds the chain33 binary, the cli and the dependencies. The test target is make test.

### How do I run a local Chain33 node for development?

Run chain33 -f chain33.toml, which starts a single node environment suitable for development and testing. The build copies chain33.toml and bityuan.toml into the build directory, and the bityuan configuration belongs to the linked typical case study project.

### What are the make targets used for contributing to Chain33?

make addupstream adds the upstream remote, make branch with a b parameter creates a working branch, make push takes the branch name and a commit message, and make pull and make pullpush handle fetching and pushing someone else's pull request branch. The master branch in your fork is never modified so it stays in sync with upstream.

## Sources

- [33cn/chain33 on GitHub](https://github.com/33cn/chain33)
- [License: BSD-3-Clause](https://github.com/33cn/chain33/blob/master/LICENSE)
- [Project website](https://chain.33.cn)
- [README](https://github.com/33cn/chain33/blob/master/README.md)
- [Releases](https://github.com/33cn/chain33/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/33cn-chain33
