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
51 changes: 51 additions & 0 deletions .github/workflows/hive.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
name: Hive

# Runs on manual dispatch, and on pull requests only when they carry the
# `run-hive` label (added on label, and re-run on subsequent pushes) so the slow
# suite doesn't run on every PR push.
Comment on lines +3 to +5

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

probably fine to run this on every PR, because if it isn't running automatically, then probably no one will run these

on:
workflow_dispatch:
pull_request:
types: [labeled, synchronize]

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

jobs:
hive:
name: Run hive tests
runs-on: ubuntu-latest
# Skip on PRs unless the `run-hive` label is present; always run on dispatch.
if: >-
github.event_name != 'pull_request' ||
contains(github.event.pull_request.labels.*.name, 'run-hive')
# hive itself imposes no timeout; cap the job so a hang can't run forever.
timeout-minutes: 180
env:
# `docker-local` -> `cross` bind-mounts this into the build container.
LEAN_REPO_ROOT: ${{ github.workspace }}
steps:
- name: Checkout repository
uses: actions/checkout@v6
with:
submodules: recursive

# Needed to build the hive binary (`go build .`).
- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: stable
cache: false

# Needed by `docker-local` to cross-build the x86_64 client binary.
- name: Install cross
run: cargo install cross --git https://github.com/cross-rs/cross --rev 7b24b6e9f6834a3ac31d3dad1e2ff24c1b66f7cf

# hive launches client containers; restart docker to settle iptables
# rules on the runner (same workaround the zeam hive workflow uses).
- name: Restart docker
run: sudo systemctl restart docker

- name: Run hive tests
run: make test-hive
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ lean_client/target/*
lean_client/tests/mainnet
lean_client/bin
lean_client/spec/
lean_client/hive/
target/*
*.local*

Expand Down
4 changes: 4 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -32,3 +32,7 @@ docker-local:
.PHONY: release
release:
$(MAKE) -C lean_client release

.PHONY: test-hive
test-hive:
$(MAKE) -C lean_client test-hive
24 changes: 24 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,3 +71,27 @@ leanEthereum Consensus Client written in Rust using Grandine's libraries.
```

After a minute all the nodes should be synced up and see each other

## Running Hive tests

Runs the [Hive](https://github.com/ethereum/hive) lean simulator against our
`grandine_lean` client. From the repo root:

```bash
make test-hive
```

Requires a **Go toolchain**, **Docker** (running, usable without `sudo`), and
**Rust + [`cross`](https://github.com/cross-rs/cross)**.

Pin a hive version (defaults to latest `master`):

```bash
make test-hive HIVE_VERSION=<full-commit-hash>
```

Remove the hive clone and other build artifacts:

```bash
make clean
```
77 changes: 75 additions & 2 deletions lean_client/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -81,18 +81,23 @@ build:
clean:
cargo clean
rm -rf ./bin
rm -rf ./hive

CLIENT_SOURCES := $(shell find . \( -name '*.rs' -o -name 'Cargo.toml' \) \
-not -path './target/*' -not -path './hive/*' -not -path './spec/*' \
-not -path './bin/*') Cargo.lock
Comment on lines +86 to +88

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Claude said:

One thing worth knowing: -not -path filters results but doesn't prune traversal, so find still walks all of ./target/, which can be slow on a large build dir. -path './target/*' -prune -o ... -print avoids that.

Don't know if that's true, but probably still worth looking - target directory can indeed be large and slow down source file discovery.


.PHONY: x86_64-unknown-linux-gnu
x86_64-unknown-linux-gnu: ./target/x86_64-unknown-linux-gnu/release/lean_client

./target/x86_64-unknown-linux-gnu/release/lean_client:
./target/x86_64-unknown-linux-gnu/release/lean_client: $(CLIENT_SOURCES)
CARGO_TARGET_X86_64_UNKNOWN_LINUX_GNU_RUSTFLAGS="-C target-cpu=x86-64-v3" \
LEAN_REPO_ROOT=$(LEAN_REPO_ROOT) cross build --bin lean_client --target x86_64-unknown-linux-gnu --profile release

.PHONY: aarch64-unknown-linux-gnu
aarch64-unknown-linux-gnu: ./target/aarch64-unknown-linux-gnu/release/lean_client

./target/aarch64-unknown-linux-gnu/release/lean_client:
./target/aarch64-unknown-linux-gnu/release/lean_client: $(CLIENT_SOURCES)
LEAN_REPO_ROOT=$(LEAN_REPO_ROOT) cross build --bin lean_client --target aarch64-unknown-linux-gnu --profile release

.PHONY: release
Expand Down Expand Up @@ -126,6 +131,74 @@ docker-local: ./target/x86_64-unknown-linux-gnu/release/lean_client
$(DOCKER_TAGS) \
.

### Hive
# ethereum/hive ref to build. Unset (default) => latest master, resolved at
# clone time. Override with `make test-hive HIVE_VERSION=<commit>` to pin.
HIVE_VERSION ?=
HIVE_REF := $(or $(HIVE_VERSION),master)
Comment on lines +134 to +138

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably would be better to put variables on top of the file, next to all other variables - this way it becomes a bit more obvious how we can parametrize our make runs.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

also, probably no need to have 2 variables here - both HIVE_VERSION and HIVE_REF? If you want to set default version, then you can just do:

HIVE_VERSION ?= master

?= already means "assign if unset".


.PHONY: test-hive
test-hive: hive/hive docker-local
@cd hive && \
./hive --sim lean \
--client-file simulators/lean/clients/devnet5.yaml \
--client grandine_lean_devnet5 \
--docker.output \
--docker.nocache="hive/clients/grandine_lean_devnet5" \
--results-root ./workspace/logs; \
Comment on lines +144 to +148

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not exactly sure, but I think we should be able to parametrize the devnet5 part

hive_status=$$?; \
logs=./workspace/logs; \
suites=$$(ls $$logs/*.json 2>/dev/null | grep -v '/hive\.json$$' || true); \
if [ -z "$$suites" ]; then \
echo "ERROR: hive produced no suite results - treating as an infrastructure/script failure."; \
exit $$hive_status; \
fi; \
if ! command -v jq >/dev/null 2>&1; then \
echo "jq not found; skipping summary. Raw results under $$logs"; \
exit 0; \
fi; \
summary=$$( \
echo "==================== Hive test summary ===================="; \
total=0; failed_total=0; \
for f in $$suites; do \
name=$$(jq -r '.name' "$$f"); \
n=$$(jq '.testCases | length' "$$f"); \
nf=$$(jq '[.testCases[] | select(.summaryResult.pass | not)] | length' "$$f"); \
total=$$((total + n)); failed_total=$$((failed_total + nf)); \
if [ "$$nf" -eq 0 ]; then \
printf '%s: %d/%d passed\n' "$$name" "$$n" "$$n"; \
else \
printf '%s: %d/%d passed (%d failed)\n' "$$name" "$$((n - nf))" "$$n" "$$nf"; \
jq -r '.testCases[] | select(.summaryResult.pass | not) | " FAIL: \(.name)"' "$$f"; \
fi; \
done; \
echo "-----------------------------------------------------------"; \
printf 'Total: %d/%d passed, %d failed\n' "$$((total - failed_total))" "$$total" "$$failed_total"; \
echo "Full failure details: lean_client/hive/workspace/logs/details/"; \
echo "===========================================================" \
); \
echo; \
printf '%s\n' "$$summary"; \
if [ -n "$$GITHUB_STEP_SUMMARY" ]; then \
{ echo '```'; printf '%s\n' "$$summary"; echo '```'; } >> "$$GITHUB_STEP_SUMMARY"; \
fi

hive/hive: hive/.hive-ref-$(HIVE_REF)
@echo "==> Building hive binary (go build)..."
@cd hive && go build .
@echo "==> Built hive binary at hive/hive ($$(cd hive && git rev-parse --short HEAD))"

hive/.hive-ref-$(HIVE_REF):
@echo "==> Fetching ethereum/hive at ref '$(HIVE_REF)'..."
@rm -rf hive
@mkdir -p hive
@cd hive && git init -q && \
git remote add origin https://github.com/ethereum/hive.git && \
git fetch --depth 1 -q origin $(HIVE_REF) && \
git switch -q --detach FETCH_HEAD
@echo "==> Checked out hive at $$(cd hive && git rev-parse --short HEAD)"
@touch $@

### Shadow-simulator support
# `rust/patch/quinn-udp` is a vendored fallback-only build of quinn-udp so QUIC
# runs under the Shadow simulator (which does not emulate sendmsg cmsg / GRO /
Expand Down
Loading