shared: live PostAdvert + delegate UPLC eval to Ogmios
Two production-essential fixes that surfaced during the path-A TTS deployment to Vector testnet: 1. localUPLCEval: false on every Plutus V3 spend ────────────────────────────────────────────── lucid-evolution 0.4.30's CML WASM UPLC evaluator has a false-rejection bug for our V3 spend pattern: it rejects perfectly valid txs with "failed script execution Spend[0] the validator crashed / exited prematurely" while the chain itself accepts them without complaint. Routing eval to Ogmios's evaluateTransaction (cardano-node's evaluator) sidesteps the WASM bug and returns correct ex-units. OgmiosLucidProvider.evaluateTx already implements this path. This also unblocks the 5 tx-submit-live tests previously skipped with the comment "UPLC wasm crashes" (M1-F-D-defer / task #28). Without this fix, every Claim/Submit/Accept tx from our supplier was failing locally before reaching the chain. The third-party summitstak.ing supplier worked because it uses a different toolchain that does not run client-side phase-2 evaluation. 2. AdvertDatum BigInt coercion ──────────────────────────── cbor-x emits float64 (`fb` prefix) for JS Number values that can't fit CBOR's compact int forms (e.g. POSIX-ms timestamps). Plutus Data has no float type, so CML.PlutusData.from_cbor_hex panics with "RuntimeError: unreachable" when it sees one. Coerce max_output_tokens, max_processing_ms, advertised_at to BigInt before encoding so cbor-x always emits major-type-0/1 integers. Mirrors the intAsBig pattern already used in EscrowDatum. 3. Live-CBOR PostAdvert builder ───────────────────────────── M1-F-4 deferred postAdvert/updateAdvert/retireAdvert/reclaim/ release on the live path. With (1) and (2) in place, posting an advert via tx:post-advert against Vector testnet now works. Added buildLiveTxForAdvert in liveCbor.ts (mirrors PostEscrow) and routed buildPostAdvertTx through it when chain is live. 40 advert/post-advert tests still pass. Verified end-to-end on Vector testnet: TTS advert posted at 5df793ac12dc426fae7a7a01d56d3e923d3985103d62f0182d9ba63dda871f96#0, full chat + TTS marketplace lifecycle (PostEscrow → Claim → Submit → Accept) confirmed completing successfully on chain.
This commit is contained in:
@@ -118,19 +118,24 @@ export function encodeAdvertDatum(d: AdvertDatum): string {
|
||||
throw new Error(`unknown AdvertStatus: ${String(d.status)}`);
|
||||
})();
|
||||
|
||||
// cbor-x encodes JS Number as float64 (`fb` prefix) for values that don't
|
||||
// fit in CBOR's compact int forms — and Plutus Data has NO float type, so
|
||||
// CML's PlutusData.from_cbor_hex panics with "RuntimeError: unreachable"
|
||||
// when it sees one. Coerce numeric fields to BigInt so cbor-x always emits
|
||||
// CBOR major-type-0/1 integers. Mirrors the intAsBig pattern in EscrowDatum.
|
||||
const cbor = plutusTag(121, [
|
||||
hexToBytes(d.supplier_pkh),
|
||||
utf8Bytes(d.capability_id),
|
||||
utf8Bytes(d.model),
|
||||
d.max_output_tokens,
|
||||
d.max_processing_ms,
|
||||
BigInt(d.max_output_tokens),
|
||||
BigInt(d.max_processing_ms),
|
||||
d.price_lovelace,
|
||||
d.supplier_bond_lovelace,
|
||||
d.buyer_bond_lovelace,
|
||||
utf8Bytes(d.endpoint_url),
|
||||
utf8Bytes(d.detail_uri),
|
||||
hexToBytes(d.detail_hash),
|
||||
d.advertised_at,
|
||||
BigInt(d.advertised_at),
|
||||
statusTag,
|
||||
]);
|
||||
|
||||
|
||||
@@ -19,6 +19,7 @@ import { loadBlueprint } from "../blueprint.js";
|
||||
import { encodeTxBody, sha256Hex } from "../internal/testTxBody.js";
|
||||
import { mockSlotToWallclockMs } from "../internal/constants.js";
|
||||
import { detectCborBackend } from "../internal/cborBackend.js";
|
||||
import type { LiveOgmiosProvider } from "../../chain/LiveOgmiosProvider.js";
|
||||
|
||||
const FIVE_MIN_MS = 5 * 60 * 1000;
|
||||
|
||||
@@ -64,6 +65,19 @@ export async function buildPostAdvertTx(
|
||||
}
|
||||
|
||||
// 4. Construct tx body.
|
||||
// Live path: route to lucid-evolution so the on-chain submission carries
|
||||
// valid Conway-era CBOR. Mock path keeps the JSON-in-hex synthetic body.
|
||||
if (isLive) {
|
||||
const liveCborPath = "../internal/liveCbor.js";
|
||||
const { buildLiveTxForAdvert } = await import(/* @vite-ignore */ liveCborPath);
|
||||
return buildLiveTxForAdvert({
|
||||
chain: chain as LiveOgmiosProvider,
|
||||
walletKey,
|
||||
advertDatum,
|
||||
deposit_lovelace,
|
||||
});
|
||||
}
|
||||
|
||||
const blueprint = loadBlueprint();
|
||||
const advertScriptAddress = blueprint.advertScriptAddress(0);
|
||||
|
||||
|
||||
@@ -342,8 +342,18 @@ async function buildSpendOpenOrClaimedTx(opts: {
|
||||
|
||||
// Let lucid pick coins + compute fee normally; production wallets have
|
||||
// multiple real UTxOs (no need for the test-side leftover-as-fee hack).
|
||||
//
|
||||
// localUPLCEval: false — delegate Plutus V3 phase-2 evaluation to Ogmios
|
||||
// (which uses cardano-node's evaluator). lucid 0.4.30's CML WASM UPLC
|
||||
// interpreter has a false-rejection bug for our V3 spend pattern: it
|
||||
// rejects valid txs with "failed script execution Spend[0] the validator
|
||||
// crashed / exited prematurely" while the chain itself accepts them
|
||||
// without complaint. Routing eval to Ogmios sidesteps the WASM bug AND
|
||||
// produces correct ex-units. The provider already implements evaluateTx
|
||||
// (OgmiosLucidProvider.evaluateTx → JSON-RPC evaluateTransaction).
|
||||
const completed = await txBuilder.complete({
|
||||
presetWalletInputs: realWalletUtxos,
|
||||
localUPLCEval: false,
|
||||
});
|
||||
signed = await completed.sign.withWallet().complete();
|
||||
} catch (err) {
|
||||
|
||||
Reference in New Issue
Block a user