From 753aa7160f854bf9f731bb83511ed08a95d43f68 Mon Sep 17 00:00:00 2001 From: pk910 Date: Wed, 31 Jan 2024 07:20:21 +0100 Subject: [PATCH 1/6] override `go-eth2-client` to verkle compatible branch --- go.mod | 2 ++ go.sum | 2 ++ 2 files changed, 4 insertions(+) diff --git a/go.mod b/go.mod index 38da9af4..adf84686 100644 --- a/go.mod +++ b/go.mod @@ -89,3 +89,5 @@ require ( gopkg.in/cenkalti/backoff.v1 v1.1.0 // indirect rsc.io/tmplfunc v0.0.3 // indirect ) + +replace github.com/attestantio/go-eth2-client => github.com/pk910/go-eth2-client v0.0.0-20231217052657-39326b2b91a7 \ No newline at end of file diff --git a/go.sum b/go.sum index ecac48c1..c506ff39 100644 --- a/go.sum +++ b/go.sum @@ -181,6 +181,8 @@ github.com/mmcloughlin/addchain v0.4.0/go.mod h1:A86O+tHqZLMNO4w6ZZ4FlVQEadcoqky github.com/mmcloughlin/profile v0.1.1/go.mod h1:IhHD7q1ooxgwTgjxQYkACGA77oFTDdFVejUS1/tS/qU= github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= +github.com/pk910/go-eth2-client v0.0.0-20231217052657-39326b2b91a7 h1:JG2FFabNp3W1bmUbJeiAV4WPFuaNnVO4y4G9WXLsXPo= +github.com/pk910/go-eth2-client v0.0.0-20231217052657-39326b2b91a7/go.mod h1:YKTloAuspHPDCFg8+jV14H1+UFoaDLqabb/C2hHg8Q4= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= From d7e303f10639f94e0b8660f110ee01a64c9581ff Mon Sep 17 00:00:00 2001 From: pk910 Date: Wed, 31 Jan 2024 07:56:12 +0100 Subject: [PATCH 2/6] disable SSZ encoding --- pkg/coordinator/clients/consensus/rpc/beaconapi.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pkg/coordinator/clients/consensus/rpc/beaconapi.go b/pkg/coordinator/clients/consensus/rpc/beaconapi.go index 4316f404..2ab82126 100644 --- a/pkg/coordinator/clients/consensus/rpc/beaconapi.go +++ b/pkg/coordinator/clients/consensus/rpc/beaconapi.go @@ -52,6 +52,8 @@ func (bc *BeaconClient) Initialize(ctx context.Context) error { http.WithLogLevel(zerolog.Disabled), // TODO (when upstream PR is merged) // http.WithConnectionCheck(false), + // TODO: remove when go-eth2-client has proper verkle support + http.WithEnforceJSON(true), } // set extra endpoint headers From c15bc4ff60566b7dbbf5b4b51aeb038271967b01 Mon Sep 17 00:00:00 2001 From: pk910 Date: Fri, 1 Mar 2024 13:47:01 +0100 Subject: [PATCH 3/6] add `check_execution_conversion_state` task (checks verkle conversion state) --- .../clients/execution/rpc/executionapi.go | 7 + .../execution/rpc/verkleconversionstate.go | 6 + .../README.md | 35 ++++ .../config.go | 25 +++ .../check_execution_conversion_state/task.go | 156 ++++++++++++++++++ pkg/coordinator/tasks/tasks.go | 2 + 6 files changed, 231 insertions(+) create mode 100644 pkg/coordinator/clients/execution/rpc/verkleconversionstate.go create mode 100644 pkg/coordinator/tasks/check_execution_conversion_state/README.md create mode 100644 pkg/coordinator/tasks/check_execution_conversion_state/config.go create mode 100644 pkg/coordinator/tasks/check_execution_conversion_state/task.go diff --git a/pkg/coordinator/clients/execution/rpc/executionapi.go b/pkg/coordinator/clients/execution/rpc/executionapi.go index fcfef4a8..0afafd4d 100644 --- a/pkg/coordinator/clients/execution/rpc/executionapi.go +++ b/pkg/coordinator/clients/execution/rpc/executionapi.go @@ -126,3 +126,10 @@ func (ec *ExecutionClient) GetTransactionReceipt(ctx context.Context, txHash com func (ec *ExecutionClient) SendTransaction(ctx context.Context, tx *types.Transaction) error { return ec.ethClient.SendTransaction(ctx, tx) } + +func (ec *ExecutionClient) GetVerkleConversionState(ctx context.Context) (*VerkleConversionState, error) { + var result VerkleConversionState + err := ec.rpcClient.CallContext(ctx, &result, "debug_conversionStatus", "latest") + + return &result, err +} diff --git a/pkg/coordinator/clients/execution/rpc/verkleconversionstate.go b/pkg/coordinator/clients/execution/rpc/verkleconversionstate.go new file mode 100644 index 00000000..ea362d38 --- /dev/null +++ b/pkg/coordinator/clients/execution/rpc/verkleconversionstate.go @@ -0,0 +1,6 @@ +package rpc + +type VerkleConversionState struct { + Started bool `json:"started"` + Ended bool `json:"ended"` +} diff --git a/pkg/coordinator/tasks/check_execution_conversion_state/README.md b/pkg/coordinator/tasks/check_execution_conversion_state/README.md new file mode 100644 index 00000000..3ebcd8b9 --- /dev/null +++ b/pkg/coordinator/tasks/check_execution_conversion_state/README.md @@ -0,0 +1,35 @@ +## `check_execution_conversion_state` Task + +### Description +The `check_execution_conversion_state` task is designed to monitor the status of execution clients regarding their conversion to the Verkle tree structure, a significant upgrade in the Ethereum network. This task assesses whether the execution clients have started, are in the process of, or have completed the conversion to Verkle trees, ensuring that the network's upgrade transitions are proceeding as expected. + +### Configuration Parameters + +- **`clientPattern`**: + A regex pattern for selecting specific execution client endpoints to check. This allows for targeted monitoring of clients based on identifiers or characteristics defined in their endpoint URLs. + +- **`pollInterval`**: + The time interval, in seconds, at which the task will poll the clients to check their Verkle conversion status. A shorter interval results in more frequent checks, allowing for timely detection of state changes. + +- **`expectStarted`**: + If set to `true`, this option indicates the expectation that the Verkle conversion process has started on the targeted execution clients. The task checks for evidence that the conversion process is underway. + +- **`expectFinished`**: + When `true`, the task expects that the Verkle conversion process has been completed on the targeted execution clients. It verifies that the clients are fully upgraded to the new tree structure. + +- **`failOnUnexpected`**: + If set to `true`, the task will fail if the actual conversion status of the clients does not match the expected states (`expectStarted`, `expectFinished`). This is useful for scenarios where strict compliance with the conversion timeline is critical. + +### Defaults + +Default settings for the `check_execution_conversion_state` task: + +```yaml +- name: check_execution_conversion_state + config: + clientPattern: "" + pollInterval: 5s + expectStarted: false + expectFinished: false + failOnUnexpected: false +``` diff --git a/pkg/coordinator/tasks/check_execution_conversion_state/config.go b/pkg/coordinator/tasks/check_execution_conversion_state/config.go new file mode 100644 index 00000000..d06db642 --- /dev/null +++ b/pkg/coordinator/tasks/check_execution_conversion_state/config.go @@ -0,0 +1,25 @@ +package checkexecutionconversionstate + +import ( + "time" + + "github.com/ethpandaops/assertoor/pkg/coordinator/human-duration" +) + +type Config struct { + ClientPattern string `yaml:"clientPattern" json:"clientPattern"` + PollInterval human.Duration `yaml:"pollInterval" json:"pollInterval"` + ExpectStarted bool `yaml:"expectStarted" json:"expectStarted"` + ExpectFinished bool `yaml:"expectFinished" json:"expectFinished"` + FailOnUnexpected bool `yaml:"failOnUnexpected" json:"failOnUnexpected"` +} + +func DefaultConfig() Config { + return Config{ + PollInterval: human.Duration{Duration: 5 * time.Second}, + } +} + +func (c *Config) Validate() error { + return nil +} diff --git a/pkg/coordinator/tasks/check_execution_conversion_state/task.go b/pkg/coordinator/tasks/check_execution_conversion_state/task.go new file mode 100644 index 00000000..c10ddbfd --- /dev/null +++ b/pkg/coordinator/tasks/check_execution_conversion_state/task.go @@ -0,0 +1,156 @@ +package checkexecutionconversionstate + +import ( + "context" + "fmt" + "time" + + "github.com/ethpandaops/assertoor/pkg/coordinator/clients/execution/rpc" + "github.com/ethpandaops/assertoor/pkg/coordinator/types" + "github.com/sirupsen/logrus" +) + +var ( + TaskName = "check_execution_conversion_state" + TaskDescriptor = &types.TaskDescriptor{ + Name: TaskName, + Description: "Checks execution clients for their verkle conversion status.", + Config: DefaultConfig(), + NewTask: NewTask, + } +) + +type Task struct { + ctx *types.TaskContext + options *types.TaskOptions + config Config + logger logrus.FieldLogger + firstHeight map[uint16]uint64 +} + +func NewTask(ctx *types.TaskContext, options *types.TaskOptions) (types.Task, error) { + return &Task{ + ctx: ctx, + options: options, + logger: ctx.Logger.GetLogger(), + firstHeight: map[uint16]uint64{}, + }, nil +} + +func (t *Task) Name() string { + return TaskName +} + +func (t *Task) Description() string { + return TaskDescriptor.Description +} + +func (t *Task) Title() string { + return t.ctx.Vars.ResolvePlaceholders(t.options.Title) +} + +func (t *Task) Config() interface{} { + return t.config +} + +func (t *Task) Logger() logrus.FieldLogger { + return t.logger +} + +func (t *Task) Timeout() time.Duration { + return t.options.Timeout.Duration +} + +func (t *Task) LoadConfig() error { + config := DefaultConfig() + + // parse static config + if t.options.Config != nil { + if err := t.options.Config.Unmarshal(&config); err != nil { + return fmt.Errorf("error parsing task config for %v: %w", TaskName, err) + } + } + + // load dynamic vars + err := t.ctx.Vars.ConsumeVars(&config, t.options.ConfigVars) + if err != nil { + return err + } + + // validate config + if err := config.Validate(); err != nil { + return err + } + + t.config = config + + return nil +} + +func (t *Task) Execute(ctx context.Context) error { + t.processCheck(ctx) + + for { + select { + case <-time.After(t.config.PollInterval.Duration): + t.processCheck(ctx) + case <-ctx.Done(): + return nil + } + } +} + +func (t *Task) processCheck(ctx context.Context) { + allResultsPass := true + failedClients := []string{} + + for _, client := range t.ctx.Scheduler.GetServices().ClientPool().GetClientsByNamePatterns(t.config.ClientPattern, "") { + var checkResult bool + + checkLogger := t.logger.WithField("client", client.Config.Name) + conversionStatus, err := client.ExecutionClient.GetRPCClient().GetVerkleConversionState(ctx) + + if ctx.Err() != nil { + return + } + + if err != nil { + checkLogger.Warnf("error fetching verkle conversion status: %v", err) + + checkResult = false + } else { + checkResult = t.processClientCheck(conversionStatus, checkLogger) + } + + if !checkResult { + allResultsPass = false + + failedClients = append(failedClients, client.Config.Name) + } + } + + t.logger.Infof("Check result: %v, Failed Clients: %v", allResultsPass, failedClients) + + switch { + case allResultsPass: + t.ctx.SetResult(types.TaskResultSuccess) + case t.config.FailOnUnexpected: + t.ctx.SetResult(types.TaskResultFailure) + default: + t.ctx.SetResult(types.TaskResultNone) + } +} + +func (t *Task) processClientCheck(conversionStatus *rpc.VerkleConversionState, checkLogger logrus.FieldLogger) bool { + if conversionStatus.Started != t.config.ExpectStarted { + checkLogger.Debugf("check failed. check: ExpectStarted, expected: %v, got: %v", t.config.ExpectStarted, conversionStatus.Started) + return false + } + + if conversionStatus.Ended != t.config.ExpectFinished { + checkLogger.Debugf("check failed. check: ExpectFinished, expected: %v, got: %v", t.config.ExpectFinished, conversionStatus.Ended) + return false + } + + return true +} diff --git a/pkg/coordinator/tasks/tasks.go b/pkg/coordinator/tasks/tasks.go index ba0add04..d8d3e757 100644 --- a/pkg/coordinator/tasks/tasks.go +++ b/pkg/coordinator/tasks/tasks.go @@ -13,6 +13,7 @@ import ( checkconsensusslotrange "github.com/ethpandaops/assertoor/pkg/coordinator/tasks/check_consensus_slot_range" checkconsensussyncstatus "github.com/ethpandaops/assertoor/pkg/coordinator/tasks/check_consensus_sync_status" checkconsensusvalidatorstatus "github.com/ethpandaops/assertoor/pkg/coordinator/tasks/check_consensus_validator_status" + checkexecutionconversionstate "github.com/ethpandaops/assertoor/pkg/coordinator/tasks/check_execution_conversion_state" checkexecutionsyncstatus "github.com/ethpandaops/assertoor/pkg/coordinator/tasks/check_execution_sync_status" generateblobtransactions "github.com/ethpandaops/assertoor/pkg/coordinator/tasks/generate_blob_transactions" generateblschanges "github.com/ethpandaops/assertoor/pkg/coordinator/tasks/generate_bls_changes" @@ -44,6 +45,7 @@ var AvailableTaskDescriptors = []*types.TaskDescriptor{ checkconsensusslotrange.TaskDescriptor, checkconsensussyncstatus.TaskDescriptor, checkconsensusvalidatorstatus.TaskDescriptor, + checkexecutionconversionstate.TaskDescriptor, checkexecutionsyncstatus.TaskDescriptor, generateblobtransactions.TaskDescriptor, generateblschanges.TaskDescriptor, From 11609513faac625f600ff390a45b0ce89e081687 Mon Sep 17 00:00:00 2001 From: pk910 Date: Fri, 1 Mar 2024 13:52:59 +0100 Subject: [PATCH 4/6] increase default polling interval for `check_execution_conversion_state` task --- .../tasks/check_execution_conversion_state/README.md | 2 +- .../tasks/check_execution_conversion_state/config.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pkg/coordinator/tasks/check_execution_conversion_state/README.md b/pkg/coordinator/tasks/check_execution_conversion_state/README.md index 3ebcd8b9..b41c9d46 100644 --- a/pkg/coordinator/tasks/check_execution_conversion_state/README.md +++ b/pkg/coordinator/tasks/check_execution_conversion_state/README.md @@ -28,7 +28,7 @@ Default settings for the `check_execution_conversion_state` task: - name: check_execution_conversion_state config: clientPattern: "" - pollInterval: 5s + pollInterval: 10s expectStarted: false expectFinished: false failOnUnexpected: false diff --git a/pkg/coordinator/tasks/check_execution_conversion_state/config.go b/pkg/coordinator/tasks/check_execution_conversion_state/config.go index d06db642..e79cc50a 100644 --- a/pkg/coordinator/tasks/check_execution_conversion_state/config.go +++ b/pkg/coordinator/tasks/check_execution_conversion_state/config.go @@ -16,7 +16,7 @@ type Config struct { func DefaultConfig() Config { return Config{ - PollInterval: human.Duration{Duration: 5 * time.Second}, + PollInterval: human.Duration{Duration: 10 * time.Second}, } } From 040a2dbebd7de4a351e828801ef1ab673673e2be Mon Sep 17 00:00:00 2001 From: pk910 Date: Fri, 1 Mar 2024 16:11:04 +0100 Subject: [PATCH 5/6] fix PR build workflow --- .github/workflows/build-dev.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/build-dev.yml b/.github/workflows/build-dev.yml index 35c1837c..bfc2bd65 100644 --- a/.github/workflows/build-dev.yml +++ b/.github/workflows/build-dev.yml @@ -44,6 +44,10 @@ jobs: echo "repository: $commit_repo" echo "commit: $commit_ref" + if [[ "$has_docker_image_label" == "true" ]]; then + run_builds="true" + fi + manual_tag="${{ inputs.docker_tag }}" if [[ ! -z "$manual_tag" ]]; then has_docker_image_label="true" From 0a544054f2c3471f3e3dfc82aa6ca682d53ea809 Mon Sep 17 00:00:00 2001 From: pk910 Date: Tue, 16 Apr 2024 21:37:57 +0200 Subject: [PATCH 6/6] fix `check_clients_are_healthy` --- pkg/coordinator/tasks/check_clients_are_healthy/task.go | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/pkg/coordinator/tasks/check_clients_are_healthy/task.go b/pkg/coordinator/tasks/check_clients_are_healthy/task.go index 4e4ab42d..99b73215 100644 --- a/pkg/coordinator/tasks/check_clients_are_healthy/task.go +++ b/pkg/coordinator/tasks/check_clients_are_healthy/task.go @@ -128,9 +128,12 @@ func (t *Task) processCheck() { switch { case t.config.MaxUnhealthyCount > -1 && len(failedClients) >= t.config.MaxUnhealthyCount: - if t.config.FailOnCheckMiss { + switch { + case t.config.FailOnCheckMiss: t.ctx.SetResult(types.TaskResultFailure) - } else { + case resultPass: + t.ctx.SetResult(types.TaskResultSuccess) + default: t.ctx.SetResult(types.TaskResultNone) } case resultPass: