This one is a bit technical it has to do with looking up and updating the constraints of an already existing transaction (that belongs to the script address). See Case ii) to skip my synopsis.
Just a little synopsis for future readers: The Core.hs
script is an Oracle, that has to update its datum regarding Ada price. The lines in which lookups occur are in the function updateOracle
that has the purpose of building a transaction and then submitting it. To accomplish this the constraints need to refer to typed script inputs and outputs. In updateOracle
we dealt with two cases
.
.
case m of
Nothing -> do
ledgerTx <- submitTxConstraints (typedOracleValidator oracle) c
.
.
Just (oref, o, _) -> do
let lookups = Constraints.unspentOutputs (Map.singleton oref o) <>
Constraints.typedValidatorLookups (typedOracleValidator oracle) <>
Constraints.otherScript (oracleValidator oracle)
tx = c <> Constraints.mustSpendScriptOutput oref (Redeemer $ PlutusTx.toBuiltinData Update)
ledgerTx <- submitTxConstraintsWith @Oracling lookups tx
.
.
Case i) uses submitTxConstraints
which takes the constraints as inputs in the form of a script instance (with typed validator hash & the compiled program) and the locked value with the script.
Case ii) on the other hand, uses submitTxConstraintsWith
which takes the updated constraints as ScriptLookup
type rather than a script instance. To your question, we need to semigroup:
Constraints.typedValidatorLookups
(this gets the previous
parameters of the ScriptLookup
)
Constraints.unspentOutputs
(updates slTxOutputs
from
ScriptLookup
, which are the unspent outputs that the script wants to
spend)
Constraints.otherScript
(updates slOtherScripts
from
ScriptLookup
, which are validators of the script other than our
script)
The reason why Constraints.typedValidatorLookups
alone is not enough is because we would not be updating anything without semigrouping ScriptLookup
element by element as defined in OffChain.hs
)