ITADN

Migrate Rpc.Transaction test to Cardano.Api.Experimental API

#6491Opencarbolymer 创建于 2026-03-13
C
carbolymercommented
## Summary The RPC transaction integration test (`cardano-testnet/test/.../Rpc/Transaction.hs`) currently uses the old `Cardano.Api` transaction-building API. It should be migrated to the new `Cardano.Api.Experimental` API to: - Align with the direction of cardano-api (old API is being deprecated) - Use ledger-aligned types directly, reducing impedance mismatch - Serve as a reference example for RPC + experimental API integration ## Current old-API patterns to replace The test currently uses these old-API constructs: 1. **Era handling**: `ConwayEraOnwards`/`ShelleyBasedEra` with `convert` — replace with `Exp.Era` (`Exp.ConwayEra`) 2. **TxOut construction**: `TxOut addr (lovelaceToTxOutValue sbe coin) TxOutDatumNone ReferenceScriptNone` — replace with `Exp.TxOut (Ledger.mkBasicTxOut ledgerAddr value)` 3. **TxBodyContent**: `defaultTxBodyContent sbe` with old setters and wrapper types (`BuildTxWith`, `TxFeeExplicit`, `KeyWitness KeyWitnessForSpending`, `LedgerProtocolParameters`) — replace with `Exp.defaultTxBodyContent` + experimental setters using direct ledger types 4. **Tx creation**: `createTransactionBody sbe content` — replace with `Exp.makeUnsignedTx era content` 5. **Tx signing**: `signShelleyTransaction sbe txBody [wit0]` — replace with `Exp.makeKeyWitness era unsignedTx wit0` then `Exp.signTx era [] [keyWit] unsignedTx` 6. **TxId extraction**: `getTxId $ getTxBody signedTx` — replace with `Exp.hashTxBody (ledgerTx ^. L.bodyTxL)` or equivalent 7. **Serialization**: `serialiseToCBOR signedTx` — replace with `serialiseToRawBytes (Exp.SignedTx ledgerTx)` ## Migration plan ### Step 1: Update imports - Add `import qualified Cardano.Api.Experimental as Exp` - Add `import qualified Cardano.Api.Experimental.Tx as Exp` - Keep `Cardano.Api` for shared types still needed (address deserialization, `TxIn`, `TxIx`, `ShelleyWitnessSigningKey`, etc.) - Keep `Cardano.Api.Ledger` for direct ledger types (`Addr`, `MaryValue`, `Coin`, etc.) ### Step 2: Update era handling - Replace `(ceo, eraProxy) = (conwayBasedEra, asType)` with `era = Exp.ConwayEra` - Derive `sbe = Exp.convert era` only where testnet infrastructure still requires `ShelleyBasedEra` (e.g., `cardanoNodeEra = AnyShelleyBasedEra sbe`) - Address deserialization can stay as old-API (`deserialiseAddress`), converting to ledger `Addr` via `toShelleyAddr` where needed for tx outputs ### Step 3: Update transaction building Replace old-style `TxBodyContent` construction: ```haskell -- OLD let content = defaultTxBodyContent sbe & setTxIns [(txIn0, pure $ KeyWitness KeyWitnessForSpending)] & setTxFee (TxFeeExplicit sbe (L.Coin fee)) & setTxOuts [TxOut addr1 (lovelaceToTxOutValue sbe $ L.Coin amount) TxOutDatumNone ReferenceScriptNone, ...] & setTxProtocolParams (pure . pure $ LedgerProtocolParameters pparams) ``` With experimental-style: ```haskell -- NEW let ledgerAddr0 = toShelleyAddr addr0 ledgerAddr1 = toShelleyAddr addr1 mkOut addr coin = Exp.obtainCommonConstraints era $ Exp.TxOut (Ledger.mkBasicTxOut addr (Ledger.valueFromList coin [])) content = Exp.defaultTxBodyContent & Exp.setTxIns [(txIn0, Exp.AnyKeyWitnessPlaceholder)] & Exp.setTxFee (L.Coin fee) & Exp.setTxOuts [mkOut ledgerAddr1 amount, mkOut ledgerAddr0 change] & Exp.setTxProtocolParams (Just pparams) ``` ### Step 4: Update transaction creation and signing ```haskell -- OLD txBody <- H.leftFail $ createTransactionBody sbe content let signedTx = signShelleyTransaction sbe txBody [wit0] -- NEW let unsignedTx = Exp.makeUnsignedTx era content keyWit = Exp.makeKeyWitness era unsignedTx wit0 Exp.SignedTx signedLedgerTx = Exp.signTx era [] [keyWit] unsignedTx ``` ### Step 5: Update TxId extraction and serialization ```haskell -- OLD txId' <- H.noteShow . getTxId $ getTxBody signedTx ... serialiseToCBOR signedTx -- NEW txId' <- H.noteShow $ Exp.hashTxBody (signedLedgerTx ^. L.bodyTxL) ... serialiseToRawBytes (Exp.SignedTx signedLedgerTx) ``` ### Step 6: Verify `utxoRpcPParamsToProtocolParams` compatibility `utxoRpcPParamsToProtocolParams` already takes `Era era` and returns `L.PParams (ShelleyLedgerEra era)` (ledger PParams), so it's already compatible with the experimental API. The call site change is minimal — pass `era` directly instead of `convert ceo`. ## Notes - The testnet infrastructure (`TestnetRuntime`, `createAndRunTestnet`, etc.) still uses `AnyShelleyBasedEra`, so `sbe = Exp.convert era` will still be needed for the testnet options. This is not part of this migration scope. - Address deserialization from RPC responses (`deserialiseAddressBs`) uses old-API `AddressInEra`. These can either be kept (with `toShelleyAddr` conversion) or replaced with direct ledger address deserialization if available. - The helper functions `txoRefToTxIn` and `deserialiseAddressBs` use old-API types (`TxIn`, `SerialiseAddress`) and can remain as-is since they're about deserialization, not tx building. - Reference test for the experimental API pattern: `cardano-api/test/cardano-api-test/Test/Cardano/Api/Experimental.hs` ## Test plan - [ ] Migrate the code following the steps above - [ ] Build successfully with `cabal build cardano-testnet-test` - [ ] Run the test: `TASTY_PATTERN='/RPC Transaction Submit/' cabal test cardano-testnet-test` - [ ] Verify the transaction is still submitted and confirmed correctly via RPC
1 条评论