-
Notifications
You must be signed in to change notification settings - Fork 214
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Replace Set TxIn
with [TxIn]
to fix StateMachine.getInput
#594
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -18,6 +18,7 @@ module Plutus.ChainIndex.Tx( | |
, txOutsWithRef | ||
, txOutRefMap | ||
, txOutRefMapForAddr | ||
, txRedeemersWithHash | ||
-- ** Lenses | ||
, citxTxId | ||
, citxInputs | ||
|
@@ -38,13 +39,13 @@ import Data.Set qualified as Set | |
import Data.Tuple (swap) | ||
import Ledger (Address, OnChainTx (..), SomeCardanoApiTx (SomeTx), Tx (..), TxIn (..), TxInType (..), | ||
TxOut (txOutAddress), TxOutRef (..), onCardanoTx, txId) | ||
import Plutus.ChainIndex.Types | ||
import Plutus.Contract.CardanoAPI (fromCardanoTx, setValidity) | ||
import Plutus.Script.Utils.V1.Scripts (datumHash, mintingPolicyHash, redeemerHash, validatorHash) | ||
import Plutus.V1.Ledger.Scripts (Datum, DatumHash, MintingPolicy (getMintingPolicy), | ||
MintingPolicyHash (MintingPolicyHash), Redeemer (..), RedeemerHash, Script, | ||
ScriptHash (..), Validator (getValidator), ValidatorHash (ValidatorHash)) | ||
|
||
import Plutus.ChainIndex.Types | ||
MintingPolicyHash (MintingPolicyHash), Redeemer, RedeemerHash, Script, ScriptHash (..), | ||
Validator (getValidator), ValidatorHash (ValidatorHash)) | ||
import Plutus.V1.Ledger.Tx (RedeemerPtr (RedeemerPtr), Redeemers, ScriptTag (Spend)) | ||
|
||
-- | Get tx output references from tx. | ||
txOutRefs :: ChainIndexTx -> [TxOutRef] | ||
|
@@ -78,7 +79,7 @@ fromOnChainTx = \case | |
let (validatorHashes, otherDataHashes, redeemers) = validators txInputs in | ||
ChainIndexTx | ||
{ _citxTxId = txId tx | ||
, _citxInputs = txInputs | ||
, _citxInputs = Set.toList txInputs | ||
, _citxOutputs = ValidTx txOutputs | ||
, _citxValidRange = txValidRange | ||
, _citxData = txData <> otherDataHashes | ||
|
@@ -94,7 +95,7 @@ fromOnChainTx = \case | |
let (validatorHashes, otherDataHashes, redeemers) = validators txInputs in | ||
ChainIndexTx | ||
{ _citxTxId = txId tx | ||
, _citxInputs = txCollateral | ||
, _citxInputs = Set.toList txCollateral | ||
, _citxOutputs = InvalidTx | ||
, _citxValidRange = txValidRange | ||
, _citxData = txData <> otherDataHashes | ||
|
@@ -117,13 +118,21 @@ mintingPolicies = Map.fromList . fmap withHash . Set.toList | |
withHash mp = let (MintingPolicyHash mph) = mintingPolicyHash mp | ||
in (ScriptHash mph, getMintingPolicy mp) | ||
|
||
validators :: Set TxIn -> (Map ScriptHash Script, Map DatumHash Datum, Map RedeemerHash Redeemer) | ||
validators = foldMap (maybe mempty withHash . txInType) . Set.toList | ||
validators :: Set TxIn -> (Map ScriptHash Script, Map DatumHash Datum, Redeemers) | ||
validators txIns = foldMap (\(ix, txIn) -> maybe mempty (withHash ix) $ txInType txIn) $ zip [0..] (Set.toList txIns) | ||
where | ||
withHash (ConsumeScriptAddress val red dat) = | ||
-- TODO: the index of the txin is probably incorrect as we take it from the set. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is this going to have bad consequences? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. My understanding is that this PR makes a move from a completely broken state to a semi-broken state. Instead of not getting redeemers at all, we will start choosing them but with a big chance of selecting the incorrect ones. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Speaking of There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. As long as the redeemer pointer points to the right input, I think this is totally fine. To show that there is a relation between the list and the indexes, I think it's better to do the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There is a problem here that we take a set that could break the order. I looked at usages of the |
||
-- To determine the proper index we have to convert the plutus's `TxIn` to cardano-api `TxIn` and | ||
-- sort them by using the standard `Ord` instance. | ||
withHash ix (ConsumeScriptAddress val red dat) = | ||
let (ValidatorHash vh) = validatorHash val | ||
in ( Map.singleton (ScriptHash vh) (getValidator val) | ||
, Map.singleton (datumHash dat) dat | ||
, Map.singleton (redeemerHash red) red | ||
, Map.singleton (RedeemerPtr Spend ix) red | ||
) | ||
withHash _ = mempty | ||
withHash _ _ = mempty | ||
|
||
txRedeemersWithHash :: ChainIndexTx -> Map RedeemerHash Redeemer | ||
txRedeemersWithHash ChainIndexTx{_citxRedeemers} = Map.fromList | ||
$ fmap (\r -> (redeemerHash r, r)) | ||
$ Map.elems _citxRedeemers |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -17,6 +17,7 @@ module Plutus.Contract.CardanoAPI( | |
|
||
import Cardano.Api qualified as C | ||
import Cardano.Api.Shelley qualified as C | ||
import Data.List (sort) | ||
import Data.Set qualified as Set | ||
import Ledger qualified as P | ||
import Ledger.Tx.CardanoAPI as Export | ||
|
@@ -37,7 +38,9 @@ fromCardanoTx eraInMode tx@(C.Tx txBody@(C.TxBody C.TxBodyContent{..}) _) = do | |
let scriptMap = plutusScriptsFromTxBody txBody | ||
isTxScriptValid = fromTxScriptValidity txScriptValidity | ||
(datums, redeemers) = scriptDataFromCardanoTxBody txBody | ||
inputs = | ||
-- We need to sort the inputs as the order is important | ||
-- to find the corresponding redeemers | ||
inputs = sort $ | ||
Comment on lines
-40
to
+42
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Here is the correct order of inputs as we sort cardano-api's There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Good catch, I would have thought they would already be in the right order! |
||
if isTxScriptValid | ||
then fst <$> txIns | ||
else case txInsCollateral of | ||
|
@@ -48,7 +51,7 @@ fromCardanoTx eraInMode tx@(C.Tx txBody@(C.TxBody C.TxBodyContent{..}) _) = do | |
{ _citxTxId = fromCardanoTxId (C.getTxId txBody) | ||
, _citxValidRange = fromCardanoValidityRange txValidityRange | ||
-- If the transaction is invalid, we use collateral inputs | ||
, _citxInputs = Set.fromList $ fmap ((`P.TxIn` Nothing) . fromCardanoTxIn) inputs | ||
, _citxInputs = fmap ((`P.TxIn` Nothing) . fromCardanoTxIn) inputs | ||
-- No outputs if the one of scripts failed | ||
, _citxOutputs = if isTxScriptValid then ValidTx txOutputs | ||
else InvalidTx | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -60,7 +60,6 @@ import Data.Aeson (FromJSON, ToJSON) | |
import Data.Map (Map) | ||
import Data.Map qualified as Map | ||
import Data.Maybe (listToMaybe, mapMaybe) | ||
import Data.Set qualified as Set | ||
import Data.Text (Text) | ||
import Data.Text qualified as Text | ||
import Data.Void (Void, absurd) | ||
|
@@ -77,7 +76,7 @@ import Ledger.Constraints.TxConstraints (ScriptInputConstraint (ScriptInputConst | |
import Ledger.Tx qualified as Tx | ||
import Ledger.Typed.Scripts qualified as Scripts | ||
import Ledger.Value qualified as Value | ||
import Plutus.ChainIndex (ChainIndexTx (_citxInputs)) | ||
import Plutus.ChainIndex (ChainIndexTx (_citxInputs, _citxRedeemers)) | ||
import Plutus.Contract (AsContractError (_ConstraintResolutionContractError, _ContractError), Contract, ContractError, | ||
Promise, adjustUnbalancedTx, awaitPromise, isSlot, isTime, logWarn, mapError, never, | ||
ownFirstPaymentPubKeyHash, ownUtxos, promiseBind, select, submitTxConfirmed, utxoIsProduced, | ||
|
@@ -128,8 +127,9 @@ getInput :: | |
-> ChainIndexTx | ||
-> Maybe i | ||
getInput outRef tx = do | ||
(_validator, Ledger.Redeemer r, _) <- | ||
listToMaybe $ mapMaybe Tx.inScripts $ filter (\Tx.TxIn{Tx.txInRef} -> outRef == txInRef) $ Set.toList $ _citxInputs tx | ||
-- We retrieve the correspondent redeemer according to the index of txIn in the list | ||
let findRedeemer (ix, _) = Map.lookup (Tx.RedeemerPtr Tx.Spend ix) (_citxRedeemers tx) | ||
Ledger.Redeemer r <- listToMaybe $ mapMaybe findRedeemer $ filter (\(_, Tx.TxIn{Tx.txInRef}) -> outRef == txInRef) $ zip [0..] $ _citxInputs tx | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Here is where we use the knowledge of inputs order to get the redeemer. I hope I got the idea correctly that index of Source: IntersectMBO/cardano-node#3389 (comment) Maybe instead of relying on their order it's better to include the index. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The fact that we now have a list instead of a set makes it clear enough that the order is significant in my opinion. |
||
PlutusTx.fromBuiltinData r | ||
|
||
getStates | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is incorrect but to fix it we need to fix the
Tx
fromplutus-core
. Or create our ownTx
with[TxIn]
instead ofSet TxIn
.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you add a TODO and a story for this? I guess it will need to be done once
next-node
is merged inmain
.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No need imho, this is good enough.