Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: implement KeyManager API #1246

Merged
merged 29 commits into from
Aug 13, 2024
Merged

feat: implement KeyManager API #1246

merged 29 commits into from
Aug 13, 2024

Conversation

avilagaston9
Copy link
Contributor

@avilagaston9 avilagaston9 commented Jul 31, 2024

Motivation

To be able to integrate with EthDocker.

Description

Implements the Local Key Manager set of endpoints: https://ethereum.github.io/keymanager-APIs/#/Local%20Key%20Manager.

  • Creates a new Phoenix endpoint with 5000 as the default port.
  • Adds Open Api Spex at GET api/openapi.
  • Creates a Keystore struct to hold the keystore data.
  • Adds the keystore data to the Validator struct.

Now we can list, add and delete Validators from Libp2pPort.

Tracked Issues

To stay in sync with the team, I've limited this PR to the changes above, which add the basic structure of the Keystore. I've created the following issues for tasks that are outside the scope of this PR.

Observations

  • The ethereum-package was modified to enable the validator-port. If you have already cloned it, a pull may be needed.
  • To enable the validator-port with Kurtosis, the keymanager-enabled parameter must be set in the network_params.yaml as specified in their docs.

Closes #1256

@avilagaston9 avilagaston9 marked this pull request as ready for review August 9, 2024 16:20
@avilagaston9 avilagaston9 requested a review from a team as a code owner August 9, 2024 16:20
@avilagaston9 avilagaston9 marked this pull request as draft August 10, 2024 02:04
@avilagaston9 avilagaston9 marked this pull request as ready for review August 12, 2024 02:43
Copy link
Collaborator

@Arkenan Arkenan left a comment

Choose a reason for hiding this comment

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

LGTM with some comments

@@ -31,6 +31,12 @@ defmodule BeaconApi.Utils do
"0x" <> Base.encode16(binary, case: :lower)
end

def hex_decode("0x" <> binary) do
with {:ok, decoded} <- Base.decode16(binary, case: :lower) do
Copy link
Collaborator

Choose a reason for hiding this comment

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

The reason we use this hex_decode utility is because we assume it's correctly stored in our genserver. If that's an assumption we make, instead of using a with here we should call this hex_decode! and match {:ok, decoded} = Base.decode16(binary, case: lower).

The reason for this is that if this decoding fails it will return an error tuple, that we are ignoring in the other function. If that's the case, we should error out directly.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Actually, this is used to decode the user input. I have updated its definition to the following:

def hex_decode("0x" <> binary), do: Base.decode16(binary, case: :lower)
def hex_decode(binary), do: {:error, "Not valid pubkey: #{inspect(binary)}"}

I have also updated the caller function to handle the result properly:

        with {:ok, pubkey} <- Utils.hex_decode(pubkey),
             ..., do:
             ...
        else
          {:error, reason} ->
            Logger.error("[Keystore] Error removing key. Reason: #{reason}")
        end

Comment on lines 542 to 544
@impl GenServer
def handle_call(:get_keystores, _from, %{validators: []} = state),
do: {:reply, [], state}
Copy link
Collaborator

Choose a reason for hiding this comment

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

Why is this clause necessary? If the validators list is empty, the enum.map will work, and return an empty list too.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

You are right! It is not necessary.


@impl GenServer
def handle_call({:delete_validator, pk}, _from, %{validators: validators} = state) do
case Map.fetch(validators, pk) do
Copy link
Collaborator

Choose a reason for hiding this comment

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

Let's use pubkey instead of pk to distinguish these from private keys.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Agreed!

Comment on lines +566 to +567
first_validator = validators |> Map.values() |> List.first()
validator = Validator.new({first_validator.slot, first_validator.root, keystore})
Copy link
Collaborator

Choose a reason for hiding this comment

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

Nothing to be done in this PR, but I think this shows how weird it is to have these values tied to individual validators. We'll get those values from the store when the other PR is merged.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Totally! This will be easily handled once we have the other PR ready.

Copy link
Collaborator

Choose a reason for hiding this comment

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

+1

Copy link
Collaborator

@rodrigo-o rodrigo-o left a comment

Choose a reason for hiding this comment

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

LGTM!

Comment on lines 37 to 43
@type state :: %__MODULE__{
slot: Types.slot(),
epoch: Types.epoch(),
root: Types.root(),
duties: Duties.duties(),
validator: validator(),
index: non_neg_integer() | nil,
keystore: Keystore.t(),
Copy link
Collaborator

@rodrigo-o rodrigo-o Aug 12, 2024

Choose a reason for hiding this comment

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

The Validator is in a weird state (obviously not because of this PR ^^) but this will be a lot better in the coming days. Lot of this is going to change in the refactor I'm working on, I already removed slot, epoch, root and even duties from here, it should be easier by then hopefully.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I agree. I just hope that this doesn't add too much noise to your PR!

Comment on lines 5 to 11
validator_count: 1
- el_type: geth
cl_type: lambda
cl_image: lambda_ethereum_consensus:latest
use_separate_vc: false
count: 1
validator_count: 32
cl_max_mem: 4096 No newline at end of file
validator_count: 63
Copy link
Collaborator

Choose a reason for hiding this comment

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

np: do we want to have 1 in every lighthouse node and 63 (62 would be sufficient) in ours as the new default config?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

My bad. I changed them only for testing and should have restored these parameters. Nice catch!

@avilagaston9 avilagaston9 merged commit f38288c into main Aug 13, 2024
19 checks passed
@avilagaston9 avilagaston9 deleted the keystore-api branch August 13, 2024 02:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Development

Successfully merging this pull request may close these issues.

Implement Local Key Manager set of endpoints
3 participants