Repository navigation
chore: Add besu-to-besu spin up script #1334
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
dhfang
merged 15 commits into
main
from
diana/fou-1225-create-script-to-launch-two-besu-chains-locally
Aug 13, 2026
Merged
Changes from all commits
Commits
Show all changes
15 commits
Select commit
Hold shift + click to select a range
56ea92e
Add besu-to-besu spin up script
dianab-cl d59b1b6
Update
dianab-cl 8765d0e
After code review
dianab-cl 3f76b5e
After code reveiw
dianab-cl 1789748
Update
dianab-cl 484bca3
ci: add CodeQL scanning (#1338)
gjermundgaraba 13eeca0
fix(e2e): bound setup transaction mining waits (#1314)
gjermundgaraba d27cc60
feat: intial attempt (#1336)
srdtrk 6a1a9b1
ci: target main after development promotion (#1339)
gjermundgaraba 7c0da14
After code review
dianab-cl b288542
Merge branch 'main' into diana/fou-1225-create-script-to-launch-two-b…
dianab-cl 27d621a
Merge branch 'main' into diana/fou-1225-create-script-to-launch-two-b…
dianab-cl 5aff9c1
Merge branch 'main' into diana/fou-1225-create-script-to-launch-two-b…
dhfang 850750c
print private keys alongside addresses in besu-to-besu setup output
dhfang ef7a547
Merge branch 'main' into diana/fou-1225-create-script-to-launch-two-b…
dhfang File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,90 @@ | ||
| <!-- SPDX-License-Identifier: Apache-2.0 --> | ||
|
|
||
| # besu-to-besu | ||
|
|
||
|
|
||
| Two independent single-validator Besu QBFT chains (A and B), the substrate for a | ||
| single IBC pair. | ||
|
|
||
| ## Prerequisites | ||
|
|
||
| `docker` (with the compose v2 plugin), `curl`, `perl`. | ||
|
|
||
| `cast` (foundry) does the BIP-39 derivation. If it isn't on `PATH`, `cast_cli` | ||
| falls back to running it inside `$FOUNDRY_IMAGE`, so a host install is optional. | ||
|
|
||
| ## Usage | ||
|
|
||
| Run from `examples/besu-to-besu/`: | ||
|
|
||
| ```bash | ||
| ./setup.sh # init + start + wait for RPC (end-to-end) | ||
| ./setup.sh init # derive keys, render configs into chains/local/ (no containers) | ||
| ./setup.sh start # docker compose up both chains, wait for RPC | ||
| ./setup.sh accounts # print the funded addresses and their roles | ||
| ./setup.sh status # RPC endpoints, chain IDs, block heights | ||
| ./setup.sh clean # stop containers, remove volumes and chains/local/ | ||
| ``` | ||
|
|
||
| Verify once the chains are up: | ||
|
|
||
| ```bash | ||
| curl -s -X POST -H 'Content-Type: application/json' \ | ||
| --data '{"jsonrpc":"2.0","method":"eth_chainId","params":[],"id":1}' \ | ||
| http://localhost:8745 # → 0xa02a (= 41002, chain B) | ||
| ``` | ||
|
|
||
| Each invocation writes a timestamped log file to `logs/`. | ||
|
|
||
| ## Chains and accounts | ||
|
|
||
| | Chain | Chain ID | Validator source | Validator (default phrases) | | ||
| |-------|---------:|------------------|-----------------------------| | ||
| | A | 41001 | `A_MNEMONIC` index 1 | `0x0D3eB21b6b21833A4939Cfff4810E9AE0758e12C` | | ||
| | B | 41002 | `B_MNEMONIC` index 1 | `0x45A1eF7572a5B9998b46E54AA5Dce838965acB35` | | ||
|
|
||
| Each chain has its own mnemonic and every account on it derives from that phrase, | ||
| so the two chains share no accounts. `FUNDED_ACCOUNTS` accounts (default 5) are | ||
| derived per chain and funded with 1 000 000 ETH in that chain's genesis and | ||
| nowhere else; index 0 is that chain's deployer, index 1 its validator. Because | ||
| the deployers differ, a contract deployed to both chains will **not** land at the | ||
| same address — `CREATE` derives it from sender and nonce. Set `A_MNEMONIC` and | ||
| `B_MNEMONIC` to the same value if you want shared accounts and matching contract | ||
| addresses. | ||
|
|
||
|
|
||
| ## Ports | ||
|
|
||
| Both containers use the same internal ports (8545 RPC, 8546 WS, 9545 metrics). | ||
| Only the host-side mappings differ: | ||
|
|
||
| | Service | RPC (host) | WS (host) | Metrics (host) | | ||
| |---------|-----------:|----------:|---------------:| | ||
| | besu-a | 8545 | 8546 | 9545 | | ||
| | besu-b | 8745 | 8746 | 9745 | | ||
|
|
||
| Every host mapping binds to `127.0.0.1` — the JSON-RPC endpoints are | ||
| unauthenticated and each node holds the key that signs every block on its chain, | ||
| so they stay off the LAN. Container-to-container traffic goes over the | ||
| `besu-besu-net` compose network and does not depend on these mappings. | ||
|
|
||
| ## Layout | ||
|
|
||
| ``` | ||
| examples/besu-to-besu/ | ||
| ├── README.md | ||
| ├── setup.sh — entrypoint: init | start | accounts | status | clean | ||
| ├── docker-compose.yml — besu-a + besu-b | ||
| ├── lib/ | ||
| │ ├── common.sh — logging, prerequisite checks, RPC waiter, | ||
| │ │ render_template, cast_cli | ||
| │ └── chains.sh — derivation, QBFT extraData, rendering, start / | ||
| │ wait / status / clean | ||
| └── chains/ | ||
| ├── besu.toml.tmpl — rendered once per chain | ||
| ├── el-genesis.json.tmpl — ${CHAIN_ID}, ${QBFT_EXTRADATA}, ${GENESIS_ALLOC} | ||
| └── local/ — generated, gitignored: | ||
| ├── chains.env — addresses, deployer keys, chain IDs, RPC URLs | ||
| ├── A/{besu.toml, el-genesis.json, key} | ||
| └── B/{besu.toml, el-genesis.json, key} | ||
| ``` | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,36 @@ | ||
| # SPDX-License-Identifier: Apache-2.0 | ||
|
|
||
| # Besu execution-layer config for chain ${CHAIN_NAME} (besu-to-besu). | ||
| # Rendered by ./setup.sh init — edit chains/besu.toml.tmpl, not this copy. | ||
| # | ||
| # DEMO KEYS ONLY: the node private key beside this file is derived from a | ||
| # publicly known BIP-39 test vector. Local devnet use only. | ||
| genesis-file = "/evm/el-genesis.json" | ||
| data-path = "/data" | ||
|
|
||
| # QBFT signing key — derived from the demo mnemonic at index ${VALIDATOR_INDEX}, | ||
| # giving ${VALIDATOR_ADDR}: | ||
| # the sole validator encoded in the genesis extraData for chain ${CHAIN_NAME}. | ||
| node-private-key-file = "/evm/key" | ||
|
|
||
| # Networking — single-validator devnet, but p2p must be enabled or QBFT's pivot | ||
| # selector blocks waiting for peers. Discovery off + no bootnodes keeps each | ||
| # chain solo; A and B never gossip with each other. | ||
| p2p-enabled = true | ||
| discovery-enabled = false | ||
| bootnodes = [] | ||
| host-allowlist = ["*"] | ||
|
|
||
| rpc-http-enabled = true | ||
| rpc-http-host = "0.0.0.0" | ||
| rpc-http-port = 8545 | ||
| rpc-http-cors-origins = ["*"] | ||
| rpc-http-api = ["ETH","NET","WEB3","TXPOOL","DEBUG","ADMIN","QBFT"] | ||
|
|
||
| rpc-ws-enabled = true | ||
| rpc-ws-host = "0.0.0.0" | ||
| rpc-ws-port = 8546 | ||
| rpc-ws-api = ["ETH","NET","WEB3","TXPOOL"] | ||
|
|
||
| sync-mode = "FULL" | ||
| sync-min-peers = 0 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,44 @@ | ||
| { | ||
| "config": { | ||
| "chainId": ${CHAIN_ID}, | ||
| "homesteadBlock": 0, | ||
| "eip150Block": 0, | ||
| "eip155Block": 0, | ||
| "eip158Block": 0, | ||
| "byzantiumBlock": 0, | ||
| "constantinopleBlock": 0, | ||
| "petersburgBlock": 0, | ||
| "istanbulBlock": 0, | ||
| "berlinBlock": 0, | ||
| "londonBlock": 0, | ||
| "arrowGlacierBlock": 0, | ||
| "grayGlacierBlock": 0, | ||
| "shanghaiTime": 0, | ||
| "cancunTime": 0, | ||
| "qbft": { | ||
| "blockperiodseconds": ${QBFT_BLOCK_PERIOD_SECONDS}, | ||
| "epochlength": ${QBFT_EPOCH_LENGTH}, | ||
| "requesttimeoutseconds": ${QBFT_REQUEST_TIMEOUT_SECONDS} | ||
| } | ||
| }, | ||
| "nonce": "0x0", | ||
| "timestamp": "0x0", | ||
| "extraData": "${QBFT_EXTRADATA}", | ||
| "gasLimit": "0x1C9C380", | ||
| "difficulty": "0x1", | ||
| "mixHash": "0x63746963616c2062797a616e74696e65206661756c7420746f6c6572616e6365", | ||
| "coinbase": "0x0000000000000000000000000000000000000000", | ||
| "alloc": { | ||
| ${GENESIS_ALLOC} | ||
| "0x000F3df6D732807Ef1319fB7B8bB8522d0Beac02": { | ||
| "comment": "EIP-4788 beacon block root contract (required by Cancun)", | ||
| "balance": "0x0", | ||
| "nonce": "0x1", | ||
| "code": "0x3373fffffffffffffffffffffffffffffffffffffffe14604d57602036146024575f5ffd5b5f35801560495762001fff810690815414603c575f5ffd5b62001fff01545f5260205ff35b5f5ffd5b62001fff42064281555f359062001fff015500" | ||
| } | ||
| }, | ||
| "baseFeePerGas": "0x7", | ||
| "number": "0x0", | ||
| "gasUsed": "0x0", | ||
| "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000" | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,79 @@ | ||
| # SPDX-License-Identifier: Apache-2.0 | ||
|
|
||
| # Two independent single-validator Besu QBFT chains. | ||
| # | ||
| # DEMO KEYS ONLY: the validator keys mounted at /evm are derived from publicly | ||
| # known BIP-39 test vectors. Local devnet use only — never on a public, shared, | ||
| # or production network. | ||
| # | ||
| # Each /evm mount points at chains/local/<chain>/, which ./setup.sh init | ||
| # renders from chains/*.tmpl — besu.toml, el-genesis.json, and the validator | ||
| # key derived from the demo mnemonic. Nothing under chains/local/ is committed, | ||
| # so `docker compose up` without a prior init has no config to mount. | ||
|
|
||
| services: | ||
|
|
||
| # ── Chains ──────────────────────────────────────────────────────────────── | ||
| besu-a: | ||
| image: ${BESU_IMAGE:-hyperledger/besu:25.4.0} | ||
| container_name: besu-a | ||
| command: | ||
| - "--config-file=/evm/besu.toml" | ||
| - "--metrics-enabled" | ||
| - "--metrics-host=0.0.0.0" | ||
| - "--metrics-port=9545" | ||
| - "--Xqbft-enable-early-round-change" | ||
| # Published on the loopback interface only. Without the explicit 127.0.0.1 | ||
| # these bind to 0.0.0.0 and expose an unauthenticated JSON-RPC endpoint — | ||
| # holding keys that can sign as the chain's sole validator — to the whole | ||
| # LAN. Container-to-container traffic goes over besu-besu-net and does not | ||
| # depend on these mappings. | ||
| ports: | ||
| - "127.0.0.1:8545:8545" | ||
| - "127.0.0.1:8546:8546" | ||
| - "127.0.0.1:9545:9545" | ||
| volumes: | ||
| - besu-a-data:/data | ||
| - ./chains/local/A:/evm:ro | ||
| networks: [ besu-besu-net ] | ||
| restart: on-failure | ||
| healthcheck: | ||
| test: [ "CMD", "bash", "-c", "exec 3<>/dev/tcp/localhost/8545" ] | ||
| interval: 5s | ||
| timeout: 3s | ||
| retries: 60 | ||
| start_period: 10s | ||
|
|
||
| besu-b: | ||
| image: ${BESU_IMAGE:-hyperledger/besu:25.4.0} | ||
| container_name: besu-b | ||
| command: | ||
| - "--config-file=/evm/besu.toml" | ||
| - "--metrics-enabled" | ||
| - "--metrics-host=0.0.0.0" | ||
| - "--metrics-port=9545" | ||
| - "--Xqbft-enable-early-round-change" | ||
| ports: # loopback only — see besu-a | ||
| - "127.0.0.1:8745:8545" | ||
| - "127.0.0.1:8746:8546" | ||
| - "127.0.0.1:9745:9545" | ||
| volumes: | ||
| - besu-b-data:/data | ||
| - ./chains/local/B:/evm:ro | ||
| networks: [ besu-besu-net ] | ||
| restart: on-failure | ||
| healthcheck: | ||
| test: [ "CMD", "bash", "-c", "exec 3<>/dev/tcp/localhost/8545" ] | ||
| interval: 5s | ||
| timeout: 3s | ||
| retries: 60 | ||
| start_period: 10s | ||
|
|
||
|
|
||
| volumes: | ||
| besu-a-data: | ||
| besu-b-data: | ||
|
|
||
| networks: | ||
| besu-besu-net: | ||
| driver: bridge |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.