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

Introduce ADR 15 for Admin API #237

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 50 additions & 0 deletions docs/adr/0015-admin-api.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
# 15. Configure Node through an Admin API

Date: 2022-03-04

## Status

:hammer_and_wrench:

## Context

* Hydra-node currently requires a whole slew of command-line arguments to configure properly its networking layer: `--peer` to connect to each peer, `--cardano-verification-key` and `--hydra-verification-key` to identify the peer on the L1 and L2 respectively.
* This poses significant challenges for operating a _cluster_ of Hydra nodes as one needs to know beforehand everything about the cluster, then pass a large number of arguments to some program or docker-compose file, before any node can be started
* This is a pain that's been felt first-hand for benchmarking and testing purpose
* Having static network configuration is probably not sustainable in the long run, even if we don't add any fancy multihead capabilities to the node, as it would make it significantly harder to have automated creation of Heads.
* There's been an [attempt](https://github.com/input-output-hk/hydra-poc/pull/222) at providing a file-based network configuration but this was deemed unconvincing
* [Hydra paper (sec. 4, p. 13)](https://eprint.iacr.org/2020/299.pdf) explicitly assumes the existence of a _setup_ phase
* This _setup_ is currently left aside, eg. exchanging keys for setting up multisig and identifying peers. The [hydra-node](https://github.com/input-output-hk/hydra-poc/blob/abailly-iohk/admin-api-adr/hydra-node/exe/hydra-node/Main.hs#L41) executable is statically configured and those things are assumed to be known beforehand

## Decision

* Hydra-node exposes an _Administrative API_ to enable configuration of the Hydra network using "standard" tools
* API is exposed as a set of HTTP endpoints on some port, consuming and producing JSON data,
* It is documented as part of the User's Guide for Hydra Head
* This API provides _commands_ and _queries_ to:
* Add/remove _peers_ providing their address and keys,
* List currently known peers and their connectivity status,
* Start/stop/reset the Hydra network
* This API is implemented by a _new component_ accessible through a network port separate from current _Client API_, that _configures_ the `Network` component

The following picture sketches the proposed architectural change:

![Architecture change](./0015-architecture-change.jpg)

## Q&A

* *Why a REST interface?*
* This API is an interface over a specific _resource_ controlled by the Hydra node, namely its knowledge of other peers with which new _Head_s can be opened. As such a proper REST interface (_not_ RPC-in-disguise) seems to make sense here, rather than stream/event-based [duplex communication channels](./0003-asynchronous-duplex-api.md)
* We can easily extend such an API with websockets to provide notifications (eg. peers connectivity, setup events...)
* *Why a separate component?*
* We could imagine extending the existing [APIServer](../../hydra-node/src/Hydra/API/Server.hs) interface with new messages related to this network configuration, however this seems to conflate different responsibilities in a single place: Configuring and managing the Hydra node itself, and configuring, managing, and interacting with the Head itself
Copy link
Member

Choose a reason for hiding this comment

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

I wouldn't say it conflates these responsibilities, but the API component would merely provide access to the functionality of managing the hydra-node. The same way as the current functionality of the hydra-node (manage a single head and use it when open) is also not provided by the API component right now.

Copy link
Author

Choose a reason for hiding this comment

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

We are talking about managing 2 different entities, with clear separation of capabilities and state: The Node and its network part on one side, the Head which the Node is hosting on the other side (there can be multiple Heads in a Node, possibly with different parties and peers, if not concurrently atm at least sequentially).
Hence it seems that having a single component (the current APIServer) providing access to these 2 capabilities is a conflation of 2 different concerns.

* "Physical" separation of endpoints makes it easier to secure a very sensitive part of the node, namely its administration, e.g by ensuring this can only be accessed through a specific network interface, without relying on application level authnz mechanisms
Copy link
Member

Choose a reason for hiding this comment

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

Another Q: The Admin API shall not allow to add/remove peers when a Head is open, how will that be handled?

(I'd like to get this answered as it is a more involved scenario which requires knowledge of the HeadState. IMO it ought to be handled in the HeadLogic, or the Admin API component needs access to the HeadState.. which the architecture change diagram above does not indicate)

Copy link
Author

Choose a reason for hiding this comment

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

I initially started with more complex interaction in the diagram to address this particular point, but then thought it would be something to refine when actually implementing this. As the name (kind of) implies and the implementation follows, HeadLogic is responsible for managing the lifecycle of a single Head whose behaviour depends on the existence of a Network component. Hence as long as the network is not properly setup there can be no well-behaving HeadLogic hence no interaction with it.
Practically speaking, this means the Admin component (arguably a very bad name so we'll need to find better) would kind of "create" the HeadLogic once it gets a go. It really is handling the setup phase so happens before any Head.


## Consequences

* It's easy to deploy Hydra nodes with some standard configuration, then dynamically configure them, thus reducing the hassle of defining and configuring the Hydra network
* It makes it possible to _reconfigure_ a Hydra node with different peers
* The _Client API_ should reflect the state of the network and disable `Init`ing a head if the network layer is not started
* In the long run, it should also have its scope reduced to represent only the possible interactions with a _Head_, moving things related to network connectivity and setup to the Admin API
* In a _Managed Head_ scenario it would even make sense to have another layer of separation between the API to manage the lifecycle of the Head and the API to make transactions within the Head
This conversation was marked as resolved.
Show resolved Hide resolved
* Operational tools could be built easily on top of the API, for command-line or Web-based configuration
Binary file added docs/adr/0015-architecture-change.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 2 additions & 1 deletion docs/adr/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ Here is a list of currently accepted or discussed **Architecture Decision Record
8. [Use custom Prelude](./0008-use-custom-prelude.md)
9. [Simplify logging](./0009-simplify-logging.md)
10. Use [Direct chain](./0010-use-direct-chain.md) connection
11. _Standardize on Cardano API_
11. [Standardize on Cardano API](./0011-use-cardano-api.md)
12. [Top-down test-driven design](./0012-testing-strategy.md)
13. [Adversarial Mutation-based Contract Testing](./0013-contract-testing-strategy.md)
14. [Token usage in Hydra scripts](./0014-hydra-script-tokens.md)
15. _[Provide Admin API for Node](./0015-admin-api.md)_