workbench: make the tx-generator a workload - #6648
Draft
Russoul wants to merge 8 commits into
Draft
Conversation
The tx-generator was a first-class service of the workbench, side by side
with the nodes, the tracer and the healthcheck. It is now just an entry of
the profile's "workloads" list, named "tx-generator", which removes the
generator-specific code paths from every backend.
Two generalizations of the workloads machinery make this possible:
- "phase" ("before-nodes" | "setup" | "load") replaces the "before_nodes"
boolean. Workloads of the new "setup" phase run to completion after the
nodes are up and before any load workload is started.
- "placement" ("producers" | "explorer") plus a single "entrypoint"
replaces the "entrypoints" pair. Voting's "pre_generator" entrypoint,
which used to be inlined into the generator's "start.sh", is now a
"voting-setup" workload of the "setup" phase.
The typed `Generator` record is kept internally, derived profile
properties need it, and translated to/from the "tx-generator" workload at
the JSON boundary.
`locli` and the run directory keep reading legacy runs: the generator's
configuration is looked up as a top-level "generator" property first and
as the "tx-generator" workload afterwards, so no run needs a "meta.json"
migration.
- `runner.nix` dumped `generator/{stdout,stderr}` when `wb start` failed,
which is now `workloads/tx-generator/{stdout,stderr}`. The `|| true`
made it print nothing precisely when the tx-generator's log was needed.
- `utils/diff.sh` special-cased a "generator-service.json" that the
profile output no longer contains.
…ofiles `P.overlay` merges its JSON object with the profile's JSON encoding, where the generator is not a top-level property anymore but a "tx-generator" entry of the "workloads" array. The "generator" key of `calibrateLoopBlockMemx15` / `calibrateLoopBlockMemx2` was therefore dropped when decoding the merged JSON back into a `Profile`, silently reverting `tx_fee` to the base 1360000 of `V.plutusTypeLoop` in "plutus-volt-memx15-nomadperf", "plutus-volt-memx2-nomadperf", "plutuscall-loop-memx2" and the two "calibrate-blockmem-*-fill" playground profiles. Those fees are the calibrated minimums the nodes' mempool rejections asked for, so the profiles would reject every transaction with "FeeTooSmallUTxO". The fee moves out of the overlays and into the `txFeeOverwrite` primitive, next to the block memory budget primitives it belongs with, and `overlay` now refuses an object with a "generator" key so this can't silently happen again.
`startsecs` is what makes `supervisorctl start` fail when a program dies immediately, which is how a crashing node or tx-generator is caught at start with its logs dumped. A "setup" phase workload, though, is expected to run to completion, and a short one would be reported as a failed start. The scenario waits for those workloads and fails the run using their "exit_code" file instead, so they don't need it.
`cardano-cli conway transaction txid` prints a JSON object with a
"txhash" property, not a bare transaction id. The whole object ended up
in the `tx_id` variables, so `query tx-mempool tx-exists` rejected it
("Failed to deserialise as TxId", once a second) and the "wait until the
transaction is not in the mempool anymore" loop of `funds_submit_retry`
never finished: a voting run stalls in its fund splitting phase until the
scenario's force-termination. The same value is also fed to `jq` as
`--argjson`, which rejected it too.
Not related to the tx-generator becoming a workload: these three call
sites are the same on master, where voting profiles are equally stuck.
The voting flow is now a "voting-setup" workload of the "setup" phase and a "voting" workload of the "load" phase, and the latter is not started until the former exits. But `workflow_generator` still waited for `proposals_count` proposals: the total, which includes the withdrawal proposals that the producers create in the "load" phase. The setup phase could therefore never finish, it waited for proposals that only its successor creates. Before this commit's parent the two overlapped, so the total was the right thing to wait for. Wait for the proposals it creates itself instead, the constitution(s) from genesis. `workflow_producer_deployed` already waits for the full count after creating its own proposal and before voting.
`cardano-cli` downloads a proposal's "--anchor-url" to check it against
"--anchor-data-hash" when building the transaction. Both URLs pointed at
the "master" branch of "github.com/cardano-foundation/CIPs", so when the
CIP-0100 common schema changed upstream every voting run started failing
to create its constitution proposal:
Error: Hash of the file is not valid. Hashes do not match!
Expected: "9d99fbca260b2d77e6d3012204e1a8658f872637ae94cdb1d8a53f4369400aa9"
Actual: "c407dda548dbbbfb4dc89b5a980f75fe0b7b6721d33d8f151ea3e711bede3cda"
Point both at a commit instead, and update the CIP-0100 hash to the one
of the file at that commit. The CIP-0108 example is unchanged there. The
commit hash is abbreviated because the ledger rejects an anchor URL of
more than 128 bytes ("Text exceeds 128 bytes", 135 with the full hash).
`cardano-cli` downloads "--constitution-url" when building the proposal's transaction and refuses to build if the document does not hash to "--constitution-hash": Error: Hash of the file is not valid. Url: https://ipfs.io/ipfs/Qmdo2J... Expected: "860f614bdfc26c070f53c7287460288e38d0569c54c43ebd7c90c5ad79b2e0ef" Actual: "a77245f63bc7504c6ce34383633729692388dc1823723b0ee9825743a87a6a6d" The hash was the one of a dummy text file created next to it ("My Constitution: free mate and asado"), which never was the content of the IPFS document the proposal points to. Hash that document instead, with `hash anchor-data --url`, and drop the dummy file.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
The tx-generator was a first-class service of the workbench, side by side with the nodes, the tracer and the healthcheck. It is now just an entry of the profile's
workloadslist, namedtx-generator, which removes the generator-specific code paths from every backend (start-generator,allocate-run-directory-generator,stop-all-generator,download-{logs,zstd,config}-generator,generator-service.json, thewithGeneratorsupervisord program, ...).Two generalizations of the workloads machinery make this possible:
phase(before-nodes|setup|load) replaces thebefore_nodesboolean. Workloads of the newsetupphase run to completion after the nodes are up and before any load workload is started; the scenario fails the run if a setup workload exits non-zero.placement(producers|explorer) plus a singleentrypointreplaces theentrypointspair. Voting'spre_generatorentrypoint, which used to be textually inlined into the generator'sstart.sh, is now avoting-setupworkload of thesetupphase, placed next to the tx-generator.On the Nomad backends,
placementis resolved by a newworkload-target-nodessubcommand, which replaces the hardcoded "every producer" assumption in log fetching, stopping and waiting.Profile-side, the typed
Generatorrecord is kept internally (derived properties need it) and translated to/from thetx-generatorworkload entry at the JSON boundary. All 132 golden profiles are regenerated accordingly; the profile name set is unchanged.Backwards compatibility:
locliand the run directory keep reading legacy runs — the generator's configuration is looked up as a top-levelgeneratorproperty first and as thetx-generatorworkload afterwards — so no historical run needs ameta.jsonmigration.Follow-up commits, all found while reviewing and test-running this:
tx_feeof the block memory budget profiles. An overlay's"generator"key can no longer reach the generator through the profile's JSON encoding, soplutus-volt-memx15-nomadperf,plutus-volt-memx2-nomadperf,plutuscall-loop-memx2and the twocalibrate-blockmem-*-fillplayground profiles silently lost their calibrated fee and would have rejected every transaction withFeeTooSmallUTxO. The fee moves to thetxFeeOverwriteprimitive andoverlaynow rejects a"generator"key.startsecsis dropped forsetupphase workloads, which are expected to run to completion; the other phases keep it as the immediate-crash detector.workflow_generatorwaited for the totalproposals_count, which includes the withdrawal proposals the producers create in theloadphase — unreachable now that the phases no longer overlap. It waits for its own constitution instead.generator/directory.Three more, all pre-existing breakage of the voting workload that this branch merely surfaced (identical on master, where voting profiles are equally stuck):
cardano-cli conway transaction txidprints JSON now, soquery tx-mempool tx-existsnever resolved and the fund splitting looped forever.masterbranch, whose content drifted away from the recorded hashes; they are pinned to a commit (abbreviated — the ledger caps an anchor URL at 128 bytes).--constitution-hashwas the hash of a dummy local text file, never of the IPFS document--constitution-urlpoints at.Checklist
See Running tests for more details
CHANGELOG.mdfor affected package.cabalfiles are updatedhlint. See.github/workflows/check-hlint.ymlto get thehlintversionstylish-haskell. See.github/workflows/stylish-haskell.ymlto get thestylish-haskellversionghc-9.6andghc-9.12