From 475b43ac8454064ec9ccb541c836d2e9ec529673 Mon Sep 17 00:00:00 2001 From: JuArce <52429267+JuArce@users.noreply.github.com> Date: Wed, 18 Sep 2024 14:11:38 -0300 Subject: [PATCH 01/55] chore: initial telemetry api setup feat: CRUD for operators version --- telemetry_api/.formatter.exs | 5 + telemetry_api/.gitignore | 27 +++++ telemetry_api/Dockerfile | 10 ++ telemetry_api/README.md | 18 +++ telemetry_api/config/config.exs | 35 ++++++ telemetry_api/config/dev.exs | 64 +++++++++++ telemetry_api/config/prod.exs | 7 ++ telemetry_api/config/runtime.exs | 99 +++++++++++++++++ telemetry_api/config/test.exs | 27 +++++ telemetry_api/lib/telemetry_api.ex | 9 ++ .../lib/telemetry_api/application.ex | 34 ++++++ telemetry_api/lib/telemetry_api/operators.ex | 104 ++++++++++++++++++ .../lib/telemetry_api/operators/operator.ex | 18 +++ telemetry_api/lib/telemetry_api/repo.ex | 5 + telemetry_api/lib/telemetry_api_web.ex | 65 +++++++++++ .../controllers/changeset_json.ex | 25 +++++ .../controllers/error_json.ex | 21 ++++ .../controllers/fallback_controller.ex | 24 ++++ .../controllers/operator_controller.ex | 43 ++++++++ .../controllers/operator_json.ex | 25 +++++ .../lib/telemetry_api_web/endpoint.ex | 51 +++++++++ telemetry_api/lib/telemetry_api_web/router.ex | 28 +++++ .../lib/telemetry_api_web/telemetry.ex | 92 ++++++++++++++++ telemetry_api/mix.exs | 62 +++++++++++ telemetry_api/mix.lock | 28 +++++ .../priv/repo/migrations/.formatter.exs | 4 + .../20240917212329_create_operators.exs | 12 ++ telemetry_api/priv/repo/seeds.exs | 11 ++ telemetry_api/priv/static/favicon.ico | Bin 0 -> 152 bytes telemetry_api/priv/static/robots.txt | 5 + telemetry_api/test/support/conn_case.ex | 38 +++++++ telemetry_api/test/support/data_case.ex | 58 ++++++++++ .../test/support/fixtures/urls_fixtures.ex | 21 ++++ .../test/telemetry_api/urls_test.exs | 61 ++++++++++ .../controllers/error_json_test.exs | 12 ++ .../controllers/operator_controller_test.exs | 88 +++++++++++++++ telemetry_api/test/test_helper.exs | 2 + 37 files changed, 1238 insertions(+) create mode 100644 telemetry_api/.formatter.exs create mode 100644 telemetry_api/.gitignore create mode 100644 telemetry_api/Dockerfile create mode 100644 telemetry_api/README.md create mode 100644 telemetry_api/config/config.exs create mode 100644 telemetry_api/config/dev.exs create mode 100644 telemetry_api/config/prod.exs create mode 100644 telemetry_api/config/runtime.exs create mode 100644 telemetry_api/config/test.exs create mode 100644 telemetry_api/lib/telemetry_api.ex create mode 100644 telemetry_api/lib/telemetry_api/application.ex create mode 100644 telemetry_api/lib/telemetry_api/operators.ex create mode 100644 telemetry_api/lib/telemetry_api/operators/operator.ex create mode 100644 telemetry_api/lib/telemetry_api/repo.ex create mode 100644 telemetry_api/lib/telemetry_api_web.ex create mode 100644 telemetry_api/lib/telemetry_api_web/controllers/changeset_json.ex create mode 100644 telemetry_api/lib/telemetry_api_web/controllers/error_json.ex create mode 100644 telemetry_api/lib/telemetry_api_web/controllers/fallback_controller.ex create mode 100644 telemetry_api/lib/telemetry_api_web/controllers/operator_controller.ex create mode 100644 telemetry_api/lib/telemetry_api_web/controllers/operator_json.ex create mode 100644 telemetry_api/lib/telemetry_api_web/endpoint.ex create mode 100644 telemetry_api/lib/telemetry_api_web/router.ex create mode 100644 telemetry_api/lib/telemetry_api_web/telemetry.ex create mode 100644 telemetry_api/mix.exs create mode 100644 telemetry_api/mix.lock create mode 100644 telemetry_api/priv/repo/migrations/.formatter.exs create mode 100644 telemetry_api/priv/repo/migrations/20240917212329_create_operators.exs create mode 100644 telemetry_api/priv/repo/seeds.exs create mode 100644 telemetry_api/priv/static/favicon.ico create mode 100644 telemetry_api/priv/static/robots.txt create mode 100644 telemetry_api/test/support/conn_case.ex create mode 100644 telemetry_api/test/support/data_case.ex create mode 100644 telemetry_api/test/support/fixtures/urls_fixtures.ex create mode 100644 telemetry_api/test/telemetry_api/urls_test.exs create mode 100644 telemetry_api/test/telemetry_api_web/controllers/error_json_test.exs create mode 100644 telemetry_api/test/telemetry_api_web/controllers/operator_controller_test.exs create mode 100644 telemetry_api/test/test_helper.exs diff --git a/telemetry_api/.formatter.exs b/telemetry_api/.formatter.exs new file mode 100644 index 000000000..5971023f6 --- /dev/null +++ b/telemetry_api/.formatter.exs @@ -0,0 +1,5 @@ +[ + import_deps: [:ecto, :ecto_sql, :phoenix], + subdirectories: ["priv/*/migrations"], + inputs: ["*.{ex,exs}", "{config,lib,test}/**/*.{ex,exs}", "priv/*/seeds.exs"] +] diff --git a/telemetry_api/.gitignore b/telemetry_api/.gitignore new file mode 100644 index 000000000..697102350 --- /dev/null +++ b/telemetry_api/.gitignore @@ -0,0 +1,27 @@ +# The directory Mix will write compiled artifacts to. +/_build/ + +# If you run "mix test --cover", coverage assets end up here. +/cover/ + +# The directory Mix downloads your dependencies sources to. +/deps/ + +# Where 3rd-party dependencies like ExDoc output generated docs. +/doc/ + +# Ignore .fetch files in case you like to edit your project deps locally. +/.fetch + +# If the VM crashes, it generates a dump, let's ignore it too. +erl_crash.dump + +# Also ignore archive artifacts (built via "mix archive.build"). +*.ez + +# Temporary files, for example, from tests. +/tmp/ + +# Ignore package tarball (built via "mix hex.build"). +telemetry_api-*.tar + diff --git a/telemetry_api/Dockerfile b/telemetry_api/Dockerfile new file mode 100644 index 000000000..0cf033f72 --- /dev/null +++ b/telemetry_api/Dockerfile @@ -0,0 +1,10 @@ +# https://hub.docker.com/_/postgres +FROM postgres:16.3 + +# Environment variables +ENV POSTGRES_USER=telemetry_user +ENV POSTGRES_PASSWORD=telemetry_pass +ENV POSTGRES_DB=telemetry_db + +# Expose the default PostgreSQL port +EXPOSE 5432 diff --git a/telemetry_api/README.md b/telemetry_api/README.md new file mode 100644 index 000000000..63ebe6d1c --- /dev/null +++ b/telemetry_api/README.md @@ -0,0 +1,18 @@ +# TelemetryApi + +To start your Phoenix server: + + * Run `mix setup` to install and setup dependencies + * Start Phoenix endpoint with `mix phx.server` or inside IEx with `iex -S mix phx.server` + +Now you can visit [`localhost:4000`](http://localhost:4000) from your browser. + +Ready to run in production? Please [check our deployment guides](https://hexdocs.pm/phoenix/deployment.html). + +## Learn more + + * Official website: https://www.phoenixframework.org/ + * Guides: https://hexdocs.pm/phoenix/overview.html + * Docs: https://hexdocs.pm/phoenix + * Forum: https://elixirforum.com/c/phoenix-forum + * Source: https://github.com/phoenixframework/phoenix diff --git a/telemetry_api/config/config.exs b/telemetry_api/config/config.exs new file mode 100644 index 000000000..46bf3bd9c --- /dev/null +++ b/telemetry_api/config/config.exs @@ -0,0 +1,35 @@ +# This file is responsible for configuring your application +# and its dependencies with the aid of the Config module. +# +# This configuration file is loaded before any dependency and +# is restricted to this project. + +# General application configuration +import Config + +config :telemetry_api, + ecto_repos: [TelemetryApi.Repo], + generators: [timestamp_type: :utc_datetime] + +# Configures the endpoint +config :telemetry_api, TelemetryApiWeb.Endpoint, + url: [host: "localhost"], + adapter: Bandit.PhoenixAdapter, + render_errors: [ + formats: [json: TelemetryApiWeb.ErrorJSON], + layout: false + ], + pubsub_server: TelemetryApi.PubSub, + live_view: [signing_salt: "eQaI7lMW"] + +# Configures Elixir's Logger +config :logger, :console, + format: "$time $metadata[$level] $message\n", + metadata: [:request_id] + +# Use Jason for JSON parsing in Phoenix +config :phoenix, :json_library, Jason + +# Import environment specific config. This must remain at the bottom +# of this file so it overrides the configuration defined above. +import_config "#{config_env()}.exs" diff --git a/telemetry_api/config/dev.exs b/telemetry_api/config/dev.exs new file mode 100644 index 000000000..90fd36b6f --- /dev/null +++ b/telemetry_api/config/dev.exs @@ -0,0 +1,64 @@ +import Config + +# Configure your database +config :telemetry_api, TelemetryApi.Repo, + username: "telemetry_user", + password: "telemetry_pass", + database: "telemetry_db", + hostname: "localhost", + port: 5432, + stacktrace: true, + show_sensitive_data_on_connection_error: true, + pool_size: 10 + +# For development, we disable any cache and enable +# debugging and code reloading. +# +# The watchers configuration can be used to run external +# watchers to your application. For example, we can use it +# to bundle .js and .css sources. +config :telemetry_api, TelemetryApiWeb.Endpoint, + # Binding to loopback ipv4 address prevents access from other machines. + # Change to `ip: {0, 0, 0, 0}` to allow access from other machines. + http: [ip: {127, 0, 0, 1}, port: 4000], + check_origin: false, + code_reloader: true, + debug_errors: true, + secret_key_base: "SKxKWZhd8cfUXMUqskUHvegw8P46kkfwIYWTW86tsqn+t6M2S1HUFjTqgVWAkvX0", + watchers: [] + +# ## SSL Support +# +# In order to use HTTPS in development, a self-signed +# certificate can be generated by running the following +# Mix task: +# +# mix phx.gen.cert +# +# Run `mix help phx.gen.cert` for more information. +# +# The `http:` config above can be replaced with: +# +# https: [ +# port: 4001, +# cipher_suite: :strong, +# keyfile: "priv/cert/selfsigned_key.pem", +# certfile: "priv/cert/selfsigned.pem" +# ], +# +# If desired, both `http:` and `https:` keys can be +# configured to run both http and https servers on +# different ports. + +# Enable dev routes for dashboard and mailbox +config :telemetry_api, dev_routes: true + +# Do not include metadata nor timestamps in development logs +config :logger, :console, format: "[$level] $message\n" + +# Set a higher stacktrace during development. Avoid configuring such +# in production as building large stacktraces may be expensive. +config :phoenix, :stacktrace_depth, 20 + +# Initialize plugs at runtime for faster development compilation +config :phoenix, :plug_init_mode, :runtime diff --git a/telemetry_api/config/prod.exs b/telemetry_api/config/prod.exs new file mode 100644 index 000000000..1fe2d9e85 --- /dev/null +++ b/telemetry_api/config/prod.exs @@ -0,0 +1,7 @@ +import Config + +# Do not print debug messages in production +config :logger, level: :info + +# Runtime production configuration, including reading +# of environment variables, is done on config/runtime.exs. diff --git a/telemetry_api/config/runtime.exs b/telemetry_api/config/runtime.exs new file mode 100644 index 000000000..0d07d01e1 --- /dev/null +++ b/telemetry_api/config/runtime.exs @@ -0,0 +1,99 @@ +import Config + +# config/runtime.exs is executed for all environments, including +# during releases. It is executed after compilation and before the +# system starts, so it is typically used to load production configuration +# and secrets from environment variables or elsewhere. Do not define +# any compile-time configuration in here, as it won't be applied. +# The block below contains prod specific runtime configuration. + +# ## Using releases +# +# If you use `mix release`, you need to explicitly enable the server +# by passing the PHX_SERVER=true when you start it: +# +# PHX_SERVER=true bin/telemetry_api start +# +# Alternatively, you can use `mix phx.gen.release` to generate a `bin/server` +# script that automatically sets the env var above. +if System.get_env("PHX_SERVER") do + config :telemetry_api, TelemetryApiWeb.Endpoint, server: true +end + +if config_env() == :prod do + database_url = + System.get_env("DATABASE_URL") || + raise """ + environment variable DATABASE_URL is missing. + For example: ecto://USER:PASS@HOST/DATABASE + """ + + maybe_ipv6 = if System.get_env("ECTO_IPV6") in ~w(true 1), do: [:inet6], else: [] + + config :telemetry_api, TelemetryApi.Repo, + # ssl: true, + url: database_url, + pool_size: String.to_integer(System.get_env("POOL_SIZE") || "10"), + socket_options: maybe_ipv6 + + # The secret key base is used to sign/encrypt cookies and other secrets. + # A default value is used in config/dev.exs and config/test.exs but you + # want to use a different value for prod and you most likely don't want + # to check this value into version control, so we use an environment + # variable instead. + secret_key_base = + System.get_env("SECRET_KEY_BASE") || + raise """ + environment variable SECRET_KEY_BASE is missing. + You can generate one by calling: mix phx.gen.secret + """ + + host = System.get_env("PHX_HOST") || "example.com" + port = String.to_integer(System.get_env("PORT") || "4000") + + config :telemetry_api, :dns_cluster_query, System.get_env("DNS_CLUSTER_QUERY") + + config :telemetry_api, TelemetryApiWeb.Endpoint, + url: [host: host, port: 443, scheme: "https"], + http: [ + # Enable IPv6 and bind on all interfaces. + # Set it to {0, 0, 0, 0, 0, 0, 0, 1} for local network only access. + # See the documentation on https://hexdocs.pm/bandit/Bandit.html#t:options/0 + # for details about using IPv6 vs IPv4 and loopback vs public addresses. + ip: {0, 0, 0, 0, 0, 0, 0, 0}, + port: port + ], + secret_key_base: secret_key_base + + # ## SSL Support + # + # To get SSL working, you will need to add the `https` key + # to your endpoint configuration: + # + # config :telemetry_api, TelemetryApiWeb.Endpoint, + # https: [ + # ..., + # port: 443, + # cipher_suite: :strong, + # keyfile: System.get_env("SOME_APP_SSL_KEY_PATH"), + # certfile: System.get_env("SOME_APP_SSL_CERT_PATH") + # ] + # + # The `cipher_suite` is set to `:strong` to support only the + # latest and more secure SSL ciphers. This means old browsers + # and clients may not be supported. You can set it to + # `:compatible` for wider support. + # + # `:keyfile` and `:certfile` expect an absolute path to the key + # and cert in disk or a relative path inside priv, for example + # "priv/ssl/server.key". For all supported SSL configuration + # options, see https://hexdocs.pm/plug/Plug.SSL.html#configure/1 + # + # We also recommend setting `force_ssl` in your config/prod.exs, + # ensuring no data is ever sent via http, always redirecting to https: + # + # config :telemetry_api, TelemetryApiWeb.Endpoint, + # force_ssl: [hsts: true] + # + # Check `Plug.SSL` for all available options in `force_ssl`. +end diff --git a/telemetry_api/config/test.exs b/telemetry_api/config/test.exs new file mode 100644 index 000000000..5916d25d5 --- /dev/null +++ b/telemetry_api/config/test.exs @@ -0,0 +1,27 @@ +import Config + +# Configure your database +# +# The MIX_TEST_PARTITION environment variable can be used +# to provide built-in test partitioning in CI environment. +# Run `mix help test` for more information. +config :telemetry_api, TelemetryApi.Repo, + username: "postgres", + password: "postgres", + hostname: "localhost", + database: "telemetry_api_test#{System.get_env("MIX_TEST_PARTITION")}", + pool: Ecto.Adapters.SQL.Sandbox, + pool_size: System.schedulers_online() * 2 + +# We don't run a server during test. If one is required, +# you can enable the server option below. +config :telemetry_api, TelemetryApiWeb.Endpoint, + http: [ip: {127, 0, 0, 1}, port: 4002], + secret_key_base: "oxlWGXR4lI6jsDZfizxmFwhPFn9vjc6rWqsdAnu5rlTmluTstw3/6YBkB5OGKi5m", + server: false + +# Print only warnings and errors during test +config :logger, level: :warning + +# Initialize plugs at runtime for faster test compilation +config :phoenix, :plug_init_mode, :runtime diff --git a/telemetry_api/lib/telemetry_api.ex b/telemetry_api/lib/telemetry_api.ex new file mode 100644 index 000000000..6d8157c74 --- /dev/null +++ b/telemetry_api/lib/telemetry_api.ex @@ -0,0 +1,9 @@ +defmodule TelemetryApi do + @moduledoc """ + TelemetryApi keeps the contexts that define your domain + and business logic. + + Contexts are also responsible for managing your data, regardless + if it comes from the database, an external API or others. + """ +end diff --git a/telemetry_api/lib/telemetry_api/application.ex b/telemetry_api/lib/telemetry_api/application.ex new file mode 100644 index 000000000..d1a065189 --- /dev/null +++ b/telemetry_api/lib/telemetry_api/application.ex @@ -0,0 +1,34 @@ +defmodule TelemetryApi.Application do + # See https://hexdocs.pm/elixir/Application.html + # for more information on OTP Applications + @moduledoc false + + use Application + + @impl true + def start(_type, _args) do + children = [ + TelemetryApiWeb.Telemetry, + TelemetryApi.Repo, + {DNSCluster, query: Application.get_env(:telemetry_api, :dns_cluster_query) || :ignore}, + {Phoenix.PubSub, name: TelemetryApi.PubSub}, + # Start a worker by calling: TelemetryApi.Worker.start_link(arg) + # {TelemetryApi.Worker, arg}, + # Start to serve requests, typically the last entry + TelemetryApiWeb.Endpoint + ] + + # See https://hexdocs.pm/elixir/Supervisor.html + # for other strategies and supported options + opts = [strategy: :one_for_one, name: TelemetryApi.Supervisor] + Supervisor.start_link(children, opts) + end + + # Tell Phoenix to update the endpoint configuration + # whenever the application is updated. + @impl true + def config_change(changed, _new, removed) do + TelemetryApiWeb.Endpoint.config_change(changed, removed) + :ok + end +end diff --git a/telemetry_api/lib/telemetry_api/operators.ex b/telemetry_api/lib/telemetry_api/operators.ex new file mode 100644 index 000000000..52a834ded --- /dev/null +++ b/telemetry_api/lib/telemetry_api/operators.ex @@ -0,0 +1,104 @@ +defmodule TelemetryApi.Operators do + @moduledoc """ + The Operators context. + """ + + import Ecto.Query, warn: false + alias TelemetryApi.Repo + + alias TelemetryApi.Operators.Operator + + @doc """ + Returns the list of operators. + + ## Examples + + iex> list_operators() + [%Operator{}, ...] + + """ + def list_operators do + Repo.all(Operator) + end + + @doc """ + Gets a single operator. + + Raises `Ecto.NoResultsError` if the Operator does not exist. + + ## Examples + + iex> get_operator!(123) + %Operator{} + + iex> get_operator!(456) + ** (Ecto.NoResultsError) + + """ + def get_operator!(id), do: Repo.get!(Operator, id) + + @doc """ + Creates a operator. + + ## Examples + + iex> create_operator(%{field: value}) + {:ok, %Operator{}} + + iex> create_operator(%{field: bad_value}) + {:error, %Ecto.Changeset{}} + + """ + def create_operator(attrs \\ %{}) do + %Operator{} + |> Operator.changeset(attrs) + |> Repo.insert() + end + + @doc """ + Updates a operator. + + ## Examples + + iex> update_operator(operator, %{field: new_value}) + {:ok, %Operator{}} + + iex> update_operator(operator, %{field: bad_value}) + {:error, %Ecto.Changeset{}} + + """ + def update_operator(%Operator{} = operator, attrs) do + operator + |> Operator.changeset(attrs) + |> Repo.update() + end + + @doc """ + Deletes a operator. + + ## Examples + + iex> delete_operator(operator) + {:ok, %Operator{}} + + iex> delete_operator(operator) + {:error, %Ecto.Changeset{}} + + """ + def delete_operator(%Operator{} = operator) do + Repo.delete(operator) + end + + @doc """ + Returns an `%Ecto.Changeset{}` for tracking operator changes. + + ## Examples + + iex> change_operator(operator) + %Ecto.Changeset{data: %Operator{}} + + """ + def change_operator(%Operator{} = operator, attrs \\ %{}) do + Operator.changeset(operator, attrs) + end +end diff --git a/telemetry_api/lib/telemetry_api/operators/operator.ex b/telemetry_api/lib/telemetry_api/operators/operator.ex new file mode 100644 index 000000000..4bdc7d195 --- /dev/null +++ b/telemetry_api/lib/telemetry_api/operators/operator.ex @@ -0,0 +1,18 @@ +defmodule TelemetryApi.Operators.Operator do + use Ecto.Schema + import Ecto.Changeset + + schema "operators" do + field :version, :string + field :address, :string + + timestamps(type: :utc_datetime) + end + + @doc false + def changeset(operator, attrs) do + operator + |> cast(attrs, [:address, :version]) + |> validate_required([:address, :version]) + end +end diff --git a/telemetry_api/lib/telemetry_api/repo.ex b/telemetry_api/lib/telemetry_api/repo.ex new file mode 100644 index 000000000..8f57bf72e --- /dev/null +++ b/telemetry_api/lib/telemetry_api/repo.ex @@ -0,0 +1,5 @@ +defmodule TelemetryApi.Repo do + use Ecto.Repo, + otp_app: :telemetry_api, + adapter: Ecto.Adapters.Postgres +end diff --git a/telemetry_api/lib/telemetry_api_web.ex b/telemetry_api/lib/telemetry_api_web.ex new file mode 100644 index 000000000..90b61b603 --- /dev/null +++ b/telemetry_api/lib/telemetry_api_web.ex @@ -0,0 +1,65 @@ +defmodule TelemetryApiWeb do + @moduledoc """ + The entrypoint for defining your web interface, such + as controllers, components, channels, and so on. + + This can be used in your application as: + + use TelemetryApiWeb, :controller + use TelemetryApiWeb, :html + + The definitions below will be executed for every controller, + component, etc, so keep them short and clean, focused + on imports, uses and aliases. + + Do NOT define functions inside the quoted expressions + below. Instead, define additional modules and import + those modules here. + """ + + def static_paths, do: ~w(assets fonts images favicon.ico robots.txt) + + def router do + quote do + use Phoenix.Router, helpers: false + + # Import common connection and controller functions to use in pipelines + import Plug.Conn + import Phoenix.Controller + end + end + + def channel do + quote do + use Phoenix.Channel + end + end + + def controller do + quote do + use Phoenix.Controller, + formats: [:html, :json], + layouts: [html: TelemetryApiWeb.Layouts] + + import Plug.Conn + + unquote(verified_routes()) + end + end + + def verified_routes do + quote do + use Phoenix.VerifiedRoutes, + endpoint: TelemetryApiWeb.Endpoint, + router: TelemetryApiWeb.Router, + statics: TelemetryApiWeb.static_paths() + end + end + + @doc """ + When used, dispatch to the appropriate controller/live_view/etc. + """ + defmacro __using__(which) when is_atom(which) do + apply(__MODULE__, which, []) + end +end diff --git a/telemetry_api/lib/telemetry_api_web/controllers/changeset_json.ex b/telemetry_api/lib/telemetry_api_web/controllers/changeset_json.ex new file mode 100644 index 000000000..5085846f9 --- /dev/null +++ b/telemetry_api/lib/telemetry_api_web/controllers/changeset_json.ex @@ -0,0 +1,25 @@ +defmodule TelemetryApiWeb.ChangesetJSON do + @doc """ + Renders changeset errors. + """ + def error(%{changeset: changeset}) do + # When encoded, the changeset returns its errors + # as a JSON object. So we just pass it forward. + %{errors: Ecto.Changeset.traverse_errors(changeset, &translate_error/1)} + end + + defp translate_error({msg, opts}) do + # You can make use of gettext to translate error messages by + # uncommenting and adjusting the following code: + + # if count = opts[:count] do + # Gettext.dngettext(TelemetryApiWeb.Gettext, "errors", msg, msg, count, opts) + # else + # Gettext.dgettext(TelemetryApiWeb.Gettext, "errors", msg, opts) + # end + + Enum.reduce(opts, msg, fn {key, value}, acc -> + String.replace(acc, "%{#{key}}", fn _ -> to_string(value) end) + end) + end +end diff --git a/telemetry_api/lib/telemetry_api_web/controllers/error_json.ex b/telemetry_api/lib/telemetry_api_web/controllers/error_json.ex new file mode 100644 index 000000000..6c619a972 --- /dev/null +++ b/telemetry_api/lib/telemetry_api_web/controllers/error_json.ex @@ -0,0 +1,21 @@ +defmodule TelemetryApiWeb.ErrorJSON do + @moduledoc """ + This module is invoked by your endpoint in case of errors on JSON requests. + + See config/config.exs. + """ + + # If you want to customize a particular status code, + # you may add your own clauses, such as: + # + # def render("500.json", _assigns) do + # %{errors: %{detail: "Internal Server Error"}} + # end + + # By default, Phoenix returns the status message from + # the template name. For example, "404.json" becomes + # "Not Found". + def render(template, _assigns) do + %{errors: %{detail: Phoenix.Controller.status_message_from_template(template)}} + end +end diff --git a/telemetry_api/lib/telemetry_api_web/controllers/fallback_controller.ex b/telemetry_api/lib/telemetry_api_web/controllers/fallback_controller.ex new file mode 100644 index 000000000..2b396181f --- /dev/null +++ b/telemetry_api/lib/telemetry_api_web/controllers/fallback_controller.ex @@ -0,0 +1,24 @@ +defmodule TelemetryApiWeb.FallbackController do + @moduledoc """ + Translates controller action results into valid `Plug.Conn` responses. + + See `Phoenix.Controller.action_fallback/1` for more details. + """ + use TelemetryApiWeb, :controller + + # This clause handles errors returned by Ecto's insert/update/delete. + def call(conn, {:error, %Ecto.Changeset{} = changeset}) do + conn + |> put_status(:unprocessable_entity) + |> put_view(json: TelemetryApiWeb.ChangesetJSON) + |> render(:error, changeset: changeset) + end + + # This clause is an example of how to handle resources that cannot be found. + def call(conn, {:error, :not_found}) do + conn + |> put_status(:not_found) + |> put_view(html: TelemetryApiWeb.ErrorHTML, json: TelemetryApiWeb.ErrorJSON) + |> render(:"404") + end +end diff --git a/telemetry_api/lib/telemetry_api_web/controllers/operator_controller.ex b/telemetry_api/lib/telemetry_api_web/controllers/operator_controller.ex new file mode 100644 index 000000000..cefb88ca4 --- /dev/null +++ b/telemetry_api/lib/telemetry_api_web/controllers/operator_controller.ex @@ -0,0 +1,43 @@ +defmodule TelemetryApiWeb.OperatorController do + use TelemetryApiWeb, :controller + + alias TelemetryApi.Operators + alias TelemetryApi.Operators.Operator + + action_fallback TelemetryApiWeb.FallbackController + + def index(conn, _params) do + operators = Operators.list_operators() + render(conn, :index, operators: operators) + end + + def create(conn, operator_params) do + with {:ok, %Operator{} = operator} <- Operators.create_operator(operator_params) do + conn + |> put_status(:created) + |> put_resp_header("location", ~p"/api/operators/#{operator}") + |> render(:show, operator: operator) + end + end + + def show(conn, %{"id" => id}) do + operator = Operators.get_operator!(id) + render(conn, :show, operator: operator) + end + + # def update(conn, %{"id" => id, "operator" => operator_params}) do + # operator = Operators.get_operator!(id) + + # with {:ok, %Operator{} = operator} <- Operators.update_operator(operator, operator_params) do + # render(conn, :show, operator: operator) + # end + # end + + # def delete(conn, %{"id" => id}) do + # operator = Operators.get_operator!(id) + + # with {:ok, %Operator{}} <- Operators.delete_operator(operator) do + # send_resp(conn, :no_content, "") + # end + # end +end diff --git a/telemetry_api/lib/telemetry_api_web/controllers/operator_json.ex b/telemetry_api/lib/telemetry_api_web/controllers/operator_json.ex new file mode 100644 index 000000000..5d0a27951 --- /dev/null +++ b/telemetry_api/lib/telemetry_api_web/controllers/operator_json.ex @@ -0,0 +1,25 @@ +defmodule TelemetryApiWeb.OperatorJSON do + alias TelemetryApi.Operators.Operator + + @doc """ + Renders a list of operators. + """ + def index(%{operators: operators}) do + for(operator <- operators, do: data(operator)) + end + + @doc """ + Renders a single operator. + """ + def show(%{operator: operator}) do + data(operator) + end + + defp data(%Operator{} = operator) do + %{ + id: operator.id, + address: operator.address, + version: operator.version + } + end +end diff --git a/telemetry_api/lib/telemetry_api_web/endpoint.ex b/telemetry_api/lib/telemetry_api_web/endpoint.ex new file mode 100644 index 000000000..861505826 --- /dev/null +++ b/telemetry_api/lib/telemetry_api_web/endpoint.ex @@ -0,0 +1,51 @@ +defmodule TelemetryApiWeb.Endpoint do + use Phoenix.Endpoint, otp_app: :telemetry_api + + # The session will be stored in the cookie and signed, + # this means its contents can be read but not tampered with. + # Set :encryption_salt if you would also like to encrypt it. + @session_options [ + store: :cookie, + key: "_telemetry_api_key", + signing_salt: "3K5HyxYk", + same_site: "Lax" + ] + + socket "/live", Phoenix.LiveView.Socket, + websocket: [connect_info: [session: @session_options]], + longpoll: [connect_info: [session: @session_options]] + + # Serve at "/" the static files from "priv/static" directory. + # + # You should set gzip to true if you are running phx.digest + # when deploying your static files in production. + plug Plug.Static, + at: "/", + from: :telemetry_api, + gzip: false, + only: TelemetryApiWeb.static_paths() + + # Code reloading can be explicitly enabled under the + # :code_reloader configuration of your endpoint. + if code_reloading? do + plug Phoenix.CodeReloader + plug Phoenix.Ecto.CheckRepoStatus, otp_app: :telemetry_api + end + + plug Phoenix.LiveDashboard.RequestLogger, + param_key: "request_logger", + cookie_key: "request_logger" + + plug Plug.RequestId + plug Plug.Telemetry, event_prefix: [:phoenix, :endpoint] + + plug Plug.Parsers, + parsers: [:urlencoded, :multipart, :json], + pass: ["*/*"], + json_decoder: Phoenix.json_library() + + plug Plug.MethodOverride + plug Plug.Head + plug Plug.Session, @session_options + plug TelemetryApiWeb.Router +end diff --git a/telemetry_api/lib/telemetry_api_web/router.ex b/telemetry_api/lib/telemetry_api_web/router.ex new file mode 100644 index 000000000..217982b11 --- /dev/null +++ b/telemetry_api/lib/telemetry_api_web/router.ex @@ -0,0 +1,28 @@ +defmodule TelemetryApiWeb.Router do + use TelemetryApiWeb, :router + + pipeline :api do + plug :accepts, ["json"] + end + + scope "/api", TelemetryApiWeb do + pipe_through :api + resources "/operators", OperatorController, only: [:index, :show, :create] + end + + # Enable LiveDashboard in development + if Application.compile_env(:telemetry_api, :dev_routes) do + # If you want to use the LiveDashboard in production, you should put + # it behind authentication and allow only admins to access it. + # If your application does not have an admins-only section yet, + # you can use Plug.BasicAuth to set up some basic authentication + # as long as you are also using SSL (which you should anyway). + import Phoenix.LiveDashboard.Router + + scope "/dev" do + pipe_through [:fetch_session, :protect_from_forgery] + + live_dashboard "/dashboard", metrics: TelemetryApiWeb.Telemetry + end + end +end diff --git a/telemetry_api/lib/telemetry_api_web/telemetry.ex b/telemetry_api/lib/telemetry_api_web/telemetry.ex new file mode 100644 index 000000000..b19a5a70c --- /dev/null +++ b/telemetry_api/lib/telemetry_api_web/telemetry.ex @@ -0,0 +1,92 @@ +defmodule TelemetryApiWeb.Telemetry do + use Supervisor + import Telemetry.Metrics + + def start_link(arg) do + Supervisor.start_link(__MODULE__, arg, name: __MODULE__) + end + + @impl true + def init(_arg) do + children = [ + # Telemetry poller will execute the given period measurements + # every 10_000ms. Learn more here: https://hexdocs.pm/telemetry_metrics + {:telemetry_poller, measurements: periodic_measurements(), period: 10_000} + # Add reporters as children of your supervision tree. + # {Telemetry.Metrics.ConsoleReporter, metrics: metrics()} + ] + + Supervisor.init(children, strategy: :one_for_one) + end + + def metrics do + [ + # Phoenix Metrics + summary("phoenix.endpoint.start.system_time", + unit: {:native, :millisecond} + ), + summary("phoenix.endpoint.stop.duration", + unit: {:native, :millisecond} + ), + summary("phoenix.router_dispatch.start.system_time", + tags: [:route], + unit: {:native, :millisecond} + ), + summary("phoenix.router_dispatch.exception.duration", + tags: [:route], + unit: {:native, :millisecond} + ), + summary("phoenix.router_dispatch.stop.duration", + tags: [:route], + unit: {:native, :millisecond} + ), + summary("phoenix.socket_connected.duration", + unit: {:native, :millisecond} + ), + summary("phoenix.channel_joined.duration", + unit: {:native, :millisecond} + ), + summary("phoenix.channel_handled_in.duration", + tags: [:event], + unit: {:native, :millisecond} + ), + + # Database Metrics + summary("telemetry_api.repo.query.total_time", + unit: {:native, :millisecond}, + description: "The sum of the other measurements" + ), + summary("telemetry_api.repo.query.decode_time", + unit: {:native, :millisecond}, + description: "The time spent decoding the data received from the database" + ), + summary("telemetry_api.repo.query.query_time", + unit: {:native, :millisecond}, + description: "The time spent executing the query" + ), + summary("telemetry_api.repo.query.queue_time", + unit: {:native, :millisecond}, + description: "The time spent waiting for a database connection" + ), + summary("telemetry_api.repo.query.idle_time", + unit: {:native, :millisecond}, + description: + "The time the connection spent waiting before being checked out for the query" + ), + + # VM Metrics + summary("vm.memory.total", unit: {:byte, :kilobyte}), + summary("vm.total_run_queue_lengths.total"), + summary("vm.total_run_queue_lengths.cpu"), + summary("vm.total_run_queue_lengths.io") + ] + end + + defp periodic_measurements do + [ + # A module, function and arguments to be invoked periodically. + # This function must call :telemetry.execute/3 and a metric must be added above. + # {TelemetryApiWeb, :count_users, []} + ] + end +end diff --git a/telemetry_api/mix.exs b/telemetry_api/mix.exs new file mode 100644 index 000000000..c78f7c5f2 --- /dev/null +++ b/telemetry_api/mix.exs @@ -0,0 +1,62 @@ +defmodule TelemetryApi.MixProject do + use Mix.Project + + def project do + [ + app: :telemetry_api, + version: "0.1.0", + elixir: "~> 1.14", + elixirc_paths: elixirc_paths(Mix.env()), + start_permanent: Mix.env() == :prod, + aliases: aliases(), + deps: deps() + ] + end + + # Configuration for the OTP application. + # + # Type `mix help compile.app` for more information. + def application do + [ + mod: {TelemetryApi.Application, []}, + extra_applications: [:logger, :runtime_tools] + ] + end + + # Specifies which paths to compile per environment. + defp elixirc_paths(:test), do: ["lib", "test/support"] + defp elixirc_paths(_), do: ["lib"] + + # Specifies your project dependencies. + # + # Type `mix help deps` for examples and options. + defp deps do + [ + {:phoenix, "~> 1.7.14"}, + {:phoenix_ecto, "~> 4.5"}, + {:ecto_sql, "~> 3.10"}, + {:postgrex, ">= 0.0.0"}, + {:phoenix_live_dashboard, "~> 0.8.3"}, + {:telemetry_metrics, "~> 1.0"}, + {:telemetry_poller, "~> 1.0"}, + {:jason, "~> 1.2"}, + {:dns_cluster, "~> 0.1.1"}, + {:bandit, "~> 1.5"} + ] + end + + # Aliases are shortcuts or tasks specific to the current project. + # For example, to install project dependencies and perform other setup tasks, run: + # + # $ mix setup + # + # See the documentation for `Mix` for more info on aliases. + defp aliases do + [ + setup: ["deps.get", "ecto.setup"], + "ecto.setup": ["ecto.create", "ecto.migrate", "run priv/repo/seeds.exs"], + "ecto.reset": ["ecto.drop", "ecto.setup"], + test: ["ecto.create --quiet", "ecto.migrate --quiet", "test"] + ] + end +end diff --git a/telemetry_api/mix.lock b/telemetry_api/mix.lock new file mode 100644 index 000000000..748eb9357 --- /dev/null +++ b/telemetry_api/mix.lock @@ -0,0 +1,28 @@ +%{ + "bandit": {:hex, :bandit, "1.5.7", "6856b1e1df4f2b0cb3df1377eab7891bec2da6a7fd69dc78594ad3e152363a50", [:mix], [{:hpax, "~> 1.0.0", [hex: :hpax, repo: "hexpm", optional: false]}, {:plug, "~> 1.14", [hex: :plug, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}, {:thousand_island, "~> 1.0", [hex: :thousand_island, repo: "hexpm", optional: false]}, {:websock, "~> 0.5", [hex: :websock, repo: "hexpm", optional: false]}], "hexpm", "f2dd92ae87d2cbea2fa9aa1652db157b6cba6c405cb44d4f6dd87abba41371cd"}, + "castore": {:hex, :castore, "1.0.8", "dedcf20ea746694647f883590b82d9e96014057aff1d44d03ec90f36a5c0dc6e", [:mix], [], "hexpm", "0b2b66d2ee742cb1d9cb8c8be3b43c3a70ee8651f37b75a8b982e036752983f1"}, + "db_connection": {:hex, :db_connection, "2.7.0", "b99faa9291bb09892c7da373bb82cba59aefa9b36300f6145c5f201c7adf48ec", [:mix], [{:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "dcf08f31b2701f857dfc787fbad78223d61a32204f217f15e881dd93e4bdd3ff"}, + "decimal": {:hex, :decimal, "2.1.1", "5611dca5d4b2c3dd497dec8f68751f1f1a54755e8ed2a966c2633cf885973ad6", [:mix], [], "hexpm", "53cfe5f497ed0e7771ae1a475575603d77425099ba5faef9394932b35020ffcc"}, + "dns_cluster": {:hex, :dns_cluster, "0.1.3", "0bc20a2c88ed6cc494f2964075c359f8c2d00e1bf25518a6a6c7fd277c9b0c66", [:mix], [], "hexpm", "46cb7c4a1b3e52c7ad4cbe33ca5079fbde4840dedeafca2baf77996c2da1bc33"}, + "ecto": {:hex, :ecto, "3.12.3", "1a9111560731f6c3606924c81c870a68a34c819f6d4f03822f370ea31a582208", [:mix], [{:decimal, "~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "9efd91506ae722f95e48dc49e70d0cb632ede3b7a23896252a60a14ac6d59165"}, + "ecto_sql": {:hex, :ecto_sql, "3.12.0", "73cea17edfa54bde76ee8561b30d29ea08f630959685006d9c6e7d1e59113b7d", [:mix], [{:db_connection, "~> 2.4.1 or ~> 2.5", [hex: :db_connection, repo: "hexpm", optional: false]}, {:ecto, "~> 3.12", [hex: :ecto, repo: "hexpm", optional: false]}, {:myxql, "~> 0.7", [hex: :myxql, repo: "hexpm", optional: true]}, {:postgrex, "~> 0.19 or ~> 1.0", [hex: :postgrex, repo: "hexpm", optional: true]}, {:tds, "~> 2.1.1 or ~> 2.2", [hex: :tds, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4.0 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "dc9e4d206f274f3947e96142a8fdc5f69a2a6a9abb4649ef5c882323b6d512f0"}, + "hpax": {:hex, :hpax, "1.0.0", "28dcf54509fe2152a3d040e4e3df5b265dcb6cb532029ecbacf4ce52caea3fd2", [:mix], [], "hexpm", "7f1314731d711e2ca5fdc7fd361296593fc2542570b3105595bb0bc6d0fad601"}, + "jason": {:hex, :jason, "1.4.4", "b9226785a9aa77b6857ca22832cffa5d5011a667207eb2a0ad56adb5db443b8a", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "c5eb0cab91f094599f94d55bc63409236a8ec69a21a67814529e8d5f6cc90b3b"}, + "mime": {:hex, :mime, "2.0.6", "8f18486773d9b15f95f4f4f1e39b710045fa1de891fada4516559967276e4dc2", [:mix], [], "hexpm", "c9945363a6b26d747389aac3643f8e0e09d30499a138ad64fe8fd1d13d9b153e"}, + "phoenix": {:hex, :phoenix, "1.7.14", "a7d0b3f1bc95987044ddada111e77bd7f75646a08518942c72a8440278ae7825", [:mix], [{:castore, ">= 0.0.0", [hex: :castore, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:phoenix_pubsub, "~> 2.1", [hex: :phoenix_pubsub, repo: "hexpm", optional: false]}, {:phoenix_template, "~> 1.0", [hex: :phoenix_template, repo: "hexpm", optional: false]}, {:phoenix_view, "~> 2.0", [hex: :phoenix_view, repo: "hexpm", optional: true]}, {:plug, "~> 1.14", [hex: :plug, repo: "hexpm", optional: false]}, {:plug_cowboy, "~> 2.7", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:plug_crypto, "~> 1.2 or ~> 2.0", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}, {:websock_adapter, "~> 0.5.3", [hex: :websock_adapter, repo: "hexpm", optional: false]}], "hexpm", "c7859bc56cc5dfef19ecfc240775dae358cbaa530231118a9e014df392ace61a"}, + "phoenix_ecto": {:hex, :phoenix_ecto, "4.6.2", "3b83b24ab5a2eb071a20372f740d7118767c272db386831b2e77638c4dcc606d", [:mix], [{:ecto, "~> 3.5", [hex: :ecto, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 2.14.2 or ~> 3.0 or ~> 4.1", [hex: :phoenix_html, repo: "hexpm", optional: true]}, {:plug, "~> 1.9", [hex: :plug, repo: "hexpm", optional: false]}, {:postgrex, "~> 0.16 or ~> 1.0", [hex: :postgrex, repo: "hexpm", optional: true]}], "hexpm", "3f94d025f59de86be00f5f8c5dd7b5965a3298458d21ab1c328488be3b5fcd59"}, + "phoenix_html": {:hex, :phoenix_html, "4.1.1", "4c064fd3873d12ebb1388425a8f2a19348cef56e7289e1998e2d2fa758aa982e", [:mix], [], "hexpm", "f2f2df5a72bc9a2f510b21497fd7d2b86d932ec0598f0210fed4114adc546c6f"}, + "phoenix_live_dashboard": {:hex, :phoenix_live_dashboard, "0.8.4", "4508e481f791ce62ec6a096e13b061387158cbeefacca68c6c1928e1305e23ed", [:mix], [{:ecto, "~> 3.6.2 or ~> 3.7", [hex: :ecto, repo: "hexpm", optional: true]}, {:ecto_mysql_extras, "~> 0.5", [hex: :ecto_mysql_extras, repo: "hexpm", optional: true]}, {:ecto_psql_extras, "~> 0.7", [hex: :ecto_psql_extras, repo: "hexpm", optional: true]}, {:ecto_sqlite3_extras, "~> 1.1.7 or ~> 1.2.0", [hex: :ecto_sqlite3_extras, repo: "hexpm", optional: true]}, {:mime, "~> 1.6 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:phoenix_live_view, "~> 0.19 or ~> 1.0", [hex: :phoenix_live_view, repo: "hexpm", optional: false]}, {:telemetry_metrics, "~> 0.6 or ~> 1.0", [hex: :telemetry_metrics, repo: "hexpm", optional: false]}], "hexpm", "2984aae96994fbc5c61795a73b8fb58153b41ff934019cfb522343d2d3817d59"}, + "phoenix_live_view": {:hex, :phoenix_live_view, "0.20.17", "f396bbdaf4ba227b82251eb75ac0afa6b3da5e509bc0d030206374237dfc9450", [:mix], [{:floki, "~> 0.36", [hex: :floki, repo: "hexpm", optional: true]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:phoenix, "~> 1.6.15 or ~> 1.7.0", [hex: :phoenix, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 3.3 or ~> 4.0", [hex: :phoenix_html, repo: "hexpm", optional: false]}, {:phoenix_template, "~> 1.0", [hex: :phoenix_template, repo: "hexpm", optional: false]}, {:phoenix_view, "~> 2.0", [hex: :phoenix_view, repo: "hexpm", optional: true]}, {:plug, "~> 1.15", [hex: :plug, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4.2 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "a61d741ffb78c85fdbca0de084da6a48f8ceb5261a79165b5a0b59e5f65ce98b"}, + "phoenix_pubsub": {:hex, :phoenix_pubsub, "2.1.3", "3168d78ba41835aecad272d5e8cd51aa87a7ac9eb836eabc42f6e57538e3731d", [:mix], [], "hexpm", "bba06bc1dcfd8cb086759f0edc94a8ba2bc8896d5331a1e2c2902bf8e36ee502"}, + "phoenix_template": {:hex, :phoenix_template, "1.0.4", "e2092c132f3b5e5b2d49c96695342eb36d0ed514c5b252a77048d5969330d639", [:mix], [{:phoenix_html, "~> 2.14.2 or ~> 3.0 or ~> 4.0", [hex: :phoenix_html, repo: "hexpm", optional: true]}], "hexpm", "2c0c81f0e5c6753faf5cca2f229c9709919aba34fab866d3bc05060c9c444206"}, + "plug": {:hex, :plug, "1.16.1", "40c74619c12f82736d2214557dedec2e9762029b2438d6d175c5074c933edc9d", [:mix], [{:mime, "~> 1.0 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:plug_crypto, "~> 1.1.1 or ~> 1.2 or ~> 2.0", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4.3 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "a13ff6b9006b03d7e33874945b2755253841b238c34071ed85b0e86057f8cddc"}, + "plug_crypto": {:hex, :plug_crypto, "2.1.0", "f44309c2b06d249c27c8d3f65cfe08158ade08418cf540fd4f72d4d6863abb7b", [:mix], [], "hexpm", "131216a4b030b8f8ce0f26038bc4421ae60e4bb95c5cf5395e1421437824c4fa"}, + "postgrex": {:hex, :postgrex, "0.19.1", "73b498508b69aded53907fe48a1fee811be34cc720e69ef4ccd568c8715495ea", [:mix], [{:db_connection, "~> 2.1", [hex: :db_connection, repo: "hexpm", optional: false]}, {:decimal, "~> 1.5 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:table, "~> 0.1.0", [hex: :table, repo: "hexpm", optional: true]}], "hexpm", "8bac7885a18f381e091ec6caf41bda7bb8c77912bb0e9285212829afe5d8a8f8"}, + "telemetry": {:hex, :telemetry, "1.3.0", "fedebbae410d715cf8e7062c96a1ef32ec22e764197f70cda73d82778d61e7a2", [:rebar3], [], "hexpm", "7015fc8919dbe63764f4b4b87a95b7c0996bd539e0d499be6ec9d7f3875b79e6"}, + "telemetry_metrics": {:hex, :telemetry_metrics, "1.0.0", "29f5f84991ca98b8eb02fc208b2e6de7c95f8bb2294ef244a176675adc7775df", [:mix], [{:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "f23713b3847286a534e005126d4c959ebcca68ae9582118ce436b521d1d47d5d"}, + "telemetry_poller": {:hex, :telemetry_poller, "1.1.0", "58fa7c216257291caaf8d05678c8d01bd45f4bdbc1286838a28c4bb62ef32999", [:rebar3], [{:telemetry, "~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "9eb9d9cbfd81cbd7cdd24682f8711b6e2b691289a0de6826e58452f28c103c8f"}, + "thousand_island": {:hex, :thousand_island, "1.3.5", "6022b6338f1635b3d32406ff98d68b843ba73b3aa95cfc27154223244f3a6ca5", [:mix], [{:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "2be6954916fdfe4756af3239fb6b6d75d0b8063b5df03ba76fd8a4c87849e180"}, + "websock": {:hex, :websock, "0.5.3", "2f69a6ebe810328555b6fe5c831a851f485e303a7c8ce6c5f675abeb20ebdadc", [:mix], [], "hexpm", "6105453d7fac22c712ad66fab1d45abdf049868f253cf719b625151460b8b453"}, + "websock_adapter": {:hex, :websock_adapter, "0.5.7", "65fa74042530064ef0570b75b43f5c49bb8b235d6515671b3d250022cb8a1f9e", [:mix], [{:bandit, ">= 0.6.0", [hex: :bandit, repo: "hexpm", optional: true]}, {:plug, "~> 1.14", [hex: :plug, repo: "hexpm", optional: false]}, {:plug_cowboy, "~> 2.6", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:websock, "~> 0.5", [hex: :websock, repo: "hexpm", optional: false]}], "hexpm", "d0f478ee64deddfec64b800673fd6e0c8888b079d9f3444dd96d2a98383bdbd1"}, +} diff --git a/telemetry_api/priv/repo/migrations/.formatter.exs b/telemetry_api/priv/repo/migrations/.formatter.exs new file mode 100644 index 000000000..49f9151ed --- /dev/null +++ b/telemetry_api/priv/repo/migrations/.formatter.exs @@ -0,0 +1,4 @@ +[ + import_deps: [:ecto_sql], + inputs: ["*.exs"] +] diff --git a/telemetry_api/priv/repo/migrations/20240917212329_create_operators.exs b/telemetry_api/priv/repo/migrations/20240917212329_create_operators.exs new file mode 100644 index 000000000..3c1e5bbb1 --- /dev/null +++ b/telemetry_api/priv/repo/migrations/20240917212329_create_operators.exs @@ -0,0 +1,12 @@ +defmodule TelemetryApi.Repo.Migrations.CreateOperators do + use Ecto.Migration + + def change do + create table(:operators) do + add :address, :string + add :version, :string + + timestamps(type: :utc_datetime) + end + end +end diff --git a/telemetry_api/priv/repo/seeds.exs b/telemetry_api/priv/repo/seeds.exs new file mode 100644 index 000000000..7b50b07e1 --- /dev/null +++ b/telemetry_api/priv/repo/seeds.exs @@ -0,0 +1,11 @@ +# Script for populating the database. You can run it as: +# +# mix run priv/repo/seeds.exs +# +# Inside the script, you can read and write to any of your +# repositories directly: +# +# TelemetryApi.Repo.insert!(%TelemetryApi.SomeSchema{}) +# +# We recommend using the bang functions (`insert!`, `update!` +# and so on) as they will fail if something goes wrong. diff --git a/telemetry_api/priv/static/favicon.ico b/telemetry_api/priv/static/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..7f372bfc21cdd8cb47585339d5fa4d9dd424402f GIT binary patch literal 152 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7TyC=@t!V@Ar*{oFEH`~d50E!_s``s q?{G*w(7?#d#v@^nKnY_HKaYb01EZMZjMqTJ89ZJ6T-G@yGywoKK_h|y literal 0 HcmV?d00001 diff --git a/telemetry_api/priv/static/robots.txt b/telemetry_api/priv/static/robots.txt new file mode 100644 index 000000000..26e06b5f1 --- /dev/null +++ b/telemetry_api/priv/static/robots.txt @@ -0,0 +1,5 @@ +# See https://www.robotstxt.org/robotstxt.html for documentation on how to use the robots.txt file +# +# To ban all spiders from the entire site uncomment the next two lines: +# User-agent: * +# Disallow: / diff --git a/telemetry_api/test/support/conn_case.ex b/telemetry_api/test/support/conn_case.ex new file mode 100644 index 000000000..b51e7f0e0 --- /dev/null +++ b/telemetry_api/test/support/conn_case.ex @@ -0,0 +1,38 @@ +defmodule TelemetryApiWeb.ConnCase do + @moduledoc """ + This module defines the test case to be used by + tests that require setting up a connection. + + Such tests rely on `Phoenix.ConnTest` and also + import other functionality to make it easier + to build common data structures and query the data layer. + + Finally, if the test case interacts with the database, + we enable the SQL sandbox, so changes done to the database + are reverted at the end of every test. If you are using + PostgreSQL, you can even run database tests asynchronously + by setting `use TelemetryApiWeb.ConnCase, async: true`, although + this option is not recommended for other databases. + """ + + use ExUnit.CaseTemplate + + using do + quote do + # The default endpoint for testing + @endpoint TelemetryApiWeb.Endpoint + + use TelemetryApiWeb, :verified_routes + + # Import conveniences for testing with connections + import Plug.Conn + import Phoenix.ConnTest + import TelemetryApiWeb.ConnCase + end + end + + setup tags do + TelemetryApi.DataCase.setup_sandbox(tags) + {:ok, conn: Phoenix.ConnTest.build_conn()} + end +end diff --git a/telemetry_api/test/support/data_case.ex b/telemetry_api/test/support/data_case.ex new file mode 100644 index 000000000..7a30b5a25 --- /dev/null +++ b/telemetry_api/test/support/data_case.ex @@ -0,0 +1,58 @@ +defmodule TelemetryApi.DataCase do + @moduledoc """ + This module defines the setup for tests requiring + access to the application's data layer. + + You may define functions here to be used as helpers in + your tests. + + Finally, if the test case interacts with the database, + we enable the SQL sandbox, so changes done to the database + are reverted at the end of every test. If you are using + PostgreSQL, you can even run database tests asynchronously + by setting `use TelemetryApi.DataCase, async: true`, although + this option is not recommended for other databases. + """ + + use ExUnit.CaseTemplate + + using do + quote do + alias TelemetryApi.Repo + + import Ecto + import Ecto.Changeset + import Ecto.Query + import TelemetryApi.DataCase + end + end + + setup tags do + TelemetryApi.DataCase.setup_sandbox(tags) + :ok + end + + @doc """ + Sets up the sandbox based on the test tags. + """ + def setup_sandbox(tags) do + pid = Ecto.Adapters.SQL.Sandbox.start_owner!(TelemetryApi.Repo, shared: not tags[:async]) + on_exit(fn -> Ecto.Adapters.SQL.Sandbox.stop_owner(pid) end) + end + + @doc """ + A helper that transforms changeset errors into a map of messages. + + assert {:error, changeset} = Accounts.create_user(%{password: "short"}) + assert "password is too short" in errors_on(changeset).password + assert %{password: ["password is too short"]} = errors_on(changeset) + + """ + def errors_on(changeset) do + Ecto.Changeset.traverse_errors(changeset, fn {message, opts} -> + Regex.replace(~r"%{(\w+)}", message, fn _, key -> + opts |> Keyword.get(String.to_existing_atom(key), key) |> to_string() + end) + end) + end +end diff --git a/telemetry_api/test/support/fixtures/urls_fixtures.ex b/telemetry_api/test/support/fixtures/urls_fixtures.ex new file mode 100644 index 000000000..f94b63845 --- /dev/null +++ b/telemetry_api/test/support/fixtures/urls_fixtures.ex @@ -0,0 +1,21 @@ +defmodule TelemetryApi.UrlsFixtures do + @moduledoc """ + This module defines test helpers for creating + entities via the `TelemetryApi.Urls` context. + """ + + @doc """ + Generate a operator. + """ + def operator_fixture(attrs \\ %{}) do + {:ok, operator} = + attrs + |> Enum.into(%{ + address: "some address", + version: "some version" + }) + |> TelemetryApi.Urls.create_operator() + + operator + end +end diff --git a/telemetry_api/test/telemetry_api/urls_test.exs b/telemetry_api/test/telemetry_api/urls_test.exs new file mode 100644 index 000000000..618f10f85 --- /dev/null +++ b/telemetry_api/test/telemetry_api/urls_test.exs @@ -0,0 +1,61 @@ +defmodule TelemetryApi.UrlsTest do + use TelemetryApi.DataCase + + alias TelemetryApi.Urls + + describe "operators" do + alias TelemetryApi.Urls.Operator + + import TelemetryApi.UrlsFixtures + + @invalid_attrs %{version: nil, address: nil} + + test "list_operators/0 returns all operators" do + operator = operator_fixture() + assert Urls.list_operators() == [operator] + end + + test "get_operator!/1 returns the operator with given id" do + operator = operator_fixture() + assert Urls.get_operator!(operator.id) == operator + end + + test "create_operator/1 with valid data creates a operator" do + valid_attrs = %{version: "some version", address: "some address"} + + assert {:ok, %Operator{} = operator} = Urls.create_operator(valid_attrs) + assert operator.version == "some version" + assert operator.address == "some address" + end + + test "create_operator/1 with invalid data returns error changeset" do + assert {:error, %Ecto.Changeset{}} = Urls.create_operator(@invalid_attrs) + end + + test "update_operator/2 with valid data updates the operator" do + operator = operator_fixture() + update_attrs = %{version: "some updated version", address: "some updated address"} + + assert {:ok, %Operator{} = operator} = Urls.update_operator(operator, update_attrs) + assert operator.version == "some updated version" + assert operator.address == "some updated address" + end + + test "update_operator/2 with invalid data returns error changeset" do + operator = operator_fixture() + assert {:error, %Ecto.Changeset{}} = Urls.update_operator(operator, @invalid_attrs) + assert operator == Urls.get_operator!(operator.id) + end + + test "delete_operator/1 deletes the operator" do + operator = operator_fixture() + assert {:ok, %Operator{}} = Urls.delete_operator(operator) + assert_raise Ecto.NoResultsError, fn -> Urls.get_operator!(operator.id) end + end + + test "change_operator/1 returns a operator changeset" do + operator = operator_fixture() + assert %Ecto.Changeset{} = Urls.change_operator(operator) + end + end +end diff --git a/telemetry_api/test/telemetry_api_web/controllers/error_json_test.exs b/telemetry_api/test/telemetry_api_web/controllers/error_json_test.exs new file mode 100644 index 000000000..5cb349fdc --- /dev/null +++ b/telemetry_api/test/telemetry_api_web/controllers/error_json_test.exs @@ -0,0 +1,12 @@ +defmodule TelemetryApiWeb.ErrorJSONTest do + use TelemetryApiWeb.ConnCase, async: true + + test "renders 404" do + assert TelemetryApiWeb.ErrorJSON.render("404.json", %{}) == %{errors: %{detail: "Not Found"}} + end + + test "renders 500" do + assert TelemetryApiWeb.ErrorJSON.render("500.json", %{}) == + %{errors: %{detail: "Internal Server Error"}} + end +end diff --git a/telemetry_api/test/telemetry_api_web/controllers/operator_controller_test.exs b/telemetry_api/test/telemetry_api_web/controllers/operator_controller_test.exs new file mode 100644 index 000000000..bcb8b8082 --- /dev/null +++ b/telemetry_api/test/telemetry_api_web/controllers/operator_controller_test.exs @@ -0,0 +1,88 @@ +defmodule TelemetryApiWeb.OperatorControllerTest do + use TelemetryApiWeb.ConnCase + + import TelemetryApi.UrlsFixtures + + alias TelemetryApi.Urls.Operator + + @create_attrs %{ + version: "some version", + address: "some address" + } + @update_attrs %{ + version: "some updated version", + address: "some updated address" + } + @invalid_attrs %{version: nil, address: nil} + + setup %{conn: conn} do + {:ok, conn: put_req_header(conn, "accept", "application/json")} + end + + describe "index" do + test "lists all operators", %{conn: conn} do + conn = get(conn, ~p"/api/operators") + assert json_response(conn, 200)["data"] == [] + end + end + + describe "create operator" do + test "renders operator when data is valid", %{conn: conn} do + conn = post(conn, ~p"/api/operators", operator: @create_attrs) + assert %{"id" => id} = json_response(conn, 201)["data"] + + conn = get(conn, ~p"/api/operators/#{id}") + + assert %{ + "id" => ^id, + "address" => "some address", + "version" => "some version" + } = json_response(conn, 200)["data"] + end + + test "renders errors when data is invalid", %{conn: conn} do + conn = post(conn, ~p"/api/operators", operator: @invalid_attrs) + assert json_response(conn, 422)["errors"] != %{} + end + end + + describe "update operator" do + setup [:create_operator] + + test "renders operator when data is valid", %{conn: conn, operator: %Operator{id: id} = operator} do + conn = put(conn, ~p"/api/operators/#{operator}", operator: @update_attrs) + assert %{"id" => ^id} = json_response(conn, 200)["data"] + + conn = get(conn, ~p"/api/operators/#{id}") + + assert %{ + "id" => ^id, + "address" => "some updated address", + "version" => "some updated version" + } = json_response(conn, 200)["data"] + end + + test "renders errors when data is invalid", %{conn: conn, operator: operator} do + conn = put(conn, ~p"/api/operators/#{operator}", operator: @invalid_attrs) + assert json_response(conn, 422)["errors"] != %{} + end + end + + describe "delete operator" do + setup [:create_operator] + + test "deletes chosen operator", %{conn: conn, operator: operator} do + conn = delete(conn, ~p"/api/operators/#{operator}") + assert response(conn, 204) + + assert_error_sent 404, fn -> + get(conn, ~p"/api/operators/#{operator}") + end + end + end + + defp create_operator(_) do + operator = operator_fixture() + %{operator: operator} + end +end diff --git a/telemetry_api/test/test_helper.exs b/telemetry_api/test/test_helper.exs new file mode 100644 index 000000000..a354f9030 --- /dev/null +++ b/telemetry_api/test/test_helper.exs @@ -0,0 +1,2 @@ +ExUnit.start() +Ecto.Adapters.SQL.Sandbox.mode(TelemetryApi.Repo, :manual) From 4bd1025206abdac67f01b3fd56d8a84db934a7cf Mon Sep 17 00:00:00 2001 From: JuArce <52429267+JuArce@users.noreply.github.com> Date: Wed, 18 Sep 2024 17:58:50 -0300 Subject: [PATCH 02/55] chore: verify signature from operator --- telemetry_api/lib/telemetry_api/operators.ex | 3 ++ .../lib/telemetry_api/signature_verifier.ex | 48 +++++++++++++++++++ telemetry_api/mix.exs | 4 +- telemetry_api/mix.lock | 5 ++ 4 files changed, 59 insertions(+), 1 deletion(-) create mode 100644 telemetry_api/lib/telemetry_api/signature_verifier.ex diff --git a/telemetry_api/lib/telemetry_api/operators.ex b/telemetry_api/lib/telemetry_api/operators.ex index 52a834ded..732dace23 100644 --- a/telemetry_api/lib/telemetry_api/operators.ex +++ b/telemetry_api/lib/telemetry_api/operators.ex @@ -50,6 +50,9 @@ defmodule TelemetryApi.Operators do """ def create_operator(attrs \\ %{}) do + # Get address from the signature + address = SignatureVerifier.get_address(attrs["version"], attrs["signature"]) + attrs = Map.put(attrs, "address", address) %Operator{} |> Operator.changeset(attrs) |> Repo.insert() diff --git a/telemetry_api/lib/telemetry_api/signature_verifier.ex b/telemetry_api/lib/telemetry_api/signature_verifier.ex new file mode 100644 index 000000000..645be1316 --- /dev/null +++ b/telemetry_api/lib/telemetry_api/signature_verifier.ex @@ -0,0 +1,48 @@ +defmodule SignatureVerifier do + alias ExSecp256k1 + alias ExKeccak + alias :binary, as: Binary + + # Hash the version string using Keccak256 + def hash_version(version) do + version + |> ExKeccak.hash_256() + end + + # Recover the public key from the signature and hashed version + defp recover_public_key(hash, signature, recovery_id) do + case ExSecp256k1.recover_compact(hash, signature, recovery_id) do + {:ok, public_key} -> public_key + _error -> {:error, "Failed to recover public key"} + end + end + + # Convert public key to Ethereum-like address + def public_key_to_address(public_key) do + # Remove the first byte (which is 0x04 for uncompressed public keys) + public_key = binary_part(public_key, 1, 64) + + # Hash the public key with Keccak256 + public_key_hash = ExKeccak.hash_256(public_key) + + # Get the last 20 bytes (Ethereum address format) + <<_::binary-size(12), address::binary-size(20)>> = public_key_hash + address + end + + # Main function to get the address from the version and signature + def get_address(version, signature) do + version_hash = hash_version(version) + {:ok, binary_signature} = Base.decode64(signature) + byte_size = byte_size(binary_signature) + IO.inspect(byte_size) + # r<>s is 64 bytes. Get r and s from the signature + rs = binary_part(binary_signature, 0, byte_size - 1) + # v is the last byte of the signature + recovery_id = Binary.decode_unsigned(binary_part(binary_signature, byte_size - 1, 1)) + IO.inspect(recovery_id) + recover_public_key(version_hash, rs, recovery_id) + |> public_key_to_address() + |> Base.encode16() + end +end diff --git a/telemetry_api/mix.exs b/telemetry_api/mix.exs index c78f7c5f2..071dea16b 100644 --- a/telemetry_api/mix.exs +++ b/telemetry_api/mix.exs @@ -41,7 +41,9 @@ defmodule TelemetryApi.MixProject do {:telemetry_poller, "~> 1.0"}, {:jason, "~> 1.2"}, {:dns_cluster, "~> 0.1.1"}, - {:bandit, "~> 1.5"} + {:bandit, "~> 1.5"}, + {:ex_keccak, "~> 0.7.5"}, + {:ex_secp256k1, "~> 0.7"}, ] end diff --git a/telemetry_api/mix.lock b/telemetry_api/mix.lock index 748eb9357..b3c2fe97c 100644 --- a/telemetry_api/mix.lock +++ b/telemetry_api/mix.lock @@ -6,9 +6,13 @@ "dns_cluster": {:hex, :dns_cluster, "0.1.3", "0bc20a2c88ed6cc494f2964075c359f8c2d00e1bf25518a6a6c7fd277c9b0c66", [:mix], [], "hexpm", "46cb7c4a1b3e52c7ad4cbe33ca5079fbde4840dedeafca2baf77996c2da1bc33"}, "ecto": {:hex, :ecto, "3.12.3", "1a9111560731f6c3606924c81c870a68a34c819f6d4f03822f370ea31a582208", [:mix], [{:decimal, "~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "9efd91506ae722f95e48dc49e70d0cb632ede3b7a23896252a60a14ac6d59165"}, "ecto_sql": {:hex, :ecto_sql, "3.12.0", "73cea17edfa54bde76ee8561b30d29ea08f630959685006d9c6e7d1e59113b7d", [:mix], [{:db_connection, "~> 2.4.1 or ~> 2.5", [hex: :db_connection, repo: "hexpm", optional: false]}, {:ecto, "~> 3.12", [hex: :ecto, repo: "hexpm", optional: false]}, {:myxql, "~> 0.7", [hex: :myxql, repo: "hexpm", optional: true]}, {:postgrex, "~> 0.19 or ~> 1.0", [hex: :postgrex, repo: "hexpm", optional: true]}, {:tds, "~> 2.1.1 or ~> 2.2", [hex: :tds, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4.0 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "dc9e4d206f274f3947e96142a8fdc5f69a2a6a9abb4649ef5c882323b6d512f0"}, + "ex_keccak": {:hex, :ex_keccak, "0.7.5", "f3b733173510d48ae9a1ea1de415e694b2651f35c787e63f33b5ed0013fbfd35", [:mix], [{:rustler, ">= 0.0.0", [hex: :rustler, repo: "hexpm", optional: true]}, {:rustler_precompiled, "~> 0.7", [hex: :rustler_precompiled, repo: "hexpm", optional: false]}], "hexpm", "8a5e1cb7f96fff5e480ff6a121477b90c4fd8c150984086dffd98819f5d83763"}, + "ex_secp256k1": {:hex, :ex_secp256k1, "0.7.3", "489b6fd57fab5a7259ace927d8cb5171aad835e9c7279c2a859a0483cb069415", [:mix], [{:rustler, ">= 0.0.0", [hex: :rustler, repo: "hexpm", optional: true]}, {:rustler_precompiled, "~> 0.7", [hex: :rustler_precompiled, repo: "hexpm", optional: false]}], "hexpm", "ea63159442f4d8143166cd1507da03edc43216d6e7c6bac4b416bdce04f0daa8"}, "hpax": {:hex, :hpax, "1.0.0", "28dcf54509fe2152a3d040e4e3df5b265dcb6cb532029ecbacf4ce52caea3fd2", [:mix], [], "hexpm", "7f1314731d711e2ca5fdc7fd361296593fc2542570b3105595bb0bc6d0fad601"}, "jason": {:hex, :jason, "1.4.4", "b9226785a9aa77b6857ca22832cffa5d5011a667207eb2a0ad56adb5db443b8a", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "c5eb0cab91f094599f94d55bc63409236a8ec69a21a67814529e8d5f6cc90b3b"}, + "libsecp256k1": {:hex, :libsecp256k1, "0.1.9", "e725f31364cda7b554d56ce2bb976241303dde5ffd1ad59598513297bf1f2af6", [:make, :mix], [{:mix_erlang_tasks, "0.1.0", [hex: :mix_erlang_tasks, repo: "hexpm", optional: false]}], "hexpm", "93da7c29e892db4d59f7ed394decb6f9c5d653deb88e183a9221e5cc5ca4b987"}, "mime": {:hex, :mime, "2.0.6", "8f18486773d9b15f95f4f4f1e39b710045fa1de891fada4516559967276e4dc2", [:mix], [], "hexpm", "c9945363a6b26d747389aac3643f8e0e09d30499a138ad64fe8fd1d13d9b153e"}, + "mix_erlang_tasks": {:hex, :mix_erlang_tasks, "0.1.0", "36819fec60b80689eb1380938675af215565a89320a9e29c72c70d97512e4649", [:mix], [], "hexpm", "95d2839c422c482a70c08a8702da8242f86b773f8ab6e8602a4eb72da8da04ed"}, "phoenix": {:hex, :phoenix, "1.7.14", "a7d0b3f1bc95987044ddada111e77bd7f75646a08518942c72a8440278ae7825", [:mix], [{:castore, ">= 0.0.0", [hex: :castore, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:phoenix_pubsub, "~> 2.1", [hex: :phoenix_pubsub, repo: "hexpm", optional: false]}, {:phoenix_template, "~> 1.0", [hex: :phoenix_template, repo: "hexpm", optional: false]}, {:phoenix_view, "~> 2.0", [hex: :phoenix_view, repo: "hexpm", optional: true]}, {:plug, "~> 1.14", [hex: :plug, repo: "hexpm", optional: false]}, {:plug_cowboy, "~> 2.7", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:plug_crypto, "~> 1.2 or ~> 2.0", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}, {:websock_adapter, "~> 0.5.3", [hex: :websock_adapter, repo: "hexpm", optional: false]}], "hexpm", "c7859bc56cc5dfef19ecfc240775dae358cbaa530231118a9e014df392ace61a"}, "phoenix_ecto": {:hex, :phoenix_ecto, "4.6.2", "3b83b24ab5a2eb071a20372f740d7118767c272db386831b2e77638c4dcc606d", [:mix], [{:ecto, "~> 3.5", [hex: :ecto, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 2.14.2 or ~> 3.0 or ~> 4.1", [hex: :phoenix_html, repo: "hexpm", optional: true]}, {:plug, "~> 1.9", [hex: :plug, repo: "hexpm", optional: false]}, {:postgrex, "~> 0.16 or ~> 1.0", [hex: :postgrex, repo: "hexpm", optional: true]}], "hexpm", "3f94d025f59de86be00f5f8c5dd7b5965a3298458d21ab1c328488be3b5fcd59"}, "phoenix_html": {:hex, :phoenix_html, "4.1.1", "4c064fd3873d12ebb1388425a8f2a19348cef56e7289e1998e2d2fa758aa982e", [:mix], [], "hexpm", "f2f2df5a72bc9a2f510b21497fd7d2b86d932ec0598f0210fed4114adc546c6f"}, @@ -19,6 +23,7 @@ "plug": {:hex, :plug, "1.16.1", "40c74619c12f82736d2214557dedec2e9762029b2438d6d175c5074c933edc9d", [:mix], [{:mime, "~> 1.0 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:plug_crypto, "~> 1.1.1 or ~> 1.2 or ~> 2.0", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4.3 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "a13ff6b9006b03d7e33874945b2755253841b238c34071ed85b0e86057f8cddc"}, "plug_crypto": {:hex, :plug_crypto, "2.1.0", "f44309c2b06d249c27c8d3f65cfe08158ade08418cf540fd4f72d4d6863abb7b", [:mix], [], "hexpm", "131216a4b030b8f8ce0f26038bc4421ae60e4bb95c5cf5395e1421437824c4fa"}, "postgrex": {:hex, :postgrex, "0.19.1", "73b498508b69aded53907fe48a1fee811be34cc720e69ef4ccd568c8715495ea", [:mix], [{:db_connection, "~> 2.1", [hex: :db_connection, repo: "hexpm", optional: false]}, {:decimal, "~> 1.5 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:table, "~> 0.1.0", [hex: :table, repo: "hexpm", optional: true]}], "hexpm", "8bac7885a18f381e091ec6caf41bda7bb8c77912bb0e9285212829afe5d8a8f8"}, + "rustler_precompiled": {:hex, :rustler_precompiled, "0.8.1", "8afe0b6f3a9a677ada046cdd23e3f4c6399618b91a6122289324774961281e1e", [:mix], [{:castore, "~> 0.1 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: false]}, {:rustler, "~> 0.23", [hex: :rustler, repo: "hexpm", optional: true]}], "hexpm", "90b8c2297bf7959cfa1c927b2881faad7bb0707183124955369991b76177a166"}, "telemetry": {:hex, :telemetry, "1.3.0", "fedebbae410d715cf8e7062c96a1ef32ec22e764197f70cda73d82778d61e7a2", [:rebar3], [], "hexpm", "7015fc8919dbe63764f4b4b87a95b7c0996bd539e0d499be6ec9d7f3875b79e6"}, "telemetry_metrics": {:hex, :telemetry_metrics, "1.0.0", "29f5f84991ca98b8eb02fc208b2e6de7c95f8bb2294ef244a176675adc7775df", [:mix], [{:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "f23713b3847286a534e005126d4c959ebcca68ae9582118ce436b521d1d47d5d"}, "telemetry_poller": {:hex, :telemetry_poller, "1.1.0", "58fa7c216257291caaf8d05678c8d01bd45f4bdbc1286838a28c4bb62ef32999", [:rebar3], [{:telemetry, "~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "9eb9d9cbfd81cbd7cdd24682f8711b6e2b691289a0de6826e58452f28c103c8f"}, From 2df7f20ad68695317e83a05b1f852f04c29b9576 Mon Sep 17 00:00:00 2001 From: JuArce <52429267+JuArce@users.noreply.github.com> Date: Fri, 20 Sep 2024 19:19:54 -0300 Subject: [PATCH 03/55] refactor: add comments to signature_verifier.ex --- .../lib/telemetry_api/signature_verifier.ex | 29 ++++++++++++------- 1 file changed, 18 insertions(+), 11 deletions(-) diff --git a/telemetry_api/lib/telemetry_api/signature_verifier.ex b/telemetry_api/lib/telemetry_api/signature_verifier.ex index 645be1316..4b7f9ae5f 100644 --- a/telemetry_api/lib/telemetry_api/signature_verifier.ex +++ b/telemetry_api/lib/telemetry_api/signature_verifier.ex @@ -4,9 +4,8 @@ defmodule SignatureVerifier do alias :binary, as: Binary # Hash the version string using Keccak256 - def hash_version(version) do - version - |> ExKeccak.hash_256() + defp hash_version(version) do + ExKeccak.hash_256(version) end # Recover the public key from the signature and hashed version @@ -30,17 +29,25 @@ defmodule SignatureVerifier do address end - # Main function to get the address from the version and signature + @doc """ + Get the address from the version and signature + + Examples + iex> version = "v0.7.0" + iex> signature = N1UJOvjJT1W39MdQUYAOsKZj4aQ1Sjkwp31NJgafpjoUniGt24tSaLw6TlTKP68AkLtsIFoVEaJcJDj7TyvhLQA= + iex> get_address(version, signature) + "0x..." + """ def get_address(version, signature) do version_hash = hash_version(version) + # Signature contains r, s and v (recovery_id) + # r<>s is 64 bytes. + # v is the last byte of the signature and have to be converted to integer {:ok, binary_signature} = Base.decode64(signature) - byte_size = byte_size(binary_signature) - IO.inspect(byte_size) - # r<>s is 64 bytes. Get r and s from the signature - rs = binary_part(binary_signature, 0, byte_size - 1) - # v is the last byte of the signature - recovery_id = Binary.decode_unsigned(binary_part(binary_signature, byte_size - 1, 1)) - IO.inspect(recovery_id) + signature_len = byte_size(binary_signature) + rs = binary_part(binary_signature, 0, signature_len - 1) + recovery_id = Binary.decode_unsigned(binary_part(binary_signature, signature_len - 1, 1)) + recover_public_key(version_hash, rs, recovery_id) |> public_key_to_address() |> Base.encode16() From 74757b88b464ea4c08a8e0c42b7511f4dadacbdf Mon Sep 17 00:00:00 2001 From: JuArce <52429267+JuArce@users.noreply.github.com> Date: Tue, 24 Sep 2024 10:38:25 -0300 Subject: [PATCH 04/55] chore: update operator endpoint --- config-files/config-operator-1.yaml | 2 +- operator/cmd/actions/start.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/config-files/config-operator-1.yaml b/config-files/config-operator-1.yaml index 28e99afd4..2682ad594 100644 --- a/config-files/config-operator-1.yaml +++ b/config-files/config-operator-1.yaml @@ -22,7 +22,7 @@ bls: ## Operator Configurations operator: aggregator_rpc_server_ip_port_address: localhost:8090 - operator_tracker_ip_port_address: http://localhost:3030 + operator_tracker_ip_port_address: http://localhost:4000 address: 0x70997970C51812dc3A010C7d01b50e0d17dc79C8 earnings_receiver_address: 0x70997970C51812dc3A010C7d01b50e0d17dc79C8 delegation_approver_address: "0x0000000000000000000000000000000000000000" diff --git a/operator/cmd/actions/start.go b/operator/cmd/actions/start.go index df7bb8281..a9a169ebc 100644 --- a/operator/cmd/actions/start.go +++ b/operator/cmd/actions/start.go @@ -65,7 +65,7 @@ func operatorMain(ctx *cli.Context) error { } // send version to operator tracker server - endpoint := operatorConfig.Operator.OperatorTrackerIpPortAddress + "/versions" + endpoint := operatorConfig.Operator.OperatorTrackerIpPortAddress + "/api/operators" operator.Logger.Info("Sending version to operator tracker server: ", "endpoint", endpoint) res, err := http.Post(endpoint, "application/json", From 7c8413e79e68b7cb5e701fa3610c2fb4d44214dd Mon Sep 17 00:00:00 2001 From: JuArce <52429267+JuArce@users.noreply.github.com> Date: Tue, 24 Sep 2024 15:26:58 -0300 Subject: [PATCH 05/55] chore: add targets docs: update README --- Makefile | 31 ++++++++++++++++++++++++++ telemetry_api/README.md | 42 +++++++++++++++++++++++++++--------- telemetry_api/config/dev.exs | 2 +- 3 files changed, 64 insertions(+), 11 deletions(-) diff --git a/Makefile b/Makefile index 065fc8ffd..0f6277c7f 100644 --- a/Makefile +++ b/Makefile @@ -722,3 +722,34 @@ tracker_dump_db: @cd operator_tracker && \ docker exec -t tracker-postgres-container pg_dumpall -c -U tracker_user > dump.$$(date +\%Y\%m\%d_\%H\%M\%S).sql @echo "Dumped database successfully to /operator_tracker" + +__TELEMETRY__: +open_telemetry_start: ## Run open telemetry services using telemetry-docker-compose.yaml + ## TODO(juarce) ADD DOCKER COMPOSE + @echo "Running telemetry..." + @docker compose -f telemetry-docker-compose.yaml up -d + +telemetry_start: ## Run Telemetry API + @cd telemetry_api && \ + mix phx.server + +telemetry_build_db: + @cd telemetry_api && \ + docker build -t telemetry-postgres-image . + +telemetry_run_db: telemetry_build_db telemetry_remove_db_container + @cd telemetry_api && \ + docker run -d --name telemetry-postgres-container -p 5434:5432 -v telemetry-postgres-data:/var/lib/postgresql/data telemetry-postgres-image + +telemetry_remove_db_container: + @docker stop telemetry-postgres-container || true && \ + docker rm telemetry-postgres-container || true + +telemetry_clean_db: telemetry_remove_db_container + @docker volume rm telemetry-postgres-data || true + +telemetry_dump_db: + @cd telemetry_api && \ + docker exec -t telemetry-postgres-container pg_dumpall -c -U tracker_user > dump.$$(date +\%Y\%m\%d_\%H\%M\%S).sql + @echo "Dumped database successfully to /telemetry_api" + diff --git a/telemetry_api/README.md b/telemetry_api/README.md index 63ebe6d1c..65f4491a1 100644 --- a/telemetry_api/README.md +++ b/telemetry_api/README.md @@ -1,18 +1,40 @@ # TelemetryApi +## Database Setup + +To create a Postgres container and run it: + +```shell +make telemetry_run_db +``` + +This will create and run the container using the credentials set in `Dockerfile` + +### Delete database + +If you want to delete the container: + +```shell +make telemetry_remove_db_container +``` + +This will remove the container but will keep the storage + +If you also want to delete the storage run: + +```shell +make telemetry_clean_db +``` + +## Run Server + To start your Phoenix server: +```shell +make telemetry_start +``` + * Run `mix setup` to install and setup dependencies * Start Phoenix endpoint with `mix phx.server` or inside IEx with `iex -S mix phx.server` Now you can visit [`localhost:4000`](http://localhost:4000) from your browser. - -Ready to run in production? Please [check our deployment guides](https://hexdocs.pm/phoenix/deployment.html). - -## Learn more - - * Official website: https://www.phoenixframework.org/ - * Guides: https://hexdocs.pm/phoenix/overview.html - * Docs: https://hexdocs.pm/phoenix - * Forum: https://elixirforum.com/c/phoenix-forum - * Source: https://github.com/phoenixframework/phoenix diff --git a/telemetry_api/config/dev.exs b/telemetry_api/config/dev.exs index 90fd36b6f..bfea813cc 100644 --- a/telemetry_api/config/dev.exs +++ b/telemetry_api/config/dev.exs @@ -6,7 +6,7 @@ config :telemetry_api, TelemetryApi.Repo, password: "telemetry_pass", database: "telemetry_db", hostname: "localhost", - port: 5432, + port: 5434, stacktrace: true, show_sensitive_data_on_connection_error: true, pool_size: 10 From c63f797b91c60962773b9bdb843f91ec28776dfe Mon Sep 17 00:00:00 2001 From: JuArce <52429267+JuArce@users.noreply.github.com> Date: Tue, 24 Sep 2024 15:30:46 -0300 Subject: [PATCH 06/55] docs: update README.md --- telemetry_api/README.md | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/telemetry_api/README.md b/telemetry_api/README.md index 65f4491a1..1ba8b3794 100644 --- a/telemetry_api/README.md +++ b/telemetry_api/README.md @@ -10,6 +10,9 @@ make telemetry_run_db This will create and run the container using the credentials set in `Dockerfile` +> [!CAUTION] +> Do not use default credentials in Production environments. + ### Delete database If you want to delete the container: @@ -34,7 +37,19 @@ To start your Phoenix server: make telemetry_start ``` +On startup, it will run ecto migrations. + * Run `mix setup` to install and setup dependencies * Start Phoenix endpoint with `mix phx.server` or inside IEx with `iex -S mix phx.server` Now you can visit [`localhost:4000`](http://localhost:4000) from your browser. + +## Database Migrations + +This API uses Ecto for migrations. To apply migrations, run: + +```shell +make telemetry_ecto_migrate +``` + + From d53b6ae563efc8c06922614a315c59ee66172aa9 Mon Sep 17 00:00:00 2001 From: JuArce <52429267+JuArce@users.noreply.github.com> Date: Tue, 24 Sep 2024 15:32:13 -0300 Subject: [PATCH 07/55] chore: update Makefile --- Makefile | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 0f6277c7f..38cc49b8b 100644 --- a/Makefile +++ b/Makefile @@ -729,10 +729,14 @@ open_telemetry_start: ## Run open telemetry services using telemetry-docker-comp @echo "Running telemetry..." @docker compose -f telemetry-docker-compose.yaml up -d -telemetry_start: ## Run Telemetry API +telemetry_start: telemetry_ecto_migrate ## Run Telemetry API @cd telemetry_api && \ mix phx.server +telemetry_ecto_migrate: ## + @cd telemetry_api && \ + mix ecto.migrate + telemetry_build_db: @cd telemetry_api && \ docker build -t telemetry-postgres-image . From d0ccfa99181b539caf8f730d7d0a39001467acb6 Mon Sep 17 00:00:00 2001 From: JuArce <52429267+JuArce@users.noreply.github.com> Date: Wed, 25 Sep 2024 01:06:57 -0300 Subject: [PATCH 08/55] feat: create and finish traces for specified merkle root --- Makefile | 1 - otel-collector.yaml | 27 +++++++ telemetry-docker-compose.yaml | 15 ++++ telemetry_api/config/config.exs | 10 +++ telemetry_api/config/dev.exs | 3 + .../lib/telemetry_api/application.ex | 1 + .../lib/telemetry_api/trace_store.ex | 29 ++++++++ telemetry_api/lib/telemetry_api/traces.ex | 70 +++++++++++++++++++ .../lib/telemetry_api/traces/trace.ex | 4 ++ .../controllers/trace_controller.ex | 31 ++++++++ .../controllers/trace_json.ex | 11 +++ telemetry_api/lib/telemetry_api_web/router.ex | 3 + telemetry_api/mix.exs | 12 ++++ telemetry_api/mix.lock | 12 ++++ 14 files changed, 228 insertions(+), 1 deletion(-) create mode 100644 otel-collector.yaml create mode 100644 telemetry-docker-compose.yaml create mode 100644 telemetry_api/lib/telemetry_api/trace_store.ex create mode 100644 telemetry_api/lib/telemetry_api/traces.ex create mode 100644 telemetry_api/lib/telemetry_api/traces/trace.ex create mode 100644 telemetry_api/lib/telemetry_api_web/controllers/trace_controller.ex create mode 100644 telemetry_api/lib/telemetry_api_web/controllers/trace_json.ex diff --git a/Makefile b/Makefile index 38cc49b8b..3076378e0 100644 --- a/Makefile +++ b/Makefile @@ -725,7 +725,6 @@ tracker_dump_db: __TELEMETRY__: open_telemetry_start: ## Run open telemetry services using telemetry-docker-compose.yaml - ## TODO(juarce) ADD DOCKER COMPOSE @echo "Running telemetry..." @docker compose -f telemetry-docker-compose.yaml up -d diff --git a/otel-collector.yaml b/otel-collector.yaml new file mode 100644 index 000000000..5730227fb --- /dev/null +++ b/otel-collector.yaml @@ -0,0 +1,27 @@ +receivers: + otlp: + protocols: + grpc: + endpoint: 0.0.0.0:4317 +processors: +extensions: + health_check: {} +exporters: + otlp: + endpoint: jaeger:4317 + tls: + insecure: true + debug: + +service: + extensions: [health_check] + pipelines: + traces: + receivers: [otlp] + processors: [] + exporters: [otlp] + + metrics: + receivers: [ otlp ] + processors: [ ] + exporters: [ debug ] \ No newline at end of file diff --git a/telemetry-docker-compose.yaml b/telemetry-docker-compose.yaml new file mode 100644 index 000000000..e3885df78 --- /dev/null +++ b/telemetry-docker-compose.yaml @@ -0,0 +1,15 @@ +version: "3" + +services: + otel-collector: + image: otel/opentelemetry-collector-contrib:0.107.0 + command: ["--config=/etc/otel-collector.yaml"] + volumes: + - ./otel-collector.yaml:/etc/otel-collector.yaml + ports: + - "4317:4317" + + jaeger: + image: jaegertracing/all-in-one:1.60 + ports: + - "16686:16686" \ No newline at end of file diff --git a/telemetry_api/config/config.exs b/telemetry_api/config/config.exs index 46bf3bd9c..fc7931ac5 100644 --- a/telemetry_api/config/config.exs +++ b/telemetry_api/config/config.exs @@ -30,6 +30,16 @@ config :logger, :console, # Use Jason for JSON parsing in Phoenix config :phoenix, :json_library, Jason +# https://opentelemetry.io/docs/languages/erlang/exporters/#setting-up-the-collector +config :opentelemetry_exporter, + otlp_protocol: :grpc, + otlp_endpoint: "http://localhost:4317" + +config :opentelemetry, + resource: %{service: %{name: "telemetry_api"}}, + span_processor: :batch, + traces_exporter: :otlp + # Import environment specific config. This must remain at the bottom # of this file so it overrides the configuration defined above. import_config "#{config_env()}.exs" diff --git a/telemetry_api/config/dev.exs b/telemetry_api/config/dev.exs index bfea813cc..8c03f42e7 100644 --- a/telemetry_api/config/dev.exs +++ b/telemetry_api/config/dev.exs @@ -62,3 +62,6 @@ config :phoenix, :stacktrace_depth, 20 # Initialize plugs at runtime for faster development compilation config :phoenix, :plug_init_mode, :runtime + +# For development, we use the stdout exporter to ensure everything is working properly +# config :opentelemetry, traces_exporter: {:otel_exporter_stdout, []} diff --git a/telemetry_api/lib/telemetry_api/application.ex b/telemetry_api/lib/telemetry_api/application.ex index d1a065189..967203b41 100644 --- a/telemetry_api/lib/telemetry_api/application.ex +++ b/telemetry_api/lib/telemetry_api/application.ex @@ -8,6 +8,7 @@ defmodule TelemetryApi.Application do @impl true def start(_type, _args) do children = [ + TraceStore, TelemetryApiWeb.Telemetry, TelemetryApi.Repo, {DNSCluster, query: Application.get_env(:telemetry_api, :dns_cluster_query) || :ignore}, diff --git a/telemetry_api/lib/telemetry_api/trace_store.ex b/telemetry_api/lib/telemetry_api/trace_store.ex new file mode 100644 index 000000000..79dc85a1c --- /dev/null +++ b/telemetry_api/lib/telemetry_api/trace_store.ex @@ -0,0 +1,29 @@ +defmodule TraceStore do + use Agent + + # Start the agent + def start_link(_opts) do + Agent.start_link(fn -> %{} end, name: __MODULE__) + end + + # Store the trace using the merkle_root as the key + def store_trace(merkle_root, trace) do + Agent.update(__MODULE__, fn state -> + Map.put(state, merkle_root, trace) + end) + end + + # Retrieve the trace by merkle_root + def get_trace(merkle_root) do + Agent.get(__MODULE__, fn state -> + Map.get(state, merkle_root) + end) + end + + # Delete the trace after it's used + def delete_trace(merkle_root) do + Agent.update(__MODULE__, fn state -> + Map.delete(state, merkle_root) + end) + end +end diff --git a/telemetry_api/lib/telemetry_api/traces.ex b/telemetry_api/lib/telemetry_api/traces.ex new file mode 100644 index 000000000..d1908c119 --- /dev/null +++ b/telemetry_api/lib/telemetry_api/traces.ex @@ -0,0 +1,70 @@ +defmodule TelemetryApi.Traces do + @moduledoc """ + The Traces context. + """ + alias TelemetryApi.Traces.Trace + + require OpenTelemetry.Tracer + require OpenTelemetry.Ctx + alias OpenTelemetry.Tracer, as: Tracer + alias OpenTelemetry.Ctx, as: Ctx + + @doc """ + Send the trace to OpenTelemetry + + This function is responsible for creating a new span and storing the context in the Agent. + + ## Examples + + iex> merkle_root = "0x1234567890abcdef" + iex> create_task_trace(merkle_root) + {:ok, "merkle_root"} + """ + def create_task_trace(merkle_root) do + span_ctx = Tracer.start_span( + "Task: #{merkle_root}", + %{attributes: [ + {:merkle_root, merkle_root} + ]} + ) + ctx = Ctx.get_current() + + TraceStore.store_trace(merkle_root, %Trace{ + parent_span: span_ctx, + context: ctx + }) + IO.inspect(merkle_root) + {:ok, merkle_root} + end + + @doc """ + Finish the task trace + + This function is responsible for ending the span and cleaning up the context. + + ## Examples + + iex> merkle_root = "0x1234567890abcdef" + iex> finish_task_trace(merkle_root) + :ok + """ + def finish_task_trace(merkle_root) do + case TraceStore.get_trace(merkle_root) do + nil -> + IO.inspect("Context not found for #{merkle_root}") + {:error, "Context not found for #{merkle_root}"} + + trace -> + Ctx.attach(trace.context) + Tracer.set_current_span(trace.parent_span) + Tracer.set_attributes(%{status: "completed"}) + + Tracer.end_span(trace.parent_span) + + # Clean up the context from the Agent + TraceStore.delete_trace(merkle_root) + IO.inspect(merkle_root) + :ok + end + end +end diff --git a/telemetry_api/lib/telemetry_api/traces/trace.ex b/telemetry_api/lib/telemetry_api/traces/trace.ex new file mode 100644 index 000000000..f2e77ef47 --- /dev/null +++ b/telemetry_api/lib/telemetry_api/traces/trace.ex @@ -0,0 +1,4 @@ +defmodule TelemetryApi.Traces.Trace do + @enforce_keys [:parent_span, :context] + defstruct [:parent_span, :context] +end diff --git a/telemetry_api/lib/telemetry_api_web/controllers/trace_controller.ex b/telemetry_api/lib/telemetry_api_web/controllers/trace_controller.ex new file mode 100644 index 000000000..28c493d3c --- /dev/null +++ b/telemetry_api/lib/telemetry_api_web/controllers/trace_controller.ex @@ -0,0 +1,31 @@ +defmodule TelemetryApiWeb.TraceController do + use TelemetryApiWeb, :controller + + alias TelemetryApi.Traces + + action_fallback TelemetryApiWeb.FallbackController + + @doc """ + Create a trace for a NewTask with the given merkle_root + Method: POST initTaskTrace + """ + def create_task_trace(conn, %{"merkle_root" => merkle_root}) do + with {:ok, merkle_root} <- Traces.create_task_trace(merkle_root) do + conn + |> put_status(:created) + |> render(:show, merkle_root: merkle_root) + end + end + + @doc """ + Finish a trace for the given merkle_root + Method: POST finishTaskTrace + """ + def finish_task_trace(conn, %{"merkle_root" => merkle_root}) do + with :ok <- Traces.finish_task_trace(merkle_root) do + conn + |> put_status(:ok) + |> render(:show, merkle_root: merkle_root) + end + end +end diff --git a/telemetry_api/lib/telemetry_api_web/controllers/trace_json.ex b/telemetry_api/lib/telemetry_api_web/controllers/trace_json.ex new file mode 100644 index 000000000..ff7f0b2a4 --- /dev/null +++ b/telemetry_api/lib/telemetry_api_web/controllers/trace_json.ex @@ -0,0 +1,11 @@ +defmodule TelemetryApiWeb.TraceJSON do + + @doc """ + + """ + def show(%{merkle_root: merkle_root}) do + %{ + merkle_root: merkle_root + } + end +end diff --git a/telemetry_api/lib/telemetry_api_web/router.ex b/telemetry_api/lib/telemetry_api_web/router.ex index 217982b11..0a126a5be 100644 --- a/telemetry_api/lib/telemetry_api_web/router.ex +++ b/telemetry_api/lib/telemetry_api_web/router.ex @@ -8,6 +8,9 @@ defmodule TelemetryApiWeb.Router do scope "/api", TelemetryApiWeb do pipe_through :api resources "/operators", OperatorController, only: [:index, :show, :create] + + post "/initTaskTrace", TraceController, :create_task_trace + post "/finishTaskTrace", TraceController, :finish_task_trace end # Enable LiveDashboard in development diff --git a/telemetry_api/mix.exs b/telemetry_api/mix.exs index 071dea16b..ed8de5566 100644 --- a/telemetry_api/mix.exs +++ b/telemetry_api/mix.exs @@ -8,6 +8,15 @@ defmodule TelemetryApi.MixProject do elixir: "~> 1.14", elixirc_paths: elixirc_paths(Mix.env()), start_permanent: Mix.env() == :prod, + releases: [ + telemetry_api: [ + applications: [ + # https://opentelemetry.io/docs/languages/erlang/exporters/#setting-up-the-collector + opentelemetry_exporter: :permanent, + opentelemetry: :temporary + ] + ] + ], aliases: aliases(), deps: deps() ] @@ -44,6 +53,9 @@ defmodule TelemetryApi.MixProject do {:bandit, "~> 1.5"}, {:ex_keccak, "~> 0.7.5"}, {:ex_secp256k1, "~> 0.7"}, + {:opentelemetry, "~> 1.3"}, + {:opentelemetry_api, "~> 1.2"}, + {:opentelemetry_exporter, "~> 1.6"}, ] end diff --git a/telemetry_api/mix.lock b/telemetry_api/mix.lock index b3c2fe97c..4c6d1ff48 100644 --- a/telemetry_api/mix.lock +++ b/telemetry_api/mix.lock @@ -1,6 +1,9 @@ %{ + "acceptor_pool": {:hex, :acceptor_pool, "1.0.0", "43c20d2acae35f0c2bcd64f9d2bde267e459f0f3fd23dab26485bf518c281b21", [:rebar3], [], "hexpm", "0cbcd83fdc8b9ad2eee2067ef8b91a14858a5883cb7cd800e6fcd5803e158788"}, "bandit": {:hex, :bandit, "1.5.7", "6856b1e1df4f2b0cb3df1377eab7891bec2da6a7fd69dc78594ad3e152363a50", [:mix], [{:hpax, "~> 1.0.0", [hex: :hpax, repo: "hexpm", optional: false]}, {:plug, "~> 1.14", [hex: :plug, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}, {:thousand_island, "~> 1.0", [hex: :thousand_island, repo: "hexpm", optional: false]}, {:websock, "~> 0.5", [hex: :websock, repo: "hexpm", optional: false]}], "hexpm", "f2dd92ae87d2cbea2fa9aa1652db157b6cba6c405cb44d4f6dd87abba41371cd"}, "castore": {:hex, :castore, "1.0.8", "dedcf20ea746694647f883590b82d9e96014057aff1d44d03ec90f36a5c0dc6e", [:mix], [], "hexpm", "0b2b66d2ee742cb1d9cb8c8be3b43c3a70ee8651f37b75a8b982e036752983f1"}, + "chatterbox": {:hex, :ts_chatterbox, "0.15.1", "5cac4d15dd7ad61fc3c4415ce4826fc563d4643dee897a558ec4ea0b1c835c9c", [:rebar3], [{:hpack, "~> 0.3.0", [hex: :hpack_erl, repo: "hexpm", optional: false]}], "hexpm", "4f75b91451338bc0da5f52f3480fa6ef6e3a2aeecfc33686d6b3d0a0948f31aa"}, + "ctx": {:hex, :ctx, "0.6.0", "8ff88b70e6400c4df90142e7f130625b82086077a45364a78d208ed3ed53c7fe", [:rebar3], [], "hexpm", "a14ed2d1b67723dbebbe423b28d7615eb0bdcba6ff28f2d1f1b0a7e1d4aa5fc2"}, "db_connection": {:hex, :db_connection, "2.7.0", "b99faa9291bb09892c7da373bb82cba59aefa9b36300f6145c5f201c7adf48ec", [:mix], [{:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "dcf08f31b2701f857dfc787fbad78223d61a32204f217f15e881dd93e4bdd3ff"}, "decimal": {:hex, :decimal, "2.1.1", "5611dca5d4b2c3dd497dec8f68751f1f1a54755e8ed2a966c2633cf885973ad6", [:mix], [], "hexpm", "53cfe5f497ed0e7771ae1a475575603d77425099ba5faef9394932b35020ffcc"}, "dns_cluster": {:hex, :dns_cluster, "0.1.3", "0bc20a2c88ed6cc494f2964075c359f8c2d00e1bf25518a6a6c7fd277c9b0c66", [:mix], [], "hexpm", "46cb7c4a1b3e52c7ad4cbe33ca5079fbde4840dedeafca2baf77996c2da1bc33"}, @@ -8,11 +11,18 @@ "ecto_sql": {:hex, :ecto_sql, "3.12.0", "73cea17edfa54bde76ee8561b30d29ea08f630959685006d9c6e7d1e59113b7d", [:mix], [{:db_connection, "~> 2.4.1 or ~> 2.5", [hex: :db_connection, repo: "hexpm", optional: false]}, {:ecto, "~> 3.12", [hex: :ecto, repo: "hexpm", optional: false]}, {:myxql, "~> 0.7", [hex: :myxql, repo: "hexpm", optional: true]}, {:postgrex, "~> 0.19 or ~> 1.0", [hex: :postgrex, repo: "hexpm", optional: true]}, {:tds, "~> 2.1.1 or ~> 2.2", [hex: :tds, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4.0 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "dc9e4d206f274f3947e96142a8fdc5f69a2a6a9abb4649ef5c882323b6d512f0"}, "ex_keccak": {:hex, :ex_keccak, "0.7.5", "f3b733173510d48ae9a1ea1de415e694b2651f35c787e63f33b5ed0013fbfd35", [:mix], [{:rustler, ">= 0.0.0", [hex: :rustler, repo: "hexpm", optional: true]}, {:rustler_precompiled, "~> 0.7", [hex: :rustler_precompiled, repo: "hexpm", optional: false]}], "hexpm", "8a5e1cb7f96fff5e480ff6a121477b90c4fd8c150984086dffd98819f5d83763"}, "ex_secp256k1": {:hex, :ex_secp256k1, "0.7.3", "489b6fd57fab5a7259ace927d8cb5171aad835e9c7279c2a859a0483cb069415", [:mix], [{:rustler, ">= 0.0.0", [hex: :rustler, repo: "hexpm", optional: true]}, {:rustler_precompiled, "~> 0.7", [hex: :rustler_precompiled, repo: "hexpm", optional: false]}], "hexpm", "ea63159442f4d8143166cd1507da03edc43216d6e7c6bac4b416bdce04f0daa8"}, + "gproc": {:hex, :gproc, "0.9.1", "f1df0364423539cf0b80e8201c8b1839e229e5f9b3ccb944c5834626998f5b8c", [:rebar3], [], "hexpm", "905088e32e72127ed9466f0bac0d8e65704ca5e73ee5a62cb073c3117916d507"}, + "grpcbox": {:hex, :grpcbox, "0.17.1", "6e040ab3ef16fe699ffb513b0ef8e2e896da7b18931a1ef817143037c454bcce", [:rebar3], [{:acceptor_pool, "~> 1.0.0", [hex: :acceptor_pool, repo: "hexpm", optional: false]}, {:chatterbox, "~> 0.15.1", [hex: :ts_chatterbox, repo: "hexpm", optional: false]}, {:ctx, "~> 0.6.0", [hex: :ctx, repo: "hexpm", optional: false]}, {:gproc, "~> 0.9.1", [hex: :gproc, repo: "hexpm", optional: false]}], "hexpm", "4a3b5d7111daabc569dc9cbd9b202a3237d81c80bf97212fbc676832cb0ceb17"}, + "hpack": {:hex, :hpack_erl, "0.3.0", "2461899cc4ab6a0ef8e970c1661c5fc6a52d3c25580bc6dd204f84ce94669926", [:rebar3], [], "hexpm", "d6137d7079169d8c485c6962dfe261af5b9ef60fbc557344511c1e65e3d95fb0"}, "hpax": {:hex, :hpax, "1.0.0", "28dcf54509fe2152a3d040e4e3df5b265dcb6cb532029ecbacf4ce52caea3fd2", [:mix], [], "hexpm", "7f1314731d711e2ca5fdc7fd361296593fc2542570b3105595bb0bc6d0fad601"}, "jason": {:hex, :jason, "1.4.4", "b9226785a9aa77b6857ca22832cffa5d5011a667207eb2a0ad56adb5db443b8a", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "c5eb0cab91f094599f94d55bc63409236a8ec69a21a67814529e8d5f6cc90b3b"}, "libsecp256k1": {:hex, :libsecp256k1, "0.1.9", "e725f31364cda7b554d56ce2bb976241303dde5ffd1ad59598513297bf1f2af6", [:make, :mix], [{:mix_erlang_tasks, "0.1.0", [hex: :mix_erlang_tasks, repo: "hexpm", optional: false]}], "hexpm", "93da7c29e892db4d59f7ed394decb6f9c5d653deb88e183a9221e5cc5ca4b987"}, "mime": {:hex, :mime, "2.0.6", "8f18486773d9b15f95f4f4f1e39b710045fa1de891fada4516559967276e4dc2", [:mix], [], "hexpm", "c9945363a6b26d747389aac3643f8e0e09d30499a138ad64fe8fd1d13d9b153e"}, "mix_erlang_tasks": {:hex, :mix_erlang_tasks, "0.1.0", "36819fec60b80689eb1380938675af215565a89320a9e29c72c70d97512e4649", [:mix], [], "hexpm", "95d2839c422c482a70c08a8702da8242f86b773f8ab6e8602a4eb72da8da04ed"}, + "opentelemetry": {:hex, :opentelemetry, "1.4.0", "f928923ed80adb5eb7894bac22e9a198478e6a8f04020ae1d6f289fdcad0b498", [:rebar3], [{:opentelemetry_api, "~> 1.3.0", [hex: :opentelemetry_api, repo: "hexpm", optional: false]}, {:opentelemetry_semantic_conventions, "~> 0.2", [hex: :opentelemetry_semantic_conventions, repo: "hexpm", optional: false]}], "hexpm", "50b32ce127413e5d87b092b4d210a3449ea80cd8224090fe68d73d576a3faa15"}, + "opentelemetry_api": {:hex, :opentelemetry_api, "1.3.1", "83b4713593f80562d9643c4ab0b6f80f3c5fa4c6d0632c43e11b2ccb6b04dfa7", [:mix, :rebar3], [{:opentelemetry_semantic_conventions, "~> 0.2", [hex: :opentelemetry_semantic_conventions, repo: "hexpm", optional: false]}], "hexpm", "9e8a5cc38671e3ac61be48abe5f6b3afdbbb50a1dc08b7950c56f169611505c1"}, + "opentelemetry_exporter": {:hex, :opentelemetry_exporter, "1.7.0", "dec4e90c0667cf11a3642f7fe71982dbc0c6bfbb8725a0b13766830718cf0d98", [:rebar3], [{:grpcbox, ">= 0.0.0", [hex: :grpcbox, repo: "hexpm", optional: false]}, {:opentelemetry, "~> 1.4.0", [hex: :opentelemetry, repo: "hexpm", optional: false]}, {:opentelemetry_api, "~> 1.3.0", [hex: :opentelemetry_api, repo: "hexpm", optional: false]}, {:tls_certificate_check, "~> 1.18", [hex: :tls_certificate_check, repo: "hexpm", optional: false]}], "hexpm", "d0f25f6439ec43f2561537c3fabbe177b38547cddaa3a692cbb8f4770dbefc1e"}, + "opentelemetry_semantic_conventions": {:hex, :opentelemetry_semantic_conventions, "0.2.0", "b67fe459c2938fcab341cb0951c44860c62347c005ace1b50f8402576f241435", [:mix, :rebar3], [], "hexpm", "d61fa1f5639ee8668d74b527e6806e0503efc55a42db7b5f39939d84c07d6895"}, "phoenix": {:hex, :phoenix, "1.7.14", "a7d0b3f1bc95987044ddada111e77bd7f75646a08518942c72a8440278ae7825", [:mix], [{:castore, ">= 0.0.0", [hex: :castore, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:phoenix_pubsub, "~> 2.1", [hex: :phoenix_pubsub, repo: "hexpm", optional: false]}, {:phoenix_template, "~> 1.0", [hex: :phoenix_template, repo: "hexpm", optional: false]}, {:phoenix_view, "~> 2.0", [hex: :phoenix_view, repo: "hexpm", optional: true]}, {:plug, "~> 1.14", [hex: :plug, repo: "hexpm", optional: false]}, {:plug_cowboy, "~> 2.7", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:plug_crypto, "~> 1.2 or ~> 2.0", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}, {:websock_adapter, "~> 0.5.3", [hex: :websock_adapter, repo: "hexpm", optional: false]}], "hexpm", "c7859bc56cc5dfef19ecfc240775dae358cbaa530231118a9e014df392ace61a"}, "phoenix_ecto": {:hex, :phoenix_ecto, "4.6.2", "3b83b24ab5a2eb071a20372f740d7118767c272db386831b2e77638c4dcc606d", [:mix], [{:ecto, "~> 3.5", [hex: :ecto, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 2.14.2 or ~> 3.0 or ~> 4.1", [hex: :phoenix_html, repo: "hexpm", optional: true]}, {:plug, "~> 1.9", [hex: :plug, repo: "hexpm", optional: false]}, {:postgrex, "~> 0.16 or ~> 1.0", [hex: :postgrex, repo: "hexpm", optional: true]}], "hexpm", "3f94d025f59de86be00f5f8c5dd7b5965a3298458d21ab1c328488be3b5fcd59"}, "phoenix_html": {:hex, :phoenix_html, "4.1.1", "4c064fd3873d12ebb1388425a8f2a19348cef56e7289e1998e2d2fa758aa982e", [:mix], [], "hexpm", "f2f2df5a72bc9a2f510b21497fd7d2b86d932ec0598f0210fed4114adc546c6f"}, @@ -24,10 +34,12 @@ "plug_crypto": {:hex, :plug_crypto, "2.1.0", "f44309c2b06d249c27c8d3f65cfe08158ade08418cf540fd4f72d4d6863abb7b", [:mix], [], "hexpm", "131216a4b030b8f8ce0f26038bc4421ae60e4bb95c5cf5395e1421437824c4fa"}, "postgrex": {:hex, :postgrex, "0.19.1", "73b498508b69aded53907fe48a1fee811be34cc720e69ef4ccd568c8715495ea", [:mix], [{:db_connection, "~> 2.1", [hex: :db_connection, repo: "hexpm", optional: false]}, {:decimal, "~> 1.5 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:table, "~> 0.1.0", [hex: :table, repo: "hexpm", optional: true]}], "hexpm", "8bac7885a18f381e091ec6caf41bda7bb8c77912bb0e9285212829afe5d8a8f8"}, "rustler_precompiled": {:hex, :rustler_precompiled, "0.8.1", "8afe0b6f3a9a677ada046cdd23e3f4c6399618b91a6122289324774961281e1e", [:mix], [{:castore, "~> 0.1 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: false]}, {:rustler, "~> 0.23", [hex: :rustler, repo: "hexpm", optional: true]}], "hexpm", "90b8c2297bf7959cfa1c927b2881faad7bb0707183124955369991b76177a166"}, + "ssl_verify_fun": {:hex, :ssl_verify_fun, "1.1.7", "354c321cf377240c7b8716899e182ce4890c5938111a1296add3ec74cf1715df", [:make, :mix, :rebar3], [], "hexpm", "fe4c190e8f37401d30167c8c405eda19469f34577987c76dde613e838bbc67f8"}, "telemetry": {:hex, :telemetry, "1.3.0", "fedebbae410d715cf8e7062c96a1ef32ec22e764197f70cda73d82778d61e7a2", [:rebar3], [], "hexpm", "7015fc8919dbe63764f4b4b87a95b7c0996bd539e0d499be6ec9d7f3875b79e6"}, "telemetry_metrics": {:hex, :telemetry_metrics, "1.0.0", "29f5f84991ca98b8eb02fc208b2e6de7c95f8bb2294ef244a176675adc7775df", [:mix], [{:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "f23713b3847286a534e005126d4c959ebcca68ae9582118ce436b521d1d47d5d"}, "telemetry_poller": {:hex, :telemetry_poller, "1.1.0", "58fa7c216257291caaf8d05678c8d01bd45f4bdbc1286838a28c4bb62ef32999", [:rebar3], [{:telemetry, "~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "9eb9d9cbfd81cbd7cdd24682f8711b6e2b691289a0de6826e58452f28c103c8f"}, "thousand_island": {:hex, :thousand_island, "1.3.5", "6022b6338f1635b3d32406ff98d68b843ba73b3aa95cfc27154223244f3a6ca5", [:mix], [{:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "2be6954916fdfe4756af3239fb6b6d75d0b8063b5df03ba76fd8a4c87849e180"}, + "tls_certificate_check": {:hex, :tls_certificate_check, "1.23.0", "bb7869c629de4ec72d4652520c1ad2255bb5712ad09a6568c41b0294b3cec78f", [:rebar3], [{:ssl_verify_fun, "~> 1.1", [hex: :ssl_verify_fun, repo: "hexpm", optional: false]}], "hexpm", "79d0c84effc7c81ac1e85fa38b1c33572fe2976fb8fafdfb2f0140de0442d494"}, "websock": {:hex, :websock, "0.5.3", "2f69a6ebe810328555b6fe5c831a851f485e303a7c8ce6c5f675abeb20ebdadc", [:mix], [], "hexpm", "6105453d7fac22c712ad66fab1d45abdf049868f253cf719b625151460b8b453"}, "websock_adapter": {:hex, :websock_adapter, "0.5.7", "65fa74042530064ef0570b75b43f5c49bb8b235d6515671b3d250022cb8a1f9e", [:mix], [{:bandit, ">= 0.6.0", [hex: :bandit, repo: "hexpm", optional: true]}, {:plug, "~> 1.14", [hex: :plug, repo: "hexpm", optional: false]}, {:plug_cowboy, "~> 2.6", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:websock, "~> 0.5", [hex: :websock, repo: "hexpm", optional: false]}], "hexpm", "d0f478ee64deddfec64b800673fd6e0c8888b079d9f3444dd96d2a98383bdbd1"}, } From 95617807b224cac733aa3b3828899c7c19875bd9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Avila=20Gast=C3=B3n?= <72628438+avilagaston9@users.noreply.github.com> Date: Wed, 25 Sep 2024 16:49:38 -0300 Subject: [PATCH 09/55] feat(tracker): update operators' version if they already exist (#1070) --- telemetry_api/lib/telemetry_api/operators.ex | 23 +++++++++++-------- .../lib/telemetry_api/operators/operator.ex | 6 ++++- .../controllers/operator_controller.ex | 22 ++++++++++++------ .../controllers/operator_json.ex | 1 - telemetry_api/lib/telemetry_api_web/router.ex | 5 ++++ .../20240917212329_create_operators.exs | 6 +++-- 6 files changed, 43 insertions(+), 20 deletions(-) diff --git a/telemetry_api/lib/telemetry_api/operators.ex b/telemetry_api/lib/telemetry_api/operators.ex index 732dace23..72cd5751a 100644 --- a/telemetry_api/lib/telemetry_api/operators.ex +++ b/telemetry_api/lib/telemetry_api/operators.ex @@ -24,18 +24,18 @@ defmodule TelemetryApi.Operators do @doc """ Gets a single operator. - Raises `Ecto.NoResultsError` if the Operator does not exist. - ## Examples - iex> get_operator!(123) + iex> get_operator("some_address"}) %Operator{} - iex> get_operator!(456) - ** (Ecto.NoResultsError) + iex> get_operator("non_existent_address") + nil """ - def get_operator!(id), do: Repo.get!(Operator, id) + def get_operator(address) do + Repo.get(Operator, address) + end @doc """ Creates a operator. @@ -51,11 +51,16 @@ defmodule TelemetryApi.Operators do """ def create_operator(attrs \\ %{}) do # Get address from the signature - address = SignatureVerifier.get_address(attrs["version"], attrs["signature"]) + address = "0x" <> SignatureVerifier.get_address(attrs["version"], attrs["signature"]) attrs = Map.put(attrs, "address", address) - %Operator{} + + # We handle updates here as there is no patch method available at the moment. + case Repo.get(Operator, address) do + nil -> %Operator{} + operator -> operator + end |> Operator.changeset(attrs) - |> Repo.insert() + |> Repo.insert_or_update() end @doc """ diff --git a/telemetry_api/lib/telemetry_api/operators/operator.ex b/telemetry_api/lib/telemetry_api/operators/operator.ex index 4bdc7d195..0392e8526 100644 --- a/telemetry_api/lib/telemetry_api/operators/operator.ex +++ b/telemetry_api/lib/telemetry_api/operators/operator.ex @@ -2,9 +2,9 @@ defmodule TelemetryApi.Operators.Operator do use Ecto.Schema import Ecto.Changeset + @primary_key {:address, :string, []} schema "operators" do field :version, :string - field :address, :string timestamps(type: :utc_datetime) end @@ -16,3 +16,7 @@ defmodule TelemetryApi.Operators.Operator do |> validate_required([:address, :version]) end end + +defimpl Phoenix.Param, for: TelemetryApi.Operators.Operator do + def to_param(%TelemetryApi.Operators.Operator{address: address}), do: address +end diff --git a/telemetry_api/lib/telemetry_api_web/controllers/operator_controller.ex b/telemetry_api/lib/telemetry_api_web/controllers/operator_controller.ex index cefb88ca4..167c34534 100644 --- a/telemetry_api/lib/telemetry_api_web/controllers/operator_controller.ex +++ b/telemetry_api/lib/telemetry_api_web/controllers/operator_controller.ex @@ -20,16 +20,24 @@ defmodule TelemetryApiWeb.OperatorController do end end - def show(conn, %{"id" => id}) do - operator = Operators.get_operator!(id) - render(conn, :show, operator: operator) + def show(conn, %{"id" => address}) do + case Operators.get_operator(address) do + %Operator{} = operator -> + render(conn, :show, operator: operator) + + nil -> + conn + |> put_status(:not_found) + |> put_view(TelemetryApiWeb.ErrorJSON) + |> render("404.json", %{}) + end end - # def update(conn, %{"id" => id, "operator" => operator_params}) do - # operator = Operators.get_operator!(id) - + # defp update(conn, operator, operator_params) do # with {:ok, %Operator{} = operator} <- Operators.update_operator(operator, operator_params) do - # render(conn, :show, operator: operator) + # conn + # |> put_status(:ok) + # |> render(:show, operator: operator) # end # end diff --git a/telemetry_api/lib/telemetry_api_web/controllers/operator_json.ex b/telemetry_api/lib/telemetry_api_web/controllers/operator_json.ex index 5d0a27951..6d0828be3 100644 --- a/telemetry_api/lib/telemetry_api_web/controllers/operator_json.ex +++ b/telemetry_api/lib/telemetry_api_web/controllers/operator_json.ex @@ -17,7 +17,6 @@ defmodule TelemetryApiWeb.OperatorJSON do defp data(%Operator{} = operator) do %{ - id: operator.id, address: operator.address, version: operator.version } diff --git a/telemetry_api/lib/telemetry_api_web/router.ex b/telemetry_api/lib/telemetry_api_web/router.ex index 217982b11..6b17f10b3 100644 --- a/telemetry_api/lib/telemetry_api_web/router.ex +++ b/telemetry_api/lib/telemetry_api_web/router.ex @@ -10,6 +10,11 @@ defmodule TelemetryApiWeb.Router do resources "/operators", OperatorController, only: [:index, :show, :create] end + scope "/versions", TelemetryApiWeb do + pipe_through :api + resources "/", OperatorController, only: [:index, :show, :create] + end + # Enable LiveDashboard in development if Application.compile_env(:telemetry_api, :dev_routes) do # If you want to use the LiveDashboard in production, you should put diff --git a/telemetry_api/priv/repo/migrations/20240917212329_create_operators.exs b/telemetry_api/priv/repo/migrations/20240917212329_create_operators.exs index 3c1e5bbb1..a4a2a9b94 100644 --- a/telemetry_api/priv/repo/migrations/20240917212329_create_operators.exs +++ b/telemetry_api/priv/repo/migrations/20240917212329_create_operators.exs @@ -2,11 +2,13 @@ defmodule TelemetryApi.Repo.Migrations.CreateOperators do use Ecto.Migration def change do - create table(:operators) do - add :address, :string + create table(:operators, primary_key: false) do + add :address, :string, primary_key: true add :version, :string timestamps(type: :utc_datetime) end + + create unique_index(:operators, [:address]) end end From 7bac49fdfcda5f78029a630a864b8cde191c75de Mon Sep 17 00:00:00 2001 From: Julian Ventura <43799596+JulianVentura@users.noreply.github.com> Date: Thu, 26 Sep 2024 11:27:14 -0300 Subject: [PATCH 10/55] feat: add operator identity check on registry manager contract before creation (#1080) Co-authored-by: Julian Ventura --- Makefile | 4 +- telemetry_api/.env.dev | 1 + telemetry_api/config/dev.exs | 3 ++ telemetry_api/config/runtime.exs | 18 ++++++++ telemetry_api/ecto_setup_db.sh | 10 ++++ telemetry_api/lib/telemetry_api/operators.ex | 27 +++++++---- .../registry_coordinator_manager.ex | 46 +++++++++++++++++++ .../lib/telemetry_api/signature_verifier.ex | 10 ++-- .../controllers/operator_controller.ex | 20 ++++++-- telemetry_api/mix.exs | 2 + telemetry_api/mix.lock | 13 +++++- .../priv/abi/IRegistryCoordinator.json | 1 + telemetry_api/start.sh | 7 +++ 13 files changed, 140 insertions(+), 22 deletions(-) create mode 100644 telemetry_api/.env.dev create mode 100755 telemetry_api/ecto_setup_db.sh create mode 100644 telemetry_api/lib/telemetry_api/registry_coordinator_manager.ex create mode 100644 telemetry_api/priv/abi/IRegistryCoordinator.json create mode 100755 telemetry_api/start.sh diff --git a/Makefile b/Makefile index 38cc49b8b..a2413ad6d 100644 --- a/Makefile +++ b/Makefile @@ -731,11 +731,11 @@ open_telemetry_start: ## Run open telemetry services using telemetry-docker-comp telemetry_start: telemetry_ecto_migrate ## Run Telemetry API @cd telemetry_api && \ - mix phx.server + ./start.sh telemetry_ecto_migrate: ## @cd telemetry_api && \ - mix ecto.migrate + ./ecto_setup_db.sh telemetry_build_db: @cd telemetry_api && \ diff --git a/telemetry_api/.env.dev b/telemetry_api/.env.dev new file mode 100644 index 000000000..e98ce001e --- /dev/null +++ b/telemetry_api/.env.dev @@ -0,0 +1 @@ +export ALIGNED_CONFIG_FILE="../contracts/script/output/devnet/alignedlayer_deployment_output.json" diff --git a/telemetry_api/config/dev.exs b/telemetry_api/config/dev.exs index bfea813cc..fdbf46dbd 100644 --- a/telemetry_api/config/dev.exs +++ b/telemetry_api/config/dev.exs @@ -62,3 +62,6 @@ config :phoenix, :stacktrace_depth, 20 # Initialize plugs at runtime for faster development compilation config :phoenix, :plug_init_mode, :runtime + +# Configure ethereumex url +config :ethereumex, url: "http://localhost:8545" diff --git a/telemetry_api/config/runtime.exs b/telemetry_api/config/runtime.exs index 0d07d01e1..d34f8f7c9 100644 --- a/telemetry_api/config/runtime.exs +++ b/telemetry_api/config/runtime.exs @@ -65,6 +65,24 @@ if config_env() == :prod do ], secret_key_base: secret_key_base + # ## Ethereum RPC calls configuration + + # Node RPC URL + rpc_url = System.get_env("RPC_URL") || + raise """ + environment variable RPC_URL is missing. + """ + + # Configure ethereumex url + config :ethereumex, url: rpc_url + + # Contract RegistryCoordinatorManager address + System.get_env("ALIGNED_CONFIG_FILE") || + raise """ + environment variable ALIGNED_CONFIG_FILE is missing. + """ + + # ## SSL Support # # To get SSL working, you will need to add the `https` key diff --git a/telemetry_api/ecto_setup_db.sh b/telemetry_api/ecto_setup_db.sh new file mode 100755 index 000000000..b41326827 --- /dev/null +++ b/telemetry_api/ecto_setup_db.sh @@ -0,0 +1,10 @@ +#!/bin/bash + +source .env.dev + +mix deps.get + +mix compile --force #force recompile to get the latest .env values + +mix ecto.create +mix ecto.migrate diff --git a/telemetry_api/lib/telemetry_api/operators.ex b/telemetry_api/lib/telemetry_api/operators.ex index 72cd5751a..7528cf37e 100644 --- a/telemetry_api/lib/telemetry_api/operators.ex +++ b/telemetry_api/lib/telemetry_api/operators.ex @@ -7,6 +7,7 @@ defmodule TelemetryApi.Operators do alias TelemetryApi.Repo alias TelemetryApi.Operators.Operator + alias TelemetryApi.RegistryCoordinatorManager @doc """ Returns the list of operators. @@ -51,16 +52,24 @@ defmodule TelemetryApi.Operators do """ def create_operator(attrs \\ %{}) do # Get address from the signature - address = "0x" <> SignatureVerifier.get_address(attrs["version"], attrs["signature"]) - attrs = Map.put(attrs, "address", address) - - # We handle updates here as there is no patch method available at the moment. - case Repo.get(Operator, address) do - nil -> %Operator{} - operator -> operator + with {:ok, address} <- SignatureVerifier.get_address(attrs["version"], attrs["signature"]), + {:ok, is_registered?} <- RegistryCoordinatorManager.is_operator_registered?(address) do + # Verify operator is registered + if is_registered? do + address = "0x" <> address + attrs = Map.put(attrs, "address", address) + + # We handle updates here as there is no patch method available at the moment. + case Repo.get(Operator, address) do + nil -> %Operator{} + operator -> operator + end + |> Operator.changeset(attrs) + |> Repo.insert_or_update() + else + {:error, "Provided address does not correspond to any registered operator"} + end end - |> Operator.changeset(attrs) - |> Repo.insert_or_update() end @doc """ diff --git a/telemetry_api/lib/telemetry_api/registry_coordinator_manager.ex b/telemetry_api/lib/telemetry_api/registry_coordinator_manager.ex new file mode 100644 index 000000000..9e3bae63d --- /dev/null +++ b/telemetry_api/lib/telemetry_api/registry_coordinator_manager.ex @@ -0,0 +1,46 @@ +defmodule TelemetryApi.RegistryCoordinatorManager do + alias TelemetryApi.RegistryCoordinatorManager + + require Logger + + @aligned_config_file System.get_env("ALIGNED_CONFIG_FILE") + + config_file_path = + case @aligned_config_file do + nil -> raise("ALIGNED_CONFIG_FILE not set in .env") + file -> file + end + + {status, config_json_string} = File.read(config_file_path) + + case status do + :ok -> + Logger.debug("Aligned deployment file read successfully") + + :error -> + raise("Config file not read successfully") + end + + @registry_coordinator_address Jason.decode!(config_json_string) + |> Map.get("addresses") + |> Map.get("registryCoordinator") + + use Ethers.Contract, + abi_file: "priv/abi/IRegistryCoordinator.json", + default_address: @registry_coordinator_address + + def get_registry_coordinator_address() do + @registry_coordinator_address + end + + def is_operator_registered?(operator_address) do + {:ok, operator_address } = Base.decode16(operator_address, case: :mixed) + + case RegistryCoordinatorManager.get_operator_status(operator_address) + |> Ethers.call() do + {:ok, response} -> {:ok, response == 1} + error -> + {:error, error} + end + end +end diff --git a/telemetry_api/lib/telemetry_api/signature_verifier.ex b/telemetry_api/lib/telemetry_api/signature_verifier.ex index 4b7f9ae5f..ccc0a44d9 100644 --- a/telemetry_api/lib/telemetry_api/signature_verifier.ex +++ b/telemetry_api/lib/telemetry_api/signature_verifier.ex @@ -11,7 +11,7 @@ defmodule SignatureVerifier do # Recover the public key from the signature and hashed version defp recover_public_key(hash, signature, recovery_id) do case ExSecp256k1.recover_compact(hash, signature, recovery_id) do - {:ok, public_key} -> public_key + {:ok, public_key} -> {:ok, public_key} _error -> {:error, "Failed to recover public key"} end end @@ -48,8 +48,10 @@ defmodule SignatureVerifier do rs = binary_part(binary_signature, 0, signature_len - 1) recovery_id = Binary.decode_unsigned(binary_part(binary_signature, signature_len - 1, 1)) - recover_public_key(version_hash, rs, recovery_id) - |> public_key_to_address() - |> Base.encode16() + with {:ok, address} <- recover_public_key(version_hash, rs, recovery_id) do + addr = public_key_to_address(address) + |> Base.encode16() + {:ok, addr} + end end end diff --git a/telemetry_api/lib/telemetry_api_web/controllers/operator_controller.ex b/telemetry_api/lib/telemetry_api_web/controllers/operator_controller.ex index 167c34534..d8249ac3e 100644 --- a/telemetry_api/lib/telemetry_api_web/controllers/operator_controller.ex +++ b/telemetry_api/lib/telemetry_api_web/controllers/operator_controller.ex @@ -6,17 +6,27 @@ defmodule TelemetryApiWeb.OperatorController do action_fallback TelemetryApiWeb.FallbackController + defp return_error(conn, message) do + conn + |> put_status(:bad_request) + |> put_resp_content_type("application/json") + |> send_resp(:bad_request, Jason.encode!(%{error: message})) + end + def index(conn, _params) do operators = Operators.list_operators() render(conn, :index, operators: operators) end def create(conn, operator_params) do - with {:ok, %Operator{} = operator} <- Operators.create_operator(operator_params) do - conn - |> put_status(:created) - |> put_resp_header("location", ~p"/api/operators/#{operator}") - |> render(:show, operator: operator) + case Operators.create_operator(operator_params) do + {:ok, %Operator{} = operator} -> + conn + |> put_status(:created) + |> put_resp_header("location", ~p"/api/operators/#{operator}") + |> render(:show, operator: operator) + {:error, message} -> + return_error(conn, message) end end diff --git a/telemetry_api/mix.exs b/telemetry_api/mix.exs index 071dea16b..7a6c0d2dd 100644 --- a/telemetry_api/mix.exs +++ b/telemetry_api/mix.exs @@ -44,6 +44,8 @@ defmodule TelemetryApi.MixProject do {:bandit, "~> 1.5"}, {:ex_keccak, "~> 0.7.5"}, {:ex_secp256k1, "~> 0.7"}, + {:ethers, "~> 0.4.4"}, + {:ethereumex, "~> 0.10"}, ] end diff --git a/telemetry_api/mix.lock b/telemetry_api/mix.lock index b3c2fe97c..ee34e83f1 100644 --- a/telemetry_api/mix.lock +++ b/telemetry_api/mix.lock @@ -6,13 +6,20 @@ "dns_cluster": {:hex, :dns_cluster, "0.1.3", "0bc20a2c88ed6cc494f2964075c359f8c2d00e1bf25518a6a6c7fd277c9b0c66", [:mix], [], "hexpm", "46cb7c4a1b3e52c7ad4cbe33ca5079fbde4840dedeafca2baf77996c2da1bc33"}, "ecto": {:hex, :ecto, "3.12.3", "1a9111560731f6c3606924c81c870a68a34c819f6d4f03822f370ea31a582208", [:mix], [{:decimal, "~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "9efd91506ae722f95e48dc49e70d0cb632ede3b7a23896252a60a14ac6d59165"}, "ecto_sql": {:hex, :ecto_sql, "3.12.0", "73cea17edfa54bde76ee8561b30d29ea08f630959685006d9c6e7d1e59113b7d", [:mix], [{:db_connection, "~> 2.4.1 or ~> 2.5", [hex: :db_connection, repo: "hexpm", optional: false]}, {:ecto, "~> 3.12", [hex: :ecto, repo: "hexpm", optional: false]}, {:myxql, "~> 0.7", [hex: :myxql, repo: "hexpm", optional: true]}, {:postgrex, "~> 0.19 or ~> 1.0", [hex: :postgrex, repo: "hexpm", optional: true]}, {:tds, "~> 2.1.1 or ~> 2.2", [hex: :tds, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4.0 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "dc9e4d206f274f3947e96142a8fdc5f69a2a6a9abb4649ef5c882323b6d512f0"}, + "ethereumex": {:hex, :ethereumex, "0.10.6", "6d75cac39b5b7a720b064fe48563f205d3d9784e5bde25f983dd07cf306c2a6d", [:make, :mix], [{:finch, "~> 0.16", [hex: :finch, repo: "hexpm", optional: false]}, {:jason, "~> 1.4", [hex: :jason, repo: "hexpm", optional: false]}, {:poolboy, "~> 1.5", [hex: :poolboy, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "58cf926239dabf8bd1fc6cf50a37b926274240b7f58ba5b235a20b5500a9a7e1"}, + "ethers": {:hex, :ethers, "0.4.5", "5af10678317ff183617072fc5970ee25d7145846e600db769f2e7a53641e6131", [:mix], [{:ethereumex, "~> 0.10.6", [hex: :ethereumex, repo: "hexpm", optional: false]}, {:ex_abi, "~> 0.7.0", [hex: :ex_abi, repo: "hexpm", optional: false]}, {:ex_rlp, "~> 0.6.0", [hex: :ex_rlp, repo: "hexpm", optional: false]}, {:ex_secp256k1, "~> 0.7.2", [hex: :ex_secp256k1, repo: "hexpm", optional: true]}, {:idna, "~> 6.1", [hex: :idna, repo: "hexpm", optional: false]}, {:jason, "~> 1.4", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "885de526ae5a37bb0cefc882caac2e3b5dd06eff35a9fee43a58523556dda009"}, + "ex_abi": {:hex, :ex_abi, "0.7.3", "5c30551af740d11a10817cb253a7b1d0315f9c02f7bc95f7434885bcff5d9dc5", [:mix], [{:ex_keccak, "~> 0.7.5", [hex: :ex_keccak, repo: "hexpm", optional: false]}, {:jason, "~> 1.4", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "756e3d2211053ca7e4217eae4193c588f3a310066b86171f03131e2400827bae"}, "ex_keccak": {:hex, :ex_keccak, "0.7.5", "f3b733173510d48ae9a1ea1de415e694b2651f35c787e63f33b5ed0013fbfd35", [:mix], [{:rustler, ">= 0.0.0", [hex: :rustler, repo: "hexpm", optional: true]}, {:rustler_precompiled, "~> 0.7", [hex: :rustler_precompiled, repo: "hexpm", optional: false]}], "hexpm", "8a5e1cb7f96fff5e480ff6a121477b90c4fd8c150984086dffd98819f5d83763"}, + "ex_rlp": {:hex, :ex_rlp, "0.6.0", "985391d2356a7cb8712a4a9a2deb93f19f2fbca0323f5c1203fcaf64d077e31e", [:mix], [], "hexpm", "7135db93b861d9e76821039b60b00a6a22d2c4e751bf8c444bffe7a042f1abaf"}, "ex_secp256k1": {:hex, :ex_secp256k1, "0.7.3", "489b6fd57fab5a7259ace927d8cb5171aad835e9c7279c2a859a0483cb069415", [:mix], [{:rustler, ">= 0.0.0", [hex: :rustler, repo: "hexpm", optional: true]}, {:rustler_precompiled, "~> 0.7", [hex: :rustler_precompiled, repo: "hexpm", optional: false]}], "hexpm", "ea63159442f4d8143166cd1507da03edc43216d6e7c6bac4b416bdce04f0daa8"}, + "finch": {:hex, :finch, "0.19.0", "c644641491ea854fc5c1bbaef36bfc764e3f08e7185e1f084e35e0672241b76d", [:mix], [{:mime, "~> 1.0 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:mint, "~> 1.6.2 or ~> 1.7", [hex: :mint, repo: "hexpm", optional: false]}, {:nimble_options, "~> 0.4 or ~> 1.0", [hex: :nimble_options, repo: "hexpm", optional: false]}, {:nimble_pool, "~> 1.1", [hex: :nimble_pool, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "fc5324ce209125d1e2fa0fcd2634601c52a787aff1cd33ee833664a5af4ea2b6"}, "hpax": {:hex, :hpax, "1.0.0", "28dcf54509fe2152a3d040e4e3df5b265dcb6cb532029ecbacf4ce52caea3fd2", [:mix], [], "hexpm", "7f1314731d711e2ca5fdc7fd361296593fc2542570b3105595bb0bc6d0fad601"}, + "idna": {:hex, :idna, "6.1.1", "8a63070e9f7d0c62eb9d9fcb360a7de382448200fbbd1b106cc96d3d8099df8d", [:rebar3], [{:unicode_util_compat, "~> 0.7.0", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm", "92376eb7894412ed19ac475e4a86f7b413c1b9fbb5bd16dccd57934157944cea"}, "jason": {:hex, :jason, "1.4.4", "b9226785a9aa77b6857ca22832cffa5d5011a667207eb2a0ad56adb5db443b8a", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "c5eb0cab91f094599f94d55bc63409236a8ec69a21a67814529e8d5f6cc90b3b"}, - "libsecp256k1": {:hex, :libsecp256k1, "0.1.9", "e725f31364cda7b554d56ce2bb976241303dde5ffd1ad59598513297bf1f2af6", [:make, :mix], [{:mix_erlang_tasks, "0.1.0", [hex: :mix_erlang_tasks, repo: "hexpm", optional: false]}], "hexpm", "93da7c29e892db4d59f7ed394decb6f9c5d653deb88e183a9221e5cc5ca4b987"}, "mime": {:hex, :mime, "2.0.6", "8f18486773d9b15f95f4f4f1e39b710045fa1de891fada4516559967276e4dc2", [:mix], [], "hexpm", "c9945363a6b26d747389aac3643f8e0e09d30499a138ad64fe8fd1d13d9b153e"}, - "mix_erlang_tasks": {:hex, :mix_erlang_tasks, "0.1.0", "36819fec60b80689eb1380938675af215565a89320a9e29c72c70d97512e4649", [:mix], [], "hexpm", "95d2839c422c482a70c08a8702da8242f86b773f8ab6e8602a4eb72da8da04ed"}, + "mint": {:hex, :mint, "1.6.2", "af6d97a4051eee4f05b5500671d47c3a67dac7386045d87a904126fd4bbcea2e", [:mix], [{:castore, "~> 0.1.0 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: true]}, {:hpax, "~> 0.1.1 or ~> 0.2.0 or ~> 1.0", [hex: :hpax, repo: "hexpm", optional: false]}], "hexpm", "5ee441dffc1892f1ae59127f74afe8fd82fda6587794278d924e4d90ea3d63f9"}, + "nimble_options": {:hex, :nimble_options, "1.1.1", "e3a492d54d85fc3fd7c5baf411d9d2852922f66e69476317787a7b2bb000a61b", [:mix], [], "hexpm", "821b2470ca9442c4b6984882fe9bb0389371b8ddec4d45a9504f00a66f650b44"}, + "nimble_pool": {:hex, :nimble_pool, "1.1.0", "bf9c29fbdcba3564a8b800d1eeb5a3c58f36e1e11d7b7fb2e084a643f645f06b", [:mix], [], "hexpm", "af2e4e6b34197db81f7aad230c1118eac993acc0dae6bc83bac0126d4ae0813a"}, "phoenix": {:hex, :phoenix, "1.7.14", "a7d0b3f1bc95987044ddada111e77bd7f75646a08518942c72a8440278ae7825", [:mix], [{:castore, ">= 0.0.0", [hex: :castore, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:phoenix_pubsub, "~> 2.1", [hex: :phoenix_pubsub, repo: "hexpm", optional: false]}, {:phoenix_template, "~> 1.0", [hex: :phoenix_template, repo: "hexpm", optional: false]}, {:phoenix_view, "~> 2.0", [hex: :phoenix_view, repo: "hexpm", optional: true]}, {:plug, "~> 1.14", [hex: :plug, repo: "hexpm", optional: false]}, {:plug_cowboy, "~> 2.7", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:plug_crypto, "~> 1.2 or ~> 2.0", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}, {:websock_adapter, "~> 0.5.3", [hex: :websock_adapter, repo: "hexpm", optional: false]}], "hexpm", "c7859bc56cc5dfef19ecfc240775dae358cbaa530231118a9e014df392ace61a"}, "phoenix_ecto": {:hex, :phoenix_ecto, "4.6.2", "3b83b24ab5a2eb071a20372f740d7118767c272db386831b2e77638c4dcc606d", [:mix], [{:ecto, "~> 3.5", [hex: :ecto, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 2.14.2 or ~> 3.0 or ~> 4.1", [hex: :phoenix_html, repo: "hexpm", optional: true]}, {:plug, "~> 1.9", [hex: :plug, repo: "hexpm", optional: false]}, {:postgrex, "~> 0.16 or ~> 1.0", [hex: :postgrex, repo: "hexpm", optional: true]}], "hexpm", "3f94d025f59de86be00f5f8c5dd7b5965a3298458d21ab1c328488be3b5fcd59"}, "phoenix_html": {:hex, :phoenix_html, "4.1.1", "4c064fd3873d12ebb1388425a8f2a19348cef56e7289e1998e2d2fa758aa982e", [:mix], [], "hexpm", "f2f2df5a72bc9a2f510b21497fd7d2b86d932ec0598f0210fed4114adc546c6f"}, @@ -22,12 +29,14 @@ "phoenix_template": {:hex, :phoenix_template, "1.0.4", "e2092c132f3b5e5b2d49c96695342eb36d0ed514c5b252a77048d5969330d639", [:mix], [{:phoenix_html, "~> 2.14.2 or ~> 3.0 or ~> 4.0", [hex: :phoenix_html, repo: "hexpm", optional: true]}], "hexpm", "2c0c81f0e5c6753faf5cca2f229c9709919aba34fab866d3bc05060c9c444206"}, "plug": {:hex, :plug, "1.16.1", "40c74619c12f82736d2214557dedec2e9762029b2438d6d175c5074c933edc9d", [:mix], [{:mime, "~> 1.0 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:plug_crypto, "~> 1.1.1 or ~> 1.2 or ~> 2.0", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4.3 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "a13ff6b9006b03d7e33874945b2755253841b238c34071ed85b0e86057f8cddc"}, "plug_crypto": {:hex, :plug_crypto, "2.1.0", "f44309c2b06d249c27c8d3f65cfe08158ade08418cf540fd4f72d4d6863abb7b", [:mix], [], "hexpm", "131216a4b030b8f8ce0f26038bc4421ae60e4bb95c5cf5395e1421437824c4fa"}, + "poolboy": {:hex, :poolboy, "1.5.2", "392b007a1693a64540cead79830443abf5762f5d30cf50bc95cb2c1aaafa006b", [:rebar3], [], "hexpm", "dad79704ce5440f3d5a3681c8590b9dc25d1a561e8f5a9c995281012860901e3"}, "postgrex": {:hex, :postgrex, "0.19.1", "73b498508b69aded53907fe48a1fee811be34cc720e69ef4ccd568c8715495ea", [:mix], [{:db_connection, "~> 2.1", [hex: :db_connection, repo: "hexpm", optional: false]}, {:decimal, "~> 1.5 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:table, "~> 0.1.0", [hex: :table, repo: "hexpm", optional: true]}], "hexpm", "8bac7885a18f381e091ec6caf41bda7bb8c77912bb0e9285212829afe5d8a8f8"}, "rustler_precompiled": {:hex, :rustler_precompiled, "0.8.1", "8afe0b6f3a9a677ada046cdd23e3f4c6399618b91a6122289324774961281e1e", [:mix], [{:castore, "~> 0.1 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: false]}, {:rustler, "~> 0.23", [hex: :rustler, repo: "hexpm", optional: true]}], "hexpm", "90b8c2297bf7959cfa1c927b2881faad7bb0707183124955369991b76177a166"}, "telemetry": {:hex, :telemetry, "1.3.0", "fedebbae410d715cf8e7062c96a1ef32ec22e764197f70cda73d82778d61e7a2", [:rebar3], [], "hexpm", "7015fc8919dbe63764f4b4b87a95b7c0996bd539e0d499be6ec9d7f3875b79e6"}, "telemetry_metrics": {:hex, :telemetry_metrics, "1.0.0", "29f5f84991ca98b8eb02fc208b2e6de7c95f8bb2294ef244a176675adc7775df", [:mix], [{:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "f23713b3847286a534e005126d4c959ebcca68ae9582118ce436b521d1d47d5d"}, "telemetry_poller": {:hex, :telemetry_poller, "1.1.0", "58fa7c216257291caaf8d05678c8d01bd45f4bdbc1286838a28c4bb62ef32999", [:rebar3], [{:telemetry, "~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "9eb9d9cbfd81cbd7cdd24682f8711b6e2b691289a0de6826e58452f28c103c8f"}, "thousand_island": {:hex, :thousand_island, "1.3.5", "6022b6338f1635b3d32406ff98d68b843ba73b3aa95cfc27154223244f3a6ca5", [:mix], [{:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "2be6954916fdfe4756af3239fb6b6d75d0b8063b5df03ba76fd8a4c87849e180"}, + "unicode_util_compat": {:hex, :unicode_util_compat, "0.7.0", "bc84380c9ab48177092f43ac89e4dfa2c6d62b40b8bd132b1059ecc7232f9a78", [:rebar3], [], "hexpm", "25eee6d67df61960cf6a794239566599b09e17e668d3700247bc498638152521"}, "websock": {:hex, :websock, "0.5.3", "2f69a6ebe810328555b6fe5c831a851f485e303a7c8ce6c5f675abeb20ebdadc", [:mix], [], "hexpm", "6105453d7fac22c712ad66fab1d45abdf049868f253cf719b625151460b8b453"}, "websock_adapter": {:hex, :websock_adapter, "0.5.7", "65fa74042530064ef0570b75b43f5c49bb8b235d6515671b3d250022cb8a1f9e", [:mix], [{:bandit, ">= 0.6.0", [hex: :bandit, repo: "hexpm", optional: true]}, {:plug, "~> 1.14", [hex: :plug, repo: "hexpm", optional: false]}, {:plug_cowboy, "~> 2.6", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:websock, "~> 0.5", [hex: :websock, repo: "hexpm", optional: false]}], "hexpm", "d0f478ee64deddfec64b800673fd6e0c8888b079d9f3444dd96d2a98383bdbd1"}, } diff --git a/telemetry_api/priv/abi/IRegistryCoordinator.json b/telemetry_api/priv/abi/IRegistryCoordinator.json new file mode 100644 index 000000000..53ece9cf8 --- /dev/null +++ b/telemetry_api/priv/abi/IRegistryCoordinator.json @@ -0,0 +1 @@ +{"abi":[{"type":"function","name":"blsApkRegistry","inputs":[],"outputs":[{"name":"","type":"address","internalType":"contract IBLSApkRegistry"}],"stateMutability":"view"},{"type":"function","name":"ejectOperator","inputs":[{"name":"operator","type":"address","internalType":"address"},{"name":"quorumNumbers","type":"bytes","internalType":"bytes"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"getCurrentQuorumBitmap","inputs":[{"name":"operatorId","type":"bytes32","internalType":"bytes32"}],"outputs":[{"name":"","type":"uint192","internalType":"uint192"}],"stateMutability":"view"},{"type":"function","name":"getOperator","inputs":[{"name":"operator","type":"address","internalType":"address"}],"outputs":[{"name":"","type":"tuple","internalType":"struct IRegistryCoordinator.OperatorInfo","components":[{"name":"operatorId","type":"bytes32","internalType":"bytes32"},{"name":"status","type":"uint8","internalType":"enum IRegistryCoordinator.OperatorStatus"}]}],"stateMutability":"view"},{"type":"function","name":"getOperatorFromId","inputs":[{"name":"operatorId","type":"bytes32","internalType":"bytes32"}],"outputs":[{"name":"operator","type":"address","internalType":"address"}],"stateMutability":"view"},{"type":"function","name":"getOperatorId","inputs":[{"name":"operator","type":"address","internalType":"address"}],"outputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"stateMutability":"view"},{"type":"function","name":"getOperatorSetParams","inputs":[{"name":"quorumNumber","type":"uint8","internalType":"uint8"}],"outputs":[{"name":"","type":"tuple","internalType":"struct IRegistryCoordinator.OperatorSetParam","components":[{"name":"maxOperatorCount","type":"uint32","internalType":"uint32"},{"name":"kickBIPsOfOperatorStake","type":"uint16","internalType":"uint16"},{"name":"kickBIPsOfTotalStake","type":"uint16","internalType":"uint16"}]}],"stateMutability":"view"},{"type":"function","name":"getOperatorStatus","inputs":[{"name":"operator","type":"address","internalType":"address"}],"outputs":[{"name":"","type":"uint8","internalType":"enum IRegistryCoordinator.OperatorStatus"}],"stateMutability":"view"},{"type":"function","name":"getQuorumBitmapAtBlockNumberByIndex","inputs":[{"name":"operatorId","type":"bytes32","internalType":"bytes32"},{"name":"blockNumber","type":"uint32","internalType":"uint32"},{"name":"index","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"uint192","internalType":"uint192"}],"stateMutability":"view"},{"type":"function","name":"getQuorumBitmapHistoryLength","inputs":[{"name":"operatorId","type":"bytes32","internalType":"bytes32"}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"getQuorumBitmapIndicesAtBlockNumber","inputs":[{"name":"blockNumber","type":"uint32","internalType":"uint32"},{"name":"operatorIds","type":"bytes32[]","internalType":"bytes32[]"}],"outputs":[{"name":"","type":"uint32[]","internalType":"uint32[]"}],"stateMutability":"view"},{"type":"function","name":"getQuorumBitmapUpdateByIndex","inputs":[{"name":"operatorId","type":"bytes32","internalType":"bytes32"},{"name":"index","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"tuple","internalType":"struct IRegistryCoordinator.QuorumBitmapUpdate","components":[{"name":"updateBlockNumber","type":"uint32","internalType":"uint32"},{"name":"nextUpdateBlockNumber","type":"uint32","internalType":"uint32"},{"name":"quorumBitmap","type":"uint192","internalType":"uint192"}]}],"stateMutability":"view"},{"type":"function","name":"indexRegistry","inputs":[],"outputs":[{"name":"","type":"address","internalType":"contract IIndexRegistry"}],"stateMutability":"view"},{"type":"function","name":"numRegistries","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"owner","inputs":[],"outputs":[{"name":"","type":"address","internalType":"address"}],"stateMutability":"view"},{"type":"function","name":"pubkeyRegistrationMessageHash","inputs":[{"name":"operator","type":"address","internalType":"address"}],"outputs":[{"name":"","type":"tuple","internalType":"struct BN254.G1Point","components":[{"name":"X","type":"uint256","internalType":"uint256"},{"name":"Y","type":"uint256","internalType":"uint256"}]}],"stateMutability":"view"},{"type":"function","name":"quorumCount","inputs":[],"outputs":[{"name":"","type":"uint8","internalType":"uint8"}],"stateMutability":"view"},{"type":"function","name":"quorumUpdateBlockNumber","inputs":[{"name":"quorumNumber","type":"uint8","internalType":"uint8"}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"registries","inputs":[{"name":"","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"address","internalType":"address"}],"stateMutability":"view"},{"type":"function","name":"stakeRegistry","inputs":[],"outputs":[{"name":"","type":"address","internalType":"contract IStakeRegistry"}],"stateMutability":"view"},{"type":"event","name":"ChurnApproverUpdated","inputs":[{"name":"prevChurnApprover","type":"address","indexed":false,"internalType":"address"},{"name":"newChurnApprover","type":"address","indexed":false,"internalType":"address"}],"anonymous":false},{"type":"event","name":"EjectorUpdated","inputs":[{"name":"prevEjector","type":"address","indexed":false,"internalType":"address"},{"name":"newEjector","type":"address","indexed":false,"internalType":"address"}],"anonymous":false},{"type":"event","name":"OperatorDeregistered","inputs":[{"name":"operator","type":"address","indexed":true,"internalType":"address"},{"name":"operatorId","type":"bytes32","indexed":true,"internalType":"bytes32"}],"anonymous":false},{"type":"event","name":"OperatorRegistered","inputs":[{"name":"operator","type":"address","indexed":true,"internalType":"address"},{"name":"operatorId","type":"bytes32","indexed":true,"internalType":"bytes32"}],"anonymous":false},{"type":"event","name":"OperatorSetParamsUpdated","inputs":[{"name":"quorumNumber","type":"uint8","indexed":true,"internalType":"uint8"},{"name":"operatorSetParams","type":"tuple","indexed":false,"internalType":"struct IRegistryCoordinator.OperatorSetParam","components":[{"name":"maxOperatorCount","type":"uint32","internalType":"uint32"},{"name":"kickBIPsOfOperatorStake","type":"uint16","internalType":"uint16"},{"name":"kickBIPsOfTotalStake","type":"uint16","internalType":"uint16"}]}],"anonymous":false},{"type":"event","name":"QuorumBlockNumberUpdated","inputs":[{"name":"quorumNumber","type":"uint8","indexed":true,"internalType":"uint8"},{"name":"blocknumber","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false}],"bytecode":{"object":"0x","sourceMap":"","linkReferences":{}},"deployedBytecode":{"object":"0x","sourceMap":"","linkReferences":{}},"methodIdentifiers":{"blsApkRegistry()":"5df45946","ejectOperator(address,bytes)":"6e3b17db","getCurrentQuorumBitmap(bytes32)":"871ef049","getOperator(address)":"5865c60c","getOperatorFromId(bytes32)":"296bb064","getOperatorId(address)":"13542a4e","getOperatorSetParams(uint8)":"e65797ad","getOperatorStatus(address)":"fd39105a","getQuorumBitmapAtBlockNumberByIndex(bytes32,uint32,uint256)":"04ec6351","getQuorumBitmapHistoryLength(bytes32)":"03fd3492","getQuorumBitmapIndicesAtBlockNumber(uint32,bytes32[])":"c391425e","getQuorumBitmapUpdateByIndex(bytes32,uint256)":"1eb812da","indexRegistry()":"9e9923c2","numRegistries()":"d72d8dd6","owner()":"8da5cb5b","pubkeyRegistrationMessageHash(address)":"3c2a7f4c","quorumCount()":"9aa1653d","quorumUpdateBlockNumber(uint8)":"249a0c42","registries(uint256)":"6347c900","stakeRegistry()":"68304835"},"rawMetadata":"{\"compiler\":{\"version\":\"0.8.12+commit.f00d7308\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"prevChurnApprover\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newChurnApprover\",\"type\":\"address\"}],\"name\":\"ChurnApproverUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"prevEjector\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newEjector\",\"type\":\"address\"}],\"name\":\"EjectorUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"operatorId\",\"type\":\"bytes32\"}],\"name\":\"OperatorDeregistered\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"operatorId\",\"type\":\"bytes32\"}],\"name\":\"OperatorRegistered\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint8\",\"name\":\"quorumNumber\",\"type\":\"uint8\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"maxOperatorCount\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"kickBIPsOfOperatorStake\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"kickBIPsOfTotalStake\",\"type\":\"uint16\"}],\"indexed\":false,\"internalType\":\"struct IRegistryCoordinator.OperatorSetParam\",\"name\":\"operatorSetParams\",\"type\":\"tuple\"}],\"name\":\"OperatorSetParamsUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint8\",\"name\":\"quorumNumber\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"blocknumber\",\"type\":\"uint256\"}],\"name\":\"QuorumBlockNumberUpdated\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"blsApkRegistry\",\"outputs\":[{\"internalType\":\"contract IBLSApkRegistry\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"quorumNumbers\",\"type\":\"bytes\"}],\"name\":\"ejectOperator\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"operatorId\",\"type\":\"bytes32\"}],\"name\":\"getCurrentQuorumBitmap\",\"outputs\":[{\"internalType\":\"uint192\",\"name\":\"\",\"type\":\"uint192\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"}],\"name\":\"getOperator\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"operatorId\",\"type\":\"bytes32\"},{\"internalType\":\"enum IRegistryCoordinator.OperatorStatus\",\"name\":\"status\",\"type\":\"uint8\"}],\"internalType\":\"struct IRegistryCoordinator.OperatorInfo\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"operatorId\",\"type\":\"bytes32\"}],\"name\":\"getOperatorFromId\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"}],\"name\":\"getOperatorId\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"quorumNumber\",\"type\":\"uint8\"}],\"name\":\"getOperatorSetParams\",\"outputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"maxOperatorCount\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"kickBIPsOfOperatorStake\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"kickBIPsOfTotalStake\",\"type\":\"uint16\"}],\"internalType\":\"struct IRegistryCoordinator.OperatorSetParam\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"}],\"name\":\"getOperatorStatus\",\"outputs\":[{\"internalType\":\"enum IRegistryCoordinator.OperatorStatus\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"operatorId\",\"type\":\"bytes32\"},{\"internalType\":\"uint32\",\"name\":\"blockNumber\",\"type\":\"uint32\"},{\"internalType\":\"uint256\",\"name\":\"index\",\"type\":\"uint256\"}],\"name\":\"getQuorumBitmapAtBlockNumberByIndex\",\"outputs\":[{\"internalType\":\"uint192\",\"name\":\"\",\"type\":\"uint192\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"operatorId\",\"type\":\"bytes32\"}],\"name\":\"getQuorumBitmapHistoryLength\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"blockNumber\",\"type\":\"uint32\"},{\"internalType\":\"bytes32[]\",\"name\":\"operatorIds\",\"type\":\"bytes32[]\"}],\"name\":\"getQuorumBitmapIndicesAtBlockNumber\",\"outputs\":[{\"internalType\":\"uint32[]\",\"name\":\"\",\"type\":\"uint32[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"operatorId\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"index\",\"type\":\"uint256\"}],\"name\":\"getQuorumBitmapUpdateByIndex\",\"outputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"updateBlockNumber\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"nextUpdateBlockNumber\",\"type\":\"uint32\"},{\"internalType\":\"uint192\",\"name\":\"quorumBitmap\",\"type\":\"uint192\"}],\"internalType\":\"struct IRegistryCoordinator.QuorumBitmapUpdate\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"indexRegistry\",\"outputs\":[{\"internalType\":\"contract IIndexRegistry\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"numRegistries\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"}],\"name\":\"pubkeyRegistrationMessageHash\",\"outputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"X\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"Y\",\"type\":\"uint256\"}],\"internalType\":\"struct BN254.G1Point\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"quorumCount\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"quorumNumber\",\"type\":\"uint8\"}],\"name\":\"quorumUpdateBlockNumber\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"registries\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"stakeRegistry\",\"outputs\":[{\"internalType\":\"contract IStakeRegistry\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"author\":\"Layr Labs, Inc.\",\"kind\":\"dev\",\"methods\":{\"ejectOperator(address,bytes)\":{\"params\":{\"operator\":\"is the operator to eject\",\"quorumNumbers\":\"are the quorum numbers to eject the operator from\"}},\"getQuorumBitmapAtBlockNumberByIndex(bytes32,uint32,uint256)\":{\"details\":\"reverts if `index` is incorrect \"},\"pubkeyRegistrationMessageHash(address)\":{\"params\":{\"operator\":\"is the address of the operator registering their BLS public key\"}}},\"title\":\"Interface for a contract that coordinates between various registries for an AVS.\",\"version\":1},\"userdoc\":{\"events\":{\"OperatorDeregistered(address,bytes32)\":{\"notice\":\"Emits when an operator is deregistered\"},\"OperatorRegistered(address,bytes32)\":{\"notice\":\"Emits when an operator is registered\"},\"QuorumBlockNumberUpdated(uint8,uint256)\":{\"notice\":\"emitted when all the operators for a quorum are updated at once\"}},\"kind\":\"user\",\"methods\":{\"blsApkRegistry()\":{\"notice\":\"the BLS Aggregate Pubkey Registry contract that will keep track of operators' BLS aggregate pubkeys per quorum\"},\"ejectOperator(address,bytes)\":{\"notice\":\"Ejects the provided operator from the provided quorums from the AVS\"},\"getCurrentQuorumBitmap(bytes32)\":{\"notice\":\"Returns the current quorum bitmap for the given `operatorId`\"},\"getOperator(address)\":{\"notice\":\"Returns the operator struct for the given `operator`\"},\"getOperatorFromId(bytes32)\":{\"notice\":\"Returns the operator address for the given `operatorId`\"},\"getOperatorId(address)\":{\"notice\":\"Returns the operatorId for the given `operator`\"},\"getOperatorSetParams(uint8)\":{\"notice\":\"Returns the operator set params for the given `quorumNumber`\"},\"getOperatorStatus(address)\":{\"notice\":\"Returns the status for the given `operator`\"},\"getQuorumBitmapAtBlockNumberByIndex(bytes32,uint32,uint256)\":{\"notice\":\"Returns the quorum bitmap for the given `operatorId` at the given `blockNumber` via the `index`\"},\"getQuorumBitmapHistoryLength(bytes32)\":{\"notice\":\"Returns the length of the quorum bitmap history for the given `operatorId`\"},\"getQuorumBitmapIndicesAtBlockNumber(uint32,bytes32[])\":{\"notice\":\"Returns the indices of the quorumBitmaps for the provided `operatorIds` at the given `blockNumber`\"},\"getQuorumBitmapUpdateByIndex(bytes32,uint256)\":{\"notice\":\"Returns the `index`th entry in the operator with `operatorId`'s bitmap history\"},\"indexRegistry()\":{\"notice\":\"the index Registry contract that will keep track of operators' indexes\"},\"numRegistries()\":{\"notice\":\"Returns the number of registries\"},\"owner()\":{\"notice\":\"The owner of the registry coordinator\"},\"pubkeyRegistrationMessageHash(address)\":{\"notice\":\"Returns the message hash that an operator must sign to register their BLS public key.\"},\"quorumCount()\":{\"notice\":\"Returns the number of quorums the registry coordinator has created\"},\"quorumUpdateBlockNumber(uint8)\":{\"notice\":\"returns the blocknumber the quorum was last updated all at once for all operators\"},\"registries(uint256)\":{\"notice\":\"Returns the registry at the desired index\"},\"stakeRegistry()\":{\"notice\":\"the Stake registry contract that will keep track of operators' stakes\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"lib/eigenlayer-middleware/src/interfaces/IRegistryCoordinator.sol\":\"IRegistryCoordinator\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[\":@openzeppelin-upgrades-v4.9.0/=lib/eigenlayer-middleware/lib/eigenlayer-contracts/lib/openzeppelin-contracts-upgradeable-v4.9.0/\",\":@openzeppelin-upgrades/=lib/eigenlayer-middleware/lib/openzeppelin-contracts-upgradeable/\",\":@openzeppelin-v4.9.0/=lib/eigenlayer-middleware/lib/eigenlayer-contracts/lib/openzeppelin-contracts-v4.9.0/\",\":@openzeppelin/=lib/eigenlayer-middleware/lib/openzeppelin-contracts/\",\":ds-test/=lib/eigenlayer-middleware/lib/ds-test/src/\",\":eigenlayer-contracts/=lib/eigenlayer-middleware/lib/eigenlayer-contracts/\",\":eigenlayer-core-contracts/=lib/eigenlayer-middleware/lib/eigenlayer-contracts/src/contracts/core/\",\":eigenlayer-core/=lib/eigenlayer-middleware/lib/eigenlayer-contracts/src/\",\":eigenlayer-middleware/=lib/eigenlayer-middleware/src/\",\":eigenlayer-scripts/=lib/eigenlayer-middleware/lib/eigenlayer-contracts/script/\",\":erc4626-tests/=lib/eigenlayer-middleware/lib/eigenlayer-contracts/lib/openzeppelin-contracts-upgradeable-v4.9.0/lib/erc4626-tests/\",\":forge-std/=lib/forge-std/src/\",\":openzeppelin-contracts-upgradeable-v4.9.0/=lib/eigenlayer-middleware/lib/eigenlayer-contracts/lib/openzeppelin-contracts-upgradeable-v4.9.0/\",\":openzeppelin-contracts-upgradeable/=lib/eigenlayer-middleware/lib/openzeppelin-contracts-upgradeable/\",\":openzeppelin-contracts-v4.9.0/=lib/eigenlayer-middleware/lib/eigenlayer-contracts/lib/openzeppelin-contracts-v4.9.0/\",\":openzeppelin-contracts/=lib/eigenlayer-middleware/lib/openzeppelin-contracts/\",\":openzeppelin/=lib/eigenlayer-middleware/lib/eigenlayer-contracts/lib/openzeppelin-contracts-upgradeable-v4.9.0/contracts/\"]},\"sources\":{\"lib/eigenlayer-middleware/lib/eigenlayer-contracts/src/contracts/interfaces/IBeaconChainOracle.sol\":{\"keccak256\":\"0x0fef07aa6179c77198f1514e12e628aa1c876e04f9c181ec853a322179e5be00\",\"license\":\"BUSL-1.1\",\"urls\":[\"bzz-raw://51438325876cc2d4c77f58488a7e27b488015d1b663c50be6a5cafbd73b9c983\",\"dweb:/ipfs/QmViCuGoYZzi6wtXA8PPKigqVv3KMuNxEVQ1Td9dGqjL18\"]},\"lib/eigenlayer-middleware/lib/eigenlayer-contracts/src/contracts/interfaces/IDelegationManager.sol\":{\"keccak256\":\"0xab76a9f4eff865cbb689f627cf98263488765519d7a4ec5ffbcb0ca4972842f9\",\"license\":\"BUSL-1.1\",\"urls\":[\"bzz-raw://ff57ce18e8350bf39f190645db0988bc0f1279f1872150a114a1b520c38a2914\",\"dweb:/ipfs/QmSsUXkNUqYuJgGRumHTSs9rAaboGjecotcM4xHrdBYWaZ\"]},\"lib/eigenlayer-middleware/lib/eigenlayer-contracts/src/contracts/interfaces/IETHPOSDeposit.sol\":{\"keccak256\":\"0x2e60e5f4b0da0a0a4e2a07c63141120998559970c21deac743ea0c64a60a880c\",\"license\":\"CC0-1.0\",\"urls\":[\"bzz-raw://e635c346bde5b7ade9bcf35bc733081520cb86015be4fbc6e761e6e9482c4c91\",\"dweb:/ipfs/QmRoeazEnbFn5SPSWAkoFK2gSN9DMp3hJAnrLWuL2sKutz\"]},\"lib/eigenlayer-middleware/lib/eigenlayer-contracts/src/contracts/interfaces/IEigenPod.sol\":{\"keccak256\":\"0xb50c36ad96b6679bb80fd8331f949cbfbcba0f529026e1421a4d2bae64396eba\",\"license\":\"BUSL-1.1\",\"urls\":[\"bzz-raw://5719181d780120f1e688c0da276992a8caf185815917f453b3550537c31ed4cc\",\"dweb:/ipfs/QmYprRC5ZEXhz3zAUND5E8Xjn6s5TL8ZF8QbnndVq7aVPR\"]},\"lib/eigenlayer-middleware/lib/eigenlayer-contracts/src/contracts/interfaces/IEigenPodManager.sol\":{\"keccak256\":\"0xd8a64dbed03d3a5cdbefe1af75968f2dde07f973749c2ef5197bf7187c3e448c\",\"license\":\"BUSL-1.1\",\"urls\":[\"bzz-raw://27ccc7c1fd9352e9f9b357c9063d255dc0ed9583f43db09f786ac7497d7846b8\",\"dweb:/ipfs/QmeJzuJkE9m2NUNwZSp4tGZEZmih1LeucePup8hzMVDRbG\"]},\"lib/eigenlayer-middleware/lib/eigenlayer-contracts/src/contracts/interfaces/IPausable.sol\":{\"keccak256\":\"0x98cffc894842947377e24c1d375813a1120dd73a84c29782ab68404e109cb34f\",\"license\":\"BUSL-1.1\",\"urls\":[\"bzz-raw://b3474f6c350ceaee57cbdfb08fb48835d0c6e81ae8ebfbb9667899584a139324\",\"dweb:/ipfs/QmWELKtksdtWxQbqAccd8yGyhKqrgPZXTADKR7BuT27Zg5\"]},\"lib/eigenlayer-middleware/lib/eigenlayer-contracts/src/contracts/interfaces/IPauserRegistry.sol\":{\"keccak256\":\"0x9de8dd682bc0d812bbd6583c0231cbf35448d5eff58b74a93efa64cb9a768c49\",\"license\":\"BUSL-1.1\",\"urls\":[\"bzz-raw://c00d6c675b9c72b092d287fe85fd37782588df32b8eb59ab4c7db7a86be25e7d\",\"dweb:/ipfs/QmeYokY3HhAdbBaCPdHg3PgQEdRCDFEJy3Wf7VtgHBkQSx\"]},\"lib/eigenlayer-middleware/lib/eigenlayer-contracts/src/contracts/interfaces/ISignatureUtils.sol\":{\"keccak256\":\"0x5e52482a31d94401a8502f3014c4aada1142b4450fc0596dff8e1866a85fe092\",\"license\":\"BUSL-1.1\",\"urls\":[\"bzz-raw://17dc326c9361bc1453379f26545963557b2883b0c88bc07d4477e04dbcc0cc8c\",\"dweb:/ipfs/QmZXT7A816W5JH2ymirE2ETaJttqztFCsEL22AV8oEfCK9\"]},\"lib/eigenlayer-middleware/lib/eigenlayer-contracts/src/contracts/interfaces/ISlasher.sol\":{\"keccak256\":\"0x45dfaa2cfdde87f48a6ee38bb6fb739847aef7cf3f6137bdcd8c8a330559ec79\",\"license\":\"BUSL-1.1\",\"urls\":[\"bzz-raw://1b7f6bd75b42fcaa91ceb7140cb2c41926a1fe6ee2d3161e4fe6186b181ba232\",\"dweb:/ipfs/QmZjbdKiSs33C9i3GDc3sdD39Pz4YPkDoKftowoUF4kHmY\"]},\"lib/eigenlayer-middleware/lib/eigenlayer-contracts/src/contracts/interfaces/IStrategy.sol\":{\"keccak256\":\"0xc530c6a944b70051fd0dac0222de9a4b5baadeaf94ad194daac6ad8d2ace7420\",\"license\":\"BUSL-1.1\",\"urls\":[\"bzz-raw://3767df0364ce835b52e786d2851431eb9223fe4747602107505477e162231d73\",\"dweb:/ipfs/QmZkH5bKUygQrJomndNaQqkefVRW4rRefCa8HPJ5HMczxJ\"]},\"lib/eigenlayer-middleware/lib/eigenlayer-contracts/src/contracts/interfaces/IStrategyManager.sol\":{\"keccak256\":\"0x68bf02a443fc8b2f612eba3d39bfefa5f61f78b549f111cdecec5f2c58236a52\",\"license\":\"BUSL-1.1\",\"urls\":[\"bzz-raw://76bc6875ce74128b861fdac5fd1c0c72f3cc9bacf67fa4a73721b95fb23959ef\",\"dweb:/ipfs/QmPix4WJmf9fXyMZxfgwXEHBcg7V4NAbRqs4HUf5YrSJcM\"]},\"lib/eigenlayer-middleware/lib/eigenlayer-contracts/src/contracts/libraries/BeaconChainProofs.sol\":{\"keccak256\":\"0x70d89b05c1c5f47b74a07fbb5a2c05e606fed494e749ea98a9915b7be73df377\",\"license\":\"BUSL-1.1\",\"urls\":[\"bzz-raw://db1d3bfaee69aef53c8b12b492a17584e6d1ac94610cb8b38aad33e1cdd81af7\",\"dweb:/ipfs/QmfVsMTj1hcf9fMEm5RzvtcBN4dMcAKFBgUUDsNDr5XFpq\"]},\"lib/eigenlayer-middleware/lib/eigenlayer-contracts/src/contracts/libraries/Endian.sol\":{\"keccak256\":\"0xf3b72653ba2567a978d4612703fa5f71c5fcd015d8dac7818468f22772d90a9d\",\"license\":\"BUSL-1.1\",\"urls\":[\"bzz-raw://cee9d09370d968138d775c39525db4cd0768d60d17be7685519de12444e7dd2f\",\"dweb:/ipfs/QmUdGh8wpMei3edKiEWA6S96s9dRt4ekZKJ4nau356X8xQ\"]},\"lib/eigenlayer-middleware/lib/eigenlayer-contracts/src/contracts/libraries/Merkle.sol\":{\"keccak256\":\"0x9095fc29b96d102b10c02d44b3a6fbfa25593ef6ae4a810363ab885b9e6b0f71\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://0945132d482d56278edddb1d32209903c4d3839c87ba4317aadd97dc23610d0f\",\"dweb:/ipfs/QmVuM2aLRHxitx4rPx3GTYTBCVNcjYn6sHBRr1biUjLBP5\"]},\"lib/eigenlayer-middleware/lib/openzeppelin-contracts/contracts/proxy/beacon/IBeacon.sol\":{\"keccak256\":\"0xd50a3421ac379ccb1be435fa646d66a65c986b4924f0849839f08692f39dde61\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://ada1e030c0231db8d143b44ce92b4d1158eedb087880cad6d8cc7bd7ebe7b354\",\"dweb:/ipfs/QmWZ2NHZweRpz1U9GF6R1h65ri76dnX7fNxLBeM2t5N5Ce\"]},\"lib/eigenlayer-middleware/lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol\":{\"keccak256\":\"0x9750c6b834f7b43000631af5cc30001c5f547b3ceb3635488f140f60e897ea6b\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://5a7d5b1ef5d8d5889ad2ed89d8619c09383b80b72ab226e0fe7bde1636481e34\",\"dweb:/ipfs/QmebXWgtEfumQGBdVeM6c71McLixYXQP5Bk6kKXuoY4Bmr\"]},\"lib/eigenlayer-middleware/src/interfaces/IBLSApkRegistry.sol\":{\"keccak256\":\"0xc07a5edfd95ab4f16f16a8dc8e76eadf4b0e90fe49db90540d01daaad86898c5\",\"license\":\"BUSL-1.1\",\"urls\":[\"bzz-raw://52b53266450a53da641e82d8ae3be93c5e09f8342b4ea0cc96bb9038d8406354\",\"dweb:/ipfs/QmVuoiQyqPTLCGnyt8zDaxiyaj4ETdgTGKv4MDHWzqEDjp\"]},\"lib/eigenlayer-middleware/src/interfaces/IIndexRegistry.sol\":{\"keccak256\":\"0x83b2d56aacf27e65c4959a832c5de573e013908c044f6e48ea8284ac5282ae2b\",\"license\":\"BUSL-1.1\",\"urls\":[\"bzz-raw://877af382587e96bb39bcc6db8bb5e4b871db5025c52347d4bee9afeaa4a6cc8d\",\"dweb:/ipfs/QmdnhsQCChzq2o5NgbeT3JxSsEcMm1PC9QW6zenZNPjD9F\"]},\"lib/eigenlayer-middleware/src/interfaces/IRegistry.sol\":{\"keccak256\":\"0x51426a17fb7e54bd3720e2890104e97a8559a13ff248b3d6b840916751c143d3\",\"license\":\"BUSL-1.1\",\"urls\":[\"bzz-raw://01f91289e6100d528cb8b318cb14ff22a0bc52882c9d4db41585e030cc9ddc25\",\"dweb:/ipfs/Qmb22nqGrsrtNovHRwbMCvDHGENuxAgrWu3Db4p7Er2MHY\"]},\"lib/eigenlayer-middleware/src/interfaces/IRegistryCoordinator.sol\":{\"keccak256\":\"0xdd8effb082c1d5957d5ff43d7c59497b32866a6d82bcc7d5efa49ea9bc9b3385\",\"license\":\"BUSL-1.1\",\"urls\":[\"bzz-raw://cb33a2a1446585b13b7a509e880c60d658d2d2522ec48a9f02e30d2cff54002d\",\"dweb:/ipfs/QmVNG8ZPZkXzNEadPdTj1uBYLiZdCnYfsE5iGU6nJcJXiD\"]},\"lib/eigenlayer-middleware/src/interfaces/IStakeRegistry.sol\":{\"keccak256\":\"0x1b8b4d757c1b804bc4cf6fbbf8bf8f89ebdeb30a31014751fe7d01deb9d513d4\",\"license\":\"BUSL-1.1\",\"urls\":[\"bzz-raw://984bf2777b898ed187d28997f9783f5c293a1a1848e3e9aa470ce9183d454c97\",\"dweb:/ipfs/Qme3aTpBrkLu8wYHFMZbCfhXHoZ1M6SpXkeC237T9BuU5B\"]},\"lib/eigenlayer-middleware/src/libraries/BN254.sol\":{\"keccak256\":\"0xb428c8d0c3b325507a88a61a80115493eb88606ccc19ed64a31e11294ab853b3\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://d7b6fb935bfe0494e6ff970c8f30a86d5f4cf5c3e0967300c28cd383c043acae\",\"dweb:/ipfs/QmUHfFZaVjLPXhkBmcxrZhAHZaSFQDqXtrLGpjGBQBa5Ki\"]}},\"version\":1}","metadata":{"compiler":{"version":"0.8.12+commit.f00d7308"},"language":"Solidity","output":{"abi":[{"inputs":[{"internalType":"address","name":"prevChurnApprover","type":"address","indexed":false},{"internalType":"address","name":"newChurnApprover","type":"address","indexed":false}],"type":"event","name":"ChurnApproverUpdated","anonymous":false},{"inputs":[{"internalType":"address","name":"prevEjector","type":"address","indexed":false},{"internalType":"address","name":"newEjector","type":"address","indexed":false}],"type":"event","name":"EjectorUpdated","anonymous":false},{"inputs":[{"internalType":"address","name":"operator","type":"address","indexed":true},{"internalType":"bytes32","name":"operatorId","type":"bytes32","indexed":true}],"type":"event","name":"OperatorDeregistered","anonymous":false},{"inputs":[{"internalType":"address","name":"operator","type":"address","indexed":true},{"internalType":"bytes32","name":"operatorId","type":"bytes32","indexed":true}],"type":"event","name":"OperatorRegistered","anonymous":false},{"inputs":[{"internalType":"uint8","name":"quorumNumber","type":"uint8","indexed":true},{"internalType":"struct IRegistryCoordinator.OperatorSetParam","name":"operatorSetParams","type":"tuple","components":[{"internalType":"uint32","name":"maxOperatorCount","type":"uint32"},{"internalType":"uint16","name":"kickBIPsOfOperatorStake","type":"uint16"},{"internalType":"uint16","name":"kickBIPsOfTotalStake","type":"uint16"}],"indexed":false}],"type":"event","name":"OperatorSetParamsUpdated","anonymous":false},{"inputs":[{"internalType":"uint8","name":"quorumNumber","type":"uint8","indexed":true},{"internalType":"uint256","name":"blocknumber","type":"uint256","indexed":false}],"type":"event","name":"QuorumBlockNumberUpdated","anonymous":false},{"inputs":[],"stateMutability":"view","type":"function","name":"blsApkRegistry","outputs":[{"internalType":"contract IBLSApkRegistry","name":"","type":"address"}]},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bytes","name":"quorumNumbers","type":"bytes"}],"stateMutability":"nonpayable","type":"function","name":"ejectOperator"},{"inputs":[{"internalType":"bytes32","name":"operatorId","type":"bytes32"}],"stateMutability":"view","type":"function","name":"getCurrentQuorumBitmap","outputs":[{"internalType":"uint192","name":"","type":"uint192"}]},{"inputs":[{"internalType":"address","name":"operator","type":"address"}],"stateMutability":"view","type":"function","name":"getOperator","outputs":[{"internalType":"struct IRegistryCoordinator.OperatorInfo","name":"","type":"tuple","components":[{"internalType":"bytes32","name":"operatorId","type":"bytes32"},{"internalType":"enum IRegistryCoordinator.OperatorStatus","name":"status","type":"uint8"}]}]},{"inputs":[{"internalType":"bytes32","name":"operatorId","type":"bytes32"}],"stateMutability":"view","type":"function","name":"getOperatorFromId","outputs":[{"internalType":"address","name":"operator","type":"address"}]},{"inputs":[{"internalType":"address","name":"operator","type":"address"}],"stateMutability":"view","type":"function","name":"getOperatorId","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}]},{"inputs":[{"internalType":"uint8","name":"quorumNumber","type":"uint8"}],"stateMutability":"view","type":"function","name":"getOperatorSetParams","outputs":[{"internalType":"struct IRegistryCoordinator.OperatorSetParam","name":"","type":"tuple","components":[{"internalType":"uint32","name":"maxOperatorCount","type":"uint32"},{"internalType":"uint16","name":"kickBIPsOfOperatorStake","type":"uint16"},{"internalType":"uint16","name":"kickBIPsOfTotalStake","type":"uint16"}]}]},{"inputs":[{"internalType":"address","name":"operator","type":"address"}],"stateMutability":"view","type":"function","name":"getOperatorStatus","outputs":[{"internalType":"enum IRegistryCoordinator.OperatorStatus","name":"","type":"uint8"}]},{"inputs":[{"internalType":"bytes32","name":"operatorId","type":"bytes32"},{"internalType":"uint32","name":"blockNumber","type":"uint32"},{"internalType":"uint256","name":"index","type":"uint256"}],"stateMutability":"view","type":"function","name":"getQuorumBitmapAtBlockNumberByIndex","outputs":[{"internalType":"uint192","name":"","type":"uint192"}]},{"inputs":[{"internalType":"bytes32","name":"operatorId","type":"bytes32"}],"stateMutability":"view","type":"function","name":"getQuorumBitmapHistoryLength","outputs":[{"internalType":"uint256","name":"","type":"uint256"}]},{"inputs":[{"internalType":"uint32","name":"blockNumber","type":"uint32"},{"internalType":"bytes32[]","name":"operatorIds","type":"bytes32[]"}],"stateMutability":"view","type":"function","name":"getQuorumBitmapIndicesAtBlockNumber","outputs":[{"internalType":"uint32[]","name":"","type":"uint32[]"}]},{"inputs":[{"internalType":"bytes32","name":"operatorId","type":"bytes32"},{"internalType":"uint256","name":"index","type":"uint256"}],"stateMutability":"view","type":"function","name":"getQuorumBitmapUpdateByIndex","outputs":[{"internalType":"struct IRegistryCoordinator.QuorumBitmapUpdate","name":"","type":"tuple","components":[{"internalType":"uint32","name":"updateBlockNumber","type":"uint32"},{"internalType":"uint32","name":"nextUpdateBlockNumber","type":"uint32"},{"internalType":"uint192","name":"quorumBitmap","type":"uint192"}]}]},{"inputs":[],"stateMutability":"view","type":"function","name":"indexRegistry","outputs":[{"internalType":"contract IIndexRegistry","name":"","type":"address"}]},{"inputs":[],"stateMutability":"view","type":"function","name":"numRegistries","outputs":[{"internalType":"uint256","name":"","type":"uint256"}]},{"inputs":[],"stateMutability":"view","type":"function","name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}]},{"inputs":[{"internalType":"address","name":"operator","type":"address"}],"stateMutability":"view","type":"function","name":"pubkeyRegistrationMessageHash","outputs":[{"internalType":"struct BN254.G1Point","name":"","type":"tuple","components":[{"internalType":"uint256","name":"X","type":"uint256"},{"internalType":"uint256","name":"Y","type":"uint256"}]}]},{"inputs":[],"stateMutability":"view","type":"function","name":"quorumCount","outputs":[{"internalType":"uint8","name":"","type":"uint8"}]},{"inputs":[{"internalType":"uint8","name":"quorumNumber","type":"uint8"}],"stateMutability":"view","type":"function","name":"quorumUpdateBlockNumber","outputs":[{"internalType":"uint256","name":"","type":"uint256"}]},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function","name":"registries","outputs":[{"internalType":"address","name":"","type":"address"}]},{"inputs":[],"stateMutability":"view","type":"function","name":"stakeRegistry","outputs":[{"internalType":"contract IStakeRegistry","name":"","type":"address"}]}],"devdoc":{"kind":"dev","methods":{"ejectOperator(address,bytes)":{"params":{"operator":"is the operator to eject","quorumNumbers":"are the quorum numbers to eject the operator from"}},"getQuorumBitmapAtBlockNumberByIndex(bytes32,uint32,uint256)":{"details":"reverts if `index` is incorrect "},"pubkeyRegistrationMessageHash(address)":{"params":{"operator":"is the address of the operator registering their BLS public key"}}},"version":1},"userdoc":{"kind":"user","methods":{"blsApkRegistry()":{"notice":"the BLS Aggregate Pubkey Registry contract that will keep track of operators' BLS aggregate pubkeys per quorum"},"ejectOperator(address,bytes)":{"notice":"Ejects the provided operator from the provided quorums from the AVS"},"getCurrentQuorumBitmap(bytes32)":{"notice":"Returns the current quorum bitmap for the given `operatorId`"},"getOperator(address)":{"notice":"Returns the operator struct for the given `operator`"},"getOperatorFromId(bytes32)":{"notice":"Returns the operator address for the given `operatorId`"},"getOperatorId(address)":{"notice":"Returns the operatorId for the given `operator`"},"getOperatorSetParams(uint8)":{"notice":"Returns the operator set params for the given `quorumNumber`"},"getOperatorStatus(address)":{"notice":"Returns the status for the given `operator`"},"getQuorumBitmapAtBlockNumberByIndex(bytes32,uint32,uint256)":{"notice":"Returns the quorum bitmap for the given `operatorId` at the given `blockNumber` via the `index`"},"getQuorumBitmapHistoryLength(bytes32)":{"notice":"Returns the length of the quorum bitmap history for the given `operatorId`"},"getQuorumBitmapIndicesAtBlockNumber(uint32,bytes32[])":{"notice":"Returns the indices of the quorumBitmaps for the provided `operatorIds` at the given `blockNumber`"},"getQuorumBitmapUpdateByIndex(bytes32,uint256)":{"notice":"Returns the `index`th entry in the operator with `operatorId`'s bitmap history"},"indexRegistry()":{"notice":"the index Registry contract that will keep track of operators' indexes"},"numRegistries()":{"notice":"Returns the number of registries"},"owner()":{"notice":"The owner of the registry coordinator"},"pubkeyRegistrationMessageHash(address)":{"notice":"Returns the message hash that an operator must sign to register their BLS public key."},"quorumCount()":{"notice":"Returns the number of quorums the registry coordinator has created"},"quorumUpdateBlockNumber(uint8)":{"notice":"returns the blocknumber the quorum was last updated all at once for all operators"},"registries(uint256)":{"notice":"Returns the registry at the desired index"},"stakeRegistry()":{"notice":"the Stake registry contract that will keep track of operators' stakes"}},"version":1}},"settings":{"remappings":["@openzeppelin-upgrades-v4.9.0/=lib/eigenlayer-middleware/lib/eigenlayer-contracts/lib/openzeppelin-contracts-upgradeable-v4.9.0/","@openzeppelin-upgrades/=lib/eigenlayer-middleware/lib/openzeppelin-contracts-upgradeable/","@openzeppelin-v4.9.0/=lib/eigenlayer-middleware/lib/eigenlayer-contracts/lib/openzeppelin-contracts-v4.9.0/","@openzeppelin/=lib/eigenlayer-middleware/lib/openzeppelin-contracts/","ds-test/=lib/eigenlayer-middleware/lib/ds-test/src/","eigenlayer-contracts/=lib/eigenlayer-middleware/lib/eigenlayer-contracts/","eigenlayer-core-contracts/=lib/eigenlayer-middleware/lib/eigenlayer-contracts/src/contracts/core/","eigenlayer-core/=lib/eigenlayer-middleware/lib/eigenlayer-contracts/src/","eigenlayer-middleware/=lib/eigenlayer-middleware/src/","eigenlayer-scripts/=lib/eigenlayer-middleware/lib/eigenlayer-contracts/script/","erc4626-tests/=lib/eigenlayer-middleware/lib/eigenlayer-contracts/lib/openzeppelin-contracts-upgradeable-v4.9.0/lib/erc4626-tests/","forge-std/=lib/forge-std/src/","openzeppelin-contracts-upgradeable-v4.9.0/=lib/eigenlayer-middleware/lib/eigenlayer-contracts/lib/openzeppelin-contracts-upgradeable-v4.9.0/","openzeppelin-contracts-upgradeable/=lib/eigenlayer-middleware/lib/openzeppelin-contracts-upgradeable/","openzeppelin-contracts-v4.9.0/=lib/eigenlayer-middleware/lib/eigenlayer-contracts/lib/openzeppelin-contracts-v4.9.0/","openzeppelin-contracts/=lib/eigenlayer-middleware/lib/openzeppelin-contracts/","openzeppelin/=lib/eigenlayer-middleware/lib/eigenlayer-contracts/lib/openzeppelin-contracts-upgradeable-v4.9.0/contracts/"],"optimizer":{"enabled":true,"runs":200},"metadata":{"bytecodeHash":"ipfs"},"compilationTarget":{"lib/eigenlayer-middleware/src/interfaces/IRegistryCoordinator.sol":"IRegistryCoordinator"},"evmVersion":"london","libraries":{}},"sources":{"lib/eigenlayer-middleware/lib/eigenlayer-contracts/src/contracts/interfaces/IBeaconChainOracle.sol":{"keccak256":"0x0fef07aa6179c77198f1514e12e628aa1c876e04f9c181ec853a322179e5be00","urls":["bzz-raw://51438325876cc2d4c77f58488a7e27b488015d1b663c50be6a5cafbd73b9c983","dweb:/ipfs/QmViCuGoYZzi6wtXA8PPKigqVv3KMuNxEVQ1Td9dGqjL18"],"license":"BUSL-1.1"},"lib/eigenlayer-middleware/lib/eigenlayer-contracts/src/contracts/interfaces/IDelegationManager.sol":{"keccak256":"0xab76a9f4eff865cbb689f627cf98263488765519d7a4ec5ffbcb0ca4972842f9","urls":["bzz-raw://ff57ce18e8350bf39f190645db0988bc0f1279f1872150a114a1b520c38a2914","dweb:/ipfs/QmSsUXkNUqYuJgGRumHTSs9rAaboGjecotcM4xHrdBYWaZ"],"license":"BUSL-1.1"},"lib/eigenlayer-middleware/lib/eigenlayer-contracts/src/contracts/interfaces/IETHPOSDeposit.sol":{"keccak256":"0x2e60e5f4b0da0a0a4e2a07c63141120998559970c21deac743ea0c64a60a880c","urls":["bzz-raw://e635c346bde5b7ade9bcf35bc733081520cb86015be4fbc6e761e6e9482c4c91","dweb:/ipfs/QmRoeazEnbFn5SPSWAkoFK2gSN9DMp3hJAnrLWuL2sKutz"],"license":"CC0-1.0"},"lib/eigenlayer-middleware/lib/eigenlayer-contracts/src/contracts/interfaces/IEigenPod.sol":{"keccak256":"0xb50c36ad96b6679bb80fd8331f949cbfbcba0f529026e1421a4d2bae64396eba","urls":["bzz-raw://5719181d780120f1e688c0da276992a8caf185815917f453b3550537c31ed4cc","dweb:/ipfs/QmYprRC5ZEXhz3zAUND5E8Xjn6s5TL8ZF8QbnndVq7aVPR"],"license":"BUSL-1.1"},"lib/eigenlayer-middleware/lib/eigenlayer-contracts/src/contracts/interfaces/IEigenPodManager.sol":{"keccak256":"0xd8a64dbed03d3a5cdbefe1af75968f2dde07f973749c2ef5197bf7187c3e448c","urls":["bzz-raw://27ccc7c1fd9352e9f9b357c9063d255dc0ed9583f43db09f786ac7497d7846b8","dweb:/ipfs/QmeJzuJkE9m2NUNwZSp4tGZEZmih1LeucePup8hzMVDRbG"],"license":"BUSL-1.1"},"lib/eigenlayer-middleware/lib/eigenlayer-contracts/src/contracts/interfaces/IPausable.sol":{"keccak256":"0x98cffc894842947377e24c1d375813a1120dd73a84c29782ab68404e109cb34f","urls":["bzz-raw://b3474f6c350ceaee57cbdfb08fb48835d0c6e81ae8ebfbb9667899584a139324","dweb:/ipfs/QmWELKtksdtWxQbqAccd8yGyhKqrgPZXTADKR7BuT27Zg5"],"license":"BUSL-1.1"},"lib/eigenlayer-middleware/lib/eigenlayer-contracts/src/contracts/interfaces/IPauserRegistry.sol":{"keccak256":"0x9de8dd682bc0d812bbd6583c0231cbf35448d5eff58b74a93efa64cb9a768c49","urls":["bzz-raw://c00d6c675b9c72b092d287fe85fd37782588df32b8eb59ab4c7db7a86be25e7d","dweb:/ipfs/QmeYokY3HhAdbBaCPdHg3PgQEdRCDFEJy3Wf7VtgHBkQSx"],"license":"BUSL-1.1"},"lib/eigenlayer-middleware/lib/eigenlayer-contracts/src/contracts/interfaces/ISignatureUtils.sol":{"keccak256":"0x5e52482a31d94401a8502f3014c4aada1142b4450fc0596dff8e1866a85fe092","urls":["bzz-raw://17dc326c9361bc1453379f26545963557b2883b0c88bc07d4477e04dbcc0cc8c","dweb:/ipfs/QmZXT7A816W5JH2ymirE2ETaJttqztFCsEL22AV8oEfCK9"],"license":"BUSL-1.1"},"lib/eigenlayer-middleware/lib/eigenlayer-contracts/src/contracts/interfaces/ISlasher.sol":{"keccak256":"0x45dfaa2cfdde87f48a6ee38bb6fb739847aef7cf3f6137bdcd8c8a330559ec79","urls":["bzz-raw://1b7f6bd75b42fcaa91ceb7140cb2c41926a1fe6ee2d3161e4fe6186b181ba232","dweb:/ipfs/QmZjbdKiSs33C9i3GDc3sdD39Pz4YPkDoKftowoUF4kHmY"],"license":"BUSL-1.1"},"lib/eigenlayer-middleware/lib/eigenlayer-contracts/src/contracts/interfaces/IStrategy.sol":{"keccak256":"0xc530c6a944b70051fd0dac0222de9a4b5baadeaf94ad194daac6ad8d2ace7420","urls":["bzz-raw://3767df0364ce835b52e786d2851431eb9223fe4747602107505477e162231d73","dweb:/ipfs/QmZkH5bKUygQrJomndNaQqkefVRW4rRefCa8HPJ5HMczxJ"],"license":"BUSL-1.1"},"lib/eigenlayer-middleware/lib/eigenlayer-contracts/src/contracts/interfaces/IStrategyManager.sol":{"keccak256":"0x68bf02a443fc8b2f612eba3d39bfefa5f61f78b549f111cdecec5f2c58236a52","urls":["bzz-raw://76bc6875ce74128b861fdac5fd1c0c72f3cc9bacf67fa4a73721b95fb23959ef","dweb:/ipfs/QmPix4WJmf9fXyMZxfgwXEHBcg7V4NAbRqs4HUf5YrSJcM"],"license":"BUSL-1.1"},"lib/eigenlayer-middleware/lib/eigenlayer-contracts/src/contracts/libraries/BeaconChainProofs.sol":{"keccak256":"0x70d89b05c1c5f47b74a07fbb5a2c05e606fed494e749ea98a9915b7be73df377","urls":["bzz-raw://db1d3bfaee69aef53c8b12b492a17584e6d1ac94610cb8b38aad33e1cdd81af7","dweb:/ipfs/QmfVsMTj1hcf9fMEm5RzvtcBN4dMcAKFBgUUDsNDr5XFpq"],"license":"BUSL-1.1"},"lib/eigenlayer-middleware/lib/eigenlayer-contracts/src/contracts/libraries/Endian.sol":{"keccak256":"0xf3b72653ba2567a978d4612703fa5f71c5fcd015d8dac7818468f22772d90a9d","urls":["bzz-raw://cee9d09370d968138d775c39525db4cd0768d60d17be7685519de12444e7dd2f","dweb:/ipfs/QmUdGh8wpMei3edKiEWA6S96s9dRt4ekZKJ4nau356X8xQ"],"license":"BUSL-1.1"},"lib/eigenlayer-middleware/lib/eigenlayer-contracts/src/contracts/libraries/Merkle.sol":{"keccak256":"0x9095fc29b96d102b10c02d44b3a6fbfa25593ef6ae4a810363ab885b9e6b0f71","urls":["bzz-raw://0945132d482d56278edddb1d32209903c4d3839c87ba4317aadd97dc23610d0f","dweb:/ipfs/QmVuM2aLRHxitx4rPx3GTYTBCVNcjYn6sHBRr1biUjLBP5"],"license":"MIT"},"lib/eigenlayer-middleware/lib/openzeppelin-contracts/contracts/proxy/beacon/IBeacon.sol":{"keccak256":"0xd50a3421ac379ccb1be435fa646d66a65c986b4924f0849839f08692f39dde61","urls":["bzz-raw://ada1e030c0231db8d143b44ce92b4d1158eedb087880cad6d8cc7bd7ebe7b354","dweb:/ipfs/QmWZ2NHZweRpz1U9GF6R1h65ri76dnX7fNxLBeM2t5N5Ce"],"license":"MIT"},"lib/eigenlayer-middleware/lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol":{"keccak256":"0x9750c6b834f7b43000631af5cc30001c5f547b3ceb3635488f140f60e897ea6b","urls":["bzz-raw://5a7d5b1ef5d8d5889ad2ed89d8619c09383b80b72ab226e0fe7bde1636481e34","dweb:/ipfs/QmebXWgtEfumQGBdVeM6c71McLixYXQP5Bk6kKXuoY4Bmr"],"license":"MIT"},"lib/eigenlayer-middleware/src/interfaces/IBLSApkRegistry.sol":{"keccak256":"0xc07a5edfd95ab4f16f16a8dc8e76eadf4b0e90fe49db90540d01daaad86898c5","urls":["bzz-raw://52b53266450a53da641e82d8ae3be93c5e09f8342b4ea0cc96bb9038d8406354","dweb:/ipfs/QmVuoiQyqPTLCGnyt8zDaxiyaj4ETdgTGKv4MDHWzqEDjp"],"license":"BUSL-1.1"},"lib/eigenlayer-middleware/src/interfaces/IIndexRegistry.sol":{"keccak256":"0x83b2d56aacf27e65c4959a832c5de573e013908c044f6e48ea8284ac5282ae2b","urls":["bzz-raw://877af382587e96bb39bcc6db8bb5e4b871db5025c52347d4bee9afeaa4a6cc8d","dweb:/ipfs/QmdnhsQCChzq2o5NgbeT3JxSsEcMm1PC9QW6zenZNPjD9F"],"license":"BUSL-1.1"},"lib/eigenlayer-middleware/src/interfaces/IRegistry.sol":{"keccak256":"0x51426a17fb7e54bd3720e2890104e97a8559a13ff248b3d6b840916751c143d3","urls":["bzz-raw://01f91289e6100d528cb8b318cb14ff22a0bc52882c9d4db41585e030cc9ddc25","dweb:/ipfs/Qmb22nqGrsrtNovHRwbMCvDHGENuxAgrWu3Db4p7Er2MHY"],"license":"BUSL-1.1"},"lib/eigenlayer-middleware/src/interfaces/IRegistryCoordinator.sol":{"keccak256":"0xdd8effb082c1d5957d5ff43d7c59497b32866a6d82bcc7d5efa49ea9bc9b3385","urls":["bzz-raw://cb33a2a1446585b13b7a509e880c60d658d2d2522ec48a9f02e30d2cff54002d","dweb:/ipfs/QmVNG8ZPZkXzNEadPdTj1uBYLiZdCnYfsE5iGU6nJcJXiD"],"license":"BUSL-1.1"},"lib/eigenlayer-middleware/src/interfaces/IStakeRegistry.sol":{"keccak256":"0x1b8b4d757c1b804bc4cf6fbbf8bf8f89ebdeb30a31014751fe7d01deb9d513d4","urls":["bzz-raw://984bf2777b898ed187d28997f9783f5c293a1a1848e3e9aa470ce9183d454c97","dweb:/ipfs/Qme3aTpBrkLu8wYHFMZbCfhXHoZ1M6SpXkeC237T9BuU5B"],"license":"BUSL-1.1"},"lib/eigenlayer-middleware/src/libraries/BN254.sol":{"keccak256":"0xb428c8d0c3b325507a88a61a80115493eb88606ccc19ed64a31e11294ab853b3","urls":["bzz-raw://d7b6fb935bfe0494e6ff970c8f30a86d5f4cf5c3e0967300c28cd383c043acae","dweb:/ipfs/QmUHfFZaVjLPXhkBmcxrZhAHZaSFQDqXtrLGpjGBQBa5Ki"],"license":"MIT"}},"version":1},"id":130} \ No newline at end of file diff --git a/telemetry_api/start.sh b/telemetry_api/start.sh new file mode 100755 index 000000000..e93cc0733 --- /dev/null +++ b/telemetry_api/start.sh @@ -0,0 +1,7 @@ +#!/bin/bash + +source .env.dev + +mix compile --force #force recompile to get the latest .env values + +mix phx.server From c796740a52c694ba7fec9f8d4fa68447d8932741 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Avila=20Gast=C3=B3n?= <72628438+avilagaston9@users.noreply.github.com> Date: Tue, 1 Oct 2024 13:41:42 -0300 Subject: [PATCH 11/55] feat(telemetry): modify the aggregator to use the elixir Tracker (#1105) --- aggregator/internal/pkg/aggregator.go | 38 +++-- aggregator/internal/pkg/server.go | 1 + aggregator/internal/pkg/telemetry.go | 134 ++++++++++++++++++ config-files/config-aggregator.yaml | 1 + core/config/aggregator.go | 8 +- telemetry_api/lib/telemetry_api/traces.ex | 107 ++++++++++++-- .../controllers/trace_controller.ex | 43 +++++- .../controllers/trace_json.ex | 12 +- telemetry_api/lib/telemetry_api_web/router.ex | 3 + 9 files changed, 324 insertions(+), 23 deletions(-) create mode 100644 aggregator/internal/pkg/telemetry.go diff --git a/aggregator/internal/pkg/aggregator.go b/aggregator/internal/pkg/aggregator.go index 477112f68..80a8e9406 100644 --- a/aggregator/internal/pkg/aggregator.go +++ b/aggregator/internal/pkg/aggregator.go @@ -12,7 +12,6 @@ import ( "github.com/prometheus/client_golang/prometheus" "github.com/yetanotherco/aligned_layer/metrics" - "github.com/Layr-Labs/eigensdk-go/chainio/clients" sdkclients "github.com/Layr-Labs/eigensdk-go/chainio/clients" "github.com/Layr-Labs/eigensdk-go/logging" "github.com/Layr-Labs/eigensdk-go/services/avsregistry" @@ -86,8 +85,12 @@ type Aggregator struct { logger logging.Logger + // Metrics metricsReg *prometheus.Registry metrics *metrics.Metrics + + // Telemetry + telemetry *Telemetry } func NewAggregator(aggregatorConfig config.AggregatorConfig) (*Aggregator, error) { @@ -125,7 +128,7 @@ func NewAggregator(aggregatorConfig config.AggregatorConfig) (*Aggregator, error aggregatorPrivateKey := aggregatorConfig.EcdsaConfig.PrivateKey logger := aggregatorConfig.BaseConfig.Logger - clients, err := clients.BuildAll(chainioConfig, aggregatorPrivateKey, logger) + clients, err := sdkclients.BuildAll(chainioConfig, aggregatorPrivateKey, logger) if err != nil { logger.Errorf("Cannot create sdk clients", "err", err) return nil, err @@ -154,6 +157,9 @@ func NewAggregator(aggregatorConfig config.AggregatorConfig) (*Aggregator, error reg := prometheus.NewRegistry() aggregatorMetrics := metrics.NewMetrics(aggregatorConfig.Aggregator.MetricsIpPortAddress, reg, logger) + // Telemetry + aggregatorTelemetry := NewTelemetry(aggregatorConfig.Aggregator.TelemetryIpPortAddress, logger) + nextBatchIndex := uint32(0) aggregator := Aggregator{ @@ -176,6 +182,7 @@ func NewAggregator(aggregatorConfig config.AggregatorConfig) (*Aggregator, error logger: logger, metricsReg: reg, metrics: aggregatorMetrics, + telemetry: aggregatorTelemetry, } return &aggregator, nil @@ -216,9 +223,20 @@ func (agg *Aggregator) Start(ctx context.Context) error { const MaxSentTxRetries = 5 func (agg *Aggregator) handleBlsAggServiceResponse(blsAggServiceResp blsagg.BlsAggregationServiceResponse) { + agg.taskMutex.Lock() + agg.AggregatorConfig.BaseConfig.Logger.Info("- Locked Resources: Fetching task data") + batchIdentifierHash := agg.batchesIdentifierHashByIdx[blsAggServiceResp.TaskIndex] + batchData := agg.batchDataByIdentifierHash[batchIdentifierHash] + taskCreatedBlock := agg.batchCreatedBlockByIdx[blsAggServiceResp.TaskIndex] + agg.taskMutex.Unlock() + agg.AggregatorConfig.BaseConfig.Logger.Info("- Unlocked Resources: Fetching task data") + + // Finish task trace once the task is processed (either successfully or not) + defer agg.telemetry.FinishTrace(batchData.BatchMerkleRoot) + if blsAggServiceResp.Err != nil { + agg.telemetry.LogTaskError(batchData.BatchMerkleRoot, blsAggServiceResp.Err) agg.taskMutex.Lock() - batchIdentifierHash := agg.batchesIdentifierHashByIdx[blsAggServiceResp.TaskIndex] agg.logger.Error("BlsAggregationServiceResponse contains an error", "err", blsAggServiceResp.Err, "batchIdentifierHash", hex.EncodeToString(batchIdentifierHash[:])) agg.logger.Info("- Locking task mutex: Delete task from operator map", "taskIndex", blsAggServiceResp.TaskIndex) @@ -249,18 +267,18 @@ func (agg *Aggregator) handleBlsAggServiceResponse(blsAggServiceResp blsagg.BlsA NonSignerStakeIndices: blsAggServiceResp.NonSignerStakeIndices, } + agg.logger.Info("- Locking task mutex: Delete task from operator map", "taskIndex", blsAggServiceResp.TaskIndex) agg.taskMutex.Lock() - agg.AggregatorConfig.BaseConfig.Logger.Info("- Locked Resources: Fetching merkle root") - batchIdentifierHash := agg.batchesIdentifierHashByIdx[blsAggServiceResp.TaskIndex] - batchData := agg.batchDataByIdentifierHash[batchIdentifierHash] - taskCreatedBlock := agg.batchCreatedBlockByIdx[blsAggServiceResp.TaskIndex] // Delete the task from the map delete(agg.operatorRespondedBatch, blsAggServiceResp.TaskIndex) - agg.AggregatorConfig.BaseConfig.Logger.Info("- Unlocked Resources: Fetching merkle root") + agg.logger.Info("- Unlocking task mutex: Delete task from operator map", "taskIndex", blsAggServiceResp.TaskIndex) + agg.taskMutex.Unlock() + agg.telemetry.LogQuorumReached(batchData.BatchMerkleRoot) + agg.logger.Info("Threshold reached", "taskIndex", blsAggServiceResp.TaskIndex, "batchIdentifierHash", "0x"+hex.EncodeToString(batchIdentifierHash[:])) @@ -282,7 +300,7 @@ func (agg *Aggregator) handleBlsAggServiceResponse(blsAggServiceResp blsagg.BlsA agg.logger.Info("Aggregator successfully responded to task", "taskIndex", blsAggServiceResp.TaskIndex, "batchIdentifierHash", "0x"+hex.EncodeToString(batchIdentifierHash[:])) - + return } @@ -312,6 +330,7 @@ func (agg *Aggregator) sendAggregatedResponse(batchIdentifierHash [32]byte, batc if err != nil { agg.walletMutex.Unlock() agg.logger.Infof("- Unlocked Wallet Resources: Error sending aggregated response for batch %s. Error: %s", hex.EncodeToString(batchIdentifierHash[:]), err) + agg.telemetry.LogTaskError(batchMerkleRoot, err) return nil, err } @@ -330,6 +349,7 @@ func (agg *Aggregator) sendAggregatedResponse(batchIdentifierHash [32]byte, batc } func (agg *Aggregator) AddNewTask(batchMerkleRoot [32]byte, senderAddress [20]byte, taskCreatedBlock uint32) { + agg.telemetry.InitNewTrace(batchMerkleRoot) batchIdentifier := append(batchMerkleRoot[:], senderAddress[:]...) var batchIdentifierHash = *(*[32]byte)(crypto.Keccak256(batchIdentifier)) diff --git a/aggregator/internal/pkg/server.go b/aggregator/internal/pkg/server.go index ec7f4fa85..9744fa212 100644 --- a/aggregator/internal/pkg/server.go +++ b/aggregator/internal/pkg/server.go @@ -54,6 +54,7 @@ func (agg *Aggregator) ProcessOperatorSignedTaskResponseV2(signedTaskResponse *t "SenderAddress", "0x"+hex.EncodeToString(signedTaskResponse.SenderAddress[:]), "BatchIdentifierHash", "0x"+hex.EncodeToString(signedTaskResponse.BatchIdentifierHash[:]), "operatorId", hex.EncodeToString(signedTaskResponse.OperatorId[:])) + agg.telemetry.LogOperatorResponse(signedTaskResponse.BatchMerkleRoot, signedTaskResponse.OperatorId) taskIndex := uint32(0) ok := false diff --git a/aggregator/internal/pkg/telemetry.go b/aggregator/internal/pkg/telemetry.go new file mode 100644 index 000000000..f2e55363a --- /dev/null +++ b/aggregator/internal/pkg/telemetry.go @@ -0,0 +1,134 @@ +package pkg + +import ( + "bytes" + "encoding/hex" + "encoding/json" + "fmt" + "io" + "net/http" + "net/url" + "time" + + "github.com/Layr-Labs/eigensdk-go/logging" +) + +type TraceMessage struct { + MerkleRoot string `json:"merkle_root"` +} + +type OperatorResponseMessage struct { + MerkleRoot string `json:"merkle_root"` + OperatorId string `json:"operator_id"` +} +type QuorumReachedMessage struct { + MerkleRoot string `json:"merkle_root"` +} + +type TaskErrorMessage struct { + MerkleRoot string `json:"merkle_root"` + TaskError string `json:"error"` +} + +type Telemetry struct { + client *http.Client + baseURL *url.URL + logger logging.Logger +} + +func NewTelemetry(serverAddress string, logger logging.Logger) *Telemetry { + client := &http.Client{} + + baseURL := &url.URL{ + Scheme: "http", + Host: serverAddress, + } + logger.Info("[Telemetry] Starting Telemetry client.", "server_address", + serverAddress) + + return &Telemetry{ + client: client, + baseURL: baseURL, + logger: logger, + } +} + +func (t *Telemetry) InitNewTrace(batchMerkleRoot [32]byte) { + body := TraceMessage{ + MerkleRoot: fmt.Sprintf("0x%s", hex.EncodeToString(batchMerkleRoot[:])), + } + if err := t.sendTelemetryMessage("/api/initTaskTrace", body); err != nil { + t.logger.Error("[Telemetry] Error in InitNewTrace", "error", err) + } +} + +func (t *Telemetry) LogOperatorResponse(batchMerkleRoot [32]byte, operatorId [32]byte) { + body := OperatorResponseMessage{ + MerkleRoot: fmt.Sprintf("0x%s", hex.EncodeToString(batchMerkleRoot[:])), + OperatorId: fmt.Sprintf("0x%s", hex.EncodeToString(operatorId[:])), + } + if err := t.sendTelemetryMessage("/api/operatorResponse", body); err != nil { + t.logger.Error("[Telemetry] Error in LogOperatorResponse", "error", err) + } +} + +func (t *Telemetry) LogQuorumReached(batchMerkleRoot [32]byte) { + body := QuorumReachedMessage{ + MerkleRoot: fmt.Sprintf("0x%s", hex.EncodeToString(batchMerkleRoot[:])), + } + if err := t.sendTelemetryMessage("/api/quorumReached", body); err != nil { + t.logger.Error("[Telemetry] Error in LogQuorumReached", "error", err) + } +} + +func (t *Telemetry) LogTaskError(batchMerkleRoot [32]byte, taskError error) { + body := TaskErrorMessage{ + MerkleRoot: fmt.Sprintf("0x%s", hex.EncodeToString(batchMerkleRoot[:])), + TaskError: taskError.Error(), + } + if err := t.sendTelemetryMessage("/api/taskError", body); err != nil { + t.logger.Error("[Telemetry] Error in LogTaskError", "error", err) + } +} + +func (t *Telemetry) FinishTrace(batchMerkleRoot [32]byte) { + // In order to wait for all operator responses, even if the quorum is reached, this function has a delayed execution + go func() { + time.Sleep(10 * time.Second) + body := TraceMessage{ + MerkleRoot: fmt.Sprintf("0x%s", hex.EncodeToString(batchMerkleRoot[:])), + } + if err := t.sendTelemetryMessage("/api/finishTaskTrace", body); err != nil { + t.logger.Error("[Telemetry] Error in FinishTrace", "error", err) + } + }() +} + +func (t *Telemetry) sendTelemetryMessage(endpoint string, message interface{}) error { + encodedBody, err := json.Marshal(message) + if err != nil { + t.logger.Error("[Telemetry] Error marshalling JSON", "error", err) + return fmt.Errorf("error marshalling JSON: %w", err) + } + + t.logger.Info("[Telemetry] Sending message.", "endpoint", endpoint, "message", message) + + fullURL := t.baseURL.ResolveReference(&url.URL{Path: endpoint}) + + resp, err := t.client.Post(fullURL.String(), "application/json", bytes.NewBuffer(encodedBody)) + if err != nil { + t.logger.Error("[Telemetry] Error sending POST request", "error", err) + return fmt.Errorf("error making POST request: %w", err) + } + defer resp.Body.Close() + + respBody, err := io.ReadAll(resp.Body) + if err != nil { + t.logger.Error("[Telemetry] Error reading response body", "error", err) + return fmt.Errorf("error reading response body: %w", err) + } + + t.logger.Info("[Telemetry] Response received", "status", resp.Status, "response_body", string(respBody)) + + return nil +} diff --git a/config-files/config-aggregator.yaml b/config-files/config-aggregator.yaml index 5bd1fb8cd..0d07f81b0 100644 --- a/config-files/config-aggregator.yaml +++ b/config-files/config-aggregator.yaml @@ -34,6 +34,7 @@ aggregator: avs_service_manager_address: 0xc3e53F4d16Ae77Db1c982e75a937B9f60FE63690 enable_metrics: true metrics_ip_port_address: localhost:9091 + telemetry_ip_port_address: localhost:4000 ## Operator Configurations # operator: # aggregator_rpc_server_ip_port_address: localhost:8090 diff --git a/core/config/aggregator.go b/core/config/aggregator.go index 2ba806c74..740e75ae0 100644 --- a/core/config/aggregator.go +++ b/core/config/aggregator.go @@ -2,10 +2,11 @@ package config import ( "errors" - sdkutils "github.com/Layr-Labs/eigensdk-go/utils" - "github.com/ethereum/go-ethereum/common" "log" "os" + + sdkutils "github.com/Layr-Labs/eigensdk-go/utils" + "github.com/ethereum/go-ethereum/common" ) type AggregatorConfig struct { @@ -18,6 +19,7 @@ type AggregatorConfig struct { AvsServiceManagerAddress common.Address EnableMetrics bool MetricsIpPortAddress string + TelemetryIpPortAddress string } } @@ -28,6 +30,7 @@ type AggregatorConfigFromYaml struct { AvsServiceManagerAddress common.Address `yaml:"avs_service_manager_address"` EnableMetrics bool `yaml:"enable_metrics"` MetricsIpPortAddress string `yaml:"metrics_ip_port_address"` + TelemetryIpPortAddress string `yaml:"telemetry_ip_port_address"` } `yaml:"aggregator"` } @@ -68,6 +71,7 @@ func NewAggregatorConfig(configFilePath string) *AggregatorConfig { AvsServiceManagerAddress common.Address EnableMetrics bool MetricsIpPortAddress string + TelemetryIpPortAddress string }(aggregatorConfigFromYaml.Aggregator), } } diff --git a/telemetry_api/lib/telemetry_api/traces.ex b/telemetry_api/lib/telemetry_api/traces.ex index d1908c119..2f6772178 100644 --- a/telemetry_api/lib/telemetry_api/traces.ex +++ b/telemetry_api/lib/telemetry_api/traces.ex @@ -21,19 +21,96 @@ defmodule TelemetryApi.Traces do {:ok, "merkle_root"} """ def create_task_trace(merkle_root) do - span_ctx = Tracer.start_span( - "Task: #{merkle_root}", - %{attributes: [ - {:merkle_root, merkle_root} - ]} + span_ctx = + Tracer.start_span( + "Task: #{merkle_root}", + %{ + attributes: [ + {:merkle_root, merkle_root} + ] + } ) + ctx = Ctx.get_current() - + TraceStore.store_trace(merkle_root, %Trace{ parent_span: span_ctx, context: ctx }) - IO.inspect(merkle_root) + + IO.inspect("New task trace with merkle_root: #{IO.inspect(merkle_root)}") + {:ok, merkle_root} + end + + @doc """ + Registers an operator response in the task trace. + + ## Examples + + iex> merkle_root = "0x1234567890abcdef" + iex> operator_id = "0x..." + iex> register_operator_response(merkle_root, operator_id) + :ok + """ + def register_operator_response(merkle_root, operator_id) do + add_event( + merkle_root, + "Operator ID: #{operator_id}", + [ + {:merkle_root, merkle_root}, + {:operator_id, operator_id} + ] + ) + + IO.inspect( + "Operator response included. merkle_root: #{IO.inspect(merkle_root)} operator_id: #{IO.inspect(operator_id)}" + ) + + {:ok, operator_id} + end + + @doc """ + Registers a reached quorum in the task trace. + + ## Examples + + iex> merkle_root = "0x1234567890abcdef" + iex> quorum_reached(merkle_root) + :ok + """ + def quorum_reached(merkle_root) do + add_event( + merkle_root, + "Quorum Reached", + [] + ) + + IO.inspect("Reached quorum registered. merkle_root: #{IO.inspect(merkle_root)}") + + {:ok, merkle_root} + end + + @doc """ + Registers an error in the task trace. + + ## Examples + + iex> merkle_root = "0x1234567890abcdef" + iex> error = "Some error.." + iex> task_error(merkle_root, error) + :ok + """ + def task_error(merkle_root, error) do + add_event( + merkle_root, + "Batch verification failed", + [ + {:status, "error"}, + {:error, error} + ] + ) + + IO.inspect("Task error registered. merkle_root: #{IO.inspect(merkle_root)}") {:ok, merkle_root} end @@ -63,8 +140,22 @@ defmodule TelemetryApi.Traces do # Clean up the context from the Agent TraceStore.delete_trace(merkle_root) - IO.inspect(merkle_root) + IO.inspect("Finished task trace with merkle_root: #{IO.inspect(merkle_root)}.") :ok end end + + defp add_event(merkle_root, event_name, event_attributes) do + case TraceStore.get_trace(merkle_root) do + nil -> + IO.inspect("Context not found for #{merkle_root}") + {:error, "Context not found for #{merkle_root}"} + + trace -> + Ctx.attach(trace.context) + Tracer.set_current_span(trace.parent_span) + + Tracer.add_event(event_name, event_attributes) + end + end end diff --git a/telemetry_api/lib/telemetry_api_web/controllers/trace_controller.ex b/telemetry_api/lib/telemetry_api_web/controllers/trace_controller.ex index 28c493d3c..27091f237 100644 --- a/telemetry_api/lib/telemetry_api_web/controllers/trace_controller.ex +++ b/telemetry_api/lib/telemetry_api_web/controllers/trace_controller.ex @@ -13,7 +13,46 @@ defmodule TelemetryApiWeb.TraceController do with {:ok, merkle_root} <- Traces.create_task_trace(merkle_root) do conn |> put_status(:created) - |> render(:show, merkle_root: merkle_root) + |> render(:show_merkle, merkle_root: merkle_root) + end + end + + @doc """ + Register an operator response in the trace of the given merkle_root + Method: POST operatorResponse + """ + def register_operator_response(conn, %{ + "merkle_root" => merkle_root, + "operator_id" => operator_id + }) do + with {:ok, operator_id} <- Traces.register_operator_response(merkle_root, operator_id) do + conn + |> put_status(:ok) + |> render(:show_operator, operator_id: operator_id) + end + end + + @doc """ + Registers a reached quorum in the trace of the given merkle_root + Method: POST quorumReached + """ + def quorum_reached(conn, %{"merkle_root" => merkle_root}) do + with {:ok, merkle_root} <- Traces.quorum_reached(merkle_root) do + conn + |> put_status(:ok) + |> render(:show_merkle, merkle_root: merkle_root) + end + end + + @doc """ + Registers an error in the trace of the given merkle_root + Method: POST taskError + """ + def task_error(conn, %{"merkle_root" => merkle_root, "error" => error}) do + with {:ok, merkle_root} <- Traces.task_error(merkle_root, error) do + conn + |> put_status(:ok) + |> render(:show_merkle, merkle_root: merkle_root) end end @@ -25,7 +64,7 @@ defmodule TelemetryApiWeb.TraceController do with :ok <- Traces.finish_task_trace(merkle_root) do conn |> put_status(:ok) - |> render(:show, merkle_root: merkle_root) + |> render(:show_merkle, merkle_root: merkle_root) end end end diff --git a/telemetry_api/lib/telemetry_api_web/controllers/trace_json.ex b/telemetry_api/lib/telemetry_api_web/controllers/trace_json.ex index ff7f0b2a4..c0bda7cc7 100644 --- a/telemetry_api/lib/telemetry_api_web/controllers/trace_json.ex +++ b/telemetry_api/lib/telemetry_api_web/controllers/trace_json.ex @@ -1,11 +1,19 @@ defmodule TelemetryApiWeb.TraceJSON do - @doc """ """ - def show(%{merkle_root: merkle_root}) do + def show_merkle(%{merkle_root: merkle_root}) do %{ merkle_root: merkle_root } end + + @doc """ + + """ + def show_operator(%{operator_id: operator_id}) do + %{ + operator_id: operator_id + } + end end diff --git a/telemetry_api/lib/telemetry_api_web/router.ex b/telemetry_api/lib/telemetry_api_web/router.ex index 0a126a5be..6da70a2c1 100644 --- a/telemetry_api/lib/telemetry_api_web/router.ex +++ b/telemetry_api/lib/telemetry_api_web/router.ex @@ -10,6 +10,9 @@ defmodule TelemetryApiWeb.Router do resources "/operators", OperatorController, only: [:index, :show, :create] post "/initTaskTrace", TraceController, :create_task_trace + post "/operatorResponse", TraceController, :register_operator_response + post "/quorumReached", TraceController, :quorum_reached + post "/taskError", TraceController, :task_error post "/finishTaskTrace", TraceController, :finish_task_trace end From 54eb9fbdfd6bce476adf3bb448d50b5b2471c4ef Mon Sep 17 00:00:00 2001 From: Julian Ventura <43799596+JulianVentura@users.noreply.github.com> Date: Tue, 1 Oct 2024 13:54:49 -0300 Subject: [PATCH 12/55] feat: Add operators data fetch at startup (#1108) Co-authored-by: Julian Ventura --- Makefile | 3 + config-files/config-operator-2.yaml | 2 +- config-files/config-operator-3.yaml | 2 +- telemetry_api/.env.dev | 3 +- telemetry_api/.gitignore | 2 + telemetry_api/config/runtime.exs | 2 +- telemetry_api/ecto_setup_db.sh | 12 ++- .../lib/telemetry_api/application.ex | 7 +- .../contract_managers/delegation_manager.ex | 53 +++++++++++ .../operator_state_retriever.ex | 74 ++++++++++++++++ .../registry_coordinator_manager.ex | 4 +- telemetry_api/lib/telemetry_api/operators.ex | 87 ++++++++++++++----- .../lib/telemetry_api/operators/operator.ex | 7 +- telemetry_api/lib/telemetry_api/utils.ex | 53 +++++++++++ .../controllers/operator_controller.ex | 2 +- .../controllers/operator_json.ex | 3 + telemetry_api/mix.exs | 2 +- telemetry_api/mix.lock | 7 ++ telemetry_api/priv/abi/DelegationManager.json | 1 + .../priv/abi/OperatorStateRetriever.json | 1 + .../20240917212329_create_operators.exs | 3 + telemetry_api/start.sh | 14 ++- 22 files changed, 310 insertions(+), 34 deletions(-) create mode 100644 telemetry_api/lib/telemetry_api/contract_managers/delegation_manager.ex create mode 100644 telemetry_api/lib/telemetry_api/contract_managers/operator_state_retriever.ex rename telemetry_api/lib/telemetry_api/{ => contract_managers}/registry_coordinator_manager.ex (89%) create mode 100644 telemetry_api/lib/telemetry_api/utils.ex create mode 100644 telemetry_api/priv/abi/DelegationManager.json create mode 100644 telemetry_api/priv/abi/OperatorStateRetriever.json diff --git a/Makefile b/Makefile index a2413ad6d..0a1d2fb4d 100644 --- a/Makefile +++ b/Makefile @@ -757,3 +757,6 @@ telemetry_dump_db: docker exec -t telemetry-postgres-container pg_dumpall -c -U tracker_user > dump.$$(date +\%Y\%m\%d_\%H\%M\%S).sql @echo "Dumped database successfully to /telemetry_api" +telemetry_create_env: + @cd telemetry_api && \ + cp .env.dev .env diff --git a/config-files/config-operator-2.yaml b/config-files/config-operator-2.yaml index a02304ee0..544130412 100644 --- a/config-files/config-operator-2.yaml +++ b/config-files/config-operator-2.yaml @@ -22,7 +22,7 @@ bls: ## Operator Configurations operator: aggregator_rpc_server_ip_port_address: localhost:8090 - operator_tracker_ip_port_address: http://localhost:3030 + operator_tracker_ip_port_address: http://localhost:4000 address: 0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC earnings_receiver_address: 0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC delegation_approver_address: "0x0000000000000000000000000000000000000000" diff --git a/config-files/config-operator-3.yaml b/config-files/config-operator-3.yaml index b8ed7fe87..314290aa5 100644 --- a/config-files/config-operator-3.yaml +++ b/config-files/config-operator-3.yaml @@ -22,7 +22,7 @@ bls: ## Operator Configurations operator: aggregator_rpc_server_ip_port_address: localhost:8090 - operator_tracker_ip_port_address: http://localhost:3030 + operator_tracker_ip_port_address: http://localhost:4000 address: 0x90F79bf6EB2c4f870365E785982E1f101E93b906 earnings_receiver_address: 0x90F79bf6EB2c4f870365E785982E1f101E93b906 delegation_approver_address: "0x0000000000000000000000000000000000000000" diff --git a/telemetry_api/.env.dev b/telemetry_api/.env.dev index e98ce001e..b2a7e87be 100644 --- a/telemetry_api/.env.dev +++ b/telemetry_api/.env.dev @@ -1 +1,2 @@ -export ALIGNED_CONFIG_FILE="../contracts/script/output/devnet/alignedlayer_deployment_output.json" +ALIGNED_CONFIG_FILE="../contracts/script/output/devnet/alignedlayer_deployment_output.json" +ENVIRONMENT=devnet diff --git a/telemetry_api/.gitignore b/telemetry_api/.gitignore index 697102350..930813079 100644 --- a/telemetry_api/.gitignore +++ b/telemetry_api/.gitignore @@ -25,3 +25,5 @@ erl_crash.dump # Ignore package tarball (built via "mix hex.build"). telemetry_api-*.tar +# Elixir lsp server +.elixir_ls diff --git a/telemetry_api/config/runtime.exs b/telemetry_api/config/runtime.exs index d34f8f7c9..040a056d2 100644 --- a/telemetry_api/config/runtime.exs +++ b/telemetry_api/config/runtime.exs @@ -76,7 +76,7 @@ if config_env() == :prod do # Configure ethereumex url config :ethereumex, url: rpc_url - # Contract RegistryCoordinatorManager address + # Aligned configuration file path System.get_env("ALIGNED_CONFIG_FILE") || raise """ environment variable ALIGNED_CONFIG_FILE is missing. diff --git a/telemetry_api/ecto_setup_db.sh b/telemetry_api/ecto_setup_db.sh index b41326827..4a225ed24 100755 --- a/telemetry_api/ecto_setup_db.sh +++ b/telemetry_api/ecto_setup_db.sh @@ -1,6 +1,16 @@ #!/bin/bash -source .env.dev +source .env + +# Add new environment variables here +env_vars=( + "ENVIRONMENT" + "ALIGNED_CONFIG_FILE" +) + +for var in "${env_vars[@]}"; do + export "$var=${!var}" +done mix deps.get diff --git a/telemetry_api/lib/telemetry_api/application.ex b/telemetry_api/lib/telemetry_api/application.ex index d1a065189..ebf12b5cf 100644 --- a/telemetry_api/lib/telemetry_api/application.ex +++ b/telemetry_api/lib/telemetry_api/application.ex @@ -21,7 +21,12 @@ defmodule TelemetryApi.Application do # See https://hexdocs.pm/elixir/Supervisor.html # for other strategies and supported options opts = [strategy: :one_for_one, name: TelemetryApi.Supervisor] - Supervisor.start_link(children, opts) + + # Now we fetch operators data from smart contract to fill db + with {:ok, pid} <- Supervisor.start_link(children, opts), + {:ok, _} <- TelemetryApi.Operators.fetch_all_operators() do + {:ok, pid} + end end # Tell Phoenix to update the endpoint configuration diff --git a/telemetry_api/lib/telemetry_api/contract_managers/delegation_manager.ex b/telemetry_api/lib/telemetry_api/contract_managers/delegation_manager.ex new file mode 100644 index 000000000..9318f6832 --- /dev/null +++ b/telemetry_api/lib/telemetry_api/contract_managers/delegation_manager.ex @@ -0,0 +1,53 @@ +defmodule TelemetryApi.ContractManagers.DelegationManager do + alias TelemetryApi.ContractManagers.DelegationManager + require Logger + + @environment System.get_env("ENVIRONMENT") + + @first_block (case @environment do + "devnet" -> 0 + "holesky" -> 1_210_000 + "mainnet" -> 20_020_000 + _ -> raise("Invalid environment") + end) + + eigenlayer_output_file_path = + "../contracts/script/output/#{@environment}/eigenlayer_deployment_output.json" + + + {status, config_json_string} = File.read(eigenlayer_output_file_path) + + case status do + :ok -> + Logger.debug("Eigenlayer deployment file read successfully") + + :error -> + raise("Config file not read successfully") + end + + @contract_address Jason.decode!(config_json_string) + |> Map.get("addresses") + |> Map.get("delegationManager") + + use Ethers.Contract, + abi_file: "priv/abi/DelegationManager.json", + default_address: @contract_address + + def get_contract_address() do + @contract_address + end + + def get_operator_url(operator_address) do + DelegationManager.EventFilters.operator_metadata_uri_updated(operator_address) + |> Ethers.get_logs(fromBlock: @first_block) + |> case do + {:ok, data} -> + url = List.last(data).data |> hd() # The head (hd) is the most recent entry + {:ok, url} + {:error, reason} -> + {:error, reason} + other -> + {:error, "Unexpected response getting operator url: #{inspect(other)}"} + end + end +end diff --git a/telemetry_api/lib/telemetry_api/contract_managers/operator_state_retriever.ex b/telemetry_api/lib/telemetry_api/contract_managers/operator_state_retriever.ex new file mode 100644 index 000000000..a61bbdf6a --- /dev/null +++ b/telemetry_api/lib/telemetry_api/contract_managers/operator_state_retriever.ex @@ -0,0 +1,74 @@ +defmodule TelemetryApi.ContractManagers.OperatorStateRetriever do + require Logger + + @aligned_config_file System.get_env("ALIGNED_CONFIG_FILE") + + config_file_path = + case @aligned_config_file do + nil -> raise("ALIGNED_CONFIG_FILE not set in .env") + file -> file + end + + {status, config_json_string} = File.read(config_file_path) + + case status do + :ok -> + Logger.debug("Aligned deployment file read successfully") + + :error -> + raise("Config file not read successfully") + end + + @contract_address Jason.decode!(config_json_string) + |> Map.get("addresses") + |> Map.get("operatorStateRetriever") + + @registry_coordinator_address Jason.decode!(config_json_string) + |> Map.get("addresses") + |> Map.get("registryCoordinator") + |> String.trim_leading("0x") + |> Base.decode16!(case: :mixed) + + use Ethers.Contract, + abi_file: "priv/abi/OperatorStateRetriever.json", + default_address: @contract_address + + # -------- PUBLIC FUNCTIONS -------- + + def get_contract_address() do + @contract_address + end + + def get_operators() do + with {:ok, block_number} = Ethers.current_block_number(), + {:ok, operators_state} = fetch_operators_state(block_number) do + parse_operators(operators_state) + end + end + + # -------- PRIVATE FUNCTIONS -------- + + defp parse_operators(operators_state) do + operators = + operators_state |> Enum.map(fn {address, id, stake} -> + id = id |> String.trim_leading("0x") |> String.upcase() + address = address |> String.trim_leading("0x") |> String.upcase() + %{ + id: "0x" <> Base.encode16(id, case: :lower), + address: "0x" <> address, + stake: Integer.to_string(stake) + } + end) + {:ok, operators} + end + + defp fetch_operators_state(block_number) do + quorum_numbers = <<0>> + response = __MODULE__.get_operator_state(@registry_coordinator_address, quorum_numbers, block_number) |> Ethers.call() + case response do + {:ok, [operators | _]} -> {:ok, operators} + {:error, message} -> {:error, message} + _ -> {:error, "Bad formated data received from OperatorStateRetriever::getOperatorState"} + end + end +end diff --git a/telemetry_api/lib/telemetry_api/registry_coordinator_manager.ex b/telemetry_api/lib/telemetry_api/contract_managers/registry_coordinator_manager.ex similarity index 89% rename from telemetry_api/lib/telemetry_api/registry_coordinator_manager.ex rename to telemetry_api/lib/telemetry_api/contract_managers/registry_coordinator_manager.ex index 9e3bae63d..b67b3c14c 100644 --- a/telemetry_api/lib/telemetry_api/registry_coordinator_manager.ex +++ b/telemetry_api/lib/telemetry_api/contract_managers/registry_coordinator_manager.ex @@ -1,5 +1,5 @@ -defmodule TelemetryApi.RegistryCoordinatorManager do - alias TelemetryApi.RegistryCoordinatorManager +defmodule TelemetryApi.ContractManagers.RegistryCoordinatorManager do + alias TelemetryApi.ContractManagers.RegistryCoordinatorManager require Logger diff --git a/telemetry_api/lib/telemetry_api/operators.ex b/telemetry_api/lib/telemetry_api/operators.ex index 7528cf37e..aafc69ed7 100644 --- a/telemetry_api/lib/telemetry_api/operators.ex +++ b/telemetry_api/lib/telemetry_api/operators.ex @@ -7,7 +7,8 @@ defmodule TelemetryApi.Operators do alias TelemetryApi.Repo alias TelemetryApi.Operators.Operator - alias TelemetryApi.RegistryCoordinatorManager + alias TelemetryApi.ContractManagers.OperatorStateRetriever + alias TelemetryApi.ContractManagers.DelegationManager @doc """ Returns the list of operators. @@ -39,36 +40,82 @@ defmodule TelemetryApi.Operators do end @doc """ - Creates a operator. + Fetches all operators. ## Examples - iex> create_operator(%{field: value}) - {:ok, %Operator{}} + iex> fetch_all_operators() + {:ok, %Ecto.Changeset{}} - iex> create_operator(%{field: bad_value}) - {:error, %Ecto.Changeset{}} + iex> fetch_all_operators() + {:error, string} """ - def create_operator(attrs \\ %{}) do - # Get address from the signature - with {:ok, address} <- SignatureVerifier.get_address(attrs["version"], attrs["signature"]), - {:ok, is_registered?} <- RegistryCoordinatorManager.is_operator_registered?(address) do - # Verify operator is registered - if is_registered? do - address = "0x" <> address - attrs = Map.put(attrs, "address", address) - - # We handle updates here as there is no patch method available at the moment. - case Repo.get(Operator, address) do + def fetch_all_operators() do + with {:ok, operators} <- OperatorStateRetriever.get_operators() do + Enum.map(operators, fn op_data -> + with {:ok, full_operator_data} <- add_operator_metadata(op_data) do + case Repo.get(Operator, op_data.address) do nil -> %Operator{} operator -> operator end - |> Operator.changeset(attrs) + |> Operator.changeset(full_operator_data) |> Repo.insert_or_update() - else - {:error, "Provided address does not correspond to any registered operator"} end + end) + |> TelemetryApi.Utils.clean_list_errors("Error fetching operators metadata") + end + end + + + #Adds operator metadata to received operator. + + ### Examples + + # iex> add_operator_metadata(operator) + # {:ok, operator_with_metadata} + # + # iex> add_operator_metadata(operator) + # {:error, string} + # + defp add_operator_metadata(op_data) do + with {:ok, url} <- DelegationManager.get_operator_url(op_data.address), + {:ok, metadata} <- TelemetryApi.Utils.fetch_json_data(url) do + operator = %{ + id: op_data.id, + address: op_data.address, + stake: op_data.stake, + name: Map.get(metadata, "name") + } + + {:ok, operator} + end + end + + @doc """ + Updates an operator's version. + + ## Examples + + iex> update_operator_version(%{field: value}) + {:ok, %Ecto.Changeset{}} + + iex> update_operator_version(%{field: bad_value}) + {:error, string} + + """ + def update_operator_version(attrs \\ %{}) do + with {:ok, address} <- SignatureVerifier.get_address(attrs["version"], attrs["signature"]) do + address = "0x" <> address + # We only want to allow changes on version + changes = %{ + version: attrs["version"] + } + + case Repo.get(Operator, address) do + nil -> {:error, "Provided address does not correspond to any registered operator"} + operator -> operator |> Operator.changeset(changes) |> Repo.insert_or_update() + end end end diff --git a/telemetry_api/lib/telemetry_api/operators/operator.ex b/telemetry_api/lib/telemetry_api/operators/operator.ex index 0392e8526..6c2892d74 100644 --- a/telemetry_api/lib/telemetry_api/operators/operator.ex +++ b/telemetry_api/lib/telemetry_api/operators/operator.ex @@ -4,6 +4,9 @@ defmodule TelemetryApi.Operators.Operator do @primary_key {:address, :string, []} schema "operators" do + field :id, :string + field :stake, :string + field :name, :string field :version, :string timestamps(type: :utc_datetime) @@ -12,8 +15,8 @@ defmodule TelemetryApi.Operators.Operator do @doc false def changeset(operator, attrs) do operator - |> cast(attrs, [:address, :version]) - |> validate_required([:address, :version]) + |> cast(attrs, [:address, :id, :stake, :name, :version]) + |> validate_required([:address, :id, :name, :stake]) end end diff --git a/telemetry_api/lib/telemetry_api/utils.ex b/telemetry_api/lib/telemetry_api/utils.ex new file mode 100644 index 000000000..5ccb9efab --- /dev/null +++ b/telemetry_api/lib/telemetry_api/utils.ex @@ -0,0 +1,53 @@ +defmodule TelemetryApi.Utils do + @moduledoc """ + Some utility functions + """ + + @doc """ + Fetches the provided url and returns a json decoded map + + ## Examples + + iex> fetch_json_data(url) + {:ok, data} + + iex> fetch_json_data(url) + {:error, message} + """ + def fetch_json_data(url) do + case HTTPoison.get(url) do + {:ok, %HTTPoison.Response{status_code: 200, body: body}} -> + {:ok, Jason.decode!(body)} + + {:ok, %HTTPoison.Response{status_code: status_code}} -> + {:error, "Request failed with status #{status_code}"} + + {:error, %HTTPoison.Error{reason: reason}} -> + {:error, "HTTP request failed: #{reason}"} + end + end + + @doc """ + Unwraps inner element status + + ## Examples + + iex> list = [{:ok, 2}, {:ok, 3}] + iex> clean_list_errors(list, error_message) + {:ok, list} + + iex> list = [{:ok, 2}, {:ok, 3}, {:error, "this is an error"}] + iex> message = "Error found on list" + iex> clean_list_errors(list, error_message) + {:error, "Error found on list"} + """ + def clean_list_errors(list, error_message) do + case Enum.find(list, fn {status, _} -> status == :error end) do + nil -> + {:ok, Enum.map(list, fn {:ok, value} -> value end)} + + {:error, _} -> + {:error, error_message} + end + end +end diff --git a/telemetry_api/lib/telemetry_api_web/controllers/operator_controller.ex b/telemetry_api/lib/telemetry_api_web/controllers/operator_controller.ex index d8249ac3e..b1b5d4bed 100644 --- a/telemetry_api/lib/telemetry_api_web/controllers/operator_controller.ex +++ b/telemetry_api/lib/telemetry_api_web/controllers/operator_controller.ex @@ -19,7 +19,7 @@ defmodule TelemetryApiWeb.OperatorController do end def create(conn, operator_params) do - case Operators.create_operator(operator_params) do + case Operators.update_operator_version(operator_params) do {:ok, %Operator{} = operator} -> conn |> put_status(:created) diff --git a/telemetry_api/lib/telemetry_api_web/controllers/operator_json.ex b/telemetry_api/lib/telemetry_api_web/controllers/operator_json.ex index 6d0828be3..f267d1788 100644 --- a/telemetry_api/lib/telemetry_api_web/controllers/operator_json.ex +++ b/telemetry_api/lib/telemetry_api_web/controllers/operator_json.ex @@ -18,6 +18,9 @@ defmodule TelemetryApiWeb.OperatorJSON do defp data(%Operator{} = operator) do %{ address: operator.address, + id: operator.id, + stake: operator.stake, + name: operator.name, version: operator.version } end diff --git a/telemetry_api/mix.exs b/telemetry_api/mix.exs index 7a6c0d2dd..313274278 100644 --- a/telemetry_api/mix.exs +++ b/telemetry_api/mix.exs @@ -39,13 +39,13 @@ defmodule TelemetryApi.MixProject do {:phoenix_live_dashboard, "~> 0.8.3"}, {:telemetry_metrics, "~> 1.0"}, {:telemetry_poller, "~> 1.0"}, + {:httpoison, "~> 2.0"}, {:jason, "~> 1.2"}, {:dns_cluster, "~> 0.1.1"}, {:bandit, "~> 1.5"}, {:ex_keccak, "~> 0.7.5"}, {:ex_secp256k1, "~> 0.7"}, {:ethers, "~> 0.4.4"}, - {:ethereumex, "~> 0.10"}, ] end diff --git a/telemetry_api/mix.lock b/telemetry_api/mix.lock index ee34e83f1..3c3f2e69d 100644 --- a/telemetry_api/mix.lock +++ b/telemetry_api/mix.lock @@ -1,6 +1,7 @@ %{ "bandit": {:hex, :bandit, "1.5.7", "6856b1e1df4f2b0cb3df1377eab7891bec2da6a7fd69dc78594ad3e152363a50", [:mix], [{:hpax, "~> 1.0.0", [hex: :hpax, repo: "hexpm", optional: false]}, {:plug, "~> 1.14", [hex: :plug, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}, {:thousand_island, "~> 1.0", [hex: :thousand_island, repo: "hexpm", optional: false]}, {:websock, "~> 0.5", [hex: :websock, repo: "hexpm", optional: false]}], "hexpm", "f2dd92ae87d2cbea2fa9aa1652db157b6cba6c405cb44d4f6dd87abba41371cd"}, "castore": {:hex, :castore, "1.0.8", "dedcf20ea746694647f883590b82d9e96014057aff1d44d03ec90f36a5c0dc6e", [:mix], [], "hexpm", "0b2b66d2ee742cb1d9cb8c8be3b43c3a70ee8651f37b75a8b982e036752983f1"}, + "certifi": {:hex, :certifi, "2.12.0", "2d1cca2ec95f59643862af91f001478c9863c2ac9cb6e2f89780bfd8de987329", [:rebar3], [], "hexpm", "ee68d85df22e554040cdb4be100f33873ac6051387baf6a8f6ce82272340ff1c"}, "db_connection": {:hex, :db_connection, "2.7.0", "b99faa9291bb09892c7da373bb82cba59aefa9b36300f6145c5f201c7adf48ec", [:mix], [{:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "dcf08f31b2701f857dfc787fbad78223d61a32204f217f15e881dd93e4bdd3ff"}, "decimal": {:hex, :decimal, "2.1.1", "5611dca5d4b2c3dd497dec8f68751f1f1a54755e8ed2a966c2633cf885973ad6", [:mix], [], "hexpm", "53cfe5f497ed0e7771ae1a475575603d77425099ba5faef9394932b35020ffcc"}, "dns_cluster": {:hex, :dns_cluster, "0.1.3", "0bc20a2c88ed6cc494f2964075c359f8c2d00e1bf25518a6a6c7fd277c9b0c66", [:mix], [], "hexpm", "46cb7c4a1b3e52c7ad4cbe33ca5079fbde4840dedeafca2baf77996c2da1bc33"}, @@ -13,13 +14,18 @@ "ex_rlp": {:hex, :ex_rlp, "0.6.0", "985391d2356a7cb8712a4a9a2deb93f19f2fbca0323f5c1203fcaf64d077e31e", [:mix], [], "hexpm", "7135db93b861d9e76821039b60b00a6a22d2c4e751bf8c444bffe7a042f1abaf"}, "ex_secp256k1": {:hex, :ex_secp256k1, "0.7.3", "489b6fd57fab5a7259ace927d8cb5171aad835e9c7279c2a859a0483cb069415", [:mix], [{:rustler, ">= 0.0.0", [hex: :rustler, repo: "hexpm", optional: true]}, {:rustler_precompiled, "~> 0.7", [hex: :rustler_precompiled, repo: "hexpm", optional: false]}], "hexpm", "ea63159442f4d8143166cd1507da03edc43216d6e7c6bac4b416bdce04f0daa8"}, "finch": {:hex, :finch, "0.19.0", "c644641491ea854fc5c1bbaef36bfc764e3f08e7185e1f084e35e0672241b76d", [:mix], [{:mime, "~> 1.0 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:mint, "~> 1.6.2 or ~> 1.7", [hex: :mint, repo: "hexpm", optional: false]}, {:nimble_options, "~> 0.4 or ~> 1.0", [hex: :nimble_options, repo: "hexpm", optional: false]}, {:nimble_pool, "~> 1.1", [hex: :nimble_pool, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "fc5324ce209125d1e2fa0fcd2634601c52a787aff1cd33ee833664a5af4ea2b6"}, + "hackney": {:hex, :hackney, "1.20.1", "8d97aec62ddddd757d128bfd1df6c5861093419f8f7a4223823537bad5d064e2", [:rebar3], [{:certifi, "~> 2.12.0", [hex: :certifi, repo: "hexpm", optional: false]}, {:idna, "~> 6.1.0", [hex: :idna, repo: "hexpm", optional: false]}, {:metrics, "~> 1.0.0", [hex: :metrics, repo: "hexpm", optional: false]}, {:mimerl, "~> 1.1", [hex: :mimerl, repo: "hexpm", optional: false]}, {:parse_trans, "3.4.1", [hex: :parse_trans, repo: "hexpm", optional: false]}, {:ssl_verify_fun, "~> 1.1.0", [hex: :ssl_verify_fun, repo: "hexpm", optional: false]}, {:unicode_util_compat, "~> 0.7.0", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm", "fe9094e5f1a2a2c0a7d10918fee36bfec0ec2a979994cff8cfe8058cd9af38e3"}, "hpax": {:hex, :hpax, "1.0.0", "28dcf54509fe2152a3d040e4e3df5b265dcb6cb532029ecbacf4ce52caea3fd2", [:mix], [], "hexpm", "7f1314731d711e2ca5fdc7fd361296593fc2542570b3105595bb0bc6d0fad601"}, + "httpoison": {:hex, :httpoison, "2.2.1", "87b7ed6d95db0389f7df02779644171d7319d319178f6680438167d7b69b1f3d", [:mix], [{:hackney, "~> 1.17", [hex: :hackney, repo: "hexpm", optional: false]}], "hexpm", "51364e6d2f429d80e14fe4b5f8e39719cacd03eb3f9a9286e61e216feac2d2df"}, "idna": {:hex, :idna, "6.1.1", "8a63070e9f7d0c62eb9d9fcb360a7de382448200fbbd1b106cc96d3d8099df8d", [:rebar3], [{:unicode_util_compat, "~> 0.7.0", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm", "92376eb7894412ed19ac475e4a86f7b413c1b9fbb5bd16dccd57934157944cea"}, "jason": {:hex, :jason, "1.4.4", "b9226785a9aa77b6857ca22832cffa5d5011a667207eb2a0ad56adb5db443b8a", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "c5eb0cab91f094599f94d55bc63409236a8ec69a21a67814529e8d5f6cc90b3b"}, + "metrics": {:hex, :metrics, "1.0.1", "25f094dea2cda98213cecc3aeff09e940299d950904393b2a29d191c346a8486", [:rebar3], [], "hexpm", "69b09adddc4f74a40716ae54d140f93beb0fb8978d8636eaded0c31b6f099f16"}, "mime": {:hex, :mime, "2.0.6", "8f18486773d9b15f95f4f4f1e39b710045fa1de891fada4516559967276e4dc2", [:mix], [], "hexpm", "c9945363a6b26d747389aac3643f8e0e09d30499a138ad64fe8fd1d13d9b153e"}, + "mimerl": {:hex, :mimerl, "1.3.0", "d0cd9fc04b9061f82490f6581e0128379830e78535e017f7780f37fea7545726", [:rebar3], [], "hexpm", "a1e15a50d1887217de95f0b9b0793e32853f7c258a5cd227650889b38839fe9d"}, "mint": {:hex, :mint, "1.6.2", "af6d97a4051eee4f05b5500671d47c3a67dac7386045d87a904126fd4bbcea2e", [:mix], [{:castore, "~> 0.1.0 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: true]}, {:hpax, "~> 0.1.1 or ~> 0.2.0 or ~> 1.0", [hex: :hpax, repo: "hexpm", optional: false]}], "hexpm", "5ee441dffc1892f1ae59127f74afe8fd82fda6587794278d924e4d90ea3d63f9"}, "nimble_options": {:hex, :nimble_options, "1.1.1", "e3a492d54d85fc3fd7c5baf411d9d2852922f66e69476317787a7b2bb000a61b", [:mix], [], "hexpm", "821b2470ca9442c4b6984882fe9bb0389371b8ddec4d45a9504f00a66f650b44"}, "nimble_pool": {:hex, :nimble_pool, "1.1.0", "bf9c29fbdcba3564a8b800d1eeb5a3c58f36e1e11d7b7fb2e084a643f645f06b", [:mix], [], "hexpm", "af2e4e6b34197db81f7aad230c1118eac993acc0dae6bc83bac0126d4ae0813a"}, + "parse_trans": {:hex, :parse_trans, "3.4.1", "6e6aa8167cb44cc8f39441d05193be6e6f4e7c2946cb2759f015f8c56b76e5ff", [:rebar3], [], "hexpm", "620a406ce75dada827b82e453c19cf06776be266f5a67cff34e1ef2cbb60e49a"}, "phoenix": {:hex, :phoenix, "1.7.14", "a7d0b3f1bc95987044ddada111e77bd7f75646a08518942c72a8440278ae7825", [:mix], [{:castore, ">= 0.0.0", [hex: :castore, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:phoenix_pubsub, "~> 2.1", [hex: :phoenix_pubsub, repo: "hexpm", optional: false]}, {:phoenix_template, "~> 1.0", [hex: :phoenix_template, repo: "hexpm", optional: false]}, {:phoenix_view, "~> 2.0", [hex: :phoenix_view, repo: "hexpm", optional: true]}, {:plug, "~> 1.14", [hex: :plug, repo: "hexpm", optional: false]}, {:plug_cowboy, "~> 2.7", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:plug_crypto, "~> 1.2 or ~> 2.0", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}, {:websock_adapter, "~> 0.5.3", [hex: :websock_adapter, repo: "hexpm", optional: false]}], "hexpm", "c7859bc56cc5dfef19ecfc240775dae358cbaa530231118a9e014df392ace61a"}, "phoenix_ecto": {:hex, :phoenix_ecto, "4.6.2", "3b83b24ab5a2eb071a20372f740d7118767c272db386831b2e77638c4dcc606d", [:mix], [{:ecto, "~> 3.5", [hex: :ecto, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 2.14.2 or ~> 3.0 or ~> 4.1", [hex: :phoenix_html, repo: "hexpm", optional: true]}, {:plug, "~> 1.9", [hex: :plug, repo: "hexpm", optional: false]}, {:postgrex, "~> 0.16 or ~> 1.0", [hex: :postgrex, repo: "hexpm", optional: true]}], "hexpm", "3f94d025f59de86be00f5f8c5dd7b5965a3298458d21ab1c328488be3b5fcd59"}, "phoenix_html": {:hex, :phoenix_html, "4.1.1", "4c064fd3873d12ebb1388425a8f2a19348cef56e7289e1998e2d2fa758aa982e", [:mix], [], "hexpm", "f2f2df5a72bc9a2f510b21497fd7d2b86d932ec0598f0210fed4114adc546c6f"}, @@ -32,6 +38,7 @@ "poolboy": {:hex, :poolboy, "1.5.2", "392b007a1693a64540cead79830443abf5762f5d30cf50bc95cb2c1aaafa006b", [:rebar3], [], "hexpm", "dad79704ce5440f3d5a3681c8590b9dc25d1a561e8f5a9c995281012860901e3"}, "postgrex": {:hex, :postgrex, "0.19.1", "73b498508b69aded53907fe48a1fee811be34cc720e69ef4ccd568c8715495ea", [:mix], [{:db_connection, "~> 2.1", [hex: :db_connection, repo: "hexpm", optional: false]}, {:decimal, "~> 1.5 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:table, "~> 0.1.0", [hex: :table, repo: "hexpm", optional: true]}], "hexpm", "8bac7885a18f381e091ec6caf41bda7bb8c77912bb0e9285212829afe5d8a8f8"}, "rustler_precompiled": {:hex, :rustler_precompiled, "0.8.1", "8afe0b6f3a9a677ada046cdd23e3f4c6399618b91a6122289324774961281e1e", [:mix], [{:castore, "~> 0.1 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: false]}, {:rustler, "~> 0.23", [hex: :rustler, repo: "hexpm", optional: true]}], "hexpm", "90b8c2297bf7959cfa1c927b2881faad7bb0707183124955369991b76177a166"}, + "ssl_verify_fun": {:hex, :ssl_verify_fun, "1.1.7", "354c321cf377240c7b8716899e182ce4890c5938111a1296add3ec74cf1715df", [:make, :mix, :rebar3], [], "hexpm", "fe4c190e8f37401d30167c8c405eda19469f34577987c76dde613e838bbc67f8"}, "telemetry": {:hex, :telemetry, "1.3.0", "fedebbae410d715cf8e7062c96a1ef32ec22e764197f70cda73d82778d61e7a2", [:rebar3], [], "hexpm", "7015fc8919dbe63764f4b4b87a95b7c0996bd539e0d499be6ec9d7f3875b79e6"}, "telemetry_metrics": {:hex, :telemetry_metrics, "1.0.0", "29f5f84991ca98b8eb02fc208b2e6de7c95f8bb2294ef244a176675adc7775df", [:mix], [{:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "f23713b3847286a534e005126d4c959ebcca68ae9582118ce436b521d1d47d5d"}, "telemetry_poller": {:hex, :telemetry_poller, "1.1.0", "58fa7c216257291caaf8d05678c8d01bd45f4bdbc1286838a28c4bb62ef32999", [:rebar3], [{:telemetry, "~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "9eb9d9cbfd81cbd7cdd24682f8711b6e2b691289a0de6826e58452f28c103c8f"}, diff --git a/telemetry_api/priv/abi/DelegationManager.json b/telemetry_api/priv/abi/DelegationManager.json new file mode 100644 index 000000000..8bbe761be --- /dev/null +++ b/telemetry_api/priv/abi/DelegationManager.json @@ -0,0 +1 @@ +{"abi":[{"type":"constructor","inputs":[{"name":"_strategyManager","type":"address","internalType":"contract IStrategyManager"},{"name":"_slasher","type":"address","internalType":"contract ISlasher"},{"name":"_eigenPodManager","type":"address","internalType":"contract IEigenPodManager"}],"stateMutability":"nonpayable"},{"type":"function","name":"DELEGATION_APPROVAL_TYPEHASH","inputs":[],"outputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"stateMutability":"view"},{"type":"function","name":"DOMAIN_TYPEHASH","inputs":[],"outputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"stateMutability":"view"},{"type":"function","name":"MAX_STAKER_OPT_OUT_WINDOW_BLOCKS","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"MAX_WITHDRAWAL_DELAY_BLOCKS","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"STAKER_DELEGATION_TYPEHASH","inputs":[],"outputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"stateMutability":"view"},{"type":"function","name":"beaconChainETHStrategy","inputs":[],"outputs":[{"name":"","type":"address","internalType":"contract IStrategy"}],"stateMutability":"view"},{"type":"function","name":"calculateCurrentStakerDelegationDigestHash","inputs":[{"name":"staker","type":"address","internalType":"address"},{"name":"operator","type":"address","internalType":"address"},{"name":"expiry","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"stateMutability":"view"},{"type":"function","name":"calculateDelegationApprovalDigestHash","inputs":[{"name":"staker","type":"address","internalType":"address"},{"name":"operator","type":"address","internalType":"address"},{"name":"_delegationApprover","type":"address","internalType":"address"},{"name":"approverSalt","type":"bytes32","internalType":"bytes32"},{"name":"expiry","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"stateMutability":"view"},{"type":"function","name":"calculateStakerDelegationDigestHash","inputs":[{"name":"staker","type":"address","internalType":"address"},{"name":"_stakerNonce","type":"uint256","internalType":"uint256"},{"name":"operator","type":"address","internalType":"address"},{"name":"expiry","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"stateMutability":"view"},{"type":"function","name":"calculateWithdrawalRoot","inputs":[{"name":"withdrawal","type":"tuple","internalType":"struct IDelegationManager.Withdrawal","components":[{"name":"staker","type":"address","internalType":"address"},{"name":"delegatedTo","type":"address","internalType":"address"},{"name":"withdrawer","type":"address","internalType":"address"},{"name":"nonce","type":"uint256","internalType":"uint256"},{"name":"startBlock","type":"uint32","internalType":"uint32"},{"name":"strategies","type":"address[]","internalType":"contract IStrategy[]"},{"name":"shares","type":"uint256[]","internalType":"uint256[]"}]}],"outputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"stateMutability":"pure"},{"type":"function","name":"completeQueuedWithdrawal","inputs":[{"name":"withdrawal","type":"tuple","internalType":"struct IDelegationManager.Withdrawal","components":[{"name":"staker","type":"address","internalType":"address"},{"name":"delegatedTo","type":"address","internalType":"address"},{"name":"withdrawer","type":"address","internalType":"address"},{"name":"nonce","type":"uint256","internalType":"uint256"},{"name":"startBlock","type":"uint32","internalType":"uint32"},{"name":"strategies","type":"address[]","internalType":"contract IStrategy[]"},{"name":"shares","type":"uint256[]","internalType":"uint256[]"}]},{"name":"tokens","type":"address[]","internalType":"contract IERC20[]"},{"name":"middlewareTimesIndex","type":"uint256","internalType":"uint256"},{"name":"receiveAsTokens","type":"bool","internalType":"bool"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"completeQueuedWithdrawals","inputs":[{"name":"withdrawals","type":"tuple[]","internalType":"struct IDelegationManager.Withdrawal[]","components":[{"name":"staker","type":"address","internalType":"address"},{"name":"delegatedTo","type":"address","internalType":"address"},{"name":"withdrawer","type":"address","internalType":"address"},{"name":"nonce","type":"uint256","internalType":"uint256"},{"name":"startBlock","type":"uint32","internalType":"uint32"},{"name":"strategies","type":"address[]","internalType":"contract IStrategy[]"},{"name":"shares","type":"uint256[]","internalType":"uint256[]"}]},{"name":"tokens","type":"address[][]","internalType":"contract IERC20[][]"},{"name":"middlewareTimesIndexes","type":"uint256[]","internalType":"uint256[]"},{"name":"receiveAsTokens","type":"bool[]","internalType":"bool[]"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"cumulativeWithdrawalsQueued","inputs":[{"name":"","type":"address","internalType":"address"}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"decreaseDelegatedShares","inputs":[{"name":"staker","type":"address","internalType":"address"},{"name":"strategy","type":"address","internalType":"contract IStrategy"},{"name":"shares","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"delegateTo","inputs":[{"name":"operator","type":"address","internalType":"address"},{"name":"approverSignatureAndExpiry","type":"tuple","internalType":"struct ISignatureUtils.SignatureWithExpiry","components":[{"name":"signature","type":"bytes","internalType":"bytes"},{"name":"expiry","type":"uint256","internalType":"uint256"}]},{"name":"approverSalt","type":"bytes32","internalType":"bytes32"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"delegateToBySignature","inputs":[{"name":"staker","type":"address","internalType":"address"},{"name":"operator","type":"address","internalType":"address"},{"name":"stakerSignatureAndExpiry","type":"tuple","internalType":"struct ISignatureUtils.SignatureWithExpiry","components":[{"name":"signature","type":"bytes","internalType":"bytes"},{"name":"expiry","type":"uint256","internalType":"uint256"}]},{"name":"approverSignatureAndExpiry","type":"tuple","internalType":"struct ISignatureUtils.SignatureWithExpiry","components":[{"name":"signature","type":"bytes","internalType":"bytes"},{"name":"expiry","type":"uint256","internalType":"uint256"}]},{"name":"approverSalt","type":"bytes32","internalType":"bytes32"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"delegatedTo","inputs":[{"name":"","type":"address","internalType":"address"}],"outputs":[{"name":"","type":"address","internalType":"address"}],"stateMutability":"view"},{"type":"function","name":"delegationApprover","inputs":[{"name":"operator","type":"address","internalType":"address"}],"outputs":[{"name":"","type":"address","internalType":"address"}],"stateMutability":"view"},{"type":"function","name":"delegationApproverSaltIsSpent","inputs":[{"name":"","type":"address","internalType":"address"},{"name":"","type":"bytes32","internalType":"bytes32"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"type":"function","name":"domainSeparator","inputs":[],"outputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"stateMutability":"view"},{"type":"function","name":"eigenPodManager","inputs":[],"outputs":[{"name":"","type":"address","internalType":"contract IEigenPodManager"}],"stateMutability":"view"},{"type":"function","name":"getDelegatableShares","inputs":[{"name":"staker","type":"address","internalType":"address"}],"outputs":[{"name":"","type":"address[]","internalType":"contract IStrategy[]"},{"name":"","type":"uint256[]","internalType":"uint256[]"}],"stateMutability":"view"},{"type":"function","name":"getOperatorShares","inputs":[{"name":"operator","type":"address","internalType":"address"},{"name":"strategies","type":"address[]","internalType":"contract IStrategy[]"}],"outputs":[{"name":"","type":"uint256[]","internalType":"uint256[]"}],"stateMutability":"view"},{"type":"function","name":"getWithdrawalDelay","inputs":[{"name":"strategies","type":"address[]","internalType":"contract IStrategy[]"}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"increaseDelegatedShares","inputs":[{"name":"staker","type":"address","internalType":"address"},{"name":"strategy","type":"address","internalType":"contract IStrategy"},{"name":"shares","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"initialize","inputs":[{"name":"initialOwner","type":"address","internalType":"address"},{"name":"_pauserRegistry","type":"address","internalType":"contract IPauserRegistry"},{"name":"initialPausedStatus","type":"uint256","internalType":"uint256"},{"name":"_minWithdrawalDelayBlocks","type":"uint256","internalType":"uint256"},{"name":"_strategies","type":"address[]","internalType":"contract IStrategy[]"},{"name":"_withdrawalDelayBlocks","type":"uint256[]","internalType":"uint256[]"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"isDelegated","inputs":[{"name":"staker","type":"address","internalType":"address"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"type":"function","name":"isOperator","inputs":[{"name":"operator","type":"address","internalType":"address"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"type":"function","name":"minWithdrawalDelayBlocks","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"modifyOperatorDetails","inputs":[{"name":"newOperatorDetails","type":"tuple","internalType":"struct IDelegationManager.OperatorDetails","components":[{"name":"__deprecated_earningsReceiver","type":"address","internalType":"address"},{"name":"delegationApprover","type":"address","internalType":"address"},{"name":"stakerOptOutWindowBlocks","type":"uint32","internalType":"uint32"}]}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"operatorDetails","inputs":[{"name":"operator","type":"address","internalType":"address"}],"outputs":[{"name":"","type":"tuple","internalType":"struct IDelegationManager.OperatorDetails","components":[{"name":"__deprecated_earningsReceiver","type":"address","internalType":"address"},{"name":"delegationApprover","type":"address","internalType":"address"},{"name":"stakerOptOutWindowBlocks","type":"uint32","internalType":"uint32"}]}],"stateMutability":"view"},{"type":"function","name":"operatorShares","inputs":[{"name":"","type":"address","internalType":"address"},{"name":"","type":"address","internalType":"contract IStrategy"}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"owner","inputs":[],"outputs":[{"name":"","type":"address","internalType":"address"}],"stateMutability":"view"},{"type":"function","name":"pause","inputs":[{"name":"newPausedStatus","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"pauseAll","inputs":[],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"paused","inputs":[{"name":"index","type":"uint8","internalType":"uint8"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"type":"function","name":"paused","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"pauserRegistry","inputs":[],"outputs":[{"name":"","type":"address","internalType":"contract IPauserRegistry"}],"stateMutability":"view"},{"type":"function","name":"pendingWithdrawals","inputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"type":"function","name":"queueWithdrawals","inputs":[{"name":"queuedWithdrawalParams","type":"tuple[]","internalType":"struct IDelegationManager.QueuedWithdrawalParams[]","components":[{"name":"strategies","type":"address[]","internalType":"contract IStrategy[]"},{"name":"shares","type":"uint256[]","internalType":"uint256[]"},{"name":"withdrawer","type":"address","internalType":"address"}]}],"outputs":[{"name":"","type":"bytes32[]","internalType":"bytes32[]"}],"stateMutability":"nonpayable"},{"type":"function","name":"registerAsOperator","inputs":[{"name":"registeringOperatorDetails","type":"tuple","internalType":"struct IDelegationManager.OperatorDetails","components":[{"name":"__deprecated_earningsReceiver","type":"address","internalType":"address"},{"name":"delegationApprover","type":"address","internalType":"address"},{"name":"stakerOptOutWindowBlocks","type":"uint32","internalType":"uint32"}]},{"name":"metadataURI","type":"string","internalType":"string"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"renounceOwnership","inputs":[],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"setMinWithdrawalDelayBlocks","inputs":[{"name":"newMinWithdrawalDelayBlocks","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"setPauserRegistry","inputs":[{"name":"newPauserRegistry","type":"address","internalType":"contract IPauserRegistry"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"setStrategyWithdrawalDelayBlocks","inputs":[{"name":"strategies","type":"address[]","internalType":"contract IStrategy[]"},{"name":"withdrawalDelayBlocks","type":"uint256[]","internalType":"uint256[]"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"slasher","inputs":[],"outputs":[{"name":"","type":"address","internalType":"contract ISlasher"}],"stateMutability":"view"},{"type":"function","name":"stakerNonce","inputs":[{"name":"","type":"address","internalType":"address"}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"stakerOptOutWindowBlocks","inputs":[{"name":"operator","type":"address","internalType":"address"}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"strategyManager","inputs":[],"outputs":[{"name":"","type":"address","internalType":"contract IStrategyManager"}],"stateMutability":"view"},{"type":"function","name":"strategyWithdrawalDelayBlocks","inputs":[{"name":"","type":"address","internalType":"contract IStrategy"}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"transferOwnership","inputs":[{"name":"newOwner","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"undelegate","inputs":[{"name":"staker","type":"address","internalType":"address"}],"outputs":[{"name":"withdrawalRoots","type":"bytes32[]","internalType":"bytes32[]"}],"stateMutability":"nonpayable"},{"type":"function","name":"unpause","inputs":[{"name":"newPausedStatus","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"updateOperatorMetadataURI","inputs":[{"name":"metadataURI","type":"string","internalType":"string"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"event","name":"Initialized","inputs":[{"name":"version","type":"uint8","indexed":false,"internalType":"uint8"}],"anonymous":false},{"type":"event","name":"MinWithdrawalDelayBlocksSet","inputs":[{"name":"previousValue","type":"uint256","indexed":false,"internalType":"uint256"},{"name":"newValue","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"OperatorDetailsModified","inputs":[{"name":"operator","type":"address","indexed":true,"internalType":"address"},{"name":"newOperatorDetails","type":"tuple","indexed":false,"internalType":"struct IDelegationManager.OperatorDetails","components":[{"name":"__deprecated_earningsReceiver","type":"address","internalType":"address"},{"name":"delegationApprover","type":"address","internalType":"address"},{"name":"stakerOptOutWindowBlocks","type":"uint32","internalType":"uint32"}]}],"anonymous":false},{"type":"event","name":"OperatorMetadataURIUpdated","inputs":[{"name":"operator","type":"address","indexed":true,"internalType":"address"},{"name":"metadataURI","type":"string","indexed":false,"internalType":"string"}],"anonymous":false},{"type":"event","name":"OperatorRegistered","inputs":[{"name":"operator","type":"address","indexed":true,"internalType":"address"},{"name":"operatorDetails","type":"tuple","indexed":false,"internalType":"struct IDelegationManager.OperatorDetails","components":[{"name":"__deprecated_earningsReceiver","type":"address","internalType":"address"},{"name":"delegationApprover","type":"address","internalType":"address"},{"name":"stakerOptOutWindowBlocks","type":"uint32","internalType":"uint32"}]}],"anonymous":false},{"type":"event","name":"OperatorSharesDecreased","inputs":[{"name":"operator","type":"address","indexed":true,"internalType":"address"},{"name":"staker","type":"address","indexed":false,"internalType":"address"},{"name":"strategy","type":"address","indexed":false,"internalType":"contract IStrategy"},{"name":"shares","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"OperatorSharesIncreased","inputs":[{"name":"operator","type":"address","indexed":true,"internalType":"address"},{"name":"staker","type":"address","indexed":false,"internalType":"address"},{"name":"strategy","type":"address","indexed":false,"internalType":"contract IStrategy"},{"name":"shares","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"OwnershipTransferred","inputs":[{"name":"previousOwner","type":"address","indexed":true,"internalType":"address"},{"name":"newOwner","type":"address","indexed":true,"internalType":"address"}],"anonymous":false},{"type":"event","name":"Paused","inputs":[{"name":"account","type":"address","indexed":true,"internalType":"address"},{"name":"newPausedStatus","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"PauserRegistrySet","inputs":[{"name":"pauserRegistry","type":"address","indexed":false,"internalType":"contract IPauserRegistry"},{"name":"newPauserRegistry","type":"address","indexed":false,"internalType":"contract IPauserRegistry"}],"anonymous":false},{"type":"event","name":"StakerDelegated","inputs":[{"name":"staker","type":"address","indexed":true,"internalType":"address"},{"name":"operator","type":"address","indexed":true,"internalType":"address"}],"anonymous":false},{"type":"event","name":"StakerForceUndelegated","inputs":[{"name":"staker","type":"address","indexed":true,"internalType":"address"},{"name":"operator","type":"address","indexed":true,"internalType":"address"}],"anonymous":false},{"type":"event","name":"StakerUndelegated","inputs":[{"name":"staker","type":"address","indexed":true,"internalType":"address"},{"name":"operator","type":"address","indexed":true,"internalType":"address"}],"anonymous":false},{"type":"event","name":"StrategyWithdrawalDelayBlocksSet","inputs":[{"name":"strategy","type":"address","indexed":false,"internalType":"contract IStrategy"},{"name":"previousValue","type":"uint256","indexed":false,"internalType":"uint256"},{"name":"newValue","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"Unpaused","inputs":[{"name":"account","type":"address","indexed":true,"internalType":"address"},{"name":"newPausedStatus","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"WithdrawalCompleted","inputs":[{"name":"withdrawalRoot","type":"bytes32","indexed":false,"internalType":"bytes32"}],"anonymous":false},{"type":"event","name":"WithdrawalQueued","inputs":[{"name":"withdrawalRoot","type":"bytes32","indexed":false,"internalType":"bytes32"},{"name":"withdrawal","type":"tuple","indexed":false,"internalType":"struct IDelegationManager.Withdrawal","components":[{"name":"staker","type":"address","internalType":"address"},{"name":"delegatedTo","type":"address","internalType":"address"},{"name":"withdrawer","type":"address","internalType":"address"},{"name":"nonce","type":"uint256","internalType":"uint256"},{"name":"startBlock","type":"uint32","internalType":"uint32"},{"name":"strategies","type":"address[]","internalType":"contract IStrategy[]"},{"name":"shares","type":"uint256[]","internalType":"uint256[]"}]}],"anonymous":false}],"bytecode":{"object":"0x6101006040523480156200001257600080fd5b5060405162005c3338038062005c33833981016040819052620000359162000140565b6001600160a01b0380841660805280821660c052821660a0526200005862000065565b50504660e0525062000194565b600054610100900460ff1615620000d25760405162461bcd60e51b815260206004820152602760248201527f496e697469616c697a61626c653a20636f6e747261637420697320696e697469604482015266616c697a696e6760c81b606482015260840160405180910390fd5b60005460ff908116101562000125576000805460ff191660ff9081179091556040519081527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b565b6001600160a01b03811681146200013d57600080fd5b50565b6000806000606084860312156200015657600080fd5b8351620001638162000127565b6020850151909350620001768162000127565b6040850151909250620001898162000127565b809150509250925092565b60805160a05160c05160e051615a0a6200022960003960006126870152600081816105b10152818161102e015281816113aa01528181611c0a015281816129e001528181613e93015261437f015260006107620152600081816104f901528181610ffc0152818161137801528181611c9e01528181612aad01528181612c3001528181613fb901526144250152615a0a6000f3fe608060405234801561001057600080fd5b50600436106103425760003560e01c8063635bbd10116101b8578063b7f06ebe11610104578063cf80873e116100a2578063f16172b01161007c578063f16172b014610908578063f2fde38b1461091b578063f698da251461092e578063fabc1cbc1461093657600080fd5b8063cf80873e146108c1578063da8be864146108e2578063eea9064b146108f557600080fd5b8063c488375a116100de578063c488375a146107de578063c5e480db146107fe578063c94b5111146108a4578063ca661c04146108b757600080fd5b8063b7f06ebe14610784578063bb45fef2146107a7578063c448feb8146107d557600080fd5b8063886f1195116101715780639104c3191161014b5780639104c3191461070f57806399be81c81461072a578063a17884841461073d578063b13442711461075d57600080fd5b8063886f1195146106cb5780638da5cb5b146106de57806390041347146106ef57600080fd5b8063635bbd101461063657806365da1264146106495780636d70f7ae14610672578063715018a614610685578063778e55f31461068d5780637f548071146106b857600080fd5b806328a573ae116102925780634665bcda11610230578063597b36da1161020a578063597b36da146105e55780635ac86ab7146105f85780635c975abb1461061b57806360d7faed1461062357600080fd5b80634665bcda146105ac5780634fc40b61146105d3578063595c6a67146105dd57600080fd5b806339b70e381161026c57806339b70e38146104f45780633cdeb5e0146105335780633e28391d14610562578063433773821461058557600080fd5b806328a573ae146104ae57806329c77d4f146104c157806333404396146104e157600080fd5b8063132d4967116102ff57806316928365116102d957806316928365146104285780631bbce0911461046157806320606b701461047457806322bf40e41461049b57600080fd5b8063132d4967146103ef578063136439dd146104025780631522bf021461041557600080fd5b80630449ca391461034757806304a4f9791461036d5780630b9f487a146103945780630dd8dd02146103a75780630f589e59146103c757806310d67a2f146103dc575b600080fd5b61035a610355366004614835565b610949565b6040519081526020015b60405180910390f35b61035a7f14bde674c9f64b2ad00eaaee4a8bed1fabef35c7507e3c5b9cfc9436909a2dad81565b61035a6103a236600461489b565b6109ce565b6103ba6103b5366004614835565b610a90565b60405161036491906148f6565b6103da6103d5366004614993565b610df9565b005b6103da6103ea3660046149e6565b610f3e565b6103da6103fd366004614a0a565b610ff1565b6103da610410366004614a4b565b6110a8565b6103da610423366004614a64565b6111e7565b61035a6104363660046149e6565b6001600160a01b0316600090815260996020526040902060010154600160a01b900463ffffffff1690565b61035a61046f366004614a0a565b6111fb565b61035a7f8cad95687ba82c2ce50e74f7b754645e5117c3a5bec8151c0726d5857980a86681565b6103da6104a9366004614acf565b611229565b6103da6104bc366004614a0a565b61136d565b61035a6104cf3660046149e6565b609b6020526000908152604090205481565b6103da6104ef366004614b76565b61141d565b61051b7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610364565b61051b6105413660046149e6565b6001600160a01b039081166000908152609960205260409020600101541690565b6105756105703660046149e6565b61155a565b6040519015158152602001610364565b61035a7f39111bc4a4d688e1f685123d7497d4615370152a8ee4a0593e647bd06ad8bb0b81565b61051b7f000000000000000000000000000000000000000000000000000000000000000081565b61035a6213c68081565b6103da61157a565b61035a6105f3366004614e73565b611641565b610575610606366004614eaf565b606654600160ff9092169190911b9081161490565b60665461035a565b6103da610631366004614ee0565b611671565b6103da610644366004614a4b565b61170c565b61051b6106573660046149e6565b609a602052600090815260409020546001600160a01b031681565b6105756106803660046149e6565b61171d565b6103da61173e565b61035a61069b366004614f6f565b609860209081526000928352604080842090915290825290205481565b6103da6106c6366004615050565b611752565b60655461051b906001600160a01b031681565b6033546001600160a01b031661051b565b6107026106fd3660046150e0565b61197e565b604051610364919061516a565b61051b73beac0eeeeeeeeeeeeeeeeeeeeeeeeeeeeeebeac081565b6103da61073836600461517d565b611a58565b61035a61074b3660046149e6565b609f6020526000908152604090205481565b61051b7f000000000000000000000000000000000000000000000000000000000000000081565b610575610792366004614a4b565b609e6020526000908152604090205460ff1681565b6105756107b53660046151b2565b609c60209081526000928352604080842090915290825290205460ff1681565b61035a609d5481565b61035a6107ec3660046149e6565b60a16020526000908152604090205481565b61086e61080c3660046149e6565b6040805160608082018352600080835260208084018290529284018190526001600160a01b03948516815260998352839020835191820184528054851682526001015493841691810191909152600160a01b90920463ffffffff169082015290565b6040805182516001600160a01b039081168252602080850151909116908201529181015163ffffffff1690820152606001610364565b61035a6108b23660046151de565b611b2a565b61035a62034bc081565b6108d46108cf3660046149e6565b611be3565b60405161036492919061525f565b6103ba6108f03660046149e6565b611f9b565b6103da610903366004615284565b61245f565b6103da6109163660046152dc565b61257c565b6103da6109293660046149e6565b61260d565b61035a612683565b6103da610944366004614a4b565b6126c1565b609d54600090815b838110156109c657600060a16000878785818110610971576109716152f8565b905060200201602081019061098691906149e6565b6001600160a01b03166001600160a01b03168152602001908152602001600020549050828111156109b5578092505b506109bf81615324565b9050610951565b509392505050565b604080517f14bde674c9f64b2ad00eaaee4a8bed1fabef35c7507e3c5b9cfc9436909a2dad6020808301919091526001600160a01b038681168385015288811660608401528716608083015260a0820185905260c08083018590528351808403909101815260e0909201909252805191012060009081610a4c612683565b60405161190160f01b602082015260228101919091526042810183905260620160408051808303601f19018152919052805160209091012098975050505050505050565b60665460609060019060029081161415610ac55760405162461bcd60e51b8152600401610abc9061533f565b60405180910390fd5b6000836001600160401b03811115610adf57610adf614c18565b604051908082528060200260200182016040528015610b08578160200160208202803683370190505b50336000908152609a60205260408120549192506001600160a01b03909116905b85811015610dee57868682818110610b4357610b436152f8565b9050602002810190610b559190615376565b610b63906020810190615396565b9050878783818110610b7757610b776152f8565b9050602002810190610b899190615376565b610b939080615396565b905014610c085760405162461bcd60e51b815260206004820152603860248201527f44656c65676174696f6e4d616e616765722e717565756557697468647261776160448201527f6c3a20696e707574206c656e677468206d69736d6174636800000000000000006064820152608401610abc565b33878783818110610c1b57610c1b6152f8565b9050602002810190610c2d9190615376565b610c3e9060608101906040016149e6565b6001600160a01b031614610cba5760405162461bcd60e51b815260206004820152603c60248201527f44656c65676174696f6e4d616e616765722e717565756557697468647261776160448201527f6c3a2077697468647261776572206d757374206265207374616b6572000000006064820152608401610abc565b610dbf3383898985818110610cd157610cd16152f8565b9050602002810190610ce39190615376565b610cf49060608101906040016149e6565b8a8a86818110610d0657610d066152f8565b9050602002810190610d189190615376565b610d229080615396565b808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152508e92508d9150889050818110610d6857610d686152f8565b9050602002810190610d7a9190615376565b610d88906020810190615396565b8080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525061281d92505050565b838281518110610dd157610dd16152f8565b602090810291909101015280610de681615324565b915050610b29565b509095945050505050565b610e023361155a565b15610e885760405162461bcd60e51b815260206004820152604a60248201527f44656c65676174696f6e4d616e616765722e726567697374657241734f70657260448201527f61746f723a2063616c6c657220697320616c7265616479206163746976656c796064820152690819195b1959d85d195960b21b608482015260a401610abc565b610e923384612ddd565b604080518082019091526060815260006020820152610eb43380836000612fd0565b336001600160a01b03167f8e8485583a2310d41f7c82b9427d0bd49bad74bb9cff9d3402a29d8f9b28a0e285604051610eed91906153df565b60405180910390a2336001600160a01b03167f02a919ed0e2acad1dd90f17ef2fa4ae5462ee1339170034a8531cca4b67080908484604051610f30929190615431565b60405180910390a250505050565b606560009054906101000a90046001600160a01b03166001600160a01b031663eab66d7a6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610f91573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fb59190615460565b6001600160a01b0316336001600160a01b031614610fe55760405162461bcd60e51b8152600401610abc9061547d565b610fee81613266565b50565b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614806110505750336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016145b61106c5760405162461bcd60e51b8152600401610abc906154c7565b6110758361155a565b156110a3576001600160a01b038084166000908152609a6020526040902054166110a18185858561335d565b505b505050565b60655460405163237dfb4760e11b81523360048201526001600160a01b03909116906346fbf68e90602401602060405180830381865afa1580156110f0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111149190615524565b6111305760405162461bcd60e51b8152600401610abc90615541565b606654818116146111a95760405162461bcd60e51b815260206004820152603860248201527f5061757361626c652e70617573653a20696e76616c696420617474656d70742060448201527f746f20756e70617573652066756e6374696f6e616c69747900000000000000006064820152608401610abc565b606681905560405181815233907fab40a374bc51de372200a8bc981af8c9ecdc08dfdaef0bb6e09f88f3c616ef3d906020015b60405180910390a250565b6111ef6133d8565b6110a184848484613432565b6001600160a01b0383166000908152609b602052604081205461122085828686611b2a565b95945050505050565b600054610100900460ff16158080156112495750600054600160ff909116105b806112635750303b158015611263575060005460ff166001145b6112c65760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608401610abc565b6000805460ff1916600117905580156112e9576000805461ff0019166101001790555b6112f38888613658565b6112fb613742565b609755611307896137d9565b6113108661382b565b61131c85858585613432565b8015611362576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050505050505050565b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614806113cc5750336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016145b6113e85760405162461bcd60e51b8152600401610abc906154c7565b6113f18361155a565b156110a3576001600160a01b038084166000908152609a6020526040902054166110a181858585613925565b606654600290600490811614156114465760405162461bcd60e51b8152600401610abc9061533f565b600260c95414156114995760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610abc565b600260c95560005b88811015611549576115398a8a838181106114be576114be6152f8565b90506020028101906114d09190615589565b8989848181106114e2576114e26152f8565b90506020028101906114f49190615396565b898986818110611506576115066152f8565b9050602002013588888781811061151f5761151f6152f8565b9050602002016020810190611534919061559f565b6139a0565b61154281615324565b90506114a1565b5050600160c9555050505050505050565b6001600160a01b039081166000908152609a602052604090205416151590565b60655460405163237dfb4760e11b81523360048201526001600160a01b03909116906346fbf68e90602401602060405180830381865afa1580156115c2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115e69190615524565b6116025760405162461bcd60e51b8152600401610abc90615541565b600019606681905560405190815233907fab40a374bc51de372200a8bc981af8c9ecdc08dfdaef0bb6e09f88f3c616ef3d9060200160405180910390a2565b6000816040516020016116549190615630565b604051602081830303815290604052805190602001209050919050565b6066546002906004908116141561169a5760405162461bcd60e51b8152600401610abc9061533f565b600260c95414156116ed5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610abc565b600260c9556116ff86868686866139a0565b5050600160c95550505050565b6117146133d8565b610fee8161382b565b6001600160a01b039081166000818152609a60205260409020549091161490565b6117466133d8565b61175060006137d9565b565b42836020015110156117d65760405162461bcd60e51b815260206004820152604160248201527f44656c65676174696f6e4d616e616765722e64656c6567617465546f4279536960448201527f676e61747572653a207374616b6572207369676e6174757265206578706972656064820152601960fa1b608482015260a401610abc565b6117df8561155a565b156118685760405162461bcd60e51b815260206004820152604d60248201527f44656c65676174696f6e4d616e616765722e64656c6567617465546f4279536960448201527f676e61747572653a207374616b657220697320616c726561647920616374697660648201526c195b1e4819195b1959d85d1959609a1b608482015260a401610abc565b6118718461171d565b6118fd5760405162461bcd60e51b815260206004820152605160248201527f44656c65676174696f6e4d616e616765722e64656c6567617465546f4279536960448201527f676e61747572653a206f70657261746f72206973206e6f7420726567697374656064820152703932b21034b71022b4b3b2b72630bcb2b960791b608482015260a401610abc565b6000609b6000876001600160a01b03166001600160a01b0316815260200190815260200160002054905060006119398783888860200151611b2a565b6001600160a01b0388166000908152609b602052604090206001840190558551909150611969908890839061418a565b61197587878686612fd0565b50505050505050565b6060600082516001600160401b0381111561199b5761199b614c18565b6040519080825280602002602001820160405280156119c4578160200160208202803683370190505b50905060005b83518110156109c6576001600160a01b03851660009081526098602052604081208551909190869084908110611a0257611a026152f8565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002054828281518110611a3d57611a3d6152f8565b6020908102919091010152611a5181615324565b90506119ca565b611a613361171d565b611ae35760405162461bcd60e51b815260206004820152604760248201527f44656c65676174696f6e4d616e616765722e7570646174654f70657261746f7260448201527f4d657461646174615552493a2063616c6c6572206d75737420626520616e206f6064820152663832b930ba37b960c91b608482015260a401610abc565b336001600160a01b03167f02a919ed0e2acad1dd90f17ef2fa4ae5462ee1339170034a8531cca4b67080908383604051611b1e929190615431565b60405180910390a25050565b604080517f39111bc4a4d688e1f685123d7497d4615370152a8ee4a0593e647bd06ad8bb0b6020808301919091526001600160a01b0387811683850152851660608301526080820186905260a08083018590528351808403909101815260c0909201909252805191012060009081611ba0612683565b60405161190160f01b602082015260228101919091526042810183905260620160408051808303601f190181529190528051602090910120979650505050505050565b6040516360f4062b60e01b81526001600160a01b03828116600483015260609182916000917f0000000000000000000000000000000000000000000000000000000000000000909116906360f4062b90602401602060405180830381865afa158015611c53573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c779190615643565b6040516394f649dd60e01b81526001600160a01b03868116600483015291925060009182917f0000000000000000000000000000000000000000000000000000000000000000909116906394f649dd90602401600060405180830381865afa158015611ce7573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052611d0f91908101906156b7565b9150915060008313611d2657909590945092505050565b606080835160001415611de0576040805160018082528183019092529060208083019080368337505060408051600180825281830190925292945090506020808301908036833701905050905073beac0eeeeeeeeeeeeeeeeeeeeeeeeeeeeeebeac082600081518110611d9b57611d9b6152f8565b60200260200101906001600160a01b031690816001600160a01b0316815250508481600081518110611dcf57611dcf6152f8565b602002602001018181525050611f8e565b8351611ded906001615771565b6001600160401b03811115611e0457611e04614c18565b604051908082528060200260200182016040528015611e2d578160200160208202803683370190505b50915081516001600160401b03811115611e4957611e49614c18565b604051908082528060200260200182016040528015611e72578160200160208202803683370190505b50905060005b8451811015611f0c57848181518110611e9357611e936152f8565b6020026020010151838281518110611ead57611ead6152f8565b60200260200101906001600160a01b031690816001600160a01b031681525050838181518110611edf57611edf6152f8565b6020026020010151828281518110611ef957611ef96152f8565b6020908102919091010152600101611e78565b5073beac0eeeeeeeeeeeeeeeeeeeeeeeeeeeeeebeac08260018451611f319190615789565b81518110611f4157611f416152f8565b60200260200101906001600160a01b031690816001600160a01b031681525050848160018451611f719190615789565b81518110611f8157611f816152f8565b6020026020010181815250505b9097909650945050505050565b60665460609060019060029081161415611fc75760405162461bcd60e51b8152600401610abc9061533f565b611fd08361155a565b6120505760405162461bcd60e51b8152602060048201526044602482018190527f44656c65676174696f6e4d616e616765722e756e64656c65676174653a207374908201527f616b6572206d7573742062652064656c65676174656420746f20756e64656c656064820152636761746560e01b608482015260a401610abc565b6120598361171d565b156120cc5760405162461bcd60e51b815260206004820152603d60248201527f44656c65676174696f6e4d616e616765722e756e64656c65676174653a206f7060448201527f657261746f72732063616e6e6f7420626520756e64656c6567617465640000006064820152608401610abc565b6001600160a01b0383166121485760405162461bcd60e51b815260206004820152603c60248201527f44656c65676174696f6e4d616e616765722e756e64656c65676174653a20636160448201527f6e6e6f7420756e64656c6567617465207a65726f2061646472657373000000006064820152608401610abc565b6001600160a01b038084166000818152609a60205260409020549091169033148061217b5750336001600160a01b038216145b806121a257506001600160a01b038181166000908152609960205260409020600101541633145b6122145760405162461bcd60e51b815260206004820152603d60248201527f44656c65676174696f6e4d616e616765722e756e64656c65676174653a20636160448201527f6c6c65722063616e6e6f7420756e64656c6567617465207374616b65720000006064820152608401610abc565b60008061222086611be3565b9092509050336001600160a01b0387161461227657826001600160a01b0316866001600160a01b03167ff0eddf07e6ea14f388b47e1e94a0f464ecbd9eed4171130e0fc0e99fb4030a8a60405160405180910390a35b826001600160a01b0316866001600160a01b03167ffee30966a256b71e14bc0ebfc94315e28ef4a97a7131a9e2b7a310a73af4467660405160405180910390a36001600160a01b0386166000908152609a6020526040902080546001600160a01b031916905581516122f8576040805160008152602081019091529450612456565b81516001600160401b0381111561231157612311614c18565b60405190808252806020026020018201604052801561233a578160200160208202803683370190505b50945060005b8251811015612454576040805160018082528183019092526000916020808301908036833750506040805160018082528183019092529293506000929150602080830190803683370190505090508483815181106123a0576123a06152f8565b6020026020010151826000815181106123bb576123bb6152f8565b60200260200101906001600160a01b031690816001600160a01b0316815250508383815181106123ed576123ed6152f8565b602002602001015181600081518110612408576124086152f8565b60200260200101818152505061242189878b858561281d565b888481518110612433576124336152f8565b6020026020010181815250505050808061244c90615324565b915050612340565b505b50505050919050565b6124683361155a565b156124e65760405162461bcd60e51b815260206004820152604260248201527f44656c65676174696f6e4d616e616765722e64656c6567617465546f3a20737460448201527f616b657220697320616c7265616479206163746976656c792064656c65676174606482015261195960f21b608482015260a401610abc565b6124ef8361171d565b6125705760405162461bcd60e51b815260206004820152604660248201527f44656c65676174696f6e4d616e616765722e64656c6567617465546f3a206f7060448201527f657261746f72206973206e6f74207265676973746572656420696e2045696765606482015265372630bcb2b960d11b608482015260a401610abc565b6110a333848484612fd0565b6125853361171d565b6126035760405162461bcd60e51b815260206004820152604360248201527f44656c65676174696f6e4d616e616765722e6d6f646966794f70657261746f7260448201527f44657461696c733a2063616c6c6572206d75737420626520616e206f706572616064820152623a37b960e91b608482015260a401610abc565b610fee3382612ddd565b6126156133d8565b6001600160a01b03811661267a5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610abc565b610fee816137d9565b60007f00000000000000000000000000000000000000000000000000000000000000004614156126b4575060975490565b6126bc613742565b905090565b606560009054906101000a90046001600160a01b03166001600160a01b031663eab66d7a6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612714573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127389190615460565b6001600160a01b0316336001600160a01b0316146127685760405162461bcd60e51b8152600401610abc9061547d565b6066541981196066541916146127e65760405162461bcd60e51b815260206004820152603860248201527f5061757361626c652e756e70617573653a20696e76616c696420617474656d7060448201527f7420746f2070617573652066756e6374696f6e616c69747900000000000000006064820152608401610abc565b606681905560405181815233907f3582d1828e26bf56bd801502bc021ac0bc8afb57c826e4986b45593c8fad389c906020016111dc565b60006001600160a01b0386166128b45760405162461bcd60e51b815260206004820152605060248201527f44656c65676174696f6e4d616e616765722e5f72656d6f76655368617265734160448201527f6e6451756575655769746864726177616c3a207374616b65722063616e6e6f7460648201526f206265207a65726f206164647265737360801b608482015260a401610abc565b825161293e5760405162461bcd60e51b815260206004820152604d60248201527f44656c65676174696f6e4d616e616765722e5f72656d6f76655368617265734160448201527f6e6451756575655769746864726177616c3a207374726174656769657320636160648201526c6e6e6f7420626520656d70747960981b608482015260a401610abc565b60005b8351811015612ceb576001600160a01b03861615612997576129978688868481518110612970576129706152f8565b602002602001015186858151811061298a5761298a6152f8565b602002602001015161335d565b73beac0eeeeeeeeeeeeeeeeeeeeeeeeeeeeeebeac06001600160a01b03168482815181106129c7576129c76152f8565b60200260200101516001600160a01b03161415612a90577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663beffbb8988858481518110612a2057612a206152f8565b60200260200101516040518363ffffffff1660e01b8152600401612a599291906001600160a01b03929092168252602082015260400190565b600060405180830381600087803b158015612a7357600080fd5b505af1158015612a87573d6000803e3d6000fd5b50505050612ce3565b846001600160a01b0316876001600160a01b03161480612b6257507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316639b4da03d858381518110612aec57612aec6152f8565b60200260200101516040518263ffffffff1660e01b8152600401612b1f91906001600160a01b0391909116815260200190565b602060405180830381865afa158015612b3c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b609190615524565b155b612c2e5760405162461bcd60e51b8152602060048201526084602482018190527f44656c65676174696f6e4d616e616765722e5f72656d6f76655368617265734160448301527f6e6451756575655769746864726177616c3a2077697468647261776572206d7560648301527f73742062652073616d652061646472657373206173207374616b657220696620908201527f746869726450617274795472616e7366657273466f7262696464656e2061726560a482015263081cd95d60e21b60c482015260e401610abc565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316638c80d4e588868481518110612c7057612c706152f8565b6020026020010151868581518110612c8a57612c8a6152f8565b60200260200101516040518463ffffffff1660e01b8152600401612cb0939291906157a0565b600060405180830381600087803b158015612cca57600080fd5b505af1158015612cde573d6000803e3d6000fd5b505050505b600101612941565b506001600160a01b0386166000908152609f60205260408120805491829190612d1383615324565b919050555060006040518060e00160405280896001600160a01b03168152602001886001600160a01b03168152602001876001600160a01b031681526020018381526020014363ffffffff1681526020018681526020018581525090506000612d7b82611641565b6000818152609e602052604090819020805460ff19166001179055519091507f9009ab153e8014fbfb02f2217f5cde7aa7f9ad734ae85ca3ee3f4ca2fdd499f990612dc990839085906157c4565b60405180910390a198975050505050505050565b6213c680612df160608301604084016157dd565b63ffffffff161115612ea65760405162461bcd60e51b815260206004820152606c60248201527f44656c65676174696f6e4d616e616765722e5f7365744f70657261746f72446560448201527f7461696c733a207374616b65724f70744f757457696e646f77426c6f636b732060648201527f63616e6e6f74206265203e204d41585f5354414b45525f4f50545f4f55545f5760848201526b494e444f575f424c4f434b5360a01b60a482015260c401610abc565b6001600160a01b0382166000908152609960205260409081902060010154600160a01b900463ffffffff1690612ee290606084019084016157dd565b63ffffffff161015612f785760405162461bcd60e51b815260206004820152605360248201527f44656c65676174696f6e4d616e616765722e5f7365744f70657261746f72446560448201527f7461696c733a207374616b65724f70744f757457696e646f77426c6f636b732060648201527218d85b9b9bdd08189948191958dc99585cd959606a1b608482015260a401610abc565b6001600160a01b03821660009081526099602052604090208190612f9c828261581a565b505060405133907ffebe5cd24b2cbc7b065b9d0fdeb904461e4afcff57dd57acda1e7832031ba7ac90611b1e9084906153df565b60665460009060019081161415612ff95760405162461bcd60e51b8152600401610abc9061533f565b6001600160a01b0380851660009081526099602052604090206001015416801580159061302f5750336001600160a01b03821614155b80156130445750336001600160a01b03861614155b156131b15742846020015110156130c35760405162461bcd60e51b815260206004820152603760248201527f44656c65676174696f6e4d616e616765722e5f64656c65676174653a2061707060448201527f726f766572207369676e617475726520657870697265640000000000000000006064820152608401610abc565b6001600160a01b0381166000908152609c6020908152604080832086845290915290205460ff161561315d5760405162461bcd60e51b815260206004820152603760248201527f44656c65676174696f6e4d616e616765722e5f64656c65676174653a2061707060448201527f726f76657253616c7420616c7265616479207370656e740000000000000000006064820152608401610abc565b6001600160a01b0381166000908152609c6020908152604080832086845282528220805460ff1916600117905585015161319e9088908890859088906109ce565b90506131af8282876000015161418a565b505b6001600160a01b038681166000818152609a602052604080822080546001600160a01b031916948a169485179055517fc3ee9f2e5fda98e8066a1f745b2df9285f416fe98cf2559cd21484b3d87433049190a360008061321088611be3565b9150915060005b82518110156113625761325e888a858481518110613237576132376152f8565b6020026020010151858581518110613251576132516152f8565b6020026020010151613925565b600101613217565b6001600160a01b0381166132f45760405162461bcd60e51b815260206004820152604960248201527f5061757361626c652e5f73657450617573657252656769737472793a206e657760448201527f50617573657252656769737472792063616e6e6f7420626520746865207a65726064820152686f206164647265737360b81b608482015260a401610abc565b606554604080516001600160a01b03928316815291831660208301527f6e9fcd539896fca60e8b0f01dd580233e48a6b0f7df013b89ba7f565869acdb6910160405180910390a1606580546001600160a01b0319166001600160a01b0392909216919091179055565b6001600160a01b03808516600090815260986020908152604080832093861683529290529081208054839290613394908490615789565b92505081905550836001600160a01b03167f6909600037b75d7b4733aedd815442b5ec018a827751c832aaff64eba5d6d2dd848484604051610f30939291906157a0565b6033546001600160a01b031633146117505760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610abc565b8281146134ba5760405162461bcd60e51b815260206004820152604a60248201527f44656c65676174696f6e4d616e616765722e5f7365745374726174656779576960448201527f746864726177616c44656c6179426c6f636b733a20696e707574206c656e67746064820152690d040dad2e6dac2e8c6d60b31b608482015260a401610abc565b8260005b818110156136505760008686838181106134da576134da6152f8565b90506020020160208101906134ef91906149e6565b6001600160a01b038116600090815260a1602052604081205491925086868581811061351d5761351d6152f8565b90506020020135905062034bc08111156135e15760405162461bcd60e51b815260206004820152607360248201527f44656c65676174696f6e4d616e616765722e5f7365745374726174656779576960448201527f746864726177616c44656c6179426c6f636b733a205f7769746864726177616c60648201527f44656c6179426c6f636b732063616e6e6f74206265203e204d41585f5749544860848201527244524157414c5f44454c41595f424c4f434b5360681b60a482015260c401610abc565b6001600160a01b038316600081815260a160209081526040918290208490558151928352820184905281018290527f0e7efa738e8b0ce6376a0c1af471655540d2e9a81647d7b09ed823018426576d9060600160405180910390a15050508061364990615324565b90506134be565b505050505050565b6065546001600160a01b031615801561367957506001600160a01b03821615155b6136fb5760405162461bcd60e51b815260206004820152604760248201527f5061757361626c652e5f696e697469616c697a655061757365723a205f696e6960448201527f7469616c697a6550617573657228292063616e206f6e6c792062652063616c6c6064820152666564206f6e636560c81b608482015260a401610abc565b606681905560405181815233907fab40a374bc51de372200a8bc981af8c9ecdc08dfdaef0bb6e09f88f3c616ef3d9060200160405180910390a261373e82613266565b5050565b604080518082018252600a81526922b4b3b2b72630bcb2b960b11b60209182015281517f8cad95687ba82c2ce50e74f7b754645e5117c3a5bec8151c0726d5857980a866818301527f71b625cfad44bac63b13dba07f2e1d6084ee04b6f8752101ece6126d584ee6ea81840152466060820152306080808301919091528351808303909101815260a0909101909252815191012090565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b62034bc08111156138e45760405162461bcd60e51b815260206004820152607160248201527f44656c65676174696f6e4d616e616765722e5f7365744d696e5769746864726160448201527f77616c44656c6179426c6f636b733a205f6d696e5769746864726177616c446560648201527f6c6179426c6f636b732063616e6e6f74206265203e204d41585f5749544844526084820152704157414c5f44454c41595f424c4f434b5360781b60a482015260c401610abc565b609d5460408051918252602082018390527fafa003cd76f87ff9d62b35beea889920f33c0c42b8d45b74954d61d50f4b6b69910160405180910390a1609d55565b6001600160a01b0380851660009081526098602090815260408083209386168352929052908120805483929061395c908490615771565b92505081905550836001600160a01b03167f1ec042c965e2edd7107b51188ee0f383e22e76179041ab3a9d18ff151405166c848484604051610f30939291906157a0565b60006139ae6105f38761587d565b6000818152609e602052604090205490915060ff16613a2f5760405162461bcd60e51b815260206004820152604360248201526000805160206159b583398151915260448201527f645769746864726177616c3a20616374696f6e206973206e6f7420696e20717560648201526265756560e81b608482015260a401610abc565b609d544390613a4460a0890160808a016157dd565b63ffffffff16613a549190615771565b1115613adc5760405162461bcd60e51b815260206004820152605f60248201526000805160206159b583398151915260448201527f645769746864726177616c3a206d696e5769746864726177616c44656c61794260648201527f6c6f636b7320706572696f6420686173206e6f74207965742070617373656400608482015260a401610abc565b613aec60608701604088016149e6565b6001600160a01b0316336001600160a01b031614613b795760405162461bcd60e51b815260206004820152605060248201526000805160206159b583398151915260448201527f645769746864726177616c3a206f6e6c7920776974686472617765722063616e60648201526f1031b7b6b83632ba329030b1ba34b7b760811b608482015260a401610abc565b8115613bfb57613b8c60a0870187615396565b85149050613bfb5760405162461bcd60e51b815260206004820152604260248201526000805160206159b583398151915260448201527f645769746864726177616c3a20696e707574206c656e677468206d69736d61746064820152610c6d60f31b608482015260a401610abc565b6000818152609e60205260409020805460ff191690558115613d605760005b613c2760a0880188615396565b9050811015613d5a574360a16000613c4260a08b018b615396565b85818110613c5257613c526152f8565b9050602002016020810190613c6791906149e6565b6001600160a01b03168152602081019190915260400160002054613c9160a08a0160808b016157dd565b63ffffffff16613ca19190615771565b1115613cbf5760405162461bcd60e51b8152600401610abc9061588f565b613d52613ccf60208901896149e6565b33613cdd60a08b018b615396565b85818110613ced57613ced6152f8565b9050602002016020810190613d0291906149e6565b613d0f60c08c018c615396565b86818110613d1f57613d1f6152f8565b905060200201358a8a87818110613d3857613d386152f8565b9050602002016020810190613d4d91906149e6565b614344565b600101613c1a565b5061414f565b336000908152609a60205260408120546001600160a01b0316905b613d8860a0890189615396565b905081101561414c574360a16000613da360a08c018c615396565b85818110613db357613db36152f8565b9050602002016020810190613dc891906149e6565b6001600160a01b03168152602081019190915260400160002054613df260a08b0160808c016157dd565b63ffffffff16613e029190615771565b1115613e205760405162461bcd60e51b8152600401610abc9061588f565b73beac0eeeeeeeeeeeeeeeeeeeeeeeeeeeeeebeac0613e4260a08a018a615396565b83818110613e5257613e526152f8565b9050602002016020810190613e6791906149e6565b6001600160a01b03161415613fb7576000613e8560208a018a6149e6565b905060006001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016630e81073c83613ec660c08e018e615396565b87818110613ed657613ed66152f8565b6040516001600160e01b031960e087901b1681526001600160a01b03909416600485015260200291909101356024830152506044016020604051808303816000875af1158015613f2a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613f4e9190615643565b6001600160a01b038084166000908152609a6020526040902054919250168015613faf57613faf8184613f8460a08f018f615396565b88818110613f9457613f946152f8565b9050602002016020810190613fa991906149e6565b85613925565b505050614144565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663c4623ea133898985818110613ff957613ff96152f8565b905060200201602081019061400e91906149e6565b61401b60a08d018d615396565b8681811061402b5761402b6152f8565b905060200201602081019061404091906149e6565b61404d60c08e018e615396565b8781811061405d5761405d6152f8565b60405160e088901b6001600160e01b03191681526001600160a01b03968716600482015294861660248601529290941660448401526020909102013560648201526084019050600060405180830381600087803b1580156140bd57600080fd5b505af11580156140d1573d6000803e3d6000fd5b505050506001600160a01b038216156141445761414482336140f660a08c018c615396565b85818110614106576141066152f8565b905060200201602081019061411b91906149e6565b61412860c08d018d615396565b86818110614138576141386152f8565b90506020020135613925565b600101613d7b565b50505b6040518181527fc97098c2f658800b4df29001527f7324bcdffcf6e8751a699ab920a1eced5b1d9060200160405180910390a1505050505050565b6001600160a01b0383163b156142a457604051630b135d3f60e11b808252906001600160a01b03851690631626ba7e906141ca9086908690600401615917565b602060405180830381865afa1580156141e7573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061420b9190615974565b6001600160e01b031916146110a35760405162461bcd60e51b815260206004820152605360248201527f454950313237315369676e61747572655574696c732e636865636b5369676e6160448201527f747572655f454950313237313a2045524331323731207369676e6174757265206064820152721d995c9a599a58d85d1a5bdb8819985a5b1959606a1b608482015260a401610abc565b826001600160a01b03166142b88383614484565b6001600160a01b0316146110a35760405162461bcd60e51b815260206004820152604760248201527f454950313237315369676e61747572655574696c732e636865636b5369676e6160448201527f747572655f454950313237313a207369676e6174757265206e6f742066726f6d6064820152661039b4b3b732b960c91b608482015260a401610abc565b6001600160a01b03831673beac0eeeeeeeeeeeeeeeeeeeeeeeeeeeeeebeac014156143ef5760405162387b1360e81b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063387b1300906143b8908890889087906004016157a0565b600060405180830381600087803b1580156143d257600080fd5b505af11580156143e6573d6000803e3d6000fd5b5050505061447d565b60405163c608c7f360e01b81526001600160a01b03858116600483015284811660248301526044820184905282811660648301527f0000000000000000000000000000000000000000000000000000000000000000169063c608c7f390608401600060405180830381600087803b15801561446957600080fd5b505af1158015611362573d6000803e3d6000fd5b5050505050565b600080600061449385856144a0565b915091506109c681614510565b6000808251604114156144d75760208301516040840151606085015160001a6144cb878285856146cb565b94509450505050614509565b82516040141561450157602083015160408401516144f68683836147b8565b935093505050614509565b506000905060025b9250929050565b60008160048111156145245761452461599e565b141561452d5750565b60018160048111156145415761454161599e565b141561458f5760405162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e617475726500000000000000006044820152606401610abc565b60028160048111156145a3576145a361599e565b14156145f15760405162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e677468006044820152606401610abc565b60038160048111156146055761460561599e565b141561465e5760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c604482015261756560f01b6064820152608401610abc565b60048160048111156146725761467261599e565b1415610fee5760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202776272076616c604482015261756560f01b6064820152608401610abc565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a083111561470257506000905060036147af565b8460ff16601b1415801561471a57508460ff16601c14155b1561472b57506000905060046147af565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa15801561477f573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b0381166147a8576000600192509250506147af565b9150600090505b94509492505050565b6000806001600160ff1b038316816147d560ff86901c601b615771565b90506147e3878288856146cb565b935093505050935093915050565b60008083601f84011261480357600080fd5b5081356001600160401b0381111561481a57600080fd5b6020830191508360208260051b850101111561450957600080fd5b6000806020838503121561484857600080fd5b82356001600160401b0381111561485e57600080fd5b61486a858286016147f1565b90969095509350505050565b6001600160a01b0381168114610fee57600080fd5b803561489681614876565b919050565b600080600080600060a086880312156148b357600080fd5b85356148be81614876565b945060208601356148ce81614876565b935060408601356148de81614876565b94979396509394606081013594506080013592915050565b6020808252825182820181905260009190848201906040850190845b8181101561492e57835183529284019291840191600101614912565b50909695505050505050565b60006060828403121561494c57600080fd5b50919050565b60008083601f84011261496457600080fd5b5081356001600160401b0381111561497b57600080fd5b60208301915083602082850101111561450957600080fd5b6000806000608084860312156149a857600080fd5b6149b2858561493a565b925060608401356001600160401b038111156149cd57600080fd5b6149d986828701614952565b9497909650939450505050565b6000602082840312156149f857600080fd5b8135614a0381614876565b9392505050565b600080600060608486031215614a1f57600080fd5b8335614a2a81614876565b92506020840135614a3a81614876565b929592945050506040919091013590565b600060208284031215614a5d57600080fd5b5035919050565b60008060008060408587031215614a7a57600080fd5b84356001600160401b0380821115614a9157600080fd5b614a9d888389016147f1565b90965094506020870135915080821115614ab657600080fd5b50614ac3878288016147f1565b95989497509550505050565b60008060008060008060008060c0898b031215614aeb57600080fd5b8835614af681614876565b97506020890135614b0681614876565b9650604089013595506060890135945060808901356001600160401b0380821115614b3057600080fd5b614b3c8c838d016147f1565b909650945060a08b0135915080821115614b5557600080fd5b50614b628b828c016147f1565b999c989b5096995094979396929594505050565b6000806000806000806000806080898b031215614b9257600080fd5b88356001600160401b0380821115614ba957600080fd5b614bb58c838d016147f1565b909a50985060208b0135915080821115614bce57600080fd5b614bda8c838d016147f1565b909850965060408b0135915080821115614bf357600080fd5b614bff8c838d016147f1565b909650945060608b0135915080821115614b5557600080fd5b634e487b7160e01b600052604160045260246000fd5b60405160e081016001600160401b0381118282101715614c5057614c50614c18565b60405290565b604080519081016001600160401b0381118282101715614c5057614c50614c18565b604051601f8201601f191681016001600160401b0381118282101715614ca057614ca0614c18565b604052919050565b63ffffffff81168114610fee57600080fd5b803561489681614ca8565b60006001600160401b03821115614cde57614cde614c18565b5060051b60200190565b600082601f830112614cf957600080fd5b81356020614d0e614d0983614cc5565b614c78565b82815260059290921b84018101918181019086841115614d2d57600080fd5b8286015b84811015614d51578035614d4481614876565b8352918301918301614d31565b509695505050505050565b600082601f830112614d6d57600080fd5b81356020614d7d614d0983614cc5565b82815260059290921b84018101918181019086841115614d9c57600080fd5b8286015b84811015614d515780358352918301918301614da0565b600060e08284031215614dc957600080fd5b614dd1614c2e565b9050614ddc8261488b565b8152614dea6020830161488b565b6020820152614dfb6040830161488b565b604082015260608201356060820152614e1660808301614cba565b608082015260a08201356001600160401b0380821115614e3557600080fd5b614e4185838601614ce8565b60a084015260c0840135915080821115614e5a57600080fd5b50614e6784828501614d5c565b60c08301525092915050565b600060208284031215614e8557600080fd5b81356001600160401b03811115614e9b57600080fd5b614ea784828501614db7565b949350505050565b600060208284031215614ec157600080fd5b813560ff81168114614a0357600080fd5b8015158114610fee57600080fd5b600080600080600060808688031215614ef857600080fd5b85356001600160401b0380821115614f0f57600080fd5b9087019060e0828a031215614f2357600080fd5b90955060208701359080821115614f3957600080fd5b50614f46888289016147f1565b909550935050604086013591506060860135614f6181614ed2565b809150509295509295909350565b60008060408385031215614f8257600080fd5b8235614f8d81614876565b91506020830135614f9d81614876565b809150509250929050565b600060408284031215614fba57600080fd5b614fc2614c56565b905081356001600160401b0380821115614fdb57600080fd5b818401915084601f830112614fef57600080fd5b813560208282111561500357615003614c18565b615015601f8301601f19168201614c78565b9250818352868183860101111561502b57600080fd5b8181850182850137600081838501015282855280860135818601525050505092915050565b600080600080600060a0868803121561506857600080fd5b853561507381614876565b9450602086013561508381614876565b935060408601356001600160401b038082111561509f57600080fd5b6150ab89838a01614fa8565b945060608801359150808211156150c157600080fd5b506150ce88828901614fa8565b95989497509295608001359392505050565b600080604083850312156150f357600080fd5b82356150fe81614876565b915060208301356001600160401b0381111561511957600080fd5b61512585828601614ce8565b9150509250929050565b600081518084526020808501945080840160005b8381101561515f57815187529582019590820190600101615143565b509495945050505050565b602081526000614a03602083018461512f565b6000806020838503121561519057600080fd5b82356001600160401b038111156151a657600080fd5b61486a85828601614952565b600080604083850312156151c557600080fd5b82356151d081614876565b946020939093013593505050565b600080600080608085870312156151f457600080fd5b84356151ff81614876565b935060208501359250604085013561521681614876565b9396929550929360600135925050565b600081518084526020808501945080840160005b8381101561515f5781516001600160a01b03168752958201959082019060010161523a565b6040815260006152726040830185615226565b8281036020840152611220818561512f565b60008060006060848603121561529957600080fd5b83356152a481614876565b925060208401356001600160401b038111156152bf57600080fd5b6152cb86828701614fa8565b925050604084013590509250925092565b6000606082840312156152ee57600080fd5b614a03838361493a565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b60006000198214156153385761533861530e565b5060010190565b60208082526019908201527f5061757361626c653a20696e6465782069732070617573656400000000000000604082015260600190565b60008235605e1983360301811261538c57600080fd5b9190910192915050565b6000808335601e198436030181126153ad57600080fd5b8301803591506001600160401b038211156153c757600080fd5b6020019150600581901b360382131561450957600080fd5b6060810182356153ee81614876565b6001600160a01b03908116835260208401359061540a82614876565b166020830152604083013561541e81614ca8565b63ffffffff811660408401525092915050565b60208152816020820152818360408301376000818301604090810191909152601f909201601f19160101919050565b60006020828403121561547257600080fd5b8151614a0381614876565b6020808252602a908201527f6d73672e73656e646572206973206e6f74207065726d697373696f6e6564206160408201526939903ab73830bab9b2b960b11b606082015260800190565b60208082526037908201527f44656c65676174696f6e4d616e616765723a206f6e6c7953747261746567794d60408201527f616e616765724f72456967656e506f644d616e61676572000000000000000000606082015260800190565b60006020828403121561553657600080fd5b8151614a0381614ed2565b60208082526028908201527f6d73672e73656e646572206973206e6f74207065726d697373696f6e6564206160408201526739903830bab9b2b960c11b606082015260800190565b6000823560de1983360301811261538c57600080fd5b6000602082840312156155b157600080fd5b8135614a0381614ed2565b600060018060a01b03808351168452806020840151166020850152806040840151166040850152506060820151606084015263ffffffff608083015116608084015260a082015160e060a085015261561760e0850182615226565b905060c083015184820360c0860152611220828261512f565b602081526000614a0360208301846155bc565b60006020828403121561565557600080fd5b5051919050565b600082601f83011261566d57600080fd5b8151602061567d614d0983614cc5565b82815260059290921b8401810191818101908684111561569c57600080fd5b8286015b84811015614d5157805183529183019183016156a0565b600080604083850312156156ca57600080fd5b82516001600160401b03808211156156e157600080fd5b818501915085601f8301126156f557600080fd5b81516020615705614d0983614cc5565b82815260059290921b8401810191818101908984111561572457600080fd5b948201945b8386101561574b57855161573c81614876565b82529482019490820190615729565b9188015191965090935050508082111561576457600080fd5b506151258582860161565c565b600082198211156157845761578461530e565b500190565b60008282101561579b5761579b61530e565b500390565b6001600160a01b039384168152919092166020820152604081019190915260600190565b828152604060208201526000614ea760408301846155bc565b6000602082840312156157ef57600080fd5b8135614a0381614ca8565b80546001600160a01b0319166001600160a01b0392909216919091179055565b813561582581614876565b61582f81836157fa565b5060018101602083013561584281614876565b61584c81836157fa565b50604083013561585b81614ca8565b815463ffffffff60a01b191660a09190911b63ffffffff60a01b161790555050565b60006158893683614db7565b92915050565b6020808252606e908201526000805160206159b583398151915260408201527f645769746864726177616c3a207769746864726177616c44656c6179426c6f6360608201527f6b7320706572696f6420686173206e6f74207965742070617373656420666f7260808201526d207468697320737472617465677960901b60a082015260c00190565b82815260006020604081840152835180604085015260005b8181101561594b5785810183015185820160600152820161592f565b8181111561595d576000606083870101525b50601f01601f191692909201606001949350505050565b60006020828403121561598657600080fd5b81516001600160e01b031981168114614a0357600080fd5b634e487b7160e01b600052602160045260246000fdfe44656c65676174696f6e4d616e616765722e5f636f6d706c6574655175657565a26469706673582212203a9863b190b0abcf799891a42203a11c6933a165f6897ec6ac670f95b48c927b64736f6c634300080c0033","sourceMap":"1137:46343:2:-:0;;;2862:284;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;5650:34:3;;;;;5694;;;;;5738:18;;;;3074:22:2::1;:20;:22::i;:::-;-1:-1:-1::0;;3126:13:2::1;3106:33;::::0;-1:-1:-1;1137:46343:2;;5388:279:46;5456:13;;;;;;;5455:14;5447:66;;;;-1:-1:-1;;;5447:66:46;;1015:2:184;5447:66:46;;;997:21:184;1054:2;1034:18;;;1027:30;1093:34;1073:18;;;1066:62;-1:-1:-1;;;1144:18:184;;;1137:37;1191:19;;5447:66:46;;;;;;;;5527:12;;5542:15;5527:12;;;:30;5523:138;;;5573:12;:30;;-1:-1:-1;;5573:30:46;5588:15;5573:30;;;;;;5622:28;;1363:36:184;;;5622:28:46;;1351:2:184;1336:18;5622:28:46;;;;;;;5523:138;5388:279::o;14:149:184:-;-1:-1:-1;;;;;107:31:184;;97:42;;87:70;;153:1;150;143:12;87:70;14:149;:::o;168:640::-;323:6;331;339;392:2;380:9;371:7;367:23;363:32;360:52;;;408:1;405;398:12;360:52;440:9;434:16;459:49;502:5;459:49;:::i;:::-;577:2;562:18;;556:25;527:5;;-1:-1:-1;590:51:184;556:25;590:51;:::i;:::-;712:2;697:18;;691:25;660:7;;-1:-1:-1;725:51:184;691:25;725:51;:::i;:::-;795:7;785:17;;;168:640;;;;;:::o;1221:184::-;1137:46343:2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;","linkReferences":{}},"deployedBytecode":{"object":"0x608060405234801561001057600080fd5b50600436106103425760003560e01c8063635bbd10116101b8578063b7f06ebe11610104578063cf80873e116100a2578063f16172b01161007c578063f16172b014610908578063f2fde38b1461091b578063f698da251461092e578063fabc1cbc1461093657600080fd5b8063cf80873e146108c1578063da8be864146108e2578063eea9064b146108f557600080fd5b8063c488375a116100de578063c488375a146107de578063c5e480db146107fe578063c94b5111146108a4578063ca661c04146108b757600080fd5b8063b7f06ebe14610784578063bb45fef2146107a7578063c448feb8146107d557600080fd5b8063886f1195116101715780639104c3191161014b5780639104c3191461070f57806399be81c81461072a578063a17884841461073d578063b13442711461075d57600080fd5b8063886f1195146106cb5780638da5cb5b146106de57806390041347146106ef57600080fd5b8063635bbd101461063657806365da1264146106495780636d70f7ae14610672578063715018a614610685578063778e55f31461068d5780637f548071146106b857600080fd5b806328a573ae116102925780634665bcda11610230578063597b36da1161020a578063597b36da146105e55780635ac86ab7146105f85780635c975abb1461061b57806360d7faed1461062357600080fd5b80634665bcda146105ac5780634fc40b61146105d3578063595c6a67146105dd57600080fd5b806339b70e381161026c57806339b70e38146104f45780633cdeb5e0146105335780633e28391d14610562578063433773821461058557600080fd5b806328a573ae146104ae57806329c77d4f146104c157806333404396146104e157600080fd5b8063132d4967116102ff57806316928365116102d957806316928365146104285780631bbce0911461046157806320606b701461047457806322bf40e41461049b57600080fd5b8063132d4967146103ef578063136439dd146104025780631522bf021461041557600080fd5b80630449ca391461034757806304a4f9791461036d5780630b9f487a146103945780630dd8dd02146103a75780630f589e59146103c757806310d67a2f146103dc575b600080fd5b61035a610355366004614835565b610949565b6040519081526020015b60405180910390f35b61035a7f14bde674c9f64b2ad00eaaee4a8bed1fabef35c7507e3c5b9cfc9436909a2dad81565b61035a6103a236600461489b565b6109ce565b6103ba6103b5366004614835565b610a90565b60405161036491906148f6565b6103da6103d5366004614993565b610df9565b005b6103da6103ea3660046149e6565b610f3e565b6103da6103fd366004614a0a565b610ff1565b6103da610410366004614a4b565b6110a8565b6103da610423366004614a64565b6111e7565b61035a6104363660046149e6565b6001600160a01b0316600090815260996020526040902060010154600160a01b900463ffffffff1690565b61035a61046f366004614a0a565b6111fb565b61035a7f8cad95687ba82c2ce50e74f7b754645e5117c3a5bec8151c0726d5857980a86681565b6103da6104a9366004614acf565b611229565b6103da6104bc366004614a0a565b61136d565b61035a6104cf3660046149e6565b609b6020526000908152604090205481565b6103da6104ef366004614b76565b61141d565b61051b7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610364565b61051b6105413660046149e6565b6001600160a01b039081166000908152609960205260409020600101541690565b6105756105703660046149e6565b61155a565b6040519015158152602001610364565b61035a7f39111bc4a4d688e1f685123d7497d4615370152a8ee4a0593e647bd06ad8bb0b81565b61051b7f000000000000000000000000000000000000000000000000000000000000000081565b61035a6213c68081565b6103da61157a565b61035a6105f3366004614e73565b611641565b610575610606366004614eaf565b606654600160ff9092169190911b9081161490565b60665461035a565b6103da610631366004614ee0565b611671565b6103da610644366004614a4b565b61170c565b61051b6106573660046149e6565b609a602052600090815260409020546001600160a01b031681565b6105756106803660046149e6565b61171d565b6103da61173e565b61035a61069b366004614f6f565b609860209081526000928352604080842090915290825290205481565b6103da6106c6366004615050565b611752565b60655461051b906001600160a01b031681565b6033546001600160a01b031661051b565b6107026106fd3660046150e0565b61197e565b604051610364919061516a565b61051b73beac0eeeeeeeeeeeeeeeeeeeeeeeeeeeeeebeac081565b6103da61073836600461517d565b611a58565b61035a61074b3660046149e6565b609f6020526000908152604090205481565b61051b7f000000000000000000000000000000000000000000000000000000000000000081565b610575610792366004614a4b565b609e6020526000908152604090205460ff1681565b6105756107b53660046151b2565b609c60209081526000928352604080842090915290825290205460ff1681565b61035a609d5481565b61035a6107ec3660046149e6565b60a16020526000908152604090205481565b61086e61080c3660046149e6565b6040805160608082018352600080835260208084018290529284018190526001600160a01b03948516815260998352839020835191820184528054851682526001015493841691810191909152600160a01b90920463ffffffff169082015290565b6040805182516001600160a01b039081168252602080850151909116908201529181015163ffffffff1690820152606001610364565b61035a6108b23660046151de565b611b2a565b61035a62034bc081565b6108d46108cf3660046149e6565b611be3565b60405161036492919061525f565b6103ba6108f03660046149e6565b611f9b565b6103da610903366004615284565b61245f565b6103da6109163660046152dc565b61257c565b6103da6109293660046149e6565b61260d565b61035a612683565b6103da610944366004614a4b565b6126c1565b609d54600090815b838110156109c657600060a16000878785818110610971576109716152f8565b905060200201602081019061098691906149e6565b6001600160a01b03166001600160a01b03168152602001908152602001600020549050828111156109b5578092505b506109bf81615324565b9050610951565b509392505050565b604080517f14bde674c9f64b2ad00eaaee4a8bed1fabef35c7507e3c5b9cfc9436909a2dad6020808301919091526001600160a01b038681168385015288811660608401528716608083015260a0820185905260c08083018590528351808403909101815260e0909201909252805191012060009081610a4c612683565b60405161190160f01b602082015260228101919091526042810183905260620160408051808303601f19018152919052805160209091012098975050505050505050565b60665460609060019060029081161415610ac55760405162461bcd60e51b8152600401610abc9061533f565b60405180910390fd5b6000836001600160401b03811115610adf57610adf614c18565b604051908082528060200260200182016040528015610b08578160200160208202803683370190505b50336000908152609a60205260408120549192506001600160a01b03909116905b85811015610dee57868682818110610b4357610b436152f8565b9050602002810190610b559190615376565b610b63906020810190615396565b9050878783818110610b7757610b776152f8565b9050602002810190610b899190615376565b610b939080615396565b905014610c085760405162461bcd60e51b815260206004820152603860248201527f44656c65676174696f6e4d616e616765722e717565756557697468647261776160448201527f6c3a20696e707574206c656e677468206d69736d6174636800000000000000006064820152608401610abc565b33878783818110610c1b57610c1b6152f8565b9050602002810190610c2d9190615376565b610c3e9060608101906040016149e6565b6001600160a01b031614610cba5760405162461bcd60e51b815260206004820152603c60248201527f44656c65676174696f6e4d616e616765722e717565756557697468647261776160448201527f6c3a2077697468647261776572206d757374206265207374616b6572000000006064820152608401610abc565b610dbf3383898985818110610cd157610cd16152f8565b9050602002810190610ce39190615376565b610cf49060608101906040016149e6565b8a8a86818110610d0657610d066152f8565b9050602002810190610d189190615376565b610d229080615396565b808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152508e92508d9150889050818110610d6857610d686152f8565b9050602002810190610d7a9190615376565b610d88906020810190615396565b8080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525061281d92505050565b838281518110610dd157610dd16152f8565b602090810291909101015280610de681615324565b915050610b29565b509095945050505050565b610e023361155a565b15610e885760405162461bcd60e51b815260206004820152604a60248201527f44656c65676174696f6e4d616e616765722e726567697374657241734f70657260448201527f61746f723a2063616c6c657220697320616c7265616479206163746976656c796064820152690819195b1959d85d195960b21b608482015260a401610abc565b610e923384612ddd565b604080518082019091526060815260006020820152610eb43380836000612fd0565b336001600160a01b03167f8e8485583a2310d41f7c82b9427d0bd49bad74bb9cff9d3402a29d8f9b28a0e285604051610eed91906153df565b60405180910390a2336001600160a01b03167f02a919ed0e2acad1dd90f17ef2fa4ae5462ee1339170034a8531cca4b67080908484604051610f30929190615431565b60405180910390a250505050565b606560009054906101000a90046001600160a01b03166001600160a01b031663eab66d7a6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610f91573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fb59190615460565b6001600160a01b0316336001600160a01b031614610fe55760405162461bcd60e51b8152600401610abc9061547d565b610fee81613266565b50565b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614806110505750336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016145b61106c5760405162461bcd60e51b8152600401610abc906154c7565b6110758361155a565b156110a3576001600160a01b038084166000908152609a6020526040902054166110a18185858561335d565b505b505050565b60655460405163237dfb4760e11b81523360048201526001600160a01b03909116906346fbf68e90602401602060405180830381865afa1580156110f0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111149190615524565b6111305760405162461bcd60e51b8152600401610abc90615541565b606654818116146111a95760405162461bcd60e51b815260206004820152603860248201527f5061757361626c652e70617573653a20696e76616c696420617474656d70742060448201527f746f20756e70617573652066756e6374696f6e616c69747900000000000000006064820152608401610abc565b606681905560405181815233907fab40a374bc51de372200a8bc981af8c9ecdc08dfdaef0bb6e09f88f3c616ef3d906020015b60405180910390a250565b6111ef6133d8565b6110a184848484613432565b6001600160a01b0383166000908152609b602052604081205461122085828686611b2a565b95945050505050565b600054610100900460ff16158080156112495750600054600160ff909116105b806112635750303b158015611263575060005460ff166001145b6112c65760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608401610abc565b6000805460ff1916600117905580156112e9576000805461ff0019166101001790555b6112f38888613658565b6112fb613742565b609755611307896137d9565b6113108661382b565b61131c85858585613432565b8015611362576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050505050505050565b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614806113cc5750336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016145b6113e85760405162461bcd60e51b8152600401610abc906154c7565b6113f18361155a565b156110a3576001600160a01b038084166000908152609a6020526040902054166110a181858585613925565b606654600290600490811614156114465760405162461bcd60e51b8152600401610abc9061533f565b600260c95414156114995760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610abc565b600260c95560005b88811015611549576115398a8a838181106114be576114be6152f8565b90506020028101906114d09190615589565b8989848181106114e2576114e26152f8565b90506020028101906114f49190615396565b898986818110611506576115066152f8565b9050602002013588888781811061151f5761151f6152f8565b9050602002016020810190611534919061559f565b6139a0565b61154281615324565b90506114a1565b5050600160c9555050505050505050565b6001600160a01b039081166000908152609a602052604090205416151590565b60655460405163237dfb4760e11b81523360048201526001600160a01b03909116906346fbf68e90602401602060405180830381865afa1580156115c2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115e69190615524565b6116025760405162461bcd60e51b8152600401610abc90615541565b600019606681905560405190815233907fab40a374bc51de372200a8bc981af8c9ecdc08dfdaef0bb6e09f88f3c616ef3d9060200160405180910390a2565b6000816040516020016116549190615630565b604051602081830303815290604052805190602001209050919050565b6066546002906004908116141561169a5760405162461bcd60e51b8152600401610abc9061533f565b600260c95414156116ed5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610abc565b600260c9556116ff86868686866139a0565b5050600160c95550505050565b6117146133d8565b610fee8161382b565b6001600160a01b039081166000818152609a60205260409020549091161490565b6117466133d8565b61175060006137d9565b565b42836020015110156117d65760405162461bcd60e51b815260206004820152604160248201527f44656c65676174696f6e4d616e616765722e64656c6567617465546f4279536960448201527f676e61747572653a207374616b6572207369676e6174757265206578706972656064820152601960fa1b608482015260a401610abc565b6117df8561155a565b156118685760405162461bcd60e51b815260206004820152604d60248201527f44656c65676174696f6e4d616e616765722e64656c6567617465546f4279536960448201527f676e61747572653a207374616b657220697320616c726561647920616374697660648201526c195b1e4819195b1959d85d1959609a1b608482015260a401610abc565b6118718461171d565b6118fd5760405162461bcd60e51b815260206004820152605160248201527f44656c65676174696f6e4d616e616765722e64656c6567617465546f4279536960448201527f676e61747572653a206f70657261746f72206973206e6f7420726567697374656064820152703932b21034b71022b4b3b2b72630bcb2b960791b608482015260a401610abc565b6000609b6000876001600160a01b03166001600160a01b0316815260200190815260200160002054905060006119398783888860200151611b2a565b6001600160a01b0388166000908152609b602052604090206001840190558551909150611969908890839061418a565b61197587878686612fd0565b50505050505050565b6060600082516001600160401b0381111561199b5761199b614c18565b6040519080825280602002602001820160405280156119c4578160200160208202803683370190505b50905060005b83518110156109c6576001600160a01b03851660009081526098602052604081208551909190869084908110611a0257611a026152f8565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002054828281518110611a3d57611a3d6152f8565b6020908102919091010152611a5181615324565b90506119ca565b611a613361171d565b611ae35760405162461bcd60e51b815260206004820152604760248201527f44656c65676174696f6e4d616e616765722e7570646174654f70657261746f7260448201527f4d657461646174615552493a2063616c6c6572206d75737420626520616e206f6064820152663832b930ba37b960c91b608482015260a401610abc565b336001600160a01b03167f02a919ed0e2acad1dd90f17ef2fa4ae5462ee1339170034a8531cca4b67080908383604051611b1e929190615431565b60405180910390a25050565b604080517f39111bc4a4d688e1f685123d7497d4615370152a8ee4a0593e647bd06ad8bb0b6020808301919091526001600160a01b0387811683850152851660608301526080820186905260a08083018590528351808403909101815260c0909201909252805191012060009081611ba0612683565b60405161190160f01b602082015260228101919091526042810183905260620160408051808303601f190181529190528051602090910120979650505050505050565b6040516360f4062b60e01b81526001600160a01b03828116600483015260609182916000917f0000000000000000000000000000000000000000000000000000000000000000909116906360f4062b90602401602060405180830381865afa158015611c53573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c779190615643565b6040516394f649dd60e01b81526001600160a01b03868116600483015291925060009182917f0000000000000000000000000000000000000000000000000000000000000000909116906394f649dd90602401600060405180830381865afa158015611ce7573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052611d0f91908101906156b7565b9150915060008313611d2657909590945092505050565b606080835160001415611de0576040805160018082528183019092529060208083019080368337505060408051600180825281830190925292945090506020808301908036833701905050905073beac0eeeeeeeeeeeeeeeeeeeeeeeeeeeeeebeac082600081518110611d9b57611d9b6152f8565b60200260200101906001600160a01b031690816001600160a01b0316815250508481600081518110611dcf57611dcf6152f8565b602002602001018181525050611f8e565b8351611ded906001615771565b6001600160401b03811115611e0457611e04614c18565b604051908082528060200260200182016040528015611e2d578160200160208202803683370190505b50915081516001600160401b03811115611e4957611e49614c18565b604051908082528060200260200182016040528015611e72578160200160208202803683370190505b50905060005b8451811015611f0c57848181518110611e9357611e936152f8565b6020026020010151838281518110611ead57611ead6152f8565b60200260200101906001600160a01b031690816001600160a01b031681525050838181518110611edf57611edf6152f8565b6020026020010151828281518110611ef957611ef96152f8565b6020908102919091010152600101611e78565b5073beac0eeeeeeeeeeeeeeeeeeeeeeeeeeeeeebeac08260018451611f319190615789565b81518110611f4157611f416152f8565b60200260200101906001600160a01b031690816001600160a01b031681525050848160018451611f719190615789565b81518110611f8157611f816152f8565b6020026020010181815250505b9097909650945050505050565b60665460609060019060029081161415611fc75760405162461bcd60e51b8152600401610abc9061533f565b611fd08361155a565b6120505760405162461bcd60e51b8152602060048201526044602482018190527f44656c65676174696f6e4d616e616765722e756e64656c65676174653a207374908201527f616b6572206d7573742062652064656c65676174656420746f20756e64656c656064820152636761746560e01b608482015260a401610abc565b6120598361171d565b156120cc5760405162461bcd60e51b815260206004820152603d60248201527f44656c65676174696f6e4d616e616765722e756e64656c65676174653a206f7060448201527f657261746f72732063616e6e6f7420626520756e64656c6567617465640000006064820152608401610abc565b6001600160a01b0383166121485760405162461bcd60e51b815260206004820152603c60248201527f44656c65676174696f6e4d616e616765722e756e64656c65676174653a20636160448201527f6e6e6f7420756e64656c6567617465207a65726f2061646472657373000000006064820152608401610abc565b6001600160a01b038084166000818152609a60205260409020549091169033148061217b5750336001600160a01b038216145b806121a257506001600160a01b038181166000908152609960205260409020600101541633145b6122145760405162461bcd60e51b815260206004820152603d60248201527f44656c65676174696f6e4d616e616765722e756e64656c65676174653a20636160448201527f6c6c65722063616e6e6f7420756e64656c6567617465207374616b65720000006064820152608401610abc565b60008061222086611be3565b9092509050336001600160a01b0387161461227657826001600160a01b0316866001600160a01b03167ff0eddf07e6ea14f388b47e1e94a0f464ecbd9eed4171130e0fc0e99fb4030a8a60405160405180910390a35b826001600160a01b0316866001600160a01b03167ffee30966a256b71e14bc0ebfc94315e28ef4a97a7131a9e2b7a310a73af4467660405160405180910390a36001600160a01b0386166000908152609a6020526040902080546001600160a01b031916905581516122f8576040805160008152602081019091529450612456565b81516001600160401b0381111561231157612311614c18565b60405190808252806020026020018201604052801561233a578160200160208202803683370190505b50945060005b8251811015612454576040805160018082528183019092526000916020808301908036833750506040805160018082528183019092529293506000929150602080830190803683370190505090508483815181106123a0576123a06152f8565b6020026020010151826000815181106123bb576123bb6152f8565b60200260200101906001600160a01b031690816001600160a01b0316815250508383815181106123ed576123ed6152f8565b602002602001015181600081518110612408576124086152f8565b60200260200101818152505061242189878b858561281d565b888481518110612433576124336152f8565b6020026020010181815250505050808061244c90615324565b915050612340565b505b50505050919050565b6124683361155a565b156124e65760405162461bcd60e51b815260206004820152604260248201527f44656c65676174696f6e4d616e616765722e64656c6567617465546f3a20737460448201527f616b657220697320616c7265616479206163746976656c792064656c65676174606482015261195960f21b608482015260a401610abc565b6124ef8361171d565b6125705760405162461bcd60e51b815260206004820152604660248201527f44656c65676174696f6e4d616e616765722e64656c6567617465546f3a206f7060448201527f657261746f72206973206e6f74207265676973746572656420696e2045696765606482015265372630bcb2b960d11b608482015260a401610abc565b6110a333848484612fd0565b6125853361171d565b6126035760405162461bcd60e51b815260206004820152604360248201527f44656c65676174696f6e4d616e616765722e6d6f646966794f70657261746f7260448201527f44657461696c733a2063616c6c6572206d75737420626520616e206f706572616064820152623a37b960e91b608482015260a401610abc565b610fee3382612ddd565b6126156133d8565b6001600160a01b03811661267a5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610abc565b610fee816137d9565b60007f00000000000000000000000000000000000000000000000000000000000000004614156126b4575060975490565b6126bc613742565b905090565b606560009054906101000a90046001600160a01b03166001600160a01b031663eab66d7a6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612714573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127389190615460565b6001600160a01b0316336001600160a01b0316146127685760405162461bcd60e51b8152600401610abc9061547d565b6066541981196066541916146127e65760405162461bcd60e51b815260206004820152603860248201527f5061757361626c652e756e70617573653a20696e76616c696420617474656d7060448201527f7420746f2070617573652066756e6374696f6e616c69747900000000000000006064820152608401610abc565b606681905560405181815233907f3582d1828e26bf56bd801502bc021ac0bc8afb57c826e4986b45593c8fad389c906020016111dc565b60006001600160a01b0386166128b45760405162461bcd60e51b815260206004820152605060248201527f44656c65676174696f6e4d616e616765722e5f72656d6f76655368617265734160448201527f6e6451756575655769746864726177616c3a207374616b65722063616e6e6f7460648201526f206265207a65726f206164647265737360801b608482015260a401610abc565b825161293e5760405162461bcd60e51b815260206004820152604d60248201527f44656c65676174696f6e4d616e616765722e5f72656d6f76655368617265734160448201527f6e6451756575655769746864726177616c3a207374726174656769657320636160648201526c6e6e6f7420626520656d70747960981b608482015260a401610abc565b60005b8351811015612ceb576001600160a01b03861615612997576129978688868481518110612970576129706152f8565b602002602001015186858151811061298a5761298a6152f8565b602002602001015161335d565b73beac0eeeeeeeeeeeeeeeeeeeeeeeeeeeeeebeac06001600160a01b03168482815181106129c7576129c76152f8565b60200260200101516001600160a01b03161415612a90577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663beffbb8988858481518110612a2057612a206152f8565b60200260200101516040518363ffffffff1660e01b8152600401612a599291906001600160a01b03929092168252602082015260400190565b600060405180830381600087803b158015612a7357600080fd5b505af1158015612a87573d6000803e3d6000fd5b50505050612ce3565b846001600160a01b0316876001600160a01b03161480612b6257507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316639b4da03d858381518110612aec57612aec6152f8565b60200260200101516040518263ffffffff1660e01b8152600401612b1f91906001600160a01b0391909116815260200190565b602060405180830381865afa158015612b3c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b609190615524565b155b612c2e5760405162461bcd60e51b8152602060048201526084602482018190527f44656c65676174696f6e4d616e616765722e5f72656d6f76655368617265734160448301527f6e6451756575655769746864726177616c3a2077697468647261776572206d7560648301527f73742062652073616d652061646472657373206173207374616b657220696620908201527f746869726450617274795472616e7366657273466f7262696464656e2061726560a482015263081cd95d60e21b60c482015260e401610abc565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316638c80d4e588868481518110612c7057612c706152f8565b6020026020010151868581518110612c8a57612c8a6152f8565b60200260200101516040518463ffffffff1660e01b8152600401612cb0939291906157a0565b600060405180830381600087803b158015612cca57600080fd5b505af1158015612cde573d6000803e3d6000fd5b505050505b600101612941565b506001600160a01b0386166000908152609f60205260408120805491829190612d1383615324565b919050555060006040518060e00160405280896001600160a01b03168152602001886001600160a01b03168152602001876001600160a01b031681526020018381526020014363ffffffff1681526020018681526020018581525090506000612d7b82611641565b6000818152609e602052604090819020805460ff19166001179055519091507f9009ab153e8014fbfb02f2217f5cde7aa7f9ad734ae85ca3ee3f4ca2fdd499f990612dc990839085906157c4565b60405180910390a198975050505050505050565b6213c680612df160608301604084016157dd565b63ffffffff161115612ea65760405162461bcd60e51b815260206004820152606c60248201527f44656c65676174696f6e4d616e616765722e5f7365744f70657261746f72446560448201527f7461696c733a207374616b65724f70744f757457696e646f77426c6f636b732060648201527f63616e6e6f74206265203e204d41585f5354414b45525f4f50545f4f55545f5760848201526b494e444f575f424c4f434b5360a01b60a482015260c401610abc565b6001600160a01b0382166000908152609960205260409081902060010154600160a01b900463ffffffff1690612ee290606084019084016157dd565b63ffffffff161015612f785760405162461bcd60e51b815260206004820152605360248201527f44656c65676174696f6e4d616e616765722e5f7365744f70657261746f72446560448201527f7461696c733a207374616b65724f70744f757457696e646f77426c6f636b732060648201527218d85b9b9bdd08189948191958dc99585cd959606a1b608482015260a401610abc565b6001600160a01b03821660009081526099602052604090208190612f9c828261581a565b505060405133907ffebe5cd24b2cbc7b065b9d0fdeb904461e4afcff57dd57acda1e7832031ba7ac90611b1e9084906153df565b60665460009060019081161415612ff95760405162461bcd60e51b8152600401610abc9061533f565b6001600160a01b0380851660009081526099602052604090206001015416801580159061302f5750336001600160a01b03821614155b80156130445750336001600160a01b03861614155b156131b15742846020015110156130c35760405162461bcd60e51b815260206004820152603760248201527f44656c65676174696f6e4d616e616765722e5f64656c65676174653a2061707060448201527f726f766572207369676e617475726520657870697265640000000000000000006064820152608401610abc565b6001600160a01b0381166000908152609c6020908152604080832086845290915290205460ff161561315d5760405162461bcd60e51b815260206004820152603760248201527f44656c65676174696f6e4d616e616765722e5f64656c65676174653a2061707060448201527f726f76657253616c7420616c7265616479207370656e740000000000000000006064820152608401610abc565b6001600160a01b0381166000908152609c6020908152604080832086845282528220805460ff1916600117905585015161319e9088908890859088906109ce565b90506131af8282876000015161418a565b505b6001600160a01b038681166000818152609a602052604080822080546001600160a01b031916948a169485179055517fc3ee9f2e5fda98e8066a1f745b2df9285f416fe98cf2559cd21484b3d87433049190a360008061321088611be3565b9150915060005b82518110156113625761325e888a858481518110613237576132376152f8565b6020026020010151858581518110613251576132516152f8565b6020026020010151613925565b600101613217565b6001600160a01b0381166132f45760405162461bcd60e51b815260206004820152604960248201527f5061757361626c652e5f73657450617573657252656769737472793a206e657760448201527f50617573657252656769737472792063616e6e6f7420626520746865207a65726064820152686f206164647265737360b81b608482015260a401610abc565b606554604080516001600160a01b03928316815291831660208301527f6e9fcd539896fca60e8b0f01dd580233e48a6b0f7df013b89ba7f565869acdb6910160405180910390a1606580546001600160a01b0319166001600160a01b0392909216919091179055565b6001600160a01b03808516600090815260986020908152604080832093861683529290529081208054839290613394908490615789565b92505081905550836001600160a01b03167f6909600037b75d7b4733aedd815442b5ec018a827751c832aaff64eba5d6d2dd848484604051610f30939291906157a0565b6033546001600160a01b031633146117505760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610abc565b8281146134ba5760405162461bcd60e51b815260206004820152604a60248201527f44656c65676174696f6e4d616e616765722e5f7365745374726174656779576960448201527f746864726177616c44656c6179426c6f636b733a20696e707574206c656e67746064820152690d040dad2e6dac2e8c6d60b31b608482015260a401610abc565b8260005b818110156136505760008686838181106134da576134da6152f8565b90506020020160208101906134ef91906149e6565b6001600160a01b038116600090815260a1602052604081205491925086868581811061351d5761351d6152f8565b90506020020135905062034bc08111156135e15760405162461bcd60e51b815260206004820152607360248201527f44656c65676174696f6e4d616e616765722e5f7365745374726174656779576960448201527f746864726177616c44656c6179426c6f636b733a205f7769746864726177616c60648201527f44656c6179426c6f636b732063616e6e6f74206265203e204d41585f5749544860848201527244524157414c5f44454c41595f424c4f434b5360681b60a482015260c401610abc565b6001600160a01b038316600081815260a160209081526040918290208490558151928352820184905281018290527f0e7efa738e8b0ce6376a0c1af471655540d2e9a81647d7b09ed823018426576d9060600160405180910390a15050508061364990615324565b90506134be565b505050505050565b6065546001600160a01b031615801561367957506001600160a01b03821615155b6136fb5760405162461bcd60e51b815260206004820152604760248201527f5061757361626c652e5f696e697469616c697a655061757365723a205f696e6960448201527f7469616c697a6550617573657228292063616e206f6e6c792062652063616c6c6064820152666564206f6e636560c81b608482015260a401610abc565b606681905560405181815233907fab40a374bc51de372200a8bc981af8c9ecdc08dfdaef0bb6e09f88f3c616ef3d9060200160405180910390a261373e82613266565b5050565b604080518082018252600a81526922b4b3b2b72630bcb2b960b11b60209182015281517f8cad95687ba82c2ce50e74f7b754645e5117c3a5bec8151c0726d5857980a866818301527f71b625cfad44bac63b13dba07f2e1d6084ee04b6f8752101ece6126d584ee6ea81840152466060820152306080808301919091528351808303909101815260a0909101909252815191012090565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b62034bc08111156138e45760405162461bcd60e51b815260206004820152607160248201527f44656c65676174696f6e4d616e616765722e5f7365744d696e5769746864726160448201527f77616c44656c6179426c6f636b733a205f6d696e5769746864726177616c446560648201527f6c6179426c6f636b732063616e6e6f74206265203e204d41585f5749544844526084820152704157414c5f44454c41595f424c4f434b5360781b60a482015260c401610abc565b609d5460408051918252602082018390527fafa003cd76f87ff9d62b35beea889920f33c0c42b8d45b74954d61d50f4b6b69910160405180910390a1609d55565b6001600160a01b0380851660009081526098602090815260408083209386168352929052908120805483929061395c908490615771565b92505081905550836001600160a01b03167f1ec042c965e2edd7107b51188ee0f383e22e76179041ab3a9d18ff151405166c848484604051610f30939291906157a0565b60006139ae6105f38761587d565b6000818152609e602052604090205490915060ff16613a2f5760405162461bcd60e51b815260206004820152604360248201526000805160206159b583398151915260448201527f645769746864726177616c3a20616374696f6e206973206e6f7420696e20717560648201526265756560e81b608482015260a401610abc565b609d544390613a4460a0890160808a016157dd565b63ffffffff16613a549190615771565b1115613adc5760405162461bcd60e51b815260206004820152605f60248201526000805160206159b583398151915260448201527f645769746864726177616c3a206d696e5769746864726177616c44656c61794260648201527f6c6f636b7320706572696f6420686173206e6f74207965742070617373656400608482015260a401610abc565b613aec60608701604088016149e6565b6001600160a01b0316336001600160a01b031614613b795760405162461bcd60e51b815260206004820152605060248201526000805160206159b583398151915260448201527f645769746864726177616c3a206f6e6c7920776974686472617765722063616e60648201526f1031b7b6b83632ba329030b1ba34b7b760811b608482015260a401610abc565b8115613bfb57613b8c60a0870187615396565b85149050613bfb5760405162461bcd60e51b815260206004820152604260248201526000805160206159b583398151915260448201527f645769746864726177616c3a20696e707574206c656e677468206d69736d61746064820152610c6d60f31b608482015260a401610abc565b6000818152609e60205260409020805460ff191690558115613d605760005b613c2760a0880188615396565b9050811015613d5a574360a16000613c4260a08b018b615396565b85818110613c5257613c526152f8565b9050602002016020810190613c6791906149e6565b6001600160a01b03168152602081019190915260400160002054613c9160a08a0160808b016157dd565b63ffffffff16613ca19190615771565b1115613cbf5760405162461bcd60e51b8152600401610abc9061588f565b613d52613ccf60208901896149e6565b33613cdd60a08b018b615396565b85818110613ced57613ced6152f8565b9050602002016020810190613d0291906149e6565b613d0f60c08c018c615396565b86818110613d1f57613d1f6152f8565b905060200201358a8a87818110613d3857613d386152f8565b9050602002016020810190613d4d91906149e6565b614344565b600101613c1a565b5061414f565b336000908152609a60205260408120546001600160a01b0316905b613d8860a0890189615396565b905081101561414c574360a16000613da360a08c018c615396565b85818110613db357613db36152f8565b9050602002016020810190613dc891906149e6565b6001600160a01b03168152602081019190915260400160002054613df260a08b0160808c016157dd565b63ffffffff16613e029190615771565b1115613e205760405162461bcd60e51b8152600401610abc9061588f565b73beac0eeeeeeeeeeeeeeeeeeeeeeeeeeeeeebeac0613e4260a08a018a615396565b83818110613e5257613e526152f8565b9050602002016020810190613e6791906149e6565b6001600160a01b03161415613fb7576000613e8560208a018a6149e6565b905060006001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016630e81073c83613ec660c08e018e615396565b87818110613ed657613ed66152f8565b6040516001600160e01b031960e087901b1681526001600160a01b03909416600485015260200291909101356024830152506044016020604051808303816000875af1158015613f2a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613f4e9190615643565b6001600160a01b038084166000908152609a6020526040902054919250168015613faf57613faf8184613f8460a08f018f615396565b88818110613f9457613f946152f8565b9050602002016020810190613fa991906149e6565b85613925565b505050614144565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663c4623ea133898985818110613ff957613ff96152f8565b905060200201602081019061400e91906149e6565b61401b60a08d018d615396565b8681811061402b5761402b6152f8565b905060200201602081019061404091906149e6565b61404d60c08e018e615396565b8781811061405d5761405d6152f8565b60405160e088901b6001600160e01b03191681526001600160a01b03968716600482015294861660248601529290941660448401526020909102013560648201526084019050600060405180830381600087803b1580156140bd57600080fd5b505af11580156140d1573d6000803e3d6000fd5b505050506001600160a01b038216156141445761414482336140f660a08c018c615396565b85818110614106576141066152f8565b905060200201602081019061411b91906149e6565b61412860c08d018d615396565b86818110614138576141386152f8565b90506020020135613925565b600101613d7b565b50505b6040518181527fc97098c2f658800b4df29001527f7324bcdffcf6e8751a699ab920a1eced5b1d9060200160405180910390a1505050505050565b6001600160a01b0383163b156142a457604051630b135d3f60e11b808252906001600160a01b03851690631626ba7e906141ca9086908690600401615917565b602060405180830381865afa1580156141e7573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061420b9190615974565b6001600160e01b031916146110a35760405162461bcd60e51b815260206004820152605360248201527f454950313237315369676e61747572655574696c732e636865636b5369676e6160448201527f747572655f454950313237313a2045524331323731207369676e6174757265206064820152721d995c9a599a58d85d1a5bdb8819985a5b1959606a1b608482015260a401610abc565b826001600160a01b03166142b88383614484565b6001600160a01b0316146110a35760405162461bcd60e51b815260206004820152604760248201527f454950313237315369676e61747572655574696c732e636865636b5369676e6160448201527f747572655f454950313237313a207369676e6174757265206e6f742066726f6d6064820152661039b4b3b732b960c91b608482015260a401610abc565b6001600160a01b03831673beac0eeeeeeeeeeeeeeeeeeeeeeeeeeeeeebeac014156143ef5760405162387b1360e81b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063387b1300906143b8908890889087906004016157a0565b600060405180830381600087803b1580156143d257600080fd5b505af11580156143e6573d6000803e3d6000fd5b5050505061447d565b60405163c608c7f360e01b81526001600160a01b03858116600483015284811660248301526044820184905282811660648301527f0000000000000000000000000000000000000000000000000000000000000000169063c608c7f390608401600060405180830381600087803b15801561446957600080fd5b505af1158015611362573d6000803e3d6000fd5b5050505050565b600080600061449385856144a0565b915091506109c681614510565b6000808251604114156144d75760208301516040840151606085015160001a6144cb878285856146cb565b94509450505050614509565b82516040141561450157602083015160408401516144f68683836147b8565b935093505050614509565b506000905060025b9250929050565b60008160048111156145245761452461599e565b141561452d5750565b60018160048111156145415761454161599e565b141561458f5760405162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e617475726500000000000000006044820152606401610abc565b60028160048111156145a3576145a361599e565b14156145f15760405162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e677468006044820152606401610abc565b60038160048111156146055761460561599e565b141561465e5760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c604482015261756560f01b6064820152608401610abc565b60048160048111156146725761467261599e565b1415610fee5760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202776272076616c604482015261756560f01b6064820152608401610abc565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a083111561470257506000905060036147af565b8460ff16601b1415801561471a57508460ff16601c14155b1561472b57506000905060046147af565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa15801561477f573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b0381166147a8576000600192509250506147af565b9150600090505b94509492505050565b6000806001600160ff1b038316816147d560ff86901c601b615771565b90506147e3878288856146cb565b935093505050935093915050565b60008083601f84011261480357600080fd5b5081356001600160401b0381111561481a57600080fd5b6020830191508360208260051b850101111561450957600080fd5b6000806020838503121561484857600080fd5b82356001600160401b0381111561485e57600080fd5b61486a858286016147f1565b90969095509350505050565b6001600160a01b0381168114610fee57600080fd5b803561489681614876565b919050565b600080600080600060a086880312156148b357600080fd5b85356148be81614876565b945060208601356148ce81614876565b935060408601356148de81614876565b94979396509394606081013594506080013592915050565b6020808252825182820181905260009190848201906040850190845b8181101561492e57835183529284019291840191600101614912565b50909695505050505050565b60006060828403121561494c57600080fd5b50919050565b60008083601f84011261496457600080fd5b5081356001600160401b0381111561497b57600080fd5b60208301915083602082850101111561450957600080fd5b6000806000608084860312156149a857600080fd5b6149b2858561493a565b925060608401356001600160401b038111156149cd57600080fd5b6149d986828701614952565b9497909650939450505050565b6000602082840312156149f857600080fd5b8135614a0381614876565b9392505050565b600080600060608486031215614a1f57600080fd5b8335614a2a81614876565b92506020840135614a3a81614876565b929592945050506040919091013590565b600060208284031215614a5d57600080fd5b5035919050565b60008060008060408587031215614a7a57600080fd5b84356001600160401b0380821115614a9157600080fd5b614a9d888389016147f1565b90965094506020870135915080821115614ab657600080fd5b50614ac3878288016147f1565b95989497509550505050565b60008060008060008060008060c0898b031215614aeb57600080fd5b8835614af681614876565b97506020890135614b0681614876565b9650604089013595506060890135945060808901356001600160401b0380821115614b3057600080fd5b614b3c8c838d016147f1565b909650945060a08b0135915080821115614b5557600080fd5b50614b628b828c016147f1565b999c989b5096995094979396929594505050565b6000806000806000806000806080898b031215614b9257600080fd5b88356001600160401b0380821115614ba957600080fd5b614bb58c838d016147f1565b909a50985060208b0135915080821115614bce57600080fd5b614bda8c838d016147f1565b909850965060408b0135915080821115614bf357600080fd5b614bff8c838d016147f1565b909650945060608b0135915080821115614b5557600080fd5b634e487b7160e01b600052604160045260246000fd5b60405160e081016001600160401b0381118282101715614c5057614c50614c18565b60405290565b604080519081016001600160401b0381118282101715614c5057614c50614c18565b604051601f8201601f191681016001600160401b0381118282101715614ca057614ca0614c18565b604052919050565b63ffffffff81168114610fee57600080fd5b803561489681614ca8565b60006001600160401b03821115614cde57614cde614c18565b5060051b60200190565b600082601f830112614cf957600080fd5b81356020614d0e614d0983614cc5565b614c78565b82815260059290921b84018101918181019086841115614d2d57600080fd5b8286015b84811015614d51578035614d4481614876565b8352918301918301614d31565b509695505050505050565b600082601f830112614d6d57600080fd5b81356020614d7d614d0983614cc5565b82815260059290921b84018101918181019086841115614d9c57600080fd5b8286015b84811015614d515780358352918301918301614da0565b600060e08284031215614dc957600080fd5b614dd1614c2e565b9050614ddc8261488b565b8152614dea6020830161488b565b6020820152614dfb6040830161488b565b604082015260608201356060820152614e1660808301614cba565b608082015260a08201356001600160401b0380821115614e3557600080fd5b614e4185838601614ce8565b60a084015260c0840135915080821115614e5a57600080fd5b50614e6784828501614d5c565b60c08301525092915050565b600060208284031215614e8557600080fd5b81356001600160401b03811115614e9b57600080fd5b614ea784828501614db7565b949350505050565b600060208284031215614ec157600080fd5b813560ff81168114614a0357600080fd5b8015158114610fee57600080fd5b600080600080600060808688031215614ef857600080fd5b85356001600160401b0380821115614f0f57600080fd5b9087019060e0828a031215614f2357600080fd5b90955060208701359080821115614f3957600080fd5b50614f46888289016147f1565b909550935050604086013591506060860135614f6181614ed2565b809150509295509295909350565b60008060408385031215614f8257600080fd5b8235614f8d81614876565b91506020830135614f9d81614876565b809150509250929050565b600060408284031215614fba57600080fd5b614fc2614c56565b905081356001600160401b0380821115614fdb57600080fd5b818401915084601f830112614fef57600080fd5b813560208282111561500357615003614c18565b615015601f8301601f19168201614c78565b9250818352868183860101111561502b57600080fd5b8181850182850137600081838501015282855280860135818601525050505092915050565b600080600080600060a0868803121561506857600080fd5b853561507381614876565b9450602086013561508381614876565b935060408601356001600160401b038082111561509f57600080fd5b6150ab89838a01614fa8565b945060608801359150808211156150c157600080fd5b506150ce88828901614fa8565b95989497509295608001359392505050565b600080604083850312156150f357600080fd5b82356150fe81614876565b915060208301356001600160401b0381111561511957600080fd5b61512585828601614ce8565b9150509250929050565b600081518084526020808501945080840160005b8381101561515f57815187529582019590820190600101615143565b509495945050505050565b602081526000614a03602083018461512f565b6000806020838503121561519057600080fd5b82356001600160401b038111156151a657600080fd5b61486a85828601614952565b600080604083850312156151c557600080fd5b82356151d081614876565b946020939093013593505050565b600080600080608085870312156151f457600080fd5b84356151ff81614876565b935060208501359250604085013561521681614876565b9396929550929360600135925050565b600081518084526020808501945080840160005b8381101561515f5781516001600160a01b03168752958201959082019060010161523a565b6040815260006152726040830185615226565b8281036020840152611220818561512f565b60008060006060848603121561529957600080fd5b83356152a481614876565b925060208401356001600160401b038111156152bf57600080fd5b6152cb86828701614fa8565b925050604084013590509250925092565b6000606082840312156152ee57600080fd5b614a03838361493a565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b60006000198214156153385761533861530e565b5060010190565b60208082526019908201527f5061757361626c653a20696e6465782069732070617573656400000000000000604082015260600190565b60008235605e1983360301811261538c57600080fd5b9190910192915050565b6000808335601e198436030181126153ad57600080fd5b8301803591506001600160401b038211156153c757600080fd5b6020019150600581901b360382131561450957600080fd5b6060810182356153ee81614876565b6001600160a01b03908116835260208401359061540a82614876565b166020830152604083013561541e81614ca8565b63ffffffff811660408401525092915050565b60208152816020820152818360408301376000818301604090810191909152601f909201601f19160101919050565b60006020828403121561547257600080fd5b8151614a0381614876565b6020808252602a908201527f6d73672e73656e646572206973206e6f74207065726d697373696f6e6564206160408201526939903ab73830bab9b2b960b11b606082015260800190565b60208082526037908201527f44656c65676174696f6e4d616e616765723a206f6e6c7953747261746567794d60408201527f616e616765724f72456967656e506f644d616e61676572000000000000000000606082015260800190565b60006020828403121561553657600080fd5b8151614a0381614ed2565b60208082526028908201527f6d73672e73656e646572206973206e6f74207065726d697373696f6e6564206160408201526739903830bab9b2b960c11b606082015260800190565b6000823560de1983360301811261538c57600080fd5b6000602082840312156155b157600080fd5b8135614a0381614ed2565b600060018060a01b03808351168452806020840151166020850152806040840151166040850152506060820151606084015263ffffffff608083015116608084015260a082015160e060a085015261561760e0850182615226565b905060c083015184820360c0860152611220828261512f565b602081526000614a0360208301846155bc565b60006020828403121561565557600080fd5b5051919050565b600082601f83011261566d57600080fd5b8151602061567d614d0983614cc5565b82815260059290921b8401810191818101908684111561569c57600080fd5b8286015b84811015614d5157805183529183019183016156a0565b600080604083850312156156ca57600080fd5b82516001600160401b03808211156156e157600080fd5b818501915085601f8301126156f557600080fd5b81516020615705614d0983614cc5565b82815260059290921b8401810191818101908984111561572457600080fd5b948201945b8386101561574b57855161573c81614876565b82529482019490820190615729565b9188015191965090935050508082111561576457600080fd5b506151258582860161565c565b600082198211156157845761578461530e565b500190565b60008282101561579b5761579b61530e565b500390565b6001600160a01b039384168152919092166020820152604081019190915260600190565b828152604060208201526000614ea760408301846155bc565b6000602082840312156157ef57600080fd5b8135614a0381614ca8565b80546001600160a01b0319166001600160a01b0392909216919091179055565b813561582581614876565b61582f81836157fa565b5060018101602083013561584281614876565b61584c81836157fa565b50604083013561585b81614ca8565b815463ffffffff60a01b191660a09190911b63ffffffff60a01b161790555050565b60006158893683614db7565b92915050565b6020808252606e908201526000805160206159b583398151915260408201527f645769746864726177616c3a207769746864726177616c44656c6179426c6f6360608201527f6b7320706572696f6420686173206e6f74207965742070617373656420666f7260808201526d207468697320737472617465677960901b60a082015260c00190565b82815260006020604081840152835180604085015260005b8181101561594b5785810183015185820160600152820161592f565b8181111561595d576000606083870101525b50601f01601f191692909201606001949350505050565b60006020828403121561598657600080fd5b81516001600160e01b031981168114614a0357600080fd5b634e487b7160e01b600052602160045260246000fdfe44656c65676174696f6e4d616e616765722e5f636f6d706c6574655175657565a26469706673582212203a9863b190b0abcf799891a42203a11c6933a165f6897ec6ac670f95b48c927b64736f6c634300080c0033","sourceMap":"1137:46343:2:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;43577:472;;;;;;:::i;:::-;;:::i;:::-;;;1014:25:184;;;1002:2;987:18;43577:472:2;;;;;;;;1131:182:3;;1194:119;1131:182;;46547:630:2;;;;;;:::i;:::-;;:::i;14140:1400::-;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;4795:692::-;;;;;;:::i;:::-;;:::i;:::-;;5826:138:29;;;;;;:::i;:::-;;:::i;20110:571:2:-;;;;;;:::i;:::-;;:::i;3832:392:29:-;;;;;;:::i;:::-;;:::i;21527:243:2:-;;;;;;:::i;:::-;;:::i;40642:159::-;;;;;;:::i;:::-;-1:-1:-1;;;;;40743:26:2;40717:7;40743:26;;;:16;:26;;;;;:51;;;-1:-1:-1;;;40743:51:2;;;;;40642:159;44553:408;;;;;;:::i;:::-;;:::i;649:130:3:-;;699:80;649:130;;3318:607:2;;;;;;:::i;:::-;;:::i;19082:486::-;;;;;;:::i;:::-;;:::i;3363:46:3:-;;;;;;:::i;:::-;;;;;;;;;;;;;;18069:471:2;;;;;;:::i;:::-;;:::i;1703:49:3:-;;;;;;;;-1:-1:-1;;;;;9831:32:184;;;9813:51;;9801:2;9786:18;1703:49:3;9642:228:184;40405:147:2;;;;;;:::i;:::-;-1:-1:-1;;;;;40500:26:2;;;40474:7;40500:26;;;:16;:26;;;;;:45;;;;;40405:147;39718:123;;;;;;:::i;:::-;;:::i;:::-;;;10248:14:184;;10241:22;10223:41;;10211:2;10196:18;39718:123:2;10083:187:184;878:152:3;;939:91;878:152;;1911:49;;;;;1885:74:2;;1944:15;1885:74;;4299:136:29;;;:::i;44115:150:2:-;;;;;;:::i;:::-;;:::i;5606:149:29:-;;;;;;:::i;:::-;5724:7;;5695:1;:10;;;;;;;;5724:14;;;5723:24;;5606:149;5418:87;5491:7;;5418:87;;16982:353:2;;;;;;:::i;:::-;;:::i;20889:167::-;;;;;;:::i;:::-;;:::i;3159:46:3:-;;;;;;:::i;:::-;;;;;;;;;;;;-1:-1:-1;;;;;3159:46:3;;;39948:122:2;;;;;;:::i;:::-;;:::i;2071:101:42:-;;;:::i;2612:71:3:-;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;9720:1488:2;;;;;;:::i;:::-;;:::i;1825:37:29:-;;;;;-1:-1:-1;;;;;1825:37:29;;;1441:85:42;1513:6;;-1:-1:-1;;;;;1513:6:42;1441:85;;40891:368:2;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;2027:104::-;;2088:42;2027:104;;6276:262;;;;;;:::i;:::-;;:::i;4904:62:3:-;;;;;;:::i;:::-;;;;;;;;;;;;;;1811:33;;;;;4607:50;;;;;;:::i;:::-;;;;;;;;;;;;;;;;3852:81;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;4451:39;;;;;;5466:66;;;;;;:::i;:::-;;;;;;;;;;;;;;40173:140:2;;;;;;:::i;:::-;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;40280:26:2;;;;;:16;:26;;;;;40273:33;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;40273:33:2;;;;;;;;;;40173:140;;;;;21632:13:184;;-1:-1:-1;;;;;21628:22:184;;;21610:41;;21711:4;21699:17;;;21693:24;21689:33;;;21667:20;;;21660:63;21771:17;;;21765:24;21791:10;21761:41;21739:20;;;21732:71;21560:2;21545:18;40173:140:2;21360:449:184;45391:560:2;;;;;;:::i;:::-;;:::i;2051:60:3:-;;2105:6;2051:60;;41484:1765:2;;;;;;:::i;:::-;;:::i;:::-;;;;;;;;:::i;11533:2250::-;;;;;;:::i;:::-;;:::i;7541:578::-;;;;;;:::i;:::-;;:::i;5791:265::-;;;;;;:::i;:::-;;:::i;2321:198:42:-;;;;;;:::i;:::-;;:::i;39379:227:2:-;;;:::i;4911:437:29:-;;;;;;:::i;:::-;;:::i;43577:472:2:-;43704:24;;43659:7;;;43738:273;43758:21;;;43738:273;;;43800:27;43830:29;:44;43860:10;;43871:1;43860:13;;;;;;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;43830:44:2;-1:-1:-1;;;;;43830:44:2;;;;;;;;;;;;;43800:74;;43914:15;43892:19;:37;43888:113;;;43967:19;43949:37;;43888:113;-1:-1:-1;43781:3:2;;;:::i;:::-;;;43738:273;;;-1:-1:-1;44027:15:2;43577:472;-1:-1:-1;;;43577:472:2:o;46547:630::-;46870:101;;;1194:119:3;46870:101:2;;;;24847:25:184;;;;-1:-1:-1;;;;;24946:15:184;;;24926:18;;;24919:43;24998:15;;;24978:18;;;24971:43;25050:15;;25030:18;;;25023:43;25082:19;;;25075:35;;;25126:19;;;;25119:35;;;46870:101:2;;;;;;;;;;24819:19:184;;;;46870:101:2;;;46847:134;;;;;-1:-1:-1;;;47096:17:2;:15;:17::i;:::-;47067:67;;-1:-1:-1;;;47067:67:2;;;25423:27:184;25466:11;;;25459:27;;;;25502:12;;;25495:28;;;25539:12;;47067:67:2;;;;;;-1:-1:-1;;47067:67:2;;;;;;47057:78;;47067:67;47057:78;;;;;46547:630;-1:-1:-1;;;;;;;;46547:630:2:o;14140:1400::-;5724:7:29;;14305:16:2;;1520:1;;5695:10:29;5724:14;;;5723:24;2767:14;2759:52;;;;-1:-1:-1;;;2759:52:29;;;;;;;:::i;:::-;;;;;;;;;14333:32:2::1;14382:22:::0;-1:-1:-1;;;;;14368:44:2;::::1;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;-1:-1:-1;14368:44:2::1;-1:-1:-1::0;14453:10:2::1;14422:16;14441:23:::0;;;:11:::1;:23;::::0;;;;;14333:79;;-1:-1:-1;;;;;;14441:23:2;;::::1;::::0;14475:1027:::1;14495:33:::0;;::::1;14475:1027;;;14604:22;;14627:1;14604:25;;;;;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;:32;::::0;::::1;::::0;::::1;::::0;::::1;:::i;:::-;:39;;14557:22;;14580:1;14557:25;;;;;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;:36;::::0;;::::1;:::i;:::-;:43;;:86;14549:155;;;::::0;-1:-1:-1;;;14549:155:2;;27580:2:184;14549:155:2::1;::::0;::::1;27562:21:184::0;27619:2;27599:18;;;27592:30;27658:34;27638:18;;;27631:62;27729:26;27709:18;;;27702:54;27773:19;;14549:155:2::1;27378:420:184::0;14549:155:2::1;14766:10;14726:22:::0;;14749:1;14726:25;;::::1;;;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;:36;::::0;;;;;::::1;;;:::i;:::-;-1:-1:-1::0;;;;;14726:50:2::1;;14718:123;;;::::0;-1:-1:-1;;;14718:123:2;;28005:2:184;14718:123:2::1;::::0;::::1;27987:21:184::0;28044:2;28024:18;;;28017:30;28083:34;28063:18;;;28056:62;28154:30;28134:18;;;28127:58;28202:19;;14718:123:2::1;27803:424:184::0;14718:123:2::1;15182:309;15240:10;15278:8;15316:22;;15339:1;15316:25;;;;;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;:36;::::0;;;;;::::1;;;:::i;:::-;15382:22;;15405:1;15382:25;;;;;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;:36;::::0;;::::1;:::i;:::-;15182:309;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::1;::::0;;;;-1:-1:-1;15444:22:2;;-1:-1:-1;15444:22:2;;-1:-1:-1;15467:1:2;;-1:-1:-1;15444:25:2;;::::1;;;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;:32;::::0;::::1;::::0;::::1;::::0;::::1;:::i;:::-;15182:309;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::1;::::0;;;;-1:-1:-1;15182:31:2::1;::::0;-1:-1:-1;;;15182:309:2:i:1;:::-;15161:15;15177:1;15161:18;;;;;;;;:::i;:::-;;::::0;;::::1;::::0;;;;;:330;14530:3;::::1;::::0;::::1;:::i;:::-;;;;14475:1027;;;-1:-1:-1::0;15518:15:2;;14140:1400;-1:-1:-1;;;;;14140:1400:2:o;4795:692::-;4955:23;4967:10;4955:11;:23::i;:::-;4954:24;4946:111;;;;-1:-1:-1;;;4946:111:2;;28434:2:184;4946:111:2;;;28416:21:184;28473:2;28453:18;;;28446:30;28512:34;28492:18;;;28485:62;28583:34;28563:18;;;28556:62;-1:-1:-1;;;28634:19:184;;;28627:41;28685:19;;4946:111:2;28232:478:184;4946:111:2;5067:59;5087:10;5099:26;5067:19;:59::i;:::-;-1:-1:-1;;;;;;;;;;;;;;;;;5248:70:2;5258:10;;5282:23;5315:1;5248:9;:70::i;:::-;5375:10;-1:-1:-1;;;;;5356:58:2;;5387:26;5356:58;;;;;;:::i;:::-;;;;;;;;5456:10;-1:-1:-1;;;;;5429:51:2;;5468:11;;5429:51;;;;;;;:::i;:::-;;;;;;;;4936:551;4795:692;;;:::o;5826:138:29:-;2285:14;;;;;;;;;-1:-1:-1;;;;;2285:14:29;-1:-1:-1;;;;;2285:23:29;;:25;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;2271:39:29;:10;-1:-1:-1;;;;;2271:39:29;;2263:94;;;;-1:-1:-1;;;2263:94:29;;;;;;;:::i;:::-;5920:37:::1;5939:17;5920:18;:37::i;:::-;5826:138:::0;:::o;20110:571:2:-;2353:10;-1:-1:-1;;;;;2375:15:2;2353:38;;;:80;;-1:-1:-1;2395:10:2;-1:-1:-1;;;;;2417:15:2;2395:38;;2353:80;2332:182;;;;-1:-1:-1;;;2332:182:2;;;;;;;:::i;:::-;20338:19:::1;20350:6;20338:11;:19::i;:::-;20334:341;;;-1:-1:-1::0;;;;;20392:19:2;;::::1;20373:16;20392:19:::0;;;:11:::1;:19;::::0;;;;;::::1;20489:175;20392:19:::0;20404:6;20609:8;20643:6;20489:23:::1;:175::i;:::-;20359:316;20334:341;20110:571:::0;;;:::o;3832:392:29:-;2125:14;;:35;;-1:-1:-1;;;2125:35:29;;2149:10;2125:35;;;9813:51:184;-1:-1:-1;;;;;2125:14:29;;;;:23;;9786:18:184;;2125:35:29;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;2117:88;;;;-1:-1:-1;;;2117:88:29;;;;;;;:::i;:::-;4064:7:::1;::::0;4034:25;;::::1;4033:38;4025:107;;;::::0;-1:-1:-1;;;4025:107:29;;31751:2:184;4025:107:29::1;::::0;::::1;31733:21:184::0;31790:2;31770:18;;;31763:30;31829:34;31809:18;;;31802:62;31900:26;31880:18;;;31873:54;31944:19;;4025:107:29::1;31549:420:184::0;4025:107:29::1;4142:7;:25:::0;;;4182:35:::1;::::0;1014:25:184;;;4189:10:29::1;::::0;4182:35:::1;::::0;1002:2:184;987:18;4182:35:29::1;;;;;;;;3832:392:::0;:::o;21527:243:2:-;1334:13:42;:11;:13::i;:::-;21695:68:2::1;21729:10;;21741:21;;21695:33;:68::i;44553:408::-:0;-1:-1:-1;;;;;44800:19:2;;44708:7;44800:19;;;:11;:19;;;;;;44873:81;44812:6;44800:19;44937:8;44947:6;44873:35;:81::i;:::-;44866:88;44553:408;-1:-1:-1;;;;;44553:408:2:o;3318:607::-;3111:19:46;3134:13;;;;;;3133:14;;3179:34;;;;-1:-1:-1;3197:12:46;;3212:1;3197:12;;;;:16;3179:34;3178:108;;;-1:-1:-1;3258:4:46;1476:19:50;:23;;;3219:66:46;;-1:-1:-1;3268:12:46;;;;;:17;3219:66;3157:201;;;;-1:-1:-1;;;3157:201:46;;32176:2:184;3157:201:46;;;32158:21:184;32215:2;32195:18;;;32188:30;32254:34;32234:18;;;32227:62;-1:-1:-1;;;32305:18:184;;;32298:44;32359:19;;3157:201:46;31974:410:184;3157:201:46;3368:12;:16;;-1:-1:-1;;3368:16:46;3383:1;3368:16;;;3394:65;;;;3428:13;:20;;-1:-1:-1;;3428:20:46;;;;;3394:65;3619:55:2::1;3637:15;3654:19;3619:17;:55::i;:::-;3704:27;:25;:27::i;:::-;3684:17;:47:::0;3741:32:::1;3760:12:::0;3741:18:::1;:32::i;:::-;3783:55;3812:25;3783:28;:55::i;:::-;3848:70;3882:11;;3895:22;;3848:33;:70::i;:::-;3483:14:46::0;3479:99;;;3529:5;3513:21;;-1:-1:-1;;3513:21:46;;;3553:14;;-1:-1:-1;32541:36:184;;3553:14:46;;32529:2:184;32514:18;3553:14:46;;;;;;;3479:99;3101:483;3318:607:2;;;;;;;;:::o;19082:486::-;2353:10;-1:-1:-1;;;;;2375:15:2;2353:38;;;:80;;-1:-1:-1;2395:10:2;-1:-1:-1;;;;;2417:15:2;2395:38;;2353:80;2332:182;;;;-1:-1:-1;;;2332:182:2;;;;;;;:::i;:::-;19310:19:::1;19322:6;19310:11;:19::i;:::-;19306:256;;;-1:-1:-1::0;;;;;19364:19:2;;::::1;19345:16;19364:19:::0;;;:11:::1;:19;::::0;;;;;::::1;19454:97;19364:19:::0;19376:6;19525:8;19543:6;19454:23:::1;:97::i;18069:471::-:0;5724:7:29;;1664:1:2;;5695:10:29;5724:14;;;5723:24;2767:14;2759:52;;;;-1:-1:-1;;;2759:52:29;;;;;;;:::i;:::-;1815:1:49::1;2569:7;;:19;;2561:63;;;::::0;-1:-1:-1;;;2561:63:49;;32790:2:184;2561:63:49::1;::::0;::::1;32772:21:184::0;32829:2;32809:18;;;32802:30;32868:33;32848:18;;;32841:61;32919:18;;2561:63:49::1;32588:355:184::0;2561:63:49::1;1815:1;2699:7;:18:::0;18366:9:2::2;18361:173;18381:22:::0;;::::2;18361:173;;;18424:99;18450:11;;18462:1;18450:14;;;;;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;18466:6;;18473:1;18466:9;;;;;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;18477:22;;18500:1;18477:25;;;;;;;:::i;:::-;;;;;;;18504:15;;18520:1;18504:18;;;;;;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;18424:25;:99::i;:::-;18405:3;::::0;::::2;:::i;:::-;;;18361:173;;;-1:-1:-1::0;;1772:1:49::1;2872:7;:22:::0;-1:-1:-1;;;;;;;;18069:471:2:o;39718:123::-;-1:-1:-1;;;;;39800:19:2;;;39776:4;39800:19;;;:11;:19;;;;;;;:33;;;39718:123::o;4299:136:29:-;2125:14;;:35;;-1:-1:-1;;;2125:35:29;;2149:10;2125:35;;;9813:51:184;-1:-1:-1;;;;;2125:14:29;;;;:23;;9786:18:184;;2125:35:29;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;2117:88;;;;-1:-1:-1;;;2117:88:29;;;;;;;:::i;:::-;-1:-1:-1;;4349:7:29::1;:27:::0;;;4391:37:::1;::::0;1014:25:184;;;4398:10:29::1;::::0;4391:37:::1;::::0;1002:2:184;987:18;4391:37:29::1;;;;;;;4299:136::o:0;44115:150:2:-;44199:7;44246:10;44235:22;;;;;;;;:::i;:::-;;;;;;;;;;;;;44225:33;;;;;;44218:40;;44115:150;;;:::o;16982:353::-;5724:7:29;;1664:1:2;;5695:10:29;5724:14;;;5723:24;2767:14;2759:52;;;;-1:-1:-1;;;2759:52:29;;;;;;;:::i;:::-;1815:1:49::1;2569:7;;:19;;2561:63;;;::::0;-1:-1:-1;;;2561:63:49;;32790:2:184;2561:63:49::1;::::0;::::1;32772:21:184::0;32829:2;32809:18;;;32802:30;32868:33;32848:18;;;32841:61;32919:18;;2561:63:49::1;32588:355:184::0;2561:63:49::1;1815:1;2699:7;:18:::0;17244:84:2::2;17270:10:::0;17282:6;;17290:20;17312:15;17244:25:::2;:84::i;:::-;-1:-1:-1::0;;1772:1:49::1;2872:7;:22:::0;-1:-1:-1;;;;16982:353:2:o;20889:167::-;1334:13:42;:11;:13::i;:::-;20992:57:2::1;21021:27;20992:28;:57::i;39948:122::-:0;-1:-1:-1;;;;;40030:33:2;;;40007:4;40030:21;;;:11;:21;;;;;;;;;:33;;39948:122::o;2071:101:42:-;1334:13;:11;:13::i;:::-;2135:30:::1;2162:1;2135:18;:30::i;:::-;2071:101::o:0;9720:1488:2:-;10074:15;10039:24;:31;;;:50;;10018:162;;;;-1:-1:-1;;;10018:162:2;;35326:2:184;10018:162:2;;;35308:21:184;35365:2;35345:18;;;35338:30;35404:34;35384:18;;;35377:62;35475:34;35455:18;;;35448:62;-1:-1:-1;;;35526:19:184;;;35519:32;35568:19;;10018:162:2;35124:469:184;10018:162:2;10199:19;10211:6;10199:11;:19::i;:::-;10198:20;10190:110;;;;-1:-1:-1;;;10190:110:2;;35800:2:184;10190:110:2;;;35782:21:184;35839:2;35819:18;;;35812:30;35878:34;35858:18;;;35851:62;35949:34;35929:18;;;35922:62;-1:-1:-1;;;36000:19:184;;;35993:44;36054:19;;10190:110:2;35598:481:184;10190:110:2;10318:20;10329:8;10318:10;:20::i;:::-;10310:114;;;;-1:-1:-1;;;10310:114:2;;36286:2:184;10310:114:2;;;36268:21:184;36325:2;36305:18;;;36298:30;36364:34;36344:18;;;36337:62;36435:34;36415:18;;;36408:62;-1:-1:-1;;;36486:19:184;;;36479:48;36544:19;;10310:114:2;36084:485:184;10310:114:2;10505:26;10534:11;:19;10546:6;-1:-1:-1;;;;;10534:19:2;-1:-1:-1;;;;;10534:19:2;;;;;;;;;;;;;10505:48;;10563:24;10590:164;10639:6;10659:18;10691:8;10713:24;:31;;;10590:35;:164::i;:::-;-1:-1:-1;;;;;10788:19:2;;;;;;:11;:19;;;;;10831:1;10810:22;;10788:44;;10978:34;;10563:191;;-1:-1:-1;10907:106:2;;10800:6;;10563:191;;10907:44;:106::i;:::-;11132:69;11142:6;11150:8;11160:26;11188:12;11132:9;:69::i;:::-;9970:1238;;9720:1488;;;;;:::o;40891:368::-;41010:16;41038:23;41078:10;:17;-1:-1:-1;;;;;41064:32:2;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;41064:32:2;;41038:58;;41111:9;41106:124;41130:10;:17;41126:1;:21;41106:124;;;-1:-1:-1;;;;;41180:24:2;;;;;;:14;:24;;;;;41205:13;;41180:24;;;41205:10;;41216:1;;41205:13;;;;;;:::i;:::-;;;;;;;-1:-1:-1;;;;;41180:39:2;-1:-1:-1;;;;;41180:39:2;;;;;;;;;;;;;41168:6;41175:1;41168:9;;;;;;;;:::i;:::-;;;;;;;;;;:51;41149:3;;;:::i;:::-;;;41106:124;;6276:262;6367:22;6378:10;6367;:22::i;:::-;6359:106;;;;-1:-1:-1;;;6359:106:2;;36776:2:184;6359:106:2;;;36758:21:184;36815:2;36795:18;;;36788:30;36854:34;36834:18;;;36827:62;36925:34;36905:18;;;36898:62;-1:-1:-1;;;36976:19:184;;;36969:38;37024:19;;6359:106:2;36574:475:184;6359:106:2;6507:10;-1:-1:-1;;;;;6480:51:2;;6519:11;;6480:51;;;;;;;:::i;:::-;;;;;;;;6276:262;;:::o;45391:560::-;45673:78;;;939:91:3;45673:78:2;;;;37313:25:184;;;;-1:-1:-1;;;;;37412:15:184;;;37392:18;;;37385:43;37464:15;;37444:18;;;37437:43;37496:18;;;37489:34;;;37539:19;;;;37532:35;;;45673:78:2;;;;;;;;;;37285:19:184;;;;45673:78:2;;;45650:111;;;;;-1:-1:-1;;;45874:17:2;:15;:17::i;:::-;45845:65;;-1:-1:-1;;;45845:65:2;;;25423:27:184;25466:11;;;25459:27;;;;25502:12;;;25495:28;;;25539:12;;45845:65:2;;;;;;-1:-1:-1;;45845:65:2;;;;;;45835:76;;45845:65;45835:76;;;;;45391:560;-1:-1:-1;;;;;;;45391:560:2:o;41484:1765::-;41685:38;;-1:-1:-1;;;41685:38:2;;-1:-1:-1;;;;;9831:32:184;;;41685:38:2;;;9813:51:184;41551:18:2;;;;-1:-1:-1;;41685:15:2;:30;;;;;;9786:18:184;;41685:38:2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;41831:35;;-1:-1:-1;;;41831:35:2;;-1:-1:-1;;;;;9831:32:184;;;41831:35:2;;;9813:51:184;41666:57:2;;-1:-1:-1;;;;;41831:15:2;:27;;;;;;9786:18:184;;41831:35:2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;41831:35:2;;;;;;;;;;;;:::i;:::-;41733:133;;;;41979:1;41966:9;:14;41962:98;;42004:21;;42027;;-1:-1:-1;41484:1765:2;-1:-1:-1;;;41484:1765:2:o;41962:98::-;42070:29;42109:23;42147:21;:28;42179:1;42147:33;42143:1062;;;42282:18;;;42298:1;42282:18;;;;;;;;;;;;;;;;;;;-1:-1:-1;;42323:16:2;;;42337:1;42323:16;;;;;;;;;42269:31;;-1:-1:-1;42337:1:2;-1:-1:-1;42323:16:2;;;;;;;;;;;-1:-1:-1;42323:16:2;42314:25;;2088:42;42353:10;42364:1;42353:13;;;;;;;;:::i;:::-;;;;;;:38;-1:-1:-1;;;;;42353:38:2;;;-1:-1:-1;;;;;42353:38:2;;;;;42425:9;42405:6;42412:1;42405:9;;;;;;;;:::i;:::-;;;;;;:30;;;;;42143:1062;;;42583:28;;:32;;42614:1;42583:32;:::i;:::-;-1:-1:-1;;;;;42567:49:2;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;42567:49:2;;42554:62;;42653:10;:17;-1:-1:-1;;;;;42639:32:2;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;42639:32:2;;42630:41;;42774:9;42769:219;42793:21;:28;42789:1;:32;42769:219;;;42859:21;42881:1;42859:24;;;;;;;;:::i;:::-;;;;;;;42843:10;42854:1;42843:13;;;;;;;;:::i;:::-;;;;;;:40;-1:-1:-1;;;;;42843:40:2;;;-1:-1:-1;;;;;42843:40:2;;;;;42913:21;42935:1;42913:24;;;;;;;;:::i;:::-;;;;;;;42901:6;42908:1;42901:9;;;;;;;;:::i;:::-;;;;;;;;;;:36;42968:3;;42769:219;;;;2088:42;43072:10;43103:1;43083:10;:17;:21;;;;:::i;:::-;43072:33;;;;;;;;:::i;:::-;;;;;;:58;-1:-1:-1;;;;;43072:58:2;;;-1:-1:-1;;;;;43072:58:2;;;;;43184:9;43144:6;43171:1;43151:10;:17;:21;;;;:::i;:::-;43144:29;;;;;;;;:::i;:::-;;;;;;:50;;;;;42143:1062;43223:10;;43235:6;;-1:-1:-1;41484:1765:2;-1:-1:-1;;;;;41484:1765:2:o;11533:2250::-;5724:7:29;;11636:32:2;;1520:1;;5695:10:29;5724:14;;;5723:24;2767:14;2759:52;;;;-1:-1:-1;;;2759:52:29;;;;;;;:::i;:::-;11688:19:2::1;11700:6;11688:11;:19::i;:::-;11680:100;;;::::0;-1:-1:-1;;;11680:100:2;;40149:2:184;11680:100:2::1;::::0;::::1;40131:21:184::0;40188:2;40168:18;;;40161:30;;;40227:34;40207:18;;;40200:62;40298:34;40278:18;;;40271:62;-1:-1:-1;;;40349:19:184;;;40342:35;40394:19;;11680:100:2::1;39947:472:184::0;11680:100:2::1;11799:18;11810:6;11799:10;:18::i;:::-;11798:19;11790:93;;;::::0;-1:-1:-1;;;11790:93:2;;40626:2:184;11790:93:2::1;::::0;::::1;40608:21:184::0;40665:2;40645:18;;;40638:30;40704:34;40684:18;;;40677:62;40775:31;40755:18;;;40748:59;40824:19;;11790:93:2::1;40424:425:184::0;11790:93:2::1;-1:-1:-1::0;;;;;11901:20:2;::::1;11893:93;;;::::0;-1:-1:-1;;;11893:93:2;;41056:2:184;11893:93:2::1;::::0;::::1;41038:21:184::0;41095:2;41075:18;;;41068:30;41134:34;41114:18;;;41107:62;41205:30;41185:18;;;41178:58;41253:19;;11893:93:2::1;40854:424:184::0;11893:93:2::1;-1:-1:-1::0;;;;;12015:19:2;;::::1;11996:16;12015:19:::0;;;:11:::1;:19;::::0;;;;;;;::::1;::::0;12065:10:::1;:20;::::0;:62:::1;;-1:-1:-1::0;12105:10:2::1;-1:-1:-1::0;;;;;12105:22:2;::::1;;12065:62;:141;;;-1:-1:-1::0;;;;;;12161:26:2;;::::1;;::::0;;;:16:::1;:26;::::0;;;;:45:::1;;::::0;::::1;12147:10;:59;12065:141;12044:249;;;::::0;-1:-1:-1;;;12044:249:2;;41485:2:184;12044:249:2::1;::::0;::::1;41467:21:184::0;41524:2;41504:18;;;41497:30;41563:34;41543:18;;;41536:62;41634:31;41614:18;;;41607:59;41683:19;;12044:249:2::1;41283:425:184::0;12044:249:2::1;12471:29;12502:23:::0;12529:28:::1;12550:6;12529:20;:28::i;:::-;12470:87:::0;;-1:-1:-1;12470:87:2;-1:-1:-1;12655:10:2::1;-1:-1:-1::0;;;;;12655:20:2;::::1;;12651:96;;12727:8;-1:-1:-1::0;;;;;12696:40:2::1;12719:6;-1:-1:-1::0;;;;;12696:40:2::1;;;;;;;;;;;12651:96;12821:8;-1:-1:-1::0;;;;;12795:35:2::1;12813:6;-1:-1:-1::0;;;;;12795:35:2::1;;;;;;;;;;;-1:-1:-1::0;;;;;12840:19:2;::::1;12870:1;12840:19:::0;;;:11:::1;:19;::::0;;;;:32;;-1:-1:-1;;;;;;12840:32:2::1;::::0;;12976:17;;12972:772:::1;;13032:16;::::0;;13046:1:::1;13032:16:::0;;::::1;::::0;::::1;::::0;;;;-1:-1:-1;12972:772:2::1;;;13111:10;:17;-1:-1:-1::0;;;;;13097:32:2::1;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;-1:-1:-1;13097:32:2::1;;13079:50;;13148:9;13143:591;13167:10;:17;13163:1;:21;13143:591;;;13245:18;::::0;;13261:1:::1;13245:18:::0;;;;;::::1;::::0;;;13209:33:::1;::::0;13245:18:::1;::::0;;::::1;::::0;;::::1;::::0;::::1;-1:-1:-1::0;;13312:16:2::1;::::0;;13326:1:::1;13312:16:::0;;;;;::::1;::::0;;;13209:54;;-1:-1:-1;13281:28:2::1;::::0;13312:16;-1:-1:-1;13312:16:2::1;::::0;;::::1;::::0;;::::1;::::0;::::1;;::::0;-1:-1:-1;13312:16:2::1;13281:47;;13366:10;13377:1;13366:13;;;;;;;;:::i;:::-;;;;;;;13346:14;13361:1;13346:17;;;;;;;;:::i;:::-;;;;;;:33;-1:-1:-1::0;;;;;13346:33:2::1;;;-1:-1:-1::0;;;;;13346:33:2::1;;;::::0;::::1;13414:6;13421:1;13414:9;;;;;;;;:::i;:::-;;;;;;;13397:11;13409:1;13397:14;;;;;;;;:::i;:::-;;;;;;:26;;;::::0;::::1;13463:256;13525:6;13563:8;13605:6;13645:14;13689:11;13463:31;:256::i;:::-;13442:15;13458:1;13442:18;;;;;;;;:::i;:::-;;;;;;:277;;;::::0;::::1;13191:543;;13186:3;;;;;:::i;:::-;;;;13143:591;;;;12972:772;13754:22;;;11533:2250:::0;;;;:::o;7541:578::-;7714:23;7726:10;7714:11;:23::i;:::-;7713:24;7705:103;;;;-1:-1:-1;;;7705:103:2;;41915:2:184;7705:103:2;;;41897:21:184;41954:2;41934:18;;;41927:30;41993:34;41973:18;;;41966:62;42064:34;42044:18;;;42037:62;-1:-1:-1;;;42115:19:184;;;42108:33;42158:19;;7705:103:2;41713:470:184;7705:103:2;7826:20;7837:8;7826:10;:20::i;:::-;7818:103;;;;-1:-1:-1;;;7818:103:2;;42390:2:184;7818:103:2;;;42372:21:184;42429:2;42409:18;;;42402:30;42468:34;42448:18;;;42441:62;42539:34;42519:18;;;42512:62;-1:-1:-1;;;42590:19:184;;;42583:37;42637:19;;7818:103:2;42188:474:184;7818:103:2;8039:73;8049:10;8061:8;8071:26;8099:12;8039:9;:73::i;5791:265::-;5894:22;5905:10;5894;:22::i;:::-;5886:102;;;;-1:-1:-1;;;5886:102:2;;42869:2:184;5886:102:2;;;42851:21:184;42908:2;42888:18;;;42881:30;42947:34;42927:18;;;42920:62;43018:34;42998:18;;;42991:62;-1:-1:-1;;;43069:19:184;;;43062:34;43113:19;;5886:102:2;42667:471:184;5886:102:2;5998:51;6018:10;6030:18;5998:19;:51::i;2321:198:42:-;1334:13;:11;:13::i;:::-;-1:-1:-1;;;;;2409:22:42;::::1;2401:73;;;::::0;-1:-1:-1;;;2401:73:42;;43345:2:184;2401:73:42::1;::::0;::::1;43327:21:184::0;43384:2;43364:18;;;43357:30;43423:34;43403:18;;;43396:62;-1:-1:-1;;;43474:18:184;;;43467:36;43520:19;;2401:73:42::1;43143:402:184::0;2401:73:42::1;2484:28;2503:8;2484:18;:28::i;39379:227:2:-:0;39427:7;39467:17;39450:13;:34;39446:154;;;-1:-1:-1;39507:17:2;;;39379:227::o;39446:154::-;39562:27;:25;:27::i;:::-;39555:34;;39379:227;:::o;4911:437:29:-;2285:14;;;;;;;;;-1:-1:-1;;;;;2285:14:29;-1:-1:-1;;;;;2285:23:29;;:25;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;2271:39:29;:10;-1:-1:-1;;;;;2271:39:29;;2263:94;;;;-1:-1:-1;;;2263:94:29;;;;;;;:::i;:::-;5164:7:::1;;5163:8;5141:15;5140:16;5128:7;;5127:8;5126:31;5125:47;5104:150;;;::::0;-1:-1:-1;;;5104:150:29;;43752:2:184;5104:150:29::1;::::0;::::1;43734:21:184::0;43791:2;43771:18;;;43764:30;43830:34;43810:18;;;43803:62;43901:26;43881:18;;;43874:54;43945:19;;5104:150:29::1;43550:420:184::0;5104:150:29::1;5264:7;:25:::0;;;5304:37:::1;::::0;1014:25:184;;;5313:10:29::1;::::0;5304:37:::1;::::0;1002:2:184;987:18;5304:37:29::1;868:177:184::0;33099:2938:2;33316:7;-1:-1:-1;;;;;33343:20:2;;33335:113;;;;-1:-1:-1;;;33335:113:2;;44177:2:184;33335:113:2;;;44159:21:184;44216:2;44196:18;;;44189:30;44255:34;44235:18;;;44228:62;44326:34;44306:18;;;44299:62;-1:-1:-1;;;44377:19:184;;;44370:47;44434:19;;33335:113:2;43975:484:184;33335:113:2;33466:17;;33458:112;;;;-1:-1:-1;;;33458:112:2;;44666:2:184;33458:112:2;;;44648:21:184;44705:2;44685:18;;;44678:30;44744:34;44724:18;;;44717:62;44815:34;44795:18;;;44788:62;-1:-1:-1;;;44866:19:184;;;44859:44;44920:19;;33458:112:2;44464:481:184;33458:112:2;33728:9;33723:1588;33747:10;:17;33743:1;:21;33723:1588;;;-1:-1:-1;;;;;33831:22:2;;;33827:264;;33873:203;33929:8;33967:6;34005:10;34016:1;34005:13;;;;;;;;:::i;:::-;;;;;;;34048:6;34055:1;34048:9;;;;;;;;:::i;:::-;;;;;;;33873:23;:203::i;:::-;2088:42;-1:-1:-1;;;;;34182:39:2;:10;34193:1;34182:13;;;;;;;;:::i;:::-;;;;;;;-1:-1:-1;;;;;34182:39:2;;34178:1091;;;34690:15;-1:-1:-1;;;;;34690:28:2;;34719:6;34727;34734:1;34727:9;;;;;;;;:::i;:::-;;;;;;;34690:47;;;;;;;;;;;;;;;-1:-1:-1;;;;;45142:32:184;;;;45124:51;;45206:2;45191:18;;45184:34;45112:2;45097:18;;44950:274;34690:47:2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;34178:1091;;;34815:10;-1:-1:-1;;;;;34805:20:2;:6;-1:-1:-1;;;;;34805:20:2;;:84;;;;34830:15;-1:-1:-1;;;;;34830:44:2;;34875:10;34886:1;34875:13;;;;;;;;:::i;:::-;;;;;;;34830:59;;;;;;;;;;;;;;-1:-1:-1;;;;;9831:32:184;;;;9813:51;;9801:2;9786:18;;9642:228;34830:59:2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;34829:60;34805:84;34776:287;;;;-1:-1:-1;;;34776:287:2;;45431:2:184;34776:287:2;;;45413:21:184;45470:3;45450:18;;;45443:31;;;45510:34;45490:18;;;45483:62;45581:34;45561:18;;;45554:62;45653:34;45632:19;;;45625:63;45725:34;45704:19;;;45697:63;-1:-1:-1;;;45776:19:184;;;45769:35;45821:19;;34776:287:2;45229:617:184;34776:287:2;35192:15;-1:-1:-1;;;;;35192:28:2;;35221:6;35229:10;35240:1;35229:13;;;;;;;;:::i;:::-;;;;;;;35244:6;35251:1;35244:9;;;;;;;;:::i;:::-;;;;;;;35192:62;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;34178:1091;35295:3;;33723:1588;;;-1:-1:-1;;;;;;35398:35:2;;35382:13;35398:35;;;:27;:35;;;;;;;;;;;35443:37;35398:35;35443:37;:::i;:::-;;;;;;35491:28;35522:257;;;;;;;;35555:6;-1:-1:-1;;;;;35522:257:2;;;;;35588:8;-1:-1:-1;;;;;35522:257:2;;;;;35622:10;-1:-1:-1;;;;;35522:257:2;;;;;35653:5;35522:257;;;;35691:12;35522:257;;;;;;35730:10;35522:257;;;;35762:6;35522:257;;;35491:288;;35790:22;35815:35;35839:10;35815:23;:35::i;:::-;35898:34;;;;:18;:34;;;;;;;:41;;-1:-1:-1;;35898:41:2;35935:4;35898:41;;;35955:44;35790:60;;-1:-1:-1;35955:44:2;;;;35790:60;;35988:10;;35955:44;:::i;:::-;;;;;;;;36016:14;33099:2938;-1:-1:-1;;;;;;;;33099:2938:2:o;22246:717::-;1944:15;22378:43;;;;;;;;:::i;:::-;:79;;;;22357:234;;;;-1:-1:-1;;;22357:234:2;;47044:2:184;22357:234:2;;;47026:21:184;47083:3;47063:18;;;47056:31;47123:34;47103:18;;;47096:62;47194:34;47174:18;;;47167:62;47266:34;47245:19;;;47238:63;-1:-1:-1;;;47317:19:184;;;47310:43;47370:19;;22357:234:2;46842:553:184;22357:234:2;-1:-1:-1;;;;;22669:26:2;;;;;;:16;:26;;;;;;;:51;;;-1:-1:-1;;;22669:51:2;;;;;22622:43;;;;;;;;;:::i;:::-;:98;;;;22601:228;;;;-1:-1:-1;;;22601:228:2;;47602:2:184;22601:228:2;;;47584:21:184;47641:2;47621:18;;;47614:30;47680:34;47660:18;;;47653:62;47751:34;47731:18;;;47724:62;-1:-1:-1;;;47802:19:184;;;47795:50;47862:19;;22601:228:2;47400:487:184;22601:228:2;-1:-1:-1;;;;;22839:26:2;;;;;;:16;:26;;;;;22868:18;;22839:47;22868:18;22839:26;:47;:::i;:::-;-1:-1:-1;;22901:55:2;;22925:10;;22901:55;;;;22937:18;;22901:55;:::i;23937:2700::-;5724:7:29;;1383:1:2;;5695::29;5724:14;;;5723:24;2767:14;2759:52;;;;-1:-1:-1;;;2759:52:29;;;;;;;:::i;:::-;-1:-1:-1;;;;;24320:26:2;;::::1;24290:27;24320:26:::0;;;:16:::1;:26;::::0;;;;:45:::1;;::::0;::::1;24782:33:::0;;;::::1;::::0;:70:::1;;-1:-1:-1::0;24819:10:2::1;-1:-1:-1::0;;;;;24819:33:2;::::1;;;24782:70;:96;;;;-1:-1:-1::0;24856:10:2::1;-1:-1:-1::0;;;;;24856:22:2;::::1;;;24782:96;24778:1267;;;24998:15;24961:26;:33;;;:52;;24936:166;;;::::0;-1:-1:-1;;;24936:166:2;;49057:2:184;24936:166:2::1;::::0;::::1;49039:21:184::0;49096:2;49076:18;;;49069:30;49135:34;49115:18;;;49108:62;49206:25;49186:18;;;49179:53;49249:19;;24936:166:2::1;48855:419:184::0;24936:166:2::1;-1:-1:-1::0;;;;;25234:50:2;::::1;;::::0;;;:29:::1;:50;::::0;;;;;;;:64;;;;;;;;;::::1;;25233:65;25208:179;;;::::0;-1:-1:-1;;;25208:179:2;;49481:2:184;25208:179:2::1;::::0;::::1;49463:21:184::0;49520:2;49500:18;;;49493:30;49559:34;49539:18;;;49532:62;49630:25;49610:18;;;49603:53;49673:19;;25208:179:2::1;49279:419:184::0;25208:179:2::1;-1:-1:-1::0;;;;;25401:50:2;::::1;;::::0;;;:29:::1;:50;::::0;;;;;;;:64;;;;;;;:71;;-1:-1:-1;;25401:71:2::1;25468:4;25401:71;::::0;;25729:33;::::1;::::0;25557:219:::1;::::0;25612:6;;25636:8;;25431:19;;25452:12;;25557:37:::1;:219::i;:::-;25528:248;;25849:185;25911:19;25948:18;25984:26;:36;;;25849:44;:185::i;:::-;24880:1165;24778:1267;-1:-1:-1::0;;;;;26148:19:2;;::::1;;::::0;;;:11:::1;:19;::::0;;;;;:30;;-1:-1:-1;;;;;;26148:30:2::1;::::0;;::::1;::::0;;::::1;::::0;;26193:33;::::1;::::0;26148:19;26193:33:::1;26238:29;26269:23:::0;26308:28:::1;26329:6;26308:20;:28::i;:::-;26237:99;;;;26352:9;26347:284;26371:10;:17;26367:1;:21;26347:284;;;26405:183;26457:8;26491:6;26525:10;26536:1;26525:13;;;;;;;;:::i;:::-;;;;;;;26564:6;26571:1;26564:9;;;;;;;;:::i;:::-;;;;;;;26405:23;:183::i;:::-;26615:3;;26347:284;;6024:360:29::0;-1:-1:-1;;;;;6127:40:29;;6106:160;;;;-1:-1:-1;;;6106:160:29;;49905:2:184;6106:160:29;;;49887:21:184;49944:2;49924:18;;;49917:30;49983:34;49963:18;;;49956:62;50054:34;50034:18;;;50027:62;-1:-1:-1;;;50105:19:184;;;50098:40;50155:19;;6106:160:29;49703:477:184;6106:160:29;6299:14;;6281:52;;;-1:-1:-1;;;;;6299:14:29;;;50445:34:184;;50515:15;;;50510:2;50495:18;;50488:43;6281:52:29;;50380:18:184;6281:52:29;;;;;;;6343:14;:34;;-1:-1:-1;;;;;;6343:34:29;-1:-1:-1;;;;;6343:34:29;;;;;;;;;;6024:360::o;32323:308:2:-;-1:-1:-1;;;;;32506:24:2;;;;;;;:14;:24;;;;;;;;:34;;;;;;;;;;;:44;;32544:6;;32506:24;:44;;32544:6;;32506:44;:::i;:::-;;;;;;;;32589:8;-1:-1:-1;;;;;32565:59:2;;32599:6;32607:8;32617:6;32565:59;;;;;;;;:::i;1599:130:42:-;1513:6;;-1:-1:-1;;;;;1513:6:42;929:10:51;1662:23:42;1654:68;;;;-1:-1:-1;;;1654:68:42;;50744:2:184;1654:68:42;;;50726:21:184;;;50763:18;;;50756:30;50822:34;50802:18;;;50795:62;50874:18;;1654:68:42;50542:356:184;37511:1259:2;37693:51;;;37672:172;;;;-1:-1:-1;;;37672:172:2;;51105:2:184;37672:172:2;;;51087:21:184;51144:2;51124:18;;;51117:30;51183:34;51163:18;;;51156:62;51254:34;51234:18;;;51227:62;-1:-1:-1;;;51305:19:184;;;51298:41;51356:19;;37672:172:2;50903:478:184;37672:172:2;37874:11;37854:17;37902:862;37926:9;37922:1;:13;37902:862;;;37956:18;37977:11;;37989:1;37977:14;;;;;;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;38049:39:2;;38005:41;38049:39;;;:29;:39;;;;;;37956:35;;-1:-1:-1;38145:22:2;;38168:1;38145:25;;;;;;;:::i;:::-;;;;;;;38102:68;;2105:6:3;38209:32:2;:63;;38184:237;;;;-1:-1:-1;;;38184:237:2;;51588:2:184;38184:237:2;;;51570:21:184;51627:3;51607:18;;;51600:31;51667:34;51647:18;;;51640:62;51738:34;51718:18;;;51711:62;51810:34;51789:19;;;51782:63;-1:-1:-1;;;51861:19:184;;;51854:50;51921:19;;38184:237:2;51386:560:184;38184:237:2;-1:-1:-1;;;;;38487:39:2;;;;;;:29;:39;;;;;;;;;:74;;;38580:173;;52171:51:184;;;52238:18;;52231:34;;;52281:18;;52274:34;;;38580:173:2;;52159:2:184;52144:18;38580:173:2;;;;;;;37942:822;;;37937:3;;;;:::i;:::-;;;37902:862;;;;37662:1108;37511:1259;;;;:::o;2943:441:29:-;3077:14;;-1:-1:-1;;;;;3077:14:29;3069:37;:79;;;;-1:-1:-1;;;;;;3110:38:29;;;;3069:79;3048:197;;;;-1:-1:-1;;;3048:197:29;;52521:2:184;3048:197:29;;;52503:21:184;52560:2;52540:18;;;52533:30;52599:34;52579:18;;;52572:62;52670:34;52650:18;;;52643:62;-1:-1:-1;;;52721:19:184;;;52714:38;52769:19;;3048:197:29;52319:475:184;3048:197:29;3255:7;:26;;;3296:36;;1014:25:184;;;3303:10:29;;3296:36;;1002:2:184;987:18;3296:36:29;;;;;;;3342:35;3361:15;3342:18;:35::i;:::-;2943:441;;:::o;47285:193:2:-;47419:19;;;;;;;;;;;-1:-1:-1;;;47419:19:2;;;;;47381:89;;699:80:3;47381:89:2;;;53030:25:184;47409:30:2;53071:18:184;;;53064:34;47441:13:2;53114:18:184;;;53107:34;47464:4:2;53157:18:184;;;;53150:60;;;;47381:89:2;;;;;;;;;;53002:19:184;;;;47381:89:2;;;47371:100;;;;;;47285:193::o;2673:187:42:-;2765:6;;;-1:-1:-1;;;;;2781:17:42;;;-1:-1:-1;;;;;;2781:17:42;;;;;;;2813:40;;2765:6;;;2781:17;2765:6;;2813:40;;2746:16;;2813:40;2736:124;2673:187;:::o;36810:472:2:-;2105:6:3;36923:25:2;:56;;36902:216;;;;-1:-1:-1;;;36902:216:2;;53423:2:184;36902:216:2;;;53405:21:184;53462:3;53442:18;;;53435:31;53502:34;53482:18;;;53475:62;53573:34;53553:18;;;53546:62;53645:34;53624:19;;;53617:63;-1:-1:-1;;;53696:19:184;;;53689:48;53754:19;;36902:216:2;53221:558:184;36902:216:2;37161:24;;37133:80;;;53958:25:184;;;54014:2;53999:18;;53992:34;;;37133:80:2;;53931:18:184;37133:80:2;;;;;;;37223:24;:52;36810:472::o;31945:247::-;-1:-1:-1;;;;;32067:24:2;;;;;;;:14;:24;;;;;;;;:34;;;;;;;;;;;:44;;32105:6;;32067:24;:44;;32105:6;;32067:44;:::i;:::-;;;;;;;;32150:8;-1:-1:-1;;;;;32126:59:2;;32160:6;32168:8;32178:6;32126:59;;;;;;;;:::i;26980:4834::-;27186:22;27211:35;;27235:10;27211:35;:::i;:::-;27278:34;;;;:18;:34;;;;;;27186:60;;-1:-1:-1;27278:34:2;;27257:149;;;;-1:-1:-1;;;27257:149:2;;54446:2:184;27257:149:2;;;54428:21:184;54485:2;54465:18;;;54458:30;-1:-1:-1;;;;;;;;;;;54504:18:184;;;54497:62;54595:34;54575:18;;;54568:62;-1:-1:-1;;;54646:19:184;;;54639:34;54690:19;;27257:149:2;54244:471:184;27257:149:2;27462:24;;27490:12;;27438:21;;;;;;;;:::i;:::-;:48;;;;;;:::i;:::-;:64;;27417:207;;;;-1:-1:-1;;;27417:207:2;;54922:2:184;27417:207:2;;;54904:21:184;54961:2;54941:18;;;54934:30;-1:-1:-1;;;;;;;;;;;54980:18:184;;;54973:62;55071:34;55051:18;;;55044:62;55143:33;55122:19;;;55115:62;55194:19;;27417:207:2;54720:499:184;27417:207:2;27670:21;;;;;;;;:::i;:::-;-1:-1:-1;;;;;27656:35:2;:10;-1:-1:-1;;;;;27656:35:2;;27635:163;;;;-1:-1:-1;;;27635:163:2;;55426:2:184;27635:163:2;;;55408:21:184;55465:2;55445:18;;;55438:30;-1:-1:-1;;;;;;;;;;;55484:18:184;;;55477:62;55575:34;55555:18;;;55548:62;-1:-1:-1;;;55626:19:184;;;55619:47;55683:19;;27635:163:2;55224:484:184;27635:163:2;27813:15;27809:217;;;27886:21;;;;:10;:21;:::i;:::-;27869:45;;;-1:-1:-1;27844:171:2;;;;-1:-1:-1;;;27844:171:2;;55915:2:184;27844:171:2;;;55897:21:184;55954:2;55934:18;;;55927:30;-1:-1:-1;;;;;;;;;;;55973:18:184;;;55966:62;56064:34;56044:18;;;56037:62;-1:-1:-1;;;56115:19:184;;;56108:33;56158:19;;27844:171:2;55713:470:184;27844:171:2;28097:34;;;;:18;:34;;;;;28090:41;;-1:-1:-1;;28090:41:2;;;28273:3484;;;;28313:9;28308:697;28332:21;;;;:10;:21;:::i;:::-;:28;;28328:1;:32;28308:697;;;28494:12;28435:29;:55;28465:21;;;;:10;:21;:::i;:::-;28487:1;28465:24;;;;;;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;28435:55:2;;;;;;;;;;;;-1:-1:-1;28435:55:2;;28411:21;;;;;;;;:::i;:::-;:79;;;;;;:::i;:::-;:95;;28382:276;;;;-1:-1:-1;;;28382:276:2;;;;;;;:::i;:::-;28677:278;28731:17;;;;:10;:17;:::i;:::-;28782:10;28824:21;;;;:10;:21;:::i;:::-;28846:1;28824:24;;;;;;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;28878:17;;;;:10;:17;:::i;:::-;28896:1;28878:20;;;;;;;:::i;:::-;;;;;;;28927:6;;28934:1;28927:9;;;;;;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;28677:23;:278::i;:::-;28985:3;;28308:697;;;;28273:3484;;;29212:10;29174:23;29200;;;:11;:23;;;;;;-1:-1:-1;;;;;29200:23:2;;29237:2510;29261:21;;;;:10;:21;:::i;:::-;:28;;29257:1;:32;29237:2510;;;29423:12;29364:29;:55;29394:21;;;;:10;:21;:::i;:::-;29416:1;29394:24;;;;;;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;29364:55:2;;;;;;;;;;;;-1:-1:-1;29364:55:2;;29340:21;;;;;;;;:::i;:::-;:79;;;;;;:::i;:::-;:95;;29311:277;;;;-1:-1:-1;;;29311:277:2;;;;;;;:::i;:::-;2088:42;29850:21;;;;:10;:21;:::i;:::-;29872:1;29850:24;;;;;;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;29850:50:2;;29846:1852;;;29924:14;29941:17;;;;:10;:17;:::i;:::-;29924:34;-1:-1:-1;30238:36:2;-1:-1:-1;;;;;30277:15:2;:25;;29924:34;30379:17;;;;:10;:17;:::i;:::-;30397:1;30379:20;;;;;;;:::i;:::-;30277:145;;-1:-1:-1;;;;;;30277:145:2;;;;;;;-1:-1:-1;;;;;45142:32:184;;;30277:145:2;;;45124:51:184;30379:20:2;;;;;;;45191:18:184;;;45184:34;-1:-1:-1;45097:18:184;;30277:145:2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;30471:19:2;;;30444:24;30471:19;;;:11;:19;;;;;;30238:184;;-1:-1:-1;30471:19:2;30570:30;;30566:451;;30628:366;30692:16;30831:6;30877:21;;;;:10;:21;:::i;:::-;30899:1;30877:24;;;;;;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;30939:28;30628:23;:366::i;:::-;29902:1133;;;29846:1852;;;31063:15;-1:-1:-1;;;;;31063:25:2;;31089:10;31101:6;;31108:1;31101:9;;;;;;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;31112:21;;;;:10;:21;:::i;:::-;31134:1;31112:24;;;;;;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;31138:17;;;;:10;:17;:::i;:::-;31156:1;31138:20;;;;;;;:::i;:::-;31063:96;;;;;;-1:-1:-1;;;;;;31063:96:2;;;-1:-1:-1;;;;;57526:15:184;;;31063:96:2;;;57508:34:184;57578:15;;;57558:18;;;57551:43;57630:15;;;;57610:18;;;57603:43;31138:20:2;;;;;;57662:18:184;;;57655:34;57442:19;;;-1:-1:-1;31063:96:2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;;;;;31239:29:2;;;31235:445;;31296:361;31360:15;31498:10;31548:21;;;;:10;:21;:::i;:::-;31570:1;31548:24;;;;;;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;31610:17;;;;:10;:17;:::i;:::-;31628:1;31610:20;;;;;;;:::i;:::-;;;;;;;31296:23;:361::i;:::-;31727:3;;29237:2510;;;;29160:2597;28273:3484;31772:35;;1014:25:184;;;31772:35:2;;1002:2:184;987:18;31772:35:2;;;;;;;27176:4638;26980:4834;;;;;:::o;974:926:25:-;-1:-1:-1;;;;;1476:19:50;;;:23;1410:484:25;;1481:56;;-1:-1:-1;;;1481:56:25;;;1541:18;-1:-1:-1;;;;;1481:33:25;;;574:10;;1481:56;;1515:10;;1527:9;;1481:56;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;;1481:78:25;;1456:220;;;;-1:-1:-1;;;1456:220:25;;58868:2:184;1456:220:25;;;58850:21:184;58907:2;58887:18;;;58880:30;58946:34;58926:18;;;58919:62;59017:34;58997:18;;;58990:62;-1:-1:-1;;;59068:19:184;;;59061:50;59128:19;;1456:220:25;58666:487:184;1410:484:25;1772:6;-1:-1:-1;;;;;1732:46:25;:36;1746:10;1758:9;1732:13;:36::i;:::-;-1:-1:-1;;;;;1732:46:25;;1707:176;;;;-1:-1:-1;;;1707:176:25;;59360:2:184;1707:176:25;;;59342:21:184;59399:2;59379:18;;;59372:30;59438:34;59418:18;;;59411:62;59509:34;59489:18;;;59482:62;-1:-1:-1;;;59560:19:184;;;59553:38;59608:19;;1707:176:25;59158:475:184;36328:476:2;-1:-1:-1;;;;;36470:34:2;;2088:42;36470:34;36466:332;;;36520:161;;-1:-1:-1;;;36520:161:2;;-1:-1:-1;;;;;36520:15:2;:38;;;;:161;;36587:6;;36624:10;;36660:6;;36520:161;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;36466:332;;;36712:75;;-1:-1:-1;;;36712:75:2;;-1:-1:-1;;;;;60339:15:184;;;36712:75:2;;;60321:34:184;60391:15;;;60371:18;;;60364:43;60423:18;;;60416:34;;;60486:15;;;60466:18;;;60459:43;36712:15:2;:38;;;;60255:19:184;;36712:75:2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;36466:332;36328:476;;;;;:::o;4402:227:77:-;4480:7;4500:17;4519:18;4541:27;4552:4;4558:9;4541:10;:27::i;:::-;4499:69;;;;4578:18;4590:5;4578:11;:18::i;2243:1373::-;2324:7;2333:12;2554:9;:16;2574:2;2554:22;2550:1060;;;2890:4;2875:20;;2869:27;2939:4;2924:20;;2918:27;2996:4;2981:20;;2975:27;2592:9;2967:36;3037:25;3048:4;2967:36;2869:27;2918;3037:10;:25::i;:::-;3030:32;;;;;;;;;2550:1060;3083:9;:16;3103:2;3083:22;3079:531;;;3399:4;3384:20;;3378:27;3449:4;3434:20;;3428:27;3489:23;3500:4;3378:27;3428;3489:10;:23::i;:::-;3482:30;;;;;;;;3079:531;-1:-1:-1;3559:1:77;;-1:-1:-1;3563:35:77;3079:531;2243:1373;;;;;:::o;548:631::-;625:20;616:5;:29;;;;;;;;:::i;:::-;;612:561;;;548:631;:::o;612:561::-;721:29;712:5;:38;;;;;;;;:::i;:::-;;708:465;;;766:34;;-1:-1:-1;;;766:34:77;;60847:2:184;766:34:77;;;60829:21:184;60886:2;60866:18;;;60859:30;60925:26;60905:18;;;60898:54;60969:18;;766:34:77;60645:348:184;708:465:77;830:35;821:5;:44;;;;;;;;:::i;:::-;;817:356;;;881:41;;-1:-1:-1;;;881:41:77;;61200:2:184;881:41:77;;;61182:21:184;61239:2;61219:18;;;61212:30;61278:33;61258:18;;;61251:61;61329:18;;881:41:77;60998:355:184;817:356:77;952:30;943:5;:39;;;;;;;;:::i;:::-;;939:234;;;998:44;;-1:-1:-1;;;998:44:77;;61560:2:184;998:44:77;;;61542:21:184;61599:2;61579:18;;;61572:30;61638:34;61618:18;;;61611:62;-1:-1:-1;;;61689:18:184;;;61682:32;61731:19;;998:44:77;61358:398:184;939:234:77;1072:30;1063:5;:39;;;;;;;;:::i;:::-;;1059:114;;;1118:44;;-1:-1:-1;;;1118:44:77;;61963:2:184;1118:44:77;;;61945:21:184;62002:2;61982:18;;;61975:30;62041:34;62021:18;;;62014:62;-1:-1:-1;;;62092:18:184;;;62085:32;62134:19;;1118:44:77;61761:398:184;5810:1603:77;5936:7;;6860:66;6847:79;;6843:161;;;-1:-1:-1;6958:1:77;;-1:-1:-1;6962:30:77;6942:51;;6843:161;7017:1;:7;;7022:2;7017:7;;:18;;;;;7028:1;:7;;7033:2;7028:7;;7017:18;7013:100;;;-1:-1:-1;7067:1:77;;-1:-1:-1;7071:30:77;7051:51;;7013:100;7224:24;;;7207:14;7224:24;;;;;;;;;62391:25:184;;;62464:4;62452:17;;62432:18;;;62425:45;;;;62486:18;;;62479:34;;;62529:18;;;62522:34;;;7224:24:77;;62363:19:184;;7224:24:77;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;7224:24:77;;-1:-1:-1;;7224:24:77;;;-1:-1:-1;;;;;;;7262:20:77;;7258:101;;7314:1;7318:29;7298:50;;;;;;;7258:101;7377:6;-1:-1:-1;7385:20:77;;-1:-1:-1;5810:1603:77;;;;;;;;:::o;4883:336::-;4993:7;;-1:-1:-1;;;;;5038:80:77;;4993:7;5144:25;5160:3;5145:18;;;5167:2;5144:25;:::i;:::-;5128:42;;5187:25;5198:4;5204:1;5207;5210;5187:10;:25::i;:::-;5180:32;;;;;;4883:336;;;;;;:::o;14:378:184:-;88:8;98:6;152:3;145:4;137:6;133:17;129:27;119:55;;170:1;167;160:12;119:55;-1:-1:-1;193:20:184;;-1:-1:-1;;;;;225:30:184;;222:50;;;268:1;265;258:12;222:50;305:4;297:6;293:17;281:29;;365:3;358:4;348:6;345:1;341:14;333:6;329:27;325:38;322:47;319:67;;;382:1;379;372:12;397:466;501:6;509;562:2;550:9;541:7;537:23;533:32;530:52;;;578:1;575;568:12;530:52;618:9;605:23;-1:-1:-1;;;;;643:6:184;640:30;637:50;;;683:1;680;673:12;637:50;722:81;795:7;786:6;775:9;771:22;722:81;:::i;:::-;822:8;;696:107;;-1:-1:-1;397:466:184;-1:-1:-1;;;;397:466:184:o;1232:131::-;-1:-1:-1;;;;;1307:31:184;;1297:42;;1287:70;;1353:1;1350;1343:12;1368:134;1436:20;;1465:31;1436:20;1465:31;:::i;:::-;1368:134;;;:::o;1507:667::-;1602:6;1610;1618;1626;1634;1687:3;1675:9;1666:7;1662:23;1658:33;1655:53;;;1704:1;1701;1694:12;1655:53;1743:9;1730:23;1762:31;1787:5;1762:31;:::i;:::-;1812:5;-1:-1:-1;1869:2:184;1854:18;;1841:32;1882:33;1841:32;1882:33;:::i;:::-;1934:7;-1:-1:-1;1993:2:184;1978:18;;1965:32;2006:33;1965:32;2006:33;:::i;:::-;1507:667;;;;-1:-1:-1;2058:7:184;;2112:2;2097:18;;2084:32;;-1:-1:-1;2163:3:184;2148:19;2135:33;;1507:667;-1:-1:-1;;1507:667:184:o;2674:632::-;2845:2;2897:21;;;2967:13;;2870:18;;;2989:22;;;2816:4;;2845:2;3068:15;;;;3042:2;3027:18;;;2816:4;3111:169;3125:6;3122:1;3119:13;3111:169;;;3186:13;;3174:26;;3255:15;;;;3220:12;;;;3147:1;3140:9;3111:169;;;-1:-1:-1;3297:3:184;;2674:632;-1:-1:-1;;;;;;2674:632:184:o;3311:163::-;3379:5;3424:2;3415:6;3410:3;3406:16;3402:25;3399:45;;;3440:1;3437;3430:12;3399:45;-1:-1:-1;3462:6:184;3311:163;-1:-1:-1;3311:163:184:o;3479:348::-;3531:8;3541:6;3595:3;3588:4;3580:6;3576:17;3572:27;3562:55;;3613:1;3610;3603:12;3562:55;-1:-1:-1;3636:20:184;;-1:-1:-1;;;;;3668:30:184;;3665:50;;;3711:1;3708;3701:12;3665:50;3748:4;3740:6;3736:17;3724:29;;3800:3;3793:4;3784:6;3776;3772:19;3768:30;3765:39;3762:59;;;3817:1;3814;3807:12;3832:554;3947:6;3955;3963;4016:3;4004:9;3995:7;3991:23;3987:33;3984:53;;;4033:1;4030;4023:12;3984:53;4056:62;4110:7;4099:9;4056:62;:::i;:::-;4046:72;;4169:2;4158:9;4154:18;4141:32;-1:-1:-1;;;;;4188:6:184;4185:30;4182:50;;;4228:1;4225;4218:12;4182:50;4267:59;4318:7;4309:6;4298:9;4294:22;4267:59;:::i;:::-;3832:554;;4345:8;;-1:-1:-1;4241:85:184;;-1:-1:-1;;;;3832:554:184:o;4391:271::-;4474:6;4527:2;4515:9;4506:7;4502:23;4498:32;4495:52;;;4543:1;4540;4533:12;4495:52;4582:9;4569:23;4601:31;4626:5;4601:31;:::i;:::-;4651:5;4391:271;-1:-1:-1;;;4391:271:184:o;4667:474::-;4762:6;4770;4778;4831:2;4819:9;4810:7;4806:23;4802:32;4799:52;;;4847:1;4844;4837:12;4799:52;4886:9;4873:23;4905:31;4930:5;4905:31;:::i;:::-;4955:5;-1:-1:-1;5012:2:184;4997:18;;4984:32;5025:33;4984:32;5025:33;:::i;:::-;4667:474;;5077:7;;-1:-1:-1;;;5131:2:184;5116:18;;;;5103:32;;4667:474::o;5146:180::-;5205:6;5258:2;5246:9;5237:7;5233:23;5229:32;5226:52;;;5274:1;5271;5264:12;5226:52;-1:-1:-1;5297:23:184;;5146:180;-1:-1:-1;5146:180:184:o;5331:813::-;5471:6;5479;5487;5495;5548:2;5536:9;5527:7;5523:23;5519:32;5516:52;;;5564:1;5561;5554:12;5516:52;5604:9;5591:23;-1:-1:-1;;;;;5674:2:184;5666:6;5663:14;5660:34;;;5690:1;5687;5680:12;5660:34;5729:81;5802:7;5793:6;5782:9;5778:22;5729:81;:::i;:::-;5829:8;;-1:-1:-1;5703:107:184;-1:-1:-1;5917:2:184;5902:18;;5889:32;;-1:-1:-1;5933:16:184;;;5930:36;;;5962:1;5959;5952:12;5930:36;;6001:83;6076:7;6065:8;6054:9;6050:24;6001:83;:::i;:::-;5331:813;;;;-1:-1:-1;6103:8:184;-1:-1:-1;;;;5331:813:184:o;6862:1252::-;7062:6;7070;7078;7086;7094;7102;7110;7118;7171:3;7159:9;7150:7;7146:23;7142:33;7139:53;;;7188:1;7185;7178:12;7139:53;7227:9;7214:23;7246:31;7271:5;7246:31;:::i;:::-;7296:5;-1:-1:-1;7353:2:184;7338:18;;7325:32;7366:33;7325:32;7366:33;:::i;:::-;7418:7;-1:-1:-1;7472:2:184;7457:18;;7444:32;;-1:-1:-1;7523:2:184;7508:18;;7495:32;;-1:-1:-1;7578:3:184;7563:19;;7550:33;-1:-1:-1;;;;;7632:14:184;;;7629:34;;;7659:1;7656;7649:12;7629:34;7698:81;7771:7;7762:6;7751:9;7747:22;7698:81;:::i;:::-;7798:8;;-1:-1:-1;7672:107:184;-1:-1:-1;7886:3:184;7871:19;;7858:33;;-1:-1:-1;7903:16:184;;;7900:36;;;7932:1;7929;7922:12;7900:36;;7971:83;8046:7;8035:8;8024:9;8020:24;7971:83;:::i;:::-;6862:1252;;;;-1:-1:-1;6862:1252:184;;-1:-1:-1;6862:1252:184;;;;;;8073:8;-1:-1:-1;;;6862:1252:184:o;8119:1518::-;8383:6;8391;8399;8407;8415;8423;8431;8439;8492:3;8480:9;8471:7;8467:23;8463:33;8460:53;;;8509:1;8506;8499:12;8460:53;8549:9;8536:23;-1:-1:-1;;;;;8619:2:184;8611:6;8608:14;8605:34;;;8635:1;8632;8625:12;8605:34;8674:81;8747:7;8738:6;8727:9;8723:22;8674:81;:::i;:::-;8774:8;;-1:-1:-1;8648:107:184;-1:-1:-1;8862:2:184;8847:18;;8834:32;;-1:-1:-1;8878:16:184;;;8875:36;;;8907:1;8904;8897:12;8875:36;8946:83;9021:7;9010:8;8999:9;8995:24;8946:83;:::i;:::-;9048:8;;-1:-1:-1;8920:109:184;-1:-1:-1;9136:2:184;9121:18;;9108:32;;-1:-1:-1;9152:16:184;;;9149:36;;;9181:1;9178;9171:12;9149:36;9220:83;9295:7;9284:8;9273:9;9269:24;9220:83;:::i;:::-;9322:8;;-1:-1:-1;9194:109:184;-1:-1:-1;9410:2:184;9395:18;;9382:32;;-1:-1:-1;9426:16:184;;;9423:36;;;9455:1;9452;9445:12;10508:127;10569:10;10564:3;10560:20;10557:1;10550:31;10600:4;10597:1;10590:15;10624:4;10621:1;10614:15;10640:253;10712:2;10706:9;10754:4;10742:17;;-1:-1:-1;;;;;10774:34:184;;10810:22;;;10771:62;10768:88;;;10836:18;;:::i;:::-;10872:2;10865:22;10640:253;:::o;10898:257::-;10970:4;10964:11;;;11002:17;;-1:-1:-1;;;;;11034:34:184;;11070:22;;;11031:62;11028:88;;;11096:18;;:::i;11160:275::-;11231:2;11225:9;11296:2;11277:13;;-1:-1:-1;;11273:27:184;11261:40;;-1:-1:-1;;;;;11316:34:184;;11352:22;;;11313:62;11310:88;;;11378:18;;:::i;:::-;11414:2;11407:22;11160:275;;-1:-1:-1;11160:275:184:o;11440:121::-;11525:10;11518:5;11514:22;11507:5;11504:33;11494:61;;11551:1;11548;11541:12;11566:132;11633:20;;11662:30;11633:20;11662:30;:::i;11703:194::-;11774:4;-1:-1:-1;;;;;11799:6:184;11796:30;11793:56;;;11829:18;;:::i;:::-;-1:-1:-1;11874:1:184;11870:14;11886:4;11866:25;;11703:194::o;11902:759::-;11967:5;12020:3;12013:4;12005:6;12001:17;11997:27;11987:55;;12038:1;12035;12028:12;11987:55;12074:6;12061:20;12100:4;12124:71;12140:54;12191:2;12140:54;:::i;:::-;12124:71;:::i;:::-;12229:15;;;12315:1;12311:10;;;;12299:23;;12295:32;;;12260:12;;;;12339:15;;;12336:35;;;12367:1;12364;12357:12;12336:35;12403:2;12395:6;12391:15;12415:217;12431:6;12426:3;12423:15;12415:217;;;12511:3;12498:17;12528:31;12553:5;12528:31;:::i;:::-;12572:18;;12610:12;;;;12448;;12415:217;;;-1:-1:-1;12650:5:184;11902:759;-1:-1:-1;;;;;;11902:759:184:o;12666:673::-;12720:5;12773:3;12766:4;12758:6;12754:17;12750:27;12740:55;;12791:1;12788;12781:12;12740:55;12827:6;12814:20;12853:4;12877:71;12893:54;12944:2;12893:54;:::i;12877:71::-;12982:15;;;13068:1;13064:10;;;;13052:23;;13048:32;;;13013:12;;;;13092:15;;;13089:35;;;13120:1;13117;13110:12;13089:35;13156:2;13148:6;13144:15;13168:142;13184:6;13179:3;13176:15;13168:142;;;13250:17;;13238:30;;13288:12;;;;13201;;13168:142;;13344:939;13401:5;13449:4;13437:9;13432:3;13428:19;13424:30;13421:50;;;13467:1;13464;13457:12;13421:50;13489:22;;:::i;:::-;13480:31;;13534:29;13553:9;13534:29;:::i;:::-;13527:5;13520:44;13596:38;13630:2;13619:9;13615:18;13596:38;:::i;:::-;13591:2;13584:5;13580:14;13573:62;13667:38;13701:2;13690:9;13686:18;13667:38;:::i;:::-;13662:2;13655:5;13651:14;13644:62;13766:2;13755:9;13751:18;13738:32;13733:2;13726:5;13722:14;13715:56;13804:38;13837:3;13826:9;13822:19;13804:38;:::i;:::-;13798:3;13791:5;13787:15;13780:63;13894:3;13883:9;13879:19;13866:33;-1:-1:-1;;;;;13959:2:184;13951:6;13948:14;13945:34;;;13975:1;13972;13965:12;13945:34;14012:68;14076:3;14067:6;14056:9;14052:22;14012:68;:::i;:::-;14006:3;13999:5;13995:15;13988:93;14134:3;14123:9;14119:19;14106:33;14090:49;;14164:2;14154:8;14151:16;14148:36;;;14180:1;14177;14170:12;14148:36;;14217:59;14272:3;14261:8;14250:9;14246:24;14217:59;:::i;:::-;14211:3;14204:5;14200:15;14193:84;;13344:939;;;;:::o;14288:351::-;14375:6;14428:2;14416:9;14407:7;14403:23;14399:32;14396:52;;;14444:1;14441;14434:12;14396:52;14484:9;14471:23;-1:-1:-1;;;;;14509:6:184;14506:30;14503:50;;;14549:1;14546;14539:12;14503:50;14572:61;14625:7;14616:6;14605:9;14601:22;14572:61;:::i;:::-;14562:71;14288:351;-1:-1:-1;;;;14288:351:184:o;14644:269::-;14701:6;14754:2;14742:9;14733:7;14729:23;14725:32;14722:52;;;14770:1;14767;14760:12;14722:52;14809:9;14796:23;14859:4;14852:5;14848:16;14841:5;14838:27;14828:55;;14879:1;14876;14869:12;14918:118;15004:5;14997:13;14990:21;14983:5;14980:32;14970:60;;15026:1;15023;15016:12;15041:951;15197:6;15205;15213;15221;15229;15282:3;15270:9;15261:7;15257:23;15253:33;15250:53;;;15299:1;15296;15289:12;15250:53;15339:9;15326:23;-1:-1:-1;;;;;15409:2:184;15401:6;15398:14;15395:34;;;15425:1;15422;15415:12;15395:34;15448:22;;;;15504:3;15486:16;;;15482:26;15479:46;;;15521:1;15518;15511:12;15479:46;15544:2;;-1:-1:-1;15599:2:184;15584:18;;15571:32;;15615:16;;;15612:36;;;15644:1;15641;15634:12;15612:36;;15683:83;15758:7;15747:8;15736:9;15732:24;15683:83;:::i;:::-;15785:8;;-1:-1:-1;15657:109:184;-1:-1:-1;;15867:2:184;15852:18;;15839:32;;-1:-1:-1;15921:2:184;15906:18;;15893:32;15934:28;15893:32;15934:28;:::i;:::-;15981:5;15971:15;;;15041:951;;;;;;;;:::o;15997:406::-;16083:6;16091;16144:2;16132:9;16123:7;16119:23;16115:32;16112:52;;;16160:1;16157;16150:12;16112:52;16199:9;16186:23;16218:31;16243:5;16218:31;:::i;:::-;16268:5;-1:-1:-1;16325:2:184;16310:18;;16297:32;16338:33;16297:32;16338:33;:::i;:::-;16390:7;16380:17;;;15997:406;;;;;:::o;16408:862::-;16474:5;16522:4;16510:9;16505:3;16501:19;16497:30;16494:50;;;16540:1;16537;16530:12;16494:50;16562:22;;:::i;:::-;16553:31;;16620:9;16607:23;-1:-1:-1;;;;;16690:2:184;16682:6;16679:14;16676:34;;;16706:1;16703;16696:12;16676:34;16744:6;16733:9;16729:22;16719:32;;16789:3;16782:4;16778:2;16774:13;16770:23;16760:51;;16807:1;16804;16797:12;16760:51;16843:2;16830:16;16865:4;16888:2;16884;16881:10;16878:36;;;16894:18;;:::i;:::-;16936:53;16979:2;16960:13;;-1:-1:-1;;16956:27:184;16952:36;;16936:53;:::i;:::-;16923:66;;17012:2;17005:5;16998:17;17052:3;17047:2;17042;17038;17034:11;17030:20;17027:29;17024:49;;;17069:1;17066;17059:12;17024:49;17124:2;17119;17115;17111:11;17106:2;17099:5;17095:14;17082:45;17168:1;17163:2;17158;17151:5;17147:14;17143:23;17136:34;17193:5;17186;17179:20;17259:2;17248:9;17244:18;17231:32;17226:2;17219:5;17215:14;17208:56;;;;;16408:862;;;;:::o;17275:983::-;17444:6;17452;17460;17468;17476;17529:3;17517:9;17508:7;17504:23;17500:33;17497:53;;;17546:1;17543;17536:12;17497:53;17585:9;17572:23;17604:31;17629:5;17604:31;:::i;:::-;17654:5;-1:-1:-1;17711:2:184;17696:18;;17683:32;17724:33;17683:32;17724:33;:::i;:::-;17776:7;-1:-1:-1;17834:2:184;17819:18;;17806:32;-1:-1:-1;;;;;17887:14:184;;;17884:34;;;17914:1;17911;17904:12;17884:34;17937:70;17999:7;17990:6;17979:9;17975:22;17937:70;:::i;:::-;17927:80;;18060:2;18049:9;18045:18;18032:32;18016:48;;18089:2;18079:8;18076:16;18073:36;;;18105:1;18102;18095:12;18073:36;;18128:72;18192:7;18181:8;18170:9;18166:24;18128:72;:::i;:::-;17275:983;;;;-1:-1:-1;17275:983:184;;18247:3;18232:19;18219:33;;17275:983;-1:-1:-1;;;17275:983:184:o;18495:512::-;18606:6;18614;18667:2;18655:9;18646:7;18642:23;18638:32;18635:52;;;18683:1;18680;18673:12;18635:52;18722:9;18709:23;18741:31;18766:5;18741:31;:::i;:::-;18791:5;-1:-1:-1;18847:2:184;18832:18;;18819:32;-1:-1:-1;;;;;18863:30:184;;18860:50;;;18906:1;18903;18896:12;18860:50;18929:72;18993:7;18984:6;18973:9;18969:22;18929:72;:::i;:::-;18919:82;;;18495:512;;;;;:::o;19012:435::-;19065:3;19103:5;19097:12;19130:6;19125:3;19118:19;19156:4;19185:2;19180:3;19176:12;19169:19;;19222:2;19215:5;19211:14;19243:1;19253:169;19267:6;19264:1;19261:13;19253:169;;;19328:13;;19316:26;;19362:12;;;;19397:15;;;;19289:1;19282:9;19253:169;;;-1:-1:-1;19438:3:184;;19012:435;-1:-1:-1;;;;;19012:435:184:o;19452:261::-;19631:2;19620:9;19613:21;19594:4;19651:56;19703:2;19692:9;19688:18;19680:6;19651:56;:::i;19944:411::-;20015:6;20023;20076:2;20064:9;20055:7;20051:23;20047:32;20044:52;;;20092:1;20089;20082:12;20044:52;20132:9;20119:23;-1:-1:-1;;;;;20157:6:184;20154:30;20151:50;;;20197:1;20194;20187:12;20151:50;20236:59;20287:7;20278:6;20267:9;20263:22;20236:59;:::i;20770:315::-;20838:6;20846;20899:2;20887:9;20878:7;20874:23;20870:32;20867:52;;;20915:1;20912;20905:12;20867:52;20954:9;20941:23;20973:31;20998:5;20973:31;:::i;:::-;21023:5;21075:2;21060:18;;;;21047:32;;-1:-1:-1;;;20770:315:184:o;21814:525::-;21900:6;21908;21916;21924;21977:3;21965:9;21956:7;21952:23;21948:33;21945:53;;;21994:1;21991;21984:12;21945:53;22033:9;22020:23;22052:31;22077:5;22052:31;:::i;:::-;22102:5;-1:-1:-1;22154:2:184;22139:18;;22126:32;;-1:-1:-1;22210:2:184;22195:18;;22182:32;22223:33;22182:32;22223:33;:::i;:::-;21814:525;;;;-1:-1:-1;22275:7:184;;22329:2;22314:18;22301:32;;-1:-1:-1;;21814:525:184:o;22344:472::-;22408:3;22446:5;22440:12;22473:6;22468:3;22461:19;22499:4;22528:2;22523:3;22519:12;22512:19;;22565:2;22558:5;22554:14;22586:1;22596:195;22610:6;22607:1;22604:13;22596:195;;;22675:13;;-1:-1:-1;;;;;22671:39:184;22659:52;;22731:12;;;;22766:15;;;;22707:1;22625:9;22596:195;;22821:494;23096:2;23085:9;23078:21;23059:4;23122:67;23185:2;23174:9;23170:18;23162:6;23122:67;:::i;:::-;23237:9;23229:6;23225:22;23220:2;23209:9;23205:18;23198:50;23265:44;23302:6;23294;23265:44;:::i;23320:572::-;23434:6;23442;23450;23503:2;23491:9;23482:7;23478:23;23474:32;23471:52;;;23519:1;23516;23509:12;23471:52;23558:9;23545:23;23577:31;23602:5;23577:31;:::i;:::-;23627:5;-1:-1:-1;23683:2:184;23668:18;;23655:32;-1:-1:-1;;;;;23699:30:184;;23696:50;;;23742:1;23739;23732:12;23696:50;23765:70;23827:7;23818:6;23807:9;23803:22;23765:70;:::i;:::-;23755:80;;;23882:2;23871:9;23867:18;23854:32;23844:42;;23320:572;;;;;:::o;23897:254::-;23991:6;24044:2;24032:9;24023:7;24019:23;24015:32;24012:52;;;24060:1;24057;24050:12;24012:52;24083:62;24137:7;24126:9;24083:62;:::i;24156:127::-;24217:10;24212:3;24208:20;24205:1;24198:31;24248:4;24245:1;24238:15;24272:4;24269:1;24262:15;24288:127;24349:10;24344:3;24340:20;24337:1;24330:31;24380:4;24377:1;24370:15;24404:4;24401:1;24394:15;24420:135;24459:3;-1:-1:-1;;24480:17:184;;24477:43;;;24500:18;;:::i;:::-;-1:-1:-1;24547:1:184;24536:13;;24420:135::o;25562:349::-;25764:2;25746:21;;;25803:2;25783:18;;;25776:30;25842:27;25837:2;25822:18;;25815:55;25902:2;25887:18;;25562:349::o;25916:339::-;26024:4;26082:11;26069:25;26176:2;26172:7;26161:8;26145:14;26141:29;26137:43;26117:18;26113:68;26103:96;;26195:1;26192;26185:12;26103:96;26216:33;;;;;25916:339;-1:-1:-1;;25916:339:184:o;26260:545::-;26353:4;26359:6;26419:11;26406:25;26513:2;26509:7;26498:8;26482:14;26478:29;26474:43;26454:18;26450:68;26440:96;;26532:1;26529;26522:12;26440:96;26559:33;;26611:20;;;-1:-1:-1;;;;;;26643:30:184;;26640:50;;;26686:1;26683;26676:12;26640:50;26719:4;26707:17;;-1:-1:-1;26770:1:184;26766:14;;;26750;26746:35;26736:46;;26733:66;;;26795:1;26792;26785:12;28715:684;28917:2;28902:18;;28942:20;;28971:31;28942:20;28971:31;:::i;:::-;-1:-1:-1;;;;;29067:14:184;;;29049:33;;29131:4;29119:17;;29106:31;;29146:33;29106:31;29146:33;:::i;:::-;29217:16;29210:4;29195:20;;29188:46;29283:4;29271:17;;29258:31;29298:32;29258:31;29298:32;:::i;:::-;29381:10;29372:7;29368:24;29361:4;29350:9;29346:20;29339:54;;28715:684;;;;:::o;29404:390::-;29563:2;29552:9;29545:21;29602:6;29597:2;29586:9;29582:18;29575:34;29659:6;29651;29646:2;29635:9;29631:18;29618:48;29715:1;29686:22;;;29710:2;29682:31;;;29675:42;;;;29778:2;29757:15;;;-1:-1:-1;;29753:29:184;29738:45;29734:54;;29404:390;-1:-1:-1;29404:390:184:o;29799:251::-;29869:6;29922:2;29910:9;29901:7;29897:23;29893:32;29890:52;;;29938:1;29935;29928:12;29890:52;29970:9;29964:16;29989:31;30014:5;29989:31;:::i;30055:406::-;30257:2;30239:21;;;30296:2;30276:18;;;30269:30;30335:34;30330:2;30315:18;;30308:62;-1:-1:-1;;;30401:2:184;30386:18;;30379:40;30451:3;30436:19;;30055:406::o;30466:419::-;30668:2;30650:21;;;30707:2;30687:18;;;30680:30;30746:34;30741:2;30726:18;;30719:62;30817:25;30812:2;30797:18;;30790:53;30875:3;30860:19;;30466:419::o;30890:245::-;30957:6;31010:2;30998:9;30989:7;30985:23;30981:32;30978:52;;;31026:1;31023;31016:12;30978:52;31058:9;31052:16;31077:28;31099:5;31077:28;:::i;31140:404::-;31342:2;31324:21;;;31381:2;31361:18;;;31354:30;31420:34;31415:2;31400:18;;31393:62;-1:-1:-1;;;31486:2:184;31471:18;;31464:38;31534:3;31519:19;;31140:404::o;32948:328::-;33044:4;33102:11;33089:25;33196:3;33192:8;33181;33165:14;33161:29;33157:44;33137:18;33133:69;33123:97;;33216:1;33213;33206:12;33847:241;33903:6;33956:2;33944:9;33935:7;33931:23;33927:32;33924:52;;;33972:1;33969;33962:12;33924:52;34011:9;33998:23;34030:28;34052:5;34030:28;:::i;34093:754::-;34146:3;34191:1;34187;34182:3;34178:11;34174:19;34232:2;34224:5;34218:12;34214:21;34209:3;34202:34;34297:2;34289:4;34282:5;34278:16;34272:23;34268:32;34261:4;34256:3;34252:14;34245:56;34362:2;34354:4;34347:5;34343:16;34337:23;34333:32;34326:4;34321:3;34317:14;34310:56;;34415:4;34408:5;34404:16;34398:23;34391:4;34386:3;34382:14;34375:47;34483:10;34475:4;34468:5;34464:16;34458:23;34454:40;34447:4;34442:3;34438:14;34431:64;34541:4;34534:5;34530:16;34524:23;34579:4;34572;34567:3;34563:14;34556:28;34605:69;34668:4;34663:3;34659:14;34645:12;34605:69;:::i;:::-;34593:81;;34722:4;34715:5;34711:16;34705:23;34770:3;34764:4;34760:14;34753:4;34748:3;34744:14;34737:38;34791:50;34836:4;34820:14;34791:50;:::i;34852:267::-;35037:2;35026:9;35019:21;35000:4;35057:56;35109:2;35098:9;35094:18;35086:6;35057:56;:::i;37578:183::-;37647:6;37700:2;37688:9;37679:7;37675:23;37671:32;37668:52;;;37716:1;37713;37706:12;37668:52;-1:-1:-1;37739:16:184;;37578:183;-1:-1:-1;37578:183:184:o;37766:670::-;37831:5;37884:3;37877:4;37869:6;37865:17;37861:27;37851:55;;37902:1;37899;37892:12;37851:55;37931:6;37925:13;37957:4;37981:71;37997:54;38048:2;37997:54;:::i;37981:71::-;38086:15;;;38172:1;38168:10;;;;38156:23;;38152:32;;;38117:12;;;;38196:15;;;38193:35;;;38224:1;38221;38214:12;38193:35;38260:2;38252:6;38248:15;38272:135;38288:6;38283:3;38280:15;38272:135;;;38354:10;;38342:23;;38385:12;;;;38305;;38272:135;;38441:1238;38588:6;38596;38649:2;38637:9;38628:7;38624:23;38620:32;38617:52;;;38665:1;38662;38655:12;38617:52;38698:9;38692:16;-1:-1:-1;;;;;38768:2:184;38760:6;38757:14;38754:34;;;38784:1;38781;38774:12;38754:34;38822:6;38811:9;38807:22;38797:32;;38867:7;38860:4;38856:2;38852:13;38848:27;38838:55;;38889:1;38886;38879:12;38838:55;38918:2;38912:9;38940:4;38964:71;38980:54;39031:2;38980:54;:::i;38964:71::-;39069:15;;;39151:1;39147:10;;;;39139:19;;39135:28;;;39100:12;;;;39175:19;;;39172:39;;;39207:1;39204;39197:12;39172:39;39231:11;;;;39251:210;39267:6;39262:3;39259:15;39251:210;;;39340:3;39334:10;39357:31;39382:5;39357:31;:::i;:::-;39401:18;;39284:12;;;;39439;;;;39251:210;;;39516:18;;;39510:25;39480:5;;-1:-1:-1;39510:25:184;;-1:-1:-1;;;39547:16:184;;;39544:36;;;39576:1;39573;39566:12;39544:36;;39599:74;39665:7;39654:8;39643:9;39639:24;39599:74;:::i;39684:128::-;39724:3;39755:1;39751:6;39748:1;39745:13;39742:39;;;39761:18;;:::i;:::-;-1:-1:-1;39797:9:184;;39684:128::o;39817:125::-;39857:4;39885:1;39882;39879:8;39876:34;;;39890:18;;:::i;:::-;-1:-1:-1;39927:9:184;;39817:125::o;45851:393::-;-1:-1:-1;;;;;46127:15:184;;;46109:34;;46179:15;;;;46174:2;46159:18;;46152:43;46226:2;46211:18;;46204:34;;;;46059:2;46044:18;;45851:393::o;46249:338::-;46462:6;46451:9;46444:25;46505:2;46500;46489:9;46485:18;46478:30;46425:4;46525:56;46577:2;46566:9;46562:18;46554:6;46525:56;:::i;46592:245::-;46650:6;46703:2;46691:9;46682:7;46678:23;46674:32;46671:52;;;46719:1;46716;46709:12;46671:52;46758:9;46745:23;46777:30;46801:5;46777:30;:::i;47892:195::-;47996:11;;-1:-1:-1;;;;;;47992:54:184;-1:-1:-1;;;;;48048:31:184;;;;47989:91;;;;47976:105;;47892:195::o;48092:758::-;48273:5;48260:19;48288:33;48313:7;48288:33;:::i;:::-;48330:62;48384:7;48378:4;48330:62;:::i;:::-;;48429:1;48423:4;48419:12;48479:2;48472:5;48468:14;48455:28;48492:33;48517:7;48492:33;:::i;:::-;48534:68;48594:7;48582:10;48534:68;:::i;:::-;;48650:2;48643:5;48639:14;48626:28;48663:32;48687:7;48663:32;:::i;:::-;48714:17;;-1:-1:-1;;;;48762:34:184;48825:3;48802:17;;;;-1:-1:-1;;;48798:44:184;48759:84;48740:104;;-1:-1:-1;;48092:758:184:o;54037:202::-;54145:9;54182:51;54218:14;54211:5;54182:51;:::i;:::-;54169:64;54037:202;-1:-1:-1;;54037:202:184:o;56188:555::-;56390:2;56372:21;;;56429:3;56409:18;;;56402:31;-1:-1:-1;;;;;;;;;;;56464:2:184;56449:18;;56442:62;56540:34;56535:2;56520:18;;56513:62;56612:34;56606:3;56591:19;;56584:63;-1:-1:-1;;;56678:3:184;56663:19;;56656:45;56733:3;56718:19;;56188:555::o;57700:666::-;57875:6;57864:9;57857:25;57838:4;57901:2;57939;57934;57923:9;57919:18;57912:30;57971:6;57965:13;58014:6;58009:2;57998:9;57994:18;57987:34;58039:1;58049:140;58063:6;58060:1;58057:13;58049:140;;;58158:14;;;58154:23;;58148:30;58124:17;;;58143:2;58120:26;58113:66;58078:10;;58049:140;;;58207:6;58204:1;58201:13;58198:91;;;58277:1;58272:2;58263:6;58252:9;58248:22;58244:31;58237:42;58198:91;-1:-1:-1;58350:2:184;58329:15;-1:-1:-1;;58325:29:184;58310:45;;;;58357:2;58306:54;;57700:666;-1:-1:-1;;;;57700:666:184:o;58371:290::-;58440:6;58493:2;58481:9;58472:7;58468:23;58464:32;58461:52;;;58509:1;58506;58499:12;58461:52;58535:16;;-1:-1:-1;;;;;;58580:32:184;;58570:43;;58560:71;;58627:1;58624;58617:12;60513:127;60574:10;60569:3;60565:20;60562:1;60555:31;60605:4;60602:1;60595:15;60629:4;60626:1;60619:15","linkReferences":{},"immutableReferences":{"2560":[{"start":1273,"length":32},{"start":4092,"length":32},{"start":4984,"length":32},{"start":7326,"length":32},{"start":10925,"length":32},{"start":11312,"length":32},{"start":16313,"length":32},{"start":17445,"length":32}],"2564":[{"start":1890,"length":32}],"2568":[{"start":1457,"length":32},{"start":4142,"length":32},{"start":5034,"length":32},{"start":7178,"length":32},{"start":10720,"length":32},{"start":16019,"length":32},{"start":17279,"length":32}],"429":[{"start":9863,"length":32}]}},"methodIdentifiers":{"DELEGATION_APPROVAL_TYPEHASH()":"04a4f979","DOMAIN_TYPEHASH()":"20606b70","MAX_STAKER_OPT_OUT_WINDOW_BLOCKS()":"4fc40b61","MAX_WITHDRAWAL_DELAY_BLOCKS()":"ca661c04","STAKER_DELEGATION_TYPEHASH()":"43377382","beaconChainETHStrategy()":"9104c319","calculateCurrentStakerDelegationDigestHash(address,address,uint256)":"1bbce091","calculateDelegationApprovalDigestHash(address,address,address,bytes32,uint256)":"0b9f487a","calculateStakerDelegationDigestHash(address,uint256,address,uint256)":"c94b5111","calculateWithdrawalRoot((address,address,address,uint256,uint32,address[],uint256[]))":"597b36da","completeQueuedWithdrawal((address,address,address,uint256,uint32,address[],uint256[]),address[],uint256,bool)":"60d7faed","completeQueuedWithdrawals((address,address,address,uint256,uint32,address[],uint256[])[],address[][],uint256[],bool[])":"33404396","cumulativeWithdrawalsQueued(address)":"a1788484","decreaseDelegatedShares(address,address,uint256)":"132d4967","delegateTo(address,(bytes,uint256),bytes32)":"eea9064b","delegateToBySignature(address,address,(bytes,uint256),(bytes,uint256),bytes32)":"7f548071","delegatedTo(address)":"65da1264","delegationApprover(address)":"3cdeb5e0","delegationApproverSaltIsSpent(address,bytes32)":"bb45fef2","domainSeparator()":"f698da25","eigenPodManager()":"4665bcda","getDelegatableShares(address)":"cf80873e","getOperatorShares(address,address[])":"90041347","getWithdrawalDelay(address[])":"0449ca39","increaseDelegatedShares(address,address,uint256)":"28a573ae","initialize(address,address,uint256,uint256,address[],uint256[])":"22bf40e4","isDelegated(address)":"3e28391d","isOperator(address)":"6d70f7ae","minWithdrawalDelayBlocks()":"c448feb8","modifyOperatorDetails((address,address,uint32))":"f16172b0","operatorDetails(address)":"c5e480db","operatorShares(address,address)":"778e55f3","owner()":"8da5cb5b","pause(uint256)":"136439dd","pauseAll()":"595c6a67","paused()":"5c975abb","paused(uint8)":"5ac86ab7","pauserRegistry()":"886f1195","pendingWithdrawals(bytes32)":"b7f06ebe","queueWithdrawals((address[],uint256[],address)[])":"0dd8dd02","registerAsOperator((address,address,uint32),string)":"0f589e59","renounceOwnership()":"715018a6","setMinWithdrawalDelayBlocks(uint256)":"635bbd10","setPauserRegistry(address)":"10d67a2f","setStrategyWithdrawalDelayBlocks(address[],uint256[])":"1522bf02","slasher()":"b1344271","stakerNonce(address)":"29c77d4f","stakerOptOutWindowBlocks(address)":"16928365","strategyManager()":"39b70e38","strategyWithdrawalDelayBlocks(address)":"c488375a","transferOwnership(address)":"f2fde38b","undelegate(address)":"da8be864","unpause(uint256)":"fabc1cbc","updateOperatorMetadataURI(string)":"99be81c8"},"rawMetadata":"{\"compiler\":{\"version\":\"0.8.12+commit.f00d7308\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"contract IStrategyManager\",\"name\":\"_strategyManager\",\"type\":\"address\"},{\"internalType\":\"contract ISlasher\",\"name\":\"_slasher\",\"type\":\"address\"},{\"internalType\":\"contract IEigenPodManager\",\"name\":\"_eigenPodManager\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"version\",\"type\":\"uint8\"}],\"name\":\"Initialized\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"previousValue\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newValue\",\"type\":\"uint256\"}],\"name\":\"MinWithdrawalDelayBlocksSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"__deprecated_earningsReceiver\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"delegationApprover\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"stakerOptOutWindowBlocks\",\"type\":\"uint32\"}],\"indexed\":false,\"internalType\":\"struct IDelegationManager.OperatorDetails\",\"name\":\"newOperatorDetails\",\"type\":\"tuple\"}],\"name\":\"OperatorDetailsModified\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"metadataURI\",\"type\":\"string\"}],\"name\":\"OperatorMetadataURIUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"__deprecated_earningsReceiver\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"delegationApprover\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"stakerOptOutWindowBlocks\",\"type\":\"uint32\"}],\"indexed\":false,\"internalType\":\"struct IDelegationManager.OperatorDetails\",\"name\":\"operatorDetails\",\"type\":\"tuple\"}],\"name\":\"OperatorRegistered\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"staker\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"contract IStrategy\",\"name\":\"strategy\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"shares\",\"type\":\"uint256\"}],\"name\":\"OperatorSharesDecreased\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"staker\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"contract IStrategy\",\"name\":\"strategy\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"shares\",\"type\":\"uint256\"}],\"name\":\"OperatorSharesIncreased\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newPausedStatus\",\"type\":\"uint256\"}],\"name\":\"Paused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract IPauserRegistry\",\"name\":\"pauserRegistry\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"contract IPauserRegistry\",\"name\":\"newPauserRegistry\",\"type\":\"address\"}],\"name\":\"PauserRegistrySet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"staker\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"}],\"name\":\"StakerDelegated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"staker\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"}],\"name\":\"StakerForceUndelegated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"staker\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"}],\"name\":\"StakerUndelegated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract IStrategy\",\"name\":\"strategy\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"previousValue\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newValue\",\"type\":\"uint256\"}],\"name\":\"StrategyWithdrawalDelayBlocksSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newPausedStatus\",\"type\":\"uint256\"}],\"name\":\"Unpaused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"withdrawalRoot\",\"type\":\"bytes32\"}],\"name\":\"WithdrawalCompleted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"withdrawalRoot\",\"type\":\"bytes32\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"staker\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"delegatedTo\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"withdrawer\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"internalType\":\"uint32\",\"name\":\"startBlock\",\"type\":\"uint32\"},{\"internalType\":\"contract IStrategy[]\",\"name\":\"strategies\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"shares\",\"type\":\"uint256[]\"}],\"indexed\":false,\"internalType\":\"struct IDelegationManager.Withdrawal\",\"name\":\"withdrawal\",\"type\":\"tuple\"}],\"name\":\"WithdrawalQueued\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"DELEGATION_APPROVAL_TYPEHASH\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"DOMAIN_TYPEHASH\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"MAX_STAKER_OPT_OUT_WINDOW_BLOCKS\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"MAX_WITHDRAWAL_DELAY_BLOCKS\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"STAKER_DELEGATION_TYPEHASH\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"beaconChainETHStrategy\",\"outputs\":[{\"internalType\":\"contract IStrategy\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"staker\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"expiry\",\"type\":\"uint256\"}],\"name\":\"calculateCurrentStakerDelegationDigestHash\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"staker\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_delegationApprover\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"approverSalt\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"expiry\",\"type\":\"uint256\"}],\"name\":\"calculateDelegationApprovalDigestHash\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"staker\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_stakerNonce\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"expiry\",\"type\":\"uint256\"}],\"name\":\"calculateStakerDelegationDigestHash\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"staker\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"delegatedTo\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"withdrawer\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"internalType\":\"uint32\",\"name\":\"startBlock\",\"type\":\"uint32\"},{\"internalType\":\"contract IStrategy[]\",\"name\":\"strategies\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"shares\",\"type\":\"uint256[]\"}],\"internalType\":\"struct IDelegationManager.Withdrawal\",\"name\":\"withdrawal\",\"type\":\"tuple\"}],\"name\":\"calculateWithdrawalRoot\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"staker\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"delegatedTo\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"withdrawer\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"internalType\":\"uint32\",\"name\":\"startBlock\",\"type\":\"uint32\"},{\"internalType\":\"contract IStrategy[]\",\"name\":\"strategies\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"shares\",\"type\":\"uint256[]\"}],\"internalType\":\"struct IDelegationManager.Withdrawal\",\"name\":\"withdrawal\",\"type\":\"tuple\"},{\"internalType\":\"contract IERC20[]\",\"name\":\"tokens\",\"type\":\"address[]\"},{\"internalType\":\"uint256\",\"name\":\"middlewareTimesIndex\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"receiveAsTokens\",\"type\":\"bool\"}],\"name\":\"completeQueuedWithdrawal\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"staker\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"delegatedTo\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"withdrawer\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"internalType\":\"uint32\",\"name\":\"startBlock\",\"type\":\"uint32\"},{\"internalType\":\"contract IStrategy[]\",\"name\":\"strategies\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"shares\",\"type\":\"uint256[]\"}],\"internalType\":\"struct IDelegationManager.Withdrawal[]\",\"name\":\"withdrawals\",\"type\":\"tuple[]\"},{\"internalType\":\"contract IERC20[][]\",\"name\":\"tokens\",\"type\":\"address[][]\"},{\"internalType\":\"uint256[]\",\"name\":\"middlewareTimesIndexes\",\"type\":\"uint256[]\"},{\"internalType\":\"bool[]\",\"name\":\"receiveAsTokens\",\"type\":\"bool[]\"}],\"name\":\"completeQueuedWithdrawals\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"cumulativeWithdrawalsQueued\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"staker\",\"type\":\"address\"},{\"internalType\":\"contract IStrategy\",\"name\":\"strategy\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"shares\",\"type\":\"uint256\"}],\"name\":\"decreaseDelegatedShares\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"signature\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"expiry\",\"type\":\"uint256\"}],\"internalType\":\"struct ISignatureUtils.SignatureWithExpiry\",\"name\":\"approverSignatureAndExpiry\",\"type\":\"tuple\"},{\"internalType\":\"bytes32\",\"name\":\"approverSalt\",\"type\":\"bytes32\"}],\"name\":\"delegateTo\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"staker\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"signature\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"expiry\",\"type\":\"uint256\"}],\"internalType\":\"struct ISignatureUtils.SignatureWithExpiry\",\"name\":\"stakerSignatureAndExpiry\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"signature\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"expiry\",\"type\":\"uint256\"}],\"internalType\":\"struct ISignatureUtils.SignatureWithExpiry\",\"name\":\"approverSignatureAndExpiry\",\"type\":\"tuple\"},{\"internalType\":\"bytes32\",\"name\":\"approverSalt\",\"type\":\"bytes32\"}],\"name\":\"delegateToBySignature\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"delegatedTo\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"}],\"name\":\"delegationApprover\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"name\":\"delegationApproverSaltIsSpent\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"domainSeparator\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"eigenPodManager\",\"outputs\":[{\"internalType\":\"contract IEigenPodManager\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"staker\",\"type\":\"address\"}],\"name\":\"getDelegatableShares\",\"outputs\":[{\"internalType\":\"contract IStrategy[]\",\"name\":\"\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"\",\"type\":\"uint256[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"},{\"internalType\":\"contract IStrategy[]\",\"name\":\"strategies\",\"type\":\"address[]\"}],\"name\":\"getOperatorShares\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"\",\"type\":\"uint256[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract IStrategy[]\",\"name\":\"strategies\",\"type\":\"address[]\"}],\"name\":\"getWithdrawalDelay\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"staker\",\"type\":\"address\"},{\"internalType\":\"contract IStrategy\",\"name\":\"strategy\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"shares\",\"type\":\"uint256\"}],\"name\":\"increaseDelegatedShares\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"initialOwner\",\"type\":\"address\"},{\"internalType\":\"contract IPauserRegistry\",\"name\":\"_pauserRegistry\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"initialPausedStatus\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_minWithdrawalDelayBlocks\",\"type\":\"uint256\"},{\"internalType\":\"contract IStrategy[]\",\"name\":\"_strategies\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"_withdrawalDelayBlocks\",\"type\":\"uint256[]\"}],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"staker\",\"type\":\"address\"}],\"name\":\"isDelegated\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"}],\"name\":\"isOperator\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"minWithdrawalDelayBlocks\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"__deprecated_earningsReceiver\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"delegationApprover\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"stakerOptOutWindowBlocks\",\"type\":\"uint32\"}],\"internalType\":\"struct IDelegationManager.OperatorDetails\",\"name\":\"newOperatorDetails\",\"type\":\"tuple\"}],\"name\":\"modifyOperatorDetails\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"}],\"name\":\"operatorDetails\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"__deprecated_earningsReceiver\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"delegationApprover\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"stakerOptOutWindowBlocks\",\"type\":\"uint32\"}],\"internalType\":\"struct IDelegationManager.OperatorDetails\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"contract IStrategy\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"operatorShares\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newPausedStatus\",\"type\":\"uint256\"}],\"name\":\"pause\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pauseAll\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"index\",\"type\":\"uint8\"}],\"name\":\"paused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"paused\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pauserRegistry\",\"outputs\":[{\"internalType\":\"contract IPauserRegistry\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"name\":\"pendingWithdrawals\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"contract IStrategy[]\",\"name\":\"strategies\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"shares\",\"type\":\"uint256[]\"},{\"internalType\":\"address\",\"name\":\"withdrawer\",\"type\":\"address\"}],\"internalType\":\"struct IDelegationManager.QueuedWithdrawalParams[]\",\"name\":\"queuedWithdrawalParams\",\"type\":\"tuple[]\"}],\"name\":\"queueWithdrawals\",\"outputs\":[{\"internalType\":\"bytes32[]\",\"name\":\"\",\"type\":\"bytes32[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"__deprecated_earningsReceiver\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"delegationApprover\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"stakerOptOutWindowBlocks\",\"type\":\"uint32\"}],\"internalType\":\"struct IDelegationManager.OperatorDetails\",\"name\":\"registeringOperatorDetails\",\"type\":\"tuple\"},{\"internalType\":\"string\",\"name\":\"metadataURI\",\"type\":\"string\"}],\"name\":\"registerAsOperator\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newMinWithdrawalDelayBlocks\",\"type\":\"uint256\"}],\"name\":\"setMinWithdrawalDelayBlocks\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract IPauserRegistry\",\"name\":\"newPauserRegistry\",\"type\":\"address\"}],\"name\":\"setPauserRegistry\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract IStrategy[]\",\"name\":\"strategies\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"withdrawalDelayBlocks\",\"type\":\"uint256[]\"}],\"name\":\"setStrategyWithdrawalDelayBlocks\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"slasher\",\"outputs\":[{\"internalType\":\"contract ISlasher\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"stakerNonce\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"}],\"name\":\"stakerOptOutWindowBlocks\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"strategyManager\",\"outputs\":[{\"internalType\":\"contract IStrategyManager\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract IStrategy\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"strategyWithdrawalDelayBlocks\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"staker\",\"type\":\"address\"}],\"name\":\"undelegate\",\"outputs\":[{\"internalType\":\"bytes32[]\",\"name\":\"withdrawalRoots\",\"type\":\"bytes32[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newPausedStatus\",\"type\":\"uint256\"}],\"name\":\"unpause\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"metadataURI\",\"type\":\"string\"}],\"name\":\"updateOperatorMetadataURI\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"author\":\"Layr Labs, Inc.\",\"kind\":\"dev\",\"methods\":{\"calculateCurrentStakerDelegationDigestHash(address,address,uint256)\":{\"params\":{\"expiry\":\"The desired expiry time of the staker's signature\",\"operator\":\"The operator who is being delegated to\",\"staker\":\"The signing staker\"}},\"calculateDelegationApprovalDigestHash(address,address,address,bytes32,uint256)\":{\"params\":{\"_delegationApprover\":\"the operator's `delegationApprover` who will be signing the delegationHash (in general)\",\"approverSalt\":\"A unique and single use value associated with the approver signature.\",\"expiry\":\"Time after which the approver's signature becomes invalid\",\"operator\":\"The account receiving delegated stake\",\"staker\":\"The account delegating their stake\"}},\"calculateStakerDelegationDigestHash(address,uint256,address,uint256)\":{\"params\":{\"_stakerNonce\":\"The nonce of the staker. In practice we use the staker's current nonce, stored at `stakerNonce[staker]`\",\"expiry\":\"The desired expiry time of the staker's signature\",\"operator\":\"The operator who is being delegated to\",\"staker\":\"The signing staker\"}},\"completeQueuedWithdrawal((address,address,address,uint256,uint32,address[],uint256[]),address[],uint256,bool)\":{\"details\":\"middlewareTimesIndex is unused, but will be used in the Slasher eventuallybeaconChainETHStrategy shares are non-transferrable, so if `receiveAsTokens = false` and `withdrawal.withdrawer != withdrawal.staker`, note that any beaconChainETHStrategy shares in the `withdrawal` will be _returned to the staker_, rather than transferred to the withdrawer, unlike shares in any other strategies, which will be transferred to the withdrawer.\",\"params\":{\"middlewareTimesIndex\":\"is the index in the operator that the staker who triggered the withdrawal was delegated to's middleware times array\",\"receiveAsTokens\":\"If true, the shares specified in the withdrawal will be withdrawn from the specified strategies themselves and sent to the caller, through calls to `withdrawal.strategies[i].withdraw`. If false, then the shares in the specified strategies will simply be transferred to the caller directly.\",\"tokens\":\"Array in which the i-th entry specifies the `token` input to the 'withdraw' function of the i-th Strategy in the `withdrawal.strategies` array. This input can be provided with zero length if `receiveAsTokens` is set to 'false' (since in that case, this input will be unused)\",\"withdrawal\":\"The Withdrawal to complete.\"}},\"completeQueuedWithdrawals((address,address,address,uint256,uint32,address[],uint256[])[],address[][],uint256[],bool[])\":{\"details\":\"See `completeQueuedWithdrawal` for relevant dev tags\",\"params\":{\"middlewareTimesIndexes\":\"One index to reference per Withdrawal. See `completeQueuedWithdrawal` for the usage of a single index.\",\"receiveAsTokens\":\"Whether or not to complete each withdrawal as tokens. See `completeQueuedWithdrawal` for the usage of a single boolean.\",\"tokens\":\"Array of tokens for each Withdrawal. See `completeQueuedWithdrawal` for the usage of a single array.\",\"withdrawals\":\"The Withdrawals to complete.\"}},\"constructor\":{\"details\":\"Initializes the immutable addresses of the strategy mananger and slasher.\"},\"decreaseDelegatedShares(address,address,uint256)\":{\"details\":\"*If the staker is actively delegated*, then decreases the `staker`'s delegated shares in `strategy` by `shares`. Otherwise does nothing.Callable only by the StrategyManager or EigenPodManager.\",\"params\":{\"shares\":\"The number of shares to decrease.\",\"staker\":\"The address to increase the delegated shares for their operator.\",\"strategy\":\"The strategy in which to decrease the delegated shares.\"}},\"delegateTo(address,(bytes,uint256),bytes32)\":{\"details\":\"The approverSignatureAndExpiry is used in the event that: 1) the operator's `delegationApprover` address is set to a non-zero value. AND 2) neither the operator nor their `delegationApprover` is the `msg.sender`, since in the event that the operator or their delegationApprover is the `msg.sender`, then approval is assumed.In the event that `approverSignatureAndExpiry` is not checked, its content is ignored entirely; it's recommended to use an empty input in this case to save on complexity + gas costs\",\"params\":{\"approverSalt\":\"A unique single use value tied to an individual signature.\",\"approverSignatureAndExpiry\":\"Verifies the operator approves of this delegation\",\"operator\":\"The account (`msg.sender`) is delegating its assets to for use in serving applications built on EigenLayer.\"}},\"delegateToBySignature(address,address,(bytes,uint256),(bytes,uint256),bytes32)\":{\"details\":\"If `staker` is an EOA, then `stakerSignature` is verified to be a valid ECDSA stakerSignature from `staker`, indicating their intention for this action.If `staker` is a contract, then `stakerSignature` will be checked according to EIP-1271.the operator's `delegationApprover` address is set to a non-zero value.neither the operator nor their `delegationApprover` is the `msg.sender`, since in the event that the operator or their delegationApprover is the `msg.sender`, then approval is assumed.This function will revert if the current `block.timestamp` is equal to or exceeds the expiryIn the case that `approverSignatureAndExpiry` is not checked, its content is ignored entirely; it's recommended to use an empty input in this case to save on complexity + gas costs\",\"params\":{\"approverSalt\":\"Is a salt used to help guarantee signature uniqueness. Each salt can only be used once by a given approver.\",\"approverSignatureAndExpiry\":\"is a parameter that will be used for verifying that the operator approves of this delegation action in the event that:\",\"operator\":\"The account (`staker`) is delegating its assets to for use in serving applications built on EigenLayer.\",\"staker\":\"The account delegating stake to an `operator` account\",\"stakerSignatureAndExpiry\":\"Signed data from the staker authorizing delegating stake to an operator\"}},\"domainSeparator()\":{\"details\":\"The domain separator will change in the event of a fork that changes the ChainID.By introducing a domain separator the DApp developers are guaranteed that there can be no signature collision. for more detailed information please read EIP-712.\"},\"getDelegatableShares(address)\":{\"details\":\"Returns two empty arrays in the case that the Staker has no actively-delegateable shares.\"},\"getWithdrawalDelay(address[])\":{\"params\":{\"strategies\":\"The strategies to check withdrawal delays for\"}},\"increaseDelegatedShares(address,address,uint256)\":{\"details\":\"*If the staker is actively delegated*, then increases the `staker`'s delegated shares in `strategy` by `shares`. Otherwise does nothing.Callable only by the StrategyManager or EigenPodManager.\",\"params\":{\"shares\":\"The number of shares to increase.\",\"staker\":\"The address to increase the delegated shares for their operator.\",\"strategy\":\"The strategy in which to increase the delegated shares.\"}},\"initialize(address,address,uint256,uint256,address[],uint256[])\":{\"details\":\"Initializes the addresses of the initial owner, pauser registry, and paused status. minWithdrawalDelayBlocks is set only once here\"},\"modifyOperatorDetails((address,address,uint32))\":{\"details\":\"The caller must have previously registered as an operator in EigenLayer.\",\"params\":{\"newOperatorDetails\":\"is the updated `OperatorDetails` for the operator, to replace their current OperatorDetails`.\"}},\"owner()\":{\"details\":\"Returns the address of the current owner.\"},\"pause(uint256)\":{\"details\":\"This function can only pause functionality, and thus cannot 'unflip' any bit in `_paused` from 1 to 0.\",\"params\":{\"newPausedStatus\":\"represents the new value for `_paused` to take, which means it may flip several bits at once.\"}},\"registerAsOperator((address,address,uint32),string)\":{\"details\":\"Once an operator is registered, they cannot 'deregister' as an operator, and they will forever be considered \\\"delegated to themself\\\".This function will revert if the caller is already delegated to an operator.Note that the `metadataURI` is *never stored * and is only emitted in the `OperatorMetadataURIUpdated` event\",\"params\":{\"metadataURI\":\"is a URI for the operator's metadata, i.e. a link providing more details on the operator.\",\"registeringOperatorDetails\":\"is the `OperatorDetails` for the operator.\"}},\"renounceOwnership()\":{\"details\":\"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner.\"},\"setMinWithdrawalDelayBlocks(uint256)\":{\"params\":{\"newMinWithdrawalDelayBlocks\":\"new value of `minWithdrawalDelayBlocks`.\"}},\"setStrategyWithdrawalDelayBlocks(address[],uint256[])\":{\"params\":{\"strategies\":\"The strategies to set the minimum withdrawal delay blocks for\",\"withdrawalDelayBlocks\":\"The minimum withdrawal delay blocks to set for each strategy\"}},\"transferOwnership(address)\":{\"details\":\"Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.\"},\"unpause(uint256)\":{\"details\":\"This function can only unpause functionality, and thus cannot 'flip' any bit in `_paused` from 0 to 1.\",\"params\":{\"newPausedStatus\":\"represents the new value for `_paused` to take, which means it may flip several bits at once.\"}},\"updateOperatorMetadataURI(string)\":{\"params\":{\"metadataURI\":\"The URI for metadata associated with an operator\"}}},\"title\":\"DelegationManager\",\"version\":1},\"userdoc\":{\"events\":{\"MinWithdrawalDelayBlocksSet(uint256,uint256)\":{\"notice\":\"Emitted when the `minWithdrawalDelayBlocks` variable is modified from `previousValue` to `newValue`.\"},\"OperatorDetailsModified(address,(address,address,uint32))\":{\"notice\":\"Emitted when an operator updates their OperatorDetails to @param newOperatorDetails\"},\"OperatorMetadataURIUpdated(address,string)\":{\"notice\":\"Emitted when @param operator indicates that they are updating their MetadataURI string\"},\"OperatorSharesDecreased(address,address,address,uint256)\":{\"notice\":\"Emitted whenever an operator's shares are decreased for a given strategy. Note that shares is the delta in the operator's shares.\"},\"OperatorSharesIncreased(address,address,address,uint256)\":{\"notice\":\"Emitted whenever an operator's shares are increased for a given strategy. Note that shares is the delta in the operator's shares.\"},\"Paused(address,uint256)\":{\"notice\":\"Emitted when the pause is triggered by `account`, and changed to `newPausedStatus`.\"},\"PauserRegistrySet(address,address)\":{\"notice\":\"Emitted when the `pauserRegistry` is set to `newPauserRegistry`.\"},\"StakerDelegated(address,address)\":{\"notice\":\"Emitted when @param staker delegates to @param operator.\"},\"StakerForceUndelegated(address,address)\":{\"notice\":\"Emitted when @param staker is undelegated via a call not originating from the staker themself\"},\"StakerUndelegated(address,address)\":{\"notice\":\"Emitted when @param staker undelegates from @param operator.\"},\"StrategyWithdrawalDelayBlocksSet(address,uint256,uint256)\":{\"notice\":\"Emitted when the `strategyWithdrawalDelayBlocks` variable is modified from `previousValue` to `newValue`.\"},\"Unpaused(address,uint256)\":{\"notice\":\"Emitted when the pause is lifted by `account`, and changed to `newPausedStatus`.\"},\"WithdrawalCompleted(bytes32)\":{\"notice\":\"Emitted when a queued withdrawal is completed\"},\"WithdrawalQueued(bytes32,(address,address,address,uint256,uint32,address[],uint256[]))\":{\"notice\":\"Emitted when a new withdrawal is queued.\"}},\"kind\":\"user\",\"methods\":{\"DELEGATION_APPROVAL_TYPEHASH()\":{\"notice\":\"The EIP-712 typehash for the `DelegationApproval` struct used by the contract\"},\"DOMAIN_TYPEHASH()\":{\"notice\":\"The EIP-712 typehash for the contract's domain\"},\"STAKER_DELEGATION_TYPEHASH()\":{\"notice\":\"The EIP-712 typehash for the `StakerDelegation` struct used by the contract\"},\"beaconChainETHStrategy()\":{\"notice\":\"Canonical, virtual beacon chain ETH strategy\"},\"calculateCurrentStakerDelegationDigestHash(address,address,uint256)\":{\"notice\":\"Calculates the digestHash for a `staker` to sign to delegate to an `operator`\"},\"calculateDelegationApprovalDigestHash(address,address,address,bytes32,uint256)\":{\"notice\":\"Calculates the digest hash to be signed by the operator's delegationApprove and used in the `delegateTo` and `delegateToBySignature` functions.\"},\"calculateStakerDelegationDigestHash(address,uint256,address,uint256)\":{\"notice\":\"Calculates the digest hash to be signed and used in the `delegateToBySignature` function\"},\"calculateWithdrawalRoot((address,address,address,uint256,uint32,address[],uint256[]))\":{\"notice\":\"Returns the keccak256 hash of `withdrawal`.\"},\"completeQueuedWithdrawal((address,address,address,uint256,uint32,address[],uint256[]),address[],uint256,bool)\":{\"notice\":\"Used to complete the specified `withdrawal`. The caller must match `withdrawal.withdrawer`\"},\"completeQueuedWithdrawals((address,address,address,uint256,uint32,address[],uint256[])[],address[][],uint256[],bool[])\":{\"notice\":\"Array-ified version of `completeQueuedWithdrawal`. Used to complete the specified `withdrawals`. The function caller must match `withdrawals[...].withdrawer`\"},\"cumulativeWithdrawalsQueued(address)\":{\"notice\":\"Mapping: staker => cumulative number of queued withdrawals they have ever initiated.\"},\"decreaseDelegatedShares(address,address,uint256)\":{\"notice\":\"Decreases a staker's delegated share balance in a strategy.\"},\"delegateTo(address,(bytes,uint256),bytes32)\":{\"notice\":\"Caller delegates their stake to an operator.\"},\"delegateToBySignature(address,address,(bytes,uint256),(bytes,uint256),bytes32)\":{\"notice\":\"Caller delegates a staker's stake to an operator with valid signatures from both parties.\"},\"delegatedTo(address)\":{\"notice\":\"Mapping: staker => operator whom the staker is currently delegated to.\"},\"delegationApprover(address)\":{\"notice\":\"Returns the delegationApprover account for an operator\"},\"delegationApproverSaltIsSpent(address,bytes32)\":{\"notice\":\"Mapping: delegationApprover => 32-byte salt => whether or not the salt has already been used by the delegationApprover.\"},\"domainSeparator()\":{\"notice\":\"Getter function for the current EIP-712 domain separator for this contract.\"},\"eigenPodManager()\":{\"notice\":\"The EigenPodManager contract for EigenLayer\"},\"getDelegatableShares(address)\":{\"notice\":\"Returns the number of actively-delegatable shares a staker has across all strategies.\"},\"getOperatorShares(address,address[])\":{\"notice\":\"Given array of strategies, returns array of shares for the operator\"},\"getWithdrawalDelay(address[])\":{\"notice\":\"Given a list of strategies, return the minimum number of blocks that must pass to withdraw from all the inputted strategies. Return value is >= minWithdrawalDelayBlocks as this is the global min withdrawal delay.\"},\"increaseDelegatedShares(address,address,uint256)\":{\"notice\":\"Increases a staker's delegated share balance in a strategy.\"},\"isDelegated(address)\":{\"notice\":\"Returns 'true' if `staker` *is* actively delegated, and 'false' otherwise.\"},\"isOperator(address)\":{\"notice\":\"Returns true is an operator has previously registered for delegation.\"},\"minWithdrawalDelayBlocks()\":{\"notice\":\"Global minimum withdrawal delay for all strategy withdrawals. In a prior Goerli release, we only had a global min withdrawal delay across all strategies. In addition, we now also configure withdrawal delays on a per-strategy basis. To withdraw from a strategy, max(minWithdrawalDelayBlocks, strategyWithdrawalDelayBlocks[strategy]) number of blocks must have passed. See mapping strategyWithdrawalDelayBlocks below for per-strategy withdrawal delays.\"},\"modifyOperatorDetails((address,address,uint32))\":{\"notice\":\"Updates an operator's stored `OperatorDetails`.\"},\"operatorDetails(address)\":{\"notice\":\"Returns the OperatorDetails struct associated with an `operator`.\"},\"operatorShares(address,address)\":{\"notice\":\"returns the total number of shares in `strategy` that are delegated to `operator`.Mapping: operator => strategy => total number of shares in the strategy delegated to the operator.\"},\"pause(uint256)\":{\"notice\":\"This function is used to pause an EigenLayer contract's functionality. It is permissioned to the `pauser` address, which is expected to be a low threshold multisig.\"},\"pauseAll()\":{\"notice\":\"Alias for `pause(type(uint256).max)`.\"},\"paused()\":{\"notice\":\"Returns the current paused status as a uint256.\"},\"paused(uint8)\":{\"notice\":\"Returns 'true' if the `indexed`th bit of `_paused` is 1, and 'false' otherwise\"},\"pauserRegistry()\":{\"notice\":\"Address of the `PauserRegistry` contract that this contract defers to for determining access control (for pausing).\"},\"pendingWithdrawals(bytes32)\":{\"notice\":\"Mapping: hash of withdrawal inputs, aka 'withdrawalRoot' => whether the withdrawal is pending\"},\"queueWithdrawals((address[],uint256[],address)[])\":{\"notice\":\"Allows a staker to withdraw some shares. Withdrawn shares/strategies are immediately removed from the staker. If the staker is delegated, withdrawn shares/strategies are also removed from their operator. All withdrawn shares/strategies are placed in a queue and can be fully withdrawn after a delay.\"},\"registerAsOperator((address,address,uint32),string)\":{\"notice\":\"Registers the caller as an operator in EigenLayer.\"},\"setMinWithdrawalDelayBlocks(uint256)\":{\"notice\":\"Owner-only function for modifying the value of the `minWithdrawalDelayBlocks` variable.\"},\"setPauserRegistry(address)\":{\"notice\":\"Allows the unpauser to set a new pauser registry\"},\"setStrategyWithdrawalDelayBlocks(address[],uint256[])\":{\"notice\":\"Called by owner to set the minimum withdrawal delay blocks for each passed in strategy Note that the min number of blocks to complete a withdrawal of a strategy is MAX(minWithdrawalDelayBlocks, strategyWithdrawalDelayBlocks[strategy])\"},\"slasher()\":{\"notice\":\"The Slasher contract for EigenLayer\"},\"stakerNonce(address)\":{\"notice\":\"Mapping: staker => number of signed messages (used in `delegateToBySignature`) from the staker that this contract has already checked.\"},\"stakerOptOutWindowBlocks(address)\":{\"notice\":\"Returns the stakerOptOutWindowBlocks for an operator\"},\"strategyManager()\":{\"notice\":\"The StrategyManager contract for EigenLayer\"},\"strategyWithdrawalDelayBlocks(address)\":{\"notice\":\"Minimum delay enforced by this contract per Strategy for completing queued withdrawals. Measured in blocks, and adjustable by this contract's owner, up to a maximum of `MAX_WITHDRAWAL_DELAY_BLOCKS`. Minimum value is 0 (i.e. no delay enforced).\"},\"undelegate(address)\":{\"notice\":\"Allows the staker, the staker's operator, or that operator's delegationApprover to undelegate a staker from their operator. Undelegation immediately removes ALL active shares/strategies from both the staker and operator, and places the shares and strategies in the withdrawal queue\"},\"unpause(uint256)\":{\"notice\":\"This function is used to unpause an EigenLayer contract's functionality. It is permissioned to the `unpauser` address, which is expected to be a high threshold multisig or governance contract.\"},\"updateOperatorMetadataURI(string)\":{\"notice\":\"Called by an operator to emit an `OperatorMetadataURIUpdated` event indicating the information has updated.\"}},\"notice\":\"Terms of Service: https://docs.eigenlayer.xyz/overview/terms-of-serviceThis is the contract for delegation in EigenLayer. The main functionalities of this contract are - enabling anyone to register as an operator in EigenLayer - allowing operators to specify parameters related to stakers who delegate to them - enabling any staker to delegate its stake to the operator of its choice (a given staker can only delegate to a single operator at a time) - enabling a staker to undelegate its assets from the operator it is delegated to (performed as part of the withdrawal process, initiated through the StrategyManager)\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"lib/eigenlayer-middleware/lib/eigenlayer-contracts/src/contracts/core/DelegationManager.sol\":\"DelegationManager\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[\":@openzeppelin-upgrades-v4.9.0/=lib/eigenlayer-middleware/lib/eigenlayer-contracts/lib/openzeppelin-contracts-upgradeable-v4.9.0/\",\":@openzeppelin-upgrades/=lib/eigenlayer-middleware/lib/openzeppelin-contracts-upgradeable/\",\":@openzeppelin-v4.9.0/=lib/eigenlayer-middleware/lib/eigenlayer-contracts/lib/openzeppelin-contracts-v4.9.0/\",\":@openzeppelin/=lib/eigenlayer-middleware/lib/openzeppelin-contracts/\",\":ds-test/=lib/eigenlayer-middleware/lib/ds-test/src/\",\":eigenlayer-contracts/=lib/eigenlayer-middleware/lib/eigenlayer-contracts/\",\":eigenlayer-core-contracts/=lib/eigenlayer-middleware/lib/eigenlayer-contracts/src/contracts/core/\",\":eigenlayer-core/=lib/eigenlayer-middleware/lib/eigenlayer-contracts/src/\",\":eigenlayer-middleware/=lib/eigenlayer-middleware/src/\",\":eigenlayer-scripts/=lib/eigenlayer-middleware/lib/eigenlayer-contracts/script/\",\":erc4626-tests/=lib/eigenlayer-middleware/lib/eigenlayer-contracts/lib/openzeppelin-contracts-upgradeable-v4.9.0/lib/erc4626-tests/\",\":forge-std/=lib/forge-std/src/\",\":openzeppelin-contracts-upgradeable-v4.9.0/=lib/eigenlayer-middleware/lib/eigenlayer-contracts/lib/openzeppelin-contracts-upgradeable-v4.9.0/\",\":openzeppelin-contracts-upgradeable/=lib/eigenlayer-middleware/lib/openzeppelin-contracts-upgradeable/\",\":openzeppelin-contracts-v4.9.0/=lib/eigenlayer-middleware/lib/eigenlayer-contracts/lib/openzeppelin-contracts-v4.9.0/\",\":openzeppelin-contracts/=lib/eigenlayer-middleware/lib/openzeppelin-contracts/\",\":openzeppelin/=lib/eigenlayer-middleware/lib/eigenlayer-contracts/lib/openzeppelin-contracts-upgradeable-v4.9.0/contracts/\"]},\"sources\":{\"lib/eigenlayer-middleware/lib/eigenlayer-contracts/src/contracts/core/DelegationManager.sol\":{\"keccak256\":\"0xebb7560a956ece70b08cf36bc548e70c7a04ad4f8718eba194927bcfc03c6190\",\"license\":\"BUSL-1.1\",\"urls\":[\"bzz-raw://ac5fe6c05d4268c8fd5853e44662bf9d306313e014d27542f02abd62265168d2\",\"dweb:/ipfs/QmTXcATcpgFpAD8FLmoeWoGYKTh3rRjxntsHCP7wcTWkwY\"]},\"lib/eigenlayer-middleware/lib/eigenlayer-contracts/src/contracts/core/DelegationManagerStorage.sol\":{\"keccak256\":\"0xd834e9bc2f4d03545102004ffa9651e5bf9b559d43e4102bf2955314ef2d94f5\",\"license\":\"BUSL-1.1\",\"urls\":[\"bzz-raw://9c7670995b7ca634f94848f426b36278f98389c120b177b737ef325bd457ca00\",\"dweb:/ipfs/QmRtLyA4Kq5TrhhhXQAp2jAH7bJ5gqbjrr1JesD6wRbqqV\"]},\"lib/eigenlayer-middleware/lib/eigenlayer-contracts/src/contracts/interfaces/IBeaconChainOracle.sol\":{\"keccak256\":\"0x0fef07aa6179c77198f1514e12e628aa1c876e04f9c181ec853a322179e5be00\",\"license\":\"BUSL-1.1\",\"urls\":[\"bzz-raw://51438325876cc2d4c77f58488a7e27b488015d1b663c50be6a5cafbd73b9c983\",\"dweb:/ipfs/QmViCuGoYZzi6wtXA8PPKigqVv3KMuNxEVQ1Td9dGqjL18\"]},\"lib/eigenlayer-middleware/lib/eigenlayer-contracts/src/contracts/interfaces/IDelegationManager.sol\":{\"keccak256\":\"0xab76a9f4eff865cbb689f627cf98263488765519d7a4ec5ffbcb0ca4972842f9\",\"license\":\"BUSL-1.1\",\"urls\":[\"bzz-raw://ff57ce18e8350bf39f190645db0988bc0f1279f1872150a114a1b520c38a2914\",\"dweb:/ipfs/QmSsUXkNUqYuJgGRumHTSs9rAaboGjecotcM4xHrdBYWaZ\"]},\"lib/eigenlayer-middleware/lib/eigenlayer-contracts/src/contracts/interfaces/IETHPOSDeposit.sol\":{\"keccak256\":\"0x2e60e5f4b0da0a0a4e2a07c63141120998559970c21deac743ea0c64a60a880c\",\"license\":\"CC0-1.0\",\"urls\":[\"bzz-raw://e635c346bde5b7ade9bcf35bc733081520cb86015be4fbc6e761e6e9482c4c91\",\"dweb:/ipfs/QmRoeazEnbFn5SPSWAkoFK2gSN9DMp3hJAnrLWuL2sKutz\"]},\"lib/eigenlayer-middleware/lib/eigenlayer-contracts/src/contracts/interfaces/IEigenPod.sol\":{\"keccak256\":\"0xb50c36ad96b6679bb80fd8331f949cbfbcba0f529026e1421a4d2bae64396eba\",\"license\":\"BUSL-1.1\",\"urls\":[\"bzz-raw://5719181d780120f1e688c0da276992a8caf185815917f453b3550537c31ed4cc\",\"dweb:/ipfs/QmYprRC5ZEXhz3zAUND5E8Xjn6s5TL8ZF8QbnndVq7aVPR\"]},\"lib/eigenlayer-middleware/lib/eigenlayer-contracts/src/contracts/interfaces/IEigenPodManager.sol\":{\"keccak256\":\"0xd8a64dbed03d3a5cdbefe1af75968f2dde07f973749c2ef5197bf7187c3e448c\",\"license\":\"BUSL-1.1\",\"urls\":[\"bzz-raw://27ccc7c1fd9352e9f9b357c9063d255dc0ed9583f43db09f786ac7497d7846b8\",\"dweb:/ipfs/QmeJzuJkE9m2NUNwZSp4tGZEZmih1LeucePup8hzMVDRbG\"]},\"lib/eigenlayer-middleware/lib/eigenlayer-contracts/src/contracts/interfaces/IPausable.sol\":{\"keccak256\":\"0x98cffc894842947377e24c1d375813a1120dd73a84c29782ab68404e109cb34f\",\"license\":\"BUSL-1.1\",\"urls\":[\"bzz-raw://b3474f6c350ceaee57cbdfb08fb48835d0c6e81ae8ebfbb9667899584a139324\",\"dweb:/ipfs/QmWELKtksdtWxQbqAccd8yGyhKqrgPZXTADKR7BuT27Zg5\"]},\"lib/eigenlayer-middleware/lib/eigenlayer-contracts/src/contracts/interfaces/IPauserRegistry.sol\":{\"keccak256\":\"0x9de8dd682bc0d812bbd6583c0231cbf35448d5eff58b74a93efa64cb9a768c49\",\"license\":\"BUSL-1.1\",\"urls\":[\"bzz-raw://c00d6c675b9c72b092d287fe85fd37782588df32b8eb59ab4c7db7a86be25e7d\",\"dweb:/ipfs/QmeYokY3HhAdbBaCPdHg3PgQEdRCDFEJy3Wf7VtgHBkQSx\"]},\"lib/eigenlayer-middleware/lib/eigenlayer-contracts/src/contracts/interfaces/ISignatureUtils.sol\":{\"keccak256\":\"0x5e52482a31d94401a8502f3014c4aada1142b4450fc0596dff8e1866a85fe092\",\"license\":\"BUSL-1.1\",\"urls\":[\"bzz-raw://17dc326c9361bc1453379f26545963557b2883b0c88bc07d4477e04dbcc0cc8c\",\"dweb:/ipfs/QmZXT7A816W5JH2ymirE2ETaJttqztFCsEL22AV8oEfCK9\"]},\"lib/eigenlayer-middleware/lib/eigenlayer-contracts/src/contracts/interfaces/ISlasher.sol\":{\"keccak256\":\"0x45dfaa2cfdde87f48a6ee38bb6fb739847aef7cf3f6137bdcd8c8a330559ec79\",\"license\":\"BUSL-1.1\",\"urls\":[\"bzz-raw://1b7f6bd75b42fcaa91ceb7140cb2c41926a1fe6ee2d3161e4fe6186b181ba232\",\"dweb:/ipfs/QmZjbdKiSs33C9i3GDc3sdD39Pz4YPkDoKftowoUF4kHmY\"]},\"lib/eigenlayer-middleware/lib/eigenlayer-contracts/src/contracts/interfaces/IStrategy.sol\":{\"keccak256\":\"0xc530c6a944b70051fd0dac0222de9a4b5baadeaf94ad194daac6ad8d2ace7420\",\"license\":\"BUSL-1.1\",\"urls\":[\"bzz-raw://3767df0364ce835b52e786d2851431eb9223fe4747602107505477e162231d73\",\"dweb:/ipfs/QmZkH5bKUygQrJomndNaQqkefVRW4rRefCa8HPJ5HMczxJ\"]},\"lib/eigenlayer-middleware/lib/eigenlayer-contracts/src/contracts/interfaces/IStrategyManager.sol\":{\"keccak256\":\"0x68bf02a443fc8b2f612eba3d39bfefa5f61f78b549f111cdecec5f2c58236a52\",\"license\":\"BUSL-1.1\",\"urls\":[\"bzz-raw://76bc6875ce74128b861fdac5fd1c0c72f3cc9bacf67fa4a73721b95fb23959ef\",\"dweb:/ipfs/QmPix4WJmf9fXyMZxfgwXEHBcg7V4NAbRqs4HUf5YrSJcM\"]},\"lib/eigenlayer-middleware/lib/eigenlayer-contracts/src/contracts/libraries/BeaconChainProofs.sol\":{\"keccak256\":\"0x70d89b05c1c5f47b74a07fbb5a2c05e606fed494e749ea98a9915b7be73df377\",\"license\":\"BUSL-1.1\",\"urls\":[\"bzz-raw://db1d3bfaee69aef53c8b12b492a17584e6d1ac94610cb8b38aad33e1cdd81af7\",\"dweb:/ipfs/QmfVsMTj1hcf9fMEm5RzvtcBN4dMcAKFBgUUDsNDr5XFpq\"]},\"lib/eigenlayer-middleware/lib/eigenlayer-contracts/src/contracts/libraries/EIP1271SignatureUtils.sol\":{\"keccak256\":\"0xe92d584c47c5828e026a8082af3da38a853e3942c4da7deb705d6470a41afab3\",\"license\":\"BUSL-1.1\",\"urls\":[\"bzz-raw://1c436c578781fd7d3dffdb24e906819422819f5e9a71d39ee63166a3d5cb3373\",\"dweb:/ipfs/QmP7bJhYqLpwqk2Xq4tqDCUMi2nFAhxxW3Pz36ctE1sbdD\"]},\"lib/eigenlayer-middleware/lib/eigenlayer-contracts/src/contracts/libraries/Endian.sol\":{\"keccak256\":\"0xf3b72653ba2567a978d4612703fa5f71c5fcd015d8dac7818468f22772d90a9d\",\"license\":\"BUSL-1.1\",\"urls\":[\"bzz-raw://cee9d09370d968138d775c39525db4cd0768d60d17be7685519de12444e7dd2f\",\"dweb:/ipfs/QmUdGh8wpMei3edKiEWA6S96s9dRt4ekZKJ4nau356X8xQ\"]},\"lib/eigenlayer-middleware/lib/eigenlayer-contracts/src/contracts/libraries/Merkle.sol\":{\"keccak256\":\"0x9095fc29b96d102b10c02d44b3a6fbfa25593ef6ae4a810363ab885b9e6b0f71\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://0945132d482d56278edddb1d32209903c4d3839c87ba4317aadd97dc23610d0f\",\"dweb:/ipfs/QmVuM2aLRHxitx4rPx3GTYTBCVNcjYn6sHBRr1biUjLBP5\"]},\"lib/eigenlayer-middleware/lib/eigenlayer-contracts/src/contracts/permissions/Pausable.sol\":{\"keccak256\":\"0xce8ee0ab28f2bce9e94aa19fffe55bebef080327632ac98ff3ab14994b369bc0\",\"license\":\"BUSL-1.1\",\"urls\":[\"bzz-raw://5c7e2be97a8840fa2a0434077a36136553a84efd9bff4b46712ce9fddb813a6a\",\"dweb:/ipfs/QmZKvgPxLAbGo1CqTA4AX6MCDPFLSSNt43ZKWRjvvzFp7S\"]},\"lib/eigenlayer-middleware/lib/openzeppelin-contracts-upgradeable/contracts/access/OwnableUpgradeable.sol\":{\"keccak256\":\"0x247c62047745915c0af6b955470a72d1696ebad4352d7d3011aef1a2463cd888\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://d7fc8396619de513c96b6e00301b88dd790e83542aab918425633a5f7297a15a\",\"dweb:/ipfs/QmXbP4kiZyp7guuS7xe8KaybnwkRPGrBc2Kbi3vhcTfpxb\"]},\"lib/eigenlayer-middleware/lib/openzeppelin-contracts-upgradeable/contracts/proxy/utils/Initializable.sol\":{\"keccak256\":\"0x0203dcadc5737d9ef2c211d6fa15d18ebc3b30dfa51903b64870b01a062b0b4e\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://6eb2fd1e9894dbe778f4b8131adecebe570689e63cf892f4e21257bfe1252497\",\"dweb:/ipfs/QmXgUGNfZvrn6N2miv3nooSs7Jm34A41qz94fu2GtDFcx8\"]},\"lib/eigenlayer-middleware/lib/openzeppelin-contracts-upgradeable/contracts/security/ReentrancyGuardUpgradeable.sol\":{\"keccak256\":\"0x8cc03c5ac17e8a7396e487cda41fc1f1dfdb91db7d528e6da84bee3b6dd7e167\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://607818f1b44548c2d8268176f73cdb290e1faed971b1061930d92698366e2a11\",\"dweb:/ipfs/QmQibMe3r5no95b6q7isGT5R75V8xSofWEDLXzp95b7LgZ\"]},\"lib/eigenlayer-middleware/lib/openzeppelin-contracts-upgradeable/contracts/utils/AddressUpgradeable.sol\":{\"keccak256\":\"0x611aa3f23e59cfdd1863c536776407b3e33d695152a266fa7cfb34440a29a8a3\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://9b4b2110b7f2b3eb32951bc08046fa90feccffa594e1176cb91cdfb0e94726b4\",\"dweb:/ipfs/QmSxLwYjicf9zWFuieRc8WQwE4FisA1Um5jp1iSa731TGt\"]},\"lib/eigenlayer-middleware/lib/openzeppelin-contracts-upgradeable/contracts/utils/ContextUpgradeable.sol\":{\"keccak256\":\"0x963ea7f0b48b032eef72fe3a7582edf78408d6f834115b9feadd673a4d5bd149\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://d6520943ea55fdf5f0bafb39ed909f64de17051bc954ff3e88c9e5621412c79c\",\"dweb:/ipfs/QmWZ4rAKTQbNG2HxGs46AcTXShsVytKeLs7CUCdCSv5N7a\"]},\"lib/eigenlayer-middleware/lib/openzeppelin-contracts/contracts/interfaces/IERC1271.sol\":{\"keccak256\":\"0x0705a4b1b86d7b0bd8432118f226ba139c44b9dcaba0a6eafba2dd7d0639c544\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://c45b821ef9e882e57c256697a152e108f0f2ad6997609af8904cae99c9bd422e\",\"dweb:/ipfs/QmRKCJW6jjzR5UYZcLpGnhEJ75UVbH6EHkEa49sWx2SKng\"]},\"lib/eigenlayer-middleware/lib/openzeppelin-contracts/contracts/proxy/beacon/IBeacon.sol\":{\"keccak256\":\"0xd50a3421ac379ccb1be435fa646d66a65c986b4924f0849839f08692f39dde61\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://ada1e030c0231db8d143b44ce92b4d1158eedb087880cad6d8cc7bd7ebe7b354\",\"dweb:/ipfs/QmWZ2NHZweRpz1U9GF6R1h65ri76dnX7fNxLBeM2t5N5Ce\"]},\"lib/eigenlayer-middleware/lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol\":{\"keccak256\":\"0x9750c6b834f7b43000631af5cc30001c5f547b3ceb3635488f140f60e897ea6b\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://5a7d5b1ef5d8d5889ad2ed89d8619c09383b80b72ab226e0fe7bde1636481e34\",\"dweb:/ipfs/QmebXWgtEfumQGBdVeM6c71McLixYXQP5Bk6kKXuoY4Bmr\"]},\"lib/eigenlayer-middleware/lib/openzeppelin-contracts/contracts/utils/Address.sol\":{\"keccak256\":\"0xd6153ce99bcdcce22b124f755e72553295be6abcd63804cfdffceb188b8bef10\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://35c47bece3c03caaa07fab37dd2bb3413bfbca20db7bd9895024390e0a469487\",\"dweb:/ipfs/QmPGWT2x3QHcKxqe6gRmAkdakhbaRgx3DLzcakHz5M4eXG\"]},\"lib/eigenlayer-middleware/lib/openzeppelin-contracts/contracts/utils/Strings.sol\":{\"keccak256\":\"0xaf159a8b1923ad2a26d516089bceca9bdeaeacd04be50983ea00ba63070f08a3\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://6f2cf1c531122bc7ca96b8c8db6a60deae60441e5223065e792553d4849b5638\",\"dweb:/ipfs/QmPBdJmBBABMDCfyDjCbdxgiqRavgiSL88SYPGibgbPas9\"]},\"lib/eigenlayer-middleware/lib/openzeppelin-contracts/contracts/utils/cryptography/ECDSA.sol\":{\"keccak256\":\"0x84ac2d2f343df1e683da7a12bbcf70db542a7a7a0cea90a5d70fcb5e5d035481\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://73ae8e0c6f975052973265113d762629002ce33987b1933c2a378667e2816f2f\",\"dweb:/ipfs/QmQAootkVfoe4PLaYbT4Xob2dJRm3bZfbCffEHRbCYXNPF\"]}},\"version\":1}","metadata":{"compiler":{"version":"0.8.12+commit.f00d7308"},"language":"Solidity","output":{"abi":[{"inputs":[{"internalType":"contract IStrategyManager","name":"_strategyManager","type":"address"},{"internalType":"contract ISlasher","name":"_slasher","type":"address"},{"internalType":"contract IEigenPodManager","name":"_eigenPodManager","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"uint8","name":"version","type":"uint8","indexed":false}],"type":"event","name":"Initialized","anonymous":false},{"inputs":[{"internalType":"uint256","name":"previousValue","type":"uint256","indexed":false},{"internalType":"uint256","name":"newValue","type":"uint256","indexed":false}],"type":"event","name":"MinWithdrawalDelayBlocksSet","anonymous":false},{"inputs":[{"internalType":"address","name":"operator","type":"address","indexed":true},{"internalType":"struct IDelegationManager.OperatorDetails","name":"newOperatorDetails","type":"tuple","components":[{"internalType":"address","name":"__deprecated_earningsReceiver","type":"address"},{"internalType":"address","name":"delegationApprover","type":"address"},{"internalType":"uint32","name":"stakerOptOutWindowBlocks","type":"uint32"}],"indexed":false}],"type":"event","name":"OperatorDetailsModified","anonymous":false},{"inputs":[{"internalType":"address","name":"operator","type":"address","indexed":true},{"internalType":"string","name":"metadataURI","type":"string","indexed":false}],"type":"event","name":"OperatorMetadataURIUpdated","anonymous":false},{"inputs":[{"internalType":"address","name":"operator","type":"address","indexed":true},{"internalType":"struct IDelegationManager.OperatorDetails","name":"operatorDetails","type":"tuple","components":[{"internalType":"address","name":"__deprecated_earningsReceiver","type":"address"},{"internalType":"address","name":"delegationApprover","type":"address"},{"internalType":"uint32","name":"stakerOptOutWindowBlocks","type":"uint32"}],"indexed":false}],"type":"event","name":"OperatorRegistered","anonymous":false},{"inputs":[{"internalType":"address","name":"operator","type":"address","indexed":true},{"internalType":"address","name":"staker","type":"address","indexed":false},{"internalType":"contract IStrategy","name":"strategy","type":"address","indexed":false},{"internalType":"uint256","name":"shares","type":"uint256","indexed":false}],"type":"event","name":"OperatorSharesDecreased","anonymous":false},{"inputs":[{"internalType":"address","name":"operator","type":"address","indexed":true},{"internalType":"address","name":"staker","type":"address","indexed":false},{"internalType":"contract IStrategy","name":"strategy","type":"address","indexed":false},{"internalType":"uint256","name":"shares","type":"uint256","indexed":false}],"type":"event","name":"OperatorSharesIncreased","anonymous":false},{"inputs":[{"internalType":"address","name":"previousOwner","type":"address","indexed":true},{"internalType":"address","name":"newOwner","type":"address","indexed":true}],"type":"event","name":"OwnershipTransferred","anonymous":false},{"inputs":[{"internalType":"address","name":"account","type":"address","indexed":true},{"internalType":"uint256","name":"newPausedStatus","type":"uint256","indexed":false}],"type":"event","name":"Paused","anonymous":false},{"inputs":[{"internalType":"contract IPauserRegistry","name":"pauserRegistry","type":"address","indexed":false},{"internalType":"contract IPauserRegistry","name":"newPauserRegistry","type":"address","indexed":false}],"type":"event","name":"PauserRegistrySet","anonymous":false},{"inputs":[{"internalType":"address","name":"staker","type":"address","indexed":true},{"internalType":"address","name":"operator","type":"address","indexed":true}],"type":"event","name":"StakerDelegated","anonymous":false},{"inputs":[{"internalType":"address","name":"staker","type":"address","indexed":true},{"internalType":"address","name":"operator","type":"address","indexed":true}],"type":"event","name":"StakerForceUndelegated","anonymous":false},{"inputs":[{"internalType":"address","name":"staker","type":"address","indexed":true},{"internalType":"address","name":"operator","type":"address","indexed":true}],"type":"event","name":"StakerUndelegated","anonymous":false},{"inputs":[{"internalType":"contract IStrategy","name":"strategy","type":"address","indexed":false},{"internalType":"uint256","name":"previousValue","type":"uint256","indexed":false},{"internalType":"uint256","name":"newValue","type":"uint256","indexed":false}],"type":"event","name":"StrategyWithdrawalDelayBlocksSet","anonymous":false},{"inputs":[{"internalType":"address","name":"account","type":"address","indexed":true},{"internalType":"uint256","name":"newPausedStatus","type":"uint256","indexed":false}],"type":"event","name":"Unpaused","anonymous":false},{"inputs":[{"internalType":"bytes32","name":"withdrawalRoot","type":"bytes32","indexed":false}],"type":"event","name":"WithdrawalCompleted","anonymous":false},{"inputs":[{"internalType":"bytes32","name":"withdrawalRoot","type":"bytes32","indexed":false},{"internalType":"struct IDelegationManager.Withdrawal","name":"withdrawal","type":"tuple","components":[{"internalType":"address","name":"staker","type":"address"},{"internalType":"address","name":"delegatedTo","type":"address"},{"internalType":"address","name":"withdrawer","type":"address"},{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"uint32","name":"startBlock","type":"uint32"},{"internalType":"contract IStrategy[]","name":"strategies","type":"address[]"},{"internalType":"uint256[]","name":"shares","type":"uint256[]"}],"indexed":false}],"type":"event","name":"WithdrawalQueued","anonymous":false},{"inputs":[],"stateMutability":"view","type":"function","name":"DELEGATION_APPROVAL_TYPEHASH","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}]},{"inputs":[],"stateMutability":"view","type":"function","name":"DOMAIN_TYPEHASH","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}]},{"inputs":[],"stateMutability":"view","type":"function","name":"MAX_STAKER_OPT_OUT_WINDOW_BLOCKS","outputs":[{"internalType":"uint256","name":"","type":"uint256"}]},{"inputs":[],"stateMutability":"view","type":"function","name":"MAX_WITHDRAWAL_DELAY_BLOCKS","outputs":[{"internalType":"uint256","name":"","type":"uint256"}]},{"inputs":[],"stateMutability":"view","type":"function","name":"STAKER_DELEGATION_TYPEHASH","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}]},{"inputs":[],"stateMutability":"view","type":"function","name":"beaconChainETHStrategy","outputs":[{"internalType":"contract IStrategy","name":"","type":"address"}]},{"inputs":[{"internalType":"address","name":"staker","type":"address"},{"internalType":"address","name":"operator","type":"address"},{"internalType":"uint256","name":"expiry","type":"uint256"}],"stateMutability":"view","type":"function","name":"calculateCurrentStakerDelegationDigestHash","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}]},{"inputs":[{"internalType":"address","name":"staker","type":"address"},{"internalType":"address","name":"operator","type":"address"},{"internalType":"address","name":"_delegationApprover","type":"address"},{"internalType":"bytes32","name":"approverSalt","type":"bytes32"},{"internalType":"uint256","name":"expiry","type":"uint256"}],"stateMutability":"view","type":"function","name":"calculateDelegationApprovalDigestHash","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}]},{"inputs":[{"internalType":"address","name":"staker","type":"address"},{"internalType":"uint256","name":"_stakerNonce","type":"uint256"},{"internalType":"address","name":"operator","type":"address"},{"internalType":"uint256","name":"expiry","type":"uint256"}],"stateMutability":"view","type":"function","name":"calculateStakerDelegationDigestHash","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}]},{"inputs":[{"internalType":"struct IDelegationManager.Withdrawal","name":"withdrawal","type":"tuple","components":[{"internalType":"address","name":"staker","type":"address"},{"internalType":"address","name":"delegatedTo","type":"address"},{"internalType":"address","name":"withdrawer","type":"address"},{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"uint32","name":"startBlock","type":"uint32"},{"internalType":"contract IStrategy[]","name":"strategies","type":"address[]"},{"internalType":"uint256[]","name":"shares","type":"uint256[]"}]}],"stateMutability":"pure","type":"function","name":"calculateWithdrawalRoot","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}]},{"inputs":[{"internalType":"struct IDelegationManager.Withdrawal","name":"withdrawal","type":"tuple","components":[{"internalType":"address","name":"staker","type":"address"},{"internalType":"address","name":"delegatedTo","type":"address"},{"internalType":"address","name":"withdrawer","type":"address"},{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"uint32","name":"startBlock","type":"uint32"},{"internalType":"contract IStrategy[]","name":"strategies","type":"address[]"},{"internalType":"uint256[]","name":"shares","type":"uint256[]"}]},{"internalType":"contract IERC20[]","name":"tokens","type":"address[]"},{"internalType":"uint256","name":"middlewareTimesIndex","type":"uint256"},{"internalType":"bool","name":"receiveAsTokens","type":"bool"}],"stateMutability":"nonpayable","type":"function","name":"completeQueuedWithdrawal"},{"inputs":[{"internalType":"struct IDelegationManager.Withdrawal[]","name":"withdrawals","type":"tuple[]","components":[{"internalType":"address","name":"staker","type":"address"},{"internalType":"address","name":"delegatedTo","type":"address"},{"internalType":"address","name":"withdrawer","type":"address"},{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"uint32","name":"startBlock","type":"uint32"},{"internalType":"contract IStrategy[]","name":"strategies","type":"address[]"},{"internalType":"uint256[]","name":"shares","type":"uint256[]"}]},{"internalType":"contract IERC20[][]","name":"tokens","type":"address[][]"},{"internalType":"uint256[]","name":"middlewareTimesIndexes","type":"uint256[]"},{"internalType":"bool[]","name":"receiveAsTokens","type":"bool[]"}],"stateMutability":"nonpayable","type":"function","name":"completeQueuedWithdrawals"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function","name":"cumulativeWithdrawalsQueued","outputs":[{"internalType":"uint256","name":"","type":"uint256"}]},{"inputs":[{"internalType":"address","name":"staker","type":"address"},{"internalType":"contract IStrategy","name":"strategy","type":"address"},{"internalType":"uint256","name":"shares","type":"uint256"}],"stateMutability":"nonpayable","type":"function","name":"decreaseDelegatedShares"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"struct ISignatureUtils.SignatureWithExpiry","name":"approverSignatureAndExpiry","type":"tuple","components":[{"internalType":"bytes","name":"signature","type":"bytes"},{"internalType":"uint256","name":"expiry","type":"uint256"}]},{"internalType":"bytes32","name":"approverSalt","type":"bytes32"}],"stateMutability":"nonpayable","type":"function","name":"delegateTo"},{"inputs":[{"internalType":"address","name":"staker","type":"address"},{"internalType":"address","name":"operator","type":"address"},{"internalType":"struct ISignatureUtils.SignatureWithExpiry","name":"stakerSignatureAndExpiry","type":"tuple","components":[{"internalType":"bytes","name":"signature","type":"bytes"},{"internalType":"uint256","name":"expiry","type":"uint256"}]},{"internalType":"struct ISignatureUtils.SignatureWithExpiry","name":"approverSignatureAndExpiry","type":"tuple","components":[{"internalType":"bytes","name":"signature","type":"bytes"},{"internalType":"uint256","name":"expiry","type":"uint256"}]},{"internalType":"bytes32","name":"approverSalt","type":"bytes32"}],"stateMutability":"nonpayable","type":"function","name":"delegateToBySignature"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function","name":"delegatedTo","outputs":[{"internalType":"address","name":"","type":"address"}]},{"inputs":[{"internalType":"address","name":"operator","type":"address"}],"stateMutability":"view","type":"function","name":"delegationApprover","outputs":[{"internalType":"address","name":"","type":"address"}]},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function","name":"delegationApproverSaltIsSpent","outputs":[{"internalType":"bool","name":"","type":"bool"}]},{"inputs":[],"stateMutability":"view","type":"function","name":"domainSeparator","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}]},{"inputs":[],"stateMutability":"view","type":"function","name":"eigenPodManager","outputs":[{"internalType":"contract IEigenPodManager","name":"","type":"address"}]},{"inputs":[{"internalType":"address","name":"staker","type":"address"}],"stateMutability":"view","type":"function","name":"getDelegatableShares","outputs":[{"internalType":"contract IStrategy[]","name":"","type":"address[]"},{"internalType":"uint256[]","name":"","type":"uint256[]"}]},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"contract IStrategy[]","name":"strategies","type":"address[]"}],"stateMutability":"view","type":"function","name":"getOperatorShares","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}]},{"inputs":[{"internalType":"contract IStrategy[]","name":"strategies","type":"address[]"}],"stateMutability":"view","type":"function","name":"getWithdrawalDelay","outputs":[{"internalType":"uint256","name":"","type":"uint256"}]},{"inputs":[{"internalType":"address","name":"staker","type":"address"},{"internalType":"contract IStrategy","name":"strategy","type":"address"},{"internalType":"uint256","name":"shares","type":"uint256"}],"stateMutability":"nonpayable","type":"function","name":"increaseDelegatedShares"},{"inputs":[{"internalType":"address","name":"initialOwner","type":"address"},{"internalType":"contract IPauserRegistry","name":"_pauserRegistry","type":"address"},{"internalType":"uint256","name":"initialPausedStatus","type":"uint256"},{"internalType":"uint256","name":"_minWithdrawalDelayBlocks","type":"uint256"},{"internalType":"contract IStrategy[]","name":"_strategies","type":"address[]"},{"internalType":"uint256[]","name":"_withdrawalDelayBlocks","type":"uint256[]"}],"stateMutability":"nonpayable","type":"function","name":"initialize"},{"inputs":[{"internalType":"address","name":"staker","type":"address"}],"stateMutability":"view","type":"function","name":"isDelegated","outputs":[{"internalType":"bool","name":"","type":"bool"}]},{"inputs":[{"internalType":"address","name":"operator","type":"address"}],"stateMutability":"view","type":"function","name":"isOperator","outputs":[{"internalType":"bool","name":"","type":"bool"}]},{"inputs":[],"stateMutability":"view","type":"function","name":"minWithdrawalDelayBlocks","outputs":[{"internalType":"uint256","name":"","type":"uint256"}]},{"inputs":[{"internalType":"struct IDelegationManager.OperatorDetails","name":"newOperatorDetails","type":"tuple","components":[{"internalType":"address","name":"__deprecated_earningsReceiver","type":"address"},{"internalType":"address","name":"delegationApprover","type":"address"},{"internalType":"uint32","name":"stakerOptOutWindowBlocks","type":"uint32"}]}],"stateMutability":"nonpayable","type":"function","name":"modifyOperatorDetails"},{"inputs":[{"internalType":"address","name":"operator","type":"address"}],"stateMutability":"view","type":"function","name":"operatorDetails","outputs":[{"internalType":"struct IDelegationManager.OperatorDetails","name":"","type":"tuple","components":[{"internalType":"address","name":"__deprecated_earningsReceiver","type":"address"},{"internalType":"address","name":"delegationApprover","type":"address"},{"internalType":"uint32","name":"stakerOptOutWindowBlocks","type":"uint32"}]}]},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"contract IStrategy","name":"","type":"address"}],"stateMutability":"view","type":"function","name":"operatorShares","outputs":[{"internalType":"uint256","name":"","type":"uint256"}]},{"inputs":[],"stateMutability":"view","type":"function","name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}]},{"inputs":[{"internalType":"uint256","name":"newPausedStatus","type":"uint256"}],"stateMutability":"nonpayable","type":"function","name":"pause"},{"inputs":[],"stateMutability":"nonpayable","type":"function","name":"pauseAll"},{"inputs":[{"internalType":"uint8","name":"index","type":"uint8"}],"stateMutability":"view","type":"function","name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}]},{"inputs":[],"stateMutability":"view","type":"function","name":"paused","outputs":[{"internalType":"uint256","name":"","type":"uint256"}]},{"inputs":[],"stateMutability":"view","type":"function","name":"pauserRegistry","outputs":[{"internalType":"contract IPauserRegistry","name":"","type":"address"}]},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function","name":"pendingWithdrawals","outputs":[{"internalType":"bool","name":"","type":"bool"}]},{"inputs":[{"internalType":"struct IDelegationManager.QueuedWithdrawalParams[]","name":"queuedWithdrawalParams","type":"tuple[]","components":[{"internalType":"contract IStrategy[]","name":"strategies","type":"address[]"},{"internalType":"uint256[]","name":"shares","type":"uint256[]"},{"internalType":"address","name":"withdrawer","type":"address"}]}],"stateMutability":"nonpayable","type":"function","name":"queueWithdrawals","outputs":[{"internalType":"bytes32[]","name":"","type":"bytes32[]"}]},{"inputs":[{"internalType":"struct IDelegationManager.OperatorDetails","name":"registeringOperatorDetails","type":"tuple","components":[{"internalType":"address","name":"__deprecated_earningsReceiver","type":"address"},{"internalType":"address","name":"delegationApprover","type":"address"},{"internalType":"uint32","name":"stakerOptOutWindowBlocks","type":"uint32"}]},{"internalType":"string","name":"metadataURI","type":"string"}],"stateMutability":"nonpayable","type":"function","name":"registerAsOperator"},{"inputs":[],"stateMutability":"nonpayable","type":"function","name":"renounceOwnership"},{"inputs":[{"internalType":"uint256","name":"newMinWithdrawalDelayBlocks","type":"uint256"}],"stateMutability":"nonpayable","type":"function","name":"setMinWithdrawalDelayBlocks"},{"inputs":[{"internalType":"contract IPauserRegistry","name":"newPauserRegistry","type":"address"}],"stateMutability":"nonpayable","type":"function","name":"setPauserRegistry"},{"inputs":[{"internalType":"contract IStrategy[]","name":"strategies","type":"address[]"},{"internalType":"uint256[]","name":"withdrawalDelayBlocks","type":"uint256[]"}],"stateMutability":"nonpayable","type":"function","name":"setStrategyWithdrawalDelayBlocks"},{"inputs":[],"stateMutability":"view","type":"function","name":"slasher","outputs":[{"internalType":"contract ISlasher","name":"","type":"address"}]},{"inputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function","name":"stakerNonce","outputs":[{"internalType":"uint256","name":"","type":"uint256"}]},{"inputs":[{"internalType":"address","name":"operator","type":"address"}],"stateMutability":"view","type":"function","name":"stakerOptOutWindowBlocks","outputs":[{"internalType":"uint256","name":"","type":"uint256"}]},{"inputs":[],"stateMutability":"view","type":"function","name":"strategyManager","outputs":[{"internalType":"contract IStrategyManager","name":"","type":"address"}]},{"inputs":[{"internalType":"contract IStrategy","name":"","type":"address"}],"stateMutability":"view","type":"function","name":"strategyWithdrawalDelayBlocks","outputs":[{"internalType":"uint256","name":"","type":"uint256"}]},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"stateMutability":"nonpayable","type":"function","name":"transferOwnership"},{"inputs":[{"internalType":"address","name":"staker","type":"address"}],"stateMutability":"nonpayable","type":"function","name":"undelegate","outputs":[{"internalType":"bytes32[]","name":"withdrawalRoots","type":"bytes32[]"}]},{"inputs":[{"internalType":"uint256","name":"newPausedStatus","type":"uint256"}],"stateMutability":"nonpayable","type":"function","name":"unpause"},{"inputs":[{"internalType":"string","name":"metadataURI","type":"string"}],"stateMutability":"nonpayable","type":"function","name":"updateOperatorMetadataURI"}],"devdoc":{"kind":"dev","methods":{"calculateCurrentStakerDelegationDigestHash(address,address,uint256)":{"params":{"expiry":"The desired expiry time of the staker's signature","operator":"The operator who is being delegated to","staker":"The signing staker"}},"calculateDelegationApprovalDigestHash(address,address,address,bytes32,uint256)":{"params":{"_delegationApprover":"the operator's `delegationApprover` who will be signing the delegationHash (in general)","approverSalt":"A unique and single use value associated with the approver signature.","expiry":"Time after which the approver's signature becomes invalid","operator":"The account receiving delegated stake","staker":"The account delegating their stake"}},"calculateStakerDelegationDigestHash(address,uint256,address,uint256)":{"params":{"_stakerNonce":"The nonce of the staker. In practice we use the staker's current nonce, stored at `stakerNonce[staker]`","expiry":"The desired expiry time of the staker's signature","operator":"The operator who is being delegated to","staker":"The signing staker"}},"completeQueuedWithdrawal((address,address,address,uint256,uint32,address[],uint256[]),address[],uint256,bool)":{"details":"middlewareTimesIndex is unused, but will be used in the Slasher eventuallybeaconChainETHStrategy shares are non-transferrable, so if `receiveAsTokens = false` and `withdrawal.withdrawer != withdrawal.staker`, note that any beaconChainETHStrategy shares in the `withdrawal` will be _returned to the staker_, rather than transferred to the withdrawer, unlike shares in any other strategies, which will be transferred to the withdrawer.","params":{"middlewareTimesIndex":"is the index in the operator that the staker who triggered the withdrawal was delegated to's middleware times array","receiveAsTokens":"If true, the shares specified in the withdrawal will be withdrawn from the specified strategies themselves and sent to the caller, through calls to `withdrawal.strategies[i].withdraw`. If false, then the shares in the specified strategies will simply be transferred to the caller directly.","tokens":"Array in which the i-th entry specifies the `token` input to the 'withdraw' function of the i-th Strategy in the `withdrawal.strategies` array. This input can be provided with zero length if `receiveAsTokens` is set to 'false' (since in that case, this input will be unused)","withdrawal":"The Withdrawal to complete."}},"completeQueuedWithdrawals((address,address,address,uint256,uint32,address[],uint256[])[],address[][],uint256[],bool[])":{"details":"See `completeQueuedWithdrawal` for relevant dev tags","params":{"middlewareTimesIndexes":"One index to reference per Withdrawal. See `completeQueuedWithdrawal` for the usage of a single index.","receiveAsTokens":"Whether or not to complete each withdrawal as tokens. See `completeQueuedWithdrawal` for the usage of a single boolean.","tokens":"Array of tokens for each Withdrawal. See `completeQueuedWithdrawal` for the usage of a single array.","withdrawals":"The Withdrawals to complete."}},"constructor":{"details":"Initializes the immutable addresses of the strategy mananger and slasher."},"decreaseDelegatedShares(address,address,uint256)":{"details":"*If the staker is actively delegated*, then decreases the `staker`'s delegated shares in `strategy` by `shares`. Otherwise does nothing.Callable only by the StrategyManager or EigenPodManager.","params":{"shares":"The number of shares to decrease.","staker":"The address to increase the delegated shares for their operator.","strategy":"The strategy in which to decrease the delegated shares."}},"delegateTo(address,(bytes,uint256),bytes32)":{"details":"The approverSignatureAndExpiry is used in the event that: 1) the operator's `delegationApprover` address is set to a non-zero value. AND 2) neither the operator nor their `delegationApprover` is the `msg.sender`, since in the event that the operator or their delegationApprover is the `msg.sender`, then approval is assumed.In the event that `approverSignatureAndExpiry` is not checked, its content is ignored entirely; it's recommended to use an empty input in this case to save on complexity + gas costs","params":{"approverSalt":"A unique single use value tied to an individual signature.","approverSignatureAndExpiry":"Verifies the operator approves of this delegation","operator":"The account (`msg.sender`) is delegating its assets to for use in serving applications built on EigenLayer."}},"delegateToBySignature(address,address,(bytes,uint256),(bytes,uint256),bytes32)":{"details":"If `staker` is an EOA, then `stakerSignature` is verified to be a valid ECDSA stakerSignature from `staker`, indicating their intention for this action.If `staker` is a contract, then `stakerSignature` will be checked according to EIP-1271.the operator's `delegationApprover` address is set to a non-zero value.neither the operator nor their `delegationApprover` is the `msg.sender`, since in the event that the operator or their delegationApprover is the `msg.sender`, then approval is assumed.This function will revert if the current `block.timestamp` is equal to or exceeds the expiryIn the case that `approverSignatureAndExpiry` is not checked, its content is ignored entirely; it's recommended to use an empty input in this case to save on complexity + gas costs","params":{"approverSalt":"Is a salt used to help guarantee signature uniqueness. Each salt can only be used once by a given approver.","approverSignatureAndExpiry":"is a parameter that will be used for verifying that the operator approves of this delegation action in the event that:","operator":"The account (`staker`) is delegating its assets to for use in serving applications built on EigenLayer.","staker":"The account delegating stake to an `operator` account","stakerSignatureAndExpiry":"Signed data from the staker authorizing delegating stake to an operator"}},"domainSeparator()":{"details":"The domain separator will change in the event of a fork that changes the ChainID.By introducing a domain separator the DApp developers are guaranteed that there can be no signature collision. for more detailed information please read EIP-712."},"getDelegatableShares(address)":{"details":"Returns two empty arrays in the case that the Staker has no actively-delegateable shares."},"getWithdrawalDelay(address[])":{"params":{"strategies":"The strategies to check withdrawal delays for"}},"increaseDelegatedShares(address,address,uint256)":{"details":"*If the staker is actively delegated*, then increases the `staker`'s delegated shares in `strategy` by `shares`. Otherwise does nothing.Callable only by the StrategyManager or EigenPodManager.","params":{"shares":"The number of shares to increase.","staker":"The address to increase the delegated shares for their operator.","strategy":"The strategy in which to increase the delegated shares."}},"initialize(address,address,uint256,uint256,address[],uint256[])":{"details":"Initializes the addresses of the initial owner, pauser registry, and paused status. minWithdrawalDelayBlocks is set only once here"},"modifyOperatorDetails((address,address,uint32))":{"details":"The caller must have previously registered as an operator in EigenLayer.","params":{"newOperatorDetails":"is the updated `OperatorDetails` for the operator, to replace their current OperatorDetails`."}},"owner()":{"details":"Returns the address of the current owner."},"pause(uint256)":{"details":"This function can only pause functionality, and thus cannot 'unflip' any bit in `_paused` from 1 to 0.","params":{"newPausedStatus":"represents the new value for `_paused` to take, which means it may flip several bits at once."}},"registerAsOperator((address,address,uint32),string)":{"details":"Once an operator is registered, they cannot 'deregister' as an operator, and they will forever be considered \"delegated to themself\".This function will revert if the caller is already delegated to an operator.Note that the `metadataURI` is *never stored * and is only emitted in the `OperatorMetadataURIUpdated` event","params":{"metadataURI":"is a URI for the operator's metadata, i.e. a link providing more details on the operator.","registeringOperatorDetails":"is the `OperatorDetails` for the operator."}},"renounceOwnership()":{"details":"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner."},"setMinWithdrawalDelayBlocks(uint256)":{"params":{"newMinWithdrawalDelayBlocks":"new value of `minWithdrawalDelayBlocks`."}},"setStrategyWithdrawalDelayBlocks(address[],uint256[])":{"params":{"strategies":"The strategies to set the minimum withdrawal delay blocks for","withdrawalDelayBlocks":"The minimum withdrawal delay blocks to set for each strategy"}},"transferOwnership(address)":{"details":"Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner."},"unpause(uint256)":{"details":"This function can only unpause functionality, and thus cannot 'flip' any bit in `_paused` from 0 to 1.","params":{"newPausedStatus":"represents the new value for `_paused` to take, which means it may flip several bits at once."}},"updateOperatorMetadataURI(string)":{"params":{"metadataURI":"The URI for metadata associated with an operator"}}},"version":1},"userdoc":{"kind":"user","methods":{"DELEGATION_APPROVAL_TYPEHASH()":{"notice":"The EIP-712 typehash for the `DelegationApproval` struct used by the contract"},"DOMAIN_TYPEHASH()":{"notice":"The EIP-712 typehash for the contract's domain"},"STAKER_DELEGATION_TYPEHASH()":{"notice":"The EIP-712 typehash for the `StakerDelegation` struct used by the contract"},"beaconChainETHStrategy()":{"notice":"Canonical, virtual beacon chain ETH strategy"},"calculateCurrentStakerDelegationDigestHash(address,address,uint256)":{"notice":"Calculates the digestHash for a `staker` to sign to delegate to an `operator`"},"calculateDelegationApprovalDigestHash(address,address,address,bytes32,uint256)":{"notice":"Calculates the digest hash to be signed by the operator's delegationApprove and used in the `delegateTo` and `delegateToBySignature` functions."},"calculateStakerDelegationDigestHash(address,uint256,address,uint256)":{"notice":"Calculates the digest hash to be signed and used in the `delegateToBySignature` function"},"calculateWithdrawalRoot((address,address,address,uint256,uint32,address[],uint256[]))":{"notice":"Returns the keccak256 hash of `withdrawal`."},"completeQueuedWithdrawal((address,address,address,uint256,uint32,address[],uint256[]),address[],uint256,bool)":{"notice":"Used to complete the specified `withdrawal`. The caller must match `withdrawal.withdrawer`"},"completeQueuedWithdrawals((address,address,address,uint256,uint32,address[],uint256[])[],address[][],uint256[],bool[])":{"notice":"Array-ified version of `completeQueuedWithdrawal`. Used to complete the specified `withdrawals`. The function caller must match `withdrawals[...].withdrawer`"},"cumulativeWithdrawalsQueued(address)":{"notice":"Mapping: staker => cumulative number of queued withdrawals they have ever initiated."},"decreaseDelegatedShares(address,address,uint256)":{"notice":"Decreases a staker's delegated share balance in a strategy."},"delegateTo(address,(bytes,uint256),bytes32)":{"notice":"Caller delegates their stake to an operator."},"delegateToBySignature(address,address,(bytes,uint256),(bytes,uint256),bytes32)":{"notice":"Caller delegates a staker's stake to an operator with valid signatures from both parties."},"delegatedTo(address)":{"notice":"Mapping: staker => operator whom the staker is currently delegated to."},"delegationApprover(address)":{"notice":"Returns the delegationApprover account for an operator"},"delegationApproverSaltIsSpent(address,bytes32)":{"notice":"Mapping: delegationApprover => 32-byte salt => whether or not the salt has already been used by the delegationApprover."},"domainSeparator()":{"notice":"Getter function for the current EIP-712 domain separator for this contract."},"eigenPodManager()":{"notice":"The EigenPodManager contract for EigenLayer"},"getDelegatableShares(address)":{"notice":"Returns the number of actively-delegatable shares a staker has across all strategies."},"getOperatorShares(address,address[])":{"notice":"Given array of strategies, returns array of shares for the operator"},"getWithdrawalDelay(address[])":{"notice":"Given a list of strategies, return the minimum number of blocks that must pass to withdraw from all the inputted strategies. Return value is >= minWithdrawalDelayBlocks as this is the global min withdrawal delay."},"increaseDelegatedShares(address,address,uint256)":{"notice":"Increases a staker's delegated share balance in a strategy."},"isDelegated(address)":{"notice":"Returns 'true' if `staker` *is* actively delegated, and 'false' otherwise."},"isOperator(address)":{"notice":"Returns true is an operator has previously registered for delegation."},"minWithdrawalDelayBlocks()":{"notice":"Global minimum withdrawal delay for all strategy withdrawals. In a prior Goerli release, we only had a global min withdrawal delay across all strategies. In addition, we now also configure withdrawal delays on a per-strategy basis. To withdraw from a strategy, max(minWithdrawalDelayBlocks, strategyWithdrawalDelayBlocks[strategy]) number of blocks must have passed. See mapping strategyWithdrawalDelayBlocks below for per-strategy withdrawal delays."},"modifyOperatorDetails((address,address,uint32))":{"notice":"Updates an operator's stored `OperatorDetails`."},"operatorDetails(address)":{"notice":"Returns the OperatorDetails struct associated with an `operator`."},"operatorShares(address,address)":{"notice":"returns the total number of shares in `strategy` that are delegated to `operator`.Mapping: operator => strategy => total number of shares in the strategy delegated to the operator."},"pause(uint256)":{"notice":"This function is used to pause an EigenLayer contract's functionality. It is permissioned to the `pauser` address, which is expected to be a low threshold multisig."},"pauseAll()":{"notice":"Alias for `pause(type(uint256).max)`."},"paused()":{"notice":"Returns the current paused status as a uint256."},"paused(uint8)":{"notice":"Returns 'true' if the `indexed`th bit of `_paused` is 1, and 'false' otherwise"},"pauserRegistry()":{"notice":"Address of the `PauserRegistry` contract that this contract defers to for determining access control (for pausing)."},"pendingWithdrawals(bytes32)":{"notice":"Mapping: hash of withdrawal inputs, aka 'withdrawalRoot' => whether the withdrawal is pending"},"queueWithdrawals((address[],uint256[],address)[])":{"notice":"Allows a staker to withdraw some shares. Withdrawn shares/strategies are immediately removed from the staker. If the staker is delegated, withdrawn shares/strategies are also removed from their operator. All withdrawn shares/strategies are placed in a queue and can be fully withdrawn after a delay."},"registerAsOperator((address,address,uint32),string)":{"notice":"Registers the caller as an operator in EigenLayer."},"setMinWithdrawalDelayBlocks(uint256)":{"notice":"Owner-only function for modifying the value of the `minWithdrawalDelayBlocks` variable."},"setPauserRegistry(address)":{"notice":"Allows the unpauser to set a new pauser registry"},"setStrategyWithdrawalDelayBlocks(address[],uint256[])":{"notice":"Called by owner to set the minimum withdrawal delay blocks for each passed in strategy Note that the min number of blocks to complete a withdrawal of a strategy is MAX(minWithdrawalDelayBlocks, strategyWithdrawalDelayBlocks[strategy])"},"slasher()":{"notice":"The Slasher contract for EigenLayer"},"stakerNonce(address)":{"notice":"Mapping: staker => number of signed messages (used in `delegateToBySignature`) from the staker that this contract has already checked."},"stakerOptOutWindowBlocks(address)":{"notice":"Returns the stakerOptOutWindowBlocks for an operator"},"strategyManager()":{"notice":"The StrategyManager contract for EigenLayer"},"strategyWithdrawalDelayBlocks(address)":{"notice":"Minimum delay enforced by this contract per Strategy for completing queued withdrawals. Measured in blocks, and adjustable by this contract's owner, up to a maximum of `MAX_WITHDRAWAL_DELAY_BLOCKS`. Minimum value is 0 (i.e. no delay enforced)."},"undelegate(address)":{"notice":"Allows the staker, the staker's operator, or that operator's delegationApprover to undelegate a staker from their operator. Undelegation immediately removes ALL active shares/strategies from both the staker and operator, and places the shares and strategies in the withdrawal queue"},"unpause(uint256)":{"notice":"This function is used to unpause an EigenLayer contract's functionality. It is permissioned to the `unpauser` address, which is expected to be a high threshold multisig or governance contract."},"updateOperatorMetadataURI(string)":{"notice":"Called by an operator to emit an `OperatorMetadataURIUpdated` event indicating the information has updated."}},"version":1}},"settings":{"remappings":["@openzeppelin-upgrades-v4.9.0/=lib/eigenlayer-middleware/lib/eigenlayer-contracts/lib/openzeppelin-contracts-upgradeable-v4.9.0/","@openzeppelin-upgrades/=lib/eigenlayer-middleware/lib/openzeppelin-contracts-upgradeable/","@openzeppelin-v4.9.0/=lib/eigenlayer-middleware/lib/eigenlayer-contracts/lib/openzeppelin-contracts-v4.9.0/","@openzeppelin/=lib/eigenlayer-middleware/lib/openzeppelin-contracts/","ds-test/=lib/eigenlayer-middleware/lib/ds-test/src/","eigenlayer-contracts/=lib/eigenlayer-middleware/lib/eigenlayer-contracts/","eigenlayer-core-contracts/=lib/eigenlayer-middleware/lib/eigenlayer-contracts/src/contracts/core/","eigenlayer-core/=lib/eigenlayer-middleware/lib/eigenlayer-contracts/src/","eigenlayer-middleware/=lib/eigenlayer-middleware/src/","eigenlayer-scripts/=lib/eigenlayer-middleware/lib/eigenlayer-contracts/script/","erc4626-tests/=lib/eigenlayer-middleware/lib/eigenlayer-contracts/lib/openzeppelin-contracts-upgradeable-v4.9.0/lib/erc4626-tests/","forge-std/=lib/forge-std/src/","openzeppelin-contracts-upgradeable-v4.9.0/=lib/eigenlayer-middleware/lib/eigenlayer-contracts/lib/openzeppelin-contracts-upgradeable-v4.9.0/","openzeppelin-contracts-upgradeable/=lib/eigenlayer-middleware/lib/openzeppelin-contracts-upgradeable/","openzeppelin-contracts-v4.9.0/=lib/eigenlayer-middleware/lib/eigenlayer-contracts/lib/openzeppelin-contracts-v4.9.0/","openzeppelin-contracts/=lib/eigenlayer-middleware/lib/openzeppelin-contracts/","openzeppelin/=lib/eigenlayer-middleware/lib/eigenlayer-contracts/lib/openzeppelin-contracts-upgradeable-v4.9.0/contracts/"],"optimizer":{"enabled":true,"runs":200},"metadata":{"bytecodeHash":"ipfs"},"compilationTarget":{"lib/eigenlayer-middleware/lib/eigenlayer-contracts/src/contracts/core/DelegationManager.sol":"DelegationManager"},"evmVersion":"london","libraries":{}},"sources":{"lib/eigenlayer-middleware/lib/eigenlayer-contracts/src/contracts/core/DelegationManager.sol":{"keccak256":"0xebb7560a956ece70b08cf36bc548e70c7a04ad4f8718eba194927bcfc03c6190","urls":["bzz-raw://ac5fe6c05d4268c8fd5853e44662bf9d306313e014d27542f02abd62265168d2","dweb:/ipfs/QmTXcATcpgFpAD8FLmoeWoGYKTh3rRjxntsHCP7wcTWkwY"],"license":"BUSL-1.1"},"lib/eigenlayer-middleware/lib/eigenlayer-contracts/src/contracts/core/DelegationManagerStorage.sol":{"keccak256":"0xd834e9bc2f4d03545102004ffa9651e5bf9b559d43e4102bf2955314ef2d94f5","urls":["bzz-raw://9c7670995b7ca634f94848f426b36278f98389c120b177b737ef325bd457ca00","dweb:/ipfs/QmRtLyA4Kq5TrhhhXQAp2jAH7bJ5gqbjrr1JesD6wRbqqV"],"license":"BUSL-1.1"},"lib/eigenlayer-middleware/lib/eigenlayer-contracts/src/contracts/interfaces/IBeaconChainOracle.sol":{"keccak256":"0x0fef07aa6179c77198f1514e12e628aa1c876e04f9c181ec853a322179e5be00","urls":["bzz-raw://51438325876cc2d4c77f58488a7e27b488015d1b663c50be6a5cafbd73b9c983","dweb:/ipfs/QmViCuGoYZzi6wtXA8PPKigqVv3KMuNxEVQ1Td9dGqjL18"],"license":"BUSL-1.1"},"lib/eigenlayer-middleware/lib/eigenlayer-contracts/src/contracts/interfaces/IDelegationManager.sol":{"keccak256":"0xab76a9f4eff865cbb689f627cf98263488765519d7a4ec5ffbcb0ca4972842f9","urls":["bzz-raw://ff57ce18e8350bf39f190645db0988bc0f1279f1872150a114a1b520c38a2914","dweb:/ipfs/QmSsUXkNUqYuJgGRumHTSs9rAaboGjecotcM4xHrdBYWaZ"],"license":"BUSL-1.1"},"lib/eigenlayer-middleware/lib/eigenlayer-contracts/src/contracts/interfaces/IETHPOSDeposit.sol":{"keccak256":"0x2e60e5f4b0da0a0a4e2a07c63141120998559970c21deac743ea0c64a60a880c","urls":["bzz-raw://e635c346bde5b7ade9bcf35bc733081520cb86015be4fbc6e761e6e9482c4c91","dweb:/ipfs/QmRoeazEnbFn5SPSWAkoFK2gSN9DMp3hJAnrLWuL2sKutz"],"license":"CC0-1.0"},"lib/eigenlayer-middleware/lib/eigenlayer-contracts/src/contracts/interfaces/IEigenPod.sol":{"keccak256":"0xb50c36ad96b6679bb80fd8331f949cbfbcba0f529026e1421a4d2bae64396eba","urls":["bzz-raw://5719181d780120f1e688c0da276992a8caf185815917f453b3550537c31ed4cc","dweb:/ipfs/QmYprRC5ZEXhz3zAUND5E8Xjn6s5TL8ZF8QbnndVq7aVPR"],"license":"BUSL-1.1"},"lib/eigenlayer-middleware/lib/eigenlayer-contracts/src/contracts/interfaces/IEigenPodManager.sol":{"keccak256":"0xd8a64dbed03d3a5cdbefe1af75968f2dde07f973749c2ef5197bf7187c3e448c","urls":["bzz-raw://27ccc7c1fd9352e9f9b357c9063d255dc0ed9583f43db09f786ac7497d7846b8","dweb:/ipfs/QmeJzuJkE9m2NUNwZSp4tGZEZmih1LeucePup8hzMVDRbG"],"license":"BUSL-1.1"},"lib/eigenlayer-middleware/lib/eigenlayer-contracts/src/contracts/interfaces/IPausable.sol":{"keccak256":"0x98cffc894842947377e24c1d375813a1120dd73a84c29782ab68404e109cb34f","urls":["bzz-raw://b3474f6c350ceaee57cbdfb08fb48835d0c6e81ae8ebfbb9667899584a139324","dweb:/ipfs/QmWELKtksdtWxQbqAccd8yGyhKqrgPZXTADKR7BuT27Zg5"],"license":"BUSL-1.1"},"lib/eigenlayer-middleware/lib/eigenlayer-contracts/src/contracts/interfaces/IPauserRegistry.sol":{"keccak256":"0x9de8dd682bc0d812bbd6583c0231cbf35448d5eff58b74a93efa64cb9a768c49","urls":["bzz-raw://c00d6c675b9c72b092d287fe85fd37782588df32b8eb59ab4c7db7a86be25e7d","dweb:/ipfs/QmeYokY3HhAdbBaCPdHg3PgQEdRCDFEJy3Wf7VtgHBkQSx"],"license":"BUSL-1.1"},"lib/eigenlayer-middleware/lib/eigenlayer-contracts/src/contracts/interfaces/ISignatureUtils.sol":{"keccak256":"0x5e52482a31d94401a8502f3014c4aada1142b4450fc0596dff8e1866a85fe092","urls":["bzz-raw://17dc326c9361bc1453379f26545963557b2883b0c88bc07d4477e04dbcc0cc8c","dweb:/ipfs/QmZXT7A816W5JH2ymirE2ETaJttqztFCsEL22AV8oEfCK9"],"license":"BUSL-1.1"},"lib/eigenlayer-middleware/lib/eigenlayer-contracts/src/contracts/interfaces/ISlasher.sol":{"keccak256":"0x45dfaa2cfdde87f48a6ee38bb6fb739847aef7cf3f6137bdcd8c8a330559ec79","urls":["bzz-raw://1b7f6bd75b42fcaa91ceb7140cb2c41926a1fe6ee2d3161e4fe6186b181ba232","dweb:/ipfs/QmZjbdKiSs33C9i3GDc3sdD39Pz4YPkDoKftowoUF4kHmY"],"license":"BUSL-1.1"},"lib/eigenlayer-middleware/lib/eigenlayer-contracts/src/contracts/interfaces/IStrategy.sol":{"keccak256":"0xc530c6a944b70051fd0dac0222de9a4b5baadeaf94ad194daac6ad8d2ace7420","urls":["bzz-raw://3767df0364ce835b52e786d2851431eb9223fe4747602107505477e162231d73","dweb:/ipfs/QmZkH5bKUygQrJomndNaQqkefVRW4rRefCa8HPJ5HMczxJ"],"license":"BUSL-1.1"},"lib/eigenlayer-middleware/lib/eigenlayer-contracts/src/contracts/interfaces/IStrategyManager.sol":{"keccak256":"0x68bf02a443fc8b2f612eba3d39bfefa5f61f78b549f111cdecec5f2c58236a52","urls":["bzz-raw://76bc6875ce74128b861fdac5fd1c0c72f3cc9bacf67fa4a73721b95fb23959ef","dweb:/ipfs/QmPix4WJmf9fXyMZxfgwXEHBcg7V4NAbRqs4HUf5YrSJcM"],"license":"BUSL-1.1"},"lib/eigenlayer-middleware/lib/eigenlayer-contracts/src/contracts/libraries/BeaconChainProofs.sol":{"keccak256":"0x70d89b05c1c5f47b74a07fbb5a2c05e606fed494e749ea98a9915b7be73df377","urls":["bzz-raw://db1d3bfaee69aef53c8b12b492a17584e6d1ac94610cb8b38aad33e1cdd81af7","dweb:/ipfs/QmfVsMTj1hcf9fMEm5RzvtcBN4dMcAKFBgUUDsNDr5XFpq"],"license":"BUSL-1.1"},"lib/eigenlayer-middleware/lib/eigenlayer-contracts/src/contracts/libraries/EIP1271SignatureUtils.sol":{"keccak256":"0xe92d584c47c5828e026a8082af3da38a853e3942c4da7deb705d6470a41afab3","urls":["bzz-raw://1c436c578781fd7d3dffdb24e906819422819f5e9a71d39ee63166a3d5cb3373","dweb:/ipfs/QmP7bJhYqLpwqk2Xq4tqDCUMi2nFAhxxW3Pz36ctE1sbdD"],"license":"BUSL-1.1"},"lib/eigenlayer-middleware/lib/eigenlayer-contracts/src/contracts/libraries/Endian.sol":{"keccak256":"0xf3b72653ba2567a978d4612703fa5f71c5fcd015d8dac7818468f22772d90a9d","urls":["bzz-raw://cee9d09370d968138d775c39525db4cd0768d60d17be7685519de12444e7dd2f","dweb:/ipfs/QmUdGh8wpMei3edKiEWA6S96s9dRt4ekZKJ4nau356X8xQ"],"license":"BUSL-1.1"},"lib/eigenlayer-middleware/lib/eigenlayer-contracts/src/contracts/libraries/Merkle.sol":{"keccak256":"0x9095fc29b96d102b10c02d44b3a6fbfa25593ef6ae4a810363ab885b9e6b0f71","urls":["bzz-raw://0945132d482d56278edddb1d32209903c4d3839c87ba4317aadd97dc23610d0f","dweb:/ipfs/QmVuM2aLRHxitx4rPx3GTYTBCVNcjYn6sHBRr1biUjLBP5"],"license":"MIT"},"lib/eigenlayer-middleware/lib/eigenlayer-contracts/src/contracts/permissions/Pausable.sol":{"keccak256":"0xce8ee0ab28f2bce9e94aa19fffe55bebef080327632ac98ff3ab14994b369bc0","urls":["bzz-raw://5c7e2be97a8840fa2a0434077a36136553a84efd9bff4b46712ce9fddb813a6a","dweb:/ipfs/QmZKvgPxLAbGo1CqTA4AX6MCDPFLSSNt43ZKWRjvvzFp7S"],"license":"BUSL-1.1"},"lib/eigenlayer-middleware/lib/openzeppelin-contracts-upgradeable/contracts/access/OwnableUpgradeable.sol":{"keccak256":"0x247c62047745915c0af6b955470a72d1696ebad4352d7d3011aef1a2463cd888","urls":["bzz-raw://d7fc8396619de513c96b6e00301b88dd790e83542aab918425633a5f7297a15a","dweb:/ipfs/QmXbP4kiZyp7guuS7xe8KaybnwkRPGrBc2Kbi3vhcTfpxb"],"license":"MIT"},"lib/eigenlayer-middleware/lib/openzeppelin-contracts-upgradeable/contracts/proxy/utils/Initializable.sol":{"keccak256":"0x0203dcadc5737d9ef2c211d6fa15d18ebc3b30dfa51903b64870b01a062b0b4e","urls":["bzz-raw://6eb2fd1e9894dbe778f4b8131adecebe570689e63cf892f4e21257bfe1252497","dweb:/ipfs/QmXgUGNfZvrn6N2miv3nooSs7Jm34A41qz94fu2GtDFcx8"],"license":"MIT"},"lib/eigenlayer-middleware/lib/openzeppelin-contracts-upgradeable/contracts/security/ReentrancyGuardUpgradeable.sol":{"keccak256":"0x8cc03c5ac17e8a7396e487cda41fc1f1dfdb91db7d528e6da84bee3b6dd7e167","urls":["bzz-raw://607818f1b44548c2d8268176f73cdb290e1faed971b1061930d92698366e2a11","dweb:/ipfs/QmQibMe3r5no95b6q7isGT5R75V8xSofWEDLXzp95b7LgZ"],"license":"MIT"},"lib/eigenlayer-middleware/lib/openzeppelin-contracts-upgradeable/contracts/utils/AddressUpgradeable.sol":{"keccak256":"0x611aa3f23e59cfdd1863c536776407b3e33d695152a266fa7cfb34440a29a8a3","urls":["bzz-raw://9b4b2110b7f2b3eb32951bc08046fa90feccffa594e1176cb91cdfb0e94726b4","dweb:/ipfs/QmSxLwYjicf9zWFuieRc8WQwE4FisA1Um5jp1iSa731TGt"],"license":"MIT"},"lib/eigenlayer-middleware/lib/openzeppelin-contracts-upgradeable/contracts/utils/ContextUpgradeable.sol":{"keccak256":"0x963ea7f0b48b032eef72fe3a7582edf78408d6f834115b9feadd673a4d5bd149","urls":["bzz-raw://d6520943ea55fdf5f0bafb39ed909f64de17051bc954ff3e88c9e5621412c79c","dweb:/ipfs/QmWZ4rAKTQbNG2HxGs46AcTXShsVytKeLs7CUCdCSv5N7a"],"license":"MIT"},"lib/eigenlayer-middleware/lib/openzeppelin-contracts/contracts/interfaces/IERC1271.sol":{"keccak256":"0x0705a4b1b86d7b0bd8432118f226ba139c44b9dcaba0a6eafba2dd7d0639c544","urls":["bzz-raw://c45b821ef9e882e57c256697a152e108f0f2ad6997609af8904cae99c9bd422e","dweb:/ipfs/QmRKCJW6jjzR5UYZcLpGnhEJ75UVbH6EHkEa49sWx2SKng"],"license":"MIT"},"lib/eigenlayer-middleware/lib/openzeppelin-contracts/contracts/proxy/beacon/IBeacon.sol":{"keccak256":"0xd50a3421ac379ccb1be435fa646d66a65c986b4924f0849839f08692f39dde61","urls":["bzz-raw://ada1e030c0231db8d143b44ce92b4d1158eedb087880cad6d8cc7bd7ebe7b354","dweb:/ipfs/QmWZ2NHZweRpz1U9GF6R1h65ri76dnX7fNxLBeM2t5N5Ce"],"license":"MIT"},"lib/eigenlayer-middleware/lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol":{"keccak256":"0x9750c6b834f7b43000631af5cc30001c5f547b3ceb3635488f140f60e897ea6b","urls":["bzz-raw://5a7d5b1ef5d8d5889ad2ed89d8619c09383b80b72ab226e0fe7bde1636481e34","dweb:/ipfs/QmebXWgtEfumQGBdVeM6c71McLixYXQP5Bk6kKXuoY4Bmr"],"license":"MIT"},"lib/eigenlayer-middleware/lib/openzeppelin-contracts/contracts/utils/Address.sol":{"keccak256":"0xd6153ce99bcdcce22b124f755e72553295be6abcd63804cfdffceb188b8bef10","urls":["bzz-raw://35c47bece3c03caaa07fab37dd2bb3413bfbca20db7bd9895024390e0a469487","dweb:/ipfs/QmPGWT2x3QHcKxqe6gRmAkdakhbaRgx3DLzcakHz5M4eXG"],"license":"MIT"},"lib/eigenlayer-middleware/lib/openzeppelin-contracts/contracts/utils/Strings.sol":{"keccak256":"0xaf159a8b1923ad2a26d516089bceca9bdeaeacd04be50983ea00ba63070f08a3","urls":["bzz-raw://6f2cf1c531122bc7ca96b8c8db6a60deae60441e5223065e792553d4849b5638","dweb:/ipfs/QmPBdJmBBABMDCfyDjCbdxgiqRavgiSL88SYPGibgbPas9"],"license":"MIT"},"lib/eigenlayer-middleware/lib/openzeppelin-contracts/contracts/utils/cryptography/ECDSA.sol":{"keccak256":"0x84ac2d2f343df1e683da7a12bbcf70db542a7a7a0cea90a5d70fcb5e5d035481","urls":["bzz-raw://73ae8e0c6f975052973265113d762629002ce33987b1933c2a378667e2816f2f","dweb:/ipfs/QmQAootkVfoe4PLaYbT4Xob2dJRm3bZfbCffEHRbCYXNPF"],"license":"MIT"}},"version":1},"id":2} \ No newline at end of file diff --git a/telemetry_api/priv/abi/OperatorStateRetriever.json b/telemetry_api/priv/abi/OperatorStateRetriever.json new file mode 100644 index 000000000..97c87658a --- /dev/null +++ b/telemetry_api/priv/abi/OperatorStateRetriever.json @@ -0,0 +1 @@ +{"abi":[{"type":"function","name":"getBatchOperatorFromId","inputs":[{"name":"registryCoordinator","type":"address","internalType":"contract IRegistryCoordinator"},{"name":"operatorIds","type":"bytes32[]","internalType":"bytes32[]"}],"outputs":[{"name":"operators","type":"address[]","internalType":"address[]"}],"stateMutability":"view"},{"type":"function","name":"getBatchOperatorId","inputs":[{"name":"registryCoordinator","type":"address","internalType":"contract IRegistryCoordinator"},{"name":"operators","type":"address[]","internalType":"address[]"}],"outputs":[{"name":"operatorIds","type":"bytes32[]","internalType":"bytes32[]"}],"stateMutability":"view"},{"type":"function","name":"getCheckSignaturesIndices","inputs":[{"name":"registryCoordinator","type":"address","internalType":"contract IRegistryCoordinator"},{"name":"referenceBlockNumber","type":"uint32","internalType":"uint32"},{"name":"quorumNumbers","type":"bytes","internalType":"bytes"},{"name":"nonSignerOperatorIds","type":"bytes32[]","internalType":"bytes32[]"}],"outputs":[{"name":"","type":"tuple","internalType":"struct OperatorStateRetriever.CheckSignaturesIndices","components":[{"name":"nonSignerQuorumBitmapIndices","type":"uint32[]","internalType":"uint32[]"},{"name":"quorumApkIndices","type":"uint32[]","internalType":"uint32[]"},{"name":"totalStakeIndices","type":"uint32[]","internalType":"uint32[]"},{"name":"nonSignerStakeIndices","type":"uint32[][]","internalType":"uint32[][]"}]}],"stateMutability":"view"},{"type":"function","name":"getOperatorState","inputs":[{"name":"registryCoordinator","type":"address","internalType":"contract IRegistryCoordinator"},{"name":"quorumNumbers","type":"bytes","internalType":"bytes"},{"name":"blockNumber","type":"uint32","internalType":"uint32"}],"outputs":[{"name":"","type":"tuple[][]","internalType":"struct OperatorStateRetriever.Operator[][]","components":[{"name":"operator","type":"address","internalType":"address"},{"name":"operatorId","type":"bytes32","internalType":"bytes32"},{"name":"stake","type":"uint96","internalType":"uint96"}]}],"stateMutability":"view"},{"type":"function","name":"getOperatorState","inputs":[{"name":"registryCoordinator","type":"address","internalType":"contract IRegistryCoordinator"},{"name":"operatorId","type":"bytes32","internalType":"bytes32"},{"name":"blockNumber","type":"uint32","internalType":"uint32"}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"},{"name":"","type":"tuple[][]","internalType":"struct OperatorStateRetriever.Operator[][]","components":[{"name":"operator","type":"address","internalType":"address"},{"name":"operatorId","type":"bytes32","internalType":"bytes32"},{"name":"stake","type":"uint96","internalType":"uint96"}]}],"stateMutability":"view"},{"type":"function","name":"getQuorumBitmapsAtBlockNumber","inputs":[{"name":"registryCoordinator","type":"address","internalType":"contract IRegistryCoordinator"},{"name":"operatorIds","type":"bytes32[]","internalType":"bytes32[]"},{"name":"blockNumber","type":"uint32","internalType":"uint32"}],"outputs":[{"name":"","type":"uint256[]","internalType":"uint256[]"}],"stateMutability":"view"}],"bytecode":{"object":"0x6080604052348015600f57600080fd5b50611dcb8061001f6000396000f3fe608060405234801561001057600080fd5b50600436106100625760003560e01c806331b36bd9146100675780633563b0d1146100905780634d2b57fe146100b05780634f739f74146100d05780635c155662146100f0578063cefdc1d414610110575b600080fd5b61007a6100753660046113b8565b610131565b60405161008791906114ac565b60405180910390f35b6100a361009e3660046114e8565b610245565b6040516100879190611653565b6100c36100be3660046116c4565b6106c5565b6040516100879190611713565b6100e36100de3660046117aa565b6107d2565b60405161008791906118ab565b6101036100fe366004611963565b610eea565b60405161008791906119c6565b61012361011e3660046119fe565b6110a8565b604051610087929190611a35565b606081516001600160401b0381111561014c5761014c61134f565b604051908082528060200260200182016040528015610175578160200160208202803683370190505b50905060005b825181101561023e57836001600160a01b03166313542a4e8483815181106101a5576101a5611a56565b60200260200101516040518263ffffffff1660e01b81526004016101d891906001600160a01b0391909116815260200190565b602060405180830381865afa1580156101f5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102199190611a6c565b82828151811061022b5761022b611a56565b602090810291909101015260010161017b565b5092915050565b60606000846001600160a01b031663683048356040518163ffffffff1660e01b8152600401602060405180830381865afa158015610287573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102ab9190611a85565b90506000856001600160a01b0316639e9923c26040518163ffffffff1660e01b8152600401602060405180830381865afa1580156102ed573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103119190611a85565b90506000866001600160a01b0316635df459466040518163ffffffff1660e01b8152600401602060405180830381865afa158015610353573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103779190611a85565b9050600086516001600160401b038111156103945761039461134f565b6040519080825280602002602001820160405280156103c757816020015b60608152602001906001900390816103b25790505b50905060005b87518110156106b95760008882815181106103ea576103ea611a56565b0160200151604051638902624560e01b815260f89190911c6004820181905263ffffffff8a16602483015291506000906001600160a01b03871690638902624590604401600060405180830381865afa15801561044b573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526104739190810190611aa2565b905080516001600160401b0381111561048e5761048e61134f565b6040519080825280602002602001820160405280156104d957816020015b60408051606081018252600080825260208083018290529282015282526000199092019101816104ac5790505b508484815181106104ec576104ec611a56565b602002602001018190525060005b81518110156106ae576040518060600160405280876001600160a01b03166347b314e885858151811061052f5761052f611a56565b60200260200101516040518263ffffffff1660e01b815260040161055591815260200190565b602060405180830381865afa158015610572573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105969190611a85565b6001600160a01b031681526020018383815181106105b6576105b6611a56565b60200260200101518152602001896001600160a01b031663fa28c6278585815181106105e4576105e4611a56565b60209081029190910101516040516001600160e01b031960e084901b168152600481019190915260ff8816602482015263ffffffff8f166044820152606401602060405180830381865afa158015610640573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106649190611b37565b6001600160601b031681525085858151811061068257610682611a56565b6020026020010151828151811061069b5761069b611a56565b60209081029190910101526001016104fa565b5050506001016103cd565b50979650505050505050565b606081516001600160401b038111156106e0576106e061134f565b604051908082528060200260200182016040528015610709578160200160208202803683370190505b50905060005b825181101561023e57836001600160a01b031663296bb06484838151811061073957610739611a56565b60200260200101516040518263ffffffff1660e01b815260040161075f91815260200190565b602060405180830381865afa15801561077c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107a09190611a85565b8282815181106107b2576107b2611a56565b6001600160a01b039092166020928302919091019091015260010161070f565b6107fd6040518060800160405280606081526020016060815260200160608152602001606081525090565b6000876001600160a01b031663683048356040518163ffffffff1660e01b8152600401602060405180830381865afa15801561083d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108619190611a85565b905061088e6040518060800160405280606081526020016060815260200160608152602001606081525090565b6040516361c8a12f60e11b81526001600160a01b038a169063c391425e906108be908b9089908990600401611b60565b600060405180830381865afa1580156108db573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526109039190810190611ba7565b81526040516340e03a8160e11b81526001600160a01b038316906381c0750290610935908b908b908b90600401611c64565b600060405180830381865afa158015610952573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261097a9190810190611ba7565b6040820152856001600160401b038111156109975761099761134f565b6040519080825280602002602001820160405280156109ca57816020015b60608152602001906001900390816109b55790505b50606082015260005b60ff8116871115610dfb576000856001600160401b038111156109f8576109f861134f565b604051908082528060200260200182016040528015610a21578160200160208202803683370190505b5083606001518360ff1681518110610a3b57610a3b611a56565b602002602001018190525060005b86811015610d055760008c6001600160a01b03166304ec63518a8a85818110610a7457610a74611a56565b905060200201358e88600001518681518110610a9257610a92611a56565b60200260200101516040518463ffffffff1660e01b8152600401610acf9392919092835263ffffffff918216602084015216604082015260600190565b602060405180830381865afa158015610aec573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b109190611c8d565b9050806001600160c01b0316600003610bbb5760405162461bcd60e51b815260206004820152605c60248201527f4f70657261746f7253746174655265747269657665722e676574436865636b5360448201527f69676e617475726573496e64696365733a206f70657261746f72206d7573742060648201527f6265207265676973746572656420617420626c6f636b6e756d62657200000000608482015260a40160405180910390fd5b8a8a8560ff16818110610bd057610bd0611a56565b60016001600160c01b038516919093013560f81c1c82169091039050610cfc57856001600160a01b031663dd9846b98a8a85818110610c1157610c11611a56565b905060200201358d8d8860ff16818110610c2d57610c2d611a56565b6040516001600160e01b031960e087901b1681526004810194909452919091013560f81c60248301525063ffffffff8f166044820152606401602060405180830381865afa158015610c83573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ca79190611cb6565b85606001518560ff1681518110610cc057610cc0611a56565b60200260200101518481518110610cd957610cd9611a56565b63ffffffff9092166020928302919091019091015282610cf881611ce9565b9350505b50600101610a49565b506000816001600160401b03811115610d2057610d2061134f565b604051908082528060200260200182016040528015610d49578160200160208202803683370190505b50905060005b82811015610dc05784606001518460ff1681518110610d7057610d70611a56565b60200260200101518181518110610d8957610d89611a56565b6020026020010151828281518110610da357610da3611a56565b63ffffffff90921660209283029190910190910152600101610d4f565b508084606001518460ff1681518110610ddb57610ddb611a56565b602002602001018190525050508080610df390611d02565b9150506109d3565b506000896001600160a01b0316635df459466040518163ffffffff1660e01b8152600401602060405180830381865afa158015610e3c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e609190611a85565b60405163354952a360e21b81529091506001600160a01b0382169063d5254a8c90610e93908b908b908e90600401611d21565b600060405180830381865afa158015610eb0573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610ed89190810190611ba7565b60208301525098975050505050505050565b60606000846001600160a01b031663c391425e84866040518363ffffffff1660e01b8152600401610f1c929190611d4b565b600060405180830381865afa158015610f39573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610f619190810190611ba7565b9050600084516001600160401b03811115610f7e57610f7e61134f565b604051908082528060200260200182016040528015610fa7578160200160208202803683370190505b50905060005b855181101561109e57866001600160a01b03166304ec6351878381518110610fd757610fd7611a56565b602002602001015187868581518110610ff257610ff2611a56565b60200260200101516040518463ffffffff1660e01b815260040161102f9392919092835263ffffffff918216602084015216604082015260600190565b602060405180830381865afa15801561104c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110709190611c8d565b6001600160c01b031682828151811061108b5761108b611a56565b6020908102919091010152600101610fad565b5095945050505050565b60408051600180825281830190925260009160609183916020808301908036833701905050905084816000815181106110e3576110e3611a56565b60209081029190910101526040516361c8a12f60e11b81526000906001600160a01b0388169063c391425e9061111f9088908690600401611d4b565b600060405180830381865afa15801561113c573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526111649190810190611ba7565b60008151811061117657611176611a56565b60209081029190910101516040516304ec635160e01b81526004810188905263ffffffff87811660248301529091166044820181905291506000906001600160a01b038916906304ec635190606401602060405180830381865afa1580156111e2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112069190611c8d565b6001600160c01b03169050600061121c8261123a565b90508161122a8a838a610245565b9550955050505050935093915050565b606060008061124884611306565b61ffff166001600160401b038111156112635761126361134f565b6040519080825280601f01601f19166020018201604052801561128d576020820181803683370190505b5090506000805b8251821080156112a5575061010081105b156112fc576001811b9350858416156112ec578060f81b8383815181106112ce576112ce611a56565b60200101906001600160f81b031916908160001a9053508160010191505b6112f581611ce9565b9050611294565b5090949350505050565b6000805b82156113315761131b600184611d6a565b909216918061132981611d7d565b91505061130a565b92915050565b6001600160a01b038116811461134c57600080fd5b50565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f191681016001600160401b038111828210171561138d5761138d61134f565b604052919050565b60006001600160401b038211156113ae576113ae61134f565b5060051b60200190565b600080604083850312156113cb57600080fd5b82356113d681611337565b915060208301356001600160401b038111156113f157600080fd5b8301601f8101851361140257600080fd5b803561141561141082611395565b611365565b8082825260208201915060208360051b85010192508783111561143757600080fd5b6020840193505b8284101561146257833561145181611337565b82526020938401939091019061143e565b809450505050509250929050565b600081518084526020840193506020830160005b828110156114a2578151865260209586019590910190600101611484565b5093949350505050565b6020815260006114bf6020830184611470565b9392505050565b63ffffffff8116811461134c57600080fd5b80356114e3816114c6565b919050565b6000806000606084860312156114fd57600080fd5b833561150881611337565b925060208401356001600160401b0381111561152357600080fd5b8401601f8101861361153457600080fd5b80356001600160401b0381111561154d5761154d61134f565b611560601f8201601f1916602001611365565b81815287602083850101111561157557600080fd5b8160208401602083013760006020838301015280945050505061159a604085016114d8565b90509250925092565b600082825180855260208501945060208160051b8301016020850160005b8381101561164757848303601f190188528151805180855260209182019185019060005b8181101561162e57835180516001600160a01b03168452602080820151818601526040918201516001600160601b031691850191909152909301926060909201916001016115e5565b50506020998a01999094509290920191506001016115c1565b50909695505050505050565b6020815260006114bf60208301846115a3565b600082601f83011261167757600080fd5b813561168561141082611395565b8082825260208201915060208360051b8601019250858311156116a757600080fd5b602085015b8381101561109e5780358352602092830192016116ac565b600080604083850312156116d757600080fd5b82356116e281611337565b915060208301356001600160401b038111156116fd57600080fd5b61170985828601611666565b9150509250929050565b602080825282518282018190526000918401906040840190835b818110156117545783516001600160a01b031683526020938401939092019160010161172d565b509095945050505050565b60008083601f84011261177157600080fd5b5081356001600160401b0381111561178857600080fd5b6020830191508360208260051b85010111156117a357600080fd5b9250929050565b600080600080600080608087890312156117c357600080fd5b86356117ce81611337565b955060208701356117de816114c6565b945060408701356001600160401b038111156117f957600080fd5b8701601f8101891361180a57600080fd5b80356001600160401b0381111561182057600080fd5b89602082840101111561183257600080fd5b6020919091019450925060608701356001600160401b0381111561185557600080fd5b61186189828a0161175f565b979a9699509497509295939492505050565b600081518084526020840193506020830160005b828110156114a257815163ffffffff16865260209586019590910190600101611887565b6020815260008251608060208401526118c760a0840182611873565b90506020840151601f198483030160408501526118e48282611873565b9150506040840151601f198483030160608501526119028282611873565b6060860151858203601f190160808701528051808352919350602090810192508084019190600582901b85010160005b828110156106b957601f1986830301845261194e828651611873565b60209586019594909401939150600101611932565b60008060006060848603121561197857600080fd5b833561198381611337565b925060208401356001600160401b0381111561199e57600080fd5b6119aa86828701611666565b92505060408401356119bb816114c6565b809150509250925092565b602080825282518282018190526000918401906040840190835b818110156117545783518352602093840193909201916001016119e0565b600080600060608486031215611a1357600080fd5b8335611a1e81611337565b92506020840135915060408401356119bb816114c6565b828152604060208201526000611a4e60408301846115a3565b949350505050565b634e487b7160e01b600052603260045260246000fd5b600060208284031215611a7e57600080fd5b5051919050565b600060208284031215611a9757600080fd5b81516114bf81611337565b600060208284031215611ab457600080fd5b81516001600160401b03811115611aca57600080fd5b8201601f81018413611adb57600080fd5b8051611ae961141082611395565b8082825260208201915060208360051b850101925086831115611b0b57600080fd5b6020840193505b82841015611b2d578351825260209384019390910190611b12565b9695505050505050565b600060208284031215611b4957600080fd5b81516001600160601b03811681146114bf57600080fd5b63ffffffff84168152604060208201819052810182905260006001600160fb1b03831115611b8d57600080fd5b8260051b8085606085013791909101606001949350505050565b600060208284031215611bb957600080fd5b81516001600160401b03811115611bcf57600080fd5b8201601f81018413611be057600080fd5b8051611bee61141082611395565b8082825260208201915060208360051b850101925086831115611c1057600080fd5b6020840193505b82841015611b2d578351611c2a816114c6565b825260209384019390910190611c17565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b63ffffffff84168152604060208201526000611c84604083018486611c3b565b95945050505050565b600060208284031215611c9f57600080fd5b81516001600160c01b03811681146114bf57600080fd5b600060208284031215611cc857600080fd5b81516114bf816114c6565b634e487b7160e01b600052601160045260246000fd5b600060018201611cfb57611cfb611cd3565b5060010190565b600060ff821660ff8103611d1857611d18611cd3565b60010192915050565b604081526000611d35604083018587611c3b565b905063ffffffff83166020830152949350505050565b63ffffffff83168152604060208201526000611a4e6040830184611470565b8181038181111561133157611331611cd3565b600061ffff821661ffff8103611d1857611d18611cd356fea264697066735822122033585ad22b02fc74fbd447d232f18fbc94c4d2d5f8667d94aaa1ee5226d7192a64736f6c634300081b0033","sourceMap":"540:11298:117:-:0;;;;;;;;;;;;;;;;;;;","linkReferences":{}},"deployedBytecode":{"object":"0x608060405234801561001057600080fd5b50600436106100625760003560e01c806331b36bd9146100675780633563b0d1146100905780634d2b57fe146100b05780634f739f74146100d05780635c155662146100f0578063cefdc1d414610110575b600080fd5b61007a6100753660046113b8565b610131565b60405161008791906114ac565b60405180910390f35b6100a361009e3660046114e8565b610245565b6040516100879190611653565b6100c36100be3660046116c4565b6106c5565b6040516100879190611713565b6100e36100de3660046117aa565b6107d2565b60405161008791906118ab565b6101036100fe366004611963565b610eea565b60405161008791906119c6565b61012361011e3660046119fe565b6110a8565b604051610087929190611a35565b606081516001600160401b0381111561014c5761014c61134f565b604051908082528060200260200182016040528015610175578160200160208202803683370190505b50905060005b825181101561023e57836001600160a01b03166313542a4e8483815181106101a5576101a5611a56565b60200260200101516040518263ffffffff1660e01b81526004016101d891906001600160a01b0391909116815260200190565b602060405180830381865afa1580156101f5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102199190611a6c565b82828151811061022b5761022b611a56565b602090810291909101015260010161017b565b5092915050565b60606000846001600160a01b031663683048356040518163ffffffff1660e01b8152600401602060405180830381865afa158015610287573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102ab9190611a85565b90506000856001600160a01b0316639e9923c26040518163ffffffff1660e01b8152600401602060405180830381865afa1580156102ed573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103119190611a85565b90506000866001600160a01b0316635df459466040518163ffffffff1660e01b8152600401602060405180830381865afa158015610353573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103779190611a85565b9050600086516001600160401b038111156103945761039461134f565b6040519080825280602002602001820160405280156103c757816020015b60608152602001906001900390816103b25790505b50905060005b87518110156106b95760008882815181106103ea576103ea611a56565b0160200151604051638902624560e01b815260f89190911c6004820181905263ffffffff8a16602483015291506000906001600160a01b03871690638902624590604401600060405180830381865afa15801561044b573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526104739190810190611aa2565b905080516001600160401b0381111561048e5761048e61134f565b6040519080825280602002602001820160405280156104d957816020015b60408051606081018252600080825260208083018290529282015282526000199092019101816104ac5790505b508484815181106104ec576104ec611a56565b602002602001018190525060005b81518110156106ae576040518060600160405280876001600160a01b03166347b314e885858151811061052f5761052f611a56565b60200260200101516040518263ffffffff1660e01b815260040161055591815260200190565b602060405180830381865afa158015610572573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105969190611a85565b6001600160a01b031681526020018383815181106105b6576105b6611a56565b60200260200101518152602001896001600160a01b031663fa28c6278585815181106105e4576105e4611a56565b60209081029190910101516040516001600160e01b031960e084901b168152600481019190915260ff8816602482015263ffffffff8f166044820152606401602060405180830381865afa158015610640573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106649190611b37565b6001600160601b031681525085858151811061068257610682611a56565b6020026020010151828151811061069b5761069b611a56565b60209081029190910101526001016104fa565b5050506001016103cd565b50979650505050505050565b606081516001600160401b038111156106e0576106e061134f565b604051908082528060200260200182016040528015610709578160200160208202803683370190505b50905060005b825181101561023e57836001600160a01b031663296bb06484838151811061073957610739611a56565b60200260200101516040518263ffffffff1660e01b815260040161075f91815260200190565b602060405180830381865afa15801561077c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107a09190611a85565b8282815181106107b2576107b2611a56565b6001600160a01b039092166020928302919091019091015260010161070f565b6107fd6040518060800160405280606081526020016060815260200160608152602001606081525090565b6000876001600160a01b031663683048356040518163ffffffff1660e01b8152600401602060405180830381865afa15801561083d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108619190611a85565b905061088e6040518060800160405280606081526020016060815260200160608152602001606081525090565b6040516361c8a12f60e11b81526001600160a01b038a169063c391425e906108be908b9089908990600401611b60565b600060405180830381865afa1580156108db573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526109039190810190611ba7565b81526040516340e03a8160e11b81526001600160a01b038316906381c0750290610935908b908b908b90600401611c64565b600060405180830381865afa158015610952573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261097a9190810190611ba7565b6040820152856001600160401b038111156109975761099761134f565b6040519080825280602002602001820160405280156109ca57816020015b60608152602001906001900390816109b55790505b50606082015260005b60ff8116871115610dfb576000856001600160401b038111156109f8576109f861134f565b604051908082528060200260200182016040528015610a21578160200160208202803683370190505b5083606001518360ff1681518110610a3b57610a3b611a56565b602002602001018190525060005b86811015610d055760008c6001600160a01b03166304ec63518a8a85818110610a7457610a74611a56565b905060200201358e88600001518681518110610a9257610a92611a56565b60200260200101516040518463ffffffff1660e01b8152600401610acf9392919092835263ffffffff918216602084015216604082015260600190565b602060405180830381865afa158015610aec573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b109190611c8d565b9050806001600160c01b0316600003610bbb5760405162461bcd60e51b815260206004820152605c60248201527f4f70657261746f7253746174655265747269657665722e676574436865636b5360448201527f69676e617475726573496e64696365733a206f70657261746f72206d7573742060648201527f6265207265676973746572656420617420626c6f636b6e756d62657200000000608482015260a40160405180910390fd5b8a8a8560ff16818110610bd057610bd0611a56565b60016001600160c01b038516919093013560f81c1c82169091039050610cfc57856001600160a01b031663dd9846b98a8a85818110610c1157610c11611a56565b905060200201358d8d8860ff16818110610c2d57610c2d611a56565b6040516001600160e01b031960e087901b1681526004810194909452919091013560f81c60248301525063ffffffff8f166044820152606401602060405180830381865afa158015610c83573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ca79190611cb6565b85606001518560ff1681518110610cc057610cc0611a56565b60200260200101518481518110610cd957610cd9611a56565b63ffffffff9092166020928302919091019091015282610cf881611ce9565b9350505b50600101610a49565b506000816001600160401b03811115610d2057610d2061134f565b604051908082528060200260200182016040528015610d49578160200160208202803683370190505b50905060005b82811015610dc05784606001518460ff1681518110610d7057610d70611a56565b60200260200101518181518110610d8957610d89611a56565b6020026020010151828281518110610da357610da3611a56565b63ffffffff90921660209283029190910190910152600101610d4f565b508084606001518460ff1681518110610ddb57610ddb611a56565b602002602001018190525050508080610df390611d02565b9150506109d3565b506000896001600160a01b0316635df459466040518163ffffffff1660e01b8152600401602060405180830381865afa158015610e3c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e609190611a85565b60405163354952a360e21b81529091506001600160a01b0382169063d5254a8c90610e93908b908b908e90600401611d21565b600060405180830381865afa158015610eb0573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610ed89190810190611ba7565b60208301525098975050505050505050565b60606000846001600160a01b031663c391425e84866040518363ffffffff1660e01b8152600401610f1c929190611d4b565b600060405180830381865afa158015610f39573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610f619190810190611ba7565b9050600084516001600160401b03811115610f7e57610f7e61134f565b604051908082528060200260200182016040528015610fa7578160200160208202803683370190505b50905060005b855181101561109e57866001600160a01b03166304ec6351878381518110610fd757610fd7611a56565b602002602001015187868581518110610ff257610ff2611a56565b60200260200101516040518463ffffffff1660e01b815260040161102f9392919092835263ffffffff918216602084015216604082015260600190565b602060405180830381865afa15801561104c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110709190611c8d565b6001600160c01b031682828151811061108b5761108b611a56565b6020908102919091010152600101610fad565b5095945050505050565b60408051600180825281830190925260009160609183916020808301908036833701905050905084816000815181106110e3576110e3611a56565b60209081029190910101526040516361c8a12f60e11b81526000906001600160a01b0388169063c391425e9061111f9088908690600401611d4b565b600060405180830381865afa15801561113c573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526111649190810190611ba7565b60008151811061117657611176611a56565b60209081029190910101516040516304ec635160e01b81526004810188905263ffffffff87811660248301529091166044820181905291506000906001600160a01b038916906304ec635190606401602060405180830381865afa1580156111e2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112069190611c8d565b6001600160c01b03169050600061121c8261123a565b90508161122a8a838a610245565b9550955050505050935093915050565b606060008061124884611306565b61ffff166001600160401b038111156112635761126361134f565b6040519080825280601f01601f19166020018201604052801561128d576020820181803683370190505b5090506000805b8251821080156112a5575061010081105b156112fc576001811b9350858416156112ec578060f81b8383815181106112ce576112ce611a56565b60200101906001600160f81b031916908160001a9053508160010191505b6112f581611ce9565b9050611294565b5090949350505050565b6000805b82156113315761131b600184611d6a565b909216918061132981611d7d565b91505061130a565b92915050565b6001600160a01b038116811461134c57600080fd5b50565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f191681016001600160401b038111828210171561138d5761138d61134f565b604052919050565b60006001600160401b038211156113ae576113ae61134f565b5060051b60200190565b600080604083850312156113cb57600080fd5b82356113d681611337565b915060208301356001600160401b038111156113f157600080fd5b8301601f8101851361140257600080fd5b803561141561141082611395565b611365565b8082825260208201915060208360051b85010192508783111561143757600080fd5b6020840193505b8284101561146257833561145181611337565b82526020938401939091019061143e565b809450505050509250929050565b600081518084526020840193506020830160005b828110156114a2578151865260209586019590910190600101611484565b5093949350505050565b6020815260006114bf6020830184611470565b9392505050565b63ffffffff8116811461134c57600080fd5b80356114e3816114c6565b919050565b6000806000606084860312156114fd57600080fd5b833561150881611337565b925060208401356001600160401b0381111561152357600080fd5b8401601f8101861361153457600080fd5b80356001600160401b0381111561154d5761154d61134f565b611560601f8201601f1916602001611365565b81815287602083850101111561157557600080fd5b8160208401602083013760006020838301015280945050505061159a604085016114d8565b90509250925092565b600082825180855260208501945060208160051b8301016020850160005b8381101561164757848303601f190188528151805180855260209182019185019060005b8181101561162e57835180516001600160a01b03168452602080820151818601526040918201516001600160601b031691850191909152909301926060909201916001016115e5565b50506020998a01999094509290920191506001016115c1565b50909695505050505050565b6020815260006114bf60208301846115a3565b600082601f83011261167757600080fd5b813561168561141082611395565b8082825260208201915060208360051b8601019250858311156116a757600080fd5b602085015b8381101561109e5780358352602092830192016116ac565b600080604083850312156116d757600080fd5b82356116e281611337565b915060208301356001600160401b038111156116fd57600080fd5b61170985828601611666565b9150509250929050565b602080825282518282018190526000918401906040840190835b818110156117545783516001600160a01b031683526020938401939092019160010161172d565b509095945050505050565b60008083601f84011261177157600080fd5b5081356001600160401b0381111561178857600080fd5b6020830191508360208260051b85010111156117a357600080fd5b9250929050565b600080600080600080608087890312156117c357600080fd5b86356117ce81611337565b955060208701356117de816114c6565b945060408701356001600160401b038111156117f957600080fd5b8701601f8101891361180a57600080fd5b80356001600160401b0381111561182057600080fd5b89602082840101111561183257600080fd5b6020919091019450925060608701356001600160401b0381111561185557600080fd5b61186189828a0161175f565b979a9699509497509295939492505050565b600081518084526020840193506020830160005b828110156114a257815163ffffffff16865260209586019590910190600101611887565b6020815260008251608060208401526118c760a0840182611873565b90506020840151601f198483030160408501526118e48282611873565b9150506040840151601f198483030160608501526119028282611873565b6060860151858203601f190160808701528051808352919350602090810192508084019190600582901b85010160005b828110156106b957601f1986830301845261194e828651611873565b60209586019594909401939150600101611932565b60008060006060848603121561197857600080fd5b833561198381611337565b925060208401356001600160401b0381111561199e57600080fd5b6119aa86828701611666565b92505060408401356119bb816114c6565b809150509250925092565b602080825282518282018190526000918401906040840190835b818110156117545783518352602093840193909201916001016119e0565b600080600060608486031215611a1357600080fd5b8335611a1e81611337565b92506020840135915060408401356119bb816114c6565b828152604060208201526000611a4e60408301846115a3565b949350505050565b634e487b7160e01b600052603260045260246000fd5b600060208284031215611a7e57600080fd5b5051919050565b600060208284031215611a9757600080fd5b81516114bf81611337565b600060208284031215611ab457600080fd5b81516001600160401b03811115611aca57600080fd5b8201601f81018413611adb57600080fd5b8051611ae961141082611395565b8082825260208201915060208360051b850101925086831115611b0b57600080fd5b6020840193505b82841015611b2d578351825260209384019390910190611b12565b9695505050505050565b600060208284031215611b4957600080fd5b81516001600160601b03811681146114bf57600080fd5b63ffffffff84168152604060208201819052810182905260006001600160fb1b03831115611b8d57600080fd5b8260051b8085606085013791909101606001949350505050565b600060208284031215611bb957600080fd5b81516001600160401b03811115611bcf57600080fd5b8201601f81018413611be057600080fd5b8051611bee61141082611395565b8082825260208201915060208360051b850101925086831115611c1057600080fd5b6020840193505b82841015611b2d578351611c2a816114c6565b825260209384019390910190611c17565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b63ffffffff84168152604060208201526000611c84604083018486611c3b565b95945050505050565b600060208284031215611c9f57600080fd5b81516001600160c01b03811681146114bf57600080fd5b600060208284031215611cc857600080fd5b81516114bf816114c6565b634e487b7160e01b600052601160045260246000fd5b600060018201611cfb57611cfb611cd3565b5060010190565b600060ff821660ff8103611d1857611d18611cd3565b60010192915050565b604081526000611d35604083018587611c3b565b905063ffffffff83166020830152949350505050565b63ffffffff83168152604060208201526000611a4e6040830184611470565b8181038181111561133157611331611cd3565b600061ffff821661ffff8103611d1857611d18611cd356fea264697066735822122033585ad22b02fc74fbd447d232f18fbc94c4d2d5f8667d94aaa1ee5226d7192a64736f6c634300081b0033","sourceMap":"540:11298:117:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;10650:380;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;3037:1255;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;11441:390::-;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;5476:3709::-;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;9602:654::-;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;1757:712::-;;;;;;:::i;:::-;;:::i;:::-;;;;;;;;:::i;10650:380::-;10793:28;10861:9;:16;-1:-1:-1;;;;;10847:31:117;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;10847:31:117;;10833:45;;10893:9;10888:136;10912:9;:16;10908:1;:20;10888:136;;;10966:19;-1:-1:-1;;;;;10966:33:117;;11000:9;11010:1;11000:12;;;;;;;;:::i;:::-;;;;;;;10966:47;;;;;;;;;;;;;;-1:-1:-1;;;;;13640:32:197;;;;13622:51;;13610:2;13595:18;;13476:203;10966:47:117;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;10949:11;10961:1;10949:14;;;;;;;;:::i;:::-;;;;;;;;;;:64;10930:3;;10888:136;;;;10650:380;;;;:::o;3037:1255::-;3205:19;3236:28;3267:19;-1:-1:-1;;;;;3267:33:117;;:35;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;3236:66;;3312:28;3343:19;-1:-1:-1;;;;;3343:33:117;;:35;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;3312:66;;3388:30;3421:19;-1:-1:-1;;;;;3421:34:117;;:36;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;3388:69;;3468:29;3517:13;:20;-1:-1:-1;;;;;3500:38:117;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;3468:70;;3553:9;3548:699;3572:13;:20;3568:1;:24;3548:699;;;3613:18;3640:13;3654:1;3640:16;;;;;;;;:::i;:::-;;;;;3702:69;;-1:-1:-1;;;3702:69:117;;3640:16;;;;;3702:69;;;14994:36:197;;;15078:10;15066:23;;15046:18;;;15039:51;3640:16:117;-1:-1:-1;;;;;;;;3702:42:117;;;;;14967:18:197;;3702:69:117;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;3702:69:117;;;;;;;;;;;;:::i;:::-;3671:100;;3815:11;:18;-1:-1:-1;;;;;3800:34:117;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;3800:34:117;;-1:-1:-1;;3800:34:117;;;;;;;;;;;;3785:9;3795:1;3785:12;;;;;;;;:::i;:::-;;;;;;:49;;;;3853:9;3848:389;3872:11;:18;3868:1;:22;3848:389;;;3933:289;;;;;;;;3974:14;-1:-1:-1;;;;;3974:40:117;;4015:11;4027:1;4015:14;;;;;;;;:::i;:::-;;;;;;;3974:56;;;;;;;;;;;;;16182:25:197;;16170:2;16155:18;;16036:177;3974:56:117;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;3933:289:117;;;;;4072:11;4084:1;4072:14;;;;;;;;:::i;:::-;;;;;;;3933:289;;;;4116:13;-1:-1:-1;;;;;4116:35:117;;4160:11;4172:1;4160:14;;;;;;;;:::i;:::-;;;;;;;;;;;4116:87;;-1:-1:-1;;;;;;4116:87:117;;;;;;;;;;16692:25:197;;;;16765:4;16753:17;;16733:18;;;16726:45;4116:87:117;16807:23:197;;16787:18;;;16780:51;16665:18;;4116:87:117;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;3933:289:117;;;;3915:9;3925:1;3915:12;;;;;;;;:::i;:::-;;;;;;;3928:1;3915:15;;;;;;;;:::i;:::-;;;;;;;;;;:307;3892:3;;3848:389;;;-1:-1:-1;;;3594:3:117;;3548:699;;;-1:-1:-1;4276:9:117;3037:1255;-1:-1:-1;;;;;;;3037:1255:117:o;11441:390::-;11590:26;11654:11;:18;-1:-1:-1;;;;;11640:33:117;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;11640:33:117;;11628:45;;11688:9;11683:142;11707:11;:18;11703:1;:22;11683:142;;;11761:19;-1:-1:-1;;;;;11761:37:117;;11799:11;11811:1;11799:14;;;;;;;;:::i;:::-;;;;;;;11761:53;;;;;;;;;;;;;16182:25:197;;16170:2;16155:18;;16036:177;11761:53:117;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;11746:9;11756:1;11746:12;;;;;;;;:::i;:::-;-1:-1:-1;;;;;11746:68:117;;;:12;;;;;;;;;;;:68;11727:3;;11683:142;;5476:3709;5716:29;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;5716:29:117;5757:28;5788:19;-1:-1:-1;;;;;5788:33:117;;:35;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;5757:66;;5833:52;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;5833:52:117;6065:99;;-1:-1:-1;;;6065:99:117;;-1:-1:-1;;;;;6065:55:117;;;;;:99;;6121:20;;6143;;;;6065:99;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;6065:99:117;;;;;;;;;;;;:::i;:::-;6011:153;;6322:84;;-1:-1:-1;;;6322:84:117;;-1:-1:-1;;;;;6322:47:117;;;;;:84;;6370:20;;6392:13;;;;6322:84;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;6322:84:117;;;;;;;;;;;;:::i;:::-;6279:40;;;:127;6487:13;-1:-1:-1;;;;;6472:36:117;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;6425:44:117;;;:83;6523:23;6518:2307;6552:40;;;;-1:-1:-1;6518:2307:117;;;6629:30;6883:20;-1:-1:-1;;;;;6870:41:117;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;6870:41:117;;6804:22;:44;;;6849:17;6804:63;;;;;;;;;;:::i;:::-;;;;;;:107;;;;6931:6;6926:1405;6943:31;;;6926:1405;;;7091:29;7144:19;-1:-1:-1;;;;;7144:55:117;;7225:20;;7246:1;7225:23;;;;;;;:::i;:::-;;;;;;;7275:20;7322:22;:51;;;7374:1;7322:54;;;;;;;;:::i;:::-;;;;;;;7144:254;;;;;;;;;;;;;;;;19436:25:197;;;19509:10;19497:23;;;19492:2;19477:18;;19470:51;19557:23;19552:2;19537:18;;19530:51;19424:2;19409:18;;19237:350;7144:254:117;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;7091:307;;7441:21;-1:-1:-1;;;;;7441:26:117;7466:1;7441:26;7433:131;;;;-1:-1:-1;;;7433:131:117;;20089:2:197;7433:131:117;;;20071:21:197;20128:2;20108:18;;;20101:30;20167:34;20147:18;;;20140:62;20238:34;20218:18;;;20211:62;20310:30;20289:19;;;20282:59;20358:19;;7433:131:117;;;;;;;;7750:13;;7764:17;7750:32;;;;;;;;;:::i;:::-;7787:1;-1:-1:-1;;;;;7719:64:117;;7750:32;;;;;;;7719:64;7718:70;;:75;;;;-1:-1:-1;7714:603:117;;8024:13;-1:-1:-1;;;;;8024:46:117;;8096:20;;8117:1;8096:23;;;;;;;:::i;:::-;;;;;;;8151:13;;8165:17;8151:32;;;;;;;;;:::i;:::-;8024:228;;-1:-1:-1;;;;;;8024:228:117;;;;;;;;;;16692:25:197;;;;8151:32:117;;;;;;;16733:18:197;;;16726:45;-1:-1:-1;8024:228:117;16807:23:197;;16787:18;;;16780:51;16665:18;;8024:228:117;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;7934:22;:44;;;7979:17;7934:63;;;;;;;;;;:::i;:::-;;;;;;;7998:22;7934:87;;;;;;;;:::i;:::-;:318;;;;:87;;;;;;;;;;;:318;8274:24;;;;:::i;:::-;;;;7714:603;-1:-1:-1;6976:3:117;;6926:1405;;;;8421:46;8483:22;-1:-1:-1;;;;;8470:36:117;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;8470:36:117;;8421:85;;8525:6;8520:185;8541:22;8537:1;:26;8520:185;;;8624:22;:44;;;8669:17;8624:63;;;;;;;;;;:::i;:::-;;;;;;;8688:1;8624:66;;;;;;;;:::i;:::-;;;;;;;8588:30;8619:1;8588:33;;;;;;;;:::i;:::-;:102;;;;:33;;;;;;;;;;;:102;8565:3;;8520:185;;;;8784:30;8718:22;:44;;;8763:17;8718:63;;;;;;;;;;:::i;:::-;;;;;;:96;;;;6615:2210;;6594:19;;;;;:::i;:::-;;;;6518:2307;;;;8835:30;8868:19;-1:-1:-1;;;;;8868:34:117;;:36;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;9060:78;;-1:-1:-1;;;9060:78:117;;8835:69;;-1:-1:-1;;;;;;9060:41:117;;;;;:78;;9102:13;;;;9117:20;;9060:78;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;9060:78:117;;;;;;;;;;;;:::i;:::-;9018:39;;;:120;-1:-1:-1;9018:39:117;5476:3709;-1:-1:-1;;;;;;;;5476:3709:117:o;9602:654::-;9786:16;9814:35;9852:19;-1:-1:-1;;;;;9852:55:117;;9908:11;9921;9852:81;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;9852:81:117;;;;;;;;;;;;:::i;:::-;9814:119;;9943:30;9990:11;:18;-1:-1:-1;;;;;9976:33:117;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;9976:33:117;;9943:66;;10024:9;10019:201;10043:11;:18;10039:1;:22;10019:201;;;10101:19;-1:-1:-1;;;;;10101:55:117;;10157:11;10169:1;10157:14;;;;;;;;:::i;:::-;;;;;;;10173:11;10186:19;10206:1;10186:22;;;;;;;;:::i;:::-;;;;;;;10101:108;;;;;;;;;;;;;;;;19436:25:197;;;19509:10;19497:23;;;19492:2;19477:18;;19470:51;19557:23;19552:2;19537:18;;19530:51;19424:2;19409:18;;19237:350;10101:108:117;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;10082:127:117;:13;10096:1;10082:16;;;;;;;;:::i;:::-;;;;;;;;;;:127;10063:3;;10019:201;;;-1:-1:-1;10236:13:117;9602:654;-1:-1:-1;;;;;9602:654:117:o;1757:712::-;1991:16;;;2005:1;1991:16;;;;;;;;;1920:7;;1929:19;;1920:7;;1991:16;;;;;;;;;;;-1:-1:-1;1991:16:117;1960:47;;2034:10;2017:11;2029:1;2017:14;;;;;;;;:::i;:::-;;;;;;;;;;:27;2070:81;;-1:-1:-1;;;2070:81:117;;2054:13;;-1:-1:-1;;;;;2070:55:117;;;;;:81;;2126:11;;2139;;2070:81;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;2070:81:117;;;;;;;;;;;;:::i;:::-;2152:1;2070:84;;;;;;;;:::i;:::-;;;;;;;;;;;2192:87;;-1:-1:-1;;;2192:87:117;;;;;21982:25:197;;;2054:100:117;22043:23:197;;;22023:18;;;22016:51;2054:100:117;;;22083:18:197;;;22076:34;;;2054:100:117;-1:-1:-1;2169:20:117;;-1:-1:-1;;;;;2192:55:117;;;;;21955:18:197;;2192:87:117;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;2169:110:117;;;2290:26;2319:44;2350:12;2319:30;:44::i;:::-;2290:73;;2382:12;2396:65;2413:19;2434:13;2449:11;2396:16;:65::i;:::-;2374:88;;;;;;;;1757:712;;;;;;:::o;5465:1257:136:-;5532:12;5650:15;5728:23;5764:20;5777:6;5764:12;:20::i;:::-;5754:31;;-1:-1:-1;;;;;5754:31:136;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;5754:31:136;;5728:57;;5841:18;6093:9;6088:601;6122:10;:17;6109:10;:30;6108:45;;;;;6149:3;6145:1;:7;6108:45;6088:601;;;6252:1;:6;;;-1:-1:-1;6339:16:136;;;:21;6335:344;;6524:1;6511:16;;6486:10;6497;6486:22;;;;;;;;:::i;:::-;;;;:41;-1:-1:-1;;;;;6486:41:136;;;;;;;;;6650:12;;;;;6335:344;6155:3;;;:::i;:::-;;;6088:601;;;-1:-1:-1;6705:10:136;;5465:1257;-1:-1:-1;;;;5465:1257:136:o;6797:406::-;6853:6;;6897:209;6904:5;;6897:209;;6931:5;6935:1;6931;:5;:::i;:::-;6925:12;;;;7020:7;;;;:::i;:::-;;;;6897:209;;;7122:5;6797:406;-1:-1:-1;;6797:406:136:o;14:153:197:-;-1:-1:-1;;;;;111:31:197;;101:42;;91:70;;157:1;154;147:12;91:70;14:153;:::o;172:127::-;233:10;228:3;224:20;221:1;214:31;264:4;261:1;254:15;288:4;285:1;278:15;304:275;375:2;369:9;440:2;421:13;;-1:-1:-1;;417:27:197;405:40;;-1:-1:-1;;;;;460:34:197;;496:22;;;457:62;454:88;;;522:18;;:::i;:::-;558:2;551:22;304:275;;-1:-1:-1;304:275:197:o;584:183::-;644:4;-1:-1:-1;;;;;669:6:197;666:30;663:56;;;699:18;;:::i;:::-;-1:-1:-1;744:1:197;740:14;756:4;736:25;;584:183::o;772:1176::-;895:6;903;956:2;944:9;935:7;931:23;927:32;924:52;;;972:1;969;962:12;924:52;1011:9;998:23;1030:53;1077:5;1030:53;:::i;:::-;1102:5;-1:-1:-1;1158:2:197;1143:18;;1130:32;-1:-1:-1;;;;;1174:30:197;;1171:50;;;1217:1;1214;1207:12;1171:50;1240:22;;1293:4;1285:13;;1281:27;-1:-1:-1;1271:55:197;;1322:1;1319;1312:12;1271:55;1362:2;1349:16;1385:64;1401:47;1441:6;1401:47;:::i;:::-;1385:64;:::i;:::-;1471:3;1495:6;1490:3;1483:19;1527:2;1522:3;1518:12;1511:19;;1582:2;1572:6;1569:1;1565:14;1561:2;1557:23;1553:32;1539:46;;1608:7;1600:6;1597:19;1594:39;;;1629:1;1626;1619:12;1594:39;1661:2;1657;1653:11;1642:22;;1673:245;1689:6;1684:3;1681:15;1673:245;;;1771:3;1758:17;1788:55;1835:7;1788:55;:::i;:::-;1856:20;;1905:2;1706:12;;;;1896;;;;1673:245;;;1937:5;1927:15;;;;;;772:1176;;;;;:::o;1953:420::-;2006:3;2044:5;2038:12;2071:6;2066:3;2059:19;2103:4;2098:3;2094:14;2087:21;;2142:4;2135:5;2131:16;2165:1;2175:173;2189:6;2186:1;2183:13;2175:173;;;2250:13;;2238:26;;2293:4;2284:14;;;;2321:17;;;;2211:1;2204:9;2175:173;;;-1:-1:-1;2364:3:197;;1953:420;-1:-1:-1;;;;1953:420:197:o;2378:261::-;2557:2;2546:9;2539:21;2520:4;2577:56;2629:2;2618:9;2614:18;2606:6;2577:56;:::i;:::-;2569:64;2378:261;-1:-1:-1;;;2378:261:197:o;2644:121::-;2729:10;2722:5;2718:22;2711:5;2708:33;2698:61;;2755:1;2752;2745:12;2770:132;2837:20;;2866:30;2837:20;2866:30;:::i;:::-;2770:132;;;:::o;2907:1024::-;3022:6;3030;3038;3091:2;3079:9;3070:7;3066:23;3062:32;3059:52;;;3107:1;3104;3097:12;3059:52;3146:9;3133:23;3165:53;3212:5;3165:53;:::i;:::-;3237:5;-1:-1:-1;3293:2:197;3278:18;;3265:32;-1:-1:-1;;;;;3309:30:197;;3306:50;;;3352:1;3349;3342:12;3306:50;3375:22;;3428:4;3420:13;;3416:27;-1:-1:-1;3406:55:197;;3457:1;3454;3447:12;3406:55;3497:2;3484:16;-1:-1:-1;;;;;3515:6:197;3512:30;3509:56;;;3545:18;;:::i;:::-;3587:57;3634:2;3611:17;;-1:-1:-1;;3607:31:197;3640:2;3603:40;3587:57;:::i;:::-;3667:6;3660:5;3653:21;3715:7;3710:2;3701:6;3697:2;3693:15;3689:24;3686:37;3683:57;;;3736:1;3733;3726:12;3683:57;3791:6;3786:2;3782;3778:11;3773:2;3766:5;3762:14;3749:49;3843:1;3838:2;3829:6;3822:5;3818:18;3814:27;3807:38;3864:5;3854:15;;;;;3888:37;3921:2;3910:9;3906:18;3888:37;:::i;:::-;3878:47;;2907:1024;;;;;:::o;3936:1255::-;4007:3;4038;4070:5;4064:12;4097:6;4092:3;4085:19;4129:4;4124:3;4120:14;4113:21;;4187:4;4177:6;4174:1;4170:14;4163:5;4159:26;4155:37;4226:4;4219:5;4215:16;4249:1;4259:906;4273:6;4270:1;4267:13;4259:906;;;4338:16;;;-1:-1:-1;;4334:30:197;4322:43;;4388:13;;4460:9;;4482:22;;;4536:4;4570:13;;;;4526:15;;;4607:1;4621:434;4637:8;4632:3;4629:17;4621:434;;;4710:15;;4760:9;;-1:-1:-1;;;;;4756:35:197;4742:50;;4848:4;4840:13;;;4834:20;4816:16;;;4809:46;4915:4;4907:13;;;4901:20;-1:-1:-1;;;;;4897:53:197;4879:16;;;4872:79;;;;5022:19;;;;4988:4;4977:16;;;;4788:1;4656:11;4621:434;;;-1:-1:-1;;5116:4:197;5141:14;;;;5076:5;;-1:-1:-1;5104:17:197;;;;;-1:-1:-1;4295:1:197;4288:9;4259:906;;;-1:-1:-1;5181:4:197;;3936:1255;-1:-1:-1;;;;;;3936:1255:197:o;5196:383::-;5479:2;5468:9;5461:21;5442:4;5499:74;5569:2;5558:9;5554:18;5546:6;5499:74;:::i;5584:723::-;5638:5;5691:3;5684:4;5676:6;5672:17;5668:27;5658:55;;5709:1;5706;5699:12;5658:55;5749:6;5736:20;5776:64;5792:47;5832:6;5792:47;:::i;5776:64::-;5864:3;5888:6;5883:3;5876:19;5920:4;5915:3;5911:14;5904:21;;5981:4;5971:6;5968:1;5964:14;5956:6;5952:27;5948:38;5934:52;;6009:3;6001:6;5998:15;5995:35;;;6026:1;6023;6016:12;5995:35;6062:4;6054:6;6050:17;6076:200;6092:6;6087:3;6084:15;6076:200;;;6184:17;;6214:18;;6261:4;6252:14;;;;6109;6076:200;;6312:535;6435:6;6443;6496:2;6484:9;6475:7;6471:23;6467:32;6464:52;;;6512:1;6509;6502:12;6464:52;6551:9;6538:23;6570:53;6617:5;6570:53;:::i;:::-;6642:5;-1:-1:-1;6698:2:197;6683:18;;6670:32;-1:-1:-1;;;;;6714:30:197;;6711:50;;;6757:1;6754;6747:12;6711:50;6780:61;6833:7;6824:6;6813:9;6809:22;6780:61;:::i;:::-;6770:71;;;6312:535;;;;;:::o;6852:637::-;7042:2;7054:21;;;7124:13;;7027:18;;;7146:22;;;6994:4;;7225:15;;;7199:2;7184:18;;;6994:4;7268:195;7282:6;7279:1;7276:13;7268:195;;;7347:13;;-1:-1:-1;;;;;7343:39:197;7331:52;;7412:2;7438:15;;;;7403:12;;;;7379:1;7297:9;7268:195;;;-1:-1:-1;7480:3:197;;6852:637;-1:-1:-1;;;;;6852:637:197:o;7494:367::-;7557:8;7567:6;7621:3;7614:4;7606:6;7602:17;7598:27;7588:55;;7639:1;7636;7629:12;7588:55;-1:-1:-1;7662:20:197;;-1:-1:-1;;;;;7694:30:197;;7691:50;;;7737:1;7734;7727:12;7691:50;7774:4;7766:6;7762:17;7750:29;;7834:3;7827:4;7817:6;7814:1;7810:14;7802:6;7798:27;7794:38;7791:47;7788:67;;;7851:1;7848;7841:12;7788:67;7494:367;;;;;:::o;7866:1244::-;8019:6;8027;8035;8043;8051;8059;8112:3;8100:9;8091:7;8087:23;8083:33;8080:53;;;8129:1;8126;8119:12;8080:53;8168:9;8155:23;8187:53;8234:5;8187:53;:::i;:::-;8259:5;-1:-1:-1;8316:2:197;8301:18;;8288:32;8329;8288;8329;:::i;:::-;8380:7;-1:-1:-1;8438:2:197;8423:18;;8410:32;-1:-1:-1;;;;;8454:30:197;;8451:50;;;8497:1;8494;8487:12;8451:50;8520:22;;8573:4;8565:13;;8561:27;-1:-1:-1;8551:55:197;;8602:1;8599;8592:12;8551:55;8642:2;8629:16;-1:-1:-1;;;;;8660:6:197;8657:30;8654:50;;;8700:1;8697;8690:12;8654:50;8745:7;8740:2;8731:6;8727:2;8723:15;8719:24;8716:37;8713:57;;;8766:1;8763;8756:12;8713:57;8797:2;8789:11;;;;;-1:-1:-1;8819:6:197;-1:-1:-1;8878:2:197;8863:18;;8850:32;-1:-1:-1;;;;;8894:32:197;;8891:52;;;8939:1;8936;8929:12;8891:52;8978:72;9042:7;9031:8;9020:9;9016:24;8978:72;:::i;:::-;7866:1244;;;;-1:-1:-1;7866:1244:197;;-1:-1:-1;7866:1244:197;;9069:8;;7866:1244;-1:-1:-1;;;7866:1244:197:o;9115:436::-;9167:3;9205:5;9199:12;9232:6;9227:3;9220:19;9264:4;9259:3;9255:14;9248:21;;9303:4;9296:5;9292:16;9326:1;9336:190;9350:6;9347:1;9344:13;9336:190;;;9415:13;;9430:10;9411:30;9399:43;;9471:4;9462:14;;;;9499:17;;;;9372:1;9365:9;9336:190;;9556:1466;9767:2;9756:9;9749:21;9730:4;9805:6;9799:13;9848:4;9843:2;9832:9;9828:18;9821:32;9876:62;9933:3;9922:9;9918:19;9904:12;9876:62;:::i;:::-;9862:76;;9987:2;9979:6;9975:15;9969:22;10059:2;10055:7;10043:9;10035:6;10031:22;10027:36;10022:2;10011:9;10007:18;10000:64;10087:51;10131:6;10115:14;10087:51;:::i;:::-;10073:65;;;10187:2;10179:6;10175:15;10169:22;10259:2;10255:7;10243:9;10235:6;10231:22;10227:36;10222:2;10211:9;10207:18;10200:64;10287:51;10331:6;10315:14;10287:51;:::i;:::-;10387:2;10375:15;;10369:22;10433;;;-1:-1:-1;;10429:36:197;10422:4;10407:20;;10400:66;10515:21;;10545:22;;;10273:65;;-1:-1:-1;10595:2:197;10680:23;;;;-1:-1:-1;10583:15:197;;;;10515:21;10641:1;10637:14;;;10625:27;;10621:36;10721:1;10731:262;10745:6;10742:1;10739:13;10731:262;;;10835:2;10831:7;10822:6;10814;10810:19;10806:33;10801:3;10794:46;10863:50;10906:6;10897;10891:13;10863:50;:::i;:::-;10948:2;10936:15;;;;10971:12;;;;;10853:60;-1:-1:-1;10767:1:197;10760:9;10731:262;;11027:674;11158:6;11166;11174;11227:2;11215:9;11206:7;11202:23;11198:32;11195:52;;;11243:1;11240;11233:12;11195:52;11282:9;11269:23;11301:53;11348:5;11301:53;:::i;:::-;11373:5;-1:-1:-1;11429:2:197;11414:18;;11401:32;-1:-1:-1;;;;;11445:30:197;;11442:50;;;11488:1;11485;11478:12;11442:50;11511:61;11564:7;11555:6;11544:9;11540:22;11511:61;:::i;:::-;11501:71;;;11624:2;11613:9;11609:18;11596:32;11637;11661:7;11637:32;:::i;:::-;11688:7;11678:17;;;11027:674;;;;;:::o;11706:611::-;11896:2;11908:21;;;11978:13;;11881:18;;;12000:22;;;11848:4;;12079:15;;;12053:2;12038:18;;;11848:4;12122:169;12136:6;12133:1;12130:13;12122:169;;;12197:13;;12185:26;;12240:2;12266:15;;;;12231:12;;;;12158:1;12151:9;12122:169;;12322:558;12428:6;12436;12444;12497:2;12485:9;12476:7;12472:23;12468:32;12465:52;;;12513:1;12510;12503:12;12465:52;12552:9;12539:23;12571:53;12618:5;12571:53;:::i;:::-;12643:5;-1:-1:-1;12721:2:197;12706:18;;12693:32;;-1:-1:-1;12803:2:197;12788:18;;12775:32;12816;12775;12816;:::i;12885:454::-;13196:6;13185:9;13178:25;13239:2;13234;13223:9;13219:18;13212:30;13159:4;13259:74;13329:2;13318:9;13314:18;13306:6;13259:74;:::i;:::-;13251:82;12885:454;-1:-1:-1;;;;12885:454:197:o;13344:127::-;13405:10;13400:3;13396:20;13393:1;13386:31;13436:4;13433:1;13426:15;13460:4;13457:1;13450:15;13684:230;13754:6;13807:2;13795:9;13786:7;13782:23;13778:32;13775:52;;;13823:1;13820;13813:12;13775:52;-1:-1:-1;13868:16:197;;13684:230;-1:-1:-1;13684:230:197:o;13919:297::-;14013:6;14066:2;14054:9;14045:7;14041:23;14037:32;14034:52;;;14082:1;14079;14072:12;14034:52;14114:9;14108:16;14133:53;14180:5;14133:53;:::i;15101:930::-;15196:6;15249:2;15237:9;15228:7;15224:23;15220:32;15217:52;;;15265:1;15262;15255:12;15217:52;15298:9;15292:16;-1:-1:-1;;;;;15323:6:197;15320:30;15317:50;;;15363:1;15360;15353:12;15317:50;15386:22;;15439:4;15431:13;;15427:27;-1:-1:-1;15417:55:197;;15468:1;15465;15458:12;15417:55;15501:2;15495:9;15524:64;15540:47;15580:6;15540:47;:::i;15524:64::-;15610:3;15634:6;15629:3;15622:19;15666:2;15661:3;15657:12;15650:19;;15721:2;15711:6;15708:1;15704:14;15700:2;15696:23;15692:32;15678:46;;15747:7;15739:6;15736:19;15733:39;;;15768:1;15765;15758:12;15733:39;15800:2;15796;15792:11;15781:22;;15812:189;15828:6;15823:3;15820:15;15812:189;;;15918:10;;15941:18;;15988:2;15845:12;;;;15979;;;;15812:189;;;16020:5;15101:930;-1:-1:-1;;;;;;15101:930:197:o;16842:296::-;16911:6;16964:2;16952:9;16943:7;16939:23;16935:32;16932:52;;;16980:1;16977;16970:12;16932:52;17012:9;17006:16;-1:-1:-1;;;;;17055:5:197;17051:38;17044:5;17041:49;17031:77;;17104:1;17101;17094:12;17143:529;17370:10;17358:23;;17340:42;;17418:2;17413;17398:18;;17391:30;;;17437:18;;17430:34;;;-1:-1:-1;;;;;;17476:31:197;;17473:51;;;17520:1;17517;17510:12;17473:51;17554:6;17551:1;17547:14;17611:6;17603;17598:2;17587:9;17583:18;17570:48;17639:22;;;;17663:2;17635:31;;17143:529;-1:-1:-1;;;;17143:529:197:o;17677:949::-;17771:6;17824:2;17812:9;17803:7;17799:23;17795:32;17792:52;;;17840:1;17837;17830:12;17792:52;17873:9;17867:16;-1:-1:-1;;;;;17898:6:197;17895:30;17892:50;;;17938:1;17935;17928:12;17892:50;17961:22;;18014:4;18006:13;;18002:27;-1:-1:-1;17992:55:197;;18043:1;18040;18033:12;17992:55;18076:2;18070:9;18099:64;18115:47;18155:6;18115:47;:::i;18099:64::-;18185:3;18209:6;18204:3;18197:19;18241:2;18236:3;18232:12;18225:19;;18296:2;18286:6;18283:1;18279:14;18275:2;18271:23;18267:32;18253:46;;18322:7;18314:6;18311:19;18308:39;;;18343:1;18340;18333:12;18308:39;18375:2;18371;18367:11;18356:22;;18387:209;18403:6;18398:3;18395:15;18387:209;;;18476:3;18470:10;18493:30;18517:5;18493:30;:::i;:::-;18536:18;;18583:2;18420:12;;;;18574;;;;18387:209;;18631:266;18719:6;18714:3;18707:19;18771:6;18764:5;18757:4;18752:3;18748:14;18735:43;-1:-1:-1;18823:1:197;18798:16;;;18816:4;18794:27;;;18787:38;;;;18879:2;18858:15;;;-1:-1:-1;;18854:29:197;18845:39;;;18841:50;;18631:266::o;18902:330::-;19097:10;19089:6;19085:23;19074:9;19067:42;19145:2;19140;19129:9;19125:18;19118:30;19048:4;19165:61;19222:2;19211:9;19207:18;19199:6;19191;19165:61;:::i;:::-;19157:69;18902:330;-1:-1:-1;;;;;18902:330:197:o;19592:290::-;19662:6;19715:2;19703:9;19694:7;19690:23;19686:32;19683:52;;;19731:1;19728;19721:12;19683:52;19757:16;;-1:-1:-1;;;;;19802:31:197;;19792:42;;19782:70;;19848:1;19845;19838:12;20388:249;20457:6;20510:2;20498:9;20489:7;20485:23;20481:32;20478:52;;;20526:1;20523;20516:12;20478:52;20558:9;20552:16;20577:30;20601:5;20577:30;:::i;20642:127::-;20703:10;20698:3;20694:20;20691:1;20684:31;20734:4;20731:1;20724:15;20758:4;20755:1;20748:15;20774:135;20813:3;20834:17;;;20831:43;;20854:18;;:::i;:::-;-1:-1:-1;20901:1:197;20890:13;;20774:135::o;20914:175::-;20951:3;20995:4;20988:5;20984:16;21024:4;21015:7;21012:17;21009:43;;21032:18;;:::i;:::-;21081:1;21068:15;;20914:175;-1:-1:-1;;20914:175:197:o;21094:331::-;21278:2;21267:9;21260:21;21241:4;21298:61;21355:2;21344:9;21340:18;21332:6;21324;21298:61;:::i;:::-;21290:69;;21407:10;21399:6;21395:23;21390:2;21379:9;21375:18;21368:51;21094:331;;;;;;:::o;21430:347::-;21647:10;21639:6;21635:23;21624:9;21617:42;21695:2;21690;21679:9;21675:18;21668:30;21598:4;21715:56;21767:2;21756:9;21752:18;21744:6;21715:56;:::i;22121:128::-;22188:9;;;22209:11;;;22206:37;;;22223:18;;:::i;22254:180::-;22292:3;22336:6;22329:5;22325:18;22367:6;22358:7;22355:19;22352:45;;22377:18;;:::i","linkReferences":{}},"methodIdentifiers":{"getBatchOperatorFromId(address,bytes32[])":"4d2b57fe","getBatchOperatorId(address,address[])":"31b36bd9","getCheckSignaturesIndices(address,uint32,bytes,bytes32[])":"4f739f74","getOperatorState(address,bytes,uint32)":"3563b0d1","getOperatorState(address,bytes32,uint32)":"cefdc1d4","getQuorumBitmapsAtBlockNumber(address,bytes32[],uint32)":"5c155662"},"rawMetadata":"{\"compiler\":{\"version\":\"0.8.27+commit.40a35a09\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"contract IRegistryCoordinator\",\"name\":\"registryCoordinator\",\"type\":\"address\"},{\"internalType\":\"bytes32[]\",\"name\":\"operatorIds\",\"type\":\"bytes32[]\"}],\"name\":\"getBatchOperatorFromId\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"operators\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract IRegistryCoordinator\",\"name\":\"registryCoordinator\",\"type\":\"address\"},{\"internalType\":\"address[]\",\"name\":\"operators\",\"type\":\"address[]\"}],\"name\":\"getBatchOperatorId\",\"outputs\":[{\"internalType\":\"bytes32[]\",\"name\":\"operatorIds\",\"type\":\"bytes32[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract IRegistryCoordinator\",\"name\":\"registryCoordinator\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"referenceBlockNumber\",\"type\":\"uint32\"},{\"internalType\":\"bytes\",\"name\":\"quorumNumbers\",\"type\":\"bytes\"},{\"internalType\":\"bytes32[]\",\"name\":\"nonSignerOperatorIds\",\"type\":\"bytes32[]\"}],\"name\":\"getCheckSignaturesIndices\",\"outputs\":[{\"components\":[{\"internalType\":\"uint32[]\",\"name\":\"nonSignerQuorumBitmapIndices\",\"type\":\"uint32[]\"},{\"internalType\":\"uint32[]\",\"name\":\"quorumApkIndices\",\"type\":\"uint32[]\"},{\"internalType\":\"uint32[]\",\"name\":\"totalStakeIndices\",\"type\":\"uint32[]\"},{\"internalType\":\"uint32[][]\",\"name\":\"nonSignerStakeIndices\",\"type\":\"uint32[][]\"}],\"internalType\":\"struct OperatorStateRetriever.CheckSignaturesIndices\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract IRegistryCoordinator\",\"name\":\"registryCoordinator\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"quorumNumbers\",\"type\":\"bytes\"},{\"internalType\":\"uint32\",\"name\":\"blockNumber\",\"type\":\"uint32\"}],\"name\":\"getOperatorState\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"operatorId\",\"type\":\"bytes32\"},{\"internalType\":\"uint96\",\"name\":\"stake\",\"type\":\"uint96\"}],\"internalType\":\"struct OperatorStateRetriever.Operator[][]\",\"name\":\"\",\"type\":\"tuple[][]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract IRegistryCoordinator\",\"name\":\"registryCoordinator\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"operatorId\",\"type\":\"bytes32\"},{\"internalType\":\"uint32\",\"name\":\"blockNumber\",\"type\":\"uint32\"}],\"name\":\"getOperatorState\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"operatorId\",\"type\":\"bytes32\"},{\"internalType\":\"uint96\",\"name\":\"stake\",\"type\":\"uint96\"}],\"internalType\":\"struct OperatorStateRetriever.Operator[][]\",\"name\":\"\",\"type\":\"tuple[][]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract IRegistryCoordinator\",\"name\":\"registryCoordinator\",\"type\":\"address\"},{\"internalType\":\"bytes32[]\",\"name\":\"operatorIds\",\"type\":\"bytes32[]\"},{\"internalType\":\"uint32\",\"name\":\"blockNumber\",\"type\":\"uint32\"}],\"name\":\"getQuorumBitmapsAtBlockNumber\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"\",\"type\":\"uint256[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"author\":\"Layr Labs Inc.\",\"kind\":\"dev\",\"methods\":{\"getBatchOperatorFromId(address,bytes32[])\":{\"details\":\"if an operator is not registered, the operator address will be 0\",\"params\":{\"operators\":\"is the array of operatorIds to get corresponding operator addresses for\",\"registryCoordinator\":\"is the AVS registry coordinator to fetch the operator information from\"}},\"getBatchOperatorId(address,address[])\":{\"details\":\"if an operator is not registered, the operatorId will be 0\",\"params\":{\"operators\":\"is the array of operator address to get corresponding operatorIds for\",\"registryCoordinator\":\"is the AVS registry coordinator to fetch the operator information from\"}},\"getCheckSignaturesIndices(address,uint32,bytes,bytes32[])\":{\"params\":{\"nonSignerOperatorIds\":\"are the ids of the nonsigning operators\",\"quorumNumbers\":\"are the ids of the quorums to get the operator state for\",\"referenceBlockNumber\":\"is the block number to get the indices for\",\"registryCoordinator\":\"is the registry coordinator to fetch the AVS registry information from\"},\"returns\":{\"_0\":\"1) the indices of the quorumBitmaps for each of the operators in the @param nonSignerOperatorIds array at the given blocknumber 2) the indices of the total stakes entries for the given quorums at the given blocknumber 3) the indices of the stakes of each of the nonsigners in each of the quorums they were a part of (for each nonsigner, an array of length the number of quorums they were a part of that are also part of the provided quorumNumbers) at the given blocknumber 4) the indices of the quorum apks for each of the provided quorums at the given blocknumber\"}},\"getOperatorState(address,bytes,uint32)\":{\"params\":{\"blockNumber\":\"is the block number to get the operator state for\",\"quorumNumbers\":\"are the ids of the quorums to get the operator state for\",\"registryCoordinator\":\"is the registry coordinator to fetch the AVS registry information from\"},\"returns\":{\"_0\":\"2d array of Operators. For each quorum, an ordered list of Operators\"}},\"getOperatorState(address,bytes32,uint32)\":{\"params\":{\"blockNumber\":\"is the block number to get the operator state for\",\"operatorId\":\"the id of the operator to fetch the quorums lists \",\"registryCoordinator\":\"is the registry coordinator to fetch the AVS registry information from\"},\"returns\":{\"_0\":\"1) the quorumBitmap of the operator at the given blockNumber 2) 2d array of Operator structs. For each quorum the provided operator was a part of at `blockNumber`, an ordered list of operators.\"}},\"getQuorumBitmapsAtBlockNumber(address,bytes32[],uint32)\":{\"params\":{\"blockNumber\":\"is the block number to get the quorumBitmaps for\",\"operatorIds\":\"are the ids of the operators to get the quorumBitmaps for\",\"registryCoordinator\":\"is the AVS registry coordinator to fetch the operator information from\"}}},\"title\":\"OperatorStateRetriever with view functions that allow to retrieve the state of an AVSs registry system.\",\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"getBatchOperatorFromId(address,bytes32[])\":{\"notice\":\"This function returns the operator addresses for each of the operators in the operatorIds array\"},\"getBatchOperatorId(address,address[])\":{\"notice\":\"This function returns the operatorIds for each of the operators in the operators array\"},\"getCheckSignaturesIndices(address,uint32,bytes,bytes32[])\":{\"notice\":\"this is called by the AVS operator to get the relevant indices for the checkSignatures function if they are not running an indexer \"},\"getOperatorState(address,bytes,uint32)\":{\"notice\":\"returns the ordered list of operators (id and stake) for each quorum. The AVS coordinator may call this function directly to get the operator state for a given block number\"},\"getOperatorState(address,bytes32,uint32)\":{\"notice\":\"This function is intended to to be called by AVS operators every time a new task is created (i.e.) the AVS coordinator makes a request to AVS operators. Since all of the crucial information is kept onchain, operators don't need to run indexers to fetch the data.\"},\"getQuorumBitmapsAtBlockNumber(address,bytes32[],uint32)\":{\"notice\":\"this function returns the quorumBitmaps for each of the operators in the operatorIds array at the given blocknumber\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"lib/eigenlayer-middleware/src/OperatorStateRetriever.sol\":\"OperatorStateRetriever\"},\"evmVersion\":\"paris\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[\":@openzeppelin-upgrades-v4.9.0/=lib/eigenlayer-middleware/lib/eigenlayer-contracts/lib/openzeppelin-contracts-upgradeable-v4.9.0/\",\":@openzeppelin-upgrades/contracts/=lib/eigenlayer-middleware/lib/openzeppelin-contracts-upgradeable/contracts/\",\":@openzeppelin-v4.9.0/=lib/eigenlayer-middleware/lib/eigenlayer-contracts/lib/openzeppelin-contracts-v4.9.0/\",\":@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/\",\":@openzeppelin/contracts/=lib/eigenlayer-middleware/lib/openzeppelin-contracts/contracts/\",\":ds-test/=lib/eigenlayer-middleware/lib/ds-test/src/\",\":eigenlayer-contracts/=lib/eigenlayer-middleware/lib/eigenlayer-contracts/\",\":eigenlayer-core-contracts/=lib/eigenlayer-middleware/lib/eigenlayer-contracts/src/contracts/core/\",\":eigenlayer-core/=lib/eigenlayer-middleware/lib/eigenlayer-contracts/src/\",\":eigenlayer-middleware/=lib/eigenlayer-middleware/src/\",\":eigenlayer-scripts/=lib/eigenlayer-middleware/lib/eigenlayer-contracts/script/\",\":erc4626-tests/=lib/openzeppelin-contracts-upgradeable/lib/erc4626-tests/\",\":forge-std/=lib/forge-std/src/\",\":openzeppelin-contracts-upgradeable-v4.9.0/=lib/eigenlayer-middleware/lib/eigenlayer-contracts/lib/openzeppelin-contracts-upgradeable-v4.9.0/\",\":openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/\",\":openzeppelin-contracts-v4.9.0/=lib/eigenlayer-middleware/lib/eigenlayer-contracts/lib/openzeppelin-contracts-v4.9.0/\",\":openzeppelin-contracts/=lib/openzeppelin-contracts/\",\":openzeppelin/=lib/eigenlayer-middleware/lib/eigenlayer-contracts/lib/openzeppelin-contracts-upgradeable-v4.9.0/contracts/\"]},\"sources\":{\"lib/eigenlayer-middleware/lib/eigenlayer-contracts/src/contracts/interfaces/IBeaconChainOracle.sol\":{\"keccak256\":\"0x0fef07aa6179c77198f1514e12e628aa1c876e04f9c181ec853a322179e5be00\",\"license\":\"BUSL-1.1\",\"urls\":[\"bzz-raw://51438325876cc2d4c77f58488a7e27b488015d1b663c50be6a5cafbd73b9c983\",\"dweb:/ipfs/QmViCuGoYZzi6wtXA8PPKigqVv3KMuNxEVQ1Td9dGqjL18\"]},\"lib/eigenlayer-middleware/lib/eigenlayer-contracts/src/contracts/interfaces/IDelegationManager.sol\":{\"keccak256\":\"0xab76a9f4eff865cbb689f627cf98263488765519d7a4ec5ffbcb0ca4972842f9\",\"license\":\"BUSL-1.1\",\"urls\":[\"bzz-raw://ff57ce18e8350bf39f190645db0988bc0f1279f1872150a114a1b520c38a2914\",\"dweb:/ipfs/QmSsUXkNUqYuJgGRumHTSs9rAaboGjecotcM4xHrdBYWaZ\"]},\"lib/eigenlayer-middleware/lib/eigenlayer-contracts/src/contracts/interfaces/IETHPOSDeposit.sol\":{\"keccak256\":\"0x2e60e5f4b0da0a0a4e2a07c63141120998559970c21deac743ea0c64a60a880c\",\"license\":\"CC0-1.0\",\"urls\":[\"bzz-raw://e635c346bde5b7ade9bcf35bc733081520cb86015be4fbc6e761e6e9482c4c91\",\"dweb:/ipfs/QmRoeazEnbFn5SPSWAkoFK2gSN9DMp3hJAnrLWuL2sKutz\"]},\"lib/eigenlayer-middleware/lib/eigenlayer-contracts/src/contracts/interfaces/IEigenPod.sol\":{\"keccak256\":\"0xb50c36ad96b6679bb80fd8331f949cbfbcba0f529026e1421a4d2bae64396eba\",\"license\":\"BUSL-1.1\",\"urls\":[\"bzz-raw://5719181d780120f1e688c0da276992a8caf185815917f453b3550537c31ed4cc\",\"dweb:/ipfs/QmYprRC5ZEXhz3zAUND5E8Xjn6s5TL8ZF8QbnndVq7aVPR\"]},\"lib/eigenlayer-middleware/lib/eigenlayer-contracts/src/contracts/interfaces/IEigenPodManager.sol\":{\"keccak256\":\"0xd8a64dbed03d3a5cdbefe1af75968f2dde07f973749c2ef5197bf7187c3e448c\",\"license\":\"BUSL-1.1\",\"urls\":[\"bzz-raw://27ccc7c1fd9352e9f9b357c9063d255dc0ed9583f43db09f786ac7497d7846b8\",\"dweb:/ipfs/QmeJzuJkE9m2NUNwZSp4tGZEZmih1LeucePup8hzMVDRbG\"]},\"lib/eigenlayer-middleware/lib/eigenlayer-contracts/src/contracts/interfaces/IPausable.sol\":{\"keccak256\":\"0x98cffc894842947377e24c1d375813a1120dd73a84c29782ab68404e109cb34f\",\"license\":\"BUSL-1.1\",\"urls\":[\"bzz-raw://b3474f6c350ceaee57cbdfb08fb48835d0c6e81ae8ebfbb9667899584a139324\",\"dweb:/ipfs/QmWELKtksdtWxQbqAccd8yGyhKqrgPZXTADKR7BuT27Zg5\"]},\"lib/eigenlayer-middleware/lib/eigenlayer-contracts/src/contracts/interfaces/IPauserRegistry.sol\":{\"keccak256\":\"0x9de8dd682bc0d812bbd6583c0231cbf35448d5eff58b74a93efa64cb9a768c49\",\"license\":\"BUSL-1.1\",\"urls\":[\"bzz-raw://c00d6c675b9c72b092d287fe85fd37782588df32b8eb59ab4c7db7a86be25e7d\",\"dweb:/ipfs/QmeYokY3HhAdbBaCPdHg3PgQEdRCDFEJy3Wf7VtgHBkQSx\"]},\"lib/eigenlayer-middleware/lib/eigenlayer-contracts/src/contracts/interfaces/ISignatureUtils.sol\":{\"keccak256\":\"0x5e52482a31d94401a8502f3014c4aada1142b4450fc0596dff8e1866a85fe092\",\"license\":\"BUSL-1.1\",\"urls\":[\"bzz-raw://17dc326c9361bc1453379f26545963557b2883b0c88bc07d4477e04dbcc0cc8c\",\"dweb:/ipfs/QmZXT7A816W5JH2ymirE2ETaJttqztFCsEL22AV8oEfCK9\"]},\"lib/eigenlayer-middleware/lib/eigenlayer-contracts/src/contracts/interfaces/ISlasher.sol\":{\"keccak256\":\"0x45dfaa2cfdde87f48a6ee38bb6fb739847aef7cf3f6137bdcd8c8a330559ec79\",\"license\":\"BUSL-1.1\",\"urls\":[\"bzz-raw://1b7f6bd75b42fcaa91ceb7140cb2c41926a1fe6ee2d3161e4fe6186b181ba232\",\"dweb:/ipfs/QmZjbdKiSs33C9i3GDc3sdD39Pz4YPkDoKftowoUF4kHmY\"]},\"lib/eigenlayer-middleware/lib/eigenlayer-contracts/src/contracts/interfaces/IStrategy.sol\":{\"keccak256\":\"0xc530c6a944b70051fd0dac0222de9a4b5baadeaf94ad194daac6ad8d2ace7420\",\"license\":\"BUSL-1.1\",\"urls\":[\"bzz-raw://3767df0364ce835b52e786d2851431eb9223fe4747602107505477e162231d73\",\"dweb:/ipfs/QmZkH5bKUygQrJomndNaQqkefVRW4rRefCa8HPJ5HMczxJ\"]},\"lib/eigenlayer-middleware/lib/eigenlayer-contracts/src/contracts/interfaces/IStrategyManager.sol\":{\"keccak256\":\"0x68bf02a443fc8b2f612eba3d39bfefa5f61f78b549f111cdecec5f2c58236a52\",\"license\":\"BUSL-1.1\",\"urls\":[\"bzz-raw://76bc6875ce74128b861fdac5fd1c0c72f3cc9bacf67fa4a73721b95fb23959ef\",\"dweb:/ipfs/QmPix4WJmf9fXyMZxfgwXEHBcg7V4NAbRqs4HUf5YrSJcM\"]},\"lib/eigenlayer-middleware/lib/eigenlayer-contracts/src/contracts/libraries/BeaconChainProofs.sol\":{\"keccak256\":\"0x70d89b05c1c5f47b74a07fbb5a2c05e606fed494e749ea98a9915b7be73df377\",\"license\":\"BUSL-1.1\",\"urls\":[\"bzz-raw://db1d3bfaee69aef53c8b12b492a17584e6d1ac94610cb8b38aad33e1cdd81af7\",\"dweb:/ipfs/QmfVsMTj1hcf9fMEm5RzvtcBN4dMcAKFBgUUDsNDr5XFpq\"]},\"lib/eigenlayer-middleware/lib/eigenlayer-contracts/src/contracts/libraries/Endian.sol\":{\"keccak256\":\"0xf3b72653ba2567a978d4612703fa5f71c5fcd015d8dac7818468f22772d90a9d\",\"license\":\"BUSL-1.1\",\"urls\":[\"bzz-raw://cee9d09370d968138d775c39525db4cd0768d60d17be7685519de12444e7dd2f\",\"dweb:/ipfs/QmUdGh8wpMei3edKiEWA6S96s9dRt4ekZKJ4nau356X8xQ\"]},\"lib/eigenlayer-middleware/lib/eigenlayer-contracts/src/contracts/libraries/Merkle.sol\":{\"keccak256\":\"0x9095fc29b96d102b10c02d44b3a6fbfa25593ef6ae4a810363ab885b9e6b0f71\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://0945132d482d56278edddb1d32209903c4d3839c87ba4317aadd97dc23610d0f\",\"dweb:/ipfs/QmVuM2aLRHxitx4rPx3GTYTBCVNcjYn6sHBRr1biUjLBP5\"]},\"lib/eigenlayer-middleware/lib/openzeppelin-contracts/contracts/proxy/beacon/IBeacon.sol\":{\"keccak256\":\"0xd50a3421ac379ccb1be435fa646d66a65c986b4924f0849839f08692f39dde61\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://ada1e030c0231db8d143b44ce92b4d1158eedb087880cad6d8cc7bd7ebe7b354\",\"dweb:/ipfs/QmWZ2NHZweRpz1U9GF6R1h65ri76dnX7fNxLBeM2t5N5Ce\"]},\"lib/eigenlayer-middleware/lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol\":{\"keccak256\":\"0x9750c6b834f7b43000631af5cc30001c5f547b3ceb3635488f140f60e897ea6b\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://5a7d5b1ef5d8d5889ad2ed89d8619c09383b80b72ab226e0fe7bde1636481e34\",\"dweb:/ipfs/QmebXWgtEfumQGBdVeM6c71McLixYXQP5Bk6kKXuoY4Bmr\"]},\"lib/eigenlayer-middleware/src/OperatorStateRetriever.sol\":{\"keccak256\":\"0x5573c9b7416d08e8b2f3e2e238ca4ba7a0c0fd4e6c6f8d4f7eca5487f26a042a\",\"license\":\"BUSL-1.1\",\"urls\":[\"bzz-raw://98c9e6ec2b3478f3a962d57e280ddb69a93be7035ed7a4cdb775d29b763053af\",\"dweb:/ipfs/QmaMHNFsddfP7fKxaVwn8foWqwp7ySwaD5Lof19bsmsdvg\"]},\"lib/eigenlayer-middleware/src/interfaces/IBLSApkRegistry.sol\":{\"keccak256\":\"0xc07a5edfd95ab4f16f16a8dc8e76eadf4b0e90fe49db90540d01daaad86898c5\",\"license\":\"BUSL-1.1\",\"urls\":[\"bzz-raw://52b53266450a53da641e82d8ae3be93c5e09f8342b4ea0cc96bb9038d8406354\",\"dweb:/ipfs/QmVuoiQyqPTLCGnyt8zDaxiyaj4ETdgTGKv4MDHWzqEDjp\"]},\"lib/eigenlayer-middleware/src/interfaces/IIndexRegistry.sol\":{\"keccak256\":\"0x83b2d56aacf27e65c4959a832c5de573e013908c044f6e48ea8284ac5282ae2b\",\"license\":\"BUSL-1.1\",\"urls\":[\"bzz-raw://877af382587e96bb39bcc6db8bb5e4b871db5025c52347d4bee9afeaa4a6cc8d\",\"dweb:/ipfs/QmdnhsQCChzq2o5NgbeT3JxSsEcMm1PC9QW6zenZNPjD9F\"]},\"lib/eigenlayer-middleware/src/interfaces/IRegistry.sol\":{\"keccak256\":\"0x51426a17fb7e54bd3720e2890104e97a8559a13ff248b3d6b840916751c143d3\",\"license\":\"BUSL-1.1\",\"urls\":[\"bzz-raw://01f91289e6100d528cb8b318cb14ff22a0bc52882c9d4db41585e030cc9ddc25\",\"dweb:/ipfs/Qmb22nqGrsrtNovHRwbMCvDHGENuxAgrWu3Db4p7Er2MHY\"]},\"lib/eigenlayer-middleware/src/interfaces/IRegistryCoordinator.sol\":{\"keccak256\":\"0xdd8effb082c1d5957d5ff43d7c59497b32866a6d82bcc7d5efa49ea9bc9b3385\",\"license\":\"BUSL-1.1\",\"urls\":[\"bzz-raw://cb33a2a1446585b13b7a509e880c60d658d2d2522ec48a9f02e30d2cff54002d\",\"dweb:/ipfs/QmVNG8ZPZkXzNEadPdTj1uBYLiZdCnYfsE5iGU6nJcJXiD\"]},\"lib/eigenlayer-middleware/src/interfaces/IStakeRegistry.sol\":{\"keccak256\":\"0x1b8b4d757c1b804bc4cf6fbbf8bf8f89ebdeb30a31014751fe7d01deb9d513d4\",\"license\":\"BUSL-1.1\",\"urls\":[\"bzz-raw://984bf2777b898ed187d28997f9783f5c293a1a1848e3e9aa470ce9183d454c97\",\"dweb:/ipfs/Qme3aTpBrkLu8wYHFMZbCfhXHoZ1M6SpXkeC237T9BuU5B\"]},\"lib/eigenlayer-middleware/src/libraries/BN254.sol\":{\"keccak256\":\"0xb428c8d0c3b325507a88a61a80115493eb88606ccc19ed64a31e11294ab853b3\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://d7b6fb935bfe0494e6ff970c8f30a86d5f4cf5c3e0967300c28cd383c043acae\",\"dweb:/ipfs/QmUHfFZaVjLPXhkBmcxrZhAHZaSFQDqXtrLGpjGBQBa5Ki\"]},\"lib/eigenlayer-middleware/src/libraries/BitmapUtils.sol\":{\"keccak256\":\"0x44315ac460be30a6b18fd4df4d1b8afb46653bf4dc06ca9f93c32353fd0605c5\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://da14f2ead3a375b02afd09d4a02edddf7b63a88945746b96789b2473184fdb04\",\"dweb:/ipfs/QmRqcjxa2Vv2MrLdPeAwsktXdWTirapEDsRbJCyYRtKT6g\"]}},\"version\":1}","metadata":{"compiler":{"version":"0.8.27+commit.40a35a09"},"language":"Solidity","output":{"abi":[{"inputs":[{"internalType":"contract IRegistryCoordinator","name":"registryCoordinator","type":"address"},{"internalType":"bytes32[]","name":"operatorIds","type":"bytes32[]"}],"stateMutability":"view","type":"function","name":"getBatchOperatorFromId","outputs":[{"internalType":"address[]","name":"operators","type":"address[]"}]},{"inputs":[{"internalType":"contract IRegistryCoordinator","name":"registryCoordinator","type":"address"},{"internalType":"address[]","name":"operators","type":"address[]"}],"stateMutability":"view","type":"function","name":"getBatchOperatorId","outputs":[{"internalType":"bytes32[]","name":"operatorIds","type":"bytes32[]"}]},{"inputs":[{"internalType":"contract IRegistryCoordinator","name":"registryCoordinator","type":"address"},{"internalType":"uint32","name":"referenceBlockNumber","type":"uint32"},{"internalType":"bytes","name":"quorumNumbers","type":"bytes"},{"internalType":"bytes32[]","name":"nonSignerOperatorIds","type":"bytes32[]"}],"stateMutability":"view","type":"function","name":"getCheckSignaturesIndices","outputs":[{"internalType":"struct OperatorStateRetriever.CheckSignaturesIndices","name":"","type":"tuple","components":[{"internalType":"uint32[]","name":"nonSignerQuorumBitmapIndices","type":"uint32[]"},{"internalType":"uint32[]","name":"quorumApkIndices","type":"uint32[]"},{"internalType":"uint32[]","name":"totalStakeIndices","type":"uint32[]"},{"internalType":"uint32[][]","name":"nonSignerStakeIndices","type":"uint32[][]"}]}]},{"inputs":[{"internalType":"contract IRegistryCoordinator","name":"registryCoordinator","type":"address"},{"internalType":"bytes","name":"quorumNumbers","type":"bytes"},{"internalType":"uint32","name":"blockNumber","type":"uint32"}],"stateMutability":"view","type":"function","name":"getOperatorState","outputs":[{"internalType":"struct OperatorStateRetriever.Operator[][]","name":"","type":"tuple[][]","components":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bytes32","name":"operatorId","type":"bytes32"},{"internalType":"uint96","name":"stake","type":"uint96"}]}]},{"inputs":[{"internalType":"contract IRegistryCoordinator","name":"registryCoordinator","type":"address"},{"internalType":"bytes32","name":"operatorId","type":"bytes32"},{"internalType":"uint32","name":"blockNumber","type":"uint32"}],"stateMutability":"view","type":"function","name":"getOperatorState","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"struct OperatorStateRetriever.Operator[][]","name":"","type":"tuple[][]","components":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bytes32","name":"operatorId","type":"bytes32"},{"internalType":"uint96","name":"stake","type":"uint96"}]}]},{"inputs":[{"internalType":"contract IRegistryCoordinator","name":"registryCoordinator","type":"address"},{"internalType":"bytes32[]","name":"operatorIds","type":"bytes32[]"},{"internalType":"uint32","name":"blockNumber","type":"uint32"}],"stateMutability":"view","type":"function","name":"getQuorumBitmapsAtBlockNumber","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}]}],"devdoc":{"kind":"dev","methods":{"getBatchOperatorFromId(address,bytes32[])":{"details":"if an operator is not registered, the operator address will be 0","params":{"operators":"is the array of operatorIds to get corresponding operator addresses for","registryCoordinator":"is the AVS registry coordinator to fetch the operator information from"}},"getBatchOperatorId(address,address[])":{"details":"if an operator is not registered, the operatorId will be 0","params":{"operators":"is the array of operator address to get corresponding operatorIds for","registryCoordinator":"is the AVS registry coordinator to fetch the operator information from"}},"getCheckSignaturesIndices(address,uint32,bytes,bytes32[])":{"params":{"nonSignerOperatorIds":"are the ids of the nonsigning operators","quorumNumbers":"are the ids of the quorums to get the operator state for","referenceBlockNumber":"is the block number to get the indices for","registryCoordinator":"is the registry coordinator to fetch the AVS registry information from"},"returns":{"_0":"1) the indices of the quorumBitmaps for each of the operators in the @param nonSignerOperatorIds array at the given blocknumber 2) the indices of the total stakes entries for the given quorums at the given blocknumber 3) the indices of the stakes of each of the nonsigners in each of the quorums they were a part of (for each nonsigner, an array of length the number of quorums they were a part of that are also part of the provided quorumNumbers) at the given blocknumber 4) the indices of the quorum apks for each of the provided quorums at the given blocknumber"}},"getOperatorState(address,bytes,uint32)":{"params":{"blockNumber":"is the block number to get the operator state for","quorumNumbers":"are the ids of the quorums to get the operator state for","registryCoordinator":"is the registry coordinator to fetch the AVS registry information from"},"returns":{"_0":"2d array of Operators. For each quorum, an ordered list of Operators"}},"getOperatorState(address,bytes32,uint32)":{"params":{"blockNumber":"is the block number to get the operator state for","operatorId":"the id of the operator to fetch the quorums lists ","registryCoordinator":"is the registry coordinator to fetch the AVS registry information from"},"returns":{"_0":"1) the quorumBitmap of the operator at the given blockNumber 2) 2d array of Operator structs. For each quorum the provided operator was a part of at `blockNumber`, an ordered list of operators."}},"getQuorumBitmapsAtBlockNumber(address,bytes32[],uint32)":{"params":{"blockNumber":"is the block number to get the quorumBitmaps for","operatorIds":"are the ids of the operators to get the quorumBitmaps for","registryCoordinator":"is the AVS registry coordinator to fetch the operator information from"}}},"version":1},"userdoc":{"kind":"user","methods":{"getBatchOperatorFromId(address,bytes32[])":{"notice":"This function returns the operator addresses for each of the operators in the operatorIds array"},"getBatchOperatorId(address,address[])":{"notice":"This function returns the operatorIds for each of the operators in the operators array"},"getCheckSignaturesIndices(address,uint32,bytes,bytes32[])":{"notice":"this is called by the AVS operator to get the relevant indices for the checkSignatures function if they are not running an indexer "},"getOperatorState(address,bytes,uint32)":{"notice":"returns the ordered list of operators (id and stake) for each quorum. The AVS coordinator may call this function directly to get the operator state for a given block number"},"getOperatorState(address,bytes32,uint32)":{"notice":"This function is intended to to be called by AVS operators every time a new task is created (i.e.) the AVS coordinator makes a request to AVS operators. Since all of the crucial information is kept onchain, operators don't need to run indexers to fetch the data."},"getQuorumBitmapsAtBlockNumber(address,bytes32[],uint32)":{"notice":"this function returns the quorumBitmaps for each of the operators in the operatorIds array at the given blocknumber"}},"version":1}},"settings":{"remappings":["@openzeppelin-upgrades-v4.9.0/=lib/eigenlayer-middleware/lib/eigenlayer-contracts/lib/openzeppelin-contracts-upgradeable-v4.9.0/","@openzeppelin-upgrades/contracts/=lib/eigenlayer-middleware/lib/openzeppelin-contracts-upgradeable/contracts/","@openzeppelin-v4.9.0/=lib/eigenlayer-middleware/lib/eigenlayer-contracts/lib/openzeppelin-contracts-v4.9.0/","@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/","@openzeppelin/contracts/=lib/eigenlayer-middleware/lib/openzeppelin-contracts/contracts/","ds-test/=lib/eigenlayer-middleware/lib/ds-test/src/","eigenlayer-contracts/=lib/eigenlayer-middleware/lib/eigenlayer-contracts/","eigenlayer-core-contracts/=lib/eigenlayer-middleware/lib/eigenlayer-contracts/src/contracts/core/","eigenlayer-core/=lib/eigenlayer-middleware/lib/eigenlayer-contracts/src/","eigenlayer-middleware/=lib/eigenlayer-middleware/src/","eigenlayer-scripts/=lib/eigenlayer-middleware/lib/eigenlayer-contracts/script/","erc4626-tests/=lib/openzeppelin-contracts-upgradeable/lib/erc4626-tests/","forge-std/=lib/forge-std/src/","openzeppelin-contracts-upgradeable-v4.9.0/=lib/eigenlayer-middleware/lib/eigenlayer-contracts/lib/openzeppelin-contracts-upgradeable-v4.9.0/","openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/","openzeppelin-contracts-v4.9.0/=lib/eigenlayer-middleware/lib/eigenlayer-contracts/lib/openzeppelin-contracts-v4.9.0/","openzeppelin-contracts/=lib/openzeppelin-contracts/","openzeppelin/=lib/eigenlayer-middleware/lib/eigenlayer-contracts/lib/openzeppelin-contracts-upgradeable-v4.9.0/contracts/"],"optimizer":{"enabled":true,"runs":200},"metadata":{"bytecodeHash":"ipfs"},"compilationTarget":{"lib/eigenlayer-middleware/src/OperatorStateRetriever.sol":"OperatorStateRetriever"},"evmVersion":"paris","libraries":{}},"sources":{"lib/eigenlayer-middleware/lib/eigenlayer-contracts/src/contracts/interfaces/IBeaconChainOracle.sol":{"keccak256":"0x0fef07aa6179c77198f1514e12e628aa1c876e04f9c181ec853a322179e5be00","urls":["bzz-raw://51438325876cc2d4c77f58488a7e27b488015d1b663c50be6a5cafbd73b9c983","dweb:/ipfs/QmViCuGoYZzi6wtXA8PPKigqVv3KMuNxEVQ1Td9dGqjL18"],"license":"BUSL-1.1"},"lib/eigenlayer-middleware/lib/eigenlayer-contracts/src/contracts/interfaces/IDelegationManager.sol":{"keccak256":"0xab76a9f4eff865cbb689f627cf98263488765519d7a4ec5ffbcb0ca4972842f9","urls":["bzz-raw://ff57ce18e8350bf39f190645db0988bc0f1279f1872150a114a1b520c38a2914","dweb:/ipfs/QmSsUXkNUqYuJgGRumHTSs9rAaboGjecotcM4xHrdBYWaZ"],"license":"BUSL-1.1"},"lib/eigenlayer-middleware/lib/eigenlayer-contracts/src/contracts/interfaces/IETHPOSDeposit.sol":{"keccak256":"0x2e60e5f4b0da0a0a4e2a07c63141120998559970c21deac743ea0c64a60a880c","urls":["bzz-raw://e635c346bde5b7ade9bcf35bc733081520cb86015be4fbc6e761e6e9482c4c91","dweb:/ipfs/QmRoeazEnbFn5SPSWAkoFK2gSN9DMp3hJAnrLWuL2sKutz"],"license":"CC0-1.0"},"lib/eigenlayer-middleware/lib/eigenlayer-contracts/src/contracts/interfaces/IEigenPod.sol":{"keccak256":"0xb50c36ad96b6679bb80fd8331f949cbfbcba0f529026e1421a4d2bae64396eba","urls":["bzz-raw://5719181d780120f1e688c0da276992a8caf185815917f453b3550537c31ed4cc","dweb:/ipfs/QmYprRC5ZEXhz3zAUND5E8Xjn6s5TL8ZF8QbnndVq7aVPR"],"license":"BUSL-1.1"},"lib/eigenlayer-middleware/lib/eigenlayer-contracts/src/contracts/interfaces/IEigenPodManager.sol":{"keccak256":"0xd8a64dbed03d3a5cdbefe1af75968f2dde07f973749c2ef5197bf7187c3e448c","urls":["bzz-raw://27ccc7c1fd9352e9f9b357c9063d255dc0ed9583f43db09f786ac7497d7846b8","dweb:/ipfs/QmeJzuJkE9m2NUNwZSp4tGZEZmih1LeucePup8hzMVDRbG"],"license":"BUSL-1.1"},"lib/eigenlayer-middleware/lib/eigenlayer-contracts/src/contracts/interfaces/IPausable.sol":{"keccak256":"0x98cffc894842947377e24c1d375813a1120dd73a84c29782ab68404e109cb34f","urls":["bzz-raw://b3474f6c350ceaee57cbdfb08fb48835d0c6e81ae8ebfbb9667899584a139324","dweb:/ipfs/QmWELKtksdtWxQbqAccd8yGyhKqrgPZXTADKR7BuT27Zg5"],"license":"BUSL-1.1"},"lib/eigenlayer-middleware/lib/eigenlayer-contracts/src/contracts/interfaces/IPauserRegistry.sol":{"keccak256":"0x9de8dd682bc0d812bbd6583c0231cbf35448d5eff58b74a93efa64cb9a768c49","urls":["bzz-raw://c00d6c675b9c72b092d287fe85fd37782588df32b8eb59ab4c7db7a86be25e7d","dweb:/ipfs/QmeYokY3HhAdbBaCPdHg3PgQEdRCDFEJy3Wf7VtgHBkQSx"],"license":"BUSL-1.1"},"lib/eigenlayer-middleware/lib/eigenlayer-contracts/src/contracts/interfaces/ISignatureUtils.sol":{"keccak256":"0x5e52482a31d94401a8502f3014c4aada1142b4450fc0596dff8e1866a85fe092","urls":["bzz-raw://17dc326c9361bc1453379f26545963557b2883b0c88bc07d4477e04dbcc0cc8c","dweb:/ipfs/QmZXT7A816W5JH2ymirE2ETaJttqztFCsEL22AV8oEfCK9"],"license":"BUSL-1.1"},"lib/eigenlayer-middleware/lib/eigenlayer-contracts/src/contracts/interfaces/ISlasher.sol":{"keccak256":"0x45dfaa2cfdde87f48a6ee38bb6fb739847aef7cf3f6137bdcd8c8a330559ec79","urls":["bzz-raw://1b7f6bd75b42fcaa91ceb7140cb2c41926a1fe6ee2d3161e4fe6186b181ba232","dweb:/ipfs/QmZjbdKiSs33C9i3GDc3sdD39Pz4YPkDoKftowoUF4kHmY"],"license":"BUSL-1.1"},"lib/eigenlayer-middleware/lib/eigenlayer-contracts/src/contracts/interfaces/IStrategy.sol":{"keccak256":"0xc530c6a944b70051fd0dac0222de9a4b5baadeaf94ad194daac6ad8d2ace7420","urls":["bzz-raw://3767df0364ce835b52e786d2851431eb9223fe4747602107505477e162231d73","dweb:/ipfs/QmZkH5bKUygQrJomndNaQqkefVRW4rRefCa8HPJ5HMczxJ"],"license":"BUSL-1.1"},"lib/eigenlayer-middleware/lib/eigenlayer-contracts/src/contracts/interfaces/IStrategyManager.sol":{"keccak256":"0x68bf02a443fc8b2f612eba3d39bfefa5f61f78b549f111cdecec5f2c58236a52","urls":["bzz-raw://76bc6875ce74128b861fdac5fd1c0c72f3cc9bacf67fa4a73721b95fb23959ef","dweb:/ipfs/QmPix4WJmf9fXyMZxfgwXEHBcg7V4NAbRqs4HUf5YrSJcM"],"license":"BUSL-1.1"},"lib/eigenlayer-middleware/lib/eigenlayer-contracts/src/contracts/libraries/BeaconChainProofs.sol":{"keccak256":"0x70d89b05c1c5f47b74a07fbb5a2c05e606fed494e749ea98a9915b7be73df377","urls":["bzz-raw://db1d3bfaee69aef53c8b12b492a17584e6d1ac94610cb8b38aad33e1cdd81af7","dweb:/ipfs/QmfVsMTj1hcf9fMEm5RzvtcBN4dMcAKFBgUUDsNDr5XFpq"],"license":"BUSL-1.1"},"lib/eigenlayer-middleware/lib/eigenlayer-contracts/src/contracts/libraries/Endian.sol":{"keccak256":"0xf3b72653ba2567a978d4612703fa5f71c5fcd015d8dac7818468f22772d90a9d","urls":["bzz-raw://cee9d09370d968138d775c39525db4cd0768d60d17be7685519de12444e7dd2f","dweb:/ipfs/QmUdGh8wpMei3edKiEWA6S96s9dRt4ekZKJ4nau356X8xQ"],"license":"BUSL-1.1"},"lib/eigenlayer-middleware/lib/eigenlayer-contracts/src/contracts/libraries/Merkle.sol":{"keccak256":"0x9095fc29b96d102b10c02d44b3a6fbfa25593ef6ae4a810363ab885b9e6b0f71","urls":["bzz-raw://0945132d482d56278edddb1d32209903c4d3839c87ba4317aadd97dc23610d0f","dweb:/ipfs/QmVuM2aLRHxitx4rPx3GTYTBCVNcjYn6sHBRr1biUjLBP5"],"license":"MIT"},"lib/eigenlayer-middleware/lib/openzeppelin-contracts/contracts/proxy/beacon/IBeacon.sol":{"keccak256":"0xd50a3421ac379ccb1be435fa646d66a65c986b4924f0849839f08692f39dde61","urls":["bzz-raw://ada1e030c0231db8d143b44ce92b4d1158eedb087880cad6d8cc7bd7ebe7b354","dweb:/ipfs/QmWZ2NHZweRpz1U9GF6R1h65ri76dnX7fNxLBeM2t5N5Ce"],"license":"MIT"},"lib/eigenlayer-middleware/lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol":{"keccak256":"0x9750c6b834f7b43000631af5cc30001c5f547b3ceb3635488f140f60e897ea6b","urls":["bzz-raw://5a7d5b1ef5d8d5889ad2ed89d8619c09383b80b72ab226e0fe7bde1636481e34","dweb:/ipfs/QmebXWgtEfumQGBdVeM6c71McLixYXQP5Bk6kKXuoY4Bmr"],"license":"MIT"},"lib/eigenlayer-middleware/src/OperatorStateRetriever.sol":{"keccak256":"0x5573c9b7416d08e8b2f3e2e238ca4ba7a0c0fd4e6c6f8d4f7eca5487f26a042a","urls":["bzz-raw://98c9e6ec2b3478f3a962d57e280ddb69a93be7035ed7a4cdb775d29b763053af","dweb:/ipfs/QmaMHNFsddfP7fKxaVwn8foWqwp7ySwaD5Lof19bsmsdvg"],"license":"BUSL-1.1"},"lib/eigenlayer-middleware/src/interfaces/IBLSApkRegistry.sol":{"keccak256":"0xc07a5edfd95ab4f16f16a8dc8e76eadf4b0e90fe49db90540d01daaad86898c5","urls":["bzz-raw://52b53266450a53da641e82d8ae3be93c5e09f8342b4ea0cc96bb9038d8406354","dweb:/ipfs/QmVuoiQyqPTLCGnyt8zDaxiyaj4ETdgTGKv4MDHWzqEDjp"],"license":"BUSL-1.1"},"lib/eigenlayer-middleware/src/interfaces/IIndexRegistry.sol":{"keccak256":"0x83b2d56aacf27e65c4959a832c5de573e013908c044f6e48ea8284ac5282ae2b","urls":["bzz-raw://877af382587e96bb39bcc6db8bb5e4b871db5025c52347d4bee9afeaa4a6cc8d","dweb:/ipfs/QmdnhsQCChzq2o5NgbeT3JxSsEcMm1PC9QW6zenZNPjD9F"],"license":"BUSL-1.1"},"lib/eigenlayer-middleware/src/interfaces/IRegistry.sol":{"keccak256":"0x51426a17fb7e54bd3720e2890104e97a8559a13ff248b3d6b840916751c143d3","urls":["bzz-raw://01f91289e6100d528cb8b318cb14ff22a0bc52882c9d4db41585e030cc9ddc25","dweb:/ipfs/Qmb22nqGrsrtNovHRwbMCvDHGENuxAgrWu3Db4p7Er2MHY"],"license":"BUSL-1.1"},"lib/eigenlayer-middleware/src/interfaces/IRegistryCoordinator.sol":{"keccak256":"0xdd8effb082c1d5957d5ff43d7c59497b32866a6d82bcc7d5efa49ea9bc9b3385","urls":["bzz-raw://cb33a2a1446585b13b7a509e880c60d658d2d2522ec48a9f02e30d2cff54002d","dweb:/ipfs/QmVNG8ZPZkXzNEadPdTj1uBYLiZdCnYfsE5iGU6nJcJXiD"],"license":"BUSL-1.1"},"lib/eigenlayer-middleware/src/interfaces/IStakeRegistry.sol":{"keccak256":"0x1b8b4d757c1b804bc4cf6fbbf8bf8f89ebdeb30a31014751fe7d01deb9d513d4","urls":["bzz-raw://984bf2777b898ed187d28997f9783f5c293a1a1848e3e9aa470ce9183d454c97","dweb:/ipfs/Qme3aTpBrkLu8wYHFMZbCfhXHoZ1M6SpXkeC237T9BuU5B"],"license":"BUSL-1.1"},"lib/eigenlayer-middleware/src/libraries/BN254.sol":{"keccak256":"0xb428c8d0c3b325507a88a61a80115493eb88606ccc19ed64a31e11294ab853b3","urls":["bzz-raw://d7b6fb935bfe0494e6ff970c8f30a86d5f4cf5c3e0967300c28cd383c043acae","dweb:/ipfs/QmUHfFZaVjLPXhkBmcxrZhAHZaSFQDqXtrLGpjGBQBa5Ki"],"license":"MIT"},"lib/eigenlayer-middleware/src/libraries/BitmapUtils.sol":{"keccak256":"0x44315ac460be30a6b18fd4df4d1b8afb46653bf4dc06ca9f93c32353fd0605c5","urls":["bzz-raw://da14f2ead3a375b02afd09d4a02edddf7b63a88945746b96789b2473184fdb04","dweb:/ipfs/QmRqcjxa2Vv2MrLdPeAwsktXdWTirapEDsRbJCyYRtKT6g"],"license":"MIT"}},"version":1},"id":117} \ No newline at end of file diff --git a/telemetry_api/priv/repo/migrations/20240917212329_create_operators.exs b/telemetry_api/priv/repo/migrations/20240917212329_create_operators.exs index a4a2a9b94..80a5e40fe 100644 --- a/telemetry_api/priv/repo/migrations/20240917212329_create_operators.exs +++ b/telemetry_api/priv/repo/migrations/20240917212329_create_operators.exs @@ -4,6 +4,9 @@ defmodule TelemetryApi.Repo.Migrations.CreateOperators do def change do create table(:operators, primary_key: false) do add :address, :string, primary_key: true + add :id, :string + add :stake, :string + add :name, :string add :version, :string timestamps(type: :utc_datetime) diff --git a/telemetry_api/start.sh b/telemetry_api/start.sh index e93cc0733..b20a0bfae 100755 --- a/telemetry_api/start.sh +++ b/telemetry_api/start.sh @@ -1,7 +1,17 @@ #!/bin/bash -source .env.dev +source .env + +# Add new environment variables here +env_vars=( + "ENVIRONMENT" + "ALIGNED_CONFIG_FILE" +) + +for var in "${env_vars[@]}"; do + export "$var=${!var}" +done mix compile --force #force recompile to get the latest .env values -mix phx.server +elixir --sname telemetry -S mix phx.server From 49b9646d408e3fb73de5b1a47f4cb95e57060887 Mon Sep 17 00:00:00 2001 From: JuArce <52429267+JuArce@users.noreply.github.com> Date: Tue, 1 Oct 2024 15:19:44 -0300 Subject: [PATCH 13/55] chore: upload mix lock --- telemetry_api/mix.lock | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/telemetry_api/mix.lock b/telemetry_api/mix.lock index 3c3f2e69d..0d3d1123e 100644 --- a/telemetry_api/mix.lock +++ b/telemetry_api/mix.lock @@ -1,7 +1,10 @@ %{ + "acceptor_pool": {:hex, :acceptor_pool, "1.0.0", "43c20d2acae35f0c2bcd64f9d2bde267e459f0f3fd23dab26485bf518c281b21", [:rebar3], [], "hexpm", "0cbcd83fdc8b9ad2eee2067ef8b91a14858a5883cb7cd800e6fcd5803e158788"}, "bandit": {:hex, :bandit, "1.5.7", "6856b1e1df4f2b0cb3df1377eab7891bec2da6a7fd69dc78594ad3e152363a50", [:mix], [{:hpax, "~> 1.0.0", [hex: :hpax, repo: "hexpm", optional: false]}, {:plug, "~> 1.14", [hex: :plug, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}, {:thousand_island, "~> 1.0", [hex: :thousand_island, repo: "hexpm", optional: false]}, {:websock, "~> 0.5", [hex: :websock, repo: "hexpm", optional: false]}], "hexpm", "f2dd92ae87d2cbea2fa9aa1652db157b6cba6c405cb44d4f6dd87abba41371cd"}, "castore": {:hex, :castore, "1.0.8", "dedcf20ea746694647f883590b82d9e96014057aff1d44d03ec90f36a5c0dc6e", [:mix], [], "hexpm", "0b2b66d2ee742cb1d9cb8c8be3b43c3a70ee8651f37b75a8b982e036752983f1"}, "certifi": {:hex, :certifi, "2.12.0", "2d1cca2ec95f59643862af91f001478c9863c2ac9cb6e2f89780bfd8de987329", [:rebar3], [], "hexpm", "ee68d85df22e554040cdb4be100f33873ac6051387baf6a8f6ce82272340ff1c"}, + "chatterbox": {:hex, :ts_chatterbox, "0.15.1", "5cac4d15dd7ad61fc3c4415ce4826fc563d4643dee897a558ec4ea0b1c835c9c", [:rebar3], [{:hpack, "~> 0.3.0", [hex: :hpack_erl, repo: "hexpm", optional: false]}], "hexpm", "4f75b91451338bc0da5f52f3480fa6ef6e3a2aeecfc33686d6b3d0a0948f31aa"}, + "ctx": {:hex, :ctx, "0.6.0", "8ff88b70e6400c4df90142e7f130625b82086077a45364a78d208ed3ed53c7fe", [:rebar3], [], "hexpm", "a14ed2d1b67723dbebbe423b28d7615eb0bdcba6ff28f2d1f1b0a7e1d4aa5fc2"}, "db_connection": {:hex, :db_connection, "2.7.0", "b99faa9291bb09892c7da373bb82cba59aefa9b36300f6145c5f201c7adf48ec", [:mix], [{:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "dcf08f31b2701f857dfc787fbad78223d61a32204f217f15e881dd93e4bdd3ff"}, "decimal": {:hex, :decimal, "2.1.1", "5611dca5d4b2c3dd497dec8f68751f1f1a54755e8ed2a966c2633cf885973ad6", [:mix], [], "hexpm", "53cfe5f497ed0e7771ae1a475575603d77425099ba5faef9394932b35020ffcc"}, "dns_cluster": {:hex, :dns_cluster, "0.1.3", "0bc20a2c88ed6cc494f2964075c359f8c2d00e1bf25518a6a6c7fd277c9b0c66", [:mix], [], "hexpm", "46cb7c4a1b3e52c7ad4cbe33ca5079fbde4840dedeafca2baf77996c2da1bc33"}, @@ -14,7 +17,10 @@ "ex_rlp": {:hex, :ex_rlp, "0.6.0", "985391d2356a7cb8712a4a9a2deb93f19f2fbca0323f5c1203fcaf64d077e31e", [:mix], [], "hexpm", "7135db93b861d9e76821039b60b00a6a22d2c4e751bf8c444bffe7a042f1abaf"}, "ex_secp256k1": {:hex, :ex_secp256k1, "0.7.3", "489b6fd57fab5a7259ace927d8cb5171aad835e9c7279c2a859a0483cb069415", [:mix], [{:rustler, ">= 0.0.0", [hex: :rustler, repo: "hexpm", optional: true]}, {:rustler_precompiled, "~> 0.7", [hex: :rustler_precompiled, repo: "hexpm", optional: false]}], "hexpm", "ea63159442f4d8143166cd1507da03edc43216d6e7c6bac4b416bdce04f0daa8"}, "finch": {:hex, :finch, "0.19.0", "c644641491ea854fc5c1bbaef36bfc764e3f08e7185e1f084e35e0672241b76d", [:mix], [{:mime, "~> 1.0 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:mint, "~> 1.6.2 or ~> 1.7", [hex: :mint, repo: "hexpm", optional: false]}, {:nimble_options, "~> 0.4 or ~> 1.0", [hex: :nimble_options, repo: "hexpm", optional: false]}, {:nimble_pool, "~> 1.1", [hex: :nimble_pool, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "fc5324ce209125d1e2fa0fcd2634601c52a787aff1cd33ee833664a5af4ea2b6"}, + "gproc": {:hex, :gproc, "0.9.1", "f1df0364423539cf0b80e8201c8b1839e229e5f9b3ccb944c5834626998f5b8c", [:rebar3], [], "hexpm", "905088e32e72127ed9466f0bac0d8e65704ca5e73ee5a62cb073c3117916d507"}, + "grpcbox": {:hex, :grpcbox, "0.17.1", "6e040ab3ef16fe699ffb513b0ef8e2e896da7b18931a1ef817143037c454bcce", [:rebar3], [{:acceptor_pool, "~> 1.0.0", [hex: :acceptor_pool, repo: "hexpm", optional: false]}, {:chatterbox, "~> 0.15.1", [hex: :ts_chatterbox, repo: "hexpm", optional: false]}, {:ctx, "~> 0.6.0", [hex: :ctx, repo: "hexpm", optional: false]}, {:gproc, "~> 0.9.1", [hex: :gproc, repo: "hexpm", optional: false]}], "hexpm", "4a3b5d7111daabc569dc9cbd9b202a3237d81c80bf97212fbc676832cb0ceb17"}, "hackney": {:hex, :hackney, "1.20.1", "8d97aec62ddddd757d128bfd1df6c5861093419f8f7a4223823537bad5d064e2", [:rebar3], [{:certifi, "~> 2.12.0", [hex: :certifi, repo: "hexpm", optional: false]}, {:idna, "~> 6.1.0", [hex: :idna, repo: "hexpm", optional: false]}, {:metrics, "~> 1.0.0", [hex: :metrics, repo: "hexpm", optional: false]}, {:mimerl, "~> 1.1", [hex: :mimerl, repo: "hexpm", optional: false]}, {:parse_trans, "3.4.1", [hex: :parse_trans, repo: "hexpm", optional: false]}, {:ssl_verify_fun, "~> 1.1.0", [hex: :ssl_verify_fun, repo: "hexpm", optional: false]}, {:unicode_util_compat, "~> 0.7.0", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm", "fe9094e5f1a2a2c0a7d10918fee36bfec0ec2a979994cff8cfe8058cd9af38e3"}, + "hpack": {:hex, :hpack_erl, "0.3.0", "2461899cc4ab6a0ef8e970c1661c5fc6a52d3c25580bc6dd204f84ce94669926", [:rebar3], [], "hexpm", "d6137d7079169d8c485c6962dfe261af5b9ef60fbc557344511c1e65e3d95fb0"}, "hpax": {:hex, :hpax, "1.0.0", "28dcf54509fe2152a3d040e4e3df5b265dcb6cb532029ecbacf4ce52caea3fd2", [:mix], [], "hexpm", "7f1314731d711e2ca5fdc7fd361296593fc2542570b3105595bb0bc6d0fad601"}, "httpoison": {:hex, :httpoison, "2.2.1", "87b7ed6d95db0389f7df02779644171d7319d319178f6680438167d7b69b1f3d", [:mix], [{:hackney, "~> 1.17", [hex: :hackney, repo: "hexpm", optional: false]}], "hexpm", "51364e6d2f429d80e14fe4b5f8e39719cacd03eb3f9a9286e61e216feac2d2df"}, "idna": {:hex, :idna, "6.1.1", "8a63070e9f7d0c62eb9d9fcb360a7de382448200fbbd1b106cc96d3d8099df8d", [:rebar3], [{:unicode_util_compat, "~> 0.7.0", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm", "92376eb7894412ed19ac475e4a86f7b413c1b9fbb5bd16dccd57934157944cea"}, @@ -25,6 +31,10 @@ "mint": {:hex, :mint, "1.6.2", "af6d97a4051eee4f05b5500671d47c3a67dac7386045d87a904126fd4bbcea2e", [:mix], [{:castore, "~> 0.1.0 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: true]}, {:hpax, "~> 0.1.1 or ~> 0.2.0 or ~> 1.0", [hex: :hpax, repo: "hexpm", optional: false]}], "hexpm", "5ee441dffc1892f1ae59127f74afe8fd82fda6587794278d924e4d90ea3d63f9"}, "nimble_options": {:hex, :nimble_options, "1.1.1", "e3a492d54d85fc3fd7c5baf411d9d2852922f66e69476317787a7b2bb000a61b", [:mix], [], "hexpm", "821b2470ca9442c4b6984882fe9bb0389371b8ddec4d45a9504f00a66f650b44"}, "nimble_pool": {:hex, :nimble_pool, "1.1.0", "bf9c29fbdcba3564a8b800d1eeb5a3c58f36e1e11d7b7fb2e084a643f645f06b", [:mix], [], "hexpm", "af2e4e6b34197db81f7aad230c1118eac993acc0dae6bc83bac0126d4ae0813a"}, + "opentelemetry": {:hex, :opentelemetry, "1.4.0", "f928923ed80adb5eb7894bac22e9a198478e6a8f04020ae1d6f289fdcad0b498", [:rebar3], [{:opentelemetry_api, "~> 1.3.0", [hex: :opentelemetry_api, repo: "hexpm", optional: false]}, {:opentelemetry_semantic_conventions, "~> 0.2", [hex: :opentelemetry_semantic_conventions, repo: "hexpm", optional: false]}], "hexpm", "50b32ce127413e5d87b092b4d210a3449ea80cd8224090fe68d73d576a3faa15"}, + "opentelemetry_api": {:hex, :opentelemetry_api, "1.3.1", "83b4713593f80562d9643c4ab0b6f80f3c5fa4c6d0632c43e11b2ccb6b04dfa7", [:mix, :rebar3], [{:opentelemetry_semantic_conventions, "~> 0.2", [hex: :opentelemetry_semantic_conventions, repo: "hexpm", optional: false]}], "hexpm", "9e8a5cc38671e3ac61be48abe5f6b3afdbbb50a1dc08b7950c56f169611505c1"}, + "opentelemetry_exporter": {:hex, :opentelemetry_exporter, "1.7.0", "dec4e90c0667cf11a3642f7fe71982dbc0c6bfbb8725a0b13766830718cf0d98", [:rebar3], [{:grpcbox, ">= 0.0.0", [hex: :grpcbox, repo: "hexpm", optional: false]}, {:opentelemetry, "~> 1.4.0", [hex: :opentelemetry, repo: "hexpm", optional: false]}, {:opentelemetry_api, "~> 1.3.0", [hex: :opentelemetry_api, repo: "hexpm", optional: false]}, {:tls_certificate_check, "~> 1.18", [hex: :tls_certificate_check, repo: "hexpm", optional: false]}], "hexpm", "d0f25f6439ec43f2561537c3fabbe177b38547cddaa3a692cbb8f4770dbefc1e"}, + "opentelemetry_semantic_conventions": {:hex, :opentelemetry_semantic_conventions, "0.2.0", "b67fe459c2938fcab341cb0951c44860c62347c005ace1b50f8402576f241435", [:mix, :rebar3], [], "hexpm", "d61fa1f5639ee8668d74b527e6806e0503efc55a42db7b5f39939d84c07d6895"}, "parse_trans": {:hex, :parse_trans, "3.4.1", "6e6aa8167cb44cc8f39441d05193be6e6f4e7c2946cb2759f015f8c56b76e5ff", [:rebar3], [], "hexpm", "620a406ce75dada827b82e453c19cf06776be266f5a67cff34e1ef2cbb60e49a"}, "phoenix": {:hex, :phoenix, "1.7.14", "a7d0b3f1bc95987044ddada111e77bd7f75646a08518942c72a8440278ae7825", [:mix], [{:castore, ">= 0.0.0", [hex: :castore, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:phoenix_pubsub, "~> 2.1", [hex: :phoenix_pubsub, repo: "hexpm", optional: false]}, {:phoenix_template, "~> 1.0", [hex: :phoenix_template, repo: "hexpm", optional: false]}, {:phoenix_view, "~> 2.0", [hex: :phoenix_view, repo: "hexpm", optional: true]}, {:plug, "~> 1.14", [hex: :plug, repo: "hexpm", optional: false]}, {:plug_cowboy, "~> 2.7", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:plug_crypto, "~> 1.2 or ~> 2.0", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}, {:websock_adapter, "~> 0.5.3", [hex: :websock_adapter, repo: "hexpm", optional: false]}], "hexpm", "c7859bc56cc5dfef19ecfc240775dae358cbaa530231118a9e014df392ace61a"}, "phoenix_ecto": {:hex, :phoenix_ecto, "4.6.2", "3b83b24ab5a2eb071a20372f740d7118767c272db386831b2e77638c4dcc606d", [:mix], [{:ecto, "~> 3.5", [hex: :ecto, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 2.14.2 or ~> 3.0 or ~> 4.1", [hex: :phoenix_html, repo: "hexpm", optional: true]}, {:plug, "~> 1.9", [hex: :plug, repo: "hexpm", optional: false]}, {:postgrex, "~> 0.16 or ~> 1.0", [hex: :postgrex, repo: "hexpm", optional: true]}], "hexpm", "3f94d025f59de86be00f5f8c5dd7b5965a3298458d21ab1c328488be3b5fcd59"}, @@ -43,6 +53,7 @@ "telemetry_metrics": {:hex, :telemetry_metrics, "1.0.0", "29f5f84991ca98b8eb02fc208b2e6de7c95f8bb2294ef244a176675adc7775df", [:mix], [{:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "f23713b3847286a534e005126d4c959ebcca68ae9582118ce436b521d1d47d5d"}, "telemetry_poller": {:hex, :telemetry_poller, "1.1.0", "58fa7c216257291caaf8d05678c8d01bd45f4bdbc1286838a28c4bb62ef32999", [:rebar3], [{:telemetry, "~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "9eb9d9cbfd81cbd7cdd24682f8711b6e2b691289a0de6826e58452f28c103c8f"}, "thousand_island": {:hex, :thousand_island, "1.3.5", "6022b6338f1635b3d32406ff98d68b843ba73b3aa95cfc27154223244f3a6ca5", [:mix], [{:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "2be6954916fdfe4756af3239fb6b6d75d0b8063b5df03ba76fd8a4c87849e180"}, + "tls_certificate_check": {:hex, :tls_certificate_check, "1.24.0", "d00e2887551ff8cdae4d0340d90d9fcbc4943c7b5f49d32ed4bc23aff4db9a44", [:rebar3], [{:ssl_verify_fun, "~> 1.1", [hex: :ssl_verify_fun, repo: "hexpm", optional: false]}], "hexpm", "90b25a58ee433d91c17f036d4d354bf8859a089bfda60e68a86f8eecae45ef1b"}, "unicode_util_compat": {:hex, :unicode_util_compat, "0.7.0", "bc84380c9ab48177092f43ac89e4dfa2c6d62b40b8bd132b1059ecc7232f9a78", [:rebar3], [], "hexpm", "25eee6d67df61960cf6a794239566599b09e17e668d3700247bc498638152521"}, "websock": {:hex, :websock, "0.5.3", "2f69a6ebe810328555b6fe5c831a851f485e303a7c8ce6c5f675abeb20ebdadc", [:mix], [], "hexpm", "6105453d7fac22c712ad66fab1d45abdf049868f253cf719b625151460b8b453"}, "websock_adapter": {:hex, :websock_adapter, "0.5.7", "65fa74042530064ef0570b75b43f5c49bb8b235d6515671b3d250022cb8a1f9e", [:mix], [{:bandit, ">= 0.6.0", [hex: :bandit, repo: "hexpm", optional: true]}, {:plug, "~> 1.14", [hex: :plug, repo: "hexpm", optional: false]}, {:plug_cowboy, "~> 2.6", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:websock, "~> 0.5", [hex: :websock, repo: "hexpm", optional: false]}], "hexpm", "d0f478ee64deddfec64b800673fd6e0c8888b079d9f3444dd96d2a98383bdbd1"}, From f60ebf102c71d3fb27e568dc5a8aaebcea3b3ccf Mon Sep 17 00:00:00 2001 From: JuArce <52429267+JuArce@users.noreply.github.com> Date: Tue, 1 Oct 2024 17:42:06 -0300 Subject: [PATCH 14/55] fix: parse operator id correctly fix: store address and operator_id in lowercase --- .../contract_managers/operator_state_retriever.ex | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/telemetry_api/lib/telemetry_api/contract_managers/operator_state_retriever.ex b/telemetry_api/lib/telemetry_api/contract_managers/operator_state_retriever.ex index a61bbdf6a..2ca144594 100644 --- a/telemetry_api/lib/telemetry_api/contract_managers/operator_state_retriever.ex +++ b/telemetry_api/lib/telemetry_api/contract_managers/operator_state_retriever.ex @@ -38,7 +38,7 @@ defmodule TelemetryApi.ContractManagers.OperatorStateRetriever do def get_contract_address() do @contract_address end - + def get_operators() do with {:ok, block_number} = Ethers.current_block_number(), {:ok, operators_state} = fetch_operators_state(block_number) do @@ -51,11 +51,11 @@ defmodule TelemetryApi.ContractManagers.OperatorStateRetriever do defp parse_operators(operators_state) do operators = operators_state |> Enum.map(fn {address, id, stake} -> - id = id |> String.trim_leading("0x") |> String.upcase() - address = address |> String.trim_leading("0x") |> String.upcase() + id = "0x" <> Base.encode16(id, case: :lower) + address = address |> String.downcase() %{ - id: "0x" <> Base.encode16(id, case: :lower), - address: "0x" <> address, + id: id, + address: address, stake: Integer.to_string(stake) } end) From fca58d2355b853a23aafccdfbdbab83d7bdb4e88 Mon Sep 17 00:00:00 2001 From: Julian Ventura Date: Tue, 1 Oct 2024 17:56:58 -0300 Subject: [PATCH 15/55] Add operators url data update --- core/config/base.go | 4 ++ operator/cmd/actions/start.go | 5 +++ operator/cmd/actions/utils.go | 14 ++++++ telemetry_api/lib/telemetry_api/operators.ex | 31 ++----------- .../lib/telemetry_api/operators/operator.ex | 16 ++++++- telemetry_api/lib/telemetry_api/utils.ex | 43 +++++++++++++++++++ .../controllers/operator_controller.ex | 26 ++++++----- .../controllers/operator_json.ex | 6 ++- .../20240917212329_create_operators.exs | 4 ++ 9 files changed, 110 insertions(+), 39 deletions(-) create mode 100644 operator/cmd/actions/utils.go diff --git a/core/config/base.go b/core/config/base.go index 65f639429..f9b9d2769 100644 --- a/core/config/base.go +++ b/core/config/base.go @@ -27,6 +27,8 @@ type BaseConfig struct { Logger sdklogging.Logger EthRpcUrl string EthWsUrl string + EthRpcUrlFallback string + EthWsUrlFallback string EthRpcClient eth.Client EthRpcClientFallback eth.Client EthWsClient eth.Client @@ -136,6 +138,8 @@ func NewBaseConfig(configFilePath string) *BaseConfig { Logger: logger, EthRpcUrl: baseConfigFromYaml.EthRpcUrl, EthWsUrl: baseConfigFromYaml.EthWsUrl, + EthRpcUrlFallback: baseConfigFromYaml.EthRpcUrlFallback, + EthWsUrlFallback: baseConfigFromYaml.EthWsUrlFallback, EthRpcClient: ethRpcClient, EthRpcClientFallback: ethRpcClientFallback, EthWsClient: ethWsClient, diff --git a/operator/cmd/actions/start.go b/operator/cmd/actions/start.go index a9a169ebc..712ef6dee 100644 --- a/operator/cmd/actions/start.go +++ b/operator/cmd/actions/start.go @@ -55,7 +55,12 @@ func operatorMain(ctx *cli.Context) error { body := map[string]interface{}{ "version": ctx.App.Version, "signature": signature, + "eth_rpc_url": urlRemoveProtocol(operatorConfig.BaseConfig.EthRpcUrl), + "eth_rpc_url_fallback": urlRemoveProtocol(operatorConfig.BaseConfig.EthRpcUrlFallback), + "eth_ws_url": urlRemoveProtocol(operatorConfig.BaseConfig.EthWsUrl), + "eth_ws_url_fallback": urlRemoveProtocol(operatorConfig.BaseConfig.EthWsUrlFallback), } + bodyBuffer := new(bytes.Buffer) bodyReader := json.NewEncoder(bodyBuffer) diff --git a/operator/cmd/actions/utils.go b/operator/cmd/actions/utils.go new file mode 100644 index 000000000..283f90d2b --- /dev/null +++ b/operator/cmd/actions/utils.go @@ -0,0 +1,14 @@ +package actions + +import "strings" + +func urlRemoveProtocol(url string) string { + // Removes the protocol part from any url formated like so: + // "://" + parts := strings.SplitN(url, "://", 2) + if len(parts) > 1 { + return parts[1] + } + + return url +} diff --git a/telemetry_api/lib/telemetry_api/operators.ex b/telemetry_api/lib/telemetry_api/operators.ex index aafc69ed7..d09011db7 100644 --- a/telemetry_api/lib/telemetry_api/operators.ex +++ b/telemetry_api/lib/telemetry_api/operators.ex @@ -97,46 +97,23 @@ defmodule TelemetryApi.Operators do ## Examples - iex> update_operator_version(%{field: value}) + iex> update_operator(%{field: value}) {:ok, %Ecto.Changeset{}} - iex> update_operator_version(%{field: bad_value}) + iex> update_operator(%{field: bad_value}) {:error, string} """ - def update_operator_version(attrs \\ %{}) do + def update_operator(attrs) do with {:ok, address} <- SignatureVerifier.get_address(attrs["version"], attrs["signature"]) do address = "0x" <> address - # We only want to allow changes on version - changes = %{ - version: attrs["version"] - } - case Repo.get(Operator, address) do nil -> {:error, "Provided address does not correspond to any registered operator"} - operator -> operator |> Operator.changeset(changes) |> Repo.insert_or_update() + operator -> operator |> Operator.changeset(attrs) |> Repo.insert_or_update() end end end - @doc """ - Updates a operator. - - ## Examples - - iex> update_operator(operator, %{field: new_value}) - {:ok, %Operator{}} - - iex> update_operator(operator, %{field: bad_value}) - {:error, %Ecto.Changeset{}} - - """ - def update_operator(%Operator{} = operator, attrs) do - operator - |> Operator.changeset(attrs) - |> Repo.update() - end - @doc """ Deletes a operator. diff --git a/telemetry_api/lib/telemetry_api/operators/operator.ex b/telemetry_api/lib/telemetry_api/operators/operator.ex index 6c2892d74..265d2a7bc 100644 --- a/telemetry_api/lib/telemetry_api/operators/operator.ex +++ b/telemetry_api/lib/telemetry_api/operators/operator.ex @@ -8,6 +8,10 @@ defmodule TelemetryApi.Operators.Operator do field :stake, :string field :name, :string field :version, :string + field :eth_rpc_url, :string + field :eth_rpc_url_fallback, :string + field :eth_ws_url, :string + field :eth_ws_url_fallback, :string timestamps(type: :utc_datetime) end @@ -15,7 +19,17 @@ defmodule TelemetryApi.Operators.Operator do @doc false def changeset(operator, attrs) do operator - |> cast(attrs, [:address, :id, :stake, :name, :version]) + |> cast(attrs, [ + :address, + :id, + :stake, + :name, + :version, + :eth_rpc_url, + :eth_rpc_url_fallback, + :eth_ws_url, + :eth_ws_url_fallback + ]) |> validate_required([:address, :id, :name, :stake]) end end diff --git a/telemetry_api/lib/telemetry_api/utils.ex b/telemetry_api/lib/telemetry_api/utils.ex index 5ccb9efab..7c5cd34ca 100644 --- a/telemetry_api/lib/telemetry_api/utils.ex +++ b/telemetry_api/lib/telemetry_api/utils.ex @@ -1,4 +1,6 @@ defmodule TelemetryApi.Utils do + use TelemetryApiWeb, :controller + @moduledoc """ Some utility functions """ @@ -50,4 +52,45 @@ defmodule TelemetryApi.Utils do {:error, error_message} end end + + + @doc """ + Returns json encoded error using http + """ + def return_error(conn, message) do + conn + |> put_status(:bad_request) + |> put_resp_content_type("application/json") + |> send_resp(:bad_request, Jason.encode!(%{error: message})) + end + + @doc """ + Validates the existance of a given list of keys in provided params map. + Extra keys will be filtered out. + + ## Examples + + iex> required_keys = ["hello", "bye"] + iex> params = %{"hello": 4, "bye": 2, "dog": 100} + iex> params_validation(required_keys, params) + {:ok, %{"hello": 4, "bye": 2}} + + iex> required_keys = ["hello", "bye"] + iex> params = %{"hello": 4} + iex> params_validation(required_keys, params) + {:error, string} + """ + def params_validation(required_keys, params) do + # Check if all required keys are present + missing_keys = Enum.filter(required_keys, &(!Map.has_key?(params, &1))) + + if Enum.empty?(missing_keys) do + # Filter the params to only include the required keys + filtered_params = Map.take(params, required_keys) + {:ok, filtered_params} + else + {:error, "Missing required parameters: #{Enum.join(missing_keys, ", ")}"} + end + end + end diff --git a/telemetry_api/lib/telemetry_api_web/controllers/operator_controller.ex b/telemetry_api/lib/telemetry_api_web/controllers/operator_controller.ex index b1b5d4bed..230760631 100644 --- a/telemetry_api/lib/telemetry_api_web/controllers/operator_controller.ex +++ b/telemetry_api/lib/telemetry_api_web/controllers/operator_controller.ex @@ -2,31 +2,37 @@ defmodule TelemetryApiWeb.OperatorController do use TelemetryApiWeb, :controller alias TelemetryApi.Operators + alias TelemetryApi.Utils alias TelemetryApi.Operators.Operator action_fallback TelemetryApiWeb.FallbackController - defp return_error(conn, message) do - conn - |> put_status(:bad_request) - |> put_resp_content_type("application/json") - |> send_resp(:bad_request, Jason.encode!(%{error: message})) - end + @create_params [ + "version", + "signature", + "eth_rpc_url", + "eth_rpc_url_fallback", + "eth_ws_url", + "eth_ws_url_fallback" + ] def index(conn, _params) do operators = Operators.list_operators() render(conn, :index, operators: operators) end - def create(conn, operator_params) do - case Operators.update_operator_version(operator_params) do - {:ok, %Operator{} = operator} -> + def create(conn, params) do + with {:ok, op_params} <- Utils.params_validation(@create_params, params), + {:ok, %Operator{} = operator} <- Operators.update_operator(op_params) do conn |> put_status(:created) |> put_resp_header("location", ~p"/api/operators/#{operator}") |> render(:show, operator: operator) + else {:error, message} -> - return_error(conn, message) + Utils.return_error(conn, message) + _ -> + Utils.return_error(conn, "Unknown error while updating operator") end end diff --git a/telemetry_api/lib/telemetry_api_web/controllers/operator_json.ex b/telemetry_api/lib/telemetry_api_web/controllers/operator_json.ex index f267d1788..cf7f2b28b 100644 --- a/telemetry_api/lib/telemetry_api_web/controllers/operator_json.ex +++ b/telemetry_api/lib/telemetry_api_web/controllers/operator_json.ex @@ -21,7 +21,11 @@ defmodule TelemetryApiWeb.OperatorJSON do id: operator.id, stake: operator.stake, name: operator.name, - version: operator.version + version: operator.version, + eth_rpc_url: operator.eth_rpc_url, + eth_rpc_url_fallback: operator.eth_rpc_url_fallback, + eth_ws_url: operator.eth_ws_url, + eth_ws_url_fallback: operator.eth_ws_url_fallback } end end diff --git a/telemetry_api/priv/repo/migrations/20240917212329_create_operators.exs b/telemetry_api/priv/repo/migrations/20240917212329_create_operators.exs index 80a5e40fe..c57f60a2f 100644 --- a/telemetry_api/priv/repo/migrations/20240917212329_create_operators.exs +++ b/telemetry_api/priv/repo/migrations/20240917212329_create_operators.exs @@ -8,6 +8,10 @@ defmodule TelemetryApi.Repo.Migrations.CreateOperators do add :stake, :string add :name, :string add :version, :string + add :eth_rpc_url, :string + add :eth_rpc_url_fallback, :string + add :eth_ws_url, :string + add :eth_ws_url_fallback, :string timestamps(type: :utc_datetime) end From 57e0776a4d0884cd55f80e9700ccf85c0fc3e07d Mon Sep 17 00:00:00 2001 From: JuArce <52429267+JuArce@users.noreply.github.com> Date: Tue, 1 Oct 2024 18:03:57 -0300 Subject: [PATCH 16/55] fix: encode address to lowercase --- telemetry_api/lib/telemetry_api/signature_verifier.ex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/telemetry_api/lib/telemetry_api/signature_verifier.ex b/telemetry_api/lib/telemetry_api/signature_verifier.ex index ccc0a44d9..8f5eba4ce 100644 --- a/telemetry_api/lib/telemetry_api/signature_verifier.ex +++ b/telemetry_api/lib/telemetry_api/signature_verifier.ex @@ -50,7 +50,7 @@ defmodule SignatureVerifier do with {:ok, address} <- recover_public_key(version_hash, rs, recovery_id) do addr = public_key_to_address(address) - |> Base.encode16() + |> Base.encode16(case: :lower) {:ok, addr} end end From 8da05e6a20d50563a374e4adf93a7fb0869cabc1 Mon Sep 17 00:00:00 2001 From: JuArce <52429267+JuArce@users.noreply.github.com> Date: Tue, 1 Oct 2024 18:05:33 -0300 Subject: [PATCH 17/55] nit --- operator/cmd/actions/start.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/operator/cmd/actions/start.go b/operator/cmd/actions/start.go index a9a169ebc..df7bb8281 100644 --- a/operator/cmd/actions/start.go +++ b/operator/cmd/actions/start.go @@ -65,7 +65,7 @@ func operatorMain(ctx *cli.Context) error { } // send version to operator tracker server - endpoint := operatorConfig.Operator.OperatorTrackerIpPortAddress + "/api/operators" + endpoint := operatorConfig.Operator.OperatorTrackerIpPortAddress + "/versions" operator.Logger.Info("Sending version to operator tracker server: ", "endpoint", endpoint) res, err := http.Post(endpoint, "application/json", From 6b714690b0b160d500305d62246925b76e541cef Mon Sep 17 00:00:00 2001 From: Julian Arce <52429267+JuArce@users.noreply.github.com> Date: Tue, 1 Oct 2024 18:38:49 -0300 Subject: [PATCH 18/55] feat(telemetry): add operators details on OperatorResponse event (#1135) --- telemetry_api/lib/telemetry_api/operators.ex | 18 +++++++++++- telemetry_api/lib/telemetry_api/traces.ex | 30 ++++++++++++-------- 2 files changed, 35 insertions(+), 13 deletions(-) diff --git a/telemetry_api/lib/telemetry_api/operators.ex b/telemetry_api/lib/telemetry_api/operators.ex index aafc69ed7..1a78efe51 100644 --- a/telemetry_api/lib/telemetry_api/operators.ex +++ b/telemetry_api/lib/telemetry_api/operators.ex @@ -39,6 +39,22 @@ defmodule TelemetryApi.Operators do Repo.get(Operator, address) end + @doc""" + Get a single operator by operator id. + + ## Examples + + iex> get_operator_by_id("some_id") + %Operator{} + + iex> get_operator_by_id("non_existent_id") + nil + """ + def get_operator_by_id(id) do + query = from(o in Operator, where: o.id == ^id) + Repo.one(query) + end + @doc """ Fetches all operators. @@ -67,7 +83,7 @@ defmodule TelemetryApi.Operators do end end - + #Adds operator metadata to received operator. ### Examples diff --git a/telemetry_api/lib/telemetry_api/traces.ex b/telemetry_api/lib/telemetry_api/traces.ex index 2f6772178..3d0c6f674 100644 --- a/telemetry_api/lib/telemetry_api/traces.ex +++ b/telemetry_api/lib/telemetry_api/traces.ex @@ -3,6 +3,7 @@ defmodule TelemetryApi.Traces do The Traces context. """ alias TelemetryApi.Traces.Trace + alias TelemetryApi.Operators require OpenTelemetry.Tracer require OpenTelemetry.Ctx @@ -53,20 +54,25 @@ defmodule TelemetryApi.Traces do :ok """ def register_operator_response(merkle_root, operator_id) do - add_event( - merkle_root, - "Operator ID: #{operator_id}", - [ - {:merkle_root, merkle_root}, - {:operator_id, operator_id} - ] - ) + with operator <- Operators.get_operator_by_id(operator_id) do + add_event( + merkle_root, + "Operator Response: " <> operator.name, + [ + {:merkle_root, merkle_root}, + {:operator_id, operator_id}, + {:name, operator.name}, + {:address, operator.address}, + {:stake, operator.stake} + ] + ) - IO.inspect( - "Operator response included. merkle_root: #{IO.inspect(merkle_root)} operator_id: #{IO.inspect(operator_id)}" - ) + IO.inspect( + "Operator response included. merkle_root: #{IO.inspect(merkle_root)} operator_id: #{IO.inspect(operator_id)}" + ) - {:ok, operator_id} + {:ok, operator_id} + end end @doc """ From a659000c9913a4f3004612c6d3ef91dcc630f4a3 Mon Sep 17 00:00:00 2001 From: Julian Ventura Date: Wed, 2 Oct 2024 10:47:34 -0300 Subject: [PATCH 19/55] Add api key filtering from operator url report to telemetry --- operator/cmd/actions/start.go | 61 ++++++++++++++++++++++++----------- operator/cmd/actions/utils.go | 23 +++++++------ 2 files changed, 56 insertions(+), 28 deletions(-) diff --git a/operator/cmd/actions/start.go b/operator/cmd/actions/start.go index 712ef6dee..3ed257995 100644 --- a/operator/cmd/actions/start.go +++ b/operator/cmd/actions/start.go @@ -26,19 +26,8 @@ var StartCommand = &cli.Command{ Action: operatorMain, } -func operatorMain(ctx *cli.Context) error { - operatorConfigFilePath := ctx.String("config") - operatorConfig := config.NewOperatorConfig(operatorConfigFilePath) - err := sdkutils.ReadYamlConfig(operatorConfigFilePath, &operatorConfig) - if err != nil { - return err - } - - operator, err := operator.NewOperatorFromConfig(*operatorConfig) - if err != nil { - return err - } +func updateTelemetryService(operator *operator.Operator, ctx *cli.Context, operatorConfig *config.OperatorConfig) error { // hash version hash := sha3.NewLegacyKeccak256() hash.Write([]byte(ctx.App.Version)) @@ -51,14 +40,30 @@ func operatorMain(ctx *cli.Context) error { if err != nil { return err } + ethRpcUrl, err := baseUrlOnly(operatorConfig.BaseConfig.EthRpcUrl) + if err != nil { + return err + } + ethRpcUrlFallback, err := baseUrlOnly(operatorConfig.BaseConfig.EthRpcUrlFallback) + if err != nil { + return err + } + ethWsUrl, err := baseUrlOnly(operatorConfig.BaseConfig.EthWsUrl) + if err != nil { + return err + } + ethWsUrlFallback, err := baseUrlOnly(operatorConfig.BaseConfig.EthWsUrlFallback) + if err != nil { + return err + } body := map[string]interface{}{ "version": ctx.App.Version, "signature": signature, - "eth_rpc_url": urlRemoveProtocol(operatorConfig.BaseConfig.EthRpcUrl), - "eth_rpc_url_fallback": urlRemoveProtocol(operatorConfig.BaseConfig.EthRpcUrlFallback), - "eth_ws_url": urlRemoveProtocol(operatorConfig.BaseConfig.EthWsUrl), - "eth_ws_url_fallback": urlRemoveProtocol(operatorConfig.BaseConfig.EthWsUrlFallback), + "eth_rpc_url": ethRpcUrl, + "eth_rpc_url_fallback": ethRpcUrlFallback, + "eth_ws_url": ethWsUrl, + "eth_ws_url_fallback": ethWsUrlFallback, } bodyBuffer := new(bytes.Buffer) @@ -73,8 +78,7 @@ func operatorMain(ctx *cli.Context) error { endpoint := operatorConfig.Operator.OperatorTrackerIpPortAddress + "/api/operators" operator.Logger.Info("Sending version to operator tracker server: ", "endpoint", endpoint) - res, err := http.Post(endpoint, "application/json", - bodyBuffer) + res, err := http.Post(endpoint, "application/json", bodyBuffer) if err != nil { // Dont prevent operator from starting if operator tracker server is down operator.Logger.Warn("Error sending version to metrics server: ", "err", err) @@ -82,6 +86,27 @@ func operatorMain(ctx *cli.Context) error { operator.Logger.Warn("Error sending version to operator tracker server: ", "status_code", res.StatusCode) } + return nil +} + +func operatorMain(ctx *cli.Context) error { + operatorConfigFilePath := ctx.String("config") + operatorConfig := config.NewOperatorConfig(operatorConfigFilePath) + err := sdkutils.ReadYamlConfig(operatorConfigFilePath, &operatorConfig) + if err != nil { + return err + } + + operator, err := operator.NewOperatorFromConfig(*operatorConfig) + if err != nil { + return err + } + + err = updateTelemetryService(operator, ctx, operatorConfig) + if err != nil { + return err + } + operator.Logger.Info("Operator starting...") err = operator.Start(context.Background()) if err != nil { diff --git a/operator/cmd/actions/utils.go b/operator/cmd/actions/utils.go index 283f90d2b..ff12645ac 100644 --- a/operator/cmd/actions/utils.go +++ b/operator/cmd/actions/utils.go @@ -1,14 +1,17 @@ package actions -import "strings" +import ( + "regexp" + "errors" +) -func urlRemoveProtocol(url string) string { - // Removes the protocol part from any url formated like so: - // "://" - parts := strings.SplitN(url, "://", 2) - if len(parts) > 1 { - return parts[1] - } - - return url +func baseUrlOnly(url string) (string, error) { + // Removes the protocol and api key part from any url formated like so: + // ":///" + regex := regexp.MustCompile(`^[a-z]+://([^/]+)`) + match := regex.FindStringSubmatch(url) + if len(match) > 1 { + return match[1], nil + } + return "", errors.New("Url did not match the expected format :///") } From b13eab82db561ab40bd9853264619bdc4e461830 Mon Sep 17 00:00:00 2001 From: Julian Ventura Date: Wed, 2 Oct 2024 11:00:09 -0300 Subject: [PATCH 20/55] Create new database migration keeping reverting changes on the last one --- .../migrations/20240917212329_create_operators.exs | 4 ---- .../20241002135112_add_operator_url_data.exs | 12 ++++++++++++ 2 files changed, 12 insertions(+), 4 deletions(-) create mode 100644 telemetry_api/priv/repo/migrations/20241002135112_add_operator_url_data.exs diff --git a/telemetry_api/priv/repo/migrations/20240917212329_create_operators.exs b/telemetry_api/priv/repo/migrations/20240917212329_create_operators.exs index c57f60a2f..80a5e40fe 100644 --- a/telemetry_api/priv/repo/migrations/20240917212329_create_operators.exs +++ b/telemetry_api/priv/repo/migrations/20240917212329_create_operators.exs @@ -8,10 +8,6 @@ defmodule TelemetryApi.Repo.Migrations.CreateOperators do add :stake, :string add :name, :string add :version, :string - add :eth_rpc_url, :string - add :eth_rpc_url_fallback, :string - add :eth_ws_url, :string - add :eth_ws_url_fallback, :string timestamps(type: :utc_datetime) end diff --git a/telemetry_api/priv/repo/migrations/20241002135112_add_operator_url_data.exs b/telemetry_api/priv/repo/migrations/20241002135112_add_operator_url_data.exs new file mode 100644 index 000000000..87010dce6 --- /dev/null +++ b/telemetry_api/priv/repo/migrations/20241002135112_add_operator_url_data.exs @@ -0,0 +1,12 @@ +defmodule TelemetryApi.Repo.Migrations.AddOperatorUrlData do + use Ecto.Migration + + def change do + alter table(:operators) do + add :eth_rpc_url, :string + add :eth_rpc_url_fallback, :string + add :eth_ws_url, :string + add :eth_ws_url_fallback, :string + end + end +end From 4b15e4353001ed2137b336574af051c24bcbf897 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Avila=20Gast=C3=B3n?= <72628438+avilagaston9@users.noreply.github.com> Date: Wed, 2 Oct 2024 15:09:28 -0300 Subject: [PATCH 21/55] feat(telemetry): add event showing missing operators (#1145) --- telemetry_api/lib/telemetry_api/traces.ex | 22 ++++++++++++++++++- .../lib/telemetry_api/traces/trace.ex | 4 ++-- 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/telemetry_api/lib/telemetry_api/traces.ex b/telemetry_api/lib/telemetry_api/traces.ex index 3d0c6f674..cac9a84dd 100644 --- a/telemetry_api/lib/telemetry_api/traces.ex +++ b/telemetry_api/lib/telemetry_api/traces.ex @@ -36,7 +36,8 @@ defmodule TelemetryApi.Traces do TraceStore.store_trace(merkle_root, %Trace{ parent_span: span_ctx, - context: ctx + context: ctx, + responses: [] }) IO.inspect("New task trace with merkle_root: #{IO.inspect(merkle_root)}") @@ -67,6 +68,10 @@ defmodule TelemetryApi.Traces do ] ) + trace = TraceStore.get_trace(merkle_root) + responses = trace.responses ++ [operator_id] + TraceStore.store_trace(merkle_root, %{trace | responses: responses}) + IO.inspect( "Operator response included. merkle_root: #{IO.inspect(merkle_root)} operator_id: #{IO.inspect(operator_id)}" ) @@ -140,6 +145,12 @@ defmodule TelemetryApi.Traces do trace -> Ctx.attach(trace.context) Tracer.set_current_span(trace.parent_span) + + missing_operators = + Operators.list_operators() |> Enum.filter(fn o -> o.id not in trace.responses end) + + add_missing_operators(missing_operators) + Tracer.set_attributes(%{status: "completed"}) Tracer.end_span(trace.parent_span) @@ -151,6 +162,15 @@ defmodule TelemetryApi.Traces do end end + defp add_missing_operators(merkle_root, []), do: :ok + + defp add_missing_operators(merkle_root, missing_operators) do + missing_operators = + missing_operators |> Enum.map(fn o -> o.name end) |> Enum.join(";") + + add_event(merkle_root, "Missing Operators", [{:operators, missing_operators}]) + end + defp add_event(merkle_root, event_name, event_attributes) do case TraceStore.get_trace(merkle_root) do nil -> diff --git a/telemetry_api/lib/telemetry_api/traces/trace.ex b/telemetry_api/lib/telemetry_api/traces/trace.ex index f2e77ef47..ee60f0744 100644 --- a/telemetry_api/lib/telemetry_api/traces/trace.ex +++ b/telemetry_api/lib/telemetry_api/traces/trace.ex @@ -1,4 +1,4 @@ defmodule TelemetryApi.Traces.Trace do - @enforce_keys [:parent_span, :context] - defstruct [:parent_span, :context] + @enforce_keys [:parent_span, :context, :responses] + defstruct [:parent_span, :context, :responses] end From fc00cc554ce6d968a4961c47ea67090e1f5f18d4 Mon Sep 17 00:00:00 2001 From: JuArce <52429267+JuArce@users.noreply.github.com> Date: Wed, 2 Oct 2024 15:30:11 -0300 Subject: [PATCH 22/55] nit --- telemetry_api/lib/telemetry_api/traces.ex | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/telemetry_api/lib/telemetry_api/traces.ex b/telemetry_api/lib/telemetry_api/traces.ex index cac9a84dd..5223d50ac 100644 --- a/telemetry_api/lib/telemetry_api/traces.ex +++ b/telemetry_api/lib/telemetry_api/traces.ex @@ -149,7 +149,7 @@ defmodule TelemetryApi.Traces do missing_operators = Operators.list_operators() |> Enum.filter(fn o -> o.id not in trace.responses end) - add_missing_operators(missing_operators) + add_missing_operators(merkle_root, missing_operators) Tracer.set_attributes(%{status: "completed"}) @@ -162,7 +162,7 @@ defmodule TelemetryApi.Traces do end end - defp add_missing_operators(merkle_root, []), do: :ok + defp add_missing_operators(_merkle_root, []), do: :ok defp add_missing_operators(merkle_root, missing_operators) do missing_operators = From fdc9bc159381845a33b9b8195be554dfe96ec0b9 Mon Sep 17 00:00:00 2001 From: Julian Arce <52429267+JuArce@users.noreply.github.com> Date: Wed, 2 Oct 2024 15:47:46 -0300 Subject: [PATCH 23/55] feat: show quorum percentage on traces (#1143) --- .../contract_managers/stake_registry.ex | 48 ++++++++++++ telemetry_api/lib/telemetry_api/traces.ex | 77 +++++++++++++------ .../lib/telemetry_api/traces/trace.ex | 4 +- .../controllers/fallback_controller.ex | 6 ++ telemetry_api/priv/abi/IStakeRegistry.json | 1 + 5 files changed, 112 insertions(+), 24 deletions(-) create mode 100644 telemetry_api/lib/telemetry_api/contract_managers/stake_registry.ex create mode 100644 telemetry_api/priv/abi/IStakeRegistry.json diff --git a/telemetry_api/lib/telemetry_api/contract_managers/stake_registry.ex b/telemetry_api/lib/telemetry_api/contract_managers/stake_registry.ex new file mode 100644 index 000000000..edf893820 --- /dev/null +++ b/telemetry_api/lib/telemetry_api/contract_managers/stake_registry.ex @@ -0,0 +1,48 @@ +defmodule TelemetryApi.ContractManagers.StakeRegistry do + alias TelemetryApi.ContractManagers.StakeRegistry + + require Logger + + @aligned_config_file System.get_env("ALIGNED_CONFIG_FILE") + + config_file_path = + case @aligned_config_file do + nil -> raise("ALIGNED_CONFIG_FILE not set in .env") + file -> file + end + + {status, config_json_string} = File.read(config_file_path) + + case status do + :ok -> + Logger.debug("Aligned deployment file read successfully") + + :error -> + raise("Config file not read successfully") + end + + @stake_registry_address Jason.decode!(config_json_string) + |> Map.get("addresses") + |> Map.get("stakeRegistry") + + use Ethers.Contract, + abi_file: "priv/abi/IStakeRegistry.json", + default_address: @stake_registry_address + + @doc """ + Get the current total stake + We only use quorum 0 + + ## Examples + + iex> get_current_total_stake() + {:ok, 100} + + iex> get_current_total_stake() + {:error, "Error message"} + """ + def get_current_total_stake() do + StakeRegistry.get_current_total_stake(0) + |> Ethers.call() + end +end diff --git a/telemetry_api/lib/telemetry_api/traces.ex b/telemetry_api/lib/telemetry_api/traces.ex index 5223d50ac..d995949ea 100644 --- a/telemetry_api/lib/telemetry_api/traces.ex +++ b/telemetry_api/lib/telemetry_api/traces.ex @@ -4,6 +4,7 @@ defmodule TelemetryApi.Traces do """ alias TelemetryApi.Traces.Trace alias TelemetryApi.Operators + alias TelemetryApi.ContractManagers.StakeRegistry require OpenTelemetry.Tracer require OpenTelemetry.Ctx @@ -22,26 +23,32 @@ defmodule TelemetryApi.Traces do {:ok, "merkle_root"} """ def create_task_trace(merkle_root) do - span_ctx = - Tracer.start_span( - "Task: #{merkle_root}", - %{ - attributes: [ - {:merkle_root, merkle_root} - ] - } - ) - - ctx = Ctx.get_current() - - TraceStore.store_trace(merkle_root, %Trace{ - parent_span: span_ctx, - context: ctx, - responses: [] - }) - - IO.inspect("New task trace with merkle_root: #{IO.inspect(merkle_root)}") - {:ok, merkle_root} + # Get total stake + with {:ok, total_stake} <- StakeRegistry.get_current_total_stake() do + span_ctx = + Tracer.start_span( + "Task: #{merkle_root}", + %{ + attributes: [ + {:merkle_root, merkle_root}, + {:total_stake, total_stake} + ] + } + ) + + ctx = Ctx.get_current() + + TraceStore.store_trace(merkle_root, %Trace{ + parent_span: span_ctx, + context: ctx, + total_stake: total_stake, + current_stake: 0, + responses: [] + }) + + IO.inspect("New task trace with merkle_root: #{IO.inspect(merkle_root)}") + {:ok, merkle_root} + end end @doc """ @@ -64,8 +71,9 @@ defmodule TelemetryApi.Traces do {:operator_id, operator_id}, {:name, operator.name}, {:address, operator.address}, - {:stake, operator.stake} - ] + {:operator_stake, operator.stake} + ], + String.to_integer(operator.stake) ) trace = TraceStore.get_trace(merkle_root) @@ -171,6 +179,31 @@ defmodule TelemetryApi.Traces do add_event(merkle_root, "Missing Operators", [{:operators, missing_operators}]) end + defp add_event(merkle_root, event_name, event_attributes, operator_stake) do + case TraceStore.get_trace(merkle_root) do + nil -> + IO.inspect("Context not found for #{merkle_root}") + {:error, "Context not found for #{merkle_root}"} + + trace -> + Ctx.attach(trace.context) + Tracer.set_current_span(trace.parent_span) + + new_stake = trace.current_stake + operator_stake + new_stake_fraction = new_stake / trace.total_stake + operator_stake_fraction = operator_stake / trace.total_stake + + TraceStore.store_trace(merkle_root, %Trace{ + parent_span: trace.parent_span, + context: trace.context, + total_stake: trace.total_stake, + current_stake: new_stake + }) + + Tracer.add_event(event_name, event_attributes ++ [{:current_stake, new_stake}, {:current_stake_fraction, new_stake_fraction}, {:operator_stake_fraction, operator_stake_fraction}]) + end + end + defp add_event(merkle_root, event_name, event_attributes) do case TraceStore.get_trace(merkle_root) do nil -> diff --git a/telemetry_api/lib/telemetry_api/traces/trace.ex b/telemetry_api/lib/telemetry_api/traces/trace.ex index ee60f0744..cabad1b41 100644 --- a/telemetry_api/lib/telemetry_api/traces/trace.ex +++ b/telemetry_api/lib/telemetry_api/traces/trace.ex @@ -1,4 +1,4 @@ defmodule TelemetryApi.Traces.Trace do - @enforce_keys [:parent_span, :context, :responses] - defstruct [:parent_span, :context, :responses] + @enforce_keys [:parent_span, :context, :total_stake, :current_stake, :responses] + defstruct [:parent_span, :context, :total_stake, :current_stake, :responses] end diff --git a/telemetry_api/lib/telemetry_api_web/controllers/fallback_controller.ex b/telemetry_api/lib/telemetry_api_web/controllers/fallback_controller.ex index 2b396181f..958b44f97 100644 --- a/telemetry_api/lib/telemetry_api_web/controllers/fallback_controller.ex +++ b/telemetry_api/lib/telemetry_api_web/controllers/fallback_controller.ex @@ -21,4 +21,10 @@ defmodule TelemetryApiWeb.FallbackController do |> put_view(html: TelemetryApiWeb.ErrorHTML, json: TelemetryApiWeb.ErrorJSON) |> render(:"404") end + + def call(conn, {:error, message}) do + conn + |> put_resp_content_type("application/json") + |> send_resp(:internal_server_error, Jason.encode!(%{error: message})) + end end diff --git a/telemetry_api/priv/abi/IStakeRegistry.json b/telemetry_api/priv/abi/IStakeRegistry.json new file mode 100644 index 000000000..da360b509 --- /dev/null +++ b/telemetry_api/priv/abi/IStakeRegistry.json @@ -0,0 +1 @@ +{"abi":[{"type":"function","name":"WEIGHTING_DIVISOR","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"pure"},{"type":"function","name":"addStrategies","inputs":[{"name":"quorumNumber","type":"uint8","internalType":"uint8"},{"name":"strategyParams","type":"tuple[]","internalType":"struct IStakeRegistry.StrategyParams[]","components":[{"name":"strategy","type":"address","internalType":"contract IStrategy"},{"name":"multiplier","type":"uint96","internalType":"uint96"}]}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"delegation","inputs":[],"outputs":[{"name":"","type":"address","internalType":"contract IDelegationManager"}],"stateMutability":"view"},{"type":"function","name":"deregisterOperator","inputs":[{"name":"operatorId","type":"bytes32","internalType":"bytes32"},{"name":"quorumNumbers","type":"bytes","internalType":"bytes"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"getCurrentStake","inputs":[{"name":"operatorId","type":"bytes32","internalType":"bytes32"},{"name":"quorumNumber","type":"uint8","internalType":"uint8"}],"outputs":[{"name":"","type":"uint96","internalType":"uint96"}],"stateMutability":"view"},{"type":"function","name":"getCurrentTotalStake","inputs":[{"name":"quorumNumber","type":"uint8","internalType":"uint8"}],"outputs":[{"name":"","type":"uint96","internalType":"uint96"}],"stateMutability":"view"},{"type":"function","name":"getLatestStakeUpdate","inputs":[{"name":"operatorId","type":"bytes32","internalType":"bytes32"},{"name":"quorumNumber","type":"uint8","internalType":"uint8"}],"outputs":[{"name":"","type":"tuple","internalType":"struct IStakeRegistry.StakeUpdate","components":[{"name":"updateBlockNumber","type":"uint32","internalType":"uint32"},{"name":"nextUpdateBlockNumber","type":"uint32","internalType":"uint32"},{"name":"stake","type":"uint96","internalType":"uint96"}]}],"stateMutability":"view"},{"type":"function","name":"getStakeAtBlockNumber","inputs":[{"name":"operatorId","type":"bytes32","internalType":"bytes32"},{"name":"quorumNumber","type":"uint8","internalType":"uint8"},{"name":"blockNumber","type":"uint32","internalType":"uint32"}],"outputs":[{"name":"","type":"uint96","internalType":"uint96"}],"stateMutability":"view"},{"type":"function","name":"getStakeAtBlockNumberAndIndex","inputs":[{"name":"quorumNumber","type":"uint8","internalType":"uint8"},{"name":"blockNumber","type":"uint32","internalType":"uint32"},{"name":"operatorId","type":"bytes32","internalType":"bytes32"},{"name":"index","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"uint96","internalType":"uint96"}],"stateMutability":"view"},{"type":"function","name":"getStakeHistory","inputs":[{"name":"operatorId","type":"bytes32","internalType":"bytes32"},{"name":"quorumNumber","type":"uint8","internalType":"uint8"}],"outputs":[{"name":"","type":"tuple[]","internalType":"struct IStakeRegistry.StakeUpdate[]","components":[{"name":"updateBlockNumber","type":"uint32","internalType":"uint32"},{"name":"nextUpdateBlockNumber","type":"uint32","internalType":"uint32"},{"name":"stake","type":"uint96","internalType":"uint96"}]}],"stateMutability":"view"},{"type":"function","name":"getStakeUpdateAtIndex","inputs":[{"name":"quorumNumber","type":"uint8","internalType":"uint8"},{"name":"operatorId","type":"bytes32","internalType":"bytes32"},{"name":"index","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"tuple","internalType":"struct IStakeRegistry.StakeUpdate","components":[{"name":"updateBlockNumber","type":"uint32","internalType":"uint32"},{"name":"nextUpdateBlockNumber","type":"uint32","internalType":"uint32"},{"name":"stake","type":"uint96","internalType":"uint96"}]}],"stateMutability":"view"},{"type":"function","name":"getStakeUpdateIndexAtBlockNumber","inputs":[{"name":"operatorId","type":"bytes32","internalType":"bytes32"},{"name":"quorumNumber","type":"uint8","internalType":"uint8"},{"name":"blockNumber","type":"uint32","internalType":"uint32"}],"outputs":[{"name":"","type":"uint32","internalType":"uint32"}],"stateMutability":"view"},{"type":"function","name":"getTotalStakeAtBlockNumberFromIndex","inputs":[{"name":"quorumNumber","type":"uint8","internalType":"uint8"},{"name":"blockNumber","type":"uint32","internalType":"uint32"},{"name":"index","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"uint96","internalType":"uint96"}],"stateMutability":"view"},{"type":"function","name":"getTotalStakeHistoryLength","inputs":[{"name":"quorumNumber","type":"uint8","internalType":"uint8"}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"getTotalStakeIndicesAtBlockNumber","inputs":[{"name":"blockNumber","type":"uint32","internalType":"uint32"},{"name":"quorumNumbers","type":"bytes","internalType":"bytes"}],"outputs":[{"name":"","type":"uint32[]","internalType":"uint32[]"}],"stateMutability":"view"},{"type":"function","name":"getTotalStakeUpdateAtIndex","inputs":[{"name":"quorumNumber","type":"uint8","internalType":"uint8"},{"name":"index","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"tuple","internalType":"struct IStakeRegistry.StakeUpdate","components":[{"name":"updateBlockNumber","type":"uint32","internalType":"uint32"},{"name":"nextUpdateBlockNumber","type":"uint32","internalType":"uint32"},{"name":"stake","type":"uint96","internalType":"uint96"}]}],"stateMutability":"view"},{"type":"function","name":"initializeQuorum","inputs":[{"name":"quorumNumber","type":"uint8","internalType":"uint8"},{"name":"minimumStake","type":"uint96","internalType":"uint96"},{"name":"strategyParams","type":"tuple[]","internalType":"struct IStakeRegistry.StrategyParams[]","components":[{"name":"strategy","type":"address","internalType":"contract IStrategy"},{"name":"multiplier","type":"uint96","internalType":"uint96"}]}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"minimumStakeForQuorum","inputs":[{"name":"quorumNumber","type":"uint8","internalType":"uint8"}],"outputs":[{"name":"","type":"uint96","internalType":"uint96"}],"stateMutability":"view"},{"type":"function","name":"modifyStrategyParams","inputs":[{"name":"quorumNumber","type":"uint8","internalType":"uint8"},{"name":"strategyIndices","type":"uint256[]","internalType":"uint256[]"},{"name":"newMultipliers","type":"uint96[]","internalType":"uint96[]"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"registerOperator","inputs":[{"name":"operator","type":"address","internalType":"address"},{"name":"operatorId","type":"bytes32","internalType":"bytes32"},{"name":"quorumNumbers","type":"bytes","internalType":"bytes"}],"outputs":[{"name":"","type":"uint96[]","internalType":"uint96[]"},{"name":"","type":"uint96[]","internalType":"uint96[]"}],"stateMutability":"nonpayable"},{"type":"function","name":"registryCoordinator","inputs":[],"outputs":[{"name":"","type":"address","internalType":"address"}],"stateMutability":"view"},{"type":"function","name":"removeStrategies","inputs":[{"name":"quorumNumber","type":"uint8","internalType":"uint8"},{"name":"indicesToRemove","type":"uint256[]","internalType":"uint256[]"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"strategyParamsByIndex","inputs":[{"name":"quorumNumber","type":"uint8","internalType":"uint8"},{"name":"index","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"tuple","internalType":"struct IStakeRegistry.StrategyParams","components":[{"name":"strategy","type":"address","internalType":"contract IStrategy"},{"name":"multiplier","type":"uint96","internalType":"uint96"}]}],"stateMutability":"view"},{"type":"function","name":"strategyParamsLength","inputs":[{"name":"quorumNumber","type":"uint8","internalType":"uint8"}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"updateOperatorStake","inputs":[{"name":"operator","type":"address","internalType":"address"},{"name":"operatorId","type":"bytes32","internalType":"bytes32"},{"name":"quorumNumbers","type":"bytes","internalType":"bytes"}],"outputs":[{"name":"","type":"uint192","internalType":"uint192"}],"stateMutability":"nonpayable"},{"type":"function","name":"weightOfOperatorForQuorum","inputs":[{"name":"quorumNumber","type":"uint8","internalType":"uint8"},{"name":"operator","type":"address","internalType":"address"}],"outputs":[{"name":"","type":"uint96","internalType":"uint96"}],"stateMutability":"view"},{"type":"event","name":"MinimumStakeForQuorumUpdated","inputs":[{"name":"quorumNumber","type":"uint8","indexed":true,"internalType":"uint8"},{"name":"minimumStake","type":"uint96","indexed":false,"internalType":"uint96"}],"anonymous":false},{"type":"event","name":"OperatorStakeUpdate","inputs":[{"name":"operatorId","type":"bytes32","indexed":true,"internalType":"bytes32"},{"name":"quorumNumber","type":"uint8","indexed":false,"internalType":"uint8"},{"name":"stake","type":"uint96","indexed":false,"internalType":"uint96"}],"anonymous":false},{"type":"event","name":"QuorumCreated","inputs":[{"name":"quorumNumber","type":"uint8","indexed":true,"internalType":"uint8"}],"anonymous":false},{"type":"event","name":"StrategyAddedToQuorum","inputs":[{"name":"quorumNumber","type":"uint8","indexed":true,"internalType":"uint8"},{"name":"strategy","type":"address","indexed":false,"internalType":"contract IStrategy"}],"anonymous":false},{"type":"event","name":"StrategyMultiplierUpdated","inputs":[{"name":"quorumNumber","type":"uint8","indexed":true,"internalType":"uint8"},{"name":"strategy","type":"address","indexed":false,"internalType":"contract IStrategy"},{"name":"multiplier","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"StrategyRemovedFromQuorum","inputs":[{"name":"quorumNumber","type":"uint8","indexed":true,"internalType":"uint8"},{"name":"strategy","type":"address","indexed":false,"internalType":"contract IStrategy"}],"anonymous":false}],"bytecode":{"object":"0x","sourceMap":"","linkReferences":{}},"deployedBytecode":{"object":"0x","sourceMap":"","linkReferences":{}},"methodIdentifiers":{"WEIGHTING_DIVISOR()":"5e5a6775","addStrategies(uint8,(address,uint96)[])":"c601527d","delegation()":"df5cf723","deregisterOperator(bytes32,bytes)":"bd29b8cd","getCurrentStake(bytes32,uint8)":"5401ed27","getCurrentTotalStake(uint8)":"d5eccc05","getLatestStakeUpdate(bytes32,uint8)":"f851e198","getStakeAtBlockNumber(bytes32,uint8,uint32)":"fa28c627","getStakeAtBlockNumberAndIndex(uint8,uint32,bytes32,uint256)":"f2be94ae","getStakeHistory(bytes32,uint8)":"2cd95940","getStakeUpdateAtIndex(uint8,bytes32,uint256)":"ac6bfb03","getStakeUpdateIndexAtBlockNumber(bytes32,uint8,uint32)":"dd9846b9","getTotalStakeAtBlockNumberFromIndex(uint8,uint32,uint256)":"c8294c56","getTotalStakeHistoryLength(uint8)":"0491b41c","getTotalStakeIndicesAtBlockNumber(uint32,bytes)":"81c07502","getTotalStakeUpdateAtIndex(uint8,uint256)":"b6904b78","initializeQuorum(uint8,uint96,(address,uint96)[])":"ff694a77","minimumStakeForQuorum(uint8)":"c46778a5","modifyStrategyParams(uint8,uint256[],uint96[])":"20b66298","registerOperator(address,bytes32,bytes)":"25504777","registryCoordinator()":"6d14a987","removeStrategies(uint8,uint256[])":"5f1f2d77","strategyParamsByIndex(uint8,uint256)":"adc804da","strategyParamsLength(uint8)":"3ca5a5f5","updateOperatorStake(address,bytes32,bytes)":"66acfefe","weightOfOperatorForQuorum(uint8,address)":"1f9b74e0"},"rawMetadata":"{\"compiler\":{\"version\":\"0.8.24+commit.e11b9ed9\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint8\",\"name\":\"quorumNumber\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"uint96\",\"name\":\"minimumStake\",\"type\":\"uint96\"}],\"name\":\"MinimumStakeForQuorumUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"operatorId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"quorumNumber\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"uint96\",\"name\":\"stake\",\"type\":\"uint96\"}],\"name\":\"OperatorStakeUpdate\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint8\",\"name\":\"quorumNumber\",\"type\":\"uint8\"}],\"name\":\"QuorumCreated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint8\",\"name\":\"quorumNumber\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"contract IStrategy\",\"name\":\"strategy\",\"type\":\"address\"}],\"name\":\"StrategyAddedToQuorum\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint8\",\"name\":\"quorumNumber\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"contract IStrategy\",\"name\":\"strategy\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"multiplier\",\"type\":\"uint256\"}],\"name\":\"StrategyMultiplierUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint8\",\"name\":\"quorumNumber\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"contract IStrategy\",\"name\":\"strategy\",\"type\":\"address\"}],\"name\":\"StrategyRemovedFromQuorum\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"WEIGHTING_DIVISOR\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"quorumNumber\",\"type\":\"uint8\"},{\"components\":[{\"internalType\":\"contract IStrategy\",\"name\":\"strategy\",\"type\":\"address\"},{\"internalType\":\"uint96\",\"name\":\"multiplier\",\"type\":\"uint96\"}],\"internalType\":\"struct IStakeRegistry.StrategyParams[]\",\"name\":\"strategyParams\",\"type\":\"tuple[]\"}],\"name\":\"addStrategies\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"delegation\",\"outputs\":[{\"internalType\":\"contract IDelegationManager\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"operatorId\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"quorumNumbers\",\"type\":\"bytes\"}],\"name\":\"deregisterOperator\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"operatorId\",\"type\":\"bytes32\"},{\"internalType\":\"uint8\",\"name\":\"quorumNumber\",\"type\":\"uint8\"}],\"name\":\"getCurrentStake\",\"outputs\":[{\"internalType\":\"uint96\",\"name\":\"\",\"type\":\"uint96\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"quorumNumber\",\"type\":\"uint8\"}],\"name\":\"getCurrentTotalStake\",\"outputs\":[{\"internalType\":\"uint96\",\"name\":\"\",\"type\":\"uint96\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"operatorId\",\"type\":\"bytes32\"},{\"internalType\":\"uint8\",\"name\":\"quorumNumber\",\"type\":\"uint8\"}],\"name\":\"getLatestStakeUpdate\",\"outputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"updateBlockNumber\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"nextUpdateBlockNumber\",\"type\":\"uint32\"},{\"internalType\":\"uint96\",\"name\":\"stake\",\"type\":\"uint96\"}],\"internalType\":\"struct IStakeRegistry.StakeUpdate\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"operatorId\",\"type\":\"bytes32\"},{\"internalType\":\"uint8\",\"name\":\"quorumNumber\",\"type\":\"uint8\"},{\"internalType\":\"uint32\",\"name\":\"blockNumber\",\"type\":\"uint32\"}],\"name\":\"getStakeAtBlockNumber\",\"outputs\":[{\"internalType\":\"uint96\",\"name\":\"\",\"type\":\"uint96\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"quorumNumber\",\"type\":\"uint8\"},{\"internalType\":\"uint32\",\"name\":\"blockNumber\",\"type\":\"uint32\"},{\"internalType\":\"bytes32\",\"name\":\"operatorId\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"index\",\"type\":\"uint256\"}],\"name\":\"getStakeAtBlockNumberAndIndex\",\"outputs\":[{\"internalType\":\"uint96\",\"name\":\"\",\"type\":\"uint96\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"operatorId\",\"type\":\"bytes32\"},{\"internalType\":\"uint8\",\"name\":\"quorumNumber\",\"type\":\"uint8\"}],\"name\":\"getStakeHistory\",\"outputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"updateBlockNumber\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"nextUpdateBlockNumber\",\"type\":\"uint32\"},{\"internalType\":\"uint96\",\"name\":\"stake\",\"type\":\"uint96\"}],\"internalType\":\"struct IStakeRegistry.StakeUpdate[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"quorumNumber\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"operatorId\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"index\",\"type\":\"uint256\"}],\"name\":\"getStakeUpdateAtIndex\",\"outputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"updateBlockNumber\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"nextUpdateBlockNumber\",\"type\":\"uint32\"},{\"internalType\":\"uint96\",\"name\":\"stake\",\"type\":\"uint96\"}],\"internalType\":\"struct IStakeRegistry.StakeUpdate\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"operatorId\",\"type\":\"bytes32\"},{\"internalType\":\"uint8\",\"name\":\"quorumNumber\",\"type\":\"uint8\"},{\"internalType\":\"uint32\",\"name\":\"blockNumber\",\"type\":\"uint32\"}],\"name\":\"getStakeUpdateIndexAtBlockNumber\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"quorumNumber\",\"type\":\"uint8\"},{\"internalType\":\"uint32\",\"name\":\"blockNumber\",\"type\":\"uint32\"},{\"internalType\":\"uint256\",\"name\":\"index\",\"type\":\"uint256\"}],\"name\":\"getTotalStakeAtBlockNumberFromIndex\",\"outputs\":[{\"internalType\":\"uint96\",\"name\":\"\",\"type\":\"uint96\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"quorumNumber\",\"type\":\"uint8\"}],\"name\":\"getTotalStakeHistoryLength\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"blockNumber\",\"type\":\"uint32\"},{\"internalType\":\"bytes\",\"name\":\"quorumNumbers\",\"type\":\"bytes\"}],\"name\":\"getTotalStakeIndicesAtBlockNumber\",\"outputs\":[{\"internalType\":\"uint32[]\",\"name\":\"\",\"type\":\"uint32[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"quorumNumber\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"index\",\"type\":\"uint256\"}],\"name\":\"getTotalStakeUpdateAtIndex\",\"outputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"updateBlockNumber\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"nextUpdateBlockNumber\",\"type\":\"uint32\"},{\"internalType\":\"uint96\",\"name\":\"stake\",\"type\":\"uint96\"}],\"internalType\":\"struct IStakeRegistry.StakeUpdate\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"quorumNumber\",\"type\":\"uint8\"},{\"internalType\":\"uint96\",\"name\":\"minimumStake\",\"type\":\"uint96\"},{\"components\":[{\"internalType\":\"contract IStrategy\",\"name\":\"strategy\",\"type\":\"address\"},{\"internalType\":\"uint96\",\"name\":\"multiplier\",\"type\":\"uint96\"}],\"internalType\":\"struct IStakeRegistry.StrategyParams[]\",\"name\":\"strategyParams\",\"type\":\"tuple[]\"}],\"name\":\"initializeQuorum\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"quorumNumber\",\"type\":\"uint8\"}],\"name\":\"minimumStakeForQuorum\",\"outputs\":[{\"internalType\":\"uint96\",\"name\":\"\",\"type\":\"uint96\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"quorumNumber\",\"type\":\"uint8\"},{\"internalType\":\"uint256[]\",\"name\":\"strategyIndices\",\"type\":\"uint256[]\"},{\"internalType\":\"uint96[]\",\"name\":\"newMultipliers\",\"type\":\"uint96[]\"}],\"name\":\"modifyStrategyParams\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"operatorId\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"quorumNumbers\",\"type\":\"bytes\"}],\"name\":\"registerOperator\",\"outputs\":[{\"internalType\":\"uint96[]\",\"name\":\"\",\"type\":\"uint96[]\"},{\"internalType\":\"uint96[]\",\"name\":\"\",\"type\":\"uint96[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"registryCoordinator\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"quorumNumber\",\"type\":\"uint8\"},{\"internalType\":\"uint256[]\",\"name\":\"indicesToRemove\",\"type\":\"uint256[]\"}],\"name\":\"removeStrategies\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"quorumNumber\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"index\",\"type\":\"uint256\"}],\"name\":\"strategyParamsByIndex\",\"outputs\":[{\"components\":[{\"internalType\":\"contract IStrategy\",\"name\":\"strategy\",\"type\":\"address\"},{\"internalType\":\"uint96\",\"name\":\"multiplier\",\"type\":\"uint96\"}],\"internalType\":\"struct IStakeRegistry.StrategyParams\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"quorumNumber\",\"type\":\"uint8\"}],\"name\":\"strategyParamsLength\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"operatorId\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"quorumNumbers\",\"type\":\"bytes\"}],\"name\":\"updateOperatorStake\",\"outputs\":[{\"internalType\":\"uint192\",\"name\":\"\",\"type\":\"uint192\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"quorumNumber\",\"type\":\"uint8\"},{\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"}],\"name\":\"weightOfOperatorForQuorum\",\"outputs\":[{\"internalType\":\"uint96\",\"name\":\"\",\"type\":\"uint96\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"author\":\"Layr Labs, Inc.\",\"kind\":\"dev\",\"methods\":{\"deregisterOperator(bytes32,bytes)\":{\"details\":\"access restricted to the RegistryCoordinatorPreconditions (these are assumed, not validated in this contract): 1) `quorumNumbers` has no duplicates 2) `quorumNumbers.length` != 0 3) `quorumNumbers` is ordered in ascending order 4) the operator is not already deregistered 5) `quorumNumbers` is a subset of the quorumNumbers that the operator is registered for\",\"params\":{\"operatorId\":\"The id of the operator to deregister.\",\"quorumNumbers\":\"The quorum numbers the operator is deregistering from, where each byte is an 8 bit integer quorumNumber.\"}},\"getCurrentStake(bytes32,uint8)\":{\"details\":\"Function returns weight of **0** in the event that the operator has no stake history\"},\"getCurrentTotalStake(uint8)\":{\"details\":\"Will revert if `_totalStakeHistory[quorumNumber]` is empty.\"},\"getLatestStakeUpdate(bytes32,uint8)\":{\"details\":\"Function returns an StakeUpdate struct with **every entry equal to 0** in the event that the operator has no stake history\"},\"getStakeAtBlockNumberAndIndex(uint8,uint32,bytes32,uint256)\":{\"details\":\"Function will revert if `index` is out-of-bounds.used the BLSSignatureChecker to get past stakes of signing operators\",\"params\":{\"blockNumber\":\"Block number to make sure the stake is from.\",\"index\":\"Array index for lookup, within the dynamic array `operatorIdToStakeHistory[operatorId][quorumNumber]`.\",\"operatorId\":\"The id of the operator of interest.\",\"quorumNumber\":\"The quorum number to get the stake for.\"}},\"getStakeHistory(bytes32,uint8)\":{\"params\":{\"operatorId\":\"The id of the operator of interest.\",\"quorumNumber\":\"The quorum number to get the stake for.\"}},\"getStakeUpdateAtIndex(uint8,bytes32,uint256)\":{\"details\":\"Function will revert if `index` is out-of-bounds.\",\"params\":{\"index\":\"Array index for lookup, within the dynamic array `operatorIdToStakeHistory[operatorId][quorumNumber]`.\",\"operatorId\":\"The id of the operator of interest.\",\"quorumNumber\":\"The quorum number to get the stake for.\"}},\"getTotalStakeAtBlockNumberFromIndex(uint8,uint32,uint256)\":{\"details\":\"Function will revert if `index` is out-of-bounds.used the BLSSignatureChecker to get past stakes of signing operators\",\"params\":{\"blockNumber\":\"Block number to make sure the stake is from.\",\"index\":\"Array index for lookup, within the dynamic array `totalStakeHistory[quorumNumber]`.\",\"quorumNumber\":\"The quorum number to get the stake for.\"}},\"getTotalStakeUpdateAtIndex(uint8,uint256)\":{\"params\":{\"index\":\"Array index for lookup, within the dynamic array `totalStakeHistory[quorumNumber]`.\",\"quorumNumber\":\"The quorum number to get the stake for.\"}},\"modifyStrategyParams(uint8,uint256[],uint96[])\":{\"params\":{\"newMultipliers\":\"are the new multipliers for the strategies\",\"quorumNumber\":\"is the quorum number to change the strategy for\",\"strategyIndices\":\"are the indices of the strategies to change\"}},\"registerOperator(address,bytes32,bytes)\":{\"details\":\"access restricted to the RegistryCoordinatorPreconditions (these are assumed, not validated in this contract): 1) `quorumNumbers` has no duplicates 2) `quorumNumbers.length` != 0 3) `quorumNumbers` is ordered in ascending order 4) the operator is not already registered\",\"params\":{\"operator\":\"The address of the operator to register.\",\"operatorId\":\"The id of the operator to register.\",\"quorumNumbers\":\"The quorum numbers the operator is registering for, where each byte is an 8 bit integer quorumNumber.\"},\"returns\":{\"_0\":\"The operator's current stake for each quorum, and the total stake for each quorum\"}},\"removeStrategies(uint8,uint256[])\":{\"details\":\"higher indices should be *first* in the list of @param indicesToRemove, since otherwise the removal of lower index entries will cause a shift in the indices of the other strategiesToRemove\",\"params\":{\"quorumNumber\":\".\"}},\"updateOperatorStake(address,bytes32,bytes)\":{\"returns\":{\"_0\":\"A bitmap of quorums where the operator no longer meets the minimum stake and should be deregistered.\"}},\"weightOfOperatorForQuorum(uint8,address)\":{\"details\":\"reverts in the case that `quorumNumber` is greater than or equal to `quorumCount`\"}},\"title\":\"Interface for a `Registry` that keeps track of stakes of operators for up to 256 quorums.\",\"version\":1},\"userdoc\":{\"events\":{\"MinimumStakeForQuorumUpdated(uint8,uint96)\":{\"notice\":\"emitted when the minimum stake for a quorum is updated\"},\"OperatorStakeUpdate(bytes32,uint8,uint96)\":{\"notice\":\"emitted whenever the stake of `operator` is updated\"},\"QuorumCreated(uint8)\":{\"notice\":\"emitted when a new quorum is created\"},\"StrategyAddedToQuorum(uint8,address)\":{\"notice\":\"emitted when `strategy` has been added to the array at `strategyParams[quorumNumber]`\"},\"StrategyMultiplierUpdated(uint8,address,uint256)\":{\"notice\":\"emitted when `strategy` has its `multiplier` updated in the array at `strategyParams[quorumNumber]`\"},\"StrategyRemovedFromQuorum(uint8,address)\":{\"notice\":\"emitted when `strategy` has removed from the array at `strategyParams[quorumNumber]`\"}},\"kind\":\"user\",\"methods\":{\"WEIGHTING_DIVISOR()\":{\"notice\":\"Constant used as a divisor in calculating weights.\"},\"addStrategies(uint8,(address,uint96)[])\":{\"notice\":\"Adds new strategies and the associated multipliers to the @param quorumNumber.\"},\"delegation()\":{\"notice\":\"Returns the EigenLayer delegation manager contract.\"},\"deregisterOperator(bytes32,bytes)\":{\"notice\":\"Deregisters the operator with `operatorId` for the specified `quorumNumbers`.\"},\"getCurrentStake(bytes32,uint8)\":{\"notice\":\"Returns the most recent stake weight for the `operatorId` for quorum `quorumNumber`\"},\"getCurrentTotalStake(uint8)\":{\"notice\":\"Returns the stake weight from the latest entry in `_totalStakeHistory` for quorum `quorumNumber`.\"},\"getLatestStakeUpdate(bytes32,uint8)\":{\"notice\":\"Returns the most recent stake weight for the `operatorId` for a certain quorum\"},\"getStakeAtBlockNumber(bytes32,uint8,uint32)\":{\"notice\":\"Returns the stake of the operator for the provided `quorumNumber` at the given `blockNumber`\"},\"getStakeAtBlockNumberAndIndex(uint8,uint32,bytes32,uint256)\":{\"notice\":\"Returns the stake weight corresponding to `operatorId` for quorum `quorumNumber`, at the `index`-th entry in the `operatorIdToStakeHistory[operatorId][quorumNumber]` array if the entry corresponds to the operator's stake at `blockNumber`. Reverts otherwise.\"},\"getStakeHistory(bytes32,uint8)\":{\"notice\":\"Returns the entire `operatorIdToStakeHistory[operatorId][quorumNumber]` array.\"},\"getStakeUpdateAtIndex(uint8,bytes32,uint256)\":{\"notice\":\"Returns the `index`-th entry in the `operatorIdToStakeHistory[operatorId][quorumNumber]` array.\"},\"getStakeUpdateIndexAtBlockNumber(bytes32,uint8,uint32)\":{\"notice\":\"Returns the indices of the operator stakes for the provided `quorumNumber` at the given `blockNumber`\"},\"getTotalStakeAtBlockNumberFromIndex(uint8,uint32,uint256)\":{\"notice\":\"Returns the total stake weight for quorum `quorumNumber`, at the `index`-th entry in the `totalStakeHistory[quorumNumber]` array if the entry corresponds to the total stake at `blockNumber`. Reverts otherwise.\"},\"getTotalStakeIndicesAtBlockNumber(uint32,bytes)\":{\"notice\":\"Returns the indices of the total stakes for the provided `quorumNumbers` at the given `blockNumber`\"},\"getTotalStakeUpdateAtIndex(uint8,uint256)\":{\"notice\":\"Returns the `index`-th entry in the dynamic array of total stake, `totalStakeHistory` for quorum `quorumNumber`.\"},\"initializeQuorum(uint8,uint96,(address,uint96)[])\":{\"notice\":\"Initialize a new quorum created by the registry coordinator by setting strategies, weights, and minimum stake\"},\"minimumStakeForQuorum(uint8)\":{\"notice\":\"In order to register for a quorum i, an operator must have at least `minimumStakeForQuorum[i]`\"},\"modifyStrategyParams(uint8,uint256[],uint96[])\":{\"notice\":\"This function is used for modifying the weights of strategies that are already in the mapping strategyParams for a specific\"},\"registerOperator(address,bytes32,bytes)\":{\"notice\":\"Registers the `operator` with `operatorId` for the specified `quorumNumbers`.\"},\"removeStrategies(uint8,uint256[])\":{\"notice\":\"This function is used for removing strategies and their associated weights from the\"},\"strategyParamsByIndex(uint8,uint256)\":{\"notice\":\"Returns the strategy and weight multiplier for the `index`'th strategy in the quorum `quorumNumber`\"},\"strategyParamsLength(uint8)\":{\"notice\":\"Returns the length of the dynamic array stored in `strategyParams[quorumNumber]`.\"},\"updateOperatorStake(address,bytes32,bytes)\":{\"notice\":\"Called by the registry coordinator to update an operator's stake for one or more quorums. If the operator no longer has the minimum stake required for a quorum, they are added to the\"},\"weightOfOperatorForQuorum(uint8,address)\":{\"notice\":\"This function computes the total weight of the @param operator in the quorum @param quorumNumber.\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"lib/eigenlayer-middleware/src/interfaces/IStakeRegistry.sol\":\"IStakeRegistry\"},\"evmVersion\":\"paris\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[\":@openzeppelin-upgrades-v4.9.0/=lib/eigenlayer-middleware/lib/eigenlayer-contracts/lib/openzeppelin-contracts-upgradeable-v4.9.0/\",\":@openzeppelin-upgrades/contracts/=lib/eigenlayer-middleware/lib/openzeppelin-contracts-upgradeable/contracts/\",\":@openzeppelin-v4.9.0/=lib/eigenlayer-middleware/lib/eigenlayer-contracts/lib/openzeppelin-contracts-v4.9.0/\",\":@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/\",\":@openzeppelin/contracts/=lib/eigenlayer-middleware/lib/openzeppelin-contracts/contracts/\",\":ds-test/=lib/eigenlayer-middleware/lib/ds-test/src/\",\":eigenlayer-contracts/=lib/eigenlayer-middleware/lib/eigenlayer-contracts/\",\":eigenlayer-core-contracts/=lib/eigenlayer-middleware/lib/eigenlayer-contracts/src/contracts/core/\",\":eigenlayer-core/=lib/eigenlayer-middleware/lib/eigenlayer-contracts/src/\",\":eigenlayer-middleware/=lib/eigenlayer-middleware/src/\",\":eigenlayer-scripts/=lib/eigenlayer-middleware/lib/eigenlayer-contracts/script/\",\":erc4626-tests/=lib/openzeppelin-contracts-upgradeable/lib/erc4626-tests/\",\":forge-std/=lib/forge-std/src/\",\":openzeppelin-contracts-upgradeable-v4.9.0/=lib/eigenlayer-middleware/lib/eigenlayer-contracts/lib/openzeppelin-contracts-upgradeable-v4.9.0/\",\":openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/\",\":openzeppelin-contracts-v4.9.0/=lib/eigenlayer-middleware/lib/eigenlayer-contracts/lib/openzeppelin-contracts-v4.9.0/\",\":openzeppelin-contracts/=lib/openzeppelin-contracts/\",\":openzeppelin/=lib/eigenlayer-middleware/lib/eigenlayer-contracts/lib/openzeppelin-contracts-upgradeable-v4.9.0/contracts/\"]},\"sources\":{\"lib/eigenlayer-middleware/lib/eigenlayer-contracts/src/contracts/interfaces/IBeaconChainOracle.sol\":{\"keccak256\":\"0x0fef07aa6179c77198f1514e12e628aa1c876e04f9c181ec853a322179e5be00\",\"license\":\"BUSL-1.1\",\"urls\":[\"bzz-raw://51438325876cc2d4c77f58488a7e27b488015d1b663c50be6a5cafbd73b9c983\",\"dweb:/ipfs/QmViCuGoYZzi6wtXA8PPKigqVv3KMuNxEVQ1Td9dGqjL18\"]},\"lib/eigenlayer-middleware/lib/eigenlayer-contracts/src/contracts/interfaces/IDelegationManager.sol\":{\"keccak256\":\"0xab76a9f4eff865cbb689f627cf98263488765519d7a4ec5ffbcb0ca4972842f9\",\"license\":\"BUSL-1.1\",\"urls\":[\"bzz-raw://ff57ce18e8350bf39f190645db0988bc0f1279f1872150a114a1b520c38a2914\",\"dweb:/ipfs/QmSsUXkNUqYuJgGRumHTSs9rAaboGjecotcM4xHrdBYWaZ\"]},\"lib/eigenlayer-middleware/lib/eigenlayer-contracts/src/contracts/interfaces/IETHPOSDeposit.sol\":{\"keccak256\":\"0x2e60e5f4b0da0a0a4e2a07c63141120998559970c21deac743ea0c64a60a880c\",\"license\":\"CC0-1.0\",\"urls\":[\"bzz-raw://e635c346bde5b7ade9bcf35bc733081520cb86015be4fbc6e761e6e9482c4c91\",\"dweb:/ipfs/QmRoeazEnbFn5SPSWAkoFK2gSN9DMp3hJAnrLWuL2sKutz\"]},\"lib/eigenlayer-middleware/lib/eigenlayer-contracts/src/contracts/interfaces/IEigenPod.sol\":{\"keccak256\":\"0xb50c36ad96b6679bb80fd8331f949cbfbcba0f529026e1421a4d2bae64396eba\",\"license\":\"BUSL-1.1\",\"urls\":[\"bzz-raw://5719181d780120f1e688c0da276992a8caf185815917f453b3550537c31ed4cc\",\"dweb:/ipfs/QmYprRC5ZEXhz3zAUND5E8Xjn6s5TL8ZF8QbnndVq7aVPR\"]},\"lib/eigenlayer-middleware/lib/eigenlayer-contracts/src/contracts/interfaces/IEigenPodManager.sol\":{\"keccak256\":\"0xd8a64dbed03d3a5cdbefe1af75968f2dde07f973749c2ef5197bf7187c3e448c\",\"license\":\"BUSL-1.1\",\"urls\":[\"bzz-raw://27ccc7c1fd9352e9f9b357c9063d255dc0ed9583f43db09f786ac7497d7846b8\",\"dweb:/ipfs/QmeJzuJkE9m2NUNwZSp4tGZEZmih1LeucePup8hzMVDRbG\"]},\"lib/eigenlayer-middleware/lib/eigenlayer-contracts/src/contracts/interfaces/IPausable.sol\":{\"keccak256\":\"0x98cffc894842947377e24c1d375813a1120dd73a84c29782ab68404e109cb34f\",\"license\":\"BUSL-1.1\",\"urls\":[\"bzz-raw://b3474f6c350ceaee57cbdfb08fb48835d0c6e81ae8ebfbb9667899584a139324\",\"dweb:/ipfs/QmWELKtksdtWxQbqAccd8yGyhKqrgPZXTADKR7BuT27Zg5\"]},\"lib/eigenlayer-middleware/lib/eigenlayer-contracts/src/contracts/interfaces/IPauserRegistry.sol\":{\"keccak256\":\"0x9de8dd682bc0d812bbd6583c0231cbf35448d5eff58b74a93efa64cb9a768c49\",\"license\":\"BUSL-1.1\",\"urls\":[\"bzz-raw://c00d6c675b9c72b092d287fe85fd37782588df32b8eb59ab4c7db7a86be25e7d\",\"dweb:/ipfs/QmeYokY3HhAdbBaCPdHg3PgQEdRCDFEJy3Wf7VtgHBkQSx\"]},\"lib/eigenlayer-middleware/lib/eigenlayer-contracts/src/contracts/interfaces/ISignatureUtils.sol\":{\"keccak256\":\"0x5e52482a31d94401a8502f3014c4aada1142b4450fc0596dff8e1866a85fe092\",\"license\":\"BUSL-1.1\",\"urls\":[\"bzz-raw://17dc326c9361bc1453379f26545963557b2883b0c88bc07d4477e04dbcc0cc8c\",\"dweb:/ipfs/QmZXT7A816W5JH2ymirE2ETaJttqztFCsEL22AV8oEfCK9\"]},\"lib/eigenlayer-middleware/lib/eigenlayer-contracts/src/contracts/interfaces/ISlasher.sol\":{\"keccak256\":\"0x45dfaa2cfdde87f48a6ee38bb6fb739847aef7cf3f6137bdcd8c8a330559ec79\",\"license\":\"BUSL-1.1\",\"urls\":[\"bzz-raw://1b7f6bd75b42fcaa91ceb7140cb2c41926a1fe6ee2d3161e4fe6186b181ba232\",\"dweb:/ipfs/QmZjbdKiSs33C9i3GDc3sdD39Pz4YPkDoKftowoUF4kHmY\"]},\"lib/eigenlayer-middleware/lib/eigenlayer-contracts/src/contracts/interfaces/IStrategy.sol\":{\"keccak256\":\"0xc530c6a944b70051fd0dac0222de9a4b5baadeaf94ad194daac6ad8d2ace7420\",\"license\":\"BUSL-1.1\",\"urls\":[\"bzz-raw://3767df0364ce835b52e786d2851431eb9223fe4747602107505477e162231d73\",\"dweb:/ipfs/QmZkH5bKUygQrJomndNaQqkefVRW4rRefCa8HPJ5HMczxJ\"]},\"lib/eigenlayer-middleware/lib/eigenlayer-contracts/src/contracts/interfaces/IStrategyManager.sol\":{\"keccak256\":\"0x68bf02a443fc8b2f612eba3d39bfefa5f61f78b549f111cdecec5f2c58236a52\",\"license\":\"BUSL-1.1\",\"urls\":[\"bzz-raw://76bc6875ce74128b861fdac5fd1c0c72f3cc9bacf67fa4a73721b95fb23959ef\",\"dweb:/ipfs/QmPix4WJmf9fXyMZxfgwXEHBcg7V4NAbRqs4HUf5YrSJcM\"]},\"lib/eigenlayer-middleware/lib/eigenlayer-contracts/src/contracts/libraries/BeaconChainProofs.sol\":{\"keccak256\":\"0x70d89b05c1c5f47b74a07fbb5a2c05e606fed494e749ea98a9915b7be73df377\",\"license\":\"BUSL-1.1\",\"urls\":[\"bzz-raw://db1d3bfaee69aef53c8b12b492a17584e6d1ac94610cb8b38aad33e1cdd81af7\",\"dweb:/ipfs/QmfVsMTj1hcf9fMEm5RzvtcBN4dMcAKFBgUUDsNDr5XFpq\"]},\"lib/eigenlayer-middleware/lib/eigenlayer-contracts/src/contracts/libraries/Endian.sol\":{\"keccak256\":\"0xf3b72653ba2567a978d4612703fa5f71c5fcd015d8dac7818468f22772d90a9d\",\"license\":\"BUSL-1.1\",\"urls\":[\"bzz-raw://cee9d09370d968138d775c39525db4cd0768d60d17be7685519de12444e7dd2f\",\"dweb:/ipfs/QmUdGh8wpMei3edKiEWA6S96s9dRt4ekZKJ4nau356X8xQ\"]},\"lib/eigenlayer-middleware/lib/eigenlayer-contracts/src/contracts/libraries/Merkle.sol\":{\"keccak256\":\"0x9095fc29b96d102b10c02d44b3a6fbfa25593ef6ae4a810363ab885b9e6b0f71\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://0945132d482d56278edddb1d32209903c4d3839c87ba4317aadd97dc23610d0f\",\"dweb:/ipfs/QmVuM2aLRHxitx4rPx3GTYTBCVNcjYn6sHBRr1biUjLBP5\"]},\"lib/eigenlayer-middleware/lib/openzeppelin-contracts/contracts/proxy/beacon/IBeacon.sol\":{\"keccak256\":\"0xd50a3421ac379ccb1be435fa646d66a65c986b4924f0849839f08692f39dde61\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://ada1e030c0231db8d143b44ce92b4d1158eedb087880cad6d8cc7bd7ebe7b354\",\"dweb:/ipfs/QmWZ2NHZweRpz1U9GF6R1h65ri76dnX7fNxLBeM2t5N5Ce\"]},\"lib/eigenlayer-middleware/lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol\":{\"keccak256\":\"0x9750c6b834f7b43000631af5cc30001c5f547b3ceb3635488f140f60e897ea6b\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://5a7d5b1ef5d8d5889ad2ed89d8619c09383b80b72ab226e0fe7bde1636481e34\",\"dweb:/ipfs/QmebXWgtEfumQGBdVeM6c71McLixYXQP5Bk6kKXuoY4Bmr\"]},\"lib/eigenlayer-middleware/src/interfaces/IRegistry.sol\":{\"keccak256\":\"0x51426a17fb7e54bd3720e2890104e97a8559a13ff248b3d6b840916751c143d3\",\"license\":\"BUSL-1.1\",\"urls\":[\"bzz-raw://01f91289e6100d528cb8b318cb14ff22a0bc52882c9d4db41585e030cc9ddc25\",\"dweb:/ipfs/Qmb22nqGrsrtNovHRwbMCvDHGENuxAgrWu3Db4p7Er2MHY\"]},\"lib/eigenlayer-middleware/src/interfaces/IStakeRegistry.sol\":{\"keccak256\":\"0x1b8b4d757c1b804bc4cf6fbbf8bf8f89ebdeb30a31014751fe7d01deb9d513d4\",\"license\":\"BUSL-1.1\",\"urls\":[\"bzz-raw://984bf2777b898ed187d28997f9783f5c293a1a1848e3e9aa470ce9183d454c97\",\"dweb:/ipfs/Qme3aTpBrkLu8wYHFMZbCfhXHoZ1M6SpXkeC237T9BuU5B\"]}},\"version\":1}","metadata":{"compiler":{"version":"0.8.24+commit.e11b9ed9"},"language":"Solidity","output":{"abi":[{"inputs":[{"internalType":"uint8","name":"quorumNumber","type":"uint8","indexed":true},{"internalType":"uint96","name":"minimumStake","type":"uint96","indexed":false}],"type":"event","name":"MinimumStakeForQuorumUpdated","anonymous":false},{"inputs":[{"internalType":"bytes32","name":"operatorId","type":"bytes32","indexed":true},{"internalType":"uint8","name":"quorumNumber","type":"uint8","indexed":false},{"internalType":"uint96","name":"stake","type":"uint96","indexed":false}],"type":"event","name":"OperatorStakeUpdate","anonymous":false},{"inputs":[{"internalType":"uint8","name":"quorumNumber","type":"uint8","indexed":true}],"type":"event","name":"QuorumCreated","anonymous":false},{"inputs":[{"internalType":"uint8","name":"quorumNumber","type":"uint8","indexed":true},{"internalType":"contract IStrategy","name":"strategy","type":"address","indexed":false}],"type":"event","name":"StrategyAddedToQuorum","anonymous":false},{"inputs":[{"internalType":"uint8","name":"quorumNumber","type":"uint8","indexed":true},{"internalType":"contract IStrategy","name":"strategy","type":"address","indexed":false},{"internalType":"uint256","name":"multiplier","type":"uint256","indexed":false}],"type":"event","name":"StrategyMultiplierUpdated","anonymous":false},{"inputs":[{"internalType":"uint8","name":"quorumNumber","type":"uint8","indexed":true},{"internalType":"contract IStrategy","name":"strategy","type":"address","indexed":false}],"type":"event","name":"StrategyRemovedFromQuorum","anonymous":false},{"inputs":[],"stateMutability":"pure","type":"function","name":"WEIGHTING_DIVISOR","outputs":[{"internalType":"uint256","name":"","type":"uint256"}]},{"inputs":[{"internalType":"uint8","name":"quorumNumber","type":"uint8"},{"internalType":"struct IStakeRegistry.StrategyParams[]","name":"strategyParams","type":"tuple[]","components":[{"internalType":"contract IStrategy","name":"strategy","type":"address"},{"internalType":"uint96","name":"multiplier","type":"uint96"}]}],"stateMutability":"nonpayable","type":"function","name":"addStrategies"},{"inputs":[],"stateMutability":"view","type":"function","name":"delegation","outputs":[{"internalType":"contract IDelegationManager","name":"","type":"address"}]},{"inputs":[{"internalType":"bytes32","name":"operatorId","type":"bytes32"},{"internalType":"bytes","name":"quorumNumbers","type":"bytes"}],"stateMutability":"nonpayable","type":"function","name":"deregisterOperator"},{"inputs":[{"internalType":"bytes32","name":"operatorId","type":"bytes32"},{"internalType":"uint8","name":"quorumNumber","type":"uint8"}],"stateMutability":"view","type":"function","name":"getCurrentStake","outputs":[{"internalType":"uint96","name":"","type":"uint96"}]},{"inputs":[{"internalType":"uint8","name":"quorumNumber","type":"uint8"}],"stateMutability":"view","type":"function","name":"getCurrentTotalStake","outputs":[{"internalType":"uint96","name":"","type":"uint96"}]},{"inputs":[{"internalType":"bytes32","name":"operatorId","type":"bytes32"},{"internalType":"uint8","name":"quorumNumber","type":"uint8"}],"stateMutability":"view","type":"function","name":"getLatestStakeUpdate","outputs":[{"internalType":"struct IStakeRegistry.StakeUpdate","name":"","type":"tuple","components":[{"internalType":"uint32","name":"updateBlockNumber","type":"uint32"},{"internalType":"uint32","name":"nextUpdateBlockNumber","type":"uint32"},{"internalType":"uint96","name":"stake","type":"uint96"}]}]},{"inputs":[{"internalType":"bytes32","name":"operatorId","type":"bytes32"},{"internalType":"uint8","name":"quorumNumber","type":"uint8"},{"internalType":"uint32","name":"blockNumber","type":"uint32"}],"stateMutability":"view","type":"function","name":"getStakeAtBlockNumber","outputs":[{"internalType":"uint96","name":"","type":"uint96"}]},{"inputs":[{"internalType":"uint8","name":"quorumNumber","type":"uint8"},{"internalType":"uint32","name":"blockNumber","type":"uint32"},{"internalType":"bytes32","name":"operatorId","type":"bytes32"},{"internalType":"uint256","name":"index","type":"uint256"}],"stateMutability":"view","type":"function","name":"getStakeAtBlockNumberAndIndex","outputs":[{"internalType":"uint96","name":"","type":"uint96"}]},{"inputs":[{"internalType":"bytes32","name":"operatorId","type":"bytes32"},{"internalType":"uint8","name":"quorumNumber","type":"uint8"}],"stateMutability":"view","type":"function","name":"getStakeHistory","outputs":[{"internalType":"struct IStakeRegistry.StakeUpdate[]","name":"","type":"tuple[]","components":[{"internalType":"uint32","name":"updateBlockNumber","type":"uint32"},{"internalType":"uint32","name":"nextUpdateBlockNumber","type":"uint32"},{"internalType":"uint96","name":"stake","type":"uint96"}]}]},{"inputs":[{"internalType":"uint8","name":"quorumNumber","type":"uint8"},{"internalType":"bytes32","name":"operatorId","type":"bytes32"},{"internalType":"uint256","name":"index","type":"uint256"}],"stateMutability":"view","type":"function","name":"getStakeUpdateAtIndex","outputs":[{"internalType":"struct IStakeRegistry.StakeUpdate","name":"","type":"tuple","components":[{"internalType":"uint32","name":"updateBlockNumber","type":"uint32"},{"internalType":"uint32","name":"nextUpdateBlockNumber","type":"uint32"},{"internalType":"uint96","name":"stake","type":"uint96"}]}]},{"inputs":[{"internalType":"bytes32","name":"operatorId","type":"bytes32"},{"internalType":"uint8","name":"quorumNumber","type":"uint8"},{"internalType":"uint32","name":"blockNumber","type":"uint32"}],"stateMutability":"view","type":"function","name":"getStakeUpdateIndexAtBlockNumber","outputs":[{"internalType":"uint32","name":"","type":"uint32"}]},{"inputs":[{"internalType":"uint8","name":"quorumNumber","type":"uint8"},{"internalType":"uint32","name":"blockNumber","type":"uint32"},{"internalType":"uint256","name":"index","type":"uint256"}],"stateMutability":"view","type":"function","name":"getTotalStakeAtBlockNumberFromIndex","outputs":[{"internalType":"uint96","name":"","type":"uint96"}]},{"inputs":[{"internalType":"uint8","name":"quorumNumber","type":"uint8"}],"stateMutability":"view","type":"function","name":"getTotalStakeHistoryLength","outputs":[{"internalType":"uint256","name":"","type":"uint256"}]},{"inputs":[{"internalType":"uint32","name":"blockNumber","type":"uint32"},{"internalType":"bytes","name":"quorumNumbers","type":"bytes"}],"stateMutability":"view","type":"function","name":"getTotalStakeIndicesAtBlockNumber","outputs":[{"internalType":"uint32[]","name":"","type":"uint32[]"}]},{"inputs":[{"internalType":"uint8","name":"quorumNumber","type":"uint8"},{"internalType":"uint256","name":"index","type":"uint256"}],"stateMutability":"view","type":"function","name":"getTotalStakeUpdateAtIndex","outputs":[{"internalType":"struct IStakeRegistry.StakeUpdate","name":"","type":"tuple","components":[{"internalType":"uint32","name":"updateBlockNumber","type":"uint32"},{"internalType":"uint32","name":"nextUpdateBlockNumber","type":"uint32"},{"internalType":"uint96","name":"stake","type":"uint96"}]}]},{"inputs":[{"internalType":"uint8","name":"quorumNumber","type":"uint8"},{"internalType":"uint96","name":"minimumStake","type":"uint96"},{"internalType":"struct IStakeRegistry.StrategyParams[]","name":"strategyParams","type":"tuple[]","components":[{"internalType":"contract IStrategy","name":"strategy","type":"address"},{"internalType":"uint96","name":"multiplier","type":"uint96"}]}],"stateMutability":"nonpayable","type":"function","name":"initializeQuorum"},{"inputs":[{"internalType":"uint8","name":"quorumNumber","type":"uint8"}],"stateMutability":"view","type":"function","name":"minimumStakeForQuorum","outputs":[{"internalType":"uint96","name":"","type":"uint96"}]},{"inputs":[{"internalType":"uint8","name":"quorumNumber","type":"uint8"},{"internalType":"uint256[]","name":"strategyIndices","type":"uint256[]"},{"internalType":"uint96[]","name":"newMultipliers","type":"uint96[]"}],"stateMutability":"nonpayable","type":"function","name":"modifyStrategyParams"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bytes32","name":"operatorId","type":"bytes32"},{"internalType":"bytes","name":"quorumNumbers","type":"bytes"}],"stateMutability":"nonpayable","type":"function","name":"registerOperator","outputs":[{"internalType":"uint96[]","name":"","type":"uint96[]"},{"internalType":"uint96[]","name":"","type":"uint96[]"}]},{"inputs":[],"stateMutability":"view","type":"function","name":"registryCoordinator","outputs":[{"internalType":"address","name":"","type":"address"}]},{"inputs":[{"internalType":"uint8","name":"quorumNumber","type":"uint8"},{"internalType":"uint256[]","name":"indicesToRemove","type":"uint256[]"}],"stateMutability":"nonpayable","type":"function","name":"removeStrategies"},{"inputs":[{"internalType":"uint8","name":"quorumNumber","type":"uint8"},{"internalType":"uint256","name":"index","type":"uint256"}],"stateMutability":"view","type":"function","name":"strategyParamsByIndex","outputs":[{"internalType":"struct IStakeRegistry.StrategyParams","name":"","type":"tuple","components":[{"internalType":"contract IStrategy","name":"strategy","type":"address"},{"internalType":"uint96","name":"multiplier","type":"uint96"}]}]},{"inputs":[{"internalType":"uint8","name":"quorumNumber","type":"uint8"}],"stateMutability":"view","type":"function","name":"strategyParamsLength","outputs":[{"internalType":"uint256","name":"","type":"uint256"}]},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bytes32","name":"operatorId","type":"bytes32"},{"internalType":"bytes","name":"quorumNumbers","type":"bytes"}],"stateMutability":"nonpayable","type":"function","name":"updateOperatorStake","outputs":[{"internalType":"uint192","name":"","type":"uint192"}]},{"inputs":[{"internalType":"uint8","name":"quorumNumber","type":"uint8"},{"internalType":"address","name":"operator","type":"address"}],"stateMutability":"view","type":"function","name":"weightOfOperatorForQuorum","outputs":[{"internalType":"uint96","name":"","type":"uint96"}]}],"devdoc":{"kind":"dev","methods":{"deregisterOperator(bytes32,bytes)":{"details":"access restricted to the RegistryCoordinatorPreconditions (these are assumed, not validated in this contract): 1) `quorumNumbers` has no duplicates 2) `quorumNumbers.length` != 0 3) `quorumNumbers` is ordered in ascending order 4) the operator is not already deregistered 5) `quorumNumbers` is a subset of the quorumNumbers that the operator is registered for","params":{"operatorId":"The id of the operator to deregister.","quorumNumbers":"The quorum numbers the operator is deregistering from, where each byte is an 8 bit integer quorumNumber."}},"getCurrentStake(bytes32,uint8)":{"details":"Function returns weight of **0** in the event that the operator has no stake history"},"getCurrentTotalStake(uint8)":{"details":"Will revert if `_totalStakeHistory[quorumNumber]` is empty."},"getLatestStakeUpdate(bytes32,uint8)":{"details":"Function returns an StakeUpdate struct with **every entry equal to 0** in the event that the operator has no stake history"},"getStakeAtBlockNumberAndIndex(uint8,uint32,bytes32,uint256)":{"details":"Function will revert if `index` is out-of-bounds.used the BLSSignatureChecker to get past stakes of signing operators","params":{"blockNumber":"Block number to make sure the stake is from.","index":"Array index for lookup, within the dynamic array `operatorIdToStakeHistory[operatorId][quorumNumber]`.","operatorId":"The id of the operator of interest.","quorumNumber":"The quorum number to get the stake for."}},"getStakeHistory(bytes32,uint8)":{"params":{"operatorId":"The id of the operator of interest.","quorumNumber":"The quorum number to get the stake for."}},"getStakeUpdateAtIndex(uint8,bytes32,uint256)":{"details":"Function will revert if `index` is out-of-bounds.","params":{"index":"Array index for lookup, within the dynamic array `operatorIdToStakeHistory[operatorId][quorumNumber]`.","operatorId":"The id of the operator of interest.","quorumNumber":"The quorum number to get the stake for."}},"getTotalStakeAtBlockNumberFromIndex(uint8,uint32,uint256)":{"details":"Function will revert if `index` is out-of-bounds.used the BLSSignatureChecker to get past stakes of signing operators","params":{"blockNumber":"Block number to make sure the stake is from.","index":"Array index for lookup, within the dynamic array `totalStakeHistory[quorumNumber]`.","quorumNumber":"The quorum number to get the stake for."}},"getTotalStakeUpdateAtIndex(uint8,uint256)":{"params":{"index":"Array index for lookup, within the dynamic array `totalStakeHistory[quorumNumber]`.","quorumNumber":"The quorum number to get the stake for."}},"modifyStrategyParams(uint8,uint256[],uint96[])":{"params":{"newMultipliers":"are the new multipliers for the strategies","quorumNumber":"is the quorum number to change the strategy for","strategyIndices":"are the indices of the strategies to change"}},"registerOperator(address,bytes32,bytes)":{"details":"access restricted to the RegistryCoordinatorPreconditions (these are assumed, not validated in this contract): 1) `quorumNumbers` has no duplicates 2) `quorumNumbers.length` != 0 3) `quorumNumbers` is ordered in ascending order 4) the operator is not already registered","params":{"operator":"The address of the operator to register.","operatorId":"The id of the operator to register.","quorumNumbers":"The quorum numbers the operator is registering for, where each byte is an 8 bit integer quorumNumber."},"returns":{"_0":"The operator's current stake for each quorum, and the total stake for each quorum"}},"removeStrategies(uint8,uint256[])":{"details":"higher indices should be *first* in the list of @param indicesToRemove, since otherwise the removal of lower index entries will cause a shift in the indices of the other strategiesToRemove","params":{"quorumNumber":"."}},"updateOperatorStake(address,bytes32,bytes)":{"returns":{"_0":"A bitmap of quorums where the operator no longer meets the minimum stake and should be deregistered."}},"weightOfOperatorForQuorum(uint8,address)":{"details":"reverts in the case that `quorumNumber` is greater than or equal to `quorumCount`"}},"version":1},"userdoc":{"kind":"user","methods":{"WEIGHTING_DIVISOR()":{"notice":"Constant used as a divisor in calculating weights."},"addStrategies(uint8,(address,uint96)[])":{"notice":"Adds new strategies and the associated multipliers to the @param quorumNumber."},"delegation()":{"notice":"Returns the EigenLayer delegation manager contract."},"deregisterOperator(bytes32,bytes)":{"notice":"Deregisters the operator with `operatorId` for the specified `quorumNumbers`."},"getCurrentStake(bytes32,uint8)":{"notice":"Returns the most recent stake weight for the `operatorId` for quorum `quorumNumber`"},"getCurrentTotalStake(uint8)":{"notice":"Returns the stake weight from the latest entry in `_totalStakeHistory` for quorum `quorumNumber`."},"getLatestStakeUpdate(bytes32,uint8)":{"notice":"Returns the most recent stake weight for the `operatorId` for a certain quorum"},"getStakeAtBlockNumber(bytes32,uint8,uint32)":{"notice":"Returns the stake of the operator for the provided `quorumNumber` at the given `blockNumber`"},"getStakeAtBlockNumberAndIndex(uint8,uint32,bytes32,uint256)":{"notice":"Returns the stake weight corresponding to `operatorId` for quorum `quorumNumber`, at the `index`-th entry in the `operatorIdToStakeHistory[operatorId][quorumNumber]` array if the entry corresponds to the operator's stake at `blockNumber`. Reverts otherwise."},"getStakeHistory(bytes32,uint8)":{"notice":"Returns the entire `operatorIdToStakeHistory[operatorId][quorumNumber]` array."},"getStakeUpdateAtIndex(uint8,bytes32,uint256)":{"notice":"Returns the `index`-th entry in the `operatorIdToStakeHistory[operatorId][quorumNumber]` array."},"getStakeUpdateIndexAtBlockNumber(bytes32,uint8,uint32)":{"notice":"Returns the indices of the operator stakes for the provided `quorumNumber` at the given `blockNumber`"},"getTotalStakeAtBlockNumberFromIndex(uint8,uint32,uint256)":{"notice":"Returns the total stake weight for quorum `quorumNumber`, at the `index`-th entry in the `totalStakeHistory[quorumNumber]` array if the entry corresponds to the total stake at `blockNumber`. Reverts otherwise."},"getTotalStakeIndicesAtBlockNumber(uint32,bytes)":{"notice":"Returns the indices of the total stakes for the provided `quorumNumbers` at the given `blockNumber`"},"getTotalStakeUpdateAtIndex(uint8,uint256)":{"notice":"Returns the `index`-th entry in the dynamic array of total stake, `totalStakeHistory` for quorum `quorumNumber`."},"initializeQuorum(uint8,uint96,(address,uint96)[])":{"notice":"Initialize a new quorum created by the registry coordinator by setting strategies, weights, and minimum stake"},"minimumStakeForQuorum(uint8)":{"notice":"In order to register for a quorum i, an operator must have at least `minimumStakeForQuorum[i]`"},"modifyStrategyParams(uint8,uint256[],uint96[])":{"notice":"This function is used for modifying the weights of strategies that are already in the mapping strategyParams for a specific"},"registerOperator(address,bytes32,bytes)":{"notice":"Registers the `operator` with `operatorId` for the specified `quorumNumbers`."},"removeStrategies(uint8,uint256[])":{"notice":"This function is used for removing strategies and their associated weights from the"},"strategyParamsByIndex(uint8,uint256)":{"notice":"Returns the strategy and weight multiplier for the `index`'th strategy in the quorum `quorumNumber`"},"strategyParamsLength(uint8)":{"notice":"Returns the length of the dynamic array stored in `strategyParams[quorumNumber]`."},"updateOperatorStake(address,bytes32,bytes)":{"notice":"Called by the registry coordinator to update an operator's stake for one or more quorums. If the operator no longer has the minimum stake required for a quorum, they are added to the"},"weightOfOperatorForQuorum(uint8,address)":{"notice":"This function computes the total weight of the @param operator in the quorum @param quorumNumber."}},"version":1}},"settings":{"remappings":["@openzeppelin-upgrades-v4.9.0/=lib/eigenlayer-middleware/lib/eigenlayer-contracts/lib/openzeppelin-contracts-upgradeable-v4.9.0/","@openzeppelin-upgrades/contracts/=lib/eigenlayer-middleware/lib/openzeppelin-contracts-upgradeable/contracts/","@openzeppelin-v4.9.0/=lib/eigenlayer-middleware/lib/eigenlayer-contracts/lib/openzeppelin-contracts-v4.9.0/","@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/","@openzeppelin/contracts/=lib/eigenlayer-middleware/lib/openzeppelin-contracts/contracts/","ds-test/=lib/eigenlayer-middleware/lib/ds-test/src/","eigenlayer-contracts/=lib/eigenlayer-middleware/lib/eigenlayer-contracts/","eigenlayer-core-contracts/=lib/eigenlayer-middleware/lib/eigenlayer-contracts/src/contracts/core/","eigenlayer-core/=lib/eigenlayer-middleware/lib/eigenlayer-contracts/src/","eigenlayer-middleware/=lib/eigenlayer-middleware/src/","eigenlayer-scripts/=lib/eigenlayer-middleware/lib/eigenlayer-contracts/script/","erc4626-tests/=lib/openzeppelin-contracts-upgradeable/lib/erc4626-tests/","forge-std/=lib/forge-std/src/","openzeppelin-contracts-upgradeable-v4.9.0/=lib/eigenlayer-middleware/lib/eigenlayer-contracts/lib/openzeppelin-contracts-upgradeable-v4.9.0/","openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/","openzeppelin-contracts-v4.9.0/=lib/eigenlayer-middleware/lib/eigenlayer-contracts/lib/openzeppelin-contracts-v4.9.0/","openzeppelin-contracts/=lib/openzeppelin-contracts/","openzeppelin/=lib/eigenlayer-middleware/lib/eigenlayer-contracts/lib/openzeppelin-contracts-upgradeable-v4.9.0/contracts/"],"optimizer":{"enabled":true,"runs":200},"metadata":{"bytecodeHash":"ipfs"},"compilationTarget":{"lib/eigenlayer-middleware/src/interfaces/IStakeRegistry.sol":"IStakeRegistry"},"evmVersion":"paris","libraries":{}},"sources":{"lib/eigenlayer-middleware/lib/eigenlayer-contracts/src/contracts/interfaces/IBeaconChainOracle.sol":{"keccak256":"0x0fef07aa6179c77198f1514e12e628aa1c876e04f9c181ec853a322179e5be00","urls":["bzz-raw://51438325876cc2d4c77f58488a7e27b488015d1b663c50be6a5cafbd73b9c983","dweb:/ipfs/QmViCuGoYZzi6wtXA8PPKigqVv3KMuNxEVQ1Td9dGqjL18"],"license":"BUSL-1.1"},"lib/eigenlayer-middleware/lib/eigenlayer-contracts/src/contracts/interfaces/IDelegationManager.sol":{"keccak256":"0xab76a9f4eff865cbb689f627cf98263488765519d7a4ec5ffbcb0ca4972842f9","urls":["bzz-raw://ff57ce18e8350bf39f190645db0988bc0f1279f1872150a114a1b520c38a2914","dweb:/ipfs/QmSsUXkNUqYuJgGRumHTSs9rAaboGjecotcM4xHrdBYWaZ"],"license":"BUSL-1.1"},"lib/eigenlayer-middleware/lib/eigenlayer-contracts/src/contracts/interfaces/IETHPOSDeposit.sol":{"keccak256":"0x2e60e5f4b0da0a0a4e2a07c63141120998559970c21deac743ea0c64a60a880c","urls":["bzz-raw://e635c346bde5b7ade9bcf35bc733081520cb86015be4fbc6e761e6e9482c4c91","dweb:/ipfs/QmRoeazEnbFn5SPSWAkoFK2gSN9DMp3hJAnrLWuL2sKutz"],"license":"CC0-1.0"},"lib/eigenlayer-middleware/lib/eigenlayer-contracts/src/contracts/interfaces/IEigenPod.sol":{"keccak256":"0xb50c36ad96b6679bb80fd8331f949cbfbcba0f529026e1421a4d2bae64396eba","urls":["bzz-raw://5719181d780120f1e688c0da276992a8caf185815917f453b3550537c31ed4cc","dweb:/ipfs/QmYprRC5ZEXhz3zAUND5E8Xjn6s5TL8ZF8QbnndVq7aVPR"],"license":"BUSL-1.1"},"lib/eigenlayer-middleware/lib/eigenlayer-contracts/src/contracts/interfaces/IEigenPodManager.sol":{"keccak256":"0xd8a64dbed03d3a5cdbefe1af75968f2dde07f973749c2ef5197bf7187c3e448c","urls":["bzz-raw://27ccc7c1fd9352e9f9b357c9063d255dc0ed9583f43db09f786ac7497d7846b8","dweb:/ipfs/QmeJzuJkE9m2NUNwZSp4tGZEZmih1LeucePup8hzMVDRbG"],"license":"BUSL-1.1"},"lib/eigenlayer-middleware/lib/eigenlayer-contracts/src/contracts/interfaces/IPausable.sol":{"keccak256":"0x98cffc894842947377e24c1d375813a1120dd73a84c29782ab68404e109cb34f","urls":["bzz-raw://b3474f6c350ceaee57cbdfb08fb48835d0c6e81ae8ebfbb9667899584a139324","dweb:/ipfs/QmWELKtksdtWxQbqAccd8yGyhKqrgPZXTADKR7BuT27Zg5"],"license":"BUSL-1.1"},"lib/eigenlayer-middleware/lib/eigenlayer-contracts/src/contracts/interfaces/IPauserRegistry.sol":{"keccak256":"0x9de8dd682bc0d812bbd6583c0231cbf35448d5eff58b74a93efa64cb9a768c49","urls":["bzz-raw://c00d6c675b9c72b092d287fe85fd37782588df32b8eb59ab4c7db7a86be25e7d","dweb:/ipfs/QmeYokY3HhAdbBaCPdHg3PgQEdRCDFEJy3Wf7VtgHBkQSx"],"license":"BUSL-1.1"},"lib/eigenlayer-middleware/lib/eigenlayer-contracts/src/contracts/interfaces/ISignatureUtils.sol":{"keccak256":"0x5e52482a31d94401a8502f3014c4aada1142b4450fc0596dff8e1866a85fe092","urls":["bzz-raw://17dc326c9361bc1453379f26545963557b2883b0c88bc07d4477e04dbcc0cc8c","dweb:/ipfs/QmZXT7A816W5JH2ymirE2ETaJttqztFCsEL22AV8oEfCK9"],"license":"BUSL-1.1"},"lib/eigenlayer-middleware/lib/eigenlayer-contracts/src/contracts/interfaces/ISlasher.sol":{"keccak256":"0x45dfaa2cfdde87f48a6ee38bb6fb739847aef7cf3f6137bdcd8c8a330559ec79","urls":["bzz-raw://1b7f6bd75b42fcaa91ceb7140cb2c41926a1fe6ee2d3161e4fe6186b181ba232","dweb:/ipfs/QmZjbdKiSs33C9i3GDc3sdD39Pz4YPkDoKftowoUF4kHmY"],"license":"BUSL-1.1"},"lib/eigenlayer-middleware/lib/eigenlayer-contracts/src/contracts/interfaces/IStrategy.sol":{"keccak256":"0xc530c6a944b70051fd0dac0222de9a4b5baadeaf94ad194daac6ad8d2ace7420","urls":["bzz-raw://3767df0364ce835b52e786d2851431eb9223fe4747602107505477e162231d73","dweb:/ipfs/QmZkH5bKUygQrJomndNaQqkefVRW4rRefCa8HPJ5HMczxJ"],"license":"BUSL-1.1"},"lib/eigenlayer-middleware/lib/eigenlayer-contracts/src/contracts/interfaces/IStrategyManager.sol":{"keccak256":"0x68bf02a443fc8b2f612eba3d39bfefa5f61f78b549f111cdecec5f2c58236a52","urls":["bzz-raw://76bc6875ce74128b861fdac5fd1c0c72f3cc9bacf67fa4a73721b95fb23959ef","dweb:/ipfs/QmPix4WJmf9fXyMZxfgwXEHBcg7V4NAbRqs4HUf5YrSJcM"],"license":"BUSL-1.1"},"lib/eigenlayer-middleware/lib/eigenlayer-contracts/src/contracts/libraries/BeaconChainProofs.sol":{"keccak256":"0x70d89b05c1c5f47b74a07fbb5a2c05e606fed494e749ea98a9915b7be73df377","urls":["bzz-raw://db1d3bfaee69aef53c8b12b492a17584e6d1ac94610cb8b38aad33e1cdd81af7","dweb:/ipfs/QmfVsMTj1hcf9fMEm5RzvtcBN4dMcAKFBgUUDsNDr5XFpq"],"license":"BUSL-1.1"},"lib/eigenlayer-middleware/lib/eigenlayer-contracts/src/contracts/libraries/Endian.sol":{"keccak256":"0xf3b72653ba2567a978d4612703fa5f71c5fcd015d8dac7818468f22772d90a9d","urls":["bzz-raw://cee9d09370d968138d775c39525db4cd0768d60d17be7685519de12444e7dd2f","dweb:/ipfs/QmUdGh8wpMei3edKiEWA6S96s9dRt4ekZKJ4nau356X8xQ"],"license":"BUSL-1.1"},"lib/eigenlayer-middleware/lib/eigenlayer-contracts/src/contracts/libraries/Merkle.sol":{"keccak256":"0x9095fc29b96d102b10c02d44b3a6fbfa25593ef6ae4a810363ab885b9e6b0f71","urls":["bzz-raw://0945132d482d56278edddb1d32209903c4d3839c87ba4317aadd97dc23610d0f","dweb:/ipfs/QmVuM2aLRHxitx4rPx3GTYTBCVNcjYn6sHBRr1biUjLBP5"],"license":"MIT"},"lib/eigenlayer-middleware/lib/openzeppelin-contracts/contracts/proxy/beacon/IBeacon.sol":{"keccak256":"0xd50a3421ac379ccb1be435fa646d66a65c986b4924f0849839f08692f39dde61","urls":["bzz-raw://ada1e030c0231db8d143b44ce92b4d1158eedb087880cad6d8cc7bd7ebe7b354","dweb:/ipfs/QmWZ2NHZweRpz1U9GF6R1h65ri76dnX7fNxLBeM2t5N5Ce"],"license":"MIT"},"lib/eigenlayer-middleware/lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol":{"keccak256":"0x9750c6b834f7b43000631af5cc30001c5f547b3ceb3635488f140f60e897ea6b","urls":["bzz-raw://5a7d5b1ef5d8d5889ad2ed89d8619c09383b80b72ab226e0fe7bde1636481e34","dweb:/ipfs/QmebXWgtEfumQGBdVeM6c71McLixYXQP5Bk6kKXuoY4Bmr"],"license":"MIT"},"lib/eigenlayer-middleware/src/interfaces/IRegistry.sol":{"keccak256":"0x51426a17fb7e54bd3720e2890104e97a8559a13ff248b3d6b840916751c143d3","urls":["bzz-raw://01f91289e6100d528cb8b318cb14ff22a0bc52882c9d4db41585e030cc9ddc25","dweb:/ipfs/Qmb22nqGrsrtNovHRwbMCvDHGENuxAgrWu3Db4p7Er2MHY"],"license":"BUSL-1.1"},"lib/eigenlayer-middleware/src/interfaces/IStakeRegistry.sol":{"keccak256":"0x1b8b4d757c1b804bc4cf6fbbf8bf8f89ebdeb30a31014751fe7d01deb9d513d4","urls":["bzz-raw://984bf2777b898ed187d28997f9783f5c293a1a1848e3e9aa470ce9183d454c97","dweb:/ipfs/Qme3aTpBrkLu8wYHFMZbCfhXHoZ1M6SpXkeC237T9BuU5B"],"license":"BUSL-1.1"}},"version":1},"id":134} \ No newline at end of file From 7c232196833bb3e2670a9ac7f9a27b2cd4a82fde Mon Sep 17 00:00:00 2001 From: avilagaston9 Date: Wed, 2 Oct 2024 16:09:07 -0300 Subject: [PATCH 24/55] fix: address comments --- .../contract_managers/delegation_manager.ex | 30 ++++++------ .../operator_state_retriever.ex | 41 ++++++++++------- .../registry_coordinator_manager.ex | 46 ------------------- telemetry_api/lib/telemetry_api/operators.ex | 13 +++--- .../lib/telemetry_api/signature_verifier.ex | 12 +++-- telemetry_api/priv/static/robots.txt | 4 +- 6 files changed, 56 insertions(+), 90 deletions(-) delete mode 100644 telemetry_api/lib/telemetry_api/contract_managers/registry_coordinator_manager.ex diff --git a/telemetry_api/lib/telemetry_api/contract_managers/delegation_manager.ex b/telemetry_api/lib/telemetry_api/contract_managers/delegation_manager.ex index 9318f6832..920c7a8f5 100644 --- a/telemetry_api/lib/telemetry_api/contract_managers/delegation_manager.ex +++ b/telemetry_api/lib/telemetry_api/contract_managers/delegation_manager.ex @@ -14,7 +14,6 @@ defmodule TelemetryApi.ContractManagers.DelegationManager do eigenlayer_output_file_path = "../contracts/script/output/#{@environment}/eigenlayer_deployment_output.json" - {status, config_json_string} = File.read(eigenlayer_output_file_path) case status do @@ -24,10 +23,10 @@ defmodule TelemetryApi.ContractManagers.DelegationManager do :error -> raise("Config file not read successfully") end - + @contract_address Jason.decode!(config_json_string) - |> Map.get("addresses") - |> Map.get("delegationManager") + |> Map.get("addresses") + |> Map.get("delegationManager") use Ethers.Contract, abi_file: "priv/abi/DelegationManager.json", @@ -39,15 +38,18 @@ defmodule TelemetryApi.ContractManagers.DelegationManager do def get_operator_url(operator_address) do DelegationManager.EventFilters.operator_metadata_uri_updated(operator_address) - |> Ethers.get_logs(fromBlock: @first_block) - |> case do - {:ok, data} -> - url = List.last(data).data |> hd() # The head (hd) is the most recent entry - {:ok, url} - {:error, reason} -> - {:error, reason} - other -> - {:error, "Unexpected response getting operator url: #{inspect(other)}"} - end + |> Ethers.get_logs(fromBlock: @first_block) + |> case do + {:ok, data} -> + # The head (hd) is the most recent entry + url = List.last(data).data |> hd() + {:ok, url} + + {:error, reason} -> + {:error, reason} + + other -> + {:error, "Unexpected response getting operator url: #{inspect(other)}"} + end end end diff --git a/telemetry_api/lib/telemetry_api/contract_managers/operator_state_retriever.ex b/telemetry_api/lib/telemetry_api/contract_managers/operator_state_retriever.ex index 2ca144594..e33b6eef3 100644 --- a/telemetry_api/lib/telemetry_api/contract_managers/operator_state_retriever.ex +++ b/telemetry_api/lib/telemetry_api/contract_managers/operator_state_retriever.ex @@ -20,14 +20,14 @@ defmodule TelemetryApi.ContractManagers.OperatorStateRetriever do end @contract_address Jason.decode!(config_json_string) - |> Map.get("addresses") - |> Map.get("operatorStateRetriever") + |> Map.get("addresses") + |> Map.get("operatorStateRetriever") @registry_coordinator_address Jason.decode!(config_json_string) - |> Map.get("addresses") - |> Map.get("registryCoordinator") - |> String.trim_leading("0x") - |> Base.decode16!(case: :mixed) + |> Map.get("addresses") + |> Map.get("registryCoordinator") + |> String.trim_leading("0x") + |> Base.decode16!(case: :mixed) use Ethers.Contract, abi_file: "priv/abi/OperatorStateRetriever.json", @@ -41,34 +41,41 @@ defmodule TelemetryApi.ContractManagers.OperatorStateRetriever do def get_operators() do with {:ok, block_number} = Ethers.current_block_number(), - {:ok, operators_state} = fetch_operators_state(block_number) do - parse_operators(operators_state) - end + {:ok, operators_state} = fetch_operators_state(block_number) do + parse_operators(operators_state) + end end # -------- PRIVATE FUNCTIONS -------- defp parse_operators(operators_state) do operators = - operators_state |> Enum.map(fn {address, id, stake} -> + operators_state + |> Enum.map(fn {address, id, stake} -> id = "0x" <> Base.encode16(id, case: :lower) address = address |> String.downcase() + %{ id: id, address: address, stake: Integer.to_string(stake) } end) + {:ok, operators} end defp fetch_operators_state(block_number) do - quorum_numbers = <<0>> - response = __MODULE__.get_operator_state(@registry_coordinator_address, quorum_numbers, block_number) |> Ethers.call() - case response do - {:ok, [operators | _]} -> {:ok, operators} - {:error, message} -> {:error, message} - _ -> {:error, "Bad formated data received from OperatorStateRetriever::getOperatorState"} - end + quorum_numbers = <<0>> + + response = + __MODULE__.get_operator_state(@registry_coordinator_address, quorum_numbers, block_number) + |> Ethers.call() + + case response do + {:ok, [operators | _]} -> {:ok, operators} + {:error, message} -> {:error, message} + _ -> {:error, "Bad formated data received from OperatorStateRetriever::getOperatorState"} + end end end diff --git a/telemetry_api/lib/telemetry_api/contract_managers/registry_coordinator_manager.ex b/telemetry_api/lib/telemetry_api/contract_managers/registry_coordinator_manager.ex deleted file mode 100644 index b67b3c14c..000000000 --- a/telemetry_api/lib/telemetry_api/contract_managers/registry_coordinator_manager.ex +++ /dev/null @@ -1,46 +0,0 @@ -defmodule TelemetryApi.ContractManagers.RegistryCoordinatorManager do - alias TelemetryApi.ContractManagers.RegistryCoordinatorManager - - require Logger - - @aligned_config_file System.get_env("ALIGNED_CONFIG_FILE") - - config_file_path = - case @aligned_config_file do - nil -> raise("ALIGNED_CONFIG_FILE not set in .env") - file -> file - end - - {status, config_json_string} = File.read(config_file_path) - - case status do - :ok -> - Logger.debug("Aligned deployment file read successfully") - - :error -> - raise("Config file not read successfully") - end - - @registry_coordinator_address Jason.decode!(config_json_string) - |> Map.get("addresses") - |> Map.get("registryCoordinator") - - use Ethers.Contract, - abi_file: "priv/abi/IRegistryCoordinator.json", - default_address: @registry_coordinator_address - - def get_registry_coordinator_address() do - @registry_coordinator_address - end - - def is_operator_registered?(operator_address) do - {:ok, operator_address } = Base.decode16(operator_address, case: :mixed) - - case RegistryCoordinatorManager.get_operator_status(operator_address) - |> Ethers.call() do - {:ok, response} -> {:ok, response == 1} - error -> - {:error, error} - end - end -end diff --git a/telemetry_api/lib/telemetry_api/operators.ex b/telemetry_api/lib/telemetry_api/operators.ex index aafc69ed7..16925542e 100644 --- a/telemetry_api/lib/telemetry_api/operators.ex +++ b/telemetry_api/lib/telemetry_api/operators.ex @@ -40,7 +40,9 @@ defmodule TelemetryApi.Operators do end @doc """ - Fetches all operators. + - Fetches the state of all operators from the RegistryCoordinator ({address, id, stake}). + - Fetches the metadata of all operators from the DelegationManager. + - Stores all data in the database. ## Examples @@ -67,8 +69,7 @@ defmodule TelemetryApi.Operators do end end - - #Adds operator metadata to received operator. + # Adds operator metadata to received operator. ### Examples @@ -104,12 +105,12 @@ defmodule TelemetryApi.Operators do {:error, string} """ - def update_operator_version(attrs \\ %{}) do - with {:ok, address} <- SignatureVerifier.get_address(attrs["version"], attrs["signature"]) do + def update_operator_version(%{"version" => version, "signature" => signature}) do + with {:ok, address} <- SignatureVerifier.recover_address(version, signature) do address = "0x" <> address # We only want to allow changes on version changes = %{ - version: attrs["version"] + version: version } case Repo.get(Operator, address) do diff --git a/telemetry_api/lib/telemetry_api/signature_verifier.ex b/telemetry_api/lib/telemetry_api/signature_verifier.ex index 8f5eba4ce..c8646801c 100644 --- a/telemetry_api/lib/telemetry_api/signature_verifier.ex +++ b/telemetry_api/lib/telemetry_api/signature_verifier.ex @@ -10,7 +10,7 @@ defmodule SignatureVerifier do # Recover the public key from the signature and hashed version defp recover_public_key(hash, signature, recovery_id) do - case ExSecp256k1.recover_compact(hash, signature, recovery_id) do + case ExSecp256k1.recover_compact(hash, signature, recovery_id) do {:ok, public_key} -> {:ok, public_key} _error -> {:error, "Failed to recover public key"} end @@ -35,10 +35,10 @@ defmodule SignatureVerifier do Examples iex> version = "v0.7.0" iex> signature = N1UJOvjJT1W39MdQUYAOsKZj4aQ1Sjkwp31NJgafpjoUniGt24tSaLw6TlTKP68AkLtsIFoVEaJcJDj7TyvhLQA= - iex> get_address(version, signature) + iex> recover_address(version, signature) "0x..." """ - def get_address(version, signature) do + def recover_address(version, signature) do version_hash = hash_version(version) # Signature contains r, s and v (recovery_id) # r<>s is 64 bytes. @@ -49,8 +49,10 @@ defmodule SignatureVerifier do recovery_id = Binary.decode_unsigned(binary_part(binary_signature, signature_len - 1, 1)) with {:ok, address} <- recover_public_key(version_hash, rs, recovery_id) do - addr = public_key_to_address(address) - |> Base.encode16(case: :lower) + addr = + public_key_to_address(address) + |> Base.encode16(case: :lower) + {:ok, addr} end end diff --git a/telemetry_api/priv/static/robots.txt b/telemetry_api/priv/static/robots.txt index 26e06b5f1..ab7fef159 100644 --- a/telemetry_api/priv/static/robots.txt +++ b/telemetry_api/priv/static/robots.txt @@ -1,5 +1,5 @@ # See https://www.robotstxt.org/robotstxt.html for documentation on how to use the robots.txt file # # To ban all spiders from the entire site uncomment the next two lines: -# User-agent: * -# Disallow: / +User-agent: * +Disallow: / From 7138c2803dc71fb97e386fdcea49118d0ee6e5eb Mon Sep 17 00:00:00 2001 From: JuArce <52429267+JuArce@users.noreply.github.com> Date: Wed, 2 Oct 2024 16:20:24 -0300 Subject: [PATCH 25/55] nit --- telemetry_api/lib/telemetry_api/traces.ex | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/telemetry_api/lib/telemetry_api/traces.ex b/telemetry_api/lib/telemetry_api/traces.ex index d995949ea..a01ccffcc 100644 --- a/telemetry_api/lib/telemetry_api/traces.ex +++ b/telemetry_api/lib/telemetry_api/traces.ex @@ -194,9 +194,7 @@ defmodule TelemetryApi.Traces do operator_stake_fraction = operator_stake / trace.total_stake TraceStore.store_trace(merkle_root, %Trace{ - parent_span: trace.parent_span, - context: trace.context, - total_stake: trace.total_stake, + trace | current_stake: new_stake }) From 365616b63caa9847d3089c848d05810073e3e13e Mon Sep 17 00:00:00 2001 From: Julian Ventura Date: Wed, 2 Oct 2024 16:29:09 -0300 Subject: [PATCH 26/55] Add operators data periodic fetcher --- telemetry_api/.env.dev | 1 + telemetry_api/ecto_setup_db.sh | 1 + .../lib/telemetry_api/application.ex | 11 +++---- .../periodic/operator_fetcher.ex | 32 +++++++++++++++++++ telemetry_api/start.sh | 1 + 5 files changed, 39 insertions(+), 7 deletions(-) create mode 100644 telemetry_api/lib/telemetry_api/periodic/operator_fetcher.ex diff --git a/telemetry_api/.env.dev b/telemetry_api/.env.dev index b2a7e87be..1a33ddc8e 100644 --- a/telemetry_api/.env.dev +++ b/telemetry_api/.env.dev @@ -1,2 +1,3 @@ ALIGNED_CONFIG_FILE="../contracts/script/output/devnet/alignedlayer_deployment_output.json" +OPERATOR_FETCHER_WAIT_TIME_MS=5000 ENVIRONMENT=devnet diff --git a/telemetry_api/ecto_setup_db.sh b/telemetry_api/ecto_setup_db.sh index 4a225ed24..aebd647f0 100755 --- a/telemetry_api/ecto_setup_db.sh +++ b/telemetry_api/ecto_setup_db.sh @@ -6,6 +6,7 @@ source .env env_vars=( "ENVIRONMENT" "ALIGNED_CONFIG_FILE" + "OPERATOR_FETCHER_WAIT_TIME_MS" ) for var in "${env_vars[@]}"; do diff --git a/telemetry_api/lib/telemetry_api/application.ex b/telemetry_api/lib/telemetry_api/application.ex index 6d62b0dea..d55bb3cf0 100644 --- a/telemetry_api/lib/telemetry_api/application.ex +++ b/telemetry_api/lib/telemetry_api/application.ex @@ -16,18 +16,15 @@ defmodule TelemetryApi.Application do # Start a worker by calling: TelemetryApi.Worker.start_link(arg) # {TelemetryApi.Worker, arg}, # Start to serve requests, typically the last entry - TelemetryApiWeb.Endpoint + TelemetryApiWeb.Endpoint, + TelemetryApi.Periodic.OperatorFetcher ] # See https://hexdocs.pm/elixir/Supervisor.html # for other strategies and supported options opts = [strategy: :one_for_one, name: TelemetryApi.Supervisor] - - # Now we fetch operators data from smart contract to fill db - with {:ok, pid} <- Supervisor.start_link(children, opts), - {:ok, _} <- TelemetryApi.Operators.fetch_all_operators() do - {:ok, pid} - end + + Supervisor.start_link(children, opts) end # Tell Phoenix to update the endpoint configuration diff --git a/telemetry_api/lib/telemetry_api/periodic/operator_fetcher.ex b/telemetry_api/lib/telemetry_api/periodic/operator_fetcher.ex new file mode 100644 index 000000000..e198e548a --- /dev/null +++ b/telemetry_api/lib/telemetry_api/periodic/operator_fetcher.ex @@ -0,0 +1,32 @@ +defmodule TelemetryApi.Periodic.OperatorFetcher do + use Task + alias TelemetryApi.Operators + + wait_time_str = System.get_env("OPERATOR_FETCHER_WAIT_TIME_MS") || + raise """ + environment variable OPERATOR_FETCHER_WAIT_TIME_MS is missing. + """ + + @wait_time_ms ( + case Integer.parse(wait_time_str) do + :error -> raise("OPERATOR_FETCHER_WAIT_TIME_MS is not a number") + {num, _} -> num + end + ) + + def start_link(_) do + Task.start_link(&poll_serivce/0) + end + + defp poll_serivce() do + receive do + after + @wait_time_ms -> + case Operators.fetch_all_operators() do + {:ok, _} -> :ok + {:error, message} -> IO.inspect "Couldn't fetch operators: #{IO.inspect message}" + end + poll_serivce() + end + end +end diff --git a/telemetry_api/start.sh b/telemetry_api/start.sh index b20a0bfae..41148952d 100755 --- a/telemetry_api/start.sh +++ b/telemetry_api/start.sh @@ -6,6 +6,7 @@ source .env env_vars=( "ENVIRONMENT" "ALIGNED_CONFIG_FILE" + "OPERATOR_FETCHER_WAIT_TIME_MS" ) for var in "${env_vars[@]}"; do From 2b9faaba3be7f7162ac48a0753b4fad5b4228488 Mon Sep 17 00:00:00 2001 From: Julian Ventura Date: Wed, 2 Oct 2024 17:40:43 -0300 Subject: [PATCH 27/55] Add operator test on BaseUrlOnly function --- operator/cmd/actions/utils_test.go | 46 ++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100644 operator/cmd/actions/utils_test.go diff --git a/operator/cmd/actions/utils_test.go b/operator/cmd/actions/utils_test.go new file mode 100644 index 000000000..1231585ca --- /dev/null +++ b/operator/cmd/actions/utils_test.go @@ -0,0 +1,46 @@ +package actions + +import ( + "testing" +) + +func TestBaseUrlOnlyHappyPath(t *testing.T) { + // Format ":///" + + urls := [...][2]string{ + {"http://localhost:8545/asdfoij2a7831has89%342jddav98j2748", "localhost:8545"}, + {"ws://test.com/23r2f98hkjva0udhvi1j%342jddav98j2748", "test.com"}, + {"http://localhost:8545", "localhost:8545"}, + } + + for _, pair := range urls { + url := pair[0] + expectedBaseUrl := pair[1] + + baseUrl, err := baseUrlOnly(url) + + if err != nil { + t.Errorf("Unexpected error for URL %s: %v", url, err) + } + + if baseUrl != expectedBaseUrl { + t.Errorf("Expected base URL %s, got %s for URL %s", expectedBaseUrl, baseUrl, url) + } + } +} + +func TestBaseUrlOnlyFailureCases(t *testing.T) { + + urls := [...]string{ + "localhost:8545/asdfoij2a7831has89%342jddav98j2748", + "this-is-all-wrong", + } + + for _, url := range urls { + baseUrl, err := baseUrlOnly(url) + + if err == nil { + t.Errorf("An error was expected, but received %s", baseUrl) + } + } +} From dd905f66202dcfc5c28f58a6a0ac9dd8d2443bfd Mon Sep 17 00:00:00 2001 From: Julian Ventura Date: Wed, 2 Oct 2024 18:08:16 -0300 Subject: [PATCH 28/55] Remove endpoint json body keys requirement --- telemetry_api/lib/telemetry_api/utils.ex | 30 ------------------- .../controllers/operator_controller.ex | 12 ++++---- 2 files changed, 6 insertions(+), 36 deletions(-) diff --git a/telemetry_api/lib/telemetry_api/utils.ex b/telemetry_api/lib/telemetry_api/utils.ex index 7c5cd34ca..b9a43f2aa 100644 --- a/telemetry_api/lib/telemetry_api/utils.ex +++ b/telemetry_api/lib/telemetry_api/utils.ex @@ -63,34 +63,4 @@ defmodule TelemetryApi.Utils do |> put_resp_content_type("application/json") |> send_resp(:bad_request, Jason.encode!(%{error: message})) end - - @doc """ - Validates the existance of a given list of keys in provided params map. - Extra keys will be filtered out. - - ## Examples - - iex> required_keys = ["hello", "bye"] - iex> params = %{"hello": 4, "bye": 2, "dog": 100} - iex> params_validation(required_keys, params) - {:ok, %{"hello": 4, "bye": 2}} - - iex> required_keys = ["hello", "bye"] - iex> params = %{"hello": 4} - iex> params_validation(required_keys, params) - {:error, string} - """ - def params_validation(required_keys, params) do - # Check if all required keys are present - missing_keys = Enum.filter(required_keys, &(!Map.has_key?(params, &1))) - - if Enum.empty?(missing_keys) do - # Filter the params to only include the required keys - filtered_params = Map.take(params, required_keys) - {:ok, filtered_params} - else - {:error, "Missing required parameters: #{Enum.join(missing_keys, ", ")}"} - end - end - end diff --git a/telemetry_api/lib/telemetry_api_web/controllers/operator_controller.ex b/telemetry_api/lib/telemetry_api_web/controllers/operator_controller.ex index 230760631..f941402a6 100644 --- a/telemetry_api/lib/telemetry_api_web/controllers/operator_controller.ex +++ b/telemetry_api/lib/telemetry_api_web/controllers/operator_controller.ex @@ -22,12 +22,12 @@ defmodule TelemetryApiWeb.OperatorController do end def create(conn, params) do - with {:ok, op_params} <- Utils.params_validation(@create_params, params), - {:ok, %Operator{} = operator} <- Operators.update_operator(op_params) do - conn - |> put_status(:created) - |> put_resp_header("location", ~p"/api/operators/#{operator}") - |> render(:show, operator: operator) + params = Map.take(params, @create_params) + with {:ok, %Operator{} = operator} <- Operators.update_operator(params) do + conn + |> put_status(:created) + |> put_resp_header("location", ~p"/api/operators/#{operator}") + |> render(:show, operator: operator) else {:error, message} -> Utils.return_error(conn, message) From 4e66b2be051d7b05c7aeb3c0e230165daf571c1c Mon Sep 17 00:00:00 2001 From: Julian Ventura Date: Wed, 2 Oct 2024 18:14:13 -0300 Subject: [PATCH 29/55] Format golang operator code --- operator/cmd/actions/start.go | 49 +++++++++++++++++------------------ 1 file changed, 24 insertions(+), 25 deletions(-) diff --git a/operator/cmd/actions/start.go b/operator/cmd/actions/start.go index d7822485c..7c0c941db 100644 --- a/operator/cmd/actions/start.go +++ b/operator/cmd/actions/start.go @@ -26,7 +26,6 @@ var StartCommand = &cli.Command{ Action: operatorMain, } - func updateTelemetryService(operator *operator.Operator, ctx *cli.Context, operatorConfig *config.OperatorConfig) error { // hash version hash := sha3.NewLegacyKeccak256() @@ -40,30 +39,30 @@ func updateTelemetryService(operator *operator.Operator, ctx *cli.Context, opera if err != nil { return err } - ethRpcUrl, err := baseUrlOnly(operatorConfig.BaseConfig.EthRpcUrl) - if err != nil { - return err - } - ethRpcUrlFallback, err := baseUrlOnly(operatorConfig.BaseConfig.EthRpcUrlFallback) - if err != nil { - return err - } - ethWsUrl, err := baseUrlOnly(operatorConfig.BaseConfig.EthWsUrl) - if err != nil { - return err - } - ethWsUrlFallback, err := baseUrlOnly(operatorConfig.BaseConfig.EthWsUrlFallback) - if err != nil { - return err - } + ethRpcUrl, err := baseUrlOnly(operatorConfig.BaseConfig.EthRpcUrl) + if err != nil { + return err + } + ethRpcUrlFallback, err := baseUrlOnly(operatorConfig.BaseConfig.EthRpcUrlFallback) + if err != nil { + return err + } + ethWsUrl, err := baseUrlOnly(operatorConfig.BaseConfig.EthWsUrl) + if err != nil { + return err + } + ethWsUrlFallback, err := baseUrlOnly(operatorConfig.BaseConfig.EthWsUrlFallback) + if err != nil { + return err + } body := map[string]interface{}{ - "version": ctx.App.Version, - "signature": signature, - "eth_rpc_url": ethRpcUrl, - "eth_rpc_url_fallback": ethRpcUrlFallback, - "eth_ws_url": ethWsUrl, - "eth_ws_url_fallback": ethWsUrlFallback, + "version": ctx.App.Version, + "signature": signature, + "eth_rpc_url": ethRpcUrl, + "eth_rpc_url_fallback": ethRpcUrlFallback, + "eth_ws_url": ethWsUrl, + "eth_ws_url_fallback": ethWsUrlFallback, } bodyBuffer := new(bytes.Buffer) @@ -86,7 +85,7 @@ func updateTelemetryService(operator *operator.Operator, ctx *cli.Context, opera operator.Logger.Warn("Error sending version to operator tracker server: ", "status_code", res.StatusCode) } - return nil + return nil } func operatorMain(ctx *cli.Context) error { @@ -102,7 +101,7 @@ func operatorMain(ctx *cli.Context) error { return err } - err = updateTelemetryService(operator, ctx, operatorConfig) + err = updateTelemetryService(operator, ctx, operatorConfig) if err != nil { return err } From 3d47d50da40ae8a86c6f3ed88d6d691b3a8b7d23 Mon Sep 17 00:00:00 2001 From: avilagaston9 Date: Thu, 3 Oct 2024 10:13:45 -0300 Subject: [PATCH 30/55] docs: add telemetry_create_env to readme --- telemetry_api/README.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/telemetry_api/README.md b/telemetry_api/README.md index 1ba8b3794..3640c501e 100644 --- a/telemetry_api/README.md +++ b/telemetry_api/README.md @@ -31,6 +31,14 @@ make telemetry_clean_db ## Run Server +First you need to manually set the `telemetry_api/.env` file. + +To use `telemetry_api/.env.dev`, run: + +```shell +make telemetry_create_env +``` + To start your Phoenix server: ```shell From e911d642771db5869a9af7eb5c6960e11b445679 Mon Sep 17 00:00:00 2001 From: avilagaston9 Date: Thu, 3 Oct 2024 10:20:50 -0300 Subject: [PATCH 31/55] refactor: remove dead code --- .../controllers/operator_controller.ex | 29 +++++-------------- 1 file changed, 7 insertions(+), 22 deletions(-) diff --git a/telemetry_api/lib/telemetry_api_web/controllers/operator_controller.ex b/telemetry_api/lib/telemetry_api_web/controllers/operator_controller.ex index b1b5d4bed..077a8c7d7 100644 --- a/telemetry_api/lib/telemetry_api_web/controllers/operator_controller.ex +++ b/telemetry_api/lib/telemetry_api_web/controllers/operator_controller.ex @@ -8,9 +8,9 @@ defmodule TelemetryApiWeb.OperatorController do defp return_error(conn, message) do conn - |> put_status(:bad_request) - |> put_resp_content_type("application/json") - |> send_resp(:bad_request, Jason.encode!(%{error: message})) + |> put_status(:bad_request) + |> put_resp_content_type("application/json") + |> send_resp(:bad_request, Jason.encode!(%{error: message})) end def index(conn, _params) do @@ -22,9 +22,10 @@ defmodule TelemetryApiWeb.OperatorController do case Operators.update_operator_version(operator_params) do {:ok, %Operator{} = operator} -> conn - |> put_status(:created) - |> put_resp_header("location", ~p"/api/operators/#{operator}") - |> render(:show, operator: operator) + |> put_status(:created) + |> put_resp_header("location", ~p"/api/operators/#{operator}") + |> render(:show, operator: operator) + {:error, message} -> return_error(conn, message) end @@ -42,20 +43,4 @@ defmodule TelemetryApiWeb.OperatorController do |> render("404.json", %{}) end end - - # defp update(conn, operator, operator_params) do - # with {:ok, %Operator{} = operator} <- Operators.update_operator(operator, operator_params) do - # conn - # |> put_status(:ok) - # |> render(:show, operator: operator) - # end - # end - - # def delete(conn, %{"id" => id}) do - # operator = Operators.get_operator!(id) - - # with {:ok, %Operator{}} <- Operators.delete_operator(operator) do - # send_resp(conn, :no_content, "") - # end - # end end From d6dedbdc1bd52c6c7e8e8d5a28988d78ddfd2890 Mon Sep 17 00:00:00 2001 From: avilagaston9 Date: Thu, 3 Oct 2024 10:35:45 -0300 Subject: [PATCH 32/55] refactor: rename clean_list_errors to check_list_status --- telemetry_api/lib/telemetry_api/operators.ex | 2 +- telemetry_api/lib/telemetry_api/utils.ex | 14 +++++++------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/telemetry_api/lib/telemetry_api/operators.ex b/telemetry_api/lib/telemetry_api/operators.ex index 16925542e..5b16154c8 100644 --- a/telemetry_api/lib/telemetry_api/operators.ex +++ b/telemetry_api/lib/telemetry_api/operators.ex @@ -65,7 +65,7 @@ defmodule TelemetryApi.Operators do |> Repo.insert_or_update() end end) - |> TelemetryApi.Utils.clean_list_errors("Error fetching operators metadata") + |> TelemetryApi.Utils.check_list_status("Error fetching operators metadata") end end diff --git a/telemetry_api/lib/telemetry_api/utils.ex b/telemetry_api/lib/telemetry_api/utils.ex index 5ccb9efab..073a7a7df 100644 --- a/telemetry_api/lib/telemetry_api/utils.ex +++ b/telemetry_api/lib/telemetry_api/utils.ex @@ -28,20 +28,20 @@ defmodule TelemetryApi.Utils do end @doc """ - Unwraps inner element status + Unwraps inner element status ## Examples - iex> list = [{:ok, 2}, {:ok, 3}] - iex> clean_list_errors(list, error_message) + iex> error_message = "Error found on list" + iex> list = [{:ok, 2}, {:ok, 3}] + iex> check_list_status(list, error_message) {:ok, list} - iex> list = [{:ok, 2}, {:ok, 3}, {:error, "this is an error"}] - iex> message = "Error found on list" - iex> clean_list_errors(list, error_message) + iex> list = [{:ok, 2}, {:ok, 3}, {:error, "this is an error"}] + iex> check_list_status(list, error_message) {:error, "Error found on list"} """ - def clean_list_errors(list, error_message) do + def check_list_status(list, error_message) do case Enum.find(list, fn {status, _} -> status == :error end) do nil -> {:ok, Enum.map(list, fn {:ok, value} -> value end)} From b58580e4972396998963dd39435d48922e6f6629 Mon Sep 17 00:00:00 2001 From: avilagaston9 Date: Thu, 3 Oct 2024 12:12:57 -0300 Subject: [PATCH 33/55] refactor: change how we invoke get_operator_state --- .../telemetry_api/contract_managers/operator_state_retriever.ex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/telemetry_api/lib/telemetry_api/contract_managers/operator_state_retriever.ex b/telemetry_api/lib/telemetry_api/contract_managers/operator_state_retriever.ex index e33b6eef3..c558d2d84 100644 --- a/telemetry_api/lib/telemetry_api/contract_managers/operator_state_retriever.ex +++ b/telemetry_api/lib/telemetry_api/contract_managers/operator_state_retriever.ex @@ -69,7 +69,7 @@ defmodule TelemetryApi.ContractManagers.OperatorStateRetriever do quorum_numbers = <<0>> response = - __MODULE__.get_operator_state(@registry_coordinator_address, quorum_numbers, block_number) + get_operator_state(@registry_coordinator_address, quorum_numbers, block_number) |> Ethers.call() case response do From 2b5c22b3ee43d162ea6c37906311ee002b66bcc0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Avila=20Gast=C3=B3n?= <72628438+avilagaston9@users.noreply.github.com> Date: Thu, 3 Oct 2024 12:51:57 -0300 Subject: [PATCH 34/55] refactor: improve tracker error handling (#1141) --- telemetry_api/lib/telemetry_api/operators.ex | 39 +++-- .../lib/telemetry_api/signature_verifier.ex | 10 +- .../lib/telemetry_api/trace_store.ex | 9 +- telemetry_api/lib/telemetry_api/traces.ex | 143 +++++++----------- .../controllers/fallback_controller.ex | 8 +- .../controllers/operator_controller.ex | 31 +--- .../controllers/trace_controller.ex | 8 +- 7 files changed, 111 insertions(+), 137 deletions(-) diff --git a/telemetry_api/lib/telemetry_api/operators.ex b/telemetry_api/lib/telemetry_api/operators.ex index 1a78efe51..7b1bd6130 100644 --- a/telemetry_api/lib/telemetry_api/operators.ex +++ b/telemetry_api/lib/telemetry_api/operators.ex @@ -29,30 +29,40 @@ defmodule TelemetryApi.Operators do ## Examples iex> get_operator("some_address"}) - %Operator{} + {:ok, %Operator{}} iex> get_operator("non_existent_address") - nil - + {:error, :not_found, "Operator not found for address: non_existent_address"} """ def get_operator(address) do - Repo.get(Operator, address) + case Repo.get(Operator, address) do + nil -> + IO.inspect("Operator not found for address: #{address}") + {:error, :not_found, "Operator not found for address: #{address}"} + + operator -> + {:ok, operator} + end end - @doc""" + @doc """ Get a single operator by operator id. ## Examples iex> get_operator_by_id("some_id") - %Operator{} + {:ok, %Operator{}} iex> get_operator_by_id("non_existent_id") - nil + {:error, :not_found, "Operator not found for id: non_existent_id"} """ def get_operator_by_id(id) do query = from(o in Operator, where: o.id == ^id) - Repo.one(query) + + case Repo.one(query) do + nil -> {:error, :not_found, "Operator not found for id: {id}"} + operator -> {:ok, operator} + end end @doc """ @@ -83,8 +93,7 @@ defmodule TelemetryApi.Operators do end end - - #Adds operator metadata to received operator. + # Adds operator metadata to received operator. ### Examples @@ -117,7 +126,7 @@ defmodule TelemetryApi.Operators do {:ok, %Ecto.Changeset{}} iex> update_operator_version(%{field: bad_value}) - {:error, string} + {:error, "Some status", "Some message"} """ def update_operator_version(attrs \\ %{}) do @@ -129,8 +138,12 @@ defmodule TelemetryApi.Operators do } case Repo.get(Operator, address) do - nil -> {:error, "Provided address does not correspond to any registered operator"} - operator -> operator |> Operator.changeset(changes) |> Repo.insert_or_update() + nil -> + {:error, :bad_request, + "Provided address does not correspond to any registered operator"} + + operator -> + operator |> Operator.changeset(changes) |> Repo.insert_or_update() end end end diff --git a/telemetry_api/lib/telemetry_api/signature_verifier.ex b/telemetry_api/lib/telemetry_api/signature_verifier.ex index 8f5eba4ce..071ad91fe 100644 --- a/telemetry_api/lib/telemetry_api/signature_verifier.ex +++ b/telemetry_api/lib/telemetry_api/signature_verifier.ex @@ -10,9 +10,9 @@ defmodule SignatureVerifier do # Recover the public key from the signature and hashed version defp recover_public_key(hash, signature, recovery_id) do - case ExSecp256k1.recover_compact(hash, signature, recovery_id) do + case ExSecp256k1.recover_compact(hash, signature, recovery_id) do {:ok, public_key} -> {:ok, public_key} - _error -> {:error, "Failed to recover public key"} + _error -> {:error, :bad_request, "Failed to recover public key"} end end @@ -49,8 +49,10 @@ defmodule SignatureVerifier do recovery_id = Binary.decode_unsigned(binary_part(binary_signature, signature_len - 1, 1)) with {:ok, address} <- recover_public_key(version_hash, rs, recovery_id) do - addr = public_key_to_address(address) - |> Base.encode16(case: :lower) + addr = + public_key_to_address(address) + |> Base.encode16(case: :lower) + {:ok, addr} end end diff --git a/telemetry_api/lib/telemetry_api/trace_store.ex b/telemetry_api/lib/telemetry_api/trace_store.ex index 79dc85a1c..0e0e43ffc 100644 --- a/telemetry_api/lib/telemetry_api/trace_store.ex +++ b/telemetry_api/lib/telemetry_api/trace_store.ex @@ -16,7 +16,14 @@ defmodule TraceStore do # Retrieve the trace by merkle_root def get_trace(merkle_root) do Agent.get(__MODULE__, fn state -> - Map.get(state, merkle_root) + case Map.get(state, merkle_root) do + nil -> + IO.inspect("Context not found for #{merkle_root}") + {:error, :not_found, "Context not found for #{merkle_root}"} + + trace -> + {:ok, trace} + end end) end diff --git a/telemetry_api/lib/telemetry_api/traces.ex b/telemetry_api/lib/telemetry_api/traces.ex index a01ccffcc..1096203ad 100644 --- a/telemetry_api/lib/telemetry_api/traces.ex +++ b/telemetry_api/lib/telemetry_api/traces.ex @@ -20,7 +20,7 @@ defmodule TelemetryApi.Traces do iex> merkle_root = "0x1234567890abcdef" iex> create_task_trace(merkle_root) - {:ok, "merkle_root"} + :ok """ def create_task_trace(merkle_root) do # Get total stake @@ -47,7 +47,7 @@ defmodule TelemetryApi.Traces do }) IO.inspect("New task trace with merkle_root: #{IO.inspect(merkle_root)}") - {:ok, merkle_root} + :ok end end @@ -62,29 +62,40 @@ defmodule TelemetryApi.Traces do :ok """ def register_operator_response(merkle_root, operator_id) do - with operator <- Operators.get_operator_by_id(operator_id) do - add_event( - merkle_root, + with {:ok, operator} <- Operators.get_operator_by_id(operator_id), + {:ok, trace} <- set_current_trace(merkle_root) do + operator_stake = String.to_integer(operator.stake) + new_stake = trace.current_stake + operator_stake + new_stake_fraction = new_stake / trace.total_stake + operator_stake_fraction = operator_stake / trace.total_stake + + Tracer.add_event( "Operator Response: " <> operator.name, [ {:merkle_root, merkle_root}, {:operator_id, operator_id}, {:name, operator.name}, {:address, operator.address}, - {:operator_stake, operator.stake} - ], - String.to_integer(operator.stake) + {:operator_stake, operator_stake}, + {:current_stake, new_stake}, + {:current_stake_fraction, new_stake_fraction}, + {:operator_stake_fraction, operator_stake_fraction} + ] ) - trace = TraceStore.get_trace(merkle_root) responses = trace.responses ++ [operator_id] - TraceStore.store_trace(merkle_root, %{trace | responses: responses}) + + TraceStore.store_trace(merkle_root, %{ + trace + | responses: responses, + current_stake: new_stake + }) IO.inspect( "Operator response included. merkle_root: #{IO.inspect(merkle_root)} operator_id: #{IO.inspect(operator_id)}" ) - {:ok, operator_id} + :ok end end @@ -98,15 +109,11 @@ defmodule TelemetryApi.Traces do :ok """ def quorum_reached(merkle_root) do - add_event( - merkle_root, - "Quorum Reached", - [] - ) - - IO.inspect("Reached quorum registered. merkle_root: #{IO.inspect(merkle_root)}") - - {:ok, merkle_root} + with {:ok, _trace} <- set_current_trace(merkle_root) do + Tracer.add_event("Quorum Reached", []) + IO.inspect("Reached quorum registered. merkle_root: #{IO.inspect(merkle_root)}") + :ok + end end @doc """ @@ -120,17 +127,18 @@ defmodule TelemetryApi.Traces do :ok """ def task_error(merkle_root, error) do - add_event( - merkle_root, - "Batch verification failed", - [ - {:status, "error"}, - {:error, error} - ] - ) - - IO.inspect("Task error registered. merkle_root: #{IO.inspect(merkle_root)}") - {:ok, merkle_root} + with {:ok, _trace} <- set_current_trace(merkle_root) do + Tracer.add_event( + "Batch verification failed", + [ + {:status, "error"}, + {:error, error} + ] + ) + + IO.inspect("Task error registered. merkle_root: #{IO.inspect(merkle_root)}") + :ok + end end @doc """ @@ -145,74 +153,37 @@ defmodule TelemetryApi.Traces do :ok """ def finish_task_trace(merkle_root) do - case TraceStore.get_trace(merkle_root) do - nil -> - IO.inspect("Context not found for #{merkle_root}") - {:error, "Context not found for #{merkle_root}"} - - trace -> - Ctx.attach(trace.context) - Tracer.set_current_span(trace.parent_span) + with {:ok, trace} <- set_current_trace(merkle_root) do + missing_operators = + Operators.list_operators() |> Enum.filter(fn o -> o.id not in trace.responses end) - missing_operators = - Operators.list_operators() |> Enum.filter(fn o -> o.id not in trace.responses end) + add_missing_operators(missing_operators) - add_missing_operators(merkle_root, missing_operators) + Tracer.set_attributes(%{status: "completed"}) - Tracer.set_attributes(%{status: "completed"}) + Tracer.end_span() - Tracer.end_span(trace.parent_span) - - # Clean up the context from the Agent - TraceStore.delete_trace(merkle_root) - IO.inspect("Finished task trace with merkle_root: #{IO.inspect(merkle_root)}.") - :ok + # Clean up the context from the Agent + TraceStore.delete_trace(merkle_root) + IO.inspect("Finished task trace with merkle_root: #{IO.inspect(merkle_root)}.") + :ok end end - defp add_missing_operators(_merkle_root, []), do: :ok + defp add_missing_operators([]), do: :ok - defp add_missing_operators(merkle_root, missing_operators) do + defp add_missing_operators(missing_operators) do missing_operators = missing_operators |> Enum.map(fn o -> o.name end) |> Enum.join(";") - add_event(merkle_root, "Missing Operators", [{:operators, missing_operators}]) + Tracer.add_event("Missing Operators", [{:operators, missing_operators}]) end - defp add_event(merkle_root, event_name, event_attributes, operator_stake) do - case TraceStore.get_trace(merkle_root) do - nil -> - IO.inspect("Context not found for #{merkle_root}") - {:error, "Context not found for #{merkle_root}"} - - trace -> - Ctx.attach(trace.context) - Tracer.set_current_span(trace.parent_span) - - new_stake = trace.current_stake + operator_stake - new_stake_fraction = new_stake / trace.total_stake - operator_stake_fraction = operator_stake / trace.total_stake - - TraceStore.store_trace(merkle_root, %Trace{ - trace | - current_stake: new_stake - }) - - Tracer.add_event(event_name, event_attributes ++ [{:current_stake, new_stake}, {:current_stake_fraction, new_stake_fraction}, {:operator_stake_fraction, operator_stake_fraction}]) - end - end - - defp add_event(merkle_root, event_name, event_attributes) do - case TraceStore.get_trace(merkle_root) do - nil -> - IO.inspect("Context not found for #{merkle_root}") - {:error, "Context not found for #{merkle_root}"} - - trace -> - Ctx.attach(trace.context) - Tracer.set_current_span(trace.parent_span) - - Tracer.add_event(event_name, event_attributes) + defp set_current_trace(merkle_root) do + with {:ok, trace} <- TraceStore.get_trace(merkle_root) do + Ctx.attach(trace.context) + Tracer.set_current_span(trace.parent_span) + {:ok, trace} end end end diff --git a/telemetry_api/lib/telemetry_api_web/controllers/fallback_controller.ex b/telemetry_api/lib/telemetry_api_web/controllers/fallback_controller.ex index 958b44f97..94ecbee59 100644 --- a/telemetry_api/lib/telemetry_api_web/controllers/fallback_controller.ex +++ b/telemetry_api/lib/telemetry_api_web/controllers/fallback_controller.ex @@ -14,12 +14,10 @@ defmodule TelemetryApiWeb.FallbackController do |> render(:error, changeset: changeset) end - # This clause is an example of how to handle resources that cannot be found. - def call(conn, {:error, :not_found}) do + def call(conn, {:error, status, message}) do conn - |> put_status(:not_found) - |> put_view(html: TelemetryApiWeb.ErrorHTML, json: TelemetryApiWeb.ErrorJSON) - |> render(:"404") + |> put_resp_content_type("application/json") + |> send_resp(status, Jason.encode!(%{error: message})) end def call(conn, {:error, message}) do diff --git a/telemetry_api/lib/telemetry_api_web/controllers/operator_controller.ex b/telemetry_api/lib/telemetry_api_web/controllers/operator_controller.ex index b1b5d4bed..14603d011 100644 --- a/telemetry_api/lib/telemetry_api_web/controllers/operator_controller.ex +++ b/telemetry_api/lib/telemetry_api_web/controllers/operator_controller.ex @@ -6,40 +6,23 @@ defmodule TelemetryApiWeb.OperatorController do action_fallback TelemetryApiWeb.FallbackController - defp return_error(conn, message) do - conn - |> put_status(:bad_request) - |> put_resp_content_type("application/json") - |> send_resp(:bad_request, Jason.encode!(%{error: message})) - end - def index(conn, _params) do operators = Operators.list_operators() render(conn, :index, operators: operators) end def create(conn, operator_params) do - case Operators.update_operator_version(operator_params) do - {:ok, %Operator{} = operator} -> - conn - |> put_status(:created) - |> put_resp_header("location", ~p"/api/operators/#{operator}") - |> render(:show, operator: operator) - {:error, message} -> - return_error(conn, message) + with {:ok, %Operator{} = operator} <- Operators.update_operator_version(operator_params) do + conn + |> put_status(:created) + |> put_resp_header("location", ~p"/api/operators/#{operator}") + |> render(:show, operator: operator) end end def show(conn, %{"id" => address}) do - case Operators.get_operator(address) do - %Operator{} = operator -> - render(conn, :show, operator: operator) - - nil -> - conn - |> put_status(:not_found) - |> put_view(TelemetryApiWeb.ErrorJSON) - |> render("404.json", %{}) + with {%Operator{} = operator} <- Operators.get_operator(address) do + render(conn, :show, operator: operator) end end diff --git a/telemetry_api/lib/telemetry_api_web/controllers/trace_controller.ex b/telemetry_api/lib/telemetry_api_web/controllers/trace_controller.ex index 27091f237..6e72237ea 100644 --- a/telemetry_api/lib/telemetry_api_web/controllers/trace_controller.ex +++ b/telemetry_api/lib/telemetry_api_web/controllers/trace_controller.ex @@ -10,7 +10,7 @@ defmodule TelemetryApiWeb.TraceController do Method: POST initTaskTrace """ def create_task_trace(conn, %{"merkle_root" => merkle_root}) do - with {:ok, merkle_root} <- Traces.create_task_trace(merkle_root) do + with :ok <- Traces.create_task_trace(merkle_root) do conn |> put_status(:created) |> render(:show_merkle, merkle_root: merkle_root) @@ -25,7 +25,7 @@ defmodule TelemetryApiWeb.TraceController do "merkle_root" => merkle_root, "operator_id" => operator_id }) do - with {:ok, operator_id} <- Traces.register_operator_response(merkle_root, operator_id) do + with :ok <- Traces.register_operator_response(merkle_root, operator_id) do conn |> put_status(:ok) |> render(:show_operator, operator_id: operator_id) @@ -37,7 +37,7 @@ defmodule TelemetryApiWeb.TraceController do Method: POST quorumReached """ def quorum_reached(conn, %{"merkle_root" => merkle_root}) do - with {:ok, merkle_root} <- Traces.quorum_reached(merkle_root) do + with :ok <- Traces.quorum_reached(merkle_root) do conn |> put_status(:ok) |> render(:show_merkle, merkle_root: merkle_root) @@ -49,7 +49,7 @@ defmodule TelemetryApiWeb.TraceController do Method: POST taskError """ def task_error(conn, %{"merkle_root" => merkle_root, "error" => error}) do - with {:ok, merkle_root} <- Traces.task_error(merkle_root, error) do + with :ok <- Traces.task_error(merkle_root, error) do conn |> put_status(:ok) |> render(:show_merkle, merkle_root: merkle_root) From 46fa064dc78535ed5950cc72ff7717268e81ced1 Mon Sep 17 00:00:00 2001 From: avilagaston9 Date: Thu, 3 Oct 2024 12:57:12 -0300 Subject: [PATCH 35/55] add telemetry_run_db to telemetry_start target --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 958668b97..71f26b253 100644 --- a/Makefile +++ b/Makefile @@ -758,7 +758,7 @@ open_telemetry_start: ## Run open telemetry services using telemetry-docker-comp @echo "Running telemetry..." @docker compose -f telemetry-docker-compose.yaml up -d -telemetry_start: telemetry_ecto_migrate ## Run Telemetry API +telemetry_start: telemetry_run_db telemetry_ecto_migrate ## Run Telemetry API @cd telemetry_api && \ ./start.sh From 42dc80148b41b0df4b9f49ad0ecd8c1c56405e35 Mon Sep 17 00:00:00 2001 From: Julian Ventura Date: Thu, 3 Oct 2024 15:08:16 -0300 Subject: [PATCH 36/55] Fix operator_fetcher error message and method name --- .../lib/telemetry_api/periodic/operator_fetcher.ex | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/telemetry_api/lib/telemetry_api/periodic/operator_fetcher.ex b/telemetry_api/lib/telemetry_api/periodic/operator_fetcher.ex index e198e548a..9df9965dd 100644 --- a/telemetry_api/lib/telemetry_api/periodic/operator_fetcher.ex +++ b/telemetry_api/lib/telemetry_api/periodic/operator_fetcher.ex @@ -9,7 +9,7 @@ defmodule TelemetryApi.Periodic.OperatorFetcher do @wait_time_ms ( case Integer.parse(wait_time_str) do - :error -> raise("OPERATOR_FETCHER_WAIT_TIME_MS is not a number") + :error -> raise("OPERATOR_FETCHER_WAIT_TIME_MS is not a number, received: #{wait_time_str}") {num, _} -> num end ) @@ -18,7 +18,7 @@ defmodule TelemetryApi.Periodic.OperatorFetcher do Task.start_link(&poll_serivce/0) end - defp poll_serivce() do + defp poll_service() do receive do after @wait_time_ms -> @@ -26,7 +26,7 @@ defmodule TelemetryApi.Periodic.OperatorFetcher do {:ok, _} -> :ok {:error, message} -> IO.inspect "Couldn't fetch operators: #{IO.inspect message}" end - poll_serivce() + poll_service() end end end From d58c300101f8829edf434c54a009d4d4f088d6a8 Mon Sep 17 00:00:00 2001 From: JuArce <52429267+JuArce@users.noreply.github.com> Date: Thu, 3 Oct 2024 17:04:23 -0300 Subject: [PATCH 37/55] chore: use port 4001 instead of 4000 --- config-files/config-operator-1.yaml | 2 +- config-files/config-operator-2.yaml | 2 +- config-files/config-operator-3.yaml | 2 +- config-files/config.yaml | 2 +- telemetry_api/config/dev.exs | 2 +- telemetry_api/config/runtime.exs | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/config-files/config-operator-1.yaml b/config-files/config-operator-1.yaml index 2682ad594..a087e6b27 100644 --- a/config-files/config-operator-1.yaml +++ b/config-files/config-operator-1.yaml @@ -22,7 +22,7 @@ bls: ## Operator Configurations operator: aggregator_rpc_server_ip_port_address: localhost:8090 - operator_tracker_ip_port_address: http://localhost:4000 + operator_tracker_ip_port_address: http://localhost:4001 address: 0x70997970C51812dc3A010C7d01b50e0d17dc79C8 earnings_receiver_address: 0x70997970C51812dc3A010C7d01b50e0d17dc79C8 delegation_approver_address: "0x0000000000000000000000000000000000000000" diff --git a/config-files/config-operator-2.yaml b/config-files/config-operator-2.yaml index 544130412..170707e24 100644 --- a/config-files/config-operator-2.yaml +++ b/config-files/config-operator-2.yaml @@ -22,7 +22,7 @@ bls: ## Operator Configurations operator: aggregator_rpc_server_ip_port_address: localhost:8090 - operator_tracker_ip_port_address: http://localhost:4000 + operator_tracker_ip_port_address: http://localhost:4001 address: 0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC earnings_receiver_address: 0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC delegation_approver_address: "0x0000000000000000000000000000000000000000" diff --git a/config-files/config-operator-3.yaml b/config-files/config-operator-3.yaml index 314290aa5..1105a54d5 100644 --- a/config-files/config-operator-3.yaml +++ b/config-files/config-operator-3.yaml @@ -22,7 +22,7 @@ bls: ## Operator Configurations operator: aggregator_rpc_server_ip_port_address: localhost:8090 - operator_tracker_ip_port_address: http://localhost:4000 + operator_tracker_ip_port_address: http://localhost:4001 address: 0x90F79bf6EB2c4f870365E785982E1f101E93b906 earnings_receiver_address: 0x90F79bf6EB2c4f870365E785982E1f101E93b906 delegation_approver_address: "0x0000000000000000000000000000000000000000" diff --git a/config-files/config.yaml b/config-files/config.yaml index b99bf0b6f..6d7fc68bc 100644 --- a/config-files/config.yaml +++ b/config-files/config.yaml @@ -39,7 +39,7 @@ aggregator: ## Operator Configurations operator: aggregator_rpc_server_ip_port_address: localhost:8090 - operator_tracker_ip_port_address: http://localhost:3030 + operator_tracker_ip_port_address: http://localhost:4001 address: 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266 earnings_receiver_address: 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266 delegation_approver_address: "0x0000000000000000000000000000000000000000" diff --git a/telemetry_api/config/dev.exs b/telemetry_api/config/dev.exs index fdbf46dbd..ac81f1d9b 100644 --- a/telemetry_api/config/dev.exs +++ b/telemetry_api/config/dev.exs @@ -20,7 +20,7 @@ config :telemetry_api, TelemetryApi.Repo, config :telemetry_api, TelemetryApiWeb.Endpoint, # Binding to loopback ipv4 address prevents access from other machines. # Change to `ip: {0, 0, 0, 0}` to allow access from other machines. - http: [ip: {127, 0, 0, 1}, port: 4000], + http: [ip: {127, 0, 0, 1}, port: 4001], check_origin: false, code_reloader: true, debug_errors: true, diff --git a/telemetry_api/config/runtime.exs b/telemetry_api/config/runtime.exs index 040a056d2..005e68aad 100644 --- a/telemetry_api/config/runtime.exs +++ b/telemetry_api/config/runtime.exs @@ -49,7 +49,7 @@ if config_env() == :prod do """ host = System.get_env("PHX_HOST") || "example.com" - port = String.to_integer(System.get_env("PORT") || "4000") + port = String.to_integer(System.get_env("PORT") || "4001") config :telemetry_api, :dns_cluster_query, System.get_env("DNS_CLUSTER_QUERY") From 4a1578accf767cb2100908e6f4b1936af5aa15e3 Mon Sep 17 00:00:00 2001 From: JuArce <52429267+JuArce@users.noreply.github.com> Date: Thu, 3 Oct 2024 19:07:10 -0300 Subject: [PATCH 38/55] chore: disable dashboard --- telemetry_api/config/dev.exs | 2 +- .../lib/telemetry_api_web/endpoint.ex | 6 ++--- telemetry_api/lib/telemetry_api_web/router.ex | 24 +++++++++---------- 3 files changed, 16 insertions(+), 16 deletions(-) diff --git a/telemetry_api/config/dev.exs b/telemetry_api/config/dev.exs index ac81f1d9b..59f51fd6a 100644 --- a/telemetry_api/config/dev.exs +++ b/telemetry_api/config/dev.exs @@ -51,7 +51,7 @@ config :telemetry_api, TelemetryApiWeb.Endpoint, # different ports. # Enable dev routes for dashboard and mailbox -config :telemetry_api, dev_routes: true +# config :telemetry_api, dev_routes: true # Do not include metadata nor timestamps in development logs config :logger, :console, format: "[$level] $message\n" diff --git a/telemetry_api/lib/telemetry_api_web/endpoint.ex b/telemetry_api/lib/telemetry_api_web/endpoint.ex index 861505826..897e4939d 100644 --- a/telemetry_api/lib/telemetry_api_web/endpoint.ex +++ b/telemetry_api/lib/telemetry_api_web/endpoint.ex @@ -32,9 +32,9 @@ defmodule TelemetryApiWeb.Endpoint do plug Phoenix.Ecto.CheckRepoStatus, otp_app: :telemetry_api end - plug Phoenix.LiveDashboard.RequestLogger, - param_key: "request_logger", - cookie_key: "request_logger" + # plug Phoenix.LiveDashboard.RequestLogger, + # param_key: "request_logger", + # cookie_key: "request_logger" plug Plug.RequestId plug Plug.Telemetry, event_prefix: [:phoenix, :endpoint] diff --git a/telemetry_api/lib/telemetry_api_web/router.ex b/telemetry_api/lib/telemetry_api_web/router.ex index 6b17f10b3..704446a60 100644 --- a/telemetry_api/lib/telemetry_api_web/router.ex +++ b/telemetry_api/lib/telemetry_api_web/router.ex @@ -16,18 +16,18 @@ defmodule TelemetryApiWeb.Router do end # Enable LiveDashboard in development - if Application.compile_env(:telemetry_api, :dev_routes) do - # If you want to use the LiveDashboard in production, you should put - # it behind authentication and allow only admins to access it. - # If your application does not have an admins-only section yet, - # you can use Plug.BasicAuth to set up some basic authentication - # as long as you are also using SSL (which you should anyway). - import Phoenix.LiveDashboard.Router + # if Application.compile_env(:telemetry_api, :dev_routes) do + # # If you want to use the LiveDashboard in production, you should put + # # it behind authentication and allow only admins to access it. + # # If your application does not have an admins-only section yet, + # # you can use Plug.BasicAuth to set up some basic authentication + # # as long as you are also using SSL (which you should anyway). + # import Phoenix.LiveDashboard.Router - scope "/dev" do - pipe_through [:fetch_session, :protect_from_forgery] + # scope "/dev" do + # pipe_through [:fetch_session, :protect_from_forgery] - live_dashboard "/dashboard", metrics: TelemetryApiWeb.Telemetry - end - end + # live_dashboard "/dashboard", metrics: TelemetryApiWeb.Telemetry + # end + # end end From aa43de0fe9e2cf1d47e39059a446040c8671c41d Mon Sep 17 00:00:00 2001 From: JuArce <52429267+JuArce@users.noreply.github.com> Date: Thu, 3 Oct 2024 19:17:44 -0300 Subject: [PATCH 39/55] fix: telemetry dump db --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 71f26b253..adbf633d1 100644 --- a/Makefile +++ b/Makefile @@ -783,7 +783,7 @@ telemetry_clean_db: telemetry_remove_db_container telemetry_dump_db: @cd telemetry_api && \ - docker exec -t telemetry-postgres-container pg_dumpall -c -U tracker_user > dump.$$(date +\%Y\%m\%d_\%H\%M\%S).sql + docker exec -t telemetry-postgres-container pg_dumpall -c -U telemetry_user > dump.$$(date +\%Y\%m\%d_\%H\%M\%S).sql @echo "Dumped database successfully to /telemetry_api" telemetry_create_env: From e50f17bcf456c48283d07d0fbce7145648807db2 Mon Sep 17 00:00:00 2001 From: Mario Rugiero Date: Fri, 4 Oct 2024 15:17:12 -0300 Subject: [PATCH 40/55] Fix typo --- telemetry_api/lib/telemetry_api/periodic/operator_fetcher.ex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/telemetry_api/lib/telemetry_api/periodic/operator_fetcher.ex b/telemetry_api/lib/telemetry_api/periodic/operator_fetcher.ex index 9df9965dd..ebbe2c897 100644 --- a/telemetry_api/lib/telemetry_api/periodic/operator_fetcher.ex +++ b/telemetry_api/lib/telemetry_api/periodic/operator_fetcher.ex @@ -15,7 +15,7 @@ defmodule TelemetryApi.Periodic.OperatorFetcher do ) def start_link(_) do - Task.start_link(&poll_serivce/0) + Task.start_link(&poll_service/0) end defp poll_service() do From 6d977da4f8e86d4a72ad31d486bc5e2380d0932d Mon Sep 17 00:00:00 2001 From: avilagaston9 Date: Sun, 6 Oct 2024 13:11:52 -0300 Subject: [PATCH 41/55] fix: update tracker port for the aggregator --- config-files/config-aggregator.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config-files/config-aggregator.yaml b/config-files/config-aggregator.yaml index 0d07f81b0..cb9f279a6 100644 --- a/config-files/config-aggregator.yaml +++ b/config-files/config-aggregator.yaml @@ -34,7 +34,7 @@ aggregator: avs_service_manager_address: 0xc3e53F4d16Ae77Db1c982e75a937B9f60FE63690 enable_metrics: true metrics_ip_port_address: localhost:9091 - telemetry_ip_port_address: localhost:4000 + telemetry_ip_port_address: localhost:4001 ## Operator Configurations # operator: # aggregator_rpc_server_ip_port_address: localhost:8090 From 933b21f9516a80c756a11d35a3887c3990763141 Mon Sep 17 00:00:00 2001 From: avilagaston9 Date: Sun, 6 Oct 2024 14:02:52 -0300 Subject: [PATCH 42/55] fix: merge --- aggregator/internal/pkg/aggregator.go | 24 ++---------------------- 1 file changed, 2 insertions(+), 22 deletions(-) diff --git a/aggregator/internal/pkg/aggregator.go b/aggregator/internal/pkg/aggregator.go index a4e221acc..a6831c155 100644 --- a/aggregator/internal/pkg/aggregator.go +++ b/aggregator/internal/pkg/aggregator.go @@ -16,6 +16,7 @@ import ( "github.com/Layr-Labs/eigensdk-go/logging" "github.com/Layr-Labs/eigensdk-go/services/avsregistry" blsagg "github.com/Layr-Labs/eigensdk-go/services/bls_aggregation" + oppubkeysserv "github.com/Layr-Labs/eigensdk-go/services/operatorsinfo" eigentypes "github.com/Layr-Labs/eigensdk-go/types" "github.com/ethereum/go-ethereum/crypto" servicemanager "github.com/yetanotherco/aligned_layer/contracts/bindings/AlignedLayerServiceManager" @@ -65,12 +66,6 @@ type Aggregator struct { // Stores the TaskResponse for each batch by batchIdentifierHash batchDataByIdentifierHash map[[32]byte]BatchData - // Stores if an operator already submitted a response for a batch - // This is to avoid double submissions - // struct{} is used as a placeholder because it is the smallest type - // go does not have a set type - operatorRespondedBatch map[uint32]map[eigentypes.Bytes32]struct{} - // This task index is to communicate with the local BLS // Service. // Note: In case of a reboot it can start from 0 again @@ -148,6 +143,7 @@ func NewAggregator(aggregatorConfig config.AggregatorConfig) (*Aggregator, error return taskResponseDigest, nil } + operatorPubkeysService := oppubkeysserv.NewOperatorsInfoServiceInMemory(context.Background(), clients.AvsRegistryChainSubscriber, clients.AvsRegistryChainReader, nil, oppubkeysserv.Opts{}, logger) avsRegistryService := avsregistry.NewAvsRegistryServiceChainCaller(avsReader.ChainReader, operatorPubkeysService, logger) blsAggregationService := blsagg.NewBlsAggregatorService(avsRegistryService, hashFunction, logger) @@ -171,7 +167,6 @@ func NewAggregator(aggregatorConfig config.AggregatorConfig) (*Aggregator, error batchesIdxByIdentifierHash: batchesIdxByIdentifierHash, batchDataByIdentifierHash: batchDataByIdentifierHash, batchCreatedBlockByIdx: batchCreatedBlockByIdx, - operatorRespondedBatch: make(map[uint32]map[eigentypes.Bytes32]struct{}), nextBatchIndex: nextBatchIndex, taskMutex: &sync.Mutex{}, walletMutex: &sync.Mutex{}, @@ -237,13 +232,6 @@ func (agg *Aggregator) handleBlsAggServiceResponse(blsAggServiceResp blsagg.BlsA agg.taskMutex.Lock() agg.logger.Error("BlsAggregationServiceResponse contains an error", "err", blsAggServiceResp.Err, "batchIdentifierHash", hex.EncodeToString(batchIdentifierHash[:])) agg.logger.Info("- Locking task mutex: Delete task from operator map", "taskIndex", blsAggServiceResp.TaskIndex) - - // Remove task from the list of tasks - delete(agg.operatorRespondedBatch, blsAggServiceResp.TaskIndex) - - agg.logger.Info("- Unlocking task mutex: Delete task from operator map", "taskIndex", blsAggServiceResp.TaskIndex) - - agg.taskMutex.Unlock() return } nonSignerPubkeys := []servicemanager.BN254G1Point{} @@ -266,14 +254,6 @@ func (agg *Aggregator) handleBlsAggServiceResponse(blsAggServiceResp blsagg.BlsA NonSignerStakeIndices: blsAggServiceResp.NonSignerStakeIndices, } - agg.logger.Info("- Locking task mutex: Delete task from operator map", "taskIndex", blsAggServiceResp.TaskIndex) - agg.taskMutex.Lock() - - // Delete the task from the map - delete(agg.operatorRespondedBatch, blsAggServiceResp.TaskIndex) - - agg.logger.Info("- Unlocking task mutex: Delete task from operator map", "taskIndex", blsAggServiceResp.TaskIndex) - agg.taskMutex.Unlock() agg.telemetry.LogQuorumReached(batchData.BatchMerkleRoot) From 071556039d11a9dcd1bd3def87ad4487802fb778 Mon Sep 17 00:00:00 2001 From: avilagaston9 Date: Sun, 6 Oct 2024 14:30:27 -0300 Subject: [PATCH 43/55] fix: aggregator --- aggregator/internal/pkg/aggregator.go | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/aggregator/internal/pkg/aggregator.go b/aggregator/internal/pkg/aggregator.go index a6831c155..730a87b5c 100644 --- a/aggregator/internal/pkg/aggregator.go +++ b/aggregator/internal/pkg/aggregator.go @@ -229,9 +229,7 @@ func (agg *Aggregator) handleBlsAggServiceResponse(blsAggServiceResp blsagg.BlsA if blsAggServiceResp.Err != nil { agg.telemetry.LogTaskError(batchData.BatchMerkleRoot, blsAggServiceResp.Err) - agg.taskMutex.Lock() agg.logger.Error("BlsAggregationServiceResponse contains an error", "err", blsAggServiceResp.Err, "batchIdentifierHash", hex.EncodeToString(batchIdentifierHash[:])) - agg.logger.Info("- Locking task mutex: Delete task from operator map", "taskIndex", blsAggServiceResp.TaskIndex) return } nonSignerPubkeys := []servicemanager.BN254G1Point{} @@ -254,8 +252,6 @@ func (agg *Aggregator) handleBlsAggServiceResponse(blsAggServiceResp blsagg.BlsA NonSignerStakeIndices: blsAggServiceResp.NonSignerStakeIndices, } - agg.taskMutex.Unlock() - agg.telemetry.LogQuorumReached(batchData.BatchMerkleRoot) agg.logger.Info("Threshold reached", "taskIndex", blsAggServiceResp.TaskIndex, @@ -292,6 +288,7 @@ func (agg *Aggregator) handleBlsAggServiceResponse(blsAggServiceResp blsagg.BlsA "merkleRoot", "0x"+hex.EncodeToString(batchData.BatchMerkleRoot[:]), "senderAddress", "0x"+hex.EncodeToString(batchData.SenderAddress[:]), "batchIdentifierHash", "0x"+hex.EncodeToString(batchIdentifierHash[:])) + agg.telemetry.LogTaskError(batchData.BatchMerkleRoot, err) } // / Sends response to contract and waits for transaction receipt From 4ad650eaf068883cf37eeb4185dfc0f813537640 Mon Sep 17 00:00:00 2001 From: avilagaston9 Date: Sun, 6 Oct 2024 16:34:07 -0300 Subject: [PATCH 44/55] fix: race condition on tracker --- aggregator/internal/pkg/server.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/aggregator/internal/pkg/server.go b/aggregator/internal/pkg/server.go index 5bfe3307a..b4f1867cf 100644 --- a/aggregator/internal/pkg/server.go +++ b/aggregator/internal/pkg/server.go @@ -49,8 +49,6 @@ func (agg *Aggregator) ProcessOperatorSignedTaskResponseV2(signedTaskResponse *t "SenderAddress", "0x"+hex.EncodeToString(signedTaskResponse.SenderAddress[:]), "BatchIdentifierHash", "0x"+hex.EncodeToString(signedTaskResponse.BatchIdentifierHash[:]), "operatorId", hex.EncodeToString(signedTaskResponse.OperatorId[:])) - agg.telemetry.LogOperatorResponse(signedTaskResponse.BatchMerkleRoot, signedTaskResponse.OperatorId) - taskIndex := uint32(0) ok := false @@ -72,6 +70,7 @@ func (agg *Aggregator) ProcessOperatorSignedTaskResponseV2(signedTaskResponse *t *reply = 1 return nil } + agg.telemetry.LogOperatorResponse(signedTaskResponse.BatchMerkleRoot, signedTaskResponse.OperatorId) // Don't wait infinitely if it can't answer // Create a context with a timeout of 5 seconds From f4db5822fb1bd447e201b39cf343b089472b7e57 Mon Sep 17 00:00:00 2001 From: avilagaston9 Date: Sun, 6 Oct 2024 16:57:22 -0300 Subject: [PATCH 45/55] fix: format issues --- .../operator_state_retriever.ex | 12 ++++++-- telemetry_api/lib/telemetry_api_web/router.ex | 30 +++++++++---------- 2 files changed, 24 insertions(+), 18 deletions(-) diff --git a/telemetry_api/lib/telemetry_api/contract_managers/operator_state_retriever.ex b/telemetry_api/lib/telemetry_api/contract_managers/operator_state_retriever.ex index c558d2d84..b1e2b2c0b 100644 --- a/telemetry_api/lib/telemetry_api/contract_managers/operator_state_retriever.ex +++ b/telemetry_api/lib/telemetry_api/contract_managers/operator_state_retriever.ex @@ -40,9 +40,11 @@ defmodule TelemetryApi.ContractManagers.OperatorStateRetriever do end def get_operators() do - with {:ok, block_number} = Ethers.current_block_number(), - {:ok, operators_state} = fetch_operators_state(block_number) do + with {:ok, block_number} <- Ethers.current_block_number(), + {:ok, operators_state} <- fetch_operators_state(block_number) do parse_operators(operators_state) + else + {:error, %{reason: :econnrefused}} -> {:error, "Blockchain is not reachable"} end end @@ -69,7 +71,11 @@ defmodule TelemetryApi.ContractManagers.OperatorStateRetriever do quorum_numbers = <<0>> response = - get_operator_state(@registry_coordinator_address, quorum_numbers, block_number) + OperatorStateRetriever.get_operator_state( + @registry_coordinator_address, + quorum_numbers, + block_number + ) |> Ethers.call() case response do diff --git a/telemetry_api/lib/telemetry_api_web/router.ex b/telemetry_api/lib/telemetry_api_web/router.ex index e10eb3e0c..a919fd301 100644 --- a/telemetry_api/lib/telemetry_api_web/router.ex +++ b/telemetry_api/lib/telemetry_api_web/router.ex @@ -2,28 +2,28 @@ defmodule TelemetryApiWeb.Router do use TelemetryApiWeb, :router pipeline :api do - plug(:accepts, ["json"]) + plug :accepts, ["json"] end scope "/api", TelemetryApiWeb do - pipe_through(:api) - - get("/operators", OperatorController, :index) - get("/operators/:id", OperatorController, :show) - post("/operators", OperatorController, :create_or_update) - post("/initTaskTrace", TraceController, :create_task_trace) - post("/operatorResponse", TraceController, :register_operator_response) - post("/quorumReached", TraceController, :quorum_reached) - post("/taskError", TraceController, :task_error) - post("/finishTaskTrace", TraceController, :finish_task_trace) + pipe_through :api + + get "/operators", OperatorController, :index + get "/operators/:id", OperatorController, :show + post "/operators", OperatorController, :create_or_update + post "/initTaskTrace", TraceController, :create_task_trace + post "/operatorResponse", TraceController, :register_operator_response + post "/quorumReached", TraceController, :quorum_reached + post "/taskError", TraceController, :task_error + post "/finishTaskTrace", TraceController, :finish_task_trace end scope "/versions", TelemetryApiWeb do - pipe_through(:api) + pipe_through :api - get("/", OperatorController, :index) - get("/:id", OperatorController, :show) - post("/", OperatorController, :create_or_update) + get "/", OperatorController, :index + get "/:id", OperatorController, :show + post "/", OperatorController, :create_or_update end # Enable LiveDashboard in development From 1f3d1c83d27d07b6c351ff5a9dd186f8d2316b04 Mon Sep 17 00:00:00 2001 From: avilagaston9 Date: Sun, 6 Oct 2024 18:48:49 -0300 Subject: [PATCH 46/55] fix: add missing alias --- .../telemetry_api/contract_managers/operator_state_retriever.ex | 1 + 1 file changed, 1 insertion(+) diff --git a/telemetry_api/lib/telemetry_api/contract_managers/operator_state_retriever.ex b/telemetry_api/lib/telemetry_api/contract_managers/operator_state_retriever.ex index b1e2b2c0b..a7ed9fbd6 100644 --- a/telemetry_api/lib/telemetry_api/contract_managers/operator_state_retriever.ex +++ b/telemetry_api/lib/telemetry_api/contract_managers/operator_state_retriever.ex @@ -1,5 +1,6 @@ defmodule TelemetryApi.ContractManagers.OperatorStateRetriever do require Logger + alias TelemetryApi.ContractManagers.OperatorStateRetriever @aligned_config_file System.get_env("ALIGNED_CONFIG_FILE") From c61c980f2da079cb4cc12872958f89d4cf205126 Mon Sep 17 00:00:00 2001 From: Julian Ventura Date: Tue, 8 Oct 2024 17:24:52 -0300 Subject: [PATCH 47/55] Solve requested changes --- telemetry_api/lib/telemetry_api/operators.ex | 4 ++-- .../lib/telemetry_api_web/controllers/operator_controller.ex | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/telemetry_api/lib/telemetry_api/operators.ex b/telemetry_api/lib/telemetry_api/operators.ex index b34e7807a..3b3282fd3 100644 --- a/telemetry_api/lib/telemetry_api/operators.ex +++ b/telemetry_api/lib/telemetry_api/operators.ex @@ -131,8 +131,8 @@ defmodule TelemetryApi.Operators do {:error, "Some status", "Some message"} """ - def update_operator(attrs) do - with {:ok, address} <- SignatureVerifier.recover_address(attrs["version"], attrs["signature"]) do + def update_operator(version, signature, changes) do + with {:ok, address} <- SignatureVerifier.recover_address(version, signature) do address = "0x" <> address case Repo.get(Operator, address) do nil -> diff --git a/telemetry_api/lib/telemetry_api_web/controllers/operator_controller.ex b/telemetry_api/lib/telemetry_api_web/controllers/operator_controller.ex index d4a4dcbb4..805e881c7 100644 --- a/telemetry_api/lib/telemetry_api_web/controllers/operator_controller.ex +++ b/telemetry_api/lib/telemetry_api_web/controllers/operator_controller.ex @@ -12,8 +12,8 @@ defmodule TelemetryApiWeb.OperatorController do render(conn, :index, operators: operators) end - def create_or_update(conn, operator_params) do - with {:ok, %Operator{} = operator} <- Operators.update_operator_version(operator_params) do + def create_or_update(conn, %{"version" => version, "signature" => signature} = attrs) do + with {:ok, %Operator{} = operator} <- Operators.update_operator(version, signature, attrs) do conn |> put_status(:created) |> put_resp_header("location", ~p"/api/operators/#{operator}") From 0fb9f2121b28c1f2337833ac3c633cedc6cc8ebc Mon Sep 17 00:00:00 2001 From: Julian Ventura Date: Mon, 14 Oct 2024 10:16:57 -0300 Subject: [PATCH 48/55] Fix formatting --- operator/cmd/actions/utils.go | 22 +++++++++++----------- operator/cmd/actions/utils_test.go | 30 +++++++++++++++--------------- 2 files changed, 26 insertions(+), 26 deletions(-) diff --git a/operator/cmd/actions/utils.go b/operator/cmd/actions/utils.go index ff12645ac..296220ead 100644 --- a/operator/cmd/actions/utils.go +++ b/operator/cmd/actions/utils.go @@ -1,17 +1,17 @@ package actions import ( - "regexp" - "errors" + "errors" + "regexp" ) -func baseUrlOnly(url string) (string, error) { - // Removes the protocol and api key part from any url formated like so: - // ":///" - regex := regexp.MustCompile(`^[a-z]+://([^/]+)`) - match := regex.FindStringSubmatch(url) - if len(match) > 1 { - return match[1], nil - } - return "", errors.New("Url did not match the expected format :///") +func baseUrlOnly(url string) (string, error) { + // Removes the protocol and api key part from any url formated like so: + // ":///" + regex := regexp.MustCompile(`^[a-z]+://([^/]+)`) + match := regex.FindStringSubmatch(url) + if len(match) > 1 { + return match[1], nil + } + return "", errors.New("Url did not match the expected format :///") } diff --git a/operator/cmd/actions/utils_test.go b/operator/cmd/actions/utils_test.go index 1231585ca..84173a327 100644 --- a/operator/cmd/actions/utils_test.go +++ b/operator/cmd/actions/utils_test.go @@ -1,19 +1,19 @@ package actions import ( - "testing" + "testing" ) func TestBaseUrlOnlyHappyPath(t *testing.T) { - // Format ":///" + // Format ":///" - urls := [...][2]string{ - {"http://localhost:8545/asdfoij2a7831has89%342jddav98j2748", "localhost:8545"}, - {"ws://test.com/23r2f98hkjva0udhvi1j%342jddav98j2748", "test.com"}, - {"http://localhost:8545", "localhost:8545"}, - } + urls := [...][2]string{ + {"http://localhost:8545/asdfoij2a7831has89%342jddav98j2748", "localhost:8545"}, + {"ws://test.com/23r2f98hkjva0udhvi1j%342jddav98j2748", "test.com"}, + {"http://localhost:8545", "localhost:8545"}, + } - for _, pair := range urls { + for _, pair := range urls { url := pair[0] expectedBaseUrl := pair[1] @@ -27,20 +27,20 @@ func TestBaseUrlOnlyHappyPath(t *testing.T) { t.Errorf("Expected base URL %s, got %s for URL %s", expectedBaseUrl, baseUrl, url) } } -} +} func TestBaseUrlOnlyFailureCases(t *testing.T) { - urls := [...]string{ - "localhost:8545/asdfoij2a7831has89%342jddav98j2748", - "this-is-all-wrong", - } + urls := [...]string{ + "localhost:8545/asdfoij2a7831has89%342jddav98j2748", + "this-is-all-wrong", + } - for _, url := range urls { + for _, url := range urls { baseUrl, err := baseUrlOnly(url) if err == nil { t.Errorf("An error was expected, but received %s", baseUrl) } } -} +} From c2183ffc84fc795694c905ac0a57ab1b62c7daea Mon Sep 17 00:00:00 2001 From: Julian Ventura Date: Mon, 14 Oct 2024 16:34:57 -0300 Subject: [PATCH 49/55] Update eigenlayer-middleware submodule pointer --- contracts/lib/eigenlayer-middleware | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/lib/eigenlayer-middleware b/contracts/lib/eigenlayer-middleware index a1801f07e..1273f59e4 160000 --- a/contracts/lib/eigenlayer-middleware +++ b/contracts/lib/eigenlayer-middleware @@ -1 +1 @@ -Subproject commit a1801f07e15192ef06db86dfec716eb2b6a4fe90 +Subproject commit 1273f59e42c9c4b9be1c33623c4ad6b0771d594a From 7cf92ea8218ef4536de023225d4980c9c8d4f3c8 Mon Sep 17 00:00:00 2001 From: avilagaston9 Date: Tue, 15 Oct 2024 17:05:56 -0300 Subject: [PATCH 50/55] refactor: move utils file into the operator pkg --- operator/cmd/actions/start.go | 9 +++++---- operator/{cmd/actions => pkg}/utils.go | 6 +++--- operator/{cmd/actions => pkg}/utils_test.go | 6 +++--- 3 files changed, 11 insertions(+), 10 deletions(-) rename operator/{cmd/actions => pkg}/utils.go (71%) rename operator/{cmd/actions => pkg}/utils_test.go (91%) diff --git a/operator/cmd/actions/start.go b/operator/cmd/actions/start.go index 7c0c941db..2896622c9 100644 --- a/operator/cmd/actions/start.go +++ b/operator/cmd/actions/start.go @@ -12,6 +12,7 @@ import ( "github.com/urfave/cli/v2" "github.com/yetanotherco/aligned_layer/core/config" operator "github.com/yetanotherco/aligned_layer/operator/pkg" + utils "github.com/yetanotherco/aligned_layer/operator/pkg" "golang.org/x/crypto/sha3" ) @@ -39,19 +40,19 @@ func updateTelemetryService(operator *operator.Operator, ctx *cli.Context, opera if err != nil { return err } - ethRpcUrl, err := baseUrlOnly(operatorConfig.BaseConfig.EthRpcUrl) + ethRpcUrl, err := utils.BaseUrlOnly(operatorConfig.BaseConfig.EthRpcUrl) if err != nil { return err } - ethRpcUrlFallback, err := baseUrlOnly(operatorConfig.BaseConfig.EthRpcUrlFallback) + ethRpcUrlFallback, err := utils.BaseUrlOnly(operatorConfig.BaseConfig.EthRpcUrlFallback) if err != nil { return err } - ethWsUrl, err := baseUrlOnly(operatorConfig.BaseConfig.EthWsUrl) + ethWsUrl, err := utils.BaseUrlOnly(operatorConfig.BaseConfig.EthWsUrl) if err != nil { return err } - ethWsUrlFallback, err := baseUrlOnly(operatorConfig.BaseConfig.EthWsUrlFallback) + ethWsUrlFallback, err := utils.BaseUrlOnly(operatorConfig.BaseConfig.EthWsUrlFallback) if err != nil { return err } diff --git a/operator/cmd/actions/utils.go b/operator/pkg/utils.go similarity index 71% rename from operator/cmd/actions/utils.go rename to operator/pkg/utils.go index 296220ead..6511372ec 100644 --- a/operator/cmd/actions/utils.go +++ b/operator/pkg/utils.go @@ -1,11 +1,11 @@ -package actions +package operator import ( "errors" "regexp" ) -func baseUrlOnly(url string) (string, error) { +func BaseUrlOnly(url string) (string, error) { // Removes the protocol and api key part from any url formated like so: // ":///" regex := regexp.MustCompile(`^[a-z]+://([^/]+)`) @@ -13,5 +13,5 @@ func baseUrlOnly(url string) (string, error) { if len(match) > 1 { return match[1], nil } - return "", errors.New("Url did not match the expected format :///") + return "", errors.New("url did not match the expected format :///") } diff --git a/operator/cmd/actions/utils_test.go b/operator/pkg/utils_test.go similarity index 91% rename from operator/cmd/actions/utils_test.go rename to operator/pkg/utils_test.go index 84173a327..7ee53ed41 100644 --- a/operator/cmd/actions/utils_test.go +++ b/operator/pkg/utils_test.go @@ -1,4 +1,4 @@ -package actions +package operator import ( "testing" @@ -17,7 +17,7 @@ func TestBaseUrlOnlyHappyPath(t *testing.T) { url := pair[0] expectedBaseUrl := pair[1] - baseUrl, err := baseUrlOnly(url) + baseUrl, err := BaseUrlOnly(url) if err != nil { t.Errorf("Unexpected error for URL %s: %v", url, err) @@ -37,7 +37,7 @@ func TestBaseUrlOnlyFailureCases(t *testing.T) { } for _, url := range urls { - baseUrl, err := baseUrlOnly(url) + baseUrl, err := BaseUrlOnly(url) if err == nil { t.Errorf("An error was expected, but received %s", baseUrl) From fac4ced17b870825c564480ba86bbf2d21290926 Mon Sep 17 00:00:00 2001 From: avilagaston9 Date: Tue, 15 Oct 2024 17:20:00 -0300 Subject: [PATCH 51/55] refactor: restore update_operator --- telemetry_api/lib/telemetry_api/operators.ex | 26 +++++++++++++++++--- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/telemetry_api/lib/telemetry_api/operators.ex b/telemetry_api/lib/telemetry_api/operators.ex index 34c768e72..fa9bc22a5 100644 --- a/telemetry_api/lib/telemetry_api/operators.ex +++ b/telemetry_api/lib/telemetry_api/operators.ex @@ -112,14 +112,14 @@ defmodule TelemetryApi.Operators do end @doc """ - Updates an operator's version. + Updates an operator. ## Examples - iex> update_operator(%{field: value}) + iex> update_operator(some_version, some_signature, %{field: value}) {:ok, %Ecto.Changeset{}} - iex> update_operator_version(%{field: bad_value}) + iex> update_operator(some_version, invalid_signature, %{field: value}) {:error, "Some status", "Some message"} """ @@ -132,11 +132,29 @@ defmodule TelemetryApi.Operators do "Provided address does not correspond to any registered operator"} operator -> - operator |> Operator.changeset(changes) |> Repo.insert_or_update() + update_operator(operator, changes) end end end + @doc """ + Updates an operator. + + ## Examples + + iex> update_operator(operator, %{field: new_value}) + {:ok, %Operator{}} + + iex> update_operator(operator, %{field: bad_value}) + {:error, %Ecto.Changeset{}} + + """ + def update_operator(%Operator{} = operator, attrs) do + operator + |> Operator.changeset(attrs) + |> Repo.update() + end + @doc """ Deletes a operator. From c2ee08c8dab08e8821da495cac4ecb5361d784a3 Mon Sep 17 00:00:00 2001 From: avilagaston9 Date: Tue, 15 Oct 2024 17:35:32 -0300 Subject: [PATCH 52/55] refactor: remove unused functions --- telemetry_api/lib/telemetry_api/utils.ex | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/telemetry_api/lib/telemetry_api/utils.ex b/telemetry_api/lib/telemetry_api/utils.ex index 8d412b2c8..073a7a7df 100644 --- a/telemetry_api/lib/telemetry_api/utils.ex +++ b/telemetry_api/lib/telemetry_api/utils.ex @@ -1,6 +1,4 @@ defmodule TelemetryApi.Utils do - use TelemetryApiWeb, :controller - @moduledoc """ Some utility functions """ @@ -52,15 +50,4 @@ defmodule TelemetryApi.Utils do {:error, error_message} end end - - - @doc """ - Returns json encoded error using http - """ - def return_error(conn, message) do - conn - |> put_status(:bad_request) - |> put_resp_content_type("application/json") - |> send_resp(:bad_request, Jason.encode!(%{error: message})) - end end From f02d279d62839da49515cbddfc2235a59eb17d78 Mon Sep 17 00:00:00 2001 From: avilagaston9 Date: Tue, 15 Oct 2024 17:36:12 -0300 Subject: [PATCH 53/55] refactor: remove unused alias --- .../lib/telemetry_api_web/controllers/operator_controller.ex | 1 - 1 file changed, 1 deletion(-) diff --git a/telemetry_api/lib/telemetry_api_web/controllers/operator_controller.ex b/telemetry_api/lib/telemetry_api_web/controllers/operator_controller.ex index 48305d5fb..64d093cf2 100644 --- a/telemetry_api/lib/telemetry_api_web/controllers/operator_controller.ex +++ b/telemetry_api/lib/telemetry_api_web/controllers/operator_controller.ex @@ -2,7 +2,6 @@ defmodule TelemetryApiWeb.OperatorController do use TelemetryApiWeb, :controller alias TelemetryApi.Operators - alias TelemetryApi.Utils alias TelemetryApi.Operators.Operator action_fallback(TelemetryApiWeb.FallbackController) From 6414762aafadda6ad52585a17f7239b95728c75d Mon Sep 17 00:00:00 2001 From: avilagaston9 Date: Tue, 15 Oct 2024 19:36:55 -0300 Subject: [PATCH 54/55] feat: handle urls with long path --- operator/pkg/utils.go | 34 +++++++++++++++++++++++++--------- operator/pkg/utils_test.go | 1 + 2 files changed, 26 insertions(+), 9 deletions(-) diff --git a/operator/pkg/utils.go b/operator/pkg/utils.go index 6511372ec..90730431c 100644 --- a/operator/pkg/utils.go +++ b/operator/pkg/utils.go @@ -1,17 +1,33 @@ package operator import ( - "errors" + "fmt" "regexp" + "strings" ) -func BaseUrlOnly(url string) (string, error) { - // Removes the protocol and api key part from any url formated like so: - // ":///" - regex := regexp.MustCompile(`^[a-z]+://([^/]+)`) - match := regex.FindStringSubmatch(url) - if len(match) > 1 { - return match[1], nil +func BaseUrlOnly(input string) (string, error) { + // Define a regex pattern to match the URL format + // The pattern captures the scheme, host, and path + pattern := `^(?P[^:]+)://(?P[^/]+)(?P/.*)?$` + re := regexp.MustCompile(pattern) + + matches := re.FindStringSubmatch(input) + + if matches == nil { + return "", fmt.Errorf("invalid URL: %s", input) + } + + host := matches[2] + path := matches[3] + + // If the path is not empty, append the path without the last segment (api_key) + if path != "" { + pathSegments := strings.Split(path, "/") + if len(pathSegments) > 1 { + return host + strings.Join(pathSegments[:len(pathSegments)-1], "/"), nil + } } - return "", errors.New("url did not match the expected format :///") + + return host, nil } diff --git a/operator/pkg/utils_test.go b/operator/pkg/utils_test.go index 7ee53ed41..09a544ae6 100644 --- a/operator/pkg/utils_test.go +++ b/operator/pkg/utils_test.go @@ -11,6 +11,7 @@ func TestBaseUrlOnlyHappyPath(t *testing.T) { {"http://localhost:8545/asdfoij2a7831has89%342jddav98j2748", "localhost:8545"}, {"ws://test.com/23r2f98hkjva0udhvi1j%342jddav98j2748", "test.com"}, {"http://localhost:8545", "localhost:8545"}, + {"https://myservice.com/holesky/ApiKey", "myservice.com/holesky"}, } for _, pair := range urls { From f05310f612aa14057f49b1e0da94fc1f8441e891 Mon Sep 17 00:00:00 2001 From: avilagaston9 Date: Wed, 16 Oct 2024 12:07:33 -0300 Subject: [PATCH 55/55] refactor: make sendTelemetryData an operator method --- operator/cmd/actions/start.go | 70 +---------------------------------- operator/pkg/operator.go | 65 ++++++++++++++++++++++++++++++++ 2 files changed, 66 insertions(+), 69 deletions(-) diff --git a/operator/cmd/actions/start.go b/operator/cmd/actions/start.go index 2896622c9..4f2d7fcb5 100644 --- a/operator/cmd/actions/start.go +++ b/operator/cmd/actions/start.go @@ -1,19 +1,13 @@ package actions import ( - "bytes" "context" - "encoding/json" "log" - "net/http" sdkutils "github.com/Layr-Labs/eigensdk-go/utils" - "github.com/ethereum/go-ethereum/crypto" "github.com/urfave/cli/v2" "github.com/yetanotherco/aligned_layer/core/config" operator "github.com/yetanotherco/aligned_layer/operator/pkg" - utils "github.com/yetanotherco/aligned_layer/operator/pkg" - "golang.org/x/crypto/sha3" ) var StartFlags = []cli.Flag{ @@ -27,68 +21,6 @@ var StartCommand = &cli.Command{ Action: operatorMain, } -func updateTelemetryService(operator *operator.Operator, ctx *cli.Context, operatorConfig *config.OperatorConfig) error { - // hash version - hash := sha3.NewLegacyKeccak256() - hash.Write([]byte(ctx.App.Version)) - - // get hash - version := hash.Sum(nil) - - // sign version - signature, err := crypto.Sign(version[:], operatorConfig.EcdsaConfig.PrivateKey) - if err != nil { - return err - } - ethRpcUrl, err := utils.BaseUrlOnly(operatorConfig.BaseConfig.EthRpcUrl) - if err != nil { - return err - } - ethRpcUrlFallback, err := utils.BaseUrlOnly(operatorConfig.BaseConfig.EthRpcUrlFallback) - if err != nil { - return err - } - ethWsUrl, err := utils.BaseUrlOnly(operatorConfig.BaseConfig.EthWsUrl) - if err != nil { - return err - } - ethWsUrlFallback, err := utils.BaseUrlOnly(operatorConfig.BaseConfig.EthWsUrlFallback) - if err != nil { - return err - } - - body := map[string]interface{}{ - "version": ctx.App.Version, - "signature": signature, - "eth_rpc_url": ethRpcUrl, - "eth_rpc_url_fallback": ethRpcUrlFallback, - "eth_ws_url": ethWsUrl, - "eth_ws_url_fallback": ethWsUrlFallback, - } - - bodyBuffer := new(bytes.Buffer) - - bodyReader := json.NewEncoder(bodyBuffer) - err = bodyReader.Encode(body) - if err != nil { - return err - } - - // send version to operator tracker server - endpoint := operatorConfig.Operator.OperatorTrackerIpPortAddress + "/versions" - operator.Logger.Info("Sending version to operator tracker server: ", "endpoint", endpoint) - - res, err := http.Post(endpoint, "application/json", bodyBuffer) - if err != nil { - // Dont prevent operator from starting if operator tracker server is down - operator.Logger.Warn("Error sending version to metrics server: ", "err", err) - } else if res.StatusCode != http.StatusCreated && res.StatusCode != http.StatusNoContent { - operator.Logger.Warn("Error sending version to operator tracker server: ", "status_code", res.StatusCode) - } - - return nil -} - func operatorMain(ctx *cli.Context) error { operatorConfigFilePath := ctx.String("config") operatorConfig := config.NewOperatorConfig(operatorConfigFilePath) @@ -102,7 +34,7 @@ func operatorMain(ctx *cli.Context) error { return err } - err = updateTelemetryService(operator, ctx, operatorConfig) + err = operator.SendTelemetryData(ctx) if err != nil { return err } diff --git a/operator/pkg/operator.go b/operator/pkg/operator.go index c1d7b7954..8a96b51c4 100644 --- a/operator/pkg/operator.go +++ b/operator/pkg/operator.go @@ -8,13 +8,16 @@ import ( "encoding/json" "fmt" "log" + "net/http" "os" "path/filepath" "sync" "time" "github.com/ethereum/go-ethereum/crypto" + "github.com/urfave/cli/v2" "github.com/yetanotherco/aligned_layer/operator/risc_zero" + "golang.org/x/crypto/sha3" "github.com/prometheus/client_golang/prometheus" "github.com/yetanotherco/aligned_layer/metrics" @@ -590,3 +593,65 @@ func (o *Operator) SignTaskResponse(batchIdentifierHash [32]byte) *bls.Signature responseSignature := *o.Config.BlsConfig.KeyPair.SignMessage(batchIdentifierHash) return &responseSignature } + +func (o *Operator) SendTelemetryData(ctx *cli.Context) error { + // hash version + hash := sha3.NewLegacyKeccak256() + hash.Write([]byte(ctx.App.Version)) + + // get hash + version := hash.Sum(nil) + + // sign version + signature, err := crypto.Sign(version[:], o.Config.EcdsaConfig.PrivateKey) + if err != nil { + return err + } + ethRpcUrl, err := BaseUrlOnly(o.Config.BaseConfig.EthRpcUrl) + if err != nil { + return err + } + ethRpcUrlFallback, err := BaseUrlOnly(o.Config.BaseConfig.EthRpcUrlFallback) + if err != nil { + return err + } + ethWsUrl, err := BaseUrlOnly(o.Config.BaseConfig.EthWsUrl) + if err != nil { + return err + } + ethWsUrlFallback, err := BaseUrlOnly(o.Config.BaseConfig.EthWsUrlFallback) + if err != nil { + return err + } + + body := map[string]interface{}{ + "version": ctx.App.Version, + "signature": signature, + "eth_rpc_url": ethRpcUrl, + "eth_rpc_url_fallback": ethRpcUrlFallback, + "eth_ws_url": ethWsUrl, + "eth_ws_url_fallback": ethWsUrlFallback, + } + + bodyBuffer := new(bytes.Buffer) + + bodyReader := json.NewEncoder(bodyBuffer) + err = bodyReader.Encode(body) + if err != nil { + return err + } + + // send version to operator tracker server + endpoint := o.Config.Operator.OperatorTrackerIpPortAddress + "/versions" + o.Logger.Info("Sending version to operator tracker server: ", "endpoint", endpoint) + + res, err := http.Post(endpoint, "application/json", bodyBuffer) + if err != nil { + // Dont prevent operator from starting if operator tracker server is down + o.Logger.Warn("Error sending version to metrics server: ", "err", err) + } else if res.StatusCode != http.StatusCreated && res.StatusCode != http.StatusNoContent { + o.Logger.Warn("Error sending version to operator tracker server: ", "status_code", res.StatusCode) + } + + return nil +}