Skip to content

Tx evaluation#378

Open
ginnun wants to merge 3 commits into
mainfrom
feat/tx-evaluation-rebased
Open

Tx evaluation#378
ginnun wants to merge 3 commits into
mainfrom
feat/tx-evaluation-rebased

Conversation

@ginnun
Copy link
Copy Markdown
Collaborator

@ginnun ginnun commented Sep 12, 2025

Resolves #306

Stacked on #537 - merge that one first.

Context

Implements tx evaluation APIs compatible with the Blockfrost.io version:

  • /utils/txs/evaluate
  • /utils/txs/evaluate/utxos

What is added

  • Two new endpoints with integration tests
  • bf-tx-evaluator crate providing native (Rust, via pallas-validate) and external (Haskell, via testgen-hs) evaluators
  • ChainConfigWatch in bf-node - a background task that watches the Cardano node and publishes protocol params + genesis config via tokio::sync::watch, refreshed only at epoch boundaries
  • Node helpers: ledger, utxo, chain_config_watch

What is changed

  • Pallas fork switched to blockfrost/pallas with pallas-validate (phase2 feature) for script evaluation
  • CBOR validation error messages improved (graceful fallback on pallas-hardano formatting failure)
  • Devshell picks up tools needed by the new native deps - m4 (for secp256k1-sys), make/awk/diffutils (for integration tests)
  • cardano-node trace silencing migrated to the newer API
  • CI: CARGO_PROFILE_DEV_DEBUG=0 on integration-test jobs to reduce disk pressure

What is scoped out (now in #537)

  • testgen-hs subprocess handling extracted from crates/node/src/cbor/ into dedicated bf-testgen and bf-error-decoder crates
  • testgen-hs version bump to 10.6.3.1 and release binary downloads switched to blockfrost/testgen-hs
  • build_utils target detection helpers factored out

@ginnun ginnun marked this pull request as draft September 12, 2025 10:03
@cloudflare-workers-and-pages
Copy link
Copy Markdown

cloudflare-workers-and-pages Bot commented Sep 12, 2025

Deploying blockfrost-platform with  Cloudflare Pages  Cloudflare Pages

Latest commit: 3bd7bfd
Status: ✅  Deploy successful!
Preview URL: https://e1927172.blockfrost-platform.pages.dev
Branch Preview URL: https://feat-tx-evaluation-rebased.blockfrost-platform.pages.dev

View logs

Copy link
Copy Markdown
Member

@michalrus michalrus left a comment

Choose a reason for hiding this comment

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

Hey, I started reviewing, but then noticed that it's a draft! Left a few comments either way :)

Comment thread nix/internal/unix.nix Outdated
Comment thread nix/internal/unix.nix Outdated
Comment thread src/api/utils/txs/evaluate/model.rs Outdated
Comment thread crates/testgen/src/testgen.rs Outdated
Comment thread crates/node/src/cbor/fallback_decoder.rs Outdated
@ginnun ginnun force-pushed the feat/tx-evaluation-rebased branch 3 times, most recently from c702f03 to a53a53c Compare September 22, 2025 12:06
@ginnun ginnun changed the title Feat/tx evaluation rebased Tx evaluation Sep 23, 2025
@ginnun ginnun force-pushed the feat/tx-evaluation-rebased branch 2 times, most recently from 3bcc5c5 to e67b1a9 Compare October 10, 2025 11:35
@ginnun ginnun marked this pull request as ready for review December 15, 2025 10:02
@ginnun ginnun force-pushed the feat/tx-evaluation-rebased branch from 6980be7 to f269525 Compare January 16, 2026 09:32
@michalrus
Copy link
Copy Markdown
Member

Maybe let's have a simpler merge commit for the current conflicts? 🥺 Unless you're using git-rerere.

@michalrus
Copy link
Copy Markdown
Member

I've just merged main into this PR in cd2794a — I hope correctly… … 🫣

Copy link
Copy Markdown
Member

@michalrus michalrus left a comment

Choose a reason for hiding this comment

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

I pushed another merge with main, because there were some more conflicts to resolve. I hope I did that correctly!

Now I see that cargo test tests are failing:

❯ cargo nextest run --workspace --lib --verbose

…

     Summary [  76.650s] 650 tests run: 195 passed, 455 failed, 0 skipped

Stuff like:

        FAIL [   1.058s] blockfrost-platform-error-decoder external::tests::test_cbor_0001_ConwayTreasuryValueMismatch_Coin_Coin

Or:

        FAIL [   1.086s] blockfrost-platform-error-decoder tests::specific::test_cbor_0013_ConwayWdrlNotDelegatedToDRep_KeyHash_KeyHash

@michalrus
Copy link
Copy Markdown
Member

Maybe the tests are failing because my commits updated testgen-hs to 10.4.1.2 also in the devshell. And it's the one against which the old CBOR tests are being run. 🤔

@ginnun
Copy link
Copy Markdown
Collaborator Author

ginnun commented Feb 20, 2026

Everything is working related to this PR. The CI failure is caused by updated ledger codebase coming from the testgen-hs binary

@michalrus
Copy link
Copy Markdown
Member

michalrus commented Feb 23, 2026

The CI failure is caused by updated ledger codebase coming from the testgen-hs binary

So what do you suggest to be a solution here?

Maybe update testgen-hs in a separate PR, to not mix them, and fix it there? And park this one until we're again matching the Haskell trasaction submission errors?

(I think we shouldn’t be merging "red" ❌ PRs.)

@michalrus
Copy link
Copy Markdown
Member

@ginnun wait, but why did I get the same error in:

I don’t have your changes (the updated testgen-hs).

So the integration tests would also fail on main now? Perhaps due to devops updating cardano-node in the "legacy" Blockfrost API?

@michalrus
Copy link
Copy Markdown
Member

Look here:

Deploying cardano-node version v10.6.2 to dev hosts

on 2026-02-19T02:55:30,167769000+00:00.

@ginnun
Copy link
Copy Markdown
Collaborator Author

ginnun commented Feb 23, 2026

So what do you suggest to be a solution here?

The plan is to fix/update the code for pallas/hardano. Until than, we can disable that specific test since it will fail for every branch. What do you say @michalrus ?

@michalrus
Copy link
Copy Markdown
Member

The plan is to fix/update the code for pallas/hardano.

Great! Here's a tracking issue for this new work:

@michalrus
Copy link
Copy Markdown
Member

michalrus commented Feb 23, 2026

Until than, we can disable that specific test since it will fail for every branch. What do you say @michalrus ?

I suppose… Hmm, WDYT, @vladimirvolek?

This temporary fix is in:

@ginnun ginnun force-pushed the feat/tx-evaluation-rebased branch 2 times, most recently from a4a277d to dde536f Compare February 27, 2026 15:03
Comment thread nix/internal/unix.nix Outdated
Comment thread nix/internal/unix.nix Outdated
@ginnun ginnun force-pushed the feat/tx-evaluation-rebased branch from 6642500 to 1db6c61 Compare March 2, 2026 15:02
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 70 out of 72 changed files in this pull request and generated 4 comments.

Comments suppressed due to low confidence (1)

src/server.rs:2

  • This file is currently empty and the workspace root has no [package], so it is unused. Keeping an empty src/server.rs in the repository is confusing and may suggest there is a root crate/module. Please remove it if it’s accidental.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread crates/tx_evaluator/src/wrapper.rs Outdated
Comment thread crates/tx_evaluator/src/ogmios5_response.rs
Comment thread crates/node/src/chain_config_watch.rs
Comment thread crates/tx_evaluator/src/external.rs
Copy link
Copy Markdown
Member

@michalrus michalrus left a comment

Choose a reason for hiding this comment

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

Note to self for when this PR is close to a merge:

Let's have a small PR to move testgen-hs handling on main in accordance to what the tx-eval PR did – for better view of conflicts and what really changed

(requesting changes so that it's not lost)

@ginnun ginnun marked this pull request as ready for review April 16, 2026 14:55
@ginnun ginnun requested a review from michalrus April 16, 2026 14:55
@ginnun
Copy link
Copy Markdown
Collaborator Author

ginnun commented Apr 17, 2026

Note to self for when this PR is close to a merge:

Let's have a small PR to move testgen-hs handling on main in accordance to what the tx-eval PR did – for better view of conflicts and what really changed

(requesting changes so that it's not lost)

@michalrus This is in the making.

@ginnun ginnun force-pushed the feat/tx-evaluation-rebased branch from aca4175 to 3b95456 Compare April 17, 2026 15:31
@ginnun ginnun changed the base branch from main to refactor/testgen-hs-handling April 17, 2026 15:36
@ginnun ginnun force-pushed the refactor/testgen-hs-handling branch from b625eed to 75aee91 Compare April 28, 2026 10:58
- chore: add devshell tools and CI tweaks for tx evaluation
- chore: update workspace deps for tx evaluation
- feat(common): add lazy chain config loader and helpers
- fix(node): improve CBOR validation error messages
- feat(node): add chain config, ledger, and utxo helpers
- feat: add bf-tx-evaluator crate with native and external evaluators
- feat(platform): add /utils/txs/evaluate endpoints
- test: add coverage for tx evaluate endpoints
@ginnun ginnun force-pushed the feat/tx-evaluation-rebased branch from 3b95456 to b02c4a6 Compare April 29, 2026 06:32
@vercel
Copy link
Copy Markdown

vercel Bot commented Apr 29, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
blockfrost-platform-docs Ready Ready Preview, Comment May 12, 2026 0:31am
blockfrost-platform-docs-next Ready Ready Preview, Comment May 12, 2026 0:31am

Request Review

@ginnun
Copy link
Copy Markdown
Collaborator Author

ginnun commented Apr 29, 2026

Failing tests are unrelated to this PR.

For evaluate failure, please see blockfrost/blockfrost-tests#73

Copy link
Copy Markdown
Member

@michalrus michalrus left a comment

Choose a reason for hiding this comment

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

A couple questions – the most important one is about the mempool omission:

Comment thread Cargo.toml
pallas-network = { git = "https://github.com/txpipe/pallas.git", rev = "ed422bc0d5a09f77617d4882dd4c71089a8bcdb2" }
pallas-primitives = { git = "https://github.com/txpipe/pallas.git", rev = "ed422bc0d5a09f77617d4882dd4c71089a8bcdb2" }
pallas-traverse = { git = "https://github.com/txpipe/pallas.git", rev = "ed422bc0d5a09f77617d4882dd4c71089a8bcdb2" }
pallas-addresses = { git = "https://github.com/blockfrost/pallas.git", rev = "cfa0c633640f5989e44f50ed27efc38992f9ed0d" }
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

There has been one more commit since then in your PR – txpipe/pallas@9a83c74


utxos.insert(TxoRef::from(&multi_era_in), EraCbor::from(multi_era_out));
}
let mut node = node_pool.get().await?;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I don't see this comment here. Maybe more like FIXME, not TODO? 🫣

@@ -37,5 +37,7 @@
"/epochs/latest/parameters",
"/genesis",
"/addresses/{address}/transactions",
"/addresses/{address}/utxos"
"/addresses/{address}/utxos",
"/utils/txs/evaluate",
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I should underline, we don't have mempool integration yet (Ogmois does use mempool + chain)

  • So the implementation is not equivalent, even though we're deferring to Haskell code?
  • Shouldn’t we add it before releasing? 👀
  • How hard is it?
  • And why isn’t it caught by blockfrost-tests?

Comment on lines +92 to +104
Err(e) => {
tracing::warn!(
"ChainConfigWatch: failed to refresh chain config: {e}. Retrying in {}s.",
RETRY_INTERVAL.as_secs()
);
tokio::select! {
() = time::sleep(RETRY_INTERVAL) => {},
() = tx.closed() => {
tracing::info!("ChainConfigWatch: stopping monitor");
return;
},
}
},
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

So between the epoch boundary and successful refresh, stale protocol params would be used by eval? And the refresh might only practically fail if a node is down?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

@michalrus Yes that is correct. Alternatively we can fail (or wait) evaluate calls on epoch boundary but that might be fragile. Another (bad) option is to never cache those values.

let (tx, rx) = watch::channel(None);

tokio::spawn(async move {
monitor_loop(node_pool, tx).await;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Can this panic? 👀 It seems rather crucial for correct eval results, and we wouldn't restart it then, no?

) -> Result<MultiEraProtocolParameters, BlockfrostError> {
// Create a Conway protocol parameters struct from the ProtocolParam and GenesisConfig
let conway_pp: ConwayProtParams = ConwayProtParams {
minfee_a: pp.minfee_a.required("minfee_a")? as u32,
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Why are they u64 in CurrentProtocolParam, but u32 in ConwayProtParams? Are these multiple conversions always safe?

let tx_id = utxo
.get("transaction")
.and_then(|transaction| transaction.get("id"))
.unwrap_or(&Value::Null);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Is the null okay here, or should we error?

- Native is based on `pallas-validate`.
- External is using `ledger` codebase via `testgen` Haskell binary.

`native` produces different evaluation results when compared to `external` at the moment. Knowing that `external` depends on the ledger codebase, we can consider `external` results accurate.
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

But we don’t implement the mempool part there? 👀

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Yes, no mempool handling. Haskell part doesn't fetch any data from any source. By design, it's the Rust parts that needs to fetch any data and pass it to forward.

if let Some(first_result) = results.first() {
matches!(first_result, TxEvalResultV6::Success(_))
} else {
true
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Can you explain this true here? Why are empty results a success?

Comment on lines +228 to +233
#[derive(Serialize, Deserialize, Debug)]
#[serde(untagged)]
pub enum EvaluationError {
Evaluation(serde_json::Value),
Deserialization(DeserializationErrorData),
}
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Since this is #[serde(untagged)], and the first variant is arbitrary JSON, the deserializer would never reach the second variant 🤔 Do we ever use the deserializer? If not, maybe let's drop it?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add POST /utils/txs/evaluate – how many execution units for a transaction

5 participants