Skip to content

ADR-4 Default eras for CLI commands #25

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

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
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
97 changes: 97 additions & 0 deletions docs/ADR-4-Era-selectors-for-CLI-commands.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
# Status

📜 Proposed 2023-09-04

# Context
Copy link
Collaborator

@carbolymer carbolymer Sep 15, 2023

Choose a reason for hiding this comment

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

There is too much spacing of paragraphs, it's a bit hard to read. Some paragraphs should be joined together.
Suggestion: use one sentence per line in markdown - it makes smaller git diffs.


The Cardano block chain can be hard forked through multiple eras throughout its existence. CLI commands may behave differently between eras depending on what the current era is and what era the user runs the command in.

The era to be used for a CLI command can be optional in which case the command may connect to the node to find out what the current era is and choose an era appropriately.

For these cases, the question arises what the default era should be for the CLI command.

Moreover there is the question of how the default era should change over time, particularly in relation to a hard fork: whether the default era should change in the release before or after the hard fork happens.

There is even scope to adopt a different strategy between query and transaction commands or even between different transaction commands.

For example we can create a transaction in two different ways using the CLI - using `transaction build` and `transaction build-raw` commands. The `transaction build` command is "magical" in that it tries to be user friendly by inferring transaction parameters wherever it can so the user doesn't have to, while the `transaction build-raw` is for more experienced users because it provides no inference and leaves it up to the user to supply all the necessary transaction parameters.

Would it make sense for "magical" commands like the `transaction build` command to try to be more helpful and use the current era as the default? That would _seem_ to be in the spirit of the command.
Copy link
Collaborator

Choose a reason for hiding this comment

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

transaction build queries the current node era


Historically we changed the default transactions era in the first release after the hard fork in order to give the tool/dapp developers the possibility to update the default transaction era in their code after the hard fork - otherwise their tools would stop working after the hard fork.

Care needs to be taken to avoid making a CLI release that does not work by default by defaulting to using an era that is not yet active. So that's why we have historically only updated the default era in the release after the hard fork, not the release before.
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
Care needs to be taken to avoid making a CLI release that does not work by default by defaulting to using an era that is not yet active. So that's why we have historically only updated the default era in the release after the hard fork, not the release before.
Care needs to be taken to avoid making a CLI release that does not work by defaulting to using an era that is not yet active. So that's why we have historically only updated the default era in the release after the hard fork, not the release before.

I get what you meant, but I think this can be simplified without losing semantics.


This way, third party tools that use the CLI would not stop working after the hard fork, they would continue to create and submit transactions in the older format, for the older era. Historically we always made that backwards compatibility work. It just meant that CLI users would not get the new features for the new era without explicitly using the right era flag - until the following release changed the default.
Copy link
Collaborator

Choose a reason for hiding this comment

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

This is not necessarily true. There could be breaking changes in the upcoming era.


Moreover, it is often the case that CLI commands in the release that crossed the hard fork may not yet be updated to work in the new era. If we adopted policy of using the current era for our CLI commands, even "magical" commands that try to infer as much as possible, we risk possibility of the command breaking after the hard fork.
Copy link
Collaborator

Choose a reason for hiding this comment

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

I don't understand what you mean here. How would CLI commands in the release post hard fork may not yet be updated to work in the new era?


This was the context from the adoption of [[ADR-1 Default eras for CLI commands]] until now.

Going foward we have additional concerns to consider:
Copy link
Collaborator

@carbolymer carbolymer Sep 15, 2023

Choose a reason for hiding this comment

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

Unnecessary colon at the end of paragraph.


Some commands require access to the protocol parameters in the era the command is operating in and the contents of the protocol parameters could have meaningful bearing on how any transactions derived from those commands will be interpreted on-chain.

It is important therefore that the protocol parameters that is used contain the sorts of value that reflect the current state of the ledger.

Unfortunately, the upcoming Conway era introduces many new protocol parameters and obsoletes many others, meaning that there is no way to construct sensible values for these protocol parameters that would guarantee that transactions derived from them operate in a predictable way on chain.

This would mean that submitting transactions built for an older era inherently carries with the risk that the transaction behaves other than intended.

This is especially true for transactions built in an older era with an incomplete, made up or out-of-date values.

This is also true for transactions upgraded from an older era, although to a lesser extent.
Copy link
Collaborator

Choose a reason for hiding this comment

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

We are no longer claiming to support this.


Constructing a command in the currently era is the for any command that requires protocol-parametes is the only way to guarantee a transaction works as intended.
Copy link
Contributor

Choose a reason for hiding this comment

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

This reads weird 🙁 Maybe a mash-up of two different versions of the sentence?


Another thing that has changed since [[ADR-1 Default eras for CLI commands]] was adopted is the intruction of an era-based command structure.

The era-based command structure looks like this: `cardano-cli selected-era command sub-command ...`. For example `cardano-cli babbage transaction build ...`.

We will for a time continue to support commands of the structure `cardano-cli command sub-command --selected-era` up until the Babbage era, but for Conway onwards, the era-based command structure must be used.

The era-based command structure means that users when running a command must make some kind of decision upfront about what era they wish to run their command in.

Such a structure also affords the possibility of having era selectors that follow an upgrade policy. For example the `latest` era may select latest era that the CLI supports as a hard-coded value, defaulting to `babbage` whilst `conway` support is still in development.

This ADR concerns what era selectors we will have and how they will behave.

The decision should as much as possible take into account the following considerations:

* Some users may care that CLI behaviour not suddenly change after a hard fork in a way that can break third party tools and user expectations.
* Some users may care that CLI behaviour be such that transactions always behave as expected on-chain at the cost of breaking at a hard fork.
* Historical precedent so as to avoid surprising SPOs and in a new release.
* Simplicity and consistency.
* Behaviour that just works where it makes sense.

# Decision

There will be no "default" era. Instead, two era selectors will be included with the CLI:
Copy link
Collaborator

@carbolymer carbolymer Sep 15, 2023

Choose a reason for hiding this comment

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

Can you provide commands examples for each of selectors?

Copy link
Collaborator

@carbolymer carbolymer Sep 15, 2023

Choose a reason for hiding this comment

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

Does it mean that there will be only three eras available to select? What If I start a testnet in babbage, and I'd like to execute commands in babbage. These new era selectors will not allow for that.


* `local` - This era is the latest hard-coded era supported by `cardano-cli` at the time `cardano-cli` was released. This will not change in the event of a
Copy link
Collaborator

Choose a reason for hiding this comment

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

Tbf I prefer latest to local. local is not clear to me in the era context.

Copy link
Contributor

Choose a reason for hiding this comment

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

But latest can be ambiguous right? In case of a hard fork, users could expect that latest is the newest fork.

What about hardcoded?

Copy link
Collaborator

Choose a reason for hiding this comment

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

We can be explicit about what we mean wrt latest. We could say latest is the current era on mainnet. We then can have a release after the hardfork to update this hardcoded value.

Outside of directly querying the node to determine the era, there will always be some discrepancy at the hardfork boundary. We just need to decide when we will fix the discrepancy and historically we have done that after the hardfork in a release.

hard-fork. This command is offline and can run in the absence of a node socket. For commands that require protocol parameters, this must be provided by
the user. Any commands that are inherently online (eg `transaction submit`) will still use the same era as commands that are not inherently online.
In the event that the era selects an era different behind that of the network, `cardano-cli` will attempt to automically upgrade transaction to the network
Copy link
Collaborator

Choose a reason for hiding this comment

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

We have already decided we are not upgrading transactions so this part isn't relevant anymore.

era unless explicitly instructed not to. `cardano-cli` maybe be instructed to fail on an era-mismatch with the network era or use some other
strategy if the need arises to have further strategies.

* `network` - This era is the era of the network the run of the command is intended for. In order to acquire the era, `cardano-cli` must connect to the node
Copy link
Collaborator

Choose a reason for hiding this comment

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

Are selectors local and network supposed to be used as:

cardano-cli local transaction build-raw
cardano-cli network transaction build

?

If yes, those seem to be super misleading. If those are era selectors, names should relate to eras somehow, for example era-local or era-network should be used instead.

If we would like to keep the names as they are, they shouldn't be called era selectors, or rather something like "locality selectors" (feel free to pick a better name). That would mean that some commands are meant to be used online, and some offline and the era aspect should get abstracted away from the end user.

Copy link
Contributor

Choose a reason for hiding this comment

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

Is there a command to query what network resolves to? Such a command could help users check - for example in their CI - that network has the value they expect. And if not, their CI will break and they are notified they need to do something.

Copy link
Collaborator

Choose a reason for hiding this comment

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

It would have to be for example cardano-cli local conway transaction build-raw. The network group of commands won't expose any notion of era to the user because it will determine the era based on the node query.

via a socket. This command is online and cannot run in the absence of a node socket. For commands that require protocol parameters, they will default to
the one supplied by the node. If the version of `cardano-cli` used does not support the network's current era, the command will fail. Because the
network era can change at a hard fork, this means that a call to a command that worked before the hard fork may fail after a hard fork. This could happen
for example if the invocation used a command line option that was valid before the hardfork but is no longer valid after the hard fork.

* `latest` - As an era selector will be removed because it is ambiguous as to what it means.

This obsoletes [[ADR-1 Default eras for CLI commands]].

# Consequences

* The possibility of a hard fork means tradeoffs are necessary with selecting eras.
There is continues to be a risk that users get surprises after a hard fork. Providing `local` and `network` selectors will just mean that users will get
choose what kind of surprises they may get.
Comment on lines +90 to +92
Copy link
Collaborator

@carbolymer carbolymer Sep 15, 2023

Choose a reason for hiding this comment

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

Suggested change
* The possibility of a hard fork means tradeoffs are necessary with selecting eras.
There is continues to be a risk that users get surprises after a hard fork. Providing `local` and `network` selectors will just mean that users will get
choose what kind of surprises they may get.
* The possibility of a hard fork means tradeoffs are necessary with selecting eras.
There continues to be a risk that users get surprised after a hard fork. Providing `local` and `network` selectors will just mean that users will get to
choose what kind of surprises they may get.

Can you rewrite this point, it's unclear what surprises are meant here?

* Third party tools will need to consider how to code around an impending hard fork boundary by being aware of what changes are coming and code defensively,
Copy link
Collaborator

Choose a reason for hiding this comment

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

Can you add a supporting example what would be a hard-fork-tolerant usage?

choosing the appropriate era selector with the behaviour they need to implement their features in a hard-fork tolerant manner.
Copy link
Collaborator

Choose a reason for hiding this comment

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

Suggested change
choosing the appropriate era selector with the behaviour they need to implement their features in a hard-fork tolerant manner.
choosing the appropriate era selector with the behaviour they need to implement their features in a hard-fork-tolerant manner.

* Users may or may not necessarily be using the current era by default depending on their choices.
Copy link
Collaborator

Choose a reason for hiding this comment

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

What does that mean?

* No default era imposes on the user the burden of either choosing an era or an era selector.
Copy link
Collaborator

Choose a reason for hiding this comment

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

The discussion how era selectors change usage of choosing eras is missing.

* The decision to have a default era is postponed so we're less likely to make the wrong choice.
Copy link
Collaborator

Choose a reason for hiding this comment

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

How so? local would mean hardcoded default era, do I get this right?

2 changes: 1 addition & 1 deletion docs/Architecture-Decision-Records.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
* ✅ [[ADR-1 Default eras for CLI commands]]
* ✅ [[ADR-2 Module structure for generators]]
* 📜 [[ADR-3 Dependencies version constraints in cabal file]]
* 📜 [[ADR-4 Era selectors for CLI commands]]

## Legend

Expand All @@ -11,4 +12,3 @@
* ❌ Rejected
* 🗑️ Deprecated
* ⬆️ Superseded