Skip to content
This repository was archived by the owner on Dec 2, 2024. It is now read-only.

SCP-2945: Only script outputs in unbalanced transactions #57

Merged
merged 6 commits into from
Nov 22, 2021

Conversation

sjoerdvisscher
Copy link
Contributor

@sjoerdvisscher sjoerdvisscher commented Oct 27, 2021

Pre-submit checklist:

  • Branch
    • Tests are provided (if possible)
    • Commit sequence broadly makes sense
    • Key commits have useful messages
    • Relevant tickets are mentioned in commit messages
    • Formatting, materialized Nix files, PNG optimization, etc. are updated
  • PR
    • Self-reviewed the diff
    • Useful pull request description
    • Reviewer requested

@sjoerdvisscher sjoerdvisscher force-pushed the SCP-2945-only-script-inputs-in-utx branch from af38edd to af6041d Compare October 27, 2021 13:55
@@ -370,7 +392,7 @@ updateUtxoIndex
=> m ()
updateUtxoIndex = do
ScriptLookups{slTxOutputs} <- ask
unbalancedTx . utxoIndex <>= fmap Tx.toTxOut slTxOutputs
unbalancedTx . utxoIndex <>= Map.mapMaybe toScriptOutput slTxOutputs
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is silently dropping public key outputs. I think that is OK, but I might be wrong. An alternative could be to let slTxOutputs also only be ScriptOutputs. Then callers of the unspentOutputs function would need to choose what to do in the case of public key outputs.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I tried this but that breaks lookupTxOutRef.

Copy link
Contributor

Choose a reason for hiding this comment

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

The public key inputs case for lookupTxOutRef is used for the MustSpendPubKeyOutput constraint. Given that we can't instruct the wallet to spend a specific public key output, maybe we should get rid of this constraint altogether? Although it still seems useful in the on-chain code, and you can definitely build a valid transaction that satisfies it. Just not with cardano-wallet. So I think dropping the public key outputs here with mapMaybe is OK.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

And cardano-wallet might support it in the future, right?

Copy link
Contributor

Choose a reason for hiding this comment

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

Yes, true!

Copy link
Contributor

@j-mueller j-mueller left a comment

Choose a reason for hiding this comment

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

Interesting, I thought this would break the state machine initialisation code. Presumably it still works because the wallet selects the right input anyway.

@@ -370,7 +392,7 @@ updateUtxoIndex
=> m ()
updateUtxoIndex = do
ScriptLookups{slTxOutputs} <- ask
unbalancedTx . utxoIndex <>= fmap Tx.toTxOut slTxOutputs
unbalancedTx . utxoIndex <>= Map.mapMaybe toScriptOutput slTxOutputs
Copy link
Contributor

Choose a reason for hiding this comment

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

The public key inputs case for lookupTxOutRef is used for the MustSpendPubKeyOutput constraint. Given that we can't instruct the wallet to spend a specific public key output, maybe we should get rid of this constraint altogether? Although it still seems useful in the on-chain code, and you can definitely build a valid transaction that satisfies it. Just not with cardano-wallet. So I think dropping the public key outputs here with mapMaybe is OK.

Comment on lines +165 to +187
data ScriptOutput =
ScriptOutput
{ scriptOutputValidatorHash :: ValidatorHash
, scriptOutputValue :: Value
, scriptOutputDatumHash :: DatumHash
}
deriving stock (Eq, Generic, Show)
deriving anyclass (FromJSON, ToJSON, OpenApi.ToSchema)

toScriptOutput :: ChainIndexTxOut -> Maybe ScriptOutput
toScriptOutput (Tx.ScriptChainIndexTxOut _ validatorOrHash datumOrHash v)
= Just $ ScriptOutput (either id validatorHash validatorOrHash) v (either id datumHash datumOrHash)
toScriptOutput Tx.PublicKeyChainIndexTxOut{}
= Nothing

fromScriptOutput :: ScriptOutput -> ChainIndexTxOut
fromScriptOutput (ScriptOutput vh v dh) =
Tx.ScriptChainIndexTxOut (Address.scriptHashAddress vh) (Left vh) (Left dh) v

instance Pretty ScriptOutput where
pretty ScriptOutput{scriptOutputValidatorHash, scriptOutputValue} =
hang 2 $ vsep ["-" <+> pretty scriptOutputValue <+> "addressed to", pretty scriptOutputValidatorHash]

Copy link
Contributor

Choose a reason for hiding this comment

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

Maybe put this in Ledger.Tx together with ChainIndexTxOut?

# Conflicts:
#	playground-common/src/PSGenerator/Common.hs
#	plutus-contract/src/Plutus/Contract/Wallet.hs
#	plutus-use-cases/test/Spec/PubKey.hs
@@ -268,7 +268,7 @@ validateTxAndAddFees feeCfg slotCfg ownTxOuts utx = do
-- Balance and sign just for validation
tx <- handleBalanceTx ownTxOuts utx
signedTx <- handleAddSignature tx
let utxoIndex = Ledger.UtxoIndex $ unBalancedTxUtxoIndex utx <> (toTxOut <$> ownTxOuts)
let utxoIndex = Ledger.UtxoIndex $ fmap toTxOut $ (U.fromScriptOutput <$> unBalancedTxUtxoIndex utx) <> ownTxOuts
Copy link
Contributor Author

Choose a reason for hiding this comment

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

@j-mueller After thinking some more this here seems to be the clue that there is no failure. The PubKeys are only unavailable in the lookups. But the wallet knows how to lookup its own outputs (ownTxOuts here) so getUnspentOutput just works!

Copy link
Contributor

Choose a reason for hiding this comment

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

getUnspentOutput works, and it gives you an unspent output from the wallet. But there is no guarantee that the wallet selects the same unspent output when balanceTx is called a second time, for the transaction that creates the token by spending this specific output.

The UTXO could have been spent in the meantime, or maybe the wallet decides that there is a different collection of UTXOs that is better suited in the second call to balanceTx.

Copy link
Contributor

Choose a reason for hiding this comment

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

Because of this, I'm inclined to think that we have to go back to creating a script output (with the PubKey contract) in a separate transaction before we can set up the state machine. What do you think @sjoerdvisscher @silky ?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@j-mueller I agree, but that’s a separate issue I think? So we can merge this one?

Copy link
Contributor

Choose a reason for hiding this comment

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

Yes, let's merge it!

@sjoerdvisscher sjoerdvisscher merged commit 0709726 into main Nov 22, 2021
@sjoerdvisscher sjoerdvisscher deleted the SCP-2945-only-script-inputs-in-utx branch November 22, 2021 09:34
bwbush added a commit that referenced this pull request Jan 27, 2022
bwbush added a commit that referenced this pull request Jan 27, 2022
bwbush added a commit that referenced this pull request Jan 28, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants