Skip to content

feat: emulator applied-tx log/index + effect-polymorphic findUtxo#317

Merged
rssh merged 2 commits into
masterfrom
feature/emulator-tx-log-and-findutxo
Jun 29, 2026
Merged

feat: emulator applied-tx log/index + effect-polymorphic findUtxo#317
rssh merged 2 commits into
masterfrom
feature/emulator-tx-log-and-findutxo

Conversation

@rssh

@rssh rssh commented Jun 26, 2026

Copy link
Copy Markdown
Collaborator

Summary

Extends the Scalus Emulator / BlockchainProvider toward use as a full backend (e.g. for a Hydrozoa test/prod backend), in two parts.

Emulator: applied-transaction log + hash index

  • New AppliedTx(tx, slot, spent) — each applied transaction with the slot it was applied at and the inputs it consumed (resolved against the pre-application UTxO set, since they're gone from the live set afterward).
  • Ordered appliedTxLog + by-hash appliedTxIndex; getTransaction / getAppliedTx / hasTx are O(1). appliedTxs stays a materialized set (O(1) field read). clearAppliedTxs resets the log/index while keeping utxos / certState / datums. The index is derived through a single shared EmulatorBase.indexAppliedTxs, so it can't drift from the log.
  • Round-trip fixes: ImmutableEmulator.fromEmulator / toEmulator now preserve certState, and ImmutableEmulator keeps a datum cache so getDatum / asReader resolve datums instead of always returning None (datums were previously lost on the round-trip).
  • resolveSpent iterates the (small) input set instead of scanning the whole UTxO set.

Provider: effect-polymorphic findUtxo

  • findUtxo(input), findUtxos(inputs), findUtxos(address) move from the Future-only BlockchainReader up to BlockchainReaderTF[F], so they work for any effect (e.g. the Scenario monad), not just Future. They share one new mapF primitive — the only capability needed to map over F without imposing an external Functor/Monad constraint; BlockchainReader provides it via its captured ExecutionContext, the Scenario provider via its monad.

Testing

  • sbt jvm/testQuick green (incl. scalus-examples, TxBuilder, Scenario, and emulator suites); JVM + JS compile; scalafmt clean.
  • New tests: emulator applied-tx log / index / clearAppliedTxs / datum round-trip, certState round-trip, and findUtxo / findUtxos(address) through the Scenario-typed provider.

Notes

  • No MiMa impact — scalus-cardano-ledger and scalus-testkit aren't binary-compatibility checked; every new constructor param / field is defaulted, so the change is source-compatible.

rssh added 2 commits June 26, 2026 18:29
Add an ordered applied-tx log (`appliedTxLog`) plus a by-hash index
(`appliedTxIndex`) to the Emulator family, so callers can reconstruct
chain history (full tx + slot + consumed inputs) without their own
bookkeeping. New API: `getTransaction`/`getAppliedTx`/`hasTx` (O(1) via
the index) and `clearAppliedTxs`, which resets the log/index while
keeping utxos/certState/datums. The index is derived through a single
shared `EmulatorBase.indexAppliedTxs` helper so it cannot drift from the
log.

Also fix datum/certState handling around the ImmutableEmulator
round-trip: `fromEmulator`/`toEmulator` preserve `certState`;
ImmutableEmulator now keeps a datum cache so `getDatum`/`asReader`
resolve datums instead of always returning `None`; and the mutable
constructor rebuilds datums from the supplied log. `resolveSpent`
iterates the input set instead of scanning all UTxOs.
Move `findUtxo(input)`, `findUtxos(inputs)` and `findUtxos(address)` from
the Future-only `BlockchainReader` up to the effect-polymorphic
`BlockchainReaderTF[F]`, so they work for any effect (e.g. the Scenario
monad), not just Future. They share one new `mapF` primitive — the only
capability needed to map over `F` without imposing an external
Functor/Monad constraint; `BlockchainReader` provides it via its captured
ExecutionContext and the Scenario provider via its monad.
@rssh rssh merged commit fcc8872 into master Jun 29, 2026
4 of 5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant