Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
6e41571
Initial script to play with celo DB history migration
mcortesi Apr 29, 2024
2677854
Can Read All the headers
mcortesi Apr 29, 2024
cbbc17f
Adds new command to migrate ancients db
mcortesi Apr 30, 2024
da81742
Adds comment
mcortesi Apr 30, 2024
e88665a
Adds extension methods for transformation
mcortesi Apr 30, 2024
f3feeeb
Implements Transform CeloBody
mcortesi Apr 30, 2024
d3aff38
Adds impl that runs steps in a concurrent pipeline
mcortesi Apr 30, 2024
c1b2e7a
Adds transformHead, verify hashing works
mcortesi Apr 30, 2024
c1cca6e
add migration for non-frozen blocks
May 2, 2024
8787ce8
copy over entire db and modify in place, works with op-geth at piersy…
May 3, 2024
3ac4661
remove unecessary copying, cleanup code
May 3, 2024
f004979
close and reopen DBs
May 6, 2024
349aaf1
migrate newdb in place
May 6, 2024
9f841a4
saving progress
May 6, 2024
4ae2e22
Refactor code to improve database migration process
mcortesi May 7, 2024
2df677a
better logging
mcortesi May 7, 2024
f158be8
refactor: inline parMigrateAncientRange
mcortesi May 7, 2024
84d516a
Remove frozen blocks from nonAncient DB
mcortesi May 7, 2024
a48f897
check hash matches on nonAncients migration
mcortesi May 7, 2024
0fecde3
clean up branch
mcortesi May 7, 2024
f1d88a2
decode into new types
May 8, 2024
5c4a1e5
fix transformHeader
mcortesi May 8, 2024
393e96e
make old freezer not readonly so that .meta files are created
May 8, 2024
c6f68f6
add configurable memory limit
May 14, 2024
62b47f3
add comment about memory
May 14, 2024
3601fe6
Added celo-dbmigrate Makefile target
jcortejoso May 15, 2024
44f15c1
Added dockerfile for celo-dbmigrate and celo-migrate tools
jcortejoso May 15, 2024
c861c70
Workflow for running cel2-migration-tool
jcortejoso May 20, 2024
eb4188f
Update cel2-migration-tool image registry
jcortejoso May 20, 2024
caec5c9
update op-geth to point to https://github.com/celo-org/op-geth/commit…
Jun 12, 2024
f72af10
add celo6 logging
Jun 12, 2024
7d222f1
fix lint err, use %w to fmt errors
Jun 13, 2024
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
132 changes: 45 additions & 87 deletions .github/workflows/docker-build-scan.yaml
Original file line number Diff line number Diff line change
@@ -1,92 +1,50 @@
name: Docker Build Scan
on:
pull_request:
branches:
Copy link
Author

Choose a reason for hiding this comment

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

These changes added here c861c70

- "master"
- "celo*"
workflow_dispatch:

jobs:
Build-Scan-Container-op-ufm:
uses: celo-org/reusable-workflows/.github/workflows/container-cicd-local.yaml@v1.11.2
with:
dockerfile: op-ufm/Dockerfile

Build-Scan-Container-ops-bedrock-l1:
uses: celo-org/reusable-workflows/.github/workflows/container-cicd-local.yaml@v1.11.2
with:
dockerfile: ops-bedrock/Dockerfile.l1
context: ops-bedrock

Build-Scan-Container-ops-bedrock-l2:
uses: celo-org/reusable-workflows/.github/workflows/container-cicd-local.yaml@v1.11.2
with:
dockerfile: ops-bedrock/Dockerfile.l2
context: ops-bedrock

Build-Scan-Container-indexer:
uses: celo-org/reusable-workflows/.github/workflows/container-cicd-local.yaml@v1.11.2
with:
dockerfile: indexer/Dockerfile

Build-Scan-Container-op-heartbeat:
uses: celo-org/reusable-workflows/.github/workflows/container-cicd-local.yaml@v1.11.2
with:
dockerfile: op-heartbeat/Dockerfile

Build-Scan-Container-op-exporter:
uses: celo-org/reusable-workflows/.github/workflows/container-cicd-local.yaml@v1.11.2
with:
dockerfile: op-exporter/Dockerfile

Build-Scan-Container-op-program:
uses: celo-org/reusable-workflows/.github/workflows/container-cicd-local.yaml@v1.11.2
with:
dockerfile: op-program/Dockerfile

Build-Scan-Container-ops-bedrock:
uses: celo-org/reusable-workflows/.github/workflows/container-cicd-local.yaml@v1.11.2
with:
dockerfile: ops-bedrock/Dockerfile.stateviz

Build-Scan-Container-ci-builder:
uses: celo-org/reusable-workflows/.github/workflows/container-cicd-local.yaml@v1.11.2
with:
dockerfile: ops/docker/ci-builder/Dockerfile

Build-Scan-Container-proxyd:
uses: celo-org/reusable-workflows/.github/workflows/container-cicd-local.yaml@v1.11.2
with:
dockerfile: proxyd/Dockerfile

Build-Scan-Container-op-node:
uses: celo-org/reusable-workflows/.github/workflows/container-cicd-local.yaml@v1.11.2
with:
dockerfile: op-node/Dockerfile

Build-Scan-Container-op-batcher:
uses: celo-org/reusable-workflows/.github/workflows/container-cicd-local.yaml@v1.11.2
with:
dockerfile: op-batcher/Dockerfile

Build-Scan-Container-indexer-ui:
uses: celo-org/reusable-workflows/.github/workflows/container-cicd-local.yaml@v1.11.2
with:
dockerfile: indexer/ui/Dockerfile

Build-Scan-Container-op-proposer:
uses: celo-org/reusable-workflows/.github/workflows/container-cicd-local.yaml@v1.11.2
with:
dockerfile: op-proposer/Dockerfile

Build-Scan-Container-op-challenger:
uses: celo-org/reusable-workflows/.github/workflows/container-cicd-local.yaml@v1.11.2
with:
dockerfile: op-challenger/Dockerfile

Build-Scan-Container-endpoint-monitor:
uses: celo-org/reusable-workflows/.github/workflows/container-cicd-local.yaml@v1.11.2
with:
dockerfile: endpoint-monitor/Dockerfile

Build-Scan-Container-opwheel:
uses: celo-org/reusable-workflows/.github/workflows/container-cicd-local.yaml@v1.11.2
with:
dockerfile: op-wheel/Dockerfile

detect-files-changed:
runs-on: ubuntu-latest
outputs:
files-changed: ${{ steps.detect-files-changed.outputs.all_changed_files }}
steps:
- uses: actions/checkout@v4
- name: Detect files changed
id: detect-files-changed
uses: tj-actions/changed-files@v44
with:
separator: ','

build-cel2-migration-tool:
runs-on: ubuntu-latest
needs: detect-files-changed
if: |
contains(needs.detect-files-changed.outputs.files-changed, 'op-chain-ops/cmd/celo-dbmigrate') ||
contains(needs.detect-files-changed.outputs.files-changed, 'op-chain-ops/cmd/celo-migrate') ||
contains(needs.detect-files-changed.outputs.files-changed, 'op-chain-ops/Dockerfile')
permissions:
contents: read
id-token: write
security-events: write
steps:
- uses: actions/checkout@v4
- name: Login at GCP Artifact Registry
uses: celo-org/reusable-workflows/.github/actions/auth-gcp-artifact-registry@v2.0
with:
workload-id-provider: 'projects/1094498259535/locations/global/workloadIdentityPools/gh-optimism/providers/github-by-repos'
service-account: 'celo-optimism-gh@devopsre.iam.gserviceaccount.com'
docker-gcp-registries: us-west1-docker.pkg.dev
- name: Build and push container
uses: celo-org/reusable-workflows/.github/actions/build-container@v2.0
with:
platforms: linux/amd64
registry: us-west1-docker.pkg.dev/devopsre/dev-images/cel2-migration-tool
tags: ${{ github.sha }}
context: ./
dockerfile: ./op-chain-ops/Dockerfile
push: true
trivy: false
3 changes: 2 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,8 @@ require (
rsc.io/tmplfunc v0.0.3 // indirect
)

replace github.com/ethereum/go-ethereum => github.com/celo-org/op-geth v0.0.0-20240612131021-96a2a76ceaaa
// replace github.com/ethereum/go-ethereum => github.com/celo-org/op-geth v0.0.0-20240612131021-96a2a76ceaaa
replace github.com/ethereum/go-ethereum => github.com/celo-org/op-geth v0.0.0-20240612164035-ef9b9a19f53e
Copy link

Choose a reason for hiding this comment

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

Note that we'll need to wait for my branch to be merged before you can merge this PR and after my branch has been merged you'll need to update this reference.


//replace github.com/ethereum/go-ethereum v1.13.9 => ../op-geth
Comment on lines +229 to 232
Copy link

Choose a reason for hiding this comment

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

Suggested change
// replace github.com/ethereum/go-ethereum => github.com/celo-org/op-geth v0.0.0-20240612131021-96a2a76ceaaa
replace github.com/ethereum/go-ethereum => github.com/celo-org/op-geth v0.0.0-20240612164035-ef9b9a19f53e
//replace github.com/ethereum/go-ethereum v1.13.9 => ../op-geth
replace github.com/ethereum/go-ethereum => github.com/celo-org/op-geth v0.0.0-20240612164035-ef9b9a19f53e


Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -77,8 +77,8 @@ github.com/btcsuite/snappy-go v1.0.0/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg
github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtEyQwv5/p4Mg4C0fgbePVuGr935/5ddU9Z3TmDRY=
github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs=
github.com/buger/jsonparser v0.0.0-20181115193947-bf1c66bbce23/go.mod h1:bbYlZJ7hK1yFx9hf58LP0zeX7UjIGs20ufpu3evjr+s=
github.com/celo-org/op-geth v0.0.0-20240612131021-96a2a76ceaaa h1:a9OVs0F3EjWwePKDuDUPr0QWe/CWi7uwElH9JzUxq/8=
github.com/celo-org/op-geth v0.0.0-20240612131021-96a2a76ceaaa/go.mod h1:vObZmT4rKd8hjSblIktsJHtLX8SXbCoaIXEd42HMDB0=
github.com/celo-org/op-geth v0.0.0-20240612164035-ef9b9a19f53e h1:7KzqBAm9YmhrdtUG4dssU77za1ytBRuLIoqnzzJoBw8=
github.com/celo-org/op-geth v0.0.0-20240612164035-ef9b9a19f53e/go.mod h1:vObZmT4rKd8hjSblIktsJHtLX8SXbCoaIXEd42HMDB0=
github.com/cespare/cp v0.1.0 h1:SE+dxFebS7Iik5LK0tsi1k9ZCxEaFX4AjQmoyA+1dJk=
github.com/cespare/cp v0.1.0/go.mod h1:SOGHArjBr4JWaSDEVpWpo/hNg6RoKrls6Oh40hiwW+s=
github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko=
Expand Down
30 changes: 30 additions & 0 deletions op-chain-ops/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
FROM golang:1.21.1-alpine3.18 as builder

RUN apk --no-cache add make

COPY ./go.mod /app/go.mod
COPY ./go.sum /app/go.sum

WORKDIR /app

RUN go mod download

COPY ./op-bindings /app/op-bindings
COPY ./op-service /app/op-service
COPY ./op-node /app/op-node
COPY ./op-chain-ops /app/op-chain-ops
WORKDIR /app/op-chain-ops
RUN make celo-dbmigrate celo-migrate

FROM alpine:3.18
RUN apk --no-cache add ca-certificates bash rsync

# RUN addgroup -S app && adduser -S app -G app
# USER app
WORKDIR /app

COPY --from=builder /app/op-chain-ops/bin/celo-dbmigrate /app
COPY --from=builder /app/op-chain-ops/bin/celo-migrate /app
ENV PATH="/app:${PATH}"

ENTRYPOINT ["/app/celo-dbmigrate"]
3 changes: 3 additions & 0 deletions op-chain-ops/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ receipt-reference-builder:
op-upgrade:
go build -o ./bin/op-upgrade ./cmd/op-upgrade/main.go

celo-dbmigrate:
go build -o ./bin/celo-dbmigrate ./cmd/celo-dbmigrate/*.go

celo-migrate:
go build -o ./bin/celo-migrate ./cmd/celo-migrate/*.go

Expand Down
191 changes: 191 additions & 0 deletions op-chain-ops/cmd/celo-dbmigrate/ancients.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,191 @@
package main

import (
"context"
"fmt"
"path/filepath"

"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/log"
"golang.org/x/sync/errgroup"
)

// RLPBlockRange is a range of blocks in RLP format
type RLPBlockRange struct {
start uint64
hashes [][]byte
headers [][]byte
bodies [][]byte
receipts [][]byte
tds [][]byte
}

func migrateAncientsDb(oldDBPath, newDBPath string, batchSize uint64) (uint64, error) {
oldFreezer, err := rawdb.NewChainFreezer(filepath.Join(oldDBPath, "ancient"), "", false) // TODO can't be readonly because we need the .meta files to be created
if err != nil {
return 0, fmt.Errorf("failed to open old freezer: %w", err)
}
defer oldFreezer.Close()

newFreezer, err := rawdb.NewChainFreezer(filepath.Join(newDBPath, "ancient"), "", false)
if err != nil {
return 0, fmt.Errorf("failed to open new freezer: %w", err)
}
defer newFreezer.Close()

numAncientsOld, err := oldFreezer.Ancients()
if err != nil {
return 0, fmt.Errorf("failed to get number of ancients in old freezer: %w", err)
}

numAncientsNew, err := newFreezer.Ancients()
if err != nil {
return 0, fmt.Errorf("failed to get number of ancients in new freezer: %w", err)
}

log.Info("Migration Started", "process", "ancients migration", "startBlock", numAncientsNew, "endBlock", numAncientsOld, "count", numAncientsOld-numAncientsNew+1)
g, ctx := errgroup.WithContext(context.Background())
readChan := make(chan RLPBlockRange, 10)
transformChan := make(chan RLPBlockRange, 10)

log.Info("Migrating data", "start", numAncientsNew, "end", numAncientsOld, "step", batchSize)

g.Go(func() error {
return readAncientBlocks(ctx, oldFreezer, numAncientsNew, numAncientsOld, batchSize, readChan)
})
g.Go(func() error { return transformBlocks(ctx, readChan, transformChan) })
g.Go(func() error { return writeAncientBlocks(ctx, newFreezer, transformChan) })

if err = g.Wait(); err != nil {
return 0, fmt.Errorf("failed to migrate ancients: %w", err)
}

numAncientsNew, err = newFreezer.Ancients()
if err != nil {
return 0, fmt.Errorf("failed to get number of ancients in new freezer: %w", err)
}

log.Info("Migration End", "process", "ancients migration", "totalBlocks", numAncientsNew)
return numAncientsNew, nil
}

func readAncientBlocks(ctx context.Context, freezer *rawdb.Freezer, startBlock, endBlock, batchSize uint64, out chan<- RLPBlockRange) error {
defer close(out)

for i := startBlock; i < endBlock; i += batchSize {
select {
case <-ctx.Done():
return ctx.Err()
default:
count := min(batchSize, endBlock-i+1)
start := i

blockRange := RLPBlockRange{
start: start,
hashes: make([][]byte, count),
headers: make([][]byte, count),
bodies: make([][]byte, count),
receipts: make([][]byte, count),
tds: make([][]byte, count),
}
var err error

blockRange.hashes, err = freezer.AncientRange(rawdb.ChainFreezerHashTable, start, count, 0)
if err != nil {
return fmt.Errorf("failed to read hashes from old freezer: %w", err)
}
blockRange.headers, err = freezer.AncientRange(rawdb.ChainFreezerHeaderTable, start, count, 0)
if err != nil {
return fmt.Errorf("failed to read headers from old freezer: %w", err)
}
blockRange.bodies, err = freezer.AncientRange(rawdb.ChainFreezerBodiesTable, start, count, 0)
if err != nil {
return fmt.Errorf("failed to read bodies from old freezer: %w", err)
}
blockRange.receipts, err = freezer.AncientRange(rawdb.ChainFreezerReceiptTable, start, count, 0)
if err != nil {
return fmt.Errorf("failed to read receipts from old freezer: %w", err)
}
blockRange.tds, err = freezer.AncientRange(rawdb.ChainFreezerDifficultyTable, start, count, 0)
if err != nil {
return fmt.Errorf("failed to read tds from old freezer: %w", err)
}

out <- blockRange
}
}
return nil
}

func transformBlocks(ctx context.Context, in <-chan RLPBlockRange, out chan<- RLPBlockRange) error {
// Transform blocks from the in channel and send them to the out channel
defer close(out)
for blockRange := range in {
select {
case <-ctx.Done():
return ctx.Err()
default:
for i := range blockRange.hashes {
blockNumber := blockRange.start + uint64(i)

newHeader, err := transformHeader(blockRange.headers[i])
if err != nil {
return fmt.Errorf("can't transform header: %w", err)
}
newBody, err := transformBlockBody(blockRange.bodies[i])
if err != nil {
return fmt.Errorf("can't transform body: %w", err)
}

if yes, newHash := hasSameHash(newHeader, blockRange.hashes[i]); !yes {
log.Error("Hash mismatch", "block", blockNumber, "oldHash", common.BytesToHash(blockRange.hashes[i]), "newHash", newHash)
return fmt.Errorf("hash mismatch at block %d", blockNumber)
}

blockRange.headers[i] = newHeader
blockRange.bodies[i] = newBody
}
out <- blockRange
}
}
return nil
}

func writeAncientBlocks(ctx context.Context, freezer *rawdb.Freezer, in <-chan RLPBlockRange) error {
// Write blocks from the in channel to the newDb
for blockRange := range in {
select {
case <-ctx.Done():
return ctx.Err()
default:
_, err := freezer.ModifyAncients(func(aWriter ethdb.AncientWriteOp) error {
for i := range blockRange.hashes {
blockNumber := blockRange.start + uint64(i)
if err := aWriter.AppendRaw(rawdb.ChainFreezerHashTable, blockNumber, blockRange.hashes[i]); err != nil {
return fmt.Errorf("can't write hash to Freezer: %w", err)
}
if err := aWriter.AppendRaw(rawdb.ChainFreezerHeaderTable, blockNumber, blockRange.headers[i]); err != nil {
return fmt.Errorf("can't write header to Freezer: %w", err)
}
if err := aWriter.AppendRaw(rawdb.ChainFreezerBodiesTable, blockNumber, blockRange.bodies[i]); err != nil {
return fmt.Errorf("can't write body to Freezer: %w", err)
}
if err := aWriter.AppendRaw(rawdb.ChainFreezerReceiptTable, blockNumber, blockRange.receipts[i]); err != nil {
return fmt.Errorf("can't write receipts to Freezer: %w", err)
}
if err := aWriter.AppendRaw(rawdb.ChainFreezerDifficultyTable, blockNumber, blockRange.tds[i]); err != nil {
return fmt.Errorf("can't write td to Freezer: %w", err)
}
}
return nil
})
if err != nil {
return fmt.Errorf("failed to write block range: %w", err)
}
log.Info("Wrote ancient blocks", "start", blockRange.start, "end", blockRange.start+uint64(len(blockRange.hashes)-1), "count", len(blockRange.hashes))
}
}
return nil
}
Loading