Skip to content
Merged
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
28 changes: 0 additions & 28 deletions internal/adapters/apis/docker/docker_adapter.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,34 +29,6 @@ func NewDockerAdapter() (*DockerAdapter, error) {
return &DockerAdapter{cli: cli}, nil
}

// StopAndGetVolumeTarget stops the container, checks for a single volume, and returns the volume target path
func (d *DockerAdapter) StopAndGetVolumeTarget(ctx context.Context, containerName string, containerVolumeName string) (string, error) {
containerJSON, err := d.cli.ContainerInspect(ctx, containerName)
if err != nil {
return "", fmt.Errorf("failed to inspect container: %w", err)
}

// the volumeName is the mount one which name is equal to the containerVolumeName, find it
// find the mount which name is equal to containerVolumeName

for _, mount := range containerJSON.Mounts {
if mount.Name == containerVolumeName {
volumeName := mount.Name

volumeTarget := fmt.Sprintf("/var/lib/docker/volumes/%s/_data", volumeName)

// Stop the container
if err := d.cli.ContainerStop(ctx, containerName, container.StopOptions{}); err != nil {
return "", fmt.Errorf("failed to stop container: %w", err)
}

return volumeTarget, nil
}
}

return "", fmt.Errorf("failed to find volume mount %s in container %s", containerVolumeName, containerName)
}

// StartContainer starts the given container
func (d *DockerAdapter) StartContainer(ctx context.Context, containerName string) error {
if err := d.cli.ContainerStart(ctx, containerName, container.StartOptions{}); err != nil {
Expand Down
47 changes: 47 additions & 0 deletions internal/adapters/apis/execution/execution_adapter.go
Original file line number Diff line number Diff line change
Expand Up @@ -111,3 +111,50 @@ func (e *ExecutionAdapter) GetIsSyncing(ctx context.Context) (bool, error) {
}
return true, nil
}

// GetLatestBlockNumber retrieves the latest block number from the execution client
func (e *ExecutionAdapter) GetLatestBlockNumber(ctx context.Context) (uint64, error) {
url := e.baseURL
// JSON-RPC request body for eth_blockNumber
body := map[string]interface{}{
"jsonrpc": "2.0",
"method": "eth_blockNumber",
"params": []interface{}{},
"id": 1,
}
jsonBytes, err := json.Marshal(body)
if err != nil {
return 0, err
}

req, err := http.NewRequestWithContext(ctx, "POST", url, bytes.NewReader(jsonBytes))
if err != nil {
return 0, err
}
req.Header.Set("Content-Type", "application/json")

resp, err := e.client.Do(req)
if err != nil {
return 0, err
}
defer resp.Body.Close()

if resp.StatusCode != http.StatusOK {
return 0, fmt.Errorf("eth_blockNumber failed: %s", resp.Status)
}

var rpcResp struct {
Result string `json:"result"`
}
if err := json.NewDecoder(resp.Body).Decode(&rpcResp); err != nil {
return 0, err
}

var blockNumber uint64
_, err = fmt.Sscanf(rpcResp.Result, "0x%x", &blockNumber)
if err != nil {
return 0, fmt.Errorf("invalid block number format: %w", err)
}

return blockNumber, nil
}
26 changes: 16 additions & 10 deletions internal/adapters/apis/snapshots/snapshots_adapter.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"fmt"
"io"
"net/http"
"strconv"
"strings"
)

Expand Down Expand Up @@ -35,42 +36,47 @@ func (s *SnapshotsAdapter) GetBaseURL() string {
}

// GetLatestBlockNumber fetches the latest available block number for a given network and client
func (s *SnapshotsAdapter) GetLatestBlockNumber(ctx context.Context, network, client string) (string, error) {
func (s *SnapshotsAdapter) GetLatestBlockNumber(ctx context.Context, network, client string) (uint64, error) {
url := fmt.Sprintf("%s/%s/%s/latest", s.baseURL, network, client)

req, err := http.NewRequestWithContext(ctx, "GET", url, nil)
if err != nil {
return "", fmt.Errorf("failed to create request: %w", err)
return 0, fmt.Errorf("failed to create request: %w", err)
}

resp, err := http.DefaultClient.Do(req)
if err != nil {
return "", fmt.Errorf("failed to fetch latest block number: %w", err)
return 0, fmt.Errorf("failed to fetch latest block number: %w", err)
}
defer resp.Body.Close()

if resp.StatusCode != http.StatusOK {
return "", fmt.Errorf("failed to fetch latest block number: status %s", resp.Status)
return 0, fmt.Errorf("failed to fetch latest block number: status %s", resp.Status)
}

body, err := io.ReadAll(resp.Body)
if err != nil {
return "", fmt.Errorf("failed to read response body: %w", err)
return 0, fmt.Errorf("failed to read response body: %w", err)
}

blockNumberStr := strings.TrimSpace(string(body))
blockNumber, err := strconv.ParseUint(blockNumberStr, 10, 64)
if err != nil {
return 0, fmt.Errorf("failed to parse block number: %w", err)
}

blockNumber := strings.TrimSpace(string(body))
return blockNumber, nil
}

// GetSnapshotURL returns the full URL for a snapshot file
func (s *SnapshotsAdapter) GetSnapshotURL(network, client, blockNumber string) string {
return fmt.Sprintf("%s/%s/%s/%s/snapshot.tar.zst", s.baseURL, network, client, blockNumber)
func (s *SnapshotsAdapter) GetSnapshotURL(network, client string, blockNumber uint64) string {
return fmt.Sprintf("%s/%s/%s/%d/snapshot.tar.zst", s.baseURL, network, client, blockNumber)
}

// GetClientVersion fetches the client version used to generate the snapshot
// The version is retrieved from the _snapshot_web3_clientVersion.json file
func (s *SnapshotsAdapter) GetClientVersion(ctx context.Context, network, client, blockNumber string) (string, error) {
url := fmt.Sprintf("%s/%s/%s/%s/_snapshot_web3_clientVersion.json", s.baseURL, network, client, blockNumber)
func (s *SnapshotsAdapter) GetClientVersion(ctx context.Context, network, client string, blockNumber uint64) (string, error) {
url := fmt.Sprintf("%s/%s/%s/%d/_snapshot_web3_clientVersion.json", s.baseURL, network, client, blockNumber)

req, err := http.NewRequestWithContext(ctx, "GET", url, nil)
if err != nil {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ func (s *SnapshotManagerAdapter) DownloadAndMountSnapshot(ctx context.Context, n
}

// GetLatestBlockNumber fetches the latest available block number for a client
func (s *SnapshotManagerAdapter) GetLatestBlockNumber(ctx context.Context, network, client string) (string, error) {
func (s *SnapshotManagerAdapter) GetLatestBlockNumber(ctx context.Context, network, client string) (uint64, error) {
return s.snapshots.GetLatestBlockNumber(ctx, network, client)
}

Expand Down
37 changes: 22 additions & 15 deletions internal/adapters/composite/testmanager/cleaner/cleaner.go
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
package cleaner

import (
"clients-test/internal/adapters/apis/beaconchain"
"clients-test/internal/adapters/apis/brain"
"clients-test/internal/adapters/apis/dappmanager"
"clients-test/internal/adapters/apis/docker"
"clients-test/internal/adapters/apis/execution"
"clients-test/internal/adapters/shared/blocknumber"
"clients-test/internal/application/domain"
"context"
"fmt"
Expand All @@ -14,36 +13,44 @@ import (
type CleanerAdapter struct {
Dappmanager *dappmanager.DappManagerAdapter
Execution *execution.ExecutionAdapter
Brain *brain.BrainAdapter
Beaconchain *beaconchain.BeaconchainAdapter
Docker *docker.DockerAdapter
BlockNumber *blocknumber.BlockNumberAdapter
}

func NewCleanerAdapter(dappmanager *dappmanager.DappManagerAdapter, execution *execution.ExecutionAdapter, brain *brain.BrainAdapter, beaconchain *beaconchain.BeaconchainAdapter, docker *docker.DockerAdapter) *CleanerAdapter {
func NewCleanerAdapter(dappmanager *dappmanager.DappManagerAdapter, execution *execution.ExecutionAdapter, docker *docker.DockerAdapter, blockNumber *blocknumber.BlockNumberAdapter) *CleanerAdapter {
return &CleanerAdapter{
Dappmanager: dappmanager,
Execution: execution,
Brain: brain,
Beaconchain: beaconchain,
Docker: docker,
BlockNumber: blockNumber,
}
}

// CleanEnvironment stops containers and removes non-core packages
func (e *CleanerAdapter) CleanEnvironment(ctx context.Context, stakerConfig domain.StakerConfig) error {
var errs []error

// Get latest block number from execution client and update it in volume
latestBlockNumber, err := e.Execution.GetLatestBlockNumber(ctx)
if err != nil {
errs = append(errs, fmt.Errorf("get latest block number failed: %w", err))
}
err = e.BlockNumber.WriteBlockNumber(ctx, latestBlockNumber)
if err != nil {
errs = append(errs, fmt.Errorf("write block number failed: %w", err))
}

// Attempt to stop container
// _, err := e.Docker.StopAndGetVolumeTarget(ctx, stakerConfig.ExecutionContainerName, stakerConfig.ExecutionVolumeName)
// if err != nil {
// errs = append(errs, fmt.Errorf("stop container failed: %w", err))
// }
err = e.Docker.StopContainer(ctx, stakerConfig.ExecutionContainerName)
if err != nil {
errs = append(errs, fmt.Errorf("stop container failed: %w", err))
}

// Attempt to remove non-core packages
// pkgErrs := e.Dappmanager.RemoveNonCorePackages(ctx)
// for _, pkgErr := range pkgErrs {
// errs = append(errs, fmt.Errorf("remove non-core package failed: %w", pkgErr))
// }
_, pkgErrs := e.Dappmanager.RemoveNonCorePackages(ctx)
for _, pkgErr := range pkgErrs {
errs = append(errs, fmt.Errorf("remove non-core package failed: %w", pkgErr))
}

// Return combined error if any step failed
if len(errs) > 0 {
Expand Down
9 changes: 3 additions & 6 deletions internal/adapters/composite/testmanager/ensurer/ensurer.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ package ensurer
import (
"context"
"fmt"
"strconv"
"time"

"clients-test/internal/adapters/apis/beaconchain"
Expand Down Expand Up @@ -129,10 +128,8 @@ func getClientVersionWithRetry(getVersionFunc func() (string, error), clientType
// and stores it in the report. Errors are silently ignored as this is informational.
func (e *EnsurerAdapter) readSnapshotBlockNumber(ctx context.Context, report *domain.TestReport) {
// Use the BlockNumber adapter which is already initialized with the correct path
blockNumberStr, err := e.BlockNumber.ReadBlockNumber(ctx)
if err == nil && blockNumberStr != "" {
if blockNumber, parseErr := strconv.ParseUint(blockNumberStr, 10, 64); parseErr == nil {
report.SnapshotBlockNumber = blockNumber
}
blockNumber, err := e.BlockNumber.ReadBlockNumber(ctx)
if err == nil && blockNumber != 0 {
report.SnapshotBlockNumber = blockNumber
}
}
2 changes: 1 addition & 1 deletion internal/adapters/composite/testmanager/testmanager.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ func NewTestManagerAdapter(

ensurer := ensurer.NewEnsurerAdapter(dappManagerAdapter, brainAdapter, dockerAdapter, beaconchainAdapter, executionAdapter, ipfsAdapter, blockNumberAdapter, snapshotVersionAdapter)
executor := executor.NewExecutorAdapter(executionAdapter, brainAdapter, beaconchainAdapter)
cleaner := cleaner.NewCleanerAdapter(dappManagerAdapter, executionAdapter, brainAdapter, beaconchainAdapter, dockerAdapter)
cleaner := cleaner.NewCleanerAdapter(dappManagerAdapter, executionAdapter, dockerAdapter, blockNumberAdapter)
return &TestManagerAdapter{
ensurer: ensurer,
executor: executor,
Expand Down
46 changes: 19 additions & 27 deletions internal/adapters/shared/blocknumber/blocknumber_adapter.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ func (b *BlockNumberAdapter) blockNumberFilePath() string {
}

// WriteBlockNumber writes the block number to the snapshot_block_number file
func (b *BlockNumberAdapter) WriteBlockNumber(ctx context.Context, blockNumber string) error {
func (b *BlockNumberAdapter) WriteBlockNumber(ctx context.Context, blockNumber uint64) error {
filePath := b.blockNumberFilePath()

// Ensure directory exists
Expand All @@ -49,7 +49,7 @@ func (b *BlockNumberAdapter) WriteBlockNumber(ctx context.Context, blockNumber s
}
defer syscall.Flock(int(f.Fd()), syscall.LOCK_UN)

_, err = f.WriteString(blockNumber)
_, err = f.WriteString(strconv.FormatUint(blockNumber, 10))
if err != nil {
return fmt.Errorf("failed to write to block number file: %w", err)
}
Expand All @@ -58,31 +58,36 @@ func (b *BlockNumberAdapter) WriteBlockNumber(ctx context.Context, blockNumber s
}

// ReadBlockNumber reads the block number from the snapshot_block_number file
// Returns empty string if file doesn't exist
func (b *BlockNumberAdapter) ReadBlockNumber(ctx context.Context) (string, error) {
// Returns 0 if file doesn't exist
func (b *BlockNumberAdapter) ReadBlockNumber(ctx context.Context) (uint64, error) {
filePath := b.blockNumberFilePath()

f, err := os.Open(filePath)
if err != nil {
if os.IsNotExist(err) {
return "", nil
return 0, nil
}
return "", fmt.Errorf("failed to open block number file: %w", err)
return 0, fmt.Errorf("failed to open block number file: %w", err)
}
defer f.Close()

// Acquire shared lock for reading
if err := syscall.Flock(int(f.Fd()), syscall.LOCK_SH); err != nil {
return "", fmt.Errorf("failed to acquire lock on block number file: %w", err)
return 0, fmt.Errorf("failed to acquire lock on block number file: %w", err)
}
defer syscall.Flock(int(f.Fd()), syscall.LOCK_UN)

data, err := os.ReadFile(filePath)
if err != nil {
return "", fmt.Errorf("failed to read block number file: %w", err)
return 0, fmt.Errorf("failed to read block number file: %w", err)
}

blockNumberStr := strings.TrimSpace(string(data))
blockNumber, err := strconv.ParseUint(blockNumberStr, 10, 64)
if err != nil {
return 0, fmt.Errorf("failed to parse block number: %w", err)
}

blockNumber := strings.TrimSpace(string(data))
return blockNumber, nil
}

Expand Down Expand Up @@ -110,37 +115,24 @@ func (b *BlockNumberAdapter) BlockNumberExists(ctx context.Context) (bool, error

// CompareBlockNumbers compares two block numbers
// Returns: -1 if a < b, 0 if a == b, 1 if a > b
func (b *BlockNumberAdapter) CompareBlockNumbers(a, blockB string) int {
aInt, aErr := strconv.ParseInt(a, 10, 64)
bInt, bErr := strconv.ParseInt(blockB, 10, 64)

if aErr != nil || bErr != nil {
// Fall back to string comparison if not valid integers
if a < blockB {
return -1
} else if a > blockB {
return 1
}
return 0
}

if aInt < bInt {
func (b *BlockNumberAdapter) CompareBlockNumbers(a, blockB uint64) int {
if a < blockB {
return -1
} else if aInt > bInt {
} else if a > blockB {
return 1
}
return 0
}

// IsNewerSnapshot checks if the latest available block number is newer than the current one
func (b *BlockNumberAdapter) IsNewerSnapshot(ctx context.Context, latestBlockNumber string) (bool, error) {
func (b *BlockNumberAdapter) IsNewerSnapshot(ctx context.Context, latestBlockNumber uint64) (bool, error) {
currentBlockNumber, err := b.ReadBlockNumber(ctx)
if err != nil {
return false, err
}

// If no current block number, we need to download
if currentBlockNumber == "" {
if currentBlockNumber == 0 {
return true, nil
}

Expand Down
2 changes: 1 addition & 1 deletion internal/application/domain/snapshot.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ type SnapshotCheckerConfig struct {
ExecutionClient ExecutionClientInfo // The execution client to manage
CronIntervalSec int // Interval between snapshot checks in seconds (default 6 hours)
Network string // Network name (e.g., hoodi)
BlockRange int // Number of blocks to consider as up-to-date range
BlockRange uint64 // Number of blocks to consider as up-to-date range
}

// ValidExecutionClients contains all valid execution client short names for hoodi
Expand Down
6 changes: 3 additions & 3 deletions internal/application/ports/blockNumber_port.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,14 @@ import "context"
type BlockNumber interface {
// ReadBlockNumber reads the current block number from storage
// Returns empty string if no block number file exists
ReadBlockNumber(ctx context.Context) (string, error)
ReadBlockNumber(ctx context.Context) (uint64, error)

// WriteBlockNumber writes the block number to storage
WriteBlockNumber(ctx context.Context, blockNumber string) error
WriteBlockNumber(ctx context.Context, blockNumber uint64) error

// BlockNumberExists checks if a block number file exists
BlockNumberExists(ctx context.Context) (bool, error)

// IsNewerSnapshot checks if the latest available block number is newer than the current one
IsNewerSnapshot(ctx context.Context, latestBlockNumber string) (bool, error)
IsNewerSnapshot(ctx context.Context, latestBlockNumber uint64) (bool, error)
}
Loading