Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions .env
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,15 @@ CHAIN_ID=714
KEYPASS="0123456789"
INIT_HOLDER="0x04d63aBCd2b9b1baa327f2Dda0f873F197ccd186"
# INIT_HOLDER_PRV="59ba8068eb256d520179e903f43dacf6d8d57d72bd306e1bd603fdb8c8da10e8"
RPC_URL="http://127.0.0.1:8545"
RPC_URL="http://bsc-node-0:8545"
GENESIS_COMMIT="34618f607f8356cf147dde6a69fae150bd53d5bf" # fermi commit
PASSED_FORK_DELAY=40
LAST_FORK_MORE_DELAY=10
PASSED_FORK_DELAY=-100000000
LAST_FORK_MORE_DELAY=0
FullImmutabilityThreshold=2048
MinBlocksForBlobRequests=576
DefaultExtraReserveForBlobRequests=32
BreatheBlockInterval=1200
useLatestBscClient=false
useLatestBscClient=true
EnableSentryNode=false
EnableFullNode=false
RegisterNodeID=false
Expand Down
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,6 @@

.idea/
lib/
bsc/
docker-compose.cluster.yml
.env.cluster
81 changes: 81 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
# Multi-stage Dockerfile for BSC Node
# Stage 1: Build Environment with all required tools
# We use Python 3.12 as the base to fulfill the requirement, then add Go 1.24
FROM python:3.12-bookworm AS build-env

# Arguments for versions
ARG NODE_VERSION=16.x
ARG GO_VERSION=1.24.0

# Install Go 1.24 (Detect architecture to support both x86_64 and arm64)
RUN ARCH=$(uname -m) && \
if [ "$ARCH" = "x86_64" ]; then GO_ARCH="amd64"; else GO_ARCH="arm64"; fi && \
curl -fsSL https://go.dev/dl/go${GO_VERSION}.linux-${GO_ARCH}.tar.gz | tar -C /usr/local -xz
ENV PATH="/usr/local/go/bin:$PATH"

# Install basic dependencies
RUN apt-get update && apt-get install -y \
curl \
git \
make \
jq \
build-essential \
software-properties-common \
&& rm -rf /var/lib/apt/lists/*

# Install Node.js (README mentions v16.15.0)
RUN curl -fsSL https://deb.nodesource.com/setup_${NODE_VERSION} | bash - && \
apt-get install -y nodejs && \
npm install -g npm@6.14.6

# Install Poetry using its official installer
# (Python 3.12 is already the system default in this image)
RUN curl -sSL https://install.python-poetry.org | python3 -
ENV PATH="/root/.local/bin:$PATH"

# Install Foundry (Ethereum development toolkit)
# This is needed because BSC's system contracts (in the genesis/ folder) use 'forge' to compile.
RUN curl -L https://foundry.paradigm.xyz | bash && \
/root/.foundry/bin/foundryup
ENV PATH="/root/.foundry/bin:$PATH"
ENV PATH="/node_deploy/bin:$PATH"

# Setting up the workspace
WORKDIR /node_deploy

# Copy and install Python requirements
# This avoids installing them manually every time you restart the container.
COPY requirements.txt .
RUN pip3 install --no-cache-dir -r requirements.txt

# Build and install the validator tool
# By installing to /usr/local/bin, we ensure the binary is available even if the
# /node_deploy directory is shadowed by a volume mount from the host.
COPY create-validator/ ./create-validator/
RUN cd create-validator && go build -o /usr/local/bin/create-validator

# Copy entrypoint script
COPY entrypoint.sh /usr/local/bin/entrypoint.sh
RUN chmod +x /usr/local/bin/entrypoint.sh

# Tool verification command
# This ensures that when the image is built, all required tools are present and functional.
RUN go version && \
node -v && \
npm -v && \
python3 --version && \
poetry --version && \
forge --version && \
jq --version && \
create-validator --help

# Add init check to .bashrc to warn users when they login
RUN echo 'if [ -f /tmp/cluster_initializing ]; then' >> /root/.bashrc && \
echo ' echo "----------------------------------------------------"' >> /root/.bashrc && \
echo ' echo " WARNING: Cluster is still initializing. Please wait! "' >> /root/.bashrc && \
echo ' echo "----------------------------------------------------"' >> /root/.bashrc && \
echo ' echo ""' >> /root/.bashrc && \
echo 'fi' >> /root/.bashrc

# Default command: show help or just stay open
CMD ["bash"]
45 changes: 45 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
# Makefile for BSC Local Cluster

.PHONY: cluster-up cluster-down cluster-logs cluster-clean cluster-restart

# Default Image to use for bootstrapping
TOOLBOX_IMAGE ?= bsc-toolbox:latest
COMPOSE_FILE := docker-compose.cluster.yml

# Auto initialize and bring up the cluster
cluster-up: check-deps
@echo "[Phase 1] Initializing blockchain data & configs using isolated Toolbox environment..."
docker run --rm -v "$(CURDIR):/node_deploy" -w /node_deploy $(TOOLBOX_IMAGE) bash docker_cluster.sh prepare
@echo ""
@echo "[Phase 2] Data prepared! Starting BSC cluster via Docker Compose..."
docker compose -f "$(COMPOSE_FILE)" up -d
@echo "[Phase 3] Waiting for RPC... then Registering Validators"
@bash docker_cluster.sh wait-rpc
@docker run --network bsc_cluster_network --rm -v "$(CURDIR):/node_deploy" -w /node_deploy $(TOOLBOX_IMAGE) bash docker_cluster.sh register
@echo "BSC Local Cluster successfully started in background! Run 'make cluster-logs' to view live logs."

# Safely stop and remove all containers
cluster-down:
@echo "Stopping and removing all BSC containers..."
if [ -f "$(COMPOSE_FILE)" ]; then docker compose -f "$(COMPOSE_FILE)" down; fi

# View real-time logs for all cluster nodes
cluster-logs:
if [ -f "$(COMPOSE_FILE)" ]; then docker compose -f "$(COMPOSE_FILE)" logs -f; fi

# Completely wipe cluster data and auto-generated configs (DANGEROUS)
cluster-clean: cluster-down
@echo "Wiping all local cluster data and temporary configurations (.local/, YAML, .env)..."
rm -rf "$(CURDIR)/.local"
rm -f "$(CURDIR)/.env.cluster" "$(COMPOSE_FILE)"
@echo "Workspace is completely clean."

# Fast restart without wiping data or rebuilding config
cluster-restart: cluster-down
@echo "Restarting all BSC containers with existing config (Phase 2 only)..."
if [ -f "$(COMPOSE_FILE)" ]; then docker compose -f "$(COMPOSE_FILE)" up -d; fi
@echo "BSC Local Cluster successfully restarted."

# Ensure host has curl for wait-rpc (Phase 3)
check-deps:
@command -v curl >/dev/null 2>&1 || (echo "ERROR: 'curl' not found on host. It is required for Phase 3!" && exit 1)
85 changes: 84 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@

## Installation
Before proceeding to the next steps, please ensure that the following packages and softwares are well installed in your local machine:

> [!TIP]
> **Don't want to install these manually?** You can skip to the [Docker Version](#docker-version-recommended) section at the bottom of this file.

- nodejs: v16.15.0
- npm: 6.14.6
- go: 1.24+
Expand Down Expand Up @@ -87,4 +91,83 @@ go build
cd txblob
go build
./txblob
```
```

## Docker Version (Recommended)

To run a fully containerized, isolated local BSC cluster without installing dependencies on your host machine, use the provided `Makefile` which handles the 2-phase orchestration automatically.

### Architecture Workflow

```mermaid
sequenceDiagram
participant User
participant Makefile
participant Toolbox as Toolbox (Docker)
participant HostFS as Host FileSystem
participant Compose as Docker Compose
participant Docker as Docker Engine

User->>Makefile: make cluster-up

Note over Makefile,Toolbox: Phase 1: Initialization (prepare)
Makefile->>Toolbox: Start disposable 'bsc-toolbox' container and execute script

Toolbox->>HostFS: Compile and save 'geth' binary
Toolbox->>HostFS: Generate genesis, keystores, config.toml (.local/)
Toolbox->>HostFS: Generate .env.cluster (cluster params, node count)
Toolbox->>HostFS: Generate docker-compose.cluster.yml (based on env)

Toolbox-->>Makefile: Exit (container removed)

Note over Makefile,Compose: Phase 2: Start Cluster (up)
Makefile->>Compose: docker compose -f docker-compose.cluster.yml up -d

Compose->>HostFS: Read docker-compose.cluster.yml
Compose->>HostFS: Load .env.cluster (env injection)

Compose->>Docker: Create & start N bsc-node-X containers

Docker->>HostFS: Mount volumes (./ -> /node_deploy)

Docker->>Docker: Run node_entrypoint.sh inside each container
Docker->>HostFS: Containers read config.toml / genesis / keystore

Docker-->>User: Cluster running (N nodes)

Note over Makefile,Toolbox: Phase 3: Validator Registration (register)
Makefile->>Makefile: Wait for RPC (localhost:8545 ready)
Makefile->>Toolbox: Start new Toolbox container inside 'bsc_cluster_network'
Toolbox->>HostFS: Load .env (get RPC_URL)
Toolbox->>Docker: Send 'Register' Transactions (via RPC to Node 0)
Toolbox-->>Makefile: Exit (registration tasks submitted)

Note over User,Docker: Local BSC Cluster active with registered validators
```

### Quick Commands

- **`make cluster-up`**: One-click start. It runs the initialization phase, starts the isolated nodes via Docker Compose, and then automatically handles validator registration on StakeHub.
- **`make cluster-down`**: Safely stop all running nodes.
- **`make cluster-logs`**: Stream aggregated, color-coded logs from all running nodes.
- **`make cluster-restart`**: Fast restart the cluster (nodes only). Use this if you manually modified `.local/nodeX/config.toml` and want to apply changes without wiping the blockchain data.
- **`make cluster-clean`**: **WARNING**. Wipes all generated data (`.local/`), genesis files, and temporary yaml configs. Use this to reset the chain back to block zero.

### Node Ports Mapping

Each node runs identically on port `8545` internally. Host mapping is structured sequentially:

| Node | RPC (HTTP/WS) | Metrics (Prometheus) | pprof (Debug) | P2P (TCP/UDP) |
| :--- | :--- | :--- | :--- | :--- |
| **Node 0** | 8545 | 6060 | 7060 | 30311 |
| **Node 1** | 8547 | 6062 | 7062 | 30312 |
| **Node 2** | 8549 | 6064 | 7064 | 30313 |
| **Node 3** | 8551 | 6066 | 7066 | 30314 |

For example, to check the block height of Node 1:
`curl -H "Content-Type: application/json" -X POST --data '{"jsonrpc":"2.0","method":"eth_blockNumber","params":[],"id":1}' http://127.0.0.1:8547`

### Logging

By default, nodes output all their logs directly to the Docker logging driver (STDOUT). You can view them using:
`docker logs -f bsc-node-0`
Loading