Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
65 commits
Select commit Hold shift + click to select a range
3fce9f3
chore: move rabby under deps/rabby
Karrq Nov 26, 2025
de3bdbd
feat(deps): fetch external deps
Karrq Nov 26, 2025
61ad03c
refactor: based/docker
Karrq Nov 26, 2025
417f80a
fix(metrics-exporter): remove reth reference
Karrq Nov 26, 2025
2518ffd
feat(docs): Justfile
Karrq Nov 27, 2025
cac8547
feat(gateway): justfile
Karrq Nov 27, 2025
b443674
refactor: avoid import, invoke instead
Karrq Nov 27, 2025
8d58c97
feat: main node cfg
Karrq Nov 27, 2025
f2daee2
feat: deploy.just
Karrq Nov 28, 2025
d508aab
chore: rename task
Karrq Nov 28, 2025
6c12916
fix(main-node): typos
Karrq Nov 30, 2025
31e2bee
feat: logs
Karrq Nov 30, 2025
17302d1
feat(just): tests
Karrq Dec 1, 2025
d07d392
chore: restore rabby at ./rabby
Karrq Dec 1, 2025
0262ea5
fix: gateway -> follower-node
Karrq Dec 1, 2025
4cb46fb
feat: remaining tests
Karrq Dec 1, 2025
efeeac7
docs: update README
Karrq Dec 1, 2025
641c6df
Merge remote-tracking branch 'origin/develop' into refactor/devex
Karrq Dec 1, 2025
f4151d4
fix: deploy-chain
Karrq Dec 2, 2025
7bce162
fix: logs
Karrq Dec 2, 2025
346ce4b
fix: register-gateway
Karrq Dec 2, 2025
9095c4a
fix(test): continue lines
Karrq Dec 2, 2025
288d604
fix: deploy-chain populate-intent call
Karrq Dec 3, 2025
f51a4f5
fix: PR review
Karrq Dec 3, 2025
23c83c2
refactor: deps module as invocation
Karrq Dec 3, 2025
dcaafa0
fix: _populate-intent location
Karrq Dec 3, 2025
281d109
working reset-and-start-full-stack-local
BrycePy Dec 3, 2025
0465f28
fix
BrycePy Dec 3, 2025
79cfb91
increase overseer start delay
BrycePy Dec 3, 2025
f8dfea3
update example port
BrycePy Dec 3, 2025
a97d86c
feat: wallet backup
Karrq Dec 3, 2025
047e831
fix: wallet backup
Karrq Dec 3, 2025
1bade95
fix: wallet typo
Karrq Dec 3, 2025
d9d7794
feat: reset follower/main node
Karrq Dec 3, 2025
dd3bf87
feat: ci script & deployed chain assets
Karrq Dec 4, 2025
68e952e
feat(script): peering
Karrq Dec 4, 2025
9342fd7
fix + peering
BrycePy Dec 4, 2025
71441c6
fix(just): peering
Karrq Dec 4, 2025
a5000bf
feat: ci script from main justfile
Karrq Dec 4, 2025
ba0cf45
fix: peering force local enode
Karrq Dec 5, 2025
fd626fd
feat: .env.example
Karrq Dec 5, 2025
a159d78
fix: local address for multiaddress
Karrq Dec 8, 2025
c233e68
fix(make): DisputeGameFactoryProxy
Karrq Dec 8, 2025
84a8754
feat(compose): prod/dev setup
Karrq Dec 8, 2025
b166d39
feat(ci): integration test
Karrq Dec 8, 2025
16b25d6
fix(ci): export correct image
Karrq Dec 9, 2025
d56e492
feat: parallel build
Karrq Dec 9, 2025
acd4c22
fix(dev): container-name
Karrq Dec 9, 2025
f3b8249
fix(ci): run against develop branch too
Karrq Dec 9, 2025
da232b9
fix: parallel deps build
Karrq Dec 9, 2025
d730c32
fix(ci): checkout repo
Karrq Dec 9, 2025
c975396
fix(ci): use .env.example
Karrq Dec 9, 2025
dcf5bb2
fix(ci): remove keys from .env.example
Karrq Dec 9, 2025
9b77a7e
fix(ci): ensure LOCAL_DATA
Karrq Dec 9, 2025
c8d92fc
fix(ci): upload hidden .local
Karrq Dec 9, 2025
e504978
fix(ci): ignore .local/data
Karrq Dec 9, 2025
d269ad7
fix(ci): ignore config artifact
Karrq Dec 9, 2025
df4feef
fix(ci): BASED_OP_GETH_PORT from .env
Karrq Dec 9, 2025
04f989d
fix(scripts): intent permission
Karrq Dec 9, 2025
ad81b94
feat(ci): upgrade chain config
Karrq Dec 10, 2025
54a07e8
feat(ci): workflow_call only
Karrq Dec 10, 2025
3902554
feat(ci): integration triggers
Karrq Dec 10, 2025
0cb8699
fix(ci): config-with-deploy
Karrq Dec 10, 2025
1ac5f43
feat(ci): layer caching
Karrq Dec 10, 2025
2aaf15e
fix: more robust wallet keys
Karrq Dec 29, 2025
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
5 changes: 5 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
LOCAL_DATA="$PWD/.local"
PUBLIC_IP="127.0.0.1"
BASED_ENV=dev

BASED_OP_GETH_PORT=8645
1 change: 1 addition & 0 deletions .github/assets/wallets/batcher/address
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
0x43d97E13a80444436517C178575D34cB364134F2
1 change: 1 addition & 0 deletions .github/assets/wallets/batcher/key
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
0xd9170dabfdd56a71fe35b3d20ce0d2e560038c2cc4484c1cd6b91ef9ca62025b
1 change: 1 addition & 0 deletions .github/assets/wallets/proposer/address
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
0xc8a32259c26b5bE53C99f62202c664CA7c94fFb1
1 change: 1 addition & 0 deletions .github/assets/wallets/proposer/key
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
0xac7f4cdcdfb1fb4c421a4c572180aac52569bd0a407881e22ba03efd73ca2fd2
1 change: 1 addition & 0 deletions .github/assets/wallets/sequencer/address
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
0x43d97E13a80444436517C178575D34cB364134F2
1 change: 1 addition & 0 deletions .github/assets/wallets/sequencer/key
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
0xd9170dabfdd56a71fe35b3d20ce0d2e560038c2cc4484c1cd6b91ef9ca62025b
92 changes: 92 additions & 0 deletions .github/workflows/integration-trigger.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
on:
workflow_dispatch:
inputs:
pr_number:
description: "PR number to check"
required: true
type: string

issue_comment:
types: [created]

env:
TRIGGER_COMMAND: '/run-integration-tests'

jobs:
# Parse comment and determine if we should run
parse-trigger:
if: |
github.event_name == 'workflow_dispatch' ||
(github.event_name == 'issue_comment' &&
github.event.issue.pull_request)

runs-on: ubuntu-latest
outputs:
should_run: ${{ steps.decision.outputs.should_run }}
sha: ${{ steps.get-ref.outputs.sha }}

steps:
- name: React to comment (if comment trigger)
if: github.event_name == 'issue_comment'
uses: peter-evans/create-or-update-comment@v3
with:
comment-id: ${{ github.event.comment.id }}
reactions: rocket

- name: Determine trigger type and decision
id: decision
run: |
if [[ "${{ github.event_name }}" == "workflow_dispatch" ]]; then
echo "should_run=true" >> $GITHUB_OUTPUT
elif [[ "${{ github.event_name }}" == "issue_comment" ]]; then
if [[ "${{ github.event.comment.body }}" == *"${{ env.TRIGGER_COMMAND }}"* ]]; then
echo "should_run=true" >> $GITHUB_OUTPUT
else
echo "should_run=false" >> $GITHUB_OUTPUT
fi
else
echo "should_run=false" >> $GITHUB_OUTPUT
fi

- name: Get PR reference information
id: get-ref
if: steps.decision.outputs.should_run == 'true'
uses: actions/github-script@v7
with:
script: |
let prNumber, sha;

if (context.eventName === 'pull_request') {
// Direct PR event
prNumber = context.payload.pull_request.number;
sha = context.payload.pull_request.head.sha;
} else if (context.eventName === 'workflow_dispatch') {
// Manual dispatch with PR number
prNumber = context.payload.inputs.pr_number;
const { data: pr } = await github.rest.pulls.get({
owner: context.repo.owner,
repo: context.repo.repo,
pull_number: parseInt(prNumber)
});
sha = pr.head.sha;
} else if (context.eventName === 'issue_comment') {
// Comment on PR
prNumber = context.payload.issue.number;
const { data: pr } = await github.rest.pulls.get({
owner: context.repo.owner,
repo: context.repo.repo,
pull_number: prNumber
});
sha = pr.head.sha;
}

core.setOutput('sha', sha);

# Call the reusable workflow
integration-tests:
needs: parse-trigger
if: needs.parse-trigger.outputs.should_run == 'true'
uses: ./.github/workflows/integration.yml
with:
sha: ${{ needs.parse-trigger.outputs.sha }}

110 changes: 110 additions & 0 deletions .github/workflows/integration.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
name: Project integration tests

on:
workflow_call:
inputs:
sha:
description: "git sha to checkout"
required: true
type: string

concurrency:
group: ${{ github.workflow }}-${{ github.head_ref || github.ref }}
cancel-in-progress: true

env:
BASED_ENV: dev
PORTAL_TIMEOUT: 180
STARTUP_DELAY: 15
GITHUB_REPOSITORY: ${{ github.repository }}

jobs:
# Build images and publish as artifacts
build:
name: Build images
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
ref: ${{ inputs.sha }}
fetch-depth: 0

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2

- name: Log in to Container Registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

- uses: taiki-e/install-action@just

- name: Build Docker images
run: |
just ci build

- name: Save Docker images to tarballs
run: |
mkdir -p artifacts
just ci export-images $(realpath ./artifacts)

- name: Upload images artifacts
uses: actions/upload-artifact@v4
with:
name: based-op-images
path: artifacts

# Use published artifacts and run nodes
test:
name: Configure nodes & run tests
runs-on: ubuntu-latest
needs: build
steps:
- uses: actions/checkout@v4
with:
ref: ${{ inputs.sha }}
fetch-depth: 0

- name: Install Just
uses: taiki-e/install-action@just

- name: Install Foundry
uses: foundry-rs/foundry-toolchain@v1

- name: Download images artifacts
uses: actions/download-artifact@v4
with:
name: based-op-images
path: /tmp/artifacts/images

- name: Load Docker images
run: |
find /tmp/artifacts/images -type f -exec docker load -i {} \;

- name: Prepare configuration
run: |
cp .env.example .env
just ci prepare

# - name: Publish configuration artifact
# uses: actions/upload-artifact@v4
# if: always()
# with:
# name: config
# include-hidden-files: true
# path: |
# .local
# !.local/**/data

- name: Start services and run tests
run: |
just ci run
sleep {{ env.STARTUP_DELAY }}
just ci test

- name: Teardown
if: always()
run: |
just ci stop
6 changes: 5 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -45,4 +45,8 @@ based/temp_registry.json
temp
webcontrol
data
*.py

*.py

/dist
/.local
138 changes: 138 additions & 0 deletions Justfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
set dotenv-load

export LOCAL_DATA := canonicalize(env("LOCAL_DATA", shell('mkdir -p .local && realpath .local')))

# dev = use locally built images
# prod = use releases
export BASED_ENV := env("BASED_ENV", "prod")

self := "just -f " + justfile()
deps := "just -f " + join(justfile_directory(), "deps", "Justfile")

# Verifies that system dependencies are present
@check:
echo "jq: {{require('jq')}}"
echo "docker: {{require('docker')}}"
echo "cast: {{require('cast')}}"
echo "rustup: {{require('rustup')}}"
echo "python: {{require('python')}}"

# Prepare the local environment: fetch deps, build them, setup toolchains...
@prepare:
{{deps}} fetch
cd docs && npm i
cd based && rustup toolchain install

# 🏗️ Build
build:
#!/usr/bin/env bash
set -euo pipefail

{{deps}} build &
just -f based/docker/Justfile all &

wait

# 📚 Build local docs
docs:
just -f docs/Justfile serve

# Build and link rabby in the configured output folder
rabby out="./dist":
just -f deps/rabby.just build
ln -s deps/rabby/dist {{out}}/rabby
ln -s deps/rabby/dist-mv2 {{out}}/rabby-mv2

## Component access (component verb)

# Run recipes from scripts/spamoor.just
spamoor *args=("start ./spamoor-config.yml"):
just -f scripts/spamoor.just {{args}}

# Run recipes from scripts/overseer.just
overseer *args=("start"):
just -f based/overseer.just {{args}}

# Run recipes from based/portal.just
portal *args:
just -f based/portal.just {{args}}

# Run recipes from based/registry.just
registry *args:
just -f based/registry.just {{args}}

# Run recipes from based/main-node.just
main-node *args:
just -f based/main-node.just {{args}}

# Run recipes from based/follower-node.just
follower-node *args:
just -f based/follower-node.just {{args}}

# Run recipes from based/monitoring.just
monitoring *args:
just -f scripts/monitoring.just {{args}}

## Action access (verb component)

# View logs for the given service
logs name:
just -f scripts/logs.just {{name}}

# Start the given service
start name:
{{self}} {{name}} start

# Stop the given service
stop name:
{{self}} {{name}} stop

# Run a test recipe described in scripts/test.just
test name:
just -f scripts/test.just {{name}}

# Cleanup all the local state of the project
reset:
{{self}} main-node reset
{{self}} follower-node reset
rm -rf $LOCAL_DATA

# Run a recipe from scripts/ci.just
ci *args:
just -f scripts/ci.just {{args}}

# TODO: consider some sort of interactive config if needed
quick-start:
{{self}} main-node config-with-deploy
{{self}} main-node start
{{self}} follower-node create-config
{{self}} follower-node start-dev

echo "Waiting for 10 seconds before starting the overseer" && sleep 10
{{self}} overseer start


# Cleanup all local state
reset-and-start-full-stack-local:
#!/usr/bin/env bash
set -euo pipefail

export PUBLIC_IP=127.0.0.1

echo "Ensuring required environment variables are available..."
echo 'OP_BATCHER_KEY={{env("OP_BATCHER_KEY")}}'
echo 'OP_PROPOSER_KEY={{env("OP_PROPOSER_KEY")}}'
echo 'OP_SEQUENCER_KEY={{env("OP_SEQUENCER_KEY")}}'

echo "Resetting configuration and deploying new L2 from scratch"
{{self}} reset || true

{{self}} main-node config-with-deploy
{{self}} main-node start
{{self}} follower-node create-config
{{self}} follower-node start-dev

echo "Waiting for 15 seconds before triggering peering and starting the overseer" && sleep 15

python peering.py
{{self}} start overseer
8 changes: 4 additions & 4 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,9 @@ L2_CHAIN_ID?=$(shell \
L2_CHAIN_ID_HEX:=$(shell printf "0x%064x" $(L2_CHAIN_ID))
PORTAL?=http://0.0.0.0:8080
TXPROXY?=http://0.0.0.0:8090
L1_RPC_URL?=http://3.84.162.42:8545
L1_BEACON_RPC_URL?=http://3.84.162.42:5051
PUBLIC_IP?=$(shell curl ifconfig.me)
L1_RPC_URL?=https://ethereum-sepolia-rpc.publicnode.com
L1_BEACON_RPC_URL?=https://ethereum-sepolia-beacon-api.publicnode.com
PUBLIC_IP?=$(shell curl -4 ifconfig.me)
# if GATEWAY_SEQUENCING_KEY is set, use that one, otherwise key_to_address will generate a new one
GATEWAY_SEQUENCING_KEY ?= $(shell \
[ -f .local_gateway_and_follower/.env ] && \
Expand Down Expand Up @@ -365,7 +365,7 @@ start-main-node: create-network
$(MAKE) fix-compose; \
echo "Initializing all components of a main sequencing node in ./.local_main_node ..."; \
{ \
echo "DISPUTE_GAME_FACTORY_ADDRESS=$$(docker run -v $$(pwd)/.local_main_node/config:/config -i --rm imega/jq -r '.opChainDeployments[0].disputeGameFactoryProxyAddress' /config/state.json)"; \
echo "DISPUTE_GAME_FACTORY_ADDRESS=$$(docker run -v $$(pwd)/.local_main_node/config:/config -i --rm imega/jq -r '.opChainDeployments[0].DisputeGameFactoryProxy' /config/state.json)"; \
echo "NETWORK_ID=$$(docker run -v $$(pwd)/.local_main_node/config:/config -i --rm imega/jq -r '.l2_chain_id' /config/rollup.json)"; \
echo "L1_RPC_URL=$(L1_RPC_URL)"; \
echo "L1_BEACON_RPC_URL=$(L1_BEACON_RPC_URL)"; \
Expand Down
Loading
Loading