Skip to content

Commit a69f7c2

Browse files
authored
Merge pull request #765 from IntersectMBO/fix-missing-gov-action
Fix missing gov action on balance transaction
2 parents a534aa2 + f4bb759 commit a69f7c2

File tree

3 files changed

+133
-21
lines changed

3 files changed

+133
-21
lines changed

cardano-api/src/Cardano/Api/Internal/Fees.hs

Lines changed: 8 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -379,11 +379,8 @@ import Cardano.Ledger.Val qualified as L
379379
import Ouroboros.Consensus.HardFork.History qualified as Consensus
380380

381381
import Control.Monad
382-
import Data.Bifunctor
383-
( bimap
384-
, first
385-
, second
386-
)
382+
import Data.Bifunctor (bimap, first, second)
383+
import Data.Bitraversable (bitraverse)
387384
import Data.ByteString.Short (ShortByteString)
388385
import Data.Function ((&))
389386
import Data.List (sortBy)
@@ -1864,20 +1861,16 @@ substituteExecutionUnits
18641861
(TxBodyErrorAutoBalance era)
18651862
(Maybe (Featured ConwayEraOnwards era (TxProposalProcedures BuildTx era)))
18661863
mapScriptWitnessesProposals Nothing = return Nothing
1867-
mapScriptWitnessesProposals (Just (Featured era txpp)) = do
1868-
let eSubstitutedExecutionUnits =
1869-
[ (proposal, updatedWitness)
1870-
| (ix, proposal, scriptWitness) <- indexTxProposalProcedures txpp
1871-
, let updatedWitness = substituteExecUnits ix scriptWitness
1872-
]
1873-
substitutedExecutionUnits <- traverseScriptWitnesses eSubstitutedExecutionUnits
1874-
1864+
mapScriptWitnessesProposals (Just (Featured era proposals)) = do
1865+
substitutedExecutionUnits <-
1866+
traverse
1867+
(bitraverse pure $ traverse $ uncurry substituteExecUnits)
1868+
$ indexWitnessedTxProposalProcedures proposals
18751869
pure $
18761870
Just $
18771871
Featured era $
18781872
conwayEraOnwardsConstraints era $
1879-
mkTxProposalProcedures $
1880-
second Just <$> substitutedExecutionUnits
1873+
mkTxProposalProcedures substitutedExecutionUnits
18811874

18821875
mapScriptWitnessesMinting
18831876
:: TxMintValue BuildTx era

cardano-api/src/Cardano/Api/Internal/Tx/Body.hs

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -322,6 +322,7 @@ module Cardano.Api.Internal.Tx.Body
322322
, TxProposalProcedures (..)
323323
, mkTxProposalProcedures
324324
, indexTxProposalProcedures
325+
, indexWitnessedTxProposalProcedures
325326
, convProposalProcedures
326327

327328
-- *** Building vs viewing transactions
@@ -1678,15 +1679,27 @@ mkTxProposalProcedures proposals = do
16781679
map (second pure) proposals
16791680

16801681
-- | Index proposal procedures by their order ('Ord').
1682+
-- | and filter out the ones that do not have a witness.
16811683
indexTxProposalProcedures
16821684
:: TxProposalProcedures BuildTx era
16831685
-> [(ScriptWitnessIndex, L.ProposalProcedure (ShelleyLedgerEra era), ScriptWitness WitCtxStake era)]
1684-
indexTxProposalProcedures TxProposalProceduresNone = []
1685-
indexTxProposalProcedures (TxProposalProcedures proposals) = do
1686-
let allProposalsList = fst <$> toList proposals
1687-
[ (ScriptWitnessIndexProposing $ fromIntegral ix, proposal, scriptWitness)
1688-
| (proposal, BuildTxWith (Just scriptWitness)) <- toList proposals
1689-
, ix <- maybeToList $ List.elemIndex proposal allProposalsList
1686+
indexTxProposalProcedures proposals =
1687+
[ (ix, proposal, scriptWitness)
1688+
| (proposal, Just (ix, scriptWitness)) <- indexWitnessedTxProposalProcedures proposals
1689+
]
1690+
1691+
-- | Index proposal procedures by their order ('Ord').
1692+
indexWitnessedTxProposalProcedures
1693+
:: TxProposalProcedures BuildTx era
1694+
-> [ ( L.ProposalProcedure (ShelleyLedgerEra era)
1695+
, Maybe (ScriptWitnessIndex, ScriptWitness WitCtxStake era)
1696+
)
1697+
]
1698+
indexWitnessedTxProposalProcedures TxProposalProceduresNone = []
1699+
indexWitnessedTxProposalProcedures (TxProposalProcedures proposals) = do
1700+
let allProposalsList = zip [0 ..] $ toList proposals
1701+
[ (proposal, fmap (ScriptWitnessIndexProposing ix,) mScriptWitness)
1702+
| (ix, (proposal, BuildTxWith mScriptWitness)) <- allProposalsList
16901703
]
16911704

16921705
-- ----------------------------------------------------------------------------

cardano-api/test/cardano-api-test/Test/Cardano/Api/Transaction/Autobalance.hs

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ import Cardano.Slotting.EpochInfo qualified as CS
3131
import Cardano.Slotting.Slot qualified as CS
3232
import Cardano.Slotting.Time qualified as CS
3333

34+
import Data.Aeson (eitherDecodeStrict)
3435
import Data.ByteString qualified as B
3536
import Data.Default (def)
3637
import Data.Function
@@ -358,8 +359,110 @@ prop_calcReturnAndTotalCollateral = H.withTests 400 . H.property $ do
358359
H.note_ "Check that collateral balance is equal to collateral in tx body"
359360
resTotCollValue === collBalance
360361

362+
-- | Regression test for: https://github.com/IntersectMBO/cardano-cli/issues/1073
363+
prop_ensure_gov_actions_are_preserved_by_autobalance :: Property
364+
prop_ensure_gov_actions_are_preserved_by_autobalance = H.propertyOnce $ do
365+
let ceo = ConwayEraOnwardsConway
366+
sbe = convert ceo
367+
368+
systemStart <- parseSystemStart "2021-09-01T00:00:00Z"
369+
let epochInfo = LedgerEpochInfo $ CS.fixedEpochInfo (CS.EpochSize 100) (CS.mkSlotLength 1000)
370+
371+
pparams <-
372+
LedgerProtocolParameters
373+
<$> H.readJsonFileOk "test/cardano-api-test/files/input/protocol-parameters/conway.json"
374+
375+
-- One UTXO with 2000 ADA
376+
let utxos = mkSimpleUTxOs sbe
377+
txInputs = map (,BuildTxWith (KeyWitness KeyWitnessForSpending)) . toList . M.keys . unUTxO $ utxos
378+
address <- H.forAll (genAddressInEra sbe)
379+
380+
anchorUrl <- H.evalEither $ eitherDecodeStrict "\"https://tinyurl.com/cardano-qa-anchor\""
381+
anchorDataHash <-
382+
H.evalEither $
383+
eitherDecodeStrict "\"f08cc9640136b1ae47428f646a9b5aadc0045fafb5529ca3ba1723784e6f0750\""
384+
let anchor =
385+
L.Anchor
386+
{ L.anchorUrl = anchorUrl
387+
, L.anchorDataHash = anchorDataHash
388+
}
389+
proposalProcedure =
390+
L.ProposalProcedure
391+
{ L.pProcDeposit = 100_000_000
392+
, L.pProcReturnAddr =
393+
L.RewardAccount
394+
{ L.raNetwork = L.Testnet
395+
, L.raCredential =
396+
L.KeyHashObj (L.KeyHash{L.unKeyHash = "0b1b872f7953bccfc4245f3282b3363f3d19e9e001a5c41e307363d7"})
397+
}
398+
, L.pProcGovAction = L.InfoAction
399+
, L.pProcAnchor = anchor
400+
}
401+
402+
let content =
403+
defaultTxBodyContent sbe
404+
& setTxIns txInputs
405+
& setTxProtocolParams (pure $ pure pparams)
406+
& setTxProposalProcedures
407+
( pure $
408+
Featured
409+
ConwayEraOnwardsConway
410+
( TxProposalProcedures
411+
(fromList [(proposalProcedure, BuildTxWith Nothing)])
412+
)
413+
)
414+
415+
-- Autobalanced body should preserve the governance action
416+
(BalancedTxBody _ balancedTxBody _ _) <-
417+
H.leftFail $
418+
makeTransactionBodyAutoBalance
419+
sbe
420+
systemStart
421+
epochInfo
422+
pparams
423+
mempty
424+
mempty
425+
mempty
426+
utxos
427+
content
428+
address
429+
Nothing
430+
431+
let balancedContent = getTxBodyContent balancedTxBody
432+
Featured _ (TxProposalProcedures balancedProposalProcedureOMap) <-
433+
H.evalMaybe $ txProposalProcedures balancedContent
434+
let balancedProposalProcedureList = toList balancedProposalProcedureOMap
435+
balancedProposalProcedureList === [(proposalProcedure, ViewTx)]
436+
361437
-- * Utilities
362438

439+
mkSimpleUTxOs :: ShelleyBasedEra ConwayEra -> UTxO ConwayEra
440+
mkSimpleUTxOs sbe =
441+
UTxO
442+
[
443+
( TxIn
444+
"01f4b788593d4f70de2a45c2e1e87088bfbdfa29577ae1b62aba60e095e3ab53"
445+
(TxIx 0)
446+
, TxOut
447+
( AddressInEra
448+
(ShelleyAddressInEra sbe)
449+
( ShelleyAddress
450+
L.Testnet
451+
( L.KeyHashObj $
452+
L.KeyHash "ebe9de78a37f84cc819c0669791aa0474d4f0a764e54b9f90cfe2137"
453+
)
454+
L.StakeRefNull
455+
)
456+
)
457+
( lovelaceToTxOutValue
458+
sbe
459+
2_000_000_000
460+
)
461+
TxOutDatumNone
462+
ReferenceScriptNone
463+
)
464+
]
465+
363466
loadPlutusWitness
364467
:: HasCallStack
365468
=> MonadFail m
@@ -499,4 +602,7 @@ tests =
499602
"makeTransactionBodyAutoBalance autobalances when deregistering certificates"
500603
prop_make_transaction_body_autobalance_when_deregistering_certs
501604
, testProperty "calcReturnAndTotalCollateral constraints hold" prop_calcReturnAndTotalCollateral
605+
, testProperty
606+
"Governance actions are preserved by autobalance"
607+
prop_ensure_gov_actions_are_preserved_by_autobalance
502608
]

0 commit comments

Comments
 (0)