Skip to main content

Plutus Core Team Update

· 2 min read
Ziyang Liu
Software Engineering Lead

High level summary

The Plutus team has recently opened two CIPs and one CPS for review. We encourage everyone to read them and leave comments - we would like as much feedback as possible.

  • CIP-0194 adds a Match node to UPLC for matching on builtin constants (primarily Data). This will make consuming script contexts in validators much cheaper than the status quo.
  • CIP-0195 specifies the Data encoding of the Plutus V4 ledger types.
  • A new CPS aims to build community consensus on how to expose our property tests, and tests for older protocol and language versions, to alternative node and UPLC evaluator implementers with minimal integration effort.

Other than these, we've merged the CollapseCase pass, which rewrites list casing into dropList whenever applicable; the uplc tool now deduces input and output formats from file extensions; and the Plutus V4 ledger API types have been released in 1.67.0.0.

Key Pull Requests Merged

Pull Requests In Progress

Hydra Team Update

· 6 min read
Noon van der Silk
Software Engineering Lead

What did the team achieve?

  • Released 2.3.0, headlined by the reapplyTx snapshot-processing speedup, node configuration via YAML file, native PaymentExtendedKey (HD wallet) key support #2583, and the batch of rotation, Blockfrost and network-layer resilience fixes from the last two updates. Note that all the subsequently listed work has not yet been released
  • Merged the performance stack #2776-#2780, in five reviewable pieces:
    • accumulator commitments are now computed through the rust-accumulator FFI (bit-identical, pinned by equivalence and golden tests) and updated incrementally from the previous confirmed snapshot, taking the 4k-UTxO commitment from 2.13s to 25ms #2780
    • BREAKING: broadcast messages are batched into a single etcd value, one Raft commit per batch over a reused gRPC connection. This bumps the network protocol version to 2, so all members of a head must upgrade together #2778
    • maxTxsPerSnapshot raised from 100 to 1000, leader-side only so no coordinated upgrade is needed #2777
    • SQLite event encoding moved onto the write-behind thread, keeping serialisation of large SnapshotRequested events off the node loop between processing a ReqSn and broadcasting the AckSn #2779
    • plus the measurement and benchmark infrastructure the whole stack was driven from #2776
  • Implemented selective partial fanout: a new PartialFanout client input lets you distribute a chosen subset of the closed head's UTxO, with a HeadPartiallyFannedOut server output telling clients whether the node keeps draining or awaits the next selection, a FanningOut head status, and a matching TUI flow. Only the node that issued the command drives the step, so observers can't steamroll UTxO another party deliberately left behind #2750, #2333, with a docs page to go with it #2794
  • BREAKING: --deposit-period is now embedded in the on-chain OpenDatum at Init time, so all nodes in a head must agree on it; a mismatch emits IgnoredHeadInitializing and the node ignores the head, the same way contestation period mismatches already worked #2734
  • Added --deposit-activation to decouple activation from the deadline calculation: it controls only the Inactive -> Active transition while --deposit-period keeps its deadline and expiry role, giving three independent windows (maturity, active, recovery). The default of 3600s reproduces the old behaviour exactly #2802, #2744
  • POST /commit now rejects deposits that could never be claimed. A dry-run increment is checked against the L1 maximum transaction and serialized value sizes, returning a new DepositTooLarge error. Previously the deposit would land on-chain and the increment claiming it could never be submitted, wedging further incremental commits and locking the funds until recovery after the deadline #2807
  • Fixed long-running nodes rejecting every layer 2 Plutus transaction carrying a validity bound: the era history queried at startup has a forecast horizon (36 hours on mainnet), and once past it those transactions failed with PastHorizon until restart. The last era is now unbounded for L2 ledger time conversions #2803, #2798
  • BREAKING (WebSocket API): removed the SyncedStatusReport server output, which the node pushed on every block. Sync status is now edge-triggered via NodeUnsynced/NodeSynced and Greetings.chainSyncedStatus, and the continuous drift value became a hydra_chain_drift_seconds metric alongside a new hydra_chain_last_block_timestamp_seconds so a stalled chain backend is detectable even while drift is frozen #2769, #2749
  • Made hydra-chain-observer version-aware: it detects which protocol version an observed transaction belongs to by matching head and deposit script hashes against a registry in networks.json covering 0.13.0 through 2.2.0, removing the compile-time coupling to a single version and the hydra-plutus dependency altogether #2740
  • Fixed pasting into hydra-tui text fields (bracketed paste mode, so a paste arrives as one event and typing c into an address no longer cancels the dialog) and stopped it submitting stale form values when the entered address or amount was invalid #2770
  • Made the mac release binaries runnable without nix: they were hard-linking libraries out of /nix/store and simply wouldn't launch on a plain machine #2795, #2461
  • Bumped Mithril to 2630.0 and switched to the v2 database backend, since the aggregator no longer certifies v1 #2808
  • Docs fixes: the transaction-cost benchmark page is now generated by the docs build instead of being dropped in as raw markdown afterwards, so it renders with the current theme and stops listing removed transactions #2799, and the fanout cost table now sweeps party counts #2796

What's next?

  • Complete the typst + Agda specification work, split into a reviewable stack: a protocol fix forbidding a commit and a decommit in flight simultaneously #2784, the prose migration from LaTeX to Typst #2785, the Agda formalisation itself #2786, a hydra-agda package extracted via MAlonzo with a CI gate #2787, and differential tests checking the node and validator against that reference #2788
  • Switch the event store to CBOR #2767 and offer an opt-in binary encoding on the client API #2762
  • Iterate on ADR 34, covering the separation of hydra-chain-observer into a service shared by several nodes #2771
  • Make rejectLowDeposits a single pass rather than quadratic #2805
  • Get a release out with the performance stack and selective partial fanout

Ledger Team Update

· 4 min read
Alexey Kuleshevich
Ledger Team Software Engineer

High level summary

Leios support in the ledger took another step forward this cycle: pool parameters now carry an actual BlsKey, replacing the placeholder types introduced previously. On the testing side, block-header serialization - Praos and Leios alike - is now covered by a dedicated round-trip test suite, giving early guard-rails on the wire format as the Leios header evolves.

Work on nested transactions in Dijkstra advanced as well: the withdrawal mechanism for sub-transactions was implemented. Predicate failures around this area were reworked to be more useful and consistent, moved into the layer the specification prescribes and given clearer names. We settled how UTxO state updates should behave under nested transactions and the AdaPots obligations invariant guard-rail was adapted accordingly. A field for the initial account balance was also added to the top-level transaction body.

On the Plutus side, a per-block script cache was introduced so that scripts decoded once for a transaction can be reused by later transactions within the same block. A related optimization now memoizes the computation of the script hashes a transaction needs.

Two CIPs advanced this cycle. CIP-50 (pledge-leverage-based staking rewards) was implemented, and groundwork for CIP-23 began with the addition of the minPoolMargin protocol parameter to the Dijkstra era.

Test coverage was expanded: the Conway conformance suite was enabled in Dijkstra, and new tests were added around stake calculations and sub-transactions - as far as the current test framework allows.

Low level summary

Features

  • PR-5945 - Fix JSON roundtrip for InjectionData
  • PR-5946 - Make AlonzoTx mempool decoder backwards compatible
  • PR-5942 - Optimize plutus script preparation
  • PR-5953 - Reuse script cache for script validation
  • PR-5952 - Add startingAccountBalanceInterval to TopTx body
  • PR-5930 - Fix deposits in AdaPots calculations
  • PR-5941 - Fix updating of UTxOState
  • PR-5947 - Add canonical ledger state CDDL spec and validation tests
  • PR-5938 - Rename isValid to isPhase2Valid
  • PR-5967 - Move network checks of deposits and withdrawals to (SUB)ENTITIES
  • PR-5961 - Remove unnecessary setup of the DRepPulser
  • PR-5960 - Memoize getScriptsHashesNeeded in StanTx
  • PR-5969 - Withdrawals rework in SubEntities
  • PR-5943 - CIP-50 Pledge Leverage-Based Staking Rewards
  • PR-5891 - Add BlsKey in StakePoolParams
  • PR-5854 - Add ToJSON/FromJSON instances for EraTxWits
  • PR-5949 - CIP-23 - Add minPoolMargin protocol parameter to Dijkstra era
  • PR-5950 - Drop EncCBORGroup BlockBody in Dijkstra
  • PR-5909 - Stable type for querySetSnapshotStakePoolDistr

Testing

  • PR-5939 - Enable Conway conformance tests in Dijkstra
  • PR-5959 - Test collateral inputs are in utxo
  • PR-5971 - Add Imp test to test that DReps unregistered and reregistered in the same tx lose vote delegated stake
  • PR-5948 - Add serialization tests for block headers
  • PR-5975 - Add stake calculation tests for conway

Infrastructure and releasing

  • PR-5874 - Update cardano-binary to 1.9.1.0
  • PR-5968 - Restore <2.6 bound for cardano-crypto-class
  • PR-5970 - Bump cardano-data version for release
  • PR-5976 - Correct a bad changlog entry

Mithril Team Update

· 4 min read
Jean-Philippe Raynaud
Mithril Tech Lead

High level overview

This week, the Mithril team released the 2630 distribution. This version promotes the DMQ node 0.7.0.0 as beta on the release-mainnet and release-preprod networks, activates the testing phase of the Cardano blocks and transactions certification on the pre-release-preview and release-preprod networks, removes the support for the CardanoImmutableFilesFull certificate type in the Mithril signer and aggregator, and includes various bug fixes and improvements.

The team also completed the assessment of the catchup from the genesis certificate for a SNARK follower aggregator and the encoding of the aggregate signature of the certificate message as bytes, and stopped forcing the rustls TLS backend in the future_snark feature of the STM library. They continued combining the dual MSM and accumulator pairing checks in the IVC proof verification, and reusing the cached unsafe SRS in the SNARK test setups.

They also completed the creation of a local IPFS network for a proof-of-concept of decentralized delivery of Cardano database artifacts, and continued implementing the aggregator CLI commands and the new chain adapter for on-chain configuration parameters, as well as the runbook documenting them.

Finally, the team upgraded the documentation website to Docusaurus 3.10.2 and tailwind v4, completed shipping the Mithril signer node binary in the Cardano node bundle, and continued upgrading to Cardano node v.11.1 and fixing the flakiness of the end-to-end tests in the CI.

Low level overview

Features

  • Completed the issue Assess catchup from genesis certificate for SNARK follower aggregator #3389
  • Completed the issue Stop forcing rustls in the future_snark feature of STM #3423
  • Completed the issue Use bytes encoding for aggregate signature in certificate message #3379
  • Completed the issue Create a local IPFS network #3434
  • Worked on the issue Implement aggregator CLI commands for configuration parameters #3392
  • Worked on the issue Create new chain adapter to read on-chain configuration parameters #3393
  • Worked on the issue Combine the dual MSM and accumulator pairing checks in IVC proof verification #3420
  • Worked on the issue Reuse the cached unsafe SRS in the SNARK test setups #3433

Protocol maintenance

  • Released the new distribution 2630.0
  • Published a dev blog post Distribution 2630 is now available
  • Published a dev blog post DMQ node beta on the release networks
  • Completed the issue Release 2630 distribution #3271
  • Completed the issue Update DMQ node to 0.7.0.0 #3358
  • Completed the issue Update documentation website to docusaurus stable version 3.10.2 #3413
  • Completed the issue Update documentation website to tailwind v4 #3414
  • Completed the issue Remove plausible from documentation website #3447
  • Completed the issue Admonitions are broken in blog posts #3455
  • Completed the issue Ship Mithril signer node binary in Cardano node bundle in GitHub #3011
  • Worked on the issue Upgrade to Cardano 11.1 #3346
  • Worked on the issue Create runbook for on-chain configuration parameters #3399
  • Worked on the issue Fix flakiness of e2e tests in the CI #3452

Performance & Tracing Update

· 7 min read
Michael Karg
Performance and Tracing Team Lead

High level summary

  • Benchmarking: Van Rossem HF: Created and performed benchmarks for new Plutus execution budgets and internals; PlutusV3 baseline shift.
  • Development: Hermod package restructre completed; cardano-config support in trace-dispatcher.
  • Infrastructure: Genesis cache overhaul / Protocol Version 11 overlay have landed.
  • Tracing: Alert manager feature for cardano-tracer in design phase; native support for spans in Hermod.
  • Leios: Major new beacon feature to impose memory limits; on-disk LedgerDB tx validation times benchmark in the works.

Low level overview

Benchmarking

The P&T team has been safeguarding the now enacted Van Rossem hard fork, which brings Protocol Version 11 with new Plutus internals and a bump to the execution budgets to mainnet. Our benchmarking automation framework, the performance workbench, gained new chain-fragment-creation profiles as well as new plutuscall-* profiles, targeting those new Plutus features specifically (cardano-node PR#6627 and cardano-node PR#6440). The former PR also adds a wb chain-fragment export op, which packages a profile run's node database, genesis files and a path-patched node config into a chain fragment consumable by beacon tool — the tooling behind the on-disk benchmarks described under Leios below.

The benchmarks performed using those new profiles have shown that the execution budget raise leads to a reasonable, predictable and expected increase in Block Adoption times. For the new PlutusV3 internals, they've also shown that they're consistently priced relative to the existing internals, and that, even when executed up to full budget exhaustion, there were no performance regressions in their implementation.

To enable those benchmarks, work has been well underway on extending plutus-scripts-bench with PlutusV3 variants of the existing scripts, and adding two new PV11 scripts targeting the new execution internals: MultiScalarMulG1 (BLS12-381 multi-scalar multiplication based on CIP-0133), and ExpModInteger, exercising the new expModInteger builtin (cardano-node PR#6440). The PR wires these through to tx-generator, and gives our analysis tool locli a new PlutusBudgetSummary module to output Plutus workload calibration data as part of comparison reports. The PR is currently under review.

Development

The long-planned restructuring of trace-dispatcher into separate Hermod packages, which we reported as underway last month, is now complete (hermod-tracing PR#16). The stable API surface — trace types, LogFormatting/MetaTrace instances, and the structural/annotation combinators — now lives in a lightweight hermod-tracing-api package, itself split into an internal and a public sublibrary, so that packages which only need to instrument their own code no longer pull in EKG, Prometheus, CBOR forwarding or the YAML config parser as dependencies. The full backend stack remains in hermod-tracing-core, while the Prometheus TCP server has been carved out into its own optional hermod-tracing-prometheus package. All modules and identifiers were renamed from Cardano.Logging.*/TraceDispatcherMessage and friends to their Hermod.Tracing.* equivalents, and trace-dispatcher itself has been kept around as a backward-compatible mirror so existing pinned consumers keep building unchanged until they migrate.

Last but not least, we've added compatibility with the cardano-config library to trace-dispatcher (hermod-tracing PR#18).

Infrastructure

The genesis cache overhaul and full Protocol Version 11 overlay for our performance workbench, close to merging as of last month, have now landed (cardano-node PR#6544). Beyond the split-cache "ripper" backend and the restoration of non-default Plutus cost models via the Alonzo genesis extraConfig field reported previously, the merged PR also standardises genesis creation on cardano-cli's create-testnet-data (retiring the old create-staked path and the separate byron genesis step), makes the era an explicit, validated input to wb start and wb run allocate via a new --era-name flag, and simplifies the workbench CLI to named flags only. A handful of breaking changes ship alongside: WB_BACKEND is renamed to WB_BACKEND_NAME, --relays and the genesis "spec" sub-command are removed, and non-default Plutus cost models must now be supplied through extraConfig. Analysis of older runs is unaffected, as wb analyse falls back to the previous genesis layout when the new one is absent.

Tracing

We've begun designing a central alarm system for cardano-tracer (alarm system concept). Today, operators typically rely on third-party tooling for this — something built on top of Grafana, the Prometheus Alertmanager, or Loki log analysis — but there's no solution native to the tracing and metrics stack, and none that takes a unified approach across trace messages and metrics. The idea is to instead give cardano-tracer a single place that collects alarms from multiple sources — our hermod-recon verifier flagging a violated property, a rule evaluated against the metrics cardano-tracer already stores, or simply a trace message severe enough to warrant attention — and forward them to wherever operators want to be notified — typically a paging service's webhook API, but custom webhooks, email, and plain logging are supported too — while keeping a queryable history of past alarms. It deliberately stays a one-shot notification layer rather than a full incident tracker: there's no acknowledgement or resolution workflow, that's left to whatever tooling operators already use for that. This is still an early design and not yet reflected in any implementation work.

On the Hermod side, we're also exploring native support for nested spans, in the spirit of tracing systems like OpenTelemetry. A span represents a bounded unit of work — say, processing a single transaction or forging a block — and the point is to let automated log analysis reconstruct not just individual events, but how long an operation took and how it decomposes into sub-operations, by pairing up an opening and a closing trace message that share a unique identifier. The tricky part is Haskell's laziness: without care, an expression's evaluation, and the trace events it triggers, can end up happening after its enclosing span has already been closed, so a fair amount of the design work goes into guaranteeing that no trace event ever escapes the span it logically belongs to. There's no branch to point to yet — this is still exploratory work.

Leios

Building on the chain-fragment export tooling introduced above, beacon — the ledger ops benchmarking tool in ouroboros-consensus-tools — gained a memory-limiting feature aimed squarely at tx validation times using an on-disk LedgerDB backend and forcing disk I/O at the same time (beacon PR#12, currently under review).

A new flag forces the LSM (on-disk) backend to genuinely exercise disk I/O, rather than being served invisibly out of the OS page cache; --mem-limit/--heap-limit cgroup caps serve as a fallback for past db-analyser builds without support for that new flag. Every run now records peak RSS and block I/O counts. A representative "sweet spot" using those new mechanisms has been determined empirically for the chain fragments used in this year's April measurements. This finally gives us concrete on-disk LedgerDB metrics by determining the overhead of I/O-backed validation times vs. pure ones, closing a gap in our Leios throughput benchmarking. A new beacon/docs/METHODOLOGY.md documents the overall approach; benchmarks are currently being performed on our benchmarking cluster, to obtain measurements on the same hardware as we did in April for the in-memory backend — but now with LSM backend forced to perform disk I/O.