Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
ferranbt committed Jul 29, 2024
0 parents commit 234ac27
Show file tree
Hide file tree
Showing 12 changed files with 2,910 additions and 0 deletions.
56 changes: 56 additions & 0 deletions .github/workflows/checks.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
name: Checks

on:
workflow_dispatch:
pull_request:
merge_group:
push:
branches: [main]

jobs:
test:
name: E2E test
runs-on: ubuntu-latest
steps:
- name: Check out code
uses: actions/checkout@v2

- name: Set up Go
uses: actions/setup-go@v2
with:
go-version: 1.22

- name: Run playground
run: go run main.go --output /tmp/playground & > /tmp/playground.log 2>&1

- name: Validate that blocks are created
run: go run main.go validate

- name: Move playground logs
if: ${{ failure() }}
run: mv /tmp/playground.log /tmp/playground/logs

- name: Archive playground logs
uses: actions/upload-artifact@v4
if: ${{ failure() }}
with:
name: playground-logs
path: /tmp/playground/logs
retention-days: 5
artifacts:
name: Artifacts
strategy:
matrix:
os: [ubuntu-latest, macos-13]
runs-on: ${{ matrix.os }}
steps:
- name: Check out code
uses: actions/checkout@v2

- name: Set up Go
uses: actions/setup-go@v2
with:
go-version: 1.22

- name: Download and test artifacts
run: go run main.go download-artifacts --validate
29 changes: 29 additions & 0 deletions .github/workflows/release.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# .github/workflows/release.yml
name: release

on:
workflow_dispatch:
push:
tags:
- "*"

jobs:
release:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0

- name: setup dependencies
uses: actions/setup-go@v2

- name: Log tag name
run: echo "Build for tag ${{ github.ref_name }}"

- name: Create release
run: make ci-release
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
TAG: ${{ github.ref_name }}
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
local-testnet
output
76 changes: 76 additions & 0 deletions .goreleaser.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
env:
- CGO_ENABLED=1
builds:
- id: builder-playground-darwin-amd64
binary: builder-playground
goarch:
- amd64
goos:
- darwin
env:
- CC=o64-clang
- CXX=o64-clang++
flags:
- -trimpath
- id: builder-playground-darwin-arm64
binary: builder-playground
goarch:
- arm64
goos:
- darwin
env:
- CC=oa64-clang
- CXX=oa64-clang++
flags:
- -trimpath
- id: builder-playground-linux-amd64
binary: builder-playground
env:
- CC=x86_64-linux-gnu-gcc
- CXX=x86_64-linux-gnu-g++
goarch:
- amd64
goos:
- linux
flags:
- -trimpath
ldflags:
- -extldflags "-Wl,-z,stack-size=0x800000 --static"
tags:
- netgo
- osusergo
- id: builder-playground-linux-arm64
binary: builder-playground
goarch:
- arm64
goos:
- linux
env:
- CC=aarch64-linux-gnu-gcc
- CXX=aarch64-linux-gnu-g++
flags:
- -trimpath
ldflags:
- -extldflags "-Wl,-z,stack-size=0x800000 --static"
tags:
- netgo
- osusergo

archives:
- id: w/version
builds:
- builder-playground-darwin-amd64
- builder-playground-darwin-arm64
- builder-playground-linux-amd64
- builder-playground-linux-arm64
name_template: "builder-playground_v{{ .Version }}_{{ .Os }}_{{ .Arch }}"
wrap_in_directory: false
format: zip
files:
- none*

checksum:
name_template: "checksums.txt"

release:
draft: true
13 changes: 13 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@

ci-release:
docker run \
--rm \
-e CGO_ENABLED=1 \
-e GITHUB_TOKEN="$(GITHUB_TOKEN)" \
-v /var/run/docker.sock:/var/run/docker.sock \
-v $(HOME)/.docker/config.json:/root/.docker/config.json \
-v `pwd`:/go/src/$(PACKAGE_NAME) \
-v `pwd`/sysroot:/sysroot \
-w /go/src/$(PACKAGE_NAME) \
ghcr.io/goreleaser/goreleaser-cross:v1.21.12 \
release --clean --auto-snapshot
33 changes: 33 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# Builder Playground

The builder playground is a tool to deploy an end-to-end environment to locally test an Ethereum L1 builder. It deploys:

- A beacon node + validator client ([lighthouse](https://github.com/sigp/lighthouse)).
- An execution client ([reth](https://github.com/paradigmxyz/reth)).
- An in-memory [mev-boost-relay](https://github.com/flashbots/mev-boost-relay).

## Usage

Clone the repository and run the following command:

```bash
$ go run main.go
```

The playground performs the following steps:

1. It attempts to download the `lighthouse` and `reth` binaries from the GitHub releases page if they are not found locally.
2. It generates the genesis artifacts for the chain.

- 100 validators with 32 ETH each.
- 10 prefunded accounts with 100 ETH each, generated with the mnemonic `test test test test test test test test test test test junk`.
- It enables the Deneb fork at startup.

3. It deploys the chain services and the relay.

- `Reth` node.
- `Lighthouse` beacon node.
- `Lighthouse` validator client.
- `Mev-boost-relay`.

To stop the playground, press `Ctrl+C`.
173 changes: 173 additions & 0 deletions artifacts/artifacts.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,173 @@
package artifacts

import (
"archive/tar"
"compress/gzip"
"fmt"
"io"
"net/http"
"os"
"os/exec"
"path/filepath"
"runtime"
)

type release struct {
Name string
Org string
Version string
Arch func(string, string) string
}

func DownloadArtifacts() (map[string]string, error) {
var artifacts = []release{
{
Name: "reth",
Org: "paradigmxyz",
Version: "v1.0.2",
Arch: func(goos, goarch string) string {
if goos == "linux" {
return "x86_64-unknown-linux-gnu"
} else if goos == "darwin" && goarch == "arm64" { // Apple M1
return "aarch64-apple-darwin"
} else if goos == "darwin" && goarch == "amd64" {
return "x86_64-apple-darwin"
}
return ""
},
},
{
Name: "lighthouse",
Org: "sigp",
Version: "v5.2.1",
Arch: func(goos, goarch string) string {
if goos == "linux" {
return "x86_64-unknown-linux-gnu"
} else if goos == "darwin" && goarch == "arm64" { // Apple M1
return "x86_64-apple-darwin-portable"
} else if goos == "darwin" && goarch == "amd64" {
return "x86_64-apple-darwin"
}
return ""
},
},
}

homeDir, err := os.UserHomeDir()
if err != nil {
return nil, fmt.Errorf("error getting user home directory: %w", err)
}

// Define the path for our custom home directory
customHomeDir := filepath.Join(homeDir, ".playground")

// Create output directory if it doesn't exist
if err := os.MkdirAll(customHomeDir, 0755); err != nil {
return nil, fmt.Errorf("error creating output directory: %v", err)
}

goos := runtime.GOOS
goarch := runtime.GOARCH

fmt.Printf("Architecture detected: %s/%s\n", goos, goarch)

// Try to download the release binaries for 'reth' and 'lighthouse'. It works as follows:
// 1. Check under $HOME/.playground if the binary-<version> exists. If exists, use it.
// 2. If the binary does not exists, use the arch and os to download the binary from the release page.
// 3. If the architecture is not supported, check if the binary is found in PATH.
releases := make(map[string]string)
for _, artifact := range artifacts {
outPath := filepath.Join(customHomeDir, artifact.Name+"-"+artifact.Version)
_, err := os.Stat(outPath)
if err != nil && !os.IsNotExist(err) {
return nil, fmt.Errorf("error checking file existence: %v", err)
}

if err != nil {
archVersion := artifact.Arch(goos, goarch)
if archVersion == "" {
// Case 2. The architecture is not supported.
fmt.Printf("unsupported OS/Arch: %s/%s\n", goos, goarch)
if _, err := exec.LookPath(artifact.Name); err != nil {
return nil, fmt.Errorf("error looking up binary in PATH: %v", err)
} else {
outPath = artifact.Name
fmt.Printf("Using %s from PATH\n", artifact.Name)
}
} else {
// Case 3. Download the binary from the release page
releasesURL := fmt.Sprintf("https://github.com/%s/%s/releases/download/%s/%s-%s-%s.tar.gz", artifact.Org, artifact.Name, artifact.Version, artifact.Name, artifact.Version, archVersion)
fmt.Printf("Downloading %s: %s\n", outPath, releasesURL)

if err := downloadArtifact(releasesURL, artifact.Name, outPath); err != nil {
return nil, fmt.Errorf("error downloading artifact: %v", err)
}
}
} else {
// Case 1. Use the binary in $HOME/.playground
fmt.Printf("%s already exists, skipping download\n", outPath)
}

releases[artifact.Name] = outPath
}

return releases, nil
}

func downloadArtifact(url string, expectedFile string, outPath string) error {
// Download the file
resp, err := http.Get(url)
if err != nil {
return fmt.Errorf("error downloading file: %v", err)
}
defer resp.Body.Close()

// Create a gzip reader
gzipReader, err := gzip.NewReader(resp.Body)
if err != nil {
return fmt.Errorf("error creating gzip reader: %v", err)
}
defer gzipReader.Close()

// Create a tar reader
tarReader := tar.NewReader(gzipReader)

// Extract the file
var found bool
for {
header, err := tarReader.Next()
if err == io.EOF {
break
}
if err != nil {
return fmt.Errorf("error reading tar: %v", err)
}

if header.Typeflag == tar.TypeReg {
if header.Name != expectedFile {
return fmt.Errorf("unexpected file in archive: %s", header.Name)
}
outFile, err := os.Create(outPath)
if err != nil {
return fmt.Errorf("error creating output file: %v", err)
}
defer outFile.Close()

if _, err := io.Copy(outFile, tarReader); err != nil {
return fmt.Errorf("error writing output file: %v", err)
}

// change permissions
if err := os.Chmod(outPath, 0755); err != nil {
return fmt.Errorf("error changing permissions: %v", err)
}
found = true
break // Assuming there's only one file per repo
}
}

if !found {
return fmt.Errorf("file not found in archive: %s", expectedFile)
}
return nil
}
Loading

0 comments on commit 234ac27

Please sign in to comment.